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