|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import "class" : new ; |
|
import errors ; |
|
import modules ; |
|
import path ; |
|
import print ; |
|
import property-set ; |
|
import sequence ; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rule load ( jamfile-location ) |
|
{ |
|
if --debug-loading in [ modules.peek : ARGV ] |
|
{ |
|
ECHO "Loading Jamfile at" '$(jamfile-location)' ; |
|
} |
|
|
|
local module-name = [ module-name $(jamfile-location) ] ; |
|
|
|
if ! $(module-name) in $(.jamfile-modules) |
|
{ |
|
load-jamfile $(jamfile-location) : $(module-name) ; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
load-used-projects $(module-name) ; |
|
} |
|
return $(module-name) ; |
|
} |
|
|
|
|
|
rule load-used-projects ( module-name ) |
|
{ |
|
local used = [ modules.peek $(module-name) : .used-projects ] ; |
|
local location = [ attribute $(module-name) location ] ; |
|
import project ; |
|
while $(used) |
|
{ |
|
local id = $(used[1]) ; |
|
local where = $(used[2]) ; |
|
|
|
project.use $(id) : [ path.root [ path.make $(where) ] $(location) ] ; |
|
used = $(used[3-]) ; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
JAMROOT ?= [ modules.peek : JAMROOT ] ; |
|
JAMROOT ?= project-root.jam [Jj]amroot [Jj]amroot.jam ; |
|
|
|
|
|
|
|
|
|
rule load-parent ( location ) |
|
{ |
|
local found = [ path.glob-in-parents $(location) : $(JAMROOT) $(JAMFILE) ] ; |
|
|
|
if ! $(found) |
|
{ |
|
ECHO error: Could not find parent for project at '$(location)' ; |
|
EXIT error: Did not find Jamfile.jam or Jamroot.jam in any parent |
|
directory. ; |
|
} |
|
|
|
return [ load $(found[1]:D) ] ; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
rule act-as-jamfile ( module : location ) |
|
{ |
|
if [ module-name $(location) ] in $(.jamfile-modules) |
|
{ |
|
errors.error "Jamfile was already loaded for '$(location)'" ; |
|
} |
|
|
|
.module.$(location) = $(module) ; |
|
|
|
|
|
|
|
.jamfile-modules += [ module-name $(location) ] ; |
|
|
|
initialize $(module) : $(location) ; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
rule find ( name : current-location ) |
|
{ |
|
local project-module ; |
|
|
|
|
|
if [ path.is-rooted $(name) ] |
|
{ |
|
project-module = $($(name).jamfile-module) ; |
|
} |
|
|
|
if ! $(project-module) |
|
{ |
|
local location = [ path.root [ path.make $(name) ] $(current-location) ] |
|
; |
|
|
|
|
|
|
|
|
|
|
|
|
|
project-module = [ module-name $(location) ] ; |
|
if ! $(project-module) in $(.jamfile-modules) |
|
{ |
|
if [ path.glob $(location) : $(JAMROOT) $(JAMFILE) ] |
|
{ |
|
project-module = [ load $(location) ] ; |
|
} |
|
else |
|
{ |
|
project-module = ; |
|
} |
|
} |
|
} |
|
|
|
return $(project-module) ; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
rule module-name ( jamfile-location ) |
|
{ |
|
if ! $(.module.$(jamfile-location)) |
|
{ |
|
|
|
|
|
jamfile-location = [ path.root $(jamfile-location) [ path.pwd ] ] ; |
|
.module.$(jamfile-location) = Jamfile<$(jamfile-location)> ; |
|
} |
|
return $(.module.$(jamfile-location)) ; |
|
} |
|
|
|
|
|
|
|
|
|
JAMFILE = [ modules.peek : JAMFILE ] ; |
|
JAMFILE ?= [Bb]uild.jam [Jj]amfile.v2 [Jj]amfile [Jj]amfile.jam ; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rule find-jamfile ( |
|
dir |
|
parent-root ? |
|
: no-errors ? |
|
) |
|
{ |
|
|
|
|
|
local jamfile-glob = ; |
|
if $(parent-root) |
|
{ |
|
if ! $(.parent-jamfile.$(dir)) |
|
{ |
|
.parent-jamfile.$(dir) = [ path.glob-in-parents $(dir) : $(JAMFILE) |
|
] ; |
|
} |
|
jamfile-glob = $(.parent-jamfile.$(dir)) ; |
|
} |
|
else |
|
{ |
|
if ! $(.jamfile.$(dir)) |
|
{ |
|
.jamfile.$(dir) = [ path.glob $(dir) : $(JAMFILE) ] ; |
|
} |
|
jamfile-glob = $(.jamfile.$(dir)) ; |
|
|
|
} |
|
|
|
local jamfile-to-load = $(jamfile-glob) ; |
|
|
|
|
|
|
|
|
|
if $(jamfile-to-load[2-]) |
|
{ |
|
local v2-jamfiles = [ MATCH (.*[Jj]amfile\\.v2)|(.*[Bb]uild\\.jam) : $(jamfile-to-load) ] ; |
|
|
|
if $(v2-jamfiles) && ! $(v2-jamfiles[2]) |
|
{ |
|
jamfile-to-load = $(v2-jamfiles) ; |
|
} |
|
else |
|
{ |
|
local jamfile = [ path.basename $(jamfile-to-load[1]) ] ; |
|
ECHO "warning: Found multiple Jamfiles at '"$(dir)"'!" |
|
"Loading the first one: '$(jamfile)'." ; |
|
} |
|
|
|
jamfile-to-load = $(jamfile-to-load[1]) ; |
|
} |
|
|
|
|
|
|
|
if ! $(no-errors) && ! $(jamfile-to-load) |
|
{ |
|
errors.error Unable to load Jamfile. |
|
: Could not find a Jamfile in directory '$(dir)'. |
|
: Attempted to find it with pattern '"$(JAMFILE:J= )"'. |
|
: Please consult the documentation at 'http://www.boost.org'. ; |
|
} |
|
|
|
return $(jamfile-to-load) ; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
local rule load-jamfile ( |
|
dir |
|
: jamfile-module |
|
) |
|
{ |
|
|
|
|
|
local jamfile-to-load = [ path.glob $(dir) : $(JAMROOT) ] ; |
|
if ! $(jamfile-to-load) |
|
{ |
|
jamfile-to-load = [ find-jamfile $(dir) ] ; |
|
} |
|
|
|
if $(jamfile-to-load[2]) |
|
{ |
|
errors.error "Multiple Jamfiles found at '$(dir)'" |
|
: "Filenames are: " $(jamfile-to-load:D=) ; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
if ! $(jamfile-module) in $(.jamfile-modules) |
|
{ |
|
|
|
|
|
|
|
initialize $(jamfile-module) : [ path.parent $(jamfile-to-load) ] |
|
: $(jamfile-to-load:BS) ; |
|
|
|
if ! $(jamfile-module) in $(.jamfile-modules) |
|
{ |
|
.jamfile-modules += $(jamfile-module) ; |
|
|
|
local saved-project = $(.current-project) ; |
|
|
|
mark-as-user $(jamfile-module) ; |
|
modules.load $(jamfile-module) : [ path.native $(jamfile-to-load) ] : . ; |
|
if [ MATCH ($(JAMROOT)) : $(jamfile-to-load:BS) ] |
|
{ |
|
jamfile = [ find-jamfile $(dir) : no-errors ] ; |
|
if $(jamfile) |
|
{ |
|
load-aux $(jamfile-module) : [ path.native $(jamfile) ] ; |
|
} |
|
} |
|
|
|
|
|
if $(.current-project) != $(saved-project) |
|
{ |
|
errors.error "The value of the .current-project variable has magically" |
|
: "changed after loading a Jamfile. This means some of the targets" |
|
: "might be defined in the wrong project." |
|
: "after loading" $(jamfile-module) |
|
: "expected value" $(saved-project) |
|
: "actual value" $(.current-project) ; |
|
} |
|
|
|
if $(.global-build-dir) |
|
{ |
|
local id = [ attribute $(jamfile-module) id ] ; |
|
local project-root = [ attribute $(jamfile-module) project-root ] ; |
|
local location = [ attribute $(jamfile-module) location ] ; |
|
|
|
if $(location) && $(project-root) = $(dir) |
|
{ |
|
|
|
if ! $(id) |
|
{ |
|
ECHO "warning: the --build-dir option was specified" ; |
|
ECHO "warning: but Jamroot at '$(dir)'" ; |
|
ECHO "warning: specified no project id" ; |
|
ECHO "warning: the --build-dir option will be ignored" ; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
rule mark-as-user ( module-name ) |
|
{ |
|
if USER_MODULE in [ RULENAMES ] |
|
{ |
|
USER_MODULE $(module-name) ; |
|
} |
|
} |
|
|
|
|
|
rule load-aux ( module-name : file ) |
|
{ |
|
mark-as-user $(module-name) ; |
|
|
|
module $(module-name) |
|
{ |
|
include $(2) ; |
|
local rules = [ RULENAMES $(1) ] ; |
|
IMPORT $(1) : $(rules) : $(1) : $(1).$(rules) ; |
|
} |
|
} |
|
|
|
|
|
.global-build-dir = [ MATCH --build-dir=(.*) : [ modules.peek : ARGV ] ] ; |
|
if $(.global-build-dir) |
|
{ |
|
|
|
.global-build-dir = [ path.make $(.global-build-dir[-1]) ] ; |
|
} |
|
|
|
|
|
|
|
|
|
rule initialize ( |
|
module-name |
|
: location ? |
|
|
|
: basename ? |
|
) |
|
{ |
|
if --debug-loading in [ modules.peek : ARGV ] |
|
{ |
|
ECHO "Initializing project '$(module-name)'" ; |
|
} |
|
|
|
local jamroot ; |
|
|
|
local parent-module ; |
|
if $(module-name) = test-config |
|
{ |
|
|
|
} |
|
else if $(module-name) = site-config |
|
{ |
|
parent-module = test-config ; |
|
} |
|
else if $(module-name) = user-config |
|
{ |
|
parent-module = site-config ; |
|
} |
|
else if $(module-name) = project-config |
|
{ |
|
parent-module = user-config ; |
|
} |
|
else |
|
{ |
|
|
|
|
|
if $(location) && ! [ MATCH ($(JAMROOT)) : $(basename) ] |
|
{ |
|
parent-module = [ load-parent $(location) ] ; |
|
} |
|
else |
|
{ |
|
|
|
|
|
if $(location) |
|
{ |
|
|
|
if $(project-config.attributes) |
|
{ |
|
parent-module = project-config ; |
|
} |
|
else |
|
{ |
|
parent-module = user-config ; |
|
} |
|
jamroot = true ; |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
location ?= "" ; |
|
|
|
module $(module-name) |
|
{ |
|
} |
|
|
|
|
|
|
|
if ! $($(module-name).attributes) { |
|
|
|
$(module-name).attributes = [ new project-attributes $(location) |
|
$(module-name) ] ; |
|
local attributes = $($(module-name).attributes) ; |
|
|
|
if $(location) |
|
{ |
|
$(attributes).set source-location : [ path.make $(location) ] : exact ; |
|
} |
|
else if ! $(module-name) in test-config site-config user-config project-config |
|
{ |
|
|
|
|
|
|
|
|
|
local s = [ modules.binding $(module-name) ] ; |
|
if ! $(s) |
|
{ |
|
errors.error "Could not determine project location $(module-name)" ; |
|
} |
|
$(attributes).set source-location : $(s:D) : exact ; |
|
} |
|
|
|
$(attributes).set requirements : [ property-set.empty ] : exact ; |
|
$(attributes).set usage-requirements : [ property-set.empty ] : exact ; |
|
|
|
|
|
|
|
local rules = [ RULENAMES project-rules ] ; |
|
IMPORT project-rules : $(rules) : $(module-name) : $(rules) ; |
|
|
|
if $(parent-module) |
|
{ |
|
inherit-attributes $(module-name) : $(parent-module) ; |
|
$(attributes).set parent-module : $(parent-module) : exact ; |
|
} |
|
|
|
if $(jamroot) |
|
{ |
|
$(attributes).set project-root : $(location) : exact ; |
|
} |
|
|
|
local parent ; |
|
if $(parent-module) |
|
{ |
|
parent = [ target $(parent-module) ] ; |
|
} |
|
|
|
if ! $(.target.$(module-name)) |
|
{ |
|
.target.$(module-name) = [ new project-target $(module-name) |
|
: $(module-name) $(parent) |
|
: [ attribute $(module-name) requirements ] ] ; |
|
|
|
if --debug-loading in [ modules.peek : ARGV ] |
|
{ |
|
ECHO "Assigned project target" $(.target.$(module-name)) |
|
"to '$(module-name)'" ; |
|
} |
|
} |
|
} |
|
|
|
.current-project = [ target $(module-name) ] ; |
|
} |
|
|
|
|
|
|
|
|
|
rule inherit-attributes ( project-module : parent-module ) |
|
{ |
|
local attributes = $($(project-module).attributes) ; |
|
local pattributes = [ attributes $(parent-module) ] ; |
|
|
|
if [ modules.binding $(parent-module) ] |
|
{ |
|
$(attributes).set parent : [ path.parent |
|
[ path.make [ modules.binding $(parent-module) ] ] ] ; |
|
} |
|
local v = [ $(pattributes).get project-root ] ; |
|
$(attributes).set project-root : $(v) : exact ; |
|
$(attributes).set default-build |
|
: [ $(pattributes).get default-build ] ; |
|
$(attributes).set requirements |
|
: [ $(pattributes).get requirements ] : exact ; |
|
$(attributes).set usage-requirements |
|
: [ $(pattributes).get usage-requirements ] : exact ; |
|
|
|
local parent-build-dir = [ $(pattributes).get build-dir ] ; |
|
if $(parent-build-dir) |
|
{ |
|
|
|
|
|
|
|
|
|
local location = [ attribute $(project-module) location ] ; |
|
local parent-location = [ attribute $(parent-module) location ] ; |
|
|
|
local pwd = [ path.pwd ] ; |
|
local parent-dir = [ path.root $(parent-location) $(pwd) ] ; |
|
local our-dir = [ path.root $(location) $(pwd) ] ; |
|
$(attributes).set build-dir : [ path.join $(parent-build-dir) |
|
[ path.relative $(our-dir) $(parent-dir) ] ] : exact ; |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
rule register-id ( id : module ) |
|
{ |
|
$(id).jamfile-module = $(module) ; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class project-attributes |
|
{ |
|
import property ; |
|
import property-set ; |
|
import errors ; |
|
import path ; |
|
import print ; |
|
import sequence ; |
|
import project ; |
|
|
|
rule __init__ ( location project-module ) |
|
{ |
|
self.location = $(location) ; |
|
self.project-module = $(project-module) ; |
|
} |
|
|
|
|
|
|
|
|
|
rule set ( attribute : specification * |
|
: exact ? |
|
) |
|
{ |
|
if $(exact) |
|
{ |
|
self.$(attribute) = $(specification) ; |
|
} |
|
else if $(attribute) = "requirements" |
|
{ |
|
local result = [ property-set.refine-from-user-input |
|
$(self.requirements) : $(specification) |
|
: $(self.project-module) : $(self.location) ] ; |
|
|
|
if $(result[1]) = "@error" |
|
{ |
|
errors.error Requirements for project at '$(self.location)' |
|
conflict with parent's. : Explanation: $(result[2-]) ; |
|
} |
|
else |
|
{ |
|
self.requirements = $(result) ; |
|
} |
|
} |
|
else if $(attribute) = "usage-requirements" |
|
{ |
|
local unconditional ; |
|
for local p in $(specification) |
|
{ |
|
local split = [ property.split-conditional $(p) ] ; |
|
split ?= nothing $(p) ; |
|
unconditional += $(split[2]) ; |
|
} |
|
|
|
local non-free = [ property.remove free : $(unconditional) ] ; |
|
if $(non-free) |
|
{ |
|
errors.error usage-requirements $(specification) have non-free |
|
properties $(non-free) ; |
|
} |
|
local t = [ property.translate-paths $(specification) |
|
: $(self.location) ] ; |
|
if $(self.usage-requirements) |
|
{ |
|
self.usage-requirements = [ property-set.create |
|
[ $(self.usage-requirements).raw ] $(t) ] ; |
|
} |
|
else |
|
{ |
|
self.usage-requirements = [ property-set.create $(t) ] ; |
|
} |
|
} |
|
else if $(attribute) = "default-build" |
|
{ |
|
self.default-build = [ property.make $(specification) ] ; |
|
} |
|
else if $(attribute) = "source-location" |
|
{ |
|
self.source-location = ; |
|
for local src-path in $(specification) |
|
{ |
|
self.source-location += [ path.root [ path.make $(src-path) ] |
|
$(self.location) ] ; |
|
} |
|
} |
|
else if $(attribute) = "build-dir" |
|
{ |
|
self.build-dir = [ path.root |
|
[ path.make $(specification) ] $(self.location) ] ; |
|
} |
|
else if $(attribute) = "id" |
|
{ |
|
id = [ path.root $(specification) / ] ; |
|
project.register-id $(id) : $(self.project-module) ; |
|
self.id = $(id) ; |
|
} |
|
else if ! $(attribute) in "default-build" "location" "parent" |
|
"projects-to-build" "project-root" "source-location" |
|
{ |
|
errors.error Invalid project attribute '$(attribute)' specified for |
|
project at '$(self.location)' ; |
|
} |
|
else |
|
{ |
|
self.$(attribute) = $(specification) ; |
|
} |
|
} |
|
|
|
# Returns the value of the given attribute. |
|
# |
|
rule get ( attribute ) |
|
{ |
|
return $(self.$(attribute)) ; |
|
} |
|
|
|
# Prints the project attributes. |
|
# |
|
rule print ( ) |
|
{ |
|
local id = $(self.id) ; id ?= (none) ; |
|
local parent = $(self.parent) ; parent ?= (none) ; |
|
print.section "'"$(id)"'" ; |
|
print.list-start ; |
|
print.list-item "Parent project:" $(parent) ; |
|
print.list-item "Requirements:" [ $(self.requirements).raw ] ; |
|
print.list-item "Default build:" $(self.default-build) ; |
|
print.list-item "Source location:" $(self.source-location) ; |
|
print.list-item "Projects to build:" |
|
[ sequence.insertion-sort $(self.projects-to-build) ] ; |
|
print.list-end ; |
|
} |
|
} |
|
|
|
|
|
# Returns the project which is currently being loaded. |
|
# |
|
rule current ( ) |
|
{ |
|
return $(.current-project) ; |
|
} |
|
|
|
|
|
# Temporarily changes the current project to 'project'. Should be followed by |
|
# 'pop-current'. |
|
# |
|
rule push-current ( project ) |
|
{ |
|
.saved-current-project += $(.current-project) ; |
|
.current-project = $(project) ; |
|
} |
|
|
|
|
|
rule pop-current ( ) |
|
{ |
|
.current-project = $(.saved-current-project[-1]) ; |
|
.saved-current-project = $(.saved-current-project[1--2]) ; |
|
} |
|
|
|
|
|
# Returns the project-attribute instance for the specified Jamfile module. |
|
# |
|
rule attributes ( project ) |
|
{ |
|
return $($(project).attributes) ; |
|
} |
|
|
|
|
|
# Returns the value of the specified attribute in the specified Jamfile module. |
|
# |
|
rule attribute ( project attribute ) |
|
{ |
|
return [ $($(project).attributes).get $(attribute) ] ; |
|
} |
|
|
|
|
|
# Returns the project target corresponding to the 'project-module'. |
|
# |
|
rule target ( project-module ) |
|
{ |
|
if ! $(.target.$(project-module)) |
|
{ |
|
.target.$(project-module) = [ new project-target $(project-module) |
|
: $(project-module) |
|
: [ attribute $(project-module) requirements ] ] ; |
|
} |
|
return $(.target.$(project-module)) ; |
|
} |
|
|
|
|
|
# Use/load a project. |
|
# |
|
rule use ( id : location ) |
|
{ |
|
local saved-project = $(.current-project) ; |
|
local project-module = [ project.load $(location) ] ; |
|
local declared-id = [ project.attribute $(project-module) id ] ; |
|
|
|
if ! $(declared-id) || $(declared-id) != $(id) |
|
{ |
|
# The project at 'location' either has no id or that id is not equal to |
|
# the 'id' parameter. |
|
if $($(id).jamfile-module) && ( $($(id).jamfile-module) != |
|
$(project-module) ) |
|
{ |
|
errors.user-error Attempt to redeclare already existing project id |
|
'$(id)' |
|
location '$(location)' ; |
|
} |
|
$(id).jamfile-module = $(project-module) ; |
|
} |
|
.current-project = $(saved-project) ; |
|
} |
|
|
|
|
|
# Defines a Boost.Build extension project. Such extensions usually contain |
|
# library targets and features that can be used by many people. Even though |
|
# extensions are really projects, they can be initialized as a module would be |
|
# with the "using" (project.project-rules.using) mechanism. |
|
# |
|
rule extension ( id : options * : * ) |
|
{ |
|
# The caller is a standalone module for the extension. |
|
local mod = [ CALLER_MODULE ] ; |
|
|
|
# We need to do the rest within the extension module. |
|
module $(mod) |
|
{ |
|
import path ; |
|
|
|
# Find the root project. |
|
local root-project = [ project.current ] ; |
|
root-project = [ $(root-project).project-module ] ; |
|
while |
|
[ project.attribute $(root-project) parent-module ] && |
|
[ project.attribute $(root-project) parent-module ] != user-config |
|
{ |
|
root-project = [ project.attribute $(root-project) parent-module ] ; |
|
} |
|
|
|
# Create the project data, and bring in the project rules into the |
|
# module. |
|
project.initialize $(__name__) : [ path.join [ project.attribute |
|
$(root-project) location ] ext $(1:L) ] ; |
|
|
|
# Create the project itself, i.e. the attributes. All extensions are |
|
# created in the "/ext" project space. |
|
project /ext/$(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : |
|
$(9) ; |
|
local attributes = [ project.attributes $(__name__) ] ; |
|
|
|
# Inherit from the root project of whomever is defining us. |
|
project.inherit-attributes $(__name__) : $(root-project) ; |
|
$(attributes).set parent-module : $(root-project) : exact ; |
|
} |
|
} |
|
|
|
|
|
rule glob-internal ( project : wildcards + : excludes * : rule-name ) |
|
{ |
|
local location = [ $(project).get source-location ] ; |
|
|
|
local result ; |
|
local paths = [ path.$(rule-name) $(location) : |
|
[ sequence.transform path.make : $(wildcards) ] : |
|
[ sequence.transform path.make : $(excludes) ] ] ; |
|
if $(wildcards:D) || $(rule-name) != glob |
|
{ |
|
# The paths we have found are relative to the current directory, but the |
|
# names specified in the sources list are assumed to be relative to the |
|
# source directory of the corresponding project. So, just make the names |
|
# absolute. |
|
for local p in $(paths) |
|
{ |
|
# If the path is below source location, use relative path. |
|
# Otherwise, use full path just to avoid any ambiguities. |
|
local rel = [ path.relative $(p) $(location) : no-error ] ; |
|
if $(rel) = not-a-child |
|
{ |
|
result += [ path.root $(p) [ path.pwd ] ] ; |
|
} |
|
else |
|
{ |
|
result += $(rel) ; |
|
} |
|
} |
|
} |
|
else |
|
{ |
|
# There were no wildcards in the directory path, so the files are all in |
|
# the source directory of the project. Just drop the directory, instead |
|
# of making paths absolute. |
|
result = $(paths:D="") ; |
|
} |
|
|
|
return $(result) ; |
|
} |
|
|
|
|
|
# This module defines rules common to all projects. |
|
# |
|
module project-rules |
|
{ |
|
rule using ( toolset-module : * ) |
|
{ |
|
import toolset ; |
|
import modules ; |
|
import project ; |
|
|
|
# Temporarily change the search path so the module referred to by |
|
# 'using' can be placed in the same directory as Jamfile. User will |
|
# expect the module to be found even though the directory is not in |
|
# BOOST_BUILD_PATH. |
|
local x = [ modules.peek : BOOST_BUILD_PATH ] ; |
|
local caller = [ CALLER_MODULE ] ; |
|
local caller-location = [ modules.binding $(caller) ] ; |
|
modules.poke : BOOST_BUILD_PATH : $(caller-location:D) $(x) ; |
|
toolset.using $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; |
|
modules.poke : BOOST_BUILD_PATH : $(x) ; |
|
|
|
# The above might have clobbered .current-project. Restore the correct |
|
# value. |
|
modules.poke project : .current-project |
|
: [ project.target $(caller) ] ; |
|
} |
|
|
|
import modules ; |
|
|
|
rule import ( * : * : * ) |
|
{ |
|
modules.import project ; |
|
|
|
local caller = [ CALLER_MODULE ] ; |
|
local saved = [ modules.peek project : .current-project ] ; |
|
module $(caller) |
|
{ |
|
modules.import $(1) : $(2) : $(3) ; |
|
} |
|
modules.poke project : .current-project : $(saved) ; |
|
} |
|
|
|
rule project ( id ? : options * : * ) |
|
{ |
|
import errors ; |
|
import path ; |
|
import project ; |
|
|
|
local caller = [ CALLER_MODULE ] ; |
|
local attributes = [ project.attributes $(caller) ] ; |
|
if $(id) |
|
{ |
|
$(attributes).set id : $(id) ; |
|
} |
|
|
|
local explicit-build-dir ; |
|
|
|
for n in 2 3 4 5 6 7 8 9 |
|
{ |
|
local option = $($(n)) ; |
|
if $(option) |
|
{ |
|
$(attributes).set $(option[1]) : $(option[2-]) ; |
|
} |
|
if $(option[1]) = "build-dir" |
|
{ |
|
explicit-build-dir = [ path.make $(option[2-]) ] ; |
|
} |
|
} |
|
|
|
# If '--build-dir' is specified, change the build dir for the project. |
|
local global-build-dir = |
|
[ modules.peek project : .global-build-dir ] ; |
|
|
|
if $(global-build-dir) |
|
{ |
|
local location = [ $(attributes).get location ] ; |
|
# Project with an empty location is a 'standalone' project such as |
|
# user-config or qt. It has no build dir. If we try to set build dir |
|
# for user-config, we shall then try to inherit it, with either |
|
# weird or wrong consequences. |
|
if $(location) && $(location) = [ $(attributes).get project-root ] |
|
{ |
|
# Re-read the project id, since it might have been changed in |
|
# the project's attributes. |
|
id = [ $(attributes).get id ] ; |
|
|
|
if $(id) |
|
{ |
|
if $(explicit-build-dir) && |
|
[ path.is-rooted $(explicit-build-dir) ] |
|
{ |
|
errors.user-error Absolute directory specified via |
|
'build-dir' project attribute : Do not know how to |
|
combine that with the --build-dir option. ; |
|
} |
|
|
|
local rid = [ MATCH /(.*) : $(id) ] ; |
|
local p = [ path.join |
|
$(global-build-dir) $(rid) $(explicit-build-dir) ] ; |
|
|
|
$(attributes).set build-dir : $(p) : exact ; |
|
} |
|
} |
|
else |
|
{ |
|
|
|
if $(explicit-build-dir) |
|
{ |
|
errors.user-error When --build-dir is specified, the |
|
'build-dir' project : attribute is allowed only for |
|
top-level 'project' invocations ; |
|
} |
|
} |
|
} |
|
} |
|
|
|
|
|
|
|
|
|
|
|
rule constant ( |
|
name |
|
: value + |
|
) |
|
{ |
|
import project ; |
|
local caller = [ CALLER_MODULE ] ; |
|
local p = [ project.target $(caller) ] ; |
|
$(p).add-constant $(name) : $(value) ; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
rule path-constant ( |
|
name |
|
: value + |
|
) |
|
{ |
|
import project ; |
|
local caller = [ CALLER_MODULE ] ; |
|
local p = [ project.target $(caller) ] ; |
|
$(p).add-constant $(name) : $(value) : path ; |
|
} |
|
|
|
rule use-project ( id : where ) |
|
{ |
|
import modules ; |
|
|
|
local caller = [ CALLER_MODULE ] ; |
|
modules.poke $(caller) : .used-projects : |
|
[ modules.peek $(caller) : .used-projects ] |
|
$(id) $(where) ; |
|
} |
|
|
|
rule build-project ( dir ) |
|
{ |
|
import project ; |
|
local caller = [ CALLER_MODULE ] ; |
|
local attributes = [ project.attributes $(caller) ] ; |
|
|
|
local now = [ $(attributes).get projects-to-build ] ; |
|
$(attributes).set projects-to-build : $(now) $(dir) ; |
|
} |
|
|
|
rule explicit ( target-names * ) |
|
{ |
|
import project ; |
|
|
|
|
|
|
|
local t = [ project.current ] ; |
|
for local n in $(target-names) |
|
{ |
|
$(t).mark-target-as-explicit $(n) ; |
|
} |
|
} |
|
|
|
rule always ( target-names * ) |
|
{ |
|
import project ; |
|
local t = [ project.current ] ; |
|
for local n in $(target-names) |
|
{ |
|
$(t).mark-target-as-always $(n) ; |
|
} |
|
} |
|
|
|
rule glob ( wildcards + : excludes * ) |
|
{ |
|
import project ; |
|
return [ project.glob-internal [ project.current ] : $(wildcards) : |
|
$(excludes) : glob ] ; |
|
} |
|
|
|
rule glob-tree ( wildcards + : excludes * ) |
|
{ |
|
import project ; |
|
|
|
if $(wildcards:D) || $(excludes:D) |
|
{ |
|
errors.user-error The patterns to 'glob-tree' may not include |
|
directory ; |
|
} |
|
return [ project.glob-internal [ project.current ] : $(wildcards) : |
|
$(excludes) : glob-tree ] ; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
rule conditional ( condition + : requirements * ) |
|
{ |
|
local condition = $(condition:J=,) ; |
|
if [ MATCH (:) : $(condition) ] |
|
{ |
|
return $(condition)$(requirements) ; |
|
} |
|
else |
|
{ |
|
return $(condition):$(requirements) ; |
|
} |
|
} |
|
|
|
rule option ( name : value ) |
|
{ |
|
local m = [ CALLER_MODULE ] ; |
|
if $(m) != site-config && $(m) != user-config && $(m) != project-config |
|
{ |
|
import errors ; |
|
errors.error "The 'option' rule may be used only in site-config or user-config" ; |
|
} |
|
import option ; |
|
option.set $(name) : $(value) ; |
|
} |
|
} |
|
|