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