diff options
570 files changed, 10751 insertions, 7089 deletions
diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..cbf7233 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,248 @@ +#version: '3.0.1.{build}' + +image: + # linux builds disabled for now + # - Ubuntu + - Visual Studio 2015 + - Visual Studio 2017 + +cache: + - downloads -> appveyor.yml + - '%LOCALAPPDATA%\pip\Cache' + - C:\ProgramData\chocolatey\bin -> appveyor.yml + - C:\ProgramData\chocolatey\lib -> appveyor.yml + +install: + ### WINDOWS ### + # add python and python user-base to path for pip installs + - cmd: "C:\\%WINPYTHON%\\python.exe --version" + - cmd: for /F "tokens=*" %%g in ('C:\\%WINPYTHON%\\python.exe -m site --user-site') do (set PYSITEDIR=%%g) + # use mingw 32 bit until #3291 is resolved + - cmd: "set PATH=C:\\%WINPYTHON%;C:\\%WINPYTHON%\\Scripts;C:\\ProgramData\\chocolatey\\bin;C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin;C:\\cygwin\\bin;%PATH%" + - cmd: "C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off pip setuptools wheel " + - cmd: "C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off pypiwin32 coverage codecov" + - cmd: set STATIC_DEPS=true & C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off lxml + # install 3rd party tools to test with + - cmd: choco install --allow-empty-checksums dmd ldc swig vswhere xsltproc winflexbison + - cmd: set + + ### LINUX ### + - sh: sudo add-apt-repository -y ppa:deadsnakes/ppa + # allow the CI to continue even if some pkg in the pkglist may not be up to date + - sh: sudo apt-get update || true + - sh: sudo apt-get -y install python$PYTHON + - sh: wget https://bootstrap.pypa.io/get-pip.py + - sh: sudo -H python$PYTHON get-pip.py + - sh: which python$PYTHON + - sh: python$PYTHON --version + - sh: export PYSITEDIR=$(python$PYTHON -m site --user-site) + - sh: python$PYTHON -m pip install --user -U --progress-bar off pip setuptools wheel + - sh: python$PYTHON -m pip install --user -U --progress-bar off coverage codecov + - sh: STATIC_DEPS=true python$PYTHON -m pip install --user -U --progress-bar off lxml + - sh: ./.travis/install.sh + - sh: printenv + +# build matrix will be number of images multiplied +# by each '-' below, split jobs into groups of 4 +# to avoid timeing out +environment: + matrix: + - WINPYTHON: "Python27" + PYTHON: "2.7" + PYVER: 27 + BUILD_JOB_NUM: 1 + COVERAGE: 1 + - WINPYTHON: "Python27" + PYTHON: "2.7" + PYVER: 27 + BUILD_JOB_NUM: 2 + COVERAGE: 1 + - WINPYTHON: "Python27" + PYTHON: "2.7" + PYVER: 27 + BUILD_JOB_NUM: 3 + COVERAGE: 1 + - WINPYTHON: "Python27" + PYTHON: "2.7" + PYVER: 27 + BUILD_JOB_NUM: 4 + COVERAGE: 1 + + - WINPYTHON: "Python36" + PYTHON: "3.6" + PYVER: 36 + BUILD_JOB_NUM: 1 + COVERAGE: 1 + - WINPYTHON: "Python36" + PYTHON: "3.6" + PYVER: 36 + BUILD_JOB_NUM: 2 + COVERAGE: 1 + - WINPYTHON: "Python36" + PYTHON: "3.6" + PYVER: 36 + BUILD_JOB_NUM: 3 + COVERAGE: 1 + - WINPYTHON: "Python36" + PYTHON: "3.6" + PYVER: 36 + BUILD_JOB_NUM: 4 + COVERAGE: 1 + + - WINPYTHON: "Python35" + PYTHON: "3.5" + PYVER: 35 + BUILD_JOB_NUM: 1 + COVERAGE: 0 + - WINPYTHON: "Python35" + PYTHON: "3.5" + PYVER: 35 + BUILD_JOB_NUM: 2 + COVERAGE: 0 + - WINPYTHON: "Python35" + PYTHON: "3.5" + PYVER: 35 + BUILD_JOB_NUM: 3 + COVERAGE: 0 + - WINPYTHON: "Python35" + PYTHON: "3.5" + PYVER: 35 + BUILD_JOB_NUM: 4 + COVERAGE: 0 + + - WINPYTHON: "Python37" + PYTHON: "3.7" + PYVER: 37 + BUILD_JOB_NUM: 1 + COVERAGE: 0 + - WINPYTHON: "Python37" + PYTHON: "3.7" + PYVER: 37 + BUILD_JOB_NUM: 2 + COVERAGE: 0 + - WINPYTHON: "Python37" + PYTHON: "3.7" + PYVER: 37 + BUILD_JOB_NUM: 3 + COVERAGE: 0 + - WINPYTHON: "Python37" + PYTHON: "3.7" + PYVER: 37 + BUILD_JOB_NUM: 4 + COVERAGE: 0 + +# remove sets of build jobs based on critia below +# to fine tune the number and platforms tested +matrix: + exclude: + # test python 3.5, 3.6 on Visual Studio 2015 image + - image: Visual Studio 2015 + WINPYTHON: "Python37" + - image: Visual Studio 2015 + WINPYTHON: "Python27" + + # test python 2.7, 3.7 on Visual Studio 2015 image + - image: Visual Studio 2017 + WINPYTHON: "Python35" + - image: Visual Studio 2017 + WINPYTHON: "Python36" + + # test python 3.7 on Ubuntu + - image: Ubuntu + WINPYTHON: "Python27" + - image: Ubuntu + WINPYTHON: "Python35" + - image: Ubuntu + WINPYTHON: "Python36" + +# remove some binaries we dont to be found +before_build: + - ps: | + if ($isWindows) + { + dir "C:\Program Files\Git\usr\bin\x*.exe" + if (Test-Path "C:\Program Files\Git\usr\bin\xsltproc.EXE" ) { + Remove-Item "C:\Program Files\Git\usr\bin\xsltproc.EXE" -ErrorAction Ignore + } + dir "C:\Program Files\Git\usr\bin\x*.exe" + } + +build: off + +build_script: + # get all tests into a list + - cmd: "C:\\%WINPYTHON%\\python.exe runtest.py -l -a > all_tests.txt" + - sh: python$PYTHON runtest.py -l -a > all_tests.txt + + # setup coverage by creating the coverage config file, and adding coverage + # to the usercustomize so that all python processes start with coverage + - ps: | + if ($env:COVERAGE -eq 1){ + $env:COVERAGE_PROCESS_START = "$($env:APPVEYOR_BUILD_FOLDER)/.coveragerc"; + $env:PYTHONNOUSERSITE = ""; + New-Item -ItemType Directory -Force -Path "$($env:PYSITEDIR)"; + $env:COVERAGE_FILE = "$($env:APPVEYOR_BUILD_FOLDER)/.coverage"; + $usercustomizeText = "import os`r`nos.environ['COVERAGE_PROCESS_START'] = '$($env:COVERAGE_PROCESS_START)'`r`nimport coverage`r`ncoverage.process_startup()"; + $usercustomizeText|Set-Content "$($env:PYSITEDIR)/usercustomize.py"; + if ($isWindows) + { + $coveragercFile = "[run]`r`nsource = $($env:APPVEYOR_BUILD_FOLDER)/src`r`nparallel = True`r`ndisable_warnings = trace-changed`r`nomit =`r`n`t*Tests.py`r`n`tsrc\test_*`r`n`tsrc\setup.py`r`n`r`n[path]`r`nsource = $($env:APPVEYOR_BUILD_FOLDER)`r`n[report]`r`nomit =`r`n`t*Tests.py`r`n`tsrc\test_*`r`n`tsrc\setup.py`r`n`r`n" + } + else + { + $coveragercFile = "[run]`nsource = $($env:APPVEYOR_BUILD_FOLDER)/src`nparallel = True`ndisable_warnings = trace-changed`nomit =`n`t*Tests.py`n`tsrc/test_*`n`tsrc/setup.py`n`n[path]`nsource = $($env:APPVEYOR_BUILD_FOLDER)`n[report]`nomit =`n`t*Tests.py`n`tsrc/test_*`n`tsrc/setup.py`n`n" + } + $coveragercFile|Set-Content "$($env:COVERAGE_PROCESS_START)"; + } + + # setup portion of tests for this build job (1-4) + - ps: | + $TOTAL_BUILD_JOBS = 4; + $Lines = (Get-Content all_tests.txt | Measure-Object -line).Lines; + $start = ($Lines / $TOTAL_BUILD_JOBS) * ($Env:BUILD_JOB_NUM - 1); + $end = ($Lines / $TOTAL_BUILD_JOBS) * $Env:BUILD_JOB_NUM; + if ( $Env:BUILD_JOB_NUM -eq $TOTAL_BUILD_JOBS){ $end = $Lines }; + if ( $start -eq 0 ){ $start = 1 }; + get-content all_tests.txt | select -first ($end - $start) -skip ($start - 1) | Out-File -Encoding ASCII build_tests.txt; + + # exclude VS 10.0 because it hangs the testing until this is resolved: + # https://help.appveyor.com/discussions/problems/19283-visual-studio-2010-trial-license-has-expired + - ps: | + New-Item -Name exclude_list.txt -ItemType File + $workaround_image = "Visual Studio 2015" + if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq $workaround_image){ + Add-Content -Path 'exclude_list.txt' -Value 'test\MSVS\vs-10.0-exec.py' + } + + # Windows run the tests + # NOTE: running powershell from cmd on purpose because it formats the output + # correctly + - cmd: powershell -Command "& { if($env:COVERAGE -eq 1) { coverage run -p --rcfile=$($env:COVERAGE_PROCESS_START) runtest.py --exclude-list exclude_list.txt -f build_tests.txt } else { C:\\%WINPYTHON%\\python.exe runtest.py -j 2 --exclude-list exclude_list.txt -f build_tests.txt }; if($LastExitCode -eq 2 -Or $LastExitCode -eq 0) { $host.SetShouldExit(0 )} else {$host.SetShouldExit(1)}}" + + # linux run the tests + # unset JAVA_TOOL_OPTIONS because newer java prints this to stderr + - sh: | + unset JAVA_TOOL_OPTIONS + if [ "$COVERAGE" -eq "1" ]; then + coverage run -p --rcfile="$COVERAGE_PROCESS_START" runtest.py --exclude-list exclude_list.txt -f build_tests.txt || if [[ $? == 2 ]]; then true; else false; fi; + else + python$PYTHON runtest.py -j 2 --exclude-list exclude_list.txt -f build_tests.txt || if [[ $? == 2 ]]; then true; else false; fi; + fi + +# run converage even if there was a test failure +on_finish: + - ps: | + if ($env:COVERAGE -eq 1) + { + & coverage combine + & coverage report + & coverage xml -o coverage_xml.xml + } + # running codecov in powershell causes an error so running in platform + # shells + - cmd: if %COVERAGE% equ 1 codecov -X gcov --file coverage_xml.xml + - sh: if [ $COVERAGE -eq 1 ]; then codecov -X gcov --file coverage_xml.xml; fi + # not using coveralls, so leaving it commented out in case we switch back + #- cmd: "C:\\%WINPYTHON%\\python.exe -m pip install --user -U coveralls" + #- sh: python$PYTHON -m pip install --user -U coveralls + #- ps: coveralls --rcfile="$($env:COVERAGE_PROCESS_START)" diff --git a/.codecov.yml b/.codecov.yml new file mode 100644 index 0000000..375b10f --- /dev/null +++ b/.codecov.yml @@ -0,0 +1,50 @@ +codecov: + notify: + # calculate coverge even when we fail + require_ci_to_pass: no + +ignore: + # ignore test files in the source + # this is redundant and should not be in the report anyways + # because the coveragerc file ignores them + - "*Test.py" + - "setup.py" + - "test_*" + +coverage: + precision: 2 + round: down + range: "70...100" + + notify: + irc: + default: + server: "chat.freenode.net#scons" + branches: master + threshold: null + message: "Coverage {{changed}} for {{owner}}/{{repo}}" # customize the message + flags: null + paths: null + + status: + project: + default: + # compare against the current coverage + # that PR is attempt to merge to + # don't consider a drop in coverage success + target: auto + threshold: null + base: pr + + patch: + default: + # considering only the lines changed + # make sure all new lines in the PR are covered + # to consider a success + target: 100 + threshold: null + base: pr + + changes: no + +comment: off diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a8cb940 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,188 @@ +dist: trusty +language: python + +notifications: + irc: "chat.freenode.net#scons" + +addons: + apt: + update: true + +os: + - linux + +install: + - ./.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: pypy + - python: pypy3 + - stage: Coverage + +# run coverage first as its still useful to collect +stages: + - Coverage + - Test + +jobs: + include: + - &test_job + stage: Test + script: python runtest.py -a -t || if [[ $? == 2 ]]; then true; else false; fi + before_script: skip + after_success: skip + python: 2.7 + env: + - PYVER=27 + - PYTHON=2.7 + 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 (travis-ci/travis-ci#9069) + + - &slow_test_job + stage: Test + script: python runtest.py -a -j 4 -t || if [[ $? == 2 ]]; then true; else false; fi + before_script: skip + after_success: skip + python: pypy + env: + - PYVER=pypy + - PYTHON=pypy + sudo: required + + - <<: *slow_test_job + python: pypy3 + env: + - PYVER=pypy3 + - PYTHON=pypy3 + sudo: required + + + - &coverage_jobs + stage: Coverage + python: 2.7 + before_script: + # install our own python so we can modify usercustomize.py + - deactivate + - sudo add-apt-repository -y ppa:deadsnakes/ppa + - sudo apt-get update || true + - sudo apt-get -y install python$PYTHON + - wget https://bootstrap.pypa.io/get-pip.py + - sudo -H python$PYTHON get-pip.py + - which python$PYTHON + - python$PYTHON --version + - python$PYTHON -m pip install --user -U coverage codecov + # set this ensure user sites are available + - export PYTHONNOUSERSITE= + # attempt to get a location where we can store the usercustomize.py file + - python$PYTHON -m site + - export PYSITEDIR=$(python$PYTHON -m site --user-site) + - sudo mkdir -p $PYSITEDIR + - sudo touch ${PYSITEDIR}/usercustomize.py + - export COVERAGE_FILE=$PWD/.coverage + # write the usercustomize.py file so all python processes use coverage and know where the config file is + - echo "import os" | sudo tee --append ${PYSITEDIR}/usercustomize.py + - echo "os.environ['COVERAGE_PROCESS_START'] = '$PWD/.coveragerc'" | sudo tee --append ${PYSITEDIR}/usercustomize.py + - echo "import coverage" | sudo tee --append ${PYSITEDIR}/usercustomize.py + - echo "coverage.process_startup()" | sudo tee --append ${PYSITEDIR}/usercustomize.py + + script: + - export TOTAL_BUILD_JOBS=4 + # write the coverage config file + - export COVERAGE_PROCESS_START=$PWD/.coveragerc + - echo "[run]" >> .coveragerc + - echo "source = $PWD/src" >> .coveragerc + - echo "parallel = True" >> .coveragerc + - printf "omit =\n\t*Tests.py\n\tsrc/test_*\n\tsrc/setup.py\n\n" >> .coveragerc + - echo "[path]" >> .coveragerc + - echo "source = $PWD" >> .coveragerc + - echo "[report]" >> .coveragerc + - printf "omit =\n\t*Tests.py\n\tsrc/test_*\n\tsrc/setup.py\n\n" >> .coveragerc + # get a list of all the tests to split them up + - python$PYTHON runtest.py -l -a > all_tests + - let "start = ($(wc -l < all_tests) / ${TOTAL_BUILD_JOBS}) * (${BUILD_JOB_NUM} - 1)"; true; + - let "end = ($(wc -l < all_tests) / ${TOTAL_BUILD_JOBS}) * ${BUILD_JOB_NUM}" + - if (( ${BUILD_JOB_NUM} == ${TOTAL_BUILD_JOBS} )); then end=$(wc -l < all_tests); fi + - if (( ${start} == 0 )); then start=1; fi + - sed -n ${start},${end}p all_tests > build_tests + - coverage run -p --rcfile=$PWD/.coveragerc runtest.py -f build_tests || if [[ $? == 2 ]]; then true; else false; fi + + after_script: + - coverage combine + - coverage report + - coverage xml -o coverage_xml.xml + - codecov -X gcov --file coverage_xml.xml + # not using coveralls but leaving it commented to + # make it easy to re-enable + #- python$PYTHON -m pip install --user -U coveralls + #- coveralls --rcfile=$PWD/.coveragerc + + env: + - PYVER=27 + - PYTHON=2.7 + - BUILD_JOB_NUM=1 + + - <<: *coverage_jobs + env: + - PYVER=27 + - PYTHON=2.7 + - BUILD_JOB_NUM=2 + - <<: *coverage_jobs + env: + - PYVER=27 + - PYTHON=2.7 + - BUILD_JOB_NUM=3 + - <<: *coverage_jobs + env: + - PYVER=27 + - PYTHON=2.7 + - BUILD_JOB_NUM=4 + + - <<: *coverage_jobs + python: 3.6 + env: + - PYVER=36 + - PYTHON=3.6 + - BUILD_JOB_NUM=1 + - <<: *coverage_jobs + python: 3.6 + env: + - PYVER=36 + - PYTHON=3.6 + - BUILD_JOB_NUM=2 + - <<: *coverage_jobs + python: 3.6 + env: + - PYVER=36 + - PYTHON=3.6 + - BUILD_JOB_NUM=3 + - <<: *coverage_jobs + python: 3.6 + env: + - PYVER=36 + - PYTHON=3.6 + - BUILD_JOB_NUM=4 + @@ -1,4 +1,4 @@ -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/QMTest/classes.qmc b/QMTest/classes.qmc deleted file mode 100644 index 88de061..0000000 --- a/QMTest/classes.qmc +++ /dev/null @@ -1,12 +0,0 @@ -<?xml version="1.0" ?> -<!DOCTYPE class-directory - PUBLIC '-//QM/2.3/Class-Directory//EN' - 'http://www.codesourcery.com/qm/dtds/2.3/-//qm/2.3/class-directory//en.dtd'> -<class-directory> - <class kind="database" name="scons_tdb.Database"/> - <class kind="test" name="scons_tdb.Test"/> - <class kind="result_stream" name="scons_tdb.AegisChangeStream"/> - <class kind="result_stream" name="scons_tdb.AegisBaselineStream"/> - <class kind="result_stream" name="scons_tdb.AegisBatchStream"/> - <class kind="result_stream" name="scons_tdb.SConsXMLResultStream"/> -</class-directory> diff --git a/QMTest/configuration b/QMTest/configuration deleted file mode 100644 index db648ae..0000000 --- a/QMTest/configuration +++ /dev/null @@ -1,6 +0,0 @@ -<?xml version='1.0' encoding='ISO-8859-1'?> -<extension class="scons_tdb.Database" kind="database"> - <argument name="srcdir"> - <text>.</text> - </argument> -</extension> diff --git a/QMTest/scons_tdb.py b/QMTest/scons_tdb.py deleted file mode 100644 index c3b082f..0000000 --- a/QMTest/scons_tdb.py +++ /dev/null @@ -1,603 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (c) 2001 - 2017 The SCons Foundation -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -from __future__ import division, print_function - -""" -QMTest classes to support SCons' testing and Aegis-inspired workflow. - -Thanks to Stefan Seefeld for the initial code. -""" - -__revision__ = "QMTest/scons_tdb.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" - -######################################################################## -# Imports -######################################################################## - -import qm -import qm.common -import qm.test.base -from qm.fields import * -from qm.executable import * -from qm.test import database -from qm.test import test -from qm.test import resource -from qm.test import suite -from qm.test.result import Result -from qm.test.file_result_stream import FileResultStream -from qm.test.classes.text_result_stream import TextResultStream -from qm.test.classes.xml_result_stream import XMLResultStream -from qm.test.directory_suite import DirectorySuite -from qm.extension import get_extension_class_name, get_class_arguments_as_dictionary - -import dircache -import os -import imp - -if sys.platform == 'win32': - console = 'con' -else: - console = '/dev/tty' - -def Trace(msg): - open(console, 'w').write(msg) - -# QMTest 2.3 hard-codes how it captures the beginning and end time by -# calling the qm.common.format_time_iso() function, which canonicalizes -# the time stamp in one-second granularity ISO format. In order to get -# sub-second granularity, as well as to use the more precise time.clock() -# function on Windows, we must replace that function with our own. - -orig_format_time_iso = qm.common.format_time_iso - -if sys.platform == 'win32': - time_func = time.clock -else: - time_func = time.time - -def my_format_time(time_secs=None): - return str(time_func()) - -qm.common.format_time_iso = my_format_time - -######################################################################## -# Classes -######################################################################## - -def get_explicit_arguments(e): - """This function can be removed once QMTest 2.4 is out.""" - - # Get all of the arguments. - arguments = get_class_arguments_as_dictionary(e.__class__) - # Determine which subset of the 'arguments' have been set - # explicitly. - explicit_arguments = {} - for name, field in arguments.items(): - # Do not record computed fields. - if field.IsComputed(): - continue - if name in e.__dict__: - explicit_arguments[name] = e.__dict__[name] - - return explicit_arguments - - -def check_exit_status(result, prefix, desc, status): - """This function can be removed once QMTest 2.4 is out.""" - - if sys.platform == "win32" or os.WIFEXITED(status): - # Obtain the exit code. - if sys.platform == "win32": - exit_code = status - else: - exit_code = os.WEXITSTATUS(status) - # If the exit code is non-zero, the test fails. - if exit_code != 0: - result.Fail("%s failed with exit code %d." % (desc, exit_code)) - # Record the exit code in the result. - result[prefix + "exit_code"] = str(exit_code) - return False - - elif os.WIFSIGNALED(status): - # Obtain the signal number. - signal = os.WTERMSIG(status) - # If the program gets a fatal signal, the test fails . - result.Fail("%s received fatal signal %d." % (desc, signal)) - result[prefix + "signal"] = str(signal) - return False - else: - # A process should only be able to stop by exiting, or - # by being terminated with a signal. - assert None - - return True - - - -class Null: - pass - -_null = Null() - -sys_attributes = [ - 'byteorder', - 'exec_prefix', - 'executable', - 'maxint', - 'maxunicode', - 'platform', - 'prefix', - 'version', - 'version_info', -] - -def get_sys_values(): - sys_attributes.sort() - result = [(k, getattr(sys, k, _null)) for k in sys_attributes] - result = [t for t in result if not t[1] is _null] - result = [t[0] + '=' + repr(t[1]) for t in result] - return '\n '.join(result) - -module_attributes = [ - '__version__', - '__build__', - '__buildsys__', - '__date__', - '__developer__', -] - -def get_module_info(module): - module_attributes.sort() - result = [(k, getattr(module, k, _null)) for k in module_attributes] - result = [t for t in result if not t[1] is _null] - result = [t[0] + '=' + repr(t[1]) for t in result] - return '\n '.join(result) - -environ_keys = [ - 'PATH', - 'SCONS', - 'SCONSFLAGS', - 'SCONS_LIB_DIR', - 'PYTHON_ROOT', - 'QTDIR', - - 'COMSPEC', - 'INTEL_LICENSE_FILE', - 'INCLUDE', - 'LIB', - 'MSDEVDIR', - 'OS', - 'PATHEXT', - 'SystemRoot', - 'TEMP', - 'TMP', - 'USERNAME', - 'VXDOMNTOOLS', - 'WINDIR', - 'XYZZY' - - 'ENV', - 'HOME', - 'LANG', - 'LANGUAGE', - 'LC_ALL', - 'LC_MESSAGES', - 'LOGNAME', - 'MACHINE', - 'OLDPWD', - 'PWD', - 'OPSYS', - 'SHELL', - 'TMPDIR', - 'USER', -] - -def get_environment(): - environ_keys.sort() - result = [(k, os.environ.get(k, _null)) for k in environ_keys] - result = [t for t in result if not t[1] is _null] - result = [t[0] + '-' + t[1] for t in result] - return '\n '.join(result) - -class SConsXMLResultStream(XMLResultStream): - def __init__(self, *args, **kw): - super(SConsXMLResultStream, self).__init__(*args, **kw) - def WriteAllAnnotations(self, context): - # Load (by hand) the SCons modules we just unwrapped so we can - # extract their version information. Note that we have to override - # SCons.Script.main() with a do_nothing() function, because loading up - # the 'scons' script will actually try to execute SCons... - - src_engine = os.environ.get('SCONS_LIB_DIR') - if not src_engine: - src_engine = os.path.join('src', 'engine') - fp, pname, desc = imp.find_module('SCons', [src_engine]) - SCons = imp.load_module('SCons', fp, pname, desc) - - # Override SCons.Script.main() with a do-nothing function, because - # loading the 'scons' script will actually try to execute SCons... - - src_engine_SCons = os.path.join(src_engine, 'SCons') - fp, pname, desc = imp.find_module('Script', [src_engine_SCons]) - SCons.Script = imp.load_module('Script', fp, pname, desc) - def do_nothing(): - pass - SCons.Script.main = do_nothing - - scons_file = os.environ.get('SCONS') - if scons_file: - src_script, scons_py = os.path.split(scons_file) - scons = os.path.splitext(scons_py)[0] - else: - src_script = os.path.join('src', 'script') - scons = 'scons' - fp, pname, desc = imp.find_module(scons, [src_script]) - scons = imp.load_module('scons', fp, pname, desc) - fp.close() - - self.WriteAnnotation("scons_test.engine", get_module_info(SCons)) - self.WriteAnnotation("scons_test.script", get_module_info(scons)) - - self.WriteAnnotation("scons_test.sys", get_sys_values()) - self.WriteAnnotation("scons_test.os.environ", get_environment()) - -class AegisStream(TextResultStream): - arguments = [ - qm.fields.IntegerField( - name = "print_time", - title = "print individual test times", - description = """ - """, - default_value = 0, - ), - ] - def __init__(self, *args, **kw): - super(AegisStream, self).__init__(*args, **kw) - self._num_tests = 0 - self._outcomes = {} - self._outcome_counts = {} - for outcome in AegisTest.aegis_outcomes: - self._outcome_counts[outcome] = 0 - self.format = "full" - def _percent(self, outcome): - return 100. * self._outcome_counts[outcome] / self._num_tests - def _aegis_no_result(self, result): - outcome = result.GetOutcome() - return (outcome == Result.FAIL and result.get('Test.exit_code') == '2') - def _DisplayText(self, text): - # qm.common.html_to_text() uses htmllib, which sticks an extra - # '\n' on the front of the text. Strip it and only display - # the text if there's anything to display. - text = qm.common.html_to_text(text) - if text[0] == '\n': - text = text[1:] - if text: - lines = text.splitlines() - if lines[-1] == '': - lines = lines[:-1] - self.file.write(' ' + '\n '.join(lines) + '\n\n') - def _DisplayResult(self, result, format): - test_id = result.GetId() - kind = result.GetKind() - if self._aegis_no_result(result): - outcome = "NO_RESULT" - else: - outcome = result.GetOutcome() - self._WriteOutcome(test_id, kind, outcome) - self.file.write('\n') - def _DisplayAnnotations(self, result): - try: - self._DisplayText(result["Test.stdout"]) - except KeyError: - pass - try: - self._DisplayText(result["Test.stderr"]) - except KeyError: - pass - if self.print_time: - start = float(result['qmtest.start_time']) - end = float(result['qmtest.end_time']) - fmt = " Total execution time: %.1f seconds\n\n" - self.file.write(fmt % (end - start)) - -class AegisChangeStream(AegisStream): - def WriteResult(self, result): - test_id = result.GetId() - if self._aegis_no_result(result): - outcome = AegisTest.NO_RESULT - else: - outcome = result.GetOutcome() - self._num_tests += 1 - self._outcome_counts[outcome] += 1 - super(AegisStream, self).WriteResult(result) - def _SummarizeTestStats(self): - self.file.write("\n") - self._DisplayHeading("STATISTICS") - if self._num_tests != 0: - # We'd like to use the _FormatStatistics() method to do - # this, but it's wrapped around the list in Result.outcomes, - # so it's simpler to just do it ourselves. - print(" %6d tests total\n" % self._num_tests) - for outcome in AegisTest.aegis_outcomes: - if self._outcome_counts[outcome] != 0: - print(" %6d (%3.0f%%) tests %s" % ( - self._outcome_counts[outcome], - self._percent(outcome), - outcome - )) - -class AegisBaselineStream(AegisStream): - def WriteResult(self, result): - test_id = result.GetId() - if self._aegis_no_result(result): - outcome = AegisTest.NO_RESULT - self.expected_outcomes[test_id] = Result.PASS - self._outcome_counts[outcome] += 1 - else: - self.expected_outcomes[test_id] = Result.FAIL - outcome = result.GetOutcome() - if outcome != Result.Fail: - self._outcome_counts[outcome] += 1 - self._num_tests += 1 - super(AegisStream, self).WriteResult(result) - def _SummarizeRelativeTestStats(self): - self.file.write("\n") - self._DisplayHeading("STATISTICS") - if self._num_tests != 0: - # We'd like to use the _FormatStatistics() method to do - # this, but it's wrapped around the list in Result.outcomes, - # so it's simpler to just do it ourselves. - if self._outcome_counts[AegisTest.FAIL]: - print(" %6d (%3.0f%%) tests as expected" % ( - self._outcome_counts[AegisTest.FAIL], - self._percent(AegisTest.FAIL), - )) - non_fail_outcomes = list(AegisTest.aegis_outcomes[:]) - non_fail_outcomes.remove(AegisTest.FAIL) - for outcome in non_fail_outcomes: - if self._outcome_counts[outcome] != 0: - print(" %6d (%3.0f%%) tests unexpected %s" % ( - self._outcome_counts[outcome], - self._percent(outcome), - outcome, - )) - -class AegisBatchStream(FileResultStream): - def __init__(self, arguments): - super(AegisBatchStream, self).__init__(arguments) - self._outcomes = {} - def WriteResult(self, result): - test_id = result.GetId() - kind = result.GetKind() - outcome = result.GetOutcome() - exit_status = '0' - if outcome == Result.FAIL: - exit_status = result.get('Test.exit_code') - self._outcomes[test_id] = exit_status - def Summarize(self): - self.file.write('test_result = [\n') - for file_name in sorted(self._outcomes.keys()): - exit_status = self._outcomes[file_name] - file_name = file_name.replace('\\', '/') - self.file.write(' { file_name = "%s";\n' % file_name) - self.file.write(' exit_status = %s; },\n' % exit_status) - self.file.write('];\n') - -class AegisTest(test.Test): - PASS = "PASS" - FAIL = "FAIL" - NO_RESULT = "NO_RESULT" - ERROR = "ERROR" - UNTESTED = "UNTESTED" - - aegis_outcomes = ( - PASS, FAIL, NO_RESULT, ERROR, UNTESTED, - ) - """Aegis test outcomes.""" - -class Test(AegisTest): - """Simple test that runs a python script and checks the status - to determine whether the test passes.""" - - script = TextField(title="Script to test") - topdir = TextField(title="Top source directory") - - def Run(self, context, result): - """Run the test. The test passes if the command exits with status=0, - and fails otherwise. The program output is logged, but not validated.""" - - command = RedirectedExecutable() - args = [context.get('python', sys.executable), '-tt', self.script] - status = command.Run(args, os.environ) - if not check_exit_status(result, 'Test.', self.script, status): - # In case of failure record exit code, stdout, and stderr. - result.Fail("Non-zero exit_code.") - result["Test.stdout"] = result.Quote(command.stdout) - result["Test.stderr"] = result.Quote(command.stderr) - - -class Database(database.Database): - """Scons test database. - * The 'src' and 'test' directories are explicit suites. - * Their subdirectories are implicit suites. - * All files under 'src/' ending with 'Tests.py' contain tests. - * All files under 'test/' with extension '.py' contain tests. - * Right now there is only a single test class, which simply runs - the specified python interpreter on the given script. To be refined...""" - - srcdir = TextField(title = "Source Directory", - description = "The root of the test suite's source tree.") - _is_generic_database = True - - def is_a_test_under_test(path, t): - return os.path.splitext(t)[1] == '.py' \ - and os.path.isfile(os.path.join(path, t)) - - def is_a_test_under_src(path, t): - return t[-8:] == 'Tests.py' \ - and os.path.isfile(os.path.join(path, t)) - - is_a_test = { - 'src' : is_a_test_under_src, - 'test' : is_a_test_under_test, - } - - exclude_subdirs = { - '.svn' : 1, - 'CVS' : 1, - } - - def is_a_test_subdir(path, subdir): - if exclude_subdirs.get(subdir): - return None - return os.path.isdir(os.path.join(path, subdir)) - - def __init__(self, path, arguments): - - self.label_class = "file_label.FileLabel" - self.modifiable = "false" - # Initialize the base class. - super(Database, self).__init__(path, arguments) - - - def GetRoot(self): - - return self.srcdir - - - def GetSubdirectories(self, directory): - - components = self.GetLabelComponents(directory) - path = os.path.join(self.GetRoot(), *components) - if directory: - dirs = [d for d in dircache.listdir(path) - if os.path.isdir(os.path.join(path, d))] - else: - dirs = list(self.is_a_test.keys()) - - dirs.sort() - return dirs - - - def GetIds(self, kind, directory = "", scan_subdirs = 1): - - components = self.GetLabelComponents(directory) - path = os.path.join(self.GetRoot(), *components) - - if kind == database.Database.TEST: - - if not components: - return [] - - ids = [self.JoinLabels(directory, t) - for t in dircache.listdir(path) - if self.is_a_test[components[0]](path, t)] - - elif kind == Database.RESOURCE: - return [] # no resources yet - - else: # SUITE - - if directory: - ids = [self.JoinLabels(directory, d) - for d in dircache.listdir(path) - if os.path.isdir(os.path.join(path, d))] - else: - ids = list(self.is_a_test.keys()) - - if scan_subdirs: - for d in dircache.listdir(path): - if (os.path.isdir(d)): - ids.extend(self.GetIds(kind, - self.JoinLabels(directory, d), - True)) - - return ids - - - def GetExtension(self, id): - - if not id: - return DirectorySuite(self, id) - - components = self.GetLabelComponents(id) - path = os.path.join(self.GetRoot(), *components) - - if os.path.isdir(path): # a directory - return DirectorySuite(self, id) - - elif os.path.isfile(path): # a test - - arguments = {} - arguments['script'] = path - arguments['topdir'] = self.GetRoot() - - return Test(arguments, qmtest_id = id, qmtest_database = self) - - else: # nothing else to offer - - return None - - - def GetTest(self, test_id): - """This method can be removed once QMTest 2.4 is out.""" - - t = self.GetExtension(test_id) - if isinstance(t, test.Test): - return database.TestDescriptor(self, - test_id, - get_extension_class_name(t.__class__), - get_explicit_arguments(t)) - - raise database.NoSuchTestError(test_id) - - def GetSuite(self, suite_id): - """This method can be removed once QMTest 2.4 is out.""" - - if suite_id == "": - return DirectorySuite(self, "") - - s = self.GetExtension(suite_id) - if isinstance(s, suite.Suite): - return s - - raise database.NoSuchSuiteError(suite_id) - - - def GetResource(self, resource_id): - """This method can be removed once QMTest 2.4 is out.""" - - r = self.GetExtension(resource_id) - if isinstance(r, resource.Resource): - return ResourceDescriptor(self, - resource_id, - get_extension_class_name(r.__class__), - get_explicit_arguments(r)) - - raise database.NoSuchResourceError(resource_id) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/QMTest/test-framework.rst b/QMTest/test-framework.rst deleted file mode 100644 index 844d99b..0000000 --- a/QMTest/test-framework.rst +++ /dev/null @@ -1,430 +0,0 @@ -======================= -SCons Testing Framework -======================= - -SCons uses extensive automated tests to try to ensure quality. The primary goal -is that users should be able to upgrade from version to version without any surprise -changes in behavior. - -In general, no change goes into SCons unless it has one or more new or modified -tests that demonstrably exercise the bug being fixed or the feature being added. -There are exceptions to this guideline, but they should be just that, ''exceptions''. -When in doubt, make sure it's tested. - -Test Organization -================= - -There are three types of SCons tests: - -*End-to-End Tests* - End-to-end tests of SCons are all Python scripts (``*.py``) underneath - the ``test/`` subdirectory. They use the test infrastructure modules in the - ``QMTest`` subdirectory. - -*Unit Tests* - Unit tests for individual SCons modules live underneath the - ``src/engine/`` subdirectory and are the same base name as the module - with ``Tests.py`` appended--for example, the unit tests for the - ``Builder.py`` module are in the ``BuilderTests.py`` script. - -*External Tests* - For the support of external Tools (in the form of packages, preferably), the - testing framework got extended, such that it can run in standalone mode. - You can start it from the top-level folder of your Tool's source tree, - where it then finds all Python scripts (``*.py``) underneath the - local ``test/`` directory. - This implies that Tool tests have to be kept in a folder named ``test``, - like for the SCons core. - - -Contrasting End-to-End and Unit Tests -##################################### - -In general, anything that we've put into an end-to-end test script should -be considered a hardened part of the interface (that is, it's something -that a user might do) and should not be broken. Unit tests are now -considered more malleable, more for testing internal interfaces that -can change so long as we don't break users' ``SConscript`` files. (This -wasn't always the case, and there's a lot of meaty code in many of the -unit test scripts that does, in fact, capture external interface -behavior. In general, we should try to move those things to end-to-end -scripts as we find them.) - -It's more difficult to debug end-to-end tests. You can actually go -straight into the Python debugger on the unit test scripts by using the -``runtest.py --pdb`` option, but the end-to-end tests treat an SCons -invocation as a "black box" and just look for external effects. -Simple ``print`` statements within the SCons code itself often don't help -debug end-to-end because they end up in SCons output that gets compared -against expected output and cause a test failure. Probably the most -effective technique is to use the internal ``SCons.Debug.Trace()`` function, -which prints output to ``/dev/tty`` on Linux/UNIX systems and ``con`` on -Windows systems, so you can see what's going on. - -Naming conventions -################## - -The end-to-end tests, more or less, stick to the following naming conventions: - -1. All tests end with a .py suffix. - -2. In the *General* form we use - - ``Feature.py`` - for the test of a specified feature; try to - keep this description reasonably short - - ``Feature-x.py`` - for the test of a specified feature using - option ``x`` - -3. The *command line option* tests take the form - - ``option-x.py`` - for a lower-case single-letter option - - ``option--X.py`` - upper-case single-letter option - (with an extra hyphen, so the file names will - be unique on case-insensitive systems) - - ``option--lo.py`` - long option; abbreviate the long - option name to a few characters - - -Running Tests -============= - -The standard set of SCons tests are run from the top-level source directory -by the ``runtest.py`` script. -There is a ``--qmtest`` option that checks whether the ``QMTest`` package -is installed on your system. If it can be found, then the ``runtest.py`` script -will use it to carry out the tests. - -Help is available through the ``-h`` option: - -:: - - $ python runtest.py -h - -To simply run all the tests, use the ``-a`` option: - -:: - - $ python runtest.py -a - -By default, ``runtest.py`` prints a count and percentage message for each test -case, along with the name of the test file. -If you need the output to be more silent, have a look at the ``-q``, ``-s`` and -``-k`` options. - -You may specifically list one or more tests to be run: - -:: - - $ python runtest.py src/engine/SCons/BuilderTests.py - $ python runtest.py test/option-j.py test/Program.py - -Folder names are allowed arguments as well, so you can do a - -:: - - $ python runtest.py test/SWIG - -to run all SWIG tests only. - -You can also use the ``-f`` option to execute just the tests listed in a specified -text file: - -:: - - $ cat testlist.txt - test/option-j.py - test/Program.py - $ python runtest.py -f testlist.txt - - -One test must be listed per line, and any lines that begin with '#' -will be ignored (the intent being to allow you, for example, -to comment out tests that -are currently passing and then uncomment all of the tests in the file -for a final validation run). - -If more than one test is run, the ``runtest.py`` script prints a summary -of how many tests passed, failed, or yielded no result, and lists any -unsuccessful tests. - -The above invocations all test directly the files underneath the ``src/`` -subdirectory, and do not require that a packaging build be performed first. -The ``runtest.py`` script supports additional options to run tests against -unpacked packages in the ``build/test-*/`` subdirectories. - -If you are testing a separate Tool outside of the SCons source tree, you have -to call the ``runtest.py`` script in *external* (stand-alone) mode:: - - $ python ~/scons/runtest.py -e -a - -. This ensures that the testing framework doesn't try to access SCons classes -needed for some of the *internal* test cases. - -Note, that the actual tests are carried out in a temporary folder each, which gets -deleted afterwards. This ensures that your source directories don't get clobbered -with temporary files from the test runs. It also means that you can't simply change -into a folder to "debug things" after a test has gone wrong. For a way around this, -check out the ``PRESERVE`` environment variable. It can be seen in action in -`How to convert old tests`_ below. - -Not Running Tests -================= - -If you simply want to check which tests would get executed, you can call the -``runtest.py`` script with the ``-l`` option:: - - $ python runtest.py -l - -Then there is also the ``-n`` option, which prints the command line for each -single test, but doesn't actually execute them:: - - $ python runtest.py -n - -Finding Tests -============= - -When started in *standard* mode - -:: - - $ python runtest.py -a - - -, ``runtest.py`` assumes that it is run from the SCons top-level source directory. -It then dives into the ``src`` and ``test`` folders, where it tries to find filenames - - ``*Test.py`` - for the ``src`` directory, and - - ``*.py`` - for the ``test`` folder. - -When using fixtures, you may quickly end up in a position where you have supporting -Python script files in a subfolder, but they shouldn't get picked up as test scripts. -In this case you have two options: - -1. Add a file with the name ``sconstest.skip`` to your subfolder. This lets - ``runtest.py`` skip the contents of the directory completely. -2. Create a file ``.exclude_tests`` in each folder in question, and in it list - line-by-line the files to get excluded from testing. - -The same rules apply when testing external Tools by using the ``-e`` option. - - -"Hello, world!" SCons Test Script -================================= - -To illustrate how the end-to-end test scripts work, -let's walk through a simple "Hello, world!" example: - -:: - - #!python - import TestSCons - - test = TestSCons.TestSCons() - - test.write('SConstruct', """\ - Program('hello.c') - """) - - test.write('hello.c', """\ - int - main(int argc, char *argv[]) - { - printf("Hello, world!\\n"); - exit (0); - } - """) - - test.run() - - test.run(program='./hello', stdout="Hello, world!\n") - - test.pass_test() - - -``import TestSCons`` - Imports the main infrastructure for writing SCons tests. This is normally the only part of the infrastructure that needs importing. Sometimes other Python modules are necessary or helpful, and get imported before this line. - -``test = TestSCons.TestSCons()`` - This initializes an object for testing. A fair amount happens under the covers when the object is created, including: - - * A temporary directory is created for all the in-line files that will get created. - * The temporary directory's removal is arranged for when the test is finished. - * We ``os.chdir()`` to the temporary directory. - -``test.write('SConstruct', ...`` - This line creates an ``SConstruct`` file in the temporary directory, to be used as input to the ``scons`` run(s) that we're testing. Note the use of the Python triple-quote syntax for the contents of the ``SConstruct`` file. Because input files for tests are all created from in-line data like this, the tests can sometimes get a little confusing to read, because some of the Python code is found - -``test.write('hello.c', ...`` - This lines creates an ``hello.c`` file in the temporary directory. Note that we have to escape the ``\\n`` in the ``"Hello, world!\\n"`` string so that it ends up as a single backslash in the ``hello.c`` file on disk. - -``test.run()`` - This actually runs SCons. Like the object initialization, things happen under the covers: - - * The exit status is verified; the test exits with a failure if the exit status is not zero. - * The error output is examined, and the test exits with a failure if there is any - -``test.run(program='./hello', stdout="Hello, world!\n")`` - This shows use of the ``TestSCons.run()`` method to execute a program other than ``scons``, in this case the ``hello`` program we just presumably built. The ``stdout=`` keyword argument also tells the ``TestSCons.run()`` method to fail if the program output does not match the expected string ``"Hello, world!\n"``. Like the previous ``test.run()`` line, it will also fail the test if the exit status is non-zero, or there is any error output. - -``test.pass_test()`` - This is always the last line in a test script. It prints ``PASSED`` on the screen and makes sure we exit with a ``0`` status to indicate the test passed. As a side effect of destroying the ``test`` object, the created temporary directory will be removed. - -Working with fixtures -===================== - -In the simple example above, we have seen how to create files in the temporary test directory. -We give a filename to the ``TestSCons.write()`` method, together with its contents, and it gets -written to the test folder right before its start. - -This technique can still be seen throughout most of the end-to-end tests, but there is a better -way. It's much easier to edit, create and maintain real files, instead of copy/pasting -content to/from a Python script. If the test files get longer, the test script -gets longer and is harder to read. - -Against this, we now have the possibility to copy single files or the contents of a -local folder to the test directory. Since we can reuse these files/folders to setup -several tests, we call them *fixtures* in the following. - -Directory fixtures -################## - -The function ``dir_fixture(self, srcdir, dstdir=None)`` in the ``TestCmd`` class -copies the contents of the specified folder ``srcdir`` from -the directory of the called test script, to the current -temporary test directory. -The ``srcdir`` name may be a list, in which case the elements are -concatenated with the ``os.path.join()`` method. The ``dstdir`` is -assumed to be under the temporary working directory, it gets -created automatically, if it does not already exist. - -A short syntax example:: - - test = TestSCons.TestSCons() - test.dir_fixture('image') - test.run() - -would copy all files and subfolders from the local ``image`` folder, to -the temporary directory for the current test. - -If you'd like to see a real example for this in action, refer to the test -named ``test/packaging/convenience-functions/convenience-functions.py``. - -File fixtures -############# - -Like for directory fixtures, ``file_fixture(self, srcfile, dstfile=None)`` -copies the file ``srcfile`` from the directory of -the called script, to the temporary test directory. -The ``dstfile`` is assumed to be under the temporary working -directory, unless it is an absolute path name. -If ``dstfile`` is specified, its target directory gets created -automatically if it doesn't already exist. - -With a:: - - test = TestSCons.TestSCons() - test.file_fixture('SConstruct') - test.file_fixture(['src','main.cpp'],['src','main.cpp']) - test.run() - -you would copy the files ``SConstruct`` and ``src/main.cpp`` to the temporary -test folder, prior to running the test itself. - -Again, a reference example can be found in the current *default* revision of -SCons, it is ``test/packaging/sandbox-test/sandbox-test.py``. - -For even more examples you should check out one of the external Tools, e.g. the -*Qt4* Tool at https://bitbucket.org/dirkbaechle/scons_qt4. Also visit the SCons -Tools Index at http://www.scons.org/wiki/ToolsIndex for a complete -list of available Tools, though not all may have tests yet. - -How to convert old tests -######################## - -We now show how to convert a test, still using the ``TestSCons.write()`` method, to -the fixture based approach. For this, we need to get at the files as they -are written to each temporary test folder. - -Luckily, ``runtest.py`` checks for the existence of an environment variable named -``PRESERVE``. If it is set to a non-zero value, the testing framework doesn't delete -the test folder as ususal, but prints its name to the screen. - -So, you should be able to give the commands - -:: - - $ export PRESERVE=1 - $ python runtest.py test/packaging/sandbox-test.py - -, assuming Linux and a bash-like shell. - -The output should then look something like this:: - - 1/1 (100.00%) /usr/bin/python -tt test/packaging/sandbox-test.py - PASSED - Preserved directory /tmp/testcmd.4060.twlYNI - -and you see that the test files have been kept in the folder ``/tmp/testcmd.4060.twlYNI``, -where you can now copy them from to your new *fixture* folder. Then, in the test -script you simply remove all the tedious ``TestSCons.write()`` statements and -replace them by a single ``TestSCons.dir_fixture()``. - -Finally, you shouldn't forget to clean up and remove the temporary test directory. ``;)`` - -Test Infrastructure -=================== - -The test API is in ``QMTest/TestSCons.py``. ``TestSCons`` is a subclass of -``TestCommon``, which is a subclass of ``TestCmd``; all those python files are -in ``QMTest``. Start in ``QMTest/TestCmd.py`` for the base API definitions, -like how to create files (``test.write()``) and run commands (``test.run()``). - -You want to use ``TestSCons`` for the end-to-end tests in ``test``, but ``TestCmd`` -for the unit tests in the ``src`` folder. - -The match functions work like this: - -TestSCons.match_re:: match each line with a RE - * Splits the lines into a list (unless they already are) - * splits the REs at newlines (unless already a list) and puts ^..$ around each - * then each RE must match each line. This means there must be as many REs as lines. - -TestSCons.match_re_dotall:: match all the lines against a single RE - * Joins the lines with newline (unless already a string) - * joins the REs with newline (unless it's a string) and puts ^..$ around the whole thing - * then whole thing must match with python re.DOTALL. - -Use them in a test like this:: - - test.run(..., match=TestSCons.match_re, ...) - -or:: - - test.must_match(..., match=TestSCons.match_re, ...) - -Avoiding Tests based on Tool existence -====================================== - -Here's an easy sample:: - - #!python - intelc = test.detect_tool('intelc', prog='icpc') - if not intelc: - test.skip_test("Could not load 'intelc' Tool; skipping test(s).\n") - -See ``QMTest/TestSCons.py`` for the ``detect_tool`` method. It calls the tool's -``generate()`` method, and then looks for the given prog (tool name by default) in -``env['ENV']['PATH']``. - - diff --git a/README.rst b/README.rst index 258d6a1..ea7667c 100644..100755 --- a/README.rst +++ b/README.rst @@ -4,15 +4,28 @@ SCons - a software construction tool .. image:: https://img.shields.io/badge/IRC-scons-blue.svg :target: http://webchat.freenode.net/?channels=%23scons&uio=d4 :alt: IRC - + .. image:: https://img.shields.io/sourceforge/dm/scons.svg :target: https://sourceforge.net/projects/scons :alt: Sourceforge Monthly Downloads - + .. image:: https://img.shields.io/sourceforge/dt/scons.svg :target: https://sourceforge.net/projects/scons :alt: Sourceforge Total Downloads +.. image:: https://travis-ci.org/SCons/scons.svg?branch=master + :target: https://travis-ci.org/SCons/scons + :alt: Travis CI build status + +.. image:: https://ci.appveyor.com/api/projects/status/github/SCons/scons?svg=true&branch=master + :target: https://ci.appveyor.com/project/SCons/scons + :alt: AppVeyor CI build Status + +.. image:: https://codecov.io/gh/SCons/scons/branch/master/graph/badge.svg + :target: https://codecov.io/gh/SCons/scons + :alt: CodeCov Coverage Status + + Welcome to the SCons development tree. The real purpose of this tree is to package SCons for production distribution in a variety of formats, not just to hack SCons code. @@ -53,15 +66,14 @@ Latest Version Before going further, you can check that this package you have is the latest version at the SCons download page: - http://www.scons.org/download.php + http://www.scons.org/pages/download.html Execution Requirements ====================== -Running SCons requires Python version 2.7 or later (Python 3 is not -yet supported). There should be no other dependencies or requirements -to run SCons. +Running SCons requires either Python version 2.7.* or Python 3.5 or higher. +There should be no other dependencies or requirements to run SCons. The default SCons configuration assumes use of the Microsoft Visual C++ compiler suite on WIN32 systems, and assumes a C compiler named 'cc', a C++ @@ -92,13 +104,11 @@ populate the build/scons/ subdirectory. You would do this as follows on a Linux or UNIX system (using sh or a derivative like bash or ksh):: $ setenv MYSCONS=`pwd`/src - $ setenv SCONS_LIB_DIR=$MYSCONS/engine $ python $MYSCONS/script/scons.py [arguments] Or on Windows:: C:\scons>set MYSCONS=%cd%\src - C:\scons>set SCONS_LIB_DIR=%MYSCONS%\engine C:\scons>python %MYSCONS%\script\scons.py [arguments] An alternative approach is to skip the above and use:: @@ -168,7 +178,7 @@ Or on Windows:: By default, the above commands will do the following: -- Install the version-numbered "scons-3.0.0" and "sconsign-3.0.0" scripts in +- Install the version-numbered "scons-3.1.0" and "sconsign-3.0.3" scripts in the default system script directory (/usr/bin or C:\\Python\*\\Scripts, for example). This can be disabled by specifying the "--no-version-script" option on the command line. @@ -180,23 +190,23 @@ By default, the above commands will do the following: before making it the default on your system. On UNIX or Linux systems, you can have the "scons" and "sconsign" scripts be - hard links or symbolic links to the "scons-3.0.0" and "sconsign-3.0.0" + hard links or symbolic links to the "scons-3.0.3" and "sconsign-3.0.3" scripts by specifying the "--hardlink-scons" or "--symlink-scons" options on the command line. -- Install "scons-3.0.0.bat" and "scons.bat" wrapper scripts in the Python +- Install "scons-3.0.3.bat" and "scons.bat" wrapper scripts in the Python prefix directory on Windows (C:\\Python\*, for example). This can be disabled by specifying the "--no-install-bat" option on the command line. On UNIX or Linux systems, the "--install-bat" option may be specified to - have "scons-3.0.0.bat" and "scons.bat" files installed in the default system + have "scons-3.0.3.bat" and "scons.bat" files installed in the default system script directory, which is useful if you want to install SCons in a shared file system directory that can be used to execute SCons from both UNIX/Linux and Windows systems. - Install the SCons build engine (a Python module) in an appropriate - version-numbered SCons library directory (/usr/lib/scons-3.0.0 or - C:\\Python\*\\scons-3.0.0, for example). See below for more options related to + version-numbered SCons library directory (/usr/lib/scons-3.0.3 or + C:\\Python\*\\scons-3.0.3, for example). See below for more options related to installing the build engine library. - Install the troff-format man pages in an appropriate directory on UNIX or @@ -474,7 +484,7 @@ running all of "runtest.py -a". Building Packages ================= -We use SCons (version 3.0.0 or later) to build its own packages. If you +We use SCons (version 3.0.3 or later) to build its own packages. If you already have an appropriate version of SCons installed on your system, you can build everything by simply running it:: @@ -489,18 +499,13 @@ about `Executing SCons Without Installing`_):: Depending on the utilities installed on your system, any or all of the following packages will be built:: - build/dist/scons-3.0.0-1.noarch.rpm - build/dist/scons-3.0.0-1.src.rpm - build/dist/scons-3.0.0.linux-i686.tar.gz - build/dist/scons-3.0.0.tar.gz - build/dist/scons-3.0.0.win32.exe - build/dist/scons-3.0.0.zip - build/dist/scons-doc-3.0.0.tar.gz - build/dist/scons-local-3.0.0.tar.gz - build/dist/scons-local-3.0.0.zip - build/dist/scons-src-3.0.0.tar.gz - build/dist/scons-src-3.0.0.zip - build/dist/scons_3.0.0-1_all.deb + build/dist/scons-3.0.5.tar.gz + build/dist/scons-3.0.5.zip + build/dist/scons-doc-3.0.5.tar.gz + build/dist/scons-local-3.0.5.tar.gz + build/dist/scons-local-3.0.5.zip + build/dist/scons-src-3.0.5.tar.gz + build/dist/scons-src-3.0.5.zip The SConstruct file is supposed to be smart enough to avoid trying to build packages for which you don't have the proper utilities installed. For @@ -524,10 +529,6 @@ system, it should not try to install it.) The runtest.py script supports a -p option that will run the specified tests (individually or collectively via the -a option) against the unpacked build/test-/\* subdirectory:: - $ python runtest.py -p deb - - $ python runtest.py -p rpm - $ python runtest.py -p local-tar-gz $ python runtest.py -p local-zip @@ -664,7 +665,7 @@ section of small examples for getting started using SCons. Additional documentation for SCons is available at: - http://www.scons.org/documentation + http://www.scons.org/documentation.html Licensing @@ -677,18 +678,22 @@ in the LICENSE file. Reporting Bugs ============== -Please report bugs by following the detailed instructions on our Bug -Submission page: +The SCons project welcomes bug reports and feature requests. - http://scons.tigris.org/bug-submission.html +Please make sure you send email with the problem or feature request to +the SCons users mailing list, which you can join via the link below: -You can also send mail to the SCons developers' mailing list: + http://two.pairlist.net/mailman/listinfo/scons-users - scons-dev@scons.org +Once you have discussed your issue on the users mailing list and the +community has confirmed that it is either a new bug or a duplicate of an +existing bug, then please follow the instructions the community provides +to file a new bug or to add yourself to the CC list for an existing bug + +You can explore the list of existing bugs, which may include workarounds +for the problem you've run into on GitHub Issues: -But even if you send email to the mailing list please make sure that you ALSO -submit a bug report to the project page bug tracker, because bug reports in -email often get overlooked in the general flood of messages. + https://github.com/SCons/scons/issues Mailing Lists @@ -760,5 +765,5 @@ many contributors, including but not at all limited to: \... and many others. -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation @@ -5,13 +5,13 @@ from __future__ import print_function -copyright_years = '2001 - 2017' +copyright_years = '2001 - 2019' # This gets inserted into the man pages to reflect the month of release. -month_year = 'September 2017' +month_year = 'March 2019' # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -34,6 +34,7 @@ month_year = 'September 2017' # import distutils.util +import distutils.command import fnmatch import os import os.path @@ -42,55 +43,25 @@ import stat import sys import tempfile import time +import socket +import textwrap import bootstrap project = 'scons' -default_version = '3.0.0' +default_version = '3.0.5' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years -platform = distutils.util.get_platform() - -def is_windows(): - if platform.startswith('win'): - return True - else: - return False - SConsignFile() # -# An internal "whereis" routine to figure out if a given program -# is available on this system. -# -def whereis(file): - exts = [''] - if is_windows(): - exts += ['.exe'] - for dir in os.environ['PATH'].split(os.pathsep): - f = os.path.join(dir, file) - for ext in exts: - f_ext = f + ext - if os.path.isfile(f_ext): - try: - st = os.stat(f_ext) - except: - continue - if stat.S_IMODE(st[stat.ST_MODE]) & 0o111: - return f_ext - return None - -# # We let the presence or absence of various utilities determine whether # or not we bother to build certain pieces of things. This should allow # people to still do SCons packaging work even if they don't have all -# of the utilities installed (e.g. RPM). +# of the utilities installed # -dh_builddeb = whereis('dh_builddeb') -fakeroot = whereis('fakeroot') gzip = whereis('gzip') -rpmbuild = whereis('rpmbuild') -hg = os.path.exists('.hg') and whereis('hg') +git = os.path.exists('.git') and whereis('git') unzip = whereis('unzip') zip = whereis('zip') @@ -99,12 +70,7 @@ zip = whereis('zip') # date = ARGUMENTS.get('DATE') if not date: - date = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(time.time())) - -# Datestring for debian -# Should look like: Mon, 03 Nov 2016 13:37:42 -0700 -deb_date = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) - + date = time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))) developer = ARGUMENTS.get('DEVELOPER') if not developer: @@ -112,44 +78,42 @@ if not developer: developer = os.environ.get(variable) if developer: break + if os.environ.get('SOURCE_DATE_EPOCH'): + developer = '_reproducible' build_system = ARGUMENTS.get('BUILD_SYSTEM') if not build_system: - import socket - build_system = socket.gethostname().split('.')[0] + if os.environ.get('SOURCE_DATE_EPOCH'): + build_system = '_reproducible' + else: + build_system = socket.gethostname().split('.')[0] version = ARGUMENTS.get('VERSION', '') if not version: version = default_version -hg_status_lines = [] +git_status_lines = [] -if hg: - cmd = "%s status --all 2> /dev/null" % hg - hg_status_lines = os.popen(cmd, "r").readlines() +if git: + cmd = "%s ls-files 2> /dev/null" % git + git_status_lines = os.popen(cmd, "r").readlines() revision = ARGUMENTS.get('REVISION', '') def generate_build_id(revision): return revision -if not revision and hg: - hg_heads = os.popen("%s heads 2> /dev/null" % hg, "r").read() - cs = re.search('changeset:\s+(\S+)', hg_heads) - if cs: - revision = cs.group(1) - b = re.search('branch:\s+(\S+)', hg_heads) - if b: - revision = b.group(1) + ':' + revision - def generate_build_id(revision): - result = revision - if [l for l in hg_status_lines if l[0] in 'AMR!']: - result = result + '[MODIFIED]' - return result +if not revision and git: + git_hash = os.popen("%s rev-parse HEAD 2> /dev/null" % git, "r").read().strip() + def generate_build_id(revision): + result = git_hash + if [l for l in git_status_lines if 'modified' in l]: + result = result + '[MODIFIED]' + return result + revision = git_hash checkpoint = ARGUMENTS.get('CHECKPOINT', '') if checkpoint: if checkpoint == 'd': - import time checkpoint = time.strftime('%Y%m%d', time.localtime(time.time())) elif checkpoint == 'r': checkpoint = 'r' + revision @@ -162,31 +126,12 @@ if build_id is None: else: build_id = '' -import os.path -import distutils.command - -no_winpack_templates = not os.path.exists(os.path.join(os.path.split(distutils.command.__file__)[0],'wininst-9.0.exe')) -skip_win_packages = ARGUMENTS.get('SKIP_WIN_PACKAGES',False) or no_winpack_templates - -if sys.version_info[0] > 2: - # TODO: Resolve this issue. Currently fails when run on windows with - # File "/opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/distutils/command/bdist_wininst.py", line 262, in create_exe - # cfgdata = cfgdata.encode("mbcs") - # LookupError: unknown encoding: mbcs - print("Temporary PY3: Skipping windows package builds") - skip_win_packages = True - -if skip_win_packages: - print("Skipping the build of Windows packages...") - -python_ver = sys.version[0:3] - # # Adding some paths to sys.path, this is mainly needed # for the doc toolchain. # addpaths = [os.path.abspath(os.path.join(os.getcwd(), 'bin')), - os.path.abspath(os.path.join(os.getcwd(), 'QMTest'))] + os.path.abspath(os.path.join(os.getcwd(), 'testing/framework'))] for a in addpaths: if a not in sys.path: sys.path.append(a) @@ -213,7 +158,8 @@ command_line_variables = [ ("BUILD_SYSTEM=", "The system on which the packages were built. " + "The default is whatever hostname is returned " + - "by socket.gethostname()."), + "by socket.gethostname(). If SOURCE_DATE_EPOCH " + + "env var is set, '_reproducible' is the default."), ("CHECKPOINT=", "The specific checkpoint release being packaged, " + "which will be appended to the VERSION string. " + @@ -231,11 +177,13 @@ command_line_variables = [ ("DEVELOPER=", "The developer who created the packages. " + "The default is the first set environment " + - "variable from the list $USERNAME, $LOGNAME, $USER."), + "variable from the list $USERNAME, $LOGNAME, $USER." + + "If the SOURCE_DATE_EPOCH env var is set, " + + "'_reproducible' is the default."), ("REVISION=", "The revision number of the source being built. " + - "The default is the Subversion revision returned " + - "'hg heads', with an appended string of " + + "The default is the git hash returned " + + "'git rev-parse HEAD', with an appended string of " + "'[MODIFIED]' if there are any changes in the " + "working copy."), @@ -243,35 +191,24 @@ command_line_variables = [ "is the hard-coded value '%s' " % default_version + "from this SConstruct file."), - ("SKIP_WIN_PACKAGES=", "If set, skip building win32 and win64 packages."), ] Default('.', build_dir) packaging_flavors = [ - ('deb', "A .deb package. (This is currently not supported.)"), - - ('rpm', "A RedHat Package Manager file."), - ('tar-gz', "The normal .tar.gz file for end-user installation."), - - ('src-tar-gz', "A .tar.gz file containing all the source " + - "(including tests and documentation)."), - ('local-tar-gz', "A .tar.gz file for dropping into other software " + "for local use."), - ('zip', "The normal .zip file for end-user installation."), - + ('local-zip', "A .zip file for dropping into other software " + + "for local use."), + ('src-tar-gz', "A .tar.gz file containing all the source " + + "(including tests and documentation)."), ('src-zip', "A .zip file containing all the source " + "(including tests and documentation)."), - ('local-zip', "A .zip file for dropping into other software " + - "for local use."), ] -test_deb_dir = os.path.join(build_dir, "test-deb") -test_rpm_dir = os.path.join(build_dir, "test-rpm") test_tar_gz_dir = os.path.join(build_dir, "test-tar-gz") test_src_tar_gz_dir = os.path.join(build_dir, "test-src-tar-gz") test_local_tar_gz_dir = os.path.join(build_dir, "test-local-tar-gz") @@ -293,7 +230,6 @@ else: -import textwrap indent_fmt = ' %-26s ' @@ -329,137 +265,13 @@ for variable, help_text in command_line_variables: -zcat = 'gzip -d -c' - -# -# Figure out if we can handle .zip files. -# -zipit = None -unzipit = None -try: - import zipfile - - def zipit(env, target, source): - print("Zipping %s:" % str(target[0])) - def visit(arg, dirname, filenames): - for filename in filenames: - path = os.path.join(dirname, filename) - if os.path.isfile(path): - arg.write(path) - # default ZipFile compression is ZIP_STORED - zf = zipfile.ZipFile(str(target[0]), 'w', compression=zipfile.ZIP_DEFLATED) - olddir = os.getcwd() - os.chdir(env['CD']) - try: - for dirname, dirnames, filenames in os.walk(env['PSV']): - visit(zf, dirname, filenames) - finally: - os.chdir(olddir) - zf.close() - - def unzipit(env, target, source): - print("Unzipping %s:" % str(source[0])) - zf = zipfile.ZipFile(str(source[0]), 'r') - for name in zf.namelist(): - dest = os.path.join(env['UNPACK_ZIP_DIR'], name) - dir = os.path.dirname(dest) - try: - os.makedirs(dir) - except: - pass - print(dest,name) - # if the file exists, then delete it before writing - # to it so that we don't end up trying to write to a symlink: - if os.path.isfile(dest) or os.path.islink(dest): - os.unlink(dest) - if not os.path.isdir(dest): - with open(dest, 'wb') as fp: - fp.write(zf.read(name)) - -except ImportError: - if unzip and zip: - zipit = "cd $CD && $ZIP $ZIPFLAGS $( ${TARGET.abspath} $) $PSV" - unzipit = "$UNZIP $UNZIPFLAGS $SOURCES" - - -def SCons_revision(target, source, env): - """Interpolate specific values from the environment into a file. - - This is used to copy files into a tree that gets packaged up - into the source file package. - """ - t = str(target[0]) - s = source[0].rstr() - - try: - with open(s, 'r') as fp: - contents = fp.read() - - - # Note: We construct the __*__ substitution strings here - # so that they don't get replaced when this file gets - # copied into the tree for packaging. - contents = contents.replace('__BUILD' + '__', env['BUILD']) - contents = contents.replace('__BUILDSYS' + '__', env['BUILDSYS']) - contents = contents.replace('__COPYRIGHT' + '__', env['COPYRIGHT']) - contents = contents.replace('__DATE' + '__', env['DATE']) - contents = contents.replace('__DEB_DATE' + '__', env['DEB_DATE']) - - contents = contents.replace('__DEVELOPER' + '__', env['DEVELOPER']) - contents = contents.replace('__FILE' + '__', str(source[0]).replace('\\', '/')) - contents = contents.replace('__MONTH_YEAR'+ '__', env['MONTH_YEAR']) - contents = contents.replace('__REVISION' + '__', env['REVISION']) - contents = contents.replace('__VERSION' + '__', env['VERSION']) - contents = contents.replace('__NULL' + '__', '') - open(t, 'w').write(contents) - except UnicodeDecodeError as e: - print("Error decoding file:%s just copying no revision edit") - with open(s, 'rb') as fp: - contents = fp.read() - open(t, 'wb').write(contents) - - - os.chmod(t, os.stat(s)[0]) - revaction = SCons_revision revbuilder = Builder(action = Action(SCons_revision, varlist=['COPYRIGHT', 'VERSION'])) -def soelim(target, source, env): - """ - Interpolate files included in [gnt]roff source files using the - .so directive. - - This behaves somewhat like the soelim(1) wrapper around groff, but - makes us independent of whether the actual underlying implementation - includes an soelim() command or the corresponding command-line option - to groff(1). The key behavioral difference is that this doesn't - recursively include .so files from the include file. Not yet, anyway. - """ - t = str(target[0]) - s = str(source[0]) - dir, f = os.path.split(s) - tfp = open(t, 'w') - sfp = open(s, 'r') - for line in sfp.readlines(): - if line[:4] in ['.so ', "'so "]: - sofile = os.path.join(dir, line[4:-1]) - tfp.write(open(sofile, 'r').read()) - else: - tfp.write(line) - sfp.close() - tfp.close() - -def soscan(node, env, path): - c = node.get_text_contents() - return re.compile(r"^[\.']so\s+(\S+)", re.M).findall(c) -soelimbuilder = Builder(action = Action(soelim), - source_scanner = Scanner(soscan)) - -# When copying local files from a Repository (Aegis), -# just make copies, don't symlink them. +# Just make copies, don't symlink them. SetOption('duplicate', 'copy') env = Environment( @@ -486,11 +298,6 @@ env = Environment( ZCAT = zcat, - RPMBUILD = rpmbuild, - RPM2CPIO = 'rpm2cpio', - - TEST_DEB_DIR = test_deb_dir, - TEST_RPM_DIR = test_rpm_dir, TEST_SRC_TAR_GZ_DIR = test_src_tar_gz_dir, TEST_SRC_ZIP_DIR = test_src_zip_dir, TEST_TAR_GZ_DIR = test_tar_gz_dir, @@ -524,19 +331,18 @@ Version_values = [Value(version), Value(build_id)] # separate packages. # -from distutils.sysconfig import get_python_lib; +from distutils.sysconfig import get_python_lib python_scons = { 'pkg' : 'python-' + project, 'src_subdir' : 'engine', 'inst_subdir' : get_python_lib(), - 'rpm_dir' : '/usr/lib/scons', 'debian_deps' : [ 'debian/changelog', 'debian/compat', - 'debian/control', + 'debian/control', 'debian/copyright', 'debian/dirs', 'debian/docs', @@ -557,67 +363,16 @@ python_scons = { 'buildermap' : {}, - 'extra_rpm_files' : [], - 'explicit_deps' : { 'SCons/__init__.py' : Version_values, }, } -# Figure out the name of a .egg-info file that might be generated -# as part of the RPM package. There are two complicating factors. -# -# First, the RPM spec file we generate will just execute "python", not -# necessarily the one in sys.executable. If *that* version of python has -# a distutils that knows about Python eggs, then setup.py will generate a -# .egg-info file, so we have to execute any distutils logic in a subshell. -# -# Second, we can't just have the subshell check for the existence of the -# distutils.command.install_egg_info module and generate the expected -# file name by hand, the way we used to, because different systems can -# have slightly different .egg-info naming conventions. (Specifically, -# Ubuntu overrides the default behavior to remove the Python version -# string from the .egg-info file name.) The right way to do this is to -# actually call into the install_egg_info() class to have it generate -# the expected name for us. -# -# This is all complicated enough that we do it by writing an in-line -# script to a temporary file and then feeding it to a separate invocation -# of "python" to tell us the actual name of the generated .egg-info file. - -print_egg_info_name = """ -try: - from distutils.dist import Distribution - from distutils.command.install_egg_info import install_egg_info -except ImportError: - pass -else: - dist = Distribution({'name' : "scons", 'version' : '%s'}) - i = install_egg_info(dist) - i.finalize_options() - import os.path - print(os.path.split(i.outputs[0])[1]) -""" % version - -try: - fd, tfname = tempfile.mkstemp() - tfp = os.fdopen(fd, "w") - tfp.write(print_egg_info_name) - tfp.close() - egg_info_file = os.popen("python %s" % tfname).read()[:-1] - if egg_info_file: - python_scons['extra_rpm_files'].append(egg_info_file) -finally: - try: - os.unlink(tfname) - except EnvironmentError: - pass scons_script = { 'pkg' : project + '-script', 'src_subdir' : 'script', 'inst_subdir' : 'bin', - 'rpm_dir' : '/usr/bin', 'debian_deps' : [ 'debian/changelog', @@ -648,13 +403,6 @@ scons_script = { 'buildermap' : {}, - 'extra_rpm_files' : [ - 'scons-' + version, - 'sconsign-' + version, - 'scons-time-' + version, - 'scons-configure-cache-' + version, - ], - 'explicit_deps' : { 'scons' : Version_values, 'sconsign' : Version_values, @@ -685,7 +433,6 @@ scons = { 'sconsign.1', 'scons-time.1', 'script/scons.bat', - #'script/scons-post-install.py', 'setup.cfg', 'setup.py', ], @@ -759,13 +506,13 @@ for p in [ scons ]: # destination files. # manifest_in = File(os.path.join(src, 'MANIFEST.in')).rstr() - src_files = bootstrap.parseManifestLines(src, open(manifest_in).readlines()) + src_files = bootstrap.parseManifestLines(src, manifest_in) raw_files = src_files[:] dst_files = src_files[:] - rpm_files = [] MANIFEST_in_list = [] + if 'subpkgs' in p: # # This package includes some sub-packages. Read up their @@ -777,23 +524,13 @@ for p in [ scons ]: ssubdir = sp['src_subdir'] isubdir = p['subinst_dirs'][sp['pkg']] - MANIFEST_in = File(os.path.join(src, ssubdir, 'MANIFEST.in')).rstr() MANIFEST_in_list.append(MANIFEST_in) - files = bootstrap.parseManifestLines(os.path.join(src, ssubdir), open(MANIFEST_in).readlines()) + files = bootstrap.parseManifestLines(os.path.join(src, ssubdir), MANIFEST_in) raw_files.extend(files) src_files.extend([os.path.join(ssubdir, x) for x in files]) - - for f in files: - r = os.path.join(sp['rpm_dir'], f) - rpm_files.append(r) - if f[-3:] == ".py": - rpm_files.append(r + 'c') - for f in sp.get('extra_rpm_files', []): - r = os.path.join(sp['rpm_dir'], f) - rpm_files.append(r) files = [os.path.join(isubdir, x) for x in files] dst_files.extend(files) for k, f in sp['filemap'].items(): @@ -814,7 +551,7 @@ for p in [ scons ]: # # Now run everything in src_file through the sed command we - # concocted to expand SConstruct, 3.0.0, etc. + # concocted to expand SConstruct, 3.0.5, etc. # for b in src_files: s = p['filemap'].get(b, b) @@ -855,12 +592,6 @@ for p in [ scons ]: distutils_formats = [] distutils_targets = [] - - if not skip_win_packages: - win64_exe = os.path.join(build, 'dist', "%s.win-amd64.exe" % pkg_version) - win32_exe = os.path.join(build, 'dist', "%s.win32.exe" % pkg_version) - distutils_targets.extend([ win32_exe , win64_exe ]) - dist_distutils_targets = [] for target in distutils_targets: @@ -908,7 +639,7 @@ for p in [ scons ]: # Run setup.py in the unpacked subdirectory to "install" everything # into our build/test subdirectory. The runtest.py script will set # PYTHONPATH so that the tests only look under build/test-{package}, - # and under QMTest (for the testing modules TestCmd.py, TestSCons.py, + # and under testing/framework (for the testing modules TestCmd.py, TestSCons.py, # etc.). This makes sure that our tests pass with what # we really packaged, not because of something hanging around in # the development directory. @@ -978,7 +709,7 @@ for p in [ scons ]: # Run setup.py in the unpacked subdirectory to "install" everything # into our build/test subdirectory. The runtest.py script will set # PYTHONPATH so that the tests only look under build/test-{package}, - # and under QMTest (for the testing modules TestCmd.py, TestSCons.py, + # and under testing/framework (for the testing modules TestCmd.py, TestSCons.py, # etc.). This makes sure that our tests pass with what # we really packaged, not because of something hanging around in # the development directory. @@ -995,91 +726,6 @@ for p in [ scons ]: os.path.join(unpack_zip_dir, pkg_version, 'setup.py'), ]) - if not rpmbuild: - msg = "@echo \"Warning: Can not build 'rpm': no rpmbuild utility found\"" - AlwaysBuild(Alias('rpm', [], msg)) - else: - topdir = os.path.join(build, 'build', - 'bdist.' + platform, 'rpm') - - buildroot = os.path.join(build_dir, 'rpm-buildroot') - - BUILDdir = os.path.join(topdir, 'BUILD', pkg + '-' + version) - RPMSdir = os.path.join(topdir, 'RPMS', 'noarch') - SOURCESdir = os.path.join(topdir, 'SOURCES') - SPECSdir = os.path.join(topdir, 'SPECS') - SRPMSdir = os.path.join(topdir, 'SRPMS') - - specfile_in = os.path.join('rpm', "%s.spec.in" % pkg) - specfile = os.path.join(SPECSdir, "%s-1.spec" % pkg_version) - sourcefile = os.path.join(SOURCESdir, "%s.tar.gz" % pkg_version); - noarch_rpm = os.path.join(RPMSdir, "%s-1.noarch.rpm" % pkg_version) - src_rpm = os.path.join(SRPMSdir, "%s-1.src.rpm" % pkg_version) - - def spec_function(target, source, env): - """Generate the RPM .spec file from the template file. - - This fills in the %files portion of the .spec file with a - list generated from our MANIFEST(s), so we don't have to - maintain multiple lists. - """ - c = open(str(source[0]), 'r').read() - c = c.replace('__VERSION' + '__', env['VERSION']) - c = c.replace('__RPM_FILES' + '__', env['RPM_FILES']) - open(str(target[0]), 'w').write(c) - - rpm_files.sort() - rpm_files_str = "\n".join(rpm_files) + "\n" - rpm_spec_env = env.Clone(RPM_FILES = rpm_files_str) - rpm_spec_action = Action(spec_function, varlist=['RPM_FILES']) - rpm_spec_env.Command(specfile, specfile_in, rpm_spec_action) - - env.InstallAs(sourcefile, tar_gz) - Local(sourcefile) - - targets = [ noarch_rpm, src_rpm ] - cmd = "$RPMBUILD --define '_topdir $(%s$)' --buildroot %s -ba $SOURCES" % (topdir, buildroot) - if not os.path.isdir(BUILDdir): - cmd = ("$( mkdir -p %s; $)" % BUILDdir) + cmd - t = env.Command(targets, specfile, cmd) - env.Depends(t, sourcefile) - - dist_noarch_rpm = env.Install('$DISTDIR', noarch_rpm) - dist_src_rpm = env.Install('$DISTDIR', src_rpm) - Local(dist_noarch_rpm, dist_src_rpm) - AddPostAction(dist_noarch_rpm, Chmod(dist_noarch_rpm, 0o644)) - AddPostAction(dist_src_rpm, Chmod(dist_src_rpm, 0o644)) - - dfiles = [os.path.join(test_rpm_dir, 'usr', x) for x in dst_files] - env.Command(dfiles, - dist_noarch_rpm, - "$RPM2CPIO $SOURCES | (cd $TEST_RPM_DIR && cpio -id)") - - if dh_builddeb and fakeroot: - # Our Debian packaging builds directly into build/dist, - # so we don't need to Install() the .debs. - # The built deb is called just x.y.z, not x.y.z.final.0 so strip those off: - deb_version = version #'.'.join(version.split('.')[0:3]) - deb = os.path.join(build_dir, 'dist', "%s_%s_all.deb" % (pkg, deb_version)) - print("Building deb into %s (version=%s)"%(deb, deb_version)) - for d in p['debian_deps']: - b = env.SCons_revision(os.path.join(build, d), d) - env.Depends(deb, b) - Local(b) - env.Command(deb, build_src_files, [ - "cd %s && fakeroot make -f debian/rules PYTHON=$PYTHON BUILDDEB_OPTIONS=--destdir=../../build/dist binary" % build, - ]) - - old = os.path.join('lib', 'scons', '') - new = os.path.join('lib', 'python' + python_ver, 'site-packages', '') - def xxx(s, old=old, new=new): - if s[:len(old)] == old: - s = new + s[len(old):] - return os.path.join('usr', s) - dfiles = [os.path.join(test_deb_dir, xxx(x)) for x in dst_files] - env.Command(dfiles, - deb, - "dpkg --fsys-tarfile $SOURCES | (cd $TEST_DEB_DIR && tar -xf -)") # @@ -1101,11 +747,6 @@ for p in [ scons ]: commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY sdist --formats=%s" % \ ','.join(distutils_formats)) - if not skip_win_packages: - commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY bdist_wininst --plat-name=win32 --user-access-control auto") - - commands.append("$PYTHON $PYTHONFLAGS $SETUP_PY bdist_wininst --plat-name=win-amd64 --user-access-control auto") - env.Command(distutils_targets, build_src_files, commands) # @@ -1189,31 +830,17 @@ for p in [ scons ]: # Export('build_dir', 'env') -SConscript('QMTest/SConscript') +SConscript('testing/framework/SConscript') # # # +sp = env.Install(build_dir, 'runtest.py') +Local(sp) files = [ 'runtest.py', ] -def copy(target, source, env): - t = str(target[0]) - s = str(source[0]) - open(t, 'wb').write(open(s, 'rb').read()) - -for file in files: - # Guarantee that real copies of these files always exist in - # build/. If there's a symlink there, then this is an Aegis - # build and we blow them away now so that they'll get "built" later. - p = os.path.join(build_dir, file) - if os.path.islink(p): - os.unlink(p) - if not os.path.isabs(p): - p = '#' + p - sp = env.Command(p, file, copy) - Local(sp) # # Documentation. @@ -1223,22 +850,22 @@ Export('build_dir', 'env', 'whereis', 'revaction') SConscript('doc/SConscript') # -# If we're running in a Subversion working directory, pack up a complete +# If we're running in a Git working directory, pack up a complete # source archive from the project files and files in the change. # -sfiles = None -if hg_status_lines: - slines = [l for l in hg_status_lines if l[0] in 'ACM'] - sfiles = [l.split()[-1] for l in slines] + +sfiles = [l.split()[-1] for l in git_status_lines] +if git_status_lines: + # slines = [l for l in git_status_lines if 'modified:' in l] + # sfiles = [l.split()[-1] for l in slines] + pass else: - print("Not building in a Mercurial tree; skipping building src package.") + print("Not building in a Git tree; skipping building src package.") if sfiles: remove_patterns = [ - '.hgt/*', - '.svnt/*', - '*.aeignore', + '*.gitignore', '*.hgignore', 'www/*', ] @@ -1305,7 +932,7 @@ if sfiles: # Run setup.py in the unpacked subdirectory to "install" everything # into our build/test subdirectory. The runtest.py script will set # PYTHONPATH so that the tests only look under build/test-{package}, - # and under QMTest (for the testing modules TestCmd.py, + # and under testing/framework (for the testing modules TestCmd.py, # TestSCons.py, etc.). This makes sure that our tests pass with # what we really packaged, not because of something hanging around # in the development directory. @@ -1359,7 +986,7 @@ if sfiles: # Run setup.py in the unpacked subdirectory to "install" everything # into our build/test subdirectory. The runtest.py script will set # PYTHONPATH so that the tests only look under build/test-{package}, - # and under QMTest (for the testing modules TestCmd.py, + # and under testing/framework (for the testing modules TestCmd.py, # TestSCons.py, etc.). This makes sure that our tests pass with # what we really packaged, not because of something hanging # around in the development directory. @@ -1397,7 +1024,7 @@ if sfiles: for pf, help_text in packaging_flavors: Alias(pf, [ os.path.join(build_dir, 'test-'+pf), - os.path.join(build_dir, 'QMTest'), + os.path.join(build_dir, 'testing/framework'), os.path.join(build_dir, 'runtest.py'), ]) diff --git a/bin/SConsDoc.py b/bin/SConsDoc.py index cfb4e54..a6654c2 100644 --- a/bin/SConsDoc.py +++ b/bin/SConsDoc.py @@ -168,7 +168,7 @@ xsi = "http://www.w3.org/2001/XMLSchema-instance" # Header comment with copyright copyright_comment = """ -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -461,6 +461,8 @@ else: return self.decorateWithHeader(t) def validateXml(self, fpath, xmlschema_context): + retval = True + # Create validation context validation_context = xmlschema_context.schemaNewValidCtxt() # Set error/warning handlers @@ -470,17 +472,19 @@ else: doc = libxml2.readFile(fpath, None, libxml2.XML_PARSE_NOENT) doc.xincludeProcessFlags(libxml2.XML_PARSE_NOENT) err = validation_context.schemaValidateDoc(doc) - # Cleanup - doc.freeDoc() - del validation_context if err or eh.errors: for e in eh.errors: print(e.rstrip("\n")) + # import pdb; pdb.set_trace() print("%s fails to validate" % fpath) - return False + retval = False - return True + # Cleanup + doc.freeDoc() + del validation_context + + return retval def findAll(self, root, tag, ns=None, xpath_context=None, nsmap=None): if hasattr(root, 'xpathEval') and xpath_context: diff --git a/bin/SConsExamples.py b/bin/SConsExamples.py index 50c4c1a..7491c58 100644 --- a/bin/SConsExamples.py +++ b/bin/SConsExamples.py @@ -39,7 +39,7 @@ # env.Program('foo') # </file> # <file name="foo.c"> -# int main() { printf("foo.c\n"); } +# int main(void) { printf("foo.c\n"); } # </file> # </scons_example> # @@ -305,6 +305,11 @@ def createAllExampleOutputs(dpath): examples = readAllExampleInfos(dpath) total = len(examples) idx = 0 + + if len(sys.argv) > 1: + examples_to_run = sys.argv[1:] + examples = { k:v for k,v in examples.items() if k in examples_to_run } + for key, value in examples.items(): # Process all scons_output tags print("%.2f%s (%d/%d) %s" % (float(idx + 1) * 100.0 / float(total), @@ -411,8 +416,8 @@ def exampleNamesAreUnique(dpath): # # ############################################################### -sys.path.append(os.path.join(os.getcwd(), 'QMTest')) -sys.path.append(os.path.join(os.getcwd(), 'build', 'QMTest')) +sys.path.append(os.path.join(os.getcwd(), 'testing/framework')) +sys.path.append(os.path.join(os.getcwd(), 'build', 'testing/framework')) scons_py = os.path.join('bootstrap', 'src', 'script', 'scons.py') if not os.path.exists(scons_py): @@ -657,21 +662,27 @@ SConscript('SConstruct') """ # "Commands" that we will execute in our examples. -def command_scons(args, c, test, dict): +def command_scons(args, command, test, values): + """ + Fake scons command + """ save_vals = {} delete_keys = [] try: - ce = c.environment + ce = command.environment except AttributeError: pass else: - for arg in c.environment.split(): + for arg in command.environment.split(): key, val = arg.split('=') try: save_vals[key] = os.environ[key] except KeyError: delete_keys.append(key) os.environ[key] = val + + test.write(test.workpath('WORK/SConstruct_created'), Stdin % values) + test.run(interpreter=sys.executable, program=scons_py, # We use ToolSurrogates to capture win32 output by "building" @@ -681,7 +692,7 @@ def command_scons(args, c, test, dict): # Visual C installed. arguments='--warn=no-visual-c-missing -f - ' + ' '.join(args), chdir=test.workpath('WORK'), - stdin=Stdin % dict) + stdin=Stdin % values) os.environ.update(save_vals) for key in delete_keys: del(os.environ[key]) @@ -698,7 +709,7 @@ def command_scons(args, c, test, dict): # sys.stderr.write(err) return lines -def command_touch(args, c, test, dict): +def command_touch(args, command, test, values): if args[0] == '-t': t = int(time.mktime(time.strptime(args[1], '%Y%m%d%H%M'))) times = (t, t) @@ -714,7 +725,7 @@ def command_touch(args, c, test, dict): os.utime(file, times) return [] -def command_edit(args, c, test, dict): +def command_edit(args, c, test, values): if c.edit is None: add_string = 'void edit(void) { ; }\n' else: @@ -728,7 +739,7 @@ def command_edit(args, c, test, dict): open(file, 'wb').write(contents + add_string) return [] -def command_ls(args, c, test, dict): +def command_ls(args, c, test, values): def ls(a): try: return [' '.join(sorted([x for x in os.listdir(a) if x[0] != '.']))] @@ -743,7 +754,7 @@ def command_ls(args, c, test, dict): else: return ls(test.workpath('WORK')) -def command_sleep(args, c, test, dict): +def command_sleep(args, c, test, values): time.sleep(int(args[0])) CommandDict = { @@ -754,17 +765,19 @@ CommandDict = { 'sleep' : command_sleep, } -def ExecuteCommand(args, c, t, dict): +def ExecuteCommand(args, c, t, values): try: func = CommandDict[args[0]] except KeyError: - func = lambda args, c, t, dict: [] - return func(args[1:], c, t, dict) + func = lambda args, c, t, values: [] + return func(args[1:], c, t, values) def create_scons_output(e): - # The real raison d'etre for this script, this is where we - # actually execute SCons to fetch the output. + """ + The real raison d'etre for this script, this is where we + actually execute SCons to fetch the output. + """ # Loop over all outputs for the example for o in e.outputs: @@ -837,37 +850,37 @@ def create_scons_output(e): sroot = stf.newEtreeNode("screen", True) curchild = None content = "" - for c in o.commands: + for command in o.commands: content += Prompt[o.os] if curchild is not None: - if not c.output: + if not command.output: # Append content as tail curchild.tail = content content = "\n" # Add new child for userinput tag curchild = stf.newEtreeNode("userinput") - d = c.cmd.replace('__ROOT__', '') + d = command.cmd.replace('__ROOT__', '') curchild.text = d sroot.append(curchild) else: - content += c.output + '\n' + content += command.output + '\n' else: - if not c.output: + if not command.output: # Add first text to root sroot.text = content content = "\n" # Add new child for userinput tag curchild = stf.newEtreeNode("userinput") - d = c.cmd.replace('__ROOT__', '') + d = command.cmd.replace('__ROOT__', '') curchild.text = d sroot.append(curchild) else: - content += c.output + '\n' + content += command.output + '\n' # Execute command and capture its output - cmd_work = c.cmd.replace('__ROOT__', t.workpath('ROOT')) + cmd_work = command.cmd.replace('__ROOT__', t.workpath('ROOT')) args = cmd_work.split() - lines = ExecuteCommand(args, c, t, {'osname':o.os, 'tools':o.tools}) - if not c.output and lines: + lines = ExecuteCommand(args, command, t, {'osname':o.os, 'tools':o.tools}) + if not command.output and lines: ncontent = '\n'.join(lines) ncontent = address_re.sub(r' at 0x700000>', ncontent) ncontent = engine_re.sub(r' File "bootstrap/src/engine/SCons/', ncontent) diff --git a/bin/import-test.py b/bin/import-test.py index 168208f..4fc4f06 100644 --- a/bin/import-test.py +++ b/bin/import-test.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # tree2test.py - turn a directory tree into TestSCons code # @@ -25,7 +25,7 @@ # """ triple-quotes will need to have their contents edited by hand. # -__revision__ = "bin/import-test.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "bin/import-test.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import sys diff --git a/bin/linecount.py b/bin/linecount.py index 75723d0..57a64e2 100644 --- a/bin/linecount.py +++ b/bin/linecount.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Count statistics about SCons test and source files. This must be run # against a fully-populated tree (for example, one that's been freshly @@ -23,7 +23,7 @@ # interesting one for most purposes. from __future__ import division, print_function -__revision__ = "bin/linecount.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "bin/linecount.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path diff --git a/bin/restore.sh b/bin/restore.sh index 49c95bc..5fcdb08 100644 --- a/bin/restore.sh +++ b/bin/restore.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh # -# Simple hack script to restore __revision__, __COPYRIGHT_, 3.0.0 +# Simple hack script to restore __revision__, __COPYRIGHT_, 3.0.5 # and other similar variables to what gets checked in to source. This # comes in handy when people send in diffs based on the released source. # @@ -22,9 +22,9 @@ header() { for i in `find $DIRS -name '*.py'`; do header $i ed $i <<EOF -g/Copyright (c) 2001.*SCons Foundation/s//Copyright (c) 2001 - 2017 The SCons Foundation/p +g/Copyright (c) 2001.*SCons Foundation/s//Copyright (c) 2001 - 2019 The SCons Foundation/p w -/^__revision__ = /s/= .*/= "bin/restore.sh rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog"/p +/^__revision__ = /s/= .*/= "bin/restore.sh 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog"/p w q EOF @@ -33,9 +33,9 @@ done for i in `find $DIRS -name 'scons.bat'`; do header $i ed $i <<EOF -g/Copyright (c) 2001.*SCons Foundation/s//Copyright (c) 2001 - 2017 The SCons Foundation/p +g/Copyright (c) 2001.*SCons Foundation/s//Copyright (c) 2001 - 2019 The SCons Foundation/p w -/^@REM src\/script\/scons.bat/s/@REM .* knight/@REM bin/restore.sh rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog/p +/^@REM src\/script\/scons.bat/s/@REM .* knight/@REM bin/restore.sh 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog/p w q EOF @@ -44,13 +44,13 @@ done for i in `find $DIRS -name '__init__.py' -o -name 'scons.py' -o -name 'sconsign.py'`; do header $i ed $i <<EOF -/^__version__ = /s/= .*/= "3.0.0"/p +/^__version__ = /s/= .*/= "3.0.5"/p w -/^__build__ = /s/= .*/= "rel_3.0.0:4395:8972f6a2f699"/p +/^__build__ = /s/= .*/= "103260fce95bf5db1c35fb2371983087d85dd611"/p w -/^__buildsys__ = /s/= .*/= "ubuntu-16"/p +/^__buildsys__ = /s/= .*/= "Williams-MBP-2"/p w -/^__date__ = /s/= .*/= "2017/09/18 12:59:24"/p +/^__date__ = /s/= .*/= "2019-07-13 18:25:30"/p w /^__developer__ = /s/= .*/= "bdbaddog"/p w @@ -61,7 +61,7 @@ done for i in `find $DIRS -name 'setup.py'`; do header $i ed $i <<EOF -/^ *version = /s/= .*/= "3.0.0",/p +/^ *version = /s/= .*/= "3.0.5",/p w q EOF @@ -70,11 +70,11 @@ done for i in `find $DIRS -name '*.txt'`; do header $i ed $i <<EOF -g/Copyright (c) 2001.*SCons Foundation/s//Copyright (c) 2001 - 2017 The SCons Foundation/p +g/Copyright (c) 2001.*SCons Foundation/s//Copyright (c) 2001 - 2019 The SCons Foundation/p w -/# [^ ]* 0.96.[CD][0-9]* [0-9\/]* [0-9:]* knight$/s/.*/# bin/restore.sh rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog/p +/# [^ ]* 0.96.[CD][0-9]* [0-9\/]* [0-9:]* knight$/s/.*/# bin/restore.sh 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog/p w -/Version [0-9][0-9]*\.[0-9][0-9]*/s//Version 3.0.0/p +/Version [0-9][0-9]*\.[0-9][0-9]*/s//Version 3.0.5/p w q EOF @@ -83,7 +83,7 @@ done for i in `find $DIRS -name '*.xml'`; do header $i ed $i <<EOF -g/Copyright (c) 2001.*SCons Foundation/s//Copyright (c) 2001 - 2017 The SCons Foundation/p +g/Copyright (c) 2001.*SCons Foundation/s//Copyright (c) 2001 - 2019 The SCons Foundation/p w q EOF diff --git a/bin/scons-cdist b/bin/scons-cdist deleted file mode 100644 index 58b1bae..0000000 --- a/bin/scons-cdist +++ /dev/null @@ -1,272 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2005 The SCons Foundation -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -PROG=`basename $0` -NOARGFLAGS="afhlnqrstz" -ARGFLAGS="p:" -ALLFLAGS="${NOARGFLAGS}${ARGFLAGS}" -USAGE="Usage: ${PROG} [-${NOARGFLAGS}] [-p project] change" - -HELP="$USAGE - - -a Update the latest Aegis baseline (aedist) file. - -f Force update, skipping up-front sanity check. - -h Print this help message and exit. - -l Update the local CVS repository. - -n Don't execute, just echo commands. - -p project Set the Aegis project. - -q Quiet, don't print commands before executing them. - -r Rsync the Aegis repository to SourceForge. - -s Update the sourceforge.net CVS repository. - -t Update the tigris.org CVS repository. - -z Update the latest .tar.gz and .zip files. -" - -DO="" -PRINT="echo" -EXECUTE="eval" -SANITY_CHECK="yes" - -while getopts $ALLFLAGS FLAG; do - case $FLAG in - a | l | r | s | t | z ) - DO="${DO}${FLAG}" - ;; - f ) - SANITY_CHECK="no" - ;; - h ) - echo "${HELP}" - exit 0 - ;; - n ) - EXECUTE=":" - ;; - p ) - AEGIS_PROJECT="${OPTARG}" - ;; - q ) - PRINT=":" - ;; - * ) - echo "FLAG = ${FLAG}" >&2 - echo "${USAGE}" >&2 - exit 1 - ;; - esac -done - -shift `expr ${OPTIND} - 1` - -if test "X$1" = "X"; then - echo "${USAGE}" >&2 - exit 1 -fi - -if test "X${AEGIS_PROJECT}" = "X"; then - echo "$PROG: No AEGIS_PROJECT set." >&2 - echo "${USAGE}" >&2 - exit 1 -fi - -if test "X$DO" = "X"; then - DO="alrstz" -fi - -cmd() -{ - $PRINT "$*" - $EXECUTE "$*" -} - -CHANGE=$1 - -if test "X${SANITY_CHECK}" = "Xyes"; then - SCM="cvs" - SCMROOT="/home/scons/CVSROOT/scons" - DELTA=`aegis -l -ter cd ${CHANGE} | sed -n 's/.*, Delta \([0-9]*\)\./\1/p'` - if test "x${DELTA}" = "x"; then - echo "${PROG}: Could not find delta for change ${CHANGE}." >&2 - echo "Has this finished integrating? Change ${CHANGE} not distributed." >&2 - exit 1 - fi - PREV_DELTA=`expr ${DELTA} - 1` - COMMAND="scons-scmcheck -D ${PREV_DELTA} -d q -p ${AEGIS_PROJECT} -s ${SCM} ${SCMROOT}" - $PRINT "${COMMAND}" - OUTPUT=`${COMMAND}` - if test "X${OUTPUT}" != "X"; then - echo "${PROG}: ${SCMROOT} is not up to date:" >&2 - echo "${OUTPUT}" >& 2 - echo "Did you skip any changes? Change ${CHANGE} not distributed." >&2 - exit 1 - fi -fi - -if test X$EXECUTE != "X:" -a "X$SSH_AGENT_PID" = "X"; then - eval `ssh-agent` - ssh-add - trap 'eval `ssh-agent -k`; exit' 0 1 2 3 15 -fi - -cd - -BASELINE=`aesub -p ${AEGIS_PROJECT} -c ${CHANGE} '${Project trunk_name}'` - -TMPBLAE="/tmp/${BASELINE}.ae" -TMPCAE="/tmp/${AEGIS_PROJECT}.C${CHANGE}.ae" - -# Original values for SourceForge. -#SFLOGIN="stevenknight" -#SFHOST="scons.sourceforge.net" -#SFDEST="/home/groups/s/sc/scons/htdocs" - -SCONSLOGIN="scons" -SCONSHOST="manam.pair.com" -#SCONSDEST="public_html/production" -SCONSDEST="public_ftp" - -# -# Copy the baseline .ae to the constant location on SourceForge. -# -case "${DO}" in -*a* ) - cmd "aedist -s -bl -p ${AEGIS_PROJECT} > ${TMPBLAE}" - cmd "scp ${TMPBLAE} ${SCONSLOGIN}@${SCONSHOST}:${SCONSDEST}/${BASELINE}.ae" - cmd "rm ${TMPBLAE}" - ;; -esac - -# -# Copy the latest .tar.gz and .zip files to the constant location on -# SourceForge. -# -case "${DO}" in -*z* ) - BUILD_DIST=`aegis -p ${AEGIS_PROJECT} -cd -bl`/build/dist - SCONS_SRC_TAR_GZ=`echo ${AEGIS_PROJECT} | sed 's/scons./scons-src-/'`*.tar.gz - SCONS_SRC_ZIP=`echo ${AEGIS_PROJECT} | sed 's/scons./scons-src-/'`*.zip - cmd "scp ${BUILD_DIST}/${SCONS_SRC_TAR_GZ} ${SCONSLOGIN}@${SCONSHOST}:${SCONSDEST}/scons-src-latest.tar.gz" - cmd "scp ${BUILD_DIST}/${SCONS_SRC_ZIP} ${SCONSLOGIN}@${SCONSHOST}:${SCONSDEST}/scons-src-latest.zip" -esac - -# -# Sync Aegis tree with SourceForge. -# -# Cribbed and modified from Peter Miller's same-named script in -# /home/groups/a/ae/aegis/aegis at SourceForge. -# -# Guide to what this does with rsync: -# -# --rsh=ssh use ssh for the transfer -# -l copy symlinks as symlinks -# -p preserve permissions -# -r recursive -# -t preserve times -# -z compress data -# --stats file transfer statistics -# --exclude exclude files matching the pattern -# --delete delete files that don't exist locally -# --delete-excluded delete files that match the --exclude patterns -# --progress show progress during the transfer -# -v verbose -# -# We no longer use the --stats option. -# -case "${DO}" in -*r* ) - LOCAL=/home/scons/scons - REMOTE=/home/groups/s/sc/scons/scons - cmd "/usr/bin/rsync --rsh='ssh -l stevenknight' \ - -l -p -r -t -z \ - --exclude build \ - --exclude '*,D' \ - --exclude '*.pyc' \ - --exclude aegis.log \ - --exclude '.sconsign*' \ - --delete --delete-excluded \ - --progress -v \ - ${LOCAL}/. scons.sourceforge.net:${REMOTE}/." - ;; -esac - -# -# Sync the CVS tree with the local repository. -# -case "${DO}" in -*l* ) - ( - export CVSROOT=/home/scons/CVSROOT/scons - #cmd "ae2cvs -X -aegis -p ${AEGIS_PROJECT} -c ${CHANGE} -u $HOME/SCons/baldmt.com/scons" - cmd "ae-cvs-ci ${AEGIS_PROJECT} ${CHANGE}" - ) - ;; -esac - -# -# Sync the Subversion tree with Tigris.org. -# -case "${DO}" in -*t* ) - ( - SVN=http://scons.tigris.org/svn/scons - case ${AEGIS_PROJECT} in - scons.0.96 ) - SVN_URL=${SVN}/branches/core - ;; - scons.0.96.513 ) - SVN_URL=${SVN}/branches/sigrefactor - ;; - * ) - echo "$PROG: Don't know SVN branch for '${AEGIS_PROJECT}'" >&2 - exit 1 - ;; - esac - SVN_CO_FLAGS="--username stevenknight" - #cmd "ae2cvs -X -aegis -p ${AEGIS_PROJECT} -c ${CHANGE} -u $HOME/SCons/tigris.org/scons" - cmd "ae-svn-ci ${AEGIS_PROJECT} ${CHANGE} ${SVN_URL} ${SVN_CO_FLAGS}" - ) - ;; -esac - -# -# Sync the CVS tree with SourceForge. -# -case "${DO}" in -*s* ) - ( - export CVS_RSH=ssh - export CVSROOT=:ext:stevenknight@scons.cvs.sourceforge.net:/cvsroot/scons - #cmd "ae2cvs -X -aegis -p ${AEGIS_PROJECT} -c ${CHANGE} -u $HOME/SCons/sourceforge.net/scons" - cmd "ae-cvs-ci ${AEGIS_PROJECT} ${CHANGE}" - ) - ;; -esac - -# -# Send the change .ae to the scons-aedist mailing list -# -# The subject requires editing by hand... -# -#aedist -s -p ${AEGIS_PROJECT} ${CHANGE} > ${TMPCAE} -#aegis -l -p ${AEGIS_PROJECT} -c ${CHANGE} cd | -# pine -attach_and_delete ${TMPCAE} scons-aedist@lists.sourceforge.net diff --git a/bin/scons_dev_master.py b/bin/scons_dev_master.py index 3d67cb5..4b1160f 100644 --- a/bin/scons_dev_master.py +++ b/bin/scons_dev_master.py @@ -11,11 +11,12 @@ import sys from Command import CommandRunner, Usage INITIAL_PACKAGES = [ - 'mercurial', + 'git', ] INSTALL_PACKAGES = [ 'wget', + 'xz-utils', ] PYTHON_PACKAGES = [ @@ -41,6 +42,7 @@ BUILDING_PACKAGES = [ 'python-epydoc', 'rpm', 'tar', + 'lynx' # additional packages that Bill Deegan's web page suggests #'docbook-to-man', @@ -60,8 +62,7 @@ DOCUMENTATION_PACKAGES = [ 'gcc-doc', 'pkg-config', 'python-doc', - 'sun-java5-doc', - 'sun-java6-doc', + 'openjdk-8-doc', 'swig-doc', 'texlive-doc', ] @@ -73,18 +74,20 @@ TESTING_PACKAGES = [ 'flex', 'g++', 'gcc', - 'gcj', + # not on ubuntu 18.04 + # 'gcj', + # 'hg', 'ghostscript', -# 'libgcj7-dev', 'm4', 'openssh-client', 'openssh-server', 'python-profiler', 'python-all-dev', + 'python3-all-dev', + 'pypy-dev', 'rcs', 'rpm', -# 'sun-java5-jdk', - 'sun-java6-jdk', + 'openjdk-8-jdk', 'swig', 'texlive-base-bin', 'texlive-extra-utils', @@ -131,7 +134,7 @@ Usage: scons_dev_master.py [-hnqy] [--password PASSWORD] [--username USER] buildbot Install packages for running BuildBot """ - scons_url = 'https://bdbaddog@bitbucket.org/scons/scons' + scons_url = 'https://github.com/SCons/scons.git' sudo = 'sudo' password = '""' username = 'guest' @@ -180,13 +183,15 @@ Usage: scons_dev_master.py [-hnqy] [--password PASSWORD] [--username USER] cmd.run('%(sudo)s apt-get %(yesflag)s upgrade') elif arg == 'checkout': cmd.run('%(sudo)s apt-get %(yesflag)s install %(initial_packages)s') - cmd.run('hg clone" %(scons_url)s') + cmd.run('git clone" %(scons_url)s') elif arg == 'building': cmd.run('%(sudo)s apt-get %(yesflag)s install %(building_packages)s') elif arg == 'docs': cmd.run('%(sudo)s apt-get %(yesflag)s install %(doc_packages)s') elif arg == 'testing': cmd.run('%(sudo)s apt-get %(yesflag)s install %(testing_packages)s') + #TODO: maybe copy ipkg-build from openwrt git + #cmd.run('%(sudo)s wget https://raw.githubusercontent.com/openwrt/openwrt/master/scripts/ipkg-build SOMEWHERE') elif arg == 'buildbot': cmd.run('%(sudo)s apt-get %(yesflag)s install %(buildbot_packages)s') elif arg == 'python-versions': diff --git a/bin/time-scons.py b/bin/time-scons.py index b7d8ef1..c5cd0cc 100644 --- a/bin/time-scons.py +++ b/bin/time-scons.py @@ -43,7 +43,7 @@ TimeSCons_revision = 4569 # The pieces of the TimeSCons infrastructure that are necessary to # produce consistent timings, even when the rest of the tree is from # an earlier revision that doesn't have these pieces. -TimeSCons_pieces = ['QMTest', 'timings', 'runtest.py'] +TimeSCons_pieces = ['testing/framework', 'timings', 'runtest.py'] class CommandRunner(object): diff --git a/bin/update-release-info.py b/bin/update-release-info.py index a4096d1..de3d164 100644 --- a/bin/update-release-info.py +++ b/bin/update-release-info.py @@ -20,10 +20,10 @@ in various files: - The RELEASE header line in src/CHANGES.txt and src/Announce.txt. - The version string at the top of src/RELEASE.txt. - The version string in the 'default_version' variable in SConstruct - and QMTest/TestSCons.py. - - The copyright years in SConstruct and QMTest/TestSCons.py. + and testing/framework/TestSCons.py. + - The copyright years in SConstruct and testing/framework/TestSCons.py. - The month and year (used for documentation) in SConstruct. - - The unsupported and deprecated Python floors in QMTest/TestSCons.py + - The unsupported and deprecated Python floors in testing/framework/TestSCons.py and src/engine/SCons/Script/Main.py - The version string in the filenames in README. @@ -36,7 +36,7 @@ In 'post' mode, files are prepared for the next release cycle: src/Announce.txt. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -58,7 +58,7 @@ In 'post' mode, files are prepared for the next release cycle: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function -__revision__ = "bin/update-release-info.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "bin/update-release-info.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import sys @@ -81,7 +81,10 @@ else: # Get configuration information config = dict() -exec(open('ReleaseConfig').read(), globals(), config) +with open('ReleaseConfig') as f: + releaseconfig = f.read() +exec(releaseconfig, globals(), config) + try: version_tuple = config['version_tuple'] @@ -152,7 +155,8 @@ class UpdateFile(object): ''' if orig is None: orig = file try: - self.content = open(orig, 'r').read() + with open(orig, 'r') as f: + self.content = f.read() except IOError: # Couldn't open file; don't try to write anything in __del__ self.file = None @@ -180,8 +184,8 @@ class UpdateFile(object): # Determine the pattern to match a version - _rel_types = '(alpha|beta|candidate|final)' - match_pat = '\d+\.\d+\.\d+\.' + _rel_types + '\.(\d+|yyyymmdd)' + _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): @@ -198,14 +202,14 @@ class UpdateFile(object): 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) + 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 = '(Sun|Mon|Tue|Wed|Thu|Fri|Sat)' - _months = '(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oce|Nov|Dec)' - match_date = _days+', \d\d '+_months+' \d\d\d\d \d\d:\d\d:\d\d [+-]\d\d\d\d' + _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) def replace_date(self, replacement = new_date, count = 1): @@ -220,7 +224,8 @@ class UpdateFile(object): ''' if self.file is not None and self.content != self.orig: print('Updating ' + self.file + '...') - open(self.file, 'w').write(self.content) + with open(self.file, 'w') as f: + f.write(self.content) if mode == 'post': # Set up for the next release series. @@ -309,15 +314,15 @@ t.replace_assign('default_version', repr(version_string)) t = UpdateFile('README.rst') if DEBUG: t.file = '/tmp/README.rst' -t.sub('-' + t.match_pat + '\.', '-' + version_string + '.', count = 0) +t.sub('-' + t.match_pat + r'\.', '-' + version_string + '.', count = 0) for suf in ['tar', 'win32', 'zip', 'rpm', 'exe', 'deb']: - t.sub('-(\d+\.\d+\.\d+)\.%s' % suf, + t.sub(r'-(\d+\.\d+\.\d+)\.%s' % suf, '-%s.%s' % (version_string, suf), count = 0) -# Update QMTest/TestSCons.py +# Update testing/framework/TestSCons.py -t = UpdateFile(os.path.join('QMTest', 'TestSCons.py')) +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)) diff --git a/bin/upload-release-files.sh b/bin/upload-release-files.sh index c853bda..9a09206 100755 --- a/bin/upload-release-files.sh +++ b/bin/upload-release-files.sh @@ -19,17 +19,10 @@ SF_TOPDIR='/home/frs/project/scons' cd build/dist cp -f ../../src/CHANGES.txt ../../src/RELEASE.txt ../../src/Announce.txt ../../src/README.txt . -cp scons-$VERSION.win32.exe scons-$VERSION-setup.exe -cp scons-$VERSION.win-amd64.exe scons-$VERSION-amd64-setup.exe - set -x # Upload main scons release files: $RSYNC $RSYNCOPTS \ - scons-$VERSION-1.noarch.rpm \ - scons-$VERSION-1.src.rpm \ - scons-$VERSION-setup.exe \ - scons-$VERSION-amd64-setup.exe \ scons-$VERSION.tar.gz \ scons-$VERSION.zip \ Announce.txt CHANGES.txt RELEASE.txt \ @@ -42,12 +35,12 @@ $RSYNC $RSYNCOPTS \ Announce.txt CHANGES.txt RELEASE.txt \ $SF_USER@$SF_MACHINE:$SF_TOPDIR/scons-local/$VERSION/ -# Source packages: +Source packages: $RSYNC $RSYNCOPTS \ - scons-src-$VERSION.tar.gz \ - scons-src-$VERSION.zip \ - Announce.txt CHANGES.txt RELEASE.txt \ - $SF_USER@$SF_MACHINE:$SF_TOPDIR/scons-src/$VERSION/ + scons-src-$VERSION.tar.gz \ + scons-src-$VERSION.zip \ + Announce.txt CHANGES.txt RELEASE.txt \ + $SF_USER@$SF_MACHINE:$SF_TOPDIR/scons-src/$VERSION/ # Readme $RSYNC $RSYNCOPTS \ @@ -80,7 +73,7 @@ ssh scons@scons.org " cd .. rm latest; ln -s $VERSION latest rm production; ln -s $VERSION production - for f in HTML PDF EPUB PS TEXT; do rm \$f; ln -s $VERSION/\$f \$f; done + for f in HTML PDF EPUB PS TEXT; do rm -f \$f; ln -s $VERSION/\$f \$f; done " echo '*****' echo '***** Now manually update index.php, includes/versions.php and news-raw.xhtml on scons.org.' diff --git a/bin/xmlagenda.py b/bin/xmlagenda.py index fcfe53e..7091ee5 100755 --- a/bin/xmlagenda.py +++ b/bin/xmlagenda.py @@ -1,7 +1,9 @@ #!/usr/bin/env python -# Query the scons.tigris.org database for the issues of interest. -# The typical triage query is found on http://www.scons.org/wiki/BugParty +# Query gihub issue tracker for the issues of interest. +# The typical triage query is found on +# https://github.com/scons/scons/wiki/BugParty +# FIXME: this needs reworking for github, and wiki needs updating # Download the issues from Issuezilla as XML; this creates a file # named 'issues.xml'. Run this script in the dir containing diff --git a/bootstrap.py b/bootstrap.py index 58fde15..1629636 100755 --- a/bootstrap.py +++ b/bootstrap.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,6 +21,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +from __future__ import print_function import os import os.path @@ -74,15 +75,24 @@ the following SCons options: "eaten" by the bootstrap.py script. """ -def parseManifestLines(basedir, lines): - """ Scans the single lines of a MANIFEST file, - and returns the list of source files. - Has basic support for recursive globs '**', - filename wildcards of the form '*.xml' and - comment lines, starting with a '#'. +def parseManifestLines(basedir, manifest): + """ + Scans a MANIFEST file, and returns the list of source files. + + Has basic support for recursive globs '**', + filename wildcards of the form '*.xml' and + comment lines, starting with a '#'. + + :param basedir: base path to find files in. Note this does not + run in an SCons context so path must not need + further processing (e.g. no '#' signs) + :param manifest: path to manifest file + :returns: list of files """ sources = [] basewd = os.path.abspath(basedir) + with open(manifest) as m: + lines = m.readlines() for l in lines: if l.startswith('#'): # Skip comments @@ -107,38 +117,38 @@ def parseManifestLines(basedir, lines): def main(): script_dir = os.path.abspath(os.path.dirname(__file__)) - + bootstrap_dir = os.path.join(script_dir, 'bootstrap') - + pass_through_args = [] update_only = None - + requires_an_argument = 'bootstrap.py: %s requires an argument\n' - + search = [script_dir] - - def find(file, search=search): - for dir in search: - f = os.path.join(dir, file) - if os.path.exists(f): - return os.path.normpath(f) - sys.stderr.write("could not find `%s' in search path:\n" % file) + + def find(filename, search=search): + for dir_name in search: + filepath = os.path.join(dir_name, filename) + if os.path.exists(filepath): + return os.path.normpath(filepath) + sys.stderr.write("could not find `%s' in search path:\n" % filename) sys.stderr.write("\t" + "\n\t".join(search) + "\n") sys.exit(2) - + def must_copy(dst, src): if not os.path.exists(dst): return 1 return not filecmp.cmp(dst,src) - + # Note: We don't use the getopt module to process the command-line # arguments because we'd have to teach it about all of the SCons options. - + command_line_args = sys.argv[1:] - + while command_line_args: arg = command_line_args.pop(0) - + if arg == '--bootstrap_dir': try: bootstrap_dir = command_line_args.pop(0) @@ -147,11 +157,9 @@ def main(): sys.exit(1) elif arg[:16] == '--bootstrap_dir=': bootstrap_dir = arg[16:] - elif arg == '--bootstrap_force': def must_copy(dst, src): return 1 - elif arg == '--bootstrap_src': try: search.insert(0, command_line_args.pop(0)) @@ -160,10 +168,8 @@ def main(): sys.exit(1) elif arg[:16] == '--bootstrap_src=': search.insert(0, arg[16:]) - elif arg == '--bootstrap_update': update_only = 1 - elif arg in ('-C', '--directory'): try: dir = command_line_args.pop(0) @@ -176,51 +182,45 @@ def main(): os.chdir(arg[2:]) elif arg[:12] == '--directory=': os.chdir(arg[12:]) - else: pass_through_args.append(arg) - - + scons_py = os.path.join('src', 'script', 'scons.py') src_engine = os.path.join('src', 'engine') MANIFEST_in = find(os.path.join(src_engine, 'MANIFEST.in')) - MANIFEST_xml_in = find(os.path.join(src_engine, 'MANIFEST-xml.in')) manifest_files = [os.path.join(src_engine, x) - for x in parseManifestLines(os.path.join(script_dir, src_engine), - open(MANIFEST_in).readlines())] - - manifest_xml_files = [os.path.join(src_engine, x) - for x in parseManifestLines(os.path.join(script_dir, src_engine), - open(MANIFEST_xml_in).readlines())] - files = [ scons_py ] + manifest_files + manifest_xml_files - - for file in files: - src = find(file) - dst = os.path.join(bootstrap_dir, file) + for x in parseManifestLines(os.path.join(script_dir, src_engine), + MANIFEST_in)] + + files = [scons_py] + manifest_files + + for filename in files: + src = find(filename) + dst = os.path.join(bootstrap_dir, filename) if must_copy(dst, src): dir = os.path.split(dst)[0] if not os.path.isdir(dir): os.makedirs(dir) - try: os.unlink(dst) - except: pass + try: + os.unlink(dst) + except Exception as e: + pass + + shutil.copyfile(src, dst) - shutil.copyfile(src,dst) - if update_only: sys.exit(0) - - args = [ - sys.executable, - os.path.join(bootstrap_dir, scons_py) - ] + pass_through_args - + + args = [sys.executable, os.path.join(bootstrap_dir, scons_py)] + pass_through_args + sys.stdout.write(" ".join(args) + '\n') sys.stdout.flush() - + os.environ['SCONS_LIB_DIR'] = os.path.join(bootstrap_dir, src_engine) - + sys.exit(subprocess.Popen(args, env=os.environ).wait()) + if __name__ == "__main__": main() diff --git a/doc/SConscript b/doc/SConscript index 46d4533..fd518f9 100644 --- a/doc/SConscript +++ b/doc/SConscript @@ -3,7 +3,7 @@ # # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -63,6 +63,7 @@ env = env.Clone() build = os.path.join(build_dir, 'doc') + epydoc_cli = whereis('epydoc') gs = whereis('gs') lynx = whereis('lynx') @@ -130,8 +131,9 @@ if skip_doc: if not os.path.isdir(scdir): os.makedirs(scdir) - import datetime - today = datetime.date.today().strftime("%m/%d/%Y") + import time + today = time.strftime("%Y-%m-%d", + time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time())))) version = env.subst('$VERSION') for m in man_page_list: man, _ = os.path.splitext(m) @@ -324,7 +326,7 @@ else: # get included by the document XML files in the subdirectories. # manifest = File('MANIFEST').rstr() - src_files = bootstrap.parseManifestLines('.', open(manifest).readlines()) + src_files = bootstrap.parseManifestLines('.', manifest) for s in src_files: if not s: continue @@ -349,7 +351,7 @@ else: if not os.path.exists(os.path.join(build, doc, 'titlepage')): env.Execute(Mkdir(os.path.join(build, doc, 'titlepage'))) manifest = File(os.path.join(doc, 'MANIFEST')).rstr() - src_files = bootstrap.parseManifestLines(doc, open(manifest).readlines()) + src_files = bootstrap.parseManifestLines(doc, manifest) for s in src_files: if not s: continue @@ -569,12 +571,15 @@ if not epydoc_cli and not epydoc: else: # XXX Should be in common with reading the same thing in # the SConstruct file. - e = os.path.join('#src', 'engine') - manifest_in = File(os.path.join(e, 'MANIFEST.in')).rstr() - sources = bootstrap.parseManifestLines(e, open(manifest_in).readlines()) - sources = [x for x in sources if x.find('Platform') == -1] + # bootstrap.py runs outside of SCons, so need to process the path + e = Dir(os.path.join('#src', 'engine')).rstr() + sources = bootstrap.parseManifestLines(e, os.path.join(e, 'MANIFEST.in')) + + # Omit some files: + # + # Don't omit Platform as we need Platform.virtualenv for the examples to be run + # sources = [x for x in sources if x.find('Platform') == -1] sources = [x for x in sources if x.find('Tool') == -1] - # XXX sources = [x for x in sources if x.find('Options') == -1] e = os.path.join(build, '..', 'scons', 'engine') @@ -586,7 +591,7 @@ else: tar_deps.append(htmldir) tar_list.append(htmldir) - if not epydoc_cli: + if sys.platform == 'darwin' or not epydoc_cli: print("doc: command line epydoc is not found, skipping PDF/PS/Tex output") else: # PDF and PostScript and TeX are built from the diff --git a/doc/design/SConstruct b/doc/design/SConstruct index 2bec66f..1fc1741 100644 --- a/doc/design/SConstruct +++ b/doc/design/SConstruct @@ -3,7 +3,7 @@ # # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/doc/design/acks.xml b/doc/design/acks.xml index f9969f4..1ed5eb1 100644 --- a/doc/design/acks.xml +++ b/doc/design/acks.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/bground.xml b/doc/design/bground.xml index d3864ad..edcc9d7 100644 --- a/doc/design/bground.xml +++ b/doc/design/bground.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/chtml.xsl b/doc/design/chtml.xsl index 6db92c7..e3af46e 100644 --- a/doc/design/chtml.xsl +++ b/doc/design/chtml.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/design/copyright.xml b/doc/design/copyright.xml index 262f894..20aaf7a 100644 --- a/doc/design/copyright.xml +++ b/doc/design/copyright.xml @@ -10,7 +10,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/engine.xml b/doc/design/engine.xml index 594625e..57c91f6 100644 --- a/doc/design/engine.xml +++ b/doc/design/engine.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/goals.xml b/doc/design/goals.xml index dec4bad..5887a95 100644 --- a/doc/design/goals.xml +++ b/doc/design/goals.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/html.xsl b/doc/design/html.xsl index 3f0760b..b4f10f5 100644 --- a/doc/design/html.xsl +++ b/doc/design/html.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/design/install.xml b/doc/design/install.xml index c45ea2b..6678afe 100644 --- a/doc/design/install.xml +++ b/doc/design/install.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/intro.xml b/doc/design/intro.xml index 38b94ae..a6d90a0 100644 --- a/doc/design/intro.xml +++ b/doc/design/intro.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/issues.xml b/doc/design/issues.xml index 48673de..86a1164 100644 --- a/doc/design/issues.xml +++ b/doc/design/issues.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/main.xml b/doc/design/main.xml index 3c7b30d..ab513cb 100644 --- a/doc/design/main.xml +++ b/doc/design/main.xml @@ -2,7 +2,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/native.xml b/doc/design/native.xml index 787f4dd..ff8960d 100644 --- a/doc/design/native.xml +++ b/doc/design/native.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -64,8 +64,9 @@ <para> By default, the &SCons; utility searches for a file named - &SConstruct;, &Sconstruct; or &sconstruct; (in that order) in the - current directory, and reads its configuration from the first file + &SConstruct;, &Sconstruct;, &sconstruct;, &SConstruct.py;, &Sconstruct.py; + or &sconstruct.py; (in that order) in the current directory, + and reads its configuration from the first file found. A <option>-f</option> command-line option exists to read a different file name. diff --git a/doc/design/overview.xml b/doc/design/overview.xml index 793a0a4..e6c28cd 100644 --- a/doc/design/overview.xml +++ b/doc/design/overview.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/pdf.xsl b/doc/design/pdf.xsl index a6d0054..230554a 100644 --- a/doc/design/pdf.xsl +++ b/doc/design/pdf.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/design/scons_title.xsl b/doc/design/scons_title.xsl index 130c6a5..21c56da 100644 --- a/doc/design/scons_title.xsl +++ b/doc/design/scons_title.xsl @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/design/summary.xml b/doc/design/summary.xml index 5dfa585..2318fea 100644 --- a/doc/design/summary.xml +++ b/doc/design/summary.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/developer/SConstruct b/doc/developer/SConstruct index b40bc6b..fd8996c 100644 --- a/doc/developer/SConstruct +++ b/doc/developer/SConstruct @@ -3,7 +3,7 @@ # # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/doc/developer/architecture.xml b/doc/developer/architecture.xml index 0f18cea..01af129 100644 --- a/doc/developer/architecture.xml +++ b/doc/developer/architecture.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/developer/branches.xml b/doc/developer/branches.xml index 91ab768..56db812 100644 --- a/doc/developer/branches.xml +++ b/doc/developer/branches.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/developer/copyright.xml b/doc/developer/copyright.xml index 50e0a42..5404d98 100644 --- a/doc/developer/copyright.xml +++ b/doc/developer/copyright.xml @@ -10,7 +10,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/developer/cycle.xml b/doc/developer/cycle.xml index 3406f76..820a6d5 100644 --- a/doc/developer/cycle.xml +++ b/doc/developer/cycle.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/developer/main.xml b/doc/developer/main.xml index 1920794..b113513 100644 --- a/doc/developer/main.xml +++ b/doc/developer/main.xml @@ -2,7 +2,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/developer/packaging.xml b/doc/developer/packaging.xml index 4222299..b922d3d 100644 --- a/doc/developer/packaging.xml +++ b/doc/developer/packaging.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/developer/preface.xml b/doc/developer/preface.xml index bd3962d..8b74db4 100644 --- a/doc/developer/preface.xml +++ b/doc/developer/preface.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/developer/sourcetree.xml b/doc/developer/sourcetree.xml index c9657d1..01985ee 100644 --- a/doc/developer/sourcetree.xml +++ b/doc/developer/sourcetree.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/developer/testing.xml b/doc/developer/testing.xml index 779eb7d..de0c8bc 100644 --- a/doc/developer/testing.xml +++ b/doc/developer/testing.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/generated/builders.gen b/doc/generated/builders.gen index d851c93..dc05443 100644 --- a/doc/generated/builders.gen +++ b/doc/generated/builders.gen @@ -572,75 +572,77 @@ env.Jar(target = 'bar.jar', <function>env.Java()</function> </term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Builds one or more Java class files. -The sources may be any combination of explicit -<filename>.java</filename> files, -or directory trees which will be scanned -for <filename>.java</filename> files. -</para> - -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -SCons will parse each source <filename>.java</filename> file -to find the classes -(including inner classes) -defined within that file, -and from that figure out the -target <filename>.class</filename> files that will be created. -The class files will be placed underneath -the specified target directory. -</para> - -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -SCons will also search each Java file -for the Java package name, -which it assumes can be found on a line -beginning with the string -<literal>package</literal> -in the first column; -the resulting <filename>.class</filename> files -will be placed in a directory reflecting -the specified package name. -For example, -the file -<filename>Foo.java</filename> -defining a single public -<classname>Foo</classname> -class and -containing a package name of -<classname>sub.dir</classname> -will generate a corresponding -<filename>sub/dir/Foo.class</filename> -class file. -</para> - -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Examples: -</para> - -<example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> -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 xmlns="http://www.scons.org/dbxsd/v1.0"> -Java source files can use the native encoding for the underlying OS. -Since SCons compiles in simple ASCII mode by default, -the compiler will generate warnings about unmappable characters, -which may lead to errors as the file is processed further. -In this case, the user must specify the <literal>LANG</literal> -environment variable to tell the compiler what encoding is used. -For portibility, it's best if the encoding is hard-coded -so that the compile will work if it is done on a system -with a different encoding. -</para> - -<example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> -env = Environment() -env['ENV']['LANG'] = 'en_GB.UTF-8' -</example_commands> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Builds one or more Java class files. + The sources may be any combination of explicit + <filename>.java</filename> + files, + or directory trees which will be scanned + for <filename>.java</filename> files. + </para> + + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + SCons will parse each source <filename>.java</filename> file + to find the classes + (including inner classes) + defined within that file, + and from that figure out the + target <filename>.class</filename> files that will be created. + The class files will be placed underneath + the specified target directory. + </para> + + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + SCons will also search each Java file + for the Java package name, + which it assumes can be found on a line + beginning with the string + <literal>package</literal> + in the first column; + the resulting <filename>.class</filename> files + will be placed in a directory reflecting + the specified package name. + For example, + the file + <filename>Foo.java</filename> + defining a single public + <classname>Foo</classname> + class and + containing a package name of + <classname>sub.dir</classname> + will generate a corresponding + <filename>sub/dir/Foo.class</filename> + class file. + </para> + + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Examples: + </para> + + <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> + 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 xmlns="http://www.scons.org/dbxsd/v1.0"> + Java source files can use the native encoding for the underlying OS. + Since SCons compiles in simple ASCII mode by default, + the compiler will generate warnings about unmappable characters, + which may lead to errors as the file is processed further. + In this case, the user must specify the + <literal>LANG</literal> + environment variable to tell the compiler what encoding is used. + For portibility, it's best if the encoding is hard-coded + so that the compile will work if it is done on a system + with a different encoding. + </para> + + <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> + env = Environment() + env['ENV']['LANG'] = 'en_GB.UTF-8' + </example_commands> + </listitem> </varlistentry> <varlistentry id="b-JavaH"> <term> @@ -836,148 +838,192 @@ Compile files for languages defined in <filename>LINGUAS</filename> file <term> <function>env.MSVSProject()</function> </term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> Builds a Microsoft Visual Studio project -file, and by default builds a solution file as well. </para> <para xmlns="http://www.scons.org/dbxsd/v1.0"> This -builds a Visual Studio project file, based on the version of Visual Studio -that is configured (either the latest installed version, or the version -specified by <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVS_VERSION"><envar>$MSVS_VERSION</envar></link> in the Environment constructor). For -Visual Studio 6, it will generate a <filename>.dsp</filename> file. For Visual -Studio 7 (.NET) and later versions, it will generate a -<filename>.vcproj</filename> file. </para> <para xmlns="http://www.scons.org/dbxsd/v1.0"> By default, this also -generates a solution file for the specified project, a -<filename>.dsw</filename> file for Visual Studio 6 or a -<filename>.sln</filename> file for Visual Studio 7 (.NET). This behavior may -be disabled by specifying <literal>auto_build_solution=0</literal> when you -call <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function>, in which case you presumably want to build the solution -file(s) by calling the <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSSolution</function> Builder (see below). </para> <para xmlns="http://www.scons.org/dbxsd/v1.0"> -The <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function> builder takes several lists of filenames to be placed into -the project file. These are currently limited to <literal>srcs</literal>, -<literal>incs</literal>, <literal>localincs</literal>, -<literal>resources</literal>, and <literal>misc</literal>. These are pretty -self-explanatory, but it should be noted that these lists are added to the -<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SOURCES"><envar>$SOURCES</envar></link> construction variable as strings, NOT as SCons File Nodes. -This is because they represent file names to be added to the project file, not -the source files used to build the project file. </para> <para xmlns="http://www.scons.org/dbxsd/v1.0"> The above -filename lists are all optional, although at least one must be specified for -the resulting project file to be non-empty. </para> <para xmlns="http://www.scons.org/dbxsd/v1.0"> In addition to the -above lists of values, the following values may be specified: -</para><variablelist xmlns="http://www.scons.org/dbxsd/v1.0"> - <varlistentry> - <term>target</term> - - <listitem> - <para>The name of the target <filename>.dsp</filename> or - <filename>.vcproj</filename> file. The correct suffix for the version - of Visual Studio must be used, but the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVSPROJECTSUFFIX"><envar>$MSVSPROJECTSUFFIX</envar></link> - construction variable will be defined to the correct value (see - example below).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>variant</term> - - <listitem> - <para>The name of this particular variant. For Visual Studio 7 - projects, this can also be a list of variant names. These are - typically things like "Debug" or "Release", but really can be anything - you want. For Visual Studio 7 projects, they may also specify a target - platform separated from the variant name by a <literal>|</literal> - (vertical pipe) character: <literal>Debug|Xbox</literal>. The default - target platform is Win32. Multiple calls to <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function> with - different variants are allowed; all variants will be added to the - project file with their appropriate build targets and - sources.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>cmdargs</term> - - <listitem> - <para>Additional command line arguments for the different - variants. The number of <literal>cmdargs</literal> entries must match - the number of <literal>variant</literal> entries, or be empty (not - specified). If you give only one, it will automatically be propagated - to all variants.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>buildtarget</term> - - <listitem> - <para>An optional string, node, or list of strings or nodes (one - per build variant), to tell the Visual Studio debugger what output - target to use in what build variant. The number of - <literal>buildtarget</literal> entries must match the number of - <literal>variant</literal> entries.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>runfile</term> - - <listitem> - <para>The name of the file that Visual Studio 7 and later will - run and debug. This appears as the value of the - <literal>Output</literal> field in the resulting Visual Studio project - file. If this is not specified, the default is the same as the - specified <literal>buildtarget</literal> value.</para> - </listitem> - </varlistentry> - </variablelist><para xmlns="http://www.scons.org/dbxsd/v1.0"> Note that because <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> always executes its build -commands from the directory in which the <filename xmlns="http://www.scons.org/dbxsd/v1.0">SConstruct</filename> file is located, if you -generate a project file in a different directory than the <filename xmlns="http://www.scons.org/dbxsd/v1.0">SConstruct</filename> -directory, users will not be able to double-click on the file name in -compilation error messages displayed in the Visual Studio console output -window. This can be remedied by adding the Visual C/C++ <literal>/FC</literal> -compiler option to the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-CCFLAGS"><envar>$CCFLAGS</envar></link> variable so that the compiler will -print the full path name of any files that cause compilation errors. </para> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> Example usage: </para> - <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Builds a Microsoft Visual Studio project file, and by default + builds a solution file as well. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + This builds a Visual Studio project file, based on the + version of Visual Studio that is configured (either the + latest installed version, or the version specified by + <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVS_VERSION"><envar>$MSVS_VERSION</envar></link> in the Environment constructor). For + Visual Studio 6, it will generate a <filename>.dsp</filename> + file. For Visual Studio 7 (.NET) and later versions, it will + generate a <filename>.vcproj</filename> file. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + By default, this also generates a solution file for the + specified project, a <filename>.dsw</filename> file for + Visual Studio 6 or a <filename>.sln</filename> file for + Visual Studio 7 (.NET). This behavior may be disabled by + specifying <literal>auto_build_solution=0</literal> when you + call <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function>, in which case you presumably want to + build the solution file(s) by calling the <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSSolution</function> + Builder (see below). + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function> builder takes several lists of filenames + to be placed into the project file. These are currently + limited to <literal>srcs</literal>, <literal>incs</literal>, + <literal>localincs</literal>, <literal>resources</literal>, and + <literal>misc</literal>. These are pretty self-explanatory, + but it should be noted that these lists are added to the + <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SOURCES"><envar>$SOURCES</envar></link> construction variable as strings, NOT as + SCons File Nodes. This is because they represent file names + to be added to the project file, not the source files used + to build the project file. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The above filename lists are all optional, although at least + one must be specified for the resulting project file to + be non-empty. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + In addition to the above lists of values, the following values + may be specified: + </para> + <variablelist xmlns="http://www.scons.org/dbxsd/v1.0"> + <varlistentry> + <term>target</term> + <listitem> + <para> + The name of the target <filename>.dsp</filename> + or <filename>.vcproj</filename> file. + The correct suffix for the version of Visual Studio + must be used, but the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVSPROJECTSUFFIX"><envar>$MSVSPROJECTSUFFIX</envar></link> + construction variable will be defined to the correct + value (see example below). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>variant</term> + <listitem> + <para> + The name of this particular variant. For Visual Studio 7 + projects, this can also be a list of variant names. These + are typically things like "Debug" or "Release", but + really can be anything you want. For Visual Studio + 7 projects, they may also specify a target platform + separated from the variant name by a <literal>|</literal> + (vertical pipe) character: <literal>Debug|Xbox</literal>. + The default target platform is Win32. Multiple calls + to <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function> with different variants are allowed; + all variants will be added to the project file with + their appropriate build targets and sources. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>cmdargs</term> + <listitem> + <para> + Additional command line arguments + for the different variants. The number of + <literal>cmdargs</literal> entries must match the number + of <literal>variant</literal> entries, or be empty (not + specified). If you give only one, it will automatically + be propagated to all variants. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>buildtarget</term> + <listitem> + <para> + An optional string, node, or list of strings + or nodes (one per build variant), to tell + the Visual Studio debugger what output target + to use in what build variant. The number of + <literal>buildtarget</literal> entries must match the + number of <literal>variant</literal> entries. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>runfile</term> + <listitem> + <para> + The name of the file that Visual Studio 7 and + later will run and debug. This appears as the + value of the <literal>Output</literal> field in the + resulting Visual Studio project file. If this is not + specified, the default is the same as the specified + <literal>buildtarget</literal> value. + </para> + </listitem> + </varlistentry> + </variablelist> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Note that because <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> always executes its build commands + from the directory in which the <filename xmlns="http://www.scons.org/dbxsd/v1.0">SConstruct</filename> file is located, + if you generate a project file in a different directory + than the <filename xmlns="http://www.scons.org/dbxsd/v1.0">SConstruct</filename> directory, users will not be able to + double-click on the file name in compilation error messages + displayed in the Visual Studio console output window. This can + be remedied by adding the Visual C/C++ <literal>/FC</literal> + compiler option to the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-CCFLAGS"><envar>$CCFLAGS</envar></link> variable so that + the compiler will print the full path name of any files that + cause compilation errors. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0">Example usage:</para> + <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> barsrcs = ['bar.cpp'] barincs = ['bar.h'] barlocalincs = ['StdAfx.h'] barresources = ['bar.rc','resource.h'] barmisc = ['bar_readme.txt'] -dll = env.SharedLibrary(target = 'bar.dll', - source = barsrcs) +dll = env.SharedLibrary(target='bar.dll', + source=barsrcs) buildtarget = [s for s in dll if str(s).endswith('dll')] -env.MSVSProject(target = 'Bar' + env['MSVSPROJECTSUFFIX'], - srcs = barsrcs, - incs = barincs, - localincs = barlocalincs, - resources = barresources, - misc = barmisc, - buildtarget = buildtarget, - variant = 'Release') -</example_commands> -<para xmlns="http://www.scons.org/dbxsd/v1.0">Starting with version 2.4 of -SCons it's also possible to specify the optional argument -<parameter>DebugSettings</parameter>, which creates files for debugging under -Visual Studio:</para><variablelist xmlns="http://www.scons.org/dbxsd/v1.0"> - <varlistentry> - <term>DebugSettings</term> - - <listitem> - <para>A dictionary of debug settings that get written to the - <filename>.vcproj.user</filename> or the - <filename>.vcxproj.user</filename> file, depending on the version - installed. As it is done for cmdargs (see above), you can specify a - <parameter>DebugSettings</parameter> dictionary per variant. If you - give only one, it will be propagated to all variants.</para> - </listitem> - </varlistentry> - </variablelist><para xmlns="http://www.scons.org/dbxsd/v1.0">Currently, only Visual Studio v9.0 and Visual Studio -version v11 are implemented, for other versions no file is generated. To -generate the user file, you just need to add a -<parameter>DebugSettings</parameter> dictionary to the environment with the -right parameters for your MSVS version. If the dictionary is empty, or does -not contain any good value, no file will be generated.</para><para xmlns="http://www.scons.org/dbxsd/v1.0">Following -is a more contrived example, involving the setup of a project for variants and -DebugSettings:</para><example_commands xmlns="http://www.scons.org/dbxsd/v1.0"># Assuming you store your defaults in a file +env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], + srcs=barsrcs, + incs=barincs, + localincs=barlocalincs, + resources=barresources, + misc=barmisc, + buildtarget=buildtarget, + variant='Release') + </example_commands> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Starting with version 2.4 of SCons it is + also possible to specify the optional argument + <parameter>DebugSettings</parameter>, which creates files + for debugging under Visual Studio: + </para> + <variablelist xmlns="http://www.scons.org/dbxsd/v1.0"> + <varlistentry> + <term>DebugSettings</term> + <listitem> + <para> + A dictionary of debug settings that get written + to the <filename>.vcproj.user</filename> or the + <filename>.vcxproj.user</filename> file, depending on the + version installed. As it is done for cmdargs (see above), + you can specify a <parameter>DebugSettings</parameter> + dictionary per variant. If you give only one, it will + be propagated to all variants. + </para> + </listitem> + </varlistentry> + </variablelist> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Currently, only Visual Studio v9.0 and Visual Studio + version v11 are implemented, for other versions no file + is generated. To generate the user file, you just need to + add a <parameter>DebugSettings</parameter> dictionary to the + environment with the right parameters for your MSVS version. If + the dictionary is empty, or does not contain any good value, + no file will be generated. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Following is a more contrived example, involving the setup + of a project for variants and DebugSettings: + </para> + <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> +# Assuming you store your defaults in a file vars = Variables('variables.py') msvcver = vars.args.get('vc', '9') @@ -986,7 +1032,7 @@ if msvcver == '9' or msvcver == '11': env = Environment(MSVC_VERSION=msvcver+'.0', MSVC_BATCH=False) else: env = Environment() - + AddOption('--userfile', action='store_true', dest='userfile', default=False, help="Create Visual Studio Project user file") @@ -1021,10 +1067,10 @@ V9DebugSettings = { } # -# 2. Because there are a lot of different options depending on the Microsoft -# Visual Studio version, if you use more than one version you have to -# define a dictionary per version, for instance if you want to create a user -# file to launch a specific application for testing your dll with Microsoft +# 2. Because there are a lot of different options depending on the Microsoft +# Visual Studio version, if you use more than one version you have to +# define a dictionary per version, for instance if you want to create a user +# file to launch a specific application for testing your dll with Microsoft # Visual Studio 2012 (v11): # V10DebugSettings = { @@ -1056,7 +1102,7 @@ V10DebugSettings = { } # -# 3. Select the dictionary you want depending on the version of visual Studio +# 3. Select the dictionary you want depending on the version of visual Studio # Files you want to generate. # if not env.GetOption('userfile'): @@ -1065,7 +1111,7 @@ elif env.get('MSVC_VERSION', None) == '9.0': dbgSettings = V9DebugSettings elif env.get('MSVC_VERSION', None) == '11.0': dbgSettings = V10DebugSettings -else: +else: dbgSettings = None # @@ -1077,20 +1123,21 @@ barlocalincs = ['StdAfx.h'] barresources = ['bar.rc','resource.h'] barmisc = ['ReadMe.txt'] -dll = env.SharedLibrary(target = 'bar.dll', - source = barsrcs) - -env.MSVSProject(target = 'Bar' + env['MSVSPROJECTSUFFIX'], - srcs = barsrcs, - incs = barincs, - localincs = barlocalincs, - resources = barresources, - misc = barmisc, - buildtarget = [dll[0]] * 2, - variant = ('Debug|Win32', 'Release|Win32'), - cmdargs = 'vc=%s' % msvcver, - DebugSettings = (dbgSettings, {})) -</example_commands> </listitem> +dll = env.SharedLibrary(target='bar.dll', + source=barsrcs) + +env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], + srcs=barsrcs, + incs=barincs, + localincs=barlocalincs, + resources=barresources, + misc=barmisc, + buildtarget=[dll[0]] * 2, + variant=('Debug|Win32', 'Release|Win32'), + cmdargs='vc=%s' % msvcver, + DebugSettings=(dbgSettings, {})) + </example_commands> + </listitem> </varlistentry> <varlistentry id="b-MSVSSolution"> <term> @@ -1099,54 +1146,60 @@ env.MSVSProject(target = 'Bar' + env['MSVSPROJECTSUFFIX'], <term> <function>env.MSVSSolution()</function> </term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">Builds a Microsoft Visual Studio solution -file. </para> <para xmlns="http://www.scons.org/dbxsd/v1.0">This builds a Visual Studio solution file, based on the -version of Visual Studio that is configured (either the latest installed -version, or the version specified by <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVS_VERSION"><envar>$MSVS_VERSION</envar></link> in the -construction environment). For Visual Studio 6, it will generate a -<filename>.dsw</filename> file. For Visual Studio 7 (.NET), it will generate a -<filename>.sln</filename> file. </para> <para xmlns="http://www.scons.org/dbxsd/v1.0"> The following values must be -specified: </para><variablelist xmlns="http://www.scons.org/dbxsd/v1.0"> - <varlistentry> - <term>target</term> - - <listitem> - <para>The name of the target .dsw or .sln file. The correct - suffix for the version of Visual Studio must be used, but the value - <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVSSOLUTIONSUFFIX"><envar>$MSVSSOLUTIONSUFFIX</envar></link> will be defined to the correct value (see - example below).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>variant</term> - - <listitem> - <para>The name of this particular variant, or a list of variant - names (the latter is only supported for MSVS 7 solutions). These are - typically things like "Debug" or "Release", but really can be anything - you want. For MSVS 7 they may also specify target platform, like this - "Debug|Xbox". Default platform is Win32.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>projects</term> - - <listitem> - <para>A list of project file names, or Project nodes returned by - calls to the <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function> Builder, to be placed into the solution - file. It should be noted that these file names are NOT added to the - $SOURCES environment variable in form of files, but rather as strings. - This is because they represent file names to be added to the solution - file, not the source files used to build the solution - file.</para> - </listitem> - </varlistentry> - </variablelist> <para xmlns="http://www.scons.org/dbxsd/v1.0"> Example Usage: </para> <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> -env.MSVSSolution(target = 'Bar' + env['MSVSSOLUTIONSUFFIX'], projects = ['bar' -+ env['MSVSPROJECTSUFFIX']], variant = 'Release') -</example_commands></listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0">Builds a Microsoft Visual Studio solution file.</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + This builds a Visual Studio solution file, based on the + version of Visual Studio that is configured (either the + latest installed version, or the version specified by + <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVS_VERSION"><envar>$MSVS_VERSION</envar></link> in the construction environment). For + Visual Studio 6, it will generate a <filename>.dsw</filename> + file. For Visual Studio 7 (.NET), it will generate a + <filename>.sln</filename> file. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0">The following values must be specified:</para> + <variablelist xmlns="http://www.scons.org/dbxsd/v1.0"> + <varlistentry> + <term>target</term> + <listitem> + <para> + The name of the target .dsw or .sln file. The correct + suffix for the version of Visual Studio must be used, + but the value <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVSSOLUTIONSUFFIX"><envar>$MSVSSOLUTIONSUFFIX</envar></link> will be + defined to the correct value (see example below). + </para> + </listitem> + </varlistentry> <varlistentry> + <term>variant</term> <listitem> + <para> + The name of this particular variant, or a list of + variant names (the latter is only supported for MSVS + 7 solutions). These are typically things like "Debug" + or "Release", but really can be anything you want. For + MSVS 7 they may also specify target platform, like this + "Debug|Xbox". Default platform is Win32. + </para> + </listitem> + </varlistentry> <varlistentry> + <term>projects</term> <listitem> + <para> + A list of project file names, or Project nodes returned + by calls to the <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function> Builder, to be placed + into the solution file. It should be noted that these + file names are NOT added to the $SOURCES environment + variable in form of files, but rather as strings. + This is because they represent file names to be added + to the solution file, not the source files used to + build the solution file. + </para> + </listitem> + </varlistentry> + </variablelist> + <para xmlns="http://www.scons.org/dbxsd/v1.0">Example Usage:</para> + <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> +env.MSVSSolution(target='Bar' + env['MSVSSOLUTIONSUFFIX'], projects=['bar' + env['MSVSPROJECTSUFFIX']], variant='Release') + </example_commands> + </listitem> </varlistentry> <varlistentry id="b-Object"> <term> @@ -1206,13 +1259,15 @@ the following packagers available: <para xmlns="http://www.scons.org/dbxsd/v1.0"> * msi - Microsoft Installer - * rpm - Redhat Package Manger + * rpm - RPM Package Manger * ipkg - Itsy Package Management System - * tarbz2 - compressed tar - * targz - compressed tar + * tarbz2 - bzip2 compressed tar + * targz - gzip compressed tar + * tarxz - xz compressed tar * zip - zip file - * src_tarbz2 - compressed tar source - * src_targz - compressed tar source + * src_tarbz2 - bzip2 compressed tar source + * src_targz - gzip compressed tar source + * src_tarxz - xz compressed tar source * src_zip - zip file source </para> @@ -2322,7 +2377,7 @@ and the result replaces the key. </para> <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> -env = Environment(tools = ['default', 'textfile']) +env = Environment(tools=['default']) env['prefix'] = '/usr/bin' script_dict = {'@prefix@': '/bin', '@exec_prefix@': '$prefix'} @@ -2349,7 +2404,7 @@ env.Substfile('bar.in', SUBST_DICT = good_bar) # the SUBST_DICT may be in common (and not an override) substutions = {} -subst = Environment(tools = ['textfile'], SUBST_DICT = substitutions) +subst = Environment(tools=['textfile'], SUBST_DICT=substitutions) substitutions['@foo@'] = 'foo' subst['SUBST_DICT']['@bar@'] = 'bar' subst.Substfile('pgm1.c', [Value('#include "@foo@.h"'), diff --git a/doc/generated/examples/addmethod_ex2_2.xml b/doc/generated/examples/addmethod_ex2_2.xml index 15ae6e0..734da63 100644 --- a/doc/generated/examples/addmethod_ex2_2.xml +++ b/doc/generated/examples/addmethod_ex2_2.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">C:\><userinput>scons -Q</userinput> -rc /fores.res res.rc +rc /nologo /fores.res res.rc cl /Fotest_stuff.obj /c test_stuff.c /nologo link /nologo /OUT:tests\test_stuff.exe test_stuff.obj res.res embedManifestExeCheck(target, source, env) diff --git a/doc/generated/examples/builderswriting_MY_EMITTER_1.xml b/doc/generated/examples/builderswriting_MY_EMITTER_1.xml index 440b105..0c17d0e 100644 --- a/doc/generated/examples/builderswriting_MY_EMITTER_1.xml +++ b/doc/generated/examples/builderswriting_MY_EMITTER_1.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> -my_command file1.input modify1.in > file1.foo -my_command file2.input modify2.in > file2.foo +./my_command file1.input modify1.in > file1.foo +./my_command file2.input modify2.in > file2.foo </screen> diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index 6f64f8f..0a432e9 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> -cc -o f2.o -c f2.c -cc -o f4.o -c f4.c -cc -o f3.o -c f3.c cc -o f5.o -c f5.c +cc -o f3.o -c f3.c +cc -o f2.o -c f2.c cc -o f1.o -c f1.c +cc -o f4.o -c f4.c cc -o prog f1.o f2.o f3.o f4.o f5.o </screen> diff --git a/doc/generated/examples/environments_ex3_1.xml b/doc/generated/examples/environments_ex3_1.xml index 5071c6e..3262302 100644 --- a/doc/generated/examples/environments_ex3_1.xml +++ b/doc/generated/examples/environments_ex3_1.xml @@ -1,22 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> -UnicodeDecodeError: 'utf8' codec can't decode byte 0xc2 in position 547: invalid continuation byte: - File "/home/my/project/SConstruct", line 6: - dbg.Program('foo', 'foo.c') - File "bootstrap/src/engine/SCons/Environment.py", line 260: - return MethodWrapper.__call__(self, target, source, *args, **kw) - File "bootstrap/src/engine/SCons/Environment.py", line 224: - return self.method(*nargs, **kwargs) - File "bootstrap/src/engine/SCons/Builder.py", line 635: - return self._execute(env, target, source, OverrideWarner(kw), ekw) - File "bootstrap/src/engine/SCons/Builder.py", line 541: - source = self.src_builder_sources(env, source, overwarn) - File "bootstrap/src/engine/SCons/Builder.py", line 748: - tlist = bld._execute(env, None, [s], overwarn) - File "bootstrap/src/engine/SCons/Builder.py", line 557: - _node_errors(self, env, tlist, slist) - File "bootstrap/src/engine/SCons/Builder.py", line 303: - msg = "Two environments with different actions were specified for the same target: %s\n(action 1: %s)\n(action 2: %s)" % (t,t_contents.decode('utf-8'),contents.decode('utf-8')) - File "/usr/lib/python2.7/encodings/utf_8.py", line 16: - return codecs.utf_8_decode(input, errors, True) + +scons: *** Two environments with different actions were specified for the same target: foo.o +File "/home/my/project/SConstruct", line 6, in <module> </screen> diff --git a/doc/generated/examples/java_jar1_1.xml b/doc/generated/examples/java_jar1_1.xml index daa3d1a..de93227 100644 --- a/doc/generated/examples/java_jar1_1.xml +++ b/doc/generated/examples/java_jar1_1.xml @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> javac -d classes -sourcepath src src/Example1.java src/Example2.java src/Example3.java -scons: *** [test.jar] Source `classes.class' not found, needed by target `test.jar'. +jar cf test.jar classes </screen> diff --git a/doc/generated/examples/mergeflags_MergeFlags1_1.xml b/doc/generated/examples/mergeflags_MergeFlags1_1.xml index 8a0c336..8f18fd8 100644 --- a/doc/generated/examples/mergeflags_MergeFlags1_1.xml +++ b/doc/generated/examples/mergeflags_MergeFlags1_1.xml @@ -1,10 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> - File "/home/my/project/SConstruct", line 5 - - print env['CCFLAGS'] - - ^ - -SyntaxError: invalid syntax +['-option', '-O1', '-whatever', '-O3'] +scons: `.' is up to date. </screen> diff --git a/doc/generated/examples/mergeflags_MergeFlags2_1.xml b/doc/generated/examples/mergeflags_MergeFlags2_1.xml index 1312c47..8cae827 100644 --- a/doc/generated/examples/mergeflags_MergeFlags2_1.xml +++ b/doc/generated/examples/mergeflags_MergeFlags2_1.xml @@ -1,10 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> - File "/home/my/project/SConstruct", line 5 - - print env['CPPPATH'] - - ^ - -SyntaxError: invalid syntax +['/include', '/usr/local/include', '/usr/include', '/usr/opt/include'] +scons: `.' is up to date. </screen> diff --git a/doc/generated/examples/mergeflags_MergeFlags3_1.xml b/doc/generated/examples/mergeflags_MergeFlags3_1.xml index 8a0c336..d4f23d4 100644 --- a/doc/generated/examples/mergeflags_MergeFlags3_1.xml +++ b/doc/generated/examples/mergeflags_MergeFlags3_1.xml @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> - File "/home/my/project/SConstruct", line 5 - - print env['CCFLAGS'] - - ^ - -SyntaxError: invalid syntax +['-option', '-O1', '-whatever', '-O3'] +['/include', '/usr/local/include', '/usr/include', '/usr/opt/include'] +scons: `.' is up to date. </screen> diff --git a/doc/generated/examples/misc_FindFile1b_1.xml b/doc/generated/examples/misc_FindFile1b_1.xml index 894b483..4b194ce 100644 --- a/doc/generated/examples/misc_FindFile1b_1.xml +++ b/doc/generated/examples/misc_FindFile1b_1.xml @@ -1,8 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> -nonesuch.h: None -config.h: config.h -private.h: src/include/private.h -dist.h: include/dist.h +nonesuch.h : None +config.h : config.h +private.h : src/include/private.h +dist.h : include/dist.h scons: `.' is up to date. </screen> diff --git a/doc/generated/examples/parseflags_ex1_1.xml b/doc/generated/examples/parseflags_ex1_1.xml index 79cdad6..d6e4d96 100644 --- a/doc/generated/examples/parseflags_ex1_1.xml +++ b/doc/generated/examples/parseflags_ex1_1.xml @@ -1,10 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> - File "/home/my/project/SConstruct", line 5 - - print k, v - - ^ - -SyntaxError: invalid syntax +CPPPATH ['/opt/include'] +LIBPATH ['/opt/lib'] +LIBS ['foo'] +cc -o f1.o -c -I/opt/include f1.c +cc -o f1 f1.o -L/opt/lib -lfoo </screen> diff --git a/doc/generated/examples/parseflags_ex1_2.xml b/doc/generated/examples/parseflags_ex1_2.xml index b9c9cd2..4c115d0 100644 --- a/doc/generated/examples/parseflags_ex1_2.xml +++ b/doc/generated/examples/parseflags_ex1_2.xml @@ -1,10 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">C:\><userinput>scons -Q</userinput> - File "/home/my/project/SConstruct", line 5 - - print k, v - - ^ - -SyntaxError: invalid syntax +CPPPATH ['/opt/include'] +LIBPATH ['/opt/lib'] +LIBS ['foo'] +cl /Fof1.obj /c f1.c /nologo /I\opt\include +link /nologo /OUT:f1.exe /LIBPATH:\opt\lib foo.lib f1.obj +embedManifestExeCheck(target, source, env) </screen> diff --git a/doc/generated/examples/parseflags_ex2_1.xml b/doc/generated/examples/parseflags_ex2_1.xml index 79cdad6..da84ee3 100644 --- a/doc/generated/examples/parseflags_ex2_1.xml +++ b/doc/generated/examples/parseflags_ex2_1.xml @@ -1,10 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> - File "/home/my/project/SConstruct", line 5 - - print k, v - - ^ - -SyntaxError: invalid syntax +CCFLAGS -whatever +cc -o f1.o -c -whatever f1.c +cc -o f1 f1.o </screen> diff --git a/doc/generated/examples/parseflags_ex3_1.xml b/doc/generated/examples/parseflags_ex3_1.xml index 79cdad6..d6e4d96 100644 --- a/doc/generated/examples/parseflags_ex3_1.xml +++ b/doc/generated/examples/parseflags_ex3_1.xml @@ -1,10 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> - File "/home/my/project/SConstruct", line 5 - - print k, v - - ^ - -SyntaxError: invalid syntax +CPPPATH ['/opt/include'] +LIBPATH ['/opt/lib'] +LIBS ['foo'] +cc -o f1.o -c -I/opt/include f1.c +cc -o f1 f1.o -L/opt/lib -lfoo </screen> diff --git a/doc/generated/examples/parseflags_ex4_1.xml b/doc/generated/examples/parseflags_ex4_1.xml index 79cdad6..d6e4d96 100644 --- a/doc/generated/examples/parseflags_ex4_1.xml +++ b/doc/generated/examples/parseflags_ex4_1.xml @@ -1,10 +1,8 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons -Q</userinput> - File "/home/my/project/SConstruct", line 5 - - print k, v - - ^ - -SyntaxError: invalid syntax +CPPPATH ['/opt/include'] +LIBPATH ['/opt/lib'] +LIBS ['foo'] +cc -o f1.o -c -I/opt/include f1.c +cc -o f1 f1.o -L/opt/lib -lfoo </screen> diff --git a/doc/generated/examples/troubleshoot_Dump_1.xml b/doc/generated/examples/troubleshoot_Dump_1.xml index 281fed7..99d1399 100644 --- a/doc/generated/examples/troubleshoot_Dump_1.xml +++ b/doc/generated/examples/troubleshoot_Dump_1.xml @@ -1,11 +1,79 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons</userinput> scons: Reading SConscript files ... - File "/home/my/project/SConstruct", line 2 - - print env.Dump() - - ^ - -SyntaxError: invalid syntax +{ 'BUILDERS': {'_InternalInstall': <function InstallBuilderWrapper at 0x700000&gt;, '_InternalInstallVersionedLib': <function InstallVersionedBuilderWrapper at 0x700000&gt;, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000&gt;}, + 'CONFIGUREDIR': '#/.sconf_temp', + 'CONFIGURELOG': '#/config.log', + 'CPPSUFFIXES': [ '.c', + '.C', + '.cxx', + '.cpp', + '.c++', + '.cc', + '.h', + '.H', + '.hxx', + '.hpp', + '.hh', + '.F', + '.fpp', + '.FPP', + '.m', + '.mm', + '.S', + '.spp', + '.SPP', + '.sx'], + 'DSUFFIXES': ['.d'], + 'Dir': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, + 'Dirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, + 'ENV': { 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}, + 'ESCAPE': <function escape at 0x700000&gt;, + 'File': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, + 'HOST_ARCH': None, + 'HOST_OS': None, + 'IDLSUFFIXES': ['.idl', '.IDL'], + 'INSTALL': <function copyFunc at 0x700000&gt;, + 'INSTALLVERSIONEDLIB': <function copyFuncVersionedLib at 0x700000&gt;, + 'LIBPREFIX': 'lib', + 'LIBPREFIXES': ['$LIBPREFIX'], + 'LIBSUFFIX': '.a', + 'LIBSUFFIXES': ['$LIBSUFFIX', '$SHLIBSUFFIX'], + 'MAXLINELENGTH': 128072, + 'OBJPREFIX': '', + 'OBJSUFFIX': '.o', + 'PLATFORM': 'posix', + 'PROGPREFIX': '', + 'PROGSUFFIX': '', + 'PSPAWN': <function piped_env_spawn at 0x700000&gt;, + 'RDirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, + 'SCANNERS': [<SCons.Scanner.Base object at 0x700000&gt;], + 'SHELL': 'sh', + 'SHLIBPREFIX': '$LIBPREFIX', + 'SHLIBSUFFIX': '.so', + 'SHOBJPREFIX': '$OBJPREFIX', + 'SHOBJSUFFIX': '$OBJSUFFIX', + 'SPAWN': <function subprocess_spawn at 0x700000&gt;, + 'TARGET_ARCH': None, + 'TARGET_OS': None, + 'TEMPFILE': <class 'SCons.Platform.TempFileMunge'>, + 'TEMPFILEPREFIX': '@', + 'TOOLS': ['install', 'install'], + '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', + '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', + '__DRPATH': '$_DRPATH', + '__DSHLIBVERSIONFLAGS': '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}', + '__LDMODULEVERSIONFLAGS': '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}', + '__RPATH': '$_RPATH', + '__SHLIBVERSIONFLAGS': '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}', + '__libversionflags': <function __libversionflags at 0x700000&gt;, + '_concat': <function _concat at 0x700000&gt;, + '_defines': <function _defines at 0x700000&gt;, + '_stripixes': <function _stripixes at 0x700000&gt;} +scons: done reading SConscript files. +scons: Building targets ... +scons: `.' is up to date. +scons: done building targets. </screen> diff --git a/doc/generated/examples/troubleshoot_Dump_2.xml b/doc/generated/examples/troubleshoot_Dump_2.xml index 78cd84b..e8e0960 100644 --- a/doc/generated/examples/troubleshoot_Dump_2.xml +++ b/doc/generated/examples/troubleshoot_Dump_2.xml @@ -1,11 +1,112 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">C:\><userinput>scons</userinput> scons: Reading SConscript files ... - File "/home/my/project/SConstruct", line 2 - - print env.Dump() - - ^ - -SyntaxError: invalid syntax +{ 'BUILDERS': {'_InternalInstallVersionedLib': <function InstallVersionedBuilderWrapper at 0x700000&gt;, '_InternalInstall': <function InstallBuilderWrapper at 0x700000&gt;, 'Object': <SCons.Builder.CompositeBuilder object at 0x700000&gt;, 'PCH': <SCons.Builder.BuilderBase object at 0x700000&gt;, 'RES': <SCons.Builder.BuilderBase object at 0x700000&gt;, 'SharedObject': <SCons.Builder.CompositeBuilder object at 0x700000&gt;, 'StaticObject': <SCons.Builder.CompositeBuilder object at 0x700000&gt;, '_InternalInstallAs': <function InstallAsBuilderWrapper at 0x700000&gt;}, + 'CC': 'cl', + 'CCCOM': <SCons.Action.FunctionAction object at 0x700000&gt;, + 'CCFLAGS': ['/nologo'], + 'CCPCHFLAGS': ['${(PCH and "/Yu%s \\"/Fp%s\\""%(PCHSTOP or "",File(PCH))) or ""}'], + 'CCPDBFLAGS': ['${(PDB and "/Z7") or ""}'], + 'CFILESUFFIX': '.c', + 'CFLAGS': [], + 'CONFIGUREDIR': '#/.sconf_temp', + 'CONFIGURELOG': '#/config.log', + 'CPPDEFPREFIX': '/D', + 'CPPDEFSUFFIX': '', + 'CPPSUFFIXES': [ '.c', + '.C', + '.cxx', + '.cpp', + '.c++', + '.cc', + '.h', + '.H', + '.hxx', + '.hpp', + '.hh', + '.F', + '.fpp', + '.FPP', + '.m', + '.mm', + '.S', + '.spp', + '.SPP', + '.sx'], + 'CXX': '$CC', + 'CXXCOM': '${TEMPFILE("$CXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $CXXFLAGS $CCFLAGS $_CCCOMCOM","$CXXCOMSTR")}', + 'CXXFILESUFFIX': '.cc', + 'CXXFLAGS': ['$(', '/TP', '$)'], + 'DSUFFIXES': ['.d'], + 'Dir': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, + 'Dirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, + 'ENV': { 'PATH': 'C:\\WINDOWS\\System32', + 'PATHEXT': '.COM;.EXE;.BAT;.CMD', + 'SystemRoot': 'C:\\WINDOWS'}, + 'ESCAPE': <function escape at 0x700000&gt;, + 'File': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, + 'HOST_ARCH': '', + 'HOST_OS': 'win32', + 'IDLSUFFIXES': ['.idl', '.IDL'], + 'INCPREFIX': '/I', + 'INCSUFFIX': '', + 'INSTALL': <function copyFunc at 0x700000&gt;, + 'INSTALLVERSIONEDLIB': <function copyFuncVersionedLib at 0x700000&gt;, + 'LEXUNISTD': ['--nounistd'], + 'LIBPREFIX': '', + 'LIBPREFIXES': ['$LIBPREFIX'], + 'LIBSUFFIX': '.lib', + 'LIBSUFFIXES': ['$LIBSUFFIX'], + 'MAXLINELENGTH': 2048, + 'MSVC_SETUP_RUN': True, + 'OBJPREFIX': '', + 'OBJSUFFIX': '.obj', + 'PCHCOM': '$CXX /Fo${TARGETS[1]} $CXXFLAGS $CCFLAGS $CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS /c $SOURCES /Yc$PCHSTOP /Fp${TARGETS[0]} $CCPDBFLAGS $PCHPDBFLAGS', + 'PCHPDBFLAGS': ['${(PDB and "/Yd") or ""}'], + 'PLATFORM': 'win32', + 'PROGPREFIX': '', + 'PROGSUFFIX': '.exe', + 'PSPAWN': <function piped_spawn at 0x700000&gt;, + 'RC': 'rc', + 'RCCOM': <SCons.Action.FunctionAction object at 0x700000&gt;, + 'RCFLAGS': ['/nologo'], + 'RCSUFFIXES': ['.rc', '.rc2'], + 'RDirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000&gt;, + 'SCANNERS': [<SCons.Scanner.Base object at 0x700000&gt;], + 'SHCC': '$CC', + 'SHCCCOM': <SCons.Action.FunctionAction object at 0x700000&gt;, + 'SHCCFLAGS': ['$CCFLAGS'], + 'SHCFLAGS': ['$CFLAGS'], + 'SHCXX': '$CXX', + 'SHCXXCOM': '${TEMPFILE("$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES $SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM","$SHCXXCOMSTR")}', + 'SHCXXFLAGS': ['$CXXFLAGS'], + 'SHELL': None, + 'SHLIBPREFIX': '', + 'SHLIBSUFFIX': '.dll', + 'SHOBJPREFIX': '$OBJPREFIX', + 'SHOBJSUFFIX': '$OBJSUFFIX', + 'SPAWN': <function spawn at 0x700000&gt;, + 'STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME': 1, + 'TARGET_ARCH': None, + 'TARGET_OS': None, + 'TEMPFILE': <class 'SCons.Platform.TempFileMunge'>, + 'TEMPFILEPREFIX': '@', + 'TOOLS': ['msvc', 'install', 'install'], + '_CCCOMCOM': '$CPPFLAGS $_CPPDEFFLAGS $_CPPINCFLAGS $CCPCHFLAGS $CCPDBFLAGS', + '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', + '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', + '_MSVC_OUTPUT_FLAG': <function msvc_output_flag at 0x700000&gt;, + '__DSHLIBVERSIONFLAGS': '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}', + '__LDMODULEVERSIONFLAGS': '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}', + '__SHLIBVERSIONFLAGS': '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}', + '__libversionflags': <function __libversionflags at 0x700000&gt;, + '_concat': <function _concat at 0x700000&gt;, + '_defines': <function _defines at 0x700000&gt;, + '_stripixes': <function _stripixes at 0x700000&gt;} +scons: done reading SConscript files. +scons: Building targets ... +scons: `.' is up to date. +scons: done building targets. </screen> diff --git a/doc/generated/examples/troubleshoot_Dump_ENV_1.xml b/doc/generated/examples/troubleshoot_Dump_ENV_1.xml index bd674a6..786491f 100644 --- a/doc/generated/examples/troubleshoot_Dump_ENV_1.xml +++ b/doc/generated/examples/troubleshoot_Dump_ENV_1.xml @@ -1,11 +1,9 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">% <userinput>scons</userinput> scons: Reading SConscript files ... - File "/home/my/project/SConstruct", line 2 - - print env.Dump('ENV') - - ^ - -SyntaxError: invalid syntax +{ 'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'} +scons: done reading SConscript files. +scons: Building targets ... +scons: `.' is up to date. +scons: done building targets. </screen> diff --git a/doc/generated/examples/troubleshoot_Dump_ENV_2.xml b/doc/generated/examples/troubleshoot_Dump_ENV_2.xml index c9f9258..b91c31c 100644 --- a/doc/generated/examples/troubleshoot_Dump_ENV_2.xml +++ b/doc/generated/examples/troubleshoot_Dump_ENV_2.xml @@ -1,11 +1,11 @@ <?xml version="1.0" encoding="UTF-8"?> <screen xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd">C:\><userinput>scons</userinput> scons: Reading SConscript files ... - File "/home/my/project/SConstruct", line 2 - - print env.Dump('ENV') - - ^ - -SyntaxError: invalid syntax +{ 'PATH': 'C:\\WINDOWS\\System32:/usr/bin', + 'PATHEXT': '.COM;.EXE;.BAT;.CMD', + 'SystemRoot': 'C:\\WINDOWS'} +scons: done reading SConscript files. +scons: Building targets ... +scons: `.' is up to date. +scons: done building targets. </screen> diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 0ee52a9..ebc13f8 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -3,5 +3,5 @@ cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/home/bdbaddog/devel/scons/as_scons/src/script/scons.py", line 201, in <module> +File "/home/bdeegan/devel/scons/git/as_scons/src/script/scons.py", line 204, in <module> </screen> diff --git a/doc/generated/examples/troubleshoot_stacktrace_2.xml b/doc/generated/examples/troubleshoot_stacktrace_2.xml index 4b55f0d..76cfc1a 100644 --- a/doc/generated/examples/troubleshoot_stacktrace_2.xml +++ b/doc/generated/examples/troubleshoot_stacktrace_2.xml @@ -4,7 +4,7 @@ scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. scons: internal stack trace: File "bootstrap/src/engine/SCons/Job.py", line 199, in start task.prepare() - File "bootstrap/src/engine/SCons/Script/Main.py", line 175, in prepare + File "bootstrap/src/engine/SCons/Script/Main.py", line 177, in prepare return SCons.Taskmaster.OutOfDateTask.prepare(self) File "bootstrap/src/engine/SCons/Taskmaster.py", line 198, in prepare executor.prepare() diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index 79a83c6..9fc9d4b 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -1197,6 +1197,10 @@ Multiple calls to <function xmlns="http://www.scons.org/dbxsd/v1.0">Default</function> are legal, and add to the list of default targets. +As noted above, both forms of this call affect the +same global list of default targets; the +construction environment method applies +construction variable expansion to the targets. </para> <para xmlns="http://www.scons.org/dbxsd/v1.0"> @@ -3523,16 +3527,16 @@ below, for a complete explanation of the arguments and behavior. </varlistentry> <varlistentry id="f-SConscript"> <term> - <literal>SConscript(scripts, [exports, variant_dir, duplicate])</literal> + <literal>SConscript(scripts, [exports, variant_dir, duplicate, must_exist])</literal> </term> <term> - <literal>env.SConscript(scripts, [exports, variant_dir, duplicate])</literal> + <literal>env.SConscript(scripts, [exports, variant_dir, duplicate, must_exist])</literal> </term> <term> - <literal>SConscript(dirs=subdirs, [name=script, exports, variant_dir, duplicate])</literal> + <literal>SConscript(dirs=subdirs, [name=script, exports, variant_dir, duplicate, must_exist])</literal> </term> <term> - <literal>env.SConscript(dirs=subdirs, [name=script, exports, variant_dir, duplicate])</literal> + <literal>env.SConscript(dirs=subdirs, [name=script, exports, variant_dir, duplicate, must_exist])</literal> </term> <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> @@ -3734,6 +3738,17 @@ TODO??? SConscript('build/SConscript', src_dir='src') </para> <para xmlns="http://www.scons.org/dbxsd/v1.0"> +The optional +<varname>must_exist</varname> +argument, if true, causes an exception to be raised if a requested +<filename xmlns="http://www.scons.org/dbxsd/v1.0">SConscript</filename> file is not found. The current default is false, +causing only a warning to be omitted, but this behavior is deprecated. +For scripts which truly intend to be optional, transition to +explicty supplying +<literal>must_exist=False</literal> to the call. +</para> + +<para xmlns="http://www.scons.org/dbxsd/v1.0"> Here are some composite examples: </para> diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index f858aa4..be717e3 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -57,11 +57,11 @@ Sets construction variables for the IBM Visual Age linker. <varlistentry id="t-applelink"> <term>applelink</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Sets construction variables for the Apple linker -(similar to the GNU linker). -</para> -<para>Sets: &cv-link-FRAMEWORKPATHPREFIX;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LINKCOM;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_FRAMEWORKPATH;, &cv-link-_FRAMEWORKS;.</para><para>Uses: &cv-link-FRAMEWORKSFLAGS;.</para></listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Sets construction variables for the Apple linker + (similar to the GNU linker). + </para> + <para>Sets: &cv-link-APPLELINK_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_CURRENT_VERSION;, &cv-link-APPLELINK_NO_COMPATIBILITY_VERSION;, &cv-link-APPLELINK_NO_CURRENT_VERSION;, &cv-link-FRAMEWORKPATHPREFIX;, &cv-link-LDMODULECOM;, &cv-link-LDMODULEFLAGS;, &cv-link-LDMODULEPREFIX;, &cv-link-LDMODULESUFFIX;, &cv-link-LINKCOM;, &cv-link-SHLINKCOM;, &cv-link-SHLINKFLAGS;, &cv-link-_APPLELINK_COMPATIBILITY_VERSION;, &cv-link-_APPLELINK_CURRENT_VERSION;, &cv-link-_FRAMEWORKPATH;, &cv-link-_FRAMEWORKS;.</para><para>Uses: &cv-link-FRAMEWORKSFLAGS;.</para></listitem> </varlistentry> <varlistentry id="t-ar"> <term>ar</term> @@ -586,10 +586,10 @@ Sets construction variables for the <application xmlns="http://www.scons.org/dbx <varlistentry id="t-javac"> <term>javac</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Sets construction variables for the <application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> compiler. -</para> -<para>Sets: &cv-link-JAVABOOTCLASSPATH;, &cv-link-JAVAC;, &cv-link-JAVACCOM;, &cv-link-JAVACFLAGS;, &cv-link-JAVACLASSPATH;, &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVASOURCEPATH;, &cv-link-JAVASUFFIX;.</para><para>Uses: &cv-link-JAVACCOMSTR;.</para></listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Sets construction variables for the <application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> compiler. + </para> + <para>Sets: &cv-link-JAVABOOTCLASSPATH;, &cv-link-JAVAC;, &cv-link-JAVACCOM;, &cv-link-JAVACFLAGS;, &cv-link-JAVACLASSPATH;, &cv-link-JAVACLASSSUFFIX;, &cv-link-JAVAINCLUDES;, &cv-link-JAVASOURCEPATH;, &cv-link-JAVASUFFIX;.</para><para>Uses: &cv-link-JAVACCOMSTR;.</para></listitem> </varlistentry> <varlistentry id="t-javah"> <term>javah</term> @@ -621,7 +621,7 @@ Sets construction variables for the D language compiler LDC2. <para xmlns="http://www.scons.org/dbxsd/v1.0"> Sets construction variables for the <application xmlns="http://www.scons.org/dbxsd/v1.0">lex</application> lexical analyser. </para> -<para>Sets: &cv-link-LEX;, &cv-link-LEXCOM;, &cv-link-LEXFLAGS;.</para><para>Uses: &cv-link-LEXCOMSTR;.</para></listitem> +<para>Sets: &cv-link-LEX;, &cv-link-LEXCOM;, &cv-link-LEXFLAGS;, &cv-link-LEXUNISTD;.</para><para>Uses: &cv-link-LEXCOMSTR;.</para></listitem> </varlistentry> <varlistentry id="t-link"> <term>link</term> @@ -750,8 +750,9 @@ Sets construction variables for the Microsoft Visual C/C++ compiler. </varlistentry> <varlistentry id="t-msvs"> <term>msvs</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> -Sets construction variables for Microsoft Visual Studio. </para> <para>Sets: &cv-link-MSVSBUILDCOM;, &cv-link-MSVSCLEANCOM;, &cv-link-MSVSENCODING;, &cv-link-MSVSPROJECTCOM;, &cv-link-MSVSREBUILDCOM;, &cv-link-MSVSSCONS;, &cv-link-MSVSSCONSCOM;, &cv-link-MSVSSCONSCRIPT;, &cv-link-MSVSSCONSFLAGS;, &cv-link-MSVSSOLUTIONCOM;.</para></listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0">Sets construction variables for Microsoft Visual Studio.</para> + <para>Sets: &cv-link-MSVSBUILDCOM;, &cv-link-MSVSCLEANCOM;, &cv-link-MSVSENCODING;, &cv-link-MSVSPROJECTCOM;, &cv-link-MSVSREBUILDCOM;, &cv-link-MSVSSCONS;, &cv-link-MSVSSCONSCOM;, &cv-link-MSVSSCONSCRIPT;, &cv-link-MSVSSCONSFLAGS;, &cv-link-MSVSSOLUTIONCOM;.</para></listitem> </varlistentry> <varlistentry id="t-mwcc"> <term>mwcc</term> @@ -778,19 +779,19 @@ Sets construction variables for the </para> <para>Sets: &cv-link-AS;, &cv-link-ASCOM;, &cv-link-ASFLAGS;, &cv-link-ASPPCOM;, &cv-link-ASPPFLAGS;.</para><para>Uses: &cv-link-ASCOMSTR;, &cv-link-ASPPCOMSTR;.</para></listitem> </varlistentry> - <varlistentry id="t-Packaging"> - <term>Packaging</term> + <varlistentry id="t-packaging"> + <term>packaging</term> <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> -Sets construction variables for the <function xmlns="http://www.scons.org/dbxsd/v1.0">Package</function> Builder. +A framework for building binary and source packages. </para> </listitem> </varlistentry> - <varlistentry id="t-packaging"> - <term>packaging</term> + <varlistentry id="t-Packaging"> + <term>Packaging</term> <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> -A framework for building binary and source packages. +Sets construction variables for the <function xmlns="http://www.scons.org/dbxsd/v1.0">Package</function> Builder. </para> </listitem> </varlistentry> diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index 1209d74..f9bc1d7 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -78,8 +78,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY t-mwcc "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>mwcc</literal>"> <!ENTITY t-mwld "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>mwld</literal>"> <!ENTITY t-nasm "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>nasm</literal>"> -<!ENTITY t-Packaging "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Packaging</literal>"> <!ENTITY t-packaging "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>packaging</literal>"> +<!ENTITY t-Packaging "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>Packaging</literal>"> <!ENTITY t-pdf "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>pdf</literal>"> <!ENTITY t-pdflatex "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>pdflatex</literal>"> <!ENTITY t-pdftex "<literal xmlns='http://www.scons.org/dbxsd/v1.0'>pdftex</literal>"> @@ -186,8 +186,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY t-link-mwcc "<link linkend='t-mwcc' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>mwcc</literal></link>"> <!ENTITY t-link-mwld "<link linkend='t-mwld' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>mwld</literal></link>"> <!ENTITY t-link-nasm "<link linkend='t-nasm' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>nasm</literal></link>"> -<!ENTITY t-link-Packaging "<link linkend='t-Packaging' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>Packaging</literal></link>"> <!ENTITY t-link-packaging "<link linkend='t-packaging' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>packaging</literal></link>"> +<!ENTITY t-link-Packaging "<link linkend='t-Packaging' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>Packaging</literal></link>"> <!ENTITY t-link-pdf "<link linkend='t-pdf' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>pdf</literal></link>"> <!ENTITY t-link-pdflatex "<link linkend='t-pdflatex' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>pdflatex</literal></link>"> <!ENTITY t-link-pdftex "<link linkend='t-pdftex' xmlns='http://www.scons.org/dbxsd/v1.0'><literal>pdftex</literal></link>"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index 8a8dc99..c7048b4 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -31,6 +31,94 @@ if <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"><enva </para> </listitem> </varlistentry> + <varlistentry id="cv-_APPLELINK_COMPATIBILITY_VERSION"> + <term>_APPLELINK_COMPATIBILITY_VERSION</term> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + A macro (by default a generator function) used to create the linker flags to specify + apple's linker's -compatibility_version flag. + The default generator uses <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-APPLELINK_COMPATIBILITY_VERSION"><envar>$APPLELINK_COMPATIBILITY_VERSION</envar></link> + and <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-APPLELINK_NO_COMPATIBILITY_VERSION"><envar>$APPLELINK_NO_COMPATIBILITY_VERSION</envar></link> and <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"><envar>$SHLIBVERSION</envar></link> + to determine the correct flag. + </para> + </listitem> + </varlistentry> + <varlistentry id="cv-APPLELINK_COMPATIBILITY_VERSION"> + <term>APPLELINK_COMPATIBILITY_VERSION</term> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + On Mac OS X this is used to set the linker flag: + + -compatibility_version + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and + 255, Z can be omitted or between 1 and 255. This value will be derived from <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"><envar>$SHLIBVERSION</envar></link> if + not + specified. The lowest digit will be dropped and replaced by a 0. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + If the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-APPLELINK_NO_COMPATIBILITY_VERSION"><envar>$APPLELINK_NO_COMPATIBILITY_VERSION</envar></link> is set then no -compatibility_version will be + output. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0">See MacOS's ld manpage for more details</para> + </listitem> + </varlistentry> + <varlistentry id="cv-_APPLELINK_CURRENT_VERSION"> + <term>_APPLELINK_CURRENT_VERSION</term> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + A macro (by default a generator function) used to create the linker flags to specify apple's linker's + -current_version flag. The default generator uses <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-APPLELINK_CURRENT_VERSION"><envar>$APPLELINK_CURRENT_VERSION</envar></link> and + <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-APPLELINK_NO_CURRENT_VERSION"><envar>$APPLELINK_NO_CURRENT_VERSION</envar></link> and <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"><envar>$SHLIBVERSION</envar></link> to determine the correct flag. + </para> + </listitem> + </varlistentry> + <varlistentry id="cv-APPLELINK_CURRENT_VERSION"> + <term>APPLELINK_CURRENT_VERSION</term> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + On Mac OS X this is used to set the linker flag: + + -current_version + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and + 255, Z can be omitted or between 1 and 255. This value will be set to <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"><envar>$SHLIBVERSION</envar></link> if not + specified. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + If the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-APPLELINK_NO_CURRENT_VERSION"><envar>$APPLELINK_NO_CURRENT_VERSION</envar></link> is set then no -current_version will be + output. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0">See MacOS's ld manpage for more details</para> + + </listitem> + </varlistentry> + <varlistentry id="cv-APPLELINK_NO_COMPATIBILITY_VERSION"> + <term>APPLELINK_NO_COMPATIBILITY_VERSION</term> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Set this to any True (1|True|non-empty string) value to disable adding -compatibility_version flag when + generating versioned shared libraries. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + This overrides <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-APPLELINK_COMPATIBILITY_VERSION"><envar>$APPLELINK_COMPATIBILITY_VERSION</envar></link>. + </para> + </listitem> + </varlistentry> + <varlistentry id="cv-APPLELINK_NO_CURRENT_VERSION"> + <term>APPLELINK_NO_CURRENT_VERSION</term> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Set this to any True (1|True|non-empty string) value to disable adding -current_version flag when + generating versioned shared libraries. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + This overrides <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-APPLELINK_CURRENT_VERSION"><envar>$APPLELINK_CURRENT_VERSION</envar></link>. + </para> + </listitem> + </varlistentry> <varlistentry id="cv-AR"> <term>AR</term> <listitem> @@ -51,7 +139,9 @@ This is used to fill in the <literal>Architecture:</literal> field in an Ipkg <filename>control</filename> file, -and as part of the name of a generated RPM file. +and the <literal>BuildArch:</literal> field +in the RPM <filename>.spec</filename> file, +as well as forming part of the name of a generated RPM package file. </para> </listitem> </varlistentry> @@ -240,7 +330,7 @@ or this: <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> env = Environment() -env['BUILDERS]['NewBuilder'] = foo +env['BUILDERS']['NewBuilder'] = foo </example_commands> </listitem> </varlistentry> @@ -389,7 +479,6 @@ the <filename>control</filename> for Ipkg, the <filename>.wxs</filename> for MSI). If set, the function will be called after the SCons template for the file has been written. -XXX </para> </listitem> </varlistentry> @@ -480,7 +569,8 @@ An automatically-generated construction variable containing the C preprocessor command-line options to define values. The value of <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_CPPDEFFLAGS</envar> is created -by appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFSUFFIX</envar> +by respectively prepending and appending +<envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFSUFFIX</envar> to the beginning and end of each definition in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFINES</envar>. </para> @@ -503,7 +593,8 @@ If <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFINES</envar> is a strin the values of the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFSUFFIX</envar> construction variables -will be added to the beginning and end. +will be respectively prepended and appended to the beginning and end +of each definition in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFINES</envar>. </para> <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> @@ -517,7 +608,7 @@ If <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFINES</envar> is a list, the values of the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFSUFFIX</envar> construction variables -will be appended to the beginning and end +will be respectively prepended and appended to the beginning and end of each element in the list. If any element is a list or tuple, then the first item is the name being @@ -535,7 +626,7 @@ If <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFINES</envar> is a dicti the values of the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFSUFFIX</envar> construction variables -will be appended to the beginning and end +will be respectively prepended and appended to the beginning and end of each item from the dictionary. The key of each dictionary item is a name being defined @@ -563,7 +654,7 @@ env = Environment(CPPDEFINES={'B':2, 'A':None}) <para xmlns="http://www.scons.org/dbxsd/v1.0"> The prefix used to specify preprocessor definitions on the C compiler command line. -This will be appended to the beginning of each definition +This will be prepended to the beginning of each definition in the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPDEFINES</envar> construction variable when the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_CPPDEFFLAGS</envar> variable is automatically generated. </para> @@ -619,7 +710,7 @@ An automatically-generated construction variable containing the C preprocessor command-line options for specifying directories to be searched for include files. The value of <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_CPPINCFLAGS</envar> is created -by appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$INCPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$INCSUFFIX</envar> +by respectively prepending and appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$INCPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$INCSUFFIX</envar> to the beginning and end of each directory in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPPATH</envar>. </para> @@ -661,7 +752,7 @@ through the automatically-generated <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_CPPINCFLAGS</envar> construction variable, which is constructed by -appending the values of the +respectively prepending and appending the value of the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$INCPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$INCSUFFIX</envar> construction variables to the beginning and end @@ -2602,7 +2693,8 @@ containing the Fortran compiler command-line options for specifying directories to be searched for include files and module files. The value of <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-_FORTRANINCFLAGS"><envar>$_FORTRANINCFLAGS</envar></link> is created -by prepending/appending <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-INCPREFIX"><envar>$INCPREFIX</envar></link> and <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-INCSUFFIX"><envar>$INCSUFFIX</envar></link> +by respectively prepending and appending +<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-INCPREFIX"><envar>$INCPREFIX</envar></link> and <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-INCSUFFIX"><envar>$INCSUFFIX</envar></link> to the beginning and end of each directory in <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FORTRANPATH"><envar>$FORTRANPATH</envar></link>. </para> @@ -2625,7 +2717,7 @@ for module files, as well. <para xmlns="http://www.scons.org/dbxsd/v1.0"> The prefix used to specify a module directory on the Fortran compiler command line. -This will be appended to the beginning of the directory +This will be prepended to the beginning of the directory in the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FORTRANMODDIR"><envar>$FORTRANMODDIR</envar></link> construction variables when the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-_FORTRANMODFLAG"><envar>$_FORTRANMODFLAG</envar></link> variables is automatically generated. </para> @@ -2637,7 +2729,7 @@ when the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-_FORTRANMODFL <para xmlns="http://www.scons.org/dbxsd/v1.0"> The suffix used to specify a module directory on the Fortran compiler command line. -This will be appended to the beginning of the directory +This will be appended to the end of the directory in the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FORTRANMODDIR"><envar>$FORTRANMODDIR</envar></link> construction variables when the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-_FORTRANMODFLAG"><envar>$_FORTRANMODFLAG</envar></link> variables is automatically generated. </para> @@ -2653,8 +2745,8 @@ for specifying the directory location where the Fortran compiler should place any module files that happen to get generated during compilation. The value of <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-_FORTRANMODFLAG"><envar>$_FORTRANMODFLAG</envar></link> is created -by prepending/appending <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FORTRANMODDIRPREFIX"><envar>$FORTRANMODDIRPREFIX</envar></link> and -<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FORTRANMODDIRSUFFIX"><envar>$FORTRANMODDIRSUFFIX</envar></link> +by respectively prepending and appending +<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FORTRANMODDIRPREFIX"><envar>$FORTRANMODDIRPREFIX</envar></link> and <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FORTRANMODDIRSUFFIX"><envar>$FORTRANMODDIRSUFFIX</envar></link> to the beginning and end of the directory in <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FORTRANMODDIR"><envar>$FORTRANMODDIR</envar></link>. </para> </listitem> @@ -2727,7 +2819,7 @@ through the automatically-generated <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-_FORTRANINCFLAGS"><envar>$_FORTRANINCFLAGS</envar></link> construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-INCPREFIX"><envar>$INCPREFIX</envar></link> and <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-INCSUFFIX"><envar>$INCSUFFIX</envar></link> construction variables to the beginning and end @@ -2797,107 +2889,107 @@ The default list is: <varlistentry id="cv-FRAMEWORKPATH"> <term>FRAMEWORKPATH</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -On Mac OS X with gcc, -a list containing the paths to search for frameworks. -Used by the compiler to find framework-style includes like -#include <Fmwk/Header.h>. -Used by the linker to find user-specified frameworks when linking (see -<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKS"><envar>$FRAMEWORKS</envar></link>). -For example: -</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + On Mac OS X with gcc, + a list containing the paths to search for frameworks. + Used by the compiler to find framework-style includes like + #include <Fmwk/Header.h>. + Used by the linker to find user-specified frameworks when linking (see + <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKS"><envar>$FRAMEWORKS</envar></link>). + For example: + </para> -<example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> - env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') -</example_commands> + <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> + env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') + </example_commands> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -will add -</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + will add + </para> -<example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> - ... -Fmyframeworkdir -</example_commands> + <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> + ... -Fmyframeworkdir + </example_commands> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -to the compiler and linker command lines. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + to the compiler and linker command lines. + </para> + </listitem> </varlistentry> <varlistentry id="cv-_FRAMEWORKPATH"> <term>_FRAMEWORKPATH</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -On Mac OS X with gcc, an automatically-generated construction variable -containing the linker command-line options corresponding to -<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPATH"><envar>$FRAMEWORKPATH</envar></link>. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + On Mac OS X with gcc, an automatically-generated construction variable + containing the linker command-line options corresponding to + <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPATH"><envar>$FRAMEWORKPATH</envar></link>. + </para> + </listitem> </varlistentry> <varlistentry id="cv-FRAMEWORKPATHPREFIX"> <term>FRAMEWORKPATHPREFIX</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -On Mac OS X with gcc, the prefix to be used for the FRAMEWORKPATH entries. -(see <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPATH"><envar>$FRAMEWORKPATH</envar></link>). -The default value is -<option>-F</option>. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + On Mac OS X with gcc, the prefix to be used for the FRAMEWORKPATH entries. + (see <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPATH"><envar>$FRAMEWORKPATH</envar></link>). + The default value is + <option>-F</option>. + </para> + </listitem> </varlistentry> <varlistentry id="cv-FRAMEWORKPREFIX"> <term>FRAMEWORKPREFIX</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -On Mac OS X with gcc, -the prefix to be used for linking in frameworks -(see <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKS"><envar>$FRAMEWORKS</envar></link>). -The default value is -<option>-framework</option>. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + On Mac OS X with gcc, + the prefix to be used for linking in frameworks + (see <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKS"><envar>$FRAMEWORKS</envar></link>). + The default value is + <option>-framework</option>. + </para> + </listitem> </varlistentry> <varlistentry id="cv-_FRAMEWORKS"> <term>_FRAMEWORKS</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -On Mac OS X with gcc, -an automatically-generated construction variable -containing the linker command-line options -for linking with FRAMEWORKS. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + On Mac OS X with gcc, + an automatically-generated construction variable + containing the linker command-line options + for linking with FRAMEWORKS. + </para> + </listitem> </varlistentry> <varlistentry id="cv-FRAMEWORKS"> <term>FRAMEWORKS</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -On Mac OS X with gcc, a list of the framework names to be linked into a -program or shared library or bundle. -The default value is the empty list. -For example: -</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + On Mac OS X with gcc, a list of the framework names to be linked into a + program or shared library or bundle. + The default value is the empty list. + For example: + </para> -<example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> - env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) -</example_commands> + <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> + env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) + </example_commands> -</listitem> + </listitem> </varlistentry> <varlistentry id="cv-FRAMEWORKSFLAGS"> <term>FRAMEWORKSFLAGS</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -On Mac OS X with gcc, -general user-supplied frameworks options to be added at -the end of a command -line building a loadable module. -(This has been largely superseded by -the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPATH"><envar>$FRAMEWORKPATH</envar></link>, <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPATHPREFIX"><envar>$FRAMEWORKPATHPREFIX</envar></link>, -<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPREFIX"><envar>$FRAMEWORKPREFIX</envar></link> and <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKS"><envar>$FRAMEWORKS</envar></link> variables -described above.) -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + On Mac OS X with gcc, + general user-supplied frameworks options to be added at + the end of a command + line building a loadable module. + (This has been largely superseded by + the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPATH"><envar>$FRAMEWORKPATH</envar></link>, <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPATHPREFIX"><envar>$FRAMEWORKPATHPREFIX</envar></link>, + <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKPREFIX"><envar>$FRAMEWORKPREFIX</envar></link> and <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-FRAMEWORKS"><envar>$FRAMEWORKS</envar></link> variables + described above.) + </para> + </listitem> </varlistentry> <varlistentry id="cv-GS"> <term>GS</term> @@ -2940,6 +3032,15 @@ is <quote><literal>-dNOPAUSE -dBATCH -sDEVICE=pdfwrite</literal></quote> <term>HOST_ARCH</term> <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The name of the host hardware architecture used to create the Environment. + If a platform is specified when creating the Environment, then + that Platform's logic will handle setting this value. + This value is immutable, and should not be changed by the user after + the Environment is initialized. + Currently only set for Win32. +</para> + +<para xmlns="http://www.scons.org/dbxsd/v1.0"> Sets the host architecture for Visual Studio compiler. If not set, default to the detected host architecture: note that this may depend on the python you are using. @@ -2955,16 +3056,7 @@ Valid values are the same as for <envar xmlns="http://www.scons.org/dbxsd/v1.0"> This is currently only used on Windows, but in the future it will be used on other OSes as well. </para> - -<para xmlns="http://www.scons.org/dbxsd/v1.0"> - The name of the host hardware architecture used to create the Environment. - If a platform is specified when creating the Environment, then - that Platform's logic will handle setting this value. - This value is immutable, and should not be changed by the user after - the Environment is initialized. - Currently only set for Win32. -</para> - </listitem> +</listitem> </varlistentry> <varlistentry id="cv-HOST_OS"> <term>HOST_OS</term> @@ -3087,7 +3179,7 @@ env = Environment(IMPLICIT_COMMAND_DEPENDENCIES = 0) <para xmlns="http://www.scons.org/dbxsd/v1.0"> The prefix used to specify an include directory on the C compiler command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPPATH</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$FORTRANPATH</envar> construction variables when the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_CPPINCFLAGS</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_FORTRANINCFLAGS</envar> variables are automatically generated. @@ -3206,7 +3298,7 @@ The command line used to call the Java archive tool. <para xmlns="http://www.scons.org/dbxsd/v1.0"> The string displayed when the Java archive tool is called -If this is not set, then <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-JARCOM"><envar>$JARCOM</envar></link> (the command line) is displayed. +If this is not set, then <envar xmlns="http://www.scons.org/dbxsd/v1.0">$JARCOM</envar> (the command line) is displayed. </para> <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> @@ -3216,7 +3308,7 @@ env = Environment(JARCOMSTR = "JARchiving $SOURCES into $TARGET") <para xmlns="http://www.scons.org/dbxsd/v1.0"> The string displayed when the Java archive tool is called -If this is not set, then <envar xmlns="http://www.scons.org/dbxsd/v1.0">$JARCOM</envar> (the command line) is displayed. +If this is not set, then <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-JARCOM"><envar>$JARCOM</envar></link> (the command line) is displayed. </para> <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> @@ -3265,107 +3357,111 @@ by default. <varlistentry id="cv-JAVABOOTCLASSPATH"> <term>JAVABOOTCLASSPATH</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Specifies the list of directories that -will be added to the -<application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> command line -via the <option>-bootclasspath</option> option. -The individual directory names will be -separated by the operating system's path separate character -(<filename>:</filename> on UNIX/Linux/POSIX, -<filename>;</filename> on Windows). -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Specifies the list of directories that + will be added to the + <application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> command line + via the <option>-bootclasspath</option> option. + The individual directory names will be + separated by the operating system's path separate character + (<filename>:</filename> on UNIX/Linux/POSIX, + <filename>;</filename> + on Windows). + </para> + </listitem> </varlistentry> <varlistentry id="cv-JAVAC"> <term>JAVAC</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -The Java compiler. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The Java compiler. + </para> + </listitem> </varlistentry> <varlistentry id="cv-JAVACCOM"> <term>JAVACCOM</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -The command line used to compile a directory tree containing -Java source files to -corresponding Java class files. -Any options specified in the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-JAVACFLAGS"><envar>$JAVACFLAGS</envar></link> construction variable -are included on this command line. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The command line used to compile a directory tree containing + Java source files to + corresponding Java class files. + Any options specified in the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-JAVACFLAGS"><envar>$JAVACFLAGS</envar></link> construction variable + are included on this command line. + </para> + </listitem> </varlistentry> <varlistentry id="cv-JAVACCOMSTR"> <term>JAVACCOMSTR</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -The string displayed when compiling -a directory tree of Java source files to -corresponding Java class files. -If this is not set, then <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-JAVACCOM"><envar>$JAVACCOM</envar></link> (the command line) is displayed. -</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The string displayed when compiling + a directory tree of Java source files to + corresponding Java class files. + If this is not set, then <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-JAVACCOM"><envar>$JAVACCOM</envar></link> (the command line) is displayed. + </para> -<example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> -env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") -</example_commands> -</listitem> + <example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> + env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") + </example_commands> + </listitem> </varlistentry> <varlistentry id="cv-JAVACFLAGS"> <term>JAVACFLAGS</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -General options that are passed to the Java compiler. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + General options that are passed to the Java compiler. + </para> + </listitem> </varlistentry> <varlistentry id="cv-JAVACLASSDIR"> <term>JAVACLASSDIR</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -The directory in which Java class files may be found. -This is stripped from the beginning of any Java .class -file names supplied to the -<literal>JavaH</literal> -builder. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The directory in which Java class files may be found. + This is stripped from the beginning of any Java .class + file names supplied to the + <literal>JavaH</literal> + builder. + </para> + </listitem> </varlistentry> <varlistentry id="cv-JAVACLASSPATH"> <term>JAVACLASSPATH</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Specifies the list of directories that -will be searched for Java -<filename>.class</filename> file. -The directories in this list will be added to the -<application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> and <application xmlns="http://www.scons.org/dbxsd/v1.0">javah</application> command lines -via the <option>-classpath</option> option. -The individual directory names will be -separated by the operating system's path separate character -(<filename>:</filename> on UNIX/Linux/POSIX, -<filename>;</filename> on Windows). -</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Specifies the list of directories that + will be searched for Java + <filename>.class</filename> + file. + The directories in this list will be added to the + <application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> and <application xmlns="http://www.scons.org/dbxsd/v1.0">javah</application> command lines + via the <option>-classpath</option> option. + The individual directory names will be + separated by the operating system's path separate character + (<filename>:</filename> on UNIX/Linux/POSIX, + <filename>;</filename> + on Windows). + </para> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Note that this currently just adds the specified -directory via the <option>-classpath</option> option. -<application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> does not currently search the -<envar xmlns="http://www.scons.org/dbxsd/v1.0">$JAVACLASSPATH</envar> directories for dependency -<filename>.class</filename> files. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Note that this currently just adds the specified + directory via the <option>-classpath</option> option. + <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> does not currently search the + <envar xmlns="http://www.scons.org/dbxsd/v1.0">$JAVACLASSPATH</envar> directories for dependency + <filename>.class</filename> + files. + </para> + </listitem> </varlistentry> <varlistentry id="cv-JAVACLASSSUFFIX"> <term>JAVACLASSSUFFIX</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -The suffix for Java class files; -<filename>.class</filename> -by default. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The suffix for Java class files; + <filename>.class</filename> + by default. + </para> + </listitem> </varlistentry> <varlistentry id="cv-JAVAH"> <term>JAVAH</term> @@ -3409,65 +3505,77 @@ for Java classes. </para> </listitem> </varlistentry> + <varlistentry id="cv-JAVAINCLUDES"> + <term>JAVAINCLUDES</term> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Include path for Java header files (such as jni.h) + </para> + </listitem> + </varlistentry> <varlistentry id="cv-JAVASOURCEPATH"> <term>JAVASOURCEPATH</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Specifies the list of directories that -will be searched for input -<filename>.java</filename> file. -The directories in this list will be added to the -<application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> command line -via the <option>-sourcepath</option> option. -The individual directory names will be -separated by the operating system's path separate character -(<filename>:</filename> on UNIX/Linux/POSIX, -<filename>;</filename> on Windows). -</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Specifies the list of directories that + will be searched for input + <filename>.java</filename> + file. + The directories in this list will be added to the + <application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> command line + via the <option>-sourcepath</option> option. + The individual directory names will be + separated by the operating system's path separate character + (<filename>:</filename> on UNIX/Linux/POSIX, + <filename>;</filename> + on Windows). + </para> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Note that this currently just adds the specified -directory via the <option>-sourcepath</option> option. -<application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> does not currently search the -<envar xmlns="http://www.scons.org/dbxsd/v1.0">$JAVASOURCEPATH</envar> directories for dependency -<filename>.java</filename> files. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Note that this currently just adds the specified + directory via the <option>-sourcepath</option> option. + <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> does not currently search the + <envar xmlns="http://www.scons.org/dbxsd/v1.0">$JAVASOURCEPATH</envar> directories for dependency + <filename>.java</filename> + files. + </para> + </listitem> </varlistentry> <varlistentry id="cv-JAVASUFFIX"> <term>JAVASUFFIX</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -The suffix for Java files; -<filename>.java</filename> -by default. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The suffix for Java files; + <filename>.java</filename> + by default. + </para> + </listitem> </varlistentry> <varlistentry id="cv-JAVAVERSION"> <term>JAVAVERSION</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Specifies the Java version being used by the <function xmlns="http://www.scons.org/dbxsd/v1.0">Java</function> builder. -This is <emphasis>not</emphasis> currently used to select one -version of the Java compiler vs. another. -Instead, you should set this to specify the version of Java -supported by your <application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> compiler. -The default is <literal>1.4</literal>. -</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + Specifies the Java version being used by the <function xmlns="http://www.scons.org/dbxsd/v1.0">Java</function> builder. + This is <emphasis>not</emphasis> currently used to select one + version of the Java compiler vs. another. + Instead, you should set this to specify the version of Java + supported by your <application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> compiler. + The default is <literal>1.4</literal>. + </para> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -This is sometimes necessary because -Java 1.5 changed the file names that are created -for nested anonymous inner classes, -which can cause a mismatch with the files -that <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> expects will be generated by the <application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> compiler. -Setting <envar xmlns="http://www.scons.org/dbxsd/v1.0">$JAVAVERSION</envar> to <literal>1.5</literal> -(or <literal>1.6</literal>, as appropriate) -can make <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> realize that a Java 1.5 or 1.6 -build is actually up to date. -</para> -</listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + This is sometimes necessary because + Java 1.5 changed the file names that are created + for nested anonymous inner classes, + which can cause a mismatch with the files + that <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> expects will be generated by the <application xmlns="http://www.scons.org/dbxsd/v1.0">javac</application> compiler. + Setting <envar xmlns="http://www.scons.org/dbxsd/v1.0">$JAVAVERSION</envar> to + <literal>1.5</literal> + (or <literal>1.6</literal>, as appropriate) + can make <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> realize that a Java 1.5 or 1.6 + build is actually up to date. + </para> + </listitem> </varlistentry> <varlistentry id="cv-LATEX"> <term>LATEX</term> @@ -3690,6 +3798,14 @@ General options passed to the lexical analyzer generator. </para> </listitem> </varlistentry> + <varlistentry id="cv-LEXUNISTD"> + <term>LEXUNISTD</term> + <listitem> +<para xmlns="http://www.scons.org/dbxsd/v1.0"> +Used only on windows environments to set a lex flag to prevent 'unistd.h' from being included. The default value is '--nounistd'. +</para> +</listitem> + </varlistentry> <varlistentry id="cv-_LIBDIRFLAGS"> <term>_LIBDIRFLAGS</term> <listitem> @@ -3698,7 +3814,7 @@ An automatically-generated construction variable containing the linker command-line options for specifying directories to be searched for library. The value of <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_LIBDIRFLAGS</envar> is created -by appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBDIRPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBDIRSUFFIX</envar> +by respectively prepending and appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBDIRPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBDIRSUFFIX</envar> to the beginning and end of each directory in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBPATH</envar>. </para> @@ -3709,7 +3825,7 @@ of each directory in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBPATH</en <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> The prefix used to specify a library directory on the linker command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBPATH</envar> construction variable when the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_LIBDIRFLAGS</envar> variable is automatically generated. </para> @@ -3742,7 +3858,7 @@ An automatically-generated construction variable containing the linker command-line options for specifying libraries to be linked with the resulting target. The value of <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_LIBFLAGS</envar> is created -by appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBLINKPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBLINKSUFFIX</envar> +by respectively prepending and appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBLINKPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBLINKSUFFIX</envar> to the beginning and end of each filename in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBS</envar>. </para> @@ -3753,7 +3869,7 @@ of each filename in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBS</envar> <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> The prefix used to specify a library to link on the linker command line. -This will be appended to the beginning of each library +This will be prepended to the beginning of each library in the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBS</envar> construction variable when the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_LIBFLAGS</envar> variable is automatically generated. </para> @@ -3807,7 +3923,7 @@ through the automatically-generated <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_LIBDIRFLAGS</envar> construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBDIRPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBDIRSUFFIX</envar> construction variables to the beginning and end @@ -3863,7 +3979,7 @@ through the automatically-generated <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_LIBFLAGS</envar> construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBLINKPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$LIBLINKSUFFIX</envar> construction variables to the beginning and end @@ -3930,10 +4046,10 @@ and these suffixes. <term>LICENSE</term> <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> -The abbreviated name of the license under which -this project is released (gpl, lpgl, bsd etc.). +The abbreviated name, preferably the SPDX code, of the license under which +this project is released (GPL-3.0, LGPL-2.1, BSD-2-Clause etc.). See http://www.opensource.org/licenses/alphabetical -for a list of license names. +for a list of license names and SPDX codes. </para> </listitem> </varlistentry> @@ -4379,6 +4495,7 @@ constructor; setting it later has no effect. <para xmlns="http://www.scons.org/dbxsd/v1.0"> Valid values for Windows are +<literal>14.1</literal>, <literal>14.0</literal>, <literal>14.0Exp</literal>, <literal>12.0</literal>, @@ -4402,254 +4519,311 @@ Versions ending in <literal>Exp</literal> refer to "Express" or </varlistentry> <varlistentry id="cv-MSVS"> <term>MSVS</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> -When the Microsoft Visual Studio tools are initialized, they set up this -dictionary with the following keys: </para><variablelist xmlns="http://www.scons.org/dbxsd/v1.0"> - <varlistentry> - <term>VERSION</term> - - <listitem> - <para>the version of MSVS being used (can be set via - <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVS_VERSION"><envar>$MSVS_VERSION</envar></link>)</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>VERSIONS</term> - - <listitem> - <para>the available versions of MSVS installed</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>VCINSTALLDIR</term> - - <listitem> - <para>installed directory of Visual C++</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>VSINSTALLDIR</term> - - <listitem> - <para>installed directory of Visual Studio</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKDIR</term> - - <listitem> - <para>installed directory of the .NET framework</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKVERSIONS</term> - - <listitem> - <para>list of installed versions of the .NET framework, sorted - latest to oldest.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKVERSION</term> - - <listitem> - <para>latest installed version of the .NET - framework</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKSDKDIR</term> - - <listitem> - <para>installed location of the .NET SDK.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>PLATFORMSDKDIR</term> - - <listitem> - <para>installed location of the Platform SDK.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>PLATFORMSDK_MODULES</term> - - <listitem> - <para>dictionary of installed Platform SDK modules, where the - dictionary keys are keywords for the various modules, and the values - are 2-tuples where the first is the release date, and the second is - the version number.</para> - </listitem> - </varlistentry> - </variablelist><para xmlns="http://www.scons.org/dbxsd/v1.0">If a value isn't set, it wasn't available in the -registry.</para></listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + When the Microsoft Visual Studio tools are initialized, + they set up this dictionary with the following keys: + </para> + <variablelist xmlns="http://www.scons.org/dbxsd/v1.0"> + <varlistentry> + <term>VERSION</term> <listitem> + <para>the version of MSVS being used (can be set via + <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVS_VERSION"><envar>$MSVS_VERSION</envar></link>)</para> + </listitem> + </varlistentry> <varlistentry> + <term>VERSIONS</term> <listitem> + <para>the available versions of MSVS installed</para> + </listitem> + </varlistentry> <varlistentry> + <term>VCINSTALLDIR</term> <listitem> + <para>installed directory of Visual C++</para> + </listitem> + </varlistentry> <varlistentry> + <term>VSINSTALLDIR</term> <listitem> + <para>installed directory of Visual Studio</para> + </listitem> + </varlistentry> <varlistentry> + <term>FRAMEWORKDIR</term> <listitem> + <para>installed directory of the .NET framework</para> + </listitem> + </varlistentry> <varlistentry> + <term>FRAMEWORKVERSIONS</term> <listitem> + <para> + list of installed versions of the .NET framework, + sorted latest to oldest. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>FRAMEWORKVERSION</term> + <listitem> + <para>latest installed version of the .NET framework</para> + </listitem> + </varlistentry> + <varlistentry> + <term>FRAMEWORKSDKDIR</term> + <listitem> + <para>installed location of the .NET SDK.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>PLATFORMSDKDIR</term> + <listitem> + <para>installed location of the Platform SDK.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>PLATFORMSDK_MODULES</term> + <listitem> + <para> + dictionary of installed Platform SDK modules, where the + dictionary keys are keywords for the various modules, + and the values are 2-tuples where the first is the + release date, and the second is the version number. + </para> + </listitem> + </varlistentry> + </variablelist> + <para xmlns="http://www.scons.org/dbxsd/v1.0">If a value is not set, it was not available in the registry.</para> + </listitem> </varlistentry> <varlistentry id="cv-MSVS_ARCH"> <term>MSVS_ARCH</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">Sets -the architecture for which the generated project(s) should build. </para> -<para xmlns="http://www.scons.org/dbxsd/v1.0">The default value is <literal>x86</literal>. <literal>amd64</literal> is -also supported by <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> for some Visual Studio versions. Trying to set -<envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVS_ARCH</envar> to an architecture that's not supported for a given Visual -Studio version will generate an error. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0">Sets the architecture for which the generated project(s) should build.</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The default value is <literal>x86</literal>. + <literal>amd64</literal> is also supported by <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> for + most Visual Studio versions. Since Visual Studio 2015 + <literal>arm</literal> is supported, and since Visual Studio + 2017 <literal>arm64</literal> is supported. + Trying to set <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVS_ARCH</envar> + to an architecture that's not supported for a given Visual + Studio version will generate an error. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVS_PROJECT_GUID"> <term>MSVS_PROJECT_GUID</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The string placed in a generated + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The string placed in a generated Microsoft Visual Studio project file as the value of the -<literal>ProjectGUID</literal> attribute. There is no default value. If not -defined, a new GUID is generated. </para> </listitem> + <literal>ProjectGUID</literal> attribute. There is no default + value. If not +defined, a new GUID is generated. + + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVS_SCC_AUX_PATH"> <term>MSVS_SCC_AUX_PATH</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The path name placed in a generated + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The path name placed in a generated Microsoft Visual Studio project file as the value of the -<literal>SccAuxPath</literal> attribute if the -<envar>MSVS_SCC_PROVIDER</envar> construction variable is also set. There is -no default value. </para> </listitem> + <literal>SccAuxPath</literal> attribute if the + <envar>MSVS_SCC_PROVIDER</envar> construction variable is + also set. There is +no default value. + + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVS_SCC_CONNECTION_ROOT"> <term>MSVS_SCC_CONNECTION_ROOT</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The root path of projects in -your SCC workspace, i.e the path under which all project and solution files -will be generated. It is used as a reference path from which the relative -paths of the generated Microsoft Visual Studio project and solution files are -computed. The relative project file path is placed as the value of the -<literal>SccLocalPath</literal> attribute of the project file and as the -values of the -<literal>SccProjectFilePathRelativizedFromConnection[i]</literal> (where [i] -ranges from 0 to the number of projects in the solution) attributes of the -<literal>GlobalSection(SourceCodeControl)</literal> section of the Microsoft -Visual Studio solution file. Similarly the relative solution file path is -placed as the values of the <literal>SccLocalPath[i]</literal> (where [i] -ranges from 0 to the number of projects in the solution) attributes of the -<literal>GlobalSection(SourceCodeControl)</literal> section of the Microsoft -Visual Studio solution file. This is used only if the -<envar>MSVS_SCC_PROVIDER</envar> construction variable is also set. The -default value is the current working directory. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The root path of projects in your SCC workspace, i.e the + path under which all project and solution files will be + generated. It is used as a reference path from which the + relative paths of the generated Microsoft Visual Studio project + and solution files are computed. The relative project file path + is placed as the value of the <literal>SccLocalPath</literal> + attribute of the project file and as the values of the + <literal>SccProjectFilePathRelativizedFromConnection[i]</literal> + (where [i] ranges from 0 to the number of projects in the solution) + attributes of the <literal>GlobalSection(SourceCodeControl)</literal> + section of the Microsoft Visual Studio solution file. Similarly + the relative solution file path is placed as the values of the + <literal>SccLocalPath[i]</literal> (where [i] ranges from 0 + to the number of projects in the solution) attributes of the + <literal>GlobalSection(SourceCodeControl)</literal> section of + the Microsoft Visual Studio solution file. This is used only if + the <envar>MSVS_SCC_PROVIDER</envar> construction variable is + also set. The default value is the current working directory. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVS_SCC_PROJECT_NAME"> <term>MSVS_SCC_PROJECT_NAME</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The project name placed in -a generated Microsoft Visual Studio project file as the value of the -<literal>SccProjectName</literal> attribute if the -<envar>MSVS_SCC_PROVIDER</envar> construction variable is also set. In this -case the string is also placed in the <literal>SccProjectName0</literal> -attribute of the <literal>GlobalSection(SourceCodeControl)</literal> section -of the Microsoft Visual Studio solution file. There is no default value. -</para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The project name placed in a generated Microsoft + Visual Studio project file as the value of the + <literal>SccProjectName</literal> attribute if the + <envar>MSVS_SCC_PROVIDER</envar> construction variable + is also set. In this case the string is also placed in + the <literal>SccProjectName0</literal> attribute of the + <literal>GlobalSection(SourceCodeControl)</literal> section + of the Microsoft Visual Studio solution file. There is no + default value. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVS_SCC_PROVIDER"> <term>MSVS_SCC_PROVIDER</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The -string placed in a generated Microsoft Visual Studio project file as the value -of the <literal>SccProvider</literal> attribute. The string is also placed in -the <literal>SccProvider0</literal> attribute of the -<literal>GlobalSection(SourceCodeControl)</literal> section of the Microsoft -Visual Studio solution file. There is no default value. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The string placed in a generated Microsoft + Visual Studio project file as the value of the + <literal>SccProvider</literal> attribute. The string is + also placed in the <literal>SccProvider0</literal> attribute + of the <literal>GlobalSection(SourceCodeControl)</literal> + section of the Microsoft Visual Studio solution file. There + is no default value. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVS_VERSION"> <term>MSVS_VERSION</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">Sets the preferred version -of Microsoft Visual Studio to use. </para> <para xmlns="http://www.scons.org/dbxsd/v1.0">If <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVS_VERSION</envar> is not -set, <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> will (by default) select the latest version of Visual Studio -installed on your system. So, if you have version 6 and version 7 (MSVS .NET) -installed, it will prefer version 7. You can override this by specifying the -<envar>MSVS_VERSION</envar> variable in the Environment initialization, -setting it to the appropriate version ('6.0' or '7.0', for example). If the -specified version isn't installed, tool initialization will fail. </para> -<para xmlns="http://www.scons.org/dbxsd/v1.0">This is obsolete: use <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVC_VERSION</envar> instead. If <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVS_VERSION</envar> is -set and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVC_VERSION</envar> is not, <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVC_VERSION</envar> will be set automatically -to <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVS_VERSION</envar>. If both are set to different values, scons will raise an -error. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0">Sets the preferred version of Microsoft Visual Studio to use.</para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + If <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVS_VERSION</envar> is not set, <application xmlns="http://www.scons.org/dbxsd/v1.0">SCons</application> will (by default) + select the latest version of Visual Studio installed on your + system. So, if you have version 6 and version 7 (MSVS .NET) + installed, it will prefer version 7. You can override this by + specifying the <envar>MSVS_VERSION</envar> variable in the + Environment initialization, setting it to the appropriate + version ('6.0' or '7.0', for example). If the specified + version isn't installed, tool initialization will fail. + </para> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + This is obsolete: use <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVC_VERSION</envar> instead. If + <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVS_VERSION</envar> is set and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVC_VERSION</envar> is + not, <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVC_VERSION</envar> will be set automatically to + <envar xmlns="http://www.scons.org/dbxsd/v1.0">$MSVS_VERSION</envar>. If both are set to different values, + scons will raise an error. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSBUILDCOM"> <term>MSVSBUILDCOM</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0">The build command line placed in a generated Microsoft Visual Studio -project file. The default is to have Visual Studio invoke SCons with any -specified build targets. </para> </listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The build command line placed in a generated Microsoft Visual + Studio project file. The default is to have Visual Studio + invoke SCons with any specified build targets. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSCLEANCOM"> <term>MSVSCLEANCOM</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The clean command line placed in a generated Microsoft Visual -Studio project file. The default is to have Visual Studio invoke SCons with -the -c option to remove any specified targets. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The clean command line placed in a generated Microsoft Visual + Studio project file. The default is to have Visual Studio + invoke SCons with the -c option to remove any specified + targets. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSENCODING"> <term>MSVSENCODING</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The encoding string placed in a -generated Microsoft Visual Studio project file. The default is encoding -<literal>Windows-1252</literal>. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The encoding string placed in a generated Microsoft + Visual Studio project file. The default is encoding + <literal>Windows-1252</literal>. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSPROJECTCOM"> <term>MSVSPROJECTCOM</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The action used to generate Microsoft -Visual Studio project files. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0">The action used to generate Microsoft Visual Studio project files.</para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSPROJECTSUFFIX"> <term>MSVSPROJECTSUFFIX</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The suffix used for Microsoft Visual -Studio project (DSP) files. The default value is <filename>.vcproj</filename> -when using Visual Studio version 7.x (.NET) or later version, and -<filename>.dsp</filename> when using earlier versions of Visual Studio. -</para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The suffix used for Microsoft Visual Studio project (DSP) + files. The default value is <filename>.vcproj</filename> + when using Visual Studio version 7.x (.NET) or later version, + and <filename>.dsp</filename> when using earlier versions of + Visual Studio. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSREBUILDCOM"> <term>MSVSREBUILDCOM</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The -rebuild command line placed in a generated Microsoft Visual Studio project -file. The default is to have Visual Studio invoke SCons with any specified -rebuild targets. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The rebuild command line placed in a generated Microsoft + Visual Studio project file. The default is to have Visual + Studio invoke SCons with any specified rebuild targets. + + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSSCONS"> <term>MSVSSCONS</term> <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0">The SCons used in generated Microsoft Visual Studio project files. The -default is the version of SCons being used to generate the project file. -</para> </listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The SCons used in generated Microsoft Visual Studio project + files. The default is the version of SCons being used to + generate the project file. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSSCONSCOM"> <term>MSVSSCONSCOM</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The default -SCons command used in generated Microsoft Visual Studio project files. </para> -</listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The default SCons command used in generated Microsoft Visual + Studio project files. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSSCONSCRIPT"> <term>MSVSSCONSCRIPT</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The sconscript -file (that is, <filename xmlns="http://www.scons.org/dbxsd/v1.0">SConstruct</filename> or <filename xmlns="http://www.scons.org/dbxsd/v1.0">SConscript</filename> file) that will be invoked by -Visual Studio project files (through the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVSSCONSCOM"><envar>$MSVSSCONSCOM</envar></link> variable). The -default is the same sconscript file that contains the call to <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function> -to build the project file. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The sconscript file (that is, <filename xmlns="http://www.scons.org/dbxsd/v1.0">SConstruct</filename> or <filename xmlns="http://www.scons.org/dbxsd/v1.0">SConscript</filename> + file) that will be invoked by Visual Studio project files + (through the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVSSCONSCOM"><envar>$MSVSSCONSCOM</envar></link> variable). The default + is the same sconscript file that contains the call to + <function xmlns="http://www.scons.org/dbxsd/v1.0">MSVSProject</function> to build the project file. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSSCONSFLAGS"> <term>MSVSSCONSFLAGS</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The -SCons flags used in generated Microsoft Visual Studio project files. </para> -</listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The SCons flags used in generated Microsoft Visual Studio project files. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSSOLUTIONCOM"> <term>MSVSSOLUTIONCOM</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The action used to generate Microsoft -Visual Studio solution files. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0">The action used to generate Microsoft Visual Studio solution files.</para> + </listitem> </varlistentry> <varlistentry id="cv-MSVSSOLUTIONSUFFIX"> <term>MSVSSOLUTIONSUFFIX</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The suffix used for Microsoft -Visual Studio solution (DSW) files. The default value is -<filename>.sln</filename> when using Visual Studio version 7.x (.NET), and -<filename>.dsw</filename> when using earlier versions of Visual Studio. -</para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The suffix used for Microsoft Visual Studio solution (DSW) + files. The default value is <filename>.sln</filename> + when using Visual Studio version 7.x (.NET), and + <filename>.dsw</filename> when using earlier versions of + Visual Studio. + </para> + </listitem> </varlistentry> <varlistentry id="cv-MT"> <term>MT</term> @@ -5601,7 +5775,8 @@ containing the command-line options for specifying directories to be searched by the resource compiler. The value of <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RCINCFLAGS</envar> is created -by appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RCINCPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RCINCSUFFIX</envar> +by respectively prepending and appending +<envar xmlns="http://www.scons.org/dbxsd/v1.0">$RCINCPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RCINCSUFFIX</envar> to the beginning and end of each directory in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPPATH</envar>. </para> @@ -5613,7 +5788,7 @@ of each directory in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPPATH</en <para xmlns="http://www.scons.org/dbxsd/v1.0"> The prefix (flag) used to specify an include directory on the resource compiler command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$CPPPATH</envar> construction variable when the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RCINCFLAGS</envar> variable is expanded. </para> @@ -5735,7 +5910,7 @@ An automatically-generated construction variable containing the rpath flags to be used when linking a program with shared libraries. The value of <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_RPATH</envar> is created -by appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RPATHPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RPATHSUFFIX</envar> +by respectively prepending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RPATHPREFIX</envar> and appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RPATHSUFFIX</envar> to the beginning and end of each directory in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RPATH</envar>. </para> @@ -5763,7 +5938,7 @@ path, you must make it absolute yourself. <para xmlns="http://www.scons.org/dbxsd/v1.0"> The prefix used to specify a directory to be searched for shared libraries when running programs. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$RPATH</envar> construction variable when the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_RPATH</envar> variable is automatically generated. </para> @@ -5863,11 +6038,15 @@ below, for more information. </varlistentry> <varlistentry id="cv-SCONS_HOME"> <term>SCONS_HOME</term> - <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0">The -(optional) path to the SCons library directory, initialized from the external -environment. If set, this is used to construct a shorter and more efficient -search path in the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVSSCONS"><envar>$MSVSSCONS</envar></link> command line executed from Microsoft -Visual Studio project files. </para> </listitem> + <listitem> + <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The (optional) path to the SCons library directory, + initialized from the external environment. If set, this is + used to construct a shorter and more efficient search path in + the <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-MSVSSCONS"><envar>$MSVSSCONS</envar></link> command line executed from Microsoft + Visual Studio project files. + </para> + </listitem> </varlistentry> <varlistentry id="cv-SHCC"> <term>SHCC</term> @@ -6610,16 +6789,6 @@ Example <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"> </para> </listitem> </varlistentry> - <varlistentry id="cv-SHLIBVERSIONFLAGS"> - <term>SHLIBVERSIONFLAGS</term> - <listitem> -<para xmlns="http://www.scons.org/dbxsd/v1.0"> -Extra flags added to <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLINKCOM"><envar>$SHLINKCOM</envar></link> when building versioned -<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="b-SharedLibrary"><function>SharedLibrary</function></link>. These flags are only used when <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"><envar>$SHLIBVERSION</envar></link> is -set. -</para> -</listitem> - </varlistentry> <varlistentry id="cv-_SHLIBVERSIONFLAGS"> <term>_SHLIBVERSIONFLAGS</term> <listitem> @@ -6633,6 +6802,16 @@ and some extra dynamically generated options (such as </para> </listitem> </varlistentry> + <varlistentry id="cv-SHLIBVERSIONFLAGS"> + <term>SHLIBVERSIONFLAGS</term> + <listitem> +<para xmlns="http://www.scons.org/dbxsd/v1.0"> +Extra flags added to <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLINKCOM"><envar>$SHLINKCOM</envar></link> when building versioned +<link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="b-SharedLibrary"><function>SharedLibrary</function></link>. These flags are only used when <link xmlns="http://www.scons.org/dbxsd/v1.0" linkend="cv-SHLIBVERSION"><envar>$SHLIBVERSION</envar></link> is +set. +</para> +</listitem> + </varlistentry> <varlistentry id="cv-SHLINK"> <term>SHLINK</term> <listitem> @@ -6935,7 +7114,8 @@ An automatically-generated construction variable containing the SWIG command-line options for specifying directories to be searched for included files. The value of <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_SWIGINCFLAGS</envar> is created -by appending <envar xmlns="http://www.scons.org/dbxsd/v1.0">$SWIGINCPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$SWIGINCSUFFIX</envar> +by respectively prepending and appending +<envar xmlns="http://www.scons.org/dbxsd/v1.0">$SWIGINCPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$SWIGINCSUFFIX</envar> to the beginning and end of each directory in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$SWIGPATH</envar>. </para> @@ -6946,7 +7126,7 @@ of each directory in <envar xmlns="http://www.scons.org/dbxsd/v1.0">$SWIGPATH</e <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> The prefix used to specify an include directory on the SWIG command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$SWIGPATH</envar> construction variable when the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_SWIGINCFLAGS</envar> variable is automatically generated. </para> @@ -7020,7 +7200,7 @@ through the automatically-generated <envar xmlns="http://www.scons.org/dbxsd/v1.0">$_SWIGINCFLAGS</envar> construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the <envar xmlns="http://www.scons.org/dbxsd/v1.0">$SWIGINCPREFIX</envar> and <envar xmlns="http://www.scons.org/dbxsd/v1.0">$SWIGINCSUFFIX</envar> construction variables to the beginning and end @@ -7095,6 +7275,13 @@ that may not be set or used in a construction environment. <term>TARGET_ARCH</term> <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> + The name of the target hardware architecture for the compiled objects + created by this Environment. + This defaults to the value of HOST_ARCH, and the user can override it. + Currently only set for Win32. +</para> + +<para xmlns="http://www.scons.org/dbxsd/v1.0"> Sets the target architecture for Visual Studio compiler (i.e. the arch of the binaries generated by the compiler). If not set, default to <envar xmlns="http://www.scons.org/dbxsd/v1.0">$HOST_ARCH</envar>, or, if that is unset, to the architecture of the @@ -7104,29 +7291,28 @@ This variable must be passed as an argument to the Environment() constructor; setting it later has no effect. This is currently only used on Windows, but in the future it will be used on other OSes as well. +If this is set and MSVC_VERSION is not set, this will search for +all installed MSVC's that support the TARGET_ARCH, selecting the +latest version for use. </para> <para xmlns="http://www.scons.org/dbxsd/v1.0"> Valid values for Windows are <literal>x86</literal>, +<literal>arm</literal>, <literal>i386</literal> (for 32 bits); <literal>amd64</literal>, +<literal>arm64</literal>, <literal>emt64</literal>, <literal>x86_64</literal> (for 64 bits); and <literal>ia64</literal> (Itanium). + For example, if you want to compile 64-bit binaries, you would set <literal>TARGET_ARCH='x86_64'</literal> in your SCons environment. </para> - -<para xmlns="http://www.scons.org/dbxsd/v1.0"> - The name of the target hardware architecture for the compiled objects - created by this Environment. - This defaults to the value of HOST_ARCH, and the user can override it. - Currently only set for Win32. -</para> - </listitem> +</listitem> </varlistentry> <varlistentry id="cv-TARGET_OS"> <term>TARGET_OS</term> @@ -7162,14 +7348,30 @@ The suffix used for tar file names. <listitem> <para xmlns="http://www.scons.org/dbxsd/v1.0"> The prefix for a temporary file used -to execute lines longer than $MAXLINELENGTH. -The default is '@'. -This may be set for toolchains that use other values, -such as '-@' for the diab compiler +to store lines lines longer than $MAXLINELENGTH +as operations which call out to a shell will fail +if the line is too long, which particularly +impacts linking. +The default is '@', which works for the Microsoft +and GNU toolchains on Windows. +Set this appropriately for other toolchains, +for example '-@' for the diab compiler or '-via' for ARM toolchain. </para> </listitem> </varlistentry> + <varlistentry id="cv-TEMPFILESUFFIX"> + <term>TEMPFILESUFFIX</term> + <listitem> +<para xmlns="http://www.scons.org/dbxsd/v1.0"> +The suffix used for the temporary file name +used for long command lines. The name should +include the dot ('.') if one is wanted as +it will not be added automatically. +The default is '.lnk'. +</para> +</listitem> + </varlistentry> <varlistentry id="cv-TEX"> <term>TEX</term> <listitem> @@ -7542,6 +7744,7 @@ This is used to fill in the <literal>BuildRequires:</literal> field in the RPM <filename>.spec</filename> file. +Note this should only be used on a host managed by rpm as the dependencies will not be resolvable at build time otherwise. </para> </listitem> </varlistentry> @@ -7600,7 +7803,8 @@ field in the RPM <para xmlns="http://www.scons.org/dbxsd/v1.0"> This is used to fill in the <literal>Epoch:</literal> -field in the controlling information for RPM packages. +field in the RPM +<filename>.spec</filename> file. </para> </listitem> </varlistentry> @@ -7626,6 +7830,38 @@ field in the RPM </para> </listitem> </varlistentry> + <varlistentry id="cv-X_RPM_EXTRADEFS"> + <term>X_RPM_EXTRADEFS</term> + <listitem> +<para xmlns="http://www.scons.org/dbxsd/v1.0"> +A list used to supply extra defintions or flags +to be added to the RPM <filename>.spec</filename> file. +Each item is added as-is with a carriage return appended. +This is useful if some specific RPM feature not otherwise +anticipated by SCons needs to be turned on or off. +Note if this variable is omitted, SCons will by +default supply the value +<literal>'%global debug_package %{nil}'</literal> +to disable debug package generation. +To enable debug package generation, include this +variable set either to None, or to a custom +list that does not include the default line. +Added in version 3.1. +</para> + +<example_commands xmlns="http://www.scons.org/dbxsd/v1.0"> +env.Package( + NAME = 'foo', +... + X_RPM_EXTRADEFS = [ + '%define _unpackaged_files_terminate_build 0' + '%define _missing_doc_files_terminate_build 0' + ], +... ) +</example_commands> + +</listitem> + </varlistentry> <varlistentry id="cv-X_RPM_GROUP"> <term>X_RPM_GROUP</term> <listitem> diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod index 6ecf6c9..28c08dc 100644 --- a/doc/generated/variables.mod +++ b/doc/generated/variables.mod @@ -10,6 +10,12 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-__LDMODULEVERSIONFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$__LDMODULEVERSIONFLAGS</envar>"> <!ENTITY cv-__SHLIBVERSIONFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$__SHLIBVERSIONFLAGS</envar>"> +<!ENTITY cv-_APPLELINK_COMPATIBILITY_VERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$_APPLELINK_COMPATIBILITY_VERSION</envar>"> +<!ENTITY cv-APPLELINK_COMPATIBILITY_VERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$APPLELINK_COMPATIBILITY_VERSION</envar>"> +<!ENTITY cv-_APPLELINK_CURRENT_VERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$_APPLELINK_CURRENT_VERSION</envar>"> +<!ENTITY cv-APPLELINK_CURRENT_VERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$APPLELINK_CURRENT_VERSION</envar>"> +<!ENTITY cv-APPLELINK_NO_COMPATIBILITY_VERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$APPLELINK_NO_COMPATIBILITY_VERSION</envar>"> +<!ENTITY cv-APPLELINK_NO_CURRENT_VERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$APPLELINK_NO_CURRENT_VERSION</envar>"> <!ENTITY cv-AR "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$AR</envar>"> <!ENTITY cv-ARCHITECTURE "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$ARCHITECTURE</envar>"> <!ENTITY cv-ARCOM "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$ARCOM</envar>"> @@ -232,6 +238,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-JAVAHCOM "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$JAVAHCOM</envar>"> <!ENTITY cv-JAVAHCOMSTR "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$JAVAHCOMSTR</envar>"> <!ENTITY cv-JAVAHFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$JAVAHFLAGS</envar>"> +<!ENTITY cv-JAVAINCLUDES "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$JAVAINCLUDES</envar>"> <!ENTITY cv-JAVASOURCEPATH "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$JAVASOURCEPATH</envar>"> <!ENTITY cv-JAVASUFFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$JAVASUFFIX</envar>"> <!ENTITY cv-JAVAVERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$JAVAVERSION</envar>"> @@ -256,6 +263,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-LEXCOM "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$LEXCOM</envar>"> <!ENTITY cv-LEXCOMSTR "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$LEXCOMSTR</envar>"> <!ENTITY cv-LEXFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$LEXFLAGS</envar>"> +<!ENTITY cv-LEXUNISTD "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$LEXUNISTD</envar>"> <!ENTITY cv-_LIBDIRFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$_LIBDIRFLAGS</envar>"> <!ENTITY cv-LIBDIRPREFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$LIBDIRPREFIX</envar>"> <!ENTITY cv-LIBDIRSUFFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$LIBDIRSUFFIX</envar>"> @@ -496,8 +504,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-_SHLIBSONAME "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$_SHLIBSONAME</envar>"> <!ENTITY cv-SHLIBSUFFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLIBSUFFIX</envar>"> <!ENTITY cv-SHLIBVERSION "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLIBVERSION</envar>"> -<!ENTITY cv-SHLIBVERSIONFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLIBVERSIONFLAGS</envar>"> <!ENTITY cv-_SHLIBVERSIONFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$_SHLIBVERSIONFLAGS</envar>"> +<!ENTITY cv-SHLIBVERSIONFLAGS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLIBVERSIONFLAGS</envar>"> <!ENTITY cv-SHLINK "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLINK</envar>"> <!ENTITY cv-SHLINKCOM "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLINKCOM</envar>"> <!ENTITY cv-SHLINKCOMSTR "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$SHLINKCOMSTR</envar>"> @@ -537,6 +545,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-TARGETS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$TARGETS</envar>"> <!ENTITY cv-TARSUFFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$TARSUFFIX</envar>"> <!ENTITY cv-TEMPFILEPREFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$TEMPFILEPREFIX</envar>"> +<!ENTITY cv-TEMPFILESUFFIX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$TEMPFILESUFFIX</envar>"> <!ENTITY cv-TEX "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$TEX</envar>"> <!ENTITY cv-TEXCOM "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$TEXCOM</envar>"> <!ENTITY cv-TEXCOMSTR "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$TEXCOMSTR</envar>"> @@ -584,6 +593,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-X_RPM_EPOCH "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$X_RPM_EPOCH</envar>"> <!ENTITY cv-X_RPM_EXCLUDEARCH "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$X_RPM_EXCLUDEARCH</envar>"> <!ENTITY cv-X_RPM_EXLUSIVEARCH "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$X_RPM_EXLUSIVEARCH</envar>"> +<!ENTITY cv-X_RPM_EXTRADEFS "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$X_RPM_EXTRADEFS</envar>"> <!ENTITY cv-X_RPM_GROUP "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$X_RPM_GROUP</envar>"> <!ENTITY cv-X_RPM_GROUP_lang "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$X_RPM_GROUP_lang</envar>"> <!ENTITY cv-X_RPM_ICON "<envar xmlns='http://www.scons.org/dbxsd/v1.0'>$X_RPM_ICON</envar>"> @@ -639,6 +649,12 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-link-__LDMODULEVERSIONFLAGS "<link linkend='cv-__LDMODULEVERSIONFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$__LDMODULEVERSIONFLAGS</envar></link>"> <!ENTITY cv-link-__SHLIBVERSIONFLAGS "<link linkend='cv-__SHLIBVERSIONFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$__SHLIBVERSIONFLAGS</envar></link>"> +<!ENTITY cv-link-_APPLELINK_COMPATIBILITY_VERSION "<link linkend='cv-_APPLELINK_COMPATIBILITY_VERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$_APPLELINK_COMPATIBILITY_VERSION</envar></link>"> +<!ENTITY cv-link-APPLELINK_COMPATIBILITY_VERSION "<link linkend='cv-APPLELINK_COMPATIBILITY_VERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$APPLELINK_COMPATIBILITY_VERSION</envar></link>"> +<!ENTITY cv-link-_APPLELINK_CURRENT_VERSION "<link linkend='cv-_APPLELINK_CURRENT_VERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$_APPLELINK_CURRENT_VERSION</envar></link>"> +<!ENTITY cv-link-APPLELINK_CURRENT_VERSION "<link linkend='cv-APPLELINK_CURRENT_VERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$APPLELINK_CURRENT_VERSION</envar></link>"> +<!ENTITY cv-link-APPLELINK_NO_COMPATIBILITY_VERSION "<link linkend='cv-APPLELINK_NO_COMPATIBILITY_VERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$APPLELINK_NO_COMPATIBILITY_VERSION</envar></link>"> +<!ENTITY cv-link-APPLELINK_NO_CURRENT_VERSION "<link linkend='cv-APPLELINK_NO_CURRENT_VERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$APPLELINK_NO_CURRENT_VERSION</envar></link>"> <!ENTITY cv-link-AR "<link linkend='cv-AR' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$AR</envar></link>"> <!ENTITY cv-link-ARCHITECTURE "<link linkend='cv-ARCHITECTURE' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$ARCHITECTURE</envar></link>"> <!ENTITY cv-link-ARCOM "<link linkend='cv-ARCOM' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$ARCOM</envar></link>"> @@ -861,6 +877,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-link-JAVAHCOM "<link linkend='cv-JAVAHCOM' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$JAVAHCOM</envar></link>"> <!ENTITY cv-link-JAVAHCOMSTR "<link linkend='cv-JAVAHCOMSTR' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$JAVAHCOMSTR</envar></link>"> <!ENTITY cv-link-JAVAHFLAGS "<link linkend='cv-JAVAHFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$JAVAHFLAGS</envar></link>"> +<!ENTITY cv-link-JAVAINCLUDES "<link linkend='cv-JAVAINCLUDES' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$JAVAINCLUDES</envar></link>"> <!ENTITY cv-link-JAVASOURCEPATH "<link linkend='cv-JAVASOURCEPATH' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$JAVASOURCEPATH</envar></link>"> <!ENTITY cv-link-JAVASUFFIX "<link linkend='cv-JAVASUFFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$JAVASUFFIX</envar></link>"> <!ENTITY cv-link-JAVAVERSION "<link linkend='cv-JAVAVERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$JAVAVERSION</envar></link>"> @@ -885,6 +902,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-link-LEXCOM "<link linkend='cv-LEXCOM' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$LEXCOM</envar></link>"> <!ENTITY cv-link-LEXCOMSTR "<link linkend='cv-LEXCOMSTR' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$LEXCOMSTR</envar></link>"> <!ENTITY cv-link-LEXFLAGS "<link linkend='cv-LEXFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$LEXFLAGS</envar></link>"> +<!ENTITY cv-link-LEXUNISTD "<link linkend='cv-LEXUNISTD' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$LEXUNISTD</envar></link>"> <!ENTITY cv-link-_LIBDIRFLAGS "<link linkend='cv-_LIBDIRFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$_LIBDIRFLAGS</envar></link>"> <!ENTITY cv-link-LIBDIRPREFIX "<link linkend='cv-LIBDIRPREFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$LIBDIRPREFIX</envar></link>"> <!ENTITY cv-link-LIBDIRSUFFIX "<link linkend='cv-LIBDIRSUFFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$LIBDIRSUFFIX</envar></link>"> @@ -1125,8 +1143,8 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-link-_SHLIBSONAME "<link linkend='cv-_SHLIBSONAME' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$_SHLIBSONAME</envar></link>"> <!ENTITY cv-link-SHLIBSUFFIX "<link linkend='cv-SHLIBSUFFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLIBSUFFIX</envar></link>"> <!ENTITY cv-link-SHLIBVERSION "<link linkend='cv-SHLIBVERSION' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLIBVERSION</envar></link>"> -<!ENTITY cv-link-SHLIBVERSIONFLAGS "<link linkend='cv-SHLIBVERSIONFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLIBVERSIONFLAGS</envar></link>"> <!ENTITY cv-link-_SHLIBVERSIONFLAGS "<link linkend='cv-_SHLIBVERSIONFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$_SHLIBVERSIONFLAGS</envar></link>"> +<!ENTITY cv-link-SHLIBVERSIONFLAGS "<link linkend='cv-SHLIBVERSIONFLAGS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLIBVERSIONFLAGS</envar></link>"> <!ENTITY cv-link-SHLINK "<link linkend='cv-SHLINK' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLINK</envar></link>"> <!ENTITY cv-link-SHLINKCOM "<link linkend='cv-SHLINKCOM' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLINKCOM</envar></link>"> <!ENTITY cv-link-SHLINKCOMSTR "<link linkend='cv-SHLINKCOMSTR' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$SHLINKCOMSTR</envar></link>"> @@ -1166,6 +1184,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-link-TARGETS "<link linkend='cv-TARGETS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$TARGETS</envar></link>"> <!ENTITY cv-link-TARSUFFIX "<link linkend='cv-TARSUFFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$TARSUFFIX</envar></link>"> <!ENTITY cv-link-TEMPFILEPREFIX "<link linkend='cv-TEMPFILEPREFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$TEMPFILEPREFIX</envar></link>"> +<!ENTITY cv-link-TEMPFILESUFFIX "<link linkend='cv-TEMPFILESUFFIX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$TEMPFILESUFFIX</envar></link>"> <!ENTITY cv-link-TEX "<link linkend='cv-TEX' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$TEX</envar></link>"> <!ENTITY cv-link-TEXCOM "<link linkend='cv-TEXCOM' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$TEXCOM</envar></link>"> <!ENTITY cv-link-TEXCOMSTR "<link linkend='cv-TEXCOMSTR' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$TEXCOMSTR</envar></link>"> @@ -1213,6 +1232,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. <!ENTITY cv-link-X_RPM_EPOCH "<link linkend='cv-X_RPM_EPOCH' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$X_RPM_EPOCH</envar></link>"> <!ENTITY cv-link-X_RPM_EXCLUDEARCH "<link linkend='cv-X_RPM_EXCLUDEARCH' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$X_RPM_EXCLUDEARCH</envar></link>"> <!ENTITY cv-link-X_RPM_EXLUSIVEARCH "<link linkend='cv-X_RPM_EXLUSIVEARCH' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$X_RPM_EXLUSIVEARCH</envar></link>"> +<!ENTITY cv-link-X_RPM_EXTRADEFS "<link linkend='cv-X_RPM_EXTRADEFS' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$X_RPM_EXTRADEFS</envar></link>"> <!ENTITY cv-link-X_RPM_GROUP "<link linkend='cv-X_RPM_GROUP' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$X_RPM_GROUP</envar></link>"> <!ENTITY cv-link-X_RPM_GROUP_lang "<link linkend='cv-X_RPM_GROUP_lang' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$X_RPM_GROUP_lang</envar></link>"> <!ENTITY cv-link-X_RPM_ICON "<link linkend='cv-X_RPM_ICON' xmlns='http://www.scons.org/dbxsd/v1.0'><envar>$X_RPM_ICON</envar></link>"> diff --git a/doc/man/SConstruct b/doc/man/SConstruct index dedf83e..f17ffd4 100644 --- a/doc/man/SConstruct +++ b/doc/man/SConstruct @@ -3,7 +3,7 @@ # # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/doc/man/epub.xsl b/doc/man/epub.xsl index d8d7f13..450f7de 100644 --- a/doc/man/epub.xsl +++ b/doc/man/epub.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/man/html.xsl b/doc/man/html.xsl index ac92faf..9594da8 100644 --- a/doc/man/html.xsl +++ b/doc/man/html.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/man/pdf.xsl b/doc/man/pdf.xsl index b066e34..a3def70 100644 --- a/doc/man/pdf.xsl +++ b/doc/man/pdf.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/man/scons-time.xml b/doc/man/scons-time.xml index 9dd4e73..80dc041 100644 --- a/doc/man/scons-time.xml +++ b/doc/man/scons-time.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -32,8 +32,8 @@ <refmeta> <refentrytitle>SCONS-TIME</refentrytitle> <manvolnum>1</manvolnum> -<refmiscinfo class='source'>SCons 3.0.0</refmiscinfo> -<refmiscinfo class='manual'>SCons 3.0.0</refmiscinfo> +<refmiscinfo class='source'>SCons 3.0.5</refmiscinfo> +<refmiscinfo class='manual'>SCons 3.0.5</refmiscinfo> </refmeta> <refnamediv id='name'> <refname>scons-time</refname> diff --git a/doc/man/scons.xml b/doc/man/scons.xml index aabd957..2f5eb32 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -54,10 +54,10 @@ <corpauthor>Steven Knight and the SCons Development Team</corpauthor> - <pubdate>2004 - 2016</pubdate> + <pubdate>2004 - 2019</pubdate> <copyright> - <year>2004 - 2016</year> + <year>2004 - 2019</year> <holder>The SCons Foundation</holder> </copyright> @@ -75,8 +75,8 @@ <refmeta> <refentrytitle>SCONS</refentrytitle> <manvolnum>1</manvolnum> -<refmiscinfo class='source'>SCons 3.0.0</refmiscinfo> -<refmiscinfo class='manual'>SCons 3.0.0</refmiscinfo> +<refmiscinfo class='source'>SCons 3.0.5</refmiscinfo> +<refmiscinfo class='manual'>SCons 3.0.5</refmiscinfo> </refmeta> <refnamediv id='name'> <refname>scons</refname> @@ -105,8 +105,11 @@ rebuild them.</para> 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</emphasis> +<emphasis>sconstruct.py</emphasis> (in that order) in the current directory and reads its configuration from the first file found. An alternate file name may be @@ -271,7 +274,7 @@ scons <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 the SConscript file(s) +may be defined in the SConscript file(s) using the <emphasis role="bold">Default()</emphasis> function, described below.</para> @@ -426,7 +429,7 @@ try to access a list member that does not exist.</para> <para><command>scons</command> -requires Python version 2.7 or later. +requires either Python 2.7 or Python 3.5 or higher. There should be no other dependencies or requirements to run <emphasis role="bold">scons.</emphasis></para> @@ -635,8 +638,11 @@ yet have any results in the cache.</para> before searching for the <emphasis>SConstruct</emphasis>, <emphasis>Sconstruct</emphasis>, +<emphasis>sconstruct</emphasis>, +<emphasis>SConstruct.py</emphasis> +<emphasis>Sconstruct.py</emphasis> or -<emphasis>sconstruct</emphasis> +<emphasis>sconstruct.py</emphasis> file, or doing anything else. Multiple <option>-C</option> @@ -649,8 +655,11 @@ equivalent to except that it will search for <emphasis>SConstruct</emphasis>, <emphasis>Sconstruct</emphasis>, +<emphasis>sconstruct</emphasis>, +<emphasis>SConstruct.py</emphasis> +<emphasis>Sconstruct.py</emphasis> or -<emphasis>sconstruct</emphasis> +<emphasis>sconstruct.py</emphasis> in the specified directory.)</para> <!-- .TP --> @@ -853,14 +862,31 @@ and ultimately removed.</para> <varlistentry> <term>--debug=time</term> <listitem> -<para>Prints various time profiling information: -the time spent executing each individual build command; -the total build time (time SCons ran from beginning to end); -the total time spent reading and executing SConscript files; -the total time spent SCons itself spend running -(that is, not counting reading and executing SConscript files); -and both the total time spent executing all build commands -and the elapsed wall-clock time spent executing those build commands. +<para>Prints various time profiling information:</para> + <itemizedlist> + <listitem> +<para>The time spent executing each individual build command</para> + </listitem> + <listitem> +<para>The total build time (time SCons ran from beginning to end)</para> + </listitem> + <listitem> +<para>The total time spent reading and executing SConscript files</para> + </listitem> + <listitem> +<para>The total time spent SCons itself spend running +(that is, not counting reading and executing SConscript files)</para> + </listitem> + <listitem> +<para>The total time spent executing all build commands</para></listitem> +<listitem> +<para>The elapsed wall-clock time spent executing those build commands</para> + </listitem> + <listitem> +<para>The time spent processing each file passed to the <emphasis>SConscript()</emphasis> function</para> + </listitem> + </itemizedlist> +<para> (When <command>scons</command> is executed without the @@ -884,7 +910,8 @@ be significantly smaller than the total time spent executing all the build commands, since multiple build commands and intervening SCons processing -should take place in parallel.)</para> +should take place in parallel.) +</para> </listitem> </varlistentry> @@ -970,6 +997,12 @@ the mechanisms in the specified order.</para> </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> <listitem> <para>Use @@ -1024,6 +1057,12 @@ are used, the directories are searched in the order specified.</para> </listitem> </varlistentry> + <varlistentry> + <term>--ignore-virtualenv</term> + <listitem> +<para>Suppress importing virtualenv-related variables to SCons.</para> + </listitem> + </varlistentry> <varlistentry> <term>--implicit-cache</term> <listitem> @@ -1640,9 +1679,12 @@ scons --tree=all,prune,status target <listitem> <para>Walks up the directory structure until an <emphasis>SConstruct ,</emphasis> -<emphasis>Sconstruct</emphasis> +<emphasis>Sconstruct ,</emphasis> +<emphasis>sconstruct ,</emphasis> +<emphasis>SConstruct.py</emphasis> +<emphasis>Sconstruct.py</emphasis> or -<emphasis>sconstruct</emphasis> +<emphasis>sconstruct.py</emphasis> file is found, and uses that as the top of the directory tree. If no targets are specified on the command line, @@ -1866,26 +1908,6 @@ These warnings are enabled by default.</para> </listitem> </varlistentry> <varlistentry> - <term>--warn=no-md5-module, --warn=no-no-md5-module</term> - <listitem> -<para>Enables or disables warnings about the version of Python -not having an MD5 checksum module available. -These warnings are enabled by default.</para> - - </listitem> - </varlistentry> - <varlistentry> - <term>--warn=no-metaclass-support, --warn=no-no-metaclass-support</term> - <listitem> -<para>Enables or disables warnings about the version of Python -not supporting metaclasses when the -<option>--debug=memoizer</option> -option is used. -These warnings are enabled by default.</para> - - </listitem> - </varlistentry> - <varlistentry> <term>--warn=no-object-count, --warn=no-no-object-count</term> <listitem> <para>Enables or disables warnings about the @@ -2299,12 +2321,12 @@ that are not absolute path names <emphasis role="bold">/</emphasis> on POSIX systems or -<emphasis role="bold">\fR +<emphasis role="bold">\</emphasis> on Windows systems, with or without an optional drive letter) are interpreted relative to the directory containing the -SConscript</emphasis> +<emphasis role="bold">SConscript</emphasis> file being read. An initial <emphasis role="bold">#</emphasis> @@ -2992,7 +3014,7 @@ function to get at the path name for each Node.</para> <literallayout class="monospaced"> print(str(DEFAULT_TARGETS[0])) -if 'foo' in map(str, DEFAULT_TARGETS): +if 'foo' in [str(t) for t in DEFAULT_TARGETS]: print("Don't forget to test the `foo' program!") </literallayout> </listitem> @@ -3006,13 +3028,13 @@ list change on on each successive call to the function:</para> <literallayout class="monospaced"> -print(map(str, DEFAULT_TARGETS)) # originally [] +print([str(t) for t in DEFAULT_TARGETS]) # originally [] Default('foo') -print(map(str, DEFAULT_TARGETS)) # now a node ['foo'] +print([str(t) for t in DEFAULT_TARGETS]) # now a node ['foo'] Default('bar') -print(map(str, DEFAULT_TARGETS)) # now a node ['foo', 'bar'] +print([str(t) for t in DEFAULT_TARGETS]) # now a node ['foo', 'bar'] Default(None) -print(map(str, DEFAULT_TARGETS)) # back to [] +print([str(t) for t in DEFAULT_TARGETS]) # back to [] </literallayout> <para>Consequently, be sure to use @@ -4056,7 +4078,9 @@ and return -1, 0 or 1 (like the standard Python <emphasis>cmp</emphasis> -function).</para> +function). + +Optionally a Boolean value of True for <emphasis>sort</emphasis> will cause a standard alphabetical sort to be performed</para> <literallayout class="monospaced"> Help(vars.GenerateHelpText(env)) @@ -5255,11 +5279,11 @@ arguments may be lists of Node objects if there is more than one target file or source file. The actual target and source file name(s) may be retrieved from their Node objects -via the built-in Python str() function:</para> +via the built-in Python <function>str</function> function:</para> <literallayout class="monospaced"> target_file_name = str(target) -source_file_names = map(lambda x: str(x), source) +source_file_names = [str(x) for x in source] </literallayout> <para>The function should return diff --git a/doc/man/scons_title.xsl b/doc/man/scons_title.xsl index cc5ae5e..0c50c96 100644 --- a/doc/man/scons_title.xsl +++ b/doc/man/scons_title.xsl @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/man/sconsign.xml b/doc/man/sconsign.xml index baa15e1..2f0d66c 100644 --- a/doc/man/sconsign.xml +++ b/doc/man/sconsign.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -25,15 +25,15 @@ --> <!-- lifted from troff+man by doclifter --> -<refentry id='sconsign1' +<refentry id='sconsign1' 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"> <refmeta> <refentrytitle>SCONSIGN</refentrytitle> <manvolnum>1</manvolnum> -<refmiscinfo class='source'>SCons 3.0.0</refmiscinfo> -<refmiscinfo class='manual'>SCons 3.0.0</refmiscinfo> +<refmiscinfo class='source'>SCons 3.0.5</refmiscinfo> +<refmiscinfo class='manual'>SCons 3.0.5</refmiscinfo> </refmeta> <refnamediv id='name'> <refname>sconsign</refname> @@ -42,7 +42,7 @@ <!-- body begins here --> <refsynopsisdiv id='synopsis'> <cmdsynopsis> - <command>sconsign</command> + <command>sconsign</command> <arg choice='opt' rep='repeat'><replaceable>options</replaceable></arg> <arg choice='plain'><replaceable>file</replaceable></arg> <arg choice='opt'><replaceable>...</replaceable></arg> @@ -51,7 +51,7 @@ <refsect1 id='description'><title>DESCRIPTION</title> -<para>The +<para>The <command>sconsign</command> command displays the contents of one or more @@ -94,17 +94,21 @@ was specified by the function). Any <emphasis>file</emphasis> -argument that does not end in -<markup>.dbm</markup> +argument that ends in +<markup>.dblite</markup> is assumed to be a traditional <markup>.sconsign</markup> file containing the signature entries for a single directory. -An explicit format +If neither of those is true, +<command>sconsign</command> +attempts to guess the format. +If that does not work, +an explicit format may be specified using the <option>-f</option> or -<option>--file=</option> +<option>--format=</option> options.</para> </refsect1> diff --git a/doc/python10/SConstruct b/doc/python10/SConstruct index 3603298..5b6eb6f 100644 --- a/doc/python10/SConstruct +++ b/doc/python10/SConstruct @@ -3,7 +3,7 @@ # # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/doc/python10/abstract.xml b/doc/python10/abstract.xml index c1715e8..55cb734 100644 --- a/doc/python10/abstract.xml +++ b/doc/python10/abstract.xml @@ -10,7 +10,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/python10/acks.xml b/doc/python10/acks.xml index d2e7796..9f7fae5 100644 --- a/doc/python10/acks.xml +++ b/doc/python10/acks.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/python10/copyright.xml b/doc/python10/copyright.xml index bedd89f..0a99e22 100644 --- a/doc/python10/copyright.xml +++ b/doc/python10/copyright.xml @@ -10,7 +10,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/python10/design.xml b/doc/python10/design.xml index 7c48cf0..4930ad4 100644 --- a/doc/python10/design.xml +++ b/doc/python10/design.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/python10/future.xml b/doc/python10/future.xml index 35926e1..d3da486 100644 --- a/doc/python10/future.xml +++ b/doc/python10/future.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/python10/install.xml b/doc/python10/install.xml index d1db496..ad3c166 100644 --- a/doc/python10/install.xml +++ b/doc/python10/install.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/python10/intro.xml b/doc/python10/intro.xml index 016ce78..7d5a099 100644 --- a/doc/python10/intro.xml +++ b/doc/python10/intro.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/python10/main.xml b/doc/python10/main.xml index e03d815..aae092d 100644 --- a/doc/python10/main.xml +++ b/doc/python10/main.xml @@ -13,7 +13,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/python10/process.xml b/doc/python10/process.xml index 78c88d9..84fe87e 100644 --- a/doc/python10/process.xml +++ b/doc/python10/process.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/python10/summary.xml b/doc/python10/summary.xml index 8437591..70186a7 100644 --- a/doc/python10/summary.xml +++ b/doc/python10/summary.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/Alias.xml b/doc/reference/Alias.xml index 9656c95..b0681fb 100644 --- a/doc/reference/Alias.xml +++ b/doc/reference/Alias.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/CFile.xml b/doc/reference/CFile.xml index 533ac16..0f50e77 100644 --- a/doc/reference/CFile.xml +++ b/doc/reference/CFile.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/CXXFile.xml b/doc/reference/CXXFile.xml index b428494..33a1d2b 100644 --- a/doc/reference/CXXFile.xml +++ b/doc/reference/CXXFile.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/Command.xml b/doc/reference/Command.xml index 513ab5d..c8a056e 100644 --- a/doc/reference/Command.xml +++ b/doc/reference/Command.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/Install.xml b/doc/reference/Install.xml index 63d3bd0..195afc1 100644 --- a/doc/reference/Install.xml +++ b/doc/reference/Install.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/InstallAs.xml b/doc/reference/InstallAs.xml index 30e4e76..418bdd9 100644 --- a/doc/reference/InstallAs.xml +++ b/doc/reference/InstallAs.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/Library.xml b/doc/reference/Library.xml index dd55a9f..54f4055 100644 --- a/doc/reference/Library.xml +++ b/doc/reference/Library.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/Object.xml b/doc/reference/Object.xml index ff5a8c2..981e70e 100644 --- a/doc/reference/Object.xml +++ b/doc/reference/Object.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/PCH.xml b/doc/reference/PCH.xml index 42e27dc..604d171 100644 --- a/doc/reference/PCH.xml +++ b/doc/reference/PCH.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/PDF.xml b/doc/reference/PDF.xml index 0d63f0a..25239ef 100644 --- a/doc/reference/PDF.xml +++ b/doc/reference/PDF.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/PostScript.xml b/doc/reference/PostScript.xml index a1d351c..559cecb 100644 --- a/doc/reference/PostScript.xml +++ b/doc/reference/PostScript.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/Program.xml b/doc/reference/Program.xml index 2160317..d4d38de 100644 --- a/doc/reference/Program.xml +++ b/doc/reference/Program.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/RES.xml b/doc/reference/RES.xml index a720bfe..86fb188 100644 --- a/doc/reference/RES.xml +++ b/doc/reference/RES.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/SConstruct b/doc/reference/SConstruct index 1134516..95bdf31 100644 --- a/doc/reference/SConstruct +++ b/doc/reference/SConstruct @@ -3,7 +3,7 @@ # # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/doc/reference/SharedLibrary.xml b/doc/reference/SharedLibrary.xml index 57bd55f..663e8aa 100644 --- a/doc/reference/SharedLibrary.xml +++ b/doc/reference/SharedLibrary.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/SharedObject.xml b/doc/reference/SharedObject.xml index c109fea..6943de2 100644 --- a/doc/reference/SharedObject.xml +++ b/doc/reference/SharedObject.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/StaticLibrary.xml b/doc/reference/StaticLibrary.xml index b188664..ba49ee7 100644 --- a/doc/reference/StaticLibrary.xml +++ b/doc/reference/StaticLibrary.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/StaticObject.xml b/doc/reference/StaticObject.xml index 0486960..af994a0 100644 --- a/doc/reference/StaticObject.xml +++ b/doc/reference/StaticObject.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/chtml.xsl b/doc/reference/chtml.xsl index 707f4d2..b0a7c9e 100644 --- a/doc/reference/chtml.xsl +++ b/doc/reference/chtml.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/reference/copyright.xml b/doc/reference/copyright.xml index e27a1ff..c2687c9 100644 --- a/doc/reference/copyright.xml +++ b/doc/reference/copyright.xml @@ -10,7 +10,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/errors.xml b/doc/reference/errors.xml index 97dbd2b..c941075 100644 --- a/doc/reference/errors.xml +++ b/doc/reference/errors.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/html.xsl b/doc/reference/html.xsl index 3f0760b..b4f10f5 100644 --- a/doc/reference/html.xsl +++ b/doc/reference/html.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/reference/main.xml b/doc/reference/main.xml index 788c967..6b58f58 100644 --- a/doc/reference/main.xml +++ b/doc/reference/main.xml @@ -16,7 +16,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/pdf.xsl b/doc/reference/pdf.xsl index a6d0054..230554a 100644 --- a/doc/reference/pdf.xsl +++ b/doc/reference/pdf.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/reference/preface.xml b/doc/reference/preface.xml index 05d5ca4..5ed81db 100644 --- a/doc/reference/preface.xml +++ b/doc/reference/preface.xml @@ -12,7 +12,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/reference/scons_title.xsl b/doc/reference/scons_title.xsl index 130c6a5..21c56da 100644 --- a/doc/reference/scons_title.xsl +++ b/doc/reference/scons_title.xsl @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/scons.mod b/doc/scons.mod index eb45a30..ea9ad4e 100644 --- a/doc/scons.mod +++ b/doc/scons.mod @@ -1,6 +1,6 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation An SCons-specific DTD module, for use with SCons DocBook documentation, that contains names, phrases, acronyms, etc. used @@ -137,6 +137,9 @@ <!ENTITY SConstruct "<filename xmlns='http://www.scons.org/dbxsd/v1.0'>SConstruct</filename>"> <!ENTITY Sconstruct "<filename xmlns='http://www.scons.org/dbxsd/v1.0'>Sconstruct</filename>"> <!ENTITY sconstruct "<filename xmlns='http://www.scons.org/dbxsd/v1.0'>sconstruct</filename>"> +<!ENTITY SConstruct.py "<filename xmlns='http://www.scons.org/dbxsd/v1.0'>SConstruct.py</filename>"> +<!ENTITY Sconstruct.py "<filename xmlns='http://www.scons.org/dbxsd/v1.0'>Sconstruct.py</filename>"> +<!ENTITY sconstruct.py "<filename xmlns='http://www.scons.org/dbxsd/v1.0'>sconstruct.py</filename>"> <!ENTITY sconsign "<filename xmlns='http://www.scons.org/dbxsd/v1.0'>.sconsign</filename>"> <!ENTITY src "<filename xmlns='http://www.scons.org/dbxsd/v1.0'>src</filename>"> diff --git a/doc/user/README b/doc/user/README index 1718f0e..5433ea2 100644 --- a/doc/user/README +++ b/doc/user/README @@ -1,4 +1,4 @@ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation When adding a new file, add it to main.xml and MANIFEST. diff --git a/doc/user/SConstruct b/doc/user/SConstruct index 96d6677..67a3fd5 100644 --- a/doc/user/SConstruct +++ b/doc/user/SConstruct @@ -3,7 +3,7 @@ # # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/doc/user/actions.xml b/doc/user/actions.xml index 3e60a9f..24ac8cf 100644 --- a/doc/user/actions.xml +++ b/doc/user/actions.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/add-method.xml b/doc/user/add-method.xml index 0d30a48..0b1187c 100644 --- a/doc/user/add-method.xml +++ b/doc/user/add-method.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/alias.xml b/doc/user/alias.xml index fee9dd1..17a1b8f 100644 --- a/doc/user/alias.xml +++ b/doc/user/alias.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/ant.xml b/doc/user/ant.xml index bd35671..ed1aac6 100644 --- a/doc/user/ant.xml +++ b/doc/user/ant.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/build-install.xml b/doc/user/build-install.xml index 845b9e6..07d5397 100644 --- a/doc/user/build-install.xml +++ b/doc/user/build-install.xml @@ -26,7 +26,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -90,9 +90,8 @@ <title>Installing Python</title> <para> - Because &SCons; is written in Python, - you must obviously have Python installed on your system + you need to have Python installed on your system to use &SCons;. Before you try to install Python, you should check to see if Python is already @@ -102,27 +101,25 @@ or <userinput>python --version</userinput> at your system's command-line prompt. - + For Linux/Unix/MacOS/BSD type systems this looks like: </para> <screen> $ <userinput>python -V</userinput> -Python 2.5.1 +Python 3.7.1 </screen> <para> - - And on a Windows system with Python installed: - + In a cmd shell or PowerShell on a Windows system + (note PoweShell needs it spelled "python.exe" rather than "python"): </para> <screen> C:\><userinput>python -V</userinput> -Python 2.5.1 +Python 3.7.1 </screen> <para> - If Python is not installed on your system, you will see an error message stating something like "command not found" @@ -132,254 +129,70 @@ Python 2.5.1 (on Windows). In that case, you need to install Python before you can install &SCons;. - </para> <para> - The standard 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 for information about - how to download and install Python on your system. - + See that page and associated links to get started. </para> <para> + For Linux systems, Python is + almost certainly available as a supported package, possibly + installed by default; this is often preferred to 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 + useful option if you need a version that is not offered by + the distribution you are using. + </para> - &SCons; will work with any 2.x version of Python from 2.7 on; - 3.0 and later are not yet supported. + <para> + &SCons; will work with Python 2.7.x or with Python 3.5 or later. If you need to install Python and have a choice, - we recommend using the most recent 2.x Python version available. + we recommend using the most recent Python version available. Newer Pythons have significant improvements that help speed up the performance of &SCons;. - </para> </section> <section> - <title>Installing &SCons; From Pre-Built Packages</title> + <title>Installing &SCons;</title> <para> - - &SCons; comes pre-packaged for installation on a number of systems, - including Linux and Windows systems. - You do not need to read this entire section, - you should need to read only the section - appropriate to the type of system you're running on. - + The canonical way to install &SCons; is from the Python Package + Index (PyPi): </para> - <section> - <title>Installing &SCons; on Red Hat (and Other RPM-based) Linux Systems</title> - - <para> - - &SCons; comes in RPM (Red Hat Package Manager) format, - pre-built and ready to install on Red Hat Linux, - Fedora, - or any other Linux distribution that uses RPM. - Your distribution may - already have an &SCons; RPM built specifically for it; - many do, including SUSE, Mandrake and Fedora. - You can check for the availability of an &SCons; RPM - on your distribution's download servers, - or by consulting an RPM search site like - <ulink url="http://www.rpmfind.net/">http://www.rpmfind.net/</ulink> or - <ulink url="http://rpm.pbone.net/">http://rpm.pbone.net/</ulink>. - - </para> - - <para> - - If your distribution supports installation via - <application>yum</application>, - you should be able to install &SCons; by running: - - </para> - - <screen> -# <userinput>yum install scons</userinput> - </screen> - - <para> - - If your Linux distribution does not already have - a specific &SCons; RPM file, - you can download and install from the - generic RPM provided by the &SCons; project. - This will install the - SCons script(s) in <filename>/usr/bin</filename>, - and the SCons library modules in - <filename>/usr/lib/scons</filename>. - - </para> - - <para> - - To install from the command line, simply download the - appropriate <filename>.rpm</filename> file, - and then run: - - </para> - - <screen> -# <userinput>rpm -Uvh scons-&buildversion;-1.noarch.rpm</userinput> - </screen> - - <para> - - Or, you can use a graphical RPM package manager. - See your package manager application's documentation - for specific instructions about - how to use it to install a downloaded RPM. - - </para> - - </section> - - <section> - <title>Installing &SCons; on Debian Linux Systems</title> - - <para> - - Debian Linux systems use a different package management - format that also makes it very easy to install &SCons;. - - </para> - - <para> - - If your system is connected to the Internet, - you can install the latest official Debian package - by running: - - </para> - - <screen> -# <userinput>apt-get install scons</userinput> - </screen> - - <!-- - - <para> - - Alternatively, - you can download the Debian package built - by the &SCons; project - and install it manually by running: - - </para> - - <screen> -# <userinput>db-XXX scons-*.deb</userinput> - </screen> - - --> - - </section> - - <section> - <title>Installing &SCons; on Windows Systems</title> - - <para> - - &SCons; provides a Windows installer - that makes installation extremely easy. - Download the <filename>scons-&buildversion;.win32.exe</filename> - file from the &SCons; download page at - <ulink url="http://scons.org/pages/download.html">http://scons.org/pages/download.html</ulink>. - Then all you need to do is execute the file - (usually by clicking on its icon in Windows Explorer). - These will take you through a small - sequence of windows that will install - &SCons; on your system. - - <!-- - Things are a little more complicated - if you are using the Cygwin version of Python. - This is because Cygwin - tries to make a Windows system look more - POSIX-like (or UNIX-like or Linux-like, if you prefer) - by having the Cygwin utilities, - including Cygwin Python, - interpret file name arguments on the command line - using the forward-slash (<filename>/</filename>) - as the directory separator, - instead of the normal Windows behavior of the - backslash (<filename>\</filename>) as the directory separator. - --> - - </para> - - <!-- - - <section> - <title>Installing &SCons; on Windows Systems Without Cygwin Python</title> - - <para> - - XXX - - </para> - - </section> - - <section> - <title>Installing &SCons; on Windows Systems With Cygwin Python</title> - - <para> - - XXX - - </para> - - </section> - - --> - - <!-- - - XXX - don't have the kinks worked out on how to - get these to display properly in all formats, - so comment them out for now. - - <screenshot> - <mediaobject> - <imageobject> - <imagedata fileref="SCons-win32-install-1.jpg" format="jpg" align="center"> - </imageobject> - </mediaobject> - </screenshot> - - <screenshot> - <mediaobject> - <imageobject> - <imagedata fileref="SCons-win32-install-2.jpg" format="jpg" align="center"> - </imageobject> - </mediaobject> - </screenshot> - - <screenshot> - <mediaobject> - <imageobject> - <imagedata fileref="SCons-win32-install-3.jpg" format="jpg" align="center"> - </imageobject> - </mediaobject> - </screenshot> + <screen> +% <userinput>python -m pip install scons</userinput> + </screen> - <screenshot> - <mediaobject> - <imageobject> - <imagedata fileref="SCons-win32-install-4.jpg" format="jpg" align="center"> - </imageobject> - </mediaobject> - </screenshot> + <para> + If you prefer not to install to the Python system location, + or do not have privileges to do so, you can add a flag to + install to a location specific to your own account: + </para> - --> + <screen> +% <userinput>python -m pip install --user scons</userinput> + </screen> - </section> + <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 + 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. + </para> </section> @@ -387,25 +200,21 @@ Python 2.5.1 <title>Building and Installing &SCons; on Any System</title> <para> - If a pre-built &SCons; package is not available for your system, + and installing using <filename>pip</filename> is not suitable, then you can still easily build and install &SCons; using the native Python <filename>distutils</filename> package. - </para> <para> - The first step is to download either the <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>. - </para> <para> - Unpack the archive you downloaded, using a utility like <application>tar</application> on Linux or UNIX, @@ -415,7 +224,6 @@ Python 2.5.1 usually in your local directory. Then change your working directory to that directory and install &SCons; by executing the following commands: - </para> <screen> @@ -429,11 +237,11 @@ Python 2.5.1 install the &scons; script in the python which is used to run the setup.py's scripts directory (<filename>/usr/local/bin</filename> or - <filename>C:\Python25\Scripts</filename>), + <filename>C:\Python27\Scripts</filename>), and will install the &SCons; build engine in the corresponding library directory for the python used (<filename>/usr/local/lib/scons</filename> or - <filename>C:\Python25\scons</filename>). + <filename>C:\Python27\scons</filename>). Because these are system directories, you may need root (on Linux or UNIX) or Administrator (on Windows) privileges to install &SCons; like this. @@ -489,7 +297,7 @@ Python 2.5.1 in the <filename>/usr/lib/scons-&buildversion;</filename> or - <filename>C:\Python25\scons-&buildversion;</filename> + <filename>C:\Python27\scons-&buildversion;</filename> directory, for example. </para> diff --git a/doc/user/builders-built-in.xml b/doc/user/builders-built-in.xml index d64b63d..f059bca 100644 --- a/doc/user/builders-built-in.xml +++ b/doc/user/builders-built-in.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/builders-commands.xml b/doc/user/builders-commands.xml index 8fa26f6..ccffaf0 100644 --- a/doc/user/builders-commands.xml +++ b/doc/user/builders-commands.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml index d26c4c6..c36d468 100644 --- a/doc/user/builders-writing.xml +++ b/doc/user/builders-writing.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -812,7 +812,7 @@ env.Foo('file') <scons_example name="builderswriting_MY_EMITTER"> <file name="SConstruct" printme="1"> -bld = Builder(action = 'my_command $SOURCES > $TARGET', +bld = Builder(action = './my_command $SOURCES > $TARGET', suffix = '.foo', src_suffix = '.input', emitter = '$MY_EMITTER') @@ -826,9 +826,6 @@ env2 = Environment(BUILDERS = {'Foo' : bld}, MY_EMITTER = modify2) env1.Foo('file1') env2.Foo('file2') -import os -env1['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() -env2['ENV']['PATH'] = env2['ENV']['PATH'] + os.pathsep + os.getcwd() </file> <file name="file1.input"> file1.input @@ -848,23 +845,6 @@ cat </scons_example> - <sconstruct> -bld = Builder(action = 'my_command $SOURCES > $TARGET', - suffix = '.foo', - src_suffix = '.input', - emitter = '$MY_EMITTER') -def modify1(target, source, env): - return target, source + ['modify1.in'] -def modify2(target, source, env): - return target, source + ['modify2.in'] -env1 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify1) -env2 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify2) -env1.Foo('file1') -env2.Foo('file2') - </sconstruct> - <para> In this example, the <filename>modify1.in</filename> diff --git a/doc/user/builders.xml b/doc/user/builders.xml index c1af202..873d677 100644 --- a/doc/user/builders.xml +++ b/doc/user/builders.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/caching.xml b/doc/user/caching.xml index db2a469..bf070f9 100644 --- a/doc/user/caching.xml +++ b/doc/user/caching.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/chtml.xsl b/doc/user/chtml.xsl index dafc044..a7b968c 100644 --- a/doc/user/chtml.xsl +++ b/doc/user/chtml.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/user/command-line.xml b/doc/user/command-line.xml index 21c17c1..bb1d32b 100644 --- a/doc/user/command-line.xml +++ b/doc/user/command-line.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -317,7 +317,7 @@ if not GetOption('help'): import os num_cpu = int(os.environ.get('NUM_CPU', 2)) SetOption('num_jobs', num_cpu) -print("running with -j", GetOption('num_jobs')) +print("running with -j %s"%GetOption('num_jobs')) </file> <file name="foo.in"> foo.in @@ -1863,7 +1863,7 @@ env = Environment(variables = vars, CPPDEFINES={'RELEASE_BUILD' : '${RELEASE}'}) unknown = vars.UnknownVariables() if unknown: - print("Unknown variables:", unknown.keys()) + print("Unknown variables: %s"%unknown.keys()) Exit(1) env.Program('foo.c') </file> @@ -1987,17 +1987,16 @@ foo.c <para> - One of the most basic things you can control - is which targets &SCons; will build by default--that is, + You can control + which targets &SCons; will build by default - that is, when there are no targets specified on the command line. As mentioned previously, &SCons; will normally build every target - in or below the current directory - by default--that is, when you don't + in or below the current directory unless you explicitly specify one or more targets on the command line. Sometimes, however, you may want - to specify explicitly that only + to specify that only certain programs, or programs in certain directories, should be built by default. You do this with the &Default; function: @@ -2193,16 +2192,16 @@ prog2.c <para> &SCons; supports a &DEFAULT_TARGETS; variable - that lets you get at the current list of default targets. + that lets you get at the current list of default targets + specified by calls to the &Default; function or method. The &DEFAULT_TARGETS; variable has two important differences from the &COMMAND_LINE_TARGETS; variable. First, the &DEFAULT_TARGETS; variable is a list of internal &SCons; nodes, so you need to convert the list elements to strings if you want to print them or look for a specific target name. - Fortunately, you can do this easily - by using the Python <function>map</function> function - to run the list through <function>str</function>: + You can do this easily by calling the <function>str</function> + on the elements in a list comprehension: </para> @@ -2210,7 +2209,7 @@ prog2.c <file name="SConstruct" printme="1"> prog1 = Program('prog1.c') Default(prog1) -print("DEFAULT_TARGETS is", map(str, DEFAULT_TARGETS)) +print("DEFAULT_TARGETS is %s" % [str(t) for t in DEFAULT_TARGETS]) </file> <file name="prog1.c"> prog1.c @@ -2234,7 +2233,7 @@ prog1.c <para> Second, - the contents of the &DEFAULT_TARGETS; list change + the contents of the &DEFAULT_TARGETS; list changes in response to calls to the &Default; function, as you can see from the following &SConstruct; file: @@ -2244,10 +2243,10 @@ prog1.c <file name="SConstruct" printme="1"> prog1 = Program('prog1.c') Default(prog1) -print("DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)) +print("DEFAULT_TARGETS is now %s" % [str(t) for t in DEFAULT_TARGETS]) prog2 = Program('prog2.c') Default(prog2) -print("DEFAULT_TARGETS is now", map(str, DEFAULT_TARGETS)) +print("DEFAULT_TARGETS is now %s" % [str(t) for t in DEFAULT_TARGETS]) </file> <file name="prog1.c"> prog1.c @@ -2338,7 +2337,7 @@ else: prog1 = Program('prog1.c') Program('prog2.c') Default(prog1) -print("BUILD_TARGETS is", map(str, BUILD_TARGETS)) +print ("BUILD_TARGETS is %s" % [str(t) for t in BUILD_TARGETS]) </file> <file name="prog1.c"> prog1.c @@ -2352,7 +2351,9 @@ prog2.c Notice how the value of &BUILD_TARGETS; changes depending on whether a target is - specified on the command line: + specified on the command line - &BUILD_TARGETS; + takes from &DEFAULT_TARGETS; + only if there are no &COMMAND_LINE_TARGETS;: </para> diff --git a/doc/user/copyright.xml b/doc/user/copyright.xml index 6971581..cc9acac 100644 --- a/doc/user/copyright.xml +++ b/doc/user/copyright.xml @@ -1,44 +1,43 @@ <?xml version='1.0'?> <!DOCTYPE sconsdoc [ - <!ENTITY % scons SYSTEM "../scons.mod"> - %scons; -]> + <!ENTITY % scons SYSTEM "../scons.mod"> + %scons; + ]> <legalnotice 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"> -<!-- + <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation - Permission is hereby granted, free of charge, to any person obtaining - a copy of this software and associated documentation files (the - "Software"), to deal in the Software without restriction, including - 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: + 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 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. + 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. ---> + --> -<blockquote> - <para> + <blockquote> + <para> + SCons User's Guide Copyright (c) 2004-2019 Steven Knight + </para> + </blockquote> - SCons User's Guide Copyright (c) 2004, 2005, 2006, 2007 Steven Knight - - </para> -</blockquote> </legalnotice> diff --git a/doc/user/depends.xml b/doc/user/depends.xml index 29a79a5..35372e7 100644 --- a/doc/user/depends.xml +++ b/doc/user/depends.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -518,7 +518,7 @@ cc -o hello hello.o <file name="SConstruct" printme="1"> Program('hello.c') def decide_if_changed(dependency, target, prev_ni): - if self.get_timestamp() != prev_ni.timestamp: + if dependency.get_timestamp() != prev_ni.timestamp: dep = str(dependency) tgt = str(target) if specific_part_of_file_has_changed(dep, tgt): @@ -571,7 +571,7 @@ int main() { printf("Hello, world!\n"); } The <emphasis>content signature</emphasis>, or MD5 checksum, of the contents of the <varname>dependency</varname> - file the list time the ⌖ was built. + file the last time the ⌖ was built. </para> </listitem> @@ -583,7 +583,7 @@ int main() { printf("Hello, world!\n"); } <listitem> <para> The size in bytes of the <varname>dependency</varname> - file the list time the target was built. + file the last time the target was built. </para> </listitem> @@ -595,7 +595,7 @@ int main() { printf("Hello, world!\n"); } <listitem> <para> The modification time of the <varname>dependency</varname> - file the list time the ⌖ was built. + file the last time the ⌖ was built. </para> </listitem> diff --git a/doc/user/environments.xml b/doc/user/environments.xml index ea5d472..ede9bc3 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -385,9 +385,9 @@ environment, of directory names, suffixes, etc. <para> A &consenv; - is a distinct object creating within + is a distinct object created within a &SConscript; file and - and which contains values that + which contains values that affect how &SCons; decides what action to use to build a target, and even to define which targets @@ -627,7 +627,7 @@ int main() { } <scons_example name="environments_ex6"> <file name="SConstruct" printme="1"> env = Environment() -print("CC is:", env['CC']) +print("CC is: %s"%env['CC']) </file> </scons_example> @@ -721,7 +721,7 @@ for item in sorted(env.Dictionary().items()): <sconstruct> env = Environment() -print("CC is:", env.subst('$CC')) +print("CC is: %s"%env.subst('$CC')) </sconstruct> <para> @@ -738,7 +738,7 @@ print("CC is:", env.subst('$CC')) <sconstruct> env = Environment(CCFLAGS = '-DFOO') -print("CCCOM is:", env['CCCOM']) +print("CCCOM is: %s"%env['CCCOM']) </sconstruct> <para> @@ -764,7 +764,7 @@ scons: `.' is up to date. <sconstruct> env = Environment(CCFLAGS = '-DFOO') -print("CCCOM is:", env.subst('$CCCOM')) +print("CCCOM is: %s"%env.subst('$CCCOM')) </sconstruct> <para> @@ -806,7 +806,7 @@ scons: `.' is up to date. <scons_example name="environments_missing1"> <file name="SConstruct" printme="1"> env = Environment() -print("value is:", env.subst( '->$MISSING<-' )) +print("value is: %s"%env.subst( '->$MISSING<-' )) </file> </scons_example> @@ -834,7 +834,7 @@ print("value is:", env.subst( '->$MISSING<-' )) <file name="SConstruct" printme="1"> AllowSubstExceptions() env = Environment() -print("value is:", env.subst( '->$MISSING<-' )) +print("value is: %s"%env.subst( '->$MISSING<-' )) </file> </scons_example> @@ -854,7 +854,7 @@ print("value is:", env.subst( '->$MISSING<-' )) <file name="SConstruct" printme="1"> AllowSubstExceptions(IndexError, NameError, ZeroDivisionError) env = Environment() -print("value is:", env.subst( '->${1 / 0}<-' )) +print("value is: %s"%env.subst( '->${1 / 0}<-' )) </file> </scons_example> @@ -1216,7 +1216,7 @@ int main() { } <file name="SConstruct" printme="1"> env = Environment() env.Replace(NEW_VARIABLE = 'xyzzy') -print("NEW_VARIABLE =", env['NEW_VARIABLE']) +print("NEW_VARIABLE = %s"%env['NEW_VARIABLE']) </file> </scons_example> @@ -1251,11 +1251,11 @@ print("NEW_VARIABLE =", env['NEW_VARIABLE']) <scons_example name="environments_Replace2"> <file name="SConstruct" printme="1"> env = Environment(CCFLAGS = '-DDEFINE1') -print("CCFLAGS =", env['CCFLAGS']) +print("CCFLAGS = %s"%env['CCFLAGS']) env.Program('foo.c') env.Replace(CCFLAGS = '-DDEFINE2') -print("CCFLAGS =", env['CCFLAGS']) +print("CCFLAGS = %s"%env['CCFLAGS']) env.Program('bar.c') </file> <file name="foo.c"> @@ -1375,7 +1375,7 @@ int main() { } <file name="SConstruct" printme="1"> env = Environment() env.Append(NEW_VARIABLE = 'added') -print("NEW_VARIABLE =", env['NEW_VARIABLE']) +print("NEW_VARIABLE = %s"%env['NEW_VARIABLE']) </file> </scons_example> @@ -1475,7 +1475,7 @@ int main() { } <file name="SConstruct" printme="1"> env = Environment() env.Prepend(NEW_VARIABLE = 'added') -print("NEW_VARIABLE =", env['NEW_VARIABLE']) +print("NEW_VARIABLE = %s"%env['NEW_VARIABLE']) </file> </scons_example> @@ -1630,7 +1630,7 @@ env['ENV']['PATH'] = '/usr/local/bin:/bin:/usr/bin' But doing so makes your &SConscript; file less portable, (although in this case that may not be a huge concern - since the directories you list are likley system-specific, anyway). + since the directories you list are likely system-specific, anyway). </para> diff --git a/doc/user/epub.xsl b/doc/user/epub.xsl index fc95c60..818a874 100644 --- a/doc/user/epub.xsl +++ b/doc/user/epub.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/user/errors.xml b/doc/user/errors.xml index 78b4f39..e7e611e 100644 --- a/doc/user/errors.xml +++ b/doc/user/errors.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/example.xml b/doc/user/example.xml index b1453ab..4787595 100644 --- a/doc/user/example.xml +++ b/doc/user/example.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/factories.xml b/doc/user/factories.xml index 916c269..43e417b 100644 --- a/doc/user/factories.xml +++ b/doc/user/factories.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/file-removal.xml b/doc/user/file-removal.xml index bc2d89b..fe38cf7 100644 --- a/doc/user/file-removal.xml +++ b/doc/user/file-removal.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/functions.xml b/doc/user/functions.xml index 6093395..bebc7bf 100644 --- a/doc/user/functions.xml +++ b/doc/user/functions.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/gettext.xml b/doc/user/gettext.xml index 8daf5f9..36f0419 100644 --- a/doc/user/gettext.xml +++ b/doc/user/gettext.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/hierarchy.xml b/doc/user/hierarchy.xml index f65a128..dc07e87 100644 --- a/doc/user/hierarchy.xml +++ b/doc/user/hierarchy.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/html.xsl b/doc/user/html.xsl index 2df2fee..5ff8e53 100644 --- a/doc/user/html.xsl +++ b/doc/user/html.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/user/install.xml b/doc/user/install.xml index 7024320..b3cb9dd 100644 --- a/doc/user/install.xml +++ b/doc/user/install.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/java.xml b/doc/user/java.xml index 73afbc7..19b51e8 100644 --- a/doc/user/java.xml +++ b/doc/user/java.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/less-simple.xml b/doc/user/less-simple.xml index c17bdae..6de1075 100644 --- a/doc/user/less-simple.xml +++ b/doc/user/less-simple.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -644,4 +644,61 @@ Program('bar', bar_files) </section> -</chapter> + <section> + <title>Overriding construction variables when calling a Builder</title> + + <para> + + It is possible to override or add construction variables + when calling a builder method by passing additional keyword arguments. + These overridden or added variables will only be in effect when + building the target, so they will not affect other parts of the build. + For example, if you want to add additional libraries for just one program: + + </para> + + <programlisting> +env.Program('hello', 'hello.c', LIBS=['gl', 'glut']) + </programlisting> + + <para> + + or generate a shared library with a non-standard suffix: + + </para> + + <programlisting> +env.SharedLibrary('word', 'word.cpp', + SHLIBSUFFIX='.ocx', + LIBSUFFIXES=['.ocx']) + </programlisting> + + <para> + + It is also possible to use the <literal>parse_flags</literal> keyword argument in an + override: + + </para> + + <para> + + This example adds 'include' to &cv-link-CPPPATH;, + 'EBUG' to &cv-link-CPPDEFINES;, and 'm' to &cv-link-LIBS;. + + </para> + + <programlisting> +env = Program('hello', 'hello.c', parse_flags = '-Iinclude -DEBUG -lm') + </programlisting> + + <para> + + Within the call to the builder action the environment is not cloned, + instead an OverrideEnvironment() is created which is more + light weight than a whole Environment() + + </para> + + </section> + +</chapter>
\ No newline at end of file diff --git a/doc/user/libraries.xml b/doc/user/libraries.xml index b905923..c6b8069 100644 --- a/doc/user/libraries.xml +++ b/doc/user/libraries.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/main.xml b/doc/user/main.xml index ad2ffe8..01470cc 100644 --- a/doc/user/main.xml +++ b/doc/user/main.xml @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -74,10 +74,10 @@ <corpauthor>Steven Knight and the SCons Development Team</corpauthor> - <pubdate>2004 - 2017</pubdate> + <pubdate>2004 - 2019</pubdate> <copyright> - <year>2004 - 2017</year> + <year>2004 - 2019</year> <holder>The SCons Foundation</holder> </copyright> diff --git a/doc/user/make.xml b/doc/user/make.xml index 4f1199d..ac6db2b 100644 --- a/doc/user/make.xml +++ b/doc/user/make.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/mergeflags.xml b/doc/user/mergeflags.xml index 36bb061..d802125 100644 --- a/doc/user/mergeflags.xml +++ b/doc/user/mergeflags.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/misc.xml b/doc/user/misc.xml index ed96625..5ade6d3 100644 --- a/doc/user/misc.xml +++ b/doc/user/misc.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -268,9 +268,9 @@ hello.c <scons_example name="misc_FindFile1a"> <file name="SConstruct" printme="1"> # one directory -print(FindFile('missing', '.')) +print("%s"%FindFile('missing', '.')) t = FindFile('exists', '.') -print(t.__class__, t) +print("%s %s"%(t.__class__, t)) </file> <file name="exists"> exists @@ -287,7 +287,7 @@ print(t.__class__, t) includes = [ '.', 'include', 'src/include'] headers = [ 'nonesuch.h', 'config.h', 'private.h', 'dist.h'] for hdr in headers: - print('%-12s' % ('%s:' % hdr), FindFile(hdr, includes)) + print('%-12s: %s'%(hdr, FindFile(hdr, includes))) </file> <file name="config.h"> exists @@ -625,4 +625,53 @@ env.Command('directory_build_info', </section> + <section> + <title>Virtual environments (virtualenvs)</title> + + <para> + + Virtualenv is a tool to create isolated Python environments. + A python application (such as SCons) may be executed within + an activated virtualenv. The activation of virtualenv modifies + current environment by defining some virtualenv-specific variables + and modifying search PATH, such that executables installed within + virtualenv's home directory are preferred over the ones installed + outside of it. + + </para> + + <para> + + Normally, SCons uses hard-coded PATH when searching for external + executables, so it always picks-up executables from these pre-defined + locations. This applies also to python interpreter, which is invoked + by some custom SCons tools or test suites. This means, when running + SCons in a virtualenv, an eventual invocation of python interpreter from + SCons script will most probably jump out of virtualenv and execute + python executable found in hard-coded SCons PATH, not the one which is + executing SCons. Some users may consider this as an inconsistency. + + </para> + + <para> + This issue may be overcome by using <literal>--enable-virtualenv</literal> + 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> + 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. + </para> + + <para> + 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 + unactivated virtualenv. + </para> + + </section> + </chapter> diff --git a/doc/user/nodes.xml b/doc/user/nodes.xml index e627bba..da1d158 100644 --- a/doc/user/nodes.xml +++ b/doc/user/nodes.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -265,8 +265,8 @@ xyzzy = Entry('xyzzy') <file name="SConstruct" printme="1"> object_list = Object('hello.c') program_list = Program(object_list) -print("The object file is:", object_list[0]) -print("The program file is:", program_list[0]) +print("The object file is: %s"%object_list[0]) +print("The program file is: %s"%program_list[0]) </file> <file name="hello.c"> int main() { printf("Hello, world!\n"); } @@ -334,7 +334,7 @@ import os.path program_list = Program('hello.c') program_name = str(program_list[0]) if not os.path.exists(program_name): - print(program_name, "does not exist!") + print("%s does not exist!"%program_name) </file> <file name="hello.c"> int main() { printf("Hello, world!\n"); } diff --git a/doc/user/output.xml b/doc/user/output.xml index cf5776d..db16393 100644 --- a/doc/user/output.xml +++ b/doc/user/output.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/parseconfig.xml b/doc/user/parseconfig.xml index 2367857..096d236 100644 --- a/doc/user/parseconfig.xml +++ b/doc/user/parseconfig.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/parseflags.xml b/doc/user/parseflags.xml index 52cbdd7..26313ce 100644 --- a/doc/user/parseflags.xml +++ b/doc/user/parseflags.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -57,7 +57,7 @@ &SCons; construction environments have a &ParseFlags; method that takes a set of typical command-line options - and distrbutes them into the appropriate construction variables. + and distributes them into the appropriate construction variables. Historically, it was created to support the &ParseConfig; method, so it focuses on options used by the GNU Compiler Collection (GCC) for the C and C++ toolchains. diff --git a/doc/user/pdf.xsl b/doc/user/pdf.xsl index 4a81d56..0f797d3 100644 --- a/doc/user/pdf.xsl +++ b/doc/user/pdf.xsl @@ -1,7 +1,7 @@ <?xml version='1.0'?>
<!--
- Copyright (c) 2001 - 2017 The SCons Foundation
+ Copyright (c) 2001 - 2019 The SCons Foundation
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/doc/user/preface.xml b/doc/user/preface.xml index 443bf38..62cd47b 100644 --- a/doc/user/preface.xml +++ b/doc/user/preface.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/python.xml b/doc/user/python.xml index 82443f9..177cb5c 100644 --- a/doc/user/python.xml +++ b/doc/user/python.xml @@ -22,7 +22,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/repositories.xml b/doc/user/repositories.xml index 6aae2e3..189a8cd 100644 --- a/doc/user/repositories.xml +++ b/doc/user/repositories.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/run.xml b/doc/user/run.xml index af28868..c9c5c6a 100644 --- a/doc/user/run.xml +++ b/doc/user/run.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/scanners.xml b/doc/user/scanners.xml index 9e3ce99..e1b2249 100644 --- a/doc/user/scanners.xml +++ b/doc/user/scanners.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -410,6 +410,59 @@ kscan = Scanner(function = kfile_scan, This is important since many files get scanned in a typical build. </para> - </section> + </section> + + <section> + <title>Using scanners with Builders</title> + + <para> + + One approach for the use of scanners is with builders. + There are two optional parameters we can use with a builder + <literal>source_scanner</literal> and <literal>target_scanner</literal>. + + </para> + + <scons_example name="scanners_builders"> + <file name="SConstruct" printme="1"> + +def kfile_scan(node, env, path, arg): + contents = node.get_text_contents() + return env.File(include_re.findall(contents)) + +kscan = Scanner(function = kfile_scan, + skeys = ['.k'], + path_function = FindPathDirs('KPATH')) + +def build_function(target, source, env): + # Code to build "target" from "source" + return None + +bld = Builder(action = build_function, + suffix = '.foo', + source_scanner = kscan + src_suffix = '.input') +env = Environment(BUILDERS = {'Foo' : bld}) +env.Foo('file') + + </file> + </scons_example> + + <para> + + An emitter function can modify the list of sources or targets + passed to the action function when the builder is triggered. + + </para> + + <para> + + A scanner function will not affect the list of sources or targets + seen by the builder during the build action. The scanner function + will however affect if the builder should be rebuilt (if any of + the files sourced by the scanner have changed for example). + + </para> + </section> </chapter> diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml index d0537cb..b8a903d 100644 --- a/doc/user/sconf.xml +++ b/doc/user/sconf.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/scons_title.xsl b/doc/user/scons_title.xsl index 130c6a5..21c56da 100644 --- a/doc/user/scons_title.xsl +++ b/doc/user/scons_title.xsl @@ -1,7 +1,7 @@ <?xml version="1.0"?> <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/separate.xml b/doc/user/separate.xml index bac7e4d..26500d6 100644 --- a/doc/user/separate.xml +++ b/doc/user/separate.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/sideeffect.xml b/doc/user/sideeffect.xml index 16dbd08..e630e4f 100644 --- a/doc/user/sideeffect.xml +++ b/doc/user/sideeffect.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/simple.xml b/doc/user/simple.xml index af7868b..43121c0 100644 --- a/doc/user/simple.xml +++ b/doc/user/simple.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/sourcecode.xml b/doc/user/sourcecode.xml index b3c51e4..f7cd492 100644 --- a/doc/user/sourcecode.xml +++ b/doc/user/sourcecode.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/tasks.xml b/doc/user/tasks.xml index 248dcd3..32e575a 100644 --- a/doc/user/tasks.xml +++ b/doc/user/tasks.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/tools.xml b/doc/user/tools.xml index 0c56603..bc9f6b9 100644 --- a/doc/user/tools.xml +++ b/doc/user/tools.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/troubleshoot.xml b/doc/user/troubleshoot.xml index aecac57..606c727 100644 --- a/doc/user/troubleshoot.xml +++ b/doc/user/troubleshoot.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/variables.xml b/doc/user/variables.xml index e0d1d32..b7b8d4e 100644 --- a/doc/user/variables.xml +++ b/doc/user/variables.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/doc/user/variants.xml b/doc/user/variants.xml index 1944201..8b78c2b 100644 --- a/doc/user/variants.xml +++ b/doc/user/variants.xml @@ -21,7 +21,7 @@ <!-- - Copyright (c) 2001 - 2017 The SCons Foundation + Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/site_scons/SConsRevision.py b/site_scons/SConsRevision.py new file mode 100644 index 0000000..11de670 --- /dev/null +++ b/site_scons/SConsRevision.py @@ -0,0 +1,40 @@ +import os + +def SCons_revision(target, source, env): + """Interpolate specific values from the environment into a file. + + This is used to copy files into a tree that gets packaged up + into the source file package. + """ + t = str(target[0]) + s = source[0].rstr() + + try: + with open(s, 'r') as fp: + contents = fp.read() + + + # Note: We construct the __*__ substitution strings here + # so that they don't get replaced when this file gets + # copied into the tree for packaging. + contents = contents.replace('__BUILD' + '__', env['BUILD']) + contents = contents.replace('__BUILDSYS' + '__', env['BUILDSYS']) + contents = contents.replace('__COPYRIGHT' + '__', env['COPYRIGHT']) + contents = contents.replace('__DATE' + '__', env['DATE']) + contents = contents.replace('__DEB_DATE' + '__', env['DEB_DATE']) + + contents = contents.replace('__DEVELOPER' + '__', env['DEVELOPER']) + contents = contents.replace('__FILE' + '__', str(source[0]).replace('\\', '/')) + contents = contents.replace('__MONTH_YEAR'+ '__', env['MONTH_YEAR']) + contents = contents.replace('__REVISION' + '__', env['REVISION']) + contents = contents.replace('__VERSION' + '__', env['VERSION']) + contents = contents.replace('__NULL' + '__', '') + open(t, 'w').write(contents) + except UnicodeDecodeError as e: + print("Error decoding file:%s just copying no revision edit") + with open(s, 'rb') as fp: + contents = fp.read() + open(t, 'wb').write(contents) + + + os.chmod(t, os.stat(s)[0])
\ No newline at end of file diff --git a/site_scons/Utilities.py b/site_scons/Utilities.py new file mode 100644 index 0000000..e8c0585 --- /dev/null +++ b/site_scons/Utilities.py @@ -0,0 +1,43 @@ +import os +import stat +import time +import distutils.util + + +platform = distutils.util.get_platform() + +def is_windows(): + " Check if we're on a Windows platform" + if platform.startswith('win'): + return True + else: + return False + + +def whereis(filename): + """ + An internal "whereis" routine to figure out if a given program + is available on this system. + """ + exts = [''] + if is_windows(): + exts += ['.exe'] + for dir in os.environ['PATH'].split(os.pathsep): + f = os.path.join(dir, filename) + for ext in exts: + f_ext = f + ext + if os.path.isfile(f_ext): + try: + st = os.stat(f_ext) + except: + continue + if stat.S_IMODE(st[stat.ST_MODE]) & 0o111: + return f_ext + return None + +# Datestring for debian +# Should look like: Mon, 03 Nov 2016 13:37:42 -0700 +deb_date = time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()) + + + diff --git a/site_scons/site_init.py b/site_scons/site_init.py new file mode 100644 index 0000000..b62eb37 --- /dev/null +++ b/site_scons/site_init.py @@ -0,0 +1,4 @@ +from SConsRevision import SCons_revision +from Utilities import is_windows, whereis, platform, deb_date +from zip_utils import unzipit, zipit, zcat +from soe_utils import soelim, soscan, soelimbuilder
\ No newline at end of file diff --git a/site_scons/soe_utils.py b/site_scons/soe_utils.py new file mode 100644 index 0000000..451c7de --- /dev/null +++ b/site_scons/soe_utils.py @@ -0,0 +1,36 @@ +import os.path +import re + +from SCons.Script import Builder, Action, Scanner + +def soelim(target, source, env): + """ + Interpolate files included in [gnt]roff source files using the + .so directive. + + This behaves somewhat like the soelim(1) wrapper around groff, but + makes us independent of whether the actual underlying implementation + includes an soelim() command or the corresponding command-line option + to groff(1). The key behavioral difference is that this doesn't + recursively include .so files from the include file. Not yet, anyway. + """ + t = str(target[0]) + s = str(source[0]) + dir, f = os.path.split(s) + tfp = open(t, 'w') + sfp = open(s, 'r') + for line in sfp.readlines(): + if line[:4] in ['.so ', "'so "]: + sofile = os.path.join(dir, line[4:-1]) + tfp.write(open(sofile, 'r').read()) + else: + tfp.write(line) + sfp.close() + tfp.close() + +def soscan(node, env, path): + c = node.get_text_contents() + return re.compile(r"^[\.']so\s+(\S+)", re.M).findall(c) + +soelimbuilder = Builder(action = Action(soelim), + source_scanner = Scanner(soscan)) diff --git a/site_scons/zip_utils.py b/site_scons/zip_utils.py new file mode 100644 index 0000000..3d5821e --- /dev/null +++ b/site_scons/zip_utils.py @@ -0,0 +1,54 @@ +import os.path + + +zcat = 'gzip -d -c' + +# +# Figure out if we can handle .zip files. +# +zipit = None +unzipit = None +try: + import zipfile + + def zipit(env, target, source): + print("Zipping %s:" % str(target[0])) + def visit(arg, dirname, filenames): + for filename in filenames: + path = os.path.join(dirname, filename) + if os.path.isfile(path): + arg.write(path) + # default ZipFile compression is ZIP_STORED + zf = zipfile.ZipFile(str(target[0]), 'w', compression=zipfile.ZIP_DEFLATED) + olddir = os.getcwd() + os.chdir(env['CD']) + try: + for dirname, dirnames, filenames in os.walk(env['PSV']): + visit(zf, dirname, filenames) + finally: + os.chdir(olddir) + zf.close() + + def unzipit(env, target, source): + print("Unzipping %s:" % str(source[0])) + zf = zipfile.ZipFile(str(source[0]), 'r') + for name in zf.namelist(): + dest = os.path.join(env['UNPACK_ZIP_DIR'], name) + dir = os.path.dirname(dest) + try: + os.makedirs(dir) + except: + pass + print(dest,name) + # if the file exists, then delete it before writing + # to it so that we don't end up trying to write to a symlink: + if os.path.isfile(dest) or os.path.islink(dest): + os.unlink(dest) + if not os.path.isdir(dest): + with open(dest, 'wb') as fp: + fp.write(zf.read(name)) + +except ImportError: + if unzip and zip: + zipit = "cd $CD && $ZIP $ZIPFLAGS $( ${TARGET.abspath} $) $PSV" + unzipit = "$UNZIP $UNZIPFLAGS $SOURCES" diff --git a/src/Announce.txt b/src/Announce.txt index ebda22e..324b9fc 100644..100755 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,24 +18,73 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.html#users to sign up for the scons-users mailing list. -RELEASE 3.0.0 - Mon, 18 Sep 2017 08:32:04 -0700 +RELEASE 3.0.5 - Mon, 26 Mar 2019 15:04:42 -0700 Please consult the RELEASE.txt file for a summary of changes since the last release and consult the CHANGES.txt file for complete a list of changes since last release. This announcement highlights only the important changes. + Please note the following important changes since release 3.0.4: + - Change the default for AppendENVPath to delete_existing=0, so path + order will not be changed, unless explicitly set (Issue #3276) + - Add lex construction variable LEXUNISTD for turning off unix headers on windows + - Update lex tool to use win_flex on windows if available + - Add the textfile tool to the default tool list + - The mingw tool now respects SHCCCOMSTR, SHLINKCOMSTR and LDMODULECOMSTR + - Add support for finding vswhere under 32 bit Windows installs + + + Please note the following important changes since release 3.0.3: + - Added TEMPFILESUFFIX to allow user to specify suffix for tempfiles used for long command lines + - Initial support for ARM architectures with Microsoft Visual Studio 2017. You must set TARGET_ARCH + to arm or arm64 to enable. + - Fixed issue detecting installs of Microsoft Visual Studio 2017 as well as Microsoft build tools 2017. + Please note the following important changes since release 2.5.1: - *IT IS NOT READY FOR PRODUCTION USE* This is the initial release supporting both python 3.5+ and 2.7.x and pypy There are some important changes: - - Any print statements must now use python 3 syntax of "print()" + - Properly support versioned shared libraries for MacOS. We've also introduced two + new env variables APPLELINK_CURRENT_VERSION and APPLELINK_COMPATIBILITY_VERSION which will specify + what is passed to the linkers -current_version and -compatibility_version flags. If not specified + they will be derived from SHLIBVERSION as such: + - APPLELINK_CURRENT_VERSION = SHLIBVERSION + - APPLELINK_COMPATIBILITY_VERSION = all but the last digit in SHLIBVERSION with .0 appended. + Note that the values of the above will be validated. Valid format for either APPLELINK variable is + X[.Y[.Z]] where 0 <= X <= 65535, 0 <= Y <= 255, 0 <= Z <= 255. + - Fix issue #2980 with credit to Piotr Bartosik (and William Blevins). This is an issue where using + TimeStamp-MD5 Decider and CacheDir can yield incorrect md5's being written into the .sconsign. + The difference between Piotr Bartosik's patch and the current code is that the more complicated + creation of file to csig map is only done when the count of children for the current node doesn't + match the previous count which is loaded from the sconsign. + - Add flag must_exist to SConscript() call to fail on missing script. + Not failing on missing script is now considered deprecated, and the first instance will print a + deprecation message. + - Add xz compression format to packaging choices. + - Add Textfile/Substfile to default environment. (issue #3147) + - Remove long deprecated SCons.Options which have been replaced by *Variable() + many years ago. + - Updated logic for mingw and clang on win32 to search default tool install paths if not + found in normal SCons PATH. If the user specifies PATH or tool specific paths they + will be used and the default paths below will be ignored. + - Default path for clang/clangxx : C:\Program Files\LLVM\bin + - Default path for mingw : C:\MinGW\bin and/or C:\mingw-w64\*\mingw64\bin + - Key program to locate mingw : mingw32-make (as the gcc with mingw prefix has no fixed name) + - Added virtualenv support. A new function Virtualenv() determines whether + SCons runs in a virtualenv. The search PATH may also be extended to + prefer executables from the current virtualenv over the ones provided by + base environment. New option --enable-virtualenv provided to import some + virtualenv-related variables to SCons and extend every env['ENV']['PATH'] + automatically. New option --ignore-virtualenv disables this. Two + environment variables, SCONS_ENABLE_VIRTUALENV and + SCONS_IGNORE_VIRTUALENV are supported for the same purpose. + - Recognize new java 9, 10, 11 (as 9.0 and 10.0, 11.0) - All node content should be in bytes. This is the default in python 2.7.x, in Python 3 all strings are by default unicode. byte and/or bytearray should be used if you construct content for return by a custom node type's get_content() method. - - This is some (as yet unresolved issue) using Literal()'s in some context with + - There are some (as yet unresolved issue) using Literal()'s in some context with Python 3 - pypy should be supported, please report any issues to the user's mailing list. - Currently if you switch back and forth between python 2.7.x and 3.5+ you will @@ -1266,6 +1315,3 @@ improve SCons for your needs. -- The SCons Development Team Gary Oberbrunner and Bill Deegan, maintainers Thanks to all the contributors for all your help! - -Copyright (c) 2001 - 2017 The SCons Foundation -src/Announce.txt rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog diff --git a/src/CHANGES.txt b/src/CHANGES.txt index ff28506..c46a804 100644..100755 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -5,6 +5,335 @@ Change Log +RELEASE 3.0.5 - Mon, 26 Mar 2019 15:04:42 -0700 + + From William Deegan: + + - Fix Issue #3283 - Handle using --config=force in combination with Decider('MD5-timestamp'). + 3.0.2 in fix for issue #2980 added that deciders can throw DeciderNeedsNode exception. + The Configure logic directly calls the decider when using --config=force but wasn't handling + that exception. This would yield minimally configure tests using TryLink() not running and + leaving TypeError Nonetype exception in config.log + - Fix Issue #3303 - Handle --config=force overwriting the Environment passed into Configure()'s + Decider and not clearing it when the configure context is completed. + - Add default paths for yacc tool on windows to include cygwin, mingw, and chocolatey + - Fix issue #2799 - Fix mingw tool to respect SHCCCOMSTR, SHLINKCOMSTR and LDMODULECOMSTR + - Fix Issue #3329 - Add support for MS SDK V10.0A (which is commonly installed with VS2017) + - Fix Issue #3333 - Add support for finding vswhere under 32 bit windows installs. + + From Maciej Kumorek: + - Update the MSVC tool to include the nologo flag by default in RCFLAGS + + From Daniel Moody: + - Change the default for AppendENVPath to delete_existing=0, so path + order will not be changed, unless explicitly set (Issue #3276) + - Fixed bug which threw error when running SCons on windows system with no MSVC installed. + - Update link tool to convert target to node before accessing node member + - Update mingw tool to remove MSVC like nologo CCFLAG + - Add default paths for lex tool on windows to include cygwin, mingw, and chocolatey + - Add lex construction variable LEXUNISTD for turning off unix headers on windows + - Update lex tool to use win_flex on windows if available + + From Mats Wichmann: + - Quiet open file ResourceWarnings on Python >= 3.6 caused by + not using a context manager around Popen.stdout + - Add the textfile tool to the default tool list + - Fix syntax on is/is not clauses: should not use with a literal + - Properly retrieve exit code when catching SystemExit + - scons-time now uses context managers around file opens + - Fix regex patterns that were not specified as raw strings + + From Bernhard M. Wiedemann: + - Do not store build host+user name if reproducible builds are wanted + + +RELEASE 3.0.4 - Mon, 20 Jan 2019 22:49:27 +0000 + + From Mats Wichmann: + - Improve finding of Microsoft compiler: add a 'products' wildcard + in case 2017 Build Tools only is installed as it is considered a separate + product from the default Visual Studio + - Add TEMPFILESUFFIX to allow a customizable filename extension, as + described in the patch attached to issue #2431. + - scons.py and sconsign.py stopped working if script called as a symlink + to location in scons-local location. + - Fix issue running scons using a symlink to scons.py in an scons-local dir + - Doc updates around Default(), and the various *TARGETS variables. + + From Daniel Moody: + - Improved support for VC14.1 and Visual Studio 2017, as well as arm and arm64 targets. + Issues #3268 & Issue #3222 + - Initial support for ARM targets with Visual Studio 2017 - Issue #3182 (You must set TARGET_ARCH for this to work) + - Update TempFileMunge class to use PRINT_CMD_LINE_FUNC + + From Tobias Herzog + - Enhance cpp scanner regex logic to detect if/elif expressions without whitespaces but + parenthesis like "#if(defined FOO)" or "#elif!(BAR)" correctly. + + +RELEASE 3.0.3 - Mon, 07 Jan 2019 20:05:22 -0400 + NOTE: 3.0.2 release was dropped because there was a packaging bug. Please consider all 3.0.2 + content. + + From William Deegan: + - Fixes to packaging logic. Ensuring the SCons.Tool.clangCommon module is added + to the release packages. + - Modify scons.bat script to check for scons python script without .py extension if no file + scons.py exists. This enables an all platform wheel to work. + + From Mats Wichmann: + - Update doc examples to work with Python 3.5+: map() now returns an iterable instead of a list. + + +RELEASE 3.0.2 - Mon, 31 Dec 2018 16:00:12 -0700 + + From Bernard Blackham: + - Fixed handling of side-effects in task master (fixes #3013). + + From William Deegan: + - Remove long deprecated SCons.Options code and tests. This removes BoolOption,EnumOption, + ListOption,PackageOption, and PathOption which have been replaced by *Variable() many years ago. + - Re-Enable parallel SCons (-j) when running via Pypy + - Move SCons test framework files to testing/framework and remove all references to QMtest. + QMTest has not been used by SCons for some time now. + - Updated logic for mingw and clang on win32 to search default tool install paths if not + found in normal SCons PATH. If the user specifies PATH or tool specific paths they + will be used and the default paths below will be ignored. + - Default path for clang/clangxx : C:\Program Files\LLVM\bin + - Default path for mingw : C:\MinGW\bin and/or C:\mingw-w64\*\mingw64\bin + - Key program to locate mingw : mingw32-make (as the gcc with mingw prefix has no fixed name) + - Fixed issue causing stack trace when python Action function contains a unicode string when being + run with Python 2.7 + - Add alternate path to QT install for Centos in qt tool: /usr/lib64/qt-3.3/bin + - Fix Java tools to search reasonable default paths for Win32, Linux, macOS. Add required paths + for swig and java native interface to JAVAINCLUDES. You should add these to your CPPPATH if you need + to compile with them. This handles spaces in paths in default Java paths on windows. + - Added more java paths to match install for Centos 7 of openjdk + - Fix new logic which populates JAVAINCLUDES to handle the case where javac is not found. + - Fix GH Issue #2580 - # in FRAMEWORKPATH doesn't get properly expanded. The # is left in the + command line. + - Fix issue #2980 with credit to Piotr Bartosik (and William Blevins). This is an issue where using + TimeStamp-MD5 Decider and CacheDir can yield incorrect md5's being written into the .sconsign. + The difference between Piotr Bartosik's patch and the current code is that the more complicated + creation of file to csig map is only done when the count of children for the current node doesn't + match the previous count which is loaded from the sconsign. + - Fix issue # 3106 MSVC if using MSVC_BATCH and target dir had a space would fail due to quirk in + MSVC's handling of escaped targetdirs when batch compiling. + - Fix GH Issue #3141 unicode string in a TryAction() with python 2.7 crashes. + - Fix GH Issue #3212 - Use of Py3 and CacheDir + Configure's TryCompile (or likely and Python Value Nodes) + yielded trying to combine strings and bytes which threw exception. + - Fix GH Issue #3225 SCons.Util.Flatten() doesn't handle MappingView's produced by dictionary as return + values from dict().{items(), keys(), values()}. + - Fix GH Issue #3241 - Properly support versioned shared libraries for MacOS. We've also introduced two + new env variables APPLELINK_CURRENT_VERSION and APPLELINK_COMPATIBILITY_VERSION which will specify + what is passed to the linkers -current_version and -compatibility_version flags. If not specified + they will be derived from SHLIBVERSION as such: + - APPLELINK_CURRENT_VERSION = SHLIBVERSION + - APPLELINK_COMPATIBILITY_VERSION = all but the last digit in SHLIBVERSION with .0 appended. + Note that the values of the above will be validated. Valid format for either APPLELINK variable is + X[.Y[.Z]] where 0 <= X <= 65535, 0 <= Y <= 255, 0 <= Z <= 255. + The new variables have been added to the documents and should show up in user guide and manpage. + - Fix GH Issue #3136 no longer wrap io.{BufferedReader,BufferedWriter,BufferedRWPair,BufferedRandom,TextIOWrapper + with logic to set HANDLE_FLAG_INHERIT flag on the file handle. Python 3.4+ automatically sets this according + to Python docs: https://docs.python.org/3/library/os.html#fd-inheritance + + From Ray Donnelly: + - Fix the PATH created by scons.bat (and other .bat files) to provide a normalized + PATH. Some pythons in the 3.6 series are no longer able to handle paths which + have ".." in them and end up crashing. This is done by cd'ing into the directory + we want to add to the path and then using %CD% to give us the normalized directory + See bug filed under Python 3.6: https://bugs.python.org/issue32457. + Note: On Win32 PATH's which have not been normalized may cause undefined behavior + by other executables being run by SCons (or any subprocesses of executables being run by SCons). + Resolving this issue should eliminate that possibility going forward. + + From Andrew Featherstone + - Removed unused --warn options from the man page and source code. + + From Arda Fu + - Fix cpp scanner regex logic to treat ifndef for py3.5+. Previously it was + not properly differentiating between if, ifdef, and ifndef. + + From Philipp Maierhöfer + - Added a __hash__ method to the class Scons.Subst.Literal. Required when substituting Literal + objects when SCons runs with Python 3. + - Added missing FORTRANMODDIRPREFIX to the gfortran tool. + + From Matthew Marinets: + - Fixed an issue that caused the Java emitter to incorrectly parse arguments to constructors that + implemented a class. + + From Fredrik Medley: + - Fix exception when printing of EnviromentError messages. + Specifically, this fixes error reporting of the race condition when + initializing the cache which error previously was hidden. + + From Daniel Moody: + - Updated Jar builder to handle nodes and directories better + - Updated Jar builder to flatten source list which could contain embedded lists + - Removed some magic numbers from jar.py on behalf of Mats Wichmann (mats@linux.com) + - Set the pickling protocal back to highest which was causing issues + with variant dir tests. This will cause issues if reading sconsigns + pickled with the previous lower protocal. + - Updated swig to setup default paths for windows + - Updated gettext tools to setup default paths for windows with Cygwin/MinGW setups + - Add common location for default paths for cygwin and mingw in Platform modules + - Updated YACC tool to work on windows with Cygwin/MinGW setups + - Set the pickling protocal back to highest which was causing issues + with variant dir tests. This will cause issues if reading sconsigns + pickled with the previous lower protocal. + - Updated FS.py to handle removal of splitunc function from python 3.7 + - Updated the vc.py to ignore MSVS versions where not compiler could be found + + From Gary Oberbrunner: + - Fix bug when Installing multiple subdirs outside the source tree + - fix to_str to handle None without raising exception + - Fix -jN for python 3.7 + + From Jonathon Reinhart: + - Replace all instances of `int main()` in C code with `int main(void)`. + Specifically, this fixes the test cases use by Configure.CheckCC() which + would fail when using -Wstrict-prototypes. + + From Zachary Tessler: + - Fix calculation of signatures for FunctionActions that contain list (or set,...) + comprehensions whose expressions involve constant literals. Those constants had + been ignored in signatures, so changing them did not cause targets to be rebuilt. + + From Paweł Tomulik: + - In the testing framework, module TestCommon, fixed must_contain(), + must_not_contain(), and related methods of TestCommon class to work with + substrings located at zero offset. + - Added virtualenv support. A new function Virtualenv() determines whether + SCons runs in a virtualenv. The search PATH may also be extended to + prefer executables from the current virtualenv over the ones provided by + base environment. New option --enable-virtualenv provided to import some + virtualenv-related variables to SCons and extend every env['ENV']['PATH'] + automatically. New option --ignore-virtualenv disables this. Two + environment variables, SCONS_ENABLE_VIRTUALENV and + SCONS_IGNORE_VIRTUALENV are supported for the same purpose. + + From Richard West: + - Add SConstruct.py, Sconstruct.py, sconstruct.py to the search path for the root SConstruct file. + Allows easier debugging within Visual Studio + - Change setup.py to change the install directory (via pip, or setup.py install) from scons-#.#.# + to scons (Yielding <pythondir>/lib/scons/SCons/ instead of <pythondir>/lib/scons/SCons-#.#.#/). + This changes SCons to better comply with normal Python installation practices. + + From Mats Wichmann: + - Recognize new java 9, 10, 11 (as 9.0 and 10.0, 11.0) + - Updated manpage scons.xml to fix a nested list problem + - Updated doc terminiology: use prepend instead of append as appropriate + - XML validity fixes from SConstruct.py change + - Update wiki links to new github location + - Update bug links to new github location + - Make it easier for SConscript() call to fail on missing script. + It was possible to call SCons.Warnings.warningAsException + (not documented as a user API) to make all warnings fail. Now + SConscript can take an optional must_exist flag which if true fails + if the script does not exist. Not failing on missing script is + now considered deprecated, and the first instance will print a + deprecation message. It is now also possible to flip the scons + behavior (which still defaults to warn, not fail) by calling + SCons.Script.set_missing_sconscript_error, which is also not a + documented interface at the moment. + - Convert TestCmd.read to use with statement on open (quiets 17 py3 warnings) + - Quiet py3 warning in UtilTests.py + - Fix tests specifying octal constants for py3 + - Fix must_contain tests for py3 + - RPM package generation: + - Fix supplying a build architecture + - Disable auto debug package generation on certain rpmbuild versions + - Adjust some tests to only supply build-id file on certain rpmbuild versions + - Tests now use a file fixture for the repeated (trivial) main.c program. + - Document and comment cleanup. + - Added new Environment Value X_RPM_EXTRADEFS to supply custom settings + to the specfile without adding specific logic for each one to scons. + - The test for Python.h needed by swig tests is moved to get_python_platform + so it does not have to be repeated in every test; picks up one failure + which did not make the (previously needed) check. Windows version + of get_python_platform needed some rework in case running in virtualenv. + - If test opens os.devnull, register with atexit so file opens do not leak. + - Fix bugs in Win32 process spawn logic to handle OSError exception correctly. + - Use time.perf_counter instead of time.clock if it exists. + time.clock deprecated since py3.3, due to remove in 3.8. deprecation + warnings from py3.7 were failing a bunch of tests on Windows since they + mess up expected stderr. + - Prefer Py3's inspect.getfullargspec over deprecated inspect.getargspec. + Switched to "new" (standard in Py2.7) usage of receiving a namedtuple - + we were unpacking to a four-tuple, two of the items of which were unused; + getfullargspec returns a named tuple with seven elements so it is a + cleaner drop-in replacement using the namedtuple. + - Updated the test-framework.rst documentation. + - Remove obsoleted internal implementaiton of OrderedDict. + - Test for tar packaging fixups + - Stop using deprecated unittest asserts + - messages in strip-install-dir test now os-neutral + - Add xz compression format to packaging choices. + - Syntax cleanups - trailing blanks, use "is" to compare with None, etc. + Three uses of variables not defined are changed. + - Some script changes in trying to find scons engine + - Update (pep8) configure-cache script, add a --show option. + - Fix for a couple of "what if tool not found" exceptions in framework. + - Add Textfile/Substfile to default environment. (issue #3147) + - sconsign: a couple of python3 fixes; be more tolerant of implicit + entries which have no signatures; minor PEP8 changes. + - Fix a couple of type mistakes (list-> string, filter type -> list) + - Fix a couple of type mistakes in packaging tools: list-> string in msi, + filter type -> list in ipk + + From Bernhard M. Wiedemann: + - Update SCons' internal scons build logic to allow overriding build date + with SOURCE_DATE_EPOCH for SCons itself. + - Change the datestamps in SCons' docs and embedded in code use ISO 8601 format and UTC + + From Hao Wu + - Typo in customized decider example in user guide + - Replace usage of unittest.TestSuite with unittest.main() (fix #3113) + +RELEASE 3.0.1 - Mon, 12 Nov 2017 15:31:33 -0700 + + From Daniel Moody: + - Jar can take multiple targets, and will make a duplicate jar from the sources for each target + - Added some warnings in case the Jar builder makes an implicit target + - Added Jar method and changed jar build to be more specific. Jar method will take in + directories or classes as source. Added more tests to JAR to ensure the jar was + packaged with the correct compiled class files. + - Added a No result test case to handle bug which seems unrelated to java in the + swig-dependencies.py test, more info here: http://scons.tigris.org/issues/show_bug.cgi?id=2907 + - Added a travis script to test on ubuntu trusty now that the project is on github + so that Continuus Integration tests can be run automatically. It tests most case and considers + no result a pass as well. Improving this script can install more dependincies allowing for more + tests to be run. + + From Daniel Moody: + - Updated the Jar Builder tool in Tool/__init__.py so that is doesn't force class files as + sources, allowing directories to be passed, which was causing test/Java/JAR.py to fail. + + From William Deegan: + - Fix issue where code in utility routine to_String_for_subst() had code whose result was never + properly returned. + (Found by: James Rinkevich https://pairlist4.pair.net/pipermail/scons-users/2017-October/006358.html ) + - Fixed Variables.GenerateHelpText() to now use the sort parameter. Due to incorrect 2to3 fixer changes + 8 years ago it was being used as a boolean parameter. Now you can specify sort to be a callable, or boolean + value. (True = normal sort). Manpage also updated. + - Fixed Tool loading logic from exploding sys.path with many site_scons/site_tools prepended on py3. + - Added additional output with time to process each SConscript file when using --debug=time. + + From Thomas Berg: + - Fixed a regression in scons-3.0.0 where "from __future__ import print_function" was imposed + on the scope where SConstruct is executed, breaking existing builds using PY 2.7. + + From William Deegan: + - Fix broken subst logic where a string with "$$(abc)" was being treated as "$(abc) and the + logic for removing the signature escapes was then failing because there was no closing "$)". + This was introduced by a pull request to allow recursive variable evaluations to yield a string + such as "$( $( some stuff $) $)". + + From Zachary Tessler: + - Fix incorrect warning for repeated identical builder calls that use overrides + + RELEASE 3.0.0 - Mon, 18 Sep 2017 08:32:04 -0700 NOTE: This is a major release. You should expect that some targets may rebuild when upgrading. @@ -77,9 +406,9 @@ will cause rebuilds. - Add support for Visual Studio 2017. This support requires vswhere.exe a helper tool installed with newer installs of 2017. SCons expects it to be located at "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" - It can be downloaded separately at + It can be downloaded separately at https://github.com/Microsoft/vswhere - + From Tom Tanner: - Allow nested $( ... $) sections @@ -6135,7 +6464,3 @@ A brief overview of important functionality available in release 0.01: - Windows installer available. - - -Copyright (c) 2001 - 2017 The SCons Foundation -src/CHANGES.txt rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog diff --git a/src/LICENSE.txt b/src/LICENSE.txt index ff04f2e..6b6cd6c 100644 --- a/src/LICENSE.txt +++ b/src/LICENSE.txt @@ -1,4 +1,4 @@ -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/src/README.txt b/src/README.txt index ffba407..40d7217 100644 --- a/src/README.txt +++ b/src/README.txt @@ -2,7 +2,7 @@ SCons - a software construction tool - Version 3.0.0 + Version 3.0.3 This is SCons, a tool for building software (and other files). SCons is @@ -28,8 +28,7 @@ the latest version by checking the SCons download page at: EXECUTION REQUIREMENTS ====================== -Running SCons requires Python version 2.7.*. Currently it does not -run on the Python 3.x release. There should be +Running SCons requires Python version 2.7.* or 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.) @@ -57,7 +56,7 @@ provided Python-standard setup script as follows: By default, the above command will do the following: - -- Install the version-numbered "scons-3.0.0" and "sconsign-3.0.0" + -- Install the version-numbered "scons-3.0.3" and "sconsign-3.0.3" scripts in the default system script directory (/usr/bin or C:\Python*\Scripts, for example). This can be disabled by specifying the "--no-version-script" option on the command @@ -71,17 +70,17 @@ By default, the above command will do the following: making it the default on your system. On UNIX or Linux systems, you can have the "scons" and "sconsign" - scripts be hard links or symbolic links to the "scons-3.0.0" and - "sconsign-3.0.0" scripts by specifying the "--hardlink-scons" + scripts be hard links or symbolic links to the "scons-3.0.3" and + "sconsign-3.0.3" scripts by specifying the "--hardlink-scons" or "--symlink-scons" options on the command line. - -- Install "scons-3.0.0.bat" and "scons.bat" wrapper scripts in the + -- Install "scons-3.0.3.bat" and "scons.bat" wrapper scripts in the Python prefix directory on Windows (C:\Python*, for example). This can be disabled by specifying the "--no-install-bat" option on the command line. On UNIX or Linux systems, the "--install-bat" option may be - specified to have "scons-3.0.0.bat" and "scons.bat" files + specified to have "scons-3.0.3.bat" and "scons.bat" files installed in the default system script directory, which is useful if you want to install SCons in a shared file system directory that can be used to execute SCons from both UNIX/Linux and @@ -89,7 +88,7 @@ By default, the above command will do the following: -- Install the SCons build engine (a Python module) in an appropriate version-numbered SCons library directory - (/usr/lib/scons-3.0.0 or C:\Python*\scons-3.0.0, for example). + (/usr/lib/scons-3.0.3 or C:\Python*\scons-3.0.3, for example). See below for more options related to installing the build engine library. @@ -146,7 +145,7 @@ of small examples for getting started using SCons. Additional documentation for SCons is available at: - http://www.scons.org/doc.html + https://scons.org/documentation.html LICENSING @@ -247,4 +246,4 @@ many contributors, including but not at all limited to: \... and many others. -Copyright (c) 2001 - 2015 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 82a0c5a..90cc745 100644..100755 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,51 +1,43 @@ - A new SCons checkpoint release, 3.0.0, is now available - on the SCons download page: +A new SCons release, 3.0.5, is now available on the SCons download page: - http://www.scons.org/download.php + https://scons.org/pages/download.html - Here is a summary of the changes since 2.5.1: +Here is a summary of the changes since 3.0.4: - NEW FUNCTIONALITY +CHANGED/ENHANCED EXISTING FUNCTIONALITY - - Initial support for Python 3.5+ - - I + - Change the default for AppendENVPath to delete_existing=0, so path + order will not be changed, unless explicitly set (Issue #3276) + - Add lex construction variable LEXUNISTD for turning off unix headers on windows + - Update lex tool to use win_flex on windows if available + - Add the textfile tool to the default tool list - DEPRECATED FUNCTIONALITY +FIXES - - List anything that's been deprecated since the last release + - Fix Issue #3283 - Handle using --config=force in combination with Decider('MD5-timestamp'). + 3.0.2 in fix for issue #2980 added that deciders can throw DeciderNeedsNode exception. + The Configure logic directly calls the decider when using --config=force but wasn't handling + that exception. This would yield minimally configure tests using TryLink() not running and + leaving TypeError Nonetype exception in config.log + - Fix Issue #3303 - Handle --config=force overwriting the Environment passed into Configure()'s + Decider and not clearing it when the configure context is completed. + - Add default paths for yacc tool on windows to include cygwin, mingw, and chocolatey + - Fix issue #2799 - Fix mingw tool to respect SHCCCOMSTR, SHLINKCOMSTR and LDMODULECOMSTR + - Fix Issue #3329 - Add support for MS SDK V10.0A (which is commonly installed with VS2017) + - Fix Issue #3333 - Add support for finding vswhere under 32 bit windows installs. + - Update the MSVC tool to include the nologo flag by default in RCFLAGS + - Fixed bug which threw error when running SCons on windows system with no MSVC installed. - CHANGED/ENHANCED EXISTING FUNCTIONALITY - - List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug +IMPROVEMENTS + - Do not store build host+user name if reproducible builds are wanted - FIXES - - List fixes of outright bugs - - IMPROVEMENTS - - - List improvements that wouldn't be visible to the user in the - documentation: performance improvements (describe the circumstances - under which they would be observed), or major code cleanups - - PACKAGING - - - List changes in the way SCons is packaged and/or released - - DOCUMENTATION - - - List any significant changes to the documentation (not individual - typo fixes, even if they're mentioned in src/CHANGES.txt to give - the contributor credit) - - DEVELOPMENT - - - List visible changes in the way SCons is developed - - Thanks to CURLY, LARRY, and MOE for their contributions to this release. - Contributors are listed alphabetically by their last name. - -Copyright (c) 2001 - 2017 The SCons Foundation -src/RELEASE.txt rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog +git shortlog --no-merges -ns 3.0.4..HEAD + 34 William Deegan + 33 Mats Wichmann + 18 Daniel + 4 Daniel Moody + 3 Bernhard M. Wiedemann + 2 Maciej Kumorek diff --git a/src/engine/MANIFEST-xml.in b/src/engine/MANIFEST-xml.in deleted file mode 100644 index cfbfd3a..0000000 --- a/src/engine/MANIFEST-xml.in +++ /dev/null @@ -1,8 +0,0 @@ -SCons/*.xml -SCons/Platform/*.xml -SCons/Scanner/__init__.xml -SCons/Script/*.xml -SCons/Tool/*.xml -SCons/Tool/docbook/__init__.xml -SCons/Tool/docbook/utils/xmldepend.xsl -SCons/Tool/packaging/__init__.xml diff --git a/src/engine/MANIFEST.in b/src/engine/MANIFEST.in index 2df278e..39aba6c 100644 --- a/src/engine/MANIFEST.in +++ b/src/engine/MANIFEST.in @@ -18,7 +18,6 @@ SCons/Node/__init__.py SCons/Node/Alias.py SCons/Node/FS.py SCons/Node/Python.py -SCons/Options/*.py SCons/PathList.py SCons/Platform/__init__.py SCons/Platform/aix.py @@ -27,9 +26,11 @@ SCons/Platform/darwin.py SCons/Platform/hpux.py SCons/Platform/irix.py SCons/Platform/os2.py +SCons/Platform/mingw.py SCons/Platform/posix.py SCons/Platform/sunos.py SCons/Platform/win32.py +SCons/Platform/virtualenv.py SCons/Scanner/__init__.py SCons/Scanner/C.py SCons/Scanner/D.py @@ -64,6 +65,7 @@ SCons/Tool/c++.py SCons/Tool/cxx.py SCons/Tool/cc.py SCons/Tool/cyglink.py +SCons/Tool/clangCommon/__init__.py SCons/Tool/clang.py SCons/Tool/clangxx.py SCons/Tool/cvf.py @@ -177,3 +179,5 @@ SCons/Tool/msgfmt.py SCons/Tool/msginit.py SCons/Tool/msgmerge.py SCons/Tool/xgettext.py +#SCons/Tool/docbook/docbook-xsl-1.76.1/** +#SCons/Tool/docbook/utils/** diff --git a/src/engine/SCons/Action.py b/src/engine/SCons/Action.py index 97040a4..f1ca2cf 100644 --- a/src/engine/SCons/Action.py +++ b/src/engine/SCons/Action.py @@ -77,7 +77,7 @@ way for wrapping up the functions. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -98,7 +98,7 @@ way for wrapping up the functions. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Action.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Action.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import pickle @@ -107,6 +107,7 @@ import sys import subprocess import itertools import inspect +from collections import OrderedDict import SCons.Debug from SCons.Debug import logInstanceCreation @@ -115,8 +116,7 @@ import SCons.Util import SCons.Subst # we use these a lot, so try to optimize them -is_String = SCons.Util.is_String -is_List = SCons.Util.is_List +from SCons.Util import is_String, is_List class _null(object): pass @@ -258,8 +258,7 @@ def _code_contents(code, docstring=None): # function. Note that we have to call _object_contents on each # constants because the code object of nested functions can # show-up among the constants. - - z = [_object_contents(cc) for cc in code.co_consts[1:]] + z = [_object_contents(cc) for cc in code.co_consts if cc != docstring] contents.extend(b',(') contents.extend(bytearray(',', 'utf-8').join(z)) contents.extend(b')') @@ -803,7 +802,7 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw): kw['env'] = new_env try: - return subprocess.Popen(cmd, **kw) + pobj = subprocess.Popen(cmd, **kw) except EnvironmentError as e: if error == 'raise': raise # return a dummy Popen instance that only returns error @@ -817,7 +816,13 @@ def _subproc(scons_env, cmd, error = 'ignore', **kw): def readline(self): return '' def __iter__(self): return iter(()) stdout = stderr = f() - return dummyPopen(e) + pobj = dummyPopen(e) + finally: + # clean up open file handles stored in parent's kw + for k, v in kw.items(): + if hasattr(v, 'close'): + v.close() + return pobj class CommandAction(_ActionAction): @@ -837,8 +842,8 @@ class CommandAction(_ActionAction): _ActionAction.__init__(self, **kw) if is_List(cmd): if [c for c in cmd if is_List(c)]: - raise TypeError("CommandAction should be given only " \ - "a single command") + raise TypeError("CommandAction should be given only " + "a single command") self.cmd_list = cmd def __str__(self): @@ -1289,7 +1294,7 @@ class ListAction(ActionBase): return result def get_varlist(self, target, source, env, executor=None): - result = SCons.Util.OrderedDict() + result = OrderedDict() for act in self.list: for var in act.get_varlist(target, source, env, executor): result[var] = True diff --git a/src/engine/SCons/Action.xml b/src/engine/SCons/Action.xml index 99f4e86..9cb186c 100644 --- a/src/engine/SCons/Action.xml +++ b/src/engine/SCons/Action.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/ActionTests.py b/src/engine/SCons/ActionTests.py index ed2412b..1b11eea 100644 --- a/src/engine/SCons/ActionTests.py +++ b/src/engine/SCons/ActionTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,8 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/ActionTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/ActionTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" + # Define a null function and a null class for use as builder actions. # Where these are defined in the file seems to affect their byte-code @@ -30,10 +31,12 @@ __revision__ = "src/engine/SCons/ActionTests.py rel_3.0.0:4395:8972f6a2f699 2017 def GlobalFunc(): pass + class GlobalActFunc(object): def __call__(self): pass + import collections import io import os @@ -47,7 +50,6 @@ import SCons.Environment import SCons.Errors import TestCmd -import TestUnit # Initial setup of the common environment for all tests, # a temporary working directory containing a @@ -56,29 +58,32 @@ import TestUnit # We don't do this as a setUp() method because it's # unnecessary to create a separate directory and script # for each test, they can just use the one. -test = TestCmd.TestCmd(workdir = '') +test = TestCmd.TestCmd(workdir='') test.write('act.py', """\ import os, string, sys -f = open(sys.argv[1], 'w') -f.write("act.py: '" + "' '".join(sys.argv[2:]) + "'\\n") -try: - if sys.argv[3]: - f.write("act.py: '" + os.environ[sys.argv[3]] + "'\\n") -except: - pass -f.close() + +with open(sys.argv[1], 'w') as f: + f.write("act.py: '" + "' '".join(sys.argv[2:]) + "'\\n") + try: + if sys.argv[3]: + f.write("act.py: '" + os.environ[sys.argv[3]] + "'\\n") + except: + pass + if 'ACTPY_PIPE' in os.environ: if 'PIPE_STDOUT_FILE' in os.environ: - stdout_msg = open(os.environ['PIPE_STDOUT_FILE'], 'r').read() + with open(os.environ['PIPE_STDOUT_FILE'], 'r') as f: + stdout_msg = f.read() else: stdout_msg = "act.py: stdout: executed act.py %s\\n" % ' '.join(sys.argv[1:]) sys.stdout.write( stdout_msg ) if 'PIPE_STDERR_FILE' in os.environ: - stderr_msg = open(os.environ['PIPE_STDERR_FILE'], 'r').read() + with open(os.environ['PIPE_STDERR_FILE'], 'r') as f: + stderr_msg = f.read() else: stderr_msg = "act.py: stderr: executed act.py %s\\n" % ' '.join(sys.argv[1:]) - sys.stderr.write( stderr_msg ) + sys.stderr.write(stderr_msg) sys.exit(0) """) @@ -100,6 +105,7 @@ scons_env = SCons.Environment.Environment() # so it doesn't clutter the output. sys.stdout = io.StringIO() + class CmdStringHolder(object): def __init__(self, cmd, literal=None): self.data = str(cmd) @@ -125,6 +131,7 @@ class CmdStringHolder(object): else: return self.data + class Environment(object): def __init__(self, **kw): self.d = {} @@ -134,53 +141,70 @@ class Environment(object): self.d['ESCAPE'] = scons_env['ESCAPE'] for k, v in kw.items(): self.d[k] = v + # Just use the underlying scons_subst*() utility methods. def subst(self, strSubst, raw=0, target=[], source=[], conv=None): return SCons.Subst.scons_subst(strSubst, self, raw, target, source, self.d, conv=conv) + subst_target_source = subst + def subst_list(self, strSubst, raw=0, target=[], source=[], conv=None): return SCons.Subst.scons_subst_list(strSubst, self, raw, - target, source, self.d, conv=conv) + target, source, self.d, conv=conv) + def __getitem__(self, item): return self.d[item] + def __setitem__(self, item, value): self.d[item] = value + def has_key(self, item): return item in self.d + def get(self, key, value=None): return self.d.get(key, value) + def items(self): return list(self.d.items()) + def Dictionary(self): return self.d + def Clone(self, **kw): res = Environment() res.d = SCons.Util.semi_deepcopy(self.d) for k, v in kw.items(): res.d[k] = v return res + def sig_dict(self): d = {} - for k,v in self.items(): d[k] = v + for k, v in self.items(): d[k] = v d['TARGETS'] = ['__t1__', '__t2__', '__t3__', '__t4__', '__t5__', '__t6__'] d['TARGET'] = d['TARGETS'][0] d['SOURCES'] = ['__s1__', '__s2__', '__s3__', '__s4__', '__s5__', '__s6__'] d['SOURCE'] = d['SOURCES'][0] return d + class DummyNode(object): def __init__(self, name): self.name = name + def str_for_display(self): return '"' + self.name + '"' + def __str__(self): return self.name + def rfile(self): return self + def get_subst_proxy(self): return self + if os.name == 'java': python = os.path.join(sys.prefix, 'jython') else: @@ -189,6 +213,7 @@ _python_ = test.escape(python) _null = SCons.Action._null + def test_varlist(pos_call, str_call, cmd, cmdstrfunc, **kw): def call_action(a, pos_call=pos_call, str_call=str_call, kw=kw): a = SCons.Action.Action(*a, **kw) @@ -226,6 +251,7 @@ def test_varlist(pos_call, str_call, cmd, cmdstrfunc, **kw): a = call_action((cmd, cmdstrfunc, 'a', 'b', 'c')) assert a.varlist == ('a', 'b', 'c', 'x', 'y', 'z'), a.varlist + def test_positional_args(pos_callback, cmd, **kw): """Test that Action() returns the expected type and that positional args work. """ @@ -235,7 +261,9 @@ def test_positional_args(pos_callback, cmd, **kw): if not isinstance(act, SCons.Action._ActionAction): # only valid cmdstrfunc is None - def none(a): pass + def none(a): + pass + test_varlist(pos_callback, none, cmd, None, **kw) else: # _ActionAction should have set these @@ -244,22 +272,27 @@ def test_positional_args(pos_callback, cmd, **kw): assert act.presub is _null, act.presub assert act.chdir is None, act.chdir assert act.exitstatfunc is SCons.Action.default_exitstatfunc, \ - act.exitstatfunc + act.exitstatfunc def cmdstr(a): assert hasattr(a, 'strfunction') assert a.cmdstr == 'cmdstr', a.cmdstr + test_varlist(pos_callback, cmdstr, cmd, 'cmdstr', **kw) - def fun(): pass + def fun(): + pass + def strfun(a, fun=fun): assert a.strfunction is fun, a.strfunction assert a.cmdstr == _null, a.cmdstr + test_varlist(pos_callback, strfun, cmd, fun, **kw) def none(a): assert hasattr(a, 'strfunction') assert a.cmdstr is None, a.cmdstr + test_varlist(pos_callback, none, cmd, None, **kw) """Test handling of bad cmdstrfunc arguments """ @@ -274,18 +307,21 @@ def test_positional_args(pos_callback, cmd, **kw): return act + class ActionTestCase(unittest.TestCase): """Test the Action() factory function""" def test_FunctionAction(self): """Test the Action() factory's creation of FunctionAction objects """ + def foo(): pass def func_action(a, foo=foo): assert isinstance(a, SCons.Action.FunctionAction), a assert a.execfunction == foo, a.execfunction + test_positional_args(func_action, foo) # a singleton list returns the contained action test_positional_args(func_action, [foo]) @@ -293,28 +329,33 @@ class ActionTestCase(unittest.TestCase): def test_CommandAction(self): """Test the Action() factory's creation of CommandAction objects """ + def cmd_action(a): assert isinstance(a, SCons.Action.CommandAction), a assert a.cmd_list == "string", a.cmd_list + test_positional_args(cmd_action, "string") # a singleton list returns the contained action test_positional_args(cmd_action, ["string"]) - try: unicode - except NameError: pass + 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 - test_positional_args(line_action, [[ "explicit", "command", "line" ]]) + assert a.cmd_list == ["explicit", "command", "line"], a.cmd_list + + test_positional_args(line_action, [["explicit", "command", "line"]]) def test_ListAction(self): """Test the Action() factory's creation of ListAction objects """ - a1 = SCons.Action.Action(["x", "y", "z", [ "a", "b", "c"]]) + a1 = SCons.Action.Action(["x", "y", "z", ["a", "b", "c"]]) assert isinstance(a1, SCons.Action.ListAction), a1 assert a1.varlist == (), a1.varlist assert isinstance(a1.list[0], SCons.Action.CommandAction), a1.list[0] @@ -324,7 +365,7 @@ class ActionTestCase(unittest.TestCase): assert isinstance(a1.list[2], SCons.Action.CommandAction), a1.list[2] assert a1.list[2].cmd_list == "z", a1.list[2].cmd_list assert isinstance(a1.list[3], SCons.Action.CommandAction), a1.list[3] - assert a1.list[3].cmd_list == [ "a", "b", "c" ], a1.list[3].cmd_list + assert a1.list[3].cmd_list == ["a", "b", "c"], a1.list[3].cmd_list a2 = SCons.Action.Action("x\ny\nz") assert isinstance(a2, SCons.Action.ListAction), a2 @@ -372,20 +413,24 @@ class ActionTestCase(unittest.TestCase): def test_CommandGeneratorAction(self): """Test the Action() factory's creation of CommandGeneratorAction objects """ + def foo(): pass def gen_action(a, foo=foo): assert isinstance(a, SCons.Action.CommandGeneratorAction), a assert a.generator is foo, a.generator + test_positional_args(gen_action, foo, generator=1) def test_LazyCmdGeneratorAction(self): """Test the Action() factory's creation of lazy CommandGeneratorAction objects """ + def lazy_action(a): assert isinstance(a, SCons.Action.LazyAction), a assert a.var == "FOO", a.var assert a.cmd_list == "${FOO}", a.cmd_list + test_positional_args(lazy_action, "$FOO") test_positional_args(lazy_action, "${FOO}") @@ -406,6 +451,7 @@ class ActionTestCase(unittest.TestCase): a2 = SCons.Action.Action(a1) assert a2 is a1, a2 + class _ActionActionTestCase(unittest.TestCase): def test__init__(self): @@ -429,7 +475,7 @@ class _ActionActionTestCase(unittest.TestCase): assert a.chdir is None, a.chdir assert a.exitstatfunc is SCons.Action.default_exitstatfunc, a.exitstatfunc - assert SCons.Action._ActionAction(kwarg = 1) + assert SCons.Action._ActionAction(kwarg=1) assert not hasattr(a, 'kwarg') assert not hasattr(a, 'strfunction') assert a.cmdstr is _null, a.cmdstr @@ -447,13 +493,13 @@ class _ActionActionTestCase(unittest.TestCase): a = SCons.Action._ActionAction(cmdstr='cmdstr') assert not hasattr(a, 'strfunction') - assert a.cmdstr is 'cmdstr', a.cmdstr + assert a.cmdstr == 'cmdstr', a.cmdstr a = SCons.Action._ActionAction(cmdstr=None) assert not hasattr(a, 'strfunction') assert a.cmdstr is None, a.cmdstr - t = ('a','b','c') + t = ('a', 'b', 'c') a = SCons.Action._ActionAction(varlist=t) assert a.varlist == t, a.varlist @@ -461,22 +507,22 @@ class _ActionActionTestCase(unittest.TestCase): assert a.presub is func1, a.presub a = SCons.Action._ActionAction(chdir=1) - assert a.chdir is 1, a.chdir + assert a.chdir == 1, a.chdir a = SCons.Action._ActionAction(exitstatfunc=func1) assert a.exitstatfunc is func1, a.exitstatfunc a = SCons.Action._ActionAction( - # alphabetical order ... - chdir='x', - cmdstr='cmdstr', - exitstatfunc=func3, - presub=func2, - strfunction=func1, - varlist=t, - ) - assert a.chdir is 'x', a.chdir - assert a.cmdstr is 'cmdstr', a.cmdstr + # alphabetical order ... + chdir='x', + cmdstr='cmdstr', + exitstatfunc=func3, + presub=func2, + strfunction=func1, + varlist=t, + ) + assert a.chdir == 'x', a.chdir + assert a.cmdstr == 'cmdstr', a.cmdstr assert a.exitstatfunc is func3, a.exitstatfunc assert a.presub is func2, a.presub assert a.strfunction is func1, a.strfunction @@ -485,7 +531,10 @@ class _ActionActionTestCase(unittest.TestCase): def test_dup_keywords(self): """Test handling of both cmdstr and strfunction arguments """ - def func(): pass + + def func(): + pass + try: a = SCons.Action.Action('foo', cmdstr='string', strfunction=func) except SCons.Errors.UserError as e: @@ -513,6 +562,7 @@ class _ActionActionTestCase(unittest.TestCase): try: def execfunc(target, source, env): pass + a = SCons.Action.Action(execfunc) sio = io.StringIO() @@ -532,9 +582,9 @@ class _ActionActionTestCase(unittest.TestCase): save_print_actions = SCons.Action.print_actions save_print_actions_presub = SCons.Action.print_actions_presub save_execute_actions = SCons.Action.execute_actions - #SCons.Action.print_actions = 0 + # SCons.Action.print_actions = 0 - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') test.subdir('sub', 'xyz') os.chdir(test.workpath()) @@ -545,16 +595,19 @@ class _ActionActionTestCase(unittest.TestCase): assert isinstance(target, list), type(target) assert isinstance(source, list), type(source) return 7 + a = SCons.Action.Action(execfunc) def firstfunc(target, source, env): assert isinstance(target, list), type(target) assert isinstance(source, list), type(source) return 0 + def lastfunc(target, source, env): assert isinstance(target, list), type(target) assert isinstance(source, list), type(source) return 9 + b = SCons.Action.Action([firstfunc, execfunc, lastfunc]) sio = io.StringIO() @@ -694,8 +747,10 @@ class _ActionActionTestCase(unittest.TestCase): SCons.Action.execute_actions = 1 result = [] + def my_print_cmd_line(s, target, source, env, result=result): result.append(s) + env['PRINT_CMD_LINE_FUNC'] = my_print_cmd_line a("output", "input", env) assert result == ["execfunc(['output'], ['input'])"], result @@ -721,39 +776,43 @@ class _ActionActionTestCase(unittest.TestCase): def func(): pass + a = SCons.Action.Action(func) s = a.presub_lines(env) assert s == ["func(target, source, env)"], s def gen(target, source, env, for_signature): return 'generat' + env.get('GEN', 'or') + a = SCons.Action.Action(gen, generator=1) s = a.presub_lines(env) assert s == ["generator"], s - s = a.presub_lines(Environment(GEN = 'ed')) + s = a.presub_lines(Environment(GEN='ed')) assert s == ["generated"], s a = SCons.Action.Action("$ACT") s = a.presub_lines(env) assert s == [''], s - s = a.presub_lines(Environment(ACT = 'expanded action')) + s = a.presub_lines(Environment(ACT='expanded action')) assert s == ['expanded action'], s def test_add(self): """Test adding Actions to stuff.""" + # Adding actions to other Actions or to stuff that can # be converted into an Action should produce a ListAction # containing all the Actions. def bar(): return None + baz = SCons.Action.Action(bar, generator=1) act1 = SCons.Action.Action('foo bar') - act2 = SCons.Action.Action([ 'foo', bar ]) + act2 = SCons.Action.Action(['foo', bar]) sum = act1 + act2 assert isinstance(sum, SCons.Action.ListAction), str(sum) assert len(sum.list) == 3, len(sum.list) - assert [isinstance(x, SCons.Action.ActionBase) for x in sum.list] == [ 1, 1, 1 ] + assert [isinstance(x, SCons.Action.ActionBase) for x in sum.list] == [1, 1, 1] sum = act1 + act1 assert isinstance(sum, SCons.Action.ListAction), str(sum) @@ -789,13 +848,13 @@ class _ActionActionTestCase(unittest.TestCase): assert len(sum.list) == 3, len(sum.list) assert isinstance(sum.list[0], SCons.Action.CommandAction) - sum = [ 'foo', 'bar' ] + act1 + sum = ['foo', 'bar'] + act1 assert isinstance(sum, SCons.Action.ListAction), str(sum) assert len(sum.list) == 3, sum.list assert isinstance(sum.list[0], SCons.Action.CommandAction) assert isinstance(sum.list[1], SCons.Action.CommandAction) - sum = act2 + [ baz, bar ] + sum = act2 + [baz, bar] assert isinstance(sum, SCons.Action.ListAction), str(sum) assert len(sum.list) == 4, len(sum.list) assert isinstance(sum.list[2], SCons.Action.CommandGeneratorAction) @@ -822,17 +881,18 @@ class _ActionActionTestCase(unittest.TestCase): else: assert 0, "Should have thrown a TypeError adding to an int." + class CommandActionTestCase(unittest.TestCase): def test___init__(self): """Test creation of a command Action """ a = SCons.Action.CommandAction(["xyzzy"]) - assert a.cmd_list == [ "xyzzy" ], a.cmd_list + assert a.cmd_list == ["xyzzy"], a.cmd_list assert a.cmdstr is _null, a.cmdstr a = SCons.Action.CommandAction(["abra"], cmdstr="cadabra") - assert a.cmd_list == [ "abra" ], a.cmd_list + assert a.cmd_list == ["abra"], a.cmd_list assert a.cmdstr == "cadabra", a.cmdstr def test___str__(self): @@ -952,6 +1012,7 @@ class CommandActionTestCase(unittest.TestCase): def sf(target, source, env): return "sf was called" + act = SCons.Action.CommandAction('foo', strfunction=sf) s = act.strfunction([], [], env) assert s == "sf was called", s @@ -959,26 +1020,35 @@ class CommandActionTestCase(unittest.TestCase): class actclass1(object): def __init__(self, targets, sources, env): pass + def __call__(self): return 1 + class actclass2(object): def __init__(self, targets, sources, env): self.strfunction = 5 + def __call__(self): return 2 + class actclass3(object): def __init__(self, targets, sources, env): pass + def __call__(self): return 3 + def strfunction(self, targets, sources, env): - return 'actclass3 on %s to get %s'%(str(sources[0]), - str(targets[0])) + return 'actclass3 on %s to get %s' % (str(sources[0]), + str(targets[0])) + class actclass4(object): def __init__(self, targets, sources, env): pass + def __call__(self): return 4 + strfunction = None act1 = SCons.Action.Action(actclass1([t1], [s1], env)) @@ -1075,7 +1145,7 @@ class CommandActionTestCase(unittest.TestCase): act = SCons.Action.CommandAction(cmd4) sources = [DummyNode('three'), DummyNode('four'), DummyNode('five')] env2 = env.Clone() - r = act([], source = sources, env = env2) + r = act([], source=sources, env=env2) assert r == 0 c = test.read(outfile, 'r') assert c == "act.py: 'three' 'four'\n", c @@ -1092,13 +1162,13 @@ class CommandActionTestCase(unittest.TestCase): PATH = '' env5['ENV']['XYZZY'] = 'xyzzy' - r = act(target = DummyNode('out5'), source = [], env = env5) + r = act(target=DummyNode('out5'), source=[], env=env5) act = SCons.Action.CommandAction(cmd5) - r = act(target = DummyNode('out5'), - source = [], - env = env.Clone(ENV = {'XYZZY' : 'xyzzy5', - 'PATH' : PATH})) + r = act(target=DummyNode('out5'), + source=[], + env=env.Clone(ENV={'XYZZY': 'xyzzy5', + 'PATH': PATH})) assert r == 0 c = test.read(outfile, 'r') assert c == "act.py: 'out5' 'XYZZY'\nact.py: 'xyzzy5'\n", c @@ -1106,19 +1176,22 @@ class CommandActionTestCase(unittest.TestCase): class Obj(object): def __init__(self, str): self._str = str + def __str__(self): return self._str + def rfile(self): return self + def get_subst_proxy(self): return self cmd6 = r'%s %s %s ${TARGETS[1]} $TARGET ${SOURCES[:2]}' % (_python_, act_py, outfile) act = SCons.Action.CommandAction(cmd6) - r = act(target = [Obj('111'), Obj('222')], - source = [Obj('333'), Obj('444'), Obj('555')], - env = env.Clone()) + r = act(target=[Obj('111'), Obj('222')], + source=[Obj('333'), Obj('444'), Obj('555')], + env=env.Clone()) assert r == 0 c = test.read(outfile, 'r') assert c == "act.py: '222' '111' '333' '444'\n", c @@ -1133,7 +1206,7 @@ class CommandActionTestCase(unittest.TestCase): expect_nonexistent = 127 # Newer cygwin seems to return 126 for following expect_nonexecutable_file = 126 - expect_nonexecutable_dir = 127 + expect_nonexecutable_dir = 127 elif sys.platform.find('sunos') != -1: expect_nonexistent = 1 expect_nonexecutable_file = 1 @@ -1141,22 +1214,22 @@ class CommandActionTestCase(unittest.TestCase): else: expect_nonexistent = 127 expect_nonexecutable_file = 126 - expect_nonexecutable_dir = 126 + expect_nonexecutable_dir = 126 # Test that a nonexistent command returns 127 act = SCons.Action.CommandAction(python + "_no_such_command_") - r = act([], [], env.Clone(out = outfile)) + r = act([], [], env.Clone(out=outfile)) assert r.status == expect_nonexistent, r.status # Test that trying to execute a directory returns 126 dir, tail = os.path.split(python) act = SCons.Action.CommandAction(dir) - r = act([], [], env.Clone(out = outfile)) + r = act([], [], env.Clone(out=outfile)) assert r.status == expect_nonexecutable_file, r.status # Test that trying to execute a non-executable file returns 126 act = SCons.Action.CommandAction(outfile) - r = act([], [], env.Clone(out = outfile)) + r = act([], [], env.Clone(out=outfile)) assert r.status == expect_nonexecutable_dir, r.status act = SCons.Action.CommandAction('%s %s 1' % (_python_, exit_py)) @@ -1190,51 +1263,59 @@ class CommandActionTestCase(unittest.TestCase): def test_set_handler(self): """Test setting the command handler... """ + class Test(object): def __init__(self): self.executed = 0 - t=Test() + + t = Test() + def func(sh, escape, cmd, args, env, test=t): test.executed = args test.shell = sh return 0 + def escape_func(cmd): return '**' + cmd + '**' class LiteralStr(object): def __init__(self, x): self.data = x + def __str__(self): return self.data + def escape(self, escape_func): return escape_func(self.data) + def is_literal(self): return 1 a = SCons.Action.CommandAction(["xyzzy"]) - e = Environment(SPAWN = func) + e = Environment(SPAWN=func) a([], [], e) - assert t.executed == [ 'xyzzy' ], t.executed + assert t.executed == ['xyzzy'], t.executed a = SCons.Action.CommandAction(["xyzzy"]) - e = Environment(SPAWN = '$FUNC', FUNC = func) + e = Environment(SPAWN='$FUNC', FUNC=func) a([], [], e) - assert t.executed == [ 'xyzzy' ], t.executed + assert t.executed == ['xyzzy'], t.executed a = SCons.Action.CommandAction(["xyzzy"]) - e = Environment(SPAWN = func, SHELL = 'fake shell') + e = Environment(SPAWN=func, SHELL='fake shell') a([], [], e) - assert t.executed == [ 'xyzzy' ], t.executed + assert t.executed == ['xyzzy'], t.executed assert t.shell == 'fake shell', t.shell - a = SCons.Action.CommandAction([ LiteralStr("xyzzy") ]) - e = Environment(SPAWN = func, ESCAPE = escape_func) + a = SCons.Action.CommandAction([LiteralStr("xyzzy")]) + e = Environment(SPAWN=func, ESCAPE=escape_func) a([], [], e) - assert t.executed == [ '**xyzzy**' ], t.executed + assert t.executed == ['**xyzzy**'], t.executed def test_get_contents(self): """Test fetching the contents of a command Action """ + def CmdGen(target, source, env, for_signature): assert for_signature return "%s %s" % \ @@ -1242,10 +1323,10 @@ class CommandActionTestCase(unittest.TestCase): # The number 1 is there to make sure all args get converted to strings. a = SCons.Action.CommandAction(["|", "$(", "$foo", "|", "$(", "$bar", - "$)", "stuff", "$)", "|", "$baz", 1]) + "$)", "stuff", "$)", "|", "$baz", 1]) c = a.get_contents(target=[], source=[], - env=Environment(foo = 'FFF', bar = 'BBB', - baz = CmdGen)) + env=Environment(foo='FFF', bar='BBB', + baz=CmdGen)) assert c == b"| | FFF BBB 1", c # Make sure that CommandActions use an Environment's @@ -1254,9 +1335,9 @@ class CommandActionTestCase(unittest.TestCase): def subst_target_source(self, strSubst, raw=0, target=[], source=[]): return 'subst_target_source: ' + strSubst - c = a.get_contents(target=DummyNode('ttt'), source = DummyNode('sss'), - env=SpecialEnvironment(foo = 'GGG', bar = 'CCC', - baz = 'ZZZ')) + c = a.get_contents(target=DummyNode('ttt'), source=DummyNode('sss'), + env=SpecialEnvironment(foo='GGG', bar='CCC', + baz='ZZZ')) assert c == b'subst_target_source: | $( $foo | $( $bar $) stuff $) | $baz 1', c # We've discussed using the real target and source names in a @@ -1304,6 +1385,7 @@ class CommandActionTestCase(unittest.TestCase): c = a.get_contents(target=t, source=s, env=env) assert c == b"s4 s5", c + class CommandGeneratorActionTestCase(unittest.TestCase): def factory(self, act, **kw): @@ -1313,16 +1395,18 @@ class CommandGeneratorActionTestCase(unittest.TestCase): def test___init__(self): """Test creation of a command generator Action """ + def f(target, source, env): pass + a = self.factory(f) assert a.generator == f def test___str__(self): """Test the pre-substitution strings for command generator Actions """ - def f(target, source, env, for_signature, self=self): + def f(target, source, env, for_signature, self=self): # See if "env" is really a construction environment (or # looks like one) by accessing the FindIxes attribute. # (The Tool/mingw.py module has a generator that uses this, @@ -1331,6 +1415,7 @@ class CommandGeneratorActionTestCase(unittest.TestCase): env.FindIxes return "FOO" + a = self.factory(f) s = str(a) assert s == 'FOO', s @@ -1338,10 +1423,12 @@ class CommandGeneratorActionTestCase(unittest.TestCase): def test_genstring(self): """Test the command generator Action genstring() method """ + def f(target, source, env, for_signature, self=self): dummy = env['dummy'] self.dummy = dummy return "$FOO $TARGET $SOURCE $TARGETS $SOURCES" + a = self.factory(f) self.dummy = 0 s = a.genstring([], [], env=Environment(FOO='xyzzy', dummy=1)) @@ -1358,13 +1445,16 @@ class CommandGeneratorActionTestCase(unittest.TestCase): s = env.subst("$FOO") assert s == 'foo baz\nbar ack', s return "$FOO" + def func_action(target, source, env, self=self): - dummy=env['dummy'] + dummy = env['dummy'] s = env.subst('$foo') assert s == 'bar', s - self.dummy=dummy + self.dummy = dummy + def f2(target, source, env, for_signature, f=func_action): return f + def ch(sh, escape, cmd, args, env, self=self): self.cmd.append(cmd) self.args.append(args) @@ -1373,30 +1463,34 @@ class CommandGeneratorActionTestCase(unittest.TestCase): self.dummy = 0 self.cmd = [] self.args = [] - a([], [], env=Environment(FOO = 'foo baz\nbar ack', - dummy = 1, - SPAWN = ch)) + a([], [], env=Environment(FOO='foo baz\nbar ack', + dummy=1, + SPAWN=ch)) assert self.dummy == 1, self.dummy assert self.cmd == ['foo', 'bar'], self.cmd - assert self.args == [[ 'foo', 'baz' ], [ 'bar', 'ack' ]], self.args + assert self.args == [['foo', 'baz'], ['bar', 'ack']], self.args b = self.factory(f2) self.dummy = 0 - b(target=[], source=[], env=Environment(foo = 'bar', - dummy = 2 )) - assert self.dummy==2, self.dummy + b(target=[], source=[], env=Environment(foo='bar', + dummy=2)) + assert self.dummy == 2, self.dummy del self.dummy class DummyFile(object): def __init__(self, t): self.t = t + def rfile(self): self.t.rfile_called = 1 return self + def get_subst_proxy(self): return self + def f3(target, source, env, for_signature): return '' + c = self.factory(f3) c(target=[], source=DummyFile(self), env=Environment()) assert self.rfile_called @@ -1404,19 +1498,20 @@ class CommandGeneratorActionTestCase(unittest.TestCase): def test_get_contents(self): """Test fetching the contents of a command generator Action """ + def f(target, source, env, for_signature): foo = env['foo'] bar = env['bar'] assert for_signature, for_signature return [["guux", foo, "$(", "$ignore", "$)", bar, - '${test("$( foo $bar $)")}' ]] + '${test("$( foo $bar $)")}']] def test(mystr): assert mystr == "$( foo $bar $)", mystr return "test" - env = Environment(foo = 'FFF', bar = 'BBB', - ignore = 'foo', test=test) + env = Environment(foo='FFF', bar='BBB', + ignore='foo', test=test) a = self.factory(f) c = a.get_contents(target=[], source=[], env=env) assert c == b"guux FFF BBB test", c @@ -1430,9 +1525,10 @@ class CommandGeneratorActionTestCase(unittest.TestCase): # Since the python bytecode has per version differences, we need different expected results per version func_matches = { - (2,7) : bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), - (3,5) : bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), - (3,6) : bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + (2, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), + (3, 5): bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), + (3, 6): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + (3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), } meth_matches = [ @@ -1446,15 +1542,17 @@ class CommandGeneratorActionTestCase(unittest.TestCase): def f_local(target, source, env, for_signature): return SCons.Action.Action(LocalFunc) - env = Environment(XYZ = 'foo') + env = Environment(XYZ='foo') a = self.factory(f_global) c = a.get_contents(target=[], source=[], env=env) - assert c == func_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected \n"+repr(func_matches[sys.version_info[:2]]) + assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + repr( + func_matches[sys.version_info[:2]]) a = self.factory(f_local) c = a.get_contents(target=[], source=[], env=env) - assert c == func_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected \n"+repr(func_matches[sys.version_info[:2]]) + assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + repr( + func_matches[sys.version_info[:2]]) def f_global(target, source, env, for_signature): return SCons.Action.Action(GlobalFunc, varlist=['XYZ']) @@ -1478,12 +1576,16 @@ class FunctionActionTestCase(unittest.TestCase): def test___init__(self): """Test creation of a function Action """ + def func1(): pass + def func2(): pass + def func3(): pass + def func4(): pass @@ -1491,15 +1593,17 @@ class FunctionActionTestCase(unittest.TestCase): assert a.execfunction == func1, a.execfunction assert isinstance(a.strfunction, types.MethodType), type(a.strfunction) - a = SCons.Action.FunctionAction(func2, { 'strfunction' : func3 }) + a = SCons.Action.FunctionAction(func2, {'strfunction': func3}) assert a.execfunction == func2, a.execfunction assert a.strfunction == func3, a.strfunction def test___str__(self): """Test the __str__() method for function Actions """ + def func1(): pass + a = SCons.Action.FunctionAction(func1, {}) s = str(a) assert s == "func1(target, source, env)", s @@ -1507,6 +1611,7 @@ class FunctionActionTestCase(unittest.TestCase): class class1(object): def __call__(self): pass + a = SCons.Action.FunctionAction(class1(), {}) s = str(a) assert s == "class1(target, source, env)", s @@ -1515,22 +1620,25 @@ class FunctionActionTestCase(unittest.TestCase): """Test executing a function Action """ self.inc = 0 + def f(target, source, env): s = env['s'] s.inc = s.inc + 1 s.target = target - s.source=source + s.source = source assert env.subst("$BAR") == 'foo bar', env.subst("$BAR") return 0 + a = SCons.Action.FunctionAction(f, {}) - a(target=1, source=2, env=Environment(BAR = 'foo bar', - s = self)) + a(target=1, source=2, env=Environment(BAR='foo bar', + s=self)) assert self.inc == 1, self.inc assert self.source == [2], self.source assert self.target == [1], self.target global count count = 0 + def function1(target, source, env): global count count = count + 1 @@ -1540,7 +1648,7 @@ class FunctionActionTestCase(unittest.TestCase): return 1 act = SCons.Action.FunctionAction(function1, {}) - r = act(target = [outfile, outfile2], source=[], env=Environment()) + r = act(target=[outfile, outfile2], source=[], env=Environment()) assert r.status == 1, r.status assert count == 1, count @@ -1555,7 +1663,7 @@ class FunctionActionTestCase(unittest.TestCase): f.write("class1a\n") act = SCons.Action.FunctionAction(class1a, {}) - r = act([], [], Environment(out = outfile)) + r = act([], [], Environment(out=outfile)) assert isinstance(r.status, class1a), r.status c = test.read(outfile, 'r') assert c == "class1a\n", c @@ -1567,7 +1675,7 @@ class FunctionActionTestCase(unittest.TestCase): return 2 act = SCons.Action.FunctionAction(class1b(), {}) - r = act([], [], Environment(out = outfile)) + r = act([], [], Environment(out=outfile)) assert r.status == 2, r.status c = test.read(outfile, 'r') assert c == "class1b\n", c @@ -1575,11 +1683,13 @@ class FunctionActionTestCase(unittest.TestCase): def build_it(target, source, env, executor=None, self=self): self.build_it = 1 return 0 + def string_it(target, source, env, executor=None, self=self): self.string_it = 1 return None + act = SCons.Action.FunctionAction(build_it, - { 'strfunction' : string_it }) + {'strfunction': string_it}) r = act([], [], Environment()) assert r == 0, r assert self.build_it @@ -1593,15 +1703,18 @@ class FunctionActionTestCase(unittest.TestCase): pass func_matches = { - (2,7) : bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), - (3,5) : bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), - (3,6) : bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + (2, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), + (3, 5): bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), + (3, 6): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + (3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + } meth_matches = { - (2,7) : bytearray(b'1, 1, 0, 0,(),(),(d\x00\x00S),(),()'), - (3,5) : bytearray(b'1, 1, 0, 0,(),(),(d\x00\x00S),(),()'), - (3,6) : bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), + (2, 7): bytearray(b'1, 1, 0, 0,(),(),(d\x00\x00S),(),()'), + (3, 5): bytearray(b'1, 1, 0, 0,(),(),(d\x00\x00S),(),()'), + (3, 6): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), + (3, 7): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), } def factory(act, **kw): @@ -1609,18 +1722,20 @@ class FunctionActionTestCase(unittest.TestCase): a = factory(GlobalFunc) c = a.get_contents(target=[], source=[], env=Environment()) - assert c == func_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(func_matches[sys.version_info[:2]]) - + assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + func_matches[sys.version_info[:2]]) a = factory(LocalFunc) c = a.get_contents(target=[], source=[], env=Environment()) - assert c == func_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(func_matches[sys.version_info[:2]]) + assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + func_matches[sys.version_info[:2]]) matches_foo = func_matches[sys.version_info[:2]] + b'foo' a = factory(GlobalFunc, varlist=['XYZ']) c = a.get_contents(target=[], source=[], env=Environment()) - assert c == func_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(func_matches[sys.version_info[:2]]) + assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + func_matches[sys.version_info[:2]]) # assert c in func_matches, repr(c) c = a.get_contents(target=[], source=[], env=Environment(XYZ='foo')) @@ -1631,8 +1746,8 @@ class FunctionActionTestCase(unittest.TestCase): a = factory(GlobalFunc, varlist='XYZ') c = a.get_contents(target=[], source=[], env=Environment()) # assert c in func_matches, repr(c) - assert c == func_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(func_matches[sys.version_info[:2]]) - + assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + func_matches[sys.version_info[:2]]) c = a.get_contents(target=[], source=[], env=Environment(XYZ='foo')) assert c in matches_foo, repr(c) @@ -1640,6 +1755,7 @@ class FunctionActionTestCase(unittest.TestCase): class Foo(object): def get_contents(self, target, source, env): return b'xyzzy' + a = factory(Foo()) c = a.get_contents(target=[], source=[], env=Environment()) assert c == b'xyzzy', repr(c) @@ -1647,14 +1763,17 @@ class FunctionActionTestCase(unittest.TestCase): class LocalClass(object): def LocalMethod(self): pass + lc = LocalClass() a = factory(lc.LocalMethod) c = a.get_contents(target=[], source=[], env=Environment()) - assert c == meth_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(meth_matches[sys.version_info[:2]]) + assert c == meth_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + meth_matches[sys.version_info[:2]]) def test_strfunction(self): """Test the FunctionAction.strfunction() method """ + def func(): pass @@ -1673,13 +1792,16 @@ class FunctionActionTestCase(unittest.TestCase): s = a.strfunction(target=[], source=[], env=Environment()) assert s == 'function', s + class ListActionTestCase(unittest.TestCase): def test___init__(self): """Test creation of a list of subsidiary Actions """ + def func(): pass + a = SCons.Action.ListAction(["x", func, ["y", "z"]]) assert isinstance(a.list[0], SCons.Action.CommandAction) assert isinstance(a.list[1], SCons.Action.FunctionAction) @@ -1689,10 +1811,13 @@ class ListActionTestCase(unittest.TestCase): def test___str__(self): """Test the __str__() method for a list of subsidiary Actions """ - def f(target,source,env): + + def f(target, source, env): pass - def g(target,source,env): + + def g(target, source, env): pass + a = SCons.Action.ListAction([f, g, "XXX", f]) s = str(a) assert s == "f(target, source, env)\ng(target, source, env)\nXXX\nf(target, source, env)", s @@ -1700,10 +1825,13 @@ class ListActionTestCase(unittest.TestCase): def test_genstring(self): """Test the genstring() method for a list of subsidiary Actions """ - def f(target,source,env): + + def f(target, source, env): pass - def g(target,source,env,for_signature): + + def g(target, source, env, for_signature): return 'generated %s %s' % (target[0], source[0]) + g = SCons.Action.Action(g, generator=1) a = SCons.Action.ListAction([f, g, "XXX", f]) s = a.genstring(['foo.x'], ['bar.y'], Environment()) @@ -1713,11 +1841,13 @@ class ListActionTestCase(unittest.TestCase): """Test executing a list of subsidiary Actions """ self.inc = 0 - def f(target,source,env): + + def f(target, source, env): s = env['s'] s.inc = s.inc + 1 + a = SCons.Action.ListAction([f, f, f]) - a([], [], Environment(s = self)) + a([], [], Environment(s=self)) assert self.inc == 3, self.inc cmd2 = r'%s %s %s syzygy' % (_python_, act_py, outfile) @@ -1737,8 +1867,9 @@ class ListActionTestCase(unittest.TestCase): def __init__(self, target, source, env): with open(env['out'], 'a') as f: f.write("class2b\n") + act = SCons.Action.ListAction([cmd2, function2, class2a(), class2b]) - r = act([], [], Environment(out = outfile)) + r = act([], [], Environment(out=outfile)) assert isinstance(r.status, class2b), r.status c = test.read(outfile, 'r') assert c == "act.py: 'syzygy'\nfunction2\nclass2a\nclass2b\n", c @@ -1746,18 +1877,21 @@ class ListActionTestCase(unittest.TestCase): def test_get_contents(self): """Test fetching the contents of a list of subsidiary Actions """ - self.foo=0 + self.foo = 0 + def gen(target, source, env, for_signature): s = env['s'] - s.foo=1 + s.foo = 1 return "y" + a = SCons.Action.ListAction(["x", SCons.Action.Action(gen, generator=1), "z"]) - c = a.get_contents(target=[], source=[], env=Environment(s = self)) - assert self.foo==1, self.foo + c = a.get_contents(target=[], source=[], env=Environment(s=self)) + assert self.foo == 1, self.foo assert c == b"xyz", c + class LazyActionTestCase(unittest.TestCase): def test___init__(self): """Test creation of a lazy-evaluation Action @@ -1776,8 +1910,10 @@ class LazyActionTestCase(unittest.TestCase): def test_genstring(self): """Test the lazy-evaluation Action genstring() method """ + def f(target, source, env): pass + a = SCons.Action.Action('$BAR') env1 = Environment(BAR=f, s=self) env2 = Environment(BAR='xxx', s=self) @@ -1789,15 +1925,17 @@ class LazyActionTestCase(unittest.TestCase): def test_execute(self): """Test executing a lazy-evaluation Action """ + def f(target, source, env): s = env['s'] - s.test=1 + s.test = 1 return 0 + a = SCons.Action.Action('$BAR') - a([], [], env=Environment(BAR = f, s = self)) + a([], [], env=Environment(BAR=f, s=self)) assert self.test == 1, self.test cmd = r'%s %s %s lazy' % (_python_, act_py, outfile) - a([], [], env=Environment(BAR = cmd, s = self)) + a([], [], env=Environment(BAR=cmd, s=self)) c = test.read(outfile, 'r') assert c == "act.py: 'lazy'\n", c @@ -1805,7 +1943,7 @@ class LazyActionTestCase(unittest.TestCase): """Test fetching the contents of a lazy-evaluation Action """ a = SCons.Action.Action("${FOO}") - env = Environment(FOO = [["This", "is", "a", "test"]]) + env = Environment(FOO=[["This", "is", "a", "test"]]) c = a.get_contents(target=[], source=[], env=env) assert c == b"This is a test", c @@ -1816,11 +1954,11 @@ class LazyActionTestCase(unittest.TestCase): def LocalFunc(): pass - func_matches = { - (2,7) : bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), - (3,5) : bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), - (3,6) : bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + (2, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), + (3, 5): bytearray(b'0, 0, 0, 0,(),(),(d\x00\x00S),(),()'), + (3, 6): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + (3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), } meth_matches = [ @@ -1831,27 +1969,26 @@ class LazyActionTestCase(unittest.TestCase): def factory(act, **kw): return SCons.Action.FunctionAction(act, kw) - a = SCons.Action.Action("${FOO}") - env = Environment(FOO = factory(GlobalFunc)) + env = Environment(FOO=factory(GlobalFunc)) c = a.get_contents(target=[], source=[], env=env) # assert c in func_matches, "Got\n"+repr(c)+"\nExpected one of \n"+"\n".join([repr(f) for f in func_matches]) - assert c == func_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(func_matches[sys.version_info[:2]]) - + assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + func_matches[sys.version_info[:2]]) - - env = Environment(FOO = factory(LocalFunc)) + env = Environment(FOO=factory(LocalFunc)) c = a.get_contents(target=[], source=[], env=env) - assert c == func_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(func_matches[sys.version_info[:2]]) + assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + func_matches[sys.version_info[:2]]) # matches_foo = [x + b"foo" for x in func_matches] matches_foo = func_matches[sys.version_info[:2]] + b'foo' - - env = Environment(FOO = factory(GlobalFunc, varlist=['XYZ'])) + env = Environment(FOO=factory(GlobalFunc, varlist=['XYZ'])) c = a.get_contents(target=[], source=[], env=env) - assert c == func_matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(func_matches[sys.version_info[:2]]) + assert c == func_matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + func_matches[sys.version_info[:2]]) env['XYZ'] = 'foo' c = a.get_contents(target=[], source=[], env=env) @@ -1861,36 +1998,39 @@ class LazyActionTestCase(unittest.TestCase): class ActionCallerTestCase(unittest.TestCase): def test___init__(self): """Test creation of an ActionCaller""" - ac = SCons.Action.ActionCaller(1, [2, 3], {'FOO' : 4, 'BAR' : 5}) + ac = SCons.Action.ActionCaller(1, [2, 3], {'FOO': 4, 'BAR': 5}) assert ac.parent == 1, ac.parent assert ac.args == [2, 3], ac.args - assert ac.kw == {'FOO' : 4, 'BAR' : 5}, ac.kw + assert ac.kw == {'FOO': 4, 'BAR': 5}, ac.kw def test_get_contents(self): """Test fetching the contents of an ActionCaller""" + def strfunc(): pass def LocalFunc(): pass - matches = { - (2,7) : b'd\x00\x00S', - (3,5) : b'd\x00\x00S', - (3,6) : b'd\x00S\x00', - } + (2, 7): b'd\x00\x00S', + (3, 5): b'd\x00\x00S', + (3, 6): b'd\x00S\x00', + (3, 7): b'd\x00S\x00', + } af = SCons.Action.ActionFactory(GlobalFunc, strfunc) ac = SCons.Action.ActionCaller(af, [], {}) c = ac.get_contents([], [], Environment()) - assert c == matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(matches[sys.version_info[:2]]) + assert c == matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + matches[sys.version_info[:2]]) af = SCons.Action.ActionFactory(LocalFunc, strfunc) ac = SCons.Action.ActionCaller(af, [], {}) c = ac.get_contents([], [], Environment()) - assert c == matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(matches[sys.version_info[:2]]) + assert c == matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + matches[sys.version_info[:2]]) class LocalActFunc(object): def __call__(self): @@ -1899,12 +2039,14 @@ class ActionCallerTestCase(unittest.TestCase): af = SCons.Action.ActionFactory(GlobalActFunc(), strfunc) ac = SCons.Action.ActionCaller(af, [], {}) c = ac.get_contents([], [], Environment()) - assert c == matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(matches[sys.version_info[:2]]) + assert c == matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + matches[sys.version_info[:2]]) af = SCons.Action.ActionFactory(LocalActFunc(), strfunc) ac = SCons.Action.ActionCaller(af, [], {}) c = ac.get_contents([], [], Environment()) - assert c == matches[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected one of \n"+repr(matches[sys.version_info[:2]]) + assert c == matches[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected one of \n" + repr( + matches[sys.version_info[:2]]) matches = [ b"<built-in function str>", @@ -1922,12 +2064,14 @@ class ActionCallerTestCase(unittest.TestCase): def test___call__(self): """Test calling an ActionCaller""" actfunc_args = [] + def actfunc(a1, a2, a3, args=actfunc_args): args.extend([a1, a2, a3]) + def strfunc(a1, a2, a3): pass - e = Environment(FOO = 2, BAR = 5) + e = Environment(FOO=2, BAR=5) af = SCons.Action.ActionFactory(actfunc, strfunc) ac = SCons.Action.ActionCaller(af, ['$__env__', '$FOO', 3], {}) @@ -1937,7 +2081,7 @@ class ActionCallerTestCase(unittest.TestCase): assert actfunc_args[2] == 3, actfunc_args del actfunc_args[:] - ac = SCons.Action.ActionCaller(af, [], {'a3' : '$__env__', 'a2' : '$BAR', 'a1' : 4}) + ac = SCons.Action.ActionCaller(af, [], {'a3': '$__env__', 'a2': '$BAR', 'a1': 4}) ac([], [], e) assert actfunc_args[0] == 4, actfunc_args assert actfunc_args[1] == '5', actfunc_args @@ -1947,29 +2091,35 @@ class ActionCallerTestCase(unittest.TestCase): def test_strfunction(self): """Test calling the ActionCaller strfunction() method""" strfunc_args = [] + def actfunc(a1, a2, a3, a4): pass + def strfunc(a1, a2, a3, a4, args=strfunc_args): args.extend([a1, a2, a3, a4]) af = SCons.Action.ActionFactory(actfunc, strfunc) ac = SCons.Action.ActionCaller(af, [1, '$FOO', 3, '$WS'], {}) - ac.strfunction([], [], Environment(FOO = 2, WS='white space')) + ac.strfunction([], [], Environment(FOO=2, WS='white space')) assert strfunc_args == [1, '2', 3, 'white space'], strfunc_args del strfunc_args[:] - d = {'a3' : 6, 'a2' : '$BAR', 'a1' : 4, 'a4' : '$WS'} + d = {'a3': 6, 'a2': '$BAR', 'a1': 4, 'a4': '$WS'} ac = SCons.Action.ActionCaller(af, [], d) - ac.strfunction([], [], Environment(BAR = 5, WS='w s')) + ac.strfunction([], [], Environment(BAR=5, WS='w s')) assert strfunc_args == [4, '5', 6, 'w s'], strfunc_args + class ActionFactoryTestCase(unittest.TestCase): def test___init__(self): """Test creation of an ActionFactory""" + def actfunc(): pass + def strfunc(): pass + ac = SCons.Action.ActionFactory(actfunc, strfunc) assert ac.actfunc is actfunc, ac.actfunc assert ac.strfunc is strfunc, ac.strfunc @@ -1978,10 +2128,13 @@ class ActionFactoryTestCase(unittest.TestCase): """Test calling whatever's returned from an ActionFactory""" actfunc_args = [] strfunc_args = [] + def actfunc(a1, a2, a3, args=actfunc_args): args.extend([a1, a2, a3]) + def strfunc(a1, a2, a3, args=strfunc_args): args.extend([a1, a2, a3]) + af = SCons.Action.ActionFactory(actfunc, strfunc) af(3, 6, 9)([], [], Environment()) assert actfunc_args == [3, 6, 9], actfunc_args @@ -1995,8 +2148,8 @@ class ActionCompareTestCase(unittest.TestCase): Basically ensures we can locate the builder, comparing it to itself along the way.""" - bar = SCons.Builder.Builder(action = {}) - env = Environment( BUILDERS = {'BAR' : bar} ) + bar = SCons.Builder.Builder(action={}) + env = Environment(BUILDERS={'BAR': bar}) name = bar.get_name(env) assert name == 'BAR', name @@ -2005,12 +2158,12 @@ class ActionCompareTestCase(unittest.TestCase): Ensure that we can compare builders (and thereby actions) to each other safely.""" - foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo') - bar = SCons.Builder.Builder(action = {}) + foo = SCons.Builder.Builder(action='$FOO', suffix='.foo') + bar = SCons.Builder.Builder(action={}) assert foo != bar assert foo.action != bar.action - env = Environment( BUILDERS = {'FOO' : foo, - 'BAR' : bar} ) + env = Environment(BUILDERS={'FOO': foo, + 'BAR': bar}) name = foo.get_name(env) assert name == 'FOO', name name = bar.get_name(env) @@ -2024,14 +2177,14 @@ class ActionCompareTestCase(unittest.TestCase): where one of the builders has a suffix dictionary with a None key.""" - foo = SCons.Builder.Builder(action = '$FOO', suffix = '.foo') - bar = SCons.Builder.Builder(action = {}, suffix={None:'.bar'}) + foo = SCons.Builder.Builder(action='$FOO', suffix='.foo') + bar = SCons.Builder.Builder(action={}, suffix={None: '.bar'}) bar.add_action('.cow', "$MOO") - dog = SCons.Builder.Builder(suffix = '.bar') + dog = SCons.Builder.Builder(suffix='.bar') - env = Environment( BUILDERS = {'FOO' : foo, - 'BAR' : bar, - 'DOG' : dog} ) + env = Environment(BUILDERS={'FOO': foo, + 'BAR': bar, + 'DOG': dog}) assert foo.get_name(env) == 'FOO', foo.get_name(env) assert bar.get_name(env) == 'BAR', bar.get_name(env) @@ -2040,9 +2193,11 @@ class ActionCompareTestCase(unittest.TestCase): class TestClass(object): """A test class used by ObjectContentsTestCase.test_object_contents""" + def __init__(self): self.a = "a" self.b = "b" + def method(self, arg): pass @@ -2058,14 +2213,15 @@ class ObjectContentsTestCase(unittest.TestCase): # Since the python bytecode has per version differences, we need different expected results per version expected = { - (2,7) : bytearray(b'3, 3, 0, 0,(),(),(|\x00\x00S),(),()'), - (3,5) : bytearray(b'3, 3, 0, 0,(),(),(|\x00\x00S),(),()'), - (3,6) : bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()'), + (2, 7): bytearray(b'3, 3, 0, 0,(),(),(|\x00\x00S),(),()'), + (3, 5): bytearray(b'3, 3, 0, 0,(),(),(|\x00\x00S),(),()'), + (3, 6): bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()'), + (3, 7): bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()'), } c = SCons.Action._function_contents(func1) - assert c == expected[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected \n"+"\n"+repr(expected[sys.version_info[:2]]) - + assert c == expected[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + "\n" + repr( + expected[sys.version_info[:2]]) def test_object_contents(self): """Test that Action._object_contents works""" @@ -2078,12 +2234,18 @@ class ObjectContentsTestCase(unittest.TestCase): # Since the python bytecode has per version differences, we need different expected results per version expected = { - (2,7): bytearray(b"{TestClass:__main__}[[[(<type \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<type \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01\x00|\x00\x00_\x00\x00d\x02\x00|\x00\x00_\x01\x00d\x00\x00S),(),(),2, 2, 0, 0,(),(),(d\x00\x00S),(),()}}{{{a=a,b=b}}}"), - (3,5): bytearray(b"{TestClass:__main__}[[[(<class \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<class \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01\x00|\x00\x00_\x00\x00d\x02\x00|\x00\x00_\x01\x00d\x00\x00S),(),(),2, 2, 0, 0,(),(),(d\x00\x00S),(),()}}{{{a=a,b=b}}}"), - (3,6): bytearray(b"{TestClass:__main__}[[[(<class \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<class \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"), + (2, 7): bytearray( + b"{TestClass:__main__}[[[(<type \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<type \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01\x00|\x00\x00_\x00\x00d\x02\x00|\x00\x00_\x01\x00d\x00\x00S),(),(),2, 2, 0, 0,(),(),(d\x00\x00S),(),()}}{{{a=a,b=b}}}"), + (3, 5): bytearray( + b"{TestClass:__main__}[[[(<class \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<class \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01\x00|\x00\x00_\x00\x00d\x02\x00|\x00\x00_\x01\x00d\x00\x00S),(),(),2, 2, 0, 0,(),(),(d\x00\x00S),(),()}}{{{a=a,b=b}}}"), + (3, 6): bytearray( + b"{TestClass:__main__}[[[(<class \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<class \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"), + (3, 7): bytearray( + b"{TestClass:__main__}[[[(<class \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<class \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"), } - assert c == expected[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected \n"+"\n"+repr(expected[sys.version_info[:2]]) + assert c == expected[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + "\n" + repr( + expected[sys.version_info[:2]]) def test_code_contents(self): """Test that Action._code_contents works""" @@ -2093,36 +2255,18 @@ class ObjectContentsTestCase(unittest.TestCase): # Since the python bytecode has per version differences, we need different expected results per version expected = { - (2,7) : bytearray(b'0, 0, 0, 0,(N.),(),(d\x00\x00GHd\x01\x00S)'), - (3,5) : bytearray(b'0, 0, 0, 0,(N.),(print),(e\x00\x00d\x00\x00\x83\x01\x00\x01d\x01\x00S)'), - (3,6) : bytearray(b'0, 0, 0, 0,(N.),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), + (2, 7): bytearray(b'0, 0, 0, 0,(Hello, World!),(),(d\x00\x00GHd\x01\x00S)'), + (3, 5): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00\x00d\x00\x00\x83\x01\x00\x01d\x01\x00S)'), + (3, 6): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), + (3, 7): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), } - assert c == expected[sys.version_info[:2]], "Got\n"+repr(c)+"\nExpected \n"+"\n"+expected[sys.version_info[:2]] - + assert c == expected[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + "\n" + repr(expected[ + sys.version_info[:2]]) if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ _ActionActionTestCase, - ActionTestCase, - CommandActionTestCase, - CommandGeneratorActionTestCase, - FunctionActionTestCase, - ListActionTestCase, - LazyActionTestCase, - ActionCallerTestCase, - ActionFactoryTestCase, - ActionCompareTestCase, - ObjectContentsTestCase ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - - TestUnit.run(suite) - - # Swap this for above to debug otherwise you can't run individual tests as TestUnit is swallowing arguments - # unittest.main() + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Builder.py b/src/engine/SCons/Builder.py index 9cb0f86..512fcf7 100644 --- a/src/engine/SCons/Builder.py +++ b/src/engine/SCons/Builder.py @@ -77,7 +77,7 @@ There are the following methods for internal use within this module: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -98,7 +98,7 @@ There are the following methods for internal use within this module: # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Builder.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Builder.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import collections @@ -291,7 +291,14 @@ def _node_errors(builder, env, tlist, slist): if t.side_effect: raise UserError("Multiple ways to build the same target were specified for: %s" % t) if t.has_explicit_builder(): - if not t.env is None and not t.env is env: + # Check for errors when the environments are different + # No error if environments are the same Environment instance + if (not t.env is None and not t.env is env and + # Check OverrideEnvironment case - no error if wrapped Environments + # are the same instance, and overrides lists match + not (getattr(t.env, '__subject', 0) is getattr(env, '__subject', 1) and + getattr(t.env, 'overrides', 0) == getattr(env, 'overrides', 1) and + not builder.multi)): action = t.builder.action t_contents = t.builder.action.get_contents(tlist, slist, t.env) contents = builder.action.get_contents(tlist, slist, env) @@ -300,7 +307,10 @@ def _node_errors(builder, env, tlist, slist): msg = "Two different environments were specified for target %s,\n\tbut they appear to have the same action: %s" % (t, action.genstring(tlist, slist, t.env)) SCons.Warnings.warn(SCons.Warnings.DuplicateEnvironmentWarning, msg) else: - msg = "Two environments with different actions were specified for the same target: %s\n(action 1: %s)\n(action 2: %s)" % (t,t_contents.decode('utf-8'),contents.decode('utf-8')) + try: + msg = "Two environments with different actions were specified for the same target: %s\n(action 1: %s)\n(action 2: %s)" % (t,t_contents.decode('utf-8'),contents.decode('utf-8')) + except UnicodeDecodeError as e: + msg = "Two environments with different actions were specified for the same target: %s"%t raise UserError(msg) if builder.multi: if t.builder != builder: diff --git a/src/engine/SCons/BuilderTests.py b/src/engine/SCons/BuilderTests.py index edc4ca8..255eced 100644 --- a/src/engine/SCons/BuilderTests.py +++ b/src/engine/SCons/BuilderTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ # from __future__ import print_function -__revision__ = "src/engine/SCons/BuilderTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/BuilderTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -680,7 +680,9 @@ class BuilderTestCase(unittest.TestCase): def test_single_source(self): """Test Builder with single_source flag set""" def func(target, source, env): - open(str(target[0]), "w") + """create the file""" + with open(str(target[0]), "w"): + pass if (len(source) == 1 and len(target) == 1): env['CNT'][0] = env['CNT'][0] + 1 @@ -736,10 +738,12 @@ class BuilderTestCase(unittest.TestCase): """Testing handling lists of targets and source""" def function2(target, source, env, tlist = [outfile, outfile2], **kw): for t in target: - open(str(t), 'w').write("function2\n") + with open(str(t), 'w') as f: + f.write("function2\n") for t in tlist: if not t in list(map(str, target)): - open(t, 'w').write("function2\n") + with open(t, 'w') as f: + f.write("function2\n") return 1 env = Environment() @@ -765,10 +769,12 @@ class BuilderTestCase(unittest.TestCase): def function3(target, source, env, tlist = [sub1_out, sub2_out]): for t in target: - open(str(t), 'w').write("function3\n") + with open(str(t), 'w') as f: + f.write("function3\n") for t in tlist: if not t in list(map(str, target)): - open(t, 'w').write("function3\n") + with open(t, 'w') as f: + f.write("function3\n") return 1 builder = SCons.Builder.Builder(action = function3) diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index 8815eb3..73df784 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,12 +21,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/CacheDir.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/CacheDir.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """ CacheDir support """ +import hashlib import json import os import stat @@ -55,6 +56,10 @@ def CacheRetrieveFunc(target, source, env): fs.symlink(fs.readlink(cachefile), t.get_internal_path()) else: env.copy_from_cache(cachefile, t.get_internal_path()) + try: + os.utime(cachefile, None) + except OSError: + pass st = fs.stat(cachefile) fs.chmod(t.get_internal_path(), stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) return 0 @@ -134,12 +139,6 @@ warned = dict() class CacheDir(object): def __init__(self, path): - try: - import hashlib - except ImportError: - msg = "No hashlib or MD5 module available, CacheDir() not supported" - SCons.Warnings.warn(SCons.Warnings.NoMD5ModuleWarning, msg) - path = None self.path = path self.current_cache_debug = None self.debugFP = None @@ -222,7 +221,9 @@ class CacheDir(object): return None, None sig = node.get_cachedir_bsig() + subdir = sig[:self.config['prefix_len']].upper() + dir = os.path.join(self.path, subdir) return dir, os.path.join(dir, sig) diff --git a/src/engine/SCons/CacheDirTests.py b/src/engine/SCons/CacheDirTests.py index e7db18c..6b644d3 100644 --- a/src/engine/SCons/CacheDirTests.py +++ b/src/engine/SCons/CacheDirTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/CacheDirTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/CacheDirTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import shutil @@ -29,7 +29,6 @@ import sys import unittest from TestCmd import TestCmd -import TestUnit import SCons.CacheDir @@ -287,16 +286,7 @@ class FileTestCase(BaseTestCase): SCons.CacheDir.CacheRetrieveSilent = save_CacheRetrieveSilent if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ - CacheDirTestCase, - FileTestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) - + unittest.main() # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/Conftest.py b/src/engine/SCons/Conftest.py index abaf00d..84aa992 100644 --- a/src/engine/SCons/Conftest.py +++ b/src/engine/SCons/Conftest.py @@ -136,7 +136,7 @@ def CheckBuilder(context, text = None, language = None): if not text: text = """ -int main() { +int main(void) { return 0; } """ @@ -157,7 +157,7 @@ def CheckCC(context): """ context.Display("Checking whether the C compiler works... ") text = """ -int main() +int main(void) { return 0; } @@ -177,7 +177,7 @@ def CheckSHCC(context): """ context.Display("Checking whether the (shared) C compiler works... ") text = """ -int foo() +int foo(void) { return 0; } @@ -197,7 +197,7 @@ def CheckCXX(context): """ context.Display("Checking whether the C++ compiler works... ") text = """ -int main() +int main(void) { return 0; } @@ -217,7 +217,7 @@ def CheckSHCXX(context): """ context.Display("Checking whether the (shared) C++ compiler works... ") text = """ -int main() +int main(void) { return 0; } @@ -290,7 +290,7 @@ char %s();""" % function_name #include <assert.h> %(hdr)s -int main() { +int main(void) { #if defined (__stub_%(name)s) || defined (__stub___%(name)s) fail fail fail #else @@ -400,7 +400,7 @@ def CheckType(context, type_name, fallback = None, %(include)s %(header)s -int main() { +int main(void) { if ((%(name)s *) 0) return 0; if (sizeof (%(name)s)) @@ -465,7 +465,7 @@ def CheckTypeSize(context, type_name, header = None, language = None, expect = N src = src + r""" typedef %s scons_check_type; -int main() +int main(void) { static int test_array[1 - 2 * !(((long int) (sizeof(scons_check_type))) == %d)]; test_array[0] = 0; @@ -498,7 +498,7 @@ int main() src = src + """ #include <stdlib.h> #include <stdio.h> -int main() { +int main(void) { printf("%d", (int)sizeof(""" + type_name + """)); return 0; } @@ -560,7 +560,7 @@ def CheckDeclaration(context, symbol, includes = None, language = None): context.Display('Checking whether %s is declared... ' % symbol) src = src + r""" -int main() +int main(void) { #ifndef %s (void) %s; diff --git a/src/engine/SCons/Debug.py b/src/engine/SCons/Debug.py index d1ee991..34ce70d 100644 --- a/src/engine/SCons/Debug.py +++ b/src/engine/SCons/Debug.py @@ -9,7 +9,7 @@ caller_trace() """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ caller_trace() # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Debug.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Debug.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import sys diff --git a/src/engine/SCons/Defaults.py b/src/engine/SCons/Defaults.py index 4a18045..c2dc70a 100644 --- a/src/engine/SCons/Defaults.py +++ b/src/engine/SCons/Defaults.py @@ -10,7 +10,7 @@ from distutils.msvccompiler. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ from distutils.msvccompiler. # from __future__ import division -__revision__ = "src/engine/SCons/Defaults.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Defaults.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os @@ -210,7 +210,7 @@ def chmod_func(dest, mode): else: raise SyntaxError("Could not find +, - or =") operation_list = operation.split(operator) - if len(operation_list) is not 2: + if len(operation_list) != 2: raise SyntaxError("More than one operator found") user = operation_list[0].strip().replace("a", "ugo") permission = operation_list[1].strip() @@ -333,8 +333,8 @@ def touch_func(dest): if os.path.exists(file): atime = os.path.getatime(file) else: - open(file, 'w') - atime = mtime + with open(file, 'w'): + atime = mtime os.utime(file, (atime, mtime)) Touch = ActionFactory(touch_func, @@ -342,6 +342,7 @@ Touch = ActionFactory(touch_func, # Internal utility functions + def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None): """ Creates a new list from 'list' by first interpolating each element @@ -358,6 +359,7 @@ def _concat(prefix, list, suffix, env, f=lambda x: x, target=None, source=None): return _concat_ixes(prefix, list, suffix, env) + def _concat_ixes(prefix, list, suffix, env): """ Creates a new list from 'list' by concatenating the 'prefix' and @@ -395,6 +397,7 @@ def _concat_ixes(prefix, list, suffix, env): return result + def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): """ This is a wrapper around _concat()/_concat_ixes() that checks for @@ -565,7 +568,6 @@ ConstructionEnvironment = { 'DSUFFIXES' : SCons.Tool.DSuffixes, 'ENV' : {}, 'IDLSUFFIXES' : SCons.Tool.IDLSuffixes, -# 'LATEXSUFFIXES' : SCons.Tool.LaTeXSuffixes, # moved to the TeX tools generate functions '_concat' : _concat, '_defines' : _defines, '_stripixes' : _stripixes, diff --git a/src/engine/SCons/Defaults.xml b/src/engine/SCons/Defaults.xml index cef1e93..e568c92 100644 --- a/src/engine/SCons/Defaults.xml +++ b/src/engine/SCons/Defaults.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -76,7 +76,8 @@ An automatically-generated construction variable containing the C preprocessor command-line options to define values. The value of &cv-_CPPDEFFLAGS; is created -by appending &cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; +by respectively prepending and appending +&cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; to the beginning and end of each definition in &cv-CPPDEFINES;. </para> @@ -99,7 +100,8 @@ If &cv-CPPDEFINES; is a string, the values of the &cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; construction variables -will be added to the beginning and end. +will be respectively prepended and appended to the beginning and end +of each definition in &cv-CPPDEFINES;. </para> <example_commands> @@ -113,7 +115,7 @@ If &cv-CPPDEFINES; is a list, the values of the &cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; construction variables -will be appended to the beginning and end +will be respectively prepended and appended to the beginning and end of each element in the list. If any element is a list or tuple, then the first item is the name being @@ -131,7 +133,7 @@ If &cv-CPPDEFINES; is a dictionary, the values of the &cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; construction variables -will be appended to the beginning and end +will be respectively prepended and appended to the beginning and end of each item from the dictionary. The key of each dictionary item is a name being defined @@ -159,7 +161,7 @@ env = Environment(CPPDEFINES={'B':2, 'A':None}) <para> The prefix used to specify preprocessor definitions on the C compiler command line. -This will be appended to the beginning of each definition +This will be prepended to the beginning of each definition in the &cv-CPPDEFINES; construction variable when the &cv-_CPPDEFFLAGS; variable is automatically generated. </para> @@ -185,7 +187,7 @@ An automatically-generated construction variable containing the C preprocessor command-line options for specifying directories to be searched for include files. The value of &cv-_CPPINCFLAGS; is created -by appending &cv-INCPREFIX; and &cv-INCSUFFIX; +by respectively prepending and appending &cv-INCPREFIX; and &cv-INCSUFFIX; to the beginning and end of each directory in &cv-CPPPATH;. </para> @@ -227,7 +229,7 @@ through the automatically-generated &cv-_CPPINCFLAGS; construction variable, which is constructed by -appending the values of the +respectively prepending and appending the value of the &cv-INCPREFIX; and &cv-INCSUFFIX; construction variables to the beginning and end @@ -304,7 +306,7 @@ The default list is: <para> The prefix used to specify an include directory on the C compiler command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the &cv-CPPPATH; and &cv-FORTRANPATH; construction variables when the &cv-_CPPINCFLAGS; and &cv-_FORTRANINCFLAGS; variables are automatically generated. @@ -388,7 +390,7 @@ An automatically-generated construction variable containing the linker command-line options for specifying directories to be searched for library. The value of &cv-_LIBDIRFLAGS; is created -by appending &cv-LIBDIRPREFIX; and &cv-LIBDIRSUFFIX; +by respectively prepending and appending &cv-LIBDIRPREFIX; and &cv-LIBDIRSUFFIX; to the beginning and end of each directory in &cv-LIBPATH;. </para> @@ -399,7 +401,7 @@ of each directory in &cv-LIBPATH;. <summary> <para> The prefix used to specify a library directory on the linker command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the &cv-LIBPATH; construction variable when the &cv-_LIBDIRFLAGS; variable is automatically generated. </para> @@ -424,7 +426,7 @@ An automatically-generated construction variable containing the linker command-line options for specifying libraries to be linked with the resulting target. The value of &cv-_LIBFLAGS; is created -by appending &cv-LIBLINKPREFIX; and &cv-LIBLINKSUFFIX; +by respectively prepending and appending &cv-LIBLINKPREFIX; and &cv-LIBLINKSUFFIX; to the beginning and end of each filename in &cv-LIBS;. </para> @@ -435,7 +437,7 @@ of each filename in &cv-LIBS;. <summary> <para> The prefix used to specify a library to link on the linker command line. -This will be appended to the beginning of each library +This will be prepended to the beginning of each library in the &cv-LIBS; construction variable when the &cv-_LIBFLAGS; variable is automatically generated. </para> @@ -489,7 +491,7 @@ through the automatically-generated &cv-_LIBDIRFLAGS; construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the &cv-LIBDIRPREFIX; and &cv-LIBDIRSUFFIX; construction variables to the beginning and end @@ -520,7 +522,7 @@ through the automatically-generated &cv-_LIBFLAGS; construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the &cv-LIBLINKPREFIX; and &cv-LIBLINKSUFFIX; construction variables to the beginning and end diff --git a/src/engine/SCons/DefaultsTests.py b/src/engine/SCons/DefaultsTests.py index fc9934b..5a4e1cb 100644 --- a/src/engine/SCons/DefaultsTests.py +++ b/src/engine/SCons/DefaultsTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/DefaultsTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/DefaultsTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -32,7 +32,6 @@ import unittest from collections import UserDict import TestCmd -import TestUnit import SCons.Errors @@ -77,13 +76,7 @@ class DefaultsTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ DefaultsTestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Environment.py b/src/engine/SCons/Environment.py index 64210aa..759ff16 100644 --- a/src/engine/SCons/Environment.py +++ b/src/engine/SCons/Environment.py @@ -10,7 +10,7 @@ Environment """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ Environment # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Environment.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Environment.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import copy @@ -150,7 +150,7 @@ def _set_BUILDERS(env, key, value): for k in list(bd.keys()): del bd[k] except KeyError: - bd = BuilderDict(kwbd, env) + bd = BuilderDict(bd, env) env._dict[key] = bd for k, v in value.items(): if not SCons.Builder.is_a_Builder(v): @@ -1217,7 +1217,7 @@ class Base(SubstitutionEnvironment): return path def AppendENVPath(self, name, newpath, envname = 'ENV', - sep = os.pathsep, delete_existing=1): + sep = os.pathsep, delete_existing=0): """Append path elements to the path 'name' in the 'ENV' dictionary for this environment. Will only add any particular path once, and will normpath and normcase all paths to help @@ -1568,12 +1568,12 @@ class Base(SubstitutionEnvironment): """ filename = self.subst(filename) try: - fp = open(filename, 'r') + with open(filename, 'r') as fp: + lines = SCons.Util.LogicalLines(fp).readlines() except IOError: if must_exist: raise return - lines = SCons.Util.LogicalLines(fp).readlines() lines = [l for l in lines if l[0] != '#'] tdlist = [] for line in lines: @@ -2258,7 +2258,7 @@ class Base(SubstitutionEnvironment): while (node != node.srcnode()): node = node.srcnode() return node - sources = list(map( final_source, sources )); + sources = list(map(final_source, sources)) # remove duplicates return list(set(sources)) @@ -2372,6 +2372,7 @@ class OverrideEnvironment(Base): kw = copy_non_reserved_keywords(kw) self.__dict__['overrides'].update(semi_deepcopy(kw)) + # The entry point that will be used by the external world # to refer to a construction environment. This allows the wrapper # interface to extend a construction environment for its own purposes diff --git a/src/engine/SCons/Environment.xml b/src/engine/SCons/Environment.xml index 0127bc2..71b11e6 100644 --- a/src/engine/SCons/Environment.xml +++ b/src/engine/SCons/Environment.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -60,7 +60,7 @@ or this: <example_commands> env = Environment() -env['BUILDERS]['NewBuilder'] = foo +env['BUILDERS']['NewBuilder'] = foo </example_commands> </summary> </cvar> diff --git a/src/engine/SCons/EnvironmentTests.py b/src/engine/SCons/EnvironmentTests.py index 70eda9e..b97ac5c 100644 --- a/src/engine/SCons/EnvironmentTests.py +++ b/src/engine/SCons/EnvironmentTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,7 +23,7 @@ from __future__ import print_function -__revision__ = "src/engine/SCons/EnvironmentTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/EnvironmentTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -139,10 +139,6 @@ class CLVar(UL): return UL.__add__(self, CLVar(other)) def __radd__(self, other): return UL.__radd__(self, CLVar(other)) - def __coerce__(self, other): - return (self, CLVar(other)) - - class DummyNode(object): def __init__(self, name): @@ -967,7 +963,7 @@ class BaseTestCase(unittest.TestCase,TestEnvironmentFixture): self.assertRaises(AttributeError, getattr, bw, 'foobar') bw.foobar = 42 - assert bw.foobar is 42 + assert bw.foobar == 42 # This unit test is currently disabled because we don't think the # underlying method it tests (Environment.BuilderWrapper.execute()) @@ -1627,9 +1623,9 @@ def exists(env): env1.AppendENVPath('PATH',r'C:\dir\num\two', sep = ';') env1.AppendENVPath('PATH',r'C:\dir\num\three', sep = ';') env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';') - env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';') + env1.AppendENVPath('MYPATH',r'C:\mydir\num\one','MYENV', sep = ';', delete_existing=1) # this should do nothing since delete_existing is 0 - env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';', delete_existing=0) + env1.AppendENVPath('MYPATH',r'C:\mydir\num\three','MYENV', sep = ';') assert(env1['ENV']['PATH'] == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three') assert(env1['MYENV']['MYPATH'] == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one') @@ -1781,15 +1777,15 @@ def exists(env): env2 = env1.Clone() env3 = env1.Clone(tools=[bar, baz]) - assert env1.get('FOO') is 1 + assert env1.get('FOO') == 1 assert env1.get('BAR') is None assert env1.get('BAZ') is None - assert env2.get('FOO') is 1 + assert env2.get('FOO') == 1 assert env2.get('BAR') is None assert env2.get('BAZ') is None - assert env3.get('FOO') is 1 - assert env3.get('BAR') is 2 - assert env3.get('BAZ') is 3 + assert env3.get('FOO') == 1 + assert env3.get('BAR') == 2 + assert env3.get('BAZ') == 3 # Ensure that recursive variable substitution when copying # environments works properly. diff --git a/src/engine/SCons/EnvironmentValues.py b/src/engine/SCons/EnvironmentValues.py index e2efccb..d94bf3a 100644 --- a/src/engine/SCons/EnvironmentValues.py +++ b/src/engine/SCons/EnvironmentValues.py @@ -84,6 +84,7 @@ class EnvironmentValue(object): """ parts = [] for c in self.value: + pass diff --git a/src/engine/SCons/Errors.py b/src/engine/SCons/Errors.py index 8388a0f..58ef92e 100644 --- a/src/engine/SCons/Errors.py +++ b/src/engine/SCons/Errors.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ and user errors in SCons. """ -__revision__ = "src/engine/SCons/Errors.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Errors.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import shutil import SCons.Util @@ -95,7 +95,7 @@ class BuildError(Exception): # py3: errstr should be string and not bytes. - self.errstr = SCons.Util.to_str(errstr) + self.errstr = SCons.Util.to_String(errstr) self.status = status self.exitstatus = exitstatus self.filename = filename @@ -176,8 +176,8 @@ def convert_to_BuildError(status, exc_info=None): filename = status.filename except AttributeError: filename = None - - buildError = BuildError( + + buildError = BuildError( errstr=status.args[0], status=status.errno, exitstatus=2, @@ -190,14 +190,13 @@ def convert_to_BuildError(status, exc_info=None): # error, which might be different from the target being built # (for example, failure to create the directory in which the # target file will appear). - try: - filename = status.filename - except AttributeError: - filename = None + filename = getattr(status, 'filename', None) + strerror = getattr(status, 'strerror', str(status)) + errno = getattr(status, 'errno', 2) - buildError = BuildError( - errstr=status.strerror, - status=status.errno, + buildError = BuildError( + errstr=strerror, + status=errno, exitstatus=2, filename=filename, exc_info=exc_info) @@ -217,7 +216,7 @@ def convert_to_BuildError(status, exc_info=None): errstr="Error %s" % status, status=status, exitstatus=2) - + #import sys #sys.stderr.write("convert_to_BuildError: status %s => (errstr %s, status %s)\n"%(status,buildError.errstr, buildError.status)) return buildError diff --git a/src/engine/SCons/ErrorsTests.py b/src/engine/SCons/ErrorsTests.py index 6ad44e3..088224d 100644 --- a/src/engine/SCons/ErrorsTests.py +++ b/src/engine/SCons/ErrorsTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,13 +21,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/ErrorsTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/ErrorsTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" +import errno +import os import sys import unittest -import TestUnit - import SCons.Errors @@ -100,9 +100,31 @@ class ErrorsTestCase(unittest.TestCase): except SCons.Errors.ExplicitExit as e: assert e.node == "node" + def test_convert_EnvironmentError_to_BuildError(self): + """Test the convert_to_BuildError function on EnvironmentError + exceptions. + """ + ee = SCons.Errors.EnvironmentError("test env error") + be = SCons.Errors.convert_to_BuildError(ee) + assert be.errstr == "test env error" + assert be.status == 2 + assert be.exitstatus == 2 + assert be.filename is None + + def test_convert_OSError_to_BuildError(self): + """Test the convert_to_BuildError function on OSError + exceptions. + """ + ose = OSError(7, 'test oserror') + be = SCons.Errors.convert_to_BuildError(ose) + assert be.errstr == 'test oserror' + assert be.status == 7 + assert be.exitstatus == 2 + assert be.filename is None + + if __name__ == "__main__": - suite = unittest.makeSuite(ErrorsTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Executor.py b/src/engine/SCons/Executor.py index 9fabf70..10fc73f 100644 --- a/src/engine/SCons/Executor.py +++ b/src/engine/SCons/Executor.py @@ -6,7 +6,7 @@ Nodes. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Nodes. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function -__revision__ = "src/engine/SCons/Executor.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Executor.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import collections @@ -450,6 +450,8 @@ class Executor(object, with_metaclass(NoSlotsPyPy)): """Fetch the signature contents. This is the main reason this class exists, so we can compute this once and cache it regardless of how many target or source Nodes there are. + + Returns bytes """ try: return self._memo['get_contents'] diff --git a/src/engine/SCons/ExecutorTests.py b/src/engine/SCons/ExecutorTests.py index 519dff0..03b8480 100644 --- a/src/engine/SCons/ExecutorTests.py +++ b/src/engine/SCons/ExecutorTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,13 +21,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/ExecutorTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/ExecutorTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest -import TestUnit - import SCons.Executor @@ -483,12 +481,7 @@ class ExecutorTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ ExecutorTestCase ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Job.py b/src/engine/SCons/Job.py index 7f3544f..45bca62 100644 --- a/src/engine/SCons/Job.py +++ b/src/engine/SCons/Job.py @@ -7,7 +7,7 @@ stop, and wait on jobs. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ stop, and wait on jobs. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Job.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Job.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -199,7 +199,7 @@ class Serial(object): task.prepare() if task.needs_execute(): task.execute() - except: + except Exception as e: if self.interrupted(): try: raise SCons.Errors.BuildError( diff --git a/src/engine/SCons/JobTests.py b/src/engine/SCons/JobTests.py index cc17c1b..7db99e7 100644 --- a/src/engine/SCons/JobTests.py +++ b/src/engine/SCons/JobTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,24 +20,47 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/JobTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/JobTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import unittest import random import math import sys import time +import os import TestUnit import SCons.Job +def get_cpu_nums(): + # Linux, Unix and MacOS: + if hasattr( os, "sysconf" ): + if "SC_NPROCESSORS_ONLN" in os.sysconf_names: + # Linux & Unix: + 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() ) + # Windows: + if "NUMBER_OF_PROCESSORS" in os.environ: + ncpus = int( os.environ[ "NUMBER_OF_PROCESSORS" ] ); + if ncpus > 0: + return ncpus + return 1 # Default + # a large number -num_sines = 10000 +num_sines = 500 # how many parallel jobs to perform for the test -num_jobs = 11 +num_jobs = get_cpu_nums()*2 + +# in case we werent able to detect num cpus for this test +# just make a hardcoded suffcient large number, though not future proof +if(num_jobs == 2): + num_jobs = 33 # how many tasks to perform for the test num_tasks = num_jobs*5 @@ -75,14 +98,24 @@ class Task(object): return True def execute(self): - self.taskmaster.test_case.failUnless(self.was_prepared, + self.taskmaster.test_case.assertTrue(self.was_prepared, "the task wasn't prepared") self.taskmaster.guard.acquire() self.taskmaster.begin_list.append(self.i) self.taskmaster.guard.release() + # while task is executing, represent this in the parallel_list + # and then turn it off + self.taskmaster.parallel_list[self.i] = 1 self._do_something() + self.taskmaster.parallel_list[self.i] = 0 + + # check if task was executing while another was also executing + for j in range(1, self.taskmaster.num_tasks): + if(self.taskmaster.parallel_list[j+1] == 1): + self.taskmaster.found_parallel = True + break self.was_executed = 1 @@ -93,26 +126,29 @@ class Task(object): def executed(self): self.taskmaster.num_executed = self.taskmaster.num_executed + 1 - self.taskmaster.test_case.failUnless(self.was_prepared, + self.taskmaster.test_case.assertTrue(self.was_prepared, "the task wasn't prepared") - self.taskmaster.test_case.failUnless(self.was_executed, + self.taskmaster.test_case.assertTrue(self.was_executed, "the task wasn't really executed") - self.taskmaster.test_case.failUnless(isinstance(self, Task), + self.taskmaster.test_case.assertTrue(isinstance(self, Task), "the task wasn't really a Task instance") def failed(self): self.taskmaster.num_failed = self.taskmaster.num_failed + 1 self.taskmaster.stop = 1 - self.taskmaster.test_case.failUnless(self.was_prepared, + self.taskmaster.test_case.assertTrue(self.was_prepared, "the task wasn't prepared") def postprocess(self): self.taskmaster.num_postprocessed = self.taskmaster.num_postprocessed + 1 + def exception_set(self): + pass + class RandomTask(Task): def _do_something(self): # do something that will take some random amount of time: - for i in range(random.randrange(0, num_sines, 1)): + for i in range(random.randrange(0, 100 + num_sines, 1)): x = math.sin(i) time.sleep(0.01) @@ -135,17 +171,17 @@ class ExceptionTask(object): def executed(self): self.taskmaster.num_executed = self.taskmaster.num_executed + 1 - self.taskmaster.test_case.failUnless(self.was_prepared, + self.taskmaster.test_case.assertTrue(self.was_prepared, "the task wasn't prepared") - self.taskmaster.test_case.failUnless(self.was_executed, + self.taskmaster.test_case.assertTrue(self.was_executed, "the task wasn't really executed") - self.taskmaster.test_case.failUnless(self.__class__ is Task, + self.taskmaster.test_case.assertTrue(self.__class__ is Task, "the task wasn't really a Task instance") def failed(self): self.taskmaster.num_failed = self.taskmaster.num_failed + 1 self.taskmaster.stop = 1 - self.taskmaster.test_case.failUnless(self.was_prepared, + self.taskmaster.test_case.assertTrue(self.was_prepared, "the task wasn't prepared") def postprocess(self): @@ -167,7 +203,10 @@ class Taskmaster(object): self.num_executed = 0 self.num_failed = 0 self.num_postprocessed = 0 + self.parallel_list = [0] * (n+1) + self.found_parallel = False self.Task = Task + # 'guard' guards 'task_begin_list' and 'task_end_list' try: import threading @@ -199,12 +238,7 @@ class Taskmaster(object): def tasks_were_serial(self): "analyze the task order to see if they were serial" - serial = 1 # assume the tasks were serial - for i in range(num_tasks): - serial = serial and (self.begin_list[i] - == self.end_list[i] - == (i + 1)) - return serial + return not self.found_parallel def exception_set(self): pass @@ -228,15 +262,15 @@ class ParallelTestCase(unittest.TestCase): jobs = SCons.Job.Jobs(num_jobs, taskmaster) jobs.run() - self.failUnless(not taskmaster.tasks_were_serial(), + self.assertTrue(not taskmaster.tasks_were_serial(), "the tasks were not executed in parallel") - self.failUnless(taskmaster.all_tasks_are_executed(), + self.assertTrue(taskmaster.all_tasks_are_executed(), "all the tests were not executed") - self.failUnless(taskmaster.all_tasks_are_iterated(), + self.assertTrue(taskmaster.all_tasks_are_iterated(), "all the tests were not iterated over") - self.failUnless(taskmaster.all_tasks_are_postprocessed(), + self.assertTrue(taskmaster.all_tasks_are_postprocessed(), "all the tests were not postprocessed") - self.failIf(taskmaster.num_failed, + self.assertFalse(taskmaster.num_failed, "some task(s) failed to execute") # Verify that parallel jobs will pull all of the completed tasks @@ -248,7 +282,7 @@ class ParallelTestCase(unittest.TestCase): class SleepTask(Task): def _do_something(self): - time.sleep(0.1) + time.sleep(0.01) global SaveThreadPool SaveThreadPool = SCons.Job.ThreadPool @@ -258,7 +292,7 @@ class ParallelTestCase(unittest.TestCase): ThreadPoolCallList.append('put(%s)' % task.i) return SaveThreadPool.put(self, task) def get(self): - time.sleep(0.5) + time.sleep(0.05) result = SaveThreadPool.get(self) ThreadPoolCallList.append('get(%s)' % result[0].i) return result @@ -291,15 +325,15 @@ class SerialTestCase(unittest.TestCase): jobs = SCons.Job.Jobs(1, taskmaster) jobs.run() - self.failUnless(taskmaster.tasks_were_serial(), + self.assertTrue(taskmaster.tasks_were_serial(), "the tasks were not executed in series") - self.failUnless(taskmaster.all_tasks_are_executed(), + self.assertTrue(taskmaster.all_tasks_are_executed(), "all the tests were not executed") - self.failUnless(taskmaster.all_tasks_are_iterated(), + self.assertTrue(taskmaster.all_tasks_are_iterated(), "all the tests were not iterated over") - self.failUnless(taskmaster.all_tasks_are_postprocessed(), + self.assertTrue(taskmaster.all_tasks_are_postprocessed(), "all the tests were not postprocessed") - self.failIf(taskmaster.num_failed, + self.assertFalse(taskmaster.num_failed, "some task(s) failed to execute") class NoParallelTestCase(unittest.TestCase): @@ -312,18 +346,18 @@ class NoParallelTestCase(unittest.TestCase): try: taskmaster = Taskmaster(num_tasks, self, RandomTask) jobs = SCons.Job.Jobs(2, taskmaster) - self.failUnless(jobs.num_jobs == 1, + self.assertTrue(jobs.num_jobs == 1, "unexpected number of jobs %d" % jobs.num_jobs) jobs.run() - self.failUnless(taskmaster.tasks_were_serial(), + self.assertTrue(taskmaster.tasks_were_serial(), "the tasks were not executed in series") - self.failUnless(taskmaster.all_tasks_are_executed(), + self.assertTrue(taskmaster.all_tasks_are_executed(), "all the tests were not executed") - self.failUnless(taskmaster.all_tasks_are_iterated(), + self.assertTrue(taskmaster.all_tasks_are_iterated(), "all the tests were not iterated over") - self.failUnless(taskmaster.all_tasks_are_postprocessed(), + self.assertTrue(taskmaster.all_tasks_are_postprocessed(), "all the tests were not postprocessed") - self.failIf(taskmaster.num_failed, + self.assertFalse(taskmaster.num_failed, "some task(s) failed to execute") finally: SCons.Job.Parallel = save_Parallel @@ -337,13 +371,13 @@ class SerialExceptionTestCase(unittest.TestCase): jobs = SCons.Job.Jobs(1, taskmaster) jobs.run() - self.failIf(taskmaster.num_executed, + self.assertFalse(taskmaster.num_executed, "a task was executed") - self.failUnless(taskmaster.num_iterated == 1, + self.assertTrue(taskmaster.num_iterated == 1, "exactly one task should have been iterated") - self.failUnless(taskmaster.num_failed == 1, + self.assertTrue(taskmaster.num_failed == 1, "exactly one task should have failed") - self.failUnless(taskmaster.num_postprocessed == 1, + self.assertTrue(taskmaster.num_postprocessed == 1, "exactly one task should have been postprocessed") class ParallelExceptionTestCase(unittest.TestCase): @@ -354,13 +388,13 @@ class ParallelExceptionTestCase(unittest.TestCase): jobs = SCons.Job.Jobs(num_jobs, taskmaster) jobs.run() - self.failIf(taskmaster.num_executed, + self.assertFalse(taskmaster.num_executed, "a task was executed") - self.failUnless(taskmaster.num_iterated >= 1, + self.assertTrue(taskmaster.num_iterated >= 1, "one or more task should have been iterated") - self.failUnless(taskmaster.num_failed >= 1, + self.assertTrue(taskmaster.num_failed >= 1, "one or more tasks should have failed") - self.failUnless(taskmaster.num_postprocessed >= 1, + self.assertTrue(taskmaster.num_postprocessed >= 1, "one or more tasks should have been postprocessed") #--------------------------------------------------------------------- @@ -491,10 +525,10 @@ class _SConsTaskTest(unittest.TestCase): for N in testnodes: state = N.get_state() - self.failUnless(state in [SCons.Node.no_state, N.expect_to_be], + self.assertTrue(state in [SCons.Node.no_state, N.expect_to_be], "Node %s got unexpected result: %s" % (N, state)) - self.failUnless([N for N in testnodes if N.get_state()], + self.assertTrue([N for N in testnodes if N.get_state()], "no nodes ran at all.") diff --git a/src/engine/SCons/Memoize.py b/src/engine/SCons/Memoize.py index 5fe481d..85670c1 100644 --- a/src/engine/SCons/Memoize.py +++ b/src/engine/SCons/Memoize.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ # from __future__ import print_function -__revision__ = "src/engine/SCons/Memoize.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Memoize.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """Memoizer diff --git a/src/engine/SCons/MemoizeTests.py b/src/engine/SCons/MemoizeTests.py index 559232f..790791f 100644 --- a/src/engine/SCons/MemoizeTests.py +++ b/src/engine/SCons/MemoizeTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,13 +21,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/MemoizeTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/MemoizeTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest -import TestUnit - import SCons.Memoize # Enable memoization counting @@ -165,15 +163,7 @@ class CountValueTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ - CountDictTestCase, - CountValueTestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Node/Alias.py b/src/engine/SCons/Node/Alias.py index 567f663..9ea2fe0 100644 --- a/src/engine/SCons/Node/Alias.py +++ b/src/engine/SCons/Node/Alias.py @@ -8,7 +8,7 @@ This creates a hash of global Aliases (dummy targets). """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ This creates a hash of global Aliases (dummy targets). # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/Alias.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Node/Alias.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import collections diff --git a/src/engine/SCons/Node/AliasTests.py b/src/engine/SCons/Node/AliasTests.py index e1929f6..21829b6 100644 --- a/src/engine/SCons/Node/AliasTests.py +++ b/src/engine/SCons/Node/AliasTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,13 +21,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/AliasTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Node/AliasTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest -import TestUnit - import SCons.Errors import SCons.Node.Alias @@ -113,16 +111,7 @@ class AliasBuildInfoTestCase(unittest.TestCase): bi = SCons.Node.Alias.AliasBuildInfo() if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ - AliasTestCase, - AliasBuildInfoTestCase, - AliasNodeInfoTestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index a953890..6319ace 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -11,7 +11,7 @@ that can be used by scripts or modules looking for the canonical default. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ that can be used by scripts or modules looking for the canonical default. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function -__revision__ = "src/engine/SCons/Node/FS.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Node/FS.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import fnmatch import os @@ -43,6 +43,7 @@ import stat import sys import time import codecs +from itertools import chain import SCons.Action import SCons.Debug @@ -56,9 +57,12 @@ import SCons.Util import SCons.Warnings from SCons.Debug import Trace +from . import DeciderNeedsNode print_duplicate = 0 +MD5_TIMESTAMP_DEBUG = False + def sconsign_none(node): raise NotImplementedError @@ -74,6 +78,9 @@ def sconsign_dir(node): _sconsign_map = {0 : sconsign_none, 1 : sconsign_dir} +class FileBuildInfoFileToCsigMappingError(Exception): + pass + class EntryProxyAttributeError(AttributeError): """ An AttributeError subclass for recording and displaying the name @@ -132,7 +139,10 @@ def initialize_do_splitdrive(): global do_splitdrive global has_unc drive, path = os.path.splitdrive('X:/foo') - has_unc = hasattr(os.path, 'splitunc') + # splitunc is removed from python 3.7 and newer + # so we can also just test if splitdrive works with UNC + has_unc = (hasattr(os.path, 'splitunc') + or os.path.splitdrive(r'\\split\drive\test')[0] == r'\\split\drive') do_splitdrive = not not drive or has_unc @@ -282,11 +292,13 @@ def set_duplicate(duplicate): Link_Funcs.append(link_dict[func]) def LinkFunc(target, source, env): - # Relative paths cause problems with symbolic links, so - # we use absolute paths, which may be a problem for people - # who want to move their soft-linked src-trees around. Those - # people should use the 'hard-copy' mode, softlinks cannot be - # used for that; at least I have no idea how ... + """ + Relative paths cause problems with symbolic links, so + we use absolute paths, which may be a problem for people + who want to move their soft-linked src-trees around. Those + people should use the 'hard-copy' mode, softlinks cannot be + used for that; at least I have no idea how ... + """ src = source[0].get_abspath() dest = target[0].get_abspath() dir, file = os.path.split(dest) @@ -328,7 +340,12 @@ Unlink = SCons.Action.Action(UnlinkFunc, None) def MkdirFunc(target, source, env): t = target[0] - if not t.exists(): + # This os.path.exists test looks redundant, but it's possible + # when using Install() to install multiple dirs outside the + # source tree to get a case where t.exists() is true but + # the path does already exist, so this prevents spurious + # build failures in that case. See test/Install/multi-dir. + if not t.exists() and not os.path.exists(t.get_abspath()): t.fs.mkdir(t.get_abspath()) return 0 @@ -682,10 +699,15 @@ class Base(SCons.Node.Node): @SCons.Memoize.CountMethodCall def stat(self): - try: return self._memo['stat'] - except KeyError: pass - try: result = self.fs.stat(self.get_abspath()) - except os.error: result = None + try: + return self._memo['stat'] + except KeyError: + pass + try: + result = self.fs.stat(self.get_abspath()) + except os.error: + result = None + self._memo['stat'] = result return result @@ -697,13 +719,17 @@ class Base(SCons.Node.Node): def getmtime(self): st = self.stat() - if st: return st[stat.ST_MTIME] - else: return None + if st: + return st[stat.ST_MTIME] + else: + return None def getsize(self): st = self.stat() - if st: return st[stat.ST_SIZE] - else: return None + if st: + return st[stat.ST_SIZE] + else: + return None def isdir(self): st = self.stat() @@ -1048,21 +1074,22 @@ _classEntry = Entry class LocalFS(object): - - # This class implements an abstraction layer for operations involving - # a local file system. Essentially, this wraps any function in - # the os, os.path or shutil modules that we use to actually go do - # anything with or to the local file system. - # - # Note that there's a very good chance we'll refactor this part of - # the architecture in some way as we really implement the interface(s) - # for remote file system Nodes. For example, the right architecture - # might be to have this be a subclass instead of a base class. - # Nevertheless, we're using this as a first step in that direction. - # - # We're not using chdir() yet because the calling subclass method - # needs to use os.chdir() directly to avoid recursion. Will we - # really need this one? + """ + This class implements an abstraction layer for operations involving + a local file system. Essentially, this wraps any function in + the os, os.path or shutil modules that we use to actually go do + anything with or to the local file system. + + Note that there's a very good chance we'll refactor this part of + the architecture in some way as we really implement the interface(s) + for remote file system Nodes. For example, the right architecture + might be to have this be a subclass instead of a base class. + Nevertheless, we're using this as a first step in that direction. + + We're not using chdir() yet because the calling subclass method + needs to use os.chdir() directly to avoid recursion. Will we + really need this one? + """ #def chdir(self, path): # return os.chdir(path) def chmod(self, path, mode): @@ -1389,10 +1416,10 @@ class FS(LocalFS): if not isinstance(d, SCons.Node.Node): d = self.Dir(d) self.Top.addRepository(d) - + def PyPackageDir(self, modulename): """Locate the directory of a given python module name - + For example scons might resolve to Windows: C:\Python27\Lib\site-packages\scons-2.5.1 Linux: /usr/lib/scons @@ -2462,11 +2489,42 @@ class FileNodeInfo(SCons.Node.NodeInfoBase): if key not in ('__weakref__',): setattr(self, key, value) + def __eq__(self, other): + return self.csig == other.csig and self.timestamp == other.timestamp and self.size == other.size + + def __ne__(self, other): + return not self.__eq__(other) + class FileBuildInfo(SCons.Node.BuildInfoBase): - __slots__ = () + """ + This is info loaded from sconsign. + + Attributes unique to FileBuildInfo: + dependency_map : Caches file->csig mapping + for all dependencies. Currently this is only used when using + MD5-timestamp decider. + It's used to ensure that we copy the correct + csig from previous build to be written to .sconsign when current build + is done. Previously the matching of csig to file was strictly by order + they appeared in bdepends, bsources, or bimplicit, and so a change in order + or count of any of these could yield writing wrong csig, and then false positive + rebuilds + """ + __slots__ = ('dependency_map') current_version_id = 2 + def __setattr__(self, key, value): + + # If any attributes are changed in FileBuildInfo, we need to + # invalidate the cached map of file name to content signature + # heald in dependency_map. Currently only used with + # MD5-timestamp decider + if key != 'dependency_map' and hasattr(self, 'dependency_map'): + del self.dependency_map + + return super(FileBuildInfo, self).__setattr__(key, value) + def convert_to_sconsign(self): """ Converts this FileBuildInfo object for writing to a .sconsign file @@ -3235,14 +3293,155 @@ class File(Base): def changed_state(self, target, prev_ni): return self.state != SCons.Node.up_to_date - def changed_timestamp_then_content(self, target, prev_ni): - if not self.changed_timestamp_match(target, prev_ni): + + # Caching node -> string mapping for the below method + __dmap_cache = {} + __dmap_sig_cache = {} + + + def _build_dependency_map(self, binfo): + """ + Build mapping from file -> signature + + Args: + self - self + binfo - buildinfo from node being considered + + Returns: + dictionary of file->signature mappings + """ + + # For an "empty" binfo properties like bsources + # do not exist: check this to avoid exception. + if (len(binfo.bsourcesigs) + len(binfo.bdependsigs) + \ + len(binfo.bimplicitsigs)) == 0: + return {} + + + # store this info so we can avoid regenerating it. + binfo.dependency_map = { str(child):signature for child, signature in zip(chain(binfo.bsources, binfo.bdepends, binfo.bimplicit), + chain(binfo.bsourcesigs, binfo.bdependsigs, binfo.bimplicitsigs))} + + return binfo.dependency_map + + def _get_previous_signatures(self, dmap): + """ + Return a list of corresponding csigs from previous + build in order of the node/files in children. + + Args: + self - self + dmap - Dictionary of file -> csig + + Returns: + List of csigs for provided list of children + """ + prev = [] + # MD5_TIMESTAMP_DEBUG = False + + if len(dmap) == 0: + if MD5_TIMESTAMP_DEBUG: print("Nothing dmap shortcutting") + return None + + if MD5_TIMESTAMP_DEBUG: print("len(dmap):%d"%len(dmap)) + # First try the simple name for node + c_str = str(self) + if MD5_TIMESTAMP_DEBUG: print("Checking :%s"%c_str) + df = dmap.get(c_str, None) + if df: + return df + + if os.altsep: + c_str = c_str.replace(os.sep, os.altsep) + df = dmap.get(c_str, None) + if MD5_TIMESTAMP_DEBUG: print("-->%s"%df) + if df: + return df + + if not df: + try: + # this should yield a path which matches what's in the sconsign + c_str = self.get_path() + df = dmap.get(c_str, None) + if MD5_TIMESTAMP_DEBUG: print("-->%s"%df) + if df: + return df + + if os.altsep: + c_str = c_str.replace(os.sep, os.altsep) + df = dmap.get(c_str, None) + if MD5_TIMESTAMP_DEBUG: print("-->%s"%df) + if df: + return df + + except AttributeError as e: + raise FileBuildInfoFileToCsigMappingError("No mapping from file name to content signature for :%s"%c_str) + + return df + + def changed_timestamp_then_content(self, target, prev_ni, node=None): + """ + Used when decider for file is Timestamp-MD5 + + NOTE: If the timestamp hasn't changed this will skip md5'ing the + file and just copy the prev_ni provided. If the prev_ni + is wrong. It will propagate it. + See: https://github.com/SCons/scons/issues/2980 + + Args: + self - dependency + target - target + prev_ni - The NodeInfo object loaded from previous builds .sconsign + node - Node instance. This is the only changed* function which requires + node to function. So if we detect that it's not passed. + we throw DeciderNeedsNode, and caller should handle this and pass node. + + Returns: + Boolean - Indicates if node(File) has changed. + """ + if node is None: + # We need required node argument to get BuildInfo to function + raise DeciderNeedsNode(self.changed_timestamp_then_content) + + # Now get sconsign name -> csig map and then get proper prev_ni if possible + bi = node.get_stored_info().binfo + rebuilt = False + try: + dependency_map = bi.dependency_map + except AttributeError as e: + dependency_map = self._build_dependency_map(bi) + rebuilt = True + + if len(dependency_map) == 0: + # If there's no dependency map, there's no need to find the + # prev_ni as there aren't any + # shortcut the rest of the logic + if MD5_TIMESTAMP_DEBUG: print("Skipping checks len(dmap)=0") + + # We still need to get the current file's csig + # This should be slightly faster than calling self.changed_content(target, new_prev_ni) + self.get_csig() + return True + + new_prev_ni = self._get_previous_signatures(dependency_map) + new = self.changed_timestamp_match(target, new_prev_ni) + + if MD5_TIMESTAMP_DEBUG: + old = self.changed_timestamp_match(target, prev_ni) + + if old != new: + print("Mismatch self.changed_timestamp_match(%s, prev_ni) old:%s new:%s"%(str(target), old, new)) + new_prev_ni = self._get_previous_signatures(dependency_map) + + + if not new: try: - self.get_ninfo().csig = prev_ni.csig + # NOTE: We're modifying the current node's csig in a query. + self.get_ninfo().csig = new_prev_ni.csig except AttributeError: pass return False - return self.changed_content(target, prev_ni) + return self.changed_content(target, new_prev_ni) def changed_timestamp_newer(self, target, prev_ni): try: @@ -3251,6 +3450,12 @@ class File(Base): return 1 def changed_timestamp_match(self, target, prev_ni): + """ + Return True if the timestamps don't match or if there is no previous timestamp + :param target: + :param prev_ni: Information about the node from the previous build + :return: + """ try: return self.get_timestamp() != prev_ni.timestamp except AttributeError: @@ -3272,7 +3477,9 @@ class File(Base): # ...and they'd like a local copy. e = LocalCopy(self, r, None) if isinstance(e, SCons.Errors.BuildError): - raise + # Likely this should be re-raising exception e + # (which would be BuildError) + raise e SCons.Node.store_info_map[self.store_info](self) if T: Trace(' 1\n') return 1 @@ -3293,11 +3500,14 @@ class File(Base): result = self if not self.exists(): norm_name = _my_normcase(self.name) - for dir in self.dir.get_all_rdirs(): - try: node = dir.entries[norm_name] - except KeyError: node = dir.file_on_disk(self.name) + for repo_dir in self.dir.get_all_rdirs(): + try: + node = repo_dir.entries[norm_name] + except KeyError: + node = repo_dir.file_on_disk(self.name) + if node and node.exists() and \ - (isinstance(node, File) or isinstance(node, Entry) \ + (isinstance(node, File) or isinstance(node, Entry) or not node.is_derived()): result = node # Copy over our local attributes to the repository @@ -3317,6 +3527,28 @@ class File(Base): self._memo['rfile'] = result return result + def find_repo_file(self): + """ + For this node, find if there exists a corresponding file in one or more repositories + :return: list of corresponding files in repositories + """ + retvals = [] + + norm_name = _my_normcase(self.name) + for repo_dir in self.dir.get_all_rdirs(): + try: + node = repo_dir.entries[norm_name] + except KeyError: + node = repo_dir.file_on_disk(self.name) + + if node and node.exists() and \ + (isinstance(node, File) or isinstance(node, Entry) \ + or not node.is_derived()): + retvals.append(node) + + return retvals + + def rstr(self): return str(self.rfile()) @@ -3374,6 +3606,8 @@ class File(Base): because multiple targets built by the same action will all have the same build signature, and we have to differentiate them somehow. + + Signature should normally be string of hex digits. """ try: return self.cachesig @@ -3383,10 +3617,13 @@ class File(Base): # Collect signatures for all children children = self.children() sigs = [n.get_cachedir_csig() for n in children] + # Append this node's signature... sigs.append(self.get_contents_sig()) + # ...and it's path sigs.append(self.get_internal_path()) + # Merge this all into a single signature result = self.cachesig = SCons.Util.MD5collect(sigs) return result diff --git a/src/engine/SCons/Node/FSTests.py b/src/engine/SCons/Node/FSTests.py index 3a36894..021d433 100644 --- a/src/engine/SCons/Node/FSTests.py +++ b/src/engine/SCons/Node/FSTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ # from __future__ import division, print_function -__revision__ = "src/engine/SCons/Node/FSTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Node/FSTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -41,6 +41,7 @@ import SCons.Errors import SCons.Node.FS import SCons.Util import SCons.Warnings +import SCons.Environment built_it = None @@ -605,7 +606,7 @@ class VariantDirTestCase(unittest.TestCase): print("File `%s' alter_targets() `%s' != expected `%s'" % (f, tp, expect)) errors = errors + 1 - self.failIf(errors) + self.assertFalse(errors) class BaseTestCase(_tempdirTestCase): def test_stat(self): @@ -1133,7 +1134,10 @@ class FSTestCase(_tempdirTestCase): e1 = fs.Entry(p) e2 = fs.Entry(path) assert e1 is e2, (e1, e2) - assert str(e1) is str(e2), (str(e1), str(e2)) + a=str(e1) + b=str(e2) + assert a == b, ("Strings should match for same file/node\n%s\n%s"%(a,b)) + # Test for a bug in 0.04 that did not like looking up # dirs with a trailing slash on Windows. @@ -1657,7 +1661,12 @@ class FSTestCase(_tempdirTestCase): import ntpath x = test.workpath(*dirs) drive, path = ntpath.splitdrive(x) - unc, path = ntpath.splitunc(path) + try: + unc, path = ntpath.splitunc(path) + except AttributeError: + # could be python 3.7 or newer, make sure splitdrive can do UNC + assert ntpath.splitdrive(r'\\split\drive\test')[0] == r'\\split\drive' + pass path = strip_slash(path) return '//' + path[1:] @@ -2455,6 +2464,139 @@ class FileTestCase(_tempdirTestCase): assert not build_f1.exists(), "%s did not realize that %s disappeared" % (build_f1, src_f1) assert not os.path.exists(build_f1.get_abspath()), "%s did not get removed after %s was removed" % (build_f1, src_f1) + def test_changed(self): + """ + Verify that changes between BuildInfo's list of souces, depends, and implicit + dependencies do not corrupt content signature values written to .SConsign + when using CacheDir and Timestamp-MD5 decider. + This is for issue #2980 + """ + # node should have + # 1 source (for example main.cpp) + # 0 depends + # N implicits (for example ['alpha.h', 'beta.h', 'gamma.h', '/usr/bin/g++']) + + class ChangedNode(SCons.Node.FS.File): + def __init__(self, name, directory=None, fs=None): + SCons.Node.FS.File.__init__(self, name, directory, fs) + self.name = name + self.Tag('found_includes', []) + self.stored_info = None + self.build_env = None + self.changed_since_last_build = 4 + self.timestamp = 1 + + def get_stored_info(self): + return self.stored_info + + def get_build_env(self): + return self.build_env + + def get_timestamp(self): + """ Fake timestamp so they always match""" + return self.timestamp + + def get_contents(self): + return self.name + + def get_ninfo(self): + """ mocked to ensure csig will equal the filename""" + try: + return self.ninfo + except AttributeError: + self.ninfo = FakeNodeInfo(self.name, self.timestamp) + return self.ninfo + + def get_csig(self): + ninfo = self.get_ninfo() + try: + return ninfo.csig + except AttributeError: + pass + + return "Should Never Happen" + + class ChangedEnvironment(SCons.Environment.Base): + + def __init__(self): + SCons.Environment.Base.__init__(self) + self.decide_source = self._changed_timestamp_then_content + + class FakeNodeInfo(object): + def __init__(self, csig, timestamp): + self.csig = csig + self.timestamp = timestamp + + #Create nodes + fs = SCons.Node.FS.FS() + d = self.fs.Dir('.') + + node = ChangedNode('main.o',d,fs) # main.o + s1 = ChangedNode('main.cpp',d,fs) # main.cpp + s1.timestamp = 2 # this changed + i1 = ChangedNode('alpha.h',d,fs) # alpha.h - The bug is caused because the second build adds this file + i1.timestamp = 2 # This is the new file. + i2 = ChangedNode('beta.h',d,fs) # beta.h + i3 = ChangedNode('gamma.h',d,fs) # gamma.h - In the bug beta.h's csig from binfo overwrites this ones + i4 = ChangedNode('/usr/bin/g++',d,fs) # /usr/bin/g++ + + node.add_source([s1]) + node.add_dependency([]) + node.implicit = [i1, i2, i3, i4] + node.implicit_set = set() + # node._add_child(node.implicit, node.implicit_set, [n7, n8, n9]) + # node._add_child(node.implicit, node.implicit_set, [n10, n11, n12]) + + # Mock out node's scan method + # node.scan = lambda *args: None + + # Mock out nodes' children() ? + # Should return Node's. + # All those nodes should have changed_since_last_build set to match Timestamp-MD5's + # decider method... + + # Generate sconsign entry needed + sconsign_entry = SCons.SConsign.SConsignEntry() + sconsign_entry.binfo = node.new_binfo() + sconsign_entry.ninfo = node.new_ninfo() + + # mock out loading info from sconsign + # This will cause node.get_stored_info() to return our freshly created sconsign_entry + node.stored_info = sconsign_entry + + # binfo = information from previous build (from sconsign) + # We'll set the following attributes (which are lists): "bsources", "bsourcesigs", + # "bdepends","bdependsigs", "bimplicit", "bimplicitsigs" + bi = sconsign_entry.binfo + bi.bsources = ['main.cpp'] + bi.bsourcesigs=[FakeNodeInfo('main.cpp',1),] + + bi.bdepends = [] + bi.bdependsigs = [] + + bi.bimplicit = ['beta.h','gamma.h'] + bi.bimplicitsigs = [FakeNodeInfo('beta.h',1), FakeNodeInfo('gamma.h',1)] + + ni = sconsign_entry.ninfo + # We'll set the following attributes (which are lists): sources, depends, implicit lists + + #Set timestamp-md5 + #Call changed + #Check results + node.build_env = ChangedEnvironment() + + changed = node.changed() + + # change to true to debug + if False: + print("Changed:%s"%changed) + print("%15s -> csig:%s"%(s1.name, s1.ninfo.csig)) + print("%15s -> csig:%s"%(i1.name, i1.ninfo.csig)) + print("%15s -> csig:%s"%(i2.name, i2.ninfo.csig)) + print("%15s -> csig:%s"%(i3.name, i3.ninfo.csig)) + print("%15s -> csig:%s"%(i4.name, i4.ninfo.csig)) + + self.assertEqual(i2.name,i2.ninfo.csig, "gamma.h's fake csig should equal gamma.h but equals:%s"%i2.ninfo.csig) class GlobTestCase(_tempdirTestCase): @@ -3747,38 +3889,7 @@ class AbsolutePathTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.TestSuite() - suite.addTest(VariantDirTestCase()) - suite.addTest(find_fileTestCase()) - suite.addTest(StringDirTestCase()) - suite.addTest(stored_infoTestCase()) - suite.addTest(has_src_builderTestCase()) - suite.addTest(prepareTestCase()) - suite.addTest(SConstruct_dirTestCase()) - suite.addTest(clearTestCase()) - suite.addTest(disambiguateTestCase()) - suite.addTest(postprocessTestCase()) - suite.addTest(SpecialAttrTestCase()) - suite.addTest(SaveStringsTestCase()) - tclasses = [ - AbsolutePathTestCase, - BaseTestCase, - CacheDirTestCase, - DirTestCase, - DirBuildInfoTestCase, - DirNodeInfoTestCase, - EntryTestCase, - FileTestCase, - FileBuildInfoTestCase, - FileNodeInfoTestCase, - FSTestCase, - GlobTestCase, - RepositoryTestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Node/NodeTests.py b/src/engine/SCons/Node/NodeTests.py index e50616a..39b928b 100644 --- a/src/engine/SCons/Node/NodeTests.py +++ b/src/engine/SCons/Node/NodeTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,7 +20,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Node/NodeTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Node/NodeTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -30,8 +30,6 @@ import re import sys import unittest -import TestUnit - import SCons.Errors import SCons.Node import SCons.Util @@ -1337,9 +1335,9 @@ class NodeListTestCase(unittest.TestCase): assert s == "['n3', 'n2', 'n1']", s r = repr(nl) - r = re.sub('at (0[xX])?[0-9a-fA-F]+', 'at 0x', r) + r = re.sub(r'at (0[xX])?[0-9a-fA-F]+', 'at 0x', r) # Don't care about ancestry: just leaf value of MyNode - r = re.sub('<.*?\.MyNode', '<MyNode', r) + r = re.sub(r'<.*?\.MyNode', '<MyNode', r) # New-style classes report as "object"; classic classes report # as "instance"... r = re.sub("object", "instance", r) @@ -1349,15 +1347,8 @@ class NodeListTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ BuildInfoBaseTestCase, - NodeInfoBaseTestCase, - NodeTestCase, - NodeListTestCase ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() + # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Node/Python.py b/src/engine/SCons/Node/Python.py index 06cb93a..30daf9a 100644 --- a/src/engine/SCons/Node/Python.py +++ b/src/engine/SCons/Node/Python.py @@ -5,7 +5,7 @@ Python nodes. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Python nodes. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/Python.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Node/Python.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Node @@ -137,6 +137,10 @@ class Value(SCons.Node.Node): return contents def get_contents(self): + """ + Get contents for signature calculations. + :return: bytes + """ text_contents = self.get_text_contents() try: return text_contents.encode() @@ -155,12 +159,17 @@ class Value(SCons.Node.Node): def get_csig(self, calc=None): """Because we're a Python value node and don't have a real timestamp, we get to ignore the calculator and just use the - value contents.""" + value contents. + + Returns string. Ideally string of hex digits. (Not bytes) + """ try: return self.ninfo.csig except AttributeError: pass - contents = self.get_contents() + + contents = self.get_text_contents() + self.get_ninfo().csig = contents return contents diff --git a/src/engine/SCons/Node/PythonTests.py b/src/engine/SCons/Node/PythonTests.py index aab7e85..2b35f00 100644 --- a/src/engine/SCons/Node/PythonTests.py +++ b/src/engine/SCons/Node/PythonTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,13 +21,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Node/PythonTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Node/PythonTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest -import TestUnit - import SCons.Errors import SCons.Node.Python @@ -90,15 +88,15 @@ class ValueTestCase(unittest.TestCase): """ v1 = SCons.Node.Python.Value('aaa') csig = v1.get_csig(None) - assert csig.decode() == 'aaa', csig + assert csig == 'aaa', csig v2 = SCons.Node.Python.Value(7) csig = v2.get_csig(None) - assert csig.decode() == '7', csig + assert csig == '7', csig v3 = SCons.Node.Python.Value(None) csig = v3.get_csig(None) - assert csig.decode() == 'None', csig + assert csig == 'None', csig class ValueNodeInfoTestCase(unittest.TestCase): def test___init__(self): @@ -113,16 +111,7 @@ class ValueBuildInfoTestCase(unittest.TestCase): bi = SCons.Node.Python.ValueBuildInfo() if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ - ValueTestCase, - ValueBuildInfoTestCase, - ValueNodeInfoTestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Node/__init__.py b/src/engine/SCons/Node/__init__.py index 793e101..564e8de 100644 --- a/src/engine/SCons/Node/__init__.py +++ b/src/engine/SCons/Node/__init__.py @@ -22,7 +22,7 @@ be able to depend on any other type of "thing." from __future__ import print_function # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -43,8 +43,9 @@ from __future__ import print_function # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Node/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Node/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" +import os import collections import copy from itertools import chain @@ -139,6 +140,7 @@ def exists_entry(node): node.disambiguate() return _exists_map[node._func_exists](node) + def exists_file(node): # Duplicate from source path if we are set up to do this. if node.duplicate and not node.is_derived() and not node.linked: @@ -155,7 +157,7 @@ def exists_file(node): # The source file does not exist. Make sure no old # copy remains in the variant directory. if print_duplicate: - print("dup: no src for %s, unlinking old variant copy"%self) + print("dup: no src for %s, unlinking old variant copy" % node) if exists_base(node) or node.islink(): node.fs.unlink(node.get_internal_path()) # Return None explicitly because the Base.exists() call @@ -246,6 +248,21 @@ _target_from_source_map = {0 : target_from_source_none, # used by it. # + +class DeciderNeedsNode(Exception): + """ + Indicate that the decider needs the node as well as the target and the dependency. + Normally the node and the target are the same, but in the case of repository + They may be different. Also the NodeInfo is retrieved from the node + """ + def __init__(self, call_this_decider): + """ + :param call_this_decider: to return the decider to call directly since deciders + are called through several levels of indirection + """ + self.decider = call_this_decider + + # # First, the single decider functions # @@ -269,6 +286,7 @@ def changed_since_last_build_node(node, target, prev_ni): """ raise NotImplementedError + def changed_since_last_build_alias(node, target, prev_ni): cur_csig = node.get_csig() try: @@ -276,19 +294,24 @@ def changed_since_last_build_alias(node, target, prev_ni): except AttributeError: return 1 + def changed_since_last_build_entry(node, target, prev_ni): node.disambiguate() return _decider_map[node.changed_since_last_build](node, target, prev_ni) + def changed_since_last_build_state_changed(node, target, prev_ni): - return (node.state != SCons.Node.up_to_date) + return node.state != SCons.Node.up_to_date + def decide_source(node, target, prev_ni): return target.get_build_env().decide_source(node, target, prev_ni) + def decide_target(node, target, prev_ni): return target.get_build_env().decide_target(node, target, prev_ni) + def changed_since_last_build_python(node, target, prev_ni): cur_csig = node.get_csig() try: @@ -380,6 +403,7 @@ class NodeInfoBase(object): """ state = other.__getstate__() self.__setstate__(state) + def format(self, field_list=None, names=0): if field_list is None: try: @@ -665,7 +689,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): executor.cleanup() def reset_executor(self): - "Remove cached executor; forces recompute when needed." + """Remove cached executor; forces recompute when needed.""" try: delattr(self, 'executor') except AttributeError: @@ -1136,7 +1160,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): binfo.bactsig = SCons.Util.MD5signature(executor.get_contents()) if self._specific_sources: - sources = [ s for s in self.sources if not s in ignore_set] + sources = [s for s in self.sources if not s in ignore_set] else: sources = executor.get_unignored_sources(self, self.ignore) @@ -1145,13 +1169,17 @@ class Node(object, with_metaclass(NoSlotsPyPy)): binfo.bsources = [s for s in sources if s not in seen and not seen.add(s)] binfo.bsourcesigs = [s.get_ninfo() for s in binfo.bsources] + binfo.bdepends = [d for d in self.depends if d not in ignore_set] + binfo.bdependsigs = [d.get_ninfo() for d in self.depends] - binfo.bdepends = self.depends - binfo.bdependsigs = [d.get_ninfo() for d in self.depends if d not in ignore_set] - - binfo.bimplicit = self.implicit or [] - binfo.bimplicitsigs = [i.get_ninfo() for i in binfo.bimplicit if i not in ignore_set] - + # Because self.implicit is initialized to None (and not empty list []) + # we have to handle this case + if not self.implicit: + binfo.bimplicit = [] + binfo.bimplicitsigs = [] + else: + binfo.bimplicit = [i for i in self.implicit if i not in ignore_set] + binfo.bimplicitsigs = [i.get_ninfo() for i in binfo.bimplicit] return binfo @@ -1213,7 +1241,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): return _exists_map[self._func_exists](self) def rexists(self): - """Does this node exist locally or in a repositiory?""" + """Does this node exist locally or in a repository?""" # There are no repositories by default: return _rexists_map[self._func_rexists](self) @@ -1452,13 +1480,18 @@ class Node(object, with_metaclass(NoSlotsPyPy)): result = True for child, prev_ni in zip(children, then): - if _decider_map[child.changed_since_last_build](child, self, prev_ni): - if t: Trace(': %s changed' % child) - result = True + try: + if _decider_map[child.changed_since_last_build](child, self, prev_ni): + if t: Trace(': %s changed' % child) + result = True + except DeciderNeedsNode as e: + if e.decider(self, prev_ni, node=node): + if t: Trace(': %s changed' % child) + result = True - contents = self.get_executor().get_contents() if self.has_builder(): import SCons.Util + contents = self.get_executor().get_contents() newsig = SCons.Util.MD5signature(contents) if bi.bactsig != newsig: if t: Trace(': bactsig %s != newsig %s' % (bi.bactsig, newsig)) @@ -1607,7 +1640,7 @@ class Node(object, with_metaclass(NoSlotsPyPy)): # so we only print them after running them through this lambda # to turn them into the right relative Node and then return # its string. - def stringify( s, E=self.dir.Entry ) : + def stringify( s, E=self.dir.Entry): if hasattr( s, 'dir' ) : return str(E(s)) return str(s) @@ -1616,15 +1649,21 @@ class Node(object, with_metaclass(NoSlotsPyPy)): removed = [x for x in old_bkids if not x in new_bkids] if removed: - removed = list(map(stringify, removed)) + removed = [stringify(r) for r in removed] fmt = "`%s' is no longer a dependency\n" lines.extend([fmt % s for s in removed]) for k in new_bkids: if not k in old_bkids: lines.append("`%s' is a new dependency\n" % stringify(k)) - elif _decider_map[k.changed_since_last_build](k, self, osig[k]): - lines.append("`%s' changed\n" % stringify(k)) + else: + try: + changed = _decider_map[k.changed_since_last_build](k, self, osig[k]) + except DeciderNeedsNode as e: + changed = e.decider(self, osig[k], node=self) + + if changed: + lines.append("`%s' changed\n" % stringify(k)) if len(lines) == 0 and old_bkids != new_bkids: lines.append("the dependency order changed:\n" + diff --git a/src/engine/SCons/Options/PackageOption.py b/src/engine/SCons/Options/PackageOption.py deleted file mode 100644 index 6ebeca2..0000000 --- a/src/engine/SCons/Options/PackageOption.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2001 - 2017 The SCons Foundation -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "src/engine/SCons/Options/PackageOption.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" - -__doc__ = """Place-holder for the old SCons.Options module hierarchy - -This is for backwards compatibility. The new equivalent is the Variables/ -class hierarchy. These will have deprecation warnings added (some day), -and will then be removed entirely (some day). -""" - -import SCons.Variables -import SCons.Warnings - -warned = False - -def PackageOption(*args, **kw): - global warned - if not warned: - msg = "The PackageOption() function is deprecated; use the PackageVariable() function instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) - warned = True - return SCons.Variables.PackageVariable(*args, **kw) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Options/PathOption.py b/src/engine/SCons/Options/PathOption.py deleted file mode 100644 index b177687..0000000 --- a/src/engine/SCons/Options/PathOption.py +++ /dev/null @@ -1,76 +0,0 @@ -# -# Copyright (c) 2001 - 2017 The SCons Foundation -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "src/engine/SCons/Options/PathOption.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" - -__doc__ = """Place-holder for the old SCons.Options module hierarchy - -This is for backwards compatibility. The new equivalent is the Variables/ -class hierarchy. These will have deprecation warnings added (some day), -and will then be removed entirely (some day). -""" - -import SCons.Variables -import SCons.Warnings - -warned = False - -class _PathOptionClass(object): - def warn(self): - global warned - if not warned: - msg = "The PathOption() function is deprecated; use the PathVariable() function instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) - warned = True - - def __call__(self, *args, **kw): - self.warn() - return SCons.Variables.PathVariable(*args, **kw) - - def PathAccept(self, *args, **kw): - self.warn() - return SCons.Variables.PathVariable.PathAccept(*args, **kw) - - def PathIsDir(self, *args, **kw): - self.warn() - return SCons.Variables.PathVariable.PathIsDir(*args, **kw) - - def PathIsDirCreate(self, *args, **kw): - self.warn() - return SCons.Variables.PathVariable.PathIsDirCreate(*args, **kw) - - def PathIsFile(self, *args, **kw): - self.warn() - return SCons.Variables.PathVariable.PathIsFile(*args, **kw) - - def PathExists(self, *args, **kw): - self.warn() - return SCons.Variables.PathVariable.PathExists(*args, **kw) - -PathOption = _PathOptionClass() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Options/__init__.py b/src/engine/SCons/Options/__init__.py deleted file mode 100644 index 8825d10..0000000 --- a/src/engine/SCons/Options/__init__.py +++ /dev/null @@ -1,67 +0,0 @@ -# -# Copyright (c) 2001 - 2017 The SCons Foundation -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "src/engine/SCons/Options/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" - -__doc__ = """Place-holder for the old SCons.Options module hierarchy - -This is for backwards compatibility. The new equivalent is the Variables/ -class hierarchy. These will have deprecation warnings added (some day), -and will then be removed entirely (some day). -""" - -import SCons.Variables -import SCons.Warnings - -from .BoolOption import BoolOption # okay -from .EnumOption import EnumOption # okay -from .ListOption import ListOption # naja -from .PackageOption import PackageOption # naja -from .PathOption import PathOption # okay - -warned = False - -class Options(SCons.Variables.Variables): - def __init__(self, *args, **kw): - global warned - if not warned: - msg = "The Options class is deprecated; use the Variables class instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) - warned = True - SCons.Variables.Variables.__init__(self, *args, **kw) - - def AddOptions(self, *args, **kw): - return SCons.Variables.Variables.AddVariables(self, *args, **kw) - - def UnknownOptions(self, *args, **kw): - return SCons.Variables.Variables.UnknownVariables(self, *args, **kw) - - def FormatOptionHelpText(self, *args, **kw): - return SCons.Variables.Variables.FormatVariableHelpText(self, *args, - **kw) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/PathList.py b/src/engine/SCons/PathList.py index 680b853..98a160c 100644 --- a/src/engine/SCons/PathList.py +++ b/src/engine/SCons/PathList.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/PathList.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/PathList.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """SCons.PathList diff --git a/src/engine/SCons/PathListTests.py b/src/engine/SCons/PathListTests.py index 0e5f319..ea9e3ff 100644 --- a/src/engine/SCons/PathListTests.py +++ b/src/engine/SCons/PathListTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/PathListTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/PathListTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest diff --git a/src/engine/SCons/Platform/PlatformTests.py b/src/engine/SCons/Platform/PlatformTests.py index 686d0d2..21dbf18 100644 --- a/src/engine/SCons/Platform/PlatformTests.py +++ b/src/engine/SCons/Platform/PlatformTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,15 +21,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/PlatformTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/PlatformTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat import collections import unittest -import TestUnit - import SCons.Errors import SCons.Platform import SCons.Environment @@ -38,7 +36,7 @@ import SCons.Action class Environment(collections.UserDict): def Detect(self, cmd): return cmd - + def AppendENVPath(self, key, value): pass @@ -176,9 +174,9 @@ class TempFileMungeTestCase(unittest.TestCase): SCons.Action.print_actions = 0 # Create an instance of object derived class to allow setattrb class Node(object) : - class Attrs(object): + class Attrs(object): pass - def __init__(self): + def __init__(self): self.attributes = self.Attrs() target = [Node()] cmd = t(target, None, env, 0) @@ -204,17 +202,8 @@ class PlatformEscapeTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.TestSuite() - - tclasses = [ PlatformTestCase, - TempFileMungeTestCase, - PlatformEscapeTestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - - TestUnit.run(suite) + unittest.main() + # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Platform/__init__.py b/src/engine/SCons/Platform/__init__.py index 61a4010..ab4b293 100644 --- a/src/engine/SCons/Platform/__init__.py +++ b/src/engine/SCons/Platform/__init__.py @@ -20,7 +20,7 @@ their own platform definition. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -43,7 +43,7 @@ their own platform definition. # from __future__ import print_function -__revision__ = "src/engine/SCons/Platform/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -87,6 +87,7 @@ def platform_default(): else: return sys.platform + def platform_module(name = platform_default()): """Return the imported module for the platform. @@ -117,11 +118,13 @@ def platform_module(name = platform_default()): setattr(SCons.Platform, name, mod) return sys.modules[full_name] + def DefaultToolList(platform, env): """Select a default tool list for the specified platform. """ return SCons.Tool.tool_list(platform, env) + class PlatformSpec(object): def __init__(self, name, generate): self.name = name @@ -133,6 +136,7 @@ class PlatformSpec(object): def __str__(self): return self.name + class TempFileMunge(object): """A callable class. You can set an Environment variable to this, then call it with a string argument, then it will perform temporary @@ -140,15 +144,20 @@ class TempFileMunge(object): line limitation. Example usage: - env["TEMPFILE"] = TempFileMunge - env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES','$LINKCOMSTR')}" + env["TEMPFILE"] = TempFileMunge + env["LINKCOM"] = "${TEMPFILE('$LINK $TARGET $SOURCES','$LINKCOMSTR')}" By default, the name of the temporary file used begins with a - prefix of '@'. This may be configred for other tool chains by - setting '$TEMPFILEPREFIX'. - - env["TEMPFILEPREFIX"] = '-@' # diab compiler - env["TEMPFILEPREFIX"] = '-via' # arm tool chain + prefix of '@'. This may be configured for other tool chains by + setting '$TEMPFILEPREFIX': + env["TEMPFILEPREFIX"] = '-@' # diab compiler + env["TEMPFILEPREFIX"] = '-via' # arm tool chain + env["TEMPFILEPREFIX"] = '' # (the empty string) PC Lint + + You can configure the extension of the temporary file through the + TEMPFILESUFFIX variable, which defaults to '.lnk' (see comments + in the code below): + env["TEMPFILESUFFIX"] = '.lnt' # PC Lint """ def __init__(self, cmd, cmdstr = None): self.cmd = cmd @@ -185,21 +194,26 @@ class TempFileMunge(object): node = target[0] if SCons.Util.is_List(target) else target cmdlist = getattr(node.attributes, 'tempfile_cmdlist', None) \ if node is not None else None - if cmdlist is not None : + if cmdlist is not None: return cmdlist # We do a normpath because mktemp() has what appears to be # a bug in Windows that will use a forward slash as a path - # delimiter. Windows's link mistakes that for a command line + # delimiter. Windows' link mistakes that for a command line # switch and barfs. # - # We use the .lnk suffix for the benefit of the Phar Lap + # 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. - (fd, tmp) = tempfile.mkstemp('.lnk', text=True) + if env.has_key('TEMPFILESUFFIX'): + suffix = env.subst('$TEMPFILESUFFIX') + else: + suffix = '.lnk' + + fd, tmp = tempfile.mkstemp(suffix, text=True) native_tmp = SCons.Util.get_native_path(os.path.normpath(tmp)) - if env.get('SHELL',None) == 'sh': + if env.get('SHELL', None) == 'sh': # The sh shell will try to escape the backslashes in the # path, so unescape them. native_tmp = native_tmp.replace('\\', r'\\\\') @@ -239,8 +253,9 @@ class TempFileMunge(object): source) if self.cmdstr is not None else '' # Print our message only if XXXCOMSTR returns an empty string if len(cmdstr) == 0 : - print("Using tempfile "+native_tmp+" for command line:\n"+ - str(cmd[0]) + " " + " ".join(args)) + cmdstr = ("Using tempfile "+native_tmp+" for command line:\n"+ + str(cmd[0]) + " " + " ".join(args)) + self._print_cmd_str(target, source, env, cmdstr) # Store the temporary file command list into the target Node.attributes # to avoid creating two temporary files one for print and one for execute. @@ -252,6 +267,23 @@ class TempFileMunge(object): pass return cmdlist + def _print_cmd_str(self, target, source, env, cmdstr): + # check if the user has specified a cmd line print function + print_func = None + try: + get = env.get + except AttributeError: + pass + else: + print_func = get('PRINT_CMD_LINE_FUNC') + + # use the default action cmd line print if user did not supply one + if not print_func: + action = SCons.Action._ActionAction() + action.print_cmd_line(cmdstr, target, source, env) + else: + print_func(cmdstr, target, source, env) + def Platform(name = platform_default()): """Select a canned Platform specification. diff --git a/src/engine/SCons/Platform/__init__.xml b/src/engine/SCons/Platform/__init__.xml index cb83a9f..60bfb38 100644 --- a/src/engine/SCons/Platform/__init__.xml +++ b/src/engine/SCons/Platform/__init__.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -232,13 +232,29 @@ The suffix used for shared object file names. <summary> <para> The prefix for a temporary file used -to execute lines longer than $MAXLINELENGTH. -The default is '@'. -This may be set for toolchains that use other values, -such as '-@' for the diab compiler +to store lines lines longer than $MAXLINELENGTH +as operations which call out to a shell will fail +if the line is too long, which particularly +impacts linking. +The default is '@', which works for the Microsoft +and GNU toolchains on Windows. +Set this appropriately for other toolchains, +for example '-@' for the diab compiler or '-via' for ARM toolchain. </para> </summary> </cvar> +<cvar name="TEMPFILESUFFIX"> +<summary> +<para> +The suffix used for the temporary file name +used for long command lines. The name should +include the dot ('.') if one is wanted as +it will not be added automatically. +The default is '.lnk'. +</para> +</summary> +</cvar> + </sconsdoc> diff --git a/src/engine/SCons/Platform/aix.py b/src/engine/SCons/Platform/aix.py index caeb3fb..ba10ae6 100644 --- a/src/engine/SCons/Platform/aix.py +++ b/src/engine/SCons/Platform/aix.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/aix.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/aix.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import subprocess diff --git a/src/engine/SCons/Platform/cygwin.py b/src/engine/SCons/Platform/cygwin.py index 0e30b5f..7538f0a 100644 --- a/src/engine/SCons/Platform/cygwin.py +++ b/src/engine/SCons/Platform/cygwin.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,11 +30,20 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/cygwin.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/cygwin.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" + +import sys from . import posix from SCons.Platform import TempFileMunge +CYGWIN_DEFAULT_PATHS = [] +if sys.platform == 'win32': + CYGWIN_DEFAULT_PATHS = [ + r'C:\cygwin64\bin', + r'C:\cygwin\bin' + ] + def generate(env): posix.generate(env) diff --git a/src/engine/SCons/Platform/darwin.py b/src/engine/SCons/Platform/darwin.py index 70ffcf4..fc6e890 100644 --- a/src/engine/SCons/Platform/darwin.py +++ b/src/engine/SCons/Platform/darwin.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/darwin.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/darwin.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from . import posix import os diff --git a/src/engine/SCons/Platform/hpux.py b/src/engine/SCons/Platform/hpux.py index 8b34901..ccda01e 100644 --- a/src/engine/SCons/Platform/hpux.py +++ b/src/engine/SCons/Platform/hpux.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/hpux.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/hpux.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from . import posix diff --git a/src/engine/SCons/Platform/irix.py b/src/engine/SCons/Platform/irix.py index 1ff4530..38f0f26 100644 --- a/src/engine/SCons/Platform/irix.py +++ b/src/engine/SCons/Platform/irix.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/irix.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/irix.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from . import posix diff --git a/src/engine/SCons/Options/BoolOption.py b/src/engine/SCons/Platform/mingw.py index 5960a2e..95fb2e4 100644 --- a/src/engine/SCons/Options/BoolOption.py +++ b/src/engine/SCons/Platform/mingw.py @@ -1,5 +1,11 @@ +"""SCons.Platform.mingw + +Platform-specific initialization for the MinGW system. + +""" + # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,30 +27,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Options/BoolOption.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" - -__doc__ = """Place-holder for the old SCons.Options module hierarchy - -This is for backwards compatibility. The new equivalent is the Variables/ -class hierarchy. These will have deprecation warnings added (some day), -and will then be removed entirely (some day). -""" - -import SCons.Variables -import SCons.Warnings - -warned = False +__revision__ = "src/engine/SCons/Platform/mingw.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -def BoolOption(*args, **kw): - global warned - if not warned: - msg = "The BoolOption() function is deprecated; use the BoolVariable() function instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) - warned = True - return SCons.Variables.BoolVariable(*args, **kw) +import sys -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: +MINGW_DEFAULT_PATHS = [] +if sys.platform == 'win32': + MINGW_DEFAULT_PATHS = [ + r'C:\msys64', + r'C:\msys' + ]
\ No newline at end of file diff --git a/src/engine/SCons/Platform/os2.py b/src/engine/SCons/Platform/os2.py index cd1c35c..bc49c88 100644 --- a/src/engine/SCons/Platform/os2.py +++ b/src/engine/SCons/Platform/os2.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/os2.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/os2.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from . import win32 def generate(env): diff --git a/src/engine/SCons/Platform/posix.py b/src/engine/SCons/Platform/posix.py index 890a70a..27c3f3a 100644 --- a/src/engine/SCons/Platform/posix.py +++ b/src/engine/SCons/Platform/posix.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/posix.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/posix.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import errno import os @@ -41,6 +41,8 @@ import select import SCons.Util from SCons.Platform import TempFileMunge +from SCons.Platform.virtualenv import ImportVirtualenv +from SCons.Platform.virtualenv import ignore_virtualenv, enable_virtualenv exitvalmap = { 2 : 127, @@ -48,7 +50,7 @@ exitvalmap = { } def escape(arg): - "escape shell special characters" + """escape shell special characters""" slash = '\\' special = '"$' @@ -119,6 +121,9 @@ def generate(env): # Must be able to have GCC and DMD work in the same build, so: env['__DRPATH'] = '$_DRPATH' + if enable_virtualenv and not ignore_virtualenv: + ImportVirtualenv(env) + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/Platform/posix.xml b/src/engine/SCons/Platform/posix.xml index 00d42ab..a710230 100644 --- a/src/engine/SCons/Platform/posix.xml +++ b/src/engine/SCons/Platform/posix.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -46,7 +46,7 @@ An automatically-generated construction variable containing the rpath flags to be used when linking a program with shared libraries. The value of &cv-_RPATH; is created -by appending &cv-RPATHPREFIX; and &cv-RPATHSUFFIX; +by respectively prepending &cv-RPATHPREFIX; and appending &cv-RPATHSUFFIX; to the beginning and end of each directory in &cv-RPATH;. </para> @@ -58,7 +58,7 @@ of each directory in &cv-RPATH;. <para> The prefix used to specify a directory to be searched for shared libraries when running programs. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the &cv-RPATH; construction variable when the &cv-_RPATH; variable is automatically generated. </para> diff --git a/src/engine/SCons/Platform/sunos.py b/src/engine/SCons/Platform/sunos.py index 3279fb9..b54be76 100644 --- a/src/engine/SCons/Platform/sunos.py +++ b/src/engine/SCons/Platform/sunos.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/sunos.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/sunos.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from . import posix diff --git a/src/engine/SCons/Platform/sunos.xml b/src/engine/SCons/Platform/sunos.xml index 541c862..abab196 100644 --- a/src/engine/SCons/Platform/sunos.xml +++ b/src/engine/SCons/Platform/sunos.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Platform/virtualenv.py b/src/engine/SCons/Platform/virtualenv.py new file mode 100644 index 0000000..e24fb7a --- /dev/null +++ b/src/engine/SCons/Platform/virtualenv.py @@ -0,0 +1,120 @@ +"""SCons.Platform.virtualenv + +Support for virtualenv. +""" + +# +# Copyright (c) 2001 - 2019 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "src/engine/SCons/Platform/virtualenv.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" + +import os +import sys +import SCons.Util + + +virtualenv_enabled_by_default = False + + +def _enable_virtualenv_default(): + return SCons.Util.get_os_env_bool('SCONS_ENABLE_VIRTUALENV', virtualenv_enabled_by_default) + + +def _ignore_virtualenv_default(): + return SCons.Util.get_os_env_bool('SCONS_IGNORE_VIRTUALENV', False) + + +enable_virtualenv = _enable_virtualenv_default() +ignore_virtualenv = _ignore_virtualenv_default() +virtualenv_variables = ['VIRTUAL_ENV', 'PIPENV_ACTIVE'] + + +def _running_in_virtualenv(): + """Returns True, if scons is executed within a virtualenv""" + # see https://stackoverflow.com/a/42580137 + return (hasattr(sys, 'real_prefix') or + (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix)) + + +def _is_path_in(path, base): + """Returns true, if **path** is located under the **base** directory.""" + if not path or not base: # empty path may happen, base too + return False + rp = os.path.relpath(path, base) + return ((not rp.startswith(os.path.pardir)) and (not rp == os.path.curdir)) + + +def _inject_venv_variables(env): + if 'ENV' not in env: + env['ENV'] = {} + ENV = env['ENV'] + for name in virtualenv_variables: + try: + ENV[name] = os.environ[name] + except KeyError: + pass + +def _inject_venv_path(env, path_list=None): + """Modify environment such that SCons will take into account its virtualenv + when running external tools.""" + if path_list is None: + path_list = os.getenv('PATH') + env.PrependENVPath('PATH', select_paths_in_venv(path_list)) + + +def select_paths_in_venv(path_list): + """Returns a list of paths from **path_list** which are under virtualenv's + home directory.""" + if SCons.Util.is_String(path_list): + path_list = path_list.split(os.path.pathsep) + # Find in path_list the paths under the virtualenv's home + return [path for path in path_list if IsInVirtualenv(path)] + + +def ImportVirtualenv(env): + """Copies virtualenv-related environment variables from OS environment + to ``env['ENV']`` and prepends virtualenv's PATH to ``env['ENV']['PATH']``. + """ + _inject_venv_variables(env) + _inject_venv_path(env) + + +def Virtualenv(): + """Returns path to the virtualenv home if scons is executing within a + virtualenv or None, if not.""" + if _running_in_virtualenv(): + return sys.prefix + return None + + +def IsInVirtualenv(path): + """Returns True, if **path** is under virtualenv's home directory. If not, + or if we don't use virtualenv, returns False.""" + return _is_path_in(path, Virtualenv()) + + +# Local Variables: +# tab-width:4 +# indent-tabs-mode:nil +# End: +# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/src/engine/SCons/Platform/virtualenvTests.py b/src/engine/SCons/Platform/virtualenvTests.py new file mode 100644 index 0000000..f560f2e --- /dev/null +++ b/src/engine/SCons/Platform/virtualenvTests.py @@ -0,0 +1,243 @@ +# +# Copyright (c) 2001 - 2019 The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "src/engine/SCons/Platform/virtualenvTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" + +import SCons.compat + +import collections +import unittest +import os +import sys + +import SCons.Platform.virtualenv +import SCons.Util + +class Environment(collections.UserDict): + def Detect(self, cmd): + return cmd + + def AppendENVPath(self, key, value): + if SCons.Util.is_List(value): + value = os.path.pathsep.join(value) + if 'ENV' not in self: + self['ENV'] = {} + current = self['ENV'].get(key) + if not current: + self['ENV'][key] = value + else: + self['ENV'][key] = os.path.pathsep.join([current, value]) + + def PrependENVPath(self, key, value): + if SCons.Util.is_List(value): + value = os.path.pathsep.join(value) + if 'ENV' not in self: + self['ENV'] = {} + current = self['ENV'].get(key) + if not current: + self['ENV'][key] = value + else: + self['ENV'][key] = os.path.pathsep.join([value, current]) + +class SysPrefixes(object): + """Used to temporarily mock sys.prefix, sys.real_prefix and sys.base_prefix""" + def __init__(self, prefix, real_prefix=None, base_prefix=None): + self._prefix = prefix + self._real_prefix = real_prefix + self._base_prefix = base_prefix + + def start(self): + self._store() + sys.prefix = self._prefix + if self._real_prefix is None: + if hasattr(sys, 'real_prefix'): + del sys.real_prefix + else: + sys.real_prefix = self._real_prefix + if self._base_prefix is None: + if hasattr(sys, 'base_prefix'): + del sys.base_prefix + else: + sys.base_prefix = self._base_prefix + + def stop(self): + self._restore() + + def __enter__(self): + self.start() + attrs = ('prefix', 'real_prefix', 'base_prefix') + return {k: getattr(sys, k) for k in attrs if hasattr(sys, k)} + + def __exit__(self, *args): + self.stop() + + def _store(self): + s = dict() + if hasattr(sys, 'real_prefix'): + s['real_prefix'] = sys.real_prefix + if hasattr(sys, 'base_prefix'): + s['base_prefix'] = sys.base_prefix + s['prefix'] = sys.prefix + self._stored = s + + def _restore(self): + s = self._stored + if 'real_prefix' in s: + sys.real_prefix = s['real_prefix'] + if 'base_prefix' in s: + sys.base_prefix = s['base_prefix'] + if 'prefix' in s: + sys.prefix = s['prefix'] + del self._stored + +def _p(p): + """Converts path string **p** from posix format to os-specific format.""" + drive = [] + if p.startswith('/') and sys.platform == 'win32': + drive = ['C:'] + pieces = p.split('/') + return os.path.sep.join(drive + pieces) + + +class _is_path_in_TestCase(unittest.TestCase): + def test_false(self): + for args in [ ('',''), + ('', _p('/foo/bar')), + (_p('/foo/bar'), ''), + (_p('/foo/bar'), _p('/foo/bar')), + (_p('/foo/bar'), _p('/foo/bar/geez')), + (_p('/'), _p('/foo')), + (_p('foo'), _p('foo/bar')) ]: + assert SCons.Platform.virtualenv._is_path_in(*args) is False, "_is_path_in(%r, %r) should be False" % args + + def test__true(self): + for args in [ (_p('/foo'), _p('/')), + (_p('/foo/bar'), _p('/foo')), + (_p('/foo/bar/geez'), _p('/foo/bar')), + (_p('/foo//bar//geez'), _p('/foo/bar')), + (_p('/foo/bar/geez'), _p('/foo//bar')), + (_p('/foo/bar/geez'), _p('//foo//bar')) ]: + assert SCons.Platform.virtualenv._is_path_in(*args) is True, "_is_path_in(%r, %r) should be True" % args + +class IsInVirtualenvTestCase(unittest.TestCase): + def test_false(self): + # "without wirtualenv" - always false + with SysPrefixes(_p('/prefix')): + for p in [ _p(''), + _p('/foo'), + _p('/prefix'), + _p('/prefix/foo') ]: + assert SCons.Platform.virtualenv.IsInVirtualenv(p) is False, "IsInVirtualenv(%r) should be False" % p + + # "with virtualenv" + with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')): + for p in [ _p(''), + _p('/real/prefix/foo'), + _p('/virtualenv/prefix'), + _p('/virtualenv/prefix/bar/..'), + _p('/virtualenv/prefix/bar/../../bleah'), + _p('/virtualenv/bleah') ]: + assert SCons.Platform.virtualenv.IsInVirtualenv(p) is False, "IsInVirtualenv(%r) should be False" % p + + # "with venv" + with SysPrefixes(_p('/virtualenv/prefix'), base_prefix=_p('/base/prefix')): + for p in [ _p(''), + _p('/base/prefix/foo'), + _p('/virtualenv/prefix'), + _p('/virtualenv/prefix/bar/..'), + _p('/virtualenv/prefix/bar/../../bleah'), + _p('/virtualenv/bleah') ]: + assert SCons.Platform.virtualenv.IsInVirtualenv(p) is False, "IsInVirtualenv(%r) should be False" % p + + def test_true(self): + # "with virtualenv" + with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')): + for p in [ _p('/virtualenv/prefix/foo'), + _p('/virtualenv/prefix/foo/bar') ]: + assert SCons.Platform.virtualenv.IsInVirtualenv(p) is True, "IsInVirtualenv(%r) should be True" % p + + # "with venv" + with SysPrefixes(_p('/virtualenv/prefix'), base_prefix=_p('/base/prefix')): + for p in [ _p('/virtualenv/prefix/foo'), + _p('/virtualenv/prefix/foo/bar') ]: + assert SCons.Platform.virtualenv.IsInVirtualenv(p) is True, "IsInVirtualenv(%r) should be True" % p + +class _inject_venv_pathTestCase(unittest.TestCase): + def path_list(self): + return [ + _p('/virtualenv/prefix/bin'), + _p('/virtualenv/prefix'), + _p('/virtualenv/prefix/../bar'), + _p('/home/user/.local/bin'), + _p('/usr/bin'), + _p('/opt/bin') + ] + def test_with_path_string(self): + env = Environment() + path_string = os.path.pathsep.join(self.path_list()) + with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')): + SCons.Platform.virtualenv._inject_venv_path(env, path_string) + assert env['ENV']['PATH'] == _p('/virtualenv/prefix/bin'), env['ENV']['PATH'] + + def test_with_path_list(self): + env = Environment() + with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')): + SCons.Platform.virtualenv._inject_venv_path(env, self.path_list()) + assert env['ENV']['PATH'] == _p('/virtualenv/prefix/bin'), env['ENV']['PATH'] + +class VirtualenvTestCase(unittest.TestCase): + def test_none(self): + def _msg(given): + return "Virtualenv() should be None, not %s" % repr(given) + + with SysPrefixes(_p('/prefix')): + ve = SCons.Platform.virtualenv.Virtualenv() + assert ve is None , _msg(ve) + with SysPrefixes(_p('/base/prefix'), base_prefix=_p('/base/prefix')): + ve = SCons.Platform.virtualenv.Virtualenv() + assert ve is None, _msg(ve) + + def test_not_none(self): + def _msg(expected, given): + return "Virtualenv() should == %r, not %s" % (_p(expected), repr(given)) + + with SysPrefixes(_p('/virtualenv/prefix'), real_prefix=_p('/real/prefix')): + ve = SCons.Platform.virtualenv.Virtualenv() + assert ve == _p('/virtualenv/prefix'), _msg('/virtualenv/prefix', ve) + with SysPrefixes(_p('/same/prefix'), real_prefix=_p('/same/prefix')): + ve = SCons.Platform.virtualenv.Virtualenv() + assert ve == _p('/same/prefix'), _msg('/same/prefix', ve) + with SysPrefixes(_p('/virtualenv/prefix'), base_prefix=_p('/base/prefix')): + ve = SCons.Platform.virtualenv.Virtualenv() + assert ve == _p('/virtualenv/prefix'), _msg('/virtualenv/prefix', ve) + + +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/Platform/win32.py b/src/engine/SCons/Platform/win32.py index 79955e7..f64081c 100644 --- a/src/engine/SCons/Platform/win32.py +++ b/src/engine/SCons/Platform/win32.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Platform/win32.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Platform/win32.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path @@ -39,8 +39,14 @@ import tempfile from SCons.Platform.posix import exitvalmap from SCons.Platform import TempFileMunge +from SCons.Platform.virtualenv import ImportVirtualenv +from SCons.Platform.virtualenv import ignore_virtualenv, enable_virtualenv import SCons.Util +CHOCO_DEFAULT_PATH = [ + r'C:\ProgramData\chocolatey\bin' +] + try: import msvcrt import win32api @@ -80,16 +86,8 @@ else: win32con.HANDLE_FLAG_INHERIT, 0) file = _scons_file else: - import io - for io_class in ['BufferedReader', 'BufferedWriter', 'BufferedRWPair', - 'BufferedRandom', 'TextIOWrapper']: - _builtin_file = getattr(io, io_class) - class _scons_file(_builtin_file): - def __init__(self, *args, **kw): - _builtin_file.__init__(self, *args, **kw) - win32api.SetHandleInformation(msvcrt.get_osfhandle(self.fileno()), - win32con.HANDLE_FLAG_INHERIT, 0) - setattr(io, io_class, _scons_file) + # No longer needed for python 3.4 and above. Files are opened non sharable + pass @@ -132,7 +130,7 @@ try: # Without this, python can randomly crash while using -jN. # See the python bug at http://bugs.python.org/issue6476 # and SCons issue at - # http://scons.tigris.org/issues/show_bug.cgi?id=2449 + # https://github.com/SCons/scons/issues/2449 def spawnve(mode, file, args, env): spawn_lock.acquire() try: @@ -200,11 +198,11 @@ def piped_spawn(sh, escape, cmd, args, env, stdout, stderr): except OSError as e: # catch any error try: - ret = exitvalmap[e[0]] + ret = exitvalmap[e.errno] except KeyError: - sys.stderr.write("scons: unknown OSError exception code %d - %s: %s\n" % (e[0], cmd, e[1])) + sys.stderr.write("scons: unknown OSError exception code %d - %s: %s\n" % (e.errno, cmd, e.strerror)) if stderr is not None: - stderr.write("scons: %s: %s\n" % (cmd, e[1])) + stderr.write("scons: %s: %s\n" % (cmd, e.strerror)) # copy child output from tempfiles to our streams # and do clean up stuff if stdout is not None and stdoutRedirected == 0: @@ -436,7 +434,7 @@ def generate(env): if v: env['ENV']['COMSPEC'] = v - env.AppendENVPath('PATH', get_system_root() + '\System32') + env.AppendENVPath('PATH', get_system_root() + '\\System32') env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD' env['OBJPREFIX'] = '' @@ -462,6 +460,9 @@ def generate(env): env['HOST_OS'] = 'win32' env['HOST_ARCH'] = get_architecture().arch + if enable_virtualenv and not ignore_virtualenv: + ImportVirtualenv(env) + # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Platform/win32.xml b/src/engine/SCons/Platform/win32.xml index c2b9b01..cc87470 100644 --- a/src/engine/SCons/Platform/win32.xml +++ b/src/engine/SCons/Platform/win32.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index c1ab159..e0cd35d 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -12,7 +12,7 @@ libraries are installed, if some command line options are supported etc. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -35,7 +35,7 @@ libraries are installed, if some command line options are supported etc. # from __future__ import print_function -__revision__ = "src/engine/SCons/SConf.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/SConf.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -56,6 +56,7 @@ import SCons.Warnings import SCons.Conftest from SCons.Debug import Trace +from SCons.Node import DeciderNeedsNode # Turn off the Conftest error logging SCons.Conftest.LogInputFiles = 0 @@ -323,18 +324,6 @@ class SConfBuildTask(SCons.Taskmaster.AlwaysTask): s = sys.stdout = sys.stderr = Streamer(sys.stdout) try: env = self.targets[0].get_build_env() - if cache_mode == FORCE: - # Set up the Decider() to force rebuilds by saying - # that every source has changed. Note that we still - # call the environment's underlying source decider so - # that the correct .sconsign info will get calculated - # and keep the build state consistent. - def force_build(dependency, target, prev_ni, - env_decider=env.decide_source): - env_decider(dependency, target, prev_ni) - return True - if env.decide_source.__code__ is not force_build.__code__: - env.Decider(force_build) env['PSTDOUT'] = env['PSTDERR'] = s try: sconf.cached = 0 @@ -405,12 +394,42 @@ class SConfBase(object): build tests in the VariantDir, not in the SourceDir) """ global SConfFS + + # Now create isolated override so setting source_decider doesn't affect parent Environment + if cache_mode == FORCE: + self.original_env = env + self.env = env.Clone() + + # Set up the Decider() to force rebuilds by saying + # that every source has changed. Note that we still + # call the environment's underlying source decider so + # that the correct .sconsign info will get calculated + # and keep the build state consistent. + def force_build(dependency, target, prev_ni, + env_decider=env.decide_source, + node=None): + try: + env_decider(dependency, target, prev_ni) + except DeciderNeedsNode as e: + e.decider(target, prev_ni, node=target) + except Exception as e: + raise e + return True + + if self.env.decide_source.__code__ is not force_build.__code__: + self.env.Decider(force_build) + + else: + self.env = env + + # print("Override env:%s"%env) + if not SConfFS: SConfFS = SCons.Node.FS.default_fs or \ SCons.Node.FS.FS(env.fs.pathTop) if sconf_global is not None: raise SCons.Errors.UserError - self.env = env + if log_file is not None: log_file = SConfFS.File(env.subst(log_file)) self.logfile = log_file @@ -449,6 +468,7 @@ class SConfBase(object): env = sconf.Finish() """ self._shutdown() + return self.env def Define(self, name, value = None, comment = None): @@ -503,6 +523,20 @@ class SConfBase(object): n.attributes = SCons.Node.Node.Attrs() n.attributes.keep_targetinfo = 1 + if True: + # Some checkers have intermediate files (for example anything that compiles a c file into a program to run + # Those files need to be set to not release their target info, otherwise taskmaster will throw a + # Nonetype not callable + for c in n.children(scan=False): + # Keep debug code here. + # print("Checking [%s] for builders and then setting keep_targetinfo"%c) + if c.has_builder(): + n.store_info = 0 + if not hasattr(c, 'attributes'): + c.attributes = SCons.Node.Node.Attrs() + c.attributes.keep_targetinfo = 1 + # pass + ret = 1 try: @@ -609,7 +643,7 @@ class SConfBase(object): ok = self.TryBuild(self.env.SConfActionBuilder, text, extension) del self.env['BUILDERS']['SConfActionBuilder'] if ok: - outputStr = self.lastTarget.get_contents().decode() + outputStr = self.lastTarget.get_text_contents() return (1, outputStr) return (0, "") @@ -739,10 +773,18 @@ class SConfBase(object): self.logstream.write("\n") self.logstream.close() self.logstream = None - # remove the SConfSourceBuilder from the environment - blds = self.env['BUILDERS'] - del blds['SConfSourceBuilder'] - self.env.Replace( BUILDERS=blds ) + + # Now reset the decider if we changed it due to --config=force + # We saved original Environment passed in and cloned it to isolate + # it from being changed. + if cache_mode == FORCE: + self.env.Decider(self.original_env.decide_source) + + # remove the SConfSourceBuilder from the environment + blds = self.env['BUILDERS'] + del blds['SConfSourceBuilder'] + self.env.Replace( BUILDERS=blds ) + self.active = 0 sconf_global = None if not self.config_h is None: @@ -1000,7 +1042,7 @@ def CheckLib(context, library = None, symbol = "main", compiles without flags. """ - if library == []: + if not library: library = [None] if not SCons.Util.is_List(library): diff --git a/src/engine/SCons/SConfTests.py b/src/engine/SCons/SConfTests.py index 36abc7e..678147c 100644 --- a/src/engine/SCons/SConfTests.py +++ b/src/engine/SCons/SConfTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/SConfTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/SConfTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -33,8 +33,6 @@ from types import * import unittest import TestCmd -import TestUnit - sys.stdout = io.StringIO() @@ -115,9 +113,9 @@ class SConfTestCase(unittest.TestCase): def checks(self, sconf, TryFuncString): TryFunc = self.SConf.SConfBase.__dict__[TryFuncString] - res1 = TryFunc( sconf, "int main() { return 0; }\n", ".c" ) + res1 = TryFunc( sconf, "int main(void) { return 0; }\n", ".c" ) res2 = TryFunc( sconf, - '#include "no_std_header.h"\nint main() {return 0; }\n', + '#include "no_std_header.h"\nint main(void) {return 0; }\n', '.c' ) return (res1,res2) @@ -196,7 +194,7 @@ class SConfTestCase(unittest.TestCase): pass def add_post_action(self, *actions): pass - def children(self): + def children(self, scan = 1): return [] def get_state(self): return self.state @@ -254,7 +252,7 @@ class SConfTestCase(unittest.TestCase): def checks(sconf): prog = """ #include <stdio.h> -int main() { +int main(void) { printf( "Hello" ); return 0; } @@ -300,10 +298,17 @@ int main() { """Test SConf.TryAction """ def actionOK(target, source, env): - open(str(target[0]), "w").write( "RUN OK\n" ) + with open(str(target[0]), "w") as f: + f.write("RUN OK\n") 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() sconf = self.SConf.SConf(self.scons_env, conf_dir=self.test.workpath('config.tests'), @@ -313,6 +318,12 @@ int main() { 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() @@ -755,7 +766,7 @@ int main() { prog = """ #include <stdio.h> -int main() { +int main(void) { printf( "Hello" ); return 0; } @@ -779,8 +790,7 @@ int main() { if __name__ == "__main__": - suite = unittest.makeSuite(SConfTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/SConsign.py b/src/engine/SCons/SConsign.py index 9d2f69e..e01026d 100644 --- a/src/engine/SCons/SConsign.py +++ b/src/engine/SCons/SConsign.py @@ -5,7 +5,7 @@ Writing and reading information to the .sconsign file or files. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ Writing and reading information to the .sconsign file or files. from __future__ import print_function -__revision__ = "src/engine/SCons/SConsign.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/SConsign.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -394,7 +394,8 @@ class DirFile(Dir): # here, or in any of the following calls, would get # raised, indicating something like a potentially # serious disk or network issue. - open(self.sconsign, 'wb').write(open(fname, 'rb').read()) + with open(self.sconsign, 'wb') as f, open(fname, 'rb') as f2: + f.write(f2.read()) os.chmod(self.sconsign, mode) try: os.unlink(temp) diff --git a/src/engine/SCons/SConsignTests.py b/src/engine/SCons/SConsignTests.py index 37e0de9..e8e9231 100644 --- a/src/engine/SCons/SConsignTests.py +++ b/src/engine/SCons/SConsignTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/SConsignTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/SConsignTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import sys diff --git a/src/engine/SCons/Scanner/C.py b/src/engine/SCons/Scanner/C.py index 6cdab4a..703ccc3 100644 --- a/src/engine/SCons/Scanner/C.py +++ b/src/engine/SCons/Scanner/C.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for C/C++ code. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This module implements the dependency scanner for C/C++ code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/C.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/C.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Node.FS import SCons.Scanner diff --git a/src/engine/SCons/Scanner/CTests.py b/src/engine/SCons/Scanner/CTests.py index f7b2b16..d39f206 100644 --- a/src/engine/SCons/Scanner/CTests.py +++ b/src/engine/SCons/Scanner/CTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/CTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/CTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -48,7 +48,7 @@ test.write('f1.cpp',""" #include \"f1.h\" #include <f2.h> -int main() +int main(void) { return 0; } @@ -60,7 +60,7 @@ test.write('f2.cpp',""" #include \"f1.h\" #import <f4.h> -int main() +int main(void) { return 0; } @@ -79,7 +79,7 @@ test.write('f3.cpp',""" const char* x = "#include <never.h>" -int main() +int main(void) { return 0; } @@ -113,7 +113,7 @@ test.write('fa.cpp',""" #include \"fa.h\" #include <fb.h> -int main() +int main(void) { return 0; } @@ -135,7 +135,7 @@ test.write(['work', 'src', 'fff.c'], """ #include <iii.h> #include <jjj.h> -int main() +int main(void) { return 0; } @@ -144,7 +144,7 @@ int main() test.write([ 'work', 'src', 'aaa.c'], """ #include "bbb.h" -int main() +int main(void) { return 0; } @@ -155,7 +155,7 @@ test.write([ 'work', 'src', 'bbb.h'], "\n") test.write([ 'repository', 'src', 'ccc.c'], """ #include "ddd.h" -int main() +int main(void) { return 0; } @@ -218,7 +218,7 @@ 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.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) + self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) # define some tests: diff --git a/src/engine/SCons/Scanner/D.py b/src/engine/SCons/Scanner/D.py index 3b6f2f9..2fc577c 100644 --- a/src/engine/SCons/Scanner/D.py +++ b/src/engine/SCons/Scanner/D.py @@ -8,7 +8,7 @@ Coded by Andy Friesen """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ Coded by Andy Friesen # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/D.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/D.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Scanner diff --git a/src/engine/SCons/Scanner/DTests.py b/src/engine/SCons/Scanner/DTests.py index 58fbe76..e649a88 100644 --- a/src/engine/SCons/Scanner/DTests.py +++ b/src/engine/SCons/Scanner/DTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,12 +21,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/DTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/DTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import unittest import TestCmd -import TestUnit import SCons.Scanner.D @@ -80,7 +79,7 @@ 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.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) + self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) """ Examples from https://dlang.org/spec/module.html @@ -266,14 +265,7 @@ class DScannerTestCase(unittest.TestCase): self.helper('multiline.d', ['A.d']) if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ - DScannerTestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Scanner/Dir.py b/src/engine/SCons/Scanner/Dir.py index 66d5b6d..ea4a351 100644 --- a/src/engine/SCons/Scanner/Dir.py +++ b/src/engine/SCons/Scanner/Dir.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,7 +20,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Scanner/Dir.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/Dir.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Node.FS import SCons.Scanner diff --git a/src/engine/SCons/Scanner/DirTests.py b/src/engine/SCons/Scanner/DirTests.py index 12f1844..3ce0fa1 100644 --- a/src/engine/SCons/Scanner/DirTests.py +++ b/src/engine/SCons/Scanner/DirTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,14 +21,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/DirTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/DirTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import sys import unittest import TestCmd -import TestUnit import SCons.Node.FS import SCons.Scanner.Dir @@ -121,14 +120,8 @@ class DirEntryScannerTestCase(DirScannerTestBase): sss = list(map(str, deps)) assert sss == [], sss -def suite(): - suite = unittest.TestSuite() - suite.addTest(DirScannerTestCase()) - suite.addTest(DirEntryScannerTestCase()) - return suite - if __name__ == "__main__": - TestUnit.run(suite()) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Scanner/Fortran.py b/src/engine/SCons/Scanner/Fortran.py index 8a8f3eb..0431660 100644 --- a/src/engine/SCons/Scanner/Fortran.py +++ b/src/engine/SCons/Scanner/Fortran.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for Fortran code. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ This module implements the dependency scanner for Fortran code. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Scanner/Fortran.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/Fortran.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import re @@ -78,7 +78,7 @@ class F90Scanner(SCons.Scanner.Classic): def scan(self, node, env, path=()): # cache the includes list in node so we only scan it once: - if node.includes != None: + if node.includes is not None: mods_and_includes = node.includes else: # retrieve all included filenames diff --git a/src/engine/SCons/Scanner/FortranTests.py b/src/engine/SCons/Scanner/FortranTests.py index 4194018..08072aa 100644 --- a/src/engine/SCons/Scanner/FortranTests.py +++ b/src/engine/SCons/Scanner/FortranTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/FortranTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/FortranTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path @@ -258,7 +258,7 @@ class DummyEnvironment(object): def deps_match(self, deps, headers): scanned = list(map(os.path.normpath, list(map(str, deps)))) expect = list(map(os.path.normpath, headers)) - self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) + self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) # define some tests: diff --git a/src/engine/SCons/Scanner/IDL.py b/src/engine/SCons/Scanner/IDL.py index 706ff41..52bd1c5 100644 --- a/src/engine/SCons/Scanner/IDL.py +++ b/src/engine/SCons/Scanner/IDL.py @@ -6,7 +6,7 @@ Definition Language) files. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Definition Language) files. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/IDL.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/IDL.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Node.FS import SCons.Scanner diff --git a/src/engine/SCons/Scanner/IDLTests.py b/src/engine/SCons/Scanner/IDLTests.py index f1b64c0..6ad35c5 100644 --- a/src/engine/SCons/Scanner/IDLTests.py +++ b/src/engine/SCons/Scanner/IDLTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/IDLTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/IDLTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import unittest import sys @@ -159,7 +159,7 @@ test.write(['work', 'src', 'fff.c'], """ #include <iii.idl> #include <jjj.idl> -int main() +int main(void) { return 0; } @@ -168,7 +168,7 @@ int main() test.write([ 'work', 'src', 'aaa.c'], """ #include "bbb.idl" -int main() +int main(void) { return 0; } @@ -179,7 +179,7 @@ test.write([ 'work', 'src', 'bbb.idl'], "\n") test.write([ 'repository', 'src', 'ccc.c'], """ #include "ddd.idl" -int main() +int main(void) { return 0; } @@ -243,7 +243,7 @@ if os.path.normcase('foo') == os.path.normcase('FOO'): def deps_match(self, deps, headers): scanned = list(map(my_normpath, list(map(str, deps)))) expect = list(map(my_normpath, headers)) - self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) + self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) # define some tests: diff --git a/src/engine/SCons/Scanner/LaTeX.py b/src/engine/SCons/Scanner/LaTeX.py index 69154bd..0385ca0 100644 --- a/src/engine/SCons/Scanner/LaTeX.py +++ b/src/engine/SCons/Scanner/LaTeX.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for LaTeX code. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This module implements the dependency scanner for LaTeX code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/LaTeX.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/LaTeX.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import re @@ -128,8 +128,8 @@ class LaTeX(SCons.Scanner.Base): Unlike most scanners, which use regular expressions that just return the included file name, this returns a tuple consisting of the keyword for the inclusion ("include", "includegraphics", - "input", or "bibliography"), and then the file name itself. - Based on a quick look at LaTeX documentation, it seems that we + "input", or "bibliography"), and then the file name itself. + Based on a quick look at LaTeX documentation, it seems that we should append .tex suffix for the "include" keywords, append .tex if there is no extension for the "input" keyword, and need to add .bib for the "bibliography" keyword that does not accept extensions by itself. @@ -137,7 +137,7 @@ class LaTeX(SCons.Scanner.Base): Finally, if there is no extension for an "includegraphics" keyword latex will append .ps or .eps to find the file, while pdftex may use .pdf, .jpg, .tif, .mps, or .png. - + The actual subset and search order may be altered by DeclareGraphicsExtensions command. This complication is ignored. The default order corresponds to experimentation with teTeX:: @@ -333,7 +333,7 @@ class LaTeX(SCons.Scanner.Base): line_continues_a_comment = False for line in text.splitlines(): line,comment = self.comment_re.findall(line)[0] - if line_continues_a_comment == True: + if line_continues_a_comment: out[-1] = out[-1] + line.lstrip() else: out.append(line) @@ -349,7 +349,7 @@ class LaTeX(SCons.Scanner.Base): # path_dict = dict(list(path)) # add option for whitespace (\s) before the '[' noopt_cre = re.compile('\s*\[.*$') - if node.includes != None: + if node.includes is not None: includes = node.includes else: text = self.canonical_text(node.get_text_contents()) @@ -386,8 +386,8 @@ class LaTeX(SCons.Scanner.Base): directory of the main file just as latex does""" path_dict = dict(list(path)) - - queue = [] + + queue = [] queue.extend( self.scan(node) ) seen = {} @@ -402,7 +402,7 @@ class LaTeX(SCons.Scanner.Base): source_dir = node.get_dir() #for include in includes: while queue: - + include = queue.pop() inc_type, inc_subdir, inc_filename = include diff --git a/src/engine/SCons/Scanner/LaTeXTests.py b/src/engine/SCons/Scanner/LaTeXTests.py index 93729d4..4f8ec16 100644 --- a/src/engine/SCons/Scanner/LaTeXTests.py +++ b/src/engine/SCons/Scanner/LaTeXTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/LaTeXTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/LaTeXTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -31,14 +31,13 @@ import sys import unittest import TestCmd -import TestUnit import SCons.Node.FS import SCons.Scanner.LaTeX test = TestCmd.TestCmd(workdir = '') -test.write('test1.latex',""" +test.write('test1.latex',r""" \include{inc1} \input{inc2} include{incNO} @@ -52,12 +51,12 @@ xyzzy \include{inc6} \subinputfrom{subdir}{inc3e} """) -test.write('test2.latex',""" +test.write('test2.latex',r""" \include{inc1} \include{inc3} """) -test.write('test3.latex',""" +test.write('test3.latex',r""" \includegraphics{inc4.eps} \includegraphics[width=60mm]{inc5.xyz} """) @@ -123,7 +122,7 @@ 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.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) + self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) class LaTeXScannerTestCase1(unittest.TestCase): @@ -156,16 +155,8 @@ class LaTeXScannerTestCase3(unittest.TestCase): files = ['inc5.xyz', 'subdir/inc4.eps'] deps_match(self, deps, files) - -def suite(): - suite = unittest.TestSuite() - suite.addTest(LaTeXScannerTestCase1()) - suite.addTest(LaTeXScannerTestCase2()) - suite.addTest(LaTeXScannerTestCase3()) - return suite - if __name__ == "__main__": - TestUnit.run(suite()) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Scanner/Prog.py b/src/engine/SCons/Scanner/Prog.py index 63d5a38..cabe6af 100644 --- a/src/engine/SCons/Scanner/Prog.py +++ b/src/engine/SCons/Scanner/Prog.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/Prog.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/Prog.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Node import SCons.Node.FS diff --git a/src/engine/SCons/Scanner/ProgTests.py b/src/engine/SCons/Scanner/ProgTests.py index 1f4dfb5..619f844 100644 --- a/src/engine/SCons/Scanner/ProgTests.py +++ b/src/engine/SCons/Scanner/ProgTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,14 +21,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/ProgTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/ProgTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import sys import unittest import TestCmd -import TestUnit import SCons.Node.FS import SCons.Scanner.Prog @@ -274,7 +273,7 @@ def suite(): return suite if __name__ == "__main__": - TestUnit.run(suite()) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Scanner/RC.py b/src/engine/SCons/Scanner/RC.py index 4202362..ccd7ebd 100644 --- a/src/engine/SCons/Scanner/RC.py +++ b/src/engine/SCons/Scanner/RC.py @@ -6,7 +6,7 @@ Definition Language) files. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Definition Language) files. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/RC.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/RC.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import re diff --git a/src/engine/SCons/Scanner/RCTests.py b/src/engine/SCons/Scanner/RCTests.py index fa0a9b4..3012350 100644 --- a/src/engine/SCons/Scanner/RCTests.py +++ b/src/engine/SCons/Scanner/RCTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/RCTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/RCTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import unittest import sys @@ -29,7 +29,6 @@ import collections import os import TestCmd -import TestUnit import SCons.Scanner.RC import SCons.Node.FS @@ -117,7 +116,7 @@ if os.path.normcase('foo') == os.path.normcase('FOO'): def deps_match(self, deps, headers): scanned = sorted(map(my_normpath, list(map(str, deps)))) expect = sorted(map(my_normpath, headers)) - self.failUnless(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) + self.assertTrue(scanned == expect, "expect %s != scanned %s" % (expect, scanned)) # define some tests: @@ -167,7 +166,7 @@ def suite(): return suite if __name__ == "__main__": - TestUnit.run(suite()) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Scanner/SWIG.py b/src/engine/SCons/Scanner/SWIG.py index 048574c..777474c 100644 --- a/src/engine/SCons/Scanner/SWIG.py +++ b/src/engine/SCons/Scanner/SWIG.py @@ -5,7 +5,7 @@ This module implements the dependency scanner for SWIG code. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This module implements the dependency scanner for SWIG code. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/SWIG.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/SWIG.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Scanner diff --git a/src/engine/SCons/Scanner/ScannerTests.py b/src/engine/SCons/Scanner/ScannerTests.py index a962a4c..7e2720c 100644 --- a/src/engine/SCons/Scanner/ScannerTests.py +++ b/src/engine/SCons/Scanner/ScannerTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,7 +20,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Scanner/ScannerTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/ScannerTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -132,16 +132,16 @@ class BaseTestCase(unittest.TestCase): scanned = scanner(filename, env, path) scanned_strs = [str(x) for x in scanned] - self.failUnless(self.filename == filename, "the filename was passed incorrectly") - self.failUnless(self.env == env, "the environment was passed incorrectly") - self.failUnless(scanned_strs == deps, "the dependencies were returned incorrectly") + self.assertTrue(self.filename == filename, "the filename was passed incorrectly") + self.assertTrue(self.env == env, "the environment was passed incorrectly") + self.assertTrue(scanned_strs == deps, "the dependencies were returned incorrectly") for d in scanned: - self.failUnless(not isinstance(d, str), "got a string in the dependencies") + self.assertTrue(not isinstance(d, str), "got a string in the dependencies") if len(args) > 0: - self.failUnless(self.arg == args[0], "the argument was passed incorrectly") + self.assertTrue(self.arg == args[0], "the argument was passed incorrectly") else: - self.failIf(hasattr(self, "arg"), "an argument was given when it shouldn't have been") + self.assertFalse(hasattr(self, "arg"), "an argument was given when it shouldn't have been") def test___call__dict(self): """Test calling Scanner.Base objects with a dictionary""" @@ -245,7 +245,7 @@ class BaseTestCase(unittest.TestCase): dict[s] = 777 i = hash(id(s)) h = hash(list(dict.keys())[0]) - self.failUnless(h == i, + self.assertTrue(h == i, "hash Scanner base class expected %s, got %s" % (i, h)) def test_scan_check(self): @@ -260,7 +260,7 @@ class BaseTestCase(unittest.TestCase): self.checked = {} path = s.path(env) scanned = s(DummyNode('x'), env, path) - self.failUnless(self.checked['x'] == 1, + self.assertTrue(self.checked['x'] == 1, "did not call check function") def test_recursive(self): @@ -269,42 +269,42 @@ class BaseTestCase(unittest.TestCase): s = SCons.Scanner.Base(function = self.func) n = s.recurse_nodes(nodes) - self.failUnless(n == [], + self.assertTrue(n == [], "default behavior returned nodes: %s" % n) s = SCons.Scanner.Base(function = self.func, recursive = None) n = s.recurse_nodes(nodes) - self.failUnless(n == [], + self.assertTrue(n == [], "recursive = None returned nodes: %s" % n) s = SCons.Scanner.Base(function = self.func, recursive = 1) n = s.recurse_nodes(nodes) - self.failUnless(n == n, + self.assertTrue(n == n, "recursive = 1 didn't return all nodes: %s" % n) def odd_only(nodes): return [n for n in nodes if n % 2] s = SCons.Scanner.Base(function = self.func, recursive = odd_only) n = s.recurse_nodes(nodes) - self.failUnless(n == [1, 3], + self.assertTrue(n == [1, 3], "recursive = 1 didn't return all nodes: %s" % n) def test_get_skeys(self): """Test the Scanner.Base get_skeys() method""" s = SCons.Scanner.Base(function = self.func) sk = s.get_skeys() - self.failUnless(sk == [], + self.assertTrue(sk == [], "did not initialize to expected []") s = SCons.Scanner.Base(function = self.func, skeys = ['.1', '.2']) sk = s.get_skeys() - self.failUnless(sk == ['.1', '.2'], + self.assertTrue(sk == ['.1', '.2'], "sk was %s, not ['.1', '.2']") s = SCons.Scanner.Base(function = self.func, skeys = '$LIST') env = DummyEnvironment(LIST = ['.3', '.4']) sk = s.get_skeys(env) - self.failUnless(sk == ['.3', '.4'], + self.assertTrue(sk == ['.3', '.4'], "sk was %s, not ['.3', '.4']") def test_select(self): @@ -432,19 +432,19 @@ class CurrentTestCase(unittest.TestCase): path = s.path(env) hnb = HasNoBuilder() s(hnb, env, path) - self.failUnless(hnb.called_has_builder, "did not call has_builder()") - self.failUnless(not hnb.called_is_up_to_date, "did call is_up_to_date()") - self.failUnless(hnb.func_called, "did not call func()") + self.assertTrue(hnb.called_has_builder, "did not call has_builder()") + self.assertTrue(not hnb.called_is_up_to_date, "did call is_up_to_date()") + self.assertTrue(hnb.func_called, "did not call func()") inc = IsNotCurrent() s(inc, env, path) - self.failUnless(inc.called_has_builder, "did not call has_builder()") - self.failUnless(inc.called_is_up_to_date, "did not call is_up_to_date()") - self.failUnless(not inc.func_called, "did call func()") + self.assertTrue(inc.called_has_builder, "did not call has_builder()") + self.assertTrue(inc.called_is_up_to_date, "did not call is_up_to_date()") + self.assertTrue(not inc.func_called, "did call func()") ic = IsCurrent() s(ic, env, path) - self.failUnless(ic.called_has_builder, "did not call has_builder()") - self.failUnless(ic.called_is_up_to_date, "did not call is_up_to_date()") - self.failUnless(ic.func_called, "did not call func()") + self.assertTrue(ic.called_has_builder, "did not call has_builder()") + self.assertTrue(ic.called_is_up_to_date, "did not call is_up_to_date()") + self.assertTrue(ic.func_called, "did not call func()") class ClassicTestCase(unittest.TestCase): @@ -461,7 +461,7 @@ class ClassicTestCase(unittest.TestCase): def test_find_include(self): """Test the Scanner.Classic find_include() method""" env = DummyEnvironment() - s = SCons.Scanner.Classic("t", ['.suf'], 'MYPATH', '^my_inc (\S+)') + s = SCons.Scanner.Classic("t", ['.suf'], 'MYPATH', r'^my_inc (\S+)') def _find_file(filename, paths): return paths[0]+'/'+filename @@ -479,7 +479,7 @@ class ClassicTestCase(unittest.TestCase): def test_name(self): """Test setting the Scanner.Classic name""" - s = SCons.Scanner.Classic("my_name", ['.s'], 'MYPATH', '^my_inc (\S+)') + s = SCons.Scanner.Classic("my_name", ['.s'], 'MYPATH', r'^my_inc (\S+)') assert s.name == "my_name", s.name def test_scan(self): @@ -505,7 +505,7 @@ class ClassicTestCase(unittest.TestCase): return include, include env = DummyEnvironment() - s = MyScanner("t", ['.suf'], 'MYPATH', '^my_inc (\S+)') + s = MyScanner("t", ['.suf'], 'MYPATH', r'^my_inc (\S+)') # This set of tests is intended to test the scanning operation # of the Classic scanner. @@ -566,7 +566,7 @@ class ClassicTestCase(unittest.TestCase): s = SCons.Scanner.Classic("Test", [], None, "", function=self.func, recursive=1) n = s.recurse_nodes(nodes) - self.failUnless(n == n, + self.assertTrue(n == n, "recursive = 1 didn't return all nodes: %s" % n) def odd_only(nodes): @@ -574,7 +574,7 @@ class ClassicTestCase(unittest.TestCase): s = SCons.Scanner.Classic("Test", [], None, "", function=self.func, recursive=odd_only) n = s.recurse_nodes(nodes) - self.failUnless(n == [1, 3], + self.assertTrue(n == [1, 3], "recursive = 1 didn't return all nodes: %s" % n) diff --git a/src/engine/SCons/Scanner/__init__.py b/src/engine/SCons/Scanner/__init__.py index 73e8c09..693fae7 100644 --- a/src/engine/SCons/Scanner/__init__.py +++ b/src/engine/SCons/Scanner/__init__.py @@ -5,7 +5,7 @@ The Scanner package for the SCons software construction utility. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ The Scanner package for the SCons software construction utility. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Scanner/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Scanner/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import re diff --git a/src/engine/SCons/Scanner/__init__.xml b/src/engine/SCons/Scanner/__init__.xml index db2d14b..436d806 100644 --- a/src/engine/SCons/Scanner/__init__.xml +++ b/src/engine/SCons/Scanner/__init__.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Script/Interactive.py b/src/engine/SCons/Script/Interactive.py index dee770c..35e32c2 100644 --- a/src/engine/SCons/Script/Interactive.py +++ b/src/engine/SCons/Script/Interactive.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function -__revision__ = "src/engine/SCons/Script/Interactive.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Script/Interactive.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """ SCons interactive mode diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 076c30b..0d626cb 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -17,7 +17,7 @@ unsupported_python_version = (2, 6, 0) deprecated_python_version = (2, 7, 0) -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -38,7 +38,7 @@ deprecated_python_version = (2, 7, 0) # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Script/Main.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Script/Main.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -48,6 +48,7 @@ import sys import time import traceback import sysconfig +import platform import SCons.CacheDir import SCons.Debug @@ -58,6 +59,7 @@ import SCons.Job import SCons.Node import SCons.Node.FS import SCons.Platform +import SCons.Platform.virtualenv import SCons.SConf import SCons.Script import SCons.Taskmaster @@ -622,7 +624,7 @@ def _SConstruct_exists(dirname='', repositories=[], filelist=None): current directory. """ if not filelist: - filelist = ['SConstruct', 'Sconstruct', 'sconstruct'] + filelist = ['SConstruct', 'Sconstruct', 'sconstruct', 'SConstruct.py', 'Sconstruct.py', 'sconstruct.py'] for file in filelist: sfile = os.path.join(dirname, file) if os.path.isfile(sfile): @@ -862,6 +864,13 @@ def _main(parser): for warning_type, message in delayed_warnings: SCons.Warnings.warn(warning_type, message) + if not SCons.Platform.virtualenv.virtualenv_enabled_by_default: + if options.enable_virtualenv: + SCons.Platform.virtualenv.enable_virtualenv = True + + if options.ignore_virtualenv: + SCons.Platform.virtualenv.ignore_virtualenv = True + if options.diskcheck: SCons.Node.FS.set_diskcheck(options.diskcheck) @@ -1253,7 +1262,11 @@ def _build_targets(fs, options, targets, target_top): BuildTask.options = options - python_has_threads = sysconfig.get_config_var('WITH_THREAD') + is_pypy = platform.python_implementation() == 'PyPy' + # As of 3.7, python removed support for threadless platforms. + # See https://www.python.org/dev/peps/pep-0011/ + is_37_or_later = sys.version_info >= (3, 7) + python_has_threads = sysconfig.get_config_var('WITH_THREAD') or is_pypy or is_37_or_later # to check if python configured with threads. global num_jobs num_jobs = options.num_jobs @@ -1347,7 +1360,7 @@ def main(): pass parts.append(version_string("engine", SCons)) parts.append(path_string("engine", SCons)) - parts.append("Copyright (c) 2001 - 2017 The SCons Foundation") + parts.append("Copyright (c) 2001 - 2019 The SCons Foundation") version = ''.join(parts) from . import SConsOptions @@ -1363,7 +1376,7 @@ def main(): revert_io() except SystemExit as s: if s: - exit_status = s + exit_status = s.code except KeyboardInterrupt: print("scons: Build interrupted.") sys.exit(2) diff --git a/src/engine/SCons/Script/Main.xml b/src/engine/SCons/Script/Main.xml index 73db83e..c1c4bde 100644 --- a/src/engine/SCons/Script/Main.xml +++ b/src/engine/SCons/Script/Main.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Script/MainTests.py b/src/engine/SCons/Script/MainTests.py index f5660b0..64d3e0f 100644 --- a/src/engine/SCons/Script/MainTests.py +++ b/src/engine/SCons/Script/MainTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,12 +21,10 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/MainTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Script/MainTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import unittest -import TestUnit - import SCons.Errors import SCons.Script.Main @@ -41,12 +39,7 @@ import SCons.Script.Main # of private functionality. if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Script/SConsOptions.py b/src/engine/SCons/Script/SConsOptions.py index 5515c7d..8f31fd8 100644 --- a/src/engine/SCons/Script/SConsOptions.py +++ b/src/engine/SCons/Script/SConsOptions.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/SConsOptions.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Script/SConsOptions.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import optparse import re @@ -38,6 +38,7 @@ except ImportError: _ = gettext import SCons.Node.FS +import SCons.Platform.virtualenv import SCons.Warnings OptionValueError = optparse.OptionValueError @@ -706,6 +707,12 @@ def Parser(version): action="callback", callback=opt_duplicate, help=opt_duplicate_help) + if not SCons.Platform.virtualenv.virtualenv_enabled_by_default: + op.add_option('--enable-virtualenv', + dest="enable_virtualenv", + action="store_true", + help="Import certain virtualenv variables to SCons") + op.add_option('-f', '--file', '--makefile', '--sconstruct', nargs=1, type="string", dest="file", default=[], @@ -733,6 +740,11 @@ def Parser(version): help="Search DIR for imported Python modules.", metavar="DIR") + op.add_option('--ignore-virtualenv', + dest="ignore_virtualenv", + action="store_true", + help="Do not import virtualenv variables to SCons") + op.add_option('--implicit-cache', dest='implicit_cache', default=False, action="store_true", @@ -906,6 +918,7 @@ def Parser(version): action="append", help="Search REPOSITORY for source and target files.") + # Options from Make and Cons classic that we do not yet support, # but which we may support someday and whose (potential) meanings # we don't want to change. These all get a "the -X option is not @@ -978,7 +991,6 @@ def Parser(version): action="callback", callback=opt_not_yet, # help="Warn when an undefined variable is referenced." help=SUPPRESS_HELP) - return op # Local Variables: diff --git a/src/engine/SCons/Script/SConscript.py b/src/engine/SCons/Script/SConscript.py index 350772e..ea239e0 100644 --- a/src/engine/SCons/Script/SConscript.py +++ b/src/engine/SCons/Script/SConscript.py @@ -5,10 +5,8 @@ files. """ -from __future__ import print_function - # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +27,7 @@ from __future__ import print_function # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Script/SConscript.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Script/SConscript.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons import SCons.Action @@ -46,12 +44,15 @@ import SCons.Script.Main import SCons.Tool import SCons.Util +from . import Main + import collections import os import os.path import re import sys import traceback +import time class SConscriptReturn(Exception): pass @@ -152,6 +153,35 @@ def Return(*vars, **kw): stack_bottom = '% Stack boTTom %' # hard to define a variable w/this name :) +def handle_missing_SConscript(f, must_exist=None): + """Take appropriate action on missing file in SConscript() call. + + Print a warning or raise an exception on missing file. + On first warning, print a deprecation message. + + Args: + f (str): path of missing configuration file + must_exist (bool): raise exception if file does not exist + + Raises: + UserError if 'must_exist' is True or if global + SCons.Script._no_missing_sconscript is True. + """ + + if must_exist or (SCons.Script._no_missing_sconscript and must_exist is not False): + msg = "Fatal: missing SConscript '%s'" % f.get_internal_path() + raise SCons.Errors.UserError(msg) + + if SCons.Script._warn_missing_sconscript_deprecated: + msg = "Calling missing SConscript without error is deprecated.\n" + \ + "Transition by adding must_exist=0 to SConscript calls.\n" + \ + "Missing SConscript '%s'" % f.get_internal_path() + SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning, msg) + SCons.Script._warn_missing_sconscript_deprecated = False + else: + msg = "Ignoring missing SConscript '%s'" % f.get_internal_path() + SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning, msg) + def _SConscript(fs, *files, **kw): top = fs.Top sd = fs.SConstruct_dir.rdir() @@ -248,17 +278,23 @@ def _SConscript(fs, *files, **kw): pass try: try: -# _file_ = SCons.Util.to_str(_file_) - exec(compile(_file_.read(), _file_.name, 'exec'), - call_stack[-1].globals) + if Main.print_time: + time1 = time.time() + scriptdata = _file_.read() + scriptname = _file_.name + _file_.close() + exec(compile(scriptdata, scriptname, 'exec'), call_stack[-1].globals) except SConscriptReturn: pass finally: + if Main.print_time: + time2 = time.time() + print('SConscript:%s took %0.3f ms' % (f.get_abspath(), (time2 - time1) * 1000.0)) + if old_file is not None: call_stack[-1].globals.update({__file__:old_file}) else: - SCons.Warnings.warn(SCons.Warnings.MissingSConscriptWarning, - "Ignoring missing SConscript '%s'" % f.get_internal_path()) + handle_missing_SConscript(f, kw.get('must_exist', None)) finally: SCons.Script.sconscript_reading = SCons.Script.sconscript_reading - 1 @@ -362,9 +398,9 @@ class SConsEnvironment(SCons.Environment.Base): something like 3.2b1.""" version = version_string.split(' ')[0].split('.') v_major = int(version[0]) - v_minor = int(re.match('\d+', version[1]).group()) + v_minor = int(re.match(r'\d+', version[1]).group()) if len(version) >= 3: - v_revision = int(re.match('\d+', version[2]).group()) + v_revision = int(re.match(r'\d+', version[2]).group()) else: v_revision = 0 return v_major, v_minor, v_revision @@ -516,6 +552,31 @@ class SConsEnvironment(SCons.Environment.Base): raise SCons.Errors.UserError("Import of non-existent variable '%s'"%x) def SConscript(self, *ls, **kw): + """Execute SCons configuration files. + + Parameters: + *ls (str or list): configuration file(s) to execute. + + Keyword arguments: + dirs (list): execute SConscript in each listed directory. + name (str): execute script 'name' (used only with 'dirs'). + exports (list or dict): locally export variables the + called script(s) can import. + variant_dir (str): mirror sources needed for the build in + a variant directory to allow building in it. + duplicate (bool): physically duplicate sources instead of just + adjusting paths of derived files (used only with 'variant_dir') + (default is True). + must_exist (bool): fail if a requested script is missing + (default is False, default is deprecated). + + Returns: + list of variables returned by the called script + + Raises: + UserError: a script is not found and such exceptions are enabled. + """ + if 'build_dir' in kw: msg = """The build_dir keyword has been deprecated; use the variant_dir keyword instead.""" SCons.Warnings.warn(SCons.Warnings.DeprecatedBuildDirWarning, msg) diff --git a/src/engine/SCons/Script/SConscript.xml b/src/engine/SCons/Script/SConscript.xml index e6be6d2..2d77aa3 100644 --- a/src/engine/SCons/Script/SConscript.xml +++ b/src/engine/SCons/Script/SConscript.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -38,6 +38,10 @@ Multiple calls to &f-Default; are legal, and add to the list of default targets. +As noted above, both forms of this call affect the +same global list of default targets; the +construction environment method applies +construction variable expansion to the targets. </para> <para> @@ -357,12 +361,12 @@ Return('val1 val2') <scons_function name="SConscript"> <arguments> -(scripts, [exports, variant_dir, duplicate]) -<!-- (scripts, [exports, variant_dir, src_dir, duplicate]) --> +(scripts, [exports, variant_dir, duplicate, must_exist]) +<!-- (scripts, [exports, variant_dir, src_dir, duplicate, must_exist]) --> </arguments> <arguments> -(dirs=subdirs, [name=script, exports, variant_dir, duplicate]) -<!-- (dirs=subdirs, [name=script, exports, variant_dir, src_dir, duplicate]) --> +(dirs=subdirs, [name=script, exports, variant_dir, duplicate, must_exist]) +<!-- (dirs=subdirs, [name=script, exports, variant_dir, src_dir, duplicate, must_exist]) --> </arguments> <summary> <para> @@ -564,6 +568,17 @@ TODO??? SConscript('build/SConscript', src_dir='src') </para> <para> +The optional +<varname>must_exist</varname> +argument, if true, causes an exception to be raised if a requested +&SConscript; file is not found. The current default is false, +causing only a warning to be omitted, but this behavior is deprecated. +For scripts which truly intend to be optional, transition to +explicty supplying +<literal>must_exist=False</literal> to the call. +</para> + +<para> Here are some composite examples: </para> diff --git a/src/engine/SCons/Script/SConscriptTests.py b/src/engine/SCons/Script/SConscriptTests.py index 2b10446..fb06ac4 100644 --- a/src/engine/SCons/Script/SConscriptTests.py +++ b/src/engine/SCons/Script/SConscriptTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/SConscriptTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Script/SConscriptTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Script.SConscript diff --git a/src/engine/SCons/Script/__init__.py b/src/engine/SCons/Script/__init__.py index ffafadf..834c70d 100644 --- a/src/engine/SCons/Script/__init__.py +++ b/src/engine/SCons/Script/__init__.py @@ -12,7 +12,7 @@ it goes here. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -34,7 +34,7 @@ it goes here. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Script/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Script/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import time start_time = time.time() @@ -81,8 +81,8 @@ import SCons.Action import SCons.Builder import SCons.Environment import SCons.Node.FS -import SCons.Options import SCons.Platform +import SCons.Platform.virtualenv import SCons.Scanner import SCons.SConf import SCons.Subst @@ -150,6 +150,7 @@ Environment = SCons.Environment.Environment #OptParser = SCons.SConsOptions.OptParser FindPathDirs = SCons.Scanner.FindPathDirs Platform = SCons.Platform.Platform +Virtualenv = SCons.Platform.virtualenv.Virtualenv Return = _SConscript.Return Scanner = SCons.Scanner.Base Tool = SCons.Tool.Tool @@ -162,12 +163,6 @@ ListVariable = SCons.Variables.ListVariable PackageVariable = SCons.Variables.PackageVariable PathVariable = SCons.Variables.PathVariable -# Deprecated names that will go away some day. -BoolOption = SCons.Options.BoolOption -EnumOption = SCons.Options.EnumOption -ListOption = SCons.Options.ListOption -PackageOption = SCons.Options.PackageOption -PathOption = SCons.Options.PathOption # Action factories. Chmod = SCons.Defaults.Chmod @@ -283,12 +278,20 @@ def HelpFunction(text, append=False): # Will be non-zero if we are reading an SConscript file. sconscript_reading = 0 +_no_missing_sconscript = False +_warn_missing_sconscript_deprecated = True + +def set_missing_sconscript_error(flag=1): + """Set behavior on missing file in SConscript() call. Returns previous value""" + global _no_missing_sconscript + old = _no_missing_sconscript + _no_missing_sconscript = flag + return old + # def Variables(files=[], args=ARGUMENTS): return SCons.Variables.Variables(files, args) -def Options(files=[], args=ARGUMENTS): - return SCons.Options.Options(files, args) # The list of global functions to add to the SConscript name space # that end up calling corresponding methods or Builders in the @@ -374,7 +377,9 @@ GlobalDefaultBuilders = [ 'SharedObject', 'StaticLibrary', 'StaticObject', + 'Substfile', 'Tar', + 'Textfile', 'TypeLibrary', 'Zip', 'Package', diff --git a/src/engine/SCons/Subst.py b/src/engine/SCons/Subst.py index 90c12a0..4fc8461 100644 --- a/src/engine/SCons/Subst.py +++ b/src/engine/SCons/Subst.py @@ -5,7 +5,7 @@ SCons string substitution. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ SCons string substitution. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Subst.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Subst.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import collections import re @@ -86,6 +86,9 @@ class Literal(object): def __neq__(self, other): return not self.__eq__(other) + def __hash__(self): + return hash(self.lstr) + class SpecialAttrWrapper(object): """This is a wrapper for what we call a 'Node special attribute.' This is any of the attributes of a Node that we can reference from @@ -338,7 +341,10 @@ SUBST_RAW = 1 SUBST_SIG = 2 _rm = re.compile(r'\$[()]') -_rm_split = re.compile(r'(\$[()])') + +# Note the pattern below only matches $( or $) when there is no +# preceeding $. (Thus the (?<!\$)) +_rm_split = re.compile(r'(?<!\$)(\$[()])') # Indexed by the SUBST_* constants above. _regex_remove = [ _rm, None, _rm_split ] @@ -437,7 +443,11 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ if s0 != '$': return s if s1 == '$': - return '$' + # In this case keep the double $'s which we'll later + # swap for a single dollar sign as we need to retain + # this information to properly avoid matching "$("" when + # the actual text was "$$("" (or "$)"" when "$$)"" ) + return '$$' elif s1 in '()': return s else: @@ -583,6 +593,12 @@ def scons_subst(strSubst, env, mode=SUBST_RAW, target=None, source=None, gvars={ # Compress strings of white space characters into # a single space. result = _space_sep.sub(' ', result).strip() + + # Now replace escaped $'s currently "$$" + # This is needed because we now retain $$ instead of + # replacing them during substition to avoid + # improperly trying to escape "$$(" as being "$(" + result = result.replace('$$','$') elif is_Sequence(result): remove = _list_remove[mode] if remove: diff --git a/src/engine/SCons/Subst.xml b/src/engine/SCons/Subst.xml index a75003f..858ff40 100644 --- a/src/engine/SCons/Subst.xml +++ b/src/engine/SCons/Subst.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/SubstTests.py b/src/engine/SCons/SubstTests.py index 5a85b6c..0da1faf 100644 --- a/src/engine/SCons/SubstTests.py +++ b/src/engine/SCons/SubstTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ # from __future__ import print_function -__revision__ = "src/engine/SCons/SubstTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/SubstTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -32,8 +32,6 @@ import unittest from collections import UserDict -import TestUnit - import SCons.Errors from SCons.Subst import * @@ -336,6 +334,10 @@ class scons_subst_TestCase(SubstTestCase): # Test double-dollar-sign behavior. "$$FFF$HHH", "$FFFIII", + # Test double-dollar-sign before open paren. It's not meant + # to be signature escaping + 'echo $$(pwd) > XYZ', 'echo $(pwd) > XYZ', + # Test that a Literal will stop dollar-sign substitution. "$XXX $LITERAL $FFF", "GGG $XXX GGG", @@ -1239,21 +1241,7 @@ class subst_dict_TestCase(unittest.TestCase): assert SOURCES == ['s3', 'v-rstr-s4', 'v-s5'], SOURCES if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ - CLVar_TestCase, - LiteralTestCase, - SpecialAttrWrapperTestCase, - quote_spaces_TestCase, - scons_subst_TestCase, - scons_subst_list_TestCase, - scons_subst_once_TestCase, - subst_dict_TestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Taskmaster.py b/src/engine/SCons/Taskmaster.py index 8fca4a9..d8d8224 100644 --- a/src/engine/SCons/Taskmaster.py +++ b/src/engine/SCons/Taskmaster.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -54,7 +54,7 @@ __doc__ = """ target(s) that it decides need to be evaluated and/or built. """ -__revision__ = "src/engine/SCons/Taskmaster.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Taskmaster.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from itertools import chain import operator @@ -470,14 +470,23 @@ class Task(object): pending_children.discard(t) for p in t.waiting_parents: parents[p] = parents.get(p, 0) + 1 + t.waiting_parents = set() for t in targets: if t.side_effects is not None: for s in t.side_effects: if s.get_state() == NODE_EXECUTING: s.set_state(NODE_NO_STATE) + + # The side-effects may have been transferred to + # NODE_NO_STATE by executed_with{,out}_callbacks, but was + # not taken out of the waiting parents/pending children + # data structures. Check for that now. + if s.get_state() == NODE_NO_STATE and s.waiting_parents: + pending_children.discard(s) for p in s.waiting_parents: parents[p] = parents.get(p, 0) + 1 + s.waiting_parents = set() for p in s.waiting_s_e: if p.ref_count == 0: self.tm.candidates.append(p) diff --git a/src/engine/SCons/TaskmasterTests.py b/src/engine/SCons/TaskmasterTests.py index fab54cf..d31a8d5 100644 --- a/src/engine/SCons/TaskmasterTests.py +++ b/src/engine/SCons/TaskmasterTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ # from __future__ import division -__revision__ = "src/engine/SCons/TaskmasterTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/TaskmasterTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -30,7 +30,6 @@ import copy import sys import unittest -import TestUnit import SCons.Taskmaster import SCons.Errors @@ -1086,6 +1085,7 @@ class TaskmasterTestCase(unittest.TestCase): exception_values = [ "integer division or modulo", "integer division or modulo by zero", + "integer division by zero", # PyPy2 ] assert str(exc_value) in exception_values, exc_value @@ -1239,8 +1239,7 @@ Taskmaster: No candidate anymore. if __name__ == "__main__": - suite = unittest.makeSuite(TaskmasterTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/386asm.py b/src/engine/SCons/Tool/386asm.py index b318c4b..930b431 100644 --- a/src/engine/SCons/Tool/386asm.py +++ b/src/engine/SCons/Tool/386asm.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/386asm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/386asm.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from SCons.Tool.PharLapCommon import addPharLapPaths import SCons.Util diff --git a/src/engine/SCons/Tool/386asm.xml b/src/engine/SCons/Tool/386asm.xml index 80a2cd6..fe819d2 100644 --- a/src/engine/SCons/Tool/386asm.xml +++ b/src/engine/SCons/Tool/386asm.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/DCommon.py b/src/engine/SCons/Tool/DCommon.py index 8973853..169f95d 100644 --- a/src/engine/SCons/Tool/DCommon.py +++ b/src/engine/SCons/Tool/DCommon.py @@ -9,7 +9,7 @@ Coded by Russel Winder (russel@winder.org.uk) """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ Coded by Russel Winder (russel@winder.org.uk) # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/DCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/DCommon.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path diff --git a/src/engine/SCons/Tool/DCommon.xml b/src/engine/SCons/Tool/DCommon.xml index b1deb82..5103ca1 100644 --- a/src/engine/SCons/Tool/DCommon.xml +++ b/src/engine/SCons/Tool/DCommon.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/FortranCommon.py b/src/engine/SCons/Tool/FortranCommon.py index d2126a4..27646f0 100644 --- a/src/engine/SCons/Tool/FortranCommon.py +++ b/src/engine/SCons/Tool/FortranCommon.py @@ -5,7 +5,7 @@ Stuff for processing Fortran, common to all fortran dialects. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Stuff for processing Fortran, common to all fortran dialects. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/FortranCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/FortranCommon.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import re import os.path diff --git a/src/engine/SCons/Tool/GettextCommon.py b/src/engine/SCons/Tool/GettextCommon.py index b475d8f..8c2163e 100644 --- a/src/engine/SCons/Tool/GettextCommon.py +++ b/src/engine/SCons/Tool/GettextCommon.py @@ -3,7 +3,7 @@ Used by several tools of `gettext` toolset. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Used by several tools of `gettext` toolset. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/GettextCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/GettextCommon.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Warnings import re @@ -390,7 +390,7 @@ def _detect_xgettext(env): """ Detects *xgettext(1)* binary """ if 'XGETTEXT' in env: return env['XGETTEXT'] - xgettext = env.Detect('xgettext'); + xgettext = env.Detect('xgettext') if xgettext: return xgettext raise SCons.Errors.StopError(XgettextNotFound, "Could not detect xgettext") @@ -409,7 +409,7 @@ def _detect_msginit(env): """ Detects *msginit(1)* program. """ if 'MSGINIT' in env: return env['MSGINIT'] - msginit = env.Detect('msginit'); + msginit = env.Detect('msginit') if msginit: return msginit raise SCons.Errors.StopError(MsginitNotFound, "Could not detect msginit") @@ -428,7 +428,7 @@ def _detect_msgmerge(env): """ Detects *msgmerge(1)* program. """ if 'MSGMERGE' in env: return env['MSGMERGE'] - msgmerge = env.Detect('msgmerge'); + msgmerge = env.Detect('msgmerge') if msgmerge: return msgmerge raise SCons.Errors.StopError(MsgmergeNotFound, "Could not detect msgmerge") @@ -447,7 +447,7 @@ def _detect_msgfmt(env): """ Detects *msgmfmt(1)* program. """ if 'MSGFMT' in env: return env['MSGFMT'] - msgfmt = env.Detect('msgfmt'); + msgfmt = env.Detect('msgfmt') if msgfmt: return msgfmt raise SCons.Errors.StopError(MsgfmtNotFound, "Could not detect msgfmt") diff --git a/src/engine/SCons/Tool/JavaCommon.py b/src/engine/SCons/Tool/JavaCommon.py index 5c2507d..2683f03 100644 --- a/src/engine/SCons/Tool/JavaCommon.py +++ b/src/engine/SCons/Tool/JavaCommon.py @@ -5,7 +5,7 @@ Stuff for processing Java. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,16 +27,21 @@ Stuff for processing Java. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/JavaCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/JavaCommon.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path import re +import glob java_parsing = 1 default_java_version = '1.4' +# a switch for which jdk versions to use the Scope state for smarter +# anonymous inner class parsing. +scopeStateVersions = ('1.8') + if java_parsing: # Parse Java files for class names. # @@ -64,8 +69,9 @@ if java_parsing: interfaces, and anonymous inner classes.""" def __init__(self, version=default_java_version): - if not version in ('1.1', '1.2', '1.3','1.4', '1.5', '1.6', '1.7', - '1.8', '5', '6'): + if not version in ('1.1', '1.2', '1.3', '1.4', '1.5', '1.6', '1.7', + '1.8', '5', '6', '9.0', '10.0', '11.0'): + msg = "Java version %s not supported" % version raise NotImplementedError(msg) @@ -115,8 +121,8 @@ if java_parsing: ret = SkipState(1, self) self.skipState = ret return ret - - def __getAnonStack(self): + + def _getAnonStack(self): return self.anonStacksStack[-1] def openBracket(self): @@ -125,15 +131,16 @@ if java_parsing: def closeBracket(self): self.brackets = self.brackets - 1 if len(self.stackBrackets) and \ - self.brackets == self.stackBrackets[-1]: + self.brackets == self.stackBrackets[-1]: self.listOutputs.append('$'.join(self.listClasses)) self.localClasses.pop() self.listClasses.pop() self.anonStacksStack.pop() self.stackBrackets.pop() if len(self.stackAnonClassBrackets) and \ - self.brackets == self.stackAnonClassBrackets[-1]: - self.__getAnonStack().pop() + self.brackets == self.stackAnonClassBrackets[-1] and \ + self.version not in scopeStateVersions: + self._getAnonStack().pop() self.stackAnonClassBrackets.pop() def parseToken(self, token): @@ -171,21 +178,87 @@ if java_parsing: if self.version in ('1.1', '1.2', '1.3', '1.4'): clazz = self.listClasses[0] self.listOutputs.append('%s$%d' % (clazz, self.nextAnon)) - elif self.version in ('1.5', '1.6', '1.7', '1.8', '5', '6'): + elif self.version in ('1.5', '1.6', '1.7', '1.8', '5', '6', '9.0', '10.0', '11.0'): self.stackAnonClassBrackets.append(self.brackets) className = [] className.extend(self.listClasses) - self.__getAnonStack()[-1] = self.__getAnonStack()[-1] + 1 - for anon in self.__getAnonStack(): + self._getAnonStack()[-1] = self._getAnonStack()[-1] + 1 + for anon in self._getAnonStack(): className.append(str(anon)) self.listOutputs.append('$'.join(className)) self.nextAnon = self.nextAnon + 1 - self.__getAnonStack().append(0) + self._getAnonStack().append(0) def setPackage(self, package): self.package = package + class ScopeState(object): + """ + A state that parses code within a scope normally, + within the confines of a scope. + """ + def __init__(self, old_state): + self.outer_state = old_state.outer_state + self.old_state = old_state + self.brackets = 0 + + def __getClassState(self): + try: + return self.classState + except AttributeError: + ret = ClassState(self) + self.classState = ret + return ret + + def __getAnonClassState(self): + try: + return self.anonState + except AttributeError: + ret = SkipState(1, AnonClassState(self)) + self.anonState = ret + return ret + + def __getSkipState(self): + try: + return self.skipState + except AttributeError: + ret = SkipState(1, self) + self.skipState = ret + return ret + + def openBracket(self): + self.brackets = self.brackets + 1 + + def closeBracket(self): + self.brackets = self.brackets - 1 + + def parseToken(self, token): + # if self.brackets == 0: + # return self.old_state.parseToken(token) + if token[:2] == '//': + return IgnoreState('\n', self) + elif token == '/*': + return IgnoreState('*/', self) + elif token == '{': + self.openBracket() + elif token == '}': + self.closeBracket() + if self.brackets == 0: + self.outer_state._getAnonStack().pop() + return self.old_state + elif token in ['"', "'"]: + return IgnoreState(token, self) + elif token == "new": + # anonymous inner class + return self.__getAnonClassState() + elif token == '.': + # Skip the attribute, it might be named "class", in which + # case we don't want to treat the following token as + # an inner class name... + return self.__getSkipState() + return self + class AnonClassState(object): """A state that looks for anonymous inner classes.""" def __init__(self, old_state): @@ -212,13 +285,15 @@ if java_parsing: if token == 'new': # look further for anonymous inner class return SkipState(1, AnonClassState(self)) - elif token in [ '"', "'" ]: + elif token in ['"', "'"]: return IgnoreState(token, self) elif token == ')': self.brace_level = self.brace_level - 1 return self if token == '{': self.outer_state.addAnonClass() + if self.outer_state.version in scopeStateVersions: + return ScopeState(old_state = self.old_state).parseToken(token) return self.old_state.parseToken(token) class SkipState(object): @@ -245,10 +320,10 @@ if java_parsing: # If that's an inner class which is declared in a method, it # requires an index prepended to the class-name, e.g. # 'Foo$1Inner' - # http://scons.tigris.org/issues/show_bug.cgi?id=2087 + # https://github.com/SCons/scons/issues/2087 if self.outer_state.localClasses and \ - self.outer_state.stackBrackets[-1] > \ - self.outer_state.stackBrackets[-2]+1: + self.outer_state.stackBrackets[-1] > \ + self.outer_state.stackBrackets[-2]+1: locals = self.outer_state.localClasses[-1] try: idx = locals[token] @@ -283,7 +358,9 @@ if java_parsing: return self.outer_state def parse_java_file(fn, version=default_java_version): - return parse_java(open(fn, 'r').read(), version) + with open(fn, 'r') as f: + data = f.read() + return parse_java(data, version) def parse_java(contents, version=default_java_version, trace=None): """Parse a .java file and return a double of package directory, @@ -315,7 +392,84 @@ else: is that the file name matches the public class name, and that the path to the file is the same as the package name. """ - return os.path.split(file) + return os.path.split(fn) + + + +java_win32_version_dir_glob = 'C:/Program Files*/Java/jdk%s*/bin' +java_win32_dir_glob = 'C:/Program Files*/Java/jdk*/bin' + +java_macos_include_dir = '/System/Library/Frameworks/JavaVM.framework/Headers/' +java_macos_version_include_dir = '/System/Library/Frameworks/JavaVM.framework/Versions/%s*/Headers/' + +java_linux_include_dirs = ['/usr/lib/jvm/default-java/include', + '/usr/lib/jvm/java-*/include'] +# Need to match path like below (from Centos 7) +# /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.191.b12-0.el7_5.x86_64/include/ +java_linux_version_include_dirs = ['/usr/lib/jvm/java-*-sun-%s*/include', + '/usr/lib/jvm/java-%s*-openjdk*/include', + '/usr/java/jdk%s*/include'] + + + +def get_java_install_dirs(platform, version=None): + """ + Using patterns above find the java jdk install dir + :param platform: + :param version: If specified, only look for java sdk's of this version + :return: list of default paths for java. + """ + paths = [] + if platform == 'win32': + if version: + paths = glob.glob(java_win32_version_dir_glob%version) + else: + paths = glob.glob(java_win32_dir_glob) + else: + # do nothing for now + pass + + paths=sorted(paths) + + return paths + +def get_java_include_paths(env, javac, version): + """ + Return java include paths + :param platform: + :param javac: + :return: + """ + paths = [] + if not javac: + # there are no paths if we've not detected javac. + pass + elif env['PLATFORM'] == 'win32': + javac_bin_dir = os.path.dirname(javac) + java_inc_dir = os.path.normpath(os.path.join(javac_bin_dir, '..', 'include')) + paths = [java_inc_dir, os.path.join(java_inc_dir, 'win32')] + elif env['PLATFORM'] == 'darwin': + if not version: + paths = [java_macos_include_dir] + else: + paths = sorted(glob.glob(java_macos_version_include_dir%version)) + else: + base_paths=[] + if not version: + for p in java_linux_include_dirs: + base_paths.extend(glob.glob(p)) + else: + for p in java_linux_version_include_dirs: + base_paths.extend(glob.glob(p%version)) + + for p in base_paths: + paths.extend([p, os.path.join(p,'linux')]) + + #print("PATHS:%s"%paths) + return paths + + + # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/JavaCommonTests.py b/src/engine/SCons/Tool/JavaCommonTests.py index da405f0..c70e445 100644 --- a/src/engine/SCons/Tool/JavaCommonTests.py +++ b/src/engine/SCons/Tool/JavaCommonTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,14 +21,12 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/JavaCommonTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/JavaCommonTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import sys import unittest -import TestUnit - import SCons.Scanner.IDL import SCons.Tool.JavaCommon @@ -566,14 +564,52 @@ public class Foo assert expect == classes, (expect, classes) + def test_in_function_class_declaration(self): + """ + Test that implementing a class in a function call doesn't confuse SCons. + """ + + input = """ +package com.Matthew; + +public class AnonDemo { + + public static void main(String[] args) { + new AnonDemo().execute(); + } + + public void execute() { + Foo bar = new Foo(new Foo() { + @Override + public int getX() { return this.x; } + }) { + @Override + public int getX() { return this.x; } + }; + } + + public abstract class Foo { + public int x; + public abstract int getX(); + + public Foo(Foo f) { + this.x = f.x; + } + + public Foo() {} + } +} +""" + expect = ['AnonDemo$1', + 'AnonDemo$2', + 'AnonDemo$Foo', + 'AnonDemo'] + pkg_dir, classes = SCons.Tool.JavaCommon.parse_java(input, '1.8') + assert expect == classes, (expect, classes) + if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ parse_javaTestCase ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/MSCommon/__init__.py b/src/engine/SCons/Tool/MSCommon/__init__.py index 989ab08..7faff33 100644 --- a/src/engine/SCons/Tool/MSCommon/__init__.py +++ b/src/engine/SCons/Tool/MSCommon/__init__.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """ Common functions for Microsoft Visual Studio and Visual C/C++. diff --git a/src/engine/SCons/Tool/MSCommon/arch.py b/src/engine/SCons/Tool/MSCommon/arch.py index 96f05a8..6965fbf 100644 --- a/src/engine/SCons/Tool/MSCommon/arch.py +++ b/src/engine/SCons/Tool/MSCommon/arch.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/arch.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """Module to define supported Windows chip architectures. """ @@ -37,22 +37,22 @@ class ArchDefinition(object): self.synonyms = synonyms SupportedArchitectureList = [ - ArchitectureDefinition( + ArchDefinition( 'x86', ['i386', 'i486', 'i586', 'i686'], ), - ArchitectureDefinition( + ArchDefinition( 'x86_64', ['AMD64', 'amd64', 'em64t', 'EM64T', 'x86_64'], ), - ArchitectureDefinition( + ArchDefinition( 'ia64', ['IA64'], ), - ArchitectureDefinition( + ArchDefinition( 'arm', ['ARM'], ), diff --git a/src/engine/SCons/Tool/MSCommon/common.py b/src/engine/SCons/Tool/MSCommon/common.py index fcf623f..c8db141 100644 --- a/src/engine/SCons/Tool/MSCommon/common.py +++ b/src/engine/SCons/Tool/MSCommon/common.py @@ -2,7 +2,7 @@ Common helper functions for working with the Microsoft tool chain. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,7 +25,7 @@ Common helper functions for working with the Microsoft tool chain. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/MSCommon/common.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/common.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import copy import os @@ -46,7 +46,7 @@ elif LOGFILE: debug = lambda message: open(LOGFILE, 'a').write(message + '\n') else: logging.basicConfig(filename=LOGFILE, level=logging.DEBUG) - debug = logging.debug + debug = logging.getLogger(name=__name__).debug else: debug = lambda x: None @@ -188,8 +188,10 @@ def get_output(vcbat, args = None, env = None): # Use the .stdout and .stderr attributes directly because the # .communicate() method uses the threading module on Windows # and won't work under Pythons not built with threading. - stdout = popen.stdout.read() - stderr = popen.stderr.read() + with popen.stdout: + stdout = popen.stdout.read() + with popen.stderr: + stderr = popen.stderr.read() # Extra debug logic, uncomment if necessary # debug('get_output():stdout:%s'%stdout) @@ -206,7 +208,7 @@ def get_output(vcbat, args = None, env = None): output = stdout.decode("mbcs") return output -def parse_output(output, keep=("INCLUDE", "LIB", "LIBPATH", "PATH")): +def parse_output(output, keep=("INCLUDE", "LIB", "LIBPATH", "PATH", 'VSCMD_ARG_app_plat')): """ Parse output from running visual c++/studios vcvarsall.bat and running set To capture the values listed in keep diff --git a/src/engine/SCons/Tool/MSCommon/netframework.py b/src/engine/SCons/Tool/MSCommon/netframework.py index b769c44..01bb5b7 100644 --- a/src/engine/SCons/Tool/MSCommon/netframework.py +++ b/src/engine/SCons/Tool/MSCommon/netframework.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,7 +20,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/netframework.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """ """ diff --git a/src/engine/SCons/Tool/MSCommon/sdk.py b/src/engine/SCons/Tool/MSCommon/sdk.py index 8bc9830..2814d97 100644 --- a/src/engine/SCons/Tool/MSCommon/sdk.py +++ b/src/engine/SCons/Tool/MSCommon/sdk.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/sdk.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """Module to detect the Platform/Windows SDK @@ -178,6 +178,16 @@ SDK100VCSetupScripts = {'x86' : r'bin\vcvars32.bat', # # If you update this list, update the documentation in Tool/mssdk.xml. SupportedSDKList = [ + WindowsSDK('10.0A', + sanity_check_file=r'bin\SetEnv.Cmd', + include_subdir='include', + lib_subdir={ + 'x86' : ['lib'], + 'x86_64' : [r'lib\x64'], + 'ia64' : [r'lib\ia64'], + }, + vc_setup_scripts = SDK70VCSetupScripts, + ), WindowsSDK('10.0', sanity_check_file=r'bin\SetEnv.Cmd', include_subdir='include', diff --git a/src/engine/SCons/Tool/MSCommon/vc.py b/src/engine/SCons/Tool/MSCommon/vc.py index fba86af..5de85d6 100644 --- a/src/engine/SCons/Tool/MSCommon/vc.py +++ b/src/engine/SCons/Tool/MSCommon/vc.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ # * test on 64 bits XP + VS 2005 (and VS 6 if possible) # * SDK # * Assembly -__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """Module for Visual C/C++ detection and configuration. """ @@ -43,6 +43,7 @@ import platform from string import digits as string_digits import SCons.Warnings +from SCons.Tool import find_program_path from . import common @@ -79,15 +80,43 @@ _ARCH_TO_CANONICAL = { "i486" : "x86", "i586" : "x86", "i686" : "x86", - "ia64" : "ia64", - "itanium" : "ia64", + "ia64" : "ia64", # deprecated + "itanium" : "ia64", # deprecated "x86" : "x86", "x86_64" : "amd64", - "x86_amd64" : "x86_amd64", # Cross compile to 64 bit from 32bits + "arm" : "arm", + "arm64" : "arm64", + "aarch64" : "arm64", } -# Given a (host, target) tuple, return the argument for the bat file. Both host -# and targets should be canonalized. +# get path to the cl.exe dir for newer VS versions +# based off a tuple of (host, target) platforms +_HOST_TARGET_TO_CL_DIR_GREATER_THAN_14 = { + ("amd64","amd64") : "Hostx64\\x64", + ("amd64","x86") : "Hostx64\\x86", + ("amd64","arm") : "Hostx64\\arm", + ("amd64","arm64") : "Hostx64\\arm64", + ("x86","amd64") : "Hostx86\\x64", + ("x86","x86") : "Hostx86\\x86", + ("x86","arm") : "Hostx86\\arm", + ("x86","arm64") : "Hostx86\\arm64", +} + +# get path to the cl.exe dir for older VS versions +# based off a tuple of (host, target) platforms +_HOST_TARGET_TO_CL_DIR = { + ("amd64","amd64") : "amd64", + ("amd64","x86") : "amd64_x86", + ("amd64","arm") : "amd64_arm", + ("amd64","arm64") : "amd64_arm64", + ("x86","amd64") : "x86_amd64", + ("x86","x86") : "", + ("x86","arm") : "x86_arm", + ("x86","arm64") : "x86_arm64", +} + +# Given a (host, target) tuple, return the argument for the bat file. +# Both host and targets should be canonalized. _HOST_TARGET_ARCH_TO_BAT_ARCH = { ("x86", "x86"): "x86", ("x86", "amd64"): "x86_amd64", @@ -95,9 +124,32 @@ _HOST_TARGET_ARCH_TO_BAT_ARCH = { ("amd64", "x86_amd64"): "x86_amd64", # This is present in (at least) VS2012 express ("amd64", "amd64"): "amd64", ("amd64", "x86"): "x86", - ("x86", "ia64"): "x86_ia64" + ("x86", "ia64"): "x86_ia64", # gone since 14.0 + ("arm", "arm"): "arm", # since 14.0, maybe gone 14.1? + ("x86", "arm"): "x86_arm", # since 14.0 + ("x86", "arm64"): "x86_arm64", # since 14.1 + ("amd64", "arm"): "amd64_arm", # since 14.0 + ("amd64", "arm64"): "amd64_arm64", # since 14.1 } +_CL_EXE_NAME = 'cl.exe' + +def get_msvc_version_numeric(msvc_version): + """Get the raw version numbers from a MSVC_VERSION string, so it + could be cast to float or other numeric values. For example, '14.0Exp' + would get converted to '14.0'. + + Args: + msvc_version: str + string representing the version number, could contain non + digit characters + + Returns: + str: the value converted to a numeric only string + + """ + return ''.join([x for x in msvc_version if x in string_digits + '.']) + def get_host_target(env): debug('vc.py:get_host_target()') @@ -188,7 +240,7 @@ _VCVER_TO_PRODUCT_DIR = { } def msvc_version_to_maj_min(msvc_version): - msvc_version_numeric = ''.join([x for x in msvc_version if x in string_digits + '.']) + msvc_version_numeric = get_msvc_version_numeric(msvc_version) t = msvc_version_numeric.split(".") if not len(t) == 2: @@ -201,21 +253,21 @@ def msvc_version_to_maj_min(msvc_version): raise ValueError("Unrecognized version %s (%s)" % (msvc_version,msvc_version_numeric)) def is_host_target_supported(host_target, msvc_version): - """Return True if the given (host, target) tuple is supported given the - msvc version. - - Parameters - ---------- - host_target: tuple - tuple of (canonalized) host-target, e.g. ("x86", "amd64") for cross - compilation from 32 bits windows to 64 bits. - msvc_version: str - msvc version (major.minor, e.g. 10.0) - - Note - ---- - This only check whether a given version *may* support the given (host, - target), not that the toolchain is actually present on the machine. + """Check if the given (host, target) tuple is supported for given version. + + Args: + host_target: tuple + tuple of (canonalized) host-targets, e.g. ("x86", "amd64") + for cross compilation from 32 bit Windows to 64 bits. + msvc_version: str + msvc version (major.minor, e.g. 10.0) + + Returns: + bool: + + Note: + This only checks whether a given version *may* support the given (host, + target), not that the toolchain is actually present on the machine. """ # We assume that any Visual Studio version supports x86 as a target if host_target[1] != "x86": @@ -228,40 +280,69 @@ def is_host_target_supported(host_target, msvc_version): def find_vc_pdir_vswhere(msvc_version): """ - Find the MSVC product directory using vswhere.exe . + Find the MSVC product directory using vswhere.exe. + Run it asking for specified version and get MSVS install location :param msvc_version: - :return: MSVC install dir + :return: MSVC install dir or None """ - vswhere_path = os.path.join( - 'C:\\', - 'Program Files (x86)', - 'Microsoft Visual Studio', - 'Installer', - 'vswhere.exe' - ) - vswhere_cmd = [vswhere_path, '-version', msvc_version, '-property', 'installationPath'] + + # For bug 3333 - support default location of vswhere for both 64 and 32 bit windows + # installs. + for pf in ['Program Files (x86)', 'Program Files']: + vswhere_path = os.path.join( + 'C:\\', + pf, + 'Microsoft Visual Studio', + 'Installer', + 'vswhere.exe' + ) + if os.path.exists(vswhere_path): + # If we found vswhere, then use it. + break + + vswhere_cmd = [vswhere_path, '-products', '*', '-version', msvc_version, '-property', 'installationPath'] if os.path.exists(vswhere_path): - sp = subprocess.Popen(vswhere_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + #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() - vsdir = vsdir.decode("mbcs") - vsdir = vsdir.rstrip() - vc_pdir = os.path.join(vsdir, 'VC') - return vc_pdir + if vsdir: + vsdir = vsdir.decode("mbcs").splitlines() + # vswhere could easily return multiple lines + # we could define a way to pick the one we prefer, but since + # this data is currently only used to make a check for existence, + # returning the first hit should be good enough for now. + vc_pdir = os.path.join(vsdir[0], 'VC') + return vc_pdir else: # No vswhere on system, no install info available return None def find_vc_pdir(msvc_version): - """Try to find the product directory for the given - version. + """Find the product directory for the given version. + + Tries to look up the path using a registry key from the table + _VCVER_TO_PRODUCT_DIR; if there is no key, calls find_vc_pdir_wshere + for help instead. + + Args: + msvc_version: str + msvc version (major.minor, e.g. 10.0) + + Returns: + str: Path found in registry, or None - Note - ---- - If for some reason the requested version could not be found, an - exception which inherits from VisualCException will be raised.""" + Raises: + UnsupportedVersion: if the version is not known by this file. + MissingConfiguration: found version but the directory is missing. + + Both exceptions inherit from VisualCException. + """ root = 'Software\\' try: hkeys = _VCVER_TO_PRODUCT_DIR[msvc_version] @@ -275,8 +356,10 @@ def find_vc_pdir(msvc_version): if not key: comps = find_vc_pdir_vswhere(msvc_version) if not comps: - debug('find_vc_dir(): no VC found via vswhere for version {}'.format(repr(key))) + debug('find_vc_pdir_vswhere(): no VC found for version {}'.format(repr(msvc_version))) raise SCons.Util.WinError + debug('find_vc_pdir_vswhere(): VC found: {}'.format(repr(msvc_version))) + return comps else: if common.is_win64(): try: @@ -308,10 +391,10 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): if pdir is None: raise NoVersionFound("No version of Visual Studio found") - debug('vc.py: find_batch_file() pdir:{}'.format(pdir)) + debug('vc.py: find_batch_file() in {}'.format(pdir)) # filter out e.g. "Exp" from the version name - msvc_ver_numeric = ''.join([x for x in msvc_version if x in string_digits + "."]) + msvc_ver_numeric = get_msvc_version_numeric(msvc_version) vernum = float(msvc_ver_numeric) if 7 <= vernum < 8: pdir = os.path.join(pdir, os.pardir, "Common7", "Tools") @@ -343,23 +426,132 @@ def find_batch_file(env,msvc_version,host_arch,target_arch): __INSTALLED_VCS_RUN = None -def cached_get_installed_vcs(): +def _check_cl_exists_in_vc_dir(env, vc_dir, msvc_version): + """Find the cl.exe on the filesystem in the vc_dir depending on + TARGET_ARCH, HOST_ARCH and the msvc version. TARGET_ARCH and + HOST_ARCH can be extracted from the passed env, unless its None, + which then the native platform is assumed the host and target. + + Args: + env: Environment + a construction environment, usually if this is passed its + because there is a desired TARGET_ARCH to be used when searching + for a cl.exe + vc_dir: str + the path to the VC dir in the MSVC installation + msvc_version: str + msvc version (major.minor, e.g. 10.0) + + Returns: + bool: + + """ + + # determine if there is a specific target platform we want to build for and + # use that to find a list of valid VCs, default is host platform == target platform + # and same for if no env is specified to extract target platform from + if env: + (host_platform, target_platform, req_target_platform) = get_host_target(env) + else: + host_platform = platform.machine().lower() + target_platform = host_platform + + host_platform = _ARCH_TO_CANONICAL[host_platform] + target_platform = _ARCH_TO_CANONICAL[target_platform] + + debug('_check_cl_exists_in_vc_dir(): host platform %s, target platform %s' % (host_platform, target_platform)) + + ver_num = float(get_msvc_version_numeric(msvc_version)) + + # make sure the cl.exe exists meaning the tool is installed + if ver_num > 14: + # 2017 and newer allowed multiple versions of the VC toolset to be installed at the same time. + # Just get the default tool version for now + #TODO: support setting a specific minor VC version + default_toolset_file = os.path.join(vc_dir, r'Auxiliary\Build\Microsoft.VCToolsVersion.default.txt') + try: + with open(default_toolset_file) as f: + vc_specific_version = f.readlines()[0].strip() + except IOError: + debug('_check_cl_exists_in_vc_dir(): failed to read ' + default_toolset_file) + return False + except IndexError: + debug('_check_cl_exists_in_vc_dir(): failed to find MSVC version in ' + default_toolset_file) + return False + + host_trgt_dir = _HOST_TARGET_TO_CL_DIR_GREATER_THAN_14.get((host_platform, target_platform), None) + if not host_trgt_dir: + debug('_check_cl_exists_in_vc_dir(): unsupported host/target platform combo') + return False + + cl_path = os.path.join(vc_dir, r'Tools\MSVC', vc_specific_version, 'bin', host_trgt_dir, _CL_EXE_NAME) + debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path) + if os.path.exists(cl_path): + debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!') + return True + + elif ver_num <= 14 and ver_num >= 8: + + host_trgt_dir = _HOST_TARGET_TO_CL_DIR.get((host_platform, target_platform), None) + if not host_trgt_dir: + debug('_check_cl_exists_in_vc_dir(): unsupported host/target platform combo') + return False + + cl_path = os.path.join(vc_dir, 'bin', host_trgt_dir, _CL_EXE_NAME) + debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path) + + cl_path_exists = os.path.exists(cl_path) + if not cl_path_exists and host_platform == 'amd64': + # older versions of visual studio only had x86 binaries, + # so if the host platform is amd64, we need to check cross + # compile options (x86 binary compiles some other target on a 64 bit os) + host_trgt_dir = _HOST_TARGET_TO_CL_DIR.get(('x86', target_platform), None) + if not host_trgt_dir: + return False + + cl_path = os.path.join(vc_dir, 'bin', host_trgt_dir, _CL_EXE_NAME) + debug('_check_cl_exists_in_vc_dir(): checking for ' + _CL_EXE_NAME + ' at ' + cl_path) + cl_path_exists = os.path.exists(cl_path) + + if cl_path_exists: + debug('_check_cl_exists_in_vc_dir(): found ' + _CL_EXE_NAME + '!') + return True + + elif ver_num < 8 and ver_num >= 6: + # not sure about these versions so if a walk the VC dir (could be slow) + for root, _, files in os.walk(vc_dir): + if _CL_EXE_NAME in files: + debug('get_installed_vcs ' + _CL_EXE_NAME + ' found %s' % os.path.join(root, _CL_EXE_NAME)) + return True + return False + else: + # version not support return false + debug('_check_cl_exists_in_vc_dir(): unsupported MSVC version: ' + str(ver_num)) + + return False + +def cached_get_installed_vcs(env=None): global __INSTALLED_VCS_RUN if __INSTALLED_VCS_RUN is None: - ret = get_installed_vcs() + ret = get_installed_vcs(env) __INSTALLED_VCS_RUN = ret return __INSTALLED_VCS_RUN -def get_installed_vcs(): +def get_installed_vcs(env=None): installed_versions = [] + for ver in _VCVER: debug('trying to find VC %s' % ver) try: - if find_vc_pdir(ver): + VC_DIR = find_vc_pdir(ver) + if VC_DIR: debug('found VC %s' % ver) - installed_versions.append(ver) + if _check_cl_exists_in_vc_dir(env, VC_DIR, ver): + installed_versions.append(ver) + else: + debug('find_vc_pdir no compiler found %s' % ver) else: debug('find_vc_pdir return None for ver %s' % ver) except VisualCException as e: @@ -416,7 +608,7 @@ def get_default_version(env): % (msvc_version, msvs_version)) return msvs_version if not msvc_version: - installed_vcs = cached_get_installed_vcs() + installed_vcs = cached_get_installed_vcs(env) debug('installed_vcs:%s' % installed_vcs) if not installed_vcs: #msg = 'No installed VCs' @@ -443,16 +635,17 @@ def msvc_find_valid_batch_script(env,version): debug('vc.py:msvc_find_valid_batch_script()') # Find the host platform, target platform, and if present the requested # target platform - (host_platform, target_platform,req_target_platform) = get_host_target(env) + platforms = get_host_target(env) + debug("vc.py: msvs_find_valid_batch_script(): host_platform %s, target_platform %s req_target_platform:%s" % platforms) + host_platform, target_platform, req_target_platform = platforms try_target_archs = [target_platform] - debug("msvs_find_valid_batch_script(): req_target_platform %s target_platform:%s"%(req_target_platform,target_platform)) # VS2012 has a "cross compile" environment to build 64 bit # with x86_amd64 as the argument to the batch setup script - if req_target_platform in ('amd64','x86_64'): + if req_target_platform in ('amd64', 'x86_64'): try_target_archs.append('x86_amd64') - elif not req_target_platform and target_platform in ['amd64','x86_64']: + elif not req_target_platform and target_platform in ['amd64', 'x86_64']: # There may not be "native" amd64, but maybe "cross" x86_amd64 tools try_target_archs.append('x86_amd64') # If the user hasn't specifically requested a TARGET_ARCH, and @@ -474,7 +667,7 @@ def msvc_find_valid_batch_script(env,version): (host_target, version) SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) arg = _HOST_TARGET_ARCH_TO_BAT_ARCH[host_target] - + # Get just version numbers maj, min = msvc_version_to_maj_min(version) # VS2015+ @@ -493,15 +686,17 @@ def msvc_find_valid_batch_script(env,version): warn_msg = "VC version %s not installed. " + \ "C/C++ compilers are most likely not set correctly.\n" + \ " Installed versions are: %s" - warn_msg = warn_msg % (version, cached_get_installed_vcs()) + warn_msg = warn_msg % (version, cached_get_installed_vcs(env)) SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, warn_msg) continue # Try to use the located batch file for this host/target platform combo debug('vc.py:msvc_find_valid_batch_script() use_script 2 %s, args:%s\n' % (repr(vc_script), arg)) + found = None if vc_script: try: d = script_env(vc_script, args=arg) + found = vc_script except BatchFileExecutionError as e: debug('vc.py:msvc_find_valid_batch_script() use_script 3: failed running VC script %s: %s: Error:%s'%(repr(vc_script),arg,e)) vc_script=None @@ -510,6 +705,7 @@ def msvc_find_valid_batch_script(env,version): debug('vc.py:msvc_find_valid_batch_script() use_script 4: trying sdk script: %s'%(sdk_script)) try: d = script_env(sdk_script) + found = sdk_script except BatchFileExecutionError as e: debug('vc.py:msvc_find_valid_batch_script() use_script 5: failed running SDK script %s: Error:%s'%(repr(sdk_script),e)) continue @@ -517,7 +713,7 @@ def msvc_find_valid_batch_script(env,version): debug('vc.py:msvc_find_valid_batch_script() use_script 6: Neither VC script nor SDK script found') continue - debug("vc.py:msvc_find_valid_batch_script() Found a working script/target: %s %s"%(repr(sdk_script),arg)) + debug("vc.py:msvc_find_valid_batch_script() Found a working script/target: %s/%s"%(repr(found),arg)) break # We've found a working target_platform, so stop looking # If we cannot find a viable installed compiler, reset the TARGET_ARCH @@ -566,8 +762,14 @@ def msvc_setup_env(env): debug('vc.py:msvc_setup_env() env:%s -> %s'%(k,v)) env.PrependENVPath(k, v, delete_existing=True) -def msvc_exists(version=None): - vcs = cached_get_installed_vcs() + # final check to issue a warning if the compiler is not present + msvc_cl = find_program_path(env, 'cl') + if not msvc_cl: + SCons.Warnings.warn(SCons.Warnings.VisualCMissingWarning, + "Could not find MSVC compiler 'cl', it may need to be installed separately with Visual Studio") + +def msvc_exists(env=None, version=None): + vcs = cached_get_installed_vcs(env) if version is None: return len(vcs) > 0 return version in vcs diff --git a/src/engine/SCons/Tool/MSCommon/vs.py b/src/engine/SCons/Tool/MSCommon/vs.py index dafdbaf..72d4421 100644 --- a/src/engine/SCons/Tool/MSCommon/vs.py +++ b/src/engine/SCons/Tool/MSCommon/vs.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/MSCommon/vs.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """Module to detect Visual Studio and/or Visual C/C++ """ @@ -68,9 +68,9 @@ class VisualStudio(object): SCons.Tool.MSCommon.vc.get_installed_vcs() dir = SCons.Tool.MSCommon.vc.find_vc_pdir(self.vc_version) if not dir: - debug('find_vs_dir(): no installed VC %s' % self.vc_version) + debug('find_vs_dir_by_vc(): no installed VC %s' % self.vc_version) return None - return dir + return os.path.abspath(os.path.join(dir, os.pardir)) def find_vs_dir_by_reg(self): root = 'Software\\' @@ -95,12 +95,11 @@ class VisualStudio(object): First try to find by registry, and if that fails find via VC dir """ - - if True: - vs_dir=self.find_vs_dir_by_reg() - return vs_dir - else: - return self.find_vs_dir_by_vc() + vs_dir=self.find_vs_dir_by_reg() + if not vs_dir: + vs_dir = self.find_vs_dir_by_vc() + debug('find_vs_dir(): found VS in ' + str(vs_dir )) + return vs_dir def find_executable(self): vs_dir = self.get_vs_dir() diff --git a/src/engine/SCons/Tool/PharLapCommon.py b/src/engine/SCons/Tool/PharLapCommon.py index c45c6d3..103e21c 100644 --- a/src/engine/SCons/Tool/PharLapCommon.py +++ b/src/engine/SCons/Tool/PharLapCommon.py @@ -7,7 +7,7 @@ Phar Lap ETS tool chain. Right now, this is linkloc and """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -29,7 +29,7 @@ Phar Lap ETS tool chain. Right now, this is linkloc and # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/PharLapCommon.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/PharLapCommon.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path diff --git a/src/engine/SCons/Tool/ToolTests.py b/src/engine/SCons/Tool/ToolTests.py index f5678c1..81b6491 100644 --- a/src/engine/SCons/Tool/ToolTests.py +++ b/src/engine/SCons/Tool/ToolTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ToolTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ToolTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest diff --git a/src/engine/SCons/Tool/__init__.py b/src/engine/SCons/Tool/__init__.py index 9265b81..b7d5dcc 100644 --- a/src/engine/SCons/Tool/__init__.py +++ b/src/engine/SCons/Tool/__init__.py @@ -14,7 +14,7 @@ tool definition. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -35,7 +35,7 @@ tool definition. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import imp import importlib @@ -44,7 +44,6 @@ import re import os import shutil - import SCons.Builder import SCons.Errors import SCons.Node.FS @@ -56,7 +55,7 @@ import SCons.Scanner.Prog import SCons.Scanner.SWIG import collections -DefaultToolpath=[] +DefaultToolpath = [] CScanner = SCons.Scanner.C.CScanner() DScanner = SCons.Scanner.D.DScanner() @@ -97,20 +96,20 @@ for suffix in LaTeXSuffixes: SourceFileScanner.add_scanner(suffix, LaTeXScanner) SourceFileScanner.add_scanner(suffix, PDFLaTeXScanner) - # Tool aliases are needed for those tools whos module names also # occur in the python standard library. This causes module shadowing and # can break using python library functions under python3 TOOL_ALIASES = { - 'gettext':'gettext_tool', + 'gettext': 'gettext_tool', 'clang++': 'clangxx', } + class Tool(object): def __init__(self, name, toolpath=[], **kw): # Rename if there's a TOOL_ALIAS for this tool - self.name = TOOL_ALIASES.get(name,name) + self.name = TOOL_ALIASES.get(name, name) self.toolpath = toolpath + DefaultToolpath # remember these so we can merge them into the call self.init_kw = kw @@ -136,7 +135,7 @@ class Tool(object): sys.path = self.toolpath + sys.path # sys.stderr.write("Tool:%s\nPATH:%s\n"%(self.name,sys.path)) - if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0,1,2,3,4)): + if sys.version_info[0] < 3 or (sys.version_info[0] == 3 and sys.version_info[1] in (0, 1, 2, 3, 4)): # Py 2 code try: try: @@ -149,7 +148,7 @@ class Tool(object): file.close() except ImportError as e: splitname = self.name.split('.') - if str(e)!="No module named %s"%splitname[0]: + if str(e) != "No module named %s" % splitname[0]: raise SCons.Errors.EnvironmentError(e) try: import zipimport @@ -184,46 +183,48 @@ class Tool(object): add_to_scons_tools_namespace = False for path in self.toolpath: sepname = self.name.replace('.', os.path.sep) - file_path = os.path.join(path, "%s.py"%sepname) + file_path = os.path.join(path, "%s.py" % sepname) file_package = os.path.join(path, sepname) - if debug: sys.stderr.write("Trying:%s %s\n"%(file_path, file_package)) + if debug: sys.stderr.write("Trying:%s %s\n" % (file_path, file_package)) if os.path.isfile(file_path): spec = importlib.util.spec_from_file_location(self.name, file_path) - if debug: print("file_Path:%s FOUND"%file_path) + if debug: print("file_Path:%s FOUND" % file_path) break elif os.path.isdir(file_package): file_package = os.path.join(file_package, '__init__.py') spec = importlib.util.spec_from_file_location(self.name, file_package) - if debug: print("PACKAGE:%s Found"%file_package) + if debug: print("PACKAGE:%s Found" % file_package) break else: continue if spec is None: - if debug: sys.stderr.write("NO SPEC :%s\n"%self.name) - spec = importlib.util.find_spec("."+self.name, package='SCons.Tool') + if debug: sys.stderr.write("NO SPEC :%s\n" % self.name) + spec = importlib.util.find_spec("." + self.name, package='SCons.Tool') if spec: - found_name = 'SCons.Tool.'+self.name + found_name = 'SCons.Tool.' + self.name add_to_scons_tools_namespace = True - if debug: sys.stderr.write("Spec Found? .%s :%s\n"%(self.name, spec)) + if debug: sys.stderr.write("Spec Found? .%s :%s\n" % (self.name, spec)) if spec is None: - error_string = "No module named %s"%self.name + error_string = "No module named %s" % self.name raise SCons.Errors.EnvironmentError(error_string) module = importlib.util.module_from_spec(spec) if module is None: - if debug: print("MODULE IS NONE:%s"%self.name) - error_string = "No module named %s"%self.name + if debug: print("MODULE IS NONE:%s" % self.name) + error_string = "No module named %s" % self.name raise SCons.Errors.EnvironmentError(error_string) # Don't reload a tool we already loaded. - sys_modules_value = sys.modules.get(found_name,False) + sys_modules_value = sys.modules.get(found_name, False) + + found_module = None if sys_modules_value and sys_modules_value.__file__ == spec.origin: - return sys.modules[found_name] + found_module = sys.modules[found_name] else: # Not sure what to do in the case that there already # exists sys.modules[self.name] but the source file is @@ -235,8 +236,11 @@ class Tool(object): # If we found it in SCons.Tool, then add it to the module setattr(SCons.Tool, self.name, module) - return module + found_module = module + if found_module is not None: + sys.path = oldpythonpath + return found_module sys.path = oldpythonpath @@ -253,11 +257,11 @@ class Tool(object): file.close() return module except ImportError as e: - if str(e)!="No module named %s"%self.name: + if str(e) != "No module named %s" % self.name: raise SCons.Errors.EnvironmentError(e) try: import zipimport - importer = zipimport.zipimporter( sys.modules['SCons.Tool'].__path__[0] ) + importer = zipimport.zipimporter(sys.modules['SCons.Tool'].__path__[0]) module = importer.load_module(full_name) setattr(SCons.Tool, self.name, module) return module @@ -278,13 +282,13 @@ class Tool(object): kw.update(call_kw) else: kw = self.init_kw - env.Append(TOOLS = [ self.name ]) + env.Append(TOOLS=[self.name]) if hasattr(self, 'options'): import SCons.Variables if 'options' not in env: from SCons.Script import ARGUMENTS - env['options']=SCons.Variables.Variables(args=ARGUMENTS) - opts=env['options'] + env['options'] = SCons.Variables.Variables(args=ARGUMENTS) + opts = env['options'] self.options(opts) opts.Update(env) @@ -294,6 +298,7 @@ class Tool(object): def __str__(self): return self.name + ########################################################################## # Create common executable program / library / object builders @@ -308,13 +313,13 @@ def createProgBuilder(env): program = env['BUILDERS']['Program'] except KeyError: import SCons.Defaults - program = SCons.Builder.Builder(action = SCons.Defaults.LinkAction, - emitter = '$PROGEMITTER', - prefix = '$PROGPREFIX', - suffix = '$PROGSUFFIX', - src_suffix = '$OBJSUFFIX', - src_builder = 'Object', - target_scanner = ProgramScanner) + program = SCons.Builder.Builder(action=SCons.Defaults.LinkAction, + emitter='$PROGEMITTER', + prefix='$PROGPREFIX', + suffix='$PROGSUFFIX', + src_suffix='$OBJSUFFIX', + src_builder='Object', + target_scanner=ProgramScanner) env['BUILDERS']['Program'] = program return program @@ -330,23 +335,24 @@ def createStaticLibBuilder(env): try: static_lib = env['BUILDERS']['StaticLibrary'] except KeyError: - action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ] - if env.get('RANLIB',False) or env.Detect('ranlib'): + action_list = [SCons.Action.Action("$ARCOM", "$ARCOMSTR")] + if env.get('RANLIB', False) or env.Detect('ranlib'): ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR") action_list.append(ranlib_action) - static_lib = SCons.Builder.Builder(action = action_list, - emitter = '$LIBEMITTER', - prefix = '$LIBPREFIX', - suffix = '$LIBSUFFIX', - src_suffix = '$OBJSUFFIX', - src_builder = 'StaticObject') + static_lib = SCons.Builder.Builder(action=action_list, + emitter='$LIBEMITTER', + prefix='$LIBPREFIX', + suffix='$LIBSUFFIX', + src_suffix='$OBJSUFFIX', + src_builder='StaticObject') env['BUILDERS']['StaticLibrary'] = static_lib env['BUILDERS']['Library'] = static_lib return static_lib -def _call_linker_cb(env, callback, args, result = None): + +def _call_linker_cb(env, callback, args, result=None): """Returns the result of env['LINKCALLBACKS'][callback](*args) if env['LINKCALLBACKS'] is a dictionary and env['LINKCALLBACKS'][callback] is callable. If these conditions are not met, return the value provided as @@ -370,84 +376,109 @@ def _call_linker_cb(env, callback, args, result = None): if Verbose: print('_call_linker_cb: env["LINKCALLBACKS"][%r] found' % callback) print('_call_linker_cb: env["LINKCALLBACKS"][%r]=%r' % (callback, cbfun)) - if(isinstance(cbfun, collections.Callable)): + if isinstance(cbfun, collections.Callable): if Verbose: print('_call_linker_cb: env["LINKCALLBACKS"][%r] is callable' % callback) result = cbfun(env, *args) return result + def _call_env_subst(env, string, *args, **kw): kw2 = {} for k in ('raw', 'target', 'source', 'conv', 'executor'): - try: kw2[k] = kw[k] - except KeyError: pass + try: + kw2[k] = kw[k] + except KeyError: + pass return env.subst(string, *args, **kw2) + class _ShLibInfoSupport(object): def get_libtype(self): return 'ShLib' + def get_lib_prefix(self, env, *args, **kw): - return _call_env_subst(env,'$SHLIBPREFIX', *args, **kw) + return _call_env_subst(env, '$SHLIBPREFIX', *args, **kw) + def get_lib_suffix(self, env, *args, **kw): - return _call_env_subst(env,'$SHLIBSUFFIX', *args, **kw) + return _call_env_subst(env, '$SHLIBSUFFIX', *args, **kw) + def get_lib_version(self, env, *args, **kw): - return _call_env_subst(env,'$SHLIBVERSION', *args, **kw) + return _call_env_subst(env, '$SHLIBVERSION', *args, **kw) + def get_lib_noversionsymlinks(self, env, *args, **kw): - return _call_env_subst(env,'$SHLIBNOVERSIONSYMLINKS', *args, **kw) + return _call_env_subst(env, '$SHLIBNOVERSIONSYMLINKS', *args, **kw) + class _LdModInfoSupport(object): def get_libtype(self): return 'LdMod' + def get_lib_prefix(self, env, *args, **kw): - return _call_env_subst(env,'$LDMODULEPREFIX', *args, **kw) + return _call_env_subst(env, '$LDMODULEPREFIX', *args, **kw) + def get_lib_suffix(self, env, *args, **kw): - return _call_env_subst(env,'$LDMODULESUFFIX', *args, **kw) + return _call_env_subst(env, '$LDMODULESUFFIX', *args, **kw) + def get_lib_version(self, env, *args, **kw): - return _call_env_subst(env,'$LDMODULEVERSION', *args, **kw) + return _call_env_subst(env, '$LDMODULEVERSION', *args, **kw) + def get_lib_noversionsymlinks(self, env, *args, **kw): - return _call_env_subst(env,'$LDMODULENOVERSIONSYMLINKS', *args, **kw) + return _call_env_subst(env, '$LDMODULENOVERSIONSYMLINKS', *args, **kw) + class _ImpLibInfoSupport(object): def get_libtype(self): return 'ImpLib' + def get_lib_prefix(self, env, *args, **kw): - return _call_env_subst(env,'$IMPLIBPREFIX', *args, **kw) + return _call_env_subst(env, '$IMPLIBPREFIX', *args, **kw) + def get_lib_suffix(self, env, *args, **kw): - return _call_env_subst(env,'$IMPLIBSUFFIX', *args, **kw) + return _call_env_subst(env, '$IMPLIBSUFFIX', *args, **kw) + def get_lib_version(self, env, *args, **kw): - version = _call_env_subst(env,'$IMPLIBVERSION', *args, **kw) + version = _call_env_subst(env, '$IMPLIBVERSION', *args, **kw) if not version: - try: lt = kw['implib_libtype'] - except KeyError: pass + try: + lt = kw['implib_libtype'] + except KeyError: + pass else: if lt == 'ShLib': - version = _call_env_subst(env,'$SHLIBVERSION', *args, **kw) + version = _call_env_subst(env, '$SHLIBVERSION', *args, **kw) elif lt == 'LdMod': - version = _call_env_subst(env,'$LDMODULEVERSION', *args, **kw) + version = _call_env_subst(env, '$LDMODULEVERSION', *args, **kw) return version + def get_lib_noversionsymlinks(self, env, *args, **kw): disable = None - try: env['IMPLIBNOVERSIONSYMLINKS'] + try: + env['IMPLIBNOVERSIONSYMLINKS'] except KeyError: - try: lt = kw['implib_libtype'] - except KeyError: pass + try: + lt = kw['implib_libtype'] + except KeyError: + pass else: if lt == 'ShLib': - disable = _call_env_subst(env,'$SHLIBNOVERSIONSYMLINKS', *args, **kw) + disable = _call_env_subst(env, '$SHLIBNOVERSIONSYMLINKS', *args, **kw) elif lt == 'LdMod': - disable = _call_env_subst(env,'$LDMODULENOVERSIONSYMLINKS', *args, **kw) + disable = _call_env_subst(env, '$LDMODULENOVERSIONSYMLINKS', *args, **kw) else: - disable = _call_env_subst(env,'$IMPLIBNOVERSIONSYMLINKS', *args, **kw) + disable = _call_env_subst(env, '$IMPLIBNOVERSIONSYMLINKS', *args, **kw) return disable + class _LibInfoGeneratorBase(object): """Generator base class for library-related info such as suffixes for versioned libraries, symlink maps, sonames etc. It handles commonities of SharedLibrary and LoadableModule """ - _support_classes = { 'ShLib' : _ShLibInfoSupport, - 'LdMod' : _LdModInfoSupport, - 'ImpLib' : _ImpLibInfoSupport } + _support_classes = {'ShLib': _ShLibInfoSupport, + 'LdMod': _LdModInfoSupport, + 'ImpLib': _ImpLibInfoSupport} + def __init__(self, libtype, infoname): self.set_libtype(libtype) self.set_infoname(infoname) @@ -469,37 +500,41 @@ class _LibInfoGeneratorBase(object): return self.infoname def get_lib_prefix(self, env, *args, **kw): - return self._support.get_lib_prefix(env,*args,**kw) + return self._support.get_lib_prefix(env, *args, **kw) def get_lib_suffix(self, env, *args, **kw): - return self._support.get_lib_suffix(env,*args,**kw) + return self._support.get_lib_suffix(env, *args, **kw) def get_lib_version(self, env, *args, **kw): - return self._support.get_lib_version(env,*args,**kw) + return self._support.get_lib_version(env, *args, **kw) def get_lib_noversionsymlinks(self, env, *args, **kw): - return self._support.get_lib_noversionsymlinks(env,*args,**kw) + return self._support.get_lib_noversionsymlinks(env, *args, **kw) # Returns name of generator linker callback that shall be used to generate # our info for a versioned library. For example, if our libtype is 'ShLib' # and infoname is 'Prefix', it would return 'VersionedShLibPrefix'. def get_versioned_lib_info_generator(self, **kw): - try: libtype = kw['generator_libtype'] - except KeyError: libtype = self.get_libtype() + try: + libtype = kw['generator_libtype'] + except KeyError: + libtype = self.get_libtype() infoname = self.get_infoname() return 'Versioned%s%s' % (libtype, infoname) - def generate_versioned_lib_info(self, env, args, result = None, **kw): + def generate_versioned_lib_info(self, env, args, result=None, **kw): callback = self.get_versioned_lib_info_generator(**kw) return _call_linker_cb(env, callback, args, result) + class _LibPrefixGenerator(_LibInfoGeneratorBase): """Library prefix generator, used as target_prefix in SharedLibrary and LoadableModule builders""" + def __init__(self, libtype): super(_LibPrefixGenerator, self).__init__(libtype, 'Prefix') - def __call__(self, env, sources = None, **kw): + def __call__(self, env, sources=None, **kw): Verbose = False if sources and 'source' not in kw: @@ -508,7 +543,7 @@ class _LibPrefixGenerator(_LibInfoGeneratorBase): else: kw2 = kw - prefix = self.get_lib_prefix(env,**kw2) + prefix = self.get_lib_prefix(env, **kw2) if Verbose: print("_LibPrefixGenerator: input prefix=%r" % prefix) @@ -523,17 +558,20 @@ class _LibPrefixGenerator(_LibInfoGeneratorBase): print("_LibPrefixGenerator: return prefix=%r" % prefix) return prefix -ShLibPrefixGenerator = _LibPrefixGenerator('ShLib') -LdModPrefixGenerator = _LibPrefixGenerator('LdMod') + +ShLibPrefixGenerator = _LibPrefixGenerator('ShLib') +LdModPrefixGenerator = _LibPrefixGenerator('LdMod') ImpLibPrefixGenerator = _LibPrefixGenerator('ImpLib') + class _LibSuffixGenerator(_LibInfoGeneratorBase): """Library suffix generator, used as target_suffix in SharedLibrary and LoadableModule builders""" + def __init__(self, libtype): super(_LibSuffixGenerator, self).__init__(libtype, 'Suffix') - def __call__(self, env, sources = None, **kw): + def __call__(self, env, sources=None, **kw): Verbose = False if sources and 'source' not in kw: @@ -557,13 +595,16 @@ class _LibSuffixGenerator(_LibInfoGeneratorBase): print("_LibSuffixGenerator: return suffix=%r" % suffix) return suffix -ShLibSuffixGenerator = _LibSuffixGenerator('ShLib') -LdModSuffixGenerator = _LibSuffixGenerator('LdMod') + +ShLibSuffixGenerator = _LibSuffixGenerator('ShLib') +LdModSuffixGenerator = _LibSuffixGenerator('LdMod') ImpLibSuffixGenerator = _LibSuffixGenerator('ImpLib') + class _LibSymlinkGenerator(_LibInfoGeneratorBase): """Library symlink map generator. It generates a list of symlinks that should be created by SharedLibrary or LoadableModule builders""" + def __init__(self, libtype): super(_LibSymlinkGenerator, self).__init__(libtype, 'Symlinks') @@ -588,18 +629,20 @@ class _LibSymlinkGenerator(_LibInfoGeneratorBase): print('_LibSymlinkGenerator: disable=%r' % disable) if version and not disable: - prefix = self.get_lib_prefix(env,**kw2) - suffix = self.get_lib_suffix(env,**kw2) + prefix = self.get_lib_prefix(env, **kw2) + suffix = self.get_lib_suffix(env, **kw2) symlinks = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) if Verbose: print('_LibSymlinkGenerator: return symlinks=%r' % StringizeLibSymlinks(symlinks)) return symlinks -ShLibSymlinkGenerator = _LibSymlinkGenerator('ShLib') -LdModSymlinkGenerator = _LibSymlinkGenerator('LdMod') + +ShLibSymlinkGenerator = _LibSymlinkGenerator('ShLib') +LdModSymlinkGenerator = _LibSymlinkGenerator('LdMod') ImpLibSymlinkGenerator = _LibSymlinkGenerator('ImpLib') + class _LibNameGenerator(_LibInfoGeneratorBase): """Generates "unmangled" library name from a library file node. @@ -614,6 +657,7 @@ class _LibNameGenerator(_LibInfoGeneratorBase): the _LibNameGenerator shall return "libfoo.so". Other link tools may implement it's own way of library name unmangling. """ + def __init__(self, libtype): super(_LibNameGenerator, self).__init__(libtype, 'Name') @@ -636,8 +680,8 @@ class _LibNameGenerator(_LibInfoGeneratorBase): name = None if version: - prefix = self.get_lib_prefix(env,**kw2) - suffix = self.get_lib_suffix(env,**kw2) + prefix = self.get_lib_prefix(env, **kw2) + suffix = self.get_lib_suffix(env, **kw2) name = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) if not name: @@ -648,13 +692,16 @@ class _LibNameGenerator(_LibInfoGeneratorBase): return name -ShLibNameGenerator = _LibNameGenerator('ShLib') -LdModNameGenerator = _LibNameGenerator('LdMod') + +ShLibNameGenerator = _LibNameGenerator('ShLib') +LdModNameGenerator = _LibNameGenerator('LdMod') ImpLibNameGenerator = _LibNameGenerator('ImpLib') + class _LibSonameGenerator(_LibInfoGeneratorBase): """Library soname generator. Returns library soname (e.g. libfoo.so.0) for a given node (e.g. /foo/bar/libfoo.so.0.1.2)""" + def __init__(self, libtype): super(_LibSonameGenerator, self).__init__(libtype, 'Soname') @@ -673,12 +720,12 @@ class _LibSonameGenerator(_LibInfoGeneratorBase): soname = _call_env_subst(env, '$SONAME', **kw2) if not soname: - version = self.get_lib_version(env,**kw2) + version = self.get_lib_version(env, **kw2) if Verbose: print("_LibSonameGenerator: version=%r" % version) if version: - prefix = self.get_lib_prefix(env,**kw2) - suffix = self.get_lib_suffix(env,**kw2) + prefix = self.get_lib_prefix(env, **kw2) + suffix = self.get_lib_suffix(env, **kw2) soname = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) if not soname: @@ -692,40 +739,44 @@ class _LibSonameGenerator(_LibInfoGeneratorBase): return soname -ShLibSonameGenerator = _LibSonameGenerator('ShLib') -LdModSonameGenerator = _LibSonameGenerator('LdMod') + +ShLibSonameGenerator = _LibSonameGenerator('ShLib') +LdModSonameGenerator = _LibSonameGenerator('LdMod') + def StringizeLibSymlinks(symlinks): """Converts list with pairs of nodes to list with pairs of node paths (strings). Used mainly for debugging.""" if SCons.Util.is_List(symlinks): try: - return [ (k.get_path(), v.get_path()) for k,v in symlinks ] + return [(k.get_path(), v.get_path()) for k, v in symlinks] except (TypeError, ValueError): return symlinks else: return symlinks + def EmitLibSymlinks(env, symlinks, libnode, **kw): """Used by emitters to handle (shared/versioned) library symlinks""" Verbose = False # nodes involved in process... all symlinks + library - nodes = list(set([ x for x,y in symlinks ] + [libnode])) + nodes = list(set([x for x, y in symlinks] + [libnode])) clean_targets = kw.get('clean_targets', []) if not SCons.Util.is_List(clean_targets): - clean_targets = [ clean_targets ] + clean_targets = [clean_targets] for link, linktgt in symlinks: env.SideEffect(link, linktgt) - if(Verbose): + if (Verbose): print("EmitLibSymlinks: SideEffect(%r,%r)" % (link.get_path(), linktgt.get_path())) clean_list = [x for x in nodes if x != linktgt] env.Clean(list(set([linktgt] + clean_targets)), clean_list) - if(Verbose): + if (Verbose): print("EmitLibSymlinks: Clean(%r,%r)" % (linktgt.get_path(), [x.get_path() for x in clean_list])) + def CreateLibSymlinks(env, symlinks): """Physically creates symlinks. The symlinks argument must be a list in form [ (link, linktarget), ... ], where link and linktarget are SCons @@ -736,38 +787,40 @@ def CreateLibSymlinks(env, symlinks): for link, linktgt in symlinks: linktgt = link.get_dir().rel_path(linktgt) link = link.get_path() - if(Verbose): + if (Verbose): print("CreateLibSymlinks: preparing to add symlink %r -> %r" % (link, linktgt)) # Delete the (previously created) symlink if exists. Let only symlinks # to be deleted to prevent accidental deletion of source files... if env.fs.islink(link): env.fs.unlink(link) - if(Verbose): + if (Verbose): print("CreateLibSymlinks: removed old symlink %r" % link) # If a file or directory exists with the same name as link, an OSError # will be thrown, which should be enough, I think. env.fs.symlink(linktgt, link) - if(Verbose): + if (Verbose): print("CreateLibSymlinks: add symlink %r -> %r" % (link, linktgt)) return 0 + def LibSymlinksActionFunction(target, source, env): for tgt in target: - symlinks = getattr(getattr(tgt,'attributes', None), 'shliblinks', None) + symlinks = getattr(getattr(tgt, 'attributes', None), 'shliblinks', None) if symlinks: CreateLibSymlinks(env, symlinks) return 0 + def LibSymlinksStrFun(target, source, env, *args): cmd = None for tgt in target: - symlinks = getattr(getattr(tgt,'attributes', None), 'shliblinks', None) + symlinks = getattr(getattr(tgt, 'attributes', None), 'shliblinks', None) if symlinks: if cmd is None: cmd = "" if cmd: cmd += "\n" cmd += "Create symlinks for: %r" % tgt.get_path() try: - linkstr = ', '.join([ "%r->%r" %(k,v) for k,v in StringizeLibSymlinks(symlinks)]) + linkstr = ', '.join(["%r->%r" % (k, v) for k, v in StringizeLibSymlinks(symlinks)]) except (KeyError, ValueError): pass else: @@ -789,20 +842,21 @@ def createSharedLibBuilder(env): shared_lib = env['BUILDERS']['SharedLibrary'] except KeyError: import SCons.Defaults - action_list = [ SCons.Defaults.SharedCheck, - SCons.Defaults.ShLinkAction, - LibSymlinksAction ] - shared_lib = SCons.Builder.Builder(action = action_list, - emitter = "$SHLIBEMITTER", - prefix = ShLibPrefixGenerator, - suffix = ShLibSuffixGenerator, - target_scanner = ProgramScanner, - src_suffix = '$SHOBJSUFFIX', - src_builder = 'SharedObject') + action_list = [SCons.Defaults.SharedCheck, + SCons.Defaults.ShLinkAction, + LibSymlinksAction] + shared_lib = SCons.Builder.Builder(action=action_list, + emitter="$SHLIBEMITTER", + prefix=ShLibPrefixGenerator, + suffix=ShLibSuffixGenerator, + target_scanner=ProgramScanner, + src_suffix='$SHOBJSUFFIX', + src_builder='SharedObject') env['BUILDERS']['SharedLibrary'] = shared_lib return shared_lib + def createLoadableModuleBuilder(env): """This is a utility function that creates the LoadableModule Builder in an Environment if it is not there already. @@ -814,20 +868,21 @@ def createLoadableModuleBuilder(env): ld_module = env['BUILDERS']['LoadableModule'] except KeyError: import SCons.Defaults - action_list = [ SCons.Defaults.SharedCheck, - SCons.Defaults.LdModuleLinkAction, - LibSymlinksAction ] - ld_module = SCons.Builder.Builder(action = action_list, - emitter = "$LDMODULEEMITTER", - prefix = LdModPrefixGenerator, - suffix = LdModSuffixGenerator, - target_scanner = ProgramScanner, - src_suffix = '$SHOBJSUFFIX', - src_builder = 'SharedObject') + action_list = [SCons.Defaults.SharedCheck, + SCons.Defaults.LdModuleLinkAction, + LibSymlinksAction] + ld_module = SCons.Builder.Builder(action=action_list, + emitter="$LDMODULEEMITTER", + prefix=LdModPrefixGenerator, + suffix=LdModSuffixGenerator, + target_scanner=ProgramScanner, + src_suffix='$SHOBJSUFFIX', + src_builder='SharedObject') env['BUILDERS']['LoadableModule'] = ld_module return ld_module + def createObjBuilders(env): """This is a utility function that creates the StaticObject and SharedObject Builders in an Environment if they @@ -841,34 +896,34 @@ def createObjBuilders(env): The return is a 2-tuple of (StaticObject, SharedObject) """ - try: static_obj = env['BUILDERS']['StaticObject'] except KeyError: - static_obj = SCons.Builder.Builder(action = {}, - emitter = {}, - prefix = '$OBJPREFIX', - suffix = '$OBJSUFFIX', - src_builder = ['CFile', 'CXXFile'], - source_scanner = SourceFileScanner, - single_source = 1) + static_obj = SCons.Builder.Builder(action={}, + emitter={}, + prefix='$OBJPREFIX', + suffix='$OBJSUFFIX', + src_builder=['CFile', 'CXXFile'], + source_scanner=SourceFileScanner, + single_source=1) env['BUILDERS']['StaticObject'] = static_obj env['BUILDERS']['Object'] = static_obj try: shared_obj = env['BUILDERS']['SharedObject'] except KeyError: - shared_obj = SCons.Builder.Builder(action = {}, - emitter = {}, - prefix = '$SHOBJPREFIX', - suffix = '$SHOBJSUFFIX', - src_builder = ['CFile', 'CXXFile'], - source_scanner = SourceFileScanner, - single_source = 1) + shared_obj = SCons.Builder.Builder(action={}, + emitter={}, + prefix='$SHOBJPREFIX', + suffix='$SHOBJSUFFIX', + src_builder=['CFile', 'CXXFile'], + source_scanner=SourceFileScanner, + single_source=1) env['BUILDERS']['SharedObject'] = shared_obj return (static_obj, shared_obj) + def createCFileBuilders(env): """This is a utility function that creates the CFile/CXXFile Builders in an Environment if they @@ -885,95 +940,109 @@ def createCFileBuilders(env): try: c_file = env['BUILDERS']['CFile'] except KeyError: - c_file = SCons.Builder.Builder(action = {}, - emitter = {}, - suffix = {None:'$CFILESUFFIX'}) + c_file = SCons.Builder.Builder(action={}, + emitter={}, + suffix={None: '$CFILESUFFIX'}) env['BUILDERS']['CFile'] = c_file - env.SetDefault(CFILESUFFIX = '.c') + env.SetDefault(CFILESUFFIX='.c') try: cxx_file = env['BUILDERS']['CXXFile'] except KeyError: - cxx_file = SCons.Builder.Builder(action = {}, - emitter = {}, - suffix = {None:'$CXXFILESUFFIX'}) + cxx_file = SCons.Builder.Builder(action={}, + emitter={}, + suffix={None: '$CXXFILESUFFIX'}) env['BUILDERS']['CXXFile'] = cxx_file - env.SetDefault(CXXFILESUFFIX = '.cc') + env.SetDefault(CXXFILESUFFIX='.cc') return (c_file, cxx_file) + ########################################################################## # Create common Java builders def CreateJarBuilder(env): + """The Jar builder expects a list of class files + which it can package into a jar file. + + The jar tool provides an interface for passing other types + of java files such as .java, directories or swig interfaces + and will build them to class files in which it can package + into the jar. + """ try: - java_jar = env['BUILDERS']['Jar'] + java_jar = env['BUILDERS']['JarFile'] except KeyError: fs = SCons.Node.FS.get_default_fs() jar_com = SCons.Action.Action('$JARCOM', '$JARCOMSTR') - java_jar = SCons.Builder.Builder(action = jar_com, - suffix = '$JARSUFFIX', - src_suffix = '$JAVACLASSSUFFIX', - src_builder = 'JavaClassFile', - source_factory = fs.Entry) - env['BUILDERS']['Jar'] = java_jar + java_jar = SCons.Builder.Builder(action=jar_com, + suffix='$JARSUFFIX', + src_suffix='$JAVACLASSSUFFIX', + src_builder='JavaClassFile', + source_factory=fs.Entry) + env['BUILDERS']['JarFile'] = java_jar return java_jar + def CreateJavaHBuilder(env): try: java_javah = env['BUILDERS']['JavaH'] except KeyError: fs = SCons.Node.FS.get_default_fs() java_javah_com = SCons.Action.Action('$JAVAHCOM', '$JAVAHCOMSTR') - java_javah = SCons.Builder.Builder(action = java_javah_com, - src_suffix = '$JAVACLASSSUFFIX', - target_factory = fs.Entry, - source_factory = fs.File, - src_builder = 'JavaClassFile') + java_javah = SCons.Builder.Builder(action=java_javah_com, + src_suffix='$JAVACLASSSUFFIX', + target_factory=fs.Entry, + source_factory=fs.File, + src_builder='JavaClassFile') env['BUILDERS']['JavaH'] = java_javah return java_javah + def CreateJavaClassFileBuilder(env): try: java_class_file = env['BUILDERS']['JavaClassFile'] except KeyError: fs = SCons.Node.FS.get_default_fs() javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR') - java_class_file = SCons.Builder.Builder(action = javac_com, - emitter = {}, - #suffix = '$JAVACLASSSUFFIX', - src_suffix = '$JAVASUFFIX', - src_builder = ['JavaFile'], - target_factory = fs.Entry, - source_factory = fs.File) + java_class_file = SCons.Builder.Builder(action=javac_com, + emitter={}, + # suffix = '$JAVACLASSSUFFIX', + src_suffix='$JAVASUFFIX', + src_builder=['JavaFile'], + target_factory=fs.Entry, + source_factory=fs.File) env['BUILDERS']['JavaClassFile'] = java_class_file return java_class_file + def CreateJavaClassDirBuilder(env): try: java_class_dir = env['BUILDERS']['JavaClassDir'] except KeyError: fs = SCons.Node.FS.get_default_fs() javac_com = SCons.Action.Action('$JAVACCOM', '$JAVACCOMSTR') - java_class_dir = SCons.Builder.Builder(action = javac_com, - emitter = {}, - target_factory = fs.Dir, - source_factory = fs.Dir) + java_class_dir = SCons.Builder.Builder(action=javac_com, + emitter={}, + target_factory=fs.Dir, + source_factory=fs.Dir) env['BUILDERS']['JavaClassDir'] = java_class_dir return java_class_dir + def CreateJavaFileBuilder(env): try: java_file = env['BUILDERS']['JavaFile'] except KeyError: - java_file = SCons.Builder.Builder(action = {}, - emitter = {}, - suffix = {None:'$JAVASUFFIX'}) + java_file = SCons.Builder.Builder(action={}, + emitter={}, + suffix={None: '$JAVASUFFIX'}) env['BUILDERS']['JavaFile'] = java_file env['JAVASUFFIX'] = '.java' return java_file + class ToolInitializerMethod(object): """ This is added to a construction environment in place of a @@ -984,6 +1053,7 @@ class ToolInitializerMethod(object): whatever builder was (presumably) added to the construction environment in place of this particular instance. """ + def __init__(self, name, initializer): """ Note: we store the tool name as __name__ so it can be used by @@ -1022,6 +1092,7 @@ class ToolInitializerMethod(object): return [], [] return builder(*args, **kw) + class ToolInitializer(object): """ A class for delayed initialization of Tools modules. @@ -1033,6 +1104,7 @@ class ToolInitializer(object): ToolInitializerMethod objects for the various Builder methods that we want to use to delay Tool searches until necessary. """ + def __init__(self, env, tools, names): if not SCons.Util.is_List(tools): tools = [tools] @@ -1067,24 +1139,30 @@ class ToolInitializer(object): env.Tool(tool) return - # If we fall through here, there was no tool module found. - # This is where we can put an informative error message - # about the inability to find the tool. We'll start doing - # this as we cut over more pre-defined Builder+Tools to use - # the ToolInitializer class. + # If we fall through here, there was no tool module found. + # This is where we can put an informative error message + # about the inability to find the tool. We'll start doing + # this as we cut over more pre-defined Builder+Tools to use + # the ToolInitializer class. + def Initializers(env): ToolInitializer(env, ['install'], ['_InternalInstall', '_InternalInstallAs', '_InternalInstallVersionedLib']) + def Install(self, *args, **kw): return self._InternalInstall(*args, **kw) + def InstallAs(self, *args, **kw): return self._InternalInstallAs(*args, **kw) + def InstallVersionedLib(self, *args, **kw): return self._InternalInstallVersionedLib(*args, **kw) + env.AddMethod(Install) env.AddMethod(InstallAs) env.AddMethod(InstallVersionedLib) + def FindTool(tools, env): for tool in tools: t = Tool(tool) @@ -1092,14 +1170,16 @@ def FindTool(tools, env): return tool return None + def FindAllTools(tools, env): def ToolExists(tool, env=env): return Tool(tool).exists(env) - return list(filter (ToolExists, tools)) -def tool_list(platform, env): + return list(filter(ToolExists, tools)) + - other_plat_tools=[] +def tool_list(platform, env): + other_plat_tools = [] # XXX this logic about what tool to prefer on which platform # should be moved into either the platform files or # the tool files themselves. @@ -1107,21 +1187,21 @@ def tool_list(platform, env): # change these search orders, update the man page as well. if str(platform) == 'win32': "prefer Microsoft tools on Windows" - linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32' ] - c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32' ] - cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'cxx', 'bcc32' ] - assemblers = ['masm', 'nasm', 'gas', '386asm' ] + linkers = ['mslink', 'gnulink', 'ilink', 'linkloc', 'ilink32'] + c_compilers = ['msvc', 'mingw', 'gcc', 'intelc', 'icl', 'icc', 'cc', 'bcc32'] + cxx_compilers = ['msvc', 'intelc', 'icc', 'g++', 'cxx', 'bcc32'] + assemblers = ['masm', 'nasm', 'gas', '386asm'] fortran_compilers = ['gfortran', 'g77', 'ifl', 'cvf', 'f95', 'f90', 'fortran'] ars = ['mslib', 'ar', 'tlib'] other_plat_tools = ['msvs', 'midl'] elif str(platform) == 'os2': "prefer IBM tools on OS/2" - linkers = ['ilink', 'gnulink', ]#'mslink'] - c_compilers = ['icc', 'gcc',]# 'msvc', 'cc'] - cxx_compilers = ['icc', 'g++',]# 'msvc', 'cxx'] - assemblers = ['nasm',]# 'masm', 'gas'] + linkers = ['ilink', 'gnulink', ] # 'mslink'] + c_compilers = ['icc', 'gcc', ] # 'msvc', 'cc'] + cxx_compilers = ['icc', 'g++', ] # 'msvc', 'cxx'] + assemblers = ['nasm', ] # 'masm', 'gas'] fortran_compilers = ['ifl', 'g77'] - ars = ['ar',]# 'mslib'] + ars = ['ar', ] # 'mslib'] elif str(platform) == 'irix': "prefer MIPSPro on IRIX" linkers = ['sgilink', 'gnulink'] @@ -1174,11 +1254,11 @@ def tool_list(platform, env): else: "prefer GNU tools on all other platforms" linkers = ['gnulink', 'ilink'] - c_compilers = ['gcc', 'intelc', 'icc', 'cc'] + c_compilers = ['gcc', 'intelc', 'icc', 'cc'] cxx_compilers = ['g++', 'intelc', 'icc', 'cxx'] assemblers = ['gas', 'nasm', 'masm'] fortran_compilers = ['gfortran', 'g77', 'ifort', 'ifl', 'f95', 'f90', 'f77'] - ars = ['ar',] + ars = ['ar', ] if not str(platform) == 'win32': other_plat_tools += ['m4', 'rpm'] @@ -1210,22 +1290,24 @@ def tool_list(platform, env): d_compiler = FindTool(d_compilers, env) or d_compilers[0] other_tools = FindAllTools(other_plat_tools + [ - #TODO: merge 'install' into 'filesystem' and - # make 'filesystem' the default - 'filesystem', - 'wix', #'midl', 'msvs', - # Parser generators - 'lex', 'yacc', - # Foreign function interface - 'rpcgen', 'swig', - # Java - 'jar', 'javac', 'javah', 'rmic', - # TeX - 'dvipdf', 'dvips', 'gs', - 'tex', 'latex', 'pdflatex', 'pdftex', - # Archivers - 'tar', 'zip', - ], env) + # TODO: merge 'install' into 'filesystem' and + # make 'filesystem' the default + 'filesystem', + 'wix', # 'midl', 'msvs', + # Parser generators + 'lex', 'yacc', + # Foreign function interface + 'rpcgen', 'swig', + # Java + 'jar', 'javac', 'javah', 'rmic', + # TeX + 'dvipdf', 'dvips', 'gs', + 'tex', 'latex', 'pdflatex', 'pdftex', + # Archivers + 'tar', 'zip', + # File builders (text) + 'textfile', + ], env) tools = ([linker, c_compiler, cxx_compiler, fortran_compiler, assembler, ar, d_compiler] @@ -1233,6 +1315,33 @@ def tool_list(platform, env): return [x for x in tools if x] + +def find_program_path(env, key_program, default_paths=[]): + """ + Find the location of key_program and then return the path it was located at. + Checking the default install locations. + Mainly for windows where tools aren't all installed in /usr/bin,etc + :param env: Current Environment() + :param key_program: Program we're using to locate the directory to add to PATH. + """ + # First search in the SCons path + path = env.WhereIs(key_program) + if (path): + return path + # then the OS path: + path = SCons.Util.WhereIs(key_program) + if (path): + return path + + # If that doesn't work try default location for mingw + save_path = env['ENV']['PATH'] + for p in default_paths: + env.AppendENVPath('PATH', p) + path = env.WhereIs(key_program) + if not path: + env['ENV']['PATH'] = save_path + return path + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/Tool/__init__.xml b/src/engine/SCons/Tool/__init__.xml index 32b8ce6..80fd2f6 100644 --- a/src/engine/SCons/Tool/__init__.xml +++ b/src/engine/SCons/Tool/__init__.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/aixc++.py b/src/engine/SCons/Tool/aixc++.py index 0a2465d..be14abc 100644 --- a/src/engine/SCons/Tool/aixc++.py +++ b/src/engine/SCons/Tool/aixc++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixc++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixc++.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" #forward proxy to the preffered cxx version from SCons.Tool.aixcxx import * diff --git a/src/engine/SCons/Tool/aixc++.xml b/src/engine/SCons/Tool/aixc++.xml index 04a27f6..0d50ae9 100644 --- a/src/engine/SCons/Tool/aixc++.xml +++ b/src/engine/SCons/Tool/aixc++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/aixcc.py b/src/engine/SCons/Tool/aixcc.py index aa351cd..a1fe216 100644 --- a/src/engine/SCons/Tool/aixcc.py +++ b/src/engine/SCons/Tool/aixcc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixcc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixcc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path diff --git a/src/engine/SCons/Tool/aixcc.xml b/src/engine/SCons/Tool/aixcc.xml index 44ee0bc..aa0e604 100644 --- a/src/engine/SCons/Tool/aixcc.xml +++ b/src/engine/SCons/Tool/aixcc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/aixcxx.py b/src/engine/SCons/Tool/aixcxx.py index 97bd8a6..ec2af1a 100644 --- a/src/engine/SCons/Tool/aixcxx.py +++ b/src/engine/SCons/Tool/aixcxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixcxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixcxx.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path diff --git a/src/engine/SCons/Tool/aixf77.py b/src/engine/SCons/Tool/aixf77.py index c72346c..6281b13 100644 --- a/src/engine/SCons/Tool/aixf77.py +++ b/src/engine/SCons/Tool/aixf77.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixf77.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixf77.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path diff --git a/src/engine/SCons/Tool/aixf77.xml b/src/engine/SCons/Tool/aixf77.xml index 69f4d92..ee4d232 100644 --- a/src/engine/SCons/Tool/aixf77.xml +++ b/src/engine/SCons/Tool/aixf77.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/aixlink.py b/src/engine/SCons/Tool/aixlink.py index fd67d66..ddb4281 100644 --- a/src/engine/SCons/Tool/aixlink.py +++ b/src/engine/SCons/Tool/aixlink.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/aixlink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/aixlink.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path diff --git a/src/engine/SCons/Tool/aixlink.xml b/src/engine/SCons/Tool/aixlink.xml index d5438ef..0f7fc62 100644 --- a/src/engine/SCons/Tool/aixlink.xml +++ b/src/engine/SCons/Tool/aixlink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/applelink.py b/src/engine/SCons/Tool/applelink.py index 45f524c..5981d19 100644 --- a/src/engine/SCons/Tool/applelink.py +++ b/src/engine/SCons/Tool/applelink.py @@ -1,6 +1,6 @@ """SCons.Tool.applelink -Tool-specific initialization for the Apple gnu-like linker. +Tool-specific initialization for Apple's gnu-like linker. There normally shouldn't be any need to import this module directly. It will usually be imported through the generic SCons.Tool.Tool() @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/applelink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/applelink.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util @@ -39,25 +39,162 @@ import SCons.Util # the -rpath option, so we use the "link" tool instead of "gnulink". from . import link + +class AppleLinkInvalidCurrentVersionException(Exception): + pass + +class AppleLinkInvalidCompatibilityVersionException(Exception): + pass + + +def _applelib_versioned_lib_suffix(env, suffix, version): + """For suffix='.dylib' and version='0.1.2' it returns '.0.1.2.dylib'""" + Verbose = False + if Verbose: + print("_applelib_versioned_lib_suffix: suffix={!r}".format(suffix)) + print("_applelib_versioned_lib_suffix: version={!r}".format(version)) + if version not in suffix: + suffix = "." + version + suffix + if Verbose: + print("_applelib_versioned_lib_suffix: return suffix={!r}".format(suffix)) + return suffix + + +def _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, name_func): + """For libnode='/optional/dir/libfoo.X.Y.Z.dylib' it returns 'libfoo.X.dylib'""" + Verbose = False + if Verbose: + print("_applelib_versioned_lib_soname: version={!r}".format(version)) + name = name_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_applelib_versioned_lib_soname: name={!r}".format(name)) + major = version.split('.')[0] + (libname,_suffix) = name.split('.') + soname = '.'.join([libname, major, _suffix]) + if Verbose: + print("_applelib_versioned_lib_soname: soname={!r}".format(soname)) + return soname + +def _applelib_versioned_shlib_soname(env, libnode, version, prefix, suffix): + return _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, link._versioned_shlib_name) + + +# User programmatically describes how SHLIBVERSION maps to values for compat/current. +_applelib_max_version_values = (65535, 255, 255) +def _applelib_check_valid_version(version_string): + """ + Check that the version # is valid. + X[.Y[.Z]] + where X 0-65535 + where Y either not specified or 0-255 + where Z either not specified or 0-255 + :param version_string: + :return: + """ + parts = version_string.split('.') + if len(parts) > 3: + return False, "Version string has too many periods [%s]"%version_string + if len(parts) <= 0: + return False, "Version string unspecified [%s]"%version_string + + for (i, p) in enumerate(parts): + try: + p_i = int(p) + except ValueError: + return False, "Version component %s (from %s) is not a number"%(p, version_string) + if p_i < 0 or p_i > _applelib_max_version_values[i]: + return False, "Version component %s (from %s) is not valid value should be between 0 and %d"%(p, version_string, _applelib_max_version_values[i]) + + return True, "" + + +def _applelib_currentVersionFromSoVersion(source, target, env, for_signature): + """ + A generator function to create the -Wl,-current_version flag if needed. + If env['APPLELINK_NO_CURRENT_VERSION'] contains a true value no flag will be generated + Otherwise if APPLELINK_CURRENT_VERSION is not specified, env['SHLIBVERSION'] + will be used. + + :param source: + :param target: + :param env: + :param for_signature: + :return: A string providing the flag to specify the current_version of the shared library + """ + if env.get('APPLELINK_NO_CURRENT_VERSION', False): + return "" + elif env.get('APPLELINK_CURRENT_VERSION', False): + version_string = env['APPLELINK_CURRENT_VERSION'] + elif env.get('SHLIBVERSION', False): + version_string = env['SHLIBVERSION'] + else: + return "" + + version_string = ".".join(version_string.split('.')[:3]) + + valid, reason = _applelib_check_valid_version(version_string) + if not valid: + raise AppleLinkInvalidCurrentVersionException(reason) + + return "-Wl,-current_version,%s" % version_string + + +def _applelib_compatVersionFromSoVersion(source, target, env, for_signature): + """ + A generator function to create the -Wl,-compatibility_version flag if needed. + If env['APPLELINK_NO_COMPATIBILITY_VERSION'] contains a true value no flag will be generated + Otherwise if APPLELINK_COMPATIBILITY_VERSION is not specified + the first two parts of env['SHLIBVERSION'] will be used with a .0 appended. + + :param source: + :param target: + :param env: + :param for_signature: + :return: A string providing the flag to specify the compatibility_version of the shared library + """ + if env.get('APPLELINK_NO_COMPATIBILITY_VERSION', False): + return "" + elif env.get('APPLELINK_COMPATIBILITY_VERSION', False): + version_string = env['APPLELINK_COMPATIBILITY_VERSION'] + elif env.get('SHLIBVERSION', False): + version_string = ".".join(env['SHLIBVERSION'].split('.')[:2] + ['0']) + else: + return "" + + if version_string is None: + return "" + + valid, reason = _applelib_check_valid_version(version_string) + if not valid: + raise AppleLinkInvalidCompatibilityVersionException(reason) + + return "-Wl,-compatibility_version,%s" % version_string + + def generate(env): """Add Builders and construction variables for applelink to an Environment.""" link.generate(env) env['FRAMEWORKPATHPREFIX'] = '-F' - env['_FRAMEWORKPATH'] = '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__)}' + env['_FRAMEWORKPATH'] = '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__, RDirs)}' + env['_FRAMEWORKS'] = '${_concat("-framework ", FRAMEWORKS, "", __env__)}' env['LINKCOM'] = env['LINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -dynamiclib') env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' - # TODO: Work needed to generate versioned shared libraries - # Leaving this commented out, and also going to disable versioned library checking for now # see: http://docstore.mik.ua/orelly/unix3/mac/ch05_04.htm for proper naming - #link._setup_versioned_lib_variables(env, tool = 'applelink')#, use_soname = use_soname) - #env['LINKCALLBACKS'] = link._versioned_lib_callbacks() + link._setup_versioned_lib_variables(env, tool = 'applelink')#, use_soname = use_soname) + env['LINKCALLBACKS'] = link._versioned_lib_callbacks() + env['LINKCALLBACKS']['VersionedShLibSuffix'] = _applelib_versioned_lib_suffix + env['LINKCALLBACKS']['VersionedShLibSoname'] = _applelib_versioned_shlib_soname + env['_APPLELINK_CURRENT_VERSION'] = _applelib_currentVersionFromSoVersion + env['_APPLELINK_COMPATIBILITY_VERSION'] = _applelib_compatVersionFromSoVersion + env['_SHLIBVERSIONFLAGS'] = '$_APPLELINK_CURRENT_VERSION $_APPLELINK_COMPATIBILITY_VERSION ' + env['_LDMODULEVERSIONFLAGS'] = '$_APPLELINK_CURRENT_VERSION $_APPLELINK_COMPATIBILITY_VERSION ' # override the default for loadable modules, which are different # on OS X than dynamic shared libs. echoing what XCode does for @@ -67,6 +204,8 @@ def generate(env): env['LDMODULEFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -bundle') env['LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' + env['__SHLIBVERSIONFLAGS'] = '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}' + def exists(env): diff --git a/src/engine/SCons/Tool/applelink.xml b/src/engine/SCons/Tool/applelink.xml index 699abf0..c7209fa 100644 --- a/src/engine/SCons/Tool/applelink.xml +++ b/src/engine/SCons/Tool/applelink.xml @@ -1,155 +1,254 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. --> <!DOCTYPE sconsdoc [ -<!ENTITY % scons SYSTEM '../../../../doc/scons.mod'> -%scons; -<!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'> -%builders-mod; -<!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'> -%functions-mod; -<!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'> -%tools-mod; -<!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'> -%variables-mod; -]> + <!ENTITY % scons SYSTEM '../../../../doc/scons.mod'> + %scons; + <!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'> + %builders-mod; + <!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'> + %functions-mod; + <!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'> + %tools-mod; + <!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'> + %variables-mod; + ]> <sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd"> -<tool name="applelink"> -<summary> -<para> -Sets construction variables for the Apple linker -(similar to the GNU linker). -</para> -</summary> -<sets> -<item>FRAMEWORKPATHPREFIX</item> -<item>_FRAMEWORKPATH</item> -<item>_FRAMEWORKS</item> -<item>LINKCOM</item> -<item>SHLINKFLAGS</item> -<item>SHLINKCOM</item> -<item>LDMODULEPREFIX</item> -<item>LDMODULESUFFIX</item> -<item>LDMODULEFLAGS</item> -<item>LDMODULECOM</item> -</sets> -<uses> -<item>FRAMEWORKSFLAGS</item> -</uses> -</tool> - -<cvar name="FRAMEWORKSFLAGS">"> -<summary> -<para> -On Mac OS X with gcc, -general user-supplied frameworks options to be added at -the end of a command -line building a loadable module. -(This has been largely superseded by -the &cv-link-FRAMEWORKPATH;, &cv-link-FRAMEWORKPATHPREFIX;, -&cv-link-FRAMEWORKPREFIX; and &cv-link-FRAMEWORKS; variables -described above.) -</para> -</summary> -</cvar> - -<cvar name="FRAMEWORKS"> -<summary> -<para> -On Mac OS X with gcc, a list of the framework names to be linked into a -program or shared library or bundle. -The default value is the empty list. -For example: -</para> - -<example_commands> - env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) -</example_commands> - -</summary> -</cvar> - -<cvar name="FRAMEWORKPREFIX"> -<summary> -<para> -On Mac OS X with gcc, -the prefix to be used for linking in frameworks -(see &cv-link-FRAMEWORKS;). -The default value is -<option>-framework</option>. -</para> -</summary> -</cvar> - -<cvar name="_FRAMEWORKS"> -<summary> -<para> -On Mac OS X with gcc, -an automatically-generated construction variable -containing the linker command-line options -for linking with FRAMEWORKS. -</para> -</summary> -</cvar> - -<cvar name="FRAMEWORKPATH"> -<summary> -<para> -On Mac OS X with gcc, -a list containing the paths to search for frameworks. -Used by the compiler to find framework-style includes like -#include <Fmwk/Header.h>. -Used by the linker to find user-specified frameworks when linking (see -&cv-link-FRAMEWORKS;). -For example: -</para> - -<example_commands> - env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') -</example_commands> - -<para> -will add -</para> - -<example_commands> - ... -Fmyframeworkdir -</example_commands> - -<para> -to the compiler and linker command lines. -</para> -</summary> -</cvar> - -<cvar name="FRAMEWORKPATHPREFIX"> -<summary> -<para> -On Mac OS X with gcc, the prefix to be used for the FRAMEWORKPATH entries. -(see &cv-link-FRAMEWORKPATH;). -The default value is -<option>-F</option>. -</para> -</summary> -</cvar> - -<cvar name="_FRAMEWORKPATH"> -<summary> -<para> -On Mac OS X with gcc, an automatically-generated construction variable -containing the linker command-line options corresponding to -&cv-link-FRAMEWORKPATH;. -</para> -</summary> -</cvar> + <tool name="applelink"> + <summary> + <para> + Sets construction variables for the Apple linker + (similar to the GNU linker). + </para> + </summary> + <sets> + <item>FRAMEWORKPATHPREFIX</item> + <item>_FRAMEWORKPATH</item> + <item>_FRAMEWORKS</item> + <item>LINKCOM</item> + <item>SHLINKFLAGS</item> + <item>SHLINKCOM</item> + <item>LDMODULEPREFIX</item> + <item>LDMODULESUFFIX</item> + <item>LDMODULEFLAGS</item> + <item>LDMODULECOM</item> + <item>APPLELINK_CURRENT_VERSION</item> + <item>APPLELINK_COMPATIBILITY_VERSION</item> + <item>APPLELINK_NO_CURRENT_VERSION</item> + <item>APPLELINK_NO_COMPATIBILITY_VERSION</item> + <item>_APPLELINK_CURRENT_VERSION</item> + <item>_APPLELINK_COMPATIBILITY_VERSION</item> + </sets> + <uses> + <item>FRAMEWORKSFLAGS</item> + </uses> + </tool> + + + <cvar name="APPLELINK_COMPATIBILITY_VERSION"> + <summary> + <para> + On Mac OS X this is used to set the linker flag: + + -compatibility_version + </para> + <para> + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and + 255, Z can be omitted or between 1 and 255. This value will be derived from &cv-link-SHLIBVERSION; if + not + specified. The lowest digit will be dropped and replaced by a 0. + </para> + <para> + If the &cv-link-APPLELINK_NO_COMPATIBILITY_VERSION; is set then no -compatibility_version will be + output. + </para> + <para>See MacOS's ld manpage for more details</para> + </summary> + </cvar> + + <cvar name="APPLELINK_NO_COMPATIBILITY_VERSION"> + <summary> + <para> + Set this to any True (1|True|non-empty string) value to disable adding -compatibility_version flag when + generating versioned shared libraries. + </para> + <para> + This overrides &cv-link-APPLELINK_COMPATIBILITY_VERSION;. + </para> + </summary> + </cvar> + + + <cvar name="_APPLELINK_COMPATIBILITY_VERSION"> + <summary> + <para> + A macro (by default a generator function) used to create the linker flags to specify + apple's linker's -compatibility_version flag. + The default generator uses &cv-link-APPLELINK_COMPATIBILITY_VERSION; + and &cv-link-APPLELINK_NO_COMPATIBILITY_VERSION; and &cv-link-SHLIBVERSION; + to determine the correct flag. + </para> + </summary> + </cvar> + + + <cvar name="APPLELINK_CURRENT_VERSION"> + <summary> + <para> + On Mac OS X this is used to set the linker flag: + + -current_version + </para> + <para> + The value is specified as X[.Y[.Z]] where X is between 1 and 65535, Y can be omitted or between 1 and + 255, Z can be omitted or between 1 and 255. This value will be set to &cv-link-SHLIBVERSION; if not + specified. + </para> + <para> + If the &cv-link-APPLELINK_NO_CURRENT_VERSION; is set then no -current_version will be + output. + </para> + <para>See MacOS's ld manpage for more details</para> + + </summary> + </cvar> + + + <cvar name="APPLELINK_NO_CURRENT_VERSION"> + <summary> + <para> + Set this to any True (1|True|non-empty string) value to disable adding -current_version flag when + generating versioned shared libraries. + </para> + <para> + This overrides &cv-link-APPLELINK_CURRENT_VERSION;. + </para> + </summary> + </cvar> + + <cvar name="_APPLELINK_CURRENT_VERSION"> + <summary> + <para> + A macro (by default a generator function) used to create the linker flags to specify apple's linker's + -current_version flag. The default generator uses &cv-link-APPLELINK_CURRENT_VERSION; and + &cv-link-APPLELINK_NO_CURRENT_VERSION; and &cv-link-SHLIBVERSION; to determine the correct flag. + </para> + </summary> + </cvar> + + + <cvar name="FRAMEWORKSFLAGS">"> + <summary> + <para> + On Mac OS X with gcc, + general user-supplied frameworks options to be added at + the end of a command + line building a loadable module. + (This has been largely superseded by + the &cv-link-FRAMEWORKPATH;, &cv-link-FRAMEWORKPATHPREFIX;, + &cv-link-FRAMEWORKPREFIX; and &cv-link-FRAMEWORKS; variables + described above.) + </para> + </summary> + </cvar> + + <cvar name="FRAMEWORKS"> + <summary> + <para> + On Mac OS X with gcc, a list of the framework names to be linked into a + program or shared library or bundle. + The default value is the empty list. + For example: + </para> + + <example_commands> + env.AppendUnique(FRAMEWORKS=Split('System Cocoa SystemConfiguration')) + </example_commands> + + </summary> + </cvar> + + <cvar name="FRAMEWORKPREFIX"> + <summary> + <para> + On Mac OS X with gcc, + the prefix to be used for linking in frameworks + (see &cv-link-FRAMEWORKS;). + The default value is + <option>-framework</option>. + </para> + </summary> + </cvar> + + <cvar name="_FRAMEWORKS"> + <summary> + <para> + On Mac OS X with gcc, + an automatically-generated construction variable + containing the linker command-line options + for linking with FRAMEWORKS. + </para> + </summary> + </cvar> + + <cvar name="FRAMEWORKPATH"> + <summary> + <para> + On Mac OS X with gcc, + a list containing the paths to search for frameworks. + Used by the compiler to find framework-style includes like + #include <Fmwk/Header.h>. + Used by the linker to find user-specified frameworks when linking (see + &cv-link-FRAMEWORKS;). + For example: + </para> + + <example_commands> + env.AppendUnique(FRAMEWORKPATH='#myframeworkdir') + </example_commands> + + <para> + will add + </para> + + <example_commands> + ... -Fmyframeworkdir + </example_commands> + + <para> + to the compiler and linker command lines. + </para> + </summary> + </cvar> + + <cvar name="FRAMEWORKPATHPREFIX"> + <summary> + <para> + On Mac OS X with gcc, the prefix to be used for the FRAMEWORKPATH entries. + (see &cv-link-FRAMEWORKPATH;). + The default value is + <option>-F</option>. + </para> + </summary> + </cvar> + + <cvar name="_FRAMEWORKPATH"> + <summary> + <para> + On Mac OS X with gcc, an automatically-generated construction variable + containing the linker command-line options corresponding to + &cv-link-FRAMEWORKPATH;. + </para> + </summary> + </cvar> </sconsdoc> diff --git a/src/engine/SCons/Tool/ar.py b/src/engine/SCons/Tool/ar.py index 4d2a005..bef719f 100644 --- a/src/engine/SCons/Tool/ar.py +++ b/src/engine/SCons/Tool/ar.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ar.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/ar.xml b/src/engine/SCons/Tool/ar.xml index 9b9e0a0..573c80b 100644 --- a/src/engine/SCons/Tool/ar.xml +++ b/src/engine/SCons/Tool/ar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/as.py b/src/engine/SCons/Tool/as.py index ab81b89..8deea59 100644 --- a/src/engine/SCons/Tool/as.py +++ b/src/engine/SCons/Tool/as.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/as.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/as.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/as.xml b/src/engine/SCons/Tool/as.xml index f4d886d..c2d1814 100644 --- a/src/engine/SCons/Tool/as.xml +++ b/src/engine/SCons/Tool/as.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/bcc32.py b/src/engine/SCons/Tool/bcc32.py index bf0a5dd..1cb0a38 100644 --- a/src/engine/SCons/Tool/bcc32.py +++ b/src/engine/SCons/Tool/bcc32.py @@ -5,7 +5,7 @@ XXX """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ XXX # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/bcc32.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/bcc32.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path diff --git a/src/engine/SCons/Tool/bcc32.xml b/src/engine/SCons/Tool/bcc32.xml index 6163016..b2d8394 100644 --- a/src/engine/SCons/Tool/bcc32.xml +++ b/src/engine/SCons/Tool/bcc32.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/c++.py b/src/engine/SCons/Tool/c++.py index ebfe0a4..e670d0d 100644 --- a/src/engine/SCons/Tool/c++.py +++ b/src/engine/SCons/Tool/c++.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/c++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/c++.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" #forward proxy to the preffered cxx version diff --git a/src/engine/SCons/Tool/c++.xml b/src/engine/SCons/Tool/c++.xml index e2021fc..c10438a 100644 --- a/src/engine/SCons/Tool/c++.xml +++ b/src/engine/SCons/Tool/c++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/cc.py b/src/engine/SCons/Tool/cc.py index 31e7b2b..9b604c4 100644 --- a/src/engine/SCons/Tool/cc.py +++ b/src/engine/SCons/Tool/cc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/cc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Tool import SCons.Defaults diff --git a/src/engine/SCons/Tool/cc.xml b/src/engine/SCons/Tool/cc.xml index 1ec3084..735f700 100644 --- a/src/engine/SCons/Tool/cc.xml +++ b/src/engine/SCons/Tool/cc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/clang.py b/src/engine/SCons/Tool/clang.py index 1271378..69cbbb6 100644 --- a/src/engine/SCons/Tool/clang.py +++ b/src/engine/SCons/Tool/clang.py @@ -11,7 +11,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -# __revision__ = "src/engine/SCons/Tool/clang.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +# __revision__ = "src/engine/SCons/Tool/clang.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" # Based on SCons/Tool/gcc.py by Paweł Tomulik 2014 as a separate tool. # Brought into the SCons mainline by Russel Winder 2017. @@ -45,6 +45,8 @@ import sys import SCons.Util import SCons.Tool.cc +from SCons.Tool.clangCommon import get_clang_install_dirs + compilers = ['clang'] @@ -52,11 +54,20 @@ def generate(env): """Add Builders and construction variables for clang to an Environment.""" SCons.Tool.cc.generate(env) + if env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for clang + clang = SCons.Tool.find_program_path(env, compilers[0], + default_paths=get_clang_install_dirs(env['PLATFORM'])) + if clang: + clang_bin_dir = os.path.dirname(clang) + env.AppendENVPath('PATH', clang_bin_dir) + env['CC'] = env.Detect(compilers) or 'clang' if env['PLATFORM'] in ['cygwin', 'win32']: env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS') else: env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS -fPIC') + # determine compiler version if env['CC']: #pipe = SCons.Action._subproc(env, [env['CC'], '-dumpversion'], diff --git a/src/engine/SCons/Tool/clang.xml b/src/engine/SCons/Tool/clang.xml index 3086a51..a546946 100644 --- a/src/engine/SCons/Tool/clang.xml +++ b/src/engine/SCons/Tool/clang.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/clangCommon/__init__.py b/src/engine/SCons/Tool/clangCommon/__init__.py new file mode 100644 index 0000000..37efbf6 --- /dev/null +++ b/src/engine/SCons/Tool/clangCommon/__init__.py @@ -0,0 +1,17 @@ +""" +Common routines and data for clang tools +""" + +clang_win32_dirs = [ + r'C:\Program Files\LLVM\bin', + r'C:\cygwin64\bin', + r'C:\msys64', + r'C:\cygwin\bin', + r'C:\msys', +] + +def get_clang_install_dirs(platform): + if platform == 'win32': + return clang_win32_dirs + else: + return []
\ No newline at end of file diff --git a/src/engine/SCons/Tool/clangxx.py b/src/engine/SCons/Tool/clangxx.py index f56c9e5..7899228 100644 --- a/src/engine/SCons/Tool/clangxx.py +++ b/src/engine/SCons/Tool/clangxx.py @@ -11,7 +11,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -# __revision__ = "src/engine/SCons/Tool/clangxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +# __revision__ = "src/engine/SCons/Tool/clangxx.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" # Based on SCons/Tool/g++.py by Paweł Tomulik 2014 as a separate tool. # Brought into the SCons mainline by Russel Winder 2017. @@ -46,6 +46,8 @@ import sys import SCons.Tool import SCons.Util import SCons.Tool.cxx +from SCons.Tool.clangCommon import get_clang_install_dirs + compilers = ['clang++'] @@ -66,13 +68,22 @@ def generate(env): env['SHOBJSUFFIX'] = '.pic.o' elif env['PLATFORM'] == 'sunos': env['SHOBJSUFFIX'] = '.pic.o' + elif env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for clang++ + clangxx = SCons.Tool.find_program_path(env, compilers[0], default_paths=get_clang_install_dirs(env['PLATFORM'])) + if clangxx: + clangxx_bin_dir = os.path.dirname(clangxx) + env.AppendENVPath('PATH', clangxx_bin_dir) + # determine compiler version if env['CXX']: pipe = SCons.Action._subproc(env, [env['CXX'], '--version'], stdin='devnull', stderr='devnull', stdout=subprocess.PIPE) - if pipe.wait() != 0: return + if pipe.wait() != 0: + return + # clang -dumpversion is of no use line = pipe.stdout.readline() if sys.version_info[0] > 2: diff --git a/src/engine/SCons/Tool/clangxx.xml b/src/engine/SCons/Tool/clangxx.xml index 309bb63..7372389 100644 --- a/src/engine/SCons/Tool/clangxx.xml +++ b/src/engine/SCons/Tool/clangxx.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/cvf.py b/src/engine/SCons/Tool/cvf.py index a785471..bc1e888 100644 --- a/src/engine/SCons/Tool/cvf.py +++ b/src/engine/SCons/Tool/cvf.py @@ -5,7 +5,7 @@ Tool-specific initialization for the Compaq Visual Fortran compiler. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Tool-specific initialization for the Compaq Visual Fortran compiler. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cvf.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/cvf.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from . import fortran diff --git a/src/engine/SCons/Tool/cvf.xml b/src/engine/SCons/Tool/cvf.xml index 1b2c447..b56c23c 100644 --- a/src/engine/SCons/Tool/cvf.xml +++ b/src/engine/SCons/Tool/cvf.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/cxx.py b/src/engine/SCons/Tool/cxx.py index 236730f..81a67c7 100644 --- a/src/engine/SCons/Tool/cxx.py +++ b/src/engine/SCons/Tool/cxx.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/cxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/cxx.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path diff --git a/src/engine/SCons/Tool/cyglink.xml b/src/engine/SCons/Tool/cyglink.xml index 13556e8..a0aefac 100644 --- a/src/engine/SCons/Tool/cyglink.xml +++ b/src/engine/SCons/Tool/cyglink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/default.py b/src/engine/SCons/Tool/default.py index 72d3399..e8aa11b 100644 --- a/src/engine/SCons/Tool/default.py +++ b/src/engine/SCons/Tool/default.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/default.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/default.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Tool diff --git a/src/engine/SCons/Tool/default.xml b/src/engine/SCons/Tool/default.xml index 3683a10..8e1ed21 100644 --- a/src/engine/SCons/Tool/default.xml +++ b/src/engine/SCons/Tool/default.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/dmd.py b/src/engine/SCons/Tool/dmd.py index 1dfb5d7..b281e1c 100644 --- a/src/engine/SCons/Tool/dmd.py +++ b/src/engine/SCons/Tool/dmd.py @@ -31,7 +31,7 @@ Lib tool variables: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -53,7 +53,7 @@ Lib tool variables: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dmd.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dmd.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import subprocess diff --git a/src/engine/SCons/Tool/dmd.xml b/src/engine/SCons/Tool/dmd.xml index a06db10..5149503 100644 --- a/src/engine/SCons/Tool/dmd.xml +++ b/src/engine/SCons/Tool/dmd.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/docbook/__init__.py b/src/engine/SCons/Tool/docbook/__init__.py index ed63784..d7d10c0 100644 --- a/src/engine/SCons/Tool/docbook/__init__.py +++ b/src/engine/SCons/Tool/docbook/__init__.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -166,6 +166,8 @@ xsltproc_com_priority = ['xsltproc', 'saxon', 'saxon-xslt', 'xalan'] # see: http://saxon.sourceforge.net/ xsltproc_com = {'xsltproc' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $DOCBOOK_XSL $SOURCE', 'saxon' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $DOCBOOK_XSL $SOURCE $DOCBOOK_XSLTPROCPARAMS', + # Note if saxon-xslt is version 5.5 the proper arguments are: (swap order of docbook_xsl and source) + # 'saxon-xslt' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $SOURCE $DOCBOOK_XSL $DOCBOOK_XSLTPROCPARAMS', 'saxon-xslt' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -o $TARGET $DOCBOOK_XSL $SOURCE $DOCBOOK_XSLTPROCPARAMS', 'xalan' : '$DOCBOOK_XSLTPROC $DOCBOOK_XSLTPROCFLAGS -q -out $TARGET -xsl $DOCBOOK_XSL -in $SOURCE'} xmllint_com = {'xmllint' : '$DOCBOOK_XMLLINT $DOCBOOK_XMLLINTFLAGS --xinclude $SOURCE > $TARGET'} diff --git a/src/engine/SCons/Tool/docbook/__init__.xml b/src/engine/SCons/Tool/docbook/__init__.xml index 1994392..3110649 100644 --- a/src/engine/SCons/Tool/docbook/__init__.xml +++ b/src/engine/SCons/Tool/docbook/__init__.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/docbook/docs/manual.xml b/src/engine/SCons/Tool/docbook/docs/manual.xml index c129753..64ee925 100644 --- a/src/engine/SCons/Tool/docbook/docs/manual.xml +++ b/src/engine/SCons/Tool/docbook/docs/manual.xml @@ -67,7 +67,7 @@ package's <literal>docbook</literal> folder to <itemizedlist><listitem><para>the SCons User's Guide, chap. 19.7 "Where to put your custom Builders and Tools" and </para> </listitem> -<listitem><para>the SCons Tools Wiki page at <ulink url="http://scons.org/wiki/ToolsIndex">http://scons.org/wiki/ToolsIndex</ulink>. +<listitem><para>the SCons Tools Wiki page at <ulink url="https://github.com/SCons/scons/wiki/ToolsIndex">http://github.com/SCons/scons/wiki/ToolsIndex</ulink>. </para> </listitem> </itemizedlist> diff --git a/src/engine/SCons/Tool/dvi.py b/src/engine/SCons/Tool/dvi.py index 9ec1563..9844e37 100644 --- a/src/engine/SCons/Tool/dvi.py +++ b/src/engine/SCons/Tool/dvi.py @@ -5,7 +5,7 @@ Common DVI Builder definition for various other Tool modules that use it. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Common DVI Builder definition for various other Tool modules that use it. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dvi.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dvi.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Builder import SCons.Tool diff --git a/src/engine/SCons/Tool/dvi.xml b/src/engine/SCons/Tool/dvi.xml index 1ec2ef0..82ff01b 100644 --- a/src/engine/SCons/Tool/dvi.xml +++ b/src/engine/SCons/Tool/dvi.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/dvipdf.py b/src/engine/SCons/Tool/dvipdf.py index 339155d..a4d7d93 100644 --- a/src/engine/SCons/Tool/dvipdf.py +++ b/src/engine/SCons/Tool/dvipdf.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/dvipdf.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dvipdf.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Action import SCons.Defaults diff --git a/src/engine/SCons/Tool/dvipdf.xml b/src/engine/SCons/Tool/dvipdf.xml index a5d2018..683ca72 100644 --- a/src/engine/SCons/Tool/dvipdf.xml +++ b/src/engine/SCons/Tool/dvipdf.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/dvips.py b/src/engine/SCons/Tool/dvips.py index 95641d6..30a79ba 100644 --- a/src/engine/SCons/Tool/dvips.py +++ b/src/engine/SCons/Tool/dvips.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/dvips.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/dvips.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Action import SCons.Builder diff --git a/src/engine/SCons/Tool/dvips.xml b/src/engine/SCons/Tool/dvips.xml index 7f47592..9838db1 100644 --- a/src/engine/SCons/Tool/dvips.xml +++ b/src/engine/SCons/Tool/dvips.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f03.py b/src/engine/SCons/Tool/f03.py index a9f91a8..64b67bf 100644 --- a/src/engine/SCons/Tool/f03.py +++ b/src/engine/SCons/Tool/f03.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f03.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f03.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/f03.xml b/src/engine/SCons/Tool/f03.xml index e486acf..af9da30 100644 --- a/src/engine/SCons/Tool/f03.xml +++ b/src/engine/SCons/Tool/f03.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f08.py b/src/engine/SCons/Tool/f08.py index eb44487..3c317f5 100644 --- a/src/engine/SCons/Tool/f08.py +++ b/src/engine/SCons/Tool/f08.py @@ -11,7 +11,7 @@ selection method. from __future__ import absolute_import # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ from __future__ import absolute_import # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f08.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f08.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/f08.xml b/src/engine/SCons/Tool/f08.xml index aac7b66..4c07890 100644 --- a/src/engine/SCons/Tool/f08.xml +++ b/src/engine/SCons/Tool/f08.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f77.py b/src/engine/SCons/Tool/f77.py index afa9a7b..8ff5f5c 100644 --- a/src/engine/SCons/Tool/f77.py +++ b/src/engine/SCons/Tool/f77.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f77.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f77.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Scanner.Fortran diff --git a/src/engine/SCons/Tool/f77.xml b/src/engine/SCons/Tool/f77.xml index 210c646..7ce1159 100644 --- a/src/engine/SCons/Tool/f77.xml +++ b/src/engine/SCons/Tool/f77.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f90.py b/src/engine/SCons/Tool/f90.py index f66ed47..6f80821 100644 --- a/src/engine/SCons/Tool/f90.py +++ b/src/engine/SCons/Tool/f90.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f90.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f90.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Scanner.Fortran diff --git a/src/engine/SCons/Tool/f90.xml b/src/engine/SCons/Tool/f90.xml index b5f7f13..f8c1854 100644 --- a/src/engine/SCons/Tool/f90.xml +++ b/src/engine/SCons/Tool/f90.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/f95.py b/src/engine/SCons/Tool/f95.py index bc5439f..363245c 100644 --- a/src/engine/SCons/Tool/f95.py +++ b/src/engine/SCons/Tool/f95.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/f95.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/f95.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/f95.xml b/src/engine/SCons/Tool/f95.xml index f1cb7c2..a575ad0 100644 --- a/src/engine/SCons/Tool/f95.xml +++ b/src/engine/SCons/Tool/f95.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/filesystem.py b/src/engine/SCons/Tool/filesystem.py index 6615c31..c3c79ce 100644 --- a/src/engine/SCons/Tool/filesystem.py +++ b/src/engine/SCons/Tool/filesystem.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/filesystem.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/filesystem.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons from SCons.Tool.install import copyFunc diff --git a/src/engine/SCons/Tool/fortran.py b/src/engine/SCons/Tool/fortran.py index b99b5e6..c090b00 100644 --- a/src/engine/SCons/Tool/fortran.py +++ b/src/engine/SCons/Tool/fortran.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/fortran.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/fortran.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import re diff --git a/src/engine/SCons/Tool/fortran.xml b/src/engine/SCons/Tool/fortran.xml index 3907ce2..0fde8f1 100644 --- a/src/engine/SCons/Tool/fortran.xml +++ b/src/engine/SCons/Tool/fortran.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -125,7 +125,8 @@ containing the Fortran compiler command-line options for specifying directories to be searched for include files and module files. The value of &cv-link-_FORTRANINCFLAGS; is created -by prepending/appending &cv-link-INCPREFIX; and &cv-link-INCSUFFIX; +by respectively prepending and appending +&cv-link-INCPREFIX; and &cv-link-INCSUFFIX; to the beginning and end of each directory in &cv-link-FORTRANPATH;. </para> @@ -148,7 +149,7 @@ for module files, as well. <para> The prefix used to specify a module directory on the Fortran compiler command line. -This will be appended to the beginning of the directory +This will be prepended to the beginning of the directory in the &cv-link-FORTRANMODDIR; construction variables when the &cv-link-_FORTRANMODFLAG; variables is automatically generated. </para> @@ -160,7 +161,7 @@ when the &cv-link-_FORTRANMODFLAG; variables is automatically generated. <para> The suffix used to specify a module directory on the Fortran compiler command line. -This will be appended to the beginning of the directory +This will be appended to the end of the directory in the &cv-link-FORTRANMODDIR; construction variables when the &cv-link-_FORTRANMODFLAG; variables is automatically generated. </para> @@ -176,8 +177,8 @@ for specifying the directory location where the Fortran compiler should place any module files that happen to get generated during compilation. The value of &cv-link-_FORTRANMODFLAG; is created -by prepending/appending &cv-link-FORTRANMODDIRPREFIX; and -&cv-link-FORTRANMODDIRSUFFIX; +by respectively prepending and appending +&cv-link-FORTRANMODDIRPREFIX; and &cv-link-FORTRANMODDIRSUFFIX; to the beginning and end of the directory in &cv-link-FORTRANMODDIR;. </para> </summary> @@ -250,7 +251,7 @@ through the automatically-generated &cv-link-_FORTRANINCFLAGS; construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the &cv-link-INCPREFIX; and &cv-link-INCSUFFIX; construction variables to the beginning and end diff --git a/src/engine/SCons/Tool/g++.py b/src/engine/SCons/Tool/g++.py index 468fa87..7b3bc50 100644 --- a/src/engine/SCons/Tool/g++.py +++ b/src/engine/SCons/Tool/g++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/g++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/g++.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" #forward proxy to the preffered cxx version diff --git a/src/engine/SCons/Tool/g++.xml b/src/engine/SCons/Tool/g++.xml index 6698869..f997540 100644 --- a/src/engine/SCons/Tool/g++.xml +++ b/src/engine/SCons/Tool/g++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/g77.py b/src/engine/SCons/Tool/g77.py index 36b3c43..fac9794 100644 --- a/src/engine/SCons/Tool/g77.py +++ b/src/engine/SCons/Tool/g77.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/g77.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/g77.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util from SCons.Tool.FortranCommon import add_all_to_env, add_f77_to_env diff --git a/src/engine/SCons/Tool/g77.xml b/src/engine/SCons/Tool/g77.xml index ae57994..519dfaf 100644 --- a/src/engine/SCons/Tool/g77.xml +++ b/src/engine/SCons/Tool/g77.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gas.py b/src/engine/SCons/Tool/gas.py index 75e5456..d6b3886 100644 --- a/src/engine/SCons/Tool/gas.py +++ b/src/engine/SCons/Tool/gas.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gas.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gas.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" try: as_module = __import__('as', globals(), locals(), []) diff --git a/src/engine/SCons/Tool/gas.xml b/src/engine/SCons/Tool/gas.xml index 95ccf27..9cfe0de 100644 --- a/src/engine/SCons/Tool/gas.xml +++ b/src/engine/SCons/Tool/gas.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gcc.py b/src/engine/SCons/Tool/gcc.py index f241c7b..3b4be6d 100644 --- a/src/engine/SCons/Tool/gcc.py +++ b/src/engine/SCons/Tool/gcc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gcc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gcc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from . import cc import os @@ -42,6 +42,7 @@ import SCons.Util compilers = ['gcc', 'cc'] + def generate(env): """Add Builders and construction variables for gcc to an Environment.""" @@ -59,38 +60,48 @@ def generate(env): if version: env['CCVERSION'] = version + def exists(env): # is executable, and is a GNU compiler (or accepts '--version' at least) return detect_version(env, env.Detect(env.get('CC', compilers))) + def detect_version(env, cc): """Return the version of the GNU compiler, or None if it is not a GNU compiler.""" + version = None cc = env.subst(cc) if not cc: - return None - version = None - #pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['-dumpversion'], - pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['--version'], - stdin = 'devnull', - stderr = 'devnull', - stdout = subprocess.PIPE) + return version + # -dumpversion was added in GCC 3.0. As long as we're supporting # GCC versions older than that, we should use --version and a # regular expression. - #line = pipe.stdout.read().strip() - #if line: - # version = line - line = SCons.Util.to_str(pipe.stdout.readline()) + # pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['-dumpversion'], + pipe = SCons.Action._subproc(env, SCons.Util.CLVar(cc) + ['--version'], + stdin='devnull', + stderr='devnull', + stdout=subprocess.PIPE) + if pipe.wait() != 0: + return version + + with pipe.stdout: + # -dumpversion variant: + # line = pipe.stdout.read().strip() + # --version variant: + line = SCons.Util.to_str(pipe.stdout.readline()) + # Non-GNU compiler's output (like AIX xlc's) may exceed the stdout buffer: + # So continue with reading to let the child process actually terminate. + while SCons.Util.to_str(pipe.stdout.readline()): + pass + + # -dumpversion variant: + # if line: + # version = line + # --version variant: match = re.search(r'[0-9]+(\.[0-9]+)+', line) if match: version = match.group(0) - # Non-GNU compiler's output (like AIX xlc's) may exceed the stdout buffer: - # So continue with reading to let the child process actually terminate. - while SCons.Util.to_str(pipe.stdout.readline()): - pass - ret = pipe.wait() - if ret != 0: - return None + return version # Local Variables: diff --git a/src/engine/SCons/Tool/gcc.xml b/src/engine/SCons/Tool/gcc.xml index 17fe2a1..8c29e9d 100644 --- a/src/engine/SCons/Tool/gcc.xml +++ b/src/engine/SCons/Tool/gcc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gdc.py b/src/engine/SCons/Tool/gdc.py index f98fabc..d12a7cf 100644 --- a/src/engine/SCons/Tool/gdc.py +++ b/src/engine/SCons/Tool/gdc.py @@ -26,7 +26,7 @@ Lib tool variables: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -48,7 +48,7 @@ Lib tool variables: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gdc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gdc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Action import SCons.Defaults diff --git a/src/engine/SCons/Tool/gdc.xml b/src/engine/SCons/Tool/gdc.xml index 8f71b5d..ea31215 100644 --- a/src/engine/SCons/Tool/gdc.xml +++ b/src/engine/SCons/Tool/gdc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gettext.xml b/src/engine/SCons/Tool/gettext.xml index 299184a..fc3af69 100644 --- a/src/engine/SCons/Tool/gettext.xml +++ b/src/engine/SCons/Tool/gettext.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gettext_tool.py b/src/engine/SCons/Tool/gettext_tool.py index e500a18..c33de28 100644 --- a/src/engine/SCons/Tool/gettext_tool.py +++ b/src/engine/SCons/Tool/gettext_tool.py @@ -2,7 +2,7 @@ """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,14 +23,26 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/gettext_tool.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gettext_tool.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" ############################################################################# def generate(env,**kw): + import sys + import os import SCons.Tool + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + from SCons.Tool.GettextCommon \ import _translate, tool_list for t in tool_list(env['PLATFORM'], env): + if sys.platform == 'win32': + tool = SCons.Tool.find_program_path(env, t, default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if tool: + tool_bin_dir = os.path.dirname(tool) + env.AppendENVPath('PATH', tool_bin_dir) + else: + SCons.Warnings.Warning(t + ' tool requested, but binary not found in ENV PATH') env.Tool(t) env.AddMethod(_translate, 'Translate') ############################################################################# diff --git a/src/engine/SCons/Tool/gfortran.py b/src/engine/SCons/Tool/gfortran.py index 730ad55..37a697e 100644 --- a/src/engine/SCons/Tool/gfortran.py +++ b/src/engine/SCons/Tool/gfortran.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gfortran.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gfortran.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util @@ -54,6 +54,8 @@ def generate(env): env['INC%sPREFIX' % dialect] = "-I" env['INC%sSUFFIX' % dialect] = "" + env['FORTRANMODDIRPREFIX'] = "-J" + def exists(env): return env.Detect('gfortran') diff --git a/src/engine/SCons/Tool/gfortran.xml b/src/engine/SCons/Tool/gfortran.xml index 926a2c8..4e78495 100644 --- a/src/engine/SCons/Tool/gfortran.xml +++ b/src/engine/SCons/Tool/gfortran.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gnulink.py b/src/engine/SCons/Tool/gnulink.py index 56bae9a..7634772 100644 --- a/src/engine/SCons/Tool/gnulink.py +++ b/src/engine/SCons/Tool/gnulink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gnulink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gnulink.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util import SCons.Tool diff --git a/src/engine/SCons/Tool/gnulink.xml b/src/engine/SCons/Tool/gnulink.xml index fce7a55..5ef80eb 100644 --- a/src/engine/SCons/Tool/gnulink.xml +++ b/src/engine/SCons/Tool/gnulink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gs.py b/src/engine/SCons/Tool/gs.py index ec5ab27..8ff9065 100644 --- a/src/engine/SCons/Tool/gs.py +++ b/src/engine/SCons/Tool/gs.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gs.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Action import SCons.Builder diff --git a/src/engine/SCons/Tool/gs.xml b/src/engine/SCons/Tool/gs.xml index 40e6f06..185f1b4 100644 --- a/src/engine/SCons/Tool/gs.xml +++ b/src/engine/SCons/Tool/gs.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/gxx.py b/src/engine/SCons/Tool/gxx.py index 709f72b..20445ba 100644 --- a/src/engine/SCons/Tool/gxx.py +++ b/src/engine/SCons/Tool/gxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/gxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/gxx.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import re @@ -45,12 +45,13 @@ from . import cxx compilers = ['g++'] + def generate(env): """Add Builders and construction variables for g++ to an Environment.""" static_obj, shared_obj = SCons.Tool.createObjBuilders(env) if 'CXX' not in env: - env['CXX'] = env.Detect(compilers) or compilers[0] + env['CXX'] = env.Detect(compilers) or compilers[0] cxx.generate(env) @@ -68,6 +69,7 @@ def generate(env): if version: env['CXXVERSION'] = version + def exists(env): # is executable, and is a GNU compiler (or accepts '--version' at least) return gcc.detect_version(env, env.Detect(env.get('CXX', compilers))) diff --git a/src/engine/SCons/Tool/hpc++.py b/src/engine/SCons/Tool/hpc++.py index 9471ef5..1528066 100644 --- a/src/engine/SCons/Tool/hpc++.py +++ b/src/engine/SCons/Tool/hpc++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpc++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hpc++.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" #forward proxy to the preffered cxx version diff --git a/src/engine/SCons/Tool/hpc++.xml b/src/engine/SCons/Tool/hpc++.xml index d3d11c4..8bb4a65 100644 --- a/src/engine/SCons/Tool/hpc++.xml +++ b/src/engine/SCons/Tool/hpc++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/hpcc.py b/src/engine/SCons/Tool/hpcc.py index 0f6a5b4..2734006 100644 --- a/src/engine/SCons/Tool/hpcc.py +++ b/src/engine/SCons/Tool/hpcc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpcc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hpcc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util diff --git a/src/engine/SCons/Tool/hpcc.xml b/src/engine/SCons/Tool/hpcc.xml index 765860f..f8bece8 100644 --- a/src/engine/SCons/Tool/hpcc.xml +++ b/src/engine/SCons/Tool/hpcc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/hpcxx.py b/src/engine/SCons/Tool/hpcxx.py index 847eaca..196777a 100644 --- a/src/engine/SCons/Tool/hpcxx.py +++ b/src/engine/SCons/Tool/hpcxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hpcxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hpcxx.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path diff --git a/src/engine/SCons/Tool/hplink.py b/src/engine/SCons/Tool/hplink.py index 2329282..9f38a3b 100644 --- a/src/engine/SCons/Tool/hplink.py +++ b/src/engine/SCons/Tool/hplink.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/hplink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/hplink.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path diff --git a/src/engine/SCons/Tool/hplink.xml b/src/engine/SCons/Tool/hplink.xml index ffa6c0d..f2b923b 100644 --- a/src/engine/SCons/Tool/hplink.xml +++ b/src/engine/SCons/Tool/hplink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/icc.py b/src/engine/SCons/Tool/icc.py index 1f9e8cf..1923c60 100644 --- a/src/engine/SCons/Tool/icc.py +++ b/src/engine/SCons/Tool/icc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/icc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/icc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from . import cc diff --git a/src/engine/SCons/Tool/icc.xml b/src/engine/SCons/Tool/icc.xml index b0af318..8492fce 100644 --- a/src/engine/SCons/Tool/icc.xml +++ b/src/engine/SCons/Tool/icc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/icl.py b/src/engine/SCons/Tool/icl.py index 99410cd..26490f0 100644 --- a/src/engine/SCons/Tool/icl.py +++ b/src/engine/SCons/Tool/icl.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/icl.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/icl.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Tool.intelc diff --git a/src/engine/SCons/Tool/icl.xml b/src/engine/SCons/Tool/icl.xml index 035a3a9..31e0bcc 100644 --- a/src/engine/SCons/Tool/icl.xml +++ b/src/engine/SCons/Tool/icl.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ifl.py b/src/engine/SCons/Tool/ifl.py index 116c9ac..e438c44 100644 --- a/src/engine/SCons/Tool/ifl.py +++ b/src/engine/SCons/Tool/ifl.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ifl.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ifl.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults from SCons.Scanner.Fortran import FortranScan diff --git a/src/engine/SCons/Tool/ifl.xml b/src/engine/SCons/Tool/ifl.xml index d693ef6..f78c9fd 100644 --- a/src/engine/SCons/Tool/ifl.xml +++ b/src/engine/SCons/Tool/ifl.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ifort.py b/src/engine/SCons/Tool/ifort.py index 8e88946..d69bd14 100644 --- a/src/engine/SCons/Tool/ifort.py +++ b/src/engine/SCons/Tool/ifort.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ifort.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ifort.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults from SCons.Scanner.Fortran import FortranScan diff --git a/src/engine/SCons/Tool/ifort.xml b/src/engine/SCons/Tool/ifort.xml index 26d4ca9..47a55e3 100644 --- a/src/engine/SCons/Tool/ifort.xml +++ b/src/engine/SCons/Tool/ifort.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ilink.py b/src/engine/SCons/Tool/ilink.py index 577e54b..6c3a072 100644 --- a/src/engine/SCons/Tool/ilink.py +++ b/src/engine/SCons/Tool/ilink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ilink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ilink.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/ilink.xml b/src/engine/SCons/Tool/ilink.xml index 941db53..731bdfb 100644 --- a/src/engine/SCons/Tool/ilink.xml +++ b/src/engine/SCons/Tool/ilink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ilink32.py b/src/engine/SCons/Tool/ilink32.py index 3e8e095..7c7e983 100644 --- a/src/engine/SCons/Tool/ilink32.py +++ b/src/engine/SCons/Tool/ilink32.py @@ -5,7 +5,7 @@ XXX """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ XXX # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ilink32.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ilink32.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Tool import SCons.Tool.bcc32 diff --git a/src/engine/SCons/Tool/ilink32.xml b/src/engine/SCons/Tool/ilink32.xml index 02343d9..3f273a8 100644 --- a/src/engine/SCons/Tool/ilink32.xml +++ b/src/engine/SCons/Tool/ilink32.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/install.py b/src/engine/SCons/Tool/install.py index 12dcf8f..6b5a741 100644 --- a/src/engine/SCons/Tool/install.py +++ b/src/engine/SCons/Tool/install.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/install.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/install.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import re diff --git a/src/engine/SCons/Tool/install.xml b/src/engine/SCons/Tool/install.xml index 139cd1e..da2d4a0 100644 --- a/src/engine/SCons/Tool/install.xml +++ b/src/engine/SCons/Tool/install.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 425f221..3429145 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import division, print_function -__revision__ = "src/engine/SCons/Tool/intelc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/intelc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import math, sys, os.path, glob, string, re @@ -73,7 +73,7 @@ def linux_ver_normalize(vstr): m = re.match(r'([0-9]+)\.([0-9]+)\.([0-9]+)', vstr) if m: vmaj,vmin,build = m.groups() - return float(vmaj) * 10. + float(vmin) + float(build) / 1000.; + return float(vmaj) * 10. + float(vmin) + float(build) / 1000. else: f = float(vstr) if is_windows: diff --git a/src/engine/SCons/Tool/intelc.xml b/src/engine/SCons/Tool/intelc.xml index 3ec9ddd..af77186 100644 --- a/src/engine/SCons/Tool/intelc.xml +++ b/src/engine/SCons/Tool/intelc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ipkg.py b/src/engine/SCons/Tool/ipkg.py index 4ad53c9..5685abb 100644 --- a/src/engine/SCons/Tool/ipkg.py +++ b/src/engine/SCons/Tool/ipkg.py @@ -11,7 +11,7 @@ packages fake_root. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ packages fake_root. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ipkg.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ipkg.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os diff --git a/src/engine/SCons/Tool/jar.py b/src/engine/SCons/Tool/jar.py index a56dd70..5858b2c 100644 --- a/src/engine/SCons/Tool/jar.py +++ b/src/engine/SCons/Tool/jar.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,10 +31,14 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/jar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/jar.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" +import os import SCons.Subst import SCons.Util +from SCons.Node.FS import _my_normcase +from SCons.Tool.JavaCommon import get_java_install_dirs + def jarSources(target, source, env, for_signature): """Only include sources that are not a manifest file.""" @@ -50,7 +54,7 @@ def jarSources(target, source, env, for_signature): result = [] for src in source: contents = src.get_text_contents() - if contents[:16] != "Manifest-Version": + if not contents.startswith("Manifest-Version"): if jarchdir_set: _chdir = jarchdir else: @@ -71,7 +75,7 @@ def jarManifest(target, source, env, for_signature): """Look in sources for a manifest file, if any.""" for src in source: contents = src.get_text_contents() - if contents[:16] == "Manifest-Version": + if contents.startswith("Manifest-Version"): return src return '' @@ -81,16 +85,137 @@ def jarFlags(target, source, env, for_signature): jarflags = env.subst('$JARFLAGS', target=target, source=source) for src in source: contents = src.get_text_contents() - if contents[:16] == "Manifest-Version": + if contents.startswith("Manifest-Version"): if not 'm' in jarflags: return jarflags + 'm' break return jarflags +def Jar(env, target = None, source = [], *args, **kw): + """ + A pseudo-Builder wrapper around the separate Jar sources{File,Dir} + Builders. + """ + + # jar target should not be a list so assume they passed + # no target and want implicit target to be made and the arg + # was actaully the list of sources + if SCons.Util.is_List(target) and source == []: + SCons.Warnings.Warning("Making implicit target jar file, " + + "and treating the list as sources") + source = target + target = None + + # mutiple targets pass so build each target the same from the + # same source + #TODO Maybe this should only be done once, and the result copied + # for each target since it should result in the same? + if SCons.Util.is_List(target) and SCons.Util.is_List(source): + jars = [] + for single_target in target: + jars += env.Jar( target = single_target, source = source, *args, **kw) + return jars + + # they passed no target so make a target implicitly + if target is None: + try: + # make target from the first source file + target = os.path.splitext(str(source[0]))[0] + env.subst('$JARSUFFIX') + except: + # something strange is happening but attempt anyways + SCons.Warnings.Warning("Could not make implicit target from sources, using directory") + target = os.path.basename(str(env.Dir('.'))) + env.subst('$JARSUFFIX') + + # make lists out of our target and sources + if not SCons.Util.is_List(target): + target = [target] + if not SCons.Util.is_List(source): + source = [source] + + # setup for checking through all the sources and handle accordingly + java_class_suffix = env.subst('$JAVACLASSSUFFIX') + java_suffix = env.subst('$JAVASUFFIX') + target_nodes = [] + + # function for determining what to do with a file and not a directory + # if its already a class file then it can be used as a + # source for jar, otherwise turn it into a class file then + # return the source + def file_to_class(s): + if _my_normcase(str(s)).endswith(java_suffix): + return env.JavaClassFile(source = s, *args, **kw) + else: + return [env.fs.File(s)] + + # function for calling the JavaClassDir builder if a directory is + # passed as a source to Jar builder. The JavaClassDir builder will + # return an empty list if there were not target classes built from + # the directory, in this case assume the user wanted the directory + # copied into the jar as is (it contains other files such as + # resources or class files compiled from proir commands) + # TODO: investigate the expexcted behavior for directories that + # have mixed content, such as Java files along side other files + # files. + def dir_to_class(s): + dir_targets = env.JavaClassDir(source = s, *args, **kw) + if(dir_targets == []): + # no classes files could be built from the source dir + # so pass the dir as is. + return [env.fs.Dir(s)] + else: + return dir_targets + + # loop through the sources and handle each accordingly + # the goal here is to get all the source files into a class + # file or a directory that contains class files + for s in SCons.Util.flatten(source): + s = env.subst(s) + if isinstance(s, SCons.Node.FS.Base): + if isinstance(s, SCons.Node.FS.File): + # found a file so make sure its a class file + target_nodes.extend(file_to_class(s)) + else: + # found a dir so get the class files out of it + target_nodes.extend(dir_to_class(s)) + else: + try: + # source is string try to convert it to file + target_nodes.extend(file_to_class(env.fs.File(s))) + continue + except: + pass + + try: + # source is string try to covnert it to dir + target_nodes.extend(dir_to_class(env.fs.Dir(s))) + continue + except: + pass + + SCons.Warnings.Warning("File: " + str(s) + " could not be identified as File or Directory, skipping.") + + # at this point all our sources have been converted to classes or directories of class + # so pass it to the Jar builder + return env.JarFile(target = target, source = target_nodes, *args, **kw) + def generate(env): """Add Builders and construction variables for jar to an Environment.""" SCons.Tool.CreateJarBuilder(env) + SCons.Tool.CreateJavaFileBuilder(env) + SCons.Tool.CreateJavaClassFileBuilder(env) + SCons.Tool.CreateJavaClassDirBuilder(env) + + env.AddMethod(Jar) + + if env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for clang + jar = SCons.Tool.find_program_path(env, 'jar', + default_paths=get_java_install_dirs(env['PLATFORM'])) + if jar: + jar_bin_dir = os.path.dirname(jar) + env.AppendENVPath('PATH', jar_bin_dir) + env['JAR'] = 'jar' env['JARFLAGS'] = SCons.Util.CLVar('cf') env['_JARFLAGS'] = jarFlags diff --git a/src/engine/SCons/Tool/jar.xml b/src/engine/SCons/Tool/jar.xml index e18207e..73f6bcb 100644 --- a/src/engine/SCons/Tool/jar.xml +++ b/src/engine/SCons/Tool/jar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/javac.py b/src/engine/SCons/Tool/javac.py index f3cabf3..b5e4aaa 100644 --- a/src/engine/SCons/Tool/javac.py +++ b/src/engine/SCons/Tool/javac.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,15 +30,16 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/javac.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/javac.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path +from collections import OrderedDict import SCons.Action import SCons.Builder from SCons.Node.FS import _my_normcase -from SCons.Tool.JavaCommon import parse_java_file +from SCons.Tool.JavaCommon import parse_java_file, get_java_install_dirs, get_java_include_paths import SCons.Util def classname(path): @@ -70,7 +71,7 @@ def emit_java_classes(target, source, env): if isinstance(entry, SCons.Node.FS.File): slist.append(entry) elif isinstance(entry, SCons.Node.FS.Dir): - result = SCons.Util.OrderedDict() + result = OrderedDict() dirnode = entry.rdir() def find_java_files(arg, dirpath, filenames): java_files = sorted([n for n in filenames @@ -207,6 +208,21 @@ def generate(env): env.AddMethod(Java) + version = env.get('JAVAVERSION', None) + + javac = SCons.Tool.find_program_path(env, 'javac') + if env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for javac + paths=get_java_install_dirs(env['PLATFORM'], version=version) + javac = SCons.Tool.find_program_path(env, 'javac', + default_paths=paths) + if javac: + javac_bin_dir = os.path.dirname(javac) + env.AppendENVPath('PATH', javac_bin_dir) + + env['JAVAINCLUDES'] = get_java_include_paths(env, javac, version) + + env['JAVAC'] = 'javac' env['JAVACFLAGS'] = SCons.Util.CLVar('') env['JAVABOOTCLASSPATH'] = [] diff --git a/src/engine/SCons/Tool/javac.xml b/src/engine/SCons/Tool/javac.xml index be478ba..dc72f75 100644 --- a/src/engine/SCons/Tool/javac.xml +++ b/src/engine/SCons/Tool/javac.xml @@ -1,285 +1,304 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. --> <!DOCTYPE sconsdoc [ -<!ENTITY % scons SYSTEM '../../../../doc/scons.mod'> -%scons; -<!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'> -%builders-mod; -<!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'> -%functions-mod; -<!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'> -%tools-mod; -<!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'> -%variables-mod; -]> + <!ENTITY % scons SYSTEM '../../../../doc/scons.mod'> + %scons; + <!ENTITY % builders-mod SYSTEM '../../../../doc/generated/builders.mod'> + %builders-mod; + <!ENTITY % functions-mod SYSTEM '../../../../doc/generated/functions.mod'> + %functions-mod; + <!ENTITY % tools-mod SYSTEM '../../../../doc/generated/tools.mod'> + %tools-mod; + <!ENTITY % variables-mod SYSTEM '../../../../doc/generated/variables.mod'> + %variables-mod; + ]> <sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd"> -<tool name="javac"> -<summary> -<para> -Sets construction variables for the &javac; compiler. -</para> -</summary> -<sets> -<item>JAVAC</item> -<item>JAVACFLAGS</item> -<item>JAVACCOM</item> -<item>JAVACLASSSUFFIX</item> -<item>JAVASUFFIX</item> -<item>JAVABOOTCLASSPATH</item> -<item>JAVACLASSPATH</item> -<item>JAVASOURCEPATH</item> -</sets> -<uses> -<item>JAVACCOMSTR</item> -</uses> -</tool> + <tool name="javac"> + <summary> + <para> + Sets construction variables for the &javac; compiler. + </para> + </summary> + <sets> + <item>JAVAC</item> + <item>JAVACFLAGS</item> + <item>JAVACCOM</item> + <item>JAVACLASSSUFFIX</item> + <item>JAVAINCLUDES</item> + <item>JAVASUFFIX</item> + <item>JAVABOOTCLASSPATH</item> + <item>JAVACLASSPATH</item> + <item>JAVASOURCEPATH</item> + </sets> + <uses> + <item>JAVACCOMSTR</item> + </uses> + </tool> -<builder name="Java"> -<summary> -<para> -Builds one or more Java class files. -The sources may be any combination of explicit -<filename>.java</filename> files, -or directory trees which will be scanned -for <filename>.java</filename> files. -</para> + <builder name="Java"> + <summary> + <para> + Builds one or more Java class files. + The sources may be any combination of explicit + <filename>.java</filename> + files, + or directory trees which will be scanned + for <filename>.java</filename> files. + </para> -<para> -SCons will parse each source <filename>.java</filename> file -to find the classes -(including inner classes) -defined within that file, -and from that figure out the -target <filename>.class</filename> files that will be created. -The class files will be placed underneath -the specified target directory. -</para> + <para> + SCons will parse each source <filename>.java</filename> file + to find the classes + (including inner classes) + defined within that file, + and from that figure out the + target <filename>.class</filename> files that will be created. + The class files will be placed underneath + the specified target directory. + </para> -<para> -SCons will also search each Java file -for the Java package name, -which it assumes can be found on a line -beginning with the string -<literal>package</literal> -in the first column; -the resulting <filename>.class</filename> files -will be placed in a directory reflecting -the specified package name. -For example, -the file -<filename>Foo.java</filename> -defining a single public -<classname>Foo</classname> -class and -containing a package name of -<classname>sub.dir</classname> -will generate a corresponding -<filename>sub/dir/Foo.class</filename> -class file. -</para> + <para> + SCons will also search each Java file + for the Java package name, + which it assumes can be found on a line + beginning with the string + <literal>package</literal> + in the first column; + the resulting <filename>.class</filename> files + will be placed in a directory reflecting + the specified package name. + For example, + the file + <filename>Foo.java</filename> + defining a single public + <classname>Foo</classname> + class and + containing a package name of + <classname>sub.dir</classname> + will generate a corresponding + <filename>sub/dir/Foo.class</filename> + class file. + </para> -<para> -Examples: -</para> + <para> + Examples: + </para> -<example_commands> -env.Java(target = 'classes', source = 'src') -env.Java(target = 'classes', source = ['src1', 'src2']) -env.Java(target = 'classes', source = ['File1.java', 'File2.java']) -</example_commands> + <example_commands> + env.Java(target = 'classes', source = 'src') + env.Java(target = 'classes', source = ['src1', 'src2']) + env.Java(target = 'classes', source = ['File1.java', 'File2.java']) + </example_commands> -<para> -Java source files can use the native encoding for the underlying OS. -Since SCons compiles in simple ASCII mode by default, -the compiler will generate warnings about unmappable characters, -which may lead to errors as the file is processed further. -In this case, the user must specify the <literal>LANG</literal> -environment variable to tell the compiler what encoding is used. -For portibility, it's best if the encoding is hard-coded -so that the compile will work if it is done on a system -with a different encoding. -</para> + <para> + Java source files can use the native encoding for the underlying OS. + Since SCons compiles in simple ASCII mode by default, + the compiler will generate warnings about unmappable characters, + which may lead to errors as the file is processed further. + In this case, the user must specify the + <literal>LANG</literal> + environment variable to tell the compiler what encoding is used. + For portibility, it's best if the encoding is hard-coded + so that the compile will work if it is done on a system + with a different encoding. + </para> -<example_commands> -env = Environment() -env['ENV']['LANG'] = 'en_GB.UTF-8' -</example_commands> -</summary> -</builder> + <example_commands> + env = Environment() + env['ENV']['LANG'] = 'en_GB.UTF-8' + </example_commands> + </summary> + </builder> -<cvar name="JAVABOOTCLASSPATH"> -<summary> -<para> -Specifies the list of directories that -will be added to the -&javac; command line -via the <option>-bootclasspath</option> option. -The individual directory names will be -separated by the operating system's path separate character -(<filename>:</filename> on UNIX/Linux/POSIX, -<filename>;</filename> on Windows). -</para> -</summary> -</cvar> + <cvar name="JAVABOOTCLASSPATH"> + <summary> + <para> + Specifies the list of directories that + will be added to the + &javac; command line + via the <option>-bootclasspath</option> option. + The individual directory names will be + separated by the operating system's path separate character + (<filename>:</filename> on UNIX/Linux/POSIX, + <filename>;</filename> + on Windows). + </para> + </summary> + </cvar> -<cvar name="JAVAC"> -<summary> -<para> -The Java compiler. -</para> -</summary> -</cvar> + <cvar name="JAVAINCLUDES"> + <summary> + <para> + Include path for Java header files (such as jni.h) + </para> + </summary> + </cvar> -<cvar name="JAVACCOM"> -<summary> -<para> -The command line used to compile a directory tree containing -Java source files to -corresponding Java class files. -Any options specified in the &cv-link-JAVACFLAGS; construction variable -are included on this command line. -</para> -</summary> -</cvar> + <cvar name="JAVAC"> + <summary> + <para> + The Java compiler. + </para> + </summary> + </cvar> -<cvar name="JAVACCOMSTR"> -<summary> -<para> -The string displayed when compiling -a directory tree of Java source files to -corresponding Java class files. -If this is not set, then &cv-link-JAVACCOM; (the command line) is displayed. -</para> + <cvar name="JAVACCOM"> + <summary> + <para> + The command line used to compile a directory tree containing + Java source files to + corresponding Java class files. + Any options specified in the &cv-link-JAVACFLAGS; construction variable + are included on this command line. + </para> + </summary> + </cvar> -<example_commands> -env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") -</example_commands> -</summary> -</cvar> + <cvar name="JAVACCOMSTR"> + <summary> + <para> + The string displayed when compiling + a directory tree of Java source files to + corresponding Java class files. + If this is not set, then &cv-link-JAVACCOM; (the command line) is displayed. + </para> -<cvar name="JAVACFLAGS"> -<summary> -<para> -General options that are passed to the Java compiler. -</para> -</summary> -</cvar> + <example_commands> + env = Environment(JAVACCOMSTR = "Compiling class files $TARGETS from $SOURCES") + </example_commands> + </summary> + </cvar> -<cvar name="JAVACLASSDIR"> -<summary> -<para> -The directory in which Java class files may be found. -This is stripped from the beginning of any Java .class -file names supplied to the -<literal>JavaH</literal> -builder. -</para> -</summary> -</cvar> + <cvar name="JAVACFLAGS"> + <summary> + <para> + General options that are passed to the Java compiler. + </para> + </summary> + </cvar> -<cvar name="JAVACLASSPATH"> -<summary> -<para> -Specifies the list of directories that -will be searched for Java -<filename>.class</filename> file. -The directories in this list will be added to the -&javac; and &javah; command lines -via the <option>-classpath</option> option. -The individual directory names will be -separated by the operating system's path separate character -(<filename>:</filename> on UNIX/Linux/POSIX, -<filename>;</filename> on Windows). -</para> + <cvar name="JAVACLASSDIR"> + <summary> + <para> + The directory in which Java class files may be found. + This is stripped from the beginning of any Java .class + file names supplied to the + <literal>JavaH</literal> + builder. + </para> + </summary> + </cvar> -<para> -Note that this currently just adds the specified -directory via the <option>-classpath</option> option. -&SCons; does not currently search the -&cv-JAVACLASSPATH; directories for dependency -<filename>.class</filename> files. -</para> -</summary> -</cvar> + <cvar name="JAVACLASSPATH"> + <summary> + <para> + Specifies the list of directories that + will be searched for Java + <filename>.class</filename> + file. + The directories in this list will be added to the + &javac; and &javah; command lines + via the <option>-classpath</option> option. + The individual directory names will be + separated by the operating system's path separate character + (<filename>:</filename> on UNIX/Linux/POSIX, + <filename>;</filename> + on Windows). + </para> -<cvar name="JAVACLASSSUFFIX"> -<summary> -<para> -The suffix for Java class files; -<filename>.class</filename> -by default. -</para> -</summary> -</cvar> + <para> + Note that this currently just adds the specified + directory via the <option>-classpath</option> option. + &SCons; does not currently search the + &cv-JAVACLASSPATH; directories for dependency + <filename>.class</filename> + files. + </para> + </summary> + </cvar> -<cvar name="JAVASOURCEPATH"> -<summary> -<para> -Specifies the list of directories that -will be searched for input -<filename>.java</filename> file. -The directories in this list will be added to the -&javac; command line -via the <option>-sourcepath</option> option. -The individual directory names will be -separated by the operating system's path separate character -(<filename>:</filename> on UNIX/Linux/POSIX, -<filename>;</filename> on Windows). -</para> + <cvar name="JAVACLASSSUFFIX"> + <summary> + <para> + The suffix for Java class files; + <filename>.class</filename> + by default. + </para> + </summary> + </cvar> -<para> -Note that this currently just adds the specified -directory via the <option>-sourcepath</option> option. -&SCons; does not currently search the -&cv-JAVASOURCEPATH; directories for dependency -<filename>.java</filename> files. -</para> -</summary> -</cvar> + <cvar name="JAVASOURCEPATH"> + <summary> + <para> + Specifies the list of directories that + will be searched for input + <filename>.java</filename> + file. + The directories in this list will be added to the + &javac; command line + via the <option>-sourcepath</option> option. + The individual directory names will be + separated by the operating system's path separate character + (<filename>:</filename> on UNIX/Linux/POSIX, + <filename>;</filename> + on Windows). + </para> -<cvar name="JAVASUFFIX"> -<summary> -<para> -The suffix for Java files; -<filename>.java</filename> -by default. -</para> -</summary> -</cvar> + <para> + Note that this currently just adds the specified + directory via the <option>-sourcepath</option> option. + &SCons; does not currently search the + &cv-JAVASOURCEPATH; directories for dependency + <filename>.java</filename> + files. + </para> + </summary> + </cvar> -<cvar name="JAVAVERSION"> -<summary> -<para> -Specifies the Java version being used by the &b-Java; builder. -This is <emphasis>not</emphasis> currently used to select one -version of the Java compiler vs. another. -Instead, you should set this to specify the version of Java -supported by your &javac; compiler. -The default is <literal>1.4</literal>. -</para> + <cvar name="JAVASUFFIX"> + <summary> + <para> + The suffix for Java files; + <filename>.java</filename> + by default. + </para> + </summary> + </cvar> -<para> -This is sometimes necessary because -Java 1.5 changed the file names that are created -for nested anonymous inner classes, -which can cause a mismatch with the files -that &SCons; expects will be generated by the &javac; compiler. -Setting &cv-JAVAVERSION; to <literal>1.5</literal> -(or <literal>1.6</literal>, as appropriate) -can make &SCons; realize that a Java 1.5 or 1.6 -build is actually up to date. -</para> -</summary> -</cvar> + <cvar name="JAVAVERSION"> + <summary> + <para> + Specifies the Java version being used by the &b-Java; builder. + This is <emphasis>not</emphasis> currently used to select one + version of the Java compiler vs. another. + Instead, you should set this to specify the version of Java + supported by your &javac; compiler. + The default is <literal>1.4</literal>. + </para> + + <para> + This is sometimes necessary because + Java 1.5 changed the file names that are created + for nested anonymous inner classes, + which can cause a mismatch with the files + that &SCons; expects will be generated by the &javac; compiler. + Setting &cv-JAVAVERSION; to + <literal>1.5</literal> + (or <literal>1.6</literal>, as appropriate) + can make &SCons; realize that a Java 1.5 or 1.6 + build is actually up to date. + </para> + </summary> + </cvar> </sconsdoc> diff --git a/src/engine/SCons/Tool/javacTests.py b/src/engine/SCons/Tool/javacTests.py index 0debbb6..067ff3e 100644 --- a/src/engine/SCons/Tool/javacTests.py +++ b/src/engine/SCons/Tool/javacTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,8 +24,6 @@ import os import unittest -import TestUnit - import SCons.Tool.javac class DummyNode(object): @@ -40,14 +38,14 @@ class pathoptTestCase(unittest.TestCase): popt = SCons.Tool.javac.pathopt('-foopath', 'FOOPATH') env = {'FOOPATH': path} actual = popt(None, None, env, None) - self.assertEquals(expect, actual) + self.assertEqual(expect, actual) def assert_pathopt_default(self, expect, path, default): popt = SCons.Tool.javac.pathopt('-foopath', 'FOOPATH', default='DPATH') env = {'FOOPATH': path, 'DPATH': default} actual = popt(None, None, env, None) - self.assertEquals(expect, actual) + self.assertEqual(expect, actual) def test_unset(self): self.assert_pathopt([], None) @@ -101,5 +99,4 @@ class pathoptTestCase(unittest.TestCase): '') if __name__ == "__main__": - suite = unittest.makeSuite(pathoptTestCase, 'test_') - TestUnit.run(suite) + unittest.main() diff --git a/src/engine/SCons/Tool/javah.py b/src/engine/SCons/Tool/javah.py index 0e1885c..84183cb 100644 --- a/src/engine/SCons/Tool/javah.py +++ b/src/engine/SCons/Tool/javah.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/javah.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/javah.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path @@ -40,6 +40,8 @@ import SCons.Builder import SCons.Node.FS import SCons.Tool.javac import SCons.Util +from SCons.Tool.JavaCommon import get_java_install_dirs + def emit_java_headers(target, source, env): """Create and return lists of Java stub header files that will @@ -120,6 +122,14 @@ def generate(env): java_javah = SCons.Tool.CreateJavaHBuilder(env) java_javah.emitter = emit_java_headers + if env['PLATFORM'] == 'win32': + # Ensure that we have a proper path for clang + javah = SCons.Tool.find_program_path(env, 'javah', + default_paths=get_java_install_dirs(env['PLATFORM'])) + if javah: + javah_bin_dir = os.path.dirname(javah) + env.AppendENVPath('PATH', javah_bin_dir) + env['_JAVAHOUTFLAG'] = JavaHOutFlagGenerator env['JAVAH'] = 'javah' env['JAVAHFLAGS'] = SCons.Util.CLVar('') diff --git a/src/engine/SCons/Tool/javah.xml b/src/engine/SCons/Tool/javah.xml index f362e3e..f72a6cd 100644 --- a/src/engine/SCons/Tool/javah.xml +++ b/src/engine/SCons/Tool/javah.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/latex.py b/src/engine/SCons/Tool/latex.py index aa7ea15..9626693 100644 --- a/src/engine/SCons/Tool/latex.py +++ b/src/engine/SCons/Tool/latex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/latex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/latex.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Action import SCons.Defaults diff --git a/src/engine/SCons/Tool/latex.xml b/src/engine/SCons/Tool/latex.xml index bb0816d..b4eb45a 100644 --- a/src/engine/SCons/Tool/latex.xml +++ b/src/engine/SCons/Tool/latex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/ldc.py b/src/engine/SCons/Tool/ldc.py index 5bb04ff..fe3df1f 100644 --- a/src/engine/SCons/Tool/ldc.py +++ b/src/engine/SCons/Tool/ldc.py @@ -26,7 +26,7 @@ Lib tool variables: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -48,7 +48,7 @@ Lib tool variables: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/ldc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/ldc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import subprocess diff --git a/src/engine/SCons/Tool/ldc.xml b/src/engine/SCons/Tool/ldc.xml index 1479867..691145a 100644 --- a/src/engine/SCons/Tool/ldc.xml +++ b/src/engine/SCons/Tool/ldc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/lex.py b/src/engine/SCons/Tool/lex.py index e185b93..affb52c 100644 --- a/src/engine/SCons/Tool/lex.py +++ b/src/engine/SCons/Tool/lex.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,13 +31,17 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/lex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/lex.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path +import sys import SCons.Action import SCons.Tool import SCons.Util +from SCons.Platform.mingw import MINGW_DEFAULT_PATHS +from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS +from SCons.Platform.win32 import CHOCO_DEFAULT_PATH LexAction = SCons.Action.Action("$LEXCOM", "$LEXCOMSTR") @@ -64,6 +68,29 @@ def lexEmitter(target, source, env): target.append(fileName) return (target, source) +def get_lex_path(env, append_paths=False): + """ + Find the a path containing the lex or flex binaries. If a construction + environment is passed in then append the path to the ENV PATH. + """ + # save existing path to reset if we don't want to append any paths + envPath = env['ENV']['PATH'] + bins = ['flex', 'lex', 'win_flex'] + + for prog in bins: + bin_path = SCons.Tool.find_program_path( + env, + prog, + default_paths=CHOCO_DEFAULT_PATH + MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if bin_path: + if not append_paths: + env['ENV']['PATH'] = envPath + else: + env.AppendENVPath('PATH', os.path.dirname(bin_path)) + return bin_path + SCons.Warnings.Warning('lex tool requested, but lex or flex binary not found in ENV PATH') + + def generate(env): """Add Builders and construction variables for lex to an Environment.""" c_file, cxx_file = SCons.Tool.createCFileBuilders(env) @@ -83,12 +110,23 @@ def generate(env): cxx_file.add_action(".ll", LexAction) cxx_file.add_emitter(".ll", lexEmitter) - env["LEX"] = env.Detect("flex") or "lex" env["LEXFLAGS"] = SCons.Util.CLVar("") - env["LEXCOM"] = "$LEX $LEXFLAGS -t $SOURCES > $TARGET" + + if sys.platform == 'win32': + get_lex_path(env, append_paths=True) + env["LEX"] = env.Detect(['flex', 'lex', 'win_flex']) + if not env.get("LEXUNISTD"): + env["LEXUNISTD"] = SCons.Util.CLVar("") + env["LEXCOM"] = "$LEX $LEXUNISTD $LEXFLAGS -t $SOURCES > $TARGET" + else: + env["LEX"] = env.Detect(["flex", "lex"]) + env["LEXCOM"] = "$LEX $LEXFLAGS -t $SOURCES > $TARGET" def exists(env): - return env.Detect(["flex", "lex"]) + if sys.platform == 'win32': + return get_lex_path(env) + else: + return env.Detect(["flex", "lex"]) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/lex.xml b/src/engine/SCons/Tool/lex.xml index e178308..0d044b8 100644 --- a/src/engine/SCons/Tool/lex.xml +++ b/src/engine/SCons/Tool/lex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -33,6 +33,7 @@ Sets construction variables for the &lex; lexical analyser. <item>LEX</item> <item>LEXFLAGS</item> <item>LEXCOM</item> +<item>LEXUNISTD</item> </sets> <uses> <item>LEXCOMSTR</item> @@ -78,4 +79,12 @@ General options passed to the lexical analyzer generator. </summary> </cvar> +<cvar name="LEXUNISTD"> +<summary> +<para> +Used only on windows environments to set a lex flag to prevent 'unistd.h' from being included. The default value is '--nounistd'. +</para> +</summary> +</cvar> + </sconsdoc> diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index e8c11ed..65fe013 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -1,4 +1,3 @@ - """SCons.Tool.link Tool-specific initialization for the generic Posix linker. @@ -10,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +32,7 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/link.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/link.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import re @@ -47,22 +46,21 @@ from SCons.Tool.FortranCommon import isfortran from SCons.Tool.DCommon import isD -import SCons.Tool.cxx -cplusplus = SCons.Tool.cxx -# cplusplus = __import__(__package__+'.cxx', globals(), locals(), ['*']) +from SCons.Tool.cxx import iscplusplus issued_mixed_link_warning = False + def smart_link(source, target, env, for_signature): - has_cplusplus = cplusplus.iscplusplus(source) + has_cplusplus = iscplusplus(source) has_fortran = isfortran(env, source) has_d = isD(env, source) if has_cplusplus and has_fortran and not has_d: global issued_mixed_link_warning if not issued_mixed_link_warning: msg = "Using $CXX to link Fortran and C++ code together.\n\t" + \ - "This may generate a buggy executable if the '%s'\n\t" + \ - "compiler does not know how to deal with Fortran runtimes." + "This may generate a buggy executable if the '%s'\n\t" + \ + "compiler does not know how to deal with Fortran runtimes." SCons.Warnings.warn(SCons.Warnings.FortranCxxMixWarning, msg % env.subst('$CXX')) issued_mixed_link_warning = True @@ -77,11 +75,14 @@ def smart_link(source, target, env, for_signature): return '$CXX' return '$CC' + def _lib_emitter(target, source, env, **kw): Verbose = False if Verbose: - print("_lib_emitter: target[0]={:r}".format(target[0].get_path())) + print("_lib_emitter: target[0]={!r}".format(target[0].get_path())) for tgt in target: + if SCons.Util.is_String(tgt): + tgt = env.File(tgt) tgt.attributes.shared = 1 try: @@ -90,21 +91,24 @@ def _lib_emitter(target, source, env, **kw): pass else: if Verbose: - print("_lib_emitter: symlink_generator={:r}".format(symlink_generator)) + print("_lib_emitter: symlink_generator={!r}".format(symlink_generator)) symlinks = symlink_generator(env, target[0]) if Verbose: - print("_lib_emitter: symlinks={:r}".format(symlinks)) + print("_lib_emitter: symlinks={!r}".format(symlinks)) if symlinks: SCons.Tool.EmitLibSymlinks(env, symlinks, target[0]) target[0].attributes.shliblinks = symlinks return (target, source) + def shlib_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator = SCons.Tool.ShLibSymlinkGenerator) + return _lib_emitter(target, source, env, symlink_generator=SCons.Tool.ShLibSymlinkGenerator) + def ldmod_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator = SCons.Tool.LdModSymlinkGenerator) + return _lib_emitter(target, source, env, symlink_generator=SCons.Tool.LdModSymlinkGenerator) + # This is generic enough to be included here... def _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw): @@ -112,98 +116,107 @@ def _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, Verbose = False if Verbose: - print("_versioned_lib_name: libnode={:r}".format(libnode.get_path())) - print("_versioned_lib_name: version={:r}".format(version)) - print("_versioned_lib_name: prefix={:r}".format(prefix)) - print("_versioned_lib_name: suffix={:r}".format(suffix)) - print("_versioned_lib_name: suffix_generator={:r}".format(suffix_generator)) + print("_versioned_lib_name: libnode={!r}".format(libnode.get_path())) + print("_versioned_lib_name: version={!r}".format(version)) + print("_versioned_lib_name: prefix={!r}".format(prefix)) + print("_versioned_lib_name: suffix={!r}".format(suffix)) + print("_versioned_lib_name: suffix_generator={!r}".format(suffix_generator)) versioned_name = os.path.basename(libnode.get_path()) if Verbose: - print("_versioned_lib_name: versioned_name={:r}".format(versioned_name)) + print("_versioned_lib_name: versioned_name={!r}".format(versioned_name)) versioned_prefix = prefix_generator(env, **kw) versioned_suffix = suffix_generator(env, **kw) if Verbose: - print("_versioned_lib_name: versioned_prefix={:r}".format(versioned_prefix)) - print("_versioned_lib_name: versioned_suffix={:r}".format(versioned_suffix)) + print("_versioned_lib_name: versioned_prefix={!r}".format(versioned_prefix)) + print("_versioned_lib_name: versioned_suffix={!r}".format(versioned_suffix)) versioned_prefix_re = '^' + re.escape(versioned_prefix) versioned_suffix_re = re.escape(versioned_suffix) + '$' name = re.sub(versioned_prefix_re, prefix, versioned_name) name = re.sub(versioned_suffix_re, suffix, name) if Verbose: - print("_versioned_lib_name: name={:r}".format(name)) + print("_versioned_lib_name: name={!r}".format(name)) return name + def _versioned_shlib_name(env, libnode, version, prefix, suffix, **kw): - pg = SCons.Tool.ShLibPrefixGenerator - sg = SCons.Tool.ShLibSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, pg, sg, **kw) + prefix_generator = SCons.Tool.ShLibPrefixGenerator + suffix_generator = SCons.Tool.ShLibSuffixGenerator + return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) + def _versioned_ldmod_name(env, libnode, version, prefix, suffix, **kw): - pg = SCons.Tool.LdModPrefixGenerator - sg = SCons.Tool.LdModSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, pg, sg, **kw) + prefix_generator = SCons.Tool.LdModPrefixGenerator + suffix_generator = SCons.Tool.LdModSuffixGenerator + return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) + def _versioned_lib_suffix(env, suffix, version): """For suffix='.so' and version='0.1.2' it returns '.so.0.1.2'""" Verbose = False if Verbose: - print("_versioned_lib_suffix: suffix={:r}".format(suffix)) - print("_versioned_lib_suffix: version={:r}".format(version)) + print("_versioned_lib_suffix: suffix={!r}".format(suffix)) + print("_versioned_lib_suffix: version={!r}".format(version)) if not suffix.endswith(version): suffix = suffix + '.' + version if Verbose: - print("_versioned_lib_suffix: return suffix={:r}".format(suffix)) + print("_versioned_lib_suffix: return suffix={!r}".format(suffix)) return suffix + def _versioned_lib_soname(env, libnode, version, prefix, suffix, name_func): """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so.X'""" Verbose = False if Verbose: - print("_versioned_lib_soname: version={:r}".format(version)) + print("_versioned_lib_soname: version={!r}".format(version)) name = name_func(env, libnode, version, prefix, suffix) if Verbose: - print("_versioned_lib_soname: name={:r}".format(name)) + print("_versioned_lib_soname: name={!r}".format(name)) major = version.split('.')[0] soname = name + '.' + major if Verbose: - print("_versioned_lib_soname: soname={:r}".format(soname)) + print("_versioned_lib_soname: soname={!r}".format(soname)) return soname + def _versioned_shlib_soname(env, libnode, version, prefix, suffix): return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_shlib_name) + def _versioned_ldmod_soname(env, libnode, version, prefix, suffix): return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_ldmod_name) + def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func): - """Generate link names that should be created for a versioned shared lirbrary. + """Generate link names that should be created for a versioned shared library. Returns a dictionary in the form { linkname : linktarget } """ Verbose = False if Verbose: - print("_versioned_lib_symlinks: libnode={:r}".format(libnode.get_path())) - print("_versioned_lib_symlinks: version={:r}".format(version)) + print("_versioned_lib_symlinks: libnode={!r}".format(libnode.get_path())) + print("_versioned_lib_symlinks: version={!r}".format(version)) if sys.platform.startswith('openbsd'): # OpenBSD uses x.y shared library versioning numbering convention # and doesn't use symlinks to backwards-compatible libraries if Verbose: - print("_versioned_lib_symlinks: return symlinks={:r}".format(None)) + print("_versioned_lib_symlinks: return symlinks={!r}".format(None)) return None linkdir = libnode.get_dir() if Verbose: - print("_versioned_lib_symlinks: linkdir={:r}".format(linkdir.get_path())) + print("_versioned_lib_symlinks: linkdir={!r}".format(linkdir.get_path())) name = name_func(env, libnode, version, prefix, suffix) if Verbose: - print("_versioned_lib_symlinks: name={:r}".format(name)) + print("_versioned_lib_symlinks: name={!r}".format(name)) soname = soname_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_versioned_lib_symlinks: soname={!r}".format(soname)) link0 = env.fs.File(soname, linkdir) link1 = env.fs.File(name, linkdir) @@ -211,50 +224,63 @@ def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, so # We create direct symlinks, not daisy-chained. if link0 == libnode: # This enables SHLIBVERSION without periods (e.g. SHLIBVERSION=1) - symlinks = [ (link1, libnode) ] + symlinks = [(link1, libnode)] else: # This handles usual SHLIBVERSION, i.e. '1.2', '1.2.3', etc. - symlinks = [ (link0, libnode), (link1, libnode) ] + symlinks = [(link0, libnode), (link1, libnode)] if Verbose: - print("_versioned_lib_symlinks: return symlinks={:r}".format(SCons.Tool.StringizeLibSymlinks(symlinks))) + print("_versioned_lib_symlinks: return symlinks={!r}".format(SCons.Tool.StringizeLibSymlinks(symlinks))) return symlinks + def _versioned_shlib_symlinks(env, libnode, version, prefix, suffix): - nf = _versioned_shlib_name - sf = _versioned_shlib_soname - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, nf, sf) + name_func = env['LINKCALLBACKS']['VersionedShLibName'] + soname_func = env['LINKCALLBACKS']['VersionedShLibSoname'] + + return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) + def _versioned_ldmod_symlinks(env, libnode, version, prefix, suffix): - nf = _versioned_ldmod_name - sf = _versioned_ldmod_soname - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, nf, sf) + name_func = _versioned_ldmod_name + soname_func = _versioned_ldmod_soname + + name_func = env['LINKCALLBACKS']['VersionedLdModName'] + soname_func = env['LINKCALLBACKS']['VersionedLdModSoname'] + + return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) + def _versioned_lib_callbacks(): return { - 'VersionedShLibSuffix' : _versioned_lib_suffix, - 'VersionedLdModSuffix' : _versioned_lib_suffix, - 'VersionedShLibSymlinks' : _versioned_shlib_symlinks, - 'VersionedLdModSymlinks' : _versioned_ldmod_symlinks, - 'VersionedShLibName' : _versioned_shlib_name, - 'VersionedLdModName' : _versioned_ldmod_name, - 'VersionedShLibSoname' : _versioned_shlib_soname, - 'VersionedLdModSoname' : _versioned_ldmod_soname, + 'VersionedShLibSuffix': _versioned_lib_suffix, + 'VersionedLdModSuffix': _versioned_lib_suffix, + 'VersionedShLibSymlinks': _versioned_shlib_symlinks, + 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, + 'VersionedShLibName': _versioned_shlib_name, + 'VersionedLdModName': _versioned_ldmod_name, + 'VersionedShLibSoname': _versioned_shlib_soname, + 'VersionedLdModSoname': _versioned_ldmod_soname, }.copy() + def _setup_versioned_lib_variables(env, **kw): """ Setup all variables required by the versioning machinery """ tool = None - try: tool = kw['tool'] - except KeyError: pass + try: + tool = kw['tool'] + except KeyError: + pass use_soname = False - try: use_soname = kw['use_soname'] - except KeyError: pass + try: + use_soname = kw['use_soname'] + except KeyError: + pass # The $_SHLIBVERSIONFLAGS define extra commandline flags used when # building VERSIONED shared libraries. It's always set, but used only @@ -284,22 +310,25 @@ def generate(env): SCons.Tool.createSharedLibBuilder(env) SCons.Tool.createProgBuilder(env) - env['SHLINK'] = '$LINK' + env['SHLINK'] = '$LINK' env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared') - env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' - # don't set up the emitter, cause AppendUnique will generate a list + env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + + # don't set up the emitter, because AppendUnique will generate a list # starting with None :-( - env.Append(SHLIBEMITTER = [shlib_emitter]) - env['SMARTLINK'] = smart_link - env['LINK'] = "$SMARTLINK" - env['LINKFLAGS'] = SCons.Util.CLVar('') + env.Append(SHLIBEMITTER=[shlib_emitter]) + + env['SMARTLINK'] = smart_link + env['LINK'] = "$SMARTLINK" + env['LINKFLAGS'] = SCons.Util.CLVar('') + # __RPATH is only set to something ($_RPATH typically) on platforms that support it. - env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' - env['LIBDIRPREFIX']='-L' - env['LIBDIRSUFFIX']='' - env['_LIBFLAGS']='${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}' - env['LIBLINKPREFIX']='-l' - env['LIBLINKSUFFIX']='' + env['LINKCOM'] = '$LINK -o $TARGET $LINKFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + env['LIBDIRPREFIX'] = '-L' + env['LIBDIRSUFFIX'] = '' + env['_LIBFLAGS'] = '${_stripixes(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, LIBPREFIXES, LIBSUFFIXES, __env__)}' + env['LIBLINKPREFIX'] = '-l' + env['LIBLINKSUFFIX'] = '' if env['PLATFORM'] == 'hpux': env['SHLIBSUFFIX'] = '.sl' @@ -311,14 +340,16 @@ def generate(env): # setting them the same means that LoadableModule works everywhere. SCons.Tool.createLoadableModuleBuilder(env) env['LDMODULE'] = '$SHLINK' - env.Append(LDMODULEEMITTER = [ldmod_emitter]) + env.Append(LDMODULEEMITTER=[ldmod_emitter]) env['LDMODULEPREFIX'] = '$SHLIBPREFIX' env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' env['LDMODULEFLAGS'] = '$SHLINKFLAGS' - env['LDMODULECOM'] = '$LDMODULE -o $TARGET $LDMODULEFLAGS $__LDMODULEVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + env[ + 'LDMODULECOM'] = '$LDMODULE -o $TARGET $LDMODULEFLAGS $__LDMODULEVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' env['LDMODULEVERSION'] = '$SHLIBVERSION' env['LDMODULENOVERSIONSYMLINKS'] = '$SHLIBNOVERSIONSYMLINKS' + def exists(env): # This module isn't really a Tool on its own, it's common logic for # other linkers. diff --git a/src/engine/SCons/Tool/link.xml b/src/engine/SCons/Tool/link.xml index 669a020..a8b6954 100644 --- a/src/engine/SCons/Tool/link.xml +++ b/src/engine/SCons/Tool/link.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/linkloc.py b/src/engine/SCons/Tool/linkloc.py index b79be06..cdcf25a 100644 --- a/src/engine/SCons/Tool/linkloc.py +++ b/src/engine/SCons/Tool/linkloc.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/linkloc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/linkloc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import re diff --git a/src/engine/SCons/Tool/linkloc.xml b/src/engine/SCons/Tool/linkloc.xml index 09b43cb..567ed66 100644 --- a/src/engine/SCons/Tool/linkloc.xml +++ b/src/engine/SCons/Tool/linkloc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/m4.py b/src/engine/SCons/Tool/m4.py index 38b9976..30dc4c9 100644 --- a/src/engine/SCons/Tool/m4.py +++ b/src/engine/SCons/Tool/m4.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/m4.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/m4.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Action import SCons.Builder diff --git a/src/engine/SCons/Tool/m4.xml b/src/engine/SCons/Tool/m4.xml index f919af9..f7e81e5 100644 --- a/src/engine/SCons/Tool/m4.xml +++ b/src/engine/SCons/Tool/m4.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/masm.py b/src/engine/SCons/Tool/masm.py index 90162f4..77e32c2 100644 --- a/src/engine/SCons/Tool/masm.py +++ b/src/engine/SCons/Tool/masm.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/masm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/masm.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/masm.xml b/src/engine/SCons/Tool/masm.xml index acc3aa3..1760252 100644 --- a/src/engine/SCons/Tool/masm.xml +++ b/src/engine/SCons/Tool/masm.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/midl.py b/src/engine/SCons/Tool/midl.py index 4088fc4..6879da1 100644 --- a/src/engine/SCons/Tool/midl.py +++ b/src/engine/SCons/Tool/midl.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/midl.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/midl.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Action import SCons.Builder @@ -79,7 +79,7 @@ def generate(env): env['BUILDERS']['TypeLibrary'] = midl_builder def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/midl.xml b/src/engine/SCons/Tool/midl.xml index cc1b880..717eb38 100644 --- a/src/engine/SCons/Tool/midl.xml +++ b/src/engine/SCons/Tool/midl.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mingw.py b/src/engine/SCons/Tool/mingw.py index c2eaa96..ed3f1a3 100644 --- a/src/engine/SCons/Tool/mingw.py +++ b/src/engine/SCons/Tool/mingw.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,10 +31,11 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mingw.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mingw.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path +import glob import SCons.Action import SCons.Builder @@ -42,29 +43,17 @@ import SCons.Defaults import SCons.Tool import SCons.Util -# This is what we search for to find mingw: -key_program = 'mingw32-gcc' - -def find(env): - # First search in the SCons path - path=env.WhereIs(key_program) - if (path): - return path - # then the OS path: - path=SCons.Util.WhereIs(key_program) - if (path): - return path - - # If that doesn't work try default location for mingw - save_path=env['ENV']['PATH'] - env.AppendENVPath('PATH',r'c:\MinGW\bin') - path =env.WhereIs(key_program) - if not path: - env['ENV']['PATH']=save_path - return path +mingw_paths = [ + r'c:\MinGW\bin', + r'C:\cygwin64\bin', + r'C:\msys64', + r'C:\cygwin\bin', + r'C:\msys', +] + def shlib_generator(target, source, env, for_signature): - cmd = SCons.Util.CLVar(['$SHLINK', '$SHLINKFLAGS']) + cmd = SCons.Util.CLVar(['$SHLINK', '$SHLINKFLAGS']) dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX') if dll: cmd.extend(['-o', dll]) @@ -72,31 +61,32 @@ def shlib_generator(target, source, env, for_signature): cmd.extend(['$SOURCES', '$_LIBDIRFLAGS', '$_LIBFLAGS']) implib = env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX') - if implib: cmd.append('-Wl,--out-implib,'+implib.get_string(for_signature)) + if implib: cmd.append('-Wl,--out-implib,' + implib.get_string(for_signature)) def_target = env.FindIxes(target, 'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX') insert_def = env.subst("$WINDOWS_INSERT_DEF") if not insert_def in ['', '0', 0] and def_target: \ - cmd.append('-Wl,--output-def,'+def_target.get_string(for_signature)) + cmd.append('-Wl,--output-def,' + def_target.get_string(for_signature)) return [cmd] + def shlib_emitter(target, source, env): dll = env.FindIxes(target, 'SHLIBPREFIX', 'SHLIBSUFFIX') no_import_lib = env.get('no_import_lib', 0) if not dll: - raise SCons.Errors.UserError("A shared library should have exactly one target with the suffix: %s Target(s) are:%s" % \ + raise SCons.Errors.UserError( + "A shared library should have exactly one target with the suffix: %s Target(s) are:%s" % \ (env.subst("$SHLIBSUFFIX"), ",".join([str(t) for t in target]))) - - if not no_import_lib and \ - not env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX'): + if not no_import_lib and \ + not env.FindIxes(target, 'LIBPREFIX', 'LIBSUFFIX'): # Create list of target libraries as strings - targetStrings=env.ReplaceIxes(dll, - 'SHLIBPREFIX', 'SHLIBSUFFIX', - 'LIBPREFIX', 'LIBSUFFIX') - + targetStrings = env.ReplaceIxes(dll, + 'SHLIBPREFIX', 'SHLIBSUFFIX', + 'LIBPREFIX', 'LIBSUFFIX') + # Now add file nodes to target list target.append(env.fs.File(targetStrings)) @@ -108,17 +98,18 @@ def shlib_emitter(target, source, env): skip_def_insert = env.subst("$WINDOWS_INSERT_DEF") in ['', '0', 0] if not def_source and not def_target and not skip_def_insert: # Create list of target libraries and def files as strings - targetStrings=env.ReplaceIxes(dll, - 'SHLIBPREFIX', 'SHLIBSUFFIX', - 'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX') - + targetStrings = env.ReplaceIxes(dll, + 'SHLIBPREFIX', 'SHLIBSUFFIX', + 'WINDOWSDEFPREFIX', 'WINDOWSDEFSUFFIX') + # Now add file nodes to target list target.append(env.fs.File(targetStrings)) return (target, source) - -shlib_action = SCons.Action.Action(shlib_generator, generator=1) + +shlib_action = SCons.Action.Action(shlib_generator, '$SHLINKCOMSTR', generator=1) +ldmodule_action = SCons.Action.Action(shlib_generator, '$LDMODULECOMSTR', generator=1) res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR') @@ -126,38 +117,63 @@ res_builder = SCons.Builder.Builder(action=res_action, suffix='.o', source_scanner=SCons.Tool.SourceFileScanner) SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan) +# This is what we search for to find mingw: +# key_program = 'mingw32-gcc' +key_program = 'mingw32-make' + + +def find_version_specific_mingw_paths(): + """ + One example of default mingw install paths is: + C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev2\mingw64\bin + + Use glob'ing to find such and add to mingw_paths + """ + new_paths = glob.glob(r"C:\mingw-w64\*\mingw64\bin") + + return new_paths + + def generate(env): - mingw = find(env) + global mingw_paths + # Check for reasoanble mingw default paths + mingw_paths += find_version_specific_mingw_paths() + + mingw = SCons.Tool.find_program_path(env, key_program, default_paths=mingw_paths) if mingw: - dir = os.path.dirname(mingw) - env.PrependENVPath('PATH', dir ) - + mingw_bin_dir = os.path.dirname(mingw) + env.AppendENVPath('PATH', mingw_bin_dir) # Most of mingw is the same as gcc and friends... gnu_tools = ['gcc', 'g++', 'gnulink', 'ar', 'gas', 'gfortran', 'm4'] for tool in gnu_tools: SCons.Tool.Tool(tool)(env) - #... but a few things differ: + # ... but a few things differ: env['CC'] = 'gcc' + # make sure the msvc tool doesnt break us, it added a /flag + if 'CCFLAGS' in env: + # make sure its a CLVar to handle list or str cases + if type(env['CCFLAGS']) is not SCons.Util.CLVar: + env['CCFLAGS'] = SCons.Util.CLVar(env['CCFLAGS']) + env['CCFLAGS'] = SCons.Util.CLVar(str(env['CCFLAGS']).replace('/nologo', '')) env['SHCCFLAGS'] = SCons.Util.CLVar('$CCFLAGS') env['CXX'] = 'g++' env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS') env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared') - env['SHLINKCOM'] = shlib_action - env['LDMODULECOM'] = shlib_action - env.Append(SHLIBEMITTER = [shlib_emitter]) - env.Append(LDMODULEEMITTER = [shlib_emitter]) + env['SHLINKCOM'] = shlib_action + env['LDMODULECOM'] = ldmodule_action + env.Append(SHLIBEMITTER=[shlib_emitter]) + env.Append(LDMODULEEMITTER=[shlib_emitter]) env['AS'] = 'as' - env['WIN32DEFPREFIX'] = '' - env['WIN32DEFSUFFIX'] = '.def' - env['WINDOWSDEFPREFIX'] = '${WIN32DEFPREFIX}' - env['WINDOWSDEFSUFFIX'] = '${WIN32DEFSUFFIX}' + env['WIN32DEFPREFIX'] = '' + env['WIN32DEFSUFFIX'] = '.def' + env['WINDOWSDEFPREFIX'] = '${WIN32DEFPREFIX}' + env['WINDOWSDEFSUFFIX'] = '${WIN32DEFSUFFIX}' env['SHOBJSUFFIX'] = '.o' env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1 - env['RC'] = 'windres' env['RCFLAGS'] = SCons.Util.CLVar('') env['RCINCFLAGS'] = '$( ${_concat(RCINCPREFIX, CPPPATH, RCINCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)' @@ -165,15 +181,21 @@ def generate(env): env['RCINCSUFFIX'] = '' env['RCCOM'] = '$RC $_CPPDEFFLAGS $RCINCFLAGS ${RCINCPREFIX} ${SOURCE.dir} $RCFLAGS -i $SOURCE -o $TARGET' env['BUILDERS']['RES'] = res_builder - + # Some setting from the platform also have to be overridden: env['OBJSUFFIX'] = '.o' env['LIBPREFIX'] = 'lib' env['LIBSUFFIX'] = '.a' env['PROGSUFFIX'] = '.exe' + def exists(env): - return find(env) + mingw = SCons.Tool.find_program_path(env, key_program, default_paths=mingw_paths) + if mingw: + mingw_bin_dir = os.path.dirname(mingw) + env.AppendENVPath('PATH', mingw_bin_dir) + + return mingw # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mingw.xml b/src/engine/SCons/Tool/mingw.xml index 4848637..b1f028d 100644 --- a/src/engine/SCons/Tool/mingw.xml +++ b/src/engine/SCons/Tool/mingw.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/msgfmt.py b/src/engine/SCons/Tool/msgfmt.py index 7e3e2a4..87589ce 100644 --- a/src/engine/SCons/Tool/msgfmt.py +++ b/src/engine/SCons/Tool/msgfmt.py @@ -1,6 +1,6 @@ """ msgfmt tool """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msgfmt.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msgfmt.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from SCons.Builder import BuilderBase ############################################################################# @@ -75,8 +75,22 @@ def _create_mo_file_builder(env, **kw): ############################################################################# def generate(env,**kw): """ Generate `msgfmt` tool """ + import sys + import os import SCons.Util + import SCons.Tool from SCons.Tool.GettextCommon import _detect_msgfmt + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + + if sys.platform == 'win32': + msgfmt = SCons.Tool.find_program_path(env, 'msgfmt', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if msgfmt: + msgfmt_bin_dir = os.path.dirname(msgfmt) + env.AppendENVPath('PATH', msgfmt_bin_dir) + else: + SCons.Warnings.Warning('msgfmt tool requested, but binary not found in ENV PATH') + try: env['MSGFMT'] = _detect_msgfmt(env) except: diff --git a/src/engine/SCons/Tool/msgfmt.xml b/src/engine/SCons/Tool/msgfmt.xml index e00f372..67a8e0d 100644 --- a/src/engine/SCons/Tool/msgfmt.xml +++ b/src/engine/SCons/Tool/msgfmt.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/msginit.py b/src/engine/SCons/Tool/msginit.py index 63daf7f..e52c1b5 100644 --- a/src/engine/SCons/Tool/msginit.py +++ b/src/engine/SCons/Tool/msginit.py @@ -3,7 +3,7 @@ Tool specific initialization of msginit tool. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Tool specific initialization of msginit tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msginit.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msginit.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Warnings import SCons.Builder @@ -77,8 +77,22 @@ def _POInitBuilderWrapper(env, target=None, source=_null, **kw): ############################################################################# def generate(env,**kw): """ Generate the `msginit` tool """ + import sys + import os import SCons.Util + import SCons.Tool from SCons.Tool.GettextCommon import _detect_msginit + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + + if sys.platform == 'win32': + msginit = SCons.Tool.find_program_path(env, 'msginit', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if msginit: + msginit_bin_dir = os.path.dirname(msginit) + env.AppendENVPath('PATH', msginit_bin_dir) + else: + SCons.Warnings.Warning('msginit tool requested, but binary not found in ENV PATH') + try: env['MSGINIT'] = _detect_msginit(env) except: diff --git a/src/engine/SCons/Tool/msginit.xml b/src/engine/SCons/Tool/msginit.xml index 3a2a969..d09dde1 100644 --- a/src/engine/SCons/Tool/msginit.xml +++ b/src/engine/SCons/Tool/msginit.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/msgmerge.py b/src/engine/SCons/Tool/msgmerge.py index aef1f5f..849fe32 100644 --- a/src/engine/SCons/Tool/msgmerge.py +++ b/src/engine/SCons/Tool/msgmerge.py @@ -3,7 +3,7 @@ Tool specific initialization for `msgmerge` tool. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Tool specific initialization for `msgmerge` tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/msgmerge.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msgmerge.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" ############################################################################# def _update_or_init_po_files(target, source, env): @@ -68,8 +68,21 @@ def _POUpdateBuilderWrapper(env, target=None, source=_null, **kw): ############################################################################# def generate(env,**kw): - """ Generate the `xgettext` tool """ + """ Generate the `msgmerge` tool """ + import sys + import os + import SCons.Tool from SCons.Tool.GettextCommon import _detect_msgmerge + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + + if sys.platform == 'win32': + msgmerge = SCons.Tool.find_program_path(env, 'msgmerge', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if msgmerge: + msgmerge_bin_dir = os.path.dirname(msgmerge) + env.AppendENVPath('PATH', msgmerge_bin_dir) + else: + SCons.Warnings.Warning('msgmerge tool requested, but binary not found in ENV PATH') try: env['MSGMERGE'] = _detect_msgmerge(env) except: diff --git a/src/engine/SCons/Tool/msgmerge.xml b/src/engine/SCons/Tool/msgmerge.xml index 65d19e1..2944679 100644 --- a/src/engine/SCons/Tool/msgmerge.xml +++ b/src/engine/SCons/Tool/msgmerge.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mslib.py b/src/engine/SCons/Tool/mslib.py index 3d79649..00a17d7 100644 --- a/src/engine/SCons/Tool/mslib.py +++ b/src/engine/SCons/Tool/mslib.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mslib.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mslib.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool @@ -55,7 +55,7 @@ def generate(env): env['LIBSUFFIX'] = '.lib' def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mslib.xml b/src/engine/SCons/Tool/mslib.xml index 6ee2f22..a9b7cef 100644 --- a/src/engine/SCons/Tool/mslib.xml +++ b/src/engine/SCons/Tool/mslib.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mslink.py b/src/engine/SCons/Tool/mslink.py index 1b16b63..9df531b 100644 --- a/src/engine/SCons/Tool/mslink.py +++ b/src/engine/SCons/Tool/mslink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/mslink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mslink.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path @@ -328,7 +328,7 @@ def generate(env): env['LDMODULECOM'] = compositeLdmodAction def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/mslink.xml b/src/engine/SCons/Tool/mslink.xml index 24b79c7..692c1da 100644 --- a/src/engine/SCons/Tool/mslink.xml +++ b/src/engine/SCons/Tool/mslink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mssdk.py b/src/engine/SCons/Tool/mssdk.py index dd9de93..d66c7fc 100644 --- a/src/engine/SCons/Tool/mssdk.py +++ b/src/engine/SCons/Tool/mssdk.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mssdk.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mssdk.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" """engine.SCons.Tool.mssdk diff --git a/src/engine/SCons/Tool/mssdk.xml b/src/engine/SCons/Tool/mssdk.xml index 0ae3553..b84597e 100644 --- a/src/engine/SCons/Tool/mssdk.xml +++ b/src/engine/SCons/Tool/mssdk.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/msvc.py b/src/engine/SCons/Tool/msvc.py index 2fe16c3..a611f8e 100644 --- a/src/engine/SCons/Tool/msvc.py +++ b/src/engine/SCons/Tool/msvc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/msvc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msvc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import re @@ -112,7 +112,7 @@ def object_emitter(target, source, env, parent_emitter): # # See issue #2505 for a discussion of what to do if it turns # out this assumption causes trouble in the wild: - # http://scons.tigris.org/issues/show_bug.cgi?id=2505 + # https://github.com/SCons/scons/issues/2505 if 'PCH' in env: pch = env['PCH'] if str(target[0]) != SCons.Util.splitext(str(pch))[0] + '.obj': @@ -195,7 +195,10 @@ def msvc_output_flag(target, source, env, for_signature): # that the test(s) for this can be run on non-Windows systems # without having a hard-coded backslash mess up command-line # argument parsing. - return '/Fo${TARGET.dir}' + os.sep + # Adding double os.sep's as if the TARGET.dir has a space or otherwise + # needs to be quoted they are needed per MSVC's odd behavior + # See: https://github.com/SCons/scons/issues/3106 + return '/Fo${TARGET.dir}' + os.sep*2 CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR", batch_key=msvc_batch_key, @@ -259,7 +262,7 @@ def generate(env): env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1 env['RC'] = 'rc' - env['RCFLAGS'] = SCons.Util.CLVar('') + env['RCFLAGS'] = SCons.Util.CLVar('/nologo') env['RCSUFFIXES']=['.rc','.rc2'] env['RCCOM'] = '$RC $_CPPDEFFLAGS $_CPPINCFLAGS $RCFLAGS /fo$TARGET $SOURCES' env['BUILDERS']['RES'] = res_builder @@ -268,6 +271,10 @@ def generate(env): env['SHOBJPREFIX'] = '$OBJPREFIX' env['SHOBJSUFFIX'] = '$OBJSUFFIX' + # MSVC probably wont support unistd.h so default + # without it for lex generation + env["LEXUNISTD"] = SCons.Util.CLVar("--nounistd") + # Set-up ms tools paths msvc_setup_env_once(env) @@ -286,7 +293,7 @@ def generate(env): env['ENV']['SystemRoot'] = SCons.Platform.win32.get_system_root() def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/msvc.xml b/src/engine/SCons/Tool/msvc.xml index edc6936..03d8ce3 100644 --- a/src/engine/SCons/Tool/msvc.xml +++ b/src/engine/SCons/Tool/msvc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -305,7 +305,8 @@ containing the command-line options for specifying directories to be searched by the resource compiler. The value of &cv-RCINCFLAGS; is created -by appending &cv-RCINCPREFIX; and &cv-RCINCSUFFIX; +by respectively prepending and appending +&cv-RCINCPREFIX; and &cv-RCINCSUFFIX; to the beginning and end of each directory in &cv-CPPPATH;. </para> @@ -317,7 +318,7 @@ of each directory in &cv-CPPPATH;. <para> The prefix (flag) used to specify an include directory on the resource compiler command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the &cv-CPPPATH; construction variable when the &cv-RCINCFLAGS; variable is expanded. </para> @@ -352,6 +353,7 @@ constructor; setting it later has no effect. <para> Valid values for Windows are +<literal>14.1</literal>, <literal>14.0</literal>, <literal>14.0Exp</literal>, <literal>12.0</literal>, @@ -424,18 +426,24 @@ This variable must be passed as an argument to the Environment() constructor; setting it later has no effect. This is currently only used on Windows, but in the future it will be used on other OSes as well. +If this is set and MSVC_VERSION is not set, this will search for +all installed MSVC's that support the TARGET_ARCH, selecting the +latest version for use. </para> <para> Valid values for Windows are <literal>x86</literal>, +<literal>arm</literal>, <literal>i386</literal> (for 32 bits); <literal>amd64</literal>, +<literal>arm64</literal>, <literal>emt64</literal>, <literal>x86_64</literal> (for 64 bits); and <literal>ia64</literal> (Itanium). + For example, if you want to compile 64-bit binaries, you would set <literal>TARGET_ARCH='x86_64'</literal> in your SCons environment. </para> diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index 05531c6..ddf8608 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/msvs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msvs.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -149,9 +149,9 @@ def splitFully(path): return [base] def makeHierarchy(sources): - '''Break a list of files into a hierarchy; for each value, if it is a string, + """Break a list of files into a hierarchy; for each value, if it is a string, then it is a file. If it is a dictionary, it is a folder. The string is - the original path of the file.''' + the original path of the file.""" hierarchy = {} for file in sources: @@ -189,7 +189,7 @@ class _UserGenerator(object): elif SCons.Util.is_List(env['variant']): variants = env['variant'] - if 'DebugSettings' not in env or env['DebugSettings'] == None: + if 'DebugSettings' not in env or env['DebugSettings'] is None: dbg_settings = [] elif SCons.Util.is_Dict(env['DebugSettings']): dbg_settings = [env['DebugSettings']] @@ -520,7 +520,7 @@ class _DSPGenerator(object): config.cmdargs = cmdargs config.runfile = runfile - match = re.match('(.*)\|(.*)', variant) + match = re.match(r'(.*)\|(.*)', variant) if match: config.variant = match.group(1) config.platform = match.group(2) @@ -1096,12 +1096,17 @@ V10DSPCommandLine = """\ \t\t<NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='%(variant)s|%(platform)s'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies> """ +V15DSPHeader = """\ +<?xml version="1.0" encoding="%(encoding)s"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +""" + class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): """Generates a Project file for MSVS 2010""" - def __init__(self, dspfile, source, env): + def __init__(self, dspfile, header, source, env): _DSPGenerator.__init__(self, dspfile, source, env) - self.dspheader = V10DSPHeader + self.dspheader = header self.dspconfiguration = V10DSPProjectConfiguration self.dspglobals = V10DSPGlobals @@ -1287,7 +1292,7 @@ class _GenerateV10DSP(_DSPGenerator, _GenerateV10User): 'Other Files': ''} cats = sorted([k for k in list(categories.keys()) if self.sources[k]], - key = lambda a: a.lower()) + key = lambda a: a.lower()) # print vcxproj.filters file first self.filters_file.write('\t<ItemGroup>\n') @@ -1423,7 +1428,7 @@ class _GenerateV7DSW(_DSWGenerator): def AddConfig(self, variant, dswfile=dswfile): config = Config() - match = re.match('(.*)\|(.*)', variant) + match = re.match(r'(.*)\|(.*)', variant) if match: config.variant = match.group(1) config.platform = match.group(2) @@ -1501,7 +1506,9 @@ class _GenerateV7DSW(_DSWGenerator): def PrintSolution(self): """Writes a solution file""" self.file.write('Microsoft Visual Studio Solution File, Format Version %s\n' % self.versionstr) - if self.version_num >= 12.0: + if self.version_num > 14.0: + self.file.write('# Visual Studio 15\n') + elif self.version_num >= 12.0: self.file.write('# Visual Studio 14\n') elif self.version_num >= 11.0: self.file.write('# Visual Studio 11\n') @@ -1519,7 +1526,7 @@ class _GenerateV7DSW(_DSWGenerator): name = base self.file.write('Project("%s") = "%s", "%s", "%s"\n' % (external_makefile_guid, name, dspinfo['SLN_RELATIVE_FILE_PATH'], dspinfo['GUID'])) - if self.version_num >= 7.1 and self.version_num < 8.0: + if 7.1 <= self.version_num < 8.0: self.file.write('\tProjectSection(ProjectDependencies) = postProject\n' '\tEndProjectSection\n') self.file.write('EndProject\n') @@ -1679,8 +1686,11 @@ def GenerateDSP(dspfile, source, env): version_num = 6.0 if 'MSVS_VERSION' in env: version_num, suite = msvs_parse_version(env['MSVS_VERSION']) - if version_num >= 10.0: - g = _GenerateV10DSP(dspfile, source, env) + if version_num > 14.0: + g = _GenerateV10DSP(dspfile, V15DSPHeader, source, env) + g.Build() + elif version_num >= 10.0: + g = _GenerateV10DSP(dspfile, V10DSPHeader, source, env) g.Build() elif version_num >= 7.0: g = _GenerateV7DSP(dspfile, source, env) @@ -1990,7 +2000,7 @@ def generate(env): env['SCONS_HOME'] = os.environ.get('SCONS_HOME') def exists(env): - return msvc_exists() + return msvc_exists(env) # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/msvs.xml b/src/engine/SCons/Tool/msvs.xml index 0408509..7943f22 100644 --- a/src/engine/SCons/Tool/msvs.xml +++ b/src/engine/SCons/Tool/msvs.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -17,160 +17,212 @@ See its __doc__ string for a discussion of the format. <!ENTITY % variables-mod SYSTEM "../../../../doc/generated/variables.mod"> %variables-mod; ]> -<sconsdoc -xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd" -xmlns="http://www.scons.org/dbxsd/v1.0" -xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -xmlns:xs="http://www.w3.org/2001/XMLSchema" -xmlns:ns="http://www.scons.org/dbxsd/v1.0"><tool name="msvs"> <summary> <para> -Sets construction variables for Microsoft Visual Studio. </para> </summary> -<sets> <item>MSVSPROJECTCOM</item> <item>MSVSSOLUTIONCOM</item> -<item>MSVSSCONSCRIPT</item> <item>MSVSSCONS</item> <item>MSVSSCONSFLAGS</item> -<item>MSVSSCONSCOM</item> <item>MSVSBUILDCOM</item> -<item>MSVSREBUILDCOM</item> <item>MSVSCLEANCOM</item> -<item>MSVSENCODING</item> </sets> <uses> </uses> </tool> <builder -name="MSVSProject"> <summary> <para> Builds a Microsoft Visual Studio project -file, and by default builds a solution file as well. </para> <para> This -builds a Visual Studio project file, based on the version of Visual Studio -that is configured (either the latest installed version, or the version -specified by &cv-link-MSVS_VERSION; in the Environment constructor). For -Visual Studio 6, it will generate a <filename>.dsp</filename> file. For Visual -Studio 7 (.NET) and later versions, it will generate a -<filename>.vcproj</filename> file. </para> <para> By default, this also -generates a solution file for the specified project, a -<filename>.dsw</filename> file for Visual Studio 6 or a -<filename>.sln</filename> file for Visual Studio 7 (.NET). This behavior may -be disabled by specifying <literal>auto_build_solution=0</literal> when you -call &b-MSVSProject;, in which case you presumably want to build the solution -file(s) by calling the &b-MSVSSolution; Builder (see below). </para> <para> -The &b-MSVSProject; builder takes several lists of filenames to be placed into -the project file. These are currently limited to <literal>srcs</literal>, -<literal>incs</literal>, <literal>localincs</literal>, -<literal>resources</literal>, and <literal>misc</literal>. These are pretty -self-explanatory, but it should be noted that these lists are added to the -&cv-link-SOURCES; construction variable as strings, NOT as SCons File Nodes. -This is because they represent file names to be added to the project file, not -the source files used to build the project file. </para> <para> The above -filename lists are all optional, although at least one must be specified for -the resulting project file to be non-empty. </para> <para> In addition to the -above lists of values, the following values may be specified: -</para><variablelist> - <varlistentry> - <term>target</term> - - <listitem> - <para>The name of the target <filename>.dsp</filename> or - <filename>.vcproj</filename> file. The correct suffix for the version - of Visual Studio must be used, but the &cv-link-MSVSPROJECTSUFFIX; - construction variable will be defined to the correct value (see - example below).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>variant</term> - - <listitem> - <para>The name of this particular variant. For Visual Studio 7 - projects, this can also be a list of variant names. These are - typically things like "Debug" or "Release", but really can be anything - you want. For Visual Studio 7 projects, they may also specify a target - platform separated from the variant name by a <literal>|</literal> - (vertical pipe) character: <literal>Debug|Xbox</literal>. The default - target platform is Win32. Multiple calls to &b-MSVSProject; with - different variants are allowed; all variants will be added to the - project file with their appropriate build targets and - sources.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>cmdargs</term> - - <listitem> - <para>Additional command line arguments for the different - variants. The number of <literal>cmdargs</literal> entries must match - the number of <literal>variant</literal> entries, or be empty (not - specified). If you give only one, it will automatically be propagated - to all variants.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>buildtarget</term> - - <listitem> - <para>An optional string, node, or list of strings or nodes (one - per build variant), to tell the Visual Studio debugger what output - target to use in what build variant. The number of - <literal>buildtarget</literal> entries must match the number of - <literal>variant</literal> entries.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>runfile</term> - - <listitem> - <para>The name of the file that Visual Studio 7 and later will - run and debug. This appears as the value of the - <literal>Output</literal> field in the resulting Visual Studio project - file. If this is not specified, the default is the same as the - specified <literal>buildtarget</literal> value.</para> - </listitem> - </varlistentry> - </variablelist><para> Note that because &SCons; always executes its build -commands from the directory in which the &SConstruct; file is located, if you -generate a project file in a different directory than the &SConstruct; -directory, users will not be able to double-click on the file name in -compilation error messages displayed in the Visual Studio console output -window. This can be remedied by adding the Visual C/C++ <literal>/FC</literal> -compiler option to the &cv-link-CCFLAGS; variable so that the compiler will -print the full path name of any files that cause compilation errors. </para> -<para> Example usage: </para> - <example_commands> +<sconsdoc xmlns="http://www.scons.org/dbxsd/v1.0" xmlns:ns="http://www.scons.org/dbxsd/v1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.scons.org/dbxsd/v1.0 http://www.scons.org/dbxsd/v1.0/scons.xsd"> + <tool name="msvs"> + <summary> + <para>Sets construction variables for Microsoft Visual Studio.</para> + </summary> + <sets> + <item>MSVSPROJECTCOM</item> + <item>MSVSSOLUTIONCOM</item> + <item>MSVSSCONSCRIPT</item> + <item>MSVSSCONS</item> + <item>MSVSSCONSFLAGS</item> + <item>MSVSSCONSCOM</item> + <item>MSVSBUILDCOM</item> + <item>MSVSREBUILDCOM</item> + <item>MSVSCLEANCOM</item> + <item>MSVSENCODING</item> + </sets> + <uses /> + </tool> + <builder name="MSVSProject"> + <summary> + <para> + Builds a Microsoft Visual Studio project file, and by default + builds a solution file as well. + </para> + <para> + This builds a Visual Studio project file, based on the + version of Visual Studio that is configured (either the + latest installed version, or the version specified by + &cv-link-MSVS_VERSION; in the Environment constructor). For + Visual Studio 6, it will generate a <filename>.dsp</filename> + file. For Visual Studio 7 (.NET) and later versions, it will + generate a <filename>.vcproj</filename> file. + </para> + <para> + By default, this also generates a solution file for the + specified project, a <filename>.dsw</filename> file for + Visual Studio 6 or a <filename>.sln</filename> file for + Visual Studio 7 (.NET). This behavior may be disabled by + specifying <literal>auto_build_solution=0</literal> when you + call &b-MSVSProject;, in which case you presumably want to + build the solution file(s) by calling the &b-MSVSSolution; + Builder (see below). + </para> + <para> + The &b-MSVSProject; builder takes several lists of filenames + to be placed into the project file. These are currently + limited to <literal>srcs</literal>, <literal>incs</literal>, + <literal>localincs</literal>, <literal>resources</literal>, and + <literal>misc</literal>. These are pretty self-explanatory, + but it should be noted that these lists are added to the + &cv-link-SOURCES; construction variable as strings, NOT as + SCons File Nodes. This is because they represent file names + to be added to the project file, not the source files used + to build the project file. + </para> + <para> + The above filename lists are all optional, although at least + one must be specified for the resulting project file to + be non-empty. + </para> + <para> + In addition to the above lists of values, the following values + may be specified: + </para> + <variablelist> + <varlistentry> + <term>target</term> + <listitem> + <para> + The name of the target <filename>.dsp</filename> + or <filename>.vcproj</filename> file. + The correct suffix for the version of Visual Studio + must be used, but the &cv-link-MSVSPROJECTSUFFIX; + construction variable will be defined to the correct + value (see example below). + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>variant</term> + <listitem> + <para> + The name of this particular variant. For Visual Studio 7 + projects, this can also be a list of variant names. These + are typically things like "Debug" or "Release", but + really can be anything you want. For Visual Studio + 7 projects, they may also specify a target platform + separated from the variant name by a <literal>|</literal> + (vertical pipe) character: <literal>Debug|Xbox</literal>. + The default target platform is Win32. Multiple calls + to &b-MSVSProject; with different variants are allowed; + all variants will be added to the project file with + their appropriate build targets and sources. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>cmdargs</term> + <listitem> + <para> + Additional command line arguments + for the different variants. The number of + <literal>cmdargs</literal> entries must match the number + of <literal>variant</literal> entries, or be empty (not + specified). If you give only one, it will automatically + be propagated to all variants. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>buildtarget</term> + <listitem> + <para> + An optional string, node, or list of strings + or nodes (one per build variant), to tell + the Visual Studio debugger what output target + to use in what build variant. The number of + <literal>buildtarget</literal> entries must match the + number of <literal>variant</literal> entries. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>runfile</term> + <listitem> + <para> + The name of the file that Visual Studio 7 and + later will run and debug. This appears as the + value of the <literal>Output</literal> field in the + resulting Visual Studio project file. If this is not + specified, the default is the same as the specified + <literal>buildtarget</literal> value. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + Note that because &SCons; always executes its build commands + from the directory in which the &SConstruct; file is located, + if you generate a project file in a different directory + than the &SConstruct; directory, users will not be able to + double-click on the file name in compilation error messages + displayed in the Visual Studio console output window. This can + be remedied by adding the Visual C/C++ <literal>/FC</literal> + compiler option to the &cv-link-CCFLAGS; variable so that + the compiler will print the full path name of any files that + cause compilation errors. + </para> + <para>Example usage:</para> + <example_commands> barsrcs = ['bar.cpp'] barincs = ['bar.h'] barlocalincs = ['StdAfx.h'] barresources = ['bar.rc','resource.h'] barmisc = ['bar_readme.txt'] -dll = env.SharedLibrary(target = 'bar.dll', - source = barsrcs) +dll = env.SharedLibrary(target='bar.dll', + source=barsrcs) buildtarget = [s for s in dll if str(s).endswith('dll')] -env.MSVSProject(target = 'Bar' + env['MSVSPROJECTSUFFIX'], - srcs = barsrcs, - incs = barincs, - localincs = barlocalincs, - resources = barresources, - misc = barmisc, - buildtarget = buildtarget, - variant = 'Release') -</example_commands> -<para>Starting with version 2.4 of -SCons it's also possible to specify the optional argument -<parameter>DebugSettings</parameter>, which creates files for debugging under -Visual Studio:</para><variablelist> - <varlistentry> - <term>DebugSettings</term> - - <listitem> - <para>A dictionary of debug settings that get written to the - <filename>.vcproj.user</filename> or the - <filename>.vcxproj.user</filename> file, depending on the version - installed. As it is done for cmdargs (see above), you can specify a - <parameter>DebugSettings</parameter> dictionary per variant. If you - give only one, it will be propagated to all variants.</para> - </listitem> - </varlistentry> - </variablelist><para>Currently, only Visual Studio v9.0 and Visual Studio -version v11 are implemented, for other versions no file is generated. To -generate the user file, you just need to add a -<parameter>DebugSettings</parameter> dictionary to the environment with the -right parameters for your MSVS version. If the dictionary is empty, or does -not contain any good value, no file will be generated.</para><para>Following -is a more contrived example, involving the setup of a project for variants and -DebugSettings:</para><example_commands># Assuming you store your defaults in a file +env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], + srcs=barsrcs, + incs=barincs, + localincs=barlocalincs, + resources=barresources, + misc=barmisc, + buildtarget=buildtarget, + variant='Release') + </example_commands> + <para> + Starting with version 2.4 of SCons it is + also possible to specify the optional argument + <parameter>DebugSettings</parameter>, which creates files + for debugging under Visual Studio: + </para> + <variablelist> + <varlistentry> + <term>DebugSettings</term> + <listitem> + <para> + A dictionary of debug settings that get written + to the <filename>.vcproj.user</filename> or the + <filename>.vcxproj.user</filename> file, depending on the + version installed. As it is done for cmdargs (see above), + you can specify a <parameter>DebugSettings</parameter> + dictionary per variant. If you give only one, it will + be propagated to all variants. + </para> + </listitem> + </varlistentry> + </variablelist> + <para> + Currently, only Visual Studio v9.0 and Visual Studio + version v11 are implemented, for other versions no file + is generated. To generate the user file, you just need to + add a <parameter>DebugSettings</parameter> dictionary to the + environment with the right parameters for your MSVS version. If + the dictionary is empty, or does not contain any good value, + no file will be generated. + </para> + <para> + Following is a more contrived example, involving the setup + of a project for variants and DebugSettings: + </para> + <example_commands> +# Assuming you store your defaults in a file vars = Variables('variables.py') msvcver = vars.args.get('vc', '9') @@ -179,7 +231,7 @@ if msvcver == '9' or msvcver == '11': env = Environment(MSVC_VERSION=msvcver+'.0', MSVC_BATCH=False) else: env = Environment() - + AddOption('--userfile', action='store_true', dest='userfile', default=False, help="Create Visual Studio Project user file") @@ -214,10 +266,10 @@ V9DebugSettings = { } # -# 2. Because there are a lot of different options depending on the Microsoft -# Visual Studio version, if you use more than one version you have to -# define a dictionary per version, for instance if you want to create a user -# file to launch a specific application for testing your dll with Microsoft +# 2. Because there are a lot of different options depending on the Microsoft +# Visual Studio version, if you use more than one version you have to +# define a dictionary per version, for instance if you want to create a user +# file to launch a specific application for testing your dll with Microsoft # Visual Studio 2012 (v11): # V10DebugSettings = { @@ -249,7 +301,7 @@ V10DebugSettings = { } # -# 3. Select the dictionary you want depending on the version of visual Studio +# 3. Select the dictionary you want depending on the version of visual Studio # Files you want to generate. # if not env.GetOption('userfile'): @@ -258,7 +310,7 @@ elif env.get('MSVC_VERSION', None) == '9.0': dbgSettings = V9DebugSettings elif env.get('MSVC_VERSION', None) == '11.0': dbgSettings = V10DebugSettings -else: +else: dbgSettings = None # @@ -270,251 +322,365 @@ barlocalincs = ['StdAfx.h'] barresources = ['bar.rc','resource.h'] barmisc = ['ReadMe.txt'] -dll = env.SharedLibrary(target = 'bar.dll', - source = barsrcs) - -env.MSVSProject(target = 'Bar' + env['MSVSPROJECTSUFFIX'], - srcs = barsrcs, - incs = barincs, - localincs = barlocalincs, - resources = barresources, - misc = barmisc, - buildtarget = [dll[0]] * 2, - variant = ('Debug|Win32', 'Release|Win32'), - cmdargs = 'vc=%s' % msvcver, - DebugSettings = (dbgSettings, {})) -</example_commands> </summary> </builder> <builder -name="MSVSSolution"> <summary> <para>Builds a Microsoft Visual Studio solution -file. </para> <para>This builds a Visual Studio solution file, based on the -version of Visual Studio that is configured (either the latest installed -version, or the version specified by &cv-link-MSVS_VERSION; in the -construction environment). For Visual Studio 6, it will generate a -<filename>.dsw</filename> file. For Visual Studio 7 (.NET), it will generate a -<filename>.sln</filename> file. </para> <para> The following values must be -specified: </para><variablelist> - <varlistentry> - <term>target</term> - - <listitem> - <para>The name of the target .dsw or .sln file. The correct - suffix for the version of Visual Studio must be used, but the value - &cv-link-MSVSSOLUTIONSUFFIX; will be defined to the correct value (see - example below).</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>variant</term> - - <listitem> - <para>The name of this particular variant, or a list of variant - names (the latter is only supported for MSVS 7 solutions). These are - typically things like "Debug" or "Release", but really can be anything - you want. For MSVS 7 they may also specify target platform, like this - "Debug|Xbox". Default platform is Win32.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>projects</term> - - <listitem> - <para>A list of project file names, or Project nodes returned by - calls to the &b-MSVSProject; Builder, to be placed into the solution - file. It should be noted that these file names are NOT added to the - $SOURCES environment variable in form of files, but rather as strings. - This is because they represent file names to be added to the solution - file, not the source files used to build the solution - file.</para> - </listitem> - </varlistentry> - </variablelist> <para> Example Usage: </para> <example_commands> -env.MSVSSolution(target = 'Bar' + env['MSVSSOLUTIONSUFFIX'], projects = ['bar' -+ env['MSVSPROJECTSUFFIX']], variant = 'Release') -</example_commands></summary></builder> <cvar name="MSVS"> <summary> <para> -When the Microsoft Visual Studio tools are initialized, they set up this -dictionary with the following keys: </para><variablelist> - <varlistentry> - <term>VERSION</term> - - <listitem> - <para>the version of MSVS being used (can be set via - &cv-link-MSVS_VERSION;)</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>VERSIONS</term> - - <listitem> - <para>the available versions of MSVS installed</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>VCINSTALLDIR</term> - - <listitem> - <para>installed directory of Visual C++</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>VSINSTALLDIR</term> - - <listitem> - <para>installed directory of Visual Studio</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKDIR</term> - - <listitem> - <para>installed directory of the .NET framework</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKVERSIONS</term> - - <listitem> - <para>list of installed versions of the .NET framework, sorted - latest to oldest.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKVERSION</term> - - <listitem> - <para>latest installed version of the .NET - framework</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>FRAMEWORKSDKDIR</term> - - <listitem> - <para>installed location of the .NET SDK.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>PLATFORMSDKDIR</term> - - <listitem> - <para>installed location of the Platform SDK.</para> - </listitem> - </varlistentry> - - <varlistentry> - <term>PLATFORMSDK_MODULES</term> - - <listitem> - <para>dictionary of installed Platform SDK modules, where the - dictionary keys are keywords for the various modules, and the values - are 2-tuples where the first is the release date, and the second is - the version number.</para> - </listitem> - </varlistentry> - </variablelist><para>If a value isn't set, it wasn't available in the -registry.</para></summary></cvar> <cvar name="MSVS_ARCH"> <summary> <para>Sets -the architecture for which the generated project(s) should build. </para> -<para>The default value is <literal>x86</literal>. <literal>amd64</literal> is -also supported by &SCons; for some Visual Studio versions. Trying to set -&cv-MSVS_ARCH; to an architecture that's not supported for a given Visual -Studio version will generate an error. </para> </summary> </cvar> <cvar -name="MSVS_PROJECT_GUID"> <summary> <para>The string placed in a generated +dll = env.SharedLibrary(target='bar.dll', + source=barsrcs) + +env.MSVSProject(target='Bar' + env['MSVSPROJECTSUFFIX'], + srcs=barsrcs, + incs=barincs, + localincs=barlocalincs, + resources=barresources, + misc=barmisc, + buildtarget=[dll[0]] * 2, + variant=('Debug|Win32', 'Release|Win32'), + cmdargs='vc=%s' % msvcver, + DebugSettings=(dbgSettings, {})) + </example_commands> + </summary> + </builder> + <builder name="MSVSSolution"> + <summary> + <para>Builds a Microsoft Visual Studio solution file.</para> + <para> + This builds a Visual Studio solution file, based on the + version of Visual Studio that is configured (either the + latest installed version, or the version specified by + &cv-link-MSVS_VERSION; in the construction environment). For + Visual Studio 6, it will generate a <filename>.dsw</filename> + file. For Visual Studio 7 (.NET), it will generate a + <filename>.sln</filename> file. + </para> + <para>The following values must be specified:</para> + <variablelist> + <varlistentry> + <term>target</term> + <listitem> + <para> + The name of the target .dsw or .sln file. The correct + suffix for the version of Visual Studio must be used, + but the value &cv-link-MSVSSOLUTIONSUFFIX; will be + defined to the correct value (see example below). + </para> + </listitem> + </varlistentry> <varlistentry> + <term>variant</term> <listitem> + <para> + The name of this particular variant, or a list of + variant names (the latter is only supported for MSVS + 7 solutions). These are typically things like "Debug" + or "Release", but really can be anything you want. For + MSVS 7 they may also specify target platform, like this + "Debug|Xbox". Default platform is Win32. + </para> + </listitem> + </varlistentry> <varlistentry> + <term>projects</term> <listitem> + <para> + A list of project file names, or Project nodes returned + by calls to the &b-MSVSProject; Builder, to be placed + into the solution file. It should be noted that these + file names are NOT added to the $SOURCES environment + variable in form of files, but rather as strings. + This is because they represent file names to be added + to the solution file, not the source files used to + build the solution file. + </para> + </listitem> + </varlistentry> + </variablelist> + <para>Example Usage:</para> + <example_commands> +env.MSVSSolution(target='Bar' + env['MSVSSOLUTIONSUFFIX'], projects=['bar' + env['MSVSPROJECTSUFFIX']], variant='Release') + </example_commands> + </summary> + </builder> <cvar name="MSVS"> + <summary> + <para> + When the Microsoft Visual Studio tools are initialized, + they set up this dictionary with the following keys: + </para> + <variablelist> + <varlistentry> + <term>VERSION</term> <listitem> + <para>the version of MSVS being used (can be set via + &cv-link-MSVS_VERSION;)</para> + </listitem> + </varlistentry> <varlistentry> + <term>VERSIONS</term> <listitem> + <para>the available versions of MSVS installed</para> + </listitem> + </varlistentry> <varlistentry> + <term>VCINSTALLDIR</term> <listitem> + <para>installed directory of Visual C++</para> + </listitem> + </varlistentry> <varlistentry> + <term>VSINSTALLDIR</term> <listitem> + <para>installed directory of Visual Studio</para> + </listitem> + </varlistentry> <varlistentry> + <term>FRAMEWORKDIR</term> <listitem> + <para>installed directory of the .NET framework</para> + </listitem> + </varlistentry> <varlistentry> + <term>FRAMEWORKVERSIONS</term> <listitem> + <para> + list of installed versions of the .NET framework, + sorted latest to oldest. + </para> + </listitem> + </varlistentry> + <varlistentry> + <term>FRAMEWORKVERSION</term> + <listitem> + <para>latest installed version of the .NET framework</para> + </listitem> + </varlistentry> + <varlistentry> + <term>FRAMEWORKSDKDIR</term> + <listitem> + <para>installed location of the .NET SDK.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>PLATFORMSDKDIR</term> + <listitem> + <para>installed location of the Platform SDK.</para> + </listitem> + </varlistentry> + <varlistentry> + <term>PLATFORMSDK_MODULES</term> + <listitem> + <para> + dictionary of installed Platform SDK modules, where the + dictionary keys are keywords for the various modules, + and the values are 2-tuples where the first is the + release date, and the second is the version number. + </para> + </listitem> + </varlistentry> + </variablelist> + <para>If a value is not set, it was not available in the registry.</para> + </summary> + </cvar> <cvar name="MSVS_ARCH"> + <summary> + <para>Sets the architecture for which the generated project(s) should build.</para> + <para> + The default value is <literal>x86</literal>. + <literal>amd64</literal> is also supported by &SCons; for + most Visual Studio versions. Since Visual Studio 2015 + <literal>arm</literal> is supported, and since Visual Studio + 2017 <literal>arm64</literal> is supported. + Trying to set &cv-MSVS_ARCH; + to an architecture that's not supported for a given Visual + Studio version will generate an error. + </para> + </summary> + </cvar> <cvar name="MSVS_PROJECT_GUID"> + <summary> + <para> + The string placed in a generated Microsoft Visual Studio project file as the value of the -<literal>ProjectGUID</literal> attribute. There is no default value. If not -defined, a new GUID is generated. </para> </summary> </cvar> <cvar -name="MSVS_SCC_AUX_PATH"> <summary> <para>The path name placed in a generated + <literal>ProjectGUID</literal> attribute. There is no default + value. If not +defined, a new GUID is generated. + + </para> + </summary> + </cvar> <cvar name="MSVS_SCC_AUX_PATH"> + <summary> + <para> + The path name placed in a generated Microsoft Visual Studio project file as the value of the -<literal>SccAuxPath</literal> attribute if the -<envar>MSVS_SCC_PROVIDER</envar> construction variable is also set. There is -no default value. </para> </summary> </cvar> <cvar -name="MSVS_SCC_CONNECTION_ROOT"> <summary> <para>The root path of projects in -your SCC workspace, i.e the path under which all project and solution files -will be generated. It is used as a reference path from which the relative -paths of the generated Microsoft Visual Studio project and solution files are -computed. The relative project file path is placed as the value of the -<literal>SccLocalPath</literal> attribute of the project file and as the -values of the -<literal>SccProjectFilePathRelativizedFromConnection[i]</literal> (where [i] -ranges from 0 to the number of projects in the solution) attributes of the -<literal>GlobalSection(SourceCodeControl)</literal> section of the Microsoft -Visual Studio solution file. Similarly the relative solution file path is -placed as the values of the <literal>SccLocalPath[i]</literal> (where [i] -ranges from 0 to the number of projects in the solution) attributes of the -<literal>GlobalSection(SourceCodeControl)</literal> section of the Microsoft -Visual Studio solution file. This is used only if the -<envar>MSVS_SCC_PROVIDER</envar> construction variable is also set. The -default value is the current working directory. </para> </summary> </cvar> -<cvar name="MSVS_SCC_PROJECT_NAME"> <summary> <para>The project name placed in -a generated Microsoft Visual Studio project file as the value of the -<literal>SccProjectName</literal> attribute if the -<envar>MSVS_SCC_PROVIDER</envar> construction variable is also set. In this -case the string is also placed in the <literal>SccProjectName0</literal> -attribute of the <literal>GlobalSection(SourceCodeControl)</literal> section -of the Microsoft Visual Studio solution file. There is no default value. -</para> </summary> </cvar> <cvar name="MSVS_SCC_PROVIDER"> <summary> <para>The -string placed in a generated Microsoft Visual Studio project file as the value -of the <literal>SccProvider</literal> attribute. The string is also placed in -the <literal>SccProvider0</literal> attribute of the -<literal>GlobalSection(SourceCodeControl)</literal> section of the Microsoft -Visual Studio solution file. There is no default value. </para> </summary> -</cvar> <cvar name="MSVS_VERSION"> <summary> <para>Sets the preferred version -of Microsoft Visual Studio to use. </para> <para>If &cv-MSVS_VERSION; is not -set, &SCons; will (by default) select the latest version of Visual Studio -installed on your system. So, if you have version 6 and version 7 (MSVS .NET) -installed, it will prefer version 7. You can override this by specifying the -<envar>MSVS_VERSION</envar> variable in the Environment initialization, -setting it to the appropriate version ('6.0' or '7.0', for example). If the -specified version isn't installed, tool initialization will fail. </para> -<para>This is obsolete: use &cv-MSVC_VERSION; instead. If &cv-MSVS_VERSION; is -set and &cv-MSVC_VERSION; is not, &cv-MSVC_VERSION; will be set automatically -to &cv-MSVS_VERSION;. If both are set to different values, scons will raise an -error. </para> </summary> </cvar> <cvar name="MSVSBUILDCOM"> <summary> -<para>The build command line placed in a generated Microsoft Visual Studio -project file. The default is to have Visual Studio invoke SCons with any -specified build targets. </para> </summary> </cvar> <cvar name="MSVSCLEANCOM"> -<summary> <para>The clean command line placed in a generated Microsoft Visual -Studio project file. The default is to have Visual Studio invoke SCons with -the -c option to remove any specified targets. </para> </summary> </cvar> -<cvar name="MSVSENCODING"> <summary> <para>The encoding string placed in a -generated Microsoft Visual Studio project file. The default is encoding -<literal>Windows-1252</literal>. </para> </summary> </cvar> <cvar -name="MSVSPROJECTCOM"> <summary> <para>The action used to generate Microsoft -Visual Studio project files. </para> </summary> </cvar> <cvar -name="MSVSPROJECTSUFFIX"> <summary> <para>The suffix used for Microsoft Visual -Studio project (DSP) files. The default value is <filename>.vcproj</filename> -when using Visual Studio version 7.x (.NET) or later version, and -<filename>.dsp</filename> when using earlier versions of Visual Studio. -</para> </summary> </cvar> <cvar name="MSVSREBUILDCOM"> <summary> <para>The -rebuild command line placed in a generated Microsoft Visual Studio project -file. The default is to have Visual Studio invoke SCons with any specified -rebuild targets. </para> </summary> </cvar> <cvar name="MSVSSCONS"> <summary> -<para>The SCons used in generated Microsoft Visual Studio project files. The -default is the version of SCons being used to generate the project file. -</para> </summary> </cvar> <cvar name="MSVSSCONSFLAGS"> <summary> <para>The -SCons flags used in generated Microsoft Visual Studio project files. </para> -</summary> </cvar> <cvar name="MSVSSCONSCOM"> <summary> <para>The default -SCons command used in generated Microsoft Visual Studio project files. </para> -</summary> </cvar> <cvar name="MSVSSCONSCRIPT"> <summary> <para>The sconscript -file (that is, &SConstruct; or &SConscript; file) that will be invoked by -Visual Studio project files (through the &cv-link-MSVSSCONSCOM; variable). The -default is the same sconscript file that contains the call to &b-MSVSProject; -to build the project file. </para> </summary> </cvar> <cvar -name="MSVSSOLUTIONCOM"> <summary> <para>The action used to generate Microsoft -Visual Studio solution files. </para> </summary> </cvar> <cvar -name="MSVSSOLUTIONSUFFIX"> <summary> <para>The suffix used for Microsoft -Visual Studio solution (DSW) files. The default value is -<filename>.sln</filename> when using Visual Studio version 7.x (.NET), and -<filename>.dsw</filename> when using earlier versions of Visual Studio. -</para> </summary> </cvar> <cvar name="SCONS_HOME"> <summary> <para>The -(optional) path to the SCons library directory, initialized from the external -environment. If set, this is used to construct a shorter and more efficient -search path in the &cv-link-MSVSSCONS; command line executed from Microsoft -Visual Studio project files. </para> </summary> </cvar></sconsdoc> + <literal>SccAuxPath</literal> attribute if the + <envar>MSVS_SCC_PROVIDER</envar> construction variable is + also set. There is +no default value. + + </para> + </summary> + </cvar> <cvar name="MSVS_SCC_CONNECTION_ROOT"> + <summary> + <para> + The root path of projects in your SCC workspace, i.e the + path under which all project and solution files will be + generated. It is used as a reference path from which the + relative paths of the generated Microsoft Visual Studio project + and solution files are computed. The relative project file path + is placed as the value of the <literal>SccLocalPath</literal> + attribute of the project file and as the values of the + <literal>SccProjectFilePathRelativizedFromConnection[i]</literal> + (where [i] ranges from 0 to the number of projects in the solution) + attributes of the <literal>GlobalSection(SourceCodeControl)</literal> + section of the Microsoft Visual Studio solution file. Similarly + the relative solution file path is placed as the values of the + <literal>SccLocalPath[i]</literal> (where [i] ranges from 0 + to the number of projects in the solution) attributes of the + <literal>GlobalSection(SourceCodeControl)</literal> section of + the Microsoft Visual Studio solution file. This is used only if + the <envar>MSVS_SCC_PROVIDER</envar> construction variable is + also set. The default value is the current working directory. + </para> + </summary> + </cvar> <cvar name="MSVS_SCC_PROJECT_NAME"> + <summary> + <para> + The project name placed in a generated Microsoft + Visual Studio project file as the value of the + <literal>SccProjectName</literal> attribute if the + <envar>MSVS_SCC_PROVIDER</envar> construction variable + is also set. In this case the string is also placed in + the <literal>SccProjectName0</literal> attribute of the + <literal>GlobalSection(SourceCodeControl)</literal> section + of the Microsoft Visual Studio solution file. There is no + default value. + </para> + </summary> + </cvar> <cvar name="MSVS_SCC_PROVIDER"> + <summary> + <para> + The string placed in a generated Microsoft + Visual Studio project file as the value of the + <literal>SccProvider</literal> attribute. The string is + also placed in the <literal>SccProvider0</literal> attribute + of the <literal>GlobalSection(SourceCodeControl)</literal> + section of the Microsoft Visual Studio solution file. There + is no default value. + </para> + </summary> + </cvar> <cvar name="MSVS_VERSION"> + <summary> + <para>Sets the preferred version of Microsoft Visual Studio to use.</para> + <para> + If &cv-MSVS_VERSION; is not set, &SCons; will (by default) + select the latest version of Visual Studio installed on your + system. So, if you have version 6 and version 7 (MSVS .NET) + installed, it will prefer version 7. You can override this by + specifying the <envar>MSVS_VERSION</envar> variable in the + Environment initialization, setting it to the appropriate + version ('6.0' or '7.0', for example). If the specified + version isn't installed, tool initialization will fail. + </para> + <para> + This is obsolete: use &cv-MSVC_VERSION; instead. If + &cv-MSVS_VERSION; is set and &cv-MSVC_VERSION; is + not, &cv-MSVC_VERSION; will be set automatically to + &cv-MSVS_VERSION;. If both are set to different values, + scons will raise an error. + </para> + </summary> + </cvar> + <cvar name="MSVSBUILDCOM"> + <summary> + <para> + The build command line placed in a generated Microsoft Visual + Studio project file. The default is to have Visual Studio + invoke SCons with any specified build targets. + </para> + </summary> + </cvar> + <cvar name="MSVSCLEANCOM"> + <summary> + <para> + The clean command line placed in a generated Microsoft Visual + Studio project file. The default is to have Visual Studio + invoke SCons with the -c option to remove any specified + targets. + </para> + </summary> + </cvar> <cvar name="MSVSENCODING"> + <summary> + <para> + The encoding string placed in a generated Microsoft + Visual Studio project file. The default is encoding + <literal>Windows-1252</literal>. + </para> + </summary> + </cvar> + <cvar name="MSVSPROJECTCOM"> + <summary> + <para>The action used to generate Microsoft Visual Studio project files.</para> + </summary> + </cvar> + <cvar name="MSVSPROJECTSUFFIX"> + <summary> + <para> + The suffix used for Microsoft Visual Studio project (DSP) + files. The default value is <filename>.vcproj</filename> + when using Visual Studio version 7.x (.NET) or later version, + and <filename>.dsp</filename> when using earlier versions of + Visual Studio. + </para> + </summary> + </cvar> + <cvar name="MSVSREBUILDCOM"> + <summary> + <para> + The rebuild command line placed in a generated Microsoft + Visual Studio project file. The default is to have Visual + Studio invoke SCons with any specified rebuild targets. + + </para> + </summary> + </cvar> + <cvar name="MSVSSCONS"> + <summary> + <para> + The SCons used in generated Microsoft Visual Studio project + files. The default is the version of SCons being used to + generate the project file. + </para> + </summary> + </cvar> + <cvar name="MSVSSCONSFLAGS"> + <summary> + <para> + The SCons flags used in generated Microsoft Visual Studio project files. + </para> + </summary> + </cvar> + <cvar name="MSVSSCONSCOM"> + <summary> + <para> + The default SCons command used in generated Microsoft Visual + Studio project files. + </para> + </summary> + </cvar> + <cvar name="MSVSSCONSCRIPT"> + <summary> + <para> + The sconscript file (that is, &SConstruct; or &SConscript; + file) that will be invoked by Visual Studio project files + (through the &cv-link-MSVSSCONSCOM; variable). The default + is the same sconscript file that contains the call to + &b-MSVSProject; to build the project file. + </para> + </summary> + </cvar> + <cvar name="MSVSSOLUTIONCOM"> + <summary> + <para>The action used to generate Microsoft Visual Studio solution files.</para> + </summary> + </cvar> <cvar name="MSVSSOLUTIONSUFFIX"> + <summary> + <para> + The suffix used for Microsoft Visual Studio solution (DSW) + files. The default value is <filename>.sln</filename> + when using Visual Studio version 7.x (.NET), and + <filename>.dsw</filename> when using earlier versions of + Visual Studio. + </para> + </summary> + </cvar> + <cvar name="SCONS_HOME"> + <summary> + <para> + The (optional) path to the SCons library directory, + initialized from the external environment. If set, this is + used to construct a shorter and more efficient search path in + the &cv-link-MSVSSCONS; command line executed from Microsoft + Visual Studio project files. + </para> + </summary> + </cvar> +</sconsdoc> diff --git a/src/engine/SCons/Tool/msvsTests.py b/src/engine/SCons/Tool/msvsTests.py index 8c09487..fd5e343 100644 --- a/src/engine/SCons/Tool/msvsTests.py +++ b/src/engine/SCons/Tool/msvsTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/msvsTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/msvsTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import sys @@ -482,8 +482,8 @@ class DummyRegistry(object): def parse(self, data): parents = [None, None] parents[0] = self.root - keymatch = re.compile('^\[(.*)\]$') - valmatch = re.compile('^(?:"(.*)"|[@])="(.*)"$') + keymatch = re.compile(r'^\[(.*)\]$') + valmatch = re.compile(r'^(?:"(.*)"|[@])="(.*)"$') for line in data: m1 = keymatch.match(line) if m1: @@ -540,6 +540,10 @@ def DummyQueryValue(key, value): def DummyExists(path): return 1 +def DummyVsWhere(msvc_version): + # not testing versions with vswhere, so return none + return None + class msvsTestCase(unittest.TestCase): """This test case is run several times with different defaults. See its subclasses below.""" @@ -809,6 +813,7 @@ if __name__ == "__main__": SCons.Util.RegEnumKey = DummyEnumKey SCons.Util.RegEnumValue = DummyEnumValue SCons.Util.RegQueryValueEx = DummyQueryValue + SCons.Tool.MSCommon.vc.find_vc_pdir_vswhere = DummyVsWhere os.path.exists = DummyExists # make sure all files exist :-) os.path.isfile = DummyExists # make sure all files are files :-) diff --git a/src/engine/SCons/Tool/mwcc.py b/src/engine/SCons/Tool/mwcc.py index 566f812..5cad127 100644 --- a/src/engine/SCons/Tool/mwcc.py +++ b/src/engine/SCons/Tool/mwcc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mwcc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mwcc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path diff --git a/src/engine/SCons/Tool/mwcc.xml b/src/engine/SCons/Tool/mwcc.xml index 39e6dfa..e9f210c 100644 --- a/src/engine/SCons/Tool/mwcc.xml +++ b/src/engine/SCons/Tool/mwcc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/mwld.py b/src/engine/SCons/Tool/mwld.py index 9abeeb5..7d7341a 100644 --- a/src/engine/SCons/Tool/mwld.py +++ b/src/engine/SCons/Tool/mwld.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/mwld.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/mwld.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Tool diff --git a/src/engine/SCons/Tool/mwld.xml b/src/engine/SCons/Tool/mwld.xml index 993fefe..261a039 100644 --- a/src/engine/SCons/Tool/mwld.xml +++ b/src/engine/SCons/Tool/mwld.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/nasm.py b/src/engine/SCons/Tool/nasm.py index c605cc6..8871ab6 100644 --- a/src/engine/SCons/Tool/nasm.py +++ b/src/engine/SCons/Tool/nasm.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/nasm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/nasm.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/nasm.xml b/src/engine/SCons/Tool/nasm.xml index 1834b34..6626411 100644 --- a/src/engine/SCons/Tool/nasm.xml +++ b/src/engine/SCons/Tool/nasm.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/packaging.xml b/src/engine/SCons/Tool/packaging.xml index ea39115..9b46000 100644 --- a/src/engine/SCons/Tool/packaging.xml +++ b/src/engine/SCons/Tool/packaging.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/packaging/__init__.py b/src/engine/SCons/Tool/packaging/__init__.py index b844afb..513e672 100644 --- a/src/engine/SCons/Tool/packaging/__init__.py +++ b/src/engine/SCons/Tool/packaging/__init__.py @@ -4,7 +4,7 @@ SCons Packaging Tool. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,18 +25,23 @@ SCons Packaging Tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/packaging/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" +import SCons.Defaults import SCons.Environment from SCons.Variables import * from SCons.Errors import * from SCons.Util import is_List, make_path_relative from SCons.Warnings import warn, Warning -import os, imp -import SCons.Defaults +import os +import imp -__all__ = [ 'src_targz', 'src_tarbz2', 'src_zip', 'tarbz2', 'targz', 'zip', 'rpm', 'msi', 'ipk' ] +__all__ = [ + 'src_targz', 'src_tarbz2', 'src_xz', 'src_zip', + 'targz', 'tarbz2', 'xz', 'zip', + 'rpm', 'msi', 'ipk', +] # # Utility and Builder function @@ -102,7 +107,7 @@ def Package(env, target=None, source=None, **kw): from SCons.Script import GetOption kw['PACKAGETYPE'] = GetOption('package_type') - if kw['PACKAGETYPE'] == None: + if kw['PACKAGETYPE'] is None: if 'Tar' in env['BUILDERS']: kw['PACKAGETYPE']='targz' elif 'Zip' in env['BUILDERS']: @@ -163,15 +168,22 @@ def Package(env, target=None, source=None, **kw): # this exception means that a needed argument for the packager is # missing. As our packagers get their "tags" as named function # arguments we need to find out which one is missing. - from inspect import getargspec - args,varargs,varkw,defaults=getargspec(packager.package) - if defaults!=None: - args=args[:-len(defaults)] # throw away arguments with default values + #TODO: getargspec deprecated in Py3. cleanup when Py2.7 dropped. + try: + from inspect import getfullargspec + argspec = getfullargspec(packager.package) + except ImportError: + from inspect import getargspec + argspec = getargspec(packager.package) + args = argspec.args + if argspec.defaults: + # throw away arguments with default values + args = args[:-len(argspec.defaults)] args.remove('env') args.remove('target') args.remove('source') # now remove any args for which we have a value in kw. - args=[x for x in args if x not in kw] + args = [x for x in args if x not in kw] if len(args)==0: raise # must be a different error, so re-raise @@ -283,10 +295,9 @@ def stripinstallbuilder(target, source, env): It also warns about files which have no install builder attached. """ def has_no_install_location(file): - return not (file.has_builder() and\ - hasattr(file.builder, 'name') and\ - (file.builder.name=="InstallBuilder" or\ - file.builder.name=="InstallAsBuilder")) + return not (file.has_builder() and hasattr(file.builder, 'name') + and file.builder.name in ["InstallBuilder", "InstallAsBuilder"]) + if len([src for src in source if has_no_install_location(src)]): warn(Warning, "there are files to package which have no\ diff --git a/src/engine/SCons/Tool/packaging/__init__.xml b/src/engine/SCons/Tool/packaging/__init__.xml index 0ee0f6b..1643def 100644 --- a/src/engine/SCons/Tool/packaging/__init__.xml +++ b/src/engine/SCons/Tool/packaging/__init__.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -64,13 +64,15 @@ the following packagers available: <para> * msi - Microsoft Installer - * rpm - Redhat Package Manger + * rpm - RPM Package Manger * ipkg - Itsy Package Management System - * tarbz2 - compressed tar - * targz - compressed tar + * tarbz2 - bzip2 compressed tar + * targz - gzip compressed tar + * tarxz - xz compressed tar * zip - zip file - * src_tarbz2 - compressed tar source - * src_targz - compressed tar source + * src_tarbz2 - bzip2 compressed tar source + * src_targz - gzip compressed tar source + * src_tarxz - xz compressed tar source * src_zip - zip file source </para> @@ -106,7 +108,9 @@ This is used to fill in the <literal>Architecture:</literal> field in an Ipkg <filename>control</filename> file, -and as part of the name of a generated RPM file. +and the <literal>BuildArch:</literal> field +in the RPM <filename>.spec</filename> file, +as well as forming part of the name of a generated RPM package file. </para> </summary> </cvar> @@ -120,7 +124,6 @@ the <filename>control</filename> for Ipkg, the <filename>.wxs</filename> for MSI). If set, the function will be called after the SCons template for the file has been written. -XXX </para> </summary> </cvar> @@ -164,10 +167,10 @@ section of an RPM <cvar name="LICENSE"> <summary> <para> -The abbreviated name of the license under which -this project is released (gpl, lpgl, bsd etc.). +The abbreviated name, preferably the SPDX code, of the license under which +this project is released (GPL-3.0, LGPL-2.1, BSD-2-Clause etc.). See http://www.opensource.org/licenses/alphabetical -for a list of license names. +for a list of license names and SPDX codes. </para> </summary> </cvar> @@ -383,6 +386,7 @@ This is used to fill in the <literal>BuildRequires:</literal> field in the RPM <filename>.spec</filename> file. +Note this should only be used on a host managed by rpm as the dependencies will not be resolvable at build time otherwise. </para> </summary> </cvar> @@ -441,7 +445,8 @@ field in the RPM <para> This is used to fill in the <literal>Epoch:</literal> -field in the controlling information for RPM packages. +field in the RPM +<filename>.spec</filename> file. </para> </summary> </cvar> @@ -468,6 +473,38 @@ field in the RPM </summary> </cvar> +<cvar name="X_RPM_EXTRADEFS"> +<summary> +<para> +A list used to supply extra defintions or flags +to be added to the RPM <filename>.spec</filename> file. +Each item is added as-is with a carriage return appended. +This is useful if some specific RPM feature not otherwise +anticipated by SCons needs to be turned on or off. +Note if this variable is omitted, SCons will by +default supply the value +<literal>'%global debug_package %{nil}'</literal> +to disable debug package generation. +To enable debug package generation, include this +variable set either to None, or to a custom +list that does not include the default line. +Added in version 3.1. +</para> + +<example_commands> +env.Package( + NAME = 'foo', +... + X_RPM_EXTRADEFS = [ + '%define _unpackaged_files_terminate_build 0' + '%define _missing_doc_files_terminate_build 0' + ], +... ) +</example_commands> + +</summary> +</cvar> + <cvar name="X_RPM_GROUP"> <summary> <para> diff --git a/src/engine/SCons/Tool/packaging/ipk.py b/src/engine/SCons/Tool/packaging/ipk.py index 71fa2b0..60cd3cb 100644 --- a/src/engine/SCons/Tool/packaging/ipk.py +++ b/src/engine/SCons/Tool/packaging/ipk.py @@ -2,7 +2,7 @@ """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,11 +24,13 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/ipk.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/ipk.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" + +import os import SCons.Builder import SCons.Node.FS -import os +import SCons.Util from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot @@ -119,7 +121,9 @@ def build_specfiles(source, target, env): try: return opened_files[needle] except KeyError: - file=filter(lambda x: x.get_path().rfind(needle)!=-1, haystack)[0] + files = filter(lambda x: x.get_path().rfind(needle) != -1, haystack) + # Py3: filter returns an iterable, not a list + file = list(files)[0] opened_files[needle]=open(file.get_abspath(), 'w') return opened_files[needle] diff --git a/src/engine/SCons/Tool/packaging/msi.py b/src/engine/SCons/Tool/packaging/msi.py index 827ce76..4e8724b 100644 --- a/src/engine/SCons/Tool/packaging/msi.py +++ b/src/engine/SCons/Tool/packaging/msi.py @@ -4,7 +4,7 @@ The msi packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,7 +25,7 @@ The msi packager. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/packaging/msi.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/msi.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import SCons @@ -63,8 +63,8 @@ def convert_to_id(s, id_set): """ charset = 'ABCDEFGHIJKLMNOPQRSTUVWXYabcdefghijklmnopqrstuvwxyz0123456789_.' if s[0] in '0123456789.': - s += '_'+s - id = [c for c in s if c in charset] + s = '_' + s + id = ''.join([c for c in s if c in charset]) # did we already generate an id for this file? try: @@ -108,14 +108,13 @@ def gen_dos_short_file_name(file, filename_set): # strip forbidden characters. forbidden = '."/[]:;=, ' - fname = [c for c in fname if c not in forbidden] + fname = ''.join([c for c in fname if c not in forbidden]) # check if we already generated a filename with the same number: # thisis1.txt, thisis2.txt etc. duplicate, num = not None, 1 while duplicate: - shortname = "%s%s" % (fname[:8-len(str(num))].upper(),\ - str(num)) + shortname = "%s%s" % (fname[:8-len(str(num))].upper(), str(num)) if len(ext) >= 2: shortname = "%s%s" % (shortname, ext[:4].upper()) @@ -301,7 +300,7 @@ def build_wxsfile_file_section(root, files, NAME, VERSION, VENDOR, filename_set, if c.nodeName == 'Directory' and c.attributes['LongName'].value == escape(d)] - if already_created != []: + if already_created: Directory = already_created[0] dir_parts.remove(d) upper_dir += d diff --git a/src/engine/SCons/Tool/packaging/rpm.py b/src/engine/SCons/Tool/packaging/rpm.py index 3c48b02..48b9aab 100644 --- a/src/engine/SCons/Tool/packaging/rpm.py +++ b/src/engine/SCons/Tool/packaging/rpm.py @@ -4,7 +4,7 @@ The rpm packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,7 +25,7 @@ The rpm packager. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/packaging/rpm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/rpm.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os @@ -51,10 +51,9 @@ def package(env, target, source, PACKAGEROOT, NAME, VERSION, if str(target[0])!="%s-%s"%(NAME, VERSION): raise UserError( "Setting target is not supported for rpm." ) else: - # This should be overridable from the construction environment, - # which it is by using ARCHITECTURE=. + # Deduce the build architecture, but allow it to be overridden + # by setting ARCHITECTURE in the construction env. buildarchitecture = SCons.Tool.rpmutils.defaultMachine() - if 'ARCHITECTURE' in kw: buildarchitecture = kw['ARCHITECTURE'] @@ -126,20 +125,18 @@ def build_specfile(target, source, env): """ Builds a RPM specfile from a dictionary with string metadata and by analyzing a tree of nodes. """ - file = open(target[0].get_abspath(), 'w') - - try: - file.write( build_specfile_header(env) ) - file.write( build_specfile_sections(env) ) - file.write( build_specfile_filesection(env, source) ) - file.close() + with open(target[0].get_abspath(), 'w') as file: + try: + file.write(build_specfile_header(env)) + file.write(build_specfile_sections(env)) + file.write(build_specfile_filesection(env, source)) - # call a user specified function - if 'CHANGE_SPECFILE' in env: - env['CHANGE_SPECFILE'](target, source) + # call a user specified function + if 'CHANGE_SPECFILE' in env: + env['CHANGE_SPECFILE'](target, source) - except KeyError as e: - raise SCons.Errors.UserError( '"%s" package field for RPM is missing.' % e.args[0] ) + except KeyError as e: + raise SCons.Errors.UserError('"%s" package field for RPM is missing.' % e.args[0]) # @@ -201,7 +198,8 @@ def build_specfile_header(spec): 'PACKAGEVERSION' : '%%define release %s\nRelease: %%{release}\n', 'X_RPM_GROUP' : 'Group: %s\n', 'SUMMARY' : 'Summary: %s\n', - 'LICENSE' : 'License: %s\n', } + 'LICENSE' : 'License: %s\n', + } str = str + SimpleTagCompiler(mandatory_header_fields).compile( spec ) @@ -211,6 +209,7 @@ def build_specfile_header(spec): 'X_RPM_URL' : 'Url: %s\n', 'SOURCE_URL' : 'Source: %s\n', 'SUMMARY_' : 'Summary(%s): %s\n', + 'ARCHITECTURE' : 'BuildArch: %s\n', 'X_RPM_DISTRIBUTION' : 'Distribution: %s\n', 'X_RPM_ICON' : 'Icon: %s\n', 'X_RPM_PACKAGER' : 'Packager: %s\n', @@ -229,19 +228,33 @@ def build_specfile_header(spec): 'X_RPM_PREFIX' : 'Prefix: %s\n', # internal use - 'X_RPM_BUILDROOT' : 'BuildRoot: %s\n', } + 'X_RPM_BUILDROOT' : 'BuildRoot: %s\n', + } # fill in default values: - # Adding a BuildRequires renders the .rpm unbuildable under System, which + # Adding a BuildRequires renders the .rpm unbuildable under systems which # are not managed by rpm, since the database to resolve this dependency is # missing (take Gentoo as an example) -# if not s.has_key('x_rpm_BuildRequires'): -# s['x_rpm_BuildRequires'] = 'scons' + #if 'X_RPM_BUILDREQUIRES' not in spec: + # spec['X_RPM_BUILDREQUIRES'] = 'scons' if 'X_RPM_BUILDROOT' not in spec: spec['X_RPM_BUILDROOT'] = '%{_tmppath}/%{name}-%{version}-%{release}' str = str + SimpleTagCompiler(optional_header_fields, mandatory=0).compile( spec ) + + # Add any extra specfile definitions the user may have supplied. + # These flags get no processing, they are just added. + # github #3164: if we don't turn off debug package generation + # the tests which build packages all fail. If there are no + # extra flags, default to adding this one. If the user wants + # to turn this back on, supply the flag set to None. + + if 'X_RPM_EXTRADEFS' not in spec: + spec['X_RPM_EXTRADEFS'] = ['%global debug_package %{nil}'] + for extra in spec['X_RPM_EXTRADEFS']: + str += extra + '\n' + return str # diff --git a/src/engine/SCons/Tool/packaging/src_tarbz2.py b/src/engine/SCons/Tool/packaging/src_tarbz2.py index b40e550..473ce75 100644 --- a/src/engine/SCons/Tool/packaging/src_tarbz2.py +++ b/src/engine/SCons/Tool/packaging/src_tarbz2.py @@ -1,10 +1,10 @@ -"""SCons.Tool.Packaging.tarbz2 +"""SCons.Tool.Packaging.src_tarbz2 The tarbz2 SRC packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The tarbz2 SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/src_tarbz2.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/src_tarbz2.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from SCons.Tool.packaging import putintopackageroot diff --git a/src/engine/SCons/Tool/packaging/src_targz.py b/src/engine/SCons/Tool/packaging/src_targz.py index 01fc91a..865b8dd 100644 --- a/src/engine/SCons/Tool/packaging/src_targz.py +++ b/src/engine/SCons/Tool/packaging/src_targz.py @@ -1,10 +1,10 @@ -"""SCons.Tool.Packaging.targz +"""SCons.Tool.Packaging.src_targz The targz SRC packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The targz SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/src_targz.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/src_targz.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from SCons.Tool.packaging import putintopackageroot diff --git a/src/engine/SCons/Options/EnumOption.py b/src/engine/SCons/Tool/packaging/src_tarxz.py index 5e030d9..07ffdb0 100644 --- a/src/engine/SCons/Options/EnumOption.py +++ b/src/engine/SCons/Tool/packaging/src_tarxz.py @@ -1,5 +1,10 @@ +"""SCons.Tool.Packaging.src_tarxz + +The tarxz SRC packager. +""" + # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,27 +26,15 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Options/EnumOption.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" - -__doc__ = """Place-holder for the old SCons.Options module hierarchy - -This is for backwards compatibility. The new equivalent is the Variables/ -class hierarchy. These will have deprecation warnings added (some day), -and will then be removed entirely (some day). -""" - -import SCons.Variables -import SCons.Warnings +__revision__ = "src/engine/SCons/Tool/packaging/src_tarxz.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -warned = False +from SCons.Tool.packaging import putintopackageroot -def EnumOption(*args, **kw): - global warned - if not warned: - msg = "The EnumOption() function is deprecated; use the EnumVariable() function instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) - warned = True - return SCons.Variables.EnumVariable(*args, **kw) +def package(env, target, source, PACKAGEROOT, **kw): + bld = env['BUILDERS']['Tar'] + bld.set_suffix('.tar.xz') + target, source = putintopackageroot(target, source, env, PACKAGEROOT, honor_install_location=0) + return bld(env, target, source, TARFLAGS='-Jc') # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/packaging/src_zip.py b/src/engine/SCons/Tool/packaging/src_zip.py index ea21a87..819e52a 100644 --- a/src/engine/SCons/Tool/packaging/src_zip.py +++ b/src/engine/SCons/Tool/packaging/src_zip.py @@ -4,7 +4,7 @@ The zip SRC packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The zip SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/src_zip.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/src_zip.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from SCons.Tool.packaging import putintopackageroot diff --git a/src/engine/SCons/Tool/packaging/tarbz2.py b/src/engine/SCons/Tool/packaging/tarbz2.py index c919cab..5658de3 100644 --- a/src/engine/SCons/Tool/packaging/tarbz2.py +++ b/src/engine/SCons/Tool/packaging/tarbz2.py @@ -1,10 +1,10 @@ """SCons.Tool.Packaging.tarbz2 -The tarbz2 SRC packager. +The tarbz2 packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,13 +26,13 @@ The tarbz2 SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/tarbz2.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/tarbz2.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot def package(env, target, source, PACKAGEROOT, **kw): bld = env['BUILDERS']['Tar'] - bld.set_suffix('.tar.gz') + bld.set_suffix('.tar.bz2') target, source = putintopackageroot(target, source, env, PACKAGEROOT) target, source = stripinstallbuilder(target, source, env) return bld(env, target, source, TARFLAGS='-jc') diff --git a/src/engine/SCons/Tool/packaging/targz.py b/src/engine/SCons/Tool/packaging/targz.py index e9e984e..f515f1e 100644 --- a/src/engine/SCons/Tool/packaging/targz.py +++ b/src/engine/SCons/Tool/packaging/targz.py @@ -1,10 +1,10 @@ """SCons.Tool.Packaging.targz -The targz SRC packager. +The targz packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The targz SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/targz.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/targz.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot diff --git a/src/engine/SCons/Options/ListOption.py b/src/engine/SCons/Tool/packaging/tarxz.py index d4e63af..5f7a8d8 100644 --- a/src/engine/SCons/Options/ListOption.py +++ b/src/engine/SCons/Tool/packaging/tarxz.py @@ -1,5 +1,10 @@ +"""SCons.Tool.Packaging.tarxz + +The tarxz packager. +""" + # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,27 +26,16 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Options/ListOption.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" - -__doc__ = """Place-holder for the old SCons.Options module hierarchy - -This is for backwards compatibility. The new equivalent is the Variables/ -class hierarchy. These will have deprecation warnings added (some day), -and will then be removed entirely (some day). -""" - -import SCons.Variables -import SCons.Warnings +__revision__ = "src/engine/SCons/Tool/packaging/tarxz.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -warned = False +from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot -def ListOption(*args, **kw): - global warned - if not warned: - msg = "The ListOption() function is deprecated; use the ListVariable() function instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedOptionsWarning, msg) - warned = True - return SCons.Variables.ListVariable(*args, **kw) +def package(env, target, source, PACKAGEROOT, **kw): + bld = env['BUILDERS']['Tar'] + bld.set_suffix('.tar.xz') + target, source = putintopackageroot(target, source, env, PACKAGEROOT) + target, source = stripinstallbuilder(target, source, env) + return bld(env, target, source, TARFLAGS='-Jc') # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/packaging/zip.py b/src/engine/SCons/Tool/packaging/zip.py index 3b80ead..2ae496e 100644 --- a/src/engine/SCons/Tool/packaging/zip.py +++ b/src/engine/SCons/Tool/packaging/zip.py @@ -4,7 +4,7 @@ The zip SRC packager. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,7 +26,7 @@ The zip SRC packager. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/packaging/zip.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/packaging/zip.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from SCons.Tool.packaging import stripinstallbuilder, putintopackageroot diff --git a/src/engine/SCons/Tool/pdf.py b/src/engine/SCons/Tool/pdf.py index 381732a..da970ff 100644 --- a/src/engine/SCons/Tool/pdf.py +++ b/src/engine/SCons/Tool/pdf.py @@ -6,7 +6,7 @@ Add an explicit action to run epstopdf to convert .eps files to .pdf """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -28,7 +28,7 @@ Add an explicit action to run epstopdf to convert .eps files to .pdf # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/pdf.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/pdf.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Builder import SCons.Tool diff --git a/src/engine/SCons/Tool/pdf.xml b/src/engine/SCons/Tool/pdf.xml index 9688a6f..876de15 100644 --- a/src/engine/SCons/Tool/pdf.xml +++ b/src/engine/SCons/Tool/pdf.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/pdflatex.py b/src/engine/SCons/Tool/pdflatex.py index d539770..2a97d0f 100644 --- a/src/engine/SCons/Tool/pdflatex.py +++ b/src/engine/SCons/Tool/pdflatex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/pdflatex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/pdflatex.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Action import SCons.Util diff --git a/src/engine/SCons/Tool/pdflatex.xml b/src/engine/SCons/Tool/pdflatex.xml index 4dae90b..975d5e9 100644 --- a/src/engine/SCons/Tool/pdflatex.xml +++ b/src/engine/SCons/Tool/pdflatex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/pdftex.py b/src/engine/SCons/Tool/pdftex.py index 06e9d7c..80913ae 100644 --- a/src/engine/SCons/Tool/pdftex.py +++ b/src/engine/SCons/Tool/pdftex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/pdftex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/pdftex.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import SCons.Action diff --git a/src/engine/SCons/Tool/pdftex.xml b/src/engine/SCons/Tool/pdftex.xml index e84296a..0a265e7 100644 --- a/src/engine/SCons/Tool/pdftex.xml +++ b/src/engine/SCons/Tool/pdftex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/qt.py b/src/engine/SCons/Tool/qt.py index e7c1b95..e8b0325 100644 --- a/src/engine/SCons/Tool/qt.py +++ b/src/engine/SCons/Tool/qt.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,10 +33,11 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/qt.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/qt.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import re +import glob import SCons.Action import SCons.Builder @@ -44,6 +45,8 @@ import SCons.Defaults import SCons.Scanner import SCons.Tool import SCons.Util +import SCons.Tool.cxx +cplusplus = SCons.Tool.cxx class ToolQtWarning(SCons.Warnings.Warning): pass @@ -60,12 +63,33 @@ header_extensions = [".h", ".hxx", ".hpp", ".hh"] if SCons.Util.case_sensitive_suffixes('.h', '.H'): header_extensions.append('.H') -import SCons.Tool.cxx -cplusplus = SCons.Tool.cxx -#cplusplus = __import__('cxx', globals(), locals(), []) - cxx_suffixes = cplusplus.CXXSuffixes + +# +def find_platform_specific_qt_paths(): + """ + If the platform has non-standard paths which it installs QT in,return the likely default path + :return: + """ + + # qt_bin_dirs = [] + qt_bin_dir = None + if os.path.isfile('/etc/redhat-release'): + with open('/etc/redhat-release','r') as rr: + lines = rr.readlines() + distro = lines[0].split()[0] + if distro == 'CentOS': + # Centos installs QT under /usr/{lib,lib64}/qt{4,5,-3.3}/bin + # so we need to handle this differently + # qt_bin_dirs = glob.glob('/usr/lib64/qt*/bin') + qt_bin_dir = '/usr/lib64/qt-3.3/bin' + + return qt_bin_dir + + +QT_BIN_DIR = find_platform_specific_qt_paths() + def checkMocIncluded(target, source, env): moc = target[0] cpp = source[0] @@ -188,13 +212,12 @@ AutomocStatic = _Automoc('StaticObject') def _detect(env): """Not really safe, but fast method to detect the QT library""" - QTDIR = None - if not QTDIR: - QTDIR = env.get('QTDIR',None) + + QTDIR = env.get('QTDIR',None) if not QTDIR: QTDIR = os.environ.get('QTDIR',None) if not QTDIR: - moc = env.WhereIs('moc') + moc = env.WhereIs('moc') or env.WhereIs('moc',QT_BIN_DIR) if moc: QTDIR = os.path.dirname(os.path.dirname(moc)) SCons.Warnings.warn( diff --git a/src/engine/SCons/Tool/qt.xml b/src/engine/SCons/Tool/qt.xml index 86d50d6..560a11d 100644 --- a/src/engine/SCons/Tool/qt.xml +++ b/src/engine/SCons/Tool/qt.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/rmic.py b/src/engine/SCons/Tool/rmic.py index 9e1eaee..1d401fd 100644 --- a/src/engine/SCons/Tool/rmic.py +++ b/src/engine/SCons/Tool/rmic.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/rmic.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rmic.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path @@ -40,6 +40,9 @@ import SCons.Builder import SCons.Node.FS import SCons.Util +from SCons.Tool.JavaCommon import get_java_install_dirs + + def emit_rmic_classes(target, source, env): """Create and return lists of Java RMI stub and skeleton class files to be created from a set of class files. @@ -105,6 +108,18 @@ def generate(env): """Add Builders and construction variables for rmic to an Environment.""" env['BUILDERS']['RMIC'] = RMICBuilder + if env['PLATFORM'] == 'win32': + version = env.get('JAVAVERSION', None) + default_paths=get_java_install_dirs(env['PLATFORM'], version=version) + + # Ensure that we have a proper path for rmic + rmic = SCons.Tool.find_program_path(env, 'rmic', default_paths=default_paths) + + # print("RMIC: %s"%rmic) + if rmic: + rmic_bin_dir = os.path.dirname(rmic) + env.AppendENVPath('PATH', rmic_bin_dir) + env['RMIC'] = 'rmic' env['RMICFLAGS'] = SCons.Util.CLVar('') env['RMICCOM'] = '$RMIC $RMICFLAGS -d ${TARGET.attributes.java_lookupdir} -classpath ${SOURCE.attributes.java_classdir} ${SOURCES.attributes.java_classname}' diff --git a/src/engine/SCons/Tool/rmic.xml b/src/engine/SCons/Tool/rmic.xml index 2b0d42b..2a273d3 100644 --- a/src/engine/SCons/Tool/rmic.xml +++ b/src/engine/SCons/Tool/rmic.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/rpcgen.py b/src/engine/SCons/Tool/rpcgen.py index 1f2c66d..349af6a 100644 --- a/src/engine/SCons/Tool/rpcgen.py +++ b/src/engine/SCons/Tool/rpcgen.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/rpcgen.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rpcgen.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from SCons.Builder import Builder import SCons.Util @@ -43,7 +43,7 @@ rpcgen_service = cmd % ('m', '$RPCGENSERVICEFLAGS') rpcgen_xdr = cmd % ('c', '$RPCGENXDRFLAGS') def generate(env): - "Add RPCGEN Builders and construction variables for an Environment." + """Add RPCGEN Builders and construction variables for an Environment.""" client = Builder(action=rpcgen_client, suffix='_clnt.c', src_suffix='.x') header = Builder(action=rpcgen_header, suffix='.h', src_suffix='.x') diff --git a/src/engine/SCons/Tool/rpcgen.xml b/src/engine/SCons/Tool/rpcgen.xml index 60f216e..1ee9df9 100644 --- a/src/engine/SCons/Tool/rpcgen.xml +++ b/src/engine/SCons/Tool/rpcgen.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/rpm.py b/src/engine/SCons/Tool/rpm.py index 5cd97b3..61e4185 100644 --- a/src/engine/SCons/Tool/rpm.py +++ b/src/engine/SCons/Tool/rpm.py @@ -11,7 +11,7 @@ tar.gz consisting of the source file and a specfile. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ tar.gz consisting of the source file and a specfile. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/rpm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rpm.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import re diff --git a/src/engine/SCons/Tool/rpmutils.py b/src/engine/SCons/Tool/rpmutils.py index f71d664..10bb28d 100644 --- a/src/engine/SCons/Tool/rpmutils.py +++ b/src/engine/SCons/Tool/rpmutils.py @@ -14,7 +14,7 @@ exact syntax. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -36,7 +36,7 @@ exact syntax. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/rpmutils.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/rpmutils.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import platform diff --git a/src/engine/SCons/Tool/sgiar.py b/src/engine/SCons/Tool/sgiar.py index a421cc1..152afd4 100644 --- a/src/engine/SCons/Tool/sgiar.py +++ b/src/engine/SCons/Tool/sgiar.py @@ -11,7 +11,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgiar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgiar.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/sgiar.xml b/src/engine/SCons/Tool/sgiar.xml index ffbc80e..6d28475 100644 --- a/src/engine/SCons/Tool/sgiar.xml +++ b/src/engine/SCons/Tool/sgiar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sgic++.py b/src/engine/SCons/Tool/sgic++.py index 7a9b1e9..35f913f 100644 --- a/src/engine/SCons/Tool/sgic++.py +++ b/src/engine/SCons/Tool/sgic++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgic++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgic++.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" #forward proxy to the preffered cxx version from SCons.Tool.sgicxx import * diff --git a/src/engine/SCons/Tool/sgic++.xml b/src/engine/SCons/Tool/sgic++.xml index 03ca3b1..bab0392 100644 --- a/src/engine/SCons/Tool/sgic++.xml +++ b/src/engine/SCons/Tool/sgic++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sgicc.py b/src/engine/SCons/Tool/sgicc.py index e9f561d..c5461e3 100644 --- a/src/engine/SCons/Tool/sgicc.py +++ b/src/engine/SCons/Tool/sgicc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgicc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgicc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" from . import cc diff --git a/src/engine/SCons/Tool/sgicc.xml b/src/engine/SCons/Tool/sgicc.xml index 1e12bf3..f26944b 100644 --- a/src/engine/SCons/Tool/sgicc.xml +++ b/src/engine/SCons/Tool/sgicc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sgicxx.py b/src/engine/SCons/Tool/sgicxx.py index 61c415b..7656939 100644 --- a/src/engine/SCons/Tool/sgicxx.py +++ b/src/engine/SCons/Tool/sgicxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgicxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgicxx.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util diff --git a/src/engine/SCons/Tool/sgilink.py b/src/engine/SCons/Tool/sgilink.py index c327151..366b227 100644 --- a/src/engine/SCons/Tool/sgilink.py +++ b/src/engine/SCons/Tool/sgilink.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sgilink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sgilink.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util diff --git a/src/engine/SCons/Tool/sgilink.xml b/src/engine/SCons/Tool/sgilink.xml index ede0eed..7cc9818 100644 --- a/src/engine/SCons/Tool/sgilink.xml +++ b/src/engine/SCons/Tool/sgilink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunar.py b/src/engine/SCons/Tool/sunar.py index cd1e18d..6745511 100644 --- a/src/engine/SCons/Tool/sunar.py +++ b/src/engine/SCons/Tool/sunar.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunar.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Defaults import SCons.Tool diff --git a/src/engine/SCons/Tool/sunar.xml b/src/engine/SCons/Tool/sunar.xml index b97e6a2..97d1a05 100644 --- a/src/engine/SCons/Tool/sunar.xml +++ b/src/engine/SCons/Tool/sunar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunc++.py b/src/engine/SCons/Tool/sunc++.py index 1219bcf..f1bbf14 100644 --- a/src/engine/SCons/Tool/sunc++.py +++ b/src/engine/SCons/Tool/sunc++.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunc++.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunc++.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" #forward proxy to the preffered cxx version diff --git a/src/engine/SCons/Tool/sunc++.xml b/src/engine/SCons/Tool/sunc++.xml index 2e7b220..d1d0160 100644 --- a/src/engine/SCons/Tool/sunc++.xml +++ b/src/engine/SCons/Tool/sunc++.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/suncc.py b/src/engine/SCons/Tool/suncc.py index bc4eb4f..49cfa70 100644 --- a/src/engine/SCons/Tool/suncc.py +++ b/src/engine/SCons/Tool/suncc.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/suncc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/suncc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util diff --git a/src/engine/SCons/Tool/suncc.xml b/src/engine/SCons/Tool/suncc.xml index 61cfb30..f191eda 100644 --- a/src/engine/SCons/Tool/suncc.xml +++ b/src/engine/SCons/Tool/suncc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/suncxx.py b/src/engine/SCons/Tool/suncxx.py index 1545500..1fa5331 100644 --- a/src/engine/SCons/Tool/suncxx.py +++ b/src/engine/SCons/Tool/suncxx.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/suncxx.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/suncxx.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons diff --git a/src/engine/SCons/Tool/sunf77.py b/src/engine/SCons/Tool/sunf77.py index 9842d31..1d9487d 100644 --- a/src/engine/SCons/Tool/sunf77.py +++ b/src/engine/SCons/Tool/sunf77.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunf77.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunf77.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util diff --git a/src/engine/SCons/Tool/sunf77.xml b/src/engine/SCons/Tool/sunf77.xml index 8f6ecaf..fafcb8d 100644 --- a/src/engine/SCons/Tool/sunf77.xml +++ b/src/engine/SCons/Tool/sunf77.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunf90.py b/src/engine/SCons/Tool/sunf90.py index 7245f99..4de62c3 100644 --- a/src/engine/SCons/Tool/sunf90.py +++ b/src/engine/SCons/Tool/sunf90.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunf90.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunf90.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util diff --git a/src/engine/SCons/Tool/sunf90.xml b/src/engine/SCons/Tool/sunf90.xml index 8f151fe..f979e15 100644 --- a/src/engine/SCons/Tool/sunf90.xml +++ b/src/engine/SCons/Tool/sunf90.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunf95.py b/src/engine/SCons/Tool/sunf95.py index aae8828..6d1ccf6 100644 --- a/src/engine/SCons/Tool/sunf95.py +++ b/src/engine/SCons/Tool/sunf95.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunf95.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunf95.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Util diff --git a/src/engine/SCons/Tool/sunf95.xml b/src/engine/SCons/Tool/sunf95.xml index a2c77da..4072d36 100644 --- a/src/engine/SCons/Tool/sunf95.xml +++ b/src/engine/SCons/Tool/sunf95.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/sunlink.py b/src/engine/SCons/Tool/sunlink.py index 175157f..1eca1b2 100644 --- a/src/engine/SCons/Tool/sunlink.py +++ b/src/engine/SCons/Tool/sunlink.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/sunlink.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/sunlink.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path diff --git a/src/engine/SCons/Tool/sunlink.xml b/src/engine/SCons/Tool/sunlink.xml index b652f5c..68eee54 100644 --- a/src/engine/SCons/Tool/sunlink.xml +++ b/src/engine/SCons/Tool/sunlink.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/swig.py b/src/engine/SCons/Tool/swig.py index dedf103..a207a89 100644 --- a/src/engine/SCons/Tool/swig.py +++ b/src/engine/SCons/Tool/swig.py @@ -10,7 +10,7 @@ selection method. from __future__ import print_function # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,9 +32,10 @@ from __future__ import print_function # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/swig.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/swig.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path +import sys import re import subprocess @@ -69,7 +70,9 @@ def _find_modules(src): directors = 0 mnames = [] try: - matches = _reModule.findall(open(src).read()) + with open(src) as f: + data = f.read() + matches = _reModule.findall(data) except IOError: # If the file's not yet generated, guess the module name from the file stem matches = [] @@ -134,21 +137,31 @@ def _swigEmitter(target, source, env): def _get_swig_version(env, swig): """Run the SWIG command line tool to get and return the version number""" + version = None swig = env.subst(swig) + if not swig: + return version pipe = SCons.Action._subproc(env, SCons.Util.CLVar(swig) + ['-version'], stdin = 'devnull', stderr = 'devnull', stdout = subprocess.PIPE) - if pipe.wait() != 0: return + if pipe.wait() != 0: + return version # MAYBE: out = SCons.Util.to_str (pipe.stdout.read()) - out = SCons.Util.to_str(pipe.stdout.read()) - match = re.search('SWIG Version\s+(\S+).*', out, re.MULTILINE) + with pipe.stdout: + out = SCons.Util.to_str(pipe.stdout.read()) + + match = re.search(r'SWIG Version\s+(\S+).*', out, re.MULTILINE) if match: - if verbose: print("Version is:%s"%match.group(1)) - return match.group(1) + version = match.group(1) + if verbose: + print("Version is: %s" % version) else: - if verbose: print("Unable to detect version: [%s]"%out) + if verbose: + print("Unable to detect version: [%s]" % out) + + return version def generate(env): """Add Builders and construction variables for swig to an Environment.""" @@ -169,6 +182,17 @@ def generate(env): java_file.add_action('.i', SwigAction) java_file.add_emitter('.i', _swigEmitter) + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + + if sys.platform == 'win32': + swig = SCons.Tool.find_program_path(env, 'swig', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS + [r'C:\ProgramData\chocolatey\bin'] ) + if swig: + swig_bin_dir = os.path.dirname(swig) + env.AppendENVPath('PATH', swig_bin_dir) + else: + SCons.Warnings.Warning('swig tool requested, but binary not found in ENV PATH') + if 'SWIG' not in env: env['SWIG'] = env.Detect(swigs) or swigs[0] env['SWIGVERSION'] = _get_swig_version(env, env['SWIG']) diff --git a/src/engine/SCons/Tool/swig.xml b/src/engine/SCons/Tool/swig.xml index 53d92ef..65a5971 100644 --- a/src/engine/SCons/Tool/swig.xml +++ b/src/engine/SCons/Tool/swig.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -153,7 +153,8 @@ An automatically-generated construction variable containing the SWIG command-line options for specifying directories to be searched for included files. The value of &cv-_SWIGINCFLAGS; is created -by appending &cv-SWIGINCPREFIX; and &cv-SWIGINCSUFFIX; +by respectively prepending and appending +&cv-SWIGINCPREFIX; and &cv-SWIGINCSUFFIX; to the beginning and end of each directory in &cv-SWIGPATH;. </para> @@ -164,7 +165,7 @@ of each directory in &cv-SWIGPATH;. <summary> <para> The prefix used to specify an include directory on the SWIG command line. -This will be appended to the beginning of each directory +This will be prepended to the beginning of each directory in the &cv-SWIGPATH; construction variable when the &cv-_SWIGINCFLAGS; variable is automatically generated. </para> @@ -238,7 +239,7 @@ through the automatically-generated &cv-_SWIGINCFLAGS; construction variable, which is constructed by -appending the values of the +respectively prepending and appending the values of the &cv-SWIGINCPREFIX; and &cv-SWIGINCSUFFIX; construction variables to the beginning and end diff --git a/src/engine/SCons/Tool/tar.py b/src/engine/SCons/Tool/tar.py index 77392ae..ac4f7f7 100644 --- a/src/engine/SCons/Tool/tar.py +++ b/src/engine/SCons/Tool/tar.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/tar.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/tar.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Action import SCons.Builder diff --git a/src/engine/SCons/Tool/tar.xml b/src/engine/SCons/Tool/tar.xml index 637b7db..95e8418 100644 --- a/src/engine/SCons/Tool/tar.xml +++ b/src/engine/SCons/Tool/tar.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/tex.py b/src/engine/SCons/Tool/tex.py index 990c9fa..2fecd1d 100644 --- a/src/engine/SCons/Tool/tex.py +++ b/src/engine/SCons/Tool/tex.py @@ -10,7 +10,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -33,7 +33,7 @@ selection method. # from __future__ import print_function -__revision__ = "src/engine/SCons/Tool/tex.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/tex.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import re @@ -74,15 +74,15 @@ openout_bcf_re = re.compile(r"OUTPUT *(.*\.bcf)") #printglossary_re = re.compile(r"^[^%]*\\printglossary", re.MULTILINE) # search to find rerun warnings -warning_rerun_str = '(^LaTeX Warning:.*Rerun)|(^Package \w+ Warning:.*Rerun)' +warning_rerun_str = r'(^LaTeX Warning:.*Rerun)|(^Package \w+ Warning:.*Rerun)' warning_rerun_re = re.compile(warning_rerun_str, re.MULTILINE) # search to find citation rerun warnings -rerun_citations_str = "^LaTeX Warning:.*\n.*Rerun to get citations correct" +rerun_citations_str = r"^LaTeX Warning:.*\n.*Rerun to get citations correct" rerun_citations_re = re.compile(rerun_citations_str, re.MULTILINE) # search to find undefined references or citations warnings -undefined_references_str = '(^LaTeX Warning:.*undefined references)|(^Package \w+ Warning:.*undefined citations)' +undefined_references_str = r'(^LaTeX Warning:.*undefined references)|(^Package \w+ Warning:.*undefined citations)' undefined_references_re = re.compile(undefined_references_str, re.MULTILINE) # used by the emitter @@ -297,7 +297,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None logfilename = targetbase + '.log' logContent = '' if os.path.isfile(logfilename): - logContent = open(logfilename, "r").read() + with open(logfilename, "r") as f: + logContent = f.read() # Read the fls file to find all .aux files @@ -305,7 +306,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None flsContent = '' auxfiles = [] if os.path.isfile(flsfilename): - flsContent = open(flsfilename, "r").read() + with open(flsfilename, "r") as f: + flsContent = f.read() auxfiles = openout_aux_re.findall(flsContent) # remove duplicates dups = {} @@ -315,7 +317,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None bcffiles = [] if os.path.isfile(flsfilename): - flsContent = open(flsfilename, "r").read() + with open(flsfilename, "r") as f: + flsContent = f.read() bcffiles = openout_bcf_re.findall(flsContent) # remove duplicates dups = {} @@ -338,7 +341,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None already_bibtexed.append(auxfilename) target_aux = os.path.join(targetdir, auxfilename) if os.path.isfile(target_aux): - content = open(target_aux, "r").read() + with open(target_aux, "r") as f: + content = f.read() if content.find("bibdata") != -1: if Verbose: print("Need to run bibtex on ",auxfilename) @@ -361,7 +365,8 @@ def InternalLaTeXAuxAction(XXXLaTeXAction, target = None, source= None, env=None already_bibtexed.append(bcffilename) target_bcf = os.path.join(targetdir, bcffilename) if os.path.isfile(target_bcf): - content = open(target_bcf, "r").read() + with open(target_bcf, "r") as f: + content = f.read() if content.find("bibdata") != -1: if Verbose: print("Need to run biber on ",bcffilename) @@ -647,7 +652,7 @@ def ScanFiles(theFile, target, paths, file_tests, file_tests_search, env, graphi if incResult: aux_files.append(os.path.join(targetdir, incResult.group(1))) if Verbose: - print("\include file names : ", aux_files) + print(r"\include file names : ", aux_files) # recursively call this on each of the included files inc_files = [ ] inc_files.extend( include_re.findall(content) ) @@ -790,7 +795,7 @@ def tex_emitter_core(target, source, env, graphics_extensions): for multibibmatch in multibib_re.finditer(content): if Verbose: print("multibib match ",multibibmatch.group(1)) - if multibibmatch != None: + if multibibmatch is not None: baselist = multibibmatch.group(1).split(',') if Verbose: print("multibib list ", baselist) @@ -813,7 +818,8 @@ def tex_emitter_core(target, source, env, graphics_extensions): # read fls file to get all other files that latex creates and will read on the next pass # remove files from list that we explicitly dealt with above if os.path.isfile(flsfilename): - content = open(flsfilename, "r").read() + with open(flsfilename, "r") as f: + content = f.read() out_files = openout_re.findall(content) myfiles = [auxfilename, logfilename, flsfilename, targetbase+'.dvi',targetbase+'.pdf'] for filename in out_files[:]: diff --git a/src/engine/SCons/Tool/tex.xml b/src/engine/SCons/Tool/tex.xml index 87741c0..c293977 100644 --- a/src/engine/SCons/Tool/tex.xml +++ b/src/engine/SCons/Tool/tex.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/textfile.py b/src/engine/SCons/Tool/textfile.py index 7303e06..bbbde9f 100644 --- a/src/engine/SCons/Tool/textfile.py +++ b/src/engine/SCons/Tool/textfile.py @@ -1,6 +1,6 @@ # -*- python -*- # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -44,7 +44,7 @@ Textfile/Substfile builder for SCons. is unpredictable whether the expansion will occur. """ -__revision__ = "src/engine/SCons/Tool/textfile.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/textfile.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons diff --git a/src/engine/SCons/Tool/textfile.xml b/src/engine/SCons/Tool/textfile.xml index bca7232..31d2d4f 100644 --- a/src/engine/SCons/Tool/textfile.xml +++ b/src/engine/SCons/Tool/textfile.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. @@ -147,7 +147,7 @@ and the result replaces the key. </para> <example_commands> -env = Environment(tools = ['default', 'textfile']) +env = Environment(tools=['default']) env['prefix'] = '/usr/bin' script_dict = {'@prefix@': '/bin', '@exec_prefix@': '$prefix'} @@ -174,7 +174,7 @@ env.Substfile('bar.in', SUBST_DICT = good_bar) # the SUBST_DICT may be in common (and not an override) substutions = {} -subst = Environment(tools = ['textfile'], SUBST_DICT = substitutions) +subst = Environment(tools=['textfile'], SUBST_DICT=substitutions) substitutions['@foo@'] = 'foo' subst['SUBST_DICT']['@bar@'] = 'bar' subst.Substfile('pgm1.c', [Value('#include "@foo@.h"'), diff --git a/src/engine/SCons/Tool/tlib.py b/src/engine/SCons/Tool/tlib.py index c0a755e..e1483a2 100644 --- a/src/engine/SCons/Tool/tlib.py +++ b/src/engine/SCons/Tool/tlib.py @@ -5,7 +5,7 @@ XXX """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ XXX # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/tlib.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/tlib.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Tool import SCons.Tool.bcc32 diff --git a/src/engine/SCons/Tool/tlib.xml b/src/engine/SCons/Tool/tlib.xml index cb15db3..2fd8c08 100644 --- a/src/engine/SCons/Tool/tlib.xml +++ b/src/engine/SCons/Tool/tlib.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/wix.py b/src/engine/SCons/Tool/wix.py index 3ddfa84..bba033e 100644 --- a/src/engine/SCons/Tool/wix.py +++ b/src/engine/SCons/Tool/wix.py @@ -8,7 +8,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/wix.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/wix.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.Builder import SCons.Action diff --git a/src/engine/SCons/Tool/wixTests.py b/src/engine/SCons/Tool/wixTests.py index 965ca57..c1812a2 100644 --- a/src/engine/SCons/Tool/wixTests.py +++ b/src/engine/SCons/Tool/wixTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/wixTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/wixTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import unittest import os.path @@ -33,7 +33,6 @@ from SCons.Tool.wix import * from SCons.Environment import Environment import TestCmd -import TestUnit # create fake candle and light, so the tool's exists() method will succeed @@ -53,8 +52,7 @@ class WixTestCase(unittest.TestCase): assert env.subst('$WIXSRCSUF') == '.wxs' if __name__ == "__main__": - suite = unittest.makeSuite(WixTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Tool/xgettext.py b/src/engine/SCons/Tool/xgettext.py index 2e2934b..3f11357 100644 --- a/src/engine/SCons/Tool/xgettext.py +++ b/src/engine/SCons/Tool/xgettext.py @@ -3,7 +3,7 @@ Tool specific initialization of `xgettext` tool. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Tool specific initialization of `xgettext` tool. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Tool/xgettext.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/xgettext.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" ############################################################################# @@ -288,9 +288,21 @@ def _POTUpdateBuilder(env, **kw): ############################################################################# def generate(env, **kw): """ Generate `xgettext` tool """ + import sys + import os import SCons.Util + import SCons.Tool from SCons.Tool.GettextCommon import RPaths, _detect_xgettext - + from SCons.Platform.mingw import MINGW_DEFAULT_PATHS + from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS + + if sys.platform == 'win32': + xgettext = SCons.Tool.find_program_path(env, 'xgettext', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if xgettext: + xgettext_bin_dir = os.path.dirname(xgettext) + env.AppendENVPath('PATH', xgettext_bin_dir) + else: + SCons.Warnings.Warning('xgettext tool requested, but binary not found in ENV PATH') try: env['XGETTEXT'] = _detect_xgettext(env) except: diff --git a/src/engine/SCons/Tool/xgettext.xml b/src/engine/SCons/Tool/xgettext.xml index 0b68c14..079693f 100644 --- a/src/engine/SCons/Tool/xgettext.xml +++ b/src/engine/SCons/Tool/xgettext.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/yacc.py b/src/engine/SCons/Tool/yacc.py index 4f9fbc2..d397de1 100644 --- a/src/engine/SCons/Tool/yacc.py +++ b/src/engine/SCons/Tool/yacc.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,13 +31,17 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/yacc.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/yacc.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path +import sys import SCons.Defaults import SCons.Tool import SCons.Util +from SCons.Platform.mingw import MINGW_DEFAULT_PATHS +from SCons.Platform.cygwin import CYGWIN_DEFAULT_PATHS +from SCons.Platform.win32 import CHOCO_DEFAULT_PATH YaccAction = SCons.Action.Action("$YACCCOM", "$YACCCOMSTR") @@ -94,6 +98,28 @@ def ymEmitter(target, source, env): def yyEmitter(target, source, env): return _yaccEmitter(target, source, env, ['.yy'], '$YACCHXXFILESUFFIX') +def get_yacc_path(env, append_paths=False): + """ + Find the a path containing the lex or flex binaries. If a construction + environment is passed in then append the path to the ENV PATH. + """ + # save existing path to reset if we don't want to append any paths + envPath = env['ENV']['PATH'] + bins = ['bison', 'yacc', 'win_bison'] + + for prog in bins: + bin_path = SCons.Tool.find_program_path( + env, + prog, + default_paths=CHOCO_DEFAULT_PATH + MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if bin_path: + if not append_paths: + env['ENV']['PATH'] = envPath + else: + env.AppendENVPath('PATH', os.path.dirname(bin_path)) + return bin_path + SCons.Warnings.Warning('lex tool requested, but lex or flex binary not found in ENV PATH') + def generate(env): """Add Builders and construction variables for yacc to an Environment.""" c_file, cxx_file = SCons.Tool.createCFileBuilders(env) @@ -113,7 +139,20 @@ def generate(env): cxx_file.add_action('.yy', YaccAction) cxx_file.add_emitter('.yy', yyEmitter) - env['YACC'] = env.Detect('bison') or 'yacc' + if sys.platform == 'win32': + bison = SCons.Tool.find_program_path(env, 'bison', default_paths=MINGW_DEFAULT_PATHS + CYGWIN_DEFAULT_PATHS ) + if bison: + bison_bin_dir = os.path.dirname(bison) + env.AppendENVPath('PATH', bison_bin_dir) + else: + SCons.Warnings.Warning('yacc tool requested, but bison binary not found in ENV PATH') + + if sys.platform == 'win32': + get_yacc_path(env, append_paths=True) + env["YACC"] = env.Detect(['bison', 'yacc', 'win_bison']) + else: + env["YACC"] = env.Detect(["bison", "yacc"]) + env['YACCFLAGS'] = SCons.Util.CLVar('') env['YACCCOM'] = '$YACC $YACCFLAGS -o $TARGET $SOURCES' env['YACCHFILESUFFIX'] = '.h' diff --git a/src/engine/SCons/Tool/yacc.xml b/src/engine/SCons/Tool/yacc.xml index 6bdbd53..8ba3658 100644 --- a/src/engine/SCons/Tool/yacc.xml +++ b/src/engine/SCons/Tool/yacc.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Tool/zip.py b/src/engine/SCons/Tool/zip.py index 0f6a8dd..55792c2 100644 --- a/src/engine/SCons/Tool/zip.py +++ b/src/engine/SCons/Tool/zip.py @@ -9,7 +9,7 @@ selection method. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Tool/zip.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Tool/zip.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path diff --git a/src/engine/SCons/Tool/zip.xml b/src/engine/SCons/Tool/zip.xml index 82eb61a..d7622dd 100644 --- a/src/engine/SCons/Tool/zip.xml +++ b/src/engine/SCons/Tool/zip.xml @@ -1,6 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <!-- -Copyright (c) 2001 - 2017 The SCons Foundation +Copyright (c) 2001 - 2019 The SCons Foundation This file is processed by the bin/SConsDoc.py module. See its __doc__ string for a discussion of the format. diff --git a/src/engine/SCons/Util.py b/src/engine/SCons/Util.py index 2a1604b..f2498e9 100644 --- a/src/engine/SCons/Util.py +++ b/src/engine/SCons/Util.py @@ -3,7 +3,7 @@ Various utility functions go here. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -24,7 +24,7 @@ Various utility functions go here. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Util.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Util.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import sys @@ -37,21 +37,18 @@ import pprint PY3 = sys.version_info[0] == 3 try: + from collections import UserDict, UserList, UserString +except ImportError: from UserDict import UserDict -except ImportError as e: - from collections import UserDict - -try: from UserList import UserList -except ImportError as e: - from collections import UserList - -from collections import Iterable + from UserString import UserString try: - from UserString import UserString -except ImportError as e: - from collections import UserString + from collections.abc import Iterable, MappingView +except ImportError: + from collections import Iterable + +from collections import OrderedDict # Don't "from types import ..." these because we need to get at the # types module later to look for UnicodeType. @@ -63,7 +60,7 @@ MethodType = types.MethodType FunctionType = types.FunctionType try: - unicode + _ = type(unicode) except NameError: UnicodeType = str else: @@ -106,7 +103,7 @@ def containsOnly(str, set): return 1 def splitext(path): - "Same as os.path.splitext() but faster." + """Same as os.path.splitext() but faster.""" sep = rightmost_separator(path, os.sep) dot = path.rfind('.') # An ext is only real if it has at least one non-digit char @@ -371,7 +368,13 @@ def print_tree(root, child_func, prune=0, showtags=0, margin=[0], visited=None): DictTypes = (dict, UserDict) ListTypes = (list, UserList) -SequenceTypes = (list, tuple, UserList) + +try: + # Handle getting dictionary views. + SequenceTypes = (list, tuple, UserList, MappingView) +except NameError: + SequenceTypes = (list, tuple, UserList) + # Note that profiling data shows a speed-up when comparing # explicitly with str and unicode instead of simply comparing @@ -481,10 +484,7 @@ def to_String_for_subst(s, if isinstance(s, BaseStringTypes): return s elif isinstance(s, SequenceTypes): - l = [] - for e in s: - l.append(to_String_for_subst(e)) - return ' '.join( s ) + 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. @@ -1032,64 +1032,9 @@ class CLVar(UserList): return UserList.__add__(self, CLVar(other)) def __radd__(self, other): return UserList.__radd__(self, CLVar(other)) - def __coerce__(self, other): - return (self, CLVar(other)) def __str__(self): return ' '.join(self.data) -# A dictionary that preserves the order in which items are added. -# Submitted by David Benjamin to ActiveState's Python Cookbook web site: -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/107747 -# Including fixes/enhancements from the follow-on discussions. -class OrderedDict(UserDict): - def __init__(self, dict = None): - self._keys = [] - UserDict.__init__(self, dict) - - def __delitem__(self, key): - UserDict.__delitem__(self, key) - self._keys.remove(key) - - def __setitem__(self, key, item): - UserDict.__setitem__(self, key, item) - if key not in self._keys: self._keys.append(key) - - def clear(self): - UserDict.clear(self) - self._keys = [] - - def copy(self): - dict = OrderedDict() - dict.update(self) - return dict - - def items(self): - return list(zip(self._keys, list(self.values()))) - - def keys(self): - return self._keys[:] - - def popitem(self): - try: - key = self._keys[-1] - except IndexError: - raise KeyError('dictionary is empty') - - val = self[key] - del self[key] - - return (key, val) - - def setdefault(self, key, failobj = None): - UserDict.setdefault(self, key, failobj) - if key not in self._keys: self._keys.append(key) - - def update(self, dict): - for (key, val) in dict.items(): - self.__setitem__(key, val) - - def values(self): - return list(map(self.get, self._keys)) class Selector(OrderedDict): """A callable ordered dictionary that maps file suffixes to @@ -1431,8 +1376,8 @@ def make_path_relative(path): # The original idea for AddMethod() and RenameFunction() come from the # following post to the ActiveState Python Cookbook: # -# ASPN: Python Cookbook : Install bound methods in an instance -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/223613 +# ASPN: Python Cookbook : Install bound methods in an instance +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/223613 # # That code was a little fragile, though, so the following changes # have been wrung on it: @@ -1449,8 +1394,8 @@ def make_path_relative(path): # the "new" module, as alluded to in Alex Martelli's response to the # following Cookbook post: # -# ASPN: Python Cookbook : Dynamically added methods to a class -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732 +# ASPN: Python Cookbook : Dynamically added methods to a class +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732 def AddMethod(obj, function, name=None): """ @@ -1520,6 +1465,11 @@ else: md5 = True def MD5signature(s): + """ + Generate a String of Hex digits representing the md5 signature of the string + :param s: either string or bytes. Normally should be bytes + :return: String of hex digits + """ m = hashlib.md5() try: @@ -1530,6 +1480,11 @@ else: return m.hexdigest() def MD5filesignature(fname, chunksize=65536): + """ + :param fname: + :param chunksize: + :return: String of Hex digits + """ m = hashlib.md5() f = open(fname, "rb") while True: @@ -1540,6 +1495,7 @@ else: f.close() return m.hexdigest() + def MD5collect(signatures): """ Collects a list of signatures into an aggregate signature. @@ -1612,16 +1568,66 @@ class NullSeq(Null): del __revision__ -def to_bytes (s): + +def to_bytes(s): + if s is None: + return b'None' + if not PY3 and isinstance(s, UnicodeType): + # PY2, must encode unicode + return bytearray(s, 'utf-8') if isinstance (s, (bytes, bytearray)) or bytes is str: + # Above case not covered here as py2 bytes and strings are the same return s - return bytes (s, 'utf-8') + return bytes(s, 'utf-8') + -def to_str (s): +def to_str(s): + if s is None: + return 'None' if bytes is str or is_String(s): return s return str (s, 'utf-8') + +def cmp(a, b): + """ + Define cmp because it's no longer available in python3 + Works under python 2 as well + """ + return (a > b) - (a < b) + + +def get_env_bool(env, name, default=False): + """Get a value of env[name] converted to boolean. The value of env[name] is + interpreted as follows: 'true', 'yes', 'y', 'on' (case insensitive) and + anything convertible to int that yields non-zero integer are True values; + '0', 'false', 'no', 'n' and 'off' (case insensitive) are False values. For + all other cases, default value is returned. + + :Parameters: + - `env` - dict or dict-like object, a convainer with variables + - `name` - name of the variable in env to be returned + - `default` - returned when env[name] does not exist or can't be converted to bool + """ + try: + var = env[name] + except KeyError: + return default + try: + return bool(int(var)) + except ValueError: + if str(var).lower() in ('true', 'yes', 'y', 'on'): + return True + elif str(var).lower() in ('false', 'no', 'n', 'off'): + return False + else: + return default + + +def get_os_env_bool(name, default=False): + """Same as get_env_bool(os.environ, name, default).""" + return get_env_bool(os.environ, name, default) + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/src/engine/SCons/UtilTests.py b/src/engine/SCons/UtilTests.py index 1df4069..c33a1fe 100644 --- a/src/engine/SCons/UtilTests.py +++ b/src/engine/SCons/UtilTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/UtilTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/UtilTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import SCons.compat @@ -32,15 +32,18 @@ import unittest from collections import UserDict, UserList, UserString import TestCmd -import TestUnit import SCons.Errors from SCons.Util import * -try: eval('unicode') -except NameError: HasUnicode = False -else: HasUnicode = True +try: + eval('unicode') +except NameError: + HasUnicode = False +else: + HasUnicode = True + class OutBuffer(object): def __init__(self): @@ -49,47 +52,59 @@ class OutBuffer(object): def write(self, str): self.buffer = self.buffer + str + class dictifyTestCase(unittest.TestCase): def test_dictify(self): """Test the dictify() function""" r = SCons.Util.dictify(['a', 'b', 'c'], [1, 2, 3]) - assert r == {'a':1, 'b':2, 'c':3}, r + assert r == {'a': 1, 'b': 2, 'c': 3}, r r = {} SCons.Util.dictify(['a'], [1], r) SCons.Util.dictify(['b'], [2], r) SCons.Util.dictify(['c'], [3], r) - assert r == {'a':1, 'b':2, 'c':3}, r + assert r == {'a': 1, 'b': 2, 'c': 3}, r + class UtilTestCase(unittest.TestCase): def test_splitext(self): - assert splitext('foo') == ('foo','') - assert splitext('foo.bar') == ('foo','.bar') - assert splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'),'') + assert splitext('foo') == ('foo', '') + assert splitext('foo.bar') == ('foo', '.bar') + assert splitext(os.path.join('foo.bar', 'blat')) == (os.path.join('foo.bar', 'blat'), '') class Node(object): def __init__(self, name, children=[]): self.children = children self.name = name self.nocache = None + def __str__(self): return self.name + def exists(self): return 1 + def rexists(self): return 1 + def has_builder(self): return 1 + def has_explicit_builder(self): return 1 + def side_effect(self): return 1 + def precious(self): return 1 + def always_build(self): return 1 + def is_up_to_date(self): return 1 + def noclean(self): return 1 @@ -116,7 +131,7 @@ class UtilTestCase(unittest.TestCase): """ lines = expect.split('\n')[:-1] - lines = ['[E BSPACN ]'+l for l in lines] + lines = ['[E BSPACN ]' + l for l in lines] withtags = '\n'.join(lines) + '\n' return foo, expect, withtags @@ -151,13 +166,14 @@ class UtilTestCase(unittest.TestCase): """ lines = expect.split('\n')[:-1] - lines = ['[E BSPACN ]'+l for l in lines] + lines = ['[E BSPACN ]' + l for l in lines] withtags = '\n'.join(lines) + '\n' return blat_o, expect, withtags def test_render_tree(self): """Test the render_tree() function""" + def get_children(node): return node.children @@ -178,6 +194,7 @@ class UtilTestCase(unittest.TestCase): def test_print_tree(self): """Test the print_tree() function""" + def get_children(node): return node.children @@ -244,7 +261,7 @@ class UtilTestCase(unittest.TestCase): assert is_Dict(UserDict()) # os.environ is not a dictionary in python 3 - if sys.version_info < (3,0): + if sys.version_info < (3, 0): assert is_Dict(os.environ) try: @@ -307,37 +324,49 @@ class UtilTestCase(unittest.TestCase): if HasUnicode: exec("assert not is_Tuple(u'')") + def test_to_Bytes(self): + """ Test the to_Bytes method""" + if not PY3: + self.assertEqual(to_bytes(UnicodeType('Hello')), + bytearray(u'Hello', 'utf-8'), + "Check that to_bytes creates byte array when presented with unicode string. PY2 only") + def test_to_String(self): """Test the to_String() method.""" assert to_String(1) == "1", to_String(1) - assert to_String([ 1, 2, 3]) == str([1, 2, 3]), to_String([1,2,3]) + assert to_String([1, 2, 3]) == str([1, 2, 3]), to_String([1, 2, 3]) assert to_String("foo") == "foo", to_String("foo") + assert to_String(None) == 'None' + # test low level string converters too + assert to_str(None) == 'None' + assert to_bytes(None) == b'None' - s1=UserString('blah') + s1 = UserString('blah') assert to_String(s1) == s1, s1 assert to_String(s1) == 'blah', s1 class Derived(UserString): pass + s2 = Derived('foo') assert to_String(s2) == s2, s2 assert to_String(s2) == 'foo', s2 if HasUnicode: - s3=UserString(unicode('bar')) + s3 = UserString(unicode('bar')) assert to_String(s3) == s3, s3 assert to_String(s3) == unicode('bar'), s3 assert isinstance(to_String(s3), unicode), \ - type(to_String(s3)) + type(to_String(s3)) if HasUnicode: s4 = unicode('baz') assert to_String(s4) == unicode('baz'), to_String(s4) assert isinstance(to_String(s4), unicode), \ - type(to_String(s4)) + type(to_String(s4)) def test_WhereIs(self): - test = TestCmd.TestCmd(workdir = '') + test = TestCmd.TestCmd(workdir='') sub1_xxx_exe = test.workpath('sub1', 'xxx.exe') sub2_xxx_exe = test.workpath('sub2', 'xxx.exe') @@ -360,17 +389,17 @@ class UtilTestCase(unittest.TestCase): env_path = os.environ['PATH'] try: - pathdirs_1234 = [ test.workpath('sub1'), - test.workpath('sub2'), - test.workpath('sub3'), - test.workpath('sub4'), - ] + env_path.split(os.pathsep) - - pathdirs_1243 = [ test.workpath('sub1'), - test.workpath('sub2'), - test.workpath('sub4'), - test.workpath('sub3'), - ] + env_path.split(os.pathsep) + pathdirs_1234 = [test.workpath('sub1'), + test.workpath('sub2'), + test.workpath('sub3'), + test.workpath('sub4'), + ] + env_path.split(os.pathsep) + + pathdirs_1243 = [test.workpath('sub1'), + test.workpath('sub2'), + test.workpath('sub4'), + test.workpath('sub3'), + ] + env_path.split(os.pathsep) os.environ['PATH'] = os.pathsep.join(pathdirs_1234) wi = WhereIs('xxx.exe') @@ -380,9 +409,9 @@ class UtilTestCase(unittest.TestCase): wi = WhereIs('xxx.exe', os.pathsep.join(pathdirs_1243)) assert wi == test.workpath(sub4_xxx_exe), wi - wi = WhereIs('xxx.exe',reject = sub3_xxx_exe) + wi = WhereIs('xxx.exe', reject=sub3_xxx_exe) assert wi == test.workpath(sub4_xxx_exe), wi - wi = WhereIs('xxx.exe', pathdirs_1243, reject = sub3_xxx_exe) + wi = WhereIs('xxx.exe', pathdirs_1243, reject=sub3_xxx_exe) assert wi == test.workpath(sub4_xxx_exe), wi os.environ['PATH'] = os.pathsep.join(pathdirs_1243) @@ -394,19 +423,19 @@ class UtilTestCase(unittest.TestCase): assert wi == test.workpath(sub3_xxx_exe), wi if sys.platform == 'win32': - wi = WhereIs('xxx', pathext = '') + wi = WhereIs('xxx', pathext='') assert wi is None, wi - wi = WhereIs('xxx', pathext = '.exe') + wi = WhereIs('xxx', pathext='.exe') assert wi == test.workpath(sub4_xxx_exe), wi - wi = WhereIs('xxx', path = pathdirs_1234, pathext = '.BAT;.EXE') + wi = WhereIs('xxx', path=pathdirs_1234, pathext='.BAT;.EXE') assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi # Test that we return a normalized path even when # the path contains forward slashes. forward_slash = test.workpath('') + '/sub3' - wi = WhereIs('xxx', path = forward_slash, pathext = '.EXE') + wi = WhereIs('xxx', path=forward_slash, pathext='.EXE') assert wi.lower() == test.workpath(sub3_xxx_exe).lower(), wi del os.environ['PATH'] @@ -426,24 +455,27 @@ class UtilTestCase(unittest.TestCase): assert get_environment_var("$BAR ") == None, get_environment_var("$BAR ") assert get_environment_var("FOO$BAR") == None, get_environment_var("FOO$BAR") assert get_environment_var("$FOO[0]") == None, get_environment_var("$FOO[0]") - assert get_environment_var("${some('complex expression')}") == None, get_environment_var("${some('complex expression')}") + assert get_environment_var("${some('complex expression')}") == None, get_environment_var( + "${some('complex expression')}") def test_Proxy(self): """Test generic Proxy class.""" + class Subject(object): def foo(self): return 1 + def bar(self): return 2 - s=Subject() + s = Subject() s.baz = 3 class ProxyTest(Proxy): def bar(self): return 4 - p=ProxyTest(s) + p = ProxyTest(s) assert p.foo() == 1, p.foo() assert p.bar() == 4, p.bar() @@ -477,8 +509,10 @@ class UtilTestCase(unittest.TestCase): filename = tempfile.mktemp() str = '1234567890 ' + filename try: - open(filename, 'w').write(str) - assert open(get_native_path(filename)).read() == str + with open(filename, 'w') as f: + f.write(str) + with open(get_native_path(filename)) as f: + assert f.read() == str finally: try: os.unlink(filename) @@ -490,49 +524,49 @@ class UtilTestCase(unittest.TestCase): p1 = r'C:\dir\num\one;C:\dir\num\two' p2 = r'C:\mydir\num\one;C:\mydir\num\two' # have to include the pathsep here so that the test will work on UNIX too. - p1 = PrependPath(p1,r'C:\dir\num\two',sep = ';') - p1 = PrependPath(p1,r'C:\dir\num\three',sep = ';') - p2 = PrependPath(p2,r'C:\mydir\num\three',sep = ';') - p2 = PrependPath(p2,r'C:\mydir\num\one',sep = ';') - assert(p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one') - assert(p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two') + p1 = PrependPath(p1, r'C:\dir\num\two', sep=';') + p1 = PrependPath(p1, r'C:\dir\num\three', sep=';') + p2 = PrependPath(p2, r'C:\mydir\num\three', sep=';') + p2 = PrependPath(p2, r'C:\mydir\num\one', sep=';') + assert (p1 == r'C:\dir\num\three;C:\dir\num\two;C:\dir\num\one') + assert (p2 == r'C:\mydir\num\one;C:\mydir\num\three;C:\mydir\num\two') def test_AppendPath(self): """Test appending to a path.""" p1 = r'C:\dir\num\one;C:\dir\num\two' p2 = r'C:\mydir\num\one;C:\mydir\num\two' # have to include the pathsep here so that the test will work on UNIX too. - p1 = AppendPath(p1,r'C:\dir\num\two',sep = ';') - p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';') - p2 = AppendPath(p2,r'C:\mydir\num\three',sep = ';') - p2 = AppendPath(p2,r'C:\mydir\num\one',sep = ';') - assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three') - assert(p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one') + p1 = AppendPath(p1, r'C:\dir\num\two', sep=';') + p1 = AppendPath(p1, r'C:\dir\num\three', sep=';') + p2 = AppendPath(p2, r'C:\mydir\num\three', sep=';') + p2 = AppendPath(p2, r'C:\mydir\num\one', sep=';') + assert (p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three') + assert (p2 == r'C:\mydir\num\two;C:\mydir\num\three;C:\mydir\num\one') def test_PrependPathPreserveOld(self): """Test prepending to a path while preserving old paths""" p1 = r'C:\dir\num\one;C:\dir\num\two' # have to include the pathsep here so that the test will work on UNIX too. - p1 = PrependPath(p1,r'C:\dir\num\two',sep = ';', delete_existing=0) - p1 = PrependPath(p1,r'C:\dir\num\three',sep = ';') - assert(p1 == r'C:\dir\num\three;C:\dir\num\one;C:\dir\num\two') + p1 = PrependPath(p1, r'C:\dir\num\two', sep=';', delete_existing=0) + p1 = PrependPath(p1, r'C:\dir\num\three', sep=';') + assert (p1 == r'C:\dir\num\three;C:\dir\num\one;C:\dir\num\two') def test_AppendPathPreserveOld(self): """Test appending to a path while preserving old paths""" p1 = r'C:\dir\num\one;C:\dir\num\two' # have to include the pathsep here so that the test will work on UNIX too. - p1 = AppendPath(p1,r'C:\dir\num\one',sep = ';', delete_existing=0) - p1 = AppendPath(p1,r'C:\dir\num\three',sep = ';') - assert(p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three') + p1 = AppendPath(p1, r'C:\dir\num\one', sep=';', delete_existing=0) + p1 = AppendPath(p1, r'C:\dir\num\three', sep=';') + assert (p1 == r'C:\dir\num\one;C:\dir\num\two;C:\dir\num\three') def test_addPathIfNotExists(self): """Test the AddPathIfNotExists() function""" - env_dict = { 'FOO' : os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), - 'BAR' : os.path.normpath('/foo/bar') + os.pathsep + \ - os.path.normpath('/baz/blat'), - 'BLAT' : [ os.path.normpath('/foo/bar'), - os.path.normpath('/baz/blat') ] } + env_dict = {'FOO': os.path.normpath('/foo/bar') + os.pathsep + \ + os.path.normpath('/baz/blat'), + 'BAR': os.path.normpath('/foo/bar') + os.pathsep + \ + os.path.normpath('/baz/blat'), + 'BLAT': [os.path.normpath('/foo/bar'), + os.path.normpath('/baz/blat')]} AddPathIfNotExists(env_dict, 'FOO', os.path.normpath('/foo/bar')) AddPathIfNotExists(env_dict, 'BAR', os.path.normpath('/bar/foo')) AddPathIfNotExists(env_dict, 'BAZ', os.path.normpath('/foo/baz')) @@ -545,9 +579,9 @@ class UtilTestCase(unittest.TestCase): os.path.normpath('/foo/bar') + os.pathsep + \ os.path.normpath('/baz/blat'), env_dict['BAR'] assert env_dict['BAZ'] == os.path.normpath('/foo/baz'), env_dict['BAZ'] - assert env_dict['BLAT'] == [ os.path.normpath('/baz/foo'), - os.path.normpath('/foo/bar'), - os.path.normpath('/baz/blat') ], env_dict['BLAT' ] + assert env_dict['BLAT'] == [os.path.normpath('/baz/foo'), + os.path.normpath('/foo/bar'), + os.path.normpath('/baz/blat')], env_dict['BLAT'] def test_CLVar(self): """Test the command-line construction variable class""" @@ -656,10 +690,11 @@ class UtilTestCase(unittest.TestCase): def __str__(self): return self.name + def get_suffix(self): return os.path.splitext(self.name)[1] - s = Selector({'a' : 'AAA', 'b' : 'BBB'}) + s = Selector({'a': 'AAA', 'b': 'BBB'}) assert s['a'] == 'AAA', s['a'] assert s['b'] == 'BBB', s['b'] exc_caught = None @@ -679,7 +714,7 @@ class UtilTestCase(unittest.TestCase): env = DummyEnv() - s = Selector({'.d' : 'DDD', '.e' : 'EEE'}) + s = Selector({'.d': 'DDD', '.e': 'EEE'}) ret = s(env, []) assert ret is None, ret ret = s(env, [MyNode('foo.d')]) @@ -692,9 +727,9 @@ class UtilTestCase(unittest.TestCase): ret = s(env, [MyNode('bar.x')]) assert ret == 'XXX', ret - env = DummyEnv({'FSUFF' : '.f', 'GSUFF' : '.g'}) + env = DummyEnv({'FSUFF': '.f', 'GSUFF': '.g'}) - s = Selector({'$FSUFF' : 'FFF', '$GSUFF' : 'GGG'}) + s = Selector({'$FSUFF': 'FFF', '$GSUFF': 'GGG'}) ret = s(env, [MyNode('foo.f')]) assert ret == 'FFF', ret ret = s(env, [MyNode('bar.g')]) @@ -780,9 +815,11 @@ class MD5TestCase(unittest.TestCase): s = MD5signature('222') assert 'bcbe3365e6ac95ea2c0343a2395834dd' == s, s + class NodeListTestCase(unittest.TestCase): def test_simple_attributes(self): """Test simple attributes of a NodeList class""" + class TestClass(object): def __init__(self, name, child=None): self.child = child @@ -793,18 +830,21 @@ class NodeListTestCase(unittest.TestCase): t3 = TestClass('t3') nl = NodeList([t1, t2, t3]) - assert nl.bar == [ 't1', 't2', 't3' ], nl.bar - assert nl[0:2].child.bar == [ 't1child', 't2child' ], \ - nl[0:2].child.bar + assert nl.bar == ['t1', 't2', 't3'], nl.bar + assert nl[0:2].child.bar == ['t1child', 't2child'], \ + nl[0:2].child.bar def test_callable_attributes(self): """Test callable attributes of a NodeList class""" + class TestClass(object): def __init__(self, name, child=None): self.child = child self.bar = name + def foo(self): return self.bar + "foo" + def getself(self): return self @@ -813,13 +853,13 @@ class NodeListTestCase(unittest.TestCase): t3 = TestClass('t3') nl = NodeList([t1, t2, t3]) - assert nl.foo() == [ 't1foo', 't2foo', 't3foo' ], nl.foo() - assert nl.bar == [ 't1', 't2', 't3' ], nl.bar - assert nl.getself().bar == [ 't1', 't2', 't3' ], nl.getself().bar - assert nl[0:2].child.foo() == [ 't1childfoo', 't2childfoo' ], \ - nl[0:2].child.foo() - assert nl[0:2].child.bar == [ 't1child', 't2child' ], \ - nl[0:2].child.bar + assert nl.foo() == ['t1foo', 't2foo', 't3foo'], nl.foo() + assert nl.bar == ['t1', 't2', 't3'], nl.bar + assert nl.getself().bar == ['t1', 't2', 't3'], nl.getself().bar + assert nl[0:2].child.foo() == ['t1childfoo', 't2childfoo'], \ + nl[0:2].child.foo() + assert nl[0:2].child.bar == ['t1child', 't2child'], \ + nl[0:2].child.bar def test_null(self): """Test a null NodeList""" @@ -835,21 +875,112 @@ class flattenTestCase(unittest.TestCase): def test_scalar(self): """Test flattening a scalar""" result = flatten('xyz') - assert result == ['xyz'], result + self.assertEqual(result,['xyz'], result) + + def test_dictionary_values(self): + """Test flattening the dictionary values""" + items = {"a": 1, "b": 2, "c": 3} + result = flatten(items.values()) + self.assertEqual(sorted(result),[1,2,3]) + + +class OsEnviron(object): + """Used to temporarily mock os.environ""" + def __init__(self, environ): + self._environ = environ + + def start(self): + self._stored = os.environ + os.environ = self._environ + + def stop(self): + os.environ = self._stored + del self._stored + + def __enter__(self): + self.start() + return os.environ + + def __exit__(self, *args): + self.stop() + + +class get_env_boolTestCase(unittest.TestCase): + def test_missing(self): + env = dict() + var = get_env_bool(env, 'FOO') + assert var is False, "var should be False, not %s" % repr(var) + env = {'FOO': '1'} + var = get_env_bool(env, 'BAR') + assert var is False, "var should be False, not %s" % repr(var) + + def test_true(self): + for foo in [ 'TRUE', 'True', 'true', + 'YES', 'Yes', 'yes', + 'Y', 'y', + 'ON', 'On', 'on', + '1', '20', '-1']: + env = {'FOO': foo} + var = get_env_bool(env, 'FOO') + assert var is True, 'var should be True, not %s' % repr(var) + + def test_false(self): + for foo in [ 'FALSE', 'False', 'false', + 'NO', 'No', 'no', + 'N', 'n', + 'OFF', 'Off', 'off', + '0']: + env = {'FOO': foo} + var = get_env_bool(env, 'FOO', True) + assert var is False, 'var should be True, not %s' % repr(var) + + def test_default(self): + env = {'FOO': 'other'} + var = get_env_bool(env, 'FOO', True) + assert var is True, 'var should be True, not %s' % repr(var) + var = get_env_bool(env, 'FOO', False) + assert var is False, 'var should be False, not %s' % repr(var) + + +class get_os_env_boolTestCase(unittest.TestCase): + def test_missing(self): + with OsEnviron(dict()): + var = get_os_env_bool('FOO') + assert var is False, "var should be False, not %s" % repr(var) + with OsEnviron({'FOO': '1'}): + var = get_os_env_bool('BAR') + assert var is False, "var should be False, not %s" % repr(var) + + def test_true(self): + for foo in [ 'TRUE', 'True', 'true', + 'YES', 'Yes', 'yes', + 'Y', 'y', + 'ON', 'On', 'on', + '1', '20', '-1']: + with OsEnviron({'FOO': foo}): + var = get_os_env_bool('FOO') + assert var is True, 'var should be True, not %s' % repr(var) + + def test_false(self): + for foo in [ 'FALSE', 'False', 'false', + 'NO', 'No', 'no', + 'N', 'n', + 'OFF', 'Off', 'off', + '0']: + with OsEnviron({'FOO': foo}): + var = get_os_env_bool('FOO', True) + assert var is False, 'var should be True, not %s' % repr(var) + + def test_default(self): + with OsEnviron({'FOO': 'other'}): + var = get_os_env_bool('FOO', True) + assert var is True, 'var should be True, not %s' % repr(var) + var = get_os_env_bool('FOO', False) + assert var is False, 'var should be False, not %s' % repr(var) if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ dictifyTestCase, - flattenTestCase, - MD5TestCase, - NodeListTestCase, - UtilTestCase, - ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Variables/BoolVariable.py b/src/engine/SCons/Variables/BoolVariable.py index 881a6b4..5af3a5f 100644 --- a/src/engine/SCons/Variables/BoolVariable.py +++ b/src/engine/SCons/Variables/BoolVariable.py @@ -12,7 +12,7 @@ Usage example:: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -34,7 +34,7 @@ Usage example:: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/BoolVariable.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/BoolVariable.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __all__ = ['BoolVariable',] diff --git a/src/engine/SCons/Variables/BoolVariableTests.py b/src/engine/SCons/Variables/BoolVariableTests.py index 42beaee..62519bc 100644 --- a/src/engine/SCons/Variables/BoolVariableTests.py +++ b/src/engine/SCons/Variables/BoolVariableTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,13 +21,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/BoolVariableTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/BoolVariableTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest -import TestUnit - import SCons.Errors import SCons.Variables @@ -118,8 +116,7 @@ class BoolVariableTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.makeSuite(BoolVariableTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Variables/EnumVariable.py b/src/engine/SCons/Variables/EnumVariable.py index b6fc382..1a5f40c 100644 --- a/src/engine/SCons/Variables/EnumVariable.py +++ b/src/engine/SCons/Variables/EnumVariable.py @@ -15,7 +15,7 @@ Usage example:: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -37,7 +37,7 @@ Usage example:: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/EnumVariable.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/EnumVariable.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __all__ = ['EnumVariable',] diff --git a/src/engine/SCons/Variables/EnumVariableTests.py b/src/engine/SCons/Variables/EnumVariableTests.py index caef48f..d6e4761 100644 --- a/src/engine/SCons/Variables/EnumVariableTests.py +++ b/src/engine/SCons/Variables/EnumVariableTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,13 +21,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/EnumVariableTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/EnumVariableTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest -import TestUnit - import SCons.Errors import SCons.Variables @@ -195,8 +193,7 @@ class EnumVariableTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.makeSuite(EnumVariableTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Variables/ListVariable.py b/src/engine/SCons/Variables/ListVariable.py index 8f9a9a8..d0f99f5 100644 --- a/src/engine/SCons/Variables/ListVariable.py +++ b/src/engine/SCons/Variables/ListVariable.py @@ -25,7 +25,7 @@ Usage example:: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -46,7 +46,7 @@ Usage example:: # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Variables/ListVariable.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/ListVariable.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" # Known Bug: This should behave like a Set-Type, but does not really, # since elements can occur twice. diff --git a/src/engine/SCons/Variables/ListVariableTests.py b/src/engine/SCons/Variables/ListVariableTests.py index be45aed..ff933d0 100644 --- a/src/engine/SCons/Variables/ListVariableTests.py +++ b/src/engine/SCons/Variables/ListVariableTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,14 +21,12 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/ListVariableTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/ListVariableTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import copy import sys import unittest -import TestUnit - import SCons.Errors import SCons.Variables @@ -125,8 +123,7 @@ class ListVariableTestCase(unittest.TestCase): n = l.__class__(copy.copy(l)) if __name__ == "__main__": - suite = unittest.makeSuite(ListVariableTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Variables/PackageVariable.py b/src/engine/SCons/Variables/PackageVariable.py index 8e229b7..e2b3394 100644 --- a/src/engine/SCons/Variables/PackageVariable.py +++ b/src/engine/SCons/Variables/PackageVariable.py @@ -28,7 +28,7 @@ Usage example: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -50,7 +50,7 @@ Usage example: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/PackageVariable.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/PackageVariable.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __all__ = ['PackageVariable',] diff --git a/src/engine/SCons/Variables/PackageVariableTests.py b/src/engine/SCons/Variables/PackageVariableTests.py index 30a88b5..636e2c1 100644 --- a/src/engine/SCons/Variables/PackageVariableTests.py +++ b/src/engine/SCons/Variables/PackageVariableTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/PackageVariableTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/PackageVariableTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest @@ -30,8 +30,6 @@ import SCons.Errors import SCons.Variables import TestCmd -import TestUnit - class PackageVariableTestCase(unittest.TestCase): def test_PackageVariable(self): @@ -115,8 +113,7 @@ class PackageVariableTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.makeSuite(PackageVariableTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Variables/PathVariable.py b/src/engine/SCons/Variables/PathVariable.py index dc5fcd2..52df0af 100644 --- a/src/engine/SCons/Variables/PathVariable.py +++ b/src/engine/SCons/Variables/PathVariable.py @@ -45,7 +45,7 @@ Usage example:: """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -67,7 +67,7 @@ Usage example:: # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/PathVariable.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/PathVariable.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __all__ = ['PathVariable',] diff --git a/src/engine/SCons/Variables/PathVariableTests.py b/src/engine/SCons/Variables/PathVariableTests.py index c8518af..1cd35f6 100644 --- a/src/engine/SCons/Variables/PathVariableTests.py +++ b/src/engine/SCons/Variables/PathVariableTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/PathVariableTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/PathVariableTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import sys @@ -31,8 +31,6 @@ import SCons.Errors import SCons.Variables import TestCmd -import TestUnit - class PathVariableTestCase(unittest.TestCase): def test_PathVariable(self): @@ -228,8 +226,7 @@ class PathVariableTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.makeSuite(PathVariableTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Variables/VariablesTests.py b/src/engine/SCons/Variables/VariablesTests.py index dc507ce..7712bb4 100644 --- a/src/engine/SCons/Variables/VariablesTests.py +++ b/src/engine/SCons/Variables/VariablesTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,17 +21,17 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/Variables/VariablesTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/VariablesTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest import TestSCons -import TestUnit import SCons.Variables import SCons.Subst import SCons.Warnings +from SCons.Util import cmp class Environment(object): @@ -49,12 +49,6 @@ class Environment(object): return key in self.dict -def cmp(a, b): - """ - Define cmp because it's no longer available in python3 - Works under python 2 as well - """ - return (a > b) - (a < b) def check(key, value, env): @@ -65,7 +59,9 @@ def check(key, value, env): def checkSave(file, expected): gdict = {} ldict = {} - exec(open(file, 'r').read(), gdict, ldict) + with open(file, 'r') as f: + exec(f.read(), gdict, ldict) + assert expected == ldict, "%s\n...not equal to...\n%s" % (expected, ldict) class VariablesTestCase(unittest.TestCase): @@ -492,9 +488,29 @@ B: b - alpha test default: 42 actual: 54 """ + + expectBackwards = """ +B: b - alpha test + default: 42 + actual: 54 + +ANSWER: THE answer to THE question + default: 42 + actual: 54 + +A: a - alpha test + default: 42 + actual: 54 +""" text = opts.GenerateHelpText(env, sort=cmp) assert text == expectAlpha, text + textBool = opts.GenerateHelpText(env, sort=True) + assert text == expectAlpha, text + + textBackwards = opts.GenerateHelpText(env, sort=lambda x, y: cmp(y, x)) + assert textBackwards == expectBackwards, "Expected:\n%s\nGot:\n%s\n"%(textBackwards, expectBackwards) + def test_FormatVariableHelpText(self): """Test generating custom format help text""" opts = SCons.Variables.Variables() @@ -675,13 +691,7 @@ class UnknownVariablesTestCase(unittest.TestCase): if __name__ == "__main__": - suite = unittest.TestSuite() - tclasses = [ VariablesTestCase, - UnknownVariablesTestCase ] - for tclass in tclasses: - names = unittest.getTestCaseNames(tclass, 'test_') - suite.addTests(list(map(tclass, names))) - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/Variables/__init__.py b/src/engine/SCons/Variables/__init__.py index 784f795..bde5b88 100644 --- a/src/engine/SCons/Variables/__init__.py +++ b/src/engine/SCons/Variables/__init__.py @@ -5,7 +5,7 @@ customizable variables to an SCons build. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -26,10 +26,11 @@ customizable variables to an SCons build. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -__revision__ = "src/engine/SCons/Variables/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Variables/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os.path import sys +from functools import cmp_to_key import SCons.Environment import SCons.Errors @@ -287,9 +288,13 @@ class Variables(object): env - an environment that is used to get the current values of the options. + cmp - Either a function as follows: The specific sort function should take two arguments and return -1, 0 or 1 + or a boolean to indicate if it should be sorted. """ - if sort: + if callable(sort): + options = sorted(self.options, key=cmp_to_key(lambda x,y: sort(x.key,y.key))) + elif sort is True: options = sorted(self.options, key=lambda x: x.key) else: options = self.options diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index 33ba050..4c6031a 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ This file implements the warnings framework for SCons. """ -__revision__ = "src/engine/SCons/Warnings.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/Warnings.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys @@ -74,12 +74,6 @@ class MisleadingKeywordsWarning(WarningOnByDefault): class MissingSConscriptWarning(WarningOnByDefault): pass -class NoMD5ModuleWarning(WarningOnByDefault): - pass - -class NoMetaclassSupportWarning(WarningOnByDefault): - pass - class NoObjectCountWarning(WarningOnByDefault): pass @@ -153,6 +147,9 @@ class DeprecatedSigModuleWarning(MandatoryDeprecatedWarning): class DeprecatedBuilderKeywordsWarning(MandatoryDeprecatedWarning): pass +class DeprecatedMissingSConscriptWarning(DeprecatedWarning): + pass + # The below is a list of 2-tuples. The first element is a class object. # The second element is true if that class is enabled, false if it is disabled. @@ -185,8 +182,8 @@ def warn(clazz, *args): global _enabled, _warningAsException, _warningOut warning = clazz(args) - for clazz, flag in _enabled: - if isinstance(warning, clazz): + for cls, flag in _enabled: + if isinstance(warning, cls): if flag: if _warningAsException: raise warning diff --git a/src/engine/SCons/WarningsTests.py b/src/engine/SCons/WarningsTests.py index fbba547..5257050 100644 --- a/src/engine/SCons/WarningsTests.py +++ b/src/engine/SCons/WarningsTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,13 +21,11 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/WarningsTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/WarningsTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import sys import unittest -import TestUnit - import SCons.Warnings class TestOutput(object): @@ -127,8 +125,7 @@ class WarningsTestCase(unittest.TestCase): assert to.out == "Foo", to.out if __name__ == "__main__": - suite = unittest.makeSuite(WarningsTestCase, 'test_') - TestUnit.run(suite) + unittest.main() # Local Variables: # tab-width:4 diff --git a/src/engine/SCons/__init__.py b/src/engine/SCons/__init__.py index 5a22146..6b22009 100644 --- a/src/engine/SCons/__init__.py +++ b/src/engine/SCons/__init__.py @@ -5,7 +5,7 @@ The main package for the SCons software construction utility. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,15 +27,15 @@ The main package for the SCons software construction utility. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -__version__ = "3.0.0" +__version__ = "3.0.5" -__build__ = "rel_3.0.0:4395:8972f6a2f699" +__build__ = "103260fce95bf5db1c35fb2371983087d85dd611" -__buildsys__ = "ubuntu-16" +__buildsys__ = "Williams-MBP-2" -__date__ = "2017/09/18 12:59:24" +__date__ = "2019-07-13 18:25:30" __developer__ = "bdbaddog" diff --git a/src/engine/SCons/compat/__init__.py b/src/engine/SCons/compat/__init__.py index 7973732..1e744e4 100644 --- a/src/engine/SCons/compat/__init__.py +++ b/src/engine/SCons/compat/__init__.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -57,7 +57,7 @@ function defined below loads the module as the "real" name (without the rest of our code will find our pre-loaded compatibility module. """ -__revision__ = "src/engine/SCons/compat/__init__.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/compat/__init__.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import sys @@ -98,7 +98,7 @@ import pickle # Was pickle.HIGHEST_PROTOCOL # Changed to 2 so py3.5+'s pickle will be compatible with py2.7. -PICKLE_PROTOCOL = 2 +PICKLE_PROTOCOL = pickle.HIGHEST_PROTOCOL # TODO: FIXME # In 3.x, 'profile' automatically loads the fast version if available. diff --git a/src/engine/SCons/compat/_scons_dbm.py b/src/engine/SCons/compat/_scons_dbm.py index 7adbeb9..31d6803 100644 --- a/src/engine/SCons/compat/_scons_dbm.py +++ b/src/engine/SCons/compat/_scons_dbm.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,7 +30,7 @@ that the whichdb.whichdb() implementstation in the various 2.X versions of Python won't blow up even if dbm wasn't compiled in. """ -__revision__ = "src/engine/SCons/compat/_scons_dbm.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/compat/_scons_dbm.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" class error(Exception): pass diff --git a/src/engine/SCons/cpp.py b/src/engine/SCons/cpp.py index ff750c2..e500711 100644 --- a/src/engine/SCons/cpp.py +++ b/src/engine/SCons/cpp.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -21,7 +21,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/cpp.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/cpp.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """ SCons C Pre-Processor module @@ -43,15 +43,18 @@ import re # that we want to fetch, using the regular expressions to which the lists # of preprocessor directives map. cpp_lines_dict = { - # Fetch the rest of a #if/#elif/#ifdef/#ifndef as one argument, + # Fetch the rest of a #if/#elif as one argument, + # with white space optional. + ('if', 'elif') : r'\s*(.+)', + + # Fetch the rest of a #ifdef/#ifndef as one argument, # separated from the keyword by white space. - ('if', 'elif', 'ifdef', 'ifndef',) - : '\s+(.+)', + ('ifdef', 'ifndef',): r'\s+(.+)', # Fetch the rest of a #import/#include/#include_next line as one # argument, with white space optional. ('import', 'include', 'include_next',) - : '\s*(.+)', + : r'\s*(.+)', # We don't care what comes after a #else or #endif line. ('else', 'endif',) : '', @@ -61,10 +64,10 @@ cpp_lines_dict = { # 2) The optional parentheses and arguments (if it's a function-like # macro, '' if it's not). # 3) The expansion value. - ('define',) : '\s+([_A-Za-z][_A-Za-z0-9_]*)(\([^)]*\))?\s*(.*)', + ('define',) : r'\s+([_A-Za-z][_A-Za-z0-9_]*)(\([^)]*\))?\s*(.*)', # Fetch the #undefed keyword from a #undef line. - ('undef',) : '\s+([_A-Za-z][A-Za-z0-9_]*)', + ('undef',) : r'\s+([_A-Za-z][A-Za-z0-9_]*)', } # Create a table that maps each individual C preprocessor directive to @@ -82,9 +85,9 @@ del op_list # Create a list of the expressions we'll use to match all of the # preprocessor directives. These are the same as the directives # themselves *except* that we must use a negative lookahead assertion -# when matching "if" so it doesn't match the "if" in "ifdef." +# when matching "if" so it doesn't match the "if" in "ifdef" or "ifndef". override = { - 'if' : 'if(?!def)', + 'if' : 'if(?!n?def)', } l = [override.get(x, x) for x in list(Table.keys())] @@ -94,7 +97,7 @@ l = [override.get(x, x) for x in list(Table.keys())] # a list of tuples, one for each preprocessor line. The preprocessor # directive will be the first element in each tuple, and the rest of # the line will be the second element. -e = '^\s*#\s*(' + '|'.join(l) + ')(.*)$' +e = r'^\s*#\s*(' + '|'.join(l) + ')(.*)$' # And last but not least, compile the expression. CPP_Expression = re.compile(e, re.M) @@ -141,12 +144,12 @@ CPP_to_Python_Ops_Expression = re.compile(expr) # A separate list of expressions to be evaluated and substituted # sequentially, not all at once. CPP_to_Python_Eval_List = [ - ['defined\s+(\w+)', '"\\1" in __dict__'], - ['defined\s*\((\w+)\)', '"\\1" in __dict__'], - ['/\*.*\*/', ''], - ['/\*.*', ''], - ['//.*', ''], - ['(0x[0-9A-Fa-f]*)[UL]+', '\\1'], + [r'defined\s+(\w+)', '"\\1" in __dict__'], + [r'defined\s*\((\w+)\)', '"\\1" in __dict__'], + [r'/\*.*\*/', ''], + [r'/\*.*', ''], + [r'//.*', ''], + [r'(0x[0-9A-Fa-f]*)[UL]+', '\\1'], ] # Replace the string representations of the regular expressions in the @@ -222,11 +225,11 @@ line_continuations = re.compile('\\\\\r?\n') # Search for a "function call" macro on an expansion. Returns the # two-tuple of the "function" name itself, and a string containing the # arguments within the call parentheses. -function_name = re.compile('(\S+)\(([^)]*)\)') +function_name = re.compile(r'(\S+)\(([^)]*)\)') # Split a string containing comma-separated function call arguments into # the separate arguments. -function_arg_separator = re.compile(',\s*') +function_arg_separator = re.compile(r',\s*') diff --git a/src/engine/SCons/cppTests.py b/src/engine/SCons/cppTests.py index 2108277..7ebdf99 100644 --- a/src/engine/SCons/cppTests.py +++ b/src/engine/SCons/cppTests.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,7 +23,7 @@ from __future__ import absolute_import -__revision__ = "src/engine/SCons/cppTests.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/cppTests.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import atexit import sys @@ -346,6 +346,80 @@ nested_ifs_input = """ +ifndef_input = """ +#define DEFINED 0 + +#ifndef DEFINED +#include "file45-no" +#else +#include "file45-yes" +#endif + +#ifndef NOT_DEFINED +#include <file46-yes> +#else +#include <file46-no> +#endif +""" + + +if_defined_no_space_input = """ +#define DEFINED 0 + +#if(defined DEFINED) +#include "file47-yes" +#endif + +#if(!defined DEFINED) +#include <file48-no> +#elif(!defined DEFINED) +#include <file49-no> +#else +#include <file50-yes> +#endif + +#if!(defined DEFINED) +#include "file51-no" +#elif!(defined DEFINED) +#include <file52-no> +#else +#include "file53-yes" +#endif +""" + +if_no_space_input = """ +#define DEFINED 0 + +#if(DEFINED) +#include "file54-no" +#endif + +#if!(DEFINED) +#include <file55-yes> +#elif!(DEFINED) +#include <file56-no> +#endif + +#if(DEFINED) +#include "file57-no" +#elif(!DEFINED) +#include <file58-yes> +#endif + +#if!( DEFINED) +#include "file59-yes" +#elif!( DEFINED) +#include <file60-no> +#endif + +#if( DEFINED) +#include "file61-no" +#elif(! DEFINED) +#include <file62-yes> +#endif +""" + + # pp_class = PreProcessor # #pp_class = DumbPreProcessor @@ -426,6 +500,25 @@ class cppTestCase(unittest.TestCase): result = self.cpp.process_contents(nested_ifs_input) assert expect == result, (expect, result) + def test_ifndef(self): + """Test basic #ifndef processing""" + expect = self.ifndef_expect + result = self.cpp.process_contents(ifndef_input) + assert expect == result, (expect, result) + + def test_if_defined_no_space(self): + """Test #if(defined, i.e.without space but parenthesis""" + expect = self.if_defined_no_space_expect + result = self.cpp.process_contents(if_defined_no_space_input) + assert expect == result, (expect, result) + + def test_if_no_space(self): + """Test #if(, i.e. without space but parenthesis""" + expect = self.if_no_space_expect + result = self.cpp.process_contents(if_no_space_input) + assert expect == result, (expect, result) + + class cppAllTestCase(cppTestCase): def setUp(self): self.cpp = self.cpp_class(current = ".", @@ -513,6 +606,24 @@ class PreProcessorTestCase(cppAllTestCase): ('include', '"', 'file7-yes'), ] + ifndef_expect = [ + ('include', '"', 'file45-yes'), + ('include', '<', 'file46-yes'), + ] + + if_defined_no_space_expect = [ + ('include', '"', 'file47-yes'), + ('include', '<', 'file50-yes'), + ('include', '"', 'file53-yes'), + ] + + if_no_space_expect = [ + ('include', '<', 'file55-yes'), + ('include', '<', 'file58-yes'), + ('include', '"', 'file59-yes'), + ('include', '<', 'file62-yes'), + ] + class DumbPreProcessorTestCase(cppAllTestCase): cpp_class = cpp.DumbPreProcessor @@ -625,7 +736,34 @@ class DumbPreProcessorTestCase(cppAllTestCase): ('include', '"', 'file7-yes') ] + ifndef_expect = [ + ('include', '"', 'file45-no'), + ('include', '"', 'file45-yes'), + ('include', '<', 'file46-yes'), + ('include', '<', 'file46-no'), + ] + + if_defined_no_space_expect = [ + ('include', '"', 'file47-yes'), + ('include', '<', 'file48-no'), + ('include', '<', 'file49-no'), + ('include', '<', 'file50-yes'), + ('include', '"', 'file51-no'), + ('include', '<', 'file52-no'), + ('include', '"', 'file53-yes'), + ] + if_no_space_expect = [ + ('include', '"', 'file54-no'), + ('include', '<', 'file55-yes'), + ('include', '<', 'file56-no'), + ('include', '"', 'file57-no'), + ('include', '<', 'file58-yes'), + ('include', '"', 'file59-yes'), + ('include', '<', 'file60-no'), + ('include', '"', 'file61-no'), + ('include', '<', 'file62-yes'), + ] import os import re @@ -679,7 +817,8 @@ class fileTestCase(unittest.TestCase): return '\n'.join(map(strip_spaces, lines)) def write(self, file, contents): - open(file, 'w').write(self.strip_initial_spaces(contents)) + with open(file, 'w') as f: + f.write(self.strip_initial_spaces(contents)) def test_basic(self): """Test basic file inclusion""" diff --git a/src/engine/SCons/dblite.py b/src/engine/SCons/dblite.py index 87a1763..14bd93d 100644 --- a/src/engine/SCons/dblite.py +++ b/src/engine/SCons/dblite.py @@ -75,7 +75,8 @@ class dblite(object): def __init__(self, file_base_name, flag, mode): assert flag in (None, "r", "w", "c", "n") - if (flag is None): flag = "r" + if flag is None: + flag = "r" base, ext = os.path.splitext(file_base_name) if ext == dblite_suffix: @@ -106,17 +107,20 @@ class dblite(object): self._chown_to = -1 # don't chown self._chgrp_to = -1 # don't chgrp - if (self._flag == "n"): - self._open(self._file_name, "wb", self._mode) + if self._flag == "n": + with self._open(self._file_name, "wb", self._mode): + pass # just make sure it exists else: try: f = self._open(self._file_name, "rb") except IOError as e: - if (self._flag != "c"): + if self._flag != "c": raise e - self._open(self._file_name, "wb", self._mode) + with self._open(self._file_name, "wb", self._mode): + pass # just make sure it exists else: p = f.read() + f.close() if len(p) > 0: try: if bytes is not str: @@ -132,7 +136,7 @@ class dblite(object): corruption_warning(self._file_name) def close(self): - if (self._needs_sync): + if self._needs_sync: self.sync() def __del__(self): diff --git a/src/engine/SCons/exitfuncs.py b/src/engine/SCons/exitfuncs.py index 2b7bd51..3f4c1ac 100644 --- a/src/engine/SCons/exitfuncs.py +++ b/src/engine/SCons/exitfuncs.py @@ -5,7 +5,7 @@ Register functions which are executed when SCons exits for any reason. """ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -27,7 +27,7 @@ Register functions which are executed when SCons exits for any reason. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "src/engine/SCons/exitfuncs.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/engine/SCons/exitfuncs.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import atexit diff --git a/src/script/scons-configure-cache.py b/src/script/scons-configure-cache.py index 9b8b737..7c5d3b6 100644 --- a/src/script/scons-configure-cache.py +++ b/src/script/scons-configure-cache.py @@ -2,7 +2,7 @@ # # SCons - a Software Constructor # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,102 +23,139 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +'''Show or convert the configuration of an SCons cache directory. + +A cache of derived files is stored by file signature. +The files are split into directories named by the first few +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 +import os -__revision__ = "src/script/scons-configure-cache.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/script/scons-configure-cache.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -__version__ = "3.0.0" +__version__ = "3.0.5" -__build__ = "rel_3.0.0:4395:8972f6a2f699" +__build__ = "103260fce95bf5db1c35fb2371983087d85dd611" -__buildsys__ = "ubuntu-16" +__buildsys__ = "Williams-MBP-2" -__date__ = "2017/09/18 12:59:24" +__date__ = "2019-07-13 18:25:30" __developer__ = "bdbaddog" -import argparse -import glob -import json -import os def rearrange_cache_entries(current_prefix_len, new_prefix_len): - print('Changing prefix length from', current_prefix_len, 'to', new_prefix_len) + '''Move cache files if prefix length changed. + + Move the existing cache files to new directories of the + appropriate name length and clean up the old directories. + ''' + print('Changing prefix length from', current_prefix_len, + 'to', new_prefix_len) dirs = set() old_dirs = set() for file in glob.iglob(os.path.join('*', '*')): name = os.path.basename(file) - dir = name[:current_prefix_len].upper() - if dir not in old_dirs: - print('Migrating', dir) - old_dirs.add(dir) - dir = name[:new_prefix_len].upper() - if dir not in dirs: - os.mkdir(dir) - dirs.add(dir) - os.rename(file, os.path.join(dir, name)) + dname = name[:current_prefix_len].upper() + if dname not in old_dirs: + print('Migrating', dname) + old_dirs.add(dname) + dname = name[:new_prefix_len].upper() + if dname not in dirs: + os.mkdir(dname) + dirs.add(dname) + os.rename(file, os.path.join(dname, name)) # Now delete the original directories - for dir in old_dirs: - os.rmdir(dir) + for dname in old_dirs: + os.rmdir(dname) + -# This dictionary should have one entry per entry in the cache config -# Each entry should have the following: +# The configuration dictionary should have one entry per entry in the +# cache config. The value of each entry should include the following: # implicit - (optional) This is to allow adding a new config entry and also # changing the behaviour of the system at the same time. This -# indicates the value the config entry would have had if it had been -# specified. +# indicates the value the config entry would have had if it had +# been specified. # default - The value the config entry should have if it wasn't previously # specified # command-line - parameters to pass to ArgumentParser.add_argument -# converter - (optional) Function to call if it's necessary to do some work +# converter - (optional) Function to call if conversion is required # if this configuration entry changes config_entries = { - 'prefix_len' : { - 'implicit' : 1, - 'default' : 2 , - 'command-line' : { - 'help' : 'Length of cache file name used as subdirectory prefix', - 'metavar' : '<number>', - 'type' : int - }, - 'converter' : rearrange_cache_entries + 'prefix_len': { + 'implicit': 1, + 'default': 2, + 'command-line': { + 'help': 'Length of cache file name used as subdirectory prefix', + 'metavar': '<number>', + 'type': int + }, + 'converter': rearrange_cache_entries } } + parser = argparse.ArgumentParser( - description = 'Modify the configuration of an scons cache directory', - epilog = ''' - Unless you specify an option, it will not be changed (if it is - already set in the cache config), or changed to an appropriate - default (it it is not set). - ''' - ) + description='Modify the configuration of an scons cache directory', + epilog=''' + Unspecified options will not be changed unless they are not + set at all, in which case they are set to an appropriate default. + ''') parser.add_argument('cache-dir', help='Path to scons cache directory') for param in config_entries: - parser.add_argument('--' + param.replace('_', '-'), + parser.add_argument('--' + param.replace('_', '-'), **config_entries[param]['command-line']) -parser.add_argument('--version', action='version', version='%(prog)s 1.0') +parser.add_argument('--version', + action='version', + version='%(prog)s 1.0') +parser.add_argument('--show', + action="store_true", + help="show current configuration") # Get the command line as a dict without any of the unspecified entries. args = dict([x for x in vars(parser.parse_args()).items() if x[1]]) # It seems somewhat strange to me, but positional arguments don't get the - # in the name changed to _, whereas optional arguments do... -os.chdir(args['cache-dir']) +cache = args['cache-dir'] +if not os.path.isdir(cache): + raise RuntimeError("There is no cache directory named %s" % cache) +os.chdir(cache) del args['cache-dir'] if not os.path.exists('config'): + # old config dirs did not have a 'config' file. Try to update. # Validate the only files in the directory are directories 0-9, a-f - expected = [ '{:X}'.format(x) for x in range(0, 16) ] + expected = ['{:X}'.format(x) for x in range(0, 16)] if not set(os.listdir('.')).issubset(expected): - raise RuntimeError("This doesn't look like a version 1 cache directory") + raise RuntimeError( + "%s does not look like a valid version 1 cache directory" % cache) config = dict() else: with open('config') as conf: config = json.load(conf) -# Find any keys that aren't currently set but should be +if args.get('show', None): + print("Current configuration in '%s':" % cache) + print(json.dumps(config, sort_keys=True, + indent=4, separators=(',', ': '))) + # in case of the show argument, emit some stats as well + file_count = 0 + for _, _, files in os.walk('.'): + file_count += len(files) + if file_count: # skip config file if it exists + file_count -= 1 + print("Cache contains %s files" % file_count) + del args['show'] + +# Find any keys that are not currently set but should be for key in config_entries: if key not in config: if 'implicit' in config_entries[key]: @@ -128,10 +165,10 @@ for key in config_entries: if key not in args: args[key] = config_entries[key]['default'] -#Now we go through each entry in args to see if it changes an existing config -#setting. +# Now go through each entry in args to see if it changes an existing config +# setting. for key in args: - if args[key] != config[key]: + if args[key] != config[key]: if 'converter' in config_entries[key]: config_entries[key]['converter'](config[key], args[key]) config[key] = args[key] diff --git a/src/script/scons-time.py b/src/script/scons-time.py index 08bde60..b2ae22b 100644 --- a/src/script/scons-time.py +++ b/src/script/scons-time.py @@ -9,7 +9,7 @@ # # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -31,7 +31,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import division, print_function -__revision__ = "src/script/scons-time.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/script/scons-time.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import getopt import glob @@ -58,12 +58,12 @@ def make_temp_file(**kw): return result def HACK_for_exec(cmd, *args): - ''' + """ For some reason, Python won't allow an exec() within a function that also declares an internal function (including lambda functions). This function is a hack that calls exec() in a function with no internal functions. - ''' + """ if not args: exec(cmd) elif len(args) == 1: exec(cmd, args[0]) else: exec(cmd, args[0], args[1]) @@ -147,7 +147,7 @@ class Gnuplotter(Plotter): return line.plot_string() def vertical_bar(self, x, type, label, comment): - if self.get_min_x() <= x and x <= self.get_max_x(): + if self.get_min_x() <= x <= self.get_max_x(): points = [(x, 0), (x, self.max_graph_value(self.get_max_y()))] self.line(points, type, label, comment) @@ -814,7 +814,9 @@ class SConsTimer(object): self.title = a if self.config_file: - exec(open(self.config_file, 'r').read(), self.__dict__) + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) if self.chdir: os.chdir(self.chdir) @@ -933,7 +935,9 @@ class SConsTimer(object): self.title = a if self.config_file: - HACK_for_exec(open(self.config_file, 'r').read(), self.__dict__) + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) if self.chdir: os.chdir(self.chdir) @@ -1053,7 +1057,9 @@ class SConsTimer(object): object_name = args.pop(0) if self.config_file: - HACK_for_exec(open(self.config_file, 'r').read(), self.__dict__) + with open(self.config_file, 'r') as f: + config = f.read() + HACK_for_exec(config, self.__dict__) if self.chdir: os.chdir(self.chdir) @@ -1191,7 +1197,9 @@ class SConsTimer(object): sys.exit(1) if self.config_file: - exec(open(self.config_file, 'r').read(), self.__dict__) + with open(self.config_file, 'r') as f: + config = f.read() + exec(config, self.__dict__) if args: self.archive_list = args diff --git a/src/script/scons.bat b/src/script/scons.bat index f759e43..156aa9c 100644 --- a/src/script/scons.bat +++ b/src/script/scons.bat @@ -1,11 +1,11 @@ -@REM Copyright (c) 2001 - 2017 The SCons Foundation
-@REM src/script/scons.bat rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog
+@REM Copyright (c) 2001 - 2019 The SCons Foundation
+@REM src/script/scons.bat 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog
@echo off
set SCONS_ERRORLEVEL=
if "%OS%" == "Windows_NT" goto WinNT
@REM for 9x/Me you better not have more than 9 args
-python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-3.0.0'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-3.0.0'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9
+python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-3.0.5'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-3.0.5'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9
@REM no way to set exit status of this script for 9x/Me
goto endscons
@@ -16,10 +16,14 @@ goto endscons :WinNT
setlocal
@REM ensure the script will be executed with the Python it was installed for
-set path=%~dp0;%~dp0..;%path%
+pushd %~dp0..
+set path=%~dp0;%CD%;%path%
+popd
@REM try the script named as the .bat file in current dir, then in Scripts subdir
set scriptname=%~dp0%~n0.py
if not exist "%scriptname%" set scriptname=%~dp0Scripts\%~n0.py
+@REM Handle when running from wheel where the script has no .py extension
+if not exist "%scriptname%" set scriptname=%~dp0%~n0
python "%scriptname%" %*
endlocal & set SCONS_ERRORLEVEL=%ERRORLEVEL%
diff --git a/src/script/scons.py b/src/script/scons.py index bee0224..e58d8e2 100644..100755 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -2,7 +2,7 @@ # # SCons - a Software Constructor # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,22 +25,30 @@ from __future__ import print_function -__revision__ = "src/script/scons.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/script/scons.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -__version__ = "3.0.0" +__version__ = "3.0.5" -__build__ = "rel_3.0.0:4395:8972f6a2f699" +__build__ = "103260fce95bf5db1c35fb2371983087d85dd611" -__buildsys__ = "ubuntu-16" +__buildsys__ = "Williams-MBP-2" -__date__ = "2017/09/18 12:59:24" +__date__ = "2019-07-13 18:25:30" __developer__ = "bdbaddog" +# This is the entry point to the SCons program. +# The only job of this script is to work out where the guts of the program +# could be and import them, where the real work begins. +# SCons can be invoked several different ways +# - from an installed location +# - from a "local install" copy +# - from a source tree, which has a different dir struture than the other two +# Try to account for all those possibilities. + import os import sys - ############################################################################## # BEGIN STANDARD SCons SCRIPT HEADER # @@ -50,57 +58,53 @@ import sys # should also change other scripts that use this same header. ############################################################################## -# Strip the script directory from sys.path() so on case-insensitive -# (WIN32) systems Python doesn't think that the "scons" script is the -# "SCons" package. Replace it with our own library directories -# (version-specific first, in case they installed by hand there, -# followed by generic) so we pick up the right version of the build -# engine modules if they're in either directory. - - +# compatibility check if (3,0,0) < sys.version_info < (3,5,0) or sys.version_info < (2,7,0): msg = "scons: *** SCons version %s does not run under Python version %s.\n\ -Python < 3.5 is not yet supported.\n" +Python 2.7 or >= 3.5 is required.\n" sys.stderr.write(msg % (__version__, sys.version.split()[0])) sys.exit(1) - -script_dir = sys.path[0] - -if script_dir in sys.path: - sys.path.remove(script_dir) +# Strip the script directory from sys.path so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. +script_dir = os.path.dirname(os.path.realpath(__file__)) +script_path = os.path.realpath(os.path.dirname(__file__)) +if script_path in sys.path: + sys.path.remove(script_path) libs = [] if "SCONS_LIB_DIR" in os.environ: libs.append(os.environ["SCONS_LIB_DIR"]) -# - running from source takes priority (since 2.3.2), excluding SCONS_LIB_DIR settings -script_path = os.path.abspath(os.path.dirname(__file__)) -source_path = os.path.join(script_path, '..', 'engine') -libs.append(source_path) +# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR +source_path = os.path.join(script_path, os.pardir, 'engine') +if os.path.isdir(source_path): + libs.append(source_path) +# add local-install locations local_version = 'scons-local-' + __version__ local = 'scons-local' if script_dir: local_version = os.path.join(script_dir, local_version) local = os.path.join(script_dir, local) -libs.append(os.path.abspath(local_version)) -libs.append(os.path.abspath(local)) +if os.path.isdir(local_version): + libs.append(os.path.abspath(local_version)) +if os.path.isdir(local): + libs.append(os.path.abspath(local)) scons_version = 'scons-%s' % __version__ # preferred order of scons lookup paths prefs = [] - -# - running from egg check +# if we can find package information, use it try: import pkg_resources except ImportError: pass else: - # when running from an egg add the egg's directory try: d = pkg_resources.get_distribution('scons') except pkg_resources.DistributionNotFound: @@ -109,18 +113,18 @@ else: prefs.append(d.location) if sys.platform == 'win32': - # sys.prefix is (likely) C:\Python*; - # check only C:\Python*. + # Use only sys.prefix on Windows prefs.append(sys.prefix) prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages')) else: # On other (POSIX) platforms, things are more complicated due to - # the variety of path names and library locations. Try to be smart - # about it. + # the variety of path names and library locations. + # Build up some possibilities, then transform them into candidates + temp = [] if script_dir == 'bin': # script_dir is `pwd`/bin; # check `pwd`/lib/scons*. - prefs.append(os.getcwd()) + temp.append(os.getcwd()) else: if script_dir == '.' or script_dir == '': script_dir = os.getcwd() @@ -128,42 +132,41 @@ else: if tail == "bin": # script_dir is /foo/bin; # check /foo/lib/scons*. - prefs.append(head) + temp.append(head) head, tail = os.path.split(sys.prefix) if tail == "usr": # sys.prefix is /foo/usr; # check /foo/usr/lib/scons* first, # then /foo/usr/local/lib/scons*. - prefs.append(sys.prefix) - prefs.append(os.path.join(sys.prefix, "local")) + temp.append(sys.prefix) + temp.append(os.path.join(sys.prefix, "local")) elif tail == "local": h, t = os.path.split(head) if t == "usr": # sys.prefix is /foo/usr/local; # check /foo/usr/local/lib/scons* first, # then /foo/usr/lib/scons*. - prefs.append(sys.prefix) - prefs.append(head) + temp.append(sys.prefix) + temp.append(head) else: # sys.prefix is /foo/local; # check only /foo/local/lib/scons*. - prefs.append(sys.prefix) + temp.append(sys.prefix) else: # sys.prefix is /foo (ends in neither /usr or /local); # check only /foo/lib/scons*. - prefs.append(sys.prefix) + temp.append(sys.prefix) + + # suffix these to add to our original prefs: + prefs.extend([os.path.join(x, 'lib') for x in temp]) + prefs.extend([os.path.join(x, 'lib', 'python' + sys.version[:3], + 'site-packages') for x in temp]) - temp = [os.path.join(x, 'lib') for x in prefs] - temp.extend([os.path.join(x, - 'lib', - 'python' + sys.version[:3], - 'site-packages') for x in prefs]) - prefs = temp # Add the parent directory of the current python's library to the - # preferences. On SuSE-91/AMD64, for example, this is /usr/lib64, - # not /usr/lib. + # preferences. This picks up differences between, e.g., lib and lib64, + # and finds the base location in case of a non-copying virtualenv. try: libpath = os.__file__ except AttributeError: @@ -177,9 +180,9 @@ else: prefs.append(libpath) # Look first for 'scons-__version__' in all of our preference libs, -# then for 'scons'. -libs.extend([os.path.join(x, scons_version) for x in prefs]) -libs.extend([os.path.join(x, 'scons') for x in prefs]) +# then for 'scons'. Skip paths that do not exist. +libs.extend([os.path.join(x, scons_version) for x in prefs if os.path.isdir(x)]) +libs.extend([os.path.join(x, 'scons') for x in prefs if os.path.isdir(x)]) sys.path = libs + sys.path @@ -191,9 +194,9 @@ if __name__ == "__main__": try: import SCons.Script except ImportError: - print("SCons import failed. Unable to find engine files in:") + sys.stderr.write("SCons import failed. Unable to find engine files in:\n") for path in libs: - print(" {}".format(path)) + sys.stderr.write(" {}\n".format(path)) raise # this does all the work, and calls sys.exit diff --git a/src/script/sconsign.py b/src/script/sconsign.py index d3450ab..217193a 100644 --- a/src/script/sconsign.py +++ b/src/script/sconsign.py @@ -2,7 +2,7 @@ # # SCons - a Software Constructor # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -25,15 +25,15 @@ from __future__ import print_function -__revision__ = "src/script/sconsign.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/script/sconsign.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" -__version__ = "3.0.0" +__version__ = "3.0.5" -__build__ = "rel_3.0.0:4395:8972f6a2f699" +__build__ = "103260fce95bf5db1c35fb2371983087d85dd611" -__buildsys__ = "ubuntu-16" +__buildsys__ = "Williams-MBP-2" -__date__ = "2017/09/18 12:59:24" +__date__ = "2019-07-13 18:25:30" __developer__ = "bdbaddog" @@ -49,48 +49,53 @@ import sys # should also change other scripts that use this same header. ############################################################################## -# Strip the script directory from sys.path() so on case-insensitive -# (WIN32) systems Python doesn't think that the "scons" script is the -# "SCons" package. Replace it with our own library directories -# (version-specific first, in case they installed by hand there, -# followed by generic) so we pick up the right version of the build -# engine modules if they're in either directory. - - -script_dir = sys.path[0] +# compatibility check +if (3,0,0) < sys.version_info < (3,5,0) or sys.version_info < (2,7,0): + msg = "scons: *** SCons version %s does not run under Python version %s.\n\ +Python 2.7 or >= 3.5 is required.\n" + sys.stderr.write(msg % (__version__, sys.version.split()[0])) + sys.exit(1) -if script_dir in sys.path: - sys.path.remove(script_dir) +# Strip the script directory from sys.path so on case-insensitive +# (WIN32) systems Python doesn't think that the "scons" script is the +# "SCons" package. +script_dir = os.path.dirname(os.path.realpath(__file__)) +script_path = os.path.realpath(os.path.dirname(__file__)) +if script_path in sys.path: + sys.path.remove(script_path) libs = [] if "SCONS_LIB_DIR" in os.environ: libs.append(os.environ["SCONS_LIB_DIR"]) -# - running from source takes priority (since 2.3.2), excluding SCONS_LIB_DIR settings -script_path = os.path.abspath(os.path.dirname(__file__)) -source_path = os.path.join(script_path, '..', 'engine') -libs.append(source_path) +# running from source takes 2nd priority (since 2.3.2), following SCONS_LIB_DIR +source_path = os.path.join(script_path, os.pardir, 'engine') +if os.path.isdir(source_path): + libs.append(source_path) +# add local-install locations local_version = 'scons-local-' + __version__ local = 'scons-local' if script_dir: local_version = os.path.join(script_dir, local_version) local = os.path.join(script_dir, local) -libs.append(os.path.abspath(local_version)) -libs.append(os.path.abspath(local)) +if os.path.isdir(local_version): + libs.append(os.path.abspath(local_version)) +if os.path.isdir(local): + libs.append(os.path.abspath(local)) scons_version = 'scons-%s' % __version__ # preferred order of scons lookup paths prefs = [] +# if we can find package information, use it try: import pkg_resources except ImportError: pass else: - # when running from an egg add the egg's directory try: d = pkg_resources.get_distribution('scons') except pkg_resources.DistributionNotFound: @@ -99,18 +104,18 @@ else: prefs.append(d.location) if sys.platform == 'win32': - # sys.prefix is (likely) C:\Python*; - # check only C:\Python*. + # Use only sys.prefix on Windows prefs.append(sys.prefix) prefs.append(os.path.join(sys.prefix, 'Lib', 'site-packages')) else: # On other (POSIX) platforms, things are more complicated due to - # the variety of path names and library locations. Try to be smart - # about it. + # the variety of path names and library locations. + # Build up some possibilities, then transform them into candidates + temp = [] if script_dir == 'bin': # script_dir is `pwd`/bin; # check `pwd`/lib/scons*. - prefs.append(os.getcwd()) + temp.append(os.getcwd()) else: if script_dir == '.' or script_dir == '': script_dir = os.getcwd() @@ -118,58 +123,57 @@ else: if tail == "bin": # script_dir is /foo/bin; # check /foo/lib/scons*. - prefs.append(head) + temp.append(head) head, tail = os.path.split(sys.prefix) if tail == "usr": # sys.prefix is /foo/usr; # check /foo/usr/lib/scons* first, # then /foo/usr/local/lib/scons*. - prefs.append(sys.prefix) - prefs.append(os.path.join(sys.prefix, "local")) + temp.append(sys.prefix) + temp.append(os.path.join(sys.prefix, "local")) elif tail == "local": h, t = os.path.split(head) if t == "usr": # sys.prefix is /foo/usr/local; # check /foo/usr/local/lib/scons* first, # then /foo/usr/lib/scons*. - prefs.append(sys.prefix) - prefs.append(head) + temp.append(sys.prefix) + temp.append(head) else: # sys.prefix is /foo/local; # check only /foo/local/lib/scons*. - prefs.append(sys.prefix) + temp.append(sys.prefix) else: # sys.prefix is /foo (ends in neither /usr or /local); # check only /foo/lib/scons*. - prefs.append(sys.prefix) + temp.append(sys.prefix) + + # suffix these to add to our original prefs: + prefs.extend([os.path.join(x, 'lib') for x in temp]) + prefs.extend([os.path.join(x, 'lib', 'python' + sys.version[:3], + 'site-packages') for x in temp]) - temp = [os.path.join(x, 'lib') for x in prefs] - temp.extend([os.path.join(x, - 'lib', - 'python' + sys.version[:3], - 'site-packages') for x in prefs]) - prefs = temp # Add the parent directory of the current python's library to the - # preferences. On SuSE-91/AMD64, for example, this is /usr/lib64, - # not /usr/lib. + # preferences. This picks up differences between, e.g., lib and lib64, + # and finds the base location in case of a non-copying virtualenv. try: libpath = os.__file__ except AttributeError: pass else: # Split /usr/libfoo/python*/os.py to /usr/libfoo/python*. - libpath, tail = os.path.split(libpath) + libpath, _ = os.path.split(libpath) # Split /usr/libfoo/python* to /usr/libfoo libpath, tail = os.path.split(libpath) # Check /usr/libfoo/scons*. prefs.append(libpath) # Look first for 'scons-__version__' in all of our preference libs, -# then for 'scons'. -libs.extend([os.path.join(x, scons_version) for x in prefs]) -libs.extend([os.path.join(x, 'scons') for x in prefs]) +# then for 'scons'. Skip paths that do not exist. +libs.extend([os.path.join(x, scons_version) for x in prefs if os.path.isdir(x)]) +libs.extend([os.path.join(x, 'scons') for x in prefs if os.path.isdir(x)]) sys.path = libs + sys.path @@ -191,6 +195,7 @@ import imp import SCons.SConsign + def my_whichdb(filename): if filename[-7:] == ".dblite": return "SCons.dblite" @@ -221,24 +226,41 @@ def my_import(mname): fp, pathname, description = imp.find_module(mname) return imp.load_module(mname, fp, pathname, description) + class Flagger(object): default_value = 1 + def __setitem__(self, item, value): self.__dict__[item] = value self.default_value = 0 + def __getitem__(self, item): return self.__dict__.get(item, self.default_value) + Do_Call = None Print_Directories = [] Print_Entries = [] Print_Flags = Flagger() Verbose = 0 Readable = 0 +Warns = 0 + + def default_mapper(entry, name): + ''' + Stringify an entry that doesn't have an explicit mapping. + + Args: + entry: entry + name: field name + + Returns: str + + ''' try: - val = eval("entry."+name) + val = eval("entry." + name) except: val = None if sys.version_info.major >= 3 and isinstance(val, bytes): @@ -248,7 +270,18 @@ def default_mapper(entry, name): val = val.decode() return str(val) -def map_action(entry, name): + +def map_action(entry, _): + ''' + Stringify an action entry and signature. + + Args: + entry: action entry + second argument is not used + + Returns: str + + ''' try: bact = entry.bact bactsig = entry.bactsig @@ -256,7 +289,17 @@ def map_action(entry, name): return None return '%s [%s]' % (bactsig, bact) -def map_timestamp(entry, name): +def map_timestamp(entry, _): + ''' + Stringify a timestamp entry. + + Args: + entry: timestamp entry + second argument is not used + + Returns: str + + ''' try: timestamp = entry.timestamp except AttributeError: @@ -266,19 +309,38 @@ def map_timestamp(entry, name): else: return str(timestamp) -def map_bkids(entry, name): +def map_bkids(entry, _): + ''' + Stringify an implicit entry. + + Args: + entry: + second argument is not used + + Returns: str + + ''' try: bkids = entry.bsources + entry.bdepends + entry.bimplicit bkidsigs = entry.bsourcesigs + entry.bdependsigs + entry.bimplicitsigs except AttributeError: return None - result = [] - for i in range(len(bkids)): - result.append(nodeinfo_string(bkids[i], bkidsigs[i], " ")) - if result == []: + + if len(bkids) != len(bkidsigs): + global Warns + Warns += 1 + # add warning to result rather than direct print so it will line up + msg = "Warning: missing information, {} ids but {} sigs" + result = [msg.format(len(bkids), len(bkidsigs))] + else: + result = [] + result += [nodeinfo_string(bkid, bkidsig, " ") + for bkid, bkidsig in zip(bkids, bkidsigs)] + if not result: return None return "\n ".join(result) + map_field = { 'action' : map_action, 'timestamp' : map_timestamp, @@ -289,6 +351,7 @@ map_name = { 'implicit' : 'bkids', } + def field(name, entry, verbose=Verbose): if not Print_Flags[name]: return None @@ -299,6 +362,7 @@ def field(name, entry, verbose=Verbose): val = name + ": " + val return val + def nodeinfo_raw(name, ninfo, prefix=""): # This just formats the dictionary, which we would normally use str() # to do, except that we want the keys sorted for deterministic output. @@ -314,6 +378,7 @@ def nodeinfo_raw(name, ninfo, prefix=""): name = repr(name) return name + ': {' + ', '.join(l) + '}' + def nodeinfo_cooked(name, ninfo, prefix=""): try: field_list = ninfo.field_list @@ -321,15 +386,19 @@ def nodeinfo_cooked(name, ninfo, prefix=""): field_list = [] if '\n' in name: name = repr(name) - outlist = [name+':'] + [_f for _f in [field(x, ninfo, Verbose) for x in field_list] if _f] + outlist = [name + ':'] + [ + f for f in [field(x, ninfo, Verbose) for x in field_list] if f + ] if Verbose: sep = '\n ' + prefix else: sep = ' ' return sep.join(outlist) + nodeinfo_string = nodeinfo_cooked + def printfield(name, entry, prefix=""): outlist = field("implicit", entry, 0) if outlist: @@ -343,13 +412,15 @@ def printfield(name, entry, prefix=""): else: print(" " + outact) + def printentries(entries, location): if Print_Entries: for name in Print_Entries: try: entry = entries[name] except KeyError: - sys.stderr.write("sconsign: no entry `%s' in `%s'\n" % (name, location)) + err = "sconsign: no entry `%s' in `%s'\n" % (name, location) + sys.stderr.write(err) else: try: ninfo = entry.ninfo @@ -369,6 +440,7 @@ def printentries(entries, location): print(nodeinfo_string(name, entry.ninfo)) printfield(name, entry.binfo) + class Do_SConsignDB(object): def __init__(self, dbm_name, dbm): self.dbm_name = dbm_name @@ -403,15 +475,17 @@ class Do_SConsignDB(object): # Nope, that file doesn't even exist, so report that # fact back. print_e = e - sys.stderr.write("sconsign: %s\n" % (print_e)) + sys.stderr.write("sconsign: %s\n" % print_e) return except KeyboardInterrupt: raise except pickle.UnpicklingError: - sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" % (self.dbm_name, fname)) + sys.stderr.write("sconsign: ignoring invalid `%s' file `%s'\n" + % (self.dbm_name, fname)) return except Exception as e: - sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" % (self.dbm_name, fname, e)) + sys.stderr.write("sconsign: ignoring invalid `%s' file `%s': %s\n" + % (self.dbm_name, fname, e)) return if Print_Directories: @@ -419,35 +493,44 @@ class Do_SConsignDB(object): try: val = db[dir] except KeyError: - sys.stderr.write("sconsign: no dir `%s' in `%s'\n" % (dir, args[0])) + err = "sconsign: no dir `%s' in `%s'\n" % (dir, args[0]) + sys.stderr.write(err) else: self.printentries(dir, val) else: for dir in sorted(db.keys()): self.printentries(dir, db[dir]) - def printentries(self, dir, val): - print('=== ' + dir + ':') + @staticmethod + def printentries(dir, val): + try: + print('=== ' + dir + ':') + except TypeError: + print('=== ' + dir.decode() + ':') printentries(pickle.loads(val), dir) + def Do_SConsignDir(name): try: fp = open(name, 'rb') except (IOError, OSError) as e: - sys.stderr.write("sconsign: %s\n" % (e)) + sys.stderr.write("sconsign: %s\n" % e) return try: sconsign = SCons.SConsign.Dir(fp) except KeyboardInterrupt: raise except pickle.UnpicklingError: - sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s'\n" % (name)) + err = "sconsign: ignoring invalid .sconsign file `%s'\n" % (name) + sys.stderr.write(err) return except Exception as e: - sys.stderr.write("sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e)) + err = "sconsign: ignoring invalid .sconsign file `%s': %s\n" % (name, e) + sys.stderr.write(err) return printentries(sconsign.entries, args[0]) + ############################################################################## import getopt @@ -489,8 +572,7 @@ for o, a in opts: elif o in ('-f', '--format'): # Try to map the given DB format to a known module # name, that we can then try to import... - Module_Map = {'dblite' : 'SCons.dblite', - 'sconsign' : None} + Module_Map = {'dblite': 'SCons.dblite', 'sconsign': None} dbm_name = Module_Map.get(a, a) if dbm_name: try: @@ -498,6 +580,7 @@ for o, a in opts: dbm = my_import(dbm_name) else: import SCons.dblite + dbm = SCons.dblite # Ensure that we don't ignore corrupt DB files, # this was handled by calling my_import('SCons.dblite') @@ -526,7 +609,6 @@ for o, a in opts: elif o in ('-v', '--verbose'): Verbose = 1 - if Do_Call: for a in args: Do_Call(a) @@ -534,11 +616,12 @@ else: for a in args: dbm_name = whichdb(a) if dbm_name: - Map_Module = {'SCons.dblite' : 'dblite'} + Map_Module = {'SCons.dblite': 'dblite'} if dbm_name != "SCons.dblite": dbm = my_import(dbm_name) else: import SCons.dblite + dbm = SCons.dblite # Ensure that we don't ignore corrupt DB files, # this was handled by calling my_import('SCons.dblite') @@ -548,6 +631,8 @@ else: else: Do_SConsignDir(a) + if Warns: + print("NOTE: there were %d warnings, please check output" % Warns) sys.exit(0) # Local Variables: diff --git a/src/setup.py b/src/setup.py index 7a2b84a..2d021c2 100644..100755 --- a/src/setup.py +++ b/src/setup.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,6 +20,17 @@ # 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 +import distutils.command.install_data +import distutils.command.install +import distutils.core +import distutils +# import setuptools """ NOTE: Installed SCons is not importable like usual Python packages. It is executed explicitly with command line scripts. This allows multiple @@ -32,15 +43,14 @@ NOTE: Installed SCons is not importable like usual Python packages. It is below is dedicated to make it happen on various platforms. """ -from __future__ import print_function -__revision__ = "src/setup.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/setup.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import stat import sys -Version = "3.0.0" +Version = "3.0.5" man_pages = [ 'scons.1', @@ -66,25 +76,6 @@ if not sys.platform == 'win32': else: is_win32 = 1 -import distutils -import distutils.core -import distutils.command.install -import distutils.command.install_data -import distutils.command.install_lib -import distutils.command.install_scripts -import distutils.command.build_scripts -import distutils.msvccompiler - - -def get_build_version(): - """ monkey patch distutils msvc version if we're not on windows. - We need to use vc version 9 for python 2.7.x and it defaults to 6 - for non-windows platforms and there is no way to override it besides - monkey patching""" - return 9 - - -distutils.msvccompiler.get_build_version = get_build_version _install = distutils.command.install.install _install_data = distutils.command.install_data.install_data @@ -175,7 +166,7 @@ class install(_install): self.no_scons_script = 0 self.no_version_script = 0 self.install_bat = 0 - self.no_install_bat = not is_win32 + self.no_install_bat = False # not is_win32 self.install_man = 0 self.no_install_man = is_win32 self.standard_lib = 0 @@ -257,10 +248,12 @@ class install_lib(_install_lib): if Options.standalone_lib: # ...but they asked for a standalone directory. self.install_dir = os.path.join(prefix, "scons") - elif Options.version_lib or not Options.standard_lib: + elif Options.version_lib: # ...they asked for a version-specific directory, - # or they get it by default. self.install_dir = os.path.join(prefix, "scons-%s" % Version) + elif not Options.standard_lib: + # default. + self.install_dir = os.path.join(prefix, "scons") msg = "Installed SCons library modules into %s" % self.install_dir Installed.append(msg) @@ -333,8 +326,8 @@ class install_scripts(_install_scripts): scons = os.path.join(self.install_dir, base) scons_ver = scons + '-' + Version if is_win32: - scons += '.py' - scons_ver += '.py' + scons = scons + '.py' + scons_ver = scons_ver + '.py' create_version_script(src, scons_ver) create_basename_script(src, scons, scons_ver) @@ -362,7 +355,8 @@ class install_scripts(_install_scripts): # Use symbolic versions of permissions so this script doesn't fail to parse under python3.x exec_and_read_permission = stat.S_IXOTH | stat.S_IXUSR | stat.S_IXGRP | stat.S_IROTH | stat.S_IRUSR | stat.S_IRGRP mode_mask = 4095 # Octal 07777 used because python3 has different octal syntax than python 2 - mode = ((os.stat(file)[stat.ST_MODE]) | exec_and_read_permission) & mode_mask + mode = ((os.stat(file)[stat.ST_MODE]) | + exec_and_read_permission) & mode_mask # log.info("changing mode of %s to %o", file, mode) os.chmod(file, mode) # --- /distutils copy/paste --- @@ -420,18 +414,19 @@ arguments = { 'version': Version, 'description': description, 'long_description': long_description, - 'author': 'Steven Knight', - 'author_email': 'knight@baldmt.com', + 'author': 'William Deegan', + 'author_email': 'bill@baddogconsulting.com', 'url': "http://www.scons.org/", 'packages': ["SCons", "SCons.compat", "SCons.Node", - "SCons.Options", "SCons.Platform", "SCons.Scanner", "SCons.Script", "SCons.Tool", + "SCons.Tool.clangCommon", "SCons.Tool.docbook", + 'SCons.Tool.clangCommon', "SCons.Tool.MSCommon", "SCons.Tool.packaging", "SCons.Variables", @@ -512,7 +507,7 @@ arguments = { 'install_lib': install_lib, 'install_data': install_data, 'install_scripts': install_scripts, - 'build_scripts': build_scripts} + 'build_scripts': build_scripts}, } distutils.core.setup(**arguments) diff --git a/src/test_files.py b/src/test_files.py index e552751..cab1045 100644 --- a/src/test_files.py +++ b/src/test_files.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,7 +23,7 @@ # from __future__ import print_function -__revision__ = "src/test_files.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/test_files.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" """ Verify that we have certain important files in our distribution diff --git a/src/test_interrupts.py b/src/test_interrupts.py index 744677f..6b8c7c3 100644 --- a/src/test_interrupts.py +++ b/src/test_interrupts.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,7 +23,7 @@ from __future__ import print_function -__revision__ = "src/test_interrupts.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/test_interrupts.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" """ Verify that the SCons source code contains only correct handling of diff --git a/src/test_pychecker.py b/src/test_pychecker.py index b0c231f..058189e 100644 --- a/src/test_pychecker.py +++ b/src/test_pychecker.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. from __future__ import print_function -__revision__ = "src/test_pychecker.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/test_pychecker.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" """ Use pychecker to catch various Python coding errors. diff --git a/src/test_setup.py b/src/test_setup.py index af8ed66..2726465 100644 --- a/src/test_setup.py +++ b/src/test_setup.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,7 +23,7 @@ # from __future__ import print_function -__revision__ = "src/test_setup.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/test_setup.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" """ Test how the setup.py script installs SCons. diff --git a/src/test_strings.py b/src/test_strings.py index ec62e82..59ac613 100644 --- a/src/test_strings.py +++ b/src/test_strings.py @@ -1,6 +1,6 @@ #!/usr/bin/env python # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,7 +23,7 @@ # from __future__ import print_function -__revision__ = "src/test_strings.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "src/test_strings.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" """ Verify that we have proper strings like Copyright notices on all the @@ -107,8 +107,8 @@ class Checker(object): class CheckUnexpandedStrings(Checker): expressions = [ - re.compile('Copyright (c) 2001 - 2017 The SCons Foundation'), - re.compile('src/test_strings.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog'), + re.compile('Copyright (c) 2001 - 2019 The SCons Foundation'), + re.compile('src/test_strings.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog'), ] def must_be_built(self): return None @@ -208,12 +208,10 @@ check_list = [ 'doc/user/SCons-win32-install-4.jpg', 'examples', 'gentoo', - 'QMTest/classes.qmc', - 'QMTest/configuration', - 'QMTest/TestCmd.py', - 'QMTest/TestCmdTests.py', - 'QMTest/TestCommon.py', - 'QMTest/TestCommonTests.py', + 'testing/framework/TestCmd.py', + 'testing/framework/TestCmdTests.py', + 'testing/framework/TestCommon.py', + 'testing/framework/TestCommonTests.py', 'src/MANIFEST.in', 'src/setup.cfg', 'src/engine/MANIFEST.in', diff --git a/testing/README.md b/testing/README.md new file mode 100644 index 0000000..bb81ce2 --- /dev/null +++ b/testing/README.md @@ -0,0 +1,7 @@ +Here lie various files related to SCons that +can not find the place in other directories: + + buildbot.yml - Ansible playbook to set up + buildbot for running tests + + buildbot.hosts - Ansible inventory file diff --git a/testing/buildbot.hosts b/testing/buildbot.hosts new file mode 100644 index 0000000..3e0be7d --- /dev/null +++ b/testing/buildbot.hosts @@ -0,0 +1 @@ +localhost ansible_connection=local builder=xxx pass=xxx
\ No newline at end of file diff --git a/testing/buildbot.yml b/testing/buildbot.yml new file mode 100644 index 0000000..7e6bb1a --- /dev/null +++ b/testing/buildbot.yml @@ -0,0 +1,80 @@ +# Ansible playbook to setup buildbot instance. +# Edit buildbot.hosts to set builder and pass variables. +# Then exec: +# +# ansible-playbook -i buildbot.hosts buildbot.yml +# +# botuser can be overridden from command line: +# +# ansible-playbook -i hosts buildbot.yml -e 'botuser=sconsy' +# +# Tested with Ansible 1.5.0, based on +# https://github.com/SCons/scons/wiki/InstallingBuildbotSlaves +# Send questions to: +# +# anatoly techtonik <techtonik@gmail.com> +# +--- +# host is overridable with --extra-vars 'host=address' +- hosts: "{{ host | default('localhost') }}" + vars: + # botuser can be overridden with -e 'botuser=scons2' + - botuser: scons + - hgrc: /home/{{ botuser }}/.hgrc + - venv: /home/{{ botuser }}/buildbot-virtualenv + - work: /home/{{ botuser }}/buildbot-workdir + + vars_prompt: + - name: maintainer + prompt: contact details of the builbot owner + default: name <mail@example.com> + private: no + + tasks: + # --- install requirements --- + - name: ubuntu/debian - make sure mercurial is installed + apt: pkg={{ item }} + with_items: + - mercurial + - python-virtualenv + + # --- enable mercurial purge extension --- + - name: create .hgrc if necessary + stat: path={{ hgrc }} + register: st + - file: path={{ hgrc }} owner={{ botuser }} state=touch + when: not st.stat.exists + - name: enable mercurial purge extension + ini_file: dest={{ hgrc }} + section=extensions option=hgext.purge + value= + + - name: install buildbot-slave in virtualenv + pip: name=buildbot-slave virtualenv={{ venv }} + + - name: create buildbot environment + command: "{{ venv }}/bin/buildslave create-slave + {{ work }} buildbot.scons.org:9989 {{ builder }} {{ pass }} + creates={{ work }}" + sudo: yes + sudo_user: "{{ botuser }}" + + - name: set contact details of the buildbot owner + copy: dest="{{ work }}/info/admin" content="{{ maintainer }}" + notify: + - restart buildbot + + - name: update host information + copy: dest="{{ work }}/info/host" + content="{{ansible_lsb.description}} + {{'\n'}}{{ansible_machine}} + {{'\n'}}{{ansible_memtotal_mb}}MB RAM + {{'\n'}}Python {{ansible_python_version}}" + notify: + - restart buildbot + + handlers: + - name: restart buildbot + command: "{{ venv }}/bin/buildslave restart {{ work }}" + sudo: yes + sudo_user: "{{ botuser }}" diff --git a/QMTest/README.txt b/testing/framework/README.txt index c644565..0e0f2bb 100644 --- a/QMTest/README.txt +++ b/testing/framework/README.txt @@ -46,13 +46,5 @@ the pieces here are local to SCons. Test infrastructure for the sconsign.py script. - classes.qmc - configuration - scons-tdb.py - - Pieces for the use of QMTest to test SCons. We're moving away - from this infrastructure, in no small part because we're not - really using it as originally envisioned. - -Copyright (c) 2001 - 2017 The SCons Foundation -QMTest/README.txt rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog +Copyright (c) 2001 - 2019 The SCons Foundation +testing/framework/README.txt 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog diff --git a/QMTest/SConscript b/testing/framework/SConscript index 4107862..535f187 100644 --- a/QMTest/SConscript +++ b/testing/framework/SConscript @@ -3,7 +3,7 @@ # # -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -30,9 +30,6 @@ import os.path Import('build_dir', 'env') files = [ - 'classes.qmc', - 'configuration', - 'scons_tdb.py', 'TestCmd.py', 'TestCommon.py', 'TestRuntest.py', @@ -53,9 +50,9 @@ def copy(target, source, env): for file in files: # Guarantee that real copies of these files always exist in - # build/QMTest. If there's a symlink there, then this is an Aegis + # build/testing/framework. If there's a symlink there, then this is an Aegis # build and we blow them away now so that they'll get "built" later. - p = os.path.join(build_dir, 'QMTest', file) + p = os.path.join(build_dir, 'testing','framework', file) if os.path.islink(p): os.unlink(p) if not os.path.isabs(p): diff --git a/QMTest/TestCmd.py b/testing/framework/TestCmd.py index 0aab9a8..a6a8045 100644 --- a/QMTest/TestCmd.py +++ b/testing/framework/TestCmd.py @@ -309,7 +309,7 @@ import types IS_PY3 = sys.version_info[0] == 3 IS_WINDOWS = sys.platform == 'win32' - +IS_64_BIT = sys.maxsize > 2**32 class null(object): pass @@ -1093,7 +1093,13 @@ class TestCmd(object): diff_function = self.simple_diff if name is not None: print(self.banner(name)) - args = (a.splitlines(), b.splitlines()) + args + + if not is_List(a): + a=a.splitlines() + if not is_List(b): + b=b.splitlines() + + args = (a, b) + args for line in diff_function(*args, **kw): print(line) @@ -1221,7 +1227,7 @@ class TestCmd(object): the temporary working directories to be preserved for all conditions. """ - if conditions is (): + if not conditions: conditions = ('pass_test', 'fail_test', 'no_result') for cond in conditions: self._preserve[cond] = 1 @@ -1247,9 +1253,11 @@ class TestCmd(object): if mode[0] != 'r': raise ValueError("mode must begin with 'r'") if IS_PY3 and 'b' not in mode: - return open(file, mode, newline=newline).read() + with open(file, mode, newline=newline) as f: + return f.read() else: - return open(file, mode).read() + with open(file, mode) as f: + return f.read() def rmdir(self, dir): """Removes the specified dir name. @@ -1577,18 +1585,28 @@ class TestCmd(object): return self._stderr[run] def stdout(self, run=None): - """Returns the standard output from the specified run number. - If there is no specified run number, then returns the standard - output of the last run. If the run number is less than zero, - then returns the standard output from that many runs back from - the current run. + """ + Returns the stored standard output from a given run. + + Args: + run: run number to select. If run number is omitted, + return the standard output of the most recent run. + If negative, use as a relative offset, so that -2 + means the run two prior to the most recent. + + Returns: + selected stdout string or None if there are no + stored runs. """ if not run: run = len(self._stdout) elif run < 0: run = len(self._stdout) + run run = run - 1 - return self._stdout[run] + try: + return self._stdout[run] + except IndexError: + return None def subdir(self, *subdirs): """Create new subdirectories under the temporary working @@ -1610,7 +1628,8 @@ class TestCmd(object): new = os.path.join(self.workdir, sub) try: os.mkdir(new) - except OSError: + except OSError as e: + print("Got error :%s"%e) pass else: count = count + 1 diff --git a/QMTest/TestCmdTests.py b/testing/framework/TestCmdTests.py index b9226fd..b9226fd 100644 --- a/QMTest/TestCmdTests.py +++ b/testing/framework/TestCmdTests.py diff --git a/QMTest/TestCommon.py b/testing/framework/TestCommon.py index a475ddc..ca4a147 100644 --- a/QMTest/TestCommon.py +++ b/testing/framework/TestCommon.py @@ -206,6 +206,28 @@ def separate_files(flist): missing.append(f) return existing, missing +def contains(seq, subseq, find): + # Returns True or False. + if find is None: + return subseq in seq + else: + f = find(seq, subseq) + return f not in (None, -1) and f is not False + +def find_index(seq, subseq, find): + # Returns either an index of the subseq within the seq, or None. + # Accepts a function find(seq, subseq), which returns an integer on success + # and either: None, False, or -1, on failure. + if find is None: + try: + return seq.index(subseq) + except ValueError: + return None + else: + i = find(seq, subseq) + return None if (i in (None, -1) or i is False) else i + + if os.name == 'posix': def _failed(self, status = 0): if self.status is None or status is None: @@ -242,11 +264,16 @@ class TestCommon(TestCmd): if options: if arguments is None: return options + + # If not list, then split into lists + # this way we're not losing arguments specified with + # Spaces in quotes. if isinstance(options, str): - options = [options] + options = options.split() if isinstance(arguments, str): - arguments = [arguments] - arguments = ' '.join(options + arguments) + arguments = arguments.split() + arguments = options + arguments + return arguments def must_be_writable(self, *files): @@ -265,24 +292,35 @@ class TestCommon(TestCmd): print("Unwritable files: `%s'" % "', `".join(unwritable)) self.fail_test(missing + unwritable) - def must_contain(self, file, required, mode = 'rb', find = None): - """Ensures that the specified file contains the required text. + def must_contain(self, file, required, mode='rb', find=None): + """Ensures specified file contains the required text. + + Args: + file (string): name of file to search in. + required (string): text to search for. For the default + find function, type must match the return type from + reading the file; current implementation will convert. + mode (string): file open mode. + find (func): optional custom search routine. Must take the + form "find(output, line)" non-negative integer on success + and None, False, or -1, on failure. + + Calling test exits FAILED if search result is false """ + if 'b' in mode: + # Python 3: reading a file in binary mode returns a + # bytes object. We cannot find the index of a different + # (str) type in that, so convert. + required = to_bytes(required) file_contents = self.read(file, mode) - if find is None: - def find(o, l): - try: - return o.index(l) - except ValueError: - return None - contains = find(file_contents, required) - if not contains: + + if not contains(file_contents, required, find): print("File `%s' does not contain required string." % file) print(self.banner('Required string ')) print(required) print(self.banner('%s contents ' % file)) print(file_contents) - self.fail_test(not contains) + self.fail_test() def must_contain_all(self, output, input, title=None, find=None): """Ensures that the specified output string (first argument) @@ -292,20 +330,13 @@ class TestCommon(TestCmd): of output being searched, and only shows up in failure output. An optional fourth argument can be used to supply a different - function, of the form "find(line, output), to use when searching + function, of the form "find(output, line)", to use when searching for lines in the output. """ - if find is None: - def find(o, i): - try: - return o.index(i) - except ValueError: - return None - if is_List(output): output = os.newline.join(output) - if find(output, input) is None: + if not contains(output, input, find): if title is None: title = 'output' print('Missing expected input from {}:'.format(title)) @@ -322,21 +353,15 @@ class TestCommon(TestCmd): of output being searched, and only shows up in failure output. An optional fourth argument can be used to supply a different - function, of the form "find(line, output), to use when searching + function, of the form "find(output, line)", to use when searching for lines in the output. """ - if find is None: - def find(o, l): - try: - return o.index(l) - except ValueError: - return None missing = [] if is_List(output): output = '\n'.join(output) for line in lines: - if find(output, line) is None: + if not contains(output, line, find): missing.append(line) if missing: @@ -357,17 +382,11 @@ class TestCommon(TestCmd): of output being searched, and only shows up in failure output. An optional fourth argument can be used to supply a different - function, of the form "find(line, output), to use when searching + function, of the form "find(output, line)", to use when searching for lines in the output. """ - if find is None: - def find(o, l): - try: - return o.index(l) - except ValueError: - return None for line in lines: - if find(output, line) is not None: + if contains(output, line, find): return if title is None: @@ -388,7 +407,7 @@ class TestCommon(TestCmd): of output being searched, and only shows up in failure output. An optional fourth argument can be used to supply a different - function, of the form "find(line, output), to use when searching + function, of the form "find(output, line)", to use when searching for lines in the output. The function must return the index of the found line in the output, or None if the line is not found. """ @@ -400,19 +419,13 @@ class TestCommon(TestCmd): if sorted(out) == sorted(exp): # early out for exact match return - if find is None: - def find(o, l): - try: - return o.index(l) - except ValueError: - return None missing = [] for line in exp: - found = find(out, line) - if found is None: + i = find_index(out, line, find) + if i is None: missing.append(line) else: - out.pop(found) + out.pop(i) if not missing and not out: # all lines were matched @@ -491,20 +504,14 @@ class TestCommon(TestCmd): """Ensures that the specified file doesn't contain the banned text. """ file_contents = self.read(file, mode) - if find is None: - def find(o, l): - try: - return o.index(l) - except ValueError: - return None - contains = find(file_contents, banned) - if contains: + + if contains(file_contents, banned, find): print("File `%s' contains banned string." % file) print(self.banner('Banned string ')) print(banned) print(self.banner('%s contents ' % file)) print(file_contents) - self.fail_test(contains) + self.fail_test() def must_not_contain_any_line(self, output, lines, title=None, find=None): """Ensures that the specified output string (first argument) @@ -514,18 +521,12 @@ class TestCommon(TestCmd): of output being searched, and only shows up in failure output. An optional fourth argument can be used to supply a different - function, of the form "find(line, output), to use when searching + function, of the form "find(output, line)", to use when searching for lines in the output. """ - if find is None: - def find(o, l): - try: - return o.index(l) - except ValueError: - return None unexpected = [] for line in lines: - if find(output, line) is not None: + if contains(output, line, find): unexpected.append(line) if unexpected: @@ -680,7 +681,7 @@ class TestCommon(TestCmd): The parameters are the same as the base TestCmd.run() method, with the addition of: - options Extra options that get appended to the beginning + options Extra options that get prepended to the beginning of the arguments. stdout The expected standard output from diff --git a/QMTest/TestCommonTests.py b/testing/framework/TestCommonTests.py index 7949cb8..c54f33f 100644 --- a/QMTest/TestCommonTests.py +++ b/testing/framework/TestCommonTests.py @@ -306,6 +306,23 @@ class must_contain_TestCase(TestCommonTestCase): stderr = run_env.stderr() assert stderr == "PASSED\n", stderr + def test_success_index_0(self): + """Test must_contain(): success at index 0""" + run_env = self.run_env + + script = lstrip("""\ + from TestCommon import TestCommon + tc = TestCommon(workdir='') + tc.write('file1', "file1 contents\\n") + tc.must_contain('file1', "file1 c") + tc.pass_test() + """) + run_env.run(program=sys.executable, stdin=script) + stdout = run_env.stdout() + assert stdout == "", stdout + stderr = run_env.stderr() + assert stderr == "PASSED\n", stderr + def test_file_missing(self): """Test must_contain(): file missing""" run_env = self.run_env @@ -1145,6 +1162,9 @@ class must_match_TestCase(TestCommonTestCase): """) expect = lstrip("""\ + match_re: mismatch at line 0: + search re='^file1$' + line='file1 does not match' Unexpected contents of `file1' contents ======================================================================= 1c1 @@ -1324,6 +1344,31 @@ class must_not_contain_TestCase(TestCommonTestCase): stderr = run_env.stderr() assert stderr.find("FAILED") != -1, stderr + def test_failure_index_0(self): + """Test must_not_contain(): failure at index 0""" + run_env = self.run_env + + script = lstrip("""\ + from TestCommon import TestCommon + tc = TestCommon(workdir='') + tc.write('file1', "file1 does contain contents\\n") + tc.must_not_contain('file1', "file1 does") + tc.run() + """) + expect = lstrip("""\ + File `file1' contains banned string. + Banned string ================================================================== + file1 does + file1 contents ================================================================= + file1 does contain contents + + """) + run_env.run(program=sys.executable, stdin=script) + stdout = run_env.stdout() + assert stdout == expect, repr(stdout) + stderr = run_env.stderr() + assert stderr.find("FAILED") != -1, stderr + def test_mode(self): """Test must_not_contain(): mode""" run_env = self.run_env @@ -1812,6 +1857,7 @@ class run_TestCase(TestCommonTestCase): """) expect_stdout = lstrip("""\ + match_re: expected 1 lines, found 2 STDOUT ========================================================================= STDERR ========================================================================= @@ -2024,6 +2070,9 @@ class run_TestCase(TestCommonTestCase): """) expect_stdout = lstrip("""\ + match_re: mismatch at line 0: + search re='^Not found$' + line='%(pass_script)s: STDOUT: []' STDOUT ========================================================================= 1c1 < Not found @@ -2053,6 +2102,9 @@ class run_TestCase(TestCommonTestCase): """) expect_stdout = lstrip("""\ + match_re: mismatch at line 0: + search re='^Not found$' + line='%(stderr_script)s: STDERR: []' STDOUT ========================================================================= STDERR ========================================================================= @@ -2286,14 +2338,14 @@ class variables_TestCase(TestCommonTestCase): 'dll_suffix', ] - script = "from __future__ import print_function" + \ + script = "from __future__ import print_function\n" + \ "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" + \ + script = "from __future__ import print_function\n" + \ "from TestCommon import *\n" + \ '\n'.join([ "print(%s)" % v for v in variables ]) run_env.run(program=sys.executable, stdin=script) diff --git a/QMTest/TestRuntest.py b/testing/framework/TestRuntest.py index f2256de..64dcf17 100644 --- a/QMTest/TestRuntest.py +++ b/testing/framework/TestRuntest.py @@ -12,9 +12,9 @@ from those classes, as well as any overridden or additional methods or attributes defined in this subclass. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation -__revision__ = "QMTest/TestRuntest.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "testing/framework/TestRuntest.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path @@ -27,6 +27,7 @@ from TestCommon import __all__ __all__.extend([ 'TestRuntest', 'pythonstring', + 'pythonflags', ]) if re.search('\s', python): @@ -34,7 +35,9 @@ if re.search('\s', python): else: pythonstring = python pythonstring = pythonstring.replace('\\', '\\\\') - +pythonflags = '' +if sys.version_info[0] < 3: + pythonflags = ' -tt' failing_test_template = """\ import sys @@ -97,14 +100,17 @@ class TestRuntest(TestCommon): The superclass TestCommon.__init__() will change directory (chdir) to the workspace directory, so an explicit "chdir = '.'" on all of the run() method calls is not necessary. This initialization - also copies the runtest.py and QMTest/ subdirectory tree to the + also copies the runtest.py and testing/framework/ subdirectory tree to the temporary directory, duplicating how this test infrastructure appears in a normal workspace. """ if 'program' not in kw: kw['program'] = 'runtest.py' if 'interpreter' not in kw: - kw['interpreter'] = [python, '-tt'] + kw['interpreter'] = [python,] + if sys.version_info[0] < 3: + kw['interpreter'].append('-tt') + if 'match' not in kw: kw['match'] = match_exact if 'workdir' not in kw: @@ -115,7 +121,7 @@ class TestRuntest(TestCommon): except KeyError: things_to_copy = [ 'runtest.py', - 'QMTest', + 'testing/framework', ] else: del kw['things_to_copy'] diff --git a/QMTest/TestSCons.py b/testing/framework/TestSCons.py index c0b4ebc..e415291 100644 --- a/QMTest/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -12,10 +12,10 @@ from those classes, as well as any overridden or additional methods or attributes defined in this subclass. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation from __future__ import division, print_function -__revision__ = "QMTest/TestSCons.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "testing/framework/TestSCons.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import re @@ -35,16 +35,16 @@ from TestCmd import PIPE # here provides some independent verification that what we packaged # conforms to what we expect. -default_version = '3.0.0' +default_version = '3.0.5' python_version_unsupported = (2, 6, 0) python_version_deprecated = (2, 7, 0) # In the checked-in source, the value of SConsVersion in the following # line must remain "__ VERSION __" (without the spaces) so the built -# version in build/QMTest/TestSCons.py contains the actual version +# version in build/testing/framework/TestSCons.py contains the actual version # string of the packages that have been built. -SConsVersion = '3.0.0' +SConsVersion = '3.0.5' if SConsVersion == '__' + 'VERSION' + '__': SConsVersion = default_version @@ -247,7 +247,9 @@ 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, '-tt'] + kw['interpreter'] = [python,] + if sys.version_info[0] < 3: + kw['interpreter'].append('-tt') if 'match' not in kw: kw['match'] = match_exact if 'workdir' not in kw: @@ -293,16 +295,25 @@ class TestSCons(TestCommon): def detect(self, var, prog=None, ENV=None, norm=None): """ - Detect a program named 'prog' by first checking the construction - variable named 'var' and finally searching the path used by - SCons. If either method fails to detect the program, then false - is returned, otherwise the full path to prog is returned. If - prog is None, then the value of the environment variable will be - used as prog. + Return the detected path to a tool program. + + Searches first the named construction variable, then + the SCons path. + + Args: + var: name of construction variable to check for tool name. + prog: tool program to check for. + ENV: if present, kwargs to initialize an environment that + will be created to perform the lookup. + norm: if true, normalize any returned path looked up in + the environment to use UNIX-style path separators. + + Returns: full path to the tool, or None. + """ env = self.Environment(ENV) if env: - v = env.subst('$'+var) + v = env.subst('$' + var) if not v: return None if prog is None: @@ -310,7 +321,7 @@ class TestSCons(TestCommon): if v != prog: return None result = env.WhereIs(prog) - if norm and os.sep != '/': + if result and norm and os.sep != '/': result = result.replace(os.sep, '/') return result @@ -333,7 +344,7 @@ class TestSCons(TestCommon): return None return env.Detect([prog]) - def where_is(self, prog, path=None): + def where_is(self, prog, path=None, pathext=None): """ Given a program, search for it in the specified external PATH, or in the actual external PATH if none is specified. @@ -343,26 +354,14 @@ class TestSCons(TestCommon): if self.external: if isinstance(prog, str): prog = [prog] - import stat - paths = path.split(os.pathsep) for p in prog: - for d in paths: - f = os.path.join(d, p) - if os.path.isfile(f): - try: - st = os.stat(f) - except OSError: - # os.stat() raises OSError, not IOError if the file - # doesn't exist, so in this case we let IOError get - # raised so as to not mask possibly serious disk or - # network issues. - continue - if stat.S_IMODE(st[stat.ST_MODE]) & 0o111: - return os.path.normpath(f) + result = TestCmd.where_is(self, p, path, pathext) + if result: + return os.path.normpath(result) else: import SCons.Environment env = SCons.Environment.Environment() - return env.WhereIs(prog, path) + return env.WhereIs(prog, path, pathext) return None @@ -418,6 +417,10 @@ class TestSCons(TestCommon): # 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. + """ s = "" for arg in arguments.split(): s = s + "scons: `%s' is up to date.\n" % arg @@ -564,7 +567,7 @@ class TestSCons(TestCommon): Returns a Python error line for output comparisons. The exec of the traceback line gives us the correct format for - this version of Python. + this version of Python. File "<string>", line 1, <module> @@ -607,7 +610,7 @@ class TestSCons(TestCommon): pattern = to_bytes(pattern) repl = to_bytes(repl) return re.sub(pattern, repl, str, count, flags) - + def normalize_pdf(self, s): s = self.to_bytes_re_sub(r'/(Creation|Mod)Date \(D:[^)]*\)', r'/\1Date (D:XXXX)', s) @@ -692,20 +695,29 @@ class TestSCons(TestCommon): env = SCons.Environment.Environment() self._java_env[version] = env - if version: - patterns = [ - '/usr/java/jdk%s*/bin' % version, - '/usr/lib/jvm/*-%s*/bin' % version, - '/usr/local/j2sdk%s*/bin' % version, - ] + if sys.platform == 'win32': + patterns = [ + 'C:/Program Files*/Java/jdk%s*/bin'%version, + ] + else: + patterns = [ + '/usr/java/jdk%s*/bin' % version, + '/usr/lib/jvm/*-%s*/bin' % version, + '/usr/local/j2sdk%s*/bin' % version, + ] java_path = self.paths(patterns) + [env['ENV']['PATH']] else: - patterns = [ - '/usr/java/latest/bin', - '/usr/lib/jvm/*/bin', - '/usr/local/j2sdk*/bin', - ] + if sys.platform == 'win32': + patterns = [ + 'C:/Program Files*/Java/jdk*/bin', + ] + else: + patterns = [ + '/usr/java/latest/bin', + '/usr/lib/jvm/*/bin', + '/usr/local/j2sdk*/bin', + ] java_path = self.paths(patterns) + [env['ENV']['PATH']] env['ENV']['PATH'] = os.pathsep.join(java_path) @@ -784,6 +796,16 @@ class TestSCons(TestCommon): print("Could not determine JAVA_HOME: %s is not a directory" % home) self.fail_test() + def java_mac_check(self, where_java_bin, java_bin_name): + # on Mac there is a place holder java installed to start the java install process + # so we need to check the output in this case, more info here: + # http://anas.pk/2015/09/02/solution-no-java-runtime-present-mac-yosemite/ + sp = subprocess.Popen([where_java_bin, "-version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = sp.communicate() + sp.wait() + if("No Java runtime" in str(stderr)): + self.skip_test("Could not find Java " + java_bin_name + ", skipping test(s).\n") + def java_where_jar(self, version=None): ENV = self.java_ENV(version) if self.detect_tool('jar', ENV=ENV): @@ -792,6 +814,9 @@ class TestSCons(TestCommon): where_jar = self.where_is('jar', ENV['PATH']) if not where_jar: self.skip_test("Could not find Java jar, skipping test(s).\n") + elif sys.platform == "darwin": + self.java_mac_check(where_jar, 'jar') + return where_jar def java_where_java(self, version=None): @@ -800,8 +825,12 @@ class TestSCons(TestCommon): """ ENV = self.java_ENV(version) where_java = self.where_is('java', ENV['PATH']) + if not where_java: self.skip_test("Could not find Java java, skipping test(s).\n") + elif sys.platform == "darwin": + self.java_mac_check(where_java, 'java') + return where_java def java_where_javac(self, version=None): @@ -815,6 +844,9 @@ class TestSCons(TestCommon): where_javac = self.where_is('javac', ENV['PATH']) if not where_javac: self.skip_test("Could not find Java javac, skipping test(s).\n") + elif sys.platform == "darwin": + self.java_mac_check(where_javac, 'javac') + self.run(program = where_javac, arguments = '-version', stderr=None, @@ -824,11 +856,15 @@ class TestSCons(TestCommon): fmt = "Could not find javac for Java version %s, skipping test(s).\n" self.skip_test(fmt % version) else: - m = re.search(r'javac (\d\.\d)', self.stderr()) + m = re.search(r'javac (\d\.*\d)', self.stderr()) + # Java 11 outputs this to stdout + if not m: + m = re.search(r'javac (\d\.*\d)', self.stdout()) + if m: version = m.group(1) self.javac_is_gcj = False - elif self.stderr().find('gcj'): + elif self.stderr().find('gcj') != -1: version='1.2' self.javac_is_gcj = True else: @@ -856,7 +892,7 @@ 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): @@ -886,7 +922,8 @@ for opt, arg in cmd_opts: else: opt_string = opt_string + ' ' + opt output.write("/* mymoc.py%s */\\n" % opt_string) for a in args: - contents = open(a, 'r').read() + with open(a, 'r') as f: + contents = f.read() a = a.replace('\\\\', '\\\\\\\\') subst = r'{ my_qt_symbol( "' + a + '\\\\n" ); }' if impl: @@ -1016,6 +1053,11 @@ SConscript( sconscript ) # to use cygwin compilers on cmd.exe -> uncomment following line #Configure_lib = 'm' + def coverage_run(self): + """ Check if the the tests are being run under coverage. + """ + return 'COVERAGE_PROCESS_START' in os.environ or 'COVERAGE_FILE' in os.environ + def skip_if_not_msvc(self, check_platform=True): """ Check whether we are on a Windows platform and skip the test if not. This check can be omitted by setting @@ -1044,7 +1086,7 @@ SConscript( sconscript ) 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. + 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. @@ -1126,19 +1168,19 @@ SConscript( sconscript ) sconstruct = sconstruct log = r'file\ \S*%s\,line \d+:' % re.escape(sconstruct) + ls - if doCheckLog: + if doCheckLog: lastEnd = matchPart(log, logfile, lastEnd) log = "\t" + re.escape("Configure(confdir = %s)" % sconf_dir) + ls - if doCheckLog: + if doCheckLog: lastEnd = matchPart(log, logfile, lastEnd) - + rdstr = "" cnt = 0 for check,result,cache_desc in zip(checks, results, cached): log = re.escape("scons: Configure: " + check) + ls - if doCheckLog: + if doCheckLog: lastEnd = matchPart(log, logfile, lastEnd) log = "" @@ -1183,7 +1225,7 @@ SConscript( sconscript ) rdstr = rdstr + re.escape(check) + re.escape(result) + "\n" log=log + re.escape("scons: Configure: " + result) + ls + ls - if doCheckLog: + if doCheckLog: lastEnd = matchPart(log, logfile, lastEnd) log = "" @@ -1222,41 +1264,83 @@ SConscript( sconscript ) # see also sys.prefix documentation return python_minor_version_string() - def get_platform_python_info(self): + def get_platform_python_info(self, python_h_required=False): """ Returns a path to a Python executable suitable for testing on - this platform and its associated include path, library path, - and library name. + this platform and its associated include path, library path and + library name. + + If the Python executable or Python header (if required) + is not found, the test is skipped. + + Returns a tuple: + (path to python, include path, library path, library name) """ - python = self.where_is('python') + python = os.environ.get('python_executable', self.where_is('python')) if not python: self.skip_test('Can not find installed "python", skipping test.\n') - self.run(program = python, stdin = """\ -import os, sys -try: - if sys.platform == 'win32': - py_ver = 'python%d%d' % sys.version_info[:2] - else: - py_ver = 'python%d.%d' % sys.version_info[:2] -except AttributeError: - py_ver = 'python' + sys.version[:3] -# print include and lib path + # construct a program to run in the intended environment + # in order to fetch the characteristics of that Python. + # Windows Python doesn't store all the info in config vars. + if sys.platform == 'win32': + self.run(program=python, stdin="""\ +import sysconfig, sys, os.path +py_ver = 'python%d%d' % sys.version_info[:2] +# use distutils to help find include and lib path +# TODO: PY3 fine to use sysconfig.get_config_var("INCLUDEPY") try: import distutils.sysconfig exec_prefix = distutils.sysconfig.EXEC_PREFIX - print(distutils.sysconfig.get_python_inc()) + include = distutils.sysconfig.get_python_inc() + print(include) lib_path = os.path.join(exec_prefix, 'libs') if not os.path.exists(lib_path): + # check for virtualenv path. + # this might not build anything different than first try. + def venv_path(): + if hasattr(sys, 'real_prefix'): + return sys.real_prefix + if hasattr(sys, 'base_prefix'): + return sys.base_prefix + lib_path = os.path.join(venv_path(), 'libs') + if not os.path.exists(lib_path): + # not clear this is useful: 'lib' does not contain linkable libs lib_path = os.path.join(exec_prefix, 'lib') print(lib_path) except: - print(os.path.join(sys.prefix, 'include', py_ver)) - print(os.path.join(sys.prefix, 'lib', py_ver, 'config')) + include = os.path.join(sys.prefix, 'include', py_ver) + print(include) + lib_path = os.path.join(sys.prefix, 'lib', py_ver, 'config') + print(lib_path) print(py_ver) +Python_h = os.path.join(include, "Python.h") +if os.path.exists(Python_h): + print(Python_h) +else: + print("False") +""") + else: + self.run(program=python, stdin="""\ +import sys, sysconfig, os.path +include = sysconfig.get_config_var("INCLUDEPY") +print(include) +print(sysconfig.get_config_var("LIBDIR")) +py_library_ver = sysconfig.get_config_var("LDVERSION") +if not py_library_ver: + py_library_ver = '%d.%d' % sys.version_info[:2] +print("python"+py_library_ver) +Python_h = os.path.join(include, "Python.h") +if os.path.exists(Python_h): + print(Python_h) +else: + print("False") """) + incpath, libpath, libname, python_h = self.stdout().strip().split('\n') + if python_h == "False" and python_h_required: + self.skip_test('Can not find required "Python.h", skipping test.\n') - return [python] + self.stdout().strip().split('\n') + return (python, incpath, libpath, libname) def start(self, *args, **kw): """ diff --git a/QMTest/TestSConsMSVS.py b/testing/framework/TestSConsMSVS.py index 30eea76..09cb5ee 100644 --- a/QMTest/TestSConsMSVS.py +++ b/testing/framework/TestSConsMSVS.py @@ -13,9 +13,9 @@ as well as any overridden or additional methods or attributes defined in this subclass. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation -__revision__ = "QMTest/TestSConsMSVS.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "testing/framework/TestSConsMSVS.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import sys @@ -536,6 +536,26 @@ Global EndGlobal """ +expected_slnfile_14_1 = """\ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Test.vcxproj", "Test.vcxproj", "{39A97E1F-1A52-8954-A0B1-A10A8487545E}" +EndProject +Global +<SCC_SLN_INFO> +\tGlobalSection(SolutionConfigurationPlatforms) = preSolution +\t\tRelease|Win32 = Release|Win32 +\tEndGlobalSection +\tGlobalSection(ProjectConfigurationPlatforms) = postSolution +\t\t{39A97E1F-1A52-8954-A0B1-A10A8487545E}.Release|Win32.ActiveCfg = Release|Win32 +\t\t{39A97E1F-1A52-8954-A0B1-A10A8487545E}.Release|Win32.Build.0 = Release|Win32 +\tEndGlobalSection +\tGlobalSection(SolutionProperties) = preSolution +\t\tHideSolutionNode = FALSE +\tEndGlobalSection +EndGlobal +""" + expected_vcprojfile_8_0 = """\ <?xml version="1.0" encoding="Windows-1252"?> <VisualStudioProject @@ -907,6 +927,71 @@ expected_vcprojfile_14_0 = """\ </Project> """ +expected_vcprojfile_14_1 = """\ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> +\t<ItemGroup Label="ProjectConfigurations"> +\t\t<ProjectConfiguration Include="Release|Win32"> +\t\t\t<Configuration>Release</Configuration> +\t\t\t<Platform>Win32</Platform> +\t\t</ProjectConfiguration> +\t</ItemGroup> +\t<PropertyGroup Label="Globals"> +\t\t<ProjectGuid>{39A97E1F-1A52-8954-A0B1-A10A8487545E}</ProjectGuid> +<SCC_VCPROJ_INFO> +\t\t<RootNamespace>Test</RootNamespace> +\t\t<Keyword>MakeFileProj</Keyword> +\t</PropertyGroup> +\t<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.Default.props" /> +\t<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> +\t\t<ConfigurationType>Makefile</ConfigurationType> +\t\t<UseOfMfc>false</UseOfMfc> +\t\t<PlatformToolset>v141</PlatformToolset> +\t</PropertyGroup> +\t<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.props" /> +\t<ImportGroup Label="ExtensionSettings"> +\t</ImportGroup> +\t<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> +\t\t<Import Project="$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> +\t</ImportGroup> +\t<PropertyGroup Label="UserMacros" /> +\t<PropertyGroup> +\t<_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion> +\t\t<NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"</NMakeBuildCommandLine> +\t\t<NMakeReBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct "Test.exe"</NMakeReBuildCommandLine> +\t\t<NMakeCleanCommandLine Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">echo Starting SCons && "<PYTHON>" -c "<SCONS_SCRIPT_MAIN_XML>" -C "<WORKPATH>" -f SConstruct -c "Test.exe"</NMakeCleanCommandLine> +\t\t<NMakeOutput Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Test.exe</NMakeOutput> +\t\t<NMakePreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">DEF1;DEF2;DEF3=1234</NMakePreprocessorDefinitions> +\t\t<NMakeIncludeSearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">inc1;inc2</NMakeIncludeSearchPath> +\t\t<NMakeForcedIncludes Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedIncludes)</NMakeForcedIncludes> +\t\t<NMakeAssemblySearchPath Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeAssemblySearchPath)</NMakeAssemblySearchPath> +\t\t<NMakeForcedUsingAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(NMakeForcedUsingAssemblies)</NMakeForcedUsingAssemblies> +\t</PropertyGroup> +\t<ItemGroup> +\t\t<ClInclude Include="sdk_dir\sdk.h" /> +\t</ItemGroup> +\t<ItemGroup> +\t\t<ClInclude Include="test.h" /> +\t</ItemGroup> +\t<ItemGroup> +\t\t<None Include="readme.txt" /> +\t</ItemGroup> +\t<ItemGroup> +\t\t<None Include="test.rc" /> +\t</ItemGroup> +\t<ItemGroup> +\t\t<ClCompile Include="test1.cpp" /> +\t\t<ClCompile Include="test2.cpp" /> +\t</ItemGroup> +\t<ItemGroup> +\t\t<None Include="SConstruct" /> +\t</ItemGroup> +\t<Import Project="$(VCTargetsPath)\\Microsoft.Cpp.targets" /> +\t<ImportGroup Label="ExtensionTargets"> +\t</ImportGroup> +</Project> +""" + SConscript_contents_8_0 = """\ env=Environment(platform='win32', tools=['msvs'], MSVS_VERSION='8.0', CPPDEFINES=['DEF1', 'DEF2',('DEF3','1234')], @@ -1022,6 +1107,29 @@ env.MSVSProject(target = 'Test.vcxproj', variant = 'Release') """ +SConscript_contents_14_1 = """\ +env=Environment(platform='win32', tools=['msvs'], MSVS_VERSION='14.1', + CPPDEFINES=['DEF1', 'DEF2',('DEF3','1234')], + CPPPATH=['inc1', 'inc2'], + HOST_ARCH='%(HOST_ARCH)s') + +testsrc = ['test1.cpp', 'test2.cpp'] +testincs = ['sdk_dir\sdk.h'] +testlocalincs = ['test.h'] +testresources = ['test.rc'] +testmisc = ['readme.txt'] + +env.MSVSProject(target = 'Test.vcxproj', + slnguid = '{SLNGUID}', + srcs = testsrc, + incs = testincs, + localincs = testlocalincs, + resources = testresources, + misc = testmisc, + buildtarget = 'Test.exe', + variant = 'Release') +""" + class TestSConsMSVS(TestSCons): """Subclass for testing MSVS-specific portions of SCons.""" @@ -1039,8 +1147,8 @@ class TestSConsMSVS(TestSCons): input = """\ import SCons import SCons.Tool.MSCommon -print("self.scons_version =", repr(SCons.__%s__)) -print("self._msvs_versions =", str(SCons.Tool.MSCommon.query_versions())) +print("self.scons_version =%%s"%%repr(SCons.__%s__)) +print("self._msvs_versions =%%s"%%str(SCons.Tool.MSCommon.query_versions())) """ % 'version' self.run(arguments = '-n -q -Q -f -', stdin = input) diff --git a/QMTest/TestSCons_time.py b/testing/framework/TestSCons_time.py index f74906a..624eb4c 100644 --- a/QMTest/TestSCons_time.py +++ b/testing/framework/TestSCons_time.py @@ -11,9 +11,9 @@ from those classes, as well as any overridden or additional methods or attributes defined in this subclass. """ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation -__revision__ = "QMTest/TestSCons_time.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "testing/framework/TestSCons_time.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" import os import os.path @@ -24,8 +24,7 @@ from TestCommon import __all__ # some of the scons_time tests may need regex-based matching: from TestSCons import search_re, search_re_in_list -__all__.extend([ 'TestSCons_time', - ]) +__all__.extend(['TestSCons_time',]) SConstruct = """\ from __future__ import print_function @@ -37,30 +36,35 @@ scons_py = """\ #!/usr/bin/env python import os import sys + def write_args(fp, args): fp.write(args[0] + '\\n') for arg in args[1:]: fp.write(' ' + arg + '\\n') + write_args(sys.stdout, sys.argv) for arg in sys.argv[1:]: if arg[:10] == '--profile=': - profile = open(arg[10:], 'w') - profile.write('--profile\\n') - write_args(profile, sys.argv) + with open(arg[10:], 'w') as profile: + profile.write('--profile\\n') + write_args(profile, sys.argv) break sys.stdout.write('SCONS_LIB_DIR = ' + os.environ['SCONS_LIB_DIR'] + '\\n') -exec(open('SConstruct', 'r').read()) +with open('SConstruct', 'r') as f: + script = f.read() +exec(script) """ aegis_py = """\ #!/usr/bin/env python import os import sys + script_dir = 'src/script' if not os.path.exists(script_dir): os.makedirs(script_dir) -open(script_dir + '/scons.py', 'w').write( -r'''%s''') +with open(script_dir + '/scons.py', 'w') as f: + f.write(r'''%s''') """ % scons_py @@ -68,11 +72,25 @@ svn_py = """\ #!/usr/bin/env python import os import sys + +dir = sys.argv[-1] +script_dir = dir + '/src/script' +os.makedirs(script_dir) +with open(script_dir + '/scons.py', 'w') as f: + f.write(r'''%s''') +""" % scons_py + + +git_py = """\ +#!/usr/bin/env python +import os +import sys + dir = sys.argv[-1] script_dir = dir + '/src/script' os.makedirs(script_dir) -open(script_dir + '/scons.py', 'w').write( -r'''%s''') +with open(script_dir + '/scons.py', 'w') as f: + f.write(r'''%s''') """ % scons_py @@ -168,7 +186,9 @@ class TestSCons_time(TestCommon): kw['program'] = p if 'interpreter' not in kw: - kw['interpreter'] = [python, '-tt'] + kw['interpreter'] = [python,] + if sys.version_info[0] < 3: + kw['interpreter'].append('-tt') if 'match' not in kw: kw['match'] = match_exact @@ -239,6 +259,12 @@ class TestSCons_time(TestCommon): os.chmod(name, 0o755) return name + def write_fake_git_py(self, name): + name = self.workpath(name) + self.write(name, git_py) + os.chmod(name, 0o755) + return name + def write_sample_directory(self, archive, dir, files): dir = self.workpath(dir) for name, content in files: @@ -271,13 +297,15 @@ class TestSCons_time(TestCommon): tar = tarfile.open(archive, mode[suffix]) for name, content in files: path = os.path.join(dir, name) - open(path, 'wb').write(bytearray(content,'utf-8')) + with open(path, 'wb') as f: + f.write(bytearray(content,'utf-8')) tarinfo = tar.gettarinfo(path, path) tarinfo.uid = 111 tarinfo.gid = 111 tarinfo.uname = 'fake_user' tarinfo.gname = 'fake_group' - tar.addfile(tarinfo, open(path, 'rb')) + with open(path, 'rb') as f: + tar.addfile(tarinfo, f) tar.close() shutil.rmtree(dir) return self.workpath(archive) @@ -296,7 +324,8 @@ class TestSCons_time(TestCommon): zip = zipfile.ZipFile(archive, 'w') for name, content in files: path = os.path.join(dir, name) - open(path, 'w').write(content) + with open(path, 'w') as f: + f.write(content) zip.write(path) zip.close() shutil.rmtree(dir) diff --git a/QMTest/TestSConsign.py b/testing/framework/TestSConsign.py index df34aa8..fc72aa4 100644 --- a/QMTest/TestSConsign.py +++ b/testing/framework/TestSConsign.py @@ -1,7 +1,7 @@ -# Copyright (c) 2001 - 2017 The SCons Foundation +# Copyright (c) 2001 - 2019 The SCons Foundation from __future__ import print_function -__revision__ = "QMTest/TestSConsign.py rel_3.0.0:4395:8972f6a2f699 2017/09/18 12:59:24 bdbaddog" +__revision__ = "testing/framework/TestSConsign.py 103260fce95bf5db1c35fb2371983087d85dd611 2019-07-13 18:25:30 bdbaddog" __doc__ = """ TestSConsign.py: a testing framework for the "sconsign" script diff --git a/testing/framework/TestUnit/__init__.py b/testing/framework/TestUnit/__init__.py new file mode 100644 index 0000000..51cf972 --- /dev/null +++ b/testing/framework/TestUnit/__init__.py @@ -0,0 +1,5 @@ + +__all__ = ['TAPTestRunner', 'TAPTestResult', 'run'] + +from .taprunner import TAPTestRunner, TAPTestResult +from .cli import run diff --git a/testing/framework/TestUnit/cli.py b/testing/framework/TestUnit/cli.py new file mode 100644 index 0000000..6aec735 --- /dev/null +++ b/testing/framework/TestUnit/cli.py @@ -0,0 +1,35 @@ +""" +Choose test runner class from --runner command line option +and execute test cases. +""" + +import unittest +import optparse +import sys + + +def get_runner(): + parser = optparse.OptionParser() + parser.add_option('--runner', default='unittest.TextTestRunner', + help='name of test runner class to use') + opts, args = parser.parse_args() + + fromsplit = opts.runner.rsplit('.', 1) + if len(fromsplit) < 2: + raise ValueError('Can\'t use module as a runner') + else: + runnermod = __import__(fromsplit[0]) + return getattr(runnermod, fromsplit[1]) + + +def run(suite=None): + runner = get_runner() + if suite: + if not runner().run(suite).wasSuccessful(): + sys.exit(1) + else: + unittest.main(argv=sys.argv[:1], testRunner=runner) + + +if __name__ == '__main__': + run() diff --git a/testing/framework/TestUnit/taprunner.py b/testing/framework/TestUnit/taprunner.py new file mode 100644 index 0000000..5c2e87c --- /dev/null +++ b/testing/framework/TestUnit/taprunner.py @@ -0,0 +1,130 @@ +""" +Format unittest results in Test Anything Protocol (TAP). +http://testanything.org/tap-version-13-specification.html + +Public domain work by: + anatoly techtonik <techtonik@gmail.com> + +Changes: + 0.3 - fixed used imports that failed on Python 2.6 + 0.2 - removed unused import that failed on Python 2.6 + 0.1 - initial release +""" + +__version__ = "0.3" + + +from unittest import TextTestRunner +try: + from unittest import TextTestResult +except ImportError: + # Python 2.6 + from unittest import _TextTestResult as TextTestResult + + +class TAPTestResult(TextTestResult): + + def _process(self, test, msg, failtype = None, directive = None): + """ increase the counter, format and output TAP info """ + # counterhack: increase test counter + test.suite.tap_counter += 1 + msg = "%s %d" % (msg, test.suite.tap_counter) + if "not" not in msg: + msg += " " # justify + self.stream.write("%s - " % msg) + if failtype: + self.stream.write("%s - " % failtype) + self.stream.write("%s" % test.__class__.__name__) + self.stream.write(".%s" % test._testMethodName) + if directive: + self.stream.write(directive) + self.stream.write("\n") + # [ ] write test __doc__ (if exists) in comment + self.stream.flush() + + def addSuccess(self, test): + super(TextTestResult, self).addSuccess(test) + self._process(test, "ok") + + def addFailure(self, test, err): + super(TextTestResult, self).addFailure(test, err) + self._process(test, "not ok", "FAIL") + # [ ] add structured data about assertion + + def addError(self, test, err): + super(TextTestResult, self).addError(test, err) + self._process(test, "not ok", "ERROR") + # [ ] add structured data about exception + + def addSkip(self, test, reason): + super(TextTestResult, self).addSkip(test, reason) + self._process(test, "ok", directive=(" # SKIP %s" % reason)) + + def addExpectedFailure(self, test, err): + super(TextTestResult, self).addExpectedFailure(test, err) + self._process(test, "not ok", directive=(" # TODO")) + + def addUnexpectedSuccess(self, test): + super(TextTestResult, self).addUnexpectedSuccess(test) + self._process(test, "not ok", "FAIL (unexpected success)") + + """ + def printErrors(self): + def printErrorList(self, flavour, errors): + """ + + +class TAPTestRunner(TextTestRunner): + resultclass = TAPTestResult + + def run(self, test): + self.stream.write("TAP version 13\n") + # [ ] add commented block with test suite __doc__ + # [ ] check call with a single test + # if isinstance(test, suite.TestSuite): + self.stream.write("1..%s\n" % len(list(test))) + + # counterhack: inject test counter into test suite + test.tap_counter = 0 + # counterhack: inject reference to suite into each test case + for case in test: + case.suite = test + + return super(TAPTestRunner, self).run(test) + + +if __name__ == "__main__": + import sys + import unittest + + class Test(unittest.TestCase): + def test_ok(self): + pass + def test_fail(self): + self.assertTrue(False) + def test_error(self): + bad_symbol + @unittest.skip("skipin'") + def test_skip(self): + pass + @unittest.expectedFailure + def test_not_ready(self): + self.fail() + @unittest.expectedFailure + def test_invalid_fail_mark(self): + pass + def test_another_ok(self): + pass + + + suite = unittest.TestSuite([ + Test('test_ok'), + Test('test_fail'), + Test('test_error'), + Test('test_skip'), + Test('test_not_ready'), + Test('test_invalid_fail_mark'), + Test('test_another_ok') + ]) + if not TAPTestRunner().run(suite).wasSuccessful(): + sys.exit(1) diff --git a/testing/framework/test-framework.rst b/testing/framework/test-framework.rst new file mode 100644 index 0000000..cb6b8e1 --- /dev/null +++ b/testing/framework/test-framework.rst @@ -0,0 +1,523 @@ +======================= +SCons Testing Framework +======================= + +SCons uses extensive automated tests to ensure quality. The primary goal +is that users be able to upgrade from version to version without +any surprise changes in behavior. + +In general, no change goes into SCons unless it has one or more new +or modified tests that demonstrably exercise the bug being fixed or +the feature being added. There are exceptions to this guideline, but +they should be just that, ''exceptions''. When in doubt, make sure +it's tested. + +Test Organization +================= + +There are three types of SCons tests: + +*End-to-End Tests* + End-to-end tests of SCons are Python scripts (``*.py``) underneath the + ``test/`` subdirectory. They use the test infrastructure modules in + the ``testing/framework`` subdirectory. They build set up complete + projects and call scons to execute them, checking that the behavior is + as expected. + +*Unit Tests* + Unit tests for individual SCons modules live underneath the + ``src/engine/`` subdirectory and are the same base name as the module + to be tests, with ``Tests`` appended before the ``.py``. For example, + the unit tests for the ``Builder.py`` module are in the + ``BuilderTests.py`` script. Unit tests tend to be based on assertions. + +*External Tests* + For the support of external Tools (in the form of packages, preferably), + the testing framework is extended so it can run in standalone mode. + You can start it from the top-level folder of your Tool's source tree, + where it then finds all Python scripts (``*.py``) underneath the local + ``test/`` directory. This implies that Tool tests have to be kept in + a folder named ``test``, like for the SCons core. + + +Contrasting End-to-End and Unit Tests +##################################### + +In general, functionality with end-to-end tests +should be considered a hardened part of the public interface (that is, +something that a user might do) and should not be broken. Unit tests +are now considered more malleable, more for testing internal interfaces +that can change so long as we don't break users' ``SConscript`` files. +(This wasn't always the case, and there's a lot of meaty code in many +of the unit test scripts that does, in fact, capture external interface +behavior. In general, we should try to move those things to end-to-end +scripts as we find them.) + +End-to-end tests are by their nature harder to debug. +You can drop straight into the Python debugger on the unit test +scripts by using the ``runtest.py --pdb`` option, but the end-to-end +tests treat an SCons invocation as a "black box" and just look for +external effects; simple methods like inserting ``print`` statements +in the SCons code itself can disrupt those external effects. +See `Debugging End-to-End Tests`_ for some more thoughts. + +Naming Conventions +################## + +The end-to-end tests, more or less, stick to the following naming +conventions: + +#. All tests end with a .py suffix. + +#. In the *General* form we use + + ``Feature.py`` + for the test of a specified feature; try to keep this description + reasonably short + + ``Feature-x.py`` + for the test of a specified feature using option ``x`` +#. The *command line option* tests take the form + + ``option-x.py`` + for a lower-case single-letter option + + ``option--X.py`` + upper-case single-letter option (with an extra hyphen, so the + file names will be unique on case-insensitive systems) + + ``option--lo.py`` + long option; abbreviate the long option name to a few characters + + +Running Tests +============= + +The standard set of SCons tests are run from the top-level source +directory by the ``runtest.py`` script. + +Help is available through the ``-h`` option:: + + $ python runtest.py -h + +To simply run all the tests, use the ``-a`` option:: + + $ python runtest.py -a + +By default, ``runtest.py`` prints a count and percentage message for each +test case, along with the name of the test file. If you need the output +to be more silent, have a look at the ``-q``, ``-s`` and ``-k`` options. + +You may specifically list one or more tests to be run:: + + $ python runtest.py src/engine/SCons/BuilderTests.py + $ python runtest.py test/option-j.py test/Program.py + +Folder names are allowed arguments as well, so you can do:: + + $ python runtest.py test/SWIG + +to run all SWIG tests only. + +You can also use the ``-f`` option to execute just the tests listed in +a specified text file:: + + $ cat testlist.txt + test/option-j.py + test/Program.py + $ python runtest.py -f testlist.txt + +One test must be listed per line, and any lines that begin with '#' +will be ignored (the intent being to allow you, for example, to comment +out tests that are currently passing and then uncomment all of the tests +in the file for a final validation run). + +If more than one test is run, the ``runtest.py`` script prints a summary +of how many tests passed, failed, or yielded no result, and lists any +unsuccessful tests. + +The above invocations all test directly the files underneath the ``src/`` +subdirectory, and do not require that a packaging build be performed +first. The ``runtest.py`` script supports additional options to run +tests against unpacked packages in the ``build/test-*/`` subdirectories. + +If you are testing a separate Tool outside of the SCons source tree, you +have to call the ``runtest.py`` script in *external* (stand-alone) mode:: + + $ python ~/scons/runtest.py -e -a + +This ensures that the testing framework doesn't try to access SCons +classes needed for some of the *internal* test cases. + +Note, that the actual tests are carried out in a temporary folder each, +which gets deleted afterwards. This ensures that your source directories +don't get clobbered with temporary files from the test runs. It also +means that you can't simply change into a folder to "debug things" after +a test has gone wrong. For a way around this, check out the ``PRESERVE`` +environment variable. It can be seen in action in +`How to convert old tests`_ below. + +Not Running Tests +================= + +If you simply want to check which tests would get executed, you can call +the ``runtest.py`` script with the ``-l`` option:: + + $ python runtest.py -l + +Then there is also the ``-n`` option, which prints the command line for +each single test, but doesn't actually execute them:: + + $ python runtest.py -n + +Finding Tests +============= + +When started in *standard* mode:: + + $ python runtest.py -a + +``runtest.py`` assumes that it is run from the SCons top-level source +directory. It then dives into the ``src`` and ``test`` folders, where +it tries to find filenames + +``*Test.py`` + for the ``src`` directory + +``*.py`` + for the ``test`` folder + +When using fixtures, you may quickly end up in a position where you have +supporting Python script files in a subfolder, but they shouldn't get +picked up as test scripts. In this case you have two options: + +#. Add a file with the name ``sconstest.skip`` to your subfolder. This + lets ``runtest.py`` skip the contents of the directory completely. +#. Create a file ``.exclude_tests`` in each folder in question, and in + it list line-by-line the files to get excluded from testing. + +The same rules apply when testing external Tools by using the ``-e`` +option. + + +Example End-to-End Test Script +============================== + +To illustrate how the end-to-end test scripts work, let's walk through +a simple "Hello, world!" example:: + + #!python + import TestSCons + + test = TestSCons.TestSCons() + + test.write('SConstruct', """\ + Program('hello.c') + """) + + test.write('hello.c', """\ + int + main(int argc, char *argv[]) + { + printf("Hello, world!\\n"); + exit (0); + } + """) + + test.run() + + test.run(program='./hello', stdout="Hello, world!\n") + + test.pass_test() + + +``import TestSCons`` + Imports the main infrastructure for writing SCons tests. This is + normally the only part of the infrastructure that needs importing. + Sometimes other Python modules are necessary or helpful, and get + imported before this line. + +``test = TestSCons.TestSCons()`` + This initializes an object for testing. A fair amount happens under + the covers when the object is created, including: + + * A temporary directory is created for all the in-line files that will + get created. + + * The temporary directory's removal is arranged for when + the test is finished. + + * The test does ``os.chdir()`` to the temporary directory. + +``test.write('SConstruct', ...)`` + This line creates an ``SConstruct`` file in the temporary directory, + to be used as input to the ``scons`` run(s) that we're testing. + Note the use of the Python triple-quote syntax for the contents + of the ``SConstruct`` file. Because input files for tests are all + created from in-line data like this, the tests can sometimes get + a little confusing to read, because some of the Python code is found + +``test.write('hello.c', ...)`` + This lines creates an ``hello.c`` file in the temporary directory. + Note that we have to escape the ``\\n`` in the + ``"Hello, world!\\n"`` string so that it ends up as a single + backslash in the ``hello.c`` file on disk. + +``test.run()`` + This actually runs SCons. Like the object initialization, things + happen under the covers: + + * The exit status is verified; the test exits with a failure if + the exit status is not zero. + * The error output is examined, and the test exits with a failure + if there is any. + +``test.run(program='./hello', stdout="Hello, world!\n")`` + This shows use of the ``TestSCons.run()`` method to execute a program + other than ``scons``, in this case the ``hello`` program we just + presumably built. The ``stdout=`` keyword argument also tells the + ``TestSCons.run()`` method to fail if the program output does not + match the expected string ``"Hello, world!\n"``. Like the previous + ``test.run()`` line, it will also fail the test if the exit status is + non-zero, or there is any error output. + +``test.pass_test()`` + This is always the last line in a test script. It prints ``PASSED`` + on the screen and makes sure we exit with a ``0`` status to indicate + the test passed. As a side effect of destroying the ``test`` object, + the created temporary directory will be removed. + +Working with Fixtures +===================== + +In the simple example above, the files to set up the test are created +on the fly by the test program. We give a filename to the ``TestSCons.write()`` +method, and a string holding its contents, and it gets written to the test +folder right before starting.. + +This technique can still be seen throughout most of the end-to-end tests, +but there is a better way. To create a test, you need to create the +files that will be used, then when they work reasonably, they need to +be pasted into the script. The process repeats for maintenance. Once +a test gets more complex and/or grows many steps, the test script gets +harder to read. Why not keep the files as is? + +In testing parlance, a fixture is a repeatable test setup. The scons +test harness allows the use of saved files or directories to be used +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. + +Directory Fixtures +################## + +The function ``dir_fixture(self, srcdir, dstdir=None)`` in the ``TestCmd`` +class copies the contents of the specified folder ``srcdir`` from +the directory of the called test script to the current temporary test +directory. The ``srcdir`` name may be a list, in which case the elements +are concatenated with the ``os.path.join()`` method. The ``dstdir`` +is assumed to be under the temporary working directory, it gets created +automatically, if it does not already exist. + +A short syntax example:: + + test = TestSCons.TestSCons() + test.dir_fixture('image') + test.run() + +would copy all files and subfolders from the local ``image`` folder, +to the temporary directory for the current test. + +To see a real example for this in action, refer to the test named +``test/packaging/convenience-functions/convenience-functions.py``. + +File Fixtures +############# + +Like for directory fixtures, ``file_fixture(self, srcfile, dstfile=None)`` +copies the file ``srcfile`` from the directory of the called script, +to the temporary test directory. The ``dstfile`` is assumed to be +under the temporary working directory, unless it is an absolute path +name. If ``dstfile`` is specified, its target directory gets created +automatically if it doesn't already exist. + +With the following code:: + + test = TestSCons.TestSCons() + test.file_fixture('SConstruct') + test.file_fixture(['src','main.cpp'],['src','main.cpp']) + test.run() + +The files ``SConstruct`` and ``src/main.cpp`` are copied to the +temporary test directory. Notice the second ``file_fixture`` line +preserves the path of the original, otherwise ``main.cpp`` +would have landed in the top level of the test directory. + +Again, a reference example can be found in the current revision +of SCons, it is ``test/packaging/sandbox-test/sandbox-test.py``. + +For even more examples you should check out +one of the external Tools, e.g. the *Qt4* Tool at +https://bitbucket.org/dirkbaechle/scons_qt4. Also visit the SCons Tools +Index at https://github.com/SCons/scons/wiki/ToolsIndex for a complete +list of available Tools, though not all may have tests yet. + +How to Convert Old Tests to Use Fixures +####################################### + +Tests using the inline ``TestSCons.write()`` method can easily be +converted to the fixture based approach. For this, we need to get at the +files as they are written to each temporary test folder. + +``runtest.py`` checks for the existence of an environment +variable named ``PRESERVE``. If it is set to a non-zero value, the testing +framework preserves the test folder instead of deleting it, and prints +its name to the screen. + +So, you should be able to give the commands:: + + $ PRESERVE=1 python runtest.py test/packaging/sandbox-test.py + +assuming Linux and a bash-like shell. For a Windows ``cmd`` shell, use +``set PRESERVE=1`` (that will leave it set for the duration of the +``cmd`` session, unless manually deleted). + +The output should then look something like this:: + + 1/1 (100.00%) /usr/bin/python -tt test/packaging/sandbox-test.py + PASSED + Preserved directory /tmp/testcmd.4060.twlYNI + +You can now copy the files from that folder to your new +*fixture* folder. Then, in the test script you simply remove all the +tedious ``TestSCons.write()`` statements and replace them by a single +``TestSCons.dir_fixture()``. + +Finally, don't forget to clean up and remove the temporary test +directory. ``;)`` + +When Not to Use a Fixture +######################### + +Note that some files are not appropriate for use in a fixture as-is: +fixture files should be static. If the creation of the file involves +interpolating data discovered during the run of the test script, +that process should stay in the script. Here is an example of this +kind of usage that does not lend itself to a fixture:: + + import TestSCons + _python_ = TestSCons._python_ + + test.write('SConstruct', """ + cc = Environment().Dictionary('CC') + env = Environment(LINK = r'%(_python_)s mylink.py', + LINKFLAGS = [], + CC = r'%(_python_)s mycc.py', + CXX = cc, + CXXFLAGS = []) + env.Program(target = 'test1', source = 'test1.c') + """ % locals()) + +Here the value of ``_python_`` is picked out of the script's +``locals`` dictionary and interpolated into the string that +will be written to ``SConstruct``. + +The other files created in this test may still be candidates for +use in a fixture, however. + +Debugging End-to-End Tests +========================== + +Most of the end to end tests have expectations for standard output +and error from the test runs. The expectation could be either +that there is nothing on that stream, or that it will contain +very specific text which the test matches against. So adding +``print()`` calls, or ``sys,stderr.write()`` or similar will +emit data that the tests do not expect, and cause further failures. +Say you have three different tests in a script, and the third +one is unexpectedly failing. You add some debug prints to the +part of scons that is involved, and now the first test of the +three starts failing, aborting the test run before it gets +to the third test you were trying to debug. + +Still, there are some techniques to help debugging. + +Probably the most effective technique is to use the internal +``SCons.Debug.Trace()`` function, which prints output to +``/dev/tty`` on Linux/UNIX systems and ``con`` on Windows systems, +so you can see what's going on. + +If you do need to add informational messages in scons code +to debug a problem, you can use logging and send the messages +to a file instead, so they don't interrupt the test expectations. + +Part of the technique discussed in the section +`How to Convert Old Tests to Use Fixures`_ can also be helpful +for debugging purposes. If you have a failing test, try:: + + $ PRESERVE=1 python runtest.py test/failing-test.py + +You can now go to the save directory reported from this run +and invoke the test manually to see what it is doing, without +the presence of the test infrastructure which would otherwise +"swallow" output you may be interested in. In this case, +adding debug prints may be more useful. + + +Test Infrastructure +=================== + +The main test API in the ``TestSCons.py`` class. ``TestSCons`` +is a subclass of ``TestCommon``, which is a subclass of ``TestCmd``. +All those classes are defined in python files of the same name +in ``testing/framework``. Start in +``testing/framework/TestCmd.py`` for the base API definitions, like how +to create files (``test.write()``) and run commands (``test.run()``). + +Use ``TestSCons`` for the end-to-end tests in ``test``, but use +``TestCmd`` for the unit tests in the ``src`` folder. + +The match functions work like this: + +``TestSCons.match_re`` + match each line with a RE + + * Splits the lines into a list (unless they already are) + * splits the REs at newlines (unless already a list) and puts ^..$ around each + * then each RE must match each line. This means there must be as many + REs as lines. + +``TestSCons.match_re_dotall`` + match all the lines against a single RE + + * Joins the lines with newline (unless already a string) + * joins the REs with newline (unless it's a string) and puts ``^..$`` + around the whole thing + * then whole thing must match with python re.DOTALL. + +Use them in a test like this:: + + test.run(..., match=TestSCons.match_re, ...) + +or:: + + test.must_match(..., match=TestSCons.match_re, ...) + +Avoiding Tests Based on Tool Existence +====================================== + +Here's a simple example:: + + #!python + intelc = test.detect_tool('intelc', prog='icpc') + if not intelc: + test.skip_test("Could not load 'intelc' Tool; skipping test(s).\n") + +See ``testing/framework/TestSCons.py`` for the ``detect_tool`` method. +It calls the tool's ``generate()`` method, and then looks for the given +program (tool name by default) in ``env['ENV']['PATH']``. + +The ``where_is`` method can be used to look for programs that +are do not have tool specifications. The existing test code +will have many samples of using either or both of these to detect +if it is worth even proceeding with a test. |