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