xref: /haiku/Jamrules (revision 94782cf7613af753ee00be756c5404372478182f)
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
30# Include BuildConfig
31{
32	local buildConfig = [ GLOB $(OBOS_TOP) : BuildConfig ] ;
33	if ! $(buildConfig)
34	{
35		EXIT "No BuildConfig!"
36			 "Run ./configure in the source tree's root directory first!" ;
37	}
38	include $(buildConfig) ;
39}
40
41# Determine if we're building on PPC or x86
42# Determine mimetype of executable
43# Cross compiling can come later
44
45if $(METROWERKS) {
46	OBOS_TARGET ?= "ppc.R1" ;
47	OBOS_TARGET_TYPE ?= "application/x-be-executable" ;
48	OBOS_ARCH ?= "ppc" ;
49	OBOS_TARGET_DEFINE ?= "ARCH_ppc" ;
50} else {
51	OBOS_TARGET ?= "x86.R1" ;
52	OBOS_TARGET_TYPE ?= "application/x-vnd.Be-elfexecutable" ;
53	OBOS_ARCH ?= "x86" ;
54	OBOS_TARGET_DEFINE ?= "ARCH_x86" ;
55	OBOS_TARGET_DIR ?= "x86" ;
56}
57
58# Enable warnings only if WARNINGS is defined
59# Should be enabled by default later
60
61if $(WARNINGS) {
62	# For an explanation of the different warning options, see:
63	# http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_2.html
64	# to get even more warnings, add:
65	# -Wwrite-strings  	(doesn't work well with some Be headers)
66	# -Wundef			(dito)
67	# -Wconversion		(gets you many warnings about implicit conversions)
68	# -W				(gets you even more warnigs)
69	CCFLAGS ?= "-Wall -Wno-multichar -Wmissing-prototypes" ;
70	CCFLAGS += "-Wpointer-arith -Wcast-align -Wsign-compare" ;
71	C++FLAGS ?= "-Wall -Wno-multichar -Wmissing-prototypes -Wno-ctor-dtor-privacy -Woverloaded-virtual" ;
72	C++FLAGS += "-Wpointer-arith -Wcast-align -Wsign-compare" ;
73}
74
75# We might later want to introduce debug levels or handle the whole issue
76# differently. For now there's only on or off.
77#
78if $(DEBUG) {
79	OPTIM ?= -O0 ;
80	CCFLAGS += -g ;
81	C++FLAGS += -g ;
82	LINKFLAGS += -g ;
83} else {
84	OPTIM ?= -O2 ;
85}
86
87KERNEL_CCFLAGS ?= "-Wall -Wno-multichar -Wmissing-prototypes -finline -nostdinc" ;
88KERNEL_CCFLAGS += "-fno-builtin -D$(OBOS_TARGET_DEFINE) " ;
89KERNEL_CCFLAGS += "-DBOCHS_E9_HACK=$(BOCHS_E9_HACK) " ;
90
91# Instructs the Library rule to not make its object files temporary.
92# This is need as some objects are used in a static library and for an
93# executable.
94KEEPOBJS = true ;
95
96AR = ar r ;
97
98# If no OBOS_OBJECT_TARGET is not defined yet, use our default directory and
99# include our "OBOS_TARGET" as subdirectory in there (to prevent different
100# builds mixing objects from different targets).
101if ! $(OBOS_OBJECT_TARGET) {
102	OBOS_OBJECT_TARGET ?= [ FDirName $(OBOS_TOP) objects $(OBOS_TARGET) ] ;
103}
104
105# If no OBOS_DISTRO_TARGET is not defined yet, use our default directory and
106# include our "OBOS_TARGET" as subdirectory in there (to prevent different
107# builds mixing executables from different targets).
108if ! $(OBOS_DISTRO_TARGET) {
109	OBOS_DISTRO_TARGET ?= [ FDirName $(OBOS_TOP) distro $(OBOS_TARGET) ] ;
110}
111
112# Set our version number if not already set and mark it as a developer build
113if ! $(OBOS_BUILD_VERSION) {
114	OBOS_BUILD_VERSION ?= "1 0 0 a 1" ;
115	OBOS_BUILD_DESCRIPTION ?= "Developer Build" ;
116}
117
118# If OBOS_BUILD_VERSION is set, but OBOS_BUILD_DESCRIPTION isn't, mark it as
119# an unknown build.
120if ! $(OBOS_BUILD_DESCRIPTION) {
121	OBOS_BUILD_DESCRIPTION ?= "Unknown Build" ;
122}
123
124# Relative subdirs for distro dir (these are for *INTERNAL* use by the following rules only!)
125OBOS_APPS_DIR   ?= [ FDirName $(OBOS_DISTRO_TARGET) beos apps ] ;
126OBOS_BIN_DIR    ?= [ FDirName $(OBOS_DISTRO_TARGET) beos bin ] ;
127OBOS_PREFS_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos preferences ] ;
128OBOS_SERVER_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system servers ] ;
129OBOS_ADDON_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system add-ons ] ;
130OBOS_SHLIB_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system lib ] ;
131OBOS_STLIB_DIR  ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system lib ] ;
132OBOS_KERNEL_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system ] ;
133OBOS_TEST_DIR   ?= [ FDirName $(OBOS_TOP) tests ] ;
134
135OBOS_KERNEL_CONFIG = config.$(OBOS_ARCH).ini ;
136OBOS_KERNEL = kernel.$(OBOS_ARCH) ;
137OBOS_FLOPPY = floppy.$(OBOS_ARCH) ;
138
139rule SetupIncludes
140{
141	OBOS_INCLUDES ?= . add-ons app be_apps device drivers game interface kernel mail media midi midi2 net opengl storage support translation ;
142	UsePublicHeaders $(OBOS_INCLUDES) ;
143    UsePosixHeaders ;
144}
145
146#-------------------------------------------------------------------------------
147# Things Jam needs in order to work :)
148#-------------------------------------------------------------------------------
149
150rule UserObject
151{
152	switch $(2)
153	{
154	case *.S    : assemble $(1) : $(2) ;
155	case *.o    : return ;
156	case *      : ECHO "unknown suffix on" $(2) ;
157	}
158}
159
160# Override the default to give "prettier" command lines.
161actions Cc
162{
163	$(CC) -c "$(2)" $(CCFLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
164}
165
166actions C++
167{
168	$(C++) -c "$(2)" $(C++FLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
169}
170
171
172#-------------------------------------------------------------------------------
173# General High-level OBOS target rules
174#-------------------------------------------------------------------------------
175
176rule App
177{
178	# App <name> : <sources> ;
179	SetupObjectsDir ;
180	Main $(<) : $(>) ;
181	MakeLocate $(<) : $(OBOS_APPS_DIR) ;
182}
183
184rule BinCommand
185{
186	# BinCommand <name> : <sources> : <libraries> ;
187	SetupObjectsDir ;
188	Main $(1) : $(2) ;
189	MakeLocate $(1) : $(OBOS_BIN_DIR) ;
190	LinkSharedOSLibs $(1) : $(3) ;
191}
192
193rule StdBinCommands
194{
195	# StdBinCommands <sources> : <libs> ;
196	local libs = $(2) ;
197	for source in $(1)
198	{
199		local target = $(source:S=) ;
200		target = [ FGristFiles $(target) ] ;
201		BinCommand $(target) : $(source) : $(libs) ;
202	}
203}
204
205rule Preference
206{
207	# Preference <name> : <sources> ;
208#	SetupIncludes ;
209	SetupObjectsDir ;
210	Main $(<) : $(>) ;
211	MakeLocate $(<) : $(OBOS_PREFS_DIR) ;
212}
213
214rule Server
215{
216	# Server <name> : <sources> ;
217
218#	SetupIncludes ;
219	SetupObjectsDir ;
220	Main $(<) : $(>) ;
221	MakeLocate $(<) : $(OBOS_SERVER_DIR) ;
222}
223
224# test pseudo targets
225NOTFILE obostests ;
226NOTFILE r5tests ;
227
228rule CommonTestLib
229{
230	# CommonUnitTest <target> : <sources> : <obos libraries>
231	#	: <r5 libraries> : <test libraries> : <public headers>;
232	# Builds a unit test for both OBOS and R5 modules.
233	# <target> The name of the target.
234	# <sources> The list of sources.
235	# <obos libraries> A list of link libraries for the OBOS tests (as passed
236	# to LinkSharedOSLibs).
237	# <r5 libraries> A list of link libraries for the R5 tests (as passed
238	# to LinkSharedOSLibs).
239	# <test libraries> A list of link libraries for both OBOS tests and R5 tests
240	# that have a common name (i.e. specify libx.so and the OBOS tests will link
241	# to libx.so and the R5 tests will link to libx_r5.so).
242	# <public headers> A list of public header dirs (as passed to
243	# UsePublicHeaders).
244
245	local testlibdir = [ FDirName $(OBOS_TEST_DIR) lib ] ; #/boot/home/config/lib/obos_tests ;
246
247	TestLib $(1) : $(2) : $(testlibdir) : $(3) $(5) : $(6) ;
248	R5TestLib $(1) : $(2) : $(testlibdir) : $(4) [ R5SharedLibraryNames $(5) ] ;
249}
250
251rule TestLib
252{
253	# TestLib <target> : <sources> : <dest> : <libraries> : <public headers>
254	# Builds a unit test library for an OBOS module.
255	# <target> The name of the target.
256	# <sources> The list of sources.
257	# <dest> The directory for the target (as passed to FDirName).
258	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
259	# <public headers> A list of public header dirs (as passed to
260	# UsePublicHeaders).
261
262	local target = $(1) ;
263	local sources = $(2) ;
264	local dest = $(3) ;
265	local libraries = $(4) ;
266	local headerDirs = $(5) ;
267
268	# Turn optimization off.
269	local optim = $(OPTIM) ;
270	OPTIM = ;
271
272#	SetupIncludes ;
273	UseCppUnitHeaders ;
274	SetupObjectsDir ;
275	MakeLocateObjects $(sources) ;
276	Main $(target) : $(sources) ;
277	MakeLocate $(target) : $(dest) ;
278	Depends $(target) : libcppunit.so ;
279	Depends obostests : $(target) ;
280	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
281	UsePublicObjectHeaders $(sources) : $(headerDirs) ;
282	ObjectDefines $(sources) : TEST_OBOS ;
283	LINKFLAGS on $(target) = $(LINKFLAGS) -nostart -Xlinker -soname=\"$(target)\" ;
284
285	# Turn debugging on. That is usually desired for test code.
286	ObjectCcFlags $(sources) : "-g" ;
287	ObjectC++Flags $(sources) : "-g" ;
288
289	# Turn optimization on again.
290	OPTIM = $(optim) ;
291}
292
293rule R5TestLib
294{
295	# R5UnitTest <target> : <sources> : <dest> : <libraries>
296	# Builds a unit test for an R5 module. "_r5" is appended to the object
297	# and the target name.
298	# <target> The name of the target.
299	# <sources> The list of sources.
300	# <dest> The directory for the target (as passed to FDirName).
301	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
302
303	local target = $(1:B)_r5$(1:S) ;
304	local sources = $(2) ;
305	local dest = $(3)_r5 ;
306	local libraries = $(4) ;
307	local objects = [ R5ObjectNames $(sources) ] ;
308
309	# Turn optimization off.
310	local optim = $(OPTIM) ;
311	OPTIM = ;
312
313	UseCppUnitHeaders ;
314	SetupObjectsDir ;
315	MakeLocateObjects $(objects) ;
316
317	# Our Main replacement.
318	MainFromObjects $(target) : $(objects) ;
319	local source ;
320	for source in [ FGristFiles $(sources) ]
321	{
322		local object = [ R5ObjectNames $(source) ] ;
323		Object $(object) : $(source) ;
324		LocalDepends obj : $(object) ;
325	}
326
327	MakeLocate $(target) : $(dest) ;
328	Depends $(target) : libcppunit.so ;
329	Depends r5tests : $(target) ;
330	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
331	ObjectDefines $(objects) : TEST_R5 ;
332	LINKFLAGS on $(target) = $(LINKFLAGS) -nostart -Xlinker -soname=\"$(target)\" ;
333
334	# Turn debugging on. That is usually desired for test code.
335	ObjectCcFlags $(objects) : "-g" ;
336	ObjectC++Flags $(objects) : "-g" ;
337
338	# Turn optimization on again.
339	OPTIM = $(optim) ;
340}
341
342rule CommonUnitTest
343{
344	# CommonUnitTest <target> : <sources> : <dest> : <obos libraries>
345	#	: <r5 libraries> : <public headers>;
346	# Builds a unit test for both OBOS and R5 modules.
347	# <target> The name of the target.
348	# <sources> The list of sources.
349	# <dest> The directory for the target (as passed to FDirName).
350	# <obos libraries> A list of link libraries for the OBOS tests (as passed
351	# to LinkSharedOSLibs).
352	# <r5 libraries> A list of link libraries for the R5 tests (as passed
353	# to LinkSharedOSLibs).
354	# <public headers> A list of public header dirs (as passed to
355	# UsePublicHeaders).
356
357	UnitTest $(1) : $(2) : $(3) : $(4) : $(6) ;
358	R5UnitTest $(1) : $(2) : $(3) : $(5) ;
359}
360
361rule UnitTest
362{
363	# UnitTest <target> : <sources> : <dest> : <libraries> : <public headers>
364	# Builds a unit test for an OBOS module.
365	# <target> The name of the target.
366	# <sources> The list of sources.
367	# <dest> The directory for the target (as passed to FDirName).
368	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
369	# <public headers> A list of public header dirs (as passed to
370	# UsePublicHeaders).
371
372	local target = $(1) ;
373	local sources = $(2) ;
374	local dest = $(3) ;
375	local libraries = $(4) ;
376	local headerDirs = $(5) ;
377
378	# Turn optimization off.
379	local optim = $(OPTIM) ;
380	OPTIM = ;
381
382#	SetupIncludes ;
383	UseCppUnitHeaders ;
384	SetupObjectsDir ;
385	MakeLocateObjects $(sources) ;
386	Main $(target) : $(sources) ;
387	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(dest) ] ;
388	Depends $(target) : libcppunit.so ;
389	Depends obostests : $(target) ;
390	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
391	UsePublicObjectHeaders $(sources) : $(headerDirs) ;
392	ObjectDefines $(sources) : TEST_OBOS ;
393
394	# Turn debugging on. That is usually desired for test code.
395	ObjectCcFlags $(sources) : "-g" ;
396	ObjectC++Flags $(sources) : "-g" ;
397
398	# Turn optimization on again.
399	OPTIM = $(optim) ;
400}
401
402rule R5UnitTest
403{
404	# R5UnitTest <target> : <sources> : <dest> : <libraries>
405	# Builds a unit test for an R5 module. "_r5" is appended to the object
406	# and the target name.
407	# <target> The name of the target.
408	# <sources> The list of sources.
409	# <dest> The directory for the target (as passed to FDirName).
410	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
411
412	local target = $(1)_r5 ;
413	local sources = $(2) ;
414	local dest = $(3) ;
415	local libraries = $(4) ;
416	local objects = [ R5ObjectNames $(sources) ] ;
417
418	# Turn optimization off.
419	local optim = $(OPTIM) ;
420	OPTIM = ;
421
422	UseCppUnitHeaders ;
423	SetupObjectsDir ;
424	MakeLocateObjects $(objects) ;
425
426	# Our Main replacement.
427	MainFromObjects $(target) : $(objects) ;
428	local source ;
429	for source in [ FGristFiles $(sources) ]
430	{
431		local object = [ R5ObjectNames $(source) ] ;
432		Object $(object) : $(source) ;
433		LocalDepends obj : $(object) ;
434	}
435
436	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(dest) ] ;
437	Depends $(target) : libcppunit.so ;
438	Depends r5tests : $(target) ;
439	LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ;
440	ObjectDefines $(objects) : TEST_R5 ;
441
442	# Turn debugging on. That is usually desired for test code.
443	ObjectCcFlags $(objects) : "-g" ;
444	ObjectC++Flags $(objects) : "-g" ;
445
446	# Turn optimization on again.
447	OPTIM = $(optim) ;
448}
449
450rule R5ObjectNames
451{
452	# R5ObjectNames <sources> ;
453	# Returns a list of gristed object names given a list of source file names.
454	# Moreover each object names gets "_r5" inserted before the object suffix.
455	local objects = $(1:S=)_r5 ;
456	return [ FGristFiles $(objects:S=$(SUFOBJ)) ] ;
457}
458
459rule R5SharedLibraryNames
460{
461	# R5SharedLibraryNames <sources> ;
462	# Returns a list of shared library names given a list of file names. NO
463	# GRISTING IS PERFORMED :-) However, each library names gets "_r5" inserted
464	# before the shared lib suffix.
465	return $(1:S=)_r5.so ;
466}
467
468rule SimpleTest
469{
470	# UnitTest <target> : <sources> : <libraries>
471	# Builds a unit test for an OBOS module.
472	# <target> The name of the target.
473	# <sources> The list of sources.
474	# <dest> The directory for the target (as passed to FDirName).
475	# <libraries> A list of link libraries (as passed to LinkSharedOSLibs).
476	# <public headers> A list of public header dirs (as passed to
477	# UsePublicHeaders).
478
479	local target = $(1) ;
480	local sources = $(2) ;
481	local libraries = $(3) ;
482	local relPath = [ FRelPath src tests : $(SUBDIR_TOKENS) ] ;
483
484	# Turn optimization off.
485	local optim = $(OPTIM) ;
486	OPTIM = ;
487
488#	SetupIncludes ;
489	SetupObjectsDir ;
490	MakeLocateObjects $(sources) ;
491	Main $(target) : $(sources) ;
492	MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(relPath) ] ;
493	Depends obostests : $(target) ;
494	LinkSharedOSLibs $(target) : $(libraries) ;
495	ObjectDefines $(sources) : TEST_OBOS ;
496
497	# Turn debugging on. That is usually desired for test code.
498	ObjectCcFlags $(sources) : "-g" ;
499	ObjectC++Flags $(sources) : "-g" ;
500
501	# Turn optimization on again.
502	OPTIM = $(optim) ;
503}
504
505rule Addon
506{
507	# Addon <name> : <relpath> : <sources> ;
508
509#	SetupIncludes ;
510	SetupObjectsDir ;
511	Main $(1) : $(3) ;
512
513	# Create output dir path for addon
514	local targetdir;
515	targetdir = [ FDirName $(OBOS_ADDON_DIR) $(2) ] ;
516
517	MakeLocate $(1) : $(targetdir) ;
518	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ]
519						-nostart -Xlinker -soname=\"$(1)\" ;
520}
521
522rule R5KernelAddon
523{
524	# R5KernelAddon <name> : <relpath> : <sources> ;
525
526	local sources = $(3) ;
527
528	Addon $(1) : $(2) : $(3) ;
529	ObjectCcFlags $(sources) : -D_KERNEL_MODE=1 -no-fpic ;
530	ObjectC++Flags $(sources) : -D_KERNEL_MODE=1 -no-fpic
531								-fno-exceptions -fno-rtti ;
532	LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -nostdlib ;
533	LinkSharedOSLibs $(1) : /boot/develop/lib/x86/_KERNEL_ ;
534}
535
536rule MakeLocateObjects
537{
538	# MakeLocateObjects <gristed_sources_or_objects> ;
539
540	local _objs = $(1:S=$(SUFOBJ)) ;
541
542	for o in $(_objs)
543	{
544		local dir = $(o:D) ;
545		if $(dir) {
546			MakeLocate $(o) : [ FDirName $(LOCATE_TARGET) $(dir) ] ;
547		} else {
548			MakeLocate $(o) : $(LOCATE_TARGET) ;
549		}
550	}
551}
552
553rule StaticLibrary
554{
555	# StaticLibrary <name> : <sources> ;
556
557#	SetupIncludes ;
558	SetupObjectsDir ;
559	MakeLocateObjects $(2) ;
560	Library lib$(<).a : $(>) ;
561	MakeLocate lib$(<).a : $(OBOS_STLIB_DIR) ;
562}
563
564rule SharedLibrary
565{
566	# SharedLibrary <name> : <sources> ;
567	local _lib = lib$(1).so ;
568
569#	SetupIncludes ;
570	SetupObjectsDir ;
571	MakeLocateObjects $(2) ;
572	Main $(_lib) : $(2) ;
573	MakeLocate $(_lib) : $(OBOS_SHLIB_DIR) ;
574	LINKFLAGS on $(_lib) = [ on $(_lib) return $(LINKFLAGS) ]
575						   -nostart -Xlinker -soname=\"$(_lib)\" ;
576}
577
578rule LinkSharedOSLibs
579{
580	# LinkSharedOSLibs <name> : <libs> ;
581	# Valid elements for <libs> are e.g. "be" or "libopenbeos.so" or
582	# "/boot/.../libfoo.so". If the basename starts with "lib" or the thingy
583	# has a dirname or grist, it is added to the NEEDLIBS variable (i.e. the
584	# file will be bound!), otherwise it is prefixed "-l" and added to
585	# LINKLIBS.
586
587	for i in $(>)
588	{
589		local isfile = ;
590		if $(i:D) || $(i:G) {
591			isfile = true ;
592		} else {
593			switch $(i:B)
594			{
595				case lib*	: isfile = true ;
596				case *		: isfile = ;
597			}
598		}
599		if $(isfile) {
600			NEEDLIBS on $(1) = [ on $(1) return $(NEEDLIBS) ] $(i) ;
601			Depends $(1) : $(i) ;
602		} else {
603			LINKLIBS on $(1) = [ on $(1) return $(LINKLIBS) ] -l$(i) ;
604		}
605	}
606}
607
608rule LinkStaticOSLibs
609{
610	# LinkStaticOSLibs <name> : <libs> ;
611
612	for i in $(>)
613	{
614		LINKLIBS on $(<) = $(LINKLIBS) -l $(i) ;
615	}
616}
617
618rule AddResources
619{
620	# AddResources <name> : <resourcefiles> ;
621
622	SEARCH on $(2) += $(SEARCH_SOURCE) ;
623	RESFILES on $(1) += $(2) ;
624}
625
626rule PublicHeaders
627{
628	# PublicHeaders <group list>
629	#
630	# Returns the directory names for the public header dirs identified by
631	# <group list>.
632
633	local list = $(1) ;
634	local dirs ;
635	for i in $(list) {
636		dirs += [ FDirName $(OBOS_TOP) headers os $(i) ] ;
637	}
638	return $(dirs) ;
639}
640
641rule PrivateHeaders
642{
643	# PrivateHeaders <group list>
644	#
645	# Returns the directory names for the private header dirs identified by
646	# <group list>.
647
648	local list = $(1) ;
649	local dirs ;
650	for i in $(list) {
651		dirs += [ FDirName $(OBOS_TOP) headers private $(i) ] ;
652	}
653	return $(dirs) ;
654}
655
656rule ArchHeaders
657{
658	# usage: ArchHeaders <arch> ;
659	#
660	# <arch> specifies the architecture (e.g. x86).
661
662	return [ FDirName $(OBOS_TOP) headers private kernel arch $(1) ] ;
663}
664
665rule UsePublicHeaders
666{
667	# UsePublicHeaders <group list> ;
668	#
669	# Adds the public C header dirs given by <group list> to the header search
670	# dirs of the subdirectory.
671	# NOTE: This rule must be invoked *before* the rule that builds the objects.
672
673	UseHeaders [ PublicHeaders $(1) ] ;
674}
675
676rule UsePublicObjectHeaders
677{
678	# UsePublicObjectHeaders <sources_or_objects> : <group list> ;
679	#
680	# Adds the public C header dirs given by <group list> to the header search
681	# dirs of <sources_or_objects>.
682	# NOTE: This rule must be invoked *after* the rule that builds the objects.
683
684	ObjectHdrs $(1) : [ PublicHeaders $(2) ] ;
685}
686
687rule UsePrivateHeaders
688{
689	# UsePrivateHeaders <group list> ;
690	#
691	# Adds the private C header dirs given by <group list> to the header search
692	# dirs of the subdirectory.
693	# NOTE: This rule must be invoked *before* the rule that builds the objects.
694
695	UseHeaders [ PrivateHeaders $(1) ] ;
696}
697
698rule UsePrivateObjectHeaders
699{
700	# UsePrivateObjectHeaders <sources_or_objects> : <group list> ;
701	#
702	# Adds the private C header dirs given by <group list> to the header search
703	# dirs of <sources_or_objects>.
704	# NOTE: This rule must be invoked *after* the rule that builds the objects.
705
706	ObjectHdrs $(1) : [ PrivateHeaders $(2) ] ;
707}
708
709rule UseHeaders
710{
711	# UseHeaders <headers> ;
712	#
713	# Adds the C header dirs <headers> to the header search
714	# dirs of the subdirectory.
715	# NOTE: This rule must be invoked *before* the rule that builds the objects.
716
717	local header ;
718	for header in $(1) {
719		SubDirHdrs $(header) ;
720	}
721}
722
723rule UseCppUnitHeaders
724{
725	SubDirHdrs [ FDirName $(OBOS_TOP) headers tools cppunit ] ;
726}
727
728rule UseArchHeaders
729{
730	# usage: UseArchHeaders <arch> ;
731	#
732	# <arch> specifies the architecture (e.g. x86).
733	# NOTE: This rule must be invoked *before* the rule that builds the objects.
734
735	local headers = [ ArchHeaders $(1) ] ;
736	local opt = -D$(OBOS_TARGET_DEFINE) ;
737
738	SubDirCcFlags $(opt)  ;
739	SubDirC++Flags $(opt)  ;
740	SubDirHdrs $(headers) ;
741}
742
743rule UseArchObjectHeaders
744{
745	# usage: UseArchObjectHeaders <sources_or_objects> : <arch> ;
746	#
747	# <arch> specifies the architecture (e.g. x86).
748	# <sources_or_objects> Source or object files.
749	# NOTE: This rule must be invoked *after* the rule that builds the objects.
750
751	local targets = $(1) ;
752	local headers = [ ArchHeaders $(2) ] ;
753	local opt = -D$(OBOS_TARGET_DEFINE) ;
754
755	ObjectCcFlags $(targets) : $(opt)  ;
756	ObjectC++Flags $(targets) : $(opt)  ;
757	ObjectHdrs $(targets) : $(headers) ;
758}
759
760rule UsePosixHeaders
761{
762	# UsePrivateHeaders <group list> ;
763	#
764	# Adds the POSIX header dir to the header search
765	# dirs of the subdirectory.
766	# NOTE: This rule must be invoked *before* the rule that builds the objects.
767
768	SubDirHdrs [ FDirName $(OBOS_TOP) headers posix ] ;
769}
770
771rule UsePosixObjectHeaders
772{
773	# UsePosixObjectHeaders <sources_or_objects> ;
774	#
775	# Adds the POSIX header dir to the header search
776	# dirs of <sources_or_objects>.
777	# NOTE: This rule must be invoked *after* the rule that builds the objects.
778
779	ObjectHdrs $(1) : [ FDirName $(OBOS_TOP) headers posix ] ;
780}
781
782rule SplitPath
783{
784	# SplitPath <path> ;
785	# Decomposes a path into its components.
786	local path = $(1:G=) ;
787	local components ;
788	# $(path:D) for "/" is "/". Therefore the second condition.
789	while $(path:D) && $(path:D) != $(path)
790	{
791		# Note: $(path:B) returns "." for "..", but $(path:D=) is fine.
792		components = $(path:D=) $(components) ;
793		path = $(path:D) ;
794	}
795	components = $(path) $(components) ;
796	return $(components) ;
797}
798
799rule PrependObjectHdrs
800{
801	# PrependObjectHdrs <objects_or_sources> : <dirs> ;
802	# Prepends <dirs> to the list of header search dirs of the objects
803	# specified by <objects_or_sources>. The HDRS variable will not be
804	# changed, only CCHDRS.
805	# Note: A subsequent ObjectHdrs invocation will therefore undo the
806	# effect of this rule.
807	# NOTE: This is a hack.
808
809	local objects = [ FGristFiles $(1:S=$(SUFOBJ)) ] ;
810	local dirs = $(2) ;
811	for object in $(objects) {
812		# Don't change HDRS to avoid screwing up the header scanning.
813		PREPENDED_HDRS on $(object)
814			= $(dirs) [ on $(object) return $(PREPENDED_HDRS) ] ;
815		CCHDRS on $(object)
816			= [ FIncludes [ on $(object) return $(PREPENDED_HDRS) $(HDRS) ] ] ;
817	}
818}
819
820rule SymLink
821{
822	# SymLink <target> : <source> ;
823	# Links <target> to <source>.
824	# <source> is the exact link contents. No binding is done.
825	LINKCONTENTS on $(1) = $(2) ;
826	SymLink1 $(1) ;
827	LocalDepends all : $(target) ;
828}
829
830actions SymLink1
831{
832	$(RM) "$(1)" && $(LN) -s "$(LINKCONTENTS)" "$(1)"
833}
834
835rule RelSymLink
836{
837	# RelSymLink <link> : <link target>
838	# Creates a relative symbolic link from <link> to <link target>.
839	# <link> and <link target> can be usual targets. They may have a grist
840	# and don't need to have any dirname. Their LOCATE variables are used to
841	# find their locations.
842
843	local target = $(1) ;
844	local source = $(2) ;
845	local targetDir = [ on $(target) FDirName $(LOCATE[1]) $(target:D) ] ;
846	local sourceDir = [ on $(source) FDirName $(LOCATE[1]) $(source:D) ] ;
847	local sourcePath = $(source:G=) ;
848	sourcePath = $(sourcePath:D=$(sourceDir)) ;
849	local targetDirComponents = [ SplitPath $(targetDir) ] ;
850	local sourceComponents = [ SplitPath $(sourcePath) ] ;
851
852	SymLink $(target)
853		: [ FRelPath $(targetDirComponents) : $(sourceComponents) ] ;
854	NOUPDATE $(target);
855	Depends $(target) : $(source) ;
856}
857
858#-------------------------------------------------------------------------------
859# Low-level OBOS utility rules
860#-------------------------------------------------------------------------------
861rule SetupObjectsDir
862{
863	local rel_objectsdir;
864
865	# Copy subdir tokens except the first, as that will be "sources", and we
866	# do not want to include that :)
867	rel_objectsdir = [ FDirName $(SUBDIR_TOKENS[2-]) ] ;
868	LOCATE_TARGET = [ FDirName $(OBOS_OBJECT_TARGET) $(rel_objectsdir) ] ;
869}
870
871#-------------------------------------------------------------------------------
872# Link rule/action are overwritten as they don't handle linking files who's name
873# contain spaces very well. Also adds resources and version to executable.
874#-------------------------------------------------------------------------------
875rule Link
876{
877	# Note: RESFILES must be set before invocation.
878	MODE on $(<) = $(EXEMODE) ;
879	on $(1) XRes $(1) : $(RESFILES) ;
880	SetVersion $(1) ;
881	Chmod $(<) ;
882	SetType $(1) ;
883	MimeSet $(1) ;
884}
885
886actions Link bind NEEDLIBS
887{
888	$(LINK) $(LINKFLAGS) -o "$(1)" $(UNDEFS) "$(2)" "$(NEEDLIBS)" $(LINKLIBS) ;
889}
890
891# BeOS specific rules
892
893rule XRes
894{
895	# XRes <target> : <resource files>
896	if $(2)
897	{
898		Depends $(1) : $(2) ;
899		XRes1 $(1) : $(2) ;
900	}
901}
902
903rule XRes1 { }
904
905rule SetVersion
906{
907	# SetVersion <target>
908}
909
910rule SetType
911{
912	# SetType <target>
913}
914
915rule MimeSet
916{
917	# SetType <target>
918}
919
920
921if $(OS) = BEOS
922{
923
924actions XRes1
925{
926	xres -o "$(1)" "$(2)" ;
927}
928
929actions SetVersion
930{
931	setversion "$(1)" -system $(OBOS_BUILD_VERSION) -short "$(OBOS_BUILD_DESCRIPTION)" ;
932}
933
934actions SetType
935{
936	settype -t $(OBOS_TARGET_TYPE) "$(1)" ;
937}
938
939actions MimeSet
940{
941	mimeset -f "$(1)" ;
942}
943
944}	# if BEOS
945
946
947rule assemble
948{
949	Depends $(<) : $(>) ;
950	ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ;
951	ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
952}
953
954actions assemble
955{
956	$(CC) -c "$(2)" -O2 $(ASFLAGS) $(KERNEL_CCFLAGS) $(ASHDRS) -o "$(1)" ;
957}
958
959# Overridden to allow spaces in file names.
960actions Chmod1
961{
962	$(CHMOD) "$(MODE)" "$(1)"
963}
964
965rule ObjectReference
966{
967	# ObjectReference <reference object> : <source object>
968	# Makes <reference object> refer to the same file as <source object>.
969	# The filenames must of course be identical.
970	# <source object> must have already been LOCATEd.
971
972	local ref = $(1) ;
973	local source = $(2) ;
974	if $(ref) != $(source) {
975		Depends $(ref) : $(source) ;
976		on $(ref) LOCATE = [ on $(source) return $(LOCATE) ] ;
977	}
978}
979
980rule ObjectReferences
981{
982	# ObjectReferences <source objects>
983	# Creates local references to <source objects>, i.e. identifiers with the
984	# current grist referring to the same files. <source objects> must have
985	# already been LOCATEd.
986
987	local source ;
988	for source in $(1) {
989		ObjectReference [ FGristFiles $(source) ] : $(source) ;
990	}
991}
992
993rule Filter
994{
995	# Filter <list> : <excludes> ;
996	# Removes all occurrences of <excludes> in <list>.
997
998	local list = $(1) ;
999	local excludes = $(2) ;
1000	local newList ;
1001	local item ;
1002	for item in $(list) {
1003		local skip ;
1004		local exclude ;
1005		for exclude in $(excludes) {
1006			if $(item) = $(exclude) {
1007				skip = true ;
1008			}
1009		}
1010		if ! $(skip) {
1011			newList += item ;
1012		}
1013	}
1014	return $(newList) ;
1015}
1016
1017
1018## Kernel stuff!
1019
1020rule SetupKernel
1021{
1022	# Usage SetupKernel <sources_or_objects> : <extra_cc_flags>;
1023
1024	local _objs = $(1:S=$(SUFOBJ)) ;
1025
1026	UsePublicHeaders kernel support drivers ;
1027	UsePublicHeaders [ FDirName os kernel ] ;
1028	UsePrivateHeaders kernel ;
1029	UsePosixHeaders ;
1030	UseArchHeaders $(OBOS_ARCH) ;
1031
1032	SetupObjectsDir ;
1033
1034	CCFLAGS on $(_objs) = $(KERNEL_CCFLAGS) $(2) ;
1035	C++FLAGS on $(_objs) = $(KERNEL_CCFLAGS) $(2) ;
1036}
1037
1038rule KernelObjects
1039{
1040	SetupKernel $(1) : $(2) ;
1041
1042	Objects $(1) ;
1043}
1044
1045rule KernelLd
1046{
1047	# KernelLd <name> : <objs> : <linkerscript> : <args> : <gcc_off> ;
1048
1049	SetupKernel $(2) ;
1050	LINK on $(1) = ld ;
1051
1052	LINKFLAGS on $(1) = $(4) ;
1053	if $(3) { LINKFLAGS on $(1) += --script=$(3) ; }
1054
1055	# Remove any preset LINKLIBS
1056	LINKLIBS on $(1) =  ;
1057
1058	# Show that we depend on the libraries we need
1059	LocalClean clean : $(1) ;
1060	LocalDepends all : $(1) ;
1061	Depends $(1) : $(2) ;
1062
1063	if $(6) {
1064		for i in $(6) {
1065			KernelConfigSection $(i) : elf32 : $(1) ;
1066		}
1067	}
1068
1069	MakeLocate $(1) : $(LOCATE_TARGET) ;
1070
1071	# Add libgcc.a - NB this should be detected not hard coded!
1072	if ! $(5) {
1073		LINKLIBS on $(1) += -L $(GCC_PATH) -lgcc ;
1074	}
1075}
1076
1077actions KernelLd
1078{
1079	$(LINK) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) ;
1080}
1081
1082rule KernelStaticLibrary
1083{
1084	# Usage KernelStaticLibrary <name> : <sources> : <extra cc flags>  ;
1085	# This is designed to take a set of sources and libraries and create
1086	# a file called lib<name>.a
1087
1088	SetupKernel $(2) : $(3) ;
1089
1090	MakeLocateObjects $(2) ;
1091	Library $(1) : $(2) ;
1092}
1093
1094rule KernelStaticLibraryObjects
1095{
1096	# Usage KernelStaticLibrary <name> : <sources> ;
1097	# This is designed to take a set of sources and libraries and create
1098	# a file called <name>
1099
1100	SetupKernel $(2) ;
1101
1102	# Show that we depend on the libraries we need
1103	LocalClean clean : $(1) ;
1104	LocalDepends all : $(1) ;
1105	Depends $(1) : $(2) ;
1106
1107	MakeLocate $(1) : $(LOCATE_TARGET) ;
1108}
1109
1110actions KernelStaticLibraryObjects
1111{
1112	ar -r "$(1)" "$(2)" ;
1113}
1114
1115rule SystemMain
1116{
1117	# Usage SystemMain <target> : <sources> ;
1118	SetupObjectsDir ;
1119
1120	LINKLIBS on $(1) = ;
1121
1122	Main $(1) : $(2) ;
1123}
1124
1125rule KernelConfigSection
1126{
1127	# KernelConfigSection <section> : <type> : <file>  ;
1128
1129	SECTION_NAMES on $(OBOS_KERNEL_CONFIG) += $(1) ;
1130	SECTION_TYPES on $(OBOS_KERNEL_CONFIG) += $(2) ;
1131	SECTION_FILES on $(OBOS_KERNEL_CONFIG) += $(3) ;
1132
1133	Depends $(OBOS_KERNEL_CONFIG) : $(3) ;
1134}
1135
1136rule WriteKernelConfig
1137{
1138	# usage: WriteKernelConfig <target> ;
1139
1140	LocalDepends files : $(1) ;
1141
1142	MakeLocate $(1) : $(OBOS_OBJECT_TARGET) ;
1143
1144	LocalClean clean : $(1) ;
1145}
1146
1147actions WriteKernelConfig bind SECTION_FILES
1148{
1149	target="$(1)"
1150	echo "# OpenBeOS Kernel Config File" > "$target"
1151	echo "# Automatically generated - do not edit!" >> "$target"
1152	count=0
1153	for section in "$(SECTION_NAMES)" ; do
1154		count=`expr $count + 1`
1155		eval section$count="$section"
1156	done
1157	i=1
1158	for type in "$(SECTION_TYPES)" ; do
1159		eval type$i="$type"
1160		i=`expr $i + 1`
1161	done
1162	i=1
1163	for file in "$(SECTION_FILES)" ; do
1164		eval file$i="$file"
1165		i=`expr $i + 1`
1166	done
1167	for i in `seq $count` ; do
1168		eval section="\$section$i"
1169		eval type="\$type$i"
1170		eval file="\$file$i"
1171		echo "" >> "$target"
1172		echo "["$section"]" >> "$target"
1173		echo "type="$type >> "$target"
1174		case "$file" in
1175			/*) ;;
1176			*) file=`pwd`/"$file";;
1177		esac
1178		echo "file="$file >> "$target"
1179	done
1180}
1181
1182rule BuildKernel
1183{
1184	# Usage BuildKernel <target> : <config_file> ;
1185	local kernel = $(1) ;
1186	local configFile = $(2) ;
1187	local bootmaker = bootmaker ;
1188
1189	LocalDepends all : $(kernel) ;
1190	Depends $(kernel) : $(configFile) $(bootmaker) ;
1191	LocalClean clean : $(kernel) ;
1192	MakeLocate $(kernel) : $(LOCATE_TARGET) ;
1193
1194	BOOT_MAKER on $(kernel) = $(bootmaker) ;
1195}
1196
1197actions BuildKernel bind BOOT_MAKER
1198{
1199	"$(BOOT_MAKER)" --strip-debug --strip-binary strip "$(2)" -o "$(1)" ;
1200	echo ""
1201	echo "Kernel linked!"
1202	echo ""
1203}
1204
1205rule KernelFloppyImage
1206{
1207	# Usage KernelFloppyImage <target> : <kernel> : <bootblock> ;
1208	local floppy = $(1) ;
1209	local kernel = $(2) ;
1210	local bootblock = $(3) ;
1211	local makeflop = makeflop ;
1212
1213	LocalDepends all : $(floppy) ;
1214	Depends $(floppy) : $(kernel) $(bootblock) $(makeflop) ;
1215	LocalClean clean : $(floppy) ;
1216	MakeLocate $(floppy) : $(OBOS_OBJECT_TARGET) ;
1217
1218	BOOT_BLOCK on $(floppy) = $(bootblock) ;
1219	MAKE_FLOP on $(floppy) = $(makeflop) ;
1220}
1221
1222# This may be a bit verbose, but I think it's useful to show what's
1223# going on, at least in this early stage of development.
1224actions KernelFloppyImage bind BOOT_BLOCK bind MAKE_FLOP
1225{
1226	"$(MAKE_FLOP)" "-p $(shell expr 18 \* 2 \* 512)" "$(BOOT_BLOCK)" "$(2)" "$(1)" ;
1227
1228	echo ""
1229	echo "*************************************************"
1230	echo "*         Kernel build completed!               *"
1231	echo "*    Boot image for a 1.44M floppy created      *"
1232	echo "*************************************************"
1233	echo ""
1234	echo "Floppy image is $(1)"
1235	echo "The following command will write it to a floppy on BeOS"
1236	echo "  dd if=$(1) of=/dev/disk/floppy/raw bs=18k"
1237	echo "Alternatively you can run"
1238	echo "  ./configure --floppy /dev/disk/floppy/raw"
1239	echo "once and build + write the image subsequently via"
1240	echo "  jam installfloppy"
1241	echo ""
1242}
1243
1244rule InstallFloppy
1245{
1246	# InstallFloppy <target> : <floppy>
1247	# "dd"s <floppy> to $(FLOPPY_PATH).
1248
1249	local target = $(1) ;
1250	local floppy = $(2) ;
1251
1252	NotFile $(target) ;
1253	Always $(target) ;
1254	Depends $(target) : $(floppy) ;
1255}
1256
1257actions InstallFloppy
1258{
1259	if [ -z $(FLOPPY_PATH) ] ; then
1260		echo "Can't install floppy: FLOPPY_PATH not set."
1261		echo "run: ./configure --floppy <floppy path>"
1262		echo
1263		exit 0
1264	fi
1265	dd if=$(2) of=$(FLOPPY_PATH) bs=18k
1266}
1267
1268