def process(self, target, matches, binding): target_path = os.path.normpath(os.path.dirname(binding[0])) bjam.call("mark-included", target, matches) get_manager().engine().set_target_variable(matches, "SEARCH", [target_path] + self.includes) get_manager().scanners().propagate(self, matches)
def prepare_foo(targets, sources, properties): if properties.get('os') in ['windows', 'cygwin']: bjam.call('set-target-variable', targets, "DECL", "void __declspec(dllexport) foo(){}") pass
def mkdir(engine, target): assert isinstance(target, basestring) # If dir exists, do not update it. Do this even for $(DOT). bjam.call('NOUPDATE', target) global __mkdir_set # FIXME: Where is DOT defined? #if $(<) != $(DOT) && ! $($(<)-mkdir): if target != '.' and target not in __mkdir_set: # Cheesy gate to prevent multiple invocations on same dir. __mkdir_set.add(target) # Schedule the mkdir build action. engine.set_update_action("common.MkDir", target, []) # Prepare a Jam 'dirs' target that can be used to make the build only # construct all the target directories. engine.add_dependency('dirs', target) # Recursively create parent directories. $(<:P) = $(<)'s parent & we # recurse until root. s = os.path.dirname(target) if os_name() == 'NT': if (__re_windows_drive.match(s)): s = '' if s: if s != target: engine.add_dependency(target, s) mkdir(engine, s) else: bjam.call('NOTFILE', s)
def gcc_archive(targets, sources, properties): # Always remove archive and start again. Here's rationale from # # Andre Hentz: # # I had a file, say a1.c, that was included into liba.a. I moved a1.c to # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd # errors. After some debugging I traced it back to the fact that a1.o was # *still* in liba.a # # Rene Rivera: # # Originally removing the archive was done by splicing an RM onto the # archive action. That makes archives fail to build on NT when they have # many files because it will no longer execute the action directly and blow # the line length limit. Instead we remove the file in a different action, # just before building the archive. clean = targets[0] + '(clean)' bjam.call('TEMPORARY', clean) bjam.call('NOCARE', clean) engine = get_manager().engine() engine.set_target_variable( 'LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) engine.add_dependency(clean, sources) engine.add_dependency(targets, clean) engine.set_update_action('common.RmTemps', clean, targets)
def mkdir(engine, target): assert isinstance(target, basestring) # If dir exists, do not update it. Do this even for $(DOT). bjam.call('NOUPDATE', target) global __mkdir_set # FIXME: Where is DOT defined? #if $(<) != $(DOT) && ! $($(<)-mkdir): if target != '.' and target not in __mkdir_set: # Cheesy gate to prevent multiple invocations on same dir. __mkdir_set.add(target) # Schedule the mkdir build action. engine.set_update_action("common.MkDir", target, []) # Prepare a Jam 'dirs' target that can be used to make the build only # construct all the target directories. engine.add_dependency('dirs', target) # Recursively create parent directories. $(<:P) = $(<)'s parent & we # recurse until root. s = os.path.dirname(target) if os_name() == 'NT': if(__re_windows_drive.match(s)): s = '' if s: if s != target: engine.add_dependency(target, s) mkdir(engine, s) else: bjam.call('NOTFILE', s)
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))
def gcc_archive(targets, sources, properties): # Always remove archive and start again. Here's rationale from # # Andre Hentz: # # I had a file, say a1.c, that was included into liba.a. I moved a1.c to # a2.c, updated my Jamfiles and rebuilt. My program was crashing with absurd # errors. After some debugging I traced it back to the fact that a1.o was # *still* in liba.a # # Rene Rivera: # # Originally removing the archive was done by splicing an RM onto the # archive action. That makes archives fail to build on NT when they have # many files because it will no longer execute the action directly and blow # the line length limit. Instead we remove the file in a different action, # just before building the archive. clean = targets[0] + '(clean)' bjam.call('TEMPORARY', clean) bjam.call('NOCARE', clean) engine = get_manager().engine() engine.set_target_variable('LOCATE', clean, bjam.call('get-target-variable', targets, 'LOCATE')) engine.add_dependency(clean, sources) engine.add_dependency(targets, clean) engine.set_update_action('common.RmTemps', clean, targets)
def actualize(self): """ Generates actual build instructions. """ if self.actualized_: return self.actualized_ = True ps = self.properties() properties = self.adjust_properties(ps) actual_targets = [] for i in self.targets(): actual_targets.append(i.actualize()) self.actualize_sources(self.sources(), properties) self.engine_.add_dependency( actual_targets, self.actual_sources_ + self.dependency_only_sources_) # This works around a bug with -j and actions that # produce multiple target, where: # - dependency on the first output is found, and # the action is started # - dependency on the second output is found, and # bjam noticed that command is already running # - instead of waiting for the command, dependents # of the second targets are immediately updated. if len(actual_targets) > 1: bjam.call("INCLUDES", actual_targets, actual_targets) # FIXME: check the comment below. Was self.action_name_ [1] # Action name can include additional argument to rule, which should not # be passed to 'set-target-variables' # FIXME: breaking circular dependency import toolset toolset.set_target_variables(self.manager_, self.action_name_, actual_targets, properties) engine = self.manager_.engine() # FIXME: this is supposed to help --out-xml option, but we don't # implement that now, and anyway, we should handle it in Python, # not but putting variables on bjam-level targets. bjam.call("set-target-variable", actual_targets, ".action", repr(self)) self.manager_.engine().set_update_action(self.action_name_, actual_targets, self.actual_sources_, properties) # Since we set up creating action here, we also set up # action for cleaning up self.manager_.engine().set_update_action('common.Clean', 'clean-all', actual_targets) return actual_targets
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))
def process(self, target, matches, binding): binding = binding[0] angle = regex.transform(matches, "#include[ ]*<([^<]+)>") quoted = regex.transform(matches, "#include[ ]*\"([^\"]+)\"") res = regex.transform(matches, "[^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)" +\ "[ ]+(([^ \"]+)|\"([^\"]+)\")", [3, 4]) # Icons and other includes may referenced as # # IDR_MAINFRAME ICON "res\\icon.ico" # # so we have to replace double backslashes to single ones. res = [ re.sub(r'\\\\', '/', match) for match in res if match is not None ] # CONSIDER: the new scoping rule seem to defeat "on target" variables. g = bjam.call('get-target-variable', target, 'HDRGRIST')[0] b = os.path.normpath(os.path.dirname(binding)) # Attach binding of including file to included targets. # When target is directly created from virtual target # this extra information is unnecessary. But in other # cases, it allows to distinguish between two headers of the # same name included from different places. # We don't need this extra information for angle includes, # since they should not depend on including file (we can't # get literal "." in include path). g2 = g + "#" + b g = "<" + g + ">" g2 = "<" + g2 + ">" angle = [g + x for x in angle] quoted = [g2 + x for x in quoted] res = [g2 + x for x in res] all = angle + quoted bjam.call('mark-included', target, all) engine = get_manager().engine() engine.add_dependency(target, res) bjam.call('NOCARE', all + res) engine.set_target_variable( angle, 'SEARCH', [utility.get_value(inc) for inc in self.includes]) engine.set_target_variable( quoted, 'SEARCH', [b + utility.get_value(inc) for inc in self.includes]) engine.set_target_variable( res, 'SEARCH', [b + utility.get_value(inc) for inc in self.includes]) # Just propagate current scanner to includes, in a hope # that includes do not change scanners. get_manager().scanners().propagate(self, angle + quoted)
def use_project(version=None): projects.push_current(projects.current()) if not version: version = __boost_default if not version: version = "auto_config" global __initialized if __initialized: if __initialized != version: get_manager().errors()( 'Attempt to use {} with different parameters'.format('boost')) else: if version in __boost_configured: opts = __boost_configured[version] root = opts.get('<root>') inc = opts.get('<include>') lib = opts.get('<library>') if debug(): print "notice: using boost library {} {}".format( version, opt.raw()) global __layout global __version_tag __layout = opts.get('<layout>') if not __layout: __layout = 'versioned' __build_id = opts.get('<build-id>') __version_tag = re.sub("[*\\/:.\"\' ]", "_", version) __initialized = version if ( root and inc ) or \ ( root and lib ) or \ ( lib and not inc ) or \ ( not lib and inc ): get_manager().errors( )("Ambiguous parameters, use either <root> or <inlude> with <library>." ) elif not root and not inc: root = bjam.variable("BOOST_ROOT") module = projects.current().project_module() if root: bjam.call('call-in-module', module, 'use-project', ['boost', root]) else: projects.initialize(__name__) if version == '0.0.1': boost_0_0_1(inc, lib) else: boost_std(inc, lib) else: get_manager().errors()("Reference to unconfigured boost version.") projects.pop_current()
def capture_output_setup(target, sources, ps): if __debug__: from ..build.property_set import PropertySet assert is_iterable_typed(target, basestring) assert is_iterable_typed(sources, basestring) assert isinstance(ps, PropertySet) run_path_setup(target[0], sources, ps) if ps.get('preserve-test-targets') == ['off']: bjam.call("set-target-variable", target, "REMOVE_TEST_TARGETS", "1")
def actualize (self): """ Generates actual build instructions. """ if self.actualized_: return self.actualized_ = True ps = self.properties () properties = self.adjust_properties (ps) actual_targets = [] for i in self.targets (): actual_targets.append (i.actualize ()) self.actualize_sources (self.sources (), properties) self.engine_.add_dependency (actual_targets, self.actual_sources_ + self.dependency_only_sources_) # This works around a bug with -j and actions that # produce multiple target, where: # - dependency on the first output is found, and # the action is started # - dependency on the second output is found, and # bjam noticed that command is already running # - instead of waiting for the command, dependents # of the second targets are immediately updated. if len(actual_targets) > 1: bjam.call("INCLUDES", actual_targets, actual_targets) # FIXME: check the comment below. Was self.action_name_ [1] # Action name can include additional argument to rule, which should not # be passed to 'set-target-variables' # FIXME: breaking circular dependency import toolset toolset.set_target_variables (self.manager_, self.action_name_, actual_targets, properties) engine = self.manager_.engine () # FIXME: this is supposed to help --out-xml option, but we don't # implement that now, and anyway, we should handle it in Python, # not but putting variables on bjam-level targets. bjam.call("set-target-variable", actual_targets, ".action", repr(self)) self.manager_.engine ().set_update_action (self.action_name_, actual_targets, self.actual_sources_, properties) # Since we set up creating action here, we also set up # action for cleaning up self.manager_.engine ().set_update_action ('common.Clean', 'clean-all', actual_targets) return actual_targets
def use_project(version = None): projects.push_current( projects.current() ) if not version: version = __boost_default if not version: version = "auto_config" global __initialized if __initialized: if __initialized != version: get_manager().errors()('Attempt to use {} with different parameters'.format('boost')) else: if version in __boost_configured: opts = __boost_configured[ version ] root = opts.get('<root>' ) inc = opts.get('<include>') lib = opts.get('<library>') if debug(): print "notice: using boost library {} {}".format( version, opt.raw() ) global __layout global __version_tag __layout = opts.get('<layout>') if not __layout: __layout = 'versioned' __build_id = opts.get('<build-id>') __version_tag = re.sub("[*\\/:.\"\' ]", "_", version) __initialized = version if ( root and inc ) or \ ( root and lib ) or \ ( lib and not inc ) or \ ( not lib and inc ): get_manager().errors()("Ambiguous parameters, use either <root> or <inlude> with <library>.") elif not root and not inc: root = bjam.variable("BOOST_ROOT") module = projects.current().project_module() if root: bjam.call('call-in-module', module, 'use-project', ['boost', root]) else: projects.initialize(__name__) if version == '0.0.1': boost_0_0_1( inc, lib ) else: boost_std( inc, lib ) else: get_manager().errors()("Reference to unconfigured boost version.") projects.pop_current()
def run_path_setup(target, sources, ps): # For testing, we need to make sure that all dynamic libraries needed by the # test are found. So, we collect all paths from dependency libraries (via # xdll-path property) and add whatever explicit dll-path user has specified. # The resulting paths are added to the environment on each test invocation. dll_paths = ps.get('dll-path') dll_paths.extend(ps.get('xdll-path')) dll_paths.extend(bjam.call("get-target-variable", sources, "RUN_PATH")) dll_paths = unique(dll_paths) if dll_paths: bjam.call("set-target-variable", target, "PATH_SETUP", common.prepend_path_variable_command( common.shared_library_path_variable(), dll_paths))
def load_standalone(self, jamfile_module, file): """Loads 'file' as standalone project that has no location associated with it. This is mostly useful for user-config.jam, which should be able to define targets, but although it has some location in filesystem, we do not want any build to happen in user's HOME, for example. The caller is required to never call this method twice on the same file. """ self.used_projects[jamfile_module] = [] bjam.call("load", jamfile_module, file) self.load_used_projects(jamfile_module)
def process(self, target, matches, binding): binding = binding[0] angle = regex.transform(matches, "#include[ ]*<([^<]+)>") quoted = regex.transform(matches, "#include[ ]*\"([^\"]+)\"") res = regex.transform(matches, "[^ ]+[ ]+(BITMAP|CURSOR|FONT|ICON|MESSAGETABLE|RT_MANIFEST)" +\ "[ ]+(([^ \"]+)|\"([^\"]+)\")", [3, 4]) # Icons and other includes may referenced as # # IDR_MAINFRAME ICON "res\\icon.ico" # # so we have to replace double backslashes to single ones. res = [ re.sub(r'\\\\', '/', match) for match in res if match is not None ] # CONSIDER: the new scoping rule seem to defeat "on target" variables. g = bjam.call('get-target-variable', target, 'HDRGRIST')[0] b = os.path.normpath(os.path.dirname(binding)) # Attach binding of including file to included targets. # When target is directly created from virtual target # this extra information is unnecessary. But in other # cases, it allows to distinguish between two headers of the # same name included from different places. # We don't need this extra information for angle includes, # since they should not depend on including file (we can't # get literal "." in include path). g2 = g + "#" + b g = "<" + g + ">" g2 = "<" + g2 + ">" angle = [g + x for x in angle] quoted = [g2 + x for x in quoted] res = [g2 + x for x in res] all = angle + quoted bjam.call('mark-included', target, all) engine = get_manager().engine() engine.add_dependency(target, res) bjam.call('NOCARE', all + res) engine.set_target_variable(angle, 'SEARCH', [utility.get_value(inc) for inc in self.includes]) engine.set_target_variable(quoted, 'SEARCH', [b + utility.get_value(inc) for inc in self.includes]) engine.set_target_variable(res, 'SEARCH', [b + utility.get_value(inc) for inc in self.includes]) # Just propagate current scanner to includes, in a hope # that includes do not change scanners. get_manager().scanners().propagate(self, angle + quoted)
def load_standalone(self, jamfile_module, file): """Loads 'file' as standalone project that has no location associated with it. This is mostly useful for user-config.jam, which should be able to define targets, but although it has some location in filesystem, we don't want any build to happen in user's HOME, for example. The caller is required to never call this method twice on the same file. """ self.used_projects[jamfile_module] = [] bjam.call("load", jamfile_module, file) self.load_used_projects(jamfile_module)
def actualize(self): """ Generates actual build instructions. """ if self.actualized_: return self.actualized_ = True ps = self.properties() properties = self.adjust_properties(ps) actual_targets = [] for i in self.targets(): actual_targets.append(i.actualize()) self.actualize_sources(self.sources(), properties) self.engine_.add_dependency( actual_targets, self.actual_sources_ + self.dependency_only_sources_) # FIXME: check the comment below. Was self.action_name_ [1] # Action name can include additional rule arguments, which should not # be passed to 'set-target-variables'. # FIXME: breaking circular dependency import toolset toolset.set_target_variables(self.manager_, self.action_name_, actual_targets, properties) engine = self.manager_.engine() # FIXME: this is supposed to help --out-xml option, but we don't # implement that now, and anyway, we should handle it in Python, # not but putting variables on bjam-level targets. bjam.call("set-target-variable", actual_targets, ".action", repr(self)) self.manager_.engine().set_update_action(self.action_name_, actual_targets, self.actual_sources_, properties) # Since we set up creating action here, we also set up # action for cleaning up self.manager_.engine().set_update_action('common.Clean', 'clean-all', actual_targets) return actual_targets
def builds(metatarget_reference, project, ps, what): # Attempt to build a metatarget named by 'metatarget-reference' # in context of 'project' with properties 'ps'. # Returns non-empty value if build is OK. assert isinstance(metatarget_reference, basestring) assert isinstance(project, targets_.ProjectTarget) assert isinstance(ps, property_set.PropertySet) assert isinstance(what, basestring) result = [] existing = __builds_cache.get((what, ps), None) if existing is None: result = False __builds_cache[(what, ps)] = False targets = targets_.generate_from_reference(metatarget_reference, project, ps).targets() jam_targets = [] for t in targets: jam_targets.append(t.actualize()) x = (" - %s" % what).rjust(__width) if bjam.call("UPDATE_NOW", jam_targets, str(__log_fd), "ignore-minus-n"): __builds_cache[(what, ps)] = True result = True log_check_result("%s: yes" % x) else: log_check_result("%s: no" % x) return result else: return existing
def builds(metatarget_reference, project, ps, what): # Attempt to build a metatarget named by 'metatarget-reference' # in context of 'project' with properties 'ps'. # Returns non-empty value if build is OK. result = [] existing = __builds_cache.get((what, ps), None) if existing is None: result = False __builds_cache[(what, ps)] = False targets = b2.build.targets.generate_from_reference(metatarget_reference, project, ps).targets() jam_targets = [] for t in targets: jam_targets.append(t.actualize()) x = (" - %s" % what).rjust(__width) if bjam.call("UPDATE_NOW", jam_targets, str(__log_fd), "ignore-minus-n"): __builds_cache[(what, ps)] = True result = True log_check_result("%s: yes" % x) else: log_check_result("%s: no" % x) return result else: return existing
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 gcc_compile_cpp(targets, sources, properties): # Some extensions are compiled as C++ by default. For others, we need to # pass -x c++. We could always pass -x c++ but distcc does not work with it. extension = os.path.splitext (sources [0]) [1] lang = '' if not extension in ['.cc', '.cp', '.cxx', '.cpp', '.c++', '.C']: lang = '-x c++' get_manager().engine().set_target_variable (targets, 'LANG', lang) engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE'))
def actualize (self): """ Generates actual build instructions. """ if self.actualized_: return self.actualized_ = True ps = self.properties () properties = self.adjust_properties (ps) actual_targets = [] for i in self.targets (): actual_targets.append (i.actualize ()) self.actualize_sources (self.sources (), properties) self.engine_.add_dependency (actual_targets, self.actual_sources_ + self.dependency_only_sources_) # FIXME: check the comment below. Was self.action_name_ [1] # Action name can include additional rule arguments, which should not # be passed to 'set-target-variables'. # FIXME: breaking circular dependency import toolset toolset.set_target_variables (self.manager_, self.action_name_, actual_targets, properties) engine = self.manager_.engine () # FIXME: this is supposed to help --out-xml option, but we don't # implement that now, and anyway, we should handle it in Python, # not but putting variables on bjam-level targets. bjam.call("set-target-variable", actual_targets, ".action", repr(self)) self.manager_.engine ().set_update_action (self.action_name_, actual_targets, self.actual_sources_, properties) # Since we set up creating action here, we also set up # action for cleaning up self.manager_.engine ().set_update_action ('common.Clean', 'clean-all', actual_targets) return actual_targets
def gcc_compile_c(targets, sources, properties): engine = get_manager().engine() # If we use the name g++ then default file suffix -> language mapping does # not work. So have to pass -x option. Maybe, we can work around this by # allowing the user to specify both C and C++ compiler names. #if $(>:S) != .c #{ engine.set_target_variable (targets, 'LANG', '-x c') #} engine.add_dependency(targets, bjam.call('get-target-variable', targets, 'PCH_FILE'))
def actualize(self, scanner=None): """ Generates all the actual targets and sets up build actions for this target. If 'scanner' is specified, creates an additional target with the same location as actual target, which will depend on the actual target and be associated with 'scanner'. That additional target is returned. See the docs (#dependency_scanning) for rationale. Target must correspond to a file if 'scanner' is specified. If scanner is not specified, then actual target is returned. """ if __debug__: from .scanner import Scanner assert scanner is None or isinstance(scanner, Scanner) actual_name = self.actualize_no_scanner() if self.always_: bjam.call("ALWAYS", actual_name) if not scanner: return actual_name else: # Add the scanner instance to the grist for name. g = '-'.join([ungrist(get_grist(actual_name)), str(id(scanner))]) name = replace_grist(actual_name, '<' + g + '>') if name not in self.made_: self.made_[name] = True self.project_.manager().engine().add_dependency( name, actual_name) self.actualize_location(name) self.project_.manager().scanners().install( scanner, name, str(self)) return name
def actualize(self, scanner=None): """ Generates all the actual targets and sets up build actions for this target. If 'scanner' is specified, creates an additional target with the same location as actual target, which will depend on the actual target and be associated with 'scanner'. That additional target is returned. See the docs (#dependency_scanning) for rationale. Target must correspond to a file if 'scanner' is specified. If scanner is not specified, then actual target is returned. """ if __debug__: from .scanner import Scanner assert scanner is None or isinstance(scanner, Scanner) actual_name = self.actualize_no_scanner() if self.always_: bjam.call("ALWAYS", actual_name) if not scanner: return actual_name else: # Add the scanner instance to the grist for name. g = "-".join([ungrist(get_grist(actual_name)), str(id(scanner))]) name = replace_grist(actual_name, "<" + g + ">") if not self.made_.has_key(name): self.made_[name] = True self.project_.manager().engine().add_dependency(name, actual_name) self.actualize_location(name) self.project_.manager().scanners().install(scanner, name, str(self)) return name
def setup_ln(targets, sources, ps): source_path = bjam.call("get-target-variable", sources[0], "LOCATE")[0] target_path = bjam.call("get-target-variable", targets[0], "LOCATE")[0] rel = os.path.relpath(source_path, target_path) if rel == ".": bjam.call("set-target-variable", targets, "PATH_TO_SOURCE", "") else: bjam.call("set-target-variable", targets, "PATH_TO_SOURCE", rel)
def reset(): """ Clear the module state. This is mainly for testing purposes. Note that this must be called _after_ resetting the module 'feature'. """ global __had_unspecified_value, __had_value, __declared_subfeature global __init_loc global __all_signatures, __debug_configuration, __show_configuration # Stores toolsets without specified initialization values. __had_unspecified_value = {} # Stores toolsets with specified initialization values. __had_value = {} # Stores toolsets with declared subfeatures. __declared_subfeature = {} # Stores all signatures of the toolsets. __all_signatures = {} # Stores the initialization locations of each toolset __init_loc = {} __debug_configuration = '--debug-configuration' in bjam.variable('ARGV') __show_configuration = '--show-configuration' in bjam.variable('ARGV') global __executable_path_variable OS = bjam.call("peek", [], "OS")[0] if OS == "NT": # On Windows the case and capitalization of PATH is not always predictable, so # let's find out what variable name was really set. for n in os.environ: if n.lower() == "path": __executable_path_variable = n break else: __executable_path_variable = "PATH" m = { "NT": __executable_path_variable, "CYGWIN": "PATH", "MACOSX": "DYLD_LIBRARY_PATH", "AIX": "LIBPATH", "HAIKU": "LIBRARY_PATH" } global __shared_library_path_variable __shared_library_path_variable = m.get(OS, "LD_LIBRARY_PATH")
def reset (): """ Clear the module state. This is mainly for testing purposes. Note that this must be called _after_ resetting the module 'feature'. """ global __had_unspecified_value, __had_value, __declared_subfeature global __init_loc global __all_signatures, __debug_configuration, __show_configuration # Stores toolsets without specified initialization values. __had_unspecified_value = {} # Stores toolsets with specified initialization values. __had_value = {} # Stores toolsets with declared subfeatures. __declared_subfeature = {} # Stores all signatures of the toolsets. __all_signatures = {} # Stores the initialization locations of each toolset __init_loc = {} __debug_configuration = '--debug-configuration' in bjam.variable('ARGV') __show_configuration = '--show-configuration' in bjam.variable('ARGV') global __executable_path_variable OS = bjam.call("peek", [], "OS")[0] if OS == "NT": # On Windows the case and capitalization of PATH is not always predictable, so # let's find out what variable name was really set. for n in os.environ: if n.lower() == "path": __executable_path_variable = n break else: __executable_path_variable = "PATH" m = {"NT": __executable_path_variable, "CYGWIN": "PATH", "MACOSX": "DYLD_LIBRARY_PATH", "AIX": "LIBPATH", "HAIKU": "LIBRARY_PATH"} global __shared_library_path_variable __shared_library_path_variable = m.get(OS, "LD_LIBRARY_PATH")
def process(self, target, matches, binding): # create a single string so that findall # can be used since it returns a list of # all grouped matches match_str = ' '.join(matches) # the question mark makes the regexes non-greedy angles = re.findall(r'<(.*?)>', match_str) quoted = re.findall(r'"(.*?)"', match_str) # CONSIDER: the new scoping rules seem to defeat "on target" variables. g = ENGINE.get_target_variable(target, 'HDRGRIST') b = os.path.normpath(os.path.dirname(binding)) # Attach binding of including file to included targets. When a target is # directly created from a virtual target this extra information is # unnecessary. But in other cases, it allows us to distinguish between # two headers of the same name included from different places. We do not # need this extra information for angle includes, since they should not # depend on the including file (we can not get literal "." in the # include path). # local g2 = $(g)"#"$(b) ; g2 = g + '#' + b angles = [replace_grist(angle, g) for angle in angles] quoted = [replace_grist(quote, g2) for quote in quoted] includes = angles + quoted bjam.call('INCLUDES', target, includes) bjam.call('NOCARE', includes) ENGINE.set_target_variable(angles, 'SEARCH', self.includes) ENGINE.set_target_variable(quoted, 'SEARCH', [b] + self.includes) # Just propagate the current scanner to includes, in hope that includes # do not change scanners. SCANNERS.propagate(self, includes) bjam.call('ISFILE', includes)
## [ modules.peek build-system : .out-xml ] ; ## } ## IMPORT ## build-system : ## out-xml.collect ## out-xml.generate-action ## : : ## build-system.out-xml.collect ## build-system.out-xml.generate-action ## ; ## } j = option.get("jobs") if j: bjam.call("set-variable", 'PARALLELISM', j) k = option.get("keep-going", "true", "true") if k in ["on", "yes", "true"]: bjam.call("set-variable", "KEEP_GOING", "1") elif k in ["off", "no", "false"]: bjam.call("set-variable", "KEEP_GOING", "0") else: print "error: Invalid value for the --keep-going option" sys.exit() # The 'all' pseudo target is not strictly needed expect in the case when we # use it below but people often assume they always have this target # available and do not declare it themselves before use which may cause # build failures with an error message about not being able to build the # 'all' target.
# Status: stub, just enough to make tests work. # # Named os_j to avoid conflicts with standard 'os'. See # project.py:import for special-casing. # # Copyright 2001, 2002, 2003, 2005 Dave Abrahams # Copyright 2006 Rene Rivera # Copyright 2003, 2005 Vladimir Prus # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) import bjam __OS = bjam.call("peek", [], "OS")[0] # Return Jam's name of OS to prevent existing code from burning # when faced with Python naming def name(): return __OS
def rc_compile_resource(targets, sources, properties): rc_type = bjam.call('get-target-variable', targets, '.RC_TYPE') rc_type = rc_type[0] if rc_type else '' global engine engine.set_update_action('rc.compile.resource.' + rc_type, targets, sources, properties)
def load_jamfile(self, dir): """Load a Jamfile at the given directory. Returns nothing. Will attempt to load the file as indicated by the JAMFILE patterns. Effect of calling this rule twice with the same 'dir' is underfined.""" # See if the Jamfile is where it should be. jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT) if not jamfile_to_load: jamfile_to_load = self.find_jamfile(dir) else: jamfile_to_load = jamfile_to_load[0] # The module of the jamfile. dir = os.path.realpath(os.path.dirname(jamfile_to_load)) jamfile_module = self.module_name(dir) # Initialize the jamfile module before loading. # self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load)) saved_project = self.current_project self.used_projects[jamfile_module] = [] # Now load the Jamfile in it's own context. # Initialization might have load parent Jamfiles, which might have # loaded the current Jamfile with use-project. Do a final check to make # sure it's not loaded already. if not jamfile_module in self.jamfile_modules: self.jamfile_modules[jamfile_module] = True # FIXME: # mark-as-user $(jamfile-module) ; bjam.call("load", jamfile_module, jamfile_to_load) basename = os.path.basename(jamfile_to_load) # Now do some checks if self.current_project != saved_project: self.manager.errors()("""The value of the .current-project variable has magically changed after loading a Jamfile. This means some of the targets might be defined a the wrong project. after loading %s expected value %s actual value %s""" % (jamfile_module, saved_project, self.current_project)) if self.global_build_dir: id = self.attribute(jamfile_module, "id") project_root = self.attribute(jamfile_module, "project-root") location = self.attribute(jamfile_module, "location") if location and project_root == dir: # This is Jamroot if not id: # FIXME: go via errors module, so that contexts are # shown? print "warning: the --build-dir option was specified" print "warning: but Jamroot at '%s'" % dir print "warning: specified no project id" print "warning: the --build-dir option will be ignored"
parent = manager.projects().attribute(project, "parent-module") if parent and parent != "user-config": r = is_child(parent) else: r = 0 is_child_cache_[project] = r return r actual_targets = [] for t in virtual_targets: actual_targets.append(t.actualize()) bjam.call("NOTFILE", "all") bjam.call("DEPENDS", "all", actual_targets) if bjam_targets: bjam.call("UPDATE", ["<e>%s" % x for x in bjam_targets]) elif clean_all: bjam.call("UPDATE", "clean-all") elif clean: to_clean = [] for t in manager.virtual_targets().all_targets(): p = t.project() # Remove only derived targets. if t.action() and \ (t in targets_to_clean or is_child(p.project_module())): to_clean.append(t)
else: parent = manager.projects().attribute(project, "parent-module") if parent and parent != "user-config": r = is_child(parent) else: r = 0 is_child_cache_[project] = r return r actual_targets = [] for t in virtual_targets: actual_targets.append(t.actualize()) bjam.call("NOTFILE", "all") bjam.call("DEPENDS", "all", actual_targets) if bjam_targets: bjam.call("UPDATE", ["<e>%s" % x for x in bjam_targets]) elif clean_all: bjam.call("UPDATE", "clean-all") elif clean: to_clean = [] for t in manager.virtual_targets().all_targets(): p = t.project() # Remove only derived targets. if t.action() and \ (t in targets_to_clean or is_child(p.project_module())): to_clean.append(t)
def capture_output_setup(target, sources, ps): run_path_setup(target, sources, ps) if ps.get('preserve-test-targets') == ['off']: bjam.call("set-target-variable", target, "REMOVE_TEST_TARGETS", "1")
run_path_setup(target, sources, ps) if ps.get('preserve-test-targets') == ['off']: bjam.call("set-target-variable", target, "REMOVE_TEST_TARGETS", "1") get_manager().engine().register_bjam_action("testing.capture-output", capture_output_setup) path = os.path.dirname(__file__) import b2.util.os_j get_manager().projects().project_rules()._import_rule("testing", "os.name", b2.util.os_j.name) import b2.tools.common get_manager().projects().project_rules()._import_rule("testing", "common.rm-command", b2.tools.common.rm_command) get_manager().projects().project_rules()._import_rule("testing", "common.file-creation-command", b2.tools.common.file_creation_command) bjam.call("load", "testing", os.path.join(path, "testing-aux.jam")) for name in ["expect-success", "expect-failure", "time"]: get_manager().engine().register_bjam_action("testing." + name) get_manager().engine().register_bjam_action("testing.unit-test", run_path_setup) if option.get("dump-tests", False, True): build_system.add_pre_build_hook(dump_tests)
## [ modules.peek build-system : .out-xml ] ; ## } ## IMPORT ## build-system : ## out-xml.collect ## out-xml.generate-action ## : : ## build-system.out-xml.collect ## build-system.out-xml.generate-action ## ; ## } j = option.get("jobs") if j: bjam.call("set-variable", PARALLELISM, j) k = option.get("keep-going", "true", "true") if k in ["on", "yes", "true"]: bjam.call("set-variable", "KEEP_GOING", "1") elif k in ["off", "no", "false"]: bjam.call("set-variable", "KEEP_GOING", "0") else: print "error: Invalid value for the --keep-going option" sys.exit() # The 'all' pseudo target is not strictly needed expect in the case when we # use it below but people often assume they always have this target # available and do not declare it themselves before use which may cause # build failures with an error message about not being able to build the # 'all' target.
def actualize_location(self, target): assert isinstance(target, basestring) bjam.call("NOTFILE", target) bjam.call("ALWAYS", target) bjam.call("NOUPDATE", target)
def actualize_location(self, target): bjam.call("NOTFILE", target) bjam.call("ALWAYS", target) bjam.call("NOUPDATE", target)
if ps.get('preserve-test-targets') == ['off']: bjam.call("set-target-variable", target, "REMOVE_TEST_TARGETS", "1") get_manager().engine().register_bjam_action("testing.capture-output", capture_output_setup) path = os.path.dirname( get_manager().projects().loaded_tool_module_path_[__name__]) import b2.util.os_j get_manager().projects().project_rules()._import_rule("testing", "os.name", b2.util.os_j.name) import b2.tools.common get_manager().projects().project_rules()._import_rule( "testing", "common.rm-command", b2.tools.common.rm_command) get_manager().projects().project_rules()._import_rule( "testing", "common.file-creation-command", b2.tools.common.file_creation_command) bjam.call("load", "testing", os.path.join(path, "testing-aux.jam")) for name in ["expect-success", "expect-failure", "time"]: get_manager().engine().register_bjam_action("testing." + name) get_manager().engine().register_bjam_action("testing.unit-test", run_path_setup) if option.get("dump-tests", False, True): build_system.add_pre_build_hook(dump_tests)
def load_jamfile(self, dir, jamfile_module): """Load a Jamfile at the given directory. Returns nothing. Will attempt to load the file as indicated by the JAMFILE patterns. Effect of calling this rule twice with the same 'dir' is underfined.""" # See if the Jamfile is where it should be. is_jamroot = False jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT) if not jamfile_to_load: jamfile_to_load = self.find_jamfile(dir) else: if len(jamfile_to_load) > 1: get_manager().errors()("Multiple Jamfiles found at '%s'\n" +\ "Filenames are: %s" % (dir, [os.path.basename(j) for j in jamfile_to_load])) is_jamroot = True jamfile_to_load = jamfile_to_load[0] dir = os.path.dirname(jamfile_to_load) if not dir: dir = "." self.used_projects[jamfile_module] = [] # Now load the Jamfile in it's own context. # The call to 'initialize' may load parent Jamfile, which might have # 'use-project' statement that causes a second attempt to load the # same project we're loading now. Checking inside .jamfile-modules # prevents that second attempt from messing up. if not jamfile_module in self.jamfile_modules: self.jamfile_modules[jamfile_module] = True # Initialize the jamfile module before loading. # self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load)) saved_project = self.current_project bjam.call("load", jamfile_module, jamfile_to_load) basename = os.path.basename(jamfile_to_load) if is_jamroot: jamfile = self.find_jamfile(dir, no_errors=True) if jamfile: bjam.call("load", jamfile_module, jamfile) # Now do some checks if self.current_project != saved_project: self.manager.errors()("""The value of the .current-project variable has magically changed after loading a Jamfile. This means some of the targets might be defined a the wrong project. after loading %s expected value %s actual value %s""" % (jamfile_module, saved_project, self.current_project)) if self.global_build_dir: id = self.attributeDefault(jamfile_module, "id", None) project_root = self.attribute(jamfile_module, "project-root") location = self.attribute(jamfile_module, "location") if location and project_root == dir: # This is Jamroot if not id: # FIXME: go via errors module, so that contexts are # shown? print "warning: the --build-dir option was specified" print "warning: but Jamroot at '%s'" % dir print "warning: specified no project id" print "warning: the --build-dir option will be ignored"
def load_jamfile(self, dir): """Load a Jamfile at the given directory. Returns nothing. Will attempt to load the file as indicated by the JAMFILE patterns. Effect of calling this rule twice with the same 'dir' is underfined.""" # See if the Jamfile is where it should be. jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT) if not jamfile_to_load: jamfile_to_load = self.find_jamfile(dir) else: jamfile_to_load = jamfile_to_load[0] # The module of the jamfile. dir = os.path.realpath(os.path.dirname(jamfile_to_load)) jamfile_module = self.module_name(dir) # Initialize the jamfile module before loading. # self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load)) saved_project = self.current_project self.used_projects[jamfile_module] = [] # Now load the Jamfile in it's own context. # Initialization might have load parent Jamfiles, which might have # loaded the current Jamfile with use-project. Do a final check to make # sure it's not loaded already. if not jamfile_module in self.jamfile_modules: self.jamfile_modules[jamfile_module] = True # FIXME: # mark-as-user $(jamfile-module) ; bjam.call("load", jamfile_module, jamfile_to_load) basename = os.path.basename(jamfile_to_load) # Now do some checks if self.current_project != saved_project: self.manager.errors()( """The value of the .current-project variable has magically changed after loading a Jamfile. This means some of the targets might be defined a the wrong project. after loading %s expected value %s actual value %s""" % (jamfile_module, saved_project, self.current_project) ) if self.global_build_dir: id = self.attribute(jamfile_module, "id") project_root = self.attribute(jamfile_module, "project-root") location = self.attribute(jamfile_module, "location") if location and project_root == dir: # This is Jamroot if not id: # FIXME: go via errors module, so that contexts are # shown? print "warning: the --build-dir option was specified" print "warning: but Jamroot at '%s'" % dir print "warning: specified no project id" print "warning: the --build-dir option will be ignored"
def rc_compile_resource(targets, sources, properties): rc_type = bjam.call('get-target-variable', targets, '.RC_TYPE') global engine engine.set_update_action('rc.compile.resource.' + rc_type, targets, sources, properties)
def load_jamfile(self, dir, jamfile_module): """Load a Jamfile at the given directory. Returns nothing. Will attempt to load the file as indicated by the JAMFILE patterns. Effect of calling this rule twice with the same 'dir' is underfined.""" # See if the Jamfile is where it should be. is_jamroot = False jamfile_to_load = b2.util.path.glob([dir], self.JAMROOT) if not jamfile_to_load: jamfile_to_load = self.find_jamfile(dir) else: if len(jamfile_to_load) > 1: get_manager().errors()("Multiple Jamfiles found at '%s'\n" +\ "Filenames are: %s" % (dir, [os.path.basename(j) for j in jamfile_to_load])) is_jamroot = True jamfile_to_load = jamfile_to_load[0] dir = os.path.dirname(jamfile_to_load) if not dir: dir = "." self.used_projects[jamfile_module] = [] # Now load the Jamfile in it's own context. # The call to 'initialize' may load parent Jamfile, which might have # 'use-project' statement that causes a second attempt to load the # same project we're loading now. Checking inside .jamfile-modules # prevents that second attempt from messing up. if not jamfile_module in self.jamfile_modules: self.jamfile_modules[jamfile_module] = True # Initialize the jamfile module before loading. # self.initialize(jamfile_module, dir, os.path.basename(jamfile_to_load)) saved_project = self.current_project bjam.call("load", jamfile_module, jamfile_to_load) basename = os.path.basename(jamfile_to_load) if is_jamroot: jamfile = self.find_jamfile(dir, no_errors=True) if jamfile: bjam.call("load", jamfile_module, jamfile) # Now do some checks if self.current_project != saved_project: self.manager.errors()( """The value of the .current-project variable has magically changed after loading a Jamfile. This means some of the targets might be defined a the wrong project. after loading %s expected value %s actual value %s""" % (jamfile_module, saved_project, self.current_project)) if self.global_build_dir: id = self.attributeDefault(jamfile_module, "id", None) project_root = self.attribute(jamfile_module, "project-root") location = self.attribute(jamfile_module, "location") if location and project_root == dir: # This is Jamroot if not id: # FIXME: go via errors module, so that contexts are # shown? print "warning: the --build-dir option was specified" print "warning: but Jamroot at '%s'" % dir print "warning: specified no project id" print "warning: the --build-dir option will be ignored"