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