diff options
Diffstat (limited to 'src/engine')
41 files changed, 1310 insertions, 345 deletions
diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index 0afda50..f62d16e 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -65,6 +65,7 @@ SCons/Tool/cc.py SCons/Tool/cyglink.py SCons/Tool/cvf.py SCons/Tool/CVS.py +SCons/Tool/DCommon.py SCons/Tool/default.py SCons/Tool/dmd.py SCons/Tool/docbook/__init__.py @@ -82,6 +83,7 @@ SCons/Tool/g++.py SCons/Tool/g77.py SCons/Tool/gas.py SCons/Tool/gcc.py +SCons/Tool/gdc.py SCons/Tool/gfortran.py SCons/Tool/gnulink.py SCons/Tool/gs.py @@ -102,6 +104,7 @@ SCons/Tool/JavaCommon.py SCons/Tool/javac.py SCons/Tool/javah.py SCons/Tool/latex.py +SCons/Tool/ldc.py SCons/Tool/lex.py SCons/Tool/link.py SCons/Tool/linkloc.py diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index cec241d..415cc9a 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -337,7 +337,7 @@ def _do_create_keywords(args, kw): 'You must either pass a string or a callback which ' 'accepts (target, source, env) as parameters.') if len(args) > 1: - kw['varlist'] = args[1:] + kw['varlist'] + kw['varlist'] = tuple(SCons.Util.flatten(args[1:])) + kw['varlist'] if kw.get('strfunction', _null) is not _null \ and kw.get('cmdstr', _null) is not _null: raise SCons.Errors.UserError( @@ -686,6 +686,7 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw): class f(object): def read(self): return '' def readline(self): return '' + def __iter__(self): return iter(()) stdout = stderr = f() return dummyPopen(e) diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index 7815413..8038f7c 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -211,6 +211,9 @@ def test_varlist(pos_call, str_call, cmd, cmdstrfunc, **kw): a = call_action((cmd, cmdstrfunc, 'a', 'b', 'c')) assert a.varlist == ('a', 'b', 'c'), a.varlist + a = call_action((cmd, cmdstrfunc, ['a', 'b', 'c'])) + assert a.varlist == ('a', 'b', 'c'), a.varlist + kw['varlist'] = 'foo' a = call_action((cmd, cmdstrfunc)) assert a.varlist == ('foo',), a.varlist diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 92f2344..2eb9c86 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -144,6 +144,9 @@ ShCAction = SCons.Action.Action("$SHCCCOM", "$SHCCCOMSTR") CXXAction = SCons.Action.Action("$CXXCOM", "$CXXCOMSTR") ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR") +DAction = SCons.Action.Action("$DCOM", "$DCOMSTR") +ShDAction = SCons.Action.Action("$SHDCOM", "$SHDCOMSTR") + ASAction = SCons.Action.Action("$ASCOM", "$ASCOMSTR") ASPPAction = SCons.Action.Action("$ASPPCOM", "$ASPPCOMSTR") @@ -178,20 +181,38 @@ def chmod_strfunc(dest, mode): Chmod = ActionFactory(chmod_func, chmod_strfunc) -def copy_func(dest, src): +def copy_func(dest, src, symlinks=True): + """ + If symlinks (is true), then a symbolic link will be + shallow copied and recreated as a symbolic link; otherwise, copying + a symbolic link will be equivalent to copying the symbolic link's + final target regardless of symbolic link depth. + """ + + dest = str(dest) + src = str(src) + SCons.Node.FS.invalidate_node_memos(dest) if SCons.Util.is_List(src) and os.path.isdir(dest): for file in src: shutil.copy2(file, dest) + return 0 + elif os.path.islink(src): + linkto = os.readlink(src) + if symlinks: + return os.symlink(linkto, dest) + else: + return copy_func(dest, linkto, symlinks) elif os.path.isfile(src): shutil.copy2(src, dest) + return 0 else: - shutil.copytree(src, dest, 1) - return 0 + return shutil.copytree(src, dest, symlinks) -Copy = ActionFactory(copy_func, - lambda dest, src: 'Copy("%s", "%s")' % (dest, src), - convert=str) +Copy = ActionFactory( + copy_func, + lambda dest, src, symlinks=True: 'Copy("%s", "%s")' % (dest, src) +) def delete_func(dest, must_exist=0): SCons.Node.FS.invalidate_node_memos(dest) @@ -321,7 +342,7 @@ def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): where it finds them. This is used by tools (like the GNU linker) that need to turn something like 'libfoo.a' into '-lfoo'. """ - + if not itms: return itms @@ -335,7 +356,7 @@ def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): c = env_c else: c = _concat_ixes - + stripprefixes = list(map(env.subst, SCons.Util.flatten(stripprefixes))) stripsuffixes = list(map(env.subst, SCons.Util.flatten(stripsuffixes))) @@ -413,7 +434,7 @@ def _defines(prefix, defs, suffix, env, c=_concat_ixes): """ return c(prefix, env.subst_path(processDefines(defs)), suffix, env) - + class NullCmdGenerator(object): """This is a callable class that can be used in place of other command generators if you don't want them to do anything. @@ -449,7 +470,7 @@ class Variable_Method_Caller(object): self.method = method def __call__(self, *args, **kw): try: 1//0 - except ZeroDivisionError: + except ZeroDivisionError: # Don't start iterating with the current stack-frame to # prevent creating reference cycles (f_back is safe). frame = sys.exc_info()[2].tb_frame.f_back diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 737289b..59390f7 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -1206,7 +1206,13 @@ class Base(SubstitutionEnvironment): # based on what we think the value looks like. if SCons.Util.is_List(val): if key == 'CPPDEFINES': - orig = list(orig.items()) + tmp = [] + for (k, v) in orig.iteritems(): + if v is not None: + tmp.append((k, v)) + else: + tmp.append((k,)) + orig = tmp orig += val self._dict[key] = orig else: @@ -1286,8 +1292,15 @@ class Base(SubstitutionEnvironment): else: tmp.append((i,)) val = tmp + # Construct a list of (key, value) tuples. if SCons.Util.is_Dict(dk): - dk = list(dk.items()) + tmp = [] + for (k, v) in dk.iteritems(): + if v is not None: + tmp.append((k, v)) + else: + tmp.append((k,)) + dk = tmp elif SCons.Util.is_String(dk): dk = [(dk,)] else: @@ -1327,8 +1340,15 @@ class Base(SubstitutionEnvironment): else: tmp.append((i,)) dk = tmp + # Construct a list of (key, value) tuples. if SCons.Util.is_Dict(val): - val = list(val.items()) + tmp = [] + for (k, v) in val.iteritems(): + if v is not None: + tmp.append((k, v)) + else: + tmp.append((k,)) + val = tmp elif SCons.Util.is_String(val): val = [(val,)] if delete_existing: @@ -1351,7 +1371,13 @@ class Base(SubstitutionEnvironment): if SCons.Util.is_String(dk): dk = [dk] elif SCons.Util.is_Dict(dk): - dk = list(dk.items()) + tmp = [] + for (k, v) in dk.iteritems(): + if v is not None: + tmp.append((k, v)) + else: + tmp.append((k,)) + dk = tmp if SCons.Util.is_String(val): if val in dk: val = [] @@ -1378,10 +1404,8 @@ class Base(SubstitutionEnvironment): (like a function). There are no references to any mutable objects in the original Environment. """ - try: - builders = self._dict['BUILDERS'] - except KeyError: - pass + + builders = self._dict.get('BUILDERS', {}) clone = copy.copy(self) # BUILDERS is not safe to do a simple copy @@ -1803,8 +1827,8 @@ class Base(SubstitutionEnvironment): pass elif SCons.Util.is_String(pathext): pathext = self.subst(pathext) - prog = self.subst(prog) - path = SCons.Util.WhereIs(prog, path, pathext, reject) + prog = SCons.Util.CLVar(self.subst(prog)) # support "program --with-args" + path = SCons.Util.WhereIs(prog[0], path, pathext, reject) if path: return path return None @@ -2149,7 +2173,7 @@ class Base(SubstitutionEnvironment): def SourceCode(self, entry, builder): """Arrange for a source code builder for (part of) a tree.""" msg = """SourceCode() has been deprecated and there is no replacement. -\tIf you need this function, please contact dev@scons.tigris.org.""" +\tIf you need this function, please contact scons-dev@scons.org""" SCons.Warnings.warn(SCons.Warnings.DeprecatedSourceCodeWarning, msg) entries = self.arg2nodes(entry, self.fs.Entry) for entry in entries: diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index c6e1f3b..2a3852f 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -1887,6 +1887,11 @@ def generate(env): env = env.Clone(KEY_THAT_I_WANT=6, tools=[my_tool]) assert env['KEY_THAT_I_WANT'] == real_value[0], env['KEY_THAT_I_WANT'] + # test for pull request #150 + env = self.TestEnvironment() + env._dict.pop('BUILDERS') + assert env.has_key('BUILDERS') is False + env2 = env.Clone() def test_Copy(self): """Test copying using the old env.Copy() method""" diff --git a/src/engine/SCons/Platform/aix.py b/src/engine/SCons/Platform/aix.py index f6853b5..0266dc6 100644 --- a/src/engine/SCons/Platform/aix.py +++ b/src/engine/SCons/Platform/aix.py @@ -33,10 +33,14 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os +import subprocess from . import posix -def get_xlc(env, xlc=None, xlc_r=None, packages=[]): +import SCons.Util +import SCons.Action + +def get_xlc(env, xlc=None, packages=[]): # Use the AIX package installer tool lslpp to figure out where a # given xl* compiler is installed and what version it is. xlcPath = None @@ -44,18 +48,30 @@ def get_xlc(env, xlc=None, xlc_r=None, packages=[]): if xlc is None: xlc = env.get('CC', 'xlc') - if xlc_r is None: - xlc_r = xlc + '_r' + if SCons.Util.is_List(xlc): + xlc = xlc[0] for package in packages: - cmd = "lslpp -fc " + package + " 2>/dev/null | egrep '" + xlc + "([^-_a-zA-Z0-9].*)?$'" - line = os.popen(cmd).readline() - if line: - v, p = line.split(':')[1:3] - xlcVersion = v.split()[1] - xlcPath = p.split()[0] - xlcPath = xlcPath[:xlcPath.rindex('/')] - break - return (xlcPath, xlc, xlc_r, xlcVersion) + # find the installed filename, which may be a symlink as well + pipe = SCons.Action._subproc(env, ['lslpp', '-fc', package], + stdin = 'devnull', + stderr = 'devnull', + stdout = subprocess.PIPE) + # output of lslpp is something like this: + # #Path:Fileset:File + # /usr/lib/objrepos:vac.C 6.0.0.0:/usr/vac/exe/xlCcpp + # /usr/lib/objrepos:vac.C 6.0.0.0:/usr/vac/bin/xlc_r -> /usr/vac/bin/xlc + for line in pipe.stdout: + if xlcPath: + continue # read everything to let lslpp terminate + fileset, filename = line.split(':')[1:3] + filename = filename.split()[0] + if ('/' in xlc and filename == xlc) \ + or ('/' not in xlc and filename.endswith('/' + xlc)): + xlcVersion = fileset.split()[1] + xlcPath, sep, xlc = filename.rpartition('/') + pass + pass + return (xlcPath, xlc, xlcVersion) def generate(env): posix.generate(env) diff --git a/src/engine/SCons/Platform/posix.py b/src/engine/SCons/Platform/posix.py index 2e21e5a..7e69a7c 100644 --- a/src/engine/SCons/Platform/posix.py +++ b/src/engine/SCons/Platform/posix.py @@ -113,6 +113,10 @@ def generate(env): # This platform supports RPATH specifications. env['__RPATH'] = '$_RPATH' + # GDC is GCC family, but DMD and LDC have different options. + # Must be able to have GCC and DMD work in the same build, so: + env['__DRPATH'] = '$_DRPATH' + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index be0b9c1..0e6967f 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -1,6 +1,14 @@ """SCons.SConf Autoconf-like configuration support. + +In other words, SConf allows to run tests on the build machine to detect +capabilities of system and do some things based on result: generate config +files, header files for C/C++, update variables in environment. + +Tests on the build system can detect if compiler sees header files, if +libraries are installed, if some command line options are supported etc. + """ # @@ -111,16 +119,22 @@ def _createConfigH(target, source, env): def _stringConfigH(target, source, env): return "scons: Configure: creating " + str(target[0]) -def CreateConfigHBuilder(env): - """Called just before the building targets phase begins.""" + +def NeedConfigHBuilder(): if len(_ac_config_hs) == 0: - return + return False + else: + return True + +def CreateConfigHBuilder(env): + """Called if necessary just before the building targets phase begins.""" action = SCons.Action.Action(_createConfigH, _stringConfigH) sconfigHBld = SCons.Builder.Builder(action=action) env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} ) for k in _ac_config_hs.keys(): env.SConfigHBuilder(k, env.Value(_ac_config_hs[k])) + class SConfWarning(SCons.Warnings.Warning): pass @@ -181,7 +195,13 @@ class Streamer(object): def write(self, str): if self.orig: self.orig.write(str) - self.s.write(str) + try: + self.s.write(str) + except TypeError as e: + if e.message.startswith('unicode argument expected'): + self.s.write(str.decode()) + else: + raise def writelines(self, lines): for l in lines: diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 1357e7f..3ef88c7 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -316,7 +316,7 @@ class BuildTask(SCons.Taskmaster.OutOfDateTask): class CleanTask(SCons.Taskmaster.AlwaysTask): """An SCons clean task.""" - def fs_delete(self, path, pathstr, remove=1): + def fs_delete(self, path, pathstr, remove=True): try: if os.path.lexists(path): if os.path.isfile(path) or os.path.islink(path): @@ -343,37 +343,41 @@ class CleanTask(SCons.Taskmaster.AlwaysTask): except (IOError, OSError) as e: print_("scons: Could not remove '%s':" % pathstr, e.strerror) - def show(self): + def _get_files_to_clean(self): + result = [] target = self.targets[0] - if (target.has_builder() or target.side_effect) and not target.noclean: - for t in self.targets: - if not t.isdir(): - display("Removed " + str(t)) - if target in SCons.Environment.CleanTargets: - files = SCons.Environment.CleanTargets[target] - for f in files: - self.fs_delete(f.abspath, str(f), 0) + if target.has_builder() or target.side_effect: + result = [t for t in self.targets if not t.noclean] + return result - def remove(self): + def _clean_targets(self, remove=True): target = self.targets[0] - if (target.has_builder() or target.side_effect) and not target.noclean: - for t in self.targets: - try: - removed = t.remove() - except OSError as e: - # An OSError may indicate something like a permissions - # issue, an IOError would indicate something like - # the file not existing. In either case, print a - # message and keep going to try to remove as many - # targets aa possible. - print_("scons: Could not remove '%s':" % str(t), e.strerror) - else: - if removed: - display("Removed " + str(t)) if target in SCons.Environment.CleanTargets: files = SCons.Environment.CleanTargets[target] for f in files: - self.fs_delete(f.abspath, str(f)) + self.fs_delete(f.abspath, str(f), remove) + + def show(self): + for t in self._get_files_to_clean(): + if not t.isdir(): + display("Removed " + str(t)) + self._clean_targets(remove=False) + + def remove(self): + for t in self._get_files_to_clean(): + try: + removed = t.remove() + except OSError, e: + # An OSError may indicate something like a permissions + # issue, an IOError would indicate something like + # the file not existing. In either case, print a + # message and keep going to try to remove as many + # targets aa possible. + print(("scons: Could not remove '%s':" % str(t), e.strerror) + else: + if removed: + display("Removed " + str(t)) + self._clean_targets(remove=True) execute = remove @@ -1025,13 +1029,17 @@ def _main(parser): # in case they disabled the warning in the SConscript files. if python_version_deprecated(): msg = "Support for pre-%s Python version (%s) is deprecated.\n" + \ - " If this will cause hardship, contact dev@scons.tigris.org." + " If this will cause hardship, contact scons-dev@scons.org" deprecated_version_string = ".".join(map(str, deprecated_python_version)) SCons.Warnings.warn(SCons.Warnings.PythonVersionWarning, msg % (deprecated_version_string, python_version_string())) if not options.help: - SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment()) + # [ ] Clarify why we need to create Builder here at all, and + # why it is created in DefaultEnvironment + # https://bitbucket.org/scons/scons/commits/d27a548aeee8ad5e67ea75c2d19a7d305f784e30 + if SCons.SConf.NeedConfigHBuilder(): + SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment()) # Now re-parse the command-line options (any to the left of a '--' # argument, that is) with any user-defined command-line options that diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index 3ee9464..d50951d 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -461,6 +461,10 @@ class SConsEnvironment(SCons.Environment.Base): def EnsureSConsVersion(self, major, minor, revision=0): """Exit abnormally if the SCons version is not late enough.""" + if SCons.__version__ == '__VERSION__': + SCons.Warnings.warn(SCons.Warnings.DevelopmentVersionWarning, + "EnsureSConsVersion is ignored for development version") + return scons_ver = self._get_major_minor_revision(SCons.__version__) if scons_ver < (major, minor, revision): if revision: diff --git a/src/engine/SCons/Tool/DCommon.py b/src/engine/SCons/Tool/DCommon.py new file mode 100644 index 0000000..02a5e73 --- /dev/null +++ b/src/engine/SCons/Tool/DCommon.py @@ -0,0 +1,56 @@ +"""SCons.Tool.DCommon + +Common code for the various D tools. + +Coded by Russel Winder (russel@winder.org.uk) +2012-09-06 +""" +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os.path + +def isD(env, source): + if not source: + return 0 + for s in source: + if s.sources: + ext = os.path.splitext(str(s.sources[0]))[1] + if ext == '.d': + return 1 + return 0 + +def addDPATHToEnv(env, executable): + dPath = env.WhereIs(executable) + if dPath: + phobosDir = dPath[:dPath.rindex(executable)] + '/../src/phobos' + if os.path.isdir(phobosDir): + env.Append(DPATH=[phobosDir]) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/JavaCommon.py b/src/engine/SCons/Tool/JavaCommon.py index 156ef97..8b13f9f 100644 --- a/src/engine/SCons/Tool/JavaCommon.py +++ b/src/engine/SCons/Tool/JavaCommon.py @@ -65,7 +65,7 @@ if java_parsing: 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', - '5', '6'): + '1.8', '5', '6'): msg = "Java version %s not supported" % version raise NotImplementedError(msg) @@ -171,7 +171,7 @@ 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', '5', '6'): + elif self.version in ('1.5', '1.6', '1.7', '1.8', '5', '6'): self.stackAnonClassBrackets.append(self.brackets) className = [] className.extend(self.listClasses) @@ -244,7 +244,8 @@ if java_parsing: return self # 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' (Tigris Issue 2087) + # 'Foo$1Inner' + # http://scons.tigris.org/issues/show_bug.cgi?id=2087 if self.outer_state.localClasses and \ self.outer_state.stackBrackets[-1] > \ self.outer_state.stackBrackets[-2]+1: diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index dbfada7..bd7bbd0 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -107,7 +107,7 @@ def get_host_target(env): # PROCESSOR_ARCHITECTURE. if not host_platform: host_platform = os.environ.get('PROCESSOR_ARCHITECTURE', '') - + # Retain user requested TARGET_ARCH req_target_platform = env.get('TARGET_ARCH') debug('vc.py:get_host_target() req_target_platform:%s'%req_target_platform) @@ -117,7 +117,7 @@ def get_host_target(env): target_platform = req_target_platform else: target_platform = host_platform - + try: host = _ARCH_TO_CANONICAL[host_platform.lower()] except KeyError as e: @@ -164,7 +164,7 @@ _VCVER_TO_PRODUCT_DIR = { '6.0': [ r'Microsoft\VisualStudio\6.0\Setup\Microsoft Visual C++\ProductDir'] } - + def msvc_version_to_maj_min(msvc_version): msvc_version_numeric = ''.join([x for x in msvc_version if x in string_digits + '.']) @@ -244,7 +244,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): pdir = find_vc_pdir(msvc_version) if pdir is None: raise NoVersionFound("No version of Visual Studio found") - + debug('vc.py: find_batch_file() pdir:%s'%pdir) # filter out e.g. "Exp" from the version name @@ -262,7 +262,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): if not os.path.exists(batfilename): debug("Not found: %s" % batfilename) batfilename = None - + installed_sdks=get_installed_sdks() for _sdk in installed_sdks: sdk_bat_file = _sdk.get_sdk_vc_script(host_arch,target_arch) @@ -270,7 +270,7 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): debug("vc.py:find_batch_file() not found:%s"%_sdk) else: sdk_bat_file_path = os.path.join(pdir,sdk_bat_file) - if os.path.exists(sdk_bat_file_path): + if os.path.exists(sdk_bat_file_path): debug('vc.py:find_batch_file() sdk_bat_file_path:%s'%sdk_bat_file_path) return (batfilename,sdk_bat_file_path) return (batfilename,None) @@ -305,8 +305,21 @@ def reset_installed_vcs(): """Make it try again to find VC. This is just for the tests.""" __INSTALLED_VCS_RUN = None +# Running these batch files isn't cheap: most of the time spent in +# msvs.generate() is due to vcvars*.bat. In a build that uses "tools='msvs'" +# in multiple environments, for example: +# env1 = Environment(tools='msvs') +# env2 = Environment(tools='msvs') +# we can greatly improve the speed of the second and subsequent Environment +# (or Clone) calls by memoizing the environment variables set by vcvars*.bat. +script_env_stdout_cache = {} def script_env(script, args=None): - stdout = common.get_output(script, args) + cache_key = (script, args) + stdout = script_env_stdout_cache.get(cache_key, None) + if stdout is None: + stdout = common.get_output(script, args) + script_env_stdout_cache[cache_key] = stdout + # Stupid batch files do not set return code: we take a look at the # beginning of the output for an error message instead olines = stdout.splitlines() @@ -320,7 +333,7 @@ def get_default_version(env): msvc_version = env.get('MSVC_VERSION') msvs_version = env.get('MSVS_VERSION') - + debug('get_default_version(): msvc_version:%s msvs_version:%s'%(msvc_version,msvs_version)) if msvs_version and not msvc_version: @@ -370,7 +383,7 @@ def msvc_find_valid_batch_script(env,version): 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 + # 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'): try_target_archs.append('x86_amd64') @@ -388,7 +401,7 @@ def msvc_find_valid_batch_script(env,version): for tp in try_target_archs: # Set to current arch. env['TARGET_ARCH']=tp - + debug("vc.py:msvc_find_valid_batch_script() trying target_platform:%s"%tp) host_target = (host_platform, tp) if not is_host_target_supported(host_target, version): @@ -396,7 +409,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] - + # Try to locate a batch file for this host/target platform combo try: (vc_script,sdk_script) = find_batch_file(env,version,host_platform,tp) @@ -410,7 +423,7 @@ def msvc_find_valid_batch_script(env,version): warn_msg = warn_msg % (version, cached_get_installed_vcs()) 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)) if vc_script: @@ -423,24 +436,24 @@ def msvc_find_valid_batch_script(env,version): if not vc_script and sdk_script: debug('vc.py:msvc_find_valid_batch_script() use_script 4: trying sdk script: %s'%(sdk_script)) try: - d = script_env(sdk_script,args=[]) + d = script_env(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 elif not vc_script and not sdk_script: 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)) break # We've found a working target_platform, so stop looking - + # If we cannot find a viable installed compiler, reset the TARGET_ARCH # To it's initial value if not d: env['TARGET_ARCH']=req_target_platform - + return d - + def msvc_setup_env(env): debug('msvc_setup_env()') @@ -459,12 +472,12 @@ def msvc_setup_env(env): env['MSVS_VERSION'] = version env['MSVS'] = {} - + use_script = env.get('MSVC_USE_SCRIPT', True) if SCons.Util.is_String(use_script): debug('vc.py:msvc_setup_env() use_script 1 %s\n' % repr(use_script)) d = script_env(use_script) - elif use_script: + elif use_script: d = msvc_find_valid_batch_script(env,version) debug('vc.py:msvc_setup_env() use_script 2 %s\n' % d) if not d: @@ -485,4 +498,4 @@ def msvc_exists(version=None): if version is None: return len(vcs) > 0 return version in vcs - + diff --git a/src/engine/SCons/Tool/ToolTests.py b/src/engine/SCons/Tool/ToolTests.py index 3e6da5b..a4353b1 100644 --- a/src/engine/SCons/Tool/ToolTests.py +++ b/src/engine/SCons/Tool/ToolTests.py @@ -51,6 +51,8 @@ class ToolTestCase(unittest.TestCase): 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['BUILDERS'] = {} env['ENV'] = {} diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index d30159d..396807f 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -706,7 +706,7 @@ def tool_list(platform, env): assemblers = ['masm', 'nasm', 'gas', '386asm' ] fortran_compilers = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran'] ars = ['mslib', 'ar', 'tlib'] - other_plat_tools=['msvs','midl'] + other_plat_tools = ['msvs', 'midl'] elif str(platform) == 'os2': "prefer IBM tools on OS/2" linkers = ['ilink', 'gnulink', ]#'mslink'] @@ -773,6 +773,9 @@ def tool_list(platform, env): fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77'] ars = ['ar', 'mslib'] + if not str(platform) == 'win32': + other_plat_tools += ['m4', 'rpm'] + c_compiler = FindTool(c_compilers, env) or c_compilers[0] # XXX this logic about what tool provides what should somehow be @@ -796,12 +799,13 @@ def tool_list(platform, env): fortran_compiler = FindTool(fortran_compilers, env) or fortran_compilers[0] ar = FindTool(ars, env) or ars[0] + d_compilers = ['dmd', 'gdc', 'ldc'] + d_compiler = FindTool(d_compilers, env) or d_compilers[0] + other_tools = FindAllTools(other_plat_tools + [ - 'dmd', #TODO: merge 'install' into 'filesystem' and # make 'filesystem' the default 'filesystem', - 'm4', 'wix', #'midl', 'msvs', # Parser generators 'lex', 'yacc', @@ -813,14 +817,14 @@ def tool_list(platform, env): 'dvipdf', 'dvips', 'gs', 'tex', 'latex', 'pdflatex', 'pdftex', # Archivers - 'tar', 'zip', 'rpm', + 'tar', 'zip', # SourceCode factories 'BitKeeper', 'CVS', 'Perforce', 'RCS', 'SCCS', # 'Subversion', ], env) tools = ([linker, c_compiler, cxx_compiler, - fortran_compiler, assembler, ar] + fortran_compiler, assembler, ar, d_compiler] + other_tools) return [x for x in tools if x] diff --git a/src/engine/SCons/Tool/aixc++.py b/src/engine/SCons/Tool/aixc++.py index 5aa1eeec..f03f763 100644 --- a/src/engine/SCons/Tool/aixc++.py +++ b/src/engine/SCons/Tool/aixc++.py @@ -43,32 +43,25 @@ packages = ['vacpp.cmp.core', 'vacpp.cmp.batch', 'vacpp.cmp.C', 'ibmcxx.cmp'] def get_xlc(env): xlc = env.get('CXX', 'xlC') - xlc_r = env.get('SHCXX', 'xlC_r') - return SCons.Platform.aix.get_xlc(env, xlc, xlc_r, packages) - -def smart_cxxflags(source, target, env, for_signature): - build_dir = env.GetBuildPath() - if build_dir: - return '-qtempinc=' + os.path.join(build_dir, 'tempinc') - return '' + return SCons.Platform.aix.get_xlc(env, xlc, packages) def generate(env): """Add Builders and construction variables for xlC / Visual Age suite to an Environment.""" - path, _cxx, _shcxx, version = get_xlc(env) - if path: + path, _cxx, version = get_xlc(env) + if path and _cxx: _cxx = os.path.join(path, _cxx) - _shcxx = os.path.join(path, _shcxx) + + if 'CXX' not in env: + env['CXX'] = _cxx cplusplus.generate(env) - env['CXX'] = _cxx - env['SHCXX'] = _shcxx - env['CXXVERSION'] = version - env['SHOBJSUFFIX'] = '.pic.o' + if version: + env['CXXVERSION'] = version def exists(env): - path, _cxx, _shcxx, version = get_xlc(env) + path, _cxx, version = get_xlc(env) if path and _cxx: xlc = os.path.join(path, _cxx) if os.path.exists(xlc): diff --git a/src/engine/SCons/Tool/aixcc.py b/src/engine/SCons/Tool/aixcc.py index b1da31e..09365b1 100644 --- a/src/engine/SCons/Tool/aixcc.py +++ b/src/engine/SCons/Tool/aixcc.py @@ -42,25 +42,25 @@ packages = ['vac.C', 'ibmcxx.cmp'] def get_xlc(env): xlc = env.get('CC', 'xlc') - xlc_r = env.get('SHCC', 'xlc_r') - return SCons.Platform.aix.get_xlc(env, xlc, xlc_r, packages) + return SCons.Platform.aix.get_xlc(env, xlc, packages) def generate(env): """Add Builders and construction variables for xlc / Visual Age suite to an Environment.""" - path, _cc, _shcc, version = get_xlc(env) - if path: + path, _cc, version = get_xlc(env) + if path and _cc: _cc = os.path.join(path, _cc) - _shcc = os.path.join(path, _shcc) + + if 'CC' not in env: + env['CC'] = _cc cc.generate(env) - env['CC'] = _cc - env['SHCC'] = _shcc - env['CCVERSION'] = version + if version: + env['CCVERSION'] = version def exists(env): - path, _cc, _shcc, version = get_xlc(env) + path, _cc, version = get_xlc(env) if path and _cc: xlc = os.path.join(path, _cc) if os.path.exists(xlc): diff --git a/src/engine/SCons/Tool/aixlink.py b/src/engine/SCons/Tool/aixlink.py index fc65afb..bfddf0a 100644 --- a/src/engine/SCons/Tool/aixlink.py +++ b/src/engine/SCons/Tool/aixlink.py @@ -62,12 +62,14 @@ def generate(env): env['SHLIBSUFFIX'] = '.a' def exists(env): - path, _cc, _shcc, version = aixcc.get_xlc(env) - if path and _cc: - xlc = os.path.join(path, _cc) - if os.path.exists(xlc): - return xlc - return None + # TODO: sync with link.smart_link() to choose a linker + linkers = { 'CXX': ['aixc++'], 'CC': ['aixcc'] } + alltools = [] + for langvar, linktools in linkers.items(): + if langvar in env: # use CC over CXX when user specified CC but not CXX + return SCons.Tool.FindTool(linktools, env) + alltools.extend(linktools) + return SCons.Tool.FindTool(alltools, env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/c++.py b/src/engine/SCons/Tool/c++.py index 82a19c5..430851c 100644 --- a/src/engine/SCons/Tool/c++.py +++ b/src/engine/SCons/Tool/c++.py @@ -72,7 +72,8 @@ def generate(env): SCons.Tool.cc.add_common_cc_variables(env) - env['CXX'] = 'c++' + if 'CXX' not in env: + env['CXX'] = env.Detect(compilers) or compilers[0] env['CXXFLAGS'] = SCons.Util.CLVar('') env['CXXCOM'] = '$CXX -o $TARGET -c $CXXFLAGS $CCFLAGS $_CCCOMCOM $SOURCES' env['SHCXX'] = '$CXX' @@ -90,7 +91,7 @@ def generate(env): env['CXXFILESUFFIX'] = '.cc' def exists(env): - return env.Detect(compilers) + return env.Detect(env.get('CXX', compilers)) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/cc.py b/src/engine/SCons/Tool/cc.py index 9b404b2..590ec5f 100644 --- a/src/engine/SCons/Tool/cc.py +++ b/src/engine/SCons/Tool/cc.py @@ -62,6 +62,8 @@ def add_common_cc_variables(env): if 'SHCCFLAGS' not in env: env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS') +compilers = ['cc'] + def generate(env): """ Add Builders and construction variables for C compilers to an Environment. @@ -76,7 +78,8 @@ def generate(env): add_common_cc_variables(env) - env['CC'] = 'cc' + if 'CC' not in env: + env['CC'] = env.Detect(compilers) or compilers[0] env['CFLAGS'] = SCons.Util.CLVar('') env['CCCOM'] = '$CC -o $TARGET -c $CFLAGS $CCFLAGS $_CCCOMCOM $SOURCES' env['SHCC'] = '$CC' @@ -93,7 +96,7 @@ def generate(env): env['CFILESUFFIX'] = '.c' def exists(env): - return env.Detect('cc') + return env.Detect(env.get('CC', compilers)) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/dmd.py b/src/engine/SCons/Tool/dmd.py index a8faf5d..082d5c3 100644 --- a/src/engine/SCons/Tool/dmd.py +++ b/src/engine/SCons/Tool/dmd.py @@ -3,14 +3,14 @@ Tool-specific initialization for the Digital Mars D compiler. (http://digitalmars.com/d) -Coded by Andy Friesen (andy@ikagames.com) +Originally coded by Andy Friesen (andy@ikagames.com) 15 November 2003 -Amended by Russel Winder (russel@russel.org.uk) -2010-02-07 +Evolved by Russel Winder (russel@winder.org.uk) +2010-02-07 onwards There are a number of problems with this script at this point in time. -The one that irritates me the most is the Windows linker setup. The D +The one that irritates the most is the Windows linker setup. The D linker doesn't have a way to add lib paths on the commandline, as far as I can see. You have to specify paths relative to the SConscript or use absolute paths. To hack around it, add '#/blah'. This will link @@ -18,14 +18,15 @@ blah.lib from the directory where SConstruct resides. Compiler variables: DC - The name of the D compiler to use. Defaults to dmd or gdmd, - whichever is found. + whichever is found. DPATH - List of paths to search for import modules. DVERSIONS - List of version tags to enable when compiling. DDEBUG - List of debug tags to enable when compiling. Linker related variables: LIBS - List of library files to link in. - DLINK - Name of the linker to use. Defaults to dmd or gdmd. + DLINK - Name of the linker to use. Defaults to dmd or gdmd, + whichever is found. DLINKFLAGS - List of linker flags. Lib tool variables: @@ -60,6 +61,7 @@ Lib tool variables: __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os +import subprocess import SCons.Action import SCons.Builder @@ -67,57 +69,34 @@ import SCons.Defaults import SCons.Scanner.D import SCons.Tool -# Adapted from c++.py -def isD(source): - if not source: - return 0 +import SCons.Tool.DCommon - for s in source: - if s.sources: - ext = os.path.splitext(str(s.sources[0]))[1] - if ext == '.d': - return 1 - return 0 - -smart_link = {} - -smart_lib = {} def generate(env): - global smart_link - global smart_lib - static_obj, shared_obj = SCons.Tool.createObjBuilders(env) - DAction = SCons.Action.Action('$DCOM', '$DCOMSTR') - - static_obj.add_action('.d', DAction) - shared_obj.add_action('.d', DAction) + static_obj.add_action('.d', SCons.Defaults.DAction) + shared_obj.add_action('.d', SCons.Defaults.ShDAction) static_obj.add_emitter('.d', SCons.Defaults.StaticObjectEmitter) shared_obj.add_emitter('.d', SCons.Defaults.SharedObjectEmitter) - dc = env.Detect(['dmd', 'gdmd']) - env['DC'] = dc + env['DC'] = env.Detect(['dmd', 'gdmd']) env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -of$TARGET $SOURCES' env['_DINCFLAGS'] = '$( ${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' env['_DVERFLAGS'] = '$( ${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)} $)' env['_DDEBUGFLAGS'] = '$( ${_concat(DDEBUGPREFIX, DDEBUG, DDEBUGSUFFIX, __env__)} $)' env['_DFLAGS'] = '$( ${_concat(DFLAGPREFIX, DFLAGS, DFLAGSUFFIX, __env__)} $)' + env['SHDC'] = '$DC' + env['SHDCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -fPIC -of$TARGET $SOURCES' + env['DPATH'] = ['#/'] env['DFLAGS'] = [] env['DVERSIONS'] = [] env['DDEBUG'] = [] - if dc: - # Add the path to the standard library. - # This is merely for the convenience of the dependency scanner. - dmd_path = env.WhereIs(dc) - if dmd_path: - x = dmd_path.rindex(dc) - phobosDir = dmd_path[:x] + '/../src/phobos' - if os.path.isdir(phobosDir): - env.Append(DPATH = [phobosDir]) + if env['DC']: + SCons.Tool.DCommon.addDPATHToEnv(env, env['DC']) env['DINCPREFIX'] = '-I' env['DINCSUFFIX'] = '' @@ -129,106 +108,39 @@ def generate(env): env['DFLAGSUFFIX'] = '' env['DFILESUFFIX'] = '.d' - # Need to use the Digital Mars linker/lib on windows. - # *nix can just use GNU link. - if env['PLATFORM'] == 'win32': - env['DLINK'] = '$DC' - env['DLINKCOM'] = '$DLINK -of$TARGET $SOURCES $DFLAGS $DLINKFLAGS $_DLINKLIBFLAGS' - env['DLIB'] = 'lib' - env['DLIBCOM'] = '$DLIB $_DLIBFLAGS -c $TARGET $SOURCES $_DLINKLIBFLAGS' - - env['_DLINKLIBFLAGS'] = '$( ${_concat(DLIBLINKPREFIX, LIBS, DLIBLINKSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' - env['_DLIBFLAGS'] = '$( ${_concat(DLIBFLAGPREFIX, DLIBFLAGS, DLIBFLAGSUFFIX, __env__)} $)' - env['DLINKFLAGS'] = [] - env['DLIBLINKPREFIX'] = '' - env['DLIBLINKSUFFIX'] = '.lib' - env['DLIBFLAGPREFIX'] = '-' - env['DLIBFLAGSUFFIX'] = '' - env['DLINKFLAGPREFIX'] = '-' - env['DLINKFLAGSUFFIX'] = '' - - SCons.Tool.createStaticLibBuilder(env) - - # Basically, we hijack the link and ar builders with our own. - # these builders check for the presence of D source, and swap out - # the system's defaults for the Digital Mars tools. If there's no D - # source, then we silently return the previous settings. - linkcom = env.get('LINKCOM') - try: - env['SMART_LINKCOM'] = smart_link[linkcom] - except KeyError: - def _smartLink(source, target, env, for_signature, - defaultLinker=linkcom): - if isD(source): - # XXX I'm not sure how to add a $DLINKCOMSTR variable - # so that it works with this _smartLink() logic, - # and I don't have a D compiler/linker to try it out, - # so we'll leave it alone for now. - return '$DLINKCOM' - else: - return defaultLinker - env['SMART_LINKCOM'] = smart_link[linkcom] = _smartLink - - arcom = env.get('ARCOM') - try: - env['SMART_ARCOM'] = smart_lib[arcom] - except KeyError: - def _smartLib(source, target, env, for_signature, - defaultLib=arcom): - if isD(source): - # XXX I'm not sure how to add a $DLIBCOMSTR variable - # so that it works with this _smartLib() logic, and - # I don't have a D compiler/archiver to try it out, - # so we'll leave it alone for now. - return '$DLIBCOM' - else: - return defaultLib - env['SMART_ARCOM'] = smart_lib[arcom] = _smartLib - - # It is worth noting that the final space in these strings is - # absolutely pivotal. SCons sees these as actions and not generators - # if it is not there. (very bad) - env['ARCOM'] = '$SMART_ARCOM ' - env['LINKCOM'] = '$SMART_LINKCOM ' - else: # assuming linux - linkcom = env.get('LINKCOM') - try: - env['SMART_LINKCOM'] = smart_link[linkcom] - except KeyError: - def _smartLink(source, target, env, for_signature, - defaultLinker=linkcom, dc=dc): - if isD(source): - try: - libs = env['LIBS'] - except KeyError: - libs = [] - if dc == 'dmd': - # TODO: This assumes that the dmd executable is in the - # bin directory and that the libraries are in a peer - # directory lib. This true of the Digital Mars - # distribution but . . . - import glob - dHome = env.WhereIs(dc).replace('/dmd' , '/..') - if glob.glob(dHome + '/lib/*phobos2*'): - if 'phobos2' not in libs: - env.Append(LIBPATH = [dHome + '/lib']) - env.Append(LIBS = ['phobos2']) - # TODO: Find out when there will be a - # 64-bit version of D. - env.Append(LINKFLAGS = ['-m32']) - else: - if 'phobos' not in libs: - env.Append(LIBS = ['phobos']) - elif dc is 'gdmd': - env.Append(LIBS = ['gphobos']) - if 'pthread' not in libs: - env.Append(LIBS = ['pthread']) - if 'm' not in libs: - env.Append(LIBS = ['m']) - return defaultLinker - env['SMART_LINKCOM'] = smart_link[linkcom] = _smartLink - - env['LINKCOM'] = '$SMART_LINKCOM ' + env['DLINK'] = '$DC' + env['DLINKFLAGS'] = SCons.Util.CLVar('') + env['DLINKCOM'] = '$DLINK -of$TARGET $DLINKFLAGS $__DRPATH $SOURCES $_DLIBDIRFLAGS $_DLIBFLAGS' + + env['DSHLINK'] = '$DC' + env['DSHLINKFLAGS'] = SCons.Util.CLVar('$DLINKFLAGS -shared -defaultlib=libphobos2.so') + env['SHDLINKCOM'] = '$DLINK -of$TARGET $DSHLINKFLAGS $__DRPATH $SOURCES $_DLIBDIRFLAGS $_DLIBFLAGS' + + env['DLIBLINKPREFIX'] = '' if env['PLATFORM'] == 'win32' else '-L-l' + env['DLIBLINKSUFFIX'] = '.lib' if env['PLATFORM'] == 'win32' else '' + env['_DLIBFLAGS'] = '${_stripixes(DLIBLINKPREFIX, LIBS, DLIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}' + + env['DLIBDIRPREFIX'] = '-L-L' + env['DLIBDIRSUFFIX'] = '' + env['_DLIBDIRFLAGS'] = '$( ${_concat(DLIBDIRPREFIX, LIBPATH, DLIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' + + + env['DLIB'] = 'lib' if env['PLATFORM'] == 'win32' else 'ar cr' + env['DLIBCOM'] = '$DLIB $_DLIBFLAGS {0}$TARGET $SOURCES $_DLIBFLAGS'.format('-c ' if env['PLATFORM'] == 'win32' else '') + + #env['_DLIBFLAGS'] = '$( ${_concat(DLIBFLAGPREFIX, DLIBFLAGS, DLIBFLAGSUFFIX, __env__)} $)' + + env['DLIBFLAGPREFIX'] = '-' + env['DLIBFLAGSUFFIX'] = '' + + # __RPATH is set to $_RPATH in the platform specification if that + # platform supports it. + env['DRPATHPREFIX'] = '-L-rpath=' + env['DRPATHSUFFIX'] = '' + env['_DRPATH'] = '${_concat(DRPATHPREFIX, RPATH, DRPATHSUFFIX, __env__)}' + + SCons.Tool.createStaticLibBuilder(env) + def exists(env): return env.Detect(['dmd', 'gdmd']) diff --git a/src/engine/SCons/Tool/dmd.xml b/src/engine/SCons/Tool/dmd.xml index d956894..f8936c1 100644 --- a/src/engine/SCons/Tool/dmd.xml +++ b/src/engine/SCons/Tool/dmd.xml @@ -21,23 +21,23 @@ See its __doc__ string for a discussion of the format. <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"> + xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0/scons.xsd"> <tool name="dmd"> <summary> <para> -Sets construction variables for D language compilers -(the Digital Mars D compiler, or GDC). +Sets construction variables for D language compiler DMD. </para> </summary> <sets> -<item><!--</item> <item>DC</item> <item>DCOM</item> <item>_DINCFLAGS</item> <item>_DVERFLAGS</item> <item>_DDEBUGFLAGS</item> <item>_DFLAGS</item> +<item>SHDC</item> +<item>SHDCOM</item> <item>DPATH</item> <item>DFLAGS</item> <item>DVERSIONS</item> @@ -50,24 +50,27 @@ Sets construction variables for D language compilers <item>DDEBUGSUFFIX</item> <item>DFLAGPREFIX</item> <item>DFLAGSUFFIX</item> -<item>DFLESUFFIX</item> +<item>DFILESUFFIX</item> <item>DLINK</item> +<item>DLINKFLAGS</item> <item>DLINKCOM</item> +<item>SHDLINK</item> +<item>SHDLINKFLAGS</item> +<item>SHDLINKCOM</item> +<item>DLIBLINKPREFIX</item> +<item>DLIBLINKSUFFIX</item> +<item>_DLIBFLAGS</item> +<item>DLIBDIRPREFIX</item> +<item>DLIBDIRSUFFIX</item> +<item>_DLIBDIRFLAGS</item> <item>DLIB</item> <item>DLIBCOM</item> -<item>_DLINKLIBFLAGS</item> <item>_DLIBFLAGS</item> -<item>DLINKFLAGS</item> -<item>DLIBLINKPREFIX</item> -<item>DLIBLINKSUFFIX</item> <item>DLIBFLAGPREFIX</item> <item>DLIBFLAGSUFFIX</item> -<item>DLINKFLAGPREFIX</item> -<item>DLINKFLAGSUFFIX</item> -<item>LINKCOM</item> -<item>ARCOM</item> -<item>LIBS</item> -<item>--></item> +<item>RPATHPREFIX</item> +<item>RPATHSUFFIX</item> +<item>_RPATH</item> </sets> <uses> </uses> diff --git a/src/engine/SCons/Tool/docbook/__init__.py b/src/engine/SCons/Tool/docbook/__init__.py index 627ff51..77ed388 100644 --- a/src/engine/SCons/Tool/docbook/__init__.py +++ b/src/engine/SCons/Tool/docbook/__init__.py @@ -242,7 +242,7 @@ def __xml_scan(node, env, path, arg): styledoc = libxml2.parseFile(xsl_file) style = libxslt.parseStylesheetDoc(styledoc) - doc = libxml2.parseFile(str(node)) + doc = libxml2.readFile(str(node), None, libxml2.XML_PARSE_NOENT) result = style.applyStylesheet(doc, None) depfiles = [] @@ -348,7 +348,7 @@ def __xinclude_libxml2(target, source, env): Resolving XIncludes, using the libxml2 module. """ doc = libxml2.readFile(str(source[0]), None, libxml2.XML_PARSE_NOENT) - doc.xincludeProcess() + doc.xincludeProcessFlags(libxml2.XML_PARSE_NOENT) doc.saveFile(str(target[0])) doc.freeDoc() diff --git a/src/engine/SCons/Tool/docbook/docs/manual.xml b/src/engine/SCons/Tool/docbook/docs/manual.xml index e232c6a..c129753 100644 --- a/src/engine/SCons/Tool/docbook/docs/manual.xml +++ b/src/engine/SCons/Tool/docbook/docs/manual.xml @@ -263,7 +263,7 @@ with large input files may occur. There will definitely arise the need for adding features, or a variable. Let us know if you can think of a nice improvement or have worked on a bugfix/patch with success. Enter your issues at the Launchpad bug tracker for the Docbook Tool, or write to the User General Discussion -list of SCons at <literal>users@scons.tigris.org</literal>. +list of SCons at <literal>scons-users@scons.org</literal>. </para> </section> diff --git a/src/engine/SCons/Tool/g++.py b/src/engine/SCons/Tool/g++.py index 0e1c181..c5eb579 100644 --- a/src/engine/SCons/Tool/g++.py +++ b/src/engine/SCons/Tool/g++.py @@ -40,16 +40,19 @@ import subprocess import SCons.Tool import SCons.Util +from . import gcc cplusplus = __import__(__package__+'.c++', globals(), locals(), ['*']) + compilers = ['g++'] def generate(env): """Add Builders and construction variables for g++ to an Environment.""" static_obj, shared_obj = SCons.Tool.createObjBuilders(env) - cplusplus.generate(env) + if 'CXX' not in env: + env['CXX'] = env.Detect(compilers) or compilers[0] - env['CXX'] = env.Detect(compilers) + cplusplus.generate(env) # platform specific settings if env['PLATFORM'] == 'aix': @@ -61,26 +64,13 @@ def generate(env): elif env['PLATFORM'] == 'sunos': env['SHOBJSUFFIX'] = '.pic.o' # determine compiler version - if env['CXX']: - #pipe = SCons.Action._subproc(env, [env['CXX'], '-dumpversion'], - pipe = SCons.Action._subproc(env, [env['CXX'], '--version'], - stdin = 'devnull', - stderr = 'devnull', - stdout = subprocess.PIPE) - if pipe.wait() != 0: return - # -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: - # env['CXXVERSION'] = line - line = SCons.Util.to_str (pipe.stdout.readline()) - match = re.search(r'[0-9]+(\.[0-9]+)+', line) - if match: - env['CXXVERSION'] = match.group(0) + version = gcc.detect_version(env, env['CXX']) + if version: + env['CXXVERSION'] = version def exists(env): - return env.Detect(compilers) + # is executable, and is a GNU compiler (or accepts '--version' at least) + return gcc.detect_version(env, env.Detect(env.get('CXX', compilers))) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/gcc.py b/src/engine/SCons/Tool/gcc.py index 72f9bfd..998e35b 100644 --- a/src/engine/SCons/Tool/gcc.py +++ b/src/engine/SCons/Tool/gcc.py @@ -44,34 +44,54 @@ compilers = ['gcc', 'cc'] def generate(env): """Add Builders and construction variables for gcc to an Environment.""" + + if 'CC' not in env: + env['CC'] = env.Detect(compilers) or compilers[0] + cc.generate(env) - env['CC'] = env.Detect(compilers) or 'gcc' 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'], - pipe = SCons.Action._subproc(env, [env['CC'], '--version'], - stdin = 'devnull', - stderr = 'devnull', - stdout = subprocess.PIPE) - if pipe.wait() != 0: return - # -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: - # env['CCVERSION'] = line - line = SCons.Util.to_str (pipe.stdout.readline()) - match = re.search(r'[0-9]+(\.[0-9]+)+', line) - if match: - env['CCVERSION'] = match.group(0) + version = detect_version(env, env['CC']) + if version: + env['CCVERSION'] = version def exists(env): - return env.Detect(compilers) + # 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.""" + 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) + # -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()) + 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: # tab-width:4 diff --git a/src/engine/SCons/Tool/gdc.py b/src/engine/SCons/Tool/gdc.py new file mode 100644 index 0000000..1178b85 --- /dev/null +++ b/src/engine/SCons/Tool/gdc.py @@ -0,0 +1,128 @@ +"""SCons.Tool.gdc + +Tool-specific initialization for the GDC compiler. +(https://github.com/D-Programming-GDC/GDC) + +Developed by Russel Winder (russel@winder.org.uk) +2012-05-09 onwards + +Compiler variables: + DC - The name of the D compiler to use. Defaults to gdc. + DPATH - List of paths to search for import modules. + DVERSIONS - List of version tags to enable when compiling. + DDEBUG - List of debug tags to enable when compiling. + +Linker related variables: + LIBS - List of library files to link in. + DLINK - Name of the linker to use. Defaults to gdc. + DLINKFLAGS - List of linker flags. + +Lib tool variables: + DLIB - Name of the lib tool to use. Defaults to lib. + DLIBFLAGS - List of flags to pass to the lib tool. + LIBS - Same as for the linker. (libraries to pull into the .lib) +""" + +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import SCons.Action +import SCons.Defaults +import SCons.Tool + +import SCons.Tool.DCommon + + +def generate(env): + static_obj, shared_obj = SCons.Tool.createObjBuilders(env) + + static_obj.add_action('.d', SCons.Defaults.DAction) + shared_obj.add_action('.d', SCons.Defaults.ShDAction) + static_obj.add_emitter('.d', SCons.Defaults.StaticObjectEmitter) + shared_obj.add_emitter('.d', SCons.Defaults.SharedObjectEmitter) + + env['DC'] = env.Detect('gdc') + env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -o $TARGET $SOURCES' + env['_DINCFLAGS'] = '$( ${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' + env['_DVERFLAGS'] = '$( ${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)} $)' + env['_DDEBUGFLAGS'] = '$( ${_concat(DDEBUGPREFIX, DDEBUG, DDEBUGSUFFIX, __env__)} $)' + env['_DFLAGS'] = '$( ${_concat(DFLAGPREFIX, DFLAGS, DFLAGSUFFIX, __env__)} $)' + + env['SHDC'] = '$DC' + env['SHDCOM'] = '$SHDC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -fPIC -c -o $TARGET $SOURCES' + + env['DPATH'] = ['#/'] + env['DFLAGS'] = [] + env['DVERSIONS'] = [] + env['DDEBUG'] = [] + + if env['DC']: + SCons.Tool.DCommon.addDPATHToEnv(env, env['DC']) + + env['DINCPREFIX'] = '-I' + env['DINCSUFFIX'] = '' + env['DVERPREFIX'] = '-version=' + env['DVERSUFFIX'] = '' + env['DDEBUGPREFIX'] = '-debug=' + env['DDEBUGSUFFIX'] = '' + env['DFLAGPREFIX'] = '-' + env['DFLAGSUFFIX'] = '' + env['DFILESUFFIX'] = '.d' + + env['DLINK'] = '$DC' + env['DLINKFLAGS'] = SCons.Util.CLVar('') + env['DLINKCOM'] = '$DLINK -o $TARGET $DLINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + + env['SHDLINK'] = '$DC' + env['SHDLINKFLAGS'] = SCons.Util.CLVar('$DLINKFLAGS -shared') + env['SHDLINKCOM'] = '$DLINK -o $TARGET $DLINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + + env['DLIB'] = 'lib' if env['PLATFORM'] == 'win32' else 'ar cr' + env['DLIBCOM'] = '$DLIB $_DLIBFLAGS {0}$TARGET $SOURCES $_DLINKLIBFLAGS'.format('-c ' if env['PLATFORM'] == 'win32' else '') + + env['_DLIBFLAGS'] = '$( ${_concat(DLIBFLAGPREFIX, DLIBFLAGS, DLIBFLAGSUFFIX, __env__)} $)' + + env['DLIBFLAGPREFIX'] = '-' + env['DLIBFLAGSUFFIX'] = '' + env['DLINKFLAGPREFIX'] = '-' + env['DLINKFLAGSUFFIX'] = '' + + # __RPATH is set to $_RPATH in the platform specification if that + # platform supports it. + env['RPATHPREFIX'] = '-Wl,-rpath=' + env['RPATHSUFFIX'] = '' + env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}' + + SCons.Tool.createStaticLibBuilder(env) + + +def exists(env): + return env.Detect('gdc') + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/gdc.xml b/src/engine/SCons/Tool/gdc.xml new file mode 100644 index 0000000..20544b0 --- /dev/null +++ b/src/engine/SCons/Tool/gdc.xml @@ -0,0 +1,387 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +__COPYRIGHT__ + +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; +]> + +<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/scons.xsd"> + +<tool name="gdc"> +<summary> +<para> +Sets construction variables for the D language compiler GDC. +</para> +</summary> +<sets> +<item>DC</item> +<item>DCOM</item> +<item>_DINCFLAGS</item> +<item>_DVERFLAGS</item> +<item>_DDEBUGFLAGS</item> +<item>_DFLAGS</item> +<item>SHDC</item> +<item>SHDCOM</item> +<item>DPATH</item> +<item>DFLAGS</item> +<item>DVERSIONS</item> +<item>DDEBUG</item> +<item>DINCPREFIX</item> +<item>DINCSUFFIX</item> +<item>DVERPREFIX</item> +<item>DVERSUFFIX</item> +<item>DDEBUGPREFIX</item> +<item>DDEBUGSUFFIX</item> +<item>DFLAGPREFIX</item> +<item>DFLAGSUFFIX</item> +<item>DFILESUFFIX</item> +<item>DLINK</item> +<item>DLINKFLAGS</item> +<item>DLINKCOM</item> +<item>SHDLINK</item> +<item>SHDLINKFLAGS</item> +<item>SHDLINKCOM</item> +<item>DLIB</item> +<item>DLIBCOM</item> +<item>_DLIBFLAGS</item> +<item>DLIBFLAGPREFIX</item> +<item>DLIBFLAGSUFFIX</item> +<item>DLINKFLAGPREFIX</item> +<item>DLINKFLAGSUFFIX</item> +<item>RPATHPREFIX</item> +<item>RPATHSUFFIX</item> +<item>_RPATH</item> +</sets> +<uses> +</uses> +</tool> + +<cvar name="DC"> +<summary> +<para> +DC. +</para> +</summary> +</cvar> + +<cvar name="DCOM"> +<summary> +<para> +DCOM. +</para> +</summary> +</cvar> + +<cvar name="DDEBUG"> +<summary> +<para> +DDEBUG. +</para> +</summary> +</cvar> + +<cvar name="DDEBUGPREFIX"> +<summary> +<para> +DDEBUGPREFIX. +</para> +</summary> +</cvar> + +<cvar name="DDEBUGSUFFIX"> +<summary> +<para> +DDEBUGSUFFIX. +</para> +</summary> +</cvar> + +<cvar name="DFILESUFFIX"> +<summary> +<para> +DFILESUFFIX. +</para> +</summary> +</cvar> + +<cvar name="DFLAGPREFIX"> +<summary> +<para> +DFLAGPREFIX. +</para> +</summary> +</cvar> + +<cvar name="DFLAGS"> +<summary> +<para> +DFLAGS. +</para> +</summary> +</cvar> + +<cvar name="DFLAGSUFFIX"> +<summary> +<para> +DFLAGSUFFIX. +</para> +</summary> +</cvar> + +<cvar name="DINCPREFIX"> +<summary> +<para> +DINCPREFIX. +</para> +</summary> +</cvar> + +<cvar name="DINCSUFFIX"> +<summary> +<para> +DINCSUFFIX. +</para> +</summary> +</cvar> + +<cvar name="DLIB"> +<summary> +<para> +DLIB. +</para> +</summary> +</cvar> + +<cvar name="DLIBCOM"> +<summary> +<para> +DLIBCOM. +</para> +</summary> +</cvar> + +<cvar name="DLIBDIRPREFIX"> +<summary> +<para> +DLIBDIRPREFIX. +</para> +</summary> +</cvar> + +<cvar name="DLIBDIRSUFFIX"> +<summary> +<para> +DLIBDIRSUFFIX. +</para> +</summary> +</cvar> + +<cvar name="DLIBFLAGPREFIX"> +<summary> +<para> +DLIBFLAGPREFIX. +</para> +</summary> +</cvar> + +<cvar name="DLIBFLAGSUFFIX"> +<summary> +<para> +DLIBFLAGSUFFIX. +</para> +</summary> +</cvar> + +<cvar name="DLIBLINKPREFIX"> +<summary> +<para> +DLIBLINKPREFIX. +</para> +</summary> +</cvar> + +<cvar name="DLIBLINKSUFFIX"> +<summary> +<para> +DLIBLINKSUFFIX. +</para> +</summary> +</cvar> + +<cvar name="DLINK"> +<summary> +<para> +DLINK. +</para> +</summary> +</cvar> + +<cvar name="DLINKCOM"> +<summary> +<para> +DLINKCOM. +</para> +</summary> +</cvar> + +<cvar name="DLINKFLAGPREFIX"> +<summary> +<para> +DLINKFLAGPREFIX. +</para> +</summary> +</cvar> + +<cvar name="DLINKFLAGS"> +<summary> +<para> +DLINKFLAGS. +</para> +</summary> +</cvar> + +<cvar name="DLINKFLAGSUFFIX"> +<summary> +<para> +DLINKFLAGSUFFIX. +</para> +</summary> +</cvar> + +<cvar name="DPATH"> +<summary> +<para> +DPATH. +</para> +</summary> +</cvar> + +<cvar name="DVERPREFIX"> +<summary> +<para> +DVERPREFIX. +</para> +</summary> +</cvar> + +<cvar name="DVERSIONS"> +<summary> +<para> +DVERSIONS. +</para> +</summary> +</cvar> + +<cvar name="DVERSUFFIX"> +<summary> +<para> +DVERSUFFIX. +</para> +</summary> +</cvar> + +<cvar name="SHDC"> +<summary> +<para> +SHDC. +</para> +</summary> +</cvar> + +<cvar name="SHDCOM"> +<summary> +<para> +SHDCOM. +</para> +</summary> +</cvar> + +<cvar name="SHDLINK"> +<summary> +<para> +SHDLINK. +</para> +</summary> +</cvar> + +<cvar name="SHDLINKCOM"> +<summary> +<para> +SHDLINKCOM. +</para> +</summary> +</cvar> + +<cvar name="SHDLINKFLAGS"> +<summary> +<para> +SHDLINKFLAGS. +</para> +</summary> +</cvar> + +<cvar name="_DDEBUGFLAGS"> +<summary> +<para> +_DDEBUGFLAGS. +</para> +</summary> +</cvar> + +<cvar name="_DFLAGS"> +<summary> +<para> +_DFLAGS. +</para> +</summary> +</cvar> + +<cvar name="_DINCFLAGS"> +<summary> +<para> +_DINCFLAGS. +</para> +</summary> +</cvar> + +<cvar name="_DLIBDIRFLAGS"> +<summary> +<para> +_DLIBDIRFLAGS. +</para> +</summary> +</cvar> + +<cvar name="_DLIBFLAGS"> +<summary> +<para> +_DLIBFLAGS. +</para> +</summary> +</cvar> + +<cvar name="_DVERFLAGS"> +<summary> +<para> +_DVERFLAGS. +</para> +</summary> +</cvar> + +</sconsdoc> diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py index ea8d7bd..6bd9471 100644 --- a/src/engine/SCons/Tool/gnulink.py +++ b/src/engine/SCons/Tool/gnulink.py @@ -37,8 +37,6 @@ import SCons.Util from . import link -linkers = ['g++', 'gcc'] - def generate(env): """Add Builders and construction variables for gnulink to an Environment.""" link.generate(env) @@ -53,7 +51,14 @@ def generate(env): env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}' def exists(env): - return env.Detect(linkers) + # TODO: sync with link.smart_link() to choose a linker + linkers = { 'CXX': ['g++'], 'CC': ['gcc'] } + alltools = [] + for langvar, linktools in linkers.items(): + if langvar in env: # use CC over CXX when user specified CC but not CXX + return SCons.Tool.FindTool(linktools, env) + alltools.extend(linktools) + return SCons.Tool.FindTool(alltools, env) # find CXX or CC # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index da5f592..7cc2376 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -156,7 +156,43 @@ def get_intel_registry_value(valuename, version=None, abi=None): try: k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K) except SCons.Util.RegError: - raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)) + # For version 13 and later, check UUID subkeys for valuename + if is_win64: + K = 'Software\\Wow6432Node\\Intel\\Suites\\' + version + "\\Defaults\\C++\\" + abi.upper() + else: + K = 'Software\\Intel\\Suites\\' + version + "\\Defaults\\C++\\" + abi.upper() + try: + k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K) + uuid = SCons.Util.RegQueryValueEx(k, 'SubKey')[0] + + if is_win64: + K = 'Software\\Wow6432Node\\Intel\\Suites\\' + version + "\\" + uuid + "\\C++" + else: + K = 'Software\\Intel\\Suites\\' + version + "\\" + uuid + "\\C++" + k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K) + + try: + v = SCons.Util.RegQueryValueEx(k, valuename)[0] + return v # or v.encode('iso-8859-1', 'replace') to remove unicode? + except SCons.Util.RegError: + if abi.upper() == 'EM64T': + abi = 'em64t_native' + if is_win64: + K = 'Software\\Wow6432Node\\Intel\\Suites\\' + version + "\\" + uuid + "\\C++\\" + abi.upper() + else: + K = 'Software\\Intel\\Suites\\' + version + "\\" + uuid + "\\C++\\" + abi.upper() + k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, K) + + try: + v = SCons.Util.RegQueryValueEx(k, valuename)[0] + return v # or v.encode('iso-8859-1', 'replace') to remove unicode? + except SCons.Util.RegError: + raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)) + + except SCons.Util.RegError: + raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)) + except WindowsError: + raise MissingRegistryError("%s was not found in the registry, for Intel compiler version %s, abi='%s'"%(K, version,abi)) # Get the value: try: @@ -180,7 +216,16 @@ def get_all_compiler_versions(): k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, keyname) except WindowsError: - return [] + # For version 13 or later, check for default instance UUID + if is_win64: + keyname = 'Software\\WoW6432Node\\Intel\\Suites' + else: + keyname = 'Software\\Intel\\Suites' + try: + k = SCons.Util.RegOpenKeyEx(SCons.Util.HKEY_LOCAL_MACHINE, + keyname) + except WindowsError: + return [] i = 0 versions = [] try: @@ -192,6 +237,9 @@ def get_all_compiler_versions(): # and then the install directory deleted or moved (rather # than uninstalling properly), so the registry values # are still there. + if subkey == 'Defaults': # Ignore default instances + i = i + 1 + continue ok = False for try_abi in ('IA32', 'IA32e', 'IA64', 'EM64T'): try: @@ -267,9 +315,17 @@ def get_intel_compiler_top(version, abi): if not SCons.Util.can_read_reg: raise NoRegistryModuleError("No Windows registry module was found") top = get_intel_registry_value('ProductDir', version, abi) + archdir={'x86_64': 'intel64', + 'amd64' : 'intel64', + 'em64t' : 'intel64', + 'x86' : 'ia32', + 'i386' : 'ia32', + 'ia32' : 'ia32' + }[abi] # for v11 and greater # pre-11, icl was in Bin. 11 and later, it's in Bin/<abi> apparently. if not os.path.exists(os.path.join(top, "Bin", "icl.exe")) \ - and not os.path.exists(os.path.join(top, "Bin", abi, "icl.exe")): + and not os.path.exists(os.path.join(top, "Bin", abi, "icl.exe")) \ + and not os.path.exists(os.path.join(top, "Bin", archdir, "icl.exe")): raise MissingDirError("Can't find Intel compiler in %s"%(top)) elif is_mac or is_linux: def find_in_2008style_dir(version): diff --git a/src/engine/SCons/Tool/ldc.py b/src/engine/SCons/Tool/ldc.py new file mode 100644 index 0000000..6b215e2 --- /dev/null +++ b/src/engine/SCons/Tool/ldc.py @@ -0,0 +1,141 @@ +"""SCons.Tool.ldc + +Tool-specific initialization for the LDC compiler. +(http://www.dsource.org/projects/ldc) + +Developed by Russel Winder (russel@winder.org.uk) +2012-05-09 onwards + +Compiler variables: + DC - The name of the D compiler to use. Defaults to ldc2. + DPATH - List of paths to search for import modules. + DVERSIONS - List of version tags to enable when compiling. + DDEBUG - List of debug tags to enable when compiling. + +Linker related variables: + LIBS - List of library files to link in. + DLINK - Name of the linker to use. Defaults to ldc2. + DLINKFLAGS - List of linker flags. + +Lib tool variables: + DLIB - Name of the lib tool to use. Defaults to lib. + DLIBFLAGS - List of flags to pass to the lib tool. + LIBS - Same as for the linker. (libraries to pull into the .lib) +""" + +# +# __COPYRIGHT__ +# +# 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__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import subprocess + +import SCons.Action +import SCons.Builder +import SCons.Defaults +import SCons.Scanner.D +import SCons.Tool + +import SCons.Tool.DCommon + + +def generate(env): + static_obj, shared_obj = SCons.Tool.createObjBuilders(env) + + static_obj.add_action('.d', SCons.Defaults.DAction) + shared_obj.add_action('.d', SCons.Defaults.ShDAction) + static_obj.add_emitter('.d', SCons.Defaults.StaticObjectEmitter) + shared_obj.add_emitter('.d', SCons.Defaults.SharedObjectEmitter) + + env['DC'] = env.Detect('ldc2') + env['DCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -of=$TARGET $SOURCES' + env['_DINCFLAGS'] = '$( ${_concat(DINCPREFIX, DPATH, DINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' + env['_DVERFLAGS'] = '$( ${_concat(DVERPREFIX, DVERSIONS, DVERSUFFIX, __env__)} $)' + env['_DDEBUGFLAGS'] = '$( ${_concat(DDEBUGPREFIX, DDEBUG, DDEBUGSUFFIX, __env__)} $)' + env['_DFLAGS'] = '$( ${_concat(DFLAGPREFIX, DFLAGS, DFLAGSUFFIX, __env__)} $)' + + env['SHDC'] = '$DC' + env['SHDCOM'] = '$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -c -relocation-model=pic -of=$TARGET $SOURCES' + + env['DPATH'] = ['#/'] + env['DFLAGS'] = [] + env['DVERSIONS'] = [] + env['DDEBUG'] = [] + + if env['DC']: + SCons.Tool.DCommon.addDPATHToEnv(env, env['DC']) + + env['DINCPREFIX'] = '-I=' + env['DINCSUFFIX'] = '' + env['DVERPREFIX'] = '-version=' + env['DVERSUFFIX'] = '' + env['DDEBUGPREFIX'] = '-debug=' + env['DDEBUGSUFFIX'] = '' + env['DFLAGPREFIX'] = '-' + env['DFLAGSUFFIX'] = '' + env['DFILESUFFIX'] = '.d' + + env['DLINK'] = '$DC' + env['DLINKFLAGS'] = SCons.Util.CLVar('') + env['DLINKCOM'] = '$DLINK -of=$TARGET $DLINKFLAGS $__DRPATH $SOURCES $_DLIBDIRFLAGS $_DLIBFLAGS' + + env['DSHLINK'] = '$DC' + env['DSHLINKFLAGS'] = SCons.Util.CLVar('$DLINKFLAGS -shared') + env['SHDLINKCOM'] = '$DLINK -of=$TARGET $DSHLINKFLAGS $__DRPATH $SOURCES $_DLIBDIRFLAGS $_DLIBFLAGS' + + env['DLIBLINKPREFIX'] = '' if env['PLATFORM'] == 'win32' else '-L-l' + env['DLIBLINKSUFFIX'] = '.lib' if env['PLATFORM'] == 'win32' else '' + #env['_DLIBFLAGS'] = '$( ${_concat(DLIBLINKPREFIX, LIBS, DLIBLINKSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' + env['_DLIBFLAGS'] = '${_stripixes(DLIBLINKPREFIX, LIBS, DLIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}' + + env['DLIBDIRPREFIX'] = '-L-L' + env['DLIBDIRSUFFIX'] = '' + env['_DLIBDIRFLAGS'] = '$( ${_concat(DLIBDIRPREFIX, LIBPATH, DLIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' + + + env['DLIB'] = 'lib' if env['PLATFORM'] == 'win32' else 'ar cr' + env['DLIBCOM'] = '$DLIB $_DLIBFLAGS {0}$TARGET $SOURCES $_DLIBFLAGS'.format('-c ' if env['PLATFORM'] == 'win32' else '') + + #env['_DLIBFLAGS'] = '$( ${_concat(DLIBFLAGPREFIX, DLIBFLAGS, DLIBFLAGSUFFIX, __env__)} $)' + + env['DLIBFLAGPREFIX'] = '-' + env['DLIBFLAGSUFFIX'] = '' + + # __RPATH is set to $_RPATH in the platform specification if that + # platform supports it. + env['DRPATHPREFIX'] = '-L-rpath=' + env['DRPATHSUFFIX'] = '' + env['_RPATH'] = '${_concat(DRPATHPREFIX, RPATH, DRPATHSUFFIX, __env__)}' + + SCons.Tool.createStaticLibBuilder(env) + + +def exists(env): + return env.Detect('ldc2') + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/ldc.xml b/src/engine/SCons/Tool/ldc.xml new file mode 100644 index 0000000..f07144b --- /dev/null +++ b/src/engine/SCons/Tool/ldc.xml @@ -0,0 +1,81 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- +__COPYRIGHT__ + +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; +]> + +<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/scons.xsd"> + +<tool name="ldc"> +<summary> +<para> +Sets construction variables for the D language compiler LDC2. +</para> +</summary> +<sets> +<item>DC</item> +<item>DCOM</item> +<item>_DINCFLAGS</item> +<item>_DVERFLAGS</item> +<item>_DDEBUGFLAGS</item> +<item>_DFLAGS</item> +<item>SHDC</item> +<item>SHDCOM</item> +<item>DPATH</item> +<item>DFLAGS</item> +<item>DVERSIONS</item> +<item>DDEBUG</item> +<item>DINCPREFIX</item> +<item>DINCSUFFIX</item> +<item>DVERPREFIX</item> +<item>DVERSUFFIX</item> +<item>DDEBUGPREFIX</item> +<item>DDEBUGSUFFIX</item> +<item>DFLAGPREFIX</item> +<item>DFLAGSUFFIX</item> +<item>DFILESUFFIX</item> +<item>DLINK</item> +<item>DLINKFLAGS</item> +<item>DLINKCOM</item> +<item>SHDLINK</item> +<item>SHDLINKFLAGS</item> +<item>SHDLINKCOM</item> +<item>DLIBLINKPREFIX</item> +<item>DLIBLINKSUFFIX</item> +<item>_DLIBFLAGS</item> +<item>DLIBDIRPREFIX</item> +<item>DLIBDIRSUFFIX</item> +<item>_DLIBDIRFLAGS</item> +<item>DLIB</item> +<item>DLIBCOM</item> +<item>_DLIBFLAGS</item> +<item>DLIBFLAGPREFIX</item> +<item>DLIBFLAGSUFFIX</item> +<item>DLINKFLAGPREFIX</item> +<item>DLINKFLAGSUFFIX</item> +<item>RPATHPREFIX</item> +<item>RPATHSUFFIX</item> +<item>_RPATH</item> +</sets> +<uses> +</uses> +</tool> + +</sconsdoc> diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index c7c6790..1b03075 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -43,6 +43,7 @@ import SCons.Warnings from SCons.Tool.FortranCommon import isfortran +from SCons.Tool.DCommon import isD cplusplus = __import__(__package__+'.c++', globals(), locals(), ['*']) issued_mixed_link_warning = False @@ -50,7 +51,8 @@ issued_mixed_link_warning = False def smart_link(source, target, env, for_signature): has_cplusplus = cplusplus.iscplusplus(source) has_fortran = isfortran(env, source) - if has_cplusplus and has_fortran: + 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" + \ @@ -60,6 +62,10 @@ def smart_link(source, target, env, for_signature): msg % env.subst('$CXX')) issued_mixed_link_warning = True return '$CXX' + elif has_d: + env['LINKCOM'] = env['DLINKCOM'] + env['SHLINKCOM'] = env['SHDLINKCOM'] + return '$DC' elif has_fortran: return '$FORTRAN' elif has_cplusplus: @@ -139,7 +145,7 @@ def shlib_emitter_names(target, source, env): print("shlib_emitter_names: side effect: ", name) # add version_name to list of names to be a Side effect version_names.append(version_name) - + except KeyError: version = None return version_names @@ -179,8 +185,8 @@ def generate(env): # don't set up the emitter, cause AppendUnique will generate a list # starting with None :-( env.Append(LDMODULEEMITTER='$SHLIBEMITTER') - env['LDMODULEPREFIX'] = '$SHLIBPREFIX' - env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' + env['LDMODULEPREFIX'] = '$SHLIBPREFIX' + env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' env['LDMODULEFLAGS'] = '$SHLINKFLAGS' env['LDMODULECOM'] = '$LDMODULE -o $TARGET $LDMODULEFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' diff --git a/src/engine/SCons/Tool/link.xml b/src/engine/SCons/Tool/link.xml index d357648..d58b9e2 100644 --- a/src/engine/SCons/Tool/link.xml +++ b/src/engine/SCons/Tool/link.xml @@ -223,4 +223,13 @@ for the variable that expands to library search path options. </summary> </cvar> +<cvar name="STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME"> + <summary> + <para> + When this variable is true, static objects and shared objects are assumed to be the same; that is, SCons does not check for linking static objects into a shared library. + </para> + </summary> +</cvar> + + </sconsdoc> diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py index a9e0fa2..9bd7dbb 100644 --- a/src/engine/SCons/Tool/packaging/rpm.py +++ b/src/engine/SCons/Tool/packaging/rpm.py @@ -182,7 +182,7 @@ def build_specfile_sections(spec): spec['X_RPM_PREP'] = '[ -n "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && rm -rf "$RPM_BUILD_ROOT"' + '\n%setup -q' if 'X_RPM_BUILD' not in spec: - spec['X_RPM_BUILD'] = 'mkdir "$RPM_BUILD_ROOT"' + spec['X_RPM_BUILD'] = '[ ! -e "$RPM_BUILD_ROOT" -a "$RPM_BUILD_ROOT" != / ] && mkdir "$RPM_BUILD_ROOT"' if 'X_RPM_INSTALL' not in spec: spec['X_RPM_INSTALL'] = 'scons --install-sandbox="$RPM_BUILD_ROOT" "$RPM_BUILD_ROOT"' diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index 5d2264c..f669f83 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -174,7 +174,8 @@ def generate(env): env.Append(SCANNERS = scanner) def exists(env): - return env.Detect(['swig']) + swig = env.get('SWIG') or env.Detect(['swig']) + return swig # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index dac98b7..0bf3792 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -103,6 +103,7 @@ makeacronyms_re = re.compile(r"^[^%\n]*\\makeglossaries", re.MULTILINE) beamer_re = re.compile(r"^[^%\n]*\\documentclass\{beamer\}", re.MULTILINE) regex = r'^[^%\n]*\\newglossary\s*\[([^\]]+)\]?\s*\{([^}]*)\}\s*\{([^}]*)\}\s*\{([^}]*)\}\s*\{([^}]*)\}' newglossary_re = re.compile(regex, re.MULTILINE) +biblatex_re = re.compile(r"^[^%\n]*\\usepackage.*\{biblatex\}", re.MULTILINE) newglossary_suffix = [] @@ -431,7 +432,7 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None if Verbose: print("Need to run makeindex for newglossary") newglfile = suffix_nodes[newglossary_suffix[ig][2]] - MakeNewGlossaryAction = SCons.Action.Action("$MAKENEWGLOSSARY ${SOURCE.filebase}%s -s ${SOURCE.filebase}.ist -t ${SOURCE.filebase}%s -o ${SOURCE.filebase}%s" % (newglossary_suffix[ig][2],newglossary_suffix[ig][0],newglossary_suffix[ig][1]), "$MAKENEWGLOSSARYCOMSTR") + MakeNewGlossaryAction = SCons.Action.Action("$MAKENEWGLOSSARYCOM ${SOURCE.filebase}%s -s ${SOURCE.filebase}.ist -t ${SOURCE.filebase}%s -o ${SOURCE.filebase}%s" % (newglossary_suffix[ig][2],newglossary_suffix[ig][0],newglossary_suffix[ig][1]), "$MAKENEWGLOSSARYCOMSTR") result = MakeNewGlossaryAction(newglfile, newglfile, env) if result != 0: @@ -640,7 +641,7 @@ def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi newglossary_suffix.append(suffix_list) if Verbose: print(" new suffixes for newglossary ",newglossary_suffix) - + incResult = includeOnly_re.search(content) if incResult: @@ -685,15 +686,18 @@ def tex_emitter_core(target, source, env, graphics_extensions): auxfilename = targetbase + '.aux' logfilename = targetbase + '.log' flsfilename = targetbase + '.fls' + syncfilename = targetbase + '.synctex.gz' env.SideEffect(auxfilename,target[0]) env.SideEffect(logfilename,target[0]) env.SideEffect(flsfilename,target[0]) + env.SideEffect(syncfilename,target[0]) if Verbose: - print("side effect :",auxfilename,logfilename,flsfilename) + print("side effect :",auxfilename,logfilename,flsfilename,syncfilename) env.Clean(target[0],auxfilename) env.Clean(target[0],logfilename) env.Clean(target[0],flsfilename) + env.Clean(target[0],syncfilename) content = source[0].get_text_contents() @@ -720,7 +724,8 @@ def tex_emitter_core(target, source, env, graphics_extensions): makeglossaries_re, makeacronyms_re, beamer_re, - newglossary_re ] + newglossary_re, + biblatex_re ] # set up list with the file suffixes that need emitting # when a feature is found file_tests_suff = [['.aux','aux_file'], @@ -738,7 +743,8 @@ def tex_emitter_core(target, source, env, graphics_extensions): ['.glo', '.gls', '.glg','glossaries'], ['.acn', '.acr', '.alg','acronyms'], ['.nav', '.snm', '.out', '.toc','beamer'], - ['newglossary',] ] + ['newglossary',], + ['.bcf', '.blg','biblatex'] ] # for newglossary the suffixes are added as we find the command # build the list of lists file_tests = [] @@ -854,7 +860,7 @@ def generate_darwin(env): except KeyError: environ = {} env['ENV'] = environ - + if (platform.system() == 'Darwin'): try: ospath = env['ENV']['PATHOSX'] diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index ca6acee..5c27825 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -54,6 +54,9 @@ class CorruptSConsignWarning(WarningOnByDefault): class DependencyWarning(Warning): pass +class DevelopmentVersionWarning(WarningOnByDefault): + pass + class DuplicateEnvironmentWarning(WarningOnByDefault): pass diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index 0ba10f5..60cfcea 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -395,9 +395,10 @@ class PreProcessor(object): """ d = self.dispatch_table - d['import'] = self.do_import - d['include'] = self.do_include - d['include_next'] = self.do_include + p = self.stack[-1] if self.stack else self.default_table + + for k in ('import', 'include', 'include_next'): + d[k] = p[k] def stop_handling_includes(self, t=None): """ diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index 5a06bee..37b4aae 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -327,6 +327,22 @@ no_space_input = """ """ +nested_ifs_input = """ +#define DEFINED + +#ifdef NOT_DEFINED + #include "file7-no" + #ifdef DEFINED + #include "file8-no" + #else + #include "file9-no" + #endif +#else + #include "file7-yes" +#endif +""" + + # pp_class = PreProcessor # #pp_class = DumbPreProcessor @@ -403,6 +419,11 @@ class cppTestCase(unittest.TestCase): result = self.cpp.process_contents(no_space_input) assert expect == result, (expect, result) + def test_nested_ifs(self): + expect = self.nested_ifs_expect + result = self.cpp.process_contents(nested_ifs_input) + assert expect == result, (expect, result) + class cppAllTestCase(cppTestCase): def setUp(self): self.cpp = self.cpp_class(current = ".", @@ -486,6 +507,10 @@ class PreProcessorTestCase(cppAllTestCase): ('include', '"', 'file44-yes'), ] + nested_ifs_expect = [ + ('include', '"', 'file7-yes'), + ] + class DumbPreProcessorTestCase(cppAllTestCase): cpp_class = cpp.DumbPreProcessor @@ -591,6 +616,13 @@ class DumbPreProcessorTestCase(cppAllTestCase): ('include', '"', 'file44-yes'), ] + nested_ifs_expect = [ + ('include', '"', 'file7-no'), + ('include', '"', 'file8-no'), + ('include', '"', 'file9-no'), + ('include', '"', 'file7-yes') + ] + import os |