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