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