mirror of
https://github.com/boostorg/build.git
synced 2026-02-17 01:32:12 +00:00
Partially upgrade build/generators.py
[SVN r64539]
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# Status: being ported by Vladimir Prus
|
||||
# Base revision: 41557
|
||||
# Base revision: 48649
|
||||
# TODO: replace the logging with dout
|
||||
|
||||
# Copyright Vladimir Prus 2002.
|
||||
@@ -59,6 +59,7 @@ from b2.util import set
|
||||
from b2.util.sequence import unique
|
||||
import b2.util.sequence as sequence
|
||||
from b2.manager import get_manager
|
||||
import b2.build.type
|
||||
|
||||
def reset ():
|
||||
""" Clear the module state. This is mainly for testing purposes.
|
||||
@@ -66,6 +67,7 @@ def reset ():
|
||||
global __generators, __type_to_generators, __generators_for_toolset, __construct_stack
|
||||
global __overrides, __active_generators
|
||||
global __viable_generators_cache, __viable_source_types_cache
|
||||
global __vstg_cached_generators, __vst_cached_types
|
||||
|
||||
__generators = {}
|
||||
__type_to_generators = {}
|
||||
@@ -78,6 +80,9 @@ def reset ():
|
||||
__viable_source_types_cache = {}
|
||||
__active_generators = []
|
||||
|
||||
__vstg_cached_generators = []
|
||||
__vst_cached_types = []
|
||||
|
||||
reset ()
|
||||
|
||||
_re_separate_types_prefix_and_postfix = re.compile ('([^\\(]*)(\\((.*)%(.*)\\))?')
|
||||
@@ -101,6 +106,54 @@ def decrease_indent():
|
||||
global __indent
|
||||
__indent = __indent[0:-4]
|
||||
|
||||
|
||||
# Updated cached viable source target type information as needed after a new
|
||||
# derived target type gets added. This is needed because if a target type is a
|
||||
# viable source target type for some generator then all of the target type's
|
||||
# derived target types are automatically viable as source target types for the
|
||||
# same generator. Does nothing if a non-derived target type is passed to it.
|
||||
#
|
||||
def update_cached_information_with_a_new_type(type):
|
||||
|
||||
base_type = b2.build.type.base(type)
|
||||
|
||||
if base_type:
|
||||
for g in __vstg_cached_generators:
|
||||
if base_type in __viable_source_types_cache.get(g, []):
|
||||
__viable_source_types_cache[g].append(type)
|
||||
|
||||
for t in __vst_cached_types:
|
||||
if base_type in __viable_source_types_cache.get(t, []):
|
||||
__viable_source_types_cache[t].append(type)
|
||||
|
||||
# Clears cached viable source target type information except for target types
|
||||
# and generators with all source types listed as viable. Should be called when
|
||||
# something invalidates those cached values by possibly causing some new source
|
||||
# types to become viable.
|
||||
#
|
||||
def invalidate_extendable_viable_source_target_type_cache():
|
||||
|
||||
global __vstg_cached_generators
|
||||
generators_with_cached_source_types = __vstg_cached_generators
|
||||
__vstg_cached_generators = []
|
||||
|
||||
for g in generators_with_cached_source_types:
|
||||
if __viable_source_types_cache.has_key(g):
|
||||
if __viable_source_types_cache[g] == ["*"]:
|
||||
__vstg_cached_generators.append(g)
|
||||
else:
|
||||
del __viable_source_types_cache[g]
|
||||
|
||||
global __vst_cached_types
|
||||
types_with_cached_sources_types = __vst_cached_types
|
||||
__vst_cached_types = []
|
||||
for t in types_with_cached_sources_types:
|
||||
if __viable_source_types_cache.has_key(t):
|
||||
if __viable_source_types_cache[t] == ["*"]:
|
||||
__vst_cached_types.append(t)
|
||||
else:
|
||||
del __viable_source_types_cache[t]
|
||||
|
||||
def dout(message):
|
||||
if debug():
|
||||
print __indent + message
|
||||
@@ -589,6 +642,24 @@ def register (g):
|
||||
|
||||
__generators_for_toolset.setdefault(base, []).append(g)
|
||||
|
||||
# After adding a new generator that can construct new target types, we need
|
||||
# to clear the related cached viable source target type information for
|
||||
# constructing a specific target type or using a specific generator. Cached
|
||||
# viable source target type lists affected by this are those containing any
|
||||
# of the target types constructed by the new generator or any of their base
|
||||
# target types.
|
||||
#
|
||||
# A more advanced alternative to clearing that cached viable source target
|
||||
# type information would be to expand it with additional source types or
|
||||
# even better - mark it as needing to be expanded on next use.
|
||||
#
|
||||
# For now we just clear all the cached viable source target type information
|
||||
# that does not simply state 'all types' and may implement a more detailed
|
||||
# algorithm later on if it becomes needed.
|
||||
|
||||
invalidate_extendable_viable_source_target_type_cache()
|
||||
|
||||
|
||||
def register_standard (id, source_types, target_types, requirements = []):
|
||||
""" Creates new instance of the 'generator' class and registers it.
|
||||
Returns the creates instance.
|
||||
@@ -632,11 +703,19 @@ def __viable_source_types_real (target_type):
|
||||
of calling itself recusrively on source types.
|
||||
"""
|
||||
generators = []
|
||||
|
||||
t = type.all_bases (target_type)
|
||||
|
||||
# 't0' is the initial list of target types we need to process to get a list
|
||||
# of their viable source target types. New target types will not be added to
|
||||
# this list.
|
||||
t0 = type.all_bases (target_type)
|
||||
|
||||
|
||||
# 't' is the list of target types which have not yet been processed to get a
|
||||
# list of their viable source target types. This list will get expanded as
|
||||
# we locate more target types to process.
|
||||
t = t0
|
||||
|
||||
result = []
|
||||
# 't' is the list of types which are not yet processed
|
||||
while t:
|
||||
# Find all generators for current type.
|
||||
# Unlike 'find_viable_generators' we don't care about prop_set.
|
||||
@@ -658,19 +737,29 @@ def __viable_source_types_real (target_type):
|
||||
all = type.all_derived (source_type)
|
||||
for n in all:
|
||||
if not n in result:
|
||||
t.append (n)
|
||||
|
||||
# Here there is no point in adding target types to
|
||||
# the list of types to process in case they are or
|
||||
# have already been on that list. We optimize this
|
||||
# check by realizing that we only need to avoid the
|
||||
# original target type's base types. Other target
|
||||
# types that are or have been on the list of target
|
||||
# types to process have been added to the 'result'
|
||||
# list as well and have thus already been eliminated
|
||||
# by the previous if.
|
||||
if not n in t0:
|
||||
t.append (n)
|
||||
result.append (n)
|
||||
|
||||
result = unique (result)
|
||||
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def viable_source_types (target_type):
|
||||
""" Helper rule, caches the result of '__viable_source_types_real'.
|
||||
"""
|
||||
if not __viable_source_types_cache.has_key (target_type):
|
||||
__viable_source_types_cache [target_type] = __viable_source_types_real (target_type)
|
||||
if not __viable_source_types_cache.has_key(target_type):
|
||||
__vst_cached_types.append(target_type)
|
||||
__viable_source_types_cache [target_type] = __viable_source_types_real (target_type)
|
||||
return __viable_source_types_cache [target_type]
|
||||
|
||||
def viable_source_types_for_generator_real (generator):
|
||||
@@ -691,20 +780,22 @@ def viable_source_types_for_generator_real (generator):
|
||||
else:
|
||||
result = []
|
||||
for s in source_types:
|
||||
result += type.all_derived (s) + viable_source_types (s)
|
||||
result = unique (result)
|
||||
if "*" in result:
|
||||
result = ["*"]
|
||||
return result
|
||||
viable_sources = viable_source_types(s)
|
||||
if viable_sources == "*":
|
||||
result = ["*"]
|
||||
break
|
||||
else:
|
||||
result.extend(type.all_derived(s) + viable_sources)
|
||||
return unique(result)
|
||||
|
||||
def viable_source_types_for_generator (generator):
|
||||
""" Caches the result of 'viable_source_types_for_generator'.
|
||||
"""
|
||||
key = str (generator)
|
||||
if not __viable_source_types_cache.has_key (key):
|
||||
__viable_source_types_cache [key] = viable_source_types_for_generator_real (generator)
|
||||
if not __viable_source_types_cache.has_key(generator):
|
||||
__vstg_cached_generators.append(generator)
|
||||
__viable_source_types_cache[generator] = viable_source_types_for_generator_real (generator)
|
||||
|
||||
return __viable_source_types_cache [key]
|
||||
return __viable_source_types_cache[generator]
|
||||
|
||||
def try_one_generator_really (project, name, generator, target_type, properties, sources):
|
||||
""" Returns usage requirements + list of created targets.
|
||||
@@ -861,6 +952,8 @@ def find_viable_generators (target_type, prop_set):
|
||||
key = target_type + '.' + str (prop_set)
|
||||
|
||||
l = __viable_generators_cache.get (key, None)
|
||||
if not l:
|
||||
l = []
|
||||
|
||||
if not l:
|
||||
l = find_viable_generators_aux (target_type, prop_set)
|
||||
@@ -899,6 +992,7 @@ def find_viable_generators (target_type, prop_set):
|
||||
for g in viable_generators:
|
||||
if not g.id () in overriden_ids:
|
||||
result.append (g)
|
||||
|
||||
|
||||
return result
|
||||
|
||||
@@ -909,7 +1003,7 @@ def __construct_really (project, name, target_type, prop_set, sources):
|
||||
viable_generators = find_viable_generators (target_type, prop_set)
|
||||
|
||||
result = []
|
||||
|
||||
|
||||
project.manager ().logger ().log (__name__, "*** %d viable generators" % len (viable_generators))
|
||||
|
||||
generators_that_succeeded = []
|
||||
|
||||
@@ -16,6 +16,7 @@ from b2.exceptions import *
|
||||
from b2.build import feature, property, scanner
|
||||
from b2.util import bjam_signature
|
||||
|
||||
|
||||
__re_hyphen = re.compile ('-')
|
||||
|
||||
def __register_features ():
|
||||
@@ -98,6 +99,12 @@ def register (type, suffixes = [], base_type = None):
|
||||
feature.compose ('<target-type>' + type, replace_grist (base_type, '<base-target-type>'))
|
||||
feature.compose ('<base-target-type>' + type, '<base-target-type>' + base_type)
|
||||
|
||||
import b2.build.generators as generators
|
||||
# Adding a new derived type affects generator selection so we need to
|
||||
# make the generator selection module update any of its cached
|
||||
# information related to a new derived type being defined.
|
||||
generators.update_cached_information_with_a_new_type(type)
|
||||
|
||||
# FIXME: resolving recursive dependency.
|
||||
from b2.manager import get_manager
|
||||
get_manager().projects().project_rules().add_rule_for_type(type)
|
||||
@@ -142,6 +149,12 @@ def get_scanner (type, prop_set):
|
||||
|
||||
return None
|
||||
|
||||
def base(type):
|
||||
"""Returns a base type for the given type or nothing in case the given type is
|
||||
not derived."""
|
||||
|
||||
return __types[type]['base']
|
||||
|
||||
def all_bases (type):
|
||||
""" Returns type and all of its bases, in the order of their distance from type.
|
||||
"""
|
||||
|
||||
@@ -51,6 +51,28 @@ else
|
||||
}
|
||||
""")
|
||||
|
||||
t.write("Other/mygen.py", """
|
||||
import b2.build.generators as generators
|
||||
import b2.build.type as type
|
||||
|
||||
from b2.manager import get_manager
|
||||
|
||||
import os
|
||||
|
||||
|
||||
type.register('MY_TYPE', ['extension'])
|
||||
generators.register_standard('mygen.generate-a-cpp-file', ['MY_TYPE'], ['CPP'])
|
||||
if os.name == 'nt':
|
||||
action = 'echo void g() {} > "$(<)"'
|
||||
else:
|
||||
action = 'echo "void g() {}" > "$(<)"'
|
||||
def f(*args):
|
||||
print "Generating a CPP file..."
|
||||
|
||||
get_manager().engine().register_action("mygen.generate-a-cpp-file",
|
||||
action, function=f)
|
||||
""")
|
||||
|
||||
t.write("Other/jamfile.jam", """
|
||||
import mygen ;
|
||||
obj other-obj : source.extension ;
|
||||
|
||||
@@ -30,7 +30,7 @@ class NullLogger:
|
||||
return False
|
||||
|
||||
def on (self):
|
||||
return False
|
||||
return True
|
||||
|
||||
class TextLogger (NullLogger):
|
||||
def __init__ (self):
|
||||
|
||||
Reference in New Issue
Block a user