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