RM_DIR ?= $(RM) -rf ;actions piecemeal together existing CleanDir{$(RM_DIR) "$(>)"}rule Copy{if $(2) {SEARCH on $(2) += $(SEARCH_SOURCE) ;Depends $(1) : <build>copyattr $(2) ;Copy1 $(1) : <build>copyattr $(2) ;}}actions Copy1{$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) \"$(2[1])" -d "$(2[2-])" "$(1)"}rule SymLink{# SymLink <target> : <source> : <makeDefaultDependencies> ;# Links <target> to <source>.# <source> is the exact link contents. No binding is done.# <makeDefaultDependencies> If true, <target> 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 <link> : <link target> : <makeDefaultDependencies> ;# Creates a relative symbolic link from <link> to <link target>.# <link> and <link target> 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.# <makeDefaultDependencies> If true (which is the default), <link> 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 <link> : <link target> : <link dir># : <makeDefaultDependencies> ;# Creates an absolute symbolic link from <link> to <link target>.# <link> and <link target> must be usual targets. If <link dir> is# given, then it is set as LOCATE directory on <link>.# <makeDefaultDependencies> If true (which is the default), <link> 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 ]># : <directory> : <sources to install> : [ <installgrist> ]# : [ <install rule> ] : [ <targets> ] ;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 <link> : <link target>if ! [ on $(2) return $(TARGET) ] {TARGET on $(2) = [ on $(2) return $(SEARCH) ] ;}AbsSymLink $(1) : $(2) : : false ;}rule HaikuInstallAbsSymLink{# Usage: HaikuInstallAbsSymLink <[ install [ and uninstall ] pseudotarget ]># : <directory> : <sources to install># : [ <installgrist> ] ;HaikuInstall $(1) : $(2) : $(3) : $(4) : InstallAbsSymLinkAdapter ;}rule InstallRelSymLinkAdapter{# InstallRelSymLinkAdapter <link> : <link target>if ! [ on $(2) return $(TARGET) ] {TARGET on $(2) = [ on $(2) return $(SEARCH) ] ;}RelSymLink $(1) : $(2) : false ;}rule HaikuInstallRelSymLink{# Usage: HaikuInstallRelSymLink <[ install [ and uninstall ] pseudotarget ]># : <directory> : <sources to install># : [ <installgrist> ] ;HaikuInstall $(1) : $(2) : $(3) : $(4) : InstallRelSymLinkAdapter ;}rule UnarchiveObjects{# UnarchiveObjects <target objects> : <static object>MakeLocateArch $(1) ;Depends $(1) : $(2) ;SEARCH on $(2) = $(SEARCH_SOURCE) ;}actions UnarchiveObjects{( cd $(1[1]:D) && $(TARGET_AR_$(TARGET_PACKAGING_ARCH)) \$(TARGET_UNARFLAGS_$(TARGET_PACKAGING_ARCH)) "$(2)" $(1:BS) )}rule ExtractArchive directory : entries : archiveFile : grist{# ExtractArchive <directory> : <entries> : <archiveFile> [ : <grist> ]## Extract the archive file target <archiveFile> to directory <directory>.# The rule can be called multiple times for different <entries> for the same# <directory> and <archiveFile> combo.## <directory> - The directory into which to extract the archive file. The# directory is created by this rule and it is the target# that the extract action is associated with.# <entries> - The entries of the archive file one is interested in. The# rule always extracts the complete archive file, from the# given entries the rule creates targets (using <grist>)# representing the extracted entries. Those targets are# returned by the rule.# <archiveFile> - The archive file target to extract.# <grist> - The grist used to create targets from <entries>. 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:G=) ;Depends $(targets) : $(directory) $(archiveFile) ;NoUpdate $(targets) ;# one-time initialization for the main target (the directory)if ! [ on $(directory) return $(INITIALIZED) ] {# make sure the parent dir existslocal 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 .hpkg :Depends $(directory) : <build>package ;ExtractHPKGArchive1 $(directory): <build>package $(archiveFile) ;case "" :Exit "ExtractArchive: No archive passed" ;case * :Exit "ExtractArchive: Unhandled archive extension:""$(archiveFile:S)" ;}INITIALIZED on $(directory) = 1 ;}return $(targets) ;}actions ExtractZipArchive1{mkdir -p $(1)unzip -q -u -o -d $(1) $(2)}actions ExtractTarArchive1{mkdir -p $(1)tar -C $(1) -xf $(2)}actions ExtractHPKGArchive1{mkdir -p "$(1)"$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR) \$(2[1]) extract -C "$(1)" "$(2[2])"}rule ObjectReference{# ObjectReference <reference object> : <source object># Makes <reference object> refer to the same file as <source object>.# The filenames must of course be identical.# <source object> 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 <source objects># Creates local references to <source objects>, i.e. identifiers with the# current grist referring to the same files. <source objects> must have# already been LOCATEd.local source ;for source in $(1) {ObjectReference [ FGristFiles $(source) ] : $(source) ;}}rule CopySetHaikuRevision target : source{# CopySetHaikuRevision <target> : <source>## Copy <source> to <target>, writing the Git revision of the working# directory into the haiku revision section of <target>.## <target> - Output file target. Gristed and located target.# <source> - ELF object to be copied. Gristed and located target.PropagateContainerUpdateTargetFlags $(target) : $(source) ;HAIKU_TARGET_IS_EXECUTABLE on $(target) = [ on $(source)return $(HAIKU_TARGET_IS_EXECUTABLE) ] ;local revisionFile = [ DetermineHaikuRevision ] ;Depends $(target): <build>copyattr <build>set_haiku_revision $(source) $(revisionFile) ;CopySetHaikuRevision1 $(target): <build>copyattr <build>set_haiku_revision $(source) $(revisionFile) ;}actions CopySetHaikuRevision1{export $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)$(2[1]) --data $(2[3]) $(1) || exit 1revision=0if [ -n "$(2[4]:E=)" ]; thenrevision="`cat $(2[4]:E=)`"fi$(2[2]) $(1) "$revision"}rule DetermineHaikuRevision{# If existing, make the target depend on the $GIT_DIR/index file,# so it gets updated when the revision changes due to commits or merges.# If GIT_DIR is not set, fall back to .git/index.local dotGit = <haiku-rootdir>.git ;local revisionFile = <haiku-rootdir>haiku-revision ;if ! [ on $(dotGit) return $(HAIKU_GIT_REVISION_DETERMINED) ] {HAIKU_GIT_REVISION_DETERMINED on $(dotGit) = 1 ;MakeLocate $(revisionFile) : $(HAIKU_BUILD_OUTPUT_DIR) ;LocalClean clean : $(revisionFile) ;if $(HAIKU_REVISION) {DetermineHaikuRevision2 $(revisionFile) ;} else if $(GIT_DIR) && $(GIT_DIR) != ".git" {local gitIndex = <$(GIT_DIR)>index ;SEARCH on $(gitIndex) = [ FDirName $(GIT_DIR) ] ;Depends $(revisionFile) : $(gitIndex) ;DetermineHaikuRevision1 $(revisionFile) : $(gitIndex) ;} else if [ Glob [ FDirName $(HAIKU_TOP) .git ] : index ] {local gitIndex = <haiku-rootdir-git>index ;SEARCH on $(gitIndex) = [ FDirName $(HAIKU_TOP) .git ] ;Depends $(revisionFile) : $(gitIndex) ;DetermineHaikuRevision1 $(revisionFile) : $(gitIndex) ;} else {Exit "ERROR: Haiku revision could not be determined." ;}}return $(revisionFile) ;}actions DetermineHaikuRevision1{$(HAIKU_TOP)/build/scripts/determine_haiku_revision $(HAIKU_TOP) $(1)}actions DetermineHaikuRevision2{echo $(HAIKU_REVISION) > $(1)}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) : <build>data_to_source $(dataFile) ;DataFileToSourceFile1 $(sourceFile) : <build>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 : source{# DownloadLocatedFile <target> : <url> [ : <source> ] ;## <source> is an optional target that <target> will be made dependent on.# Its resolved path can be used in <url> via '$source'.URL on $(target) = $(url) ;if $(HOST_WGET_RETRY_ON_HOST_ERROR) {WGET_RETRY_FLAGS on $(target) = "--retry-connrefused --retry-on-host-error" ;} else {WGET_RETRY_FLAGS on $(target) = "--retry-connrefused" ;}if $(source) {Depends $(target) : $(source) ;}DownloadLocatedFile1 $(target) : $(source) ;}if $(HAIKU_NO_DOWNLOADS) = 1 {actions DownloadLocatedFile1{source="$(2)"echo "ERROR: Would need to download $(URL), but HAIKU_NO_DOWNLOADS is set!"exit 1}} else {actions DownloadLocatedFile1{source="$(2)"wget $(WGET_RETRY_FLAGS) --timeout 30 -O "$(1)" $(URL) || exit 1touch "$(1)"}}rule DownloadFile file : url : source{# DownloadFile <file> : <url> [ : <source> ] ;## <source> is an optional target that the target will be made dependent on.# Its resolved path can be used in <url> via '$source'.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) : $(source) ;return $(file) ;}actions ChecksumFileSHA256{$(HOST_SHA256) $(2) \| $(HOST_EXTENDED_REGEX_SED) 's,([^[:space:]]*).*,\1,' > $(1)# The sed part is only necessary for sha256sum, but it doesn't harm for# sha256 either.}rule Sed target : source : substitutions : targetMap{# Sed <target> : [ <source> ] : <substitutions> [ : <targetMap> ] ;## Performs substitutions in a text file. If <source> is given, that is the# input, otherwise the substitutions are performed in place on <target>. The# caller is responsible for locating <target>, <source>, and any other used# target.## <target> - The target file.# <source> - The source file. If not given, the substitutions are performed# in place on <target>. If given, a dependency of <target> to <source># will be established.# <substitutions> - List of substitutions to be performed. Each element# specifies a substitution. It's a partial sed "s" command of the form# "<pattern>,<replacement>".# <targetMap> - A list of elements of the form "<variable>=<mappedTarget>".# <variable> specifies a name of a shell variable, <mappedTarget> a jam# target whose bound name will be assigned to the shell variable. The# variable can be used in <substitutions>. A dependency of <target> to# <mappedTarget> will be established.# We need a temporary (shell) file to which we write the target variable# mappings and the sed invocations. This is necessary, since multiple rule# invocations are allowed for a target, so that we cannot use on-target# variables.local script = [ NextID ] ;script = temp-sed-script-$(target:BS)-$(script) ;# process the target variable mappingslocal mappedTargets ;local targetMapElement ;for targetMapElement in $(targetMap) {local split = [ Match ([^=]+)=(.*) : $(targetMapElement) ] ;HAIKU_SED_SCRIPT_VARIABLE on $(script) += $(split[1]) ;local mappedTarget = $(split[2]) ;mappedTargets += $(mappedTarget) ;}HAIKU_SED_SCRIPT_SUBSTITUTIONS on $(script)= "-e \"s,$(substitutions),g\"" ;HAIKU_SED_SCRIPT_SOURCE on $(script) = $(source) ;if $(source) {HAIKU_SED_SCRIPT_SOURCE_ARGUMENTS on $(script) = ">" ;} else {HAIKU_SED_SCRIPT_SOURCE_ARGUMENTS on $(script) = -i ;}# build the scriptMakeLocate $(script) : $(HAIKU_TMP_DIR) ;Depends $(script) : $(mappedTargets) $(source) ;SedCreateScript $(script) : $(mappedTargets) ;# build the targetDepends $(target) : $(script) ;Sed1 $(target) : $(script) ;RmTemps $(target) : $(script) ;}actions SedCreateScript bind HAIKU_SED_SCRIPT_SOURCE{set -o errexit$(RM) "$(1)"touch "$(1)"set -- $(2)for variable in "$(HAIKU_SED_SCRIPT_VARIABLE)" ; doecho "$variable=\"$1\"" >> "$(1)"shiftdoneecho sed '$(HAIKU_SED_SCRIPT_SUBSTITUTIONS)' \'"$(HAIKU_SED_SCRIPT_SOURCE)"' "$(HAIKU_SED_SCRIPT_SOURCE_ARGUMENTS)" \'"$target"' >> "$(1)"}actions Sed1{set -o errexittarget="$(1)". "$(2)"}rule StripFile target : source{# Note: The caller is reponsible for matching TARGET_PACKAGING_ARCH with# the architecture the target was built for.STRIP on $(target) = $(HAIKU_STRIP_$(TARGET_PACKAGING_ARCH)) ;PropagateContainerUpdateTargetFlags $(target) : $(source) ;LocalClean clean : $(target) ;Depends $(target) : $(source) <build>xres <build>copyattr ;StripFile1 $(target) : $(source) <build>xres <build>copyattr ;}actions StripFile1{export $(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)"$(STRIP)" -o "$(1)" "$(2[1])""$(2[2])" -o "$(1)" "$(2[1])""$(2[3])" "$(2[1])" "$(1)"}rule StripFiles files{# Note: The caller is reponsible for matching TARGET_PACKAGING_ARCH with# the architecture the targets were built for.local strippedFiles ;local file ;for file in $(files) {local strippedFile = $(file:G=stripped_$(file:G)) ;# Place the stripped file in a "stripped" subdirectory of the file's# location.local location = [ on $(file) return $(LOCATE) ] ;if ! $(location) {location= $(TARGET_COMMON_DEBUG_OBJECT_DIR_$(TARGET_PACKAGING_ARCH)) ;}MakeLocateArch $(strippedFile) : [ FDirName $(location) stripped ] ;StripFile $(strippedFile) : $(file) ;strippedFiles += $(strippedFile) ;}return $(strippedFiles) ;}