ImageRules revision d05822f18b93c2de6b904304ecd9dea7047870b6
1rule FSameTargetWithPrependedGrist
2{
3	# SameTargetWithPrependedGrist <target> : <grist to prepend> ;
4	#
5	local target = $(1) ;
6	local gristToPrepend = $(2) ;
7	local grist = $(target:G) ;
8
9	if $(grist) {
10		grist = $(gristToPrepend)!$(grist) ;
11	} else {
12		grist = $(gristToPrepend) ;
13	}
14
15	return $(target:G=$(grist)) ;
16}
17
18rule InitScript
19{
20	# Note: The script must have been LOCATEd before.
21	local script = $(1) ;
22	local initScript
23		= [ FSameTargetWithPrependedGrist $(script) : init-script ] ;
24
25	if ! [ on $(script) return $(__is_initialized) ] {
26		__is_initialized on $(script) = true ;
27
28		MakeLocate $(initScript) : [ on $(script) return $(LOCATE) ] ;
29		Always $(initScript) ;
30		Depends $(script) : $(initScript) ;
31
32		InitScript1 $(initScript) ;
33	}
34
35	return $(initScript) ;
36}
37
38actions InitScript1
39{
40	$(RM) $(1)
41	touch $(1)
42}
43
44rule AddVariableToScript script : variable : value
45{
46	# AddVariableToScript <script> : <variable> : <value> ;
47
48	# interpret an empty variable value as empty string
49	if ! $(value) {
50		value = "" ;
51	}
52
53	InitScript $(script) ;
54
55	VARIABLE_DEFS on $(script) += "echo $(variable)=\\\"$(value[1])\\\" >> " ;
56
57	# if the value is an array, add the other array elements
58	value = $(value[2-]) ;
59	while $(value) {
60		VARIABLE_DEFS on $(script)
61			+= "echo $(variable)=\\\" \\\$$(variable) $(value[1])\\\" >> " ;
62		value = $(value[2-]) ;
63	}
64
65	AddVariableToScript1 $(script) ;
66}
67
68actions together AddVariableToScript1
69{
70	$(VARIABLE_DEFS)$(1);
71}
72
73
74rule AddTargetVariableToScript script : targets : variable
75{
76	# AddTargetVariableToScript <script> : <targets> [ : <variable> ] ;
77	#
78	# If <targets> contains multiple targets, their paths must not contain
79	# whitespaces or other characters that need to be escaped in the shell.
80	#
81	variable ?= $(3:E=$(targets[1]:BS)) ;
82
83	local initScript = [ InitScript $(script) ] ;
84
85	serialization = [ on $(script) return $(HAIKU_SERIALIZATION) ] ;
86
87	local variableTarget = [ NewUniqueTarget ] ;
88	NotFile $(variableTarget) ;
89	Depends $(variableTarget) : $(initScript) $(targets) $(serialization) ;
90	Depends $(script) : $(variableTarget) ;
91
92	HAIKU_SERIALIZATION on $(script) = $(variableTarget) ;
93
94	HAIKU_VARIABLE_NAME on $(variableTarget) = $(variable) ;
95	AddTargetVariableToScript1 $(variableTarget) : $(initScript) $(targets) ;
96}
97
98
99actions AddTargetVariableToScript1
100{
101	script="$(2[1])"
102	echo "$(HAIKU_VARIABLE_NAME)=" >> "$script"
103
104	firstSeen=
105	for value in "$(2[2-])" ; do
106		if [ -z "$firstSeen" ]; then
107			echo "$(HAIKU_VARIABLE_NAME)=\"$value\"" >> "$script"
108			firstSeen=1
109		else
110			echo "$(HAIKU_VARIABLE_NAME)=\"\$$(HAIKU_VARIABLE_NAME) $value\"" \
111				>> "$script"
112		fi
113	done
114}
115
116
117#pragma mark -
118
119rule AddDirectoryToContainer container : directoryTokens : attributeFiles
120{
121	# AddDirectoryToContainer <container> : <directoryTokens> : <attributeFiles>
122
123	local containerGrist = [ on $(container) return $(HAIKU_CONTAINER_GRIST) ] ;
124	local directory = [ FDirName $(directoryTokens) ] ;
125	directory = $(directory:G=$(containerGrist)) ;
126
127	if ! [ on $(directory) return $(__is_on_image) ] {
128		HAIKU_INSTALL_DIRECTORIES on $(container) += $(directory) ;
129		__is_on_image on $(directory) = true ;
130		DIRECTORY_TOKENS on $(directory) = $(directoryTokens) ;
131		NotFile $(directory) ;
132
133		# mark the parent dir as not to be created
134		local parent = [ FReverse $(directoryTokens) ] ;
135		parent = [ FReverse $(parent[2-]) ] ;
136		if $(parent) {
137			parent = [ FDirName $(parent) ] ;
138			parent = $(parent:G=$(containerGrist)) ;
139			DONT_CREATE on $(parent) = true ;
140		}
141	}
142
143	if $(attributeFiles) {
144		SEARCH on $(attributeFiles)
145			+= [ FDirName $(HAIKU_TOP) data image_directories ] ;
146		ATTRIBUTE_FILES on $(dir) += $(attributeFiles) ;
147	}
148
149	return $(directory) ;
150}
151
152rule FilterContainerUpdateTargets targets : filterVariable
153{
154	# FilterContainerUpdateTargets targets : filterVariable
155
156	local filteredTargets ;
157	local target ;
158	for target in $(targets) {
159		if [ on $(target) return $($(filterVariable)) ] {
160			filteredTargets += $(target) ;
161		}
162	}
163	return $(filteredTargets) ;
164}
165
166
167rule IncludeAllTargetsInContainer container
168{
169	local filterVar
170		= [ on $(container) return $(HAIKU_INCLUDE_IN_CONTAINER_VAR) ] ;
171	if $(filterVar) {
172		return $($(filterVar)) ;
173	}
174
175	return ;
176}
177
178
179rule PropagateContainerUpdateTargetFlags toTarget : fromTarget
180{
181	if [ on $(fromTarget) return $(HAIKU_INCLUDE_IN_IMAGE) ] {
182		HAIKU_INCLUDE_IN_IMAGE on $(toTarget) = 1 ;
183	}
184
185	if [ on $(fromTarget) return $(HAIKU_INCLUDE_IN_PACKAGES) ] {
186		HAIKU_INCLUDE_IN_PACKAGES on $(toTarget) = 1 ;
187	}
188}
189
190
191rule AddFilesToContainer container : directoryTokens : targets : destName
192	: flags
193{
194	# AddFilesToContainer <container> : <directoryTokens> : <targets>
195	#	: [ <destName> ] : [ <flags> ]
196	#
197	# Supported flags:
198	#	computeName - <destName> is the name of a shell command/function that
199	#		computes the destination name.
200
201	local containerGrist = [ on $(container) return $(HAIKU_CONTAINER_GRIST) ] ;
202	local systemDirTokens
203		= [ on $(container) return $(HAIKU_CONTAINER_SYSTEM_DIR_TOKENS) ] ;
204
205	targets = [ FFilterByBuildFeatures $(targets) ] ;
206
207	# If the image shall only be updated, we filter out all targets not marked
208	# accordingly.
209	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ]
210		&& ! [ IncludeAllTargetsInContainer $(container) ] {
211		local filterVar
212			= [ on $(container) return $(HAIKU_INCLUDE_IN_CONTAINER_VAR) ] ;
213		if $(filterVar) {
214			targets = [ FilterContainerUpdateTargets $(targets)
215				: $(filterVar) ] ;
216
217			# If there are any targets, mark the container as to be included in
218			# an update, too, if it has set the update inheritance variable.
219			# This makes updating a target that lives in a package on an image
220			# work.
221			if $(targets) {
222				local updateVariable = [ on $(container) return
223					$(HAIKU_CONTAINER_INHERIT_UPDATE_VARIABLE) ] ;
224				if $(updateVariable) {
225					$(updateVariable) on $(container) = 1 ;
226				}
227			}
228		}
229	}
230
231	if ! $(targets) {
232		return ;
233	}
234
235	local directory = [ AddDirectoryToContainer $(container)
236		: $(directoryTokens) ] ;
237
238	# We create a unique dummy target per target to install.
239	local installTargetsVar
240		= [ on $(container) return $(HAIKU_INSTALL_TARGETS_VAR) ] ;
241	local target ;
242	for target in $(targets) {
243		local name ;
244		local nameFunction ;
245		if $(destName) {
246			if computeName in $(flags) {
247				nameFunction = $(destName) ;
248				name = $(destName)/$(target:BS) ;
249			} else {
250				name = $(destName) ;
251			}
252		} else {
253			name = $(target:BS) ;
254		}
255
256		local destTarget = $(name:G=$(containerGrist)__$(directory:G=)) ;
257		TARGET on $(destTarget) = $(target) ;
258		INSTALL_DIR on $(destTarget) = $(directory) ;
259		NAME_FUNCTION on $(destTarget) = $(nameFunction) ;
260		$(installTargetsVar) on $(target) += $(destTarget) ;
261		TARGETS_TO_INSTALL on $(directory) += $(destTarget) ;
262
263		# If the target is associated with catalog files, add those, too.
264		local catalogs = [ on $(target) return $(HAIKU_CATALOG_FILES) ] ;
265		if $(catalogs) {
266			local signature
267				= [ on $(target) return $(HAIKU_CATALOG_SIGNATURE) ] ;
268			AddFilesToContainer $(container)
269				: $(systemDirTokens) data locale catalogs $(signature)
270				: $(catalogs) ;
271		}
272
273		# If the target is associated with MIME DB entries, add those, too.
274		local mimeDBEntries = [ on $(target) return $(HAIKU_MIME_DB_ENTRIES) ] ;
275		if $(mimeDBEntries) {
276			# Make sure we add the entries only once by tracking the containers
277			# we have already added it to.
278			local containers = [ on $(mimeDBEntries)
279				return $(HAIKU_MIME_DB_ENTRIES_IN_CONTAINERS) ] ;
280			if ! $(container) in $(containers) {
281				HAIKU_MIME_DB_ENTRIES_IN_CONTAINERS on $(mimeDBEntries)
282					= $(containers) $(container) ;
283	 			CopyDirectoryToContainer $(container) : data
284 					: $(mimeDBEntries) : mime_db : : alwaysUpdate isTarget ;
285 			}
286		}
287	}
288}
289
290rule FFilesInContainerDirectory container : directoryTokens
291{
292	local containerGrist = [ on $(container) return $(HAIKU_CONTAINER_GRIST) ] ;
293	local directory = [ FDirName $(directoryTokens) ] ;
294	directory = $(directory:G=$(containerGrist)) ;
295
296	if [ on $(directory) return $(__is_on_image) ] {
297		on $(directory) return $(TARGETS_TO_INSTALL) ;
298	}
299
300	return ;
301}
302
303rule AddSymlinkToContainer container : directoryTokens : linkTarget : linkName
304{
305	# AddSymlinkToContainer <container> : <directory> : <link target>
306	#	[ : <link name> ] ;
307	#
308
309	# If the image shall only be updated, we don't add any symlinks.
310	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ]
311		&& ! [ IncludeAllTargetsInContainer $(container) ] {
312		return ;
313	}
314
315	local directory = [ AddDirectoryToContainer $(container)
316		: $(directoryTokens) ] ;
317
318	if ! $(linkName) {
319		local path = [ FReverse [ FSplitPath $(linkTarget) ] ] ;
320		linkName = $(path[1]) ;
321	}
322
323	local link = $(directory)/$(linkName) ;
324	SYMLINK_TARGET on $(link) = $(linkTarget) ;
325	SYMLINKS_TO_INSTALL on $(directory) += $(link) ;
326}
327
328rule FSymlinksInContainerDirectory container : directoryTokens
329{
330	local containerGrist = [ on $(container) return $(HAIKU_CONTAINER_GRIST) ] ;
331	local directory = [ FDirName $(directoryTokens) ] ;
332	directory = $(directory:G=$(containerGrist)) ;
333
334	if [ on $(directory) return $(__is_on_image) ] {
335		on $(directory) return $(SYMLINKS_TO_INSTALL) ;
336	}
337
338	return ;
339}
340
341rule CopyDirectoryToContainer container : directoryTokens : sourceDirectory
342	: targetDirectoryName : excludePatterns : flags
343{
344	# CopyDirectoryToContainer <container> : <directoryTokens>
345	#	: <sourceDirectory> : <targetDirectoryName> : <excludePatterns>
346	#	[ : <flags> ] ;
347	#
348	# Supported flags: alwaysUpdate, isTarget
349	# isTarget: <sourceDirectory> is a target, not a path
350
351	# If the image shall only be updated, we don't copy any directories
352	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ]
353			&& ! [ IncludeAllTargetsInContainer $(container) ]
354			&& ! alwaysUpdate in $(flags) {
355		return ;
356	}
357
358	if ! $(targetDirectoryName) {
359		targetDirectoryName = $(sourceDirectory[1]:BS) ;
360	}
361
362	# If sourceDirectory is a path, not a target, make it a target, so we can
363	# treat both the same way.
364	if ! isTarget in $(flags) {
365		sourceDirectory = $(sourceDirectory:G=copy-directory-to-container) ;
366		SEARCH on $(sourceDirectory) = ;
367		TARGET on $(sourceDirectory) = ;
368	}
369
370	local directory = [ AddDirectoryToContainer $(container)
371		: $(directoryTokens) $(targetDirectoryName) ] ;
372
373	local targetDir = $(directory)/-/$(sourceDirectory) ;
374	Depends $(targetDir) : $(sourceDirectory) ;
375	EXCLUDE_PATTERNS on $(targetDir) = $(excludePatterns) ;
376	SOURCE_DIRECTORY on $(targetDir) = $(sourceDirectory) ;
377	TARGET_DIRECTORY on $(targetDir) = $(directory) ;
378	DIRECTORIES_TO_INSTALL on $(directory) += $(targetDir) ;
379}
380
381
382rule AddHeaderDirectoryToContainer container : dirTokens : dirName
383	: flags
384{
385	# AddHeaderDirectoryToContainer <container> : <dirTokens> : [ <dirName> ]
386	#	[ : <flags> ] ;
387	#
388	# Supported flags: alwaysUpdate
389
390	local systemDirTokens
391		= [ on $(container) return $(HAIKU_CONTAINER_SYSTEM_DIR_TOKENS) ] ;
392
393	CopyDirectoryToContainer $(container) : $(systemDirTokens) develop headers
394		: [ FDirName $(HAIKU_TOP) headers $(dirTokens) ]
395		: $(dirName) : -x .svn : $(flags) ;
396}
397
398
399rule AddWifiFirmwareToContainer container : driver : package : archive : extract
400{
401	# AddWifiFirmwareToContainer <container> : <driver> : <package> : <archive>
402	#	: <extract>
403
404	# complete location to wifi firmware archive
405	local firmwareArchive = [ FDirName
406		$(HAIKU_TOP) data system data firmware $(driver) $(archive) ] ;
407
408	local systemDirTokens
409		= [ on $(container) return $(HAIKU_CONTAINER_SYSTEM_DIR_TOKENS) ] ;
410
411	local dirTokens = $(systemDirTokens) data firmware $(driver) ;
412	if $(extract) = true || $(extract) = 1 {
413		ExtractArchiveToContainer $(container) : $(dirTokens)
414			: $(firmwareArchive) : : $(package) ;
415	} else {
416		AddFilesToContainer $(container) : $(dirTokens) : $(firmwareArchive)  ;
417	}
418}
419
420
421rule ExtractArchiveToContainer container : directoryTokens : archiveFile
422	: flags : extractedSubDir
423{
424	# ExtractArchiveToContainer <container> : <directory> : <archiveFile>
425	#	: [ <flags> ] : <extractedSubDir> ;
426	#
427	# Supported flags: alwaysUpdate
428
429	# If the container shall only be updated, we extract only, if explicitely
430	# requested.
431	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ]
432		&& ! alwaysUpdate in $(flags) {
433		return ;
434	}
435
436	local directory = [ AddDirectoryToContainer $(container)
437		: $(directoryTokens) ] ;
438
439	ARCHIVE_FILES_TO_INSTALL on $(directory) += $(archiveFile) ;
440	ARCHIVE_SUBDIR_TO_INSTALL_FROM on $(archiveFile) = $(extractedSubDir) ;
441}
442
443rule AddDriversToContainer container : relativeDirectoryTokens : targets
444{
445	# AddDriversToContainer <container> : <relative directory> : <targets> ;
446	#
447	local systemDirTokens
448		= [ on $(container) return $(HAIKU_CONTAINER_SYSTEM_DIR_TOKENS) ] ;
449	local directoryTokens = $(systemDirTokens) add-ons kernel drivers dev
450		$(relativeDirectoryTokens) ;
451
452	targets = [ FFilterByBuildFeatures $(targets) ] ;
453
454	# A driver can be in multiple categories. Avoid adding it to the bin/
455	# directory more than once.
456	local binTargets ;
457	local target ;
458	for target in $(targets) {
459		local containers
460			= [ on $(target) return $(HAIKU_DRIVER_IN_CONTAINERS) ] ;
461		if ! $(container) in $(containers) {
462			HAIKU_DRIVER_IN_CONTAINERS on $(target)
463				= $(containers) $(container) ;
464			binTargets += $(target) ;
465		}
466	}
467
468	AddFilesToContainer $(container)
469		: $(systemDirTokens) add-ons kernel drivers bin
470		: $(binTargets) ;
471
472	# If the image shall only be updated, we don't add any symlinks.
473	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ]
474		&& ! [ IncludeAllTargetsInContainer $(container) ] {
475		return ;
476	}
477
478	# get the relative symlink path prefix
479	local linkPrefix = ;
480	for i in $(relativeDirectoryTokens) {
481		linkPrefix += .. ;
482	}
483	linkPrefix += .. bin ;
484
485	# add the symlinks
486	local name ;
487	for name in $(targets:BS) {
488		AddSymlinkToContainer $(container) : $(directoryTokens)
489			: [ FDirName $(linkPrefix) $(name) ] : $(name) ;
490	}
491}
492
493rule AddNewDriversToContainer container : relativeDirectoryTokens
494	: targets
495{
496	# AddNewDriversToContainer <container> : <directory> : <targets> ;
497	#
498	local systemDirTokens
499		= [ on $(container) return $(HAIKU_CONTAINER_SYSTEM_DIR_TOKENS) ] ;
500	local directoryTokens = $(systemDirTokens) add-ons kernel drivers
501		$(relativeDirectoryTokens) ;
502
503	targets = [ FFilterByBuildFeatures $(targets) ] ;
504
505	AddFilesToContainer $(container) : $(directoryTokens)
506		: $(targets) ;
507}
508
509rule AddBootModuleSymlinksToContainer container : targets
510{
511	# AddBootModuleSymlinksToContainer <container> : <targets> ;
512	#
513
514	# If the container shall only be updated, we don't add any symlinks.
515
516	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ]
517		&& ! [ IncludeAllTargetsInContainer $(container) ] {
518		return ;
519	}
520
521	local systemDirTokens
522		= [ on $(container) return $(HAIKU_CONTAINER_SYSTEM_DIR_TOKENS) ] ;
523	targets = [ FFilterByBuildFeatures $(targets) ] ;
524
525	# add the symlinks
526	local installTargetsVar
527		= [ on $(container) return $(HAIKU_INSTALL_TARGETS_VAR) ] ;
528	local target ;
529	for target in $(targets) {
530		# Symlink to the first place where the target has been installed.
531		local destTarget = [ on $(target) return $($(installTargetsVar)[1]) ] ;
532		local installDir = [ on $(destTarget) return $(INSTALL_DIR) ] ;
533
534		if ! $(installDir) {
535			Echo "ERROR: AddBootModuleSymlinksToContainer: Can't create a "
536				"symlink to target" \"$(target)"\"." ;
537			Exit "ERROR: Add*ToContainer has not been invoked for it yet." ;
538		}
539
540		# chop off the system dir prefix from installDir
541		installDir = [ on $(installDir) return $(DIRECTORY_TOKENS) ] ;
542		local dummy ;
543		for dummy in $(systemDirTokens) {
544			installDir = $(installDir[2-]) ;
545		}
546
547		local name = $(target:BS) ;
548		local linkTarget = [ FDirName ../../.. $(installDir) $(name) ] ;
549
550		AddSymlinkToContainer $(container)
551			: $(systemDirTokens) add-ons kernel boot
552			: $(linkTarget) : $(name) ;
553	}
554}
555
556
557rule AddLibrariesToContainer container : directory : libs
558{
559	# AddLibrariesToContainer <container> : <directory> : <libs>
560	#
561	# Installs libraries with the appropriate links into the container.
562	#
563
564	local lib ;
565	for lib in $(libs) {
566		local abiVersion = [ on $(lib) return $(HAIKU_LIB_ABI_VERSION) ] ;
567		if $(abiVersion) {
568			local abiVersionedLib = $(lib:G=).$(abiVersion) ;
569			AddFilesToContainer $(container) : $(directory) : $(lib)
570				: $(abiVersionedLib) ;
571			AddSymlinkToContainer $(container) : $(directory)
572				: $(abiVersionedLib) : $(lib:G=) ;
573		} else {
574			AddFilesToContainer $(container) : $(directory) : $(lib) ;
575		}
576	}
577}
578
579
580rule CreateContainerMakeDirectoriesScript container : script
581{
582	MakeLocate $(script) : $(HAIKU_OUTPUT_DIR) ;
583	Always $(script) ;
584
585	local initScript = [ InitScript $(script) ] ;
586
587	local scriptBody
588		= [ FSameTargetWithPrependedGrist $(script) : script-body ] ;
589	LOCATE on $(scriptBody) = [ on $(script) return $(LOCATE) ] ;
590	Depends $(scriptBody) : $(initScript) ;
591	Depends $(script) : $(scriptBody) ;
592
593	# collect the directories to create
594	local dirsToCreate ;
595	local directories
596		= [ on $(container) return $(HAIKU_INSTALL_DIRECTORIES) ] ;
597	local dir ;
598	for dir in $(directories) {
599		if ! [ on $(dir) return $(DONT_CREATE) ] {
600			dirsToCreate += $(dir) ;
601		}
602	}
603
604	# If the image shall only be updated, we don't create directories.
605	if $(dirsToCreate)
606		&& ( ! [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ]
607			|| [ IncludeAllTargetsInContainer $(container) ]
608			|| [ on $(container) return
609				$(HAIKU_CONTAINER_ALWAYS_CREATE_DIRECTORIES) ] ) {
610		Depends $(scriptBody) : $(dirsToCreate) ;
611		CreateContainerMakeDirectoriesScript1 $(scriptBody) : $(dirsToCreate) ;
612
613		local serializationDependency = $(scriptBody) ;
614			# Used to create a dependency chain between the dummy targets.
615			# This forces jam to build them one after the other, thus preventing
616			# concurrent writes to the script file when building with multiple
617			# jobs.
618
619		# For directories with attributes, we convert those the specified
620		# resource files to files with attributes and add commands to the script
621		# adding the attributes to the directories.
622		for dir in $(directories) {
623			local resourceFiles = [ on $(dir) return $(ATTRIBUTE_FILES) ] ;
624			if $(resourceFiles) {
625				local dirTokens = [ on $(dir) return $(DIRECTORY_TOKENS) ] ;
626
627				# translate resources file to file with attributes
628				local attributeFile = $(script)-attributes-$(dirTokens:J=-) ;
629				ResAttr $(attributeFile) : $(resourceFiles) ;
630
631				# use a unique dummy target for this file, on which we
632				# can define the TARGET_DIR variable
633				local dummyTarget = $(script)-attributes-dummy-$(dir:G=) ;
634				NotFile $(dummyTarget) ;
635				TARGET_DIR on $(dummyTarget) = $(dir:G=) ;
636
637				Depends $(dummyTarget) : $(initScript) $(attributeFile)
638					$(serializationDependency) ;
639				Depends $(script) : $(dummyTarget) ;
640				serializationDependency = $(dummyTarget) ;
641
642				AppendToContainerMakeDirectoriesScriptAttributes $(dummyTarget)
643					: $(initScript) $(attributeFile) ;
644			}
645		}
646	}
647}
648
649actions piecemeal CreateContainerMakeDirectoriesScript1
650{
651	echo \$mkdir -p "\"\${tPrefix}$(2:G=)\"" >> $(1)
652}
653
654actions AppendToContainerMakeDirectoriesScriptAttributes
655{
656	echo \$copyAttrs "\"\${sPrefix}$(2[2])\"" \
657		"\"\${tPrefix}$(TARGET_DIR)\"" >> $(2[1])
658}
659
660rule CreateContainerCopyFilesScript container : script
661{
662	MakeLocate $(script) : $(HAIKU_OUTPUT_DIR) ;
663	Always $(script) ;
664
665	local initScript = [ InitScript $(script) ] ;
666
667	local scriptBody
668		= [ FSameTargetWithPrependedGrist $(script) : script-body ] ;
669	LOCATE on $(scriptBody) = [ on $(script) return $(LOCATE) ] ;
670	Depends $(scriptBody) : $(initScript) ;
671	Depends $(script) : $(scriptBody) ;
672
673	local serializationDependency = $(scriptBody) ;
674		# Used to create a dependency chain between the dummy targets.
675		# This forces jam to build them one after the other, thus preventing
676		# concurrent writes to the script file when building with multiple
677		# jobs.
678
679	local needStrip = [ on $(container)
680		return $(HAIKU_CONTAINER_STRIP_BINARIES) ] ;
681		# We are asked to strip the binaries when copying them.
682
683	local dir ;
684	for dir in [ on $(container) return $(HAIKU_INSTALL_DIRECTORIES) ] {
685		# filter the targets that shall be renamed; they have to be copied
686		# individually
687		# we also handle binary separately when asked to strip them
688		local destTargets = [ on $(dir) return $(TARGETS_TO_INSTALL) ] ;
689		local remainingTargets ;
690		local destTarget ;
691		for destTarget in $(destTargets) {
692			local target = [ on $(destTarget) return $(TARGET) ] ;
693			local name = $(destTarget:G=) ;
694			local isBinary = [ on $(target) return $(LINKFLAGS) ] ;
695			local doStrip ;
696			if $(needStrip) && $(isBinary) {
697				doStrip = 1 ;
698			}
699			if $(name) != $(target:BS) || $(doStrip) {
700				# use a unique dummy target for this file, on which we
701				# can define the TARGET_DIR variable
702				local dummyTarget = $(script)-dummy-$(dir:G=)-$(target) ;
703				NotFile $(dummyTarget) ;
704				TARGET_DIR on $(dummyTarget) = $(dir:G=) ;
705
706				local nameFunction
707					= [ on $(destTarget) return $(NAME_FUNCTION) ] ;
708				if $(nameFunction) {
709					INSTALL_TARGET_NAME on $(dummyTarget) = "\\${name}" ;
710				} else {
711					INSTALL_TARGET_NAME on $(dummyTarget) = $(name) ;
712				}
713				NAME_FUNCTION on $(dummyTarget) = $(nameFunction) ;
714
715				Depends $(dummyTarget) : $(initScript) $(target)
716					$(serializationDependency) ;
717				Depends $(script) : $(dummyTarget) ;
718				serializationDependency = $(dummyTarget) ;
719
720				if $(doStrip) {
721					AppendToContainerCopyFilesScriptStripFile $(dummyTarget)
722						: $(initScript) $(target) ;
723				} else {
724					AppendToContainerCopyFilesScriptSingleFile $(dummyTarget)
725						: $(initScript) $(target) ;
726				}
727			} else {
728				remainingTargets += $(target) ;
729			}
730		}
731		targets = $(remainingTargets) ;
732
733		if $(targets) {
734			# use a unique dummy target for this directory, on which we
735			# can define the TARGET_DIR variable
736			local dummyTarget = $(script)-dummy-$(dir:G=) ;
737			NotFile $(dummyTarget) ;
738			TARGET_DIR on $(dummyTarget) = $(dir:G=) ;
739
740			Depends $(dummyTarget) : $(initScript) $(targets)
741				$(serializationDependency) ;
742			Depends $(script) : $(dummyTarget) ;
743			serializationDependency = $(dummyTarget) ;
744
745			OUTPUT_SCRIPT on $(dummyTarget) = $(initScript) ;
746			AppendToContainerCopyFilesScript $(dummyTarget) : $(targets) ;
747		}
748
749		local symlinks = [ on $(dir) return $(SYMLINKS_TO_INSTALL) ] ;
750		local symlink ;
751		for symlink in $(symlinks) {
752			NotFile $(symlink) ;
753
754			Depends $(script) : $(symlink) ;
755			Depends $(symlink) : $(initScript) $(serializationDependency) ;
756			serializationDependency = $(symlink) ;
757
758			AddSymlinkToContainerCopyFilesScript $(symlink) : $(initScript) ;
759		}
760
761		local targetDirs = [ on $(dir) return $(DIRECTORIES_TO_INSTALL) ] ;
762		local targetDir ;
763		for targetDir in $(targetDirs) {
764			NotFile $(targetDir) ;
765
766			Depends $(script) : $(targetDir) ;
767			Depends $(targetDir) : $(initScript) $(serializationDependency) ;
768			serializationDependency = $(targetDir) ;
769
770			AddDirectoryToContainerCopyFilesScript $(targetDir)
771				: $(initScript) ;
772		}
773	}
774}
775
776
777actions piecemeal AppendToContainerCopyFilesScript bind OUTPUT_SCRIPT
778{
779	echo \$cp "\"\${sPrefix}$(2)\"" "\"\${tPrefix}$(TARGET_DIR)\"" \
780		>> $(OUTPUT_SCRIPT)
781}
782
783
784actions AppendToContainerCopyFilesScriptSingleFile
785{
786	if [ -n "$(NAME_FUNCTION:E)" ]; then
787		echo "name=\`$(NAME_FUNCTION:E) \"$(2[2])\" 2> /dev/null \` || exit 1" \
788			>> $(2[1])
789	fi
790
791	echo \$cp "\"\${sPrefix}$(2[2])\"" \
792		"\"\${tPrefix}$(TARGET_DIR)/$(INSTALL_TARGET_NAME)\"" >> $(2[1])
793}
794
795
796actions AppendToContainerCopyFilesScriptStripFile
797{
798	if [ -n "$(NAME_FUNCTION:E)" ]; then
799		echo "name=\`$(NAME_FUNCTION:E) \"$(2[2])\" 2> /dev/null \` || exit 1" \
800			>> $(2[1])
801	fi
802
803	echo \$cp "\"\${sPrefix}$(2[2])\"" \
804		"\"\${tPrefix}$(TARGET_DIR)/$(INSTALL_TARGET_NAME)\"" >> $(2[1])
805
806	echo \$strip "\"\${tPrefix}$(TARGET_DIR)/$(INSTALL_TARGET_NAME)\"" \
807		"2>/dev/null" "|| true" >> $(2[1])
808}
809
810
811actions AddSymlinkToContainerCopyFilesScript
812{
813	echo \$ln -sfn "\"$(SYMLINK_TARGET)\"" "\"\${tPrefix}$(1:G=)\"" >> $(2[1])
814}
815
816
817actions AddDirectoryToContainerCopyFilesScript bind SOURCE_DIRECTORY
818{
819	echo \$cp -r $(EXCLUDE_PATTERNS) "\"\${sPrefix}$(SOURCE_DIRECTORY)/.\"" \
820		"\"\${tPrefix}$(TARGET_DIRECTORY:G=)\"" >> $(2[1])
821}
822
823
824rule CreateContainerExtractFilesScript container : script
825{
826	MakeLocate $(script) : $(HAIKU_OUTPUT_DIR) ;
827	Always $(script) ;
828
829	local initScript = [ InitScript $(script) ] ;
830
831	local scriptBody
832		= [ FSameTargetWithPrependedGrist $(script) : script-body ] ;
833	LOCATE on $(scriptBody) = [ on $(script) return $(LOCATE) ] ;
834	Depends $(scriptBody) : $(initScript) ;
835	Depends $(script) : $(scriptBody) ;
836
837	local serializationDependency = $(scriptBody) ;
838		# Used to create a dependency chain between the dummy targets.
839		# This forces jam to build them one after the other, thus preventing
840		# concurrent writes to the script file when building with multiple
841		# jobs.
842
843	local dir ;
844	for dir in [ on $(container) return $(HAIKU_INSTALL_DIRECTORIES) ] {
845		local archiveFiles = [ on $(dir) return $(ARCHIVE_FILES_TO_INSTALL) ] ;
846		local archiveFile ;
847		for archiveFile in $(archiveFiles) {
848			# use a unique dummy target for this file, on which we
849			# can define the TARGET_DIR variable
850			local dummyTarget = $(script)-dummy-$(dir:G=)-$(archiveFile) ;
851			NotFile $(dummyTarget) ;
852			TARGET_DIR on $(dummyTarget) = $(dir:G=) ;
853
854			local extractedSubDir = [ on $(archiveFile)
855				return $(ARCHIVE_SUBDIR_TO_INSTALL_FROM) ] ;
856			ARCHIVE_SUBDIR_TO_INSTALL_FROM on $(dummyTarget) =
857				$(extractedSubDir:E=.) ;
858
859			Depends $(dummyTarget) : $(initScript) $(archiveFile)
860				$(serializationDependency) ;
861			Depends $(script) : $(dummyTarget) ;
862			serializationDependency = $(dummyTarget) ;
863
864			AddExtractFileToContainerExtractFilesScript $(dummyTarget)
865				: $(initScript) $(archiveFile) ;
866		}
867	}
868}
869
870
871actions AddExtractFileToContainerExtractFilesScript
872{
873	echo extractFile "\"$(2[2])\"" "\"$(TARGET_DIR)\"" \
874		"\"$(ARCHIVE_SUBDIR_TO_INSTALL_FROM)\"" >> $(2[1])
875}
876
877
878rule AddPackagesAndRepositoryVariablesToContainerScript script : container
879{
880	AddVariableToScript $(script) : downloadDir : $(HAIKU_DOWNLOAD_DIR) ;
881	AddTargetVariableToScript $(script) : <build>package ;
882	AddTargetVariableToScript $(script) : <build>get_package_dependencies
883		: getPackageDependencies ;
884
885	# Add a variable to indicate whether packages dependencies shall be
886	# resolved. We always want to do that in non-update mode, but also in update
887	# mode when all packages are updated.
888	local updateOnly
889		= [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ] ;
890	local resolvePackageDependencies ;
891	if ( ! $(updateOnly) || $(HAIKU_UPDATE_ALL_PACKAGES) )
892		&& ! $(HAIKU_BOOTSTRAP_BUILD) {
893		resolvePackageDependencies = 1 ;
894	}
895	AddVariableToScript $(script) : resolvePackageDependencies
896		: $(resolvePackageDependencies) ;
897
898	AddVariableToScript $(script) : updateAllPackages
899		: $(HAIKU_UPDATE_ALL_PACKAGES) ;
900
901	# Add variable "systemPackages"  with the packages copied/updated.
902	local allPackages = [ on $(container) return $(HAIKU_PACKAGES_IN_IMAGE) ] ;
903	if $(updateOnly) && ! [ IncludeAllTargetsInContainer $(container) ] {
904		allPackages = [ FilterContainerUpdateTargets $(allPackages)
905			: [ on $(container) return $(HAIKU_INCLUDE_IN_CONTAINER_VAR) ] ] ;
906	}
907
908	AddTargetVariableToScript $(script) : $(allPackages) : systemPackages ;
909
910	# Generate the repository package lists and add variables for the
911	# repositories.
912	local repository ;
913	local repositoryFiles ;
914	for repository in $(HAIKU_REPOSITORIES) {
915		repositoryFiles
916			+= [ on $(repository) return $(HAIKU_REPOSITORY_CACHE_FILE) ] ;
917	}
918
919	AddTargetVariableToScript $(script) : $(repositoryFiles) : repositories ;
920}
921
922
923#pragma mark - Haiku Image rules
924
925rule SetUpdateHaikuImageOnly flag
926{
927	HAIKU_CONTAINER_UPDATE_ONLY on $(HAIKU_IMAGE_CONTAINER_NAME) = $(flag) ;
928}
929
930rule IsUpdateHaikuImageOnly
931{
932	on $(HAIKU_IMAGE_CONTAINER_NAME) return $(HAIKU_CONTAINER_UPDATE_ONLY) ;
933}
934
935rule AddDirectoryToHaikuImage directoryTokens : attributeFiles
936{
937	# AddDirectoryToHaikuImage <directoryTokens> : <attributeFiles>
938
939	return [ AddDirectoryToContainer $(HAIKU_IMAGE_CONTAINER_NAME)
940		: $(directoryTokens) : $(attributeFiles) ] ;
941}
942
943rule AddFilesToHaikuImage directory : targets : destName : flags
944{
945	# AddFilesToHaikuImage <directory> : <targets> : [ <destName> ]
946	#	: [ <flags> ]
947
948	AddFilesToContainer $(HAIKU_IMAGE_CONTAINER_NAME) : $(directory)
949		: $(targets) : $(destName) : $(flags) ;
950}
951
952rule FFilesInHaikuImageDirectory directoryTokens
953{
954	return [ FFilesInContainerDirectory $(HAIKU_IMAGE_CONTAINER_NAME)
955		: $(directoryTokens) ] ;
956}
957
958rule AddSymlinkToHaikuImage directoryTokens : linkTarget : linkName
959{
960	# AddSymlinkToHaikuImage <directory> : <link target> [ : <link name> ] ;
961
962	linkTarget = $(linkTarget:J=/) ;
963
964	AddSymlinkToContainer $(HAIKU_IMAGE_CONTAINER_NAME) : $(directoryTokens)
965		: $(linkTarget) : $(linkName) ;
966}
967
968rule FSymlinksInHaikuImageDirectory directoryTokens
969{
970	return [ FSymlinksInContainerDirectory $(HAIKU_IMAGE_CONTAINER_NAME)
971		: $(directoryTokens) ] ;
972}
973
974rule CopyDirectoryToHaikuImage directoryTokens : sourceDirectory
975	: targetDirectoryName : excludePatterns : flags
976{
977	CopyDirectoryToContainer $(HAIKU_IMAGE_CONTAINER_NAME) : $(directoryTokens)
978		: $(sourceDirectory) : $(targetDirectoryName) : $(excludePatterns)
979		: $(flags) ;
980}
981
982rule AddSourceDirectoryToHaikuImage dirTokens : flags
983{
984	# AddSourceDirectoryToHaikuImage <dirTokens> : <flags> ;
985
986	CopyDirectoryToHaikuImage home HaikuSources
987		: [ FDirName $(HAIKU_TOP) $(dirTokens) ]
988		: : : $(flags) ;
989}
990
991rule AddHeaderDirectoryToHaikuImage dirTokens : dirName : flags
992{
993	# AddHeaderDirectoryToHaikuImage <dirTokens> : [ <dirName> ]
994	#	: <flags> ;
995
996	AddHeaderDirectoryToContainer $(HAIKU_IMAGE_CONTAINER_NAME) : $(dirTokens)
997		: $(dirName) : $(flags) ;
998}
999
1000rule AddWifiFirmwareToHaikuImage driver : package : archive : extract
1001{
1002	# AddWifiFirmwareToHaikuImage <driver> : <package> : <archive> : <extract>
1003
1004	AddWifiFirmwareToHaikuImage $(HAIKU_IMAGE_CONTAINER_NAME) : $(driver)
1005		: $(package) : $(archive) : $(extract) ;
1006}
1007
1008rule ExtractArchiveToHaikuImage dirTokens : archiveFile : flags
1009	: extractedSubDir
1010{
1011	# ExtractArchiveToHaikuImage <dirTokens> : <archiveFile> : <flags>
1012	#	: <extractedSubDir> ;
1013
1014	ExtractArchiveToContainer $(HAIKU_IMAGE_CONTAINER_NAME) : $(dirTokens)
1015		: $(archiveFile) : $(flags) : $(extractedSubDir) ;
1016}
1017
1018rule AddDriversToHaikuImage relativeDirectoryTokens : targets
1019{
1020	# AddDriversToHaikuImage <relative directory> : <targets> ;
1021
1022	AddDriversToContainer $(HAIKU_IMAGE_CONTAINER_NAME)
1023		: $(relativeDirectoryTokens) : $(targets) ;
1024}
1025
1026rule AddNewDriversToHaikuImage relativeDirectoryTokens : targets
1027{
1028	# AddNewDriversToHaikuImage <relative directory> : <targets> ;
1029
1030	AddNewDriversToContainer $(HAIKU_IMAGE_CONTAINER_NAME)
1031		: $(relativeDirectoryTokens) : $(targets) ;
1032}
1033
1034rule AddBootModuleSymlinksToHaikuImage targets
1035{
1036	# AddBootModuleSymlinksToHaikuImage <targets> ;
1037
1038	AddBootModuleSymlinksToContainer $(HAIKU_IMAGE_CONTAINER_NAME)
1039		: $(targets) ;
1040}
1041
1042rule AddPackageFilesToHaikuImage location : packages : flags
1043{
1044	# AddPackageFilesToHaikuImage <location> : <packages> : <flags>
1045	#
1046	# Supported flags:
1047	#	nameFromMetaInfo - determine the target file name from the package meta
1048	#		info
1049
1050	packages = [ FFilterByBuildFeatures $(packages) ] ;
1051	HAIKU_PACKAGES_IN_IMAGE on $(HAIKU_IMAGE_CONTAINER_NAME)
1052		= [ on $(HAIKU_IMAGE_CONTAINER_NAME) return $(HAIKU_PACKAGES_IN_IMAGE) ]
1053			$(packages) ;
1054	HAIKU_PACKAGE_INSTALLATION_LOCATION on $(packages) = $(location) ;
1055
1056	if nameFromMetaInfo in $(flags) {
1057		AddFilesToHaikuImage $(location) packages : $(packages)
1058			: packageFileName : computeName ;
1059	} else {
1060		AddFilesToHaikuImage $(location) packages : $(packages) ;
1061	}
1062}
1063
1064rule AddOptionalHaikuImagePackages packages
1065{
1066	local package ;
1067	for package in $(packages) {
1068		if ! [ on $(package) return $(HAIKU_OPTIONAL_PACKAGE_ADDED) ] {
1069			HAIKU_OPTIONAL_PACKAGE_ADDED on $(package) = 1 ;
1070			HAIKU_ADDED_OPTIONAL_PACKAGES += $(package) ;
1071		}
1072		local dependencies = [ on $(package)
1073			return $(HAIKU_OPTIONAL_PACKAGE_DEPENDENCIES) ] ;
1074		AddOptionalHaikuImagePackages $(dependencies) ;
1075	}
1076}
1077
1078rule SuppressOptionalHaikuImagePackages packages
1079{
1080	local package ;
1081	for package in $(packages) {
1082		if ! [ on $(package) return $(HAIKU_OPTIONAL_PACKAGE_SUPPRESSED) ] {
1083			HAIKU_OPTIONAL_PACKAGE_SUPPRESSED on $(package) = 1 ;
1084		}
1085	}
1086}
1087
1088rule IsOptionalHaikuImagePackageAdded package
1089{
1090	if ! [ on $(package) return $(HAIKU_OPTIONAL_PACKAGE_EXISTS) ] {
1091		HAIKU_OPTIONAL_PACKAGE_EXISTS on $(package) = 1 ;
1092		HAIKU_EXISTING_OPTIONAL_PACKAGES += $(package) ;
1093	}
1094
1095	if [ on $(package) return $(HAIKU_OPTIONAL_PACKAGE_ADDED) ] &&
1096			! [ on $(package) return $(HAIKU_OPTIONAL_PACKAGE_SUPPRESSED) ] {
1097		return 1 ;
1098	}
1099
1100	return ;
1101}
1102
1103rule OptionalPackageDependencies package : dependencies
1104{
1105	HAIKU_OPTIONAL_PACKAGE_DEPENDENCIES on $(package) = $(dependencies) ;
1106	if [ on $(package) return $(HAIKU_OPTIONAL_PACKAGE_ADDED) ] {
1107		AddOptionalHaikuImagePackages $(dependencies) ;
1108	}
1109}
1110
1111
1112rule AddHaikuImagePackages packages
1113{
1114	# AddHaikuImagePackages <packages> ;
1115	# Adds the given packages <packages> to the image.
1116
1117	packages = [ FFilterByBuildFeatures $(packages) ] ;
1118
1119	local package ;
1120	for package in $(packages) {
1121		local resolvedPackage = [ IsPackageAvailable $(package) ] ;
1122		if ! $(resolvedPackage) {
1123			Echo "AddHaikuImagePackages: package" $(package)
1124				"not available!" ;
1125			continue ;
1126		}
1127
1128		if ! [ on $(resolvedPackage) return $(HAIKU_PACKAGE_ADDED) ] {
1129			HAIKU_PACKAGE_ADDED on $(resolvedPackage) = 1 ;
1130			HAIKU_ADDED_PACKAGES += $(resolvedPackage) ;
1131
1132			# download the package file and add it to the image
1133			local file = [ FetchPackage $(package) ] ;
1134
1135			if $(HAIKU_UPDATE_ALL_PACKAGES) {
1136				HAIKU_INCLUDE_IN_IMAGE on $(file) = 1 ;
1137			}
1138
1139			AddPackageFilesToHaikuImage system : $(file) ;
1140		}
1141	}
1142}
1143
1144
1145rule IsHaikuImagePackageAdded package
1146{
1147	local resolvedPackage = [ IsPackageAvailable $(package) ] ;
1148	if $(resolvedPackage)
1149		&& [ on $(resolvedPackage) return $(HAIKU_PACKAGE_ADDED) ] {
1150		return 1 ;
1151	}
1152
1153	return ;
1154}
1155
1156
1157rule BuildHaikuImagePackageList target
1158{
1159	if ! $(target) {
1160		return ;
1161	}
1162
1163	# get the file names of all added packages
1164	local packageFiles ;
1165	local package ;
1166	for package in $(HAIKU_ADDED_PACKAGES) {
1167		packageFiles += [ FetchPackage $(package) : nameResolved ] ;
1168	}
1169
1170	# extract the versioned package names (without revision)
1171	packageFiles = [ Match "(.*)-[^-]*-[^-]*" : $(packageFiles:B) ] ;
1172
1173	HAIKU_IMAGE_PACKAGES on $(target) = $(packageFiles) ;
1174}
1175
1176
1177actions BuildHaikuImagePackageList
1178{
1179	echo $(HAIKU_IMAGE_PACKAGES) | xargs -n 1 echo | LC_ALL=C sort -u > $(1)
1180}
1181
1182
1183rule InstallSourceArchive file : url
1184{
1185	if $(HAIKU_INCLUDE_SOURCES) = 1 {
1186		# download archive file
1187		local archiveFile = [ DownloadFile $(file) : $(url) ] ;
1188
1189		# copy directly into image
1190		AddFilesToHaikuImage _sources_ : $(archiveFile) ;
1191	}
1192}
1193
1194rule InstallOptionalHaikuImagePackage url : dirTokens : flags
1195{
1196	# TODO: Remove the non-hpkg cases!
1197	# Currently the semantics differs depending on whether the  cdPackage flag
1198	# has been specified and the type of the package file:
1199	# * For a hpkg <dirTokens> is ignored. The package will be copied into the
1200	#   system/packages directory.
1201	# * For a regular archive and cdPackage, <dirTokens> is ignored and
1202	#   the package will be copied to the _package_ directory of the CD image.
1203	# * For a regular archive and without cdPackage, <dirTokens> specifies the
1204	#   directory relative to the image's root directory where the content of
1205	#   the archive will be extracted to.
1206	#
1207	# Supported flags: cdPackage
1208
1209	local package = $(url:BS) ;
1210
1211	# download archive file
1212	local archiveFile = [ DownloadFile $(package) : $(url) ] ;
1213
1214	if $(package:S) = .hpkg {
1215		if $(HAIKU_UPDATE_ALL_PACKAGES) {
1216			HAIKU_INCLUDE_IN_IMAGE on $(archiveFile) = 1 ;
1217		}
1218		AddPackageFilesToHaikuImage system : $(archiveFile) ;
1219	} else if cdPackage in $(flags) && $(HAIKU_CD_NAME) {
1220		# TODO: If HAIKU_CD_NAME is set, that doesn't mean we're building a CD
1221		# image!
1222		# copy onto image
1223		AddFilesToHaikuImage _packages_ : $(archiveFile) ;
1224	} else {
1225		# extract onto image
1226		ExtractArchiveToHaikuImage $(dirTokens) : $(archiveFile) : $(flags) ;
1227	}
1228}
1229
1230rule AddEntryToHaikuImageUserGroupFile file : entry
1231{
1232	local allEntries = [ on $(file) return $(HAIKU_IMAGE_USER_GROUP_ENTRIES) ] ;
1233
1234	if $(allEntries) {
1235		allEntries = $(allEntries)|$(entry) ;
1236	} else {
1237		allEntries = $(entry) ;
1238
1239		Always $(file) ;
1240		MakeLocate $(file) : $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) ;
1241		BuildHaikuImageUserGroupFile $(file) ;
1242		AddFilesToHaikuImage system settings etc : $(file) ;
1243	}
1244
1245	HAIKU_IMAGE_USER_GROUP_ENTRIES on $(file) = $(allEntries) ;
1246}
1247
1248actions BuildHaikuImageUserGroupFile
1249{
1250	echo "$(HAIKU_IMAGE_USER_GROUP_ENTRIES)" | tr '|' '\n' > $(1)
1251}
1252
1253rule AddUserToHaikuImage user : uid : gid : home : shell : realName
1254{
1255	if ! $(user) || ! $(uid) || ! $(gid) || ! $(home) {
1256		Exit "Invalid haiku user specification passed to AddUserToHaikuImage." ;
1257	}
1258
1259	local entry
1260		= $(user):x:$(uid):$(gid):$(realName:E=$(user)):$(home):$(shell:E="") ;
1261
1262	AddEntryToHaikuImageUserGroupFile <haiku-image>passwd : $(entry) ;
1263}
1264
1265rule AddGroupToHaikuImage group : gid : members
1266{
1267	if ! $(group) || ! $(gid) {
1268		Exit "Invalid haiku group specification passed to"
1269			"AddGroupToHaikuImage." ;
1270	}
1271
1272	local entry = $(group):x:$(gid):$(members:J=,:E) ;
1273
1274	AddEntryToHaikuImageUserGroupFile <haiku-image>group : $(entry) ;
1275}
1276
1277
1278rule AddLibrariesToHaikuImage directory : libs
1279{
1280	# AddLibraryToHaikuImage <directory> : <libs>
1281	#
1282	# Installs libraries with the appropriate links onto the image.
1283	#
1284
1285	AddLibrariesToContainer $(HAIKU_IMAGE_CONTAINER_NAME) : $(directory)
1286		: $(libs) ;
1287}
1288
1289
1290rule CreateHaikuImageMakeDirectoriesScript script
1291{
1292	CreateContainerMakeDirectoriesScript $(HAIKU_IMAGE_CONTAINER_NAME)
1293		: $(script) ;
1294}
1295
1296rule CreateHaikuImageCopyFilesScript script
1297{
1298	CreateContainerCopyFilesScript $(HAIKU_IMAGE_CONTAINER_NAME) : $(script) ;
1299}
1300
1301rule CreateHaikuImageExtractFilesScript script
1302{
1303	CreateContainerExtractFilesScript $(HAIKU_IMAGE_CONTAINER_NAME)
1304		: $(script) ;
1305}
1306
1307rule BuildHaikuImage haikuImage : scripts : isImage : isVMwareImage
1308{
1309	# BuildHaikuImage <haiku image> : <scripts> : <is image> : <isVMwareImage> ;
1310
1311	if $(isImage) = 1 || $(isImage) = true {
1312		IS_IMAGE on $(haikuImage) = 1 ;
1313	} else {
1314		IS_IMAGE on $(haikuImage) = "" ;
1315	}
1316
1317	if $(isVMwareImage) = 1 || $(isVMwareImage) = true {
1318		IS_VMWARE_IMAGE on $(haikuImage) = 1 ;
1319	} else {
1320		IS_VMWARE_IMAGE on $(haikuImage) = "" ;
1321	}
1322
1323	local mainScript = build_haiku_image ;
1324	SEARCH on $(mainScript) = [ FDirName $(HAIKU_TOP) build scripts ] ;
1325
1326	Depends $(haikuImage) : $(mainScript) $(scripts) ;
1327	BuildHaikuImage1 $(haikuImage) : $(mainScript) $(scripts) ;
1328}
1329
1330actions BuildHaikuImage1
1331{
1332	export imagePath="$(1)"
1333	export isImage="$(IS_IMAGE)"
1334	export isVMwareImage="$(IS_VMWARE_IMAGE)"
1335	$(2[1]) $(2[2-])
1336}
1337
1338rule BuildVMWareImage vmwareImage : plainImage : imageSize
1339{
1340	# BuildVMWareImage <vmware image> : <plain image> : <image size in MB>
1341
1342	IMAGE_SIZE on $(vmwareImage) = $(imageSize) ;
1343
1344	Depends $(vmwareImage) : <build>vmdkheader $(plainImage) ;
1345	BuildVMWareImage1 $(vmwareImage) : <build>vmdkheader $(plainImage) ;
1346}
1347
1348actions BuildVMWareImage1
1349{
1350	$(RM) $(1)
1351	$(2[1]) -h 64k -i$(IMAGE_SIZE)M $(1) &&
1352	cat $(2[2]) >> $(1)
1353}
1354
1355
1356#pragma mark - Network Boot Archive rules
1357
1358rule AddDirectoryToNetBootArchive directoryTokens
1359{
1360	# AddDirectoryToNetBootArchive <directoryTokens>
1361
1362	return [ AddDirectoryToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
1363		: $(directoryTokens) ] ;
1364}
1365
1366rule AddFilesToNetBootArchive directory : targets : destName
1367{
1368	# AddFilesToNetBootArchive <directory> : <targets> [ : dest name ]
1369
1370	AddFilesToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME) : $(directory)
1371		: $(targets) : $(destName) ;
1372}
1373
1374rule AddSymlinkToNetBootArchive directoryTokens : linkTarget : linkName
1375{
1376	# AddSymlinkToNetBootArchive <directory> : <link target> [ : <link name> ] ;
1377
1378	AddSymlinkToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
1379		: $(directoryTokens) : $(linkTarget) : $(linkName) ;
1380}
1381
1382rule AddDriversToNetBootArchive relativeDirectoryTokens : targets
1383{
1384	# AddDriversToNetBootArchive <relative directory> : <targets> ;
1385
1386	AddDriversToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
1387		: $(relativeDirectoryTokens) : $(targets) ;
1388}
1389
1390rule AddNewDriversToNetBootArchive relativeDirectoryTokens : targets
1391{
1392	# AddNewDriversToNetBootArchive <relative directory> : <targets> ;
1393
1394	AddNewDriversToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
1395		: $(relativeDirectoryTokens) : $(targets) ;
1396}
1397
1398rule AddDriverRegistrationToNetBootArchive relativeDirectoryTokens : target
1399	: links
1400{
1401	# AddDriverRegistrationToNetBootArchive <directory> : <link target>
1402	#	: <link names> ] ;
1403
1404	AddDriverRegistrationToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
1405		: $(relativeDirectoryTokens) : $(target) : $(links) ;
1406}
1407
1408rule AddBootModuleSymlinksToNetBootArchive targets
1409{
1410	# AddBootModuleSymlinksToNetBootArchive <targets> ;
1411
1412	AddBootModuleSymlinksToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
1413		: $(targets) ;
1414}
1415
1416rule CreateNetBootArchiveMakeDirectoriesScript script
1417{
1418	CreateContainerMakeDirectoriesScript
1419		$(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME) : $(script) ;
1420}
1421
1422rule CreateNetBootArchiveCopyFilesScript script
1423{
1424	CreateContainerCopyFilesScript $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
1425		: $(script) ;
1426}
1427
1428rule BuildNetBootArchive archive : scripts
1429{
1430	# BuildNetBootArchive <archive> : <scripts>  ;
1431
1432	local mainScript = build_archive ;
1433	SEARCH on $(mainScript) = [ FDirName $(HAIKU_TOP) build scripts ] ;
1434
1435	Depends $(archive) : $(mainScript) $(scripts) ;
1436	BuildNetBootArchive1 $(archive) : $(mainScript) $(scripts) ;
1437}
1438
1439actions BuildNetBootArchive1
1440{
1441	$(2[1]) $(1) $(2[2-])
1442}
1443
1444
1445#pragma mark - Floppy Boot Archive rules
1446
1447
1448rule AddDirectoryToFloppyBootArchive directoryTokens
1449{
1450	# AddDirectoryToFloppyBootArchive <directoryTokens>
1451
1452	return [ AddDirectoryToContainer $(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME)
1453		: $(directoryTokens) ] ;
1454}
1455
1456rule AddFilesToFloppyBootArchive directory : targets : destName
1457{
1458	# AddFilesToFloppyBootArchive <directory> : <targets> [ : dest name ]
1459
1460	AddFilesToContainer $(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME) : $(directory)
1461		: $(targets) : $(destName) ;
1462}
1463
1464rule AddSymlinkToFloppyBootArchive directoryTokens : linkTarget : linkName
1465{
1466	# AddSymlinkToFloppyBootArchive <directory> : <link target>
1467	#	[ : <link name> ] ;
1468
1469	AddSymlinkToContainer $(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME)
1470		: $(directoryTokens) : $(linkTarget) : $(linkName) ;
1471}
1472
1473rule AddDriversToFloppyBootArchive relativeDirectoryTokens : targets
1474{
1475	# AddDriversToFloppyBootArchive <relative directory> : <targets> ;
1476
1477	AddDriversToContainer $(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME)
1478		: $(relativeDirectoryTokens) : $(targets) ;
1479}
1480
1481rule AddNewDriversToFloppyBootArchive relativeDirectoryTokens : targets
1482{
1483	# AddNewDriversToFloppyBootArchive <relative directory> : <targets> ;
1484
1485	AddNewDriversToContainer $(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME)
1486		: $(relativeDirectoryTokens) : $(targets) ;
1487}
1488
1489rule AddDriverRegistrationToFloppyBootArchive relativeDirectoryTokens : target
1490	: links
1491{
1492	# AddDriverRegistrationToFloppyBootArchive <directory> : <link target>
1493	#	: <link names> ] ;
1494
1495	AddDriverRegistrationToContainer $(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME)
1496		: $(relativeDirectoryTokens) : $(target) : $(links) ;
1497}
1498
1499rule AddBootModuleSymlinksToFloppyBootArchive targets
1500{
1501	# AddBootModuleSymlinksToFloppyBootArchive <targets> ;
1502
1503	AddBootModuleSymlinksToContainer $(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME)
1504		: $(targets) ;
1505}
1506
1507rule CreateFloppyBootArchiveMakeDirectoriesScript script
1508{
1509	CreateContainerMakeDirectoriesScript
1510		$(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME) : $(script) ;
1511}
1512
1513rule CreateFloppyBootArchiveCopyFilesScript script
1514{
1515	CreateContainerCopyFilesScript $(HAIKU_FLOPPY_BOOT_IMAGE_CONTAINER_NAME)
1516		: $(script) ;
1517}
1518
1519rule BuildFloppyBootArchive archive : scripts
1520{
1521	# BuildHFloppyBootArchive <archive> : <scripts>  ;
1522
1523	local mainScript = build_archive ;
1524	SEARCH on $(mainScript) = [ FDirName $(HAIKU_TOP) build scripts ] ;
1525
1526	Depends $(archive) : $(mainScript) $(scripts) ;
1527	BuildFloppyBootArchive1 $(archive) : $(mainScript) $(scripts) ;
1528}
1529
1530actions BuildFloppyBootArchive1
1531{
1532	$(2[1]) $(1) $(2[2-])
1533}
1534
1535# warning: that is quite x86 dependant...
1536
1537rule BuildFloppyBootImage image : haikuLoader : archive
1538{
1539	Depends $(image) : $(haikuLoader) ;
1540	Depends $(image) : $(archive) ;
1541	#MakeLocateDebug $(image) ;
1542	FLOPPY_IMAGE_SIZE on $(image) = $(HAIKU_BOOT_FLOPPY_IMAGE_SIZE) ;
1543	ARCHIVE_IMAGE_OFFSET on $(image) = $(HAIKU_BOOT_ARCHIVE_IMAGE_OFFSET) ;
1544	BuildFloppyBootImage1 $(image) : $(haikuLoader) $(archive) ;
1545	if $(HAIKU_BOOT_PLATFORM) = atari_m68k {
1546		Depends $(image) : <build>fixup_tos_boot_checksum ;
1547		BuildFloppyBootImageFixupM68K $(image)
1548			: <build>fixup_tos_boot_checksum ;
1549	}
1550	if $(HAIKU_BOOT_PLATFORM) = amiga_m68k {
1551		Depends $(image) : <build>fixup_amiga_boot_checksum ;
1552		BuildFloppyBootImageFixupM68K $(image)
1553			: <build>fixup_amiga_boot_checksum ;
1554	}
1555}
1556
1557actions BuildFloppyBootImage1
1558{
1559	haiku_loader_size=`stat -c %s "$(>[1])"`
1560	drivers_tgz_size=`stat -c %s "$(>[2])"`
1561	if [ $? -ne 0 ] ; then
1562		# FreeBSD's stat command don't support -c/--format option
1563		# and use %z specifier for file size
1564		haiku_loader_size=`stat -f %z "$(>[1])"`
1565		drivers_tgz_size=`stat -f %z "$(>[2])"`
1566	fi
1567	archive_image_offset=`echo "$(ARCHIVE_IMAGE_OFFSET) * 1024" | bc`
1568	floppy_tgz_size=\
1569		`echo "($(FLOPPY_IMAGE_SIZE) - $(ARCHIVE_IMAGE_OFFSET)) * 1024" | bc`
1570	if [ $haiku_loader_size -gt $archive_image_offset ] ; then
1571		echo "Error: $(>[1]) is too big ($haiku_loader_size) to fit "
1572		echo "       before the boot archive starting at $archive_image_offset!"
1573		exit 1
1574	fi
1575	if [ $drivers_tgz_size -gt $floppy_tgz_size ] ; then
1576		echo "Error: $(>[2]) is too big ($drivers_tgz_size) to fit "
1577		echo "       in the boot floppy ($floppy_tgz_size)!"
1578		exit 1
1579	fi
1580	$(RM) $(<)
1581	# make an empty image
1582	dd if=/dev/zero of=$(<) bs=1k count=$(FLOPPY_IMAGE_SIZE)
1583	# add haiku_loader
1584	dd if=$(>[1]) of=$(<) conv=notrunc
1585	# add the boot drivers tgz archive
1586	dd if=$(>[2]) of=$(<) bs=$(ARCHIVE_IMAGE_OFFSET)k seek=1 conv=notrunc
1587}
1588
1589actions BuildFloppyBootImageFixupM68K
1590{
1591	# fixup the boot sector checksum
1592	$(>[1]) $(<)
1593}
1594
1595#pragma mark - CD Boot Image rules
1596
1597rule BuildCDBootImage image : bootfloppy : extrafiles
1598{
1599	Depends $(image) : $(bootfloppy) ;
1600	Depends $(image) : $(extrafiles) ;
1601	BOOTIMG on $(image) = $(bootfloppy) ;
1602
1603	BuildCDBootImage1 $(image) : $(bootfloppy) $(extrafiles) ;
1604}
1605
1606actions BuildCDBootImage1
1607{
1608	$(RM) $(<)
1609	mkisofs -b $(BOOTIMG) -r -J -V bootimg -o $(<) $(>[1]) $(>[2-])
1610}
1611
1612
1613#pragma mark - CD Boot PPC Image rules
1614
1615rule BuildCDBootPPCImage image : hfsmaps : elfloader : coffloader : chrpscript
1616	: extrafiles
1617{
1618	Depends $(image) : $(elfloader) ;
1619	Depends $(image) : $(coffloader) ;
1620	Depends $(image) : $(chrpscript) ;
1621	Depends $(image) : $(extrafiles) ;
1622	Depends $(image) : $(hfsmaps) ;
1623	MAPS on $(image) = $(hfsmaps) ;
1624
1625	BuildCDBootPPCImage1 $(image) : $(elfloader) $(coffloader) $(chrpscript)
1626		$(extrafiles) ;
1627}
1628
1629actions BuildCDBootPPCImage1 bind MAPS
1630{
1631	$(RM) $(<)
1632	mkdir -p $(HAIKU_OUTPUT_DIR)/cd/ppc
1633	mkdir -p $(HAIKU_OUTPUT_DIR)/cd/boot
1634	# CHRP Boot script
1635	cp $(>[3]) $(HAIKU_OUTPUT_DIR)/cd/ppc/bootinfo.txt
1636	cp $(>[3]) $(HAIKU_OUTPUT_DIR)/cd/boot/boot.chrp
1637	# Haiku Bootloaders
1638	cp $(>[2]) $(HAIKU_OUTPUT_DIR)/cd/boot/haikuloader.xcf
1639	cp $(>[1]) $(HAIKU_OUTPUT_DIR)/cd/boot/haikuloader.elf
1640	# Extras (readme files, etc)
1641	cp $(>[4]) $(HAIKU_OUTPUT_DIR)/cd/
1642
1643	mkisofs -v -hfs -part -map $(MAPS) -no-desktop -hfs-volid bootimg \
1644		-V bootimg -hfs-bless $(HAIKU_OUTPUT_DIR)/cd/boot -prep-boot \
1645		boot/haikuloader.xcf -r -o $(<) $(HAIKU_OUTPUT_DIR)/cd \
1646	|| \
1647	genisoimage -v -hfs -part -map $(MAPS) -no-desktop -hfs-volid bootimg \
1648		-V bootimg -hfs-bless $(HAIKU_OUTPUT_DIR)/cd/boot -prep-boot \
1649		boot/haikuloader.xcf -r -o $(<) $(HAIKU_OUTPUT_DIR)/cd
1650	$(RM) -R $(HAIKU_OUTPUT_DIR)/cd
1651}
1652
1653
1654