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