From baee03c569c91b745a1e025660b19a718db16e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Thu, 28 Sep 2017 12:18:58 +0200 Subject: New upstream version 3.0.0 --- src/engine/MANIFEST-xml.in | 1 + src/engine/MANIFEST.in | 20 +- src/engine/SCons/Action.py | 378 ++++++++---- src/engine/SCons/Action.xml | 2 +- src/engine/SCons/ActionTests.py | 280 ++++++--- src/engine/SCons/Builder.py | 49 +- src/engine/SCons/BuilderTests.py | 47 +- src/engine/SCons/CacheDir.py | 4 +- src/engine/SCons/CacheDirTests.py | 8 +- src/engine/SCons/Conftest.py | 45 +- src/engine/SCons/Debug.py | 8 +- src/engine/SCons/Defaults.py | 23 +- src/engine/SCons/Defaults.xml | 2 +- src/engine/SCons/DefaultsTests.py | 6 +- src/engine/SCons/Environment.py | 80 +-- src/engine/SCons/Environment.xml | 31 +- src/engine/SCons/EnvironmentTests.py | 74 ++- src/engine/SCons/EnvironmentValues.py | 97 +++ src/engine/SCons/EnvironmentValuesTest.py | 16 + src/engine/SCons/Errors.py | 128 ++-- src/engine/SCons/ErrorsTests.py | 16 +- src/engine/SCons/Executor.py | 25 +- src/engine/SCons/ExecutorTests.py | 41 +- src/engine/SCons/Job.py | 8 +- src/engine/SCons/JobTests.py | 4 +- src/engine/SCons/Memoize.py | 20 +- src/engine/SCons/MemoizeTests.py | 5 +- src/engine/SCons/Node/Alias.py | 4 +- src/engine/SCons/Node/AliasTests.py | 4 +- src/engine/SCons/Node/FS.py | 321 +++++----- src/engine/SCons/Node/FSTests.py | 113 ++-- src/engine/SCons/Node/NodeTests.py | 4 +- src/engine/SCons/Node/Python.py | 21 +- src/engine/SCons/Node/PythonTests.py | 10 +- src/engine/SCons/Node/__init__.py | 118 ++-- src/engine/SCons/Options/BoolOption.py | 4 +- src/engine/SCons/Options/EnumOption.py | 4 +- src/engine/SCons/Options/ListOption.py | 4 +- src/engine/SCons/Options/PackageOption.py | 4 +- src/engine/SCons/Options/PathOption.py | 4 +- src/engine/SCons/Options/__init__.py | 14 +- src/engine/SCons/PathList.py | 8 +- src/engine/SCons/PathListTests.py | 4 +- src/engine/SCons/Platform/PlatformTests.py | 4 +- src/engine/SCons/Platform/__init__.py | 25 +- src/engine/SCons/Platform/__init__.xml | 2 +- src/engine/SCons/Platform/aix.py | 6 +- src/engine/SCons/Platform/cygwin.py | 6 +- src/engine/SCons/Platform/darwin.py | 10 +- src/engine/SCons/Platform/hpux.py | 6 +- src/engine/SCons/Platform/irix.py | 6 +- src/engine/SCons/Platform/os2.py | 6 +- src/engine/SCons/Platform/posix.py | 6 +- src/engine/SCons/Platform/posix.xml | 2 +- src/engine/SCons/Platform/sunos.py | 6 +- src/engine/SCons/Platform/sunos.xml | 2 +- src/engine/SCons/Platform/win32.py | 113 +++- src/engine/SCons/Platform/win32.xml | 2 +- src/engine/SCons/SConf.py | 51 +- src/engine/SCons/SConfTests.py | 61 +- src/engine/SCons/SConsign.py | 39 +- src/engine/SCons/SConsignTests.py | 4 +- src/engine/SCons/Scanner/C.py | 11 +- src/engine/SCons/Scanner/CTests.py | 4 +- src/engine/SCons/Scanner/D.py | 20 +- src/engine/SCons/Scanner/DTests.py | 282 +++++++++ src/engine/SCons/Scanner/Dir.py | 6 +- src/engine/SCons/Scanner/DirTests.py | 4 +- src/engine/SCons/Scanner/Fortran.py | 4 +- src/engine/SCons/Scanner/FortranTests.py | 4 +- src/engine/SCons/Scanner/IDL.py | 4 +- src/engine/SCons/Scanner/IDLTests.py | 4 +- src/engine/SCons/Scanner/LaTeX.py | 129 ++-- src/engine/SCons/Scanner/LaTeXTests.py | 19 +- src/engine/SCons/Scanner/Prog.py | 4 +- src/engine/SCons/Scanner/ProgTests.py | 6 +- src/engine/SCons/Scanner/RC.py | 27 +- src/engine/SCons/Scanner/RCTests.py | 4 +- src/engine/SCons/Scanner/SWIG.py | 4 +- src/engine/SCons/Scanner/ScannerTests.py | 38 +- src/engine/SCons/Scanner/__init__.py | 42 +- src/engine/SCons/Scanner/__init__.xml | 2 +- src/engine/SCons/Script/Interactive.py | 36 +- src/engine/SCons/Script/Main.py | 91 +-- src/engine/SCons/Script/Main.xml | 14 +- src/engine/SCons/Script/MainTests.py | 4 +- src/engine/SCons/Script/SConsOptions.py | 28 +- src/engine/SCons/Script/SConscript.py | 35 +- src/engine/SCons/Script/SConscript.xml | 2 +- src/engine/SCons/Script/SConscriptTests.py | 4 +- src/engine/SCons/Script/__init__.py | 23 +- src/engine/SCons/Sig.py | 63 -- src/engine/SCons/Subst.py | 39 +- src/engine/SCons/Subst.xml | 2 +- src/engine/SCons/SubstTests.py | 83 ++- src/engine/SCons/Taskmaster.py | 96 +-- src/engine/SCons/TaskmasterTests.py | 43 +- src/engine/SCons/Tool/386asm.py | 6 +- src/engine/SCons/Tool/386asm.xml | 2 +- src/engine/SCons/Tool/BitKeeper.py | 66 --- src/engine/SCons/Tool/BitKeeper.xml | 123 ---- src/engine/SCons/Tool/CVS.py | 72 --- src/engine/SCons/Tool/CVS.xml | 159 ----- src/engine/SCons/Tool/DCommon.py | 17 +- src/engine/SCons/Tool/DCommon.xml | 71 +++ src/engine/SCons/Tool/FortranCommon.py | 17 +- src/engine/SCons/Tool/GettextCommon.py | 654 +++++++++++---------- src/engine/SCons/Tool/JavaCommon.py | 4 +- src/engine/SCons/Tool/JavaCommonTests.py | 4 +- src/engine/SCons/Tool/MSCommon/__init__.py | 7 +- src/engine/SCons/Tool/MSCommon/arch.py | 4 +- src/engine/SCons/Tool/MSCommon/common.py | 100 ++-- src/engine/SCons/Tool/MSCommon/netframework.py | 14 +- src/engine/SCons/Tool/MSCommon/sdk.py | 51 +- src/engine/SCons/Tool/MSCommon/vc.py | 162 +++-- src/engine/SCons/Tool/MSCommon/vs.py | 31 +- src/engine/SCons/Tool/Perforce.py | 99 ---- src/engine/SCons/Tool/Perforce.xml | 129 ---- src/engine/SCons/Tool/PharLapCommon.py | 4 +- src/engine/SCons/Tool/RCS.py | 63 -- src/engine/SCons/Tool/RCS.xml | 142 ----- src/engine/SCons/Tool/SCCS.py | 63 -- src/engine/SCons/Tool/SCCS.xml | 133 ----- src/engine/SCons/Tool/Subversion.py | 70 --- src/engine/SCons/Tool/Subversion.xml | 135 ----- src/engine/SCons/Tool/ToolTests.py | 4 +- src/engine/SCons/Tool/__init__.py | 286 ++++++--- src/engine/SCons/Tool/__init__.xml | 2 +- src/engine/SCons/Tool/aixc++.py | 40 +- src/engine/SCons/Tool/aixc++.xml | 2 +- src/engine/SCons/Tool/aixcc.py | 6 +- src/engine/SCons/Tool/aixcc.xml | 2 +- src/engine/SCons/Tool/aixcxx.py | 77 +++ src/engine/SCons/Tool/aixf77.py | 6 +- src/engine/SCons/Tool/aixf77.xml | 2 +- src/engine/SCons/Tool/aixlink.py | 12 +- src/engine/SCons/Tool/aixlink.xml | 2 +- src/engine/SCons/Tool/applelink.py | 14 +- src/engine/SCons/Tool/applelink.xml | 2 +- src/engine/SCons/Tool/ar.py | 8 +- src/engine/SCons/Tool/ar.xml | 2 +- src/engine/SCons/Tool/as.py | 4 +- src/engine/SCons/Tool/as.xml | 2 +- src/engine/SCons/Tool/bcc32.py | 4 +- src/engine/SCons/Tool/bcc32.xml | 2 +- src/engine/SCons/Tool/c++.py | 64 +- src/engine/SCons/Tool/c++.xml | 2 +- src/engine/SCons/Tool/cc.py | 4 +- src/engine/SCons/Tool/cc.xml | 2 +- src/engine/SCons/Tool/clang.py | 83 +++ src/engine/SCons/Tool/clang.xml | 39 ++ src/engine/SCons/Tool/clangxx.py | 91 +++ src/engine/SCons/Tool/clangxx.xml | 41 ++ src/engine/SCons/Tool/cvf.py | 6 +- src/engine/SCons/Tool/cvf.xml | 2 +- src/engine/SCons/Tool/cxx.py | 100 ++++ src/engine/SCons/Tool/cyglink.py | 50 +- src/engine/SCons/Tool/cyglink.xml | 2 +- src/engine/SCons/Tool/default.py | 4 +- src/engine/SCons/Tool/default.xml | 2 +- src/engine/SCons/Tool/dmd.py | 48 +- src/engine/SCons/Tool/dmd.xml | 314 +++++++++- src/engine/SCons/Tool/docbook/__init__.py | 29 +- src/engine/SCons/Tool/docbook/__init__.xml | 2 +- .../docbook-xsl-1.76.1/extensions/docbook.py | 11 +- .../docbook/docbook-xsl-1.76.1/extensions/xslt.py | 13 +- src/engine/SCons/Tool/dvi.py | 4 +- src/engine/SCons/Tool/dvi.xml | 2 +- src/engine/SCons/Tool/dvipdf.py | 8 +- src/engine/SCons/Tool/dvipdf.xml | 2 +- src/engine/SCons/Tool/dvips.py | 4 +- src/engine/SCons/Tool/dvips.xml | 2 +- src/engine/SCons/Tool/f03.py | 6 +- src/engine/SCons/Tool/f03.xml | 2 +- src/engine/SCons/Tool/f08.py | 8 +- src/engine/SCons/Tool/f08.xml | 2 +- src/engine/SCons/Tool/f77.py | 4 +- src/engine/SCons/Tool/f77.xml | 2 +- src/engine/SCons/Tool/f90.py | 4 +- src/engine/SCons/Tool/f90.xml | 2 +- src/engine/SCons/Tool/f95.py | 6 +- src/engine/SCons/Tool/f95.xml | 2 +- src/engine/SCons/Tool/filesystem.py | 6 +- src/engine/SCons/Tool/fortran.py | 4 +- src/engine/SCons/Tool/fortran.xml | 2 +- src/engine/SCons/Tool/g++.py | 43 +- src/engine/SCons/Tool/g++.xml | 2 +- src/engine/SCons/Tool/g77.py | 4 +- src/engine/SCons/Tool/g77.xml | 2 +- src/engine/SCons/Tool/gas.py | 9 +- src/engine/SCons/Tool/gas.xml | 2 +- src/engine/SCons/Tool/gcc.py | 10 +- src/engine/SCons/Tool/gcc.xml | 2 +- src/engine/SCons/Tool/gdc.py | 34 +- src/engine/SCons/Tool/gdc.xml | 356 ++++++----- src/engine/SCons/Tool/gettext.py | 48 -- src/engine/SCons/Tool/gettext.xml | 2 +- src/engine/SCons/Tool/gettext_tool.py | 48 ++ src/engine/SCons/Tool/gfortran.py | 6 +- src/engine/SCons/Tool/gfortran.xml | 2 +- src/engine/SCons/Tool/gnulink.py | 6 +- src/engine/SCons/Tool/gnulink.xml | 2 +- src/engine/SCons/Tool/gs.py | 8 +- src/engine/SCons/Tool/gs.xml | 2 +- src/engine/SCons/Tool/gxx.py | 79 +++ src/engine/SCons/Tool/hpc++.py | 47 +- src/engine/SCons/Tool/hpc++.xml | 2 +- src/engine/SCons/Tool/hpcc.py | 6 +- src/engine/SCons/Tool/hpcc.xml | 2 +- src/engine/SCons/Tool/hpcxx.py | 87 +++ src/engine/SCons/Tool/hplink.py | 6 +- src/engine/SCons/Tool/hplink.xml | 2 +- src/engine/SCons/Tool/icc.py | 6 +- src/engine/SCons/Tool/icc.xml | 2 +- src/engine/SCons/Tool/icl.py | 4 +- src/engine/SCons/Tool/icl.xml | 2 +- src/engine/SCons/Tool/ifl.py | 6 +- src/engine/SCons/Tool/ifl.xml | 2 +- src/engine/SCons/Tool/ifort.py | 6 +- src/engine/SCons/Tool/ifort.xml | 2 +- src/engine/SCons/Tool/ilink.py | 4 +- src/engine/SCons/Tool/ilink.xml | 2 +- src/engine/SCons/Tool/ilink32.py | 4 +- src/engine/SCons/Tool/ilink32.xml | 2 +- src/engine/SCons/Tool/install.py | 25 +- src/engine/SCons/Tool/install.xml | 2 +- src/engine/SCons/Tool/intelc.py | 25 +- src/engine/SCons/Tool/intelc.xml | 2 +- src/engine/SCons/Tool/ipkg.py | 28 +- src/engine/SCons/Tool/jar.py | 4 +- src/engine/SCons/Tool/jar.xml | 2 +- src/engine/SCons/Tool/javac.py | 4 +- src/engine/SCons/Tool/javac.xml | 2 +- src/engine/SCons/Tool/javacTests.py | 2 +- src/engine/SCons/Tool/javah.py | 4 +- src/engine/SCons/Tool/javah.xml | 2 +- src/engine/SCons/Tool/latex.py | 8 +- src/engine/SCons/Tool/latex.xml | 2 +- src/engine/SCons/Tool/ldc.py | 47 +- src/engine/SCons/Tool/ldc.xml | 312 +++++++++- src/engine/SCons/Tool/lex.py | 4 +- src/engine/SCons/Tool/lex.xml | 2 +- src/engine/SCons/Tool/link.py | 70 ++- src/engine/SCons/Tool/link.xml | 2 +- src/engine/SCons/Tool/linkloc.py | 8 +- src/engine/SCons/Tool/linkloc.xml | 2 +- src/engine/SCons/Tool/m4.py | 4 +- src/engine/SCons/Tool/m4.xml | 2 +- src/engine/SCons/Tool/masm.py | 4 +- src/engine/SCons/Tool/masm.xml | 2 +- src/engine/SCons/Tool/midl.py | 18 +- src/engine/SCons/Tool/midl.xml | 2 +- src/engine/SCons/Tool/mingw.py | 7 +- src/engine/SCons/Tool/mingw.xml | 2 +- src/engine/SCons/Tool/msgfmt.py | 6 +- src/engine/SCons/Tool/msgfmt.xml | 2 +- src/engine/SCons/Tool/msginit.py | 8 +- src/engine/SCons/Tool/msginit.xml | 2 +- src/engine/SCons/Tool/msgmerge.py | 6 +- src/engine/SCons/Tool/msgmerge.xml | 2 +- src/engine/SCons/Tool/mslib.py | 6 +- src/engine/SCons/Tool/mslib.xml | 2 +- src/engine/SCons/Tool/mslink.py | 19 +- src/engine/SCons/Tool/mslink.xml | 2 +- src/engine/SCons/Tool/mssdk.py | 6 +- src/engine/SCons/Tool/mssdk.xml | 2 +- src/engine/SCons/Tool/msvc.py | 25 +- src/engine/SCons/Tool/msvc.xml | 27 +- src/engine/SCons/Tool/msvs.py | 214 +++---- src/engine/SCons/Tool/msvs.xml | 12 +- src/engine/SCons/Tool/msvsTests.py | 17 +- src/engine/SCons/Tool/mwcc.py | 4 +- src/engine/SCons/Tool/mwcc.xml | 2 +- src/engine/SCons/Tool/mwld.py | 4 +- src/engine/SCons/Tool/mwld.xml | 2 +- src/engine/SCons/Tool/nasm.py | 4 +- src/engine/SCons/Tool/nasm.xml | 2 +- src/engine/SCons/Tool/packaging.xml | 2 +- src/engine/SCons/Tool/packaging/__init__.py | 16 +- src/engine/SCons/Tool/packaging/__init__.xml | 2 +- src/engine/SCons/Tool/packaging/ipk.py | 6 +- src/engine/SCons/Tool/packaging/msi.py | 6 +- src/engine/SCons/Tool/packaging/rpm.py | 17 +- src/engine/SCons/Tool/packaging/src_tarbz2.py | 4 +- src/engine/SCons/Tool/packaging/src_targz.py | 4 +- src/engine/SCons/Tool/packaging/src_zip.py | 4 +- src/engine/SCons/Tool/packaging/tarbz2.py | 4 +- src/engine/SCons/Tool/packaging/targz.py | 4 +- src/engine/SCons/Tool/packaging/zip.py | 4 +- src/engine/SCons/Tool/pdf.py | 4 +- src/engine/SCons/Tool/pdf.xml | 2 +- src/engine/SCons/Tool/pdflatex.py | 6 +- src/engine/SCons/Tool/pdflatex.xml | 2 +- src/engine/SCons/Tool/pdftex.py | 6 +- src/engine/SCons/Tool/pdftex.xml | 2 +- src/engine/SCons/Tool/qt.py | 25 +- src/engine/SCons/Tool/qt.xml | 2 +- src/engine/SCons/Tool/rmic.py | 4 +- src/engine/SCons/Tool/rmic.xml | 2 +- src/engine/SCons/Tool/rpcgen.py | 4 +- src/engine/SCons/Tool/rpcgen.xml | 2 +- src/engine/SCons/Tool/rpm.py | 6 +- src/engine/SCons/Tool/rpmutils.py | 14 +- src/engine/SCons/Tool/sgiar.py | 4 +- src/engine/SCons/Tool/sgiar.xml | 2 +- src/engine/SCons/Tool/sgic++.py | 23 +- src/engine/SCons/Tool/sgic++.xml | 2 +- src/engine/SCons/Tool/sgicc.py | 6 +- src/engine/SCons/Tool/sgicc.xml | 2 +- src/engine/SCons/Tool/sgicxx.py | 61 ++ src/engine/SCons/Tool/sgilink.py | 6 +- src/engine/SCons/Tool/sgilink.xml | 2 +- src/engine/SCons/Tool/sunar.py | 4 +- src/engine/SCons/Tool/sunar.xml | 2 +- src/engine/SCons/Tool/sunc++.py | 105 +--- src/engine/SCons/Tool/sunc++.xml | 2 +- src/engine/SCons/Tool/suncc.py | 6 +- src/engine/SCons/Tool/suncc.xml | 2 +- src/engine/SCons/Tool/suncxx.py | 144 +++++ src/engine/SCons/Tool/sunf77.py | 6 +- src/engine/SCons/Tool/sunf77.xml | 2 +- src/engine/SCons/Tool/sunf90.py | 6 +- src/engine/SCons/Tool/sunf90.xml | 2 +- src/engine/SCons/Tool/sunf95.py | 6 +- src/engine/SCons/Tool/sunf95.xml | 2 +- src/engine/SCons/Tool/sunlink.py | 6 +- src/engine/SCons/Tool/sunlink.xml | 2 +- src/engine/SCons/Tool/swig.py | 14 +- src/engine/SCons/Tool/swig.xml | 2 +- src/engine/SCons/Tool/tar.py | 4 +- src/engine/SCons/Tool/tar.xml | 2 +- src/engine/SCons/Tool/tex.py | 115 ++-- src/engine/SCons/Tool/tex.xml | 2 +- src/engine/SCons/Tool/textfile.py | 115 ++-- src/engine/SCons/Tool/textfile.xml | 4 +- src/engine/SCons/Tool/tlib.py | 4 +- src/engine/SCons/Tool/tlib.xml | 2 +- src/engine/SCons/Tool/wix.py | 4 +- src/engine/SCons/Tool/wixTests.py | 4 +- src/engine/SCons/Tool/xgettext.py | 555 ++++++++--------- src/engine/SCons/Tool/xgettext.xml | 2 +- src/engine/SCons/Tool/yacc.py | 4 +- src/engine/SCons/Tool/yacc.xml | 2 +- src/engine/SCons/Tool/zip.py | 46 +- src/engine/SCons/Tool/zip.xml | 2 +- src/engine/SCons/Util.py | 256 +++++--- src/engine/SCons/UtilTests.py | 59 +- src/engine/SCons/Variables/BoolVariable.py | 14 +- src/engine/SCons/Variables/BoolVariableTests.py | 4 +- src/engine/SCons/Variables/EnumVariable.py | 28 +- src/engine/SCons/Variables/EnumVariableTests.py | 4 +- src/engine/SCons/Variables/ListVariable.py | 16 +- src/engine/SCons/Variables/ListVariableTests.py | 4 +- src/engine/SCons/Variables/PackageVariable.py | 28 +- src/engine/SCons/Variables/PackageVariableTests.py | 4 +- src/engine/SCons/Variables/PathVariable.py | 13 +- src/engine/SCons/Variables/PathVariableTests.py | 20 +- src/engine/SCons/Variables/VariablesTests.py | 14 +- src/engine/SCons/Variables/__init__.py | 43 +- src/engine/SCons/Warnings.py | 4 +- src/engine/SCons/WarningsTests.py | 4 +- src/engine/SCons/__init__.py | 12 +- src/engine/SCons/__main__.py | 4 + src/engine/SCons/compat/__init__.py | 92 ++- src/engine/SCons/compat/_scons_dbm.py | 4 +- src/engine/SCons/cpp.py | 26 +- src/engine/SCons/cppTests.py | 6 +- src/engine/SCons/dblite.py | 438 +++++++------- src/engine/SCons/exitfuncs.py | 4 +- 369 files changed, 6692 insertions(+), 5147 deletions(-) create mode 100644 src/engine/SCons/EnvironmentValues.py create mode 100644 src/engine/SCons/EnvironmentValuesTest.py create mode 100644 src/engine/SCons/Scanner/DTests.py delete mode 100644 src/engine/SCons/Sig.py delete mode 100644 src/engine/SCons/Tool/BitKeeper.py delete mode 100644 src/engine/SCons/Tool/BitKeeper.xml delete mode 100644 src/engine/SCons/Tool/CVS.py delete mode 100644 src/engine/SCons/Tool/CVS.xml create mode 100644 src/engine/SCons/Tool/DCommon.xml delete mode 100644 src/engine/SCons/Tool/Perforce.py delete mode 100644 src/engine/SCons/Tool/Perforce.xml delete mode 100644 src/engine/SCons/Tool/RCS.py delete mode 100644 src/engine/SCons/Tool/RCS.xml delete mode 100644 src/engine/SCons/Tool/SCCS.py delete mode 100644 src/engine/SCons/Tool/SCCS.xml delete mode 100644 src/engine/SCons/Tool/Subversion.py delete mode 100644 src/engine/SCons/Tool/Subversion.xml create mode 100644 src/engine/SCons/Tool/aixcxx.py create mode 100644 src/engine/SCons/Tool/clang.py create mode 100644 src/engine/SCons/Tool/clang.xml create mode 100644 src/engine/SCons/Tool/clangxx.py create mode 100644 src/engine/SCons/Tool/clangxx.xml create mode 100644 src/engine/SCons/Tool/cxx.py delete mode 100644 src/engine/SCons/Tool/gettext.py create mode 100644 src/engine/SCons/Tool/gettext_tool.py create mode 100644 src/engine/SCons/Tool/gxx.py create mode 100644 src/engine/SCons/Tool/hpcxx.py create mode 100644 src/engine/SCons/Tool/sgicxx.py create mode 100644 src/engine/SCons/Tool/suncxx.py create mode 100644 src/engine/SCons/__main__.py (limited to 'src/engine') diff --git a/src/engine/MANIFEST-xml.in b/src/engine/MANIFEST-xml.in index a657734..cfbfd3a 100644 --- a/src/engine/MANIFEST-xml.in +++ b/src/engine/MANIFEST-xml.in @@ -4,4 +4,5 @@ SCons/Scanner/__init__.xml SCons/Script/*.xml SCons/Tool/*.xml SCons/Tool/docbook/__init__.xml +SCons/Tool/docbook/utils/xmldepend.xsl SCons/Tool/packaging/__init__.xml diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index f7d5aa7..2df278e 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -47,12 +47,12 @@ SCons/Script/Interactive.py SCons/Script/Main.py SCons/Script/SConscript.py SCons/Script/SConsOptions.py -SCons/Sig.py SCons/Subst.py SCons/Taskmaster.py SCons/Tool/__init__.py SCons/Tool/386asm.py SCons/Tool/aixc++.py +SCons/Tool/aixcxx.py SCons/Tool/aixcc.py SCons/Tool/aixf77.py SCons/Tool/aixlink.py @@ -60,12 +60,13 @@ SCons/Tool/applelink.py SCons/Tool/ar.py SCons/Tool/as.py SCons/Tool/bcc32.py -SCons/Tool/BitKeeper.py SCons/Tool/c++.py +SCons/Tool/cxx.py SCons/Tool/cc.py SCons/Tool/cyglink.py +SCons/Tool/clang.py +SCons/Tool/clangxx.py SCons/Tool/cvf.py -SCons/Tool/CVS.py SCons/Tool/DCommon.py SCons/Tool/default.py SCons/Tool/dmd.py @@ -73,14 +74,16 @@ SCons/Tool/docbook/__init__.py SCons/Tool/dvi.py SCons/Tool/dvipdf.py SCons/Tool/dvips.py +SCons/Tool/f03.py +SCons/Tool/f08.py SCons/Tool/f77.py SCons/Tool/f90.py SCons/Tool/f95.py -SCons/Tool/f03.py SCons/Tool/filesystem.py SCons/Tool/fortran.py SCons/Tool/FortranCommon.py SCons/Tool/g++.py +SCons/Tool/gxx.py SCons/Tool/g77.py SCons/Tool/gas.py SCons/Tool/gcc.py @@ -89,6 +92,7 @@ SCons/Tool/gfortran.py SCons/Tool/gnulink.py SCons/Tool/gs.py SCons/Tool/hpc++.py +SCons/Tool/hpcxx.py SCons/Tool/hpcc.py SCons/Tool/hplink.py SCons/Tool/icc.py @@ -132,22 +136,20 @@ SCons/Tool/packaging/*.py SCons/Tool/pdf.py SCons/Tool/pdflatex.py SCons/Tool/pdftex.py -SCons/Tool/Perforce.py SCons/Tool/PharLapCommon.py SCons/Tool/qt.py -SCons/Tool/RCS.py SCons/Tool/rmic.py SCons/Tool/rpcgen.py SCons/Tool/rpm.py SCons/Tool/rpmutils.py -SCons/Tool/SCCS.py SCons/Tool/sgiar.py SCons/Tool/sgic++.py +SCons/Tool/sgicxx.py SCons/Tool/sgicc.py SCons/Tool/sgilink.py -SCons/Tool/Subversion.py SCons/Tool/sunar.py SCons/Tool/sunc++.py +SCons/Tool/suncxx.py SCons/Tool/suncc.py SCons/Tool/sunf77.py SCons/Tool/sunf90.py @@ -170,7 +172,7 @@ SCons/Variables/PackageVariable.py SCons/Variables/PathVariable.py SCons/Warnings.py SCons/Tool/GettextCommon.py -SCons/Tool/gettext.py +SCons/Tool/gettext_tool.py SCons/Tool/msgfmt.py SCons/Tool/msginit.py SCons/Tool/msgmerge.py diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 00b2909..97040a4 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -60,6 +60,7 @@ this module: get_presig() Fetches the "contents" of a subclass for signature calculation. The varlist is added to this to produce the Action's contents. + TODO(?): Change this to always return ascii/bytes and not unicode (or py3 strings) strfunction() Returns a substituted string representation of the Action. @@ -76,7 +77,7 @@ way for wrapping up the functions. """ -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -97,15 +98,15 @@ way for wrapping up the functions. # 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/Action.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Action.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" -import dis import os -# compat layer imports "cPickle" for us if it's available. import pickle import re import sys import subprocess +import itertools +import inspect import SCons.Debug from SCons.Debug import logInstanceCreation @@ -124,37 +125,25 @@ print_actions = 1 execute_actions = 1 print_actions_presub = 0 +# Use pickle protocol 1 when pickling functions for signature +# otherwise python3 and python2 will yield different pickles +# for the same object. +# This is due to default being 1 for python 2.7, and 3 for 3.x +# TODO: We can roll this forward to 2 (if it has value), but not +# before a deprecation cycle as the sconsigns will change +ACTION_SIGNATURE_PICKLE_PROTOCOL = 1 + + def rfile(n): try: return n.rfile() except AttributeError: return n + def default_exitstatfunc(s): return s -try: - SET_LINENO = dis.SET_LINENO - HAVE_ARGUMENT = dis.HAVE_ARGUMENT -except AttributeError: - remove_set_lineno_codes = lambda x: x -else: - def remove_set_lineno_codes(code): - result = [] - n = len(code) - i = 0 - while i < n: - c = code[i] - op = ord(c) - if op >= HAVE_ARGUMENT: - if op != SET_LINENO: - result.append(code[i:i+3]) - i = i+3 - else: - result.append(c) - i = i+1 - return ''.join(result) - strip_quotes = re.compile('^[\'"](.*)[\'"]$') @@ -163,12 +152,12 @@ def _callable_contents(obj): """ try: # Test if obj is a method. - return _function_contents(obj.im_func) + return _function_contents(obj.__func__) except AttributeError: try: # Test if obj is a callable object. - return _function_contents(obj.__call__.im_func) + return _function_contents(obj.__call__.__func__) except AttributeError: try: @@ -176,8 +165,8 @@ def _callable_contents(obj): return _code_contents(obj) except AttributeError: - # Test if obj is a function object. - return _function_contents(obj) + # Test if obj is a function object. + return _function_contents(obj) def _object_contents(obj): @@ -188,12 +177,12 @@ def _object_contents(obj): """ try: # Test if obj is a method. - return _function_contents(obj.im_func) + return _function_contents(obj.__func__) except AttributeError: try: # Test if obj is a callable object. - return _function_contents(obj.__call__.im_func) + return _function_contents(obj.__call__.__func__) except AttributeError: try: @@ -205,20 +194,23 @@ def _object_contents(obj): # Test if obj is a function object. return _function_contents(obj) - except AttributeError: - # Should be a pickable Python object. + except AttributeError as ae: + # Should be a pickle-able Python object. try: - return pickle.dumps(obj) - except (pickle.PicklingError, TypeError): + return _object_instance_content(obj) + # pickling an Action instance or object doesn't yield a stable + # content as instance property may be dumped in different orders + # return pickle.dumps(obj, ACTION_SIGNATURE_PICKLE_PROTOCOL) + except (pickle.PicklingError, TypeError, AttributeError) as ex: # This is weird, but it seems that nested classes # are unpickable. The Python docs say it should # always be a PicklingError, but some Python # versions seem to return TypeError. Just do # the best we can. - return str(obj) + return bytearray(repr(obj), 'utf-8') -def _code_contents(code): +def _code_contents(code, docstring=None): """Return the signature contents of a code object. By providing direct access to the code object of the @@ -228,62 +220,174 @@ def _code_contents(code): number indications in the compiled byte code. Boo! So we remove the line number byte codes to prevent recompilations from moving a Python function. + + See: + - https://docs.python.org/2/library/inspect.html + - http://python-reference.readthedocs.io/en/latest/docs/code/index.html + + For info on what each co\_ variable provides + + The signature is as follows (should be byte/chars): + co_argcount, len(co_varnames), len(co_cellvars), len(co_freevars), + ( comma separated signature for each object in co_consts ), + ( comma separated signature for each object in co_names ), + ( The bytecode with line number bytecodes removed from co_code ) + + co_argcount - Returns the number of positional arguments (including arguments with default values). + co_varnames - Returns a tuple containing the names of the local variables (starting with the argument names). + co_cellvars - Returns a tuple containing the names of local variables that are referenced by nested functions. + co_freevars - Returns a tuple containing the names of free variables. (?) + co_consts - Returns a tuple containing the literals used by the bytecode. + co_names - Returns a tuple containing the names used by the bytecode. + co_code - Returns a string representing the sequence of bytecode instructions. + """ - contents = [] + # contents = [] # The code contents depends on the number of local variables # but not their actual names. - contents.append("%s,%s" % (code.co_argcount, len(code.co_varnames))) - contents.append(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars))) + contents = bytearray("{}, {}".format(code.co_argcount, len(code.co_varnames)), 'utf-8') + + contents.extend(b", ") + contents.extend(bytearray(str(len(code.co_cellvars)), 'utf-8')) + contents.extend(b", ") + contents.extend(bytearray(str(len(code.co_freevars)), 'utf-8')) # The code contents depends on any constants accessed by the # function. Note that we have to call _object_contents on each # constants because the code object of nested functions can # show-up among the constants. - # - # Note that we also always ignore the first entry of co_consts - # which contains the function doc string. We assume that the - # function does not access its doc string. - contents.append(',(' + ','.join(map(_object_contents,code.co_consts[1:])) + ')') + + z = [_object_contents(cc) for cc in code.co_consts[1:]] + contents.extend(b',(') + contents.extend(bytearray(',', 'utf-8').join(z)) + contents.extend(b')') # The code contents depends on the variable names used to # accessed global variable, as changing the variable name changes # the variable actually accessed and therefore changes the # function result. - contents.append(',(' + ','.join(map(_object_contents,code.co_names)) + ')') - + z= [bytearray(_object_contents(cc)) for cc in code.co_names] + contents.extend(b',(') + contents.extend(bytearray(',','utf-8').join(z)) + contents.extend(b')') # The code contents depends on its actual code!!! - contents.append(',(' + str(remove_set_lineno_codes(code.co_code)) + ')') + contents.extend(b',(') + contents.extend(code.co_code) + contents.extend(b')') - return ''.join(contents) + return contents def _function_contents(func): - """Return the signature contents of a function.""" + """ + The signature is as follows (should be byte/chars): + < _code_contents (see above) from func.__code__ > + ,( comma separated _object_contents for function argument defaults) + ,( comma separated _object_contents for any closure contents ) + + + See also: https://docs.python.org/3/reference/datamodel.html + - func.__code__ - The code object representing the compiled function body. + - func.__defaults__ - A tuple containing default argument values for those arguments that have defaults, or None if no arguments have a default value + - func.__closure__ - None or a tuple of cells that contain bindings for the function's free variables. + + :Returns: + Signature contents of a function. (in bytes) + """ - contents = [_code_contents(func.func_code)] + contents = [_code_contents(func.__code__, func.__doc__)] # The function contents depends on the value of defaults arguments - if func.func_defaults: - contents.append(',(' + ','.join(map(_object_contents,func.func_defaults)) + ')') + if func.__defaults__: + + function_defaults_contents = [_object_contents(cc) for cc in func.__defaults__] + + defaults = bytearray(b',(') + defaults.extend(bytearray(b',').join(function_defaults_contents)) + defaults.extend(b')') + + contents.append(defaults) else: - contents.append(',()') + contents.append(b',()') # The function contents depends on the closure captured cell values. - closure = func.func_closure or [] + closure = func.__closure__ or [] - #xxx = [_object_contents(x.cell_contents) for x in closure] try: - xxx = [_object_contents(x.cell_contents) for x in closure] + closure_contents = [_object_contents(x.cell_contents) for x in closure] except AttributeError: - xxx = [] - contents.append(',(' + ','.join(xxx) + ')') + closure_contents = [] + + contents.append(b',(') + contents.append(bytearray(b',').join(closure_contents)) + contents.append(b')') - return ''.join(contents) + retval = bytearray(b'').join(contents) + return retval +def _object_instance_content(obj): + """ + Returns consistant content for a action class or an instance thereof + + :Parameters: + - `obj` Should be either and action class or an instance thereof + + :Returns: + bytearray or bytes representing the obj suitable for generating a signature from. + """ + retval = bytearray() + + if obj is None: + return b'N.' + + if isinstance(obj, SCons.Util.BaseStringTypes): + return SCons.Util.to_bytes(obj) + + inst_class = obj.__class__ + inst_class_name = bytearray(obj.__class__.__name__,'utf-8') + inst_class_module = bytearray(obj.__class__.__module__,'utf-8') + inst_class_hierarchy = bytearray(repr(inspect.getclasstree([obj.__class__,])),'utf-8') + # print("ICH:%s : %s"%(inst_class_hierarchy, repr(obj))) + + properties = [(p, getattr(obj, p, "None")) for p in dir(obj) if not (p[:2] == '__' or inspect.ismethod(getattr(obj, p)) or inspect.isbuiltin(getattr(obj,p))) ] + properties.sort() + properties_str = ','.join(["%s=%s"%(p[0],p[1]) for p in properties]) + properties_bytes = bytearray(properties_str,'utf-8') + + methods = [p for p in dir(obj) if inspect.ismethod(getattr(obj, p))] + methods.sort() + + method_contents = [] + for m in methods: + # print("Method:%s"%m) + v = _function_contents(getattr(obj, m)) + # print("[%s->]V:%s [%s]"%(m,v,type(v))) + method_contents.append(v) + + retval = bytearray(b'{') + retval.extend(inst_class_name) + retval.extend(b":") + retval.extend(inst_class_module) + retval.extend(b'}[[') + retval.extend(inst_class_hierarchy) + retval.extend(b']]{{') + retval.extend(bytearray(b",").join(method_contents)) + retval.extend(b"}}{{{") + retval.extend(properties_bytes) + retval.extend(b'}}}') + return retval + + # print("class :%s"%inst_class) + # print("class_name :%s"%inst_class_name) + # print("class_module :%s"%inst_class_module) + # print("Class hier :\n%s"%pp.pformat(inst_class_hierarchy)) + # print("Inst Properties:\n%s"%pp.pformat(properties)) + # print("Inst Methods :\n%s"%pp.pformat(methods)) + def _actionAppend(act1, act2): # This function knows how to slap two actions together. # Mainly, it handles ListActions by concatenating into @@ -305,6 +409,7 @@ def _actionAppend(act1, act2): else: return ListAction([ a1, a2 ]) + def _do_create_keywords(args, kw): """This converts any arguments after the action argument into their equivalent keywords and adds them to the kw argument. @@ -332,6 +437,7 @@ def _do_create_keywords(args, kw): raise SCons.Errors.UserError( 'Cannot have both strfunction and cmdstr args to Action()') + def _do_create_action(act, kw): """This is the actual "implementation" for the Action factory method, below. This handles the @@ -362,7 +468,7 @@ def _do_create_action(act, kw): # The list of string commands may include a LazyAction, so we # reprocess them via _do_create_list_action. return _do_create_list_action(commands, kw) - + if is_List(act): return CommandAction(act, **kw) @@ -384,6 +490,7 @@ def _do_create_action(act, kw): # Else fail silently (???) return None + def _do_create_list_action(act, kw): """A factory for list actions. Convert the input list into Actions and then wrap them in a ListAction.""" @@ -398,6 +505,7 @@ def _do_create_list_action(act, kw): else: return ListAction(acts) + def Action(act, *args, **kw): """A factory for action objects.""" # Really simple: the _do_create_* routines do the heavy lifting. @@ -406,13 +514,14 @@ def Action(act, *args, **kw): return _do_create_list_action(act, kw) return _do_create_action(act, kw) + class ActionBase(object): """Base class for all types of action objects that can be held by other objects (Builders, Executors, etc.) This provides the common methods for manipulating and combining those actions.""" - def __cmp__(self, other): - return cmp(self.__dict__, other) + def __eq__(self, other): + return self.__dict__ == other def no_batch_key(self, env, target, source): return None @@ -423,7 +532,18 @@ class ActionBase(object): return str(self) def get_contents(self, target, source, env): - result = [ self.get_presig(target, source, env) ] + result = self.get_presig(target, source, env) + + if not isinstance(result,(bytes, bytearray)): + result = bytearray("",'utf-8').join([ SCons.Util.to_bytes(r) for r in result ]) + else: + # Make a copy and put in bytearray, without this the contents returned by get_presig + # can be changed by the logic below, appending with each call and causing very + # hard to track down issues... + result = bytearray(result) + + # At this point everything should be a bytearray + # This should never happen, as the Action() factory should wrap # the varlist, but just in case an action is created directly, # we duplicate this check here. @@ -431,8 +551,18 @@ class ActionBase(object): if is_String(vl): vl = (vl,) for v in vl: # do the subst this way to ignore $(...$) parts: - result.append(env.subst_target_source('${'+v+'}', SCons.Subst.SUBST_SIG, target, source)) - return ''.join(result) + if isinstance(result, bytearray): + result.extend(SCons.Util.to_bytes(env.subst_target_source('${'+v+'}', SCons.Subst.SUBST_SIG, target, source))) + else: + raise Exception("WE SHOULD NEVER GET HERE result should be bytearray not:%s"%type(result)) + # result.append(SCons.Util.to_bytes(env.subst_target_source('${'+v+'}', SCons.Subst.SUBST_SIG, target, source))) + + + if isinstance(result, (bytes,bytearray)): + return result + else: + raise Exception("WE SHOULD NEVER GET HERE - #2 result should be bytearray not:%s" % type(result)) + # return b''.join(result) def __add__(self, other): return _actionAppend(self, other) @@ -462,6 +592,7 @@ class ActionBase(object): """ return self.targets + class _ActionAction(ActionBase): """Base class for actions that create output objects.""" def __init__(self, cmdstr=_null, strfunction=_null, varlist=(), @@ -495,16 +626,18 @@ class _ActionAction(ActionBase): SCons.Util.AddMethod(self, batch_key, 'batch_key') def print_cmd_line(self, s, target, source, env): - # In python 3, and in some of our tests, sys.stdout is - # a String io object, and it takes unicode strings only - # In other cases it's a regular Python 2.x file object - # which takes strings (bytes), and if you pass those a - # unicode object they try to decode with 'ascii' codec - # which fails if the cmd line has any hi-bit-set chars. - # This code assumes s is a regular string, but should - # work if it's unicode too. + """ + In python 3, and in some of our tests, sys.stdout is + a String io object, and it takes unicode strings only + In other cases it's a regular Python 2.x file object + which takes strings (bytes), and if you pass those a + unicode object they try to decode with 'ascii' codec + which fails if the cmd line has any hi-bit-set chars. + This code assumes s is a regular string, but should + work if it's unicode too. + """ try: - sys.stdout.write(unicode(s + "\n")) + sys.stdout.write(s + u"\n") except UnicodeDecodeError: sys.stdout.write(s + "\n") @@ -601,13 +734,17 @@ def _string_from_cmd_list(cmd_list): cl.append(arg) return ' '.join(cl) -# A fiddlin' little function that has an 'import SCons.Environment' which -# can't be moved to the top level without creating an import loop. Since -# this import creates a local variable named 'SCons', it blocks access to -# the global variable, so we move it here to prevent complaints about local -# variables being used uninitialized. default_ENV = None + + def get_default_ENV(env): + """ + A fiddlin' little function that has an 'import SCons.Environment' which + can't be moved to the top level without creating an import loop. Since + this import creates a local variable named 'SCons', it blocks access to + the global variable, so we move it here to prevent complaints about local + variables being used uninitialized. + """ global default_ENV try: return env['ENV'] @@ -622,12 +759,15 @@ def get_default_ENV(env): default_ENV = SCons.Environment.Environment()['ENV'] return default_ENV -# This function is still in draft mode. We're going to need something like -# it in the long run as more and more places use subprocess, but I'm sure -# it'll have to be tweaked to get the full desired functionality. -# one special arg (so far?), 'error', to tell what to do with exceptions. + def _subproc(scons_env, cmd, error = 'ignore', **kw): - """Do common setup for a subprocess.Popen() call""" + """Do common setup for a subprocess.Popen() call + + This function is still in draft mode. We're going to need something like + it in the long run as more and more places use subprocess, but I'm sure + it'll have to be tweaked to get the full desired functionality. + one special arg (so far?), 'error', to tell what to do with exceptions. + """ # allow std{in,out,err} to be "'devnull'" io = kw.get('stdin') if is_String(io) and io == 'devnull': @@ -664,12 +804,12 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw): try: return subprocess.Popen(cmd, **kw) - except EnvironmentError, e: + except EnvironmentError as e: if error == 'raise': raise # return a dummy Popen instance that only returns error class dummyPopen(object): def __init__(self, e): self.exception = e - def communicate(self,input=None): return ('','') + def communicate(self, input=None): return ('', '') def wait(self): return -self.exception.errno stdin = None class f(object): @@ -679,6 +819,7 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw): stdout = stderr = f() return dummyPopen(e) + class CommandAction(_ActionAction): """Class for command-execution actions.""" def __init__(self, cmd, **kw): @@ -695,7 +836,7 @@ class CommandAction(_ActionAction): _ActionAction.__init__(self, **kw) if is_List(cmd): - if list(filter(is_List, cmd)): + if [c for c in cmd if is_List(c)]: raise TypeError("CommandAction should be given only " \ "a single command") self.cmd_list = cmd @@ -845,6 +986,7 @@ class CommandAction(_ActionAction): res.append(env.fs.File(d)) return res + class CommandGeneratorAction(ActionBase): """Class for command-generator actions.""" def __init__(self, generator, kw): @@ -916,25 +1058,25 @@ class CommandGeneratorAction(ActionBase): return self._generate(None, None, env, 1, executor).get_targets(env, executor) - -# A LazyAction is a kind of hybrid generator and command action for -# strings of the form "$VAR". These strings normally expand to other -# strings (think "$CCCOM" to "$CC -c -o $TARGET $SOURCE"), but we also -# want to be able to replace them with functions in the construction -# environment. Consequently, we want lazy evaluation and creation of -# an Action in the case of the function, but that's overkill in the more -# normal case of expansion to other strings. -# -# So we do this with a subclass that's both a generator *and* -# a command action. The overridden methods all do a quick check -# of the construction variable, and if it's a string we just call -# the corresponding CommandAction method to do the heavy lifting. -# If not, then we call the same-named CommandGeneratorAction method. -# The CommandGeneratorAction methods work by using the overridden -# _generate() method, that is, our own way of handling "generation" of -# an action based on what's in the construction variable. - class LazyAction(CommandGeneratorAction, CommandAction): + """ + A LazyAction is a kind of hybrid generator and command action for + strings of the form "$VAR". These strings normally expand to other + strings (think "$CCCOM" to "$CC -c -o $TARGET $SOURCE"), but we also + want to be able to replace them with functions in the construction + environment. Consequently, we want lazy evaluation and creation of + an Action in the case of the function, but that's overkill in the more + normal case of expansion to other strings. + + So we do this with a subclass that's both a generator *and* + a command action. The overridden methods all do a quick check + of the construction variable, and if it's a string we just call + the corresponding CommandAction method to do the heavy lifting. + If not, then we call the same-named CommandGeneratorAction method. + The CommandGeneratorAction methods work by using the overridden + _generate() method, that is, our own way of handling "generation" of + an action based on what's in the construction variable. + """ def __init__(self, var, kw): if SCons.Debug.track_instances: logInstanceCreation(self, 'Action.LazyAction') @@ -1013,6 +1155,7 @@ class FunctionAction(_ActionAction): c = env.subst(self.cmdstr, SUBST_RAW, target, source) if c: return c + def array(a): def quote(s): try: @@ -1052,11 +1195,11 @@ class FunctionAction(_ActionAction): rsources = list(map(rfile, source)) try: result = self.execfunction(target=target, source=rsources, env=env) - except KeyboardInterrupt, e: + except KeyboardInterrupt as e: raise - except SystemExit, e: + except SystemExit as e: raise - except Exception, e: + except Exception as e: result = e exc_info = sys.exc_info() @@ -1086,7 +1229,6 @@ class FunctionAction(_ActionAction): # more information about this issue. del exc_info - def get_presig(self, target, source, env): """Return the signature contents of this callable action.""" try: @@ -1126,7 +1268,7 @@ class ListAction(ActionBase): Simple concatenation of the signatures of the elements. """ - return "".join([x.get_contents(target, source, env) for x in self.list]) + return b"".join([bytes(x.get_contents(target, source, env)) for x in self.list]) def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, show=_null, execute=_null, chdir=_null, executor=None): @@ -1153,6 +1295,7 @@ class ListAction(ActionBase): result[var] = True return list(result.keys()) + class ActionCaller(object): """A class for delaying calling an Action function with specific (positional and keyword) arguments until the Action is actually @@ -1171,16 +1314,16 @@ class ActionCaller(object): actfunc = self.parent.actfunc try: # "self.actfunc" is a function. - contents = str(actfunc.func_code.co_code) + contents = actfunc.__code__.co_code except AttributeError: # "self.actfunc" is a callable object. try: - contents = str(actfunc.__call__.im_func.func_code.co_code) + contents = actfunc.__call__.__func__.__code__.co_code except AttributeError: # No __call__() method, so it might be a builtin # or something like that. Do the best we can. - contents = str(actfunc) - contents = remove_set_lineno_codes(contents) + contents = repr(actfunc) + return contents def subst(self, s, target, source, env): @@ -1206,7 +1349,7 @@ class ActionCaller(object): def subst_kw(self, target, source, env): kw = {} - for key in self.kw.keys(): + for key in list(self.kw.keys()): kw[key] = self.subst(self.kw[key], target, source, env) return kw @@ -1223,6 +1366,7 @@ class ActionCaller(object): def __str__(self): return self.parent.strfunc(*self.args, **self.kw) + class ActionFactory(object): """A factory class that will wrap up an arbitrary function as an SCons-executable Action object. diff --git a/src/engine/SCons/Action.xml b/src/engine/SCons/Action.xml index 3b35a1a..99f4e86 100644 --- a/src/engine/SCons/Action.xml +++ b/src/engine/SCons/Action.xml @@ -1,6 +1,6 @@ Node B(Pending) --> Node C (NoState) - ^ | - | | - +-------------------------------------+ + Next candidate \ + \ + Node A (Pending) --> Node B(Pending) --> Node C (NoState) + ^ | + | | + +-------------------------------------+ Now, when the Taskmaster examines the Node C's child Node A, it finds that Node A is in the "pending" state. Therefore, @@ -685,15 +708,14 @@ class Taskmaster(object): Pending children indicate that the Taskmaster has potentially loop back through a cycle. We say potentially because it could also occur when a DAG is evaluated in parallel. For example, - consider the following graph: - + consider the following graph:: - Node A (Pending) --> Node B(Pending) --> Node C (Pending) --> ... - | ^ - | | - +----------> Node D (NoState) --------+ - / - Next candidate / + Node A (Pending) --> Node B(Pending) --> Node C (Pending) --> ... + | ^ + | | + +----------> Node D (NoState) --------+ + / + Next candidate / The Taskmaster first evaluates the nodes A, B, and C and starts building some children of node C. Assuming, that the @@ -761,7 +783,7 @@ class Taskmaster(object): self.ready_exc = None T = self.trace - if T: T.write(u'\n' + self.trace_message('Looking for a node to evaluate')) + if T: T.write(SCons.Util.UnicodeType('\n') + self.trace_message('Looking for a node to evaluate')) while True: node = self.next_candidate() @@ -810,7 +832,7 @@ class Taskmaster(object): self.ready_exc = (SCons.Errors.ExplicitExit, e) if T: T.write(self.trace_message(' SystemExit')) return node - except Exception, e: + except Exception as e: # We had a problem just trying to figure out the # children (like a child couldn't be linked in to a # VariantDir, or a Scanner threw something). Arrange to @@ -840,13 +862,13 @@ class Taskmaster(object): if childstate <= NODE_EXECUTING: children_not_ready.append(child) - # These nodes have not even been visited yet. Add # them to the list so that on some next pass we can # take a stab at evaluating them (or their children). children_not_visited.reverse() self.candidates.extend(self.order(children_not_visited)) - #if T and children_not_visited: + + # if T and children_not_visited: # T.write(self.trace_message(' adding to candidates: %s' % map(str, children_not_visited))) # T.write(self.trace_message(' candidates now: %s\n' % map(str, self.candidates))) @@ -943,13 +965,13 @@ class Taskmaster(object): executor = node.get_executor() if executor is None: return None - + tlist = executor.get_all_targets() task = self.tasker(self, tlist, node in self.original_top, node) try: task.make_ready() - except: + except Exception as e : # We had a problem just trying to get this task ready (like # a child couldn't be linked to a VariantDir when deciding # whether this node is current). Arrange to raise the diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index b1bd9d6..fab54cf 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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 division -__revision__ = "src/engine/SCons/TaskmasterTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/TaskmasterTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.compat @@ -697,7 +697,7 @@ class TaskmasterTestCase(unittest.TestCase): tm = SCons.Taskmaster.Taskmaster([n3]) try: t = tm.next_task() - except SCons.Errors.UserError, e: + except SCons.Errors.UserError as e: assert str(e) == "Dependency cycle: n3 -> n1 -> n2 -> n3", str(e) else: assert 'Did not catch expected UserError' @@ -849,14 +849,18 @@ class TaskmasterTestCase(unittest.TestCase): t = tm.next_task() t.exception_set((MyException, "exception value")) exc_caught = None + exc_actually_caught = None + exc_value = None try: t.prepare() - except MyException, e: + except MyException as e: exc_caught = 1 - except: + exc_value = e + except Exception as e: + exc_actually_caught = e pass - assert exc_caught, "did not catch expected MyException" - assert str(e) == "exception value", e + assert exc_caught, "did not catch expected MyException: %s"%exc_actually_caught + assert str(exc_value) == "exception value", exc_value assert built_text is None, built_text # Regression test, make sure we prepare not only @@ -904,7 +908,7 @@ class TaskmasterTestCase(unittest.TestCase): t = tm.next_task() try: t.prepare() - except Exception, e: + except Exception as e: assert str(e) == "Executor.prepare() exception", e else: raise AssertionError("did not catch expected exception") @@ -958,7 +962,7 @@ class TaskmasterTestCase(unittest.TestCase): t = tm.next_task() try: t.execute() - except SCons.Errors.BuildError, e: + except SCons.Errors.BuildError as e: assert e.node == n4, e.node assert e.errstr == "OtherError : ", e.errstr assert len(e.exc_info) == 3, e.exc_info @@ -1065,10 +1069,20 @@ class TaskmasterTestCase(unittest.TestCase): assert t.exception == 3 try: 1//0 - except: pass - t.exception_set(None) + except: + # Moved from below + t.exception_set(None) + #pass + +# import pdb; pdb.set_trace() + + # Having this here works for python 2.x, + # but it is a tuple (None, None, None) when called outside + # an except statement + # t.exception_set(None) + exc_type, exc_value, exc_tb = t.exception - assert exc_type is ZeroDivisionError, exc_type + assert exc_type is ZeroDivisionError, "Expecting ZeroDevisionError got:%s"%exc_type exception_values = [ "integer division or modulo", "integer division or modulo by zero", @@ -1078,13 +1092,14 @@ class TaskmasterTestCase(unittest.TestCase): class Exception1(Exception): pass - t.exception_set((Exception1, None)) + # Previously value was None, but while PY2 None = "", in Py3 None != "", so set to "" + t.exception_set((Exception1, "")) try: t.exception_raise() except: exc_type, exc_value = sys.exc_info()[:2] assert exc_type == Exception1, exc_type - assert str(exc_value) == '', exc_value + assert str(exc_value) == '', "Expecting empty string got:%s (type %s)"%(exc_value,type(exc_value)) else: assert 0, "did not catch expected exception" diff --git a/src/engine/SCons/Tool/386asm.py b/src/engine/SCons/Tool/386asm.py index 8fee694..b318c4b 100644 --- a/src/engine/SCons/Tool/386asm.py +++ b/src/engine/SCons/Tool/386asm.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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. # -__revision__ = "src/engine/SCons/Tool/386asm.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/386asm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" from SCons.Tool.PharLapCommon import addPharLapPaths import SCons.Util -as_module = __import__('as', globals(), locals(), []) +as_module = __import__('as', globals(), locals(), [], 1) def generate(env): """Add Builders and construction variables for ar to an Environment.""" diff --git a/src/engine/SCons/Tool/386asm.xml b/src/engine/SCons/Tool/386asm.xml index a29fc0f..80a2cd6 100644 --- a/src/engine/SCons/Tool/386asm.xml +++ b/src/engine/SCons/Tool/386asm.xml @@ -1,6 +1,6 @@ - - -%scons; - -%builders-mod; - -%functions-mod; - -%tools-mod; - -%variables-mod; -]> - - - - - - -Sets construction variables for the BitKeeper -source code control system. - - - -BITKEEPER -BITKEEPERGET -BITKEEPERGETFLAGS -BITKEEPERCOM - - -BITKEEPERCOMSTR - - - - - - -The BitKeeper executable. - - - - - - - -The command line for -fetching source files using BitKeeper. - - - - - - - -The string displayed when fetching -a source file using BitKeeper. -If this is not set, then &cv-link-BITKEEPERCOM; -(the command line) is displayed. - - - - - - - -The command (&cv-link-BITKEEPER;) and subcommand -for fetching source files using BitKeeper. - - - - - - - -Options that are passed to the BitKeeper -get -subcommand. - - - - - - -() - - - -A factory function that -returns a Builder object -to be used to fetch source files -using BitKeeper. -The returned Builder -is intended to be passed to the -&f-SourceCode; -function. - - - -This function is deprecated. For details, see the entry for the -&f-SourceCode; -function. - - - -Example: - - - -env.SourceCode('.', env.BitKeeper()) - - - - - diff --git a/src/engine/SCons/Tool/CVS.py b/src/engine/SCons/Tool/CVS.py deleted file mode 100644 index a8e5a8d..0000000 --- a/src/engine/SCons/Tool/CVS.py +++ /dev/null @@ -1,72 +0,0 @@ -"""SCons.Tool.CVS.py - -Tool-specific initialization for CVS. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# Copyright (c) 2001 - 2016 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/CVS.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" - -import SCons.Action -import SCons.Builder -import SCons.Util - -def generate(env): - """Add a Builder factory function and construction variables for - CVS to an Environment.""" - - def CVSFactory(repos, module='', env=env): - """ """ - import SCons.Warnings as W - W.warn(W.DeprecatedSourceCodeWarning, """The CVS() factory is deprecated and there is no replacement.""") - # fail if repos is not an absolute path name? - if module != '': - # Don't use os.path.join() because the name we fetch might - # be across a network and must use POSIX slashes as separators. - module = module + '/' - env['CVSCOM'] = '$CVS $CVSFLAGS co $CVSCOFLAGS -d ${TARGET.dir} $CVSMODULE${TARGET.posix}' - act = SCons.Action.Action('$CVSCOM', '$CVSCOMSTR') - return SCons.Builder.Builder(action = act, - env = env, - CVSREPOSITORY = repos, - CVSMODULE = module) - - env.CVS = CVSFactory - - env['CVS'] = 'cvs' - env['CVSFLAGS'] = SCons.Util.CLVar('-d $CVSREPOSITORY') - env['CVSCOFLAGS'] = SCons.Util.CLVar('') - env['CVSCOM'] = '$CVS $CVSFLAGS co $CVSCOFLAGS ${TARGET.posix}' - -def exists(env): - return env.Detect('cvs') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/CVS.xml b/src/engine/SCons/Tool/CVS.xml deleted file mode 100644 index b6ff10a..0000000 --- a/src/engine/SCons/Tool/CVS.xml +++ /dev/null @@ -1,159 +0,0 @@ - - - - -%scons; - -%builders-mod; - -%functions-mod; - -%tools-mod; - -%variables-mod; -]> - - - - - - -Sets construction variables for the CVS source code -management system. - - - -CVS -CVSCOM -CVSFLAGS -CVSCOFLAGS - - -CVSCOMSTR - - - - - - -The CVS executable. - - - - - - - -Options that are passed to the CVS checkout subcommand. - - - - - - - -The command line used to -fetch source files from a CVS repository. - - - - - - - -The string displayed when fetching -a source file from a CVS repository. -If this is not set, then &cv-link-CVSCOM; -(the command line) is displayed. - - - - - - - -General options that are passed to CVS. -By default, this is set to --d $CVSREPOSITORY -to specify from where the files must be fetched. - - - - - - - -The path to the CVS repository. -This is referenced in the default -&cv-link-CVSFLAGS; value. - - - - - - -(repository, module) - - - -A factory function that -returns a Builder object -to be used to fetch source files -from the specified -CVS -repository. -The returned Builder -is intended to be passed to the -&f-link-SourceCode; -function. - - - -This function is deprecated. For details, see the entry for the -&f-SourceCode; -function. - - - -The optional specified -module -will be added to the beginning -of all repository path names; -this can be used, in essence, -to strip initial directory names -from the repository path names, -so that you only have to -replicate part of the repository -directory hierarchy in your -local build directory. - - - -Examples: - - - -# Will fetch foo/bar/src.c -# from /usr/local/CVSROOT/foo/bar/src.c. -env.SourceCode('.', env.CVS('/usr/local/CVSROOT')) - -# Will fetch bar/src.c -# from /usr/local/CVSROOT/foo/bar/src.c. -env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo')) - -# Will fetch src.c -# from /usr/local/CVSROOT/foo/bar/src.c. -env.SourceCode('.', env.CVS('/usr/local/CVSROOT', 'foo/bar')) - - - - - diff --git a/src/engine/SCons/Tool/DCommon.py b/src/engine/SCons/Tool/DCommon.py index e2750a4..8973853 100644 --- a/src/engine/SCons/Tool/DCommon.py +++ b/src/engine/SCons/Tool/DCommon.py @@ -1,3 +1,5 @@ +from __future__ import print_function + """SCons.Tool.DCommon Common code for the various D tools. @@ -5,8 +7,9 @@ Common code for the various D tools. Coded by Russel Winder (russel@winder.org.uk) 2012-09-06 """ + # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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,10 +31,11 @@ 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/DCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import os.path + def isD(env, source): if not source: return 0 @@ -42,6 +46,7 @@ def isD(env, source): return 1 return 0 + def addDPATHToEnv(env, executable): dPath = env.WhereIs(executable) if dPath: @@ -49,6 +54,14 @@ def addDPATHToEnv(env, executable): if os.path.isdir(phobosDir): env.Append(DPATH=[phobosDir]) + +def allAtOnceEmitter(target, source, env): + if env['DC'] in ('ldc2', 'dmd'): + env.SideEffect(str(target[0]) + '.o', target[0]) + env.Clean(target[0], str(target[0]) + '.o') + return target, source + + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/Tool/DCommon.xml b/src/engine/SCons/Tool/DCommon.xml new file mode 100644 index 0000000..b1deb82 --- /dev/null +++ b/src/engine/SCons/Tool/DCommon.xml @@ -0,0 +1,71 @@ + + + + + %scons; + + %builders-mod; + + %functions-mod; + + %tools-mod; + + %variables-mod; + ]> + + + + + + + + + + + DRPATHPREFIX. + + + + + + + + DRPATHSUFFIX. + + + + + + + + + DShLibSonameGenerator. + + + + + + + + SHDLIBVERSION. + + + + + + + SHDLIBVERSIONFLAGS. + + + + + + diff --git a/src/engine/SCons/Tool/FortranCommon.py b/src/engine/SCons/Tool/FortranCommon.py index 058f24d..d2126a4 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 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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,8 +26,9 @@ Stuff for processing Fortran, common to all fortran dialects. # 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 __future__ import print_function -__revision__ = "src/engine/SCons/Tool/FortranCommon.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/FortranCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import re import os.path @@ -61,7 +62,7 @@ def isfortran(env, source): def _fortranEmitter(target, source, env): node = source[0].rfile() if not node.exists() and not node.is_derived(): - print "Could not locate " + str(node.name) + print("Could not locate " + str(node.name)) return ([], []) mod_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)""" cre = re.compile(mod_regex,re.M) @@ -167,7 +168,7 @@ def add_fortran_to_env(env): except KeyError: FortranSuffixes = ['.f', '.for', '.ftn'] - #print "Adding %s to fortran suffixes" % FortranSuffixes + #print("Adding %s to fortran suffixes" % FortranSuffixes) try: FortranPPSuffixes = env['FORTRANPPFILESUFFIXES'] except KeyError: @@ -191,7 +192,7 @@ def add_f77_to_env(env): except KeyError: F77Suffixes = ['.f77'] - #print "Adding %s to f77 suffixes" % F77Suffixes + #print("Adding %s to f77 suffixes" % F77Suffixes) try: F77PPSuffixes = env['F77PPFILESUFFIXES'] except KeyError: @@ -206,7 +207,7 @@ def add_f90_to_env(env): except KeyError: F90Suffixes = ['.f90'] - #print "Adding %s to f90 suffixes" % F90Suffixes + #print("Adding %s to f90 suffixes" % F90Suffixes) try: F90PPSuffixes = env['F90PPFILESUFFIXES'] except KeyError: @@ -222,7 +223,7 @@ def add_f95_to_env(env): except KeyError: F95Suffixes = ['.f95'] - #print "Adding %s to f95 suffixes" % F95Suffixes + #print("Adding %s to f95 suffixes" % F95Suffixes) try: F95PPSuffixes = env['F95PPFILESUFFIXES'] except KeyError: @@ -238,7 +239,7 @@ def add_f03_to_env(env): except KeyError: F03Suffixes = ['.f03'] - #print "Adding %s to f95 suffixes" % F95Suffixes + #print("Adding %s to f95 suffixes" % F95Suffixes) try: F03PPSuffixes = env['F03PPFILESUFFIXES'] except KeyError: diff --git a/src/engine/SCons/Tool/GettextCommon.py b/src/engine/SCons/Tool/GettextCommon.py index 596586c..b475d8f 100644 --- a/src/engine/SCons/Tool/GettextCommon.py +++ b/src/engine/SCons/Tool/GettextCommon.py @@ -3,7 +3,7 @@ Used by several tools of `gettext` toolset. """ -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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,20 +24,37 @@ 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/GettextCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import SCons.Warnings import re + ############################################################################# class XgettextToolWarning(SCons.Warnings.Warning): pass + + class XgettextNotFound(XgettextToolWarning): pass + + class MsginitToolWarning(SCons.Warnings.Warning): pass + + class MsginitNotFound(MsginitToolWarning): pass + + class MsgmergeToolWarning(SCons.Warnings.Warning): pass + + class MsgmergeNotFound(MsgmergeToolWarning): pass + + class MsgfmtToolWarning(SCons.Warnings.Warning): pass + + class MsgfmtNotFound(MsgfmtToolWarning): pass + + ############################################################################# SCons.Warnings.enableWarningClass(XgettextToolWarning) SCons.Warnings.enableWarningClass(XgettextNotFound) @@ -47,367 +64,406 @@ SCons.Warnings.enableWarningClass(MsgmergeToolWarning) SCons.Warnings.enableWarningClass(MsgmergeNotFound) SCons.Warnings.enableWarningClass(MsgfmtToolWarning) 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. - """ - 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 `'.'` - - *alias* (`string`) - if provided, produced nodes will be automatically - added to this alias, and alias will be set as `AlwaysBuild` - - *precious* (`boolean`) - if `True`, the produced nodes will be set as - `Precious`. - - *noclen* (`boolean`) - if `True`, the produced nodes will be excluded - from `Clean`. + """ 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. """ - self.env = env - self.alias = alias - self.precious = precious - self.noclean = noclean - self.nodefault = nodefault - - def _create_node(self, name, factory, directory = None, create = 1): - """ Create node, and set it up to factory settings. """ - import SCons.Util - node = factory(name, directory, create) - node.set_noclean(self.noclean) - node.set_precious(self.precious) - if self.nodefault: - self.env.Ignore('.', node) - if self.alias: - self.env.AlwaysBuild(self.env.Alias(self.alias, node)) - return node - - def Entry(self, name, directory = None, create = 1): - """ Create `SCons.Node.FS.Entry` """ - return self._create_node(name, self.env.fs.Entry, directory, create) - - def File(self, name, directory = None, create = 1): - """ Create `SCons.Node.FS.File` """ - return self._create_node(name, self.env.fs.File, directory, create) + + 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 `'.'` + - *alias* (`string`) - if provided, produced nodes will be automatically + added to this alias, and alias will be set as `AlwaysBuild` + - *precious* (`boolean`) - if `True`, the produced nodes will be set as + `Precious`. + - *noclen* (`boolean`) - if `True`, the produced nodes will be excluded + from `Clean`. + """ + self.env = env + self.alias = alias + self.precious = precious + self.noclean = noclean + self.nodefault = nodefault + + def _create_node(self, name, factory, directory=None, create=1): + """ Create node, and set it up to factory settings. """ + import SCons.Util + node = factory(name, directory, create) + node.set_noclean(self.noclean) + node.set_precious(self.precious) + if self.nodefault: + self.env.Ignore('.', node) + if self.alias: + self.env.AlwaysBuild(self.env.Alias(self.alias, node)) + return node + + def Entry(self, name, directory=None, create=1): + """ Create `SCons.Node.FS.Entry` """ + return self._create_node(name, self.env.fs.Entry, directory, create) + + def File(self, name, directory=None, create=1): + """ Create `SCons.Node.FS.File` """ + return self._create_node(name, self.env.fs.File, directory, create) + + ############################################################################# ############################################################################# _re_comment = re.compile(r'(#[^\n\r]+)$', re.M) _re_lang = re.compile(r'([a-zA-Z0-9_]+)', re.M) + + ############################################################################# -def _read_linguas_from_files(env, linguas_files = None): - """ Parse `LINGUAS` file and return list of extracted languages """ - import SCons.Util - import SCons.Environment - global _re_comment - global _re_lang - if not SCons.Util.is_List(linguas_files) \ - and not SCons.Util.is_String(linguas_files) \ - and not isinstance(linguas_files, SCons.Node.FS.Base) \ - and linguas_files: - # If, linguas_files==True or such, then read 'LINGUAS' file. - linguas_files = [ 'LINGUAS' ] - if linguas_files is None: - return [] - fnodes = env.arg2nodes(linguas_files) - linguas = [] - for fnode in fnodes: - contents = _re_comment.sub("", fnode.get_text_contents()) - ls = [ l for l in _re_lang.findall(contents) if l ] - linguas.extend(ls) - return linguas +def _read_linguas_from_files(env, linguas_files=None): + """ Parse `LINGUAS` file and return list of extracted languages """ + import SCons.Util + import SCons.Environment + global _re_comment + global _re_lang + if not SCons.Util.is_List(linguas_files) \ + and not SCons.Util.is_String(linguas_files) \ + and not isinstance(linguas_files, SCons.Node.FS.Base) \ + and linguas_files: + # If, linguas_files==True or such, then read 'LINGUAS' file. + linguas_files = ['LINGUAS'] + if linguas_files is None: + return [] + fnodes = env.arg2nodes(linguas_files) + linguas = [] + for fnode in fnodes: + contents = _re_comment.sub("", fnode.get_text_contents()) + ls = [l for l in _re_lang.findall(contents) if l] + linguas.extend(ls) + return linguas + + ############################################################################# ############################################################################# 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. + """ `PO` file builder. - **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, - when new language `ll` enters `LINGUAS_FILE` (at this moment there is no - `ll.po` file yet). To avoid this, we override - `SCons.Builder.BuilerBase._execute()` and call it separatelly for each - target. Here we also append to the target list the languages read from - `LINGUAS_FILE`. - """ - # - #* The argument for overriding _execute(): We must use environment with - # builder overrides applied (see BuilderBase.__init__(). Here it comes for - # free. - #* The argument against using 'emitter': The emitter is called too late - # by BuilderBase._execute(). If user calls, for example: - # - # env.POUpdate(LINGUAS_FILE = 'LINGUAS') - # - # the builder throws error, because it is called with target=None, - # source=None and is trying to "generate" sources or target list first. - # If user calls - # - # env.POUpdate(['foo', 'baz'], LINGUAS_FILE = 'LINGUAS') - # - # the env.BuilderWrapper() calls our builder with target=None, - # source=['foo', 'baz']. The BuilderBase._execute() then splits execution - # and execute iterativelly (recursion) self._execute(None, source[i]). - # 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: - kw['suffix'] = '$POSUFFIX' - if not 'src_suffix' in kw: - kw['src_suffix'] = '$POTSUFFIX' - if not 'src_builder' in kw: - kw['src_builder'] = '_POTUpdateBuilder' - if not 'single_source' 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: - kw['target_factory'] = _POTargetFactory(env, alias=alias).File - BuilderBase.__init__(self, **kw) - - def _execute(self, env, target, source, *args, **kw): - """ Execute builder's actions. + 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. - 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()`. + **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, + when new language `ll` enters `LINGUAS_FILE` (at this moment there is no + `ll.po` file yet). To avoid this, we override + `SCons.Builder.BuilerBase._execute()` and call it separatelly for each + target. Here we also append to the target list the languages read from + `LINGUAS_FILE`. """ - import SCons.Util - import SCons.Node - linguas_files = None - if env.has_key('LINGUAS_FILE') and env['LINGUAS_FILE']: - linguas_files = env['LINGUAS_FILE'] - # This prevents endless recursion loop (we'll be invoked once for - # each target appended here, we must not extend the list again). - env['LINGUAS_FILE'] = None - linguas = _read_linguas_from_files(env,linguas_files) - if SCons.Util.is_List(target): - target.extend(linguas) - elif target is not None: - target = [target] + linguas - else: - target = linguas - if not target: - # Let the SCons.BuilderBase to handle this patologic situation - return BuilderBase._execute( self, env, target, source, *args, **kw) - # The rest is ours - if not SCons.Util.is_List(target): - target = [ target ] - result = [] - for tgt in target: - r = BuilderBase._execute( self, env, [tgt], source, *args, **kw) - result.extend(r) - if linguas_files is not None: - env['LINGUAS_FILE'] = linguas_files - return SCons.Node.NodeList(result) + + # + # * The argument for overriding _execute(): We must use environment with + # builder overrides applied (see BuilderBase.__init__(). Here it comes for + # free. + # * The argument against using 'emitter': The emitter is called too late + # by BuilderBase._execute(). If user calls, for example: + # + # env.POUpdate(LINGUAS_FILE = 'LINGUAS') + # + # the builder throws error, because it is called with target=None, + # source=None and is trying to "generate" sources or target list first. + # If user calls + # + # env.POUpdate(['foo', 'baz'], LINGUAS_FILE = 'LINGUAS') + # + # the env.BuilderWrapper() calls our builder with target=None, + # source=['foo', 'baz']. The BuilderBase._execute() then splits execution + # and execute iterativelly (recursion) self._execute(None, source[i]). + # 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: + kw['suffix'] = '$POSUFFIX' + if not 'src_suffix' in kw: + kw['src_suffix'] = '$POTSUFFIX' + if not 'src_builder' in kw: + kw['src_builder'] = '_POTUpdateBuilder' + if not 'single_source' 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: + 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 + apply `SCons.Builder.BuilderBase._execute()` separatelly to each target. + The arguments and return value are same as for + `SCons.Builder.BuilderBase._execute()`. + """ + import SCons.Util + import SCons.Node + linguas_files = None + if 'LINGUAS_FILE' in env and env['LINGUAS_FILE']: + linguas_files = env['LINGUAS_FILE'] + # This prevents endless recursion loop (we'll be invoked once for + # each target appended here, we must not extend the list again). + env['LINGUAS_FILE'] = None + linguas = _read_linguas_from_files(env, linguas_files) + if SCons.Util.is_List(target): + target.extend(linguas) + elif target is not None: + target = [target] + linguas + else: + target = linguas + if not target: + # Let the SCons.BuilderBase to handle this patologic situation + return BuilderBase._execute(self, env, target, source, *args, **kw) + # The rest is ours + if not SCons.Util.is_List(target): + target = [target] + result = [] + for tgt in target: + r = BuilderBase._execute(self, env, [tgt], source, *args, **kw) + result.extend(r) + if linguas_files is not None: + env['LINGUAS_FILE'] = linguas_files + return SCons.Node.NodeList(result) + + ############################################################################# import SCons.Environment + + ############################################################################# def _translate(env, target=None, source=SCons.Environment._null, *args, **kw): - """ Function for `Translate()` pseudo-builder """ - if target is None: target = [] - pot = env.POTUpdate(None, source, *args, **kw) - po = env.POUpdate(target, pot, *args, **kw) - return po + """ Function for `Translate()` pseudo-builder """ + if target is None: target = [] + pot = env.POTUpdate(None, source, *args, **kw) + po = env.POUpdate(target, pot, *args, **kw) + return po + + ############################################################################# ############################################################################# 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/` - directory and source files (e.g. `*.c`) outside of it. When generating `POT` - template file, references to source files are written to `POT` template, so - a translator may later quickly jump to appropriate source file and line from - its `PO` editor (e.g. `poedit`). Relative paths in `PO` file are usually - interpreted by `PO` editor as paths relative to the place, where `PO` file - lives. The absolute paths would make resultant `POT` file nonportable, as - 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 - ... - sources = '$( ${_concat( "", SOURCES, "", __env__, XgettextRPaths, TARGET, SOURCES)} $)' - env.Append( - ... - XGETTEXTCOM = 'XGETTEXT ... ' + sources, - ... - XgettextRPaths = RPaths(env) - ) - """ - # NOTE: This callable object returns pathnames of dirs/files relative to - # current working directory. The pathname remains relative also for entries - # that are outside of current working directory (node, that - # SCons.Node.FS.File and siblings return absolute path in such case). For - # simplicity we compute path relative to current working directory, this - # seems be enough for our purposes (don't need TARGET variable and - # SCons.Defaults.Variable_Caller stuff). + """ Callable object, which returns pathnames relative to SCons current + working directory. - def __init__(self, env): - """ Initialize `RPaths` callable object. - - **Arguments**: - - - *env* - a `SCons.Environment.Environment` object, defines *current - working dir*. + 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/` + directory and source files (e.g. `*.c`) outside of it. When generating `POT` + template file, references to source files are written to `POT` template, so + a translator may later quickly jump to appropriate source file and line from + its `PO` editor (e.g. `poedit`). Relative paths in `PO` file are usually + interpreted by `PO` editor as paths relative to the place, where `PO` file + lives. The absolute paths would make resultant `POT` file nonportable, as + 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 + ... + sources = '$( ${_concat( "", SOURCES, "", __env__, XgettextRPaths, TARGET, SOURCES)} $)' + env.Append( + ... + XGETTEXTCOM = 'XGETTEXT ... ' + sources, + ... + XgettextRPaths = RPaths(env) + ) """ - self.env = env - # 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. - - **Arguments**: + # NOTE: This callable object returns pathnames of dirs/files relative to + # current working directory. The pathname remains relative also for entries + # that are outside of current working directory (node, that + # SCons.Node.FS.File and siblings return absolute path in such case). For + # simplicity we compute path relative to current working directory, this + # seems be enough for our purposes (don't need TARGET variable and + # SCons.Defaults.Variable_Caller stuff). - - *nodes* ([`SCons.Node.FS.Base`]) - list of nodes. - - *args* - currently unused. - - *kw* - currently unused. + def __init__(self, env): + """ Initialize `RPaths` callable object. + + **Arguments**: + + - *env* - a `SCons.Environment.Environment` object, defines *current + working dir*. + """ + self.env = env + + # 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. + + **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). + """ + import os + import SCons.Node.FS + rpaths = () + cwd = self.env.fs.getcwd().get_abspath() + for node in nodes: + rpath = None + if isinstance(node, SCons.Node.FS.Base): + rpath = os.path.relpath(node.get_abspath(), cwd) + # FIXME: Other types possible here? + if rpath is not None: + rpaths += (rpath,) + return rpaths - **Returns**: - - Tuple of strings, which represent paths relative to current working - directory (for given environment). - """ - import os - import SCons.Node.FS - rpaths = () - cwd = self.env.fs.getcwd().get_abspath() - for node in nodes: - rpath = None - if isinstance(node, SCons.Node.FS.Base): - rpath = os.path.relpath(node.get_abspath(), cwd) - # FIXME: Other types possible here? - if rpath is not None: - rpaths += (rpath,) - return rpaths ############################################################################# - + ############################################################################# def _init_po_files(target, source, env): - """ Action function for `POInit` builder. """ - nop = lambda target, source, env : 0 - if env.has_key('POAUTOINIT'): - autoinit = env['POAUTOINIT'] - else: - autoinit = False - # Well, if everything outside works well, this loop should do single - # iteration. Otherwise we are rebuilding all the targets even, if just - # one has changed (but is this our fault?). - for tgt in target: - if not tgt.exists(): - if autoinit: - action = SCons.Action.Action('$MSGINITCOM', '$MSGINITCOMSTR') - else: - msg = 'File ' + repr(str(tgt)) + ' does not exist. ' \ - + 'If you are a translator, you can create it through: \n' \ - + '$MSGINITCOM' - action = SCons.Action.Action(nop, msg) - status = action([tgt], source, env) - if status: return status - return 0 + """ Action function for `POInit` builder. """ + nop = lambda target, source, env: 0 + if 'POAUTOINIT' in env: + autoinit = env['POAUTOINIT'] + else: + autoinit = False + # Well, if everything outside works well, this loop should do single + # iteration. Otherwise we are rebuilding all the targets even, if just + # one has changed (but is this our fault?). + for tgt in target: + if not tgt.exists(): + if autoinit: + action = SCons.Action.Action('$MSGINITCOM', '$MSGINITCOMSTR') + else: + msg = 'File ' + repr(str(tgt)) + ' does not exist. ' \ + + 'If you are a translator, you can create it through: \n' \ + + '$MSGINITCOM' + action = SCons.Action.Action(nop, msg) + status = action([tgt], source, env) + if status: return status + return 0 + + ############################################################################# ############################################################################# def _detect_xgettext(env): - """ Detects *xgettext(1)* binary """ - if env.has_key('XGETTEXT'): - return env['XGETTEXT'] - xgettext = env.Detect('xgettext'); - if xgettext: - return xgettext - raise SCons.Errors.StopError(XgettextNotFound,"Could not detect xgettext") - return None + """ Detects *xgettext(1)* binary """ + if 'XGETTEXT' in env: + return env['XGETTEXT'] + xgettext = env.Detect('xgettext'); + if xgettext: + return xgettext + raise SCons.Errors.StopError(XgettextNotFound, "Could not detect xgettext") + return None + + ############################################################################# def _xgettext_exists(env): - return _detect_xgettext(env) + return _detect_xgettext(env) + + ############################################################################# ############################################################################# def _detect_msginit(env): - """ Detects *msginit(1)* program. """ - if env.has_key('MSGINIT'): - return env['MSGINIT'] - msginit = env.Detect('msginit'); - if msginit: - return msginit - raise SCons.Errors.StopError(MsginitNotFound, "Could not detect msginit") - return None + """ Detects *msginit(1)* program. """ + if 'MSGINIT' in env: + return env['MSGINIT'] + msginit = env.Detect('msginit'); + if msginit: + return msginit + raise SCons.Errors.StopError(MsginitNotFound, "Could not detect msginit") + return None + + ############################################################################# def _msginit_exists(env): - return _detect_msginit(env) + return _detect_msginit(env) + + ############################################################################# ############################################################################# def _detect_msgmerge(env): - """ Detects *msgmerge(1)* program. """ - if env.has_key('MSGMERGE'): - return env['MSGMERGE'] - msgmerge = env.Detect('msgmerge'); - if msgmerge: - return msgmerge - raise SCons.Errors.StopError(MsgmergeNotFound, "Could not detect msgmerge") - return None + """ Detects *msgmerge(1)* program. """ + if 'MSGMERGE' in env: + return env['MSGMERGE'] + msgmerge = env.Detect('msgmerge'); + if msgmerge: + return msgmerge + raise SCons.Errors.StopError(MsgmergeNotFound, "Could not detect msgmerge") + return None + + ############################################################################# def _msgmerge_exists(env): - return _detect_msgmerge(env) + return _detect_msgmerge(env) + + ############################################################################# ############################################################################# def _detect_msgfmt(env): - """ Detects *msgmfmt(1)* program. """ - if env.has_key('MSGFMT'): - return env['MSGFMT'] - msgfmt = env.Detect('msgfmt'); - if msgfmt: - return msgfmt - raise SCons.Errors.StopError(MsgfmtNotFound, "Could not detect msgfmt") - return None + """ Detects *msgmfmt(1)* program. """ + if 'MSGFMT' in env: + return env['MSGFMT'] + msgfmt = env.Detect('msgfmt'); + if msgfmt: + return msgfmt + raise SCons.Errors.StopError(MsgfmtNotFound, "Could not detect msgfmt") + return None + + ############################################################################# def _msgfmt_exists(env): - return _detect_msgfmt(env) + return _detect_msgfmt(env) + + ############################################################################# ############################################################################# def tool_list(platform, env): - """ List tools that shall be generated by top-level `gettext` tool """ - return [ 'xgettext', 'msginit', 'msgmerge', 'msgfmt' ] -############################################################################# + """ List tools that shall be generated by top-level `gettext` tool """ + return ['xgettext', 'msginit', 'msgmerge', 'msgfmt'] +############################################################################# diff --git a/src/engine/SCons/Tool/JavaCommon.py b/src/engine/SCons/Tool/JavaCommon.py index 38f4e47..5c2507d 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 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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 @@ Stuff for processing Java. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/JavaCommon.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/JavaCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import os import os.path diff --git a/src/engine/SCons/Tool/JavaCommonTests.py b/src/engine/SCons/Tool/JavaCommonTests.py index 6a67370..da405f0 100644 --- a/src/engine/SCons/Tool/JavaCommonTests.py +++ b/src/engine/SCons/Tool/JavaCommonTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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/JavaCommonTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/JavaCommonTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import os.path import sys diff --git a/src/engine/SCons/Tool/MSCommon/__init__.py b/src/engine/SCons/Tool/MSCommon/__init__.py index 6b637fe..989ab08 100644 --- a/src/engine/SCons/Tool/MSCommon/__init__.py +++ b/src/engine/SCons/Tool/MSCommon/__init__.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" __doc__ = """ Common functions for Microsoft Visual Studio and Visual C/C++. @@ -41,7 +41,8 @@ from SCons.Tool.MSCommon.sdk import mssdk_exists, \ from SCons.Tool.MSCommon.vc import msvc_exists, \ msvc_setup_env, \ - msvc_setup_env_once + msvc_setup_env_once, \ + msvc_version_to_maj_min from SCons.Tool.MSCommon.vs import get_default_version, \ get_vs_by_version, \ diff --git a/src/engine/SCons/Tool/MSCommon/arch.py b/src/engine/SCons/Tool/MSCommon/arch.py index 46fb601..96f05a8 100644 --- a/src/engine/SCons/Tool/MSCommon/arch.py +++ b/src/engine/SCons/Tool/MSCommon/arch.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" __doc__ = """Module to define supported Windows chip architectures. """ diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index 1467543..fcf623f 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -1,5 +1,8 @@ +""" +Common helper functions for working with the Microsoft tool chain. +""" # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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,12 +23,9 @@ # 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 __future__ import print_function -__revision__ = "src/engine/SCons/Tool/MSCommon/common.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" - -__doc__ = """ -Common helper functions for working with the Microsoft tool chain. -""" +__revision__ = "src/engine/SCons/Tool/MSCommon/common.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import copy import os @@ -35,17 +35,17 @@ import re import SCons.Util -logfile = os.environ.get('SCONS_MSCOMMON_DEBUG') -if logfile == '-': - def debug(x): - print x -elif logfile: +LOGFILE = os.environ.get('SCONS_MSCOMMON_DEBUG') +if LOGFILE == '-': + def debug(message): + print(message) +elif LOGFILE: try: import logging except ImportError: - debug = lambda x: open(logfile, 'a').write(x + '\n') + debug = lambda message: open(LOGFILE, 'a').write(message + '\n') else: - logging.basicConfig(filename=logfile, level=logging.DEBUG) + logging.basicConfig(filename=LOGFILE, level=logging.DEBUG) debug = logging.debug else: debug = lambda x: None @@ -75,7 +75,7 @@ def is_win64(): # I structured these tests to make it easy to add new ones or # add exceptions in the future, because this is a bit fragile. _is_win64 = False - if os.environ.get('PROCESSOR_ARCHITECTURE','x86') != 'x86': + if os.environ.get('PROCESSOR_ARCHITECTURE', 'x86') != 'x86': _is_win64 = True if os.environ.get('PROCESSOR_ARCHITEW6432'): _is_win64 = True @@ -113,21 +113,30 @@ def normalize_env(env, keys, force=False): Note: the environment is copied.""" normenv = {} if env: - for k in env.keys(): - normenv[k] = copy.deepcopy(env[k]).encode('mbcs') + for k in list(env.keys()): + normenv[k] = copy.deepcopy(env[k]) for k in keys: if k in os.environ and (force or not k in normenv): - normenv[k] = os.environ[k].encode('mbcs') + normenv[k] = os.environ[k] # This shouldn't be necessary, since the default environment should include system32, # but keep this here to be safe, since it's needed to find reg.exe which the MSVC # bat scripts use. - sys32_dir = os.path.join(os.environ.get("SystemRoot", os.environ.get("windir",r"C:\Windows\system32")),"System32") + sys32_dir = os.path.join(os.environ.get("SystemRoot", + os.environ.get("windir", r"C:\Windows\system32")), + "System32") if sys32_dir not in normenv['PATH']: normenv['PATH'] = normenv['PATH'] + os.pathsep + sys32_dir + # Without Wbem in PATH, vcvarsall.bat has a "'wmic' is not recognized" + # error starting with Visual Studio 2017, although the script still + # seems to work anyway. + sys32_wbem_dir = os.path.join(sys32_dir, 'Wbem') + if sys32_wbem_dir not in normenv['PATH']: + normenv['PATH'] = normenv['PATH'] + os.pathsep + sys32_wbem_dir + debug("PATH: %s"%normenv['PATH']) return normenv @@ -144,11 +153,13 @@ def get_output(vcbat, args = None, env = None): # execution to work. This list should really be either directly # controlled by vc.py, or else derived from the common_tools_var # settings in vs.py. - vars = [ + vs_vc_vars = [ 'COMSPEC', -# VS100 and VS110: Still set, but modern MSVC setup scripts will -# discard these if registry has values. However Intel compiler setup -# script still requires these as of 2013/2014. + # VS100 and VS110: Still set, but modern MSVC setup scripts will + # discard these if registry has values. However Intel compiler setup + # script still requires these as of 2013/2014. + 'VS140COMNTOOLS', + 'VS120COMNTOOLS', 'VS110COMNTOOLS', 'VS100COMNTOOLS', 'VS90COMNTOOLS', @@ -157,22 +168,22 @@ def get_output(vcbat, args = None, env = None): 'VS70COMNTOOLS', 'VS60COMNTOOLS', ] - env['ENV'] = normalize_env(env['ENV'], vars, force=False) + env['ENV'] = normalize_env(env['ENV'], vs_vc_vars, force=False) if args: debug("Calling '%s %s'" % (vcbat, args)) popen = SCons.Action._subproc(env, - '"%s" %s & set' % (vcbat, args), - stdin = 'devnull', - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + '"%s" %s & set' % (vcbat, args), + stdin='devnull', + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) else: debug("Calling '%s'" % vcbat) popen = SCons.Action._subproc(env, - '"%s" & set' % vcbat, - stdin = 'devnull', - stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + '"%s" & set' % vcbat, + stdin='devnull', + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) # Use the .stdout and .stderr attributes directly because the # .communicate() method uses the threading module on Windows @@ -195,10 +206,14 @@ 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")): + """ + Parse output from running visual c++/studios vcvarsall.bat and running set + To capture the values listed in keep + """ + # dkeep is a dict associating key: path_list, where key is one item from # keep, and pat_list the associated list of paths - dkeep = dict([(i, []) for i in keep]) # rdk will keep the regex to match the .bat file output line starts @@ -207,22 +222,21 @@ def parse_output(output, keep = ("INCLUDE", "LIB", "LIBPATH", "PATH")): rdk[i] = re.compile('%s=(.*)' % i, re.I) def add_env(rmatch, key, dkeep=dkeep): - plist = rmatch.group(1).split(os.pathsep) - for p in plist: + path_list = rmatch.group(1).split(os.pathsep) + for path in path_list: # Do not add empty paths (when a var ends with ;) - if p: - p = p.encode('mbcs') + if path: # XXX: For some reason, VC98 .bat file adds "" around the PATH # values, and it screws up the environment later, so we strip # it. - p = p.strip('"') - dkeep[key].append(p) + path = path.strip('"') + dkeep[key].append(str(path)) for line in output.splitlines(): - for k,v in rdk.items(): - m = v.match(line) - if m: - add_env(m, k) + for k, value in rdk.items(): + match = value.match(line) + if match: + add_env(match, k) return dkeep diff --git a/src/engine/SCons/Tool/MSCommon/netframework.py b/src/engine/SCons/Tool/MSCommon/netframework.py index 8d39cf6..b769c44 100644 --- a/src/engine/SCons/Tool/MSCommon/netframework.py +++ b/src/engine/SCons/Tool/MSCommon/netframework.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" __doc__ = """ """ @@ -29,7 +29,7 @@ import os import re import SCons.Util -from common import read_reg, debug +from .common import read_reg, debug # Original value recorded by dcournapeau _FRAMEWORKDIR_HKEY_ROOT = r'Software\Microsoft\.NETFramework\InstallRoot' @@ -40,13 +40,13 @@ def find_framework_root(): # XXX: find it from environment (FrameworkDir) try: froot = read_reg(_FRAMEWORKDIR_HKEY_ROOT) - debug("Found framework install root in registry: %s" % froot) - except SCons.Util.WinError, e: - debug("Could not read reg key %s" % _FRAMEWORKDIR_HKEY_ROOT) + debug("Found framework install root in registry: {}".format(froot)) + except SCons.Util.WinError as e: + debug("Could not read reg key {}".format(_FRAMEWORKDIR_HKEY_ROOT)) return None if not os.path.exists(froot): - debug("%s not found on fs" % froot) + debug("{} not found on fs".format(froot)) return None return froot diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index 53bb8aa..8bc9830 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" __doc__ = """Module to detect the Platform/Windows SDK @@ -33,7 +33,7 @@ import os import SCons.Errors import SCons.Util -import common +from . import common debug = common.debug @@ -76,23 +76,23 @@ class SDKDefinition(object): return None hkey = self.HKEY_FMT % self.hkey_data - debug('find_sdk_dir(): checking registry:%s'%hkey) + debug('find_sdk_dir(): checking registry:{}'.format(hkey)) try: sdk_dir = common.read_reg(hkey) - except SCons.Util.WinError, e: - debug('find_sdk_dir(): no SDK registry key %s' % repr(hkey)) + except SCons.Util.WinError as e: + debug('find_sdk_dir(): no SDK registry key {}'.format(repr(hkey))) return None - debug('find_sdk_dir(): Trying SDK Dir: %s'%sdk_dir) + debug('find_sdk_dir(): Trying SDK Dir: {}'.format(sdk_dir)) if not os.path.exists(sdk_dir): - debug('find_sdk_dir(): %s not on file system' % sdk_dir) + debug('find_sdk_dir(): {} not on file system'.format(sdk_dir)) return None ftc = os.path.join(sdk_dir, self.sanity_check_file) if not os.path.exists(ftc): - debug("find_sdk_dir(): sanity check %s not found" % ftc) + debug("find_sdk_dir(): sanity check {} not found".format(ftc)) return None return sdk_dir @@ -105,7 +105,7 @@ class SDKDefinition(object): sdk_dir = self.find_sdk_dir() self._sdk_dir = sdk_dir return sdk_dir - + def get_sdk_vc_script(self,host_arch, target_arch): """ Return the script to initialize the VC compiler installed by SDK """ @@ -113,11 +113,11 @@ class SDKDefinition(object): if (host_arch == 'amd64' and target_arch == 'x86'): # No cross tools needed compiling 32 bits on 64 bit machine host_arch=target_arch - + arch_string=target_arch if (host_arch != target_arch): arch_string='%s_%s'%(host_arch,target_arch) - + debug("sdk.py: get_sdk_vc_script():arch_string:%s host_arch:%s target_arch:%s"%(arch_string, host_arch, target_arch)) @@ -164,6 +164,12 @@ SDK70VCSetupScripts = { 'x86' : r'bin\vcvars32.bat', 'x86_ia64' : r'bin\vcvarsx86_ia64.bat', 'ia64' : r'bin\vcvarsia64.bat'} +SDK100VCSetupScripts = {'x86' : r'bin\vcvars32.bat', + 'amd64' : r'bin\vcvars64.bat', + 'x86_amd64': r'bin\x86_amd64\vcvarsx86_amd64.bat', + 'x86_arm' : r'bin\x86_arm\vcvarsx86_arm.bat'} + + # The list of support SDKs which we know how to detect. # # The first SDK found in the list is the one used by default if there @@ -172,6 +178,16 @@ SDK70VCSetupScripts = { 'x86' : r'bin\vcvars32.bat', # # If you update this list, update the documentation in Tool/mssdk.xml. SupportedSDKList = [ + WindowsSDK('10.0', + 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('7.1', sanity_check_file=r'bin\SetEnv.Cmd', include_subdir='include', @@ -308,8 +324,7 @@ def set_sdk_by_directory(env, sdk_dir): def get_sdk_by_version(mssdk): if mssdk not in SupportedSDKMap: - msg = "SDK version %s is not supported" % repr(mssdk) - raise SCons.Errors.UserError(msg) + raise SCons.Errors.UserError("SDK version {} is not supported".format(repr(mssdk))) get_installed_sdks() return InstalledSDKMap.get(mssdk) @@ -327,16 +342,16 @@ def mssdk_setup_env(env): if sdk_dir is None: return sdk_dir = env.subst(sdk_dir) - debug('sdk.py:mssdk_setup_env: Using MSSDK_DIR:%s'%sdk_dir) + debug('sdk.py:mssdk_setup_env: Using MSSDK_DIR:{}'.format(sdk_dir)) elif 'MSSDK_VERSION' in env: sdk_version = env['MSSDK_VERSION'] if sdk_version is None: - msg = "SDK version is specified as None" + msg = "SDK version is specified as None" raise SCons.Errors.UserError(msg) sdk_version = env.subst(sdk_version) mssdk = get_sdk_by_version(sdk_version) if mssdk is None: - msg = "SDK version %s is not installed" % sdk_version + msg = "SDK version %s is not installed" % sdk_version raise SCons.Errors.UserError(msg) sdk_dir = mssdk.get_sdk_dir() debug('sdk.py:mssdk_setup_env: Using MSSDK_VERSION:%s'%sdk_dir) @@ -347,7 +362,7 @@ def mssdk_setup_env(env): debug('sdk.py:mssdk_setup_env thinks msvs_version is None') return msvs_version = env.subst(msvs_version) - import vs + from . import vs msvs = vs.get_vs_by_version(msvs_version) debug('sdk.py:mssdk_setup_env:msvs is :%s'%msvs) if not msvs: diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index ca8a2da..fba86af 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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,24 +30,25 @@ # * test on 64 bits XP + VS 2005 (and VS 6 if possible) # * SDK # * Assembly -__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" __doc__ = """Module for Visual C/C++ detection and configuration. """ import SCons.compat import SCons.Util +import subprocess import os import platform from string import digits as string_digits import SCons.Warnings -import common +from . import common debug = common.debug -import sdk +from . import sdk get_installed_sdks = sdk.get_installed_sdks @@ -108,7 +109,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) @@ -118,26 +119,28 @@ 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, e: + except KeyError as e: msg = "Unrecognized host architecture %s" raise ValueError(msg % repr(host_platform)) try: target = _ARCH_TO_CANONICAL[target_platform.lower()] - except KeyError, e: - all_archs = str(_ARCH_TO_CANONICAL.keys()) + except KeyError as e: + all_archs = str(list(_ARCH_TO_CANONICAL.keys())) raise ValueError("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.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.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_TO_PRODUCT_DIR = { + '14.1' : [ + (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # Visual Studio 2017 doesn't set this registry key anymore '14.0' : [ (SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\14.0\Setup\VC\ProductDir')], '14.0Exp' : [ @@ -183,19 +186,19 @@ _VCVER_TO_PRODUCT_DIR = { (SCons.Util.HKEY_LOCAL_MACHINE, 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 + '.']) - - t = msvc_version_numeric.split(".") - if not len(t) == 2: - raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) - try: - maj = int(t[0]) - min = int(t[1]) - return maj, min - except ValueError, e: - raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) + msvc_version_numeric = ''.join([x for x in msvc_version if x in string_digits + '.']) + + t = msvc_version_numeric.split(".") + if not len(t) == 2: + raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) + try: + maj = int(t[0]) + min = int(t[1]) + return maj, min + except ValueError as e: + 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 @@ -222,6 +225,35 @@ def is_host_target_supported(host_target, msvc_version): 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 + """ + 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') + return vc_pdir + else: + # No vswhere on system, no install info available + return None + + def find_vc_pdir(msvc_version): """Try to find the product directory for the given version. @@ -240,26 +272,31 @@ def find_vc_pdir(msvc_version): for hkroot, key in hkeys: try: comps = None - if common.is_win64(): - try: - # ordinally at win64, try Wow6432Node first. - comps = common.read_reg(root + 'Wow6432Node\\' + key, hkroot) - except SCons.Util.WinError, e: - # at Microsoft Visual Studio for Python 2.7, value is not in Wow6432Node - pass - if not comps: - # not Win64, or Microsoft Visual Studio for Python 2.7 - comps = common.read_reg(root + key, hkroot) - except SCons.Util.WinError, e: - debug('find_vc_dir(): no VC registry key %s' % repr(key)) + 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))) + raise SCons.Util.WinError + else: + if common.is_win64(): + try: + # ordinally at win64, try Wow6432Node first. + comps = common.read_reg(root + 'Wow6432Node\\' + key, hkroot) + except SCons.Util.WinError as e: + # at Microsoft Visual Studio for Python 2.7, value is not in Wow6432Node + pass + if not comps: + # not Win64, or Microsoft Visual Studio for Python 2.7 + comps = common.read_reg(root + key, hkroot) + except SCons.Util.WinError as e: + debug('find_vc_dir(): no VC registry key {}'.format(repr(key))) else: - debug('find_vc_dir(): found VC in registry: %s' % comps) + debug('find_vc_dir(): found VC in registry: {}'.format(comps)) if os.path.exists(comps): return comps else: - debug('find_vc_dir(): reg says dir is %s, but it does not exist. (ignoring)'\ - % comps) - raise MissingConfiguration("registry dir %s not found on the filesystem" % comps) + debug('find_vc_dir(): reg says dir is {}, but it does not exist. (ignoring)'.format(comps)) + raise MissingConfiguration("registry dir {} not found on the filesystem".format(comps)) return None def find_batch_file(env,msvc_version,host_arch,target_arch): @@ -270,8 +307,8 @@ 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) + + debug('vc.py: find_batch_file() pdir:{}'.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 + "."]) @@ -282,13 +319,15 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): elif vernum < 7: pdir = os.path.join(pdir, "Bin") batfilename = os.path.join(pdir, "vcvars32.bat") - else: # >= 8 + elif 8 <= vernum <= 14: batfilename = os.path.join(pdir, "vcvarsall.bat") + else: # vernum >= 14.1 VS2017 and above + batfilename = os.path.join(pdir, "Auxiliary", "Build", "vcvarsall.bat") 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) @@ -296,7 +335,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) @@ -323,7 +362,7 @@ def get_installed_vcs(): installed_versions.append(ver) else: debug('find_vc_pdir return None for ver %s' % ver) - except VisualCException, e: + except VisualCException as e: debug('did not find VC %s: caught exception %s' % (ver, str(e))) return installed_versions @@ -359,7 +398,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: @@ -409,7 +448,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') @@ -427,7 +466,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): @@ -436,11 +475,19 @@ def msvc_find_valid_batch_script(env,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+ + if maj >= 14: + if env.get('MSVC_UWP_APP') == '1': + # Initialize environment variables with store/universal paths + arg += ' store' + # 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) debug('vc.py:msvc_find_valid_batch_script() vc_script:%s sdk_script:%s'%(vc_script,sdk_script)) - except VisualCException, e: + except VisualCException as e: msg = str(e) debug('Caught exception while looking for batch file (%s)' % msg) warn_msg = "VC version %s not installed. " + \ @@ -449,13 +496,13 @@ 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: try: d = script_env(vc_script, args=arg) - except BatchFileExecutionError, e: + 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 continue @@ -463,23 +510,23 @@ 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) - except BatchFileExecutionError,e: + 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()') @@ -498,12 +545,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: @@ -524,4 +571,3 @@ def msvc_exists(version=None): if version is None: return len(vcs) > 0 return version in vcs - diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index 1f04cbe..dafdbaf 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" __doc__ = """Module to detect Visual Studio and/or Visual C/C++ """ @@ -31,7 +31,7 @@ import os import SCons.Errors import SCons.Util -from common import debug, \ +from .common import debug, \ get_output, \ is_win64, \ normalize_env, \ @@ -83,10 +83,10 @@ class VisualStudio(object): key = root + key try: comps = read_reg(key) - except SCons.Util.WinError, e: - debug('find_vs_dir_by_reg(): no VS registry key %s' % repr(key)) + except SCons.Util.WinError as e: + debug('find_vs_dir_by_reg(): no VS registry key {}'.format(repr(key))) else: - debug('find_vs_dir_by_reg(): found VS in registry: %s' % comps) + debug('find_vs_dir_by_reg(): found VS in registry: {}'.format(comps)) return comps return None @@ -105,12 +105,12 @@ class VisualStudio(object): def find_executable(self): vs_dir = self.get_vs_dir() if not vs_dir: - debug('find_executable(): no vs_dir (%s)'%vs_dir) + debug('find_executable(): no vs_dir ({})'.format(vs_dir)) return None executable = os.path.join(vs_dir, self.executable_path) executable = os.path.normpath(executable) if not os.path.isfile(executable): - debug('find_executable(): %s not on file system' % executable) + debug('find_executable(): {} not on file system'.format(executable)) return None return executable @@ -199,17 +199,28 @@ class VisualStudio(object): # Tool/MSCommon/vc.py, and the MSVC_VERSION documentation in Tool/msvc.xml. SupportedVSList = [ + # Visual Studio 2017 + VisualStudio('14.1', + vc_version='14.1', + sdk_version='10.0A', + hkeys=[], + common_tools_var='VS150COMNTOOLS', + executable_path=r'Common7\IDE\devenv.com', + batch_file_path=r'VC\Auxiliary\Build\vsvars32.bat', + supported_arch=['x86', 'amd64', "arm"], + ), + # Visual Studio 2015 VisualStudio('14.0', vc_version='14.0', - sdk_version='10.0A', + sdk_version='10.0', hkeys=[r'Microsoft\VisualStudio\14.0\Setup\VS\ProductDir'], common_tools_var='VS140COMNTOOLS', executable_path=r'Common7\IDE\devenv.com', batch_file_path=r'Common7\Tools\vsvars32.bat', supported_arch=['x86', 'amd64', "arm"], ), - + # Visual C++ 2015 Express Edition (for Desktop) VisualStudio('14.0Exp', vc_version='14.0', diff --git a/src/engine/SCons/Tool/Perforce.py b/src/engine/SCons/Tool/Perforce.py deleted file mode 100644 index 212150a..0000000 --- a/src/engine/SCons/Tool/Perforce.py +++ /dev/null @@ -1,99 +0,0 @@ -"""SCons.Tool.Perforce.py - -Tool-specific initialization for Perforce Source Code Management system. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# Copyright (c) 2001 - 2016 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/Perforce.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" - -import os - -import SCons.Action -import SCons.Builder -import SCons.Node.FS -import SCons.Util - - -# Variables that we want to import from the base OS environment. -_import_env = [ 'P4PORT', 'P4CLIENT', 'P4USER', 'USER', 'USERNAME', 'P4PASSWD', - 'P4CHARSET', 'P4LANGUAGE', 'SystemRoot' ] - -PerforceAction = SCons.Action.Action('$P4COM', '$P4COMSTR') - -def generate(env): - """Add a Builder factory function and construction variables for - Perforce to an Environment.""" - - def PerforceFactory(env=env): - """ """ - import SCons.Warnings as W - W.warn(W.DeprecatedSourceCodeWarning, """The Perforce() factory is deprecated and there is no replacement.""") - return SCons.Builder.Builder(action = PerforceAction, env = env) - - env.Perforce = PerforceFactory - - env['P4'] = 'p4' - env['P4FLAGS'] = SCons.Util.CLVar('') - env['P4COM'] = '$P4 $P4FLAGS sync $TARGET' - try: - environ = env['ENV'] - except KeyError: - environ = {} - env['ENV'] = environ - - # Perforce seems to use the PWD environment variable rather than - # calling getcwd() for itself, which is odd. If no PWD variable - # is present, p4 WILL call getcwd, but this seems to cause problems - # with good ol' Windows's tilde-mangling for long file names. - environ['PWD'] = env.Dir('#').get_abspath() - - for var in _import_env: - v = os.environ.get(var) - if v: - environ[var] = v - - if SCons.Util.can_read_reg: - # If we can read the registry, add the path to Perforce to our environment. - try: - k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, - 'Software\\Perforce\\environment') - val, tok = SCons.Util.RegQueryValueEx(k, 'P4INSTROOT') - SCons.Util.AddPathIfNotExists(environ, 'PATH', val) - except SCons.Util.RegError: - # Can't detect where Perforce is, hope the user has it set in the - # PATH. - pass - -def exists(env): - return env.Detect('p4') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/Perforce.xml b/src/engine/SCons/Tool/Perforce.xml deleted file mode 100644 index 2431c72..0000000 --- a/src/engine/SCons/Tool/Perforce.xml +++ /dev/null @@ -1,129 +0,0 @@ - - - - -%scons; - -%builders-mod; - -%functions-mod; - -%tools-mod; - -%variables-mod; -]> - - - - - - -Sets construction variables for interacting with the -Perforce source code management system. - - - -P4 -P4FLAGS -P4COM - - -P4COMSTR - - - - - - -The Perforce executable. - - - - - - - -The command line used to -fetch source files from Perforce. - - - - - - - -The string displayed when -fetching a source file from Perforce. -If this is not set, then &cv-link-P4COM; (the command line) is displayed. - - - - - - - -General options that are passed to Perforce. - - - - - - -() - - - -A factory function that -returns a Builder object -to be used to fetch source files -from the Perforce source code management system. -The returned Builder -is intended to be passed to the -&f-SourceCode; -function. - - - -This function is deprecated. For details, see the entry for the -&f-SourceCode; -function. - - - -Example: - - - -env.SourceCode('.', env.Perforce()) - - - -Perforce uses a number of external -environment variables for its operation. -Consequently, this function adds the -following variables from the user's external environment -to the construction environment's -ENV dictionary: -P4CHARSET, -P4CLIENT, -P4LANGUAGE, -P4PASSWD, -P4PORT, -P4USER, -SystemRoot, -USER, -and -USERNAME. - - - - - diff --git a/src/engine/SCons/Tool/PharLapCommon.py b/src/engine/SCons/Tool/PharLapCommon.py index ccc2004..c45c6d3 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 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/PharLapCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import os import os.path diff --git a/src/engine/SCons/Tool/RCS.py b/src/engine/SCons/Tool/RCS.py deleted file mode 100644 index 7a8b8b1..0000000 --- a/src/engine/SCons/Tool/RCS.py +++ /dev/null @@ -1,63 +0,0 @@ -"""SCons.Tool.RCS.py - -Tool-specific initialization for RCS. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# Copyright (c) 2001 - 2016 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/RCS.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" - -import SCons.Action -import SCons.Builder -import SCons.Util - -def generate(env): - """Add a Builder factory function and construction variables for - RCS to an Environment.""" - - def RCSFactory(env=env): - """ """ - import SCons.Warnings as W - W.warn(W.DeprecatedSourceCodeWarning, """The RCS() factory is deprecated and there is no replacement.""") - act = SCons.Action.Action('$RCS_COCOM', '$RCS_COCOMSTR') - return SCons.Builder.Builder(action = act, env = env) - - env.RCS = RCSFactory - - env['RCS'] = 'rcs' - env['RCS_CO'] = 'co' - env['RCS_COFLAGS'] = SCons.Util.CLVar('') - env['RCS_COCOM'] = '$RCS_CO $RCS_COFLAGS $TARGET' - -def exists(env): - return env.Detect('rcs') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/RCS.xml b/src/engine/SCons/Tool/RCS.xml deleted file mode 100644 index 3c034e4..0000000 --- a/src/engine/SCons/Tool/RCS.xml +++ /dev/null @@ -1,142 +0,0 @@ - - - - -%scons; - -%builders-mod; - -%functions-mod; - -%tools-mod; - -%variables-mod; -]> - - - - - - -Sets construction variables for the interaction -with the Revision Control System. - - - -RCS -RCS_CO -RCS_COFLAGS -RCS_COCOM - - -RCS_COCOMSTR - - - - - - -The RCS executable. -Note that this variable is not actually used -for the command to fetch source files from RCS; -see the -&cv-link-RCS_CO; -construction variable, below. - - - - - - - -The RCS "checkout" executable, -used to fetch source files from RCS. - - - - - - - -The command line used to -fetch (checkout) source files from RCS. - - - - - - - -The string displayed when fetching -a source file from RCS. -If this is not set, then &cv-link-RCS_COCOM; -(the command line) is displayed. - - - - - - - -Options that are passed to the &cv-link-RCS_CO; command. - - - - - - -() - - - -A factory function that -returns a Builder object -to be used to fetch source files -from RCS. -The returned Builder -is intended to be passed to the -&f-SourceCode; -function: - - - -This function is deprecated. For details, see the entry for the -&f-SourceCode; -function. - - - -Examples: - - - -env.SourceCode('.', env.RCS()) - - - -Note that -&scons; -will fetch source files -from RCS subdirectories automatically, -so configuring RCS -as demonstrated in the above example -should only be necessary if -you are fetching from -RCS,v -files in the same -directory as the source files, -or if you need to explicitly specify RCS -for a specific subdirectory. - - - - - diff --git a/src/engine/SCons/Tool/SCCS.py b/src/engine/SCons/Tool/SCCS.py deleted file mode 100644 index c4dbbf8..0000000 --- a/src/engine/SCons/Tool/SCCS.py +++ /dev/null @@ -1,63 +0,0 @@ -"""SCons.Tool.SCCS.py - -Tool-specific initialization for SCCS. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# Copyright (c) 2001 - 2016 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/SCCS.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" - -import SCons.Action -import SCons.Builder -import SCons.Util - -def generate(env): - """Add a Builder factory function and construction variables for - SCCS to an Environment.""" - - def SCCSFactory(env=env): - """ """ - import SCons.Warnings as W - W.warn(W.DeprecatedSourceCodeWarning, """The SCCS() factory is deprecated and there is no replacement.""") - act = SCons.Action.Action('$SCCSCOM', '$SCCSCOMSTR') - return SCons.Builder.Builder(action = act, env = env) - - env.SCCS = SCCSFactory - - env['SCCS'] = 'sccs' - env['SCCSFLAGS'] = SCons.Util.CLVar('') - env['SCCSGETFLAGS'] = SCons.Util.CLVar('') - env['SCCSCOM'] = '$SCCS $SCCSFLAGS get $SCCSGETFLAGS $TARGET' - -def exists(env): - return env.Detect('sccs') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/SCCS.xml b/src/engine/SCons/Tool/SCCS.xml deleted file mode 100644 index 97c72a9..0000000 --- a/src/engine/SCons/Tool/SCCS.xml +++ /dev/null @@ -1,133 +0,0 @@ - - - - -%scons; - -%builders-mod; - -%functions-mod; - -%tools-mod; - -%variables-mod; -]> - - - - - - -Sets construction variables for interacting with the -Source Code Control System. - - - -SCCS -SCCSFLAGS -SCCSGETFLAGS -SCCSCOM - - -SCCSCOMSTR - - - - - - -The SCCS executable. - - - - - - - -The command line used to -fetch source files from SCCS. - - - - - - - -The string displayed when fetching -a source file from a CVS repository. -If this is not set, then &cv-link-SCCSCOM; -(the command line) is displayed. - - - - - - - -General options that are passed to SCCS. - - - - - - - -Options that are passed specifically to the SCCS "get" subcommand. -This can be set, for example, to - -to check out editable files from SCCS. - - - - - - -() - - - -A factory function that -returns a Builder object -to be used to fetch source files -from SCCS. -The returned Builder -is intended to be passed to the -&f-link-SourceCode; -function. - - - -Example: - - - -env.SourceCode('.', env.SCCS()) - - - -Note that -&scons; -will fetch source files -from SCCS subdirectories automatically, -so configuring SCCS -as demonstrated in the above example -should only be necessary if -you are fetching from -s.SCCS -files in the same -directory as the source files, -or if you need to explicitly specify SCCS -for a specific subdirectory. - - - - - diff --git a/src/engine/SCons/Tool/Subversion.py b/src/engine/SCons/Tool/Subversion.py deleted file mode 100644 index cb34e07..0000000 --- a/src/engine/SCons/Tool/Subversion.py +++ /dev/null @@ -1,70 +0,0 @@ -"""SCons.Tool.Subversion.py - -Tool-specific initialization for Subversion. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - -# Copyright (c) 2001 - 2016 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/Subversion.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" - -import os.path - -import SCons.Action -import SCons.Builder -import SCons.Util - -def generate(env): - """Add a Builder factory function and construction variables for - Subversion to an Environment.""" - - def SubversionFactory(repos, module='', env=env): - """ """ - # fail if repos is not an absolute path name? - import SCons.Warnings as W - W.warn(W.DeprecatedSourceCodeWarning, """The Subversion() factory is deprecated and there is no replacement.""") - if module != '': - module = os.path.join(module, '') - act = SCons.Action.Action('$SVNCOM', '$SVNCOMSTR') - return SCons.Builder.Builder(action = act, - env = env, - SVNREPOSITORY = repos, - SVNMODULE = module) - - env.Subversion = SubversionFactory - - env['SVN'] = 'svn' - env['SVNFLAGS'] = SCons.Util.CLVar('') - env['SVNCOM'] = '$SVN $SVNFLAGS cat $SVNREPOSITORY/$SVNMODULE$TARGET > $TARGET' - -def exists(env): - return env.Detect('svn') - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/Subversion.xml b/src/engine/SCons/Tool/Subversion.xml deleted file mode 100644 index 2d8fd26..0000000 --- a/src/engine/SCons/Tool/Subversion.xml +++ /dev/null @@ -1,135 +0,0 @@ - - - - -%scons; - -%builders-mod; - -%functions-mod; - -%tools-mod; - -%variables-mod; -]> - - - - - - - - - - - - - - diff --git a/src/engine/SCons/Tool/ToolTests.py b/src/engine/SCons/Tool/ToolTests.py index 0739063..f5678c1 100644 --- a/src/engine/SCons/Tool/ToolTests.py +++ b/src/engine/SCons/Tool/ToolTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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/ToolTests.py rel_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ToolTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import sys import unittest diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 274b563..9265b81 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -14,7 +14,7 @@ tool definition. """ # -# Copyright (c) 2001 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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,14 +35,16 @@ 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" import imp +import importlib import sys import re import os import shutil + import SCons.Builder import SCons.Errors import SCons.Node.FS @@ -52,6 +54,7 @@ import SCons.Scanner.D import SCons.Scanner.LaTeX import SCons.Scanner.Prog import SCons.Scanner.SWIG +import collections DefaultToolpath=[] @@ -94,9 +97,20 @@ 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', + 'clang++': 'clangxx', +} + class Tool(object): def __init__(self, name, toolpath=[], **kw): - self.name = name + + # Rename if there's a TOOL_ALIAS for this tool + 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 @@ -107,35 +121,124 @@ class Tool(object): if hasattr(module, 'options'): self.options = module.options + def _load_dotted_module_py2(self, short_name, full_name, searchpaths=None): + splitname = short_name.split('.') + index = 0 + srchpths = searchpaths + for item in splitname: + file, path, desc = imp.find_module(item, srchpths) + mod = imp.load_module(full_name, file, path, desc) + srchpths = [path] + return mod, file + def _tool_module(self): - # TODO: Interchange zipimport with normal initialization for better error reporting oldpythonpath = sys.path sys.path = self.toolpath + sys.path + # sys.stderr.write("Tool:%s\nPATH:%s\n"%(self.name,sys.path)) - try: + 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: - file, path, desc = imp.find_module(self.name, self.toolpath) try: - return imp.load_module(self.name, file, path, desc) - finally: - if file: - file.close() - except ImportError, e: - if str(e)!="No module named %s"%self.name: - raise SCons.Errors.EnvironmentError(e) - try: - import zipimport - except ImportError: - pass + file = None + try: + mod, file = self._load_dotted_module_py2(self.name, self.name, self.toolpath) + return mod + finally: + if file: + file.close() + except ImportError as e: + splitname = self.name.split('.') + if str(e)!="No module named %s"%splitname[0]: + raise SCons.Errors.EnvironmentError(e) + try: + import zipimport + except ImportError: + pass + else: + for aPath in self.toolpath: + try: + importer = zipimport.zipimporter(aPath) + return importer.load_module(self.name) + except ImportError as e: + pass + finally: + sys.path = oldpythonpath + elif sys.version_info[1] > 4: + # From: http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path/67692#67692 + # import importlib.util + # spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py") + # foo = importlib.util.module_from_spec(spec) + # spec.loader.exec_module(foo) + # foo.MyClass() + # Py 3 code + + # import pdb; pdb.set_trace() + import importlib.util + + # sys.stderr.write("toolpath:%s\n" % self.toolpath) + # sys.stderr.write("SCONS.TOOL path:%s\n" % sys.modules['SCons.Tool'].__path__) + debug = False + spec = None + found_name = self.name + 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_package = os.path.join(path, sepname) + + 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) + 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) + break + else: - for aPath in self.toolpath: - try: - importer = zipimport.zipimporter(aPath) - return importer.load_module(self.name) - except ImportError, e: - pass - finally: - sys.path = oldpythonpath + 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 spec: + 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 spec is None: + error_string = "No module named %s"%self.name + raise SCons.Errors.EnvironmentError(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) + + # Don't reload a tool we already loaded. + sys_modules_value = sys.modules.get(found_name,False) + if sys_modules_value and sys_modules_value.__file__ == spec.origin: + return 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 + # different.. ? + module = spec.loader.load_module(spec.name) + + sys.modules[found_name] = module + if add_to_scons_tools_namespace: + # If we found it in SCons.Tool, then add it to the module + setattr(SCons.Tool, self.name, module) + + return module + + + sys.path = oldpythonpath full_name = 'SCons.Tool.' + self.name try: @@ -144,13 +247,12 @@ class Tool(object): try: smpath = sys.modules['SCons.Tool'].__path__ try: - file, path, desc = imp.find_module(self.name, smpath) - module = imp.load_module(full_name, file, path, desc) + module, file = self._load_dotted_module_py2(self.name, full_name, smpath) setattr(SCons.Tool, self.name, module) if file: file.close() return module - except ImportError, e: + except ImportError as e: if str(e)!="No module named %s"%self.name: raise SCons.Errors.EnvironmentError(e) try: @@ -159,10 +261,10 @@ class Tool(object): module = importer.load_module(full_name) setattr(SCons.Tool, self.name, module) return module - except ImportError, e: + except ImportError as e: m = "No tool named '%s': %s" % (self.name, e) raise SCons.Errors.EnvironmentError(m) - except ImportError, e: + except ImportError as e: m = "No tool named '%s': %s" % (self.name, e) raise SCons.Errors.EnvironmentError(m) @@ -217,6 +319,7 @@ def createProgBuilder(env): return program + def createStaticLibBuilder(env): """This is a utility function that creates the StaticLibrary Builder in an Environment if it is not there already. @@ -228,7 +331,7 @@ def createStaticLibBuilder(env): static_lib = env['BUILDERS']['StaticLibrary'] except KeyError: action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ] - if env.Detect('ranlib'): + if env.get('RANLIB',False) or env.Detect('ranlib'): ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR") action_list.append(ranlib_action) @@ -254,22 +357,22 @@ def _call_linker_cb(env, callback, args, result = None): Verbose = False if Verbose: - print '_call_linker_cb: args=%r' % args - print '_call_linker_cb: callback=%r' % callback - + print('_call_linker_cb: args=%r' % args) + print('_call_linker_cb: callback=%r' % callback) + try: cbfun = env['LINKCALLBACKS'][callback] except (KeyError, TypeError): if Verbose: - print '_call_linker_cb: env["LINKCALLBACKS"][%r] not found or can not be used' % callback + print('_call_linker_cb: env["LINKCALLBACKS"][%r] not found or can not be used' % callback) pass else: if Verbose: - print '_call_linker_cb: env["LINKCALLBACKS"][%r] found' % callback - print '_call_linker_cb: env["LINKCALLBACKS"][%r]=%r' % (callback, cbfun) - if(callable(cbfun)): + 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 Verbose: - print '_call_linker_cb: env["LINKCALLBACKS"][%r] is callable' % callback + print('_call_linker_cb: env["LINKCALLBACKS"][%r] is callable' % callback) result = cbfun(env, *args) return result @@ -388,7 +491,7 @@ class _LibInfoGeneratorBase(object): 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) + return _call_linker_cb(env, callback, args, result) class _LibPrefixGenerator(_LibInfoGeneratorBase): """Library prefix generator, used as target_prefix in SharedLibrary and @@ -407,17 +510,17 @@ class _LibPrefixGenerator(_LibInfoGeneratorBase): prefix = self.get_lib_prefix(env,**kw2) if Verbose: - print "_LibPrefixGenerator: input prefix=%r" % prefix + print("_LibPrefixGenerator: input prefix=%r" % prefix) version = self.get_lib_version(env, **kw2) if Verbose: - print "_LibPrefixGenerator: version=%r" % version + print("_LibPrefixGenerator: version=%r" % version) if version: prefix = self.generate_versioned_lib_info(env, [prefix, version], prefix, **kw2) if Verbose: - print "_LibPrefixGenerator: return prefix=%r" % prefix + print("_LibPrefixGenerator: return prefix=%r" % prefix) return prefix ShLibPrefixGenerator = _LibPrefixGenerator('ShLib') @@ -441,17 +544,17 @@ class _LibSuffixGenerator(_LibInfoGeneratorBase): suffix = self.get_lib_suffix(env, **kw2) if Verbose: - print "_LibSuffixGenerator: input suffix=%r" % suffix + print("_LibSuffixGenerator: input suffix=%r" % suffix) version = self.get_lib_version(env, **kw2) if Verbose: - print "_LibSuffixGenerator: version=%r" % version + print("_LibSuffixGenerator: version=%r" % version) if version: suffix = self.generate_versioned_lib_info(env, [suffix, version], suffix, **kw2) if Verbose: - print "_LibSuffixGenerator: return suffix=%r" % suffix + print("_LibSuffixGenerator: return suffix=%r" % suffix) return suffix ShLibSuffixGenerator = _LibSuffixGenerator('ShLib') @@ -474,15 +577,15 @@ class _LibSymlinkGenerator(_LibInfoGeneratorBase): kw2 = kw if Verbose: - print "_LibSymLinkGenerator: libnode=%r" % libnode.get_path() + print("_LibSymLinkGenerator: libnode=%r" % libnode.get_path()) symlinks = None version = self.get_lib_version(env, **kw2) disable = self.get_lib_noversionsymlinks(env, **kw2) if Verbose: - print '_LibSymlinkGenerator: version=%r' % version - print '_LibSymlinkGenerator: disable=%r' % disable + print('_LibSymlinkGenerator: version=%r' % version) + print('_LibSymlinkGenerator: disable=%r' % disable) if version and not disable: prefix = self.get_lib_prefix(env,**kw2) @@ -490,7 +593,7 @@ class _LibSymlinkGenerator(_LibInfoGeneratorBase): symlinks = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) if Verbose: - print '_LibSymlinkGenerator: return symlinks=%r' % StringizeLibSymlinks(symlinks) + print('_LibSymlinkGenerator: return symlinks=%r' % StringizeLibSymlinks(symlinks)) return symlinks ShLibSymlinkGenerator = _LibSymlinkGenerator('ShLib') @@ -499,7 +602,7 @@ ImpLibSymlinkGenerator = _LibSymlinkGenerator('ImpLib') class _LibNameGenerator(_LibInfoGeneratorBase): """Generates "unmangled" library name from a library file node. - + Generally, it's thought to revert modifications done by prefix/suffix generators (_LibPrefixGenerator/_LibSuffixGenerator) used by a library builder. For example, on gnulink the suffix generator used by SharedLibrary @@ -509,7 +612,7 @@ class _LibNameGenerator(_LibInfoGeneratorBase): "$SHLIBSUFFIX" in the node's basename. So that, if $SHLIBSUFFIX is ".so", $SHLIBVERSION is "0.1.2" and the node path is "/foo/bar/libfoo.so.0.1.2", the _LibNameGenerator shall return "libfoo.so". Other link tools may - implement it's own way of library name unmangling. + implement it's own way of library name unmangling. """ def __init__(self, libtype): super(_LibNameGenerator, self).__init__(libtype, 'Name') @@ -525,11 +628,11 @@ class _LibNameGenerator(_LibInfoGeneratorBase): kw2 = kw if Verbose: - print "_LibNameGenerator: libnode=%r" % libnode.get_path() + print("_LibNameGenerator: libnode=%r" % libnode.get_path()) version = self.get_lib_version(env, **kw2) if Verbose: - print '_LibNameGenerator: version=%r' % version + print('_LibNameGenerator: version=%r' % version) name = None if version: @@ -541,7 +644,7 @@ class _LibNameGenerator(_LibInfoGeneratorBase): name = os.path.basename(libnode.get_path()) if Verbose: - print '_LibNameGenerator: return name=%r' % name + print('_LibNameGenerator: return name=%r' % name) return name @@ -550,7 +653,7 @@ LdModNameGenerator = _LibNameGenerator('LdMod') ImpLibNameGenerator = _LibNameGenerator('ImpLib') class _LibSonameGenerator(_LibInfoGeneratorBase): - """Library soname generator. Returns library soname (e.g. libfoo.so.0) for + """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') @@ -566,13 +669,13 @@ class _LibSonameGenerator(_LibInfoGeneratorBase): kw2 = kw if Verbose: - print "_LibSonameGenerator: libnode=%r" % libnode.get_path() + print("_LibSonameGenerator: libnode=%r" % libnode.get_path()) soname = _call_env_subst(env, '$SONAME', **kw2) if not soname: version = self.get_lib_version(env,**kw2) if Verbose: - print "_LibSonameGenerator: version=%r" % version + print("_LibSonameGenerator: version=%r" % version) if version: prefix = self.get_lib_prefix(env,**kw2) suffix = self.get_lib_suffix(env,**kw2) @@ -582,10 +685,10 @@ class _LibSonameGenerator(_LibInfoGeneratorBase): # fallback to library name (as returned by appropriate _LibNameGenerator) soname = _LibNameGenerator(self.get_libtype())(env, libnode) if Verbose: - print "_LibSonameGenerator: FALLBACK: soname=%r" % soname + print("_LibSonameGenerator: FALLBACK: soname=%r" % soname) if Verbose: - print "_LibSonameGenerator: return soname=%r" % soname + print("_LibSonameGenerator: return soname=%r" % soname) return soname @@ -613,39 +716,39 @@ def EmitLibSymlinks(env, symlinks, libnode, **kw): clean_targets = kw.get('clean_targets', []) if not SCons.Util.is_List(clean_targets): clean_targets = [ clean_targets ] - + for link, linktgt in symlinks: env.SideEffect(link, linktgt) if(Verbose): - print "EmitLibSymlinks: SideEffect(%r,%r)" % (link.get_path(), linktgt.get_path()) - clean_list = filter(lambda x : x != linktgt, nodes) + 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): - print "EmitLibSymlinks: Clean(%r,%r)" % (linktgt.get_path(), map(lambda x : x.get_path(), clean_list)) + 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 nodes. """ - + Verbose = False for link, linktgt in symlinks: linktgt = link.get_dir().rel_path(linktgt) link = link.get_path() if(Verbose): - print "CreateLibSymlinks: preparing to add symlink %r -> %r" % (link, linktgt) + 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): - print "CreateLibSymlinks: removed old symlink %r" % link + 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): - print "CreateLibSymlinks: add symlink %r -> %r" % (link, linktgt) + print("CreateLibSymlinks: add symlink %r -> %r" % (link, linktgt)) return 0 def LibSymlinksActionFunction(target, source, env): @@ -670,10 +773,11 @@ def LibSymlinksStrFun(target, source, env, *args): else: cmd += ": %s" % linkstr return cmd - + LibSymlinksAction = SCons.Action.Action(LibSymlinksActionFunction, LibSymlinksStrFun) + def createSharedLibBuilder(env): """This is a utility function that creates the SharedLibrary Builder in an Environment if it is not there already. @@ -810,7 +914,7 @@ def CreateJarBuilder(env): jar_com = SCons.Action.Action('$JARCOM', '$JARCOMSTR') java_jar = SCons.Builder.Builder(action = jar_com, suffix = '$JARSUFFIX', - src_suffix = '$JAVACLASSSUFIX', + src_suffix = '$JAVACLASSSUFFIX', src_builder = 'JavaClassFile', source_factory = fs.Entry) env['BUILDERS']['Jar'] = java_jar @@ -890,9 +994,9 @@ class ToolInitializerMethod(object): def get_builder(self, env): """ - Returns the appropriate real Builder for this method name - after having the associated ToolInitializer object apply - the appropriate Tool module. + Returns the appropriate real Builder for this method name + after having the associated ToolInitializer object apply + the appropriate Tool module. """ builder = getattr(env, self.__name__) @@ -949,13 +1053,13 @@ class ToolInitializer(object): so we no longer copy and re-bind them when the construction environment gets cloned. """ - for method in self.methods.values(): + for method in list(self.methods.values()): env.RemoveMethod(method) def apply_tools(self, env): """ - Searches the list of associated Tool modules for one that - exists, and applies that to the construction environment. + Searches the list of associated Tool modules for one that + exists, and applies that to the construction environment. """ for t in self.tools: tool = SCons.Tool.Tool(t) @@ -1005,7 +1109,7 @@ def tool_list(platform, env): "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++', 'c++', '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'] @@ -1014,7 +1118,7 @@ def tool_list(platform, env): "prefer IBM tools on OS/2" linkers = ['ilink', 'gnulink', ]#'mslink'] c_compilers = ['icc', 'gcc',]# 'msvc', 'cc'] - cxx_compilers = ['icc', 'g++',]# 'msvc', 'c++'] + cxx_compilers = ['icc', 'g++',]# 'msvc', 'cxx'] assemblers = ['nasm',]# 'masm', 'gas'] fortran_compilers = ['ifl', 'g77'] ars = ['ar',]# 'mslib'] @@ -1022,7 +1126,7 @@ def tool_list(platform, env): "prefer MIPSPro on IRIX" linkers = ['sgilink', 'gnulink'] c_compilers = ['sgicc', 'gcc', 'cc'] - cxx_compilers = ['sgic++', 'g++', 'c++'] + cxx_compilers = ['sgicxx', 'g++', 'cxx'] assemblers = ['as', 'gas'] fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran'] ars = ['sgiar'] @@ -1030,7 +1134,7 @@ def tool_list(platform, env): "prefer Forte tools on SunOS" linkers = ['sunlink', 'gnulink'] c_compilers = ['suncc', 'gcc', 'cc'] - cxx_compilers = ['sunc++', 'g++', 'c++'] + cxx_compilers = ['suncxx', 'g++', 'cxx'] assemblers = ['as', 'gas'] fortran_compilers = ['sunf95', 'sunf90', 'sunf77', 'f95', 'f90', 'f77', 'gfortran', 'g77', 'fortran'] @@ -1039,7 +1143,7 @@ def tool_list(platform, env): "prefer aCC tools on HP-UX" linkers = ['hplink', 'gnulink'] c_compilers = ['hpcc', 'gcc', 'cc'] - cxx_compilers = ['hpc++', 'g++', 'c++'] + cxx_compilers = ['hpcxx', 'g++', 'cxx'] assemblers = ['as', 'gas'] fortran_compilers = ['f95', 'f90', 'f77', 'g77', 'fortran'] ars = ['ar'] @@ -1047,7 +1151,7 @@ def tool_list(platform, env): "prefer AIX Visual Age tools on AIX" linkers = ['aixlink', 'gnulink'] c_compilers = ['aixcc', 'gcc', 'cc'] - cxx_compilers = ['aixc++', 'g++', 'c++'] + cxx_compilers = ['aixcxx', 'g++', 'cxx'] assemblers = ['as', 'gas'] fortran_compilers = ['f95', 'f90', 'aixf77', 'g77', 'fortran'] ars = ['ar'] @@ -1055,7 +1159,7 @@ def tool_list(platform, env): "prefer GNU tools on Mac OS X, except for some linkers and IBM tools" linkers = ['applelink', 'gnulink'] c_compilers = ['gcc', 'cc'] - cxx_compilers = ['g++', 'c++'] + cxx_compilers = ['g++', 'cxx'] assemblers = ['as'] fortran_compilers = ['gfortran', 'f95', 'f90', 'g77'] ars = ['ar'] @@ -1063,18 +1167,18 @@ def tool_list(platform, env): "prefer GNU tools on Cygwin, except for a platform-specific linker" linkers = ['cyglink', 'mslink', 'ilink'] c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc'] - cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'c++'] + cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'cxx'] assemblers = ['gas', 'nasm', 'masm'] fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77'] ars = ['ar', 'mslib'] else: "prefer GNU tools on all other platforms" - linkers = ['gnulink', 'mslink', 'ilink'] - c_compilers = ['gcc', 'msvc', 'intelc', 'icc', 'cc'] - cxx_compilers = ['g++', 'msvc', 'intelc', 'icc', 'c++'] + linkers = ['gnulink', 'ilink'] + 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', 'mslib'] + ars = ['ar',] if not str(platform) == 'win32': other_plat_tools += ['m4', 'rpm'] @@ -1102,7 +1206,7 @@ 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_compilers = ['dmd', 'ldc', 'gdc'] d_compiler = FindTool(d_compilers, env) or d_compilers[0] other_tools = FindAllTools(other_plat_tools + [ @@ -1121,9 +1225,6 @@ def tool_list(platform, env): 'tex', 'latex', 'pdflatex', 'pdftex', # Archivers 'tar', 'zip', - # SourceCode factories - 'BitKeeper', 'CVS', 'Perforce', - 'RCS', 'SCCS', # 'Subversion', ], env) tools = ([linker, c_compiler, cxx_compiler, @@ -1137,4 +1238,3 @@ def tool_list(platform, env): # indent-tabs-mode:nil # End: # vim: set expandtab tabstop=4 shiftwidth=4: - diff --git a/src/engine/SCons/Tool/__init__.xml b/src/engine/SCons/Tool/__init__.xml index d66b04a..32b8ce6 100644 --- a/src/engine/SCons/Tool/__init__.xml +++ b/src/engine/SCons/Tool/__init__.xml @@ -1,6 +1,6 @@ + + +%scons; + +%builders-mod; + +%functions-mod; + +%tools-mod; + +%variables-mod; +]> + + + + + + +Set construction variables for the Clang C compiler. + + + +CC +SHCCFLAGS +CCVERSION + + + + diff --git a/src/engine/SCons/Tool/clangxx.py b/src/engine/SCons/Tool/clangxx.py new file mode 100644 index 0000000..f56c9e5 --- /dev/null +++ b/src/engine/SCons/Tool/clangxx.py @@ -0,0 +1,91 @@ +# -*- coding: utf-8; -*- + +"""SCons.Tool.clang++ + +Tool-specific initialization for clang++. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" + +# +# Copyright (c) 2001 - 2017 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/clangxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" + +# Based on SCons/Tool/g++.py by Paweł Tomulik 2014 as a separate tool. +# Brought into the SCons mainline by Russel Winder 2017. + +import os.path +import re +import subprocess +import sys + +import SCons.Tool +import SCons.Util +import SCons.Tool.cxx + +compilers = ['clang++'] + +def generate(env): + """Add Builders and construction variables for clang++ to an Environment.""" + static_obj, shared_obj = SCons.Tool.createObjBuilders(env) + + SCons.Tool.cxx.generate(env) + + env['CXX'] = env.Detect(compilers) or 'clang++' + + # platform specific settings + if env['PLATFORM'] == 'aix': + env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS -mminimal-toc') + env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1 + env['SHOBJSUFFIX'] = '$OBJSUFFIX' + elif env['PLATFORM'] == 'hpux': + env['SHOBJSUFFIX'] = '.pic.o' + elif env['PLATFORM'] == 'sunos': + env['SHOBJSUFFIX'] = '.pic.o' + # 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 + # clang -dumpversion is of no use + line = pipe.stdout.readline() + if sys.version_info[0] > 2: + line = line.decode() + match = re.search(r'clang +version +([0-9]+(?:\.[0-9]+)+)', line) + if match: + env['CXXVERSION'] = match.group(1) + +def exists(env): + return env.Detect(compilers) + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Tool/clangxx.xml b/src/engine/SCons/Tool/clangxx.xml new file mode 100644 index 0000000..309bb63 --- /dev/null +++ b/src/engine/SCons/Tool/clangxx.xml @@ -0,0 +1,41 @@ + + + + +%scons; + +%builders-mod; + +%functions-mod; + +%tools-mod; + +%variables-mod; +]> + + + + + + +Set construction variables for the Clang C++ compiler. + + + +CXX +SHCXXFLAGS +STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME +SHOBJSUFFIX +CXXVERSION + + + + diff --git a/src/engine/SCons/Tool/cvf.py b/src/engine/SCons/Tool/cvf.py index 37b4a00..a785471 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 - 2016 The SCons Foundation +# Copyright (c) 2001 - 2017 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,9 +27,9 @@ 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_2.5.1:3735:9dc6cee5c168 2016/11/03 14:02:02 bdbaddog" +__revision__ = "src/engine/SCons/Tool/cvf.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" -import fortran +from . import fortran compilers = ['f90'] diff --git a/src/engine/SCons/Tool/cvf.xml b/src/engine/SCons/Tool/cvf.xml index 1227658..1b2c447 100644 --- a/src/engine/SCons/Tool/cvf.xml +++ b/src/engine/SCons/Tool/cvf.xml @@ -1,6 +1,6 @@ \n') def printSources(self, hierarchy, commonprefix): @@ -950,7 +954,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): self.file.write('\t\n') - cats = sorted([k for k in categories.keys() if self.sources[k]], + cats = sorted([k for k in list(categories.keys()) if self.sources[k]], key=lambda a: a.lower()) for kind in cats: if len(cats) > 1: @@ -1037,13 +1041,13 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User): def Build(self): try: self.file = open(self.dspabs,'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.dspabs + '" for writing:' + str(detail)) else: self.PrintHeader() self.PrintProject() self.file.close() - + _GenerateV7User.Build(self) V10DSPHeader = """\ @@ -1100,7 +1104,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): self.dspheader = V10DSPHeader self.dspconfiguration = V10DSPProjectConfiguration self.dspglobals = V10DSPGlobals - + _GenerateV10User.__init__(self, dspfile, source, env) def PrintHeader(self): @@ -1131,27 +1135,27 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): '\t\t%s\n' % (scc_project_name, scc_local_path_legacy)) else: self.dspglobals = self.dspglobals.replace('%(scc_attrs)s', '') - + self.file.write(self.dspheader % locals()) - + self.file.write('\t\n') - + confkeys = sorted(self.configs.keys()) for kind in confkeys: variant = self.configs[kind].variant platform = self.configs[kind].platform self.file.write(self.dspconfiguration % locals()) - + self.file.write('\t\n') - + self.file.write(self.dspglobals % locals()) - + def PrintProject(self): name = self.name confkeys = sorted(self.configs.keys()) - + self.file.write('\t\n') - + toolset = '' if 'MSVC_VERSION' in self.env: version_num, suite = msvs_parse_version(self.env['MSVC_VERSION']) @@ -1164,16 +1168,16 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): self.file.write('\t\n') self.file.write('\t\n') self.file.write('\t\n') - + for kind in confkeys: variant = self.configs[kind].variant platform = self.configs[kind].platform self.file.write(V10DSPImportGroupCondition % locals()) - + self.file.write('\t\n') self.file.write('\t\n') self.file.write('\t<_ProjectFileVersion>10.0.30319.1\n') - + for kind in confkeys: variant = self.configs[kind].variant platform = self.configs[kind].platform @@ -1181,7 +1185,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): buildtarget = self.configs[kind].buildtarget runfile = self.configs[kind].runfile cmdargs = self.configs[kind].cmdargs - + env_has_buildtarget = 'MSVSBUILDTARGET' in self.env if not env_has_buildtarget: self.env['MSVSBUILDTARGET'] = buildtarget @@ -1206,41 +1210,41 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): del self.env['MSVSBUILDTARGET'] self.file.write(V10DSPCommandLine % locals()) - + self.file.write('\t\n') - + #filter settings in MSVS 2010 are stored in separate file self.filtersabs = self.dspabs + '.filters' try: self.filters_file = open(self.filtersabs, 'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.filtersabs + '" for writing:' + str(detail)) - + self.filters_file.write('\n' '\n') - + self.PrintSourceFiles() - + self.filters_file.write('') self.filters_file.close() - + self.file.write('\t\n' '\t\n' '\t\n' '\n') - + if self.nokeep == 0: # now we pickle some data and add it to the file -- MSDEV will ignore it. - pdata = pickle.dumps(self.configs,1) - pdata = base64.encodestring(pdata) + pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) + pdata = base64.encodestring(pdata).decode() self.file.write('\n') def printFilters(self, hierarchy, name): sorteditems = sorted(hierarchy.items(), key = lambda a: a[0].lower()) - + for key, value in sorteditems: if SCons.Util.is_Dict(value): filter_name = name + '\\' + key @@ -1248,14 +1252,14 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): '\t\t\t%s\n' '\t\t\n' % (filter_name, _generateGUID(self.dspabs, filter_name))) self.printFilters(value, filter_name) - + def printSources(self, hierarchy, kind, commonprefix, filter_name): keywords = {'Source Files': 'ClCompile', 'Header Files': 'ClInclude', 'Local Headers': 'ClInclude', 'Resource Files': 'None', 'Other Files': 'None'} - + sorteditems = sorted(hierarchy.items(), key = lambda a: a[0].lower()) # First folders, then files @@ -1269,7 +1273,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): if commonprefix: file = os.path.join(commonprefix, value) file = os.path.normpath(file) - + self.file.write('\t\t<%s Include="%s" />\n' % (keywords[kind], file)) self.filters_file.write('\t\t<%s Include="%s">\n' '\t\t\t%s\n' @@ -1281,10 +1285,10 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): 'Local Headers': 'h;hpp;hxx;hm;inl', 'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe', 'Other Files': ''} - - cats = sorted([k for k in categories.keys() if self.sources[k]], + + cats = sorted([k for k in list(categories.keys()) if self.sources[k]], key = lambda a: a.lower()) - + # print vcxproj.filters file first self.filters_file.write('\t\n') for kind in cats: @@ -1292,7 +1296,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): '\t\t\t{7b42d31d-d53c-4868-8b92-ca2bc9fc052f}\n' '\t\t\t%s\n' '\t\t\n' % (kind, categories[kind])) - + # First remove any common prefix sources = self.sources[kind] commonprefix = None @@ -1305,17 +1309,17 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): # +1 because the filename starts after the separator sources = [s[len(cp)+1:] for s in sources] commonprefix = cp - + hierarchy = makeHierarchy(sources) self.printFilters(hierarchy, kind) - + self.filters_file.write('\t\n') - + # then print files and filters for kind in cats: self.file.write('\t\n') self.filters_file.write('\t\n') - + # First remove any common prefix sources = self.sources[kind] commonprefix = None @@ -1328,13 +1332,13 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): # +1 because the filename starts after the separator sources = [s[len(cp)+1:] for s in sources] commonprefix = cp - + hierarchy = makeHierarchy(sources) self.printSources(hierarchy, kind, commonprefix, kind) - + self.file.write('\t\n') self.filters_file.write('\t\n') - + # add the SConscript file outside of the groups self.file.write('\t\n' '\t\t\n' @@ -1342,18 +1346,18 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): '\t\n' % str(self.sconscript)) def Parse(self): - print "_GenerateV10DSP.Parse()" + print("_GenerateV10DSP.Parse()") def Build(self): try: self.file = open(self.dspabs, 'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.dspabs + '" for writing:' + str(detail)) else: self.PrintHeader() self.PrintProject() self.file.close() - + _GenerateV10User.Build(self) class _DSWGenerator(object): @@ -1428,7 +1432,7 @@ class _GenerateV7DSW(_DSWGenerator): config.platform = 'Win32' self.configs[variant] = config - print "Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dswfile) + "'" + print("Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dswfile) + "'") if 'variant' not in env: raise SCons.Errors.InternalError("You must specify a 'variant' argument (i.e. 'Debug' or " +\ @@ -1440,7 +1444,7 @@ class _GenerateV7DSW(_DSWGenerator): AddConfig(self, variant) self.platforms = [] - for key in self.configs.keys(): + for key in list(self.configs.keys()): platform = self.configs[key].platform if not platform in self.platforms: self.platforms.append(platform) @@ -1461,7 +1465,7 @@ class _GenerateV7DSW(_DSWGenerator): 'SLN_RELATIVE_FOLDER_PATH': dsp_relative_folder_path, 'SLN_RELATIVE_FILE_PATH': dsp_relative_file_path} self.dspfiles_info.append(dspfile_info) - + self.dspfiles_info = [] GenerateProjectFilesInfo(self) @@ -1507,7 +1511,7 @@ class _GenerateV7DSW(_DSWGenerator): self.file.write('# Visual Studio 2008\n') elif self.version_num >= 8.0: self.file.write('# Visual Studio 2005\n') - + for dspinfo in self.dspfiles_info: name = dspinfo['NAME'] base, suffix = SCons.Util.splitext(name) @@ -1605,14 +1609,15 @@ class _GenerateV7DSW(_DSWGenerator): '\tEndGlobalSection\n') self.file.write('EndGlobal\n') if self.nokeep == 0: - pdata = pickle.dumps(self.configs,1) - pdata = base64.encodestring(pdata) - self.file.write(pdata + '\n') + pdata = pickle.dumps(self.configs,PICKLE_PROTOCOL) + pdata = base64.encodestring(pdata).decode() + self.file.write(pdata) + self.file.write('\n') def Build(self): try: self.file = open(self.dswfile,'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.dswfile + '" for writing:' + str(detail)) else: self.PrintSolution() @@ -1661,7 +1666,7 @@ class _GenerateV6DSW(_DSWGenerator): def Build(self): try: self.file = open(self.dswfile,'w') - except IOError, detail: + except IOError as detail: raise SCons.Errors.InternalError('Unable to open "' + self.dswfile + '" for writing:' + str(detail)) else: self.PrintWorkspace() @@ -1718,8 +1723,8 @@ def GenerateProject(target, source, env): if not dspfile is builddspfile: try: bdsp = open(str(builddspfile), "w+") - except IOError, detail: - print 'Unable to open "' + str(dspfile) + '" for writing:',detail,'\n' + except IOError as detail: + print('Unable to open "' + str(dspfile) + '" for writing:',detail,'\n') raise bdsp.write("This is just a placeholder file.\nThe real project file is here:\n%s\n" % dspfile.get_abspath()) @@ -1734,8 +1739,8 @@ def GenerateProject(target, source, env): try: bdsw = open(str(builddswfile), "w+") - except IOError, detail: - print 'Unable to open "' + str(dspfile) + '" for writing:',detail,'\n' + except IOError as detail: + print('Unable to open "' + str(dspfile) + '" for writing:',detail,'\n') raise bdsw.write("This is just a placeholder file.\nThe real workspace file is here:\n%s\n" % dswfile.get_abspath()) @@ -1843,7 +1848,10 @@ def projectEmitter(target, source, env): targetlist = targetlist + t # Beginning with Visual Studio 2010 for each project file (.vcxproj) we have additional file (.vcxproj.filters) - if float(env['MSVS_VERSION']) >= 10.0: + version_num = 6.0 + if 'MSVS_VERSION' in env: + version_num, suite = msvs_parse_version(env['MSVS_VERSION']) + if version_num >= 10.0: targetlist.append(targetlist[0] + '.filters') return (targetlist, sourcelist) @@ -1969,7 +1977,7 @@ def generate(env): else: env['MSVS']['PROJECTSUFFIX'] = '.vcxproj' env['MSVS']['SOLUTIONSUFFIX'] = '.sln' - + if (version_num >= 10.0): env['MSVSENCODING'] = 'utf-8' else: diff --git a/src/engine/SCons/Tool/msvs.xml b/src/engine/SCons/Tool/msvs.xml index 4ca5fb1..0408509 100644 --- a/src/engine/SCons/Tool/msvs.xml +++ b/src/engine/SCons/Tool/msvs.xml @@ -1,6 +1,6 @@