2
0
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:
Vladimir Prus
2010-08-02 11:38:54 +00:00
parent 160f162bd5
commit a4095787fa
3 changed files with 139 additions and 73 deletions

View File

@@ -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

View File

@@ -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):

View File

@@ -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,