#------------------------------------------------------------------------------- # 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. if [ on $(1) return $(PLATFORM) ] = host { LINK on $(1) = $(HOST_LINK) ; LINKFLAGS on $(1) = $(HOST_LINKFLAGS) [ on $(1) return $(LINKFLAGS) ] ; } else { LINK on $(1) = $(TARGET_LINK_$(TARGET_PACKAGING_ARCH)) ; LINKFLAGS on $(1) = $(TARGET_LINKFLAGS_$(TARGET_PACKAGING_ARCH)) [ on $(1) return $(LINKFLAGS) ] ; } HAIKU_TARGET_IS_EXECUTABLE on $(1) = 1 ; NEEDLIBS on $(1) = [ on $(1) return $(NEEDLIBS) ] ; LINKLIBS on $(1) = [ on $(1) return $(LINKLIBS) ] ; MODE on $(<) = $(EXEMODE) ; on $(1) XRes $(1) : $(RESFILES) ; if ! [ on $(1) return $(DONT_USE_BEOS_RULES) ] { SetType $(1) ; MimeSet $(1) : sharedObject ; SetVersion $(1) ; # For applications for the target also generate the MIME DB entries. if [ on $(1) return $(PLATFORM) ] != host && [ on $(1) return $(RESFILES) ] { CreateAppMimeDBEntries $(1) ; } # If the generic attribute emulation is enabled, make sure the tool to # remove the attributes is built first. if $(HOST_RM_ATTRS_TARGET) { Depends $(1) : $(HOST_RM_ATTRS_TARGET) ; } } Chmod $(<) ; } # When using "real" attributes (i.e. BeOS attributes or xattr/extattr) on the # host platform, unlinking the main target by gcc will also automatically get # rid of the attributes. When using the generic attribute emulation, which # uses separate files, we need to remove the target explicitely first, so that # the attributes won't be "leaked". if $(HAIKU_HOST_USE_XATTR) = 1 { actions Link bind NEEDLIBS LINK_BEGIN_GLUE LINK_END_GLUE VERSION_SCRIPT { $(LINK) $(LINKFLAGS) -o "$(1)" $(UNDEFS) "$(LINK_BEGIN_GLUE)" "$(2)" \ "$(NEEDLIBS)" $(LINKLIBS) "$(LINK_END_GLUE)" \ -Wl,--version-script,$(VERSION_SCRIPT) } } else { actions Link bind NEEDLIBS LINK_BEGIN_GLUE LINK_END_GLUE VERSION_SCRIPT { $(RM) "$(1)" $(LINK) $(LINKFLAGS) -o "$(1)" $(UNDEFS) "$(LINK_BEGIN_GLUE)" "$(2)" \ "$(NEEDLIBS)" $(LINKLIBS) "$(LINK_END_GLUE)" \ -Wl,--version-script,$(VERSION_SCRIPT) } } rule Object { # find out which headers and defines to use local headers ; local sysHeaders ; local defines ; on $(1) { # use on $(1) variable values if ! $(PLATFORM) in $(SUPPORTED_PLATFORMS) { return ; } # Save HDRS for -I$(HDRS) on compile. # We shouldn't need -I$(SEARCH_SOURCE) as cc can find headers # in the .c file's directory, but generated .c files (from # yacc, lex, etc) are located in $(LOCATE_TARGET), possibly # different from $(SEARCH_SOURCE). headers = $(HAIKU_CONFIG_HEADERS) $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ; sysHeaders = $(SUBDIRSYSHDRS) $(SYSHDRS) ; defines = $(DEFINES) ; if $(PLATFORM) = host { sysHeaders += $(HOST_HDRS) ; defines += $(HOST_DEFINES) ; if $(USES_BE_API) { sysHeaders += $(HOST_BE_API_HEADERS) ; } } else { sysHeaders += [ FStandardHeaders $(TARGET_PACKAGING_ARCH) ] $(TARGET_HDRS_$(TARGET_PACKAGING_ARCH)) ; defines += $(TARGET_DEFINES_$(TARGET_PACKAGING_ARCH)) $(TARGET_DEFINES) ; } } # locate object and search for source LocalClean clean : $(<) ; MakeLocateDebug $(<) ; SEARCH on $(>) = $(SEARCH_SOURCE) ; HDRS on $(<) = $(headers) ; SYSHDRS on $(<) = $(sysHeaders) ; # handle #includes for source: Jam scans for headers with # the regexp pattern $(HDRSCAN) and then invokes $(HDRRULE) # with the scanned file as the target and the found headers # as the sources. HDRSEARCH is the value of SEARCH used for # the found header files. Finally, if jam must deal with # header files of the same name in different directories, # they can be distinguished with HDRGRIST. # $(SEARCH_SOURCE:E) is where cc first looks for #include # "foo.h" files. If the source file is in a distant directory, # look there. Else, look in "" (the current directory). HDRRULE on $(>) = HdrRule ; HDRSCAN on $(>) = $(HDRPATTERN) ; HDRSEARCH on $(>) = $(headers) $(sysHeaders) $(STDHDRS) ; HDRGRIST on $(>) = $(HDRGRIST) ; # propagate target specific-defines DEFINES on $(1) = $(defines) ; # if source is not .c, generate .c with specific rule switch $(>:S) { case .asm : As $(<) : $(>) ; case .nasm : AssembleNasm $(<) : $(>) ; case .c : Cc $(<) : $(>) ; case .C : C++ $(<) : $(>) ; case .cc : C++ $(<) : $(>) ; case .cpp : C++ $(<) : $(>) ; case .f : Fortran $(<) : $(>) ; case .l : if [ on $(2) return $(GENERATE_C++) ] { InheritPlatform $(<:S=.cpp) : $(1) ; C++ $(<) : $(<:S=.cpp) ; Lex $(<:S=.cpp) : $(>) ; } else { InheritPlatform $(<:S=.c) : $(1) ; Cc $(<) : $(<:S=.c) ; Lex $(<:S=.c) : $(>) ; } case *.o : return ; case .s : As $(<) : $(>) ; case .S : As $(<) : $(>) ; case .y : if [ on $(2) return $(GENERATE_C++) ] { InheritPlatform $(1:S=.cpp) $(1:S=.hpp) : $(1) ; C++ $(1) : $(1:S=.cpp) ; Yacc $(1:S=.cpp) $(1:S=.hpp) : $(2) ; } else { InheritPlatform $(1:S=.c) $(1:S=.h) : $(1) ; Cc $(1) : $(1:S=.c) ; Yacc $(1:S=.c) $(1:S=.h) : $(2) ; } case * : UserObject $(<) : $(>) ; } } rule As { local flags ; local includesSeparator ; local localIncludesOption ; local systemIncludesOption ; if [ on $(1) return $(PLATFORM) ] = host { flags = [ on $(1) return $(HOST_ASFLAGS) $(ASFLAGS) ] ; CC on $(1) = $(HOST_CC) ; includesSeparator = $(HOST_INCLUDES_SEPARATOR) ; localIncludesOption = $(HOST_LOCAL_INCLUDES_OPTION) ; systemIncludesOption = $(HOST_SYSTEM_INCLUDES_OPTION) ; } else { flags = [ on $(1) return $(TARGET_ASFLAGS_$(TARGET_PACKAGING_ARCH)) $(ASFLAGS) ] ; CC on $(1) = $(TARGET_CC_$(TARGET_PACKAGING_ARCH)) ; includesSeparator = $(TARGET_INCLUDES_SEPARATOR_$(TARGET_PACKAGING_ARCH)) ; localIncludesOption = $(TARGET_LOCAL_INCLUDES_OPTION_$(TARGET_PACKAGING_ARCH)) ; systemIncludesOption = $(TARGET_SYSTEM_INCLUDES_OPTION_$(TARGET_PACKAGING_ARCH)) ; } Depends $(<) : $(>) [ on $(1) return $(PLATFORM) ] ; ASFLAGS on $(<) += $(flags) $(SUBDIRASFLAGS) ; ASHDRS on $(<) = [ on $(<) FIncludes $(HDRS) : $(localIncludesOption) ] $(includesSeparator) [ on $(<) FSysIncludes $(SYSHDRS) : $(systemIncludesOption) ] ; ASDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ; } actions As { $(CC) -c "$(2)" -O2 $(ASFLAGS) -D_ASSEMBLER $(ASDEFS) $(ASHDRS) -o "$(1)" } rule Lex { Depends $(1) : $(2) [ on $(1) return $(PLATFORM) ] ; MakeLocateArch $(1) ; LocalClean clean : $(1) ; } actions Lex { $(LEX) $(LEXFLAGS) -o$(1) $(2) } rule Yacc { local source = $(1[1]) ; local header = $(1[2]) ; local yaccSource = $(2) ; MakeLocateArch $(source) $(header) ; Depends $(source) $(header) : $(yaccSource) [ on $(source) return $(PLATFORM) ] ; Yacc1 $(source) $(header) : $(yaccSource) ; LocalClean clean : $(source) $(header) ; # make sure someone includes $(header) else it will be # a deadly independent target Includes $(source) : $(header) ; } actions Yacc1 { bison $(YACCFLAGS) -o $(1[1]) $(2) [ -f $(1[1]).h ] && mv $(1[1]).h $(1[2]) || true } rule Cc { Depends $(<) : $(>) [ on $(1) return $(PLATFORM) ] ; on $(1) { local flags ; local includesSeparator ; local localIncludesOption ; local systemIncludesOption ; # optimization flags if $(DEBUG) = 0 { flags += $(OPTIM) ; } else { flags += -O0 ; } if $(PLATFORM) = host { # warning flags if $(WARNINGS) != 0 { flags += $(HOST_WARNING_CCFLAGS) ; if $(WARNINGS) = treatAsErrors { flags += -Werror $(HOST_WERROR_FLAGS) ; } } # debug and other flags flags += $(HOST_CCFLAGS) $(HOST_DEBUG_$(DEBUG)_CCFLAGS) $(SUBDIRCCFLAGS) $(CCFLAGS) ; if $(USES_BE_API) { flags += $(HOST_BE_API_CCFLAGS) ; } CC on $(1) = $(HOST_CC) ; includesSeparator = $(HOST_INCLUDES_SEPARATOR) ; localIncludesOption = $(HOST_LOCAL_INCLUDES_OPTION) ; systemIncludesOption = $(HOST_SYSTEM_INCLUDES_OPTION) ; } else { # warning flags if $(WARNINGS) != 0 { flags += $(TARGET_WARNING_CCFLAGS_$(TARGET_PACKAGING_ARCH)) ; if $(WARNINGS) = treatAsErrors { flags += -Werror $(TARGET_WERROR_FLAGS_$(TARGET_PACKAGING_ARCH)) ; } } # debug and other flags flags += $(TARGET_CCFLAGS_$(TARGET_PACKAGING_ARCH)) $(TARGET_DEBUG_$(DEBUG)_CCFLAGS_$(TARGET_PACKAGING_ARCH)) $(SUBDIRCCFLAGS) $(CCFLAGS) ; CC on $(1) = $(TARGET_CC_$(TARGET_PACKAGING_ARCH)) ; includesSeparator = $(TARGET_INCLUDES_SEPARATOR_$(TARGET_PACKAGING_ARCH)) ; localIncludesOption = $(TARGET_LOCAL_INCLUDES_OPTION_$(TARGET_PACKAGING_ARCH)) ; systemIncludesOption = $(TARGET_SYSTEM_INCLUDES_OPTION_$(TARGET_PACKAGING_ARCH)) ; } CCFLAGS on $(<) = $(flags) ; CCHDRS on $(<) = [ FIncludes $(HDRS) : $(localIncludesOption) ] $(includesSeparator) [ FSysIncludes $(SYSHDRS) : $(systemIncludesOption) ] ; CCDEFS on $(<) = [ FDefines $(DEFINES) ] ; } } actions Cc { $(CC) $(CCFLAGS) -c "$(2)" $(CCDEFS) $(CCHDRS) -o "$(1)" } rule C++ { Depends $(<) : $(>) [ on $(1) return $(PLATFORM) ] ; on $(1) { local flags ; local includesSeparator ; local localIncludesOption ; local systemIncludesOption ; # optimization flags if $(DEBUG) = 0 { flags += $(OPTIM) ; } else { flags += -O0 ; } if $(PLATFORM) = host { # warning flags if $(WARNINGS) != 0 { flags += $(HOST_WARNING_C++FLAGS) ; if $(WARNINGS) = treatAsErrors { flags += -Werror $(HOST_WERROR_FLAGS) ; } } # debug and other flags flags += $(HOST_C++FLAGS) $(HOST_DEBUG_$(DEBUG)_C++FLAGS) $(SUBDIRC++FLAGS) $(C++FLAGS) ; if $(USES_BE_API) { flags += $(HOST_BE_API_C++FLAGS) ; } C++ on $(1) = $(HOST_C++) ; includesSeparator = $(HOST_INCLUDES_SEPARATOR) ; localIncludesOption = $(HOST_LOCAL_INCLUDES_OPTION) ; systemIncludesOption = $(HOST_SYSTEM_INCLUDES_OPTION) ; } else { # warning flags if $(WARNINGS) != 0 { flags += $(TARGET_WARNING_C++FLAGS_$(TARGET_PACKAGING_ARCH)) ; if $(WARNINGS) = treatAsErrors { flags += -Werror $(TARGET_WERROR_FLAGS_$(TARGET_PACKAGING_ARCH)) ; } } # debug and other flags flags += $(TARGET_C++FLAGS_$(TARGET_PACKAGING_ARCH)) $(TARGET_DEBUG_$(DEBUG)_C++FLAGS_$(TARGET_PACKAGING_ARCH)) $(SUBDIRC++FLAGS) $(C++FLAGS) ; C++ on $(1) = $(TARGET_C++_$(TARGET_PACKAGING_ARCH)) ; includesSeparator = $(TARGET_INCLUDES_SEPARATOR_$(TARGET_PACKAGING_ARCH)) ; localIncludesOption = $(TARGET_LOCAL_INCLUDES_OPTION_$(TARGET_PACKAGING_ARCH)) ; systemIncludesOption = $(TARGET_SYSTEM_INCLUDES_OPTION_$(TARGET_PACKAGING_ARCH)) ; } C++FLAGS on $(<) = $(flags) ; CCHDRS on $(<) = [ FIncludes $(HDRS) : $(localIncludesOption) ] $(includesSeparator) [ FSysIncludes $(SYSHDRS) : $(systemIncludesOption) ] ; CCDEFS on $(<) = [ FDefines $(DEFINES) ] ; } } actions C++ { $(C++) -c "$(2)" $(C++FLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" } # Force recreation of the archive to avoid build errors caused by # stale dependencies after renaming or deleting object files. actions together Archive { $(RM) $(<) $(AR) $(<) $(>) } rule Library { local lib = $(1) ; local sources = [ FGristFiles $(2) ] ; local objects = $(sources:S=$(SUFOBJ)) ; InheritPlatform $(objects) : $(lib) ; LibraryFromObjects $(lib) : $(objects) ; Objects $(sources) ; } rule LibraryFromObjects { local _i _l _s ; # Add grist to file names # bonefish: No, don't. The Library rule does that anyway, and when we # have an object from another dir, we certainly don't want that. _s = $(>) ; _l = $(<:S=$(SUFLIB)) ; on $(_l) { # set the tools according to the platform if $(PLATFORM) = host { AR on $(_l) = $(HOST_AR) $(HOST_ARFLAGS) ; RANLIB on $(_l) = $(HOST_RANLIB) ; } else { AR on $(_l) = $(TARGET_AR_$(TARGET_PACKAGING_ARCH)) $(TARGET_ARFLAGS_$(TARGET_PACKAGING_ARCH)) ; RANLIB on $(_l) = $(TARGET_RANLIB_$(TARGET_PACKAGING_ARCH)) ; } # library depends on its member objects if $(KEEPOBJS) { LocalDepends obj : $(_s) ; } 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) { # locate the library only, if it hasn't been located yet local dir = $(LOCATE[1]) ; if ! $(dir) { MakeLocateDebug $(_l) ; dir = [ on $(_l) return $(LOCATE[1]) ] ; # Note: The "on ..." is necessary, since our environment # isn't changed by MakeLocateDebug. } MakeLocate $(_l)($(_s:BS)) : $(dir) ; } 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) ; Archive $(_l) : $(_s) ; if $(RANLIB) { Ranlib $(_l) ; } # If we can't scan the library, we have to leave the .o's around. if ! ( $(KEEPOBJS) || $(NOARSCAN) || $(NOARUPDATE) ) { RmTemps $(_l) : $(_s) ; } } } rule Main { local target = $(1) ; local sources = [ FGristFiles $(2) ] ; local objects = $(sources:S=$(SUFOBJ)) ; InheritPlatform $(objects) : $(target) ; MainFromObjects $(target) : $(objects) ; Objects $(sources) ; } rule MainFromObjects { local _s _t ; # Add grist to file names # Add suffix to exe _s = [ FGristFiles $(>) ] ; _t = [ FAppendSuffix $(<) : $(SUFEXE) ] ; # so 'jam foo' works when it's really foo.exe if $(_t) != $(<) { Depends $(<) : $(_t) ; NotFile $(<) ; } # make compiled sources a dependency of target LocalDepends exe : $(_t) ; Depends $(_t) : $(_s) ; MakeLocateDebug $(_t) ; LocalClean clean : $(_t) ; Link $(_t) : $(_s) ; } # Override Jam 2.5rc3 MakeLocate and MkDir to deal more intelligently # with grist set on the supplied directory name. Also do nothing for already # located files. rule MakeLocate { local dir = $(2[1]) ; if $(dir) { if ! $(dir:G) { dir = $(dir:G=dir) ; } local target ; for target in $(1) { # don't relocate once located LOCATE on $(target) += $(dir:G=) ; if [ on $(target) return $(LOCATE) ] = $(dir:G=) { Depends $(target) : $(dir) ; MkDir $(dir) ; } } } } # Overridden to use "-p", as Jam does not properly normalize # paths passed to NoUpdate, and so tries to make some directories # twice: once for the relative path, and once for the absolute path. actions MkDir1 { $(MKDIR) -p "$(<)" } rule MkDir { local dir = $(<) ; if ! $(dir:G) { dir = $(dir:G=dir) ; } # make this and all super directories while true { # If dir exists, don't update it # Do this even for $(DOT). NoUpdate $(dir) ; # Bail out when reaching the CWD (".") or a directory we've already # made. if $(dir:G=) = $(DOT) || $($(dir:G=)-mkdir) { return ; } local s ; # Cheesy gate to prevent multiple invocations on same dir # MkDir1 has the actions # Arrange for jam dirs $(dir:G=)-mkdir = true ; MkDir1 $(dir) ; LocalDepends dirs : $(dir) ; # Recursively make parent directories. # $(dir:P) = $(dir)'s parent, & we recurse until root s = $(dir:P) ; # parent keeps grist if $(s:G=) && $(s) != $(dir) { Depends $(dir) : $(s) ; dir = $(s) ; } else if $(s) { NotFile $(s) ; break ; } } } rule ObjectCcFlags { # supports inheriting the global variable value local file ; for file in [ FGristFiles $(1:S=$(SUFOBJ)) ] { CCFLAGS on $(file) = [ on $(file) return $(CCFLAGS) ] $(2) ; } } rule ObjectC++Flags { # supports inheriting the global variable value local file ; for file in [ FGristFiles $(1:S=$(SUFOBJ)) ] { C++FLAGS on $(file) = [ on $(file) return $(C++FLAGS) ] $(2) ; } } rule ObjectDefines { # supports inheriting the global variable value and multiple files if $(2) { local file ; for file in [ FGristFiles $(1:S=$(SUFOBJ)) ] { DEFINES on $(file) = [ on $(file) return $(DEFINES) ] $(2) ; CCDEFS on $(file) = [ on $(file) FDefines $(DEFINES) ] ; } } } rule ObjectHdrs { # ObjectHdrs : : # Note: Parameter 3 is an extension. local objects = [ FGristFiles $(1:S=$(SUFOBJ)) ] $(3) ; local headers = $(2) ; local file ; for file in $(objects) { on $(file) { local localHeaders = $(HDRS) $(headers) ; SYSHDRS on $(file) = $(localHeaders) ; # reformat ASHDRS and CCHDRS local fileHeaders ; if $(PLATFORM) = host { fileHeaders = [ FIncludes $(localHeaders) : $(HOST_LOCAL_INCLUDES_OPTION) ] $(HOST_INCLUDES_SEPARATOR) [ FSysIncludes $(SYSHDRS) : $(HOST_SYSTEM_INCLUDES_OPTION) ] ; } else { local architecture = $(TARGET_PACKAGING_ARCH) ; fileHeaders = [ FIncludes $(localHeaders) : $(TARGET_LOCAL_INCLUDES_OPTION_$(architecture)) ] $(TARGET_INCLUDES_SEPARATOR_$(architecture)) [ FSysIncludes $(SYSHDRS) : $(TARGET_SYSTEM_INCLUDES_OPTION_$(architecture)) ] ; } ASHDRS on $(file) = $(fileHeaders) ; CCHDRS on $(file) = $(fileHeaders) ; } } } # Overridden to avoid calling SubDir for a directory twice (in SubInclude # and from the Jamfile in the directory). rule SubInclude { # SubInclude TOP d1 ... ; # # Include a subdirectory's Jamfile. if ! $($(<[1])) { Exit SubInclude $(<[1]) without prior SubDir $(<[1]) ; } # Set up the config variables for the subdirectory. local config = [ ConfigObject $(1) ] ; __configured = ; if ! [ on $(config) return $(__configured) ] { # No custom configuration defined for the subdir. We use the variable # values inherited by the closest ancestor. config = $(HAIKU_INHERITED_SUBDIR_CONFIG) ; } # store SUBDIR_TOKENS local oldSubDirTokens = $(SUBDIR_TOKENS) ; on $(config) { include [ FDirName $($(1[1])) $(1[2-) $(JAMFILE) ] ; } # restore SUBDIR_TOKENS SUBDIR_TOKENS = $(oldSubDirTokens) ; }