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