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