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