ImageRules revision b39c8d37
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 -f $(1)
41	echo -n > $(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)+=\\\" $(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		NotFile $(directory) ;
112	
113		# mark the parent dir as not to be created
114		local parent = [ FReverse $(directoryTokens) ] ;
115		parent = [ FReverse $(parent[2-]) ] ;
116		if $(parent) {
117			parent = [ FDirName $(parent) ] ;
118			parent = $(parent:G=$(containerGrist)) ;
119			DONT_CREATE on $(parent) = true ;
120		}
121	}
122
123	return $(directory) ;
124}
125
126rule FilterContainerUpdateTargets targets : filterVariable
127{
128	# FilterContainerUpdateTargets targets : filterVariable
129
130	local filteredTargets ;
131	local target ;
132	for target in $(targets) {
133		if [ on $(target) return $($(filterVariable)) ] {
134			filteredTargets += $(target) ;
135		}
136	}
137	return $(filteredTargets) ;
138}
139
140rule AddFilesToContainer container : directoryTokens : targets : destName
141{
142	# AddFilesToContainer <container> : <directoryTokens> : <targets>
143	#	[ : dest name ]
144	#
145	local directory = [ AddDirectoryToContainer $(container)
146		: $(directoryTokens) ] ;
147	local containerGrist = [ on $(container) return $(HAIKU_CONTAINER_GRIST) ] ;
148
149	# If the image shall only be updated, we filter out all targets not marked
150	# accordingly.
151	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ] {
152		local filterVar
153			= [ on $(container) return $(HAIKU_INCLUDE_IN_CONTAINER_VAR) ] ;
154		if $(filterVar) {
155			targets = [ FilterContainerUpdateTargets $(targets)
156				: $(filterVar) ] ;
157		}
158	}
159
160	# We create a unique dummy target per target to install.
161	local installTargetsVar
162		= [ on $(container) return $(HAIKU_INSTALL_TARGETS_VAR) ] ;
163	local target ;
164	for target in $(targets) {
165		local name ;
166		if $(destName) {
167			name = $(destName) ;
168		} else {
169			name = $(target:G=:D=) ;
170		}
171
172		local destTarget = $(name:G=$(containerGrist)__$(directory:G=)) ;
173		TARGET on $(destTarget) = $(target) ;
174		INSTALL_DIR on $(destTarget) = $(directory) ;
175		$(installTargetsVar) on $(target) += $(destTarget) ;
176		TARGETS_TO_INSTALL on $(directory) += $(destTarget) ;
177	}
178}
179
180rule AddSymlinkToContainer container : directoryTokens : linkTarget : linkName
181{
182	# AddSymlinkToContainer <container> : <directory> : <link target>
183	#	[ : <link name> ] ;
184	#
185
186	# If the image shall only be updated, we don't add any symlinks.
187	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ] {
188		return ;
189	}
190
191	local directory = [ AddDirectoryToContainer $(container)
192		: $(directoryTokens) ] ;
193
194	if ! $(linkName) {
195		local path = [ FReverse [ FSplitPath $(linkTarget) ] ] ;
196		linkName = $(path[1]) ;
197	}
198
199	local link = $(directory)/$(linkName) ;
200	SYMLINK_TARGET on $(link) = $(linkTarget) ;
201	SYMLINKS_TO_INSTALL on $(directory) += $(link) ;
202}
203
204rule AddDriversToContainer container : relativeDirectoryTokens : targets
205{
206	# AddDriversToContainer <container> : <relative directory> : <targets> ;
207	#
208	local directoryTokens = beos system add-ons kernel drivers dev
209		$(relativeDirectoryTokens) ;
210
211	AddFilesToContainer $(container) : beos system add-ons kernel drivers bin
212		: $(targets) ;
213
214	# If the image shall only be updated, we don't add any symlinks.
215	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ] {
216		return ;
217	}
218
219	# get the relative symlink path prefix
220	local linkPrefix = ;
221	for i in $(relativeDirectoryTokens) {
222		linkPrefix += .. ;
223	}
224	linkPrefix += .. bin ;
225
226	# add the symlinks
227	local name ;
228	for name in $(targets:BS) {
229		AddSymlinkToContainer $(container) : $(directoryTokens)
230			: [ FDirName $(linkPrefix) $(name) ] : $(name) ;
231	}
232}
233
234rule AddDriverRegistrationToContainer container : relativeDirectoryTokens
235	: target : links
236{
237	# AddDriverRegistrationToContainer <container> : <directory>
238	#	: <link target> : <link names> ] ;
239	#
240	local directoryTokens = beos system add-ons kernel registration
241		$(relativeDirectoryTokens) ;
242
243	# get the relative symlink path prefix
244	local linkPrefix = ;
245	for i in $(relativeDirectoryTokens) {
246		linkPrefix += .. ;
247	}
248	linkPrefix += .. drivers bin ;
249
250	# add the symlink
251	AddSymlinkToContainer $(container) : $(directoryTokens)
252		: [ FDirName $(linkPrefix) $(target:BS) ] : $(links) ;
253}
254
255rule AddBootModuleSymlinksToContainer container : targets
256{
257	# AddBootModuleSymlinksToContainer <container> : <targets> ;
258	#
259
260	# If the image shall only be updated, we don't add any symlinks.
261	if [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ] {
262		return ;
263	}
264
265	# add the symlinks
266	local installTargetsVar
267		= [ on $(container) return $(HAIKU_INSTALL_TARGETS_VAR) ] ;
268	local target ;
269	for target in $(targets) {
270		# Symlink to the first place where the target has been installed.
271		local destTarget = [ on $(target) return $($(installTargetsVar)[1]) ] ;
272		local installDir = [ on $(destTarget) return $(INSTALL_DIR) ] ;
273
274		if ! $(installDir) {
275			Echo "ERROR: AddBootModuleSymlinksToContainer: Can't create a "
276				"symlink to target" \"$(target)"\"." ;
277			Exit "ERROR: Add*ToContainer has not been invoked for it yet." ;
278		}
279
280		local name = $(target:BS) ;
281		local linkTarget = [ FDirName /boot $(installDir:G=) $(name) ] ; 
282
283		AddSymlinkToContainer $(container) : beos system add-ons kernel boot
284			: $(linkTarget) : $(name) ;
285	}
286}
287
288
289rule CreateContainerMakeDirectoriesScript container : script
290{
291	MakeLocate $(script) : $(HAIKU_OUTPUT_DIR) ;
292	Always $(script) ;
293
294	local initScript = [ InitScript $(script) ] ;
295
296	local scriptBody
297		= [ FSameTargetWithPrependedGrist $(script) : script-body ] ;
298	LOCATE on $(scriptBody) = [ on $(script) return $(LOCATE) ] ;
299	Depends $(scriptBody) : $(initScript) ;
300	Depends $(script) : $(scriptBody) ;
301	
302	local dirsToCreate ;
303	local dir ;
304	for dir in [ on $(container) return $(HAIKU_INSTALL_DIRECTORIES) ] {
305		if ! [ on $(dir) return $(DONT_CREATE) ] {
306			dirsToCreate += $(dir) ;
307		}
308	}
309
310	Depends $(scriptBody) : $(dirsToCreate) ;
311	# If the image shall only be updated, we don't create directories.
312	if $(dirsToCreate)
313		&& ! [ on $(container) return $(HAIKU_CONTAINER_UPDATE_ONLY) ] {
314		CreateContainerMakeDirectoriesScript1 $(scriptBody) : $(dirsToCreate) ;
315	}
316}
317
318actions piecemeal CreateContainerMakeDirectoriesScript1
319{
320	echo \$mkdir -p "\"\${tPrefix}$(2:G=)\"" >> $(1)
321}
322
323rule CreateContainerCopyFilesScript container : script
324{
325	MakeLocate $(script) : $(HAIKU_OUTPUT_DIR) ;
326	Always $(script) ;
327
328	local initScript = [ InitScript $(script) ] ;
329
330	local scriptBody
331		= [ FSameTargetWithPrependedGrist $(script) : script-body ] ;
332	LOCATE on $(scriptBody) = [ on $(script) return $(LOCATE) ] ;
333	Depends $(scriptBody) : $(initScript) ;
334	Depends $(script) : $(scriptBody) ;
335
336	local dir ;
337	for dir in [ on $(container) return $(HAIKU_INSTALL_DIRECTORIES) ] {
338		# filter the targets that shall be renamed; they have to be copied
339		# individually
340		local destTargets = [ on $(dir) return $(TARGETS_TO_INSTALL) ] ;
341		local remainingTargets ;
342		local destTarget ;
343		for destTarget in $(destTargets) {
344			local target = [ on $(destTarget) return $(TARGET) ] ;
345			local name = $(destTarget:BS) ;
346			if $(name) != $(target:BS) {
347				# use a unique dummy target for this file, on which we
348				# can define the TARGET_DIR variable
349				local dummyTarget = $(script)-dummy-$(dir:G=)-$(target) ;
350				NotFile $(dummyTarget) ;
351				TARGET_DIR on $(dummyTarget) = $(dir:G=) ;
352				INSTALL_TARGET_NAME on $(dummyTarget) = $(name) ;
353	
354				Depends $(dummyTarget) : $(initScript) $(target) ;
355				Depends $(script) : $(dummyTarget) ;
356
357				AppendToContainerCopyFilesScriptSingleFile $(dummyTarget)
358					: $(initScript) $(target) ;
359			} else {
360				remainingTargets += $(target) ;
361			}
362		}
363		targets = $(remainingTargets) ;
364
365		if $(targets) {
366			# use a unique dummy target for this directory, on which we
367			# can define the TARGET_DIR variable
368			local dummyTarget = $(script)-dummy-$(dir:G=) ;
369			NotFile $(dummyTarget) ;
370			TARGET_DIR on $(dummyTarget) = $(dir:G=) ;
371
372			Depends $(dummyTarget) : $(initScript) $(targets) ;
373			Depends $(script) : $(dummyTarget) ;
374
375			OUTPUT_SCRIPT on $(dummyTarget) = $(initScript) ;
376			AppendToContainerCopyFilesScript $(dummyTarget) : $(targets) ;
377		}
378	
379		local symlinks = [ on $(dir) return $(SYMLINKS_TO_INSTALL) ] ;
380		local symlink ;
381		for symlink in $(symlinks) {
382			NotFile $(symlink) ;
383
384			Depends $(script) : $(symlink) ;
385			Depends $(symlink) : $(initScript) ;
386
387			AddSymlinkToContainerCopyFilesScript $(symlink) : $(initScript) ;
388		}
389	}
390}
391
392actions piecemeal AppendToContainerCopyFilesScript bind OUTPUT_SCRIPT
393{
394	echo \$cp "\"\${sPrefix}$(2)\"" "\"\${tPrefix}$(TARGET_DIR)\"" >> $(OUTPUT_SCRIPT)
395}
396
397actions AppendToContainerCopyFilesScriptSingleFile
398{
399	echo \$cp "\"\${sPrefix}$(2[2])\"" \
400		"\"\${tPrefix}$(TARGET_DIR)/$(INSTALL_TARGET_NAME)\"" >> $(2[1])
401}
402
403actions AddSymlinkToContainerCopyFilesScript
404{
405	echo \$ln -sfn "\"$(SYMLINK_TARGET)\"" "\"\${tPrefix}$(1:G=)\"" >> $(2[1])
406}
407
408
409#pragma mark - Haiku Image rules
410
411rule SetUpdateHaikuImageOnly flag
412{
413	HAIKU_CONTAINER_UPDATE_ONLY on $(HAIKU_IMAGE_CONTAINER_NAME) = $(flag) ;
414}
415
416rule AddDirectoryToHaikuImage directoryTokens
417{
418	# AddDirectoryToHaikuImage <directoryTokens>
419
420	return [ AddDirectoryToContainer $(HAIKU_IMAGE_CONTAINER_NAME)
421		: $(directoryTokens) ] ;
422}
423
424rule AddFilesToHaikuImage directory : targets : destName
425{
426	# AddFilesToHaikuImage <directory> : <targets> [ : dest name ]
427
428	AddFilesToContainer $(HAIKU_IMAGE_CONTAINER_NAME) : $(directory)
429		: $(targets) : $(destName) ;
430}
431
432rule AddSymlinkToHaikuImage directoryTokens : linkTarget : linkName
433{
434	# AddSymlinkToHaikuImage <directory> : <link target> [ : <link name> ] ;
435
436	AddSymlinkToContainer $(HAIKU_IMAGE_CONTAINER_NAME) : $(directoryTokens)
437		: $(linkTarget) : $(linkName) ;
438}
439
440rule AddSourceDirectoryToHaikuImage dirTokens : alwaysUpdate
441{
442	# AddSourceDirectoryToHaikuImage <dirTokens> : <alwaysUpdate> ;
443
444	# If the image shall only be updated, we update sources only, if explicitely
445	# requested.
446	if ! $(HAIKU_IMAGE_UPDATE_ONLY) || $(alwaysUpdate) {
447		HAIKU_INSTALL_SOURCE_DIRS += [ FDirName $(HAIKU_TOP) $(dirTokens) ] ;
448	}
449}
450
451rule AddDriversToHaikuImage relativeDirectoryTokens : targets
452{
453	# AddDriversToHaikuImage <relative directory> : <targets> ;
454
455	AddDriversToContainer $(HAIKU_IMAGE_CONTAINER_NAME)
456		: $(relativeDirectoryTokens) : $(targets) ;
457}
458
459rule AddDriverRegistrationToHaikuImage relativeDirectoryTokens : target : links
460{
461	# AddDriverRegistrationToHaikuImage <directory> : <link target> : <link names> ] ;
462
463	AddDriverRegistrationToContainer $(HAIKU_IMAGE_CONTAINER_NAME)
464		: $(relativeDirectoryTokens) : $(target) : $(links) ;
465}
466
467rule AddBootModuleSymlinksToHaikuImage targets
468{
469	# AddBootModuleSymlinksToHaikuImage <targets> ;
470
471	AddBootModuleSymlinksToContainer $(HAIKU_IMAGE_CONTAINER_NAME)
472		: $(targets) ;
473}
474
475rule CreateHaikuImageMakeDirectoriesScript script
476{
477	CreateContainerMakeDirectoriesScript $(HAIKU_IMAGE_CONTAINER_NAME)
478		: $(script) ;
479}
480
481rule CreateHaikuImageCopyFilesScript script
482{
483	CreateContainerCopyFilesScript $(HAIKU_IMAGE_CONTAINER_NAME) : $(script) ;
484}
485
486rule BuildHaikuImage haikuImage : scripts : isImage
487{
488	# BuildHaikuImage <haiku image> : <scripts> : <is image> ;
489
490	if $(isImage) = 1 || $(isImage) = true {
491		IS_IMAGE on $(haikuImage) = 1 ;
492	} else {
493		IS_IMAGE on $(haikuImage) = "" ;
494	}
495
496	local mainScript = build_haiku_image ;
497	SEARCH on $(mainScript) = [ FDirName $(HAIKU_TOP) build scripts ] ;
498
499	Depends $(haikuImage) : $(mainScript) $(scripts) ;
500	BuildHaikuImage1 $(haikuImage) : $(mainScript) $(scripts) ;
501}
502
503actions BuildHaikuImage1
504{
505	export isImage="$(IS_IMAGE)"
506	$(2[1]) $(2[2-])
507}
508
509rule BuildVMWareImage vmwareImage : plainImage : imageSize
510{
511	# BuildVMWareImage <vmware image> : <plain image> : <image size in MB>
512
513	IMAGE_SIZE on $(vmwareImage) = $(imageSize) ;
514
515	Depends $(vmwareImage) : <build>vmdkheader $(plainImage) ;
516	BuildVMWareImage1 $(vmwareImage) : <build>vmdkheader $(plainImage) ;
517}
518
519actions BuildVMWareImage1
520{
521	rm -f $(1)
522	$(2[1]) -h 64k -i$(IMAGE_SIZE)M $(1) &&
523	cat $(2[2]) >> $(1)
524}
525
526
527#pragma mark - Network Boot Archive rules
528
529rule AddDirectoryToNetBootArchive directoryTokens
530{
531	# AddDirectoryToNetBootArchive <directoryTokens>
532
533	return [ AddDirectoryToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
534		: $(directoryTokens) ] ;
535}
536
537rule AddFilesToNetBootArchive directory : targets : destName
538{
539	# AddFilesToNetBootArchive <directory> : <targets> [ : dest name ]
540
541	AddFilesToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME) : $(directory)
542		: $(targets) : $(destName) ;
543}
544
545rule AddSymlinkToNetBootArchive directoryTokens : linkTarget : linkName
546{
547	# AddSymlinkToNetBootArchive <directory> : <link target> [ : <link name> ] ;
548
549	AddSymlinkToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
550		: $(directoryTokens) : $(linkTarget) : $(linkName) ;
551}
552
553rule AddDriversToNetBootArchive relativeDirectoryTokens : targets
554{
555	# AddDriversToNetBootArchive <relative directory> : <targets> ;
556
557	AddDriversToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
558		: $(relativeDirectoryTokens) : $(targets) ;
559}
560
561rule AddDriverRegistrationToNetBootArchive relativeDirectoryTokens : target
562	: links
563{
564	# AddDriverRegistrationToNetBootArchive <directory> : <link target>
565	#	: <link names> ] ;
566
567	AddDriverRegistrationToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
568		: $(relativeDirectoryTokens) : $(target) : $(links) ;
569}
570
571rule AddBootModuleSymlinksToNetBootArchive targets
572{
573	# AddBootModuleSymlinksToNetBootArchive <targets> ;
574
575	AddBootModuleSymlinksToContainer $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
576		: $(targets) ;
577}
578
579rule CreateNetBootArchiveMakeDirectoriesScript script
580{
581	CreateContainerMakeDirectoriesScript
582		$(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME) : $(script) ;
583}
584
585rule CreateNetBootArchiveCopyFilesScript script
586{
587	CreateContainerCopyFilesScript $(HAIKU_NET_BOOT_ARCHIVE_CONTAINER_NAME)
588		: $(script) ;
589}
590
591rule BuildNetBootArchive archive : scripts
592{
593	# BuildHNetBootArchive <archive> : <scripts>  ;
594
595	local mainScript = build_tgz_archive ;
596	SEARCH on $(mainScript) = [ FDirName $(HAIKU_TOP) build scripts ] ;
597
598	Depends $(archive) : $(mainScript) $(scripts) ;
599	BuildNetBootArchive1 $(archive) : $(mainScript) $(scripts) ;
600}
601
602actions BuildNetBootArchive1
603{
604	$(2[1]) $(1) $(2[2-])
605}
606