xref: /haiku/build/jam/MiscRules (revision 2222d0559df303a9846a2fad53741f8b20b14d7c)
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), "cd-image" (ISO CD
283	#          image), "install" (installation in a directory), or "custom"
284	#          (user-defined).
285	# <path> - The path associated with the profile. Depending on the profile
286	#          type, this is the path to the disk image/VMware image, hard
287	#          disk/partition device, or the installation directory. If the
288	#          parameter is omitted, the value of the HAIKU[_VMWARE]_IMAGE_NAME,
289	#          HAIKU_IMAGE_DIR, respectively HAIKU_INSTALL_DIR or their default
290	#          values will be used instead.
291
292	if [ on $(name) return $(HAIKU_BUILD_PROFILE_SPECIFIED) ] {
293		Exit "ERROR: Build profile \"$(name)\" defined twice!" ;
294	}
295	HAIKU_BUILD_PROFILE_SPECIFIED on $(name) = 1 ;
296
297	if ! $(HAIKU_BUILD_PROFILE) || $(HAIKU_BUILD_PROFILE) != $(name) {
298		return ;
299	}
300
301	HAIKU_BUILD_PROFILE_DEFINED = 1 ;
302
303	# split path into directory path and name
304	local targetDir = $(path:D) ;
305	local targetName = $(path:BS) ;
306
307	# Jam's path splitting produces an empty string, if a component doesn't
308	# exist. That's a little unhandy for checks.
309	if $(targetDir) = "" {
310		targetDir = ;
311	}
312	if $(targetName) = "" {
313		targetName = ;
314	}
315
316	targetDir ?= $(HAIKU_IMAGE_DIR) ;
317	targetDir ?= $(HAIKU_DEFAULT_IMAGE_DIR) ;
318
319	# "disk" is "image" with HAIKU_DONT_CLEAR_IMAGE
320	if $(type) = "disk" {
321		type = "image" ;
322		HAIKU_DONT_CLEAR_IMAGE = 1 ;
323	}
324
325	local buildTarget ;
326	local startOffset ;
327
328	switch $(type) {
329		case "cd-image" : {
330			targetName ?= $(HAIKU_CD_NAME) ;
331			targetName ?= $(HAIKU_DEFAULT_CD_NAME) ;
332			HAIKU_CD_DIR = $(targetDir) ;
333			HAIKU_CD_NAME = $(targetName) ;
334			buildTarget = haiku-cd ;
335		}
336
337		case "image" : {
338			targetName ?= $(HAIKU_IMAGE_NAME) ;
339			targetName ?= $(HAIKU_DEFAULT_IMAGE_NAME) ;
340			HAIKU_IMAGE_DIR = $(targetDir) ;
341			HAIKU_IMAGE_NAME = $(targetName) ;
342			buildTarget = haiku-image ;
343		}
344
345		case "vmware-image" : {
346			targetName ?= $(HAIKU_VMWARE_IMAGE_NAME) ;
347			targetName ?= $(HAIKU_DEFAULT_VMWARE_IMAGE_NAME) ;
348			HAIKU_IMAGE_DIR = $(targetDir) ;
349			HAIKU_VMWARE_IMAGE_NAME = $(targetName) ;
350			buildTarget = haiku-vmware-image ;
351			startOffset = --start-offset 65536 ;
352		}
353
354		case "install" : {
355			path ?= $(HAIKU_INSTALL_DIR) ;
356			path ?= $(HAIKU_DEFAULT_INSTALL_DIR) ;
357			HAIKU_INSTALL_DIR = $(path) ;
358			buildTarget = install-haiku ;
359		}
360
361		case "custom" : {
362			# user-defined -- don't do anything
363			return 1 ;
364		}
365
366		case * : {
367			Exit "Unsupported build profile type: " $(type) ;
368		}
369	}
370
371	switch $(HAIKU_BUILD_PROFILE_ACTION) {
372		case "build" : {
373			JAM_TARGETS = $(buildTarget) ;
374		}
375
376		case "update" : {
377			JAM_TARGETS = $(buildTarget) ;
378			SetUpdateHaikuImageOnly 1 ;
379			HAIKU_INCLUDE_IN_IMAGE on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ;
380		}
381
382		case "update-all" : {
383			JAM_TARGETS = $(buildTarget) ;
384			SetUpdateHaikuImageOnly 1 ;
385			HAIKU_INCLUDE_IN_IMAGE = 1 ;
386		}
387
388		case "mount" : {
389			if $(type) in "install" "cd-image" {
390				Exit "Build action \"mount\" not supported for profile type"
391					"\"$(type)\"." ;
392			}
393
394			local commandLine = :<build>bfs_shell $(startOffset)
395				\"$(targetName:D=$(targetDir))\" ;
396			JAM_TARGETS = [ RunCommandLine $(commandLine) ] ;
397		}
398	}
399
400	return 1 ;
401}
402