xref: /haiku/build/jam/MiscRules (revision be012e21222c4d8d70082d12353acb163dc60ba8)
1
2rule SetupObjectsDir
3{
4	# SetupObjectsDir
5	#
6	# Internal rule used to set up the *{LOCATE,SEARCH}*_{TARGET,SOURCE}
7	# variables for the current directory.
8
9	local relPath = [ FDirName $(SUBDIR_TOKENS[2-]) ] ;
10	if $(relPath) = . {
11		relPath = ;
12	}
13
14	COMMON_PLATFORM_LOCATE_TARGET
15		= [ FDirName $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) $(relPath) ] ;
16	HOST_COMMON_ARCH_LOCATE_TARGET
17		= [ FDirName $(HOST_COMMON_ARCH_OBJECT_DIR) $(relPath) ] ;
18	TARGET_COMMON_ARCH_LOCATE_TARGET
19		= [ FDirName $(TARGET_COMMON_ARCH_OBJECT_DIR) $(relPath) ] ;
20
21	local var ;
22	for var in COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) {
23		HOST_$(var)_LOCATE_TARGET
24			= [ FDirName $(HOST_$(var)_OBJECT_DIR) $(relPath) ] ;
25		TARGET_$(var)_LOCATE_TARGET
26			= [ FDirName $(TARGET_$(var)_OBJECT_DIR_$(TARGET_PACKAGING_ARCH))
27				$(relPath) ] ;
28	}
29
30	LOCATE_TARGET = $(COMMON_PLATFORM_LOCATE_TARGET) ;
31	LOCATE_SOURCE = $(LOCATE_TARGET) ;
32	SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE)
33		$(HOST_COMMON_DEBUG_LOCATE_TARGET)		# Also add the standard output
34		$(TARGET_COMMON_DEBUG_LOCATE_TARGET)	# dirs for generated sources.
35	;
36}
37
38rule SetupFeatureObjectsDir feature
39{
40	# SetupFeatureObjectsDir <feature>
41	#
42	# Updates the *{LOCATE,SEARCH}*_{TARGET,SOURCE} variables for the current
43	# directory appending a <feature> to each of them. Note that it resets
44	# the LOCATE_TARGET, LOCATE_SOURCE, SEARCH_SOURCE (!) variables. I.e. it
45	# should be invoked before customizing these variables further (e.g. like
46	# adding additional source directories to SEARCH_SOURCE).
47
48	COMMON_PLATFORM_LOCATE_TARGET
49		= [ FDirName $(COMMON_PLATFORM_LOCATE_TARGET) $(feature) ] ;
50
51	local var ;
52	for var in COMMON_ARCH COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) {
53		HOST_$(var)_LOCATE_TARGET
54			= [ FDirName $(HOST_$(var)_LOCATE_TARGET) $(feature) ] ;
55		TARGET_$(var)_LOCATE_TARGET
56			= [ FDirName $(TARGET_$(var)_LOCATE_TARGET) $(feature) ] ;
57	}
58
59	LOCATE_TARGET = [ FDirName $(LOCATE_TARGET) $(feature) ] ;
60	LOCATE_SOURCE = $(LOCATE_TARGET) ;
61	SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE)
62		$(HOST_COMMON_DEBUG_LOCATE_TARGET)		# Also add the standard output
63		$(TARGET_COMMON_DEBUG_LOCATE_TARGET)	# dirs for generated sources.
64	;
65}
66
67rule SubIncludeGPL
68{
69	# SubInclude rule that can be used to conditionally include GPL licensed
70	# add-ons
71	if $(HAIKU_INCLUDE_GPL_ADDONS) = 1 {
72		SubInclude $(1) ;
73	}
74}
75
76
77# pragma mark - MakeLocate variants
78
79
80rule MakeLocateCommonPlatform files : subdir
81{
82	# The file is shared between all target platforms.
83	MakeLocate $(files)
84		: [ FDirName $(COMMON_PLATFORM_LOCATE_TARGET) $(subdir) ] ;
85}
86
87rule MakeLocatePlatform files : subdir
88{
89	# The file is specific for the target platform, but
90	# architecture independent. Usually the right rule for generated
91	# sources, though sometimes sources can be architecture specific.
92	local file ;
93	for file in $(files) {
94		local directory ;
95		if [ on $(file) return $(PLATFORM) ] = host {
96			directory = $(HOST_COMMON_ARCH_LOCATE_TARGET) ;
97		} else {
98			directory = $(TARGET_COMMON_ARCH_LOCATE_TARGET) ;
99		}
100		MakeLocate $(file) : [ FDirName $(directory) $(subdir) ] ;
101	}
102}
103
104rule MakeLocateArch files : subdir
105{
106	# The file is platform+architecture specific, but is debug
107	# level independent. This is usually the right rule for generated
108	# architecture specific data or source files.
109	local file ;
110	for file in $(files) {
111		local directory ;
112		if [ on $(file) return $(PLATFORM) ] = host {
113			directory = $(HOST_COMMON_DEBUG_LOCATE_TARGET) ;
114		} else {
115			directory = $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ;
116		}
117		MakeLocate $(file) : [ FDirName $(directory) $(subdir) ] ;
118	}
119}
120
121rule MakeLocateDebug files : subdir
122{
123	# The file is platform+architecture+debug level specific.
124	# That's what should be used for compiled code.
125	local file ;
126	for file in $(files) {
127		local directory ;
128		on $(file) {
129			if $(PLATFORM) = host {
130				directory = $(HOST_DEBUG_$(DEBUG)_LOCATE_TARGET) ;
131			} else {
132				directory = $(TARGET_DEBUG_$(DEBUG)_LOCATE_TARGET) ;
133			}
134		}
135		MakeLocate $(file) : [ FDirName $(directory) $(subdir) ] ;
136	}
137}
138
139
140# pragma mark - Deferred SubIncludes
141
142
143# The variable used to collect the deferred SubIncludes.
144HAIKU_DEFERRED_SUB_INCLUDES = ;
145
146rule DeferredSubInclude params : jamfile : scope
147{
148	# DeferredSubInclude <subdir tokens> [ : <jamfile name>  [ : <scope> ] ] ;
149	#
150	# Takes the same directory tokens parameter as SubInclude plus an optional
151	# alternative Jamfile name. The the subdirectory referred to by
152	# <subdir tokens> will be included when ExecuteDeferredSubIncludes is
153	# invoked, i.e. at the end of the root Jamfile. The <jamfile name> parameter
154	# specifies the name of the Jamfile to include. By default it is "Jamfile".
155	# The <scope> parameter can be "global" (default) or "local", specifying
156	# whether the alternative Jamfile name shall also be used for subdirectories.
157
158	HAIKU_DEFERRED_SUB_INCLUDES += "/" $(params) ;
159	if $(jamfile) {
160		SetConfigVar JAMFILE : $(params) : $(jamfile) : $(scope) ;
161	}
162}
163
164rule ExecuteDeferredSubIncludes
165{
166	# ExecuteDeferredSubIncludes ;
167	#
168	# Performs the deferred SubIncludes scheduled by DeferredSubInclude.
169
170	local tokensList = $(HAIKU_DEFERRED_SUB_INCLUDES) ;
171	while $(tokensList) {
172		# chop off leading "/"
173		tokensList = $(tokensList[2-]) ;
174
175		# get the tokens for the next include
176		local tokens ;
177		while $(tokensList) && $(tokensList[1]) != "/" {
178			tokens += $(tokensList[1]) ;
179			tokensList = $(tokensList[2-]) ;
180		}
181
182		# perform the include
183		if $(tokens) {
184			SubInclude $(tokens) ;
185		}
186	}
187}
188
189rule HaikuSubInclude tokens
190{
191	# HaikuSubInclude <tokens> ;
192	#
193	# Current subdir relative SubInclude.
194	# <tokens> - subdir tokens specifying the subdirectory to be include
195	#            (relative to the current subdir)
196
197	if $(tokens) {
198		SubInclude HAIKU_TOP $(SUBDIR_TOKENS) $(tokens) ;
199	}
200}
201
202
203# pragma mark - Unique IDs/targets
204
205
206# private to NextID; incremented with each NextID invocation
207HAIKU_NEXT_ID = 0 ;
208
209rule NextID
210{
211	# NextID ;
212
213	local result = $(HAIKU_NEXT_ID:J=) ;
214	HAIKU_NEXT_ID = [ AddNumAbs $(HAIKU_NEXT_ID) : 1 ] ;
215	return $(result) ;
216}
217
218rule NewUniqueTarget basename
219{
220	# NewUniqueTarget [ basename ] ;
221
222	local id = [ NextID ] ;
223	return $(basename[1]:E=_target:G=unique!target)_$(id) ;
224}
225
226
227# pragma mark - RunCommandLine
228
229
230rule RunCommandLine commandLine
231{
232	# RunCommandLine <commandLine>
233	#
234	# Creates a pseudo target that, when made by jam, causes the supplied shell
235	# command line to be executed. Elements of <commandLine> with the prefix ":"
236	# are replaced by the rule. After stripping the prefix such a string specifies
237	# a build system target and the finally executed command line will contain
238	# a path to the target instead.
239	# The pseudo target will depend on all targets thus identified. Each
240	# invocation of this rule creates a different pseudo target, which is
241	# returned to the caller.
242
243	# collect the targets in the command line and replace them by $targetX*
244	# variables
245	local substitutedCommandLine ;
246	local targets ;
247
248	local targetVarName = target ;
249	local i ;
250	for i in $(commandLine)  {
251		# targets are marked by the ":" prefix
252		local target = [ Match ^:(.*) : $(i) ] ;
253		if $(target) {
254			targets += $(target) ;
255			targetVarName = $(targetVarName)X ;
256			i = "$"$(targetVarName) ;
257		}
258
259		substitutedCommandLine += $(i) ;
260	}
261
262	# define the "run" target
263	local run = [ NewUniqueTarget run ] ;
264	COMMAND_LINE on $(run) = $(substitutedCommandLine) ;
265	NotFile $(run) ;
266	Always $(run) ;
267	Depends $(run) : $(targets) ;
268	RunCommandLine1 $(run) : $(targets) ;
269
270	return $(run) ;
271}
272
273actions RunCommandLine1 {
274	target=target;
275	for t in $(2) ; do
276		target=${target}X
277		eval "${target}=${t}"
278	done
279	$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
280	"$(COMMAND_LINE)"
281}
282
283
284#pragma mark - DefineBuildProfile
285
286
287rule DefineBuildProfile name : type : path {
288	# DefineBuildProfile <name> : <type> [ : <path> ]
289	#
290	# Makes a build profile known. Build profiles can be used to define
291	# different sets of settings for Haiku images/installations. For each
292	# profile the default actions "build", "update", and "mount" (the latter
293	# only for disks or image types) will be available (i.e. can be specified
294	# as second parameter on the jam command line). They will build an image
295	# or installation, update only given targets, respectively just mount the
296	# image or disk using the bfs_shell.
297	#
298	# <name> - The name of the build profile.
299	# <type> - The type of the build profile. Must be one of "image" (plain
300	#          disk image), "anyboot-image" (custom disk image that can be
301	#          written to CD or disk device), "cd-image" (ISO CD image),
302	#          "vmware-image" (VMware disk image), "disk" (actual partition
303	#          or hard disk device), "install" (installation in a directory),
304	#          or "custom" (user-defined).
305	# <path> - The path associated with the profile. Depending on the profile
306	#          type, this is the path to the disk image/VMware image, hard
307	#          disk/partition device, or the installation directory. If the
308	#          parameter is omitted, the value of the HAIKU[_VMWARE]_IMAGE_NAME,
309	#          HAIKU_IMAGE_DIR, respectively HAIKU_INSTALL_DIR or their default
310	#          values will be used instead.
311
312	if [ on $(name) return $(HAIKU_BUILD_PROFILE_SPECIFIED) ] {
313		Exit "ERROR: Build profile \"$(name)\" defined twice!" ;
314	}
315	HAIKU_BUILD_PROFILE_SPECIFIED on $(name) = 1 ;
316
317	if ! $(HAIKU_BUILD_PROFILE) || $(HAIKU_BUILD_PROFILE) != $(name) {
318		return ;
319	}
320
321	HAIKU_BUILD_PROFILE_DEFINED = 1 ;
322
323	# split path into directory path and name
324	local targetDir = $(path:D) ;
325	local targetName = $(path:BS) ;
326
327	# Jam's path splitting produces an empty string, if a component doesn't
328	# exist. That's a little unhandy for checks.
329	if $(targetDir) = "" {
330		targetDir = ;
331	}
332	if $(targetName) = "" {
333		targetName = ;
334	}
335
336	targetDir ?= $(HAIKU_IMAGE_DIR) ;
337	targetDir ?= $(HAIKU_DEFAULT_IMAGE_DIR) ;
338
339	# "disk" is "image" with HAIKU_DONT_CLEAR_IMAGE
340	if $(type) = "disk" {
341		type = "image" ;
342		HAIKU_DONT_CLEAR_IMAGE = 1 ;
343	}
344
345	local buildTarget ;
346	local startOffset ;
347
348	switch $(type) {
349		case "anyboot-image" : {
350			targetName ?= $(HAIKU_ANYBOOT_NAME) ;
351			targetName ?= $(HAIKU_DEFAULT_ANYBOOT_NAME) ;
352			HAIKU_ANYBOOT_DIR = $(targetDir) ;
353			HAIKU_ANYBOOT_NAME = $(targetName) ;
354			buildTarget = haiku-anyboot-image ;
355		}
356
357		case "cd-image" : {
358			targetName ?= $(HAIKU_CD_NAME) ;
359			targetName ?= $(HAIKU_DEFAULT_CD_NAME) ;
360			HAIKU_CD_DIR = $(targetDir) ;
361			HAIKU_CD_NAME = $(targetName) ;
362			buildTarget = haiku-cd ;
363		}
364
365		case "image" : {
366			targetName ?= $(HAIKU_IMAGE_NAME) ;
367			targetName ?= $(HAIKU_DEFAULT_IMAGE_NAME) ;
368			HAIKU_IMAGE_DIR = $(targetDir) ;
369			HAIKU_IMAGE_NAME = $(targetName) ;
370			buildTarget = haiku-image ;
371		}
372
373		case "vmware-image" : {
374			targetName ?= $(HAIKU_VMWARE_IMAGE_NAME) ;
375			targetName ?= $(HAIKU_DEFAULT_VMWARE_IMAGE_NAME) ;
376			HAIKU_IMAGE_DIR = $(targetDir) ;
377			HAIKU_VMWARE_IMAGE_NAME = $(targetName) ;
378			buildTarget = haiku-vmware-image ;
379			startOffset = --start-offset 65536 ;
380		}
381
382		case "install" : {
383			path ?= $(HAIKU_INSTALL_DIR) ;
384			path ?= $(HAIKU_DEFAULT_INSTALL_DIR) ;
385			HAIKU_INSTALL_DIR = $(path) ;
386			buildTarget = install-haiku ;
387		}
388
389		case "custom" : {
390			# user-defined -- don't do anything
391			return 1 ;
392		}
393
394		case * : {
395			Exit "Unsupported build profile type: " $(type) ;
396		}
397	}
398
399	switch $(HAIKU_BUILD_PROFILE_ACTION) {
400		case "build" : {
401			# If parameters are specified, only build those targets (under the
402			# influence of the build profile).
403			if $(HAIKU_BUILD_PROFILE_PARAMETERS) {
404				JAM_TARGETS = $(HAIKU_BUILD_PROFILE_PARAMETERS) ;
405			} else {
406				JAM_TARGETS = $(buildTarget) ;
407			}
408		}
409
410		case "update" : {
411			JAM_TARGETS = $(buildTarget) ;
412			SetUpdateHaikuImageOnly 1 ;
413			HAIKU_PACKAGES_UPDATE_ONLY = 1 ;
414			HAIKU_INCLUDE_IN_IMAGE on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ;
415			HAIKU_INCLUDE_IN_PACKAGES on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ;
416		}
417
418		case "update-all" : {
419			JAM_TARGETS = $(buildTarget) ;
420			SetUpdateHaikuImageOnly 1 ;
421			HAIKU_INCLUDE_IN_IMAGE = 1 ;
422			HAIKU_UPDATE_ALL_PACKAGES = 1 ;
423		}
424
425		case "update-packages" : {
426			JAM_TARGETS = $(buildTarget) ;
427			SetUpdateHaikuImageOnly 1 ;
428			HAIKU_UPDATE_ALL_PACKAGES = 1 ;
429		}
430
431		case "build-package-list" : {
432			HAIKU_IMAGE_LIST_PACKAGES_TARGET
433				= $(HAIKU_BUILD_PROFILE_PARAMETERS[1]) ;
434			HAIKU_IMAGE_ADDITIONAL_PACKAGES
435				= $(HAIKU_BUILD_PROFILE_PARAMETERS[2-]) ;
436			JAM_TARGETS = $(HAIKU_IMAGE_LIST_PACKAGES_TARGET) ;
437		}
438
439		case "mount" : {
440			if $(type) in "install" "cd-image" {
441				Exit "Build action \"mount\" not supported for profile type"
442					"\"$(type)\"." ;
443			}
444
445			local commandLine = :<build>bfs_shell $(startOffset)
446				\"$(targetName:D=$(targetDir))\" ;
447			JAM_TARGETS = [ RunCommandLine $(commandLine) ] ;
448		}
449	}
450
451	return 1 ;
452}
453