# Vanilla Jam compatibility if ! $(INVOCATION_SUBDIR_SET) { rule FIsPrefix { # FIsPrefix : ; # Returns true, if list is a prefix (a proper one or equal) of # list , an empty list otherwise. local a = $(1) ; local b = $(2) ; while $(a) && $(a[1]) = $(b[1]) { a = $(a[2-]) ; b = $(b[2-]) ; } if $(a) { return ; } else { return true ; } } rule LocalClean { Clean $(1) : $(2) ; } rule LocalDepends { Depends $(1) : $(2) ; } } # vanilla Jam compatibility # Include BuildConfig { local buildConfig = [ GLOB $(OBOS_TOP) : BuildConfig ] ; if ! $(buildConfig) { EXIT "No BuildConfig!" "Run ./configure in the source tree's root directory first!" ; } include $(buildConfig) ; } # Determine if we're building on PPC or x86 # Determine mimetype of executable # Cross compiling can come later if $(METROWERKS) { OBOS_TARGET ?= "ppc.R1" ; OBOS_TARGET_TYPE ?= "application/x-be-executable" ; OBOS_ARCH ?= "ppc" ; OBOS_TARGET_DEFINE ?= "ARCH_ppc" ; } else { OBOS_TARGET ?= "x86.R1" ; OBOS_TARGET_TYPE ?= "application/x-vnd.Be-elfexecutable" ; OBOS_ARCH ?= "x86" ; OBOS_TARGET_DEFINE ?= "ARCH_x86" ; OBOS_TARGET_DIR ?= "x86" ; } # Enable warnings only if WARNINGS is defined # Should be enabled by default later # if $(WARNINGS) { # For an explanation of the different warning options, see: # http://gcc.gnu.org/onlinedocs/gcc-2.95.3/gcc_2.html # to get even more warnings, add: # -Wwrite-strings (doesn't work well with some Be headers) # -Wundef (dito) # -Wconversion (gets you many warnings about implicit conversions) # -W (gets you even more warnigs) CCFLAGS ?= "-Wall -Wno-multichar -Wmissing-prototypes" ; CCFLAGS += "-Wpointer-arith -Wcast-align -Wsign-compare" ; C++FLAGS ?= "-Wall -Wno-multichar -Wmissing-prototypes -Wno-ctor-dtor-privacy -Woverloaded-virtual" ; C++FLAGS += "-Wpointer-arith -Wcast-align -Wsign-compare" ; } # We might later want to introduce debug levels or handle the whole issue # differently. For now there's only on or off. # if $(DEBUG) { OPTIM ?= -O0 ; CCFLAGS += -g ; C++FLAGS += -g ; LINKFLAGS += -g ; } else { OPTIM ?= -O2 ; } # # To disable for the tests OPTIM and DEBUG are overridden, set the environment # variable NO_TEST_DEBUG. KERNEL_CCFLAGS ?= "-Wall -Wno-multichar -Wmissing-prototypes -finline -nostdinc" ; KERNEL_CCFLAGS += "-fno-builtin -D$(OBOS_TARGET_DEFINE) " ; KERNEL_CCFLAGS += "-DBOCHS_E9_HACK=$(BOCHS_E9_HACK) " ; # Instructs the Library rule to not make its object files temporary. # This is need as some objects are used in a static library and for an # executable. KEEPOBJS = true ; AR = ar r ; # If no OBOS_OBJECT_TARGET is not defined yet, use our default directory and # include our "OBOS_TARGET" as subdirectory in there (to prevent different # builds mixing objects from different targets). if ! $(OBOS_OBJECT_TARGET) { OBOS_OBJECT_TARGET ?= [ FDirName $(OBOS_TOP) objects $(OBOS_TARGET) ] ; } # If no OBOS_DISTRO_TARGET is not defined yet, use our default directory and # include our "OBOS_TARGET" as subdirectory in there (to prevent different # builds mixing executables from different targets). if ! $(OBOS_DISTRO_TARGET) { OBOS_DISTRO_TARGET ?= [ FDirName $(OBOS_TOP) distro $(OBOS_TARGET) ] ; } # Set our version number if not already set and mark it as a developer build if ! $(OBOS_BUILD_VERSION) { OBOS_BUILD_VERSION ?= "1 0 0 a 1" ; OBOS_BUILD_DESCRIPTION ?= "Developer Build" ; } # If OBOS_BUILD_VERSION is set, but OBOS_BUILD_DESCRIPTION isn't, mark it as # an unknown build. if ! $(OBOS_BUILD_DESCRIPTION) { OBOS_BUILD_DESCRIPTION ?= "Unknown Build" ; } # Relative subdirs for distro dir (these are for *INTERNAL* use by the following rules only!) OBOS_APPS_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos apps ] ; OBOS_BIN_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos bin ] ; OBOS_PREFS_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos preferences ] ; OBOS_SERVER_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system servers ] ; OBOS_ADDON_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system add-ons ] ; OBOS_SHLIB_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system lib ] ; OBOS_STLIB_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system lib ] ; OBOS_KERNEL_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system ] ; OBOS_TEST_DIR ?= [ FDirName $(OBOS_TOP) tests ] ; OBOS_KERNEL_CONFIG = config.$(OBOS_ARCH).ini ; OBOS_KERNEL = kernel.$(OBOS_ARCH) ; OBOS_FLOPPY = floppy.$(OBOS_ARCH) ; rule SetupIncludes { OBOS_INCLUDES ?= . add-ons app be_apps device drivers game interface kernel mail media midi midi2 net opengl storage support translation ; UsePublicHeaders $(OBOS_INCLUDES) ; UsePosixHeaders ; } #------------------------------------------------------------------------------- # Things Jam needs in order to work :) #------------------------------------------------------------------------------- rule UserObject { switch $(2) { case *.S : assemble $(1) : $(2) ; case *.o : return ; case * : ECHO "unknown suffix on" $(2) ; } } # Override the default to give "prettier" command lines. actions Cc { $(CC) -c "$(2)" $(CCFLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ; } actions C++ { $(C++) -c "$(2)" $(C++FLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ; } #------------------------------------------------------------------------------- # General High-level OBOS target rules #------------------------------------------------------------------------------- rule App { # App : ; SetupObjectsDir ; Main $(<) : $(>) ; MakeLocate $(<) : $(OBOS_APPS_DIR) ; } rule BinCommand { # BinCommand : : ; SetupObjectsDir ; Main $(1) : $(2) ; MakeLocate $(1) : $(OBOS_BIN_DIR) ; LinkSharedOSLibs $(1) : $(3) ; } rule StdBinCommands { # StdBinCommands : ; local libs = $(2) ; local source ; for source in $(1) { local target = $(source:S=) ; target = [ FGristFiles $(target) ] ; BinCommand $(target) : $(source) : $(libs) ; } } rule Preference { # Preference : ; # SetupIncludes ; SetupObjectsDir ; Main $(<) : $(>) ; MakeLocate $(<) : $(OBOS_PREFS_DIR) ; } rule Server { # Server : ; # SetupIncludes ; SetupObjectsDir ; Main $(<) : $(>) ; MakeLocate $(<) : $(OBOS_SERVER_DIR) ; } # test pseudo targets NOTFILE obostests ; NOTFILE r5tests ; rule CommonTestLib { # CommonTestLib : : # : : : ; # Builds a unit test for both OBOS and R5 modules. # The name of the target. # The list of sources. # A list of link libraries for the OBOS tests (as passed # to LinkSharedOSLibs). # A list of link libraries for the R5 tests (as passed # to LinkSharedOSLibs). # A list of link libraries for both OBOS tests and R5 tests # that have a common name (i.e. specify libx.so and the OBOS tests will link # to libx.so and the R5 tests will link to libx_r5.so). # A list of public header dirs (as passed to # UsePublicHeaders). TestLib $(1) : $(2) : [ FDirName $(OBOS_TEST_DIR) unittester lib ] : $(3) $(5) : $(6) ; R5TestLib $(1) : $(2) : [ FDirName $(OBOS_TEST_DIR) unittester_r5 lib ] : $(4) [ R5SharedLibraryNames $(5) ] ; } rule TestLib { # TestLib : : : : # Builds a unit test library for an OBOS module. # The name of the target. # The list of sources. # The directory for the target (as passed to FDirName). # A list of link libraries (as passed to LinkSharedOSLibs). # A list of public header dirs (as passed to # UsePublicHeaders). local target = $(1) ; local sources = $(2) ; local dest = $(3) ; local libraries = $(4) ; local headerDirs = $(5) ; local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ; # Our Main replacement. MainFromObjects $(target) : $(objects) ; TestObjects $(sources) : $(headerDirs) ; MakeLocate $(target) : $(dest) ; Depends $(target) : libcppunit.so ; Depends obostests : $(target) ; LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ; LINKFLAGS on $(target) = $(LINKFLAGS) -nostart -Xlinker -soname=\"$(target)\" ; } rule R5TestLib { # R5TestLib : : : # Builds a unit test for an R5 module. "_r5" is appended to the object # and the target name. # The name of the target. # The list of sources. # The directory for the target (as passed to FDirName). # A list of link libraries (as passed to LinkSharedOSLibs). local target = $(1:B)_r5$(1:S) ; local sources = $(2) ; local dest = $(3) ; local libraries = $(4) ; local objects = [ R5ObjectNames $(sources) ] ; # Our Main replacement. MainFromObjects $(target) : $(objects) ; TestObjects $(sources) : : true ; MakeLocate $(target) : $(dest) ; Depends $(target) : libcppunit.so ; Depends r5tests : $(target) ; LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ; LINKFLAGS on $(target) = $(LINKFLAGS) -nostart -Xlinker -soname=\"$(target)\" ; } rule CommonUnitTest { # CommonUnitTest : : : # : : ; # Builds a unit test for both OBOS and R5 modules. # The name of the target. # The list of sources. # The directory for the target (as passed to FDirName). # A list of link libraries for the OBOS tests (as passed # to LinkSharedOSLibs). # A list of link libraries for the R5 tests (as passed # to LinkSharedOSLibs). # A list of public header dirs (as passed to # UsePublicHeaders). UnitTest $(1) : $(2) : $(3) : $(4) : $(6) ; R5UnitTest $(1) : $(2) : $(3) : $(5) ; } rule UnitTest { # UnitTest : : : : # Builds a unit test for an OBOS module. # The name of the target. # The list of sources. # The directory for the target (as passed to FDirName). # A list of link libraries (as passed to LinkSharedOSLibs). # A list of public header dirs (as passed to # UsePublicHeaders). local target = $(1) ; local sources = $(2) ; local dest = $(3) ; local libraries = $(4) ; local headerDirs = $(5) ; local objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ; # Our Main replacement. MainFromObjects $(target) : $(objects) ; TestObjects $(sources) : $(headerDirs) ; MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(dest) ] ; Depends $(target) : libcppunit.so ; Depends obostests : $(target) ; LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ; } rule R5UnitTest { # R5UnitTest : : : # Builds a unit test for an R5 module. "_r5" is appended to the object # and the target name. # The name of the target. # The list of sources. # The directory for the target (as passed to FDirName). # A list of link libraries (as passed to LinkSharedOSLibs). local target = $(1)_r5 ; local sources = $(2) ; local dest = $(3) ; local libraries = $(4) ; local objects = [ R5ObjectNames $(sources) ] ; # Our Main replacement. MainFromObjects $(target) : $(objects) ; TestObjects $(sources) : : true ; MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(dest) ] ; Depends $(target) : libcppunit.so ; Depends r5tests : $(target) ; LinkSharedOSLibs $(target) : libcppunit.so $(libraries) ; } rule R5ObjectNames { # R5ObjectNames ; # Returns a list of gristed object names given a list of source file names. # Moreover each object names gets "_r5" inserted before the object suffix. local objects = $(1:S=)_r5 ; return [ FGristFiles $(objects:S=$(SUFOBJ)) ] ; } rule R5Objects { # R5Objects # Similar to Objects, but appends "_r5" to the object file names. # The source files. local sources = $(1) ; local source ; for source in [ FGristFiles $(sources) ] { local object = [ R5ObjectNames $(source) ] ; Object $(object) : $(source) ; LocalDepends obj : $(object) ; } } rule TestObjects { # TestLib : : # Compiles objects for tests. # The list of sources. # A list of public header dirs (as passed to # UsePublicHeaders). # If set, "_r5" is appended to the object file names and # is ignored. Furthermore the pre-processor macro # TEST_R5 is defined, TEST_OBOS otherwise. local sources = $(1) ; local headerDirs = $(2) ; local r5 = $(3) ; local objects ; # Turn optimization off. if ! $(NO_TEST_DEBUG) { local optim = $(OPTIM) ; OPTIM = ; } SetupObjectsDir ; # compile if $(r5) { objects = [ R5ObjectNames $(sources) ] ; R5Objects $(sources) ; } else { objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ; Objects $(sources) ; } # set headers/defines UseCppUnitObjectHeaders $(objects) ; if $(r5) { ObjectDefines $(objects) : TEST_R5 ; } else { UsePublicObjectHeaders $(objects) : $(headerDirs) ; ObjectDefines $(objects) : TEST_OBOS ; } if ! $(NO_TEST_DEBUG) { # Turn debugging on. That is usually desired for test code. ObjectCcFlags $(objects) : "-g" ; ObjectC++Flags $(objects) : "-g" ; # Turn optimization on again. OPTIM = $(optim) ; } } rule R5SharedLibraryNames { # R5SharedLibraryNames ; # Returns a list of shared library names given a list of file names. NO # GRISTING IS PERFORMED :-) However, each library names gets "_r5" inserted # before the shared lib suffix. return $(1:S=)_r5.so ; } rule SimpleTest { # UnitTest : : # Builds a unit test for an OBOS module. # The name of the target. # The list of sources. # The directory for the target (as passed to FDirName). # A list of link libraries (as passed to LinkSharedOSLibs). # A list of public header dirs (as passed to # UsePublicHeaders). local target = $(1) ; local sources = $(2) ; local libraries = $(3) ; local relPath = [ FRelPath src tests : $(SUBDIR_TOKENS) ] ; # Turn optimization off. if ! $(NO_TEST_DEBUG) { local optim = $(OPTIM) ; OPTIM = ; } # SetupIncludes ; SetupObjectsDir ; MakeLocateObjects $(sources) ; Main $(target) : $(sources) ; MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(relPath) ] ; Depends obostests : $(target) ; LinkSharedOSLibs $(target) : $(libraries) ; ObjectDefines $(sources) : TEST_OBOS ; if ! $(NO_TEST_DEBUG) { # Turn debugging on. That is usually desired for test code. ObjectCcFlags $(sources) : "-g" ; ObjectC++Flags $(sources) : "-g" ; # Turn optimization on again. OPTIM = $(optim) ; } } rule Addon { # Addon : : ; # SetupIncludes ; SetupObjectsDir ; Main $(1) : $(3) ; # Create output dir path for addon local targetdir; targetdir = [ FDirName $(OBOS_ADDON_DIR) $(2) ] ; MakeLocate $(1) : $(targetdir) ; LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -nostart -Xlinker -soname=\"$(1)\" ; } rule R5KernelAddon { # R5KernelAddon : : ; local sources = $(3) ; Addon $(1) : $(2) : $(3) ; ObjectCcFlags $(sources) : -D_KERNEL_MODE=1 -no-fpic ; ObjectC++Flags $(sources) : -D_KERNEL_MODE=1 -no-fpic -fno-exceptions -fno-rtti ; LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -nostdlib ; LinkSharedOSLibs $(1) : /boot/develop/lib/x86/_KERNEL_ ; } rule Translator { # Translator : ; SetupObjectsDir ; Main $(1) : $(2) ; # Create output dir path for translator local targetdir; targetdir = [ FDirName $(OBOS_ADDON_DIR) translators ] ; MakeLocate $(1) : $(targetdir) ; } rule MakeLocateObjects { # MakeLocateObjects ; local _objs = $(1:S=$(SUFOBJ)) ; for o in $(_objs) { local dir = $(o:D) ; if $(dir) { MakeLocate $(o) : [ FDirName $(LOCATE_TARGET) $(dir) ] ; } else { MakeLocate $(o) : $(LOCATE_TARGET) ; } } } rule StaticLibrary { # StaticLibrary : ; # SetupIncludes ; SetupObjectsDir ; MakeLocateObjects $(2) ; Library lib$(<).a : $(>) ; MakeLocate lib$(<).a : $(OBOS_STLIB_DIR) ; } rule SharedLibrary { # SharedLibrary : ; local _lib = lib$(1).so ; # SetupIncludes ; SetupObjectsDir ; MakeLocateObjects $(2) ; Main $(_lib) : $(2) ; MakeLocate $(_lib) : $(OBOS_SHLIB_DIR) ; LINKFLAGS on $(_lib) = [ on $(_lib) return $(LINKFLAGS) ] -nostart -Xlinker -soname=\"$(_lib)\" ; } rule LinkSharedOSLibs { # LinkSharedOSLibs : ; # Valid elements for are e.g. "be" or "libopenbeos.so" or # "/boot/.../libfoo.so". If the basename starts with "lib" or the thingy # has a dirname or grist, it is added to the NEEDLIBS variable (i.e. the # file will be bound!), otherwise it is prefixed "-l" and added to # LINKLIBS. for i in $(>) { local isfile = ; if $(i:D) || $(i:G) { isfile = true ; } else { switch $(i:B) { case lib* : isfile = true ; case * : isfile = ; } } if $(isfile) { NEEDLIBS on $(1) = [ on $(1) return $(NEEDLIBS) ] $(i) ; Depends $(1) : $(i) ; } else { LINKLIBS on $(1) = [ on $(1) return $(LINKLIBS) ] -l$(i) ; } } } rule LinkStaticOSLibs { # LinkStaticOSLibs : ; for i in $(>) { LINKLIBS on $(<) = $(LINKLIBS) -l $(i) ; } } rule AddResources { # AddResources : ; SEARCH on $(2) += $(SEARCH_SOURCE) ; RESFILES on $(1) += $(2) ; } rule PublicHeaders { # PublicHeaders # # Returns the directory names for the public header dirs identified by # . local list = $(1) ; local dirs = [ FDirName $(OBOS_TOP) headers os ] ; for i in $(list) { dirs += [ FDirName $(OBOS_TOP) headers os $(i) ] ; } return $(dirs) ; } rule PrivateHeaders { # PrivateHeaders # # Returns the directory names for the private header dirs identified by # . local list = $(1) ; local dirs ; for i in $(list) { dirs += [ FDirName $(OBOS_TOP) headers private $(i) ] ; } return $(dirs) ; } rule ArchHeaders { # usage: ArchHeaders ; # # specifies the architecture (e.g. x86). return [ FDirName $(OBOS_TOP) headers private kernel arch $(1) ] ; } rule UsePublicHeaders { # UsePublicHeaders ; # # Adds the public C header dirs given by to the header search # dirs of the subdirectory. # NOTE: This rule must be invoked *before* the rule that builds the objects. UseHeaders [ PublicHeaders $(1) ] ; } rule UsePublicObjectHeaders { # UsePublicObjectHeaders : ; # # Adds the public C header dirs given by to the header search # dirs of . # NOTE: This rule must be invoked *after* the rule that builds the objects. ObjectHdrs $(1) : [ PublicHeaders $(2) ] ; } rule UsePrivateHeaders { # UsePrivateHeaders ; # # Adds the private C header dirs given by to the header search # dirs of the subdirectory. # NOTE: This rule must be invoked *before* the rule that builds the objects. UseHeaders [ PrivateHeaders $(1) ] ; } rule UsePrivateObjectHeaders { # UsePrivateObjectHeaders : ; # # Adds the private C header dirs given by to the header search # dirs of . # NOTE: This rule must be invoked *after* the rule that builds the objects. ObjectHdrs $(1) : [ PrivateHeaders $(2) ] ; } rule UseHeaders { # UseHeaders ; # # Adds the C header dirs to the header search # dirs of the subdirectory. # NOTE: This rule must be invoked *before* the rule that builds the objects. local header ; for header in $(1) { SubDirHdrs $(header) ; } } rule UseCppUnitHeaders { SubDirHdrs [ FDirName $(OBOS_TOP) headers tools cppunit ] ; } rule UseCppUnitObjectHeaders { ObjectHdrs $(1) : [ FDirName $(OBOS_TOP) headers tools cppunit ] ; } rule UseArchHeaders { # usage: UseArchHeaders ; # # specifies the architecture (e.g. x86). # NOTE: This rule must be invoked *before* the rule that builds the objects. local headers = [ ArchHeaders $(1) ] ; local opt = -D$(OBOS_TARGET_DEFINE) ; SubDirCcFlags $(opt) ; SubDirC++Flags $(opt) ; SubDirHdrs $(headers) ; } rule UseArchObjectHeaders { # usage: UseArchObjectHeaders : ; # # specifies the architecture (e.g. x86). # Source or object files. # NOTE: This rule must be invoked *after* the rule that builds the objects. local targets = $(1) ; local headers = [ ArchHeaders $(2) ] ; local opt = -D$(OBOS_TARGET_DEFINE) ; ObjectCcFlags $(targets) : $(opt) ; ObjectC++Flags $(targets) : $(opt) ; ObjectHdrs $(targets) : $(headers) ; } rule UsePosixHeaders { # UsePrivateHeaders ; # # Adds the POSIX header dir to the header search # dirs of the subdirectory. # NOTE: This rule must be invoked *before* the rule that builds the objects. SubDirHdrs [ FDirName $(OBOS_TOP) headers posix ] ; } rule UsePosixObjectHeaders { # UsePosixObjectHeaders ; # # Adds the POSIX header dir to the header search # dirs of . # NOTE: This rule must be invoked *after* the rule that builds the objects. ObjectHdrs $(1) : [ FDirName $(OBOS_TOP) headers posix ] ; } rule SplitPath { # SplitPath ; # Decomposes a path into its components. local path = $(1:G=) ; local components ; # $(path:D) for "/" is "/". Therefore the second condition. while $(path:D) && $(path:D) != $(path) { # Note: $(path:B) returns "." for "..", but $(path:D=) is fine. components = $(path:D=) $(components) ; path = $(path:D) ; } components = $(path) $(components) ; return $(components) ; } rule PrependObjectHdrs { # PrependObjectHdrs : ; # Prepends to the list of header search dirs of the objects # specified by . The HDRS variable will not be # changed, only CCHDRS. # Note: A subsequent ObjectHdrs invocation will therefore undo the # effect of this rule. # NOTE: This is a hack. local objects = [ FGristFiles $(1:S=$(SUFOBJ)) ] ; local dirs = $(2) ; for object in $(objects) { # Don't change HDRS to avoid screwing up the header scanning. PREPENDED_HDRS on $(object) = $(dirs) [ on $(object) return $(PREPENDED_HDRS) ] ; CCHDRS on $(object) = [ FIncludes [ on $(object) return $(PREPENDED_HDRS) $(HDRS) ] ] ; } } rule SymLink { # SymLink : ; # Links to . # is the exact link contents. No binding is done. LINKCONTENTS on $(1) = $(2) ; SymLink1 $(1) ; LocalDepends all : $(target) ; } actions SymLink1 { $(RM) "$(1)" && $(LN) -s "$(LINKCONTENTS)" "$(1)" } rule RelSymLink { # RelSymLink : # Creates a relative symbolic link from to . # and can be usual targets. They may have a grist # and don't need to have any dirname. Their LOCATE variables are used to # find their locations. local target = $(1) ; local source = $(2) ; local targetDir = [ on $(target) FDirName $(LOCATE[1]) $(target:D) ] ; local sourceDir = [ on $(source) FDirName $(LOCATE[1]) $(source:D) ] ; local sourcePath = $(source:G=) ; sourcePath = $(sourcePath:D=$(sourceDir)) ; local targetDirComponents = [ SplitPath $(targetDir) ] ; local sourceComponents = [ SplitPath $(sourcePath) ] ; SymLink $(target) : [ FRelPath $(targetDirComponents) : $(sourceComponents) ] ; NOUPDATE $(target); Depends $(target) : $(source) ; } #------------------------------------------------------------------------------- # Low-level OBOS utility rules #------------------------------------------------------------------------------- rule SetupObjectsDir { local rel_objectsdir; # Copy subdir tokens except the first, as that will be "sources", and we # do not want to include that :) rel_objectsdir = [ FDirName $(SUBDIR_TOKENS[2-]) ] ; LOCATE_TARGET = [ FDirName $(OBOS_OBJECT_TARGET) $(rel_objectsdir) ] ; } #------------------------------------------------------------------------------- # Link rule/action are overwritten as they don't handle linking files who's name # contain spaces very well. Also adds resources and version to executable. #------------------------------------------------------------------------------- rule Link { # Note: RESFILES must be set before invocation. MODE on $(<) = $(EXEMODE) ; on $(1) XRes $(1) : $(RESFILES) ; SetVersion $(1) ; Chmod $(<) ; SetType $(1) ; MimeSet $(1) ; } actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) -o "$(1)" $(UNDEFS) "$(2)" "$(NEEDLIBS)" $(LINKLIBS) ; } # BeOS specific rules rule XRes { # XRes : if $(2) { Depends $(1) : $(2) ; XRes1 $(1) : $(2) ; } } rule XRes1 { } rule SetVersion { # SetVersion } rule SetType { # SetType } rule MimeSet { # SetType } if $(OS) = BEOS { actions XRes1 { xres -o "$(1)" "$(2)" ; } actions SetVersion { setversion "$(1)" -system $(OBOS_BUILD_VERSION) -short "$(OBOS_BUILD_DESCRIPTION)" ; } actions SetType { settype -t $(OBOS_TARGET_TYPE) "$(1)" ; } actions MimeSet { mimeset -f "$(1)" ; } } # if BEOS rule assemble { Depends $(<) : $(>) ; ASFLAGS on $(<) += $(ASFLAGS) $(SUBDIRASFLAGS) ; ASHDRS on $(<) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ; } actions assemble { $(CC) -c "$(2)" -O2 $(ASFLAGS) $(KERNEL_CCFLAGS) $(ASHDRS) -o "$(1)" ; } # Overridden to allow spaces in file names. actions Chmod1 { $(CHMOD) "$(MODE)" "$(1)" } rule ObjectReference { # ObjectReference : # Makes refer to the same file as . # The filenames must of course be identical. # must have already been LOCATEd. local ref = $(1) ; local source = $(2) ; if $(ref) != $(source) { Depends $(ref) : $(source) ; on $(ref) LOCATE = [ on $(source) return $(LOCATE) ] ; } } rule ObjectReferences { # ObjectReferences # Creates local references to , i.e. identifiers with the # current grist referring to the same files. must have # already been LOCATEd. local source ; for source in $(1) { ObjectReference [ FGristFiles $(source) ] : $(source) ; } } rule Filter { # Filter : ; # Removes all occurrences of in . local list = $(1) ; local excludes = $(2) ; local newList ; local item ; for item in $(list) { local skip ; local exclude ; for exclude in $(excludes) { if $(item) = $(exclude) { skip = true ; } } if ! $(skip) { newList += item ; } } return $(newList) ; } ## Kernel stuff! rule SetupKernel { # Usage SetupKernel : ; local _objs = $(1:S=$(SUFOBJ)) ; UsePublicHeaders kernel support drivers ; UsePublicHeaders [ FDirName os kernel ] ; UsePrivateHeaders kernel ; UsePosixHeaders ; UseArchHeaders $(OBOS_ARCH) ; SetupObjectsDir ; CCFLAGS on $(_objs) = $(KERNEL_CCFLAGS) $(2) ; C++FLAGS on $(_objs) = $(KERNEL_CCFLAGS) $(2) ; } rule KernelObjects { SetupKernel $(1) : $(2) ; Objects $(1) ; } rule KernelLd { # KernelLd : : : : ; SetupKernel $(2) ; LINK on $(1) = ld ; LINKFLAGS on $(1) = $(4) ; if $(3) { LINKFLAGS on $(1) += --script=$(3) ; } # Remove any preset LINKLIBS LINKLIBS on $(1) = ; # Show that we depend on the libraries we need LocalClean clean : $(1) ; LocalDepends all : $(1) ; Depends $(1) : $(2) ; if $(6) { for i in $(6) { KernelConfigSection $(i) : elf32 : $(1) ; } } MakeLocate $(1) : $(LOCATE_TARGET) ; # Add libgcc.a - NB this should be detected not hard coded! if ! $(5) { LINKLIBS on $(1) += -L $(GCC_PATH) -lgcc ; } } actions KernelLd { $(LINK) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) ; } rule KernelStaticLibrary { # Usage KernelStaticLibrary : : ; # This is designed to take a set of sources and libraries and create # a file called lib.a SetupKernel $(2) : $(3) ; MakeLocateObjects $(2) ; Library $(1) : $(2) ; } rule KernelStaticLibraryObjects { # Usage KernelStaticLibrary : ; # This is designed to take a set of sources and libraries and create # a file called SetupKernel $(2) ; # Show that we depend on the libraries we need LocalClean clean : $(1) ; LocalDepends all : $(1) ; Depends $(1) : $(2) ; MakeLocate $(1) : $(LOCATE_TARGET) ; } actions KernelStaticLibraryObjects { ar -r "$(1)" "$(2)" ; } rule SystemMain { # Usage SystemMain : ; SetupObjectsDir ; LINKLIBS on $(1) = ; Main $(1) : $(2) ; } rule KernelConfigSection { # KernelConfigSection
: : ; SECTION_NAMES on $(OBOS_KERNEL_CONFIG) += $(1) ; SECTION_TYPES on $(OBOS_KERNEL_CONFIG) += $(2) ; SECTION_FILES on $(OBOS_KERNEL_CONFIG) += $(3) ; Depends $(OBOS_KERNEL_CONFIG) : $(3) ; } rule WriteKernelConfig { # usage: WriteKernelConfig ; LocalDepends files : $(1) ; MakeLocate $(1) : $(OBOS_OBJECT_TARGET) ; LocalClean clean : $(1) ; } actions WriteKernelConfig bind SECTION_FILES { target="$(1)" echo "# OpenBeOS Kernel Config File" > "$target" echo "# Automatically generated - do not edit!" >> "$target" count=0 for section in "$(SECTION_NAMES)" ; do count=`expr $count + 1` eval section$count="$section" done i=1 for type in "$(SECTION_TYPES)" ; do eval type$i="$type" i=`expr $i + 1` done i=1 for file in "$(SECTION_FILES)" ; do eval file$i="$file" i=`expr $i + 1` done for i in `seq $count` ; do eval section="\$section$i" eval type="\$type$i" eval file="\$file$i" echo "" >> "$target" echo "["$section"]" >> "$target" echo "type="$type >> "$target" case "$file" in /*) ;; *) file=`pwd`/"$file";; esac echo "file="$file >> "$target" done } rule BuildKernel { # Usage BuildKernel : ; local kernel = $(1) ; local configFile = $(2) ; local bootmaker = bootmaker ; LocalDepends all : $(kernel) ; Depends $(kernel) : $(configFile) $(bootmaker) ; LocalClean clean : $(kernel) ; MakeLocate $(kernel) : $(LOCATE_TARGET) ; BOOT_MAKER on $(kernel) = $(bootmaker) ; } actions BuildKernel bind BOOT_MAKER { "$(BOOT_MAKER)" --strip-debug --strip-binary strip "$(2)" -o "$(1)" ; echo "" echo "Kernel linked!" echo "" } rule KernelFloppyImage { # Usage KernelFloppyImage : : ; local floppy = $(1) ; local kernel = $(2) ; local bootblock = $(3) ; local makeflop = makeflop ; LocalDepends all : $(floppy) ; Depends $(floppy) : $(kernel) $(bootblock) $(makeflop) ; LocalClean clean : $(floppy) ; MakeLocate $(floppy) : $(OBOS_OBJECT_TARGET) ; BOOT_BLOCK on $(floppy) = $(bootblock) ; MAKE_FLOP on $(floppy) = $(makeflop) ; } # This may be a bit verbose, but I think it's useful to show what's # going on, at least in this early stage of development. actions KernelFloppyImage bind BOOT_BLOCK bind MAKE_FLOP { "$(MAKE_FLOP)" "-p $(shell expr 18 \* 2 \* 512)" "$(BOOT_BLOCK)" "$(2)" "$(1)" ; echo "" echo "*************************************************" echo "* Kernel build completed! *" echo "* Boot image for a 1.44M floppy created *" echo "*************************************************" echo "" echo "Floppy image is $(1)" echo "The following command will write it to a floppy on BeOS" echo " dd if=$(1) of=/dev/disk/floppy/raw bs=18k" echo "Alternatively you can run" echo " ./configure --floppy /dev/disk/floppy/raw" echo "once and build + write the image subsequently via" echo " jam installfloppy" echo "" } rule InstallFloppy { # InstallFloppy : # "dd"s to $(FLOPPY_PATH). local target = $(1) ; local floppy = $(2) ; NotFile $(target) ; Always $(target) ; Depends $(target) : $(floppy) ; } actions InstallFloppy { if [ -z $(FLOPPY_PATH) ] ; then echo "Can't install floppy: FLOPPY_PATH not set." echo "run: ./configure --floppy " echo exit 0 fi dd if=$(2) of=$(FLOPPY_PATH) bs=18k }