/usr/share/boost-build/src/build
Edit: /usr/share/boost-build/src/build/configure.jam (17112B)
# Copyright (c) 2010 Vladimir Prus.
# Copyright 2017 Rene Rivera.
#
# Use, modification and distribution is subject to the Boost Software
# License Version 1.0. (See accompanying file LICENSE_1_0.txt or
# http://www.boost.org/LICENSE_1_0.txt)
# This module defines function to help with two main tasks:
#
# - Discovering build-time configuration for the purposes of adjusting the build
# process.
# - Reporting what is built, and how it is configured.
import "class" : new ;
import common ;
import indirect ;
import path ;
import project ;
import property ;
import property-set ;
import targets ;
import config-cache ;
import feature ;
import modules ;
import sequence ;
import utility ;
import virtual-target ;
# The configure feature allows external definition of what features are
# relevant for doing configuration builds. One can add additional relevant
# features by using:
#
# import feature ;
# import configure ;
# feature.compose
: ;
#
feature.feature configure : : composite optional ;
# This is the initial set of relevant features. Note that subfeature of all
# relevant features are also considered relevant.
#
feature.compose :
;
rule log-summary ( )
{
}
.width = 30 ;
rule set-width ( width )
{
.width = $(width) ;
}
# Declare that the components specified by the parameter exist.
#
rule register-components ( components * )
{
.components += $(components) ;
}
# Declare that the components specified by the parameters will be built.
#
rule components-building ( components * )
{
.built-components += $(components) ;
}
# Report something about component configuration that the user should better
# know.
#
rule log-component-configuration ( component : message )
{
# FIXME: Implement per-property-set logs.
.component-logs.$(component) += $(message) ;
}
rule log-check-result ( result )
{
if ! $(.announced-checks)
{
ECHO "Performing configuration checks\n" ;
.announced-checks = 1 ;
}
ECHO $(result) ;
# FIXME: Unfinished code. Nothing seems to set .check-results at the moment.
#.check-results += $(result) ;
}
rule log-library-search-result ( library : result )
{
local x = [ PAD " - $(library)" : $(.width) ] ;
log-check-result "$(x) : $(result)" ;
}
rule print-component-configuration ( )
{
# FIXME: See what was intended with this initial assignment.
# local c = [ sequence.unique $(.components) ] ;
ECHO "\nComponent configuration:\n" ;
local c ;
for c in $(.components)
{
local s ;
if $(c) in $(.built-components)
{
s = "building" ;
}
else
{
s = "not building" ;
}
ECHO [ PAD " - $(c)" : $(.width) ] ": $(s)" ;
for local m in $(.component-logs.$(c))
{
ECHO " -" $(m) ;
}
}
ECHO ;
}
rule print-configure-checks-summary ( )
{
# FIXME: The problem with this approach is that the user sees the checks
# summary when all checks are done, and has no progress reporting while the
# checks are being executed.
if $(.check-results)
{
ECHO "Configuration checks summary\n" ;
for local r in $(.check-results)
{
ECHO $(r) ;
}
ECHO ;
}
}
if --reconfigure in [ modules.peek : ARGV ]
{
.reconfigure = true ;
}
# Handle the --reconfigure option
rule maybe-force-rebuild ( targets * )
{
if $(.reconfigure)
{
local all-targets ;
for local t in $(targets)
{
all-targets += [ virtual-target.traverse $(t) ] ;
}
for local t in [ sequence.unique $(all-targets) ]
{
$(t).always ;
}
}
}
# Attempts to build a set of virtual targets
rule try-build ( targets * : ps : what : retry ? )
{
local cache-name = $(what) [ $(ps).raw ] ;
cache-name = $(cache-name:J=-) ;
local value = [ config-cache.get $(cache-name) ] ;
local result ;
local jam-targets ;
maybe-force-rebuild $(targets) ;
for local t in $(targets)
{
jam-targets += [ $(t).actualize ] ;
}
if $(value)
{
local x = [ PAD " - $(what)" : $(.width) ] ;
if $(value) = true
{
.$(what)-supported.$(ps) = yes ;
result = true ;
log-check-result "$(x) : yes (cached)" ;
}
else
{
log-check-result "$(x) : no (cached)" ;
}
}
else if ! UPDATE_NOW in [ RULENAMES ]
{
# Cannot determine. Assume existence.
}
else
{
local x = [ PAD " - $(what)" : $(.width) ] ;
if [ UPDATE_NOW $(jam-targets) :
$(.log-fd) : ignore-minus-n : ignore-minus-q ]
{
.$(what)-supported.$(ps) = yes ;
result = true ;
log-check-result "$(x) : yes" ;
}
else
{
log-check-result "$(x) : no" ;
}
}
if ! $(value)
{
if $(result)
{
config-cache.set $(cache-name) : true ;
}
else
{
config-cache.set $(cache-name) : false ;
}
}
return $(result) ;
}
# Attempts to build several sets of virtual targets. Returns the
# the index of the first set that builds.
rule try-find-build ( ps : what : * )
{
local args = 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ;
# The outer layer only needs to check $(what), but we
# also need to check the individual elements, in case
# the set of targets has changed since the last build.
local cache-name = $(what) $($(args)[1]) [ $(ps).raw ] ;
cache-name = $(cache-name:J=-) ;
local value = [ config-cache.get $(cache-name) ] ;
local result ;
local jam-targets ;
maybe-force-rebuild $($(args)[2-]) ;
# Make sure that the targets are always actualized,
# even if the result is cached. This is needed to
# allow clean-all to find them and also to avoid
# unintentional behavior changes.
for local t in $($(args)[2-])
{
$(t).actualize ;
}
if $(value)
{
local none = none ; # What to show when the argument
local name = $(value) ;
if $(name) != none
{
name = [ CALC $(name) + 2 ] ;
}
local x = [ PAD " - $(what)" : $(.width) ] ;
local y = [ PAD $($(name)[1]) : 3 ] ;
result = $(value) ;
log-check-result "$(x) : $(y) (cached)" ;
}
else
{
local x = [ PAD " - $(what)" : $(.width) ] ;
for local i in $(args)
{
if ! $($(i)[1])
{
break ;
}
local jam-targets ;
for local t in $($(i)[2-])
{
jam-targets += [ $(t).actualize ] ;
}
if [ UPDATE_NOW $(jam-targets) :
$(.log-fd) : ignore-minus-n : ignore-minus-q ]
{
result = [ CALC $(i) - 2 ] ;
log-check-result "$(x) : $($(i)[1])" ;
break ;
}
}
if ! $(result)
{
log-check-result "$(x) : none" ;
result = none ;
}
}
if ! $(value)
{
if $(result)
{
config-cache.set $(cache-name) : $(result) ;
}
else
{
config-cache.set $(cache-name) : $(result) ;
}
}
if $(result) != none
{
return $(result) ;
}
}
# Attempt to build a metatarget named by 'metatarget-reference'
# in context of 'project' with properties 'ps'.
# Returns non-empty value if build is OK.
rule builds-raw ( metatarget-reference : project : ps : what : retry ? )
{
local result ;
if ! $(retry) && ! $(.$(what)-tested.$(ps))
{
.$(what)-tested.$(ps) = true ;
local targets = [ targets.generate-from-reference
$(metatarget-reference) : $(project) : $(ps) ] ;
result = [ try-build $(targets[2-]) : $(ps) : $(what) : $(retry) ] ;
.$(what)-supported.$(ps) = $(result) ;
return $(result) ;
}
else
{
return $(.$(what)-supported.$(ps)) ;
}
}
# Attempt to build a metatarget named by 'metatarget-reference'
# in context of 'project' with properties 'ps'.
# Returns the 1-based index of the first target
# that builds.
rule find-builds-raw ( project : ps : what : * )
{
local result ;
local args = 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ;
if ! $(.$(what)-tested.$(ps))
{
.$(what)-tested.$(ps) = true ;
local targets.$(i) what.$(i) ;
for local i in $(args)
{
if ! $($(i))
{
break ;
}
targets.$(i) = [ targets.generate-from-reference
$($(i)[1]) : $(project) : $(ps) ] ;
# ignore usage requirements
targets.$(i) = $(targets.$(i)[2-]) ;
if $($(i)[2])
{
what.$(i) = $($(i)[2]) ;
}
else
{
local t = [ targets.resolve-reference
$($(i)[1]) : $(project) ] ;
what.$(i) = [ $(t[1]).name ] ;
}
}
result = [ try-find-build $(ps) : $(what)
: $(what.4) $(targets.4)
: $(what.5) $(targets.5)
: $(what.6) $(targets.6)
: $(what.7) $(targets.7)
: $(what.8) $(targets.8)
: $(what.9) $(targets.9)
: $(what.10) $(targets.10)
: $(what.11) $(targets.11)
: $(what.12) $(targets.12)
: $(what.13) $(targets.13)
: $(what.14) $(targets.14)
: $(what.15) $(targets.15)
: $(what.16) $(targets.16)
: $(what.17) $(targets.17)
: $(what.18) $(targets.18)
: $(what.19) $(targets.19) ] ;
.$(what)-result.$(ps) = $(result) ;
return $(result) ;
}
else
{
return $(.$(what)-result.$(ps)) ;
}
}
rule get-relevant-features ( )
{
local relevant = [ feature.expand ] ;
local result = ;
for local f in $(relevant)
{
if $(f) !=
{
local sub = [ modules.peek feature : $(f).subfeatures ] ;
local name = [ utility.ungrist $(f) ] ;
result += $(f) <$(name)-$(sub)> ;
}
}
return $(result) ;
}
rule builds ( metatarget-reference : properties * : what ? : retry ? )
{
local toolset-subfeatures = [ modules.peek feature : .subfeatures ] ;
toolset-subfeatures = ;
# FIXME: This should not be hardcoded. Other checks might want to consider a
# different set of features as relevant.
local relevant = [ property.select [ get-relevant-features ] : $(properties) ] ;
local ps = [ property-set.create $(relevant) ] ;
local t = [ targets.current ] ;
local p = [ $(t).project ] ;
if ! $(what)
{
local resolved = [ targets.resolve-reference $(metatarget-reference) : $(p) ] ;
local name = [ $(resolved[1]).name ] ;
what = "$(name) builds" ;
}
return [ builds-raw $(metatarget-reference) : $(p) : $(ps) : $(what) :
$(retry) ] ;
}
rule find-builds ( what : properties * : * )
{
local relevant = [ property.select [ get-relevant-features ] : $(properties) ] ;
local ps = [ property-set.create $(relevant) ] ;
local t = [ targets.current ] ;
local p = [ $(t).project ] ;
return [ find-builds-raw $(p) : $(ps) : $(what) :
$(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) :
$(10) : $(11) : $(12) : $(13) : $(14) : $(15) :
$(16) : $(17) : $(18) : $(19) ] ;
}
# Called by B2 startup code to specify the file to receive the
# configuration check results. Should never be called by user code.
#
rule set-log-file ( log-file )
{
path.makedirs [ path.parent $(log-file) ] ;
.log-fd = [ FILE_OPEN [ path.native $(log-file) ] : "w" ] ;
if ! $(.log-fd)
{
ECHO "warning:" failed to open log file $(log-file) for writing ;
}
}
# Frontend rules
class check-target-builds-worker
{
import configure ;
import property-set ;
import targets ;
import project ;
import property ;
rule __init__ ( target message ? : true-properties * : false-properties * )
{
local project = [ project.current ] ;
self.target = $(target) ;
self.message = $(message) ;
self.true-properties =
[ configure.translate-properties $(true-properties) : $(project) ] ;
self.false-properties =
[ configure.translate-properties $(false-properties) : $(project) ] ;
}
rule check ( properties * )
{
local choosen ;
if [ configure.builds $(self.target) : $(properties) : $(self.message) ]
{
choosen = $(self.true-properties) ;
}
else
{
choosen = $(self.false-properties) ;
}
return [ property.evaluate-conditionals-in-context $(choosen) :
$(properties) ] ;
}
}
class configure-choose-worker
{
import configure ;
import property ;
import project ;
rule __init__ ( message : * )
{
local project = [ project.current ] ;
self.message = $(message) ;
for i in 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
{
local name = [ CALC $(i) - 1 ] ;
self.targets.$(name) = $($(i)[1]) ;
if ! $($(i)[2]:G) # Check whether the second argument is a property
{
self.what.$(name) = $($(i)[2]) ;
self.props.$(name) = $($(i)[3-]) ;
}
else
{
self.props.$(name) = $($(i)[2-]) ;
}
self.props.$(name) = [ configure.translate-properties
$(self.props.$(name)) : $(project) ] ;
}
}
rule all-properties ( )
{
local i = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ;
return $(self.props.$(i)) ;
}
rule check ( properties * )
{
local i = [ configure.find-builds $(self.message) : $(properties)
: $(self.targets.1) $(self.what.1)
: $(self.targets.2) $(self.what.2)
: $(self.targets.3) $(self.what.3)
: $(self.targets.4) $(self.what.4)
: $(self.targets.5) $(self.what.5)
: $(self.targets.6) $(self.what.6)
: $(self.targets.7) $(self.what.7)
: $(self.targets.8) $(self.what.8)
: $(self.targets.9) $(self.what.9)
: $(self.targets.10) $(self.what.10)
: $(self.targets.11) $(self.what.11)
: $(self.targets.12) $(self.what.12)
: $(self.targets.13) $(self.what.13)
: $(self.targets.14) $(self.what.14)
: $(self.targets.15) $(self.what.15)
: $(self.targets.16) $(self.what.16)
: $(self.targets.17) $(self.what.17)
: $(self.targets.18) $(self.what.18)
: $(self.targets.19) $(self.what.19) ] ;
if $(self.props.$(i))
{
return [ property.evaluate-conditionals-in-context $(self.props.$(i)) : $(properties) ] ;
}
}
}
rule translate-properties ( properties * : project ? )
{
if $(project) && [ $(project).location ]
{
local location = [ $(project).location ] ;
local m = [ $(project).project-module ] ;
local project-id = [ project.attribute $(m) id ] ;
project-id ?= [ path.root $(location) [ path.pwd ] ] ;
return [ property.translate $(properties)
: $(project-id) : $(location) : $(m) ] ;
}
else
{
return $(properties) ;
}
}
rule check-target-builds ( target message ? : true-properties * :
false-properties * )
{
local instance = [ new check-target-builds-worker $(target) $(message) :
$(true-properties) : $(false-properties) ] ;
local rulename = [ indirect.make check : $(instance) ] ;
return @$(rulename)
[ property.evaluate-conditional-relevance
$(true-properties) $(false-properties)
: [ configure.get-relevant-features ] ] ;
}
# Usage:
# [ configure.choose "architecture"
# : /config//x86 x86 x86
# : /config//mips mips mips
# ]
rule choose ( message : * )
{
local instance = [ new configure-choose-worker $(message)
: $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9)
: $(10) : $(11) : $(12) : $(13) : $(14) : $(15) : $(16)
: $(17) : $(18) : $(19) ] ;
local rulename = [ indirect.make check : $(instance) ] ;
return @$(rulename)
[ property.evaluate-conditional-relevance
[ $(instance).all-properties ]
: [ configure.get-relevant-features ] ] ;
}
IMPORT $(__name__) : check-target-builds : : check-target-builds ;