xref: /haiku/Jamrules (revision 5dc4e1ef105c69b599627c9ae7787f6a1b7a0f8b)
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
38{
39	local buildConfig = [ GLOB $(OBOS_BUILD_DIR) : BuildConfig ] ;
40	if ! $(buildConfig)
41	{
42		ECHO "No BuildConfig found in $(OBOS_BUILD_DIR)!" ;
43		EXIT "Run ./configure in the source tree's root directory first!" ;
44	}
45	LOCATE on BuildConfig = $(OBOS_BUILD_DIR) ;
46	include BuildConfig ;
47}
48
49# Save the platform default headers.
50PLATFORM_DEFAULT_HEADERS = $(HDRS) ;
51
52# We do not include any local BeOS system headers by default
53CCFLAGS += -nostdinc ;
54C++FLAGS += -nostdinc ;
55
56# Determine if we're building on PPC or x86
57# Determine mimetype of executable
58# Cross compiling can come later
59
60TARGET_CPU ?= $(OSPLAT:L) ;
61OBOS_VERSION ?= R1 ;
62
63switch $(TARGET_CPU) {
64	case ppc :
65	{
66		if $(METROWERKS) {
67			# at least parts of OpenBeOS still can be compiled with
68			# the Metrowerks compiler on BeOS/PPC
69			OBOS_TARGET_TYPE ?= "application/x-be-executable" ;
70		} else {
71			OBOS_TARGET_TYPE ?= "application/x-vnd.Be-elfexecutable" ;
72		}
73		DEFINES += D__POWERPC__ ;
74	}
75	case x86 :
76	{
77		# nothing special to do here...
78	}
79	case * :
80		Exit "Currently unsupported build platform:" $(TARGET_CPU) ;
81}
82
83# set target specific variables
84{
85	#Echo "Building for" $(TARGET_CPU) ;
86
87	OBOS_TARGET ?= $(TARGET_CPU).$(OBOS_VERSION) ;
88	OBOS_TARGET_TYPE ?= "application/x-vnd.Be-elfexecutable" ;
89	OBOS_ARCH ?= $(TARGET_CPU) ;
90	OBOS_TARGET_DEFINE ?= "ARCH_"$(TARGET_CPU) ;
91}
92
93# Enable warnings only if WARNINGS is defined
94# Should be enabled by default later
95#
96if $(WARNINGS) {
97	# For an explanation of the different warning options, see:
98	# http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_2.html
99	# to get even more warnings, add:
100	# -Wwrite-strings  	(doesn't work well with some Be headers)
101	# -Wundef			(dito)
102	# -Wconversion		(gets you many warnings about implicit conversions)
103	# -W				(gets you even more warnigs)
104	CCFLAGS += -Wall -Wno-multichar -Wmissing-prototypes ;
105	CCFLAGS += -Wpointer-arith -Wcast-align -Wsign-compare ;
106	C++FLAGS += -Wall -Wno-multichar -Wmissing-prototypes -Wno-ctor-dtor-privacy -Woverloaded-virtual ;
107	C++FLAGS += -Wpointer-arith -Wcast-align -Wsign-compare ;
108}
109
110KERNEL_CCFLAGS ?= -Wall -Wno-multichar -Wmissing-prototypes -finline -nostdinc ;
111KERNEL_CCFLAGS += -fno-builtin -D$(OBOS_TARGET_DEFINE) ;
112KERNEL_CCFLAGS += -DBOCHS_DEBUG_HACK=$(BOCHS_DEBUG_HACK) ;
113
114
115# We might later want to introduce debug levels or handle the whole issue
116# differently. For now there's only on or off.
117#
118if $(DEBUG) {
119	OPTIM ?= -O0 ;
120	CCFLAGS += -g -DDEBUG=$(DEBUG) ;
121	C++FLAGS += -g -DDEBUG=$(DEBUG)  ;
122	KERNEL_CCFLAGS += -g -DDEBUG=$(DEBUG) ;
123	LINKFLAGS += -g ;
124} else {
125	OPTIM ?= -O2 ;
126}
127#
128# To disable for the tests OPTIM and DEBUG are overridden, set the environment
129# variable NO_TEST_DEBUG.
130
131# Instructs the Library rule to not make its object files temporary.
132# This is need as some objects are used in a static library and for an
133# executable.
134KEEPOBJS = true ;
135
136AR = ar r ;
137
138# If no OBOS_OBJECT_TARGET is not defined yet, use our default directory and
139# include our "OBOS_TARGET" as subdirectory in there (to prevent different
140# builds mixing objects from different targets).
141if ! $(OBOS_OBJECT_TARGET) {
142	OBOS_OBJECT_TARGET ?= [ FDirName $(OBOS_TOP) objects $(OBOS_TARGET) ] ;
143}
144
145# If no OBOS_DISTRO_TARGET is not defined yet, use our default directory and
146# include our "OBOS_TARGET" as subdirectory in there (to prevent different
147# builds mixing executables from different targets).
148if ! $(OBOS_DISTRO_TARGET) {
149	OBOS_DISTRO_TARGET ?= [ FDirName $(OBOS_TOP) distro $(OBOS_TARGET) ] ;
150}
151
152# Set our version number if not already set and mark it as a developer build
153if ! $(OBOS_BUILD_VERSION) {
154	OBOS_BUILD_VERSION ?= "1 0 0 a 1" ;
155	OBOS_BUILD_DESCRIPTION ?= "Developer Build" ;
156}
157
158# If OBOS_BUILD_VERSION is set, but OBOS_BUILD_DESCRIPTION isn't, mark it as
159# an unknown build.
160if ! $(OBOS_BUILD_DESCRIPTION) {
161	OBOS_BUILD_DESCRIPTION ?= "Unknown Build" ;
162}
163
164# Relative subdirs for distro dir (these are for *INTERNAL* use by the following rules only!)
165OBOS_APPS_DIR   ?= [ FDirName $(OBOS_DISTRO_TARGET) beos apps ] ;
166OBOS_BIN_DIR    ?= [ FDirName $(OBOS_DISTRO_TARGET) beos bin ] ;
167OBOS_PREFS_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos preferences ] ;
168OBOS_SERVER_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system servers ] ;
169OBOS_ADDON_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system add-ons ] ;
170OBOS_SHLIB_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system lib ] ;
171OBOS_STLIB_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system lib ] ;
172OBOS_KERNEL_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system ] ;
173OBOS_TEST_DIR   ?= [ FDirName $(OBOS_TOP) tests ] ;
174
175OBOS_KERNEL_CONFIG = config.$(OBOS_ARCH).ini ;
176OBOS_KERNEL = kernel.$(OBOS_ARCH) ;
177OBOS_FLOPPY = floppy.$(OBOS_ARCH) ;
178
179rule SetupIncludes
180{
181	# XXX add "opengl" later
182	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 ;
183
184	# Overwrite any exiting content when changing HDRS. This rule may be invoked multiple times.
185
186	# Use headers directory, to allow to do things like include <posix/string.h>
187	HDRS = [ FDirName $(OBOS_TOP) headers ] ;
188
189	# Use posix headers directory
190	HDRS += [ FDirName $(OBOS_TOP) headers posix ] ;
191
192	# Use public OS header directories
193	HDRS += [ PublicHeaders $(os_includes) ] ;
194
195	# Used as a fallback, the R5 header directories (we should remove this as soon as possible)
196	HDRS += /boot/develop/headers/posix /boot/develop/headers/cpp ;
197
198	# The platform dependent headers.
199	HDRS += $(PLATFORM_HEADERS) ;
200}
201
202rule SetupR5Includes
203{
204	# Unsets HDRS, so that the OBOS headers do not `shadow' the system headers.
205	HDRS = ;
206}
207
208rule SetupDefaultIncludes
209{
210	# Resets HDRS to the default headers for the build platform.
211	HDRS = $(PLATFORM_DEFAULT_HEADERS) ;
212}
213
214#-------------------------------------------------------------------------------
215# Things Jam needs in order to work :)
216#-------------------------------------------------------------------------------
217
218rule Object
219{
220	# This is basically the original Jambase 2.4 Object rule stripped by
221	# comments. Only the final switch statement has been changed to allow
222	# intermediate C++ files for Yacc and Lex.
223
224	LocalClean clean : $(<) ;
225
226	MakeLocate $(<) : $(LOCATE_TARGET) ;
227	SEARCH on $(>) = $(SEARCH_SOURCE) ;
228
229	HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ;
230
231	HDRRULE on $(>) = HdrRule ;
232	HDRSCAN on $(>) = $(HDRPATTERN) ;
233	HDRSEARCH on $(>) =
234		$(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ;
235
236	HDRGRIST on $(>) = $(HDRGRIST) ;
237
238	DEFINES on $(<) += $(DEFINES) ;
239
240	# if source is not .c, generate .c with specific rule
241
242	switch $(>:S)
243	{
244	    case .asm : As $(<) : $(>) ;
245	    case .c :	Cc $(<) : $(>) ;
246	    case .C :	C++ $(<) : $(>) ;
247	    case .cc :	C++ $(<) : $(>) ;
248	    case .cpp : C++ $(<) : $(>) ;
249	    case .f :	Fortran $(<) : $(>) ;
250	    case .l :	if [ on $(2) return $(GENERATE_C++) ] {
251						C++ $(<) : $(<:S=.cpp) ;
252						LexC++ $(<:S=.cpp) : $(>) ;
253					} else {
254						Cc $(<) : $(<:S=.c) ;
255						Lex $(<:S=.c) : $(>) ;
256					}
257	    case .s :	As $(<) : $(>) ;
258	    case .y :	if [ on $(2) return $(GENERATE_C++) ] {
259						C++ $(<) : $(<:S=.cpp) ;
260						Bison $(<:S=.cpp) : $(>) ;
261					} else {
262						Cc $(<) : $(<:S=$(YACCGEN)) ;
263						Yacc $(<:S=$(YACCGEN)) : $(>) ;
264					}
265	    case * :	UserObject $(<) : $(>) ;
266	}
267}
268
269rule UserObject
270{
271	switch $(2)
272	{
273	case *.S    : assemble $(1) : $(2) ;
274	case *.o    : return ;
275	case *      : ECHO "unknown suffix on" $(2) ;
276	}
277}
278
279# Override the default to give "prettier" command lines.
280actions Cc
281{
282	$(CC) -c "$(2)" $(CCFLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
283}
284
285actions C++
286{
287	$(C++) -c "$(2)" $(C++FLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
288}
289
290
291#-------------------------------------------------------------------------------
292# General High-level OBOS target rules
293#-------------------------------------------------------------------------------
294
295rule App
296{
297	# App <name> : <sources> ;
298	SetupIncludes ;
299	SetupObjectsDir ;
300	Main $(<) : $(>) ;
301	MakeLocate $(<) : $(OBOS_APPS_DIR) ;
302}
303
304rule BinCommand
305{
306	# BinCommand <name> : <sources> : <libraries> ;
307	SetupIncludes ;
308	SetupObjectsDir ;
309	Main $(1) : $(2) ;
310	MakeLocate $(1) : $(OBOS_BIN_DIR) ;
311	LinkSharedOSLibs $(1) : $(3) ;
312}
313
314rule StdBinCommands
315{
316	# StdBinCommands <sources> : <libs> ;
317	SetupIncludes ;
318	SetupObjectsDir ;
319	local libs = $(2) ;
320	local source ;
321	for source in $(1)
322	{
323		local target = $(source:S=) ;
324		target = [ FGristFiles $(target) ] ;
325
326		BinCommand $(target) : $(source) : $(libs) ;
327	}
328}
329
330rule Preference
331{
332	# Preference <name> : <sources> ;
333	SetupIncludes ;
334	SetupObjectsDir ;
335	Main $(<) : $(>) ;
336	MakeLocate $(<) : $(OBOS_PREFS_DIR) ;
337}
338
339rule Server
340{
341	# Server <name> : <sources> ;
342
343	SetupIncludes ;
344	SetupObjectsDir ;
345	Main $(<) : $(>) ;
346	MakeLocate $(<) : $(OBOS_SERVER_DIR) ;
347}
348
349# test pseudo targets
350NOTFILE obostests ;
351NOTFILE r5tests ;
352
353rule CommonTestLib
354{
355	# CommonTestLib <target> : <sources> : <obos libraries>
356	#	: <r5 libraries> : <test libraries> : <public headers>;
357	# Builds a unit test for both OBOS and R5 modules.
358	# <target> The name of the target.
359	# <sources> The list of sources.
360	# <obos libraries> A list of link libraries for the OBOS tests (as passed
361	# to LinkSharedOSLibs).
362	# <r5 libraries> A list of link libraries for the R5 tests (as passed
363	# to LinkSharedOSLibs).
364	# <test libraries> A list of link libraries for both OBOS tests and R5 tests
365	# that have a common name (i.e. specify libx.so and the OBOS tests will link
366	# to libx.so and the R5 tests will link to libx_r5.so).
367	# <public headers> A list of public header dirs (as passed to
368	# UsePublicHeaders).
369
370	TestLib $(1) : $(2) : [ FDirName $(OBOS_TEST_DIR) unittester lib ] : $(3) $(5) : $(6) ;
371	R5TestLib $(1) : $(2) : [ FDirName $(OBOS_TEST_DIR) unittester_r5 lib ] : $(4) [ R5SharedLibraryNames $(5) ] ;
372}
373
374rule TestLib
375{
376	# TestLib <target> : <sources> : <dest> : <libraries> : <public headers>
377	# Builds a unit test library for an OBOS module.
378	# <target> The name of the target.
379	# <sources> The list of sources.
380	# <dest> The directory for the target (as passed to FDirName).
381	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
382	# <public headers> A list of public header dirs (as passed to
383	# UsePublicHeaders).
384
385	local target = $(1) ;
386	local sources = $(2) ;
387	local dest = $(3) ;
388	local libraries = $(4) ;
389	local headerDirs = $(5) ;
390	local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
391
392	# Our Main replacement.
393	MainFromObjects $(target) : $(objects) ;
394	TestObjects $(sources) : $(headerDirs) ;
395
396	MakeLocate $(target) : $(dest) ;
397	Depends $(target) : libcppunit.so ;
398	Depends obostests : $(target) ;
399	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
400	LINKFLAGS on $(target) = $(LINKFLAGS) -nostart -Xlinker -soname=\"$(target)\" ;
401}
402
403rule R5TestLib
404{
405	# R5TestLib <target> : <sources> : <dest> : <libraries>
406	# Builds a unit test for an R5 module. "_r5" is appended to the object
407	# and the target name.
408	# <target> The name of the target.
409	# <sources> The list of sources.
410	# <dest> The directory for the target (as passed to FDirName).
411	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
412
413	local target = $(1:B)_r5$(1:S) ;
414	local sources = $(2) ;
415	local dest = $(3) ;
416	local libraries = $(4) ;
417	local objects = [ R5ObjectNames $(sources) ] ;
418
419	# Our Main replacement.
420	MainFromObjects $(target) : $(objects) ;
421	TestObjects $(sources) : : true ;
422
423	MakeLocate $(target) : $(dest) ;
424	Depends $(target) : libcppunit.so ;
425	Depends r5tests : $(target) ;
426	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
427	LINKFLAGS on $(target) = $(LINKFLAGS) -nostart -Xlinker -soname=\"$(target)\" ;
428}
429
430rule CommonUnitTest
431{
432	# CommonUnitTest <target> : <sources> : <dest> : <obos libraries>
433	#	: <r5 libraries> : <public headers>;
434	# Builds a unit test for both OBOS and R5 modules.
435	# <target> The name of the target.
436	# <sources> The list of sources.
437	# <dest> The directory for the target (as passed to FDirName).
438	# <obos libraries> A list of link libraries for the OBOS tests (as passed
439	# to LinkSharedOSLibs).
440	# <r5 libraries> A list of link libraries for the R5 tests (as passed
441	# to LinkSharedOSLibs).
442	# <public headers> A list of public header dirs (as passed to
443	# UsePublicHeaders).
444
445	UnitTest $(1) : $(2) : $(3) : $(4) : $(6) ;
446	R5UnitTest $(1) : $(2) : $(3) : $(5) ;
447}
448
449rule UnitTest
450{
451	# UnitTest <target> : <sources> : <dest> : <libraries> : <public headers>
452	# Builds a unit test for an OBOS module.
453	# <target> The name of the target.
454	# <sources> The list of sources.
455	# <dest> The directory for the target (as passed to FDirName).
456	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
457	# <public headers> A list of public header dirs (as passed to
458	# UsePublicHeaders).
459
460	local target = $(1) ;
461	local sources = $(2) ;
462	local dest = $(3) ;
463	local libraries = $(4) ;
464	local headerDirs = $(5) ;
465	local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
466
467	# Our Main replacement.
468	MainFromObjects $(target) : $(objects) ;
469	TestObjects $(sources) : $(headerDirs) ;
470
471	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(dest) ] ;
472	Depends $(target) : libcppunit.so ;
473	Depends obostests : $(target) ;
474	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
475}
476
477rule R5UnitTest
478{
479	# R5UnitTest <target> : <sources> : <dest> : <libraries>
480	# Builds a unit test for an R5 module. "_r5" is appended to the object
481	# and the target name.
482	# <target> The name of the target.
483	# <sources> The list of sources.
484	# <dest> The directory for the target (as passed to FDirName).
485	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
486
487	local target = $(1)_r5 ;
488	local sources = $(2) ;
489	local dest = $(3) ;
490	local libraries = $(4) ;
491	local objects = [ R5ObjectNames $(sources) ] ;
492
493	# Our Main replacement.
494	MainFromObjects $(target) : $(objects) ;
495	TestObjects $(sources) : : true ;
496
497	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(dest) ] ;
498	Depends $(target) : libcppunit.so ;
499	Depends r5tests : $(target) ;
500	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
501}
502
503rule R5ObjectNames
504{
505	# R5ObjectNames <sources> ;
506	# Returns a list of gristed object names given a list of source file names.
507	# Moreover each object names gets "_r5" inserted before the object suffix.
508	local objects = $(1:S=)_r5 ;
509	return [ FGristFiles $(objects:S=$(SUFOBJ)) ] ;
510}
511
512rule R5Objects
513{
514	# R5Objects <sources>
515	# Similar to Objects, but appends "_r5" to the object file names and
516	# removes `-nostdinc' from the CC and C++ flags to enable system headers.
517	# <sources> The source files.
518
519	# Remove `-nostdinc' from CCFLAGS and C++FLAGS.
520	local oldCCFLAGS = $(CCFLAGS) ;
521	local oldC++FLAGS = $(C++FLAGS) ;
522	CCFLAGS = [ Filter $(CCFLAGS) : -nostdinc ] ;
523	C++FLAGS = [ Filter $(C++FLAGS) : -nostdinc ] ;
524
525	local sources = $(1) ;
526	local source ;
527	for source in [ FGristFiles $(sources) ]
528	{
529		local object = [ R5ObjectNames $(source) ] ;
530		Object $(object) : $(source) ;
531		LocalDepends obj : $(object) ;
532	}
533
534	# Reset CCFLAGS and C++FLAGS to original values.
535	CCFLAGS = $(oldCCFLAGS) ;
536	C++FLAGS = $(oldC++FLAGS) ;
537}
538
539rule TestObjects
540{
541	# TestLib <sources> : <public headers> : <r5>
542	# Compiles objects for tests.
543	# <sources> The list of sources.
544	# <public headers> A list of public header dirs (as passed to
545	# UsePublicHeaders).
546	# <r5> If set, "_r5" is appended to the object file names and
547	# <public headers> is ignored. Furthermore the pre-processor macro
548	# TEST_R5 is defined, TEST_OBOS otherwise.
549
550	local sources = $(1) ;
551	local headerDirs = $(2) ;
552	local r5 = $(3) ;
553	local objects ;
554
555	# Turn optimization off.
556	if ! $(NO_TEST_DEBUG) {
557		local optim = $(OPTIM) ;
558		OPTIM = ;
559	}
560
561	SetupObjectsDir ;
562
563	# compile
564	if $(r5) {
565		SetupR5Includes ;
566		objects = [ R5ObjectNames $(sources) ] ;
567		R5Objects $(sources) ;
568	} else {
569		SetupIncludes ;
570		objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
571		Objects $(sources) ;
572	}
573
574	# set headers/defines
575	UseCppUnitObjectHeaders $(sources) : $(objects) ;
576	if $(r5) {
577		ObjectDefines $(objects) : TEST_R5 ;
578	} else {
579		UsePublicObjectHeaders $(sources) : $(headerDirs) : $(objects) ;
580		ObjectDefines $(objects) : TEST_OBOS ;
581	}
582
583	if ! $(NO_TEST_DEBUG) {
584		# Turn debugging on. That is usually desired for test code.
585		ObjectCcFlags $(objects) : "-g" ;
586		ObjectC++Flags $(objects) : "-g" ;
587
588		# Turn optimization on again.
589		OPTIM = $(optim) ;
590	}
591}
592
593rule R5SharedLibraryNames
594{
595	# R5SharedLibraryNames <sources> ;
596	# Returns a list of shared library names given a list of file names. NO
597	# GRISTING IS PERFORMED :-) However, each library names gets "_r5" inserted
598	# before the shared lib suffix.
599	return $(1:S=)_r5.so ;
600}
601
602rule SimpleTest
603{
604	# UnitTest <target> : <sources> : <libraries>
605	# Builds a unit test for an OBOS module.
606	# <target> The name of the target.
607	# <sources> The list of sources.
608	# <dest> The directory for the target (as passed to FDirName).
609	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
610	# <public headers> A list of public header dirs (as passed to
611	# UsePublicHeaders).
612
613	local target = $(1) ;
614	local sources = $(2) ;
615	local libraries = $(3) ;
616	local relPath = [ FRelPath src tests : $(SUBDIR_TOKENS) ] ;
617
618	# Turn optimization off.
619	if ! $(NO_TEST_DEBUG) {
620		local optim = $(OPTIM) ;
621		OPTIM = ;
622	}
623
624	SetupIncludes ;
625	SetupObjectsDir ;
626	MakeLocateObjects $(sources) ;
627	Main $(target) : $(sources) ;
628	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(relPath) ] ;
629	Depends obostests : $(target) ;
630	LinkSharedOSLibs $(target) : $(libraries) ;
631	ObjectDefines $(sources) : TEST_OBOS ;
632
633	if ! $(NO_TEST_DEBUG) {
634		# Turn debugging on. That is usually desired for test code.
635		ObjectCcFlags $(sources) : "-g" ;
636		ObjectC++Flags $(sources) : "-g" ;
637
638		# Turn optimization on again.
639		OPTIM = $(optim) ;
640	}
641}
642
643rule Addon
644{
645	# Addon <name> : <relpath> : <sources> : <is executable> : <libraries> ;
646	# <name>: Name of the add-on.
647	# <relpath>: Path where the add-on shall live relative to the add-on dir.
648	# <sources>: Source files.
649	# <is executable>: true, if the target shall be executable as well.
650	# <libraries>: Libraries to be linked against.
651
652	local isExecutable = $(4) ;
653
654	SetupIncludes ;
655	SetupObjectsDir ;
656	Main $(1) : $(3) ;
657
658	# Create output dir path for addon
659	local targetdir;
660	targetdir = [ FDirName $(OBOS_ADDON_DIR) $(2) ] ;
661
662	MakeLocate $(1) : $(targetdir) ;
663
664	local linkFlags = -Xlinker -soname=\"$(1)\" ;
665	if $(isExecutable) != true {
666		linkFlags = -nostart $(linkFlags) ;
667	}
668	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] $(linkFlags) ;
669	LinkSharedOSLibs $(1) : $(5) ;
670}
671
672rule R5KernelAddon
673{
674	# R5KernelAddon <name> : <relpath> : <sources> ;
675
676	local sources = $(3) ;
677
678	Addon $(1) : $(2) : $(3) ;
679	ObjectCcFlags $(sources) : -D_KERNEL_MODE=1 -no-fpic ;
680	ObjectC++Flags $(sources) : -D_KERNEL_MODE=1 -no-fpic
681								-fno-exceptions -fno-rtti ;
682	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -nostdlib ;
683	LinkSharedOSLibs $(1) : /boot/develop/lib/x86/_KERNEL_ ;
684}
685
686rule Translator
687{
688	# Translator <name> : <sources> ;
689	SetupIncludes ;
690	SetupObjectsDir ;
691	Main $(1) : $(2) ;
692
693	# Create output dir path for translator
694	local targetdir;
695	targetdir = [ FDirName $(OBOS_ADDON_DIR) translators ] ;
696	MakeLocate $(1) : $(targetdir) ;
697}
698
699rule MakeLocateObjects
700{
701	# MakeLocateObjects <sources_or_objects> ;
702
703	local _objs = [ FGristFiles $(1:S=$(SUFOBJ)) ] ;
704
705	for o in $(_objs)
706	{
707		local dir = $(o:D) ;
708		if $(dir) {
709			MakeLocate $(o) : [ FDirName $(LOCATE_TARGET) $(dir) ] ;
710		} else {
711			MakeLocate $(o) : $(LOCATE_TARGET) ;
712		}
713	}
714}
715
716rule StaticLibrary
717{
718	# StaticLibrary <name> : <sources> ;
719
720	SetupIncludes ;
721	SetupObjectsDir ;
722	MakeLocateObjects $(2) ;
723	Library lib$(<).a : $(>) ;
724	MakeLocate lib$(<).a : $(OBOS_STLIB_DIR) ;
725}
726
727rule MergeObjectFromObjects
728{
729	# MergeObjectFromObjects <name> : <objects> ;
730	MakeLocate $(1) : $(LOCATE_TARGET) ;
731	Depends $(<) : $(>) ;
732	LINK on $(1) = ld ;
733	MergeObjectFromObjects1 $(1) : [ FGristFiles $(2) ] ;
734}
735
736actions MergeObjectFromObjects1
737{
738	$(LINK) -r $(2) -o $(1) ;
739}
740
741rule MergeObject
742{
743	# MergeObject <name> : <sources> ;
744	SetupIncludes ;
745	SetupObjectsDir ;
746	MakeLocateObjects $(2) ;
747	Objects $(2) ;
748	MergeObjectFromObjects $(1) : $(2:S=$(SUFOBJ)) ;
749}
750
751rule SharedLibraryFromObjects
752{
753	# SharedLibraryFromObjects <name> : <objects> : <libraries> ;
754	local _lib = lib$(1).so ;
755	MainFromObjects $(_lib) : $(2) ;
756	MakeLocate $(_lib) : $(OBOS_SHLIB_DIR) ;
757	LINKFLAGS on $(_lib) = [ on $(_lib) return $(LINKFLAGS) ]
758						   -nostart -Xlinker -soname=\"$(_lib)\" ;
759	LinkSharedOSLibs $(_lib) : $(3) ;
760}
761
762rule SharedLibrary
763{
764	# SharedLibrary <name> : <sources> : <libraries> ;
765	SetupIncludes ;
766	SetupObjectsDir ;
767	MakeLocateObjects $(2) ;
768	Objects $(2) ;
769	SharedLibraryFromObjects $(1) : $(2:S=$(SUFOBJ)) : $(3) ;
770}
771
772rule LinkSharedOSLibs
773{
774	# LinkSharedOSLibs <name> : <libs> ;
775	# Valid elements for <libs> are e.g. "be" or "libopenbeos.so" or
776	# "/boot/.../libfoo.so". If the basename starts with "lib" or the thingy
777	# has a dirname or grist, it is added to the NEEDLIBS variable (i.e. the
778	# file will be bound!), otherwise it is prefixed "-l" and added to
779	# LINKLIBS.
780
781	for i in $(>)
782	{
783		local isfile = ;
784		if $(i:D) || $(i:G) {
785			isfile = true ;
786		} else {
787			switch $(i:B)
788			{
789				case _APP_ : isfile = true ;
790				case _KERNEL_ : isfile = true ;
791				case *.so     : isfile = true ;
792				case *.a      : isfile = true ;
793				case lib*	: isfile = true ;
794				case *	: isfile = ;
795			}
796		}
797		if $(isfile) {
798			NEEDLIBS on $(1) = [ on $(1) return $(NEEDLIBS) ] $(i) ;
799			Depends $(1) : $(i) ;
800		} else {
801			LINKLIBS on $(1) = [ on $(1) return $(LINKLIBS) ] -l$(i) ;
802		}
803	}
804}
805
806rule LinkStaticOSLibs
807{
808	# LinkStaticOSLibs <name> : <libs> ;
809
810	for i in $(>)
811	{
812		LINKLIBS on $(<) = $(LINKLIBS) -l $(i) ;
813	}
814}
815
816rule AddResources
817{
818	# AddResources <name> : <resourcefiles> ;
819
820	local resfiles = [ FGristFiles $(2) ] ;
821	SEARCH on $(resfiles) += $(SEARCH_SOURCE) ;
822
823	for file in $(resfiles) {
824		if $(file:S) = .rdef {
825			local rdef = $(file) ;
826			file = $(rdef:S=.rsrc) ;
827			ResComp $(file) : $(rdef) ;
828		}
829		RESFILES on $(1) += $(file) ;
830	}
831}
832
833rule ResComp
834{
835	# ResComp <resource file> : <rdef file> ;
836	#
837	# <resource file> and <rdef file> must be gristed.
838
839	SetupObjectsDir ;
840
841	SEARCH on $(2) += $(SEARCH_SOURCE) ;
842	MakeLocate $(1) : $(LOCATE_TARGET) ;
843	Depends $(1) : $(2) rc ;
844	LocalClean clean : $(1) ;
845	ResComp1 $(1) : rc $(2) ;
846}
847
848actions ResComp1
849{
850	$(2[1]) -o $(1) $(2[2-])
851}
852
853rule SourceHdrs
854{
855	# SourceHdrs <sources> : <headers> [ : <gristed objects> ] ;
856	#
857	# Is a wrapper for ObjectHdrs, that passes <sources> and <headers> or,
858	# if supplied <objects> and <headers>, and also adjusts HDRSEARCH (not
859	# done by ObjectHdrs).
860
861	local sources = [ FGristFiles $(1) ] ;
862	local headers = $(2) ;
863	local objects = $(3) ;
864
865	if $(objects) {
866		ObjectHdrs $(objects) : $(headers) ;
867	} else {
868		ObjectHdrs $(sources) : $(headers) ;
869	}
870
871	# Also add the header search dirs to HDRSEARCH. Note, that these dirs
872	# will be listed after the STDHDRS (if any), but that's better than not
873	# being listed at all.
874	HDRSEARCH on $(sources) += $(headers) ;
875}
876
877rule PublicHeaders
878{
879	# PublicHeaders <group list>
880	#
881	# Returns the directory names for the public header dirs identified by
882	# <group list>.
883
884	local list = $(1) ;
885	local dirs = [ FDirName $(OBOS_TOP) headers os ] ;
886
887	for i in $(list) {
888		dirs += [ FDirName $(OBOS_TOP) headers os $(i) ] ;
889	}
890	return $(dirs) ;
891}
892
893rule PrivateHeaders
894{
895	# PrivateHeaders <group list>
896	#
897	# Returns the directory names for the private header dirs identified by
898	# <group list>.
899
900	local list = $(1) ;
901	local dirs ;
902	for i in $(list) {
903		dirs += [ FDirName $(OBOS_TOP) headers private $(i) ] ;
904	}
905	return $(dirs) ;
906}
907
908rule LibraryHeaders
909{
910	# LibraryHeaders <group list>
911	#
912	# Returns the directory names for the library header dirs identified by
913	# <group list>.
914
915	local list = $(1) ;
916	local dirs ;
917	for i in $(list) {
918		dirs += [ FDirName $(OBOS_TOP) headers libs $(i) ] ;
919	}
920	return $(dirs) ;
921}
922
923rule ArchHeaders
924{
925	# usage: ArchHeaders <arch> ;
926	#
927	# <arch> specifies the architecture (e.g. x86).
928
929	return [ FDirName $(OBOS_TOP) headers private kernel arch $(1) ] ;
930}
931
932rule UsePublicHeaders
933{
934	# XXX changed to do nothing
935}
936
937rule UsePublicObjectHeaders
938{
939	# UsePublicObjectHeaders <sources> : <group list> [ : <objects> ] ;
940	#
941	# Adds the public C header dirs given by <group list> to the header search
942	# dirs of either the object targets of <sources> or if supplied to
943	# <objects>. Also adjusts HDRSEARCH of <sources>.
944	# NOTE: This rule must be invoked *after* the rule that builds the objects.
945
946	SourceHdrs $(1) : [ PublicHeaders $(2) ] : $(3) ;
947}
948
949rule UsePrivateHeaders
950{
951	# UsePrivateHeaders <group list> ;
952	#
953	# Adds the private C header dirs given by <group list> to the header search
954	# dirs of the subdirectory.
955	# NOTE: This rule must be invoked *before* the rule that builds the objects.
956
957	UseHeaders [ PrivateHeaders $(1) ] ;
958}
959
960rule UsePrivateObjectHeaders
961{
962	# UsePrivateObjectHeaders <sources> : <group list> [ : <objects> ] ;
963	#
964	# Adds the private C header dirs given by <group list> to the header search
965	# dirs of either the object targets of <sources> or if supplied to
966	# <objects>. Also adjusts HDRSEARCH of <sources>.
967	# NOTE: This rule must be invoked *after* the rule that builds the objects.
968
969	SourceHdrs $(1) : [ PrivateHeaders $(2) ] : $(3) ;
970}
971
972rule UseHeaders
973{
974	# UseHeaders <headers> ;
975	#
976	# Adds the C header dirs <headers> to the header search
977	# dirs of the subdirectory.
978	# NOTE: This rule must be invoked *before* the rule that builds the objects.
979
980	local header ;
981	for header in $(1) {
982		SubDirHdrs $(header) ;
983	}
984}
985
986rule UseCppUnitHeaders
987{
988	SubDirHdrs [ FDirName $(OBOS_TOP) headers tools cppunit ] ;
989}
990
991rule UseCppUnitObjectHeaders
992{
993	# UseCppUnitObjectHeaders <sources> [ : <objects> ] ;
994	SourceHdrs $(1) : [ FDirName $(OBOS_TOP) headers tools cppunit ] : $(2) ;
995}
996
997rule UseArchHeaders
998{
999	# usage: UseArchHeaders <arch> ;
1000	#
1001	# <arch> specifies the architecture (e.g. x86).
1002	# NOTE: This rule must be invoked *before* the rule that builds the objects.
1003
1004	local headers = [ ArchHeaders $(1) ] ;
1005	local opt = -D$(OBOS_TARGET_DEFINE) ;
1006
1007	SubDirCcFlags $(opt)  ;
1008	SubDirC++Flags $(opt)  ;
1009	HDRS += $(headers) ;
1010}
1011
1012rule UseArchObjectHeaders
1013{
1014	# usage: UseArchObjectHeaders <sources> : <arch> : [ <objects> ] ;
1015	#
1016	# <arch> specifies the architecture (e.g. x86).
1017	# <sources_or_objects> Source or object files.
1018	# NOTE: This rule must be invoked *after* the rule that builds the objects.
1019
1020	local sources = $(1) ;
1021	local headers = [ ArchHeaders $(2) ] ;
1022	local objects = $(3) ;
1023	local targets ;
1024	if $(objects) {
1025		targets = $(objects) ;
1026	} else {
1027		targets = $(sources) ;
1028	}
1029	local opt = -D$(OBOS_TARGET_DEFINE) ;
1030
1031	ObjectCcFlags $(targets) : $(opt)  ;
1032	ObjectC++Flags $(targets) : $(opt)  ;
1033	SourceHdrs $(sources) : $(headers) : $(objects) ;
1034}
1035
1036rule UsePosixHeaders
1037{
1038	# XXX changed to do nothing
1039}
1040
1041rule UsePosixObjectHeaders
1042{
1043	# UsePosixObjectHeaders <sources> [ : <objects> ] ;
1044	#
1045	# Adds the POSIX header dir to the header search
1046	# dirs of either the object targets of <sources> or if supplied to
1047	# <objects>. Also adjusts HDRSEARCH of <sources>.
1048	# NOTE: This rule must be invoked *after* the rule that builds the objects.
1049
1050	SourceHdrs $(1) : [ FDirName $(OBOS_TOP) headers posix ] : $(2) ;
1051}
1052
1053rule UseLibraryHeaders
1054{
1055	# UseLibraryHeaders <group list> ;
1056	#
1057	# Adds the library header dirs given by <group list> to the header search
1058	# dirs of the subdirectory.
1059	# NOTE: This rule must be invoked *before* the rule that builds the objects.
1060
1061	UseHeaders [ LibraryHeaders $(1) ] ;
1062}
1063
1064rule SplitPath
1065{
1066	# SplitPath <path> ;
1067	# Decomposes a path into its components.
1068	local path = $(1:G=) ;
1069	local components ;
1070	# $(path:D) for "/" is "/". Therefore the second condition.
1071	while $(path:D) && $(path:D) != $(path)
1072	{
1073		# Note: $(path:B) returns "." for "..", but $(path:D=) is fine.
1074		components = $(path:D=) $(components) ;
1075		path = $(path:D) ;
1076	}
1077	components = $(path) $(components) ;
1078	return $(components) ;
1079}
1080
1081rule PrependObjectHdrs
1082{
1083	# PrependObjectHdrs <objects_or_sources> : <dirs> ;
1084	# Prepends <dirs> to the list of header search dirs of the objects
1085	# specified by <objects_or_sources>. The HDRS variable will not be
1086	# changed, only CCHDRS.
1087	# Note: A subsequent ObjectHdrs invocation will therefore undo the
1088	# effect of this rule.
1089	# NOTE: This is a hack.
1090
1091	local objects = [ FGristFiles $(1:S=$(SUFOBJ)) ] ;
1092	local dirs = $(2) ;
1093	for object in $(objects) {
1094		# Don't change HDRS to avoid screwing up the header scanning.
1095		PREPENDED_HDRS on $(object)
1096			= $(dirs) [ on $(object) return $(PREPENDED_HDRS) ] ;
1097		CCHDRS on $(object)
1098			= [ FIncludes [ on $(object) return $(PREPENDED_HDRS) $(HDRS) ] ] ;
1099	}
1100}
1101
1102rule SymLink
1103{
1104	# SymLink <target> : <source> ;
1105	# Links <target> to <source>.
1106	# <source> is the exact link contents. No binding is done.
1107	LINKCONTENTS on $(1) = $(2) ;
1108	SymLink1 $(1) ;
1109	LocalDepends all : $(target) ;
1110}
1111
1112actions SymLink1
1113{
1114	$(RM) "$(1)" && $(LN) -s "$(LINKCONTENTS)" "$(1)"
1115}
1116
1117rule RelSymLink
1118{
1119	# RelSymLink <link> : <link target>
1120	# Creates a relative symbolic link from <link> to <link target>.
1121	# <link> and <link target> can be usual targets. They may have a grist
1122	# and don't need to have any dirname. Their LOCATE variables are used to
1123	# find their locations.
1124
1125	local target = $(1) ;
1126	local source = $(2) ;
1127	local targetDir = [ on $(target) FDirName $(LOCATE[1]) $(target:D) ] ;
1128	local sourceDir = [ on $(source) FDirName $(LOCATE[1]) $(source:D) ] ;
1129	local sourcePath = $(source:G=) ;
1130	sourcePath = $(sourcePath:D=$(sourceDir)) ;
1131	local targetDirComponents = [ SplitPath $(targetDir) ] ;
1132	local sourceComponents = [ SplitPath $(sourcePath) ] ;
1133
1134	SymLink $(target)
1135		: [ FRelPath $(targetDirComponents) : $(sourceComponents) ] ;
1136	NOUPDATE $(target) ;
1137	Depends $(target) : $(source) ;
1138	LocalClean clean : $(target) ;
1139}
1140
1141rule AbsSymLink
1142{
1143	# RelSymLink <link> : <link target> : <link dir>
1144	# Creates an absolute symbolic link from <link> to <link target>.
1145	# <link> and <link target> must be usual targets. If <link dir> is
1146	# given, then it is set as LOCATE directory on <link>.
1147
1148	LocalDepends files : $(1) ;
1149	Depends $(1) : $(2) ;
1150	if $(3) {
1151		MakeLocate $(1) : $(3) ;
1152	}
1153	SEARCH on $(2) += $(SEARCH_SOURCE) ;
1154	LocalClean clean : $(1) ;
1155}
1156
1157actions AbsSymLink
1158{
1159	target="$(2)"
1160	case "$target" in
1161		/*) ;;
1162		*) target=`pwd`/"$target";;
1163	esac
1164	$(RM) "$(1)" && $(LN) -s "$target" "$(1)"
1165}
1166
1167#-------------------------------------------------------------------------------
1168# Low-level OBOS utility rules
1169#-------------------------------------------------------------------------------
1170rule SetupObjectsDir
1171{
1172	local rel_objectsdir;
1173
1174	# Copy subdir tokens except the first, as that will be "sources", and we
1175	# do not want to include that :)
1176	rel_objectsdir = [ FDirName $(SUBDIR_TOKENS[2-]) ] ;
1177	LOCATE_TARGET = [ FDirName $(OBOS_OBJECT_TARGET) $(rel_objectsdir) ] ;
1178	LOCATE_SOURCE = $(LOCATE_TARGET) ;
1179	SEARCH_SOURCE = [ Filter $(SEARCH_SOURCE) : $(LOCATE_TARGET) ]
1180					$(LOCATE_TARGET) ;
1181}
1182
1183#-------------------------------------------------------------------------------
1184# Link rule/action are overwritten as they don't handle linking files who's name
1185# contain spaces very well. Also adds resources and version to executable.
1186#-------------------------------------------------------------------------------
1187rule Link
1188{
1189	# Note: RESFILES must be set before invocation.
1190	MODE on $(<) = $(EXEMODE) ;
1191	on $(1) XRes $(1) : $(RESFILES) ;
1192	Chmod $(<) ;
1193	SetType $(1) ;
1194	MimeSet $(1) ;
1195	SetVersion $(1) ;
1196}
1197
1198actions Link bind NEEDLIBS
1199{
1200	$(LINK) $(LINKFLAGS) -o "$(1)" $(UNDEFS) "$(2)" "$(NEEDLIBS)" $(LINKLIBS) ;
1201}
1202
1203rule LexC++
1204{
1205	Depends $(1) : $(2) ;
1206	MakeLocate $(1) : $(LOCATE_SOURCE) ;
1207	LocalClean clean : $(1) ;
1208}
1209
1210actions LexC++
1211{
1212	$(LEX) -o$(1) $(2)
1213}
1214
1215rule Bison
1216{
1217	local _h ;
1218
1219	_h = $(1).h ;
1220
1221	MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ;
1222
1223    Depends $(<) $(_h) : $(>) ;
1224    Bison1 $(<) $(_h) : $(>) ;
1225    LocalClean clean : $(<) $(_h) ;
1226
1227	# make sure someone includes $(_h) else it will be
1228	# a deadly independent target
1229
1230	Includes $(<) : $(_h) ;
1231}
1232
1233actions Bison1
1234{
1235	bison $(YACCFLAGS) -o $(1[1]) $(2)
1236}
1237
1238# BeOS specific rules
1239
1240rule XRes
1241{
1242	# XRes <target> : <resource files>
1243	if $(2)
1244	{
1245		Depends $(1) : $(2) ;
1246		XRes1 $(1) : $(2) ;
1247	}
1248}
1249
1250rule XRes1 { }
1251
1252rule SetVersion
1253{
1254	# SetVersion <target>
1255}
1256
1257rule SetType
1258{
1259	# SetType <target>
1260}
1261
1262rule MimeSet
1263{
1264	# SetType <target>
1265}
1266
1267
1268if $(OS) = BEOS
1269{
1270
1271actions XRes1
1272{
1273	xres -o "$(1)" "$(2)" ;
1274}
1275
1276actions SetVersion
1277{
1278	setversion "$(1)" -system $(OBOS_BUILD_VERSION) -short "$(OBOS_BUILD_DESCRIPTION)" ;
1279}
1280
1281actions SetType
1282{
1283	settype -t $(OBOS_TARGET_TYPE) "$(1)" ;
1284}
1285
1286actions MimeSet
1287{
1288	mimeset -f "$(1)" ;
1289}
1290
1291}	# if BEOS
1292
1293
1294rule assemble
1295{
1296	Depends $(<) : $(>) ;
1297	ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
1298	ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
1299}
1300
1301actions assemble
1302{
1303	$(CC) -c "$(2)" -O2 $(ASFLAGS) -D_ASSEMBLER $(KERNEL_CCFLAGS) $(ASHDRS) -o "$(1)" ;
1304}
1305
1306# Overridden to allow spaces in file names.
1307actions Chmod1
1308{
1309	$(CHMOD) "$(MODE)" "$(1)"
1310}
1311
1312# Overridden to allow spaces in file names.
1313actions piecemeal together existing Clean
1314{
1315	$(RM) "$(>)"
1316}
1317
1318rule ObjectReference
1319{
1320	# ObjectReference <reference object> : <source object>
1321	# Makes <reference object> refer to the same file as <source object>.
1322	# The filenames must of course be identical.
1323	# <source object> must have already been LOCATEd.
1324
1325	local ref = $(1) ;
1326	local source = $(2) ;
1327	if $(ref) != $(source) {
1328		Depends $(ref) : $(source) ;
1329		LOCATE on $(ref) = [ on $(source) return $(LOCATE) ] ;
1330	}
1331}
1332
1333rule ObjectReferences
1334{
1335	# ObjectReferences <source objects>
1336	# Creates local references to <source objects>, i.e. identifiers with the
1337	# current grist referring to the same files. <source objects> must have
1338	# already been LOCATEd.
1339
1340	local source ;
1341	for source in $(1) {
1342		ObjectReference [ FGristFiles $(source) ] : $(source) ;
1343	}
1344}
1345
1346rule Filter
1347{
1348	# Filter <list> : <excludes> ;
1349	# Removes all occurrences of <excludes> in <list>.
1350
1351	local list = $(1) ;
1352	local excludes = $(2) ;
1353	local newList ;
1354	local item ;
1355	for item in $(list) {
1356		local skip ;
1357		local exclude ;
1358		for exclude in $(excludes) {
1359			if $(item) = $(exclude) {
1360				skip = true ;
1361			}
1362		}
1363		if ! $(skip) {
1364			newList += $(item) ;
1365		}
1366	}
1367	return $(newList) ;
1368}
1369
1370
1371## Kernel stuff!
1372
1373rule SetupKernel
1374{
1375	# Usage SetupKernel <sources_or_objects> : <extra_cc_flags>;
1376
1377	local _objs = $(1:S=$(SUFOBJ)) ;
1378
1379	#Setup Kernel header directories
1380	local public_kernel_includes = add-ons/file_system add-ons/graphics device drivers kernel storage support ;
1381	local private_kernel_includes = kernel libroot ;
1382	# Use posix headers directory
1383	HDRS = [ FDirName $(OBOS_TOP) headers posix ] ;
1384	# Use public OS header directories
1385	HDRS += [ PublicHeaders $(public_kernel_includes) ] ;
1386	# Use private directories
1387	HDRS += [ PrivateHeaders $(private_kernel_includes) ] ;
1388	# The platform dependent headers.
1389	HDRS += $(PLATFORM_HEADERS) ;
1390
1391	UseArchHeaders $(OBOS_ARCH) ;
1392
1393	SetupObjectsDir ;
1394
1395	CCFLAGS on $(_objs) = $(KERNEL_CCFLAGS) $(2) ;
1396	C++FLAGS on $(_objs) = $(KERNEL_CCFLAGS) $(2) ;
1397}
1398
1399rule KernelObjects
1400{
1401	SetupKernel $(1) : $(2) ;
1402
1403	Objects $(1) ;
1404}
1405
1406rule KernelLd
1407{
1408	# KernelLd <name> : <objs> : <linkerscript> : <args> : <gcc_off> : <config_section> ;
1409
1410	SetupKernel $(2) ;
1411	LINK on $(1) = ld ;
1412
1413	LINKFLAGS on $(1) = $(4) ;
1414	if $(3) { LINKFLAGS on $(1) += --script=$(3) ; }
1415
1416	# Remove any preset LINKLIBS
1417	LINKLIBS on $(1) =  ;
1418
1419	# Show that we depend on the libraries we need
1420	LocalClean clean : $(1) ;
1421	LocalDepends all : $(1) ;
1422	Depends $(1) : $(2) ;
1423
1424	if $(6) {
1425		for i in $(6) {
1426			KernelConfigSection $(i) : elf32 : $(1) ;
1427		}
1428	}
1429
1430	MakeLocate $(1) : $(LOCATE_TARGET) ;
1431
1432	# Add the platform specific static libs (libgcc.a).
1433	if ! $(5) {
1434		LINKLIBS on $(1) += $(PLATFORM_LINKLIBS) ;
1435	}
1436}
1437
1438actions KernelLd
1439{
1440	$(LINK) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) ;
1441}
1442
1443rule KernelMergeObject
1444{
1445	# KernelMergeObject <name> : <sources> : <extra CFLAGS> ;
1446
1447	SetupKernel $(2) : $(3) ;
1448
1449	MakeLocateObjects $(2) ;
1450	Objects $(2) ;
1451	MergeObjectFromObjects $(1) : $(2:S=$(SUFOBJ)) ;
1452}
1453
1454rule KernelStaticLibrary
1455{
1456	# Usage KernelStaticLibrary <name> : <sources> : <extra cc flags>  ;
1457	# This is designed to take a set of sources and libraries and create
1458	# a file called lib<name>.a
1459
1460	SetupKernel $(2) : $(3) ;
1461
1462	MakeLocateObjects $(2) ;
1463	Library $(1) : $(2) ;
1464}
1465
1466rule KernelStaticLibraryObjects
1467{
1468	# Usage KernelStaticLibrary <name> : <sources> ;
1469	# This is designed to take a set of sources and libraries and create
1470	# a file called <name>
1471
1472	SetupKernel $(2) ;
1473
1474	# Show that we depend on the libraries we need
1475	LocalClean clean : $(1) ;
1476	LocalDepends all : $(1) ;
1477	Depends $(1) : $(2) ;
1478
1479	MakeLocate $(1) : $(LOCATE_TARGET) ;
1480}
1481
1482actions KernelStaticLibraryObjects
1483{
1484	ar -r "$(1)" "$(2)" ;
1485}
1486
1487rule BuildPlatformMain
1488{
1489	# Usage BuildPlatformMain <target> : <sources> ;
1490	SetupObjectsDir ;
1491	SetupDefaultIncludes ;
1492
1493	# Remove `-nostdinc' from CCFLAGS and C++FLAGS.
1494	local oldCCFLAGS = $(CCFLAGS) ;
1495	local oldC++FLAGS = $(C++FLAGS) ;
1496	CCFLAGS = [ Filter $(CCFLAGS) : -nostdinc ] ;
1497	C++FLAGS = [ Filter $(C++FLAGS) : -nostdinc ] ;
1498
1499	Main $(1) : $(2) ;
1500
1501	# Reset CCFLAGS and C++FLAGS to original values.
1502	CCFLAGS = $(oldCCFLAGS) ;
1503	C++FLAGS = $(oldC++FLAGS) ;
1504}
1505
1506rule KernelConfigSection
1507{
1508	# KernelConfigSection <section> : <type> : <file>  ;
1509
1510	SECTION_NAMES on $(OBOS_KERNEL_CONFIG) += $(1) ;
1511	SECTION_TYPES on $(OBOS_KERNEL_CONFIG) += $(2) ;
1512	SECTION_FILES on $(OBOS_KERNEL_CONFIG) += $(3) ;
1513
1514	Depends $(OBOS_KERNEL_CONFIG) : $(3) ;
1515}
1516
1517rule WriteKernelConfig
1518{
1519	# usage: WriteKernelConfig <target> ;
1520
1521	LocalDepends files : $(1) ;
1522
1523	MakeLocate $(1) : $(OBOS_OBJECT_TARGET) ;
1524
1525	LocalClean clean : $(1) ;
1526}
1527
1528actions WriteKernelConfig bind SECTION_FILES
1529{
1530	target="$(1)"
1531	echo "# OpenBeOS Kernel Config File" > "$target"
1532	echo "# Automatically generated - do not edit!" >> "$target"
1533	count=0
1534	for section in "$(SECTION_NAMES)" ; do
1535		count=`expr $count + 1`
1536		eval section$count="$section"
1537	done
1538	i=1
1539	for type in "$(SECTION_TYPES)" ; do
1540		eval type$i="$type"
1541		i=`expr $i + 1`
1542	done
1543	i=1
1544	for file in "$(SECTION_FILES)" ; do
1545		eval file$i="$file"
1546		i=`expr $i + 1`
1547	done
1548	for i in `seq $count` ; do
1549		eval section="\$section$i"
1550		eval type="\$type$i"
1551		eval file="\$file$i"
1552		echo "" >> "$target"
1553		echo "["$section"]" >> "$target"
1554		echo "type="$type >> "$target"
1555		case "$file" in
1556			/*) ;;
1557			*) file=`pwd`/"$file";;
1558		esac
1559		echo "file="$file >> "$target"
1560	done
1561}
1562
1563rule BuildKernel
1564{
1565	# Usage BuildKernel <target> : <config_file> ;
1566	local kernel = $(1) ;
1567	local configFile = $(2) ;
1568	local bootmaker = bootmaker ;
1569
1570	LocalDepends all : $(kernel) ;
1571	Depends $(kernel) : $(configFile) $(bootmaker) ;
1572	LocalClean clean : $(kernel) ;
1573	MakeLocate $(kernel) : $(LOCATE_TARGET) ;
1574
1575	BOOT_MAKER on $(kernel) = $(bootmaker) ;
1576}
1577
1578actions BuildKernel bind BOOT_MAKER
1579{
1580	"$(BOOT_MAKER)" --strip-debug --strip-binary strip "$(2)" -o "$(1)" ;
1581	echo ""
1582	echo "Kernel linked!"
1583	echo ""
1584}
1585
1586rule KernelFloppyImage
1587{
1588	# Usage KernelFloppyImage <target> : <kernel> : <bootblock> ;
1589	local floppy = $(1) ;
1590	local kernel = $(2) ;
1591	local bootblock = $(3) ;
1592	local makeflop = makeflop ;
1593
1594	LocalDepends all : $(floppy) ;
1595	Depends $(floppy) : $(kernel) $(bootblock) $(makeflop) ;
1596	LocalClean clean : $(floppy) ;
1597	MakeLocate $(floppy) : $(OBOS_OBJECT_TARGET) ;
1598
1599	BOOT_BLOCK on $(floppy) = $(bootblock) ;
1600	MAKE_FLOP on $(floppy) = $(makeflop) ;
1601}
1602
1603# This may be a bit verbose, but I think it's useful to show what's
1604# going on, at least in this early stage of development.
1605actions KernelFloppyImage bind BOOT_BLOCK bind MAKE_FLOP
1606{
1607	"$(MAKE_FLOP)" "-p $(shell expr 18 \* 2 \* 512)" "$(BOOT_BLOCK)" "$(2)" "$(1)" ;
1608
1609	echo ""
1610	echo "*************************************************"
1611	echo "*         Kernel build completed!               *"
1612	echo "*    Boot image for a 1.44M floppy created      *"
1613	echo "*************************************************"
1614	echo ""
1615	echo "Floppy image is $(1)"
1616	echo "The following command will write it to a floppy on BeOS"
1617	echo "  dd if=$(1) of=/dev/disk/floppy/raw bs=18k"
1618	echo "Alternatively you can run"
1619	echo "  ./configure --floppy /dev/disk/floppy/raw"
1620	echo "once and build + write the image subsequently via"
1621	echo "  jam installfloppy"
1622	echo ""
1623}
1624
1625rule InstallFloppy
1626{
1627	# InstallFloppy <target> : <floppy>
1628	# "dd"s <floppy> to $(FLOPPY_PATH).
1629
1630	local target = $(1) ;
1631	local floppy = $(2) ;
1632
1633	NotFile $(target) ;
1634	Always $(target) ;
1635	Depends $(target) : $(floppy) ;
1636}
1637
1638actions InstallFloppy
1639{
1640	if [ -z $(FLOPPY_PATH) ] ; then
1641		echo "Can't install floppy: FLOPPY_PATH not set."
1642		echo "run: ./configure --floppy <floppy path>"
1643		echo
1644		exit 0
1645	fi
1646	dd if=$(2) of=$(FLOPPY_PATH) bs=18k
1647}
1648
1649#-------------------------------------------------------------------------------
1650# FreeType 2 specific rules and variables
1651#-------------------------------------------------------------------------------
1652
1653FT2_INCLUDE = [ FDirName $(OBOS_TOP) headers libs freetype2 ] ;
1654FT2_SRC     = [ FDirName $(OBOS_TOP) src libs freetype2 ] ;
1655
1656FT2_LIB     = freetype ;
1657
1658FT2_COMPONENTS ?= gzip       # support for gzip-compressed files.
1659                  autohint   # auto-hinter
1660                  base       # base component (public APIs)
1661                  bdf        # BDF font driver
1662                  cache      # cache sub-system
1663                  cff        # CFF/CEF font driver
1664                  cid        # Postscript CID-keyed font driver
1665                  pcf        # PCF font driver
1666                  pfr        # PFR/TrueDoc font driver
1667                  psaux      # Common Postscript routines module
1668                  pshinter   # Postscript hinter module
1669                  psnames    # Postscript names handling
1670                  raster     # Monochrome rasterizer
1671                  smooth     # Anti-aliased rasterizer
1672                  sfnt       # SFNT-based format support routines
1673                  truetype   # TrueType font driver
1674                  type1      # Postscript Type 1 font driver
1675                  type42     # Postscript Type 42 (embedded TrueType) driver
1676                  winfonts   # Windows FON/FNT font driver
1677                  ;
1678
1679rule UseFreeTypeHeaders
1680{
1681	SubDirHdrs $(FT2_INCLUDE) ;
1682}
1683
1684rule UseFreeTypeObjectHeaders
1685{
1686	# UseFreeTypeObjectHeaders <sources> [ : <objects> ] ;
1687	SourceHdrs $(1) : $(FT2_INCLUDE) : $(2) ;
1688}
1689
1690rule FT2_SubDir
1691{
1692	# FT2_SubDir <dir>
1693	# <dir>: Components of a directory in the original hierarchy.
1694	local dir = $(1) ;
1695	local topDir ;
1696	switch $(dir[1])
1697	{
1698		case "include"	: topDir = $(FT2_INCLUDE) ;
1699		case src		: topDir = $(FT2_SRC) ;
1700		case *			: ECHO "Unknown FreeType2 directory: " $(dir) ;
1701	}
1702	return [ FDirName $(topDir) $(dir[2-]) ] ;
1703}
1704
1705rule FT2_Library
1706{
1707	# FT2_Library <libname> : <sources>
1708	# Builds objects from sources and adds the objects to the list of objects
1709	# to be linked into the library.
1710	# <libname> The name of the library.
1711	# <sources> The sources.
1712
1713	local library = lib$(1).so ;
1714	local sources = $(2) ;
1715	SetupIncludes ;
1716	SetupObjectsDir ;
1717	MakeLocateObjects $(sources) ;
1718	Objects $(sources) ;
1719	LIBRARY_OBJECTS on $(library) += [ FGristFiles $(sources:S=$(SUFOBJ)) ] ;
1720}
1721
1722rule FT2_LinkLibrary
1723{
1724	# FT2_LinkLibrary <libname>
1725	# Links the library from the objects build with FT2_LIBRARY before.
1726
1727	local library = lib$(1).so ;
1728	local objects = [ on $(library) return $(LIBRARY_OBJECTS) ] ;
1729	ObjectReferences $(objects) ;
1730	objects = [ FGristFiles $(objects) ] ;
1731	SharedLibraryFromObjects $(1) : $(objects) ;
1732}
1733
1734