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