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