xref: /haiku/Jamrules (revision 16df67022abf8bb2dc970e56218937fb5cc6c092)
1# Vanilla Jam compatibility
2if ! $(INVOCATION_SUBDIR_SET) {
3
4	rule FIsPrefix
5	{
6		# FIsPrefix <a> : <b> ;
7		# Returns true, if list <a> is a prefix (a proper one or equal) of
8		# list <b>, an empty list otherwise.
9		local a = $(1) ;
10		local b = $(2) ;
11		while $(a) && $(a[1]) = $(b[1]) {
12			a = $(a[2-]) ;
13			b = $(b[2-]) ;
14		}
15
16		if $(a) {
17			return ;
18		} else {
19			return true ;
20		}
21	}
22
23	rule LocalClean { Clean $(1) : $(2) ; }
24
25	rule LocalDepends { Depends $(1) : $(2) ; }
26
27} # vanilla Jam compatibility
28
29# The directory for build system specific files
30OBOS_BUILD_DIR = [ FDirName $(OBOS_TOP) build ] ;
31
32# Cache files for header scanning and jamfile caching
33HCACHEFILE = header_cache ;
34JCACHEFILE = jamfile_cache ;
35LOCATE on $(HCACHEFILE) $(JCACHEFILE) = $(OBOS_BUILD_DIR) ;
36
37# Include BuildConfig/Timezones/libgccObjects
38{
39	local buildConfig = [ GLOB $(OBOS_BUILD_DIR) : BuildConfig ] ;
40	local timezones = [ GLOB $(OBOS_BUILD_DIR) : Timezones ] ;
41	local libgccObjects = [ GLOB $(OBOS_BUILD_DIR) : libgccObjects ] ;
42
43	if ! $(buildConfig) {
44		ECHO "No `BuildConfig' found in $(OBOS_BUILD_DIR)!" ;
45		EXIT "Run ./configure in the source tree's root directory first!" ;
46	}
47	if ! ( $(timezones) && $(libgccObjects) ) {
48		ECHO "No `Timezones' or `libgccObjects' found in $(OBOS_BUILD_DIR)!" ;
49		EXIT "Please run ./configure in the source tree's root directory again!" ;
50	}
51
52	LOCATE on BuildConfig = $(OBOS_BUILD_DIR) ;
53	LOCATE on Timezones = $(OBOS_BUILD_DIR) ;
54	LOCATE on libgccObjects = $(OBOS_BUILD_DIR) ;
55
56	include BuildConfig ;
57	include Timezones ;
58	include libgccObjects ;
59}
60
61# analyze GCC version
62if ! $(GCC_RAW_VERSION) {
63	ECHO "Variable GCC_RAW_VERSION not set. Please run ./configure or" ;
64	EXIT "specify it manually." ;
65}
66GCC_VERSION = ;
67{
68	# split the raw version string at `.' and `-' characters
69	local version = $(GCC_RAW_VERSION) ;
70	while $(version) {
71		local split = [ Match "([^.-]*)[.-](.*)" : $(version) ] ;
72		if $(split) {
73			GCC_VERSION += $(split[1]) ;
74			version = $(split[2]) ;
75		} else {
76			GCC_VERSION += $(version) ;
77			version = ;
78		}
79	}
80}
81
82# Save the platform default headers.
83PLATFORM_DEFAULT_HEADERS = $(HDRS) ;
84
85# Add some grist to the libgcc objects
86LIBGCC_OBJECTS = $(LIBGCC_OBJECTS:G=libgcc) ;
87
88# We do not include any local BeOS system headers by default
89CCFLAGS += -nostdinc ;
90C++FLAGS += -nostdinc ;
91
92# Allow compiling unit tests on Zeta. Instead of fixing the PostMessage()
93# issues, they deprecated that nice function. This will enable it again:
94C++FLAGS += -D_ZETA_USING_DEPRECATED_API_=1 ;
95
96if ! $(TARGET_PLATFORM) {
97	ECHO "Variable TARGET_PLATFORM not set. Please run ./configure or" ;
98	EXIT "specify it manually." ;
99}
100switch $(TARGET_PLATFORM)
101{
102	case r5 :
103	{
104		# "everything" is r5 compatible
105	}
106	case bone :
107	{
108		BONE_COMPATIBLE = true ;
109	}
110	case dano :
111	{
112		BONE_COMPATIBLE = true ;
113		DANO_COMPATIBLE = true ;
114	}
115	case haiku :
116	{
117		BONE_COMPATIBLE = true ;
118		DANO_COMPATIBLE = true ;
119		HAIKU_COMPATIBLE = true ;
120		DEFINES += __HAIKU__ ;
121	}
122}
123if $(BONE_COMPATIBLE) {
124	# FIXME: we don't have our own "libbnetapi.so" yet :-(
125	# NETWORK_LIBS = libsocket.so libbind.so libbnetapi.so ;
126	NETWORK_LIBS = libsocket.so libbind.so bnetapi ;
127	SELECT_UNAME_ETC_LIB = libroot.so ;
128} else {
129	NETWORK_LIBS = libnet.so libnetapi.so ;
130	SELECT_UNAME_ETC_LIB = libnet.so ;
131}
132
133# Determine if we're building on PPC or x86
134# Determine mimetype of executable
135# Cross compiling can come later
136
137TARGET_CPU ?= $(OSPLAT:L) ;
138OBOS_VERSION ?= R1 ;
139
140switch $(TARGET_CPU) {
141	case ppc :
142	{
143		if $(METROWERKS) {
144			# at least parts of OpenBeOS still can be compiled with
145			# the Metrowerks compiler on BeOS/PPC
146			OBOS_TARGET_TYPE ?= "application/x-be-executable" ;
147		} else {
148			OBOS_TARGET_TYPE ?= "application/x-vnd.Be-elfexecutable" ;
149		}
150		DEFINES += __POWERPC__ ARCH_ppc ;
151		OBOS_BOOT_PLATFORM = openfirmware ;
152	}
153	case x86 :
154	{
155		# nothing special to do here...
156		DEFINES += __INTEL__ ARCH_x86 ;
157		OBOS_BOOT_PLATFORM = bios_ia32 ;
158	}
159	case * :
160		Exit "Currently unsupported build platform:" $(TARGET_CPU) ;
161}
162
163# set target specific variables
164{
165	#Echo "Building for" $(TARGET_CPU) ;
166
167	OBOS_TARGET ?= $(TARGET_CPU).$(OBOS_VERSION) ;
168	OBOS_TARGET_TYPE ?= "application/x-vnd.Be-elfexecutable" ;
169	OBOS_ARCH ?= $(TARGET_CPU) ;
170	OBOS_TARGET_DEFINE ?= "ARCH_"$(TARGET_CPU) ;
171}
172
173# Disable warnings only if WARNINGS is set to 0
174# Should be enabled by default later
175#
176WARNINGS ?= 1 ;
177if $(WARNINGS) = 1 {
178	# For an explanation of the different warning options, see:
179	# http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_2.html
180	# to get even more warnings, add:
181	# -Wwrite-strings  	(doesn't work well with some Be headers)
182	# -Wundef			(dito)
183	# -Wconversion		(gets you many warnings about implicit conversions)
184	# -W				(gets you even more warnigs)
185	CCFLAGS += -Wall -Wno-multichar -Wmissing-prototypes ;
186	CCFLAGS += -Wpointer-arith -Wcast-align -Wsign-compare ;
187	C++FLAGS += -Wall -Wno-multichar -Wmissing-prototypes -Wno-ctor-dtor-privacy -Woverloaded-virtual ;
188	C++FLAGS += -Wpointer-arith -Wcast-align -Wsign-compare ;
189} else {
190	CCFLAGS += -Wno-multichar ;
191	C++FLAGS += -Wno-multichar ;
192}
193
194# standard kernel C/C++ flags
195KERNEL_CCFLAGS ?= -Wall -Wno-multichar -Wmissing-prototypes -finline -nostdinc ;
196KERNEL_CCFLAGS += -fno-builtin -D$(OBOS_TARGET_DEFINE) -D__HAIKU__ ;
197KERNEL_CCFLAGS += -DBOCHS_DEBUG_HACK=$(BOCHS_DEBUG_HACK) -D_KERNEL_MODE ;
198KERNEL_C++FLAGS ?= -Wall -Wno-multichar -Wmissing-prototypes -finline -nostdinc ;
199KERNEL_C++FLAGS += -fno-builtin -fno-exceptions -D$(OBOS_TARGET_DEFINE) -D__HAIKU__ ;
200KERNEL_C++FLAGS += -DBOCHS_DEBUG_HACK=$(BOCHS_DEBUG_HACK) -D_KERNEL_MODE ;
201if $(GCC_VERSION[1]) >= 3 {
202	KERNEL_C++FLAGS += -fno-use-cxa-atexit ;
203}
204
205# We might later want to introduce debug levels or handle the whole issue
206# differently. For now there's only on or off.
207#
208DEBUG ?= 0 ;
209if $(DEBUG) != 0 {
210	OPTIM ?= -O0 ;
211	CCFLAGS += -g [ FDefines DEBUG=$(DEBUG) ] ;
212	C++FLAGS += -g [ FDefines DEBUG=$(DEBUG) ] ;
213	KERNEL_CCFLAGS += -g [ FDefines DEBUG=$(DEBUG) ] ;
214	KERNEL_C++FLAGS += -g [ FDefines DEBUG=$(DEBUG) ] ;
215	LINKFLAGS += -g ;
216} else {
217	OPTIM ?= -O2 ;
218}
219#
220# To disable for the tests OPTIM and DEBUG are overridden, set the environment
221# variable NO_TEST_DEBUG.
222
223# If the environment variable DEBUG_PRINTF is defined we define an equally
224# named macro to the variable value. Some components use the macro to allow
225# another function than printf() to print the debug output. The variable should
226# be set to the name of the alternative function.
227#
228if $(DEBUG_PRINTF) {
229	CCFLAGS += [ FDefines DEBUG_PRINTF=$(DEBUG_PRINTF) ] ;
230	C++FLAGS += [ FDefines DEBUG_PRINTF=$(DEBUG_PRINTF) ] ;
231}
232
233# Instructs the Library rule to not make its object files temporary.
234# This is needed as some objects are used in a static library and for an
235# executable.
236KEEPOBJS = true ;
237
238# under BeOS use copyattr instead of cp
239if $(OS) = BEOS
240{
241	CP = copyattr --data ;
242}
243
244# for builds of tools in the current environment
245if $(OS) = BEOS {
246	BUILD_LIBSTDC++ = stdc++.r4 ;
247} else {
248	BUILD_LIBSTDC++ = stdc++ ;
249}
250
251# If no OBOS_OBJECT_TARGET is not defined yet, use our default directory and
252# include our "OBOS_TARGET" as subdirectory in there (to prevent different
253# builds mixing objects from different targets).
254if ! $(OBOS_OBJECT_TARGET) {
255	OBOS_OBJECT_TARGET ?= [ FDirName $(OBOS_TOP) objects $(OBOS_TARGET) ] ;
256}
257
258# If no OBOS_DISTRO_TARGET is not defined yet, use our default directory and
259# include our "OBOS_TARGET" as subdirectory in there (to prevent different
260# builds mixing executables from different targets).
261if ! $(OBOS_DISTRO_TARGET) {
262	OBOS_DISTRO_TARGET ?= [ FDirName $(OBOS_TOP) distro $(OBOS_TARGET) ] ;
263}
264
265# Set our version number if not already set and mark it as a developer build
266if ! $(OBOS_BUILD_VERSION) {
267	OBOS_BUILD_VERSION ?= "1 0 0 a 1" ;
268	OBOS_BUILD_DESCRIPTION ?= "Developer Build" ;
269}
270
271# If OBOS_BUILD_VERSION is set, but OBOS_BUILD_DESCRIPTION isn't, mark it as
272# an unknown build.
273if ! $(OBOS_BUILD_DESCRIPTION) {
274	OBOS_BUILD_DESCRIPTION ?= "Unknown Build" ;
275}
276
277# Relative subdirs for distro dir
278OBOS_ADDON_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system add-ons ] ;
279OBOS_APPS_DIR   ?= [ FDirName $(OBOS_DISTRO_TARGET) beos apps ] ;
280OBOS_BIN_DIR    ?= [ FDirName $(OBOS_DISTRO_TARGET) beos bin ] ;
281OBOS_ETC_DIR    ?= [ FDirName $(OBOS_DISTRO_TARGET) beos etc ] ;
282OBOS_FONTS_DIR  ?= [ FDirName $(OBOS_ETC_DIR) fonts ] ;
283OBOS_KERNEL_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system ] ;
284OBOS_PREFS_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos preferences ] ;
285OBOS_SERVER_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system servers ] ;
286OBOS_SHLIB_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system lib ] ;
287OBOS_STLIB_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) develop lib
288							  $(OBOS_ARCH) ] ;
289OBOS_TEST_DIR   ?= [ FDirName $(OBOS_TOP) tests ] ;
290
291OBOS_PACKAGE_DIR ?= [ FDirName $(OBOS_TOP) packages $(OBOS_TARGET) ] ;
292OBOS_PACKAGE_OBJECT_DIR ?= [ FDirName $(OBOS_OBJECT_TARGET) packages ] ;
293
294OBOS_KERNEL_CONFIG = config.$(OBOS_ARCH).ini ;
295OBOS_KERNEL = kernel.$(OBOS_ARCH) ;
296OBOS_FLOPPY = floppy.$(OBOS_ARCH) ;
297
298rule SetupIncludes
299{
300	# XXX add "opengl" later
301	local os_includes = add-ons add-ons/file_system add-ons/graphics add-ons/input_server add-ons/screen_saver add-ons/tracker app device drivers game interface kernel media mail midi midi2 net storage support translation ;
302
303	# Overwrite any exiting content when changing HDRS. This rule may be invoked multiple times.
304
305	# Use headers directory, to allow to do things like include <posix/string.h>
306	HDRS = [ FDirName $(OBOS_TOP) headers ] ;
307
308	# Use posix headers directory
309	HDRS += [ FDirName $(OBOS_TOP) headers posix ] ;
310
311	# Use public OS header directories
312	HDRS += [ PublicHeaders $(os_includes) ] ;
313
314	# Use the root of the private headers -- not so nice, but simplifies things.
315	HDRS += [ PrivateHeaders $(DOT) ] ;
316
317	# Used as a fallback, the R5 header directories (we should remove this as soon as possible)
318	HDRS += /boot/develop/headers/posix /boot/develop/headers/cpp ;
319
320	# The platform dependent headers.
321	HDRS += $(PLATFORM_HEADERS) ;
322}
323
324rule SetupR5Includes
325{
326	# Unsets HDRS, so that the OBOS headers do not `shadow' the system headers.
327	HDRS = ;
328}
329
330rule SetupDefaultIncludes
331{
332	# Resets HDRS to the default headers for the build platform.
333	HDRS = $(PLATFORM_DEFAULT_HEADERS) ;
334}
335
336#-------------------------------------------------------------------------------
337# Things Jam needs in order to work :)
338#-------------------------------------------------------------------------------
339
340# TODO: back-ported from jam 2.5: remove when not longer needed
341rule MakeLocate
342{
343	if $(>)
344	{
345	    LOCATE on $(<) = $(>) ;
346	    Depends $(<) : $(>[1]:G=dir) ;
347	    MkDir $(>[1]:G=dir) ;
348	}
349}
350
351rule Object
352{
353	# This is basically the original Jambase 2.4 Object rule stripped by
354	# comments. Only the final switch statement has been changed to allow
355	# intermediate C++ files for Yacc and Lex.
356
357	LocalClean clean : $(<) ;
358
359	MakeLocate $(<) : $(LOCATE_TARGET) ;
360	SEARCH on $(>) = $(SEARCH_SOURCE) ;
361
362	HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ;
363
364	HDRRULE on $(>) = HdrRule ;
365	HDRSCAN on $(>) = $(HDRPATTERN) ;
366	HDRSEARCH on $(>) =
367		$(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;
368
369	HDRGRIST on $(>) = $(HDRGRIST) ;
370
371	DEFINES on $(<) += $(DEFINES) ;
372
373	# if source is not .c, generate .c with specific rule
374
375	switch $(>:S)
376	{
377	    case .asm : As $(<) : $(>) ;
378	    case .c :	Cc $(<) : $(>) ;
379	    case .C :	C++ $(<) : $(>) ;
380	    case .cc :	C++ $(<) : $(>) ;
381	    case .cpp : C++ $(<) : $(>) ;
382	    case .f :	Fortran $(<) : $(>) ;
383	    case .l :	if [ on $(2) return $(GENERATE_C++) ] {
384						C++ $(<) : $(<:S=.cpp) ;
385						LexC++ $(<:S=.cpp) : $(>) ;
386					} else {
387						Cc $(<) : $(<:S=.c) ;
388						Lex $(<:S=.c) : $(>) ;
389					}
390	    case .s :	As $(<) : $(>) ;
391	    case .y :	if [ on $(2) return $(GENERATE_C++) ] {
392						C++ $(<) : $(<:S=.cpp) ;
393						Bison $(<:S=.cpp) : $(>) ;
394					} else {
395						Cc $(<) : $(<:S=$(YACCGEN)) ;
396						Yacc $(<:S=$(YACCGEN)) : $(>) ;
397					}
398	    case * :	UserObject $(<) : $(>) ;
399	}
400}
401
402rule UserObject
403{
404	switch $(2)
405	{
406	case *.S    : assemble $(1) : $(2) ;
407	case *.o    : return ;
408	case *      : ECHO "unknown suffix on" $(2) ;
409	}
410}
411
412# Override the default to give "prettier" command lines.
413actions Cc
414{
415	$(CC) $(CCFLAGS) -c "$(2)" $(CCDEFS) $(CCHDRS) -o "$(1)" ;
416}
417
418actions C++
419{
420	$(C++) -c "$(2)" $(C++FLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
421}
422
423
424#-------------------------------------------------------------------------------
425# General High-level OBOS target rules
426#-------------------------------------------------------------------------------
427
428rule App
429{
430	# App <name> : <sources> : <libraries> : <res> ;
431	SetupIncludes ;
432	SetupObjectsDir ;
433	AddResources $(1) : $(4) ;
434	Main $(1) : $(2) ;
435	MakeLocate $(1) : $(OBOS_APPS_DIR) ;
436	LinkSharedOSLibs $(1) : $(3) ;
437	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ]
438						-Xlinker -soname=_APP_ ;
439}
440
441rule BinCommand
442{
443	# BinCommand <name> : <sources> : <libraries> : <res> ;
444	SetupIncludes ;
445	SetupObjectsDir ;
446	AddResources $(1) : $(4) ;
447	Main $(1) : $(2) ;
448	MakeLocate $(1) : $(OBOS_BIN_DIR) ;
449	LinkSharedOSLibs $(1) : $(3) ;
450	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ]
451						-Xlinker -soname=_APP_ ;
452}
453
454rule StdBinCommands
455{
456	# StdBinCommands <sources> : <libs> : <res> ;
457	SetupIncludes ;
458	SetupObjectsDir ;
459	local libs = $(2) ;
460	local ress = $(3) ;
461	local source ;
462	for source in $(1)
463	{
464		local target = $(source:S=) ;
465
466		BinCommand $(target) : $(source) : $(libs) : $(ress) ;
467	}
468}
469
470rule Preference
471{
472	# Preference <name> : <sources> : <libraries> ;
473	SetupIncludes ;
474	SetupObjectsDir ;
475	Main $(1) : $(2) ;
476	MakeLocate $(1) : $(OBOS_PREFS_DIR) ;
477	LinkSharedOSLibs $(1) : $(3) ;
478	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ]
479						-Xlinker -soname=_APP_ ;
480}
481
482rule Server
483{
484	# Server <name> : <sources> : <libraries> ;
485
486	SetupIncludes ;
487	SetupObjectsDir ;
488	Main $(1) : $(2) ;
489	MakeLocate $(1) : $(OBOS_SERVER_DIR) ;
490	LinkSharedOSLibs $(1) : $(3) ;
491	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ]
492						-Xlinker -soname=_APP_ ;
493}
494
495# test pseudo targets
496NOTFILE obostests ;
497NOTFILE r5tests ;
498
499rule CommonTestLib
500{
501	# CommonTestLib <target> : <sources> : <obos libraries>
502	#	: <r5 libraries> : <test libraries> : <public headers>;
503	# Builds a unit test for both OBOS and R5 modules.
504	# <target> The name of the target.
505	# <sources> The list of sources.
506	# <obos libraries> A list of link libraries for the OBOS tests (as passed
507	# to LinkSharedOSLibs).
508	# <r5 libraries> A list of link libraries for the R5 tests (as passed
509	# to LinkSharedOSLibs).
510	# <test libraries> A list of link libraries for both OBOS tests and R5 tests
511	# that have a common name (i.e. specify libx.so and the OBOS tests will link
512	# to libx.so and the R5 tests will link to libx_r5.so).
513	# <public headers> A list of public header dirs (as passed to
514	# UsePublicHeaders).
515
516	TestLib $(1) : $(2) : [ FDirName $(OBOS_TEST_DIR) unittester lib ] : $(3) $(5) : $(6) ;
517	R5TestLib $(1) : $(2) : [ FDirName $(OBOS_TEST_DIR) unittester_r5 lib ] : $(4) [ R5SharedLibraryNames $(5) ] ;
518}
519
520rule TestLib
521{
522	# TestLib <target> : <sources> : <dest> : <libraries> : <public headers>
523	# Builds a unit test library for an OBOS module.
524	# <target> The name of the target.
525	# <sources> The list of sources.
526	# <dest> The directory for the target (as passed to FDirName).
527	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
528	# <public headers> A list of public header dirs (as passed to
529	# UsePublicHeaders).
530
531	local target = $(1) ;
532	local sources = $(2) ;
533	local dest = $(3) ;
534	local libraries = $(4) ;
535	local headerDirs = $(5) ;
536	local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
537
538	# Our Main replacement.
539	MainFromObjects $(target) : $(objects) ;
540	TestObjects $(sources) : $(headerDirs) ;
541
542	MakeLocate $(target) : $(dest) ;
543	Depends $(target) : libcppunit.so ;
544	Depends obostests : $(target) ;
545	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
546	LINKFLAGS on $(target) = $(LINKFLAGS) -nostart -Xlinker -soname=\"$(target)\" ;
547}
548
549rule R5TestLib
550{
551	# R5TestLib <target> : <sources> : <dest> : <libraries>
552	# Builds a unit test for an R5 module. "_r5" is appended to the object
553	# and the target name.
554	# <target> The name of the target.
555	# <sources> The list of sources.
556	# <dest> The directory for the target (as passed to FDirName).
557	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
558
559	local target = $(1:B)_r5$(1:S) ;
560	local sources = $(2) ;
561	local dest = $(3) ;
562	local libraries = $(4) ;
563	local objects = [ R5ObjectNames $(sources) ] ;
564
565	# Our Main replacement.
566	MainFromObjects $(target) : $(objects) ;
567	TestObjects $(sources) : : true ;
568
569	MakeLocate $(target) : $(dest) ;
570	Depends $(target) : libcppunit.so ;
571	Depends r5tests : $(target) ;
572	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
573	LINKFLAGS on $(target) = $(LINKFLAGS) -nostart -Xlinker -soname=\"$(target)\" ;
574}
575
576rule CommonUnitTest
577{
578	# CommonUnitTest <target> : <sources> : <dest> : <obos libraries>
579	#	: <r5 libraries> : <public headers>;
580	# Builds a unit test for both OBOS and R5 modules.
581	# <target> The name of the target.
582	# <sources> The list of sources.
583	# <dest> The directory for the target (as passed to FDirName).
584	# <obos libraries> A list of link libraries for the OBOS tests (as passed
585	# to LinkSharedOSLibs).
586	# <r5 libraries> A list of link libraries for the R5 tests (as passed
587	# to LinkSharedOSLibs).
588	# <public headers> A list of public header dirs (as passed to
589	# UsePublicHeaders).
590
591	UnitTest $(1) : $(2) : $(3) : $(4) : $(6) ;
592	R5UnitTest $(1) : $(2) : $(3) : $(5) ;
593}
594
595rule UnitTest
596{
597	# UnitTest <target> : <sources> : <dest> : <libraries> : <public headers>
598	# Builds a unit test for an OBOS module.
599	# <target> The name of the target.
600	# <sources> The list of sources.
601	# <dest> The directory for the target (as passed to FDirName).
602	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
603	# <public headers> A list of public header dirs (as passed to
604	# UsePublicHeaders).
605
606	local target = $(1) ;
607	local sources = $(2) ;
608	local dest = $(3) ;
609	local libraries = $(4) ;
610	local headerDirs = $(5) ;
611	local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
612
613	# Our Main replacement.
614	MainFromObjects $(target) : $(objects) ;
615	TestObjects $(sources) : $(headerDirs) ;
616
617	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(dest) ] ;
618	Depends $(target) : libcppunit.so ;
619	Depends obostests : $(target) ;
620	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
621}
622
623rule R5UnitTest
624{
625	# R5UnitTest <target> : <sources> : <dest> : <libraries>
626	# Builds a unit test for an R5 module. "_r5" is appended to the object
627	# and the target name.
628	# <target> The name of the target.
629	# <sources> The list of sources.
630	# <dest> The directory for the target (as passed to FDirName).
631	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
632
633	local target = $(1)_r5 ;
634	local sources = $(2) ;
635	local dest = $(3) ;
636	local libraries = $(4) ;
637	local objects = [ R5ObjectNames $(sources) ] ;
638
639	# Our Main replacement.
640	MainFromObjects $(target) : $(objects) ;
641	TestObjects $(sources) : : true ;
642
643	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(dest) ] ;
644	Depends $(target) : libcppunit.so ;
645	Depends r5tests : $(target) ;
646	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
647}
648
649rule R5ObjectNames
650{
651	# R5ObjectNames <sources> ;
652	# Returns a list of gristed object names given a list of source file names.
653	# Moreover each object names gets "_r5" inserted before the object suffix.
654	local objects = $(1:S=)_r5 ;
655	return [ FGristFiles $(objects:S=$(SUFOBJ)) ] ;
656}
657
658rule R5Objects
659{
660	# R5Objects <sources>
661	# Similar to Objects, but appends "_r5" to the object file names and
662	# removes `-nostdinc' from the CC and C++ flags to enable system headers.
663	# <sources> The source files.
664
665	# Remove `-nostdinc' from CCFLAGS and C++FLAGS.
666	local oldCCFLAGS = $(CCFLAGS) ;
667	local oldC++FLAGS = $(C++FLAGS) ;
668	CCFLAGS = [ Filter $(CCFLAGS) : -nostdinc ] ;
669	C++FLAGS = [ Filter $(C++FLAGS) : -nostdinc ] ;
670
671	local sources = $(1) ;
672	local source ;
673	for source in [ FGristFiles $(sources) ]
674	{
675		local object = [ R5ObjectNames $(source) ] ;
676		Object $(object) : $(source) ;
677		LocalDepends obj : $(object) ;
678	}
679
680	# Reset CCFLAGS and C++FLAGS to original values.
681	CCFLAGS = $(oldCCFLAGS) ;
682	C++FLAGS = $(oldC++FLAGS) ;
683}
684
685rule TestObjects
686{
687	# TestLib <sources> : <public headers> : <r5>
688	# Compiles objects for tests.
689	# <sources> The list of sources.
690	# <public headers> A list of public header dirs (as passed to
691	# UsePublicHeaders).
692	# <r5> If set, "_r5" is appended to the object file names and
693	# <public headers> is ignored. Furthermore the pre-processor macro
694	# TEST_R5 is defined, TEST_OBOS otherwise.
695
696	local sources = $(1) ;
697	local headerDirs = $(2) ;
698	local r5 = $(3) ;
699	local objects ;
700
701	# Turn optimization off.
702	if ! $(NO_TEST_DEBUG) {
703		local optim = $(OPTIM) ;
704		OPTIM = ;
705	}
706
707	SetupObjectsDir ;
708
709	# compile
710	if $(r5) {
711		SetupR5Includes ;
712		objects = [ R5ObjectNames $(sources) ] ;
713		R5Objects $(sources) ;
714	} else {
715		SetupIncludes ;
716		objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
717		Objects $(sources) ;
718	}
719
720	# set headers/defines
721	UseCppUnitObjectHeaders $(sources) : $(objects) ;
722	if $(r5) {
723		ObjectsDefines $(objects) : TEST_R5 ;
724	} else {
725		UsePublicObjectHeaders $(sources) : $(headerDirs) : $(objects) ;
726		ObjectsDefines $(objects) : TEST_OBOS ;
727	}
728
729	if ! $(NO_TEST_DEBUG) {
730		# Turn debugging on. That is usually desired for test code.
731		ObjectCcFlags $(objects) : "-g" ;
732		ObjectC++Flags $(objects) : "-g" ;
733
734		# Turn optimization on again.
735		OPTIM = $(optim) ;
736	}
737}
738
739rule R5SharedLibraryNames
740{
741	# R5SharedLibraryNames <sources> ;
742	# Returns a list of shared library names given a list of file names. NO
743	# GRISTING IS PERFORMED :-) However, each library names gets "_r5" inserted
744	# before the shared lib suffix.
745	return $(1:S=)_r5.so ;
746}
747
748rule SimpleTest
749{
750	# UnitTest <target> : <sources> : <libraries>
751	# Builds a unit test for an OBOS module.
752	# <target> The name of the target.
753	# <sources> The list of sources.
754	# <dest> The directory for the target (as passed to FDirName).
755	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
756	# <public headers> A list of public header dirs (as passed to
757	# UsePublicHeaders).
758
759	local target = $(1) ;
760	local sources = $(2) ;
761	local libraries = $(3) ;
762	local relPath = [ FRelPath src tests : $(SUBDIR_TOKENS) ] ;
763
764	# Turn optimization off.
765	if ! $(NO_TEST_DEBUG) {
766		local optim = $(OPTIM) ;
767		OPTIM = ;
768	}
769
770	SetupIncludes ;
771	SetupObjectsDir ;
772	MakeLocateObjects $(sources) ;
773	Main $(target) : $(sources) ;
774	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(relPath) ] ;
775	Depends obostests : $(target) ;
776	LinkSharedOSLibs $(target) : $(libraries) ;
777	ObjectsDefines $(sources) : TEST_OBOS ;
778	if ! $(NO_TEST_DEBUG) {
779		# Turn debugging on. That is usually desired for test code.
780		ObjectCcFlags $(sources) : "-g" ;
781		ObjectC++Flags $(sources) : "-g" ;
782
783		# Turn optimization on again.
784		OPTIM = $(optim) ;
785	}
786}
787
788rule Addon
789{
790	# Addon <name> : <relpath> : <sources> : <is executable> : <libraries> ;
791	# <name>: Name of the add-on.
792	# <relpath>: Path where the add-on shall live relative to the add-on dir.
793	# <sources>: Source files.
794	# <is executable>: true, if the target shall be executable as well.
795	# <libraries>: Libraries to be linked against.
796
797	local isExecutable = $(4) ;
798
799	SetupIncludes ;
800	SetupObjectsDir ;
801	Main $(1) : $(3) ;
802
803	# Create output dir path for addon
804	local targetdir;
805	targetdir = [ FDirName $(OBOS_ADDON_DIR) $(2) ] ;
806
807	MakeLocate $(1) : $(targetdir) ;
808
809	local linkFlags = -Xlinker -soname=\"$(1)\" ;
810	if $(isExecutable) != true {
811		linkFlags = -nostart $(linkFlags) ;
812	}
813	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] $(linkFlags) ;
814	LinkSharedOSLibs $(1) : $(5) ;
815}
816
817rule R5KernelAddon
818{
819	# R5KernelAddon <name> : <relpath> : <sources> : <static-libraries> ;
820
821	local sources = $(3) ;
822
823	Addon $(1) : $(2) : $(3) ;
824	ObjectCcFlags $(sources) : -D_KERNEL_MODE=1 -no-fpic ;
825	ObjectC++Flags $(sources) : -D_KERNEL_MODE=1 -no-fpic -fno-exceptions ;
826	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -nostdlib ;
827	LinkSharedOSLibs $(1) : $(4) /boot/develop/lib/x86/_KERNEL_ ;
828}
829
830rule Translator
831{
832	# Translator <name> : <sources> : <libraries> ;
833	SetupIncludes ;
834	SetupObjectsDir ;
835	Main $(1) : $(2) ;
836	LinkSharedOSLibs $(1) : $(3) ;
837
838	# Create output dir path for translator
839	local targetdir;
840	targetdir = [ FDirName $(OBOS_ADDON_DIR) Translators ] ;
841	MakeLocate $(1) : $(targetdir) ;
842}
843
844rule ScreenSaver
845{
846	# ScreenSaver <name> : <sources> : <libraries> ;
847	Addon $(1) : screen_savers : $(2) : false : $(3) ;
848}
849
850rule MakeLocateObjects
851{
852	# MakeLocateObjects <sources_or_objects> ;
853
854	local _objs = [ FGristFiles $(1:S=$(SUFOBJ)) ] ;
855
856	for o in $(_objs)
857	{
858		local dir = $(o:D) ;
859		if $(dir) {
860			MakeLocate $(o) : [ FDirName $(LOCATE_TARGET) $(dir) ] ;
861		} else {
862			MakeLocate $(o) : $(LOCATE_TARGET) ;
863		}
864	}
865}
866
867rule StaticLibrary
868{
869	# StaticLibrary <name> : <sources> [ : <target dir> ] ;
870	# Creates a static library from sources.
871	# <name>: Basename of the library, without leading "lib" and trailing ".a".
872	#         Grist is allowed -- it will be re-prepended after constructing
873	#         the complete library name.
874	# <source>: List of source files.
875	# <target dir>: Directory into which the library shall be placed. Defaults
876	#               to the objects directory for this subdir. If
877	#               STATIC_LIBRARY_DIR is supplied (the literal string)
878	#               the standard directory for static libs is used, otherwise
879	#               the parameter is interpreted as directory path.
880	#
881	local lib = lib$(1:B)$(SUFLIB) ;
882	lib = $(lib:G=$(1:G)) ;
883	SetupIncludes ;
884	SetupObjectsDir ;
885	MakeLocateObjects $(2) ;
886	Library $(lib) : $(2) ;
887	local targetDir = $(3) ;
888	if $(targetDir) {
889		if $(targetDir) = STATIC_LIBRARY_DIR {
890			targetDir = $(OBOS_STLIB_DIR) ;
891		}
892		MakeLocate $(lib) : $(targetDir) ;
893	} else {
894		# nothing to do, since the Library rule already located the library
895		# in $(LOCATE_TARGET)
896	}
897
898	# If KEEPOBJS is set, Library doesn't make the library depend on
899	# `lib'.
900	if $(KEEPOBJS) {
901		LocalDepends lib : $(lib) ;
902	}
903}
904
905rule R5KernelStaticLibrary
906{
907	# R5KernelStaticLibrary <name> : <sources> ;
908
909	local lib = lib$(1)$(SUFLIB) ;
910	local sources = $(2) ;
911
912	SetupIncludes ;
913	SetupObjectsDir ;
914	MakeLocateObjects $(sources) ;
915	Library $(lib) : $(sources) ;
916	ObjectCcFlags $(sources) : -D_KERNEL_MODE=1 -no-fpic ;
917	ObjectC++Flags $(sources) : -D_KERNEL_MODE=1 -no-fpic -fno-exceptions ;
918}
919
920rule MergeObjectFromObjects
921{
922	# MergeObjectFromObjects <name> : <objects> : <other objects> ;
923	# Merges object files to an object file.
924	# <name>: Name of the object file to create. No grist will be added.
925	# <objects>: Object files to be merged. Grist will be added.
926	# <other objects>: Object files or static libraries to be merged. No grist
927	#                  will be added.
928	#
929	local objects = [ FGristFiles $(2) ] ;
930	MakeLocate $(1) : $(LOCATE_TARGET) ;
931	Depends $(1) : $(objects) ;
932	Depends $(1) : $(3) ;
933	LINK on $(1) = ld ;
934	MergeObjectFromObjects1 $(1) : $(objects) $(3) ;
935}
936
937actions MergeObjectFromObjects1
938{
939	$(LINK) -r $(2) -o $(1) ;
940}
941
942rule MergeObject
943{
944	# MergeObject <name> : <sources> : <other objects> ;
945	# Compiles source files and merges the object files to an object file.
946	# <name>: Name of the object file to create. No grist will be added.
947	# <sources>: Sources to be compiled. Grist will be added.
948	# <other objects>: Object files or static libraries to be merged. No grist
949	#                  will be added.
950	#
951	SetupIncludes ;
952	SetupObjectsDir ;
953	MakeLocateObjects $(2) ;
954	Objects $(2) ;
955	MergeObjectFromObjects $(1) : $(2:S=$(SUFOBJ)) : $(3) ;
956}
957
958rule SharedLibraryFromObjects
959{
960	# SharedLibraryFromObjects <name> : <objects> : <libraries> ;
961	local _lib = lib$(1:B).so ;
962	_lib = $(_lib:G=$(1:G)) ;
963	MainFromObjects $(_lib) : $(2) ;
964	MakeLocate $(_lib) : $(OBOS_SHLIB_DIR) ;
965	LINKFLAGS on $(_lib) = [ on $(_lib) return $(LINKFLAGS) ]
966						   -nostart -Xlinker -soname=\"$(_lib)\" ;
967	LinkSharedOSLibs $(_lib) : $(3) ;
968}
969
970rule SharedLibrary
971{
972	# SharedLibrary <name> : <sources> : <libraries> ;
973	SetupIncludes ;
974	SetupObjectsDir ;
975	MakeLocateObjects $(2) ;
976	Objects $(2) ;
977	SharedLibraryFromObjects $(1) : $(2:S=$(SUFOBJ)) : $(3) ;
978}
979
980rule LinkSharedOSLibs
981{
982	# LinkSharedOSLibs <name> : <libs> ;
983	# Valid elements for <libs> are e.g. "be" or "libopenbeos.so" or
984	# "/boot/.../libfoo.so". If the basename starts with "lib" or the thingy
985	# has a dirname or grist, it is added to the NEEDLIBS variable (i.e. the
986	# file will be bound!), otherwise it is prefixed "-l" and added to
987	# LINKLIBS. If you want to specify a target that isn't a library and
988	# also has neither grist nor a dirname, you can prepend "<nogrist>" as
989	# grist; it will be stripped by this rule.
990
991	for i in $(>)
992	{
993		local isfile = ;
994		if $(i:D) || $(i:G) {
995			isfile = true ;
996			if $(i:G) = <nogrist> {
997				i = $(i:G=) ;
998			}
999		} else {
1000			switch $(i:B)
1001			{
1002				# XXX: _APP_ and _KERNEL_ should not be needed for ELF.
1003				case _APP_ : isfile = true ;
1004				case _KERNEL_ : isfile = true ;
1005				case lib*	: isfile = true ;
1006				case *	: isfile = ;
1007			}
1008			if ! $(isfile) && ( $(i:S) = .so || $(i:S) = .a ) {
1009				isfile = true ;
1010			}
1011		}
1012		if $(isfile) {
1013			NEEDLIBS on $(1) = [ on $(1) return $(NEEDLIBS) ] $(i) ;
1014			Depends $(1) : $(i) ;
1015		} else {
1016			LINKLIBS on $(1) = [ on $(1) return $(LINKLIBS) ] -l$(i) ;
1017		}
1018	}
1019}
1020
1021rule AddResources
1022{
1023	# AddResources <name> : <resourcefiles> ;
1024
1025	local resfiles = [ FGristFiles $(2) ] ;
1026	SEARCH on $(resfiles) += $(SEARCH_SOURCE) ;
1027
1028	for file in $(resfiles) {
1029		if $(file:S) = .rdef {
1030			local rdef = $(file) ;
1031			file = $(rdef:S=.rsrc) ;
1032			ResComp $(file) : $(rdef) ;
1033		}
1034		RESFILES on $(1) += $(file) ;
1035	}
1036}
1037
1038rule ResComp
1039{
1040	# ResComp <resource file> : <rdef file> ;
1041	#
1042	# <resource file> and <rdef file> must be gristed.
1043
1044	SetupObjectsDir ;
1045
1046	SEARCH on $(2) += $(SEARCH_SOURCE) ;
1047	MakeLocate $(1) : $(LOCATE_TARGET) ;
1048	Depends $(1) : $(2) rc ;
1049	LocalClean clean : $(1) ;
1050	ResComp1 $(1) : rc $(2) ;
1051}
1052
1053actions ResComp1
1054{
1055	$(2[1]) -o $(1) $(2[2-])
1056}
1057
1058rule ObjectsDefines
1059{
1060	# Like ObjectDefines, but allows multiple files to be supplied
1061	local file ;
1062	for file in $(1) {
1063		ObjectDefines $(file) : $(2) ;
1064	}
1065}
1066
1067rule SourceHdrs
1068{
1069	# SourceHdrs <sources> : <headers> [ : <gristed objects> ] ;
1070	#
1071	# Is a wrapper for ObjectHdrs, that passes <sources> and <headers> or,
1072	# if supplied <objects> and <headers>, and also adjusts HDRSEARCH (not
1073	# done by ObjectHdrs).
1074
1075	local sources = [ FGristFiles $(1) ] ;
1076	local headers = $(2) ;
1077	local objects = $(3) ;
1078
1079	local file ;
1080	if $(objects) {
1081		for file in $(objects) {
1082			ObjectHdrs $(file) : $(headers) ;
1083			# also reformat the assembler headers
1084			ASHDRS on $(file) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS)
1085								  [ on $(file) return $(HDRS) ] ] ;
1086		}
1087	} else {
1088		for file in $(sources:S=$(SUFOBJ)) {
1089			ObjectHdrs $(file) : $(headers) ;
1090			# also reformat the assembler headers
1091			ASHDRS on $(file) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS)
1092								  [ on $(file) return $(HDRS) ] ] ;
1093		}
1094	}
1095
1096	# Also add the header search dirs to HDRSEARCH. Note, that these dirs
1097	# will be listed after the STDHDRS (if any), but that's better than not
1098	# being listed at all.
1099	HDRSEARCH on $(sources) += $(headers) ;
1100}
1101
1102rule PublicHeaders
1103{
1104	# PublicHeaders <group list>
1105	#
1106	# Returns the directory names for the public header dirs identified by
1107	# <group list>.
1108
1109	local list = $(1) ;
1110	local dirs = [ FDirName $(OBOS_TOP) headers os ] ;
1111
1112	for i in $(list) {
1113		dirs += [ FDirName $(OBOS_TOP) headers os $(i) ] ;
1114	}
1115	return $(dirs) ;
1116}
1117
1118rule PrivateHeaders
1119{
1120	# PrivateHeaders <group list>
1121	#
1122	# Returns the directory names for the private header dirs identified by
1123	# <group list>.
1124
1125	local list = $(1) ;
1126	local dirs ;
1127	for i in $(list) {
1128		dirs += [ FDirName $(OBOS_TOP) headers private $(i) ] ;
1129	}
1130	return $(dirs) ;
1131}
1132
1133rule LibraryHeaders
1134{
1135	# LibraryHeaders <group list>
1136	#
1137	# Returns the directory names for the library header dirs identified by
1138	# <group list>.
1139
1140	local list = $(1) ;
1141	local dirs ;
1142	for i in $(list) {
1143		dirs += [ FDirName $(OBOS_TOP) headers libs $(i) ] ;
1144	}
1145	return $(dirs) ;
1146}
1147
1148rule ArchHeaders
1149{
1150	# usage: ArchHeaders <arch> ;
1151	#
1152	# <arch> specifies the architecture (e.g. x86).
1153
1154	return [ FDirName $(OBOS_TOP) headers private kernel arch $(1) ] ;
1155}
1156
1157rule UsePublicHeaders
1158{
1159	# UsePublicHeaders <group list> ;
1160	#
1161	# Adds the public C header dirs given by <group list> to the header search
1162	# dirs of the subdirectory.
1163	# NOTE: This rule must be invoked *before* the rule that builds the
1164	# objects.
1165
1166	UseHeaders [ PublicHeaders $(1) ] ;
1167}
1168
1169rule UsePublicObjectHeaders
1170{
1171	# UsePublicObjectHeaders <sources> : <group list> [ : <objects> ] ;
1172	#
1173	# Adds the public C header dirs given by <group list> to the header search
1174	# dirs of either the object targets of <sources> or if supplied to
1175	# <objects>. Also adjusts HDRSEARCH of <sources>.
1176	# NOTE: This rule must be invoked *after* the rule that builds the objects.
1177
1178	SourceHdrs $(1) : [ PublicHeaders $(2) ] : $(3) ;
1179}
1180
1181rule UsePrivateHeaders
1182{
1183	# UsePrivateHeaders <group list> ;
1184	#
1185	# Adds the private C header dirs given by <group list> to the header search
1186	# dirs of the subdirectory.
1187	# NOTE: This rule must be invoked *before* the rule that builds the objects.
1188
1189	UseHeaders [ PrivateHeaders $(1) ] ;
1190}
1191
1192rule UsePrivateObjectHeaders
1193{
1194	# UsePrivateObjectHeaders <sources> : <group list> [ : <objects> ] ;
1195	#
1196	# Adds the private C header dirs given by <group list> to the header search
1197	# dirs of either the object targets of <sources> or if supplied to
1198	# <objects>. Also adjusts HDRSEARCH of <sources>.
1199	# NOTE: This rule must be invoked *after* the rule that builds the objects.
1200
1201	SourceHdrs $(1) : [ PrivateHeaders $(2) ] : $(3) ;
1202}
1203
1204rule UseHeaders
1205{
1206	# UseHeaders <headers> ;
1207	#
1208	# Adds the C header dirs <headers> to the header search
1209	# dirs of the subdirectory.
1210	# NOTE: This rule must be invoked *before* the rule that builds the objects.
1211
1212	local header ;
1213	for header in $(1) {
1214		SubDirHdrs $(header) ;
1215	}
1216}
1217
1218rule UseCppUnitHeaders
1219{
1220	SubDirHdrs [ FDirName $(OBOS_TOP) headers tools cppunit ] ;
1221}
1222
1223rule UseCppUnitObjectHeaders
1224{
1225	# UseCppUnitObjectHeaders <sources> [ : <objects> ] ;
1226	SourceHdrs $(1) : [ FDirName $(OBOS_TOP) headers tools cppunit ] : $(2) ;
1227}
1228
1229rule UseArchHeaders
1230{
1231	# usage: UseArchHeaders <arch> ;
1232	#
1233	# <arch> specifies the architecture (e.g. x86).
1234	# NOTE: This rule must be invoked *before* the rule that builds the objects.
1235
1236	local headers = [ ArchHeaders $(1) ] ;
1237	local opt = -D$(OBOS_TARGET_DEFINE) ;
1238
1239	SubDirCcFlags $(opt)  ;
1240	SubDirC++Flags $(opt)  ;
1241	UseHeaders $(headers) ;
1242}
1243
1244rule UseArchObjectHeaders
1245{
1246	# usage: UseArchObjectHeaders <sources> : <arch> : [ <objects> ] ;
1247	#
1248	# <arch> specifies the architecture (e.g. x86).
1249	# <sources_or_objects> Source or object files.
1250	# NOTE: This rule must be invoked *after* the rule that builds the objects.
1251
1252	local sources = $(1) ;
1253	local headers = [ ArchHeaders $(2) ] ;
1254	local objects = $(3) ;
1255	local targets ;
1256	if $(objects) {
1257		targets = $(objects) ;
1258	} else {
1259		targets = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
1260	}
1261	local opt = -D$(OBOS_TARGET_DEFINE) ;
1262
1263	ObjectCcFlags $(targets) : $(opt)  ;
1264	ObjectC++Flags $(targets) : $(opt)  ;
1265	SourceHdrs $(sources) : $(headers) : $(objects) ;
1266}
1267
1268rule UsePosixHeaders
1269{
1270	# XXX changed to do nothing
1271}
1272
1273rule UsePosixObjectHeaders
1274{
1275	# UsePosixObjectHeaders <sources> [ : <objects> ] ;
1276	#
1277	# Adds the POSIX header dir to the header search
1278	# dirs of either the object targets of <sources> or if supplied to
1279	# <objects>. Also adjusts HDRSEARCH of <sources>.
1280	# NOTE: This rule must be invoked *after* the rule that builds the objects.
1281
1282	SourceHdrs $(1) : [ FDirName $(OBOS_TOP) headers posix ] : $(2) ;
1283}
1284
1285rule UseLibraryHeaders
1286{
1287	# UseLibraryHeaders <group list> ;
1288	#
1289	# Adds the library header dirs given by <group list> to the header search
1290	# dirs of the subdirectory.
1291	# NOTE: This rule must be invoked *before* the rule that builds the objects.
1292
1293	UseHeaders [ LibraryHeaders $(1) ] ;
1294}
1295
1296rule SplitPath
1297{
1298	# SplitPath <path> ;
1299	# Decomposes a path into its components.
1300	local path = $(1:G=) ;
1301	local components ;
1302	# $(path:D) for "/" is "/". Therefore the second condition.
1303	while $(path:D) && $(path:D) != $(path)
1304	{
1305		# Note: $(path:B) returns "." for "..", but $(path:D=) is fine.
1306		components = $(path:D=) $(components) ;
1307		path = $(path:D) ;
1308	}
1309	components = $(path) $(components) ;
1310	return $(components) ;
1311}
1312
1313rule PrependObjectHdrs
1314{
1315	# PrependObjectHdrs <objects_or_sources> : <dirs> ;
1316	# Prepends <dirs> to the list of header search dirs of the objects
1317	# specified by <objects_or_sources>. The HDRS variable will not be
1318	# changed, only CCHDRS.
1319	# Note: A subsequent ObjectHdrs invocation will therefore undo the
1320	# effect of this rule.
1321	# NOTE: This is a hack.
1322
1323	local objects = [ FGristFiles $(1:S=$(SUFOBJ)) ] ;
1324	local dirs = $(2) ;
1325	for object in $(objects) {
1326		# Don't change HDRS to avoid screwing up the header scanning.
1327		PREPENDED_HDRS on $(object)
1328			= $(dirs) [ on $(object) return $(PREPENDED_HDRS) ] ;
1329		CCHDRS on $(object)
1330			= [ FIncludes [ on $(object) return $(PREPENDED_HDRS) $(HDRS) ] ] ;
1331	}
1332}
1333
1334rule SymLink
1335{
1336	# SymLink <target> : <source> : <makeDefaultDependencies> ;
1337	# Links <target> to <source>.
1338	# <source> is the exact link contents. No binding is done.
1339	# <makeDefaultDependencies> If true, <target> will be made a dependency
1340	# of the `all' pseudo target, i.e. it will be made by default, and removed
1341	# on `jam clean'.
1342
1343	local target = $(1) ;
1344	local source = $(2) ;
1345	local makeDefaultDependencies = $(3) ;
1346	if ! $(makeDefaultDependencies) {
1347		makeDefaultDependencies = true ;
1348	}
1349	LINKCONTENTS on $(target) = $(source) ;
1350	SymLink1 $(target) ;
1351	if $(makeDefaultDependencies) = true {
1352		LocalDepends files : $(target) ;
1353		LocalClean clean : $(target) ;
1354	}
1355}
1356
1357actions SymLink1
1358{
1359	$(RM) "$(1)" && $(LN) -s "$(LINKCONTENTS)" "$(1)"
1360}
1361
1362rule RelSymLink
1363{
1364	# RelSymLink <link> : <link target> : <makeDefaultDependencies> ;
1365	# Creates a relative symbolic link from <link> to <link target>.
1366	# <link> and <link target> can be usual targets. They may have a grist
1367	# and don't need to have any dirname. Their LOCATE variables are used to
1368	# find their locations.
1369	# <makeDefaultDependencies> If true (which is the default), <link> will be
1370	# made a dependency of the `files' pseudo target, i.e. it will be made by
1371	# default, and removed on `jam clean'.
1372
1373	local target = $(1) ;
1374	local source = $(2) ;
1375	local makeDefaultDependencies = $(3) ;
1376	local targetDir = [ on $(target) FDirName $(LOCATE[1]) $(target:D) ] ;
1377	local sourceDir = [ on $(source) FDirName $(LOCATE[1]) $(source:D) ] ;
1378	local sourcePath = $(source:G=) ;
1379	sourcePath = $(sourcePath:D=$(sourceDir)) ;
1380	local targetDirComponents = [ SplitPath $(targetDir) ] ;
1381	local sourceComponents = [ SplitPath $(sourcePath) ] ;
1382
1383	SymLink $(target)
1384		: [ FRelPath $(targetDirComponents) : $(sourceComponents) ]
1385		: $(makeDefaultDependencies) ;
1386	NOUPDATE $(target) ;
1387	Depends $(target) : $(source) ;
1388}
1389
1390rule AbsSymLink
1391{
1392	# AbsSymLink <link> : <link target> : <link dir>
1393	#			: <makeDefaultDependencies> ;
1394	# Creates an absolute symbolic link from <link> to <link target>.
1395	# <link> and <link target> must be usual targets. If <link dir> is
1396	# given, then it is set as LOCATE directory on <link>.
1397	# <makeDefaultDependencies> If true (which is the default), <link> will be
1398	# made a dependency of the `files' pseudo target, i.e. it will be made by
1399	# default, and removed on `jam clean'.
1400
1401	local makeDefaultDependencies = $(4) ;
1402	if ! $(makeDefaultDependencies) {
1403		makeDefaultDependencies = true ;
1404	}
1405
1406	Depends $(1) : $(2) ;
1407	if $(3) {
1408		MakeLocate $(1) : $(3) ;
1409	}
1410	SEARCH on $(2) += $(SEARCH_SOURCE) ;
1411	if $(makeDefaultDependencies) = true {
1412		LocalDepends files : $(1) ;
1413		LocalClean clean : $(1) ;
1414	}
1415}
1416
1417actions AbsSymLink
1418{
1419	target="$(2)"
1420	case "$target" in
1421		/*) ;;
1422		*) target=`pwd`/"$target";;
1423	esac
1424	$(RM) "$(1)" && $(LN) -s "$target" "$(1)"
1425}
1426
1427rule OBOSInstall
1428{
1429	# Usage: OBOSInstall <[ install [ and uninstall ] pseudotarget ]>
1430	#					 : <directory> : <sources to install>
1431	#					 : [ <installgrist> ] : [ <install rule> ] ;
1432	local install = $(1[1]) ;
1433	install ?= install ;
1434	local uninstall = $(1[2]) ;
1435	uninstall ?= un$(install) ;
1436	local dir = $(2) ;
1437	local sources = $(3) ;
1438	local installgrist = $(4) ;
1439	installgrist ?= $(INSTALLGRIST) ;
1440	local installRule = $(5) ;
1441	installRule ?= Install ;
1442	local targets = $(sources:G=$(installgrist)) ;
1443
1444	NotFile $(install) ;
1445	NotFile $(uninstall) ;
1446	Depends $(install) : $(targets) ;
1447	Clean $(uninstall) : $(targets) ;
1448
1449	SEARCH on $(sources) += $(SEARCH_SOURCE) ;
1450	MakeLocate $(targets) : $(dir) ;
1451
1452	local source ;
1453	for source in $(sources) {
1454		local target = $(source:G=$(installgrist)) ;
1455
1456		Depends $(target) : $(source) ;
1457		$(installRule) $(target) : $(source) ;
1458
1459		if [ on $(target) return $(MODE) ] {
1460			Chmod $(target) ;
1461		}
1462
1463		if $(OWNER) && $(CHOWN) {
1464			Chown $(target) ;
1465			OWNER on $(target) = $(OWNER) ;
1466		}
1467
1468		if $(GROUP) && $(CHGRP) {
1469			Chgrp $(target) ;
1470			GROUP on $(target) = $(GROUP) ;
1471		}
1472	}
1473}
1474
1475rule InstallAbsSymLinkAdapter
1476{
1477	# InstallAbsSymLinkAdapter <link> : <link target>
1478	if ! [ on $(2) return $(TARGET) ] {
1479		TARGET on $(2) = [ on $(2) return $(SEARCH) ] ;
1480	}
1481	AbsSymLink $(1) : $(2) : : false ;
1482}
1483
1484rule OBOSInstallAbsSymLink
1485{
1486	# Usage: OBOSInstallAbsSymLink <[ install [ and uninstall ] pseudotarget ]>
1487	#							   : <directory> : <sources to install>
1488	#							   : [ <installgrist> ] ;
1489	OBOSInstall $(1) : $(2) : $(3) : $(4) : InstallAbsSymLinkAdapter ;
1490}
1491
1492rule InstallRelSymLinkAdapter
1493{
1494	# InstallRelSymLinkAdapter <link> : <link target>
1495	if ! [ on $(2) return $(TARGET) ] {
1496		TARGET on $(2) = [ on $(2) return $(SEARCH) ] ;
1497	}
1498	RelSymLink $(1) : $(2) : false ;
1499}
1500
1501rule OBOSInstallRelSymLink
1502{
1503	# Usage: OBOSInstallRelSymLink <[ install [ and uninstall ] pseudotarget ]>
1504	#							   : <directory> : <sources to install>
1505	#							   : [ <installgrist> ] ;
1506	OBOSInstall $(1) : $(2) : $(3) : $(4) : InstallRelSymLinkAdapter ;
1507}
1508
1509
1510#-------------------------------------------------------------------------------
1511# Low-level OBOS utility rules
1512#-------------------------------------------------------------------------------
1513rule FObjectsDir
1514{
1515	# FObjectsDir <subdir tokens>
1516	#
1517	# Returns the output directory for object files the specified
1518	# subdirectory.
1519	#
1520	# <subdir tokens>: The tokens of the subdir relative to the top.
1521	#
1522
1523	return [ FDirName $(OBOS_OBJECT_TARGET) $(1[2-]) ] ;
1524}
1525
1526rule FCurrentObjectsDir
1527{
1528	# FCurrentObjectsDir
1529	#
1530	# Returns the output directory for object files for the current
1531	# subdirectory.
1532
1533	return [ FObjectsDir $(SUBDIR_TOKENS) ] ;
1534}
1535
1536rule SetupObjectsDir
1537{
1538	LOCATE_TARGET = [ FCurrentObjectsDir ] ;
1539	LOCATE_SOURCE = $(LOCATE_TARGET) ;
1540	SEARCH_SOURCE = [ Filter $(SEARCH_SOURCE) : $(LOCATE_TARGET) ]
1541					$(LOCATE_TARGET) ;
1542}
1543
1544#-------------------------------------------------------------------------------
1545# Link rule/action are overwritten as they don't handle linking files who's name
1546# contain spaces very well. Also adds resources and version to executable.
1547#-------------------------------------------------------------------------------
1548rule Link
1549{
1550	# Note: RESFILES must be set before invocation.
1551	MODE on $(<) = $(EXEMODE) ;
1552	on $(1) XRes $(1) : $(RESFILES) ;
1553	Chmod $(<) ;
1554	SetType $(1) ;
1555	MimeSet $(1) ;
1556	SetVersion $(1) ;
1557}
1558
1559actions Link bind NEEDLIBS
1560{
1561	$(LINK) $(LINKFLAGS) -o "$(1)" $(UNDEFS) "$(2)" "$(NEEDLIBS)" $(LINKLIBS) ;
1562}
1563
1564rule LexC++
1565{
1566	Depends $(1) : $(2) ;
1567	MakeLocate $(1) : $(LOCATE_SOURCE) ;
1568	LocalClean clean : $(1) ;
1569}
1570
1571actions LexC++
1572{
1573	$(LEX) -o$(1) $(2)
1574}
1575
1576rule Bison
1577{
1578	local _h ;
1579
1580	_h = $(1:S=.hpp) ;
1581
1582	MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;
1583
1584	Depends $(<) $(_h) : $(>) ;
1585	Bison1 $(<) $(_h) : $(>) ;
1586	LocalClean clean : $(<) $(_h) ;
1587
1588	# make sure someone includes $(_h) else it will be
1589	# a deadly independent target
1590
1591	Includes $(<) : $(_h) ;
1592}
1593
1594actions Bison1
1595{
1596	bison $(YACCFLAGS) -o $(1[1]) $(2)
1597	[ -f $(1[1]).h ] && mv $(1[1]).h $(1[2]) || true
1598}
1599
1600rule UnarchiveObjects
1601{
1602	# UnarchiveObjects <target objects> : <static object>
1603
1604	MakeLocate $(1) : $(LOCATE_TARGET) ;
1605	Depends $(2) : $(1) ;
1606	SEARCH on $(2) = $(SEARCH_SOURCE) ;
1607}
1608
1609actions UnarchiveObjects
1610{
1611	cd $(1[1]:D)
1612	ar -x "$(2)" $(1:BS)
1613	cd -
1614}
1615
1616# BeOS specific rules
1617
1618rule XRes
1619{
1620	# XRes <target> : <resource files>
1621	if $(2)
1622	{
1623		Depends $(1) : $(2) ;
1624		XRes1 $(1) : $(2) ;
1625	}
1626}
1627
1628rule XRes1 { }
1629
1630rule SetVersion
1631{
1632	# SetVersion <target>
1633}
1634
1635rule SetType
1636{
1637	# SetType <target>
1638}
1639
1640rule MimeSet
1641{
1642	# SetType <target>
1643}
1644
1645
1646if $(OS) = BEOS
1647{
1648
1649actions XRes1
1650{
1651	xres -o "$(1)" "$(2)" ;
1652}
1653
1654actions SetVersion
1655{
1656	setversion "$(1)" -system $(OBOS_BUILD_VERSION) -short "$(OBOS_BUILD_DESCRIPTION)" ;
1657}
1658
1659actions SetType
1660{
1661	settype -t $(OBOS_TARGET_TYPE) "$(1)" ;
1662}
1663
1664actions MimeSet
1665{
1666	mimeset -f "$(1)" ;
1667}
1668
1669}	# if BEOS
1670
1671
1672rule assemble
1673{
1674	Depends $(<) : $(>) ;
1675	ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
1676	ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
1677}
1678
1679actions assemble
1680{
1681	$(CC) -c "$(2)" -O2 $(ASFLAGS) -D_ASSEMBLER $(KERNEL_CCFLAGS) $(ASHDRS) -o "$(1)" ;
1682}
1683
1684# Overridden to allow spaces in file names.
1685actions Chmod1
1686{
1687	$(CHMOD) "$(MODE)" "$(1)"
1688}
1689
1690# Overridden to allow spaces in file names.
1691actions piecemeal together existing Clean
1692{
1693	$(RM) "$(>)"
1694}
1695
1696rule ObjectReference
1697{
1698	# ObjectReference <reference object> : <source object>
1699	# Makes <reference object> refer to the same file as <source object>.
1700	# The filenames must of course be identical.
1701	# <source object> must have already been LOCATEd.
1702
1703	local ref = $(1) ;
1704	local source = $(2) ;
1705	if $(ref) != $(source) {
1706		Depends $(ref) : $(source) ;
1707		LOCATE on $(ref) = [ on $(source) return $(LOCATE) ] ;
1708	}
1709}
1710
1711rule ObjectReferences
1712{
1713	# ObjectReferences <source objects>
1714	# Creates local references to <source objects>, i.e. identifiers with the
1715	# current grist referring to the same files. <source objects> must have
1716	# already been LOCATEd.
1717
1718	local source ;
1719	for source in $(1) {
1720		ObjectReference [ FGristFiles $(source) ] : $(source) ;
1721	}
1722}
1723
1724rule Filter
1725{
1726	# Filter <list> : <excludes> ;
1727	# Removes all occurrences of <excludes> in <list>.
1728
1729	local list = $(1) ;
1730	local excludes = $(2) ;
1731	local newList ;
1732	local item ;
1733	for item in $(list) {
1734		local skip ;
1735		local exclude ;
1736		for exclude in $(excludes) {
1737			if $(item) = $(exclude) {
1738				skip = true ;
1739			}
1740		}
1741		if ! $(skip) {
1742			newList += $(item) ;
1743		}
1744	}
1745	return $(newList) ;
1746}
1747
1748
1749## Kernel stuff!
1750
1751rule SetupKernel
1752{
1753	# Usage SetupKernel <sources_or_objects> : <extra_cc_flags>;
1754	#
1755	# <sources_or_objects> - Ideally sources, otherwise HDRSEARCH can not be
1756	#                        set for the sources and the sources some header
1757	#                        dependencies might be missing.
1758
1759	local sources = [ FGristFiles $(1) ] ;
1760	local _objs = $(sources:S=$(SUFOBJ)) ;
1761
1762	#Setup Kernel header directories
1763	local public_kernel_includes = add-ons/file_system add-ons/graphics app device drivers kernel storage support ;
1764	local private_kernel_includes = $(DOT) kernel libroot kernel/boot/platform/$(OBOS_BOOT_PLATFORM) ;
1765	# Use posix headers directory
1766	local headers = [ FDirName $(OBOS_TOP) headers posix ] ;
1767	# Use public OS header directories
1768	headers += [ PublicHeaders $(public_kernel_includes) ] ;
1769	# Use private directories
1770	headers += [ PrivateHeaders $(private_kernel_includes) ] ;
1771	# The platform dependent headers.
1772	headers += $(PLATFORM_HEADERS) ;
1773
1774	SourceHdrs $(sources) : $(headers) ;
1775	UseArchObjectHeaders $(sources) : $(OBOS_ARCH) ;
1776
1777	local object ;
1778	for object in $(_objs) {
1779		ObjectCcFlags $(object) : $(KERNEL_CCFLAGS) $(2) ;
1780		ObjectC++Flags $(object) : $(KERNEL_C++FLAGS) $(2) ;
1781	}
1782}
1783
1784rule KernelObjects
1785{
1786	SetupObjectsDir ;
1787
1788	Objects $(1) ;
1789
1790	SetupKernel $(1) : $(2) ;
1791}
1792
1793rule KernelLd
1794{
1795	# KernelLd <name> : <objs> : <linkerscript> : <args> : <gcc_off> : <config_section> ;
1796
1797	SetupObjectsDir ;
1798	LINK on $(1) = ld ;
1799
1800	LINKFLAGS on $(1) = $(4) ;
1801	if $(3) { LINKFLAGS on $(1) += --script=$(3) ; }
1802
1803	# Remove any preset LINKLIBS
1804	LINKLIBS on $(1) =  ;
1805
1806	# Show that we depend on the libraries we need
1807	LocalClean clean : $(1) ;
1808	LocalDepends all : $(1) ;
1809	Depends $(1) : $(2) ;
1810
1811	if $(6) {
1812		for i in $(6) {
1813			KernelConfigSection $(i) : elf32 : $(1) ;
1814		}
1815	}
1816
1817	MakeLocate $(1) : $(LOCATE_TARGET) ;
1818
1819	# Add the platform specific static libs (libgcc.a).
1820	if ! $(5) {
1821		LINKLIBS on $(1) += $(PLATFORM_LINKLIBS) ;
1822	}
1823
1824	SetupKernel $(2) ;
1825}
1826
1827actions KernelLd
1828{
1829	$(LINK) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) ;
1830}
1831
1832rule KernelAddon
1833{
1834	# KernelAddon <name> : <relpath> : <sources> : <static-libraries> ;
1835
1836	local sources = $(3) ;
1837
1838	SetupObjectsDir ;
1839	Addon $(1) : $(2) : $(sources) ;
1840	ObjectCcFlags $(sources) : -D_KERNEL_MODE=1 -no-fpic ;
1841	ObjectC++Flags $(sources) : -D_KERNEL_MODE=1 -no-fpic -fno-exceptions ;
1842	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -nostdlib ;
1843	LinkSharedOSLibs $(1) : $(4) <nogrist>kernel.so ;
1844	SetupKernel $(sources) ;
1845}
1846
1847rule KernelMergeObject
1848{
1849	# KernelMergeObject <name> : <sources> : <extra CFLAGS> : <other objects> ;
1850	# Compiles source files and merges the object files to an object file.
1851	# <name>: Name of the object file to create. No grist will be added.
1852	# <sources>: Sources to be compiled. Grist will be added.
1853	# <extra CFLAGS>: Additional flags for compilation.
1854	# <other objects>: Object files or static libraries to be merged. No grist
1855	#                  will be added.
1856	#
1857
1858	SetupObjectsDir ;
1859
1860	MakeLocateObjects $(2) ;
1861	Objects $(2) ;
1862	MergeObjectFromObjects $(1) : $(2:S=$(SUFOBJ)) : $(4) ;
1863
1864	SetupKernel $(2) : $(3) ;
1865}
1866
1867rule KernelStaticLibrary
1868{
1869	# Usage KernelStaticLibrary <name> : <sources> : <extra cc flags>  ;
1870	# This is designed to take a set of sources and libraries and create
1871	# a file called lib<name>.a
1872
1873	SetupObjectsDir ;
1874
1875	MakeLocateObjects $(2) ;
1876	Library $(1) : $(2) ;
1877
1878	SetupKernel $(2) : $(3) ;
1879}
1880
1881rule KernelStaticLibraryObjects
1882{
1883	# Usage KernelStaticLibrary <name> : <sources> ;
1884	# This is designed to take a set of sources and libraries and create
1885	# a file called <name>
1886
1887	SetupObjectsDir ;
1888
1889	# Show that we depend on the libraries we need
1890	LocalClean clean : $(1) ;
1891	LocalDepends all : $(1) ;
1892	Depends $(1) : $(2) ;
1893
1894	MakeLocate $(1) : $(LOCATE_TARGET) ;
1895
1896	SetupKernel $(2) ;
1897}
1898
1899actions KernelStaticLibraryObjects
1900{
1901	ar -r "$(1)" "$(2)" ;
1902}
1903
1904rule BuildPlatformMain
1905{
1906	# Usage BuildPlatformMain <target> : <sources> ;
1907	SetupObjectsDir ;
1908	SetupDefaultIncludes ;
1909
1910	# Remove `-nostdinc' from CCFLAGS and C++FLAGS.
1911	local oldCCFLAGS = $(CCFLAGS) ;
1912	local oldC++FLAGS = $(C++FLAGS) ;
1913	CCFLAGS = [ Filter $(CCFLAGS) : -nostdinc ] ;
1914	C++FLAGS = [ Filter $(C++FLAGS) : -nostdinc ] ;
1915
1916	Main $(1) : $(2) ;
1917
1918	# Reset CCFLAGS and C++FLAGS to original values.
1919	CCFLAGS = $(oldCCFLAGS) ;
1920	C++FLAGS = $(oldC++FLAGS) ;
1921}
1922
1923rule BuildPlatformTest
1924{
1925	# Usage BuildPlatformTest <target> : <sources> ;
1926
1927	local target = $(1) ;
1928	local sources = $(2) ;
1929
1930	BuildPlatformMain $(target) : $(sources) ;
1931	local relPath ;
1932	if [ FIsPrefix src tests : $(SUBDIR_TOKENS) ] {
1933		relPath = $(SUBDIR_TOKENS[3-]) ;
1934	} else {
1935		relPath = $(SUBDIR_TOKENS[2-]) ;
1936	}
1937	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(relPath) ] ;
1938}
1939
1940rule KernelConfigSection
1941{
1942	# KernelConfigSection <section> : <type> : <file>  ;
1943
1944	SECTION_NAMES on $(OBOS_KERNEL_CONFIG) += $(1) ;
1945	SECTION_TYPES on $(OBOS_KERNEL_CONFIG) += $(2) ;
1946	SECTION_FILES on $(OBOS_KERNEL_CONFIG) += $(3) ;
1947
1948	Depends $(OBOS_KERNEL_CONFIG) : $(3) ;
1949}
1950
1951rule WriteKernelConfig
1952{
1953	# usage: WriteKernelConfig <target> ;
1954
1955	LocalDepends files : $(1) ;
1956
1957	MakeLocate $(1) : $(OBOS_OBJECT_TARGET) ;
1958
1959	LocalClean clean : $(1) ;
1960}
1961
1962actions WriteKernelConfig bind SECTION_FILES
1963{
1964	target="$(1)"
1965	echo "# OpenBeOS Kernel Config File" > "$target"
1966	echo "# Automatically generated - do not edit!" >> "$target"
1967	count=0
1968	for section in "$(SECTION_NAMES)" ; do
1969		count=`expr $count + 1`
1970		eval section$count="$section"
1971	done
1972	i=1
1973	for type in "$(SECTION_TYPES)" ; do
1974		eval type$i="$type"
1975		i=`expr $i + 1`
1976	done
1977	i=1
1978	for file in "$(SECTION_FILES)" ; do
1979		eval file$i="$file"
1980		i=`expr $i + 1`
1981	done
1982	for i in `seq $count` ; do
1983		eval section="\$section$i"
1984		eval type="\$type$i"
1985		eval file="\$file$i"
1986		echo "" >> "$target"
1987		echo "["$section"]" >> "$target"
1988		echo "type="$type >> "$target"
1989		case "$file" in
1990			/*) ;;
1991			*) file=`pwd`/"$file";;
1992		esac
1993		echo "file="$file >> "$target"
1994	done
1995}
1996
1997rule BuildKernel
1998{
1999	# Usage BuildKernel <target> : <config_file> ;
2000	local kernel = $(1) ;
2001	local configFile = $(2) ;
2002	local bootmaker = bootmaker ;
2003
2004	LocalDepends all : $(kernel) ;
2005	Depends $(kernel) : $(configFile) $(bootmaker) ;
2006	LocalClean clean : $(kernel) ;
2007	MakeLocate $(kernel) : $(LOCATE_TARGET) ;
2008
2009	BOOT_MAKER on $(kernel) = $(bootmaker) ;
2010}
2011
2012actions BuildKernel bind BOOT_MAKER
2013{
2014	"$(BOOT_MAKER)" --strip-debug --strip-binary strip "$(2)" -o "$(1)" ;
2015	echo ""
2016	echo "Kernel linked!"
2017	echo ""
2018}
2019
2020rule KernelFloppyImage
2021{
2022	# Usage KernelFloppyImage <target> : <kernel> : <bootblock> ;
2023	local floppy = $(1) ;
2024	local kernel = $(2) ;
2025	local bootblock = $(3) ;
2026	local makeflop = makeflop ;
2027
2028	LocalDepends all : $(floppy) ;
2029	Depends $(floppy) : $(kernel) $(bootblock) $(makeflop) ;
2030	LocalClean clean : $(floppy) ;
2031	MakeLocate $(floppy) : $(OBOS_OBJECT_TARGET) ;
2032
2033	BOOT_BLOCK on $(floppy) = $(bootblock) ;
2034	MAKE_FLOP on $(floppy) = $(makeflop) ;
2035}
2036
2037# This may be a bit verbose, but I think it's useful to show what's
2038# going on, at least in this early stage of development.
2039actions KernelFloppyImage bind BOOT_BLOCK bind MAKE_FLOP
2040{
2041	"$(MAKE_FLOP)" "-p $(shell expr 18 \* 2 \* 512)" "$(BOOT_BLOCK)" "$(2)" "$(1)" ;
2042
2043	echo ""
2044	echo "*************************************************"
2045	echo "*         Kernel build completed!               *"
2046	echo "*    Boot image for a 1.44M floppy created      *"
2047	echo "*************************************************"
2048	echo ""
2049	echo "Floppy image is $(1)"
2050	echo "The following command will write it to a floppy on BeOS"
2051	echo "  dd if=$(1) of=/dev/disk/floppy/raw bs=18k"
2052	echo "Alternatively you can run"
2053	echo "  ./configure --floppy /dev/disk/floppy/raw"
2054	echo "once and build + write the image subsequently via"
2055	echo "  jam installfloppy"
2056	echo ""
2057}
2058
2059rule InstallFloppy
2060{
2061	# InstallFloppy <target> : <floppy>
2062	# "dd"s <floppy> to $(FLOPPY_PATH).
2063
2064	local target = $(1) ;
2065	local floppy = $(2) ;
2066
2067	NotFile $(target) ;
2068	Always $(target) ;
2069	Depends $(target) : $(floppy) ;
2070}
2071
2072actions InstallFloppy
2073{
2074	if [ -z $(FLOPPY_PATH) ] ; then
2075		echo "Can't install floppy: FLOPPY_PATH not set."
2076		echo "run: ./configure --floppy <floppy path>"
2077		echo
2078		exit 0
2079	fi
2080	dd if=$(2) of=$(FLOPPY_PATH) bs=18k
2081}
2082
2083#-------------------------------------------------------------------------------
2084# FreeType 2 specific rules and variables
2085#-------------------------------------------------------------------------------
2086
2087FT2_INCLUDE = [ FDirName $(OBOS_TOP) headers libs freetype2 ] ;
2088FT2_SRC     = [ FDirName $(OBOS_TOP) src libs freetype2 ] ;
2089
2090FT2_LIB     = freetype ;
2091
2092FT2_COMPONENTS ?= gzip       # support for gzip-compressed files.
2093                  autohint   # auto-hinter
2094                  base       # base component (public APIs)
2095                  bdf        # BDF font driver
2096                  cache      # cache sub-system
2097                  cff        # CFF/CEF font driver
2098                  cid        # Postscript CID-keyed font driver
2099		lzw	   # LZW routines
2100                  pcf        # PCF font driver
2101                  pfr        # PFR/TrueDoc font driver
2102                  psaux      # Common Postscript routines module
2103                  pshinter   # Postscript hinter module
2104                  psnames    # Postscript names handling
2105                  raster     # Monochrome rasterizer
2106                  smooth     # Anti-aliased rasterizer
2107                  sfnt       # SFNT-based format support routines
2108                  truetype   # TrueType font driver
2109                  type1      # Postscript Type 1 font driver
2110                  type42     # Postscript Type 42 (embedded TrueType) driver
2111                  winfonts   # Windows FON/FNT font driver
2112                  ;
2113
2114rule UseFreeTypeHeaders
2115{
2116	SubDirHdrs $(FT2_INCLUDE) ;
2117}
2118
2119rule UseFreeTypeObjectHeaders
2120{
2121	# UseFreeTypeObjectHeaders <sources> [ : <objects> ] ;
2122	SourceHdrs $(1) : $(FT2_INCLUDE) : $(2) ;
2123}
2124
2125rule FT2_SubDir
2126{
2127	# FT2_SubDir <dir>
2128	# <dir>: Components of a directory in the original hierarchy.
2129	local dir = $(1) ;
2130	local topDir ;
2131	switch $(dir[1])
2132	{
2133		case "include"	: topDir = $(FT2_INCLUDE) ;
2134		case src		: topDir = $(FT2_SRC) ;
2135		case *			: ECHO "Unknown FreeType2 directory: " $(dir) ;
2136	}
2137	return [ FDirName $(topDir) $(dir[2-]) ] ;
2138}
2139
2140rule FT2_Library
2141{
2142	# FT2_Library <libname> : <sources>
2143	# Builds objects from sources and adds the objects to the list of objects
2144	# to be linked into the library.
2145	# <libname> The name of the library.
2146	# <sources> The sources.
2147
2148	local library = lib$(1).so ;
2149	local sources = $(2) ;
2150	SetupIncludes ;
2151	SetupObjectsDir ;
2152	MakeLocateObjects $(sources) ;
2153	Objects $(sources) ;
2154	LIBRARY_OBJECTS on $(library) += [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
2155}
2156
2157rule FT2_LinkLibrary
2158{
2159	# FT2_LinkLibrary <libname>
2160	# Links the library from the objects build with FT2_LIBRARY before.
2161
2162	local library = lib$(1).so ;
2163	local objects = [ on $(library) return $(LIBRARY_OBJECTS) ] ;
2164	ObjectReferences $(objects) ;
2165	objects = [ FGristFiles $(objects) ] ;
2166	SharedLibraryFromObjects $(1) : $(objects) ;
2167}
2168
2169#-------------------------------------------------------------------------------
2170# Packages for OBOS alpha/beta testers
2171#-------------------------------------------------------------------------------
2172
2173rule Copy
2174{
2175	Depends $(<) : $(>) ;
2176	SEARCH on $(>) = $(SEARCH_SOURCE) ;
2177}
2178
2179actions Copy
2180{
2181	cp -dp "$(>)" "$(<)" ;
2182	if [ -f "$(>)" ] ; then copyattr "$(>)" "$(<)" ; fi ;
2183}
2184
2185rule Packages
2186{
2187	local packagenames = $(1) ;
2188	local packagefiles = $(2) ;
2189	local path = $(3) ;
2190	for name in $(packagenames) {
2191		Package $(name) : $(packagefiles) : $(path) ;
2192    }
2193}
2194
2195rule Package
2196{
2197	local packagename = $(1) ;
2198    local packagefiles = $(2) ;
2199	local path = $(3) ;
2200
2201	local packagezip = $(packagename:S=.zip:G=_packages) ;
2202	local packagedir = [ FDirName $(OBOS_PACKAGE_DIR) $(packagename) ] ;
2203
2204    local installscript = install.sh ;
2205	local packageinstallscript = $(installscript:G=_packages!$(packagename)) ;
2206    local installzip = install.zip ;
2207	local packageinstallzip = $(installzip:G=_packages!$(packagename)) ;
2208
2209    local packageobjectdir
2210    	= [ FDirName $(OBOS_PACKAGE_OBJECT_DIR) $(packagename) ] ;
2211	local packagefiledir =  [ FDirName $(packageobjectdir) $(path) ] ;
2212    local packagefileinstallzip
2213    	= $(installzip:G=_package_objects!$(packagename)) ;
2214
2215	# add the files to the install.zip
2216	local packagefilegrist = [ FGrist _package_files $(packagename) $(path) ] ;
2217    for file in $(packagefiles) {
2218		if $(3[0]) = "boot" {
2219			local packagefile = $(file:G=$(packagefilegrist)) ;
2220			MakeLocate $(packagefile) : $(packagefiledir) ;
2221			Copy $(packagefile) : $(file) ;
2222			Clean cleanPackages : $(packagefile) ;
2223			PackageInstallZip $(packagefileinstallzip) : $(packagefile) ;
2224		} else {
2225			local packagefile = $(file:G=_packages!$(packagename)) ;
2226			MakeLocate $(packagefile) : $(packagedir) ;
2227			Copy $(packagefile) : [ FGristFiles $(file) ] ;
2228			Clean cleanPackages : $(packagefile) ;
2229			Depends $(packagezip) : $(packagefile) ;
2230		}
2231	}
2232
2233	# general setup for this packages -- only on first invocation
2234	if ! $(_setup_$(packagename)) {
2235		_setup_$(packagename) = true ;
2236
2237		NotFile $(packagename) ;
2238		LocalDepends packages : $(packagename) ;
2239
2240		MakeLocate $(packagezip) : $(OBOS_PACKAGE_DIR) ;
2241		MakeLocate $(packageinstallscript) : $(packagedir) ;
2242		MakeLocate $(packageinstallzip) : $(packagedir) ;
2243		MakeLocate $(packagefileinstallzip) : $(packageobjectdir) ;
2244
2245		PackageInstallScript $(packageinstallscript) : $(packagedir) ;
2246		LinkInstallZip $(packageinstallzip) : $(packagefileinstallzip) ;
2247		Depends $(packagename) : $(packagezip) ;
2248		PackageZip $(packagezip) : $(packagedir)
2249			: $(packageinstallscript) $(packageinstallzip) ;
2250	}
2251
2252}
2253
2254rule PackageZip
2255{
2256	local dir = $(2:G=dir) ;
2257	Depends $(1) : $(dir) $(3) ;
2258	Clean cleanPackages : $(1) ;
2259	PackageZip1 $(1) : $(dir) ;
2260}
2261
2262actions together PackageZip1 {
2263	cd "$(OBOS_PACKAGE_DIR)" ;
2264	zip -rq "$(1:BS)" "$(2:BS)" ;
2265}
2266
2267rule PackageInstallScript
2268{
2269	MakeLocate $(1) : $(2) ;
2270	Clean cleanPackages : $(1) ;
2271	PackageInstallScript1 $(1) : $(2:G=dir) ;
2272}
2273
2274actions together PackageInstallScript1
2275{
2276echo '#!/bin/sh
2277base=`dirname "$0"`
2278cd "$base"
2279if [ -n "$TTY" ]
2280then
2281    unzip -d / install.zip
2282else
2283    response=`alert "Would you like to automatically overwrite existing files, or receive a prompt?" "Overwrite" "Prompt"`
2284    if [ $response == "Overwrite" ]
2285    then
2286        unzip -od / install.zip
2287        alert "Finished installing" "Thanks"
2288    else
2289        if [ -e /boot/beos/apps/Terminal ]
2290        then
2291            terminal=/boot/beos/apps/Terminal
2292        else
2293            terminal=`query Terminal | head -1`
2294        fi
2295        $terminal -t "installer" /bin/sh "$0"
2296    fi
2297fi' > "$(1)" ;
2298	chmod 755 "$(1)" ;
2299}
2300
2301rule PackageInstallZip
2302{
2303	Depends $(1) : $(2) ;
2304	Clean cleanPackages : $(1) ;
2305}
2306
2307actions together PackageInstallZip
2308{
2309	cd "$(1:P)" ;
2310	zip -rqy "$(1:BS)" boot ;
2311}
2312
2313rule LinkInstallZip
2314{
2315	Depends $(1) : $(2) ;
2316	Clean cleanPackages : $(1) ;
2317}
2318
2319actions together LinkInstallZip
2320{
2321	ln -sf "`pwd`/$(2)" "$(1)" ;
2322}
2323
2324rule SubIncludeGPL
2325{
2326	# SubInclude rule that can be used to conditionally include GPL licensed add-ons
2327	if $(INCLUDE_GPL_ADDONS) = 1 {
2328		SubInclude $(1) ;
2329	}
2330}
2331