haiku/build/jam/FileRules
Augustin Cavalier b16a18cba6 build: Include extra information in the package version.
Previously only the "effective revision", i.e. the hrev by itself,
was used. Now we include the "commits ahead" count and the "dirty" flag,
if they're there, using _ instead of - of course.

Change-Id: I5238d01926c2cca242bffbdef30bff606a173a06
Reviewed-on: https://review.haiku-os.org/596
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
(cherry picked from commit e7c5d994267fb7d49e3dd50c2854e9b37c9ffca1)
Reviewed-on: https://review.haiku-os.org/597
2018-09-27 03:38:07 +00:00

621 lines
16 KiB
Plaintext

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 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 .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
{
$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
$(2[1]) --data $(2[3]) $(1) || exit 1
revision=0
if [ -n "$(2[4]:E=)" ]; then
revision="`cat $(2[4]:E=)`"
fi
$(2[2]) $(1) "$revision"
}
rule DetermineHaikuRevision
{
# If existing, make the target depend on the .git/index file in the
# root directory, so it gets updated when the revision changes due to
# commits or merges.
local gitIndex = <haiku-rootdir-git>index ;
local revisionFile = <haiku-rootdir>haiku-revision ;
if ! [ on $(gitIndex) return $(HAIKU_GIT_REVISION_DETERMINED) ] {
HAIKU_GIT_REVISION_DETERMINED on $(gitIndex) = 1 ;
MakeLocate $(revisionFile) : $(HAIKU_BUILD_OUTPUT_DIR) ;
LocalClean clean : $(revisionFile) ;
if $(HAIKU_REVISION) {
DetermineHaikuRevision2 $(revisionFile) ;
} else if [ Glob [ FDirName $(HAIKU_TOP) .git ] : index ] {
SEARCH on $(gitIndex) = [ FDirName $(HAIKU_TOP) .git ] ;
Depends $(revisionFile) : $(gitIndex) ;
DetermineHaikuRevision1 $(revisionFile) : $(gitIndex) ;
} else {
revisionFile = ;
}
}
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 $(source) {
Depends $(target) : $(source) ;
}
DownloadLocatedFile1 $(target) : $(source) ;
}
actions DownloadLocatedFile1
{
source="$(2)"
if [ "$(HAIKU_NO_DOWNLOADS)" = 1 ]; then
echo "ERROR: Would need to download $(URL), but HAIKU_NO_DOWNLOADS is set!"
exit 1
fi
wget --retry-connrefused --timeout 30 -O "$(1)" $(URL) || exit 1
touch "$(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 mappings
local 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 script
MakeLocate $(script) : $(HAIKU_TMP_DIR) ;
Depends $(script) : $(mappedTargets) $(source) ;
SedCreateScript $(script) : $(mappedTargets) ;
# build the target
Depends $(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)" ; do
echo "$variable=\"$1\"" >> "$(1)"
shift
done
echo sed '$(HAIKU_SED_SCRIPT_SUBSTITUTIONS)' \
'"$(HAIKU_SED_SCRIPT_SOURCE)"' "$(HAIKU_SED_SCRIPT_SOURCE_ARGUMENTS)" \
'"$target"' >> "$(1)"
}
actions Sed1
{
set -o errexit
target="$(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
{
$(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) ;
}