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 = [ FSplitPath $(targetDir) ] ; local sourceComponents = [ FSplitPath $(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 HaikuInstall installAndUninstall : dir : sources : installgrist : installRule : targets { # Usage: HaikuInstall <[ install [ and uninstall ] pseudotarget ]> # : : : [ ] # : [ ] : [ ] ; local install = $(installAndUninstall[1]) ; install ?= install ; local uninstall = $(installAndUninstall[2]) ; uninstall ?= un$(install) ; installgrist ?= $(INSTALLGRIST) ; installRule ?= Install ; targets ?= $(sources) ; targets = $(targets: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 = $(targets[1]) ; targets = $(targets[2-]) ; 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 HaikuInstallAbsSymLink { # Usage: HaikuInstallAbsSymLink <[ install [ and uninstall ] pseudotarget ]> # : : # : [ ] ; HaikuInstall $(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 HaikuInstallRelSymLink { # Usage: HaikuInstallRelSymLink <[ install [ and uninstall ] pseudotarget ]> # : : # : [ ] ; HaikuInstall $(1) : $(2) : $(3) : $(4) : InstallRelSymLinkAdapter ; } rule UnarchiveObjects { # UnarchiveObjects : MakeLocateArch $(1) ; Depends $(1) : $(2) ; SEARCH on $(2) = $(SEARCH_SOURCE) ; } actions UnarchiveObjects { ( cd $(1[1]:D) && $(TARGET_AR) $(TARGET_UNARFLAGS) "$(2)" $(1:BS) ) } rule ExtractArchive directory : entries : archiveFile : grist { # ExtractArchive : : [ : ] # # Extract the archive file target to directory . # The rule can be called multiple times for different for the same # and combo. # # - The directory into which to extract the archive file. The # directory is created is by this rule and it is the target # that the extract action is associated with. # - The entries of the archive file one is interested in. The # rule always exctracts the complete archive file, from the # given entries the rule creates targets (using ) # representing the extracted entries. Those targets are # returned by the rule. # - The archive file target to extract. # - The grist used to create targets from . Defaults to # "extracted". grist ?= extracted ; # Turn the entries into targets to build. local targets ; local entry ; for entry in $(entries) { local target = $(entry:G=$(grist)) ; targets += $(target) ; } LOCATE on $(targets) = $(directory) ; Depends $(targets) : $(directory) ; NoUpdate $(targets) ; # one-time initialization for the main target (the directory) if ! [ on $(directory) return $(INITIALIZED) ] { # make sure the parent dir exists local parentDir = $(directory:PG=dir) ; Depends $(directory) : $(parentDir) ; MkDir $(parentDir) ; NoUpdate $(directory) ; Depends $(directory) : $(archiveFile) ; switch $(archiveFile:S) { case .zip : ExtractZipArchive1 $(directory) : $(archiveFile) ; case .tgz : ExtractTarArchive1 $(directory) : $(archiveFile) ; case * : Exit "ExtractArchive: Unhandled archive extension: $(archiveFile:S)" ; } INITIALIZED on $(directory) = 1 ; } # Use a dummy rule so that it looks to jam like the targets are actually # built from the directory target. ExtractArchiveDummy $(targets) : $(directory) ; return $(targets) ; } actions ExtractZipArchive1 { mkdir -p $(1[1]) unzip -q -u -o -d $(1[1]) $(2) } actions ExtractTarArchive1 { mkdir -p $(1[1]) tar -C $(1[1]) -xf $(2) } actions ExtractArchiveDummy { } 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 CopySetHaikuRevision target : source { # CopySetHaikuRevision : # # Copy to , writing the SVN revision of the working root # directory into the haiku revision section of . # # - Output file target. Gristed and located target. # - ELF object to be copied. Gristed and located target. # If existent, make the target depend on the .svn/entries file in the # root directory, so it gets updated when the revision changes due to # "svn up". if [ Glob [ FDirName $(HAIKU_TOP) .svn ] : entries ] { local svnEntries = entries ; SEARCH on $(svnEntries) = [ FDirName $(HAIKU_TOP) .svn ] ; Depends $(target) : $(svnEntries) ; } else if [ Glob [ FDirName $(HAIKU_TOP) .git ] : index ] { local gitIndex = index ; SEARCH on $(gitIndex) = [ FDirName $(HAIKU_TOP) .git ] ; Depends $(target) : $(gitIndex) ; } HAIKU_INCLUDE_IN_IMAGE on $(target) = [ on $(source) return $(HAIKU_INCLUDE_IN_IMAGE) ] ; Depends $(target) : copyattr set_haiku_revision $(source) ; CopySetHaikuRevision1 $(target) : copyattr set_haiku_revision $(source) ; } actions CopySetHaikuRevision1 { $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) # Try svn or git-svn # Extract from "Revision: 12345" line revision=`(LC_ALL=C LANG=C svn info $(HAIKU_TOP) || (cd $(HAIKU_TOP) && [ -d .git/svn ] && LC_ALL=C LANG=C git svn info)) 2> /dev/null | grep Revision | awk '{printf $2}'` if [ "$revision" = 0 -o "$revision" = "" ]; then # git-svn not present or not configured for this repository # Try searching git logs for last git-svn commit # Extract from " git-svn-id: .../haiku/trunk@12345 ..." line revision=`cd $(HAIKU_TOP) && git log --max-count=1 --grep="git-svn-id:" 2> /dev/null | grep "git-svn-id:" | cut -d '@' -f 2 | awk '{printf $1}'` fi if [ "$revision" = "" ]; then revision=0 fi $(2[1]) --data $(2[3]) $(1) && $(2[2]) $(1) ${revision} } rule DataFileToSourceFile sourceFile : dataFile : dataVariable : sizeVariable { sourceFile = [ FGristFiles $(sourceFile) ] ; MakeLocateCommonPlatform $(sourceFile) ; sizeVariable ?= $(dataVariable)Size ; DATA_VARIABLE on $(sourceFile) = $(dataVariable) ; SIZE_VARIABLE on $(sourceFile) = $(sizeVariable) ; Depends $(sourceFile) : data_to_source $(dataFile) ; DataFileToSourceFile1 $(sourceFile) : data_to_source $(dataFile) ; LocalClean clean : $(sourceFile) ; } actions DataFileToSourceFile1 { $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) $(2[1]) $(DATA_VARIABLE) $(SIZE_VARIABLE) $(2[2]) $(1) } rule DownloadLocatedFile target : url { URL on $(target) = $(url) ; DownloadLocatedFile1 $(target) ; } actions DownloadLocatedFile1 { wget -O $(1) $(URL) } rule DownloadFile file : url { file = $(file:G=download) ; # Request the download only once. if [ on $(file) return $(HAIKU_FILE_DOWNLOAD) ] { return $(file) ; } HAIKU_FILE_DOWNLOAD on $(file) = 1 ; MakeLocate $(file) : $(HAIKU_DOWNLOAD_DIR) ; DownloadLocatedFile $(file) : $(url) ; return $(file) ; }