| # Status: being ported by Steven Watanabe |
| # Base revision: 47174 |
| # |
| # Copyright (C) Vladimir Prus 2002. Permission to copy, use, modify, sell and |
| # distribute this software is granted provided this copyright notice appears in |
| # all copies. This software is provided "as is" without express or implied |
| # warranty, and with no claim as to its suitability for any purpose. |
| |
| """ Provides actions common to all toolsets, such as creating directories and |
| removing files. |
| """ |
| |
| import re |
| import bjam |
| import os |
| import os.path |
| |
| from b2.build import feature |
| from b2.util.utility import * |
| from b2.util import path |
| |
| __re__before_first_dash = re.compile ('([^-]*)-') |
| |
| 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') |
| |
| reset() |
| |
| # ported from trunk@47174 |
| class Configurations(object): |
| """ |
| This class helps to manage toolset configurations. Each configuration |
| has a unique ID and one or more parameters. A typical example of a unique ID |
| is a condition generated by 'common.check-init-parameters' rule. Other kinds |
| of IDs can be used. Parameters may include any details about the configuration |
| like 'command', 'path', etc. |
| |
| A toolset configuration may be in one of the following states: |
| |
| - registered |
| Configuration has been registered (e.g. by autodetection code) but has |
| not yet been marked as used, i.e. 'toolset.using' rule has not yet been |
| called for it. |
| - used |
| Once called 'toolset.using' rule marks the configuration as 'used'. |
| |
| The main difference between the states above is that while a configuration is |
| 'registered' its options can be freely changed. This is useful in particular |
| for autodetection code - all detected configurations may be safely overwritten |
| by user code. |
| """ |
| |
| def __init__(self): |
| self.used_ = set() |
| self.all_ = set() |
| self.params = {} |
| |
| def register(self, id): |
| """ |
| Registers a configuration. |
| |
| Returns True if the configuration has been added and False if |
| it already exists. Reports an error if the configuration is 'used'. |
| """ |
| if id in self.used_: |
| #FIXME |
| errors.error("common: the configuration '$(id)' is in use") |
| |
| if id not in self.all_: |
| self.all_ += [id] |
| |
| # Indicate that a new configuration has been added. |
| return True |
| else: |
| return False |
| |
| def use(self, id): |
| """ |
| Mark a configuration as 'used'. |
| |
| Returns True if the state of the configuration has been changed to |
| 'used' and False if it the state wasn't changed. Reports an error |
| if the configuration isn't known. |
| """ |
| if id not in self.all_: |
| #FIXME: |
| errors.error("common: the configuration '$(id)' is not known") |
| |
| if id not in self.used_: |
| self.used_ += [id] |
| |
| # indicate that the configuration has been marked as 'used' |
| return True |
| else: |
| return False |
| |
| def all(self): |
| """ Return all registered configurations. """ |
| return self.all_ |
| |
| def used(self): |
| """ Return all used configurations. """ |
| return self.used_ |
| |
| def get(self, id, param): |
| """ Returns the value of a configuration parameter. """ |
| self.params_.getdefault(param, {}).getdefault(id, None) |
| |
| def set (self, id, param, value): |
| """ Sets the value of a configuration parameter. """ |
| self.params_.setdefault(param, {})[id] = value |
| |
| # Ported from trunk@47174 |
| def check_init_parameters(toolset, requirement, *args): |
| """ The rule for checking toolset parameters. Trailing parameters should all be |
| parameter name/value pairs. The rule will check that each parameter either has |
| a value in each invocation or has no value in each invocation. Also, the rule |
| will check that the combination of all parameter values is unique in all |
| invocations. |
| |
| Each parameter name corresponds to a subfeature. This rule will declare a |
| subfeature the first time a non-empty parameter value is passed and will |
| extend it with all the values. |
| |
| The return value from this rule is a condition to be used for flags settings. |
| """ |
| # The type checking here is my best guess about |
| # what the types should be. |
| assert(isinstance(toolset, str)) |
| assert(isinstance(requirement, str) or requirement is None) |
| sig = toolset |
| condition = replace_grist(toolset, '<toolset>') |
| subcondition = [] |
| |
| for arg in args: |
| assert(isinstance(arg, tuple)) |
| assert(len(arg) == 2) |
| name = arg[0] |
| value = arg[1] |
| assert(isinstance(name, str)) |
| assert(isinstance(value, str) or value is None) |
| |
| str_toolset_name = str((toolset, name)) |
| |
| # FIXME: is this the correct translation? |
| ### if $(value)-is-not-empty |
| if value is not None: |
| condition = condition + '-' + value |
| if __had_unspecified_value.has_key(str_toolset_name): |
| raise BaseException("'%s' initialization: parameter '%s' inconsistent\n" \ |
| "no value was specified in earlier initialization\n" \ |
| "an explicit value is specified now" % (toolset, name)) |
| |
| # The logic below is for intel compiler. It calls this rule |
| # with 'intel-linux' and 'intel-win' as toolset, so we need to |
| # get the base part of toolset name. |
| # We can't pass 'intel' as toolset, because it that case it will |
| # be impossible to register versionles intel-linux and |
| # intel-win of specific version. |
| t = toolset |
| m = __re__before_first_dash.match(toolset) |
| if m: |
| t = m.group(1) |
| |
| if not __had_value.has_key(str_toolset_name): |
| if not __declared_subfeature.has_key(str((t, name))): |
| feature.subfeature('toolset', t, name, [], ['propagated']) |
| __declared_subfeature[str((t, name))] = True |
| |
| __had_value[str_toolset_name] = True |
| |
| feature.extend_subfeature('toolset', t, name, [value]) |
| subcondition += ['<toolset-' + t + ':' + name + '>' + value ] |
| |
| else: |
| if __had_value.has_key(str_toolset_name): |
| raise BaseException ("'%s' initialization: parameter '%s' inconsistent\n" \ |
| "an explicit value was specified in an earlier initialization\n" \ |
| "no value is specified now" % (toolset, name)) |
| |
| __had_unspecified_value[str_toolset_name] = True |
| |
| if value == None: value = '' |
| |
| sig = sig + value + '-' |
| |
| if __all_signatures.has_key(sig): |
| message = "duplicate initialization of '%s' with the following parameters: " % toolset |
| |
| for arg in args: |
| name = arg[0] |
| value = arg[1] |
| if value == None: value = '<unspecified>' |
| |
| message += "'%s' = '%s'\n" % (name, value) |
| |
| raise BaseException(message) |
| |
| __all_signatures[sig] = True |
| # FIXME |
| __init_loc[sig] = "User location unknown" #[ errors.nearest-user-location ] ; |
| |
| # If we have a requirement, this version should only be applied under that |
| # condition. To accomplish this we add a toolset requirement that imposes |
| # the toolset subcondition, which encodes the version. |
| if requirement: |
| r = ['<toolset>' + toolset, requirement] |
| r = ','.join(r) |
| toolset.add_requirements([r + ':' + c for c in subcondition]) |
| |
| # We add the requirements, if any, to the condition to scope the toolset |
| # variables and options to this specific version. |
| condition = [condition] |
| if requirement: |
| condition += [requirement] |
| |
| if __show_configuration: |
| print "notice:", condition |
| return ['/'.join(condition)] |
| |
| # Ported from trunk@47077 |
| def get_invocation_command_nodefault( |
| toolset, tool, user_provided_command=[], additional_paths=[], path_last=False): |
| """ |
| A helper rule to get the command to invoke some tool. If |
| 'user-provided-command' is not given, tries to find binary named 'tool' in |
| PATH and in the passed 'additional-path'. Otherwise, verifies that the first |
| element of 'user-provided-command' is an existing program. |
| |
| This rule returns the command to be used when invoking the tool. If we can't |
| find the tool, a warning is issued. If 'path-last' is specified, PATH is |
| checked after 'additional-paths' when searching for 'tool'. |
| """ |
| assert(isinstance(toolset, str)) |
| assert(isinstance(tool, str)) |
| assert(isinstance(user_provided_command, list)) |
| if additional_paths is not None: |
| assert(isinstance(additional_paths, list)) |
| assert(all([isinstance(path, str) for path in additional_paths])) |
| assert(all(isinstance(path, str) for path in additional_paths)) |
| assert(isinstance(path_last, bool)) |
| |
| if not user_provided_command: |
| command = find_tool(tool, additional_paths, path_last) |
| if not command and __debug_configuration: |
| print "warning: toolset", toolset, "initialization: can't find tool, tool" |
| #FIXME |
| #print "warning: initialized from" [ errors.nearest-user-location ] ; |
| else: |
| command = check_tool(user_provided_command) |
| if not command and __debug_configuration: |
| print "warning: toolset", toolset, "initialization:" |
| print "warning: can't find user-provided command", user_provided_command |
| #FIXME |
| #ECHO "warning: initialized from" [ errors.nearest-user-location ] |
| |
| assert(isinstance(command, str)) |
| |
| return command |
| |
| # ported from trunk@47174 |
| def get_invocation_command(toolset, tool, user_provided_command = [], |
| additional_paths = [], path_last = False): |
| """ Same as get_invocation_command_nodefault, except that if no tool is found, |
| returns either the user-provided-command, if present, or the 'tool' parameter. |
| """ |
| |
| assert(isinstance(toolset, str)) |
| assert(isinstance(tool, str)) |
| assert(isinstance(user_provided_command, list)) |
| if additional_paths is not None: |
| assert(isinstance(additional_paths, list)) |
| assert(all([isinstance(path, str) for path in additional_paths])) |
| assert(isinstance(path_last, bool)) |
| |
| result = get_invocation_command_nodefault(toolset, tool, |
| user_provided_command, |
| additional_paths, |
| path_last) |
| |
| if not result: |
| if user_provided_command: |
| result = user_provided_command[0] |
| else: |
| result = tool |
| |
| assert(isinstance(result, str)) |
| |
| return result |
| |
| # ported from trunk@47281 |
| def get_absolute_tool_path(command): |
| """ |
| Given an invocation command, |
| return the absolute path to the command. This works even if commnad |
| has not path element and is present in PATH. |
| """ |
| if os.path.dirname(command): |
| return os.path.dirname(command) |
| else: |
| programs = path.programs_path() |
| m = path.glob(programs, [command, command + '.exe' ]) |
| if not len(m): |
| print "Could not find:", command, "in", programs |
| return os.path.dirname(m[0]) |
| |
| # ported from trunk@47174 |
| def find_tool(name, additional_paths = [], path_last = False): |
| """ Attempts to find tool (binary) named 'name' in PATH and in |
| 'additional-paths'. If found in path, returns 'name'. If |
| found in additional paths, returns full name. If the tool |
| is found in several directories, returns the first path found. |
| Otherwise, returns the empty string. If 'path_last' is specified, |
| path is checked after 'additional_paths'. |
| """ |
| assert(isinstance(name, str)) |
| assert(isinstance(additional_paths, list)) |
| assert(isinstance(path_last, bool)) |
| |
| programs = path.programs_path() |
| match = path.glob(programs, [name, name + '.exe']) |
| additional_match = path.glob(additional_paths, [name, name + '.exe']) |
| |
| result = [] |
| if path_last: |
| result = additional_match |
| if not result and match: |
| result = match |
| |
| else: |
| if match: |
| result = match |
| |
| elif additional_match: |
| result = additional_match |
| |
| if result: |
| return path.native(result[0]) |
| else: |
| return '' |
| |
| #ported from trunk@47281 |
| def check_tool_aux(command): |
| """ Checks if 'command' can be found either in path |
| or is a full name to an existing file. |
| """ |
| assert(isinstance(command, str)) |
| dirname = os.path.dirname(command) |
| if dirname: |
| if os.path.exists(command): |
| return command |
| # Both NT and Cygwin will run .exe files by their unqualified names. |
| elif on_windows() and os.path.exists(command + '.exe'): |
| return command |
| # Only NT will run .bat files by their unqualified names. |
| elif os_name() == 'NT' and os.path.exists(command + '.bat'): |
| return command |
| else: |
| paths = path.programs_path() |
| if path.glob(paths, [command]): |
| return command |
| |
| # ported from trunk@47281 |
| def check_tool(command): |
| """ Checks that a tool can be invoked by 'command'. |
| If command is not an absolute path, checks if it can be found in 'path'. |
| If comand is absolute path, check that it exists. Returns 'command' |
| if ok and empty string otherwise. |
| """ |
| assert(isinstance(command, list)) |
| assert(all(isinstance(c, str) for c in command)) |
| #FIXME: why do we check the first and last elements???? |
| if check_tool_aux(command[0]) or check_tool_aux(command[-1]): |
| return command |
| |
| # ported from trunk@47281 |
| def handle_options(tool, condition, command, options): |
| """ Handle common options for toolset, specifically sets the following |
| flag variables: |
| - CONFIG_COMMAND to 'command' |
| - OPTIOns for compile to the value of <compileflags> in options |
| - OPTIONS for compile.c to the value of <cflags> in options |
| - OPTIONS for compile.c++ to the value of <cxxflags> in options |
| - OPTIONS for compile.fortran to the value of <fflags> in options |
| - OPTIONs for link to the value of <linkflags> in options |
| """ |
| from b2.build import toolset |
| |
| assert(isinstance(tool, str)) |
| assert(isinstance(condition, list)) |
| assert(isinstance(command, str)) |
| assert(isinstance(options, list)) |
| assert(command) |
| toolset.flags(tool, 'CONFIG_COMMAND', condition, [command]) |
| toolset.flags(tool + '.compile', 'OPTIONS', condition, feature.get_values('<compileflags>', options)) |
| toolset.flags(tool + '.compile.c', 'OPTIONS', condition, feature.get_values('<cflags>', options)) |
| toolset.flags(tool + '.compile.c++', 'OPTIONS', condition, feature.get_values('<cxxflags>', options)) |
| toolset.flags(tool + '.compile.fortran', 'OPTIONS', condition, feature.get_values('<fflags>', options)) |
| toolset.flags(tool + '.link', 'OPTIONS', condition, feature.get_values('<linkflags>', options)) |
| |
| # ported from trunk@47281 |
| def get_program_files_dir(): |
| """ returns the location of the "program files" directory on a windows |
| platform |
| """ |
| ProgramFiles = bjam.variable("ProgramFiles") |
| if ProgramFiles: |
| ProgramFiles = ' '.join(ProgramFiles) |
| else: |
| ProgramFiles = "c:\\Program Files" |
| return ProgramFiles |
| |
| # ported from trunk@47281 |
| def rm_command(): |
| return __RM |
| |
| # ported from trunk@47281 |
| def copy_command(): |
| return __CP |
| |
| # ported from trunk@47281 |
| def variable_setting_command(variable, value): |
| """ |
| Returns the command needed to set an environment variable on the current |
| platform. The variable setting persists through all following commands and is |
| visible in the environment seen by subsequently executed commands. In other |
| words, on Unix systems, the variable is exported, which is consistent with the |
| only possible behavior on Windows systems. |
| """ |
| assert(isinstance(variable, str)) |
| assert(isinstance(value, str)) |
| |
| if os_name() == 'NT': |
| return "set " + variable + "=" + value + os.linesep |
| else: |
| # (todo) |
| # The following does not work on CYGWIN and needs to be fixed. On |
| # CYGWIN the $(nl) variable holds a Windows new-line \r\n sequence that |
| # messes up the executed export command which then reports that the |
| # passed variable name is incorrect. This is most likely due to the |
| # extra \r character getting interpreted as a part of the variable name. |
| # |
| # Several ideas pop to mind on how to fix this: |
| # * One way would be to separate the commands using the ; shell |
| # command separator. This seems like the quickest possible |
| # solution but I do not know whether this would break code on any |
| # platforms I I have no access to. |
| # * Another would be to not use the terminating $(nl) but that would |
| # require updating all the using code so it does not simply |
| # prepend this variable to its own commands. |
| # * I guess the cleanest solution would be to update Boost Jam to |
| # allow explicitly specifying \n & \r characters in its scripts |
| # instead of always relying only on the 'current OS native newline |
| # sequence'. |
| # |
| # Some code found to depend on this behaviour: |
| # * This Boost Build module. |
| # * __test__ rule. |
| # * path-variable-setting-command rule. |
| # * python.jam toolset. |
| # * xsltproc.jam toolset. |
| # * fop.jam toolset. |
| # (todo) (07.07.2008.) (Jurko) |
| # |
| # I think that this works correctly in python -- Steven Watanabe |
| return variable + "=" + value + os.linesep + "export " + variable + os.linesep |
| |
| def path_variable_setting_command(variable, paths): |
| """ |
| Returns a command to sets a named shell path variable to the given NATIVE |
| paths on the current platform. |
| """ |
| assert(isinstance(variable, str)) |
| assert(isinstance(paths, list)) |
| sep = os.path.pathsep |
| return variable_setting_command(variable, sep.join(paths)) |
| |
| def prepend_path_variable_command(variable, paths): |
| """ |
| Returns a command that prepends the given paths to the named path variable on |
| the current platform. |
| """ |
| return path_variable_setting_command(variable, |
| paths + os.environ(variable).split(os.pathsep)) |
| |
| def file_creation_command(): |
| """ |
| Return a command which can create a file. If 'r' is result of invocation, then |
| 'r foobar' will create foobar with unspecified content. What happens if file |
| already exists is unspecified. |
| """ |
| if os_name() == 'NT': |
| return "echo. > " |
| else: |
| return "touch " |
| |
| #FIXME: global variable |
| __mkdir_set = set() |
| __re_windows_drive = re.compile(r'^.*:\$') |
| |
| def mkdir(engine, target): |
| # 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. |
| if os_name() == 'NT': |
| engine.set_update_action("common.MkDir1-quick-fix-for-windows", target, [], None) |
| else: |
| engine.set_update_action("common.MkDir1-quick-fix-for-unix", target, [], None) |
| |
| # 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) |
| |
| __re_version = re.compile(r'^([^.]+)[.]([^.]+)[.]?([^.]*)') |
| |
| def format_name(format, name, target_type, prop_set): |
| """ Given a target, as given to a custom tag rule, returns a string formatted |
| according to the passed format. Format is a list of properties that is |
| represented in the result. For each element of format the corresponding target |
| information is obtained and added to the result string. For all, but the |
| literal, the format value is taken as the as string to prepend to the output |
| to join the item to the rest of the result. If not given "-" is used as a |
| joiner. |
| |
| The format options can be: |
| |
| <base>[joiner] |
| :: The basename of the target name. |
| <toolset>[joiner] |
| :: The abbreviated toolset tag being used to build the target. |
| <threading>[joiner] |
| :: Indication of a multi-threaded build. |
| <runtime>[joiner] |
| :: Collective tag of the build runtime. |
| <version:/version-feature | X.Y[.Z]/>[joiner] |
| :: Short version tag taken from the given "version-feature" |
| in the build properties. Or if not present, the literal |
| value as the version number. |
| <property:/property-name/>[joiner] |
| :: Direct lookup of the given property-name value in the |
| build properties. /property-name/ is a regular expression. |
| e.g. <property:toolset-.*:flavor> will match every toolset. |
| /otherwise/ |
| :: The literal value of the format argument. |
| |
| For example this format: |
| |
| boost_ <base> <toolset> <threading> <runtime> <version:boost-version> |
| |
| Might return: |
| |
| boost_thread-vc80-mt-gd-1_33.dll, or |
| boost_regex-vc80-gd-1_33.dll |
| |
| The returned name also has the target type specific prefix and suffix which |
| puts it in a ready form to use as the value from a custom tag rule. |
| """ |
| assert(isinstance(format, list)) |
| assert(isinstance(name, str)) |
| assert(isinstance(target_type, str) or not type) |
| # assert(isinstance(prop_set, property_set.PropertySet)) |
| if type.is_derived(target_type, 'LIB'): |
| result = "" ; |
| for f in format: |
| grist = get_grist(f) |
| if grist == '<base>': |
| result += os.path.basename(name) |
| elif grist == '<toolset>': |
| result += join_tag(ungrist(f), |
| toolset_tag(name, target_type, prop_set)) |
| elif grist == '<threading>': |
| result += join_tag(ungrist(f), |
| threading_tag(name, target_type, prop_set)) |
| elif grist == '<runtime>': |
| result += join_tag(ungrist(f), |
| runtime_tag(name, target_type, prop_set)) |
| elif grist.startswith('<version:'): |
| key = grist[len('<version:'):-1] |
| version = prop_set.get('<' + key + '>') |
| if not version: |
| version = key |
| version = __re_version.match(version) |
| result += join_tag(ungrist(f), version[1] + '_' + version[2]) |
| elif grist.startswith('<property:'): |
| key = grist[len('<property:'):-1] |
| property_re = re.compile('<(' + key + ')>') |
| p0 = None |
| for prop in prop_set.raw(): |
| match = property_re.match(prop) |
| if match: |
| p0 = match[1] |
| break |
| if p0: |
| p = prop_set.get('<' + p0 + '>') |
| if p: |
| assert(len(p) == 1) |
| result += join_tag(ungrist(f), p) |
| else: |
| result += ungrist(f) |
| |
| result = virtual_target.add_prefix_and_suffix( |
| ''.join(result), target_type, prop_set) |
| return result |
| |
| def join_tag(joiner, tag): |
| if not joiner: joiner = '-' |
| return joiner + tag |
| |
| __re_toolset_version = re.compile(r"<toolset.*version>(\d+)[.](\d*)") |
| |
| def toolset_tag(name, target_type, prop_set): |
| tag = '' |
| |
| properties = prop_set.raw() |
| tools = prop_set.get('<toolset>') |
| assert(len(tools) == 0) |
| tools = tools[0] |
| if tools.startswith('borland'): tag += 'bcb' |
| elif tools.startswith('como'): tag += 'como' |
| elif tools.startswith('cw'): tag += 'cw' |
| elif tools.startswith('darwin'): tag += 'xgcc' |
| elif tools.startswith('edg'): tag += edg |
| elif tools.startswith('gcc'): |
| flavor = prop_set.get('<toolset-gcc:flavor>') |
| ''.find |
| if flavor.find('mingw') != -1: |
| tag += 'mgw' |
| else: |
| tag += 'gcc' |
| elif tools == 'intel': |
| if prop_set.get('<toolset-intel:platform>') == ['win']: |
| tag += 'iw' |
| else: |
| tag += 'il' |
| elif tools.startswith('kcc'): tag += 'kcc' |
| elif tools.startswith('kylix'): tag += 'bck' |
| #case metrowerks* : tag += cw ; |
| #case mingw* : tag += mgw ; |
| elif tools.startswith('mipspro'): tag += 'mp' |
| elif tools.startswith('msvc'): tag += 'vc' |
| elif tools.startswith('sun'): tag += 'sw' |
| elif tools.startswith('tru64cxx'): tag += 'tru' |
| elif tools.startswith('vacpp'): tag += 'xlc' |
| |
| for prop in properties: |
| match = __re_toolset_version.match(prop) |
| if(match): |
| version = match |
| break |
| version_string = None |
| # For historical reasons, vc6.0 and vc7.0 use different naming. |
| if tag == 'vc': |
| if version.group(1) == '6': |
| # Cancel minor version. |
| version_string = '6' |
| elif version.group(1) == '7' and version.group(2) == '0': |
| version_string = '7' |
| |
| # On intel, version is not added, because it does not matter and it's the |
| # version of vc used as backend that matters. Ideally, we'd encode the |
| # backend version but that would break compatibility with V1. |
| elif tag == 'iw': |
| version_string = '' |
| |
| # On borland, version is not added for compatibility with V1. |
| elif tag == 'bcb': |
| version_string = '' |
| |
| if version_string is None: |
| version = version.group(1) + version.group(2) |
| |
| tag += version |
| |
| return tag |
| |
| |
| def threading_tag(name, target_type, prop_set): |
| tag = '' |
| properties = prop_set.raw() |
| if '<threading>multi' in properties: tag = 'mt' |
| |
| return tag |
| |
| |
| def runtime_tag(name, target_type, prop_set ): |
| tag = '' |
| |
| properties = prop_set.raw() |
| if '<runtime-link>static' in properties: tag += 's' |
| |
| # This is an ugly thing. In V1, there's a code to automatically detect which |
| # properties affect a target. So, if <runtime-debugging> does not affect gcc |
| # toolset, the tag rules won't even see <runtime-debugging>. Similar |
| # functionality in V2 is not implemented yet, so we just check for toolsets |
| # which are known to care about runtime debug. |
| if '<toolset>msvc' in properties \ |
| or '<stdlib>stlport' in properties \ |
| or '<toolset-intel:platform>win' in properties: |
| if '<runtime-debugging>on' in properties: tag += 'g' |
| |
| if '<python-debugging>on' in properties: tag += 'y' |
| if '<variant>debug' in properties: tag += 'd' |
| if '<stdlib>stlport' in properties: tag += 'p' |
| if '<stdlib-stlport:iostream>hostios' in properties: tag += 'n' |
| |
| return tag |
| |
| |
| ## TODO: |
| ##rule __test__ ( ) |
| ##{ |
| ## import assert ; |
| ## |
| ## local nl = " |
| ##" ; |
| ## |
| ## local save-os = [ modules.peek os : .name ] ; |
| ## |
| ## modules.poke os : .name : LINUX ; |
| ## |
| ## assert.result "PATH=foo:bar:baz$(nl)export PATH$(nl)" |
| ## : path-variable-setting-command PATH : foo bar baz ; |
| ## |
| ## assert.result "PATH=foo:bar:$PATH$(nl)export PATH$(nl)" |
| ## : prepend-path-variable-command PATH : foo bar ; |
| ## |
| ## modules.poke os : .name : NT ; |
| ## |
| ## assert.result "set PATH=foo;bar;baz$(nl)" |
| ## : path-variable-setting-command PATH : foo bar baz ; |
| ## |
| ## assert.result "set PATH=foo;bar;%PATH%$(nl)" |
| ## : prepend-path-variable-command PATH : foo bar ; |
| ## |
| ## modules.poke os : .name : $(save-os) ; |
| ##} |
| |
| def init(manager): |
| engine = manager.engine() |
| |
| engine.register_action("common.MkDir1-quick-fix-for-unix", 'mkdir -p "$(<)"') |
| engine.register_action("common.MkDir1-quick-fix-for-windows", 'if not exist "$(<)\\" mkdir "$(<)"') |
| |
| import b2.tools.make |
| import b2.build.alias |
| |
| global __RM, __CP, __IGNORE, __LN |
| # ported from trunk@47281 |
| if os_name() == 'NT': |
| __RM = 'del /f /q' |
| __CP = 'copy' |
| __IGNORE = '2>nul >nul & setlocal' |
| __LN = __CP |
| #if not __LN: |
| # __LN = CP |
| else: |
| __RM = 'rm -f' |
| __CP = 'cp' |
| __IGNORE = '' |
| __LN = 'ln' |
| |
| engine.register_action("common.Clean", __RM + ' "$(>)"', |
| flags=['piecemeal', 'together', 'existing']) |
| engine.register_action("common.copy", __CP + ' "$(>)" "$(<)"') |
| engine.register_action("common.RmTemps", __RM + ' "$(>)" ' + __IGNORE, |
| flags=['quietly', 'updated', 'piecemeal', 'together']) |
| |
| engine.register_action("common.hard-link", |
| __RM + ' "$(<)" 2$(NULL_OUT) $(NULL_OUT)' + os.linesep + |
| __LN + ' "$(>)" "$(<)" $(NULL_OUT)') |