# Haiku main build rules # 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 # The directory for build system specific files OBOS_BUILD_DIR = [ FDirName $(OBOS_TOP) build ] ; # Cache files for header scanning and jamfile caching HCACHEFILE = header_cache ; JCACHEFILE = jamfile_cache ; LOCATE on $(HCACHEFILE) $(JCACHEFILE) = $(OBOS_BUILD_DIR) ; # Include BuildConfig/Timezones/libgccObjects { local buildConfig = [ GLOB $(OBOS_BUILD_DIR) : BuildConfig ] ; local timezones = [ GLOB $(OBOS_BUILD_DIR) : Timezones ] ; local libgccObjects = [ GLOB $(OBOS_BUILD_DIR) : libgccObjects ] ; if ! $(buildConfig) { ECHO "No `BuildConfig' found in $(OBOS_BUILD_DIR)!" ; EXIT "Run ./configure in the source tree's root directory first!" ; } if ! ( $(timezones) && $(libgccObjects) ) { ECHO "No `Timezones' or `libgccObjects' found in $(OBOS_BUILD_DIR)!" ; EXIT "Please run ./configure in the source tree's root directory again!" ; } LOCATE on BuildConfig = $(OBOS_BUILD_DIR) ; LOCATE on Timezones = $(OBOS_BUILD_DIR) ; LOCATE on libgccObjects = $(OBOS_BUILD_DIR) ; include BuildConfig ; include Timezones ; include libgccObjects ; } # analyze GCC version if ! $(GCC_RAW_VERSION) { ECHO "Variable GCC_RAW_VERSION not set. Please run ./configure or" ; EXIT "specify it manually." ; } GCC_VERSION = ; { # split the raw version string at `.' and `-' characters local version = $(GCC_RAW_VERSION) ; while $(version) { local split = [ Match "([^.-]*)[.-](.*)" : $(version) ] ; if $(split) { GCC_VERSION += $(split[1]) ; version = $(split[2]) ; } else { GCC_VERSION += $(version) ; version = ; } } } # Save the platform default headers. PLATFORM_DEFAULT_HEADERS = $(HDRS) ; # Add some grist to the libgcc objects LIBGCC_OBJECTS = $(LIBGCC_OBJECTS:G=libgcc) ; # We do not include any local BeOS system headers by default CCFLAGS += -nostdinc ; C++FLAGS += -nostdinc ; # Allow compiling unit tests on Zeta. Instead of fixing the PostMessage() # issues, they deprecated that nice function. This will enable it again: C++FLAGS += -D_ZETA_USING_DEPRECATED_API_=1 ; if ! $(TARGET_PLATFORM) { ECHO "Variable TARGET_PLATFORM not set. Please run ./configure or" ; EXIT "specify it manually." ; } switch $(TARGET_PLATFORM) { case r5 : { # "everything" is r5 compatible } case bone : { BONE_COMPATIBLE = true ; } case dano : { BONE_COMPATIBLE = true ; DANO_COMPATIBLE = true ; } case haiku : { BONE_COMPATIBLE = true ; DANO_COMPATIBLE = true ; HAIKU_COMPATIBLE = true ; DEFINES += __HAIKU__ ; } } if $(BONE_COMPATIBLE) { NETWORK_LIBS = libsocket.so libbind.so ; NETAPI_LIB = libbnetapi.so ; SELECT_UNAME_ETC_LIB = libroot.so ; } else { NETWORK_LIBS = libnet.so ; NETAPI_LIB = libnetapi.so ; SELECT_UNAME_ETC_LIB = libnet.so ; } # Determine if we're building on PPC or x86 # Determine mimetype of executable # Cross compiling can come later TARGET_CPU ?= $(OSPLAT:L) ; OBOS_VERSION ?= R1 ; switch $(TARGET_CPU) { case ppc : { if $(METROWERKS) { # at least parts of OpenBeOS still can be compiled with # the Metrowerks compiler on BeOS/PPC OBOS_TARGET_TYPE ?= "application/x-be-executable" ; } else { OBOS_TARGET_TYPE ?= "application/x-vnd.Be-elfexecutable" ; } DEFINES += __POWERPC__ ARCH_ppc ; OBOS_BOOT_PLATFORM = openfirmware ; } case x86 : { # nothing special to do here... DEFINES += __INTEL__ ARCH_x86 ; OBOS_BOOT_PLATFORM = bios_ia32 ; } case * : Exit "Currently unsupported build platform:" $(TARGET_CPU) ; } # set target specific variables { #Echo "Building for" $(TARGET_CPU) ; OBOS_TARGET ?= $(TARGET_CPU).$(OBOS_VERSION) ; OBOS_TARGET_TYPE ?= "application/x-vnd.Be-elfexecutable" ; OBOS_ARCH ?= $(TARGET_CPU) ; OBOS_TARGET_DEFINE ?= "ARCH_"$(TARGET_CPU) ; } # Disable warnings only if WARNINGS is set to 0 # Should be enabled by default later # WARNINGS ?= 1 ; if $(WARNINGS) = 1 { # 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 ; } else { CCFLAGS += -Wno-multichar ; C++FLAGS += -Wno-multichar ; } # standard kernel C/C++ flags KERNEL_CCFLAGS ?= -Wall -Wno-multichar -Wmissing-prototypes -finline -nostdinc ; KERNEL_CCFLAGS += -fno-builtin -D$(OBOS_TARGET_DEFINE) -D__HAIKU__ ; KERNEL_CCFLAGS += -DBOCHS_DEBUG_HACK=$(BOCHS_DEBUG_HACK) -D_KERNEL_MODE ; KERNEL_C++FLAGS ?= -Wall -Wno-multichar -Wmissing-prototypes -finline -nostdinc ; KERNEL_C++FLAGS += -fno-builtin -fno-exceptions -D$(OBOS_TARGET_DEFINE) -D__HAIKU__ ; KERNEL_C++FLAGS += -DBOCHS_DEBUG_HACK=$(BOCHS_DEBUG_HACK) -D_KERNEL_MODE ; if $(GCC_VERSION[1]) >= 3 { KERNEL_C++FLAGS += -fno-use-cxa-atexit ; } DEBUG_FLAGS ?= -g ; # We might later want to introduce debug levels or handle the whole issue # differently. For now there's only on or off. # DEBUG ?= 0 ; if $(DEBUG) != 0 { OPTIM ?= -O0 ; CCFLAGS += $(DEBUG_FLAGS) [ FDefines DEBUG=$(DEBUG) ] ; C++FLAGS += $(DEBUG_FLAGS) [ FDefines DEBUG=$(DEBUG) ] ; KERNEL_CCFLAGS += $(DEBUG_FLAGS) [ FDefines DEBUG=$(DEBUG) ] ; KERNEL_C++FLAGS += $(DEBUG_FLAGS) [ FDefines DEBUG=$(DEBUG) ] ; LINKFLAGS += $(DEBUG_FLAGS) ; } else { OPTIM ?= -O2 ; } # # To disable for the tests OPTIM and DEBUG are overridden, set the environment # variable NO_TEST_DEBUG. # If the environment variable DEBUG_PRINTF is defined we define an equally # named macro to the variable value. Some components use the macro to allow # another function than printf() to print the debug output. The variable should # be set to the name of the alternative function. # if $(DEBUG_PRINTF) { CCFLAGS += [ FDefines DEBUG_PRINTF=$(DEBUG_PRINTF) ] ; C++FLAGS += [ FDefines DEBUG_PRINTF=$(DEBUG_PRINTF) ] ; } # Instructs the Library rule to not make its object files temporary. # This is needed as some objects are used in a static library and for an # executable. KEEPOBJS = true ; # under BeOS use copyattr instead of cp if $(OS) = BEOS { CP = copyattr --data ; } # for builds of tools in the current environment if $(OS) = BEOS { BUILD_LIBSTDC++ = stdc++.r4 ; } else { BUILD_LIBSTDC++ = stdc++ ; } if $(GCC_VERSION[1]) >= 3 { C++_SUPPORT_LIBS = supc++ ; KERNEL_C++_SUPPORT_LIBS = -L/usr/lib -l$(C++_SUPPORT_LIBS) -lgcc_eh ; # TODO: -L/usr/lib is a bit Linux specific. STL_HEADERS = /usr/include/g++ ; # TODO: Also a bit Linux specific. } else { C++_SUPPORT_LIBS = ; KERNEL_C++_SUPPORT_LIBS = ; STL_HEADERS = [ FDirName $(OBOS_TOP) headers cpp ] ; } # 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 OBOS_ADDON_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system add-ons ] ; OBOS_APPS_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos apps ] ; OBOS_BIN_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos bin ] ; OBOS_ETC_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos etc ] ; OBOS_FONTS_DIR ?= [ FDirName $(OBOS_ETC_DIR) fonts ] ; OBOS_KERNEL_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system ] ; OBOS_PREFS_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos preferences ] ; OBOS_SERVER_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system servers ] ; OBOS_SHLIB_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) beos system lib ] ; OBOS_STLIB_DIR ?= [ FDirName $(OBOS_DISTRO_TARGET) develop lib $(OBOS_ARCH) ] ; OBOS_TEST_DIR ?= [ FDirName $(OBOS_TOP) tests ] ; OBOS_PACKAGE_DIR ?= [ FDirName $(OBOS_TOP) packages $(OBOS_TARGET) ] ; OBOS_PACKAGE_OBJECT_DIR ?= [ FDirName $(OBOS_OBJECT_TARGET) packages ] ; OBOS_KERNEL_CONFIG = config.$(OBOS_ARCH).ini ; OBOS_KERNEL = kernel.$(OBOS_ARCH) ; OBOS_FLOPPY = floppy.$(OBOS_ARCH) ; rule SetupIncludes { local os_includes = add-ons add-ons/file_system add-ons/graphics add-ons/input_server add-ons/screen_saver add-ons/tracker app device drivers game interface kernel media mail midi midi2 net storage support translation opengl ; # Overwrite any exiting content when changing HDRS. This rule may be invoked multiple times. # Use headers directory, to allow to do things like include HDRS = [ FDirName $(OBOS_TOP) headers ] ; # Use posix headers directory HDRS += [ FDirName $(OBOS_TOP) headers posix ] ; # TODO: This is actually more correct. Under BeOS # /boot/develop/headers/posix/_G_config.h is included, which is not correct, # since we use another glibc version. This might even be a reason why STL # string has problems (see strace sources). The problem is just that there # are conflicts with STL/gcc headers, if we do that. # # This is nasty, but we don't get around it, since some public headers # # include _G_config.h which in turn includes other private headers. # HDRS += [ FDirName $(OBOS_TOP) src kernel libroot posix glibc include ] ; # HDRS += [ FDirName $(OBOS_TOP) src kernel libroot posix glibc include arch # $(OBOS_ARCH) ] ; # HDRS += [ FDirName $(OBOS_TOP) src kernel libroot posix glibc ] ; # HDRS += [ FDirName $(OBOS_TOP) src kernel libroot posix glibc libio ] ; # # for _G_config.h HDRS += $(STL_HEADERS) ; # Use public OS header directories HDRS += [ PublicHeaders $(os_includes) ] ; # Use the root of the private headers -- not so nice, but simplifies things. HDRS += [ PrivateHeaders $(DOT) ] ; # Used as a fallback, the R5 header directories (we should remove this as soon as possible) HDRS += /boot/develop/headers/posix /boot/develop/headers/cpp ; # The platform dependent headers. HDRS += $(PLATFORM_HEADERS) ; } rule SetupR5Includes { # Unsets HDRS, so that the OBOS headers do not `shadow' the system headers. HDRS = ; } rule SetupDefaultIncludes { # Resets HDRS to the default headers for the build platform. HDRS = $(PLATFORM_DEFAULT_HEADERS) ; } #------------------------------------------------------------------------------- # Things Jam needs in order to work :) #------------------------------------------------------------------------------- # TODO: back-ported from jam 2.5: remove when not longer needed rule MakeLocate { if $(>) { LOCATE on $(<) = $(>) ; Depends $(<) : $(>[1]:G=dir) ; MkDir $(>[1]:G=dir) ; } } rule Object { # This is basically the original Jambase 2.4 Object rule stripped by # comments. Only the final switch statement has been changed to allow # intermediate C++ files for Yacc and Lex. LocalClean clean : $(<) ; MakeLocate $(<) : $(LOCATE_TARGET) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; HDRS on $(<) = $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ; HDRRULE on $(>) = HdrRule ; HDRSCAN on $(>) = $(HDRPATTERN) ; HDRSEARCH on $(>) = $(SEARCH_SOURCE:E) $(SUBDIRHDRS) $(HDRS) $(STDHDRS) ; HDRGRIST on $(>) = $(HDRGRIST) ; DEFINES on $(<) += $(DEFINES) ; # if source is not .c, generate .c with specific rule switch $(>:S) { case .asm : As $(<) : $(>) ; case .c : Cc $(<) : $(>) ; case .C : C++ $(<) : $(>) ; case .cc : C++ $(<) : $(>) ; case .cpp : C++ $(<) : $(>) ; case .f : Fortran $(<) : $(>) ; case .l : if [ on $(2) return $(GENERATE_C++) ] { C++ $(<) : $(<:S=.cpp) ; LexC++ $(<:S=.cpp) : $(>) ; } else { Cc $(<) : $(<:S=.c) ; Lex $(<:S=.c) : $(>) ; } case .s : As $(<) : $(>) ; case .y : if [ on $(2) return $(GENERATE_C++) ] { C++ $(<) : $(<:S=.cpp) ; Bison $(<:S=.cpp) : $(>) ; } else { Cc $(<) : $(<:S=$(YACCGEN)) ; Yacc $(<:S=$(YACCGEN)) : $(>) ; } case * : UserObject $(<) : $(>) ; } } 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) $(CCFLAGS) -c "$(2)" $(CCDEFS) $(CCHDRS) -o "$(1)" ; } actions C++ { $(C++) -c "$(2)" $(C++FLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ; } #------------------------------------------------------------------------------- # General High-level OBOS target rules #------------------------------------------------------------------------------- rule App { # App : : : ; SetupIncludes ; SetupObjectsDir ; AddResources $(1) : $(4) ; Main $(1) : $(2) ; MakeLocate $(1) : $(OBOS_APPS_DIR) ; LinkSharedOSLibs $(1) : $(3) ; LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -Xlinker -soname=_APP_ ; } rule BinCommand { # BinCommand : : : ; SetupIncludes ; SetupObjectsDir ; AddResources $(1) : $(4) ; Main $(1) : $(2) ; MakeLocate $(1) : $(OBOS_BIN_DIR) ; LinkSharedOSLibs $(1) : $(3) ; LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -Xlinker -soname=_APP_ ; } rule StdBinCommands { # StdBinCommands : : ; SetupIncludes ; SetupObjectsDir ; local libs = $(2) ; local ress = $(3) ; local source ; for source in $(1) { local target = $(source:S=) ; BinCommand $(target) : $(source) : $(libs) : $(ress) ; } } rule Preference { # Preference : : : ; SetupIncludes ; SetupObjectsDir ; AddResources $(1) : $(4) ; Main $(1) : $(2) ; MakeLocate $(1) : $(OBOS_PREFS_DIR) ; LinkSharedOSLibs $(1) : $(3) ; LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -Xlinker -soname=_APP_ ; } rule Server { # Server : : ; SetupIncludes ; SetupObjectsDir ; Main $(1) : $(2) ; MakeLocate $(1) : $(OBOS_SERVER_DIR) ; LinkSharedOSLibs $(1) : $(3) ; LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -Xlinker -soname=_APP_ ; } # 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 and # removes `-nostdinc' from the CC and C++ flags to enable system headers. # The source files. # Remove `-nostdinc' from CCFLAGS and C++FLAGS. local oldCCFLAGS = $(CCFLAGS) ; local oldC++FLAGS = $(C++FLAGS) ; CCFLAGS = [ Filter $(CCFLAGS) : -nostdinc ] ; C++FLAGS = [ Filter $(C++FLAGS) : -nostdinc ] ; local sources = $(1) ; local source ; for source in [ FGristFiles $(sources) ] { local object = [ R5ObjectNames $(source) ] ; Object $(object) : $(source) ; LocalDepends obj : $(object) ; } # Reset CCFLAGS and C++FLAGS to original values. CCFLAGS = $(oldCCFLAGS) ; C++FLAGS = $(oldC++FLAGS) ; } 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) { SetupR5Includes ; objects = [ R5ObjectNames $(sources) ] ; R5Objects $(sources) ; } else { SetupIncludes ; objects = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ; Objects $(sources) ; } # set headers/defines UseCppUnitObjectHeaders $(sources) : $(objects) ; if $(r5) { ObjectsDefines $(objects) : TEST_R5 ; } else { UsePublicObjectHeaders $(sources) : $(headerDirs) : $(objects) ; ObjectsDefines $(objects) : TEST_OBOS ; } if ! $(NO_TEST_DEBUG) { # Turn debugging on. That is usually desired for test code. ObjectCcFlags $(objects) : $(DEBUG_FLAGS) ; ObjectC++Flags $(objects) : $(DEBUG_FLAGS) ; # 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) ; ObjectsDefines $(sources) : TEST_OBOS ; if ! $(NO_TEST_DEBUG) { # Turn debugging on. That is usually desired for test code. ObjectCcFlags $(sources) : $(DEBUG_FLAGS) ; ObjectC++Flags $(sources) : $(DEBUG_FLAGS) ; # Turn optimization on again. OPTIM = $(optim) ; } } rule Addon { # Addon : : : : ; # : Name of the add-on. # : Path where the add-on shall live relative to the add-on dir. # : Source files. # : true, if the target shall be executable as well. # : Libraries to be linked against. local isExecutable = $(4) ; SetupIncludes ; SetupObjectsDir ; Main $(1) : $(3) ; # Create output dir path for addon local targetdir; targetdir = [ FDirName $(OBOS_ADDON_DIR) $(2) ] ; MakeLocate $(1) : $(targetdir) ; local linkFlags = -Xlinker -soname=\"$(1)\" ; if $(isExecutable) != true { linkFlags = -nostart $(linkFlags) ; } LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] $(linkFlags) ; LinkSharedOSLibs $(1) : $(5) ; } rule R5KernelAddon { # R5KernelAddon : : : ; local sources = $(3) ; Addon $(1) : $(2) : $(3) ; ObjectCcFlags $(sources) : -D_KERNEL_MODE=1 -fno-pic ; ObjectC++Flags $(sources) : -D_KERNEL_MODE=1 -fno-pic -fno-exceptions ; LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -nostdlib ; LinkSharedOSLibs $(1) : $(4) /boot/develop/lib/x86/_KERNEL_ ; } rule Translator { # Translator : : ; SetupIncludes ; SetupObjectsDir ; Main $(1) : $(2) ; LinkSharedOSLibs $(1) : $(3) ; # Create output dir path for translator local targetdir; targetdir = [ FDirName $(OBOS_ADDON_DIR) Translators ] ; MakeLocate $(1) : $(targetdir) ; } rule ScreenSaver { # ScreenSaver : : ; Addon $(1) : screen_savers : $(2) : false : $(3) ; } rule MakeLocateObjects { # MakeLocateObjects ; local _objs = [ FGristFiles $(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 : [ : [ : ] ] ; # Creates a static library from sources. # : Basename of the library, without leading "lib" and trailing ".a". # Grist is allowed -- it will be re-prepended after constructing # the complete library name. # : List of source files. # : Directory into which the library shall be placed. Defaults # to the objects directory for this subdir. If # STATIC_LIBRARY_DIR is supplied (the literal string) # the standard directory for static libs is used, otherwise # the parameter is interpreted as directory path. # : static libraries to include (ie: libmesa_x86.a) local lib = lib$(1:B)$(SUFLIB) ; lib = $(lib:G=$(1:G)) ; SetupIncludes ; SetupObjectsDir ; MakeLocateObjects $(2) ; StaticLibraryFromObjects $(lib) : [ FGristFiles $(2:S=$(SUFOBJ)) ] ; Objects $(2) ; if $(4) { StaticLibraryFromObjects $(lib) : $(4) ; } local targetDir = $(3) ; if $(targetDir) { if $(targetDir) = STATIC_LIBRARY_DIR { targetDir = $(OBOS_STLIB_DIR) ; } MakeLocate $(lib) : $(targetDir) ; } else { # nothing to do, since the Library rule already located the library # in $(LOCATE_TARGET) } # If KEEPOBJS is set, Library doesn't make the library depend on # `lib'. if $(KEEPOBJS) { LocalDepends lib : $(lib) ; } } rule StaticLibraryFromObjects { local _i _l _s ; # Add grist to file names _s = $(>) ; _l = $(<:S=$(SUFLIB)) ; # library depends on its member objects if $(KEEPOBJS) { LocalDepends obj : $(_s) ; } else { LocalDepends lib : $(_l) ; } # Set LOCATE for the library and its contents. The bound # value shows up as $(NEEDLIBS) on the Link actions. # For compatibility, we only do this if the library doesn't # already have a path. if ! $(_l:D) { MakeLocate $(_l) $(_l)($(_s:BS)) : $(LOCATE_TARGET) ; } if $(NOARSCAN) { # If we can't scan the library to timestamp its contents, # we have to just make the library depend directly on the # on-disk object files. Depends $(_l) : $(_s) ; } else { # If we can scan the library, we make the library depend # on its members and each member depend on the on-disk # object file. Depends $(_l) : $(_l)($(_s:BS)) ; for _i in $(_s) { Depends $(_l)($(_i:BS)) : $(_i) ; } } LocalClean clean : $(_l) ; if $(CRELIB) { CreLib $(_l) : $(_s[1]) ; } Archive $(_l) : $(_s) ; if $(RANLIB) { Ranlib $(_l) ; } # If we can't scan the library, we have to leave the .o's around. if ! ( $(NOARSCAN) || $(NOARUPDATE) ) { RmTemps $(_l) : $(_s) ; } } rule R5KernelStaticLibrary { # R5KernelStaticLibrary : ; local lib = lib$(1)$(SUFLIB) ; local sources = $(2) ; SetupIncludes ; SetupObjectsDir ; MakeLocateObjects $(sources) ; Library $(lib) : $(sources) ; ObjectCcFlags $(sources) : -D_KERNEL_MODE=1 -fno-pic ; ObjectC++Flags $(sources) : -D_KERNEL_MODE=1 -fno-pic -fno-exceptions ; } rule MergeObjectFromObjects { # MergeObjectFromObjects : : ; # Merges object files to an object file. # : Name of the object file to create. No grist will be added. # : Object files to be merged. Grist will be added. # : Object files or static libraries to be merged. No grist # will be added. # local objects = [ FGristFiles $(2) ] ; MakeLocate $(1) : $(LOCATE_TARGET) ; Depends $(1) : $(objects) ; Depends $(1) : $(3) ; LINK on $(1) = ld ; MergeObjectFromObjects1 $(1) : $(objects) $(3) ; } actions MergeObjectFromObjects1 { $(LINK) -r $(2) -o $(1) ; } rule MergeObject { # MergeObject : : ; # Compiles source files and merges the object files to an object file. # : Name of the object file to create. No grist will be added. # : Sources to be compiled. Grist will be added. # : Object files or static libraries to be merged. No grist # will be added. # SetupIncludes ; SetupObjectsDir ; MakeLocateObjects $(2) ; Objects $(2) ; MergeObjectFromObjects $(1) : $(2:S=$(SUFOBJ)) : $(3) ; } rule SharedLibraryFromObjects { # SharedLibraryFromObjects : : ; local _lib = lib$(1:B).so ; _lib = $(_lib:G=$(1:G)) ; MainFromObjects $(_lib) : $(2) ; MakeLocate $(_lib) : $(OBOS_SHLIB_DIR) ; LINKFLAGS on $(_lib) = [ on $(_lib) return $(LINKFLAGS) ] -nostart -Xlinker -soname=\"$(_lib)\" ; LinkSharedOSLibs $(_lib) : $(3) ; } rule SharedLibrary { # SharedLibrary : : ; SetupIncludes ; SetupObjectsDir ; MakeLocateObjects $(2) ; Objects $(2) ; SharedLibraryFromObjects $(1) : $(2:S=$(SUFOBJ)) : $(3) ; } 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. If you want to specify a target that isn't a library and # also has neither grist nor a dirname, you can prepend "" as # grist; it will be stripped by this rule. for i in $(>) { local isfile = ; if $(i:D) || $(i:G) { isfile = true ; if $(i:G) = { i = $(i:G=) ; } } else { switch $(i:B) { # XXX: _APP_ and _KERNEL_ should not be needed for ELF. case _APP_ : isfile = true ; case _KERNEL_ : isfile = true ; case lib* : isfile = true ; case * : isfile = ; } if ! $(isfile) && ( $(i:S) = .so || $(i:S) = .a ) { isfile = true ; } } if $(isfile) { NEEDLIBS on $(1) = [ on $(1) return $(NEEDLIBS) ] $(i) ; Depends $(1) : $(i) ; } else { LINKLIBS on $(1) = [ on $(1) return $(LINKLIBS) ] -l$(i) ; } } } rule AddResources { # AddResources : ; local resfiles = [ FGristFiles $(2) ] ; SEARCH on $(resfiles) += $(SEARCH_SOURCE) ; for file in $(resfiles) { if $(file:S) = .rdef { local rdef = $(file) ; file = $(rdef:S=.rsrc) ; ResComp $(file) : $(rdef) ; } RESFILES on $(1) += $(file) ; } } if $(OS) = BEOS { rule ResComp { # ResComp : ; # # and must be gristed. SetupObjectsDir ; SEARCH on $(2) += $(SEARCH_SOURCE) ; MakeLocate $(1) : $(LOCATE_TARGET) ; Depends $(1) : $(2) rc ; LocalClean clean : $(1) ; ResComp1 $(1) : rc $(2) ; } } else { rule ResComp { } } actions ResComp1 { $(2[1]) -o $(1) $(2[2-]) } rule ObjectsDefines { # Like ObjectDefines, but allows multiple files to be supplied local file ; for file in $(1) { ObjectDefines $(file) : $(2) ; } } rule SourceHdrs { # SourceHdrs : [ : ] ; # # Is a wrapper for ObjectHdrs, that passes and or, # if supplied and , and also adjusts HDRSEARCH (not # done by ObjectHdrs). local sources = [ FGristFiles $(1) ] ; local headers = $(2) ; local objects = $(3) ; local file ; if $(objects) { for file in $(objects) { ObjectHdrs $(file) : $(headers) ; # also reformat the assembler headers ASHDRS on $(file) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) [ on $(file) return $(HDRS) ] ] ; } } else { for file in $(sources:S=$(SUFOBJ)) { ObjectHdrs $(file) : $(headers) ; # also reformat the assembler headers ASHDRS on $(file) = [ FIncludes $(SEARCH_SOURCE) $(SUBDIRHDRS) [ on $(file) return $(HDRS) ] ] ; } } # Also add the header search dirs to HDRSEARCH. Note, that these dirs # will be listed after the STDHDRS (if any), but that's better than not # being listed at all. HDRSEARCH on $(sources) += $(headers) ; } 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 LibraryHeaders { # LibraryHeaders # # Returns the directory names for the library header dirs identified by # . local list = $(1) ; local dirs ; for i in $(list) { dirs += [ FDirName $(OBOS_TOP) headers libs $(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 either the object targets of or if supplied to # . Also adjusts HDRSEARCH of . # NOTE: This rule must be invoked *after* the rule that builds the objects. SourceHdrs $(1) : [ PublicHeaders $(2) ] : $(3) ; } 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 either the object targets of or if supplied to # . Also adjusts HDRSEARCH of . # NOTE: This rule must be invoked *after* the rule that builds the objects. SourceHdrs $(1) : [ PrivateHeaders $(2) ] : $(3) ; } 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 { # UseCppUnitObjectHeaders [ : ] ; SourceHdrs $(1) : [ FDirName $(OBOS_TOP) headers tools cppunit ] : $(2) ; } 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) ; UseHeaders $(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 sources = $(1) ; local headers = [ ArchHeaders $(2) ] ; local objects = $(3) ; local targets ; if $(objects) { targets = $(objects) ; } else { targets = [ FGristFiles $(sources:S=$(SUFOBJ)) ] ; } local opt = -D$(OBOS_TARGET_DEFINE) ; ObjectCcFlags $(targets) : $(opt) ; ObjectC++Flags $(targets) : $(opt) ; SourceHdrs $(sources) : $(headers) : $(objects) ; } rule UsePosixHeaders { # XXX changed to do nothing } rule UsePosixObjectHeaders { # UsePosixObjectHeaders [ : ] ; # # Adds the POSIX header dir to the header search # dirs of either the object targets of or if supplied to # . Also adjusts HDRSEARCH of . # NOTE: This rule must be invoked *after* the rule that builds the objects. SourceHdrs $(1) : [ FDirName $(OBOS_TOP) headers posix ] : $(2) ; } rule UseLibraryHeaders { # UseLibraryHeaders ; # # Adds the library 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 [ LibraryHeaders $(1) ] ; } 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. # If true, will be made a dependency # of the `all' pseudo target, i.e. it will be made by default, and removed # on `jam clean'. local target = $(1) ; local source = $(2) ; local makeDefaultDependencies = $(3) ; if ! $(makeDefaultDependencies) { makeDefaultDependencies = true ; } LINKCONTENTS on $(target) = $(source) ; SymLink1 $(target) ; if $(makeDefaultDependencies) = true { LocalDepends files : $(target) ; LocalClean clean : $(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. # If true (which is the default), will be # made a dependency of the `files' pseudo target, i.e. it will be made by # default, and removed on `jam clean'. local target = $(1) ; local source = $(2) ; local makeDefaultDependencies = $(3) ; 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) ] : $(makeDefaultDependencies) ; NOUPDATE $(target) ; Depends $(target) : $(source) ; } rule AbsSymLink { # AbsSymLink : : # : ; # Creates an absolute symbolic link from to . # and must be usual targets. If is # given, then it is set as LOCATE directory on . # If true (which is the default), will be # made a dependency of the `files' pseudo target, i.e. it will be made by # default, and removed on `jam clean'. local makeDefaultDependencies = $(4) ; if ! $(makeDefaultDependencies) { makeDefaultDependencies = true ; } Depends $(1) : $(2) ; if $(3) { MakeLocate $(1) : $(3) ; } SEARCH on $(2) += $(SEARCH_SOURCE) ; if $(makeDefaultDependencies) = true { LocalDepends files : $(1) ; LocalClean clean : $(1) ; } } actions AbsSymLink { target="$(2)" case "$target" in /*) ;; *) target=`pwd`/"$target";; esac $(RM) "$(1)" && $(LN) -s "$target" "$(1)" } rule OBOSInstall { # Usage: OBOSInstall <[ install [ and uninstall ] pseudotarget ]> # : : # : [ ] : [ ] ; local install = $(1[1]) ; install ?= install ; local uninstall = $(1[2]) ; uninstall ?= un$(install) ; local dir = $(2) ; local sources = $(3) ; local installgrist = $(4) ; installgrist ?= $(INSTALLGRIST) ; local installRule = $(5) ; installRule ?= Install ; local targets = $(sources:G=$(installgrist)) ; NotFile $(install) ; NotFile $(uninstall) ; Depends $(install) : $(targets) ; Clean $(uninstall) : $(targets) ; SEARCH on $(sources) += $(SEARCH_SOURCE) ; MakeLocate $(targets) : $(dir) ; local source ; for source in $(sources) { local target = $(source:G=$(installgrist)) ; Depends $(target) : $(source) ; $(installRule) $(target) : $(source) ; if [ on $(target) return $(MODE) ] { Chmod $(target) ; } if $(OWNER) && $(CHOWN) { Chown $(target) ; OWNER on $(target) = $(OWNER) ; } if $(GROUP) && $(CHGRP) { Chgrp $(target) ; GROUP on $(target) = $(GROUP) ; } } } rule InstallAbsSymLinkAdapter { # InstallAbsSymLinkAdapter : if ! [ on $(2) return $(TARGET) ] { TARGET on $(2) = [ on $(2) return $(SEARCH) ] ; } AbsSymLink $(1) : $(2) : : false ; } rule OBOSInstallAbsSymLink { # Usage: OBOSInstallAbsSymLink <[ install [ and uninstall ] pseudotarget ]> # : : # : [ ] ; OBOSInstall $(1) : $(2) : $(3) : $(4) : InstallAbsSymLinkAdapter ; } rule InstallRelSymLinkAdapter { # InstallRelSymLinkAdapter : if ! [ on $(2) return $(TARGET) ] { TARGET on $(2) = [ on $(2) return $(SEARCH) ] ; } RelSymLink $(1) : $(2) : false ; } rule OBOSInstallRelSymLink { # Usage: OBOSInstallRelSymLink <[ install [ and uninstall ] pseudotarget ]> # : : # : [ ] ; OBOSInstall $(1) : $(2) : $(3) : $(4) : InstallRelSymLinkAdapter ; } #------------------------------------------------------------------------------- # Low-level OBOS utility rules #------------------------------------------------------------------------------- rule FObjectsDir { # FObjectsDir # # Returns the output directory for object files the specified # subdirectory. # # : The tokens of the subdir relative to the top. # return [ FDirName $(OBOS_OBJECT_TARGET) $(1[2-]) ] ; } rule FCurrentObjectsDir { # FCurrentObjectsDir # # Returns the output directory for object files for the current # subdirectory. return [ FObjectsDir $(SUBDIR_TOKENS) ] ; } rule SetupObjectsDir { LOCATE_TARGET = [ FCurrentObjectsDir ] ; LOCATE_SOURCE = $(LOCATE_TARGET) ; SEARCH_SOURCE = [ Filter $(SEARCH_SOURCE) : $(LOCATE_TARGET) ] $(LOCATE_TARGET) ; } #------------------------------------------------------------------------------- # 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) ; Chmod $(<) ; SetType $(1) ; MimeSet $(1) ; SetVersion $(1) ; } actions Link bind NEEDLIBS { $(LINK) $(LINKFLAGS) -o "$(1)" $(UNDEFS) "$(2)" "$(NEEDLIBS)" $(LINKLIBS) ; } rule LexC++ { Depends $(1) : $(2) ; MakeLocate $(1) : $(LOCATE_SOURCE) ; LocalClean clean : $(1) ; } actions LexC++ { $(LEX) -o$(1) $(2) } rule Bison { local _h ; _h = $(1:S=.hpp) ; MakeLocate $(<) $(_h) : $(LOCATE_SOURCE) ; Depends $(<) $(_h) : $(>) ; Bison1 $(<) $(_h) : $(>) ; LocalClean clean : $(<) $(_h) ; # make sure someone includes $(_h) else it will be # a deadly independent target Includes $(<) : $(_h) ; } actions Bison1 { bison $(YACCFLAGS) -o $(1[1]) $(2) [ -f $(1[1]).h ] && mv $(1[1]).h $(1[2]) || true } rule UnarchiveObjects { # UnarchiveObjects : MakeLocate $(1) : $(LOCATE_TARGET) ; Depends $(2) : $(1) ; SEARCH on $(2) = $(SEARCH_SOURCE) ; } actions UnarchiveObjects { cd $(1[1]:D) ar -x "$(2)" $(1:BS) cd - } # 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) -D_ASSEMBLER $(KERNEL_CCFLAGS) $(ASHDRS) -o "$(1)" ; } # Overridden to allow spaces in file names. actions Chmod1 { $(CHMOD) "$(MODE)" "$(1)" } # Overridden to allow spaces in file names. actions piecemeal together existing Clean { $(RM) "$(>)" } 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) ; LOCATE on $(ref) = [ 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 : ; # # - Ideally sources, otherwise HDRSEARCH can not be # set for the sources and the sources some header # dependencies might be missing. local sources = [ FGristFiles $(1) ] ; local _objs = $(sources:S=$(SUFOBJ)) ; #Setup Kernel header directories local public_kernel_includes = add-ons/file_system add-ons/graphics app device drivers kernel storage support ; local private_kernel_includes = $(DOT) kernel libroot kernel/boot/platform/$(OBOS_BOOT_PLATFORM) ; # Use posix headers directory local headers = [ FDirName $(OBOS_TOP) headers posix ] ; # Use public OS header directories headers += [ PublicHeaders $(public_kernel_includes) ] ; # Use private directories headers += [ PrivateHeaders $(private_kernel_includes) ] ; # The platform dependent headers. headers += $(PLATFORM_HEADERS) ; SourceHdrs $(sources) : $(headers) ; UseArchObjectHeaders $(sources) : $(OBOS_ARCH) ; local object ; for object in $(_objs) { ObjectCcFlags $(object) : $(KERNEL_CCFLAGS) $(2) ; ObjectC++Flags $(object) : $(KERNEL_C++FLAGS) $(2) ; } } rule KernelObjects { SetupObjectsDir ; Objects $(1) ; SetupKernel $(1) : $(2) ; } rule KernelLd { # KernelLd : : : : : ; SetupObjectsDir ; 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 the platform specific static libs (libgcc.a). if ! $(5) { LINKLIBS on $(1) += $(PLATFORM_LINKLIBS) ; } SetupKernel $(2) ; } actions KernelLd { $(LINK) $(LINKFLAGS) -o "$(1)" "$(2)" $(LINKLIBS) ; } rule KernelAddon { # KernelAddon : : : ; local sources = $(3) ; SetupObjectsDir ; Addon $(1) : $(2) : $(sources) ; ObjectCcFlags $(sources) : -D_KERNEL_MODE=1 -fno-pic ; ObjectC++Flags $(sources) : -D_KERNEL_MODE=1 -fno-pic -fno-exceptions ; LINKFLAGS on $(1) = [ on $(1) return $(LINKFLAGS) ] -nostdlib ; LinkSharedOSLibs $(1) : $(4) kernel.so ; SetupKernel $(sources) ; } rule KernelMergeObject { # KernelMergeObject : : : ; # Compiles source files and merges the object files to an object file. # : Name of the object file to create. No grist will be added. # : Sources to be compiled. Grist will be added. # : Additional flags for compilation. # : Object files or static libraries to be merged. No grist # will be added. # SetupObjectsDir ; MakeLocateObjects $(2) ; Objects $(2) ; MergeObjectFromObjects $(1) : $(2:S=$(SUFOBJ)) : $(4) ; SetupKernel $(2) : $(3) ; } rule KernelStaticLibrary { # Usage KernelStaticLibrary : : ; # This is designed to take a set of sources and libraries and create # a file called lib.a SetupObjectsDir ; MakeLocateObjects $(2) ; Library $(1) : $(2) ; SetupKernel $(2) : $(3) ; } rule KernelStaticLibraryObjects { # Usage KernelStaticLibrary : ; # This is designed to take a set of sources and libraries and create # a file called SetupObjectsDir ; # Show that we depend on the libraries we need LocalClean clean : $(1) ; LocalDepends all : $(1) ; Depends $(1) : $(2) ; MakeLocate $(1) : $(LOCATE_TARGET) ; SetupKernel $(2) ; } actions KernelStaticLibraryObjects { ar -r "$(1)" "$(2)" ; } rule BuildPlatformMain { # Usage BuildPlatformMain : [ : ] ; # The executable. # The sources. # "false", if header search dirs shall not be reset to the # platform defaults. Defaults to "true". # SetupObjectsDir ; if $(3) != false { SetupDefaultIncludes ; } # Remove `-nostdinc' from CCFLAGS and C++FLAGS. local oldCCFLAGS = $(CCFLAGS) ; local oldC++FLAGS = $(C++FLAGS) ; CCFLAGS = [ Filter $(CCFLAGS) : -nostdinc ] ; C++FLAGS = [ Filter $(C++FLAGS) : -nostdinc ] ; Main $(1) : $(2) ; ObjectsDefines $(2) : _NO_INLINE_ASM ; # Be careful with find_thread() and the like. # Reset CCFLAGS and C++FLAGS to original values. CCFLAGS = $(oldCCFLAGS) ; C++FLAGS = $(oldC++FLAGS) ; } rule BuildPlatformTest { # Usage BuildPlatformTest : ; local target = $(1) ; local sources = $(2) ; BuildPlatformMain $(target) : $(sources) ; local relPath ; if [ FIsPrefix src tests : $(SUBDIR_TOKENS) ] { relPath = $(SUBDIR_TOKENS[3-]) ; } else { relPath = $(SUBDIR_TOKENS[2-]) ; } MakeLocate $(target) : [ FDirName $(OBOS_TEST_DIR) $(relPath) ] ; } 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 } #------------------------------------------------------------------------------- # FreeType 2 specific rules and variables #------------------------------------------------------------------------------- FT2_INCLUDE = [ FDirName $(OBOS_TOP) headers libs freetype2 ] ; FT2_SRC = [ FDirName $(OBOS_TOP) src libs freetype2 ] ; FT2_LIB = freetype ; FT2_COMPONENTS ?= gzip # support for gzip-compressed files. autohint # auto-hinter base # base component (public APIs) bdf # BDF font driver cache # cache sub-system cff # CFF/CEF font driver cid # Postscript CID-keyed font driver lzw # LZW routines pcf # PCF font driver pfr # PFR/TrueDoc font driver psaux # Common Postscript routines module pshinter # Postscript hinter module psnames # Postscript names handling raster # Monochrome rasterizer smooth # Anti-aliased rasterizer sfnt # SFNT-based format support routines truetype # TrueType font driver type1 # Postscript Type 1 font driver type42 # Postscript Type 42 (embedded TrueType) driver winfonts # Windows FON/FNT font driver ; rule UseFreeTypeHeaders { SubDirHdrs $(FT2_INCLUDE) ; } rule UseFreeTypeObjectHeaders { # UseFreeTypeObjectHeaders [ : ] ; SourceHdrs $(1) : $(FT2_INCLUDE) : $(2) ; } rule FT2_SubDir { # FT2_SubDir # : Components of a directory in the original hierarchy. local dir = $(1) ; local topDir ; switch $(dir[1]) { case "include" : topDir = $(FT2_INCLUDE) ; case src : topDir = $(FT2_SRC) ; case * : ECHO "Unknown FreeType2 directory: " $(dir) ; } return [ FDirName $(topDir) $(dir[2-]) ] ; } rule FT2_Library { # FT2_Library : # Builds objects from sources and adds the objects to the list of objects # to be linked into the library. # The name of the library. # The sources. local library = lib$(1).so ; local sources = $(2) ; SetupIncludes ; SetupObjectsDir ; MakeLocateObjects $(sources) ; Objects $(sources) ; LIBRARY_OBJECTS on $(library) += [ FGristFiles $(sources:S=$(SUFOBJ)) ] ; } rule FT2_LinkLibrary { # FT2_LinkLibrary # Links the library from the objects build with FT2_LIBRARY before. local library = lib$(1).so ; local objects = [ on $(library) return $(LIBRARY_OBJECTS) ] ; ObjectReferences $(objects) ; objects = [ FGristFiles $(objects) ] ; SharedLibraryFromObjects $(1) : $(objects) ; } #------------------------------------------------------------------------------- # Packages for OBOS alpha/beta testers #------------------------------------------------------------------------------- rule Copy { Depends $(<) : $(>) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; } actions Copy { cp -dp "$(>)" "$(<)" ; if [ -f "$(>)" ] ; then copyattr "$(>)" "$(<)" ; fi ; } rule Packages { local packagenames = $(1) ; local packagefiles = $(2) ; local path = $(3) ; for name in $(packagenames) { Package $(name) : $(packagefiles) : $(path) ; } } rule Package { local packagename = $(1) ; local packagefiles = $(2) ; local path = $(3) ; local packagezip = $(packagename:S=.zip:G=_packages) ; local packagedir = [ FDirName $(OBOS_PACKAGE_DIR) $(packagename) ] ; local installscript = install.sh ; local packageinstallscript = $(installscript:G=_packages!$(packagename)) ; local installzip = install.zip ; local packageinstallzip = $(installzip:G=_packages!$(packagename)) ; local packageobjectdir = [ FDirName $(OBOS_PACKAGE_OBJECT_DIR) $(packagename) ] ; local packagefiledir = [ FDirName $(packageobjectdir) $(path) ] ; local packagefileinstallzip = $(installzip:G=_package_objects!$(packagename)) ; # add the files to the install.zip local packagefilegrist = [ FGrist _package_files $(packagename) $(path) ] ; for file in $(packagefiles) { if $(3[0]) = "boot" { local packagefile = $(file:G=$(packagefilegrist)) ; MakeLocate $(packagefile) : $(packagefiledir) ; Copy $(packagefile) : $(file) ; Clean cleanPackages : $(packagefile) ; PackageInstallZip $(packagefileinstallzip) : $(packagefile) ; } else { local packagefile = $(file:G=_packages!$(packagename)) ; MakeLocate $(packagefile) : $(packagedir) ; Copy $(packagefile) : [ FGristFiles $(file) ] ; Clean cleanPackages : $(packagefile) ; Depends $(packagezip) : $(packagefile) ; } } # general setup for this packages -- only on first invocation if ! $(_setup_$(packagename)) { _setup_$(packagename) = true ; NotFile $(packagename) ; LocalDepends packages : $(packagename) ; MakeLocate $(packagezip) : $(OBOS_PACKAGE_DIR) ; MakeLocate $(packageinstallscript) : $(packagedir) ; MakeLocate $(packageinstallzip) : $(packagedir) ; MakeLocate $(packagefileinstallzip) : $(packageobjectdir) ; PackageInstallScript $(packageinstallscript) : $(packagedir) ; LinkInstallZip $(packageinstallzip) : $(packagefileinstallzip) ; Depends $(packagename) : $(packagezip) ; PackageZip $(packagezip) : $(packagedir) : $(packageinstallscript) $(packageinstallzip) ; } } rule PackageZip { local dir = $(2:G=dir) ; Depends $(1) : $(dir) $(3) ; Clean cleanPackages : $(1) ; PackageZip1 $(1) : $(dir) ; } actions together PackageZip1 { cd "$(OBOS_PACKAGE_DIR)" ; zip -rq "$(1:BS)" "$(2:BS)" ; } rule PackageInstallScript { MakeLocate $(1) : $(2) ; Clean cleanPackages : $(1) ; PackageInstallScript1 $(1) : $(2:G=dir) ; } actions together PackageInstallScript1 { echo '#!/bin/sh base=`dirname "$0"` cd "$base" if [ -n "$TTY" ] then unzip -d / install.zip else response=`alert "Would you like to automatically overwrite existing files, or receive a prompt?" "Overwrite" "Prompt"` if [ $response == "Overwrite" ] then unzip -od / install.zip alert "Finished installing" "Thanks" else if [ -e /boot/beos/apps/Terminal ] then terminal=/boot/beos/apps/Terminal else terminal=`query Terminal | head -1` fi $terminal -t "installer" /bin/sh "$0" fi fi' > "$(1)" ; chmod 755 "$(1)" ; } rule PackageInstallZip { Depends $(1) : $(2) ; Clean cleanPackages : $(1) ; } actions together PackageInstallZip { cd "$(1:P)" ; zip -rqy "$(1:BS)" boot ; } rule LinkInstallZip { Depends $(1) : $(2) ; Clean cleanPackages : $(1) ; } actions together LinkInstallZip { ln -sf "`pwd`/$(2)" "$(1)" ; } rule SubIncludeGPL { # SubInclude rule that can be used to conditionally include GPL licensed add-ons if $(INCLUDE_GPL_ADDONS) = 1 { SubInclude $(1) ; } } rule Man2Doc { local source = [ FGristFiles $(2) ] ; local binary = $(1) ; SEARCH on $(source) = $(SEARCH_SOURCE) ; MakeLocate $(binary) : [ FDirName $(OBOS_OBJECT_TARGET) documentation Shell_Tools ] ; Depends $(binary) : $(source) rman ; LocalDepends doc_files : $(binary) ; Man2Doc1 $(binary) : rman $(source) ; LocalClean clean : $(binary) ; } actions Man2Doc1 { $(2[1]) -f XML "$(2[2])" > "$(1)" ; } rule Man2Docs { # Man2Docs ; local source ; for source in [ FGristFiles $(1) ] { local target = $(source:S=.xml) ; Man2Doc $(target) : $(source) ; } }