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