summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.appveyor/install.bat2
-rw-r--r--.gitignore4
-rw-r--r--.travis.yml1
-rwxr-xr-x.travis/verify_packages.sh32
-rwxr-xr-xCHANGES.txt74
-rw-r--r--MANIFEST.in2
-rwxr-xr-xREADME-SF.rst3
-rwxr-xr-xREADME-package.rst3
-rwxr-xr-xREADME.rst28
-rw-r--r--SCons/Action.py54
-rw-r--r--SCons/Action.xml2
-rw-r--r--SCons/ActionTests.py7
-rw-r--r--SCons/Builder.py47
-rw-r--r--SCons/BuilderTests.py5
-rw-r--r--SCons/CacheDir.py9
-rw-r--r--SCons/CacheDirTests.py6
-rw-r--r--SCons/Conftest.py145
-rw-r--r--SCons/Debug.py60
-rw-r--r--SCons/Defaults.py26
-rw-r--r--SCons/Defaults.xml2
-rw-r--r--SCons/DefaultsTests.py9
-rw-r--r--SCons/Environment.py359
-rw-r--r--SCons/Environment.xml254
-rw-r--r--SCons/EnvironmentTests.py124
-rw-r--r--SCons/EnvironmentValues.py24
-rw-r--r--SCons/EnvironmentValuesTest.py23
-rw-r--r--SCons/Errors.py11
-rw-r--r--SCons/ErrorsTests.py8
-rw-r--r--SCons/Executor.py13
-rw-r--r--SCons/ExecutorTests.py7
-rw-r--r--SCons/Job.py18
-rw-r--r--SCons/JobTests.py9
-rw-r--r--SCons/Memoize.py7
-rw-r--r--SCons/MemoizeTests.py7
-rw-r--r--SCons/Node/Alias.py18
-rw-r--r--SCons/Node/AliasTests.py7
-rw-r--r--SCons/Node/FS.py78
-rw-r--r--SCons/Node/FSTests.py24
-rw-r--r--SCons/Node/NodeTests.py9
-rw-r--r--SCons/Node/Python.py33
-rw-r--r--SCons/Node/PythonTests.py6
-rw-r--r--SCons/Node/__init__.py92
-rw-r--r--SCons/PathList.py17
-rw-r--r--SCons/PathListTests.py7
-rw-r--r--SCons/Platform/Platform.xml2
-rw-r--r--SCons/Platform/PlatformTests.py35
-rw-r--r--SCons/Platform/__init__.py74
-rw-r--r--SCons/Platform/aix.py23
-rw-r--r--SCons/Platform/cygwin.py20
-rw-r--r--SCons/Platform/darwin.py20
-rw-r--r--SCons/Platform/hpux.py20
-rw-r--r--SCons/Platform/irix.py20
-rw-r--r--SCons/Platform/mingw.py14
-rw-r--r--SCons/Platform/os2.py21
-rw-r--r--SCons/Platform/posix.py23
-rw-r--r--SCons/Platform/posix.xml2
-rw-r--r--SCons/Platform/sunos.py20
-rw-r--r--SCons/Platform/sunos.xml2
-rw-r--r--SCons/Platform/virtualenv.py15
-rw-r--r--SCons/Platform/virtualenvTests.py9
-rw-r--r--SCons/Platform/win32.py37
-rw-r--r--SCons/Platform/win32.xml2
-rw-r--r--SCons/SConf.py28
-rw-r--r--SCons/SConfTests.py8
-rw-r--r--SCons/SConsign.py25
-rw-r--r--SCons/SConsignTests.py7
-rw-r--r--SCons/Scanner/C.py35
-rw-r--r--SCons/Scanner/CTests.py9
-rw-r--r--SCons/Scanner/D.py18
-rw-r--r--SCons/Scanner/DTests.py10
-rw-r--r--SCons/Scanner/Dir.py5
-rw-r--r--SCons/Scanner/DirTests.py7
-rw-r--r--SCons/Scanner/Fortran.py11
-rw-r--r--SCons/Scanner/FortranTests.py7
-rw-r--r--SCons/Scanner/IDL.py23
-rw-r--r--SCons/Scanner/IDLTests.py7
-rw-r--r--SCons/Scanner/LaTeX.py18
-rw-r--r--SCons/Scanner/LaTeXTests.py10
-rw-r--r--SCons/Scanner/Prog.py16
-rw-r--r--SCons/Scanner/ProgTests.py7
-rw-r--r--SCons/Scanner/Python.py31
-rw-r--r--SCons/Scanner/PythonTests.py6
-rw-r--r--SCons/Scanner/RC.py39
-rw-r--r--SCons/Scanner/RCTests.py7
-rw-r--r--SCons/Scanner/SWIG.py12
-rw-r--r--SCons/Scanner/Scanner.xml2
-rw-r--r--SCons/Scanner/ScannerTests.py9
-rw-r--r--SCons/Scanner/__init__.py168
-rw-r--r--SCons/Script/Interactive.py8
-rw-r--r--SCons/Script/Main.py59
-rw-r--r--SCons/Script/Main.xml234
-rw-r--r--SCons/Script/MainTests.py6
-rw-r--r--SCons/Script/SConsOptions.py17
-rw-r--r--SCons/Script/SConscript.py13
-rw-r--r--SCons/Script/SConscript.xml2
-rw-r--r--SCons/Script/SConscriptTests.py6
-rw-r--r--SCons/Script/__init__.py40
-rw-r--r--SCons/Subst.py24
-rw-r--r--SCons/Subst.xml2
-rw-r--r--SCons/SubstTests.py15
-rw-r--r--SCons/Taskmaster.py59
-rw-r--r--SCons/TaskmasterTests.py11
-rw-r--r--SCons/Tool/JavaCommonTests.py1
-rw-r--r--SCons/Tool/MSCommon/__init__.py4
-rw-r--r--SCons/Tool/MSCommon/arch.py1
-rw-r--r--SCons/Tool/MSCommon/vc.py10
-rw-r--r--SCons/Tool/ToolTests.py17
-rw-r--r--SCons/Tool/__init__.py12
-rw-r--r--SCons/Tool/clang.py3
-rw-r--r--SCons/Tool/clangxx.py3
-rw-r--r--SCons/Tool/compilation_db.py7
-rw-r--r--SCons/Tool/compilation_db.xml22
-rw-r--r--SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py2
-rw-r--r--SCons/Tool/fortran.py1
-rw-r--r--SCons/Tool/gcc.py1
-rw-r--r--SCons/Tool/gxx.py3
-rw-r--r--SCons/Tool/intelc.py6
-rw-r--r--SCons/Tool/linkCommon/__init__.py1
-rw-r--r--SCons/Tool/linkloc.py1
-rw-r--r--SCons/Tool/msginit.py1
-rw-r--r--SCons/Tool/msvc.py2
-rw-r--r--SCons/Tool/msvs.py8
-rw-r--r--SCons/Tool/msvsTests.py26
-rw-r--r--SCons/Tool/packaging/__init__.py2
-rw-r--r--SCons/Tool/packaging/msi.py2
-rw-r--r--SCons/Tool/packaging/rpm.py1
-rw-r--r--SCons/Tool/qt.py1
-rw-r--r--SCons/Tool/tex.py25
-rw-r--r--SCons/Tool/textfile.py6
-rw-r--r--SCons/Tool/wixTests.py1
-rw-r--r--SCons/Util.py166
-rw-r--r--SCons/UtilTests.py17
-rw-r--r--SCons/Utilities/ConfigureCache.py6
-rw-r--r--SCons/Utilities/sconsign.py19
-rw-r--r--SCons/Variables/BoolVariable.py28
-rw-r--r--SCons/Variables/BoolVariableTests.py7
-rw-r--r--SCons/Variables/EnumVariable.py44
-rw-r--r--SCons/Variables/EnumVariableTests.py7
-rw-r--r--SCons/Variables/ListVariable.py59
-rw-r--r--SCons/Variables/ListVariableTests.py7
-rw-r--r--SCons/Variables/PackageVariable.py54
-rw-r--r--SCons/Variables/PackageVariableTests.py7
-rw-r--r--SCons/Variables/PathVariable.py78
-rw-r--r--SCons/Variables/PathVariableTests.py7
-rw-r--r--SCons/Variables/VariablesTests.py7
-rw-r--r--SCons/Variables/__init__.py11
-rw-r--r--SCons/Warnings.py12
-rw-r--r--SCons/WarningsTests.py7
-rw-r--r--SCons/__init__.py8
-rw-r--r--SCons/__main__.py23
-rw-r--r--SCons/compat/__init__.py30
-rw-r--r--SCons/compat/_scons_dbm.py9
-rw-r--r--SCons/compat/win32.py101
-rw-r--r--SCons/cpp.py11
-rw-r--r--SCons/cppTests.py6
-rw-r--r--SCons/dblite.py118
-rw-r--r--SCons/exitfuncs.py13
-rw-r--r--SConstruct19
-rw-r--r--doc/generated/examples/builderscommands_ex5_1.xml3
-rw-r--r--doc/generated/examples/commandline_BoolVariable_5.xml2
-rw-r--r--doc/generated/examples/commandline_EnumVariable_2.xml2
-rw-r--r--doc/generated/examples/commandline_EnumVariable_4.xml6
-rw-r--r--doc/generated/examples/commandline_ListVariable_3.xml2
-rw-r--r--doc/generated/examples/commandline_ListVariable_4.xml6
-rw-r--r--doc/generated/examples/commandline_PathVariable_2.xml2
-rw-r--r--doc/generated/examples/commandline_UnknownVariables_1.xml2
-rw-r--r--doc/generated/examples/separate_ex1_1.xml2
-rw-r--r--doc/generated/examples/sideeffect_simple2_1.xml4
-rw-r--r--doc/generated/examples/sideeffect_simple_1.xml2
-rw-r--r--doc/man/scons.xml214
-rw-r--r--doc/man/sconsign.xml85
-rw-r--r--doc/user/MANIFEST1
-rw-r--r--doc/user/builders-commands.xml66
-rw-r--r--doc/user/command-line.xml195
-rw-r--r--doc/user/environments.xml2
-rw-r--r--doc/user/external.xml59
-rw-r--r--doc/user/main.xml51
-rw-r--r--doc/user/misc.xml3
-rw-r--r--doc/user/output.xml2
-rw-r--r--doc/user/parse_flags_arg.xml2
-rw-r--r--doc/user/separate.xml179
-rw-r--r--doc/user/sideeffect.xml208
-rw-r--r--doc/user/simple.xml2
-rw-r--r--doc/user/troubleshoot.xml4
-rw-r--r--doc/user/variants.xml70
-rwxr-xr-xruntest.py787
-rw-r--r--setup.cfg15
-rw-r--r--setup.py3
-rw-r--r--site_scons/scons_local_package.py10
-rw-r--r--site_scons/update_build_info.py1
-rw-r--r--template/Tests.py9
-rw-r--r--template/__init__.py68
-rw-r--r--template/file.py17
-rw-r--r--template/test.py10
-rw-r--r--test/AR/AR.py1
-rw-r--r--test/AR/ARFLAGS.py1
-rw-r--r--test/AS/AS.py2
-rw-r--r--test/AS/ASFLAGS.py1
-rw-r--r--test/AS/ASPP.py2
-rw-r--r--test/AS/ASPPFLAGS.py1
-rw-r--r--test/Actions/append.py1
-rw-r--r--test/Actions/pre-post.py1
-rw-r--r--test/Builder/errors.py1
-rw-r--r--test/CC/CCVERSION.py1
-rw-r--r--test/CC/SHCC.py1
-rw-r--r--test/CFILESUFFIX.py1
-rw-r--r--test/CXX/CXX.py1
-rw-r--r--test/CXX/CXXFILESUFFIX.py1
-rw-r--r--test/CacheDir/CacheDir_TryCompile.py1
-rw-r--r--test/CacheDir/NoCache.py2
-rw-r--r--test/CacheDir/multiple-targets.py2
-rw-r--r--test/CacheDir/option--cd.py2
-rw-r--r--test/CacheDir/option--cr.py2
-rw-r--r--test/CacheDir/option--cs.py2
-rwxr-xr-xtest/CacheDir/readonly-cache.py1
-rw-r--r--test/CacheDir/scanner-target.py2
-rw-r--r--test/Clean/Option.py1
-rw-r--r--test/CommandGenerator.py1
-rw-r--r--test/CompilationDatabase/fixture/SConstruct_variant4
-rw-r--r--test/CompilationDatabase/variant_dir.py49
-rw-r--r--test/Configure/VariantDir2.py1
-rw-r--r--test/Configure/config-h.py1
-rw-r--r--test/Copy-Symlinks.py2
-rw-r--r--test/D/Issues/2994/Common/D_changed_DFLAGS_not_rebuilding.py2
-rw-r--r--test/D/MixedDAndC/Common/common.py1
-rw-r--r--test/DVIPDF/DVIPDFFLAGS.py2
-rw-r--r--test/Decider/MD5-winonly-firstbuild.py2
-rw-r--r--test/Dir/PyPackageDir/PyPackageDir.py1
-rw-r--r--test/Docbook/basedir/htmlchunked/htmlchunked_cmd.py1
-rw-r--r--test/Docbook/basedir/htmlhelp/htmlhelp_cmd.py1
-rw-r--r--test/Docbook/basedir/slideshtml/slideshtml_cmd.py1
-rw-r--r--test/Docbook/basic/htmlchunked/htmlchunked_cmd.py1
-rw-r--r--test/Docbook/basic/slideshtml/slideshtml_cmd.py1
-rw-r--r--test/Errors/execute-a-directory.py1
-rw-r--r--test/Errors/non-executable-file.py1
-rw-r--r--test/Fortran/F03.py1
-rw-r--r--test/Fortran/F03FILESUFFIXES.py1
-rw-r--r--test/Fortran/F03FILESUFFIXES2.py1
-rw-r--r--test/Fortran/F03FLAGS.py1
-rw-r--r--test/Fortran/F08.py1
-rw-r--r--test/Fortran/F08FILESUFFIXES.py1
-rw-r--r--test/Fortran/F08FILESUFFIXES2.py1
-rw-r--r--test/Fortran/F08FLAGS.py1
-rw-r--r--test/Fortran/F77.py1
-rw-r--r--test/Fortran/F77FILESUFFIXES.py1
-rw-r--r--test/Fortran/F77FILESUFFIXES2.py1
-rw-r--r--test/Fortran/F77FLAGS.py1
-rw-r--r--test/Fortran/F90.py1
-rw-r--r--test/Fortran/F90FILESUFFIXES.py1
-rw-r--r--test/Fortran/F90FILESUFFIXES2.py1
-rw-r--r--test/Fortran/F90FLAGS.py1
-rw-r--r--test/Fortran/F95.py1
-rw-r--r--test/Fortran/F95FILESUFFIXES.py1
-rw-r--r--test/Fortran/F95FILESUFFIXES2.py1
-rw-r--r--test/Fortran/F95FLAGS.py1
-rw-r--r--test/Fortran/FORTRAN.py1
-rw-r--r--test/Fortran/FORTRANFILESUFFIXES.py1
-rw-r--r--test/Fortran/FORTRANFILESUFFIXES2.py1
-rw-r--r--test/Fortran/FORTRANFLAGS.py1
-rw-r--r--test/Fortran/FORTRANPPFILESUFFIXES.py3
-rw-r--r--test/Fortran/SHF03.py1
-rw-r--r--test/Fortran/SHF08.py1
-rw-r--r--test/Fortran/SHF77.py1
-rw-r--r--test/Fortran/SHF77FLAGS.py1
-rw-r--r--test/Fortran/SHF90.py1
-rw-r--r--test/Fortran/SHF90FLAGS.py1
-rw-r--r--test/Fortran/SHF95.py1
-rw-r--r--test/Fortran/SHF95FLAGS.py1
-rw-r--r--test/Fortran/SHFORTRAN.py1
-rw-r--r--test/Fortran/SHFORTRANFLAGS.py1
-rw-r--r--test/Install/directories.py1
-rw-r--r--test/Install/non-ascii-name.py1
-rw-r--r--test/Java/JAR.py1
-rw-r--r--test/Java/JARCHDIR.py1
-rw-r--r--test/Java/JARFLAGS.py1
-rw-r--r--test/Java/jar_not_in_PATH.py1
-rw-r--r--test/Java/nested-classes.py1
-rw-r--r--test/Java/swig-dependencies.py1
-rw-r--r--test/LEX/LEX.py1
-rw-r--r--test/LEX/LEXFLAGS.py1
-rw-r--r--test/LINK/LDMODULEVERSIONFLAGS.py2
-rw-r--r--test/LINK/LINK.py1
-rw-r--r--test/LINK/LINKFLAGS.py1
-rw-r--r--test/LINK/SHLINK.py1
-rw-r--r--test/LINK/SHLINKFLAGS.py1
-rw-r--r--test/LINK/VersionedLib.py1
-rw-r--r--test/Libs/SharedLibrary-update-deps.py1
-rw-r--r--test/MSVC/PCHSTOP-errors.py1
-rw-r--r--test/MSVC/mssdk.py1
-rw-r--r--test/MSVC/pch-basics.py1
-rw-r--r--test/MSVC/pch-spaces-subdir.py1
-rw-r--r--test/MSVS/common-prefix.py1
-rw-r--r--test/MSVS/runfile.py1
-rw-r--r--test/MSVS/vs-6.0-exec.py1
-rw-r--r--test/MSVS/vs-7.0-exec.py1
-rw-r--r--test/MSVS/vs-7.0-scc-files.py1
-rw-r--r--test/MSVS/vs-7.0-scc-legacy-files.py1
-rw-r--r--test/MSVS/vs-7.1-exec.py1
-rw-r--r--test/MSVS/vs-7.1-scc-files.py1
-rw-r--r--test/MSVS/vs-7.1-scc-legacy-files.py1
-rw-r--r--test/MinGW/mingw_uses_comstr_issue_2799.py1
-rw-r--r--test/Progress/TARGET.py1
-rw-r--r--test/Progress/spinner.py1
-rw-r--r--test/Repository/Install.py1
-rw-r--r--test/Repository/InstallAs.py1
-rw-r--r--test/Repository/M4.py1
-rw-r--r--test/SConsignFile/default.py27
-rw-r--r--test/SConsignFile/explicit-dbm-module.py85
-rw-r--r--test/SConsignFile/explicit-file.py29
-rw-r--r--test/SConsignFile/make-directory.py17
-rw-r--r--test/SConsignFile/use-dbhash.py18
-rw-r--r--test/SConsignFile/use-dbm.py40
-rw-r--r--test/SConsignFile/use-dumbdbm.py33
-rw-r--r--test/SConsignFile/use-gdbm.py33
-rw-r--r--test/SWIG/SWIGFLAGS.py1
-rw-r--r--test/SWIG/live.py1
-rw-r--r--test/Scanner/Scanner.py1
-rw-r--r--test/TEMPFILE/TEMPFILE-actionlist.py53
-rw-r--r--test/TEMPFILE/TEMPFILEDIR.py (renamed from test/TempFileMunge/TEMPFILEDIR.py)0
-rw-r--r--test/TEMPFILE/TEMPFILEPREFIX.py (renamed from test/TempFileMunge/TEMPFILEPREFIX.py)2
-rw-r--r--test/TEMPFILE/TEMPFILESUFFIX.py (renamed from test/TempFileMunge/TEMPFILESUFFIX.py)2
-rw-r--r--test/TEMPFILE/fixture/SConstruct-tempfile-actionlist6
-rw-r--r--test/TEMPFILE/fixture/SConstruct.tempfiledir (renamed from test/TempFileMunge/fixture/SConstruct.tempfiledir)0
-rw-r--r--test/TEX/generated_files.py1
-rw-r--r--test/TEX/synctex.py1
-rw-r--r--test/Value/GetContent.py50
-rw-r--r--test/Variables/BoolVariable.py1
-rw-r--r--test/Variables/EnumVariable.py1
-rw-r--r--test/Variables/PackageVariable.py1
-rw-r--r--test/YACC/YACCFLAGS.py1
-rw-r--r--test/YACC/live.py2
-rw-r--r--test/ZIP/ZIPROOT.py2
-rw-r--r--test/emitter.py1
-rw-r--r--test/exitfns.py3
-rw-r--r--test/gettext/MOFiles/UserExamples.py1
-rw-r--r--test/gettext/POUpdate/UserExamples.py1
-rw-r--r--test/gettext/Translate/MultiCatalog.py1
-rw-r--r--test/ignore-command.py1
-rw-r--r--test/import.py1
-rw-r--r--test/long-lines/signature.py4
-rw-r--r--test/multiline.py1
-rw-r--r--test/no-arguments.py1
-rw-r--r--test/option--random.py1
-rw-r--r--test/option--tree.py1
-rw-r--r--test/option-k.py1
-rw-r--r--test/option/debug-count.py7
-rw-r--r--test/option/debug-memory.py16
-rw-r--r--test/option/debug-objects.py7
-rw-r--r--test/packaging/msi/explicit-target.py2
-rw-r--r--test/packaging/msi/file-placement.py2
-rw-r--r--test/packaging/msi/package.py2
-rw-r--r--test/packaging/place-files-in-subdirectory.py1
-rw-r--r--test/python-version.py1
-rw-r--r--test/runtest/SCons.py7
-rw-r--r--test/runtest/faillog.py (renamed from test/runtest/fallback.py)42
-rw-r--r--test/runtest/no_faillog.py (renamed from test/runtest/noqmtest.py)36
-rw-r--r--test/runtest/print_time.py4
-rw-r--r--test/runtest/python.py2
-rw-r--r--test/runtest/retry.py69
-rw-r--r--test/runtest/simple/combined.py25
-rw-r--r--test/runtest/testlistfile.py5
-rw-r--r--test/scons-time/func/prefix.py1
-rw-r--r--test/scons-time/run/archive/zip.py1
-rw-r--r--test/sconsign/script/SConsignFile.py1
-rw-r--r--test/silent-command.py1
-rw-r--r--test/srcchange.py1
-rw-r--r--test/subdir.py1
-rw-r--r--test/symlink/dangling-include.py1
-rw-r--r--test/symlink/dangling-source.py1
-rw-r--r--test/timestamp-fallback.py1
-rw-r--r--test/tool_args.py1
-rw-r--r--test/toolpath/basic.py1
-rw-r--r--test/toolpath/nested/nested.py1
-rw-r--r--test/toolpath/relative_import/relative_import.py1
-rw-r--r--test/update-release-info/update-release-info.py3
-rw-r--r--test/virtualenv/activated/option/enable-virtualenv.py1
-rw-r--r--test/virtualenv/activated/option/ignore-virtualenv.py1
-rw-r--r--test/virtualenv/activated/virtualenv_activated_python.py1
-rw-r--r--test/virtualenv/activated/virtualenv_detect_virtualenv.py1
-rw-r--r--test/virtualenv/regularenv/virtualenv_detect_regularenv.py1
-rw-r--r--test/virtualenv/unactivated/virtualenv_unactivated_python.py1
-rw-r--r--testing/framework/TestCmd.py7
-rw-r--r--testing/framework/TestCmdTests.py2
-rw-r--r--testing/framework/TestCommon.py1
-rw-r--r--testing/framework/TestCommonTests.py2
-rw-r--r--testing/framework/TestRuntest.py2
-rw-r--r--testing/framework/TestSCons.py34
-rw-r--r--testing/framework/TestSConsign.py1
388 files changed, 3651 insertions, 3455 deletions
diff --git a/.appveyor/install.bat b/.appveyor/install.bat
index 67a064d..3dea66a 100644
--- a/.appveyor/install.bat
+++ b/.appveyor/install.bat
@@ -3,7 +3,7 @@ for /F "tokens=*" %%g in ('C:\\%WINPYTHON%\\python.exe -c "import sys; print(sys
REM use mingw 32 bit until #3291 is resolved
set PATH=C:\\%WINPYTHON%;C:\\%WINPYTHON%\\Scripts;C:\\ProgramData\\chocolatey\\bin;C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin;C:\\cygwin\\bin;C:\\msys64\\usr\\bin;C:\\msys64\\mingw64\\bin;%PATH%
C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off pip setuptools wheel
-C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off pypiwin32 coverage codecov
+C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off coverage codecov
set STATIC_DEPS=true & C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off lxml
REM install 3rd party tools to test with
choco install --allow-empty-checksums dmd ldc swig vswhere xsltproc winflexbison
diff --git a/.gitignore b/.gitignore
index ec824d7..a7b59b3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,7 @@ htmlcov
# Mac junk
**/.DS_Store
+
+
+# SCons specific
+*.1
diff --git a/.travis.yml b/.travis.yml
index 263a7ea..10bc138 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -92,3 +92,4 @@ jobs:
- python scripts/scons.py
- ls -l build/dist
- python build/scons-local/scons.py --version
+ - ./.travis/verify_packages.sh
diff --git a/.travis/verify_packages.sh b/.travis/verify_packages.sh
new file mode 100755
index 0000000..de64a4f
--- /dev/null
+++ b/.travis/verify_packages.sh
@@ -0,0 +1,32 @@
+#!/usr/bin/env bash
+set -e
+set -x
+
+retval=0
+expected_man_file_count=3
+echo "Checking wheel file"
+wheel_man_files=$(unzip -l build/dist/SCons-*-py3-none-any.whl | grep -e '[a-z].1$' | wc -l | xargs)
+echo "Number of manpage files: $wheel_man_files"
+
+echo "Checking tgz sdist package"
+tgz_man_files=$(tar tvfz build/dist/SCons-*.tar.gz | grep -e '[a-z].1$' | wc -l |xargs)
+
+echo "Checking zip sdist package"
+zip_man_files=$(unzip -l build/dist/SCons-*.zip | grep -e '[a-z].1$' | wc -l |xargs)
+
+if [[ $wheel_man_files != $expected_man_file_count ]]; then
+ echo "Manpages not in wheel"
+ retval=1
+fi
+
+if [[ $tgz_man_files != $expected_man_file_count ]]; then
+ echo "Manpages not in tgz sdist package"
+ retval=2
+fi
+
+if [[ $zip_man_files != $expected_man_file_count ]]; then
+ echo "Manpages not in zip sdist package"
+ retval=3
+fi
+
+exit $retval \ No newline at end of file
diff --git a/CHANGES.txt b/CHANGES.txt
index 6293590..7d11cb9 100755
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -8,6 +8,10 @@ NOTE: The 4.0.0 Release of SCons dropped Python 2.7 Support
RELEASE VERSION/DATE TO BE FILLED IN LATER
+ From James Benton:
+ - Add COMPILATIONDB_PATH_FILTER env option for CompilationDatabase() builder which allows
+ filtering of entries based on the output file paths using glob style file matching (issue #3742).
+
From Joseph Brill:
- Internal MSVC and test updates: Rework the msvc installed versions cache so that it
is not exposed externally and update external references accordingly.
@@ -17,10 +21,34 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
From William Deegan:
- Fix yacc tool, not respecting YACC set at time of tool initialization.
- Refactor SCons.Tool to move all common shared and loadable module linking logic to SCons.Tool.linkCommon
+ - Remove pywin32 imports from SCons.Script.Main. No longer needed.
+ - Switch to use ctypes instead of pywin32 (requiring an extra pip install) - Fixes Github Issue #2291
+ - pywin32 no longer necessary for SCons install. (pip install SCons will no longer also require pywin32 on win32)
+ - Remove pywin32 usage from SCons.Util where it was used for accessing the registry. Python native winreg
+ library already includes this functionality.
+ - Remove using pywin32 to retrieve peak memory usage on Win32 for `--debug=memory`
+ - Fix Issue #3759 - include scons.1, sconsign.1, scons-time.1 manpages in sdist and wheel packages.
+ - Change SCons's build so the generated `SCons/__init__.py` is no longer removed by `scons -c`
+
+ From Michał Górny:
+ - Fix dvipdf test failure due to passing incorrect flag to dvipdf.
From Adam Gross:
- Fix minor bug affecting SCons.Node.FS.File.get_csig()'s usage of the MD5 chunksize.
User-facing behavior does not change with this fix (GH Issue #3726).
+ - Fix occasional test failures caused by not being able to find a file or directory fixture
+ when running multiple tests with multiple jobs.
+ - Fix incorrect cache hits and/or misses when running in interactive mode by having
+ SCons.Node.Node.clear() clear out all caching-related state.
+
+ From Jason Kenny
+ - Fix python3 crash when Value node get_text_content when child content does not have decode()
+ NOTE: If you depend on Value node's get_text_content returning concatenated contents of it's
+ children. This may break your code. It now concatenates the csig() of all children.
+
+ From Joachim Kuebart:
+ - Suppress missing SConscript deprecation warning if `must_exist=False`
+ is used.
From Rocco Matano:
- Fix Zip tool to respect ZIPCOMSTR. Previously all zip builder calls would yield something
@@ -30,15 +58,54 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
From Daniel Moody:
- Fix issue where java parsed a class incorrectly from lambdas used after a new.
+ From Simon Tegelid
+ - Fix using TEMPFILE in multiple actions in an action list. Previously a builder, or command
+ with an action list like this:
+ ['${TEMPFILE("xxx.py -otempfile $SOURCE")}', '${TEMPFILE("yyy.py -o$TARGET tempfile")}']
+ Could yield a single tempfile with the first TEMPFILE's contents, used by both steps
+ in the action list.
+
From Mats Wichmann:
- Complete tests for Dictionary, env.keys() and env.values() for
OverrideEnvironment. Enable env.setdefault() method, add tests.
- Raise an error if an option (not otherwise consumed) is used which
looks like an abbreviation of one one added by AddOption. (#3653)
+ - Tool module not found will now raise a UserError to more clearly indicate this is
+ probably an SConscript problem, and to make the traceback more relevant.
+ - Fix three issues with MergeFlags:
+ - Signature/return did not match documentation or existing usage - the implementation
+ now no longer returns the passed env
+ - merging --param arguments did not work (issue #3107);
+ - passing a dict to merge where the values are strings failed (issue #2961).
+ - Include previously-excluded SideEffect section in User Guide.
+ - Clean up unneeded imports (autoflake tool).
+ - Make sure cProfile is used if profiling - SCons was expecting
+ the Util module to monkeypatch in cProfile as profile if available,
+ but this is no longer being done.
+ - Cleanup in SCons.Util.AddMethod. If called with an environment instance
+ as the object to modify, the method would not be correctly set up in
+ any Clone of that instance. Now tries to detect this and calls
+ MethodWrapper to set up the method the same way env.AddMethod does.
+ MethodWrapper moved to Util to avoid a circular import. Fixes #3028.
+ - Some Python 2 compatibility code dropped
+ - Rework runtest.py to use argparse for arg handling (was a mix
+ of hand-coded and optparse, with a stated intent to "gradually port").
+ - Add options to runtest to generate/not generate a log of failed tests,
+ and to rerun such tests. Useful when an error cascades through several
+ tests, can quickly try if a change improves all the fails. Dropped
+ runtest test for fallback from qmtest, not needed; added new tests.
+ - Eliminate tex tool usage of "for foo in range(len(iterable))"
+ - Restore internal Trace function to functional state.
+ - Only try to initialize the wix tool by default (or when tool `default` is explicitly installed)
+ on Windows based systems.
+ - Pick a better "Topic" Trove classifier for SCons: SW Dev / Build Tools
+ - Use os.replace instead of os.rename in dblite so don't need to
+ special-case Windows here. dblite is the default storage engine for the SConsign file(s).
+ - Fix cut-n-paste error in msvc debug printout and make some debug output
+ in msvs and msvsTests.py be off until needed (uncomment to use)
+ - Fix Issue #3014 - Empty file and missing file have same csig
+
- From Joachim Kuebart:
- - Suppress missing SConscript deprecation warning if `must_exist=False`
- is used.
RELEASE 4.0.1 - Mon, 16 Jul 2020 16:06:40 -0700
@@ -70,6 +137,7 @@ RELEASE 4.0.0 - Sat, 04 Jul 2020 12:00:27 +0000
removed libxslt support from the Docbook Tool. (issue #3580)
- Added Docker images for building and testing SCons. (issue #3585)
+
From James Benton:
- Improve Visual Studio solution/project generation code to add support
for a per-variant cppflags. Intellisense can be affected by cppflags,
diff --git a/MANIFEST.in b/MANIFEST.in
index e509c38..04ec000 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -3,6 +3,8 @@ recursive-include SCons/Tool/docbook *
# For license file
include LICENSE
+include scons.1 sconsign.1 scons-time.1
+recursive-include build/doc/man *.1
diff --git a/README-SF.rst b/README-SF.rst
index e33c3f1..fce28d9 100755
--- a/README-SF.rst
+++ b/README-SF.rst
@@ -48,8 +48,7 @@ Execution Requirements
======================
Running SCons requires Python 3.5 or higher. There should be no other
-dependencies or requirements to run scons, although the pywin32 Python
-package is strongly recommended if running on Windows systems.
+dependencies or requirements to run scons.
The default SCons configuration assumes use of the Microsoft Visual C++
compiler suite on Win32 systems, and assumes a C compiler named 'cc', a C++
diff --git a/README-package.rst b/README-package.rst
index 605e5fe..4aaea1c 100755
--- a/README-package.rst
+++ b/README-package.rst
@@ -45,8 +45,7 @@ Requirements
------------
Running SCons requires Python 3.5 or higher. There should be no other
-dependencies or requirements to run SCons, although the pywin32 Python
-package is strongly recommended if running on Windows systems.
+dependencies or requirements to run SCons.
By default, SCons knows how to search for available programming tools on
diff --git a/README.rst b/README.rst
index 79f730a..1d7b858 100755
--- a/README.rst
+++ b/README.rst
@@ -73,8 +73,7 @@ Execution Requirements
======================
Running SCons requires Python 3.5 or higher. There should be no other
-dependencies or requirements to run scons, although the pywin32 Python
-package is strongly recommended if running on Windows systems.
+dependencies or requirements to run scons
The default SCons configuration assumes use of the Microsoft Visual C++
compiler suite on Win32 systems, and assumes a C compiler named 'cc', a C++
@@ -98,33 +97,20 @@ Nothing special.
Executing SCons Without Installing
==================================
-You can execute the local SCons directly from the SCons subdirectory by first
-setting the SCONS_LIB_DIR environment variable to the local SCons
-subdirectory, and then executing the local scripts/scons.py script to
-populate the build/scons/ subdirectory. You would do this as follows on a
-Linux or UNIX system (using sh or a derivative like bash or ksh)::
+You can execute the SCons directly from this repository. For Linux or UNIX::
- $ setenv MYSCONS=`pwd`
- $ python $MYSCONS/scripts/scons.py [arguments]
+ $ python scripts/scons.py [arguments]
Or on Windows::
- C:\scons>set MYSCONS=%cd%
- C:\scons>python %MYSCONS%\scripts\scons.py [arguments]
-
-An alternative approach is to skip the above and use::
-
- $ python scripts/scons.py [arguments]
+ C:\scons>python scripts\scons.py [arguments]
-
-You can use the -C option to have SCons change directory to another location
-where you already have a build configuration set up::
+If you run SCons this way, it will execute `SConstruct` file for this repo,
+which will build and pack SCons itself. Use the -C option to change directory
+to your project::
$ python scripts/scons.py -C /some/other/location [arguments]
-For simplicity in the following examples, we will only show the bootstrap.py
-approach.
-
Installation
============
diff --git a/SCons/Action.py b/SCons/Action.py
index 1f499ee..d7f10df 100644
--- a/SCons/Action.py
+++ b/SCons/Action.py
@@ -1,11 +1,34 @@
-"""SCons.Action
+# MIT License
+#
+# Copyright 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.
+
+"""SCons Actions.
-This encapsulates information about executing any sort of action that
+Information about executing any sort of action that
can build one or more target Nodes (typically files) from one or more
source Nodes (also typically files) given a specific Environment.
The base class here is ActionBase. The base class supplies just a few
-OO utility methods and some generic methods for displaying information
+utility methods and some generic methods for displaying information
about an Action in response to the various commands that control printing.
A second-level base class is _ActionAction. This extends ActionBase
@@ -60,7 +83,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)
+ TODO(?): Change this to always return bytes and not str?
strfunction()
Returns a substituted string representation of the Action.
@@ -77,29 +100,6 @@ way for wrapping up the functions.
"""
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
import os
import pickle
import re
diff --git a/SCons/Action.xml b/SCons/Action.xml
index 8263a57..0e3ef33 100644
--- a/SCons/Action.xml
+++ b/SCons/Action.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
diff --git a/SCons/ActionTests.py b/SCons/ActionTests.py
index 81dacfa..c03e87f 100644
--- a/SCons/ActionTests.py
+++ b/SCons/ActionTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,13 +22,11 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-
# Define a null function and a null class for use as builder actions.
# Where these are defined in the file seems to affect their byte-code
# contents, so try to minimize changes by defining them here, before we
# even import anything.
+
def GlobalFunc():
pass
diff --git a/SCons/Builder.py b/SCons/Builder.py
index 5f51078..035196d 100644
--- a/SCons/Builder.py
+++ b/SCons/Builder.py
@@ -1,3 +1,26 @@
+# MIT License
+#
+# Copyright 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.
+
"""
SCons.Builder
@@ -76,30 +99,6 @@ There are the following methods for internal use within this module:
"""
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
from collections import UserDict, UserList
import SCons.Action
diff --git a/SCons/BuilderTests.py b/SCons/BuilderTests.py
index d8c9d48..0e46194 100644
--- a/SCons/BuilderTests.py
+++ b/SCons/BuilderTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,8 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
diff --git a/SCons/CacheDir.py b/SCons/CacheDir.py
index 3bb6671..879c21b 100644
--- a/SCons/CacheDir.py
+++ b/SCons/CacheDir.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-__doc__ = """
-CacheDir support
+"""CacheDir support
"""
import atexit
diff --git a/SCons/CacheDirTests.py b/SCons/CacheDirTests.py
index 17294d5..f0278ac 100644
--- a/SCons/CacheDirTests.py
+++ b/SCons/CacheDirTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
import shutil
diff --git a/SCons/Conftest.py b/SCons/Conftest.py
index 4491884..908713c 100644
--- a/SCons/Conftest.py
+++ b/SCons/Conftest.py
@@ -1,9 +1,6 @@
-"""SCons.Conftest
-
-Autoconf-like configuration support; low level implementation of tests.
-"""
-
+# MIT License
#
+# Copyright The SCons Foundation
# Copyright (c) 2003 Stichting NLnet Labs
# Copyright (c) 2001, 2002, 2003 Steven Knight
#
@@ -25,80 +22,72 @@ Autoconf-like configuration support; low level implementation of tests.
# 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.
-#
-#
-# The purpose of this module is to define how a check is to be performed.
-# Use one of the Check...() functions below.
-#
-
-#
-# A context class is used that defines functions for carrying out the tests,
-# logging and messages. The following methods and members must be present:
-#
-# context.Display(msg) Function called to print messages that are normally
-# displayed for the user. Newlines are explicitly used.
-# The text should also be written to the logfile!
-#
-# context.Log(msg) Function called to write to a log file.
-#
-# context.BuildProg(text, ext)
-# Function called to build a program, using "ext" for the
-# file extention. Must return an empty string for
-# success, an error message for failure.
-# For reliable test results building should be done just
-# like an actual program would be build, using the same
-# command and arguments (including configure results so
-# far).
-#
-# context.CompileProg(text, ext)
-# Function called to compile a program, using "ext" for
-# the file extention. Must return an empty string for
-# success, an error message for failure.
-# For reliable test results compiling should be done just
-# like an actual source file would be compiled, using the
-# same command and arguments (including configure results
-# so far).
-#
-# context.AppendLIBS(lib_name_list)
-# Append "lib_name_list" to the value of LIBS.
-# "lib_namelist" is a list of strings.
-# Return the value of LIBS before changing it (any type
-# can be used, it is passed to SetLIBS() later.)
-#
-# context.PrependLIBS(lib_name_list)
-# Prepend "lib_name_list" to the value of LIBS.
-# "lib_namelist" is a list of strings.
-# Return the value of LIBS before changing it (any type
-# can be used, it is passed to SetLIBS() later.)
-#
-# context.SetLIBS(value)
-# Set LIBS to "value". The type of "value" is what
-# AppendLIBS() returned.
-# Return the value of LIBS before changing it (any type
-# can be used, it is passed to SetLIBS() later.)
-#
-# context.headerfilename
-# Name of file to append configure results to, usually
-# "confdefs.h".
-# The file must not exist or be empty when starting.
-# Empty or None to skip this (some tests will not work!).
-#
-# context.config_h (may be missing). If present, must be a string, which
-# will be filled with the contents of a config_h file.
-#
-# context.vardict Dictionary holding variables used for the tests and
-# stores results from the tests, used for the build
-# commands.
-# Normally contains "CC", "LIBS", "CPPFLAGS", etc.
-#
-# context.havedict Dictionary holding results from the tests that are to
-# be used inside a program.
-# Names often start with "HAVE_". These are zero
-# (feature not present) or one (feature present). Other
-# variables may have any value, e.g., "PERLVERSION" can
-# be a number and "SYSTEMNAME" a string.
-#
+"""Autoconf-like configuration support
+
+The purpose of this module is to define how a check is to be performed.
+
+A context class is used that defines functions for carrying out the tests,
+logging and messages. The following methods and members must be present:
+
+context.Display(msg)
+ Function called to print messages that are normally displayed
+ for the user. Newlines are explicitly used. The text should
+ also be written to the logfile!
+
+context.Log(msg)
+ Function called to write to a log file.
+
+context.BuildProg(text, ext)
+ Function called to build a program, using "ext" for the file
+ extension. Must return an empty string for success, an error
+ message for failure. For reliable test results building should
+ be done just like an actual program would be build, using the
+ same command and arguments (including configure results so far).
+
+context.CompileProg(text, ext)
+ Function called to compile a program, using "ext" for the file
+ extension. Must return an empty string for success, an error
+ message for failure. For reliable test results compiling should be
+ done just like an actual source file would be compiled, using the
+ same command and arguments (including configure results so far).
+
+context.AppendLIBS(lib_name_list)
+ Append "lib_name_list" to the value of LIBS. "lib_namelist" is
+ a list of strings. Return the value of LIBS before changing it
+ (any type can be used, it is passed to SetLIBS() later.)
+
+context.PrependLIBS(lib_name_list)
+ Prepend "lib_name_list" to the value of LIBS. "lib_namelist" is
+ a list of strings. Return the value of LIBS before changing it
+ (any type can be used, it is passed to SetLIBS() later.)
+
+context.SetLIBS(value)
+ Set LIBS to "value". The type of "value" is what AppendLIBS()
+ returned. Return the value of LIBS before changing it (any type
+ can be used, it is passed to SetLIBS() later.)
+
+context.headerfilename
+ Name of file to append configure results to, usually "confdefs.h".
+ The file must not exist or be empty when starting. Empty or None
+ to skip this (some tests will not work!).
+
+context.config_h (may be missing).
+ If present, must be a string, which will be filled with the
+ contents of a config_h file.
+
+context.vardict
+ Dictionary holding variables used for the tests and stores results
+ from the tests, used for the build commands. Normally contains
+ "CC", "LIBS", "CPPFLAGS", etc.
+
+context.havedict
+ Dictionary holding results from the tests that are to be used
+ inside a program. Names often start with "HAVE_". These are zero
+ (feature not present) or one (feature present). Other variables
+ may have any value, e.g., "PERLVERSION" can be a number and
+ "SYSTEMNAME" a string.
+"""
import re
diff --git a/SCons/Debug.py b/SCons/Debug.py
index 2212eb8..f4b802e 100644
--- a/SCons/Debug.py
+++ b/SCons/Debug.py
@@ -1,15 +1,6 @@
-"""SCons.Debug
-
-Code for debugging SCons internal things. Shouldn't be
-needed by most users. Quick shortcuts:
-
-from SCons.Debug import caller_trace
-caller_trace()
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,14 @@ caller_trace()
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Code for debugging SCons internal things.
+
+Shouldn't be needed by most users. Quick shortcuts:
+
+from SCons.Debug import caller_trace
+caller_trace()
+"""
import atexit
import os
@@ -94,7 +90,6 @@ def dumpLoggedInstances(classes, file=sys.stdout):
file.write(' %20s : %s\n' % (key, value))
-
if sys.platform[:5] == "linux":
# Linux doesn't actually support memory usage stats from getrusage().
def memory():
@@ -106,28 +101,23 @@ elif sys.platform[:6] == 'darwin':
#TODO really get memory stats for OS X
def memory():
return 0
+elif sys.platform == 'win32':
+ from SCons.compat.win32 import get_peak_memory_usage
+ memory = get_peak_memory_usage
else:
try:
import resource
except ImportError:
- try:
- import win32process
- import win32api
- except ImportError:
- def memory():
- return 0
- else:
- def memory():
- process_handle = win32api.GetCurrentProcess()
- memory_info = win32process.GetProcessMemoryInfo( process_handle )
- return memory_info['PeakWorkingSetSize']
+ def memory():
+ return 0
else:
def memory():
res = resource.getrusage(resource.RUSAGE_SELF)
return res[4]
-# returns caller's stack
+
def caller_stack():
+ """return caller's stack"""
import traceback
tb = traceback.extract_stack()
# strip itself and the caller from the output
@@ -206,17 +196,17 @@ TimeStampDefault = False
StartTime = time.time()
PreviousTime = StartTime
-def Trace(msg, filename=None, mode='w', tstamp=False):
+def Trace(msg, tracefile=None, mode='w', tstamp=False):
"""Write a trace message.
Write messages when debugging which do not interfere with stdout.
Useful in tests, which monitor stdout and would break with
unexpected output. Trace messages can go to the console (which is
- opened as a file), or to a disk file; the file argument persists
+ opened as a file), or to a disk file; the tracefile argument persists
across calls unless overridden.
Args:
- filename: file to write trace message to. If omitted,
+ tracefile: file to write trace message to. If omitted,
write to the previous trace file (default: console).
mode: file open mode (default: 'w')
tstamp: write relative timestamps with trace. Outputs time since
@@ -230,23 +220,23 @@ def Trace(msg, filename=None, mode='w', tstamp=False):
def trace_cleanup(traceFP):
traceFP.close()
- if file is None:
- file = TraceDefault
+ if tracefile is None:
+ tracefile = TraceDefault
else:
- TraceDefault = file
+ TraceDefault = tracefile
if not tstamp:
tstamp = TimeStampDefault
else:
TimeStampDefault = tstamp
try:
- fp = TraceFP[file]
+ fp = TraceFP[tracefile]
except KeyError:
try:
- fp = TraceFP[file] = open(file, mode)
+ fp = TraceFP[tracefile] = open(tracefile, mode)
atexit.register(trace_cleanup, fp)
except TypeError:
# Assume we were passed an open file pointer.
- fp = file
+ fp = tracefile
if tstamp:
now = time.time()
fp.write('%8.4f %8.4f: ' % (now - StartTime, now - PreviousTime))
diff --git a/SCons/Defaults.py b/SCons/Defaults.py
index 143342e..c59fbcf 100644
--- a/SCons/Defaults.py
+++ b/SCons/Defaults.py
@@ -1,14 +1,6 @@
-"""SCons.Defaults
-
-Builders and other things for the local site. Here's where we'll
-duplicate the functionality of autoconf until we move it into the
-installation procedure or use something like qmconf.
-
-The code that reads the registry to find MSVC components was borrowed
-from distutils.msvccompiler.
-
-"""
-
+# MIT License
+#
+# Copyright 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,6 +22,14 @@ from distutils.msvccompiler.
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
+"""Builders and other things for the local site.
+
+Here's where we'll duplicate the functionality of autoconf until we
+move it into the installation procedure or use something like qmconf.
+
+The code that reads the registry to find MSVC components was borrowed
+from distutils.msvccompiler.
+"""
import os
import errno
@@ -55,9 +55,7 @@ _default_env = None
# Lazily instantiate the default environment so the overhead of creating
# it doesn't apply when it's not needed.
def _fetch_DefaultEnvironment(*args, **kw):
- """
- Returns the already-created default construction environment.
- """
+ """Returns the already-created default construction environment."""
global _default_env
return _default_env
diff --git a/SCons/Defaults.xml b/SCons/Defaults.xml
index 8f3fe12..6b034d9 100644
--- a/SCons/Defaults.xml
+++ b/SCons/Defaults.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
diff --git a/SCons/DefaultsTests.py b/SCons/DefaultsTests.py
index 34941bc..1e1ebdd 100644
--- a/SCons/DefaultsTests.py
+++ b/SCons/DefaultsTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,21 +20,17 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
import os
-import sys
import unittest
import TestCmd
import SCons.Errors
-from SCons.Defaults import *
+from SCons.Defaults import mkdir_func
class DefaultsTestCase(unittest.TestCase):
def test_mkdir_func0(self):
diff --git a/SCons/Environment.py b/SCons/Environment.py
index 13eaf3c..55a5003 100644
--- a/SCons/Environment.py
+++ b/SCons/Environment.py
@@ -1,16 +1,6 @@
-"""SCons.Environment
-
-Base class for construction Environments. These are
-the primary objects used to communicate dependency and
-construction information to the build engine.
-
-Keyword arguments supplied when the construction Environment
-is created are construction variables used to initialize the
-Environment
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -31,8 +21,14 @@ Environment
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Base class for construction Environments.
+
+These are the primary objects used to communicate dependency and
+construction information to the build engine.
+Keyword arguments supplied when the construction Environment is created
+are construction variables used to initialize the Environment.
+"""
import copy
import os
@@ -57,8 +53,27 @@ import SCons.SConf
import SCons.SConsign
import SCons.Subst
import SCons.Tool
-import SCons.Util
import SCons.Warnings
+from SCons.Util import (
+ AppendPath,
+ CLVar,
+ LogicalLines,
+ MethodWrapper,
+ PrependPath,
+ Split,
+ WhereIs,
+ flatten,
+ is_Dict,
+ is_List,
+ is_Sequence,
+ is_String,
+ is_Tuple,
+ md5,
+ semi_deepcopy,
+ semi_deepcopy_dict,
+ to_String_for_subst,
+ uniquer_hashables,
+)
class _Null:
pass
@@ -72,18 +87,17 @@ _warn_target_signatures_deprecated = True
CleanTargets = {}
CalculatorArgs = {}
-semi_deepcopy = SCons.Util.semi_deepcopy
-semi_deepcopy_dict = SCons.Util.semi_deepcopy_dict
-
def alias_builder(env, target, source):
pass
-AliasBuilder = SCons.Builder.Builder(action = alias_builder,
- target_factory = SCons.Node.Alias.default_ans.Alias,
- source_factory = SCons.Node.FS.Entry,
- multi = 1,
- is_explicit = None,
- name='AliasBuilder')
+AliasBuilder = SCons.Builder.Builder(
+ action=alias_builder,
+ target_factory=SCons.Node.Alias.default_ans.Alias,
+ source_factory=SCons.Node.FS.Entry,
+ multi=True,
+ is_explicit=None,
+ name='AliasBuilder',
+)
def apply_tools(env, tools, toolpath):
# Store the toolpath in the Environment.
@@ -94,7 +108,7 @@ def apply_tools(env, tools, toolpath):
return
# Filter out null tools from the list.
for tool in [_f for _f in tools if _f]:
- if SCons.Util.is_List(tool) or isinstance(tool, tuple):
+ if is_List(tool) or isinstance(tool, tuple):
toolname = tool[0]
toolargs = tool[1] # should be a dict of kw args
tool = env.Tool(toolname, **toolargs)
@@ -184,46 +198,15 @@ def _delete_duplicates(l, keep_last):
# Shannon at the following page (there called the "transplant" class):
#
# ASPN : Python Cookbook : Dynamically added methods to a class
-# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732
+# https://code.activestate.com/recipes/81732/
#
# We had independently been using the idiom as BuilderWrapper, but
# factoring out the common parts into this base class, and making
# BuilderWrapper a subclass that overrides __call__() to enforce specific
# Builder calling conventions, simplified some of our higher-layer code.
-
-class MethodWrapper:
- """
- A generic Wrapper class that associates a method (which can
- actually be any callable) with an object. As part of creating this
- MethodWrapper object an attribute with the specified (by default,
- the name of the supplied method) is added to the underlying object.
- When that new "method" is called, our __call__() method adds the
- object as the first argument, simulating the Python behavior of
- supplying "self" on method calls.
-
- We hang on to the name by which the method was added to the underlying
- base class so that we can provide a method to "clone" ourselves onto
- a new underlying object being copied (without which we wouldn't need
- to save that info).
- """
- def __init__(self, object, method, name=None):
- if name is None:
- name = method.__name__
- self.object = object
- self.method = method
- self.name = name
- setattr(self.object, name, self)
-
- def __call__(self, *args, **kwargs):
- nargs = (self.object,) + args
- return self.method(*nargs, **kwargs)
-
- def clone(self, new_object):
- """
- Returns an object that re-binds the underlying "method" to
- the specified new object.
- """
- return self.__class__(new_object, self.method, self.name)
+#
+# Note: MethodWrapper moved to SCons.Util as it was needed there
+# and otherwise we had a circular import problem.
class BuilderWrapper(MethodWrapper):
"""
@@ -248,11 +231,11 @@ class BuilderWrapper(MethodWrapper):
if source is _null:
source = target
target = None
- if target is not None and not SCons.Util.is_List(target):
+ if target is not None and not is_List(target):
target = [target]
- if source is not None and not SCons.Util.is_List(source):
+ if source is not None and not is_List(source):
source = [source]
- return MethodWrapper.__call__(self, target, source, *args, **kw)
+ return super().__call__(target, source, *args, **kw)
def __repr__(self):
return '<BuilderWrapper %s>' % repr(self.name)
@@ -465,24 +448,24 @@ class SubstitutionEnvironment:
if not args:
return []
- args = SCons.Util.flatten(args)
+ args = flatten(args)
nodes = []
for v in args:
- if SCons.Util.is_String(v):
+ if is_String(v):
n = None
for l in lookup_list:
n = l(v)
if n is not None:
break
if n is not None:
- if SCons.Util.is_String(n):
+ if is_String(n):
# n = self.subst(n, raw=1, **kw)
kw['raw'] = 1
n = self.subst(n, **kw)
if node_factory:
n = node_factory(n)
- if SCons.Util.is_List(n):
+ if is_List(n):
nodes.extend(n)
else:
nodes.append(n)
@@ -490,7 +473,7 @@ class SubstitutionEnvironment:
# v = node_factory(self.subst(v, raw=1, **kw))
kw['raw'] = 1
v = node_factory(self.subst(v, **kw))
- if SCons.Util.is_List(v):
+ if is_List(v):
nodes.extend(v)
else:
nodes.append(v)
@@ -526,7 +509,7 @@ class SubstitutionEnvironment:
nkw = {}
for k, v in kw.items():
k = self.subst(k, raw, target, source)
- if SCons.Util.is_String(v):
+ if is_String(v):
v = self.subst(v, raw, target, source)
nkw[k] = v
return nkw
@@ -545,7 +528,7 @@ class SubstitutionEnvironment:
"""Substitute a path list, turning EntryProxies into Nodes
and leaving Nodes (and other objects) as-is."""
- if not SCons.Util.is_List(path):
+ if not is_List(path):
path = [path]
def s(obj):
@@ -558,23 +541,23 @@ class SubstitutionEnvironment:
try:
get = obj.get
except AttributeError:
- obj = SCons.Util.to_String_for_subst(obj)
+ obj = to_String_for_subst(obj)
else:
obj = get()
return obj
r = []
for p in path:
- if SCons.Util.is_String(p):
+ if is_String(p):
p = self.subst(p, target=target, source=source, conv=s)
- if SCons.Util.is_List(p):
+ if is_List(p):
if len(p) == 1:
p = p[0]
else:
# We have an object plus a string, or multiple
# objects that we need to smush together. No choice
# but to make them into a string.
- p = ''.join(map(SCons.Util.to_String_for_subst, p))
+ p = ''.join(map(to_String_for_subst, p))
else:
p = s(p)
r.append(p)
@@ -592,7 +575,7 @@ class SubstitutionEnvironment:
}
# if the command is a list, assume it's been quoted
# othewise force a shell
- if not SCons.Util.is_List(command): kw['shell'] = True
+ if not is_List(command): kw['shell'] = True
# run constructed command
p = SCons.Action._subproc(self, command, **kw)
out,err = p.communicate()
@@ -642,32 +625,38 @@ class SubstitutionEnvironment:
else:
overrides[key] = SCons.Subst.scons_subst_once(value, self, key)
env = OverrideEnvironment(self, overrides)
- if merges: env.MergeFlags(merges)
+ if merges:
+ env.MergeFlags(merges)
return env
def ParseFlags(self, *flags):
- """
- Parse the set of flags and return a dict with the flags placed
- in the appropriate entry. The flags are treated as a typical
- set of command-line flags for a GNU-like toolchain and used to
- populate the entries in the dict immediately below. If one of
- the flag strings begins with a bang (exclamation mark), it is
- assumed to be a command and the rest of the string is executed;
+ """Return a dict of parsed flags.
+
+ Parse ``flags`` and return a dict with the flags distributed into
+ the appropriate construction variable names. The flags are treated
+ as a typical set of command-line flags for a GNU-like toolchain,
+ such as might have been generated by one of the \*-config scripts,
+ and used to populate the entries based on knowledge embedded in
+ this method - the choices are not expected to be portable to other
+ toolchains.
+
+ If one of the ``flags`` strings begins with a bang (exclamation mark),
+ it is assumed to be a command and the rest of the string is executed;
the result of that evaluation is then added to the dict.
"""
dict = {
- 'ASFLAGS' : SCons.Util.CLVar(''),
- 'CFLAGS' : SCons.Util.CLVar(''),
- 'CCFLAGS' : SCons.Util.CLVar(''),
- 'CXXFLAGS' : SCons.Util.CLVar(''),
+ 'ASFLAGS' : CLVar(''),
+ 'CFLAGS' : CLVar(''),
+ 'CCFLAGS' : CLVar(''),
+ 'CXXFLAGS' : CLVar(''),
'CPPDEFINES' : [],
- 'CPPFLAGS' : SCons.Util.CLVar(''),
+ 'CPPFLAGS' : CLVar(''),
'CPPPATH' : [],
- 'FRAMEWORKPATH' : SCons.Util.CLVar(''),
- 'FRAMEWORKS' : SCons.Util.CLVar(''),
+ 'FRAMEWORKPATH' : CLVar(''),
+ 'FRAMEWORKS' : CLVar(''),
'LIBPATH' : [],
'LIBS' : [],
- 'LINKFLAGS' : SCons.Util.CLVar(''),
+ 'LINKFLAGS' : CLVar(''),
'RPATH' : [],
}
@@ -676,7 +665,7 @@ class SubstitutionEnvironment:
if not arg:
return
- if not SCons.Util.is_String(arg):
+ if not is_String(arg):
for t in arg: do_parse(t)
return
@@ -741,6 +730,9 @@ class SubstitutionEnvironment:
t = ('-arch', arg)
dict['CCFLAGS'].append(t)
dict['LINKFLAGS'].append(t)
+ elif append_next_arg_to == '--param':
+ t = ('--param', arg)
+ dict['CCFLAGS'].append(t)
else:
dict[append_next_arg_to].append(arg)
append_next_arg_to = None
@@ -792,11 +784,13 @@ class SubstitutionEnvironment:
dict['FRAMEWORKPATH'].append(arg[2:])
else:
append_next_arg_to = 'FRAMEWORKPATH'
- elif arg in ['-mno-cygwin',
- '-pthread',
- '-openmp',
- '-fmerge-all-constants',
- '-fopenmp']:
+ elif arg in [
+ '-mno-cygwin',
+ '-pthread',
+ '-openmp',
+ '-fmerge-all-constants',
+ '-fopenmp',
+ ]:
dict['CCFLAGS'].append(arg)
dict['LINKFLAGS'].append(arg)
elif arg == '-mwindows':
@@ -810,7 +804,16 @@ class SubstitutionEnvironment:
elif arg[0] == '+':
dict['CCFLAGS'].append(arg)
dict['LINKFLAGS'].append(arg)
- elif arg in ['-include', '-imacros', '-isysroot', '-isystem', '-iquote', '-idirafter', '-arch']:
+ elif arg in [
+ '-include',
+ '-imacros',
+ '-isysroot',
+ '-isystem',
+ '-iquote',
+ '-idirafter',
+ '-arch',
+ '--param',
+ ]:
append_next_arg_to = arg
else:
dict['CCFLAGS'].append(arg)
@@ -819,24 +822,30 @@ class SubstitutionEnvironment:
do_parse(arg)
return dict
- def MergeFlags(self, args, unique=1, dict=None):
- """
- Merge the dict in args into the construction variables of this
- env, or the passed-in dict. If args is not a dict, it is
- converted into a dict using ParseFlags. If unique is not set,
- the flags are appended rather than merged.
- """
+ def MergeFlags(self, args, unique=True):
+ """Merge flags into construction variables.
+
+ Merges the flags from ``args`` into this construction environent.
+ If ``args`` is not a dict, it is first converted to a dictionary with
+ flags distributed into appropriate construction variables.
+ See :meth:`ParseFlags`.
+
+ Args:
+ args: flags to merge
+ unique: merge flags rather than appending (default: True)
- if dict is None:
- dict = self
- if not SCons.Util.is_Dict(args):
+ """
+ if not is_Dict(args):
args = self.ParseFlags(args)
+
if not unique:
self.Append(**args)
- return self
+ return
+
for key, value in args.items():
if not value:
continue
+ value = Split(value)
try:
orig = self[key]
except KeyError:
@@ -873,7 +882,6 @@ class SubstitutionEnvironment:
if v not in t:
t.insert(0, v)
self[key] = t
- return self
def default_decide_source(dependency, target, prev_ni, repo_node=None):
@@ -961,7 +969,7 @@ class Base(SubstitutionEnvironment):
platform = self._dict.get('PLATFORM', None)
if platform is None:
platform = SCons.Platform.Platform()
- if SCons.Util.is_String(platform):
+ if is_String(platform):
platform = SCons.Platform.Platform(platform)
self._dict['PLATFORM'] = str(platform)
platform(self)
@@ -1012,7 +1020,8 @@ class Base(SubstitutionEnvironment):
self._dict[key] = val
# Finally, apply any flags to be merged in
- if parse_flags: self.MergeFlags(parse_flags)
+ if parse_flags:
+ self.MergeFlags(parse_flags)
#######################################################################
# Utility methods that are primarily for internal use by SCons.
@@ -1089,7 +1098,7 @@ class Base(SubstitutionEnvironment):
# claim they can scan the same suffix, earlier scanners
# in the list will overwrite later scanners, so that
# the result looks like a "first match" to the user.
- if not SCons.Util.is_List(scanners):
+ if not is_List(scanners):
scanners = [scanners]
else:
scanners = scanners[:] # copy so reverse() doesn't mod original
@@ -1164,9 +1173,7 @@ class Base(SubstitutionEnvironment):
#######################################################################
def Append(self, **kw):
- """Append values to existing construction variables
- in an Environment.
- """
+ """Append values to existing construction variables in an Environment."""
kw = copy_non_reserved_keywords(kw)
for key, val in kw.items():
# It would be easier on the eyes to write this using
@@ -1174,13 +1181,13 @@ class Base(SubstitutionEnvironment):
# but Python 1.5.2 apparently doesn't let you use "continue"
# within try:-except: blocks, so we have to nest our code.
try:
- if key == 'CPPDEFINES' and SCons.Util.is_String(self._dict[key]):
+ if key == 'CPPDEFINES' and is_String(self._dict[key]):
self._dict[key] = [self._dict[key]]
orig = self._dict[key]
except KeyError:
# No existing variable in the environment, so just set
# it to the new value.
- if key == 'CPPDEFINES' and SCons.Util.is_String(val):
+ if key == 'CPPDEFINES' and is_String(val):
self._dict[key] = [val]
else:
self._dict[key] = val
@@ -1219,7 +1226,7 @@ class Base(SubstitutionEnvironment):
else:
# The original looks like a dictionary, so update it
# based on what we think the value looks like.
- if SCons.Util.is_List(val):
+ if is_List(val):
if key == 'CPPDEFINES':
tmp = []
for (k, v) in orig.items():
@@ -1237,7 +1244,7 @@ class Base(SubstitutionEnvironment):
try:
update_dict(val)
except (AttributeError, TypeError, ValueError):
- if SCons.Util.is_Dict(val):
+ if is_Dict(val):
for k, v in val.items():
orig[k] = v
else:
@@ -1247,7 +1254,7 @@ class Base(SubstitutionEnvironment):
# allow Dirs and strings beginning with # for top-relative
# Note this uses the current env's fs (in self).
def _canonicalize(self, path):
- if not SCons.Util.is_String(path): # typically a Dir
+ if not is_String(path): # typically a Dir
path = str(path)
if path and path[0] == '#':
path = str(self.fs.Dir(path))
@@ -1269,8 +1276,7 @@ class Base(SubstitutionEnvironment):
if envname in self._dict and name in self._dict[envname]:
orig = self._dict[envname][name]
- nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing,
- canonicalize=self._canonicalize)
+ nv = AppendPath(orig, newpath, sep, delete_existing, canonicalize=self._canonicalize)
if envname not in self._dict:
self._dict[envname] = {}
@@ -1285,30 +1291,30 @@ class Base(SubstitutionEnvironment):
"""
kw = copy_non_reserved_keywords(kw)
for key, val in kw.items():
- if SCons.Util.is_List(val):
+ if is_List(val):
val = _delete_duplicates(val, delete_existing)
if key not in self._dict or self._dict[key] in ('', None):
self._dict[key] = val
- elif SCons.Util.is_Dict(self._dict[key]) and \
- SCons.Util.is_Dict(val):
+ elif is_Dict(self._dict[key]) and \
+ is_Dict(val):
self._dict[key].update(val)
- elif SCons.Util.is_List(val):
+ elif is_List(val):
dk = self._dict[key]
if key == 'CPPDEFINES':
tmp = []
for i in val:
- if SCons.Util.is_List(i):
+ if is_List(i):
if len(i) >= 2:
tmp.append((i[0], i[1]))
else:
tmp.append((i[0],))
- elif SCons.Util.is_Tuple(i):
+ elif is_Tuple(i):
tmp.append(i)
else:
tmp.append((i,))
val = tmp
# Construct a list of (key, value) tuples.
- if SCons.Util.is_Dict(dk):
+ if is_Dict(dk):
tmp = []
for (k, v) in dk.items():
if v is not None:
@@ -1316,23 +1322,23 @@ class Base(SubstitutionEnvironment):
else:
tmp.append((k,))
dk = tmp
- elif SCons.Util.is_String(dk):
+ elif is_String(dk):
dk = [(dk,)]
else:
tmp = []
for i in dk:
- if SCons.Util.is_List(i):
+ if is_List(i):
if len(i) >= 2:
tmp.append((i[0], i[1]))
else:
tmp.append((i[0],))
- elif SCons.Util.is_Tuple(i):
+ elif is_Tuple(i):
tmp.append(i)
else:
tmp.append((i,))
dk = tmp
else:
- if not SCons.Util.is_List(dk):
+ if not is_List(dk):
dk = [dk]
if delete_existing:
dk = [x for x in dk if x not in val]
@@ -1341,22 +1347,22 @@ class Base(SubstitutionEnvironment):
self._dict[key] = dk + val
else:
dk = self._dict[key]
- if SCons.Util.is_List(dk):
+ if is_List(dk):
if key == 'CPPDEFINES':
tmp = []
for i in dk:
- if SCons.Util.is_List(i):
+ if is_List(i):
if len(i) >= 2:
tmp.append((i[0], i[1]))
else:
tmp.append((i[0],))
- elif SCons.Util.is_Tuple(i):
+ elif is_Tuple(i):
tmp.append(i)
else:
tmp.append((i,))
dk = tmp
# Construct a list of (key, value) tuples.
- if SCons.Util.is_Dict(val):
+ if is_Dict(val):
tmp = []
for (k, v) in val.items():
if v is not None:
@@ -1364,7 +1370,7 @@ class Base(SubstitutionEnvironment):
else:
tmp.append((k,))
val = tmp
- elif SCons.Util.is_String(val):
+ elif is_String(val):
val = [(val,)]
if delete_existing:
dk = list(filter(lambda x, val=val: x not in val, dk))
@@ -1383,9 +1389,9 @@ class Base(SubstitutionEnvironment):
self._dict[key] = dk + [val]
else:
if key == 'CPPDEFINES':
- if SCons.Util.is_String(dk):
+ if is_String(dk):
dk = [dk]
- elif SCons.Util.is_Dict(dk):
+ elif is_Dict(dk):
tmp = []
for (k, v) in dk.items():
if v is not None:
@@ -1393,12 +1399,12 @@ class Base(SubstitutionEnvironment):
else:
tmp.append((k,))
dk = tmp
- if SCons.Util.is_String(val):
+ if is_String(val):
if val in dk:
val = []
else:
val = [val]
- elif SCons.Util.is_Dict(val):
+ elif is_Dict(val):
tmp = []
for i,j in val.items():
if j is not None:
@@ -1453,7 +1459,8 @@ class Base(SubstitutionEnvironment):
clone.Replace(**new)
# Finally, apply any flags to be merged in
- if parse_flags: clone.MergeFlags(parse_flags)
+ if parse_flags:
+ clone.MergeFlags(parse_flags)
if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.EnvironmentClone')
return clone
@@ -1492,7 +1499,7 @@ class Base(SubstitutionEnvironment):
def Decider(self, function):
copy_function = self._copy2_from_cache
if function in ('MD5', 'content'):
- if not SCons.Util.md5:
+ if not md5:
raise UserError("MD5 signatures are not available in this version of Python.")
function = self._changed_content
elif function == 'MD5-timestamp':
@@ -1520,7 +1527,7 @@ class Base(SubstitutionEnvironment):
progs (str or list): one or more command names to check for
"""
- if not SCons.Util.is_List(progs):
+ if not is_List(progs):
progs = [progs]
for prog in progs:
path = self.WhereIs(prog)
@@ -1610,7 +1617,7 @@ class Base(SubstitutionEnvironment):
if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix:
return path
- def ParseConfig(self, command, function=None, unique=1):
+ def ParseConfig(self, command, function=None, unique=True):
"""
Use the specified function to parse the output of the command
in order to modify the current environment. The 'command' can
@@ -1625,12 +1632,12 @@ class Base(SubstitutionEnvironment):
def parse_conf(env, cmd, unique=unique):
return env.MergeFlags(cmd, unique)
function = parse_conf
- if SCons.Util.is_List(command):
+ if is_List(command):
command = ' '.join(command)
command = self.subst(command)
return function(self, self.backtick(command))
- def ParseDepends(self, filename, must_exist=None, only_one=0):
+ def ParseDepends(self, filename, must_exist=None, only_one=False):
"""
Parse a mkdep-style file for explicit dependencies. This is
completely abusable, and should be unnecessary in the "normal"
@@ -1643,7 +1650,7 @@ class Base(SubstitutionEnvironment):
filename = self.subst(filename)
try:
with open(filename, 'r') as fp:
- lines = SCons.Util.LogicalLines(fp).readlines()
+ lines = LogicalLines(fp).readlines()
except IOError:
if must_exist:
raise
@@ -1725,14 +1732,14 @@ class Base(SubstitutionEnvironment):
else:
# The original looks like a dictionary, so update it
# based on what we think the value looks like.
- if SCons.Util.is_List(val):
+ if is_List(val):
for v in val:
orig[v] = None
else:
try:
update_dict(val)
except (AttributeError, TypeError, ValueError):
- if SCons.Util.is_Dict(val):
+ if is_Dict(val):
for k, v in val.items():
orig[k] = v
else:
@@ -1755,7 +1762,7 @@ class Base(SubstitutionEnvironment):
if envname in self._dict and name in self._dict[envname]:
orig = self._dict[envname][name]
- nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing,
+ nv = PrependPath(orig, newpath, sep, delete_existing,
canonicalize=self._canonicalize)
if envname not in self._dict:
@@ -1771,16 +1778,16 @@ class Base(SubstitutionEnvironment):
"""
kw = copy_non_reserved_keywords(kw)
for key, val in kw.items():
- if SCons.Util.is_List(val):
+ if is_List(val):
val = _delete_duplicates(val, not delete_existing)
if key not in self._dict or self._dict[key] in ('', None):
self._dict[key] = val
- elif SCons.Util.is_Dict(self._dict[key]) and \
- SCons.Util.is_Dict(val):
+ elif is_Dict(self._dict[key]) and \
+ is_Dict(val):
self._dict[key].update(val)
- elif SCons.Util.is_List(val):
+ elif is_List(val):
dk = self._dict[key]
- if not SCons.Util.is_List(dk):
+ if not is_List(dk):
dk = [dk]
if delete_existing:
dk = [x for x in dk if x not in val]
@@ -1789,7 +1796,7 @@ class Base(SubstitutionEnvironment):
self._dict[key] = val + dk
else:
dk = self._dict[key]
- if SCons.Util.is_List(dk):
+ if is_List(dk):
# By elimination, val is not a list. Since dk is a
# list, wrap val in a list first.
if delete_existing:
@@ -1854,7 +1861,7 @@ class Base(SubstitutionEnvironment):
return self.fs.Dir(self.subst(tp)).srcnode().get_abspath()
def Tool(self, tool, toolpath=None, **kw):
- if SCons.Util.is_String(tool):
+ if is_String(tool):
tool = self.subst(tool)
if toolpath is None:
toolpath = self.get('toolpath', [])
@@ -1870,17 +1877,17 @@ class Base(SubstitutionEnvironment):
path = self['ENV']['PATH']
except KeyError:
pass
- elif SCons.Util.is_String(path):
+ elif is_String(path):
path = self.subst(path)
if pathext is None:
try:
pathext = self['ENV']['PATHEXT']
except KeyError:
pass
- elif SCons.Util.is_String(pathext):
+ elif is_String(pathext):
pathext = self.subst(pathext)
- prog = SCons.Util.CLVar(self.subst(prog)) # support "program --with-args"
- path = SCons.Util.WhereIs(prog[0], path, pathext, reject)
+ prog = CLVar(self.subst(prog)) # support "program --with-args"
+ path = WhereIs(prog[0], path, pathext, reject)
if path: return path
return None
@@ -1894,7 +1901,7 @@ class Base(SubstitutionEnvironment):
def Action(self, *args, **kw):
def subst_string(a, self=self):
- if SCons.Util.is_String(a):
+ if is_String(a):
a = self.subst(a)
return a
nargs = list(map(subst_string, args))
@@ -1923,7 +1930,7 @@ class Base(SubstitutionEnvironment):
def Alias(self, target, source=[], action=None, **kw):
tlist = self.arg2nodes(target, self.ans.Alias)
- if not SCons.Util.is_List(source):
+ if not is_List(source):
source = [source]
source = [_f for _f in source if _f]
@@ -2071,7 +2078,7 @@ class Base(SubstitutionEnvironment):
"""
"""
s = self.subst(name)
- if SCons.Util.is_Sequence(s):
+ if is_Sequence(s):
result=[]
for e in s:
result.append(self.fs.Dir(e, *args, **kw))
@@ -2080,7 +2087,7 @@ class Base(SubstitutionEnvironment):
def PyPackageDir(self, modulename):
s = self.subst(modulename)
- if SCons.Util.is_Sequence(s):
+ if is_Sequence(s):
result=[]
for e in s:
result.append(self.fs.PyPackageDir(e))
@@ -2109,7 +2116,7 @@ class Base(SubstitutionEnvironment):
"""
"""
s = self.subst(name)
- if SCons.Util.is_Sequence(s):
+ if is_Sequence(s):
result=[]
for e in s:
result.append(self.fs.Entry(e, *args, **kw))
@@ -2137,7 +2144,7 @@ class Base(SubstitutionEnvironment):
"""
"""
s = self.subst(name)
- if SCons.Util.is_Sequence(s):
+ if is_Sequence(s):
result=[]
for e in s:
result.append(self.fs.File(e, *args, **kw))
@@ -2150,11 +2157,11 @@ class Base(SubstitutionEnvironment):
return SCons.Node.FS.find_file(file, tuple(nodes))
def Flatten(self, sequence):
- return SCons.Util.flatten(sequence)
+ return flatten(sequence)
def GetBuildPath(self, files):
result = list(map(str, self.arg2nodes(files, self.fs.Entry)))
- if SCons.Util.is_List(files):
+ if is_List(files):
return result
else:
return result[0]
@@ -2218,7 +2225,7 @@ class Base(SubstitutionEnvironment):
def Scanner(self, *args, **kw):
nargs = []
for arg in args:
- if SCons.Util.is_String(arg):
+ if is_String(arg):
arg = self.subst(arg)
nargs.append(arg)
nkw = self.subst_kw(kw)
@@ -2266,9 +2273,9 @@ class Base(SubstitutionEnvironment):
In all cases, the function returns a list of Nodes and strings."""
- if SCons.Util.is_List(arg):
+ if is_List(arg):
return list(map(self.subst, arg))
- elif SCons.Util.is_String(arg):
+ elif is_String(arg):
return self.subst(arg).split()
else:
return [self.subst(arg)]
@@ -2312,7 +2319,7 @@ class Base(SubstitutionEnvironment):
"""
from SCons.Tool import install
if install._UNIQUE_INSTALLED_FILES is None:
- install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES)
+ install._UNIQUE_INSTALLED_FILES = uniquer_hashables(install._INSTALLED_FILES)
return install._UNIQUE_INSTALLED_FILES
@@ -2356,7 +2363,7 @@ class OverrideEnvironment(Base):
# Environment they are being constructed with and so will not
# have access to overrided values. So we rebuild them with the
# OverrideEnvironment so they have access to overrided values.
- if isinstance(attr, (MethodWrapper, BuilderWrapper)):
+ if isinstance(attr, MethodWrapper):
return attr.clone(self)
else:
return attr
diff --git a/SCons/Environment.xml b/SCons/Environment.xml
index ac40f74..d594bdf 100644
--- a/SCons/Environment.xml
+++ b/SCons/Environment.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
@@ -286,31 +286,22 @@ until the Action object is actually used.
</arguments>
<summary>
<para>
-When called with the
-<function>AddMethod</function>()
-form,
-adds the specified
-<parameter>function</parameter>
-to the specified
-<parameter>object</parameter>
-as the specified method
-<parameter>name</parameter>.
-When called using the
-&f-env-AddMethod; form,
-adds the specified
-<parameter>function</parameter>
-to the construction environment
-<replaceable>env</replaceable>
-as the specified method
-<parameter>name</parameter>.
-In both cases, if
-<parameter>name</parameter>
-is omitted or
-<constant>None</constant>,
-the name of the
-specified
-<parameter>function</parameter>
-itself is used for the method name.
+Adds <parameter>function</parameter> to an object as a method.
+<parameter>function</parameter> will be called with an instance
+object as the first argument as for other methods.
+If <parameter>name</parameter> is given, it is used as
+the name of the new method, else the name of
+<parameter>function</parameter> is used.
+</para>
+<para>
+When the global function &f-AddMethod; is called,
+the object to add the method to must be passed as the first argument;
+typically this will be &Environment;,
+in order to create a method which applies to all &consenvs;
+subsequently constructed.
+When called using the &f-env-AddMethod; form,
+the method is added to the specified &consenv; only.
+Added methods propagate through &f-env-Clone; calls.
</para>
<para>
@@ -318,22 +309,17 @@ Examples:
</para>
<example_commands>
-# Note that the first argument to the function to
-# be attached as a method must be the object through
-# which the method will be called; the Python
-# convention is to call it 'self'.
+# Function to add must accept an instance argument.
+# The Python convention is to call this 'self'.
def my_method(self, arg):
print("my_method() got", arg)
-# Use the global AddMethod() function to add a method
-# to the Environment class. This
+# Use the global function to add a method to the Environment class:
AddMethod(Environment, my_method)
env = Environment()
env.my_method('arg')
-# Add the function as a method, using the function
-# name for the method call.
-env = Environment()
+# Use the optional name argument to set the name of the method:
env.AddMethod(my_method, 'other_method_name')
env.other_method_name('another arg')
</example_commands>
@@ -2754,58 +2740,76 @@ SConscript('bar/SConscript') # will chdir to bar
<scons_function name="SConsignFile">
<arguments>
-([file, dbm_module])
+([name, dbm_module])
</arguments>
<summary>
<para>
-This tells
-&scons;
-to store all file signatures
-in the specified database
-<parameter>file</parameter>.
-If the
-<parameter>file</parameter>
-name is omitted,
-<filename>.sconsign</filename>
-is used by default.
-(The actual file name(s) stored on disk
-may have an appropriated suffix appended
-by the
-<parameter>dbm_module</parameter>.)
-If
-<parameter>file</parameter>
-is not an absolute path name,
-the file is placed in the same directory as the top-level
-&SConstruct;
-file.
+Specify where to store the &SCons; file signature database,
+and which database format to use.
+This may be useful to specify alternate
+database files and/or file locations for different types of builds.
+</para>
+<para>
+The optional <parameter>name</parameter> argument
+is the base name of the database file(s).
+If not an absolute path name,
+these are placed relative to the directory containing the
+top-level &SConstruct; file.
+The default is
+<filename>.sconsign</filename>.
+The actual database file(s) stored on disk
+may have an appropriate suffix appended
+by the chosen
+<parameter>dbm_module</parameter>
+</para>
+<para>
+The optional <parameter>dbm_module</parameter>
+argument specifies which
+Python database module to use
+for reading/writing the file.
+The module must be imported first;
+then the imported module name
+is passed as the argument.
+The default is a custom
+<systemitem>SCons.dblite</systemitem>
+module that uses pickled
+Python data structures,
+which works on all Python versions.
+See documentation of the Python
+<systemitem>dbm</systemitem> module
+for other available types.
+</para>
+<para>
+If called with no arguments,
+the database will default to
+<filename>.sconsign.dblite</filename>
+in the top directory of the project,
+which is also the default if
+if &f-SConsignFile; is not called.
+</para>
+<para>
+The setting is global, so the only difference
+between the global function and the environment method form
+is variable expansion on <parameter>name</parameter>.
+There should only be one active call to this
+function/method in a given build setup.
</para>
-
<para>
If
-<parameter>file</parameter>
-is
+<parameter>name</parameter>
+is set to
<constant>None</constant>,
-then
&scons;
will store file signatures
in a separate
<filename>.sconsign</filename>
file in each directory,
-not in one global database file.
-(This was the default behavior
-prior to SCons 0.96.91 and 0.97.)
-</para>
-
-<para>
-The optional
-<parameter>dbm_module</parameter>
-argument can be used to specify
-which Python database module
-The default is to use a custom
-<filename>SCons.dblite</filename>
-module that uses pickled
-Python data structures,
-and which works on all Python versions.
+not in a single combined database file.
+This is a backwards-compatibility meaure to support
+what was the default behavior
+prior to &SCons; 0.97 (i.e. before 2008).
+Use of this mode is discouraged and may be
+deprecated in a future &SCons; release.
</para>
<para>
@@ -2814,20 +2818,25 @@ Examples:
<example_commands>
# Explicitly stores signatures in ".sconsign.dblite"
-# in the top-level SConstruct directory (the
-# default behavior).
+# in the top-level SConstruct directory (the default behavior).
SConsignFile()
# Stores signatures in the file "etc/scons-signatures"
# relative to the top-level SConstruct directory.
+# SCons will add a database suffix to this name.
SConsignFile("etc/scons-signatures")
# Stores signatures in the specified absolute file name.
+# SCons will add a database suffix to this name.
SConsignFile("/home/me/SCons/signatures")
# Stores signatures in a separate .sconsign file
# in each directory.
SConsignFile(None)
+
+# Stores signatures in a GNU dbm format .sconsign file
+import dbm.gnu
+SConsignFile(dbm_module=dbm.gnu)
</example_commands>
</summary>
</scons_function>
@@ -3171,8 +3180,8 @@ def create(target, source, env):
# A function that will write a 'prefix=$SOURCE'
# string into the file name specified as the
# $TARGET.
- f = open(str(target[0]), 'wb')
- f.write('prefix=' + source[0].get_contents())
+ with open(str(target[0]), 'wb') as f:
+ f.write('prefix=' + source[0].get_contents())
# Fetch the prefix= argument, if any, from the command
# line, and use /usr/local as the default.
@@ -3206,90 +3215,75 @@ env.UpdateValue(target = Value(output), source = Value(input))
</arguments>
<summary>
<para>
-Use the
-&f-VariantDir;
-function to create a copy of your sources in another location:
-if a name under
-<parameter>variant_dir</parameter>
-is not found but exists under
-<parameter>src_dir</parameter>,
-the file or directory is copied to
-<parameter>variant_dir</parameter>.
-Target files can be built in a different directory
-than the original sources by simply refering to the sources (and targets)
-within the variant tree.
-</para>
-
-<para>
+Sets up an alternate build location.
+When building in the <parameter>variant_dir</parameter>,
+&SCons; backfills as needed with files from <parameter>src_dir</parameter>
+to create a complete build directory.
&f-VariantDir;
can be called multiple times with the same
<parameter>src_dir</parameter>
to set up multiple builds with different options
-(<parameter>variants</parameter>).
+(<emphasis>variants</emphasis>).
+</para>
+
+<para>
The
-<parameter>src_dir</parameter>
-location must be in or underneath the SConstruct file's directory, and
-<parameter>variant_dir</parameter>
+<parameter>variant</parameter>
+location must be in or underneath the project top directory,
+and <parameter>src_dir</parameter>
may not be underneath
-<parameter>src_dir</parameter>.
-<!--
-TODO: Can the above restrictions be clarified or relaxed?
-TODO: The latter restriction is clearly not completely right;
-TODO: src_dir = '.' works fine with a build dir under it.
--->
+<parameter>variant_dir</parameter>.
</para>
<para>
-The default behavior is for
-&scons;
-to physically duplicate the source files in the variant tree.
+By default, &SCons;
+physically duplicates the source files and SConscript files
+as needed into the variant tree.
Thus, a build performed in the variant tree is guaranteed to be identical
to a build performed in the source tree even if
intermediate source files are generated during the build,
-or preprocessors or other scanners search for included files
+or if preprocessors or other scanners search for included files
relative to the source file,
-or individual compilers or other invoked tools are hard-coded
+or if individual compilers or other invoked tools are hard-coded
to put derived files in the same directory as source files.
+Only the files &SCons; calculates are needed for the build are
+duplicated into <parameter>variant_dir</parameter>.
</para>
<para>
If possible on the platform,
-the duplication is performed by linking rather than copying;
-see also the
+the duplication is performed by linking rather than copying.
+This behavior is affected by the
<option>--duplicate</option>
command-line option.
-Moreover, only the files needed for the build are duplicated;
-files and directories that are not used are not present in
-<parameter>variant_dir</parameter>.
</para>
<para>
-Duplicating the source tree may be disabled by setting the
-<literal>duplicate</literal>
+Duplicating the source files may be disabled by setting the
+<parameter>duplicate</parameter>
argument to
-<literal>0</literal>
-(zero).
+<constant>False</constant>.
This will cause
-&scons;
+&SCons;
to invoke Builders using the path names of source files in
<parameter>src_dir</parameter>
and the path names of derived files within
<parameter>variant_dir</parameter>.
-This is always more efficient than
-<literal>duplicate=1</literal>,
-and is usually safe for most builds
-(but see above for cases that may cause problems).
+This is more efficient than
+<literal>duplicate=True</literal>,
+and is safe for most builds;
+revert to <constant>True</constant>
+if it causes problems.
</para>
<para>
-Note that
&f-VariantDir;
-works most naturally with a subsidiary SConscript file.
-However, you would then call the subsidiary SConscript file
-not in the source directory, but in the
+works most naturally with used with a subsidiary SConscript file.
+The subsidiary SConscript file is called as if it
+were in
<parameter>variant_dir</parameter>,
regardless of the value of
-<literal>duplicate</literal>.
+<parameter>duplicate</parameter>.
This is how you tell
&scons;
which variant of a source tree to build:
@@ -3319,15 +3313,11 @@ Examples:
# use names in the build directory, not the source directory
VariantDir('build', 'src', duplicate=0)
Program('build/prog', 'build/source.c')
-</example_commands>
-<example_commands>
# this builds both the source and docs in a separate subtree
VariantDir('build', '.', duplicate=0)
SConscript(dirs=['build/src','build/doc'])
-</example_commands>
-<example_commands>
# same as previous example, but only uses SConscript
SConscript(dirs='src', variant_dir='build/src', duplicate=0)
SConscript(dirs='doc', variant_dir='build/doc', duplicate=0)
diff --git a/SCons/EnvironmentTests.py b/SCons/EnvironmentTests.py
index 7a26a61..53dd9a7 100644
--- a/SCons/EnvironmentTests.py
+++ b/SCons/EnvironmentTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,8 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -34,7 +33,13 @@ from collections import UserDict as UD, UserList as UL
import TestCmd
import TestUnit
-from SCons.Environment import *
+from SCons.Environment import (
+ Environment,
+ NoSubstitutionProxy,
+ OverrideEnvironment,
+ SubstitutionEnvironment,
+ is_valid_construction_var,
+)
import SCons.Warnings
def diff_env(env1, env2):
@@ -722,7 +727,7 @@ sys.exit(0)
r = env4.func2()
assert r == 'func2-4', r
- # Test that clones don't re-bind an attribute that the user
+ # Test that clones don't re-bind an attribute that the user set.
env1 = Environment(FOO = '1')
env1.AddMethod(func2)
def replace_func2():
@@ -732,6 +737,18 @@ sys.exit(0)
r = env2.func2()
assert r == 'replace_func2', r
+ # Test clone rebinding if using global AddMethod.
+ env1 = Environment(FOO='1')
+ SCons.Util.AddMethod(env1, func2)
+ r = env1.func2()
+ assert r == 'func2-1', r
+ r = env1.func2('-xxx')
+ assert r == 'func2-1-xxx', r
+ env2 = env1.Clone(FOO='2')
+ r = env2.func2()
+ assert r == 'func2-2', r
+
+
def test_Override(self):
"""Test overriding construction variables"""
env = SubstitutionEnvironment(ONE=1, TWO=2, THREE=3, FOUR=4)
@@ -787,33 +804,36 @@ sys.exit(0)
d = env.ParseFlags([])
assert d == empty, d
- s = "-I/usr/include/fum -I bar -X\n" + \
- '-I"C:\\Program Files\\ASCEND\\include" ' + \
- "-L/usr/fax -L foo -lxxx -l yyy " + \
- '-L"C:\\Program Files\\ASCEND" -lascend ' + \
- "-Wa,-as -Wl,-link " + \
- "-Wl,-rpath=rpath1 " + \
- "-Wl,-R,rpath2 " + \
- "-Wl,-Rrpath3 " + \
- "-Wp,-cpp " + \
- "-std=c99 " + \
- "-std=c++0x " + \
- "-framework Carbon " + \
- "-frameworkdir=fwd1 " + \
- "-Ffwd2 " + \
- "-F fwd3 " + \
- "-dylib_file foo-dylib " + \
- "-pthread " + \
- "-fmerge-all-constants " +\
- "-fopenmp " + \
- "-mno-cygwin -mwindows " + \
- "-arch i386 -isysroot /tmp " + \
- "-iquote /usr/include/foo1 " + \
- "-isystem /usr/include/foo2 " + \
- "-idirafter /usr/include/foo3 " + \
- "-imacros /usr/include/foo4 " + \
- "+DD64 " + \
+ s = (
+ "-I/usr/include/fum -I bar -X "
+ '-I"C:\\Program Files\\ASCEND\\include" '
+ "-L/usr/fax -L foo -lxxx -l yyy "
+ '-L"C:\\Program Files\\ASCEND" -lascend '
+ "-Wa,-as -Wl,-link "
+ "-Wl,-rpath=rpath1 "
+ "-Wl,-R,rpath2 "
+ "-Wl,-Rrpath3 "
+ "-Wp,-cpp "
+ "-std=c99 "
+ "-std=c++0x "
+ "-framework Carbon "
+ "-frameworkdir=fwd1 "
+ "-Ffwd2 "
+ "-F fwd3 "
+ "-dylib_file foo-dylib "
+ "-pthread "
+ "-fmerge-all-constants "
+ "-fopenmp "
+ "-mno-cygwin -mwindows "
+ "-arch i386 -isysroot /tmp "
+ "-iquote /usr/include/foo1 "
+ "-isystem /usr/include/foo2 "
+ "-idirafter /usr/include/foo3 "
+ "-imacros /usr/include/foo4 "
+ "--param l1-cache-size=32 --param l2-cache-size=6144 "
+ "+DD64 "
"-DFOO -DBAR=value -D BAZ "
+ )
d = env.ParseFlags(s)
@@ -827,6 +847,7 @@ sys.exit(0)
('-isystem', '/usr/include/foo2'),
('-idirafter', '/usr/include/foo3'),
('-imacros', env.fs.File('/usr/include/foo4')),
+ ('--param', 'l1-cache-size=32'), ('--param', 'l2-cache-size=6144'),
'+DD64'], repr(d['CCFLAGS'])
assert d['CXXFLAGS'] == ['-std=c++0x'], repr(d['CXXFLAGS'])
assert d['CPPDEFINES'] == ['FOO', ['BAR', 'value'], 'BAZ'], d['CPPDEFINES']
@@ -852,24 +873,40 @@ sys.exit(0)
def test_MergeFlags(self):
- """Test the MergeFlags() method
- """
+ """Test the MergeFlags() method."""
+
env = SubstitutionEnvironment()
+ # does not set flag if value empty
env.MergeFlags('')
assert 'CCFLAGS' not in env, env['CCFLAGS']
+ # merges value if flag did not exist
env.MergeFlags('-X')
assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
+
+ # avoid SubstitutionEnvironment for these, has no .Append method,
+ # which is needed for unique=False test
+ env = Environment(CCFLAGS=None)
+ # merge with existing but empty flag
env.MergeFlags('-X')
assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
+ # default Unique=True enforces no dupes
+ env.MergeFlags('-X')
+ assert env['CCFLAGS'] == ['-X'], env['CCFLAGS']
+ # Unique=False allows dupes
+ env.MergeFlags('-X', unique=False)
+ assert env['CCFLAGS'] == ['-X', '-X'], env['CCFLAGS']
- env = SubstitutionEnvironment(CCFLAGS=None)
- env.MergeFlags('-Y')
- assert env['CCFLAGS'] == ['-Y'], env['CCFLAGS']
+ # merge from a dict with list values
+ env = SubstitutionEnvironment(B='b')
+ env.MergeFlags({'A': ['aaa'], 'B': ['bb', 'bbb']})
+ assert env['A'] == ['aaa'], env['A']
+ assert env['B'] == ['b', 'bb', 'bbb'], env['B']
- env = SubstitutionEnvironment()
- env.MergeFlags({'A':['aaa'], 'B':['bbb']})
+ # issue #2961: merge from a dict with string values
+ env = SubstitutionEnvironment(B='b')
+ env.MergeFlags({'A': 'aaa', 'B': 'bb bbb'})
assert env['A'] == ['aaa'], env['A']
- assert env['B'] == ['bbb'], env['B']
+ assert env['B'] == ['b', 'bb', 'bbb'], env['B']
# issue #3665: if merging dict which is a compound object
# (i.e. value can be lists, etc.), the value object should not
@@ -881,6 +918,7 @@ sys.exit(0)
pass
flags = {'CFLAGS': ['-pipe', '-pthread', '-g']}
import copy
+
saveflags = copy.deepcopy(flags)
env.MergeFlags(flags)
self.assertEqual(flags, saveflags)
@@ -2456,16 +2494,16 @@ f5: \
exc_caught = None
try:
env.Tool('does_not_exist')
- except SCons.Errors.SConsEnvironmentError:
+ except SCons.Errors.UserError:
exc_caught = 1
- assert exc_caught, "did not catch expected SConsEnvironmentError"
+ assert exc_caught, "did not catch expected UserError"
exc_caught = None
try:
env.Tool('$NONE')
- except SCons.Errors.SConsEnvironmentError:
+ except SCons.Errors.UserError:
exc_caught = 1
- assert exc_caught, "did not catch expected SConsEnvironmentError"
+ assert exc_caught, "did not catch expected UserError"
# Use a non-existent toolpath directory just to make sure we
# can call Tool() with the keyword argument.
diff --git a/SCons/EnvironmentValues.py b/SCons/EnvironmentValues.py
index aaa71d0..c5eb972 100644
--- a/SCons/EnvironmentValues.py
+++ b/SCons/EnvironmentValues.py
@@ -1,3 +1,26 @@
+# MIT License
+#
+# Copyright 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.
+
import re
_is_valid_var = re.compile(r'[_a-zA-Z]\w*$')
@@ -72,7 +95,6 @@ class EnvironmentValue:
# Now we need to parse the specified string
result = _dollar_exps.sub(sub_match, args)
print(result)
- pass
except TypeError:
# likely callable? either way we don't parse
self._parsed = self.value
diff --git a/SCons/EnvironmentValuesTest.py b/SCons/EnvironmentValuesTest.py
index 58ee9cf..074aa85 100644
--- a/SCons/EnvironmentValuesTest.py
+++ b/SCons/EnvironmentValuesTest.py
@@ -1,3 +1,26 @@
+# MIT License
+#
+# Copyright 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.
+
import unittest
from SCons.EnvironmentValues import EnvironmentValues
diff --git a/SCons/Errors.py b/SCons/Errors.py
index 887afcf..42db072 100644
--- a/SCons/Errors.py
+++ b/SCons/Errors.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,17 +20,13 @@
# 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.
-#
-"""SCons.Errors
+"""SCons exception classes.
-This file contains the exception classes used to handle internal
-and user errors in SCons.
+Used to handle internal and user errors in SCons.
"""
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
import shutil
import SCons.Util
diff --git a/SCons/ErrorsTests.py b/SCons/ErrorsTests.py
index d777ba1..cc63d9b 100644
--- a/SCons/ErrorsTests.py
+++ b/SCons/ErrorsTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,13 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import errno
-import os
-import sys
import unittest
import SCons.Errors
diff --git a/SCons/Executor.py b/SCons/Executor.py
index f658229..005906f 100644
--- a/SCons/Executor.py
+++ b/SCons/Executor.py
@@ -1,12 +1,6 @@
-"""SCons.Executor
-
-A module for executing actions with specific lists of target and source
-Nodes.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -26,7 +20,8 @@ Nodes.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""Execute actions with specific lists of target and source Nodes."""
import collections
diff --git a/SCons/ExecutorTests.py b/SCons/ExecutorTests.py
index 41728ef..c43c450 100644
--- a/SCons/ExecutorTests.py
+++ b/SCons/ExecutorTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,7 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import unittest
import SCons.Executor
diff --git a/SCons/Job.py b/SCons/Job.py
index 4e2f68c..f87a3bb 100644
--- a/SCons/Job.py
+++ b/SCons/Job.py
@@ -1,13 +1,6 @@
-"""SCons.Job
-
-This module defines the Serial and Parallel classes that execute tasks to
-complete a build. The Jobs class provides a higher level interface to start,
-stop, and wait on jobs.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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 +20,12 @@ stop, and wait on jobs.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Serial and Parallel classes to execute build tasks.
+
+The Jobs class provides a higher level interface to start,
+stop, and wait on jobs.
+"""
import SCons.compat
diff --git a/SCons/JobTests.py b/SCons/JobTests.py
index 7fc969b..5b5a590 100644
--- a/SCons/JobTests.py
+++ b/SCons/JobTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,8 +21,6 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
import unittest
import random
import math
@@ -211,7 +210,7 @@ class Taskmaster:
try:
import threading
self.guard = threading.Lock()
- except:
+ except ImportError:
self.guard = DummyLock()
# keep track of the order tasks are begun in
@@ -255,7 +254,7 @@ class ParallelTestCase(unittest.TestCase):
try:
import threading
- except:
+ except ImportError:
raise NoThreadsException()
taskmaster = Taskmaster(num_tasks, self, RandomTask)
diff --git a/SCons/Memoize.py b/SCons/Memoize.py
index 9d6bc51..8c3303f 100644
--- a/SCons/Memoize.py
+++ b/SCons/Memoize.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,10 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-__doc__ = """Memoizer
+"""Decorator-based memoizer to count caching stats.
A decorator-based implementation to count hits and misses of the computed
values that various methods cache in memory.
diff --git a/SCons/MemoizeTests.py b/SCons/MemoizeTests.py
index f1e5550..7830d99 100644
--- a/SCons/MemoizeTests.py
+++ b/SCons/MemoizeTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,7 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import unittest
import SCons.Memoize
diff --git a/SCons/Node/Alias.py b/SCons/Node/Alias.py
index 55d94f9..64054d2 100644
--- a/SCons/Node/Alias.py
+++ b/SCons/Node/Alias.py
@@ -1,14 +1,6 @@
-
-"""scons.Node.Alias
-
-Alias nodes.
-
-This creates a hash of global Aliases (dummy targets).
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,11 @@ This creates a hash of global Aliases (dummy targets).
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Alias nodes.
+
+This creates a hash of global Aliases (dummy targets).
+"""
import collections
diff --git a/SCons/Node/AliasTests.py b/SCons/Node/AliasTests.py
index 613a5c0..14662fd 100644
--- a/SCons/Node/AliasTests.py
+++ b/SCons/Node/AliasTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,7 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import unittest
import SCons.Errors
diff --git a/SCons/Node/FS.py b/SCons/Node/FS.py
index ad9dd6f..290fcb3 100644
--- a/SCons/Node/FS.py
+++ b/SCons/Node/FS.py
@@ -1,17 +1,6 @@
-"""scons.Node.FS
-
-File system nodes.
-
-These Nodes represent the canonical external objects that people think
-of when they think of building software: files and directories.
-
-This holds a "default_fs" variable that should be initialized with an FS
-that can be used by scripts or modules looking for the canonical default.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -31,7 +20,15 @@ that can be used by scripts or modules looking for the canonical default.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""File system nodes.
+
+These Nodes represent the canonical external objects that people think
+of when they think of building software: files and directories.
+
+This holds a "default_fs" variable that should be initialized with an FS
+that can be used by scripts or modules looking for the canonical default.
+"""
import fnmatch
import os
@@ -46,7 +43,7 @@ import importlib.util
import SCons.Action
import SCons.Debug
-from SCons.Debug import logInstanceCreation
+from SCons.Debug import logInstanceCreation, Trace
import SCons.Errors
import SCons.Memoize
import SCons.Node
@@ -56,8 +53,6 @@ import SCons.Util
from SCons.Util import MD5signature, MD5filesignature, MD5collect
import SCons.Warnings
-from SCons.Debug import Trace
-
print_duplicate = 0
MD5_TIMESTAMP_DEBUG = False
@@ -439,7 +434,7 @@ class EntryProxy(SCons.Util.Proxy):
# In PY3 if a class defines __eq__, then it must explicitly provide
# __hash__. Since SCons.Util.Proxy provides __eq__ we need the following
- # see: https://docs.python.org/3.1/reference/datamodel.html#object.__hash__
+ # see: https://docs.python.org/3/reference/datamodel.html#object.__hash__
__hash__ = SCons.Util.Delegate('__hash__')
def __get_abspath(self):
@@ -2698,11 +2693,13 @@ class File(Base):
def scanner_key(self):
return self.get_suffix()
- def get_contents(self):
+ def get_contents(self) -> bytes:
+ """Return the contents of the file as bytes."""
return SCons.Node._get_contents_map[self._func_get_contents](self)
- def get_text_contents(self):
- """
+ def get_text_contents(self) -> str:
+ """Return the contents of the file in text form.
+
This attempts to figure out what the encoding of the text is
based upon the BOM bytes, and then decodes the contents so that
it's a valid python string.
@@ -2726,15 +2723,13 @@ class File(Base):
try:
return contents.decode('latin-1')
except UnicodeDecodeError as e:
- return contents.decode('utf-8', error='backslashreplace')
+ return contents.decode('utf-8', errors='backslashreplace')
- def get_content_hash(self):
- """
- Compute and return the MD5 hash for this file.
- """
+ def get_content_hash(self) -> str:
+ """Compute and return the hash of the file contents."""
if not self.rexists():
- return MD5signature('')
+ return MD5signature(SCons.Util.NOFILE)
fname = self.rfile().get_abspath()
try:
cs = MD5filesignature(fname, chunksize=File.md5_chunksize)
@@ -2745,7 +2740,7 @@ class File(Base):
return cs
@SCons.Memoize.CountMethodCall
- def get_size(self):
+ def get_size(self) -> int:
try:
return self._memo['get_size']
except KeyError:
@@ -2754,14 +2749,14 @@ class File(Base):
if self.rexists():
size = self.rfile().getsize()
else:
- size = 0
+ # sentinel value for doesn't exist, even in repository
+ size = -1
self._memo['get_size'] = size
-
return size
@SCons.Memoize.CountMethodCall
- def get_timestamp(self):
+ def get_timestamp(self) -> int:
try:
return self._memo['get_timestamp']
except KeyError:
@@ -2773,7 +2768,6 @@ class File(Base):
timestamp = 0
self._memo['get_timestamp'] = timestamp
-
return timestamp
convert_copy_attrs = [
@@ -2785,7 +2779,6 @@ class File(Base):
'ninfo',
]
-
convert_sig_attrs = [
'bsourcesigs',
'bimplicitsigs',
@@ -3178,7 +3171,7 @@ class File(Base):
# SIGNATURE SUBSYSTEM
#
- def get_max_drift_csig(self):
+ def get_max_drift_csig(self) -> str:
"""
Returns the content signature currently stored for this node
if it's been unmodified longer than the max_drift value, or the
@@ -3204,15 +3197,8 @@ class File(Base):
return None
- def get_csig(self):
- """
- Generate a node's content signature, the digested signature
- of its content.
-
- node - the node
- cache - alternate node to use for the signature cache
- returns - the content signature
- """
+ def get_csig(self) -> str:
+ """Generate a node's content signature."""
ninfo = self.get_ninfo()
try:
return ninfo.csig
@@ -3221,9 +3207,11 @@ class File(Base):
csig = self.get_max_drift_csig()
if csig is None:
-
try:
- if self.get_size() < File.md5_chunksize:
+ size = self.get_size()
+ if size == -1:
+ contents = SCons.Util.NOFILE
+ elif size < File.md5_chunksize:
contents = self.get_contents()
else:
csig = self.get_content_hash()
diff --git a/SCons/Node/FSTests.py b/SCons/Node/FSTests.py
index 77c6dbb..1f886d7 100644
--- a/SCons/Node/FSTests.py
+++ b/SCons/Node/FSTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
-
import os
import os.path
import sys
@@ -1694,7 +1692,6 @@ class FSTestCase(_tempdirTestCase):
except AttributeError:
# could be python 3.7 or newer, make sure splitdrive can do UNC
assert ntpath.splitdrive(r'\\split\drive\test')[0] == r'\\split\drive'
- pass
path = strip_slash(path)
return '//' + path[1:]
@@ -2689,8 +2686,11 @@ class FileTestCase(_tempdirTestCase):
print("%15s -> csig:%s" % (i3.name, i3.ninfo.csig))
print("%15s -> csig:%s" % (i4.name, i4.ninfo.csig))
- self.assertEqual(i2.name, i2.ninfo.csig,
- "gamma.h's fake csig should equal gamma.h but equals:%s" % i2.ninfo.csig)
+ self.assertEqual(
+ i2.name,
+ i2.ninfo.csig,
+ "gamma.h's fake csig should equal gamma.h but equals:%s" % i2.ninfo.csig,
+ )
class GlobTestCase(_tempdirTestCase):
@@ -3676,7 +3676,8 @@ class CacheDirTestCase(unittest.TestCase):
f9 = fs.File('f9')
r = f9.get_cachedir_csig()
- assert r == 'd41d8cd98f00b204e9800998ecf8427e', r
+ exsig = SCons.Util.MD5signature(SCons.Util.NOFILE)
+ assert r == exsig, r
class clearTestCase(unittest.TestCase):
@@ -3725,6 +3726,13 @@ class clearTestCase(unittest.TestCase):
assert not f.exists()
assert not f.rexists()
assert str(f) == test.workpath('f'), str(f)
+ # Now verify clear() resets optional File-specific attributes
+ optional_attrs = ['cachedir_csig', 'cachesig', 'contentsig']
+ for attr in optional_attrs:
+ setattr(f, attr, 'xyz')
+ f.clear()
+ for attr in optional_attrs:
+ assert not hasattr(f, attr), attr
class disambiguateTestCase(unittest.TestCase):
diff --git a/SCons/Node/NodeTests.py b/SCons/Node/NodeTests.py
index 729be01..29a3887 100644
--- a/SCons/Node/NodeTests.py
+++ b/SCons/Node/NodeTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,14 +21,10 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
import SCons.compat
import collections
-import os
import re
-import sys
import unittest
import SCons.Errors
@@ -1300,6 +1297,7 @@ class NodeTestCase(unittest.TestCase):
n.includes = 'testincludes'
n.Tag('found_includes', {'testkey':'testvalue'})
n.implicit = 'testimplicit'
+ n.cached = 1
x = MyExecutor()
n.set_executor(x)
@@ -1307,6 +1305,7 @@ class NodeTestCase(unittest.TestCase):
n.clear()
assert n.includes is None, n.includes
+ assert n.cached == 0, n.cached
assert x.cleaned_up
def test_get_subst_proxy(self):
diff --git a/SCons/Node/Python.py b/SCons/Node/Python.py
index 68c6ee8..738682c 100644
--- a/SCons/Node/Python.py
+++ b/SCons/Node/Python.py
@@ -1,11 +1,6 @@
-"""scons.Node.Python
-
-Python nodes.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,9 +20,8 @@ Python nodes.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Python nodes."""
import SCons.Node
@@ -135,7 +129,7 @@ class Value(SCons.Node.Node):
self.built_value = self.value
return self.built_value
- def get_text_contents(self):
+ def get_text_contents(self) -> str:
"""By the assumption that the node.built_value is a
deterministic product of the sources, the contents of a Value
are the concatenation of all the contents of its sources. As
@@ -144,27 +138,20 @@ class Value(SCons.Node.Node):
###TODO: something reasonable about universal newlines
contents = str(self.value)
for kid in self.children(None):
- contents = contents + kid.get_contents().decode()
+ # Get csig() value of child as this is more efficent
+ contents = contents + kid.get_csig()
return contents
- def get_contents(self):
- """
- Get contents for signature calculations.
- :return: bytes
- """
- text_contents = self.get_text_contents()
- try:
- return text_contents.encode()
- except UnicodeDecodeError:
- # Already encoded as python2 str are bytes
- return text_contents
+ def get_contents(self) -> bytes:
+ """Get contents for signature calculations."""
+ return self.get_text_contents().encode()
def changed_since_last_build(self, target, prev_ni):
cur_csig = self.get_csig()
try:
return cur_csig != prev_ni.csig
except AttributeError:
- return 1
+ return True
def get_csig(self, calc=None):
"""Because we're a Python value node and don't have a real
diff --git a/SCons/Node/PythonTests.py b/SCons/Node/PythonTests.py
index b6fa859..b6a3f79 100644
--- a/SCons/Node/PythonTests.py
+++ b/SCons/Node/PythonTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import unittest
diff --git a/SCons/Node/__init__.py b/SCons/Node/__init__.py
index f7d9289..3685af3 100644
--- a/SCons/Node/__init__.py
+++ b/SCons/Node/__init__.py
@@ -1,26 +1,6 @@
-"""SCons.Node
-
-The Node package for the SCons software construction utility.
-
-This is, in many ways, the heart of SCons.
-
-A Node is where we encapsulate all of the dependency information about
-any thing that SCons can build, or about any thing which SCons can use
-to build some other thing. The canonical "thing," of course, is a file,
-but a Node can also represent something remote (like a web page) or
-something completely abstract (like an Alias).
-
-Each specific type of "thing" is specifically represented by a subclass
-of the Node base class: Node.FS.File for files, Node.Alias for aliases,
-etc. Dependency information is kept here in the base class, and
-information specific to files/aliases/etc. is in the subclass. The
-goal, if we've done this correctly, is that any type of "thing" should
-be able to depend on any other type of "thing."
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -41,28 +21,36 @@ be able to depend on any other type of "thing."
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""The Node package for the SCons software construction utility.
+
+This is, in many ways, the heart of SCons.
+
+A Node is where we encapsulate all of the dependency information about
+any thing that SCons can build, or about any thing which SCons can use
+to build some other thing. The canonical "thing," of course, is a file,
+but a Node can also represent something remote (like a web page) or
+something completely abstract (like an Alias).
+
+Each specific type of "thing" is specifically represented by a subclass
+of the Node base class: Node.FS.File for files, Node.Alias for aliases,
+etc. Dependency information is kept here in the base class, and
+information specific to files/aliases/etc. is in the subclass. The
+goal, if we've done this correctly, is that any type of "thing" should
+be able to depend on any other type of "thing."
+
+"""
-import os
import collections
import copy
-from itertools import chain
-
-try:
- from itertools import zip_longest
-except ImportError:
- from itertools import izip_longest as zip_longest
+from itertools import chain, zip_longest
import SCons.Debug
-from SCons.Debug import logInstanceCreation
import SCons.Executor
import SCons.Memoize
import SCons.Util
-from SCons.Util import MD5signature
-
-from SCons.Debug import Trace
-
from SCons.compat import NoSlotsPyPy
+from SCons.Debug import logInstanceCreation, Trace
+from SCons.Util import MD5signature
print_duplicate = 0
@@ -823,25 +811,21 @@ class Node(object, metaclass=NoSlotsPyPy):
def release_target_info(self):
"""Called just after this node has been marked
- up-to-date or was built completely.
+ up-to-date or was built completely.
- This is where we try to release as many target node infos
- as possible for clean builds and update runs, in order
- to minimize the overall memory consumption.
+ This is where we try to release as many target node infos
+ as possible for clean builds and update runs, in order
+ to minimize the overall memory consumption.
- By purging attributes that aren't needed any longer after
- a Node (=File) got built, we don't have to care that much how
- many KBytes a Node actually requires...as long as we free
- the memory shortly afterwards.
+ By purging attributes that aren't needed any longer after
+ a Node (=File) got built, we don't have to care that much how
+ many KBytes a Node actually requires...as long as we free
+ the memory shortly afterwards.
- @see: built() and File.release_target_info()
- """
+ @see: built() and File.release_target_info()
+ """
pass
- #
- #
- #
-
def add_to_waiting_s_e(self, node):
self.waiting_s_e.add(node)
@@ -877,10 +861,12 @@ class Node(object, metaclass=NoSlotsPyPy):
self.clear_memoized_values()
self.ninfo = self.new_ninfo()
self.executor_cleanup()
- try:
- delattr(self, '_calculated_sig')
- except AttributeError:
- pass
+ for attr in ['cachedir_csig', 'cachesig', 'contentsig']:
+ try:
+ delattr(self, attr)
+ except AttributeError:
+ pass
+ self.cached = 0
self.includes = None
def clear_memoized_values(self):
diff --git a/SCons/PathList.py b/SCons/PathList.py
index 768198b..a7e666d 100644
--- a/SCons/PathList.py
+++ b/SCons/PathList.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,17 +20,13 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-__doc__ = """SCons.PathList
-A module for handling lists of directory paths (the sort of things
-that get set as CPPPATH, LIBPATH, etc.) with as much caching of data and
-efficiency as we can, while still keeping the evaluation delayed so that we
-Do the Right Thing (almost) regardless of how the variable is specified.
+"""Handle lists of directory paths.
+These are the path lists that get set as CPPPATH, LIBPATH,
+etc.) with as much caching of data and efficiency as we can, while
+still keeping the evaluation delayed so that we Do the Right Thing
+(almost) regardless of how the variable is specified.
"""
import os
diff --git a/SCons/PathListTests.py b/SCons/PathListTests.py
index 80f2b9c..ea7cecd 100644
--- a/SCons/PathListTests.py
+++ b/SCons/PathListTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,7 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import unittest
import TestUnit
diff --git a/SCons/Platform/Platform.xml b/SCons/Platform/Platform.xml
index 6582590..b150906 100644
--- a/SCons/Platform/Platform.xml
+++ b/SCons/Platform/Platform.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
diff --git a/SCons/Platform/PlatformTests.py b/SCons/Platform/PlatformTests.py
index e065c3c..1a72eb7 100644
--- a/SCons/Platform/PlatformTests.py
+++ b/SCons/Platform/PlatformTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,16 +20,12 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import SCons.compat
import collections
import unittest
import os
+import SCons.compat
import SCons.Errors
import SCons.Platform
import SCons.Environment
@@ -107,14 +104,13 @@ class PlatformTestCase(unittest.TestCase):
p(env)
assert env['PROGSUFFIX'] == '.exe', env
assert env['LIBSUFFIX'] == '.lib', env
- assert str
+ exc_caught = None
try:
p = SCons.Platform.Platform('_does_not_exist_')
except SCons.Errors.UserError:
- pass
- else: # TODO pylint E0704: bare raise not inside except
- raise
+ exc_caught = 1
+ assert exc_caught, "did not catch expected UserError"
env = Environment()
SCons.Platform.Platform()(env)
@@ -193,14 +189,15 @@ class TempFileMungeTestCase(unittest.TestCase):
SCons.Action.print_actions = old_actions
assert file_content != env['TEMPFILEARGJOINBYTE'].join(['test','command','line'])
-
def test_tempfilecreation_once(self):
- # Init class with cmd, such that the fully expanded
- # string reads "a test command line".
- # Note, how we're using a command string here that is
- # actually longer than the substituted one. This is to ensure
- # that the TempFileMunge class internally really takes the
- # length of the expanded string into account.
+ """
+ Init class with cmd, such that the fully expanded
+ string reads "a test command line".
+ Note, how we're using a command string here that is
+ actually longer than the substituted one. This is to ensure
+ that the TempFileMunge class internally really takes the
+ length of the expanded string into account.
+ """
defined_cmd = "a $VERY $OVERSIMPLIFIED line"
t = SCons.Platform.TempFileMunge(defined_cmd)
env = SCons.Environment.SubstitutionEnvironment(tools=[])
@@ -220,12 +217,14 @@ class TempFileMungeTestCase(unittest.TestCase):
def __init__(self):
self.attributes = self.Attrs()
+
target = [Node()]
cmd = t(target, None, env, 0)
# ...and restoring its setting.
SCons.Action.print_actions = old_actions
assert cmd != defined_cmd, cmd
- assert cmd == getattr(target[0].attributes, 'tempfile_cmdlist', None)
+ assert cmd == target[0].attributes.tempfile_cmdlist[defined_cmd]
+
class PlatformEscapeTestCase(unittest.TestCase):
diff --git a/SCons/Platform/__init__.py b/SCons/Platform/__init__.py
index 5d3541b..745db09 100644
--- a/SCons/Platform/__init__.py
+++ b/SCons/Platform/__init__.py
@@ -1,26 +1,6 @@
-"""SCons.Platform
-
-SCons platform selection.
-
-This looks for modules that define a callable object that can modify a
-construction environment as appropriate for a given platform.
-
-Note that we take a more simplistic view of "platform" than Python does.
-We're looking for a single string that determines a set of
-tool-independent variables with which to initialize a construction
-environment. Consequently, we'll examine both sys.platform and os.name
-(and anything else that might come in to play) in order to return some
-specification which is unique enough for our purposes.
-
-Note that because this subsystem just *selects* a callable that can
-modify a construction environment, it's possible for people to define
-their own "platform specification" in an arbitrary callable function.
-No one needs to use or tie in to this subsystem in order to roll
-their own platform definition.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -40,8 +20,25 @@ their own platform definition.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""SCons platform selection.
+
+Looks for modules that define a callable object that can modify a
+construction environment as appropriate for a given platform.
+
+Note that we take a more simplistic view of "platform" than Python does.
+We're looking for a single string that determines a set of
+tool-independent variables with which to initialize a construction
+environment. Consequently, we'll examine both sys.platform and os.name
+(and anything else that might come in to play) in order to return some
+specification which is unique enough for our purposes.
+
+Note that because this subsystem just *selects* a callable that can
+modify a construction environment, it's possible for people to define
+their own "platform specification" in an arbitrary callable function.
+No one needs to use or tie in to this subsystem in order to roll
+their own platform definition.
+"""
import SCons.compat
@@ -191,9 +188,20 @@ class TempFileMunge:
# Check if we already created the temporary file for this target
# It should have been previously done by Action.strfunction() call
- node = target[0] if SCons.Util.is_List(target) else target
- cmdlist = getattr(node.attributes, 'tempfile_cmdlist', None) \
- if node is not None else None
+ if SCons.Util.is_List(target):
+ node = target[0]
+ else:
+ node = target
+
+ cmdlist = None
+
+ if SCons.Util.is_List(self.cmd):
+ cmdlist_key = tuple(self.cmd)
+ else:
+ cmdlist_key = self.cmd
+
+ if node and hasattr(node.attributes, 'tempfile_cmdlist'):
+ cmdlist = node.attributes.tempfile_cmdlist.get(cmdlist_key, None)
if cmdlist is not None:
return cmdlist
@@ -260,14 +268,18 @@ class TempFileMunge:
str(cmd[0]) + " " + " ".join(args))
self._print_cmd_str(target, source, env, cmdstr)
+ cmdlist = [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ]
+
# Store the temporary file command list into the target Node.attributes
# to avoid creating two temporary files one for print and one for execute.
- cmdlist = [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ]
if node is not None:
- try :
- setattr(node.attributes, 'tempfile_cmdlist', cmdlist)
+ try:
+ # Storing in tempfile_cmdlist by self.cmd provided when intializing
+ # $TEMPFILE{} fixes issue raised in PR #3140 and #3553
+ node.attributes.tempfile_cmdlist[cmdlist_key] = cmdlist
except AttributeError:
- pass
+ node.attributes.tempfile_cmdlist = {cmdlist_key:cmdlist}
+
return cmdlist
def _print_cmd_str(self, target, source, env, cmdstr):
diff --git a/SCons/Platform/aix.py b/SCons/Platform/aix.py
index e5b4d03..db1ccdb 100644
--- a/SCons/Platform/aix.py
+++ b/SCons/Platform/aix.py
@@ -1,14 +1,6 @@
-"""SCons.Platform.aix
-
-Platform-specific initialization for IBM AIX systems.
-
-There normally shouldn't be any need to import this module directly. It
-will usually be imported through the generic SCons.Platform.Platform()
-selection method.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,11 +20,14 @@ selection method.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for IBM AIX systems.
+
+There normally shouldn't be any need to import this module directly. It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
-import os
import subprocess
from . import posix
@@ -70,8 +65,6 @@ def get_xlc(env, xlc=None, packages=[]):
or ('/' not in xlc and filename.endswith('/' + xlc)):
xlcVersion = fileset.split()[1]
xlcPath, sep, xlc = filename.rpartition('/')
- pass
- pass
return (xlcPath, xlc, xlcVersion)
def generate(env):
diff --git a/SCons/Platform/cygwin.py b/SCons/Platform/cygwin.py
index f6c5086..ce01007 100644
--- a/SCons/Platform/cygwin.py
+++ b/SCons/Platform/cygwin.py
@@ -1,14 +1,6 @@
-"""SCons.Platform.cygwin
-
-Platform-specific initialization for Cygwin systems.
-
-There normally shouldn't be any need to import this module directly. It
-will usually be imported through the generic SCons.Platform.Platform()
-selection method.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,13 @@ selection method.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for Cygwin systems.
+
+There normally shouldn't be any need to import this module directly. It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
import sys
diff --git a/SCons/Platform/darwin.py b/SCons/Platform/darwin.py
index 590e79a..68cb7df 100644
--- a/SCons/Platform/darwin.py
+++ b/SCons/Platform/darwin.py
@@ -1,14 +1,6 @@
-"""SCons.Platform.darwin
-
-Platform-specific initialization for Mac OS X systems.
-
-There normally shouldn't be any need to import this module directly. It
-will usually be imported through the generic SCons.Platform.Platform()
-selection method.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,13 @@ selection method.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for Mac OS X systems.
+
+There normally shouldn't be any need to import this module directly. It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
from . import posix
import os
diff --git a/SCons/Platform/hpux.py b/SCons/Platform/hpux.py
index 2f455c0..53c7b67 100644
--- a/SCons/Platform/hpux.py
+++ b/SCons/Platform/hpux.py
@@ -1,14 +1,6 @@
-"""SCons.Platform.hpux
-
-Platform-specific initialization for HP-UX systems.
-
-There normally shouldn't be any need to import this module directly. It
-will usually be imported through the generic SCons.Platform.Platform()
-selection method.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,13 @@ selection method.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for HP-UX systems.
+
+There normally shouldn't be any need to import this module directly. It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
from . import posix
diff --git a/SCons/Platform/irix.py b/SCons/Platform/irix.py
index 2e5f217..70f3708 100644
--- a/SCons/Platform/irix.py
+++ b/SCons/Platform/irix.py
@@ -1,14 +1,6 @@
-"""SCons.Platform.irix
-
-Platform-specific initialization for SGI IRIX systems.
-
-There normally shouldn't be any need to import this module directly. It
-will usually be imported through the generic SCons.Platform.Platform()
-selection method.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,13 @@ selection method.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for SGI IRIX systems.
+
+There normally shouldn't be any need to import this module directly. It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
from . import posix
diff --git a/SCons/Platform/mingw.py b/SCons/Platform/mingw.py
index 73633d7..1d38a9b 100644
--- a/SCons/Platform/mingw.py
+++ b/SCons/Platform/mingw.py
@@ -1,11 +1,6 @@
-"""SCons.Platform.mingw
-
-Platform-specific initialization for the MinGW system.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,9 +20,8 @@ Platform-specific initialization for the MinGW system.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for the MinGW system."""
import sys
@@ -36,4 +30,4 @@ if sys.platform == 'win32':
MINGW_DEFAULT_PATHS = [
r'C:\msys64',
r'C:\msys'
- ] \ No newline at end of file
+ ]
diff --git a/SCons/Platform/os2.py b/SCons/Platform/os2.py
index 5ca26bc..6b412ee 100644
--- a/SCons/Platform/os2.py
+++ b/SCons/Platform/os2.py
@@ -1,14 +1,6 @@
-"""SCons.Platform.os2
-
-Platform-specific initialization for OS/2 systems.
-
-There normally shouldn't be any need to import this module directly. It
-will usually be imported through the generic SCons.Platform.Platform()
-selection method.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,14 @@ selection method.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for OS/2 systems.
+
+There normally shouldn't be any need to import this module directly. It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
+
from . import win32
def generate(env):
diff --git a/SCons/Platform/posix.py b/SCons/Platform/posix.py
index ad4e859..4a5db10 100644
--- a/SCons/Platform/posix.py
+++ b/SCons/Platform/posix.py
@@ -1,14 +1,6 @@
-"""SCons.Platform.posix
-
-Platform-specific initialization for POSIX (Linux, UNIX, etc.) systems.
-
-There normally shouldn't be any need to import this module directly. It
-will usually be imported through the generic SCons.Platform.Platform()
-selection method.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,15 +20,16 @@ selection method.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for POSIX (Linux, UNIX, etc.) systems.
+
+There normally shouldn't be any need to import this module directly. It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
import errno
-import os
-import os.path
import subprocess
-import sys
import select
import SCons.Util
diff --git a/SCons/Platform/posix.xml b/SCons/Platform/posix.xml
index b58af83..e90e159 100644
--- a/SCons/Platform/posix.xml
+++ b/SCons/Platform/posix.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
diff --git a/SCons/Platform/sunos.py b/SCons/Platform/sunos.py
index 40e698e..d33af1e 100644
--- a/SCons/Platform/sunos.py
+++ b/SCons/Platform/sunos.py
@@ -1,14 +1,6 @@
-"""SCons.Platform.sunos
-
-Platform-specific initialization for Sun systems.
-
-There normally shouldn't be any need to import this module directly. It
-will usually be imported through the generic SCons.Platform.Platform()
-selection method.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,13 @@ selection method.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for Sun systems.
+
+There normally shouldn't be any need to import this module directly. It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
from . import posix
diff --git a/SCons/Platform/sunos.xml b/SCons/Platform/sunos.xml
index a518301..ffeae96 100644
--- a/SCons/Platform/sunos.xml
+++ b/SCons/Platform/sunos.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
diff --git a/SCons/Platform/virtualenv.py b/SCons/Platform/virtualenv.py
index 4708cb2..2204a59 100644
--- a/SCons/Platform/virtualenv.py
+++ b/SCons/Platform/virtualenv.py
@@ -1,10 +1,6 @@
-"""SCons.Platform.virtualenv
-
-Support for virtualenv.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,8 @@ Support for virtualenv.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""'Platform" support for a Python virtualenv."""
import os
import sys
@@ -50,14 +45,14 @@ virtualenv_variables = ['VIRTUAL_ENV', 'PIPENV_ACTIVE']
def _running_in_virtualenv():
- """Returns True, if scons is executed within a virtualenv"""
+ """Returns True if scons is executed within a virtualenv"""
# see https://stackoverflow.com/a/42580137
return (hasattr(sys, 'real_prefix') or
(hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix))
def _is_path_in(path, base):
- """Returns true, if **path** is located under the **base** directory."""
+ """Returns true if **path** is located under the **base** directory."""
if not path or not base: # empty path may happen, base too
return False
rp = os.path.relpath(path, base)
diff --git a/SCons/Platform/virtualenvTests.py b/SCons/Platform/virtualenvTests.py
index da0c06b..c840749 100644
--- a/SCons/Platform/virtualenvTests.py
+++ b/SCons/Platform/virtualenvTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,17 +20,13 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import SCons.compat
import collections
import unittest
import os
import sys
+import SCons.compat
import SCons.Platform.virtualenv
import SCons.Util
diff --git a/SCons/Platform/win32.py b/SCons/Platform/win32.py
index 84fd8f8..aa76387 100644
--- a/SCons/Platform/win32.py
+++ b/SCons/Platform/win32.py
@@ -1,14 +1,6 @@
-"""SCons.Platform.win32
-
-Platform-specific initialization for Win32 systems.
-
-There normally shouldn't be any need to import this module directly. It
-will usually be imported through the generic SCons.Platform.Platform()
-selection method.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,13 @@ selection method.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Platform-specific initialization for Win32 systems.
+
+There normally shouldn't be any need to import this module directly. It
+will usually be imported through the generic SCons.Platform.Platform()
+selection method.
+"""
import os
import os.path
@@ -47,22 +43,6 @@ CHOCO_DEFAULT_PATH = [
r'C:\ProgramData\chocolatey\bin'
]
-try:
- import msvcrt
- import win32api
- import win32con
-except ImportError:
- parallel_msg = \
- "you do not seem to have the pywin32 extensions installed;\n" + \
- "\tparallel (-j) builds may not work reliably with open Python files."
-except AttributeError:
- parallel_msg = \
- "your pywin32 extensions do not support file handle operations;\n" + \
- "\tparallel (-j) builds may not work reliably with open Python files."
-else:
- parallel_msg = None
-
-
if False:
# Now swap out shutil.filecopy and filecopy2 for win32 api native CopyFile
try:
@@ -288,7 +268,6 @@ def get_program_files_dir():
val, tok = SCons.Util.RegQueryValueEx(k, 'ProgramFilesDir')
except SCons.Util.RegError:
val = ''
- pass
if val == '':
# A reasonable default if we can't read the registry
diff --git a/SCons/Platform/win32.xml b/SCons/Platform/win32.xml
index e53f02a..3000e33 100644
--- a/SCons/Platform/win32.xml
+++ b/SCons/Platform/win32.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
diff --git a/SCons/SConf.py b/SCons/SConf.py
index 6e2a0ba..70a98c8 100644
--- a/SCons/SConf.py
+++ b/SCons/SConf.py
@@ -1,18 +1,6 @@
-"""SCons.SConf
-
-Autoconf-like configuration support.
-
-In other words, SConf allows to run tests on the build machine to detect
-capabilities of system and do some things based on result: generate config
-files, header files for C/C++, update variables in environment.
-
-Tests on the build system can detect if compiler sees header files, if
-libraries are installed, if some command line options are supported etc.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -32,8 +20,16 @@ libraries are installed, if some command line options are supported etc.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""Autoconf-like configuration support.
+
+In other words, SConf allows to run tests on the build machine to detect
+capabilities of system and do some things based on result: generate config
+files, header files for C/C++, update variables in environment.
+
+Tests on the build system can detect if compiler sees header files, if
+libraries are installed, if some command line options are supported etc.
+"""
import SCons.compat
diff --git a/SCons/SConfTests.py b/SCons/SConfTests.py
index 7faabdd..a6fe508 100644
--- a/SCons/SConfTests.py
+++ b/SCons/SConfTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -29,7 +27,7 @@ import io
import os
import re
import sys
-from types import *
+from types import ModuleType
import unittest
import TestCmd
diff --git a/SCons/SConsign.py b/SCons/SConsign.py
index dc2311a..95b8096 100644
--- a/SCons/SConsign.py
+++ b/SCons/SConsign.py
@@ -1,11 +1,6 @@
-"""SCons.SConsign
-
-Writing and reading information to the .sconsign file or files.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,8 +20,8 @@ Writing and reading information to the .sconsign file or files.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""Operations on signature database files (.sconsign). """
import SCons.compat
@@ -40,10 +35,12 @@ from SCons.compat import PICKLE_PROTOCOL
def corrupt_dblite_warning(filename):
- SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning,
- "Ignoring corrupt .sconsign file: %s"%filename)
+ SCons.Warnings.warn(
+ SCons.Warnings.CorruptSConsignWarning,
+ "Ignoring corrupt .sconsign file: %s" % filename,
+ )
-SCons.dblite.ignore_corrupt_dbfiles = 1
+SCons.dblite.IGNORE_CORRUPT_DBFILES = True
SCons.dblite.corruption_warning = corrupt_dblite_warning
# XXX Get rid of the global array so this becomes re-entrant.
@@ -146,7 +143,7 @@ class SConsignEntry:
def __getstate__(self):
state = getattr(self, '__dict__', {}).copy()
for obj in type(self).mro():
- for name in getattr(obj,'__slots__',()):
+ for name in getattr(obj, '__slots__', ()):
if hasattr(self, name):
state[name] = getattr(self, name)
@@ -159,7 +156,7 @@ class SConsignEntry:
def __setstate__(self, state):
for key, value in state.items():
- if key not in ('_version_id','__weakref__'):
+ if key not in ('_version_id', '__weakref__'):
setattr(self, key, value)
diff --git a/SCons/SConsignTests.py b/SCons/SConsignTests.py
index 84c1d41..fdce588 100644
--- a/SCons/SConsignTests.py
+++ b/SCons/SConsignTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
-import sys
import unittest
import TestCmd
diff --git a/SCons/Scanner/C.py b/SCons/Scanner/C.py
index 21da574..91beb04 100644
--- a/SCons/Scanner/C.py
+++ b/SCons/Scanner/C.py
@@ -1,11 +1,6 @@
-"""SCons.Scanner.C
-
-This module implements the dependency scanner for C/C++ code.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,9 +20,8 @@ This module implements the dependency scanner for C/C++ code.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Dependency scanner for C/C++ code."""
import SCons.Node.FS
import SCons.Scanner
@@ -36,8 +30,7 @@ import SCons.Util
import SCons.cpp
class SConsCPPScanner(SCons.cpp.PreProcessor):
- """
- SCons-specific subclass of the cpp.py module's processing.
+ """SCons-specific subclass of the cpp.py module's processing.
We subclass this so that: 1) we can deal with files represented
by Nodes, not strings; 2) we can keep track of the files that are
@@ -81,8 +74,7 @@ def dictify_CPPDEFINES(env):
return cppdefines
class SConsCPPScannerWrapper:
- """
- The SCons wrapper around a cpp.py scanner.
+ """The SCons wrapper around a cpp.py scanner.
This is the actual glue between the calling conventions of generic
SCons scanners, and the (subclass of) cpp.py class that knows how
@@ -116,12 +108,14 @@ def CScanner():
# knows how to evaluate #if/#ifdef/#else/#elif lines when searching
# for #includes. This is commented out for now until we add the
# right configurability to let users pick between the scanners.
- #return SConsCPPScannerWrapper("CScanner", "CPPPATH")
-
- cs = SCons.Scanner.ClassicCPP("CScanner",
- "$CPPSUFFIXES",
- "CPPPATH",
- '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")')
+ # return SConsCPPScannerWrapper("CScanner", "CPPPATH")
+
+ cs = SCons.Scanner.ClassicCPP(
+ "CScanner",
+ "$CPPSUFFIXES",
+ "CPPPATH",
+ r'^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")',
+ )
return cs
@@ -131,8 +125,7 @@ def CScanner():
class SConsCPPConditionalScanner(SCons.cpp.PreProcessor):
- """
- SCons-specific subclass of the cpp.py module's processing.
+ """SCons-specific subclass of the cpp.py module's processing.
We subclass this so that: 1) we can deal with files represented
by Nodes, not strings; 2) we can keep track of the files that are
diff --git a/SCons/Scanner/CTests.py b/SCons/Scanner/CTests.py
index 8042e3f..25c6e99 100644
--- a/SCons/Scanner/CTests.py
+++ b/SCons/Scanner/CTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import SCons.compat
import collections
import os
@@ -32,6 +28,7 @@ import unittest
import TestCmd
import TestUnit
+import SCons.compat
import SCons.Node.FS
import SCons.Warnings
diff --git a/SCons/Scanner/D.py b/SCons/Scanner/D.py
index b3fb29e..645934b 100644
--- a/SCons/Scanner/D.py
+++ b/SCons/Scanner/D.py
@@ -1,14 +1,6 @@
-"""SCons.Scanner.D
-
-Scanner for the Digital Mars "D" programming language.
-
-Coded by Andy Friesen
-17 Nov 2003
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,11 @@ Coded by Andy Friesen
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Scanner for the Digital Mars "D" programming language.
+
+Coded by Andy Friesen, 17 Nov 2003
+"""
import SCons.Scanner
diff --git a/SCons/Scanner/DTests.py b/SCons/Scanner/DTests.py
index d0157bf..7b764aa 100644
--- a/SCons/Scanner/DTests.py
+++ b/SCons/Scanner/DTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,10 +20,9 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+import collections
+import os
import unittest
import TestCmd
@@ -31,8 +31,6 @@ import SCons.Scanner.D
test = TestCmd.TestCmd(workdir = '')
-import collections
-import os
class DummyEnvironment(collections.UserDict):
def __init__(self, **kw):
diff --git a/SCons/Scanner/Dir.py b/SCons/Scanner/Dir.py
index 3b33fe5..617bf2b 100644
--- a/SCons/Scanner/Dir.py
+++ b/SCons/Scanner/Dir.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,8 +21,6 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
import SCons.Node.FS
import SCons.Scanner
diff --git a/SCons/Scanner/DirTests.py b/SCons/Scanner/DirTests.py
index 8f866c4..2e73fe2 100644
--- a/SCons/Scanner/DirTests.py
+++ b/SCons/Scanner/DirTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
-import sys
import unittest
import TestCmd
diff --git a/SCons/Scanner/Fortran.py b/SCons/Scanner/Fortran.py
index 67e6180..18e5082 100644
--- a/SCons/Scanner/Fortran.py
+++ b/SCons/Scanner/Fortran.py
@@ -1,11 +1,6 @@
-"""SCons.Scanner.Fortran
-
-This module implements the dependency scanner for Fortran code.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -26,7 +21,7 @@ This module implements the dependency scanner for Fortran code.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Dependency scanner for Fortran code."""
import re
diff --git a/SCons/Scanner/FortranTests.py b/SCons/Scanner/FortranTests.py
index be2acd3..487fb7b 100644
--- a/SCons/Scanner/FortranTests.py
+++ b/SCons/Scanner/FortranTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
-import os.path
import unittest
import SCons.Scanner.Fortran
diff --git a/SCons/Scanner/IDL.py b/SCons/Scanner/IDL.py
index 86ee006..418608f 100644
--- a/SCons/Scanner/IDL.py
+++ b/SCons/Scanner/IDL.py
@@ -1,12 +1,6 @@
-"""SCons.Scanner.IDL
-
-This module implements the dependency scanner for IDL (Interface
-Definition Language) files.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,19 +20,20 @@ Definition Language) files.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Dependency scanner for IDL (Interface Definition Language) files."""
import SCons.Node.FS
import SCons.Scanner
def IDLScan():
"""Return a prototype Scanner instance for scanning IDL source files"""
- cs = SCons.Scanner.ClassicCPP("IDLScan",
- "$IDLSUFFIXES",
- "CPPPATH",
- '^[ \t]*(?:#[ \t]*include|[ \t]*import)[ \t]+(<|")([^>"]+)(>|")')
+ cs = SCons.Scanner.ClassicCPP(
+ "IDLScan",
+ "$IDLSUFFIXES",
+ "CPPPATH",
+ r'^[ \t]*(?:#[ \t]*include|[ \t]*import)[ \t]+(<|")([^>"]+)(>|")',
+ )
return cs
# Local Variables:
diff --git a/SCons/Scanner/IDLTests.py b/SCons/Scanner/IDLTests.py
index 9cbb73d..fc1d1c8 100644
--- a/SCons/Scanner/IDLTests.py
+++ b/SCons/Scanner/IDLTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import unittest
-import sys
import os
import os.path
diff --git a/SCons/Scanner/LaTeX.py b/SCons/Scanner/LaTeX.py
index a85592e..73f0035 100644
--- a/SCons/Scanner/LaTeX.py
+++ b/SCons/Scanner/LaTeX.py
@@ -1,11 +1,6 @@
-"""SCons.Scanner.LaTeX
-
-This module implements the dependency scanner for LaTeX code.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,9 +20,8 @@ This module implements the dependency scanner for LaTeX code.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Dependency scanner for LaTeX code."""
import os.path
import re
@@ -96,7 +90,6 @@ class FindENVPathDirs:
return tuple(dir.Rfindalldirs(path))
-
def LaTeXScanner():
"""
Return a prototype Scanner instance for scanning LaTeX source files
@@ -109,6 +102,7 @@ def LaTeXScanner():
recursive = 0)
return ds
+
def PDFLaTeXScanner():
"""
Return a prototype Scanner instance for scanning LaTeX source files
@@ -121,9 +115,9 @@ def PDFLaTeXScanner():
recursive = 0)
return ds
+
class LaTeX(SCons.Scanner.Base):
- """
- Class for scanning LaTeX files for included files.
+ """Class for scanning LaTeX files for included files.
Unlike most scanners, which use regular expressions that just
return the included file name, this returns a tuple consisting
diff --git a/SCons/Scanner/LaTeXTests.py b/SCons/Scanner/LaTeXTests.py
index 409699c..818cbe4 100644
--- a/SCons/Scanner/LaTeXTests.py
+++ b/SCons/Scanner/LaTeXTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,19 +20,14 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import SCons.compat
import collections
import os
-import sys
import unittest
import TestCmd
+import SCons.compat
import SCons.Node.FS
import SCons.Scanner.LaTeX
diff --git a/SCons/Scanner/Prog.py b/SCons/Scanner/Prog.py
index 6567b3d..41be1a4 100644
--- a/SCons/Scanner/Prog.py
+++ b/SCons/Scanner/Prog.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Dependency scanner for program files."""
import SCons.Node
import SCons.Node.FS
@@ -39,9 +39,7 @@ def ProgramScanner(**kw):
return ps
def _subst_libs(env, libs):
- """
- Substitute environment variables and split into list.
- """
+ """Substitute environment variables and split into list."""
if SCons.Util.is_String(libs):
libs = env.subst(libs)
if SCons.Util.is_String(libs):
@@ -57,9 +55,9 @@ def _subst_libs(env, libs):
return libs
def scan(node, env, libpath = ()):
- """
- This scanner scans program files for static-library
- dependencies. It will search the LIBPATH environment variable
+ """Scans program files for static-library dependencies.
+
+ It will search the LIBPATH environment variable
for libraries specified in the LIBS variable, returning any
files it finds as dependencies.
"""
diff --git a/SCons/Scanner/ProgTests.py b/SCons/Scanner/ProgTests.py
index b91a2ad..4b17d9b 100644
--- a/SCons/Scanner/ProgTests.py
+++ b/SCons/Scanner/ProgTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
-import sys
import unittest
import TestCmd
diff --git a/SCons/Scanner/Python.py b/SCons/Scanner/Python.py
index deb2241..dc6812c 100644
--- a/SCons/Scanner/Python.py
+++ b/SCons/Scanner/Python.py
@@ -1,18 +1,6 @@
-"""SCons.Scanner.Python
-
-This module implements the dependency scanner for Python code.
-
-One important note about the design is that this does not take any dependencies
-upon packages or binaries in the Python installation unless they are listed in
-PYTHONPATH. To do otherwise would have required code to determine where the
-Python installation is, which is outside of the scope of a scanner like this.
-If consumers want to pick up dependencies upon these packages, they must put
-those directories in PYTHONPATH.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -32,9 +20,17 @@ those directories in PYTHONPATH.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Dependency scanner for Python code.
+
+One important note about the design is that this does not take any dependencies
+upon packages or binaries in the Python installation unless they are listed in
+PYTHONPATH. To do otherwise would have required code to determine where the
+Python installation is, which is outside of the scope of a scanner like this.
+If consumers want to pick up dependencies upon these packages, they must put
+those directories in PYTHONPATH.
+
+"""
import itertools
import os
@@ -55,8 +51,7 @@ def path_function(env, dir=None, target=None, source=None, argument=None):
def find_include_names(node):
- """
- Scans the node for all imports.
+ """Scans the node for all imports.
Returns a list of tuples. Each tuple has two elements:
1. The main import (e.g. module, module.file, module.module2)
diff --git a/SCons/Scanner/PythonTests.py b/SCons/Scanner/PythonTests.py
index 0d4e628..faf548a 100644
--- a/SCons/Scanner/PythonTests.py
+++ b/SCons/Scanner/PythonTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
diff --git a/SCons/Scanner/RC.py b/SCons/Scanner/RC.py
index abaaef7..12e431d 100644
--- a/SCons/Scanner/RC.py
+++ b/SCons/Scanner/RC.py
@@ -1,12 +1,6 @@
-"""SCons.Scanner.RC
-
-This module implements the dependency scanner for RC (Interface
-Definition Language) files.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,20 +20,17 @@ Definition Language) files.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Dependency scanner for RC (Interface Definition Language) files."""
-import re
import SCons.Node.FS
import SCons.Scanner
def no_tlb(nodes):
- """
- Filter out .tlb files as they are binary and shouldn't be scanned
- """
+ """Filter out .tlb files as they are binary and shouldn't be scanned."""
+
# print("Nodes:%s"%[str(n) for n in nodes])
return [n for n in nodes if str(n)[-4:] != '.tlb']
@@ -47,16 +38,16 @@ def no_tlb(nodes):
def RCScan():
"""Return a prototype Scanner instance for scanning RC source files"""
- res_re= r'^(?:\s*#\s*(?:include)|' \
- r'.*?\s+(?:ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)' \
- r'\s*.*?)' \
- r'\s*(<|"| )([^>"\s]+)(?:[>"\s])*$'
- resScanner = SCons.Scanner.ClassicCPP("ResourceScanner",
- "$RCSUFFIXES",
- "CPPPATH",
- res_re,
- recursive=no_tlb)
-
+ res_re = (
+ r'^(?:\s*#\s*(?:include)|'
+ r'.*?\s+(?:ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)'
+ r'\s*.*?)'
+ r'\s*(<|"| )([^>"\s]+)(?:[>"\s])*$'
+ )
+ resScanner = SCons.Scanner.ClassicCPP(
+ "ResourceScanner", "$RCSUFFIXES", "CPPPATH", res_re, recursive=no_tlb
+ )
+
return resScanner
# Local Variables:
diff --git a/SCons/Scanner/RCTests.py b/SCons/Scanner/RCTests.py
index 487250e..9183ec7 100644
--- a/SCons/Scanner/RCTests.py
+++ b/SCons/Scanner/RCTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import unittest
-import sys
import collections
import os
diff --git a/SCons/Scanner/SWIG.py b/SCons/Scanner/SWIG.py
index a333134..5a60c74 100644
--- a/SCons/Scanner/SWIG.py
+++ b/SCons/Scanner/SWIG.py
@@ -1,11 +1,6 @@
-"""SCons.Scanner.SWIG
-
-This module implements the dependency scanner for SWIG code.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,9 +20,8 @@ This module implements the dependency scanner for SWIG code.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Dependency scanner for SWIG code."""
import SCons.Scanner
diff --git a/SCons/Scanner/Scanner.xml b/SCons/Scanner/Scanner.xml
index 4f96d39..c9b7f32 100644
--- a/SCons/Scanner/Scanner.xml
+++ b/SCons/Scanner/Scanner.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
diff --git a/SCons/Scanner/ScannerTests.py b/SCons/Scanner/ScannerTests.py
index bf9879e..815dabd 100644
--- a/SCons/Scanner/ScannerTests.py
+++ b/SCons/Scanner/ScannerTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,16 +21,12 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import SCons.compat
-
import collections
-import sys
import unittest
import TestUnit
+import SCons.compat
import SCons.Scanner
class DummyFS:
diff --git a/SCons/Scanner/__init__.py b/SCons/Scanner/__init__.py
index e99c526..d98f651 100644
--- a/SCons/Scanner/__init__.py
+++ b/SCons/Scanner/__init__.py
@@ -1,11 +1,6 @@
-"""SCons.Scanner
-
-The Scanner package for the SCons software construction utility.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,9 +20,8 @@ The Scanner package for the SCons software construction utility.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""The Scanner package for the SCons software construction utility."""
import re
@@ -43,16 +37,16 @@ class _Null:
_null = _Null
def Scanner(function, *args, **kw):
- """
- Public interface factory function for creating different types
- of Scanners based on the different types of "functions" that may
- be supplied.
+ """Factory function to create a Scanner Object.
+
+ Creates the appropriate Scanner based on the type of "function".
TODO: Deprecate this some day. We've moved the functionality
inside the Base class and really don't need this factory function
any more. It was, however, used by some of our Tool modules, so
the call probably ended up in various people's custom modules
patterned on SCons code.
+
"""
if SCons.Util.is_Dict(function):
return Selector(function, *args, **kw)
@@ -60,10 +54,8 @@ def Scanner(function, *args, **kw):
return Base(function, *args, **kw)
-
class FindPathDirs:
- """
- A class to bind a specific E{*}PATH variable name to a function that
+ """Class to bind a specific E{*}PATH variable name to a function that
will return all of the E{*}path directories.
"""
def __init__(self, variable):
@@ -82,66 +74,25 @@ class FindPathDirs:
class Base:
- """
- The base class for dependency scanners. This implements
- straightforward, single-pass scanning of a single file.
- """
-
- def __init__(self,
- function,
- name = "NONE",
- argument = _null,
- skeys = _null,
- path_function = None,
- # Node.FS.Base so that, by default, it's okay for a
- # scanner to return a Dir, File or Entry.
- node_class = SCons.Node.FS.Base,
- node_factory = None,
- scan_check = None,
- recursive = None):
- """
- Construct a new scanner object given a scanner function.
-
- 'function' - a scanner function taking two or three
- arguments and returning a list of strings.
-
- 'name' - a name for identifying this scanner object.
+ """Base class for dependency scanners.
- 'argument' - an optional argument that, if specified, will be
- passed to both the scanner function and the path_function.
-
- 'skeys' - an optional list argument that can be used to determine
- which scanner should be used for a given Node. In the case of File
- nodes, for example, the 'skeys' would be file suffixes.
-
- 'path_function' - a function that takes four or five arguments
- (a construction environment, Node for the directory containing
- the SConscript file that defined the primary target, list of
- target nodes, list of source nodes, and optional argument for
- this instance) and returns a tuple of the directories that can
- be searched for implicit dependency files. May also return a
- callable() which is called with no args and returns the tuple
- (supporting Bindable class).
-
- 'node_class' - the class of Nodes which this scan will return.
- If node_class is None, then this scanner will not enforce any
- Node conversion and will return the raw results from the
- underlying scanner function.
-
- 'node_factory' - the factory function to be called to translate
- the raw results returned by the scanner function into the
- expected node_class objects.
-
- 'scan_check' - a function to be called to first check whether
- this node really needs to be scanned.
-
- 'recursive' - specifies that this scanner should be invoked
- recursively on all of the implicit dependencies it returns
- (the canonical example being #include lines in C source files).
- May be a callable, which will be called to filter the list
- of nodes found to select a subset for recursive scanning
- (the canonical example being only recursively scanning
- subdirectories within a directory).
+ This implements straightforward, single-pass scanning of a single file.
+ """
+ def __init__(
+ self,
+ function,
+ name="NONE",
+ argument=_null,
+ skeys=_null,
+ path_function=None,
+ # Node.FS.Base so that, by default, it's okay for a
+ # scanner to return a Dir, File or Entry.
+ node_class=SCons.Node.FS.Base,
+ node_factory=None,
+ scan_check=None,
+ recursive=None,
+ ):
+ """Construct a new scanner object given a scanner function.
The scanner function's first argument will be a Node that should
be scanned for dependencies, the second argument will be an
@@ -152,14 +103,55 @@ class Base:
Examples:
- s = Scanner(my_scanner_function)
-
- s = Scanner(function = my_scanner_function)
-
- s = Scanner(function = my_scanner_function, argument = 'foo')
+ s = Scanner(my_scanner_function)
+ s = Scanner(function = my_scanner_function)
+ s = Scanner(function = my_scanner_function, argument = 'foo')
+
+ Args:
+ function: a scanner function taking two or three arguments
+ and returning a list of strings.
+
+ name: a name for identifying this scanner object.
+
+ argument: an optional argument that, if specified, will be
+ passed to both the scanner function and the path_function.
+
+ skeys: an optional list argument that can be used
+ to determine which scanner should be used for a given
+ Node. In the case of File nodes, for example, the 'skeys'
+ would be file suffixes.
+
+ path_function: a function that takes four or five arguments
+ (a construction environment, Node for the directory
+ containing the SConscript file that defined the primary
+ target, list of target nodes, list of source nodes, and
+ optional argument for this instance) and returns a tuple
+ of the directories that can be searched for implicit
+ dependency files. May also return a callable() which
+ is called with no args and returns the tuple (supporting
+ Bindable class).
+
+ node_class: the class of Nodes which this scan will return.
+ If node_class is None, then this scanner will not enforce
+ any Node conversion and will return the raw results from
+ the underlying scanner function.
+
+ node_factory: the factory function to be called to
+ translate the raw results returned by the scanner function
+ into the expected node_class objects.
+
+ scan_check: a function to be called to first check whether
+ this node really needs to be scanned.
+
+ recursive: specifies that this scanner should be invoked
+ recursively on all of the implicit dependencies it returns
+ (the canonical example being #include lines in C source
+ files). May be a callable, which will be called to filter
+ the list of nodes found to select a subset for recursive
+ scanning (the canonical example being only recursively
+ scanning subdirectories within a directory).
"""
-
# Note: this class could easily work with scanner functions that take
# something other than a filename as an argument (e.g. a database
# node) and a dependencies list that aren't file names. All that
@@ -196,11 +188,15 @@ class Base:
return self.path_function(env, dir, target, source)
def __call__(self, node, env, path=()):
- """
- This method scans a single object. 'node' is the node
- that will be passed to the scanner function, and 'env' is the
- environment that will be passed to the scanner function. A list of
- direct dependency nodes for the specified node will be returned.
+ """Scans a single object.
+
+ Args:
+ node: the node that will be passed to the scanner function
+ env: the environment that will be passed to the scanner function.
+
+ Returns:
+ A list of direct dependency nodes for the specified node.
+
"""
if self.scan_check and not self.scan_check(node, env):
return []
diff --git a/SCons/Script/Interactive.py b/SCons/Script/Interactive.py
index a414b4e..26a8bcd 100644
--- a/SCons/Script/Interactive.py
+++ b/SCons/Script/Interactive.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-__doc__ = """
-SCons interactive mode
-"""
+"""SCons interactive mode. """
# TODO:
#
diff --git a/SCons/Script/Main.py b/SCons/Script/Main.py
index 66222ae..1f2a455 100644
--- a/SCons/Script/Main.py
+++ b/SCons/Script/Main.py
@@ -1,20 +1,6 @@
-"""SCons.Script
-
-This file implements the main() function used by the scons script.
-
-Architecturally, this *is* the scons script, and will likely only be
-called from the external "scons" wrapper. Consequently, anything here
-should not be, or be considered, part of the build engine. If it's
-something that we expect other software to want to use, it should go in
-some other module. If it's specific to the "scons" script invocation,
-it goes here.
-"""
-
-unsupported_python_version = (3, 4, 0)
-deprecated_python_version = (3, 4, 0)
-
-
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright 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,8 +21,19 @@ deprecated_python_version = (3, 4, 0)
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""The main() function used by the scons script.
+
+Architecturally, this *is* the scons script, and will likely only be
+called from the external "scons" wrapper. Consequently, anything here
+should not be, or be considered, part of the build engine. If it's
+something that we expect other software to want to use, it should go in
+some other module. If it's specific to the "scons" script invocation,
+it goes here.
+"""
+# these define the range of versions SCons supports
+unsupported_python_version = (3, 4, 0)
+deprecated_python_version = (3, 4, 0)
import SCons.compat
@@ -49,6 +46,7 @@ import time
import traceback
import sysconfig
import platform
+import threading
import SCons.CacheDir
import SCons.Debug
@@ -83,17 +81,6 @@ num_jobs = None
delayed_warnings = []
-def fetch_win32_parallel_msg():
- # A subsidiary function that exists solely to isolate this import
- # so we don't have to pull it in on all platforms, and so that an
- # in-line "import" statement in the _main() function below doesn't
- # cause warnings about local names shadowing use of the 'SCons'
- # global in nest scopes and UnboundLocalErrors and the like in some
- # versions (2.1) of Python.
- import SCons.Platform.win32
- return SCons.Platform.win32.parallel_msg
-
-
def revert_io():
# This call is added to revert stderr and stdout to the original
# ones just in case some build rule or something else in the system
@@ -1284,16 +1271,19 @@ def _build_targets(fs, options, targets, target_top):
# As of 3.7, python removed support for threadless platforms.
# See https://www.python.org/dev/peps/pep-0011/
is_37_or_later = sys.version_info >= (3, 7)
- python_has_threads = sysconfig.get_config_var('WITH_THREAD') or is_pypy or is_37_or_later
+ # python_has_threads = sysconfig.get_config_var('WITH_THREAD') or is_pypy or is_37_or_later
+
+ # As of python 3.4 threading has a dummy_threading module for use when there is no threading
+ # it's get_ident() will allways return -1, while real threading modules get_ident() will
+ # always return a positive integer
+ python_has_threads = threading.get_ident() != -1
# to check if python configured with threads.
global num_jobs
num_jobs = options.num_jobs
jobs = SCons.Job.Jobs(num_jobs, taskmaster)
if num_jobs > 1:
msg = None
- if sys.platform == 'win32':
- msg = fetch_win32_parallel_msg()
- elif jobs.num_jobs == 1 or not python_has_threads:
+ if jobs.num_jobs == 1 or not python_has_threads:
msg = "parallel builds are unsupported by this version of Python;\n" + \
"\tignoring -j or num_jobs option.\n"
if msg:
@@ -1343,8 +1333,7 @@ def _exec_main(parser, values):
import pdb
pdb.Pdb().runcall(_main, parser)
elif options.profile_file:
- # compat layer imports "cProfile" for us if it's available.
- from profile import Profile
+ from cProfile import Profile
prof = Profile()
try:
diff --git a/SCons/Script/Main.xml b/SCons/Script/Main.xml
index f65ffca..ff1165c 100644
--- a/SCons/Script/Main.xml
+++ b/SCons/Script/Main.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
@@ -80,10 +80,10 @@ it will recognize <option>--device</option>,
and so forth as long as there is no other option
which could also match to the same abbreviation.
Options added via
-<function>AddOption</function> do not support
+&f-AddOption; do not support
the automatic recognition of abbreviations.
Instead, to allow specific abbreviations,
-include them in the &f-AddOption; call.
+include them as synonyms in the &f-AddOption; call itself.
</para>
<para>
@@ -99,7 +99,7 @@ options added with &f-AddOption;.
The value may also be set using
&f-SetOption;
or
-<function>env.SetOption</function>(),
+&f-env.SetOption;,
if conditions in a
&SConscript;
require overriding any default value.
@@ -765,123 +765,135 @@ Multiple targets can be passed in to a single call to
</arguments>
<summary>
<para>
-This function provides a way to set a select subset of the scons command
-line options from a SConscript file. The options supported are:
-</para>
-
-<para>
-<variablelist>
-<varlistentry>
-<term><literal>clean</literal></term>
-<listitem>
-<para>
-which corresponds to <option>-c</option>, <option>--clean</option>
-and <option>--remove</option>;
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>duplicate</literal></term>
-<listitem>
-<para>
-which corresponds to <option>--duplicate</option>;
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>help</literal></term>
-<listitem>
-<para>
-which corresponds to <option>-h</option> and <option>--help</option>;
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>implicit_cache</literal></term>
-<listitem>
-<para>
-which corresponds to <option>--implicit-cache</option>;
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>max_drift</literal></term>
-<listitem>
-<para>
-which corresponds to <option>--max-drift</option>;
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>no_exec</literal></term>
-<listitem>
-<para>
-which corresponds to <option>-n</option>, <option>--no-exec</option>,
-<option>--just-print</option>, <option>--dry-run</option>
-and <option>--recon</option>;
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>num_jobs</literal></term>
-<listitem>
-<para>
-which corresponds to <option>-j</option> and <option>--jobs</option>;
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>random</literal></term>
-<listitem>
-<para>
-which corresponds to <option>--random</option>; and
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>silent</literal></term>
-<listitem>
-<para>
-which corresponds to <option>--silent</option>.
-</para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>no_progress</literal></term>
-<listitem>
-<para>
-which corresponds to -Q.
-</para>
-<para>
- Note: The initial progress output will still be output as this is done before the SConstruct/SConscript which contains the SetOption is processed
- <literal>scons: Reading SConscript files ...</literal>
-</para>
-<para><emphasis>Available since &scons; 4.0.</emphasis></para>
-</listitem>
-</varlistentry>
-<varlistentry>
-<term><literal>stack_size</literal></term>
-<listitem>
-<para>
-which corresponds to --stack-size.
-</para>
-</listitem>
-</varlistentry>
-</variablelist>
+Sets &scons; option variable <parameter>name</parameter>
+to <parameter>value</parameter>.
+These options are all also settable via
+&scons; command-line options but the variable name
+may differ from the command-line option name (see table).
+A value set via command-line option will take
+precedence over one set with &f-SetOption;, which
+allows setting a project default in the scripts and
+temporarily overriding it via command line.
+Options which affect the reading and processing of SConscript files
+are not settable this way, since those files must
+be read in order to find the &f-SetOption; call.
+</para>
+
+<para>
+The settable variables with their associated command-line options are:
+</para>
+
+<!-- UPDATE_SETOPTION_DOCS -->
+<!-- This list comes directly from SConsValues.settable. Keep in sync. -->
+
+<informaltable rowsep="1" colsep="1" frame="topbot">
+<tgroup cols="2">
+<thead>
+<row><entry>Variable</entry><entry>Command-line options</entry></row>
+</thead>
+<tbody>
+<row><entry>
+<varname>clean</varname>
+</entry><entry>
+<option>-c</option>, <option>--clean</option>, <option>--remove</option>
+</entry></row>
+<row><entry>
+<varname>diskcheck</varname>
+</entry><entry>
+<option>--diskcheck</option>
+</entry></row>
+<row><entry>
+<varname>duplicate</varname>
+</entry><entry>
+<option>--duplicate</option>
+</entry></row>
+<row><entry>
+<varname>help</varname>
+</entry><entry>
+<option>-h</option>, <option>--help</option>
+</entry></row>
+<row><entry>
+<varname>implicit_cache</varname>
+</entry><entry>
+<option>--implicit-cache</option>
+</entry></row>
+<!--TODO: add implicit-deps-changed, implicit-deps-unchanged ? -->
+<row><entry>
+<varname>max_drift</varname>
+</entry><entry>
+<option>--max-drift</option>
+</entry></row>
+<row><entry>
+<varname>md5_chunksize</varname>
+</entry><entry>
+<option>--md5-chunksize</option>
+</entry></row>
+<row><entry>
+<varname>no_exec</varname>
+</entry><entry>
+<option>-n</option>, <option>--no-exec</option>,
+<option>--just-print</option>, <option>--dry-run</option>,
+<option>--recon</option>
+</entry></row>
+<row><entry>
+<varname>no_progress</varname>
+</entry><entry>
+<option>-Q</option>
+</entry></row>
+<row><entry>
+<varname>num_jobs</varname>
+</entry><entry>
+<option>-j</option>, <option>--jobs</option>
+</entry></row>
+<row><entry>
+<varname>random</varname>
+</entry><entry>
+<option>--random</option>
+</entry></row>
+<row><entry>
+<varname>silent</varname>
+</entry><entry>
+<option>--silent</option>.
+</entry></row>
+<row><entry>
+<varname>stack_size</varname>
+</entry><entry>
+<option>--stack-size</option>
+</entry></row>
+<row><entry>
+<varname>warn</varname>
+</entry><entry>
+<option>--warn</option>.
+</entry></row>
+</tbody>
+</tgroup>
+</informaltable>
+
+<para>
+See the documentation in the manpage for the
+corresponding command line option for information about each specific option.
+Option values which are boolean in nature (that is, they are
+either on or off) should be set to a true value (<constant>True</constant>,
+<constant>1</constant>) or a false value (<constant>False</constant>,
+<constant>0</constant>).
</para>
+<note>
<para>
-See the documentation for the
-corresponding command line option for information about each specific
-option.
+If <varname>no_progress</varname> is set via &f-SetOption;
+there will still be initial progress output as &SCons; has
+to start reading SConscript files before it can see the
+&f-SetOption; in an SConscript file:
+<computeroutput>scons: Reading SConscript files ...</computeroutput>
</para>
+</note>
<para>
Example:
</para>
<example_commands>
-SetOption('max_drift', 1)
+SetOption('max_drift', True)
</example_commands>
</summary>
</scons_function>
diff --git a/SCons/Script/MainTests.py b/SCons/Script/MainTests.py
index aa6bfac..232a8a2 100644
--- a/SCons/Script/MainTests.py
+++ b/SCons/Script/MainTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import unittest
diff --git a/SCons/Script/SConsOptions.py b/SCons/Script/SConsOptions.py
index aa31635..7b79292 100644
--- a/SCons/Script/SConsOptions.py
+++ b/SCons/Script/SConsOptions.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import optparse
import re
@@ -30,12 +28,8 @@ import textwrap
no_hyphen_re = re.compile(r'(\s+|(?<=[\w!\"\'&.,?])-{2,}(?=\w))')
-try:
- from gettext import gettext
-except ImportError:
- def gettext(message):
- return message
-_ = gettext
+import gettext
+_ = gettext.gettext
import SCons.Node.FS
import SCons.Platform.virtualenv
@@ -126,7 +120,8 @@ class SConsValues(optparse.Values):
# is not available.
raise AttributeError(attr)
-
+ # keep this list in sync with the SetOption doc in SCons/Script/Main.xml
+ # search for UPDATE_SETOPTION_DOCS there.
settable = [
'clean',
'diskcheck',
diff --git a/SCons/Script/SConscript.py b/SCons/Script/SConscript.py
index e7f53f5..b8dfd93 100644
--- a/SCons/Script/SConscript.py
+++ b/SCons/Script/SConscript.py
@@ -1,12 +1,6 @@
-"""SCons.Script.SConscript
-
-This module defines the Python API provided to SConscript and SConstruct
-files.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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 +21,7 @@ files.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""This module defines the Python API provided to SConscript files."""
import SCons
import SCons.Action
@@ -46,7 +40,6 @@ from SCons.Util import is_List, is_String, is_Dict, flatten
from SCons.Node import SConscriptNodes
from . import Main
-import collections
import os
import os.path
import re
diff --git a/SCons/Script/SConscript.xml b/SCons/Script/SConscript.xml
index 03efcfb..dc6e7a6 100644
--- a/SCons/Script/SConscript.xml
+++ b/SCons/Script/SConscript.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
diff --git a/SCons/Script/SConscriptTests.py b/SCons/Script/SConscriptTests.py
index 8b2521d..bb88dfa 100644
--- a/SCons/Script/SConscriptTests.py
+++ b/SCons/Script/SConscriptTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.Script.SConscript
diff --git a/SCons/Script/__init__.py b/SCons/Script/__init__.py
index ee9b382..dff1567 100644
--- a/SCons/Script/__init__.py
+++ b/SCons/Script/__init__.py
@@ -1,18 +1,6 @@
-"""SCons.Script
-
-This file implements the main() function used by the scons script.
-
-Architecturally, this *is* the scons script, and will likely only be
-called from the external "scons" wrapper. Consequently, anything here
-should not be, or be considered, part of the build engine. If it's
-something that we expect other software to want to use, it should go in
-some other module. If it's specific to the "scons" script invocation,
-it goes here.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,20 +20,23 @@ it goes here.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""The main() function used by the scons script.
+
+Architecturally, this *is* the scons script, and will likely only be
+called from the external "scons" wrapper. Consequently, anything here
+should not be, or be considered, part of the build engine. If it's
+something that we expect other software to want to use, it should go in
+some other module. If it's specific to the "scons" script invocation,
+it goes here.
+"""
import time
start_time = time.time()
import collections
import os
-
-try:
- from StringIO import StringIO
-except ImportError:
- from io import StringIO
+from io import StringIO
import sys
@@ -134,7 +125,6 @@ GetBuildFailures = Main.GetBuildFailures
#profiling = Main.profiling
#repositories = Main.repositories
-#
from . import SConscript
_SConscript = SConscript
@@ -282,7 +272,11 @@ _no_missing_sconscript = False
_warn_missing_sconscript_deprecated = True
def set_missing_sconscript_error(flag=1):
- """Set behavior on missing file in SConscript() call. Returns previous value"""
+ """Set behavior on missing file in SConscript() call.
+
+ Returns:
+ previous value
+ """
global _no_missing_sconscript
old = _no_missing_sconscript
_no_missing_sconscript = flag
diff --git a/SCons/Subst.py b/SCons/Subst.py
index 3aa0d8a..ea756ff 100644
--- a/SCons/Subst.py
+++ b/SCons/Subst.py
@@ -1,11 +1,6 @@
-"""SCons.Subst
-
-SCons string substitution.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -26,7 +21,7 @@ SCons string substitution.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""SCons string substitution."""
import collections
import re
@@ -36,18 +31,20 @@ import SCons.Errors
from SCons.Util import is_String, is_Sequence
# Indexed by the SUBST_* constants below.
-_strconv = [SCons.Util.to_String_for_subst,
- SCons.Util.to_String_for_subst,
- SCons.Util.to_String_for_signature]
-
-
+_strconv = [
+ SCons.Util.to_String_for_subst,
+ SCons.Util.to_String_for_subst,
+ SCons.Util.to_String_for_signature,
+]
AllowableExceptions = (IndexError, NameError)
+
def SetAllowableExceptions(*excepts):
global AllowableExceptions
AllowableExceptions = [_f for _f in excepts if _f]
+
def raise_exception(exception, target, s):
name = exception.__class__.__name__
msg = "%s `%s' trying to evaluate `%s'" % (name, exception, s)
@@ -57,7 +54,6 @@ def raise_exception(exception, target, s):
raise SCons.Errors.UserError(msg)
-
class Literal:
"""A wrapper for a string. If you use this object wrapped
around a string, then it will be interpreted as literal.
diff --git a/SCons/Subst.xml b/SCons/Subst.xml
index 4352de4..0d50bf2 100644
--- a/SCons/Subst.xml
+++ b/SCons/Subst.xml
@@ -1,6 +1,6 @@
<?xml version="1.0"?>
<!--
-__COPYRIGHT__
+Copyright The SCons Foundation
This file is processed by the bin/SConsDoc.py module.
See its __doc__ string for a discussion of the format.
diff --git a/SCons/SubstTests.py b/SCons/SubstTests.py
index 07eb61d..be62db0 100644
--- a/SCons/SubstTests.py
+++ b/SCons/SubstTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,20 +20,18 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
import os
-import sys
import unittest
-from collections import UserDict
import SCons.Errors
-from SCons.Subst import *
+from SCons.Subst import (Literal, SUBST_CMD, SUBST_RAW, SUBST_SIG, SpecialAttrWrapper, collections,
+ escape_list, quote_spaces, scons_subst, scons_subst_list, scons_subst_once,
+ subst_dict)
class DummyNode:
"""Simple node work-alike."""
@@ -544,9 +543,7 @@ class scons_subst_TestCase(SubstTestCase):
scons_subst('$foo.bar.3.0', env)
except SCons.Errors.UserError as e:
expect = [
- # Python 2.3, 2.4
- "SyntaxError `invalid syntax (line 1)' trying to evaluate `$foo.bar.3.0'",
- # Python 2.5
+ # Python 2.5 and later
"SyntaxError `invalid syntax (<string>, line 1)' trying to evaluate `$foo.bar.3.0'",
]
assert str(e) in expect, e
diff --git a/SCons/Taskmaster.py b/SCons/Taskmaster.py
index bfb7dc1..a1358e0 100644
--- a/SCons/Taskmaster.py
+++ b/SCons/Taskmaster.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,43 +21,33 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-import sys
+"""Generic Taskmaster module for the SCons build engine.
-__doc__ = """
- Generic Taskmaster module for the SCons build engine.
- =====================================================
-
- This module contains the primary interface(s) between a wrapping user
- interface and the SCons build engine. There are two key classes here:
-
- Taskmaster
- ----------
- This is the main engine for walking the dependency graph and
- calling things to decide what does or doesn't need to be built.
-
- Task
- ----
- This is the base class for allowing a wrapping interface to
- decide what does or doesn't actually need to be done. The
- intention is for a wrapping interface to subclass this as
- appropriate for different types of behavior it may need.
-
- The canonical example is the SCons native Python interface,
- which has Task subclasses that handle its specific behavior,
- like printing "'foo' is up to date" when a top-level target
- doesn't need to be built, and handling the -c option by removing
- targets as its "build" action. There is also a separate subclass
- for suppressing this output when the -q option is used.
-
- The Taskmaster instantiates a Task object for each (set of)
- target(s) that it decides need to be evaluated and/or built.
-"""
+This module contains the primary interface(s) between a wrapping user
+interface and the SCons build engine. There are two key classes here:
+
+Taskmaster
+ This is the main engine for walking the dependency graph and
+ calling things to decide what does or doesn't need to be built.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+Task
+ This is the base class for allowing a wrapping interface to
+ decide what does or doesn't actually need to be done. The
+ intention is for a wrapping interface to subclass this as
+ appropriate for different types of behavior it may need.
+
+ The canonical example is the SCons native Python interface,
+ which has Task subclasses that handle its specific behavior,
+ like printing "'foo' is up to date" when a top-level target
+ doesn't need to be built, and handling the -c option by removing
+ targets as its "build" action. There is also a separate subclass
+ for suppressing this output when the -q option is used.
+
+ The Taskmaster instantiates a Task object for each (set of)
+ target(s) that it decides need to be evaluated and/or built.
+"""
-import operator
import sys
-import traceback
from abc import ABC, abstractmethod
from itertools import chain
diff --git a/SCons/TaskmasterTests.py b/SCons/TaskmasterTests.py
index c11d8e8..f20fd71 100644
--- a/SCons/TaskmasterTests.py
+++ b/SCons/TaskmasterTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,9 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
-import copy
import sys
import unittest
@@ -867,10 +865,9 @@ class TaskmasterTestCase(unittest.TestCase):
except MyException as e:
exc_caught = 1
exc_value = e
- except Exception as e:
- exc_actually_caught = e
+ except Exception as exc_actually_caught:
pass
- assert exc_caught, "did not catch expected MyException: %s"%exc_actually_caught
+ 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
diff --git a/SCons/Tool/JavaCommonTests.py b/SCons/Tool/JavaCommonTests.py
index 83354b8..f35cb9e 100644
--- a/SCons/Tool/JavaCommonTests.py
+++ b/SCons/Tool/JavaCommonTests.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
-import sys
import unittest
import fnmatch
diff --git a/SCons/Tool/MSCommon/__init__.py b/SCons/Tool/MSCommon/__init__.py
index be7720a..ee8f2bd 100644
--- a/SCons/Tool/MSCommon/__init__.py
+++ b/SCons/Tool/MSCommon/__init__.py
@@ -27,10 +27,6 @@ __doc__ = """
Common functions for Microsoft Visual Studio and Visual C/C++.
"""
-import copy
-import os
-import re
-import subprocess
import SCons.Errors
import SCons.Platform.win32
diff --git a/SCons/Tool/MSCommon/arch.py b/SCons/Tool/MSCommon/arch.py
index ba57a2c..0032422 100644
--- a/SCons/Tool/MSCommon/arch.py
+++ b/SCons/Tool/MSCommon/arch.py
@@ -26,7 +26,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
__doc__ = """Module to define supported Windows chip architectures.
"""
-import os
class ArchDefinition:
"""
diff --git a/SCons/Tool/MSCommon/vc.py b/SCons/Tool/MSCommon/vc.py
index 886288a..e50277d 100644
--- a/SCons/Tool/MSCommon/vc.py
+++ b/SCons/Tool/MSCommon/vc.py
@@ -43,7 +43,6 @@ import SCons.Util
import subprocess
import os
import platform
-import sys
from string import digits as string_digits
from subprocess import PIPE
@@ -204,7 +203,7 @@ def get_host_target(env):
# Retain user requested TARGET_ARCH
req_target_platform = env.get('TARGET_ARCH')
- debug("HOST_ARCH:" + str(req_target_platform))
+ debug("TARGET_ARCH:" + str(req_target_platform))
if req_target_platform:
# If user requested a specific platform then only try that one.
target_platform = req_target_platform
@@ -221,9 +220,12 @@ def get_host_target(env):
target = _ARCH_TO_CANONICAL[target_platform.lower()]
except KeyError:
all_archs = str(list(_ARCH_TO_CANONICAL.keys()))
- raise MSVCUnsupportedTargetArch("Unrecognized target architecture %s\n\tValid architectures: %s" % (target_platform, all_archs))
+ raise MSVCUnsupportedTargetArch(
+ "Unrecognized target architecture %s\n\tValid architectures: %s"
+ % (target_platform, all_archs)
+ )
- return (host, target,req_target_platform)
+ 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.
diff --git a/SCons/Tool/ToolTests.py b/SCons/Tool/ToolTests.py
index 75a9454..9a6d9b5 100644
--- a/SCons/Tool/ToolTests.py
+++ b/SCons/Tool/ToolTests.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
-import sys
import unittest
import TestUnit
@@ -84,19 +83,21 @@ class ToolTestCase(unittest.TestCase):
assert env['INCPREFIX'] == '-I', env['INCPREFIX']
assert env['TOOLS'] == ['g++'], env['TOOLS']
+ exc_caught = None
try:
SCons.Tool.Tool()
except TypeError:
- pass
- else: # TODO pylint E0704: bare raise not inside except
- raise
+ exc_caught = 1
+ assert exc_caught, "did not catch expected UserError"
+ exc_caught = None
try:
p = SCons.Tool.Tool('_does_not_exist_')
- except SCons.Errors.SConsEnvironmentError:
- pass
- else: # TODO pylint E0704: bare raise not inside except
- raise
+ except SCons.Errors.UserError as e:
+ exc_caught = 1
+ # Old msg was Python-style "No tool named", check for new msg:
+ assert "No tool module" in str(e), e
+ assert exc_caught, "did not catch expected UserError"
def test_pathfind(self):
diff --git a/SCons/Tool/__init__.py b/SCons/Tool/__init__.py
index 24fb9d2..87139f1 100644
--- a/SCons/Tool/__init__.py
+++ b/SCons/Tool/__init__.py
@@ -184,13 +184,16 @@ class Tool:
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.SConsEnvironmentError(error_string)
+ sconstools = os.path.normpath(sys.modules['SCons.Tool'].__path__[0])
+ if self.toolpath:
+ sconstools = ", ".join(self.toolpath) + ", " + sconstools
+ error_string = "No tool module '%s' found in %s" % (self.name, sconstools)
+ raise SCons.Errors.UserError(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
+ error_string = "Tool module '%s' failed import" % self.name
raise SCons.Errors.SConsEnvironmentError(error_string)
# Don't reload a tool we already loaded.
@@ -691,7 +694,7 @@ def tool_list(platform, env):
assemblers = ['masm', 'nasm', 'gas', '386asm']
fortran_compilers = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran']
ars = ['mslib', 'ar', 'tlib']
- other_plat_tools = ['msvs', 'midl']
+ other_plat_tools = ['msvs', 'midl', 'wix']
elif str(platform) == 'os2':
"prefer IBM tools on OS/2"
linkers = ['ilink', 'gnulink', ] # 'mslink']
@@ -791,7 +794,6 @@ def tool_list(platform, env):
# TODO: merge 'install' into 'filesystem' and
# make 'filesystem' the default
'filesystem',
- 'wix', # 'midl', 'msvs',
# Parser generators
'lex', 'yacc',
# Foreign function interface
diff --git a/SCons/Tool/clang.py b/SCons/Tool/clang.py
index 162daad..e39c742 100644
--- a/SCons/Tool/clang.py
+++ b/SCons/Tool/clang.py
@@ -84,8 +84,7 @@ def generate(env):
# clang -dumpversion is of no use
with pipe.stdout:
line = pipe.stdout.readline()
- if sys.version_info[0] > 2:
- line = line.decode()
+ line = line.decode()
match = re.search(r'clang +version +([0-9]+(?:\.[0-9]+)+)', line)
if match:
env['CCVERSION'] = match.group(1)
diff --git a/SCons/Tool/clangxx.py b/SCons/Tool/clangxx.py
index b1dc6f3..736d455 100644
--- a/SCons/Tool/clangxx.py
+++ b/SCons/Tool/clangxx.py
@@ -92,8 +92,7 @@ def generate(env):
# clang -dumpversion is of no use
with pipe.stdout:
line = pipe.stdout.readline()
- if sys.version_info[0] > 2:
- line = line.decode()
+ line = line.decode()
match = re.search(r'clang +version +([0-9]+(?:\.[0-9]+)+)', line)
if match:
env['CXXVERSION'] = match.group(1)
diff --git a/SCons/Tool/compilation_db.py b/SCons/Tool/compilation_db.py
index b610574..d20d171 100644
--- a/SCons/Tool/compilation_db.py
+++ b/SCons/Tool/compilation_db.py
@@ -31,6 +31,7 @@ which is the name that most clang tools search for by default.
import json
import itertools
+import fnmatch
import SCons
from .cxx import CXXSuffixes
@@ -52,7 +53,6 @@ class __CompilationDbNode(SCons.Node.Python.Value):
SCons.Node.Python.Value.__init__(self, value)
self.Decider(changed_since_last_build_node)
-
def changed_since_last_build_node(child, target, prev_ni, node):
""" Dummy decider to force always building"""
return True
@@ -135,6 +135,7 @@ def write_compilation_db(target, source, env):
entries = []
use_abspath = env['COMPILATIONDB_USE_ABSPATH'] in [True, 1, 'True', 'true']
+ use_path_filter = env.subst('$COMPILATIONDB_PATH_FILTER')
for s in __COMPILATION_DB_ENTRIES:
entry = s.read()
@@ -148,6 +149,9 @@ def write_compilation_db(target, source, env):
source_file = source_file.srcnode().path
output_file = output_file.path
+ if use_path_filter and not fnmatch.fnmatch(output_file, use_path_filter):
+ continue
+
path_entry = {'directory': entry['directory'],
'command': entry['command'],
'file': source_file,
@@ -244,6 +248,7 @@ def generate(env, **kwargs):
)
env['COMPILATIONDB_USE_ABSPATH'] = False
+ env['COMPILATIONDB_PATH_FILTER'] = ''
def exists(env):
diff --git a/SCons/Tool/compilation_db.xml b/SCons/Tool/compilation_db.xml
index 88ea6ca..40a104e 100644
--- a/SCons/Tool/compilation_db.xml
+++ b/SCons/Tool/compilation_db.xml
@@ -38,6 +38,7 @@ See its __doc__ string for a discussion of the format.
<item>__COMPILATIONDB_ENV</item>
-->
<item>COMPILATIONDB_USE_ABSPATH</item>
+ <item>COMPILATIONDB_PATH_FILTER</item>
</sets>
</tool>
@@ -62,10 +63,10 @@ env.CompilationDatabase('my_output.json')
</para>
<para>
You should not specify source files. The &b-CompilationDatabase; builder instruments SCons to collect them from all
- the C, C++, assembly source/target pairs.
+ the C, C++, assembly source/output pairs.
</para>
<para>
- NOTE: You must load the &t-compilation_db; tool prior to specifying any part of your build or some source/target
+ NOTE: You must load the &t-compilation_db; tool prior to specifying any part of your build or some source/output
files will not show up in your output file.
</para>
<para>
@@ -86,7 +87,7 @@ env.CompilationDatabase('my_output.json')
<summary>
<para>
This is a boolean flag to instruct &b-link-CompilationDatabase; to
- write the <literal>file</literal> and <literal>target</literal> members
+ write the <literal>file</literal> and <literal>output</literal> members
in the compilation database with absolute or relative paths.
</para>
<para>
@@ -94,6 +95,21 @@ env.CompilationDatabase('my_output.json')
</para>
</summary>
</cvar>
+
+ <cvar name="COMPILATIONDB_PATH_FILTER">
+ <summary>
+ <para>
+ This is a string which instructs &b-link-CompilationDatabase; to
+ only include entries where the <literal>output</literal> member
+ matches the pattern in the filter string using fnmatch, which
+ uses glob style wildcards.
+
+ </para>
+ <para>
+ The default value is an empty string '', which disables filtering.
+ </para>
+ </summary>
+ </cvar>
<!-- Internal env vars for use by CompilationDatabase builder/pseudobuilder only -->
<!-- <cvar name="__COMPILATIONDB_UACTION">-->
<!-- <summary>-->
diff --git a/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py b/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py
index 3d53bf7..d79ece3 100644
--- a/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py
+++ b/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py
@@ -1,7 +1,5 @@
# docbook.py: extension module
# $Id: docbook.py 8353 2009-03-17 16:57:50Z mzjn $
-import sys
-import string
import libxml2
import libxslt
import re
diff --git a/SCons/Tool/fortran.py b/SCons/Tool/fortran.py
index aeb9130..0a68df6 100644
--- a/SCons/Tool/fortran.py
+++ b/SCons/Tool/fortran.py
@@ -33,7 +33,6 @@ selection method.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import re
import SCons.Action
import SCons.Defaults
diff --git a/SCons/Tool/gcc.py b/SCons/Tool/gcc.py
index d56f6a0..37626ef 100644
--- a/SCons/Tool/gcc.py
+++ b/SCons/Tool/gcc.py
@@ -34,7 +34,6 @@ selection method.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
from . import cc
-import os
import re
import subprocess
diff --git a/SCons/Tool/gxx.py b/SCons/Tool/gxx.py
index 4b86327..88186cb 100644
--- a/SCons/Tool/gxx.py
+++ b/SCons/Tool/gxx.py
@@ -33,9 +33,6 @@ selection method.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
-import re
-import subprocess
import SCons.Tool
import SCons.Util
diff --git a/SCons/Tool/intelc.py b/SCons/Tool/intelc.py
index 38bdc32..5025719 100644
--- a/SCons/Tool/intelc.py
+++ b/SCons/Tool/intelc.py
@@ -32,7 +32,11 @@ selection method.
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import math, sys, os.path, glob, string, re
+import glob
+import math
+import os.path
+import re
+import sys
is_windows = sys.platform == 'win32'
is_win64 = is_windows and (os.environ['PROCESSOR_ARCHITECTURE'] == 'AMD64' or
diff --git a/SCons/Tool/linkCommon/__init__.py b/SCons/Tool/linkCommon/__init__.py
index 413b13e..c49bc23 100644
--- a/SCons/Tool/linkCommon/__init__.py
+++ b/SCons/Tool/linkCommon/__init__.py
@@ -55,7 +55,6 @@ def _call_linker_cb(env, callback, args, result=None):
except (KeyError, TypeError):
if Verbose:
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)
diff --git a/SCons/Tool/linkloc.py b/SCons/Tool/linkloc.py
index 0ca37b3..6ee5d61 100644
--- a/SCons/Tool/linkloc.py
+++ b/SCons/Tool/linkloc.py
@@ -34,7 +34,6 @@ selection method.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import re
import SCons.Action
diff --git a/SCons/Tool/msginit.py b/SCons/Tool/msginit.py
index a94cb85..4b72c30 100644
--- a/SCons/Tool/msginit.py
+++ b/SCons/Tool/msginit.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.Warnings
import SCons.Builder
-import re
#############################################################################
def _optional_no_translator_flag(env):
diff --git a/SCons/Tool/msvc.py b/SCons/Tool/msvc.py
index b9eb60a..a06a434 100644
--- a/SCons/Tool/msvc.py
+++ b/SCons/Tool/msvc.py
@@ -35,8 +35,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
import os
-import re
-import sys
import SCons.Action
import SCons.Builder
diff --git a/SCons/Tool/msvs.py b/SCons/Tool/msvs.py
index c10b802..c398365 100644
--- a/SCons/Tool/msvs.py
+++ b/SCons/Tool/msvs.py
@@ -607,6 +607,7 @@ class _DSPGenerator:
config.platform = 'Win32'
self.configs[variant] = config
+ # DEBUG: leave enabled, test/MSVS/CPPPATH-dirs.py expects this
print("Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dspfile) + "'")
for i in range(len(variants)):
@@ -1444,7 +1445,9 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):
'\t</ItemGroup>\n' % str(self.sconscript))
def Parse(self):
- print("_GenerateV10DSP.Parse()")
+ # DEBUG
+ # print("_GenerateV10DSP.Parse()")
+ pass
def Build(self):
try:
@@ -1530,7 +1533,8 @@ class _GenerateV7DSW(_DSWGenerator):
config.platform = 'Win32'
self.configs[variant] = config
- print("Adding '" + self.name + ' - ' + config.variant + '|' + config.platform + "' to '" + str(dswfile) + "'")
+ # DEBUG
+ # 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 " +\
diff --git a/SCons/Tool/msvsTests.py b/SCons/Tool/msvsTests.py
index 30c3b58..336c6f9 100644
--- a/SCons/Tool/msvsTests.py
+++ b/SCons/Tool/msvsTests.py
@@ -564,17 +564,20 @@ def DummyEnumKey(key, index):
rv = key.keyarray[index]
except IndexError:
raise SCons.Util.RegError
-# print "Enum Key",key.name,"[",index,"] =>",rv
+ # DEBUG
+ # print "Enum Key",key.name,"[",index,"] =>",rv
return rv
def DummyEnumValue(key, index):
rv = key.valindex(index)
-# print "Enum Value",key.name,"[",index,"] =>",rv
+ # DEBUG
+ # print "Enum Value",key.name,"[",index,"] =>",rv
return rv
def DummyQueryValue(key, value):
rv = key.value(value)
-# print "Query Value",key.name+"\\"+value,"=>",rv
+ # DEBUG
+ # print "Query Value",key.name+"\\"+value,"=>",rv
return rv
def DummyExists(path):
@@ -726,8 +729,18 @@ class msvsTestCase(unittest.TestCase):
for param_cppdefines, expected_cppdefines in tests_cppdefines:
for param_cpppaths, expected_cpppaths in tests_cpppaths:
for param_cppflags, expected_cppflags in tests_cppflags:
- print('Testing %s. with :\n variant = %s \n cmdargs = "%s" \n cppdefines = "%s" \n cpppaths = "%s" \n cppflags = "%s"' % \
- (str_function_test, list_variant, param_cmdargs, param_cppdefines, param_cpppaths, param_cppflags))
+ # DEBUG:
+ # print(
+ # 'Testing %s. with :\n variant = %s \n cmdargs = "%s" \n cppdefines = "%s" \n cpppaths = "%s" \n cppflags = "%s"'
+ # % (
+ # str_function_test,
+ # list_variant,
+ # param_cmdargs,
+ # param_cppdefines,
+ # param_cpppaths,
+ # param_cppflags,
+ # )
+ # )
param_configs = []
expected_configs = {}
for platform in ['Win32', 'x64']:
@@ -959,7 +972,8 @@ if __name__ == "__main__":
]
for test_class in test_classes:
- print("TEST: ", test_class.__doc__)
+ # DEBUG
+ # print("TEST: ", test_class.__doc__)
back_osenv = copy.deepcopy(os.environ)
try:
# XXX: overriding the os.environ is bad, but doing it
diff --git a/SCons/Tool/packaging/__init__.py b/SCons/Tool/packaging/__init__.py
index c45a96b..c378909 100644
--- a/SCons/Tool/packaging/__init__.py
+++ b/SCons/Tool/packaging/__init__.py
@@ -35,7 +35,7 @@ import SCons.Environment
from SCons.Errors import UserError, SConsEnvironmentError
from SCons.Script import AddOption, GetOption
from SCons.Util import is_List, make_path_relative
-from SCons.Variables import *
+from SCons.Variables import EnumVariable
from SCons.Warnings import warn, SConsWarning
diff --git a/SCons/Tool/packaging/msi.py b/SCons/Tool/packaging/msi.py
index defb5c6..458e81f 100644
--- a/SCons/Tool/packaging/msi.py
+++ b/SCons/Tool/packaging/msi.py
@@ -32,7 +32,7 @@ import SCons
from SCons.Action import Action
from SCons.Builder import Builder
-from xml.dom.minidom import *
+from xml.dom.minidom import Document
from xml.sax.saxutils import escape
from SCons.Tool.packaging import stripinstallbuilder
diff --git a/SCons/Tool/packaging/rpm.py b/SCons/Tool/packaging/rpm.py
index a026e45..cdeabcf 100644
--- a/SCons/Tool/packaging/rpm.py
+++ b/SCons/Tool/packaging/rpm.py
@@ -27,7 +27,6 @@ The rpm packager.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import SCons.Builder
import SCons.Tool.rpmutils
diff --git a/SCons/Tool/qt.py b/SCons/Tool/qt.py
index fab1625..d8a51b2 100644
--- a/SCons/Tool/qt.py
+++ b/SCons/Tool/qt.py
@@ -35,7 +35,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
import re
-import glob
import SCons.Action
import SCons.Builder
diff --git a/SCons/Tool/tex.py b/SCons/Tool/tex.py
index 1d61e2d..0ca7e2d 100644
--- a/SCons/Tool/tex.py
+++ b/SCons/Tool/tex.py
@@ -429,18 +429,23 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None
return result
# Now decide if latex will need to be run again due to newglossary command.
- for ig in range(len(newglossary_suffix)):
- if check_MD5(suffix_nodes[newglossary_suffix[ig][2]],newglossary_suffix[ig][2]) or (count == 1):
+ for ng in newglossary_suffix:
+ if check_MD5(suffix_nodes[ng[2]], ng[2]) or (count == 1):
# We must run makeindex
if Verbose:
print("Need to run makeindex for newglossary")
- newglfile = suffix_nodes[newglossary_suffix[ig][2]]
- MakeNewGlossaryAction = SCons.Action.Action("$MAKENEWGLOSSARYCOM ${SOURCE.filebase}%s -s ${SOURCE.filebase}.ist -t ${SOURCE.filebase}%s -o ${SOURCE.filebase}%s" % (newglossary_suffix[ig][2],newglossary_suffix[ig][0],newglossary_suffix[ig][1]), "$MAKENEWGLOSSARYCOMSTR")
+ newglfile = suffix_nodes[ng[2]]
+ MakeNewGlossaryAction = SCons.Action.Action(
+ "$MAKENEWGLOSSARYCOM ${SOURCE.filebase}%s -s ${SOURCE.filebase}.ist -t ${SOURCE.filebase}%s -o ${SOURCE.filebase}%s"
+ % (ng[2], ng[0], ng[1]),
+ "$MAKENEWGLOSSARYCOMSTR",
+ )
result = MakeNewGlossaryAction(newglfile, newglfile, env)
if result != 0:
- check_file_error_message('%s (newglossary)' % env['MAKENEWGLOSSARY'],
- newglossary_suffix[ig][0])
+ check_file_error_message(
+ '%s (newglossary)' % env['MAKENEWGLOSSARY'], ng[0]
+ )
return result
# Now decide if latex needs to be run yet again to resolve warnings.
@@ -786,8 +791,8 @@ def tex_emitter_core(target, source, env, graphics_extensions):
file_basename = os.path.join(targetdir, 'bu*.aux')
file_list = glob.glob(file_basename)
# remove the suffix '.aux'
- for i in range(len(file_list)):
- file_list.append(SCons.Util.splitext(file_list[i])[0])
+ for fl in file_list.copy():
+ file_list.append(SCons.Util.splitext(fl)[0])
# for multibib we need a list of files
if suffix_list[-1] == 'multibib':
for multibibmatch in multibib_re.finditer(content):
@@ -797,8 +802,8 @@ def tex_emitter_core(target, source, env, graphics_extensions):
baselist = multibibmatch.group(1).split(',')
if Verbose:
print("multibib list ", baselist)
- for i in range(len(baselist)):
- file_list.append(os.path.join(targetdir, baselist[i]))
+ for bl in baselist:
+ file_list.append(os.path.join(targetdir, bl))
# now define the side effects
for file_name in file_list:
for suffix in suffix_list[:-1]:
diff --git a/SCons/Tool/textfile.py b/SCons/Tool/textfile.py
index bb8a0f9..c1b597f 100644
--- a/SCons/Tool/textfile.py
+++ b/SCons/Tool/textfile.py
@@ -48,8 +48,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons
-import os
-import re
from SCons.Node import Node
from SCons.Node.Python import Value
@@ -76,8 +74,8 @@ def _do_subst(node, subs):
if 'b' in TEXTFILE_FILE_WRITE_MODE:
try:
contents = bytearray(contents, 'utf-8')
- except UnicodeDecodeError:
- # contents is already utf-8 encoded python 2 str i.e. a byte array
+ except TypeError:
+ # TODO: this should not happen, get_text_contents returns text
contents = bytearray(contents)
return contents
diff --git a/SCons/Tool/wixTests.py b/SCons/Tool/wixTests.py
index 6039115..5b255d9 100644
--- a/SCons/Tool/wixTests.py
+++ b/SCons/Tool/wixTests.py
@@ -26,7 +26,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import unittest
import os.path
import os
-import sys
import SCons.Errors
from SCons.Tool.wix import *
diff --git a/SCons/Util.py b/SCons/Util.py
index ae204a1..fae2d64 100644
--- a/SCons/Util.py
+++ b/SCons/Util.py
@@ -1,9 +1,6 @@
-"""SCons.Util
-
-Various utility functions go here.
-"""
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,30 +21,29 @@ Various utility functions go here.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Various SCons utility functions."""
import os
import sys
import copy
import re
-import types
-import codecs
import pprint
import hashlib
from collections import UserDict, UserList, UserString, OrderedDict
from collections.abc import MappingView
+from types import MethodType, FunctionType
PYPY = hasattr(sys, 'pypy_translation_info')
-# Below not used?
-# InstanceType = types.InstanceType
-
-MethodType = types.MethodType
-FunctionType = types.FunctionType
+# this string will be hashed if a Node refers to a file that doesn't exist
+# in order to distinguish from a file that exists but is empty.
+NOFILE = "SCONS_MAGIC_MISSING_FILE_STRING"
-def dictify(keys, values, result={}):
- for k, v in zip(keys, values):
- result[k] = v
+# unused?
+def dictify(keys, values, result=None):
+ if result is None:
+ result = {}
+ result.update(dict(zip(keys, values)))
return result
_altsep = os.altsep
@@ -637,6 +633,41 @@ class Delegate:
else:
return self
+
+class MethodWrapper:
+ """A generic Wrapper class that associates a method with an object.
+
+ As part of creating this MethodWrapper object an attribute with the
+ specified name (by default, the name of the supplied method) is added
+ to the underlying object. When that new "method" is called, our
+ __call__() method adds the object as the first argument, simulating
+ the Python behavior of supplying "self" on method calls.
+
+ We hang on to the name by which the method was added to the underlying
+ base class so that we can provide a method to "clone" ourselves onto
+ a new underlying object being copied (without which we wouldn't need
+ to save that info).
+ """
+ def __init__(self, object, method, name=None):
+ if name is None:
+ name = method.__name__
+ self.object = object
+ self.method = method
+ self.name = name
+ setattr(self.object, name, self)
+
+ def __call__(self, *args, **kwargs):
+ nargs = (self.object,) + args
+ return self.method(*nargs, **kwargs)
+
+ def clone(self, new_object):
+ """
+ Returns an object that re-binds the underlying "method" to
+ the specified new object.
+ """
+ return self.__class__(new_object, self.method, self.name)
+
+
# attempt to load the windows registry module:
can_read_reg = 0
try:
@@ -652,22 +683,9 @@ try:
RegError = winreg.error
except ImportError:
- try:
- import win32api
- import win32con
- can_read_reg = 1
- hkey_mod = win32con
-
- RegOpenKeyEx = win32api.RegOpenKeyEx
- RegEnumKey = win32api.RegEnumKey
- RegEnumValue = win32api.RegEnumValue
- RegQueryValueEx = win32api.RegQueryValueEx
- RegError = win32api.error
-
- except ImportError:
- class _NoError(Exception):
- pass
- RegError = _NoError
+ class _NoError(Exception):
+ pass
+ RegError = _NoError
# Make sure we have a definition of WindowsError so we can
@@ -1113,7 +1131,7 @@ def adjustixes(fname, pre, suf, ensure_suffix=False):
# From Tim Peters,
-# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
+# https://code.activestate.com/recipes/52560
# ASPN: Python Cookbook: Remove duplicates from a sequence
# (Also in the printed Python Cookbook.)
@@ -1187,9 +1205,8 @@ def unique(s):
return u
-
# From Alex Martelli,
-# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560
+# https://code.activestate.com/recipes/52560
# ASPN: Python Cookbook: Remove duplicates from a sequence
# First comment, dated 2001/10/13.
# (Also in the printed Python Cookbook.)
@@ -1392,42 +1409,41 @@ def make_path_relative(path):
return path
-
-# The original idea for AddMethod() and RenameFunction() come from the
+# The original idea for AddMethod() came from the
# following post to the ActiveState Python Cookbook:
#
-# ASPN: Python Cookbook : Install bound methods in an instance
-# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/223613
-#
-# That code was a little fragile, though, so the following changes
-# have been wrung on it:
+# ASPN: Python Cookbook : Install bound methods in an instance
+# https://code.activestate.com/recipes/223613
#
+# Changed as follows:
# * Switched the installmethod() "object" and "function" arguments,
# so the order reflects that the left-hand side is the thing being
# "assigned to" and the right-hand side is the value being assigned.
-#
-# * Changed explicit type-checking to the "try: klass = object.__class__"
-# block in installmethod() below so that it still works with the
-# old-style classes that SCons uses.
-#
-# * Replaced the by-hand creation of methods and functions with use of
-# the "new" module, as alluded to in Alex Martelli's response to the
-# following Cookbook post:
-#
-# ASPN: Python Cookbook : Dynamically added methods to a class
-# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732
+# * The instance/class detection is changed a bit, as it's all
+# new-style classes now with Py3.
+# * The by-hand construction of the function object from renamefunction()
+# is not needed, the remaining bit is now used inline in AddMethod.
def AddMethod(obj, function, name=None):
- """
- Adds either a bound method to an instance or the function itself (or an unbound method in Python 2) to a class.
- If name is ommited the name of the specified function
- is used by default.
+ """Adds a method to an object.
+
+ Adds `function` to `obj` if `obj` is a class object.
+ Adds `function` as a bound method if `obj` is an instance object.
+ If `obj` looks like an environment instance, use `MethodWrapper`
+ to add it. If `name` is supplied it is used as the name of `function`.
+
+ Although this works for any class object, the intent as a public
+ API is to be used on Environment, to be able to add a method to all
+ construction environments; it is preferred to use env.AddMethod
+ to add to an individual environment.
Example::
+ class A:
+ ...
a = A()
def f(self, x, y):
- self.z = x + y
+ self.z = x + y
AddMethod(f, A, "add")
a.add(2, 4)
print(a.z)
@@ -1437,32 +1453,24 @@ def AddMethod(obj, function, name=None):
if name is None:
name = function.__name__
else:
- function = RenameFunction(function, name)
+ # "rename"
+ function = FunctionType(
+ function.__code__, function.__globals__, name, function.__defaults__
+ )
- # Note the Python version checks - WLB
- # Python 3.3 dropped the 3rd parameter from types.MethodType
if hasattr(obj, '__class__') and obj.__class__ is not type:
- # "obj" is an instance, so it gets a bound method.
- if sys.version_info[:2] > (3, 2):
- method = MethodType(function, obj)
+ # obj is an instance, so it gets a bound method.
+ if hasattr(obj, "added_methods"):
+ method = MethodWrapper(obj, function, name)
+ obj.added_methods.append(method)
else:
- method = MethodType(function, obj, obj.__class__)
+ method = MethodType(function, obj)
else:
- # Handle classes
+ # obj is a class
method = function
setattr(obj, name, method)
-def RenameFunction(function, name):
- """
- Returns a function identical to the specified function, but with
- the specified name.
- """
- return FunctionType(function.__code__,
- function.__globals__,
- name,
- function.__defaults__)
-
if hasattr(hashlib, 'md5'):
md5 = True
@@ -1540,8 +1548,7 @@ def silent_intern(x):
# From Dinu C. Gherman,
# Python Cookbook, second edition, recipe 6.17, p. 277.
-# Also:
-# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/68205
+# Also: https://code.activestate.com/recipes/68205
# ASPN: Python Cookbook: Null Object Design Pattern
class Null:
@@ -1582,9 +1589,6 @@ class NullSeq(Null):
return self
-del __revision__
-
-
def to_bytes(s):
if s is None:
return b'None'
diff --git a/SCons/UtilTests.py b/SCons/UtilTests.py
index c831108..72bbaf3 100644
--- a/SCons/UtilTests.py
+++ b/SCons/UtilTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -195,11 +193,7 @@ class UtilTestCase(unittest.TestCase):
try:
node, expect, withtags = self.tree_case_1()
- if sys.version_info.major < 3:
- IOStream = io.BytesIO
- else:
- IOStream = io.StringIO
-
+ IOStream = io.StringIO
sys.stdout = IOStream()
print_tree(node, get_children)
actual = sys.stdout.getvalue()
@@ -251,11 +245,6 @@ class UtilTestCase(unittest.TestCase):
def test_is_Dict(self):
assert is_Dict({})
assert is_Dict(UserDict())
-
- # os.environ is not a dictionary in python 3
- if sys.version_info < (3, 0):
- assert is_Dict(os.environ)
-
try:
class mydict(dict):
pass
diff --git a/SCons/Utilities/ConfigureCache.py b/SCons/Utilities/ConfigureCache.py
index 08faeae..67aac3c 100644
--- a/SCons/Utilities/ConfigureCache.py
+++ b/SCons/Utilities/ConfigureCache.py
@@ -2,7 +2,9 @@
#
# SCons - a Software Constructor
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -166,4 +168,4 @@ def main():
json.dump(config, conf)
if __name__ == "__main__":
- main() \ No newline at end of file
+ main()
diff --git a/SCons/Utilities/sconsign.py b/SCons/Utilities/sconsign.py
index 76a8233..e595b2d 100644
--- a/SCons/Utilities/sconsign.py
+++ b/SCons/Utilities/sconsign.py
@@ -2,7 +2,9 @@
#
# SCons - a Software Constructor
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -23,6 +25,8 @@
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+"""Utility script to dump information from SCons signature database."""
+
import getopt
import os
import sys
@@ -94,11 +98,6 @@ def default_mapper(entry, name):
val = eval("entry." + name)
except AttributeError:
val = None
- if sys.version_info.major >= 3 and isinstance(val, bytes):
- # This is a dirty hack for py 2/3 compatibility. csig is a bytes object
- # in Python3 while Python2 bytes are str. Hence, we decode the csig to a
- # Python3 string
- val = val.decode()
return str(val)
@@ -323,8 +322,8 @@ class Do_SConsignDB:
sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n"
% (self.dbm_name, fname, e))
exc_type, _, _ = sys.exc_info()
- if exc_type.__name__ == "ValueError" and sys.version_info < (3,0,0):
- sys.stderr.write("Python 2 only supports pickle protocols 0-2.\n")
+ if exc_type.__name__ == "ValueError":
+ sys.stderr.write("unrecognized pickle protocol.\n")
return
if Print_Directories:
@@ -432,7 +431,7 @@ def main():
# Ensure that we don't ignore corrupt DB files,
# this was handled by calling my_import('SCons.dblite')
# again in earlier versions...
- SCons.dblite.ignore_corrupt_dbfiles = 0
+ SCons.dblite.IGNORE_CORRUPT_DBFILES = False
except ImportError:
sys.stderr.write("sconsign: illegal file format `%s'\n" % a)
print(helpstr)
@@ -475,7 +474,7 @@ def main():
# Ensure that we don't ignore corrupt DB files,
# this was handled by calling my_import('SCons.dblite')
# again in earlier versions...
- SCons.dblite.ignore_corrupt_dbfiles = 0
+ SCons.dblite.IGNORE_CORRUPT_DBFILES = False
Do_SConsignDB(Map_Module.get(dbm_name, dbm_name), dbm)(a)
else:
Do_SConsignDir(a)
diff --git a/SCons/Variables/BoolVariable.py b/SCons/Variables/BoolVariable.py
index 9c66cde..6d9ff72 100644
--- a/SCons/Variables/BoolVariable.py
+++ b/SCons/Variables/BoolVariable.py
@@ -1,18 +1,6 @@
-"""SCons.Variables.BoolVariable
-
-This file defines the option type for SCons implementing true/false values.
-
-Usage example::
-
- opts = Variables()
- opts.Add(BoolVariable('embedded', 'build for an embedded system', 0))
- ...
- if env['embedded'] == 1:
- ...
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -32,9 +20,17 @@ Usage example::
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Option type for true/false Variables.
+
+Usage example::
+
+ opts = Variables()
+ opts.Add(BoolVariable('embedded', 'build for an embedded system', 0))
+ ...
+ if env['embedded'] == 1:
+ ...
+"""
__all__ = ['BoolVariable',]
diff --git a/SCons/Variables/BoolVariableTests.py b/SCons/Variables/BoolVariableTests.py
index 3184407..e486e4b 100644
--- a/SCons/Variables/BoolVariableTests.py
+++ b/SCons/Variables/BoolVariableTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,7 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import unittest
import SCons.Errors
diff --git a/SCons/Variables/EnumVariable.py b/SCons/Variables/EnumVariable.py
index 8053503..6e0a8c5 100644
--- a/SCons/Variables/EnumVariable.py
+++ b/SCons/Variables/EnumVariable.py
@@ -1,21 +1,6 @@
-"""SCons.Variables.EnumVariable
-
-This file defines the option type for SCons allowing only specified
-input-values.
-
-Usage example::
-
- opts = Variables()
- opts.Add(EnumVariable('debug', 'debug output and symbols', 'no',
- allowed_values=('yes', 'no', 'full'),
- map={}, ignorecase=2))
- ...
- if env['debug'] == 'full':
- ...
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,9 +20,30 @@ Usage example::
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Option type for enumeration Variables.
+
+This file defines the option type for SCons allowing only specified
+input-values.
+
+Usage example::
+
+ opts = Variables()
+ opts.Add(
+ EnumVariable(
+ 'debug',
+ 'debug output and symbols',
+ 'no',
+ allowed_values=('yes', 'no', 'full'),
+ map={},
+ ignorecase=2,
+ )
+ )
+ ...
+ if env['debug'] == 'full':
+ ...
+"""
+
__all__ = ['EnumVariable',]
diff --git a/SCons/Variables/EnumVariableTests.py b/SCons/Variables/EnumVariableTests.py
index 4ecb8bd..75bb54f 100644
--- a/SCons/Variables/EnumVariableTests.py
+++ b/SCons/Variables/EnumVariableTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,7 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import unittest
import SCons.Errors
diff --git a/SCons/Variables/ListVariable.py b/SCons/Variables/ListVariable.py
index 7ebbb23..c615258 100644
--- a/SCons/Variables/ListVariable.py
+++ b/SCons/Variables/ListVariable.py
@@ -1,31 +1,6 @@
-"""SCons.Variables.ListVariable
-
-This file defines the option type for SCons implementing 'lists'.
-
-A 'list' option may either be 'all', 'none' or a list of names
-separated by comma. After the option has been processed, the option
-value holds either the named list elements, all list elements or no
-list elements at all.
-
-Usage example::
-
- list_of_libs = Split('x11 gl qt ical')
-
- opts = Variables()
- opts.Add(ListVariable('shared',
- 'libraries to build as shared libraries',
- 'all',
- elems = list_of_libs))
- ...
- for lib in list_of_libs:
- if lib in env['shared']:
- env.SharedObject(...)
- else:
- env.Object(...)
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -46,7 +21,35 @@ Usage example::
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Option type for list Variables.
+
+This file defines the option type for SCons implementing 'lists'.
+
+A 'list' option may either be 'all', 'none' or a list of names
+separated by comma. After the option has been processed, the option
+value holds either the named list elements, all list elements or no
+list elements at all.
+
+Usage example::
+
+ list_of_libs = Split('x11 gl qt ical')
+
+ opts = Variables()
+ opts.Add(
+ ListVariable(
+ 'shared',
+ 'libraries to build as shared libraries',
+ 'all',
+ elems=list_of_libs,
+ )
+ )
+ ...
+ for lib in list_of_libs:
+ if lib in env['shared']:
+ env.SharedObject(...)
+ else:
+ env.Object(...)
+"""
# Known Bug: This should behave like a Set-Type, but does not really,
# since elements can occur twice.
diff --git a/SCons/Variables/ListVariableTests.py b/SCons/Variables/ListVariableTests.py
index 8f79e07..c73cef3 100644
--- a/SCons/Variables/ListVariableTests.py
+++ b/SCons/Variables/ListVariableTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import copy
-import sys
import unittest
import SCons.Errors
diff --git a/SCons/Variables/PackageVariable.py b/SCons/Variables/PackageVariable.py
index 6847f3d..d4dafd5 100644
--- a/SCons/Variables/PackageVariable.py
+++ b/SCons/Variables/PackageVariable.py
@@ -1,7 +1,29 @@
-"""SCons.Variables.PackageVariable
+# MIT License
+#
+# Copyright 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.
+
+"""Option type for package Variables.
-This file defines the option type for SCons implementing 'package
-activation'.
+This file defines the option type for SCons implementing 'package activation'.
To be used whenever a 'package' may be enabled/disabled and the
package path may be specified.
@@ -15,6 +37,7 @@ Usage example:
To replace autoconf's --with-xxx=yyy ::
+
opts = Variables()
opts.Add(PackageVariable('x11',
'use X11 installed here (yes = search some places',
@@ -27,31 +50,6 @@ Usage example:
... build with x11 ...
"""
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
__all__ = ['PackageVariable',]
import SCons.Errors
diff --git a/SCons/Variables/PackageVariableTests.py b/SCons/Variables/PackageVariableTests.py
index a7e6b0d..988fbe0 100644
--- a/SCons/Variables/PackageVariableTests.py
+++ b/SCons/Variables/PackageVariableTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,7 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import unittest
import SCons.Errors
diff --git a/SCons/Variables/PathVariable.py b/SCons/Variables/PathVariable.py
index c0ebb18..081872b 100644
--- a/SCons/Variables/PathVariable.py
+++ b/SCons/Variables/PathVariable.py
@@ -1,4 +1,27 @@
-"""SCons.Variables.PathVariable
+# MIT License
+#
+# Copyright 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.
+
+"""Option type for path Variables.
This file defines an option type for SCons implementing path settings.
@@ -8,21 +31,18 @@ Arguments to PathVariable are:
option-name = name of this option on the command line (e.g. "prefix")
option-help = help string for option
option-dflt = default value for this option
- validator = [optional] validator for option value. Predefined validators are:
-
- PathAccept -- accepts any path setting; no validation
- PathIsDir -- path must be an existing directory
- PathIsDirCreate -- path must be a dir; will create
- PathIsFile -- path must be a file
- PathExists -- path must exist (any type) [default]
-
- The validator is a function that is called and which
- should return True or False to indicate if the path
- is valid. The arguments to the validator function
- are: (key, val, env). The key is the name of the
- option, the val is the path specified for the option,
- and the env is the env to which the Options have been
- added.
+ validator = [optional] validator for option value. Predefined are:
+ PathAccept -- accepts any path setting; no validation
+ PathIsDir -- path must be an existing directory
+ PathIsDirCreate -- path must be a dir; will create
+ PathIsFile -- path must be a file
+ PathExists -- path must exist (any type) [default]
+
+ The validator is a function that is called and which should return
+ True or False to indicate if the path is valid. The arguments
+ to the validator function are: (key, val, env). The key is the
+ name of the option, the val is the path specified for the option,
+ and the env is the env to which the Options have been added.
Usage example::
@@ -41,34 +61,8 @@ Usage example::
opts.Add(PathVariable('qt_libraries',
'where the Qt library is installed',
'$qtdir/lib'))
-
"""
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
__all__ = ['PathVariable',]
import os
diff --git a/SCons/Variables/PathVariableTests.py b/SCons/Variables/PathVariableTests.py
index 48ad0e0..6e3a70b 100644
--- a/SCons/Variables/PathVariableTests.py
+++ b/SCons/Variables/PathVariableTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,12 +20,8 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
-import sys
import unittest
import SCons.Errors
diff --git a/SCons/Variables/VariablesTests.py b/SCons/Variables/VariablesTests.py
index 93866e0..768f88e 100644
--- a/SCons/Variables/VariablesTests.py
+++ b/SCons/Variables/VariablesTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,7 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import unittest
import TestSCons
diff --git a/SCons/Variables/__init__.py b/SCons/Variables/__init__.py
index f7531b4..2c32310 100644
--- a/SCons/Variables/__init__.py
+++ b/SCons/Variables/__init__.py
@@ -1,11 +1,6 @@
-"""SCons.Variables
-
-This file defines the Variables class that is used to add user-friendly
-customizable variables to an SCons build.
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -26,7 +21,7 @@ customizable variables to an SCons build.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Add user-friendly customizable variables to an SCons build. """
import os.path
import sys
diff --git a/SCons/Warnings.py b/SCons/Warnings.py
index b5ce52e..198c6ae 100644
--- a/SCons/Warnings.py
+++ b/SCons/Warnings.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,15 +20,8 @@
# 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.
-#
-
-"""SCons.Warnings
-
-This file implements the warnings framework for SCons.
-
-"""
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""The SCons warnings framework."""
import sys
diff --git a/SCons/WarningsTests.py b/SCons/WarningsTests.py
index e4720eb..c22b049 100644
--- a/SCons/WarningsTests.py
+++ b/SCons/WarningsTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,11 +20,7 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import unittest
import SCons.Warnings
diff --git a/SCons/__init__.py b/SCons/__init__.py
index f3d3851..fcd665e 100644
--- a/SCons/__init__.py
+++ b/SCons/__init__.py
@@ -1,9 +1,9 @@
-__version__="4.0.1"
+__version__="4.0.1.9998"
__copyright__="Copyright (c) 2001 - 2020 The SCons Foundation"
__developer__="bdbaddog"
-__date__="2020-07-17 01:50:03"
+__date__="2020-10-09 19:00:35"
__buildsys__="ProDog2020"
-__revision__="c289977f8b34786ab6c334311e232886da7e8df1"
-__build__="c289977f8b34786ab6c334311e232886da7e8df1"
+__revision__="93525bed88d19a00f5de400086c0046011d3b833"
+__build__="93525bed88d19a00f5de400086c0046011d3b833"
# make sure compatibility is always in place
import SCons.compat # noqa \ No newline at end of file
diff --git a/SCons/__main__.py b/SCons/__main__.py
index 0dfbb9d..67120c8 100644
--- a/SCons/__main__.py
+++ b/SCons/__main__.py
@@ -1,3 +1,26 @@
+# MIT License
+#
+# Copyright 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.
+
import SCons.Script
# this does all the work, and calls sys.exit
# with the proper exit status when done.
diff --git a/SCons/compat/__init__.py b/SCons/compat/__init__.py
index 9fb4898..03b12af 100644
--- a/SCons/compat/__init__.py
+++ b/SCons/compat/__init__.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,21 +20,21 @@
# 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.
-#
-__doc__ = """
-SCons compatibility package for old Python versions
+"""SCons compatibility package for old Python versions
This subpackage holds modules that provide backwards-compatible
-implementations of various things that we'd like to use in SCons but which
-only show up in later versions of Python than the early, old version(s)
-we still support.
+implementations of various things from newer Python versions
+that we cannot count on because SCons still supported older Pythons.
Other code will not generally reference things in this package through
the SCons.compat namespace. The modules included here add things to
the builtins namespace or the global module list so that the rest
of our code can use the objects and names imported here regardless of
-Python version.
+Python version. As a result, if this module is used, it should violate
+the normal convention for imports (standard library imports first,
+then program-specific imports, each ordered aplhabetically)
+and needs to be listed first.
The rest of the things here will be in individual compatibility modules
that are either: 1) suitably modified copies of the future modules that
@@ -57,9 +58,6 @@ function defined below loads the module as the "real" name (without the
rest of our code will find our pre-loaded compatibility module.
"""
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import os
import sys
import importlib
@@ -81,22 +79,12 @@ def rename_module(new, old):
# Default pickle protocol. Higher protocols are more efficient/featured
# but incompatible with older Python versions.
# Negative numbers choose the highest available protocol.
-import pickle
# Was pickle.HIGHEST_PROTOCOL
# Changed to 4 so that python 3.8's not incompatible with previous versions
# Python 3.8 introduced protocol 5 which is mainly an improvement for for out-of-band data buffers
PICKLE_PROTOCOL = 4
-import shutil
-try:
- shutil.SameFileError
-except AttributeError:
- class SameFileError(Exception):
- pass
-
- shutil.SameFileError = SameFileError
-
class NoSlotsPyPy(type):
""" Metaclass for PyPy compatitbility.
diff --git a/SCons/compat/_scons_dbm.py b/SCons/compat/_scons_dbm.py
index edfe6fd..72e5d6a 100644
--- a/SCons/compat/_scons_dbm.py
+++ b/SCons/compat/_scons_dbm.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,10 +20,8 @@
# 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.
-#
-__doc__ = """
-dbm compatibility module for Python versions that don't have dbm.
+"""dbm compatibility module for Python versions that don't have dbm.
This does not not NOT (repeat, *NOT*) provide complete dbm functionality.
It's just a stub on which to hang just enough pieces of dbm functionality
@@ -30,8 +29,6 @@ that the whichdb.whichdb() implementstation in the various 2.X versions of
Python won't blow up even if dbm wasn't compiled in.
"""
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
class error(Exception):
pass
diff --git a/SCons/compat/win32.py b/SCons/compat/win32.py
new file mode 100644
index 0000000..e01adfa
--- /dev/null
+++ b/SCons/compat/win32.py
@@ -0,0 +1,101 @@
+# MIT License
+#
+# Copyright 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.
+"""Logic to replicate parts of pywin32 SCons uses."""
+
+__all__ = ['get_current_process', 'get_memory_info', 'get_memory_usage', 'get_peak_memory_usage']
+
+import ctypes
+from ctypes import wintypes
+
+#
+# From Activestate Recipe
+# https://code.activestate.com/recipes/578513-get-memory-usage-of-windows-processes-using-getpro/
+# MIT licensed
+#
+GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess
+GetCurrentProcess.argtypes = []
+GetCurrentProcess.restype = wintypes.HANDLE
+
+SIZE_T = ctypes.c_size_t
+
+
+class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure):
+ _fields_ = [
+ ('cb', wintypes.DWORD),
+ ('PageFaultCount', wintypes.DWORD),
+ ('PeakWorkingSetSize', SIZE_T),
+ ('WorkingSetSize', SIZE_T),
+ ('QuotaPeakPagedPoolUsage', SIZE_T),
+ ('QuotaPagedPoolUsage', SIZE_T),
+ ('QuotaPeakNonPagedPoolUsage', SIZE_T),
+ ('QuotaNonPagedPoolUsage', SIZE_T),
+ ('PagefileUsage', SIZE_T),
+ ('PeakPagefileUsage', SIZE_T),
+ ('PrivateUsage', SIZE_T),
+ ]
+
+
+GetProcessMemoryInfo = ctypes.windll.psapi.GetProcessMemoryInfo
+GetProcessMemoryInfo.argtypes = [
+ wintypes.HANDLE,
+ ctypes.POINTER(PROCESS_MEMORY_COUNTERS_EX),
+ wintypes.DWORD,
+]
+GetProcessMemoryInfo.restype = wintypes.BOOL
+
+
+def get_current_process():
+ """Return handle to current process."""
+ return GetCurrentProcess()
+
+
+def get_memory_info(process=None):
+ """Return Win32 process memory counters structure as a dict."""
+ if process is None:
+ process = get_current_process()
+ counters = PROCESS_MEMORY_COUNTERS_EX()
+ ret = GetProcessMemoryInfo(process, ctypes.byref(counters),
+ ctypes.sizeof(counters))
+ if not ret:
+ raise ctypes.WinError()
+ info = dict((name, getattr(counters, name))
+ for name, _ in counters._fields_)
+ return info
+
+
+def get_memory_usage(process=None):
+ """Return this process's memory usage in bytes."""
+ info = get_memory_info(process=process)
+ return info['PrivateUsage']
+
+
+def get_peak_memory_usage(process=None):
+ """Return this process's memory usage in bytes."""
+ info = get_memory_info(process=process)
+ return info['PeakWorkingSetSize']
+
+
+if __name__ == '__main__':
+ import pprint
+
+ pprint.pprint(get_memory_info())
diff --git a/SCons/cpp.py b/SCons/cpp.py
index 0811c71..65358b3 100644
--- a/SCons/cpp.py
+++ b/SCons/cpp.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,13 +20,9 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""SCons C Pre-Processor module"""
-__doc__ = """
-SCons C Pre-Processor module
-"""
import SCons.compat
import os
@@ -651,8 +648,6 @@ class DumbPreProcessor(PreProcessor):
for func in ['if', 'elif', 'else', 'endif', 'ifdef', 'ifndef']:
d[func] = d[func] = self.do_nothing
-del __revision__
-
# Local Variables:
# tab-width:4
# indent-tabs-mode:nil
diff --git a/SCons/cppTests.py b/SCons/cppTests.py
index 22a5c81..c19046c 100644
--- a/SCons/cppTests.py
+++ b/SCons/cppTests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,8 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import atexit
import unittest
@@ -30,7 +29,6 @@ import TestUnit
import cpp
-
basic_input = """
#include "file1-yes"
#include <file2-yes>
diff --git a/SCons/dblite.py b/SCons/dblite.py
index 338dcc7..a5186ca 100644
--- a/SCons/dblite.py
+++ b/SCons/dblite.py
@@ -1,3 +1,26 @@
+# MIT License
+#
+# Copyright 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.
+
"""
dblite.py module contributed by Ralf W. Grosse-Kunstleve.
Extended for Unicode by Steven Knight.
@@ -10,20 +33,20 @@ import time
from SCons.compat import PICKLE_PROTOCOL
-keep_all_files = 00000
-ignore_corrupt_dbfiles = 0
+KEEP_ALL_FILES = False
+IGNORE_CORRUPT_DBFILES = False
def corruption_warning(filename):
- print("Warning: Discarding corrupt database:", filename)
+ """Local warning for corrupt db.
+ Used for self-tests. SCons overwrites this with a
+ different warning function in SConsign.py.
+ """
+ print("Warning: Discarding corrupt database:", filename)
-dblite_suffix = '.dblite'
-
-# TODO: Does commenting this out break switching from py2/3?
-# if bytes is not str:
-# dblite_suffix += '.p3'
-tmp_suffix = '.tmp'
+DBLITE_SUFFIX = '.dblite'
+TMP_SUFFIX = '.tmp'
class dblite:
@@ -43,15 +66,13 @@ class dblite:
_open = open
_pickle_dump = staticmethod(pickle.dump)
_pickle_protocol = PICKLE_PROTOCOL
- _os_chmod = os.chmod
try:
_os_chown = os.chown
except AttributeError:
_os_chown = None
-
- _os_rename = os.rename
- _os_unlink = os.unlink
+ _os_replace = os.replace
+ _os_chmod = os.chmod
_shutil_copyfile = shutil.copyfile
_time_time = time.time
@@ -61,18 +82,18 @@ class dblite:
flag = "r"
base, ext = os.path.splitext(file_base_name)
- if ext == dblite_suffix:
+ if ext == DBLITE_SUFFIX:
# There's already a suffix on the file name, don't add one.
self._file_name = file_base_name
- self._tmp_name = base + tmp_suffix
+ self._tmp_name = base + TMP_SUFFIX
else:
- self._file_name = file_base_name + dblite_suffix
- self._tmp_name = file_base_name + tmp_suffix
+ self._file_name = file_base_name + DBLITE_SUFFIX
+ self._tmp_name = file_base_name + TMP_SUFFIX
self._flag = flag
self._mode = mode
self._dict = {}
- self._needs_sync = 00000
+ self._needs_sync = False
if self._os_chown is not None and (os.geteuid() == 0 or os.getuid() == 0):
# running as root; chown back to current owner/group when done
@@ -80,7 +101,7 @@ class dblite:
statinfo = os.stat(self._file_name)
self._chown_to = statinfo.st_uid
self._chgrp_to = statinfo.st_gid
- except OSError as e:
+ except OSError:
# db file doesn't exist yet.
# Check os.environ for SUDO_UID, use if set
self._chown_to = int(os.environ.get('SUDO_UID', -1))
@@ -105,15 +126,12 @@ class dblite:
f.close()
if len(p) > 0:
try:
- if bytes is not str:
- self._dict = pickle.loads(p, encoding='bytes')
- else:
- self._dict = pickle.loads(p)
+ self._dict = pickle.loads(p, encoding='bytes')
except (pickle.UnpicklingError, EOFError, KeyError):
# Note how we catch KeyErrors too here, which might happen
# when we don't have cPickle available (default pickle
# throws it).
- if ignore_corrupt_dbfiles:
+ if IGNORE_CORRUPT_DBFILES:
corruption_warning(self._file_name)
else:
raise
@@ -127,32 +145,35 @@ class dblite:
def sync(self):
self._check_writable()
- f = self._open(self._tmp_name, "wb", self._mode)
- self._pickle_dump(self._dict, f, self._pickle_protocol)
- f.close()
-
- # Windows doesn't allow renaming if the file exists, so unlink
- # it first, chmod'ing it to make sure we can do so. On UNIX, we
- # may not be able to chmod the file if it's owned by someone else
- # (e.g. from a previous run as root). We should still be able to
- # unlink() the file if the directory's writable, though, so ignore
- # any OSError exception thrown by the chmod() call.
+ with self._open(self._tmp_name, "wb", self._mode) as f:
+ self._pickle_dump(self._dict, f, self._pickle_protocol)
+
try:
- self._os_chmod(self._file_name, 0o777)
- except OSError:
- pass
- self._os_unlink(self._file_name)
- self._os_rename(self._tmp_name, self._file_name)
+ self._os_replace(self._tmp_name, self._file_name)
+ except PermissionError:
+ # If we couldn't replace due to perms, try to change and retry.
+ # This is mainly for Windows - on POSIX the file permissions
+ # don't matter, the os.replace would have worked anyway.
+ # We're giving up if the retry fails, just let the Python
+ # exception abort us.
+ try:
+ self._os_chmod(self._file_name, 0o777)
+ except PermissionError:
+ pass
+ self._os_replace(self._tmp_name, self._file_name)
+
if self._os_chown is not None and self._chown_to > 0: # don't chown to root or -1
try:
self._os_chown(self._file_name, self._chown_to, self._chgrp_to)
except OSError:
pass
- self._needs_sync = 00000
- if keep_all_files:
+
+ self._needs_sync = False
+ if KEEP_ALL_FILES:
self._shutil_copyfile(
self._file_name,
- self._file_name + "_" + str(int(self._time_time())))
+ self._file_name + "_" + str(int(self._time_time()))
+ )
def _check_writable(self):
if self._flag == "r":
@@ -171,7 +192,7 @@ class dblite:
raise TypeError("value `%s' must be a bytes but is %s" % (value, type(value)))
self._dict[key] = value
- self._needs_sync = 0o001
+ self._needs_sync = True
def keys(self):
return list(self._dict.keys())
@@ -182,11 +203,8 @@ class dblite:
def __contains__(self, key):
return key in self._dict
- def iterkeys(self):
- # Wrapping name in () prevents fixer from "fixing" this
- return (self._dict.iterkeys)()
-
- __iter__ = iterkeys
+ def __iter__(self):
+ return iter(self._dict)
def __len__(self):
return len(self._dict)
@@ -255,8 +273,8 @@ def _exercise():
else:
raise RuntimeError("pickle exception expected.")
- global ignore_corrupt_dbfiles
- ignore_corrupt_dbfiles = 2
+ global IGNORE_CORRUPT_DBFILES
+ IGNORE_CORRUPT_DBFILES = True
db = open("tmp", "r")
assert len(db) == 0, len(db)
os.unlink("tmp.dblite")
diff --git a/SCons/exitfuncs.py b/SCons/exitfuncs.py
index 7d00df7..ba6243a 100644
--- a/SCons/exitfuncs.py
+++ b/SCons/exitfuncs.py
@@ -1,11 +1,6 @@
-"""SCons.exitfuncs
-
-Register functions which are executed when SCons exits for any reason.
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,10 +20,10 @@ Register functions which are executed when SCons exits for any reason.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""Register functions which are executed when SCons exits for any reason."""
+# This is obsolete now
import atexit
diff --git a/SConstruct b/SConstruct
index 2cd2fde..27235ad 100644
--- a/SConstruct
+++ b/SConstruct
@@ -12,7 +12,9 @@ copyright_years = strftime('2001 - %Y')
# This gets inserted into the man pages to reflect the month of release.
month_year = strftime('%B %Y')
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -36,7 +38,7 @@ month_year = strftime('%B %Y')
project = 'scons'
-default_version = '4.0.1'
+default_version = '4.0.1.9998'
copyright = "Copyright (c) %s The SCons Foundation" % copyright_years
#
@@ -193,14 +195,21 @@ Export('command_line', 'env', 'whereis', 'revaction')
SConscript('doc/SConscript')
+# Copy manpage's into base dir for inclusign in pypi packages
+man_pages = env.Install("#/", Glob("#/build/doc/man/*.1"))
+
# Build packages for pypi
-env.Command('$DISTDIR/SCons-${VERSION}-py3-none-any.whl', ['setup.cfg', 'setup.py', 'SCons/__init__.py'],
+wheel = env.Command('$DISTDIR/SCons-${VERSION}-py3-none-any.whl', ['setup.cfg', 'setup.py', 'SCons/__init__.py']+man_pages,
'$PYTHON setup.py bdist_wheel')
-env.Command('$DISTDIR/SCons-${VERSION}.zip', ['setup.cfg', 'setup.py', 'SCons/__init__.py'],
+zip_file = env.Command('$DISTDIR/SCons-${VERSION}.zip', ['setup.cfg', 'setup.py', 'SCons/__init__.py']+man_pages,
'$PYTHON setup.py sdist --format=zip')
-env.Command('$DISTDIR/SCons-${VERSION}.tar.gz', ['setup.cfg', 'setup.py', 'SCons/__init__.py'],
+tgz_file = env.Command('$DISTDIR/SCons-${VERSION}.tar.gz', ['setup.cfg', 'setup.py', 'SCons/__init__.py']+man_pages,
'$PYTHON setup.py sdist --format=gztar')
+# Now set depends so the above run in a particular order
+env.Depends(tgz_file, [zip_file, wheel])
+env.AddPostAction(tgz_file, Delete(man_pages))
+
# TODO add auto copyright date to README.rst, LICENSE
# TODO build API DOCS
diff --git a/doc/generated/examples/builderscommands_ex5_1.xml b/doc/generated/examples/builderscommands_ex5_1.xml
new file mode 100644
index 0000000..67659c1
--- /dev/null
+++ b/doc/generated/examples/builderscommands_ex5_1.xml
@@ -0,0 +1,3 @@
+<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput>
+Building foo.out
+</screen>
diff --git a/doc/generated/examples/commandline_BoolVariable_5.xml b/doc/generated/examples/commandline_BoolVariable_5.xml
index e232588..3cd75e9 100644
--- a/doc/generated/examples/commandline_BoolVariable_5.xml
+++ b/doc/generated/examples/commandline_BoolVariable_5.xml
@@ -2,5 +2,5 @@
scons: *** Error converting option: RELEASE
Invalid value for boolean option: bad_value
-File "/home/my/project/SConstruct", line 5, in &lt;module&gt;
+File "/home/my/project/SConstruct", line 3, in &lt;module&gt;
</screen>
diff --git a/doc/generated/examples/commandline_EnumVariable_2.xml b/doc/generated/examples/commandline_EnumVariable_2.xml
index 51a5462..8856d29 100644
--- a/doc/generated/examples/commandline_EnumVariable_2.xml
+++ b/doc/generated/examples/commandline_EnumVariable_2.xml
@@ -1,5 +1,5 @@
<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q COLOR=magenta foo.o</userinput>
scons: *** Invalid value for option COLOR: magenta. Valid values are: ('red', 'green', 'blue')
-File "/home/my/project/SConstruct", line 6, in &lt;module&gt;
+File "/home/my/project/SConstruct", line 10, in &lt;module&gt;
</screen>
diff --git a/doc/generated/examples/commandline_EnumVariable_4.xml b/doc/generated/examples/commandline_EnumVariable_4.xml
index d1aca84..3e73c5b 100644
--- a/doc/generated/examples/commandline_EnumVariable_4.xml
+++ b/doc/generated/examples/commandline_EnumVariable_4.xml
@@ -1,13 +1,13 @@
<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q COLOR=Red foo.o</userinput>
scons: *** Invalid value for option COLOR: Red. Valid values are: ('red', 'green', 'blue')
-File "/home/my/project/SConstruct", line 6, in &lt;module&gt;
+File "/home/my/project/SConstruct", line 10, in &lt;module&gt;
% <userinput>scons -Q COLOR=BLUE foo.o</userinput>
scons: *** Invalid value for option COLOR: BLUE. Valid values are: ('red', 'green', 'blue')
-File "/home/my/project/SConstruct", line 6, in &lt;module&gt;
+File "/home/my/project/SConstruct", line 10, in &lt;module&gt;
% <userinput>scons -Q COLOR=nAvY foo.o</userinput>
scons: *** Invalid value for option COLOR: nAvY. Valid values are: ('red', 'green', 'blue')
-File "/home/my/project/SConstruct", line 6, in &lt;module&gt;
+File "/home/my/project/SConstruct", line 10, in &lt;module&gt;
</screen>
diff --git a/doc/generated/examples/commandline_ListVariable_3.xml b/doc/generated/examples/commandline_ListVariable_3.xml
index 7a8c857..11936ab 100644
--- a/doc/generated/examples/commandline_ListVariable_3.xml
+++ b/doc/generated/examples/commandline_ListVariable_3.xml
@@ -2,5 +2,5 @@
scons: *** Error converting option: COLORS
Invalid value(s) for option: magenta
-File "/home/my/project/SConstruct", line 6, in &lt;module&gt;
+File "/home/my/project/SConstruct", line 7, in &lt;module&gt;
</screen>
diff --git a/doc/generated/examples/commandline_ListVariable_4.xml b/doc/generated/examples/commandline_ListVariable_4.xml
new file mode 100644
index 0000000..d464c48
--- /dev/null
+++ b/doc/generated/examples/commandline_ListVariable_4.xml
@@ -0,0 +1,6 @@
+<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q foo.o</userinput>
+
+scons: *** Error converting option: COLORS
+Invalid value(s) for option: 0
+File "/home/my/project/SConstruct", line 7, in &lt;module&gt;
+</screen>
diff --git a/doc/generated/examples/commandline_PathVariable_2.xml b/doc/generated/examples/commandline_PathVariable_2.xml
index d2ce952..156702a 100644
--- a/doc/generated/examples/commandline_PathVariable_2.xml
+++ b/doc/generated/examples/commandline_PathVariable_2.xml
@@ -1,5 +1,5 @@
<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q CONFIG=/does/not/exist foo.o</userinput>
scons: *** Path for option CONFIG does not exist: /does/not/exist
-File "/home/my/project/SConstruct", line 5, in &lt;module&gt;
+File "/home/my/project/SConstruct", line 7, in &lt;module&gt;
</screen>
diff --git a/doc/generated/examples/commandline_UnknownVariables_1.xml b/doc/generated/examples/commandline_UnknownVariables_1.xml
index 08c566c..6725c47 100644
--- a/doc/generated/examples/commandline_UnknownVariables_1.xml
+++ b/doc/generated/examples/commandline_UnknownVariables_1.xml
@@ -1,3 +1,3 @@
<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q NOT_KNOWN=foo</userinput>
-Unknown variables: dict_keys(['NOT_KNOWN'])
+Unknown variables: NOT_KNOWN
</screen>
diff --git a/doc/generated/examples/separate_ex1_1.xml b/doc/generated/examples/separate_ex1_1.xml
index 6efc16f..803bc4f 100644
--- a/doc/generated/examples/separate_ex1_1.xml
+++ b/doc/generated/examples/separate_ex1_1.xml
@@ -3,6 +3,8 @@ SConscript hello.c
% <userinput>scons -Q</userinput>
cc -o build/hello.o -c build/hello.c
cc -o build/hello build/hello.o
+% <userinput>ls src</userinput>
+SConscript hello.c
% <userinput>ls build</userinput>
SConscript hello hello.c hello.o
</screen>
diff --git a/doc/generated/examples/sideeffect_simple2_1.xml b/doc/generated/examples/sideeffect_simple2_1.xml
new file mode 100644
index 0000000..f60625b
--- /dev/null
+++ b/doc/generated/examples/sideeffect_simple2_1.xml
@@ -0,0 +1,4 @@
+<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput>
+echo &gt; file1 data1; echo &gt;log updated file1
+Copy("file2", "log")
+</screen>
diff --git a/doc/generated/examples/sideeffect_simple_1.xml b/doc/generated/examples/sideeffect_simple_1.xml
index cc94830..f60625b 100644
--- a/doc/generated/examples/sideeffect_simple_1.xml
+++ b/doc/generated/examples/sideeffect_simple_1.xml
@@ -1,4 +1,4 @@
-<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q --jobs=2</userinput>
+<screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput>
echo &gt; file1 data1; echo &gt;log updated file1
Copy("file2", "log")
</screen>
diff --git a/doc/man/scons.xml b/doc/man/scons.xml
index fc28e2a..45bc9bd 100644
--- a/doc/man/scons.xml
+++ b/doc/man/scons.xml
@@ -515,9 +515,7 @@ by appropriate setting of &consvars;.</para>
<para>&scons;
requires Python 3.5 or higher.
-There should be no other dependencies or requirements to run &scons;,
-although the <package>pywin32</package> Python package is
-strongly recommended if running on Windows systems.
+There should be no other dependencies or requirements to run &scons;.
</para>
</refsect1>
@@ -4237,6 +4235,13 @@ Calling &Variables; with no arguments is equivalent to:
vars = Variables(files=None, args=ARGUMENTS)
</programlisting>
+<para>
+Note that since the variables are eventually added as &consvars;,
+you should choose variable names which do not unintentionally change
+pre-defined &consvars; that your project will make use of
+(see <xref linkend="construction_variables"/>).
+</para>
+
</listitem>
</varlistentry>
</variablelist>
@@ -5521,18 +5526,21 @@ and emitter functions.</para>
function will turn its
<parameter>action</parameter>
keyword argument into an appropriate
-internal Action object.
+internal Action object, as will
+the &f-link-Command; function.
You can also explicitly create Action objects
for passing to &f-Builder;, or other functions
that take actions as arguments,
by calling the &f-link-Action; factory function.
-This can be used to configure
-an Action object more flexibly,
-or it may simply be more efficient
-than letting each separate Builder object
-create a separate Action
-when multiple
-Builder objects need to do the same thing.</para>
+This may more efficient when multiple
+Builder objects need to do the same thing
+rather than letting each of those Builder objects
+create a separate Action object.
+It also allows more flexible configuration
+of an Action object. For example, to control
+the message printed when the action is taken
+you need to create the action object using &f-Action;.
+</para>
<para>The
&Action; factory function
@@ -5652,23 +5660,22 @@ it was called. The global function form &f-link-Action;
the Action object is actually used.
</para>
-<para>The second argument to &f-Action;
-is optional and is used to define the output
+<para>The optional second argument to &f-Action;
+is used to control the output
which is printed when the Action is actually performed.
-In the absence of this parameter,
-or if it's an empty string,
+If this parameter is omitted,
+or if the value is an empty string,
a default output depending on the type of the action is used.
For example, a command-line action will print the executed command.
-The argument must be either a Python function or a string:</para>
+The following argument types are accepted:
+</para>
<itemizedlist>
<listitem>
<para>If the output argument is a function,
-it must return a string
+the function will be called to obtain a string
describing the action being executed.
-A function may also be specified using the
-<parameter>strfunction</parameter>
-keyword argument. The function
+The function
must accept these three keyword arguments:</para>
<simplelist type="vert">
@@ -5689,18 +5696,29 @@ more than one target file or source file.</para>
<listitem>
<para>If the output argument is a string,
-substitution is performed on it before it is printed.
-The output string may also be specified using the
-<parameter>cmdstr</parameter>
-keyword argument.
+substitution is performed on the string before it is printed.
The string typically contains variables, notably
<literal>$TARGET(S)</literal> and <literal>$SOURCE(S)</literal>,
or consists of just a single
variable, which is optionally defined somewhere else.
-SCons itself heavily uses the latter variant.</para>
+&SCons; itself heavily uses the latter variant.</para>
+ </listitem>
+
+ <listitem>
+<para>If the argument is <constant>None</constant>,
+output is suppressed entirely.</para>
</listitem>
</itemizedlist>
+<para>
+Instead of using a positional argument,
+the <parameter>cmdstr</parameter>
+keyword argument may be used to specify the output string,
+or the <parameter>strfunction</parameter> keyword argument
+may be used to specify a function to return the output string,
+Use <literal>cmdstr=None</literal> to suppress output.
+</para>
+
<para>Examples:</para>
<programlisting language="python">
@@ -6164,14 +6182,25 @@ env.Command('marker', 'input_file', action=[MyBuildAction, Touch('$TARGET')])
<para>Before executing a command,
&scons;
-performs &consvar; substitution on the string that makes up
-the command line of the builder.
-&Consvars; to be interpolated are indicated in the
+performs variable substitution on the string that makes up
+the action part of the builder.
+Variables to be interpolated are indicated in the
string with a leading
<literal>$</literal>, to distinguish them from plain text
which is not to be substituted.
+The name may be surrounded by curly braces
+(<literal>${}</literal>)
+to separate the name from surrounding characters if necessary.
+Curly braces are required when you use
+Python list subscripting/slicing notation on a variable
+to select one or more items from a list,
+or access a variable's special attributes,
+or use Python expression substitution.
+</para>
+
+<para>
Besides regular &consvars;, scons provides the following
-special variables for each command execution:</para>
+special variables for use in expanding commands:</para>
<variablelist>
<varlistentry>
@@ -6243,45 +6272,39 @@ changed since the target was last built.</para>
</varlistentry>
</variablelist>
-<para>Note that the above variables are reserved
-and may not be assigned to in the &consenv;.</para>
+<para>These names are reserved
+and may not be assigned to or used as &consvars;.</para>
-<para>For example, given the &consvars;
-<literal>CC='cc'</literal>,
-<literal>targets=['foo']</literal>
-and
-<literal>sources=['foo.c', 'bar.c']</literal>:
+<para>For example, the following builder call:
</para>
<programlisting language="python">
-action='$CC -c -o $TARGET $SOURCES'
+env = Environment(CC='cc')
+env.Command(
+ target=['foo'],
+ source=['foo.c', 'bar.c'],
+ action='@echo $CC -c -o $TARGET $SOURCES'
+)
</programlisting>
-<para>would produce the command line:</para>
+<para>would produce the following output:</para>
<screen>
cc -c -o foo foo.c bar.c
</screen>
-<para>Variable names may be surrounded by curly braces
-(<emphasis role="bold">{}</emphasis>)
-to separate the name from surrounding characters which
-are not part of the name.
-Within the curly braces, a variable name may use
-Python list subscripting/slicing notation to select one
-or more items from a list.
-In the previous example, the string:
+<para>
+In the previous example, a string
<code>${SOURCES[1]}</code>
-would produce:</para>
-
-<screen>
-bar.c
-</screen>
+would expand to: <computeroutput>bar.c</computeroutput>.
+</para>
-<para>Additionally, a variable name may
+<para>A variable name may
have the following
modifiers appended within the enclosing curly braces
-to access properties of the interpolated string:</para>
+to access properties of the interpolated string.
+These are known as <firstterm>special attributes</firstterm>.
+</para>
<simplelist>
<member><parameter>base</parameter> -
@@ -6360,23 +6383,18 @@ ${SOURCE.rsrcdir} =&gt; /usr/repository/src
</literallayout>
<para>
-Modifiers can be combined, like
-<literal>${TARGET.base.windows}</literal>,
+Some modifiers can be combined, like
<literal>${TARGET.srcpath.base)</literal>,
<literal>${TARGET.file.suffix}</literal>, etc.
</para>
-<para>Note that curly braces braces may also be used
-to enclose arbitrary Python code to be evaluated.
-(In fact, this is how the above modifiers are substituted,
-they are simply attributes of the Python objects
-that represent &cv-TARGET;, &cv-SOURCES;, etc.)
+<para>The curly brace notation may also be used
+to enclose a Python expression to be evaluated.
See <xref linkend='python_code_substitution'/> below
-for more thorough examples of
-how this can be used.</para>
+for a description.</para>
-<para>Lastly, a variable name
-may be a callable Python function
+<para>A variable name
+may also be a Python function
associated with a
&consvar; in the environment.
The function should
@@ -6407,6 +6425,12 @@ def foo(target, source, env, for_signature):
env=Environment(FOO=foo, BAR="$FOO baz")
</programlisting>
+<para>As a reminder, this evaluation happens when
+<literal>$BAR</literal> is actually used in a
+builder action. The value of <literal>env['BAR']</literal>
+will be exactly as it was set: <literal>"$FOO baz"</literal>.
+</para>
+
<para>You can use this feature to pass arguments to a
Python function by creating a callable class
that stores one or more arguments in an object,
@@ -6478,19 +6502,20 @@ echo Last build occurred . &gt; $TARGET
<title>Python Code Substitution</title>
<para>
-Any Python code within curly braces
-(<emphasis role="bold">{}</emphasis>)
-and introduced by the variable prefix <literal>$</literal>
-will be evaluated using the Python <function>eval</function> statement,
-with the Python globals set to
-the current environment's set of &consvars;, and the result
-substituted in.
+If a substitutable expression using the notation
+<literal>${something}</literal> does not appear to match one of
+the other substitution patterns,
+it is evaluated as a Python expression.
+This uses Python's <function>eval</function> function,
+with the <parameter>globals</parameter> parameter set to
+the current environment's set of &consvars;,
+and the result substituted in.
So in the following case:</para>
<programlisting language="python">
-env['COND'] = 0
-env.Command('foo.out', 'foo.in',
- '''echo ${COND==1 and 'FOO' or 'BAR'} &gt; $TARGET''')
+env.Command(
+ 'foo.out', 'foo.in', "echo ${COND==1 and 'FOO' or 'BAR'} &gt; $TARGET"
+)
</programlisting>
<para>the command executed will be either</para>
@@ -6512,7 +6537,7 @@ built, not when the SConscript is being read. So if
<literal>env['COND']</literal> is changed
later in the SConscript, the final value will be used.</para>
-<para>Here's a more interesting example. Note that all of
+<para>Here's a more complete example. Note that all of
<envar>COND</envar>,
<envar>FOO</envar>,
and
@@ -6523,17 +6548,29 @@ separated by spaces.</para>
<programlisting language="python">
env=Environment()
-env['COND'] = 0
+env['COND'] = 1
env['FOO'] = ['foo1', 'foo2']
env['BAR'] = 'barbar'
-env.Command('foo.out', 'foo.in',
- 'echo ${COND==1 and FOO or BAR} &gt; $TARGET')
-
-# Will execute this:
-# echo foo1 foo2 &gt; foo.out
+env.Command(
+ 'foo.out', 'foo.in', "echo ${COND==1 and FOO or BAR} &gt; $TARGET"
+)
</programlisting>
-<para>SCons uses the following rules when converting &consvars; into
+<para>will execute:</para>
+<screen>
+echo foo1 foo2 &gt; foo.out
+</screen>
+
+<para>
+In point of fact, Python expression evaluation is
+how the special attributes are substituted:
+they are simply attributes of the Python objects
+that represent &cv-TARGET;, &cv-SOURCES;, etc.,
+which &SCons; passes to <function>eval</function> which
+returns the value.
+</para>
+
+<para>&SCons; uses the following rules when converting &consvars; into
command lines:</para>
<variablelist>
@@ -6571,6 +6608,16 @@ contain embedded newline characters.</para>
</listitem>
</varlistentry>
</variablelist>
+
+<note><para>
+Use of the Python <function>eval</function> function
+is considered to have security implications, since,
+depending on input sources,
+arbitrary unchecked strings of code can be executed by the Python interpreter.
+Although &SCons; makes use of it in a somewhat restricted context,
+you should be aware of this issue when using the
+<literal>${python-expression-for-subst}</literal> form.
+</para></note>
</refsect2>
<refsect2 id='scanner_objects'>
@@ -6595,8 +6642,7 @@ a Python function that will process
the Node (file)
and return a list of File Nodes
representing the implicit
-dependencies (file names) found in the contents;
-or:
+dependencies (file names) found in the contents.
</para></listitem>
<listitem><para>
a dictionary that maps keys
diff --git a/doc/man/sconsign.xml b/doc/man/sconsign.xml
index d2d14c7..726f86e 100644
--- a/doc/man/sconsign.xml
+++ b/doc/man/sconsign.xml
@@ -49,67 +49,58 @@
<refsect1 id='description'><title>DESCRIPTION</title>
-<para>The
-<command>sconsign</command>
-command
-displays the contents of one or more signature database
-(<firstterm>sconsign</firstterm>)
-files used by the <command>scons</command> build tool.
+<para>
+Displays the contents of one or more
+<firstterm>sconsign files</firstterm>,
+the signature database files
+used by the <application>SCons</application> build tool.
</para>
<para>By default,
<command>sconsign</command>
dumps the entire contents of the
sconsign file(s).
-Without the verbose option,
-each entry is printed in the following format:</para>
+Without options,
+individual dependency entries are printed in the following format:</para>
-<literallayout class="monospaced">
-file: signature timestamp length
- implicit_dependency_1: signature timestamp length
- implicit_dependency_2: signature timestamp length
+<screen>
+depfile: signature timestamp length
+ implicit_dependency_1: content_signature timestamp length
+ implicit_dependency_2: content_signature timestamp length
...
action_signature [action string]
-</literallayout>
+</screen>
<para><emphasis role="bold">None</emphasis>
-is printed
-in place of any missing timestamp, <firstterm>build signature</firstterm>
-(<emphasis role="bold">bsig</emphasis>),
-or <firstterm>content signature</firstterm>
+is printed in place of any missing timestamp,
+ <firstterm>content signature</firstterm>
(<emphasis role="bold">csig</emphasis>)
-values for
-any entry
+or
+<firstterm>build action signature</firstterm>
+values for any entry
or any of its dependencies.
If the entry has no implicit dependencies,
or no build action,
-the lines are simply omitted.</para>
-
-<para>
-The verbose option expands the display into a more human
-readable format.
-</para>
+those lines are omitted.</para>
<para>By default,
<command>sconsign</command>
assumes that any
<replaceable>file</replaceable>
arguments that end with a
-<filename>.dbm</filename>
+<filename>.dblite</filename>
suffix contains
signature entries for
more than one directory
(that is,
was specified by the
-<emphasis role="bold">SConsignFile</emphasis>
+<function>SConsignFile</function>
function).
Any
<replaceable>file</replaceable>
-argument that ends in
-<filename>.dblite</filename>
-is assumed to be a traditional
-sconsign
-file containing the signature entries
+argument that has no suffix
+is assumed to be an old-style
+sconsign file containing the signature entries
for a single directory.
If neither of those is true,
<command>sconsign</command>
@@ -127,7 +118,7 @@ If there are no
<replaceable>file</replaceable>
arguments, the name
<filename>.sconsign.dblite</filename>
-is assumed.
+is assumed by default.
</para>
</refsect1>
@@ -145,7 +136,7 @@ and the format:</para>
<option>--action</option>
</term>
<listitem>
-<para>Prints the build action information
+<para>Prints only the build action information
for all entries or the specified entries.</para>
</listitem>
@@ -156,7 +147,7 @@ for all entries or the specified entries.</para>
<option>--csig</option>
</term>
<listitem>
-<para>Prints the content signature (csig) information
+<para>Prints only the content signature (csig) information
for all entries or the specified entries.</para>
</listitem>
@@ -169,11 +160,11 @@ for all entries or the specified entries.</para>
<listitem>
<para>When the signatures are being
read from a
-<filename>.dbm</filename>
+<filename>.dblite</filename>
file, or the
-<option>-f dbm</option>
+<option>-f dblite</option>
or
-<option>--format=dbm</option>
+<option>--format=dblite</option>
options are used,
prints information about
only the signatures
@@ -208,15 +199,15 @@ options are specified on the command line.</para>
are in the specified
<replaceable>FORMAT</replaceable>.
Legal values are
-<emphasis role="bold">dbm</emphasis>
-(the DBM format used
-when the
-<emphasis role="bold">SConsignFile</emphasis>
-function is used)
-or
-<command>sconsign</command>
-(the default format
-used for an individual
+<emphasis role="bold">dblite</emphasis>
+(the SCons.dblite format used by default,
+as well as when the
+<function>SConsignFile</function>
+function is called, except when a filename argument
+of <constant>None</constant> is given)
+and
+<emphasis role="bold">sconsign</emphasis>
+(the format used for an individual
<filename>.sconsign</filename>
file in each directory).</para>
diff --git a/doc/user/MANIFEST b/doc/user/MANIFEST
index d7237df..5be5aff 100644
--- a/doc/user/MANIFEST
+++ b/doc/user/MANIFEST
@@ -44,6 +44,7 @@ run.xml
scanners.xml
sconf.xml
separate.xml
+sideeffect.xml
simple.xml
tasks.xml
tools.xml
diff --git a/doc/user/builders-commands.xml b/doc/user/builders-commands.xml
index 5d378b3..7d47dae 100644
--- a/doc/user/builders-commands.xml
+++ b/doc/user/builders-commands.xml
@@ -81,7 +81,7 @@
if you only need to execute one specific command
to build a single file (or group of files).
For these situations, &SCons; supports a
- &Command; &Builder; that arranges
+ &f-link-Command; builder that arranges
for a specific action to be executed
to build a specific file or files.
This looks a lot like the other builders
@@ -119,7 +119,7 @@ foo.in
This is often more convenient than
creating a &Builder; object
and adding it to the &cv-link-BUILDERS; variable
- of a &consenv;
+ of a &consenv;.
</para>
@@ -134,9 +134,11 @@ foo.in
<scons_example name="builderscommands_ex2">
<file name="SConstruct" printme="1">
env = Environment()
+
def build(target, source, env):
# Whatever it takes to build
return None
+
env.Command('foo.out', 'foo.in', build)
</file>
<file name="foo.in">
@@ -157,8 +159,7 @@ foo.in
<para>
Note that &cv-link-SOURCE; and &cv-link-TARGET; are expanded
- in the source and target as well as of SCons 1.1,
- so you can write:
+ in the source and target as well, so you can write:
</para>
@@ -168,7 +169,6 @@ env.Command('${SOURCE.basename}.out', 'foo.in', build)
</file>
</scons_example>
-
<para>
which does the same thing as the previous example, but allows you
@@ -176,5 +176,61 @@ env.Command('${SOURCE.basename}.out', 'foo.in', build)
</para>
+ <para>
+
+ It may be helpful to use the <parameter>action</parameter>
+ keyword to specify the action, is this makes things more clear
+ to the reader:
+
+ </para>
+
+ <scons_example name="builderscommands_ex4">
+ <file name="SConstruct" printme="1">
+env.Command('${SOURCE.basename}.out', 'foo.in', action=build)
+ </file>
+ </scons_example>
+
+ <para>
+
+ The method described in
+ <xref linkend="sect-controlling-build-output"/> for controlling
+ build output works well when used with pre-defined builders which
+ have pre-defined <literal>*COMSTR</literal> variables for that purpose,
+ but that is not the case when calling &f-Command;,
+ where &SCons; has no specific knowledge of the action ahead of time.
+ If the action argument to &f-Command; is not already an &Action; object,
+ it will construct one for you with suitable defaults,
+ which include a message based on the type of action.
+ However, you can also construct the &Action; object yourself
+ to pass to &f-Command;, which gives you much more control.
+ Here's an evolution of the example from above showing this approach:
+
+ </para>
+
+ <scons_example name="builderscommands_ex5">
+ <file name="SConstruct" printme="1">
+env = Environment()
+
+def build(target, source, env):
+ # Whatever it takes to build
+ return None
+
+act = Action(build, cmdstr="Building ${TARGET}")
+env.Command('foo.out', 'foo.in', action=act)
+ </file>
+ <file name="foo.in">
+foo.in
+ </file>
+ </scons_example>
+
+ <para>
+
+ Which executes as follows:
+
+ </para>
+
+ <scons_output example="builderscommands_ex5" suffix="1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
</chapter>
diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml
index 6910290..8db9230 100644
--- a/doc/user/command-line.xml
+++ b/doc/user/command-line.xml
@@ -174,8 +174,8 @@ def b(target, source, env):
pass
def s(target, source, env):
return " ... [build output] ..."
-a = Action(b, strfunction = s)
-env = Environment(BUILDERS = {'A' : Builder(action=a)})
+a = Action(b, strfunction=s)
+env = Environment(BUILDERS={'A': Builder(action=a)})
env.A('foo.out', 'foo.in')
</file>
<file name="foo.in">
@@ -330,7 +330,7 @@ if not GetOption('help'):
import os
num_cpu = int(os.environ.get('NUM_CPU', 2))
SetOption('num_jobs', num_cpu)
-print("running with -j %s"%GetOption('num_jobs'))
+print("running with -j %s" % GetOption('num_jobs'))
</file>
<file name="foo.in">
foo.in
@@ -347,9 +347,9 @@ foo.in
where the string is spelled differently from
the from command-line option.
The string for fetching or setting the <option>--jobs</option>
- value is <literal>num_jobs</literal>
+ value is <parameter>num_jobs</parameter>
for historical reasons.)
- The code in this example prints the <literal>num_jobs</literal>
+ The code in this example prints the <parameter>num_jobs</parameter>
value for illustrative purposes.
It uses a default value of <literal>2</literal>
to provide some minimal parallelism even on
@@ -817,7 +817,7 @@ foo.in
env = Environment()
debug = ARGUMENTS.get('debug', 0)
if int(debug):
- env.Append(CCFLAGS = '-g')
+ env.Append(CCFLAGS='-g')
env.Program('prog.c')
</file>
<file name="prog.c">
@@ -847,7 +847,7 @@ prog.c
the last values used to build the object files,
and as a result correctly rebuilds
the object and executable files
- only when the value of the <literal>debug</literal>
+ only when the value of the <parameter>debug</parameter>
argument has changed.
</para>
@@ -1265,9 +1265,7 @@ vars = Variables('custom.py', ARGUMENTS)
<scons_example name="commandline_BoolVariable">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(BoolVariable('RELEASE',
- help='Set to build for release',
- default=0))
+vars.Add(BoolVariable('RELEASE', help='Set to build for release', default=0))
env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'})
env.Program('foo.c')
</file>
@@ -1348,7 +1346,7 @@ foo.c
</section>
<section>
- <title>Single Value From a List: the &EnumVariable; Build Variable Function</title>
+ <title>Single Value From a Selection: the &EnumVariable; Build Variable Function</title>
<para>
@@ -1370,10 +1368,14 @@ foo.c
<scons_example name="commandline_EnumVariable">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(EnumVariable('COLOR',
- help='Set background color',
- default='red',
- allowed_values=('red', 'green', 'blue')))
+vars.Add(
+ EnumVariable(
+ 'COLOR',
+ help='Set background color',
+ default='red',
+ allowed_values=('red', 'green', 'blue'),
+ )
+)
env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'})
env.Program('foo.c')
Help(vars.GenerateHelpText(env))
@@ -1440,11 +1442,15 @@ foo.c
<scons_example name="EnumVariable_map">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(EnumVariable('COLOR',
- help='Set background color',
- default='red',
- allowed_values=('red', 'green', 'blue'),
- map={'navy':'blue'}))
+vars.Add(
+ EnumVariable(
+ 'COLOR',
+ help='Set background color',
+ default='red',
+ allowed_values=('red', 'green', 'blue'),
+ map={'navy': 'blue'},
+ )
+)
env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'})
env.Program('foo.c')
</file>
@@ -1496,13 +1502,17 @@ foo.c
<scons_example name="commandline_EnumVariable_ic1">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(EnumVariable('COLOR',
- help='Set background color',
- default='red',
- allowed_values=('red', 'green', 'blue'),
- map={'navy':'blue'},
- ignorecase=1))
-env = Environment(variables=vars, CPPDEFINES={'COLOR':'"${COLOR}"'})
+vars.Add(
+ EnumVariable(
+ 'COLOR',
+ help='Set background color',
+ default='red',
+ allowed_values=('red', 'green', 'blue'),
+ map={'navy': 'blue'},
+ ignorecase=1,
+ )
+)
+env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'})
env.Program('foo.c')
</file>
<file name="foo.c">
@@ -1537,12 +1547,16 @@ foo.c
<scons_example name="commandline_EnumVariable_ic2">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(EnumVariable('COLOR',
- help='Set background color',
- default='red',
- allowed_values=('red', 'green', 'blue'),
- map={'navy':'blue'},
- ignorecase=2))
+vars.Add(
+ EnumVariable(
+ 'COLOR',
+ help='Set background color',
+ default='red',
+ allowed_values=('red', 'green', 'blue'),
+ map={'navy': 'blue'},
+ ignorecase=2,
+ )
+)
env = Environment(variables=vars, CPPDEFINES={'COLOR': '"${COLOR}"'})
env.Program('foo.c')
</file>
@@ -1587,10 +1601,11 @@ foo.c
<scons_example name="commandline_ListVariable">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(ListVariable('COLORS',
- help='List of colors',
- default=0,
- names=['red', 'green', 'blue']))
+vars.Add(
+ ListVariable(
+ 'COLORS', help='List of colors', default=0, names=['red', 'green', 'blue']
+ )
+)
env = Environment(variables=vars, CPPDEFINES={'COLORS': '"${COLORS}"'})
env.Program('foo.c')
</file>
@@ -1639,6 +1654,29 @@ foo.c
<scons_output_command>scons -Q COLORS=magenta foo.o</scons_output_command>
</scons_output>
+ <para>
+
+ You can use this last characteristic as a way to enforce at least
+ one of your valid options being chosen by specifying the valid
+ values with the <parameter>names</parameter> parameter and then
+ giving a value not in that list as the <parameter>default</parameter>
+ parameter - that way if no value is given on the command line,
+ the default is chosen, and it will error out with an invalid value.
+ The example is, in fact, set up that way by using
+ <literal>0</literal> as the default:
+
+ </para>
+
+ <scons_output example="commandline_ListVariable" suffix="4">
+ <scons_output_command>scons -Q foo.o</scons_output_command>
+ </scons_output>
+
+ <para>
+
+ This technique works for &EnumVariable; as well.
+
+ </para>
+
</section>
<section>
@@ -1659,9 +1697,11 @@ foo.c
<scons_example name="commandline_PathVariable">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(PathVariable('CONFIG',
- help='Path to configuration file',
- default='__ROOT__/etc/my_config'))
+vars.Add(
+ PathVariable(
+ 'CONFIG', help='Path to configuration file', default='__ROOT__/etc/my_config'
+ )
+)
env = Environment(variables=vars, CPPDEFINES={'CONFIG_FILE': '"$CONFIG"'})
env.Program('foo.c')
</file>
@@ -1678,7 +1718,7 @@ foo.c
<para>
- This then allows the user to
+ This allows you to
override the &CONFIG; build variable
on the command line as necessary:
@@ -1714,10 +1754,14 @@ foo.c
<scons_example name="commandline_PathIsFile">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(PathVariable('CONFIG',
- help='Path to configuration file',
- default='__ROOT__/etc/my_config',
- validator=PathVariable.PathIsFile))
+vars.Add(
+ PathVariable(
+ 'CONFIG',
+ help='Path to configuration file',
+ default='__ROOT__/etc/my_config',
+ validator=PathVariable.PathIsFile,
+ )
+)
env = Environment(variables=vars, CPPDEFINES={'CONFIG_FILE': '"$CONFIG"'})
env.Program('foo.c')
</file>
@@ -1740,10 +1784,14 @@ foo.c
<scons_example name="commandline_PathIsDir">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(PathVariable('DBDIR',
- help='Path to database directory',
- default='__ROOT__/var/my_dbdir',
- validator=PathVariable.PathIsDir))
+vars.Add(
+ PathVariable(
+ 'DBDIR',
+ help='Path to database directory',
+ default='__ROOT__/var/my_dbdir',
+ validator=PathVariable.PathIsDir,
+ )
+)
env = Environment(variables=vars, CPPDEFINES={'DBDIR': '"$DBDIR"'})
env.Program('foo.c')
</file>
@@ -1768,10 +1816,14 @@ foo.c
<scons_example name="commandline_PathIsDirCreate">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(PathVariable('DBDIR',
- help='Path to database directory',
- default='__ROOT__/var/my_dbdir',
- validator=PathVariable.PathIsDirCreate))
+vars.Add(
+ PathVariable(
+ 'DBDIR',
+ help='Path to database directory',
+ default='__ROOT__/var/my_dbdir',
+ validator=PathVariable.PathIsDirCreate,
+ )
+)
env = Environment(variables=vars, CPPDEFINES={'DBDIR': '"$DBDIR"'})
env.Program('foo.c')
</file>
@@ -1795,10 +1847,14 @@ foo.c
<scons_example name="commandline_PathAccept">
<file name="SConstruct" printme="1">
vars = Variables('custom.py')
-vars.Add(PathVariable('OUTPUT',
- help='Path to output file or directory',
- default=None,
- validator=PathVariable.PathAccept))
+vars.Add(
+ PathVariable(
+ 'OUTPUT',
+ help='Path to output file or directory',
+ default=None,
+ validator=PathVariable.PathAccept,
+ )
+)
env = Environment(variables=vars, CPPDEFINES={'OUTPUT': '"$OUTPUT"'})
env.Program('foo.c')
</file>
@@ -1829,9 +1885,9 @@ foo.c
<scons_example name="commandline_PackageVariable">
<file name="SConstruct" printme="1">
vars = Variables("custom.py")
-vars.Add(PackageVariable("PACKAGE",
- help="Location package",
- default="__ROOT__/opt/location"))
+vars.Add(
+ PackageVariable("PACKAGE", help="Location package", default="__ROOT__/opt/location")
+)
env = Environment(variables=vars, CPPDEFINES={"PACKAGE": '"$PACKAGE"'})
env.Program("foo.c")
</file>
@@ -1967,7 +2023,7 @@ vars.Add('RELEASE', help='Set to 1 to build for release', default=0)
env = Environment(variables=vars, CPPDEFINES={'RELEASE_BUILD': '${RELEASE}'})
unknown = vars.UnknownVariables()
if unknown:
- print("Unknown variables: %s"%unknown.keys())
+ print("Unknown variables: %s" % " ".join(unknown.keys()))
Exit(1)
env.Program('foo.c')
</file>
@@ -1984,12 +2040,12 @@ foo.c
that are <emphasis>not</emphasis>
among the variables known to the &Variables; object
(from having been specified using
- the &Variables; object's&Add; method).
- In the examble above,
+ the &Variables; object's &Add; method).
+ In the example above,
we check for whether the dictionary
- returned by the &UnknownVariables; is non-empty,
+ returned by &UnknownVariables; is non-empty,
and if so print the Python list
- containing the names of the unknwown variables
+ containing the names of the unknown variables
and then call the &Exit; function
to terminate &SCons;:
@@ -2016,8 +2072,9 @@ foo.c
Note that you must delay the call of &UnknownVariables;
until after you have applied the &Variables; object
to a construction environment
- with the <literal>variables=</literal>
- keyword argument of an &Environment; call.
+ with the <parameter>variables=</parameter>
+ keyword argument of an &Environment; call: the variables
+ in the object are not fully processed until this has happened.
</para>
@@ -2259,7 +2316,7 @@ int bar() { printf("prog2/bar.c\n"); }
Lastly, if for some reason you don't want
any targets built by default,
- you can use the Python <literal>None</literal>
+ you can use the Python <constant>None</constant>
variable:
</para>
@@ -2441,7 +2498,7 @@ else:
prog1 = Program('prog1.c')
Program('prog2.c')
Default(prog1)
-print ("BUILD_TARGETS is %s" % [str(t) for t in BUILD_TARGETS])
+print("BUILD_TARGETS is %s" % [str(t) for t in BUILD_TARGETS])
</file>
<file name="prog1.c">
prog1.c
diff --git a/doc/user/environments.xml b/doc/user/environments.xml
index 99df99d..40bcd31 100644
--- a/doc/user/environments.xml
+++ b/doc/user/environments.xml
@@ -379,7 +379,7 @@ environment, of directory names, suffixes, etc.
</varlistentry>
<varlistentry>
- <term>&ConsEnv;</term>
+ <term>Construction Environment</term>
<listitem>
<para>
diff --git a/doc/user/external.xml b/doc/user/external.xml
index a72fa54..3d55a8c 100644
--- a/doc/user/external.xml
+++ b/doc/user/external.xml
@@ -100,17 +100,27 @@
<para>
The compilation database can be populated with
- source and target files either with paths relative
+ source and output files either with paths relative
to the top of the build, or using absolute paths.
This is controlled by
<envar>COMPILATIONDB_USE_ABSPATH=(True|False)</envar>
which defaults to <constant>False</constant>.
+ The entries in this file can be filtered by using
+
+ <envar>COMPILATIONDB_PATH_FILTER='fnmatch pattern'</envar>
+ where the filter string is a
+ <ulink url="https://docs.python.org/3/library/fnmatch.html">
+ <citetitle>fnmatch</citetitle>
+ </ulink>
+ based pattern which is a typical file glob syntax.
+ This filtering can be used for outputting different
+ build variants to different compilation database files.
</para>
<para>
- Example of absolute paths for target and source:
+ Example of absolute paths for output and source:
</para>
@@ -126,14 +136,14 @@ env.CompilationDatabase('compile_commands.json')
"command": "gcc -o test_main.o -c test_main.c",
"directory": "/home/user/sandbox",
"file": "/home/user/sandbox/test_main.c",
- "target": "/home/user/sandbox/test_main.o"
+ "output": "/home/user/sandbox/test_main.o"
}
]
</programlisting>
<para>
- Example of relative paths for target and source:
+ Example of relative paths for output and source:
</para>
@@ -148,7 +158,46 @@ env.CompilationDatabase('compile_commands.json')
"command": "gcc -o test_main.o -c test_main.c",
"directory": "/home/user/sandbox",
"file": "test_main.c",
- "target": "test_main.o"
+ "output": "test_main.o"
+ }
+]
+ </programlisting>
+
+ <para>
+
+ Example of using filtering for build variants:
+
+ </para>
+
+ <sconstruct>
+env = Environment()
+env.Tool('compilation_db')
+
+env1 = env.Clone()
+env1['COMPILATIONDB_PATH_FILTER'] = 'build/linux32/*'
+env1.CompilationDatabase('compile_commands-linux32.json')
+
+env2 = env.Clone()
+env2['COMPILATIONDB_PATH_FILTER'] = 'build/linux64/*'
+env2.CompilationDatabase('compile_commands-linux64.json')
+ </sconstruct>
+ <programlisting language="json">
+[
+ {
+ "command": "gcc -m32 -o build/linux32/test_main.o -c test_main.c",
+ "directory": "/home/user/sandbox",
+ "file": "test_main.c",
+ "output": "build/linux32/test_main.o"
+ }
+]
+ </programlisting>
+ <programlisting language="json">
+[
+ {
+ "command": "gcc -m64 -o build/linux64/test_main.o -c test_main.c",
+ "directory": "/home/user/sandbox",
+ "file": "test_main.c",
+ "output": "build/linux64/test_main.o"
}
]
</programlisting>
diff --git a/doc/user/main.xml b/doc/user/main.xml
index 6f516f9..fd643b5 100644
--- a/doc/user/main.xml
+++ b/doc/user/main.xml
@@ -82,7 +82,8 @@
<chapter id="chap-manip-options">
<title>Automatically Putting Command-line Options into their Construction Variables</title>
- <!-- TODO: This intro paragraph should describe at a high-level
+ <!-- TODO: combine this into a chapter document.
+ This intro paragraph should describe at a high-level
what these things do. People are likely to use the intro as a
(brief) overview of *what* these functions do to decide if this
chapter is where they should read in more detail. -->
@@ -104,60 +105,34 @@
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="file-removal.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="hierarchy.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="separate.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="variants.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="gettext.xml"/>
-
- <!--
-
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="builders-built-in.xml"/>
-
- -->
-
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="repositories.xml"/>
+ <!-- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="builders-built-in.xml"/> -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="builders-writing.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="builders-commands.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="add-method.xml"/>
-
- <!--
-
- XXX Action()
- XXX AddPostAction()
- XXX AddPreAction()
-
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="actions.xml"/>
-
- -->
-
+ <!-- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="actions.xml"/> -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="scanners.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="repositories.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="sconf.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="caching.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="alias.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="java.xml"/>
-
- <!--
-
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="run.xml"/>
-
- -->
-
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="gettext.xml"/>
+ <!-- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="run.xml"/> -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="misc.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="external.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="troubleshoot.xml"/>
-<!-- Appendix below here -->
+ <!-- Appendix below here -->
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="variables.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="builders.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="tools.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="functions.xml"/>
<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="tasks.xml"/>
- <!--
-
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="python.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="example.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="make.xml"/>
- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="ant.xml"/>
-
- -->
+ <!-- These sections are only sekeletons: -->
+ <!-- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="python.xml"/> -->
+ <!-- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="example.xml"/> -->
+ <!-- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="make.xml"/> -->
+ <!-- <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="ant.xml"/> -->
</book>
diff --git a/doc/user/misc.xml b/doc/user/misc.xml
index b093629..1b18d2f 100644
--- a/doc/user/misc.xml
+++ b/doc/user/misc.xml
@@ -625,6 +625,9 @@ env.Command('directory_build_info',
</section>
+ <!-- Former unpublished chapter now included as a section here: -->
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="sideeffect.xml"/>
+
<section>
<title>Virtual environments (virtualenvs)</title>
diff --git a/doc/user/output.xml b/doc/user/output.xml
index bae018a..cf6571c 100644
--- a/doc/user/output.xml
+++ b/doc/user/output.xml
@@ -197,7 +197,7 @@ if env['PLATFORM'] == 'win32':
</section>
- <section>
+ <section id="sect-controlling-build-output">
<title>Controlling How &SCons; Prints Build Commands: the <envar>$*COMSTR</envar> Variables</title>
<para>
diff --git a/doc/user/parse_flags_arg.xml b/doc/user/parse_flags_arg.xml
index 6e9b926..6014145 100644
--- a/doc/user/parse_flags_arg.xml
+++ b/doc/user/parse_flags_arg.xml
@@ -17,7 +17,7 @@
xmlns="http://www.scons.org/dbxsd/v1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
-<title>Merging Options into the Environment: the <parameter>merge_flags</parameter> Parameter</title>
+<title>Merging Options While Creating Environment: the <parameter>parse_flags</parameter> Parameter</title>
<!--
diff --git a/doc/user/separate.xml b/doc/user/separate.xml
index 748a124..236556d 100644
--- a/doc/user/separate.xml
+++ b/doc/user/separate.xml
@@ -2,7 +2,7 @@
<!DOCTYPE sconsdoc [
<!ENTITY % scons SYSTEM "../scons.mod">
%scons;
-
+
<!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
%builders-mod;
<!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
@@ -17,7 +17,7 @@
xmlns="http://www.scons.org/dbxsd/v1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
-<title>Separating Source and Build Directories</title>
+<title>Separating Source and Build Trees: Variant Directories</title>
<!--
@@ -44,115 +44,49 @@
-->
-<!--
+ <para>
-=head1 Separating source and build trees
-
-It's often desirable to keep any derived files from the build completely
-separate from the source files. This makes it much easier to keep track of
-just what is a source file, and also makes it simpler to handle B<variant>
-builds, especially if you want the variant builds to co-exist.
-
-=head2 Separating build and source directories using the Link command
-
-Cons provides a simple mechanism that handles all of these requirements. The
-C<Link> command is invoked as in this example:
-
- Link 'build' => 'src';
-
-The specified directories are ``linked'' to the specified source
-directory. Let's suppose that you setup a source directory, F<src>, with the
-sub-directories F<world> and F<hello> below it, as in the previous
-example. You could then substitute for the original build lines the
-following:
-
- Build qw(
- build/world/Conscript
- build/hello/Conscript
- );
-
-Notice that you treat the F<Conscript> file as if it existed in the build
-directory. Now if you type the same command as before, you will get the
-following results:
-
- % cons export
- Install build/world/world.h as export/include/world.h
- cc -Iexport/include -c build/hello/hello.c -o build/hello/hello.o
- cc -Iexport/include -c build/world/world.c -o build/world/world.o
- ar r build/world/libworld.a build/world/world.o
- ar: creating build/world/libworld.a
- ranlib build/world/libworld.a
- Install build/world/libworld.a as export/lib/libworld.a
- cc -o build/hello/hello build/hello/hello.o -Lexport/lib -lworld
- Install build/hello/hello as export/bin/hello
-
-Again, Cons has taken care of the details for you. In particular, you will
-notice that all the builds are done using source files and object files from
-the build directory. For example, F<build/world/world.o> is compiled from
-F<build/world/world.c>, and F<export/include/world.h> is installed from
-F<build/world/world.h>. This is accomplished on most systems by the simple
-expedient of ``hard'' linking the required files from each source directory
-into the appropriate build directory.
-
-The links are maintained correctly by Cons, no matter what you do to the
-source directory. If you modify a source file, your editor may do this ``in
-place'' or it may rename it first and create a new file. In the latter case,
-any hard link will be lost. Cons will detect this condition the next time
-the source file is needed, and will relink it appropriately.
-
-You'll also notice, by the way, that B<no> changes were required to the
-underlying F<Conscript> files. And we can go further, as we shall see in the
-next section.
-
-=head2 Explicit references to the source directory
-
-When using the C<Link> command on some operating systems or with some
-tool chains, it's sometimes useful to have a command actually use
-the path name to the source directory, not the build directory. For
-example, on systems that must copy, not "hard link," the F<src/> and
-F<build/> copies of C<Linked> files, using the F<src/> path of a file
-name might make an editor aware that a syntax error must be fixed in the
-source directory, not the build directory.
-
-You can tell Cons that you want to use the "source path" for a file by
-preceding the file name with a ``!'' (exclamation point). For example,
-if we add a ``!'' to the beginning of a source file:
-
- Program $env "foo", "!foo.c"; # Notice initial ! on foo.c
-
-Cons will compile the target as follows:
-
- cc -c src/foo.c -o build/foo.o
- cc -o build/foo build/foo.o
-
-Notice that Cons has compiled the program from the the F<src/foo.c>
-source file. Without the initial ``!'', Cons would have compiled the
-program using the F<build/foo.c> path name.
+ It's often useful to keep any built files completely
+ separate from the source files. Consider if you have a
+ project to build software for a variety of different
+ controller hardware. The boards are able to share a
+ lot of code, so it makes sense to keep them in the same
+ source tree, but certain build options in the source code
+ and header files differ. If you build "Controller A" first,
+ then "Controller B", on the second build everything would
+ have to be rebuilt, because &SCons; sees that the build
+ instructions differ, and thus the targets that depend on those
+ different instructions are not valid for the current build.
+ Now when you go back and build for "Controller A",
+ things have to be rebuilt from scratch again for the same reason.
+ However, if you can separate the places the output files
+ go, this problem can be avoided.
+ You can even set up to do both builds in one invocation of &SCons;.
--->
+ </para>
<para>
- It's often useful to keep any built files completely
- separate from the source files.
- In &SCons;, this is usually done by creating one or more separate
- <emphasis>variant directory trees</emphasis>
+ You can enable this separation by creating one or more
+ <firstterm>variant directory</firstterm> trees
that are used to hold the built objects files, libraries,
and executable programs, etc.
for a specific flavor, or variant, of build.
&SCons; provides two ways to do this,
- one through the &SConscript; function that we've already seen,
- and the second through a more flexible &VariantDir; function.
+ one through the &f-link-SConscript; function that we've already seen,
+ and the second through a more flexible &f-link-VariantDir; function.
</para>
<para>
- One historical note: the &VariantDir; function
+ Historical note: the &VariantDir; function
used to be called &BuildDir;, a name which was
removed because the &SCons; functionality
- differs from the model of a "build directory"
- implemented by other build systems like the GNU Autotools.
+ differs from a familiar model of a "build directory"
+ implemented by other build systems like GNU Autotools.
+ You might still find references to the old name on
+ the Internet in postings about &SCons;, but it no longer works.
</para>
@@ -162,11 +96,11 @@ program using the F<build/foo.c> path name.
<para>
The most straightforward way to establish a variant directory tree
- uses the fact that the usual way to
+ relies the fact that the usual way to
set up a build hierarchy is to have an
- &SConscript; file in the source subdirectory.
- If you then pass a &variant_dir; argument to the
- &SConscript; function call:
+ SConscript file in the source subdirectory.
+ If you pass a &variant_dir; argument to the
+ &f-link-SConscript; function call:
</para>
@@ -193,20 +127,25 @@ int main() { printf("Hello, world!\n"); }
<scons_output example="separate_ex1" suffix="1">
<scons_output_command>ls src</scons_output_command>
<scons_output_command>scons -Q</scons_output_command>
+ <scons_output_command>ls src</scons_output_command>
<scons_output_command>ls build</scons_output_command>
</scons_output>
<para>
- But wait a minute--what's going on here?
- &SCons; created the object file
+ No files were built in &src;, they went to &build;.
+ The build output might show a bit of a surprise:
+ the object file
<filename>build/hello.o</filename>
- in the &build; subdirectory,
+ and the executable file
+ <filename>build/hello</filename>
+ were built in the &build; subdirectory,
as expected.
But even though our &hello_c; file lives in the &src; subdirectory,
&SCons; has actually compiled a
<filename>build/hello.c</filename> file
- to create the object file.
+ to create the object file,
+ and that file is now seen in &build;.
</para>
@@ -215,7 +154,7 @@ int main() { printf("Hello, world!\n"); }
What's happened is that &SCons; has <emphasis>duplicated</emphasis>
the &hello_c; file from the &src; subdirectory
to the &build; subdirectory,
- and built the program from there.
+ and built the program from there (it also duplicated &SConscript;).
The next section explains why &SCons; does this.
</para>
@@ -227,13 +166,13 @@ int main() { printf("Hello, world!\n"); }
<para>
- &SCons; duplicates source files in variant directory trees
- because it's the most straightforward way to guarantee a correct build
- <emphasis>regardless of include-file directory paths,
- relative references between files,
- or tool support for putting files in different locations</emphasis>,
- and the &SCons; philosophy is to, by default,
- guarantee a correct build in all cases.
+ The important thing to understand is that when you set up a variant directory,
+ &SCons; performs the build <emphasis>in that directory</emphasis>.
+ It turns out it's easiest to ensure where build products end up
+ by just building in place.
+ Since the build is happening in a place different from where the
+ sources are, the most straightforward way to guarantee a correct build
+ is for &SCons; to copy them there.
</para>
@@ -312,13 +251,13 @@ int main() { printf("Hello, world!\n"); }
duplicating the source files
and everything will work just fine.
You can disable the default &SCons; behavior
- by specifying <literal>duplicate=0</literal>
+ by specifying <literal>duplicate=False</literal>
when you call the &SConscript; function:
</para>
<sconstruct>
-SConscript('src/SConscript', variant_dir='build', duplicate=0)
+SConscript('src/SConscript', variant_dir='build', duplicate=False)
</sconstruct>
<para>
@@ -395,14 +334,14 @@ int main() { printf("Hello, world!\n"); }
<para>
- You can specify the same <literal>duplicate=0</literal> argument
+ You can specify the same <literal>duplicate=False</literal> argument
that you can specify for an &SConscript; call:
</para>
<scons_example name="separate_duplicate0">
<file name="SConstruct" printme="1">
-VariantDir('build', 'src', duplicate=0)
+VariantDir('build', 'src', duplicate=False)
env = Environment()
env.Program('build/hello.c')
</file>
@@ -432,8 +371,10 @@ int main() { printf("Hello, world!\n"); }
<para>
Even when using the &VariantDir; function,
- it's much more natural to use it with
- a subsidiary &SConscript; file.
+ it's more natural to use it with
+ a subsidiary &SConscript; file,
+ because then you don't have to adjust your individual
+ build instructions to use the variant directory path.
For example, if the
<filename>src/SConscript</filename>
looks like this:
@@ -490,7 +431,7 @@ int main() { printf("Hello, world!\n"); }
<para>
- The &Glob; file name pattern matching function
+ The &f-link-Glob; file name pattern matching function
works just as usual when using &VariantDir;.
For example, if the
<filename>src/SConscript</filename>
@@ -558,4 +499,6 @@ const char * f2();
-->
+ <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="variants.xml"/>
+
</chapter>
diff --git a/doc/user/sideeffect.xml b/doc/user/sideeffect.xml
index d03fbe2..2733769 100644
--- a/doc/user/sideeffect.xml
+++ b/doc/user/sideeffect.xml
@@ -2,7 +2,7 @@
<!DOCTYPE sconsdoc [
<!ENTITY % scons SYSTEM "../scons.mod">
%scons;
-
+
<!ENTITY % builders-mod SYSTEM "../generated/builders.mod">
%builders-mod;
<!ENTITY % functions-mod SYSTEM "../generated/functions.mod">
@@ -13,11 +13,11 @@
%variables-mod;
]>
-<chapter id="chap-sideeffect"
+<section id="sect-sideeffect"
xmlns="http://www.scons.org/dbxsd/v1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
-<title>Sideeffect files</title>
+<title>Declaring Additional Outputs: the &f-SideEffect; Function </title>
<!--
@@ -46,68 +46,142 @@
<para>
- If &SCons; is unaware that a build step produces an extra file,
- the &SideEffect; method can be used to identify it,
- so that the file can be used as a dependency in subsequent build steps.
- However, the primary use for the &SideEffect; method
- is to prevent two build steps from simultaneously modifying the same file.
+ Sometimes the way an action is defined causes effects on files
+ that &SCons; does not recognize as targets. The &f-link-SideEffect;
+ method can be used to informs &SCons; about such files.
+ This can be used just to flag a dependency for use in subsequent
+ build steps, although there is usually a better way to do that.
+ The primary use for the &SideEffect; method
+ is to prevent two build steps from simultaneously modifying
+ or accessing the same file in a way that could impact each other.
</para>
<para>
- TODO: currently doesn't work due to issue #2154:
- https://github.com/SCons/scons/issues/2154
+
+ In this example, the rule to build <filename>file1</filename>
+ will also put data into <filename>log</filename>, which is used
+ as a source for the command to generate <filename>file2</filename>,
+ but <filename>log</filename> is unknown to &SCons; on a clean
+ build: it neither exists, nor is it a target output by any builder.
+ The <filename>SConscript</filename> uses
+ &SideEffect; to inform &SCons; about the additional output file.
+
</para>
-
+
+ <scons_example name="sideeffect_simple">
+ <file name="SConstruct" printme="1">
+env = Environment()
+f2 = env.Command(
+ target='file2',
+ source='log',
+ action=Copy('$TARGET', '$SOURCE')
+)
+f1 = env.Command(
+ target='file1',
+ source=[],
+ action='echo >$TARGET data1; echo >log updated file1'
+)
+env.SideEffect('log', f1)
+ </file>
+ </scons_example>
+
<para>
- If more than one build step creates or manipulates the same file,
- it can cause unpleasant results if both build steps are run at the same time.
- The shared file is declared as a side-effect of building the primary targets
- and &SCons; will prevent the two build steps from running in parallel.
+ Without the &f-SideEffect;, this build would fail with a message
+ <computeroutput>Source `log' not found, needed by target `file2'</computeroutput>,
+ but now it can proceed:
</para>
+ <scons_output example="sideeffect_simple" suffix="1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
<para>
- In this example, the <filename>SConscript</filename> uses
- &SideEffect; to inform &SCons; about the additional output file.
+ However, it is better to actually identify
+ <filename>log</filename> as a target, since in this
+ case that's what it is:
</para>
- <scons_example name="sideeffect_simple">
+ <scons_example name="sideeffect_simple2">
<file name="SConstruct" printme="1">
env = Environment()
-f2 = env.Command('file2', 'log', Copy('$TARGET', '$SOURCE'))
-f1 = env.Command('file1', [],
- 'echo >$TARGET data1; echo >log updated file1')
-env.SideEffect('log', env.Command('file1', [],
- 'echo >$TARGET data1; echo >log updated file1'))
+f2 = env.Command(
+ target='file2',
+ source='log',
+ action=Copy('$TARGET', '$SOURCE')
+)
+f1 = env.Command(
+ target=['file1', 'log'],
+ source=[],
+ action='echo >$TARGET data1; echo >log updated file1'
+)
</file>
</scons_example>
+ <scons_output example="sideeffect_simple2" suffix="1">
+ <scons_output_command>scons -Q</scons_output_command>
+ </scons_output>
+
<para>
- Even when run in parallel mode, &SCons; will run the two steps in order:
+ In general, &SideEffect; is not intended for the case when
+ a command produces extra target files (that is, files which
+ will be used as sources to other build steps). For example, the
+ the Microsoft Visual C/C++ compiler is capable of performing
+ incremental linking, for which it uses a status file - such that
+ linking <filename>foo.exe</filename> also produces
+ a <filename>foo.ilk</filename>, or uses it if it was already present,
+ if the <option>/INCREMENTAL</option> option was supplied.
+ Specifying <filename>foo.ilk</filename> as a
+ side-effect of <filename>foo.exe</filename>
+ is <emphasis>not</emphasis> a recommended use of &SideEffect;
+ since <filename>foo.ilk</filename> is used by the link.
+ &SCons; handles side-effect files
+ slightly differently in its analysis of the dependency graph.
+ When a command produces multiple output files,
+ they should be specified as multiple targets of
+ the call to the relevant builder function.
+ The &SideEffect; function itself should really only be used
+ when it's important to ensure that commands are not executed in parallel,
+ such as when a "peripheral" file (such as a log file)
+ may actually be updated by more than one command invocation.
</para>
- <scons_output example="sideeffect_simple" suffix="1">
- <scons_output_command>scons -Q --jobs=2</scons_output_command>
- </scons_output>
+ <para>
+
+ Unfortunately, the tool which sets up the &b-Program; builder
+ for the MSVC compiler chain does not come prebuilt
+ with an understanding of the details of the <filename>.ilk</filename>
+ example - that the target list would need to change
+ in the presence of that specific option flag. Unlike the trivial
+ example above where we could simply tell the &Command; builder
+ there were two targets of the action, modifying the
+ chain of events for a builder like &b-Program;,
+ though not inherently complex, is definitely an
+ advanced &SCons; topic. It's okay to use &SideEffect; here
+ to get started, as long as it comes with an understanding
+ that it's "not quite right". Perhaps leave a comment in
+ the file as a reminder, if it does turn out to cause problems later.
+
+ </para>
<para>
- Sometimes a program the you need to call
- to build a target file
- will also update another file,
- such as a log file describing what the program
+ So if the main use is to prevent parallelism problems,
+ here is an example to illustrate.
+ Say a program that you need to call to build a target file
+ will also update a log file describing what the program
does while building the target.
- For example, we the folowing configuration
+ The following configuration
would have &SCons; invoke a hypothetical
script named <application>build</application>
(in the local directory)
- with command-line arguments that write
+ with command-line arguments telling it to write
log information to a common
<filename>logfile.txt</filename> file:
@@ -115,10 +189,16 @@ env.SideEffect('log', env.Command('file1', [],
<screen>
env = Environment()
-env.Command('file1.out', 'file.in',
- './build --log logfile.txt $SOURCE $TARGET')
-env.Command('file2.out', 'file.in',
- './build --log logfile.txt $SOURCE $TARGET')
+env.Command(
+ target='file1.out',
+ source='file1.in',
+ action='./build --log logfile.txt $SOURCE $TARGET'
+)
+env.Command(
+ target='file2.out',
+ source='file2.in',
+ action='./build --log logfile.txt $SOURCE $TARGET'
+)
</screen>
<para>
@@ -156,10 +236,16 @@ env.Command('file2.out', 'file.in',
<scons_example name="sideeffect_shared">
<file name="SConstruct" printme="1">
env = Environment()
-f1 = env.Command('file1.out', 'file1.in',
- './build --log logfile.txt $SOURCE $TARGET')
-f2 = env.Command('file2.out', 'file2.in',
- './build --log logfile.txt $SOURCE $TARGET')
+f1 = env.Command(
+ target='file1.out',
+ source='file1.in',
+ action='./build --log logfile.txt $SOURCE $TARGET'
+)
+f2 = env.Command(
+ target='file2.out',
+ source='file2.in',
+ action='./build --log logfile.txt $SOURCE $TARGET'
+)
env.SideEffect('logfile.txt', f1 + f2)
</file>
<file name="file1.in">file1.in</file>
@@ -177,7 +263,7 @@ cat
This makes sure the the two
<application>./build</application> steps are run sequentially,
- even withthe <filename>--jobs=2</filename> in the command line:
+ even with the <filename>--jobs=2</filename> in the command line:
</para>
@@ -189,20 +275,23 @@ cat
The &SideEffect; function can be called multiple
times for the same side-effect file.
- Additionally, the name used as a &SideEffect; does not
- even need to actually exist as a file on disk.
+ In fact, the name used as a &SideEffect; does not
+ even need to actually exist as a file on disk -
&SCons; will still make sure
that the relevant targets
- will be executed sequentially, not in parallel:
+ will be executed sequentially, not in parallel.
+ The side effect is actually a pseudo-target, and &SCons;
+ mainly cares whether nodes are listed as depending on it,
+ not about its contents.
</para>
<scons_example name="sideeffect_parallel">
<file name="SConstruct" printme="1">
env = Environment()
-f1 = env.Command('file1.out', [], 'echo >$TARGET data1')
+f1 = env.Command('file1.out', [], action='echo >$TARGET data1')
env.SideEffect('not_really_updated', f1)
-f2 = env.Command('file2.out', [], 'echo >$TARGET data2')
+f2 = env.Command('file2.out', [], action='echo >$TARGET data2')
env.SideEffect('not_really_updated', f2)
</file>
</scons_example>
@@ -211,28 +300,5 @@ env.SideEffect('not_really_updated', f2)
<scons_output_command>scons -Q --jobs=2</scons_output_command>
</scons_output>
- <para>
-
- Note that it might be tempting to
- use &SideEffect; for additional target files
- that a command produces.
- For example, versions the Microsoft Visual C/C++ compiler
- produce a <filename>foo.ilk</filename>
- alongside compiling <filename>foo.obj</filename> file.
- Specifying <filename>foo.ilk</filename> as a
- side-effect of <filename>foo.obj</filename>
- is <emphasis>not</emphasis> a recommended use of &SideEffect;,
- because &SCons; handle side-effect files
- slightly differently in its analysis of the dependency graph.
- When a command produces multiple output files,
- they should be specified as multiple targets of
- the call to the relevant builder function,
- and the &SideEffect; function itself should really only be used
- when it's important to ensure that commands are not executed in parallel,
- such as when a "peripheral" file (such as a log file)
- may actually updated by more than one command invocation.
-
- </para>
+ </section>
- </chapter>
-
diff --git a/doc/user/simple.xml b/doc/user/simple.xml
index 138ff54..8582613 100644
--- a/doc/user/simple.xml
+++ b/doc/user/simple.xml
@@ -459,7 +459,7 @@ int main() { printf("Goodbye, world!\n"); }
we see the output from calling the <function>print</function>
function in between the messages about
reading the &SConscript; files,
- indicating that that is when the
+ indicating that is when the
Python statements are being executed:
</para>
diff --git a/doc/user/troubleshoot.xml b/doc/user/troubleshoot.xml
index 7049deb..3906af6 100644
--- a/doc/user/troubleshoot.xml
+++ b/doc/user/troubleshoot.xml
@@ -69,8 +69,8 @@
odds are pretty good that someone else will run into
the same problem, too.
If so, please let the SCons development team know
- (preferably by filing a bug report
- or feature request at our project pages at tigris.org)
+ using the contact information at
+ <ulink url="https://scons.org/contact.html"/>
so that we can use your feedback
to try to come up with a better way to help you,
and others, get the necessary insight into &SCons; behavior
diff --git a/doc/user/variants.xml b/doc/user/variants.xml
index 0c83b04..6cf8c3d 100644
--- a/doc/user/variants.xml
+++ b/doc/user/variants.xml
@@ -13,11 +13,11 @@
%variables-mod;
]>
-<chapter id="chap-variants"
+<section id="sect-variants"
xmlns="http://www.scons.org/dbxsd/v1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
-<title>Variant Builds</title>
+<title>Variant Build Examples</title>
<!--
@@ -44,30 +44,6 @@
-->
-<!--
-
-=head1 Variant builds
-
-=head2 Variations on a theme
-
-Other variations of this model are possible. For example, you might decide
-that you want to separate out your include files into platform dependent and
-platform independent files. In this case, you'd have to define an
-alternative to C<$INCLUDE> for platform-dependent files. Most F<Conscript>
-files, generating purely platform-independent include files, would not have
-to change.
-
-You might also want to be able to compile your whole system with debugging
-or profiling, for example, enabled. You could do this with appropriate
-command line options, such as C<DEBUG=on>. This would then be translated
-into the appropriate platform-specific requirements to enable debugging
-(this might include turning off optimization, for example). You could
-optionally vary the name space for these different types of systems, but, as
-we'll see in the next section, it's not B<essential> to do this, since Cons
-is pretty smart about rebuilding things when you change options.
-
--->
-
<para>
The &variant_dir; keyword argument of
@@ -76,9 +52,15 @@ is pretty smart about rebuilding things when you change options.
variant builds using &SCons;.
Suppose, for example, that we want to
build a program for both Windows and Linux platforms,
- but that we want to build it in a shared directory
+ but that we want to build it in directory on a network share
with separate side-by-side build directories
for the Windows and Linux versions of the program.
+ We have to do a little bit of work to construct paths,
+ to make sure unwanted location dependencies don't creep in.
+ The top-relative path reference can be useful here.
+ To avoid writing conditional code based on platform,
+ we can build the <parameter>variant_dir</parameter>
+ path dynamically:
</para>
@@ -90,13 +72,15 @@ include = "#export/$PLATFORM/include"
lib = "#export/$PLATFORM/lib"
bin = "#export/$PLATFORM/bin"
-env = Environment(PLATFORM = platform,
- BINDIR = bin,
- INCDIR = include,
- LIBDIR = lib,
- CPPPATH = [include],
- LIBPATH = [lib],
- LIBS = 'world')
+env = Environment(
+ PLATFORM=platform,
+ BINDIR=bin,
+ INCDIR=include,
+ LIBDIR=lib,
+ CPPPATH=[include],
+ LIBPATH=[lib],
+ LIBS='world',
+)
Export('env')
@@ -155,20 +139,32 @@ int world() { printf "world.c\n"; }
<scons_output_command>scons -Q OS=windows</scons_output_command>
</scons_output>
- <!--
+ <para>
+
+ In order to build several variants at once when using the
+ <parameter>variant_dir</parameter> argument to &SConscript;,
+ you can call the function repeatedely - this example
+ does so in a loop. Note that the &f-link-SConscript; trick of
+ passing a list of script files, or a list of source directories,
+ does not work with <parameter>variant_dir</parameter>,
+ &SCons; allows only a single &SConscript; to be given if
+ <parameter>variant_dir</parameter> is used.
+
+ </para>
<scons_example name="variants_ex2">
<file name="SConstruct" printme="1">
-env = Environment(OS = ARGUMENTS.get('OS'))
+env = Environment(OS=ARGUMENTS.get('OS'))
for os in ['newell', 'post']:
SConscript('src/SConscript', variant_dir='build/' + os)
</file>
</scons_example>
+ <!--
<scons_output example="variants_ex2" suffix="1">
<scons_output_command>scons -Q</scons_output_command>
</scons_output>
-->
-</chapter>
+</section>
diff --git a/runtest.py b/runtest.py
index a36ba85..9e7cb2c 100755
--- a/runtest.py
+++ b/runtest.py
@@ -1,76 +1,20 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
-# runtest.py - wrapper script for running SCons tests
-#
-# The SCons test suite consists of:
-#
-# - unit tests - included in *Tests.py files from src/ dir
-# - end-to-end tests - these are *.py files in test/ directory that
-# require custom SCons framework from testing/
-#
-# This script adds SCons/ and testing/ directories to PYTHONPATH,
-# performs test discovery and processes them according to options.
-#
-# With -p (--package) option, script tests specified package from
-# build directory and sets PYTHONPATH to reference modules unpacked
-# during build process for testing purposes (build/test-*).
+"""runtest - wrapper script for running SCons tests
-"""
-Options:
- -a --all Run all tests.
- -b --baseline BASE Run test scripts against baseline BASE.
- --builddir DIR Directory in which packages were built.
- -d --debug Run test scripts under the Python debugger.
- -D --devmode Run tests in Python's development mode (3.7+ only)
- -e --external Run the script in external mode (for external Tools)
- -f --file FILE Only run tests listed in FILE.
- -j --jobs JOBS Run tests in JOBS parallel jobs.
- -k --no-progress Suppress count and percent progress messages.
- -l --list List available tests and exit.
- -n --no-exec No execute, just print command lines.
- --nopipefiles Do not use the "file pipe" workaround for Popen()
- for starting tests. WARNING: use only when too much
- file traffic is giving you trouble AND you can be
- sure that none of your tests create output >65K
- chars! You might run into some deadlocks else.
- -o --output FILE Save the output from a test run to the log file.
- -P PYTHON Use the specified Python interpreter.
- -p --package PACKAGE Test against the specified PACKAGE:
- deb Debian
- local-tar-gz .tar.gz standalone package
- local-zip .zip standalone package
- rpm Red Hat
- src-tar-gz .tar.gz source package
- src-zip .zip source package
- tar-gz .tar.gz distribution
- zip .zip distribution
- --passed Summarize which tests passed.
- -q --quiet Don't print the test being executed.
- --quit-on-failure Quit on any test failure.
- --runner CLASS Alternative test runner class for unit tests.
- -s --short-progress Short progress, prints only the command line.
- and a percentage value, based on the total and
- current number of tests.
- -t --time Print test execution time.
- -v VERSION Specify the SCons version.
- --verbose=LEVEL Set verbose level:
- 1 = print executed commands,
- 2 = print commands and non-zero output,
- 3 = print commands and all output.
- -X Test script is executable, don't feed to Python.
- -x --exec SCRIPT Test SCRIPT.
- --xml file Save results to file in SCons XML format.
- --exclude-list FILE List of tests to exclude in the current selection.
- Use to exclude tests when using the -a option.
+The SCons test suite consists of:
-Environment Variables:
- PRESERVE, PRESERVE_{PASS,FAIL,NO_RESULT}: preserve test subdirs
- TESTCMD_VERBOSE: turn on verbosity in TestCommand
+ * unit tests - *Tests.py files from the SCons/ dir
+ * end-to-end tests - *.py files in the test/ directory that
+ require the custom SCons framework from testing/
+
+This script adds SCons/ and testing/ directories to PYTHONPATH,
+performs test discovery and processes tests according to options.
"""
-import getopt
+import argparse
import glob
import os
import re
@@ -81,175 +25,198 @@ import tempfile
import threading
import time
from abc import ABC, abstractmethod
-from optparse import OptionParser, BadOptionError
+from pathlib import Path
from queue import Queue
cwd = os.getcwd()
-baseline = None
-builddir = os.path.join(cwd, 'build')
-external = 0
-devmode = False
-debug = ''
-execute_tests = True
-jobs = 1
-list_only = False
-printcommand = True
-package = None
-print_passed_summary = False
+debug = None
scons = None
-scons_exec = False
-testlistfile = None
-version = ''
-print_times = False
-python = None
-sp = []
-print_progress = True
catch_output = False
suppress_output = False
-allow_pipe_files = True
-quit_on_failure = False
-excludelistfile = None
-script = sys.argv[0].split("/")[-1]
+script = os.path.basename(sys.argv[0])
usagestr = """\
-Usage: %(script)s [OPTIONS] [TEST ...]
+%(script)s [OPTIONS] [TEST ...]
%(script)s -h|--help
""" % locals()
-helpstr = usagestr + __doc__
-
-# "Pass-through" option parsing -- an OptionParser that ignores
-# unknown options and lets them pile up in the leftover argument
-# list. Useful to gradually port getopt to optparse.
+epilogstr = """\
+Environment Variables:
+ PRESERVE, PRESERVE_{PASS,FAIL,NO_RESULT}: preserve test subdirs
+ TESTCMD_VERBOSE: turn on verbosity in TestCommand\
+"""
-class PassThroughOptionParser(OptionParser):
- def _process_long_opt(self, rargs, values):
- try:
- OptionParser._process_long_opt(self, rargs, values)
- except BadOptionError as err:
- self.largs.append(err.opt_str)
- def _process_short_opts(self, rargs, values):
- try:
- OptionParser._process_short_opts(self, rargs, values)
- except BadOptionError as err:
- self.largs.append(err.opt_str)
-
-parser = PassThroughOptionParser(add_help_option=False)
-parser.add_option('-a', '--all', action='store_true', help="Run all tests.")
-parser.add_option('-o', '--output',
- help="Save the output from a test run to the log file.")
-parser.add_option('--runner', metavar='class',
- help="Test runner class for unit tests.")
-parser.add_option('--xml', help="Save results to file in SCons XML format.")
-(options, args) = parser.parse_args()
-
-# print("options:", options)
-# print("args:", args)
-
-
-opts, args = getopt.getopt(
- args,
- "b:dDef:hj:klnP:p:qsv:Xx:t",
- [
- "baseline=",
- "builddir=",
- "debug",
- "devmode",
- "external",
- "file=",
- "help",
- "no-progress",
- "jobs=",
- "list",
- "no-exec",
- "nopipefiles",
- "package=",
- "passed",
- "python=",
- "quiet",
- "quit-on-failure",
- "short-progress",
- "time",
- "version=",
- "exec=",
- "verbose=",
- "exclude-list=",
- ],
+parser = argparse.ArgumentParser(
+ usage=usagestr, epilog=epilogstr, allow_abbrev=False,
+ formatter_class=argparse.RawDescriptionHelpFormatter
)
-for o, a in opts:
- if o in ['-b', '--baseline']:
- baseline = a
- elif o in ['--builddir']:
- builddir = a
- if not os.path.isabs(builddir):
- builddir = os.path.normpath(os.path.join(cwd, builddir))
- elif o in ['-d', '--debug']:
- for d in sys.path:
- pdb = os.path.join(d, 'pdb.py')
- if os.path.exists(pdb):
- debug = pdb
- break
- elif o in ['-D', '--devmode']:
- devmode = True
- elif o in ['-e', '--external']:
- external = True
- elif o in ['-f', '--file']:
- if not os.path.isabs(a):
- a = os.path.join(cwd, a)
- testlistfile = a
- elif o in ['-h', '--help']:
- print(helpstr)
- sys.exit(0)
- elif o in ['-j', '--jobs']:
- jobs = int(a)
- # don't let tests write stdout/stderr directly if multi-job,
- # or outputs will interleave and be hard to read
- catch_output = True
- elif o in ['-k', '--no-progress']:
- print_progress = False
- elif o in ['-l', '--list']:
- list_only = True
- elif o in ['-n', '--no-exec']:
- execute_tests = False
- elif o in ['--nopipefiles']:
- allow_pipe_files = False
- elif o in ['-p', '--package']:
- package = a
- elif o in ['--passed']:
- print_passed_summary = True
- elif o in ['-P', '--python']:
- python = a
- elif o in ['-q', '--quiet']:
- printcommand = False
- suppress_output = catch_output = True
- elif o in ['--quit-on-failure']:
- quit_on_failure = True
- elif o in ['-s', '--short-progress']:
- print_progress = True
- suppress_output = catch_output = True
- elif o in ['-t', '--time']:
- print_times = True
- elif o in ['--verbose']:
- os.environ['TESTCMD_VERBOSE'] = a
- elif o in ['-v', '--version']:
- version = a
- elif o in ['-X']:
- scons_exec = True
- elif o in ['-x', '--exec']:
- scons = a
- elif o in ['--exclude-list']:
- excludelistfile = a
-
-
-class Unbuffered():
- """ class to arrange for stdout/stderr to be unbuffered """
+# test selection options:
+testsel = parser.add_argument_group(description='Test selection options:')
+testsel.add_argument(metavar='TEST', nargs='*', dest='testlist',
+ help="Select TEST(s) (tests and/or directories) to run")
+testlisting = testsel.add_mutually_exclusive_group()
+testlisting.add_argument('-f', '--file', metavar='FILE', dest='testlistfile',
+ help="Select only tests in FILE")
+testlisting.add_argument('-a', '--all', action='store_true',
+ help="Select all tests")
+testlisting.add_argument('--retry', action='store_true',
+ help="Rerun the last failed tests in 'failed_tests.log'")
+testsel.add_argument('--exclude-list', metavar="FILE", dest='excludelistfile',
+ help="""Exclude tests in FILE from current selection""")
+testtype = testsel.add_mutually_exclusive_group()
+testtype.add_argument('--e2e-only', action='store_true',
+ help="Exclude unit tests from selection")
+testtype.add_argument('--unit-only', action='store_true',
+ help="Exclude end-to-end tests from selection")
+
+# miscellaneous options
+parser.add_argument('-b', '--baseline', metavar='BASE',
+ help="Run test scripts against baseline BASE.")
+parser.add_argument('-d', '--debug', action='store_true',
+ help="Run test scripts under the Python debugger.")
+parser.add_argument('-D', '--devmode', action='store_true',
+ help="Run tests in Python's development mode (Py3.7+ only).")
+parser.add_argument('-e', '--external', action='store_true',
+ help="Run the script in external mode (for external Tools)")
+parser.add_argument('-j', '--jobs', metavar='JOBS', default=1, type=int,
+ help="Run tests in JOBS parallel jobs.")
+parser.add_argument('-l', '--list', action='store_true', dest='list_only',
+ help="List available tests and exit.")
+parser.add_argument('-n', '--no-exec', action='store_false',
+ dest='execute_tests',
+ help="No execute, just print command lines.")
+parser.add_argument('--nopipefiles', action='store_false',
+ dest='allow_pipe_files',
+ help="""Do not use the "file pipe" workaround for subprocess
+ for starting tests. See source code for warnings.""")
+parser.add_argument('-P', '--python', metavar='PYTHON',
+ help="Use the specified Python interpreter.")
+parser.add_argument('--quit-on-failure', action='store_true',
+ help="Quit on any test failure.")
+parser.add_argument('--runner', metavar='CLASS',
+ help="Test runner class for unit tests.")
+parser.add_argument('-X', dest='scons_exec', action='store_true',
+ help="Test script is executable, don't feed to Python.")
+parser.add_argument('-x', '--exec', metavar="SCRIPT",
+ help="Test using SCRIPT as path to SCons.")
+parser.add_argument('--faillog', dest='error_log', metavar="FILE",
+ default='failed_tests.log',
+ help="Log failed tests to FILE (enabled by default, "
+ "default file 'failed_tests.log')")
+parser.add_argument('--no-faillog', dest='error_log',
+ action='store_const', const=None,
+ default='failed_tests.log',
+ help="Do not log failed tests to a file")
+
+outctl = parser.add_argument_group(description='Output control options:')
+outctl.add_argument('-k', '--no-progress', action='store_false',
+ dest='print_progress',
+ help="Suppress count and progress percentage messages.")
+outctl.add_argument('--passed', action='store_true',
+ dest='print_passed_summary',
+ help="Summarize which tests passed.")
+outctl.add_argument('-q', '--quiet', action='store_false',
+ dest='printcommand',
+ help="Don't print the test being executed.")
+outctl.add_argument('-s', '--short-progress', action='store_true',
+ help="""Short progress, prints only the command line
+ and a progress percentage.""")
+outctl.add_argument('-t', '--time', action='store_true', dest='print_times',
+ help="Print test execution time.")
+outctl.add_argument('--verbose', metavar='LEVEL', type=int, choices=range(1, 4),
+ help="""Set verbose level:
+ 1 = print executed commands,
+ 2 = print commands and non-zero output,
+ 3 = print commands and all output.""")
+# maybe add?
+# outctl.add_argument('--version', action='version', version='%s 1.0' % script)
+
+logctl = parser.add_argument_group(description='Log control options:')
+logctl.add_argument('-o', '--output', metavar='LOG', help="Save console output to LOG.")
+logctl.add_argument('--xml', metavar='XML', help="Save results to XML in SCons XML format.")
+
+# process args and handle a few specific cases:
+args = parser.parse_args()
+
+# we can't do this check with an argparse exclusive group, since those
+# only work with optional args, and the cmdline tests (args.testlist)
+# are not optional args,
+if args.testlist and (args.testlistfile or args.all or args.retry):
+ sys.stderr.write(
+ parser.format_usage()
+ + "error: command line tests cannot be combined with -f/--file, -a/--all or --retry\n"
+ )
+ sys.exit(1)
+
+if args.retry:
+ args.testlistfile = 'failed_tests.log'
+
+if args.testlistfile:
+ # args.testlistfile changes from a string to a pathlib Path object
+ try:
+ p = Path(args.testlistfile)
+ if sys.version_info.major == 3 and sys.version_info.minor < 6:
+ args.testlistfile = p.resolve()
+ else:
+ args.testlistfile = p.resolve(strict=True)
+ except FileNotFoundError:
+ sys.stderr.write(
+ parser.format_usage()
+ + "error: -f/--file testlist file \"%s\" not found\n" % p
+ )
+ sys.exit(1)
+
+if args.excludelistfile:
+ # args.excludelistfile changes from a string to a pathlib Path object
+ try:
+ p = Path(args.excludelistfile)
+ if sys.version_info.major == 3 and sys.version_info.minor < 6:
+ args.excludelistfile = p.resolve()
+ else:
+ args.excludelistfile = p.resolve(strict=True)
+ except FileNotFoundError:
+ sys.stderr.write(
+ parser.format_usage()
+ + "error: --exclude-list file \"%s\" not found\n" % p
+ )
+ sys.exit(1)
+
+if args.jobs > 1:
+ # don't let tests write stdout/stderr directly if multi-job,
+ # else outputs will interleave and be hard to read
+ catch_output = True
+
+if not args.printcommand:
+ suppress_output = catch_output = True
+
+if args.verbose:
+ os.environ['TESTCMD_VERBOSE'] = str(args.verbose)
+
+if args.short_progress:
+ args.print_progress = True
+ suppress_output = catch_output = True
+
+if args.debug:
+ for d in sys.path:
+ pdb = os.path.join(d, 'pdb.py')
+ if os.path.exists(pdb):
+ debug = pdb
+ break
+
+if args.exec:
+ scons = args.exec
+
+# --- setup stdout/stderr ---
+class Unbuffered:
def __init__(self, file):
self.file = file
+
def write(self, arg):
self.file.write(arg)
self.file.flush()
+
def __getattr__(self, attr):
return getattr(self.file, attr)
@@ -259,9 +226,9 @@ sys.stderr = Unbuffered(sys.stderr)
# possible alternative: switch to using print, and:
# print = functools.partial(print, flush)
-if options.output:
- logfile = open(options.output, 'w')
- class Tee():
+if args.output:
+ logfile = open(args.output, 'w')
+ class Tee:
def __init__(self, openfile, stream):
self.file = openfile
self.stream = stream
@@ -273,6 +240,7 @@ if options.output:
# --- define helpers ----
if sys.platform in ('win32', 'cygwin'):
+
def whereis(file):
pathext = [''] + os.environ['PATHEXT'].split(os.pathsep)
for d in os.environ['PATH'].split(os.pathsep):
@@ -284,6 +252,7 @@ if sys.platform in ('win32', 'cygwin'):
return None
else:
+
def whereis(file):
for d in os.environ['PATH'].split(os.pathsep):
f = os.path.join(d, file)
@@ -296,13 +265,9 @@ else:
return f
return None
-sp.append(builddir)
-sp.append(cwd)
-#
_ws = re.compile(r'\s')
-
def escape(s):
if _ws.search(s):
s = '"' + s + '"'
@@ -313,12 +278,14 @@ def escape(s):
if not catch_output:
# Without any output suppressed, we let the subprocess
# write its stuff freely to stdout/stderr.
- def spawn_it(command_args):
- cp = subprocess.run(command_args, shell=False)
+
+ def spawn_it(command_args, env):
+ cp = subprocess.run(command_args, shell=False, env=env)
return cp.stdout, cp.stderr, cp.returncode
+
else:
# Else, we catch the output of both pipes...
- if allow_pipe_files:
+ if args.allow_pipe_files:
# The subprocess.Popen() suffers from a well-known
# problem. Data for stdout/stderr is read into a
# memory buffer of fixed size, 65K which is not very much.
@@ -327,18 +294,22 @@ else:
# be able to write the rest of its output. Hang!
# In order to work around this, we follow a suggestion
# by Anders Pearson in
- # http://http://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/
+ # https://thraxil.org/users/anders/posts/2008/03/13/Subprocess-Hanging-PIPE-is-your-enemy/
# and pass temp file objects to Popen() instead of the ubiquitous
# subprocess.PIPE.
- def spawn_it(command_args):
+
+ def spawn_it(command_args, env):
# Create temporary files
tmp_stdout = tempfile.TemporaryFile(mode='w+t')
tmp_stderr = tempfile.TemporaryFile(mode='w+t')
# Start subprocess...
- cp = subprocess.run(command_args,
- stdout=tmp_stdout,
- stderr=tmp_stderr,
- shell=False)
+ cp = subprocess.run(
+ command_args,
+ stdout=tmp_stdout,
+ stderr=tmp_stderr,
+ shell=False,
+ env=env,
+ )
try:
# Rewind to start of files
@@ -368,11 +339,15 @@ else:
# (but the subprocess isn't writing anything there).
# Hence a deadlock.
# Be dragons here! Better don't use this!
- def spawn_it(command_args):
- cp = subprocess.run(command_args,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=False)
+
+ def spawn_it(command_args, env):
+ cp = subprocess.run(
+ command_args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=False,
+ env=env,
+ )
return cp.stdout, cp.stderr, cp.returncode
@@ -400,8 +375,8 @@ class RuntestBase(ABC):
class SystemExecutor(RuntestBase):
""" Test class for tests executed with spawn_it() """
- def execute(self):
- self.stderr, self.stdout, s = spawn_it(self.command_args)
+ def execute(self, env):
+ self.stderr, self.stdout, s = spawn_it(self.command_args, env)
self.status = s
if s < 0 or s > 2:
sys.stdout.write("Unexpected exit status %d\n" % s)
@@ -414,21 +389,25 @@ class PopenExecutor(RuntestBase):
by calling subprocess.run (behind the covers uses Popen.
Very similar to SystemExecutor, but uses command_str
instead of command_args, and doesn't allow for not catching
- the output.
+ the output).
"""
# For an explanation of the following 'if ... else'
# and the 'allow_pipe_files' option, please check out the
# definition of spawn_it() above.
- if allow_pipe_files:
- def execute(self):
+ if args.allow_pipe_files:
+
+ def execute(self, env):
# Create temporary files
tmp_stdout = tempfile.TemporaryFile(mode='w+t')
tmp_stderr = tempfile.TemporaryFile(mode='w+t')
# Start subprocess...
- cp = subprocess.run(self.command_str.split(),
- stdout=tmp_stdout,
- stderr=tmp_stderr,
- shell=False)
+ cp = subprocess.run(
+ self.command_str.split(),
+ stdout=tmp_stdout,
+ stderr=tmp_stderr,
+ shell=False,
+ env=env,
+ )
self.status = cp.returncode
try:
@@ -443,14 +422,16 @@ class PopenExecutor(RuntestBase):
tmp_stdout.close()
tmp_stderr.close()
else:
- def execute(self):
- cp = subprocess.run(self.command_str.split(),
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=False)
- self.status = cp.returncode
- self.stdout = cp.stdout
- self.stderr = cp.stderr
+
+ def execute(self, env):
+ cp = subprocess.run(
+ self.command_str.split(),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=False,
+ env=env,
+ )
+ self.status, self.stdout, self.stderr = cp.returncode, cp.stdout, cp.stderr
class XML(PopenExecutor):
""" Test class for tests that will output in scons xml """
@@ -472,92 +453,97 @@ class XML(PopenExecutor):
f.write(' <time>%.1f</time>\n' % self.total_time)
f.write(' </results>\n')
-if options.xml:
+if args.xml:
Test = XML
else:
Test = SystemExecutor
# --- start processing ---
-sd = None
-tools_dir = None
-ld = None
-
-if not baseline or baseline == '.':
- base = cwd
-elif baseline == '-':
+if not args.baseline or args.baseline == '.':
+ baseline = cwd
+elif args.baseline == '-':
print("This logic used to checkout from svn. It's been removed. If you used this, please let us know on devel mailing list, IRC, or discord server")
sys.exit(-1)
else:
- base = baseline
+ baseline = args.baseline
+scons_runtest_dir = baseline
-scons_runtest_dir = base
-
-if not external:
- scons_script_dir = sd or os.path.join(base, 'scripts')
- scons_tools_dir = tools_dir or os.path.join(base, 'bin')
- scons_lib_dir = ld or base
+if not args.external:
+ scons_script_dir = os.path.join(baseline, 'scripts')
+ scons_tools_dir = os.path.join(baseline, 'bin')
+ scons_lib_dir = baseline
else:
- scons_script_dir = sd or ''
- scons_tools_dir = tools_dir or ''
- scons_lib_dir = ld or ''
+ scons_script_dir = ''
+ scons_tools_dir = ''
+ scons_lib_dir = ''
-pythonpath_dir = scons_lib_dir
+testenv = {
+ 'SCONS_RUNTEST_DIR': scons_runtest_dir,
+ 'SCONS_TOOLS_DIR': scons_tools_dir,
+ 'SCONS_SCRIPT_DIR': scons_script_dir,
+ 'SCONS_CWD': cwd,
+}
if scons:
# Let the version of SCons that the -x option pointed to find
# its own modules.
- os.environ['SCONS'] = scons
+ testenv['SCONS'] = scons
elif scons_lib_dir:
# Because SCons is really aggressive about finding its modules,
# it sometimes finds SCons modules elsewhere on the system.
# This forces SCons to use the modules that are being tested.
- os.environ['SCONS_LIB_DIR'] = scons_lib_dir
+ testenv['SCONS_LIB_DIR'] = scons_lib_dir
-if scons_exec:
- os.environ['SCONS_EXEC'] = '1'
+if args.scons_exec:
+ testenv['SCONS_EXEC'] = '1'
-if external:
- os.environ['SCONS_EXTERNAL_TEST'] = '1'
+if args.external:
+ testenv['SCONS_EXTERNAL_TEST'] = '1'
-os.environ['SCONS_RUNTEST_DIR'] = scons_runtest_dir
-os.environ['SCONS_SCRIPT_DIR'] = scons_script_dir
-os.environ['SCONS_TOOLS_DIR'] = scons_tools_dir
-os.environ['SCONS_CWD'] = cwd
-os.environ['SCONS_VERSION'] = version
+# Insert scons path and path for testing framework to PYTHONPATH
+scriptpath = os.path.dirname(os.path.realpath(__file__))
+frameworkpath = os.path.join(scriptpath, 'testing', 'framework')
+testenv['PYTHONPATH'] = os.pathsep.join((scons_lib_dir, frameworkpath))
+pythonpath = os.environ.get('PYTHONPATH')
+if pythonpath:
+ testenv['PYTHONPATH'] = testenv['PYTHONPATH'] + os.pathsep + pythonpath
-old_pythonpath = os.environ.get('PYTHONPATH')
+os.environ.update(testenv)
# Clear _JAVA_OPTIONS which java tools output to stderr when run breaking tests
if '_JAVA_OPTIONS' in os.environ:
del os.environ['_JAVA_OPTIONS']
-# FIXME: the following is necessary to pull in half of the testing
-# harness from $srcdir/etc. Those modules should be transfered
-# to testing/, in which case this manipulation of PYTHONPATH
-# should be able to go away.
-pythonpaths = [pythonpath_dir]
-
-scriptpath = os.path.dirname(os.path.realpath(__file__))
-
-# Add path for testing framework to PYTHONPATH
-pythonpaths.append(os.path.join(scriptpath, 'testing', 'framework'))
-
-
-os.environ['PYTHONPATH'] = os.pathsep.join(pythonpaths)
-
-if old_pythonpath:
- os.environ['PYTHONPATH'] = os.environ['PYTHONPATH'] + \
- os.pathsep + \
- old_pythonpath
-
# ---[ test discovery ]------------------------------------
+# This section figures which tests to run.
+#
+# The initial testlist is made by reading from the testlistfile,
+# if supplied, or by looking at the test arguments, if supplied,
+# or by looking for all test files if the "all" argument is supplied.
+# One of the three is required.
+#
+# Each test path, whichever of the three sources it comes from,
+# specifies either a test file or a directory to search for
+# SCons tests. SCons code layout assumes that any file under the 'SCons'
+# subdirectory that ends with 'Tests.py' is a unit test, and any Python
+# script (*.py) under the 'test' subdirectory is an end-to-end test.
+# We need to track these because they are invoked differently.
+# find_unit_tests and find_e2e_tests are used for this searching.
+#
+# Note that there are some tests under 'SCons' that *begin* with
+# 'test_', but they're packaging and installation tests, not
+# functional tests, so we don't execute them by default. (They can
+# still be executed by hand, though).
+#
+# Test exclusions, if specified, are then applied.
-tests = []
-excludetests = []
-unittests = []
-endtests = []
+
+def scanlist(testlist):
+ """ Process a testlist file """
+ tests = [t.strip() for t in testlist if not t.startswith('#')]
+ return [t for t in tests if t]
def find_unit_tests(directory):
@@ -576,14 +562,13 @@ def find_unit_tests(directory):
def find_e2e_tests(directory):
""" Look for end-to-end tests """
result = []
-
for dirpath, dirnames, filenames in os.walk(directory):
# Skip folders containing a sconstest.skip file
if 'sconstest.skip' in filenames:
continue
try:
with open(os.path.join(dirpath, ".exclude_tests")) as f:
- excludes = [e.split("#", 1)[0].strip() for e in f.readlines()]
+ excludes = scanlist(f)
except EnvironmentError:
excludes = []
for fname in filenames:
@@ -592,95 +577,79 @@ def find_e2e_tests(directory):
return sorted(result)
-if testlistfile:
- with open(testlistfile, 'r') as f:
- tests = f.readlines()
- tests = [x for x in tests if x[0] != '#']
- tests = [x[:-1] for x in tests]
- tests = [x.strip() for x in tests]
- tests = [x for x in tests if x]
+# initial selection:
+unittests = []
+endtests = []
+if args.testlistfile:
+ with args.testlistfile.open() as f:
+ tests = scanlist(f)
else:
testpaths = []
-
- # Each test path specifies a test file, or a directory to search for
- # SCons tests. SCons code layout assumes that any file under the 'SCons'
- # subdirectory that ends with 'Tests.py' is a unit test, and any Python
- # script (*.py) under the 'test' subdirectory an end-to-end test.
- # We need to track these because they are invoked differently.
- #
- # Note that there are some tests under 'SCons' that *begin* with
- # 'test_', but they're packaging and installation tests, not
- # functional tests, so we don't execute them by default. (They can
- # still be executed by hand, though).
-
- if options.all:
+ if args.all:
testpaths = ['SCons', 'test']
- elif args:
- testpaths = args
+ elif args.testlist:
+ testpaths = args.testlist
for tp in testpaths:
# Clean up path so it can match startswith's below
- # sys.stderr.write("Changed:%s->"%tp)
# remove leading ./ or .\
- if tp[0] == '.' and tp[1] in (os.sep, os.altsep):
+ if tp.startswith('.') and tp[1] in (os.sep, os.altsep):
tp = tp[2:]
- # tp = os.path.normpath(tp)
- # sys.stderr.write('->%s<-'%tp)
- # sys.stderr.write("to:%s\n"%tp)
+
for path in glob.glob(tp):
if os.path.isdir(path):
- if path.startswith('SCons') or path.startswith('testing'):
- for p in find_unit_tests(path):
- unittests.append(p)
+ if path.startswith(('SCons', 'testing')):
+ unittests.extend(find_unit_tests(path))
elif path.startswith('test'):
- for p in find_e2e_tests(path):
- endtests.append(p)
+ endtests.extend(find_e2e_tests(path))
else:
if path.endswith("Tests.py"):
unittests.append(path)
- else:
+ elif path.endswith(".py"):
endtests.append(path)
+ tests = sorted(unittests + endtests)
+
- tests.extend(unittests)
- tests.extend(endtests)
- tests.sort()
+# Remove exclusions:
+if args.e2e_only:
+ tests = [t for t in tests if not t.endswith("Tests.py")]
+if args.unit_only:
+ tests = [t for t in tests if t.endswith("Tests.py")]
+if args.excludelistfile:
+ with args.excludelistfile.open() as f:
+ excludetests = scanlist(f)
+ tests = [t for t in tests if t not in excludetests]
if not tests:
- sys.stderr.write(usagestr + """
-runtest.py: No tests were found.
- Tests can be specified on the command line, read from file
- with -f option, or discovered with -a to run all tests.
+ sys.stderr.write(parser.format_usage() + """
+error: no tests were found.
+ Tests can be specified on the command line, read from a file with
+ the -f/--file option, or discovered with -a/--all to run all tests.
""")
sys.exit(1)
-if excludelistfile:
- with open(excludelistfile, 'r') as f:
- excludetests = f.readlines()
- excludetests = [x for x in excludetests if x[0] != '#']
- excludetests = [x[:-1] for x in excludetests]
- excludetests = [x.strip() for x in excludetests]
- excludetests = [x for x in excludetests if x]
-
# ---[ test processing ]-----------------------------------
-tests = [t for t in tests if t not in excludetests]
tests = [Test(t, n + 1) for n, t in enumerate(tests)]
-if list_only:
+if args.list_only:
for t in tests:
sys.stdout.write(t.path + "\n")
sys.exit(0)
-if not python:
+if not args.python:
if os.name == 'java':
- python = os.path.join(sys.prefix, 'jython')
+ args.python = os.path.join(sys.prefix, 'jython')
else:
- python = sys.executable
-os.environ["python_executable"] = python
+ args.python = sys.executable
+os.environ["python_executable"] = args.python
+
+if args.print_times:
-if print_times:
def print_time(fmt, tm):
sys.stdout.write(fmt % tm)
+
else:
+
def print_time(fmt, tm):
pass
@@ -697,10 +666,9 @@ def log_result(t, io_lock=None):
we need to lock access to the log to avoid interleaving. The same
would apply if output was a file.
- :param t: a completed testcase
- :type t: Test
- :param io_lock:
- :type io_lock: threading.Lock
+ Args:
+ t (Test): (completed) testcase instance
+ io_lock (threading.lock): (optional) lock to use
"""
# there is no lock in single-job run, which includes
@@ -720,30 +688,41 @@ def log_result(t, io_lock=None):
if io_lock:
io_lock.release()
- if quit_on_failure and t.status == 1:
+ if args.quit_on_failure and t.status == 1:
print("Exiting due to error")
print(t.status)
sys.exit(1)
def run_test(t, io_lock=None, run_async=True):
+ """ Run a testcase.
+
+ Builds the command line to give to execute().
+ Also the best place to record some information that will be
+ used in output, which in some conditions is printed here.
+
+ Args:
+ t (Test): testcase instance
+ io_lock (threading.Lock): (optional) lock to use
+ run_async (bool): whether to run asynchronously
+ """
+
t.headline = ""
command_args = []
if debug:
command_args.append(debug)
- if devmode and sys.version_info >= (3, 7, 0):
- command_args.append('-X dev')
+ if args.devmode and sys.version_info >= (3, 7, 0):
+ command_args.append('-X dev')
command_args.append(t.path)
- if options.runner and t.path in unittests:
+ if args.runner and t.path in unittests:
# For example --runner TestUnit.TAPTestRunner
- command_args.append('--runner ' + options.runner)
- t.command_args = [escape(python)] + command_args
- t.command_str = " ".join([escape(python)] + command_args)
- if printcommand:
- if print_progress:
+ command_args.append('--runner ' + args.runner)
+ t.command_args = [escape(args.python)] + command_args
+ t.command_str = " ".join(t.command_args)
+ if args.printcommand:
+ if args.print_progress:
t.headline += "%d/%d (%.2f%s) %s\n" % (
- t.num,
- total_num_tests,
+ t.num, total_num_tests,
float(t.num) * 100.0 / float(total_num_tests),
"%",
t.command_str,
@@ -753,29 +732,33 @@ def run_test(t, io_lock=None, run_async=True):
if not suppress_output and not catch_output:
# defer printing the headline until test is done
sys.stdout.write(t.headline)
- head, tail = os.path.split(t.abspath)
+ head, _ = os.path.split(t.abspath)
fixture_dirs = []
if head:
fixture_dirs.append(head)
fixture_dirs.append(os.path.join(scriptpath, 'test', 'fixture'))
- os.environ['FIXTURE_DIRS'] = os.pathsep.join(fixture_dirs)
+
+ # Set the list of fixture dirs directly in the environment. Just putting
+ # it in os.environ and spawning the process is racy. Make it reliable by
+ # overriding the environment passed to execute().
+ env = dict(os.environ)
+ env['FIXTURE_DIRS'] = os.pathsep.join(fixture_dirs)
test_start_time = time_func()
- if execute_tests:
- t.execute()
+ if args.execute_tests:
+ t.execute(env)
t.test_time = time_func() - test_start_time
log_result(t, io_lock=io_lock)
class RunTest(threading.Thread):
- """ Test Runner class
+ """ Test Runner class.
One instance will be created for each job thread in multi-job mode
"""
- def __init__(self, queue=None, io_lock=None,
- group=None, target=None, name=None, args=(), kwargs=None):
- super(RunTest, self).__init__(group=group, target=target, name=name)
+ def __init__(self, queue=None, io_lock=None, group=None, target=None, name=None):
+ super().__init__(group=group, target=target, name=name)
self.queue = queue
self.io_lock = io_lock
@@ -784,14 +767,14 @@ class RunTest(threading.Thread):
run_test(t, io_lock=self.io_lock, run_async=True)
self.queue.task_done()
-if jobs > 1:
- print("Running tests using %d jobs" % jobs)
+if args.jobs > 1:
+ print("Running tests using %d jobs" % args.jobs)
testq = Queue()
for t in tests:
testq.put(t)
testlock = threading.Lock()
# Start worker threads to consume the queue
- threads = [RunTest(queue=testq, io_lock=testlock) for _ in range(jobs)]
+ threads = [RunTest(queue=testq, io_lock=testlock) for _ in range(args.jobs)]
for t in threads:
t.daemon = True
t.start()
@@ -810,8 +793,9 @@ passed = [t for t in tests if t.status == 0]
fail = [t for t in tests if t.status == 1]
no_result = [t for t in tests if t.status == 2]
-if len(tests) != 1 and execute_tests:
- if passed and print_passed_summary:
+# print summaries, but only if multiple tests were run
+if len(tests) != 1 and args.execute_tests:
+ if passed and args.print_passed_summary:
if len(passed) == 1:
sys.stdout.write("\nPassed the following test:\n")
else:
@@ -833,21 +817,29 @@ if len(tests) != 1 and execute_tests:
paths = [x.path for x in no_result]
sys.stdout.write("\t" + "\n\t".join(paths) + "\n")
-if options.xml:
- if options.xml == '-':
+# save the fails to a file
+if fail and args.error_log:
+ paths = [x.path for x in fail]
+ #print(f"DEBUG: Writing fails to {args.error_log}")
+ with open(args.error_log, "w") as f:
+ for test in paths:
+ print(test, file=f)
+
+if args.xml:
+ if args.output == '-':
f = sys.stdout
else:
- f = open(options.xml, 'w')
+ f = open(args.xml, 'w')
tests[0].header(f)
#f.write("test_result = [\n")
for t in tests:
t.write(f)
tests[0].footer(f)
#f.write("];\n")
- if options.xml != '-':
+ if args.output != '-':
f.close()
-if options.output:
+if args.output:
if isinstance(sys.stdout, Tee):
sys.stdout.file.close()
if isinstance(sys.stderr, Tee):
@@ -856,6 +848,7 @@ if options.output:
if fail:
sys.exit(1)
elif no_result:
+ # if no fails, but skips were found
sys.exit(2)
else:
sys.exit(0)
diff --git a/setup.cfg b/setup.cfg
index 1243fd2..421542f 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -20,7 +20,7 @@ project-urls =
classifiers =
Development Status :: 5 - Production/Stable
- Topic :: Utilities
+ Topic :: Software Development :: Build Tools
Programming Language :: Python
Programming Language :: Python :: 3
Programming Language :: Python :: 3 :: Only
@@ -28,6 +28,7 @@ classifiers =
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
+ Programming Language :: Python :: 3.9
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
@@ -42,7 +43,6 @@ zip_safe = False
python_requires = >=3.5
install_requires =
setuptools
- pywin32 >= 1.0;platform_system=="Windows"
setup_requires = setuptools
include_package_data = True
@@ -61,13 +61,20 @@ console_scripts =
[options.package_data]
-* = *.txt, *.rst
+* = *.txt, *.rst, *.1
SCons.Tool.docbook = *.*
+
+[options.data_files]
+. = build/doc/man/scons.1
+ build/doc/man/scons-time.1
+ build/doc/man/sconsign.1
+
[sdist]
dist-dir=build/dist
[bdist_wheel]
; We're now py3 only
;universal=true
-dist-dir=build/dist \ No newline at end of file
+dist-dir=build/dist
+
diff --git a/setup.py b/setup.py
index 8ea0246..6d52278 100644
--- a/setup.py
+++ b/setup.py
@@ -7,11 +7,13 @@ from setuptools.command.build_py import build_py as build_py_orig
import codecs
import os.path
+
def read(rel_path):
here = os.path.abspath(os.path.dirname(__file__))
with codecs.open(os.path.join(here, rel_path), 'r') as fp:
return fp.read()
+
def get_version(rel_path):
for line in read(rel_path).splitlines():
if line.startswith('__version__'):
@@ -21,7 +23,6 @@ def get_version(rel_path):
raise RuntimeError("Unable to find version string.")
-
exclude = ['*Tests']
diff --git a/site_scons/scons_local_package.py b/site_scons/scons_local_package.py
index 5e633e9..aaf058a 100644
--- a/site_scons/scons_local_package.py
+++ b/site_scons/scons_local_package.py
@@ -1,4 +1,6 @@
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -60,6 +62,12 @@ def install_local_package_files(env):
fn = os.path.basename(bf)
all_local_installed.append(env.SCons_revision('#/build/scons-local/%s'%fn, bf))
+ # Now copy manpages into scons-local package
+ built_manpage_files = env.Glob('build/doc/man/*.1')
+ for bmp in built_manpage_files:
+ fn = os.path.basename(str(bmp))
+ all_local_installed.append(env.SCons_revision('#/build/scons-local/%s'%fn, bmp))
+
rename_files = [('scons-${VERSION}.bat', 'scripts/scons.bat'),
('scons-README', 'README-local'),
('scons-LICENSE', 'LICENSE-local')]
diff --git a/site_scons/update_build_info.py b/site_scons/update_build_info.py
index b9d565a..59ddf0c 100644
--- a/site_scons/update_build_info.py
+++ b/site_scons/update_build_info.py
@@ -14,3 +14,4 @@ def update_init_file(env):
'import SCons.compat # noqa'],
)
env.Precious(si)
+ env.NoClean(si) # Don't clean this file as it breaks the build.
diff --git a/template/Tests.py b/template/Tests.py
index 4d62e0a..a615314 100644
--- a/template/Tests.py
+++ b/template/Tests.py
@@ -1,5 +1,6 @@
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -19,9 +20,11 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+"""
+Template for unit-test file.
+Replace this with a description of the test.
+"""
import unittest
diff --git a/template/__init__.py b/template/__init__.py
deleted file mode 100644
index caae1ba..0000000
--- a/template/__init__.py
+++ /dev/null
@@ -1,68 +0,0 @@
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-"""SCons
-
-The main package for the SCons software construction utility.
-
-"""
-
-#
-# __COPYRIGHT__
-#
-# Permission is hereby granted, free of charge, to any person obtaining
-# a copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-#
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
-# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
-# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__REVISION__"
-__version__ = "__VERSION__"
-__build__ = "__BUILD__"
-__buildsys__ = "__BUILDSYS__"
-__date__ = "__DATE__"
-__developer__ = "__DEVELOPER__"
-__copyright__ = "__COPYRIGHT__"
-
-# make sure compatibility is always in place
-import SCons.compat # noqa
-
-# Local Variables:
-# tab-width:4
-# indent-tabs-mode:nil
-# End:
-# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/template/file.py b/template/file.py
index f506de4..8c95d01 100644
--- a/template/file.py
+++ b/template/file.py
@@ -1,11 +1,6 @@
-"""${subst '/' '.' ${subst '^src/' '' ${subst '\.py$' '' $filename}}}
-
-XXX
-
-"""
-
+# MIT License
#
-# __COPYRIGHT__
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -25,11 +20,11 @@ XXX
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
+"""
+Template for an SCons source file.
+Replace this with the purpose of the file.
+"""
import XXX
diff --git a/template/test.py b/template/test.py
index 0463cbf..b60f40f 100644
--- a/template/test.py
+++ b/template/test.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright 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 +22,10 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
-XXX Put a description of the test here.
+Template for end-to-end test file.
+Replace this with a description of the test.
"""
import TestSCons
diff --git a/test/AR/AR.py b/test/AR/AR.py
index 552b827..2b92ff4 100644
--- a/test/AR/AR.py
+++ b/test/AR/AR.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/AR/ARFLAGS.py b/test/AR/ARFLAGS.py
index 2aa1a14..21b3793 100644
--- a/test/AR/ARFLAGS.py
+++ b/test/AR/ARFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/AS/AS.py b/test/AS/AS.py
index 56a1498..0b6611d 100644
--- a/test/AS/AS.py
+++ b/test/AS/AS.py
@@ -29,8 +29,6 @@ Verify the ability to set the $AS construction variable to a different
assembler (a wrapper we create).
"""
-import os
-import sys
import TestSCons
diff --git a/test/AS/ASFLAGS.py b/test/AS/ASFLAGS.py
index 52f44af..4a1c162 100644
--- a/test/AS/ASFLAGS.py
+++ b/test/AS/ASFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import sys
import TestSCons
diff --git a/test/AS/ASPP.py b/test/AS/ASPP.py
index 64e1080..9c8f047 100644
--- a/test/AS/ASPP.py
+++ b/test/AS/ASPP.py
@@ -24,8 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
-import sys
import TestSCons
diff --git a/test/AS/ASPPFLAGS.py b/test/AS/ASPPFLAGS.py
index 5dd9a38..f7d7c5c 100644
--- a/test/AS/ASPPFLAGS.py
+++ b/test/AS/ASPPFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import sys
import TestSCons
diff --git a/test/Actions/append.py b/test/Actions/append.py
index 0a59c42..b5d4c3a 100644
--- a/test/Actions/append.py
+++ b/test/Actions/append.py
@@ -30,7 +30,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
import stat
-import sys
import TestSCons
_exe = TestSCons._exe
diff --git a/test/Actions/pre-post.py b/test/Actions/pre-post.py
index 4d22b07..358aa43 100644
--- a/test/Actions/pre-post.py
+++ b/test/Actions/pre-post.py
@@ -28,7 +28,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
-import stat
import TestSCons
diff --git a/test/Builder/errors.py b/test/Builder/errors.py
index bd7e100..375e052 100644
--- a/test/Builder/errors.py
+++ b/test/Builder/errors.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test the ability to catch Builder creation with poorly specified Actions.
"""
-import os.path
import TestSCons
diff --git a/test/CC/CCVERSION.py b/test/CC/CCVERSION.py
index 7e829f0..3ee601f 100644
--- a/test/CC/CCVERSION.py
+++ b/test/CC/CCVERSION.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import sys
import TestSCons
diff --git a/test/CC/SHCC.py b/test/CC/SHCC.py
index c756219..1c9f68d 100644
--- a/test/CC/SHCC.py
+++ b/test/CC/SHCC.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/CFILESUFFIX.py b/test/CFILESUFFIX.py
index 7af4fa4..0a62307 100644
--- a/test/CFILESUFFIX.py
+++ b/test/CFILESUFFIX.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify that we can set CFILESUFFIX to arbitrary values.
"""
-import os
import TestSCons
diff --git a/test/CXX/CXX.py b/test/CXX/CXX.py
index abccf1e..4be4199 100644
--- a/test/CXX/CXX.py
+++ b/test/CXX/CXX.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import sys
import TestSCons
diff --git a/test/CXX/CXXFILESUFFIX.py b/test/CXX/CXXFILESUFFIX.py
index 48d727e..0ae5827 100644
--- a/test/CXX/CXXFILESUFFIX.py
+++ b/test/CXX/CXXFILESUFFIX.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/CacheDir/CacheDir_TryCompile.py b/test/CacheDir/CacheDir_TryCompile.py
index bb22835..dbea9be 100644
--- a/test/CacheDir/CacheDir_TryCompile.py
+++ b/test/CacheDir/CacheDir_TryCompile.py
@@ -32,7 +32,6 @@ could be bytes instead of a string which would fail when combining cache signatu
which ended up a mixture of bytes and strings.
"""
-import os
import TestSCons
diff --git a/test/CacheDir/NoCache.py b/test/CacheDir/NoCache.py
index 8ecfeb3..506a859 100644
--- a/test/CacheDir/NoCache.py
+++ b/test/CacheDir/NoCache.py
@@ -28,7 +28,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify that the NoCache environment method works.
"""
-import TestSCons, os.path
+import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/CacheDir/multiple-targets.py b/test/CacheDir/multiple-targets.py
index 99ab8da..d985ca0 100644
--- a/test/CacheDir/multiple-targets.py
+++ b/test/CacheDir/multiple-targets.py
@@ -28,8 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test that multiple target files get retrieved from a CacheDir correctly.
"""
-import os.path
-import shutil
import TestSCons
diff --git a/test/CacheDir/option--cd.py b/test/CacheDir/option--cd.py
index 1620858..3ea739c 100644
--- a/test/CacheDir/option--cd.py
+++ b/test/CacheDir/option--cd.py
@@ -29,8 +29,6 @@ Test the --cache-disable option when retrieving derived files from a
CacheDir.
"""
-import os.path
-import shutil
import TestSCons
diff --git a/test/CacheDir/option--cr.py b/test/CacheDir/option--cr.py
index b7696c5..0395876 100644
--- a/test/CacheDir/option--cr.py
+++ b/test/CacheDir/option--cr.py
@@ -29,8 +29,6 @@ Test the --cache-readonly option when retrieving derived files from a
CacheDir. It should retrieve as normal but not update files.
"""
-import os.path
-import shutil
import TestSCons
diff --git a/test/CacheDir/option--cs.py b/test/CacheDir/option--cs.py
index feb89bd..a2b09ed 100644
--- a/test/CacheDir/option--cs.py
+++ b/test/CacheDir/option--cs.py
@@ -29,8 +29,6 @@ Test printing build actions when using the --cache-show option and
retrieving derived files from a CacheDir.
"""
-import os.path
-import shutil
import TestSCons
diff --git a/test/CacheDir/readonly-cache.py b/test/CacheDir/readonly-cache.py
index 63cfd22..4aad0ee 100755
--- a/test/CacheDir/readonly-cache.py
+++ b/test/CacheDir/readonly-cache.py
@@ -32,7 +32,6 @@ import glob
import os
import TestSCons
import time
-from stat import *
test = TestSCons.TestSCons()
diff --git a/test/CacheDir/scanner-target.py b/test/CacheDir/scanner-target.py
index 249e587..202910b 100644
--- a/test/CacheDir/scanner-target.py
+++ b/test/CacheDir/scanner-target.py
@@ -31,8 +31,6 @@ to push the file to the CacheDir after the build signature had already
been cleared (as a sign that the built file should now be rescanned).
"""
-import os.path
-import shutil
import TestSCons
diff --git a/test/Clean/Option.py b/test/Clean/Option.py
index 5795ff2..c63dff7 100644
--- a/test/Clean/Option.py
+++ b/test/Clean/Option.py
@@ -29,7 +29,6 @@ Verify that {Set,Get}Option('clean') works correctly to control
cleaning behavior.
"""
-import os
import TestSCons
diff --git a/test/CommandGenerator.py b/test/CommandGenerator.py
index b8155e7..5cae4a6 100644
--- a/test/CommandGenerator.py
+++ b/test/CommandGenerator.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
diff --git a/test/CompilationDatabase/fixture/SConstruct_variant b/test/CompilationDatabase/fixture/SConstruct_variant
index f47c732..ea461fb 100644
--- a/test/CompilationDatabase/fixture/SConstruct_variant
+++ b/test/CompilationDatabase/fixture/SConstruct_variant
@@ -32,6 +32,10 @@ env.CompilationDatabase('compile_commands_over_rel.json', COMPILATIONDB_USE_ABSP
env.CompilationDatabase('compile_commands_over_abs_1.json', COMPILATIONDB_USE_ABSPATH=1)
env.CompilationDatabase('compile_commands_over_abs_0.json', COMPILATIONDB_USE_ABSPATH=0)
+# Try filter for build and build2 output
+env.CompilationDatabase('compile_commands_filter_build.json', COMPILATIONDB_PATH_FILTER='build/*')
+env.CompilationDatabase('compile_commands_filter_build2.json', COMPILATIONDB_PATH_FILTER='build2/*')
+
env.VariantDir('build','src')
env.Program('build/main', 'build/test_main.c')
diff --git a/test/CompilationDatabase/variant_dir.py b/test/CompilationDatabase/variant_dir.py
index a36e516..6a2675b 100644
--- a/test/CompilationDatabase/variant_dir.py
+++ b/test/CompilationDatabase/variant_dir.py
@@ -56,6 +56,14 @@ abs_files = [
'compile_commands_over_abs_1.json',
]
+filter_build_files = [
+ 'compile_commands_filter_build.json',
+]
+
+filter_build2_files = [
+ 'compile_commands_filter_build2.json',
+]
+
example_rel_file = """[
{
"command": "%(exe)s mygcc.py cc -o %(output_file)s -c %(variant_src_file)s",
@@ -115,4 +123,45 @@ for f in abs_files:
test.must_exist(f)
test.must_match(f, example_abs_file, mode='r')
+example_filter_build_file = """[
+ {
+ "command": "%(exe)s mygcc.py cc -o %(output_file)s -c %(variant_src_file)s",
+ "directory": "%(workdir)s",
+ "file": "%(src_file)s",
+ "output": "%(output_file)s"
+ }
+]""" % {'exe': sys.executable,
+ 'workdir': test.workdir,
+ 'src_file': os.path.join('src', 'test_main.c'),
+ 'output_file': os.path.join('build', 'test_main.o'),
+ 'variant_src_file': os.path.join('build', 'test_main.c')
+ }
+
+if sys.platform == 'win32':
+ example_filter_build_file = example_filter_build_file.replace('\\', '\\\\')
+
+for f in filter_build_files:
+ test.must_exist(f)
+ test.must_match(f, example_filter_build_file, mode='r')
+
+example_filter_build2_file = """[
+ {
+ "command": "%(exe)s mygcc.py cc -o %(output2_file)s -c %(src_file)s",
+ "directory": "%(workdir)s",
+ "file": "%(src_file)s",
+ "output": "%(output2_file)s"
+ }
+]""" % {'exe': sys.executable,
+ 'workdir': test.workdir,
+ 'src_file': os.path.join('src', 'test_main.c'),
+ 'output2_file': os.path.join('build2', 'test_main.o'),
+ }
+
+if sys.platform == 'win32':
+ example_filter_build2_file = example_filter_build2_file.replace('\\', '\\\\')
+
+for f in filter_build2_files:
+ test.must_exist(f)
+ test.must_match(f, example_filter_build2_file, mode='r')
+
test.pass_test()
diff --git a/test/Configure/VariantDir2.py b/test/Configure/VariantDir2.py
index ffe6525..98f4ccd 100644
--- a/test/Configure/VariantDir2.py
+++ b/test/Configure/VariantDir2.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify that Configure contexts work with SConstruct/SConscript structure
"""
-import os
import TestSCons
diff --git a/test/Configure/config-h.py b/test/Configure/config-h.py
index 0331b24..f617d92 100644
--- a/test/Configure/config-h.py
+++ b/test/Configure/config-h.py
@@ -27,7 +27,6 @@ Verify creation of a config.h file from a Configure context.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import re
import TestSCons
diff --git a/test/Copy-Symlinks.py b/test/Copy-Symlinks.py
index eab38e3..d2f5f4b 100644
--- a/test/Copy-Symlinks.py
+++ b/test/Copy-Symlinks.py
@@ -29,8 +29,6 @@ Verify that the Copy() Action symlink soft-copy support works.
"""
import os
-import stat
-import sys
import TestSCons
import SCons.Defaults
diff --git a/test/D/Issues/2994/Common/D_changed_DFLAGS_not_rebuilding.py b/test/D/Issues/2994/Common/D_changed_DFLAGS_not_rebuilding.py
index b58227d..66d84c8 100644
--- a/test/D/Issues/2994/Common/D_changed_DFLAGS_not_rebuilding.py
+++ b/test/D/Issues/2994/Common/D_changed_DFLAGS_not_rebuilding.py
@@ -30,7 +30,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons
-from os.path import abspath, dirname, join
+from os.path import abspath, dirname
import sys
sys.path.insert(1, abspath(dirname(__file__) + '/../../../Support'))
diff --git a/test/D/MixedDAndC/Common/common.py b/test/D/MixedDAndC/Common/common.py
index 852e2e2..2de1304 100644
--- a/test/D/MixedDAndC/Common/common.py
+++ b/test/D/MixedDAndC/Common/common.py
@@ -30,7 +30,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons
from os.path import abspath, dirname
-from platform import architecture
import sys
sys.path.insert(1, abspath(dirname(__file__) + '/../../Support'))
diff --git a/test/DVIPDF/DVIPDFFLAGS.py b/test/DVIPDF/DVIPDFFLAGS.py
index 9ecb736..9900cf7 100644
--- a/test/DVIPDF/DVIPDFFLAGS.py
+++ b/test/DVIPDF/DVIPDFFLAGS.py
@@ -122,7 +122,7 @@ subprocess.run(cmd, shell=True)
test.write('SConstruct', """
import os
ENV = {'PATH' : os.environ['PATH']}
-foo = Environment(DVIPDFFLAGS = '-N', ENV = ENV)
+foo = Environment(DVIPDFFLAGS = '-R2', ENV = ENV)
dvipdf = foo.Dictionary('DVIPDF')
bar = Environment(DVIPDF = r'%(_python_)s wrapper.py ' + dvipdf, ENV = ENV)
foo.PDF(target = 'foo.pdf',
diff --git a/test/Decider/MD5-winonly-firstbuild.py b/test/Decider/MD5-winonly-firstbuild.py
index 87f7999..beabce3 100644
--- a/test/Decider/MD5-winonly-firstbuild.py
+++ b/test/Decider/MD5-winonly-firstbuild.py
@@ -29,8 +29,6 @@ Test but which only shows on windows when one generated file depends on another
In this case flex and yacc are an example.
"""
-import os
-import stat
import TestSCons
from TestCmd import IS_WINDOWS
diff --git a/test/Dir/PyPackageDir/PyPackageDir.py b/test/Dir/PyPackageDir/PyPackageDir.py
index b215c7b..beb256b 100644
--- a/test/Dir/PyPackageDir/PyPackageDir.py
+++ b/test/Dir/PyPackageDir/PyPackageDir.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/Docbook/basedir/htmlchunked/htmlchunked_cmd.py b/test/Docbook/basedir/htmlchunked/htmlchunked_cmd.py
index 3ad6369..e603232 100644
--- a/test/Docbook/basedir/htmlchunked/htmlchunked_cmd.py
+++ b/test/Docbook/basedir/htmlchunked/htmlchunked_cmd.py
@@ -28,7 +28,6 @@ the xsltproc executable, if it exists.
"""
import os
-import sys
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/Docbook/basedir/htmlhelp/htmlhelp_cmd.py b/test/Docbook/basedir/htmlhelp/htmlhelp_cmd.py
index 2b004c6..ebefb92 100644
--- a/test/Docbook/basedir/htmlhelp/htmlhelp_cmd.py
+++ b/test/Docbook/basedir/htmlhelp/htmlhelp_cmd.py
@@ -28,7 +28,6 @@ the xsltproc executable, if it exists.
"""
import os
-import sys
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/Docbook/basedir/slideshtml/slideshtml_cmd.py b/test/Docbook/basedir/slideshtml/slideshtml_cmd.py
index 901d94e..b0f1f25 100644
--- a/test/Docbook/basedir/slideshtml/slideshtml_cmd.py
+++ b/test/Docbook/basedir/slideshtml/slideshtml_cmd.py
@@ -28,7 +28,6 @@ the xsltproc executable, if it exists.
"""
import os
-import sys
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/Docbook/basic/htmlchunked/htmlchunked_cmd.py b/test/Docbook/basic/htmlchunked/htmlchunked_cmd.py
index 6b79102..9715c0f 100644
--- a/test/Docbook/basic/htmlchunked/htmlchunked_cmd.py
+++ b/test/Docbook/basic/htmlchunked/htmlchunked_cmd.py
@@ -27,7 +27,6 @@ Test the chunked HTML builder while using
the xsltproc executable, if it exists.
"""
-import os
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/Docbook/basic/slideshtml/slideshtml_cmd.py b/test/Docbook/basic/slideshtml/slideshtml_cmd.py
index 7ebc8d4..9c8097b 100644
--- a/test/Docbook/basic/slideshtml/slideshtml_cmd.py
+++ b/test/Docbook/basic/slideshtml/slideshtml_cmd.py
@@ -28,7 +28,6 @@ the xsltproc executable, if it exists.
"""
import os
-import sys
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/Errors/execute-a-directory.py b/test/Errors/execute-a-directory.py
index 8b6d13b..ff50620 100644
--- a/test/Errors/execute-a-directory.py
+++ b/test/Errors/execute-a-directory.py
@@ -25,7 +25,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
-import sys
import TestSCons
diff --git a/test/Errors/non-executable-file.py b/test/Errors/non-executable-file.py
index 64c75c6..98d4721 100644
--- a/test/Errors/non-executable-file.py
+++ b/test/Errors/non-executable-file.py
@@ -25,7 +25,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
-import sys
import TestSCons
diff --git a/test/Fortran/F03.py b/test/Fortran/F03.py
index 989d878..ce56cc3 100644
--- a/test/Fortran/F03.py
+++ b/test/Fortran/F03.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F03FILESUFFIXES.py b/test/Fortran/F03FILESUFFIXES.py
index 5620a2d..49c9c66 100644
--- a/test/Fortran/F03FILESUFFIXES.py
+++ b/test/Fortran/F03FILESUFFIXES.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F03FILESUFFIXES2.py b/test/Fortran/F03FILESUFFIXES2.py
index 6073aab..6512341 100644
--- a/test/Fortran/F03FILESUFFIXES2.py
+++ b/test/Fortran/F03FILESUFFIXES2.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F03FLAGS.py b/test/Fortran/F03FLAGS.py
index 54b8083..63d1fcb 100644
--- a/test/Fortran/F03FLAGS.py
+++ b/test/Fortran/F03FLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F08.py b/test/Fortran/F08.py
index f60509c..eb381ee 100644
--- a/test/Fortran/F08.py
+++ b/test/Fortran/F08.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F08FILESUFFIXES.py b/test/Fortran/F08FILESUFFIXES.py
index 989d685..392ff64 100644
--- a/test/Fortran/F08FILESUFFIXES.py
+++ b/test/Fortran/F08FILESUFFIXES.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F08FILESUFFIXES2.py b/test/Fortran/F08FILESUFFIXES2.py
index 0d99225..babb8e6 100644
--- a/test/Fortran/F08FILESUFFIXES2.py
+++ b/test/Fortran/F08FILESUFFIXES2.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F08FLAGS.py b/test/Fortran/F08FLAGS.py
index 015fb0b..81ae441 100644
--- a/test/Fortran/F08FLAGS.py
+++ b/test/Fortran/F08FLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F77.py b/test/Fortran/F77.py
index ed5d33f..c43fb3e 100644
--- a/test/Fortran/F77.py
+++ b/test/Fortran/F77.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F77FILESUFFIXES.py b/test/Fortran/F77FILESUFFIXES.py
index c289e10..8c7aec8 100644
--- a/test/Fortran/F77FILESUFFIXES.py
+++ b/test/Fortran/F77FILESUFFIXES.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F77FILESUFFIXES2.py b/test/Fortran/F77FILESUFFIXES2.py
index 1f26012..86cd931 100644
--- a/test/Fortran/F77FILESUFFIXES2.py
+++ b/test/Fortran/F77FILESUFFIXES2.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F77FLAGS.py b/test/Fortran/F77FLAGS.py
index caf291d..01bf33b 100644
--- a/test/Fortran/F77FLAGS.py
+++ b/test/Fortran/F77FLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F90.py b/test/Fortran/F90.py
index d76af07..404f883 100644
--- a/test/Fortran/F90.py
+++ b/test/Fortran/F90.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F90FILESUFFIXES.py b/test/Fortran/F90FILESUFFIXES.py
index d91c4c8..e376f3c 100644
--- a/test/Fortran/F90FILESUFFIXES.py
+++ b/test/Fortran/F90FILESUFFIXES.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F90FILESUFFIXES2.py b/test/Fortran/F90FILESUFFIXES2.py
index 3efc52c..e01425f 100644
--- a/test/Fortran/F90FILESUFFIXES2.py
+++ b/test/Fortran/F90FILESUFFIXES2.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F90FLAGS.py b/test/Fortran/F90FLAGS.py
index f748e5d..5a469e9 100644
--- a/test/Fortran/F90FLAGS.py
+++ b/test/Fortran/F90FLAGS.py
@@ -25,7 +25,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F95.py b/test/Fortran/F95.py
index 8e6d0b9..7b4c97a 100644
--- a/test/Fortran/F95.py
+++ b/test/Fortran/F95.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F95FILESUFFIXES.py b/test/Fortran/F95FILESUFFIXES.py
index 427c881..710f838 100644
--- a/test/Fortran/F95FILESUFFIXES.py
+++ b/test/Fortran/F95FILESUFFIXES.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F95FILESUFFIXES2.py b/test/Fortran/F95FILESUFFIXES2.py
index a0ee1cf..2f8bb17 100644
--- a/test/Fortran/F95FILESUFFIXES2.py
+++ b/test/Fortran/F95FILESUFFIXES2.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/F95FLAGS.py b/test/Fortran/F95FLAGS.py
index 203aee1..2853cc9 100644
--- a/test/Fortran/F95FLAGS.py
+++ b/test/Fortran/F95FLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/FORTRAN.py b/test/Fortran/FORTRAN.py
index 721d48f..62d7065 100644
--- a/test/Fortran/FORTRAN.py
+++ b/test/Fortran/FORTRAN.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/FORTRANFILESUFFIXES.py b/test/Fortran/FORTRANFILESUFFIXES.py
index ec659a1..e58b971 100644
--- a/test/Fortran/FORTRANFILESUFFIXES.py
+++ b/test/Fortran/FORTRANFILESUFFIXES.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/FORTRANFILESUFFIXES2.py b/test/Fortran/FORTRANFILESUFFIXES2.py
index 6dda07d..a57dd2a 100644
--- a/test/Fortran/FORTRANFILESUFFIXES2.py
+++ b/test/Fortran/FORTRANFILESUFFIXES2.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/FORTRANFLAGS.py b/test/Fortran/FORTRANFLAGS.py
index 316f67c..218c95f 100644
--- a/test/Fortran/FORTRANFLAGS.py
+++ b/test/Fortran/FORTRANFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/FORTRANPPFILESUFFIXES.py b/test/Fortran/FORTRANPPFILESUFFIXES.py
index 6b3b3d8..2c10b10 100644
--- a/test/Fortran/FORTRANPPFILESUFFIXES.py
+++ b/test/Fortran/FORTRANPPFILESUFFIXES.py
@@ -25,9 +25,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
-import string
-import sys
import TestSCons
diff --git a/test/Fortran/SHF03.py b/test/Fortran/SHF03.py
index 0ab2cc9..1c3fb1b 100644
--- a/test/Fortran/SHF03.py
+++ b/test/Fortran/SHF03.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/SHF08.py b/test/Fortran/SHF08.py
index 8147b79..49a4c47 100644
--- a/test/Fortran/SHF08.py
+++ b/test/Fortran/SHF08.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/SHF77.py b/test/Fortran/SHF77.py
index 1b0e180..4358533 100644
--- a/test/Fortran/SHF77.py
+++ b/test/Fortran/SHF77.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/SHF77FLAGS.py b/test/Fortran/SHF77FLAGS.py
index 19d40b6..3a7e6b2 100644
--- a/test/Fortran/SHF77FLAGS.py
+++ b/test/Fortran/SHF77FLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/SHF90.py b/test/Fortran/SHF90.py
index 1524bf3..057f98c 100644
--- a/test/Fortran/SHF90.py
+++ b/test/Fortran/SHF90.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/SHF90FLAGS.py b/test/Fortran/SHF90FLAGS.py
index 947bf4b..900acbc 100644
--- a/test/Fortran/SHF90FLAGS.py
+++ b/test/Fortran/SHF90FLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/SHF95.py b/test/Fortran/SHF95.py
index 27d9a76..3b1f4fb 100644
--- a/test/Fortran/SHF95.py
+++ b/test/Fortran/SHF95.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/SHF95FLAGS.py b/test/Fortran/SHF95FLAGS.py
index d1fbe3f..56744d6 100644
--- a/test/Fortran/SHF95FLAGS.py
+++ b/test/Fortran/SHF95FLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/SHFORTRAN.py b/test/Fortran/SHFORTRAN.py
index f4850d7..a8806e7 100644
--- a/test/Fortran/SHFORTRAN.py
+++ b/test/Fortran/SHFORTRAN.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Fortran/SHFORTRANFLAGS.py b/test/Fortran/SHFORTRANFLAGS.py
index ac2abd8..6a4692b 100644
--- a/test/Fortran/SHFORTRANFLAGS.py
+++ b/test/Fortran/SHFORTRANFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Install/directories.py b/test/Install/directories.py
index 3ebc713..e980936 100644
--- a/test/Install/directories.py
+++ b/test/Install/directories.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test using Install() on directories.
"""
-import os.path
import TestSCons
diff --git a/test/Install/non-ascii-name.py b/test/Install/non-ascii-name.py
index 462040d..7e25743 100644
--- a/test/Install/non-ascii-name.py
+++ b/test/Install/non-ascii-name.py
@@ -29,7 +29,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify that the Install() Builder works
"""
-import os.path
import TestSCons
diff --git a/test/Java/JAR.py b/test/Java/JAR.py
index d5425af..2cd6012 100644
--- a/test/Java/JAR.py
+++ b/test/Java/JAR.py
@@ -26,7 +26,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
import TestSCons
-import sys
_python_ = TestSCons._python_
diff --git a/test/Java/JARCHDIR.py b/test/Java/JARCHDIR.py
index 59bf082..24a8597 100644
--- a/test/Java/JARCHDIR.py
+++ b/test/Java/JARCHDIR.py
@@ -33,7 +33,6 @@ Includes logic to make sure that expansions of $JARCHDIR that include
${TARGET} or ${SOURCE} work.
"""
-import os
import TestSCons
diff --git a/test/Java/JARFLAGS.py b/test/Java/JARFLAGS.py
index 6983bf7..fc6e55e 100644
--- a/test/Java/JARFLAGS.py
+++ b/test/Java/JARFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/Java/jar_not_in_PATH.py b/test/Java/jar_not_in_PATH.py
index 9a716c5..d69f9c3 100644
--- a/test/Java/jar_not_in_PATH.py
+++ b/test/Java/jar_not_in_PATH.py
@@ -29,7 +29,6 @@ Ensures that the Tool gets initialized, even when jar is not directly
found via the PATH variable (issue #2730).
"""
-import os
import TestSCons
diff --git a/test/Java/nested-classes.py b/test/Java/nested-classes.py
index a764054..0208eb6 100644
--- a/test/Java/nested-classes.py
+++ b/test/Java/nested-classes.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test Java compilation with inner and anonymous classes (Issue 2087).
"""
-import os
import TestSCons
diff --git a/test/Java/swig-dependencies.py b/test/Java/swig-dependencies.py
index a3af9ec..c1821f8 100644
--- a/test/Java/swig-dependencies.py
+++ b/test/Java/swig-dependencies.py
@@ -143,7 +143,6 @@ except:
# the test framework
test.skip_test('Throwing no result for this test because of bug ' +
'related here: https://github.com/SCons/scons/issues/2907\n')
- pass
#test.must_exist(['java', 'classes', 'foopack', 'foopack.class'])
#test.must_exist(['java', 'classes', 'foopack', 'foopackJNI.class'])
test.must_exist(['java', 'classes', 'foopack.class'])
diff --git a/test/LEX/LEX.py b/test/LEX/LEX.py
index a739bfe..79d8359 100644
--- a/test/LEX/LEX.py
+++ b/test/LEX/LEX.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/LEX/LEXFLAGS.py b/test/LEX/LEXFLAGS.py
index 994834e..2cebca7 100644
--- a/test/LEX/LEXFLAGS.py
+++ b/test/LEX/LEXFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import sys
import TestSCons
diff --git a/test/LINK/LDMODULEVERSIONFLAGS.py b/test/LINK/LDMODULEVERSIONFLAGS.py
index d8f280a..509bde8 100644
--- a/test/LINK/LDMODULEVERSIONFLAGS.py
+++ b/test/LINK/LDMODULEVERSIONFLAGS.py
@@ -24,8 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
-import re
import TestSCons
import SCons.Platform
diff --git a/test/LINK/LINK.py b/test/LINK/LINK.py
index 6c99134..f278ac0 100644
--- a/test/LINK/LINK.py
+++ b/test/LINK/LINK.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/LINK/LINKFLAGS.py b/test/LINK/LINKFLAGS.py
index 749e369..d3b675e 100644
--- a/test/LINK/LINKFLAGS.py
+++ b/test/LINK/LINKFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/LINK/SHLINK.py b/test/LINK/SHLINK.py
index 9d406fc..26d88fa 100644
--- a/test/LINK/SHLINK.py
+++ b/test/LINK/SHLINK.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/LINK/SHLINKFLAGS.py b/test/LINK/SHLINKFLAGS.py
index af5bdbb..a4ae652 100644
--- a/test/LINK/SHLINKFLAGS.py
+++ b/test/LINK/SHLINKFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/LINK/VersionedLib.py b/test/LINK/VersionedLib.py
index 104f696..5f74f92 100644
--- a/test/LINK/VersionedLib.py
+++ b/test/LINK/VersionedLib.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
-import sys
import TestSCons
import SCons.Platform
diff --git a/test/Libs/SharedLibrary-update-deps.py b/test/Libs/SharedLibrary-update-deps.py
index 3abce83..922d580 100644
--- a/test/Libs/SharedLibrary-update-deps.py
+++ b/test/Libs/SharedLibrary-update-deps.py
@@ -30,7 +30,6 @@ This is https://github.com/SCons/scons/issues/2903
"""
import sys
-import os.path
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/MSVC/PCHSTOP-errors.py b/test/MSVC/PCHSTOP-errors.py
index aa14a3f..a359135 100644
--- a/test/MSVC/PCHSTOP-errors.py
+++ b/test/MSVC/PCHSTOP-errors.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
# Test error reporting
"""
-import re
import TestSCons
diff --git a/test/MSVC/mssdk.py b/test/MSVC/mssdk.py
index 9890d48..88dd5d1 100644
--- a/test/MSVC/mssdk.py
+++ b/test/MSVC/mssdk.py
@@ -27,7 +27,6 @@ Simple test to make sure mssdk works.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import time
import TestSCons
diff --git a/test/MSVC/pch-basics.py b/test/MSVC/pch-basics.py
index ebee0da..e2b40f1 100644
--- a/test/MSVC/pch-basics.py
+++ b/test/MSVC/pch-basics.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify PCH works to build a simple exe and a simple dll.
"""
-import time
import TestSCons
diff --git a/test/MSVC/pch-spaces-subdir.py b/test/MSVC/pch-spaces-subdir.py
index 65595fc..f00fac1 100644
--- a/test/MSVC/pch-spaces-subdir.py
+++ b/test/MSVC/pch-spaces-subdir.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify PCH works if variant dir has spaces in its name
"""
-import time
import TestSCons
diff --git a/test/MSVS/common-prefix.py b/test/MSVS/common-prefix.py
index 7079661..7bba783 100644
--- a/test/MSVS/common-prefix.py
+++ b/test/MSVS/common-prefix.py
@@ -30,7 +30,6 @@ Test that we can generate Visual Studio 8.0 project (.vcproj) and
solution (.sln) files that look correct.
"""
-import os
import sys
import TestSConsMSVS
diff --git a/test/MSVS/runfile.py b/test/MSVS/runfile.py
index 631c919..1cc4720 100644
--- a/test/MSVS/runfile.py
+++ b/test/MSVS/runfile.py
@@ -30,7 +30,6 @@ Test that we can generate Visual Studio 8.0 project (.vcproj) and
solution (.sln) files that look correct.
"""
-import os
import sys
import TestSConsMSVS
diff --git a/test/MSVS/vs-6.0-exec.py b/test/MSVS/vs-6.0-exec.py
index ab70872..40f69c0 100644
--- a/test/MSVS/vs-6.0-exec.py
+++ b/test/MSVS/vs-6.0-exec.py
@@ -29,7 +29,6 @@ Test that we can actually build a simple program using our generated
Visual Studio 6 project (.dsp) and solution (.dsw) files.
"""
-import os
import sys
import TestSConsMSVS
diff --git a/test/MSVS/vs-7.0-exec.py b/test/MSVS/vs-7.0-exec.py
index 3c41aa5..a6235a7 100644
--- a/test/MSVS/vs-7.0-exec.py
+++ b/test/MSVS/vs-7.0-exec.py
@@ -29,7 +29,6 @@ Test that we can actually build a simple program using our generated
Visual Studio 7.0 project (.vcproj) and solution (.sln) files.
"""
-import os
import sys
import TestSConsMSVS
diff --git a/test/MSVS/vs-7.0-scc-files.py b/test/MSVS/vs-7.0-scc-files.py
index 4d90a92..f1f77db 100644
--- a/test/MSVS/vs-7.0-scc-files.py
+++ b/test/MSVS/vs-7.0-scc-files.py
@@ -29,7 +29,6 @@ Test that we can generate Visual Studio 7.0 project (.vcproj) and
solution (.sln) files that contain SCC information and look correct.
"""
-import os
import TestSConsMSVS
diff --git a/test/MSVS/vs-7.0-scc-legacy-files.py b/test/MSVS/vs-7.0-scc-legacy-files.py
index e87441b..a180b8a 100644
--- a/test/MSVS/vs-7.0-scc-legacy-files.py
+++ b/test/MSVS/vs-7.0-scc-legacy-files.py
@@ -29,7 +29,6 @@ Test that we can generate Visual Studio 7.0 project (.vcproj) and
solution (.sln) files that contain SCC information and look correct.
"""
-import os
import TestSConsMSVS
diff --git a/test/MSVS/vs-7.1-exec.py b/test/MSVS/vs-7.1-exec.py
index f66b92d..7bb3055 100644
--- a/test/MSVS/vs-7.1-exec.py
+++ b/test/MSVS/vs-7.1-exec.py
@@ -29,7 +29,6 @@ Test that we can actually build a simple program using our generated
Visual Studio 7.1 project (.vcproj) and solution (.sln) files
"""
-import os
import sys
import TestSConsMSVS
diff --git a/test/MSVS/vs-7.1-scc-files.py b/test/MSVS/vs-7.1-scc-files.py
index 8404422..0b42930 100644
--- a/test/MSVS/vs-7.1-scc-files.py
+++ b/test/MSVS/vs-7.1-scc-files.py
@@ -29,7 +29,6 @@ Test that we can generate Visual Studio 7.1 project (.vcproj) and
solution (.sln) files that contain SCC information and look correct.
"""
-import os
import TestSConsMSVS
diff --git a/test/MSVS/vs-7.1-scc-legacy-files.py b/test/MSVS/vs-7.1-scc-legacy-files.py
index f80c965..bb184d6 100644
--- a/test/MSVS/vs-7.1-scc-legacy-files.py
+++ b/test/MSVS/vs-7.1-scc-legacy-files.py
@@ -29,7 +29,6 @@ Test that we can generate Visual Studio 7.1 project (.vcproj) and
solution (.sln) files that contain SCC information and look correct.
"""
-import os
import TestSConsMSVS
diff --git a/test/MinGW/mingw_uses_comstr_issue_2799.py b/test/MinGW/mingw_uses_comstr_issue_2799.py
index cc92446..fc96ad4 100644
--- a/test/MinGW/mingw_uses_comstr_issue_2799.py
+++ b/test/MinGW/mingw_uses_comstr_issue_2799.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test that mingw respects SHLINKCOMSTR, SHCCCOMSTR, and LDMODULECOMSTR
"""
-import sys
import TestSCons
_python_ = TestSCons._python_
diff --git a/test/Progress/TARGET.py b/test/Progress/TARGET.py
index bbe2538..9535390 100644
--- a/test/Progress/TARGET.py
+++ b/test/Progress/TARGET.py
@@ -29,7 +29,6 @@ Verify substition of the $TARGET string in progress output, including
overwriting it by setting the overwrite= keyword argument.
"""
-import os
import TestSCons
diff --git a/test/Progress/spinner.py b/test/Progress/spinner.py
index ff88841..f9be6e9 100644
--- a/test/Progress/spinner.py
+++ b/test/Progress/spinner.py
@@ -29,7 +29,6 @@ Verify output when a Progress() call is initialized with the list
that represents a canonical "spinner" on the output.
"""
-import os
import TestSCons
diff --git a/test/Repository/Install.py b/test/Repository/Install.py
index 75052e7..9c1259a 100644
--- a/test/Repository/Install.py
+++ b/test/Repository/Install.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
diff --git a/test/Repository/InstallAs.py b/test/Repository/InstallAs.py
index d717254..c153771 100644
--- a/test/Repository/InstallAs.py
+++ b/test/Repository/InstallAs.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
diff --git a/test/Repository/M4.py b/test/Repository/M4.py
index 8fa91ab..2e40468 100644
--- a/test/Repository/M4.py
+++ b/test/Repository/M4.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test that $M4 and $M4FLAGS work with repositories.
"""
-import os
import TestSCons
diff --git a/test/SConsignFile/default.py b/test/SConsignFile/default.py
index 62ac006..868f9d7 100644
--- a/test/SConsignFile/default.py
+++ b/test/SConsignFile/default.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright 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,16 +22,10 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-"""
-Verify the default behavior of SConsignFile(), called with no arguments.
-"""
+"""Verify the default behavior of SConsignFile() called with no arguments."""
import TestSCons
-import os.path
_python_ = TestSCons._python_
@@ -47,12 +43,13 @@ sys.exit(0)
#
test.write('SConstruct', """
SConsignFile()
-B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES')
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'subdir/f3.out', source = 'subdir/f3.in')
-env.B(target = 'subdir/f4.out', source = 'subdir/f4.in')
+DefaultEnvironment(tools=[])
+B = Builder(action=r'%(_python_)s build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS={'B': B}, tools=[])
+env.B(target='f1.out', source='f1.in')
+env.B(target='f2.out', source='f2.in')
+env.B(target='subdir/f3.out', source='subdir/f3.in')
+env.B(target='subdir/f4.out', source='subdir/f4.in')
""" % locals())
test.write('f1.in', "f1.in\n")
@@ -71,7 +68,7 @@ test.must_match('f2.out', "f2.in\n")
test.must_match(['subdir', 'f3.out'], "subdir/f3.in\n")
test.must_match(['subdir', 'f4.out'], "subdir/f4.in\n")
-test.up_to_date(arguments = '.')
+test.up_to_date(arguments='.')
test.must_exist(test.workpath('.sconsign.dblite'))
test.must_not_exist(test.workpath('.sconsign'))
diff --git a/test/SConsignFile/explicit-dbm-module.py b/test/SConsignFile/explicit-dbm-module.py
new file mode 100644
index 0000000..c093271
--- /dev/null
+++ b/test/SConsignFile/explicit-dbm-module.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+#
+# MIT License
+#
+# Copyright 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.
+
+"""Verify SConsignFile() when used with explicit SCons.dblite."""
+
+import TestSCons
+
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+
+use_db = 'SCons.dblite'
+
+test.subdir('subdir')
+
+test.write('build.py', r"""
+import sys
+with open(sys.argv[1], 'wb') as ofp, open(sys.argv[2], 'rb') as ifp:
+ ofp.write(ifp.read())
+sys.exit(0)
+""")
+
+test.write('SConstruct', """
+import %(use_db)s
+SConsignFile(dbm_module=%(use_db)s)
+DefaultEnvironment(tools=[])
+B = Builder(action=r'%(_python_)s build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS={'B': B}, tools=[])
+env.B(target='f1.out', source='f1.in')
+env.B(target='f2.out', source='f2.in')
+env.B(target='subdir/f3.out', source='subdir/f3.in')
+env.B(target='subdir/f4.out', source='subdir/f4.in')
+""" % locals())
+
+test.write('f1.in', "f1.in\n")
+test.write('f2.in', "f2.in\n")
+test.write(['subdir', 'f3.in'], "subdir/f3.in\n")
+test.write(['subdir', 'f4.in'], "subdir/f4.in\n")
+
+test.run()
+
+test.must_exist(test.workpath('.sconsign.dblite'))
+test.must_not_exist(test.workpath('.sconsign'))
+test.must_not_exist(test.workpath('subdir', '.sconsign'))
+
+test.must_match('f1.out', "f1.in\n")
+test.must_match('f2.out', "f2.in\n")
+test.must_match(['subdir', 'f3.out'], "subdir/f3.in\n")
+test.must_match(['subdir', 'f4.out'], "subdir/f4.in\n")
+
+test.up_to_date(arguments='.')
+
+test.must_exist(test.workpath('.sconsign.dblite'))
+test.must_not_exist(test.workpath('.sconsign'))
+test.must_not_exist(test.workpath('subdir', '.sconsign'))
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/SConsignFile/explicit-file.py b/test/SConsignFile/explicit-file.py
index 7583bdc..850b0ef 100644
--- a/test/SConsignFile/explicit-file.py
+++ b/test/SConsignFile/explicit-file.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright 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,16 +22,10 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-"""
-Verify the default behavior of SConsignFile(), called with no arguments.
-"""
+"""Verify the behavior of env.SConsignFile() called with a subst-able path."""
import TestSCons
-import os.path
_python_ = TestSCons._python_
@@ -45,14 +41,15 @@ with open(sys.argv[1], 'wb') as ofp, open(sys.argv[2], 'rb') as ifp:
#
test.write('SConstruct', """
-e = Environment(XXX = 'scons')
+DefaultEnvironment(tools=[])
+e = Environment(XXX='scons', tools=[])
e.SConsignFile('my_${XXX}ign')
-B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES')
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f5.out', source = 'f5.in')
-env.B(target = 'f6.out', source = 'f6.in')
-env.B(target = 'subdir/f7.out', source = 'subdir/f7.in')
-env.B(target = 'subdir/f8.out', source = 'subdir/f8.in')
+B = Builder(action=r'%(_python_)s build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS={'B': B}, tools=[])
+env.B(target='f5.out', source='f5.in')
+env.B(target='f6.out', source='f6.in')
+env.B(target='subdir/f7.out', source='subdir/f7.in')
+env.B(target='subdir/f8.out', source='subdir/f8.in')
""" % locals())
test.write('f5.in', "f5.in\n")
@@ -71,7 +68,7 @@ test.must_match('f6.out', "f6.in\n")
test.must_match(['subdir', 'f7.out'], "subdir/f7.in\n")
test.must_match(['subdir', 'f8.out'], "subdir/f8.in\n")
-test.up_to_date(arguments = '.')
+test.up_to_date(arguments='.')
test.must_exist(test.workpath('my_sconsign.dblite'))
test.must_not_exist(test.workpath('.sconsign'))
diff --git a/test/SConsignFile/make-directory.py b/test/SConsignFile/make-directory.py
index 50bab79..264ee26 100644
--- a/test/SConsignFile/make-directory.py
+++ b/test/SConsignFile/make-directory.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright 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,9 +22,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify the ability to make a SConsignFile() in a non-existent
@@ -40,15 +39,17 @@ bar_foo_txt = os.path.join('bar', 'foo.txt')
test.write('SConstruct', """
import SCons.dblite
-env = Environment()
+DefaultEnvironment(tools=[])
+env = Environment(tools=[])
env.SConsignFile("sub/dir/sconsign", SCons.dblite)
env.Install('bar', 'foo.txt')
""")
test.write('foo.txt', "Foo\n")
-
-expect = test.wrap_stdout(read_str = 'Mkdir("%s")\n' % sub_dir,
- build_str = 'Install file: "foo.txt" as "%s"\n' % bar_foo_txt)
+expect = test.wrap_stdout(
+ read_str='Mkdir("%s")\n' % sub_dir,
+ build_str='Install file: "foo.txt" as "%s"\n' % bar_foo_txt,
+)
test.run(options='-n', stdout=expect)
diff --git a/test/SConsignFile/use-dbhash.py b/test/SConsignFile/use-dbhash.py
index e57e244..2968cd7 100644
--- a/test/SConsignFile/use-dbhash.py
+++ b/test/SConsignFile/use-dbhash.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright 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,9 +22,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify SConsignFile() when used with dbhash.
@@ -36,8 +35,9 @@ test = TestSCons.TestSCons()
try:
import dbm.bsd
+ use_dbm = 'dbm.bsd'
except ImportError:
- test.skip_test('No dbhash in this version of Python; skipping test.\n')
+ test.skip_test('No dbm.bsd in this version of Python; skipping test.\n')
test.subdir('subdir')
@@ -50,11 +50,11 @@ sys.exit(0)
#
test.write('SConstruct', """
-import sys
-import dbhash
-SConsignFile('.sconsign', dbhash)
+import %(use_dbm)s
+SConsignFile('.sconsign', %(use_dbm)s)
+DefaultEnvironment(tools=[])
B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES')
-env = Environment(BUILDERS = { 'B' : B })
+env = Environment(BUILDERS={'B': B}, tools=[])
env.B(target = 'f1.out', source = 'f1.in')
env.B(target = 'f2.out', source = 'f2.in')
env.B(target = 'subdir/f3.out', source = 'subdir/f3.in')
diff --git a/test/SConsignFile/use-dbm.py b/test/SConsignFile/use-dbm.py
index 5100916..a1ef1b2 100644
--- a/test/SConsignFile/use-dbm.py
+++ b/test/SConsignFile/use-dbm.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright 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,9 +22,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify SConsignFile() when used with dbm.
@@ -37,15 +36,9 @@ test = TestSCons.TestSCons()
try:
import dbm.ndbm
-
- use_db = 'dbm.ndbm'
+ use_dbm = 'dbm.ndbm'
except ImportError:
- try:
- import dbm
-
- use_db = 'dbm'
- except ImportError:
- test.skip_test('No dbm.ndbm in this version of Python; skipping test.\n')
+ test.skip_test('No dbm.ndbm in this version of Python; skipping test.\n')
test.subdir('subdir')
@@ -58,16 +51,15 @@ sys.exit(0)
#
test.write('SConstruct', """
-import sys
-import %(use_db)s
-SConsignFile('.sconsign', %(use_db)s)
-B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES')
+import %(use_dbm)s
+SConsignFile('.sconsign', %(use_dbm)s)
DefaultEnvironment(tools=[])
-env = Environment(BUILDERS = { 'B' : B }, tools=[])
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'subdir/f3.out', source = 'subdir/f3.in')
-env.B(target = 'subdir/f4.out', source = 'subdir/f4.in')
+B = Builder(action=r'%(_python_)s build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS={'B': B}, tools=[])
+env.B(target='f1.out', source='f1.in')
+env.B(target='f2.out', source='f2.in')
+env.B(target='subdir/f3.out', source='subdir/f3.in')
+env.B(target='subdir/f4.out', source='subdir/f4.in')
""" % locals())
test.write('f1.in', "f1.in\n")
@@ -80,8 +72,10 @@ test.run()
# We don't check for explicit .db or other file, because base "dbm"
# can use different file extensions on different implementations.
-test.fail_test(os.path.exists('.sconsign') and 'dbm' not in dbm.whichdb('.sconsign'),
- message=".sconsign existed and wasn't any type of dbm file")
+test.fail_test(
+ os.path.exists('.sconsign') and 'dbm' not in dbm.whichdb('.sconsign'),
+ message=".sconsign existed and wasn't any type of dbm file",
+)
test.must_not_exist(test.workpath('.sconsign.dblite'))
test.must_not_exist(test.workpath('subdir', '.sconsign'))
test.must_not_exist(test.workpath('subdir', '.sconsign.dblite'))
diff --git a/test/SConsignFile/use-dumbdbm.py b/test/SConsignFile/use-dumbdbm.py
index 36ba18b..875f3fc 100644
--- a/test/SConsignFile/use-dumbdbm.py
+++ b/test/SConsignFile/use-dumbdbm.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright 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,9 +22,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify SConsignFile() when used with dumbdbm.
@@ -35,14 +34,10 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
try:
- import dumbdbm
- use_dbm = 'dumbdbm'
+ import dbm.dumb
+ use_dbm = 'dbm.dumb'
except ImportError:
- try:
- import dbm.dumb
- use_dbm='dbm.dumb'
- except ImportError:
- test.skip_test('No dumbdbm or dbm.dumb in this version of Python; skipping test.\n')
+ test.skip_test('No dbm.dumb in this version of Python; skipping test.\n')
test.subdir('subdir')
@@ -55,15 +50,15 @@ sys.exit(0)
#
test.write('SConstruct', """
-import sys
import %(use_dbm)s
SConsignFile('.sconsign', %(use_dbm)s)
-B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES')
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'subdir/f3.out', source = 'subdir/f3.in')
-env.B(target = 'subdir/f4.out', source = 'subdir/f4.in')
+DefaultEnvironment(tools=[])
+B = Builder(action=r'%(_python_)s build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS={'B': B}, tools=[])
+env.B(target='f1.out', source='f1.in')
+env.B(target='f2.out', source='f2.in')
+env.B(target='subdir/f3.out', source='subdir/f3.in')
+env.B(target='subdir/f4.out', source='subdir/f4.in')
""" % locals())
test.write('f1.in', "f1.in\n")
@@ -87,7 +82,7 @@ test.must_match('f2.out', "f2.in\n")
test.must_match(['subdir', 'f3.out'], "subdir/f3.in\n")
test.must_match(['subdir', 'f4.out'], "subdir/f4.in\n")
-test.up_to_date(arguments = '.')
+test.up_to_date(arguments='.')
test.must_exist(test.workpath('.sconsign.dat'))
test.must_exist(test.workpath('.sconsign.dir'))
diff --git a/test/SConsignFile/use-gdbm.py b/test/SConsignFile/use-gdbm.py
index 12a2e8b..c1f0c4d 100644
--- a/test/SConsignFile/use-gdbm.py
+++ b/test/SConsignFile/use-gdbm.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright 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,9 +22,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify SConsignFile() when used with gdbm.
@@ -35,14 +34,10 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
try:
- import gdbm
- use_dbm = "gdbm"
+ import dbm.gnu
+ use_dbm = "dbm.gnu"
except ImportError:
- try:
- import dbm.gnu
- use_dbm = "dbm.gnu"
- except ImportError:
- test.skip_test('No GNU dbm in this version of Python; skipping test.\n')
+ test.skip_test('No GNU dbm in this version of Python; skipping test.\n')
test.subdir('subdir')
@@ -55,15 +50,15 @@ sys.exit(0)
#
test.write('SConstruct', """
-import sys
import %(use_dbm)s
SConsignFile('.sconsign', %(use_dbm)s)
-B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES')
-env = Environment(BUILDERS = { 'B' : B })
-env.B(target = 'f1.out', source = 'f1.in')
-env.B(target = 'f2.out', source = 'f2.in')
-env.B(target = 'subdir/f3.out', source = 'subdir/f3.in')
-env.B(target = 'subdir/f4.out', source = 'subdir/f4.in')
+DefaultEnvironment(tools=[])
+B = Builder(action='%(_python_)s build.py $TARGETS $SOURCES')
+env = Environment(BUILDERS={'B': B}, tools=[])
+env.B(target='f1.out', source='f1.in')
+env.B(target='f2.out', source='f2.in')
+env.B(target='subdir/f3.out', source='subdir/f3.in')
+env.B(target='subdir/f4.out', source='subdir/f4.in')
""" % locals())
test.write('f1.in', "f1.in\n")
@@ -83,7 +78,7 @@ test.must_match('f2.out', "f2.in\n")
test.must_match(['subdir', 'f3.out'], "subdir/f3.in\n")
test.must_match(['subdir', 'f4.out'], "subdir/f4.in\n")
-test.up_to_date(arguments = '.')
+test.up_to_date(arguments='.')
test.must_exist(test.workpath('.sconsign'))
test.must_not_exist(test.workpath('.sconsign.dblite'))
diff --git a/test/SWIG/SWIGFLAGS.py b/test/SWIG/SWIGFLAGS.py
index cb91699..70e16a6 100644
--- a/test/SWIG/SWIGFLAGS.py
+++ b/test/SWIG/SWIGFLAGS.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify that we can use ${SOURCE} expansions in $SWIGFLAGS.
"""
-import sys
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/SWIG/live.py b/test/SWIG/live.py
index e7b2602..3d46b74 100644
--- a/test/SWIG/live.py
+++ b/test/SWIG/live.py
@@ -27,7 +27,6 @@ Test SWIG behavior with a live, installed SWIG.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import sys
import TestSCons
diff --git a/test/Scanner/Scanner.py b/test/Scanner/Scanner.py
index 7e39134..4889d0f 100644
--- a/test/Scanner/Scanner.py
+++ b/test/Scanner/Scanner.py
@@ -25,7 +25,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons
-import os
_python_ = TestSCons._python_
diff --git a/test/TEMPFILE/TEMPFILE-actionlist.py b/test/TEMPFILE/TEMPFILE-actionlist.py
new file mode 100644
index 0000000..d66b217
--- /dev/null
+++ b/test/TEMPFILE/TEMPFILE-actionlist.py
@@ -0,0 +1,53 @@
+#!/usr/bin/env python
+#
+# Copyright 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.
+#
+
+"""
+Verify that using $TEMPFILE in multiple actions in a
+list invokes each command in the list.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons(match=TestSCons.match_re)
+test.file_fixture('fixture/SConstruct-tempfile-actionlist', 'SConstruct')
+
+test.write('file.input', "file.input\n")
+
+test.run(arguments='-n -Q .',
+ stdout="""\
+Using tempfile \\S+ for command line:
+xxx.py -otempfile file.input
+xxx.py @\\S+
+Using tempfile \\S+ for command line:
+yyy.py -ofile.output tempfile
+yyy.py @\\S+
+""")
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/TempFileMunge/TEMPFILEDIR.py b/test/TEMPFILE/TEMPFILEDIR.py
index b528be3..b528be3 100644
--- a/test/TempFileMunge/TEMPFILEDIR.py
+++ b/test/TEMPFILE/TEMPFILEDIR.py
diff --git a/test/TempFileMunge/TEMPFILEPREFIX.py b/test/TEMPFILE/TEMPFILEPREFIX.py
index ac2ae46..62ac814 100644
--- a/test/TempFileMunge/TEMPFILEPREFIX.py
+++ b/test/TEMPFILE/TEMPFILEPREFIX.py
@@ -25,8 +25,6 @@ it to appear at the front of name of the generated tempfile
used for long command lines.
"""
-import os
-import stat
import TestSCons
diff --git a/test/TempFileMunge/TEMPFILESUFFIX.py b/test/TEMPFILE/TEMPFILESUFFIX.py
index a19317d..bd4cf09 100644
--- a/test/TempFileMunge/TEMPFILESUFFIX.py
+++ b/test/TEMPFILE/TEMPFILESUFFIX.py
@@ -25,8 +25,6 @@ it to appear at the end of name of the generated tempfile
used for long command lines.
"""
-import os
-import stat
import TestSCons
diff --git a/test/TEMPFILE/fixture/SConstruct-tempfile-actionlist b/test/TEMPFILE/fixture/SConstruct-tempfile-actionlist
new file mode 100644
index 0000000..07b6345
--- /dev/null
+++ b/test/TEMPFILE/fixture/SConstruct-tempfile-actionlist
@@ -0,0 +1,6 @@
+DefaultEnvironment(tools=[])
+env = Environment(tools=[],
+ BUILDCOM=['${TEMPFILE("xxx.py -otempfile $SOURCE")}',
+ '${TEMPFILE("yyy.py -o$TARGET tempfile")}'],
+ MAXLINELENGTH=1)
+env.Command('file.output', 'file.input', '$BUILDCOM')
diff --git a/test/TempFileMunge/fixture/SConstruct.tempfiledir b/test/TEMPFILE/fixture/SConstruct.tempfiledir
index ea26c27..ea26c27 100644
--- a/test/TempFileMunge/fixture/SConstruct.tempfiledir
+++ b/test/TEMPFILE/fixture/SConstruct.tempfiledir
diff --git a/test/TEX/generated_files.py b/test/TEX/generated_files.py
index 9bafc9b..418d99b 100644
--- a/test/TEX/generated_files.py
+++ b/test/TEX/generated_files.py
@@ -33,7 +33,6 @@ Test courtesy Rob Managan.
"""
import TestSCons
-import os
test = TestSCons.TestSCons()
diff --git a/test/TEX/synctex.py b/test/TEX/synctex.py
index 385a173..c9552d5 100644
--- a/test/TEX/synctex.py
+++ b/test/TEX/synctex.py
@@ -31,7 +31,6 @@ be aware of the created synctex.gz file.
Test configuration contributed by Robert Managan.
"""
-import os
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/Value/GetContent.py b/test/Value/GetContent.py
new file mode 100644
index 0000000..8fbbf29
--- /dev/null
+++ b/test/Value/GetContent.py
@@ -0,0 +1,50 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test the Value node as a build target
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.write('SConstruct', """
+import SCons.Script
+def null_build(target, source, env):
+ pass
+env = DefaultEnvironment()
+env['BUILDERS']['ValueBuilder'] = SCons.Builder.Builder(
+ action=SCons.Action.Action(null_build),
+ target_factory=SCons.Node.Python.Value,
+)
+v = env.ValueBuilder("myvalue",env.Dir("#"))
+v[0].get_text_contents()
+""")
+
+test.run()
+test.pass_test()
+
diff --git a/test/Variables/BoolVariable.py b/test/Variables/BoolVariable.py
index d259984..eaf496a 100644
--- a/test/Variables/BoolVariable.py
+++ b/test/Variables/BoolVariable.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test the BoolVariable canned Variable type.
"""
-import os
import TestSCons
diff --git a/test/Variables/EnumVariable.py b/test/Variables/EnumVariable.py
index cf35b9b..14a8bf3 100644
--- a/test/Variables/EnumVariable.py
+++ b/test/Variables/EnumVariable.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test the EnumVariable canned Variable type.
"""
-import os.path
import TestSCons
diff --git a/test/Variables/PackageVariable.py b/test/Variables/PackageVariable.py
index b3fd10a..eb14383 100644
--- a/test/Variables/PackageVariable.py
+++ b/test/Variables/PackageVariable.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test the PackageVariable canned Variable type.
"""
-import os
import TestSCons
diff --git a/test/YACC/YACCFLAGS.py b/test/YACC/YACCFLAGS.py
index b3f86fe..1ab8c0d 100644
--- a/test/YACC/YACCFLAGS.py
+++ b/test/YACC/YACCFLAGS.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import sys
import TestSCons
diff --git a/test/YACC/live.py b/test/YACC/live.py
index 4567dba..6314e6c 100644
--- a/test/YACC/live.py
+++ b/test/YACC/live.py
@@ -29,8 +29,6 @@ Test YACC and YACCFLAGS with a live yacc compiler.
"""
import TestSCons
-import sys
-import os
_exe = TestSCons._exe
_python_ = TestSCons._python_
diff --git a/test/ZIP/ZIPROOT.py b/test/ZIP/ZIPROOT.py
index f3e4496..24e82eb 100644
--- a/test/ZIP/ZIPROOT.py
+++ b/test/ZIP/ZIPROOT.py
@@ -24,8 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
-import stat
import TestSCons
diff --git a/test/emitter.py b/test/emitter.py
index 7712d3a..d2a8b67 100644
--- a/test/emitter.py
+++ b/test/emitter.py
@@ -25,7 +25,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons
-import os
test = TestSCons.TestSCons()
diff --git a/test/exitfns.py b/test/exitfns.py
index fca44b8..ee2ada1 100644
--- a/test/exitfns.py
+++ b/test/exitfns.py
@@ -25,7 +25,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons
-import os
test = TestSCons.TestSCons()
# also exclude these tests since it overides the exit function which doesnt work with coverage
@@ -35,7 +34,7 @@ if test.coverage_run():
test.skip_test("This test replaces the exit function which is needed by coverage to write test data; skipping test.")
sconstruct = """
-from SCons.exitfuncs import *
+from SCons.exitfuncs import register
def x1():
print("running x1")
diff --git a/test/gettext/MOFiles/UserExamples.py b/test/gettext/MOFiles/UserExamples.py
index 1b78268..5cc3037 100644
--- a/test/gettext/MOFiles/UserExamples.py
+++ b/test/gettext/MOFiles/UserExamples.py
@@ -30,7 +30,6 @@ Make sure, that the examples given in user guide all work.
"""
import TestSCons
-import os
test = TestSCons.TestSCons()
diff --git a/test/gettext/POUpdate/UserExamples.py b/test/gettext/POUpdate/UserExamples.py
index 5f3e6c7..be38996 100644
--- a/test/gettext/POUpdate/UserExamples.py
+++ b/test/gettext/POUpdate/UserExamples.py
@@ -29,7 +29,6 @@ Make sure, that the examples given in user guide all work.
"""
import TestSCons
-import os
test = TestSCons.TestSCons()
diff --git a/test/gettext/Translate/MultiCatalog.py b/test/gettext/Translate/MultiCatalog.py
index 1a5708c..e8c2b97 100644
--- a/test/gettext/Translate/MultiCatalog.py
+++ b/test/gettext/Translate/MultiCatalog.py
@@ -42,7 +42,6 @@ files correctly.
# replicate the bug.
import TestSCons
-from os import path
test = TestSCons.TestSCons()
diff --git a/test/ignore-command.py b/test/ignore-command.py
index d5c18a5..3833e61 100644
--- a/test/ignore-command.py
+++ b/test/ignore-command.py
@@ -28,7 +28,6 @@ Test use of a preceding - to ignore the return value from a command.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/import.py b/test/import.py
index df64a1e..55a40cc 100644
--- a/test/import.py
+++ b/test/import.py
@@ -27,7 +27,6 @@ modules directly.
import os
import re
-import sys
# must do this here, since TestSCons will chdir
tooldir = os.path.join(os.getcwd(), 'SCons', 'Tool')
diff --git a/test/long-lines/signature.py b/test/long-lines/signature.py
index 082a13b..7f9ba43 100644
--- a/test/long-lines/signature.py
+++ b/test/long-lines/signature.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# Copyright 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,8 +22,6 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
"""
Verify that use of long command lines correctly excludes arguments
surrounded by $( $) from the signature calculation.
diff --git a/test/multiline.py b/test/multiline.py
index c2fabf8..b910b69 100644
--- a/test/multiline.py
+++ b/test/multiline.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
diff --git a/test/no-arguments.py b/test/no-arguments.py
index 8925c48..5ed66ab 100644
--- a/test/no-arguments.py
+++ b/test/no-arguments.py
@@ -30,7 +30,6 @@ is no Default() in the SConstruct file and there are no command-line
arguments, or a null command-line argument.
"""
-import os.path
import TestSCons
diff --git a/test/option--random.py b/test/option--random.py
index c25ec12..1dafca4 100644
--- a/test/option--random.py
+++ b/test/option--random.py
@@ -27,7 +27,6 @@ Verify that we build correctly using the --random option.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
diff --git a/test/option--tree.py b/test/option--tree.py
index 290f1d4..5192ac0 100644
--- a/test/option--tree.py
+++ b/test/option--tree.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import sys
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/option-k.py b/test/option-k.py
index 4f4c86b..d6c81ea 100644
--- a/test/option-k.py
+++ b/test/option-k.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
diff --git a/test/option/debug-count.py b/test/option/debug-count.py
index f2fceb4..cf46feb 100644
--- a/test/option/debug-count.py
+++ b/test/option/debug-count.py
@@ -34,13 +34,6 @@ import TestSCons
test = TestSCons.TestSCons()
-try:
- import weakref
-except ImportError:
- x = "Python version has no 'weakref' module; skipping tests.\n"
- test.skip_test(x)
-
-
test.write('SConstruct', """
DefaultEnvironment(tools=[])
diff --git a/test/option/debug-memory.py b/test/option/debug-memory.py
index bf720cc..2958e0b 100644
--- a/test/option/debug-memory.py
+++ b/test/option/debug-memory.py
@@ -1,6 +1,7 @@
#!/usr/bin/env python
+# MIT License
#
-# __COPYRIGHT__
+# Copyright 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,8 +23,6 @@
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
"""
Test that the --debug=memory option works.
"""
@@ -31,21 +30,18 @@ Test that the --debug=memory option works.
import re
import TestSCons
+from TestCmd import IS_WINDOWS
test = TestSCons.TestSCons()
-try:
- import resource
-except ImportError:
+if not IS_WINDOWS:
try:
- import win32process
- import win32api
+ import resource # noqa: F401
except ImportError:
- x = "Python version has no 'resource' or 'win32api/win32process' module; skipping tests.\n"
+ x = "Python version has no 'resource' skipping tests.\n"
test.skip_test(x)
-
test.write('SConstruct', """
DefaultEnvironment(tools=[])
def cat(target, source, env):
diff --git a/test/option/debug-objects.py b/test/option/debug-objects.py
index beec4b7..9c8536c 100644
--- a/test/option/debug-objects.py
+++ b/test/option/debug-objects.py
@@ -32,13 +32,6 @@ import TestSCons
test = TestSCons.TestSCons()
-try:
- import weakref
-except ImportError:
- x = "Python version has no 'weakref' module; skipping tests.\n"
- test.skip_test(x)
-
-
test.write('SConstruct', """
DefaultEnvironment(tools=[])
diff --git a/test/packaging/msi/explicit-target.py b/test/packaging/msi/explicit-target.py
index 85bfa85..015baee 100644
--- a/test/packaging/msi/explicit-target.py
+++ b/test/packaging/msi/explicit-target.py
@@ -36,7 +36,7 @@ python = TestSCons.python
test = TestSCons.TestSCons()
try:
- from xml.dom.minidom import *
+ from xml.dom.minidom import parse
except ImportError:
test.skip_test('Canoot import xml.dom.minidom skipping test\n')
diff --git a/test/packaging/msi/file-placement.py b/test/packaging/msi/file-placement.py
index 2cc9e61..405e55b 100644
--- a/test/packaging/msi/file-placement.py
+++ b/test/packaging/msi/file-placement.py
@@ -35,7 +35,7 @@ python = TestSCons.python
test = TestSCons.TestSCons()
try:
- from xml.dom.minidom import *
+ from xml.dom.minidom import parse
except ImportError:
test.skip_test('Cannot import xml.dom.minidom; skipping test\n')
diff --git a/test/packaging/msi/package.py b/test/packaging/msi/package.py
index 4988742..19183bf 100644
--- a/test/packaging/msi/package.py
+++ b/test/packaging/msi/package.py
@@ -35,7 +35,7 @@ python = TestSCons.python
test = TestSCons.TestSCons()
try:
- from xml.dom.minidom import *
+ from xml.dom.minidom import parse
except ImportError:
test.skip_test('Canoot import xml.dom.minidom skipping test\n')
diff --git a/test/packaging/place-files-in-subdirectory.py b/test/packaging/place-files-in-subdirectory.py
index 838d6b8..dd422e6 100644
--- a/test/packaging/place-files-in-subdirectory.py
+++ b/test/packaging/place-files-in-subdirectory.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test the requirement to place files in a given subdirectory before archiving.
"""
-import os
import subprocess
import TestSCons
diff --git a/test/python-version.py b/test/python-version.py
index 9cfd2bd..bbec233 100644
--- a/test/python-version.py
+++ b/test/python-version.py
@@ -29,7 +29,6 @@ Verify the behavior of our check for unsupported or deprecated versions
of Python.
"""
-import os
import re
import TestCmd
diff --git a/test/runtest/SCons.py b/test/runtest/SCons.py
index 9bc86e8..20c4c64 100644
--- a/test/runtest/SCons.py
+++ b/test/runtest/SCons.py
@@ -34,9 +34,7 @@ import os
import TestRuntest
test = TestRuntest.TestRuntest()
-
-test.subdir(['SCons'],
- ['SCons', 'suite'])
+test.subdir(['SCons'], ['SCons', 'suite'])
pythonstring = TestRuntest.pythonstring
pythonflags = TestRuntest.pythonflags
@@ -44,11 +42,8 @@ src_passTests_py = os.path.join('SCons', 'passTests.py')
src_suite_passTests_py = os.path.join('SCons', 'suite', 'passTests.py')
test.write_passing_test(['SCons', 'pass.py'])
-
test.write_passing_test(['SCons', 'passTests.py'])
-
test.write_passing_test(['SCons', 'suite', 'pass.py'])
-
test.write_passing_test(['SCons', 'suite', 'passTests.py'])
expect_stdout = """\
diff --git a/test/runtest/fallback.py b/test/runtest/faillog.py
index b137307..e2ca67e 100644
--- a/test/runtest/fallback.py
+++ b/test/runtest/faillog.py
@@ -25,68 +25,52 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
-Test that runtest.py falls back (with a warning) using --noqmtest
-if it can't find qmtest on the $PATH.
+Test a list of tests in failed_tests.log to run with the --retry option
"""
-import os
+import os.path
import TestRuntest
pythonstring = TestRuntest.pythonstring
pythonflags = TestRuntest.pythonflags
+test_fail_py = os.path.join('test', 'fail.py')
+test_pass_py = os.path.join('test', 'pass.py')
test = TestRuntest.TestRuntest()
-
-# qmtest may be in more than one location in your path
-while test.where_is('qmtest'):
- qmtest=test.where_is('qmtest')
- dir = os.path.split(qmtest)[0]
- path = os.environ['PATH'].split(os.pathsep)
- path.remove(dir)
- os.environ['PATH'] = os.pathsep.join(path)
-
test.subdir('test')
-
-test_fail_py = os.path.join('test', 'fail.py')
-test_no_result_py = os.path.join('test', 'no_result.py')
-test_pass_py = os.path.join('test', 'pass.py')
-
test.write_failing_test(test_fail_py)
-test.write_no_result_test(test_no_result_py)
test.write_passing_test(test_pass_py)
expect_stdout = """\
%(pythonstring)s%(pythonflags)s %(test_fail_py)s
FAILING TEST STDOUT
-%(pythonstring)s%(pythonflags)s %(test_no_result_py)s
-NO RESULT TEST STDOUT
%(pythonstring)s%(pythonflags)s %(test_pass_py)s
PASSING TEST STDOUT
Failed the following test:
\t%(test_fail_py)s
-
-NO RESULT from the following test:
-\t%(test_no_result_py)s
""" % locals()
expect_stderr = """\
FAILING TEST STDERR
-NO RESULT TEST STDERR
PASSING TEST STDERR
"""
testlist = [
test_fail_py,
- test_no_result_py,
test_pass_py,
]
-test.run(arguments = '-k '+' '.join(testlist),
- status = 1,
- stdout = expect_stdout,
- stderr = expect_stderr)
+test.run(
+ arguments='-k --faillog=fail.log %s' % ' '.join(testlist),
+ status=1,
+ stdout=expect_stdout,
+ stderr=expect_stderr,
+)
+test.must_exist('fail.log')
+test.must_contain('fail.log', test_fail_py)
+test.must_not_exist('failed_tests.log')
test.pass_test()
diff --git a/test/runtest/noqmtest.py b/test/runtest/no_faillog.py
index fcf7ac0..db17c8e 100644
--- a/test/runtest/noqmtest.py
+++ b/test/runtest/no_faillog.py
@@ -25,60 +25,54 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
-Test that by default tests are invoked directly via Python, not
-using qmtest.
+Test a list of tests in failed_tests.log to run with the --retry option
"""
-import os
+import os.path
import TestRuntest
pythonstring = TestRuntest.pythonstring
pythonflags = TestRuntest.pythonflags
+test_fail_py = os.path.join('test', 'fail.py')
+test_pass_py = os.path.join('test', 'pass.py')
test = TestRuntest.TestRuntest()
-
test.subdir('test')
-
-test_fail_py = os.path.join('test', 'fail.py')
-test_no_result_py = os.path.join('test', 'no_result.py')
-test_pass_py = os.path.join('test', 'pass.py')
-
test.write_failing_test(test_fail_py)
-test.write_no_result_test(test_no_result_py)
test.write_passing_test(test_pass_py)
+test.write('failed_tests.log', """\
+%(test_fail_py)s
+""" % locals())
+
expect_stdout = """\
%(pythonstring)s%(pythonflags)s %(test_fail_py)s
FAILING TEST STDOUT
-%(pythonstring)s%(pythonflags)s %(test_no_result_py)s
-NO RESULT TEST STDOUT
%(pythonstring)s%(pythonflags)s %(test_pass_py)s
PASSING TEST STDOUT
Failed the following test:
\t%(test_fail_py)s
-
-NO RESULT from the following test:
-\t%(test_no_result_py)s
""" % locals()
expect_stderr = """\
FAILING TEST STDERR
-NO RESULT TEST STDERR
PASSING TEST STDERR
"""
testlist = [
test_fail_py,
- test_no_result_py,
test_pass_py,
]
-test.run(arguments = '-k %s' % ' '.join(testlist),
- status = 1,
- stdout = expect_stdout,
- stderr = expect_stderr)
+test.run(
+ arguments='-k --no-faillog %s' % ' '.join(testlist),
+ status=1,
+ stdout=expect_stdout,
+ stderr=expect_stderr,
+)
+test.must_not_exist('failing_tests.log')
test.pass_test()
diff --git a/test/runtest/print_time.py b/test/runtest/print_time.py
index 322b88b..834d2ae 100644
--- a/test/runtest/print_time.py
+++ b/test/runtest/print_time.py
@@ -42,13 +42,9 @@ test_no_result_py = re.escape(os.path.join('test', 'no_result.py'))
test_pass_py = re.escape(os.path.join('test', 'pass.py'))
test = TestRuntest.TestRuntest(match = TestCmd.match_re)
-
test.subdir('test')
-
test.write_failing_test(['test', 'fail.py'])
-
test.write_no_result_test(['test', 'no_result.py'])
-
test.write_passing_test(['test', 'pass.py'])
expect_stdout = """\
diff --git a/test/runtest/python.py b/test/runtest/python.py
index da62378..499ab77 100644
--- a/test/runtest/python.py
+++ b/test/runtest/python.py
@@ -37,9 +37,7 @@ if not hasattr(os.path, 'pardir'):
import TestRuntest
test = TestRuntest.TestRuntest()
-
test_pass_py = os.path.join('test', 'pass.py')
-
head, python = os.path.split(TestRuntest.python)
head, dir = os.path.split(head)
diff --git a/test/runtest/retry.py b/test/runtest/retry.py
new file mode 100644
index 0000000..4280152
--- /dev/null
+++ b/test/runtest/retry.py
@@ -0,0 +1,69 @@
+#!/usr/bin/env python
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+"""
+Test a list of tests in failed_tests.log to run with the --retry option
+"""
+
+import os.path
+
+import TestRuntest
+
+pythonstring = TestRuntest.pythonstring
+pythonflags = TestRuntest.pythonflags
+test_fail_py = os.path.join('test', 'fail.py')
+test_no_result_py = os.path.join('test', 'no_result.py')
+test_pass_py = os.path.join('test', 'pass.py')
+
+test = TestRuntest.TestRuntest()
+
+test.subdir('test')
+test.write_failing_test(['test', 'fail.py'])
+test.write_no_result_test(['test', 'no_result.py'])
+test.write_passing_test(['test', 'pass.py'])
+
+test.write('failed_tests.log', """\
+%(test_fail_py)s
+""" % locals())
+
+expect_stdout = """\
+%(pythonstring)s%(pythonflags)s %(test_fail_py)s
+FAILING TEST STDOUT
+""" % locals()
+
+expect_stderr = """\
+FAILING TEST STDERR
+"""
+
+test.run(arguments='-k --retry', status=1, stdout=expect_stdout, stderr=expect_stderr)
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/runtest/simple/combined.py b/test/runtest/simple/combined.py
index ec0a1bb..a54e57c 100644
--- a/test/runtest/simple/combined.py
+++ b/test/runtest/simple/combined.py
@@ -1,4 +1,3 @@
-
#!/usr/bin/env python
#
# __COPYRIGHT__
@@ -34,21 +33,17 @@ import os
import TestRuntest
-test = TestRuntest.TestRuntest()
-
pythonstring = TestRuntest.pythonstring
pythonflags = TestRuntest.pythonflags
test_fail_py = os.path.join('test', 'fail.py')
test_no_result_py = os.path.join('test', 'no_result.py')
test_pass_py = os.path.join('test', 'pass.py')
+test = TestRuntest.TestRuntest()
test.subdir('test')
-
-test.write_failing_test(['test', 'fail.py'])
-
-test.write_no_result_test(['test', 'no_result.py'])
-
-test.write_passing_test(['test', 'pass.py'])
+test.write_failing_test(test_fail_py)
+test.write_no_result_test(test_no_result_py)
+test.write_passing_test(test_pass_py)
expect_stdout = """\
%(pythonstring)s%(pythonflags)s %(test_fail_py)s
@@ -71,10 +66,14 @@ NO RESULT TEST STDERR
PASSING TEST STDERR
"""
-test.run(arguments='-k test',
- status=1,
- stdout=expect_stdout,
- stderr=expect_stderr)
+test.run(
+ arguments='-k test',
+ status=1,
+ stdout=expect_stdout,
+ stderr=expect_stderr
+)
+test.must_exist('failed_tests.log')
+test.must_contain('failed_tests.log', test_fail_py)
test.pass_test()
diff --git a/test/runtest/testlistfile.py b/test/runtest/testlistfile.py
index 063a8d0..5c956b8 100644
--- a/test/runtest/testlistfile.py
+++ b/test/runtest/testlistfile.py
@@ -26,10 +26,10 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Test a list of tests to run in a file specified with the -f option.
+The commented-out test should not run.
"""
import os.path
-import re
import TestRuntest
@@ -42,11 +42,8 @@ test_pass_py = os.path.join('test', 'pass.py')
test = TestRuntest.TestRuntest()
test.subdir('test')
-
test.write_failing_test(['test', 'fail.py'])
-
test.write_no_result_test(['test', 'no_result.py'])
-
test.write_passing_test(['test', 'pass.py'])
test.write('t.txt', """\
diff --git a/test/scons-time/func/prefix.py b/test/scons-time/func/prefix.py
index 67a0c6b..36c9ddf 100644
--- a/test/scons-time/func/prefix.py
+++ b/test/scons-time/func/prefix.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify that the func -p and --prefix options specify what log files to use.
"""
-import os.path
import TestSCons_time
diff --git a/test/scons-time/run/archive/zip.py b/test/scons-time/run/archive/zip.py
index 4620440..7bd5538 100644
--- a/test/scons-time/run/archive/zip.py
+++ b/test/scons-time/run/archive/zip.py
@@ -29,7 +29,6 @@ Verify basic generation of timing information from an input fake-project
.zip file.
"""
-import sys
import TestSCons_time
diff --git a/test/sconsign/script/SConsignFile.py b/test/sconsign/script/SConsignFile.py
index cd82fac..47fe94f 100644
--- a/test/sconsign/script/SConsignFile.py
+++ b/test/sconsign/script/SConsignFile.py
@@ -29,7 +29,6 @@ Verify that the sconsign script works with files generated when
using the signatures in an SConsignFile().
"""
-import re
import TestSCons
import TestSConsign
diff --git a/test/silent-command.py b/test/silent-command.py
index 7f3b010..3622a04 100644
--- a/test/silent-command.py
+++ b/test/silent-command.py
@@ -28,7 +28,6 @@ Test the use of a preceding @ to suppress printing a command.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import TestSCons
diff --git a/test/srcchange.py b/test/srcchange.py
index 30f6f20..e72d923 100644
--- a/test/srcchange.py
+++ b/test/srcchange.py
@@ -32,7 +32,6 @@ of Decider('content').
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
diff --git a/test/subdir.py b/test/subdir.py
index 363d44c..c5bfcdc 100644
--- a/test/subdir.py
+++ b/test/subdir.py
@@ -25,7 +25,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons
-import os.path
_python_ = TestSCons._python_
diff --git a/test/symlink/dangling-include.py b/test/symlink/dangling-include.py
index b7d5d2f..081573f 100644
--- a/test/symlink/dangling-include.py
+++ b/test/symlink/dangling-include.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test how we handle #includes of dangling symlinks.
"""
-import os
import TestSCons
diff --git a/test/symlink/dangling-source.py b/test/symlink/dangling-source.py
index b2bc540..94690f4 100644
--- a/test/symlink/dangling-source.py
+++ b/test/symlink/dangling-source.py
@@ -28,7 +28,6 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test how we handle dangling symlinks as source files.
"""
-import os
import TestSCons
diff --git a/test/timestamp-fallback.py b/test/timestamp-fallback.py
index 2dd50a2..b3e812b 100644
--- a/test/timestamp-fallback.py
+++ b/test/timestamp-fallback.py
@@ -32,7 +32,6 @@ rare no-md5 Pythons comes into play (some entities ban the use
of md5 as unsafe, although SCons does not use it in a security context.
"""
-import sys
import os
import TestSCons
diff --git a/test/tool_args.py b/test/tool_args.py
index 6983705..464d009 100644
--- a/test/tool_args.py
+++ b/test/tool_args.py
@@ -29,7 +29,6 @@ Test the ability to pass a dictionary of keyword arguments to
a Tool specification's generate() method.
"""
-import os.path
import TestSCons
diff --git a/test/toolpath/basic.py b/test/toolpath/basic.py
index 793497b..0d2429e 100644
--- a/test/toolpath/basic.py
+++ b/test/toolpath/basic.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
diff --git a/test/toolpath/nested/nested.py b/test/toolpath/nested/nested.py
index df2ba07..47c0b03 100644
--- a/test/toolpath/nested/nested.py
+++ b/test/toolpath/nested/nested.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/toolpath/relative_import/relative_import.py b/test/toolpath/relative_import/relative_import.py
index 8fa2f62..f4362f7 100644
--- a/test/toolpath/relative_import/relative_import.py
+++ b/test/toolpath/relative_import/relative_import.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os.path
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/update-release-info/update-release-info.py b/test/update-release-info/update-release-info.py
index f353d38..2de4713 100644
--- a/test/update-release-info/update-release-info.py
+++ b/test/update-release-info/update-release-info.py
@@ -27,7 +27,8 @@ have the appropriate triggers to cause the modifications.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os, sys, time
+import os
+import time
import TestRuntest
diff --git a/test/virtualenv/activated/option/enable-virtualenv.py b/test/virtualenv/activated/option/enable-virtualenv.py
index a5ceecc..ff06583 100644
--- a/test/virtualenv/activated/option/enable-virtualenv.py
+++ b/test/virtualenv/activated/option/enable-virtualenv.py
@@ -30,7 +30,6 @@ Ensure that the --enable-virtualenv flag works.
import TestSCons
import SCons.Platform.virtualenv
-import sys
import os
import re
diff --git a/test/virtualenv/activated/option/ignore-virtualenv.py b/test/virtualenv/activated/option/ignore-virtualenv.py
index ac6f945..b0d482e 100644
--- a/test/virtualenv/activated/option/ignore-virtualenv.py
+++ b/test/virtualenv/activated/option/ignore-virtualenv.py
@@ -30,7 +30,6 @@ Ensure that the --ignore-virtualenv flag works.
import TestSCons
import SCons.Platform.virtualenv
-import sys
import os
import re
diff --git a/test/virtualenv/activated/virtualenv_activated_python.py b/test/virtualenv/activated/virtualenv_activated_python.py
index c673ae1..4e793da 100644
--- a/test/virtualenv/activated/virtualenv_activated_python.py
+++ b/test/virtualenv/activated/virtualenv_activated_python.py
@@ -33,7 +33,6 @@ environment or in unactivated virtualenv.
import TestSCons
import SCons.Platform.virtualenv
-import sys
import os
import re
diff --git a/test/virtualenv/activated/virtualenv_detect_virtualenv.py b/test/virtualenv/activated/virtualenv_detect_virtualenv.py
index 2c00793..e7b7cb0 100644
--- a/test/virtualenv/activated/virtualenv_detect_virtualenv.py
+++ b/test/virtualenv/activated/virtualenv_detect_virtualenv.py
@@ -30,7 +30,6 @@ Check if SCons.Platform.virtualenv.Virtualenv() works in SConscripts.
import TestSCons
import SCons.Platform.virtualenv
-import sys
test = TestSCons.TestSCons()
diff --git a/test/virtualenv/regularenv/virtualenv_detect_regularenv.py b/test/virtualenv/regularenv/virtualenv_detect_regularenv.py
index 57a0d4f..6856838 100644
--- a/test/virtualenv/regularenv/virtualenv_detect_regularenv.py
+++ b/test/virtualenv/regularenv/virtualenv_detect_regularenv.py
@@ -30,7 +30,6 @@ Check if SCons.Platform.virtualenv.Virtualenv() works in SConscript.
import TestSCons
import SCons.Platform.virtualenv
-import sys
test = TestSCons.TestSCons()
diff --git a/test/virtualenv/unactivated/virtualenv_unactivated_python.py b/test/virtualenv/unactivated/virtualenv_unactivated_python.py
index a4dc240..38d5329 100644
--- a/test/virtualenv/unactivated/virtualenv_unactivated_python.py
+++ b/test/virtualenv/unactivated/virtualenv_unactivated_python.py
@@ -33,7 +33,6 @@ a regular environment or in an activated virtualenv.
import TestSCons
import SCons.Platform.virtualenv
-import sys
import os
import re
diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py
index f0051ba..76609a0 100644
--- a/testing/framework/TestCmd.py
+++ b/testing/framework/TestCmd.py
@@ -309,7 +309,6 @@ import tempfile
import threading
import time
import traceback
-import types
from collections import UserList, UserString
from subprocess import PIPE, STDOUT
@@ -345,13 +344,13 @@ def is_List(e):
def to_bytes(s):
- if isinstance(s, bytes) or bytes is str:
+ if isinstance(s, bytes):
return s
return bytes(s, 'utf-8')
def to_str(s):
- if bytes is str or is_String(s):
+ if is_String(s):
return s
return str(s, 'utf-8')
@@ -470,7 +469,7 @@ def match_exact(lines=None, matches=None, newline=os.sep):
:returns: an object (1) on match, else None, like re.match
"""
- if isinstance(lines, bytes) or bytes is str:
+ if isinstance(lines, bytes):
newline = to_bytes(newline)
if not is_List(lines):
diff --git a/testing/framework/TestCmdTests.py b/testing/framework/TestCmdTests.py
index 7017d2c..e37b90e 100644
--- a/testing/framework/TestCmdTests.py
+++ b/testing/framework/TestCmdTests.py
@@ -24,13 +24,11 @@ __revision__ = "TestCmdTests.py 1.3.D001 2010/06/03 12:58:27 knight"
import os
import shutil
-import signal
import stat
import subprocess
import sys
import tempfile
import time
-import types
import unittest
from io import StringIO
from contextlib import closing
diff --git a/testing/framework/TestCommon.py b/testing/framework/TestCommon.py
index 35bf365..1471439 100644
--- a/testing/framework/TestCommon.py
+++ b/testing/framework/TestCommon.py
@@ -99,7 +99,6 @@ __author__ = "Steven Knight <knight at baldmt dot com>"
__revision__ = "TestCommon.py 1.3.D001 2010/06/03 12:58:27 knight"
__version__ = "1.3"
-import copy
import glob
import os
import stat
diff --git a/testing/framework/TestCommonTests.py b/testing/framework/TestCommonTests.py
index 6c9e92d..8a93b35 100644
--- a/testing/framework/TestCommonTests.py
+++ b/testing/framework/TestCommonTests.py
@@ -22,11 +22,9 @@ SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
__author__ = "Steven Knight <knight at baldmt dot com>"
__revision__ = "TestCommonTests.py 1.3.D001 2010/06/03 12:58:27 knight"
-import difflib
import os
import re
import signal
-import stat
import sys
import unittest
diff --git a/testing/framework/TestRuntest.py b/testing/framework/TestRuntest.py
index 801f710..a70110c 100644
--- a/testing/framework/TestRuntest.py
+++ b/testing/framework/TestRuntest.py
@@ -36,8 +36,6 @@ else:
pythonstring = python
pythonstring = pythonstring.replace('\\', '\\\\')
pythonflags = ''
-if sys.version_info[0] < 3:
- pythonflags = ' -tt'
failing_test_template = """\
import sys
diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py
index a7eb4c5..36b9df4 100644
--- a/testing/framework/TestSCons.py
+++ b/testing/framework/TestSCons.py
@@ -1491,12 +1491,9 @@ SConscript(sconscript)
self.run(program=python, stdin="""\
import sysconfig, sys, os.path
py_ver = 'python%d%d' % sys.version_info[:2]
-# use distutils to help find include and lib path
-# TODO: PY3 fine to use sysconfig.get_config_var("INCLUDEPY")
try:
- import distutils.sysconfig
- exec_prefix = distutils.sysconfig.EXEC_PREFIX
- include = distutils.sysconfig.get_python_inc()
+ exec_prefix = sysconfig.get_config_var("exec_prefix")
+ include = sysconfig.get_config_var("INCLUDEPY")
print(include)
lib_path = os.path.join(exec_prefix, 'libs')
if not os.path.exists(lib_path):
@@ -1826,7 +1823,11 @@ class TimeSCons(TestSCons):
# TODO(sgk): allow the caller to specify the target (argument)
# that must be up-to-date.
self.add_timing_options(kw)
- self.up_to_date(arguments='.', **kw)
+
+ # Build up regex for
+ # SConscript:/private/var/folders/ng/48pttrpj239fw5rmm3x65pxr0000gn/T/testcmd.12081.pk1bv5i5/SConstruct took 533.646 ms
+ read_str = 'SConscript:.*\n'
+ self.up_to_date(arguments='.', read_str=read_str, **kw)
sys.stdout.write(self.stdout())
stats = self.collect_stats(self.stdout())
# time-commands should always be 0.0 on a null build, because
@@ -1888,6 +1889,27 @@ class TimeSCons(TestSCons):
destination = source.replace(source_dir, dest_dir)
shutil.copy2(source, destination)
+ def up_to_date(self, arguments='.', read_str="", **kw):
+ """Asserts that all of the targets listed in arguments is
+ up to date, but does not make any assumptions on other targets.
+ This function is most useful in conjunction with the -n option.
+ Note: This custom version for timings tests does NOT escape
+ read_str.
+ """
+ s = ""
+ for arg in arguments.split():
+ s = s + "scons: `%s' is up to date.\n" % arg
+ kw['arguments'] = arguments
+ stdout = self.wrap_stdout(read_str="REPLACEME", build_str=s)
+ # Append '.*' so that timing output that comes after the
+ # up-to-date output is okay.
+ stdout = re.escape(stdout) + '.*'
+ stdout = stdout.replace('REPLACEME', read_str)
+ kw['stdout'] = stdout
+ kw['match'] = self.match_re_dotall
+ self.run(**kw)
+
+
# In some environments, $AR will generate a warning message to stderr
# if the library doesn't previously exist and is being created. One
diff --git a/testing/framework/TestSConsign.py b/testing/framework/TestSConsign.py
index 665059c..11a764c 100644
--- a/testing/framework/TestSConsign.py
+++ b/testing/framework/TestSConsign.py
@@ -19,7 +19,6 @@ in this subclass.
import os
import os.path
-import sys
from TestSCons import *
from TestSCons import __all__