mirror of
https://github.com/boostorg/build.git
synced 2026-02-14 00:32:11 +00:00
Complete porting of build/targets.jam
[SVN r64537]
This commit is contained in:
@@ -853,7 +853,7 @@ def find_viable_generators_aux (target_type, prop_set):
|
||||
m = g.match_rank(prop_set)
|
||||
if m:
|
||||
dout(" is viable")
|
||||
viable_generators.append(g)
|
||||
viable_generators.append(g)
|
||||
|
||||
return viable_generators
|
||||
|
||||
@@ -873,6 +873,8 @@ def find_viable_generators (target_type, prop_set):
|
||||
# TODO: is this really used?
|
||||
if not g in __active_generators:
|
||||
viable_generators.append (g)
|
||||
else:
|
||||
dout(" generator %s is active, discarning" % g.id())
|
||||
|
||||
# Generators which override 'all'.
|
||||
all_overrides = []
|
||||
@@ -941,7 +943,7 @@ def __construct_really (project, name, target_type, prop_set, sources):
|
||||
return result;
|
||||
|
||||
|
||||
def construct (project, name, target_type, prop_set, sources):
|
||||
def construct (project, name, target_type, prop_set, sources, top_level=False):
|
||||
""" Attempts to create target of 'target-type' with 'properties'
|
||||
from 'sources'. The 'sources' are treated as a collection of
|
||||
*possible* ingridients -- i.e. it is not required to consume
|
||||
@@ -951,9 +953,19 @@ def construct (project, name, target_type, prop_set, sources):
|
||||
Returns a list of target. When this invocation is first instance of
|
||||
'construct' in stack, returns only targets of requested 'target-type',
|
||||
otherwise, returns also unused sources and additionally generated
|
||||
targets.
|
||||
targets.
|
||||
|
||||
If 'top-level' is set, does not suppress generators that are already
|
||||
used in the stack. This may be useful in cases where a generator
|
||||
has to build a metatargets -- for example a target corresponding to
|
||||
built tool.
|
||||
"""
|
||||
# TODO: Why is global needed here?
|
||||
|
||||
global __active_generators
|
||||
if top_level:
|
||||
saved_active = __active_generators
|
||||
__active_generators = []
|
||||
|
||||
global __construct_stack
|
||||
if __construct_stack:
|
||||
__ensure_type (sources)
|
||||
@@ -976,5 +988,8 @@ def construct (project, name, target_type, prop_set, sources):
|
||||
|
||||
__construct_stack = __construct_stack [1:]
|
||||
|
||||
if top_level:
|
||||
__active_generators = saved_active
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Status: being ported by Vladimir Prus
|
||||
# Still to do: call toolset.requirements when those are ported.
|
||||
# Remember the location of target.
|
||||
# Base revision: 40480
|
||||
# Status: ported.
|
||||
# Base revision: 64488
|
||||
|
||||
# Copyright Vladimir Prus 2002-2007.
|
||||
# Copyright Rene Rivera 2006.
|
||||
@@ -104,6 +102,8 @@ class TargetRegistry:
|
||||
|
||||
self.debug_building_ = "--debug-building" in bjam.variable("ARGV")
|
||||
|
||||
self.targets_ = []
|
||||
|
||||
def main_target_alternative (self, target):
|
||||
""" Registers the specified target as a main target alternatives.
|
||||
Returns 'target'.
|
||||
@@ -232,6 +232,16 @@ class TargetRegistry:
|
||||
if self.debug_building_:
|
||||
print self.indent_ + message
|
||||
|
||||
def push_target(self, target):
|
||||
self.targets_.append(target)
|
||||
|
||||
def pop_target(self):
|
||||
self.targets_ = self.targets_[:-1]
|
||||
|
||||
def current(self):
|
||||
return self.targets_[0]
|
||||
|
||||
|
||||
class GenerateResult:
|
||||
|
||||
def __init__ (self, ur=None, targets=None):
|
||||
@@ -363,6 +373,9 @@ class ProjectTarget (AbstractTarget):
|
||||
# Targets marked as explicit.
|
||||
self.explicit_targets_ = set()
|
||||
|
||||
# Targets marked as always
|
||||
self.always_targets_ = set()
|
||||
|
||||
# The constants defined for this project.
|
||||
self.constants_ = {}
|
||||
|
||||
@@ -423,7 +436,7 @@ class ProjectTarget (AbstractTarget):
|
||||
# Collect all projects referenced via "projects-to-build" attribute.
|
||||
self_location = self.get ('location')
|
||||
for pn in self.get ('projects-to-build'):
|
||||
result.append (self.find(pn))
|
||||
result.append (self.find(pn + "/"))
|
||||
|
||||
return result
|
||||
|
||||
@@ -434,6 +447,9 @@ class ProjectTarget (AbstractTarget):
|
||||
# Record the name of the target, not instance, since this
|
||||
# rule is called before main target instaces are created.
|
||||
self.explicit_targets_.add(target_name)
|
||||
|
||||
def mark_target_as_always(self, target_name):
|
||||
self.always_targets_.add(target_name)
|
||||
|
||||
def add_alternative (self, target_instance):
|
||||
""" Add new target alternative.
|
||||
@@ -548,6 +564,9 @@ class ProjectTarget (AbstractTarget):
|
||||
if not self.main_target_.has_key (name):
|
||||
t = MainTarget (name, self.project_)
|
||||
self.main_target_ [name] = t
|
||||
|
||||
if name in self.always_targets_:
|
||||
a.always()
|
||||
|
||||
self.main_target_ [name].add_alternative (a)
|
||||
|
||||
@@ -561,7 +580,16 @@ class ProjectTarget (AbstractTarget):
|
||||
"""
|
||||
|
||||
if path:
|
||||
value = os.path.join(self.location_, value)
|
||||
l = self.location_
|
||||
if not l:
|
||||
# Project corresponding to config files do not have
|
||||
# 'location' attribute, but do have source location.
|
||||
# It might be more reasonable to make every project have
|
||||
# a location and use some other approach to prevent buildable
|
||||
# targets in config files, but that's for later.
|
||||
l = get('source-location')
|
||||
|
||||
value = os.path.join(l, value)
|
||||
# Now make the value absolute path
|
||||
value = os.path.join(os.getcwd(), value)
|
||||
|
||||
@@ -660,46 +688,7 @@ class MainTarget (AbstractTarget):
|
||||
return best
|
||||
|
||||
def apply_default_build (self, property_set):
|
||||
# 1. First, see what properties from default_build
|
||||
# are already present in property_set.
|
||||
|
||||
specified_features = set(p.feature() for p in property_set.all())
|
||||
|
||||
defaults_to_apply = []
|
||||
for d in self.default_build_.all():
|
||||
if not d.feature() in specified_features:
|
||||
defaults_to_apply.append(d)
|
||||
|
||||
# 2. If there's any defaults to be applied, form the new
|
||||
# build request. Pass it throw 'expand-no-defaults', since
|
||||
# default_build might contain "release debug", which will
|
||||
# result in two property_sets.
|
||||
result = []
|
||||
if defaults_to_apply:
|
||||
|
||||
# We have to compress subproperties here to prevent
|
||||
# property lists like:
|
||||
#
|
||||
# <toolset>msvc <toolset-msvc:version>7.1 <threading>multi
|
||||
#
|
||||
# from being expanded into:
|
||||
#
|
||||
# <toolset-msvc:version>7.1/<threading>multi
|
||||
# <toolset>msvc/<toolset-msvc:version>7.1/<threading>multi
|
||||
#
|
||||
# due to cross-product property combination. That may
|
||||
# be an indication that
|
||||
# build_request.expand-no-defaults is the wrong rule
|
||||
# to use here.
|
||||
compressed = feature.compress_subproperties(property_set.all())
|
||||
|
||||
result = build_request.expand_no_defaults(
|
||||
b2.build.property_set.create([p]) for p in (compressed + defaults_to_apply))
|
||||
|
||||
else:
|
||||
result.append (property_set)
|
||||
|
||||
return result
|
||||
return apply_default_build(property_set, self.default_build_)
|
||||
|
||||
def generate (self, ps):
|
||||
""" Select an alternative for this main target, by finding all alternatives
|
||||
@@ -821,11 +810,16 @@ class BasicTarget (AbstractTarget):
|
||||
self.request_cache = {}
|
||||
|
||||
self.user_context_ = self.manager_.errors().capture_user_context()
|
||||
|
||||
self.always_ = False
|
||||
|
||||
def always(self):
|
||||
self.always_ = True
|
||||
|
||||
def sources (self):
|
||||
""" Returns the list of AbstractTargets which are used as sources.
|
||||
The extra properties specified for sources are not represented.
|
||||
The only used of this rule at the moment is the '--dump-test'
|
||||
The only used of this rule at the moment is the '--dump-tests'
|
||||
feature of the test system.
|
||||
"""
|
||||
if self.source_targets_ == None:
|
||||
@@ -1084,6 +1078,8 @@ class BasicTarget (AbstractTarget):
|
||||
"Command line free features: '%s'" % str (cf.raw ()))
|
||||
self.manager().targets().log(
|
||||
"Target requirements: %s'" % str (self.requirements().raw ()))
|
||||
|
||||
self.manager().targets().push_target(self)
|
||||
|
||||
if not self.generated_.has_key(ps):
|
||||
|
||||
@@ -1127,7 +1123,10 @@ class BasicTarget (AbstractTarget):
|
||||
# We might get duplicate sources, for example if
|
||||
# we link to two library which have the same <library> in
|
||||
# usage requirements.
|
||||
source_targets = unique (source_targets)
|
||||
# Use stable sort, since for some targets the order is
|
||||
# important. E.g. RUN_PY target need python source to come
|
||||
# first.
|
||||
source_targets = unique(source_targets, stable=True)
|
||||
|
||||
# FIXME: figure why this call messes up source_targets in-place
|
||||
result = self.construct (self.name_, source_targets[:], rproperties)
|
||||
@@ -1137,6 +1136,10 @@ class BasicTarget (AbstractTarget):
|
||||
gur = result [0]
|
||||
result = result [1]
|
||||
|
||||
if self.always_:
|
||||
for t in result:
|
||||
t.always()
|
||||
|
||||
s = self.create_subvariant (
|
||||
result,
|
||||
self.manager().virtual_targets().recent_targets(), ps,
|
||||
@@ -1155,17 +1158,25 @@ class BasicTarget (AbstractTarget):
|
||||
else:
|
||||
self.generated_[ps] = GenerateResult (property_set.empty(), [])
|
||||
else:
|
||||
self.manager().targets().log(
|
||||
"Skipping build: <build>no in common properties")
|
||||
# If we just see <build>no, we cannot produce any reasonable
|
||||
# diagnostics. The code that adds this property is expected
|
||||
# to explain why a target is not built, for example using
|
||||
# the configure.log-component-configuration function.
|
||||
|
||||
# We're here either because there's error computing
|
||||
# properties, or there's <build>no in properties.
|
||||
# In the latter case we don't want any diagnostic.
|
||||
# In the former case, we need diagnostics. TODOo
|
||||
self.generated_[ps] = GenerateResult (rproperties, [])
|
||||
# If this target fails to build, add <build>no to properties
|
||||
# to cause any parent target to fail to build. Except that it
|
||||
# - does not work now, since we check for <build>no only in
|
||||
# common properties, but not in properties that came from
|
||||
# dependencies
|
||||
# - it's not clear if that's a good idea anyway. The alias
|
||||
# target, for example, should not fail to build if a dependency
|
||||
# fails.
|
||||
self.generated_[ps] = GenerateResult(
|
||||
property_set.create(["<build>no"]), [])
|
||||
else:
|
||||
self.manager().targets().log ("Already built")
|
||||
|
||||
self.manager().targets().pop_target()
|
||||
self.manager().targets().decrease_indent()
|
||||
|
||||
return self.generated_[ps]
|
||||
@@ -1273,7 +1284,7 @@ class TypedTarget (BasicTarget):
|
||||
|
||||
r = generators.construct (self.project_, name, self.type_,
|
||||
prop_set.add_raw(['<main-target-type>' + self.type_]),
|
||||
source_targets)
|
||||
source_targets, True)
|
||||
|
||||
if not r:
|
||||
print "warning: Unable to construct '%s'" % self.full_name ()
|
||||
@@ -1290,6 +1301,48 @@ class TypedTarget (BasicTarget):
|
||||
|
||||
return r
|
||||
|
||||
def apply_default_build(property_set, default_build):
|
||||
# 1. First, see what properties from default_build
|
||||
# are already present in property_set.
|
||||
|
||||
specified_features = set(p.feature() for p in property_set.all())
|
||||
|
||||
defaults_to_apply = []
|
||||
for d in default_build.all():
|
||||
if not d.feature() in specified_features:
|
||||
defaults_to_apply.append(d)
|
||||
|
||||
# 2. If there's any defaults to be applied, form the new
|
||||
# build request. Pass it throw 'expand-no-defaults', since
|
||||
# default_build might contain "release debug", which will
|
||||
# result in two property_sets.
|
||||
result = []
|
||||
if defaults_to_apply:
|
||||
|
||||
# We have to compress subproperties here to prevent
|
||||
# property lists like:
|
||||
#
|
||||
# <toolset>msvc <toolset-msvc:version>7.1 <threading>multi
|
||||
#
|
||||
# from being expanded into:
|
||||
#
|
||||
# <toolset-msvc:version>7.1/<threading>multi
|
||||
# <toolset>msvc/<toolset-msvc:version>7.1/<threading>multi
|
||||
#
|
||||
# due to cross-product property combination. That may
|
||||
# be an indication that
|
||||
# build_request.expand-no-defaults is the wrong rule
|
||||
# to use here.
|
||||
compressed = feature.compress_subproperties(property_set.all())
|
||||
|
||||
result = build_request.expand_no_defaults(
|
||||
b2.build.property_set.create([p]) for p in (compressed + defaults_to_apply))
|
||||
|
||||
else:
|
||||
result.append (property_set)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def create_typed_metatarget(name, type, sources, requirements, default_build, usage_requirements):
|
||||
|
||||
|
||||
@@ -5,19 +5,17 @@
|
||||
|
||||
import operator
|
||||
|
||||
def unique (values):
|
||||
# TODO: is this the most efficient way?
|
||||
# consider using a set from Python 2.4.
|
||||
return list(set(values))
|
||||
# cache = {}
|
||||
# result = []
|
||||
# for v in values:
|
||||
# if not cache.has_key(v):
|
||||
# cache[v] = None
|
||||
# result.append(v)
|
||||
# return result
|
||||
|
||||
|
||||
def unique (values, stable=False):
|
||||
if stable:
|
||||
s = set()
|
||||
r = []
|
||||
for v in values:
|
||||
if not v in s:
|
||||
r.append(v)
|
||||
s.add(v)
|
||||
return r
|
||||
else:
|
||||
return list(set(values))
|
||||
|
||||
def max_element (elements, ordered = None):
|
||||
""" Returns the maximum number in 'elements'. Uses 'ordered' for comparisons,
|
||||
|
||||
Reference in New Issue
Block a user