summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2020-02-21 02:53:29 (GMT)
committerGitHub <noreply@github.com>2020-02-21 02:53:29 (GMT)
commit0814deb56ca870f631a415a3255ce8dd99688e01 (patch)
tree22fe52c634a5b1a483a9ad208b4e41b751a7392a
parent420f23129a3eb298e20e2250f97eb8eefdd923d4 (diff)
parent54c36335c575a98fcf6de2ff84c16b66efa7da5e (diff)
downloadSCons-0814deb56ca870f631a415a3255ce8dd99688e01.zip
SCons-0814deb56ca870f631a415a3255ce8dd99688e01.tar.gz
SCons-0814deb56ca870f631a415a3255ce8dd99688e01.tar.bz2
Merge branch 'master' into topic/grossag/compoundactionscan
-rw-r--r--.github/FUNDING.yml2
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md1
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.md1
-rw-r--r--.travis.yml19
-rw-r--r--LICENSE2
-rwxr-xr-xREADME-SF.rst8
-rw-r--r--README-local43
-rwxr-xr-xREADME.rst8
-rwxr-xr-xReleaseConfig4
-rw-r--r--SConstruct2
-rw-r--r--bin/calibrate.py4
-rw-r--r--bin/import-test.py2
-rw-r--r--bin/install_scons.py2
-rw-r--r--bin/update-release-info.py458
-rwxr-xr-xbootstrap.py20
-rw-r--r--doc/SConscript7
-rw-r--r--doc/design/engine.xml14
-rw-r--r--doc/generated/variables.gen11
-rw-r--r--doc/generated/variables.mod4
-rw-r--r--doc/man/scons.xml971
-rw-r--r--doc/scons.mod45
-rw-r--r--doc/user/build-install.xml52
-rw-r--r--doc/user/builders-writing.xml2
-rw-r--r--doc/user/depends.xml52
-rw-r--r--doc/user/environments.xml49
-rw-r--r--doc/user/install.xml18
-rw-r--r--doc/user/less-simple.xml6
-rw-r--r--doc/user/misc.xml15
-rw-r--r--doc/user/nodes.xml4
-rw-r--r--doc/user/output.xml43
-rw-r--r--doc/user/parseflags.xml20
-rw-r--r--doc/user/simple.xml65
-rwxr-xr-xruntest.py4
-rw-r--r--site_scons/SConsRevision.py8
-rwxr-xr-xsrc/CHANGES.txt39
-rw-r--r--src/README.txt11
-rw-r--r--src/engine/MANIFEST.in2
-rw-r--r--src/engine/SCons/Action.py14
-rw-r--r--src/engine/SCons/ActionTests.py10
-rw-r--r--src/engine/SCons/Builder.py12
-rw-r--r--src/engine/SCons/BuilderTests.py36
-rw-r--r--src/engine/SCons/Conftest.py4
-rw-r--r--src/engine/SCons/Defaults.py2
-rw-r--r--src/engine/SCons/DefaultsTests.py2
-rw-r--r--src/engine/SCons/Environment.py10
-rw-r--r--src/engine/SCons/Environment.xml78
-rw-r--r--src/engine/SCons/EnvironmentTests.py20
-rw-r--r--src/engine/SCons/Executor.py2
-rw-r--r--src/engine/SCons/JobTests.py4
-rw-r--r--src/engine/SCons/Memoize.py2
-rw-r--r--src/engine/SCons/Node/AliasTests.py2
-rw-r--r--src/engine/SCons/Node/FS.py41
-rw-r--r--src/engine/SCons/Node/FSTests.py49
-rw-r--r--src/engine/SCons/Node/NodeTests.py2
-rw-r--r--src/engine/SCons/Node/Python.py22
-rw-r--r--src/engine/SCons/Node/PythonTests.py34
-rw-r--r--src/engine/SCons/Node/__init__.py2
-rw-r--r--src/engine/SCons/PathListTests.py2
-rw-r--r--src/engine/SCons/Platform/__init__.py4
-rw-r--r--src/engine/SCons/Platform/win32.py43
-rw-r--r--src/engine/SCons/SConf.py57
-rw-r--r--src/engine/SCons/SConfTests.py30
-rw-r--r--src/engine/SCons/SConsign.py3
-rw-r--r--src/engine/SCons/SConsignTests.py2
-rw-r--r--src/engine/SCons/Scanner/ProgTests.py17
-rw-r--r--src/engine/SCons/Scanner/Python.py171
-rw-r--r--src/engine/SCons/Scanner/PythonTests.py269
-rw-r--r--src/engine/SCons/Scanner/RCTests.py2
-rw-r--r--src/engine/SCons/Scanner/ScannerTests.py2
-rw-r--r--src/engine/SCons/Script/Interactive.py4
-rw-r--r--src/engine/SCons/Script/Main.py129
-rw-r--r--src/engine/SCons/Script/Main.xml88
-rw-r--r--src/engine/SCons/Subst.xml2
-rw-r--r--src/engine/SCons/SubstTests.py2
-rw-r--r--src/engine/SCons/Taskmaster.py41
-rw-r--r--src/engine/SCons/TaskmasterTests.py12
-rw-r--r--src/engine/SCons/Tool/DCommon.py2
-rw-r--r--src/engine/SCons/Tool/DCommon.xml32
-rw-r--r--src/engine/SCons/Tool/FortranCommon.py2
-rw-r--r--src/engine/SCons/Tool/MSCommon/common.py6
-rw-r--r--src/engine/SCons/Tool/MSCommon/vc.py285
-rw-r--r--src/engine/SCons/Tool/MSCommon/vs.py18
-rw-r--r--src/engine/SCons/Tool/__init__.py189
-rw-r--r--src/engine/SCons/Tool/c++.xml17
-rw-r--r--src/engine/SCons/Tool/cc.xml22
-rw-r--r--src/engine/SCons/Tool/cyglink.py2
-rw-r--r--src/engine/SCons/Tool/dmd.py2
-rw-r--r--src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py10
-rw-r--r--src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py2
-rw-r--r--src/engine/SCons/Tool/f03.xml16
-rw-r--r--src/engine/SCons/Tool/f08.py2
-rw-r--r--src/engine/SCons/Tool/f08.xml16
-rw-r--r--src/engine/SCons/Tool/f77.xml16
-rw-r--r--src/engine/SCons/Tool/f90.xml16
-rw-r--r--src/engine/SCons/Tool/f95.xml16
-rw-r--r--src/engine/SCons/Tool/fortran.xml16
-rw-r--r--src/engine/SCons/Tool/gdc.py2
-rw-r--r--src/engine/SCons/Tool/install.py2
-rw-r--r--src/engine/SCons/Tool/install.xml37
-rw-r--r--src/engine/SCons/Tool/intelc.py10
-rw-r--r--src/engine/SCons/Tool/javac.xml12
-rw-r--r--src/engine/SCons/Tool/ldc.py2
-rw-r--r--src/engine/SCons/Tool/link.py2
-rw-r--r--src/engine/SCons/Tool/link.xml24
-rw-r--r--src/engine/SCons/Tool/mslink.py2
-rw-r--r--src/engine/SCons/Tool/msvc.xml1
-rw-r--r--src/engine/SCons/Tool/msvs.py30
-rw-r--r--src/engine/SCons/Tool/msvsTests.py16
-rw-r--r--src/engine/SCons/Tool/packaging.xml66
-rw-r--r--src/engine/SCons/Tool/packaging/__init__.xml56
-rw-r--r--src/engine/SCons/Tool/packaging/ipk.py2
-rw-r--r--src/engine/SCons/Tool/packaging/rpm.py2
-rw-r--r--src/engine/SCons/Tool/python.py49
-rw-r--r--src/engine/SCons/Tool/python.xml36
-rw-r--r--src/engine/SCons/Tool/qt.py2
-rw-r--r--src/engine/SCons/Tool/rpmutils.py2
-rw-r--r--src/engine/SCons/Tool/swig.py2
-rw-r--r--src/engine/SCons/Tool/tex.py2
-rw-r--r--src/engine/SCons/Tool/textfile.py2
-rw-r--r--src/engine/SCons/Tool/textfile.xml10
-rw-r--r--src/engine/SCons/Util.py53
-rw-r--r--src/engine/SCons/UtilTests.py7
-rw-r--r--src/engine/SCons/Variables/ListVariableTests.py2
-rw-r--r--src/engine/SCons/Variables/PackageVariableTests.py4
-rw-r--r--src/engine/SCons/cpp.py4
-rw-r--r--src/engine/SCons/cppTests.py3
-rw-r--r--src/engine/SCons/dblite.py82
-rw-r--r--src/script/scons-configure-cache.py1
-rw-r--r--src/script/scons-time.py1
-rwxr-xr-xsrc/script/scons.py2
-rw-r--r--src/script/sconsign.py2
-rwxr-xr-xsrc/setup.py3
-rw-r--r--src/test_files.py2
-rw-r--r--src/test_interrupts.py4
-rw-r--r--src/test_pychecker.py2
-rw-r--r--src/test_setup.py2
-rw-r--r--src/test_strings.py2
-rw-r--r--test/AS/as-live.py4
-rw-r--r--test/Actions/actions.py10
-rw-r--r--test/AddOption/help.py5
-rw-r--r--test/CC/CCVERSION-fixture/versioned.py4
-rw-r--r--test/CXX/CXXVERSION.py8
-rw-r--r--test/CacheDir/value_dependencies.py52
-rw-r--r--test/CacheDir/value_dependencies/SConstruct32
-rw-r--r--test/CacheDir/value_dependencies/testfile0
-rw-r--r--test/Command.py3
-rw-r--r--test/Configure/ConfigureDryRunError.py8
-rw-r--r--test/Configure/basic.py6
-rw-r--r--test/Configure/config-h.py6
-rw-r--r--test/Configure/custom-tests.py7
-rw-r--r--test/Configure/fixture/SConstruct.issue-29065
-rw-r--r--test/Configure/implicit-cache.py10
-rw-r--r--test/Configure/issue-2906-useful-duplicate-configure-message.py57
-rw-r--r--test/Configure/issue-3469/fixture/SConstruct25
-rw-r--r--test/Configure/issue-3469/fixture/sconstest.skip0
-rw-r--r--test/Configure/issue-3469/issue-3469.py94
-rw-r--r--test/Configure/option--config.py142
-rw-r--r--test/DVIPDF/DVIPDF.py5
-rw-r--r--test/DVIPDF/DVIPDFFLAGS.py5
-rw-r--r--test/DVIPDF/makeindex.py6
-rw-r--r--test/DVIPS/DVIPS.py44
-rw-r--r--test/DVIPS/DVIPSFLAGS.py7
-rw-r--r--test/Dir/Dir.py18
-rw-r--r--test/ENV.py5
-rw-r--r--test/File.py14
-rw-r--r--test/GetBuildFailures/parallel.py2
-rw-r--r--test/Ghostscript/GS.py5
-rw-r--r--test/Glob/glob-libpath.py6
-rw-r--r--test/Interactive/shell.py6
-rw-r--r--test/Interactive/version.py5
-rw-r--r--test/Java/multi-step.py6
-rw-r--r--test/LINK/LINKFLAGS.py6
-rw-r--r--test/LINK/SHLINKFLAGS.py6
-rw-r--r--test/LINK/VersionedLib.py3
-rw-r--r--test/MSVC/MSVC_UWP_APP.py39
-rw-r--r--test/MSVC/mssdk.py6
-rw-r--r--test/MSVC/msvc.py6
-rw-r--r--test/QT/Tool.py7
-rw-r--r--test/QT/copied-env.py5
-rw-r--r--test/QT/qt_warnings.py6
-rw-r--r--test/SCONS_LIB_DIR.py3
-rw-r--r--test/SPAWN.py15
-rw-r--r--test/SWIG/SWIG.py42
-rw-r--r--test/SWIG/SWIGPATH.py10
-rw-r--r--test/SWIG/build-dir.py6
-rw-r--r--test/SWIG/implicit-dependencies.py10
-rw-r--r--test/SWIG/live.py7
-rw-r--r--test/SWIG/noproxy.py1
-rw-r--r--test/TEMPFILEPREFIX.py6
-rw-r--r--test/TEMPFILESUFFIX.py6
-rw-r--r--test/TEX/TEX.py7
-rw-r--r--test/TEX/auxiliaries.py4
-rwxr-xr-xtest/TEX/biber_biblatex.py7
-rw-r--r--test/TEX/biber_biblatex2.py7
-rwxr-xr-xtest/TEX/biblatex.py7
-rw-r--r--test/TEX/biblatex_plain.py7
-rw-r--r--test/TEX/bibliography.py6
-rw-r--r--test/TEX/bibtex-latex-rerun.py2
-rw-r--r--test/TEX/clean.py9
-rw-r--r--test/TEX/configure.py4
-rw-r--r--test/TEX/dryrun.py2
-rw-r--r--test/TEX/glossaries.py9
-rw-r--r--test/TEX/glossary.py9
-rw-r--r--test/TEX/lstinputlisting.py9
-rw-r--r--test/TEX/makeindex.py4
-rw-r--r--test/TEX/multi-line_include_options.py2
-rw-r--r--test/TEX/multi-run.py7
-rw-r--r--test/TEX/multibib.py7
-rw-r--r--test/TEX/newglossary.py9
-rw-r--r--test/TEX/nomencl.py9
-rw-r--r--test/TEX/recursive_scanner_dependencies_import.py9
-rw-r--r--test/TEX/recursive_scanner_dependencies_input.py2
-rw-r--r--test/TEX/rename_result.py2
-rw-r--r--test/TEX/synctex.py2
-rw-r--r--test/TEX/usepackage.py2
-rw-r--r--test/TEX/variant_dir.py5
-rw-r--r--test/TEX/variant_dir_bibunit.py11
-rw-r--r--test/TEX/variant_dir_dup0.py4
-rw-r--r--test/TEX/variant_dir_newglossary.py9
-rw-r--r--test/TEX/variant_dir_style_dup0.py4
-rw-r--r--test/Value.py2
-rw-r--r--test/VariantDir/reflect.py8
-rw-r--r--test/Win32/bad-drive.py2
-rw-r--r--test/Win32/default-drive.py2
-rw-r--r--test/builderrors.py2
-rw-r--r--test/explain/basic.py6
-rw-r--r--test/explain/save-info.py7
-rw-r--r--test/fixture/mycompile.py2
-rw-r--r--test/fixture/mylink.py12
-rw-r--r--test/fixture/myrewrite.py2
-rw-r--r--test/fixture/python_scanner/curdir_reference/helper.py0
-rw-r--r--test/fixture/python_scanner/curdir_reference/sconstest.skip0
-rw-r--r--test/fixture/python_scanner/curdir_reference/script.py1
-rw-r--r--test/fixture/python_scanner/from_import_simple_package_module1.py1
-rw-r--r--test/fixture/python_scanner/from_import_simple_package_module1_as.py1
-rw-r--r--test/fixture/python_scanner/from_import_simple_package_modules_no_space.py1
-rw-r--r--test/fixture/python_scanner/from_import_simple_package_modules_with_space.py1
-rw-r--r--test/fixture/python_scanner/import_simple_package_module1.py1
-rw-r--r--test/fixture/python_scanner/import_simple_package_module1_as.py1
-rw-r--r--test/fixture/python_scanner/imports_nested3.py1
-rw-r--r--test/fixture/python_scanner/imports_simple_package.py1
-rw-r--r--test/fixture/python_scanner/nested1/__init__.py0
-rw-r--r--test/fixture/python_scanner/nested1/module.py0
-rw-r--r--test/fixture/python_scanner/nested1/nested2/__init__.py0
-rw-r--r--test/fixture/python_scanner/nested1/nested2/module.py0
-rw-r--r--test/fixture/python_scanner/nested1/nested2/nested3/__init__.py0
-rw-r--r--test/fixture/python_scanner/nested1/nested2/nested3/imports_grandparent_module.py1
-rw-r--r--test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_module.py1
-rw-r--r--test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_then_submodule.py1
-rw-r--r--test/fixture/python_scanner/nested1/nested2/nested3/module.py0
-rw-r--r--test/fixture/python_scanner/nested1/nested2/nested3/sconstest.skip0
-rw-r--r--test/fixture/python_scanner/nested1/nested2/sconstest.skip0
-rw-r--r--test/fixture/python_scanner/nested1/nested2a/__init__.py0
-rw-r--r--test/fixture/python_scanner/nested1/nested2a/module.py0
-rw-r--r--test/fixture/python_scanner/nested1/nested2a/sconstest.skip0
-rw-r--r--test/fixture/python_scanner/nested1/sconstest.skip0
-rw-r--r--test/fixture/python_scanner/sconstest.skip0
-rw-r--r--test/fixture/python_scanner/simple_package/__init__.py0
-rw-r--r--test/fixture/python_scanner/simple_package/module1.py0
-rw-r--r--test/fixture/python_scanner/simple_package/module2.py0
-rw-r--r--test/fixture/python_scanner/simple_package/sconstest.skip0
-rw-r--r--test/fixture/wrapper.py2
-rw-r--r--test/fixture/wrapper_with_args.py2
-rw-r--r--test/gnutools.py6
-rw-r--r--test/option--random.py6
-rw-r--r--test/option-n.py56
-rw-r--r--test/option-v.py2
-rw-r--r--test/option/debug-action-timestamps.py1
-rw-r--r--test/option/debug-count.py5
-rw-r--r--test/option/debug-multiple.py6
-rw-r--r--test/option/debug-time.py1
-rw-r--r--test/option/help-options.py5
-rw-r--r--test/packaging/convenience-functions/image/SConstruct2
-rw-r--r--test/packaging/use-builddir.py15
-rw-r--r--test/question/Configure.py4
-rw-r--r--test/scons-time/run/config/python.py6
-rw-r--r--test/scons-time/run/config/scons.py5
-rw-r--r--test/sconsign/script/Configure.py6
-rw-r--r--test/site_scons/sysdirs.py11
-rw-r--r--test/srcchange.py8
-rw-r--r--test/textfile/fixture/SConstruct22
-rw-r--r--test/textfile/fixture/SConstruct.225
-rw-r--r--test/textfile/fixture/SConstruct.issue-355012
-rw-r--r--test/textfile/fixture/foo-3550.in1
-rw-r--r--test/textfile/issue-3550.py44
-rw-r--r--test/textfile/textfile.py (renamed from test/textfile.py)78
-rw-r--r--test/update-release-info/update-release-info.py184
-rw-r--r--testing/framework/TestCmd.py56
-rw-r--r--testing/framework/TestCmdTests.py20
-rw-r--r--testing/framework/TestCommon.py2
-rw-r--r--testing/framework/TestCommonTests.py55
-rw-r--r--testing/framework/TestSCons.py532
-rw-r--r--testing/framework/TestSCons_time.py1
-rw-r--r--testing/framework/TestSConsign.py1
-rw-r--r--testing/framework/test-framework.rst3
295 files changed, 3855 insertions, 2846 deletions
diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index 9daae32..486f170 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,5 +1,5 @@
# These are supported funding model platforms
-github: bdbaddog
+github: [bdbaddog, mwichmann]
patreon: bdbaddog
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index e249a70..41c04f7 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -9,6 +9,7 @@ assignees: ''
## Please bring your issue to the SCons users mailing list before filing an issue here
## See: https://scons.org/bugs.html
+## or join our Discord server : https://discord.gg/bXVpWAy
**Describe the bug**
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 14f8e7e..5db5bea 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -9,6 +9,7 @@ assignees: ''
## Please bring your feature request to the SCons users mailing list before filing an issue here
## See: https://scons.org/bugs.html
+## or join our Discord server : https://discord.gg/bXVpWAy
**Describe the Feature**
diff --git a/.travis.yml b/.travis.yml
index 985a544..b941f4c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -19,13 +19,6 @@ install:
# do the rest of the image setup
- ./.travis/install.sh
-# pypy is not passing atm, but still report build success for now
-# allow coverage to fail, so we can still do testing for all platforms
-matrix:
- allow_failures:
- - python: pypy3
- - stage: Coverage
-
# run coverage first as its still useful to collect
stages:
- Coverage
@@ -43,6 +36,12 @@ stages:
# apparently not guaranteed.
jobs:
+
+ # pypy is not passing atm, but still report build success for now
+ # allow coverage to fail, so we can still do testing for all platforms
+ allow_failures:
+ - python: pypy3
+ - stage: Coverage
include:
- &test_job
stage: Test
@@ -53,29 +52,24 @@ jobs:
env:
- PYVER=pypy3
- PYTHON=pypy3
- sudo: required
-
- <<: *test_job
python: 3.5
env:
- PYVER=35
- PYTHON=3.5
- sudo: required
- <<: *test_job
python: 3.6
env:
- PYVER=36
- PYTHON=3.6
- sudo: required
- <<: *test_job
python: 3.7
env:
- PYVER=37
- PYTHON=3.7
- sudo: required
dist: xenial # required for Python >= 3.7
- <<: *test_job
@@ -83,7 +77,6 @@ jobs:
env:
- PYVER=38
- PYTHON=3.8
- sudo: required
dist: bionic # required for Python >= 3.8
diff --git a/LICENSE b/LICENSE
index 67e0e2f..9a7749b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2001 - 2019 The SCons Foundation
+Copyright (c) 2001 - 2020 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/README-SF.rst b/README-SF.rst
index 0c66bb3..d8da15d 100755
--- a/README-SF.rst
+++ b/README-SF.rst
@@ -683,11 +683,6 @@ Subscription to the developer's mailing list is by approval. In practice, no
one is refused list membership, but we reserve the right to limit membership
in the future and/or weed out lurkers.
-There is also a low-volume mailing list available for announcements about
-SCons. Subscribe by sending email to:
-
- announce-subscribe@scons.tigris.org
-
There are other mailing lists available for SCons users, for notification of
SCons code changes, and for notification of updated bug reports and project
documents. Please see our mailing lists page for details.
@@ -733,8 +728,9 @@ many contributors, including but not at all limited to:
- Anatoly Techtonik
- Christoph Wiedemann
- Russel Winder
+- Mats Wichmann
\... and many others.
-Copyright (c) 2001 - 2019 The SCons Foundation
+Copyright (c) 2001 - 2020 The SCons Foundation
diff --git a/README-local b/README-local
index 314d735..3be108c 100644
--- a/README-local
+++ b/README-local
@@ -38,7 +38,7 @@ LATEST VERSION
Before going further, you can check for the latest version of the
scons-local package, or any SCons package, at the SCons download page:
- http://www.scons.org/download.html
+ https://scons.org/pages/download.html
EXECUTION REQUIREMENTS
@@ -202,11 +202,6 @@ Subscription to the developer's mailing list is by approval. In practice, no
one is refused list membership, but we reserve the right to limit membership
in the future and/or weed out lurkers.
-There is also a low-volume mailing list available for announcements about
-SCons. Subscribe by sending email to:
-
- announce-subscribe@scons.tigris.org
-
There are other mailing lists available for SCons users, for notification of
SCons code changes, and for notification of updated bug reports and project
documents. Please see our mailing lists page for details.
@@ -221,18 +216,28 @@ Check the SCons web site at:
http://www.scons.org/
-AUTHOR INFO
+Author Info
===========
-Steven Knight
-knight at baldmt dot com
-http://www.baldmt.com/~knight/
-
-With plenty of help from the SCons Development team:
- Chad Austin
- Charles Crain
- Steve Leblanc
- Anthony Roach
- Terrel Shumway
-
-
+SCons was originally written by Steven Knight, knight at baldmt dot com.
+Since around 2010 it has been maintained by the SCons
+development team, co-managed by Bill Deegan and Gary Oberbrunner, with
+many contributors, including but not at all limited to:
+
+- Chad Austin
+- Dirk Baechle
+- Charles Crain
+- William Deegan
+- Steve Leblanc
+- Rob Managan
+- Greg Noel
+- Gary Oberbrunner
+- Anthony Roach
+- Greg Spencer
+- Tom Tanner
+- Anatoly Techtonik
+- Christoph Wiedemann
+- Russel Winder
+- Mats Wichmann
+
+\... and many others. \ No newline at end of file
diff --git a/README.rst b/README.rst
index 2954904..e77d2d2 100755
--- a/README.rst
+++ b/README.rst
@@ -707,11 +707,6 @@ Subscription to the developer's mailing list is by approval. In practice, no
one is refused list membership, but we reserve the right to limit membership
in the future and/or weed out lurkers.
-There is also a low-volume mailing list available for announcements about
-SCons. Subscribe by sending email to:
-
- announce-subscribe@scons.tigris.org
-
There are other mailing lists available for SCons users, for notification of
SCons code changes, and for notification of updated bug reports and project
documents. Please see our mailing lists page for details.
@@ -757,8 +752,9 @@ many contributors, including but not at all limited to:
- Anatoly Techtonik
- Christoph Wiedemann
- Russel Winder
+- Mats Wichmann
\... and many others.
-Copyright (c) 2001 - 2019 The SCons Foundation
+Copyright (c) 2001 - 2020 The SCons Foundation
diff --git a/ReleaseConfig b/ReleaseConfig
index 818b405..64de640 100755
--- a/ReleaseConfig
+++ b/ReleaseConfig
@@ -32,7 +32,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
# 'final', the patchlevel is set to the release date. This value is
# mandatory and must be present in this file.
#version_tuple = (2, 2, 0, 'final', 0)
-version_tuple = (3, 1, 3, 'alpha', 0)
+version_tuple = (3, 1, 3, 'dev', 0)
# Python versions prior to unsupported_python_version cause a fatal error
# when that version is used. Python versions prior to deprecate_python_version
@@ -51,7 +51,7 @@ deprecated_python_version = (2, 7, 0)
#month_year = 'December 2012'
# If copyright years is not given, the release year is used as the end.
-copyright_years = '2001 - 2019'
+copyright_years = '2001 - 2020'
# Local Variables:
# tab-width:4
diff --git a/SConstruct b/SConstruct
index 1adf714..23797da 100644
--- a/SConstruct
+++ b/SConstruct
@@ -3,8 +3,6 @@
#
# See the README.rst file for an overview of how SCons is built and tested.
-from __future__ import print_function
-
copyright_years = '2001 - 2019'
# This gets inserted into the man pages to reflect the month of release.
diff --git a/bin/calibrate.py b/bin/calibrate.py
index be06a54..d18cfcd 100644
--- a/bin/calibrate.py
+++ b/bin/calibrate.py
@@ -20,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.
-from __future__ import division, print_function
-
import optparse
import os
import re
@@ -31,6 +29,7 @@ import sys
variable_re = re.compile(r'^VARIABLE: (.*)$', re.M)
elapsed_re = re.compile(r'^ELAPSED: (.*)$', re.M)
+
def main(argv=None):
if argv is None:
argv = sys.argv
@@ -84,5 +83,6 @@ def main(argv=None):
return 0
+
if __name__ == "__main__":
sys.exit(main())
diff --git a/bin/import-test.py b/bin/import-test.py
index 65b6e79..6a71a37 100644
--- a/bin/import-test.py
+++ b/bin/import-test.py
@@ -82,7 +82,7 @@ def print_files(dir):
for dirpath, dirnames, filenames in os.walk(directory):
dir = lookup(dirpath)
- for f in fnames:
+ for f in filenames:
dir.entries[f] = None
subdir_list = []
diff --git a/bin/install_scons.py b/bin/install_scons.py
index ac79fd3..ed919f8 100644
--- a/bin/install_scons.py
+++ b/bin/install_scons.py
@@ -25,7 +25,7 @@ import os
import shutil
import sys
import tarfile
-from urllib import urlretrieve
+from urllib.request import urlretrieve
from Command import CommandRunner, Usage
diff --git a/bin/update-release-info.py b/bin/update-release-info.py
index fa7a5f8..3fcdf72 100644
--- a/bin/update-release-info.py
+++ b/bin/update-release-info.py
@@ -9,7 +9,7 @@ It takes one parameter that says what the mode of update should be, which
may be one of 'develop', 'release', or 'post'.
In 'develop' mode, which is what someone would use as part of their own
-development practices, the release type is forced to be 'alpha' and the
+development practices, the release type is forced to be 'dev' and the
patch level is the string 'yyyymmdd'. Otherwise, it's the same as the
'release' mode.
@@ -30,7 +30,7 @@ in various files:
In 'post' mode, files are prepared for the next release cycle:
- In ReleaseConfig, the version tuple is updated for the next release
by incrementing the release number (either minor or micro, depending
- on the branch) and resetting release type to 'alpha'.
+ on the branch) and resetting release type to 'dev'.
- A blank template replaces src/RELEASE.txt.
- A new section to accumulate changes is added to src/CHANGES.txt and
src/Announce.txt.
@@ -56,100 +56,151 @@ In 'post' mode, files are prepared for the next release cycle:
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
import sys
import time
import re
+import argparse
DEBUG = os.environ.get('DEBUG', 0)
-# Evaluate parameter
-if len(sys.argv) < 2:
- mode = 'develop'
-else:
- mode = sys.argv[1]
- if mode not in ['develop', 'release', 'post']:
- print(("""ERROR: `%s' as a parameter is invalid; it must be one of
-\tdevelop, release, or post. The default is develop.""" % mode))
- sys.exit(1)
-
-# Get configuration information
-
-config = dict()
-with open('ReleaseConfig') as f:
- releaseconfig = f.read()
-exec(releaseconfig, globals(), config)
-
-
-try:
- version_tuple = config['version_tuple']
- unsupported_version = config['unsupported_python_version']
- deprecated_version = config['deprecated_python_version']
-except KeyError:
- print('''ERROR: Config file must contain at least version_tuple,
+class ReleaseInfo(object):
+ def __init__(self, args):
+ self.config = {}
+ self.args = args
+ self.release_date = time.localtime()[:6]
+
+ self.unsupported_version = None
+ self.deprecated_version = None
+
+ # version_tuple = (3, 1, 3, 'alpha', 0)
+ self.version_tuple = (-1, -1, -1, 'not_set', -1)
+
+ self.version_string = "UNSET"
+ self.version_type = 'UNSET'
+ self.month_year = 'UNSET'
+ self.copyright_years = 'UNSET'
+ self.new_date = 'NEW DATE WILL BE INSERTED HERE'
+
+ self.read_config()
+ self.process_config()
+ if not self.args.timestamp:
+ self.set_new_date()
+
+ def read_config(self):
+ # Get configuration information
+
+ config = dict()
+ with open('ReleaseConfig') as f:
+ release_config = f.read()
+ exec(release_config, globals(), config)
+
+ self.config = config
+
+ def process_config(self):
+ """
+ Process and validate the config info loaded from ReleaseConfig file
+ """
+
+ try:
+ self.version_tuple = self.config['version_tuple']
+ self.unsupported_version = self.config['unsupported_python_version']
+ self.deprecated_version = self.config['deprecated_python_version']
+ except KeyError:
+ print('''ERROR: Config file must contain at least version_tuple,
\tunsupported_python_version, and deprecated_python_version.''')
- sys.exit(1)
-if DEBUG: print('version tuple', version_tuple)
-if DEBUG: print('unsupported Python version', unsupported_version)
-if DEBUG: print('deprecated Python version', deprecated_version)
-
-try:
- release_date = config['release_date']
-except KeyError:
- release_date = time.localtime()[:6]
-else:
- if len(release_date) == 3:
- release_date = release_date + time.localtime()[3:6]
- if len(release_date) != 6:
- print('''ERROR: Invalid release date''', release_date)
- sys.exit(1)
-if DEBUG: print('release date', release_date)
-
-if mode == 'develop' and version_tuple[3] != 'alpha':
- version_tuple == version_tuple[:3] + ('alpha', 0)
-if len(version_tuple) > 3 and version_tuple[3] != 'final':
- if mode == 'develop':
- version_tuple = version_tuple[:4] + ('yyyymmdd',)
- else:
- yyyy,mm,dd,_,_,_ = release_date
- version_tuple = version_tuple[:4] + ((yyyy*100 + mm)*100 + dd,)
-version_string = '.'.join(map(str, version_tuple))
-if len(version_tuple) > 3:
- version_type = version_tuple[3]
-else:
- version_type = 'final'
-if DEBUG: print('version string', version_string)
-
-if version_type not in ['alpha', 'beta', 'candidate', 'final']:
- print(("""ERROR: `%s' is not a valid release type in version tuple;
-\tit must be one of alpha, beta, candidate, or final""" % version_type))
- sys.exit(1)
-
-try:
- month_year = config['month_year']
-except KeyError:
- if version_type == 'alpha':
- month_year = 'MONTH YEAR'
- else:
- month_year = time.strftime('%B %Y', release_date + (0,0,0))
-if DEBUG: print('month year', month_year)
-
-try:
- copyright_years = config['copyright_years']
-except KeyError:
- copyright_years = '2001 - %d'%(release_date[0] + 1)
-if DEBUG: print('copyright years', copyright_years)
+ sys.exit(1)
+
+ if 'release_date' in self.config:
+ self.release_date = self.config['release_date']
+ if len(self.release_date) == 3:
+ self.release_date = self.release_date + time.localtime()[3:6]
+ if len(self.release_date) != 6:
+ print('''ERROR: Invalid release date''', self.release_date)
+ sys.exit(1)
+
+ yyyy, mm, dd, h, m, s = self.release_date
+ date_string = "".join(["%.2d" % d for d in self.release_date])
+
+ if self.args.timestamp:
+ date_string = self.args.timestamp
+
+ if self.args.mode == 'develop' and self.version_tuple[3] != 'dev':
+ self.version_tuple == self.version_tuple[:3] + ('dev', 0)
+
+ if len(self.version_tuple) > 3 and self.version_tuple[3] != 'final':
+ self.version_tuple = self.version_tuple[:4] + (date_string,)
+
+ self.version_string = '.'.join(map(str, self.version_tuple[:4])) + date_string
+
+ if len(self.version_tuple) > 3:
+ self.version_type = self.version_tuple[3]
+ else:
+ self.version_type = 'final'
+
+ if self.version_type not in ['dev', 'beta', 'candidate', 'final']:
+ print(("""ERROR: `%s' is not a valid release type in version tuple;
+\tit must be one of dev, beta, candidate, or final""" % self.version_type))
+ sys.exit(1)
+
+ try:
+ self.month_year = self.config['month_year']
+ except KeyError:
+ if self.args.timestamp:
+ self.month_year = "MONTH YEAR"
+ else:
+ self.month_year = time.strftime('%B %Y', self.release_date + (0, 0, 0))
+
+ try:
+ self.copyright_years = self.config['copyright_years']
+ except KeyError:
+ self.copyright_years = '2001 - %d' % (self.release_date[0] + 1)
+
+ if DEBUG:
+ print('version tuple', self.version_tuple)
+ print('unsupported Python version', self.unsupported_version)
+ print('deprecated Python version', self.deprecated_version)
+ print('release date', self.release_date)
+ print('version string', self.version_string)
+ print('month year', self.month_year)
+ print('copyright years', self.copyright_years)
+
+ def set_new_date(self):
+ """
+ Determine the release date and the pattern to match a date
+ Mon, 05 Jun 2010 21:17:15 -0700
+ NEW DATE WILL BE INSERTED HERE
+ """
+ min = (time.daylight and time.altzone or time.timezone) // 60
+ hr = min // 60
+ min = -(min % 60 + hr * 100)
+ self.new_date = (time.strftime('%a, %d %b %Y %X', self.release_date + (0, 0, 0))
+ + ' %+.4d' % min)
+
class UpdateFile(object):
""" XXX """
- def __init__(self, file, orig = None):
- if orig is None: orig = file
+ rel_info = None
+ mode = 'develop'
+ _days = r'(Sun|Mon|Tue|Wed|Thu|Fri|Sat)'
+ _months = r'(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oce|Nov|Dec)'
+ match_date = r''.join([_days, r', \d\d ', _months, r' \d\d\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d'])
+ match_date = re.compile(match_date)
+
+ # Determine the pattern to match a version
+
+ _rel_types = r'(dev|beta|candidate|final)'
+ match_pat = r'\d+\.\d+\.\d+\.' + _rel_types + r'\.?(\d+|yyyymmdd)'
+ match_rel = re.compile(match_pat)
+
+ def __init__(self, file, orig=None):
+ if orig is None:
+ orig = file
+
try:
with open(orig, 'r') as f:
self.content = f.read()
@@ -166,45 +217,21 @@ class UpdateFile(object):
# pretend file changed
self.orig = ''
- def sub(self, pattern, replacement, count = 1):
+ def sub(self, pattern, replacement, count=1):
""" XXX """
self.content = re.sub(pattern, replacement, self.content, count)
- def replace_assign(self, name, replacement, count = 1):
+ def replace_assign(self, name, replacement, count=1):
""" XXX """
self.sub('\n' + name + ' = .*', '\n' + name + ' = ' + replacement)
- # Determine the pattern to match a version
-
- _rel_types = r'(alpha|beta|candidate|final)'
- match_pat = r'\d+\.\d+\.\d+\.' + _rel_types + r'\.(\d+|yyyymmdd)'
- match_rel = re.compile(match_pat)
-
- def replace_version(self, replacement = version_string, count = 1):
+ def replace_version(self, count=1):
""" XXX """
- self.content = self.match_rel.sub(replacement, self.content, count)
-
- # Determine the release date and the pattern to match a date
- # Mon, 05 Jun 2010 21:17:15 -0700
- # NEW DATE WILL BE INSERTED HERE
-
- if mode == 'develop':
- new_date = 'NEW DATE WILL BE INSERTED HERE'
- else:
- min = (time.daylight and time.altzone or time.timezone)//60
- hr = min // 60
- min = -(min % 60 + hr * 100)
- new_date = (time.strftime('%a, %d %b %Y %X', release_date + (0,0,0))
- + ' %+.4d' % min)
-
- _days = r'(Sun|Mon|Tue|Wed|Thu|Fri|Sat)'
- _months = r'(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oce|Nov|Dec)'
- match_date = r''.join([_days, r', \d\d ', _months, r' \d\d\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d'])
- match_date = re.compile(match_date)
+ self.content = self.match_rel.sub(rel_info.version_string, self.content, count)
- def replace_date(self, replacement = new_date, count = 1):
+ def replace_date(self, count=1):
""" XXX """
- self.content = self.match_date.sub(replacement, self.content, count)
+ self.content = self.match_date.sub(rel_info.new_date, self.content, count)
def __del__(self):
""" XXX """
@@ -213,135 +240,160 @@ class UpdateFile(object):
with open(self.file, 'w') as f:
f.write(self.content)
-if mode == 'post':
- # Set up for the next release series.
- if version_tuple[2]:
- # micro release, increment micro value
- minor = version_tuple[1]
- micro = version_tuple[2] + 1
- else:
- # minor release, increment minor value
- minor = version_tuple[1] + 1
- micro = 0
- new_tuple = (version_tuple[0], minor, micro, 'alpha', 0)
- new_version = '.'.join(map(str, new_tuple[:4])) + '.yyyymmdd'
+def main(args, rel_info):
+ if args.mode == 'post':
+ # Set up for the next release series.
+
+ if rel_info.version_tuple[2]:
+ # micro release, increment micro value
+ minor = rel_info.version_tuple[1]
+ micro = rel_info.version_tuple[2] + 1
+ else:
+ # minor release, increment minor value
+ minor = rel_info.version_tuple[1] + 1
+ micro = 0
+ new_tuple = (rel_info.version_tuple[0], minor, micro, 'dev', 0)
+ new_version = '.'.join(map(str, new_tuple[:4])) + 'yyyymmdd'
+
+ rel_info.version_string = new_version
+
+ # Update ReleaseConfig
+
+ t = UpdateFile('ReleaseConfig')
+ if DEBUG: t.file = '/tmp/ReleaseConfig'
+ t.replace_assign('version_tuple', str(new_tuple))
+
+ # Update src/CHANGES.txt
- # Update ReleaseConfig
+ t = UpdateFile(os.path.join('src', 'CHANGES.txt'))
+ if DEBUG: t.file = '/tmp/CHANGES.txt'
+ t.sub('(\nRELEASE .*)', r"""\nRELEASE VERSION/DATE TO BE FILLED IN LATER\n
+ From John Doe:\n
+ - Whatever John Doe did.\n
+ \1""")
- t = UpdateFile('ReleaseConfig')
- if DEBUG: t.file = '/tmp/ReleaseConfig'
- t.replace_assign('version_tuple', str(new_tuple))
+ # Update src/RELEASE.txt
+
+ t = UpdateFile(os.path.join('src', 'RELEASE.txt'),
+ os.path.join('template', 'RELEASE.txt'))
+ if DEBUG: t.file = '/tmp/RELEASE.txt'
+ t.replace_version()
+
+ # Update src/Announce.txt
+
+ t = UpdateFile(os.path.join('src', 'Announce.txt'))
+ if DEBUG: t.file = '/tmp/Announce.txt'
+ t.sub('\nRELEASE .*', '\nRELEASE VERSION/DATE TO BE FILLED IN LATER')
+ announce_pattern = """(
+ Please note the following important changes scheduled for the next
+ release:
+ )"""
+ announce_replace = (r"""\1
+ -- FEATURE THAT WILL CHANGE\n
+ Please note the following important changes since release """
+ + '.'.join(map(str, rel_info.version_tuple[:3])) + ':\n')
+ t.sub(announce_pattern, announce_replace)
+
+ # Write out the last update and exit
+
+ t = None
+ sys.exit()
# Update src/CHANGES.txt
t = UpdateFile(os.path.join('src', 'CHANGES.txt'))
if DEBUG: t.file = '/tmp/CHANGES.txt'
- t.sub('(\nRELEASE .*)', r"""\nRELEASE VERSION/DATE TO BE FILLED IN LATER\n
- From John Doe:\n
- - Whatever John Doe did.\n
-\1""")
+ t.sub('\nRELEASE .*', '\nRELEASE ' + rel_info.version_string + ' - ' + rel_info.new_date)
# Update src/RELEASE.txt
- t = UpdateFile(os.path.join('src', 'RELEASE.txt'),
- os.path.join('template', 'RELEASE.txt'))
+ t = UpdateFile(os.path.join('src', 'RELEASE.txt'))
if DEBUG: t.file = '/tmp/RELEASE.txt'
- t.replace_version(new_version)
+ t.replace_version()
# Update src/Announce.txt
t = UpdateFile(os.path.join('src', 'Announce.txt'))
if DEBUG: t.file = '/tmp/Announce.txt'
- t.sub('\nRELEASE .*', '\nRELEASE VERSION/DATE TO BE FILLED IN LATER')
- announce_pattern = """(
- Please note the following important changes scheduled for the next
- release:
-)"""
- announce_replace = (r"""\1
- -- FEATURE THAT WILL CHANGE\n
- Please note the following important changes since release """
- + '.'.join(map(str, version_tuple[:3])) + ':\n')
- t.sub(announce_pattern, announce_replace)
-
- # Write out the last update and exit
-
- t = None
- sys.exit()
+ t.sub('\nRELEASE .*', '\nRELEASE ' + rel_info.version_string + ' - ' + rel_info.new_date)
-# Update src/CHANGES.txt
+ # Update SConstruct
-t = UpdateFile(os.path.join('src', 'CHANGES.txt'))
-if DEBUG: t.file = '/tmp/CHANGES.txt'
-t.sub('\nRELEASE .*', '\nRELEASE ' + version_string + ' - ' + t.new_date)
+ t = UpdateFile('SConstruct')
+ if DEBUG: t.file = '/tmp/SConstruct'
+ t.replace_assign('month_year', repr(rel_info.month_year))
+ t.replace_assign('copyright_years', repr(rel_info.copyright_years))
+ t.replace_assign('default_version', repr(rel_info.version_string))
-# Update src/RELEASE.txt
+ # Update README
-t = UpdateFile(os.path.join('src', 'RELEASE.txt'))
-if DEBUG: t.file = '/tmp/RELEASE.txt'
-t.replace_version()
+ t = UpdateFile('README.rst')
+ if DEBUG: t.file = '/tmp/README.rst'
+ t.sub('-' + t.match_pat + r'\.', '-' + rel_info.version_string + '.', count=0)
+ for suf in ['tar', 'win32', 'zip', 'rpm', 'exe', 'deb']:
+ t.sub(r'-(\d+\.\d+\.\d+)\.%s' % suf,
+ '-%s.%s' % (rel_info.version_string, suf),
+ count=0)
-# Update src/Announce.txt
+ # Update testing/framework/TestSCons.py
-t = UpdateFile(os.path.join('src', 'Announce.txt'))
-if DEBUG: t.file = '/tmp/Announce.txt'
-t.sub('\nRELEASE .*', '\nRELEASE ' + version_string + ' - ' + t.new_date)
+ t = UpdateFile(os.path.join('testing', 'framework', 'TestSCons.py'))
+ if DEBUG: t.file = '/tmp/TestSCons.py'
+ t.replace_assign('copyright_years', repr(rel_info.copyright_years))
+ t.replace_assign('default_version', repr(rel_info.version_string))
+ # ??? t.replace_assign('SConsVersion', repr(version_string))
+ t.replace_assign('python_version_unsupported', str(rel_info.unsupported_version))
+ t.replace_assign('python_version_deprecated', str(rel_info.deprecated_version))
+ # Update Script/Main.py
-# Update SConstruct
+ t = UpdateFile(os.path.join('src', 'engine', 'SCons', 'Script', 'Main.py'))
+ if DEBUG: t.file = '/tmp/Main.py'
+ t.replace_assign('unsupported_python_version', str(rel_info.unsupported_version))
+ t.replace_assign('deprecated_python_version', str(rel_info.deprecated_version))
-t = UpdateFile('SConstruct')
-if DEBUG: t.file = '/tmp/SConstruct'
-t.replace_assign('month_year', repr(month_year))
-t.replace_assign('copyright_years', repr(copyright_years))
-t.replace_assign('default_version', repr(version_string))
+ # Update doc/user/main.{in,xml}
-# Update README
+ docyears = '2004 - %d' % rel_info.release_date[0]
+ if os.path.exists(os.path.join('doc', 'user', 'main.in')):
+ # this is no longer used as of Dec 2013
+ t = UpdateFile(os.path.join('doc', 'user', 'main.in'))
+ if DEBUG: t.file = '/tmp/main.in'
+ ## TODO debug these
+ # t.sub('<pubdate>[^<]*</pubdate>', '<pubdate>' + docyears + '</pubdate>')
+ # t.sub('<year>[^<]*</year>', '<year>' + docyears + '</year>')
-t = UpdateFile('README.rst')
-if DEBUG: t.file = '/tmp/README.rst'
-t.sub('-' + t.match_pat + r'\.', '-' + version_string + '.', count = 0)
-for suf in ['tar', 'win32', 'zip', 'rpm', 'exe', 'deb']:
- t.sub(r'-(\d+\.\d+\.\d+)\.%s' % suf,
- '-%s.%s' % (version_string, suf),
- count = 0)
+ t = UpdateFile(os.path.join('doc', 'user', 'main.xml'))
+ if DEBUG: t.file = '/tmp/main.xml'
+ t.sub('<pubdate>[^<]*</pubdate>', '<pubdate>' + docyears + '</pubdate>')
+ t.sub('<year>[^<]*</year>', '<year>' + docyears + '</year>')
-# Update testing/framework/TestSCons.py
+ # Write out the last update
-t = UpdateFile(os.path.join('testing','framework', 'TestSCons.py'))
-if DEBUG: t.file = '/tmp/TestSCons.py'
-t.replace_assign('copyright_years', repr(copyright_years))
-t.replace_assign('default_version', repr(version_string))
-#??? t.replace_assign('SConsVersion', repr(version_string))
-t.replace_assign('python_version_unsupported', str(unsupported_version))
-t.replace_assign('python_version_deprecated', str(deprecated_version))
+ t = None
-# Update Script/Main.py
-t = UpdateFile(os.path.join('src', 'engine', 'SCons', 'Script', 'Main.py'))
-if DEBUG: t.file = '/tmp/Main.py'
-t.replace_assign('unsupported_python_version', str(unsupported_version))
-t.replace_assign('deprecated_python_version', str(deprecated_version))
+def parse_arguments():
+ """
+ Create ArgumentParser object and process arguments
+ """
-# Update doc/user/main.{in,xml}
+ parser = argparse.ArgumentParser(prog='update-release-info.py')
+ parser.add_argument('mode', nargs='?', choices=['develop', 'release', 'post'], default='develop')
+ parser.add_argument('--verbose', dest='verbose', action='store_true', help='Enable verbose logging')
-docyears = '2004 - %d' % release_date[0]
-if os.path.exists(os.path.join('doc', 'user', 'main.in')):
- # this is no longer used as of Dec 2013
- t = UpdateFile(os.path.join('doc', 'user', 'main.in'))
- if DEBUG: t.file = '/tmp/main.in'
- ## TODO debug these
- #t.sub('<pubdate>[^<]*</pubdate>', '<pubdate>' + docyears + '</pubdate>')
- #t.sub('<year>[^<]*</year>', '<year>' + docyears + '</year>')
+ parser.add_argument('--timestamp', dest='timestamp', help='Override the default current timestamp')
-t = UpdateFile(os.path.join('doc', 'user', 'main.xml'))
-if DEBUG: t.file = '/tmp/main.xml'
-t.sub('<pubdate>[^<]*</pubdate>', '<pubdate>' + docyears + '</pubdate>')
-t.sub('<year>[^<]*</year>', '<year>' + docyears + '</year>')
+ args = parser.parse_args()
+ return args
-# Write out the last update
-t = None
+if __name__ == "__main__":
+ options = parse_arguments()
+ rel_info = ReleaseInfo(options)
+ UpdateFile.rel_info = rel_info
+ main(options, rel_info)
# Local Variables:
# tab-width:4
diff --git a/bootstrap.py b/bootstrap.py
index 4ade361..d47c966 100755
--- a/bootstrap.py
+++ b/bootstrap.py
@@ -20,18 +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.
-#
-from __future__ import print_function
-
-import os
-import os.path
-import sys
-import glob
-import subprocess
-import filecmp
-import shutil
-__doc__ = """bootstrap.py
+"""bootstrap.py
Execute SCons from this source tree. It copies Python scripts and modules
from src/ subdirectory into a subdirectory named "bootstrap/" (by default),
@@ -75,6 +65,14 @@ the following SCons options:
"eaten" by the bootstrap.py script.
"""
+import os
+import os.path
+import sys
+import glob
+import subprocess
+import filecmp
+import shutil
+
def parseManifestLines(basedir, manifest):
"""
Scans a MANIFEST file, and returns the list of source files.
diff --git a/doc/SConscript b/doc/SConscript
index ff29a70..8f6d1cd 100644
--- a/doc/SConscript
+++ b/doc/SConscript
@@ -24,8 +24,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.
-from __future__ import print_function
-
import os.path
import re
import sys
@@ -90,7 +88,8 @@ def writeVersionXml(verfile, date, ver, rev):
os.makedirs(dir)
except OSError:
pass # okay if the directory already exists
- open(verfile, "w").write("""<!--
+ with open(verfile, "w") as vf:
+ vf.write("""<!--
THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
-->
<!ENTITY builddate "%s">
@@ -105,7 +104,7 @@ man_page_list = ['scons.1','scons-time.1','sconsign.1']
# Template for the MAN page texts when we can't properly
# create them because the skip_doc flag is set (required
# modules/tools aren't installed in the current system)
-man_replace_tpl = """.TH "%(uctitle)s" "1" "%(today)s" "SCons %(version)s" "SCons %(version)s"
+man_replace_tpl = r""".TH "%(uctitle)s" "1" "%(today)s" "SCons %(version)s" "SCons %(version)s"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.nh
diff --git a/doc/design/engine.xml b/doc/design/engine.xml
index 39289f9..6b8b2a6 100644
--- a/doc/design/engine.xml
+++ b/doc/design/engine.xml
@@ -1104,13 +1104,13 @@ you set it up with another environment...
</para>
<programlisting>
- env.Dependency(target = 'output1', dependency = 'input_1 input_2')
- env.Dependency(target = 'output2', dependency = ['input_1', 'input_2'])
- env.Dependency(target = 'output3', dependency = ['white space input'])
+ env.Depends(target = 'output1', dependency = 'input_1 input_2')
+ env.Depends(target = 'output2', dependency = ['input_1', 'input_2'])
+ env.Depends(target = 'output3', dependency = ['white space input'])
- env.Dependency(target = 'output_a output_b', dependency = 'input_3')
- env.Dependency(target = ['output_c', 'output_d'], dependency = 'input_4')
- env.Dependency(target = ['white space output'], dependency = 'input_5')
+ env.Depends(target = 'output_a output_b', dependency = 'input_3')
+ env.Depends(target = ['output_c', 'output_d'], dependency = 'input_4')
+ env.Depends(target = ['white space output'], dependency = 'input_5')
</programlisting>
<para>
@@ -1129,7 +1129,7 @@ you set it up with another environment...
</para>
<programlisting>
- env.Dependency(target = 'archive.tar.gz', dependency = 'SConstruct')
+ env.Depends(target = 'archive.tar.gz', dependency = 'SConstruct')
</programlisting>
</section>
diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen
index 9050832..21e0b1f 100644
--- a/doc/generated/variables.gen
+++ b/doc/generated/variables.gen
@@ -3448,17 +3448,6 @@ If this is not set, then <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="
</para>
</listitem>
</varlistentry>
- <varlistentry id="cv-LDMODULEEMITTER">
- <term>LDMODULEEMITTER</term>
- <listitem>
-<para xmlns="http://www.scons.org/dbxsd/v1.0">
-Contains the emitter specification for the
-<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="b-LoadableModule"><function>LoadableModule</function></link> builder.
-The manpage section "Builder Objects" contains
-general information on specifying emitters.
-</para>
-</listitem>
- </varlistentry>
<varlistentry id="cv-LDMODULEFLAGS">
<term>LDMODULEFLAGS</term>
<listitem>
diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod
index ba92aa9..ff44a23 100644
--- a/doc/generated/variables.mod
+++ b/doc/generated/variables.mod
@@ -65,6 +65,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
<!ENTITY cv-CXXVERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$CXXVERSION</envar>">
<!ENTITY cv-DC "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$DC</envar>">
<!ENTITY cv-DCOM "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$DCOM</envar>">
+<!ENTITY cv-DCOMSTR "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$DCOMSTR</envar>">
<!ENTITY cv-DDEBUG "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$DDEBUG</envar>">
<!ENTITY cv-DDEBUGPREFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$DDEBUGPREFIX</envar>">
<!ENTITY cv-DDEBUGSUFFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$DDEBUGSUFFIX</envar>">
@@ -457,6 +458,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
<!ENTITY cv-SHCXXFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHCXXFLAGS</envar>">
<!ENTITY cv-SHDC "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHDC</envar>">
<!ENTITY cv-SHDCOM "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHDCOM</envar>">
+<!ENTITY cv-SHDCOMSTR "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHDCOMSTR</envar>">
<!ENTITY cv-SHDLIBVERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHDLIBVERSION</envar>">
<!ENTITY cv-SHDLIBVERSIONFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHDLIBVERSIONFLAGS</envar>">
<!ENTITY cv-SHDLINK "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHDLINK</envar>">
@@ -706,6 +708,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
<!ENTITY cv-link-CXXVERSION "<link linkend='cv-CXXVERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$CXXVERSION</envar></link>">
<!ENTITY cv-link-DC "<link linkend='cv-DC' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$DC</envar></link>">
<!ENTITY cv-link-DCOM "<link linkend='cv-DCOM' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$DCOM</envar></link>">
+<!ENTITY cv-link-DCOMSTR "<link linkend='cv-DCOMSTR' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$DCOMSTR</envar></link>">
<!ENTITY cv-link-DDEBUG "<link linkend='cv-DDEBUG' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$DDEBUG</envar></link>">
<!ENTITY cv-link-DDEBUGPREFIX "<link linkend='cv-DDEBUGPREFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$DDEBUGPREFIX</envar></link>">
<!ENTITY cv-link-DDEBUGSUFFIX "<link linkend='cv-DDEBUGSUFFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$DDEBUGSUFFIX</envar></link>">
@@ -1098,6 +1101,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT.
<!ENTITY cv-link-SHCXXFLAGS "<link linkend='cv-SHCXXFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHCXXFLAGS</envar></link>">
<!ENTITY cv-link-SHDC "<link linkend='cv-SHDC' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHDC</envar></link>">
<!ENTITY cv-link-SHDCOM "<link linkend='cv-SHDCOM' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHDCOM</envar></link>">
+<!ENTITY cv-link-SHDCOMSTR "<link linkend='cv-SHDCOMSTR' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHDCOMSTR</envar></link>">
<!ENTITY cv-link-SHDLIBVERSION "<link linkend='cv-SHDLIBVERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHDLIBVERSION</envar></link>">
<!ENTITY cv-link-SHDLIBVERSIONFLAGS "<link linkend='cv-SHDLIBVERSIONFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHDLIBVERSIONFLAGS</envar></link>">
<!ENTITY cv-link-SHDLINK "<link linkend='cv-SHDLINK' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHDLINK</envar></link>">
diff --git a/doc/man/scons.xml b/doc/man/scons.xml
index bd8d5f0..6aa42a3 100644
--- a/doc/man/scons.xml
+++ b/doc/man/scons.xml
@@ -54,10 +54,10 @@
<corpauthor>Steven Knight and the SCons Development Team</corpauthor>
- <pubdate>2004 - 2019</pubdate>
+ <pubdate>2004 - 2020</pubdate>
<copyright>
- <year>2004 - 2019</year>
+ <year>2004 - 2020</year>
<holder>The SCons Foundation</holder>
</copyright>
@@ -93,88 +93,88 @@
</refsynopsisdiv>
-<refsect1 id='description'><title>DESCRIPTION</title>
-<para>The
+<refsect1 id='description'>
+<title>DESCRIPTION</title>
+<para>
<command>scons</command>
-utility builds software (or other files) by determining which
-component pieces must be rebuilt and executing the necessary commands to
-rebuild them.</para>
+orchestrates the construction of software
+(and other tangible products such as documentation files)
+by determining which
+component pieces must be built or rebuilt and invoking the necessary
+commands to build them.</para>
+
+<para>You instruct
+<command>scons</command> by writing a configuration file
+which specifies the files to be built (<firstterm>targets</firstterm>),
+and, if necessary, the rules to build those files. Premade
+rules exist for building many common software components
+(such as executable programs, object files, libraries),
+so that for most software projects,
+only the target and input files need be specified.</para>
-<para>By default,
-<command>scons</command>
+<para>
+When invoked, <command>scons</command>
searches for a file named
-<emphasis>SConstruct</emphasis>,
-<emphasis>Sconstruct</emphasis>,
-<emphasis>sconstruct</emphasis>,
-<emphasis>SConstruct.py</emphasis>
-<emphasis>Sconstruct.py</emphasis>
-or
-<emphasis>sconstruct.py</emphasis>
-(in that order) in the current directory and reads its
-configuration from the first file found.
+&SConstruct;
+(going on to check alternative names
+&Sconstruct;, &sconstruct;, &SConstruct.py; &Sconstruct.py;
+and &sconstruct.py;
+in that order) in the current directory and reads its
+configuration from that file.
An alternate file name may be
specified via the
<option>-f</option>
-option.</para>
-
-<para>The
-<emphasis>SConstruct</emphasis>
+option.
+The &SConstruct;
file can specify subsidiary
configuration files using the
-<emphasis role="bold">SConscript</emphasis>()
-function.
+&SConscriptFunc; function.
By convention,
these subsidiary files are named
-<emphasis>SConscript</emphasis>,
+&SConscript;,
although any name may be used.
-(Because of this naming convention,
-the term "SConscript files"
-is sometimes used to refer
-generically to all
-<command>scons</command>
-configuration files,
-regardless of actual file name.)</para>
-
-<para>The configuration files
-specify the target files to be built, and
-(optionally) the rules to build those targets. Reasonable default
-rules exist for building common software components (executable
-programs, object files, libraries), so that for most software
-projects, only the target and input files need be specified.</para>
-
-<para>Before reading the
-<emphasis>SConstruct</emphasis>
-file,
+As a result of this naming convention,
+the term <firstterm>SConscript files</firstterm>
+is often used to refer
+generically to the complete set of
+configuration files for a project,
+including the &SConstruct; file,
+regardless of the actual file names or number of files.</para>
+
+<para>Before reading the SConscript files,
<command>scons</command>
looks for a directory named
-<emphasis>site_scons</emphasis>
-in various system directories (see below) and the directory containing the
-<emphasis>SConstruct</emphasis>
-file; for each of those dirs which exists,
-<emphasis>site_scons</emphasis>
-is prepended to sys.path,
-the file
-<emphasis>site_scons/site_init.py</emphasis>,
-is evaluated if it exists,
-and the directory
-<emphasis>site_scons/site_tools</emphasis>
-is prepended to the default toolpath if it exists.
+<filename>site_scons</filename>
+in various system directories and in the directory containing the
+&SConstruct; file and prepends the ones it
+finds to the Python module search path (<varname>sys.path</varname>),
+thus allowing modules in such directories to be imported in
+the normal Python way in SConscript files.
+For each found site directory,
+if it contains a file <filename>site_init.py</filename>
+it is evaluated, and if it contains a directory
+<filename>site_tools</filename> the path to it
+is prepended to the default toolpath.
See the
-<option>--no-site-dir</option>
-and
<option>--site-dir</option>
-options for more details.</para>
+and
+<option>--no-site-dir</option>
+options for details on default paths and
+controlling the site directories.
+</para>
<para><command>scons</command>
reads and executes the SConscript files as Python scripts,
so you may use normal Python scripting capabilities
(such as flow control, data manipulation, and imported Python libraries)
-to handle complicated build situations.
-<command>scons</command>,
-however, reads and executes all of the SConscript files
+to handle complicated build situations.</para>
+
+<para>
+<command>scons</command>
+reads and executes all of the SConscript files
<emphasis>before</emphasis>
it begins building any targets.
-To make this obvious,
+To make this clear,
<command>scons</command>
prints the following messages about what it is doing:</para>
@@ -189,7 +189,7 @@ $
</literallayout>
<para>The status messages
-(everything except the line that reads "cp foo.in foo.out")
+(lines beginning with the <literal>scons:</literal> tag)
may be suppressed using the
<option>-Q</option>
option.</para>
@@ -209,34 +209,28 @@ that you want to use to build your target files
are not in standard system locations,
<command>scons</command>
will not find them unless
-you explicitly set the <envar>PATH</envar>
+you explicitly set the <command>scons</command>
+<envar>PATH</envar> in the internal environment
to include those locations.
-Whenever you create an
-<command>scons</command>
-construction environment,
+Whenever you create a &consenv;,
you can propagate the value of <envar>PATH</envar>
from your external environment as follows:</para>
<literallayout class="monospaced">
import os
-env = Environment(ENV = {'PATH' : os.environ['PATH']})
+env = Environment(ENV={'PATH': os.environ['PATH']})
</literallayout>
-<para>Similarly, if the commands use external environment variables
-like
-<envar>PATH</envar>,
-<envar>HOME</envar>,
-<envar>JAVA_HOME</envar>,
-<envar>LANG</envar>,
-<envar>SHELL</envar>,
-<envar>TERM</envar>,
-etc.,
-these variables can also be explicitly propagated:</para>
+<para>Similarly, if the commands use specific
+external environment variables that <command>scons</command>
+does not recognize, they can be propagated into
+the internal environment:</para>
<literallayout class="monospaced">
import os
-env = Environment(ENV = {'PATH': os.environ['PATH'],
- 'HOME': os.environ['HOME']})
+env = Environment(ENV={'PATH': os.environ['PATH'],
+ 'ANDROID_HOME': os.environ['ANDROID_HOME'],
+ 'ANDROID_NDK_HOME': os.environ['ANDROID_NDK_HOME']})
</literallayout>
<para>Or you may explicitly propagate the invoking user's
@@ -244,17 +238,23 @@ complete external environment:</para>
<literallayout class="monospaced">
import os
-env = Environment(ENV = os.environ)
+env = Environment(ENV=os.environ)
</literallayout>
<para>This comes at the expense of making your build
dependent on the user's environment being set correctly,
-but it may be more convenient for many configurations.</para>
+but it may be more convenient for many configurations.
+It should not cause problems if done in a build setup which tightly
+controls how the environment is set up before invoking
+<command>scons</command>, as in many continuous
+integration setups.
+</para>
<para><command>scons</command>
can scan known input files automatically for dependency
-information (for example, #include statements
-in C or C++ files) and will rebuild dependent files appropriately
+information (for example, <literal>#include</literal>
+preprocessor directives in C or C++ files)
+and will rebuild dependent files appropriately
whenever any "included" input file changes.
<command>scons</command>
supports the
@@ -266,41 +266,46 @@ SCCS or RCS subdirectories
using SCCS, RCS or BitKeeper.</para>
<para><command>scons</command>
-is normally executed in a top-level directory containing a
-<emphasis>SConstruct</emphasis>
-file, optionally specifying
-as command-line arguments
-the target file or files to be built.</para>
-
-<para>By default, the command</para>
-
-<literallayout class="monospaced">
-scons
-</literallayout>
+is normally executed in a top-level directory containing an
+&SConstruct; file.
+When <command>scons</command> is invoked,
+the command line (including the contents
+of the &SCONSFLAGS; environment variable,
+if set) is processed.
+The options are consumed (see <xref linkend="options"></xref>;
+and also note that SConscript files may define additional options
+for the project using the &AddOption; function).
+Any variable argument assignments (see below) are also consumed.
+Any remaining arguments are taken as the targets to build.
+Targets on the command line may be files, directories,
+or phony targets defined using the &Alias; function.
+The command line targets are available in the
+&COMMAND_LINE_TARGETS; list.
+</para>
-<para>will build all target files in or below the current directory.
-Explicit default targets
-(to be built when no targets are specified on the command line)
-may be defined in the SConscript file(s)
-using the
-<emphasis role="bold">Default()</emphasis>
-function, described below.</para>
+<para>If no targets are specified on the command line,
+<command>scons</command>
+will build the default targets. The default targets
+are those specified in the SConscript files via calls
+to the &Default; function; if none, the default targets are
+those target files in or below the current directory.
+Targets specified via the &Default; function are available
+in the &DEFAULT_TARGETS; list.
+</para>
-<para>Even when
-<emphasis role="bold">Default()</emphasis>
-targets are specified in the SConscript file(s),
-all target files in or below the current directory
-may be built by explicitly specifying
-the current directory (.)
+<para>To ignore the default targets specified
+through calls to &Default; and instead build all
+target files in or below the current directory
+specify the current directory (<literal>.</literal>)
as a command-line target:</para>
<literallayout class="monospaced">
scons .
</literallayout>
-<para>Building all target files,
+<para>To build all target files,
including any files outside of the current directory,
-may be specified by supplying a command-line target
+supply a command-line target
of the root directory (on POSIX systems):</para>
<literallayout class="monospaced">
@@ -314,15 +319,33 @@ should be built (on Windows systems):</para>
scons C:\ D:\
</literallayout>
-<para>To build only specific targets,
-supply them as command-line arguments:</para>
+<para>A subset of a hierarchical tree may be built by
+remaining at the top-level directory (where the
+&SConstruct;
+file lives) and specifying the subdirectory as the target to
+build:</para>
<literallayout class="monospaced">
-scons foo bar
+scons src/subdir
</literallayout>
-<para>in which case only the specified targets will be built
-(along with any derived files on which they depend).</para>
+<para>or by changing directory and invoking scons with the
+<option>-u</option>
+option, which traverses up the directory
+hierarchy until it finds the
+&SConstruct;
+file, and then builds
+targets relatively to the current subdirectory (see
+also the related <option>-D</option> and <option>-U</option> options):</para>
+
+<literallayout class="monospaced">
+cd src/subdir
+scons -u .
+</literallayout>
+
+<para>In all cases, more files may be built than are
+requested, as <command>scons</command> needs to make
+sure any dependent files are built.</para>
<para>Specifying "cleanup" targets in SConscript files is not usually necessary.
The
@@ -334,45 +357,22 @@ necessary to build the specified target:</para>
scons -c .
</literallayout>
-<para>to remove all target files, or:</para>
+<para>to remove all target files in or under the current directory, or:</para>
<literallayout class="monospaced">
scons -c build export
</literallayout>
-<para>to remove target files under build and export.
+<para>to remove target files under <filename>build</filename>
+and <filename>export</filename>.</para>
+
+<para>
Additional files or directories to remove can be specified using the
-<emphasis role="bold">Clean()</emphasis>
-function.
+&Clean; function in the SConscript files.
Conversely, targets that would normally be removed by the
<option>-c</option>
-invocation
-can be prevented from being removed by using the
-<emphasis role="bold">NoClean</emphasis>()
-function.</para>
-
-<para>A subset of a hierarchical tree may be built by
-remaining at the top-level directory (where the
-<emphasis>SConstruct</emphasis>
-file lives) and specifying the subdirectory as the target to be
-built:</para>
-
-<literallayout class="monospaced">
-scons src/subdir
-</literallayout>
-
-<para>or by changing directory and invoking scons with the
-<option>-u</option>
-option, which traverses up the directory
-hierarchy until it finds the
-<emphasis>SConstruct</emphasis>
-file, and then builds
-targets relatively to the current subdirectory:</para>
-
-<literallayout class="monospaced">
-cd src/subdir
-scons -u .
-</literallayout>
+invocation can be retained by calling the
+&NoClean; function with those targets.</para>
<para><command>scons</command>
supports building multiple targets in parallel via a
@@ -405,16 +405,16 @@ command-line options. The
option is useful to prevent multiple builds
from trying to update the cache simultaneously.</para>
-<para>Values of variables to be passed to the SConscript file(s)
+<para>Values of variables to be passed to the SConscript files
may be specified on the command line:</para>
<literallayout class="monospaced">
scons debug=1 .
</literallayout>
-<para>These variables are available in SConscript files
-through the ARGUMENTS dictionary,
-and can be used in the SConscript file(s) to modify
+<para>These variables are available
+through the &ARGUMENTS; dictionary,
+and can be used in the SConscript files to modify
the build in any way:</para>
<literallayout class="monospaced">
@@ -425,13 +425,12 @@ else:
</literallayout>
<para>The command-line variable arguments are also available
-in the ARGLIST list,
+in the &ARGLIST; list,
indexed by their order on the command line.
This allows you to process them in order rather than by name,
-if necessary.
-ARGLIST[0] returns a tuple
-containing (argname, argvalue).
-A Python exception is thrown if you
+if necessary. Each &ARGLIST; entry is a tuple
+containing (<replaceable>argname</replaceable>, <replaceable>argvalue</replaceable>).
+A Python <literal>IndexError</literal> exception is raised if you
try to access a list member that
does not exist.</para>
@@ -443,24 +442,28 @@ There should be no other dependencies or requirements to run
<!-- The following paragraph reflects the default tool search orders -->
<!-- currently in SCons/Tool/__init__.py. If any of those search orders -->
<!-- change, this documentation should change, too. -->
+
<para>By default,
<command>scons</command>
-knows how to search for available programming tools
-on various systems.
-On Windows systems,
+searches for known programming tools
+on various systems and initializes itself based on what is found.
+On Windows systems which identify as <emphasis>win32</emphasis>,
<command>scons</command>
searches in order for the
Microsoft Visual C++ tools,
the MinGW tool chain,
the Intel compiler tools,
and the PharLap ETS compiler.
+On Windows system which identify as <emphasis>cygwin</emphasis>
+(that is, if <command>scons</command> is invoked from a cygwin shell),
+the order changes to prefer the GCC toolchain over the MSVC tools.
On OS/2 systems,
<command>scons</command>
searches in order for the
OS/2 compiler,
the GCC tool chain,
and the Microsoft Visual C++ tools,
-On SGI IRIX, IBM AIX, Hewlett Packard HP-UX, and Sun Solaris systems,
+On SGI IRIX, IBM AIX, Hewlett Packard HP-UX, and Oracle Solaris systems,
<command>scons</command>
searches for the native compiler tools
(MIPSpro, Visual Age, aCC, and Forte tools respectively)
@@ -470,7 +473,6 @@ including POSIX (Linux and UNIX) platforms,
<command>scons</command>
searches in order
for the GCC tool chain,
-the Microsoft Visual C++ tools,
and the Intel compiler tools.
You may, of course, override these default values
by appropriate configuration of
@@ -486,67 +488,61 @@ supports the same command-line options as GNU
and many of those supported by
<emphasis role="bold">cons</emphasis>.</para>
+<!-- Note: commented-out options are retained as they may be a model -->
+<!-- for future development directions. Do not remove. -->
+
<variablelist>
<varlistentry>
<term>-b</term>
<listitem>
-<para>Ignored for compatibility with non-GNU versions of
-<emphasis role="bold">make.</emphasis></para>
-
+<para>Ignored for compatibility with non-GNU versions of &Make;</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term>-c, --clean, --remove</term>
<listitem>
<para>Clean up by removing all target files for which a construction
command is specified.
Also remove any files or directories associated to the construction command
-using the
-<emphasis role="bold">Clean</emphasis>()
-function.
-Will not remove any targets specified by the
-<emphasis role="bold">NoClean</emphasis>()
-function.</para>
-
+using the &Clean; function.
+Will not remove any targets specified by the &NoClean; function.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term>--cache-debug=<emphasis>file</emphasis></term>
<listitem>
-<para>Print debug information about the
-<emphasis role="bold">CacheDir</emphasis>()
-derived-file caching
-to the specified
+<para>Print debug information about the &CacheDir;
+derived-file caching to the specified
<emphasis>file</emphasis>.
If
<emphasis>file</emphasis>
is
<emphasis role="bold">-</emphasis>
(a hyphen),
-the debug information are printed to the standard output.
-The printed messages describe what signature file names are
-being looked for in, retrieved from, or written to the
-<emphasis role="bold">CacheDir</emphasis>()
-directory tree.</para>
-
+the debug information is printed to the standard output.
+The printed messages describe what signature-file names
+are being looked for in, retrieved from, or written to the
+&CacheDir; directory tree.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term>--cache-disable, --no-cache</term>
<listitem>
<para>Disable the derived-file caching specified by
-<emphasis role="bold">CacheDir</emphasis>().
+&CacheDir;.
<command>scons</command>
will neither retrieve files from the cache
nor copy files to the cache.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--cache-force, --cache-populate</term>
<listitem>
-<para>When using
-<emphasis role="bold">CacheDir</emphasis>(),
+<para>When using &CacheDir;,
populate a cache by copying any already-existing, up-to-date
derived files to the cache,
in addition to files built by this invocation.
@@ -556,23 +552,22 @@ or to add to the cache any derived files
recently built with caching disabled via the
<option>--cache-disable</option>
option.</para>
-
</listitem>
</varlistentry>
-<varlistentry>
+
+ <varlistentry>
<term>--cache-readonly</term>
<listitem>
<para>Use the cache (if enabled) for reading, but do not not update the
cache with changed files.
</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--cache-show</term>
<listitem>
-<para>When using
-<emphasis role="bold">CacheDir</emphasis>()
+<para>When using &CacheDir;
and retrieving a derived file from the cache,
show the command
that would have been executed to build the file,
@@ -581,21 +576,20 @@ instead of the usual report,
This will produce consistent output for build logs,
regardless of whether a target
file was rebuilt or retrieved from the cache.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--config=<emphasis>mode</emphasis></term>
<listitem>
-<para>This specifies how the
-<emphasis role="bold">Configure</emphasis>
+<para>This specifies how the &Configure;
call should use or generate the
results of configuration tests.
The option should be specified from
-among the following choices:</para>
-
+among the following choices.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term>--config=auto</term>
<listitem>
@@ -607,9 +601,9 @@ but will overlook changes in system header files
or external commands (such as compilers)
if you don't specify those dependecies explicitly.
This is the default behavior.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--config=force</term>
<listitem>
@@ -621,9 +615,9 @@ This can be used to explicitly
force the configuration tests to be updated
in response to an otherwise unconfigured change
in a system header file or compiler.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--config=cache</term>
<listitem>
@@ -634,9 +628,9 @@ Note that scons will still consider it an error
if --config=cache is specified
and a necessary test does not
yet have any results in the cache.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-C <replaceable>directory</replaceable>, --directory=<replaceable>directory</replaceable></term>
<listitem>
@@ -651,7 +645,7 @@ That is, change directory before searching for the
&Sconstruct.py;
or
&sconstruct.py;
-file, or doing anything else.
+file or doing anything else.
When multiple
<option>-C</option>
options are given, each subsequent non-absolute
@@ -728,18 +722,18 @@ have been compiled with optimization
(that is, when executing from
<emphasis role="bold">*.pyo</emphasis>
files).</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=duplicate</term>
<listitem>
<para>Print a line for each unlink/relink (or copy) of a variant file from
its source file. Includes debugging info for unlinking stale variant
files, as well as unlinking old targets before building them.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=explain</term>
<listitem>
@@ -750,9 +744,9 @@ is deciding to (re-)build any targets.
for targets that are
<emphasis>not</emphasis>
rebuilt.)</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=findlibs</term>
<listitem>
@@ -760,9 +754,9 @@ rebuilt.)</para>
to print a message about each potential library
name it is searching for,
and about the actual libraries it finds.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=includes</term>
<listitem>
@@ -776,6 +770,7 @@ $ scons --debug=includes foo.o
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=memoizer</term>
<listitem>
@@ -783,35 +778,35 @@ $ scons --debug=includes foo.o
an internal subsystem that counts
how often SCons uses cached values in memory
instead of recomputing them each time they're needed.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=memory</term>
<listitem>
<para>Prints how much memory SCons uses
before and after reading the SConscript files
and before and after building targets.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=objects</term>
<listitem>
<para>Prints a list of the various objects
of the various classes used internally by SCons.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=pdb</term>
<listitem>
<para>Re-run SCons under the control of the
-pdb
+<command>pdb</command>
Python debugger.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=prepare</term>
<listitem>
@@ -824,9 +819,9 @@ This can help debug problems with targets that aren't being
built; it shows whether
<command>scons</command>
is at least considering them or not.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=presub</term>
<listitem>
@@ -834,50 +829,51 @@ is at least considering them or not.</para>
before the construction environment variables are substituted.
Also shows which targets are being built by this command.
Output looks something like this:</para>
+
<literallayout class="monospaced">
$ scons --debug=presub
Building myprog.o with action(s):
$SHCC $SHCFLAGS $SHCCFLAGS $CPPFLAGS $_CPPINCFLAGS -c -o $TARGET $SOURCES
...
</literallayout>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=stacktrace</term>
<listitem>
<para>Prints an internal Python stack trace
when encountering an otherwise unexplained error.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--debug=time</term>
<listitem>
<para>Prints various time profiling information:</para>
- <itemizedlist>
- <listitem>
+ <itemizedlist>
+ <listitem>
<para>The time spent executing each individual build command</para>
- </listitem>
- <listitem>
+ </listitem>
+ <listitem>
<para>The total build time (time SCons ran from beginning to end)</para>
- </listitem>
- <listitem>
+ </listitem>
+ <listitem>
<para>The total time spent reading and executing SConscript files</para>
- </listitem>
- <listitem>
-<para>The total time spent SCons itself spend running
+ </listitem>
+ <listitem>
+<para>The total time SCons itself spent running
(that is, not counting reading and executing SConscript files)</para>
- </listitem>
- <listitem>
+ </listitem>
+ <listitem>
<para>The total time spent executing all build commands</para></listitem>
-<listitem>
+ <listitem>
<para>The elapsed wall-clock time spent executing those build commands</para>
- </listitem>
- <listitem>
+ </listitem>
+ <listitem>
<para>The time spent processing each file passed to the <emphasis>SConscript()</emphasis> function</para>
- </listitem>
- </itemizedlist>
+ </listitem>
+ </itemizedlist>
<para>
(When
<command>scons</command>
@@ -948,9 +944,9 @@ or of not handling errors gracefully
found in SCCS or RCS, for example,
or if a file really does exist
where the SCons configuration expects a directory).</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--duplicate=<emphasis>ORDER</emphasis></term>
<listitem>
@@ -969,22 +965,23 @@ or
<emphasis>copy</emphasis>.
SCons will attempt to duplicate files using
the mechanisms in the specified order.</para>
+ </listitem>
+ </varlistentry>
<!-- .TP -->
<!-- \-e, \-\-environment\-overrides -->
<!-- Variables from the execution environment override construction -->
<!-- variables from the SConscript files. -->
- </listitem>
- </varlistentry>
<varlistentry>
<term>--enable-virtualenv</term>
<listitem>
<para>Import virtualenv-related variables to SCons.</para>
</listitem>
</varlistentry>
+
<varlistentry>
- <term>-f<emphasis> file</emphasis>, --file=<emphasis>file</emphasis>, --makefile=<emphasis>file</emphasis>, --sconstruct=<emphasis>file</emphasis></term>
+ <term>-f <emphasis>file</emphasis>, --file=<emphasis>file</emphasis>, --makefile=<emphasis>file</emphasis>, --sconstruct=<emphasis>file</emphasis></term>
<listitem>
<para>Use
<emphasis>file</emphasis>
@@ -995,29 +992,29 @@ options may be specified,
in which case
<command>scons</command>
will read all of the specified files.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-h, --help</term>
<listitem>
<para>Print a local help message for this build, if one is defined in
-the SConscript file(s), plus a line that describes the
+the SConscript files, plus a line that describes the
<option>-H</option>
option for command-line option help. If no local help message
is defined, prints the standard help message about command-line
options. Exits after displaying the appropriate message.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-H, --help-options</term>
<listitem>
<para>Print the standard help message about command-line options and
exit.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-i, --ignore-errors</term>
<listitem>
@@ -1025,6 +1022,7 @@ exit.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term>-I<emphasis> directory</emphasis>, --include-dir=<emphasis>directory</emphasis></term>
<listitem>
@@ -1035,15 +1033,16 @@ imported Python modules. If several
<option>-I</option>
options
are used, the directories are searched in the order specified.</para>
-
</listitem>
</varlistentry>
- <varlistentry>
- <term>--ignore-virtualenv</term>
- <listitem>
+
+ <varlistentry>
+ <term>--ignore-virtualenv</term>
+ <listitem>
<para>Suppress importing virtualenv-related variables to SCons.</para>
- </listitem>
- </varlistentry>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>--implicit-cache</term>
<listitem>
@@ -1055,9 +1054,6 @@ from the last time it was run
instead of scanning the files for implicit dependencies.
This can significantly speed up SCons,
but with the following limitations:</para>
- </listitem>
- </varlistentry>
-</variablelist>
<para><command>scons</command>
will not detect changes to implicit dependency search paths
@@ -1073,17 +1069,18 @@ dependency is added earlier in the implicit dependency search path
(e.g.
<emphasis role="bold">CPPPATH</emphasis>, <emphasis role="bold">LIBPATH</emphasis>)
than a current implicit dependency with the same name.</para>
+ </listitem>
+ </varlistentry>
-<variablelist>
<varlistentry>
<term>--implicit-deps-changed</term>
<listitem>
<para>Forces SCons to ignore the cached implicit dependencies. This causes the
implicit dependencies to be rescanned and recached. This implies
<option>--implicit-cache</option>.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--implicit-deps-unchanged</term>
<listitem>
@@ -1091,7 +1088,6 @@ implicit dependencies to be rescanned and recached. This implies
This causes cached implicit dependencies to always be used.
This implies
<option>--implicit-cache</option>.</para>
-
</listitem>
</varlistentry>
@@ -1155,7 +1151,6 @@ command:</para>
--taskmastertrace=FILE
--tree=OPTIONS
</literallayout>
-
</listitem>
</varlistentry>
</variablelist>
@@ -1180,9 +1175,9 @@ with the specified options.
is a synonym.
This command is itself a synonym for
<userinput>build --clean</userinput></para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term><emphasis role="bold">exit</emphasis></term>
<listitem>
@@ -1190,9 +1185,9 @@ This command is itself a synonym for
You can also exit by terminating input
(CTRL+D on UNIX or Linux systems,
CTRL+Z on Windows systems).</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term><emphasis role="bold">help</emphasis><emphasis>[COMMAND]</emphasis></term>
<listitem>
@@ -1205,9 +1200,9 @@ is specified,
and
<emphasis role="bold">?</emphasis>
are synonyms.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term><emphasis role="bold">shell</emphasis><emphasis>[COMMANDLINE]</emphasis></term>
<listitem>
@@ -1230,9 +1225,9 @@ environment variable
and
<emphasis role="bold">!</emphasis>
are synonyms.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term><emphasis role="bold">version</emphasis></term>
<listitem>
@@ -1274,15 +1269,17 @@ option, the last one is effective.</para>
<!-- .B scons -->
<!-- will not limit the number of -->
<!-- simultaneous jobs. -->
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-k, --keep-going</term>
<listitem>
<para>Continue as much as possible after an error. The target that
failed and those that depend on it will not be remade, but other
targets specified on the command line will still be processed.</para>
+ </listitem>
+ </varlistentry>
<!-- .TP -->
<!-- .RI \-l " N" ", \-\-load\-average=" N ", \-\-max\-load=" N -->
@@ -1292,7 +1289,6 @@ targets specified on the command line will still be processed.</para>
<!-- .I N -->
<!-- (a floating\-point number). -->
-
<!-- .TP -->
<!-- \-\-list\-derived -->
<!-- List derived files (targets, dependencies) that would be built, -->
@@ -1314,16 +1310,13 @@ targets specified on the command line will still be processed.</para>
<!-- [XXX This can probably go away with the right -->
<!-- combination of other options. Revisit this issue.] -->
- </listitem>
- </varlistentry>
<varlistentry>
<term>-m</term>
<listitem>
-<para>Ignored for compatibility with non-GNU versions of
-<emphasis role="bold">make</emphasis>.</para>
-
+<para>Ignored for compatibility with non-GNU versions of &Make;.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term>--max-drift=<emphasis>SECONDS</emphasis></term>
<listitem>
@@ -1341,9 +1334,9 @@ A negative value means to never cache the content
signature and to ignore the cached value if there already is one. A value
of 0 means to always use the cached signature,
no matter how old the file is.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--md5-chunksize=<emphasis>KILOBYTES</emphasis></term>
<listitem>
@@ -1357,29 +1350,31 @@ small block-size slows down the build considerably.</para>
<para>The default value is to use a chunk size of 64 kilobytes, which should
be appropriate for most uses.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-n, --just-print, --dry-run, --recon</term>
<listitem>
<para>No execute. Print the commands that would be executed to build
any out-of-date target files, but do not execute the commands.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--no-site-dir</term>
<listitem>
<para>Prevents the automatic addition of the standard
<emphasis>site_scons</emphasis>
dirs to
-<emphasis>sys.path</emphasis>.
+<varname>sys.path</varname>.
Also prevents loading the
-<emphasis>site_scons/site_init.py</emphasis>
+<filename>site_scons/site_init.py</filename>
modules if they exist, and prevents adding their
-<emphasis>site_scons/site_tools</emphasis>
+<filename>site_scons/site_tools</filename>
dirs to the toolpath.</para>
+ </listitem>
+ </varlistentry>
<!-- .TP -->
<!-- .RI \-o " file" ", \-\-old\-file=" file ", \-\-assume\-old=" file -->
@@ -1393,6 +1388,7 @@ dirs to the toolpath.</para>
<!-- Read values to override specific build environment variables -->
<!-- from the specified -->
<!-- .IR file . -->
+
<!-- .TP -->
<!-- \-p -->
<!-- Print the data base (construction environments, -->
@@ -1411,8 +1407,6 @@ dirs to the toolpath.</para>
<!-- scons \-p \-q -->
<!-- .EE -->
- </listitem>
- </varlistentry>
<varlistentry>
<term>--profile=<emphasis>file</emphasis></term>
<listitem>
@@ -1421,9 +1415,9 @@ and save the results in the specified
<emphasis>file</emphasis>.
The results may be analyzed using the Python
pstats module.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-q, --question</term>
<listitem>
@@ -1432,6 +1426,7 @@ status that is zero if the specified targets are already up to
date, non-zero otherwise.</para>
</listitem>
</varlistentry>
+
<varlistentry>
<term>-Q</term>
<listitem>
@@ -1441,14 +1436,14 @@ building targets
and entering directories.
Commands that are executed
to rebuild target files are still printed.</para>
+ </listitem>
+ </varlistentry>
<!-- .TP -->
<!-- \-r, \-R, \-\-no\-builtin\-rules, \-\-no\-builtin\-variables -->
<!-- Clear the default construction variables. Construction -->
<!-- environments that are created will be completely empty. -->
- </listitem>
- </varlistentry>
<varlistentry>
<term>--random</term>
<listitem>
@@ -1456,37 +1451,37 @@ to rebuild target files are still printed.</para>
building multiple trees simultaneously with caching enabled,
to prevent multiple builds from simultaneously trying to build
or retrieve the same target files.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-s, --silent, --quiet</term>
<listitem>
<para>Silent. Do not print commands that are executed to rebuild
target files.
Also suppresses SCons status messages.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-S, --no-keep-going, --stop</term>
<listitem>
<para>Ignored for compatibility with GNU
<emphasis role="bold">make</emphasis>.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
- <term>--site-dir=<emphasis>dir</emphasis></term>
+ <term>--site-dir=<replaceable>dir</replaceable></term>
<listitem>
-<para>Uses the named dir as the site dir rather than the default
+<para>Uses the named <replaceable>dir</replaceable> as the site dir rather than the default
<emphasis>site_scons</emphasis>
dirs. This dir will get prepended to
-<emphasis>sys.path</emphasis>,
+<varname>sys.path</varname>,
the module
-<emphasis>dir</emphasis>/site_init.py
+<filename><replaceable>dir</replaceable>/site_init.py</filename>
will get loaded if it exists, and
-<emphasis>dir</emphasis>/site_tools
+<filename><replaceable>dir</replaceable>/site_tools</filename>
will get added to the default toolpath.</para>
<para>The default set of
@@ -1495,18 +1490,15 @@ dirs used when
<option>--site-dir</option>
is not specified depends on the system platform, as follows. Note
that the directories are examined in the order given, from most
-generic to most specific, so the last-executed site_init.py file is
+generic to most specific, so the last-executed <filename>site_init.py</filename> file is
the most specific one (which gives it the chance to override
everything else), and the dirs are prepended to the paths, again so
the last dir examined comes first in the resulting path.</para>
- </listitem>
- </varlistentry>
-</variablelist>
-<variablelist>
- <varlistentry>
- <term>Windows:</term>
- <listitem>
+ <variablelist>
+ <varlistentry>
+ <term>Windows:</term>
+ <listitem>
<literallayout class="monospaced">
%ALLUSERSPROFILE/Application Data/scons/site_scons
%USERPROFILE%/Local Settings/Application Data/scons/site_scons
@@ -1514,11 +1506,12 @@ the last dir examined comes first in the resulting path.</para>
%HOME%/.scons/site_scons
./site_scons
</literallayout>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Mac OS X:</term>
- <listitem>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Mac OS X:</term>
+ <listitem>
<literallayout class="monospaced">
/Library/Application Support/SCons/site_scons
/opt/local/share/scons/site_scons (for MacPorts)
@@ -1527,32 +1520,36 @@ $HOME/Library/Application Support/SCons/site_scons
$HOME/.scons/site_scons
./site_scons
</literallayout>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Solaris:</term>
- <listitem>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Solaris:</term>
+ <listitem>
<literallayout class="monospaced">
/opt/sfw/scons/site_scons
/usr/share/scons/site_scons
$HOME/.scons/site_scons
./site_scons
</literallayout>
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>Linux, HPUX, and other Posix-like systems:</term>
- <listitem>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Linux, HPUX, and other Posix-like systems:</term>
+ <listitem>
<literallayout class="monospaced">
/usr/share/scons/site_scons
$HOME/.scons/site_scons
./site_scons
</literallayout>
+ </listitem>
+ </varlistentry>
+ </variablelist>
</listitem>
</varlistentry>
-</variablelist>
-<variablelist>
+
<varlistentry>
<term>--stack-size=<emphasis>KILOBYTES</emphasis></term>
<listitem>
@@ -1573,9 +1570,9 @@ build process.</para>
<para>The default value is to use a stack size of 256 kilobytes, which should
be appropriate for most uses. You should not need to increase this value
unless you encounter stack overflow errors.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-t, --touch</term>
<listitem>
@@ -1584,9 +1581,9 @@ unless you encounter stack overflow errors.</para>
(Touching a file to make it
appear up-to-date is unnecessary when using
<command>scons</command>.)</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--taskmastertrace=<emphasis>file</emphasis></term>
<listitem>
@@ -1597,9 +1594,9 @@ evaluates and controls the order in which Nodes are built.
A file name of
<emphasis role="bold">-</emphasis>
may be used to specify the standard output.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-tree=<emphasis>options</emphasis></term>
<listitem>
@@ -1610,9 +1607,9 @@ in various formats,
depending on the
<emphasis>options</emphasis>
specified:</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--tree=all</term>
<listitem>
@@ -1620,24 +1617,24 @@ specified:</para>
after each top-level target is built.
This prints out the complete dependency tree,
including implicit dependencies and ignored dependencies.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--tree=derived</term>
<listitem>
<para>Restricts the tree output to only derived (target) files,
not source files.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--tree=status</term>
<listitem>
<para>Prints status information for each displayed node.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--tree=prune</term>
<listitem>
@@ -1649,7 +1646,6 @@ will have its name printed in
as an indication that the dependencies
for that node can be found by searching
for the relevant output higher up in the tree.</para>
-
</listitem>
</varlistentry>
</variablelist>
@@ -1671,21 +1667,16 @@ scons --tree=all,prune,status target
<term>-u, --up, --search-up</term>
<listitem>
<para>Walks up the directory structure until an
-<emphasis>SConstruct ,</emphasis>
-<emphasis>Sconstruct ,</emphasis>
-<emphasis>sconstruct ,</emphasis>
-<emphasis>SConstruct.py</emphasis>
-<emphasis>Sconstruct.py</emphasis>
-or
-<emphasis>sconstruct.py</emphasis>
+&SConstruct;, &Sconstruct;, &sconstruct;, &SConstruct.py;,
+&Sconstruct.py; or &sconstruct.py;
file is found, and uses that
as the top of the directory tree.
If no targets are specified on the command line,
only targets at or below the
current directory will be built.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-U</term>
<listitem>
@@ -1696,9 +1687,9 @@ When this option is used and no targets are specified on the command line,
all default targets that are defined in the SConscript(s) in the current
directory are built, regardless of what directory the resultant targets end
up in.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-v, --version</term>
<listitem>
@@ -1707,40 +1698,40 @@ up in.</para>
version, copyright information,
list of authors, and any other relevant information.
Then exit.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>-w, --print-directory</term>
<listitem>
<para>Print a message containing the working directory before and
after other processing.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--no-print-directory</term>
<listitem>
<para>Turn off -w, even if it was turned on implicitly.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=<emphasis>type</emphasis>, --warn=no-<emphasis>type</emphasis></term>
<listitem>
<para>Enable or disable warnings.
<emphasis>type</emphasis>
specifies the type of warnings to be enabled or disabled:</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=all, --warn=no-all</term>
<listitem>
<para>Enables or disables all warnings.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=cache-version, --warn=no-cache-version</term>
<listitem>
@@ -1748,9 +1739,9 @@ specifies the type of warnings to be enabled or disabled:</para>
the latest configuration information
<emphasis role="bold">CacheDir</emphasis>().
These warnings are enabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=cache-write-error, --warn=no-cache-write-error</term>
<listitem>
@@ -1758,9 +1749,9 @@ These warnings are enabled by default.</para>
write a copy of a built file to a specified
<emphasis role="bold">CacheDir</emphasis>().
These warnings are disabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=corrupt-sconsign, --warn=no-corrupt-sconsign</term>
<listitem>
@@ -1768,17 +1759,17 @@ These warnings are disabled by default.</para>
<markup>.sconsign</markup>
files.
These warnings are enabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=dependency, --warn=no-dependency</term>
<listitem>
<para>Enables or disables warnings about dependencies.
These warnings are disabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=deprecated, --warn=no-deprecated</term>
<listitem>
@@ -1795,9 +1786,9 @@ before they are officially no longer supported by SCons.
Warnings for some specific deprecated features
may be enabled or disabled individually;
see below.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=duplicate-environment, --warn=no-duplicate-environment</term>
<listitem>
@@ -1805,18 +1796,18 @@ see below.</para>
of a target with two different construction environments
that use the same action.
These warnings are enabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=fortran-cxx-mix, --warn=no-fortran-cxx-mix</term>
<listitem>
<para>Enables or disables the specific warning about linking
Fortran and C++ object files in a single executable,
which can yield unpredictable behavior with some compilers.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=future-deprecated, --warn=no-future-deprecated</term>
<listitem>
@@ -1829,16 +1820,16 @@ SCons configurations for other users to build,
so that the project can be warned as soon as possible
about to-be-deprecated features
that may require changes to the configuration.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=link, --warn=no-link</term>
<listitem>
<para>Enables or disables warnings about link steps.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=misleading-keywords, --warn=no-misleading-keywords</term>
<listitem>
@@ -1854,17 +1845,17 @@ characters, the correct spellings are
and
<emphasis role="bold">source.)</emphasis>
These warnings are enabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=missing-sconscript, --warn=no-missing-sconscript</term>
<listitem>
<para>Enables or disables warnings about missing SConscript files.
These warnings are enabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=no-object-count, --warn=no-no-object-count</term>
<listitem>
@@ -1875,9 +1866,9 @@ feature not working when
is run with the Python
<option>-O</option>
option or from optimized Python (.pyo) modules.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=no-parallel-support, --warn=no-no-parallel-support</term>
<listitem>
@@ -1886,18 +1877,18 @@ not being able to support parallel builds when the
<option>-j</option>
option is used.
These warnings are enabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=python-version, --warn=no-python-version</term>
<listitem>
<para>Enables or disables the warning about running
SCons with a deprecated version of Python.
These warnings are enabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=reserved-variable, --warn=no-reserved-variable</term>
<listitem>
@@ -1913,15 +1904,29 @@ reserved construction variable names
or
<emphasis role="bold">UNCHANGED_TARGETS</emphasis>.
These warnings are disabled by default.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>--warn=stack-size, --warn=no-stack-size</term>
<listitem>
<para>Enables or disables warnings about requests to set the stack size
that could not be honored.
These warnings are enabled by default.</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>--warn=target_not_build, --warn=no-target_not_built</term>
+ <listitem>
+<para>Enables or disables warnings about a build rule not building the
+ expected targets. These warnings are not currently enabled by default.</para>
+ </listitem>
+ </varlistentry>
+
+<!-- .TP -->
+<!-- \-\-warn\-undefined\-variables -->
+<!-- Warn when an undefined variable is referenced. -->
<!-- .TP -->
<!-- .RI \-\-write\-filenames= file -->
@@ -1941,20 +1946,6 @@ These warnings are enabled by default.</para>
<!-- .B \-n -->
<!-- ... what? XXX -->
-<!-- .TP -->
-<!-- \-\-warn\-undefined\-variables -->
-<!-- Warn when an undefined variable is referenced. -->
-
- </listitem>
- </varlistentry>
- <varlistentry>
- <term>--warn=target_not_build, --warn=no-target_not_built</term>
- <listitem>
-<para>Enables or disables warnings about a build rule not building the
- expected targets. These warnings are not currently enabled by default.</para>
-
- </listitem>
- </varlistentry>
<varlistentry>
<term>-Y<emphasis> repository</emphasis>, --repository=<emphasis>repository</emphasis>, --srcdir=<emphasis>repository</emphasis></term>
<listitem>
@@ -1963,9 +1954,9 @@ files not found in the local directory hierarchy. Multiple
<option>-Y</option>
options may be specified, in which case the
repositories are searched in the order specified.</para>
-
</listitem>
</varlistentry>
+
</variablelist>
</refsect1>
@@ -1974,10 +1965,10 @@ repositories are searched in the order specified.</para>
<!-- XXX Adding this in the future would be a help. -->
<refsect2 id='construction_environments'><title>Construction Environments</title>
-<para>A construction environment is the basic means by which the SConscript
+<para>A <firstterm>&ConsEnv;</firstterm> is the basic means by which the SConscript
files communicate build information to
<command>scons</command>.
-A new construction environment is created using the
+A new &consenv; is created using the
<emphasis role="bold">Environment</emphasis>
function:</para>
@@ -1986,27 +1977,26 @@ env = Environment()
</literallayout>
<para>Variables, called
-<emphasis>construction</emphasis>
-<emphasis>variables</emphasis>,
-may be set in a construction environment
+<firstterm>&ConsVars;</firstterm>
+may be set in a &consenv;
either by specifying them as keywords when the object is created
or by assigning them a value after the object is created:</para>
<literallayout class="monospaced">
-env = Environment(FOO = 'foo')
+env = Environment(FOO='foo')
env['BAR'] = 'bar'
</literallayout>
<para>As a convenience,
-construction variables may also be set or modified by the
-<emphasis role="bold">parse_flags</emphasis>
+&consvars; may also be set or modified by the
+<parameter class="function">parse_flags</parameter>
keyword argument, which applies the
&f-link-env-MergeFlags;
method (described below) to the argument value
after all other processing is completed.
This is useful either if the exact content of the flags is unknown
(for example, read from a control file)
-or if the flags are distributed to a number of construction variables.</para>
+or if the flags are distributed to a number of &consvars;.</para>
<literallayout class="monospaced">
env = Environment(parse_flags='-Iinclude -DEBUG -lm')
@@ -2019,9 +2009,9 @@ env = Environment(parse_flags='-Iinclude -DEBUG -lm')
and 'm' to
<emphasis role="bold">LIBS</emphasis>.</para>
-<para>By default, a new construction environment is
+<para>By default, a new &consenv; is
initialized with a set of builder methods
-and construction variables that are appropriate
+and &consvars; that are appropriate
for the current platform.
An optional platform keyword argument may be
used to specify that an environment should
@@ -2035,7 +2025,7 @@ env = Environment(platform = 'win32')
</literallayout>
<para>Specifying a platform initializes the appropriate
-construction variables in the environment
+&consvars; in the environment
to use and generate file names with prefixes
and suffixes appropriate for the platform.</para>
@@ -2326,8 +2316,8 @@ path strings: if the string begins with
the <emphasis role="bold">#</emphasis> character it is
top-relative - it works like a relative path but the
search follows down from the directory containing the top-level
-<emphasis role="bold">SConstruct</emphasis> rather than
-from the current directory (the # is allowed
+&SConstruct; rather than
+from the current directory (the <emphasis role="bold">#</emphasis> is allowed
to be followed by a pathname separator, which is ignored if
found in that position).
Top-relative paths only work in places where &scons; will
@@ -2634,14 +2624,14 @@ construction variables like
<emphasis role="bold">$TARGET</emphasis>
and
<emphasis role="bold">$SOURCE</emphasis>
-when using the chdir
+when using the <parameter>chdir</parameter>
keyword argument--that is,
the expanded file names
will still be relative to
-the top-level SConstruct directory,
+the top-level directory where &SConstruct; was found,
and consequently incorrect
relative to the chdir directory.
-If you use the chdir keyword argument,
+If you use the <parameter>chdir</parameter> keyword argument,
you will typically need to supply a different
command line using
expansions like
@@ -2652,7 +2642,7 @@ to use just the filename portion of the
targets and source.</para>
<para><command>scons</command>
-predefined the following builder methods.
+predefines the following builder methods.
Depending on the setup of a particular
&consenv; and on the type and software
installation status of the underlying system,
@@ -2743,7 +2733,8 @@ object.</para>
</refsect2>
-<refsect2 id='methods_and_functions_to_do_things'><title>Methods and Functions to Do Things</title>
+<refsect2 id='methods_and_functions_to_do_things'>
+<title>Methods and Functions To Do Things</title>
<para>In addition to Builder methods,
<command>scons</command>
provides a number of other construction environment methods
@@ -2752,41 +2743,30 @@ manipulate the build configuration.</para>
<para>Usually, a construction environment method
and global function with the same name both exist
-so that you don't have to remember whether
-to a specific bit of functionality
-must be called with or without a construction environment.
-In the following list,
-if you call something as a global function
-it looks like:</para>
+for convenience.
+In the following list, the global function
+is documented like:</para>
<literallayout class="monospaced">
Function(<emphasis>arguments</emphasis>)
</literallayout>
-<para>and if you call something through a construction
-environment it looks like:</para>
+<para>and the construction environment method looks like:</para>
<literallayout class="monospaced">
env.Function(<emphasis>arguments</emphasis>)
</literallayout>
-<para>If you can call the functionality in both ways,
+<para>If you can call the function in both ways,
then both forms are listed.</para>
-<para>Global functions may be called from custom Python modules that you
-import into an SConscript file by adding the following
-to the Python module:</para>
-
-<literallayout class="monospaced">
-from SCons.Script import *
-</literallayout>
-
-<para>Except where otherwise noted,
-the same-named
+<para>The global function and same-named
construction environment method
-and global function
-provide the exact same functionality.
-The only difference is that,
-where appropriate,
+provide almost identical functionality, with a couple of exceptions.
+First, many of the construction environment methods affect only that
+construction environment, while the global function has a
+global effect. Second, where appropriate,
calling the functionality through a construction environment will
substitute construction variables into
-any supplied strings.
+any supplied strings, while the global function doesn't have the
+context of a construction environment to pick variables from,
+so it cannot perform the substitution.
For example:</para>
<literallayout class="monospaced">
@@ -2812,6 +2792,14 @@ For more on construction variable expansion,
see the next section on
construction variables.</para>
+<para>Global functions may be called from custom Python modules that you
+import into an SConscript file by adding the following import
+to the Python module:</para>
+
+<literallayout class="monospaced">
+from SCons.Script import *
+</literallayout>
+
<para>Construction environment methods
and global functions supported by
<command>scons</command>
@@ -2935,9 +2923,10 @@ else:
<command>scons</command>
will actually try to build,
regardless of whether they were specified on
-the command line or via the
-<emphasis role="bold">Default</emphasis>()
-function or method.
+the command line or via the &Default;
+function or method
+(but empty if neither
+command line targets or &Default; calls are present).
The elements of this list may be strings
<emphasis>or</emphasis>
nodes, so you should run the list through the Python
@@ -2947,8 +2936,7 @@ are converted to strings.</para>
<para>Because this list may be taken from the
list of targets specified using the
-<emphasis role="bold">Default</emphasis>()
-function or method,
+&Default; function or method,
the contents of the list may change
on each successive call to
<emphasis role="bold">Default</emphasis>().
@@ -2971,7 +2959,7 @@ if 'special/program' in BUILD_TARGETS:
<para>Note that the
<emphasis role="bold">BUILD_TARGETS</emphasis>
-list only contains targets expected listed
+list only contains targets listed
on the command line or via calls to the
<emphasis role="bold">Default</emphasis>()
function or method.
@@ -3989,9 +3977,9 @@ opt.AddVariables(
'notset', validator, None),
)
</literallayout>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>Update(<emphasis>env</emphasis>, [<emphasis>args</emphasis>])</term>
<listitem>
@@ -4013,13 +4001,12 @@ the Environment() function:</para>
<literallayout class="monospaced">
env = Environment(variables=vars)
</literallayout>
-
</listitem>
</varlistentry>
</variablelist>
<para>The text file(s) that were specified
-when the Variables object was created
+when the &Variables; object was created
are executed as Python scripts,
and the values of (global) Python variables set in the file
are added to the construction environment.</para>
@@ -4383,20 +4370,17 @@ vars.AddVariables(
</refsect2>
-<refsect2 id='file_and_directory_nodes'><title>File and Directory Nodes</title>
+<refsect2 id='file_and_directory_nodes'>
+<title>File and Directory Nodes</title>
-<para>The
-<emphasis>File</emphasis>()
-and
-<emphasis>Dir</emphasis>()
-functions return
-<emphasis>File</emphasis>
-and
-<emphasis>Dir</emphasis>
-Nodes, respectively.
-Python objects, respectively.
-Those objects have several user-visible attributes
-and methods that are often useful:</para>
+<para>
+The &f-link-File; and &f-link-Dir;
+functions/methods return
+File and Directory Nodes, respectively.
+Such nodes are Python objects with
+several user-visible attributes
+and methods that are often useful to access
+in SConscript files:</para>
<variablelist>
<varlistentry>
@@ -4406,39 +4390,35 @@ and methods that are often useful:</para>
of the given
file or directory.
This path is relative to the top-level directory
-(where the
-<emphasis role="bold">SConstruct</emphasis>
-file is found).
+(where the &SConstruct; file is found).
The build path is the same as the source path if
<emphasis>variant_dir</emphasis>
is not being used.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>abspath</term>
<listitem>
<para>The absolute build path of the given file or directory.</para>
-
</listitem>
</varlistentry>
+
<varlistentry>
<term>srcnode()</term>
<listitem>
<para>The
<emphasis>srcnode</emphasis>()
method
-returns another
-<emphasis>File</emphasis>
-or
-<emphasis>Dir</emphasis>
-object representing the
-<emphasis>source</emphasis>
-path of the given
-<emphasis>File</emphasis>
-or
-<emphasis>Dir</emphasis>.
-The</para>
+returns another File or Directory Node
+representing the source path of the given
+File or Directory Node.
+</para>
+ </listitem>
+ </varlistentry>
+</variablelist>
+
+<para>For example:</para>
<literallayout class="monospaced">
# Get the current build dir's path, relative to top.
@@ -4451,98 +4431,90 @@ File('foo.c').srcnode().path # source path of the given source file.
# Builders also return File objects:
foo = env.Program('foo.c')
-print("foo will be built in %s"%foo.path)
+print("foo will be built in", foo.path)
</literallayout>
-<para>A
-<emphasis>Dir</emphasis>
-Node or
-<emphasis>File</emphasis>
-Node can also be used to create
-file and subdirectory Nodes relative to the generating Node.
-A
-<emphasis>Dir</emphasis>
-Node will place the new Nodes within the directory it represents.
-A
-<emphasis>File</emphasis>
-node will place the new Nodes within its parent directory
-(that is, "beside" the file in question).
-If
-<emphasis>d</emphasis>
-is a
-<emphasis>Dir</emphasis>
-(directory) Node and
-<emphasis>f</emphasis>
-is a
-<emphasis>File</emphasis>
-(file) Node,
-then these methods are available:</para>
+<para>
+File and Directory Node objects have methods to create
+File and Directory Nodes relative to the original Node.
+</para>
+
+<para>
+If the object is a Directory Node,
+these methods will place the the new Node within the directory
+the Node represents:
+</para>
- </listitem>
- </varlistentry>
-</variablelist>
<variablelist>
<varlistentry>
- <term><emphasis>d</emphasis>.Dir(<emphasis>name</emphasis>)</term>
+ <term><replaceable>d</replaceable>.Dir(<replaceable>name</replaceable>)</term>
<listitem>
<para>Returns a directory Node for a subdirectory of
-<emphasis>d</emphasis>
+<replaceable>d</replaceable>
named
-<emphasis>name</emphasis>.</para>
-
+<replaceable>name</replaceable>.</para>
</listitem>
</varlistentry>
+
<varlistentry>
- <term><emphasis>d</emphasis>.File(<emphasis>name</emphasis>)</term>
+ <term><replaceable>d</replaceable>.File(<replaceable>name</replaceable>)</term>
<listitem>
<para>Returns a file Node for a file within
-<emphasis>d</emphasis>
+<replaceable>d</replaceable>
named
-<emphasis>name</emphasis>.</para>
-
+<replaceable>name</replaceable>.</para>
</listitem>
</varlistentry>
+
<varlistentry>
- <term><emphasis>d</emphasis>.Entry(<emphasis>name</emphasis>)</term>
+ <term><replaceable>d</replaceable>.Entry(<replaceable>name</replaceable>)</term>
<listitem>
<para>Returns an unresolved Node within
-<emphasis>d</emphasis>
+<replaceable>d</replaceable>
named
-<emphasis>name</emphasis>.</para>
-
+<replaceable>name</replaceable>.</para>
</listitem>
</varlistentry>
+</variablelist>
+
+<para>
+If the object is a File Node,
+these methods will place the the new Node in the same
+directory as the one the Node represents:
+</para>
+
+<variablelist>
<varlistentry>
- <term><emphasis>f</emphasis>.Dir(<emphasis>name</emphasis>)</term>
+ <term><replaceable>d</replaceable>.Dir(<replaceable>name</replaceable>)</term>
<listitem>
<para>Returns a directory named
-<emphasis>name</emphasis>
+<replaceable>name</replaceable>
within the parent directory of
-<emphasis>f</emphasis>.</para>
-
+<replaceable>f</replaceable>.</para>
</listitem>
</varlistentry>
+
<varlistentry>
- <term><emphasis>f</emphasis>.File(<emphasis>name</emphasis>)</term>
+ <term><replaceable>d</replaceable>.File(<replaceable>name</replaceable>)</term>
<listitem>
<para>Returns a file named
-<emphasis>name</emphasis>
+<replaceable>name</replaceable>
within the parent directory of
-<emphasis>f</emphasis>.</para>
-
+<replaceable>f</replaceable>.</para>
</listitem>
</varlistentry>
+
<varlistentry>
- <term><emphasis>f</emphasis>.Entry(<emphasis>name</emphasis>)</term>
+ <term><replaceable>d</replaceable>.Entry(<replaceable>name</replaceable>)</term>
<listitem>
<para>Returns an unresolved Node named
-<emphasis>name</emphasis>
+<replaceable>name</replaceable>
within the parent directory of
-<emphasis>f</emphasis>.</para>
-
+<replaceable>f</replaceable>.</para>
</listitem>
</varlistentry>
</variablelist>
+
<para>For example:</para>
<literallayout class="monospaced">
@@ -5106,14 +5078,14 @@ construction variables like
<emphasis role="bold">$TARGET</emphasis>
and
<emphasis role="bold">$SOURCE</emphasis>
-when using the chdir
+when using the <parameter>chdir</parameter>
keyword argument--that is,
the expanded file names
will still be relative to
-the top-level SConstruct directory,
+the top-level directory containing the &SConstruct; file,
and consequently incorrect
relative to the chdir directory.
-Builders created using chdir keyword argument,
+Builders created using <parameter>chdir</parameter> keyword argument,
will need to use construction variable
expansions like
<emphasis role="bold">${TARGET.file}</emphasis>
@@ -5444,14 +5416,14 @@ construction variables like
<emphasis role="bold">$TARGET</emphasis>
and
<emphasis role="bold">$SOURCE</emphasis>
-when using the chdir
+when using the <parameter>chdir</parameter>
keyword argument--that is,
the expanded file names
will still be relative to
-the top-level SConstruct directory,
+the top-level directory containing the &SConstruct; file,
and consequently incorrect
relative to the chdir directory.
-Builders created using chdir keyword argument,
+Builders created using <parameter>chdir</parameter> keyword argument,
will need to use construction variable
expansions like
<emphasis role="bold">${TARGET.file}</emphasis>
@@ -5923,7 +5895,7 @@ action='$CC -c -o $TARGET $SOURCES'
cc -c -o foo foo.c bar.c
</literallayout>
-<para>Variable names may be surrounded by curly braces
+<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.
@@ -7063,7 +7035,7 @@ prefix and suffix for the current platform
<refsect2 id='customizing_construction_variables_from_'><title>Customizing construction variables from the command line.</title>
<para>The following would allow the C compiler to be specified on the command
-line or in the file custom.py.</para>
+line or in the file <filename>custom.py</filename>.</para>
<literallayout class="monospaced">
vars = Variables('custom.py')
@@ -7078,7 +7050,7 @@ Help(vars.GenerateHelpText(env))
scons "CC=my_cc"
</literallayout>
-<para>or in the custom.py file:</para>
+<para>or in the <filename>custom.py</filename> file:</para>
<literallayout class="monospaced">
CC = 'my_cc'
@@ -7182,7 +7154,10 @@ However the following variables are imported by
<term>SCONS_LIB_DIR</term>
<listitem>
<para>Specifies the directory that contains the &scons;
-Python module directory (for example,
+Python module directory. Normally &scons; can deduce this,
+but in some circumstances, such as working with a source
+release, it may be necessary to specify
+(for example,
<filename>/home/aroach/scons-src-0.01/src/engine</filename>).</para>
</listitem>
</varlistentry>
@@ -7200,7 +7175,7 @@ in addition to those passed on the command line.</para>
<listitem>
<para>(Windows only). If set, save the shell environment variables
generated when setting up the Microsoft Visual C++ compiler
-(and/or Build Tools) to a file to give these settings,
+(and/or Build Tools) to a file to give these settings,
which are expensive to generate, persistence
across &scons; invocations.
Use of this option is primarily intended to aid performance
@@ -7222,7 +7197,7 @@ Remove the cache file in case of problems with this.
&scons; will ignore failures reading or writing the file
and will silently revert to non-cached behavior in such cases.</para>
-<para>Since &scons; 3.1.</para>
+<para>Since &scons; 3.1 (experimental).</para>
</listitem>
</varlistentry>
diff --git a/doc/scons.mod b/doc/scons.mod
index 3e843a0..024afab 100644
--- a/doc/scons.mod
+++ b/doc/scons.mod
@@ -225,6 +225,7 @@
<!ENTITY NoCache "<function xmlns='http://www.scons.org/dbxsd/v1.0'>NoCache</function>">
<!ENTITY Objects "<function xmlns='http://www.scons.org/dbxsd/v1.0'>Objects</function>">
<!ENTITY Options "<function xmlns='http://www.scons.org/dbxsd/v1.0'>Options</function>">
+<!ENTITY SConscriptFunc "<function xmlns='http://www.scons.org/dbxsd/v1.0'>SConscript</function>">
<!ENTITY Variables "<function xmlns='http://www.scons.org/dbxsd/v1.0'>Variables</function>">
<!ENTITY PackageOption "<function xmlns='http://www.scons.org/dbxsd/v1.0'>PackageOption</function>">
<!ENTITY PackageVariable "<function xmlns='http://www.scons.org/dbxsd/v1.0'>PackageVariable</function>">
@@ -418,27 +419,27 @@
-->
-<!ENTITY buildfunc "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>builder function</literal>">
-<!ENTITY build_action "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>build action</literal>">
-<!ENTITY build_actions "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>build actions</literal>">
-<!ENTITY builder_method "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>builder method</literal>">
+<!ENTITY buildfunc "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>builder function</phrase>">
+<!ENTITY build_action "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>build action</phrase>">
+<!ENTITY build_actions "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>build actions</phrase>">
+<!ENTITY builder_method "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>builder method</phrase>">
-<!ENTITY Configure_Contexts "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Configure Contexts</literal>">
-<!ENTITY configure_context "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>configure context</literal>">
+<!ENTITY Configure_Contexts "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>Configure Contexts</phrase>">
+<!ENTITY configure_context "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>configure context</phrase>">
-<!ENTITY ConsEnv "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Construction Environment</literal>">
-<!ENTITY ConsEnvs "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Construction Environments</literal>">
-<!ENTITY Consenv "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Construction environment</literal>">
-<!ENTITY Consenvs "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Construction environments</literal>">
-<!ENTITY consenv "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>construction environment</literal>">
-<!ENTITY consenvs "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>construction environments</literal>">
+<!ENTITY ConsEnv "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>Construction Environment</phrase>">
+<!ENTITY ConsEnvs "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>Construction Environments</phrase>">
+<!ENTITY Consenv "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>Construction environment</phrase>">
+<!ENTITY Consenvs "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>Construction environments</phrase>">
+<!ENTITY consenv "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>construction environment</phrase>">
+<!ENTITY consenvs "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>construction environments</phrase>">
-<!ENTITY ConsVar "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Construction Variable</literal>">
-<!ENTITY ConsVars "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Construction Variables</literal>">
-<!ENTITY Consvar "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Construction variable</literal>">
-<!ENTITY Consvars "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Construction variables</literal>">
-<!ENTITY consvar "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>construction variable</literal>">
-<!ENTITY consvars "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>construction variables</literal>">
+<!ENTITY ConsVar "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>Construction Variable</phrase>">
+<!ENTITY ConsVars "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>Construction Variables</phrase>">
+<!ENTITY Consvar "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>Construction variable</phrase>">
+<!ENTITY Consvars "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>Construction variables</phrase>">
+<!ENTITY consvar "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>construction variable</phrase>">
+<!ENTITY consvars "<phrase xmlns='http://www.scons.org/dbxsd/v1.0'>construction variables</phrase>">
<!ENTITY CPPPATH "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>CPPPATH</literal>">
@@ -529,14 +530,14 @@
-->
-<!ENTITY scons-announce "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>announce@scons.tigris.org</literal>">
-<!ENTITY scons-devel "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>scons-dev@scons.org</literal>">
-<!ENTITY scons-users "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>scons-users@scons.org</literal>">
+<!ENTITY scons-announce "<email xmlns='http://www.scons.org/dbxsd/v1.0'>announce@scons.tigris.org</email>">
+<!ENTITY scons-devel "<email xmlns='http://www.scons.org/dbxsd/v1.0'>scons-dev@scons.org</email>">
+<!ENTITY scons-users "<email xmlns='http://www.scons.org/dbxsd/v1.0'>scons-users@scons.org</email>">
<!--
Character entities
-
+
-->
<!ENTITY lambda "&#923;">
diff --git a/doc/user/build-install.xml b/doc/user/build-install.xml
index fbb14e5..87a86aa 100644
--- a/doc/user/build-install.xml
+++ b/doc/user/build-install.xml
@@ -110,29 +110,37 @@ Python 3.7.1
</screen>
<para>
- In a cmd shell or PowerShell on a Windows system
- (note PoweShell needs it spelled "python.exe" rather than "python"):
+ Note to Windows users: there are many different ways Python
+ can get installed or invoked on Windows, it is beyond the scope
+ of this guide to unravel all of them. Try using the
+ <firstterm>Python launcher</firstterm> (see
+ <ulink url="https://www.python.org/dev/peps/pep-0397/">PEP 397</ulink>)
+ by using the name <command>py</command> instead of
+ <command>python</command>, if that is not available drop
+ back to trying <command>python</command>.
</para>
<screen>
-C:\><userinput>python -V</userinput>
+C:\><userinput>py -V</userinput>
Python 3.7.1
</screen>
<para>
If Python is not installed on your system,
+ or is not findable in the current search path,
you will see an error message
stating something like "command not found"
(on UNIX or Linux)
or "'python' is not recognized
as an internal or external command, operable progam or batch file"
- (on Windows).
+ (on Windows <command>cmd</command>).
In that case, you need to install Python
+ (or fix the search path)
before you can install &SCons;.
</para>
<para>
- The standard location for information
+ The canonical location for information
about downloading and installing Python is
<ulink url="http://www.python.org/download/">http://www.python.org/download/</ulink>.
See that page and associated links to get started.
@@ -141,16 +149,18 @@ Python 3.7.1
<para>
For Linux systems, Python is
almost certainly available as a supported package, possibly
- installed by default; this is often preferred to installing
+ installed by default; this is often preferred over installing
by other means, and is easier than installing from source code.
Many such systems have separate packages for
- Python 2 and Python 3. Building from source may still be a
+ Python 2 and Python 3 - make sure the Python 3 package is
+ installed, as &SCons; requires it.
+ Building from source may still be a
useful option if you need a version that is not offered by
the distribution you are using.
</para>
<para>
- &SCons; will work with Python 2.7.x or with Python 3.5 or later.
+ &SCons; will work with Python 3.5 or later.
If you need to install Python and have a choice,
we recommend using the most recent Python version available.
Newer Pythons have significant improvements
@@ -182,13 +192,31 @@ Python 3.7.1
</screen>
<para>
- &SCons; comes pre-packaged for installation on many Linux systems
+ For those users using Anaconda or Miniconda, use the
+ <command>conda</command> installer instead, so the &scons;
+ install location will match the version of Python that
+ system will be using:
+ </para>
+
+ <screen>
+% <userinput>conda install -c conda-forge scons</userinput>
+ </screen>
+
+ <para>
+ &SCons; comes pre-packaged for installation on many Linux systems.
Check your package installation system
to see if there is an &SCons; package available.
Many people prefer to install distribution-native packages if available,
as they provide a central point for management and updating.
- Some distributions have two &SCons; packages available, one which
- uses Python 2 and one which uses Python 3. If you need a specific
+ During the still-ongoing Python 2 to 3 transition,
+ some distributions may still have two &SCons; packages available,
+ one which uses Python 2 and one which uses Python 3. Since
+ latest &scons; only runs on Python 3, to get the current version
+ you should choose the Python 3 package.
+ </para>
+
+ <para>
+ If you need a specific
version of &SCons; that is different from the package available,
<filename>pip</filename> has a version option or you can follow
the instructions in the next section.
@@ -211,7 +239,7 @@ Python 3.7.1
<filename>scons-&buildversion;.tar.gz</filename>
or <filename>scons-&buildversion;.zip</filename>,
which are available from the SCons download page at
- <ulink url="http://www.scons.org/download.html">http://www.scons.org/download.html</ulink>.
+ <ulink url="https://scons.org/pages/download.html">https://scons.org/pages/download.html</ulink>.
</para>
<para>
diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml
index 76fa794..d9a155f 100644
--- a/doc/user/builders-writing.xml
+++ b/doc/user/builders-writing.xml
@@ -558,6 +558,8 @@ file.input
&SCons; Builder objects can create an action "on the fly"
by using a function called a &generator;.
+ (Note: this is not the same thing as a Python generator function
+ described in <ulink url="https://www.python.org/dev/peps/pep-0255/">PEP 255</ulink>)
This provides a great deal of flexibility to
construct just the right list of commands
to build your target.
diff --git a/doc/user/depends.xml b/doc/user/depends.xml
index 703855d..24bede6 100644
--- a/doc/user/depends.xml
+++ b/doc/user/depends.xml
@@ -561,13 +561,6 @@ int main() { printf("Hello, world!\n"); }
</para>
- <para>
- The fourth argument <varname>repo_node</varname>,
- is the &Node; to use if it is not None when comparing &BuildInfo;.
- This is typically only set when the target node only exists in a
- &Repository;
- </para>
-
<variablelist>
<varlistentry>
@@ -612,22 +605,33 @@ int main() { printf("Hello, world!\n"); }
<para>
- Note that ignoring some of the arguments
- in your custom &Decider; function
- is a perfectly normal thing to do,
- if they don't impact the way you want to
- decide if the dependency file has changed.
+ These attributes may not be present at the time of the
+ first run. Without any prior build, no targets have been
+ created and no <filename>.sconsign</filename> DB file exists yet.
+ So you should always check whether the
+ <varname>prev_ni</varname> attribute in question is available
+ (use the Python <function>hasattr</function> method or a
+ <literal>try</literal>-<literal>except</literal> block).
+
+ </para>
+
+
+ <para>
+
+ The fourth argument <varname>repo_node</varname>
+ is the &Node; to use if it is not None when comparing &BuildInfo;.
+ This is typically only set when the target node only exists in a
+ &Repository;
</para>
<para>
- Another thing to look out for is the fact that the three
- attributes above may not be present at the time of the first run.
- Without any prior build, no targets have been created and no
- <filename>.sconsign</filename> DB file exists yet.
- So, you should always check whether the
- <varname>prev_ni</varname> attribute in question is available.
+ Note that ignoring some of the arguments
+ in your custom &Decider; function
+ is a perfectly normal thing to do,
+ if they don't impact the way you want to
+ decide if the dependency file has changed.
</para>
@@ -644,13 +648,14 @@ int main() { printf("Hello, world!\n"); }
<sconstruct>
env = Environment()
+
def config_file_decider(dependency, target, prev_ni, repo_node=None):
import os.path
# We always have to init the .csig value...
dep_csig = dependency.get_csig()
# .csig may not exist, because no target was built yet...
- if 'csig' not in dir(prev_ni):
+ if not prev_ni.hasattr("csig"):
return True
# Target file may not exist yet
if not os.path.exists(str(target.abspath)):
@@ -660,17 +665,18 @@ def config_file_decider(dependency, target, prev_ni, repo_node=None):
return True
return False
+
def update_file():
- f = open("test.txt","a")
- f.write("some line\n")
- f.close()
+ with open("test.txt", "a") as f:
+ f.write("some line\n")
+
update_file()
# Activate our own decider function
env.Decider(config_file_decider)
-env.Install("install","test.txt")
+env.Install("install", "test.txt")
</sconstruct>
</section>
diff --git a/doc/user/environments.xml b/doc/user/environments.xml
index d3e5d6d..0a5722b 100644
--- a/doc/user/environments.xml
+++ b/doc/user/environments.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">
@@ -90,8 +90,8 @@ no further substitutions can be made:
The string: "The string says: %STRING"
expands to: "The string says: The result is: final value"
-If a construction variable is not defined in an environment, then the
-null string is substituted:
+If a construction variable is not defined in an environment, then an
+empty string is substituted:
Construction variables:
FOO => 'value1',
@@ -348,7 +348,7 @@ environment, of directory names, suffixes, etc.
<para>
- An <literal>environment</literal>
+ An <firstterm>environment</firstterm>
is a collection of values that
can affect how a program executes.
&SCons; distinguishes between three
@@ -367,7 +367,7 @@ environment, of directory names, suffixes, etc.
<listitem>
<para>
- The <literal>external environment</literal>
+ The <firstterm>external environment</firstterm>
is the set of variables in the user's environment
at the time the user runs &SCons;.
These variables are available within the &SConscript; files
@@ -384,7 +384,7 @@ environment, of directory names, suffixes, etc.
<listitem>
<para>
- A &consenv;
+ A <firstterm>&consenv;</firstterm>
is a distinct object created within
a &SConscript; file and
which contains values that
@@ -408,13 +408,13 @@ environment, of directory names, suffixes, etc.
<listitem>
<para>
- An <literal>execution environment</literal>
+ An <firstterm>execution environment</firstterm>
is the values that &SCons; sets
when executing an external
command (such as a compiler or linker)
to build one or more targets.
Note that this is not the same as
- the <literal>external environment</literal>
+ the external environment
(see above).
See <xref linkend="sect-execution-environments"></xref>, below.
@@ -473,7 +473,7 @@ environment, of directory names, suffixes, etc.
<para>
- The <literal>external environment</literal>
+ The external environment
variable settings that
the user has in force
when executing &SCons;
@@ -596,7 +596,7 @@ int main() { }
construction variable values,
except that the user has explicitly specified use of the
GNU C compiler &gcc;,
- and further specifies that the <literal>-O2</literal>
+ and further specifies that the <option>-O2</option>
(optimization level two)
flag should be used when compiling the object file.
In other words, the explicit initializations of
@@ -627,7 +627,7 @@ int main() { }
<scons_example name="environments_ex6">
<file name="SConstruct" printme="1">
env = Environment()
-print("CC is: %s"%env['CC'])
+print("CC is: %s" % env['CC'])
</file>
</scons_example>
@@ -811,7 +811,7 @@ scons: `.' is up to date.
If a problem occurs when expanding a construction variable,
by default it is expanded to <literal>''</literal>
- (a null string), and will not cause scons to fail.
+ (an empty string), and will not cause scons to fail.
</para>
<scons_example name="environments_missing1">
@@ -996,8 +996,8 @@ env = DefaultEnvironment(tools=['gcc', 'gnulink'],
each tailored to a different way to build
some piece of software or other file.
If, for example, we need to build
- one program with the <literal>-O2</literal> flag
- and another with the <literal>-g</literal> (debug) flag,
+ one program with the <option>-O2</option> flag
+ and another with the <option>-g</option> (debug) flag,
we would do this like so:
</para>
@@ -1063,9 +1063,9 @@ int main() { }
each implicitly told &SCons; to generate an object file named
<filename>foo.o</filename>,
one with a &cv-link-CCFLAGS; value of
- <literal>-O2</literal>
+ <option>-O2</option>
and one with a &cv-link-CCFLAGS; value of
- <literal>-g</literal>.
+ <option>-g</option>.
&SCons; can't just decide that one of them
should take precedence over the other,
so it generates the error.
@@ -1279,7 +1279,7 @@ int main() { }
actually occurs relative
to when the targets get built
becomes apparent
- if we run &scons; without the <literal>-Q</literal>
+ if we run &scons; without the <option>-Q</option>
option:
</para>
@@ -1625,7 +1625,9 @@ env['ENV']['PATH'] = ['/usr/local/bin', '/bin', '/usr/bin']
Note that &SCons; does allow you to define
the directories in the &PATH; in a string,
separated by the pathname-separator character
- for your system (':' on POSIX systems, ';' on Windows):
+ for your system (':' on POSIX systems, ';' on Windows
+ or use <literal>os.pathsep</literal> for portability).
+
</para>
@@ -1761,10 +1763,11 @@ env.AppendENVPath('LIB', '/usr/local/lib')
Note that the added values are strings,
and if you want to add multiple directories to
a variable like <envar>$PATH</envar>,
- you must include the path separate character
+ you must include the path separator character
+ in the string
(<literal>:</literal> on Linux or POSIX,
- <literal>;</literal> on Windows)
- in the string.
+ <literal>;</literal> on Windows, or use
+ <literal>os.pathsep</literal> for portability).
</para>
@@ -1782,8 +1785,8 @@ env.AppendENVPath('LIB', '/usr/local/lib')
<para>
Normally when using a tool from the construction environment,
several different search locations are checked by default.
- This includes the <literal>Scons/Tools/</literal> directory
- inbuilt to scons and the directory <literal>site_scons/site_tools</literal>
+ This includes the <filename>Scons/Tools/</filename> directory
+ inbuilt to scons and the directory <filename>site_scons/site_tools</filename>
relative to the root SConstruct file.
</para>
diff --git a/doc/user/install.xml b/doc/user/install.xml
index db87521..d5ea4d8 100644
--- a/doc/user/install.xml
+++ b/doc/user/install.xml
@@ -92,8 +92,11 @@ int main() { printf("Hello, world!\n"); }
It can, however, be cumbersome to remember
(and type) the specific destination directory
- in which the program (or any other file)
- should be installed.
+ in which the program (or other file)
+ should be installed. A call to &Default; can be used to
+ add the directory to the list of default targets,
+ removing the need to type it,
+ but sometimes you don't want to install on every build.
This is an area where the &Alias;
function comes in handy,
allowing you, for example,
@@ -118,7 +121,8 @@ int main() { printf("Hello, world!\n"); }
This then yields the more natural
ability to install the program
- in its destination as follows:
+ in its destination as a separate
+ invocation, as follows:
</para>
@@ -328,6 +332,14 @@ int call_foo() {
</scons_output>
-->
+ <para>
+ On systems which expect a shared library to be installed both with
+ a name that indicates the version, for run-time resolution,
+ and as a plain name, for link-time resolution, the
+ &InstallVersionedLib; function can be used. Symbolic links
+ appropriate to the type of system will be generated based on
+ symlinks of the source library.
+ </para>
</section>
</chapter>
diff --git a/doc/user/less-simple.xml b/doc/user/less-simple.xml
index 1a32492..10f0c1a 100644
--- a/doc/user/less-simple.xml
+++ b/doc/user/less-simple.xml
@@ -100,7 +100,9 @@ int main() { printf("Hello, world!\n"); }
so that the order mimics that of an
assignment statement in most programming languages,
including Python:
- <literal>"program = source files"</literal>.)
+ <literal>"target = source files"</literal>. For an
+ alternative way to supply this information, see
+ <xref linkend="keyword-args"></xref>).
</para>
@@ -453,7 +455,7 @@ Program('program', src_files)
</section>
- <section>
+ <section id="keyword-args">
<title>Keyword Arguments</title>
<para>
diff --git a/doc/user/misc.xml b/doc/user/misc.xml
index a595e59..b093629 100644
--- a/doc/user/misc.xml
+++ b/doc/user/misc.xml
@@ -654,21 +654,22 @@ env.Command('directory_build_info',
</para>
<para>
- This issue may be overcome by using <literal>--enable-virtualenv</literal>
+ This issue may be overcome by using the
+ <option>--enable-virtualenv</option>
option. The option automatically imports virtualenv-related environment
variables to all created construction environment <literal>env['ENV']</literal>,
and modifies SCons PATH appropriately to prefer virtualenv's executables.
- Setting environment variable <literal>SCONS_ENABLE_VIRTUALENV=1</literal>
+ Setting environment variable <envar>SCONS_ENABLE_VIRTUALENV=1</envar>
will have same effect. If virtualenv support is enabled system-vide
- by the environment variable, it may be suppressed with
- <literal>--ignore-virtualenv</literal> option.
+ by the environment variable, it may be suppressed with the
+ <option>--ignore-virtualenv</option> option.
</para>
<para>
- Inside of SConscript, a global function <literal>Virtualenv</literal> is
+ Inside of &SConscript;, a global function <literal>Virtualenv</literal> is
available. It returns a path to virtualenv's home directory, or
- <literal>None</literal> if SCons is not running from virtualenv. Note,
- that this function returns a path even if SCons is run from an
+ <literal>None</literal> if &scons; is not running from virtualenv. Note
+ that this function returns a path even if &scons; is run from an
unactivated virtualenv.
</para>
diff --git a/doc/user/nodes.xml b/doc/user/nodes.xml
index 7d36a65..29f2270 100644
--- a/doc/user/nodes.xml
+++ b/doc/user/nodes.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">
@@ -299,7 +299,7 @@ int main() { printf("Hello, world!\n"); }
the <literal>object_list[0]</literal>
extracts an actual Node <emphasis>object</emphasis>
from the list,
- and the Python <literal>print</literal> statement
+ and the Python <function>print</function> function
converts the object to a string for printing.
</para>
diff --git a/doc/user/output.xml b/doc/user/output.xml
index f9e1a98..bae018a 100644
--- a/doc/user/output.xml
+++ b/doc/user/output.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">
@@ -47,7 +47,7 @@
<para>
A key aspect of creating a usable build configuration
- is providing good output from the build
+ is providing useful output from the build
so its users can readily understand
what the build is doing
and get information about how to control the build.
@@ -109,7 +109,7 @@ Type: 'scons program' to build the production program,
When the &SConstruct; or &SConscript; files
contain such a call to the &Help; function,
the specified help text will be displayed in response to
- the &SCons; <literal>-h</literal> option:
+ the &SCons; <option>-h</option> option:
</para>
@@ -191,7 +191,7 @@ if env['PLATFORM'] == 'win32':
standard list that describes the &SCons; command-line
options.
This list is also always displayed whenever
- the <literal>-H</literal> option is used.
+ the <option>-H</option> option is used.
</para>
@@ -325,7 +325,7 @@ foo.c
By only setting the appropriate
<envar>$*COMSTR</envar> variables
if the user specifies
- <literal>VERBOSE=1</literal>
+ <parameter class="option">VERBOSE=1</parameter>
on the command line,
the user has control
over how &SCons;
@@ -355,6 +355,17 @@ cc -o foo.o -c foo.c
cc -o foo foo.o
</screen>
+ <para>
+
+ A gentle reminder here: many of the commands for building come in
+ pairs, depending on whether the intent is to build an object for
+ use in a shared library or not. The command strings mirror this,
+ so it may be necessary to set, for example, both
+ <envar>CCCOMSTR</envar> and <envar>SHCCCOMSTR</envar>
+ to get the desired results.
+
+ </para>
+
</section>
<section>
@@ -411,7 +422,7 @@ f2.c
Note that the &Progress; function does not
arrange for a newline to be printed automatically
at the end of the string (as does the Python
- <literal>print</literal> statement),
+ <function>print</function> function),
and we must specify the
<literal>\n</literal>
that we want printed at the end of the configured string.
@@ -457,15 +468,15 @@ Program('f2.c')
<para>
Note that we also specified the
- <literal>overwrite=True</literal> argument
+ <parameter>overwrite=True</parameter> argument
to the &Progress; function,
which causes &SCons; to
"wipe out" the previous string with space characters
before printing the next &Progress; string.
Without the
- <literal>overwrite=True</literal> argument,
+ <parameter>overwrite=True</parameter> argument,
a shorter file name would not overwrite
- all of the charactes in a longer file name that
+ all of the charactes in a longer file name that
precedes it,
making it difficult to tell what the
actual file name is on the output.
@@ -512,11 +523,11 @@ Program('f2.c')
<para>
Note that here we have also used the
- <literal>interval=</literal>
+ <parameter>interval=</parameter>
keyword argument to have &SCons;
only print a new "spinner" string
once every five evaluated nodes.
- Using an <literal>interval=</literal> count,
+ Using an <parameter>interval=</parameter> count,
even with strings that use <literal>$TARGET</literal> like
our examples above,
can be a good way to lessen the
@@ -610,7 +621,7 @@ Progress(progress_function)
you can use in a python <function>atexit</function> function
to get a list of objects describing the actions that failed
while attempting to build targets. There can be more
- than one if you're using <literal>-j</literal>. Here's a
+ than one if you're using <option>-j</option>. Here's a
simple example:
</para>
@@ -636,7 +647,7 @@ atexit.register(print_build_failures)
it calls &GetBuildFailures; to fetch the list of failed objects.
See the man page
for the detailed contents of the returned objects;
- some of the more useful attributes are
+ some of the more useful attributes are
<literal>.node</literal>,
<literal>.errstr</literal>,
<literal>.filename</literal>, and
@@ -644,7 +655,7 @@ atexit.register(print_build_failures)
The <literal>filename</literal> is not necessarily
the same file as the <literal>node</literal>; the
<literal>node</literal> is the target that was
- being built when the error occurred, while the
+ being built when the error occurred, while the
<literal>filename</literal>is the file or dir that
actually caused the error.
Note: only call &GetBuildFailures; at the end of the
@@ -652,7 +663,7 @@ atexit.register(print_build_failures)
</para>
- <para>
+ <para>
Here is a more complete example showing how to
turn each element of &GetBuildFailures; into a string:
@@ -711,7 +722,7 @@ atexit.register(display_build_status)
</scons_example>
<para>
-
+
When this runs, you'll see the appropriate output:
</para>
diff --git a/doc/user/parseflags.xml b/doc/user/parseflags.xml
index 836b7f2..35c336e 100644
--- a/doc/user/parseflags.xml
+++ b/doc/user/parseflags.xml
@@ -80,14 +80,13 @@
<scons_example name="parseflags_ex1">
<file name="SConstruct" printme="1">
-from __future__ import print_function
env = Environment()
d = env.ParseFlags("-I/opt/include -L/opt/lib -lfoo")
-for k,v in sorted(d.items()):
+for k, v in sorted(d.items()):
if v:
print(k, v)
env.MergeFlags(d)
-env.Program('f1.c')
+env.Program("f1.c")
</file>
<file name="f1.c">
int main() { return 0; }
@@ -120,14 +119,13 @@ int main() { return 0; }
<scons_example name="parseflags_ex2">
<file name="SConstruct" printme="1">
-from __future__ import print_function
env = Environment()
d = env.ParseFlags("-whatever")
-for k,v in sorted(d.items()):
+for k, v in sorted(d.items()):
if v:
print(k, v)
env.MergeFlags(d)
-env.Program('f1.c')
+env.Program("f1.c")
</file>
<file name="f1.c">
int main() { return 0; }
@@ -147,14 +145,13 @@ env.Program('f1.c')
<scons_example name="parseflags_ex3">
<file name="SConstruct" printme="1">
-from __future__ import print_function
env = Environment()
d = env.ParseFlags(["-I/opt/include", ["-L/opt/lib", "-lfoo"]])
-for k,v in sorted(d.items()):
+for k, v in sorted(d.items()):
if v:
print(k, v)
env.MergeFlags(d)
-env.Program('f1.c')
+env.Program("f1.c")
</file>
<file name="f1.c">
int main() { return 0; }
@@ -175,14 +172,13 @@ int main() { return 0; }
<scons_example name="parseflags_ex4">
<file name="SConstruct" printme="1">
-from __future__ import print_function
env = Environment()
d = env.ParseFlags(["!echo -I/opt/include", "!echo -L/opt/lib", "-lfoo"])
-for k,v in sorted(d.items()):
+for k, v in sorted(d.items()):
if v:
print(k, v)
env.MergeFlags(d)
-env.Program('f1.c')
+env.Program("f1.c")
</file>
<file name="f1.c">
int main() { return 0; }
diff --git a/doc/user/simple.xml b/doc/user/simple.xml
index acc438b..138ff54 100644
--- a/doc/user/simple.xml
+++ b/doc/user/simple.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">
@@ -76,7 +76,8 @@ main()
<para>
And here's how to build it using &SCons;.
- Enter the following into a file named &SConstruct;:
+ Save the code above into <filename>hello.c</filename>,
+ and enter the following into a file named &SConstruct;:
</para>
@@ -98,7 +99,7 @@ int main() { printf("Hello, world!\n"); }
and the input file from
which you want it built
(the <filename>hello.c</filename> file).
- &b-link-Program; is a <firstterm>builder_method</firstterm>,
+ &b-link-Program; is a <firstterm>&builder_method;</firstterm>,
a Python call that tells &SCons; that you want to build an
executable program.
@@ -142,10 +143,8 @@ int main() { printf("Hello, world!\n"); }
Second, notice that the same input &SConstruct; file,
without any changes,
generates the correct output file names on both systems:
- <filename>hello.o</filename> and <filename>hello</filename>
- on POSIX systems,
- <filename>hello.obj</filename> and <filename>hello.exe</filename>
- on Windows systems.
+ &hello_o; and &hello; on POSIX systems,
+ &hello_obj; and &hello_exe; on Windows systems.
This is a simple example of how &SCons;
makes it extremely easy to
write portable software builds.
@@ -274,7 +273,7 @@ public class Example1
When using &SCons;, it is unnecessary to add special
commands or target names to clean up after a build.
Instead, you simply use the
- <literal>-c</literal> or <literal>--clean</literal>
+ <option>-c</option> or <option>--clean</option>
option when you invoke &SCons;,
and &SCons; removes the appropriate built files.
So if we build our example above
@@ -388,8 +387,8 @@ Program('hello.c') # "hello.c" is the source file.
does <emphasis>not</emphasis>
affect the order in which &SCons;
actually builds the programs and object files
- you want it to build.<footnote>
- <para>In programming parlance,
+ you want it to build
+ <footnote><para>In programming parlance,
the &SConstruct; file is
<emphasis>declarative</emphasis>,
meaning you tell &SCons; what you want done
@@ -398,22 +397,20 @@ Program('hello.c') # "hello.c" is the source file.
where you specify explicitly the order in
which to do things.
</para>
- </footnote>
+ </footnote>.
In other words, when you call the &b-link-Program; builder
(or any other builder method),
you're not telling &SCons; to build
- the program at the instant the builder method is called.
- Instead, you're telling &SCons; to build the program
- that you want, for example,
- a program built from a file named &hello_c;,
- and it's up to &SCons; to build that program
- (and any other files) whenever it's necessary.
- (We'll learn more about how
- &SCons; decides when building or rebuilding a file
- is necessary in <xref linkend="chap-depends"></xref>, below.)
-
+ the program at that moment.
+ Instead, you're telling &SCons; what you want accomplished,
+ and it's up to &SCons; to figure out how to do that, and to
+ take those steps if/when it's necessary.
+ We'll learn more about how
+ &SCons; decides when building or rebuilding a target
+ is necessary in <xref linkend="chap-depends"></xref>, below.
+
</para>
-
+
<para>
&SCons; reflects this distinction between
@@ -433,9 +430,9 @@ Program('hello.c') # "hello.c" is the source file.
<para>
Let's clarify this with an example.
- Python has a <literal>print</literal> statement that
+ Python has a <function>print</function> function that
prints a string of characters to the screen.
- If we put <literal>print</literal> statements around
+ If we put <function>print</function> calls around
our calls to the &b-Program; builder method:
</para>
@@ -459,8 +456,8 @@ int main() { printf("Goodbye, world!\n"); }
<para>
Then when we execute &SCons;,
- we see the output from the <literal>print</literal>
- statements in between the messages about
+ 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
Python statements are being executed:
@@ -473,13 +470,25 @@ int main() { printf("Goodbye, world!\n"); }
<para>
- Notice also that &SCons; built the &goodbye; program first,
+ Notice that &SCons; built the &goodbye; program first,
even though the "reading &SConscript;" output
- shows that we called <literal>Program('hello.c')</literal>
+ shows that we called <function>Program('hello.c')</function>
first in the &SConstruct; file.
</para>
+ <para>
+
+ Notice also that &SCons; was able to infer a lot of information
+ from the two &Program; calls. Because
+ &hello_c; and <filename>goodbye.c</filename>
+ were recognized as C-language source files, it knew to build
+ the intermediate target files &hello_o; and &goodbye_o;
+ and the final files &hello; and &goodbye;
+ It was not necessary to program &scons; beyond just calling &Program;.
+
+ </para>
+
</section>
</section>
diff --git a/runtest.py b/runtest.py
index 554b4f6..57b4ba4 100755
--- a/runtest.py
+++ b/runtest.py
@@ -69,8 +69,6 @@ Environment Variables:
TESTCMD_VERBOSE: turn on verbosity in TestCommand\
"""
-from __future__ import print_function
-
import getopt
import glob
import os
@@ -662,7 +660,7 @@ else:
# sys.stderr.write("to:%s\n"%tp)
for path in glob.glob(tp):
if os.path.isdir(path):
- if path.startswith('src'):
+ if path.startswith('src') or path.startswith('testing'):
for p in find_Tests_py(path):
unittests.append(p)
elif path.startswith('test'):
diff --git a/site_scons/SConsRevision.py b/site_scons/SConsRevision.py
index 11de670..f6f7a71 100644
--- a/site_scons/SConsRevision.py
+++ b/site_scons/SConsRevision.py
@@ -29,12 +29,14 @@ def SCons_revision(target, source, env):
contents = contents.replace('__REVISION' + '__', env['REVISION'])
contents = contents.replace('__VERSION' + '__', env['VERSION'])
contents = contents.replace('__NULL' + '__', '')
- open(t, 'w').write(contents)
+
+ with open(t,'w') as of:
+ of.write(contents)
except UnicodeDecodeError as e:
print("Error decoding file:%s just copying no revision edit")
- with open(s, 'rb') as fp:
+ with open(s, 'rb') as fp, open(t, 'wb') as of:
contents = fp.read()
- open(t, 'wb').write(contents)
+ of.write(contents)
os.chmod(t, os.stat(s)[0]) \ No newline at end of file
diff --git a/src/CHANGES.txt b/src/CHANGES.txt
index 53f4d48..025e046 100755
--- a/src/CHANGES.txt
+++ b/src/CHANGES.txt
@@ -5,6 +5,8 @@
Change Log
NOTE: The 4.0.0 Release of SCons will drop Python 2.7 Support
+NOTE: Please add your name below in alphabetical order by last name.
+NOTE: Please include a reference to any Issues resolved by your changes in the bullet(s) you add
RELEASE VERSION/DATE TO BE FILLED IN LATER
@@ -15,12 +17,39 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
- Added C:\msys64\mingw64\bin to default mingw and clang windows PATH's. This
is a reasonable default and also aligns with changes in Appveyor's VS2019 image.
- Drop support for Python 2.7. SCons will be Python 3.5+ going forward.
+ - Change SCons.Node.ValueWithMemo to consider any name passed when memoizing Value() nodes
+ - Fix Github Issue #3550 - When using Substfile() with a value like Z:\mongo\build\install\bin
+ the implementation using re.sub() would end up interpreting the string and finding regex escape
+ characters where it should have been simply replacing existing text. Switched to use string.replace().
+ - Fix Github Issue #2904 - Provide useful error message when more than one Configure Contexts are opened.
+ Only one open is allowed. You must call conf.Finish() to complete the currently open one before creating another
+
+ From Jeremy Elson:
+ - Updated design doc to use the correct syntax for Depends()
From Adam Gross:
- Added support for scanning multiple entries in an action string if
IMPLICIT_COMMAND_DEPENDENCIES is set to 2. This opts into more thorough
action scanning where every string in the command is scanned to determine
if it is a non-source and non-target path.
+ - Added support for taking instances of the Value class as implicit
+ dependencies.
+ - Added new module SCons.Scanner.Python to allow scanning .py files.
+ - Added support for explicitly passing a name when creating Value() nodes. This may be useful
+ when the value can't be converted to a string or if having a name is otherwise desirable.
+
+ From Andrew Morrow:
+ - Fix Issue #3469 - Fixed improper reuse of temporary and compiled files by Configure when changing
+ the order and/or number of tests. This is done by using the hash of the generated temporary files
+ content and (For the target files) the hash of the action.
+ So where previously files would be named:
+ - config_1.c, config_1.o, config_1
+ The will now be named (For example)
+ - conftest_68b375d16e812c43e6d72d6e93401e7c_0.c,
+ conftest_68b375d16e812c43e6d72d6e93401e7c_0_5713f09fc605f46b2ab2f7950455f187.o
+ or
+ conftest_68b375d16e812c43e6d72d6e93401e7c_0.o
+ conftest_68b375d16e812c43e6d72d6e93401e7c_0_5713f09fc605f46b2ab2f7950455f187 (for executable)
From Mathew Robinson:
- Improve performance of Subst by preventing unnecessary frame
@@ -36,6 +65,16 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
- str.format syntax errors fixed
- a bunch of linter/checker syntax fixups
- Convert remaining uses of insecure/deprecated mktemp method.
+ - Clean up some duplications in manpage. Clarify portion of manpage on Dir and File nodes.
+ - Reduce needless list conversions.
+ - Fixed regex in Python scanner.
+ - Accommodate VS 2017 Express - it's got a more liberal license then VS
+ Community, so some people prefer it (from 2019, no more Express)
+ - vswhere call should also now work even if programs aren't on the C: drive.
+ - Add an alternate warning message cl.exe is not found and msvc config
+ cache is in use (SCONS_CACHE_MSVC_CONFIG was given) - config cache
+ may be out of date.
+ - Script/Main.py now uses importlib instead of imp module.
RELEASE 3.1.2 - Mon, 17 Dec 2019 02:06:27 +0000
diff --git a/src/README.txt b/src/README.txt
index 40d7217..01ef436 100644
--- a/src/README.txt
+++ b/src/README.txt
@@ -22,13 +22,13 @@ LATEST VERSION
Before going further, you can check that this package you have is
the latest version by checking the SCons download page at:
- http://www.scons.org/download.html
+ https://scons.org/pages/download.html
EXECUTION REQUIREMENTS
======================
-Running SCons requires Python version 2.7.* or 3.5.* and above. There should be
+Running SCons requires Python 3.5.* and above. There should be
no other dependencies or requirements to run SCons. (There is, however,
an additional requirement to *install* SCons from this particular
package; see the next section.)
@@ -193,10 +193,6 @@ You may subscribe to the mailing list by sending email to:
scons-users-join@scons.org
-There is also a low-volume mailing list available for announcements
-about SCons. Subscribe by sending email to:
-
- announce-subscribe@scons.tigris.org
There are other mailing lists available for SCons developers, for
notification of SCons code changes, and for notification of updated
@@ -243,7 +239,8 @@ many contributors, including but not at all limited to:
- Anatoly Techtonik
- Christoph Wiedemann
- Russel Winder
+- Mats Wichmann
\... and many others.
-Copyright (c) 2001 - 2019 The SCons Foundation
+Copyright (c) 2001 - 2020 The SCons Foundation
diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in
index 3125824..3c2c0c2 100644
--- a/src/engine/MANIFEST.in
+++ b/src/engine/MANIFEST.in
@@ -40,6 +40,7 @@ SCons/Scanner/Fortran.py
SCons/Scanner/IDL.py
SCons/Scanner/LaTeX.py
SCons/Scanner/Prog.py
+SCons/Scanner/Python.py
SCons/Scanner/RC.py
SCons/Scanner/SWIG.py
SCons/SConf.py
@@ -140,6 +141,7 @@ SCons/Tool/pdf.py
SCons/Tool/pdflatex.py
SCons/Tool/pdftex.py
SCons/Tool/PharLapCommon.py
+SCons/Tool/python.py
SCons/Tool/qt.py
SCons/Tool/rmic.py
SCons/Tool/rpcgen.py
diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py
index 3f5e4b8..8a8cf27 100644
--- a/src/engine/SCons/Action.py
+++ b/src/engine/SCons/Action.py
@@ -628,17 +628,9 @@ class _ActionAction(ActionBase):
"""
In python 3, and in some of our tests, sys.stdout is
a String io object, and it takes unicode strings only
- In other cases it's a regular Python 2.x file object
- which takes strings (bytes), and if you pass those a
- unicode object they try to decode with 'ascii' codec
- which fails if the cmd line has any hi-bit-set chars.
- This code assumes s is a regular string, but should
- work if it's unicode too.
+ This code assumes s is a regular string.
"""
- try:
- sys.stdout.write(s + u"\n")
- except UnicodeDecodeError:
- sys.stdout.write(s + "\n")
+ sys.stdout.write(s + "\n")
def __call__(self, target, source, env,
exitstatfunc=_null,
@@ -677,7 +669,7 @@ class _ActionAction(ActionBase):
source = executor.get_all_sources()
t = ' and '.join(map(str, target))
l = '\n '.join(self.presub_lines(env))
- out = u"Building %s with action:\n %s\n" % (t, l)
+ out = "Building %s with action:\n %s\n" % (t, l)
sys.stdout.write(out)
cmd = None
if show and self.strfunction:
diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py
index 3303750..4784abf 100644
--- a/src/engine/SCons/ActionTests.py
+++ b/src/engine/SCons/ActionTests.py
@@ -37,10 +37,8 @@ class GlobalActFunc(object):
pass
-import collections
import io
import os
-import re
import sys
import types
import unittest
@@ -339,14 +337,6 @@ class ActionTestCase(unittest.TestCase):
# a singleton list returns the contained action
test_positional_args(cmd_action, ["string"])
- try:
- unicode
- except NameError:
- pass
- else:
- a2 = eval("SCons.Action.Action(u'string')")
- assert isinstance(a2, SCons.Action.CommandAction), a2
-
def line_action(a):
assert isinstance(a, SCons.Action.CommandAction), a
assert a.cmd_list == ["explicit", "command", "line"], a.cmd_list
diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py
index e3fb396..3f0be63 100644
--- a/src/engine/SCons/Builder.py
+++ b/src/engine/SCons/Builder.py
@@ -100,7 +100,7 @@ There are the following methods for internal use within this module:
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import collections
+from collections import UserDict, UserList
import SCons.Action
import SCons.Debug
@@ -197,7 +197,7 @@ class DictEmitter(SCons.Util.Selector):
target, source = emitter(target, source, env)
return (target, source)
-class ListEmitter(collections.UserList):
+class ListEmitter(UserList):
"""A callable list of emitters that calls each in sequence,
returning the result.
"""
@@ -215,7 +215,7 @@ misleading_keywords = {
'sources' : 'source',
}
-class OverrideWarner(collections.UserDict):
+class OverrideWarner(UserDict):
"""A class for warning about keyword arguments that we use as
overrides in a Builder call.
@@ -224,13 +224,13 @@ class OverrideWarner(collections.UserDict):
warnings once, no matter how many Builders are invoked.
"""
def __init__(self, dict):
- collections.UserDict.__init__(self, dict)
+ UserDict.__init__(self, dict)
if SCons.Debug.track_instances: logInstanceCreation(self, 'Builder.OverrideWarner')
self.already_warned = None
def warn(self):
if self.already_warned:
return
- for k in list(self.keys()):
+ for k in self.keys():
if k in misleading_keywords:
alt = misleading_keywords[k]
msg = "Did you mean to use `%s' instead of `%s'?" % (alt, k)
@@ -647,6 +647,8 @@ class BuilderBase(object):
env_kw = kw
else:
env_kw = self.overrides
+
+ # TODO if env_kw: then the following line. there's no purpose in calling if no overrides.
env = env.Override(env_kw)
return self._execute(env, target, source, OverrideWarner(kw), ekw)
diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py
index f28e201..d509219 100644
--- a/src/engine/SCons/BuilderTests.py
+++ b/src/engine/SCons/BuilderTests.py
@@ -20,8 +20,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.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -33,7 +31,7 @@ import SCons.compat
def Func():
pass
-import collections
+from collections import UserList
import io
import os.path
import re
@@ -173,7 +171,7 @@ class MyNode_without_target_from_source(object):
def builder_set(self, builder):
self.builder = builder
def has_builder(self):
- return not self.builder is None
+ return self.builder is not None
def set_explicit(self, is_explicit):
self.is_explicit = is_explicit
def has_explicit_builder(self):
@@ -205,7 +203,7 @@ class BuilderTestCase(unittest.TestCase):
"""Test simple Builder creation
"""
builder = SCons.Builder.Builder(action="foo")
- assert not builder is None, builder
+ assert builder is not None, builder
builder = SCons.Builder.Builder(action="foo", OVERRIDE='x')
x = builder.overrides['OVERRIDE']
assert x == 'x', x
@@ -256,7 +254,7 @@ class BuilderTestCase(unittest.TestCase):
assert not hasattr(n2, 'env')
l = [1]
- ul = collections.UserList([2])
+ ul = UserList([2])
try:
l.extend(ul)
except TypeError:
@@ -308,22 +306,6 @@ class BuilderTestCase(unittest.TestCase):
#be = target.get_build_env()
#assert be['VAR'] == 'foo', be['VAR']
- try: unicode
- except NameError:
- uni = str
- else:
- uni = unicode
-
- target = builder(env, target = uni('n12 n13'),
- source = [uni('n14 n15')])[0]
- assert target.name == uni('n12 n13')
- assert target.sources[0].name == uni('n14 n15')
-
- target = builder(env, target = [uni('n16 n17')],
- source = uni('n18 n19'))[0]
- assert target.name == uni('n16 n17')
- assert target.sources[0].name == uni('n18 n19')
-
n20 = MyNode_without_target_from_source('n20')
flag = 0
try:
@@ -429,7 +411,7 @@ class BuilderTestCase(unittest.TestCase):
return Foo(target)
builder = SCons.Builder.Builder(target_factory = FooFactory)
assert builder.target_factory is FooFactory
- assert not builder.source_factory is FooFactory
+ assert builder.source_factory is not FooFactory
def test_source_factory(self):
"""Test a Builder that creates source nodes of a specified class
@@ -440,7 +422,7 @@ class BuilderTestCase(unittest.TestCase):
global Foo
return Foo(source)
builder = SCons.Builder.Builder(source_factory = FooFactory)
- assert not builder.target_factory is FooFactory
+ assert builder.target_factory is not FooFactory
assert builder.source_factory is FooFactory
def test_splitext(self):
@@ -737,7 +719,7 @@ class BuilderTestCase(unittest.TestCase):
with open(str(t), 'w') as f:
f.write("function2\n")
for t in tlist:
- if not t in list(map(str, target)):
+ if t not in list(map(str, target)):
with open(t, 'w') as f:
f.write("function2\n")
return 1
@@ -768,7 +750,7 @@ class BuilderTestCase(unittest.TestCase):
with open(str(t), 'w') as f:
f.write("function3\n")
for t in tlist:
- if not t in list(map(str, target)):
+ if t not in list(map(str, target)):
with open(t, 'w') as f:
f.write("function3\n")
return 1
@@ -821,7 +803,7 @@ class BuilderTestCase(unittest.TestCase):
assert s == ['aaa.bar'], s
builder3 = SCons.Builder.Builder(action='bld3')
- assert not builder3.src_builder is builder1.src_builder
+ assert builder3.src_builder is not builder1.src_builder
builder4 = SCons.Builder.Builder(action='bld4',
src_suffix='.i',
diff --git a/src/engine/SCons/Conftest.py b/src/engine/SCons/Conftest.py
index c24adf8..4491884 100644
--- a/src/engine/SCons/Conftest.py
+++ b/src/engine/SCons/Conftest.py
@@ -315,8 +315,8 @@ int main(void) {
return ret
-def CheckHeader(context, header_name, header = None, language = None,
- include_quotes = None):
+def CheckHeader(context, header_name, header=None, language=None,
+ include_quotes=None):
"""
Configure check for a C or C++ header file "header_name".
Optional "header" can be defined to do something before including the
diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py
index a69d8b0..2bac41e 100644
--- a/src/engine/SCons/Defaults.py
+++ b/src/engine/SCons/Defaults.py
@@ -31,8 +31,6 @@ from distutils.msvccompiler.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import division
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
diff --git a/src/engine/SCons/DefaultsTests.py b/src/engine/SCons/DefaultsTests.py
index 2cbad70..34941bc 100644
--- a/src/engine/SCons/DefaultsTests.py
+++ b/src/engine/SCons/DefaultsTests.py
@@ -29,8 +29,6 @@ import os
import sys
import unittest
-from collections import UserDict
-
import TestCmd
import SCons.Errors
diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py
index 3e23196..00379e1 100644
--- a/src/engine/SCons/Environment.py
+++ b/src/engine/SCons/Environment.py
@@ -584,7 +584,7 @@ class SubstitutionEnvironment(object):
out,err = p.communicate()
status = p.wait()
if err:
- sys.stderr.write(u"" + err)
+ sys.stderr.write("" + err)
if status:
raise OSError("'%s' exited %d" % (command, status))
return out
@@ -1854,7 +1854,7 @@ class Base(SubstitutionEnvironment):
uniq = {}
for executor in [n.get_executor() for n in nodes]:
uniq[executor] = 1
- for executor in list(uniq.keys()):
+ for executor in uniq.keys():
executor.add_pre_action(action)
return nodes
@@ -1864,7 +1864,7 @@ class Base(SubstitutionEnvironment):
uniq = {}
for executor in [n.get_executor() for n in nodes]:
uniq[executor] = 1
- for executor in list(uniq.keys()):
+ for executor in uniq.keys():
executor.add_post_action(action)
return nodes
@@ -2220,10 +2220,10 @@ class Base(SubstitutionEnvironment):
else:
return [self.subst(arg)]
- def Value(self, value, built_value=None):
+ def Value(self, value, built_value=None, name=None):
"""
"""
- return SCons.Node.Python.ValueWithMemo(value, built_value)
+ return SCons.Node.Python.ValueWithMemo(value, built_value, name)
def VariantDir(self, variant_dir, src_dir, duplicate=1):
variant_dir = self.arg2nodes(variant_dir, self.fs.Dir)[0]
diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml
index 35e4bd8..e1d5e74 100644
--- a/src/engine/SCons/Environment.xml
+++ b/src/engine/SCons/Environment.xml
@@ -65,15 +65,6 @@ env['BUILDERS']['NewBuilder'] = foo
</summary>
</cvar>
-<cvar name="Dir">
-<summary>
-<para>
-A function that converts a string
-into a Dir instance relative to the target being built.
-</para>
-</summary>
-</cvar>
-
<cvar name="ENV">
<summary>
<para>
@@ -130,15 +121,6 @@ env = Environment(ENV = {'PATH' : os.environ['PATH']})
</summary>
</cvar>
-<cvar name="File">
-<summary>
-<para>
-A function that converts a string into a File instance relative to the
-target being built.
-</para>
-</summary>
-</cvar>
-
<cvar name="SCANNERS">
<summary>
<para>
@@ -460,6 +442,8 @@ including another alias.
can be called multiple times for the same
alias to add additional targets to the alias,
or additional actions to the list for this alias.
+Aliases are global even if set through
+the construction environment method.
</para>
<para>
@@ -1163,17 +1147,16 @@ env.Decider('content')
</example_commands>
<para>
-In addition to the above already-available functions,
-the
+In addition to the above already-available functions, the
<varname>function</varname>
-argument may be an actual Python function
-that takes the following three arguments:
+argument may be a Python function you supply.
+Such a function must accept the following four arguments:
</para>
<para>
<variablelist>
<varlistentry>
-<term><parameter>dependency</parameter></term>
+<term><parameter class="function">dependency</parameter></term>
<listitem>
<para>
The Node (file) which
@@ -1187,7 +1170,7 @@ was built.
</listitem>
</varlistentry>
<varlistentry>
-<term><parameter>target</parameter></term>
+<term><parameter class="function">target</parameter></term>
<listitem>
<para>
The Node (file) being built.
@@ -1200,7 +1183,7 @@ has "changed."
</listitem>
</varlistentry>
<varlistentry>
-<term><parameter>prev_ni</parameter></term>
+<term><parameter class="function">prev_ni</parameter></term>
<listitem>
<para>
Stored information about the state of the
@@ -1216,12 +1199,17 @@ size, or content signature.
</listitem>
</varlistentry>
<varlistentry>
-<term><parameter>repo_node</parameter></term>
+<term><parameter class="function">repo_node</parameter></term>
<listitem>
<para>
-Use this node instead of the one specified by
+If set, use this Node instead of the one specified by
<varname>dependency</varname>
- to determine if the dependency has changed.
+to determine if the dependency has changed.
+This argument is optional so should be written
+as a default argument (typically it would be
+written as <literal>repo_node=None</literal>).
+A caller will normally only set this if the
+target only exists in a Repository.
</para>
</listitem>
</varlistentry>
@@ -1351,11 +1339,10 @@ cc_values = env.Dictionary('CC', 'CCFLAGS', 'CCCOM')
</arguments>
<summary>
<para>
-This returns a Directory Node,
-an object that represents the specified directory
-<varname>name</varname>.
+Returns Directory Node(s).
+A Directory Node is an object that represents a directory.
<varname>name</varname>
-can be a relative or absolute path.
+can be a relative or absolute path or a list of such paths.
<varname>directory</varname>
is an optional directory that will be used as the parent directory.
If no
@@ -1366,7 +1353,10 @@ is specified, the current script's directory is used as the parent.
<para>
If
<varname>name</varname>
-is a list, SCons returns a list of Dir nodes.
+is a single pathname, the corresponding node is returned.
+If
+<varname>name</varname>
+is a list, SCons returns a list of nodes.
Construction variables are expanded in
<varname>name</varname>.
</para>
@@ -1511,20 +1501,24 @@ if Execute("mkdir sub/dir/ectory"):
</arguments>
<summary>
<para>
-This returns a
-File Node,
-an object that represents the specified file
-<varname>name</varname>.
+Returns File Node(s).
+A File Node is an object that represents a file.
<varname>name</varname>
-can be a relative or absolute path.
+can be a relative or absolute path or a list of such paths.
<varname>directory</varname>
is an optional directory that will be used as the parent directory.
+If no
+<varname>directory</varname>
+is specified, the current script's directory is used as the parent.
</para>
<para>
If
<varname>name</varname>
-is a list, SCons returns a list of File nodes.
+is a single pathname, the corresponding node is returned.
+If
+<varname>name</varname>
+is a list, SCons returns a list of nodes.
Construction variables are expanded in
<varname>name</varname>.
</para>
@@ -3087,7 +3081,7 @@ env.Tool('opengl', toolpath = ['build/tools'])
<scons_function name="Value">
<arguments>
-(value, [built_value])
+(value, [built_value], [name])
</arguments>
<summary>
<para>
@@ -3102,6 +3096,10 @@ will be rebuilt.
files are up-to-date.)
When using timestamp source signatures, Value Nodes'
timestamps are equal to the system time when the Node is created.
+<varname>name</varname> can be provided as an alternative name
+for the resulting <literal>Value</literal> node; this is advised
+if the <varname>value</varname> parameter can't be converted to
+a string.
</para>
<para>
diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py
index f3779c7..a9ec674 100644
--- a/src/engine/SCons/EnvironmentTests.py
+++ b/src/engine/SCons/EnvironmentTests.py
@@ -20,9 +20,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.
#
-
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -236,7 +233,7 @@ class SubstitutionTestCase(unittest.TestCase):
"""
env = SubstitutionEnvironment(XXX = 'x')
assert 'XXX' in env
- assert not 'YYY' in env
+ assert 'YYY' not in env
def test_items(self):
"""Test the SubstitutionEnvironment items() method
@@ -265,11 +262,6 @@ class SubstitutionTestCase(unittest.TestCase):
assert isinstance(nodes[0], X)
assert nodes[0].name == "Util.py UtilTests.py", nodes[0].name
- nodes = env.arg2nodes(u"Util.py UtilTests.py", Factory)
- assert len(nodes) == 1, nodes
- assert isinstance(nodes[0], X)
- assert nodes[0].name == u"Util.py UtilTests.py", nodes[0].name
-
nodes = env.arg2nodes(["Util.py", "UtilTests.py"], Factory)
assert len(nodes) == 2, nodes
assert isinstance(nodes[0], X)
@@ -1759,7 +1751,7 @@ def exists(env):
env2.Dictionary('ZZZ')[5] = 6
assert env1.Dictionary('XXX') is env2.Dictionary('XXX')
assert 4 in env2.Dictionary('YYY')
- assert not 4 in env1.Dictionary('YYY')
+ assert 4 not in env1.Dictionary('YYY')
assert 5 in env2.Dictionary('ZZZ')
assert 5 not in env1.Dictionary('ZZZ')
@@ -3289,6 +3281,10 @@ def generate(env):
v3 = env.Value('c', 'build-c')
assert v3.value == 'c', v3.value
+ v4 = env.Value(b'\x00\x0F', name='name')
+ assert v4.value == b'\x00\x0F', v4.value
+ assert v4.name == 'name', v4.name
+
def test_Environment_global_variable(self):
"""Test setting Environment variable to an Environment.Base subclass"""
@@ -3547,8 +3543,8 @@ class OverrideEnvironmentTestCase(unittest.TestCase,TestEnvironmentFixture):
assert 'YYY' in env
assert 'YYY' in env2
assert 'YYY' in env3
- assert not 'ZZZ' in env
- assert not 'ZZZ' in env2
+ assert 'ZZZ' not in env
+ assert 'ZZZ' not in env2
assert 'ZZZ' in env3
def test_items(self):
diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py
index 28bb6ad..fb2224f 100644
--- a/src/engine/SCons/Executor.py
+++ b/src/engine/SCons/Executor.py
@@ -26,8 +26,6 @@ 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.
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import collections
diff --git a/src/engine/SCons/JobTests.py b/src/engine/SCons/JobTests.py
index 2e3af4f..9c9bb41 100644
--- a/src/engine/SCons/JobTests.py
+++ b/src/engine/SCons/JobTests.py
@@ -42,8 +42,8 @@ def get_cpu_nums():
ncpus = os.sysconf( "SC_NPROCESSORS_ONLN" )
if isinstance(ncpus, int) and ncpus > 0:
return ncpus
- else: # OSX:
- return int( os.popen2( "sysctl -n hw.ncpu")[1].read() )
+ else: # OSX:
+ return int(os.popen2("sysctl -n hw.ncpu")[1].read() )
# Windows:
if "NUMBER_OF_PROCESSORS" in os.environ:
ncpus = int(os.environ["NUMBER_OF_PROCESSORS"])
diff --git a/src/engine/SCons/Memoize.py b/src/engine/SCons/Memoize.py
index 5bdcf42..0595fdf 100644
--- a/src/engine/SCons/Memoize.py
+++ b/src/engine/SCons/Memoize.py
@@ -20,8 +20,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.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
__doc__ = """Memoizer
diff --git a/src/engine/SCons/Node/AliasTests.py b/src/engine/SCons/Node/AliasTests.py
index 5d9c799..27b75b3 100644
--- a/src/engine/SCons/Node/AliasTests.py
+++ b/src/engine/SCons/Node/AliasTests.py
@@ -93,7 +93,7 @@ class AliasTestCase(unittest.TestCase):
a2 = SCons.Node.Alias.Alias('a')
assert a2.name == 'a', a2.name
- assert not a1 is a2
+ assert a1 is not a2
assert a1.name == a2.name
class AliasNodeInfoTestCase(unittest.TestCase):
diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py
index e1d6f68..bb965db 100644
--- a/src/engine/SCons/Node/FS.py
+++ b/src/engine/SCons/Node/FS.py
@@ -31,8 +31,6 @@ 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.
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import fnmatch
@@ -44,6 +42,7 @@ import sys
import time
import codecs
from itertools import chain
+import importlib.util
import SCons.Action
import SCons.Debug
@@ -1427,22 +1426,10 @@ class FS(LocalFS):
This can be useful when we want to determine a toolpath based on a python module name"""
dirpath = ''
- if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0,1,2,3,4)):
- # Python2 Code
- import imp
- splitname = modulename.split('.')
- srchpths = sys.path
- for item in splitname:
- file, path, desc = imp.find_module(item, srchpths)
- if file is not None:
- path = os.path.dirname(path)
- srchpths = [path]
- dirpath = path
- else:
- # Python3 Code
- import importlib.util
- modspec = importlib.util.find_spec(modulename)
- dirpath = os.path.dirname(modspec.origin)
+
+ # Python3 Code
+ modspec = importlib.util.find_spec(modulename)
+ dirpath = os.path.dirname(modspec.origin)
return self._lookup(dirpath, None, Dir, True)
@@ -1549,9 +1536,7 @@ class Dir(Base):
self.repositories = []
self.srcdir = None
- self.entries = {}
- self.entries['.'] = self
- self.entries['..'] = self.dir
+ self.entries = {'.': self, '..': self.dir}
self.cwd = self
self.searched = 0
self._sconsign = None
@@ -1612,7 +1597,7 @@ class Dir(Base):
This clears any cached information that is invalidated by changing
the repository."""
- for node in list(self.entries.values()):
+ for node in self.entries.values():
if node != self.dir:
if node != self and isinstance(node, Dir):
node.__clearRepositoryCache(duplicate)
@@ -1623,7 +1608,7 @@ class Dir(Base):
except AttributeError:
pass
if duplicate is not None:
- node.duplicate=duplicate
+ node.duplicate = duplicate
def __resetDuplicate(self, node):
if node != self:
@@ -2306,10 +2291,8 @@ class RootDir(Dir):
self._morph()
self.duplicate = 0
- self._lookupDict = {}
+ self._lookupDict = {'': self, '/': self}
- self._lookupDict[''] = self
- self._lookupDict['/'] = self
self.root = self
# The // entry is necessary because os.path.normpath()
# preserves double slashes at the beginning of a path on Posix
@@ -2329,9 +2312,7 @@ class RootDir(Dir):
self.repositories = []
self.srcdir = None
- self.entries = {}
- self.entries['.'] = self
- self.entries['..'] = self.dir
+ self.entries = {'.': self, '..': self.dir}
self.cwd = self
self.searched = 0
self._sconsign = None
@@ -3746,7 +3727,7 @@ class FileFinder(object):
if verbose and not callable(verbose):
if not SCons.Util.is_String(verbose):
verbose = "find_file"
- _verbose = u' %s: ' % verbose
+ _verbose = ' %s: ' % verbose
verbose = lambda s: sys.stdout.write(_verbose + s)
filedir, filename = os.path.split(filename)
diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py
index 9c19481..3f2cb0e 100644
--- a/src/engine/SCons/Node/FSTests.py
+++ b/src/engine/SCons/Node/FSTests.py
@@ -20,8 +20,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.
#
-from __future__ import division, print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -465,10 +463,7 @@ class VariantDirTestCase(unittest.TestCase):
def __init__(self, duplicate, link, symlink, copy):
self.duplicate = duplicate
- self.have = {}
- self.have['hard'] = link
- self.have['soft'] = symlink
- self.have['copy'] = copy
+ self.have = {'hard': link, 'soft': symlink, 'copy': copy}
self.links_to_be_called = []
for link in self.duplicate.split('-'):
@@ -1347,11 +1342,10 @@ class FSTestCase(_tempdirTestCase):
assert f1.get_contents() == bytearray("Foo\x1aBar", 'utf-8'), f1.get_contents()
# This tests to make sure we can decode UTF-8 text files.
- test_string = u"Foo\x1aBar"
+ test_string = "Foo\x1aBar"
test.write("utf8_file", test_string.encode('utf-8'))
f1 = fs.File(test.workpath("utf8_file"))
- assert eval('f1.get_text_contents() == u"Foo\x1aBar"'), \
- f1.get_text_contents()
+ f1.get_text_contents() == "Foo\x1aBar", f1.get_text_contents()
# Check for string which doesn't have BOM and isn't valid
# ASCII
@@ -1449,7 +1443,7 @@ class FSTestCase(_tempdirTestCase):
c = e.get_text_contents()
try:
- eval('assert c == u"", c')
+ eval('assert c == "", c')
except SyntaxError:
assert c == ""
@@ -1460,10 +1454,7 @@ class FSTestCase(_tempdirTestCase):
assert e.__class__ == SCons.Node.FS.Entry, e.__class__
assert c == "", c
c = e.get_text_contents()
- try:
- eval('assert c == u"", c')
- except SyntaxError:
- assert c == "", c
+ assert c == "", c
test.write("tstamp", "tstamp\n")
try:
@@ -3066,12 +3057,12 @@ class RepositoryTestCase(_tempdirTestCase):
assert r is d1, r
r = d2.rentry()
- assert not r is d2, r
+ assert r is not d2, r
r = str(r)
assert r == os.path.join(self.rep1, 'd2'), r
r = d3.rentry()
- assert not r is d3, r
+ assert r is not d3, r
r = str(r)
assert r == os.path.join(self.rep2, 'd3'), r
@@ -3079,12 +3070,12 @@ class RepositoryTestCase(_tempdirTestCase):
assert r is e1, r
r = e2.rentry()
- assert not r is e2, r
+ assert r is not e2, r
r = str(r)
assert r == os.path.join(self.rep1, 'e2'), r
r = e3.rentry()
- assert not r is e3, r
+ assert r is not e3, r
r = str(r)
assert r == os.path.join(self.rep2, 'e3'), r
@@ -3092,12 +3083,12 @@ class RepositoryTestCase(_tempdirTestCase):
assert r is f1, r
r = f2.rentry()
- assert not r is f2, r
+ assert r is not f2, r
r = str(r)
assert r == os.path.join(self.rep1, 'f2'), r
r = f3.rentry()
- assert not r is f3, r
+ assert r is not f3, r
r = str(r)
assert r == os.path.join(self.rep2, 'f3'), r
@@ -3127,12 +3118,12 @@ class RepositoryTestCase(_tempdirTestCase):
assert r is d1, r
r = d2.rdir()
- assert not r is d2, r
+ assert r is not d2, r
r = str(r)
assert r == os.path.join(self.rep1, 'd2'), r
r = d3.rdir()
- assert not r is d3, r
+ assert r is not d3, r
r = str(r)
assert r == os.path.join(self.rep3, 'd3'), r
@@ -3183,12 +3174,12 @@ class RepositoryTestCase(_tempdirTestCase):
assert r is f1, r
r = f2.rfile()
- assert not r is f2, r
+ assert r is not f2, r
r = str(r)
assert r == os.path.join(self.rep1, 'f2'), r
r = f3.rfile()
- assert not r is f3, r
+ assert r is not f3, r
r = f3.rstr()
assert r == os.path.join(self.rep3, 'f3'), r
@@ -3316,15 +3307,7 @@ class RepositoryTestCase(_tempdirTestCase):
# Use a test string that has a file terminator in it to make
# sure we read the entire file, regardless of its contents.
- try:
- eval('test_string = u"Con\x1aTents\n"')
- except SyntaxError:
- import collections
- class FakeUnicodeString(collections.UserString):
- def encode(self, encoding):
- return str(self)
-
- test_string = FakeUnicodeString("Con\x1aTents\n")
+ test_string = "Con\x1aTents\n"
# Test with ASCII.
test.write(["rep3", "contents"], test_string.encode('ascii'))
diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py
index d8179ff..8d9d3a9 100644
--- a/src/engine/SCons/Node/NodeTests.py
+++ b/src/engine/SCons/Node/NodeTests.py
@@ -1104,7 +1104,7 @@ class NodeTestCase(unittest.TestCase):
for kid in [n1, n3, n4, n6, n7, n9, n10, n12]:
assert kid in kids, kid
for kid in [n2, n5, n8, n11]:
- assert not kid in kids, kid
+ assert kid not in kids, kid
def test_all_children(self):
"""Test fetching all the "children" of a Node.
diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py
index a5bcd4b..68c6ee8 100644
--- a/src/engine/SCons/Node/Python.py
+++ b/src/engine/SCons/Node/Python.py
@@ -88,7 +88,7 @@ class Value(SCons.Node.Node):
NodeInfo = ValueNodeInfo
BuildInfo = ValueBuildInfo
- def __init__(self, value, built_value=None):
+ def __init__(self, value, built_value=None, name=None):
SCons.Node.Node.__init__(self)
self.value = value
self.changed_since_last_build = 6
@@ -96,6 +96,13 @@ class Value(SCons.Node.Node):
if built_value is not None:
self.built_value = built_value
+ # Set a name so it can be a child of a node and not break
+ # its parent's implementation of Node.get_contents.
+ if name:
+ self.name = name
+ else:
+ self.name = str(value)
+
def str_for_display(self):
return repr(self.value)
@@ -177,23 +184,26 @@ class Value(SCons.Node.Node):
return contents
-def ValueWithMemo(value, built_value=None):
+def ValueWithMemo(value, built_value=None, name=None):
+ """
+ Memoized Value() node factory.
+ """
global _memo_lookup_map
# No current support for memoizing a value that needs to be built.
if built_value:
- return Value(value, built_value)
+ return Value(value, built_value, name=name)
try:
- memo_lookup_key = hash(value)
+ memo_lookup_key = hash((value, name))
except TypeError:
# Non-primitive types will hit this codepath.
- return Value(value)
+ return Value(value, name=name)
try:
return _memo_lookup_map[memo_lookup_key]
except KeyError:
- v = Value(value)
+ v = Value(value, built_value, name)
_memo_lookup_map[memo_lookup_key] = v
return v
diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py
index dbb4ec8..51a49c0 100644
--- a/src/engine/SCons/Node/PythonTests.py
+++ b/src/engine/SCons/Node/PythonTests.py
@@ -64,6 +64,12 @@ class ValueTestCase(unittest.TestCase):
v2.build()
assert v2.built_value == 'faked', v2.built_value
+ v3 = SCons.Node.Python.Value(b'\x00\x0F', name='name')
+ v3.executor = fake_executor()
+ v3.build()
+ assert v3.name == 'name', v3.name
+ assert v3.built_value == 'faked', v3.built_value
+
def test_read(self):
"""Test the Value.read() method
"""
@@ -98,6 +104,9 @@ class ValueTestCase(unittest.TestCase):
assert csig == 'None', csig
+
+
+
class ValueNodeInfoTestCase(unittest.TestCase):
def test___init__(self):
"""Test ValueNodeInfo initialization"""
@@ -112,6 +121,18 @@ class ValueBuildInfoTestCase(unittest.TestCase):
bi = SCons.Node.Python.ValueBuildInfo()
+class ValueChildTestCase(unittest.TestCase):
+ def test___init__(self):
+ """Test support for a Value() being an implicit dependency of a Node"""
+ value = SCons.Node.Python.Value('v')
+ node = SCons.Node.Node()
+ node._func_get_contents = 2 # Pretend to be a Dir.
+ node.add_to_implicit([value])
+ contents = node.get_contents()
+ expected_contents = '%s %s\n' % (value.get_csig(), value.name)
+ assert contents == expected_contents
+
+
class ValueMemoTestCase(unittest.TestCase):
def test_memo(self):
"""Test memoization"""
@@ -144,6 +165,19 @@ class ValueMemoTestCase(unittest.TestCase):
v4 = SCons.Node.Python.ValueWithMemo(a)
assert v3 is not v4
+ def test_value_set_name(self):
+ """ Confirm setting name and caching takes the name into account """
+
+ v1 = SCons.Node.Python.ValueWithMemo(b'\x00\x0F', name='name')
+ v2 = SCons.Node.Python.ValueWithMemo(b'\x00\x0F', name='name2')
+ v3 = SCons.Node.Python.ValueWithMemo('Jibberish')
+
+ self.assertEqual(v1.name,'name', msg=v1.name)
+ self.assertEqual(v2.name,'name2', msg=v2.name)
+ self.assertEqual(v3.name,'Jibberish', msg=v3.name)
+ self.assertTrue(v1 is not v2, msg="v1 and v2 should be different as they have different names but same values")
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py
index 0b58282..c3565bf 100644
--- a/src/engine/SCons/Node/__init__.py
+++ b/src/engine/SCons/Node/__init__.py
@@ -19,8 +19,6 @@ be able to depend on any other type of "thing."
"""
-from __future__ import print_function
-
#
# __COPYRIGHT__
#
diff --git a/src/engine/SCons/PathListTests.py b/src/engine/SCons/PathListTests.py
index 104be73..09b1132 100644
--- a/src/engine/SCons/PathListTests.py
+++ b/src/engine/SCons/PathListTests.py
@@ -185,7 +185,7 @@ class PathListTestCase(unittest.TestCase):
x3 = SCons.PathList.PathList('x')
- assert not x1 is x3, (x1, x3)
+ assert x1 is not x3, (x1, x3)
if __name__ == "__main__":
diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py
index 058241d..21e63b4 100644
--- a/src/engine/SCons/Platform/__init__.py
+++ b/src/engine/SCons/Platform/__init__.py
@@ -41,8 +41,6 @@ their own platform definition.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -195,7 +193,7 @@ class TempFileMunge(object):
# Default to the .lnk suffix for the benefit of the Phar Lap
# linkloc linker, which likes to append an .lnk suffix if
# none is given.
- if env.has_key('TEMPFILESUFFIX'):
+ if 'TEMPFILESUFFIX' in env:
suffix = env.subst('$TEMPFILESUFFIX')
else:
suffix = '.lnk'
diff --git a/src/engine/SCons/Platform/win32.py b/src/engine/SCons/Platform/win32.py
index bb1b46d..afe2df9 100644
--- a/src/engine/SCons/Platform/win32.py
+++ b/src/engine/SCons/Platform/win32.py
@@ -62,46 +62,6 @@ except AttributeError:
else:
parallel_msg = None
- if sys.version_info.major == 2:
- import __builtin__
-
- _builtin_file = __builtin__.file
- _builtin_open = __builtin__.open
-
- def _scons_fixup_mode(mode):
- """Adjust 'mode' to mark handle as non-inheritable.
-
- SCons is multithreaded, so allowing handles to be inherited by
- children opens us up to races, where (e.g.) processes spawned by
- the Taskmaster may inherit and retain references to files opened
- by other threads. This may lead to sharing violations and,
- ultimately, build failures.
-
- By including 'N' as part of fopen's 'mode' parameter, all file
- handles returned from these functions are atomically marked as
- non-inheritable.
- """
- if not mode:
- # Python's default is 'r'.
- # https://docs.python.org/2/library/functions.html#open
- mode = 'rN'
- elif 'N' not in mode:
- mode += 'N'
- return mode
-
- class _scons_file(_builtin_file):
- def __init__(self, name, mode=None, *args, **kwargs):
- _builtin_file.__init__(self, name, _scons_fixup_mode(mode),
- *args, **kwargs)
-
- def _scons_open(name, mode=None, *args, **kwargs):
- return _builtin_open(name, _scons_fixup_mode(mode),
- *args, **kwargs)
-
- __builtin__.file = _scons_file
- __builtin__.open = _scons_open
-
-
if False:
# Now swap out shutil.filecopy and filecopy2 for win32 api native CopyFile
@@ -307,9 +267,6 @@ def get_system_root():
except:
pass
- # Ensure system root is a string and not unicode
- # (This only matters for py27 were unicode in env passed to POpen fails)
- val = str(val)
_system_root = val
return val
diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py
index e706dae..e0e492b 100644
--- a/src/engine/SCons/SConf.py
+++ b/src/engine/SCons/SConf.py
@@ -33,8 +33,6 @@ libraries are installed, if some command line options are supported etc.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -56,6 +54,7 @@ import SCons.Warnings
import SCons.Conftest
from SCons.Debug import Trace
+from collections import defaultdict
# Turn off the Conftest error logging
SCons.Conftest.LogInputFiles = 0
@@ -98,7 +97,7 @@ def SetProgressDisplay(display):
SConfFS = None
-_ac_build_counter = 0 # incremented, whenever TryBuild is called
+_ac_build_counter = defaultdict(int)
_ac_config_logs = {} # all config.log files created in this build
_ac_config_hs = {} # all config.h files created in this build
sconf_global = None # current sconf object
@@ -132,8 +131,8 @@ def CreateConfigHBuilder(env):
_stringConfigH)
sconfigHBld = SCons.Builder.Builder(action=action)
env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} )
- for k in list(_ac_config_hs.keys()):
- env.SConfigHBuilder(k, env.Value(_ac_config_hs[k]))
+ for k, v in _ac_config_hs.items():
+ env.SConfigHBuilder(k, env.Value(v))
class SConfWarning(SCons.Warnings.Warning):
@@ -161,11 +160,14 @@ class ConfigureCacheError(SConfError):
def __init__(self,target):
SConfError.__init__(self, '"%s" is not yet built and cache is forced.' % str(target))
+
# define actions for building text files
-def _createSource( target, source, env ):
+def _createSource(target, source, env):
fd = open(str(target[0]), "w")
fd.write(source[0].get_contents().decode())
fd.close()
+
+
def _stringSource( target, source, env ):
return (str(target[0]) + ' <-\n |' +
source[0].get_contents().decode().replace( '\n', "\n |" ) )
@@ -426,7 +428,8 @@ class SConfBase(object):
SConfFS = SCons.Node.FS.default_fs or \
SCons.Node.FS.FS(env.fs.pathTop)
if sconf_global is not None:
- raise SCons.Errors.UserError
+ raise SCons.Errors.UserError("""Configure() called while another Configure() exists.
+ Please call .Finish() before creating and second Configure() context""")
if log_file is not None:
log_file = SConfFS.File(env.subst(log_file))
@@ -573,8 +576,7 @@ class SConfBase(object):
"""
return self.pspawn(sh, escape, cmd, args, env, self.logstream, self.logstream)
-
- def TryBuild(self, builder, text = None, extension = ""):
+ def TryBuild(self, builder, text=None, extension=""):
"""Low level TryBuild implementation. Normally you don't need to
call that - you can use TryCompile / TryLink / TryRun instead
"""
@@ -592,8 +594,30 @@ class SConfBase(object):
raise SCons.Errors.UserError('Missing SPAWN construction variable.')
nodesToBeBuilt = []
+ sourcetext = self.env.Value(text)
+ f = "conftest"
+
+ if text is not None:
+ textSig = SCons.Util.MD5signature(sourcetext)
+ textSigCounter = str(_ac_build_counter[textSig])
+ _ac_build_counter[textSig] += 1
+
+ f = "_".join([f, textSig, textSigCounter])
+ textFile = self.confdir.File(f + extension)
+ textFileNode = self.env.SConfSourceBuilder(target=textFile,
+ source=sourcetext)
+ nodesToBeBuilt.extend(textFileNode)
+
+ source = textFile
+ target = textFile.File(f + "SConfActionsContentDummyTarget")
+ else:
+ source = None
+ target = None
+
+ action = builder.builder.action.get_contents(target=target, source=[source], env=self.env)
+ actionsig = SCons.Util.MD5signature(action)
+ f = "_".join([f, actionsig])
- f = "conftest_" + str(_ac_build_counter)
pref = self.env.subst( builder.builder.prefix )
suff = self.env.subst( builder.builder.suffix )
target = self.confdir.File(pref + f + suff)
@@ -602,16 +626,6 @@ class SConfBase(object):
# Slide our wrapper into the construction environment as
# the SPAWN function.
self.env['SPAWN'] = self.pspawn_wrapper
- sourcetext = self.env.Value(text)
-
- if text is not None:
- textFile = self.confdir.File(f + extension)
- textFileNode = self.env.SConfSourceBuilder(target=textFile,
- source=sourcetext)
- nodesToBeBuilt.extend(textFileNode)
- source = textFileNode
- else:
- source = None
nodes = builder(target = target, source = source)
if not SCons.Util.is_List(nodes):
@@ -622,7 +636,6 @@ class SConfBase(object):
finally:
self.env['SPAWN'] = save_spawn
- _ac_build_counter = _ac_build_counter + 1
if result:
self.lastTarget = nodes[0]
else:
@@ -703,7 +716,7 @@ class SConfBase(object):
"""Adds all the tests given in the tests dictionary to this SConf
instance
"""
- for name in list(tests.keys()):
+ for name in tests.keys():
self.AddTest(name, tests[name])
def _createDir( self, node ):
diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py
index c5d1fbd..e2b9133 100644
--- a/src/engine/SCons/SConfTests.py
+++ b/src/engine/SCons/SConfTests.py
@@ -56,18 +56,6 @@ class SConfTestCase(unittest.TestCase):
os.chdir(self.save_cwd)
def _resetSConfState(self):
- if sys.platform in ['cygwin', 'win32'] and sys.version_info.major == 2:
- # On Windows with Python2, SCons.Platform.win32 redefines the
- # built-in file() and open() functions to disable handle
- # inheritance. Because we are unloading all SCons modules other
- # than SCons.Compat, SCons.Platform.win32 will lose the variables
- # it needs. As a result, we should reset the file() and open()
- # functions to their original built-in versions.
- import __builtin__
- import SCons.Platform.win32
- __builtin__.file = SCons.Platform.win32._builtin_file
- __builtin__.open = SCons.Platform.win32._builtin_open
-
# Ok, this is tricky, and i do not know, if everything is sane.
# We try to reset scons' state (including all global variables)
import SCons.SConsign
@@ -169,10 +157,18 @@ class SConfTestCase(unittest.TestCase):
log_file=self.test.workpath('config.log'))
import SCons.Builder
import SCons.Node
+
+ class MyAction(object):
+ def get_contents(self, target, source, env):
+ return 'MyBuilder-MyAction $SOURCE $TARGET'
+
class MyBuilder(SCons.Builder.BuilderBase):
def __init__(self):
self.prefix = ''
self.suffix = ''
+ # need action because temporary file name uses hash of actions get_contents()
+ self.action = MyAction()
+
def __call__(self, env, target, source):
class MyNode(object):
def __init__(self, name):
@@ -299,10 +295,6 @@ int main(void) {
return None
def actionFAIL(target, source, env):
return 1
- def actionUnicode(target, source, env):
- with open(str(target[0]), "wb") as f:
- f.write('2\302\242\n')
- return None
self._resetSConfState()
@@ -311,14 +303,10 @@ int main(void) {
log_file=self.test.workpath('config.log'))
try:
(ret, output) = sconf.TryAction(action=actionOK)
- assert ret and output.encode('utf-8') == bytearray("RUN OK"+os.linesep,'utf-8'), (ret, output)
+ assert ret and output.encode('utf-8') == bytearray("RUN OK"+os.linesep, 'utf-8'), (ret, output)
(ret, output) = sconf.TryAction(action=actionFAIL)
assert not ret and output == "", (ret, output)
- if not TestCmd.IS_PY3:
- # GH Issue #3141 - unicode text and py2.7 crashes.
- (ret, output) = sconf.TryAction(action=actionUnicode)
- assert ret and output == u'2\xa2\n', (ret, output)
finally:
sconf.Finish()
diff --git a/src/engine/SCons/SConsign.py b/src/engine/SCons/SConsign.py
index 1115f2a..a516e1f 100644
--- a/src/engine/SCons/SConsign.py
+++ b/src/engine/SCons/SConsign.py
@@ -26,9 +26,6 @@ Writing and reading information to the .sconsign file or 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.
#
-
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
diff --git a/src/engine/SCons/SConsignTests.py b/src/engine/SCons/SConsignTests.py
index d40a7b6..782072d 100644
--- a/src/engine/SCons/SConsignTests.py
+++ b/src/engine/SCons/SConsignTests.py
@@ -337,7 +337,7 @@ class SConsignFileTestCase(SConsignTestCase):
SCons.SConsign.ForDirectory(DummyNode(test.workpath('dir')))
- assert not SCons.SConsign.DataBase is None, SCons.SConsign.DataBase
+ assert SCons.SConsign.DataBase is not None, SCons.SConsign.DataBase
assert fake_dbm.name == file, fake_dbm.name
assert fake_dbm.mode == "c", fake_dbm.mode
diff --git a/src/engine/SCons/Scanner/ProgTests.py b/src/engine/SCons/Scanner/ProgTests.py
index 45fdcb2..8981fd4 100644
--- a/src/engine/SCons/Scanner/ProgTests.py
+++ b/src/engine/SCons/Scanner/ProgTests.py
@@ -43,6 +43,7 @@ libs = [ 'l1.lib', 'd1/l2.lib', 'd1/d2/l3.lib',
for h in libs:
test.write(h, "\n")
+
# define some helpers:
class DummyEnvironment(object):
@@ -254,22 +255,6 @@ def suite():
suite.addTest(ProgramScannerTestCase8())
suite.addTest(ProgramScannerTestCase9())
suite.addTest(ProgramScannerTestCase10())
- try: unicode
- except NameError: pass
- else:
- code = """if 1:
- class ProgramScannerTestCase4(unittest.TestCase):
- def runTest(self):
- env = DummyEnvironment(LIBPATH=[test.workpath("d1/d2"),
- test.workpath("d1")],
- LIBS=u'l2 l3'.split())
- s = SCons.Scanner.Prog.ProgramScanner()
- path = s.path(env)
- deps = s(DummyNode('dummy'), env, path)
- assert deps_match(deps, ['d1/l2.lib', 'd1/d2/l3.lib']), map(str, deps)
- suite.addTest(ProgramScannerTestCase4())
- \n"""
- exec(code)
return suite
if __name__ == "__main__":
diff --git a/src/engine/SCons/Scanner/Python.py b/src/engine/SCons/Scanner/Python.py
new file mode 100644
index 0000000..deb2241
--- /dev/null
+++ b/src/engine/SCons/Scanner/Python.py
@@ -0,0 +1,171 @@
+"""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.
+
+"""
+
+#
+# __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 itertools
+import os
+import re
+import SCons.Scanner
+
+# Capture python "from a import b" and "import a" statements.
+from_cre = re.compile(r'^\s*from\s+([^\s]+)\s+import\s+(.*)', re.M)
+import_cre = re.compile(r'^\s*import\s+([^\s]+)', re.M)
+
+
+def path_function(env, dir=None, target=None, source=None, argument=None):
+ """Retrieves a tuple with all search paths."""
+ paths = env['ENV'].get('PYTHONPATH', '').split(os.pathsep)
+ if source:
+ paths.append(source[0].dir.abspath)
+ return tuple(paths)
+
+
+def find_include_names(node):
+ """
+ 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)
+ 2. Additional optional imports that could be functions or files
+ in the case of a "from X import Y" statement. In the case of a
+ normal "import" statement, this is None.
+ """
+ text = node.get_text_contents()
+ all_matches = []
+ matches = from_cre.findall(text)
+ if matches:
+ for match in matches:
+ imports = [i.strip() for i in match[1].split(',')]
+
+ # Add some custom logic to strip out "as" because the regex
+ # includes it.
+ last_import_split = imports[-1].split()
+ if len(last_import_split) > 1:
+ imports[-1] = last_import_split[0]
+
+ all_matches.append((match[0], imports))
+
+ matches = import_cre.findall(text)
+ if matches:
+ for match in matches:
+ all_matches.append((match, None))
+
+ return all_matches
+
+
+def scan(node, env, path=()):
+ # cache the includes list in node so we only scan it once:
+ if node.includes is not None:
+ includes = node.includes
+ else:
+ includes = find_include_names(node)
+ # Intern the names of the include files. Saves some memory
+ # if the same header is included many times.
+ node.includes = list(map(SCons.Util.silent_intern, includes))
+
+ # XXX TODO: Sort?
+ nodes = []
+ if callable(path):
+ path = path()
+ for module, imports in includes:
+ is_relative = module.startswith('.')
+ if is_relative:
+ # This is a relative include, so we must ignore PYTHONPATH.
+ module_lstripped = module.lstrip('.')
+ # One dot is current directory, two is parent, three is
+ # grandparent, etc.
+ num_parents = len(module) - len(module_lstripped) - 1
+ current_dir = node.get_dir()
+ for i in itertools.repeat(None, num_parents):
+ current_dir = current_dir.up()
+
+ search_paths = [current_dir.abspath]
+ search_string = module_lstripped
+ else:
+ search_paths = path
+ search_string = module
+
+ module_components = search_string.split('.')
+ for search_path in search_paths:
+ candidate_path = os.path.join(search_path, *module_components)
+ # The import stored in "module" could refer to a directory or file.
+ import_dirs = []
+ if os.path.isdir(candidate_path):
+ import_dirs = module_components
+
+ # Because this resolved to a directory, there is a chance that
+ # additional imports (e.g. from module import A, B) could refer
+ # to files to import.
+ if imports:
+ for imp in imports:
+ file = os.path.join(candidate_path, imp + '.py')
+ if os.path.isfile(file):
+ nodes.append(file)
+ elif os.path.isfile(candidate_path + '.py'):
+ nodes.append(candidate_path + '.py')
+ import_dirs = module_components[:-1]
+
+ # We can ignore imports because this resolved to a file. Any
+ # additional imports (e.g. from module.file import A, B) would
+ # only refer to functions in this file.
+
+ # Take a dependency on all __init__.py files from all imported
+ # packages unless it's a relative import. If it's a relative
+ # import, we don't need to take the dependency because Python
+ # requires that all referenced packages have already been imported,
+ # which means that the dependency has already been established.
+ if import_dirs and not is_relative:
+ for i in range(len(import_dirs)):
+ init_components = module_components[:i+1] + ['__init__.py']
+ init_path = os.path.join(search_path, *(init_components))
+ if os.path.isfile(init_path):
+ nodes.append(init_path)
+ break
+
+ return sorted(nodes)
+
+
+PythonSuffixes = ['.py']
+PythonScanner = SCons.Scanner.Base(scan, name='PythonScanner',
+ skeys=PythonSuffixes,
+ path_function=path_function, recursive=1)
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/src/engine/SCons/Scanner/PythonTests.py b/src/engine/SCons/Scanner/PythonTests.py
new file mode 100644
index 0000000..0d4e628
--- /dev/null
+++ b/src/engine/SCons/Scanner/PythonTests.py
@@ -0,0 +1,269 @@
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.compat
+
+import collections
+import os
+import unittest
+
+import TestCmd
+
+import SCons.Node.FS
+import SCons.Scanner.Python
+
+test = TestCmd.TestCmd(workdir='')
+test.dir_fixture('python_scanner')
+
+if os.path.normcase('foo') == os.path.normcase('FOO'):
+ my_normpath = os.path.normcase
+else:
+ my_normpath = os.path.normpath
+
+
+def deps_match(self, deps, headers):
+ global my_normpath
+ scanned = list(map(my_normpath, list(map(str, deps))))
+ expect = list(map(my_normpath, headers))
+ self.assertTrue(scanned == expect,
+ "expect %s != scanned %s" % (expect, scanned))
+
+
+# Copied from LaTeXTests.py.
+class DummyEnvironment(collections.UserDict):
+ def __init__(self, **kw):
+ collections.UserDict.__init__(self)
+ self.data.update(kw)
+ self.fs = SCons.Node.FS.FS(test.workpath(''))
+ self['ENV'] = {}
+
+ def Dictionary(self, *args):
+ return self.data
+
+ def subst(self, strSubst, target=None, source=None, conv=None):
+ if strSubst[0] == '$':
+ return self.data[strSubst[1:]]
+ return strSubst
+
+ def subst_list(self, strSubst, target=None, source=None, conv=None):
+ if strSubst[0] == '$':
+ return [self.data[strSubst[1:]]]
+ return [[strSubst]]
+
+ def subst_path(self, path, target=None, source=None, conv=None):
+ if not isinstance(path, list):
+ path = [path]
+ return list(map(self.subst, path))
+
+ def get_calculator(self):
+ return None
+
+ def get_factory(self, factory):
+ return factory or self.fs.File
+
+ def Dir(self, filename):
+ return self.fs.Dir(filename)
+
+ def File(self, filename):
+ return self.fs.File(filename)
+
+
+class PythonScannerTestPythonPath(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ env['ENV']['PYTHONPATH'] = test.workpath('')
+ path = s.path(env)
+ deps = s(env.File('imports_simple_package.py'), env, path)
+ files = ['simple_package/__init__.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestPythonCallablePath(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ env['ENV']['PYTHONPATH'] = test.workpath('')
+ deps = s(env.File('imports_simple_package.py'), env,
+ lambda : s.path(env))
+ files = ['simple_package/__init__.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestImportSimplePackage(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File('imports_simple_package.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['simple_package/__init__.py']
+ deps_match(self, deps, files)
+
+ # Repeat the test in case there are any issues caching includes.
+ deps = s(node, env, path)
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestImportSimplePackageModule1As(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File('import_simple_package_module1_as.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['simple_package/__init__.py', 'simple_package/module1.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestImportSimplePackageModuleAs(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File('import_simple_package_module1.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['simple_package/__init__.py', 'simple_package/module1.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestFromImportSimplePackageModule1(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File('from_import_simple_package_module1.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['simple_package/__init__.py', 'simple_package/module1.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestFromImportSimplePackageModule1As(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File('from_import_simple_package_module1_as.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['simple_package/__init__.py', 'simple_package/module1.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestFromImportSimplePackageModulesNoSpace(
+ unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File('from_import_simple_package_modules_no_space.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['simple_package/__init__.py', 'simple_package/module1.py',
+ 'simple_package/module2.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestFromImportSimplePackageModulesWithSpace(
+ unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File('from_import_simple_package_modules_with_space.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['simple_package/__init__.py', 'simple_package/module1.py',
+ 'simple_package/module2.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestCurdirReferenceScript(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.Dir('curdir_reference').File('script.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['curdir_reference/helper.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestImportsNested3(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File('imports_nested3.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['nested1/__init__.py', 'nested1/nested2/__init__.py',
+ 'nested1/nested2/nested3/__init__.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestImportsGrandparentModule(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File(
+ 'nested1/nested2/nested3/imports_grandparent_module.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ # Note: there is some ambiguity here in what the scanner should return.
+ # Relative imports require that the referenced packages have already
+ # been imported.
+ files = ['nested1/module.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestImportsParentModule(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File(
+ 'nested1/nested2/nested3/imports_parent_module.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['nested1/nested2/module.py']
+ deps_match(self, deps, files)
+
+
+class PythonScannerTestImportsParentThenSubmodule(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment()
+ s = SCons.Scanner.Python.PythonScanner
+ node = env.File(
+ 'nested1/nested2/nested3/imports_parent_then_submodule.py')
+ path = s.path(env, source=[node])
+ deps = s(node, env, path)
+ files = ['nested1/nested2a/module.py']
+ deps_match(self, deps, files)
+
+
+if __name__ == "__main__":
+ unittest.main()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/src/engine/SCons/Scanner/RCTests.py b/src/engine/SCons/Scanner/RCTests.py
index 551e613..347149c 100644
--- a/src/engine/SCons/Scanner/RCTests.py
+++ b/src/engine/SCons/Scanner/RCTests.py
@@ -82,7 +82,7 @@ class DummyEnvironment(collections.UserDict):
def Dictionary(self, *args):
return self.data
- def subst(self, arg, target=None, source=None, conv=None):
+ def subst(self, strSubst, target=None, source=None, conv=None):
if strSubst[0] == '$':
return self.data[strSubst[1:]]
return strSubst
diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py
index abe4042..6206af9 100644
--- a/src/engine/SCons/Scanner/ScannerTests.py
+++ b/src/engine/SCons/Scanner/ScannerTests.py
@@ -599,7 +599,7 @@ class ClassicCPPTestCase(unittest.TestCase):
assert n == 'path/bbb', n
assert i == 'bbb', i
- n, i = s.find_include(('<', u'ccc'), 'foo', ('path',))
+ n, i = s.find_include(('<', 'ccc'), 'foo', ('path',))
assert n == 'path/ccc', n
assert i == 'ccc', i
diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py
index cc4f23c..a414b4e 100644
--- a/src/engine/SCons/Script/Interactive.py
+++ b/src/engine/SCons/Script/Interactive.py
@@ -19,8 +19,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.
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
__doc__ = """
@@ -247,7 +245,7 @@ version Prints SCons version information.
while n:
n = walker.get_next()
- for node in list(seen_nodes.keys()):
+ for node in seen_nodes.keys():
# Call node.clear() to clear most of the state
node.clear()
# node.clear() doesn't reset node.state, so call
diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py
index f9c8384..ce948a0 100644
--- a/src/engine/SCons/Script/Main.py
+++ b/src/engine/SCons/Script/Main.py
@@ -10,9 +10,6 @@ some other module. If it's specific to the "scons" script invocation,
it goes here.
"""
-from __future__ import print_function
-
-
unsupported_python_version = (2, 6, 0)
deprecated_python_version = (2, 7, 0)
@@ -43,7 +40,9 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
+import importlib.util
import os
+import re
import sys
import time
import traceback
@@ -65,7 +64,6 @@ import SCons.Script
import SCons.Taskmaster
import SCons.Util
import SCons.Warnings
-
import SCons.Script.Interactive
# Global variables
@@ -698,80 +696,87 @@ def _create_path(plist):
return path
def _load_site_scons_dir(topdir, site_dir_name=None):
- """Load the site_scons dir under topdir.
- Prepends site_scons to sys.path, imports site_scons/site_init.py,
- and prepends site_scons/site_tools to default toolpath."""
+ """Load the site directory under topdir.
+
+ If a site dir name is supplied use it, else use default "site_scons"
+ Prepend site dir to sys.path.
+ If a "site_tools" subdir exists, prepend to toolpath.
+ Import "site_init.py" from site dir if it exists.
+ """
if site_dir_name:
err_if_not_found = True # user specified: err if missing
else:
site_dir_name = "site_scons"
- err_if_not_found = False
-
+ err_if_not_found = False # scons default: okay to be missing
site_dir = os.path.join(topdir, site_dir_name)
+
if not os.path.exists(site_dir):
if err_if_not_found:
- raise SCons.Errors.UserError("site dir %s not found."%site_dir)
+ raise SCons.Errors.UserError("site dir %s not found." % site_dir)
return
+ sys.path.insert(0, os.path.abspath(site_dir))
site_init_filename = "site_init.py"
site_init_modname = "site_init"
site_tools_dirname = "site_tools"
- # prepend to sys.path
- sys.path = [os.path.abspath(site_dir)] + sys.path
site_init_file = os.path.join(site_dir, site_init_filename)
site_tools_dir = os.path.join(site_dir, site_tools_dirname)
- if os.path.exists(site_init_file):
- import imp, re
- try:
- try:
- fp, pathname, description = imp.find_module(site_init_modname,
- [site_dir])
- # Load the file into SCons.Script namespace. This is
- # opaque and clever; m is the module object for the
- # SCons.Script module, and the exec ... in call executes a
- # file (or string containing code) in the context of the
- # module's dictionary, so anything that code defines ends
- # up adding to that module. This is really short, but all
- # the error checking makes it longer.
- try:
- m = sys.modules['SCons.Script']
- except Exception as e:
- fmt = 'cannot import site_init.py: missing SCons.Script module %s'
- raise SCons.Errors.InternalError(fmt % repr(e))
- try:
- sfx = description[0]
- modname = os.path.basename(pathname)[:-len(sfx)]
- site_m = {"__file__": pathname, "__name__": modname, "__doc__": None}
- re_special = re.compile("__[^_]+__")
- for k in list(m.__dict__.keys()):
- if not re_special.match(k):
- site_m[k] = m.__dict__[k]
-
- # This is the magic.
- exec(compile(fp.read(), fp.name, 'exec'), site_m)
- except KeyboardInterrupt:
- raise
- except Exception as e:
- fmt = '*** Error loading site_init file %s:\n'
- sys.stderr.write(fmt % repr(site_init_file))
- raise
- else:
- for k in site_m:
- if not re_special.match(k):
- m.__dict__[k] = site_m[k]
- except KeyboardInterrupt:
- raise
- except ImportError as e:
- fmt = '*** cannot import site init file %s:\n'
- sys.stderr.write(fmt % repr(site_init_file))
- raise
- finally:
- if fp:
- fp.close()
+
if os.path.exists(site_tools_dir):
- # prepend to DefaultToolpath
SCons.Tool.DefaultToolpath.insert(0, os.path.abspath(site_tools_dir))
+ if not os.path.exists(site_init_file):
+ return
+
+ # "import" the site_init.py file into the SCons.Script namespace.
+ # This is a variant on the basic Python import flow in that the globals
+ # dict for the compile step is prepopulated from the SCons.Script
+ # module object; on success the SCons.Script globals are refilled
+ # from the site_init globals so it all appears in SCons.Script
+ # instead of as a separate module.
+ try:
+ try:
+ m = sys.modules['SCons.Script']
+ except KeyError:
+ fmt = 'cannot import {}: missing SCons.Script module'
+ raise SCons.Errors.InternalError(fmt.format(site_init_file))
+
+ spec = importlib.util.spec_from_file_location(site_init_modname, site_init_file)
+ site_m = {
+ "__file__": spec.origin,
+ "__name__": spec.name,
+ "__doc__": None,
+ }
+ re_dunder = re.compile(r"__[^_]+__")
+ # update site dict with all but magic (dunder) methods
+ for k, v in m.__dict__.items():
+ if not re_dunder.match(k):
+ site_m[k] = v
+
+ with open(spec.origin, 'r') as f:
+ code = f.read()
+ try:
+ codeobj = compile(code, spec.name, "exec")
+ exec(codeobj, site_m)
+ except KeyboardInterrupt:
+ raise
+ except Exception:
+ fmt = "*** Error loading site_init file {}:\n"
+ sys.stderr.write(fmt.format(site_init_file))
+ raise
+ else:
+ # now refill globals with site_init's symbols
+ for k, v in site_m.items():
+ if not re_dunder.match(k):
+ m.__dict__[k] = v
+ except KeyboardInterrupt:
+ raise
+ except Exception:
+ fmt = "*** cannot import site init file {}:\n"
+ sys.stderr.write(fmt.format(site_init_file))
+ raise
+
+
def _load_all_site_scons_dirs(topdir, verbose=None):
"""Load all of the predefined site_scons dir.
Order is significant; we load them in order from most generic
@@ -810,7 +815,7 @@ def _load_all_site_scons_dirs(topdir, verbose=None):
sysdirs=['/usr/share/scons',
homedir('.scons')]
- dirs=sysdirs + [topdir]
+ dirs = sysdirs + [topdir]
for d in dirs:
if verbose: # this is used by unit tests.
print("Loading site dir ", d)
diff --git a/src/engine/SCons/Script/Main.xml b/src/engine/SCons/Script/Main.xml
index 5c68dee..b54df0e 100644
--- a/src/engine/SCons/Script/Main.xml
+++ b/src/engine/SCons/Script/Main.xml
@@ -312,7 +312,7 @@ The options supported are:
<term><literal>cache_debug</literal></term>
<listitem>
<para>
-which corresponds to --cache-debug;
+which corresponds to <option>--cache-debug</option>;
</para>
</listitem>
</varlistentry>
@@ -320,7 +320,7 @@ which corresponds to --cache-debug;
<term><literal>cache_disable</literal></term>
<listitem>
<para>
-which corresponds to --cache-disable;
+which corresponds to <option>--cache-disable</option>;
</para>
</listitem>
</varlistentry>
@@ -328,7 +328,7 @@ which corresponds to --cache-disable;
<term><literal>cache_force</literal></term>
<listitem>
<para>
-which corresponds to --cache-force;
+which corresponds to <option>--cache-force</option>;
</para>
</listitem>
</varlistentry>
@@ -336,7 +336,7 @@ which corresponds to --cache-force;
<term><literal>cache_show</literal></term>
<listitem>
<para>
-which corresponds to --cache-show;
+which corresponds to <option>--cache-show</option>;
</para>
</listitem>
</varlistentry>
@@ -344,7 +344,8 @@ which corresponds to --cache-show;
<term><literal>clean</literal></term>
<listitem>
<para>
-which corresponds to -c, --clean and --remove;
+which corresponds to <option>-c</option>, <option>--clean</option>
+and <option>--remove</option>;
</para>
</listitem>
</varlistentry>
@@ -352,7 +353,7 @@ which corresponds to -c, --clean and --remove;
<term><literal>config</literal></term>
<listitem>
<para>
-which corresponds to --config;
+which corresponds to <option>--config</option>;
</para>
</listitem>
</varlistentry>
@@ -360,7 +361,7 @@ which corresponds to --config;
<term><literal>directory</literal></term>
<listitem>
<para>
-which corresponds to -C and --directory;
+which corresponds to <option>-C</option> and <option>--directory</option>;
</para>
</listitem>
</varlistentry>
@@ -368,7 +369,7 @@ which corresponds to -C and --directory;
<term><literal>diskcheck</literal></term>
<listitem>
<para>
-which corresponds to --diskcheck
+which corresponds to <option>--diskcheck</option>;
</para>
</listitem>
</varlistentry>
@@ -376,7 +377,7 @@ which corresponds to --diskcheck
<term><literal>duplicate</literal></term>
<listitem>
<para>
-which corresponds to --duplicate;
+which corresponds to <option>--duplicate</option>;
</para>
</listitem>
</varlistentry>
@@ -384,7 +385,7 @@ which corresponds to --duplicate;
<term><literal>file</literal></term>
<listitem>
<para>
-which corresponds to -f, --file, --makefile and --sconstruct;
+which corresponds to <option>-f</option>, <option>--file</option>, <option>--makefile</option> and <option>--sconstruct</option>;
</para>
</listitem>
</varlistentry>
@@ -392,7 +393,7 @@ which corresponds to -f, --file, --makefile and --sconstruct;
<term><literal>help</literal></term>
<listitem>
<para>
-which corresponds to -h and --help;
+which corresponds to <option>-h</option> and <option>--help</option>;
</para>
</listitem>
</varlistentry>
@@ -400,7 +401,7 @@ which corresponds to -h and --help;
<term><literal>ignore_errors</literal></term>
<listitem>
<para>
-which corresponds to --ignore-errors;
+which corresponds to <option>--ignore-errors</option>;
</para>
</listitem>
</varlistentry>
@@ -408,7 +409,7 @@ which corresponds to --ignore-errors;
<term><literal>implicit_cache</literal></term>
<listitem>
<para>
-which corresponds to --implicit-cache;
+which corresponds to <option>--implicit-cache</option>;
</para>
</listitem>
</varlistentry>
@@ -416,7 +417,7 @@ which corresponds to --implicit-cache;
<term><literal>implicit_deps_changed</literal></term>
<listitem>
<para>
-which corresponds to --implicit-deps-changed;
+which corresponds to <option>--implicit-deps-changed</option>;
</para>
</listitem>
</varlistentry>
@@ -424,7 +425,7 @@ which corresponds to --implicit-deps-changed;
<term><literal>implicit_deps_unchanged</literal></term>
<listitem>
<para>
-which corresponds to --implicit-deps-unchanged;
+which corresponds to <option>--implicit-deps-unchanged</option>;
</para>
</listitem>
</varlistentry>
@@ -432,7 +433,7 @@ which corresponds to --implicit-deps-unchanged;
<term><literal>interactive</literal></term>
<listitem>
<para>
-which corresponds to --interact and --interactive;
+which corresponds to <option>--interact</option> and <option>--interactive</option>;
</para>
</listitem>
</varlistentry>
@@ -440,7 +441,7 @@ which corresponds to --interact and --interactive;
<term><literal>keep_going</literal></term>
<listitem>
<para>
-which corresponds to -k and --keep-going;
+which corresponds to <option>-k</option> and <option>--keep-going</option>;
</para>
</listitem>
</varlistentry>
@@ -448,7 +449,7 @@ which corresponds to -k and --keep-going;
<term><literal>max_drift</literal></term>
<listitem>
<para>
-which corresponds to --max-drift;
+which corresponds to <option>--max-drift</option>;
</para>
</listitem>
</varlistentry>
@@ -456,7 +457,9 @@ which corresponds to --max-drift;
<term><literal>no_exec</literal></term>
<listitem>
<para>
-which corresponds to -n, --no-exec, --just-print, --dry-run and --recon;
+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>
@@ -464,7 +467,7 @@ which corresponds to -n, --no-exec, --just-print, --dry-run and --recon;
<term><literal>no_site_dir</literal></term>
<listitem>
<para>
-which corresponds to --no-site-dir;
+which corresponds to <option>--no-site-dir</option>;
</para>
</listitem>
</varlistentry>
@@ -472,7 +475,7 @@ which corresponds to --no-site-dir;
<term><literal>num_jobs</literal></term>
<listitem>
<para>
-which corresponds to -j and --jobs;
+which corresponds to <option>-j</option> and <option>--jobs</option>;
</para>
</listitem>
</varlistentry>
@@ -480,7 +483,7 @@ which corresponds to -j and --jobs;
<term><literal>profile_file</literal></term>
<listitem>
<para>
-which corresponds to --profile;
+which corresponds to <option>--profile</option>;
</para>
</listitem>
</varlistentry>
@@ -488,7 +491,7 @@ which corresponds to --profile;
<term><literal>question</literal></term>
<listitem>
<para>
-which corresponds to -q and --question;
+which corresponds to <option>-q</option> and <option>--question</option>;
</para>
</listitem>
</varlistentry>
@@ -496,7 +499,7 @@ which corresponds to -q and --question;
<term><literal>random</literal></term>
<listitem>
<para>
-which corresponds to --random;
+which corresponds to <option>--random</option>;
</para>
</listitem>
</varlistentry>
@@ -504,7 +507,7 @@ which corresponds to --random;
<term><literal>repository</literal></term>
<listitem>
<para>
-which corresponds to -Y, --repository and --srcdir;
+which corresponds to <option>-Y</option>, <option>--repository</option> and <option>--srcdir</option>;
</para>
</listitem>
</varlistentry>
@@ -512,7 +515,7 @@ which corresponds to -Y, --repository and --srcdir;
<term><literal>silent</literal></term>
<listitem>
<para>
-which corresponds to -s, --silent and --quiet;
+which corresponds to <option>-s</option>, <option>--silent</option> and <option>--quiet</option>;
</para>
</listitem>
</varlistentry>
@@ -520,7 +523,7 @@ which corresponds to -s, --silent and --quiet;
<term><literal>site_dir</literal></term>
<listitem>
<para>
-which corresponds to --site-dir;
+which corresponds to <option>--site-dir</option>;
</para>
</listitem>
</varlistentry>
@@ -528,7 +531,7 @@ which corresponds to --site-dir;
<term><literal>stack_size</literal></term>
<listitem>
<para>
-which corresponds to --stack-size;
+which corresponds to <option>--stack-size</option>;
</para>
</listitem>
</varlistentry>
@@ -536,7 +539,7 @@ which corresponds to --stack-size;
<term><literal>taskmastertrace_file</literal></term>
<listitem>
<para>
-which corresponds to --taskmastertrace; and
+which corresponds to <option>--taskmastertrace</option>; and
</para>
</listitem>
</varlistentry>
@@ -544,7 +547,7 @@ which corresponds to --taskmastertrace; and
<term><literal>warn</literal></term>
<listitem>
<para>
-which corresponds to --warn and --warning.
+which corresponds to <option>--warn</option> and <option>--warning</option>.
</para>
</listitem>
</varlistentry>
@@ -553,7 +556,7 @@ which corresponds to --warn and --warning.
<para>
See the documentation for the
-corresponding command line object for information about each specific
+corresponding command line option for information about each specific
option.
</para>
</summary>
@@ -749,7 +752,8 @@ line options from a SConscript file. The options supported are:
<term><literal>clean</literal></term>
<listitem>
<para>
-which corresponds to -c, --clean and --remove;
+which corresponds to <option>-c</option>, <option>--clean</option>
+and <option>--remove</option>;
</para>
</listitem>
</varlistentry>
@@ -757,7 +761,7 @@ which corresponds to -c, --clean and --remove;
<term><literal>duplicate</literal></term>
<listitem>
<para>
-which corresponds to --duplicate;
+which corresponds to <option>--duplicate</option>;
</para>
</listitem>
</varlistentry>
@@ -765,7 +769,7 @@ which corresponds to --duplicate;
<term><literal>help</literal></term>
<listitem>
<para>
-which corresponds to -h and --help;
+which corresponds to <option>-h</option> and <option>--help</option>;
</para>
</listitem>
</varlistentry>
@@ -773,7 +777,7 @@ which corresponds to -h and --help;
<term><literal>implicit_cache</literal></term>
<listitem>
<para>
-which corresponds to --implicit-cache;
+which corresponds to <option>--implicit-cache</option>;
</para>
</listitem>
</varlistentry>
@@ -781,7 +785,7 @@ which corresponds to --implicit-cache;
<term><literal>max_drift</literal></term>
<listitem>
<para>
-which corresponds to --max-drift;
+which corresponds to <option>--max-drift</option>;
</para>
</listitem>
</varlistentry>
@@ -789,7 +793,9 @@ which corresponds to --max-drift;
<term><literal>no_exec</literal></term>
<listitem>
<para>
-which corresponds to -n, --no-exec, --just-print, --dry-run and --recon;
+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>
@@ -797,7 +803,7 @@ which corresponds to -n, --no-exec, --just-print, --dry-run and --recon;
<term><literal>num_jobs</literal></term>
<listitem>
<para>
-which corresponds to -j and --jobs;
+which corresponds to <option>-j</option> and <option>--jobs</option>;
</para>
</listitem>
</varlistentry>
@@ -805,7 +811,7 @@ which corresponds to -j and --jobs;
<term><literal>random</literal></term>
<listitem>
<para>
-which corresponds to --random; and
+which corresponds to <option>--random</option>; and
</para>
</listitem>
</varlistentry>
@@ -813,7 +819,7 @@ which corresponds to --random; and
<term><literal>silent</literal></term>
<listitem>
<para>
-which corresponds to --silent.
+which corresponds to <option>--silent</option>.
</para>
</listitem>
</varlistentry>
@@ -830,7 +836,7 @@ which corresponds to --stack-size.
<para>
See the documentation for the
-corresponding command line object for information about each specific
+corresponding command line option for information about each specific
option.
</para>
diff --git a/src/engine/SCons/Subst.xml b/src/engine/SCons/Subst.xml
index 980a9ad..77372ce 100644
--- a/src/engine/SCons/Subst.xml
+++ b/src/engine/SCons/Subst.xml
@@ -39,7 +39,7 @@ or
<literal>IndexError</literal>
exception will expand to a
<literal>''</literal>
-(a null string) and not cause scons to fail.
+(an empty string) and not cause scons to fail.
All exceptions not in the specified list
will generate an error message
and terminate processing.
diff --git a/src/engine/SCons/SubstTests.py b/src/engine/SCons/SubstTests.py
index c25b377..574e714 100644
--- a/src/engine/SCons/SubstTests.py
+++ b/src/engine/SCons/SubstTests.py
@@ -20,8 +20,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.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py
index 1e5776c..6ca0e03 100644
--- a/src/engine/SCons/Taskmaster.py
+++ b/src/engine/SCons/Taskmaster.py
@@ -20,8 +20,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.
-from __future__ import print_function
-
import sys
__doc__ = """
@@ -171,7 +169,7 @@ class Task(object):
"""
global print_prepare
T = self.tm.trace
- if T: T.write(self.trace_message(u'Task.prepare()', self.node))
+ if T: T.write(self.trace_message('Task.prepare()', self.node))
# Now that it's the appropriate time, give the TaskMaster a
# chance to raise any exceptions it encountered while preparing
@@ -233,7 +231,7 @@ class Task(object):
prepare(), executed() or failed().
"""
T = self.tm.trace
- if T: T.write(self.trace_message(u'Task.execute()', self.node))
+ if T: T.write(self.trace_message('Task.execute()', self.node))
try:
cached_targets = []
@@ -399,7 +397,7 @@ class Task(object):
"""
global print_prepare
T = self.tm.trace
- if T: T.write(self.trace_message(u'Task.make_ready_current()',
+ if T: T.write(self.trace_message('Task.make_ready_current()',
self.node))
self.out_of_date = []
@@ -447,7 +445,7 @@ class Task(object):
that can be put back on the candidates list.
"""
T = self.tm.trace
- if T: T.write(self.trace_message(u'Task.postprocess()', self.node))
+ if T: T.write(self.trace_message('Task.postprocess()', self.node))
# We may have built multiple targets, some of which may have
# common parents waiting for this build. Count up how many
@@ -464,7 +462,7 @@ class Task(object):
# A node can only be in the pending_children set if it has
# some waiting_parents.
if t.waiting_parents:
- if T: T.write(self.trace_message(u'Task.postprocess()',
+ if T: T.write(self.trace_message('Task.postprocess()',
t,
'removing'))
pending_children.discard(t)
@@ -493,7 +491,7 @@ class Task(object):
for p, subtract in parents.items():
p.ref_count = p.ref_count - subtract
- if T: T.write(self.trace_message(u'Task.postprocess()',
+ if T: T.write(self.trace_message('Task.postprocess()',
p,
'adjusted parent ref count'))
if p.ref_count == 0:
@@ -555,15 +553,12 @@ class Task(object):
exc_traceback = None
# raise exc_type(exc_value).with_traceback(exc_traceback)
- if sys.version_info[0] == 2:
- exec("raise exc_type, exc_value, exc_traceback")
- else: # sys.version_info[0] == 3:
- if isinstance(exc_value, Exception): #hasattr(exc_value, 'with_traceback'):
- # If exc_value is an exception, then just reraise
- exec("raise exc_value.with_traceback(exc_traceback)")
- else:
- # else we'll create an exception using the value and raise that
- exec("raise exc_type(exc_value).with_traceback(exc_traceback)")
+ if isinstance(exc_value, Exception): #hasattr(exc_value, 'with_traceback'):
+ # If exc_value is an exception, then just reraise
+ raise exc_value.with_traceback(exc_traceback)
+ else:
+ # else we'll create an exception using the value and raise that
+ raise exc_type(exc_value).with_traceback(exc_traceback)
# raise e.__class__, e.__class__(e), sys.exc_info()[2]
@@ -797,7 +792,7 @@ class Taskmaster(object):
while True:
node = self.next_candidate()
if node is None:
- if T: T.write(self.trace_message('No candidate anymore.') + u'\n')
+ if T: T.write(self.trace_message('No candidate anymore.') + '\n')
return None
node = node.disambiguate()
@@ -820,7 +815,7 @@ class Taskmaster(object):
else:
S = None
- if T: T.write(self.trace_message(u' Considering node %s and its children:' % self.trace_node(node)))
+ if T: T.write(self.trace_message(' Considering node %s and its children:' % self.trace_node(node)))
if state == NODE_NO_STATE:
# Mark this node as being on the execution stack:
@@ -828,7 +823,7 @@ class Taskmaster(object):
elif state > NODE_PENDING:
# Skip this node if it has already been evaluated:
if S: S.already_handled = S.already_handled + 1
- if T: T.write(self.trace_message(u' already handled (executed)'))
+ if T: T.write(self.trace_message(' already handled (executed)'))
continue
executor = node.get_executor()
@@ -859,7 +854,7 @@ class Taskmaster(object):
for child in chain(executor.get_all_prerequisites(), children):
childstate = child.get_state()
- if T: T.write(self.trace_message(u' ' + self.trace_node(child)))
+ if T: T.write(self.trace_message(' ' + self.trace_node(child)))
if childstate == NODE_NO_STATE:
children_not_visited.append(child)
@@ -920,7 +915,7 @@ class Taskmaster(object):
# count so we can be put back on the list for
# re-evaluation when they've all finished.
node.ref_count = node.ref_count + child.add_to_waiting_parents(node)
- if T: T.write(self.trace_message(u' adjusted ref count: %s, child %s' %
+ if T: T.write(self.trace_message(' adjusted ref count: %s, child %s' %
(self.trace_node(node), repr(str(child)))))
if T:
@@ -946,7 +941,7 @@ class Taskmaster(object):
# The default when we've gotten through all of the checks above:
# this node is ready to be built.
if S: S.build = S.build + 1
- if T: T.write(self.trace_message(u'Evaluating %s\n' %
+ if T: T.write(self.trace_message('Evaluating %s\n' %
self.trace_node(node)))
# For debugging only:
diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py
index c0c77b0..58a31aa 100644
--- a/src/engine/SCons/TaskmasterTests.py
+++ b/src/engine/SCons/TaskmasterTests.py
@@ -20,8 +20,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.
#
-from __future__ import division
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -146,7 +144,7 @@ class Node(object):
pass
def has_builder(self):
- return not self.builder is None
+ return self.builder is not None
def is_derived(self):
return self.has_builder or self.side_effect
@@ -935,7 +933,7 @@ class TaskmasterTestCase(unittest.TestCase):
except SCons.Errors.UserError:
pass
else:
- raise TestFailed("did not catch expected UserError")
+ self.fail("did not catch expected UserError")
def raise_BuildError():
raise SCons.Errors.BuildError
@@ -948,7 +946,7 @@ class TaskmasterTestCase(unittest.TestCase):
except SCons.Errors.BuildError:
pass
else:
- raise TestFailed("did not catch expected BuildError")
+ self.fail("did not catch expected BuildError")
# On a generic (non-BuildError) exception from a Builder,
# the target should throw a BuildError exception with the
@@ -968,7 +966,7 @@ class TaskmasterTestCase(unittest.TestCase):
exc_traceback = sys.exc_info()[2]
assert isinstance(e.exc_info[2], type(exc_traceback)), e.exc_info[2]
else:
- raise TestFailed("did not catch expected BuildError")
+ self.fail("did not catch expected BuildError")
built_text = None
cache_text = []
@@ -1049,7 +1047,7 @@ class TaskmasterTestCase(unittest.TestCase):
assert cache_text == ["n1 retrieved"], cache_text
# If no binfo exists anymore, something has gone wrong...
has_binfo = hasattr(n1, 'binfo')
- assert has_binfo == True, has_binfo
+ assert has_binfo, has_binfo
def test_exception(self):
"""Test generic Taskmaster exception handling
diff --git a/src/engine/SCons/Tool/DCommon.py b/src/engine/SCons/Tool/DCommon.py
index 71c4d8d..d29db3a 100644
--- a/src/engine/SCons/Tool/DCommon.py
+++ b/src/engine/SCons/Tool/DCommon.py
@@ -1,5 +1,3 @@
-from __future__ import print_function
-
"""SCons.Tool.DCommon
Common code for the various D tools.
diff --git a/src/engine/SCons/Tool/DCommon.xml b/src/engine/SCons/Tool/DCommon.xml
index 7cc47da..6d907c6 100644
--- a/src/engine/SCons/Tool/DCommon.xml
+++ b/src/engine/SCons/Tool/DCommon.xml
@@ -27,6 +27,7 @@ See its __doc__ string for a discussion of the format.
<summary>
<para>
The D compiler to use.
+See also &cv-link-SHDC; for compiling to shared objects.
</para>
</summary>
</cvar>
@@ -37,6 +38,18 @@ The D compiler to use.
The command line used to compile a D file to an object file.
Any options specified in the &cv-link-DFLAGS; construction variable
is included on this command line.
+See also &cv-link-SHDCOM; for compiling to shared objects.
+</para>
+</summary>
+</cvar>
+
+<cvar name="DCOMSTR">
+<summary>
+<para>
+If set, the string displayed when a D source file
+is compiled to a (static) object file.
+If not set, then &cv-link-DCOM; (the command line) is displayed.
+See also &cv-link-SHDCOMSTR; for compiling to shared objects.
</para>
</summary>
</cvar>
@@ -181,6 +194,7 @@ DLIBLINKSUFFIX.
<summary>
<para>
Name of the linker to use for linking systems including D sources.
+See also &cv-link-SHDLINK; for linking shared objects.
</para>
</summary>
</cvar>
@@ -189,6 +203,7 @@ Name of the linker to use for linking systems including D sources.
<summary>
<para>
The command line to use when linking systems including D sources.
+See also &cv-link-SHDLINKCOM; for linking shared objects.
</para>
</summary>
</cvar>
@@ -197,6 +212,7 @@ The command line to use when linking systems including D sources.
<summary>
<para>
List of linker flags.
+See also &cv-link-SHDLINKFLAGS; for linking shared objects.
</para>
</summary>
</cvar>
@@ -278,6 +294,7 @@ DVERSUFFIX.
<para>
The name of the compiler to use when compiling D source
destined to be in a shared objects.
+See also &cv-link-DC; for compiling to static objects.
</para>
</summary>
</cvar>
@@ -286,6 +303,18 @@ destined to be in a shared objects.
<summary>
<para>
The command line to use when compiling code to be part of shared objects.
+See also &cv-link-DCOM; for compiling to static objects.
+</para>
+</summary>
+</cvar>
+
+<cvar name="SHDCOMSTR">
+<summary>
+<para>
+If set, the string displayed when a D source file
+is compiled to a (shared) object file.
+If not set, then &cv-link-SHDCOM; (the command line) is displayed.
+See also &cv-link-DCOMSTR; for compiling to static objects.
</para>
</summary>
</cvar>
@@ -311,6 +340,7 @@ SHDLIBVERSIONFLAGS.
<para>
The linker to use when creating shared objects for code bases
include D sources.
+See also &cv-link-DLINK; for linking static objects.
</para>
</summary>
</cvar>
@@ -319,6 +349,7 @@ include D sources.
<summary>
<para>
The command line to use when generating shared objects.
+See also &cv-link-DLINKCOM; for linking static objects.
</para>
</summary>
</cvar>
@@ -327,6 +358,7 @@ The command line to use when generating shared objects.
<summary>
<para>
The list of flags to use when generating a shared object.
+See also &cv-link-DLINKFLAGS; for linking static objects.
</para>
</summary>
</cvar>
diff --git a/src/engine/SCons/Tool/FortranCommon.py b/src/engine/SCons/Tool/FortranCommon.py
index cbb9a03..bfa1c1c 100644
--- a/src/engine/SCons/Tool/FortranCommon.py
+++ b/src/engine/SCons/Tool/FortranCommon.py
@@ -26,8 +26,6 @@ Stuff for processing Fortran, common to all fortran dialects.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import re
diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py
index 386f445..505136e 100644
--- a/src/engine/SCons/Tool/MSCommon/common.py
+++ b/src/engine/SCons/Tool/MSCommon/common.py
@@ -23,8 +23,6 @@ Common helper functions for working with the Microsoft tool chain.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import copy
@@ -152,8 +150,8 @@ def normalize_env(env, keys, force=False):
Note: the environment is copied."""
normenv = {}
if env:
- for k in list(env.keys()):
- normenv[k] = copy.deepcopy(env[k])
+ for k, v in env.items():
+ normenv[k] = copy.deepcopy(v)
for k in keys:
if k in os.environ and (force or k not in normenv):
diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py
index 6f9bd12..82fb6b9 100644
--- a/src/engine/SCons/Tool/MSCommon/vc.py
+++ b/src/engine/SCons/Tool/MSCommon/vc.py
@@ -22,6 +22,9 @@
#
# TODO:
+# * gather all the information from a single vswhere call instead
+# of calling repeatedly (use json format?)
+# * support passing/setting location for vswhere in env.
# * supported arch for versions: for old versions of batch file without
# argument, giving bogus argument cannot be detected, so we have to hardcode
# this here
@@ -42,19 +45,14 @@ import os
import platform
import sys
from string import digits as string_digits
-if sys.version_info[0] == 2:
- import collections
+from subprocess import PIPE
import SCons.Warnings
from SCons.Tool import find_program_path
from . import common
-
-debug = common.debug
-
-from . import sdk
-
-get_installed_sdks = sdk.get_installed_sdks
+from .common import CONFIG_CACHE, debug
+from .sdk import get_installed_sdks
class VisualCException(Exception):
@@ -95,6 +93,10 @@ _ARCH_TO_CANONICAL = {
"aarch64" : "arm64",
}
+# Starting with 14.1 (aka VS2017), the tools are organized by host directory.
+# subdirs for each target. They are now in .../VC/Auxuiliary/Build.
+# Note 2017 Express uses Hostx86 even if it's on 64-bit Windows,
+# not reflected in this table.
_HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 = {
("amd64","amd64") : ("Hostx64","x64"),
("amd64","x86") : ("Hostx64","x86"),
@@ -106,8 +108,9 @@ _HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 = {
("x86","arm64") : ("Hostx86","arm64"),
}
-# get path to the cl.exe dir for older VS versions
-# based off a tuple of (host, target) platforms
+# before 14.1 (VS2017): the original x86 tools are in the tools dir,
+# any others are in a subdir named by the host/target pair,
+# or just a single word if host==target
_HOST_TARGET_TO_CL_DIR = {
("amd64","amd64") : "amd64",
("amd64","x86") : "amd64_x86",
@@ -117,10 +120,38 @@ _HOST_TARGET_TO_CL_DIR = {
("x86","x86") : "",
("x86","arm") : "x86_arm",
("x86","arm64") : "x86_arm64",
+ ("arm","arm") : "arm",
}
-# Given a (host, target) tuple, return the argument for the bat file.
-# Both host and targets should be canonalized.
+# 14.1 (VS2017) and later:
+# Given a (host, target) tuple, return the batch file to look for.
+# We can't rely on returning an arg to use for vcvarsall.bat,
+# because that script will run even if given a pair that isn't installed.
+# Targets that already look like a pair are pseudo targets that
+# effectively mean to skip whatever the host was specified as.
+_HOST_TARGET_TO_BAT_ARCH_GT14 = {
+ ("amd64", "amd64"): "vcvars64.bat",
+ ("amd64", "x86"): "vcvarsamd64_x86.bat",
+ ("amd64", "x86_amd64"): "vcvarsx86_amd64.bat",
+ ("amd64", "x86_x86"): "vcvars32.bat",
+ ("amd64", "arm"): "vcvarsamd64_arm.bat",
+ ("amd64", "x86_arm"): "vcvarsx86_arm.bat",
+ ("amd64", "arm64"): "vcvarsamd64_arm64.bat",
+ ("amd64", "x86_arm64"): "vcvarsx86_arm64.bat",
+ ("x86", "x86"): "vcvars32.bat",
+ ("x86", "amd64"): "vcvarsx86_amd64.bat",
+ ("x86", "x86_amd64"): "vcvarsx86_amd64.bat",
+ ("x86", "arm"): "vcvarsx86_arm.bat",
+ ("x86", "x86_arm"): "vcvarsx86_arm.bat",
+ ("x86", "arm64"): "vcvarsx86_arm64.bat",
+ ("x86", "x86_arm64"): "vcvarsx86_arm64.bat",
+}
+
+# before 14.1 (VS2017):
+# Given a (host, target) tuple, return the argument for the bat file;
+# Both host and target should be canoncalized.
+# If the target already looks like a pair, return it - these are
+# pseudo targets (mainly used by Express versions)
_HOST_TARGET_ARCH_TO_BAT_ARCH = {
("x86", "x86"): "x86",
("x86", "amd64"): "x86_amd64",
@@ -128,12 +159,16 @@ _HOST_TARGET_ARCH_TO_BAT_ARCH = {
("amd64", "x86_amd64"): "x86_amd64", # This is present in (at least) VS2012 express
("amd64", "amd64"): "amd64",
("amd64", "x86"): "x86",
+ ("amd64", "x86_x86"): "x86",
("x86", "ia64"): "x86_ia64", # gone since 14.0
- ("arm", "arm"): "arm", # since 14.0, maybe gone 14.1?
("x86", "arm"): "x86_arm", # since 14.0
("x86", "arm64"): "x86_arm64", # since 14.1
("amd64", "arm"): "amd64_arm", # since 14.0
("amd64", "arm64"): "amd64_arm64", # since 14.1
+ ("x86", "x86_arm"): "x86_arm", # since 14.0
+ ("x86", "x86_arm64"): "x86_arm64", # since 14.1
+ ("amd64", "x86_arm"): "x86_arm", # since 14.0
+ ("amd64", "x86_arm64"): "x86_arm64", # since 14.1
}
_CL_EXE_NAME = 'cl.exe'
@@ -194,7 +229,7 @@ def get_host_target(env):
# If you update this, update SupportedVSList in Tool/MSCommon/vs.py, and the
# MSVC_VERSION documentation in Tool/msvc.xml.
-_VCVER = ["14.2", "14.1", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"]
+_VCVER = ["14.2", "14.1", "14.1Exp", "14.0", "14.0Exp", "12.0", "12.0Exp", "11.0", "11.0Exp", "10.0", "10.0Exp", "9.0", "9.0Exp","8.0", "8.0Exp","7.1", "7.0", "6.0"]
# if using vswhere, a further mapping is needed
_VCVER_TO_VSWHERE_VER = {
@@ -204,9 +239,11 @@ _VCVER_TO_VSWHERE_VER = {
_VCVER_TO_PRODUCT_DIR = {
'14.2' : [
- (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # VS 2019 doesn't set this key
+ (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version
'14.1' : [
- (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # VS 2017 doesn't set this key
+ (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version
+ '14.1Exp' : [
+ (SCons.Util.HKEY_LOCAL_MACHINE, r'')], # not set by this version
'14.0' : [
(SCons.Util.HKEY_LOCAL_MACHINE, r'Microsoft\VisualStudio\14.0\Setup\VC\ProductDir')],
'14.0Exp' : [
@@ -299,44 +336,46 @@ def find_vc_pdir_vswhere(msvc_version):
debug("Unknown version of MSVC: %s" % msvc_version)
raise UnsupportedVersion("Unknown version %s" % msvc_version)
- # For bug 3333 - support default location of vswhere for both 64 and 32 bit windows
- # installs.
- for pf in ['Program Files (x86)', 'Program Files']:
- vswhere_path = os.path.join(
- 'C:\\',
- pf,
- 'Microsoft Visual Studio',
- 'Installer',
- 'vswhere.exe'
- )
+ # For bug 3333: support default location of vswhere for both
+ # 64 and 32 bit windows installs.
+ # For bug 3542: also accommodate not being on C: drive.
+ # NB: this gets called from testsuite on non-Windows platforms.
+ # Whether that makes sense or not, don't break it for those.
+ # TODO: requested to add a user-specified path to vswhere
+ # and have this routine set the same var if it finds it.
+ pfpaths = [
+ os.path.expandvars(r"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer"),
+ os.path.expandvars(r"%ProgramFiles%\Microsoft Visual Studio\Installer"),
+ os.path.expandvars(r"%ChocolateyInstall%\bin"),
+ ]
+ for pf in pfpaths:
+ vswhere_path = os.path.join(pf, "vswhere.exe")
if os.path.exists(vswhere_path):
- # If we found vswhere, then use it.
break
else:
- # No vswhere on system, no install info available
+ # No vswhere on system, no install info available this way
return None
- vswhere_cmd = [vswhere_path,
- '-products', '*',
- '-version', vswhere_version,
- '-property', 'installationPath']
-
- #TODO PY27 cannot use Popen as context manager
- # try putting it back to the old way for now
- sp = subprocess.Popen(vswhere_cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE)
- vsdir, err = sp.communicate()
- if vsdir:
- vsdir = vsdir.decode("mbcs").splitlines()
- # vswhere could easily return multiple lines
- # we could define a way to pick the one we prefer, but since
+ vswhere_cmd = [
+ vswhere_path,
+ "-products", "*",
+ "-version", vswhere_version,
+ "-property", "installationPath",
+ ]
+
+ #cp = subprocess.run(vswhere_cmd, capture_output=True) # 3.7+ only
+ cp = subprocess.run(vswhere_cmd, stdout=PIPE, stderr=PIPE)
+
+ if cp.stdout:
+ # vswhere could return multiple lines, e.g. if Build Tools
+ # and {Community,Professional,Enterprise} are both installed.
+ # We could define a way to pick the one we prefer, but since
# this data is currently only used to make a check for existence,
- # returning the first hit should be good enough for now.
- vc_pdir = os.path.join(vsdir[0], 'VC')
- return vc_pdir
+ # returning the first hit should be good enough.
+ lines = cp.stdout.decode("mbcs").splitlines()
+ return os.path.join(lines[0], 'VC')
else:
- # No vswhere on system, no install info available
+ # We found vswhere, but no install info available for this version
return None
@@ -403,15 +442,20 @@ def find_batch_file(env,msvc_version,host_arch,target_arch):
"""
Find the location of the batch script which should set up the compiler
for any TARGET_ARCH whose compilers were installed by Visual Studio/VCExpress
+
+ In newer (2017+) compilers, make use of the fact there are vcvars
+ scripts named with a host_target pair that calls vcvarsall.bat properly,
+ so use that and return an indication we don't need the argument
+ we would have computed to run vcvarsall.bat.
"""
pdir = find_vc_pdir(msvc_version)
if pdir is None:
raise NoVersionFound("No version of Visual Studio found")
-
debug('find_batch_file() in {}'.format(pdir))
# filter out e.g. "Exp" from the version name
msvc_ver_numeric = get_msvc_version_numeric(msvc_version)
+ use_arg = True
vernum = float(msvc_ver_numeric)
if 7 <= vernum < 8:
pdir = os.path.join(pdir, os.pardir, "Common7", "Tools")
@@ -422,7 +466,10 @@ def find_batch_file(env,msvc_version,host_arch,target_arch):
elif 8 <= vernum <= 14:
batfilename = os.path.join(pdir, "vcvarsall.bat")
else: # vernum >= 14.1 VS2017 and above
- batfilename = os.path.join(pdir, "Auxiliary", "Build", "vcvarsall.bat")
+ batfiledir = os.path.join(pdir, "Auxiliary", "Build")
+ targ = _HOST_TARGET_TO_BAT_ARCH_GT14[(host_arch, target_arch)]
+ batfilename = os.path.join(batfiledir, targ)
+ use_arg = False
if not os.path.exists(batfilename):
debug("Not found: %s" % batfilename)
@@ -437,8 +484,8 @@ def find_batch_file(env,msvc_version,host_arch,target_arch):
sdk_bat_file_path = os.path.join(pdir,sdk_bat_file)
if os.path.exists(sdk_bat_file_path):
debug('find_batch_file() sdk_bat_file_path:%s'%sdk_bat_file_path)
- return (batfilename, sdk_bat_file_path)
- return (batfilename, None)
+ return (batfilename, use_arg, sdk_bat_file_path)
+ return (batfilename, use_arg, None)
__INSTALLED_VCS_RUN = None
@@ -446,10 +493,12 @@ _VC_TOOLS_VERSION_FILE_PATH = ['Auxiliary', 'Build', 'Microsoft.VCToolsVersion.d
_VC_TOOLS_VERSION_FILE = os.sep.join(_VC_TOOLS_VERSION_FILE_PATH)
def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version):
- """Find the cl.exe on the filesystem in the vc_dir depending on
- TARGET_ARCH, HOST_ARCH and the msvc version. TARGET_ARCH and
- HOST_ARCH can be extracted from the passed env, unless its None,
- which then the native platform is assumed the host and target.
+ """Return status of finding a cl.exe to use.
+
+ Locates cl in the vc_dir depending on TARGET_ARCH, HOST_ARCH and the
+ msvc version. TARGET_ARCH and HOST_ARCH can be extracted from the
+ passed env, unless it is None, in which case the native platform is
+ assumed for both host and target.
Args:
env: Environment
@@ -484,7 +533,8 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version):
# make sure the cl.exe exists meaning the tool is installed
if ver_num > 14:
- # 2017 and newer allowed multiple versions of the VC toolset to be installed at the same time.
+ # 2017 and newer allowed multiple versions of the VC toolset to be
+ # installed at the same time. This changes the layout.
# Just get the default tool version for now
#TODO: support setting a specific minor VC version
default_toolset_file = os.path.join(vc_dir, _VC_TOOLS_VERSION_FILE)
@@ -509,10 +559,24 @@ def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version):
debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!')
return True
+ elif host_platform == "amd64" and host_trgt_dir[0] == "Hostx64":
+ # Special case: fallback to Hostx86 if Hostx64 was tried
+ # and failed. This is because VS 2017 Express running on amd64
+ # will look to our probe like the host dir should be Hostx64,
+ # but Express uses Hostx86 anyway.
+ # We should key this off the "x86_amd64" and related pseudo
+ # targets, but we don't see those in this function.
+ host_trgt_dir = ("Hostx86", host_trgt_dir[1])
+ cl_path = os.path.join(vc_dir, 'Tools','MSVC', vc_specific_version, 'bin', host_trgt_dir[0], host_trgt_dir[1], _CL_EXE_NAME)
+ debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path)
+ if os.path.exists(cl_path):
+ debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!')
+ return True
+
elif 14 >= ver_num >= 8:
- # Set default value to be -1 as "" which is the value for x86/x86 yields true when tested
- # if not host_trgt_dir
+ # Set default value to be -1 as "" which is the value for x86/x86
+ # yields true when tested if not host_trgt_dir
host_trgt_dir = _HOST_TARGET_TO_CL_DIR.get((host_platform, target_platform), None)
if host_trgt_dir is None:
debug('_check_cl_exists_in_vc_dir(): unsupported host/target platform combo')
@@ -604,7 +668,7 @@ def reset_installed_vcs():
# within the same scons run. Windows builds on the CI system were split
# into chunks to get around single-build time limits.
# With VS2019 it got even slower and an optional persistent cache file
-# was introduced. The cache now also stores only the parsed vars,
+# was introduced. The cache now also stores only the parsed vars,
# not the entire output of running the batch file - saves a bit
# of time not parsing every time.
@@ -630,23 +694,7 @@ def script_env(script, args=None):
script_env_cache[cache_key] = cache_data
# once we updated cache, give a chance to write out if user wanted
common.write_script_env_cache(script_env_cache)
- else:
- #TODO: Python 2 cleanup
- # If we "hit" data from the json file, we have a Py2 problem:
- # keys & values will be unicode. don't detect, just convert.
- if sys.version_info[0] == 2:
- def convert(data):
- if isinstance(data, basestring):
- return str(data)
- elif isinstance(data, collections.Mapping):
- return dict(map(convert, data.iteritems()))
- elif isinstance(data, collections.Iterable):
- return type(data)(map(convert, data))
- else:
- return data
- cache_data = convert(cache_data)
-
return cache_data
def get_default_version(env):
@@ -696,33 +744,56 @@ def msvc_setup_env_once(env):
env["MSVC_SETUP_RUN"] = True
def msvc_find_valid_batch_script(env, version):
- debug('msvc_find_valid_batch_script()')
- # Find the host platform, target platform, and if present the requested
- # target platform
+ """Find and execute appropriate batch script to set up build env.
+
+ The MSVC build environment depends heavily on having the shell
+ environment set. SCons does not inherit that, and does not count
+ on that being set up correctly anyway, so it tries to find the right
+ MSVC batch script, or the right arguments to the generic batch script
+ vcvarsall.bat, and run that, so we have a valid environment to build in.
+ There are dragons here: the batch scripts don't fail (see comments
+ elsewhere), they just leave you with a bad setup, so try hard to
+ get it right.
+ """
+
+ # Find the host, target, and if present the requested target:
platforms = get_host_target(env)
debug(" msvs_find_valid_batch_script(): host_platform %s, target_platform %s req_target_platform:%s" % platforms)
-
host_platform, target_platform, req_target_platform = platforms
- try_target_archs = [target_platform]
- # VS2012 has a "cross compile" environment to build 64 bit
- # with x86_amd64 as the argument to the batch setup script
+ # Most combinations of host + target are straightforward.
+ # While all MSVC / Visual Studio tools are pysically 32-bit, they
+ # make it look like there are 64-bit tools if the host is 64-bit,
+ # so you can invoke the environment batch script to set up to build,
+ # say, amd64 host -> x86 target. Express versions are an exception:
+ # they always look 32-bit, so the batch scripts with 64-bit
+ # host parts are absent. We try to fix that up in a couple of ways.
+ # One is here: we make a table of "targets" to try, with the extra
+ # targets being tags that tell us to try a different "host" instead
+ # of the deduced host.
+ try_target_archs = [target_platform]
if req_target_platform in ('amd64', 'x86_64'):
try_target_archs.append('x86_amd64')
- elif not req_target_platform and target_platform in ['amd64', 'x86_64']:
- # There may not be "native" amd64, but maybe "cross" x86_amd64 tools
- try_target_archs.append('x86_amd64')
- # If the user hasn't specifically requested a TARGET_ARCH, and
- # The TARGET_ARCH is amd64 then also try 32 bits if there are no viable
- # 64 bit tools installed
- try_target_archs.append('x86')
+ elif req_target_platform in ('x86',):
+ try_target_archs.append('x86_x86')
+ elif req_target_platform in ('arm',):
+ try_target_archs.append('x86_arm')
+ elif req_target_platform in ('arm64',):
+ try_target_archs.append('x86_arm64')
+ elif not req_target_platform:
+ if target_platform in ('amd64', 'x86_64'):
+ try_target_archs.append('x86_amd64')
+ # If the user hasn't specifically requested a TARGET_ARCH,
+ # and the TARGET_ARCH is amd64 then also try 32 bits
+ # if there are no viable 64 bit tools installed
+ try_target_archs.append('x86')
debug("msvs_find_valid_batch_script(): host_platform: %s try_target_archs:%s"%(host_platform, try_target_archs))
d = None
for tp in try_target_archs:
# Set to current arch.
- env['TARGET_ARCH']=tp
+ env['TARGET_ARCH'] = tp
debug("msvc_find_valid_batch_script() trying target_platform:%s"%tp)
host_target = (host_platform, tp)
@@ -732,17 +803,9 @@ def msvc_find_valid_batch_script(env, version):
SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[host_target]
- # Get just version numbers
- maj, min = msvc_version_to_maj_min(version)
- # VS2015+
- if maj >= 14:
- if env.get('MSVC_UWP_APP') == '1':
- # Initialize environment variables with store/universal paths
- arg += ' store'
-
# Try to locate a batch file for this host/target platform combo
try:
- (vc_script, sdk_script) = find_batch_file(env, version, host_platform, tp)
+ (vc_script, use_arg, sdk_script) = find_batch_file(env, version, host_platform, tp)
debug('msvc_find_valid_batch_script() vc_script:%s sdk_script:%s'%(vc_script,sdk_script))
except VisualCException as e:
msg = str(e)
@@ -758,6 +821,16 @@ def msvc_find_valid_batch_script(env, version):
debug('msvc_find_valid_batch_script() use_script 2 %s, args:%s' % (repr(vc_script), arg))
found = None
if vc_script:
+ if not use_arg:
+ arg = '' # bat file will supply platform type
+ # Get just version numbers
+ maj, min = msvc_version_to_maj_min(version)
+ # VS2015+
+ if maj >= 14:
+ if env.get('MSVC_UWP_APP') == '1':
+ # Initialize environment variables with store/UWP paths
+ arg = (arg + ' store').lstrip()
+
try:
d = script_env(vc_script, args=arg)
found = vc_script
@@ -823,14 +896,18 @@ def msvc_setup_env(env):
return None
for k, v in d.items():
- debug('msvc_setup_env() env:%s -> %s'%(k,v))
env.PrependENVPath(k, v, delete_existing=True)
+ debug("msvc_setup_env() env['ENV']['%s'] = %s" % (k, env['ENV'][k]))
# final check to issue a warning if the compiler is not present
- msvc_cl = find_program_path(env, 'cl')
- if not msvc_cl:
- SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning,
- "Could not find MSVC compiler 'cl', it may need to be installed separately with Visual Studio")
+ if not find_program_path(env, 'cl'):
+ debug("msvc_setup_env() did not find 'cl'")
+ if CONFIG_CACHE:
+ propose = "SCONS_CACHE_MSVC_CONFIG caching enabled, remove cache file {} if out of date.".format(CONFIG_CACHE)
+ else:
+ propose = "It may need to be installed separately with Visual Studio."
+ warn_msg = "Could not find MSVC compiler 'cl'. {}".format(propose)
+ SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg)
def msvc_exists(env=None, version=None):
vcs = cached_get_installed_vcs(env)
diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py
index bac35d8..e13f52f 100644
--- a/src/engine/SCons/Tool/MSCommon/vs.py
+++ b/src/engine/SCons/Tool/MSCommon/vs.py
@@ -205,7 +205,8 @@ SupportedVSList = [
hkeys=[],
common_tools_var='VS160COMNTOOLS',
executable_path=r'Common7\IDE\devenv.com',
- batch_file_path=r'VC\Auxiliary\Build\vsvars32.bat',
+ # should be a fallback, prefer use vswhere installationPath
+ batch_file_path=r'Common7\Tools\VsDevCmd.bat',
supported_arch=['x86', 'amd64', "arm"],
),
@@ -216,10 +217,23 @@ SupportedVSList = [
hkeys=[],
common_tools_var='VS150COMNTOOLS',
executable_path=r'Common7\IDE\devenv.com',
- batch_file_path=r'VC\Auxiliary\Build\vsvars32.bat',
+ # should be a fallback, prefer use vswhere installationPath
+ batch_file_path=r'Common7\Tools\VsDevCmd.bat',
supported_arch=['x86', 'amd64', "arm"],
),
+ # Visual C++ 2017 Express Edition (for Desktop)
+ VisualStudio('14.1Exp',
+ vc_version='14.1',
+ sdk_version='10.0A',
+ hkeys=[],
+ common_tools_var='VS150COMNTOOLS',
+ executable_path=r'Common7\IDE\WDExpress.exe',
+ # should be a fallback, prefer use vswhere installationPath
+ batch_file_path=r'Common7\Tools\VsDevCmd.bat',
+ supported_arch=['x86', 'amd64', "arm"],
+ ),
+
# Visual Studio 2015
VisualStudio('14.0',
vc_version='14.0',
diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py
index 14306ab..4cb77c0 100644
--- a/src/engine/SCons/Tool/__init__.py
+++ b/src/engine/SCons/Tool/__init__.py
@@ -38,9 +38,9 @@ tool definition.
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import sys
-import re
import os
-import shutil
+from collections.abc import Callable
+import importlib.util
import SCons.Builder
import SCons.Errors
@@ -51,12 +51,6 @@ import SCons.Scanner.D
import SCons.Scanner.LaTeX
import SCons.Scanner.Prog
import SCons.Scanner.SWIG
-try:
- # Python 3
- from collections.abc import Callable
-except ImportError:
- # Python 2.7
- from collections import Callable
DefaultToolpath = []
@@ -142,112 +136,81 @@ class Tool(object):
sys.path = self.toolpath + sys.path
# sys.stderr.write("Tool:%s\nPATH:%s\n"%(self.name,sys.path))
- if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0, 1, 2, 3, 4)):
- # Py 2 code
- try:
- try:
- file = None
- try:
- mod, file = self._load_dotted_module_py2(self.name, self.name, self.toolpath)
- return mod
- finally:
- if file:
- file.close()
- except ImportError as e:
- splitname = self.name.split('.')
- if str(e) != "No module named %s" % splitname[0]:
- raise SCons.Errors.SConsEnvironmentError(e)
- try:
- import zipimport
- except ImportError:
- pass
- else:
- for aPath in self.toolpath:
- try:
- importer = zipimport.zipimporter(aPath)
- return importer.load_module(self.name)
- except ImportError as e:
- pass
- finally:
- sys.path = oldpythonpath
- elif sys.version_info[1] > 4:
- # From: http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path/67692#67692
- # import importlib.util
- # spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
- # foo = importlib.util.module_from_spec(spec)
- # spec.loader.exec_module(foo)
- # foo.MyClass()
- # Py 3 code
-
- # import pdb; pdb.set_trace()
- import importlib.util
-
- # sys.stderr.write("toolpath:%s\n" % self.toolpath)
- # sys.stderr.write("SCONS.TOOL path:%s\n" % sys.modules['SCons.Tool'].__path__)
- debug = False
- spec = None
- found_name = self.name
- add_to_scons_tools_namespace = False
- for path in self.toolpath:
- sepname = self.name.replace('.', os.path.sep)
- file_path = os.path.join(path, "%s.py" % sepname)
- file_package = os.path.join(path, sepname)
-
- if debug: sys.stderr.write("Trying:%s %s\n" % (file_path, file_package))
-
- if os.path.isfile(file_path):
- spec = importlib.util.spec_from_file_location(self.name, file_path)
- if debug: print("file_Path:%s FOUND" % file_path)
- break
- elif os.path.isdir(file_package):
- file_package = os.path.join(file_package, '__init__.py')
- spec = importlib.util.spec_from_file_location(self.name, file_package)
- if debug: print("PACKAGE:%s Found" % file_package)
- break
-
- else:
- continue
-
- if spec is None:
- if debug: sys.stderr.write("NO SPEC :%s\n" % self.name)
- spec = importlib.util.find_spec("." + self.name, package='SCons.Tool')
- if spec:
- found_name = 'SCons.Tool.' + self.name
- add_to_scons_tools_namespace = True
- if debug: sys.stderr.write("Spec Found? .%s :%s\n" % (self.name, spec))
-
- if spec is None:
- error_string = "No module named %s" % self.name
- raise SCons.Errors.SConsEnvironmentError(error_string)
-
- module = importlib.util.module_from_spec(spec)
- if module is None:
- if debug: print("MODULE IS NONE:%s" % self.name)
- error_string = "No module named %s" % self.name
- raise SCons.Errors.SConsEnvironmentError(error_string)
-
- # Don't reload a tool we already loaded.
- sys_modules_value = sys.modules.get(found_name, False)
-
- found_module = None
- if sys_modules_value and sys_modules_value.__file__ == spec.origin:
- found_module = sys.modules[found_name]
+ # From: http://stackoverflow.com/questions/67631/how-to-import-a-module-given-the-full-path/67692#67692
+ # import importlib.util
+ # spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
+ # foo = importlib.util.module_from_spec(spec)
+ # spec.loader.exec_module(foo)
+ # foo.MyClass()
+ # Py 3 code
+
+
+ # sys.stderr.write("toolpath:%s\n" % self.toolpath)
+ # sys.stderr.write("SCONS.TOOL path:%s\n" % sys.modules['SCons.Tool'].__path__)
+ debug = False
+ spec = None
+ found_name = self.name
+ add_to_scons_tools_namespace = False
+ for path in self.toolpath:
+ sepname = self.name.replace('.', os.path.sep)
+ file_path = os.path.join(path, "%s.py" % sepname)
+ file_package = os.path.join(path, sepname)
+
+ if debug: sys.stderr.write("Trying:%s %s\n" % (file_path, file_package))
+
+ if os.path.isfile(file_path):
+ spec = importlib.util.spec_from_file_location(self.name, file_path)
+ if debug: print("file_Path:%s FOUND" % file_path)
+ break
+ elif os.path.isdir(file_package):
+ file_package = os.path.join(file_package, '__init__.py')
+ spec = importlib.util.spec_from_file_location(self.name, file_package)
+ if debug: print("PACKAGE:%s Found" % file_package)
+ break
+
else:
- # Not sure what to do in the case that there already
- # exists sys.modules[self.name] but the source file is
- # different.. ?
- module = spec.loader.load_module(spec.name)
-
- sys.modules[found_name] = module
- if add_to_scons_tools_namespace:
- # If we found it in SCons.Tool, then add it to the module
- setattr(SCons.Tool, self.name, module)
+ continue
+
+ if spec is None:
+ if debug: sys.stderr.write("NO SPEC :%s\n" % self.name)
+ spec = importlib.util.find_spec("." + self.name, package='SCons.Tool')
+ if spec:
+ found_name = 'SCons.Tool.' + self.name
+ add_to_scons_tools_namespace = True
+ if debug: sys.stderr.write("Spec Found? .%s :%s\n" % (self.name, spec))
+
+ if spec is None:
+ error_string = "No module named %s" % self.name
+ raise SCons.Errors.SConsEnvironmentError(error_string)
+
+ module = importlib.util.module_from_spec(spec)
+ if module is None:
+ if debug: print("MODULE IS NONE:%s" % self.name)
+ error_string = "No module named %s" % self.name
+ raise SCons.Errors.SConsEnvironmentError(error_string)
+
+ # Don't reload a tool we already loaded.
+ sys_modules_value = sys.modules.get(found_name, False)
+
+ found_module = None
+ if sys_modules_value and sys_modules_value.__file__ == spec.origin:
+ found_module = sys.modules[found_name]
+ else:
+ # Not sure what to do in the case that there already
+ # exists sys.modules[self.name] but the source file is
+ # different.. ?
+ module = spec.loader.load_module(spec.name)
+
+ sys.modules[found_name] = module
+ if add_to_scons_tools_namespace:
+ # If we found it in SCons.Tool, then add it to the module
+ setattr(SCons.Tool, self.name, module)
- found_module = module
+ found_module = module
- if found_module is not None:
- sys.path = oldpythonpath
- return found_module
+ if found_module is not None:
+ sys.path = oldpythonpath
+ return found_module
sys.path = oldpythonpath
@@ -1130,7 +1093,7 @@ class ToolInitializer(object):
so we no longer copy and re-bind them when the construction
environment gets cloned.
"""
- for method in list(self.methods.values()):
+ for method in self.methods.values():
env.RemoveMethod(method)
def apply_tools(self, env):
@@ -1312,6 +1275,8 @@ def tool_list(platform, env):
'tar', 'zip',
# File builders (text)
'textfile',
+ # Python scanner tool
+ 'python',
], env)
tools = ([linker, c_compiler, cxx_compiler,
diff --git a/src/engine/SCons/Tool/c++.xml b/src/engine/SCons/Tool/c++.xml
index b59816b..019821c 100644
--- a/src/engine/SCons/Tool/c++.xml
+++ b/src/engine/SCons/Tool/c++.xml
@@ -47,6 +47,7 @@ Sets construction variables for generic POSIX C++ compilers.
</sets>
<uses>
<item>CXXCOMSTR</item>
+<item>SHCXXCOMSTR</item>
</uses>
</tool>
@@ -54,6 +55,7 @@ Sets construction variables for generic POSIX C++ compilers.
<summary>
<para>
The C++ compiler.
+See also &cv-link-SHCXX; for compiling to shared objects..
</para>
</summary>
</cvar>
@@ -65,6 +67,7 @@ The command line used to compile a C++ source file to an object file.
Any options specified in the &cv-link-CXXFLAGS; and
&cv-link-CPPFLAGS; construction variables
are included on this command line.
+See also &cv-link-SHCXXCOM; for compiling to shared objects..
</para>
</summary>
</cvar>
@@ -72,9 +75,10 @@ are included on this command line.
<cvar name="CXXCOMSTR">
<summary>
<para>
-The string displayed when a C++ source file
+If set, the string displayed when a C++ source file
is compiled to a (static) object file.
-If this is not set, then &cv-link-CXXCOM; (the command line) is displayed.
+If not set, then &cv-link-CXXCOM; (the command line) is displayed.
+See also &cv-link-SHCXXCOMSTR; for compiling to shared objects..
</para>
<example_commands>
@@ -91,6 +95,7 @@ By default, this includes the value of &cv-link-CCFLAGS;,
so that setting &cv-CCFLAGS; affects both C and C++ compilation.
If you want to add C++-specific flags,
you must set or override the value of &cv-link-CXXFLAGS;.
+See also &cv-link-SHCXXFLAGS; for compiling to shared objects..
</para>
</summary>
</cvar>
@@ -99,6 +104,7 @@ you must set or override the value of &cv-link-CXXFLAGS;.
<summary>
<para>
The C++ compiler used for generating shared-library objects.
+See also &cv-link-CXX; for compiling to static objects.
</para>
</summary>
</cvar>
@@ -111,6 +117,7 @@ to a shared-library object file.
Any options specified in the &cv-link-SHCXXFLAGS; and
&cv-link-CPPFLAGS; construction variables
are included on this command line.
+See also &cv-link-CXXCOM; for compiling to static objects.
</para>
</summary>
</cvar>
@@ -118,9 +125,10 @@ are included on this command line.
<cvar name="SHCXXCOMSTR">
<summary>
<para>
-The string displayed when a C++ source file
+If set, the string displayed when a C++ source file
is compiled to a shared object file.
-If this is not set, then &cv-link-SHCXXCOM; (the command line) is displayed.
+If not set, then &cv-link-SHCXXCOM; (the command line) is displayed.
+See also &cv-link-CXXCOMSTR; for compiling to static objects.
</para>
<example_commands>
@@ -134,6 +142,7 @@ env = Environment(SHCXXCOMSTR = "Compiling shared object $TARGET")
<para>
Options that are passed to the C++ compiler
to generate shared-library objects.
+See also &cv-link-CXXFLAGS; for compiling to static objects.
</para>
</summary>
</cvar>
diff --git a/src/engine/SCons/Tool/cc.xml b/src/engine/SCons/Tool/cc.xml
index 06e73ff..e47cf2d 100644
--- a/src/engine/SCons/Tool/cc.xml
+++ b/src/engine/SCons/Tool/cc.xml
@@ -51,6 +51,8 @@ Sets construction variables for generic POSIX C compilers.
</sets>
<uses>
<item>PLATFORM</item>
+<item>CCCOMSTR</item>
+<item>SHCCCOMSTR</item>
</uses>
</tool>
@@ -67,8 +69,8 @@ The C compiler.
<para>
The command line used to compile a C source file to a (static) object
file. Any options specified in the &cv-link-CFLAGS;, &cv-link-CCFLAGS; and
-&cv-link-CPPFLAGS; construction variables are included on this command
-line.
+&cv-link-CPPFLAGS; construction variables are included on this command line.
+See also &cv-link-SHCCCOM; for compiling to shared objects.
</para>
</summary>
</cvar>
@@ -76,9 +78,10 @@ line.
<cvar name="CCCOMSTR">
<summary>
<para>
-The string displayed when a C source file
+If set, the string displayed when a C source file
is compiled to a (static) object file.
-If this is not set, then &cv-link-CCCOM; (the command line) is displayed.
+If not set, then &cv-link-CCCOM; (the command line) is displayed.
+See also &cv-link-SHCCCOMSTR; for compiling to shared objects.
</para>
<example_commands>
@@ -91,6 +94,7 @@ env = Environment(CCCOMSTR = "Compiling static object $TARGET")
<summary>
<para>
General options that are passed to the C and C++ compilers.
+See also &cv-link-SHCCFLAGS; for compiling to shared objects.
</para>
</summary>
</cvar>
@@ -99,6 +103,7 @@ General options that are passed to the C and C++ compilers.
<summary>
<para>
General options that are passed to the C compiler (C only; not C++).
+See also &cv-link-SHCFLAGS; for compiling to shared objects.
</para>
</summary>
</cvar>
@@ -156,6 +161,7 @@ The default list is:
<summary>
<para>
The C compiler used for generating shared-library objects.
+See also &cv-link-CC; for compiling to static objects.
</para>
</summary>
</cvar>
@@ -169,6 +175,7 @@ Any options specified in the &cv-link-SHCFLAGS;,
&cv-link-SHCCFLAGS; and
&cv-link-CPPFLAGS; construction variables
are included on this command line.
+See also &cv-link-CCCOM; for compiling to static objects.
</para>
</summary>
</cvar>
@@ -176,9 +183,10 @@ are included on this command line.
<cvar name="SHCCCOMSTR">
<summary>
<para>
-The string displayed when a C source file
+If set, the string displayed when a C source file
is compiled to a shared object file.
-If this is not set, then &cv-link-SHCCCOM; (the command line) is displayed.
+If not set, then &cv-link-SHCCCOM; (the command line) is displayed.
+See also &cv-link-CCCOMSTR; for compiling to static objects.
</para>
<example_commands>
@@ -192,6 +200,7 @@ env = Environment(SHCCCOMSTR = "Compiling shared object $TARGET")
<para>
Options that are passed to the C and C++ compilers
to generate shared-library objects.
+See also &cv-link-CCFLAGS; for compiling to static objects.
</para>
</summary>
</cvar>
@@ -201,6 +210,7 @@ to generate shared-library objects.
<para>
Options that are passed to the C compiler (only; not C++)
to generate shared-library objects.
+See also &cv-link-CFLAGS; for compiling to static objects.
</para>
</summary>
</cvar>
diff --git a/src/engine/SCons/Tool/cyglink.py b/src/engine/SCons/Tool/cyglink.py
index c3d78de..fbb6d24 100644
--- a/src/engine/SCons/Tool/cyglink.py
+++ b/src/engine/SCons/Tool/cyglink.py
@@ -8,8 +8,6 @@ selection method.
"""
-from __future__ import absolute_import, print_function
-
import re
import os
diff --git a/src/engine/SCons/Tool/dmd.py b/src/engine/SCons/Tool/dmd.py
index 6a64a72..3cc4ed0 100644
--- a/src/engine/SCons/Tool/dmd.py
+++ b/src/engine/SCons/Tool/dmd.py
@@ -1,5 +1,3 @@
-from __future__ import print_function
-
"""SCons.Tool.dmd
Tool-specific initialization for the Digital Mars D compiler.
diff --git a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py
index de1375d..3d53bf7 100644
--- a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/docbook.py
+++ b/src/engine/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 $
-from __future__ import print_function
-
import sys
import string
import libxml2
@@ -69,9 +67,9 @@ def adjustColumnWidths(ctx, nodeset):
relPart = 0.0
absPart = 0.0
- starPos = string.find(width, "*")
+ starPos = width.find("*")
if starPos >= 0:
- relPart, absPart = string.split(width, "*", 2)
+ relPart, absPart = width.split("*", 2)
relPart = float(relPart)
relTotal = relTotal + float(relPart)
else:
@@ -113,7 +111,7 @@ def adjustColumnWidths(ctx, nodeset):
widths = correctRoundingError(widths)
else:
pixelWidth = nominalWidth
- if string.find(tableWidth, "%") < 0:
+ if '%' not in tableWidth:
pixelWidth = convertLength(tableWidth)
if pixelWidth <= absTotal:
@@ -127,7 +125,7 @@ def adjustColumnWidths(ctx, nodeset):
relParts[count] = rel + absParts[count]
absTotal = absTotal + rel + absParts[count]
- if string.find(tableWidth, "%") < 0:
+ if '%' not in tableWidth:
for count in range(len(relParts)):
if foStylesheet:
pixels = relParts[count]
diff --git a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py
index d5529b8..0a4ff92 100644
--- a/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py
+++ b/src/engine/SCons/Tool/docbook/docbook-xsl-1.76.1/extensions/xslt.py
@@ -1,7 +1,5 @@
#!/usr/bin/python -u
# $Id: xslt.py 8353 2009-03-17 16:57:50Z mzjn $
-from __future__ import print_function
-
import sys
import libxml2
import libxslt
diff --git a/src/engine/SCons/Tool/f03.xml b/src/engine/SCons/Tool/f03.xml
index c020b81..61c02ef 100644
--- a/src/engine/SCons/Tool/f03.xml
+++ b/src/engine/SCons/Tool/f03.xml
@@ -77,9 +77,9 @@ for all Fortran versions.
<cvar name="F03COMSTR">
<summary>
<para>
-The string displayed when a Fortran 03 source file
+If set, the string displayed when a Fortran 03 source file
is compiled to an object file.
-If this is not set, then &cv-link-F03COM; or &cv-link-FORTRANCOM;
+If not set, then &cv-link-F03COM; or &cv-link-FORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -217,10 +217,10 @@ for all Fortran versions.
<cvar name="F03PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 03 source file
+If set, the string displayed when a Fortran 03 source file
is compiled to an object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-F03PPCOM; or &cv-link-FORTRANPPCOM;
+If not set, then &cv-link-F03PPCOM; or &cv-link-FORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
@@ -256,9 +256,9 @@ for all Fortran versions.
<cvar name="SHF03COMSTR">
<summary>
<para>
-The string displayed when a Fortran 03 source file
+If set, the string displayed when a Fortran 03 source file
is compiled to a shared-library object file.
-If this is not set, then &cv-link-SHF03COM; or &cv-link-SHFORTRANCOM;
+If not set, then &cv-link-SHF03COM; or &cv-link-SHFORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -299,10 +299,10 @@ for all Fortran versions.
<cvar name="SHF03PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 03 source file
+If set, the string displayed when a Fortran 03 source file
is compiled to a shared-library object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-SHF03PPCOM; or &cv-link-SHFORTRANPPCOM;
+If not set, then &cv-link-SHF03PPCOM; or &cv-link-SHFORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
diff --git a/src/engine/SCons/Tool/f08.py b/src/engine/SCons/Tool/f08.py
index 7fa5872..64bac8e 100644
--- a/src/engine/SCons/Tool/f08.py
+++ b/src/engine/SCons/Tool/f08.py
@@ -8,8 +8,6 @@ selection method.
"""
-from __future__ import absolute_import
-
#
# __COPYRIGHT__
#
diff --git a/src/engine/SCons/Tool/f08.xml b/src/engine/SCons/Tool/f08.xml
index 802e4cc..a56d60b 100644
--- a/src/engine/SCons/Tool/f08.xml
+++ b/src/engine/SCons/Tool/f08.xml
@@ -77,9 +77,9 @@ for all Fortran versions.
<cvar name="F08COMSTR">
<summary>
<para>
-The string displayed when a Fortran 08 source file
+If set, the string displayed when a Fortran 08 source file
is compiled to an object file.
-If this is not set, then &cv-link-F08COM; or &cv-link-FORTRANCOM;
+If not set, then &cv-link-F08COM; or &cv-link-FORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -217,10 +217,10 @@ for all Fortran versions.
<cvar name="F08PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 08 source file
+If set, the string displayed when a Fortran 08 source file
is compiled to an object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-F08PPCOM; or &cv-link-FORTRANPPCOM;
+If not set, then &cv-link-F08PPCOM; or &cv-link-FORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
@@ -256,9 +256,9 @@ for all Fortran versions.
<cvar name="SHF08COMSTR">
<summary>
<para>
-The string displayed when a Fortran 08 source file
+If set, the string displayed when a Fortran 08 source file
is compiled to a shared-library object file.
-If this is not set, then &cv-link-SHF08COM; or &cv-link-SHFORTRANCOM;
+If not set, then &cv-link-SHF08COM; or &cv-link-SHFORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -299,10 +299,10 @@ for all Fortran versions.
<cvar name="SHF08PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 08 source file
+If set, the string displayed when a Fortran 08 source file
is compiled to a shared-library object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-SHF08PPCOM; or &cv-link-SHFORTRANPPCOM;
+If not set, then &cv-link-SHF08PPCOM; or &cv-link-SHFORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
diff --git a/src/engine/SCons/Tool/f77.xml b/src/engine/SCons/Tool/f77.xml
index abfc4a2..70ec721 100644
--- a/src/engine/SCons/Tool/f77.xml
+++ b/src/engine/SCons/Tool/f77.xml
@@ -108,9 +108,9 @@ F77 dialect will be used. By default, this is empty
<cvar name="F77COMSTR">
<summary>
<para>
-The string displayed when a Fortran 77 source file
+If set, the string displayed when a Fortran 77 source file
is compiled to an object file.
-If this is not set, then &cv-link-F77COM; or &cv-link-FORTRANCOM;
+If not set, then &cv-link-F77COM; or &cv-link-FORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -230,10 +230,10 @@ for all Fortran versions.
<cvar name="F77PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 77 source file
+If set, the string displayed when a Fortran 77 source file
is compiled to an object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-F77PPCOM; or &cv-link-FORTRANPPCOM;
+If not set, then &cv-link-F77PPCOM; or &cv-link-FORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
@@ -269,9 +269,9 @@ for all Fortran versions.
<cvar name="SHF77COMSTR">
<summary>
<para>
-The string displayed when a Fortran 77 source file
+If set, the string displayed when a Fortran 77 source file
is compiled to a shared-library object file.
-If this is not set, then &cv-link-SHF77COM; or &cv-link-SHFORTRANCOM;
+If not set, then &cv-link-SHF77COM; or &cv-link-SHFORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -312,10 +312,10 @@ for all Fortran versions.
<cvar name="SHF77PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 77 source file
+If set, the string displayed when a Fortran 77 source file
is compiled to a shared-library object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-SHF77PPCOM; or &cv-link-SHFORTRANPPCOM;
+If not set, then &cv-link-SHF77PPCOM; or &cv-link-SHFORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
diff --git a/src/engine/SCons/Tool/f90.xml b/src/engine/SCons/Tool/f90.xml
index 94249a3..64dc6e1 100644
--- a/src/engine/SCons/Tool/f90.xml
+++ b/src/engine/SCons/Tool/f90.xml
@@ -77,9 +77,9 @@ for all Fortran versions.
<cvar name="F90COMSTR">
<summary>
<para>
-The string displayed when a Fortran 90 source file
+If set, the string displayed when a Fortran 90 source file
is compiled to an object file.
-If this is not set, then &cv-link-F90COM; or &cv-link-FORTRANCOM;
+If not set, then &cv-link-F90COM; or &cv-link-FORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -217,9 +217,9 @@ for all Fortran versions.
<cvar name="F90PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 90 source file
+If set, the string displayed when a Fortran 90 source file
is compiled after first running the file through the C preprocessor.
-If this is not set, then &cv-link-F90PPCOM; or &cv-link-FORTRANPPCOM;
+If not set, then &cv-link-F90PPCOM; or &cv-link-FORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
@@ -255,9 +255,9 @@ for all Fortran versions.
<cvar name="SHF90COMSTR">
<summary>
<para>
-The string displayed when a Fortran 90 source file
+If set, the string displayed when a Fortran 90 source file
is compiled to a shared-library object file.
-If this is not set, then &cv-link-SHF90COM; or &cv-link-SHFORTRANCOM;
+If not set, then &cv-link-SHF90COM; or &cv-link-SHFORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -298,10 +298,10 @@ for all Fortran versions.
<cvar name="SHF90PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 90 source file
+If set, the string displayed when a Fortran 90 source file
is compiled to a shared-library object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-SHF90PPCOM; or &cv-link-SHFORTRANPPCOM;
+If not set, then &cv-link-SHF90PPCOM; or &cv-link-SHFORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
diff --git a/src/engine/SCons/Tool/f95.xml b/src/engine/SCons/Tool/f95.xml
index 4a4db46..4bda653 100644
--- a/src/engine/SCons/Tool/f95.xml
+++ b/src/engine/SCons/Tool/f95.xml
@@ -77,9 +77,9 @@ for all Fortran versions.
<cvar name="F95COMSTR">
<summary>
<para>
-The string displayed when a Fortran 95 source file
+If set, the string displayed when a Fortran 95 source file
is compiled to an object file.
-If this is not set, then &cv-link-F95COM; or &cv-link-FORTRANCOM;
+If not set, then &cv-link-F95COM; or &cv-link-FORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -217,10 +217,10 @@ for all Fortran versions.
<cvar name="F95PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 95 source file
+If set, the string displayed when a Fortran 95 source file
is compiled to an object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-F95PPCOM; or &cv-link-FORTRANPPCOM;
+If not set, then &cv-link-F95PPCOM; or &cv-link-FORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
@@ -256,9 +256,9 @@ for all Fortran versions.
<cvar name="SHF95COMSTR">
<summary>
<para>
-The string displayed when a Fortran 95 source file
+If set, the string displayed when a Fortran 95 source file
is compiled to a shared-library object file.
-If this is not set, then &cv-link-SHF95COM; or &cv-link-SHFORTRANCOM;
+If not set, then &cv-link-SHF95COM; or &cv-link-SHFORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -299,10 +299,10 @@ for all Fortran versions.
<cvar name="SHF95PPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran 95 source file
+If set, the string displayed when a Fortran 95 source file
is compiled to a shared-library object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-SHF95PPCOM; or &cv-link-SHFORTRANPPCOM;
+If not set, then &cv-link-SHF95PPCOM; or &cv-link-SHFORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
diff --git a/src/engine/SCons/Tool/fortran.xml b/src/engine/SCons/Tool/fortran.xml
index 53bcfb1..7b3c51f 100644
--- a/src/engine/SCons/Tool/fortran.xml
+++ b/src/engine/SCons/Tool/fortran.xml
@@ -73,9 +73,9 @@ are included on this command line.
<cvar name="FORTRANCOMSTR">
<summary>
<para>
-The string displayed when a Fortran source file
+If set, the string displayed when a Fortran source file
is compiled to an object file.
-If this is not set, then &cv-link-FORTRANCOM;
+If not set, then &cv-link-FORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -285,10 +285,10 @@ construction variables are included on this command line.
<cvar name="FORTRANPPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran source file
+If set, the string displayed when a Fortran source file
is compiled to an object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-FORTRANPPCOM;
+If not set, then &cv-link-FORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
@@ -330,9 +330,9 @@ to a shared-library object file.
<cvar name="SHFORTRANCOMSTR">
<summary>
<para>
-The string displayed when a Fortran source file
+If set, the string displayed when a Fortran source file
is compiled to a shared-library object file.
-If this is not set, then &cv-link-SHFORTRANCOM;
+If not set, then &cv-link-SHFORTRANCOM;
(the command line) is displayed.
</para>
</summary>
@@ -364,10 +364,10 @@ are included on this command line.
<cvar name="SHFORTRANPPCOMSTR">
<summary>
<para>
-The string displayed when a Fortran source file
+If set, the string displayed when a Fortran source file
is compiled to a shared-library object file
after first running the file through the C preprocessor.
-If this is not set, then &cv-link-SHFORTRANPPCOM;
+If not set, then &cv-link-SHFORTRANPPCOM;
(the command line) is displayed.
</para>
</summary>
diff --git a/src/engine/SCons/Tool/gdc.py b/src/engine/SCons/Tool/gdc.py
index 0c6a8ab..ecf4f3a 100644
--- a/src/engine/SCons/Tool/gdc.py
+++ b/src/engine/SCons/Tool/gdc.py
@@ -1,5 +1,3 @@
-from __future__ import print_function
-
"""SCons.Tool.gdc
Tool-specific initialization for the GDC compiler.
diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py
index dcb3581..06f7902 100644
--- a/src/engine/SCons/Tool/install.py
+++ b/src/engine/SCons/Tool/install.py
@@ -29,8 +29,6 @@ selection method.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
diff --git a/src/engine/SCons/Tool/install.xml b/src/engine/SCons/Tool/install.xml
index 150308b..ce70d91 100644
--- a/src/engine/SCons/Tool/install.xml
+++ b/src/engine/SCons/Tool/install.xml
@@ -50,10 +50,24 @@ a builder.
</para>
<example_commands>
-env.Install('/usr/local/bin', source = ['foo', 'bar'])
+env.Install(target='/usr/local/bin', source=['foo', 'bar'])
</example_commands>
<para>
+Note that if target paths chosen for the
+&Install; builder (and the related &InstallAs; and
+&InstallVersionedLib; builders) are outside the
+project tree, such as in the example above,
+they may not be selected for "building" by default,
+since in the absence of other instructions
+&scons; builds targets that are underneath the top directory
+(the directory that contains the &SConstruct; file,
+usually the current directory).
+Use command line targets or the &Default; function
+in this case.
+</para>
+
+<para>
If the <option>--install-sandbox</option> command line
option is given, the target directory will be prefixed
by the directory path specified.
@@ -86,12 +100,16 @@ arguments list different numbers of files or directories.
</para>
<example_commands>
-env.InstallAs(target = '/usr/local/bin/foo',
- source = 'foo_debug')
-env.InstallAs(target = ['../lib/libfoo.a', '../lib/libbar.a'],
- source = ['libFOO.a', 'libBAR.a'])
+env.InstallAs(target='/usr/local/bin/foo',
+ source='foo_debug')
+env.InstallAs(target=['../lib/libfoo.a', '../lib/libbar.a'],
+ source=['libFOO.a', 'libBAR.a'])
</example_commands>
+<para>
+See the note under &Install;.
+</para>
+
</summary>
</builder>
@@ -103,9 +121,14 @@ architecture will be generated based on symlinks of the source library.
</para>
<example_commands>
-env.InstallVersionedLib(target = '/usr/local/bin/foo',
- source = 'libxyz.1.5.2.so')
+env.InstallVersionedLib(target='/usr/local/bin/foo',
+ source='libxyz.1.5.2.so')
</example_commands>
+
+<para>
+See the note under &Install;.
+</para>
+
</summary>
</builder>
diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py
index 5a101b4..0880976 100644
--- a/src/engine/SCons/Tool/intelc.py
+++ b/src/engine/SCons/Tool/intelc.py
@@ -30,8 +30,6 @@ 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.
-from __future__ import division, print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import math, sys, os.path, glob, string, re
@@ -495,15 +493,15 @@ def generate(env, version=None, abi=None, topdir=None, verbose=0):
'LIB' : libdir,
'PATH' : bindir,
'LD_LIBRARY_PATH' : libdir}
- for p in list(paths.keys()):
- env.PrependENVPath(p, os.path.join(topdir, paths[p]))
+ for p, v in paths.items():
+ env.PrependENVPath(p, os.path.join(topdir, v))
if is_mac:
paths={'INCLUDE' : 'include',
'LIB' : libdir,
'PATH' : bindir,
'LD_LIBRARY_PATH' : libdir}
- for p in list(paths.keys()):
- env.PrependENVPath(p, os.path.join(topdir, paths[p]))
+ for p, v in paths.items():
+ env.PrependENVPath(p, os.path.join(topdir, v))
if is_windows:
# env key reg valname default subdir of top
paths=(('INCLUDE', 'IncludeDir', 'Include'),
diff --git a/src/engine/SCons/Tool/javac.xml b/src/engine/SCons/Tool/javac.xml
index bc89342..893130b 100644
--- a/src/engine/SCons/Tool/javac.xml
+++ b/src/engine/SCons/Tool/javac.xml
@@ -95,9 +95,9 @@ See its __doc__ string for a discussion of the format.
</para>
<example_commands>
- env.Java(target = 'classes', source = 'src')
- env.Java(target = 'classes', source = ['src1', 'src2'])
- env.Java(target = 'classes', source = ['File1.java', 'File2.java'])
+env.Java(target = 'classes', source = 'src')
+env.Java(target = 'classes', source = ['src1', 'src2'])
+env.Java(target = 'classes', source = ['File1.java', 'File2.java'])
</example_commands>
<para>
@@ -114,8 +114,8 @@ See its __doc__ string for a discussion of the format.
</para>
<example_commands>
- env = Environment()
- env['ENV']['LANG'] = 'en_GB.UTF-8'
+env = Environment()
+env['ENV']['LANG'] = 'en_GB.UTF-8'
</example_commands>
</summary>
</builder>
@@ -174,7 +174,7 @@ See its __doc__ string for a discussion of the format.
</para>
<example_commands>
- env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES")
+env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES")
</example_commands>
</summary>
</cvar>
diff --git a/src/engine/SCons/Tool/ldc.py b/src/engine/SCons/Tool/ldc.py
index 3e12199..f915569 100644
--- a/src/engine/SCons/Tool/ldc.py
+++ b/src/engine/SCons/Tool/ldc.py
@@ -1,5 +1,3 @@
-from __future__ import print_function
-
"""SCons.Tool.ldc
Tool-specific initialization for the LDC compiler.
diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py
index 5d920fb..d52c90d 100644
--- a/src/engine/SCons/Tool/link.py
+++ b/src/engine/SCons/Tool/link.py
@@ -30,8 +30,6 @@ selection method.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import sys
diff --git a/src/engine/SCons/Tool/link.xml b/src/engine/SCons/Tool/link.xml
index 654dafc..281e147 100644
--- a/src/engine/SCons/Tool/link.xml
+++ b/src/engine/SCons/Tool/link.xml
@@ -32,9 +32,6 @@ based on the types of source files.
</para>
</summary>
<sets>
-<item>SHLINK</item>
-<item>SHLINKFLAGS</item>
-<item>SHLINKCOM</item>
<item>LINK</item>
<item>LINKFLAGS</item>
<item>LINKCOM</item>
@@ -42,6 +39,9 @@ based on the types of source files.
<item>LIBDIRSUFFIX</item>
<item>LIBLINKPREFIX</item>
<item>LIBLINKSUFFIX</item>
+<item>SHLINK</item>
+<item>SHLINKFLAGS</item>
+<item>SHLINKCOM</item>
<item>SHLIBSUFFIX</item>
<item>__SHLIBVERSIONFLAGS</item>
<item>LDMODULE</item>
@@ -55,8 +55,8 @@ based on the types of source files.
<item>__LDMODULEVERSIONFLAGS</item>
</sets>
<uses>
-<item>SHLINKCOMSTR</item>
<item>LINKCOMSTR</item>
+<item>SHLINKCOMSTR</item>
<item>LDMODULECOMSTR</item>
</uses>
</tool>
@@ -184,8 +184,8 @@ On other systems, this is the same as &cv-link-SHLINK;.
<cvar name="LDMODULECOMSTR">
<summary>
<para>
-The string displayed when building loadable modules.
-If this is not set, then &cv-link-LDMODULECOM; (the command line) is displayed.
+If set, the string displayed when building loadable modules.
+If not set, then &cv-link-LDMODULECOM; (the command line) is displayed.
</para>
</summary>
</cvar>
@@ -243,6 +243,7 @@ set.
<summary>
<para>
The linker.
+See also &cv-link-SHLINK; for linking shared objects.
</para>
</summary>
</cvar>
@@ -251,6 +252,7 @@ The linker.
<summary>
<para>
The command line used to link object files into an executable.
+See also &cv-link-SHLINKCOM; for linking shared objects.
</para>
</summary>
</cvar>
@@ -258,9 +260,10 @@ The command line used to link object files into an executable.
<cvar name="LINKCOMSTR">
<summary>
<para>
-The string displayed when object files
+If set, the string displayed when object files
are linked into an executable.
-If this is not set, then &cv-link-LINKCOM; (the command line) is displayed.
+If not set, then &cv-link-LINKCOM; (the command line) is displayed.
+See also &cv-link-SHLINKCOMSTR;. for linking shared objects.
</para>
<example_commands>
@@ -290,6 +293,7 @@ and
&cv-link-_LIBDIRFLAGS;
above,
for the variable that expands to library search path options.
+See also &cv-link-SHLINKFLAGS;. for linking shared objects.
</para>
</summary>
</cvar>
@@ -317,6 +321,7 @@ set.
<summary>
<para>
The linker for programs that use shared libraries.
+See also &cv-link-LINK; for linking static objects.
</para>
</summary>
</cvar>
@@ -325,6 +330,7 @@ The linker for programs that use shared libraries.
<summary>
<para>
The command line used to link programs using shared libraries.
+See also &cv-link-LINKCOM; for linking static objects.
</para>
</summary>
</cvar>
@@ -334,6 +340,7 @@ The command line used to link programs using shared libraries.
<para>
The string displayed when programs using shared libraries are linked.
If this is not set, then &cv-link-SHLINKCOM; (the command line) is displayed.
+See also &cv-link-LINKCOMSTR; for linking static objects.
</para>
<example_commands>
@@ -363,6 +370,7 @@ and
&cv-link-_LIBDIRFLAGS;
above,
for the variable that expands to library search path options.
+See also &cv-link-LINKFLAGS; for linking static objects.
</para>
</summary>
</cvar>
diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py
index fc5f009..bab78d8 100644
--- a/src/engine/SCons/Tool/mslink.py
+++ b/src/engine/SCons/Tool/mslink.py
@@ -30,8 +30,6 @@ selection method.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml
index dcac6cc..100c84c 100644
--- a/src/engine/SCons/Tool/msvc.xml
+++ b/src/engine/SCons/Tool/msvc.xml
@@ -355,6 +355,7 @@ constructor; setting it later has no effect.
Valid values for Windows are
<literal>14.2</literal>,
<literal>14.1</literal>,
+<literal>14.1Exp</literal>,
<literal>14.0</literal>,
<literal>14.0Exp</literal>,
<literal>12.0</literal>,
diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py
index 929e558..7332b49 100644
--- a/src/engine/SCons/Tool/msvs.py
+++ b/src/engine/SCons/Tool/msvs.py
@@ -29,9 +29,6 @@ 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.
-
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import SCons.compat
@@ -220,7 +217,7 @@ class _UserGenerator(object):
for var, src in dbg_settings.items():
# Update only expected keys
trg = {}
- for key in [k for k in list(self.usrdebg.keys()) if k in src]:
+ for key in [k for k in self.usrdebg.keys() if k in src]:
trg[key] = str(src[key])
self.configs[var].debug = trg
@@ -544,7 +541,7 @@ class _DSPGenerator(object):
if t[1] in self.env:
if SCons.Util.is_List(self.env[t[1]]):
for i in self.env[t[1]]:
- if not i in self.sources[t[0]]:
+ if i not in self.sources[t[0]]:
self.sources[t[0]].append(i)
else:
if not self.env[t[1]] in self.sources[t[0]]:
@@ -578,11 +575,10 @@ class _DSPGenerator(object):
for i in range(len(variants)):
AddConfig(self, variants[i], buildtarget[i], outdir[i], runfile[i], cmdargs[i], cppdefines[i], cpppaths[i])
- self.platforms = []
- for key in list(self.configs.keys()):
- platform = self.configs[key].platform
- if platform not in self.platforms:
- self.platforms.append(platform)
+ seen = set()
+ self.platforms = [p.platform for p in self.configs.values()
+ if not (p.platform in seen or seen.add(p.platform))]
+
def Build(self):
pass
@@ -702,7 +698,7 @@ class _GenerateV6DSP(_DSPGenerator):
'Resource Files': 'r|rc|ico|cur|bmp|dlg|rc2|rct|bin|cnt|rtf|gif|jpg|jpeg|jpe',
'Other Files': ''}
- for kind in sorted(list(categories.keys()), key=lambda a: a.lower()):
+ for kind in sorted(categories.keys(), key=lambda a: a.lower()):
if not self.sources[kind]:
continue # skip empty groups
@@ -1003,7 +999,7 @@ class _GenerateV7DSP(_DSPGenerator, _GenerateV7User):
self.file.write('\t<Files>\n')
- cats = sorted([k for k in list(categories.keys()) if self.sources[k]],
+ cats = sorted([k for k in categories.keys() if self.sources[k]],
key=lambda a: a.lower())
for kind in cats:
if len(cats) > 1:
@@ -1348,7 +1344,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User):
'Resource Files': 'r;rc;ico;cur;bmp;dlg;rc2;rct;bin;cnt;rtf;gif;jpg;jpeg;jpe',
'Other Files': ''}
- cats = sorted([k for k in list(categories.keys()) if self.sources[k]],
+ cats = sorted([k for k in categories.keys() if self.sources[k]],
key = lambda a: a.lower())
# print vcxproj.filters file first
@@ -1505,11 +1501,9 @@ class _GenerateV7DSW(_DSWGenerator):
for variant in env['variant']:
AddConfig(self, variant)
- self.platforms = []
- for key in list(self.configs.keys()):
- platform = self.configs[key].platform
- if platform not in self.platforms:
- self.platforms.append(platform)
+ seen = set()
+ self.platforms = [p.platform for p in self.configs.values()
+ if not (p.platform in seen or seen.add(p.platform))]
def GenerateProjectFilesInfo(self):
for dspfile in self.dspfiles:
diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py
index cc4f717..b3373ea 100644
--- a/src/engine/SCons/Tool/msvsTests.py
+++ b/src/engine/SCons/Tool/msvsTests.py
@@ -20,8 +20,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.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os
@@ -405,20 +403,20 @@ class DummyEnv(object):
return self.dict
return self.dict[key]
- def __setitem__(self,key,value):
+ def __setitem__(self, key, value):
self.dict[key] = value
- def __getitem__(self,key):
+ def __getitem__(self, key):
return self.dict[key]
- def __contains__(self,key):
+ def __contains__(self, key):
return key in self.dict
- def has_key(self,name):
+ def has_key(self, name):
return name in self.dict
def get(self, name, value=None):
- if self.has_key(name):
+ if name in self.dict:
return self.dict[name]
else:
return value
@@ -771,8 +769,8 @@ class msvsTestCase(unittest.TestCase):
# Check expected result
self.assertListEqual(list(genDSP.configs.keys()), list(expected_configs.keys()))
- for key in list(genDSP.configs.keys()):
- self.assertDictEqual(genDSP.configs[key].__dict__, expected_configs[key])
+ for key, v in genDSP.configs.items():
+ self.assertDictEqual(v.__dict__, expected_configs[key])
genDSP.Build()
diff --git a/src/engine/SCons/Tool/packaging.xml b/src/engine/SCons/Tool/packaging.xml
index 8ab4912..55fecec 100644
--- a/src/engine/SCons/Tool/packaging.xml
+++ b/src/engine/SCons/Tool/packaging.xml
@@ -34,7 +34,7 @@ A framework for building binary and source packages.
<builder name="Package">
<summary>
<para>
-Builds a Binary Package of the given source files.
+Builds a Binary Package of the given source files.
</para>
<example_commands>
@@ -43,68 +43,4 @@ env.Package(source = FindInstalledFiles())
</summary>
</builder>
-<cvar name="JAR">
-<summary>
-<para>
-The Java archive tool.
-</para>
-</summary>
-</cvar>
-
-<cvar name="JARCHDIR">
-<summary>
-<para>
-The directory to which the Java archive tool should change
-(using the
-<option>-C</option>
-option).
-</para>
-</summary>
-</cvar>
-
-<cvar name="JARCOM">
-<summary>
-<para>
-The command line used to call the Java archive tool.
-</para>
-</summary>
-</cvar>
-
-<cvar name="JARCOMSTR">
-<summary>
-<para>
-The string displayed when the Java archive tool
-is called
-If this is not set, then &cv-JARCOM; (the command line) is displayed.
-</para>
-
-<example_commands>
-env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET")
-</example_commands>
-</summary>
-</cvar>
-
-<cvar name="JARFLAGS">
-<summary>
-<para>
-General options passed to the Java archive tool.
-By default this is set to
-<option>cf</option>
-to create the necessary
-<command>jar</command>
-file.
-</para>
-</summary>
-</cvar>
-
-<cvar name="JARSUFFIX">
-<summary>
-<para>
-The suffix for Java archives:
-<filename>.jar</filename>
-by default.
-</para>
-</summary>
-</cvar>
-
</sconsdoc>
diff --git a/src/engine/SCons/Tool/packaging/__init__.xml b/src/engine/SCons/Tool/packaging/__init__.xml
index 31c6eed..66a7aa0 100644
--- a/src/engine/SCons/Tool/packaging/__init__.xml
+++ b/src/engine/SCons/Tool/packaging/__init__.xml
@@ -62,24 +62,25 @@ option or with the &cv-PACKAGETYPE; construction variable. Currently
the following packagers available:
</para>
-<para>
- * msi - Microsoft Installer
- * rpm - RPM Package Manger
- * ipkg - Itsy Package Management System
- * tarbz2 - bzip2 compressed tar
- * targz - gzip compressed tar
- * tarxz - xz compressed tar
- * zip - zip file
- * src_tarbz2 - bzip2 compressed tar source
- * src_targz - gzip compressed tar source
- * src_tarxz - xz compressed tar source
- * src_zip - zip file source
-</para>
+<para><literal>msi</literal> - Microsoft Installer</para>
+<para><literal>rpm</literal> - RPM Package Manger</para>
+<para><literal>ipkg</literal> - Itsy Package Management System</para>
+<para><literal>tarbz2</literal> - bzip2 compressed tar</para>
+<para><literal>targz</literal> - gzip compressed tar</para>
+<para><literal>tarxz</literal> - xz compressed tar</para>
+<para><literal>zip</literal> - zip file</para>
+<para><literal>src_tarbz2</literal> - bzip2 compressed tar source</para>
+<para><literal>src_targz</literal> - gzip compressed tar source</para>
+<para><literal>src_tarxz</literal> - xz compressed tar source</para>
+<para><literal>src_zip</literal> - zip file source</para>
<para>
-An updated list is always available under the "package_type" option when
-running "scons --help" on a project that has packaging activated.
+An updated list is always available under the
+<replaceable>package_type</replaceable> option when
+running <command>scons --help</command>
+on a project that has packaging activated.
</para>
+
<example_commands>
env = Environment(tools=['default', 'packaging'])
env.Install('/bin/', 'my_program')
@@ -198,20 +199,21 @@ placed if applicable. The default value is "$NAME-$VERSION".
Selects the package type to build. Currently these are available:
</para>
-<para>
- * msi - Microsoft Installer
- * rpm - Redhat Package Manger
- * ipkg - Itsy Package Management System
- * tarbz2 - compressed tar
- * targz - compressed tar
- * zip - zip file
- * src_tarbz2 - compressed tar source
- * src_targz - compressed tar source
- * src_zip - zip file source
-</para>
+<para><literal>msi</literal> - Microsoft Installer</para>
+<para><literal>rpm</literal> - RPM Package Manger</para>
+<para><literal>ipkg</literal> - Itsy Package Management System</para>
+<para><literal>tarbz2</literal> - bzip2 compressed tar</para>
+<para><literal>targz</literal> - gzip compressed tar</para>
+<para><literal>tarxz</literal> - xz compressed tar</para>
+<para><literal>zip</literal> - zip file</para>
+<para><literal>src_tarbz2</literal> - bzip2 compressed tar source</para>
+<para><literal>src_targz</literal> - gzip compressed tar source</para>
+<para><literal>src_tarxz</literal> - xz compressed tar source</para>
+<para><literal>src_zip</literal> - zip file source</para>
<para>
-This may be overridden with the "package_type" command line option.
+This may be overridden with the <option>package_type</option>
+command line option.
</para>
</summary>
</cvar>
diff --git a/src/engine/SCons/Tool/packaging/ipk.py b/src/engine/SCons/Tool/packaging/ipk.py
index fe3f49b..ac8b992 100644
--- a/src/engine/SCons/Tool/packaging/ipk.py
+++ b/src/engine/SCons/Tool/packaging/ipk.py
@@ -173,7 +173,7 @@ Description: $X_IPK_DESCRIPTION
#
# close all opened files
- for f in list(opened_files.values()):
+ for f in opened_files.values():
f.close()
# call a user specified function
diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py
index ebaa701..db8ae24 100644
--- a/src/engine/SCons/Tool/packaging/rpm.py
+++ b/src/engine/SCons/Tool/packaging/rpm.py
@@ -284,7 +284,7 @@ def build_specfile_filesection(spec, files):
for file in files:
# build the tagset
tags = {}
- for k in list(supported_tags.keys()):
+ for k in supported_tags.keys():
try:
v = file.GetTag(k)
if v:
diff --git a/src/engine/SCons/Tool/python.py b/src/engine/SCons/Tool/python.py
new file mode 100644
index 0000000..c61fc8d
--- /dev/null
+++ b/src/engine/SCons/Tool/python.py
@@ -0,0 +1,49 @@
+"""SCons.Tool.python
+
+Registers the Python scanner for the supported Python source file suffixes.
+
+"""
+
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+#
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import SCons.Tool
+from SCons.Scanner.Python import PythonScanner, PythonSuffixes
+
+
+def generate(env):
+ """Hook the python builder and scanner into the environment."""
+ for suffix in PythonSuffixes:
+ SCons.Tool.SourceFileScanner.add_scanner(suffix, PythonScanner)
+
+
+def exists(env):
+ return True
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/src/engine/SCons/Tool/python.xml b/src/engine/SCons/Tool/python.xml
new file mode 100644
index 0000000..e3f7da3
--- /dev/null
+++ b/src/engine/SCons/Tool/python.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<!--
+__COPYRIGHT__
+
+This file is processed by the bin/SConsDoc.py module.
+See its __doc__ string for a discussion of the format.
+-->
+
+<!DOCTYPE sconsdoc [
+<!ENTITY % scons SYSTEM '../../../../doc/scons.mod'>
+%scons;
+<!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'>
+%builders-mod;
+<!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'>
+%functions-mod;
+<!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'>
+%tools-mod;
+<!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'>
+%variables-mod;
+]>
+
+<sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">
+
+<tool name="python">
+<summary>
+<para>
+Loads the Python scanner scanner into the invoking environment. When loaded, the scanner will
+attempt to find implicit dependencies for any Python source files in the list of sources
+provided to an actual that uses this environment.
+</para>
+</summary>
+</tool>
+
+</sconsdoc>
diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py
index 0c471f9..3dc87c0 100644
--- a/src/engine/SCons/Tool/qt.py
+++ b/src/engine/SCons/Tool/qt.py
@@ -31,8 +31,6 @@ selection method.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
diff --git a/src/engine/SCons/Tool/rpmutils.py b/src/engine/SCons/Tool/rpmutils.py
index 566f8e1..2c4fb32 100644
--- a/src/engine/SCons/Tool/rpmutils.py
+++ b/src/engine/SCons/Tool/rpmutils.py
@@ -34,8 +34,6 @@ exact syntax.
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py
index f139a09..4d98494 100644
--- a/src/engine/SCons/Tool/swig.py
+++ b/src/engine/SCons/Tool/swig.py
@@ -7,8 +7,6 @@ It will usually be imported through the generic SCons.Tool.Tool()
selection method.
"""
-from __future__ import print_function
-
#
# __COPYRIGHT__
#
diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py
index fa18cf9..1d61e2d 100644
--- a/src/engine/SCons/Tool/tex.py
+++ b/src/engine/SCons/Tool/tex.py
@@ -31,8 +31,6 @@ selection method.
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import os.path
diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py
index 48a2904..c233658 100644
--- a/src/engine/SCons/Tool/textfile.py
+++ b/src/engine/SCons/Tool/textfile.py
@@ -71,7 +71,7 @@ def _do_subst(node, subs):
contents = node.get_text_contents()
if subs:
for (k, val) in subs:
- contents = re.sub(k, val, contents)
+ contents = contents.replace(k, val)
if 'b' in TEXTFILE_FILE_WRITE_MODE:
try:
diff --git a/src/engine/SCons/Tool/textfile.xml b/src/engine/SCons/Tool/textfile.xml
index 957e18c..878eb9f 100644
--- a/src/engine/SCons/Tool/textfile.xml
+++ b/src/engine/SCons/Tool/textfile.xml
@@ -59,7 +59,7 @@ see the &b-Substfile; description for details.
<para>
The prefix and suffix specified by the &cv-TEXTFILEPREFIX;
and &cv-TEXTFILESUFFIX; construction variables
-(the null string and <filename>.txt</filename> by default, respectively)
+(an empty string and <filename>.txt</filename> by default, respectively)
are automatically added to the target if they are not already present.
Examples:
</para>
@@ -124,7 +124,7 @@ the suffix is stripped and the remainder is used as the default target name.
<para>
The prefix and suffix specified by the &cv-SUBSTFILEPREFIX;
and &cv-SUBSTFILESUFFIX; construction variables
-(the null string by default in both cases)
+(an empty string by default in both cases)
are automatically added to the target if they are not already present.
</para>
@@ -218,7 +218,7 @@ lists of tuples are also acceptable.
<summary>
<para>
The prefix used for &b-Substfile; file names,
-the null string by default.
+an empty string by default.
</para>
</summary>
</cvar>
@@ -227,7 +227,7 @@ the null string by default.
<summary>
<para>
The suffix used for &b-Substfile; file names,
-the null string by default.
+an empty string by default.
</para>
</summary>
</cvar>
@@ -236,7 +236,7 @@ the null string by default.
<summary>
<para>
The prefix used for &b-Textfile; file names,
-the null string by default.
+an empty string by default.
</para>
</summary>
</cvar>
diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py
index 130cc5e..22df6fa 100644
--- a/src/engine/SCons/Util.py
+++ b/src/engine/SCons/Util.py
@@ -34,18 +34,11 @@ import types
import codecs
import pprint
import hashlib
+from collections import UserDict, UserList, UserString, OrderedDict
+from collections.abc import MappingView
-PY3 = sys.version_info[0] == 3
PYPY = hasattr(sys, 'pypy_translation_info')
-
-from collections import UserDict, UserList, UserString
-from collections.abc import Iterable, MappingView
-from collections import OrderedDict
-
-# Don't "from types import ..." these because we need to get at the
-# types module later to look for UnicodeType.
-
# Below not used?
# InstanceType = types.InstanceType
@@ -359,27 +352,17 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None):
DictTypes = (dict, UserDict)
ListTypes = (list, UserList)
-try:
- # Handle getting dictionary views.
- SequenceTypes = (list, tuple, UserList, MappingView)
-except NameError:
- SequenceTypes = (list, tuple, UserList)
-
+# Handle getting dictionary views.
+SequenceTypes = (list, tuple, UserList, MappingView)
+# TODO: PY3 check this benchmarking is still correct.
# Note that profiling data shows a speed-up when comparing
-# explicitly with str and unicode instead of simply comparing
+# explicitly with str instead of simply comparing
# with basestring. (at least on Python 2.5.1)
-try:
- StringTypes = (str, unicode, UserString)
-except NameError:
- StringTypes = (str, UserString)
+StringTypes = (str, UserString)
-# Empirically, it is faster to check explicitly for str and
-# unicode than for basestring.
-try:
- BaseStringTypes = (str, unicode)
-except NameError:
- BaseStringTypes = str
+# Empirically, it is faster to check explicitly for str than for basestring.
+BaseStringTypes = str
def is_Dict(obj, isinstance=isinstance, DictTypes=DictTypes):
return isinstance(obj, DictTypes)
@@ -447,24 +430,25 @@ def flatten_sequence(sequence, isinstance=isinstance, StringTypes=StringTypes,
do_flatten(item, result)
return result
-# Generic convert-to-string functions that abstract away whether or
-# not the Python we're executing has Unicode support. The wrapper
+# Generic convert-to-string functions. The wrapper
# to_String_for_signature() will use a for_signature() method if the
# specified object has one.
#
+
+
def to_String(s,
isinstance=isinstance, str=str,
UserString=UserString, BaseStringTypes=BaseStringTypes):
- if isinstance(s,BaseStringTypes):
+ if isinstance(s, BaseStringTypes):
# Early out when already a string!
return s
elif isinstance(s, UserString):
- # s.data can only be either a unicode or a regular
- # string. Please see the UserString initializer.
+ # s.data can only be a regular string. Please see the UserString initializer.
return s.data
else:
return str(s)
+
def to_String_for_subst(s,
isinstance=isinstance, str=str, to_String=to_String,
BaseStringTypes=BaseStringTypes, SequenceTypes=SequenceTypes,
@@ -476,12 +460,12 @@ def to_String_for_subst(s,
elif isinstance(s, SequenceTypes):
return ' '.join([to_String_for_subst(e) for e in s])
elif isinstance(s, UserString):
- # s.data can only be either a unicode or a regular
- # string. Please see the UserString initializer.
+ # s.data can only a regular string. Please see the UserString initializer.
return s.data
else:
return str(s)
+
def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst,
AttributeError=AttributeError):
try:
@@ -491,6 +475,7 @@ def to_String_for_signature(obj, to_String_for_subst=to_String_for_subst,
# pprint will output dictionary in key sorted order
# with py3.5 the order was randomized. In general depending on dictionary order
# which was undefined until py3.6 (where it's by insertion order) was not wise.
+ # TODO: Change code when floor is raised to PY36
return pprint.pformat(obj, width=1000000)
else:
return to_String_for_subst(obj)
@@ -1508,7 +1493,7 @@ def MD5collect(signatures):
def silent_intern(x):
"""
Perform sys.intern() on the passed argument and return the result.
- If the input is ineligible (e.g. a unicode string) the original argument is
+ If the input is ineligible the original argument is
returned and no exception is thrown.
"""
try:
diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py
index ee07e61..d96b63f 100644
--- a/src/engine/SCons/UtilTests.py
+++ b/src/engine/SCons/UtilTests.py
@@ -313,7 +313,7 @@ class UtilTestCase(unittest.TestCase):
""" Test the to_Bytes method"""
self.assertEqual(to_bytes('Hello'),
bytearray('Hello', 'utf-8'),
- "Check that to_bytes creates byte array when presented with unicode string.")
+ "Check that to_bytes creates byte array when presented with non byte string.")
def test_to_String(self):
"""Test the to_String() method."""
@@ -740,7 +740,7 @@ class UtilTestCase(unittest.TestCase):
def test_LogicalLines(self):
"""Test the LogicalLines class"""
- content = u"""
+ content = """
foo \\
bar \\
baz
@@ -761,9 +761,6 @@ bling
def test_intern(self):
s1 = silent_intern("spam")
- # TODO: Python 3.x does not have a unicode() global function
- if sys.version[0] == '2':
- s2 = silent_intern(unicode("unicode spam"))
s3 = silent_intern(42)
s4 = silent_intern("spam")
assert id(s1) == id(s4)
diff --git a/src/engine/SCons/Variables/ListVariableTests.py b/src/engine/SCons/Variables/ListVariableTests.py
index ef4832c..8f79e07 100644
--- a/src/engine/SCons/Variables/ListVariableTests.py
+++ b/src/engine/SCons/Variables/ListVariableTests.py
@@ -42,7 +42,7 @@ class ListVariableTestCase(unittest.TestCase):
assert o.help == 'test option help\n (all|none|comma-separated list of names)\n allowed names: one two three', repr(o.help)
assert o.default == 'all', o.default
assert o.validator is None, o.validator
- assert not o.converter is None, o.converter
+ assert o.converter is not None, o.converter
opts = SCons.Variables.Variables()
opts.Add(SCons.Variables.ListVariable('test2', 'test2 help',
diff --git a/src/engine/SCons/Variables/PackageVariableTests.py b/src/engine/SCons/Variables/PackageVariableTests.py
index cda3a4a..a7e6b0d 100644
--- a/src/engine/SCons/Variables/PackageVariableTests.py
+++ b/src/engine/SCons/Variables/PackageVariableTests.py
@@ -80,10 +80,10 @@ class PackageVariableTestCase(unittest.TestCase):
# False when we give it str(False). This assures consistent operation
# through a cycle of Variables.Save(<file>) -> Variables(<file>).
x = o.converter(str(True))
- assert x == True, "converter returned a string when given str(True)"
+ assert x, "converter returned a string when given str(True)"
x = o.converter(str(False))
- assert x == False, "converter returned a string when given str(False)"
+ assert not x, "converter returned a string when given str(False)"
def test_validator(self):
"""Test the PackageVariable validator"""
diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py
index 5b35390..0c20c94 100644
--- a/src/engine/SCons/cpp.py
+++ b/src/engine/SCons/cpp.py
@@ -89,7 +89,7 @@ del op_list
override = {
'if' : 'if(?!n?def)',
}
-l = [override.get(x, x) for x in list(Table.keys())]
+l = [override.get(x, x) for x in Table.keys()]
# Turn the list of expressions into one big honkin' regular expression
@@ -268,7 +268,7 @@ class PreProcessor(object):
d = {
'scons_current_file' : self.scons_current_file
}
- for op in list(Table.keys()):
+ for op in Table.keys():
d[op] = getattr(self, 'do_' + op)
self.default_table = d
diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py
index eff7715..eb9189d 100644
--- a/src/engine/SCons/cppTests.py
+++ b/src/engine/SCons/cppTests.py
@@ -20,9 +20,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.
#
-
-from __future__ import absolute_import
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import atexit
diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py
index 55254b3..765516c 100644
--- a/src/engine/SCons/dblite.py
+++ b/src/engine/SCons/dblite.py
@@ -1,6 +1,7 @@
-# dblite.py module contributed by Ralf W. Grosse-Kunstleve.
-# Extended for Unicode by Steven Knight.
-from __future__ import print_function
+"""
+dblite.py module contributed by Ralf W. Grosse-Kunstleve.
+Extended for Unicode by Steven Knight.
+"""
import os
import pickle
@@ -17,26 +18,6 @@ def corruption_warning(filename):
print("Warning: Discarding corrupt database:", filename)
-try:
- unicode
-except NameError:
- def is_string(s):
- return isinstance(s, str)
-else:
- def is_string(s):
- return type(s) in (str, unicode)
-
-
-def is_bytes(s):
- return isinstance(s, bytes)
-
-
-try:
- unicode('a')
-except NameError:
- def unicode(s):
- return s
-
dblite_suffix = '.dblite'
# TODO: Does commenting this out break switching from py2/3?
@@ -181,10 +162,13 @@ class dblite(object):
def __setitem__(self, key, value):
self._check_writable()
- if not is_string(key):
+
+ if not isinstance(key, str):
raise TypeError("key `%s' must be a string but is %s" % (key, type(key)))
- if not is_bytes(value):
+
+ if not isinstance(value, bytes):
raise TypeError("value `%s' must be a bytes but is %s" % (value, type(value)))
+
self._dict[key] = value
self._needs_sync = 0o001
@@ -214,25 +198,21 @@ def open(file, flag=None, mode=0o666):
def _exercise():
db = open("tmp", "n")
assert len(db) == 0
- db["foo"] = "bar"
- assert db["foo"] == "bar"
- db[unicode("ufoo")] = unicode("ubar")
- assert db[unicode("ufoo")] == unicode("ubar")
+ db["foo"] = b"bar"
+ assert db["foo"] == b"bar"
db.sync()
+
db = open("tmp", "c")
- assert len(db) == 2, len(db)
- assert db["foo"] == "bar"
- db["bar"] = "foo"
- assert db["bar"] == "foo"
- db[unicode("ubar")] = unicode("ufoo")
- assert db[unicode("ubar")] == unicode("ufoo")
+ assert len(db) == 1, len(db)
+ assert db["foo"] == b"bar"
+ db["bar"] = b"foo"
+ assert db["bar"] == b"foo"
db.sync()
+
db = open("tmp", "r")
- assert len(db) == 4, len(db)
- assert db["foo"] == "bar"
- assert db["bar"] == "foo"
- assert db[unicode("ufoo")] == unicode("ubar")
- assert db[unicode("ubar")] == unicode("ufoo")
+ assert len(db) == 2, len(db)
+ assert db["foo"] == b"bar"
+ assert db["bar"] == b"foo"
try:
db.sync()
except IOError as e:
@@ -240,26 +220,31 @@ def _exercise():
else:
raise RuntimeError("IOError expected.")
db = open("tmp", "w")
- assert len(db) == 4
- db["ping"] = "pong"
+ assert len(db) == 2, len(db)
+ db["ping"] = b"pong"
db.sync()
+
try:
db[(1, 2)] = "tuple"
except TypeError as e:
- assert str(e) == "key `(1, 2)' must be a string but is <type 'tuple'>", str(e)
+ assert str(e) == "key `(1, 2)' must be a string but is <class 'tuple'>", str(e)
else:
raise RuntimeError("TypeError exception expected")
+
try:
db["list"] = [1, 2]
except TypeError as e:
- assert str(e) == "value `[1, 2]' must be a string but is <type 'list'>", str(e)
+ assert str(e) == "value `[1, 2]' must be a bytes but is <class 'list'>", str(e)
else:
raise RuntimeError("TypeError exception expected")
+
db = open("tmp", "r")
- assert len(db) == 5
+ assert len(db) == 3, len(db)
+
db = open("tmp", "n")
- assert len(db) == 0
+ assert len(db) == 0, len(db)
dblite._open("tmp.dblite", "w")
+
db = open("tmp", "r")
dblite._open("tmp.dblite", "w").write("x")
try:
@@ -268,10 +253,11 @@ def _exercise():
pass
else:
raise RuntimeError("pickle exception expected.")
+
global ignore_corrupt_dbfiles
ignore_corrupt_dbfiles = 2
db = open("tmp", "r")
- assert len(db) == 0
+ assert len(db) == 0, len(db)
os.unlink("tmp.dblite")
try:
db = open("tmp", "w")
@@ -280,6 +266,8 @@ def _exercise():
else:
raise RuntimeError("IOError expected.")
+ print("Completed _exercise()")
+
if __name__ == "__main__":
_exercise()
diff --git a/src/script/scons-configure-cache.py b/src/script/scons-configure-cache.py
index a687c9c..716315c 100644
--- a/src/script/scons-configure-cache.py
+++ b/src/script/scons-configure-cache.py
@@ -31,7 +31,6 @@ digits of the signature. The prefix length used for directory
names can be changed by this script.
"""
-from __future__ import print_function
import argparse
import glob
import json
diff --git a/src/script/scons-time.py b/src/script/scons-time.py
index 91a105b..e4dd863 100644
--- a/src/script/scons-time.py
+++ b/src/script/scons-time.py
@@ -29,7 +29,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.
-from __future__ import division, print_function
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
diff --git a/src/script/scons.py b/src/script/scons.py
index 2e76365..1e12898 100755
--- a/src/script/scons.py
+++ b/src/script/scons.py
@@ -23,8 +23,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.
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
__version__ = "__VERSION__"
diff --git a/src/script/sconsign.py b/src/script/sconsign.py
index 5ea5ea5..726838c 100644
--- a/src/script/sconsign.py
+++ b/src/script/sconsign.py
@@ -23,8 +23,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.
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
__version__ = "__VERSION__"
diff --git a/src/setup.py b/src/setup.py
index 0f9a672..261e2a4 100755
--- a/src/setup.py
+++ b/src/setup.py
@@ -20,9 +20,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.
-from __future__ import print_function
-
-
import distutils.command.build_scripts
import distutils.command.install_scripts
import distutils.command.install_lib
diff --git a/src/test_files.py b/src/test_files.py
index 1eee11d..fcb2b4c 100644
--- a/src/test_files.py
+++ b/src/test_files.py
@@ -21,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.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
diff --git a/src/test_interrupts.py b/src/test_interrupts.py
index de18a54..1cac046 100644
--- a/src/test_interrupts.py
+++ b/src/test_interrupts.py
@@ -21,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.
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
@@ -105,7 +103,7 @@ for f in files:
indent_list.append( (line_num, match.group('try_or_except') ) )
try_except_lines[match.group('indent')] = indent_list
uncaught_this_file = []
- for indent in list(try_except_lines.keys()):
+ for indent in try_except_lines.keys():
exc_keyboardint_seen = 0
exc_all_seen = 0
for (l,statement) in try_except_lines[indent] + [(-1,indent + 'try')]:
diff --git a/src/test_pychecker.py b/src/test_pychecker.py
index 56233c2..fdc8d20 100644
--- a/src/test_pychecker.py
+++ b/src/test_pychecker.py
@@ -20,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.
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
diff --git a/src/test_setup.py b/src/test_setup.py
index d9fa5b5..8410be3 100644
--- a/src/test_setup.py
+++ b/src/test_setup.py
@@ -21,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.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
diff --git a/src/test_strings.py b/src/test_strings.py
index a8a5000..b43340f 100644
--- a/src/test_strings.py
+++ b/src/test_strings.py
@@ -21,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.
#
-from __future__ import print_function
-
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
diff --git a/test/AS/as-live.py b/test/AS/as-live.py
index b781caf..676b537 100644
--- a/test/AS/as-live.py
+++ b/test/AS/as-live.py
@@ -56,12 +56,12 @@ if sys.platform == "win32":
testccc = ""
test.write("wrapper.py", """\
-import os
+import subprocess
import sys
with open('%s', 'wb') as f:
f.write(("wrapper.py: %%s\\n" %% sys.argv[-1]).encode())
cmd = " ".join(sys.argv[1:])
-os.system(cmd)
+subprocess.run(cmd, shell=True)
""" % test.workpath('wrapper.out').replace('\\', '\\\\'))
test.write('SConstruct', """\
diff --git a/test/Actions/actions.py b/test/Actions/actions.py
index f1bb6fe..cf5890d 100644
--- a/test/Actions/actions.py
+++ b/test/Actions/actions.py
@@ -65,12 +65,13 @@ test.must_match('foo.out', '2\nfoo.in\n')
test.up_to_date(arguments = '.')
test.write('SConstruct', """
-import os
+import subprocess
def func(env, target, source):
cmd = r'%(_python_)s build.py %%s 3 %%s' %% (' '.join(map(str, target)),
' '.join(map(str, source)))
print(cmd)
- return os.system(cmd)
+ cp = subprocess.run(cmd, shell=True)
+ return cp.returncode
B = Builder(action = func)
env = Environment(BUILDERS = { 'B' : B })
env.B(target = 'foo.out', source = 'foo.in')
@@ -83,7 +84,7 @@ test.must_match('foo.out', '3\nfoo.in\n')
test.up_to_date(arguments = '.')
test.write('SConstruct', """
-import os
+import subprocess
assert 'string' not in globals()
class bld(object):
def __init__(self):
@@ -91,7 +92,8 @@ class bld(object):
def __call__(self, env, target, source):
cmd = self.get_contents(env, target, source)
print(cmd)
- return os.system(cmd)
+ cp = subprocess.run(cmd, shell=True)
+ return cp.returncode
def get_contents(self, env, target, source):
return self.cmd %% (' '.join(map(str, target)),
' '.join(map(str, source)))
diff --git a/test/AddOption/help.py b/test/AddOption/help.py
index 7b886cb..23e5bd1 100644
--- a/test/AddOption/help.py
+++ b/test/AddOption/help.py
@@ -20,15 +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.
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify the help text when the AddOption() function is used (and when
it's not).
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/CC/CCVERSION-fixture/versioned.py b/test/CC/CCVERSION-fixture/versioned.py
index d6c7ae8..33dc574 100644
--- a/test/CC/CCVERSION-fixture/versioned.py
+++ b/test/CC/CCVERSION-fixture/versioned.py
@@ -1,4 +1,4 @@
-import os
+import subprocess
import sys
if '-dumpversion' in sys.argv:
print('3.9.9')
@@ -9,4 +9,4 @@ if '--version' in sys.argv:
if sys.argv[1] not in [ '2.9.9', '3.9.9' ]:
print('wrong version', sys.argv[1], 'when wrapping', sys.argv[2])
sys.exit(1)
-os.system(" ".join(sys.argv[2:]))
+subprocess.run(" ".join(sys.argv[2:]), shell=True)
diff --git a/test/CXX/CXXVERSION.py b/test/CXX/CXXVERSION.py
index abe6ce0..50ff8f8 100644
--- a/test/CXX/CXXVERSION.py
+++ b/test/CXX/CXXVERSION.py
@@ -24,7 +24,6 @@
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-import os
import sys
import TestSCons
@@ -37,9 +36,8 @@ if sys.platform == 'win32':
test.skip_test('CXXVERSION not set with MSVC, skipping test.')
-test.write("versioned.py",
-"""from __future__ import print_function
-import os
+test.write("versioned.py", """\
+import subprocess
import sys
if '-dumpversion' in sys.argv:
print('3.9.9')
@@ -50,7 +48,7 @@ if '--version' in sys.argv:
if sys.argv[1] not in [ '2.9.9', '3.9.9' ]:
print('wrong version', sys.argv[1], 'when wrapping', sys.argv[2])
sys.exit(1)
-os.system(" ".join(sys.argv[2:]))
+subprocess.run(" ".join(sys.argv[2:]), shell=True)
""")
test.write('SConstruct', """
diff --git a/test/CacheDir/value_dependencies.py b/test/CacheDir/value_dependencies.py
new file mode 100644
index 0000000..7992bef
--- /dev/null
+++ b/test/CacheDir/value_dependencies.py
@@ -0,0 +1,52 @@
+#!/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__"
+
+"""
+Verify that bwuilds with caching work for an action with a Value as a child
+in a variety of cases. Specifically:
+
+1. A source file that depends on a Value.
+2. A source directory that depends on a Value.
+3. A scanner that returns a Value and a directory that depends on a Value.
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.dir_fixture('value_dependencies')
+test.subdir('cache')
+
+# First build, populates the cache
+test.run(arguments='.')
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/CacheDir/value_dependencies/SConstruct b/test/CacheDir/value_dependencies/SConstruct
new file mode 100644
index 0000000..7b7e596
--- /dev/null
+++ b/test/CacheDir/value_dependencies/SConstruct
@@ -0,0 +1,32 @@
+import SCons.Node
+
+CacheDir('cache')
+
+def b(target, source, env):
+ with open(target[0].abspath, 'w') as f:
+ pass
+
+def scan(node, env, path):
+ # Have the node depend on a directory, which depends on an instance of
+ # SCons.Node.Python.Value.
+ sample_dir = env.fs.Dir('dir2')
+ env.Depends(sample_dir, env.Value('c'))
+ return [sample_dir, env.Value('d'), env.Value(b'\x03\x0F', name='name3')]
+
+scanner = Scanner(function=scan, node_class=SCons.Node.Node)
+builder = Builder(action=b, source_scanner=scanner)
+
+env = Environment()
+env.Append(BUILDERS={'B': builder})
+
+# Create a node and a directory that each depend on an instance of
+# SCons.Node.Python.Value.
+sample_dir = env.fs.Dir('dir1')
+env.Depends(sample_dir,
+ [env.Value('a'), env.Value(b'\x01\x0F', name='name1')])
+
+sample_file = env.fs.File('testfile')
+env.Depends(sample_file,
+ [env.Value('b'), env.Value(b'\x02\x0F', name='name2')])
+
+env.B(target='File1.out', source=[sample_dir, sample_file])
diff --git a/test/CacheDir/value_dependencies/testfile b/test/CacheDir/value_dependencies/testfile
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/CacheDir/value_dependencies/testfile
diff --git a/test/Command.py b/test/Command.py
index d8ca86d..5abdf16 100644
--- a/test/Command.py
+++ b/test/Command.py
@@ -20,7 +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 TestSCons
@@ -42,7 +42,6 @@ test.write('build.py', build_py)
test.write(['expand_chdir_sub', 'subbuild.py'], build_py)
test.write('SConstruct', """
-from __future__ import print_function
import os
import sys
diff --git a/test/Configure/ConfigureDryRunError.py b/test/Configure/ConfigureDryRunError.py
index 1b89b03..3648518 100644
--- a/test/Configure/ConfigureDryRunError.py
+++ b/test/Configure/ConfigureDryRunError.py
@@ -20,15 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify the ConfigureDryRunError.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import TestSCons
@@ -67,7 +65,7 @@ test.run(arguments='-n', status=2, stderr=expect)
test.must_not_exist('config.log')
test.subdir('.sconf_temp')
-conftest_0_c = os.path.join(".sconf_temp", "conftest_0.c")
+conftest_0_c = os.path.join(".sconf_temp", "conftest_df286a1d2f67e69d030b4eff75ca7e12_0.c")
SConstruct_file_line = test.python_file_line(SConstruct_path, 6)[:-1]
expect = """
diff --git a/test/Configure/basic.py b/test/Configure/basic.py
index 4038a45..253fa25 100644
--- a/test/Configure/basic.py
+++ b/test/Configure/basic.py
@@ -28,11 +28,11 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Verify that basic builds work with Configure contexts.
"""
-import TestSCons
+from TestSCons import TestSCons, ConfigCheckInfo, _obj
+from TestCmd import IS_WINDOWS
-_obj = TestSCons._obj
-test = TestSCons.TestSCons(match = TestSCons.match_re_dotall)
+test = TestSCons(match = TestSCons.match_re_dotall)
NCR = test.NCR # non-cached rebuild
CR = test.CR # cached rebuild (up to date)
diff --git a/test/Configure/config-h.py b/test/Configure/config-h.py
index 405f259..0331b24 100644
--- a/test/Configure/config-h.py
+++ b/test/Configure/config-h.py
@@ -20,15 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify creation of a config.h file from a Configure context.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import re
diff --git a/test/Configure/custom-tests.py b/test/Configure/custom-tests.py
index 1c6eac8..47b344a 100644
--- a/test/Configure/custom-tests.py
+++ b/test/Configure/custom-tests.py
@@ -20,14 +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__"
"""
Verify execution of custom test cases.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import TestSCons
_exe = TestSCons._exe
@@ -49,8 +48,6 @@ runOK = compileOK
runFAIL = "int main(void) { return 1; }"
test.write('pyAct.py', """\
-from __future__ import print_function
-
import sys
print(sys.argv[1])
sys.exit(int(sys.argv[1]))
diff --git a/test/Configure/fixture/SConstruct.issue-2906 b/test/Configure/fixture/SConstruct.issue-2906
new file mode 100644
index 0000000..7763653
--- /dev/null
+++ b/test/Configure/fixture/SConstruct.issue-2906
@@ -0,0 +1,5 @@
+env = Environment()
+conf1 = Configure(env)
+env2 = Environment()
+# Error right here. You can't have two configure contexts in flight at the same time.
+conf2 = Configure(env2) \ No newline at end of file
diff --git a/test/Configure/implicit-cache.py b/test/Configure/implicit-cache.py
index 1a9ff34..f4f3e94 100644
--- a/test/Configure/implicit-cache.py
+++ b/test/Configure/implicit-cache.py
@@ -20,10 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify that use of --implicit-cache with the Python Value Nodes
@@ -56,6 +52,8 @@ something else changed in the .sconf_temp directory), the string would
get longer and longer until it blew out the users's memory.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import TestSConsign
test = TestSConsign.TestSConsign()
@@ -77,7 +75,7 @@ test.write('foo.h', "#define FOO 1\n")
test.run(arguments = '.')
-test.run_sconsign('-d .sconf_temp -e conftest_0.c --raw .sconsign.dblite')
+test.run_sconsign('-d .sconf_temp -e conftest_5a3fa36d51dd2a28d521d6cc0e2e1d04_0.c --raw .sconsign.dblite')
old_sconsign_dblite = test.stdout()
# Second run: Have the configure subsystem also look for foo.h, so
@@ -90,7 +88,7 @@ old_sconsign_dblite = test.stdout()
test.run(arguments = '--implicit-cache USE_FOO=1 .')
-test.run_sconsign('-d .sconf_temp -e conftest_0.c --raw .sconsign.dblite')
+test.run_sconsign('-d .sconf_temp -e conftest_5a3fa36d51dd2a28d521d6cc0e2e1d04_0.c --raw .sconsign.dblite')
new_sconsign_dblite = test.stdout()
if old_sconsign_dblite != new_sconsign_dblite:
diff --git a/test/Configure/issue-2906-useful-duplicate-configure-message.py b/test/Configure/issue-2906-useful-duplicate-configure-message.py
new file mode 100644
index 0000000..c980bd3
--- /dev/null
+++ b/test/Configure/issue-2906-useful-duplicate-configure-message.py
@@ -0,0 +1,57 @@
+#!/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__"
+
+"""
+Verify useful error message when you create a second Configure context without
+finalizing the previous one via conf.Finish()
+This addresses Issue 2906:
+https://github.com/SCons/scons/issues/2906
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+test.verbose_set(1)
+
+test.file_fixture('./fixture/SConstruct.issue-2906', 'SConstruct')
+
+test_SConstruct_path = test.workpath('SConstruct')
+
+expected_stdout = "scons: Reading SConscript files ...\n"
+
+expected_stderr = """
+scons: *** Configure() called while another Configure() exists.
+ Please call .Finish() before creating and second Configure() context
+File "%s", line 5, in <module>\n"""%test_SConstruct_path
+test.run(stderr=expected_stderr, stdout=expected_stdout, status=2)
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Configure/issue-3469/fixture/SConstruct b/test/Configure/issue-3469/fixture/SConstruct
new file mode 100644
index 0000000..4b5bedc
--- /dev/null
+++ b/test/Configure/issue-3469/fixture/SConstruct
@@ -0,0 +1,25 @@
+"""
+This tests if we add/remove a test in between other tests if a rerun will properly cache the results.
+Github issue #3469
+"""
+
+DefaultEnvironment(tools=[])
+
+vars = Variables()
+vars.Add(BoolVariable('SKIP', 'Skip Middle Conf test', 0))
+env = Environment(variables=vars)
+
+conf = Configure(env)
+if not conf.CheckCHeader('math.h'):
+ print('Math.h must be installed!')
+ Exit(1)
+
+if not env['SKIP'] and not conf.CheckCHeader('stdlib.h'):
+ print('stdlib.h must be installed!')
+ Exit(1)
+
+if not conf.CheckCHeader('stdio.h'):
+ print('stdio.h must be installed!')
+ Exit(1)
+
+env = conf.Finish()
diff --git a/test/Configure/issue-3469/fixture/sconstest.skip b/test/Configure/issue-3469/fixture/sconstest.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/Configure/issue-3469/fixture/sconstest.skip
diff --git a/test/Configure/issue-3469/issue-3469.py b/test/Configure/issue-3469/issue-3469.py
new file mode 100644
index 0000000..a2fd7c2
--- /dev/null
+++ b/test/Configure/issue-3469/issue-3469.py
@@ -0,0 +1,94 @@
+#!/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__"
+
+"""
+Verify that changing the order and/or number of config tests does not reuse
+incorrect temporary test files on successive runs.
+This addresses Issue 3469:
+https://github.com/SCons/scons/issues/3469
+"""
+
+import TestSCons
+
+_exe = TestSCons._exe
+_obj = TestSCons._obj
+_python_ = TestSCons._python_
+
+test = TestSCons.TestSCons()
+test.verbose_set(1)
+
+NCR = test.NCR # non-cached rebuild
+CR = test.CR # cached rebuild (up to date)
+NCF = test.NCF # non-cached build failure
+CF = test.CF # cached build failure
+
+test.file_fixture('./fixture/SConstruct')
+
+test.run()
+
+# First run all tests should build
+test.checkLogAndStdout(["Checking for C header file math.h... ",
+ "Checking for C header file stdlib.h... ",
+ "Checking for C header file stdio.h... "],
+ ["yes", "yes", "yes"],
+ [[(('.c', NCR), (_obj, NCR))],
+ [(('.c', NCR), (_obj, NCR))],
+ [(('.c', NCR), (_obj, NCR))]],
+ "config.log", ".sconf_temp", "SConstruct")
+
+
+# Second run, this will skip middle check. First and third (now second) checks should
+# reuse cached
+test.run('SKIP=1')
+test.checkLogAndStdout(["Checking for C header file math.h... ",
+ # "Checking for C header file stdlib.h... ",
+ "Checking for C header file stdio.h... "],
+ ["yes", "yes", "yes"],
+ [[(('.c', CR), (_obj, CR))],
+ # [(('.c', CR), (_obj, CR))],
+ [(('.c', CR), (_obj, CR))]],
+ "config.log", ".sconf_temp", "SConstruct")
+
+# Third run. We're re-adding the middle test, all tests should reuse cached.
+test.run('SKIP=0')
+test.checkLogAndStdout(["Checking for C header file math.h... ",
+ "Checking for C header file stdlib.h... ",
+ "Checking for C header file stdio.h... "],
+ ["yes", "yes", "yes"],
+ [[(('.c', CR), (_obj, CR))],
+ [(('.c', CR), (_obj, CR))],
+ [(('.c', CR), (_obj, CR))]],
+ "config.log", ".sconf_temp", "SConstruct")
+
+
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Configure/option--config.py b/test/Configure/option--config.py
index 838409d..8b23496 100644
--- a/test/Configure/option--config.py
+++ b/test/Configure/option--config.py
@@ -30,11 +30,11 @@ Verify use of the --config=<auto|force|cache> option.
import os.path
-import TestSCons
+from TestSCons import TestSCons, ConfigCheckInfo, _obj
+from TestCmd import IS_WINDOWS
-_obj = TestSCons._obj
-
-test = TestSCons.TestSCons()
+test = TestSCons()
+# test.verbose_set(1)
test.subdir('include')
@@ -59,7 +59,20 @@ test.write(['include', 'non_system_header0.h'], """
/* A header */
""")
-conftest_0_c = os.path.join(".sconf_temp", "conftest_0.c")
+conftest_0_c_hash = 'cda36b76729ffb03bf36a48d13b2d98d'
+conftest_1_c_hash = 'acc476a565a3f6d5d67ddc21f187d062'
+
+if IS_WINDOWS:
+ conftest_0_obj_suffix = '_213c72f9eb682c6f27f2eb78ed8bd57a'+_obj
+ conftest_1_obj_suffix = '_7c505229a64dccfea6e7cfdffe76bd2a'+_obj
+else:
+ conftest_0_obj_suffix = '_9b191e4c46e9d6ba17c8cd4d730900cf'+_obj
+ conftest_1_obj_suffix = '_b9da1a844a8707269188b28a62c0d83e'+_obj
+
+conftest_0_base = os.path.join(".sconf_temp", "conftest_%s_0%%s"%conftest_0_c_hash)
+conftest_0_c = conftest_0_base%'.c'
+conftest_1_base = os.path.join(".sconf_temp", "conftest_%s_0%%s"%conftest_1_c_hash)
+
SConstruct_file_line = test.python_file_line(SConstruct_path, 6)[:-1]
expect = """
@@ -70,36 +83,67 @@ scons: *** "%(conftest_0_c)s" is not yet built and cache is forced.
test.run(arguments='--config=cache', status=2, stderr=expect)
test.run(arguments='--config=auto')
-test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ",
- "Checking for C header file non_system_header1.h... "],
- ["yes", "no"],
- [[((".c", NCR), (_obj, NCR))],
- [((".c", NCR), (_obj, NCF))]],
- "config.log", ".sconf_temp", "SConstruct")
+test.checkConfigureLogAndStdout(checks=[
+ ConfigCheckInfo("Checking for C header file non_system_header0.h... ",
+ 'yes',
+ [((".c", NCR),
+ (_obj, NCR))],
+ conftest_0_base
+ ),
+ ConfigCheckInfo("Checking for C header file non_system_header1.h... ",
+ 'no',
+ [((".c", NCR),
+ (_obj, NCF))],
+ conftest_1_base)]
+)
test.run(arguments='--config=auto')
-test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ",
- "Checking for C header file non_system_header1.h... "],
- ["yes", "no"],
- [[((".c", CR), (_obj, CR))],
- [((".c", CR), (_obj, CF))]],
- "config.log", ".sconf_temp", "SConstruct")
+test.checkConfigureLogAndStdout(checks=[
+ ConfigCheckInfo("Checking for C header file non_system_header0.h... ",
+ 'yes',
+ [((".c", CR),
+ (conftest_0_obj_suffix, CR))],
+ conftest_0_base,
+ ),
+ ConfigCheckInfo("Checking for C header file non_system_header1.h... ",
+ 'no',
+ [((".c", CR),
+ (conftest_1_obj_suffix, CF))],
+ conftest_1_base)]
+)
+
test.run(arguments='--config=force')
-test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ",
- "Checking for C header file non_system_header1.h... "],
- ["yes", "no"],
- [[((".c", NCR), (_obj, NCR))],
- [((".c", NCR), (_obj, NCF))]],
- "config.log", ".sconf_temp", "SConstruct")
+test.checkConfigureLogAndStdout(checks=[
+ ConfigCheckInfo("Checking for C header file non_system_header0.h... ",
+ 'yes',
+ [((".c", NCR),
+ (conftest_0_obj_suffix, NCR))],
+ conftest_0_base,
+ ),
+ ConfigCheckInfo("Checking for C header file non_system_header1.h... ",
+ 'no',
+ [((".c", NCR),
+ (conftest_1_obj_suffix, NCF))],
+ conftest_1_base)]
+)
+
test.run(arguments='--config=cache')
-test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ",
- "Checking for C header file non_system_header1.h... "],
- ["yes", "no"],
- [[((".c", CR), (_obj, CR))],
- [((".c", CR), (_obj, CF))]],
- "config.log", ".sconf_temp", "SConstruct")
+test.checkConfigureLogAndStdout(checks=[
+ ConfigCheckInfo("Checking for C header file non_system_header0.h... ",
+ 'yes',
+ [((".c", CR),
+ (conftest_0_obj_suffix, CR))],
+ conftest_0_base,
+ ),
+ ConfigCheckInfo("Checking for C header file non_system_header1.h... ",
+ 'no',
+ [((".c", CR),
+ (conftest_1_obj_suffix, CF))],
+ conftest_1_base)]
+)
+
test.write(['include', 'non_system_header1.h'], """
/* Another header */
@@ -107,21 +151,35 @@ test.write(['include', 'non_system_header1.h'], """
test.unlink(['include', 'non_system_header0.h'])
test.run(arguments='--config=cache')
-test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ",
- "Checking for C header file non_system_header1.h... "],
- ["yes", "no"],
- [[((".c", CR), (_obj, CR))],
- [((".c", CR), (_obj, CF))]],
- "config.log", ".sconf_temp", "SConstruct")
-test.run(arguments='--config=auto')
-test.checkLogAndStdout(["Checking for C header file non_system_header0.h... ",
- "Checking for C header file non_system_header1.h... "],
- ["no", "yes"],
- [[((".c", CR), (_obj, NCF))],
- [((".c", CR), (_obj, NCR))]],
- "config.log", ".sconf_temp", "SConstruct")
+test.checkConfigureLogAndStdout(checks=[
+ ConfigCheckInfo("Checking for C header file non_system_header0.h... ",
+ 'yes',
+ [((".c", CR),
+ (conftest_0_obj_suffix, CR))],
+ conftest_0_base,
+ ),
+ ConfigCheckInfo("Checking for C header file non_system_header1.h... ",
+ 'no',
+ [((".c", CR),
+ (conftest_1_obj_suffix, CF))],
+ conftest_1_base)]
+)
+test.run(arguments='--config=auto')
+test.checkConfigureLogAndStdout(checks=[
+ ConfigCheckInfo("Checking for C header file non_system_header0.h... ",
+ 'no',
+ [((".c", CR),
+ (conftest_0_obj_suffix, NCF))],
+ conftest_0_base,
+ ),
+ ConfigCheckInfo("Checking for C header file non_system_header1.h... ",
+ 'yes',
+ [((".c", CR),
+ (conftest_1_obj_suffix, NCR))],
+ conftest_1_base)]
+)
test.file_fixture('test_main.c')
diff --git a/test/DVIPDF/DVIPDF.py b/test/DVIPDF/DVIPDF.py
index 87f4012..1c017a9 100644
--- a/test/DVIPDF/DVIPDF.py
+++ b/test/DVIPDF/DVIPDF.py
@@ -107,11 +107,12 @@ tex = test.where_is('tex')
if dvipdf and tex:
- test.write("wrapper.py", """import os
+ test.write("wrapper.py", """\
+import subprocess
import sys
cmd = " ".join(sys.argv[1:])
open('%s', 'a').write("%%s\\n" %% cmd)
-os.system(cmd)
+subprocess.run(cmd, shell=True)
""" % test.workpath('wrapper.out').replace('\\', '\\\\'))
test.write('SConstruct', """
diff --git a/test/DVIPDF/DVIPDFFLAGS.py b/test/DVIPDF/DVIPDFFLAGS.py
index 30d0e4f..9ecb736 100644
--- a/test/DVIPDF/DVIPDFFLAGS.py
+++ b/test/DVIPDF/DVIPDFFLAGS.py
@@ -111,11 +111,12 @@ tex = test.where_is('tex')
if dvipdf and tex:
- test.write("wrapper.py", """import os
+ test.write("wrapper.py", """\
+import subprocess
import sys
cmd = " ".join(sys.argv[1:])
open('%s', 'a').write("%%s\\n" %% cmd)
-os.system(cmd)
+subprocess.run(cmd, shell=True)
""" % test.workpath('wrapper.out').replace('\\', '\\\\'))
test.write('SConstruct', """
diff --git a/test/DVIPDF/makeindex.py b/test/DVIPDF/makeindex.py
index b4ac2d0..bb44d27 100644
--- a/test/DVIPDF/makeindex.py
+++ b/test/DVIPDF/makeindex.py
@@ -32,15 +32,15 @@ test = TestSCons.TestSCons()
dvipdf = test.where_is('dvipdf')
if not dvipdf:
- test.skip_test('Could not find dvipdf; skipping test(s).\n')
+ test.skip_test("Could not find 'dvipdf'; skipping test(s).\n")
tex = test.where_is('tex')
if not tex:
- test.skip_test('Could not find tex; skipping test(s).\n')
+ test.skip_test("Could not find 'tex'; skipping test(s).\n")
latex = test.where_is('latex')
if not latex:
- test.skip_test('Could not find latex; skipping test(s).\n')
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
diff --git a/test/DVIPS/DVIPS.py b/test/DVIPS/DVIPS.py
index 27e89ba..3cfd730 100644
--- a/test/DVIPS/DVIPS.py
+++ b/test/DVIPS/DVIPS.py
@@ -116,21 +116,21 @@ test.must_match('test4.ps', "This is a .latex test.\n", mode='r')
have_latex = test.where_is('latex')
if not have_latex:
- test.skip_test('Could not find latex; skipping test(s).\n')
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
dvips = test.where_is('dvips')
+if not dvips:
+ test.skip_test("Could not find 'dvips'; skipping test(s).\n")
-if dvips:
-
- test.write("wrapper.py", """
-import os
+test.write("wrapper.py", """
+import subprocess
import sys
cmd = " ".join(sys.argv[1:])
open('%s', 'a').write("%%s\\n" %% cmd)
-os.system(cmd)
+subprocess.run(cmd, shell=True)
""" % test.workpath('wrapper.out').replace('\\', '\\\\'))
- test.write('SConstruct', """
+test.write('SConstruct', """
import os
ENV = { 'PATH' : os.environ['PATH'] }
foo = Environment(ENV = ENV)
@@ -142,41 +142,41 @@ bar.PostScript(target = 'bar2', source = 'bar2.ltx')
bar.PostScript(target = 'bar3', source = 'bar3.latex')
""" % locals())
- tex = r"""
+tex = r"""
This is the %s TeX file.
\end
"""
- latex = r"""
+latex = r"""
\documentclass{letter}
\begin{document}
This is the %s LaTeX file.
\end{document}
"""
- test.write('foo.tex', tex % 'foo.tex')
- test.write('bar1.tex', tex % 'bar1.tex')
- test.write('bar2.ltx', latex % 'bar2.ltx')
- test.write('bar3.latex', latex % 'bar3.latex')
+test.write('foo.tex', tex % 'foo.tex')
+test.write('bar1.tex', tex % 'bar1.tex')
+test.write('bar2.ltx', latex % 'bar2.ltx')
+test.write('bar3.latex', latex % 'bar3.latex')
- test.run(arguments = 'foo.dvi', stderr = None)
+test.run(arguments = 'foo.dvi', stderr = None)
- test.must_not_exist(test.workpath('wrapper.out'))
+test.must_not_exist(test.workpath('wrapper.out'))
- test.must_exist(test.workpath('foo.dvi'))
+test.must_exist(test.workpath('foo.dvi'))
- test.run(arguments = 'bar1.ps bar2.ps bar3.ps', stderr = None)
+test.run(arguments = 'bar1.ps bar2.ps bar3.ps', stderr = None)
- expect = """dvips -o bar1.ps bar1.dvi
+expect = """dvips -o bar1.ps bar1.dvi
dvips -o bar2.ps bar2.dvi
dvips -o bar3.ps bar3.dvi
"""
- test.must_match('wrapper.out', expect, mode='r')
+test.must_match('wrapper.out', expect, mode='r')
- test.must_exist(test.workpath('bar1.ps'))
- test.must_exist(test.workpath('bar2.ps'))
- test.must_exist(test.workpath('bar3.ps'))
+test.must_exist(test.workpath('bar1.ps'))
+test.must_exist(test.workpath('bar2.ps'))
+test.must_exist(test.workpath('bar3.ps'))
test.pass_test()
diff --git a/test/DVIPS/DVIPSFLAGS.py b/test/DVIPS/DVIPSFLAGS.py
index b6625d7..f2e6ba9 100644
--- a/test/DVIPS/DVIPSFLAGS.py
+++ b/test/DVIPS/DVIPSFLAGS.py
@@ -126,11 +126,12 @@ dvips = test.where_is('dvips')
if dvips:
test.write("wrapper.py", """
-import os
+import subprocess
import sys
cmd = " ".join(sys.argv[1:])
-open('%s', 'a').write("%%s\\n" %% cmd)
-os.system(cmd)
+with open('%s', 'a') as f:
+ f.write("%%s\\n" %% cmd)
+subprocess.run(cmd, shell=True)
""" % test.workpath('wrapper.out').replace('\\', '\\\\'))
test.write('SConstruct', """
diff --git a/test/Dir/Dir.py b/test/Dir/Dir.py
index e726b94..42a48f3 100644
--- a/test/Dir/Dir.py
+++ b/test/Dir/Dir.py
@@ -36,28 +36,34 @@ test = TestSCons.TestSCons()
test.write('SConstruct', """
DefaultEnvironment(tools=[])
-env = Environment(tools=[], FOO = 'fff', BAR = 'bbb')
+env = Environment(tools=[], FOO='fff', BAR='bbb')
print(Dir('ddd'))
print(Dir('$FOO'))
print(Dir('${BAR}_$BAR'))
+rv = Dir(['mmm', 'nnn'])
+rv_msg = [node.path for node in rv]
+print(rv_msg)
print(env.Dir('eee'))
print(env.Dir('$FOO'))
print(env.Dir('${BAR}_$BAR'))
+rv = env.Dir(['ooo', 'ppp'])
+rv_msg = [node.path for node in rv]
+print(rv_msg)
""")
-test.run(stdout = test.wrap_stdout(read_str = """\
+test.run(stdout=test.wrap_stdout(read_str="""\
ddd
$FOO
${BAR}_$BAR
+['mmm', 'nnn']
eee
fff
bbb_bbb
-""", build_str = """\
+['ooo', 'ppp']
+""", build_str="""\
scons: `.' is up to date.
"""))
-
-
test.write('SConstruct', """\
DefaultEnvironment(tools=[])
import os
@@ -66,7 +72,7 @@ def my_mkdir(target=None, source=None, env=None):
MDBuilder = Builder(action=my_mkdir, target_factory=Dir)
env = Environment(tools=[])
-env.Append(BUILDERS = {'MD':MDBuilder})
+env.Append(BUILDERS={'MD': MDBuilder})
env.MD(target='sub1', source=['SConstruct'])
env.MD(target='sub2', source=['SConstruct'], OVERRIDE='foo')
""")
diff --git a/test/ENV.py b/test/ENV.py
index 0866cf5..0fc3f09 100644
--- a/test/ENV.py
+++ b/test/ENV.py
@@ -20,7 +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__"
@@ -70,9 +69,7 @@ env['ENV']['LIST'] = [foo, 'bar']
env['ENV']['FOO'] = foo
""" % locals())
-test.write('build.py',
-r"""
-from __future__ import print_function
+test.write('build.py', r"""
import os
print('LIST:', os.environ['LIST'])
print('FOO:', os.environ['FOO'])
diff --git a/test/File.py b/test/File.py
index ec148b2..bde4449 100644
--- a/test/File.py
+++ b/test/File.py
@@ -37,13 +37,19 @@ import TestSCons
test = TestSCons.TestSCons()
test.write('SConstruct', """
-env = Environment(FOO = 'fff', BAR = 'bbb')
+env = Environment(FOO='fff', BAR='bbb')
print(File('ddd'))
print(File('$FOO'))
print(File('${BAR}_$BAR'))
+rv = File(['mmm', 'nnn'])
+rv_msg = [node.path for node in rv]
+print(rv_msg)
print(env.File('eee'))
print(env.File('$FOO'))
print(env.File('${BAR}_$BAR'))
+rv = env.File(['ooo', 'ppp'])
+rv_msg = [node.path for node in rv]
+print(rv_msg)
f1 = env.File('f1')
print(f1)
f2 = f1.File('f2')
@@ -54,16 +60,18 @@ expect = test.wrap_stdout(read_str = """\
ddd
$FOO
${BAR}_$BAR
+['mmm', 'nnn']
eee
fff
bbb_bbb
+['ooo', 'ppp']
f1
f2
-""", build_str = """\
+""", build_str="""\
scons: `.' is up to date.
""")
-test.run(stdout = expect)
+test.run(stdout=expect)
test.pass_test()
diff --git a/test/GetBuildFailures/parallel.py b/test/GetBuildFailures/parallel.py
index 63125ad..9b162d8 100644
--- a/test/GetBuildFailures/parallel.py
+++ b/test/GetBuildFailures/parallel.py
@@ -20,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.
-#
-from __future__ import print_function
"""
Verify that a failed build action with -j works as expected.
diff --git a/test/Ghostscript/GS.py b/test/Ghostscript/GS.py
index 3f5aa58..68f7427 100644
--- a/test/Ghostscript/GS.py
+++ b/test/Ghostscript/GS.py
@@ -74,13 +74,12 @@ else:
gs = test.where_is(gs_executable)
if gs:
-
test.write("wrapper.py", """\
-import os
+import subprocess
import sys
cmd = " ".join(sys.argv[1:])
open('%s', 'a').write("%%s\\n" %% cmd)
-os.system(cmd)
+subprocess.run(cmd, shell=True)
""" % test.workpath('wrapper.out').replace('\\', '\\\\'))
test.write('SConstruct', """\
diff --git a/test/Glob/glob-libpath.py b/test/Glob/glob-libpath.py
index 0878090..b688b7e 100644
--- a/test/Glob/glob-libpath.py
+++ b/test/Glob/glob-libpath.py
@@ -20,10 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify that Glob() in a subdir doesn't corrupt LIBPATH.
@@ -31,6 +27,8 @@ See bug #2184, "Glob pollutes LIBPATH" from Ian P. Cardenas.
Test output should not contain -Lsrc/util.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/Interactive/shell.py b/test/Interactive/shell.py
index dd13504..e839d6d 100644
--- a/test/Interactive/shell.py
+++ b/test/Interactive/shell.py
@@ -20,14 +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__"
"""
Verify the ability of the "shell" command (and its "sh" and "!" aliases)
to shell out of interactive mode.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import sys
import TestSCons
@@ -40,8 +40,6 @@ shell_command_py = test.workpath('shell_command.py')
_shell_command_py_ = '"%s"' % shell_command_py.replace('\\', '\\\\')
test.write(shell_command_py, """\
-from __future__ import print_function
-
print('hello from shell_command.py')
""")
diff --git a/test/Interactive/version.py b/test/Interactive/version.py
index 88416ad..6609ad7 100644
--- a/test/Interactive/version.py
+++ b/test/Interactive/version.py
@@ -20,14 +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.
-#
-from __future__ import print_function
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify the behavior of the "version" subcommand.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import TestCmd
import TestSCons
diff --git a/test/Java/multi-step.py b/test/Java/multi-step.py
index f5ee257..d0b3450 100644
--- a/test/Java/multi-step.py
+++ b/test/Java/multi-step.py
@@ -20,16 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Real-world test (courtesy Leanid Nazdrynau) of the multi-step
capabilities of the various Java Builders.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import TestSCons
diff --git a/test/LINK/LINKFLAGS.py b/test/LINK/LINKFLAGS.py
index 1642459..749e369 100644
--- a/test/LINK/LINKFLAGS.py
+++ b/test/LINK/LINKFLAGS.py
@@ -33,13 +33,13 @@ _exe = TestSCons._exe
test = TestSCons.TestSCons()
-test.write("wrapper.py",
-"""import os
+test.write("wrapper.py", """\
+import subprocess
import sys
with open('%s', 'wb') as f:
f.write(("wrapper.py\\n").encode())
args = [s for s in sys.argv[1:] if s != 'fake_link_flag']
-os.system(" ".join(args))
+subprocess.run(" ".join(args), shell=True)
""" % test.workpath('wrapper.out').replace('\\', '\\\\'))
test.write('SConstruct', """
diff --git a/test/LINK/SHLINKFLAGS.py b/test/LINK/SHLINKFLAGS.py
index ab90ece..af5bdbb 100644
--- a/test/LINK/SHLINKFLAGS.py
+++ b/test/LINK/SHLINKFLAGS.py
@@ -34,13 +34,13 @@ _shlib = TestSCons._dll
test = TestSCons.TestSCons()
-test.write("wrapper.py",
-"""import os
+test.write("wrapper.py", """
+import subprocess
import sys
with open('%s', 'wb') as f:
f.write(("wrapper.py\\n").encode())
args = [s for s in sys.argv[1:] if s != 'fake_shlink_flag']
-os.system(" ".join(args))
+subprocess.run(" ".join(args), shell=True)
""" % test.workpath('wrapper.out').replace('\\', '\\\\'))
test.write('SConstruct', """
diff --git a/test/LINK/VersionedLib.py b/test/LINK/VersionedLib.py
index 64f9b90..104f696 100644
--- a/test/LINK/VersionedLib.py
+++ b/test/LINK/VersionedLib.py
@@ -20,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.
-#
-
-from __future__ import print_function
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
diff --git a/test/MSVC/MSVC_UWP_APP.py b/test/MSVC/MSVC_UWP_APP.py
index 861edcd..0f33dda 100644
--- a/test/MSVC/MSVC_UWP_APP.py
+++ b/test/MSVC/MSVC_UWP_APP.py
@@ -83,23 +83,23 @@ test = TestSCons.TestSCons()
test.skip_if_not_msvc()
installed_msvc_versions = msvc.cached_get_installed_vcs()
-# MSVC guaranteed to be at least one version on the system or else skip_if_not_msvc() function
-# would have skipped the test
+# MSVC guaranteed to be at least one version on the system or else
+# skip_if_not_msvc() function would have skipped the test
msvc_140 = '14.0' in installed_msvc_versions
msvc_141 = '14.1' in installed_msvc_versions
+msvc_142 = '14.2' in installed_msvc_versions
-if not (msvc_140 or msvc_141):
- test.skip_test("Available MSVC doesn't support App store")
+if not any((msvc_140, msvc_141, msvc_142)):
+ test.skip_test("Available MSVC doesn't support App store\n")
if msvc_140:
-
- test.write('SConstruct', """
+ test.write('SConstruct', """\
if ARGUMENTS.get('MSVC_UWP_APP'):
help_vars = Variables()
help_vars.Add(EnumVariable(
'MSVC_UWP_APP',
- 'Build for a Universal Windows Platform (UWP) Application',
+ 'Build a Universal Windows Platform (UWP) Application',
'0',
allowed_values=('0', '1')))
else:
@@ -128,14 +128,31 @@ print('env[MSVC_VERSION]=%s' % env.get('MSVC_VERSION'))
test.fail_test((vclibstore_path_present is True) or (vclibstorerefs_path_present is True),
message='VC Store LIBPATHs present when MSVC_UWP_APP not set (msvc_version=%s)' % msvc_version)
-if msvc_141:
-
- test.write('SConstruct', """
+if msvc_141 or msvc_142:
+ if msvc_142:
+ test.write('SConstruct', """\
+if ARGUMENTS.get('MSVC_UWP_APP'):
+ help_vars = Variables()
+ help_vars.Add(EnumVariable(
+ 'MSVC_UWP_APP',
+ 'Build a Universal Windows Platform (UWP) Application',
+ '0',
+ allowed_values=('0', '1')))
+else:
+ help_vars = None
+env = Environment(tools=['default', 'msvc'], variables=help_vars, MSVC_VERSION='14.2')
+# Print the ENV LIBPATH to stdout
+print('env[ENV][LIBPATH]=%s' % env.get('ENV').get('LIBPATH'))
+print('env[MSVC_VERSION]=%s' % env.get('MSVC_VERSION'))
+print('env[ENV][VSCMD_ARG_app_plat]=%s' % env.get('ENV').get('VSCMD_ARG_app_plat'))
+""")
+ elif msvc_141:
+ test.write('SConstruct', """\
if ARGUMENTS.get('MSVC_UWP_APP'):
help_vars = Variables()
help_vars.Add(EnumVariable(
'MSVC_UWP_APP',
- 'Build for a Universal Windows Platform (UWP) Application',
+ 'Build a Universal Windows Platform (UWP) Application',
'0',
allowed_values=('0', '1')))
else:
diff --git a/test/MSVC/mssdk.py b/test/MSVC/mssdk.py
index ba45346..8d1bb5c 100644
--- a/test/MSVC/mssdk.py
+++ b/test/MSVC/mssdk.py
@@ -20,15 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Simple test to make sure mssdk works.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import time
import TestSCons
diff --git a/test/MSVC/msvc.py b/test/MSVC/msvc.py
index 838922c..b92cf3a 100644
--- a/test/MSVC/msvc.py
+++ b/test/MSVC/msvc.py
@@ -20,16 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify basic invocation of Microsoft Visual C/C++, including use
of a precompiled header with the $CCFLAGS variable.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import time
import TestSCons
diff --git a/test/QT/Tool.py b/test/QT/Tool.py
index 9e4a277..f684e91 100644
--- a/test/QT/Tool.py
+++ b/test/QT/Tool.py
@@ -20,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.
-#
-
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify that applying env.Tool('qt') after running Configure checks
@@ -36,6 +31,8 @@ not completely minimal, but we're leaving it as-is since it represents a
good real-world sanity check on the interaction of some key subsystems.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import TestSCons
diff --git a/test/QT/copied-env.py b/test/QT/copied-env.py
index 3989143..be9f599 100644
--- a/test/QT/copied-env.py
+++ b/test/QT/copied-env.py
@@ -20,14 +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.
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Test Qt with a copied construction environment.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import TestSCons
test = TestSCons.TestSCons()
diff --git a/test/QT/qt_warnings.py b/test/QT/qt_warnings.py
index 020333e..2aa7940 100644
--- a/test/QT/qt_warnings.py
+++ b/test/QT/qt_warnings.py
@@ -20,15 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Test the Qt tool warnings.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import re
diff --git a/test/SCONS_LIB_DIR.py b/test/SCONS_LIB_DIR.py
index 65ec3de..5691f61 100644
--- a/test/SCONS_LIB_DIR.py
+++ b/test/SCONS_LIB_DIR.py
@@ -20,7 +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__"
@@ -31,8 +30,6 @@ test = TestSCons.TestSCons()
test.subdir('SCons')
test.write(['SCons','Script.py'], """
-from __future__ import print_function
-
def main ():
print("SCons.Script")
""")
diff --git a/test/SPAWN.py b/test/SPAWN.py
index fba21d5..ca9d344 100644
--- a/test/SPAWN.py
+++ b/test/SPAWN.py
@@ -43,18 +43,19 @@ with open(sys.argv[1], 'wb') as ofp:
""")
test.write('SConstruct', """
-import os
+import subprocess
import sys
+
def my_spawn1(sh, escape, cmd, args, env):
s = " ".join(args + ['extra1.txt'])
- if sys.platform in ['win32']:
- s = '"' + s + '"'
- os.system(s)
+ cp = subprocess.run(s, shell=True)
+ return cp.returncode
+
def my_spawn2(sh, escape, cmd, args, env):
s = " ".join(args + ['extra2.txt'])
- if sys.platform in ['win32']:
- s = '"' + s + '"'
- os.system(s)
+ cp = subprocess.run(s, shell=True)
+ return cp.returncode
+
env = Environment(MY_SPAWN1 = my_spawn1,
MY_SPAWN2 = my_spawn2,
COMMAND = r'%(_python_)s cat.py $TARGET $SOURCES')
diff --git a/test/SWIG/SWIG.py b/test/SWIG/SWIG.py
index 31bc7d7..625b5f1 100644
--- a/test/SWIG/SWIG.py
+++ b/test/SWIG/SWIG.py
@@ -35,19 +35,19 @@ _obj = TestSCons._obj
test = TestSCons.TestSCons()
-python = test.where_is('python')
-if not python:
- test.skip_test('Can not find installed "python", skipping test.\n')
+_python_ = TestSCons._python_
-
-test.write('myswig.py', r"""
+test.write('myswig.py', """\
import getopt
import sys
-opts, args = getopt.getopt(sys.argv[1:], 'c:o:v:')
+
+opts, args = getopt.getopt(sys.argv[1:], "c:o:v:")
for opt, arg in opts:
- if opt == '-c': pass
- elif opt == '-o': out = arg
- elif opt == '-v' and arg == 'ersion':
+ if opt == "-c":
+ pass
+ elif opt == "-o":
+ out = arg
+ elif opt == "-v" and arg == "ersion":
print("")
print("SWIG Version 0.1.2")
print("")
@@ -55,23 +55,23 @@ for opt, arg in opts:
print("")
print("Configured options: +pcre")
print("")
- print("Please see http://www.swig.org for reporting bugs and further information")
+ print("Please see http://www.swig.org for reporting bugs "
+ "and further information")
sys.exit(0)
-infile = open(args[0], 'r')
-outfile = open(out, 'w')
-for l in infile.readlines():
- if l[:4] != 'swig':
- outfile.write(l)
+
+with open(args[0], "r") as ifp, open(out, "w") as ofp:
+ for line in ifp:
+ if not line.startswith("swig"):
+ ofp.write(line)
sys.exit(0)
""")
-test.write('SConstruct', """
-env = Environment(tools=['default', 'swig'],
- SWIG = [r'%(python)s', 'myswig.py'])
+test.write('SConstruct', """\
+env = Environment(tools=["default", "swig"], SWIG=[r"%(_python_)s", "myswig.py"])
print(env.subst("Using SWIG $SWIGVERSION"))
-env.Program(target = 'test1', source = 'test1.i')
-env.CFile(target = 'test2', source = 'test2.i')
-env.Clone(SWIGFLAGS = '-c++').Program(target = 'test3', source = 'test3.i')
+env.Program(target="test1", source="test1.i")
+env.CFile(target="test2", source="test2.i")
+env.Clone(SWIGFLAGS="-c++").Program(target="test3", source="test3.i")
""" % locals())
test.write('test1.i', r"""
diff --git a/test/SWIG/SWIGPATH.py b/test/SWIG/SWIGPATH.py
index d516c0c..ef4fb18 100644
--- a/test/SWIG/SWIGPATH.py
+++ b/test/SWIG/SWIGPATH.py
@@ -35,13 +35,8 @@ test = TestSCons.TestSCons()
swig = test.where_is('swig')
if not swig:
test.skip_test('Can not find installed "swig", skipping test.\n')
-
-python = test.where_is('python')
-if not python:
- test,skip_test('Can not find installed "python", skipping test.\n')
-
swig = swig.replace('\\','/')
-python = python.replace('\\','/')
+
test.subdir('inc1', 'inc2')
test.write(['inc2', 'dependency.i'], """\
@@ -59,7 +54,6 @@ foo = Environment(SWIGFLAGS='-python',
SWIG='%(swig)s',
SWIGPATH=['inc1', 'inc2'])
swig = foo.Dictionary('SWIG')
-bar = foo.Clone(SWIG = [r'%(python)s', 'wrapper.py', swig])
foo.CFile(target = 'dependent', source = ['dependent.i'])
""" % locals())
@@ -96,4 +90,4 @@ test.pass_test()
# tab-width:4
# indent-tabs-mode:nil
# End:
-# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/SWIG/build-dir.py b/test/SWIG/build-dir.py
index f70e6e1..372b052 100644
--- a/test/SWIG/build-dir.py
+++ b/test/SWIG/build-dir.py
@@ -21,14 +21,14 @@
# 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__"
-
"""
Make sure SWIG works when a VariantDir (or variant_dir) is used.
Test case courtesy Joe Maruszewski.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import sys
import TestSCons
@@ -143,8 +143,6 @@ public:
## XXX: @ptomulik: looks like it was unused?
## test.write(['source', 'test.py'], """\
## #!%(_python_)s
-## from __future__ import print_function
-##
## import linalg
##
##
diff --git a/test/SWIG/implicit-dependencies.py b/test/SWIG/implicit-dependencies.py
index 8664bf6..715db83 100644
--- a/test/SWIG/implicit-dependencies.py
+++ b/test/SWIG/implicit-dependencies.py
@@ -35,13 +35,8 @@ test = TestSCons.TestSCons()
swig = test.where_is('swig')
if not swig:
test.skip_test('Can not find installed "swig", skipping test.\n')
-
-python = test.where_is('python')
-if not python:
- test.skip_test('Can not find installed "python", skipping test.\n')
-
swig = swig.replace('\\','/')
-python = python.replace('\\','/')
+
test.write("dependency.i", """\
%module dependency
""")
@@ -55,7 +50,6 @@ test.write("dependent.i", """\
test.write('SConstruct', """
foo = Environment(SWIGFLAGS='-python', SWIG='%(swig)s')
swig = foo.Dictionary('SWIG')
-bar = foo.Clone(SWIG = [r'%(python)s', r'wrapper.py', swig])
foo.CFile(target = 'dependent', source = ['dependent.i'])
""" % locals())
@@ -76,4 +70,4 @@ test.pass_test()
# tab-width:4
# indent-tabs-mode:nil
# End:
-# vim: set expandtab tabstop=4 shiftwidth=4: \ No newline at end of file
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/SWIG/live.py b/test/SWIG/live.py
index e01597d..e7b2602 100644
--- a/test/SWIG/live.py
+++ b/test/SWIG/live.py
@@ -20,14 +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__"
"""
Test SWIG behavior with a live, installed SWIG.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import sys
@@ -134,7 +133,6 @@ test.run(arguments = ldmodule_prefix+'foo' + _dll)
test.must_not_exist(test.workpath('wrapper.out'))
test.run(program = python, stdin = """\
-from __future__ import print_function
import foo
print(foo.foo_string())
""", stdout="""\
@@ -148,7 +146,6 @@ test.run(arguments = ldmodule_prefix+'bar' + _dll)
test.must_match('wrapper.out', "wrapper.py\n")
test.run(program = python, stdin = """\
-from __future__ import print_function
import foo
import bar
print(foo.foo_string())
diff --git a/test/SWIG/noproxy.py b/test/SWIG/noproxy.py
index f94f553..deeaa3a 100644
--- a/test/SWIG/noproxy.py
+++ b/test/SWIG/noproxy.py
@@ -73,7 +73,6 @@ foo = Environment(SWIGFLAGS=['-python', '-noproxy'],
)
swig = foo.Dictionary('SWIG')
-bar = foo.Clone(SWIG = [r'%(python)s', 'wrapper.py', swig])
foo.CFile(target = 'dependent', source = ['dependent.i'])
""" % locals())
diff --git a/test/TEMPFILEPREFIX.py b/test/TEMPFILEPREFIX.py
index f5093e1..4ccfd7d 100644
--- a/test/TEMPFILEPREFIX.py
+++ b/test/TEMPFILEPREFIX.py
@@ -20,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__"
"""
Verify that setting the $TEMPFILEPREFIX variable will cause
@@ -30,6 +27,8 @@ it to appear at the front of name of the generated tempfile
used for long command lines.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import stat
@@ -38,7 +37,6 @@ import TestSCons
test = TestSCons.TestSCons(match = TestSCons.match_re)
test.write('echo.py', """\
-from __future__ import print_function
import sys
print(sys.argv)
""")
diff --git a/test/TEMPFILESUFFIX.py b/test/TEMPFILESUFFIX.py
index aee1e2d..df546ac 100644
--- a/test/TEMPFILESUFFIX.py
+++ b/test/TEMPFILESUFFIX.py
@@ -20,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__"
"""
Verify that setting the $TEMPFILESUFFIX variable will cause
@@ -30,6 +27,8 @@ it to appear at the end of name of the generated tempfile
used for long command lines.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import stat
@@ -38,7 +37,6 @@ import TestSCons
test = TestSCons.TestSCons(match=TestSCons.match_re)
test.write('echo.py', """\
-from __future__ import print_function
import sys
print(sys.argv)
""")
diff --git a/test/TEX/TEX.py b/test/TEX/TEX.py
index 3964eb8..4c4bd87 100644
--- a/test/TEX/TEX.py
+++ b/test/TEX/TEX.py
@@ -20,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.
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
r"""
Validate that we can set the TEX string to our own utility, that
@@ -30,6 +27,8 @@ the produced .dvi, .aux and .log files get removed by the -c option,
and that we can use this to wrap calls to the real latex utility.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import TestSCons
_python_ = TestSCons._python_
@@ -38,7 +37,7 @@ test = TestSCons.TestSCons()
have_latex = test.where_is('latex')
if not have_latex:
- test.skip_test('Could not find latex; skipping test(s).\n')
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
test.write('mytex.py', r"""
diff --git a/test/TEX/auxiliaries.py b/test/TEX/auxiliaries.py
index e28c212..1e37e7a 100644
--- a/test/TEX/auxiliaries.py
+++ b/test/TEX/auxiliaries.py
@@ -45,8 +45,8 @@ test = TestSCons.TestSCons()
dvips = test.where_is('dvips')
latex = test.where_is('latex')
-if not dvips or not latex:
- test.skip_test("Could not find dvips or latex; skipping test(s).\n")
+if not all((dvips, latex)):
+ test.skip_test("Could not find 'dvips' and/or 'latex'; skipping test(s).\n")
test.subdir(['docs'])
diff --git a/test/TEX/biber_biblatex.py b/test/TEX/biber_biblatex.py
index 6ee8121..10c75af 100755
--- a/test/TEX/biber_biblatex.py
+++ b/test/TEX/biber_biblatex.py
@@ -30,8 +30,9 @@ Test creation of a Tex document that uses the multibib oackage
Test courtesy Rob Managan.
"""
+import subprocess
+
import TestSCons
-import os
test = TestSCons.TestSCons()
@@ -43,8 +44,8 @@ biber = test.where_is('biber')
if not biber:
test.skip_test("Could not find 'biber'; skipping test.\n")
-gloss = os.system('kpsewhich biblatex.sty')
-if not gloss==0:
+cp = subprocess.run('kpsewhich biblatex.sty', shell=True)
+if cp.returncode:
test.skip_test("biblatex.sty not installed; skipping test(s).\n")
diff --git a/test/TEX/biber_biblatex2.py b/test/TEX/biber_biblatex2.py
index 61fafcf..92c7ea9 100644
--- a/test/TEX/biber_biblatex2.py
+++ b/test/TEX/biber_biblatex2.py
@@ -32,8 +32,9 @@ Require both be installed
Test courtesy Rob Managan.
"""
+import subprocess
+
import TestSCons
-import os
test = TestSCons.TestSCons()
@@ -49,8 +50,8 @@ bibtex = test.where_is('bibtex')
if not bibtex:
test.skip_test("Could not find 'bibtex'; skipping test.\n")
-biblatex = os.system('kpsewhich biblatex.sty')
-if not biblatex==0:
+cp = subprocess.run('kpsewhich biblatex.sty', shell=True)
+if cp.returncode:
test.skip_test("biblatex.sty not installed; skipping test(s).\n")
diff --git a/test/TEX/biblatex.py b/test/TEX/biblatex.py
index bb88aaa..1e605cf 100755
--- a/test/TEX/biblatex.py
+++ b/test/TEX/biblatex.py
@@ -30,8 +30,9 @@ Test creation of a Tex document that uses the biblatex package
Test courtesy Rob Managan.
"""
+import subprocess
+
import TestSCons
-import os
test = TestSCons.TestSCons()
@@ -39,8 +40,8 @@ latex = test.where_is('pdflatex')
if not latex:
test.skip_test("Could not find 'pdflatex'; skipping test.\n")
-biblatex = os.system('kpsewhich biblatex.sty')
-if not biblatex==0:
+cp = subprocess.run('kpsewhich biblatex.sty', shell=True)
+if cp.returncode:
test.skip_test("biblatex.sty not installed; skipping test(s).\n")
diff --git a/test/TEX/biblatex_plain.py b/test/TEX/biblatex_plain.py
index 5cad924..0fe15f8 100644
--- a/test/TEX/biblatex_plain.py
+++ b/test/TEX/biblatex_plain.py
@@ -30,8 +30,9 @@ Test creation of a Tex document that uses the biblatex package
Test courtesy Rob Managan.
"""
+import subprocess
+
import TestSCons
-import os
test = TestSCons.TestSCons()
@@ -39,8 +40,8 @@ latex = test.where_is('pdflatex')
if not latex:
test.skip_test("Could not find 'pdflatex'; skipping test.\n")
-biblatex = os.system('kpsewhich biblatex.sty')
-if not biblatex==0:
+cp = subprocess.run('kpsewhich biblatex.sty', shell=True)
+if cp.returncode:
test.skip_test("biblatex.sty not installed; skipping test(s).\n")
diff --git a/test/TEX/bibliography.py b/test/TEX/bibliography.py
index a8032db..afccf8f 100644
--- a/test/TEX/bibliography.py
+++ b/test/TEX/bibliography.py
@@ -38,15 +38,15 @@ test = TestSCons.TestSCons()
dvips = test.where_is('dvips')
if not dvips:
- test.skip_test("Could not find dvips; skipping test(s).\n")
+ test.skip_test("Could not find 'dvips'; skipping test(s).\n")
bibtex = test.where_is('bibtex')
if not bibtex:
- test.skip_test("Could not find bibtex; skipping test(s).\n")
+ test.skip_test("Could not find 'bibtex'; skipping test(s).\n")
have_latex = test.where_is('latex')
if not have_latex:
- test.skip_test('Could not find latex; skipping test(s).\n')
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
test.write('SConstruct', """\
diff --git a/test/TEX/bibtex-latex-rerun.py b/test/TEX/bibtex-latex-rerun.py
index 300f03b..f0f8c34 100644
--- a/test/TEX/bibtex-latex-rerun.py
+++ b/test/TEX/bibtex-latex-rerun.py
@@ -39,7 +39,7 @@ test = TestSCons.TestSCons()
pdflatex = test.where_is('pdflatex')
if not pdflatex:
- test.skip_test("Could not find pdflatex; skipping test(s).\n")
+ test.skip_test("Could not find 'pdflatex'; skipping test(s).\n")
test.write(['SConstruct'], """\
import os
diff --git a/test/TEX/clean.py b/test/TEX/clean.py
index ad828d2..4cae61d 100644
--- a/test/TEX/clean.py
+++ b/test/TEX/clean.py
@@ -28,7 +28,8 @@ r"""
Check that all auxilary files created by LaTeX are properly cleaned by scons -c.
"""
-import os
+import subprocess
+
import TestSCons
test = TestSCons.TestSCons()
@@ -36,10 +37,10 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test("Could not find tex or latex; skipping test(s).\n")
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
-comment = os.system('kpsewhich comment.sty')
-if not comment==0:
+cp = subprocess.run('kpsewhich comment.sty', shell=True)
+if cp.returncode:
test.skip_test("comment.sty not installed; skipping test(s).\n")
# package hyperref generates foo.out
diff --git a/test/TEX/configure.py b/test/TEX/configure.py
index 763f86f..9fb4b3e 100644
--- a/test/TEX/configure.py
+++ b/test/TEX/configure.py
@@ -40,8 +40,8 @@ test = TestSCons.TestSCons()
dvips = test.where_is('dvips')
latex = test.where_is('latex')
-if not dvips or not latex:
- test.skip_test("Could not find dvips or latex; skipping test(s).\n")
+if not all((dvips, latex)):
+ test.skip_test("Could not find 'dvips' and/or 'latex'; skipping test(s).\n")
NCR = test.NCR # non-cached rebuild
diff --git a/test/TEX/dryrun.py b/test/TEX/dryrun.py
index 4265791..90357fc 100644
--- a/test/TEX/dryrun.py
+++ b/test/TEX/dryrun.py
@@ -39,7 +39,7 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test('could not find latex; skipping test\n')
+ test.skip_test("could not find 'latex'; skipping test\n")
test.write('SConstruct', """
import os
diff --git a/test/TEX/glossaries.py b/test/TEX/glossaries.py
index 21180a0..a9fd1dc 100644
--- a/test/TEX/glossaries.py
+++ b/test/TEX/glossaries.py
@@ -31,7 +31,8 @@ be aware of the necessary created glossary files.
Test configuration contributed by Robert Managan.
"""
-import os
+import subprocess
+
import TestSCons
test = TestSCons.TestSCons()
@@ -39,10 +40,10 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test("Could not find latex; skipping test(s).\n")
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
-gloss = os.system('kpsewhich glossaries.sty')
-if not gloss==0:
+cp = subprocess.run('kpsewhich glossaries.sty', shell=True)
+if cp.returncode:
test.skip_test("glossaries.sty not installed; skipping test(s).\n")
test.write('SConstruct', """\
diff --git a/test/TEX/glossary.py b/test/TEX/glossary.py
index 0becb40..d4ab579 100644
--- a/test/TEX/glossary.py
+++ b/test/TEX/glossary.py
@@ -31,7 +31,8 @@ be aware of the necessary created glossary files.
Test configuration contributed by Robert Managan.
"""
-import os
+import subprocess
+
import TestSCons
test = TestSCons.TestSCons()
@@ -39,10 +40,10 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test("Could not find latex; skipping test(s).\n")
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
-gloss = os.system('kpsewhich glossary.sty')
-if not gloss==0:
+cp = subprocess.run('kpsewhich glossary.sty', shell=True)
+if cp.returncode:
test.skip_test("glossary.sty not installed; skipping test(s).\n")
test.write('SConstruct', """\
diff --git a/test/TEX/lstinputlisting.py b/test/TEX/lstinputlisting.py
index 1d60df7..40f935b 100644
--- a/test/TEX/lstinputlisting.py
+++ b/test/TEX/lstinputlisting.py
@@ -31,18 +31,19 @@ changes.
Thanks to Stefan Hepp for the patch that fixed this.
"""
+import subprocess
+
import TestSCons
-import os
test = TestSCons.TestSCons()
pdflatex = test.where_is('pdflatex')
if not pdflatex:
- test.skip_test("Could not find pdflatex; skipping test(s).\n")
+ test.skip_test("Could not find 'pdflatex'; skipping test(s).\n")
-listings = os.system('kpsewhich listings.sty')
-if not listings==0:
+cp = subprocess.run('kpsewhich listings.sty', shell=True)
+if cp.returncode:
test.skip_test("listings.sty not installed; skipping test(s).\n")
test.write(['SConstruct'], """\
diff --git a/test/TEX/makeindex.py b/test/TEX/makeindex.py
index 960ed68..0b81f31 100644
--- a/test/TEX/makeindex.py
+++ b/test/TEX/makeindex.py
@@ -38,8 +38,8 @@ test = TestSCons.TestSCons()
pdflatex = test.where_is('pdflatex')
makeindex = test.where_is('makeindex')
-if not pdflatex or not makeindex:
- test.skip_test("Could not find pdflatex or makeindex; skipping test(s).\n")
+if not all((pdflatex, makeindex)):
+ test.skip_test("Could not find 'pdflatex' and/or 'makeindex'; skipping test(s).\n")
test.write('SConstruct', """\
import os
diff --git a/test/TEX/multi-line_include_options.py b/test/TEX/multi-line_include_options.py
index bb8a5f2..94466b6 100644
--- a/test/TEX/multi-line_include_options.py
+++ b/test/TEX/multi-line_include_options.py
@@ -44,7 +44,7 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test("Could not find latex; skipping test(s).\n")
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
test.write('SConstruct', """\
import os
diff --git a/test/TEX/multi-run.py b/test/TEX/multi-run.py
index 9de0da4..3c4e901 100644
--- a/test/TEX/multi-run.py
+++ b/test/TEX/multi-run.py
@@ -38,11 +38,8 @@ test = TestSCons.TestSCons()
tex = test.where_is('tex')
latex = test.where_is('latex')
-
-if not latex:
- test.skip_test("Could not find latex; skipping test(s).\n")
-if not tex and not latex:
- test.skip_test("Could not find tex or latex; skipping test(s).\n")
+if not all((tex, latex)):
+ test.skip_test("Could not find 'tex' and/or 'latex'; skipping test(s).\n")
test.subdir('work1', 'work2', 'work3', 'work4')
diff --git a/test/TEX/multibib.py b/test/TEX/multibib.py
index 114ade6..f80384a 100644
--- a/test/TEX/multibib.py
+++ b/test/TEX/multibib.py
@@ -30,8 +30,9 @@ Test creation of a Tex document that uses the multibib oackage
Test courtesy Rob Managan.
"""
+import subprocess
+
import TestSCons
-import os
test = TestSCons.TestSCons()
@@ -39,8 +40,8 @@ latex = test.where_is('latex')
if not latex:
test.skip_test("Could not find 'latex'; skipping test.\n")
-multibib = os.system('kpsewhich multibib.sty')
-if not multibib==0:
+cp = subprocess.run('kpsewhich multibib.sty', shell=True)
+if cp.returncode:
test.skip_test("multibib.sty not installed; skipping test(s).\n")
test.subdir(['src'])
diff --git a/test/TEX/newglossary.py b/test/TEX/newglossary.py
index faae7d3..70296cf 100644
--- a/test/TEX/newglossary.py
+++ b/test/TEX/newglossary.py
@@ -31,7 +31,8 @@ be aware of the necessary created glossary files.
Test configuration contributed by Robert Managan.
"""
-import os
+import subprocess
+
import TestSCons
test = TestSCons.TestSCons()
@@ -39,10 +40,10 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test("Could not find latex; skipping test(s).\n")
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
-gloss = os.system('kpsewhich glossaries.sty')
-if not gloss==0:
+cp = subprocess.run('kpsewhich glossaries.sty', shell=True)
+if cp.returncode:
test.skip_test("glossaries.sty not installed; skipping test(s).\n")
test.write('SConstruct', """\
diff --git a/test/TEX/nomencl.py b/test/TEX/nomencl.py
index 7afb84b..9cbced7 100644
--- a/test/TEX/nomencl.py
+++ b/test/TEX/nomencl.py
@@ -31,7 +31,8 @@ be aware of the necessary created glossary files.
Test configuration contributed by Robert Managan.
"""
-import os
+import subprocess
+
import TestSCons
test = TestSCons.TestSCons()
@@ -39,10 +40,10 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test("Could not find latex; skipping test(s).\n")
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
-nomencl = os.system('kpsewhich nomencl.sty')
-if not nomencl==0:
+cp = subprocess.run('kpsewhich nomencl.sty', shell=True)
+if cp.returncode:
test.skip_test("nomencl.sty not installed; skipping test(s).\n")
test.write('SConstruct', """\
diff --git a/test/TEX/recursive_scanner_dependencies_import.py b/test/TEX/recursive_scanner_dependencies_import.py
index c8c6569..7b6cb65 100644
--- a/test/TEX/recursive_scanner_dependencies_import.py
+++ b/test/TEX/recursive_scanner_dependencies_import.py
@@ -34,7 +34,8 @@ recursive_scanner_dependencies_input.py test because \input and
dependencies are found only by the scanner.
"""
-import os
+import subprocess
+
import TestSCons
test = TestSCons.TestSCons()
@@ -42,10 +43,10 @@ test = TestSCons.TestSCons()
pdflatex = test.where_is('pdflatex')
if not pdflatex:
- test.skip_test("Could not find pdflatex; skipping test(s).\n")
+ test.skip_test("Could not find 'pdflatex'; skipping test(s).\n")
-latex_import = os.system('kpsewhich import.sty')
-if latex_import != 0:
+cp = subprocess.run('kpsewhich import.sty', shell=True)
+if cp.returncode:
test.skip_test("import.sty not installed; skipping test(s).\n")
test.subdir('subdir')
diff --git a/test/TEX/recursive_scanner_dependencies_input.py b/test/TEX/recursive_scanner_dependencies_input.py
index 5f37bf1..5afcbc2 100644
--- a/test/TEX/recursive_scanner_dependencies_input.py
+++ b/test/TEX/recursive_scanner_dependencies_input.py
@@ -36,7 +36,7 @@ test = TestSCons.TestSCons()
pdflatex = test.where_is('pdflatex')
if not pdflatex:
- test.skip_test("Could not find pdflatex; skipping test(s).\n")
+ test.skip_test("Could not find 'pdflatex'; skipping test(s).\n")
test.write(['SConstruct'], """\
env = Environment(tools=['pdftex', 'tex'])
diff --git a/test/TEX/rename_result.py b/test/TEX/rename_result.py
index b06d388..f67e569 100644
--- a/test/TEX/rename_result.py
+++ b/test/TEX/rename_result.py
@@ -38,7 +38,7 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test('could not find latex; skipping test\n')
+ test.skip_test("could not find 'latex'; skipping test\n")
test.write('SConstruct', """
import os
diff --git a/test/TEX/synctex.py b/test/TEX/synctex.py
index f07db78..385a173 100644
--- a/test/TEX/synctex.py
+++ b/test/TEX/synctex.py
@@ -39,7 +39,7 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test("Could not find latex; skipping test(s).\n")
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
test.write('SConstruct', """\
import os
diff --git a/test/TEX/usepackage.py b/test/TEX/usepackage.py
index 0bb8c22..66510c2 100644
--- a/test/TEX/usepackage.py
+++ b/test/TEX/usepackage.py
@@ -39,7 +39,7 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test('could not find latex; skipping test\n')
+ test.skip_test("could not find 'latex'; skipping test\n")
test.write('SConstruct', """
import os
diff --git a/test/TEX/variant_dir.py b/test/TEX/variant_dir.py
index d81f542..9d05863 100644
--- a/test/TEX/variant_dir.py
+++ b/test/TEX/variant_dir.py
@@ -36,8 +36,9 @@ import TestSCons
test = TestSCons.TestSCons()
latex = test.where_is('latex')
-if not latex:
- test.skip_test("Could not find 'latex'; skipping test.\n")
+dvipdf = test.where_is('dvipdf')
+if not all((latex, dvipdf)):
+ test.skip_test("Could not find 'latex' and/or 'dvipdf'; skipping test(s).\n")
test.subdir(['docs'])
diff --git a/test/TEX/variant_dir_bibunit.py b/test/TEX/variant_dir_bibunit.py
index cd3409e..2a669ba 100644
--- a/test/TEX/variant_dir_bibunit.py
+++ b/test/TEX/variant_dir_bibunit.py
@@ -34,18 +34,19 @@ Latex produces by default.
Test courtesy Rob Managan.
"""
+import subprocess
+
import TestSCons
-import os
test = TestSCons.TestSCons()
latex = test.where_is('pdflatex')
bibtex = test.where_is('bibtex')
-if not latex or not bibtex:
- test.skip_test("Could not find 'latex' or 'bibtex'; skipping test.\n")
+if not all((latex, bibtex)):
+ test.skip_test("Could not find 'latex' and/or 'bibtex'; skipping test.\n")
-bibunits = os.system('kpsewhich bibunits.sty')
-if not bibunits==0:
+cp = subprocess.run('kpsewhich bibunits.sty', shell=True)
+if cp.returncode:
test.skip_test("bibunits.sty not installed; skipping test(s).\n")
test.subdir(['src'])
diff --git a/test/TEX/variant_dir_dup0.py b/test/TEX/variant_dir_dup0.py
index 8f4334f..ea6b51e 100644
--- a/test/TEX/variant_dir_dup0.py
+++ b/test/TEX/variant_dir_dup0.py
@@ -42,8 +42,8 @@ latex = test.where_is('latex')
dvipdf = test.where_is('dvipdf')
makeindex = test.where_is('makeindex')
bibtex = test.where_is('bibtex')
-if not latex or not makeindex or not bibtex or not dvipdf:
- test.skip_test("Could not find 'latex', 'makeindex', 'bibtex', or dvipdf; skipping test.\n")
+if not all((latex, makeindex, bibtex, dvipdf)):
+ test.skip_test("Could not find one or more of 'latex', 'makeindex', 'bibtex', or 'dvipdf'; skipping test.\n")
test.subdir(['docs'])
diff --git a/test/TEX/variant_dir_newglossary.py b/test/TEX/variant_dir_newglossary.py
index 1e6ab43..ae865aa 100644
--- a/test/TEX/variant_dir_newglossary.py
+++ b/test/TEX/variant_dir_newglossary.py
@@ -31,7 +31,8 @@ with variant_dir.
Test configuration contributed by Kendrick Boyd.
"""
-import os
+import subprocess
+
import TestSCons
test = TestSCons.TestSCons()
@@ -39,10 +40,10 @@ test = TestSCons.TestSCons()
latex = test.where_is('latex')
if not latex:
- test.skip_test("Could not find latex; skipping test(s).\n")
+ test.skip_test("Could not find 'latex'; skipping test(s).\n")
-gloss = os.system('kpsewhich glossaries.sty')
-if gloss!=0:
+cp = subprocess.run('kpsewhich glossaries.sty', shell=True)
+if cp.returncode:
test.skip_test("glossaries.sty not installed; skipping test(s).\n")
diff --git a/test/TEX/variant_dir_style_dup0.py b/test/TEX/variant_dir_style_dup0.py
index a9649b0..430b792 100644
--- a/test/TEX/variant_dir_style_dup0.py
+++ b/test/TEX/variant_dir_style_dup0.py
@@ -45,8 +45,8 @@ latex = test.where_is('latex')
dvipdf = test.where_is('dvipdf')
makeindex = test.where_is('makeindex')
bibtex = test.where_is('bibtex')
-if not latex or not makeindex or not bibtex or not dvipdf:
- test.skip_test("Could not find 'latex', 'makeindex', 'bibtex', or 'dvipdf'; skipping test.\n")
+if not all((latex, makeindex, bibtex, dvipdf)):
+ test.skip_test("Could not find one or more of 'latex', 'makeindex', 'bibtex', or 'dvipdf'; skipping test.\n")
test.subdir(['docs'])
diff --git a/test/Value.py b/test/Value.py
index 8f6c7fe..eb04eb0 100644
--- a/test/Value.py
+++ b/test/Value.py
@@ -20,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.
-#
-from __future__ import print_function
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
diff --git a/test/VariantDir/reflect.py b/test/VariantDir/reflect.py
index 72f3af7..56b0c18 100644
--- a/test/VariantDir/reflect.py
+++ b/test/VariantDir/reflect.py
@@ -20,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__"
"""
This test validates the correct operation of a VariantDir specification
@@ -33,6 +30,8 @@ in the variant_dir as sources for that same build dir.
Test based on bug #1055521 filed by Gary Oberbrunner.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os.path
import re
@@ -44,14 +43,11 @@ _python_ = TestSCons._python_
re_python = re.escape(TestSCons._python_)
test.write("mycc.py", """
-from __future__ import print_function
print('Compile')
""")
test.write("mylink.py", """
-from __future__ import print_function
-
print('Link')
""")
diff --git a/test/Win32/bad-drive.py b/test/Win32/bad-drive.py
index 28d926b..cca5462 100644
--- a/test/Win32/bad-drive.py
+++ b/test/Win32/bad-drive.py
@@ -20,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.
-#
-from __future__ import print_function
"""
This test verifies (on Windows systems) that we fail gracefully and
diff --git a/test/Win32/default-drive.py b/test/Win32/default-drive.py
index 78db4be..7d19c57 100644
--- a/test/Win32/default-drive.py
+++ b/test/Win32/default-drive.py
@@ -20,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.
-#
-from __future__ import print_function
"""
This test verifies (on Windows systems) that specifying an
diff --git a/test/builderrors.py b/test/builderrors.py
index f5cbccf..635f448 100644
--- a/test/builderrors.py
+++ b/test/builderrors.py
@@ -20,7 +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__"
@@ -169,7 +168,6 @@ test.must_not_contain_any_line(test.stderr(), ['Exception', 'Traceback'])
# Should not give traceback; the task error should get converted
# to a BuildError.
test.write('SConstruct', """
-from __future__ import print_function
import atexit
env = Environment()
diff --git a/test/explain/basic.py b/test/explain/basic.py
index 46ce6bc..6d41496 100644
--- a/test/explain/basic.py
+++ b/test/explain/basic.py
@@ -20,14 +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__"
"""
Verify a lot of the basic operation of the --debug=explain option.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import TestSCons
@@ -52,7 +51,6 @@ inc_bbb_k = test.workpath('inc', 'bbb.k')
test.write(cat_py, r"""
-from __future__ import print_function
import sys
diff --git a/test/explain/save-info.py b/test/explain/save-info.py
index 24ebb88..500bb55 100644
--- a/test/explain/save-info.py
+++ b/test/explain/save-info.py
@@ -20,14 +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__"
"""
Verify that the --debug=explain information gets saved by default.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import TestSCons
_python_ = TestSCons._python_
@@ -42,8 +41,6 @@ inc_ddd = test.workpath('inc', 'ddd')
inc_eee = test.workpath('inc', 'eee')
test.write(cat_py, r"""
-from __future__ import print_function
-
import sys
def process(outfp, infp):
diff --git a/test/fixture/mycompile.py b/test/fixture/mycompile.py
index 27bf840..0f37d19 100644
--- a/test/fixture/mycompile.py
+++ b/test/fixture/mycompile.py
@@ -13,7 +13,7 @@ if __name__ == '__main__':
with open(sys.argv[2], 'wb') as ofp:
for f in sys.argv[3:]:
with open(f, 'rb') as ifp:
- lines = [ln for ln in ifp.readlines() if ln != line]
+ lines = [ln for ln in ifp if ln != line]
for ln in lines:
ofp.write(ln)
sys.exit(0)
diff --git a/test/fixture/mylink.py b/test/fixture/mylink.py
index b567118..38d9846 100644
--- a/test/fixture/mylink.py
+++ b/test/fixture/mylink.py
@@ -23,9 +23,9 @@ if __name__ == '__main__':
args = args[1:]
if a[:5].lower() == '/out:': out = a[5:]
with open(args[0], 'rb') as ifp, open(out, 'wb') as ofp:
- for l in ifp.readlines():
- if not l.startswith(b'#link'):
- ofp.write(l)
+ for line in ifp:
+ if not line.startswith(b'#link'):
+ ofp.write(line)
sys.exit(0)
else:
import getopt
@@ -33,7 +33,7 @@ if __name__ == '__main__':
for opt, arg in opts:
if opt == '-o': out = arg
with open(args[0], 'rb') as ifp, open(out, 'wb') as ofp:
- for l in ifp.readlines():
- if not l.startswith(b'#link'):
- ofp.write(l)
+ for line in ifp:
+ if not line.startswith(b'#link'):
+ ofp.write(line)
sys.exit(0)
diff --git a/test/fixture/myrewrite.py b/test/fixture/myrewrite.py
index ad46091..6914611 100644
--- a/test/fixture/myrewrite.py
+++ b/test/fixture/myrewrite.py
@@ -10,7 +10,7 @@ import sys
if __name__ == '__main__':
line = ('/*' + sys.argv[1] + '*/\n').encode()
with open(sys.argv[2], 'rb') as ifp:
- lines = [ln for ln in ifp.readlines() if ln != line]
+ lines = [ln for ln in ifp if ln != line]
with open(sys.argv[2], 'wb') as ofp:
for ln in lines:
ofp.write(ln)
diff --git a/test/fixture/python_scanner/curdir_reference/helper.py b/test/fixture/python_scanner/curdir_reference/helper.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/curdir_reference/helper.py
diff --git a/test/fixture/python_scanner/curdir_reference/sconstest.skip b/test/fixture/python_scanner/curdir_reference/sconstest.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/curdir_reference/sconstest.skip
diff --git a/test/fixture/python_scanner/curdir_reference/script.py b/test/fixture/python_scanner/curdir_reference/script.py
new file mode 100644
index 0000000..d533863
--- /dev/null
+++ b/test/fixture/python_scanner/curdir_reference/script.py
@@ -0,0 +1 @@
+from . import helper
diff --git a/test/fixture/python_scanner/from_import_simple_package_module1.py b/test/fixture/python_scanner/from_import_simple_package_module1.py
new file mode 100644
index 0000000..dcc86de
--- /dev/null
+++ b/test/fixture/python_scanner/from_import_simple_package_module1.py
@@ -0,0 +1 @@
+from simple_package import module1
diff --git a/test/fixture/python_scanner/from_import_simple_package_module1_as.py b/test/fixture/python_scanner/from_import_simple_package_module1_as.py
new file mode 100644
index 0000000..51061c6
--- /dev/null
+++ b/test/fixture/python_scanner/from_import_simple_package_module1_as.py
@@ -0,0 +1 @@
+from simple_package import module1 as m1
diff --git a/test/fixture/python_scanner/from_import_simple_package_modules_no_space.py b/test/fixture/python_scanner/from_import_simple_package_modules_no_space.py
new file mode 100644
index 0000000..17b82f8
--- /dev/null
+++ b/test/fixture/python_scanner/from_import_simple_package_modules_no_space.py
@@ -0,0 +1 @@
+from simple_package import module1,module2
diff --git a/test/fixture/python_scanner/from_import_simple_package_modules_with_space.py b/test/fixture/python_scanner/from_import_simple_package_modules_with_space.py
new file mode 100644
index 0000000..169e6f7
--- /dev/null
+++ b/test/fixture/python_scanner/from_import_simple_package_modules_with_space.py
@@ -0,0 +1 @@
+from simple_package import module1, module2
diff --git a/test/fixture/python_scanner/import_simple_package_module1.py b/test/fixture/python_scanner/import_simple_package_module1.py
new file mode 100644
index 0000000..bd85010
--- /dev/null
+++ b/test/fixture/python_scanner/import_simple_package_module1.py
@@ -0,0 +1 @@
+import simple_package.module1
diff --git a/test/fixture/python_scanner/import_simple_package_module1_as.py b/test/fixture/python_scanner/import_simple_package_module1_as.py
new file mode 100644
index 0000000..a706672
--- /dev/null
+++ b/test/fixture/python_scanner/import_simple_package_module1_as.py
@@ -0,0 +1 @@
+import simple_package.module1 as m1
diff --git a/test/fixture/python_scanner/imports_nested3.py b/test/fixture/python_scanner/imports_nested3.py
new file mode 100644
index 0000000..c2929d0
--- /dev/null
+++ b/test/fixture/python_scanner/imports_nested3.py
@@ -0,0 +1 @@
+import nested1.nested2.nested3
diff --git a/test/fixture/python_scanner/imports_simple_package.py b/test/fixture/python_scanner/imports_simple_package.py
new file mode 100644
index 0000000..d974128
--- /dev/null
+++ b/test/fixture/python_scanner/imports_simple_package.py
@@ -0,0 +1 @@
+import simple_package
diff --git a/test/fixture/python_scanner/nested1/__init__.py b/test/fixture/python_scanner/nested1/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/__init__.py
diff --git a/test/fixture/python_scanner/nested1/module.py b/test/fixture/python_scanner/nested1/module.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/module.py
diff --git a/test/fixture/python_scanner/nested1/nested2/__init__.py b/test/fixture/python_scanner/nested1/nested2/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2/__init__.py
diff --git a/test/fixture/python_scanner/nested1/nested2/module.py b/test/fixture/python_scanner/nested1/nested2/module.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2/module.py
diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/__init__.py b/test/fixture/python_scanner/nested1/nested2/nested3/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2/nested3/__init__.py
diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/imports_grandparent_module.py b/test/fixture/python_scanner/nested1/nested2/nested3/imports_grandparent_module.py
new file mode 100644
index 0000000..06bb7f5
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2/nested3/imports_grandparent_module.py
@@ -0,0 +1 @@
+from ... import module
diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_module.py b/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_module.py
new file mode 100644
index 0000000..be10279
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_module.py
@@ -0,0 +1 @@
+from .. import module
diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_then_submodule.py b/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_then_submodule.py
new file mode 100644
index 0000000..39f1a1a
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2/nested3/imports_parent_then_submodule.py
@@ -0,0 +1 @@
+from ...nested2a import module
diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/module.py b/test/fixture/python_scanner/nested1/nested2/nested3/module.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2/nested3/module.py
diff --git a/test/fixture/python_scanner/nested1/nested2/nested3/sconstest.skip b/test/fixture/python_scanner/nested1/nested2/nested3/sconstest.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2/nested3/sconstest.skip
diff --git a/test/fixture/python_scanner/nested1/nested2/sconstest.skip b/test/fixture/python_scanner/nested1/nested2/sconstest.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2/sconstest.skip
diff --git a/test/fixture/python_scanner/nested1/nested2a/__init__.py b/test/fixture/python_scanner/nested1/nested2a/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2a/__init__.py
diff --git a/test/fixture/python_scanner/nested1/nested2a/module.py b/test/fixture/python_scanner/nested1/nested2a/module.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2a/module.py
diff --git a/test/fixture/python_scanner/nested1/nested2a/sconstest.skip b/test/fixture/python_scanner/nested1/nested2a/sconstest.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/nested2a/sconstest.skip
diff --git a/test/fixture/python_scanner/nested1/sconstest.skip b/test/fixture/python_scanner/nested1/sconstest.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/nested1/sconstest.skip
diff --git a/test/fixture/python_scanner/sconstest.skip b/test/fixture/python_scanner/sconstest.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/sconstest.skip
diff --git a/test/fixture/python_scanner/simple_package/__init__.py b/test/fixture/python_scanner/simple_package/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/simple_package/__init__.py
diff --git a/test/fixture/python_scanner/simple_package/module1.py b/test/fixture/python_scanner/simple_package/module1.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/simple_package/module1.py
diff --git a/test/fixture/python_scanner/simple_package/module2.py b/test/fixture/python_scanner/simple_package/module2.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/simple_package/module2.py
diff --git a/test/fixture/python_scanner/simple_package/sconstest.skip b/test/fixture/python_scanner/simple_package/sconstest.skip
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test/fixture/python_scanner/simple_package/sconstest.skip
diff --git a/test/fixture/wrapper.py b/test/fixture/wrapper.py
index a023689..112186e 100644
--- a/test/fixture/wrapper.py
+++ b/test/fixture/wrapper.py
@@ -7,4 +7,4 @@ if __name__ == '__main__':
if '--version' not in sys.argv and '-dumpversion' not in sys.argv:
with open(path, 'wb') as f:
f.write(b"wrapper.py\n")
- subprocess.call(sys.argv[1:])
+ subprocess.run(sys.argv[1:])
diff --git a/test/fixture/wrapper_with_args.py b/test/fixture/wrapper_with_args.py
index f9e4d22..b8d6ae5 100644
--- a/test/fixture/wrapper_with_args.py
+++ b/test/fixture/wrapper_with_args.py
@@ -6,4 +6,4 @@ if __name__ == '__main__':
path = os.path.join(os.path.dirname(os.path.relpath(__file__)), 'wrapper.out')
with open(path, 'a') as f:
f.write("wrapper_with_args.py %s\n" % " ".join(sys.argv[1:]))
- subprocess.call(sys.argv[1:])
+ subprocess.run(sys.argv[1:])
diff --git a/test/gnutools.py b/test/gnutools.py
index 040de2a..eb0d847 100644
--- a/test/gnutools.py
+++ b/test/gnutools.py
@@ -20,15 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Testing the gnu tool chain, i.e. the tools 'gcc', 'g++' and 'gnulink'.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import TestSCons
import sys
diff --git a/test/option--random.py b/test/option--random.py
index 2944ad8..c25ec12 100644
--- a/test/option--random.py
+++ b/test/option--random.py
@@ -20,15 +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.
-#
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify that we build correctly using the --random option.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os.path
import TestSCons
diff --git a/test/option-n.py b/test/option-n.py
index 2ec3fdc..e647b8e 100644
--- a/test/option-n.py
+++ b/test/option-n.py
@@ -91,27 +91,27 @@ test.fail_test(not os.path.exists(test.workpath('f2.out')))
test.unlink('f1.out')
test.unlink('f2.out')
-test.run(arguments = '-n ' + args, stdout = expect)
+test.run(arguments='-n ' + args, stdout=expect)
test.fail_test(os.path.exists(test.workpath('f1.out')))
test.fail_test(os.path.exists(test.workpath('f2.out')))
-test.run(arguments = '--no-exec ' + args, stdout = expect)
+test.run(arguments='--no-exec ' + args, stdout=expect)
test.fail_test(os.path.exists(test.workpath('f1.out')))
test.fail_test(os.path.exists(test.workpath('f2.out')))
-test.run(arguments = '--just-print ' + args, stdout = expect)
+test.run(arguments='--just-print ' + args, stdout=expect)
test.fail_test(os.path.exists(test.workpath('f1.out')))
test.fail_test(os.path.exists(test.workpath('f2.out')))
-test.run(arguments = '--dry-run ' + args, stdout = expect)
+test.run(arguments='--dry-run ' + args, stdout=expect)
test.fail_test(os.path.exists(test.workpath('f1.out')))
test.fail_test(os.path.exists(test.workpath('f2.out')))
-test.run(arguments = '--recon ' + args, stdout = expect)
+test.run(arguments='--recon ' + args, stdout=expect)
test.fail_test(os.path.exists(test.workpath('f1.out')))
test.fail_test(os.path.exists(test.workpath('f2.out')))
-test.run(arguments = args)
+test.run(arguments=args)
test.fail_test(not os.path.exists(test.workpath('f1.out')))
# Test that SCons does not write a modified .sconsign when -n is used.
@@ -120,14 +120,14 @@ expect = test.wrap_stdout("""\
""" % locals())
test.unlink('.sconsign.dblite')
test.write('f1.out', "X1.out\n")
-test.run(arguments = '-n f1.out', stdout = expect)
-test.run(arguments = '-n f1.out', stdout = expect)
+test.run(arguments='-n f1.out', stdout=expect)
+test.run(arguments='-n f1.out', stdout=expect)
expect = test.wrap_stdout("Removed f1.out\nRemoved f2.out\n", cleaning=1)
-test.run(arguments = '-n -c ' + args, stdout = expect)
+test.run(arguments='-n -c ' + args, stdout=expect)
-test.run(arguments = '-c -n ' + args, stdout = expect)
+test.run(arguments='-c -n ' + args, stdout=expect)
test.fail_test(not os.path.exists(test.workpath('f1.out')))
test.fail_test(not os.path.exists(test.workpath('f2.out')))
@@ -136,15 +136,15 @@ test.fail_test(not os.path.exists(test.workpath('f2.out')))
install_f3_in = os.path.join('install', 'f3.in')
expect = test.wrap_stdout('Install file: "f3.in" as "%s"\n' % install_f3_in)
-test.run(arguments = '-n install', stdout = expect)
+test.run(arguments='-n install', stdout=expect)
test.fail_test(os.path.exists(test.workpath('install', 'f3.in')))
-test.run(arguments = 'install', stdout = expect)
+test.run(arguments='install', stdout=expect)
test.fail_test(not os.path.exists(test.workpath('install', 'f3.in')))
test.write('f3.in', "f3.in again\n")
-test.run(arguments = '-n install', stdout = expect)
+test.run(arguments='-n install', stdout=expect)
test.fail_test(not os.path.exists(test.workpath('install', 'f3.in')))
# Make sure duplicate source files in a VariantDir aren't created
@@ -159,11 +159,11 @@ test.fail_test(not os.path.exists(test.workpath('install', 'f3.in')))
# method on that node, which may happen via other processing.
# Therefore add this conditional removal to ensure a clean setting
# before running this test.
-
+
if os.path.exists(test.workpath('build', 'f4.in')):
test.unlink(test.workpath('build', 'f4.in'))
-test.run(arguments = '-n build')
+test.run(arguments='-n build')
test.fail_test(os.path.exists(test.workpath('build', 'f4.in')))
# test Configure-calls in conjunction with -n
@@ -195,11 +195,11 @@ else:
env = conf.Finish()
""")
# test that conf_dir isn't created and an error is raised
-stderr=r"""
+stderr = r"""
scons: \*\*\* Cannot create configure directory "config\.test" within a dry-run\.
File \S+, line \S+, in \S+
"""
-test.run(arguments="-n",stderr=stderr,status=2,
+test.run(arguments="-n", stderr=stderr, status=2,
chdir=test.workpath("configure"))
test.fail_test(os.path.exists(test.workpath("configure", "config.test")))
test.fail_test(os.path.exists(test.workpath("configure", "config.log")))
@@ -207,12 +207,12 @@ test.fail_test(os.path.exists(test.workpath("configure", "config.log")))
# test that targets are not built, if conf_dir exists.
# verify that .cache and config.log are not created.
# an error should be raised
-stderr=r"""
+stderr = r"""
scons: \*\*\* Cannot update configure test "%s" within a dry-run\.
File \S+, line \S+, in \S+
-""" % re.escape(os.path.join("config.test", "conftest_0.in"))
-test.subdir(['configure','config.test'])
-test.run(arguments="-n",stderr=stderr,status=2,
+""" % re.escape(os.path.join("config.test", "conftest_b10a8db164e0754105b7a99be72e3fe5_0.in"))
+test.subdir(['configure', 'config.test'])
+test.run(arguments="-n", stderr=stderr, status=2,
chdir=test.workpath("configure"))
test.fail_test(os.path.exists(test.workpath("configure", "config.test",
".cache")))
@@ -224,15 +224,15 @@ test.fail_test(os.path.exists(test.workpath("configure", "config.log")))
# test that no error is raised, if all targets are up-to-date. In this
# case .cache and config.log shouldn't be created
-stdout=test.wrap_stdout(build_str="scons: `.' is up to date.\n",
- read_str=r"""Executing Custom Test ... \(cached\) yes
+stdout = test.wrap_stdout(build_str="scons: `.' is up to date.\n",
+ read_str=r"""Executing Custom Test ... \(cached\) yes
""")
-test.run(status=0,chdir=test.workpath("configure"))
-log1_mtime = os.path.getmtime(test.workpath("configure","config.log"))
-test.run(stdout=stdout,arguments="-n",status=0,
+test.run(status=0, chdir=test.workpath("configure"))
+log1_mtime = os.path.getmtime(test.workpath("configure", "config.log"))
+test.run(stdout=stdout, arguments="-n", status=0,
chdir=test.workpath("configure"))
-log2_mtime = os.path.getmtime(test.workpath("configure","config.log"))
-test.fail_test( log1_mtime != log2_mtime )
+log2_mtime = os.path.getmtime(test.workpath("configure", "config.log"))
+test.fail_test(log1_mtime != log2_mtime)
test.pass_test()
diff --git a/test/option-v.py b/test/option-v.py
index ed8c4e5..ec20b20 100644
--- a/test/option-v.py
+++ b/test/option-v.py
@@ -20,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.
-#
-from __future__ import print_function
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
diff --git a/test/option/debug-action-timestamps.py b/test/option/debug-action-timestamps.py
index 059cfdf..747d880 100644
--- a/test/option/debug-action-timestamps.py
+++ b/test/option/debug-action-timestamps.py
@@ -20,7 +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.
-from __future__ import division, print_function
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
diff --git a/test/option/debug-count.py b/test/option/debug-count.py
index 0234bfa..f2fceb4 100644
--- a/test/option/debug-count.py
+++ b/test/option/debug-count.py
@@ -20,14 +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.
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Test that the --debug=count option works.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import re
import sys
diff --git a/test/option/debug-multiple.py b/test/option/debug-multiple.py
index 020aa85..124e033 100644
--- a/test/option/debug-multiple.py
+++ b/test/option/debug-multiple.py
@@ -21,14 +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.
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
"""
Test that --debug can take multiple options
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import re
import TestSCons
diff --git a/test/option/debug-time.py b/test/option/debug-time.py
index 3ed7555..7e95af3 100644
--- a/test/option/debug-time.py
+++ b/test/option/debug-time.py
@@ -20,7 +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.
-from __future__ import division, print_function
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
diff --git a/test/option/help-options.py b/test/option/help-options.py
index 1835a62..2dac532 100644
--- a/test/option/help-options.py
+++ b/test/option/help-options.py
@@ -20,14 +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.
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify behavior of the -H and --help-options options.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import re
import TestSCons
diff --git a/test/packaging/convenience-functions/image/SConstruct b/test/packaging/convenience-functions/image/SConstruct
index f35c3e3..a424fd9 100644
--- a/test/packaging/convenience-functions/image/SConstruct
+++ b/test/packaging/convenience-functions/image/SConstruct
@@ -1,5 +1,3 @@
-from __future__ import print_function
-
env = Environment(tools=['default', 'packaging'])
prog = env.Install( 'bin/', ["f1", "f2"] )
env.File( "f3" )
diff --git a/test/packaging/use-builddir.py b/test/packaging/use-builddir.py
index 2395a8e..86a8219 100644
--- a/test/packaging/use-builddir.py
+++ b/test/packaging/use-builddir.py
@@ -28,13 +28,13 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
Test the ability to use the archiver in combination with builddir.
"""
-import os
+import subprocess
+
import TestSCons
python = TestSCons.python
test = TestSCons.TestSCons()
-test.verbose_set(3)
tar = test.detect("TAR", "tar")
if not tar:
@@ -48,9 +48,7 @@ test.subdir("build")
test.write("src/main.c", "")
-test.write(
- "SConstruct",
- """
+test.write("SConstruct", """\
VariantDir('build', 'src')
DefaultEnvironment(tools=[])
env=Environment(tools=['packaging', 'filesystem', 'zip'])
@@ -76,9 +74,7 @@ test.subdir("temp")
test.write("src/main.c", "")
-test.write(
- "SConstruct",
- """
+test.write("SConstruct", """\
DefaultEnvironment(tools=[])
VariantDir('build', 'src')
env=Environment(tools=['packaging', 'filesystem', 'tar'])
@@ -93,7 +89,8 @@ test.run(stderr=None)
test.must_exist("libfoo-1.2.3.tar.gz")
-os.system('%s -C temp -xzf %s'%(tar, test.workpath('libfoo-1.2.3.tar.gz') ))
+testdir = test.workpath('libfoo-1.2.3.tar.gz')
+subprocess.run('%s -C temp -xzf %s' % (tar, testdir), shell=True)
test.must_exist("temp/libfoo-1.2.3/src/main.c")
test.must_exist("temp/libfoo-1.2.3/SConstruct")
diff --git a/test/question/Configure.py b/test/question/Configure.py
index 88b0784..7df29f5 100644
--- a/test/question/Configure.py
+++ b/test/question/Configure.py
@@ -86,7 +86,7 @@ test.must_not_exist(test.workpath("config.log"))
stderr=r"""
scons: \*\*\* Cannot update configure test "%s" within a dry-run\.
File \S+, line \S+, in \S+
-""" % re.escape(os.path.join("config.test", "conftest_0.in"))
+""" % re.escape(os.path.join("config.test", "conftest_b10a8db164e0754105b7a99be72e3fe5_0.in"))
test.subdir('config.test')
@@ -94,7 +94,7 @@ test.run(arguments="-q aaa.out",stderr=stderr,status=2)
test.must_not_exist(test.workpath("config.test", ".cache"))
test.must_not_exist(test.workpath("config.test", "conftest_0"))
-test.must_not_exist(test.workpath("config.test", "conftest_0.in"))
+test.must_not_exist(test.workpath("config.test", "conftest_b10a8db164e0754105b7a99be72e3fe5_0.in"))
test.must_not_exist(test.workpath("config.log"))
# test that no error is raised, if all targets are up-to-date. In this
diff --git a/test/scons-time/run/config/python.py b/test/scons-time/run/config/python.py
index c8842c1..bf873fa 100644
--- a/test/scons-time/run/config/python.py
+++ b/test/scons-time/run/config/python.py
@@ -20,14 +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__"
"""
Verify specifying an alternate Python executable in a config file.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os
import TestSCons_time
@@ -46,7 +45,6 @@ python = r'%(my_python_py)s'
test.write(my_python_py, """\
#!%(_python_)s
-from __future__ import print_function
import sys
profile = ''
for arg in sys.argv[1:]:
diff --git a/test/scons-time/run/config/scons.py b/test/scons-time/run/config/scons.py
index b782e83..168ee7a 100644
--- a/test/scons-time/run/config/scons.py
+++ b/test/scons-time/run/config/scons.py
@@ -20,14 +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__"
"""
Verify specifying an alternate SCons through a config file.
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons_time
@@ -42,7 +40,6 @@ scons = r'%(my_scons_py)s'
""" % locals())
test.write(my_scons_py, """\
-from __future__ import print_function
import sys
profile = ''
for arg in sys.argv[1:]:
diff --git a/test/sconsign/script/Configure.py b/test/sconsign/script/Configure.py
index 679f084..125022d 100644
--- a/test/sconsign/script/Configure.py
+++ b/test/sconsign/script/Configure.py
@@ -55,7 +55,6 @@ CC_file = re.escape(CC_file)
# in the expected output because paths in the .sconsign files are
# canonicalized to use / as the separator.
-_sconf_temp_conftest_0_c = '.sconf_temp/conftest_0.c'
test.write('SConstruct', """
import os
@@ -69,6 +68,7 @@ test.run(arguments = '.')
sig_re = r'[0-9a-fA-F]{32}'
date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d'
+_sconf_temp_conftest_0_c = '.sconf_temp/conftest_%(sig_re)s_0.c'%locals()
# Note: There's a space at the end of the '.*': line, because the
# Value node being printed actually begins with a newline. It would
@@ -76,13 +76,13 @@ date_re = r'\S+ \S+ [ \d]\d \d\d:\d\d:\d\d \d\d\d\d'
expect = r"""=== .:
SConstruct: None \d+ \d+
=== .sconf_temp:
-conftest_0.c:
+conftest_%(sig_re)s_0.c:
'.*':
#include "math.h"
%(sig_re)s \[.*\]
-conftest_0%(_obj)s:
+conftest_%(sig_re)s_0_%(sig_re)s%(_obj)s:
%(_sconf_temp_conftest_0_c)s: %(sig_re)s \d+ \d+
%(CC)s: %(sig_re)s \d+ \d+
%(sig_re)s \[.*\]
diff --git a/test/site_scons/sysdirs.py b/test/site_scons/sysdirs.py
index 36a581e..61f9c02 100644
--- a/test/site_scons/sysdirs.py
+++ b/test/site_scons/sysdirs.py
@@ -20,13 +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.
-#
-
-from __future__ import print_function
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
-
-import TestSCons
"""
Verify site_scons system dirs are getting loaded.
@@ -37,6 +30,10 @@ files from the system dirs, but the test harness can't put files in
those dirs (which may not even exist on a build system).
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+import TestSCons
+
test = TestSCons.TestSCons()
test.write('SConstruct', """
diff --git a/test/srcchange.py b/test/srcchange.py
index c2356b6..30f6f20 100644
--- a/test/srcchange.py
+++ b/test/srcchange.py
@@ -20,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__"
"""
Test changing the C source files based on an always-executed revision
@@ -33,6 +30,8 @@ expected. This relies on the default behavior being the equivalent
of Decider('content').
"""
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
import os.path
import TestSCons
@@ -42,7 +41,6 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
test.write('getrevision', r"""
-from __future__ import print_function
with open('revnum.in', 'r') as f:
print(f.read().strip(), end='')
""")
@@ -62,7 +60,7 @@ SubRevision = Action(subrevision)
env=Environment()
content_env=env.Clone()
-content_env.Command('revision.in', [], '%(_python_)s getrevision > $TARGET')
+content_env.Command('revision.in', [], r'%(_python_)s getrevision > $TARGET')
content_env.AlwaysBuild('revision.in')
env.Precious('main.c')
env.Command('main.c', 'revision.in', SubRevision)
diff --git a/test/textfile/fixture/SConstruct b/test/textfile/fixture/SConstruct
new file mode 100644
index 0000000..8cfe909
--- /dev/null
+++ b/test/textfile/fixture/SConstruct
@@ -0,0 +1,22 @@
+DefaultEnvironment(tools=[])
+
+
+env = Environment(tools=['textfile'])
+data0 = ['Goethe', 'Schiller']
+data = ['lalala', 42, data0, 'tanteratei']
+
+env.Textfile('foo1', data)
+env.Textfile('foo2', data, LINESEPARATOR='|*')
+env.Textfile('foo1a.txt', data + [''])
+env.Textfile('foo2a.txt', data + [''], LINESEPARATOR='|*')
+
+# recreate the list with the data wrapped in Value()
+data0 = list(map(Value, data0))
+data = list(map(Value, data))
+data[2] = data0
+
+env.Substfile('bar1', data)
+env.Substfile('bar2', data, LINESEPARATOR='|*')
+data.append(Value(''))
+env.Substfile('bar1a.txt', data)
+env.Substfile('bar2a.txt', data, LINESEPARATOR='|*')
diff --git a/test/textfile/fixture/SConstruct.2 b/test/textfile/fixture/SConstruct.2
new file mode 100644
index 0000000..b7e63a1
--- /dev/null
+++ b/test/textfile/fixture/SConstruct.2
@@ -0,0 +1,25 @@
+DefaultEnvironment(tools=[])
+
+textlist = ['This line has no substitutions',
+ 'This line has @subst@ substitutions',
+ 'This line has %subst% substitutions',
+ ]
+
+sub1 = {'@subst@': 'most'}
+sub2 = {'%subst%': 'many'}
+sub3 = {'@subst@': 'most', '%subst%': 'many'}
+
+env = Environment(tools=['textfile'])
+
+t = env.Textfile('text', textlist)
+# no substitutions
+s = env.Substfile('sub1', t)
+# one substitution
+s = env.Substfile('sub2', s, SUBST_DICT=sub1)
+# the other substution
+s = env.Substfile('sub3', s, SUBST_DICT=sub2)
+# the reverse direction
+s = env.Substfile('sub4', t, SUBST_DICT=sub2)
+s = env.Substfile('sub5', s, SUBST_DICT=sub1)
+# both
+s = env.Substfile('sub6', t, SUBST_DICT=sub3)
diff --git a/test/textfile/fixture/SConstruct.issue-3550 b/test/textfile/fixture/SConstruct.issue-3550
new file mode 100644
index 0000000..8502717
--- /dev/null
+++ b/test/textfile/fixture/SConstruct.issue-3550
@@ -0,0 +1,12 @@
+DefaultEnvironment(tools=[])
+env = Environment(tools=['textfile'])
+
+env['FOO_PATH'] = r'Z:\mongo\build\install\bin'
+
+foo = env.Substfile(
+ target="foo",
+ source="foo-3550.in",
+ SUBST_DICT={
+ "@foo_path@": "$FOO_PATH",
+ }
+)
diff --git a/test/textfile/fixture/foo-3550.in b/test/textfile/fixture/foo-3550.in
new file mode 100644
index 0000000..c806a04
--- /dev/null
+++ b/test/textfile/fixture/foo-3550.in
@@ -0,0 +1 @@
+foo_path: @foo_path@
diff --git a/test/textfile/issue-3550.py b/test/textfile/issue-3550.py
new file mode 100644
index 0000000..60430ed
--- /dev/null
+++ b/test/textfile/issue-3550.py
@@ -0,0 +1,44 @@
+#!/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__"
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+test.verbose_set(1)
+
+match_mode = 'r'
+
+test.file_fixture('fixture/SConstruct.issue-3550', 'SConstruct')
+test.file_fixture('fixture/foo-3550.in', 'foo-3550.in')
+
+test.run(arguments='.')
+
+test.must_match('foo',
+ r'''foo_path: Z:\mongo\build\install\bin
+''', mode=match_mode)
+
+test.pass_test()
diff --git a/test/textfile.py b/test/textfile/textfile.py
index 1d5b3c7..0f2e18e 100644
--- a/test/textfile.py
+++ b/test/textfile/textfile.py
@@ -31,33 +31,13 @@ import os
test = TestSCons.TestSCons()
foo1 = test.workpath('foo1.txt')
-#foo2 = test.workpath('foo2.txt')
-#foo1a = test.workpath('foo1a.txt')
-#foo2a = test.workpath('foo2a.txt')
+# foo2 = test.workpath('foo2.txt')
+# foo1a = test.workpath('foo1a.txt')
+# foo2a = test.workpath('foo2a.txt')
match_mode = 'r'
-test.write('SConstruct', """
-env = Environment(tools=['textfile'])
-data0 = ['Goethe', 'Schiller']
-data = ['lalala', 42, data0, 'tanteratei']
-
-env.Textfile('foo1', data)
-env.Textfile('foo2', data, LINESEPARATOR='|*')
-env.Textfile('foo1a.txt', data + [''])
-env.Textfile('foo2a.txt', data + [''], LINESEPARATOR='|*')
-
-# recreate the list with the data wrapped in Value()
-data0 = list(map(Value, data0))
-data = list(map(Value, data))
-data[2] = data0
-
-env.Substfile('bar1', data)
-env.Substfile('bar2', data, LINESEPARATOR='|*')
-data.append(Value(''))
-env.Substfile('bar1a.txt', data)
-env.Substfile('bar2a.txt', data, LINESEPARATOR='|*')
-""", mode='w')
+test.file_fixture('fixture/SConstruct', 'SConstruct')
test.run(arguments='.')
@@ -75,7 +55,7 @@ test.up_to_date(arguments='.')
files = list(map(test.workpath, (
'foo1.txt', 'foo2.txt', 'foo1a.txt', 'foo2a.txt',
- 'bar1', 'bar2', 'bar1a.txt', 'bar2a.txt',
+ 'bar1', 'bar2', 'bar1a.txt', 'bar2a.txt',
)))
@@ -93,10 +73,10 @@ def check_times():
# make sure that the file content is as expected
-test.must_match('foo1.txt', foo1Text, mode=match_mode)
-test.must_match('bar1', foo1Text, mode=match_mode)
-test.must_match('foo2.txt', foo2Text, mode=match_mode)
-test.must_match('bar2', foo2Text, mode=match_mode)
+test.must_match('foo1.txt', foo1Text, mode=match_mode)
+test.must_match('bar1', foo1Text, mode=match_mode)
+test.must_match('foo2.txt', foo2Text, mode=match_mode)
+test.must_match('bar2', foo2Text, mode=match_mode)
test.must_match('foo1a.txt', foo1aText, mode=match_mode)
test.must_match('bar1a.txt', foo1aText, mode=match_mode)
test.must_match('foo2a.txt', foo2aText, mode=match_mode)
@@ -105,10 +85,10 @@ check_times()
# write the contents and make sure the files
# didn't get rewritten, because nothing changed:
-test.write('foo1.txt', foo1Text)
-test.write('bar1', foo1Text)
-test.write('foo2.txt', foo2Text)
-test.write('bar2', foo2Text)
+test.write('foo1.txt', foo1Text)
+test.write('bar1', foo1Text)
+test.write('foo2.txt', foo2Text)
+test.write('bar2', foo2Text)
test.write('foo1a.txt', foo1aText)
test.write('bar1a.txt', foo1aText)
test.write('foo2a.txt', foo2aText)
@@ -117,33 +97,9 @@ check_times()
# now that textfile is part of default tool list, run one testcase
# without adding it explicitly as a tool to make sure.
-test.write('SConstruct', """
-textlist = ['This line has no substitutions',
- 'This line has @subst@ substitutions',
- 'This line has %subst% substitutions',
- ]
-
-sub1 = { '@subst@' : 'most' }
-sub2 = { '%subst%' : 'many' }
-sub3 = { '@subst@' : 'most' , '%subst%' : 'many' }
-
-env = Environment()
-
-t = env.Textfile('text', textlist)
-# no substitutions
-s = env.Substfile('sub1', t)
-# one substitution
-s = env.Substfile('sub2', s, SUBST_DICT = sub1)
-# the other substution
-s = env.Substfile('sub3', s, SUBST_DICT = sub2)
-# the reverse direction
-s = env.Substfile('sub4', t, SUBST_DICT = sub2)
-s = env.Substfile('sub5', s, SUBST_DICT = sub1)
-# both
-s = env.Substfile('sub6', t, SUBST_DICT = sub3)
-""", mode='w')
+test.file_fixture('fixture/SConstruct.2', 'SConstruct.2')
-test.run(arguments='.')
+test.run(options='-f SConstruct.2', arguments='.')
line1 = 'This line has no substitutions'
line2a = 'This line has @subst@ substitutions'
@@ -158,7 +114,7 @@ def matchem(match_file, lines):
then compare
"""
lines = linesep.join(lines)
- test.must_match(match_file, lines, mode=match_mode, message="Expected:\n%s\n"%lines)
+ test.must_match(match_file, lines, mode=match_mode, message="Expected:\n%s\n" % lines)
matchem('text.txt', [line1, line2a, line3a])
@@ -169,6 +125,6 @@ matchem('sub4', [line1, line2a, line3b])
matchem('sub5', [line1, line2b, line3b])
matchem('sub6', [line1, line2b, line3b])
-test.up_to_date(arguments='.')
+test.up_to_date(options='-f SConstruct.2', arguments='.')
test.pass_test()
diff --git a/test/update-release-info/update-release-info.py b/test/update-release-info/update-release-info.py
index d0242a8..a6ce5b4 100644
--- a/test/update-release-info/update-release-info.py
+++ b/test/update-release-info/update-release-info.py
@@ -32,65 +32,63 @@ import os, sys, time
import TestRuntest
# Needed to ensure we're using the correct year
-this_year=time.localtime()[0]
-
-TestSCons = 'testing/framework/TestSCons.py' .split('/')
-README = 'README.rst' .split('/')
-ReleaseConfig = 'ReleaseConfig' .split('/')
-SConstruct = 'SConstruct' .split('/')
-Announce = 'src/Announce.txt' .split('/')
-CHANGES = 'src/CHANGES.txt' .split('/')
-RELEASE = 'src/RELEASE.txt' .split('/')
-Main = 'src/engine/SCons/Script/Main.py' .split('/')
-main_in = 'doc/user/main.in' .split('/')
-main_xml = 'doc/user/main.xml' .split('/')
+this_year = time.localtime()[0]
+
+TestSCons = 'testing/framework/TestSCons.py'.split('/')
+README = 'README.rst'.split('/')
+ReleaseConfig = 'ReleaseConfig'.split('/')
+SConstruct = 'SConstruct'.split('/')
+Announce = 'src/Announce.txt'.split('/')
+CHANGES = 'src/CHANGES.txt'.split('/')
+RELEASE = 'src/RELEASE.txt'.split('/')
+Main = 'src/engine/SCons/Script/Main.py'.split('/')
+main_in = 'doc/user/main.in'.split('/')
+main_xml = 'doc/user/main.xml'.split('/')
test = TestRuntest.TestRuntest(
- program = os.path.join('bin', 'update-release-info.py'),
- things_to_copy = ['bin']
- )
+ program=os.path.join('bin', 'update-release-info.py'),
+ things_to_copy=['bin']
+)
+# test.verbose_set(1)
if not os.path.exists(test.program):
test.skip_test("update-release-info.py is not distributed in this package\n")
-test.run(arguments = 'bad', status = 1)
+expected_stderr = """usage: update-release-info.py [-h] [--verbose] [--timestamp TIMESTAMP]
+ [{develop,release,post}]
+update-release-info.py: error: argument mode: invalid choice: 'bad' (choose from 'develop', 'release', 'post')
+"""
+test.run(arguments='bad', stderr=expected_stderr, status=2)
# Strings to go in ReleaseConfig
combo_strings = [
-# Index 0: version tuple with bad release level
-"""version_tuple = (2, 0, 0, 'bad', 0)
-""",
-# Index 1: Python version tuple
-"""unsupported_python_version = (2, 6)
-""",
-# Index 2: Python version tuple
-"""deprecated_python_version = (2, 7)
-""",
-# Index 3: alpha version tuple
-"""version_tuple = (2, 0, 0, 'alpha', 0)
-""",
-# Index 4: final version tuple
-"""version_tuple = (2, 0, 0, 'final', 0)
-""",
-# Index 5: bad release date
-"""release_date = (%d, 12)
-"""%this_year,
-# Index 6: release date (hhhh, mm, dd)
-"""release_date = (%d, 12, 21)
-"""%this_year,
-# Index 7: release date (hhhh, mm, dd, hh, mm, ss)
-"""release_date = (%d, 12, 21, 12, 21, 12)
-"""%this_year,
+ # Index 0: version tuple with bad release level
+ """version_tuple = (2, 0, 0, 'bad', 0)\n""",
+ # Index 1: Python version tuple
+ """unsupported_python_version = (2, 6)\n""",
+ # Index 2: Python version tuple
+ """deprecated_python_version = (2, 7)\n""",
+ # Index 3: alpha version tuple
+ """version_tuple = (2, 0, 0, 'dev', 0)\n""",
+ # Index 4: final version tuple
+ """version_tuple = (2, 0, 0, 'final', 0)\n""",
+ # Index 5: bad release date
+ """release_date = (%d, 12)\n""" % this_year,
+ # Index 6: release date (hhhh, mm, dd)
+ """release_date = (%d, 12, 21)\n""" % this_year,
+ # Index 7: release date (hhhh, mm, dd, hh, mm, ss)
+ """release_date = (%d, 12, 21, 12, 21, 12)\n""" % this_year,
]
combo_error = \
-"""ERROR: Config file must contain at least version_tuple,
-\tunsupported_python_version, and deprecated_python_version.
-"""
+ """ERROR: Config file must contain at least version_tuple,
+\tunsupported_python_version, and deprecated_python_version.\n"""
+
def combo_fail(*args, **kw):
kw.setdefault('status', 1)
combo_run(*args, **kw)
+
def combo_run(*args, **kw):
t = '\n'
for a in args:
@@ -101,6 +99,7 @@ def combo_run(*args, **kw):
kw.setdefault('stdout', combo_error)
test.run(**kw)
+
combo_fail()
combo_fail(0)
combo_fail(1)
@@ -108,17 +107,17 @@ combo_fail(2)
combo_fail(0, 1)
combo_fail(0, 2)
combo_fail(1, 2)
-combo_fail(0, 1, 2, stdout =
+combo_fail(0, 1, 2, stdout=
"""ERROR: `bad' is not a valid release type in version tuple;
-\tit must be one of alpha, beta, candidate, or final
-""")
+\tit must be one of dev, beta, candidate, or final\n""")
# We won't need this entry again, so put in a default
combo_strings[0] = combo_strings[1] + combo_strings[2] + combo_strings[3]
-combo_fail(0, 5, stdout =
+combo_fail(0, 5, stdout=
"""ERROR: Invalid release date (%d, 12)
-"""%this_year )
+""" % this_year)
+
def pave(path):
path = path[:-1]
@@ -127,10 +126,12 @@ def pave(path):
pave(path)
test.subdir(path)
+
def pave_write(file, contents):
pave(file)
test.write(file, contents)
+
pave_write(CHANGES, """
RELEASE It doesn't matter what goes here...
""")
@@ -180,80 +181,81 @@ pave_write(main_xml, """
TODO
""")
+
def updating_run(*args):
stdout = ''
for file in args:
stdout += 'Updating %s...\n' % os.path.join(*file)
- combo_run(0, 7, stdout = stdout)
+ combo_run(0, 7, stdout=stdout, arguments=['--timestamp=yyyymmdd'])
+
updating_run(CHANGES, RELEASE, Announce, SConstruct, README, TestSCons, Main)
test.must_match(CHANGES, """
-RELEASE 2.0.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE
-""", mode = 'r')
+RELEASE 2.0.0.devyyyymmdd - NEW DATE WILL BE INSERTED HERE
+""", mode='r')
test.must_match(RELEASE, """
-This file has a 2.0.0.alpha.yyyymmdd version string in it
-""", mode = 'r')
+This file has a 2.0.0.devyyyymmdd version string in it
+""", mode='r')
test.must_match(Announce, """
-RELEASE 2.0.0.alpha.yyyymmdd - NEW DATE WILL BE INSERTED HERE
-""", mode = 'r')
-
+RELEASE 2.0.0.devyyyymmdd - NEW DATE WILL BE INSERTED HERE
+""", mode='r')
-years = '2001 - %d'%(this_year + 1)
+years = '2001 - %d' % (this_year + 1)
test.must_match(SConstruct, """
month_year = 'MONTH YEAR'
copyright_years = %s
-default_version = '2.0.0.alpha.yyyymmdd'
-""" % repr(years), mode = 'r')
+default_version = '2.0.0.devyyyymmdd'
+""" % repr(years), mode='r')
test.must_match(README, """
These files are a part of 33.22.11:
- scons-2.0.0.alpha.yyyymmdd.tar.gz
- scons-2.0.0.alpha.yyyymmdd.win32.exe
- scons-2.0.0.alpha.yyyymmdd.zip
- scons-2.0.0.alpha.yyyymmdd.rpm
- scons-2.0.0.alpha.yyyymmdd.deb
+ scons-2.0.0.devyyyymmdd.tar.gz
+ scons-2.0.0.devyyyymmdd.win32.exe
+ scons-2.0.0.devyyyymmdd.zip
+ scons-2.0.0.devyyyymmdd.rpm
+ scons-2.0.0.devyyyymmdd.deb
- scons-2.0.0.alpha.yyyymmdd.suffix
-""", mode = 'r')
+ scons-2.0.0.devyyyymmdd.suffix
+""", mode='r')
# should get Python floors from TestSCons module.
test.must_match(TestSCons, """
copyright_years = '%s'
-default_version = '2.0.0.alpha.yyyymmdd'
+default_version = '2.0.0.devyyyymmdd'
python_version_unsupported = (2, 6)
python_version_deprecated = (2, 7)
-"""%years, mode = 'r')
+""" % years, mode='r')
# should get Python floors from TestSCons module.
test.must_match(Main, """
unsupported_python_version = (2, 6)
deprecated_python_version = (2, 7)
-""", mode = 'r')
-
-#TODO: Release option
-#TODO: ==============
-#TODO:
-#TODO: Dates in beta/candidate flow
-#TODO:
-#TODO: Dates in final flow
-#TODO:
-#TODO: Post option
-#TODO: ===========
-#TODO:
-#TODO: Dates in post flow
-#TODO:
-#TODO: Update minor or micro version
-#TODO:
-#TODO: ReleaseConfig - new version tuple
-#TODO:
-#TODO: CHANGES - new section
-#TODO:
-#TODO: RELEASE - new template
-#TODO:
-#TODO: Announce - new section
+""", mode='r')
+
+# TODO: Release option
+# TODO: ==============
+# TODO:
+# TODO: Dates in beta/candidate flow
+# TODO:
+# TODO: Dates in final flow
+# TODO:
+# TODO: Post option
+# TODO: ===========
+# TODO:
+# TODO: Dates in post flow
+# TODO:
+# TODO: Update minor or micro version
+# TODO:
+# TODO: ReleaseConfig - new version tuple
+# TODO:
+# TODO: CHANGES - new section
+# TODO:
+# TODO: RELEASE - new template
+# TODO:
+# TODO: Announce - new section
test.pass_test()
diff --git a/testing/framework/TestCmd.py b/testing/framework/TestCmd.py
index 6beed24..ed8b4b4 100644
--- a/testing/framework/TestCmd.py
+++ b/testing/framework/TestCmd.py
@@ -285,7 +285,6 @@ version.
# PARTICULAR PURPOSE. THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-from __future__ import division, print_function
__author__ = "Steven Knight <knight at baldmt dot com>"
__revision__ = "TestCmd.py 1.3.D001 2010/06/03 12:58:27 knight"
@@ -358,14 +357,8 @@ def to_str(s):
return str(s, 'utf-8')
-try:
- eval('unicode')
-except NameError:
- def is_String(e):
- return isinstance(e, (str, UserString))
-else:
- def is_String(e):
- return isinstance(e, (str, unicode, UserString))
+def is_String(e):
+ return isinstance(e, (str, UserString))
testprefix = 'testcmd.'
if os.name in ('posix', 'nt'):
@@ -498,11 +491,9 @@ def match_caseinsensitive(lines=None, matches=None):
"""
Match function using case-insensitive matching.
- Only a simplistic comparison is done, based on lowercasing the
- strings. This has plenty of holes for unicode data using
- non-English languages.
-
- TODO: casefold() is better than lower() if we don't need Py2 support.
+ Only a simplistic comparison is done, based on casefolding
+ the strings. This may still fail but is the suggestion of
+ the Unicode Standard.
:param lines: data lines
:type lines: str or list[str]
@@ -518,7 +509,7 @@ def match_caseinsensitive(lines=None, matches=None):
if len(lines) != len(matches):
return None
for line, match in zip(lines, matches):
- if line.lower() != match.lower():
+ if line.casefold() != match.casefold():
return None
return 1
@@ -706,7 +697,7 @@ if sys.platform == 'win32':
if is_String(pathext):
pathext = pathext.split(os.pathsep)
for ext in pathext:
- if ext.lower() == file[-len(ext):].lower():
+ if ext.casefold() == file[-len(ext):].casefold():
pathext = ['']
break
for dir in path:
@@ -1094,7 +1085,7 @@ class TestCmd(object):
condition = self.condition
if self._preserve[condition]:
for dir in self._dirlist:
- print(u"Preserved directory " + dir)
+ print("Preserved directory " + dir)
else:
list = self._dirlist[:]
list.reverse()
@@ -1510,13 +1501,13 @@ class TestCmd(object):
@staticmethod
def fix_binary_stream(stream):
"""
- Handle stdout/stderr from popen when we specify universal_newlines = False.
+ Handle stdout/stderr from popen when we specify not universal_newlines
- This will read from the pipes in binary mode, not decode the output,
- and not convert line endings to \n.
+ This will read from the pipes in binary mode, will not decode the
+ output, and will not convert line endings to \n.
We do this because in py3 (3.5) with universal_newlines=True, it will
choose the default system locale to decode the output, and this breaks unicode
- output. Specifically breaking test/option--tree.py which outputs a unicode char.
+ output. Specifically test/option--tree.py which outputs a unicode char.
py 3.6 allows us to pass an encoding param to popen thus not requiring the decode
nor end of line handling, because we propagate universal_newlines as specified.
@@ -1536,7 +1527,6 @@ class TestCmd(object):
return stream
-
def finish(self, popen=None, **kw):
"""
Finishes and waits for the process being run under control of
@@ -1975,13 +1965,20 @@ class TestCmd(object):
do_chmod(top)
def write(self, file, content, mode='wb'):
- """Writes the specified content text (second argument) to the
- specified file name (first argument). The file name may be
- a list, in which case the elements are concatenated with the
- os.path.join() method. The file is created under the temporary
- working directory. Any subdirectories in the path must already
- exist. The I/O mode for the file may be specified; it must
- begin with a 'w'. The default is 'wb' (binary write).
+ """Write data to file
+
+ The file is created under the temporary working directory.
+ Any subdirectories in the path must already exist. The
+ write is converted to the required type rather than failing
+ if there is a str/bytes mistmatch.
+
+ :param file: name of file to write to. If a list, treated
+ as components of a path and concatenated into a path.
+ :type file: str or list(str)
+ :param content: data to write.
+ :type content: str or bytes
+ :param mode: file mode, default is binary.
+ :type mode: str
"""
file = self.canonicalize(file)
if mode[0] != 'w':
@@ -1990,7 +1987,6 @@ class TestCmd(object):
try:
f.write(content)
except TypeError as e:
- # python 3 default strings are not bytes, but unicode
f.write(bytes(content, 'utf-8'))
# Local Variables:
diff --git a/testing/framework/TestCmdTests.py b/testing/framework/TestCmdTests.py
index 48eba1e..e8c2744 100644
--- a/testing/framework/TestCmdTests.py
+++ b/testing/framework/TestCmdTests.py
@@ -254,7 +254,7 @@ class cleanup_TestCase(TestCmdTestCase):
def test_atexit(self):
"""Test cleanup() when atexit is used"""
- self.popen_python("""from __future__ import print_function
+ self.popen_python("""\
import sys
sys.path = ['%s'] + sys.path
import atexit
@@ -269,7 +269,7 @@ sys.exit(0)
@unittest.skipIf(TestCmd.IS_PY3, "No sys.exitfunc in Python 3")
def test_exitfunc(self):
"""Test cleanup() when sys.exitfunc is set"""
- self.popen_python("""from __future__ import print_function
+ self.popen_python("""\
import sys
sys.path = ['%s'] + sys.path
def my_exitfunc():
@@ -609,7 +609,7 @@ sys.exit(0)
def test_diff_stderr_not_affecting_diff_stdout(self):
"""Test diff_stderr() not affecting diff_stdout() behavior"""
- self.popen_python(r"""from __future__ import print_function
+ self.popen_python(r"""
import sys
sys.path = ['%s'] + sys.path
import TestCmd
@@ -716,7 +716,7 @@ sys.exit(0)
def test_diff_stdout_not_affecting_diff_stderr(self):
"""Test diff_stdout() not affecting diff_stderr() behavior"""
- self.popen_python(r"""from __future__ import print_function
+ self.popen_python(r"""
import sys
sys.path = ['%s'] + sys.path
import TestCmd
@@ -2089,7 +2089,7 @@ sys.exit(0)
def test_set_diff_function_stdout(self):
"""Test set_diff_function(): stdout"""
- self.popen_python("""from __future__ import print_function
+ self.popen_python("""\
import sys
sys.path = ['%s'] + sys.path
import TestCmd
@@ -2118,7 +2118,7 @@ diff_stdout:
def test_set_diff_function_stderr(self):
"""Test set_diff_function(): stderr """
- self.popen_python("""from __future__ import print_function
+ self.popen_python("""\
import sys
sys.path = ['%s'] + sys.path
import TestCmd
@@ -2693,7 +2693,7 @@ class stdin_TestCase(TestCmdTestCase):
def test_stdin(self):
"""Test stdin()"""
run_env = TestCmd.TestCmd(workdir = '')
- run_env.write('run', """from __future__ import print_function
+ run_env.write('run', """\
import fileinput
for line in fileinput.input():
print('Y'.join(line[:-1].split('X')))
@@ -3332,15 +3332,13 @@ class variables_TestCase(TestCmdTestCase):
'TestCmd',
]
- script = "from __future__ import print_function\n" + \
- "import TestCmd\n" + \
+ script = "import TestCmd\n" + \
'\n'.join([ "print(TestCmd.%s\n)" % v for v in variables ])
run_env.run(program=sys.executable, stdin=script)
stderr = run_env.stderr()
assert stderr == "", stderr
- script = "from __future__ import print_function\n" + \
- "from TestCmd import *\n" + \
+ script = "from TestCmd import *\n" + \
'\n'.join([ "print(%s)" % v for v in variables ])
run_env.run(program=sys.executable, stdin=script)
stderr = run_env.stderr()
diff --git a/testing/framework/TestCommon.py b/testing/framework/TestCommon.py
index 8e6cc8e..1bd9f6b 100644
--- a/testing/framework/TestCommon.py
+++ b/testing/framework/TestCommon.py
@@ -93,8 +93,6 @@ The TestCommon module also provides the following variables
# AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-from __future__ import print_function
-
__author__ = "Steven Knight <knight at baldmt dot com>"
__revision__ = "TestCommon.py 1.3.D001 2010/06/03 12:58:27 knight"
__version__ = "1.3"
diff --git a/testing/framework/TestCommonTests.py b/testing/framework/TestCommonTests.py
index c54f33f..01e9fe1 100644
--- a/testing/framework/TestCommonTests.py
+++ b/testing/framework/TestCommonTests.py
@@ -45,10 +45,9 @@ def lstrip(s):
lines = [ l[spaces:] for l in lines ]
return '\n'.join(lines)
-if sys.version[:3] == '1.5':
- expected_newline = '\\012'
-else:
- expected_newline = '\\n'
+
+expected_newline = '\\n'
+
def assert_display(expect, result, error=None):
try:
@@ -57,9 +56,9 @@ def assert_display(expect, result, error=None):
pass
result = [
'\n',
- ('*'*80) + '\n',
+ 'EXPECTED'+('*'*80) + '\n',
expect,
- ('*'*80) + '\n',
+ 'GOT'+('*'*80) + '\n',
result,
('*'*80) + '\n',
]
@@ -168,7 +167,6 @@ class __init__TestCase(TestCommonTestCase):
os.chdir(run_env.workdir)
script = lstrip("""\
- from __future__ import print_function
from TestCommon import TestCommon
tc = TestCommon(workdir='')
import os
@@ -353,14 +351,13 @@ class must_contain_TestCase(TestCommonTestCase):
expect = lstrip("""\
File `file1' does not contain required string.
Required string ================================================================
- 1 c
+ b'1 c'
file1 contents =================================================================
- file1 does not match
-
+ b'file1 does not match\\n'
""")
run_env.run(program=sys.executable, stdin=script)
stdout = run_env.stdout()
- assert stdout == expect, repr(stdout)
+ assert stdout == expect, "got:\n%s\nexpected:\n%s"%(stdout, expect)
stderr = run_env.stderr()
assert stderr.find("FAILED") != -1, stderr
@@ -1294,7 +1291,7 @@ class must_not_contain_TestCase(TestCommonTestCase):
from TestCommon import TestCommon
tc = TestCommon(workdir='')
tc.write('file1', "file1 contents\\n")
- tc.must_not_contain('file1', "1 does not contain c")
+ tc.must_not_contain('file1', b"1 does not contain c")
tc.pass_test()
""")
run_env.run(program=sys.executable, stdin=script)
@@ -1327,20 +1324,20 @@ class must_not_contain_TestCase(TestCommonTestCase):
from TestCommon import TestCommon
tc = TestCommon(workdir='')
tc.write('file1', "file1 does contain contents\\n")
- tc.must_not_contain('file1', "1 does contain c")
+ tc.must_not_contain('file1', b"1 does contain c")
tc.run()
""")
expect = lstrip("""\
File `file1' contains banned string.
Banned string ==================================================================
- 1 does contain c
+ b'1 does contain c'
file1 contents =================================================================
- file1 does contain contents
-
+ b'file1 does contain contents\\n'
""")
run_env.run(program=sys.executable, stdin=script)
stdout = run_env.stdout()
- assert stdout == expect, repr(stdout)
+ assert stdout == expect, "\ngot:\n%s\nexpected:\n%s" % (stdout, expect)
+
stderr = run_env.stderr()
assert stderr.find("FAILED") != -1, stderr
@@ -1352,20 +1349,20 @@ class must_not_contain_TestCase(TestCommonTestCase):
from TestCommon import TestCommon
tc = TestCommon(workdir='')
tc.write('file1', "file1 does contain contents\\n")
- tc.must_not_contain('file1', "file1 does")
+ tc.must_not_contain('file1', b"file1 does")
tc.run()
""")
expect = lstrip("""\
File `file1' contains banned string.
Banned string ==================================================================
- file1 does
+ b'file1 does'
file1 contents =================================================================
- file1 does contain contents
-
+ b'file1 does contain contents\\n'
""")
run_env.run(program=sys.executable, stdin=script)
stdout = run_env.stdout()
- assert stdout == expect, repr(stdout)
+ assert stdout == expect, "\ngot:\n%s\nexpected:\n%s" % (stdout, expect)
+
stderr = run_env.stderr()
assert stderr.find("FAILED") != -1, stderr
@@ -1379,7 +1376,7 @@ class must_not_contain_TestCase(TestCommonTestCase):
tc.write('file1', "file1 contents\\n", mode='w')
tc.must_not_contain('file1', "1 does not contain c", mode='r')
tc.write('file2', "file2 contents\\n", mode='wb')
- tc.must_not_contain('file2', "2 does not contain c", mode='rb')
+ tc.must_not_contain('file2', b"2 does not contain c", mode='rb')
tc.pass_test()
""")
run_env.run(program=sys.executable, stdin=script)
@@ -1891,6 +1888,7 @@ class run_TestCase(TestCommonTestCase):
expect_stdout = lstrip("""\
STDOUT =========================================================================
+ None
STDERR =========================================================================
""")
@@ -1904,6 +1902,9 @@ class run_TestCase(TestCommonTestCase):
.*
File "[^"]+TestCommon.py", line \\d+, in start
raise e
+ File "[^"]+TestCommon.py", line \\d+, in start
+ return TestCmd.start\\(self, program, interpreter, arguments,
+ File "<stdin>", line \\d+, in raise_exception
TypeError: forced TypeError
""" % re.escape(repr(sys.executable)))
expect_stderr = re.compile(expect_stderr, re.M)
@@ -2172,7 +2173,7 @@ class run_TestCase(TestCommonTestCase):
tc.run()
""")
- self.SIGTERM = signal.SIGTERM
+ self.SIGTERM = int(signal.SIGTERM)
# Script returns the signal value as a negative number.
expect_stdout = lstrip("""\
@@ -2338,15 +2339,13 @@ class variables_TestCase(TestCommonTestCase):
'dll_suffix',
]
- script = "from __future__ import print_function\n" + \
- "import TestCommon\n" + \
+ script = "import TestCommon\n" + \
'\n'.join([ "print(TestCommon.%s)\n" % v for v in variables ])
run_env.run(program=sys.executable, stdin=script)
stderr = run_env.stderr()
assert stderr == "", stderr
- script = "from __future__ import print_function\n" + \
- "from TestCommon import *\n" + \
+ script = "from TestCommon import *\n" + \
'\n'.join([ "print(%s)" % v for v in variables ])
run_env.run(program=sys.executable, stdin=script)
stderr = run_env.stderr()
diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py
index a633617..8800c1b 100644
--- a/testing/framework/TestSCons.py
+++ b/testing/framework/TestSCons.py
@@ -13,7 +13,6 @@ attributes defined in this subclass.
"""
# __COPYRIGHT__
-from __future__ import division, print_function
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
@@ -23,6 +22,7 @@ import shutil
import sys
import time
import subprocess
+from collections import namedtuple
from TestCommon import *
from TestCommon import __all__
@@ -49,23 +49,23 @@ if SConsVersion == '__' + 'VERSION' + '__':
SConsVersion = default_version
__all__.extend([
- 'TestSCons',
- 'machine',
- 'python',
- '_exe',
- '_obj',
- '_shobj',
- 'shobj_',
- 'lib_',
- '_lib',
- 'dll_',
- '_dll'
- ])
+ 'TestSCons',
+ 'machine',
+ 'python',
+ '_exe',
+ '_obj',
+ '_shobj',
+ 'shobj_',
+ 'lib_',
+ '_lib',
+ 'dll_',
+ '_dll'
+])
machine_map = {
- 'i686' : 'i386',
- 'i586' : 'i386',
- 'i486' : 'i386',
+ 'i686': 'i386',
+ 'i586': 'i386',
+ 'i486': 'i386',
}
try:
@@ -88,7 +88,6 @@ lib_ = lib_prefix
_dll = dll_suffix
dll_ = dll_prefix
-
if sys.platform == 'cygwin':
# On Cygwin, os.path.normcase() lies, so just report back the
# fact that the underlying Win32 OS is case-insensitive.
@@ -98,16 +97,17 @@ else:
def case_sensitive_suffixes(s1, s2):
return (os.path.normcase(s1) != os.path.normcase(s2))
-
file_expr = r"""File "[^"]*", line \d+, in [^\n]+
"""
+
# re.escape escapes too much.
def re_escape(str):
- for c in '\\.[]()*+?': # Not an exhaustive list.
+ for c in '\\.[]()*+?': # Not an exhaustive list.
str = str.replace(c, '\\' + c)
return str
+
#
# Helper functions that we use as a replacement to the default re.match
# when searching for special strings in stdout/stderr.
@@ -122,6 +122,7 @@ def search_re(out, l):
return None
+
def search_re_in_list(out, l):
""" Search the regular expression 'l' in each line of
the given string list 'out' and return the line's index
@@ -134,21 +135,26 @@ def search_re_in_list(out, l):
return None
+
#
# Helpers for handling Python version numbers
#
def python_version_string():
return sys.version.split()[0]
+
def python_minor_version_string():
return sys.version[:3]
+
def unsupported_python_version(version=sys.version_info):
return version < python_version_unsupported
+
def deprecated_python_version(version=sys.version_info):
return version < python_version_deprecated
+
if deprecated_python_version():
msg = r"""
scons: warning: Support for pre-2.7.0 Python version (%s) is deprecated.
@@ -187,6 +193,7 @@ def initialize_sconsflags(ignore_python_version):
os.environ['SCONSFLAGS'] = ' '.join(sconsflags)
return save_sconsflags
+
def restore_sconsflags(sconsflags):
if sconsflags is None:
del os.environ['SCONSFLAGS']
@@ -194,6 +201,34 @@ def restore_sconsflags(sconsflags):
os.environ['SCONSFLAGS'] = sconsflags
+# Helpers for Configure()'s config.log processing
+ConfigCheckInfo = namedtuple('ConfigCheckInfo',
+ ['check_string', 'result', 'cached', 'temp_filename'])
+# check_string: the string output to for this checker
+# results : The expected results for each check
+# cached : If the corresponding check is expected to be cached
+# temp_filename : The name of the generated tempfile for this check
+
+
+class NoMatch(Exception):
+ """
+ Exception for matchPart to indicate there was no match found in the passed logfile
+ """
+ def __init__(self, p):
+ self.pos = p
+
+
+def match_part_of_configlog(log, logfile, lastEnd, NoMatch=NoMatch):
+ """
+ Match part of the logfile
+ """
+ # print("Match:\n%s\n==============\n%s" % (log , logfile[lastEnd:]))
+ m = re.match(log, logfile[lastEnd:])
+ if not m:
+ raise NoMatch(lastEnd)
+ return m.end() + lastEnd
+
+
class TestSCons(TestCommon):
"""Class for testing SCons.
@@ -247,7 +282,7 @@ class TestSCons(TestCommon):
elif not self.external and not os.path.isabs(kw['program']):
kw['program'] = os.path.join(self.orig_cwd, kw['program'])
if 'interpreter' not in kw and not os.environ.get('SCONS_EXEC'):
- kw['interpreter'] = [python,]
+ kw['interpreter'] = [python, ]
if sys.version_info[0] < 3:
kw['interpreter'].append('-tt')
if 'match' not in kw:
@@ -365,12 +400,12 @@ class TestSCons(TestCommon):
return None
- def wrap_stdout(self, build_str = "", read_str = "", error = 0, cleaning = 0):
+ def wrap_stdout(self, build_str="", read_str="", error=0, cleaning=0):
"""Wraps standard output string(s) in the normal
"Reading ... done" and "Building ... done" strings
"""
- cap,lc = [ ('Build','build'),
- ('Clean','clean') ][cleaning]
+ cap, lc = [('Build', 'build'),
+ ('Clean', 'clean')][cleaning]
if error:
term = "scons: %sing terminated because of errors.\n" % lc
else:
@@ -393,30 +428,30 @@ class TestSCons(TestCommon):
finally:
restore_sconsflags(sconsflags)
-# Modifying the options should work and ought to be simpler, but this
-# class is used for more than just running 'scons' itself. If there's
-# an automated way of determining whether it's running 'scons' or
-# something else, this code should be resurected.
-# options = kw.get('options')
-# if options:
-# options = [options]
-# else:
-# options = []
-# if self.ignore_python_version and deprecated_python_version():
-# options.append('--warn=no-python-version')
-# # Provide a way to suppress or provide alternate flags for
-# # TestSCons purposes by setting TESTSCONS_SCONSFLAGS.
-# # (The intended use case is to set it to null when running
-# # timing tests of earlier versions of SCons which don't
-# # support the --warn=no-visual-c-missing warning.)
-# visual_c = os.environ.get('TESTSCONS_SCONSFLAGS',
-# '--warn=no-visual-c-missing')
-# if visual_c:
-# options.append(visual_c)
-# kw['options'] = ' '.join(options)
-# TestCommon.run(self, *args, **kw)
-
- def up_to_date(self, arguments = '.', read_str = "", **kw):
+ # Modifying the options should work and ought to be simpler, but this
+ # class is used for more than just running 'scons' itself. If there's
+ # an automated way of determining whether it's running 'scons' or
+ # something else, this code should be resurected.
+ # options = kw.get('options')
+ # if options:
+ # options = [options]
+ # else:
+ # options = []
+ # if self.ignore_python_version and deprecated_python_version():
+ # options.append('--warn=no-python-version')
+ # # Provide a way to suppress or provide alternate flags for
+ # # TestSCons purposes by setting TESTSCONS_SCONSFLAGS.
+ # # (The intended use case is to set it to null when running
+ # # timing tests of earlier versions of SCons which don't
+ # # support the --warn=no-visual-c-missing warning.)
+ # visual_c = os.environ.get('TESTSCONS_SCONSFLAGS',
+ # '--warn=no-visual-c-missing')
+ # if visual_c:
+ # options.append(visual_c)
+ # kw['options'] = ' '.join(options)
+ # TestCommon.run(self, *args, **kw)
+
+ 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.
@@ -425,14 +460,14 @@ class TestSCons(TestCommon):
for arg in arguments.split():
s = s + "scons: `%s' is up to date.\n" % arg
kw['arguments'] = arguments
- stdout = self.wrap_stdout(read_str = read_str, build_str = s)
+ stdout = self.wrap_stdout(read_str=read_str, build_str=s)
# Append '.*' so that timing output that comes after the
# up-to-date output is okay.
kw['stdout'] = re.escape(stdout) + '.*'
kw['match'] = self.match_re_dotall
self.run(**kw)
- def not_up_to_date(self, arguments = '.', **kw):
+ def not_up_to_date(self, arguments='.', **kw):
"""Asserts that none 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.
@@ -440,7 +475,7 @@ class TestSCons(TestCommon):
s = ""
for arg in arguments.split():
s = s + "(?!scons: `%s' is up to date.)" % re.escape(arg)
- s = '('+s+'[^\n]*\n)*'
+ s = '(' + s + '[^\n]*\n)*'
kw['arguments'] = arguments
stdout = re.escape(self.wrap_stdout(build_str='ARGUMENTSGOHERE'))
kw['stdout'] = stdout.replace('ARGUMENTSGOHERE', s)
@@ -495,22 +530,22 @@ class TestSCons(TestCommon):
# no option, should get one of nothing, warning, or error
warning = self.deprecated_wrap(msg)
- self.run(arguments = '.', stderr = None)
+ self.run(arguments='.', stderr=None)
stderr = self.stderr()
if stderr:
# most common case done first
if match_re_dotall(stderr, warning):
- # expected output
- pass
+ # expected output
+ pass
elif match_re_dotall(stderr, err_out()):
- # now a fatal error; skip the rest of the tests
- self.pass_test()
+ # now a fatal error; skip the rest of the tests
+ self.pass_test()
else:
- # test failed; have to do this by hand...
- print(self.banner('STDOUT '))
- print(self.stdout())
- print(self.diff(warning, stderr, 'STDERR '))
- self.fail_test()
+ # test failed; have to do this by hand...
+ print(self.banner('STDOUT '))
+ print(self.stdout())
+ print(self.diff(warning, stderr, 'STDERR '))
+ self.fail_test()
return warning
@@ -529,14 +564,14 @@ class TestSCons(TestCommon):
def RunPair(option, expected):
# run the same test with the option on the command line and
# then with the option passed via SetOption().
- self.run(options = '--warn=' + option,
- arguments = '.',
- stderr = expected,
- match = match_re_dotall)
- self.run(options = 'WARN=' + option,
- arguments = '.',
- stderr = expected,
- match = match_re_dotall)
+ self.run(options='--warn=' + option,
+ arguments='.',
+ stderr=expected,
+ match=match_re_dotall)
+ self.run(options='WARN=' + option,
+ arguments='.',
+ stderr=expected,
+ match=match_re_dotall)
# all warnings off, should get no output
RunPair('no-deprecated', '')
@@ -557,8 +592,8 @@ class TestSCons(TestCommon):
return "Actual did not match expect at char %d:\n" \
" Expect: %s\n" \
" Actual: %s\n" \
- % (i, repr(expect[i-prelen:i+postlen]),
- repr(actual[i-prelen:i+postlen]))
+ % (i, repr(expect[i - prelen:i + postlen]),
+ repr(actual[i - prelen:i + postlen]))
i = i + 1
return "Actual matched the expected output???"
@@ -579,14 +614,14 @@ class TestSCons(TestCommon):
# traceback seems to be stable, so let's just format
# an appropriate string
#
- #exec('import traceback; x = traceback.format_stack()[-1]')
+ # exec('import traceback; x = traceback.format_stack()[-1]')
# import traceback
# x = traceback.format_stack()
# x = # XXX: .lstrip()
# x = x.replace('<string>', file)
# x = x.replace('line 1,', 'line %s,' % line)
# x="\n".join(x)
- x='File "%s", line %s, in <module>\n'%(file,line)
+ x = 'File "%s", line %s, in <module>\n' % (file, line)
return x
def normalize_ps(self, s):
@@ -613,13 +648,13 @@ class TestSCons(TestCommon):
def normalize_pdf(self, s):
s = self.to_bytes_re_sub(r'/(Creation|Mod)Date \(D:[^)]*\)',
- r'/\1Date (D:XXXX)', s)
+ r'/\1Date (D:XXXX)', s)
s = self.to_bytes_re_sub(r'/ID \[<[0-9a-fA-F]*> <[0-9a-fA-F]*>\]',
- r'/ID [<XXXX> <XXXX>]', s)
+ r'/ID [<XXXX> <XXXX>]', s)
s = self.to_bytes_re_sub(r'/(BaseFont|FontName) /[A-Z]{6}',
- r'/\1 /XXXXXX', s)
+ r'/\1 /XXXXXX', s)
s = self.to_bytes_re_sub(r'/Length \d+ *\n/Filter /FlateDecode\n',
- r'/Length XXXX\n/Filter /FlateDecode\n', s)
+ r'/Length XXXX\n/Filter /FlateDecode\n', s)
try:
import zlib
@@ -643,11 +678,11 @@ class TestSCons(TestCommon):
r.append(s[x:b])
d = zlib.decompress(s[b:e])
d = self.to_bytes_re_sub(r'%%CreationDate: [^\n]*\n',
- r'%%CreationDate: 1970 Jan 01 00:00:00\n', d)
+ r'%%CreationDate: 1970 Jan 01 00:00:00\n', d)
d = self.to_bytes_re_sub(r'%DVIPSSource: TeX output \d\d\d\d\.\d\d\.\d\d:\d\d\d\d',
- r'%DVIPSSource: TeX output 1970.01.01:0000', d)
+ r'%DVIPSSource: TeX output 1970.01.01:0000', d)
d = self.to_bytes_re_sub(r'/(BaseFont|FontName) /[A-Z]{6}',
- r'/\1 /XXXXXX', d)
+ r'/\1 /XXXXXX', d)
r.append(d)
x = e
r.append(s[x:])
@@ -655,14 +690,14 @@ class TestSCons(TestCommon):
return s
- def paths(self,patterns):
+ def paths(self, patterns):
import glob
result = []
for p in patterns:
result.extend(sorted(glob.glob(p)))
return result
- def unlink_sconsignfile(self,name='.sconsign.dblite'):
+ def unlink_sconsignfile(self, name='.sconsign.dblite'):
"""
Delete sconsign file.
Note on python it seems to append .p3 to the file name so we take care of that
@@ -728,7 +763,7 @@ class TestSCons(TestCommon):
return None
- def java_where_includes(self,version=None):
+ def java_where_includes(self, version=None):
"""
Find include path needed for compiling java jni code.
@@ -740,30 +775,30 @@ class TestSCons(TestCommon):
result = []
if sys.platform[:6] == 'darwin':
java_home = self.java_where_java_home(version)
- jni_path = os.path.join(java_home,'include','jni.h')
+ jni_path = os.path.join(java_home, 'include', 'jni.h')
if os.path.exists(jni_path):
result.append(os.path.dirname(jni_path))
if not version:
- version=''
+ version = ''
jni_dirs = ['/System/Library/Frameworks/JavaVM.framework/Headers/jni.h',
'/usr/lib/jvm/default-java/include/jni.h',
'/usr/lib/jvm/java-*-oracle/include/jni.h']
else:
- jni_dirs = ['/System/Library/Frameworks/JavaVM.framework/Versions/%s*/Headers/jni.h'%version]
- jni_dirs.extend(['/usr/lib/jvm/java-*-sun-%s*/include/jni.h'%version,
- '/usr/lib/jvm/java-%s*-openjdk*/include/jni.h'%version,
- '/usr/java/jdk%s*/include/jni.h'%version])
+ jni_dirs = ['/System/Library/Frameworks/JavaVM.framework/Versions/%s*/Headers/jni.h' % version]
+ jni_dirs.extend(['/usr/lib/jvm/java-*-sun-%s*/include/jni.h' % version,
+ '/usr/lib/jvm/java-%s*-openjdk*/include/jni.h' % version,
+ '/usr/java/jdk%s*/include/jni.h' % version])
dirs = self.paths(jni_dirs)
if not dirs:
return None
- d=os.path.dirname(self.paths(jni_dirs)[0])
+ d = os.path.dirname(self.paths(jni_dirs)[0])
result.append(d)
if sys.platform == 'win32':
- result.append(os.path.join(d,'win32'))
+ result.append(os.path.join(d, 'win32'))
elif sys.platform.startswith('linux'):
- result.append(os.path.join(d,'linux'))
+ result.append(os.path.join(d, 'linux'))
return result
def java_where_java_home(self, version=None):
@@ -788,14 +823,14 @@ class TestSCons(TestCommon):
return java_home
else:
homes = ['/System/Library/Frameworks/JavaVM.framework/Home',
- # osx 10.10
+ # osx 10.10
'/System/Library/Frameworks/JavaVM.framework/Versions/Current/Home']
for home in homes:
if os.path.exists(home):
return home
else:
- if java_home.find('jdk%s'%version) != -1:
+ if java_home.find('jdk%s' % version) != -1:
return java_home
else:
home = '/System/Library/Frameworks/JavaVM.framework/Versions/%s/Home' % version
@@ -804,7 +839,7 @@ class TestSCons(TestCommon):
home = '/System/Library/Frameworks/JavaVM.framework/Versions/Current/'
else:
jar = self.java_where_jar(version)
- home = os.path.normpath('%s/..'%jar)
+ home = os.path.normpath('%s/..' % jar)
if os.path.isdir(home):
return home
print("Could not determine JAVA_HOME: %s is not a directory" % home)
@@ -873,8 +908,8 @@ class TestSCons(TestCommon):
elif sys.platform == "darwin":
self.java_mac_check(where_javac, 'javac')
- self.run(program = where_javac,
- arguments = '-version',
+ self.run(program=where_javac,
+ arguments='-version',
stderr=None,
status=None)
# Note recent versions output version info to stdout instead of stderr
@@ -893,7 +928,7 @@ class TestSCons(TestCommon):
version = m.group(1)
self.javac_is_gcj = False
elif self.stderr().find('gcj') != -1:
- version='1.2'
+ version = '1.2'
self.javac_is_gcj = True
else:
version = None
@@ -936,7 +971,6 @@ class TestSCons(TestCommon):
self.skip_test("Could not find Java rmic, skipping non-simulated test(s).\n")
return where_rmic
-
def java_get_class_files(self, dir):
result = []
for dirpath, dirnames, filenames in os.walk(dir):
@@ -945,7 +979,6 @@ class TestSCons(TestCommon):
result.append(os.path.join(dirpath, fname))
return sorted(result)
-
def Qt_dummy_installation(self, dir='qt'):
# create a dummy qt installation
@@ -1016,7 +1049,7 @@ with open(outfile, 'w') as ofp, open(source, 'r') as ifp:
else:
ofp.write('#include "my_qobject.h"\\n' + ifp.read() + " Q_OBJECT \\n")
sys.exit(0)
-""" )
+""")
self.write([dir, 'include', 'my_qobject.h'], r"""
#define Q_OBJECT ;
@@ -1040,10 +1073,10 @@ else:
env.SharedLibrary('myqt', 'my_qobject.cpp')
""")
- self.run(chdir = self.workpath(dir, 'lib'),
- arguments = '.',
- stderr = noisy_ar,
- match = self.match_re_dotall)
+ self.run(chdir=self.workpath(dir, 'lib'),
+ arguments='.',
+ stderr=noisy_ar,
+ match=self.match_re_dotall)
self.QT = self.workpath(dir)
self.QT_LIB = 'myqt'
@@ -1083,11 +1116,10 @@ Export("env dup")
SConscript(sconscript)
""" % (self.QT, self.QT_LIB, self.QT_MOC, self.QT_UIC))
-
- NCR = 0 # non-cached rebuild
- CR = 1 # cached rebuild (up to date)
- NCF = 2 # non-cached build failure
- CF = 3 # cached build failure
+ NCR = 0 # non-cached rebuild
+ CR = 1 # cached rebuild (up to date)
+ NCF = 2 # non-cached build failure
+ CF = 3 # cached build failure
if sys.platform == 'win32':
Configure_lib = 'msvcrt'
@@ -1095,7 +1127,7 @@ SConscript(sconscript)
Configure_lib = 'm'
# to use cygwin compilers on cmd.exe -> uncomment following line
- #Configure_lib = 'm'
+ # Configure_lib = 'm'
def coverage_run(self):
""" Check if the the tests are being run under coverage.
@@ -1125,6 +1157,145 @@ SConscript(sconscript)
except:
pass
+ def checkConfigureLogAndStdout(self, checks,
+ logfile='config.log',
+ sconf_dir='.sconf_temp',
+ sconstruct="SConstruct",
+ doCheckLog=True, doCheckStdout=True):
+ """
+ Used to verify the expected output from using Configure()
+ via the contents of one or both of stdout or config.log file.
+ The checks, results, cached parameters all are zipped together
+ for use in comparing results.
+
+ TODO: Perhaps a better API makes sense?
+
+ Parameters
+ ----------
+ checks : list of ConfigCheckInfo tuples which specify
+ logfile : Name of the config log
+ sconf_dir : Name of the sconf dir
+ sconstruct : SConstruct file name
+ doCheckLog : check specified log file, defaults to true
+ doCheckStdout : Check stdout, defaults to true
+
+ Returns
+ -------
+
+ """
+
+
+ try:
+ ls = '\n'
+ nols = '([^\n])'
+ lastEnd = 0
+
+ # Read the whole logfile
+ logfile = self.read(self.workpath(logfile), mode='r')
+
+ # Some debug code to keep around..
+ # sys.stderr.write("LOGFILE[%s]:%s"%(type(logfile),logfile))
+
+ if (doCheckLog and
+ logfile.find("scons: warning: The stored build information has an unexpected class.") >= 0):
+ self.fail_test()
+
+ log = r'file\ \S*%s\,line \d+:' % re.escape(sconstruct) + ls
+ if doCheckLog:
+ lastEnd = match_part_of_configlog(log, logfile, lastEnd)
+
+ log = "\t" + re.escape("Configure(confdir = %s)" % sconf_dir) + ls
+ if doCheckLog:
+ lastEnd = match_part_of_configlog(log, logfile, lastEnd)
+
+ rdstr = ""
+
+ for check_info in checks:
+ log = re.escape("scons: Configure: " + check_info.check_string) + ls
+
+ if doCheckLog:
+ lastEnd = match_part_of_configlog(log, logfile, lastEnd)
+
+ log = ""
+ result_cached = 1
+ for bld_desc in check_info.cached: # each TryXXX
+ for ext, flag in bld_desc: # each file in TryBuild
+ conf_filename = re.escape(check_info.temp_filename%ext)
+
+ if flag == self.NCR:
+ # NCR = Non Cached Rebuild
+ # rebuild will pass
+ if ext in ['.c', '.cpp']:
+ log = log + conf_filename + re.escape(" <-") + ls
+ log = log + r"( \|" + nols + "*" + ls + ")+?"
+ else:
+ log = log + "(" + nols + "*" + ls + ")*?"
+ result_cached = 0
+ if flag == self.CR:
+ # CR = cached rebuild (up to date)s
+ # up to date
+ log = log + \
+ re.escape("scons: Configure: \"") + \
+ conf_filename + \
+ re.escape("\" is up to date.") + ls
+ log = log + re.escape("scons: Configure: The original builder "
+ "output was:") + ls
+ log = log + r"( \|.*" + ls + ")+"
+ if flag == self.NCF:
+ # non-cached rebuild failure
+ log = log + "(" + nols + "*" + ls + ")*?"
+ result_cached = 0
+ if flag == self.CF:
+ # cached rebuild failure
+ log = log + \
+ re.escape("scons: Configure: Building \"") + \
+ conf_filename + \
+ re.escape("\" failed in a previous run and all its sources are up to date.") + ls
+ log = log + re.escape("scons: Configure: The original builder output was:") + ls
+ log = log + r"( \|.*" + ls + ")+"
+ if result_cached:
+ result = "(cached) " + check_info.result
+ else:
+ result = check_info.result
+ rdstr = rdstr + re.escape(check_info.check_string) + re.escape(result) + "\n"
+
+ log = log + re.escape("scons: Configure: " + result) + ls + ls
+
+ if doCheckLog:
+ lastEnd = match_part_of_configlog(log, logfile, lastEnd)
+
+ log = ""
+ if doCheckLog:
+ lastEnd = match_part_of_configlog(ls, logfile, lastEnd)
+
+ if doCheckLog and lastEnd != len(logfile):
+ raise NoMatch(lastEnd)
+
+ except NoMatch as m:
+ print("Cannot match log file against log regexp.")
+ print("log file: ")
+ print("------------------------------------------------------")
+ print(logfile[m.pos:])
+ print("------------------------------------------------------")
+ print("log regexp: ")
+ print("------------------------------------------------------")
+ print(log)
+ print("------------------------------------------------------")
+ self.fail_test()
+
+ if doCheckStdout:
+ exp_stdout = self.wrap_stdout(".*", rdstr)
+ if not self.match_re_dotall(self.stdout(), exp_stdout):
+ print("Unexpected stdout: ")
+ print("-----------------------------------------------------")
+ print(repr(self.stdout()))
+ print("-----------------------------------------------------")
+ print(repr(exp_stdout))
+ print("-----------------------------------------------------")
+ self.fail_test()
+
+
+
def checkLogAndStdout(self, checks, results, cached,
logfile, sconf_dir, sconstruct,
doCheckLog=True, doCheckStdout=True):
@@ -1158,42 +1329,8 @@ SConscript(sconscript)
-------
"""
-
- class NoMatch(Exception):
- def __init__(self, p):
- self.pos = p
-
- def matchPart(log, logfile, lastEnd, NoMatch=NoMatch):
- """
- Match part of the logfile
- """
- m = re.match(log, logfile[lastEnd:])
- if not m:
- raise NoMatch(lastEnd)
- return m.end() + lastEnd
-
try:
- # Build regexp for a character which is not
- # a linesep, and in the case of CR/LF
- # build it with both CR and CR/LF
- # TODO: Not sure why this is a good idea. A static string
- # could do the same since we only have two variations
- # to do with?
- # ls = os.linesep
- # nols = "("
- # for i in range(len(ls)):
- # nols = nols + "("
- # for j in range(i):
- # nols = nols + ls[j]
- # nols = nols + "[^" + ls[i] + "])"
- # if i < len(ls)-1:
- # nols = nols + "|"
- # nols = nols + ")"
- #
- # Replaced above logic with \n as we're reading the file
- # using non-binary read. Python will translate \r\n -> \n
- # For us.
ls = '\n'
nols = '([^\n])'
lastEnd = 0
@@ -1205,7 +1342,7 @@ SConscript(sconscript)
# sys.stderr.write("LOGFILE[%s]:%s"%(type(logfile),logfile))
if (doCheckLog and
- logfile.find("scons: warning: The stored build information has an unexpected class.") >= 0):
+ logfile.find("scons: warning: The stored build information has an unexpected class.") >= 0):
self.fail_test()
sconf_dir = sconf_dir
@@ -1213,67 +1350,90 @@ SConscript(sconscript)
log = r'file\ \S*%s\,line \d+:' % re.escape(sconstruct) + ls
if doCheckLog:
- lastEnd = matchPart(log, logfile, lastEnd)
+ lastEnd = match_part_of_configlog(log, logfile, lastEnd)
log = "\t" + re.escape("Configure(confdir = %s)" % sconf_dir) + ls
if doCheckLog:
- lastEnd = matchPart(log, logfile, lastEnd)
+ lastEnd = match_part_of_configlog(log, logfile, lastEnd)
rdstr = ""
+
cnt = 0
- for check,result,cache_desc in zip(checks, results, cached):
- log = re.escape("scons: Configure: " + check) + ls
+ for check, result, cache_desc in zip(checks, results, cached):
+ log = re.escape("scons: Configure: " + check) + ls
if doCheckLog:
- lastEnd = matchPart(log, logfile, lastEnd)
+ lastEnd = match_part_of_configlog(log, logfile, lastEnd)
log = ""
result_cached = 1
- for bld_desc in cache_desc: # each TryXXX
- for ext, flag in bld_desc: # each file in TryBuild
- file = os.path.join(sconf_dir,"conftest_%d%s" % (cnt, ext))
+ for bld_desc in cache_desc: # each TryXXX
+ for ext, flag in bld_desc: # each file in TryBuild
+ if ext in ['.c', '.cpp']:
+ conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\
+ r'_[a-z0-9]{32}_\d+%s' % re.escape(ext)
+ elif ext == '':
+ conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\
+ r'_[a-z0-9]{32}(_\d+_[a-z0-9]{32})?'
+
+ else:
+ # We allow the second hash group to be optional because
+ # TryLink() will create a c file, then compile to obj, then link that
+ # The intermediate object file will not get the action hash
+ # But TryCompile()'s where the product is the .o will get the
+ # action hash. Rather than add a ton of complications to this logic
+ # this shortcut should be sufficient.
+ # TODO: perhaps revisit and/or fix file naming for intermediate files in
+ # Configure context logic
+ conf_filename = re.escape(os.path.join(sconf_dir, "conftest")) +\
+ r'_[a-z0-9]{32}_\d+(_[a-z0-9]{32})?%s' % re.escape(ext)
+
if flag == self.NCR:
# NCR = Non Cached Rebuild
# rebuild will pass
if ext in ['.c', '.cpp']:
- log=log + re.escape(file + " <-") + ls
- log=log + r"( \|" + nols + "*" + ls + ")+?"
+ log = log + conf_filename + re.escape(" <-") + ls
+ log = log + r"( \|" + nols + "*" + ls + ")+?"
else:
- log=log + "(" + nols + "*" + ls +")*?"
+ log = log + "(" + nols + "*" + ls + ")*?"
result_cached = 0
if flag == self.CR:
# CR = cached rebuild (up to date)s
# up to date
- log=log + \
- re.escape("scons: Configure: \"%s\" is up to date."
- % file) + ls
- log=log+re.escape("scons: Configure: The original builder "
- "output was:") + ls
- log=log+r"( \|.*"+ls+")+"
+ log = log + \
+ re.escape("scons: Configure: \"") + \
+ conf_filename + \
+ re.escape("\" is up to date.") + ls
+ log = log + re.escape("scons: Configure: The original builder "
+ "output was:") + ls
+ log = log + r"( \|.*" + ls + ")+"
if flag == self.NCF:
# non-cached rebuild failure
- log=log + "(" + nols + "*" + ls + ")*?"
+ log = log + "(" + nols + "*" + ls + ")*?"
result_cached = 0
if flag == self.CF:
# cached rebuild failure
- log=log + \
- re.escape("scons: Configure: Building \"%s\" failed "
- "in a previous run and all its sources are"
- " up to date." % file) + ls
- log=log+re.escape("scons: Configure: The original builder "
- "output was:") + ls
- log=log+r"( \|.*"+ls+")+"
- cnt = cnt + 1
+ log = log + \
+ re.escape("scons: Configure: Building \"") + \
+ conf_filename + \
+ re.escape("\" failed in a previous run and all its sources are up to date.") + ls
+ log = log + re.escape("scons: Configure: The original builder output was:") + ls
+ log = log + r"( \|.*" + ls + ")+"
+ # cnt = cnt + 1
if result_cached:
result = "(cached) " + result
+
rdstr = rdstr + re.escape(check) + re.escape(result) + "\n"
- log=log + re.escape("scons: Configure: " + result) + ls + ls
+
+ log = log + re.escape("scons: Configure: " + result) + ls + ls
if doCheckLog:
- lastEnd = matchPart(log, logfile, lastEnd)
+ lastEnd = match_part_of_configlog(log, logfile, lastEnd)
log = ""
- if doCheckLog: lastEnd = matchPart(ls, logfile, lastEnd)
+ if doCheckLog:
+ lastEnd = match_part_of_configlog(ls, logfile, lastEnd)
+
if doCheckLog and lastEnd != len(logfile):
raise NoMatch(lastEnd)
@@ -1293,9 +1453,9 @@ SConscript(sconscript)
exp_stdout = self.wrap_stdout(".*", rdstr)
if not self.match_re_dotall(self.stdout(), exp_stdout):
print("Unexpected stdout: ")
- print("-----------------------------------------------------")
+ print("----Actual-------------------------------------------")
print(repr(self.stdout()))
- print("-----------------------------------------------------")
+ print("----Expected-----------------------------------------")
print(repr(exp_stdout))
print("-----------------------------------------------------")
self.fail_test()
@@ -1435,7 +1595,7 @@ else:
files with .C and .c as different files or not
in which case they are instructed to use .cpp instead of .C
"""
- if not case_sensitive_suffixes('.c','.C'):
+ if not case_sensitive_suffixes('.c', '.C'):
alt_cpp_suffix = '.cpp'
else:
alt_cpp_suffix = '.C'
@@ -1457,6 +1617,7 @@ class Stat:
self.expression = re.compile(expression)
self.convert = convert
+
StatList = [
Stat('memory-initial', 'kbytes',
r'Memory before reading SConscript files:\s+(\d+)',
@@ -1481,6 +1642,7 @@ StatList = [
class TimeSCons(TestSCons):
"""Class for timing SCons."""
+
def __init__(self, *args, **kw):
"""
In addition to normal TestSCons.TestSCons intialization,
@@ -1563,7 +1725,7 @@ class TimeSCons(TestSCons):
fmt = "TRACE: graph=%s name=%s value=%s units=%s"
line = fmt % (graph, name, value, units)
if sort is not None:
- line = line + (' sort=%s' % sort)
+ line = line + (' sort=%s' % sort)
line = line + '\n'
sys.stdout.write(line)
sys.stdout.flush()
@@ -1585,9 +1747,9 @@ class TimeSCons(TestSCons):
else:
avg1, avg5, avg15 = fp.readline().split(" ")[:3]
fp.close()
- self.trace('load-average', 'average1', avg1, 'processes')
- self.trace('load-average', 'average5', avg5, 'processes')
- self.trace('load-average', 'average15', avg15, 'processes')
+ self.trace('load-average', 'average1', avg1, 'processes')
+ self.trace('load-average', 'average5', avg5, 'processes')
+ self.trace('load-average', 'average15', avg15, 'processes')
def collect_stats(self, input):
result = {}
@@ -1598,7 +1760,7 @@ class TimeSCons(TestSCons):
# The dict keys match the keyword= arguments
# of the trace() method above so they can be
# applied directly to that call.
- result[stat.name] = {'value':value, 'units':stat.units}
+ result[stat.name] = {'value': value, 'units': stat.units}
return result
def add_timing_options(self, kw, additional=None):
@@ -1713,8 +1875,8 @@ class TimeSCons(TestSCons):
for root, dirs, files in os.walk(source_dir):
if '.svn' in dirs:
dirs.remove('.svn')
- dirs = [ d for d in dirs if not d.startswith('TimeSCons-') ]
- files = [ f for f in files if not f.startswith('TimeSCons-') ]
+ dirs = [d for d in dirs if not d.startswith('TimeSCons-')]
+ files = [f for f in files if not f.startswith('TimeSCons-')]
for dirname in dirs:
source = os.path.join(root, dirname)
destination = source.replace(source_dir, dest_dir)
@@ -1736,7 +1898,7 @@ class TimeSCons(TestSCons):
# <file>" messages to be successful executions of the test (see
# test/AR.py for sample usage).
-noisy_ar=r'(ar: creating( archive)? \S+\n?)*'
+noisy_ar = r'(ar: creating( archive)? \S+\n?)*'
# Local Variables:
# tab-width:4
diff --git a/testing/framework/TestSCons_time.py b/testing/framework/TestSCons_time.py
index f27e0e3..6f46e26 100644
--- a/testing/framework/TestSCons_time.py
+++ b/testing/framework/TestSCons_time.py
@@ -27,7 +27,6 @@ from TestSCons import search_re, search_re_in_list
__all__.extend(['TestSCons_time',])
SConstruct = """\
-from __future__ import print_function
import os
print("SConstruct file directory:", os.getcwd())
"""
diff --git a/testing/framework/TestSConsign.py b/testing/framework/TestSConsign.py
index a48b648..665059c 100644
--- a/testing/framework/TestSConsign.py
+++ b/testing/framework/TestSConsign.py
@@ -1,5 +1,4 @@
# __COPYRIGHT__
-from __future__ import print_function
__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
diff --git a/testing/framework/test-framework.rst b/testing/framework/test-framework.rst
index 24240ac..a0fe861 100644
--- a/testing/framework/test-framework.rst
+++ b/testing/framework/test-framework.rst
@@ -308,6 +308,9 @@ in that sense: "the fixture for this test is foo", instead of writing
a whole bunch of strings to create files. Since these setups can be
reusable across multiple tests, the *fixture* terminology applies well.
+Note: fixtures must not be treated by SCons as runnable tests. To exclude
+them, see instructions in the above section named "Finding Tests".
+
Directory Fixtures
##################