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