mirror of
https://github.com/boostorg/build.git
synced 2026-02-16 13:22:11 +00:00
137 lines
3.6 KiB
Python
137 lines
3.6 KiB
Python
|
|
import bjam
|
|
import re
|
|
import types
|
|
|
|
# Decorator the specifies bjam-side prototype for a Python function
|
|
def bjam_signature(s):
|
|
|
|
def wrap(f):
|
|
f.bjam_signature = s
|
|
return f
|
|
|
|
return wrap
|
|
|
|
def metatarget(f):
|
|
|
|
f.bjam_signature = (["name"], ["sources", "*"], ["requirements", "*"],
|
|
["default_build", "*"], ["usage_requirements", "*"])
|
|
return f
|
|
|
|
class cached(object):
|
|
|
|
def __init__(self, function):
|
|
self.function = function
|
|
self.cache = {}
|
|
|
|
def __call__(self, *args):
|
|
try:
|
|
return self.cache[args]
|
|
except KeyError:
|
|
v = self.function(*args)
|
|
self.cache[args] = v
|
|
return v
|
|
|
|
def __get__(self, instance, type):
|
|
return types.MethodType(self, instance, type)
|
|
|
|
def unquote(s):
|
|
if s and s[0] == '"' and s[-1] == '"':
|
|
return s[1:-1]
|
|
else:
|
|
return s
|
|
|
|
_extract_jamfile_and_rule = re.compile("(Jamfile<.*>)%(.*)")
|
|
|
|
def qualify_jam_action(action_name, context_module):
|
|
|
|
if action_name.startswith("###"):
|
|
# Callable exported from Python. Don't touch
|
|
return action_name
|
|
elif _extract_jamfile_and_rule.match(action_name):
|
|
# Rule is already in indirect format
|
|
return action_name
|
|
else:
|
|
ix = action_name.find('.')
|
|
if ix != -1 and action_name[:ix] == context_module:
|
|
return context_module + '%' + action_name[ix+1:]
|
|
|
|
return context_module + '%' + action_name
|
|
|
|
|
|
def set_jam_action(name, *args):
|
|
|
|
m = _extract_jamfile_and_rule.match(name)
|
|
if m:
|
|
args = ("set-update-action-in-module", m.group(1), m.group(2)) + args
|
|
else:
|
|
args = ("set-update-action", name) + args
|
|
|
|
return bjam.call(*args)
|
|
|
|
|
|
def call_jam_function(name, *args):
|
|
|
|
m = _extract_jamfile_and_rule.match(name)
|
|
if m:
|
|
args = ("call-in-module", m.group(1), m.group(2)) + args
|
|
return bjam.call(*args)
|
|
else:
|
|
return bjam.call(*((name,) + args))
|
|
|
|
__value_id = 0
|
|
__python_to_jam = {}
|
|
__jam_to_python = {}
|
|
|
|
def value_to_jam(value, methods=False):
|
|
"""Makes a token to refer to a Python value inside Jam language code.
|
|
|
|
The token is merely a string that can be passed around in Jam code and
|
|
eventually passed back. For example, we might want to pass PropertySet
|
|
instance to a tag function and it might eventually call back
|
|
to virtual_target.add_suffix_and_prefix, passing the same instance.
|
|
|
|
For values that are classes, we'll also make class methods callable
|
|
from Jam.
|
|
|
|
Note that this is necessary to make a bit more of existing Jamfiles work.
|
|
This trick should not be used to much, or else the performance benefits of
|
|
Python port will be eaten.
|
|
"""
|
|
|
|
global __value_id
|
|
|
|
r = __python_to_jam.get(value, None)
|
|
if r:
|
|
return r
|
|
|
|
exported_name = '###_' + str(__value_id)
|
|
__value_id = __value_id + 1
|
|
__python_to_jam[value] = exported_name
|
|
__jam_to_python[exported_name] = value
|
|
|
|
if methods and type(value) == types.InstanceType:
|
|
for field_name in dir(value):
|
|
field = getattr(value, field_name)
|
|
if callable(field) and not field_name.startswith("__"):
|
|
bjam.import_rule("", exported_name + "." + field_name, field)
|
|
|
|
return exported_name
|
|
|
|
def record_jam_to_value_mapping(jam_value, python_value):
|
|
__jam_to_python[jam_value] = python_value
|
|
|
|
def jam_to_value_maybe(jam_value):
|
|
|
|
if type(jam_value) == type(""):
|
|
return __jam_to_python.get(jam_value, jam_value)
|
|
else:
|
|
return jam_value
|
|
|
|
def stem(filename):
|
|
i = filename.find('.')
|
|
if i != -1:
|
|
return filename[0:i]
|
|
else:
|
|
return filename
|