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