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