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