diff options
Diffstat (limited to 'src/engine/SCons/Tool')
239 files changed, 4484 insertions, 2154 deletions
diff --git a/src/engine/SCons/Tool/386asm.py b/src/engine/SCons/Tool/386asm.py index b318c4b..1121c3d 100644 --- a/src/engine/SCons/Tool/386asm.py +++ b/src/engine/SCons/Tool/386asm.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/386asm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/386asm.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from SCons.Tool.PharLapCommon import addPharLapPaths import SCons.Util diff --git a/src/engine/SCons/Tool/386asm.xml b/src/engine/SCons/Tool/386asm.xml index 80a2cd6..fe819d2 100644 --- a/src/engine/SCons/Tool/386asm.xml +++ b/src/engine/SCons/Tool/386asm.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/DCommon.py b/src/engine/SCons/Tool/DCommon.py index 8973853..f6b6000 100644 --- a/src/engine/SCons/Tool/DCommon.py +++ b/src/engine/SCons/Tool/DCommon.py @@ -9,7 +9,7 @@ Coded by Russel Winder (russel@winder.org.uk) """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ Coded by Russel Winder (russel@winder.org.uk) # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/DCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/DCommon.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path diff --git a/src/engine/SCons/Tool/DCommon.xml b/src/engine/SCons/Tool/DCommon.xml index b1deb82..5103ca1 100644 --- a/src/engine/SCons/Tool/DCommon.xml +++ b/src/engine/SCons/Tool/DCommon.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/FortranCommon.py b/src/engine/SCons/Tool/FortranCommon.py index d2126a4..11f1eb7 100644 --- a/src/engine/SCons/Tool/FortranCommon.py +++ b/src/engine/SCons/Tool/FortranCommon.py @@ -5,7 +5,7 @@ Stuff for processing Fortran, common to all fortran dialects. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Stuff for processing Fortran, common to all fortran dialects. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/FortranCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/FortranCommon.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import re import os.path @@ -64,7 +64,8 @@ def _fortranEmitter(target, source, env): if not node.exists() and not node.is_derived(): print("Could not locate " + str(node.name)) return ([], []) - mod_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)""" + # This has to match the def_regex in the Fortran scanner + mod_regex = r"""(?i)^\s*MODULE\s+(?!PROCEDURE|SUBROUTINE|FUNCTION|PURE|ELEMENTAL)(\w+)""" cre = re.compile(mod_regex,re.M) # Retrieve all USE'd module names modules = cre.findall(node.get_text_contents()) diff --git a/src/engine/SCons/Tool/FortranCommonTests.py b/src/engine/SCons/Tool/FortranCommonTests.py new file mode 100644 index 0000000..9cca9b0 --- /dev/null +++ b/src/engine/SCons/Tool/FortranCommonTests.py @@ -0,0 +1,125 @@ +# +# Copyright (c) 2001 - 2019 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# from typing import Dict, Any + +__revision__ = "src/engine/SCons/Tool/FortranCommonTests.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" + +import os +import os.path +import unittest + +import SCons.Node.FS +import SCons.Warnings +import SCons.Tool.FortranCommon + +import TestCmd + +original = os.getcwd() + +test = TestCmd.TestCmd(workdir='') + +os.chdir(test.workpath('')) + + +class DummyEnvironment(object): + dictionary = None # type: Dict[Any, Any] + + def __init__(self, list_cpp_path): + self.path = list_cpp_path + self.fs = SCons.Node.FS.FS(test.workpath('')) + self.dictionary = {} + + def has_key(self, key): + return key in self.dictionary + + def __getitem__(self, key): + return self.dictionary[key] + + def __setitem__(self, key, value): + self.dictionary[key] = value + + def __delitem__(self, key): + del self.dictionary[key] + + def subst(self, arg, target=None, source=None, conv=None): + if arg[0] == '$': + return self[arg[1:]] + return arg + + def subst_path(self, path, target=None, source=None, conv=None): + if not isinstance(path, list): + path = [path] + return list(map(self.subst, path)) + + def get_calculator(self): + return None + + def get_factory(self, factory): + return factory or self.fs.File + + def Dir(self, filename): + return self.fs.Dir(filename) + + def File(self, filename): + return self.fs.File(filename) + + +class FortranScannerSubmodulesTestCase(unittest.TestCase): + def runTest(self): + """ + Check that test_1.f90 and test_2.f90 which have interface specifications + Don't generate targets for those modules listed in the interface section + """ + + test.dir_fixture('fortran_unittests') + env = DummyEnvironment([test.workpath('modules')]) + env['FORTRANMODDIR'] = 'modules' + env['FORTRANMODSUFFIX'] = '.mod' + emitter = SCons.Tool.FortranCommon._fortranEmitter + # path = s.path(env) + + for fort in ['test_1.f90', 'test_2.f90']: + file_base, _ = os.path.splitext(fort) + file_mod = '%s.mod' % file_base + f = env.File(fort) + (target, source) = emitter([], [f, ], env) + + # print("Targets:%s\nSources:%s"%([str(a) for a in target], [str(a) for a in source])) + + # should only be 1 target and 1 source + self.assertEqual(len(target), 1, + msg="More than 1 target: %d [%s]" % (len(target), [str(t) for t in target])) + self.assertEqual(len(source), 1, + msg="More than 1 source: %d [%s]" % (len(source), [str(t) for t in source])) + + # target should be file_base.mod + self.assertEqual(str(target[0]).endswith(file_mod), True, + msg="Target[0]=%s doesn't end with '%s'" % (str(target[0]), file_mod)) + + # source should be file_base .f90 + self.assertEqual(str(source[0]).endswith(fort), True, + msg="Source[0]=%s doesn't end with '%s'" % (str(source[0]), fort)) + + +if __name__ == "__main__": + unittest.main() diff --git a/src/engine/SCons/Tool/GettextCommon.py b/src/engine/SCons/Tool/GettextCommon.py index b475d8f..79912b6 100644 --- a/src/engine/SCons/Tool/GettextCommon.py +++ b/src/engine/SCons/Tool/GettextCommon.py @@ -3,8 +3,8 @@ Used by several tools of `gettext` toolset. """ -# Copyright (c) 2001 - 2017 The SCons Foundation -# +# Copyright (c) 2001 - 2019 The SCons Foundation +# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -12,10 +12,10 @@ Used by several tools of `gettext` toolset. # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: -# +# # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. -# +# # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND @@ -24,7 +24,7 @@ Used by several tools of `gettext` toolset. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/GettextCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/GettextCommon.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Warnings import re @@ -71,7 +71,7 @@ SCons.Warnings.enableWarningClass(MsgfmtNotFound) ############################################################################# class _POTargetFactory(object): """ A factory of `PO` target files. - + Factory defaults differ from these of `SCons.Node.FS.FS`. We set `precious` (this is required by builders and actions gettext) and `noclean` flags by default for all produced nodes. @@ -80,9 +80,9 @@ class _POTargetFactory(object): def __init__(self, env, nodefault=True, alias=None, precious=True , noclean=True): """ Object constructor. - + **Arguments** - + - *env* (`SCons.Environment.Environment`) - *nodefault* (`boolean`) - if `True`, produced nodes will be ignored from default target `'.'` @@ -160,13 +160,13 @@ from SCons.Builder import BuilderBase ############################################################################# class _POFileBuilder(BuilderBase): """ `PO` file builder. - + This is multi-target single-source builder. In typical situation the source is single `POT` file, e.g. `messages.pot`, and there are multiple `PO` targets to be updated from this `POT`. We must run `SCons.Builder.BuilderBase._execute()` separatelly for each target to track dependencies separatelly for each target file. - + **NOTE**: if we call `SCons.Builder.BuilderBase._execute(.., target, ...)` with target being list of all targets, all targets would be rebuilt each time one of the targets from this list is missing. This would happen, for example, @@ -198,29 +198,29 @@ class _POFileBuilder(BuilderBase): # After that it calls emitter (which is quite too late). The emitter is # also called in each iteration, what makes things yet worse. def __init__(self, env, **kw): - if not 'suffix' in kw: + if 'suffix' not in kw: kw['suffix'] = '$POSUFFIX' - if not 'src_suffix' in kw: + if 'src_suffix' not in kw: kw['src_suffix'] = '$POTSUFFIX' - if not 'src_builder' in kw: + if 'src_builder' not in kw: kw['src_builder'] = '_POTUpdateBuilder' - if not 'single_source' in kw: + if 'single_source' not in kw: kw['single_source'] = True alias = None if 'target_alias' in kw: alias = kw['target_alias'] del kw['target_alias'] - if not 'target_factory' in kw: + if 'target_factory' not in kw: kw['target_factory'] = _POTargetFactory(env, alias=alias).File BuilderBase.__init__(self, **kw) def _execute(self, env, target, source, *args, **kw): """ Execute builder's actions. - - Here we append to `target` the languages read from `$LINGUAS_FILE` and + + Here we append to `target` the languages read from `$LINGUAS_FILE` and apply `SCons.Builder.BuilderBase._execute()` separatelly to each target. The arguments and return value are same as for - `SCons.Builder.BuilderBase._execute()`. + `SCons.Builder.BuilderBase._execute()`. """ import SCons.Util import SCons.Node @@ -272,7 +272,7 @@ def _translate(env, target=None, source=SCons.Environment._null, *args, **kw): class RPaths(object): """ Callable object, which returns pathnames relative to SCons current working directory. - + It seems like `SCons.Node.FS.Base.get_path()` returns absolute paths for nodes that are outside of current working directory (`env.fs.getcwd()`). Here, we often have `SConscript`, `POT` and `PO` files within `po/` @@ -285,17 +285,17 @@ class RPaths(object): the references would be correct only on the machine, where `POT` file was recently re-created. For such reason, we need a function, which always returns relative paths. This is the purpose of `RPaths` callable object. - + The `__call__` method returns paths relative to current working directory, but we assume, that *xgettext(1)* is run from the directory, where target file is going to be created. - + Note, that this may not work for files distributed over several hosts or across different drives on windows. We assume here, that single local filesystem holds both source files and target `POT` templates. - + Intended use of `RPaths` - in `xgettext.py`:: - + def generate(env): from GettextCommon import RPaths ... @@ -318,9 +318,9 @@ class RPaths(object): def __init__(self, env): """ Initialize `RPaths` callable object. - + **Arguments**: - + - *env* - a `SCons.Environment.Environment` object, defines *current working dir*. """ @@ -329,16 +329,16 @@ class RPaths(object): # FIXME: I'm not sure, how it should be implemented (what the *args are in # general, what is **kw). def __call__(self, nodes, *args, **kw): - """ Return nodes' paths (strings) relative to current working directory. - + """ Return nodes' paths (strings) relative to current working directory. + **Arguments**: - + - *nodes* ([`SCons.Node.FS.Base`]) - list of nodes. - *args* - currently unused. - *kw* - currently unused. - + **Returns**: - + - Tuple of strings, which represent paths relative to current working directory (for given environment). """ @@ -390,7 +390,7 @@ def _detect_xgettext(env): """ Detects *xgettext(1)* binary """ if 'XGETTEXT' in env: return env['XGETTEXT'] - xgettext = env.Detect('xgettext'); + xgettext = env.Detect('xgettext') if xgettext: return xgettext raise SCons.Errors.StopError(XgettextNotFound, "Could not detect xgettext") @@ -409,7 +409,7 @@ def _detect_msginit(env): """ Detects *msginit(1)* program. """ if 'MSGINIT' in env: return env['MSGINIT'] - msginit = env.Detect('msginit'); + msginit = env.Detect('msginit') if msginit: return msginit raise SCons.Errors.StopError(MsginitNotFound, "Could not detect msginit") @@ -428,7 +428,7 @@ def _detect_msgmerge(env): """ Detects *msgmerge(1)* program. """ if 'MSGMERGE' in env: return env['MSGMERGE'] - msgmerge = env.Detect('msgmerge'); + msgmerge = env.Detect('msgmerge') if msgmerge: return msgmerge raise SCons.Errors.StopError(MsgmergeNotFound, "Could not detect msgmerge") @@ -447,7 +447,7 @@ def _detect_msgfmt(env): """ Detects *msgmfmt(1)* program. """ if 'MSGFMT' in env: return env['MSGFMT'] - msgfmt = env.Detect('msgfmt'); + msgfmt = env.Detect('msgfmt') if msgfmt: return msgfmt raise SCons.Errors.StopError(MsgfmtNotFound, "Could not detect msgfmt") diff --git a/src/engine/SCons/Tool/JavaCommon.py b/src/engine/SCons/Tool/JavaCommon.py index 5c2507d..1e58af6 100644 --- a/src/engine/SCons/Tool/JavaCommon.py +++ b/src/engine/SCons/Tool/JavaCommon.py @@ -5,7 +5,7 @@ Stuff for processing Java. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,16 +27,48 @@ Stuff for processing Java. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/JavaCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/JavaCommon.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import os.path import re +import glob java_parsing = 1 default_java_version = '1.4' +# a switch for which jdk versions to use the Scope state for smarter +# anonymous inner class parsing. +scopeStateVersions = ('1.8') + +# Glob patterns for use in finding where the JDK is. +# These are pairs, *dir_glob used in the general case, +# *version_dir_glob if matching only a specific version. +# For now only used for Windows. +java_win32_dir_glob = 'C:/Program Files*/Java/jdk*/bin' +# On windows, since Java 9, there is a dash between 'jdk' and the version +# string that wasn't there before. this glob should catch either way. +java_win32_version_dir_glob = 'C:/Program Files*/Java/jdk*%s*/bin' + +# Glob patterns for use in finding where the JDK headers are. +# These are pairs, *dir_glob used in the general case, +# *version_dir_glob if matching only a specific version. +java_macos_include_dir_glob = '/System/Library/Frameworks/JavaVM.framework/Headers/' +java_macos_version_include_dir_glob = '/System/Library/Frameworks/JavaVM.framework/Versions/%s*/Headers/' + +java_linux_include_dirs_glob = [ + '/usr/lib/jvm/default-java/include', + '/usr/lib/jvm/java-*/include' +] +# Need to match path like below (from Centos 7) +# /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/include/ +java_linux_version_include_dirs_glob = [ + '/usr/lib/jvm/java-*-sun-%s*/include', + '/usr/lib/jvm/java-%s*-openjdk*/include', + '/usr/java/jdk%s*/include' +] + if java_parsing: # Parse Java files for class names. # @@ -59,13 +91,15 @@ if java_parsing: r'\d*\.\d*|[A-Za-z_][\w\$\.]*|<[A-Za-z_]\w+>|' + r'/\*|\*/|\[\])') + class OuterState(object): """The initial state for parsing a Java file for classes, interfaces, and anonymous inner classes.""" + def __init__(self, version=default_java_version): - if not version in ('1.1', '1.2', '1.3','1.4', '1.5', '1.6', '1.7', - '1.8', '5', '6'): + if version not in ('1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', + '1.8', '5', '6', '9.0', '10.0', '11.0', '12.0'): msg = "Java version %s not supported" % version raise NotImplementedError(msg) @@ -115,8 +149,8 @@ if java_parsing: ret = SkipState(1, self) self.skipState = ret return ret - - def __getAnonStack(self): + + def _getAnonStack(self): return self.anonStacksStack[-1] def openBracket(self): @@ -125,15 +159,16 @@ if java_parsing: def closeBracket(self): self.brackets = self.brackets - 1 if len(self.stackBrackets) and \ - self.brackets == self.stackBrackets[-1]: + self.brackets == self.stackBrackets[-1]: self.listOutputs.append('$'.join(self.listClasses)) self.localClasses.pop() self.listClasses.pop() self.anonStacksStack.pop() self.stackBrackets.pop() if len(self.stackAnonClassBrackets) and \ - self.brackets == self.stackAnonClassBrackets[-1]: - self.__getAnonStack().pop() + self.brackets == self.stackAnonClassBrackets[-1] and \ + self.version not in scopeStateVersions: + self._getAnonStack().pop() self.stackAnonClassBrackets.pop() def parseToken(self, token): @@ -145,13 +180,13 @@ if java_parsing: self.openBracket() elif token == '}': self.closeBracket() - elif token in [ '"', "'" ]: + elif token in ['"', "'"]: return IgnoreState(token, self) elif token == "new": # anonymous inner class if len(self.listClasses) > 0: return self.__getAnonClassState() - return self.__getSkipState() # Skip the class name + return self.__getSkipState() # Skip the class name elif token in ['class', 'interface', 'enum']: if len(self.listClasses) == 0: self.nextAnon = 1 @@ -171,28 +206,99 @@ if java_parsing: if self.version in ('1.1', '1.2', '1.3', '1.4'): clazz = self.listClasses[0] self.listOutputs.append('%s$%d' % (clazz, self.nextAnon)) - elif self.version in ('1.5', '1.6', '1.7', '1.8', '5', '6'): + elif self.version in ('1.5', '1.6', '1.7', '1.8', '5', '6', '9.0', '10.0', '11.0', '12.0'): self.stackAnonClassBrackets.append(self.brackets) className = [] className.extend(self.listClasses) - self.__getAnonStack()[-1] = self.__getAnonStack()[-1] + 1 - for anon in self.__getAnonStack(): + self._getAnonStack()[-1] = self._getAnonStack()[-1] + 1 + for anon in self._getAnonStack(): className.append(str(anon)) self.listOutputs.append('$'.join(className)) self.nextAnon = self.nextAnon + 1 - self.__getAnonStack().append(0) + self._getAnonStack().append(0) def setPackage(self, package): self.package = package + + class ScopeState(object): + """ + A state that parses code within a scope normally, + within the confines of a scope. + """ + + def __init__(self, old_state): + self.outer_state = old_state.outer_state + self.old_state = old_state + self.brackets = 0 + + def __getClassState(self): + try: + return self.classState + except AttributeError: + ret = ClassState(self) + self.classState = ret + return ret + + def __getAnonClassState(self): + try: + return self.anonState + except AttributeError: + ret = SkipState(1, AnonClassState(self)) + self.anonState = ret + return ret + + def __getSkipState(self): + try: + return self.skipState + except AttributeError: + ret = SkipState(1, self) + self.skipState = ret + return ret + + def openBracket(self): + self.brackets = self.brackets + 1 + + def closeBracket(self): + self.brackets = self.brackets - 1 + + def parseToken(self, token): + # if self.brackets == 0: + # return self.old_state.parseToken(token) + if token[:2] == '//': + return IgnoreState('\n', self) + elif token == '/*': + return IgnoreState('*/', self) + elif token == '{': + self.openBracket() + elif token == '}': + self.closeBracket() + if self.brackets == 0: + self.outer_state._getAnonStack().pop() + return self.old_state + elif token in ['"', "'"]: + return IgnoreState(token, self) + elif token == "new": + # anonymous inner class + return self.__getAnonClassState() + elif token == '.': + # Skip the attribute, it might be named "class", in which + # case we don't want to treat the following token as + # an inner class name... + return self.__getSkipState() + return self + + class AnonClassState(object): """A state that looks for anonymous inner classes.""" + def __init__(self, old_state): # outer_state is always an instance of OuterState self.outer_state = old_state.outer_state self.old_state = old_state self.brace_level = 0 + def parseToken(self, token): # This is an anonymous class if and only if the next # non-whitespace token is a bracket. Everything between @@ -212,32 +318,40 @@ if java_parsing: if token == 'new': # look further for anonymous inner class return SkipState(1, AnonClassState(self)) - elif token in [ '"', "'" ]: + elif token in ['"', "'"]: return IgnoreState(token, self) elif token == ')': self.brace_level = self.brace_level - 1 return self if token == '{': self.outer_state.addAnonClass() + if self.outer_state.version in scopeStateVersions: + return ScopeState(old_state=self.old_state).parseToken(token) return self.old_state.parseToken(token) + class SkipState(object): """A state that will skip a specified number of tokens before reverting to the previous state.""" + def __init__(self, tokens_to_skip, old_state): self.tokens_to_skip = tokens_to_skip self.old_state = old_state + def parseToken(self, token): self.tokens_to_skip = self.tokens_to_skip - 1 if self.tokens_to_skip < 1: return self.old_state return self + class ClassState(object): """A state we go into when we hit a class or interface keyword.""" + def __init__(self, outer_state): # outer_state is always an instance of OuterState self.outer_state = outer_state + def parseToken(self, token): # the next non-whitespace token should be the name of the class if token == '\n': @@ -245,14 +359,14 @@ if java_parsing: # If that's an inner class which is declared in a method, it # requires an index prepended to the class-name, e.g. # 'Foo$1Inner' - # http://scons.tigris.org/issues/show_bug.cgi?id=2087 + # https://github.com/SCons/scons/issues/2087 if self.outer_state.localClasses and \ - self.outer_state.stackBrackets[-1] > \ - self.outer_state.stackBrackets[-2]+1: + self.outer_state.stackBrackets[-1] > \ + self.outer_state.stackBrackets[-2] + 1: locals = self.outer_state.localClasses[-1] try: idx = locals[token] - locals[token] = locals[token]+1 + locals[token] = locals[token] + 1 except KeyError: locals[token] = 1 token = str(locals[token]) + token @@ -261,29 +375,39 @@ if java_parsing: self.outer_state.anonStacksStack.append([0]) return self.outer_state + class IgnoreState(object): """A state that will ignore all tokens until it gets to a specified token.""" + def __init__(self, ignore_until, old_state): self.ignore_until = ignore_until self.old_state = old_state + def parseToken(self, token): if self.ignore_until == token: return self.old_state return self + class PackageState(object): """The state we enter when we encounter the package keyword. We assume the next token will be the package name.""" + def __init__(self, outer_state): # outer_state is always an instance of OuterState self.outer_state = outer_state + def parseToken(self, token): self.outer_state.setPackage(token) return self.outer_state + def parse_java_file(fn, version=default_java_version): - return parse_java(open(fn, 'r').read(), version) + with open(fn, 'r') as f: + data = f.read() + return parse_java(data, version) + def parse_java(contents, version=default_java_version, trace=None): """Parse a .java file and return a double of package directory, @@ -315,7 +439,71 @@ else: is that the file name matches the public class name, and that the path to the file is the same as the package name. """ - return os.path.split(file) + return os.path.split(fn) + + +def get_java_install_dirs(platform, version=None): + """ + Find the java jdk installation directories. + + This list is intended to supply as "default paths" for use when looking + up actual java binaries. + + :param platform: selector for search algorithm. + :param version: If specified, only look for java sdk's of this version + :return: list of default paths for java. + """ + + paths = [] + if platform == 'win32': + if version: + paths = glob.glob(java_win32_version_dir_glob % version) + else: + paths = glob.glob(java_win32_dir_glob) + else: + # other platforms, do nothing for now + pass + + return sorted(paths) + + +def get_java_include_paths(env, javac, version): + """ + Find java include paths for JNI building. + + :param env: construction environment, used to extract platform. + :param javac: path to detected javac. + :return: list of paths. + """ + + paths = [] + if not javac: + # there are no paths if we've not detected javac. + pass + elif env['PLATFORM'] == 'win32': + # on Windows, we have the right path to javac, so look locally + javac_bin_dir = os.path.dirname(javac) + java_inc_dir = os.path.normpath(os.path.join(javac_bin_dir, '..', 'include')) + paths = [java_inc_dir, os.path.join(java_inc_dir, 'win32')] + elif env['PLATFORM'] == 'darwin': + if not version: + paths = [java_macos_include_dir_glob] + else: + paths = sorted(glob.glob(java_macos_version_include_dir_glob % version)) + else: + base_paths = [] + if not version: + for p in java_linux_include_dirs_glob: + base_paths.extend(glob.glob(p)) + else: + for p in java_linux_version_include_dirs_glob: + base_paths.extend(glob.glob(p % version)) + + for p in base_paths: + paths.extend([p, os.path.join(p, 'linux')]) + + # print("PATHS:%s"%paths) + return paths # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/JavaCommonTests.py b/src/engine/SCons/Tool/JavaCommonTests.py index da405f0..45a8a0b 100644 --- a/src/engine/SCons/Tool/JavaCommonTests.py +++ b/src/engine/SCons/Tool/JavaCommonTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,17 +21,17 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/JavaCommonTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/JavaCommonTests.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path import sys import unittest - -import TestUnit +import fnmatch import SCons.Scanner.IDL import SCons.Tool.JavaCommon +import TestSCons # Adding trace=trace to any of the parse_jave() calls below will cause # the parser to spit out trace messages of the tokens it sees and the @@ -566,14 +566,122 @@ public class Foo assert expect == classes, (expect, classes) + def test_in_function_class_declaration(self): + """ + Test that implementing a class in a function call doesn't confuse SCons. + """ + + input = """ +package com.Matthew; + +public class AnonDemo { + + public static void main(String[] args) { + new AnonDemo().execute(); + } + + public void execute() { + Foo bar = new Foo(new Foo() { + @Override + public int getX() { return this.x; } + }) { + @Override + public int getX() { return this.x; } + }; + } + + public abstract class Foo { + public int x; + public abstract int getX(); + + public Foo(Foo f) { + this.x = f.x; + } + + public Foo() {} + } +} +""" + expect = ['AnonDemo$1', + 'AnonDemo$2', + 'AnonDemo$Foo', + 'AnonDemo'] + pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.8') + assert expect == classes, (expect, classes) + + def test_jdk_globs(self): + """ + Verify that the java path globs work with specific examples. + :return: + """ + from SCons.Tool.JavaCommon import java_linux_include_dirs_glob, java_linux_version_include_dirs_glob, java_win32_dir_glob, java_win32_version_dir_glob, java_macos_include_dir_glob, java_macos_version_include_dir_glob + + # Test windows globs + win_java_dirs = [ + ('C:/Program Files/Java/jdk1.8.0_201/bin', '1.8.0'), + ('C:/Program Files/Java/jdk-11.0.2/bin', '11.0.2'), + ('C:/Program Files/Java/jdk1.7.0_80/bin', '1.7.0') + ] + + for (wjd, version) in win_java_dirs: + if not fnmatch.fnmatch(wjd, java_win32_dir_glob): + self.fail("Didn't properly match %s with pattern %s" % (wjd, java_win32_dir_glob)) + if not fnmatch.fnmatch(wjd, java_win32_version_dir_glob % version): + self.fail("Didn't properly match %s with version (%s) specific pattern %s" % ( + wjd, version, java_win32_version_dir_glob % version)) + + non_win_java_include_dirs = [ + ('/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/include', '1.8.0'), + ('/usr/lib/jvm/java-1.8.0-openjdk-amd64/include', '1.8.0'), + ('/usr/lib/jvm/java-8-openjdk-amd64/include', '8'), + ] + + # Test non-windows/non-macos globs + for (wjd, version) in non_win_java_include_dirs: + match = False + globs_tried =[] + for jlig in java_linux_include_dirs_glob: + globs_tried.append(jlig) + + if fnmatch.fnmatch(wjd, jlig): + match = True + break + + if not match: + self.fail("Didn't properly match %s with pattern %s" % (wjd, globs_tried)) + + match = False + globs_tried = [] + for jlvig in java_linux_version_include_dirs_glob: + globs_tried.append(jlvig%version) + if fnmatch.fnmatch(wjd, jlvig % version): + match = True + break + + if not match: + self.fail("Didn't properly match %s with version (%s) specific pattern %s" % ( + wjd, version, globs_tried)) + + # Test macos globs + # Test windows globs + macos_java_dirs = [ + # ('/System/Library/Frameworks/JavaVM.framework/Headers/', None), + ('/System/Library/Frameworks/JavaVM.framework/Versions/11.0.2/Headers/', '11.0.2'), + ] + + if not fnmatch.fnmatch('/System/Library/Frameworks/JavaVM.framework/Headers/', java_macos_include_dir_glob): + self.fail("Didn't properly match %s with pattern %s" % ('/System/Library/Frameworks/JavaVM.framework/Headers/', java_macos_include_dir_glob)) + + for (wjd, version) in macos_java_dirs: + if not fnmatch.fnmatch(wjd, java_macos_version_include_dir_glob % version): + self.fail("Didn't properly match %s with version (%s) specific pattern %s" % ( + wjd, version, java_macos_version_include_dir_glob % version)) + + + if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ parse_javaTestCase ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/MSCommon/__init__.py b/src/engine/SCons/Tool/MSCommon/__init__.py index 989ab08..e3c4471 100644 --- a/src/engine/SCons/Tool/MSCommon/__init__.py +++ b/src/engine/SCons/Tool/MSCommon/__init__.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" __doc__ = """ Common functions for Microsoft Visual Studio and Visual C/C++. diff --git a/src/engine/SCons/Tool/MSCommon/arch.py b/src/engine/SCons/Tool/MSCommon/arch.py index 96f05a8..6312541 100644 --- a/src/engine/SCons/Tool/MSCommon/arch.py +++ b/src/engine/SCons/Tool/MSCommon/arch.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" __doc__ = """Module to define supported Windows chip architectures. """ @@ -37,22 +37,22 @@ class ArchDefinition(object): self.synonyms = synonyms SupportedArchitectureList = [ - ArchitectureDefinition( + ArchDefinition( 'x86', ['i386', 'i486', 'i586', 'i686'], ), - ArchitectureDefinition( + ArchDefinition( 'x86_64', ['AMD64', 'amd64', 'em64t', 'EM64T', 'x86_64'], ), - ArchitectureDefinition( + ArchDefinition( 'ia64', ['IA64'], ), - ArchitectureDefinition( + ArchDefinition( 'arm', ['ARM'], ), diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index fcf623f..8353944 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -2,7 +2,7 @@ Common helper functions for working with the Microsoft tool chain. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,7 +25,7 @@ Common helper functions for working with the Microsoft tool chain. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/MSCommon/common.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/common.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import copy import os @@ -34,7 +34,6 @@ import re import SCons.Util - LOGFILE = os.environ.get('SCONS_MSCOMMON_DEBUG') if LOGFILE == '-': def debug(message): @@ -46,7 +45,7 @@ elif LOGFILE: debug = lambda message: open(LOGFILE, 'a').write(message + '\n') else: logging.basicConfig(filename=LOGFILE, level=logging.DEBUG) - debug = logging.debug + debug = logging.getLogger(name=__name__).debug else: debug = lambda x: None @@ -117,7 +116,7 @@ def normalize_env(env, keys, force=False): normenv[k] = copy.deepcopy(env[k]) for k in keys: - if k in os.environ and (force or not k in normenv): + if k in os.environ and (force or k not in normenv): normenv[k] = os.environ[k] # This shouldn't be necessary, since the default environment should include system32, @@ -188,8 +187,10 @@ def get_output(vcbat, args = None, env = None): # Use the .stdout and .stderr attributes directly because the # .communicate() method uses the threading module on Windows # and won't work under Pythons not built with threading. - stdout = popen.stdout.read() - stderr = popen.stderr.read() + with popen.stdout: + stdout = popen.stdout.read() + with popen.stderr: + stderr = popen.stderr.read() # Extra debug logic, uncomment if necessary # debug('get_output():stdout:%s'%stdout) @@ -206,7 +207,7 @@ def get_output(vcbat, args = None, env = None): output = stdout.decode("mbcs") return output -def parse_output(output, keep=("INCLUDE", "LIB", "LIBPATH", "PATH")): +def parse_output(output, keep=("INCLUDE", "LIB", "LIBPATH", "PATH", 'VSCMD_ARG_app_plat')): """ Parse output from running visual c++/studios vcvarsall.bat and running set To capture the values listed in keep diff --git a/src/engine/SCons/Tool/MSCommon/netframework.py b/src/engine/SCons/Tool/MSCommon/netframework.py index b769c44..edd9fd9 100644 --- a/src/engine/SCons/Tool/MSCommon/netframework.py +++ b/src/engine/SCons/Tool/MSCommon/netframework.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,7 +20,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" __doc__ = """ """ @@ -68,7 +68,7 @@ def query_versions(): # sequence comparison in python is lexicographical # which is exactly what we want. # Note we sort backwards so the highest version is first. - return cmp(bbl,aal) + return (aal > bbl) - (aal < bbl) versions.sort(versrt) else: diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index 8bc9830..e664a30 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" __doc__ = """Module to detect the Platform/Windows SDK @@ -178,6 +178,16 @@ SDK100VCSetupScripts = {'x86' : r'bin\vcvars32.bat', # # If you update this list, update the documentation in Tool/mssdk.xml. SupportedSDKList = [ + WindowsSDK('10.0A', + sanity_check_file=r'bin\SetEnv.Cmd', + include_subdir='include', + lib_subdir={ + 'x86' : ['lib'], + 'x86_64' : [r'lib\x64'], + 'ia64' : [r'lib\ia64'], + }, + vc_setup_scripts = SDK70VCSetupScripts, + ), WindowsSDK('10.0', sanity_check_file=r'bin\SetEnv.Cmd', include_subdir='include', diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index fba86af..fa7be96 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # * test on 64 bits XP + VS 2005 (and VS 6 if possible) # * SDK # * Assembly -__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" __doc__ = """Module for Visual C/C++ detection and configuration. """ @@ -43,6 +43,7 @@ import platform from string import digits as string_digits import SCons.Warnings +from SCons.Tool import find_program_path from . import common @@ -59,7 +60,10 @@ class VisualCException(Exception): class UnsupportedVersion(VisualCException): pass -class UnsupportedArch(VisualCException): +class MSVCUnsupportedHostArch(VisualCException): + pass + +class MSVCUnsupportedTargetArch(VisualCException): pass class MissingConfiguration(VisualCException): @@ -79,15 +83,41 @@ _ARCH_TO_CANONICAL = { "i486" : "x86", "i586" : "x86", "i686" : "x86", - "ia64" : "ia64", - "itanium" : "ia64", + "ia64" : "ia64", # deprecated + "itanium" : "ia64", # deprecated "x86" : "x86", "x86_64" : "amd64", - "x86_amd64" : "x86_amd64", # Cross compile to 64 bit from 32bits + "arm" : "arm", + "arm64" : "arm64", + "aarch64" : "arm64", +} + +_HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 = { + ("amd64","amd64") : ("Hostx64","x64"), + ("amd64","x86") : ("Hostx64","x86"), + ("amd64","arm") : ("Hostx64","arm"), + ("amd64","arm64") : ("Hostx64","arm64"), + ("x86","amd64") : ("Hostx86","x64"), + ("x86","x86") : ("Hostx86","x86"), + ("x86","arm") : ("Hostx86","arm"), + ("x86","arm64") : ("Hostx86","arm64"), } -# Given a (host, target) tuple, return the argument for the bat file. Both host -# and targets should be canonalized. +# get path to the cl.exe dir for older VS versions +# based off a tuple of (host, target) platforms +_HOST_TARGET_TO_CL_DIR = { + ("amd64","amd64") : "amd64", + ("amd64","x86") : "amd64_x86", + ("amd64","arm") : "amd64_arm", + ("amd64","arm64") : "amd64_arm64", + ("x86","amd64") : "x86_amd64", + ("x86","x86") : "", + ("x86","arm") : "x86_arm", + ("x86","arm64") : "x86_arm64", +} + +# Given a (host, target) tuple, return the argument for the bat file. +# Both host and targets should be canonalized. _HOST_TARGET_ARCH_TO_BAT_ARCH = { ("x86", "x86"): "x86", ("x86", "amd64"): "x86_amd64", @@ -95,9 +125,32 @@ _HOST_TARGET_ARCH_TO_BAT_ARCH = { ("amd64", "x86_amd64"): "x86_amd64", # This is present in (at least) VS2012 express ("amd64", "amd64"): "amd64", ("amd64", "x86"): "x86", - ("x86", "ia64"): "x86_ia64" + ("x86", "ia64"): "x86_ia64", # gone since 14.0 + ("arm", "arm"): "arm", # since 14.0, maybe gone 14.1? + ("x86", "arm"): "x86_arm", # since 14.0 + ("x86", "arm64"): "x86_arm64", # since 14.1 + ("amd64", "arm"): "amd64_arm", # since 14.0 + ("amd64", "arm64"): "amd64_arm64", # since 14.1 } +_CL_EXE_NAME = 'cl.exe' + +def get_msvc_version_numeric(msvc_version): + """Get the raw version numbers from a MSVC_VERSION string, so it + could be cast to float or other numeric values. For example, '14.0Exp' + would get converted to '14.0'. + + Args: + msvc_version: str + string representing the version number, could contain non + digit characters + + Returns: + str: the value converted to a numeric only string + + """ + return ''.join([x for x in msvc_version if x in string_digits + '.']) + def get_host_target(env): debug('vc.py:get_host_target()') @@ -122,25 +175,33 @@ def get_host_target(env): try: host = _ARCH_TO_CANONICAL[host_platform.lower()] - except KeyError as e: + except KeyError: msg = "Unrecognized host architecture %s" - raise ValueError(msg % repr(host_platform)) + raise MSVCUnsupportedHostArch(msg % repr(host_platform)) try: target = _ARCH_TO_CANONICAL[target_platform.lower()] - except KeyError as e: + except KeyError: all_archs = str(list(_ARCH_TO_CANONICAL.keys())) - raise ValueError("Unrecognized target architecture %s\n\tValid architectures: %s" % (target_platform, all_archs)) + raise MSVCUnsupportedTargetArch("Unrecognized target architecture %s\n\tValid architectures: %s" % (target_platform, all_archs)) return (host, target,req_target_platform) # If you update this, update SupportedVSList in Tool/MSCommon/vs.py, and the # MSVC_VERSION documentation in Tool/msvc.xml. -_VCVER = ["14.1", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] +_VCVER = ["14.2", "14.1", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"] + +# if using vswhere, a further mapping is needed +_VCVER_TO_VSWHERE_VER = { + '14.2' : '[16.0, 17.0)', + '14.1' : '[15.0, 16.0)', +} _VCVER_TO_PRODUCT_DIR = { + '14.2' : [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # VS 2019 doesn't set this key '14.1' : [ - (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # Visual Studio 2017 doesn't set this registry key anymore + (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # VS 2017 doesn't set this key '14.0' : [ (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\14.0\Setup\VC\ProductDir')], '14.0Exp' : [ @@ -188,7 +249,7 @@ _VCVER_TO_PRODUCT_DIR = { } def msvc_version_to_maj_min(msvc_version): - msvc_version_numeric = ''.join([x for x in msvc_version if x in string_digits + '.']) + msvc_version_numeric = get_msvc_version_numeric(msvc_version) t = msvc_version_numeric.split(".") if not len(t) == 2: @@ -201,53 +262,73 @@ def msvc_version_to_maj_min(msvc_version): raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) def is_host_target_supported(host_target, msvc_version): - """Return True if the given (host, target) tuple is supported given the - msvc version. - - Parameters - ---------- - host_target: tuple - tuple of (canonalized) host-target, e.g. ("x86", "amd64") for cross - compilation from 32 bits windows to 64 bits. - msvc_version: str - msvc version (major.minor, e.g. 10.0) - - Note - ---- - This only check whether a given version *may* support the given (host, - target), not that the toolchain is actually present on the machine. + """Check if (host, target) pair is supported for a VC version. + + :note: only checks whether a given version *may* support the given (host, + target), not that the toolchain is actually present on the machine. + :param tuple host_target: canonalized host-targets pair, e.g. + ("x86", "amd64") for cross compilation from 32 bit Windows to 64 bits. + :param str msvc_version: Visual C++ version (major.minor), e.g. "10.0" + :returns: True or False """ # We assume that any Visual Studio version supports x86 as a target if host_target[1] != "x86": maj, min = msvc_version_to_maj_min(msvc_version) if maj < 8: return False - return True def find_vc_pdir_vswhere(msvc_version): """ - Find the MSVC product directory using vswhere.exe . - Run it asking for specified version and get MSVS install location - :param msvc_version: - :return: MSVC install dir + Find the MSVC product directory using the vswhere program. + + :param msvc_version: MSVC version to search for + :return: MSVC install dir or None + :raises UnsupportedVersion: if the version is not known by this file """ - vswhere_path = os.path.join( - 'C:\\', - 'Program Files (x86)', - 'Microsoft Visual Studio', - 'Installer', - 'vswhere.exe' - ) - vswhere_cmd = [vswhere_path, '-version', msvc_version, '-property', 'installationPath'] - - if os.path.exists(vswhere_path): - sp = subprocess.Popen(vswhere_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - vsdir, err = sp.communicate() - vsdir = vsdir.decode("mbcs") - vsdir = vsdir.rstrip() - vc_pdir = os.path.join(vsdir, 'VC') + + try: + vswhere_version = _VCVER_TO_VSWHERE_VER[msvc_version] + except KeyError: + debug("Unknown version of MSVC: %s" % msvc_version) + raise UnsupportedVersion("Unknown version %s" % msvc_version) + + # For bug 3333 - support default location of vswhere for both 64 and 32 bit windows + # installs. + for pf in ['Program Files (x86)', 'Program Files']: + vswhere_path = os.path.join( + 'C:\\', + pf, + 'Microsoft Visual Studio', + 'Installer', + 'vswhere.exe' + ) + if os.path.exists(vswhere_path): + # If we found vswhere, then use it. + break + else: + # No vswhere on system, no install info available + return None + + vswhere_cmd = [vswhere_path, + '-products', '*', + '-version', vswhere_version, + '-property', 'installationPath'] + + #TODO PY27 cannot use Popen as context manager + # try putting it back to the old way for now + sp = subprocess.Popen(vswhere_cmd, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + vsdir, err = sp.communicate() + if vsdir: + vsdir = vsdir.decode("mbcs").splitlines() + # vswhere could easily return multiple lines + # we could define a way to pick the one we prefer, but since + # this data is currently only used to make a check for existence, + # returning the first hit should be good enough for now. + vc_pdir = os.path.join(vsdir[0], 'VC') return vc_pdir else: # No vswhere on system, no install info available @@ -255,13 +336,25 @@ def find_vc_pdir_vswhere(msvc_version): def find_vc_pdir(msvc_version): - """Try to find the product directory for the given - version. + """Find the MSVC product directory for the given version. + + Tries to look up the path using a registry key from the table + _VCVER_TO_PRODUCT_DIR; if there is no key, calls find_vc_pdir_wshere + for help instead. - Note - ---- - If for some reason the requested version could not be found, an - exception which inherits from VisualCException will be raised.""" + Args: + msvc_version: str + msvc version (major.minor, e.g. 10.0) + + Returns: + str: Path found in registry, or None + + Raises: + UnsupportedVersion: if the version is not known by this file. + MissingConfiguration: found version but the directory is missing. + + Both exceptions inherit from VisualCException. + """ root = 'Software\\' try: hkeys = _VCVER_TO_PRODUCT_DIR[msvc_version] @@ -275,8 +368,10 @@ def find_vc_pdir(msvc_version): if not key: comps = find_vc_pdir_vswhere(msvc_version) if not comps: - debug('find_vc_dir(): no VC found via vswhere for version {}'.format(repr(key))) + debug('find_vc_pdir_vswhere(): no VC found for version {}'.format(repr(msvc_version))) raise SCons.Util.WinError + debug('find_vc_pdir_vswhere(): VC found: {}'.format(repr(msvc_version))) + return comps else: if common.is_win64(): try: @@ -308,10 +403,10 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): if pdir is None: raise NoVersionFound("No version of Visual Studio found") - debug('vc.py: find_batch_file() pdir:{}'.format(pdir)) + debug('vc.py: find_batch_file() in {}'.format(pdir)) # filter out e.g. "Exp" from the version name - msvc_ver_numeric = ''.join([x for x in msvc_version if x in string_digits + "."]) + msvc_ver_numeric = get_msvc_version_numeric(msvc_version) vernum = float(msvc_ver_numeric) if 7 <= vernum < 8: pdir = os.path.join(pdir, os.pardir, "Common7", "Tools") @@ -342,26 +437,146 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): __INSTALLED_VCS_RUN = None +_VC_TOOLS_VERSION_FILE_PATH = ['Auxiliary', 'Build', 'Microsoft.VCToolsVersion.default.txt'] +_VC_TOOLS_VERSION_FILE = os.sep.join(_VC_TOOLS_VERSION_FILE_PATH) + +def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): + """Find the cl.exe on the filesystem in the vc_dir depending on + TARGET_ARCH, HOST_ARCH and the msvc version. TARGET_ARCH and + HOST_ARCH can be extracted from the passed env, unless its None, + which then the native platform is assumed the host and target. + + Args: + env: Environment + a construction environment, usually if this is passed its + because there is a desired TARGET_ARCH to be used when searching + for a cl.exe + vc_dir: str + the path to the VC dir in the MSVC installation + msvc_version: str + msvc version (major.minor, e.g. 10.0) + + Returns: + bool: + + """ -def cached_get_installed_vcs(): + # determine if there is a specific target platform we want to build for and + # use that to find a list of valid VCs, default is host platform == target platform + # and same for if no env is specified to extract target platform from + if env: + (host_platform, target_platform, req_target_platform) = get_host_target(env) + else: + host_platform = platform.machine().lower() + target_platform = host_platform + + host_platform = _ARCH_TO_CANONICAL[host_platform] + target_platform = _ARCH_TO_CANONICAL[target_platform] + + debug('_check_cl_exists_in_vc_dir(): host platform %s, target platform %s for version %s' % (host_platform, target_platform, msvc_version)) + + ver_num = float(get_msvc_version_numeric(msvc_version)) + + # make sure the cl.exe exists meaning the tool is installed + if ver_num > 14: + # 2017 and newer allowed multiple versions of the VC toolset to be installed at the same time. + # Just get the default tool version for now + #TODO: support setting a specific minor VC version + default_toolset_file = os.path.join(vc_dir, _VC_TOOLS_VERSION_FILE) + try: + with open(default_toolset_file) as f: + vc_specific_version = f.readlines()[0].strip() + except IOError: + debug('_check_cl_exists_in_vc_dir(): failed to read ' + default_toolset_file) + return False + except IndexError: + debug('_check_cl_exists_in_vc_dir(): failed to find MSVC version in ' + default_toolset_file) + return False + + host_trgt_dir = _HOST_TARGET_TO_CL_DIR_GREATER_THAN_14.get((host_platform, target_platform), None) + if host_trgt_dir is None: + debug('_check_cl_exists_in_vc_dir(): unsupported host/target platform combo: (%s,%s)'%(host_platform, target_platform)) + return False + + cl_path = os.path.join(vc_dir, 'Tools','MSVC', vc_specific_version, 'bin', host_trgt_dir[0], host_trgt_dir[1], _CL_EXE_NAME) + debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path) + if os.path.exists(cl_path): + debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!') + return True + + elif ver_num <= 14 and ver_num >= 8: + + # Set default value to be -1 as "" which is the value for x86/x86 yields true when tested + # if not host_trgt_dir + host_trgt_dir = _HOST_TARGET_TO_CL_DIR.get((host_platform, target_platform), None) + if host_trgt_dir is None: + debug('_check_cl_exists_in_vc_dir(): unsupported host/target platform combo') + return False + + cl_path = os.path.join(vc_dir, 'bin', host_trgt_dir, _CL_EXE_NAME) + debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path) + + cl_path_exists = os.path.exists(cl_path) + if not cl_path_exists and host_platform == 'amd64': + # older versions of visual studio only had x86 binaries, + # so if the host platform is amd64, we need to check cross + # compile options (x86 binary compiles some other target on a 64 bit os) + + # Set default value to be -1 as "" which is the value for x86/x86 yields true when tested + # if not host_trgt_dir + host_trgt_dir = _HOST_TARGET_TO_CL_DIR.get(('x86', target_platform), None) + if host_trgt_dir is None: + return False + + cl_path = os.path.join(vc_dir, 'bin', host_trgt_dir, _CL_EXE_NAME) + debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path) + cl_path_exists = os.path.exists(cl_path) + + if cl_path_exists: + debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!') + return True + + elif ver_num < 8 and ver_num >= 6: + # not sure about these versions so if a walk the VC dir (could be slow) + for root, _, files in os.walk(vc_dir): + if _CL_EXE_NAME in files: + debug('get_installed_vcs ' + _CL_EXE_NAME + ' found %s' % os.path.join(root, _CL_EXE_NAME)) + return True + return False + else: + # version not support return false + debug('_check_cl_exists_in_vc_dir(): unsupported MSVC version: ' + str(ver_num)) + + return False + +def cached_get_installed_vcs(env=None): global __INSTALLED_VCS_RUN if __INSTALLED_VCS_RUN is None: - ret = get_installed_vcs() + ret = get_installed_vcs(env) __INSTALLED_VCS_RUN = ret return __INSTALLED_VCS_RUN -def get_installed_vcs(): +def get_installed_vcs(env=None): installed_versions = [] + for ver in _VCVER: debug('trying to find VC %s' % ver) try: - if find_vc_pdir(ver): + VC_DIR = find_vc_pdir(ver) + if VC_DIR: debug('found VC %s' % ver) - installed_versions.append(ver) + if _check_cl_exists_in_vc_dir(env, VC_DIR, ver): + installed_versions.append(ver) + else: + debug('find_vc_pdir no compiler found %s' % ver) else: debug('find_vc_pdir return None for ver %s' % ver) + except (MSVCUnsupportedTargetArch, MSVCUnsupportedHostArch): + # Allow this exception to propagate further as it should cause + # SCons to exit with an error code + raise except VisualCException as e: debug('did not find VC %s: caught exception %s' % (ver, str(e))) return installed_versions @@ -416,7 +631,7 @@ def get_default_version(env): % (msvc_version, msvs_version)) return msvs_version if not msvc_version: - installed_vcs = cached_get_installed_vcs() + installed_vcs = cached_get_installed_vcs(env) debug('installed_vcs:%s' % installed_vcs) if not installed_vcs: #msg = 'No installed VCs' @@ -443,16 +658,17 @@ def msvc_find_valid_batch_script(env,version): debug('vc.py:msvc_find_valid_batch_script()') # Find the host platform, target platform, and if present the requested # target platform - (host_platform, target_platform,req_target_platform) = get_host_target(env) + platforms = get_host_target(env) + debug("vc.py: msvs_find_valid_batch_script(): host_platform %s, target_platform %s req_target_platform:%s" % platforms) + host_platform, target_platform, req_target_platform = platforms try_target_archs = [target_platform] - debug("msvs_find_valid_batch_script(): req_target_platform %s target_platform:%s"%(req_target_platform,target_platform)) # VS2012 has a "cross compile" environment to build 64 bit # with x86_amd64 as the argument to the batch setup script - if req_target_platform in ('amd64','x86_64'): + if req_target_platform in ('amd64', 'x86_64'): try_target_archs.append('x86_amd64') - elif not req_target_platform and target_platform in ['amd64','x86_64']: + elif not req_target_platform and target_platform in ['amd64', 'x86_64']: # There may not be "native" amd64, but maybe "cross" x86_amd64 tools try_target_archs.append('x86_amd64') # If the user hasn't specifically requested a TARGET_ARCH, and @@ -474,7 +690,7 @@ def msvc_find_valid_batch_script(env,version): (host_target, version) SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[host_target] - + # Get just version numbers maj, min = msvc_version_to_maj_min(version) # VS2015+ @@ -493,15 +709,17 @@ def msvc_find_valid_batch_script(env,version): warn_msg = "VC version %s not installed. " + \ "C/C++ compilers are most likely not set correctly.\n" + \ " Installed versions are: %s" - warn_msg = warn_msg % (version, cached_get_installed_vcs()) + warn_msg = warn_msg % (version, cached_get_installed_vcs(env)) SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) continue # Try to use the located batch file for this host/target platform combo debug('vc.py:msvc_find_valid_batch_script() use_script 2 %s, args:%s\n' % (repr(vc_script), arg)) + found = None if vc_script: try: d = script_env(vc_script, args=arg) + found = vc_script except BatchFileExecutionError as e: debug('vc.py:msvc_find_valid_batch_script() use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e)) vc_script=None @@ -510,6 +728,7 @@ def msvc_find_valid_batch_script(env,version): debug('vc.py:msvc_find_valid_batch_script() use_script 4: trying sdk script: %s'%(sdk_script)) try: d = script_env(sdk_script) + found = sdk_script except BatchFileExecutionError as e: debug('vc.py:msvc_find_valid_batch_script() use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script),e)) continue @@ -517,7 +736,7 @@ def msvc_find_valid_batch_script(env,version): debug('vc.py:msvc_find_valid_batch_script() use_script 6: Neither VC script nor SDK script found') continue - debug("vc.py:msvc_find_valid_batch_script() Found a working script/target: %s %s"%(repr(sdk_script),arg)) + debug("vc.py:msvc_find_valid_batch_script() Found a working script/target: %s/%s"%(repr(found),arg)) break # We've found a working target_platform, so stop looking # If we cannot find a viable installed compiler, reset the TARGET_ARCH @@ -566,8 +785,14 @@ def msvc_setup_env(env): debug('vc.py:msvc_setup_env() env:%s -> %s'%(k,v)) env.PrependENVPath(k, v, delete_existing=True) -def msvc_exists(version=None): - vcs = cached_get_installed_vcs() + # final check to issue a warning if the compiler is not present + msvc_cl = find_program_path(env, 'cl') + if not msvc_cl: + SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, + "Could not find MSVC compiler 'cl', it may need to be installed separately with Visual Studio") + +def msvc_exists(env=None, version=None): + vcs = cached_get_installed_vcs(env) if version is None: return len(vcs) > 0 return version in vcs diff --git a/src/engine/SCons/Tool/MSCommon/vcTests.py b/src/engine/SCons/Tool/MSCommon/vcTests.py new file mode 100644 index 0000000..25537f3 --- /dev/null +++ b/src/engine/SCons/Tool/MSCommon/vcTests.py @@ -0,0 +1,180 @@ +# +# Copyright (c) 2001 - 2019 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# from typing import Dict, Any + +__revision__ = "src/engine/SCons/Tool/MSCommon/vcTests.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" + +import os +import os.path +import unittest + +import SCons.Node.FS +import SCons.Warnings +import SCons.Tool.MSCommon.vc + +import TestCmd + +original = os.getcwd() + +test = TestCmd.TestCmd(workdir='') + +os.chdir(test.workpath('')) + +MSVCUnsupportedHostArch = SCons.Tool.MSCommon.vc.MSVCUnsupportedHostArch +MSVCUnsupportedTargetArch = SCons.Tool.MSCommon.vc.MSVCUnsupportedTargetArch + +MS_TOOLS_VERSION='1.1.1' + +class MSVcTestCase(unittest.TestCase): + + @staticmethod + def _createDummyCl(path, add_bin=True): + """ + Creates a dummy cl.ex in the correct directory. + It will create all missing parent directories as well + + Args: + path: Relative path to cl.exe for the version about to be tested. + """ + + # print("PATH:%s"%path) + + path = path.replace('\\', os.sep) + if add_bin: + create_path = os.path.join(path,'bin') + else: + create_path = path + if create_path and not os.path.isdir(create_path): + os.makedirs(create_path) + + create_this = os.path.join(create_path,'cl.exe') + + # print("Creating: %s"%create_this) + with open(create_this,'w') as ct: + ct.write('created') + + + + + def runTest(self): + """ + Check that all proper HOST_PLATFORM and TARGET_PLATFORM are handled. + Verify that improper HOST_PLATFORM and/or TARGET_PLATFORM are properly handled. + by SCons.Tool.MSCommon.vc._check_cl_exists_in_vc_dir() + """ + + check = SCons.Tool.MSCommon.vc._check_cl_exists_in_vc_dir + + env={'TARGET_ARCH':'x86'} + p = SCons.Tool.MSCommon.vc._HOST_TARGET_TO_CL_DIR[('x86','x86')] + MSVcTestCase._createDummyCl(p) + + # print("retval:%s"%check(env, '.', '8.0')) + + + # Setup for VC 14+ tests + + # Create the VC minor/major version file + tools_version_file = SCons.Tool.MSCommon.vc._VC_TOOLS_VERSION_FILE + tools_dir = os.path.dirname(tools_version_file) + if not os.path.isdir(tools_dir): + os.makedirs(tools_dir) + try: + with open(tools_version_file, 'w') as tf: + tf.write(MS_TOOLS_VERSION) + except IOError as e: + print("Failed trying to write :%s :%s"%(tools_version_file, e)) + + + # Now walk all the valid combinations of host/target for VC 14 + + vc_gt_14_map = SCons.Tool.MSCommon.vc._HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 + + for key, value in vc_gt_14_map.items(): + # print("GT 14 Got: %s -> %s"%(key,value)) + + env={'TARGET_ARCH':key[1], 'HOST_ARCH':key[0]} + path = os.path.join('.','Tools','MSVC', MS_TOOLS_VERSION, 'bin', value[0], value[1]) + MSVcTestCase._createDummyCl(path, add_bin=False) + result=check(env, '.', '14.1') + # print("for:%s got :%s"%(key[1], result)) + self.assertTrue(result, "Checking host: %s target: %s"%(value[0], value[1])) + + # Now test bogus value for HOST_ARCH + env={'TARGET_ARCH':'x86', 'HOST_ARCH':'GARBAGE'} + try: + result=check(env, '.', '14.1') + # print("for:%s got :%s"%(env, result)) + self.assertFalse(result, "Did not fail with bogus HOST_ARCH host: %s target: %s"%(value[0], value[1])) + except MSVCUnsupportedHostArch: + pass + else: + self.fail('Did not fail when HOST_ARCH specified as: %s'%env['HOST_ARCH']) + + # Now test bogus value for TARGET_ARCH + env={'TARGET_ARCH':'GARBAGE', 'HOST_ARCH':'x86'} + try: + result=check(env, '.', '14.1') + # print("for:%s got :%s"%(env, result)) + self.assertFalse(result, "Did not fail with bogus TARGET_ARCH host: %s target: %s"%(value[0], value[1])) + except MSVCUnsupportedTargetArch: + pass + else: + self.fail('Did not fail when HOST_ARCH specified as: %s'%env['TARGET_ARCH']) + + # Test >8 < 14 VC versions + vc_map = SCons.Tool.MSCommon.vc._HOST_TARGET_TO_CL_DIR + for key,value in vc_map.items(): + # print("LT 14 Got: %s -> %s"%(key,value)) + env={'TARGET_ARCH':key[1], 'HOST_ARCH':key[0]} + path = os.path.join('.', 'bin', value ) + MSVcTestCase._createDummyCl(path, add_bin=False) + result=check(env, '.', '9.0') + # print("for:%s got :%s"%(key[1], result)) + self.assertTrue(result, "Checking host: %s target: %s"%(key[0], key[1])) + + # Now test bogus value for HOST_ARCH + env={'TARGET_ARCH':'x86', 'HOST_ARCH':'GARBAGE'} + try: + result=check(env, '.', '9.0') + # print("for:%s got :%s"%(env, result)) + self.assertFalse(result, "Did not fail with bogus HOST_ARCH host: %s target: %s"%(env['HOST_ARCH'], env['TARGET_ARCH'])) + except MSVCUnsupportedHostArch: + pass + else: + self.fail('Did not fail when HOST_ARCH specified as: %s'%env['HOST_ARCH']) + + # Now test bogus value for TARGET_ARCH + env={'TARGET_ARCH':'GARBAGE', 'HOST_ARCH':'x86'} + try: + result=check(env, '.', '9.0') + # print("for:%s got :%s"%(env, result)) + self.assertFalse(result, "Did not fail with bogus TARGET_ARCH host: %s target: %s"%(env['HOST_ARCH'], env['TARGET_ARCH'])) + except MSVCUnsupportedTargetArch: + pass + else: + self.fail('Did not fail when HOST_ARCH specified as: %s'%env['TARGET_ARCH']) + + + +if __name__ == "__main__": + unittest.main() diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index dafdbaf..731f328 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" __doc__ = """Module to detect Visual Studio and/or Visual C/C++ """ @@ -68,9 +68,9 @@ class VisualStudio(object): SCons.Tool.MSCommon.vc.get_installed_vcs() dir = SCons.Tool.MSCommon.vc.find_vc_pdir(self.vc_version) if not dir: - debug('find_vs_dir(): no installed VC %s' % self.vc_version) + debug('find_vs_dir_by_vc(): no installed VC %s' % self.vc_version) return None - return dir + return os.path.abspath(os.path.join(dir, os.pardir)) def find_vs_dir_by_reg(self): root = 'Software\\' @@ -95,12 +95,11 @@ class VisualStudio(object): First try to find by registry, and if that fails find via VC dir """ - - if True: - vs_dir=self.find_vs_dir_by_reg() - return vs_dir - else: - return self.find_vs_dir_by_vc() + vs_dir=self.find_vs_dir_by_reg() + if not vs_dir: + vs_dir = self.find_vs_dir_by_vc() + debug('find_vs_dir(): found VS in ' + str(vs_dir )) + return vs_dir def find_executable(self): vs_dir = self.get_vs_dir() @@ -199,6 +198,17 @@ class VisualStudio(object): # Tool/MSCommon/vc.py, and the MSVC_VERSION documentation in Tool/msvc.xml. SupportedVSList = [ + # Visual Studio 2019 + VisualStudio('14.2', + vc_version='14.2', + sdk_version='10.0A', + hkeys=[], + common_tools_var='VS160COMNTOOLS', + executable_path=r'Common7\IDE\devenv.com', + batch_file_path=r'VC\Auxiliary\Build\vsvars32.bat', + supported_arch=['x86', 'amd64', "arm"], + ), + # Visual Studio 2017 VisualStudio('14.1', vc_version='14.1', @@ -521,7 +531,7 @@ def get_default_arch(env): if not msvs: arch = 'x86' - elif not arch in msvs.get_supported_arch(): + elif arch not in msvs.get_supported_arch(): fmt = "Visual Studio version %s does not support architecture %s" raise SCons.Errors.UserError(fmt % (env['MSVS_VERSION'], arch)) diff --git a/src/engine/SCons/Tool/PharLapCommon.py b/src/engine/SCons/Tool/PharLapCommon.py index c45c6d3..623f2a8 100644 --- a/src/engine/SCons/Tool/PharLapCommon.py +++ b/src/engine/SCons/Tool/PharLapCommon.py @@ -7,7 +7,7 @@ Phar Lap ETS tool chain. Right now, this is linkloc and """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ Phar Lap ETS tool chain. Right now, this is linkloc and # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/PharLapCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/PharLapCommon.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import os.path @@ -79,7 +79,8 @@ def getPharLapVersion(): include_path = os.path.join(getPharLapPath(), os.path.normpath("include/embkern.h")) if not os.path.exists(include_path): raise SCons.Errors.UserError("Cannot find embkern.h in ETS include directory.\nIs Phar Lap ETS installed properly?") - mo = REGEX_ETS_VER.search(open(include_path, 'r').read()) + with open(include_path, 'r') as f: + mo = REGEX_ETS_VER.search(f.read()) if mo: return int(mo.group(1)) # Default return for Phar Lap 9.1 diff --git a/src/engine/SCons/Tool/ToolTests.py b/src/engine/SCons/Tool/ToolTests.py index f5678c1..25e9b2d 100644 --- a/src/engine/SCons/Tool/ToolTests.py +++ b/src/engine/SCons/Tool/ToolTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,8 +21,9 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ToolTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ToolTests.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" +import os import sys import unittest @@ -31,29 +32,49 @@ import TestUnit import SCons.Errors import SCons.Tool + +class DummyEnvironment(object): + def __init__(self): + self.dict = {} + def Detect(self, progs): + if not SCons.Util.is_List(progs): + progs = [ progs ] + return progs[0] + def Append(self, **kw): + self.dict.update(kw) + def __getitem__(self, key): + return self.dict[key] + def __setitem__(self, key, val): + self.dict[key] = val + def __contains__(self, key): + return self.dict.__contains__(key) + def has_key(self, key): + return key in self.dict + def subst(self, string, *args, **kwargs): + return string + + PHONY_PATH = "/usr/phony/bin" + def WhereIs(self, key_program): + # for pathfind test for Issue #3336: + # need to fake the case where extra paths are searched, and + # if one has a "hit" after some fails, the fails are left in + # the environment's PATH. So construct a positive answer if + # we see a magic known path component in PATH; answer in + # the negative otherwise. + paths = self['ENV']['PATH'] + if self.PHONY_PATH in paths: + return os.path.join(self.PHONY_PATH, key_program) + return None + def AppendENVPath(self, pathvar, path): + # signature matches how called from find_program_path() + self['ENV'][pathvar] = self['ENV'][pathvar] + os.pathsep + path + + class ToolTestCase(unittest.TestCase): def test_Tool(self): """Test the Tool() function""" - class Environment(object): - def __init__(self): - self.dict = {} - def Detect(self, progs): - if not SCons.Util.is_List(progs): - progs = [ progs ] - return progs[0] - def Append(self, **kw): - self.dict.update(kw) - def __getitem__(self, key): - return self.dict[key] - def __setitem__(self, key, val): - self.dict[key] = val - def __contains__(self, key): - return self.dict.__contains__(key) - def has_key(self, key): - return key in self.dict - def subst(self, string, *args, **kwargs): - return string - env = Environment() + + env = DummyEnvironment() env['BUILDERS'] = {} env['ENV'] = {} env['PLATFORM'] = 'test' @@ -67,17 +88,34 @@ class ToolTestCase(unittest.TestCase): SCons.Tool.Tool() except TypeError: pass - else: + else: # TODO pylint E0704: bare raise not inside except raise try: p = SCons.Tool.Tool('_does_not_exist_') - except SCons.Errors.EnvironmentError: + except SCons.Errors.SConsEnvironmentError: pass - else: + else: # TODO pylint E0704: bare raise not inside except raise + def test_pathfind(self): + """Test that find_program_path() does not alter PATH""" + + env = DummyEnvironment() + PHONY_PATHS = [ + r'C:\cygwin64\bin', + r'C:\cygwin\bin', + '/usr/local/dummy/bin', + env.PHONY_PATH, # will be recognized by dummy WhereIs + ] + env['ENV'] = {} + env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin' + pre_path = env['ENV']['PATH'] + _ = SCons.Tool.find_program_path(env, 'no_tool', default_paths=PHONY_PATHS) + assert env['ENV']['PATH'] == pre_path, env['ENV']['PATH'] + + if __name__ == "__main__": suite = unittest.makeSuite(ToolTestCase, 'test_') TestUnit.run(suite) diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 9265b81..271f214 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -14,7 +14,7 @@ tool definition. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -35,16 +35,13 @@ tool definition. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/__init__.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" -import imp -import importlib import sys import re import os import shutil - import SCons.Builder import SCons.Errors import SCons.Node.FS @@ -54,9 +51,14 @@ import SCons.Scanner.D import SCons.Scanner.LaTeX import SCons.Scanner.Prog import SCons.Scanner.SWIG -import collections +try: + # Python 3 + from collections.abc import Callable +except ImportError: + # Python 2.7 + from collections import Callable -DefaultToolpath=[] +DefaultToolpath = [] CScanner = SCons.Scanner.C.CScanner() DScanner = SCons.Scanner.D.DScanner() @@ -97,20 +99,22 @@ for suffix in LaTeXSuffixes: SourceFileScanner.add_scanner(suffix, LaTeXScanner) SourceFileScanner.add_scanner(suffix, PDFLaTeXScanner) - # Tool aliases are needed for those tools whos module names also # occur in the python standard library. This causes module shadowing and # can break using python library functions under python3 TOOL_ALIASES = { - 'gettext':'gettext_tool', + 'gettext': 'gettext_tool', 'clang++': 'clangxx', } + class Tool(object): - def __init__(self, name, toolpath=[], **kw): + def __init__(self, name, toolpath=None, **kw): + if toolpath is None: + toolpath = [] # Rename if there's a TOOL_ALIAS for this tool - self.name = TOOL_ALIASES.get(name,name) + self.name = TOOL_ALIASES.get(name, name) self.toolpath = toolpath + DefaultToolpath # remember these so we can merge them into the call self.init_kw = kw @@ -122,6 +126,8 @@ class Tool(object): self.options = module.options def _load_dotted_module_py2(self, short_name, full_name, searchpaths=None): + import imp + splitname = short_name.split('.') index = 0 srchpths = searchpaths @@ -136,7 +142,7 @@ class Tool(object): sys.path = self.toolpath + sys.path # sys.stderr.write("Tool:%s\nPATH:%s\n"%(self.name,sys.path)) - if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0,1,2,3,4)): + if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0, 1, 2, 3, 4)): # Py 2 code try: try: @@ -149,8 +155,8 @@ class Tool(object): file.close() except ImportError as e: splitname = self.name.split('.') - if str(e)!="No module named %s"%splitname[0]: - raise SCons.Errors.EnvironmentError(e) + if str(e) != "No module named %s" % splitname[0]: + raise SCons.Errors.SConsEnvironmentError(e) try: import zipimport except ImportError: @@ -184,46 +190,48 @@ class Tool(object): add_to_scons_tools_namespace = False for path in self.toolpath: sepname = self.name.replace('.', os.path.sep) - file_path = os.path.join(path, "%s.py"%sepname) + file_path = os.path.join(path, "%s.py" % sepname) file_package = os.path.join(path, sepname) - if debug: sys.stderr.write("Trying:%s %s\n"%(file_path, file_package)) + if debug: sys.stderr.write("Trying:%s %s\n" % (file_path, file_package)) if os.path.isfile(file_path): spec = importlib.util.spec_from_file_location(self.name, file_path) - if debug: print("file_Path:%s FOUND"%file_path) + if debug: print("file_Path:%s FOUND" % file_path) break elif os.path.isdir(file_package): file_package = os.path.join(file_package, '__init__.py') spec = importlib.util.spec_from_file_location(self.name, file_package) - if debug: print("PACKAGE:%s Found"%file_package) + if debug: print("PACKAGE:%s Found" % file_package) break else: continue if spec is None: - if debug: sys.stderr.write("NO SPEC :%s\n"%self.name) - spec = importlib.util.find_spec("."+self.name, package='SCons.Tool') + if debug: sys.stderr.write("NO SPEC :%s\n" % self.name) + spec = importlib.util.find_spec("." + self.name, package='SCons.Tool') if spec: - found_name = 'SCons.Tool.'+self.name + found_name = 'SCons.Tool.' + self.name add_to_scons_tools_namespace = True - if debug: sys.stderr.write("Spec Found? .%s :%s\n"%(self.name, spec)) + if debug: sys.stderr.write("Spec Found? .%s :%s\n" % (self.name, spec)) if spec is None: - error_string = "No module named %s"%self.name - raise SCons.Errors.EnvironmentError(error_string) + error_string = "No module named %s" % self.name + raise SCons.Errors.SConsEnvironmentError(error_string) module = importlib.util.module_from_spec(spec) if module is None: - if debug: print("MODULE IS NONE:%s"%self.name) - error_string = "No module named %s"%self.name - raise SCons.Errors.EnvironmentError(error_string) + if debug: print("MODULE IS NONE:%s" % self.name) + error_string = "No module named %s" % self.name + raise SCons.Errors.SConsEnvironmentError(error_string) # Don't reload a tool we already loaded. - sys_modules_value = sys.modules.get(found_name,False) + sys_modules_value = sys.modules.get(found_name, False) + + found_module = None if sys_modules_value and sys_modules_value.__file__ == spec.origin: - return sys.modules[found_name] + found_module = sys.modules[found_name] else: # Not sure what to do in the case that there already # exists sys.modules[self.name] but the source file is @@ -235,8 +243,11 @@ class Tool(object): # If we found it in SCons.Tool, then add it to the module setattr(SCons.Tool, self.name, module) - return module + found_module = module + if found_module is not None: + sys.path = oldpythonpath + return found_module sys.path = oldpythonpath @@ -253,20 +264,20 @@ class Tool(object): file.close() return module except ImportError as e: - if str(e)!="No module named %s"%self.name: - raise SCons.Errors.EnvironmentError(e) + if str(e) != "No module named %s" % self.name: + raise SCons.Errors.SConsEnvironmentError(e) try: import zipimport - importer = zipimport.zipimporter( sys.modules['SCons.Tool'].__path__[0] ) + importer = zipimport.zipimporter(sys.modules['SCons.Tool'].__path__[0]) module = importer.load_module(full_name) setattr(SCons.Tool, self.name, module) return module except ImportError as e: m = "No tool named '%s': %s" % (self.name, e) - raise SCons.Errors.EnvironmentError(m) + raise SCons.Errors.SConsEnvironmentError(m) except ImportError as e: m = "No tool named '%s': %s" % (self.name, e) - raise SCons.Errors.EnvironmentError(m) + raise SCons.Errors.SConsEnvironmentError(m) def __call__(self, env, *args, **kw): if self.init_kw is not None: @@ -278,13 +289,13 @@ class Tool(object): kw.update(call_kw) else: kw = self.init_kw - env.Append(TOOLS = [ self.name ]) + env.Append(TOOLS=[self.name]) if hasattr(self, 'options'): import SCons.Variables if 'options' not in env: from SCons.Script import ARGUMENTS - env['options']=SCons.Variables.Variables(args=ARGUMENTS) - opts=env['options'] + env['options'] = SCons.Variables.Variables(args=ARGUMENTS) + opts = env['options'] self.options(opts) opts.Update(env) @@ -294,6 +305,7 @@ class Tool(object): def __str__(self): return self.name + ########################################################################## # Create common executable program / library / object builders @@ -308,13 +320,13 @@ def createProgBuilder(env): program = env['BUILDERS']['Program'] except KeyError: import SCons.Defaults - program = SCons.Builder.Builder(action = SCons.Defaults.LinkAction, - emitter = '$PROGEMITTER', - prefix = '$PROGPREFIX', - suffix = '$PROGSUFFIX', - src_suffix = '$OBJSUFFIX', - src_builder = 'Object', - target_scanner = ProgramScanner) + program = SCons.Builder.Builder(action=SCons.Defaults.LinkAction, + emitter='$PROGEMITTER', + prefix='$PROGPREFIX', + suffix='$PROGSUFFIX', + src_suffix='$OBJSUFFIX', + src_builder='Object', + target_scanner=ProgramScanner) env['BUILDERS']['Program'] = program return program @@ -330,23 +342,24 @@ def createStaticLibBuilder(env): try: static_lib = env['BUILDERS']['StaticLibrary'] except KeyError: - action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ] - if env.get('RANLIB',False) or env.Detect('ranlib'): + action_list = [SCons.Action.Action("$ARCOM", "$ARCOMSTR")] + if env.get('RANLIB', False) or env.Detect('ranlib'): ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR") action_list.append(ranlib_action) - static_lib = SCons.Builder.Builder(action = action_list, - emitter = '$LIBEMITTER', - prefix = '$LIBPREFIX', - suffix = '$LIBSUFFIX', - src_suffix = '$OBJSUFFIX', - src_builder = 'StaticObject') + static_lib = SCons.Builder.Builder(action=action_list, + emitter='$LIBEMITTER', + prefix='$LIBPREFIX', + suffix='$LIBSUFFIX', + src_suffix='$OBJSUFFIX', + src_builder='StaticObject') env['BUILDERS']['StaticLibrary'] = static_lib env['BUILDERS']['Library'] = static_lib return static_lib -def _call_linker_cb(env, callback, args, result = None): + +def _call_linker_cb(env, callback, args, result=None): """Returns the result of env['LINKCALLBACKS'][callback](*args) if env['LINKCALLBACKS'] is a dictionary and env['LINKCALLBACKS'][callback] is callable. If these conditions are not met, return the value provided as @@ -370,136 +383,163 @@ def _call_linker_cb(env, callback, args, result = None): if Verbose: print('_call_linker_cb: env["LINKCALLBACKS"][%r] found' % callback) print('_call_linker_cb: env["LINKCALLBACKS"][%r]=%r' % (callback, cbfun)) - if(isinstance(cbfun, collections.Callable)): + if isinstance(cbfun, Callable): if Verbose: print('_call_linker_cb: env["LINKCALLBACKS"][%r] is callable' % callback) result = cbfun(env, *args) return result + def _call_env_subst(env, string, *args, **kw): kw2 = {} for k in ('raw', 'target', 'source', 'conv', 'executor'): - try: kw2[k] = kw[k] - except KeyError: pass + try: + kw2[k] = kw[k] + except KeyError: + pass return env.subst(string, *args, **kw2) + class _ShLibInfoSupport(object): - def get_libtype(self): + @property + def libtype(self): return 'ShLib' + def get_lib_prefix(self, env, *args, **kw): - return _call_env_subst(env,'$SHLIBPREFIX', *args, **kw) + return _call_env_subst(env, '$SHLIBPREFIX', *args, **kw) + def get_lib_suffix(self, env, *args, **kw): - return _call_env_subst(env,'$SHLIBSUFFIX', *args, **kw) + return _call_env_subst(env, '$SHLIBSUFFIX', *args, **kw) + def get_lib_version(self, env, *args, **kw): - return _call_env_subst(env,'$SHLIBVERSION', *args, **kw) + return _call_env_subst(env, '$SHLIBVERSION', *args, **kw) + def get_lib_noversionsymlinks(self, env, *args, **kw): - return _call_env_subst(env,'$SHLIBNOVERSIONSYMLINKS', *args, **kw) + return _call_env_subst(env, '$SHLIBNOVERSIONSYMLINKS', *args, **kw) + class _LdModInfoSupport(object): - def get_libtype(self): + @property + def libtype(self): return 'LdMod' + def get_lib_prefix(self, env, *args, **kw): - return _call_env_subst(env,'$LDMODULEPREFIX', *args, **kw) + return _call_env_subst(env, '$LDMODULEPREFIX', *args, **kw) + def get_lib_suffix(self, env, *args, **kw): - return _call_env_subst(env,'$LDMODULESUFFIX', *args, **kw) + return _call_env_subst(env, '$LDMODULESUFFIX', *args, **kw) + def get_lib_version(self, env, *args, **kw): - return _call_env_subst(env,'$LDMODULEVERSION', *args, **kw) + return _call_env_subst(env, '$LDMODULEVERSION', *args, **kw) + def get_lib_noversionsymlinks(self, env, *args, **kw): - return _call_env_subst(env,'$LDMODULENOVERSIONSYMLINKS', *args, **kw) + return _call_env_subst(env, '$LDMODULENOVERSIONSYMLINKS', *args, **kw) + class _ImpLibInfoSupport(object): - def get_libtype(self): + @property + def libtype(self): return 'ImpLib' + def get_lib_prefix(self, env, *args, **kw): - return _call_env_subst(env,'$IMPLIBPREFIX', *args, **kw) + return _call_env_subst(env, '$IMPLIBPREFIX', *args, **kw) + def get_lib_suffix(self, env, *args, **kw): - return _call_env_subst(env,'$IMPLIBSUFFIX', *args, **kw) + return _call_env_subst(env, '$IMPLIBSUFFIX', *args, **kw) + def get_lib_version(self, env, *args, **kw): - version = _call_env_subst(env,'$IMPLIBVERSION', *args, **kw) + version = _call_env_subst(env, '$IMPLIBVERSION', *args, **kw) if not version: - try: lt = kw['implib_libtype'] - except KeyError: pass + try: + lt = kw['implib_libtype'] + except KeyError: + pass else: if lt == 'ShLib': - version = _call_env_subst(env,'$SHLIBVERSION', *args, **kw) + version = _call_env_subst(env, '$SHLIBVERSION', *args, **kw) elif lt == 'LdMod': - version = _call_env_subst(env,'$LDMODULEVERSION', *args, **kw) + version = _call_env_subst(env, '$LDMODULEVERSION', *args, **kw) return version + def get_lib_noversionsymlinks(self, env, *args, **kw): disable = None - try: env['IMPLIBNOVERSIONSYMLINKS'] + try: + env['IMPLIBNOVERSIONSYMLINKS'] except KeyError: - try: lt = kw['implib_libtype'] - except KeyError: pass + try: + lt = kw['implib_libtype'] + except KeyError: + pass else: if lt == 'ShLib': - disable = _call_env_subst(env,'$SHLIBNOVERSIONSYMLINKS', *args, **kw) + disable = _call_env_subst(env, '$SHLIBNOVERSIONSYMLINKS', *args, **kw) elif lt == 'LdMod': - disable = _call_env_subst(env,'$LDMODULENOVERSIONSYMLINKS', *args, **kw) + disable = _call_env_subst(env, '$LDMODULENOVERSIONSYMLINKS', *args, **kw) else: - disable = _call_env_subst(env,'$IMPLIBNOVERSIONSYMLINKS', *args, **kw) + disable = _call_env_subst(env, '$IMPLIBNOVERSIONSYMLINKS', *args, **kw) return disable + class _LibInfoGeneratorBase(object): """Generator base class for library-related info such as suffixes for versioned libraries, symlink maps, sonames etc. It handles commonities of SharedLibrary and LoadableModule """ - _support_classes = { 'ShLib' : _ShLibInfoSupport, - 'LdMod' : _LdModInfoSupport, - 'ImpLib' : _ImpLibInfoSupport } + _support_classes = {'ShLib': _ShLibInfoSupport, + 'LdMod': _LdModInfoSupport, + 'ImpLib': _ImpLibInfoSupport} + def __init__(self, libtype, infoname): - self.set_libtype(libtype) - self.set_infoname(infoname) + self.libtype = libtype + self.infoname = infoname + + @property + def libtype(self): + return self._support.libtype - def set_libtype(self, libtype): + @libtype.setter + def libtype(self, libtype): try: support_class = self._support_classes[libtype] except KeyError: raise ValueError('unsupported libtype %r' % libtype) self._support = support_class() - def get_libtype(self): - return self._support.get_libtype() - - def set_infoname(self, infoname): - self.infoname = infoname - - def get_infoname(self): - return self.infoname - def get_lib_prefix(self, env, *args, **kw): - return self._support.get_lib_prefix(env,*args,**kw) + return self._support.get_lib_prefix(env, *args, **kw) def get_lib_suffix(self, env, *args, **kw): - return self._support.get_lib_suffix(env,*args,**kw) + return self._support.get_lib_suffix(env, *args, **kw) def get_lib_version(self, env, *args, **kw): - return self._support.get_lib_version(env,*args,**kw) + return self._support.get_lib_version(env, *args, **kw) def get_lib_noversionsymlinks(self, env, *args, **kw): - return self._support.get_lib_noversionsymlinks(env,*args,**kw) + return self._support.get_lib_noversionsymlinks(env, *args, **kw) # Returns name of generator linker callback that shall be used to generate # our info for a versioned library. For example, if our libtype is 'ShLib' # and infoname is 'Prefix', it would return 'VersionedShLibPrefix'. def get_versioned_lib_info_generator(self, **kw): - try: libtype = kw['generator_libtype'] - except KeyError: libtype = self.get_libtype() - infoname = self.get_infoname() - return 'Versioned%s%s' % (libtype, infoname) + try: + libtype = kw['generator_libtype'] + except KeyError: + libtype = self.libtype + return 'Versioned%s%s' % (libtype, self.infoname) - def generate_versioned_lib_info(self, env, args, result = None, **kw): + def generate_versioned_lib_info(self, env, args, result=None, **kw): callback = self.get_versioned_lib_info_generator(**kw) return _call_linker_cb(env, callback, args, result) + class _LibPrefixGenerator(_LibInfoGeneratorBase): """Library prefix generator, used as target_prefix in SharedLibrary and LoadableModule builders""" + def __init__(self, libtype): super(_LibPrefixGenerator, self).__init__(libtype, 'Prefix') - def __call__(self, env, sources = None, **kw): + def __call__(self, env, sources=None, **kw): Verbose = False if sources and 'source' not in kw: @@ -508,7 +548,7 @@ class _LibPrefixGenerator(_LibInfoGeneratorBase): else: kw2 = kw - prefix = self.get_lib_prefix(env,**kw2) + prefix = self.get_lib_prefix(env, **kw2) if Verbose: print("_LibPrefixGenerator: input prefix=%r" % prefix) @@ -523,17 +563,20 @@ class _LibPrefixGenerator(_LibInfoGeneratorBase): print("_LibPrefixGenerator: return prefix=%r" % prefix) return prefix -ShLibPrefixGenerator = _LibPrefixGenerator('ShLib') -LdModPrefixGenerator = _LibPrefixGenerator('LdMod') + +ShLibPrefixGenerator = _LibPrefixGenerator('ShLib') +LdModPrefixGenerator = _LibPrefixGenerator('LdMod') ImpLibPrefixGenerator = _LibPrefixGenerator('ImpLib') + class _LibSuffixGenerator(_LibInfoGeneratorBase): """Library suffix generator, used as target_suffix in SharedLibrary and LoadableModule builders""" + def __init__(self, libtype): super(_LibSuffixGenerator, self).__init__(libtype, 'Suffix') - def __call__(self, env, sources = None, **kw): + def __call__(self, env, sources=None, **kw): Verbose = False if sources and 'source' not in kw: @@ -557,13 +600,16 @@ class _LibSuffixGenerator(_LibInfoGeneratorBase): print("_LibSuffixGenerator: return suffix=%r" % suffix) return suffix -ShLibSuffixGenerator = _LibSuffixGenerator('ShLib') -LdModSuffixGenerator = _LibSuffixGenerator('LdMod') + +ShLibSuffixGenerator = _LibSuffixGenerator('ShLib') +LdModSuffixGenerator = _LibSuffixGenerator('LdMod') ImpLibSuffixGenerator = _LibSuffixGenerator('ImpLib') + class _LibSymlinkGenerator(_LibInfoGeneratorBase): """Library symlink map generator. It generates a list of symlinks that should be created by SharedLibrary or LoadableModule builders""" + def __init__(self, libtype): super(_LibSymlinkGenerator, self).__init__(libtype, 'Symlinks') @@ -588,18 +634,20 @@ class _LibSymlinkGenerator(_LibInfoGeneratorBase): print('_LibSymlinkGenerator: disable=%r' % disable) if version and not disable: - prefix = self.get_lib_prefix(env,**kw2) - suffix = self.get_lib_suffix(env,**kw2) + prefix = self.get_lib_prefix(env, **kw2) + suffix = self.get_lib_suffix(env, **kw2) symlinks = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) if Verbose: print('_LibSymlinkGenerator: return symlinks=%r' % StringizeLibSymlinks(symlinks)) return symlinks -ShLibSymlinkGenerator = _LibSymlinkGenerator('ShLib') -LdModSymlinkGenerator = _LibSymlinkGenerator('LdMod') + +ShLibSymlinkGenerator = _LibSymlinkGenerator('ShLib') +LdModSymlinkGenerator = _LibSymlinkGenerator('LdMod') ImpLibSymlinkGenerator = _LibSymlinkGenerator('ImpLib') + class _LibNameGenerator(_LibInfoGeneratorBase): """Generates "unmangled" library name from a library file node. @@ -614,6 +662,7 @@ class _LibNameGenerator(_LibInfoGeneratorBase): the _LibNameGenerator shall return "libfoo.so". Other link tools may implement it's own way of library name unmangling. """ + def __init__(self, libtype): super(_LibNameGenerator, self).__init__(libtype, 'Name') @@ -636,8 +685,8 @@ class _LibNameGenerator(_LibInfoGeneratorBase): name = None if version: - prefix = self.get_lib_prefix(env,**kw2) - suffix = self.get_lib_suffix(env,**kw2) + prefix = self.get_lib_prefix(env, **kw2) + suffix = self.get_lib_suffix(env, **kw2) name = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) if not name: @@ -648,13 +697,16 @@ class _LibNameGenerator(_LibInfoGeneratorBase): return name -ShLibNameGenerator = _LibNameGenerator('ShLib') -LdModNameGenerator = _LibNameGenerator('LdMod') + +ShLibNameGenerator = _LibNameGenerator('ShLib') +LdModNameGenerator = _LibNameGenerator('LdMod') ImpLibNameGenerator = _LibNameGenerator('ImpLib') + class _LibSonameGenerator(_LibInfoGeneratorBase): """Library soname generator. Returns library soname (e.g. libfoo.so.0) for a given node (e.g. /foo/bar/libfoo.so.0.1.2)""" + def __init__(self, libtype): super(_LibSonameGenerator, self).__init__(libtype, 'Soname') @@ -673,17 +725,17 @@ class _LibSonameGenerator(_LibInfoGeneratorBase): soname = _call_env_subst(env, '$SONAME', **kw2) if not soname: - version = self.get_lib_version(env,**kw2) + version = self.get_lib_version(env, **kw2) if Verbose: print("_LibSonameGenerator: version=%r" % version) if version: - prefix = self.get_lib_prefix(env,**kw2) - suffix = self.get_lib_suffix(env,**kw2) + prefix = self.get_lib_prefix(env, **kw2) + suffix = self.get_lib_suffix(env, **kw2) soname = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) if not soname: # fallback to library name (as returned by appropriate _LibNameGenerator) - soname = _LibNameGenerator(self.get_libtype())(env, libnode) + soname = _LibNameGenerator(self.libtype)(env, libnode) if Verbose: print("_LibSonameGenerator: FALLBACK: soname=%r" % soname) @@ -692,40 +744,44 @@ class _LibSonameGenerator(_LibInfoGeneratorBase): return soname -ShLibSonameGenerator = _LibSonameGenerator('ShLib') -LdModSonameGenerator = _LibSonameGenerator('LdMod') + +ShLibSonameGenerator = _LibSonameGenerator('ShLib') +LdModSonameGenerator = _LibSonameGenerator('LdMod') + def StringizeLibSymlinks(symlinks): """Converts list with pairs of nodes to list with pairs of node paths (strings). Used mainly for debugging.""" if SCons.Util.is_List(symlinks): try: - return [ (k.get_path(), v.get_path()) for k,v in symlinks ] + return [(k.get_path(), v.get_path()) for k, v in symlinks] except (TypeError, ValueError): return symlinks else: return symlinks + def EmitLibSymlinks(env, symlinks, libnode, **kw): """Used by emitters to handle (shared/versioned) library symlinks""" Verbose = False # nodes involved in process... all symlinks + library - nodes = list(set([ x for x,y in symlinks ] + [libnode])) + nodes = list(set([x for x, y in symlinks] + [libnode])) clean_targets = kw.get('clean_targets', []) if not SCons.Util.is_List(clean_targets): - clean_targets = [ clean_targets ] + clean_targets = [clean_targets] for link, linktgt in symlinks: env.SideEffect(link, linktgt) - if(Verbose): + if (Verbose): print("EmitLibSymlinks: SideEffect(%r,%r)" % (link.get_path(), linktgt.get_path())) clean_list = [x for x in nodes if x != linktgt] env.Clean(list(set([linktgt] + clean_targets)), clean_list) - if(Verbose): + if (Verbose): print("EmitLibSymlinks: Clean(%r,%r)" % (linktgt.get_path(), [x.get_path() for x in clean_list])) + def CreateLibSymlinks(env, symlinks): """Physically creates symlinks. The symlinks argument must be a list in form [ (link, linktarget), ... ], where link and linktarget are SCons @@ -736,38 +792,40 @@ def CreateLibSymlinks(env, symlinks): for link, linktgt in symlinks: linktgt = link.get_dir().rel_path(linktgt) link = link.get_path() - if(Verbose): + if (Verbose): print("CreateLibSymlinks: preparing to add symlink %r -> %r" % (link, linktgt)) # Delete the (previously created) symlink if exists. Let only symlinks # to be deleted to prevent accidental deletion of source files... if env.fs.islink(link): env.fs.unlink(link) - if(Verbose): + if (Verbose): print("CreateLibSymlinks: removed old symlink %r" % link) # If a file or directory exists with the same name as link, an OSError # will be thrown, which should be enough, I think. env.fs.symlink(linktgt, link) - if(Verbose): + if (Verbose): print("CreateLibSymlinks: add symlink %r -> %r" % (link, linktgt)) return 0 + def LibSymlinksActionFunction(target, source, env): for tgt in target: - symlinks = getattr(getattr(tgt,'attributes', None), 'shliblinks', None) + symlinks = getattr(getattr(tgt, 'attributes', None), 'shliblinks', None) if symlinks: CreateLibSymlinks(env, symlinks) return 0 + def LibSymlinksStrFun(target, source, env, *args): cmd = None for tgt in target: - symlinks = getattr(getattr(tgt,'attributes', None), 'shliblinks', None) + symlinks = getattr(getattr(tgt, 'attributes', None), 'shliblinks', None) if symlinks: if cmd is None: cmd = "" if cmd: cmd += "\n" cmd += "Create symlinks for: %r" % tgt.get_path() try: - linkstr = ', '.join([ "%r->%r" %(k,v) for k,v in StringizeLibSymlinks(symlinks)]) + linkstr = ', '.join(["%r->%r" % (k, v) for k, v in StringizeLibSymlinks(symlinks)]) except (KeyError, ValueError): pass else: @@ -789,20 +847,21 @@ def createSharedLibBuilder(env): shared_lib = env['BUILDERS']['SharedLibrary'] except KeyError: import SCons.Defaults - action_list = [ SCons.Defaults.SharedCheck, - SCons.Defaults.ShLinkAction, - LibSymlinksAction ] - shared_lib = SCons.Builder.Builder(action = action_list, - emitter = "$SHLIBEMITTER", - prefix = ShLibPrefixGenerator, - suffix = ShLibSuffixGenerator, - target_scanner = ProgramScanner, - src_suffix = '$SHOBJSUFFIX', - src_builder = 'SharedObject') + action_list = [SCons.Defaults.SharedCheck, + SCons.Defaults.ShLinkAction, + LibSymlinksAction] + shared_lib = SCons.Builder.Builder(action=action_list, + emitter="$SHLIBEMITTER", + prefix=ShLibPrefixGenerator, + suffix=ShLibSuffixGenerator, + target_scanner=ProgramScanner, + src_suffix='$SHOBJSUFFIX', + src_builder='SharedObject') env['BUILDERS']['SharedLibrary'] = shared_lib return shared_lib + def createLoadableModuleBuilder(env): """This is a utility function that creates the LoadableModule Builder in an Environment if it is not there already. @@ -814,20 +873,21 @@ def createLoadableModuleBuilder(env): ld_module = env['BUILDERS']['LoadableModule'] except KeyError: import SCons.Defaults - action_list = [ SCons.Defaults.SharedCheck, - SCons.Defaults.LdModuleLinkAction, - LibSymlinksAction ] - ld_module = SCons.Builder.Builder(action = action_list, - emitter = "$LDMODULEEMITTER", - prefix = LdModPrefixGenerator, - suffix = LdModSuffixGenerator, - target_scanner = ProgramScanner, - src_suffix = '$SHOBJSUFFIX', - src_builder = 'SharedObject') + action_list = [SCons.Defaults.SharedCheck, + SCons.Defaults.LdModuleLinkAction, + LibSymlinksAction] + ld_module = SCons.Builder.Builder(action=action_list, + emitter="$LDMODULEEMITTER", + prefix=LdModPrefixGenerator, + suffix=LdModSuffixGenerator, + target_scanner=ProgramScanner, + src_suffix='$SHOBJSUFFIX', + src_builder='SharedObject') env['BUILDERS']['LoadableModule'] = ld_module return ld_module + def createObjBuilders(env): """This is a utility function that creates the StaticObject and SharedObject Builders in an Environment if they @@ -841,34 +901,34 @@ def createObjBuilders(env): The return is a 2-tuple of (StaticObject, SharedObject) """ - try: static_obj = env['BUILDERS']['StaticObject'] except KeyError: - static_obj = SCons.Builder.Builder(action = {}, - emitter = {}, - prefix = '$OBJPREFIX', - suffix = '$OBJSUFFIX', - src_builder = ['CFile', 'CXXFile'], - source_scanner = SourceFileScanner, - single_source = 1) + static_obj = SCons.Builder.Builder(action={}, + emitter={}, + prefix='$OBJPREFIX', + suffix='$OBJSUFFIX', + src_builder=['CFile', 'CXXFile'], + source_scanner=SourceFileScanner, + single_source=1) env['BUILDERS']['StaticObject'] = static_obj env['BUILDERS']['Object'] = static_obj try: shared_obj = env['BUILDERS']['SharedObject'] except KeyError: - shared_obj = SCons.Builder.Builder(action = {}, - emitter = {}, - prefix = '$SHOBJPREFIX', - suffix = '$SHOBJSUFFIX', - src_builder = ['CFile', 'CXXFile'], - source_scanner = SourceFileScanner, - single_source = 1) + shared_obj = SCons.Builder.Builder(action={}, + emitter={}, + prefix='$SHOBJPREFIX', + suffix='$SHOBJSUFFIX', + src_builder=['CFile', 'CXXFile'], + source_scanner=SourceFileScanner, + single_source=1) env['BUILDERS']['SharedObject'] = shared_obj return (static_obj, shared_obj) + def createCFileBuilders(env): """This is a utility function that creates the CFile/CXXFile Builders in an Environment if they @@ -885,95 +945,109 @@ def createCFileBuilders(env): try: c_file = env['BUILDERS']['CFile'] except KeyError: - c_file = SCons.Builder.Builder(action = {}, - emitter = {}, - suffix = {None:'$CFILESUFFIX'}) + c_file = SCons.Builder.Builder(action={}, + emitter={}, + suffix={None: '$CFILESUFFIX'}) env['BUILDERS']['CFile'] = c_file - env.SetDefault(CFILESUFFIX = '.c') + env.SetDefault(CFILESUFFIX='.c') try: cxx_file = env['BUILDERS']['CXXFile'] except KeyError: - cxx_file = SCons.Builder.Builder(action = {}, - emitter = {}, - suffix = {None:'$CXXFILESUFFIX'}) + cxx_file = SCons.Builder.Builder(action={}, + emitter={}, + suffix={None: '$CXXFILESUFFIX'}) env['BUILDERS']['CXXFile'] = cxx_file - env.SetDefault(CXXFILESUFFIX = '.cc') + env.SetDefault(CXXFILESUFFIX='.cc') return (c_file, cxx_file) + ########################################################################## # Create common Java builders def CreateJarBuilder(env): + """The Jar builder expects a list of class files + which it can package into a jar file. + + The jar tool provides an interface for passing other types + of java files such as .java, directories or swig interfaces + and will build them to class files in which it can package + into the jar. + """ try: - java_jar = env['BUILDERS']['Jar'] + java_jar = env['BUILDERS']['JarFile'] except KeyError: fs = SCons.Node.FS.get_default_fs() jar_com = SCons.Action.Action('$JARCOM', '$JARCOMSTR') - java_jar = SCons.Builder.Builder(action = jar_com, - suffix = '$JARSUFFIX', - src_suffix = '$JAVACLASSSUFFIX', - src_builder = 'JavaClassFile', - source_factory = fs.Entry) - env['BUILDERS']['Jar'] = java_jar + java_jar = SCons.Builder.Builder(action=jar_com, + suffix='$JARSUFFIX', + src_suffix='$JAVACLASSSUFFIX', + src_builder='JavaClassFile', + source_factory=fs.Entry) + env['BUILDERS']['JarFile'] = java_jar return java_jar + def CreateJavaHBuilder(env): try: java_javah = env['BUILDERS']['JavaH'] except KeyError: fs = SCons.Node.FS.get_default_fs() java_javah_com = SCons.Action.Action('$JAVAHCOM', '$JAVAHCOMSTR') - java_javah = SCons.Builder.Builder(action = java_javah_com, - src_suffix = '$JAVACLASSSUFFIX', - target_factory = fs.Entry, - source_factory = fs.File, - src_builder = 'JavaClassFile') + java_javah = SCons.Builder.Builder(action=java_javah_com, + src_suffix='$JAVACLASSSUFFIX', + target_factory=fs.Entry, + source_factory=fs.File, + src_builder='JavaClassFile') env['BUILDERS']['JavaH'] = java_javah return java_javah + def CreateJavaClassFileBuilder(env): try: java_class_file = env['BUILDERS']['JavaClassFile'] except KeyError: fs = SCons.Node.FS.get_default_fs() javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR') - java_class_file = SCons.Builder.Builder(action = javac_com, - emitter = {}, - #suffix = '$JAVACLASSSUFFIX', - src_suffix = '$JAVASUFFIX', - src_builder = ['JavaFile'], - target_factory = fs.Entry, - source_factory = fs.File) + java_class_file = SCons.Builder.Builder(action=javac_com, + emitter={}, + # suffix = '$JAVACLASSSUFFIX', + src_suffix='$JAVASUFFIX', + src_builder=['JavaFile'], + target_factory=fs.Entry, + source_factory=fs.File) env['BUILDERS']['JavaClassFile'] = java_class_file return java_class_file + def CreateJavaClassDirBuilder(env): try: java_class_dir = env['BUILDERS']['JavaClassDir'] except KeyError: fs = SCons.Node.FS.get_default_fs() javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR') - java_class_dir = SCons.Builder.Builder(action = javac_com, - emitter = {}, - target_factory = fs.Dir, - source_factory = fs.Dir) + java_class_dir = SCons.Builder.Builder(action=javac_com, + emitter={}, + target_factory=fs.Dir, + source_factory=fs.Dir) env['BUILDERS']['JavaClassDir'] = java_class_dir return java_class_dir + def CreateJavaFileBuilder(env): try: java_file = env['BUILDERS']['JavaFile'] except KeyError: - java_file = SCons.Builder.Builder(action = {}, - emitter = {}, - suffix = {None:'$JAVASUFFIX'}) + java_file = SCons.Builder.Builder(action={}, + emitter={}, + suffix={None: '$JAVASUFFIX'}) env['BUILDERS']['JavaFile'] = java_file env['JAVASUFFIX'] = '.java' return java_file + class ToolInitializerMethod(object): """ This is added to a construction environment in place of a @@ -984,6 +1058,7 @@ class ToolInitializerMethod(object): whatever builder was (presumably) added to the construction environment in place of this particular instance. """ + def __init__(self, name, initializer): """ Note: we store the tool name as __name__ so it can be used by @@ -1022,6 +1097,7 @@ class ToolInitializerMethod(object): return [], [] return builder(*args, **kw) + class ToolInitializer(object): """ A class for delayed initialization of Tools modules. @@ -1033,6 +1109,7 @@ class ToolInitializer(object): ToolInitializerMethod objects for the various Builder methods that we want to use to delay Tool searches until necessary. """ + def __init__(self, env, tools, names): if not SCons.Util.is_List(tools): tools = [tools] @@ -1067,24 +1144,30 @@ class ToolInitializer(object): env.Tool(tool) return - # If we fall through here, there was no tool module found. - # This is where we can put an informative error message - # about the inability to find the tool. We'll start doing - # this as we cut over more pre-defined Builder+Tools to use - # the ToolInitializer class. + # If we fall through here, there was no tool module found. + # This is where we can put an informative error message + # about the inability to find the tool. We'll start doing + # this as we cut over more pre-defined Builder+Tools to use + # the ToolInitializer class. + def Initializers(env): ToolInitializer(env, ['install'], ['_InternalInstall', '_InternalInstallAs', '_InternalInstallVersionedLib']) + def Install(self, *args, **kw): return self._InternalInstall(*args, **kw) + def InstallAs(self, *args, **kw): return self._InternalInstallAs(*args, **kw) + def InstallVersionedLib(self, *args, **kw): return self._InternalInstallVersionedLib(*args, **kw) + env.AddMethod(Install) env.AddMethod(InstallAs) env.AddMethod(InstallVersionedLib) + def FindTool(tools, env): for tool in tools: t = Tool(tool) @@ -1092,14 +1175,16 @@ def FindTool(tools, env): return tool return None + def FindAllTools(tools, env): def ToolExists(tool, env=env): return Tool(tool).exists(env) - return list(filter (ToolExists, tools)) -def tool_list(platform, env): + return list(filter(ToolExists, tools)) - other_plat_tools=[] + +def tool_list(platform, env): + other_plat_tools = [] # XXX this logic about what tool to prefer on which platform # should be moved into either the platform files or # the tool files themselves. @@ -1107,21 +1192,21 @@ def tool_list(platform, env): # change these search orders, update the man page as well. if str(platform) == 'win32': "prefer Microsoft tools on Windows" - linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ] - c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32' ] - cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'cxx', 'bcc32' ] - assemblers = ['masm', 'nasm', 'gas', '386asm' ] + linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32'] + c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32'] + cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'cxx', 'bcc32'] + assemblers = ['masm', 'nasm', 'gas', '386asm'] fortran_compilers = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran'] ars = ['mslib', 'ar', 'tlib'] other_plat_tools = ['msvs', 'midl'] elif str(platform) == 'os2': "prefer IBM tools on OS/2" - linkers = ['ilink', 'gnulink', ]#'mslink'] - c_compilers = ['icc', 'gcc',]# 'msvc', 'cc'] - cxx_compilers = ['icc', 'g++',]# 'msvc', 'cxx'] - assemblers = ['nasm',]# 'masm', 'gas'] + linkers = ['ilink', 'gnulink', ] # 'mslink'] + c_compilers = ['icc', 'gcc', ] # 'msvc', 'cc'] + cxx_compilers = ['icc', 'g++', ] # 'msvc', 'cxx'] + assemblers = ['nasm', ] # 'masm', 'gas'] fortran_compilers = ['ifl', 'g77'] - ars = ['ar',]# 'mslib'] + ars = ['ar', ] # 'mslib'] elif str(platform) == 'irix': "prefer MIPSPro on IRIX" linkers = ['sgilink', 'gnulink'] @@ -1174,11 +1259,11 @@ def tool_list(platform, env): else: "prefer GNU tools on all other platforms" linkers = ['gnulink', 'ilink'] - c_compilers = ['gcc', 'intelc', 'icc', 'cc'] + c_compilers = ['gcc', 'intelc', 'icc', 'cc'] cxx_compilers = ['g++', 'intelc', 'icc', 'cxx'] assemblers = ['gas', 'nasm', 'masm'] fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77'] - ars = ['ar',] + ars = ['ar', ] if not str(platform) == 'win32': other_plat_tools += ['m4', 'rpm'] @@ -1210,22 +1295,24 @@ def tool_list(platform, env): d_compiler = FindTool(d_compilers, env) or d_compilers[0] other_tools = FindAllTools(other_plat_tools + [ - #TODO: merge 'install' into 'filesystem' and - # make 'filesystem' the default - 'filesystem', - 'wix', #'midl', 'msvs', - # Parser generators - 'lex', 'yacc', - # Foreign function interface - 'rpcgen', 'swig', - # Java - 'jar', 'javac', 'javah', 'rmic', - # TeX - 'dvipdf', 'dvips', 'gs', - 'tex', 'latex', 'pdflatex', 'pdftex', - # Archivers - 'tar', 'zip', - ], env) + # TODO: merge 'install' into 'filesystem' and + # make 'filesystem' the default + 'filesystem', + 'wix', # 'midl', 'msvs', + # Parser generators + 'lex', 'yacc', + # Foreign function interface + 'rpcgen', 'swig', + # Java + 'jar', 'javac', 'javah', 'rmic', + # TeX + 'dvipdf', 'dvips', 'gs', + 'tex', 'latex', 'pdflatex', 'pdftex', + # Archivers + 'tar', 'zip', + # File builders (text) + 'textfile', + ], env) tools = ([linker, c_compiler, cxx_compiler, fortran_compiler, assembler, ar, d_compiler] @@ -1233,6 +1320,38 @@ def tool_list(platform, env): return [x for x in tools if x] + +def find_program_path(env, key_program, default_paths=None): + """ + Find the location of a tool using various means. + + Mainly for windows where tools aren't all installed in /usr/bin, etc. + + :param env: Current Construction Environment. + :param key_program: Tool to locate. + :param default_paths: List of additional paths this tool might be found in. + """ + # First search in the SCons path + path = env.WhereIs(key_program) + if path: + return path + + # Then in the OS path + path = SCons.Util.WhereIs(key_program) + if path: + return path + + # Finally, add the defaults and check again. Do not change + # ['ENV']['PATH'] permananetly, the caller can do that if needed. + if default_paths is None: + return path + save_path = env['ENV']['PATH'] + for p in default_paths: + env.AppendENVPath('PATH', p) + path = env.WhereIs(key_program) + env['ENV']['PATH'] = save_path + return path + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/Tool/__init__.xml b/src/engine/SCons/Tool/__init__.xml index 32b8ce6..80fd2f6 100644 --- a/src/engine/SCons/Tool/__init__.xml +++ b/src/engine/SCons/Tool/__init__.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/aixc++.py b/src/engine/SCons/Tool/aixc++.py index 0a2465d..bafaea4 100644 --- a/src/engine/SCons/Tool/aixc++.py +++ b/src/engine/SCons/Tool/aixc++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixc++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixc++.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" #forward proxy to the preffered cxx version from SCons.Tool.aixcxx import * diff --git a/src/engine/SCons/Tool/aixc++.xml b/src/engine/SCons/Tool/aixc++.xml index 04a27f6..0d50ae9 100644 --- a/src/engine/SCons/Tool/aixc++.xml +++ b/src/engine/SCons/Tool/aixc++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/aixcc.py b/src/engine/SCons/Tool/aixcc.py index aa351cd..349a40a 100644 --- a/src/engine/SCons/Tool/aixcc.py +++ b/src/engine/SCons/Tool/aixcc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixcc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixcc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path diff --git a/src/engine/SCons/Tool/aixcc.xml b/src/engine/SCons/Tool/aixcc.xml index 44ee0bc..aa0e604 100644 --- a/src/engine/SCons/Tool/aixcc.xml +++ b/src/engine/SCons/Tool/aixcc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/aixcxx.py b/src/engine/SCons/Tool/aixcxx.py index 97bd8a6..0830e33 100644 --- a/src/engine/SCons/Tool/aixcxx.py +++ b/src/engine/SCons/Tool/aixcxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixcxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixcxx.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path diff --git a/src/engine/SCons/Tool/aixf77.py b/src/engine/SCons/Tool/aixf77.py index c72346c..d2c619a 100644 --- a/src/engine/SCons/Tool/aixf77.py +++ b/src/engine/SCons/Tool/aixf77.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixf77.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixf77.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path diff --git a/src/engine/SCons/Tool/aixf77.xml b/src/engine/SCons/Tool/aixf77.xml index 69f4d92..ee4d232 100644 --- a/src/engine/SCons/Tool/aixf77.xml +++ b/src/engine/SCons/Tool/aixf77.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/aixlink.py b/src/engine/SCons/Tool/aixlink.py index fd67d66..ea2949f 100644 --- a/src/engine/SCons/Tool/aixlink.py +++ b/src/engine/SCons/Tool/aixlink.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixlink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixlink.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import os.path diff --git a/src/engine/SCons/Tool/aixlink.xml b/src/engine/SCons/Tool/aixlink.xml index d5438ef..0f7fc62 100644 --- a/src/engine/SCons/Tool/aixlink.xml +++ b/src/engine/SCons/Tool/aixlink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/applelink.py b/src/engine/SCons/Tool/applelink.py index 45f524c..011b29d 100644 --- a/src/engine/SCons/Tool/applelink.py +++ b/src/engine/SCons/Tool/applelink.py @@ -1,6 +1,6 @@ """SCons.Tool.applelink -Tool-specific initialization for the Apple gnu-like linker. +Tool-specific initialization for Apple's gnu-like linker. There normally shouldn't be any need to import this module directly. It will usually be imported through the generic SCons.Tool.Tool() @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/applelink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/applelink.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util @@ -39,25 +39,162 @@ import SCons.Util # the -rpath option, so we use the "link" tool instead of "gnulink". from . import link + +class AppleLinkInvalidCurrentVersionException(Exception): + pass + +class AppleLinkInvalidCompatibilityVersionException(Exception): + pass + + +def _applelib_versioned_lib_suffix(env, suffix, version): + """For suffix='.dylib' and version='0.1.2' it returns '.0.1.2.dylib'""" + Verbose = False + if Verbose: + print("_applelib_versioned_lib_suffix: suffix={!r}".format(suffix)) + print("_applelib_versioned_lib_suffix: version={!r}".format(version)) + if version not in suffix: + suffix = "." + version + suffix + if Verbose: + print("_applelib_versioned_lib_suffix: return suffix={!r}".format(suffix)) + return suffix + + +def _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, name_func): + """For libnode='/optional/dir/libfoo.X.Y.Z.dylib' it returns 'libfoo.X.dylib'""" + Verbose = False + if Verbose: + print("_applelib_versioned_lib_soname: version={!r}".format(version)) + name = name_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_applelib_versioned_lib_soname: name={!r}".format(name)) + major = version.split('.')[0] + (libname,_suffix) = name.split('.') + soname = '.'.join([libname, major, _suffix]) + if Verbose: + print("_applelib_versioned_lib_soname: soname={!r}".format(soname)) + return soname + +def _applelib_versioned_shlib_soname(env, libnode, version, prefix, suffix): + return _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, link._versioned_shlib_name) + + +# User programmatically describes how SHLIBVERSION maps to values for compat/current. +_applelib_max_version_values = (65535, 255, 255) +def _applelib_check_valid_version(version_string): + """ + Check that the version # is valid. + X[.Y[.Z]] + where X 0-65535 + where Y either not specified or 0-255 + where Z either not specified or 0-255 + :param version_string: + :return: + """ + parts = version_string.split('.') + if len(parts) > 3: + return False, "Version string has too many periods [%s]"%version_string + if len(parts) <= 0: + return False, "Version string unspecified [%s]"%version_string + + for (i, p) in enumerate(parts): + try: + p_i = int(p) + except ValueError: + return False, "Version component %s (from %s) is not a number"%(p, version_string) + if p_i < 0 or p_i > _applelib_max_version_values[i]: + return False, "Version component %s (from %s) is not valid value should be between 0 and %d"%(p, version_string, _applelib_max_version_values[i]) + + return True, "" + + +def _applelib_currentVersionFromSoVersion(source, target, env, for_signature): + """ + A generator function to create the -Wl,-current_version flag if needed. + If env['APPLELINK_NO_CURRENT_VERSION'] contains a true value no flag will be generated + Otherwise if APPLELINK_CURRENT_VERSION is not specified, env['SHLIBVERSION'] + will be used. + + :param source: + :param target: + :param env: + :param for_signature: + :return: A string providing the flag to specify the current_version of the shared library + """ + if env.get('APPLELINK_NO_CURRENT_VERSION', False): + return "" + elif env.get('APPLELINK_CURRENT_VERSION', False): + version_string = env['APPLELINK_CURRENT_VERSION'] + elif env.get('SHLIBVERSION', False): + version_string = env['SHLIBVERSION'] + else: + return "" + + version_string = ".".join(version_string.split('.')[:3]) + + valid, reason = _applelib_check_valid_version(version_string) + if not valid: + raise AppleLinkInvalidCurrentVersionException(reason) + + return "-Wl,-current_version,%s" % version_string + + +def _applelib_compatVersionFromSoVersion(source, target, env, for_signature): + """ + A generator function to create the -Wl,-compatibility_version flag if needed. + If env['APPLELINK_NO_COMPATIBILITY_VERSION'] contains a true value no flag will be generated + Otherwise if APPLELINK_COMPATIBILITY_VERSION is not specified + the first two parts of env['SHLIBVERSION'] will be used with a .0 appended. + + :param source: + :param target: + :param env: + :param for_signature: + :return: A string providing the flag to specify the compatibility_version of the shared library + """ + if env.get('APPLELINK_NO_COMPATIBILITY_VERSION', False): + return "" + elif env.get('APPLELINK_COMPATIBILITY_VERSION', False): + version_string = env['APPLELINK_COMPATIBILITY_VERSION'] + elif env.get('SHLIBVERSION', False): + version_string = ".".join(env['SHLIBVERSION'].split('.')[:2] + ['0']) + else: + return "" + + if version_string is None: + return "" + + valid, reason = _applelib_check_valid_version(version_string) + if not valid: + raise AppleLinkInvalidCompatibilityVersionException(reason) + + return "-Wl,-compatibility_version,%s" % version_string + + def generate(env): """Add Builders and construction variables for applelink to an Environment.""" link.generate(env) env['FRAMEWORKPATHPREFIX'] = '-F' - env['_FRAMEWORKPATH'] = '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__)}' + env['_FRAMEWORKPATH'] = '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__, RDirs)}' + env['_FRAMEWORKS'] = '${_concat("-framework ", FRAMEWORKS, "", __env__)}' env['LINKCOM'] = env['LINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -dynamiclib') env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' - # TODO: Work needed to generate versioned shared libraries - # Leaving this commented out, and also going to disable versioned library checking for now # see: http://docstore.mik.ua/orelly/unix3/mac/ch05_04.htm for proper naming - #link._setup_versioned_lib_variables(env, tool = 'applelink')#, use_soname = use_soname) - #env['LINKCALLBACKS'] = link._versioned_lib_callbacks() + link._setup_versioned_lib_variables(env, tool = 'applelink')#, use_soname = use_soname) + env['LINKCALLBACKS'] = link._versioned_lib_callbacks() + env['LINKCALLBACKS']['VersionedShLibSuffix'] = _applelib_versioned_lib_suffix + env['LINKCALLBACKS']['VersionedShLibSoname'] = _applelib_versioned_shlib_soname + env['_APPLELINK_CURRENT_VERSION'] = _applelib_currentVersionFromSoVersion + env['_APPLELINK_COMPATIBILITY_VERSION'] = _applelib_compatVersionFromSoVersion + env['_SHLIBVERSIONFLAGS'] = '$_APPLELINK_CURRENT_VERSION $_APPLELINK_COMPATIBILITY_VERSION ' + env['_LDMODULEVERSIONFLAGS'] = '$_APPLELINK_CURRENT_VERSION $_APPLELINK_COMPATIBILITY_VERSION ' # override the default for loadable modules, which are different # on OS X than dynamic shared libs. echoing what XCode does for @@ -67,6 +204,8 @@ def generate(env): env['LDMODULEFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -bundle') env['LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' + env['__SHLIBVERSIONFLAGS'] = '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}' + def exists(env): diff --git a/src/engine/SCons/Tool/applelink.xml b/src/engine/SCons/Tool/applelink.xml index 699abf0..c7209fa 100644 --- a/src/engine/SCons/Tool/applelink.xml +++ b/src/engine/SCons/Tool/applelink.xml @@ -1,155 +1,254 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. --> <!DOCTYPE sconsdoc [ -<!ENTITY % scons SYSTEM '../../../../doc/scons.mod'> -%scons; -<!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'> -%builders-mod; -<!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'> -%functions-mod; -<!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'> -%tools-mod; -<!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'> -%variables-mod; -]> + <!ENTITY % scons SYSTEM '../../../../doc/scons.mod'> + %scons; + <!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'> + %builders-mod; + <!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'> + %functions-mod; + <!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'> + %tools-mod; + <!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'> + %variables-mod; + ]> <sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd"> -<tool name="applelink"> -<summary> -<para> -Sets construction variables for the Apple linker -(similar to the GNU linker). -</para> -</summary> -<sets> -<item>FRAMEWORKPATHPREFIX</item> -<item>_FRAMEWORKPATH</item> -<item>_FRAMEWORKS</item> -<item>LINKCOM</item> -<item>SHLINKFLAGS</item> -<item>SHLINKCOM</item> -<item>LDMODULEPREFIX</item> -<item>LDMODULESUFFIX</item> -<item>LDMODULEFLAGS</item> -<item>LDMODULECOM</item> -</sets> -<uses> -<item>FRAMEWORKSFLAGS</item> -</uses> -</tool> - -<cvar name="FRAMEWORKSFLAGS">"> -<summary> -<para> -On Mac OS X with gcc, -general user-supplied frameworks options to be added at -the end of a command -line building a loadable module. -(This has been largely superseded by -the &cv-link-FRAMEWORKPATH;, &cv-link-FRAMEWORKPATHPREFIX;, -&cv-link-FRAMEWORKPREFIX; and &cv-link-FRAMEWORKS; variables -described above.) -</para> -</summary> -</cvar> - -<cvar name="FRAMEWORKS"> -<summary> -<para> -On Mac OS X with gcc, a list of the framework names to be linked into a -program or shared library or bundle. -The default value is the empty list. -For example: -</para> - -<example_commands> - env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) -</example_commands> - -</summary> -</cvar> - -<cvar name="FRAMEWORKPREFIX"> -<summary> -<para> -On Mac OS X with gcc, -the prefix to be used for linking in frameworks -(see &cv-link-FRAMEWORKS;). -The default value is -<option>-framework</option>. -</para> -</summary> -</cvar> - -<cvar name="_FRAMEWORKS"> -<summary> -<para> -On Mac OS X with gcc, -an automatically-generated construction variable -containing the linker command-line options -for linking with FRAMEWORKS. -</para> -</summary> -</cvar> - -<cvar name="FRAMEWORKPATH"> -<summary> -<para> -On Mac OS X with gcc, -a list containing the paths to search for frameworks. -Used by the compiler to find framework-style includes like -#include <Fmwk/Header.h>. -Used by the linker to find user-specified frameworks when linking (see -&cv-link-FRAMEWORKS;). -For example: -</para> - -<example_commands> - env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') -</example_commands> - -<para> -will add -</para> - -<example_commands> - ... -Fmyframeworkdir -</example_commands> - -<para> -to the compiler and linker command lines. -</para> -</summary> -</cvar> - -<cvar name="FRAMEWORKPATHPREFIX"> -<summary> -<para> -On Mac OS X with gcc, the prefix to be used for the FRAMEWORKPATH entries. -(see &cv-link-FRAMEWORKPATH;). -The default value is -<option>-F</option>. -</para> -</summary> -</cvar> - -<cvar name="_FRAMEWORKPATH"> -<summary> -<para> -On Mac OS X with gcc, an automatically-generated construction variable -containing the linker command-line options corresponding to -&cv-link-FRAMEWORKPATH;. -</para> -</summary> -</cvar> + <tool name="applelink"> + <summary> + <para> + Sets construction variables for the Apple linker + (similar to the GNU linker). + </para> + </summary> + <sets> + <item>FRAMEWORKPATHPREFIX</item> + <item>_FRAMEWORKPATH</item> + <item>_FRAMEWORKS</item> + <item>LINKCOM</item> + <item>SHLINKFLAGS</item> + <item>SHLINKCOM</item> + <item>LDMODULEPREFIX</item> + <item>LDMODULESUFFIX</item> + <item>LDMODULEFLAGS</item> + <item>LDMODULECOM</item> + <item>APPLELINK_CURRENT_VERSION</item> + <item>APPLELINK_COMPATIBILITY_VERSION</item> + <item>APPLELINK_NO_CURRENT_VERSION</item> + <item>APPLELINK_NO_COMPATIBILITY_VERSION</item> + <item>_APPLELINK_CURRENT_VERSION</item> + <item>_APPLELINK_COMPATIBILITY_VERSION</item> + </sets> + <uses> + <item>FRAMEWORKSFLAGS</item> + </uses> + </tool> + + + <cvar name="APPLELINK_COMPATIBILITY_VERSION"> + <summary> + <para> + On Mac OS X this is used to set the linker flag: + + -compatibility_version + </para> + <para> + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and + 255, Z can be omitted or between 1 and 255. This value will be derived from &cv-link-SHLIBVERSION; if + not + specified. The lowest digit will be dropped and replaced by a 0. + </para> + <para> + If the &cv-link-APPLELINK_NO_COMPATIBILITY_VERSION; is set then no -compatibility_version will be + output. + </para> + <para>See MacOS's ld manpage for more details</para> + </summary> + </cvar> + + <cvar name="APPLELINK_NO_COMPATIBILITY_VERSION"> + <summary> + <para> + Set this to any True (1|True|non-empty string) value to disable adding -compatibility_version flag when + generating versioned shared libraries. + </para> + <para> + This overrides &cv-link-APPLELINK_COMPATIBILITY_VERSION;. + </para> + </summary> + </cvar> + + + <cvar name="_APPLELINK_COMPATIBILITY_VERSION"> + <summary> + <para> + A macro (by default a generator function) used to create the linker flags to specify + apple's linker's -compatibility_version flag. + The default generator uses &cv-link-APPLELINK_COMPATIBILITY_VERSION; + and &cv-link-APPLELINK_NO_COMPATIBILITY_VERSION; and &cv-link-SHLIBVERSION; + to determine the correct flag. + </para> + </summary> + </cvar> + + + <cvar name="APPLELINK_CURRENT_VERSION"> + <summary> + <para> + On Mac OS X this is used to set the linker flag: + + -current_version + </para> + <para> + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and + 255, Z can be omitted or between 1 and 255. This value will be set to &cv-link-SHLIBVERSION; if not + specified. + </para> + <para> + If the &cv-link-APPLELINK_NO_CURRENT_VERSION; is set then no -current_version will be + output. + </para> + <para>See MacOS's ld manpage for more details</para> + + </summary> + </cvar> + + + <cvar name="APPLELINK_NO_CURRENT_VERSION"> + <summary> + <para> + Set this to any True (1|True|non-empty string) value to disable adding -current_version flag when + generating versioned shared libraries. + </para> + <para> + This overrides &cv-link-APPLELINK_CURRENT_VERSION;. + </para> + </summary> + </cvar> + + <cvar name="_APPLELINK_CURRENT_VERSION"> + <summary> + <para> + A macro (by default a generator function) used to create the linker flags to specify apple's linker's + -current_version flag. The default generator uses &cv-link-APPLELINK_CURRENT_VERSION; and + &cv-link-APPLELINK_NO_CURRENT_VERSION; and &cv-link-SHLIBVERSION; to determine the correct flag. + </para> + </summary> + </cvar> + + + <cvar name="FRAMEWORKSFLAGS">"> + <summary> + <para> + On Mac OS X with gcc, + general user-supplied frameworks options to be added at + the end of a command + line building a loadable module. + (This has been largely superseded by + the &cv-link-FRAMEWORKPATH;, &cv-link-FRAMEWORKPATHPREFIX;, + &cv-link-FRAMEWORKPREFIX; and &cv-link-FRAMEWORKS; variables + described above.) + </para> + </summary> + </cvar> + + <cvar name="FRAMEWORKS"> + <summary> + <para> + On Mac OS X with gcc, a list of the framework names to be linked into a + program or shared library or bundle. + The default value is the empty list. + For example: + </para> + + <example_commands> + env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) + </example_commands> + + </summary> + </cvar> + + <cvar name="FRAMEWORKPREFIX"> + <summary> + <para> + On Mac OS X with gcc, + the prefix to be used for linking in frameworks + (see &cv-link-FRAMEWORKS;). + The default value is + <option>-framework</option>. + </para> + </summary> + </cvar> + + <cvar name="_FRAMEWORKS"> + <summary> + <para> + On Mac OS X with gcc, + an automatically-generated construction variable + containing the linker command-line options + for linking with FRAMEWORKS. + </para> + </summary> + </cvar> + + <cvar name="FRAMEWORKPATH"> + <summary> + <para> + On Mac OS X with gcc, + a list containing the paths to search for frameworks. + Used by the compiler to find framework-style includes like + #include <Fmwk/Header.h>. + Used by the linker to find user-specified frameworks when linking (see + &cv-link-FRAMEWORKS;). + For example: + </para> + + <example_commands> + env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') + </example_commands> + + <para> + will add + </para> + + <example_commands> + ... -Fmyframeworkdir + </example_commands> + + <para> + to the compiler and linker command lines. + </para> + </summary> + </cvar> + + <cvar name="FRAMEWORKPATHPREFIX"> + <summary> + <para> + On Mac OS X with gcc, the prefix to be used for the FRAMEWORKPATH entries. + (see &cv-link-FRAMEWORKPATH;). + The default value is + <option>-F</option>. + </para> + </summary> + </cvar> + + <cvar name="_FRAMEWORKPATH"> + <summary> + <para> + On Mac OS X with gcc, an automatically-generated construction variable + containing the linker command-line options corresponding to + &cv-link-FRAMEWORKPATH;. + </para> + </summary> + </cvar> </sconsdoc> diff --git a/src/engine/SCons/Tool/ar.py b/src/engine/SCons/Tool/ar.py index 4d2a005..459fb55 100644 --- a/src/engine/SCons/Tool/ar.py +++ b/src/engine/SCons/Tool/ar.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ar.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/ar.xml b/src/engine/SCons/Tool/ar.xml index 9b9e0a0..573c80b 100644 --- a/src/engine/SCons/Tool/ar.xml +++ b/src/engine/SCons/Tool/ar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/as.py b/src/engine/SCons/Tool/as.py index ab81b89..02139c5 100644 --- a/src/engine/SCons/Tool/as.py +++ b/src/engine/SCons/Tool/as.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/as.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/as.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/as.xml b/src/engine/SCons/Tool/as.xml index f4d886d..c2d1814 100644 --- a/src/engine/SCons/Tool/as.xml +++ b/src/engine/SCons/Tool/as.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/bcc32.py b/src/engine/SCons/Tool/bcc32.py index bf0a5dd..e8ffbbf 100644 --- a/src/engine/SCons/Tool/bcc32.py +++ b/src/engine/SCons/Tool/bcc32.py @@ -5,7 +5,7 @@ XXX """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ XXX # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/bcc32.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/bcc32.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import os.path diff --git a/src/engine/SCons/Tool/bcc32.xml b/src/engine/SCons/Tool/bcc32.xml index 6163016..b2d8394 100644 --- a/src/engine/SCons/Tool/bcc32.xml +++ b/src/engine/SCons/Tool/bcc32.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/c++.py b/src/engine/SCons/Tool/c++.py index ebfe0a4..8819f82 100644 --- a/src/engine/SCons/Tool/c++.py +++ b/src/engine/SCons/Tool/c++.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/c++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/c++.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" #forward proxy to the preffered cxx version diff --git a/src/engine/SCons/Tool/c++.xml b/src/engine/SCons/Tool/c++.xml index e2021fc..c10438a 100644 --- a/src/engine/SCons/Tool/c++.xml +++ b/src/engine/SCons/Tool/c++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/cc.py b/src/engine/SCons/Tool/cc.py index 31e7b2b..698d725 100644 --- a/src/engine/SCons/Tool/cc.py +++ b/src/engine/SCons/Tool/cc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/cc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Tool import SCons.Defaults diff --git a/src/engine/SCons/Tool/cc.xml b/src/engine/SCons/Tool/cc.xml index 1ec3084..735f700 100644 --- a/src/engine/SCons/Tool/cc.xml +++ b/src/engine/SCons/Tool/cc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/clang.py b/src/engine/SCons/Tool/clang.py index 1271378..f48afbf 100644 --- a/src/engine/SCons/Tool/clang.py +++ b/src/engine/SCons/Tool/clang.py @@ -11,7 +11,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -# __revision__ = "src/engine/SCons/Tool/clang.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +# __revision__ = "src/engine/SCons/Tool/clang.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" # Based on SCons/Tool/gcc.py by Paweł Tomulik 2014 as a separate tool. # Brought into the SCons mainline by Russel Winder 2017. @@ -45,6 +45,8 @@ import sys import SCons.Util import SCons.Tool.cc +from SCons.Tool.clangCommon import get_clang_install_dirs + compilers = ['clang'] @@ -52,11 +54,20 @@ def generate(env): """Add Builders and construction variables for clang to an Environment.""" SCons.Tool.cc.generate(env) + if env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for clang + clang = SCons.Tool.find_program_path(env, compilers[0], + default_paths=get_clang_install_dirs(env['PLATFORM'])) + if clang: + clang_bin_dir = os.path.dirname(clang) + env.AppendENVPath('PATH', clang_bin_dir) + env['CC'] = env.Detect(compilers) or 'clang' if env['PLATFORM'] in ['cygwin', 'win32']: env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS') else: env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS -fPIC') + # determine compiler version if env['CC']: #pipe = SCons.Action._subproc(env, [env['CC'], '-dumpversion'], @@ -66,7 +77,8 @@ def generate(env): stdout=subprocess.PIPE) if pipe.wait() != 0: return # clang -dumpversion is of no use - line = pipe.stdout.readline() + with pipe.stdout: + line = pipe.stdout.readline() if sys.version_info[0] > 2: line = line.decode() match = re.search(r'clang +version +([0-9]+(?:\.[0-9]+)+)', line) diff --git a/src/engine/SCons/Tool/clang.xml b/src/engine/SCons/Tool/clang.xml index 3086a51..a546946 100644 --- a/src/engine/SCons/Tool/clang.xml +++ b/src/engine/SCons/Tool/clang.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/clangCommon/__init__.py b/src/engine/SCons/Tool/clangCommon/__init__.py new file mode 100644 index 0000000..37efbf6 --- /dev/null +++ b/src/engine/SCons/Tool/clangCommon/__init__.py @@ -0,0 +1,17 @@ +""" +Common routines and data for clang tools +""" + +clang_win32_dirs = [ + r'C:\Program Files\LLVM\bin', + r'C:\cygwin64\bin', + r'C:\msys64', + r'C:\cygwin\bin', + r'C:\msys', +] + +def get_clang_install_dirs(platform): + if platform == 'win32': + return clang_win32_dirs + else: + return []
\ No newline at end of file diff --git a/src/engine/SCons/Tool/clangxx.py b/src/engine/SCons/Tool/clangxx.py index f56c9e5..d88874e 100644 --- a/src/engine/SCons/Tool/clangxx.py +++ b/src/engine/SCons/Tool/clangxx.py @@ -11,7 +11,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -# __revision__ = "src/engine/SCons/Tool/clangxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +# __revision__ = "src/engine/SCons/Tool/clangxx.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" # Based on SCons/Tool/g++.py by Paweł Tomulik 2014 as a separate tool. # Brought into the SCons mainline by Russel Winder 2017. @@ -46,6 +46,8 @@ import sys import SCons.Tool import SCons.Util import SCons.Tool.cxx +from SCons.Tool.clangCommon import get_clang_install_dirs + compilers = ['clang++'] @@ -66,15 +68,25 @@ def generate(env): env['SHOBJSUFFIX'] = '.pic.o' elif env['PLATFORM'] == 'sunos': env['SHOBJSUFFIX'] = '.pic.o' + elif env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for clang++ + clangxx = SCons.Tool.find_program_path(env, compilers[0], default_paths=get_clang_install_dirs(env['PLATFORM'])) + if clangxx: + clangxx_bin_dir = os.path.dirname(clangxx) + env.AppendENVPath('PATH', clangxx_bin_dir) + # determine compiler version if env['CXX']: pipe = SCons.Action._subproc(env, [env['CXX'], '--version'], stdin='devnull', stderr='devnull', stdout=subprocess.PIPE) - if pipe.wait() != 0: return + if pipe.wait() != 0: + return + # clang -dumpversion is of no use - line = pipe.stdout.readline() + with pipe.stdout: + line = pipe.stdout.readline() if sys.version_info[0] > 2: line = line.decode() match = re.search(r'clang +version +([0-9]+(?:\.[0-9]+)+)', line) diff --git a/src/engine/SCons/Tool/clangxx.xml b/src/engine/SCons/Tool/clangxx.xml index 309bb63..7372389 100644 --- a/src/engine/SCons/Tool/clangxx.xml +++ b/src/engine/SCons/Tool/clangxx.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/cvf.py b/src/engine/SCons/Tool/cvf.py index a785471..aa24d69 100644 --- a/src/engine/SCons/Tool/cvf.py +++ b/src/engine/SCons/Tool/cvf.py @@ -5,7 +5,7 @@ Tool-specific initialization for the Compaq Visual Fortran compiler. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Tool-specific initialization for the Compaq Visual Fortran compiler. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cvf.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/cvf.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from . import fortran diff --git a/src/engine/SCons/Tool/cvf.xml b/src/engine/SCons/Tool/cvf.xml index 1b2c447..b56c23c 100644 --- a/src/engine/SCons/Tool/cvf.xml +++ b/src/engine/SCons/Tool/cvf.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/cxx.py b/src/engine/SCons/Tool/cxx.py index 236730f..2ac278e 100644 --- a/src/engine/SCons/Tool/cxx.py +++ b/src/engine/SCons/Tool/cxx.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/cxx.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py index f69b886..c3d78de 100644 --- a/src/engine/SCons/Tool/cyglink.py +++ b/src/engine/SCons/Tool/cyglink.py @@ -133,7 +133,7 @@ def _versioned_lib_suffix(env, suffix, version): if Verbose: print("_versioned_lib_suffix: suffix= ", suffix) print("_versioned_lib_suffix: version= ", version) - cygversion = re.sub('\.', '-', version) + cygversion = re.sub(r'\.', '-', version) if not suffix.startswith('-' + cygversion): suffix = '-' + cygversion + suffix if Verbose: diff --git a/src/engine/SCons/Tool/cyglink.xml b/src/engine/SCons/Tool/cyglink.xml index 13556e8..a0aefac 100644 --- a/src/engine/SCons/Tool/cyglink.xml +++ b/src/engine/SCons/Tool/cyglink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/default.py b/src/engine/SCons/Tool/default.py index 72d3399..866b823 100644 --- a/src/engine/SCons/Tool/default.py +++ b/src/engine/SCons/Tool/default.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/default.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/default.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Tool diff --git a/src/engine/SCons/Tool/default.xml b/src/engine/SCons/Tool/default.xml index 3683a10..8e1ed21 100644 --- a/src/engine/SCons/Tool/default.xml +++ b/src/engine/SCons/Tool/default.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/dmd.py b/src/engine/SCons/Tool/dmd.py index 1dfb5d7..befcd22 100644 --- a/src/engine/SCons/Tool/dmd.py +++ b/src/engine/SCons/Tool/dmd.py @@ -31,7 +31,7 @@ Lib tool variables: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -53,7 +53,7 @@ Lib tool variables: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dmd.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dmd.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import subprocess diff --git a/src/engine/SCons/Tool/dmd.xml b/src/engine/SCons/Tool/dmd.xml index a06db10..5149503 100644 --- a/src/engine/SCons/Tool/dmd.xml +++ b/src/engine/SCons/Tool/dmd.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/docbook/__init__.py b/src/engine/SCons/Tool/docbook/__init__.py index ed63784..147556d 100644 --- a/src/engine/SCons/Tool/docbook/__init__.py +++ b/src/engine/SCons/Tool/docbook/__init__.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -84,7 +84,7 @@ def __extend_targets_sources(target, source): source = [source] if len(target) < len(source): target.extend(source[len(target):]) - + return target, source def __init_xsl_stylesheet(kw, env, user_xsl_var, default_path): @@ -94,12 +94,12 @@ def __init_xsl_stylesheet(kw, env, user_xsl_var, default_path): path_args = [scriptpath, db_xsl_folder] + default_path xsl_style = os.path.join(*path_args) kw['DOCBOOK_XSL'] = xsl_style - + def __select_builder(lxml_builder, libxml2_builder, cmdline_builder): """ Selects a builder, based on which Python modules are present. """ if prefer_xsltproc: return cmdline_builder - + if not has_libxml2: # At the moment we prefer libxml2 over lxml, the latter can lead # to conflicts when installed together with libxml2. @@ -115,7 +115,7 @@ def __ensure_suffix(t, suffix): tpath = str(t) if not tpath.endswith(suffix): return tpath+suffix - + return t def __ensure_suffix_stem(t, suffix): @@ -124,11 +124,11 @@ def __ensure_suffix_stem(t, suffix): if not tpath.endswith(suffix): stem = tpath tpath += suffix - + return tpath, stem else: stem, ext = os.path.splitext(tpath) - + return t, stem def __get_xml_text(root): @@ -151,7 +151,7 @@ def __create_output_dir(base_dir): else: if base_dir.endswith('/'): dir = base_dir - + if dir and not os.path.isdir(dir): os.makedirs(dir) @@ -166,6 +166,8 @@ xsltproc_com_priority = ['xsltproc', 'saxon', 'saxon-xslt', 'xalan'] # see: http://saxon.sourceforge.net/ xsltproc_com = {'xsltproc' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $DOCBOOK_XSL $SOURCE', 'saxon' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $DOCBOOK_XSL $SOURCE $DOCBOOK_XSLTPROCPARAMS', + # Note if saxon-xslt is version 5.5 the proper arguments are: (swap order of docbook_xsl and source) + # 'saxon-xslt' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $SOURCE $DOCBOOK_XSL $DOCBOOK_XSLTPROCPARAMS', 'saxon-xslt' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $DOCBOOK_XSL $SOURCE $DOCBOOK_XSLTPROCPARAMS', 'xalan' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -q -out $TARGET -xsl $DOCBOOK_XSL -in $SOURCE'} xmllint_com = {'xmllint' : '$DOCBOOK_XMLLINT $DOCBOOK_XMLLINTFLAGS --xinclude $SOURCE > $TARGET'} @@ -201,10 +203,10 @@ def _detect(env): the requested output formats. """ global prefer_xsltproc - + if env.get('DOCBOOK_PREFER_XSLTPROC',''): prefer_xsltproc = True - + if ((not has_libxml2 and not has_lxml) or (prefer_xsltproc)): # Try to find the XSLT processors __detect_cl_tool(env, 'DOCBOOK_XSLTPROC', xsltproc_com, xsltproc_com_priority) @@ -217,15 +219,15 @@ def _detect(env): # include_re = re.compile('fileref\\s*=\\s*["|\']([^\\n]*)["|\']') sentity_re = re.compile('<!ENTITY\\s+%*\\s*[^\\s]+\\s+SYSTEM\\s+["|\']([^\\n]*)["|\']>') - + def __xml_scan(node, env, path, arg): """ Simple XML file scanner, detecting local images and XIncludes as implicit dependencies. """ # Does the node exist yet? if not os.path.isfile(str(node)): return [] - + if env.get('DOCBOOK_SCANENT',''): - # Use simple pattern matching for system entities..., no support + # Use simple pattern matching for system entities..., no support # for recursion yet. contents = node.get_text_contents() return sentity_re.findall(contents) @@ -233,9 +235,9 @@ def __xml_scan(node, env, path, arg): xsl_file = os.path.join(scriptpath,'utils','xmldepend.xsl') if not has_libxml2 or prefer_xsltproc: if has_lxml and not prefer_xsltproc: - + from lxml import etree - + xsl_tree = etree.parse(xsl_file) doc = etree.parse(str(node)) result = doc.xslt(xsl_tree) @@ -264,7 +266,7 @@ def __xml_scan(node, env, path, arg): for x in str(result).splitlines(): if x.strip() != "" and not x.startswith("<?xml "): depfiles.extend(x.strip().split()) - + style.freeStylesheet() doc.freeDoc() result.freeDoc() @@ -280,7 +282,7 @@ docbook_xml_scanner = SCons.Script.Scanner(function = __xml_scan, # Action generators # def __generate_xsltproc_action(source, target, env, for_signature): - cmd = env['DOCBOOK_XSLTPROCCOM'] + cmd = env['DOCBOOK_XSLTPROCCOM'] # Does the environment have a base_dir defined? base_dir = env.subst('$base_dir') if base_dir: @@ -298,7 +300,7 @@ def __emit_xsl_basedir(target, source, env): if base_dir: # Yes, so prepend it to each target return [os.path.join(base_dir, str(t)) for t in target], source - + # No, so simply pass target and source names through return target, source @@ -332,11 +334,11 @@ def __build_lxml(target, source, env): General XSLT builder (HTML/FO), using the lxml module. """ from lxml import etree - - xslt_ac = etree.XSLTAccessControl(read_file=True, - write_file=True, - create_dir=True, - read_network=False, + + xslt_ac = etree.XSLTAccessControl(read_file=True, + write_file=True, + create_dir=True, + read_network=False, write_network=False) xsl_style = env.subst('$DOCBOOK_XSL') xsl_tree = etree.parse(xsl_style) @@ -348,11 +350,10 @@ def __build_lxml(target, source, env): result = transform(doc, **parampass) else: result = transform(doc) - + try: - of = open(str(target[0]), "wb") - of.write(of.write(etree.tostring(result, pretty_print=True))) - of.close() + with open(str(target[0]), "wb") as of: + of.write(etree.tostring(result, pretty_print=True)) except: pass @@ -374,11 +375,11 @@ def __xinclude_lxml(target, source, env): Resolving XIncludes, using the lxml module. """ from lxml import etree - + doc = etree.parse(str(source[0])) doc.xinclude() try: - doc.write(str(target[0]), xml_declaration=True, + doc.write(str(target[0]), xml_declaration=True, encoding="UTF-8", pretty_print=True) except: pass @@ -430,33 +431,31 @@ def DocbookEpub(env, target, source=None, *args, **kw): """ import zipfile import shutil - + def build_open_container(target, source, env): """Generate the *.epub file from intermediate outputs - Constructs the epub file according to the Open Container Format. This + Constructs the epub file according to the Open Container Format. This function could be replaced by a call to the SCons Zip builder if support was added for different compression formats for separate source nodes. """ - zf = zipfile.ZipFile(str(target[0]), 'w') - mime_file = open('mimetype', 'w') - mime_file.write('application/epub+zip') - mime_file.close() - zf.write(mime_file.name, compress_type = zipfile.ZIP_STORED) - for s in source: - if os.path.isfile(str(s)): - head, tail = os.path.split(str(s)) - if not head: - continue - s = head - for dirpath, dirnames, filenames in os.walk(str(s)): - for fname in filenames: - path = os.path.join(dirpath, fname) - if os.path.isfile(path): - zf.write(path, os.path.relpath(path, str(env.get('ZIPROOT', ''))), - zipfile.ZIP_DEFLATED) - zf.close() - + with zipfile.ZipFile(str(target[0]), 'w') as zf: + with open('mimetype', 'w') as mime_file: + mime_file.write('application/epub+zip') + zf.write(mime_file.name, compress_type = zipfile.ZIP_STORED) + for s in source: + if os.path.isfile(str(s)): + head, tail = os.path.split(str(s)) + if not head: + continue + s = head + for dirpath, dirnames, filenames in os.walk(str(s)): + for fname in filenames: + path = os.path.join(dirpath, fname) + if os.path.isfile(path): + zf.write(path, os.path.relpath(path, str(env.get('ZIPROOT', ''))), + zipfile.ZIP_DEFLATED) + def add_resources(target, source, env): """Add missing resources to the OEBPS directory @@ -466,7 +465,7 @@ def DocbookEpub(env, target, source=None, *args, **kw): content_file = os.path.join(source[0].get_abspath(), 'content.opf') if not os.path.isfile(content_file): return - + hrefs = [] if has_libxml2: nsmap = {'opf' : 'http://www.idpf.org/2007/opf'} @@ -493,51 +492,51 @@ def DocbookEpub(env, target, source=None, *args, **kw): hrefs.append(item.attrib['href']) doc.freeDoc() - xpath_context.xpathFreeContext() + xpath_context.xpathFreeContext() elif has_lxml: from lxml import etree - + opf = etree.parse(content_file) # All the opf:item elements are resources - for item in opf.xpath('//opf:item', + for item in opf.xpath('//opf:item', namespaces= { 'opf': 'http://www.idpf.org/2007/opf' }): hrefs.append(item.attrib['href']) - + for href in hrefs: - # If the resource was not already created by DocBook XSL itself, + # If the resource was not already created by DocBook XSL itself, # copy it into the OEBPS folder referenced_file = os.path.join(source[0].get_abspath(), href) if not os.path.exists(referenced_file): shutil.copy(href, os.path.join(source[0].get_abspath(), href)) - + # Init list of targets/sources target, source = __extend_targets_sources(target, source) - + # Init XSL stylesheet __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_EPUB', ['epub','docbook.xsl']) # Setup builder __builder = __select_builder(__lxml_builder, __libxml2_builder, __xsltproc_builder) - + # Create targets result = [] - if not env.GetOption('clean'): + if not env.GetOption('clean'): # Ensure that the folders OEBPS and META-INF exist __create_output_dir('OEBPS/') __create_output_dir('META-INF/') dirs = env.Dir(['OEBPS', 'META-INF']) - + # Set the fixed base_dir kw['base_dir'] = 'OEBPS/' tocncx = __builder.__call__(env, 'toc.ncx', source[0], **kw) cxml = env.File('META-INF/container.xml') env.SideEffect(cxml, tocncx) - + env.Depends(tocncx, kw['DOCBOOK_XSL']) result.extend(tocncx+[cxml]) - container = env.Command(__ensure_suffix(str(target[0]), '.epub'), - tocncx+[cxml], [add_resources, build_open_container]) + container = env.Command(__ensure_suffix(str(target[0]), '.epub'), + tocncx+[cxml], [add_resources, build_open_container]) mimetype = env.File('mimetype') env.SideEffect(mimetype, container) @@ -553,13 +552,13 @@ def DocbookHtml(env, target, source=None, *args, **kw): """ # Init list of targets/sources target, source = __extend_targets_sources(target, source) - + # Init XSL stylesheet __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_HTML', ['html','docbook.xsl']) # Setup builder __builder = __select_builder(__lxml_builder, __libxml2_builder, __xsltproc_builder) - + # Create targets result = [] for t,s in zip(target,source): @@ -581,18 +580,18 @@ def DocbookHtmlChunked(env, target, source=None, *args, **kw): target = ['index.html'] elif not SCons.Util.is_List(source): source = [source] - + # Init XSL stylesheet __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_HTMLCHUNKED', ['html','chunkfast.xsl']) # Setup builder __builder = __select_builder(__lxml_builder, __libxml2_builder, __xsltproc_builder) - + # Detect base dir base_dir = kw.get('base_dir', '') if base_dir: __create_output_dir(base_dir) - + # Create targets result = [] r = __builder.__call__(env, __ensure_suffix(str(target[0]), '.html'), source[0], **kw) @@ -615,8 +614,8 @@ def DocbookHtmlhelp(env, target, source=None, *args, **kw): source = target target = ['index.html'] elif not SCons.Util.is_List(source): - source = [source] - + source = [source] + # Init XSL stylesheet __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_HTMLHELP', ['htmlhelp','htmlhelp.xsl']) @@ -627,7 +626,7 @@ def DocbookHtmlhelp(env, target, source=None, *args, **kw): base_dir = kw.get('base_dir', '') if base_dir: __create_output_dir(base_dir) - + # Create targets result = [] r = __builder.__call__(env, __ensure_suffix(str(target[0]), '.html'), source[0], **kw) @@ -685,30 +684,29 @@ def DocbookMan(env, target, source=None, *args, **kw): if os.path.isfile(srcfile): try: import xml.dom.minidom - + dom = xml.dom.minidom.parse(__ensure_suffix(str(s),'.xml')) # Extract volume number, default is 1 for node in dom.getElementsByTagName('refmeta'): for vol in node.getElementsByTagName('manvolnum'): volnum = __get_xml_text(vol) - + # Extract output filenames for node in dom.getElementsByTagName('refnamediv'): for ref in node.getElementsByTagName('refname'): outfiles.append(__get_xml_text(ref)+'.'+volnum) - + except: - # Use simple regex parsing - f = open(__ensure_suffix(str(s),'.xml'), 'r') - content = f.read() - f.close() - + # Use simple regex parsing + with open(__ensure_suffix(str(s),'.xml'), 'r') as f: + content = f.read() + for m in re_manvolnum.finditer(content): volnum = m.group(1) - + for m in re_refname.finditer(content): outfiles.append(m.group(1)+'.'+volnum) - + if not outfiles: # Use stem of the source file spath = str(s) @@ -720,14 +718,14 @@ def DocbookMan(env, target, source=None, *args, **kw): else: # We have to completely rely on the given target name outfiles.append(t) - + __builder.__call__(env, outfiles[0], s, **kw) env.Depends(outfiles[0], kw['DOCBOOK_XSL']) result.append(outfiles[0]) if len(outfiles) > 1: env.Clean(outfiles[0], outfiles[1:]) - + return result def DocbookSlidesPdf(env, target, source=None, *args, **kw): @@ -748,7 +746,7 @@ def DocbookSlidesPdf(env, target, source=None, *args, **kw): for t,s in zip(target,source): t, stem = __ensure_suffix_stem(t, '.pdf') xsl = __builder.__call__(env, stem+'.fo', s, **kw) - env.Depends(xsl, kw['DOCBOOK_XSL']) + env.Depends(xsl, kw['DOCBOOK_XSL']) result.extend(xsl) result.extend(__fop_builder.__call__(env, t, xsl, **kw)) @@ -765,7 +763,7 @@ def DocbookSlidesHtml(env, target, source=None, *args, **kw): source = target target = ['index.html'] elif not SCons.Util.is_List(source): - source = [source] + source = [source] # Init XSL stylesheet __init_xsl_stylesheet(kw, env, '$DOCBOOK_DEFAULT_XSL_SLIDESHTML', ['slides','html','plain.xsl']) @@ -798,12 +796,12 @@ def DocbookXInclude(env, target, source, *args, **kw): # Setup builder __builder = __select_builder(__xinclude_lxml_builder,__xinclude_libxml2_builder,__xmllint_builder) - + # Create targets result = [] for t,s in zip(target,source): result.extend(__builder.__call__(env, t, s, **kw)) - + return result def DocbookXslt(env, target, source=None, *args, **kw): @@ -812,13 +810,13 @@ def DocbookXslt(env, target, source=None, *args, **kw): """ # Init list of targets/sources target, source = __extend_targets_sources(target, source) - + # Init XSL stylesheet kw['DOCBOOK_XSL'] = kw.get('xsl', 'transform.xsl') # Setup builder __builder = __select_builder(__lxml_builder, __libxml2_builder, __xsltproc_builder) - + # Create targets result = [] for t,s in zip(target,source): @@ -842,18 +840,18 @@ def generate(env): DOCBOOK_DEFAULT_XSL_MAN = '', DOCBOOK_DEFAULT_XSL_SLIDESPDF = '', DOCBOOK_DEFAULT_XSL_SLIDESHTML = '', - + # Paths to the detected executables DOCBOOK_XSLTPROC = '', DOCBOOK_XMLLINT = '', DOCBOOK_FOP = '', - + # Additional flags for the text processors DOCBOOK_XSLTPROCFLAGS = SCons.Util.CLVar(''), DOCBOOK_XMLLINTFLAGS = SCons.Util.CLVar(''), DOCBOOK_FOPFLAGS = SCons.Util.CLVar(''), DOCBOOK_XSLTPROCPARAMS = SCons.Util.CLVar(''), - + # Default command lines for the detected executables DOCBOOK_XSLTPROCCOM = xsltproc_com['xsltproc'], DOCBOOK_XMLLINTCOM = xmllint_com['xmllint'], @@ -863,7 +861,7 @@ def generate(env): DOCBOOK_XSLTPROCCOMSTR = None, DOCBOOK_XMLLINTCOMSTR = None, DOCBOOK_FOPCOMSTR = None, - + ) _detect(env) diff --git a/src/engine/SCons/Tool/docbook/__init__.xml b/src/engine/SCons/Tool/docbook/__init__.xml index 1994392..3110649 100644 --- a/src/engine/SCons/Tool/docbook/__init__.xml +++ b/src/engine/SCons/Tool/docbook/__init__.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/docbook/docs/manual.xml b/src/engine/SCons/Tool/docbook/docs/manual.xml index c129753..64ee925 100644 --- a/src/engine/SCons/Tool/docbook/docs/manual.xml +++ b/src/engine/SCons/Tool/docbook/docs/manual.xml @@ -67,7 +67,7 @@ package's <literal>docbook</literal> folder to <itemizedlist><listitem><para>the SCons User's Guide, chap. 19.7 "Where to put your custom Builders and Tools" and </para> </listitem> -<listitem><para>the SCons Tools Wiki page at <ulink url="http://scons.org/wiki/ToolsIndex">http://scons.org/wiki/ToolsIndex</ulink>. +<listitem><para>the SCons Tools Wiki page at <ulink url="https://github.com/SCons/scons/wiki/ToolsIndex">http://github.com/SCons/scons/wiki/ToolsIndex</ulink>. </para> </listitem> </itemizedlist> diff --git a/src/engine/SCons/Tool/dvi.py b/src/engine/SCons/Tool/dvi.py index 9ec1563..5cd85ed 100644 --- a/src/engine/SCons/Tool/dvi.py +++ b/src/engine/SCons/Tool/dvi.py @@ -5,7 +5,7 @@ Common DVI Builder definition for various other Tool modules that use it. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Common DVI Builder definition for various other Tool modules that use it. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dvi.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dvi.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Builder import SCons.Tool diff --git a/src/engine/SCons/Tool/dvi.xml b/src/engine/SCons/Tool/dvi.xml index 1ec2ef0..82ff01b 100644 --- a/src/engine/SCons/Tool/dvi.xml +++ b/src/engine/SCons/Tool/dvi.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/dvipdf.py b/src/engine/SCons/Tool/dvipdf.py index 339155d..32f57e6 100644 --- a/src/engine/SCons/Tool/dvipdf.py +++ b/src/engine/SCons/Tool/dvipdf.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/dvipdf.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dvipdf.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Action import SCons.Defaults diff --git a/src/engine/SCons/Tool/dvipdf.xml b/src/engine/SCons/Tool/dvipdf.xml index a5d2018..683ca72 100644 --- a/src/engine/SCons/Tool/dvipdf.xml +++ b/src/engine/SCons/Tool/dvipdf.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/dvips.py b/src/engine/SCons/Tool/dvips.py index 95641d6..988ecd3 100644 --- a/src/engine/SCons/Tool/dvips.py +++ b/src/engine/SCons/Tool/dvips.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dvips.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dvips.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Action import SCons.Builder diff --git a/src/engine/SCons/Tool/dvips.xml b/src/engine/SCons/Tool/dvips.xml index 7f47592..9838db1 100644 --- a/src/engine/SCons/Tool/dvips.xml +++ b/src/engine/SCons/Tool/dvips.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f03.py b/src/engine/SCons/Tool/f03.py index a9f91a8..541ec88 100644 --- a/src/engine/SCons/Tool/f03.py +++ b/src/engine/SCons/Tool/f03.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f03.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f03.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/f03.xml b/src/engine/SCons/Tool/f03.xml index e486acf..af9da30 100644 --- a/src/engine/SCons/Tool/f03.xml +++ b/src/engine/SCons/Tool/f03.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f08.py b/src/engine/SCons/Tool/f08.py index eb44487..5dc49da 100644 --- a/src/engine/SCons/Tool/f08.py +++ b/src/engine/SCons/Tool/f08.py @@ -11,7 +11,7 @@ selection method. from __future__ import absolute_import # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ from __future__ import absolute_import # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f08.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f08.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/f08.xml b/src/engine/SCons/Tool/f08.xml index aac7b66..4c07890 100644 --- a/src/engine/SCons/Tool/f08.xml +++ b/src/engine/SCons/Tool/f08.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f77.py b/src/engine/SCons/Tool/f77.py index afa9a7b..6d60edf 100644 --- a/src/engine/SCons/Tool/f77.py +++ b/src/engine/SCons/Tool/f77.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f77.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f77.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Scanner.Fortran diff --git a/src/engine/SCons/Tool/f77.xml b/src/engine/SCons/Tool/f77.xml index 210c646..7ce1159 100644 --- a/src/engine/SCons/Tool/f77.xml +++ b/src/engine/SCons/Tool/f77.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f90.py b/src/engine/SCons/Tool/f90.py index f66ed47..e0b5fae 100644 --- a/src/engine/SCons/Tool/f90.py +++ b/src/engine/SCons/Tool/f90.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f90.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f90.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Scanner.Fortran diff --git a/src/engine/SCons/Tool/f90.xml b/src/engine/SCons/Tool/f90.xml index b5f7f13..f8c1854 100644 --- a/src/engine/SCons/Tool/f90.xml +++ b/src/engine/SCons/Tool/f90.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f95.py b/src/engine/SCons/Tool/f95.py index bc5439f..9a1afdf 100644 --- a/src/engine/SCons/Tool/f95.py +++ b/src/engine/SCons/Tool/f95.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f95.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f95.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/f95.xml b/src/engine/SCons/Tool/f95.xml index f1cb7c2..a575ad0 100644 --- a/src/engine/SCons/Tool/f95.xml +++ b/src/engine/SCons/Tool/f95.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/filesystem.py b/src/engine/SCons/Tool/filesystem.py index 6615c31..a625714 100644 --- a/src/engine/SCons/Tool/filesystem.py +++ b/src/engine/SCons/Tool/filesystem.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/filesystem.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/filesystem.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons from SCons.Tool.install import copyFunc diff --git a/src/engine/SCons/Tool/fortran.py b/src/engine/SCons/Tool/fortran.py index b99b5e6..1b09880 100644 --- a/src/engine/SCons/Tool/fortran.py +++ b/src/engine/SCons/Tool/fortran.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/fortran.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/fortran.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import re diff --git a/src/engine/SCons/Tool/fortran.xml b/src/engine/SCons/Tool/fortran.xml index 3907ce2..0fde8f1 100644 --- a/src/engine/SCons/Tool/fortran.xml +++ b/src/engine/SCons/Tool/fortran.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -125,7 +125,8 @@ containing the Fortran compiler command-line options for specifying directories to be searched for include files and module files. The value of &cv-link-_FORTRANINCFLAGS; is created -by prepending/appending &cv-link-INCPREFIX; and &cv-link-INCSUFFIX; +by respectively prepending and appending +&cv-link-INCPREFIX; and &cv-link-INCSUFFIX; to the beginning and end of each directory in &cv-link-FORTRANPATH;. </para> @@ -148,7 +149,7 @@ for module files, as well. <para> The prefix used to specify a module directory on the Fortran compiler command line. -This will be appended to the beginning of the directory +This will be prepended to the beginning of the directory in the &cv-link-FORTRANMODDIR; construction variables when the &cv-link-_FORTRANMODFLAG; variables is automatically generated. </para> @@ -160,7 +161,7 @@ when the &cv-link-_FORTRANMODFLAG; variables is automatically generated. <para> The suffix used to specify a module directory on the Fortran compiler command line. -This will be appended to the beginning of the directory +This will be appended to the end of the directory in the &cv-link-FORTRANMODDIR; construction variables when the &cv-link-_FORTRANMODFLAG; variables is automatically generated. </para> @@ -176,8 +177,8 @@ for specifying the directory location where the Fortran compiler should place any module files that happen to get generated during compilation. The value of &cv-link-_FORTRANMODFLAG; is created -by prepending/appending &cv-link-FORTRANMODDIRPREFIX; and -&cv-link-FORTRANMODDIRSUFFIX; +by respectively prepending and appending +&cv-link-FORTRANMODDIRPREFIX; and &cv-link-FORTRANMODDIRSUFFIX; to the beginning and end of the directory in &cv-link-FORTRANMODDIR;. </para> </summary> @@ -250,7 +251,7 @@ through the automatically-generated &cv-link-_FORTRANINCFLAGS; construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the &cv-link-INCPREFIX; and &cv-link-INCSUFFIX; construction variables to the beginning and end diff --git a/src/engine/SCons/Tool/g++.py b/src/engine/SCons/Tool/g++.py index 468fa87..8cf881f 100644 --- a/src/engine/SCons/Tool/g++.py +++ b/src/engine/SCons/Tool/g++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/g++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/g++.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" #forward proxy to the preffered cxx version diff --git a/src/engine/SCons/Tool/g++.xml b/src/engine/SCons/Tool/g++.xml index 6698869..f997540 100644 --- a/src/engine/SCons/Tool/g++.xml +++ b/src/engine/SCons/Tool/g++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/g77.py b/src/engine/SCons/Tool/g77.py index 36b3c43..fc0bcba 100644 --- a/src/engine/SCons/Tool/g77.py +++ b/src/engine/SCons/Tool/g77.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/g77.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/g77.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util from SCons.Tool.FortranCommon import add_all_to_env, add_f77_to_env diff --git a/src/engine/SCons/Tool/g77.xml b/src/engine/SCons/Tool/g77.xml index ae57994..519dfaf 100644 --- a/src/engine/SCons/Tool/g77.xml +++ b/src/engine/SCons/Tool/g77.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gas.py b/src/engine/SCons/Tool/gas.py index 75e5456..c104e34 100644 --- a/src/engine/SCons/Tool/gas.py +++ b/src/engine/SCons/Tool/gas.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gas.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gas.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" try: as_module = __import__('as', globals(), locals(), []) diff --git a/src/engine/SCons/Tool/gas.xml b/src/engine/SCons/Tool/gas.xml index 95ccf27..9cfe0de 100644 --- a/src/engine/SCons/Tool/gas.xml +++ b/src/engine/SCons/Tool/gas.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gcc.py b/src/engine/SCons/Tool/gcc.py index f241c7b..2532427 100644 --- a/src/engine/SCons/Tool/gcc.py +++ b/src/engine/SCons/Tool/gcc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gcc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gcc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from . import cc import os @@ -42,6 +42,7 @@ import SCons.Util compilers = ['gcc', 'cc'] + def generate(env): """Add Builders and construction variables for gcc to an Environment.""" @@ -59,38 +60,48 @@ def generate(env): if version: env['CCVERSION'] = version + def exists(env): # is executable, and is a GNU compiler (or accepts '--version' at least) return detect_version(env, env.Detect(env.get('CC', compilers))) + def detect_version(env, cc): """Return the version of the GNU compiler, or None if it is not a GNU compiler.""" + version = None cc = env.subst(cc) if not cc: - return None - version = None - #pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['-dumpversion'], - pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['--version'], - stdin = 'devnull', - stderr = 'devnull', - stdout = subprocess.PIPE) + return version + # -dumpversion was added in GCC 3.0. As long as we're supporting # GCC versions older than that, we should use --version and a # regular expression. - #line = pipe.stdout.read().strip() - #if line: - # version = line - line = SCons.Util.to_str(pipe.stdout.readline()) + # pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['-dumpversion'], + pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['--version'], + stdin='devnull', + stderr='devnull', + stdout=subprocess.PIPE) + if pipe.wait() != 0: + return version + + with pipe.stdout: + # -dumpversion variant: + # line = pipe.stdout.read().strip() + # --version variant: + line = SCons.Util.to_str(pipe.stdout.readline()) + # Non-GNU compiler's output (like AIX xlc's) may exceed the stdout buffer: + # So continue with reading to let the child process actually terminate. + while SCons.Util.to_str(pipe.stdout.readline()): + pass + + # -dumpversion variant: + # if line: + # version = line + # --version variant: match = re.search(r'[0-9]+(\.[0-9]+)+', line) if match: version = match.group(0) - # Non-GNU compiler's output (like AIX xlc's) may exceed the stdout buffer: - # So continue with reading to let the child process actually terminate. - while SCons.Util.to_str(pipe.stdout.readline()): - pass - ret = pipe.wait() - if ret != 0: - return None + return version # Local Variables: diff --git a/src/engine/SCons/Tool/gcc.xml b/src/engine/SCons/Tool/gcc.xml index 17fe2a1..8c29e9d 100644 --- a/src/engine/SCons/Tool/gcc.xml +++ b/src/engine/SCons/Tool/gcc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gdc.py b/src/engine/SCons/Tool/gdc.py index f98fabc..46a910c 100644 --- a/src/engine/SCons/Tool/gdc.py +++ b/src/engine/SCons/Tool/gdc.py @@ -26,7 +26,7 @@ Lib tool variables: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -48,7 +48,7 @@ Lib tool variables: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gdc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gdc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Action import SCons.Defaults diff --git a/src/engine/SCons/Tool/gdc.xml b/src/engine/SCons/Tool/gdc.xml index 8f71b5d..ea31215 100644 --- a/src/engine/SCons/Tool/gdc.xml +++ b/src/engine/SCons/Tool/gdc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gettext.xml b/src/engine/SCons/Tool/gettext.xml index 299184a..fc3af69 100644 --- a/src/engine/SCons/Tool/gettext.xml +++ b/src/engine/SCons/Tool/gettext.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gettext_tool.py b/src/engine/SCons/Tool/gettext_tool.py index e500a18..5fc0158 100644 --- a/src/engine/SCons/Tool/gettext_tool.py +++ b/src/engine/SCons/Tool/gettext_tool.py @@ -2,7 +2,7 @@ """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,14 +23,26 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/gettext_tool.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gettext_tool.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" ############################################################################# def generate(env,**kw): + import sys + import os import SCons.Tool + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + from SCons.Tool.GettextCommon \ import _translate, tool_list for t in tool_list(env['PLATFORM'], env): + if sys.platform == 'win32': + tool = SCons.Tool.find_program_path(env, t, default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if tool: + tool_bin_dir = os.path.dirname(tool) + env.AppendENVPath('PATH', tool_bin_dir) + else: + SCons.Warnings.Warning(t + ' tool requested, but binary not found in ENV PATH') env.Tool(t) env.AddMethod(_translate, 'Translate') ############################################################################# diff --git a/src/engine/SCons/Tool/gfortran.py b/src/engine/SCons/Tool/gfortran.py index 730ad55..8d02daa 100644 --- a/src/engine/SCons/Tool/gfortran.py +++ b/src/engine/SCons/Tool/gfortran.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gfortran.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gfortran.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util @@ -54,6 +54,8 @@ def generate(env): env['INC%sPREFIX' % dialect] = "-I" env['INC%sSUFFIX' % dialect] = "" + env['FORTRANMODDIRPREFIX'] = "-J" + def exists(env): return env.Detect('gfortran') diff --git a/src/engine/SCons/Tool/gfortran.xml b/src/engine/SCons/Tool/gfortran.xml index 926a2c8..4e78495 100644 --- a/src/engine/SCons/Tool/gfortran.xml +++ b/src/engine/SCons/Tool/gfortran.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py index 56bae9a..53f5081 100644 --- a/src/engine/SCons/Tool/gnulink.py +++ b/src/engine/SCons/Tool/gnulink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gnulink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gnulink.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util import SCons.Tool diff --git a/src/engine/SCons/Tool/gnulink.xml b/src/engine/SCons/Tool/gnulink.xml index fce7a55..5ef80eb 100644 --- a/src/engine/SCons/Tool/gnulink.xml +++ b/src/engine/SCons/Tool/gnulink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gs.py b/src/engine/SCons/Tool/gs.py index ec5ab27..371b810 100644 --- a/src/engine/SCons/Tool/gs.py +++ b/src/engine/SCons/Tool/gs.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gs.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Action import SCons.Builder diff --git a/src/engine/SCons/Tool/gs.xml b/src/engine/SCons/Tool/gs.xml index 40e6f06..185f1b4 100644 --- a/src/engine/SCons/Tool/gs.xml +++ b/src/engine/SCons/Tool/gs.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gxx.py b/src/engine/SCons/Tool/gxx.py index 709f72b..d956c9f 100644 --- a/src/engine/SCons/Tool/gxx.py +++ b/src/engine/SCons/Tool/gxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gxx.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path import re @@ -45,12 +45,13 @@ from . import cxx compilers = ['g++'] + def generate(env): """Add Builders and construction variables for g++ to an Environment.""" static_obj, shared_obj = SCons.Tool.createObjBuilders(env) if 'CXX' not in env: - env['CXX'] = env.Detect(compilers) or compilers[0] + env['CXX'] = env.Detect(compilers) or compilers[0] cxx.generate(env) @@ -68,6 +69,7 @@ def generate(env): if version: env['CXXVERSION'] = version + def exists(env): # is executable, and is a GNU compiler (or accepts '--version' at least) return gcc.detect_version(env, env.Detect(env.get('CXX', compilers))) diff --git a/src/engine/SCons/Tool/hpc++.py b/src/engine/SCons/Tool/hpc++.py index 9471ef5..4ec2fe3 100644 --- a/src/engine/SCons/Tool/hpc++.py +++ b/src/engine/SCons/Tool/hpc++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpc++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hpc++.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" #forward proxy to the preffered cxx version diff --git a/src/engine/SCons/Tool/hpc++.xml b/src/engine/SCons/Tool/hpc++.xml index d3d11c4..8bb4a65 100644 --- a/src/engine/SCons/Tool/hpc++.xml +++ b/src/engine/SCons/Tool/hpc++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/hpcc.py b/src/engine/SCons/Tool/hpcc.py index 0f6a5b4..6a564b9 100644 --- a/src/engine/SCons/Tool/hpcc.py +++ b/src/engine/SCons/Tool/hpcc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpcc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hpcc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util diff --git a/src/engine/SCons/Tool/hpcc.xml b/src/engine/SCons/Tool/hpcc.xml index 765860f..f8bece8 100644 --- a/src/engine/SCons/Tool/hpcc.xml +++ b/src/engine/SCons/Tool/hpcc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/hpcxx.py b/src/engine/SCons/Tool/hpcxx.py index 847eaca..8ee888f 100644 --- a/src/engine/SCons/Tool/hpcxx.py +++ b/src/engine/SCons/Tool/hpcxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpcxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hpcxx.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path @@ -68,7 +68,8 @@ def generate(env): env['CXX'] = acc or 'aCC' env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS +Z') # determine version of aCC - line = os.popen(acc + ' -V 2>&1').readline().rstrip() + with os.popen(acc + ' -V 2>&1') as p: + line = p.readline().rstrip() if line.find('aCC: HP ANSI C++') == 0: env['CXXVERSION'] = line.split()[-1] diff --git a/src/engine/SCons/Tool/hplink.py b/src/engine/SCons/Tool/hplink.py index 2329282..1afa95e 100644 --- a/src/engine/SCons/Tool/hplink.py +++ b/src/engine/SCons/Tool/hplink.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hplink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hplink.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import os.path diff --git a/src/engine/SCons/Tool/hplink.xml b/src/engine/SCons/Tool/hplink.xml index ffa6c0d..f2b923b 100644 --- a/src/engine/SCons/Tool/hplink.xml +++ b/src/engine/SCons/Tool/hplink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/icc.py b/src/engine/SCons/Tool/icc.py index 1f9e8cf..8110a60 100644 --- a/src/engine/SCons/Tool/icc.py +++ b/src/engine/SCons/Tool/icc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/icc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/icc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from . import cc diff --git a/src/engine/SCons/Tool/icc.xml b/src/engine/SCons/Tool/icc.xml index b0af318..8492fce 100644 --- a/src/engine/SCons/Tool/icc.xml +++ b/src/engine/SCons/Tool/icc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/icl.py b/src/engine/SCons/Tool/icl.py index 99410cd..29d5862 100644 --- a/src/engine/SCons/Tool/icl.py +++ b/src/engine/SCons/Tool/icl.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/icl.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/icl.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Tool.intelc diff --git a/src/engine/SCons/Tool/icl.xml b/src/engine/SCons/Tool/icl.xml index 035a3a9..31e0bcc 100644 --- a/src/engine/SCons/Tool/icl.xml +++ b/src/engine/SCons/Tool/icl.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ifl.py b/src/engine/SCons/Tool/ifl.py index 116c9ac..0eb7cda 100644 --- a/src/engine/SCons/Tool/ifl.py +++ b/src/engine/SCons/Tool/ifl.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ifl.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ifl.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults from SCons.Scanner.Fortran import FortranScan diff --git a/src/engine/SCons/Tool/ifl.xml b/src/engine/SCons/Tool/ifl.xml index d693ef6..f78c9fd 100644 --- a/src/engine/SCons/Tool/ifl.xml +++ b/src/engine/SCons/Tool/ifl.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ifort.py b/src/engine/SCons/Tool/ifort.py index 8e88946..730e778 100644 --- a/src/engine/SCons/Tool/ifort.py +++ b/src/engine/SCons/Tool/ifort.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ifort.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ifort.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults from SCons.Scanner.Fortran import FortranScan diff --git a/src/engine/SCons/Tool/ifort.xml b/src/engine/SCons/Tool/ifort.xml index 26d4ca9..47a55e3 100644 --- a/src/engine/SCons/Tool/ifort.xml +++ b/src/engine/SCons/Tool/ifort.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ilink.py b/src/engine/SCons/Tool/ilink.py index 577e54b..7c69e72 100644 --- a/src/engine/SCons/Tool/ilink.py +++ b/src/engine/SCons/Tool/ilink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ilink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ilink.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/ilink.xml b/src/engine/SCons/Tool/ilink.xml index 941db53..731bdfb 100644 --- a/src/engine/SCons/Tool/ilink.xml +++ b/src/engine/SCons/Tool/ilink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ilink32.py b/src/engine/SCons/Tool/ilink32.py index 3e8e095..a1e12a6 100644 --- a/src/engine/SCons/Tool/ilink32.py +++ b/src/engine/SCons/Tool/ilink32.py @@ -5,7 +5,7 @@ XXX """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ XXX # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ilink32.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ilink32.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Tool import SCons.Tool.bcc32 diff --git a/src/engine/SCons/Tool/ilink32.xml b/src/engine/SCons/Tool/ilink32.xml index 02343d9..3f273a8 100644 --- a/src/engine/SCons/Tool/ilink32.xml +++ b/src/engine/SCons/Tool/ilink32.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index 12dcf8f..c0a8917 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/install.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/install.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import re diff --git a/src/engine/SCons/Tool/install.xml b/src/engine/SCons/Tool/install.xml index 139cd1e..da2d4a0 100644 --- a/src/engine/SCons/Tool/install.xml +++ b/src/engine/SCons/Tool/install.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 425f221..fdd9730 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,12 +32,12 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import division, print_function -__revision__ = "src/engine/SCons/Tool/intelc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/intelc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import math, sys, os.path, glob, string, re is_windows = sys.platform == 'win32' -is_win64 = is_windows and (os.environ['PROCESSOR_ARCHITECTURE'] == 'AMD64' or +is_win64 = is_windows and (os.environ['PROCESSOR_ARCHITECTURE'] == 'AMD64' or ('PROCESSOR_ARCHITEW6432' in os.environ and os.environ['PROCESSOR_ARCHITEW6432'] == 'AMD64')) is_linux = sys.platform.startswith('linux') @@ -73,7 +73,7 @@ def linux_ver_normalize(vstr): m = re.match(r'([0-9]+)\.([0-9]+)\.([0-9]+)', vstr) if m: vmaj,vmin,build = m.groups() - return float(vmaj) * 10. + float(vmin) + float(build) / 1000.; + return float(vmaj) * 10. + float(vmin) + float(build) / 1000. else: f = float(vstr) if is_windows: @@ -113,11 +113,6 @@ def check_abi(abi): (abi, list(valid_abis.keys()))) return abi -def vercmp(a, b): - """Compare strings as floats, - but Intel changed Linux naming convention at 9.0""" - return cmp(linux_ver_normalize(b), linux_ver_normalize(a)) - def get_version_from_list(v, vlist): """See if we can match v (string) in vlist (list of strings) Linux has to match in a fuzzy way.""" @@ -221,7 +216,7 @@ def get_all_compiler_versions(): versions = [] try: while i < 100: - subkey = SCons.Util.RegEnumKey(k, i) # raises EnvironmentError + subkey = SCons.Util.RegEnumKey(k, i) # raises SConsEnvironmentError # Check that this refers to an existing dir. # This is not 100% perfect but should catch common # installation issues like when the compiler was installed @@ -293,7 +288,7 @@ def get_all_compiler_versions(): m = re.search(r'([0-9]{0,4})(?:_sp\d*)?\.([0-9][0-9.]*)$', d) if m: versions.append("%s.%s"%(m.group(1), m.group(2))) - + def keyfunc(str): """Given a dot-separated version string, return a tuple of ints representing it.""" return [int(x) for x in str.split('.')] @@ -383,7 +378,7 @@ def get_intel_compiler_top(version, abi): top = d break return top - + top = find_in_2016style_dir(version) or find_in_2011style_dir(version) or find_in_2010style_dir(version) or find_in_2008style_dir(version) # print "INTELC: top=",top if not top: diff --git a/src/engine/SCons/Tool/intelc.xml b/src/engine/SCons/Tool/intelc.xml index 3ec9ddd..af77186 100644 --- a/src/engine/SCons/Tool/intelc.xml +++ b/src/engine/SCons/Tool/intelc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ipkg.py b/src/engine/SCons/Tool/ipkg.py index 4ad53c9..664c3a6 100644 --- a/src/engine/SCons/Tool/ipkg.py +++ b/src/engine/SCons/Tool/ipkg.py @@ -11,7 +11,7 @@ packages fake_root. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ packages fake_root. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ipkg.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ipkg.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os @@ -55,8 +55,10 @@ def generate(env): env['IPKGCOM'] = '$IPKG $IPKGFLAGS ${SOURCE}' if env.WhereIs('id'): - env['IPKGUSER'] = os.popen('id -un').read().strip() - env['IPKGGROUP'] = os.popen('id -gn').read().strip() + with os.popen('id -un') as p: + env['IPKGUSER'] = p.read().strip() + with os.popen('id -gn') as p: + env['IPKGGROUP'] = p.read().strip() env['IPKGFLAGS'] = SCons.Util.CLVar('-o $IPKGUSER -g $IPKGGROUP') env['IPKGSUFFIX'] = '.ipk' diff --git a/src/engine/SCons/Tool/jar.py b/src/engine/SCons/Tool/jar.py index a56dd70..98be08f 100644 --- a/src/engine/SCons/Tool/jar.py +++ b/src/engine/SCons/Tool/jar.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,10 +31,14 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/jar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/jar.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" +import os import SCons.Subst import SCons.Util +from SCons.Node.FS import _my_normcase +from SCons.Tool.JavaCommon import get_java_install_dirs + def jarSources(target, source, env, for_signature): """Only include sources that are not a manifest file.""" @@ -50,7 +54,7 @@ def jarSources(target, source, env, for_signature): result = [] for src in source: contents = src.get_text_contents() - if contents[:16] != "Manifest-Version": + if not contents.startswith("Manifest-Version"): if jarchdir_set: _chdir = jarchdir else: @@ -71,7 +75,7 @@ def jarManifest(target, source, env, for_signature): """Look in sources for a manifest file, if any.""" for src in source: contents = src.get_text_contents() - if contents[:16] == "Manifest-Version": + if contents.startswith("Manifest-Version"): return src return '' @@ -81,16 +85,137 @@ def jarFlags(target, source, env, for_signature): jarflags = env.subst('$JARFLAGS', target=target, source=source) for src in source: contents = src.get_text_contents() - if contents[:16] == "Manifest-Version": - if not 'm' in jarflags: + if contents.startswith("Manifest-Version"): + if 'm' not in jarflags: return jarflags + 'm' break return jarflags +def Jar(env, target = None, source = [], *args, **kw): + """ + A pseudo-Builder wrapper around the separate Jar sources{File,Dir} + Builders. + """ + + # jar target should not be a list so assume they passed + # no target and want implicit target to be made and the arg + # was actaully the list of sources + if SCons.Util.is_List(target) and source == []: + SCons.Warnings.Warning("Making implicit target jar file, " + + "and treating the list as sources") + source = target + target = None + + # mutiple targets pass so build each target the same from the + # same source + #TODO Maybe this should only be done once, and the result copied + # for each target since it should result in the same? + if SCons.Util.is_List(target) and SCons.Util.is_List(source): + jars = [] + for single_target in target: + jars += env.Jar( target = single_target, source = source, *args, **kw) + return jars + + # they passed no target so make a target implicitly + if target is None: + try: + # make target from the first source file + target = os.path.splitext(str(source[0]))[0] + env.subst('$JARSUFFIX') + except: + # something strange is happening but attempt anyways + SCons.Warnings.Warning("Could not make implicit target from sources, using directory") + target = os.path.basename(str(env.Dir('.'))) + env.subst('$JARSUFFIX') + + # make lists out of our target and sources + if not SCons.Util.is_List(target): + target = [target] + if not SCons.Util.is_List(source): + source = [source] + + # setup for checking through all the sources and handle accordingly + java_class_suffix = env.subst('$JAVACLASSSUFFIX') + java_suffix = env.subst('$JAVASUFFIX') + target_nodes = [] + + # function for determining what to do with a file and not a directory + # if its already a class file then it can be used as a + # source for jar, otherwise turn it into a class file then + # return the source + def file_to_class(s): + if _my_normcase(str(s)).endswith(java_suffix): + return env.JavaClassFile(source = s, *args, **kw) + else: + return [env.fs.File(s)] + + # function for calling the JavaClassDir builder if a directory is + # passed as a source to Jar builder. The JavaClassDir builder will + # return an empty list if there were not target classes built from + # the directory, in this case assume the user wanted the directory + # copied into the jar as is (it contains other files such as + # resources or class files compiled from proir commands) + # TODO: investigate the expexcted behavior for directories that + # have mixed content, such as Java files along side other files + # files. + def dir_to_class(s): + dir_targets = env.JavaClassDir(source = s, *args, **kw) + if(dir_targets == []): + # no classes files could be built from the source dir + # so pass the dir as is. + return [env.fs.Dir(s)] + else: + return dir_targets + + # loop through the sources and handle each accordingly + # the goal here is to get all the source files into a class + # file or a directory that contains class files + for s in SCons.Util.flatten(source): + s = env.subst(s) + if isinstance(s, SCons.Node.FS.Base): + if isinstance(s, SCons.Node.FS.File): + # found a file so make sure its a class file + target_nodes.extend(file_to_class(s)) + else: + # found a dir so get the class files out of it + target_nodes.extend(dir_to_class(s)) + else: + try: + # source is string try to convert it to file + target_nodes.extend(file_to_class(env.fs.File(s))) + continue + except: + pass + + try: + # source is string try to covnert it to dir + target_nodes.extend(dir_to_class(env.fs.Dir(s))) + continue + except: + pass + + SCons.Warnings.Warning("File: " + str(s) + " could not be identified as File or Directory, skipping.") + + # at this point all our sources have been converted to classes or directories of class + # so pass it to the Jar builder + return env.JarFile(target = target, source = target_nodes, *args, **kw) + def generate(env): """Add Builders and construction variables for jar to an Environment.""" SCons.Tool.CreateJarBuilder(env) + SCons.Tool.CreateJavaFileBuilder(env) + SCons.Tool.CreateJavaClassFileBuilder(env) + SCons.Tool.CreateJavaClassDirBuilder(env) + + env.AddMethod(Jar) + + if env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for jar + paths = get_java_install_dirs('win32') + jar = SCons.Tool.find_program_path(env, 'jar', default_paths=paths) + if jar: + jar_bin_dir = os.path.dirname(jar) + env.AppendENVPath('PATH', jar_bin_dir) + env['JAR'] = 'jar' env['JARFLAGS'] = SCons.Util.CLVar('cf') env['_JARFLAGS'] = jarFlags diff --git a/src/engine/SCons/Tool/jar.xml b/src/engine/SCons/Tool/jar.xml index e18207e..73f6bcb 100644 --- a/src/engine/SCons/Tool/jar.xml +++ b/src/engine/SCons/Tool/jar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/javac.py b/src/engine/SCons/Tool/javac.py index f3cabf3..387afdb 100644 --- a/src/engine/SCons/Tool/javac.py +++ b/src/engine/SCons/Tool/javac.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,15 +30,16 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/javac.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/javac.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import os.path +from collections import OrderedDict import SCons.Action import SCons.Builder from SCons.Node.FS import _my_normcase -from SCons.Tool.JavaCommon import parse_java_file +from SCons.Tool.JavaCommon import parse_java_file, get_java_install_dirs, get_java_include_paths import SCons.Util def classname(path): @@ -70,7 +71,7 @@ def emit_java_classes(target, source, env): if isinstance(entry, SCons.Node.FS.File): slist.append(entry) elif isinstance(entry, SCons.Node.FS.Dir): - result = SCons.Util.OrderedDict() + result = OrderedDict() dirnode = entry.rdir() def find_java_files(arg, dirpath, filenames): java_files = sorted([n for n in filenames @@ -207,6 +208,21 @@ def generate(env): env.AddMethod(Java) + version = env.get('JAVAVERSION', None) + + if env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for javac + paths = get_java_install_dirs('win32', version=version) + javac = SCons.Tool.find_program_path(env, 'javac', default_paths=paths) + if javac: + javac_bin_dir = os.path.dirname(javac) + env.AppendENVPath('PATH', javac_bin_dir) + else: + javac = SCons.Tool.find_program_path(env, 'javac') + + env['JAVAINCLUDES'] = get_java_include_paths(env, javac, version) + + env['JAVAC'] = 'javac' env['JAVACFLAGS'] = SCons.Util.CLVar('') env['JAVABOOTCLASSPATH'] = [] diff --git a/src/engine/SCons/Tool/javac.xml b/src/engine/SCons/Tool/javac.xml index be478ba..dc72f75 100644 --- a/src/engine/SCons/Tool/javac.xml +++ b/src/engine/SCons/Tool/javac.xml @@ -1,285 +1,304 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. --> <!DOCTYPE sconsdoc [ -<!ENTITY % scons SYSTEM '../../../../doc/scons.mod'> -%scons; -<!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'> -%builders-mod; -<!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'> -%functions-mod; -<!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'> -%tools-mod; -<!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'> -%variables-mod; -]> + <!ENTITY % scons SYSTEM '../../../../doc/scons.mod'> + %scons; + <!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'> + %builders-mod; + <!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'> + %functions-mod; + <!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'> + %tools-mod; + <!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'> + %variables-mod; + ]> <sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd"> -<tool name="javac"> -<summary> -<para> -Sets construction variables for the &javac; compiler. -</para> -</summary> -<sets> -<item>JAVAC</item> -<item>JAVACFLAGS</item> -<item>JAVACCOM</item> -<item>JAVACLASSSUFFIX</item> -<item>JAVASUFFIX</item> -<item>JAVABOOTCLASSPATH</item> -<item>JAVACLASSPATH</item> -<item>JAVASOURCEPATH</item> -</sets> -<uses> -<item>JAVACCOMSTR</item> -</uses> -</tool> + <tool name="javac"> + <summary> + <para> + Sets construction variables for the &javac; compiler. + </para> + </summary> + <sets> + <item>JAVAC</item> + <item>JAVACFLAGS</item> + <item>JAVACCOM</item> + <item>JAVACLASSSUFFIX</item> + <item>JAVAINCLUDES</item> + <item>JAVASUFFIX</item> + <item>JAVABOOTCLASSPATH</item> + <item>JAVACLASSPATH</item> + <item>JAVASOURCEPATH</item> + </sets> + <uses> + <item>JAVACCOMSTR</item> + </uses> + </tool> -<builder name="Java"> -<summary> -<para> -Builds one or more Java class files. -The sources may be any combination of explicit -<filename>.java</filename> files, -or directory trees which will be scanned -for <filename>.java</filename> files. -</para> + <builder name="Java"> + <summary> + <para> + Builds one or more Java class files. + The sources may be any combination of explicit + <filename>.java</filename> + files, + or directory trees which will be scanned + for <filename>.java</filename> files. + </para> -<para> -SCons will parse each source <filename>.java</filename> file -to find the classes -(including inner classes) -defined within that file, -and from that figure out the -target <filename>.class</filename> files that will be created. -The class files will be placed underneath -the specified target directory. -</para> + <para> + SCons will parse each source <filename>.java</filename> file + to find the classes + (including inner classes) + defined within that file, + and from that figure out the + target <filename>.class</filename> files that will be created. + The class files will be placed underneath + the specified target directory. + </para> -<para> -SCons will also search each Java file -for the Java package name, -which it assumes can be found on a line -beginning with the string -<literal>package</literal> -in the first column; -the resulting <filename>.class</filename> files -will be placed in a directory reflecting -the specified package name. -For example, -the file -<filename>Foo.java</filename> -defining a single public -<classname>Foo</classname> -class and -containing a package name of -<classname>sub.dir</classname> -will generate a corresponding -<filename>sub/dir/Foo.class</filename> -class file. -</para> + <para> + SCons will also search each Java file + for the Java package name, + which it assumes can be found on a line + beginning with the string + <literal>package</literal> + in the first column; + the resulting <filename>.class</filename> files + will be placed in a directory reflecting + the specified package name. + For example, + the file + <filename>Foo.java</filename> + defining a single public + <classname>Foo</classname> + class and + containing a package name of + <classname>sub.dir</classname> + will generate a corresponding + <filename>sub/dir/Foo.class</filename> + class file. + </para> -<para> -Examples: -</para> + <para> + Examples: + </para> -<example_commands> -env.Java(target = 'classes', source = 'src') -env.Java(target = 'classes', source = ['src1', 'src2']) -env.Java(target = 'classes', source = ['File1.java', 'File2.java']) -</example_commands> + <example_commands> + env.Java(target = 'classes', source = 'src') + env.Java(target = 'classes', source = ['src1', 'src2']) + env.Java(target = 'classes', source = ['File1.java', 'File2.java']) + </example_commands> -<para> -Java source files can use the native encoding for the underlying OS. -Since SCons compiles in simple ASCII mode by default, -the compiler will generate warnings about unmappable characters, -which may lead to errors as the file is processed further. -In this case, the user must specify the <literal>LANG</literal> -environment variable to tell the compiler what encoding is used. -For portibility, it's best if the encoding is hard-coded -so that the compile will work if it is done on a system -with a different encoding. -</para> + <para> + Java source files can use the native encoding for the underlying OS. + Since SCons compiles in simple ASCII mode by default, + the compiler will generate warnings about unmappable characters, + which may lead to errors as the file is processed further. + In this case, the user must specify the + <literal>LANG</literal> + environment variable to tell the compiler what encoding is used. + For portibility, it's best if the encoding is hard-coded + so that the compile will work if it is done on a system + with a different encoding. + </para> -<example_commands> -env = Environment() -env['ENV']['LANG'] = 'en_GB.UTF-8' -</example_commands> -</summary> -</builder> + <example_commands> + env = Environment() + env['ENV']['LANG'] = 'en_GB.UTF-8' + </example_commands> + </summary> + </builder> -<cvar name="JAVABOOTCLASSPATH"> -<summary> -<para> -Specifies the list of directories that -will be added to the -&javac; command line -via the <option>-bootclasspath</option> option. -The individual directory names will be -separated by the operating system's path separate character -(<filename>:</filename> on UNIX/Linux/POSIX, -<filename>;</filename> on Windows). -</para> -</summary> -</cvar> + <cvar name="JAVABOOTCLASSPATH"> + <summary> + <para> + Specifies the list of directories that + will be added to the + &javac; command line + via the <option>-bootclasspath</option> option. + The individual directory names will be + separated by the operating system's path separate character + (<filename>:</filename> on UNIX/Linux/POSIX, + <filename>;</filename> + on Windows). + </para> + </summary> + </cvar> -<cvar name="JAVAC"> -<summary> -<para> -The Java compiler. -</para> -</summary> -</cvar> + <cvar name="JAVAINCLUDES"> + <summary> + <para> + Include path for Java header files (such as jni.h) + </para> + </summary> + </cvar> -<cvar name="JAVACCOM"> -<summary> -<para> -The command line used to compile a directory tree containing -Java source files to -corresponding Java class files. -Any options specified in the &cv-link-JAVACFLAGS; construction variable -are included on this command line. -</para> -</summary> -</cvar> + <cvar name="JAVAC"> + <summary> + <para> + The Java compiler. + </para> + </summary> + </cvar> -<cvar name="JAVACCOMSTR"> -<summary> -<para> -The string displayed when compiling -a directory tree of Java source files to -corresponding Java class files. -If this is not set, then &cv-link-JAVACCOM; (the command line) is displayed. -</para> + <cvar name="JAVACCOM"> + <summary> + <para> + The command line used to compile a directory tree containing + Java source files to + corresponding Java class files. + Any options specified in the &cv-link-JAVACFLAGS; construction variable + are included on this command line. + </para> + </summary> + </cvar> -<example_commands> -env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") -</example_commands> -</summary> -</cvar> + <cvar name="JAVACCOMSTR"> + <summary> + <para> + The string displayed when compiling + a directory tree of Java source files to + corresponding Java class files. + If this is not set, then &cv-link-JAVACCOM; (the command line) is displayed. + </para> -<cvar name="JAVACFLAGS"> -<summary> -<para> -General options that are passed to the Java compiler. -</para> -</summary> -</cvar> + <example_commands> + env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") + </example_commands> + </summary> + </cvar> -<cvar name="JAVACLASSDIR"> -<summary> -<para> -The directory in which Java class files may be found. -This is stripped from the beginning of any Java .class -file names supplied to the -<literal>JavaH</literal> -builder. -</para> -</summary> -</cvar> + <cvar name="JAVACFLAGS"> + <summary> + <para> + General options that are passed to the Java compiler. + </para> + </summary> + </cvar> -<cvar name="JAVACLASSPATH"> -<summary> -<para> -Specifies the list of directories that -will be searched for Java -<filename>.class</filename> file. -The directories in this list will be added to the -&javac; and &javah; command lines -via the <option>-classpath</option> option. -The individual directory names will be -separated by the operating system's path separate character -(<filename>:</filename> on UNIX/Linux/POSIX, -<filename>;</filename> on Windows). -</para> + <cvar name="JAVACLASSDIR"> + <summary> + <para> + The directory in which Java class files may be found. + This is stripped from the beginning of any Java .class + file names supplied to the + <literal>JavaH</literal> + builder. + </para> + </summary> + </cvar> -<para> -Note that this currently just adds the specified -directory via the <option>-classpath</option> option. -&SCons; does not currently search the -&cv-JAVACLASSPATH; directories for dependency -<filename>.class</filename> files. -</para> -</summary> -</cvar> + <cvar name="JAVACLASSPATH"> + <summary> + <para> + Specifies the list of directories that + will be searched for Java + <filename>.class</filename> + file. + The directories in this list will be added to the + &javac; and &javah; command lines + via the <option>-classpath</option> option. + The individual directory names will be + separated by the operating system's path separate character + (<filename>:</filename> on UNIX/Linux/POSIX, + <filename>;</filename> + on Windows). + </para> -<cvar name="JAVACLASSSUFFIX"> -<summary> -<para> -The suffix for Java class files; -<filename>.class</filename> -by default. -</para> -</summary> -</cvar> + <para> + Note that this currently just adds the specified + directory via the <option>-classpath</option> option. + &SCons; does not currently search the + &cv-JAVACLASSPATH; directories for dependency + <filename>.class</filename> + files. + </para> + </summary> + </cvar> -<cvar name="JAVASOURCEPATH"> -<summary> -<para> -Specifies the list of directories that -will be searched for input -<filename>.java</filename> file. -The directories in this list will be added to the -&javac; command line -via the <option>-sourcepath</option> option. -The individual directory names will be -separated by the operating system's path separate character -(<filename>:</filename> on UNIX/Linux/POSIX, -<filename>;</filename> on Windows). -</para> + <cvar name="JAVACLASSSUFFIX"> + <summary> + <para> + The suffix for Java class files; + <filename>.class</filename> + by default. + </para> + </summary> + </cvar> -<para> -Note that this currently just adds the specified -directory via the <option>-sourcepath</option> option. -&SCons; does not currently search the -&cv-JAVASOURCEPATH; directories for dependency -<filename>.java</filename> files. -</para> -</summary> -</cvar> + <cvar name="JAVASOURCEPATH"> + <summary> + <para> + Specifies the list of directories that + will be searched for input + <filename>.java</filename> + file. + The directories in this list will be added to the + &javac; command line + via the <option>-sourcepath</option> option. + The individual directory names will be + separated by the operating system's path separate character + (<filename>:</filename> on UNIX/Linux/POSIX, + <filename>;</filename> + on Windows). + </para> -<cvar name="JAVASUFFIX"> -<summary> -<para> -The suffix for Java files; -<filename>.java</filename> -by default. -</para> -</summary> -</cvar> + <para> + Note that this currently just adds the specified + directory via the <option>-sourcepath</option> option. + &SCons; does not currently search the + &cv-JAVASOURCEPATH; directories for dependency + <filename>.java</filename> + files. + </para> + </summary> + </cvar> -<cvar name="JAVAVERSION"> -<summary> -<para> -Specifies the Java version being used by the &b-Java; builder. -This is <emphasis>not</emphasis> currently used to select one -version of the Java compiler vs. another. -Instead, you should set this to specify the version of Java -supported by your &javac; compiler. -The default is <literal>1.4</literal>. -</para> + <cvar name="JAVASUFFIX"> + <summary> + <para> + The suffix for Java files; + <filename>.java</filename> + by default. + </para> + </summary> + </cvar> -<para> -This is sometimes necessary because -Java 1.5 changed the file names that are created -for nested anonymous inner classes, -which can cause a mismatch with the files -that &SCons; expects will be generated by the &javac; compiler. -Setting &cv-JAVAVERSION; to <literal>1.5</literal> -(or <literal>1.6</literal>, as appropriate) -can make &SCons; realize that a Java 1.5 or 1.6 -build is actually up to date. -</para> -</summary> -</cvar> + <cvar name="JAVAVERSION"> + <summary> + <para> + Specifies the Java version being used by the &b-Java; builder. + This is <emphasis>not</emphasis> currently used to select one + version of the Java compiler vs. another. + Instead, you should set this to specify the version of Java + supported by your &javac; compiler. + The default is <literal>1.4</literal>. + </para> + + <para> + This is sometimes necessary because + Java 1.5 changed the file names that are created + for nested anonymous inner classes, + which can cause a mismatch with the files + that &SCons; expects will be generated by the &javac; compiler. + Setting &cv-JAVAVERSION; to + <literal>1.5</literal> + (or <literal>1.6</literal>, as appropriate) + can make &SCons; realize that a Java 1.5 or 1.6 + build is actually up to date. + </para> + </summary> + </cvar> </sconsdoc> diff --git a/src/engine/SCons/Tool/javacTests.py b/src/engine/SCons/Tool/javacTests.py index 0debbb6..067ff3e 100644 --- a/src/engine/SCons/Tool/javacTests.py +++ b/src/engine/SCons/Tool/javacTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,8 +24,6 @@ import os import unittest -import TestUnit - import SCons.Tool.javac class DummyNode(object): @@ -40,14 +38,14 @@ class pathoptTestCase(unittest.TestCase): popt = SCons.Tool.javac.pathopt('-foopath', 'FOOPATH') env = {'FOOPATH': path} actual = popt(None, None, env, None) - self.assertEquals(expect, actual) + self.assertEqual(expect, actual) def assert_pathopt_default(self, expect, path, default): popt = SCons.Tool.javac.pathopt('-foopath', 'FOOPATH', default='DPATH') env = {'FOOPATH': path, 'DPATH': default} actual = popt(None, None, env, None) - self.assertEquals(expect, actual) + self.assertEqual(expect, actual) def test_unset(self): self.assert_pathopt([], None) @@ -101,5 +99,4 @@ class pathoptTestCase(unittest.TestCase): '') if __name__ == "__main__": - suite = unittest.makeSuite(pathoptTestCase, 'test_') - TestUnit.run(suite) + unittest.main() diff --git a/src/engine/SCons/Tool/javah.py b/src/engine/SCons/Tool/javah.py index 0e1885c..251778d 100644 --- a/src/engine/SCons/Tool/javah.py +++ b/src/engine/SCons/Tool/javah.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/javah.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/javah.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path @@ -40,6 +40,8 @@ import SCons.Builder import SCons.Node.FS import SCons.Tool.javac import SCons.Util +from SCons.Tool.JavaCommon import get_java_install_dirs + def emit_java_headers(target, source, env): """Create and return lists of Java stub header files that will @@ -120,6 +122,14 @@ def generate(env): java_javah = SCons.Tool.CreateJavaHBuilder(env) java_javah.emitter = emit_java_headers + if env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for javah + paths = get_java_install_dirs('win32') + javah = SCons.Tool.find_program_path(env, 'javah', default_paths=paths) + if javah: + javah_bin_dir = os.path.dirname(javah) + env.AppendENVPath('PATH', javah_bin_dir) + env['_JAVAHOUTFLAG'] = JavaHOutFlagGenerator env['JAVAH'] = 'javah' env['JAVAHFLAGS'] = SCons.Util.CLVar('') diff --git a/src/engine/SCons/Tool/javah.xml b/src/engine/SCons/Tool/javah.xml index f362e3e..f72a6cd 100644 --- a/src/engine/SCons/Tool/javah.xml +++ b/src/engine/SCons/Tool/javah.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/latex.py b/src/engine/SCons/Tool/latex.py index aa7ea15..3f1af08 100644 --- a/src/engine/SCons/Tool/latex.py +++ b/src/engine/SCons/Tool/latex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/latex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/latex.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Action import SCons.Defaults diff --git a/src/engine/SCons/Tool/latex.xml b/src/engine/SCons/Tool/latex.xml index bb0816d..b4eb45a 100644 --- a/src/engine/SCons/Tool/latex.xml +++ b/src/engine/SCons/Tool/latex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ldc.py b/src/engine/SCons/Tool/ldc.py index 5bb04ff..dda1a5e 100644 --- a/src/engine/SCons/Tool/ldc.py +++ b/src/engine/SCons/Tool/ldc.py @@ -26,7 +26,7 @@ Lib tool variables: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -48,7 +48,7 @@ Lib tool variables: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ldc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ldc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import subprocess diff --git a/src/engine/SCons/Tool/ldc.xml b/src/engine/SCons/Tool/ldc.xml index 1479867..691145a 100644 --- a/src/engine/SCons/Tool/ldc.xml +++ b/src/engine/SCons/Tool/ldc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/lex.py b/src/engine/SCons/Tool/lex.py index e185b93..4831776 100644 --- a/src/engine/SCons/Tool/lex.py +++ b/src/engine/SCons/Tool/lex.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,16 +31,25 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/lex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/lex.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path +import sys import SCons.Action import SCons.Tool import SCons.Util +from SCons.Platform.mingw import MINGW_DEFAULT_PATHS +from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS +from SCons.Platform.win32 import CHOCO_DEFAULT_PATH LexAction = SCons.Action.Action("$LEXCOM", "$LEXCOMSTR") +if sys.platform == 'win32': + BINS = ['flex', 'lex', 'win_flex'] +else: + BINS = ["flex", "lex"] + def lexEmitter(target, source, env): sourceBase, sourceExt = os.path.splitext(SCons.Util.to_String(source[0])) @@ -64,6 +73,29 @@ def lexEmitter(target, source, env): target.append(fileName) return (target, source) +def get_lex_path(env, append_paths=False): + """ + Find the path to the lex tool, searching several possible names + + Only called in the Windows case, so the default_path + can be Windows-specific + + :param env: current construction environment + :param append_paths: if set, add the path to the tool to PATH + :return: path to lex tool, if found + """ + for prog in BINS: + bin_path = SCons.Tool.find_program_path( + env, + prog, + default_paths=CHOCO_DEFAULT_PATH + MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if bin_path: + if append_paths: + env.AppendENVPath('PATH', os.path.dirname(bin_path)) + return bin_path + SCons.Warnings.Warning('lex tool requested, but lex or flex binary not found in ENV PATH') + + def generate(env): """Add Builders and construction variables for lex to an Environment.""" c_file, cxx_file = SCons.Tool.createCFileBuilders(env) @@ -83,12 +115,24 @@ def generate(env): cxx_file.add_action(".ll", LexAction) cxx_file.add_emitter(".ll", lexEmitter) - env["LEX"] = env.Detect("flex") or "lex" env["LEXFLAGS"] = SCons.Util.CLVar("") - env["LEXCOM"] = "$LEX $LEXFLAGS -t $SOURCES > $TARGET" + + if sys.platform == 'win32': + # ignore the return - we do not need the full path here + _ = get_lex_path(env, append_paths=True) + env["LEX"] = env.Detect(BINS) + if not env.get("LEXUNISTD"): + env["LEXUNISTD"] = SCons.Util.CLVar("") + env["LEXCOM"] = "$LEX $LEXUNISTD $LEXFLAGS -t $SOURCES > $TARGET" + else: + env["LEX"] = env.Detect(BINS) + env["LEXCOM"] = "$LEX $LEXFLAGS -t $SOURCES > $TARGET" def exists(env): - return env.Detect(["flex", "lex"]) + if sys.platform == 'win32': + return get_lex_path(env) + else: + return env.Detect(BINS) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/lex.xml b/src/engine/SCons/Tool/lex.xml index e178308..0d044b8 100644 --- a/src/engine/SCons/Tool/lex.xml +++ b/src/engine/SCons/Tool/lex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -33,6 +33,7 @@ Sets construction variables for the &lex; lexical analyser. <item>LEX</item> <item>LEXFLAGS</item> <item>LEXCOM</item> +<item>LEXUNISTD</item> </sets> <uses> <item>LEXCOMSTR</item> @@ -78,4 +79,12 @@ General options passed to the lexical analyzer generator. </summary> </cvar> +<cvar name="LEXUNISTD"> +<summary> +<para> +Used only on windows environments to set a lex flag to prevent 'unistd.h' from being included. The default value is '--nounistd'. +</para> +</summary> +</cvar> + </sconsdoc> diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index e8c11ed..dcaf91f 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -1,4 +1,3 @@ - """SCons.Tool.link Tool-specific initialization for the generic Posix linker. @@ -10,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +32,7 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/link.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/link.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import sys import re @@ -47,22 +46,21 @@ from SCons.Tool.FortranCommon import isfortran from SCons.Tool.DCommon import isD -import SCons.Tool.cxx -cplusplus = SCons.Tool.cxx -# cplusplus = __import__(__package__+'.cxx', globals(), locals(), ['*']) +from SCons.Tool.cxx import iscplusplus issued_mixed_link_warning = False + def smart_link(source, target, env, for_signature): - has_cplusplus = cplusplus.iscplusplus(source) + has_cplusplus = iscplusplus(source) has_fortran = isfortran(env, source) has_d = isD(env, source) if has_cplusplus and has_fortran and not has_d: global issued_mixed_link_warning if not issued_mixed_link_warning: msg = "Using $CXX to link Fortran and C++ code together.\n\t" + \ - "This may generate a buggy executable if the '%s'\n\t" + \ - "compiler does not know how to deal with Fortran runtimes." + "This may generate a buggy executable if the '%s'\n\t" + \ + "compiler does not know how to deal with Fortran runtimes." SCons.Warnings.warn(SCons.Warnings.FortranCxxMixWarning, msg % env.subst('$CXX')) issued_mixed_link_warning = True @@ -77,11 +75,14 @@ def smart_link(source, target, env, for_signature): return '$CXX' return '$CC' + def _lib_emitter(target, source, env, **kw): Verbose = False if Verbose: - print("_lib_emitter: target[0]={:r}".format(target[0].get_path())) + print("_lib_emitter: target[0]={!r}".format(target[0].get_path())) for tgt in target: + if SCons.Util.is_String(tgt): + tgt = env.File(tgt) tgt.attributes.shared = 1 try: @@ -90,21 +91,24 @@ def _lib_emitter(target, source, env, **kw): pass else: if Verbose: - print("_lib_emitter: symlink_generator={:r}".format(symlink_generator)) + print("_lib_emitter: symlink_generator={!r}".format(symlink_generator)) symlinks = symlink_generator(env, target[0]) if Verbose: - print("_lib_emitter: symlinks={:r}".format(symlinks)) + print("_lib_emitter: symlinks={!r}".format(symlinks)) if symlinks: SCons.Tool.EmitLibSymlinks(env, symlinks, target[0]) target[0].attributes.shliblinks = symlinks return (target, source) + def shlib_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator = SCons.Tool.ShLibSymlinkGenerator) + return _lib_emitter(target, source, env, symlink_generator=SCons.Tool.ShLibSymlinkGenerator) + def ldmod_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator = SCons.Tool.LdModSymlinkGenerator) + return _lib_emitter(target, source, env, symlink_generator=SCons.Tool.LdModSymlinkGenerator) + # This is generic enough to be included here... def _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw): @@ -112,98 +116,107 @@ def _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, Verbose = False if Verbose: - print("_versioned_lib_name: libnode={:r}".format(libnode.get_path())) - print("_versioned_lib_name: version={:r}".format(version)) - print("_versioned_lib_name: prefix={:r}".format(prefix)) - print("_versioned_lib_name: suffix={:r}".format(suffix)) - print("_versioned_lib_name: suffix_generator={:r}".format(suffix_generator)) + print("_versioned_lib_name: libnode={!r}".format(libnode.get_path())) + print("_versioned_lib_name: version={!r}".format(version)) + print("_versioned_lib_name: prefix={!r}".format(prefix)) + print("_versioned_lib_name: suffix={!r}".format(suffix)) + print("_versioned_lib_name: suffix_generator={!r}".format(suffix_generator)) versioned_name = os.path.basename(libnode.get_path()) if Verbose: - print("_versioned_lib_name: versioned_name={:r}".format(versioned_name)) + print("_versioned_lib_name: versioned_name={!r}".format(versioned_name)) versioned_prefix = prefix_generator(env, **kw) versioned_suffix = suffix_generator(env, **kw) if Verbose: - print("_versioned_lib_name: versioned_prefix={:r}".format(versioned_prefix)) - print("_versioned_lib_name: versioned_suffix={:r}".format(versioned_suffix)) + print("_versioned_lib_name: versioned_prefix={!r}".format(versioned_prefix)) + print("_versioned_lib_name: versioned_suffix={!r}".format(versioned_suffix)) versioned_prefix_re = '^' + re.escape(versioned_prefix) versioned_suffix_re = re.escape(versioned_suffix) + '$' name = re.sub(versioned_prefix_re, prefix, versioned_name) name = re.sub(versioned_suffix_re, suffix, name) if Verbose: - print("_versioned_lib_name: name={:r}".format(name)) + print("_versioned_lib_name: name={!r}".format(name)) return name + def _versioned_shlib_name(env, libnode, version, prefix, suffix, **kw): - pg = SCons.Tool.ShLibPrefixGenerator - sg = SCons.Tool.ShLibSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, pg, sg, **kw) + prefix_generator = SCons.Tool.ShLibPrefixGenerator + suffix_generator = SCons.Tool.ShLibSuffixGenerator + return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) + def _versioned_ldmod_name(env, libnode, version, prefix, suffix, **kw): - pg = SCons.Tool.LdModPrefixGenerator - sg = SCons.Tool.LdModSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, pg, sg, **kw) + prefix_generator = SCons.Tool.LdModPrefixGenerator + suffix_generator = SCons.Tool.LdModSuffixGenerator + return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) + def _versioned_lib_suffix(env, suffix, version): """For suffix='.so' and version='0.1.2' it returns '.so.0.1.2'""" Verbose = False if Verbose: - print("_versioned_lib_suffix: suffix={:r}".format(suffix)) - print("_versioned_lib_suffix: version={:r}".format(version)) + print("_versioned_lib_suffix: suffix={!r}".format(suffix)) + print("_versioned_lib_suffix: version={!r}".format(version)) if not suffix.endswith(version): suffix = suffix + '.' + version if Verbose: - print("_versioned_lib_suffix: return suffix={:r}".format(suffix)) + print("_versioned_lib_suffix: return suffix={!r}".format(suffix)) return suffix + def _versioned_lib_soname(env, libnode, version, prefix, suffix, name_func): """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so.X'""" Verbose = False if Verbose: - print("_versioned_lib_soname: version={:r}".format(version)) + print("_versioned_lib_soname: version={!r}".format(version)) name = name_func(env, libnode, version, prefix, suffix) if Verbose: - print("_versioned_lib_soname: name={:r}".format(name)) + print("_versioned_lib_soname: name={!r}".format(name)) major = version.split('.')[0] soname = name + '.' + major if Verbose: - print("_versioned_lib_soname: soname={:r}".format(soname)) + print("_versioned_lib_soname: soname={!r}".format(soname)) return soname + def _versioned_shlib_soname(env, libnode, version, prefix, suffix): return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_shlib_name) + def _versioned_ldmod_soname(env, libnode, version, prefix, suffix): return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_ldmod_name) + def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func): - """Generate link names that should be created for a versioned shared lirbrary. + """Generate link names that should be created for a versioned shared library. Returns a dictionary in the form { linkname : linktarget } """ Verbose = False if Verbose: - print("_versioned_lib_symlinks: libnode={:r}".format(libnode.get_path())) - print("_versioned_lib_symlinks: version={:r}".format(version)) + print("_versioned_lib_symlinks: libnode={!r}".format(libnode.get_path())) + print("_versioned_lib_symlinks: version={!r}".format(version)) if sys.platform.startswith('openbsd'): # OpenBSD uses x.y shared library versioning numbering convention # and doesn't use symlinks to backwards-compatible libraries if Verbose: - print("_versioned_lib_symlinks: return symlinks={:r}".format(None)) + print("_versioned_lib_symlinks: return symlinks={!r}".format(None)) return None linkdir = libnode.get_dir() if Verbose: - print("_versioned_lib_symlinks: linkdir={:r}".format(linkdir.get_path())) + print("_versioned_lib_symlinks: linkdir={!r}".format(linkdir.get_path())) name = name_func(env, libnode, version, prefix, suffix) if Verbose: - print("_versioned_lib_symlinks: name={:r}".format(name)) + print("_versioned_lib_symlinks: name={!r}".format(name)) soname = soname_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_versioned_lib_symlinks: soname={!r}".format(soname)) link0 = env.fs.File(soname, linkdir) link1 = env.fs.File(name, linkdir) @@ -211,50 +224,63 @@ def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, so # We create direct symlinks, not daisy-chained. if link0 == libnode: # This enables SHLIBVERSION without periods (e.g. SHLIBVERSION=1) - symlinks = [ (link1, libnode) ] + symlinks = [(link1, libnode)] else: # This handles usual SHLIBVERSION, i.e. '1.2', '1.2.3', etc. - symlinks = [ (link0, libnode), (link1, libnode) ] + symlinks = [(link0, libnode), (link1, libnode)] if Verbose: - print("_versioned_lib_symlinks: return symlinks={:r}".format(SCons.Tool.StringizeLibSymlinks(symlinks))) + print("_versioned_lib_symlinks: return symlinks={!r}".format(SCons.Tool.StringizeLibSymlinks(symlinks))) return symlinks + def _versioned_shlib_symlinks(env, libnode, version, prefix, suffix): - nf = _versioned_shlib_name - sf = _versioned_shlib_soname - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, nf, sf) + name_func = env['LINKCALLBACKS']['VersionedShLibName'] + soname_func = env['LINKCALLBACKS']['VersionedShLibSoname'] + + return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) + def _versioned_ldmod_symlinks(env, libnode, version, prefix, suffix): - nf = _versioned_ldmod_name - sf = _versioned_ldmod_soname - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, nf, sf) + name_func = _versioned_ldmod_name + soname_func = _versioned_ldmod_soname + + name_func = env['LINKCALLBACKS']['VersionedLdModName'] + soname_func = env['LINKCALLBACKS']['VersionedLdModSoname'] + + return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) + def _versioned_lib_callbacks(): return { - 'VersionedShLibSuffix' : _versioned_lib_suffix, - 'VersionedLdModSuffix' : _versioned_lib_suffix, - 'VersionedShLibSymlinks' : _versioned_shlib_symlinks, - 'VersionedLdModSymlinks' : _versioned_ldmod_symlinks, - 'VersionedShLibName' : _versioned_shlib_name, - 'VersionedLdModName' : _versioned_ldmod_name, - 'VersionedShLibSoname' : _versioned_shlib_soname, - 'VersionedLdModSoname' : _versioned_ldmod_soname, + 'VersionedShLibSuffix': _versioned_lib_suffix, + 'VersionedLdModSuffix': _versioned_lib_suffix, + 'VersionedShLibSymlinks': _versioned_shlib_symlinks, + 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, + 'VersionedShLibName': _versioned_shlib_name, + 'VersionedLdModName': _versioned_ldmod_name, + 'VersionedShLibSoname': _versioned_shlib_soname, + 'VersionedLdModSoname': _versioned_ldmod_soname, }.copy() + def _setup_versioned_lib_variables(env, **kw): """ Setup all variables required by the versioning machinery """ tool = None - try: tool = kw['tool'] - except KeyError: pass + try: + tool = kw['tool'] + except KeyError: + pass use_soname = False - try: use_soname = kw['use_soname'] - except KeyError: pass + try: + use_soname = kw['use_soname'] + except KeyError: + pass # The $_SHLIBVERSIONFLAGS define extra commandline flags used when # building VERSIONED shared libraries. It's always set, but used only @@ -284,22 +310,25 @@ def generate(env): SCons.Tool.createSharedLibBuilder(env) SCons.Tool.createProgBuilder(env) - env['SHLINK'] = '$LINK' + env['SHLINK'] = '$LINK' env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared') - env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' - # don't set up the emitter, cause AppendUnique will generate a list + env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + + # don't set up the emitter, because AppendUnique will generate a list # starting with None :-( - env.Append(SHLIBEMITTER = [shlib_emitter]) - env['SMARTLINK'] = smart_link - env['LINK'] = "$SMARTLINK" - env['LINKFLAGS'] = SCons.Util.CLVar('') + env.Append(SHLIBEMITTER=[shlib_emitter]) + + env['SMARTLINK'] = smart_link + env['LINK'] = "$SMARTLINK" + env['LINKFLAGS'] = SCons.Util.CLVar('') + # __RPATH is only set to something ($_RPATH typically) on platforms that support it. - env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' - env['LIBDIRPREFIX']='-L' - env['LIBDIRSUFFIX']='' - env['_LIBFLAGS']='${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}' - env['LIBLINKPREFIX']='-l' - env['LIBLINKSUFFIX']='' + env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + env['LIBDIRPREFIX'] = '-L' + env['LIBDIRSUFFIX'] = '' + env['_LIBFLAGS'] = '${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}' + env['LIBLINKPREFIX'] = '-l' + env['LIBLINKSUFFIX'] = '' if env['PLATFORM'] == 'hpux': env['SHLIBSUFFIX'] = '.sl' @@ -311,14 +340,16 @@ def generate(env): # setting them the same means that LoadableModule works everywhere. SCons.Tool.createLoadableModuleBuilder(env) env['LDMODULE'] = '$SHLINK' - env.Append(LDMODULEEMITTER = [ldmod_emitter]) + env.Append(LDMODULEEMITTER=[ldmod_emitter]) env['LDMODULEPREFIX'] = '$SHLIBPREFIX' env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' env['LDMODULEFLAGS'] = '$SHLINKFLAGS' - env['LDMODULECOM'] = '$LDMODULE -o $TARGET $LDMODULEFLAGS $__LDMODULEVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + env[ + 'LDMODULECOM'] = '$LDMODULE -o $TARGET $LDMODULEFLAGS $__LDMODULEVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' env['LDMODULEVERSION'] = '$SHLIBVERSION' env['LDMODULENOVERSIONSYMLINKS'] = '$SHLIBNOVERSIONSYMLINKS' + def exists(env): # This module isn't really a Tool on its own, it's common logic for # other linkers. diff --git a/src/engine/SCons/Tool/link.xml b/src/engine/SCons/Tool/link.xml index 669a020..a8b6954 100644 --- a/src/engine/SCons/Tool/link.xml +++ b/src/engine/SCons/Tool/link.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/linkloc.py b/src/engine/SCons/Tool/linkloc.py index b79be06..42d010d 100644 --- a/src/engine/SCons/Tool/linkloc.py +++ b/src/engine/SCons/Tool/linkloc.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/linkloc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/linkloc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path import re diff --git a/src/engine/SCons/Tool/linkloc.xml b/src/engine/SCons/Tool/linkloc.xml index 09b43cb..567ed66 100644 --- a/src/engine/SCons/Tool/linkloc.xml +++ b/src/engine/SCons/Tool/linkloc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/m4.py b/src/engine/SCons/Tool/m4.py index 38b9976..0ecc82a 100644 --- a/src/engine/SCons/Tool/m4.py +++ b/src/engine/SCons/Tool/m4.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/m4.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/m4.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Action import SCons.Builder diff --git a/src/engine/SCons/Tool/m4.xml b/src/engine/SCons/Tool/m4.xml index f919af9..f7e81e5 100644 --- a/src/engine/SCons/Tool/m4.xml +++ b/src/engine/SCons/Tool/m4.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/masm.py b/src/engine/SCons/Tool/masm.py index 90162f4..cf147a7 100644 --- a/src/engine/SCons/Tool/masm.py +++ b/src/engine/SCons/Tool/masm.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/masm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/masm.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/masm.xml b/src/engine/SCons/Tool/masm.xml index acc3aa3..1760252 100644 --- a/src/engine/SCons/Tool/masm.xml +++ b/src/engine/SCons/Tool/masm.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/midl.py b/src/engine/SCons/Tool/midl.py index 4088fc4..f75204a 100644 --- a/src/engine/SCons/Tool/midl.py +++ b/src/engine/SCons/Tool/midl.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/midl.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/midl.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Action import SCons.Builder @@ -79,7 +79,7 @@ def generate(env): env['BUILDERS']['TypeLibrary'] = midl_builder def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/midl.xml b/src/engine/SCons/Tool/midl.xml index cc1b880..717eb38 100644 --- a/src/engine/SCons/Tool/midl.xml +++ b/src/engine/SCons/Tool/midl.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mingw.py b/src/engine/SCons/Tool/mingw.py index c2eaa96..8410d2f 100644 --- a/src/engine/SCons/Tool/mingw.py +++ b/src/engine/SCons/Tool/mingw.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,10 +31,11 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mingw.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mingw.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import os.path +import glob import SCons.Action import SCons.Builder @@ -42,29 +43,17 @@ import SCons.Defaults import SCons.Tool import SCons.Util -# This is what we search for to find mingw: -key_program = 'mingw32-gcc' - -def find(env): - # First search in the SCons path - path=env.WhereIs(key_program) - if (path): - return path - # then the OS path: - path=SCons.Util.WhereIs(key_program) - if (path): - return path - - # If that doesn't work try default location for mingw - save_path=env['ENV']['PATH'] - env.AppendENVPath('PATH',r'c:\MinGW\bin') - path =env.WhereIs(key_program) - if not path: - env['ENV']['PATH']=save_path - return path +mingw_paths = [ + r'c:\MinGW\bin', + r'C:\cygwin64\bin', + r'C:\msys64', + r'C:\cygwin\bin', + r'C:\msys', +] + def shlib_generator(target, source, env, for_signature): - cmd = SCons.Util.CLVar(['$SHLINK', '$SHLINKFLAGS']) + cmd = SCons.Util.CLVar(['$SHLINK', '$SHLINKFLAGS']) dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX') if dll: cmd.extend(['-o', dll]) @@ -72,31 +61,32 @@ def shlib_generator(target, source, env, for_signature): cmd.extend(['$SOURCES', '$_LIBDIRFLAGS', '$_LIBFLAGS']) implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX') - if implib: cmd.append('-Wl,--out-implib,'+implib.get_string(for_signature)) + if implib: cmd.append('-Wl,--out-implib,' + implib.get_string(for_signature)) def_target = env.FindIxes(target, 'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX') insert_def = env.subst("$WINDOWS_INSERT_DEF") - if not insert_def in ['', '0', 0] and def_target: \ - cmd.append('-Wl,--output-def,'+def_target.get_string(for_signature)) + if insert_def not in ['', '0', 0] and def_target: \ + cmd.append('-Wl,--output-def,' + def_target.get_string(for_signature)) return [cmd] + def shlib_emitter(target, source, env): dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX') no_import_lib = env.get('no_import_lib', 0) if not dll: - raise SCons.Errors.UserError("A shared library should have exactly one target with the suffix: %s Target(s) are:%s" % \ + raise SCons.Errors.UserError( + "A shared library should have exactly one target with the suffix: %s Target(s) are:%s" % \ (env.subst("$SHLIBSUFFIX"), ",".join([str(t) for t in target]))) - - if not no_import_lib and \ - not env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX'): + if not no_import_lib and \ + not env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX'): # Create list of target libraries as strings - targetStrings=env.ReplaceIxes(dll, - 'SHLIBPREFIX', 'SHLIBSUFFIX', - 'LIBPREFIX', 'LIBSUFFIX') - + targetStrings = env.ReplaceIxes(dll, + 'SHLIBPREFIX', 'SHLIBSUFFIX', + 'LIBPREFIX', 'LIBSUFFIX') + # Now add file nodes to target list target.append(env.fs.File(targetStrings)) @@ -108,17 +98,18 @@ def shlib_emitter(target, source, env): skip_def_insert = env.subst("$WINDOWS_INSERT_DEF") in ['', '0', 0] if not def_source and not def_target and not skip_def_insert: # Create list of target libraries and def files as strings - targetStrings=env.ReplaceIxes(dll, - 'SHLIBPREFIX', 'SHLIBSUFFIX', - 'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX') - + targetStrings = env.ReplaceIxes(dll, + 'SHLIBPREFIX', 'SHLIBSUFFIX', + 'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX') + # Now add file nodes to target list target.append(env.fs.File(targetStrings)) return (target, source) - -shlib_action = SCons.Action.Action(shlib_generator, generator=1) + +shlib_action = SCons.Action.Action(shlib_generator, '$SHLINKCOMSTR', generator=1) +ldmodule_action = SCons.Action.Action(shlib_generator, '$LDMODULECOMSTR', generator=1) res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR') @@ -126,38 +117,63 @@ res_builder = SCons.Builder.Builder(action=res_action, suffix='.o', source_scanner=SCons.Tool.SourceFileScanner) SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan) +# This is what we search for to find mingw: +# key_program = 'mingw32-gcc' +key_program = 'mingw32-make' + + +def find_version_specific_mingw_paths(): + r""" + One example of default mingw install paths is: + C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev2\mingw64\bin + + Use glob'ing to find such and add to mingw_paths + """ + new_paths = glob.glob(r"C:\mingw-w64\*\mingw64\bin") + + return new_paths + + def generate(env): - mingw = find(env) + global mingw_paths + # Check for reasoanble mingw default paths + mingw_paths += find_version_specific_mingw_paths() + + mingw = SCons.Tool.find_program_path(env, key_program, default_paths=mingw_paths) if mingw: - dir = os.path.dirname(mingw) - env.PrependENVPath('PATH', dir ) - + mingw_bin_dir = os.path.dirname(mingw) + env.AppendENVPath('PATH', mingw_bin_dir) # Most of mingw is the same as gcc and friends... gnu_tools = ['gcc', 'g++', 'gnulink', 'ar', 'gas', 'gfortran', 'm4'] for tool in gnu_tools: SCons.Tool.Tool(tool)(env) - #... but a few things differ: + # ... but a few things differ: env['CC'] = 'gcc' + # make sure the msvc tool doesnt break us, it added a /flag + if 'CCFLAGS' in env: + # make sure its a CLVar to handle list or str cases + if type(env['CCFLAGS']) is not SCons.Util.CLVar: + env['CCFLAGS'] = SCons.Util.CLVar(env['CCFLAGS']) + env['CCFLAGS'] = SCons.Util.CLVar(str(env['CCFLAGS']).replace('/nologo', '')) env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS') env['CXX'] = 'g++' env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS') env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared') - env['SHLINKCOM'] = shlib_action - env['LDMODULECOM'] = shlib_action - env.Append(SHLIBEMITTER = [shlib_emitter]) - env.Append(LDMODULEEMITTER = [shlib_emitter]) + env['SHLINKCOM'] = shlib_action + env['LDMODULECOM'] = ldmodule_action + env.Append(SHLIBEMITTER=[shlib_emitter]) + env.Append(LDMODULEEMITTER=[shlib_emitter]) env['AS'] = 'as' - env['WIN32DEFPREFIX'] = '' - env['WIN32DEFSUFFIX'] = '.def' - env['WINDOWSDEFPREFIX'] = '${WIN32DEFPREFIX}' - env['WINDOWSDEFSUFFIX'] = '${WIN32DEFSUFFIX}' + env['WIN32DEFPREFIX'] = '' + env['WIN32DEFSUFFIX'] = '.def' + env['WINDOWSDEFPREFIX'] = '${WIN32DEFPREFIX}' + env['WINDOWSDEFSUFFIX'] = '${WIN32DEFSUFFIX}' env['SHOBJSUFFIX'] = '.o' env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1 - env['RC'] = 'windres' env['RCFLAGS'] = SCons.Util.CLVar('') env['RCINCFLAGS'] = '$( ${_concat(RCINCPREFIX, CPPPATH, RCINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' @@ -165,15 +181,21 @@ def generate(env): env['RCINCSUFFIX'] = '' env['RCCOM'] = '$RC $_CPPDEFFLAGS $RCINCFLAGS ${RCINCPREFIX} ${SOURCE.dir} $RCFLAGS -i $SOURCE -o $TARGET' env['BUILDERS']['RES'] = res_builder - + # Some setting from the platform also have to be overridden: env['OBJSUFFIX'] = '.o' env['LIBPREFIX'] = 'lib' env['LIBSUFFIX'] = '.a' env['PROGSUFFIX'] = '.exe' + def exists(env): - return find(env) + mingw = SCons.Tool.find_program_path(env, key_program, default_paths=mingw_paths) + if mingw: + mingw_bin_dir = os.path.dirname(mingw) + env.AppendENVPath('PATH', mingw_bin_dir) + + return mingw # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mingw.xml b/src/engine/SCons/Tool/mingw.xml index 4848637..b1f028d 100644 --- a/src/engine/SCons/Tool/mingw.xml +++ b/src/engine/SCons/Tool/mingw.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/msgfmt.py b/src/engine/SCons/Tool/msgfmt.py index 7e3e2a4..c8141a0 100644 --- a/src/engine/SCons/Tool/msgfmt.py +++ b/src/engine/SCons/Tool/msgfmt.py @@ -1,6 +1,6 @@ """ msgfmt tool """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msgfmt.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msgfmt.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from SCons.Builder import BuilderBase ############################################################################# @@ -75,8 +75,22 @@ def _create_mo_file_builder(env, **kw): ############################################################################# def generate(env,**kw): """ Generate `msgfmt` tool """ + import sys + import os import SCons.Util + import SCons.Tool from SCons.Tool.GettextCommon import _detect_msgfmt + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + + if sys.platform == 'win32': + msgfmt = SCons.Tool.find_program_path(env, 'msgfmt', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if msgfmt: + msgfmt_bin_dir = os.path.dirname(msgfmt) + env.AppendENVPath('PATH', msgfmt_bin_dir) + else: + SCons.Warnings.Warning('msgfmt tool requested, but binary not found in ENV PATH') + try: env['MSGFMT'] = _detect_msgfmt(env) except: diff --git a/src/engine/SCons/Tool/msgfmt.xml b/src/engine/SCons/Tool/msgfmt.xml index e00f372..67a8e0d 100644 --- a/src/engine/SCons/Tool/msgfmt.xml +++ b/src/engine/SCons/Tool/msgfmt.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/msginit.py b/src/engine/SCons/Tool/msginit.py index 63daf7f..69e803a 100644 --- a/src/engine/SCons/Tool/msginit.py +++ b/src/engine/SCons/Tool/msginit.py @@ -3,7 +3,7 @@ Tool specific initialization of msginit tool. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Tool specific initialization of msginit tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msginit.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msginit.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Warnings import SCons.Builder @@ -77,8 +77,22 @@ def _POInitBuilderWrapper(env, target=None, source=_null, **kw): ############################################################################# def generate(env,**kw): """ Generate the `msginit` tool """ + import sys + import os import SCons.Util + import SCons.Tool from SCons.Tool.GettextCommon import _detect_msginit + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + + if sys.platform == 'win32': + msginit = SCons.Tool.find_program_path(env, 'msginit', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if msginit: + msginit_bin_dir = os.path.dirname(msginit) + env.AppendENVPath('PATH', msginit_bin_dir) + else: + SCons.Warnings.Warning('msginit tool requested, but binary not found in ENV PATH') + try: env['MSGINIT'] = _detect_msginit(env) except: diff --git a/src/engine/SCons/Tool/msginit.xml b/src/engine/SCons/Tool/msginit.xml index 3a2a969..d09dde1 100644 --- a/src/engine/SCons/Tool/msginit.xml +++ b/src/engine/SCons/Tool/msginit.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/msgmerge.py b/src/engine/SCons/Tool/msgmerge.py index aef1f5f..4254fa6 100644 --- a/src/engine/SCons/Tool/msgmerge.py +++ b/src/engine/SCons/Tool/msgmerge.py @@ -3,7 +3,7 @@ Tool specific initialization for `msgmerge` tool. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Tool specific initialization for `msgmerge` tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msgmerge.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msgmerge.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" ############################################################################# def _update_or_init_po_files(target, source, env): @@ -68,8 +68,21 @@ def _POUpdateBuilderWrapper(env, target=None, source=_null, **kw): ############################################################################# def generate(env,**kw): - """ Generate the `xgettext` tool """ + """ Generate the `msgmerge` tool """ + import sys + import os + import SCons.Tool from SCons.Tool.GettextCommon import _detect_msgmerge + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + + if sys.platform == 'win32': + msgmerge = SCons.Tool.find_program_path(env, 'msgmerge', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if msgmerge: + msgmerge_bin_dir = os.path.dirname(msgmerge) + env.AppendENVPath('PATH', msgmerge_bin_dir) + else: + SCons.Warnings.Warning('msgmerge tool requested, but binary not found in ENV PATH') try: env['MSGMERGE'] = _detect_msgmerge(env) except: diff --git a/src/engine/SCons/Tool/msgmerge.xml b/src/engine/SCons/Tool/msgmerge.xml index 65d19e1..2944679 100644 --- a/src/engine/SCons/Tool/msgmerge.xml +++ b/src/engine/SCons/Tool/msgmerge.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mslib.py b/src/engine/SCons/Tool/mslib.py index 3d79649..cecdbdc 100644 --- a/src/engine/SCons/Tool/mslib.py +++ b/src/engine/SCons/Tool/mslib.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,9 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mslib.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mslib.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" + +import os import SCons.Defaults import SCons.Tool @@ -54,8 +56,15 @@ def generate(env): env['LIBPREFIX'] = '' env['LIBSUFFIX'] = '.lib' + # Issue #3350 + # Change tempfile argument joining character from a space to a newline + # mslink will fail if any single line is too long, but is fine with many lines + # in a tempfile + env['TEMPFILEARGJOIN'] = os.linesep + + def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mslib.xml b/src/engine/SCons/Tool/mslib.xml index 6ee2f22..a9b7cef 100644 --- a/src/engine/SCons/Tool/mslib.xml +++ b/src/engine/SCons/Tool/mslib.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index 1b16b63..9fbce4b 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,8 +32,9 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/mslink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mslink.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" +import os import os.path import SCons.Action @@ -107,7 +108,7 @@ def _dllEmitter(target, source, env, paramtp): raise SCons.Errors.UserError('A shared library should have exactly one target with the suffix: %s' % env.subst('$%sSUFFIX' % paramtp)) insert_def = env.subst("$WINDOWS_INSERT_DEF") - if not insert_def in ['', '0', 0] and \ + if insert_def not in ['', '0', 0] and \ not env.FindIxes(source, "WINDOWSDEFPREFIX", "WINDOWSDEFSUFFIX"): # append a def file to the list of sources @@ -158,7 +159,7 @@ def windowsLibEmitter(target, source, env): def ldmodEmitter(target, source, env): """Emitter for loadable modules. - + Loadable modules are identical to shared libraries on Windows, but building them is subject to different parameters (LDMODULE*). """ @@ -219,7 +220,7 @@ def embedManifestDllCheck(target, source, env): if env.get('WINDOWS_EMBED_MANIFEST', 0): manifestSrc = target[0].get_abspath() + '.manifest' if os.path.exists(manifestSrc): - ret = (embedManifestDllAction) ([target[0]],None,env) + ret = (embedManifestDllAction) ([target[0]],None,env) if ret: raise SCons.Errors.UserError("Unable to embed manifest into %s" % (target[0])) return ret @@ -327,8 +328,14 @@ def generate(env): env['LDMODULEEMITTER'] = [ldmodEmitter] env['LDMODULECOM'] = compositeLdmodAction + # Issue #3350 + # Change tempfile argument joining character from a space to a newline + # mslink will fail if any single line is too long, but is fine with many lines + # in a tempfile + env['TEMPFILEARGJOIN'] = os.linesep + def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mslink.xml b/src/engine/SCons/Tool/mslink.xml index 24b79c7..692c1da 100644 --- a/src/engine/SCons/Tool/mslink.xml +++ b/src/engine/SCons/Tool/mslink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mssdk.py b/src/engine/SCons/Tool/mssdk.py index dd9de93..7a38c6a 100644 --- a/src/engine/SCons/Tool/mssdk.py +++ b/src/engine/SCons/Tool/mssdk.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mssdk.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mssdk.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" """engine.SCons.Tool.mssdk diff --git a/src/engine/SCons/Tool/mssdk.xml b/src/engine/SCons/Tool/mssdk.xml index 0ae3553..b84597e 100644 --- a/src/engine/SCons/Tool/mssdk.xml +++ b/src/engine/SCons/Tool/mssdk.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index 2fe16c3..052a0b0 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,9 +31,10 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/msvc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msvc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path +import os import re import sys @@ -112,7 +113,7 @@ def object_emitter(target, source, env, parent_emitter): # # See issue #2505 for a discussion of what to do if it turns # out this assumption causes trouble in the wild: - # http://scons.tigris.org/issues/show_bug.cgi?id=2505 + # https://github.com/SCons/scons/issues/2505 if 'PCH' in env: pch = env['PCH'] if str(target[0]) != SCons.Util.splitext(str(pch))[0] + '.obj': @@ -161,7 +162,7 @@ def msvc_batch_key(action, env, target, source): # Note we need to do the env.subst so $MSVC_BATCH can be a reference to # another construction variable, which is why we test for False and 0 # as strings. - if not 'MSVC_BATCH' in env or env.subst('$MSVC_BATCH') in ('0', 'False', '', None): + if 'MSVC_BATCH' not in env or env.subst('$MSVC_BATCH') in ('0', 'False', '', None): # We're not using batching; return no key. return None t = target[0] @@ -187,7 +188,7 @@ def msvc_output_flag(target, source, env, for_signature): # len(source)==1 as batch mode can compile only one file # (and it also fixed problem with compiling only one changed file # with batch mode enabled) - if not 'MSVC_BATCH' in env or env.subst('$MSVC_BATCH') in ('0', 'False', '', None): + if 'MSVC_BATCH' not in env or env.subst('$MSVC_BATCH') in ('0', 'False', '', None): return '/Fo$TARGET' else: # The Visual C/C++ compiler requires a \ at the end of the /Fo @@ -195,7 +196,10 @@ def msvc_output_flag(target, source, env, for_signature): # that the test(s) for this can be run on non-Windows systems # without having a hard-coded backslash mess up command-line # argument parsing. - return '/Fo${TARGET.dir}' + os.sep + # Adding double os.sep's as if the TARGET.dir has a space or otherwise + # needs to be quoted they are needed per MSVC's odd behavior + # See: https://github.com/SCons/scons/issues/3106 + return '/Fo${TARGET.dir}' + os.sep*2 CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR", batch_key=msvc_batch_key, @@ -259,7 +263,7 @@ def generate(env): env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1 env['RC'] = 'rc' - env['RCFLAGS'] = SCons.Util.CLVar('') + env['RCFLAGS'] = SCons.Util.CLVar('/nologo') env['RCSUFFIXES']=['.rc','.rc2'] env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES' env['BUILDERS']['RES'] = res_builder @@ -268,6 +272,10 @@ def generate(env): env['SHOBJPREFIX'] = '$OBJPREFIX' env['SHOBJSUFFIX'] = '$OBJSUFFIX' + # MSVC probably wont support unistd.h so default + # without it for lex generation + env["LEXUNISTD"] = SCons.Util.CLVar("--nounistd") + # Set-up ms tools paths msvc_setup_env_once(env) @@ -276,6 +284,12 @@ def generate(env): msvc_set_PCHPDBFLAGS(env) + # Issue #3350 + # Change tempfile argument joining character from a space to a newline + # mslink will fail if any single line is too long, but is fine with many lines + # in a tempfile + env['TEMPFILEARGJOIN'] = os.linesep + env['PCHCOM'] = '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS' env['BUILDERS']['PCH'] = pch_builder @@ -286,7 +300,7 @@ def generate(env): env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root() def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index edc6936..b8b4f6d 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -305,7 +305,8 @@ containing the command-line options for specifying directories to be searched by the resource compiler. The value of &cv-RCINCFLAGS; is created -by appending &cv-RCINCPREFIX; and &cv-RCINCSUFFIX; +by respectively prepending and appending +&cv-RCINCPREFIX; and &cv-RCINCSUFFIX; to the beginning and end of each directory in &cv-CPPPATH;. </para> @@ -317,7 +318,7 @@ of each directory in &cv-CPPPATH;. <para> The prefix (flag) used to specify an include directory on the resource compiler command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the &cv-CPPPATH; construction variable when the &cv-RCINCFLAGS; variable is expanded. </para> @@ -352,6 +353,8 @@ constructor; setting it later has no effect. <para> Valid values for Windows are +<literal>14.2</literal>, +<literal>14.1</literal>, <literal>14.0</literal>, <literal>14.0Exp</literal>, <literal>12.0</literal>, @@ -424,18 +427,24 @@ This variable must be passed as an argument to the Environment() constructor; setting it later has no effect. This is currently only used on Windows, but in the future it will be used on other OSes as well. +If this is set and MSVC_VERSION is not set, this will search for +all installed MSVC's that support the TARGET_ARCH, selecting the +latest version for use. </para> <para> Valid values for Windows are <literal>x86</literal>, +<literal>arm</literal>, <literal>i386</literal> (for 32 bits); <literal>amd64</literal>, +<literal>arm64</literal>, <literal>emt64</literal>, <literal>x86_64</literal> (for 64 bits); and <literal>ia64</literal> (Itanium). + For example, if you want to compile 64-bit binaries, you would set <literal>TARGET_ARCH='x86_64'</literal> in your SCons environment. </para> diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 05531c6..38965e3 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/msvs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msvs.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.compat @@ -70,10 +70,14 @@ def xmlify(s): s = s.replace('\n', '
') return s -# Process a CPPPATH list in includes, given the env, target and source. -# Returns a tuple of nodes. def processIncludes(includes, env, target, source): - return SCons.PathList.PathList(includes).subst_path(env, target, source) + """ + Process a CPPPATH list in includes, given the env, target and source. + Returns a list of directory paths. These paths are absolute so we avoid + putting pound-prefixed paths in a Visual Studio project file. + """ + return [env.Dir(i).abspath for i in + SCons.PathList.PathList(includes).subst_path(env, target, source)] external_makefile_guid = '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}' @@ -149,9 +153,9 @@ def splitFully(path): return [base] def makeHierarchy(sources): - '''Break a list of files into a hierarchy; for each value, if it is a string, + """Break a list of files into a hierarchy; for each value, if it is a string, then it is a file. If it is a dictionary, it is a folder. The string is - the original path of the file.''' + the original path of the file.""" hierarchy = {} for file in sources: @@ -189,7 +193,7 @@ class _UserGenerator(object): elif SCons.Util.is_List(env['variant']): variants = env['variant'] - if 'DebugSettings' not in env or env['DebugSettings'] == None: + if 'DebugSettings' not in env or env['DebugSettings'] is None: dbg_settings = [] elif SCons.Util.is_Dict(env['DebugSettings']): dbg_settings = [env['DebugSettings']] @@ -348,10 +352,20 @@ V10DebugSettings = { } class _GenerateV10User(_UserGenerator): - """Generates a Project'user file for MSVS 2010""" + """Generates a Project'user file for MSVS 2010 or later""" def __init__(self, dspfile, source, env): - self.versionstr = '4.0' + version_num, suite = msvs_parse_version(env['MSVS_VERSION']) + if version_num >= 14.2: + # Visual Studio 2019 is considered to be version 16. + self.versionstr = '16.0' + elif version_num >= 14.1: + # Visual Studio 2017 is considered to be version 15. + self.versionstr = '15.0' + elif version_num == 14.0: + self.versionstr = '14.0' + else: + self.versionstr = '4.0' self.usrhead = V10UserHeader self.usrconf = V10UserConfiguration self.usrdebg = V10DebugSettings @@ -397,7 +411,7 @@ class _DSPGenerator(object): elif SCons.Util.is_List(env['variant']): variants = env['variant'] - if 'buildtarget' not in env or env['buildtarget'] == None: + if 'buildtarget' not in env or env['buildtarget'] is None: buildtarget = [''] elif SCons.Util.is_String(env['buildtarget']): buildtarget = [env['buildtarget']] @@ -418,7 +432,7 @@ class _DSPGenerator(object): for _ in variants: buildtarget.append(bt) - if 'outdir' not in env or env['outdir'] == None: + if 'outdir' not in env or env['outdir'] is None: outdir = [''] elif SCons.Util.is_String(env['outdir']): outdir = [env['outdir']] @@ -439,7 +453,7 @@ class _DSPGenerator(object): for v in variants: outdir.append(s) - if 'runfile' not in env or env['runfile'] == None: + if 'runfile' not in env or env['runfile'] is None: runfile = buildtarget[-1:] elif SCons.Util.is_String(env['runfile']): runfile = [env['runfile']] @@ -462,15 +476,41 @@ class _DSPGenerator(object): self.sconscript = env['MSVSSCONSCRIPT'] - if 'cmdargs' not in env or env['cmdargs'] == None: - cmdargs = [''] * len(variants) - elif SCons.Util.is_String(env['cmdargs']): - cmdargs = [env['cmdargs']] * len(variants) - elif SCons.Util.is_List(env['cmdargs']): - if len(env['cmdargs']) != len(variants): - raise SCons.Errors.InternalError("Sizes of 'cmdargs' and 'variant' lists must be the same.") + def GetKeyFromEnv(env, key, variants): + """ + Retrieves a specific key from the environment. If the key is + present, it is expected to either be a string or a list with length + equal to the number of variants. The function returns a list of + the desired value (e.g. cpp include paths) guaranteed to be of + length equal to the length of the variants list. + """ + if key not in env or env[key] is None: + return [''] * len(variants) + elif SCons.Util.is_String(env[key]): + return [env[key]] * len(variants) + elif SCons.Util.is_List(env[key]): + if len(env[key]) != len(variants): + raise SCons.Errors.InternalError("Sizes of '%s' and 'variant' lists must be the same." % key) + else: + return env[key] else: - cmdargs = env['cmdargs'] + raise SCons.Errors.InternalError("Unsupported type for key '%s' in environment: %s" % + (key, type(env[key]))) + + cmdargs = GetKeyFromEnv(env, 'cmdargs', variants) + + # The caller is allowed to put 'cppdefines' and/or 'cpppaths' in the + # environment, which is useful if they want to provide per-variant + # values for these. Otherwise, we fall back to using the global + # 'CPPDEFINES' and 'CPPPATH' functions. + if 'cppdefines' in env: + cppdefines = GetKeyFromEnv(env, 'cppdefines', variants) + else: + cppdefines = [env.get('CPPDEFINES', [])] * len(variants) + if 'cpppaths' in env: + cpppaths = GetKeyFromEnv(env, 'cpppaths', variants) + else: + cpppaths = [env.get('CPPPATH', [])] * len(variants) self.env = env @@ -513,14 +553,18 @@ class _DSPGenerator(object): for n in sourcenames: self.sources[n].sort(key=lambda a: a.lower()) - def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, dspfile=dspfile): + def AddConfig(self, variant, buildtarget, outdir, runfile, cmdargs, cppdefines, cpppaths, dspfile=dspfile, env=env): config = Config() config.buildtarget = buildtarget config.outdir = outdir config.cmdargs = cmdargs + config.cppdefines = cppdefines config.runfile = runfile - match = re.match('(.*)\|(.*)', variant) + # Dir objects can't be pickled, so we need an absolute path here. + config.cpppaths = processIncludes(cpppaths, env, None, None) + + match = re.match(r'(.*)\|(.*)', variant) if match: config.variant = match.group(1) config.platform = match.group(2) @@ -532,12 +576,12 @@ class _DSPGenerator(object): print("Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dspfile) + "'") for i in range(len(variants)): - AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i]) + AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i], cppdefines[i], cpppaths[i]) self.platforms = [] for key in list(self.configs.keys()): platform = self.configs[key].platform - if not platform in self.platforms: + if platform not in self.platforms: self.platforms.append(platform) def Build(self): @@ -553,16 +597,16 @@ V6DSPHeader = """\ CFG=%(name)s - Win32 %(confkey)s !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "%(name)s.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "%(name)s.mak" CFG="%(name)s - Win32 %(confkey)s" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE """ class _GenerateV6DSP(_DSPGenerator): @@ -580,7 +624,7 @@ class _GenerateV6DSP(_DSPGenerator): for kind in confkeys: self.file.write('!MESSAGE "%s - Win32 %s" (based on "Win32 (x86) External Target")\n' % (name, kind)) - self.file.write('!MESSAGE \n\n') + self.file.write('!MESSAGE\n\n') def PrintProject(self): name = self.name @@ -637,7 +681,7 @@ class _GenerateV6DSP(_DSPGenerator): first = 1 else: self.file.write('!ELSEIF "$(CFG)" == "%s - Win32 %s"\n\n' % (name,kind)) - self.file.write('!ENDIF \n\n') + self.file.write('!ENDIF\n\n') self.PrintSourceFiles() self.file.write('# End Target\n' '# End Project\n') @@ -645,10 +689,10 @@ class _GenerateV6DSP(_DSPGenerator): if self.nokeep == 0: # now we pickle some data and add it to the file -- MSDEV will ignore it. pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) - pdata = base64.encodestring(pdata).decode() + pdata = base64.b64encode(pdata).decode() self.file.write(pdata + '\n') pdata = pickle.dumps(self.sources,PICKLE_PROTOCOL) - pdata = base64.encodestring(pdata).decode() + pdata = base64.b64encode(pdata).decode() self.file.write(pdata + '\n') def PrintSourceFiles(self): @@ -685,11 +729,13 @@ class _GenerateV6DSP(_DSPGenerator): return # doesn't exist yet, so can't add anything to configs. line = dspfile.readline() + # skip until marker while line: if line.find("# End Project") > -1: break line = dspfile.readline() + # read to get configs line = dspfile.readline() datas = line while line and line != '\n': @@ -707,12 +753,14 @@ class _GenerateV6DSP(_DSPGenerator): self.configs.update(data) + # keep reading to get sources data = None line = dspfile.readline() datas = line while line and line != '\n': line = dspfile.readline() datas = datas + line + dspfile.close() # OK, we've found our little pickled cache of data. # it has a "# " in front of it, so we strip that. @@ -878,6 +926,8 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): buildtarget = self.configs[kind].buildtarget runfile = self.configs[kind].runfile cmdargs = self.configs[kind].cmdargs + cpppaths = self.configs[kind].cpppaths + cppdefines = self.configs[kind].cppdefines env_has_buildtarget = 'MSVSBUILDTARGET' in self.env if not env_has_buildtarget: @@ -895,9 +945,8 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): # This isn't perfect; CPPDEFINES and CPPPATH can contain $TARGET and $SOURCE, # so they could vary depending on the command being generated. This code # assumes they don't. - preprocdefs = xmlify(';'.join(processDefines(self.env.get('CPPDEFINES', [])))) - includepath_Dirs = processIncludes(self.env.get('CPPPATH', []), self.env, None, None) - includepath = xmlify(';'.join([str(x) for x in includepath_Dirs])) + preprocdefs = xmlify(';'.join(processDefines(cppdefines))) + includepath = xmlify(';'.join(processIncludes(cpppaths, self.env, None, None))) if not env_has_buildtarget: del self.env['MSVSBUILDTARGET'] @@ -917,10 +966,10 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): if self.nokeep == 0: # now we pickle some data and add it to the file -- MSDEV will ignore it. pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) - pdata = base64.encodestring(pdata).decode() + pdata = base64.b64encode(pdata).decode() self.file.write('<!-- SCons Data:\n' + pdata + '\n') pdata = pickle.dumps(self.sources,PICKLE_PROTOCOL) - pdata = base64.encodestring(pdata).decode() + pdata = base64.b64encode(pdata).decode() self.file.write(pdata + '-->\n') def printSources(self, hierarchy, commonprefix): @@ -998,11 +1047,13 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): return # doesn't exist yet, so can't add anything to configs. line = dspfile.readline() + # skip until marker while line: if line.find('<!-- SCons Data:') > -1: break line = dspfile.readline() + # read to get configs line = dspfile.readline() datas = line while line and line != '\n': @@ -1020,12 +1071,14 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): self.configs.update(data) + # keep reading to get sources data = None line = dspfile.readline() datas = line while line and line != '\n': line = dspfile.readline() datas = datas + line + dspfile.close() # OK, we've found our little pickled cache of data. try: @@ -1052,7 +1105,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): V10DSPHeader = """\ <?xml version="1.0" encoding="%(encoding)s"?> -<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +<Project DefaultTargets="Build" ToolsVersion="%(versionstr)s" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> """ V10DSPProjectConfiguration = """\ @@ -1067,6 +1120,7 @@ V10DSPGlobals = """\ \t\t<ProjectGuid>%(project_guid)s</ProjectGuid> %(scc_attrs)s\t\t<RootNamespace>%(name)s</RootNamespace> \t\t<Keyword>MakeFileProj</Keyword> +\t\t<VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName> \t</PropertyGroup> """ @@ -1080,7 +1134,7 @@ V10DSPPropertyGroupCondition = """\ V10DSPImportGroupCondition = """\ \t<ImportGroup Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'" Label="PropertySheets"> -\t\t<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +\t\t<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> \t</ImportGroup> """ @@ -1096,6 +1150,11 @@ V10DSPCommandLine = """\ \t\t<NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies> """ +V15DSPHeader = """\ +<?xml version="1.0" encoding="%(encoding)s"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +""" + class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): """Generates a Project file for MSVS 2010""" @@ -1110,6 +1169,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): def PrintHeader(self): env = self.env name = self.name + versionstr = self.versionstr encoding = env.subst('$MSVSENCODING') project_guid = env.get('MSVS_PROJECT_GUID', '') scc_provider = env.get('MSVS_SCC_PROVIDER', '') @@ -1154,7 +1214,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): name = self.name confkeys = sorted(self.configs.keys()) - self.file.write('\t<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />\n') + self.file.write('\t<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" />\n') toolset = '' if 'MSVC_VERSION' in self.env: @@ -1165,7 +1225,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): platform = self.configs[kind].platform self.file.write(V10DSPPropertyGroupCondition % locals()) - self.file.write('\t<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />\n') + self.file.write('\t<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" />\n') self.file.write('\t<ImportGroup Label="ExtensionSettings">\n') self.file.write('\t</ImportGroup>\n') @@ -1185,6 +1245,8 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): buildtarget = self.configs[kind].buildtarget runfile = self.configs[kind].runfile cmdargs = self.configs[kind].cmdargs + cpppaths = self.configs[kind].cpppaths + cppdefines = self.configs[kind].cppdefines env_has_buildtarget = 'MSVSBUILDTARGET' in self.env if not env_has_buildtarget: @@ -1202,9 +1264,8 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): # This isn't perfect; CPPDEFINES and CPPPATH can contain $TARGET and $SOURCE, # so they could vary depending on the command being generated. This code # assumes they don't. - preprocdefs = xmlify(';'.join(processDefines(self.env.get('CPPDEFINES', [])))) - includepath_Dirs = processIncludes(self.env.get('CPPPATH', []), self.env, None, None) - includepath = xmlify(';'.join([str(x) for x in includepath_Dirs])) + preprocdefs = xmlify(';'.join(processDefines(cppdefines))) + includepath = xmlify(';'.join(processIncludes(cpppaths, self.env, None, None))) if not env_has_buildtarget: del self.env['MSVSBUILDTARGET'] @@ -1221,14 +1282,15 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): raise SCons.Errors.InternalError('Unable to open "' + self.filtersabs + '" for writing:' + str(detail)) self.filters_file.write('<?xml version="1.0" encoding="utf-8"?>\n' - '<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n') + '<Project ToolsVersion="%s" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">\n' % + self.versionstr) self.PrintSourceFiles() self.filters_file.write('</Project>') self.filters_file.close() - self.file.write('\t<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\n' + self.file.write('\t<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" />\n' '\t<ImportGroup Label="ExtensionTargets">\n' '\t</ImportGroup>\n' '</Project>\n') @@ -1236,10 +1298,10 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): if self.nokeep == 0: # now we pickle some data and add it to the file -- MSDEV will ignore it. pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) - pdata = base64.encodestring(pdata).decode() + pdata = base64.b64encode(pdata).decode() self.file.write('<!-- SCons Data:\n' + pdata + '\n') pdata = pickle.dumps(self.sources,PICKLE_PROTOCOL) - pdata = base64.encodestring(pdata).decode() + pdata = base64.b64encode(pdata).decode() self.file.write(pdata + '-->\n') def printFilters(self, hierarchy, name): @@ -1287,7 +1349,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): 'Other Files': ''} cats = sorted([k for k in list(categories.keys()) if self.sources[k]], - key = lambda a: a.lower()) + key = lambda a: a.lower()) # print vcxproj.filters file first self.filters_file.write('\t<ItemGroup>\n') @@ -1423,7 +1485,7 @@ class _GenerateV7DSW(_DSWGenerator): def AddConfig(self, variant, dswfile=dswfile): config = Config() - match = re.match('(.*)\|(.*)', variant) + match = re.match(r'(.*)\|(.*)', variant) if match: config.variant = match.group(1) config.platform = match.group(2) @@ -1446,13 +1508,16 @@ class _GenerateV7DSW(_DSWGenerator): self.platforms = [] for key in list(self.configs.keys()): platform = self.configs[key].platform - if not platform in self.platforms: + if platform not in self.platforms: self.platforms.append(platform) def GenerateProjectFilesInfo(self): for dspfile in self.dspfiles: dsp_folder_path, name = os.path.split(dspfile) dsp_folder_path = os.path.abspath(dsp_folder_path) + if SCons.Util.splitext(name)[1] == '.filters': + # Ignore .filters project files + continue dsp_relative_folder_path = os.path.relpath(dsp_folder_path, self.dsw_folder_path) if dsp_relative_folder_path == os.curdir: dsp_relative_file_path = name @@ -1486,6 +1551,7 @@ class _GenerateV7DSW(_DSWGenerator): while line: line = dswfile.readline() datas = datas + line + dswfile.close() # OK, we've found our little pickled cache of data. try: @@ -1501,7 +1567,13 @@ class _GenerateV7DSW(_DSWGenerator): def PrintSolution(self): """Writes a solution file""" self.file.write('Microsoft Visual Studio Solution File, Format Version %s\n' % self.versionstr) - if self.version_num >= 12.0: + if self.version_num >= 14.2: + # Visual Studio 2019 is considered to be version 16. + self.file.write('# Visual Studio 16\n') + elif self.version_num > 14.0: + # Visual Studio 2015 and 2017 are both considered to be version 15. + self.file.write('# Visual Studio 15\n') + elif self.version_num >= 12.0: self.file.write('# Visual Studio 14\n') elif self.version_num >= 11.0: self.file.write('# Visual Studio 11\n') @@ -1519,7 +1591,7 @@ class _GenerateV7DSW(_DSWGenerator): name = base self.file.write('Project("%s") = "%s", "%s", "%s"\n' % (external_makefile_guid, name, dspinfo['SLN_RELATIVE_FILE_PATH'], dspinfo['GUID'])) - if self.version_num >= 7.1 and self.version_num < 8.0: + if 7.1 <= self.version_num < 8.0: self.file.write('\tProjectSection(ProjectDependencies) = postProject\n' '\tEndProjectSection\n') self.file.write('EndProject\n') @@ -1610,7 +1682,7 @@ class _GenerateV7DSW(_DSWGenerator): self.file.write('EndGlobal\n') if self.nokeep == 0: pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) - pdata = base64.encodestring(pdata).decode() + pdata = base64.b64encode(pdata).decode() self.file.write(pdata) self.file.write('\n') @@ -1720,7 +1792,7 @@ def GenerateProject(target, source, env): dspfile = builddspfile.srcnode() # this detects whether or not we're using a VariantDir - if not dspfile is builddspfile: + if dspfile is not builddspfile: try: bdsp = open(str(builddspfile), "w+") except IOError as detail: @@ -1728,6 +1800,7 @@ def GenerateProject(target, source, env): raise bdsp.write("This is just a placeholder file.\nThe real project file is here:\n%s\n" % dspfile.get_abspath()) + bdsp.close() GenerateDSP(dspfile, source, env) @@ -1735,7 +1808,7 @@ def GenerateProject(target, source, env): builddswfile = target[1] dswfile = builddswfile.srcnode() - if not dswfile is builddswfile: + if dswfile is not builddswfile: try: bdsw = open(str(builddswfile), "w+") @@ -1744,6 +1817,7 @@ def GenerateProject(target, source, env): raise bdsw.write("This is just a placeholder file.\nThe real workspace file is here:\n%s\n" % dswfile.get_abspath()) + bdsw.close() GenerateDSW(dswfile, source, env) @@ -1771,11 +1845,10 @@ def projectEmitter(target, source, env): # Project file depends on CPPDEFINES and CPPPATH preprocdefs = xmlify(';'.join(processDefines(env.get('CPPDEFINES', [])))) - includepath_Dirs = processIncludes(env.get('CPPPATH', []), env, None, None) - includepath = xmlify(';'.join([str(x) for x in includepath_Dirs])) + includepath = xmlify(';'.join(processIncludes(env.get('CPPPATH', []), env, None, None))) source = source + "; ppdefs:%s incpath:%s"%(preprocdefs, includepath) - if 'buildtarget' in env and env['buildtarget'] != None: + if 'buildtarget' in env and env['buildtarget'] is not None: if SCons.Util.is_String(env['buildtarget']): source = source + ' "%s"' % env['buildtarget'] elif SCons.Util.is_List(env['buildtarget']): @@ -1789,7 +1862,7 @@ def projectEmitter(target, source, env): try: source = source + ' "%s"' % env['buildtarget'].get_abspath() except AttributeError: raise SCons.Errors.InternalError("buildtarget can be a string, a node, a list of strings or nodes, or None") - if 'outdir' in env and env['outdir'] != None: + if 'outdir' in env and env['outdir'] is not None: if SCons.Util.is_String(env['outdir']): source = source + ' "%s"' % env['outdir'] elif SCons.Util.is_List(env['outdir']): @@ -1952,8 +2025,14 @@ def generate(env): default_MSVS_SConscript = env.File('SConstruct') env['MSVSSCONSCRIPT'] = default_MSVS_SConscript - env['MSVSSCONS'] = '"%s" -c "%s"' % (python_executable, getExecScriptMain(env)) - env['MSVSSCONSFLAGS'] = '-C "${MSVSSCONSCRIPT.dir.get_abspath()}" -f ${MSVSSCONSCRIPT.name}' + # Allow consumers to provide their own versions of MSVSSCONS and + # MSVSSCONSFLAGS. This helps support consumers who use wrapper scripts to + # invoke scons. + if 'MSVSSCONS' not in env: + env['MSVSSCONS'] = '"%s" -c "%s"' % (python_executable, getExecScriptMain(env)) + if 'MSVSSCONSFLAGS' not in env: + env['MSVSSCONSFLAGS'] = '-C "${MSVSSCONSCRIPT.dir.get_abspath()}" -f ${MSVSSCONSCRIPT.name}' + env['MSVSSCONSCOM'] = '$MSVSSCONS $MSVSSCONSFLAGS' env['MSVSBUILDCOM'] = '$MSVSSCONSCOM "$MSVSBUILDTARGET"' env['MSVSREBUILDCOM'] = '$MSVSSCONSCOM "$MSVSBUILDTARGET"' @@ -1990,7 +2069,7 @@ def generate(env): env['SCONS_HOME'] = os.environ.get('SCONS_HOME') def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/msvs.xml b/src/engine/SCons/Tool/msvs.xml index 0408509..9f2353a 100644 --- a/src/engine/SCons/Tool/msvs.xml +++ b/src/engine/SCons/Tool/msvs.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -17,160 +17,244 @@ See its __doc__ string for a discussion of the format. <!ENTITY % variables-mod SYSTEM "../../../../doc/generated/variables.mod"> %variables-mod; ]> -<sconsdoc -xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd" -xmlns="http://www.scons.org/dbxsd/v1.0" -xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -xmlns:xs="http://www.w3.org/2001/XMLSchema" -xmlns:ns="http://www.scons.org/dbxsd/v1.0"><tool name="msvs"> <summary> <para> -Sets construction variables for Microsoft Visual Studio. </para> </summary> -<sets> <item>MSVSPROJECTCOM</item> <item>MSVSSOLUTIONCOM</item> -<item>MSVSSCONSCRIPT</item> <item>MSVSSCONS</item> <item>MSVSSCONSFLAGS</item> -<item>MSVSSCONSCOM</item> <item>MSVSBUILDCOM</item> -<item>MSVSREBUILDCOM</item> <item>MSVSCLEANCOM</item> -<item>MSVSENCODING</item> </sets> <uses> </uses> </tool> <builder -name="MSVSProject"> <summary> <para> Builds a Microsoft Visual Studio project -file, and by default builds a solution file as well. </para> <para> This -builds a Visual Studio project file, based on the version of Visual Studio -that is configured (either the latest installed version, or the version -specified by &cv-link-MSVS_VERSION; in the Environment constructor). For -Visual Studio 6, it will generate a <filename>.dsp</filename> file. For Visual -Studio 7 (.NET) and later versions, it will generate a -<filename>.vcproj</filename> file. </para> <para> By default, this also -generates a solution file for the specified project, a -<filename>.dsw</filename> file for Visual Studio 6 or a -<filename>.sln</filename> file for Visual Studio 7 (.NET). This behavior may -be disabled by specifying <literal>auto_build_solution=0</literal> when you -call &b-MSVSProject;, in which case you presumably want to build the solution -file(s) by calling the &b-MSVSSolution; Builder (see below). </para> <para> -The &b-MSVSProject; builder takes several lists of filenames to be placed into -the project file. These are currently limited to <literal>srcs</literal>, -<literal>incs</literal>, <literal>localincs</literal>, -<literal>resources</literal>, and <literal>misc</literal>. These are pretty -self-explanatory, but it should be noted that these lists are added to the -&cv-link-SOURCES; construction variable as strings, NOT as SCons File Nodes. -This is because they represent file names to be added to the project file, not -the source files used to build the project file. </para> <para> The above -filename lists are all optional, although at least one must be specified for -the resulting project file to be non-empty. </para> <para> In addition to the -above lists of values, the following values may be specified: -</para><variablelist> - <varlistentry> - <term>target</term> - - <listitem> - <para>The name of the target <filename>.dsp</filename> or - <filename>.vcproj</filename> file. The correct suffix for the version - of Visual Studio must be used, but the &cv-link-MSVSPROJECTSUFFIX; - construction variable will be defined to the correct value (see - example below).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>variant</term> - - <listitem> - <para>The name of this particular variant. For Visual Studio 7 - projects, this can also be a list of variant names. These are - typically things like "Debug" or "Release", but really can be anything - you want. For Visual Studio 7 projects, they may also specify a target - platform separated from the variant name by a <literal>|</literal> - (vertical pipe) character: <literal>Debug|Xbox</literal>. The default - target platform is Win32. Multiple calls to &b-MSVSProject; with - different variants are allowed; all variants will be added to the - project file with their appropriate build targets and - sources.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>cmdargs</term> - - <listitem> - <para>Additional command line arguments for the different - variants. The number of <literal>cmdargs</literal> entries must match - the number of <literal>variant</literal> entries, or be empty (not - specified). If you give only one, it will automatically be propagated - to all variants.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>buildtarget</term> - - <listitem> - <para>An optional string, node, or list of strings or nodes (one - per build variant), to tell the Visual Studio debugger what output - target to use in what build variant. The number of - <literal>buildtarget</literal> entries must match the number of - <literal>variant</literal> entries.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>runfile</term> - - <listitem> - <para>The name of the file that Visual Studio 7 and later will - run and debug. This appears as the value of the - <literal>Output</literal> field in the resulting Visual Studio project - file. If this is not specified, the default is the same as the - specified <literal>buildtarget</literal> value.</para> - </listitem> - </varlistentry> - </variablelist><para> Note that because &SCons; always executes its build -commands from the directory in which the &SConstruct; file is located, if you -generate a project file in a different directory than the &SConstruct; -directory, users will not be able to double-click on the file name in -compilation error messages displayed in the Visual Studio console output -window. This can be remedied by adding the Visual C/C++ <literal>/FC</literal> -compiler option to the &cv-link-CCFLAGS; variable so that the compiler will -print the full path name of any files that cause compilation errors. </para> -<para> Example usage: </para> - <example_commands> +<sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:ns="http://www.scons.org/dbxsd/v1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd"> + <tool name="msvs"> + <summary> + <para>Sets construction variables for Microsoft Visual Studio.</para> + </summary> + <sets> + <item>MSVSPROJECTCOM</item> + <item>MSVSSOLUTIONCOM</item> + <item>MSVSSCONSCRIPT</item> + <item>MSVSSCONS</item> + <item>MSVSSCONSFLAGS</item> + <item>MSVSSCONSCOM</item> + <item>MSVSBUILDCOM</item> + <item>MSVSREBUILDCOM</item> + <item>MSVSCLEANCOM</item> + <item>MSVSENCODING</item> + </sets> + <uses /> + </tool> + <builder name="MSVSProject"> + <summary> + <para> + Builds a Microsoft Visual Studio project file, and by default + builds a solution file as well. + </para> + <para> + This builds a Visual Studio project file, based on the + version of Visual Studio that is configured (either the + latest installed version, or the version specified by + &cv-link-MSVS_VERSION; in the Environment constructor). For + Visual Studio 6, it will generate a <filename>.dsp</filename> + file. For Visual Studio 7, 8, and 9, it will + generate a <filename>.vcproj</filename> file. For Visual + Studio 10 and later, it will generate a + <filename>.vcxproj</filename> file. + </para> + <para> + By default, this also generates a solution file for the + specified project, a <filename>.dsw</filename> file for + Visual Studio 6 or a <filename>.sln</filename> file for + Visual Studio 7 and later. This behavior may be disabled by + specifying <literal>auto_build_solution=0</literal> when you + call &b-MSVSProject;, in which case you presumably want to + build the solution file(s) by calling the &b-MSVSSolution; + Builder (see below). + </para> + <para> + The &b-MSVSProject; builder takes several lists of filenames + to be placed into the project file. These are currently + limited to <literal>srcs</literal>, <literal>incs</literal>, + <literal>localincs</literal>, <literal>resources</literal>, and + <literal>misc</literal>. These are pretty self-explanatory, + but it should be noted that these lists are added to the + &cv-link-SOURCES; construction variable as strings, NOT as + SCons File Nodes. This is because they represent file names + to be added to the project file, not the source files used + to build the project file. + </para> + <para> + The above filename lists are all optional, although at least + one must be specified for the resulting project file to + be non-empty. + </para> + <para> + In addition to the above lists of values, the following values + may be specified: + </para> + <variablelist> + <varlistentry> + <term>target</term> + <listitem> + <para> + The name of the target <filename>.dsp</filename> + or <filename>.vcproj</filename> file. + The correct suffix for the version of Visual Studio + must be used, but the &cv-link-MSVSPROJECTSUFFIX; + construction variable will be defined to the correct + value (see example below). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>variant</term> + <listitem> + <para> + The name of this particular variant. For Visual Studio 7 + projects, this can also be a list of variant names. These + are typically things like "Debug" or "Release", but + really can be anything you want. For Visual Studio + 7 projects, they may also specify a target platform + separated from the variant name by a <literal>|</literal> + (vertical pipe) character: <literal>Debug|Xbox</literal>. + The default target platform is Win32. Multiple calls + to &b-MSVSProject; with different variants are allowed; + all variants will be added to the project file with + their appropriate build targets and sources. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>cmdargs</term> + <listitem> + <para> + Additional command line arguments + for the different variants. The number of + <literal>cmdargs</literal> entries must match the number + of <literal>variant</literal> entries, or be empty (not + specified). If you give only one, it will automatically + be propagated to all variants. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>cppdefines</term> + <listitem> + <para> + Preprocessor definitions for the different variants. + The number of <literal>cppdefines</literal> entries + must match the number of <literal>variant</literal> + entries, or be empty (not specified). If you give + only one, it will automatically be propagated to all + variants. If you don't give this parameter, SCons + will use the invoking environment's + <literal>CPPDEFINES</literal> entry for all variants. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>cpppaths</term> + <listitem> + <para> + Compiler include paths for the different variants. + The number of <literal>cpppaths</literal> entries + must match the number of <literal>variant</literal> + entries, or be empty (not specified). If you give + only one, it will automatically be propagated to all + variants. If you don't give this parameter, SCons + will use the invoking environment's + <literal>CPPPATH</literal> entry for all variants. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>buildtarget</term> + <listitem> + <para> + An optional string, node, or list of strings + or nodes (one per build variant), to tell + the Visual Studio debugger what output target + to use in what build variant. The number of + <literal>buildtarget</literal> entries must match the + number of <literal>variant</literal> entries. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>runfile</term> + <listitem> + <para> + The name of the file that Visual Studio 7 and + later will run and debug. This appears as the + value of the <literal>Output</literal> field in the + resulting Visual Studio project file. If this is not + specified, the default is the same as the specified + <literal>buildtarget</literal> value. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + Note that because &SCons; always executes its build commands + from the directory in which the &SConstruct; file is located, + if you generate a project file in a different directory + than the &SConstruct; directory, users will not be able to + double-click on the file name in compilation error messages + displayed in the Visual Studio console output window. This can + be remedied by adding the Visual C/C++ <literal>/FC</literal> + compiler option to the &cv-link-CCFLAGS; variable so that + the compiler will print the full path name of any files that + cause compilation errors. + </para> + <para>Example usage:</para> + <example_commands> barsrcs = ['bar.cpp'] barincs = ['bar.h'] barlocalincs = ['StdAfx.h'] barresources = ['bar.rc','resource.h'] barmisc = ['bar_readme.txt'] -dll = env.SharedLibrary(target = 'bar.dll', - source = barsrcs) +dll = env.SharedLibrary(target='bar.dll', + source=barsrcs) buildtarget = [s for s in dll if str(s).endswith('dll')] -env.MSVSProject(target = 'Bar' + env['MSVSPROJECTSUFFIX'], - srcs = barsrcs, - incs = barincs, - localincs = barlocalincs, - resources = barresources, - misc = barmisc, - buildtarget = buildtarget, - variant = 'Release') -</example_commands> -<para>Starting with version 2.4 of -SCons it's also possible to specify the optional argument -<parameter>DebugSettings</parameter>, which creates files for debugging under -Visual Studio:</para><variablelist> - <varlistentry> - <term>DebugSettings</term> - - <listitem> - <para>A dictionary of debug settings that get written to the - <filename>.vcproj.user</filename> or the - <filename>.vcxproj.user</filename> file, depending on the version - installed. As it is done for cmdargs (see above), you can specify a - <parameter>DebugSettings</parameter> dictionary per variant. If you - give only one, it will be propagated to all variants.</para> - </listitem> - </varlistentry> - </variablelist><para>Currently, only Visual Studio v9.0 and Visual Studio -version v11 are implemented, for other versions no file is generated. To -generate the user file, you just need to add a -<parameter>DebugSettings</parameter> dictionary to the environment with the -right parameters for your MSVS version. If the dictionary is empty, or does -not contain any good value, no file will be generated.</para><para>Following -is a more contrived example, involving the setup of a project for variants and -DebugSettings:</para><example_commands># Assuming you store your defaults in a file +env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], + srcs=barsrcs, + incs=barincs, + localincs=barlocalincs, + resources=barresources, + misc=barmisc, + buildtarget=buildtarget, + variant='Release') + </example_commands> + <para> + Starting with version 2.4 of SCons it is + also possible to specify the optional argument + <parameter>DebugSettings</parameter>, which creates files + for debugging under Visual Studio: + </para> + <variablelist> + <varlistentry> + <term>DebugSettings</term> + <listitem> + <para> + A dictionary of debug settings that get written + to the <filename>.vcproj.user</filename> or the + <filename>.vcxproj.user</filename> file, depending on the + version installed. As it is done for cmdargs (see above), + you can specify a <parameter>DebugSettings</parameter> + dictionary per variant. If you give only one, it will + be propagated to all variants. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + Currently, only Visual Studio v9.0 and Visual Studio + version v11 are implemented, for other versions no file + is generated. To generate the user file, you just need to + add a <parameter>DebugSettings</parameter> dictionary to the + environment with the right parameters for your MSVS version. If + the dictionary is empty, or does not contain any good value, + no file will be generated. + </para> + <para> + Following is a more contrived example, involving the setup + of a project for variants and DebugSettings: + </para> + <example_commands> +# Assuming you store your defaults in a file vars = Variables('variables.py') msvcver = vars.args.get('vc', '9') @@ -179,7 +263,7 @@ if msvcver == '9' or msvcver == '11': env = Environment(MSVC_VERSION=msvcver+'.0', MSVC_BATCH=False) else: env = Environment() - + AddOption('--userfile', action='store_true', dest='userfile', default=False, help="Create Visual Studio Project user file") @@ -214,10 +298,10 @@ V9DebugSettings = { } # -# 2. Because there are a lot of different options depending on the Microsoft -# Visual Studio version, if you use more than one version you have to -# define a dictionary per version, for instance if you want to create a user -# file to launch a specific application for testing your dll with Microsoft +# 2. Because there are a lot of different options depending on the Microsoft +# Visual Studio version, if you use more than one version you have to +# define a dictionary per version, for instance if you want to create a user +# file to launch a specific application for testing your dll with Microsoft # Visual Studio 2012 (v11): # V10DebugSettings = { @@ -249,7 +333,7 @@ V10DebugSettings = { } # -# 3. Select the dictionary you want depending on the version of visual Studio +# 3. Select the dictionary you want depending on the version of visual Studio # Files you want to generate. # if not env.GetOption('userfile'): @@ -258,7 +342,7 @@ elif env.get('MSVC_VERSION', None) == '9.0': dbgSettings = V9DebugSettings elif env.get('MSVC_VERSION', None) == '11.0': dbgSettings = V10DebugSettings -else: +else: dbgSettings = None # @@ -270,251 +354,365 @@ barlocalincs = ['StdAfx.h'] barresources = ['bar.rc','resource.h'] barmisc = ['ReadMe.txt'] -dll = env.SharedLibrary(target = 'bar.dll', - source = barsrcs) - -env.MSVSProject(target = 'Bar' + env['MSVSPROJECTSUFFIX'], - srcs = barsrcs, - incs = barincs, - localincs = barlocalincs, - resources = barresources, - misc = barmisc, - buildtarget = [dll[0]] * 2, - variant = ('Debug|Win32', 'Release|Win32'), - cmdargs = 'vc=%s' % msvcver, - DebugSettings = (dbgSettings, {})) -</example_commands> </summary> </builder> <builder -name="MSVSSolution"> <summary> <para>Builds a Microsoft Visual Studio solution -file. </para> <para>This builds a Visual Studio solution file, based on the -version of Visual Studio that is configured (either the latest installed -version, or the version specified by &cv-link-MSVS_VERSION; in the -construction environment). For Visual Studio 6, it will generate a -<filename>.dsw</filename> file. For Visual Studio 7 (.NET), it will generate a -<filename>.sln</filename> file. </para> <para> The following values must be -specified: </para><variablelist> - <varlistentry> - <term>target</term> - - <listitem> - <para>The name of the target .dsw or .sln file. The correct - suffix for the version of Visual Studio must be used, but the value - &cv-link-MSVSSOLUTIONSUFFIX; will be defined to the correct value (see - example below).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>variant</term> - - <listitem> - <para>The name of this particular variant, or a list of variant - names (the latter is only supported for MSVS 7 solutions). These are - typically things like "Debug" or "Release", but really can be anything - you want. For MSVS 7 they may also specify target platform, like this - "Debug|Xbox". Default platform is Win32.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>projects</term> - - <listitem> - <para>A list of project file names, or Project nodes returned by - calls to the &b-MSVSProject; Builder, to be placed into the solution - file. It should be noted that these file names are NOT added to the - $SOURCES environment variable in form of files, but rather as strings. - This is because they represent file names to be added to the solution - file, not the source files used to build the solution - file.</para> - </listitem> - </varlistentry> - </variablelist> <para> Example Usage: </para> <example_commands> -env.MSVSSolution(target = 'Bar' + env['MSVSSOLUTIONSUFFIX'], projects = ['bar' -+ env['MSVSPROJECTSUFFIX']], variant = 'Release') -</example_commands></summary></builder> <cvar name="MSVS"> <summary> <para> -When the Microsoft Visual Studio tools are initialized, they set up this -dictionary with the following keys: </para><variablelist> - <varlistentry> - <term>VERSION</term> - - <listitem> - <para>the version of MSVS being used (can be set via - &cv-link-MSVS_VERSION;)</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>VERSIONS</term> - - <listitem> - <para>the available versions of MSVS installed</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>VCINSTALLDIR</term> - - <listitem> - <para>installed directory of Visual C++</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>VSINSTALLDIR</term> - - <listitem> - <para>installed directory of Visual Studio</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKDIR</term> - - <listitem> - <para>installed directory of the .NET framework</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKVERSIONS</term> - - <listitem> - <para>list of installed versions of the .NET framework, sorted - latest to oldest.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKVERSION</term> - - <listitem> - <para>latest installed version of the .NET - framework</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKSDKDIR</term> - - <listitem> - <para>installed location of the .NET SDK.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>PLATFORMSDKDIR</term> - - <listitem> - <para>installed location of the Platform SDK.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>PLATFORMSDK_MODULES</term> - - <listitem> - <para>dictionary of installed Platform SDK modules, where the - dictionary keys are keywords for the various modules, and the values - are 2-tuples where the first is the release date, and the second is - the version number.</para> - </listitem> - </varlistentry> - </variablelist><para>If a value isn't set, it wasn't available in the -registry.</para></summary></cvar> <cvar name="MSVS_ARCH"> <summary> <para>Sets -the architecture for which the generated project(s) should build. </para> -<para>The default value is <literal>x86</literal>. <literal>amd64</literal> is -also supported by &SCons; for some Visual Studio versions. Trying to set -&cv-MSVS_ARCH; to an architecture that's not supported for a given Visual -Studio version will generate an error. </para> </summary> </cvar> <cvar -name="MSVS_PROJECT_GUID"> <summary> <para>The string placed in a generated +dll = env.SharedLibrary(target='bar.dll', + source=barsrcs) + +env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], + srcs=barsrcs, + incs=barincs, + localincs=barlocalincs, + resources=barresources, + misc=barmisc, + buildtarget=[dll[0]] * 2, + variant=('Debug|Win32', 'Release|Win32'), + cmdargs='vc=%s' % msvcver, + DebugSettings=(dbgSettings, {})) + </example_commands> + </summary> + </builder> + <builder name="MSVSSolution"> + <summary> + <para>Builds a Microsoft Visual Studio solution file.</para> + <para> + This builds a Visual Studio solution file, based on the + version of Visual Studio that is configured (either the + latest installed version, or the version specified by + &cv-link-MSVS_VERSION; in the construction environment). For + Visual Studio 6, it will generate a <filename>.dsw</filename> + file. For Visual Studio 7 (.NET), it will generate a + <filename>.sln</filename> file. + </para> + <para>The following values must be specified:</para> + <variablelist> + <varlistentry> + <term>target</term> + <listitem> + <para> + The name of the target .dsw or .sln file. The correct + suffix for the version of Visual Studio must be used, + but the value &cv-link-MSVSSOLUTIONSUFFIX; will be + defined to the correct value (see example below). + </para> + </listitem> + </varlistentry> <varlistentry> + <term>variant</term> <listitem> + <para> + The name of this particular variant, or a list of + variant names (the latter is only supported for MSVS + 7 solutions). These are typically things like "Debug" + or "Release", but really can be anything you want. For + MSVS 7 they may also specify target platform, like this + "Debug|Xbox". Default platform is Win32. + </para> + </listitem> + </varlistentry> <varlistentry> + <term>projects</term> <listitem> + <para> + A list of project file names, or Project nodes returned + by calls to the &b-MSVSProject; Builder, to be placed + into the solution file. It should be noted that these + file names are NOT added to the $SOURCES environment + variable in form of files, but rather as strings. + This is because they represent file names to be added + to the solution file, not the source files used to + build the solution file. + </para> + </listitem> + </varlistentry> + </variablelist> + <para>Example Usage:</para> + <example_commands> +env.MSVSSolution(target='Bar' + env['MSVSSOLUTIONSUFFIX'], projects=['bar' + env['MSVSPROJECTSUFFIX']], variant='Release') + </example_commands> + </summary> + </builder> <cvar name="MSVS"> + <summary> + <para> + When the Microsoft Visual Studio tools are initialized, + they set up this dictionary with the following keys: + </para> + <variablelist> + <varlistentry> + <term>VERSION</term> <listitem> + <para>the version of MSVS being used (can be set via + &cv-link-MSVS_VERSION;)</para> + </listitem> + </varlistentry> <varlistentry> + <term>VERSIONS</term> <listitem> + <para>the available versions of MSVS installed</para> + </listitem> + </varlistentry> <varlistentry> + <term>VCINSTALLDIR</term> <listitem> + <para>installed directory of Visual C++</para> + </listitem> + </varlistentry> <varlistentry> + <term>VSINSTALLDIR</term> <listitem> + <para>installed directory of Visual Studio</para> + </listitem> + </varlistentry> <varlistentry> + <term>FRAMEWORKDIR</term> <listitem> + <para>installed directory of the .NET framework</para> + </listitem> + </varlistentry> <varlistentry> + <term>FRAMEWORKVERSIONS</term> <listitem> + <para> + list of installed versions of the .NET framework, + sorted latest to oldest. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>FRAMEWORKVERSION</term> + <listitem> + <para>latest installed version of the .NET framework</para> + </listitem> + </varlistentry> + <varlistentry> + <term>FRAMEWORKSDKDIR</term> + <listitem> + <para>installed location of the .NET SDK.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>PLATFORMSDKDIR</term> + <listitem> + <para>installed location of the Platform SDK.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>PLATFORMSDK_MODULES</term> + <listitem> + <para> + dictionary of installed Platform SDK modules, where the + dictionary keys are keywords for the various modules, + and the values are 2-tuples where the first is the + release date, and the second is the version number. + </para> + </listitem> + </varlistentry> + </variablelist> + <para>If a value is not set, it was not available in the registry.</para> + </summary> + </cvar> <cvar name="MSVS_ARCH"> + <summary> + <para>Sets the architecture for which the generated project(s) should build.</para> + <para> + The default value is <literal>x86</literal>. + <literal>amd64</literal> is also supported by &SCons; for + most Visual Studio versions. Since Visual Studio 2015 + <literal>arm</literal> is supported, and since Visual Studio + 2017 <literal>arm64</literal> is supported. + Trying to set &cv-MSVS_ARCH; + to an architecture that's not supported for a given Visual + Studio version will generate an error. + </para> + </summary> + </cvar> <cvar name="MSVS_PROJECT_GUID"> + <summary> + <para> + The string placed in a generated Microsoft Visual Studio project file as the value of the -<literal>ProjectGUID</literal> attribute. There is no default value. If not -defined, a new GUID is generated. </para> </summary> </cvar> <cvar -name="MSVS_SCC_AUX_PATH"> <summary> <para>The path name placed in a generated + <literal>ProjectGUID</literal> attribute. There is no default + value. If not +defined, a new GUID is generated. + + </para> + </summary> + </cvar> <cvar name="MSVS_SCC_AUX_PATH"> + <summary> + <para> + The path name placed in a generated Microsoft Visual Studio project file as the value of the -<literal>SccAuxPath</literal> attribute if the -<envar>MSVS_SCC_PROVIDER</envar> construction variable is also set. There is -no default value. </para> </summary> </cvar> <cvar -name="MSVS_SCC_CONNECTION_ROOT"> <summary> <para>The root path of projects in -your SCC workspace, i.e the path under which all project and solution files -will be generated. It is used as a reference path from which the relative -paths of the generated Microsoft Visual Studio project and solution files are -computed. The relative project file path is placed as the value of the -<literal>SccLocalPath</literal> attribute of the project file and as the -values of the -<literal>SccProjectFilePathRelativizedFromConnection[i]</literal> (where [i] -ranges from 0 to the number of projects in the solution) attributes of the -<literal>GlobalSection(SourceCodeControl)</literal> section of the Microsoft -Visual Studio solution file. Similarly the relative solution file path is -placed as the values of the <literal>SccLocalPath[i]</literal> (where [i] -ranges from 0 to the number of projects in the solution) attributes of the -<literal>GlobalSection(SourceCodeControl)</literal> section of the Microsoft -Visual Studio solution file. This is used only if the -<envar>MSVS_SCC_PROVIDER</envar> construction variable is also set. The -default value is the current working directory. </para> </summary> </cvar> -<cvar name="MSVS_SCC_PROJECT_NAME"> <summary> <para>The project name placed in -a generated Microsoft Visual Studio project file as the value of the -<literal>SccProjectName</literal> attribute if the -<envar>MSVS_SCC_PROVIDER</envar> construction variable is also set. In this -case the string is also placed in the <literal>SccProjectName0</literal> -attribute of the <literal>GlobalSection(SourceCodeControl)</literal> section -of the Microsoft Visual Studio solution file. There is no default value. -</para> </summary> </cvar> <cvar name="MSVS_SCC_PROVIDER"> <summary> <para>The -string placed in a generated Microsoft Visual Studio project file as the value -of the <literal>SccProvider</literal> attribute. The string is also placed in -the <literal>SccProvider0</literal> attribute of the -<literal>GlobalSection(SourceCodeControl)</literal> section of the Microsoft -Visual Studio solution file. There is no default value. </para> </summary> -</cvar> <cvar name="MSVS_VERSION"> <summary> <para>Sets the preferred version -of Microsoft Visual Studio to use. </para> <para>If &cv-MSVS_VERSION; is not -set, &SCons; will (by default) select the latest version of Visual Studio -installed on your system. So, if you have version 6 and version 7 (MSVS .NET) -installed, it will prefer version 7. You can override this by specifying the -<envar>MSVS_VERSION</envar> variable in the Environment initialization, -setting it to the appropriate version ('6.0' or '7.0', for example). If the -specified version isn't installed, tool initialization will fail. </para> -<para>This is obsolete: use &cv-MSVC_VERSION; instead. If &cv-MSVS_VERSION; is -set and &cv-MSVC_VERSION; is not, &cv-MSVC_VERSION; will be set automatically -to &cv-MSVS_VERSION;. If both are set to different values, scons will raise an -error. </para> </summary> </cvar> <cvar name="MSVSBUILDCOM"> <summary> -<para>The build command line placed in a generated Microsoft Visual Studio -project file. The default is to have Visual Studio invoke SCons with any -specified build targets. </para> </summary> </cvar> <cvar name="MSVSCLEANCOM"> -<summary> <para>The clean command line placed in a generated Microsoft Visual -Studio project file. The default is to have Visual Studio invoke SCons with -the -c option to remove any specified targets. </para> </summary> </cvar> -<cvar name="MSVSENCODING"> <summary> <para>The encoding string placed in a -generated Microsoft Visual Studio project file. The default is encoding -<literal>Windows-1252</literal>. </para> </summary> </cvar> <cvar -name="MSVSPROJECTCOM"> <summary> <para>The action used to generate Microsoft -Visual Studio project files. </para> </summary> </cvar> <cvar -name="MSVSPROJECTSUFFIX"> <summary> <para>The suffix used for Microsoft Visual -Studio project (DSP) files. The default value is <filename>.vcproj</filename> -when using Visual Studio version 7.x (.NET) or later version, and -<filename>.dsp</filename> when using earlier versions of Visual Studio. -</para> </summary> </cvar> <cvar name="MSVSREBUILDCOM"> <summary> <para>The -rebuild command line placed in a generated Microsoft Visual Studio project -file. The default is to have Visual Studio invoke SCons with any specified -rebuild targets. </para> </summary> </cvar> <cvar name="MSVSSCONS"> <summary> -<para>The SCons used in generated Microsoft Visual Studio project files. The -default is the version of SCons being used to generate the project file. -</para> </summary> </cvar> <cvar name="MSVSSCONSFLAGS"> <summary> <para>The -SCons flags used in generated Microsoft Visual Studio project files. </para> -</summary> </cvar> <cvar name="MSVSSCONSCOM"> <summary> <para>The default -SCons command used in generated Microsoft Visual Studio project files. </para> -</summary> </cvar> <cvar name="MSVSSCONSCRIPT"> <summary> <para>The sconscript -file (that is, &SConstruct; or &SConscript; file) that will be invoked by -Visual Studio project files (through the &cv-link-MSVSSCONSCOM; variable). The -default is the same sconscript file that contains the call to &b-MSVSProject; -to build the project file. </para> </summary> </cvar> <cvar -name="MSVSSOLUTIONCOM"> <summary> <para>The action used to generate Microsoft -Visual Studio solution files. </para> </summary> </cvar> <cvar -name="MSVSSOLUTIONSUFFIX"> <summary> <para>The suffix used for Microsoft -Visual Studio solution (DSW) files. The default value is -<filename>.sln</filename> when using Visual Studio version 7.x (.NET), and -<filename>.dsw</filename> when using earlier versions of Visual Studio. -</para> </summary> </cvar> <cvar name="SCONS_HOME"> <summary> <para>The -(optional) path to the SCons library directory, initialized from the external -environment. If set, this is used to construct a shorter and more efficient -search path in the &cv-link-MSVSSCONS; command line executed from Microsoft -Visual Studio project files. </para> </summary> </cvar></sconsdoc> + <literal>SccAuxPath</literal> attribute if the + <envar>MSVS_SCC_PROVIDER</envar> construction variable is + also set. There is +no default value. + + </para> + </summary> + </cvar> <cvar name="MSVS_SCC_CONNECTION_ROOT"> + <summary> + <para> + The root path of projects in your SCC workspace, i.e the + path under which all project and solution files will be + generated. It is used as a reference path from which the + relative paths of the generated Microsoft Visual Studio project + and solution files are computed. The relative project file path + is placed as the value of the <literal>SccLocalPath</literal> + attribute of the project file and as the values of the + <literal>SccProjectFilePathRelativizedFromConnection[i]</literal> + (where [i] ranges from 0 to the number of projects in the solution) + attributes of the <literal>GlobalSection(SourceCodeControl)</literal> + section of the Microsoft Visual Studio solution file. Similarly + the relative solution file path is placed as the values of the + <literal>SccLocalPath[i]</literal> (where [i] ranges from 0 + to the number of projects in the solution) attributes of the + <literal>GlobalSection(SourceCodeControl)</literal> section of + the Microsoft Visual Studio solution file. This is used only if + the <envar>MSVS_SCC_PROVIDER</envar> construction variable is + also set. The default value is the current working directory. + </para> + </summary> + </cvar> <cvar name="MSVS_SCC_PROJECT_NAME"> + <summary> + <para> + The project name placed in a generated Microsoft + Visual Studio project file as the value of the + <literal>SccProjectName</literal> attribute if the + <envar>MSVS_SCC_PROVIDER</envar> construction variable + is also set. In this case the string is also placed in + the <literal>SccProjectName0</literal> attribute of the + <literal>GlobalSection(SourceCodeControl)</literal> section + of the Microsoft Visual Studio solution file. There is no + default value. + </para> + </summary> + </cvar> <cvar name="MSVS_SCC_PROVIDER"> + <summary> + <para> + The string placed in a generated Microsoft + Visual Studio project file as the value of the + <literal>SccProvider</literal> attribute. The string is + also placed in the <literal>SccProvider0</literal> attribute + of the <literal>GlobalSection(SourceCodeControl)</literal> + section of the Microsoft Visual Studio solution file. There + is no default value. + </para> + </summary> + </cvar> <cvar name="MSVS_VERSION"> + <summary> + <para>Sets the preferred version of Microsoft Visual Studio to use.</para> + <para> + If &cv-MSVS_VERSION; is not set, &SCons; will (by default) + select the latest version of Visual Studio installed on your + system. So, if you have version 6 and version 7 (MSVS .NET) + installed, it will prefer version 7. You can override this by + specifying the <envar>MSVS_VERSION</envar> variable in the + Environment initialization, setting it to the appropriate + version ('6.0' or '7.0', for example). If the specified + version isn't installed, tool initialization will fail. + </para> + <para> + This is obsolete: use &cv-MSVC_VERSION; instead. If + &cv-MSVS_VERSION; is set and &cv-MSVC_VERSION; is + not, &cv-MSVC_VERSION; will be set automatically to + &cv-MSVS_VERSION;. If both are set to different values, + scons will raise an error. + </para> + </summary> + </cvar> + <cvar name="MSVSBUILDCOM"> + <summary> + <para> + The build command line placed in a generated Microsoft Visual + Studio project file. The default is to have Visual Studio + invoke SCons with any specified build targets. + </para> + </summary> + </cvar> + <cvar name="MSVSCLEANCOM"> + <summary> + <para> + The clean command line placed in a generated Microsoft Visual + Studio project file. The default is to have Visual Studio + invoke SCons with the -c option to remove any specified + targets. + </para> + </summary> + </cvar> <cvar name="MSVSENCODING"> + <summary> + <para> + The encoding string placed in a generated Microsoft + Visual Studio project file. The default is encoding + <literal>Windows-1252</literal>. + </para> + </summary> + </cvar> + <cvar name="MSVSPROJECTCOM"> + <summary> + <para>The action used to generate Microsoft Visual Studio project files.</para> + </summary> + </cvar> + <cvar name="MSVSPROJECTSUFFIX"> + <summary> + <para> + The suffix used for Microsoft Visual Studio project (DSP) + files. The default value is <filename>.vcproj</filename> + when using Visual Studio version 7.x (.NET) or later version, + and <filename>.dsp</filename> when using earlier versions of + Visual Studio. + </para> + </summary> + </cvar> + <cvar name="MSVSREBUILDCOM"> + <summary> + <para> + The rebuild command line placed in a generated Microsoft + Visual Studio project file. The default is to have Visual + Studio invoke SCons with any specified rebuild targets. + + </para> + </summary> + </cvar> + <cvar name="MSVSSCONS"> + <summary> + <para> + The SCons used in generated Microsoft Visual Studio project + files. The default is the version of SCons being used to + generate the project file. + </para> + </summary> + </cvar> + <cvar name="MSVSSCONSFLAGS"> + <summary> + <para> + The SCons flags used in generated Microsoft Visual Studio project files. + </para> + </summary> + </cvar> + <cvar name="MSVSSCONSCOM"> + <summary> + <para> + The default SCons command used in generated Microsoft Visual + Studio project files. + </para> + </summary> + </cvar> + <cvar name="MSVSSCONSCRIPT"> + <summary> + <para> + The sconscript file (that is, &SConstruct; or &SConscript; + file) that will be invoked by Visual Studio project files + (through the &cv-link-MSVSSCONSCOM; variable). The default + is the same sconscript file that contains the call to + &b-MSVSProject; to build the project file. + </para> + </summary> + </cvar> + <cvar name="MSVSSOLUTIONCOM"> + <summary> + <para>The action used to generate Microsoft Visual Studio solution files.</para> + </summary> + </cvar> <cvar name="MSVSSOLUTIONSUFFIX"> + <summary> + <para> + The suffix used for Microsoft Visual Studio solution (DSW) + files. The default value is <filename>.sln</filename> + when using Visual Studio version 7.x (.NET), and + <filename>.dsw</filename> when using earlier versions of + Visual Studio. + </para> + </summary> + </cvar> + <cvar name="SCONS_HOME"> + <summary> + <para> + The (optional) path to the SCons library directory, + initialized from the external environment. If set, this is + used to construct a shorter and more efficient search path in + the &cv-link-MSVSSCONS; command line executed from Microsoft + Visual Studio project files. + </para> + </summary> + </cvar> +</sconsdoc> diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 8c09487..e0b5ced 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/msvsTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msvsTests.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import sys @@ -34,6 +34,7 @@ import TestUnit from SCons.Tool.msvs import * from SCons.Tool.MSCommon.vs import SupportedVSList +import SCons.Node.FS import SCons.Util import SCons.Warnings @@ -352,6 +353,36 @@ regdata_80 = r''' "VCXDCMakeTool"="*.xdc" '''.split('\n') +regdata_140 = r''' +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\14.0\Setup\VS] +"MSMDir"="C:\\Program Files (x86)\\Common Files\\Merge Modules\\" +"ProductDir"="C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\" +"VS7EnvironmentLocation"="C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\devenv.exe" +"EnvironmentPath"="C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\devenv.exe" +"EnvironmentDirectory"="C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\IDE\\" +"VS7CommonDir"="C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\Common7\\" +"VS7CommonBinDir"="" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\14.0\Setup\VS\BuildNumber] +"1033"="14.0" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\14.0\Setup\VS\Community] +"ProductDir"="C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\14.0\Setup\VS\JSLS_MSI] +"Version"="14.0.25527" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\14.0\Setup\VS\JSPS_MSI] +"Version"="14.0.25527" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\14.0\Setup\VS\Pro] +"ProductDir"="C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\14.0\Setup\VS\professional] +"IsInstallInProgress"="0" +"CurrentOperation"="install" +"SetupFeedUri"="http://go.microsoft.com/fwlink/?LinkID=659004&clcid=0x409" +"SetupFeedLocalCache"="C:\\ProgramData\\Microsoft\\VisualStudioSecondaryInstaller\\14.0\\LastUsedFeed\\{68432bbb-c9a5-4a7b-bab3-ae5a49b28303}\\Feed.xml" +"InstallResult"="0" +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\14.0\Setup\VS\SecondaryInstaller] +[HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\14.0\Setup\VS\SecondaryInstaller\AppInsightsTools] +"Version"="7.0.20620.1" +'''.split('\n') + regdata_cv = r'''[HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion] "ProgramFilesDir"="C:\Program Files" "CommonFilesDir"="C:\Program Files\Common Files" @@ -363,6 +394,7 @@ regdata_none = [] class DummyEnv(object): def __init__(self, dict=None): + self.fs = SCons.Node.FS.FS() if dict: self.dict = dict else: @@ -385,6 +417,16 @@ class DummyEnv(object): def has_key(self,name): return name in self.dict + def get(self, name, value=None): + if self.has_key(name): + return self.dict[name] + else: + return value + + def Dir(self, name): + return self.fs.Dir(name) + + class RegKey(object): """key class for storing an 'open' registry key""" def __init__(self,key): @@ -482,8 +524,8 @@ class DummyRegistry(object): def parse(self, data): parents = [None, None] parents[0] = self.root - keymatch = re.compile('^\[(.*)\]$') - valmatch = re.compile('^(?:"(.*)"|[@])="(.*)"$') + keymatch = re.compile(r'^\[(.*)\]$') + valmatch = re.compile(r'^(?:"(.*)"|[@])="(.*)"$') for line in data: m1 = keymatch.match(line) if m1: @@ -540,6 +582,10 @@ def DummyQueryValue(key, value): def DummyExists(path): return 1 +def DummyVsWhere(msvc_version): + # not testing versions with vswhere, so return none + return None + class msvsTestCase(unittest.TestCase): """This test case is run several times with different defaults. See its subclasses below.""" @@ -550,6 +596,11 @@ class msvsTestCase(unittest.TestCase): from SCons.Tool.MSCommon.vs import reset_installed_visual_studios reset_installed_visual_studios() + self.test = TestCmd.TestCmd(workdir='') + # FS doesn't like the cwd to be something other than its root. + os.chdir(self.test.workpath("")) + self.fs = SCons.Node.FS.FS() + def test_get_default_version(self): """Test retrieval of the default visual studio version""" @@ -603,13 +654,19 @@ class msvsTestCase(unittest.TestCase): version_num, suite = msvs_parse_version(self.highest_version) if version_num >= 10.0: function_test = _GenerateV10DSP + suffix = '.vcxproj' elif version_num >= 7.0: function_test = _GenerateV7DSP + suffix = '.dsp' else: function_test = _GenerateV6DSP + suffix = '.dsp' + + # Avoid any race conditions between the test cases when we test + # actually writing the files. + dspfile = 'test%s%s' % (hash(self), suffix) str_function_test = str(function_test.__init__) - dspfile = 'test.dsp' source = 'test.cpp' # Create the cmdargs test list @@ -619,50 +676,95 @@ class msvsTestCase(unittest.TestCase): 'debug=False target_arch=32', 'debug=True target_arch=x64', 'debug=False target_arch=x64'] - - # Tuple list : (parameter, dictionary of expected result per variant) - tests_cmdargs = [(None, dict.fromkeys(list_variant, '')), - ('', dict.fromkeys(list_variant, '')), - (list_cmdargs[0], dict.fromkeys(list_variant, list_cmdargs[0])), - (list_cmdargs, dict(list(zip(list_variant, list_cmdargs))))] - + list_cppdefines = [['_A', '_B', 'C'], ['_B', '_C_'], ['D'], []] + list_cpppaths = [[r'C:\test1'], [r'C:\test1;C:\test2'], + [self.fs.Dir('subdir')], []] + + def TestParamsFromList(test_variant, test_list): + """ + Generates test data based on the parameters passed in. + + Returns tuple list: + 1. Parameter. + 2. Dictionary of expected result per variant. + """ + def normalizeParam(param): + """ + Converts the raw data based into the AddConfig function of + msvs.py to the expected result. + + Expects the following behavior: + 1. A value of None will be converted to an empty list. + 2. A File or Directory object will be converted to an + absolute path (because those objects can't be pickled). + 3. Otherwise, the parameter will be used. + """ + if param is None: + return [] + elif isinstance(param, list): + return [normalizeParam(p) for p in param] + elif hasattr(param, 'abspath'): + return param.abspath + else: + return param + + return [ + (None, dict.fromkeys(test_variant, '')), + ('', dict.fromkeys(test_variant, '')), + (test_list[0], dict.fromkeys(test_variant, normalizeParam(test_list[0]))), + (test_list, dict(list(zip(test_variant, [normalizeParam(x) for x in test_list])))) + ] + + tests_cmdargs = TestParamsFromList(list_variant, list_cmdargs) + tests_cppdefines = TestParamsFromList(list_variant, list_cppdefines) + tests_cpppaths = TestParamsFromList(list_variant, list_cpppaths) + # Run the test for each test case for param_cmdargs, expected_cmdargs in tests_cmdargs: - debug('Testing %s. with :\n variant = %s \n cmdargs = "%s"' % \ - (str_function_test, list_variant, param_cmdargs)) - param_configs = [] - expected_configs = {} - for platform in ['Win32', 'x64']: - for variant in ['Debug', 'Release']: - variant_platform = '%s|%s' % (variant, platform) - runfile = '%s\\%s\\test.exe' % (platform, variant) - buildtarget = '%s\\%s\\test.exe' % (platform, variant) - outdir = '%s\\%s' % (platform, variant) + for param_cppdefines, expected_cppdefines in tests_cppdefines: + for param_cpppaths, expected_cpppaths in tests_cpppaths: + debug('Testing %s. with :\n variant = %s \n cmdargs = "%s" \n cppdefines = "%s" \n cpppaths = "%s"' % \ + (str_function_test, list_variant, param_cmdargs, param_cppdefines, param_cpppaths)) + param_configs = [] + expected_configs = {} + for platform in ['Win32', 'x64']: + for variant in ['Debug', 'Release']: + variant_platform = '%s|%s' % (variant, platform) + runfile = '%s\\%s\\test.exe' % (platform, variant) + buildtarget = '%s\\%s\\test.exe' % (platform, variant) + outdir = '%s\\%s' % (platform, variant) - # Create parameter list for this variant_platform - param_configs.append([variant_platform, runfile, buildtarget, outdir]) - - # Create expected dictionary result for this variant_platform - expected_configs[variant_platform] = \ - {'variant': variant, 'platform': platform, - 'runfile': runfile, - 'buildtarget': buildtarget, - 'outdir': outdir, - 'cmdargs': expected_cmdargs[variant_platform]} + # Create parameter list for this variant_platform + param_configs.append([variant_platform, runfile, buildtarget, outdir]) + # Create expected dictionary result for this variant_platform + expected_configs[variant_platform] = { + 'variant': variant, + 'platform': platform, + 'runfile': runfile, + 'buildtarget': buildtarget, + 'outdir': outdir, + 'cmdargs': expected_cmdargs[variant_platform], + 'cppdefines': expected_cppdefines[variant_platform], + 'cpppaths': expected_cpppaths[variant_platform], + } + # Create parameter environment with final parameter dictionary param_dict = dict(list(zip(('variant', 'runfile', 'buildtarget', 'outdir'), [list(l) for l in zip(*param_configs)]))) param_dict['cmdargs'] = param_cmdargs + param_dict['cppdefines'] = param_cppdefines + param_dict['cpppaths'] = param_cpppaths # Hack to be able to run the test with a 'DummyEnv' class _DummyEnv(DummyEnv): - def subst(self, string) : + def subst(self, string, *args, **kwargs): return string env = _DummyEnv(param_dict) env['MSVSSCONSCRIPT'] = '' env['MSVS_VERSION'] = self.highest_version + env['MSVSBUILDTARGET'] = 'target' # Call function to test genDSP = function_test(dspfile, source, env) @@ -672,6 +774,16 @@ class msvsTestCase(unittest.TestCase): for key in list(genDSP.configs.keys()): self.assertDictEqual(genDSP.configs[key].__dict__, expected_configs[key]) + genDSP.Build() + + # Delete the resulting file so we don't leave anything behind. + for file in [dspfile, dspfile + '.filters']: + path = os.path.realpath(file) + try: + os.remove(path) + except OSError: + pass + class msvs6aTestCase(msvsTestCase): """Test MSVS 6 Registry""" registry = DummyRegistry(regdata_6a + regdata_cv) @@ -783,6 +895,18 @@ class msvs80TestCase(msvsTestCase): } default_install_loc = install_locs['8.0'] +class msvs140TestCase(msvsTestCase): + """Test MSVS 140 Registry""" + registry = DummyRegistry(regdata_140 + regdata_cv) + default_version = '14.0' + highest_version = '14.0' + number_of_versions = 2 + install_locs = { + '14.0' : {'VSINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 14.0', + 'VCINSTALLDIR': 'C:\\Program Files\\Microsoft Visual Studio 14.0\\VC'}, + } + default_install_loc = install_locs['14.0'] + class msvsEmptyTestCase(msvsTestCase): """Test Empty Registry""" registry = DummyRegistry(regdata_none) @@ -809,6 +933,7 @@ if __name__ == "__main__": SCons.Util.RegEnumKey = DummyEnumKey SCons.Util.RegEnumValue = DummyEnumValue SCons.Util.RegQueryValueEx = DummyQueryValue + SCons.Tool.MSCommon.vc.find_vc_pdir_vswhere = DummyVsWhere os.path.exists = DummyExists # make sure all files exist :-) os.path.isfile = DummyExists # make sure all files are files :-) @@ -824,6 +949,7 @@ if __name__ == "__main__": msvs71TestCase, msvs8ExpTestCase, msvs80TestCase, + msvs140TestCase, msvsEmptyTestCase, ] diff --git a/src/engine/SCons/Tool/mwcc.py b/src/engine/SCons/Tool/mwcc.py index 566f812..b2b2f5b 100644 --- a/src/engine/SCons/Tool/mwcc.py +++ b/src/engine/SCons/Tool/mwcc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mwcc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mwcc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import os.path diff --git a/src/engine/SCons/Tool/mwcc.xml b/src/engine/SCons/Tool/mwcc.xml index 39e6dfa..e9f210c 100644 --- a/src/engine/SCons/Tool/mwcc.xml +++ b/src/engine/SCons/Tool/mwcc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mwld.py b/src/engine/SCons/Tool/mwld.py index 9abeeb5..5049c55 100644 --- a/src/engine/SCons/Tool/mwld.py +++ b/src/engine/SCons/Tool/mwld.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mwld.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mwld.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Tool diff --git a/src/engine/SCons/Tool/mwld.xml b/src/engine/SCons/Tool/mwld.xml index 993fefe..261a039 100644 --- a/src/engine/SCons/Tool/mwld.xml +++ b/src/engine/SCons/Tool/mwld.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/nasm.py b/src/engine/SCons/Tool/nasm.py index c605cc6..d4d0a1b 100644 --- a/src/engine/SCons/Tool/nasm.py +++ b/src/engine/SCons/Tool/nasm.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/nasm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/nasm.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/nasm.xml b/src/engine/SCons/Tool/nasm.xml index 1834b34..6626411 100644 --- a/src/engine/SCons/Tool/nasm.xml +++ b/src/engine/SCons/Tool/nasm.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/packaging.xml b/src/engine/SCons/Tool/packaging.xml index ea39115..9b46000 100644 --- a/src/engine/SCons/Tool/packaging.xml +++ b/src/engine/SCons/Tool/packaging.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/packaging/__init__.py b/src/engine/SCons/Tool/packaging/__init__.py index b844afb..72b9eef 100644 --- a/src/engine/SCons/Tool/packaging/__init__.py +++ b/src/engine/SCons/Tool/packaging/__init__.py @@ -4,7 +4,7 @@ SCons Packaging Tool. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,18 +25,23 @@ SCons Packaging Tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/packaging/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/__init__.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" +import SCons.Defaults import SCons.Environment from SCons.Variables import * from SCons.Errors import * from SCons.Util import is_List, make_path_relative from SCons.Warnings import warn, Warning -import os, imp -import SCons.Defaults +import os +import importlib -__all__ = [ 'src_targz', 'src_tarbz2', 'src_zip', 'tarbz2', 'targz', 'zip', 'rpm', 'msi', 'ipk' ] +__all__ = [ + 'src_targz', 'src_tarbz2', 'src_tarxz', 'src_zip', + 'targz', 'tarbz2', 'tarxz', 'zip', + 'rpm', 'msi', 'ipk', +] # # Utility and Builder function @@ -102,7 +107,7 @@ def Package(env, target=None, source=None, **kw): from SCons.Script import GetOption kw['PACKAGETYPE'] = GetOption('package_type') - if kw['PACKAGETYPE'] == None: + if kw['PACKAGETYPE'] is None: if 'Tar' in env['BUILDERS']: kw['PACKAGETYPE']='targz' elif 'Zip' in env['BUILDERS']: @@ -117,12 +122,12 @@ def Package(env, target=None, source=None, **kw): # load the needed packagers. def load_packager(type): try: - file,path,desc=imp.find_module(type, __path__) - return imp.load_module(type, file, path, desc) + # the specific packager is a relative import + return importlib.import_module("." + type, __name__) except ImportError as e: - raise EnvironmentError("packager %s not available: %s"%(type,str(e))) + raise SConsEnvironmentError("packager %s not available: %s" % (type, str(e))) - packagers=list(map(load_packager, PACKAGETYPE)) + packagers = list(map(load_packager, PACKAGETYPE)) # set up targets and the PACKAGEROOT try: @@ -163,15 +168,22 @@ def Package(env, target=None, source=None, **kw): # this exception means that a needed argument for the packager is # missing. As our packagers get their "tags" as named function # arguments we need to find out which one is missing. - from inspect import getargspec - args,varargs,varkw,defaults=getargspec(packager.package) - if defaults!=None: - args=args[:-len(defaults)] # throw away arguments with default values + #TODO: getargspec deprecated in Py3. cleanup when Py2.7 dropped. + try: + from inspect import getfullargspec + argspec = getfullargspec(packager.package) + except ImportError: + from inspect import getargspec + argspec = getargspec(packager.package) + args = argspec.args + if argspec.defaults: + # throw away arguments with default values + args = args[:-len(argspec.defaults)] args.remove('env') args.remove('target') args.remove('source') # now remove any args for which we have a value in kw. - args=[x for x in args if x not in kw] + args = [x for x in args if x not in kw] if len(args)==0: raise # must be a different error, so re-raise @@ -283,10 +295,9 @@ def stripinstallbuilder(target, source, env): It also warns about files which have no install builder attached. """ def has_no_install_location(file): - return not (file.has_builder() and\ - hasattr(file.builder, 'name') and\ - (file.builder.name=="InstallBuilder" or\ - file.builder.name=="InstallAsBuilder")) + return not (file.has_builder() and hasattr(file.builder, 'name') + and file.builder.name in ["InstallBuilder", "InstallAsBuilder"]) + if len([src for src in source if has_no_install_location(src)]): warn(Warning, "there are files to package which have no\ diff --git a/src/engine/SCons/Tool/packaging/__init__.xml b/src/engine/SCons/Tool/packaging/__init__.xml index 0ee0f6b..1643def 100644 --- a/src/engine/SCons/Tool/packaging/__init__.xml +++ b/src/engine/SCons/Tool/packaging/__init__.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -64,13 +64,15 @@ the following packagers available: <para> * msi - Microsoft Installer - * rpm - Redhat Package Manger + * rpm - RPM Package Manger * ipkg - Itsy Package Management System - * tarbz2 - compressed tar - * targz - compressed tar + * tarbz2 - bzip2 compressed tar + * targz - gzip compressed tar + * tarxz - xz compressed tar * zip - zip file - * src_tarbz2 - compressed tar source - * src_targz - compressed tar source + * src_tarbz2 - bzip2 compressed tar source + * src_targz - gzip compressed tar source + * src_tarxz - xz compressed tar source * src_zip - zip file source </para> @@ -106,7 +108,9 @@ This is used to fill in the <literal>Architecture:</literal> field in an Ipkg <filename>control</filename> file, -and as part of the name of a generated RPM file. +and the <literal>BuildArch:</literal> field +in the RPM <filename>.spec</filename> file, +as well as forming part of the name of a generated RPM package file. </para> </summary> </cvar> @@ -120,7 +124,6 @@ the <filename>control</filename> for Ipkg, the <filename>.wxs</filename> for MSI). If set, the function will be called after the SCons template for the file has been written. -XXX </para> </summary> </cvar> @@ -164,10 +167,10 @@ section of an RPM <cvar name="LICENSE"> <summary> <para> -The abbreviated name of the license under which -this project is released (gpl, lpgl, bsd etc.). +The abbreviated name, preferably the SPDX code, of the license under which +this project is released (GPL-3.0, LGPL-2.1, BSD-2-Clause etc.). See http://www.opensource.org/licenses/alphabetical -for a list of license names. +for a list of license names and SPDX codes. </para> </summary> </cvar> @@ -383,6 +386,7 @@ This is used to fill in the <literal>BuildRequires:</literal> field in the RPM <filename>.spec</filename> file. +Note this should only be used on a host managed by rpm as the dependencies will not be resolvable at build time otherwise. </para> </summary> </cvar> @@ -441,7 +445,8 @@ field in the RPM <para> This is used to fill in the <literal>Epoch:</literal> -field in the controlling information for RPM packages. +field in the RPM +<filename>.spec</filename> file. </para> </summary> </cvar> @@ -468,6 +473,38 @@ field in the RPM </summary> </cvar> +<cvar name="X_RPM_EXTRADEFS"> +<summary> +<para> +A list used to supply extra defintions or flags +to be added to the RPM <filename>.spec</filename> file. +Each item is added as-is with a carriage return appended. +This is useful if some specific RPM feature not otherwise +anticipated by SCons needs to be turned on or off. +Note if this variable is omitted, SCons will by +default supply the value +<literal>'%global debug_package %{nil}'</literal> +to disable debug package generation. +To enable debug package generation, include this +variable set either to None, or to a custom +list that does not include the default line. +Added in version 3.1. +</para> + +<example_commands> +env.Package( + NAME = 'foo', +... + X_RPM_EXTRADEFS = [ + '%define _unpackaged_files_terminate_build 0' + '%define _missing_doc_files_terminate_build 0' + ], +... ) +</example_commands> + +</summary> +</cvar> + <cvar name="X_RPM_GROUP"> <summary> <para> diff --git a/src/engine/SCons/Tool/packaging/ipk.py b/src/engine/SCons/Tool/packaging/ipk.py index 71fa2b0..dbf5be8 100644 --- a/src/engine/SCons/Tool/packaging/ipk.py +++ b/src/engine/SCons/Tool/packaging/ipk.py @@ -2,8 +2,8 @@ """ # -# Copyright (c) 2001 - 2017 The SCons Foundation -# +# Copyright (c) 2001 - 2019 The SCons Foundation +# # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including @@ -24,11 +24,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/ipk.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/ipk.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" + +import os import SCons.Builder import SCons.Node.FS -import os +import SCons.Util from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot @@ -115,15 +117,17 @@ def build_specfiles(source, target, env): # # opened_files={} - def open_file(needle, haystack): + def open_file(needle, haystack=None): try: return opened_files[needle] except KeyError: - file=filter(lambda x: x.get_path().rfind(needle)!=-1, haystack)[0] - opened_files[needle]=open(file.get_abspath(), 'w') + files = filter(lambda x: x.get_path().rfind(needle) != -1, haystack) + # Py3: filter returns an iterable, not a list + file = list(files)[0] + opened_files[needle] = open(file.get_abspath(), 'w') return opened_files[needle] - control_file=open_file('control', target) + control_file = open_file('control', target) if 'X_IPK_DESCRIPTION' not in env: env['X_IPK_DESCRIPTION']="%s\n %s"%(env['SUMMARY'], @@ -145,7 +149,7 @@ Description: $X_IPK_DESCRIPTION control_file.write(env.subst(content)) # - # now handle the various other files, which purpose it is to set post-, + # now handle the various other files, which purpose it is to set post-, # pre-scripts and mark files as config files. # # We do so by filtering the source files for files which are marked with @@ -157,14 +161,14 @@ Description: $X_IPK_DESCRIPTION # into the same named file. # for f in [x for x in source if 'PACKAGING_CONFIG' in dir(x)]: - config=open_file('conffiles') + config = open_file('conffiles') config.write(f.PACKAGING_INSTALL_LOCATION) config.write('\n') for str in 'POSTRM PRERM POSTINST PREINST'.split(): name="PACKAGING_X_IPK_%s"%str for f in [x for x in source if name in dir(x)]: - file=open_file(name) + file = open_file(name) file.write(env[str]) # diff --git a/src/engine/SCons/Tool/packaging/msi.py b/src/engine/SCons/Tool/packaging/msi.py index 827ce76..4a48b47 100644 --- a/src/engine/SCons/Tool/packaging/msi.py +++ b/src/engine/SCons/Tool/packaging/msi.py @@ -4,7 +4,7 @@ The msi packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,7 +25,7 @@ The msi packager. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/packaging/msi.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/msi.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import SCons @@ -63,8 +63,8 @@ def convert_to_id(s, id_set): """ charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyz0123456789_.' if s[0] in '0123456789.': - s += '_'+s - id = [c for c in s if c in charset] + s = '_' + s + id = ''.join([c for c in s if c in charset]) # did we already generate an id for this file? try: @@ -108,14 +108,13 @@ def gen_dos_short_file_name(file, filename_set): # strip forbidden characters. forbidden = '."/[]:;=, ' - fname = [c for c in fname if c not in forbidden] + fname = ''.join([c for c in fname if c not in forbidden]) # check if we already generated a filename with the same number: # thisis1.txt, thisis2.txt etc. duplicate, num = not None, 1 while duplicate: - shortname = "%s%s" % (fname[:8-len(str(num))].upper(),\ - str(num)) + shortname = "%s%s" % (fname[:8-len(str(num))].upper(), str(num)) if len(ext) >= 2: shortname = "%s%s" % (shortname, ext[:4].upper()) @@ -189,7 +188,7 @@ def build_wxsfile(target, source, env): """ Compiles a .wxs file from the keywords given in env['msi_spec'] and by analyzing the tree of source nodes and their tags. """ - file = open(target[0].get_abspath(), 'w') + f = open(target[0].get_abspath(), 'w') try: # Create a document with the Wix root tag @@ -210,7 +209,7 @@ def build_wxsfile(target, source, env): build_license_file(target[0].get_dir(), env) # write the xml to a file - file.write( doc.toprettyxml() ) + f.write( doc.toprettyxml() ) # call a user specified function if 'CHANGE_SPECFILE' in env: @@ -218,6 +217,8 @@ def build_wxsfile(target, source, env): except KeyError as e: raise SCons.Errors.UserError( '"%s" package field for MSI is missing.' % e.args[0] ) + finally: + f.close() # # setup function @@ -301,7 +302,7 @@ def build_wxsfile_file_section(root, files, NAME, VERSION, VENDOR, filename_set, if c.nodeName == 'Directory' and c.attributes['LongName'].value == escape(d)] - if already_created != []: + if already_created: Directory = already_created[0] dir_parts.remove(d) upper_dir += d @@ -441,14 +442,13 @@ def build_license_file(directory, spec): pass # ignore this as X_MSI_LICENSE_TEXT is optional if name!='' or text!='': - file = open( os.path.join(directory.get_path(), 'License.rtf'), 'w' ) - file.write('{\\rtf') - if text!='': - file.write(text.replace('\n', '\\par ')) - else: - file.write(name+'\\par\\par') - file.write('}') - file.close() + with open(os.path.join(directory.get_path(), 'License.rtf'), 'w') as f: + f.write('{\\rtf') + if text!='': + f.write(text.replace('\n', '\\par ')) + else: + f.write(name+'\\par\\par') + f.write('}') # # mandatory and optional package tags diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py index 3c48b02..a948e29 100644 --- a/src/engine/SCons/Tool/packaging/rpm.py +++ b/src/engine/SCons/Tool/packaging/rpm.py @@ -4,7 +4,7 @@ The rpm packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,7 +25,7 @@ The rpm packager. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/packaging/rpm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/rpm.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os @@ -51,10 +51,9 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, if str(target[0])!="%s-%s"%(NAME, VERSION): raise UserError( "Setting target is not supported for rpm." ) else: - # This should be overridable from the construction environment, - # which it is by using ARCHITECTURE=. + # Deduce the build architecture, but allow it to be overridden + # by setting ARCHITECTURE in the construction env. buildarchitecture = SCons.Tool.rpmutils.defaultMachine() - if 'ARCHITECTURE' in kw: buildarchitecture = kw['ARCHITECTURE'] @@ -126,20 +125,18 @@ def build_specfile(target, source, env): """ Builds a RPM specfile from a dictionary with string metadata and by analyzing a tree of nodes. """ - file = open(target[0].get_abspath(), 'w') - - try: - file.write( build_specfile_header(env) ) - file.write( build_specfile_sections(env) ) - file.write( build_specfile_filesection(env, source) ) - file.close() + with open(target[0].get_abspath(), 'w') as ofp: + try: + ofp.write(build_specfile_header(env)) + ofp.write(build_specfile_sections(env)) + ofp.write(build_specfile_filesection(env, source)) - # call a user specified function - if 'CHANGE_SPECFILE' in env: - env['CHANGE_SPECFILE'](target, source) + # call a user specified function + if 'CHANGE_SPECFILE' in env: + env['CHANGE_SPECFILE'](target, source) - except KeyError as e: - raise SCons.Errors.UserError( '"%s" package field for RPM is missing.' % e.args[0] ) + except KeyError as e: + raise SCons.Errors.UserError('"%s" package field for RPM is missing.' % e.args[0]) # @@ -201,7 +198,8 @@ def build_specfile_header(spec): 'PACKAGEVERSION' : '%%define release %s\nRelease: %%{release}\n', 'X_RPM_GROUP' : 'Group: %s\n', 'SUMMARY' : 'Summary: %s\n', - 'LICENSE' : 'License: %s\n', } + 'LICENSE' : 'License: %s\n', + } str = str + SimpleTagCompiler(mandatory_header_fields).compile( spec ) @@ -211,6 +209,7 @@ def build_specfile_header(spec): 'X_RPM_URL' : 'Url: %s\n', 'SOURCE_URL' : 'Source: %s\n', 'SUMMARY_' : 'Summary(%s): %s\n', + 'ARCHITECTURE' : 'BuildArch: %s\n', 'X_RPM_DISTRIBUTION' : 'Distribution: %s\n', 'X_RPM_ICON' : 'Icon: %s\n', 'X_RPM_PACKAGER' : 'Packager: %s\n', @@ -229,19 +228,33 @@ def build_specfile_header(spec): 'X_RPM_PREFIX' : 'Prefix: %s\n', # internal use - 'X_RPM_BUILDROOT' : 'BuildRoot: %s\n', } + 'X_RPM_BUILDROOT' : 'BuildRoot: %s\n', + } # fill in default values: - # Adding a BuildRequires renders the .rpm unbuildable under System, which + # Adding a BuildRequires renders the .rpm unbuildable under systems which # are not managed by rpm, since the database to resolve this dependency is # missing (take Gentoo as an example) -# if not s.has_key('x_rpm_BuildRequires'): -# s['x_rpm_BuildRequires'] = 'scons' + #if 'X_RPM_BUILDREQUIRES' not in spec: + # spec['X_RPM_BUILDREQUIRES'] = 'scons' if 'X_RPM_BUILDROOT' not in spec: spec['X_RPM_BUILDROOT'] = '%{_tmppath}/%{name}-%{version}-%{release}' str = str + SimpleTagCompiler(optional_header_fields, mandatory=0).compile( spec ) + + # Add any extra specfile definitions the user may have supplied. + # These flags get no processing, they are just added. + # github #3164: if we don't turn off debug package generation + # the tests which build packages all fail. If there are no + # extra flags, default to adding this one. If the user wants + # to turn this back on, supply the flag set to None. + + if 'X_RPM_EXTRADEFS' not in spec: + spec['X_RPM_EXTRADEFS'] = ['%global debug_package %{nil}'] + for extra in spec['X_RPM_EXTRADEFS']: + str += extra + '\n' + return str # diff --git a/src/engine/SCons/Tool/packaging/src_tarbz2.py b/src/engine/SCons/Tool/packaging/src_tarbz2.py index b40e550..b628ccd 100644 --- a/src/engine/SCons/Tool/packaging/src_tarbz2.py +++ b/src/engine/SCons/Tool/packaging/src_tarbz2.py @@ -1,10 +1,10 @@ -"""SCons.Tool.Packaging.tarbz2 +"""SCons.Tool.Packaging.src_tarbz2 The tarbz2 SRC packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The tarbz2 SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/src_tarbz2.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/src_tarbz2.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from SCons.Tool.packaging import putintopackageroot diff --git a/src/engine/SCons/Tool/packaging/src_targz.py b/src/engine/SCons/Tool/packaging/src_targz.py index 01fc91a..4c7469c 100644 --- a/src/engine/SCons/Tool/packaging/src_targz.py +++ b/src/engine/SCons/Tool/packaging/src_targz.py @@ -1,10 +1,10 @@ -"""SCons.Tool.Packaging.targz +"""SCons.Tool.Packaging.src_targz The targz SRC packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The targz SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/src_targz.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/src_targz.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from SCons.Tool.packaging import putintopackageroot diff --git a/src/engine/SCons/Tool/packaging/src_tarxz.py b/src/engine/SCons/Tool/packaging/src_tarxz.py new file mode 100644 index 0000000..6688c46 --- /dev/null +++ b/src/engine/SCons/Tool/packaging/src_tarxz.py @@ -0,0 +1,43 @@ +"""SCons.Tool.Packaging.src_tarxz + +The tarxz SRC packager. +""" + +# +# Copyright (c) 2001 - 2019 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "src/engine/SCons/Tool/packaging/src_tarxz.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" + +from SCons.Tool.packaging import putintopackageroot + +def package(env, target, source, PACKAGEROOT, **kw): + bld = env['BUILDERS']['Tar'] + bld.set_suffix('.tar.xz') + target, source = putintopackageroot(target, source, env, PACKAGEROOT, honor_install_location=0) + return bld(env, target, source, TARFLAGS='-Jc') + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/packaging/src_zip.py b/src/engine/SCons/Tool/packaging/src_zip.py index ea21a87..d56f3aa 100644 --- a/src/engine/SCons/Tool/packaging/src_zip.py +++ b/src/engine/SCons/Tool/packaging/src_zip.py @@ -4,7 +4,7 @@ The zip SRC packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The zip SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/src_zip.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/src_zip.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from SCons.Tool.packaging import putintopackageroot diff --git a/src/engine/SCons/Tool/packaging/tarbz2.py b/src/engine/SCons/Tool/packaging/tarbz2.py index c919cab..e371f1b 100644 --- a/src/engine/SCons/Tool/packaging/tarbz2.py +++ b/src/engine/SCons/Tool/packaging/tarbz2.py @@ -1,10 +1,10 @@ """SCons.Tool.Packaging.tarbz2 -The tarbz2 SRC packager. +The tarbz2 packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,13 +26,13 @@ The tarbz2 SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/tarbz2.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/tarbz2.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot def package(env, target, source, PACKAGEROOT, **kw): bld = env['BUILDERS']['Tar'] - bld.set_suffix('.tar.gz') + bld.set_suffix('.tar.bz2') target, source = putintopackageroot(target, source, env, PACKAGEROOT) target, source = stripinstallbuilder(target, source, env) return bld(env, target, source, TARFLAGS='-jc') diff --git a/src/engine/SCons/Tool/packaging/targz.py b/src/engine/SCons/Tool/packaging/targz.py index e9e984e..121e4a4 100644 --- a/src/engine/SCons/Tool/packaging/targz.py +++ b/src/engine/SCons/Tool/packaging/targz.py @@ -1,10 +1,10 @@ """SCons.Tool.Packaging.targz -The targz SRC packager. +The targz packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The targz SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/targz.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/targz.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot diff --git a/src/engine/SCons/Tool/packaging/tarxz.py b/src/engine/SCons/Tool/packaging/tarxz.py new file mode 100644 index 0000000..3ec9822 --- /dev/null +++ b/src/engine/SCons/Tool/packaging/tarxz.py @@ -0,0 +1,44 @@ +"""SCons.Tool.Packaging.tarxz + +The tarxz packager. +""" + +# +# Copyright (c) 2001 - 2019 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "src/engine/SCons/Tool/packaging/tarxz.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" + +from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot + +def package(env, target, source, PACKAGEROOT, **kw): + bld = env['BUILDERS']['Tar'] + bld.set_suffix('.tar.xz') + target, source = putintopackageroot(target, source, env, PACKAGEROOT) + target, source = stripinstallbuilder(target, source, env) + return bld(env, target, source, TARFLAGS='-Jc') + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/packaging/zip.py b/src/engine/SCons/Tool/packaging/zip.py index 3b80ead..11ab3b5 100644 --- a/src/engine/SCons/Tool/packaging/zip.py +++ b/src/engine/SCons/Tool/packaging/zip.py @@ -4,7 +4,7 @@ The zip SRC packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The zip SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/zip.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/zip.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot diff --git a/src/engine/SCons/Tool/pdf.py b/src/engine/SCons/Tool/pdf.py index 381732a..50988b6 100644 --- a/src/engine/SCons/Tool/pdf.py +++ b/src/engine/SCons/Tool/pdf.py @@ -6,7 +6,7 @@ Add an explicit action to run epstopdf to convert .eps files to .pdf """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Add an explicit action to run epstopdf to convert .eps files to .pdf # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/pdf.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/pdf.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Builder import SCons.Tool diff --git a/src/engine/SCons/Tool/pdf.xml b/src/engine/SCons/Tool/pdf.xml index 9688a6f..876de15 100644 --- a/src/engine/SCons/Tool/pdf.xml +++ b/src/engine/SCons/Tool/pdf.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/pdflatex.py b/src/engine/SCons/Tool/pdflatex.py index d539770..2c559f7 100644 --- a/src/engine/SCons/Tool/pdflatex.py +++ b/src/engine/SCons/Tool/pdflatex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/pdflatex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/pdflatex.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Action import SCons.Util diff --git a/src/engine/SCons/Tool/pdflatex.xml b/src/engine/SCons/Tool/pdflatex.xml index 4dae90b..975d5e9 100644 --- a/src/engine/SCons/Tool/pdflatex.xml +++ b/src/engine/SCons/Tool/pdflatex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/pdftex.py b/src/engine/SCons/Tool/pdftex.py index 06e9d7c..c658aa0 100644 --- a/src/engine/SCons/Tool/pdftex.py +++ b/src/engine/SCons/Tool/pdftex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/pdftex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/pdftex.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import SCons.Action diff --git a/src/engine/SCons/Tool/pdftex.xml b/src/engine/SCons/Tool/pdftex.xml index e84296a..0a265e7 100644 --- a/src/engine/SCons/Tool/pdftex.xml +++ b/src/engine/SCons/Tool/pdftex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py index e7c1b95..a582e6f 100644 --- a/src/engine/SCons/Tool/qt.py +++ b/src/engine/SCons/Tool/qt.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,10 +33,11 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/qt.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/qt.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path import re +import glob import SCons.Action import SCons.Builder @@ -44,6 +45,8 @@ import SCons.Defaults import SCons.Scanner import SCons.Tool import SCons.Util +import SCons.Tool.cxx +cplusplus = SCons.Tool.cxx class ToolQtWarning(SCons.Warnings.Warning): pass @@ -60,12 +63,40 @@ header_extensions = [".h", ".hxx", ".hpp", ".hh"] if SCons.Util.case_sensitive_suffixes('.h', '.H'): header_extensions.append('.H') -import SCons.Tool.cxx -cplusplus = SCons.Tool.cxx -#cplusplus = __import__('cxx', globals(), locals(), []) - cxx_suffixes = cplusplus.CXXSuffixes + +def find_platform_specific_qt_paths(): + """ + find non-standard QT paths + + If the platform does not put QT tools in standard search paths, + the path is expected to be set using QTDIR. SCons violates + the normal rule of not pulling from the user's environment + in this case. However, some test cases try to validate what + happens when QTDIR is unset, so we need to try to make a guess. + + :return: a guess at a path + """ + + # qt_bin_dirs = [] + qt_bin_dir = None + if os.path.isfile('/etc/redhat-release'): + with open('/etc/redhat-release','r') as rr: + lines = rr.readlines() + distro = lines[0].split()[0] + if distro == 'CentOS': + # Centos installs QT under /usr/{lib,lib64}/qt{4,5,-3.3}/bin + # so we need to handle this differently + # qt_bin_dirs = glob.glob('/usr/lib64/qt*/bin') + # TODO: all current Fedoras do the same, need to look deeper here. + qt_bin_dir = '/usr/lib64/qt-3.3/bin' + + return qt_bin_dir + + +QT_BIN_DIR = find_platform_specific_qt_paths() + def checkMocIncluded(target, source, env): moc = target[0] cpp = source[0] @@ -73,7 +104,7 @@ def checkMocIncluded(target, source, env): # not really sure about the path transformations (moc.cwd? cpp.cwd?) :-/ path = SCons.Defaults.CScan.path(env, moc.cwd) includes = SCons.Defaults.CScan(cpp, env, path) - if not moc in includes: + if moc not in includes: SCons.Warnings.warn( GeneratedMocFileNotIncluded, "Generated moc file '%s' is not included by '%s'" % @@ -94,7 +125,7 @@ class _Automoc(object): def __init__(self, objBuilderName): self.objBuilderName = objBuilderName - + def __call__(self, target, source, env): """ Smart autoscan function. Gets the list of objects for the Program @@ -109,25 +140,25 @@ class _Automoc(object): debug = int(env.subst('$QT_DEBUG')) except ValueError: debug = 0 - + # some shortcuts used in the scanner splitext = SCons.Util.splitext objBuilder = getattr(env, self.objBuilderName) - + # some regular expressions: # Q_OBJECT detection - q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]') + q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]') # cxx and c comment 'eater' #comment = re.compile(r'(//.*)|(/\*(([^*])|(\*[^/]))*\*/)') # CW: something must be wrong with the regexp. See also bug #998222 # CURRENTLY THERE IS NO TEST CASE FOR THAT - + # The following is kind of hacky to get builders working properly (FIXME) objBuilderEnv = objBuilder.env objBuilder.env = env mocBuilderEnv = env.Moc.env env.Moc.env = env - + # make a deep copy for the result; MocH objects will be appended out_sources = source[:] @@ -140,7 +171,7 @@ class _Automoc(object): cpp = obj.sources[0] if not splitext(str(cpp))[1] in cxx_suffixes: if debug: - print("scons: qt: '%s' is no cxx file. Discarded." % str(cpp)) + print("scons: qt: '%s' is no cxx file. Discarded." % str(cpp)) # c or fortran source continue #cpp_contents = comment.sub('', cpp.get_text_contents()) @@ -188,13 +219,12 @@ AutomocStatic = _Automoc('StaticObject') def _detect(env): """Not really safe, but fast method to detect the QT library""" - QTDIR = None - if not QTDIR: - QTDIR = env.get('QTDIR',None) + + QTDIR = env.get('QTDIR',None) if not QTDIR: QTDIR = os.environ.get('QTDIR',None) if not QTDIR: - moc = env.WhereIs('moc') + moc = env.WhereIs('moc') or env.WhereIs('moc',QT_BIN_DIR) if moc: QTDIR = os.path.dirname(os.path.dirname(moc)) SCons.Warnings.warn( @@ -237,7 +267,7 @@ def uicScannerFunc(node, env, path): return result uicScanner = SCons.Scanner.Base(uicScannerFunc, - name = "UicScanner", + name = "UicScanner", node_class = SCons.Node.FS.File, node_factory = SCons.Node.FS.File, recursive = 0) @@ -313,7 +343,7 @@ def generate(env): mocBld.prefix[cxx] = '$QT_MOCCXXPREFIX' mocBld.suffix[cxx] = '$QT_MOCCXXSUFFIX' - # register the builders + # register the builders env['BUILDERS']['Uic'] = uicBld env['BUILDERS']['Moc'] = mocBld static_obj, shared_obj = SCons.Tool.createObjBuilders(env) diff --git a/src/engine/SCons/Tool/qt.xml b/src/engine/SCons/Tool/qt.xml index 86d50d6..560a11d 100644 --- a/src/engine/SCons/Tool/qt.xml +++ b/src/engine/SCons/Tool/qt.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/rmic.py b/src/engine/SCons/Tool/rmic.py index 9e1eaee..d6f7b2b 100644 --- a/src/engine/SCons/Tool/rmic.py +++ b/src/engine/SCons/Tool/rmic.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/rmic.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rmic.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path @@ -40,6 +40,9 @@ import SCons.Builder import SCons.Node.FS import SCons.Util +from SCons.Tool.JavaCommon import get_java_install_dirs + + def emit_rmic_classes(target, source, env): """Create and return lists of Java RMI stub and skeleton class files to be created from a set of class files. @@ -105,6 +108,16 @@ def generate(env): """Add Builders and construction variables for rmic to an Environment.""" env['BUILDERS']['RMIC'] = RMICBuilder + if env['PLATFORM'] == 'win32': + version = env.get('JAVAVERSION', None) + # Ensure that we have a proper path for rmic + paths = get_java_install_dirs('win32', version=version) + rmic = SCons.Tool.find_program_path(env, 'rmic', default_paths=paths) + # print("RMIC: %s"%rmic) + if rmic: + rmic_bin_dir = os.path.dirname(rmic) + env.AppendENVPath('PATH', rmic_bin_dir) + env['RMIC'] = 'rmic' env['RMICFLAGS'] = SCons.Util.CLVar('') env['RMICCOM'] = '$RMIC $RMICFLAGS -d ${TARGET.attributes.java_lookupdir} -classpath ${SOURCE.attributes.java_classdir} ${SOURCES.attributes.java_classname}' diff --git a/src/engine/SCons/Tool/rmic.xml b/src/engine/SCons/Tool/rmic.xml index 2b0d42b..2a273d3 100644 --- a/src/engine/SCons/Tool/rmic.xml +++ b/src/engine/SCons/Tool/rmic.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/rpcgen.py b/src/engine/SCons/Tool/rpcgen.py index 1f2c66d..b9f8ca6 100644 --- a/src/engine/SCons/Tool/rpcgen.py +++ b/src/engine/SCons/Tool/rpcgen.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/rpcgen.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rpcgen.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from SCons.Builder import Builder import SCons.Util @@ -43,7 +43,7 @@ rpcgen_service = cmd % ('m', '$RPCGENSERVICEFLAGS') rpcgen_xdr = cmd % ('c', '$RPCGENXDRFLAGS') def generate(env): - "Add RPCGEN Builders and construction variables for an Environment." + """Add RPCGEN Builders and construction variables for an Environment.""" client = Builder(action=rpcgen_client, suffix='_clnt.c', src_suffix='.x') header = Builder(action=rpcgen_header, suffix='.h', src_suffix='.x') diff --git a/src/engine/SCons/Tool/rpcgen.xml b/src/engine/SCons/Tool/rpcgen.xml index 60f216e..1ee9df9 100644 --- a/src/engine/SCons/Tool/rpcgen.xml +++ b/src/engine/SCons/Tool/rpcgen.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/rpm.py b/src/engine/SCons/Tool/rpm.py index 5cd97b3..0253365 100644 --- a/src/engine/SCons/Tool/rpm.py +++ b/src/engine/SCons/Tool/rpm.py @@ -11,7 +11,7 @@ tar.gz consisting of the source file and a specfile. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ tar.gz consisting of the source file and a specfile. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/rpm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rpm.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import re @@ -51,43 +51,44 @@ def get_cmd(source, env): if SCons.Util.is_List(source): tar_file_with_included_specfile = source[0] return "%s %s %s"%(env['RPM'], env['RPMFLAGS'], - tar_file_with_included_specfile.get_abspath() ) + tar_file_with_included_specfile.get_abspath()) def build_rpm(target, source, env): # create a temporary rpm build root. - tmpdir = os.path.join( os.path.dirname( target[0].get_abspath() ), 'rpmtemp' ) + tmpdir = os.path.join(os.path.dirname(target[0].get_abspath()), 'rpmtemp') if os.path.exists(tmpdir): shutil.rmtree(tmpdir) # now create the mandatory rpm directory structure. for d in ['RPMS', 'SRPMS', 'SPECS', 'BUILD']: - os.makedirs( os.path.join( tmpdir, d ) ) + os.makedirs(os.path.join(tmpdir, d)) # set the topdir as an rpmflag. - env.Prepend( RPMFLAGS = '--define \'_topdir %s\'' % tmpdir ) + env.Prepend(RPMFLAGS = '--define \'_topdir %s\'' % tmpdir) # now call rpmbuild to create the rpm package. handle = subprocess.Popen(get_cmd(source, env), stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True) - output = SCons.Util.to_str(handle.stdout.read()) + with handle.stdout: + output = SCons.Util.to_str(handle.stdout.read()) status = handle.wait() if status: - raise SCons.Errors.BuildError( node=target[0], - errstr=output, - filename=str(target[0]) ) + raise SCons.Errors.BuildError(node=target[0], + errstr=output, + filename=str(target[0])) else: # XXX: assume that LC_ALL=C is set while running rpmbuild - output_files = re.compile( 'Wrote: (.*)' ).findall( output ) + output_files = re.compile('Wrote: (.*)').findall(output) - for output, input in zip( output_files, target ): + for output, input in zip(output_files, target): rpm_output = os.path.basename(output) expected = os.path.basename(input.get_path()) assert expected == rpm_output, "got %s but expected %s" % (rpm_output, expected) - shutil.copy( output, input.get_abspath() ) + shutil.copy(output, input.get_abspath()) # cleanup before leaving. diff --git a/src/engine/SCons/Tool/rpmutils.py b/src/engine/SCons/Tool/rpmutils.py index f71d664..a2400ff 100644 --- a/src/engine/SCons/Tool/rpmutils.py +++ b/src/engine/SCons/Tool/rpmutils.py @@ -14,7 +14,7 @@ exact syntax. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -36,7 +36,7 @@ exact syntax. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/rpmutils.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rpmutils.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import platform @@ -482,9 +482,11 @@ def updateRpmDicts(rpmrc, pyfile): """ try: # Read old rpmutils.py file - oldpy = open(pyfile,"r").readlines() + with open(pyfile,"r") as f: + oldpy = f.readlines() # Read current rpmrc.in file - rpm = open(rpmrc,"r").readlines() + with open(rpmrc,"r") as f: + rpm = f.readlines() # Parse for data data = {} # Allowed section names that get parsed @@ -511,24 +513,23 @@ def updateRpmDicts(rpmrc, pyfile): # Insert data data[key][tokens[1]] = tokens[2:] # Write new rpmutils.py file - out = open(pyfile,"w") - pm = 0 - for l in oldpy: - if pm: - if l.startswith('# End of rpmrc dictionaries'): - pm = 0 + with open(pyfile,"w") as out: + pm = 0 + for l in oldpy: + if pm: + if l.startswith('# End of rpmrc dictionaries'): + pm = 0 + out.write(l) + else: out.write(l) - else: - out.write(l) - if l.startswith('# Start of rpmrc dictionaries'): - pm = 1 - # Write data sections to single dictionaries - for key, entries in data.items(): - out.write("%s = {\n" % key) - for arch in sorted(entries.keys()): - out.write(" '%s' : ['%s'],\n" % (arch, "','".join(entries[arch]))) - out.write("}\n\n") - out.close() + if l.startswith('# Start of rpmrc dictionaries'): + pm = 1 + # Write data sections to single dictionaries + for key, entries in data.items(): + out.write("%s = {\n" % key) + for arch in sorted(entries.keys()): + out.write(" '%s' : ['%s'],\n" % (arch, "','".join(entries[arch]))) + out.write("}\n\n") except: pass diff --git a/src/engine/SCons/Tool/sgiar.py b/src/engine/SCons/Tool/sgiar.py index a421cc1..d82ec89 100644 --- a/src/engine/SCons/Tool/sgiar.py +++ b/src/engine/SCons/Tool/sgiar.py @@ -11,7 +11,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgiar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgiar.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/sgiar.xml b/src/engine/SCons/Tool/sgiar.xml index ffbc80e..6d28475 100644 --- a/src/engine/SCons/Tool/sgiar.xml +++ b/src/engine/SCons/Tool/sgiar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sgic++.py b/src/engine/SCons/Tool/sgic++.py index 7a9b1e9..84d775a 100644 --- a/src/engine/SCons/Tool/sgic++.py +++ b/src/engine/SCons/Tool/sgic++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgic++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgic++.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" #forward proxy to the preffered cxx version from SCons.Tool.sgicxx import * diff --git a/src/engine/SCons/Tool/sgic++.xml b/src/engine/SCons/Tool/sgic++.xml index 03ca3b1..bab0392 100644 --- a/src/engine/SCons/Tool/sgic++.xml +++ b/src/engine/SCons/Tool/sgic++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sgicc.py b/src/engine/SCons/Tool/sgicc.py index e9f561d..537f1a3 100644 --- a/src/engine/SCons/Tool/sgicc.py +++ b/src/engine/SCons/Tool/sgicc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgicc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgicc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" from . import cc diff --git a/src/engine/SCons/Tool/sgicc.xml b/src/engine/SCons/Tool/sgicc.xml index 1e12bf3..f26944b 100644 --- a/src/engine/SCons/Tool/sgicc.xml +++ b/src/engine/SCons/Tool/sgicc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sgicxx.py b/src/engine/SCons/Tool/sgicxx.py index 61c415b..d44ec26 100644 --- a/src/engine/SCons/Tool/sgicxx.py +++ b/src/engine/SCons/Tool/sgicxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgicxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgicxx.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util diff --git a/src/engine/SCons/Tool/sgilink.py b/src/engine/SCons/Tool/sgilink.py index c327151..ca9e69c 100644 --- a/src/engine/SCons/Tool/sgilink.py +++ b/src/engine/SCons/Tool/sgilink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgilink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgilink.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util diff --git a/src/engine/SCons/Tool/sgilink.xml b/src/engine/SCons/Tool/sgilink.xml index ede0eed..7cc9818 100644 --- a/src/engine/SCons/Tool/sgilink.xml +++ b/src/engine/SCons/Tool/sgilink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunar.py b/src/engine/SCons/Tool/sunar.py index cd1e18d..07d45b2 100644 --- a/src/engine/SCons/Tool/sunar.py +++ b/src/engine/SCons/Tool/sunar.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunar.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/sunar.xml b/src/engine/SCons/Tool/sunar.xml index b97e6a2..97d1a05 100644 --- a/src/engine/SCons/Tool/sunar.xml +++ b/src/engine/SCons/Tool/sunar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunc++.py b/src/engine/SCons/Tool/sunc++.py index 1219bcf..1611fe9 100644 --- a/src/engine/SCons/Tool/sunc++.py +++ b/src/engine/SCons/Tool/sunc++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunc++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunc++.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" #forward proxy to the preffered cxx version diff --git a/src/engine/SCons/Tool/sunc++.xml b/src/engine/SCons/Tool/sunc++.xml index 2e7b220..d1d0160 100644 --- a/src/engine/SCons/Tool/sunc++.xml +++ b/src/engine/SCons/Tool/sunc++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/suncc.py b/src/engine/SCons/Tool/suncc.py index bc4eb4f..da6ca6e 100644 --- a/src/engine/SCons/Tool/suncc.py +++ b/src/engine/SCons/Tool/suncc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/suncc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/suncc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util diff --git a/src/engine/SCons/Tool/suncc.xml b/src/engine/SCons/Tool/suncc.xml index 61cfb30..f191eda 100644 --- a/src/engine/SCons/Tool/suncc.xml +++ b/src/engine/SCons/Tool/suncc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/suncxx.py b/src/engine/SCons/Tool/suncxx.py index 1545500..1ee1c6a 100644 --- a/src/engine/SCons/Tool/suncxx.py +++ b/src/engine/SCons/Tool/suncxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/suncxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/suncxx.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons @@ -52,11 +52,17 @@ def get_package_info(package_name, pkginfo, pkgchk): version = None pathname = None try: - sadm_contents = open('/var/sadm/install/contents', 'r').read() + from subprocess import DEVNULL # py3k + except ImportError: + DEVNULL = open(os.devnull, 'wb') + + try: + with open('/var/sadm/install/contents', 'r') as f: + sadm_contents = f.read() except EnvironmentError: pass else: - sadm_re = re.compile('^(\S*/bin/CC)(=\S*)? %s$' % package_name, re.M) + sadm_re = re.compile(r'^(\S*/bin/CC)(=\S*)? %s$' % package_name, re.M) sadm_match = sadm_re.search(sadm_contents) if sadm_match: pathname = os.path.dirname(sadm_match.group(1)) @@ -64,12 +70,12 @@ def get_package_info(package_name, pkginfo, pkgchk): try: p = subprocess.Popen([pkginfo, '-l', package_name], stdout=subprocess.PIPE, - stderr=open('/dev/null', 'w')) + stderr=DEVNULL) except EnvironmentError: pass else: pkginfo_contents = p.communicate()[0] - version_re = re.compile('^ *VERSION:\s*(.*)$', re.M) + version_re = re.compile(r'^ *VERSION:\s*(.*)$', re.M) version_match = version_re.search(pkginfo_contents) if version_match: version = version_match.group(1) @@ -78,7 +84,7 @@ def get_package_info(package_name, pkginfo, pkgchk): try: p = subprocess.Popen([pkgchk, '-l', package_name], stdout=subprocess.PIPE, - stderr=open('/dev/null', 'w')) + stderr=DEVNULL) except EnvironmentError: pass else: diff --git a/src/engine/SCons/Tool/sunf77.py b/src/engine/SCons/Tool/sunf77.py index 9842d31..c1c216f 100644 --- a/src/engine/SCons/Tool/sunf77.py +++ b/src/engine/SCons/Tool/sunf77.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunf77.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunf77.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util diff --git a/src/engine/SCons/Tool/sunf77.xml b/src/engine/SCons/Tool/sunf77.xml index 8f6ecaf..fafcb8d 100644 --- a/src/engine/SCons/Tool/sunf77.xml +++ b/src/engine/SCons/Tool/sunf77.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunf90.py b/src/engine/SCons/Tool/sunf90.py index 7245f99..4cabee8 100644 --- a/src/engine/SCons/Tool/sunf90.py +++ b/src/engine/SCons/Tool/sunf90.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunf90.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunf90.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util diff --git a/src/engine/SCons/Tool/sunf90.xml b/src/engine/SCons/Tool/sunf90.xml index 8f151fe..f979e15 100644 --- a/src/engine/SCons/Tool/sunf90.xml +++ b/src/engine/SCons/Tool/sunf90.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunf95.py b/src/engine/SCons/Tool/sunf95.py index aae8828..077b1bc 100644 --- a/src/engine/SCons/Tool/sunf95.py +++ b/src/engine/SCons/Tool/sunf95.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunf95.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunf95.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Util diff --git a/src/engine/SCons/Tool/sunf95.xml b/src/engine/SCons/Tool/sunf95.xml index a2c77da..4072d36 100644 --- a/src/engine/SCons/Tool/sunf95.xml +++ b/src/engine/SCons/Tool/sunf95.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunlink.py b/src/engine/SCons/Tool/sunlink.py index 175157f..8d965fa 100644 --- a/src/engine/SCons/Tool/sunlink.py +++ b/src/engine/SCons/Tool/sunlink.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunlink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunlink.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os import os.path diff --git a/src/engine/SCons/Tool/sunlink.xml b/src/engine/SCons/Tool/sunlink.xml index b652f5c..68eee54 100644 --- a/src/engine/SCons/Tool/sunlink.xml +++ b/src/engine/SCons/Tool/sunlink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index dedf103..2e61b91 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -10,7 +10,7 @@ selection method. from __future__ import print_function # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,9 +32,10 @@ from __future__ import print_function # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/swig.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/swig.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path +import sys import re import subprocess @@ -69,7 +70,9 @@ def _find_modules(src): directors = 0 mnames = [] try: - matches = _reModule.findall(open(src).read()) + with open(src) as f: + data = f.read() + matches = _reModule.findall(data) except IOError: # If the file's not yet generated, guess the module name from the file stem matches = [] @@ -134,21 +137,31 @@ def _swigEmitter(target, source, env): def _get_swig_version(env, swig): """Run the SWIG command line tool to get and return the version number""" + version = None swig = env.subst(swig) + if not swig: + return version pipe = SCons.Action._subproc(env, SCons.Util.CLVar(swig) + ['-version'], stdin = 'devnull', stderr = 'devnull', stdout = subprocess.PIPE) - if pipe.wait() != 0: return + if pipe.wait() != 0: + return version # MAYBE: out = SCons.Util.to_str (pipe.stdout.read()) - out = SCons.Util.to_str(pipe.stdout.read()) - match = re.search('SWIG Version\s+(\S+).*', out, re.MULTILINE) + with pipe.stdout: + out = SCons.Util.to_str(pipe.stdout.read()) + + match = re.search(r'SWIG Version\s+(\S+).*', out, re.MULTILINE) if match: - if verbose: print("Version is:%s"%match.group(1)) - return match.group(1) + version = match.group(1) + if verbose: + print("Version is: %s" % version) else: - if verbose: print("Unable to detect version: [%s]"%out) + if verbose: + print("Unable to detect version: [%s]" % out) + + return version def generate(env): """Add Builders and construction variables for swig to an Environment.""" @@ -169,6 +182,18 @@ def generate(env): java_file.add_action('.i', SwigAction) java_file.add_emitter('.i', _swigEmitter) + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + from SCons.Platform.win32 import CHOCO_DEFAULT_PATH + + if sys.platform == 'win32': + swig = SCons.Tool.find_program_path(env, 'swig', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS + CHOCO_DEFAULT_PATH) + if swig: + swig_bin_dir = os.path.dirname(swig) + env.AppendENVPath('PATH', swig_bin_dir) + else: + SCons.Warnings.Warning('swig tool requested, but binary not found in ENV PATH') + if 'SWIG' not in env: env['SWIG'] = env.Detect(swigs) or swigs[0] env['SWIGVERSION'] = _get_swig_version(env, env['SWIG']) diff --git a/src/engine/SCons/Tool/swig.xml b/src/engine/SCons/Tool/swig.xml index 53d92ef..65a5971 100644 --- a/src/engine/SCons/Tool/swig.xml +++ b/src/engine/SCons/Tool/swig.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -153,7 +153,8 @@ An automatically-generated construction variable containing the SWIG command-line options for specifying directories to be searched for included files. The value of &cv-_SWIGINCFLAGS; is created -by appending &cv-SWIGINCPREFIX; and &cv-SWIGINCSUFFIX; +by respectively prepending and appending +&cv-SWIGINCPREFIX; and &cv-SWIGINCSUFFIX; to the beginning and end of each directory in &cv-SWIGPATH;. </para> @@ -164,7 +165,7 @@ of each directory in &cv-SWIGPATH;. <summary> <para> The prefix used to specify an include directory on the SWIG command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the &cv-SWIGPATH; construction variable when the &cv-_SWIGINCFLAGS; variable is automatically generated. </para> @@ -238,7 +239,7 @@ through the automatically-generated &cv-_SWIGINCFLAGS; construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the &cv-SWIGINCPREFIX; and &cv-SWIGINCSUFFIX; construction variables to the beginning and end diff --git a/src/engine/SCons/Tool/tar.py b/src/engine/SCons/Tool/tar.py index 77392ae..08c80f2 100644 --- a/src/engine/SCons/Tool/tar.py +++ b/src/engine/SCons/Tool/tar.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/tar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/tar.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Action import SCons.Builder diff --git a/src/engine/SCons/Tool/tar.xml b/src/engine/SCons/Tool/tar.xml index 637b7db..95e8418 100644 --- a/src/engine/SCons/Tool/tar.xml +++ b/src/engine/SCons/Tool/tar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index 990c9fa..9beb557 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/tex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/tex.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path import re @@ -74,15 +74,15 @@ openout_bcf_re = re.compile(r"OUTPUT *(.*\.bcf)") #printglossary_re = re.compile(r"^[^%]*\\printglossary", re.MULTILINE) # search to find rerun warnings -warning_rerun_str = '(^LaTeX Warning:.*Rerun)|(^Package \w+ Warning:.*Rerun)' +warning_rerun_str = r'(^LaTeX Warning:.*Rerun)|(^Package \w+ Warning:.*Rerun)' warning_rerun_re = re.compile(warning_rerun_str, re.MULTILINE) # search to find citation rerun warnings -rerun_citations_str = "^LaTeX Warning:.*\n.*Rerun to get citations correct" +rerun_citations_str = r"^LaTeX Warning:.*\n.*Rerun to get citations correct" rerun_citations_re = re.compile(rerun_citations_str, re.MULTILINE) # search to find undefined references or citations warnings -undefined_references_str = '(^LaTeX Warning:.*undefined references)|(^Package \w+ Warning:.*undefined citations)' +undefined_references_str = r'(^LaTeX Warning:.*undefined references)|(^Package \w+ Warning:.*undefined citations)' undefined_references_re = re.compile(undefined_references_str, re.MULTILINE) # used by the emitter @@ -297,7 +297,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None logfilename = targetbase + '.log' logContent = '' if os.path.isfile(logfilename): - logContent = open(logfilename, "r").read() + with open(logfilename, "r") as f: + logContent = f.read() # Read the fls file to find all .aux files @@ -305,7 +306,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None flsContent = '' auxfiles = [] if os.path.isfile(flsfilename): - flsContent = open(flsfilename, "r").read() + with open(flsfilename, "r") as f: + flsContent = f.read() auxfiles = openout_aux_re.findall(flsContent) # remove duplicates dups = {} @@ -315,7 +317,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None bcffiles = [] if os.path.isfile(flsfilename): - flsContent = open(flsfilename, "r").read() + with open(flsfilename, "r") as f: + flsContent = f.read() bcffiles = openout_bcf_re.findall(flsContent) # remove duplicates dups = {} @@ -338,7 +341,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None already_bibtexed.append(auxfilename) target_aux = os.path.join(targetdir, auxfilename) if os.path.isfile(target_aux): - content = open(target_aux, "r").read() + with open(target_aux, "r") as f: + content = f.read() if content.find("bibdata") != -1: if Verbose: print("Need to run bibtex on ",auxfilename) @@ -361,7 +365,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None already_bibtexed.append(bcffilename) target_bcf = os.path.join(targetdir, bcffilename) if os.path.isfile(target_bcf): - content = open(target_bcf, "r").read() + with open(target_bcf, "r") as f: + content = f.read() if content.find("bibdata") != -1: if Verbose: print("Need to run biber on ",bcffilename) @@ -647,7 +652,7 @@ def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi if incResult: aux_files.append(os.path.join(targetdir, incResult.group(1))) if Verbose: - print("\include file names : ", aux_files) + print(r"\include file names : ", aux_files) # recursively call this on each of the included files inc_files = [ ] inc_files.extend( include_re.findall(content) ) @@ -776,7 +781,7 @@ def tex_emitter_core(target, source, env, graphics_extensions): # add side effects if feature is present.If file is to be generated,add all side effects if Verbose and theSearch: print("check side effects for ",suffix_list[-1]) - if (theSearch != None) or (not source[0].exists() ): + if theSearch is not None or not source[0].exists(): file_list = [targetbase,] # for bibunit we need a list of files if suffix_list[-1] == 'bibunit': @@ -790,7 +795,7 @@ def tex_emitter_core(target, source, env, graphics_extensions): for multibibmatch in multibib_re.finditer(content): if Verbose: print("multibib match ",multibibmatch.group(1)) - if multibibmatch != None: + if multibibmatch is not None: baselist = multibibmatch.group(1).split(',') if Verbose: print("multibib list ", baselist) @@ -813,7 +818,8 @@ def tex_emitter_core(target, source, env, graphics_extensions): # read fls file to get all other files that latex creates and will read on the next pass # remove files from list that we explicitly dealt with above if os.path.isfile(flsfilename): - content = open(flsfilename, "r").read() + with open(flsfilename, "r") as f: + content = f.read() out_files = openout_re.findall(content) myfiles = [auxfilename, logfilename, flsfilename, targetbase+'.dvi',targetbase+'.pdf'] for filename in out_files[:]: diff --git a/src/engine/SCons/Tool/tex.xml b/src/engine/SCons/Tool/tex.xml index 87741c0..c293977 100644 --- a/src/engine/SCons/Tool/tex.xml +++ b/src/engine/SCons/Tool/tex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index 7303e06..58a5007 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -1,6 +1,6 @@ # -*- python -*- # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -44,7 +44,7 @@ Textfile/Substfile builder for SCons. is unpredictable whether the expansion will occur. """ -__revision__ = "src/engine/SCons/Tool/textfile.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/textfile.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons diff --git a/src/engine/SCons/Tool/textfile.xml b/src/engine/SCons/Tool/textfile.xml index bca7232..31d2d4f 100644 --- a/src/engine/SCons/Tool/textfile.xml +++ b/src/engine/SCons/Tool/textfile.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -147,7 +147,7 @@ and the result replaces the key. </para> <example_commands> -env = Environment(tools = ['default', 'textfile']) +env = Environment(tools=['default']) env['prefix'] = '/usr/bin' script_dict = {'@prefix@': '/bin', '@exec_prefix@': '$prefix'} @@ -174,7 +174,7 @@ env.Substfile('bar.in', SUBST_DICT = good_bar) # the SUBST_DICT may be in common (and not an override) substutions = {} -subst = Environment(tools = ['textfile'], SUBST_DICT = substitutions) +subst = Environment(tools=['textfile'], SUBST_DICT=substitutions) substitutions['@foo@'] = 'foo' subst['SUBST_DICT']['@bar@'] = 'bar' subst.Substfile('pgm1.c', [Value('#include "@foo@.h"'), diff --git a/src/engine/SCons/Tool/tlib.py b/src/engine/SCons/Tool/tlib.py index c0a755e..4d8101b 100644 --- a/src/engine/SCons/Tool/tlib.py +++ b/src/engine/SCons/Tool/tlib.py @@ -5,7 +5,7 @@ XXX """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ XXX # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/tlib.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/tlib.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Tool import SCons.Tool.bcc32 diff --git a/src/engine/SCons/Tool/tlib.xml b/src/engine/SCons/Tool/tlib.xml index cb15db3..2fd8c08 100644 --- a/src/engine/SCons/Tool/tlib.xml +++ b/src/engine/SCons/Tool/tlib.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/wix.py b/src/engine/SCons/Tool/wix.py index 3ddfa84..e79e4a1 100644 --- a/src/engine/SCons/Tool/wix.py +++ b/src/engine/SCons/Tool/wix.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/wix.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/wix.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import SCons.Builder import SCons.Action diff --git a/src/engine/SCons/Tool/wixTests.py b/src/engine/SCons/Tool/wixTests.py index 965ca57..f2649a3 100644 --- a/src/engine/SCons/Tool/wixTests.py +++ b/src/engine/SCons/Tool/wixTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/wixTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/wixTests.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import unittest import os.path @@ -33,7 +33,6 @@ from SCons.Tool.wix import * from SCons.Environment import Environment import TestCmd -import TestUnit # create fake candle and light, so the tool's exists() method will succeed @@ -53,8 +52,7 @@ class WixTestCase(unittest.TestCase): assert env.subst('$WIXSRCSUF') == '.wxs' if __name__ == "__main__": - suite = unittest.makeSuite(WixTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index 2e2934b..185558e 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -3,7 +3,7 @@ Tool specific initialization of `xgettext` tool. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,24 @@ Tool specific initialization of `xgettext` tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/xgettext.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/xgettext.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" + +import os +import re +import subprocess +import sys + +import SCons.Action +import SCons.Node.FS +import SCons.Tool +import SCons.Util +from SCons.Builder import BuilderBase +from SCons.Environment import _null +from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS +from SCons.Platform.mingw import MINGW_DEFAULT_PATHS +from SCons.Tool.GettextCommon import _POTargetFactory +from SCons.Tool.GettextCommon import RPaths, _detect_xgettext +from SCons.Tool.GettextCommon import _xgettext_exists ############################################################################# @@ -41,10 +58,6 @@ class _CmdRunner(object): self.commandstr = commandstr def __call__(self, target, source, env): - import SCons.Action - import subprocess - import os - import sys kw = { 'stdin': 'devnull', 'stdout': subprocess.PIPE, @@ -57,11 +70,10 @@ class _CmdRunner(object): self.out, self.err = proc.communicate() self.status = proc.wait() if self.err: - sys.stderr.write(unicode(self.err)) + sys.stderr.write(SCons.Util.UnicodeType(self.err)) return self.status def strfunction(self, target, source, env): - import os comstr = self.commandstr if env.subst(comstr, target=target, source=source) == "": comstr = self.command @@ -74,9 +86,6 @@ class _CmdRunner(object): ############################################################################# def _update_pot_file(target, source, env): """ Action function for `POTUpdate` builder """ - import re - import os - import SCons.Action nop = lambda target, source, env: 0 # Save scons cwd and os cwd (NOTE: they may be different. After the job, we @@ -154,10 +163,6 @@ def _update_pot_file(target, source, env): ############################################################################# ############################################################################# -from SCons.Builder import BuilderBase - - -############################################################################# class _POTBuilder(BuilderBase): def _execute(self, env, target, source, *args): if not target: @@ -175,10 +180,6 @@ class _POTBuilder(BuilderBase): def _scan_xgettext_from_files(target, source, env, files=None, path=None): """ Parses `POTFILES.in`-like file and returns list of extracted file names. """ - import re - import SCons.Util - import SCons.Node.FS - if files is None: return 0 if not SCons.Util.is_List(files): @@ -230,10 +231,6 @@ def _scan_xgettext_from_files(target, source, env, files=None, path=None): ############################################################################# def _pot_update_emitter(target, source, env): """ Emitter function for `POTUpdate` builder """ - from SCons.Tool.GettextCommon import _POTargetFactory - import SCons.Util - import SCons.Node.FS - if 'XGETTEXTFROM' in env: xfrom = env['XGETTEXTFROM'] else: @@ -261,10 +258,6 @@ def _pot_update_emitter(target, source, env): ############################################################################# ############################################################################# -from SCons.Environment import _null - - -############################################################################# def _POTUpdateBuilderWrapper(env, target=None, source=_null, **kw): return env._POTUpdateBuilder(target, source, **kw) @@ -274,8 +267,6 @@ def _POTUpdateBuilderWrapper(env, target=None, source=_null, **kw): ############################################################################# def _POTUpdateBuilder(env, **kw): """ Creates `POTUpdate` builder object """ - import SCons.Action - from SCons.Tool.GettextCommon import _POTargetFactory kw['action'] = SCons.Action.Action(_update_pot_file, None) kw['suffix'] = '$POTSUFFIX' kw['target_factory'] = _POTargetFactory(env, alias='$POTUPDATE_ALIAS').File @@ -288,9 +279,14 @@ def _POTUpdateBuilder(env, **kw): ############################################################################# def generate(env, **kw): """ Generate `xgettext` tool """ - import SCons.Util - from SCons.Tool.GettextCommon import RPaths, _detect_xgettext + if sys.platform == 'win32': + xgettext = SCons.Tool.find_program_path(env, 'xgettext', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if xgettext: + xgettext_bin_dir = os.path.dirname(xgettext) + env.AppendENVPath('PATH', xgettext_bin_dir) + else: + SCons.Warnings.Warning('xgettext tool requested, but binary not found in ENV PATH') try: env['XGETTEXT'] = _detect_xgettext(env) except: @@ -347,7 +343,6 @@ def generate(env, **kw): ############################################################################# def exists(env): """ Check, whether the tool exists """ - from SCons.Tool.GettextCommon import _xgettext_exists try: return _xgettext_exists(env) except: diff --git a/src/engine/SCons/Tool/xgettext.xml b/src/engine/SCons/Tool/xgettext.xml index 0b68c14..079693f 100644 --- a/src/engine/SCons/Tool/xgettext.xml +++ b/src/engine/SCons/Tool/xgettext.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/yacc.py b/src/engine/SCons/Tool/yacc.py index 4f9fbc2..6857574 100644 --- a/src/engine/SCons/Tool/yacc.py +++ b/src/engine/SCons/Tool/yacc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,16 +31,25 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/yacc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/yacc.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path +import sys import SCons.Defaults import SCons.Tool import SCons.Util +from SCons.Platform.mingw import MINGW_DEFAULT_PATHS +from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS +from SCons.Platform.win32 import CHOCO_DEFAULT_PATH YaccAction = SCons.Action.Action("$YACCCOM", "$YACCCOMSTR") +if sys.platform == 'win32': + BINS = ['bison', 'yacc', 'win_bison'] +else: + BINS = ["bison", "yacc"] + def _yaccEmitter(target, source, env, ysuf, hsuf): yaccflags = env.subst("$YACCFLAGS", target=target, source=source) flags = SCons.Util.CLVar(yaccflags) @@ -94,6 +103,29 @@ def ymEmitter(target, source, env): def yyEmitter(target, source, env): return _yaccEmitter(target, source, env, ['.yy'], '$YACCHXXFILESUFFIX') +def get_yacc_path(env, append_paths=False): + """ + Find the path to the yacc tool, searching several possible names + + Only called in the Windows case, so the default_path + can be Windows-specific + + :param env: current construction environment + :param append_paths: if set, add the path to the tool to PATH + :return: path to yacc tool, if found + """ + for prog in BINS: + bin_path = SCons.Tool.find_program_path( + env, + prog, + default_paths=CHOCO_DEFAULT_PATH + MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if bin_path: + if append_paths: + env.AppendENVPath('PATH', os.path.dirname(bin_path)) + return bin_path + SCons.Warnings.Warning('yacc tool requested, but yacc or bison binary not found in ENV PATH') + + def generate(env): """Add Builders and construction variables for yacc to an Environment.""" c_file, cxx_file = SCons.Tool.createCFileBuilders(env) @@ -113,17 +145,22 @@ def generate(env): cxx_file.add_action('.yy', YaccAction) cxx_file.add_emitter('.yy', yyEmitter) - env['YACC'] = env.Detect('bison') or 'yacc' + if sys.platform == 'win32': + # ignore the return, all we need is for the path to be added + _ = get_yacc_path(env, append_paths=True) + + env["YACC"] = env.Detect(BINS) env['YACCFLAGS'] = SCons.Util.CLVar('') env['YACCCOM'] = '$YACC $YACCFLAGS -o $TARGET $SOURCES' env['YACCHFILESUFFIX'] = '.h' - env['YACCHXXFILESUFFIX'] = '.hpp' - env['YACCVCGFILESUFFIX'] = '.vcg' def exists(env): - return env.Detect(['bison', 'yacc']) + if sys.platform == 'win32': + return get_yacc_path(env) + else: + return env.Detect(BINS) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/yacc.xml b/src/engine/SCons/Tool/yacc.xml index 6bdbd53..8ba3658 100644 --- a/src/engine/SCons/Tool/yacc.xml +++ b/src/engine/SCons/Tool/yacc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/zip.py b/src/engine/SCons/Tool/zip.py index 0f6a8dd..b7efdc7 100644 --- a/src/engine/SCons/Tool/zip.py +++ b/src/engine/SCons/Tool/zip.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/zip.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/zip.py e724ae812eb96f4858a132f5b8c769724744faf6 2019-07-21 00:04:47 bdeegan" import os.path diff --git a/src/engine/SCons/Tool/zip.xml b/src/engine/SCons/Tool/zip.xml index 82eb61a..d7622dd 100644 --- a/src/engine/SCons/Tool/zip.xml +++ b/src/engine/SCons/Tool/zip.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. |