98c6dfa41e
* Build libsolv and the dependency solver part of the package kit for the build platform. * Add build tool get_package_dependencies. Given a list of package files and a list of repository files it determines the additional packages that need to be retrieved from the repositories and prints their URLs. * Add rules to work with external repositories in the build system (build/jam/RepositoryRules): - PackageRepository declares an external repository with all its packages. The URL of the repository file isn't specified. It is computed from a given base URL and the SHA256 hash of the list of package files. - GeneratedRepositoryPackageList generates a file containing the file names of all packages in a repository. - IsPackageAvailable returns whether a package is available in any repository. - PackageURL returns the URL for a package. * Declare the HaikuPorts repository for x86_gcc2 (build/jam/repositories/HaikuPorts/x86_gcc2). * Add rule AddHaikuImagePackages to add a package to the image and rule IsHaikuImagePackageAdded to determine whether a package has been added. * OptionalPackages: Remove all entries that just downloaded and installed an external package. AddHaikuImagePackages can be used instead and is used in the remaining entries. Also move the remaining optional package dependency declarations from OptionalPackageDependencies here. * ExtractBuildFeatureArchives: Instead of the URL parameter a package name must be specified now. This allows to simplify BuildFeatures significantly, since there's no dealing with URLs anymore. "if" out the entries that aren't supported yet. * build_haiku_image: For the packages installed in system and common resolve their dependencies and download and install them as well.
758 lines
22 KiB
Plaintext
758 lines
22 KiB
Plaintext
|
|
rule SetupObjectsDir
|
|
{
|
|
# SetupObjectsDir
|
|
#
|
|
# Internal rule used to set up the *{LOCATE,SEARCH}*_{TARGET,SOURCE}
|
|
# variables for the current directory.
|
|
|
|
local relPath = [ FDirName $(SUBDIR_TOKENS[2-]) ] ;
|
|
if $(relPath) = . {
|
|
relPath = ;
|
|
}
|
|
COMMON_PLATFORM_LOCATE_TARGET =
|
|
[ FDirName $(HAIKU_COMMON_PLATFORM_OBJECT_DIR) $(relPath) ] ;
|
|
|
|
local var ;
|
|
for var in COMMON_ARCH COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) {
|
|
HOST_$(var)_LOCATE_TARGET
|
|
= [ FDirName $(HOST_$(var)_OBJECT_DIR) $(relPath) ] ;
|
|
TARGET_$(var)_LOCATE_TARGET
|
|
= [ FDirName $(TARGET_$(var)_OBJECT_DIR) $(relPath) ] ;
|
|
}
|
|
|
|
LOCATE_TARGET = $(COMMON_PLATFORM_LOCATE_TARGET) ;
|
|
LOCATE_SOURCE = $(LOCATE_TARGET) ;
|
|
SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE)
|
|
$(HOST_COMMON_DEBUG_LOCATE_TARGET) # Also add the standard output
|
|
$(TARGET_COMMON_DEBUG_LOCATE_TARGET) # dirs for generated sources.
|
|
;
|
|
}
|
|
|
|
rule SetupFeatureObjectsDir feature
|
|
{
|
|
# SetupFeatureObjectsDir <feature>
|
|
#
|
|
# Updates the *{LOCATE,SEARCH}*_{TARGET,SOURCE} variables for the current
|
|
# directory appending a <feature> to each of them. Note that it resets
|
|
# the LOCATE_TARGET, LOCATE_SOURCE, SEARCH_SOURCE (!) variables. I.e. it
|
|
# should be invoked before customizing these variables further (e.g. like
|
|
# adding additional source directories to SEARCH_SOURCE).
|
|
|
|
COMMON_PLATFORM_LOCATE_TARGET
|
|
= [ FDirName $(COMMON_PLATFORM_LOCATE_TARGET) $(feature) ] ;
|
|
|
|
local var ;
|
|
for var in COMMON_ARCH COMMON_DEBUG DEBUG_$(HAIKU_DEBUG_LEVELS) {
|
|
HOST_$(var)_LOCATE_TARGET
|
|
= [ FDirName $(HOST_$(var)_LOCATE_TARGET) $(feature) ] ;
|
|
TARGET_$(var)_LOCATE_TARGET
|
|
= [ FDirName $(TARGET_$(var)_LOCATE_TARGET) $(feature) ] ;
|
|
}
|
|
|
|
LOCATE_TARGET = [ FDirName $(LOCATE_TARGET) $(feature) ] ;
|
|
LOCATE_SOURCE = $(LOCATE_TARGET) ;
|
|
SEARCH_SOURCE = $(SUBDIR) $(LOCATE_SOURCE)
|
|
$(HOST_COMMON_DEBUG_LOCATE_TARGET) # Also add the standard output
|
|
$(TARGET_COMMON_DEBUG_LOCATE_TARGET) # dirs for generated sources.
|
|
;
|
|
}
|
|
|
|
rule SubIncludeGPL
|
|
{
|
|
# SubInclude rule that can be used to conditionally include GPL licensed
|
|
# add-ons
|
|
if $(HAIKU_INCLUDE_GPL_ADDONS) = 1 {
|
|
SubInclude $(1) ;
|
|
}
|
|
}
|
|
|
|
|
|
# pragma mark - MakeLocate variants
|
|
|
|
|
|
rule MakeLocateCommonPlatform
|
|
{
|
|
# The file is shared between all target platforms.
|
|
MakeLocate $(1) : $(COMMON_PLATFORM_LOCATE_TARGET) ;
|
|
}
|
|
|
|
rule MakeLocatePlatform
|
|
{
|
|
# The file is specific for the target platform, but
|
|
# architecture independent. Usually the right rule for generated
|
|
# sources, though sometimes sources can be architecture specific.
|
|
local files = $(1) ;
|
|
local file ;
|
|
for file in $(files) {
|
|
if [ on $(file) return $(PLATFORM) ] = host {
|
|
MakeLocate $(file) : $(HOST_COMMON_ARCH_LOCATE_TARGET) ;
|
|
} else {
|
|
MakeLocate $(file) : $(TARGET_COMMON_ARCH_LOCATE_TARGET) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
rule MakeLocateArch
|
|
{
|
|
# The file is platform+architecture specific, but is debug
|
|
# level independent. This is usually the right rule for generated
|
|
# architecture specific data or source files.
|
|
local files = $(1) ;
|
|
local file ;
|
|
for file in $(files) {
|
|
if [ on $(file) return $(PLATFORM) ] = host {
|
|
MakeLocate $(file) : $(HOST_COMMON_DEBUG_LOCATE_TARGET) ;
|
|
} else {
|
|
MakeLocate $(file) : $(TARGET_COMMON_DEBUG_LOCATE_TARGET) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
rule MakeLocateDebug
|
|
{
|
|
# The file is platform+architecture+debug level specific.
|
|
# That's what should be used for compiled code.
|
|
local files = $(1) ;
|
|
local file ;
|
|
for file in $(files) {
|
|
on $(file) {
|
|
if $(PLATFORM) = host {
|
|
MakeLocate $(file) : $(HOST_DEBUG_$(DEBUG)_LOCATE_TARGET) ;
|
|
} else {
|
|
MakeLocate $(file) : $(TARGET_DEBUG_$(DEBUG)_LOCATE_TARGET) ;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
# pragma mark - Deferred SubIncludes
|
|
|
|
|
|
# The variable used to collect the deferred SubIncludes.
|
|
HAIKU_DEFERRED_SUB_INCLUDES = ;
|
|
|
|
rule DeferredSubInclude params : jamfile : scope
|
|
{
|
|
# DeferredSubInclude <subdir tokens> [ : <jamfile name> [ : <scope> ] ] ;
|
|
#
|
|
# Takes the same directory tokens parameter as SubInclude plus an optional
|
|
# alternative Jamfile name. The the subdirectory referred to by
|
|
# <subdir tokens> will be included when ExecuteDeferredSubIncludes is
|
|
# invoked, i.e. at the end of the root Jamfile. The <jamfile name> parameter
|
|
# specifies the name of the Jamfile to include. By default it is "Jamfile".
|
|
# The <scope> parameter can be "global" (default) or "local", specifying
|
|
# whether the alternative Jamfile name shall also be used for subdirectories.
|
|
|
|
HAIKU_DEFERRED_SUB_INCLUDES += "/" $(params) ;
|
|
if $(jamfile) {
|
|
SetConfigVar JAMFILE : $(params) : $(jamfile) : $(scope) ;
|
|
}
|
|
}
|
|
|
|
rule ExecuteDeferredSubIncludes
|
|
{
|
|
# ExecuteDeferredSubIncludes ;
|
|
#
|
|
# Performs the deferred SubIncludes scheduled by DeferredSubInclude.
|
|
|
|
local tokensList = $(HAIKU_DEFERRED_SUB_INCLUDES) ;
|
|
while $(tokensList) {
|
|
# chop off leading "/"
|
|
tokensList = $(tokensList[2-]) ;
|
|
|
|
# get the tokens for the next include
|
|
local tokens ;
|
|
while $(tokensList) && $(tokensList[1]) != "/" {
|
|
tokens += $(tokensList[1]) ;
|
|
tokensList = $(tokensList[2-]) ;
|
|
}
|
|
|
|
# perform the include
|
|
if $(tokens) {
|
|
SubInclude $(tokens) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
rule HaikuSubInclude tokens
|
|
{
|
|
# HaikuSubInclude <tokens> ;
|
|
#
|
|
# Current subdir relative SubInclude.
|
|
# <tokens> - subdir tokens specifying the subdirectory to be include
|
|
# (relative to the current subdir)
|
|
|
|
if $(tokens) {
|
|
SubInclude HAIKU_TOP $(SUBDIR_TOKENS) $(tokens) ;
|
|
}
|
|
}
|
|
|
|
|
|
# pragma mark - Unique IDs/targets
|
|
|
|
|
|
# private to NextID; incremented with each NextID invocation
|
|
HAIKU_NEXT_ID = 0 ;
|
|
|
|
rule NextID
|
|
{
|
|
# NextID ;
|
|
|
|
local result = $(HAIKU_NEXT_ID:J=) ;
|
|
HAIKU_NEXT_ID = [ AddNumAbs $(HAIKU_NEXT_ID) : 1 ] ;
|
|
return $(result) ;
|
|
}
|
|
|
|
rule NewUniqueTarget basename
|
|
{
|
|
# NewUniqueTarget [ basename ] ;
|
|
|
|
local id = [ NextID ] ;
|
|
return $(basename[1]:E=_target:G=unique!target)_$(id) ;
|
|
}
|
|
|
|
|
|
# pragma mark - RunCommandLine
|
|
|
|
|
|
rule RunCommandLine commandLine
|
|
{
|
|
# RunCommandLine <commandLine>
|
|
#
|
|
# Creates a pseudo target that, when made by jam, causes the supplied shell
|
|
# command line to be executed. Elements of <commandLine> with the prefix ":"
|
|
# are replaced by the rule. After stripping the prefix such a string specifies
|
|
# a build system target and the finally executed command line will contain
|
|
# a path to the target instead.
|
|
# The pseudo target will depend on all targets thus identified. Each
|
|
# invocation of this rule creates a different pseudo target, which is
|
|
# returned to the caller.
|
|
|
|
# collect the targets in the command line and replace them by $targetX*
|
|
# variables
|
|
local substitutedCommandLine ;
|
|
local targets ;
|
|
|
|
local targetVarName = target ;
|
|
local i ;
|
|
for i in $(commandLine) {
|
|
# targets are marked by the ":" prefix
|
|
local target = [ Match ^:(.*) : $(i) ] ;
|
|
if $(target) {
|
|
targets += $(target) ;
|
|
targetVarName = $(targetVarName)X ;
|
|
i = "$"$(targetVarName) ;
|
|
}
|
|
|
|
substitutedCommandLine += $(i) ;
|
|
}
|
|
|
|
# define the "run" target
|
|
local run = [ NewUniqueTarget run ] ;
|
|
COMMAND_LINE on $(run) = $(substitutedCommandLine) ;
|
|
NotFile $(run) ;
|
|
Always $(run) ;
|
|
Depends $(run) : $(targets) ;
|
|
RunCommandLine1 $(run) : $(targets) ;
|
|
|
|
return $(run) ;
|
|
}
|
|
|
|
actions RunCommandLine1 {
|
|
target=target;
|
|
for t in $(2) ; do
|
|
target=${target}X
|
|
eval "${target}=${t}"
|
|
done
|
|
$(HOST_ADD_BUILD_COMPATIBILITY_LIB_DIR)
|
|
"$(COMMAND_LINE)"
|
|
}
|
|
|
|
|
|
#pragma mark - DefineBuildProfile
|
|
|
|
|
|
rule DefineBuildProfile name : type : path {
|
|
# DefineBuildProfile <name> : <type> [ : <path> ]
|
|
#
|
|
# Makes a build profile known. Build profiles can be used to define
|
|
# different sets of settings for Haiku images/installations. For each
|
|
# profile the default actions "build", "update", and "mount" (the latter
|
|
# only for disks or image types) will be available (i.e. can be specified
|
|
# as second parameter on the jam command line). They will build an image
|
|
# or installation, update only given targets, respectively just mount the
|
|
# image or disk using the bfs_shell.
|
|
#
|
|
# <name> - The name of the build profile.
|
|
# <type> - The type of the build profile. Must be one of "image" (plain
|
|
# disk image), "anyboot-image" (custom disk image that can be
|
|
# written to CD or disk device), "cd-image" (ISO CD image),
|
|
# "vmware-image" (VMware disk image), "disk" (actual partition
|
|
# or hard disk device), "install" (installation in a directory),
|
|
# or "custom" (user-defined).
|
|
# <path> - The path associated with the profile. Depending on the profile
|
|
# type, this is the path to the disk image/VMware image, hard
|
|
# disk/partition device, or the installation directory. If the
|
|
# parameter is omitted, the value of the HAIKU[_VMWARE]_IMAGE_NAME,
|
|
# HAIKU_IMAGE_DIR, respectively HAIKU_INSTALL_DIR or their default
|
|
# values will be used instead.
|
|
|
|
if [ on $(name) return $(HAIKU_BUILD_PROFILE_SPECIFIED) ] {
|
|
Exit "ERROR: Build profile \"$(name)\" defined twice!" ;
|
|
}
|
|
HAIKU_BUILD_PROFILE_SPECIFIED on $(name) = 1 ;
|
|
|
|
if ! $(HAIKU_BUILD_PROFILE) || $(HAIKU_BUILD_PROFILE) != $(name) {
|
|
return ;
|
|
}
|
|
|
|
HAIKU_BUILD_PROFILE_DEFINED = 1 ;
|
|
|
|
# split path into directory path and name
|
|
local targetDir = $(path:D) ;
|
|
local targetName = $(path:BS) ;
|
|
|
|
# Jam's path splitting produces an empty string, if a component doesn't
|
|
# exist. That's a little unhandy for checks.
|
|
if $(targetDir) = "" {
|
|
targetDir = ;
|
|
}
|
|
if $(targetName) = "" {
|
|
targetName = ;
|
|
}
|
|
|
|
targetDir ?= $(HAIKU_IMAGE_DIR) ;
|
|
targetDir ?= $(HAIKU_DEFAULT_IMAGE_DIR) ;
|
|
|
|
# "disk" is "image" with HAIKU_DONT_CLEAR_IMAGE
|
|
if $(type) = "disk" {
|
|
type = "image" ;
|
|
HAIKU_DONT_CLEAR_IMAGE = 1 ;
|
|
}
|
|
|
|
local buildTarget ;
|
|
local startOffset ;
|
|
|
|
switch $(type) {
|
|
case "anyboot-image" : {
|
|
targetName ?= $(HAIKU_ANYBOOT_NAME) ;
|
|
targetName ?= $(HAIKU_DEFAULT_ANYBOOT_NAME) ;
|
|
HAIKU_ANYBOOT_DIR = $(targetDir) ;
|
|
HAIKU_ANYBOOT_NAME = $(targetName) ;
|
|
buildTarget = haiku-anyboot-image ;
|
|
}
|
|
|
|
case "cd-image" : {
|
|
targetName ?= $(HAIKU_CD_NAME) ;
|
|
targetName ?= $(HAIKU_DEFAULT_CD_NAME) ;
|
|
HAIKU_CD_DIR = $(targetDir) ;
|
|
HAIKU_CD_NAME = $(targetName) ;
|
|
buildTarget = haiku-cd ;
|
|
}
|
|
|
|
case "image" : {
|
|
targetName ?= $(HAIKU_IMAGE_NAME) ;
|
|
targetName ?= $(HAIKU_DEFAULT_IMAGE_NAME) ;
|
|
HAIKU_IMAGE_DIR = $(targetDir) ;
|
|
HAIKU_IMAGE_NAME = $(targetName) ;
|
|
buildTarget = haiku-image ;
|
|
}
|
|
|
|
case "vmware-image" : {
|
|
targetName ?= $(HAIKU_VMWARE_IMAGE_NAME) ;
|
|
targetName ?= $(HAIKU_DEFAULT_VMWARE_IMAGE_NAME) ;
|
|
HAIKU_IMAGE_DIR = $(targetDir) ;
|
|
HAIKU_VMWARE_IMAGE_NAME = $(targetName) ;
|
|
buildTarget = haiku-vmware-image ;
|
|
startOffset = --start-offset 65536 ;
|
|
}
|
|
|
|
case "install" : {
|
|
path ?= $(HAIKU_INSTALL_DIR) ;
|
|
path ?= $(HAIKU_DEFAULT_INSTALL_DIR) ;
|
|
HAIKU_INSTALL_DIR = $(path) ;
|
|
buildTarget = install-haiku ;
|
|
}
|
|
|
|
case "custom" : {
|
|
# user-defined -- don't do anything
|
|
return 1 ;
|
|
}
|
|
|
|
case * : {
|
|
Exit "Unsupported build profile type: " $(type) ;
|
|
}
|
|
}
|
|
|
|
switch $(HAIKU_BUILD_PROFILE_ACTION) {
|
|
case "build" : {
|
|
JAM_TARGETS = $(buildTarget) ;
|
|
}
|
|
|
|
case "update" : {
|
|
JAM_TARGETS = $(buildTarget) ;
|
|
SetUpdateHaikuImageOnly 1 ;
|
|
HAIKU_PACKAGES_UPDATE_ONLY = 1 ;
|
|
HAIKU_INCLUDE_IN_IMAGE on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ;
|
|
HAIKU_INCLUDE_IN_PACKAGES on $(HAIKU_BUILD_PROFILE_PARAMETERS) = 1 ;
|
|
}
|
|
|
|
case "update-all" : {
|
|
JAM_TARGETS = $(buildTarget) ;
|
|
SetUpdateHaikuImageOnly 1 ;
|
|
HAIKU_PACKAGES_UPDATE_ONLY = 1 ;
|
|
HAIKU_INCLUDE_IN_IMAGE = 1 ;
|
|
HAIKU_INCLUDE_IN_PACKAGES = 1 ;
|
|
}
|
|
|
|
case "update-packages" : {
|
|
JAM_TARGETS = $(buildTarget) ;
|
|
SetUpdateHaikuImageOnly 1 ;
|
|
HAIKU_UPDATE_ALL_PACKAGES = 1 ;
|
|
}
|
|
|
|
case "mount" : {
|
|
if $(type) in "install" "cd-image" {
|
|
Exit "Build action \"mount\" not supported for profile type"
|
|
"\"$(type)\"." ;
|
|
}
|
|
|
|
local commandLine = :<build>bfs_shell $(startOffset)
|
|
\"$(targetName:D=$(targetDir))\" ;
|
|
JAM_TARGETS = [ RunCommandLine $(commandLine) ] ;
|
|
}
|
|
}
|
|
|
|
return 1 ;
|
|
}
|
|
|
|
|
|
# pragma mark - Build Features
|
|
|
|
|
|
rule FIsBuildFeatureEnabled feature
|
|
{
|
|
# FIsBuildFeatureEnabled <feature> ;
|
|
# Returns whether the given build feature <feature> is enabled (if so: "1",
|
|
# if not: empty list).
|
|
#
|
|
# <feature> - The name of the build feature (all lower case).
|
|
|
|
if $(feature) in $(HAIKU_BUILD_FEATURES) {
|
|
return 1 ;
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
|
|
rule FMatchesBuildFeatures specification
|
|
{
|
|
# FMatchesBuildFeatures <specification> ;
|
|
# Returns whether the given build feature specification <specification>
|
|
# holds. <specification> consists of positive and negative build feature
|
|
# conditions. Conditions can be individual list elements and multiple
|
|
# conditions can be joined, separated by ",", in a single list element. The
|
|
# effect is the same; they are considered as single set of conditions.
|
|
# A positive condition does not start with a "!". It holds when the build
|
|
# feature named by the element is enabled.
|
|
# A negative condition starts with a "!". It holds when the build feature
|
|
# named by the string resulting from removing the leading "!" is not
|
|
# enabled.
|
|
# <specification> holds when it is not empty and
|
|
# * none of the negative conditions it contains hold and
|
|
# * if it contains any positive conditions, at least one one of them holds.
|
|
#
|
|
# <specification> - The build feature specification. A list of individual
|
|
# conditions or conditions joined by ",".
|
|
|
|
local splitSpecification ;
|
|
local element ;
|
|
for element in $(specification) {
|
|
splitSpecification += [ FSplitString $(element) : "," ] ;
|
|
}
|
|
return [ FSetConditionsHold $(splitSpecification)
|
|
: $(HAIKU_BUILD_FEATURES) ] ;
|
|
}
|
|
|
|
|
|
rule FFilterByBuildFeatures list
|
|
{
|
|
# FFilterByBuildFeatures <list> ;
|
|
# Filters the list annotated by build feature specifications and returns the
|
|
# resulting list. The list can be annotated in two different ways:
|
|
# * A single list element can be annotated by appending "@<specification>"
|
|
# to it, with <specification> being a build feature specification (a
|
|
# single comma-separated string). The element appears in the resulting
|
|
# list, only if <specification> holds.
|
|
# * A sublist can be annotated by enclosing it in "<specification> @{" (two
|
|
# separate list elements) and "}@", with <specification> being a build
|
|
# feature specification (a single comma-separated string). The enclosed
|
|
# sublist appears in the resulting list, only if <specification> holds.
|
|
# The sublist annotations can be nested. The annotations themselves don't
|
|
# appear in the resulting list.
|
|
#
|
|
# <list> - A list annotated with build feature specifications.
|
|
|
|
local filteredList ;
|
|
|
|
# Since we must look ahead one element to be able to decide whether an
|
|
# element is a regular list element or a features specification for a
|
|
# subsequent "@{". Hence we always process an element other than "@{" and
|
|
# "}@" in the next iteration. We append a dummy element to the list so we
|
|
# don't need special handling for the last element.
|
|
local evaluationStack = 1 ;
|
|
local previousElement ;
|
|
local element ;
|
|
for element in $(list) dummy {
|
|
local stackTop = $(evaluationStack[1]) ;
|
|
local processElement = $(previousElement) ;
|
|
switch $(element) {
|
|
case }@ :
|
|
{
|
|
# Pop the topmost specification off the stack.
|
|
evaluationStack = $(evaluationStack[2-]) ;
|
|
if ! $(evaluationStack) {
|
|
Exit "FFilterByBuildFeatures: Unbalanced @( in: " $(list) ;
|
|
}
|
|
|
|
processElement = $(previousElement) ;
|
|
previousElement = ;
|
|
}
|
|
case @{ :
|
|
{
|
|
if ! $(previousElement) {
|
|
Exit "FFilterByBuildFeatures: No feature specification"
|
|
"after )@ in: " $(list) ;
|
|
}
|
|
|
|
if $(evaluationStack[1]) = 1
|
|
&& [ FMatchesBuildFeatures $(previousElement) ] {
|
|
evaluationStack = 1 $(evaluationStack) ;
|
|
} else {
|
|
evaluationStack = 0 $(evaluationStack) ;
|
|
}
|
|
|
|
processElement = ;
|
|
previousElement = ;
|
|
}
|
|
case * :
|
|
{
|
|
processElement = $(previousElement) ;
|
|
previousElement = $(element) ;
|
|
}
|
|
}
|
|
|
|
if $(processElement) && $(stackTop) = 1 {
|
|
local splitElement = [ Match "(.*)@([^@]*)" : $(processElement) ] ;
|
|
if $(splitElement) {
|
|
if [ FMatchesBuildFeatures $(splitElement[2]) ] {
|
|
filteredList += $(splitElement[1]) ;
|
|
}
|
|
} else {
|
|
filteredList += $(processElement) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if $(evaluationStack[2-]) {
|
|
Exit "FFilterByBuildFeatures: Unbalanced )@ in: " $(list) ;
|
|
}
|
|
|
|
return $(filteredList) ;
|
|
}
|
|
|
|
|
|
rule EnableBuildFeatures features : specification
|
|
{
|
|
# EnableBuildFeatures <features> : <specification> ;
|
|
# Enables the build features <features>, if the build features specification
|
|
# <specification> holds. If <specification> is omitted, the features are
|
|
# enabled unconditionally.
|
|
# The rule enables a build feature by adding its given lower case name to
|
|
# the build variable HAIKU_BUILD_FEATURES and defining a build variable
|
|
# HAIKU_BUILD_FEATURE_<FEATURE>_ENABLED (<FEATURE> being the upper case name
|
|
# of the build feature) to "1".
|
|
#
|
|
# <features> - A list of build feature names (lower case).
|
|
# <specification> - An optional build features specification (cf.
|
|
# FMatchesBuildFeatures).
|
|
|
|
if ! $(specification)
|
|
|| [ FMatchesBuildFeatures $(specification)
|
|
: $(HAIKU_BUILD_FEATURES) ] {
|
|
local feature ;
|
|
for feature in $(features) {
|
|
HAIKU_BUILD_FEATURES += $(feature) ;
|
|
HAIKU_BUILD_FEATURE_$(feature:U)_ENABLED = 1 ;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
rule BuildFeatureObject feature
|
|
{
|
|
# BuildFeatureObject <feature> ;
|
|
# Returns a unique object for the given build feature. It is used for
|
|
# attaching attribute values to it.
|
|
|
|
local featureObject = $(HAIKU_BUILD_FEATURE_$(feature:U)) ;
|
|
if ! $(featureObject) {
|
|
featureObject = [ NewUniqueTarget ] ;
|
|
HAIKU_BUILD_FEATURE_$(feature:U) = $(featureObject) ;
|
|
}
|
|
|
|
return $(featureObject) ;
|
|
}
|
|
|
|
|
|
rule SetBuildFeatureAttribute feature : attribute : values : package
|
|
{
|
|
# SetBuildFeatureAttribute <feature> : <attribute> : <values>
|
|
# [ : <package> ] ;
|
|
# Sets attribute <attribute> of a build feature <feature> to value <values>.
|
|
# If <package> is specified, it names the package the attribute belongs to.
|
|
|
|
local featureObject = [ BuildFeatureObject $(feature) ] ;
|
|
HAIKU_ATTRIBUTE_$(attribute) on $(featureObject) = $(values) ;
|
|
if $(package) {
|
|
HAIKU_ATTRIBUTE_$(attribute):package on $(featureObject) = $(package) ;
|
|
}
|
|
}
|
|
|
|
|
|
rule BuildFeatureAttribute feature : attribute : flags
|
|
{
|
|
# BuildFeatureAttribute <feature> : <attribute> [ : <flags> ] ;
|
|
# Returns the value of attribute <attribute> of a build feature <feature>.
|
|
# Flags can be a list of flags which influence the returned value. Currently
|
|
# only flag "path" is defined, which will convert the attribute value --
|
|
# which is assumed to be a list of (gristed) targets with a path relative to
|
|
# the extraction directory of the build feature archive files -- to paths.
|
|
# A typical example is the "headers" attribute, whose value can be used as
|
|
# dependency, but which must be converted to a path to be a valid headers
|
|
# search path.
|
|
|
|
local featureObject = [ BuildFeatureObject $(feature) ] ;
|
|
local values
|
|
= [ on $(featureObject) return $(HAIKU_ATTRIBUTE_$(attribute)) ] ;
|
|
if path in $(flags) {
|
|
# get the attribute's package and the corresponding extraction dir
|
|
local package
|
|
= [ BuildFeatureAttribute $(feature) : $(attribute):package ] ;
|
|
local directory ;
|
|
if $(package) {
|
|
directory = [ BuildFeatureAttribute $(feature)
|
|
: $(package):directory ] ;
|
|
}
|
|
|
|
# translate the values
|
|
local paths ;
|
|
local value ;
|
|
for value in $(values:G=) {
|
|
paths += [ FDirName $(directory) $(value) ] ;
|
|
}
|
|
values = $(paths) ;
|
|
}
|
|
|
|
return $(values) ;
|
|
}
|
|
|
|
|
|
rule ExtractBuildFeatureArchives feature : list
|
|
{
|
|
# ExtractBuildFeatureArchives <feature> : <list> ;
|
|
# Downloads and extracts one or more archives for build feature <feature>
|
|
# and sets attributes for the build feature to extracted entries. The syntax
|
|
# for <list> is:
|
|
# "file:" <packageName> <url>
|
|
# <attribute>: <value> ...
|
|
# ...
|
|
# "file:" <packageName2> <url2>
|
|
# ...
|
|
#
|
|
# <packageName> specifies a short name for the archive (e.g. "base" for the
|
|
# base package, "devel" for the development package, etc.), <url> the URL
|
|
# from which to download the file. <attribute> and be any name and <value>
|
|
# any relative path in the extraction directory.
|
|
#
|
|
# The attribute with the name "depends" will be handled specially. Its
|
|
# <value> specifies the name of a package the current package depends on
|
|
# (e.g. "devel" typically depends on "base"). If such a dependency is
|
|
# specified the current package will be extracted to the same directory as
|
|
# the package it depends on. The "depends" attribute must precede any other
|
|
# attribute for the package.
|
|
#
|
|
# The rule also sets the build feature attribute "<packageName>:directory"
|
|
# to the extraction directory for each package.
|
|
|
|
while $(list) {
|
|
if $(list[1]) != file: {
|
|
Exit "ExtractBuildFeatureArchives: Expected \"file: ...\", got:"
|
|
$(list) ;
|
|
}
|
|
|
|
local package = $(list[2]) ;
|
|
local url = [ PackageURL $(list[3]) ] ;
|
|
local fileName = $(url:BS) ;
|
|
list = $(list[4-]) ;
|
|
|
|
local file = [ DownloadFile $(fileName) : $(url) ] ;
|
|
|
|
local directory = [ FDirName $(HAIKU_OPTIONAL_BUILD_PACKAGES_DIR)
|
|
$(fileName:B) ] ;
|
|
directory = $(directory:G=$(package)) ;
|
|
|
|
while $(list) {
|
|
local attribute = [ Match "(.*):" : $(list[1]) ] ;
|
|
if ! $(attribute) {
|
|
Exit "ExtractBuildFeatureArchives: Expected attribute, got:"
|
|
$(list) ;
|
|
}
|
|
if $(attribute) = file {
|
|
break ;
|
|
}
|
|
|
|
list = $(list[2-]) ;
|
|
|
|
local values ;
|
|
|
|
while $(list) {
|
|
switch $(list[1]) {
|
|
case *: :
|
|
{
|
|
break ;
|
|
}
|
|
case * :
|
|
{
|
|
values += $(list[1]) ;
|
|
list = $(list[2-]) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
if $(attribute) = depends {
|
|
# Inherit the extraction directory (with a different grist) and
|
|
# depend on the extraction directory of the base package.
|
|
local basePackage = $(values[1]) ;
|
|
local baseDirectory = [ BuildFeatureAttribute $(feature)
|
|
: $(basePackage):directory ] ;
|
|
directory = $(baseDirectory:G=$(package)) ;
|
|
Depends $(directory) : $(directory:G=$(basePackage)) ;
|
|
} else {
|
|
SetBuildFeatureAttribute $(feature) : $(attribute)
|
|
: [ ExtractArchive $(directory)
|
|
: $(values) : $(file)
|
|
: extracted-$(feature)-$(package) ] ;
|
|
SetBuildFeatureAttribute $(feature) : $(attribute):package
|
|
: $(package) ;
|
|
}
|
|
}
|
|
|
|
SetBuildFeatureAttribute $(feature) : $(package):directory
|
|
: $(directory:G=) ;
|
|
}
|
|
}
|