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