diff options
author | Russel Winder <russel@winder.org.uk> | 2016-04-10 09:41:00 (GMT) |
---|---|---|
committer | Russel Winder <russel@winder.org.uk> | 2016-04-10 09:41:00 (GMT) |
commit | 6a37189174372c9c98c63ada58ab4352adf650e8 (patch) | |
tree | 521ddb1071569fa90100e11d7f03af13d5689aaf | |
parent | 14924bcc1713c5bd7dcf4db5b420204407048889 (diff) | |
parent | 3e0a831c7fcd60384266e14641a3a15f2cba1ced (diff) | |
download | SCons-6a37189174372c9c98c63ada58ab4352adf650e8.zip SCons-6a37189174372c9c98c63ada58ab4352adf650e8.tar.gz SCons-6a37189174372c9c98c63ada58ab4352adf650e8.tar.bz2 |
Commit resolved conflicted merge.
58 files changed, 494 insertions, 216 deletions
diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index 6820ae1..88d0e9c 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -34,9 +34,9 @@ from TestCmd import PIPE # here provides some independent verification that what we packaged # conforms to what we expect. -default_version = '2.4.2.alpha.yyyymmdd' +default_version = '2.5.0' -python_version_unsupported = (2, 3, 0) +python_version_unsupported = (2, 6, 0) python_version_deprecated = (2, 7, 0) # In the checked-in source, the value of SConsVersion in the following @@ -168,7 +168,7 @@ Or on Windows:: By default, the above commands will do the following: -- Install the version-numbered "scons-2.4.1" and "sconsign-2.4.1" scripts in +- Install the version-numbered "scons-2.5.0" and "sconsign-2.5.0" 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 +180,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-2.4.1" and "sconsign-2.4.1" + hard links or symbolic links to the "scons-2.5.0" and "sconsign-2.5.0" scripts by specifying the "--hardlink-scons" or "--symlink-scons" options on the command line. -- Install "scons-2.4.1.bat" and "scons.bat" wrapper scripts in the Python +- Install "scons-2.5.0.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-2.4.1.bat" and "scons.bat" files installed in the default system + have "scons-2.5.0.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-2.4.0 or - C:\\Python\*\\scons-2.4.0, for example). See below for more options related to + version-numbered SCons library directory (/usr/lib/scons-2.5.0 or + C:\\Python\*\\scons-2.5.0, 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 +474,7 @@ running all of "runtest.py -a". Building Packages ================= -We use SCons (version 2.4.1 or later) to build its own packages. If you +We use SCons (version 2.5.0 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 +489,18 @@ 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-2.4.1-1.noarch.rpm - build/dist/scons-2.4.1-1.src.rpm - build/dist/scons-2.4.1.linux-i686.tar.gz - build/dist/scons-2.4.2.alpha.yyyymmdd.tar.gz - build/dist/scons-2.4.2.alpha.yyyymmdd.win32.exe - build/dist/scons-2.4.2.alpha.yyyymmdd.zip - build/dist/scons-doc-2.4.2.alpha.yyyymmdd.tar.gz - build/dist/scons-local-2.4.2.alpha.yyyymmdd.tar.gz - build/dist/scons-local-2.4.2.alpha.yyyymmdd.zip - build/dist/scons-src-2.4.2.alpha.yyyymmdd.tar.gz - build/dist/scons-src-2.4.2.alpha.yyyymmdd.zip - build/dist/scons_2.4.1-1_all.deb + build/dist/scons-2.5.0-1.noarch.rpm + build/dist/scons-2.5.0-1.src.rpm + build/dist/scons-2.5.0.linux-i686.tar.gz + build/dist/scons-2.5.0.tar.gz + build/dist/scons-2.5.0.win32.exe + build/dist/scons-2.5.0.zip + build/dist/scons-doc-2.5.0.tar.gz + build/dist/scons-local-2.5.0.tar.gz + build/dist/scons-local-2.5.0.zip + build/dist/scons-src-2.5.0.tar.gz + build/dist/scons-src-2.5.0.zip + build/dist/scons_2.5.0-1_all.deb 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 diff --git a/ReleaseConfig b/ReleaseConfig index e1f462a..7a68f89 100644 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -32,7 +32,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" # 'final', the patchlevel is set to the release date. This value is # mandatory and must be present in this file. #version_tuple = (2, 2, 0, 'final', 0) -version_tuple = (2, 4, 2, 'alpha', 0) +version_tuple = (2, 6, 0, 'alpha', 0) # Python versions prior to unsupported_python_version cause a fatal error # when that version is used. Python versions prior to deprecate_python_version @@ -51,7 +51,7 @@ deprecated_python_version = (2, 7, 0) #month_year = 'December 2012' # If copyright years is not given, the release year is used as the end. -copyright_years = '2001 - 2015' +copyright_years = '2001 - 2016' # Local Variables: # tab-width:4 @@ -5,10 +5,10 @@ from __future__ import print_function -copyright_years = '2001 - 2015' +copyright_years = '2001 - 2016' # This gets inserted into the man pages to reflect the month of release. -month_year = 'MONTH YEAR' +month_year = 'April 2016' # # __COPYRIGHT__ @@ -45,7 +45,7 @@ import tempfile import bootstrap project = 'scons' -default_version = '2.4.2.alpha.yyyymmdd' +default_version = '2.5.0' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years platform = distutils.util.get_platform() @@ -371,7 +371,7 @@ def SCons_revision(target, source, env): """ t = str(target[0]) s = source[0].rstr() - contents = open(s, 'r').read() + contents = open(s, 'rb').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. @@ -385,7 +385,7 @@ def SCons_revision(target, source, env): contents = contents.replace('__REVISION' + '__', env['REVISION']) contents = contents.replace('__VERSION' + '__', env['VERSION']) contents = contents.replace('__NULL' + '__', '') - open(t, 'w').write(contents) + open(t, 'wb').write(contents) os.chmod(t, os.stat(s)[0]) revaction = SCons_revision @@ -419,7 +419,6 @@ def soelim(target, source, env): def soscan(node, env, path): c = node.get_text_contents() - # Node contents are bytes ==> br"..." return re.compile(br"^[\.']so\s+(\S+)", re.M).findall(c) soelimbuilder = Builder(action = Action(soelim), @@ -830,7 +829,7 @@ for p in [ scons ]: def write_src_files(target, source, **kw): global src_files src_files.sort() - f = open(str(target[0]), 'w') + f = open(str(target[0]), 'wb') for file in src_files: f.write(file + "\n") f.close() diff --git a/debian/changelog b/debian/changelog index 9d60e3a..e3ab00c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +scons (2.5.0) unstable; urgency=low + + * Feature Release + + -- William Deegan <bill@baddogconsulting.com> Sat, 09 Apr 2016 08:56:00 -0700 + scons (2.4.1) unstable; urgency=low * Maintenance release. diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index cb14259..232e96f 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 f1.o -c f1.c cc -o f4.o -c f4.c +cc -o f2.o -c f2.c +cc -o f1.o -c f1.c cc -o f5.o -c f5.c cc -o f3.o -c f3.c -cc -o f2.o -c f2.c cc -o prog f1.o f2.o f3.o f4.o f5.o </screen> diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 7e495ea..3d8592d 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/ghost/projects/scons/bootstrap/src/script/scons.py", line 199, in <module> +File "/scons/as_scons/bootstrap/src/script/scons.py", line 199, in <module> </screen> diff --git a/doc/generated/examples/troubleshoot_stacktrace_2.xml b/doc/generated/examples/troubleshoot_stacktrace_2.xml index 1de0dcf..add59ff 100644 --- a/doc/generated/examples/troubleshoot_stacktrace_2.xml +++ b/doc/generated/examples/troubleshoot_stacktrace_2.xml @@ -4,10 +4,10 @@ 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 164, in prepare + File "bootstrap/src/engine/SCons/Script/Main.py", line 173, in prepare return SCons.Taskmaster.OutOfDateTask.prepare(self) File "bootstrap/src/engine/SCons/Taskmaster.py", line 191, in prepare executor.prepare() - File "bootstrap/src/engine/SCons/Executor.py", line 427, in prepare + File "bootstrap/src/engine/SCons/Executor.py", line 430, in prepare raise SCons.Errors.StopError(msg % (s, self.batches[0].targets[0])) </screen> diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index fcb7587..ba12966 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -780,19 +780,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"> -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> - <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> diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index 1191e6a..2ee2270 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>"> @@ -189,8 +189,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 b64eb5a..b377102 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -2838,6 +2838,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. @@ -2853,16 +2862,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> @@ -3104,7 +3104,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"> @@ -3114,7 +3114,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"> @@ -7038,6 +7038,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 @@ -7062,14 +7069,7 @@ 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> diff --git a/doc/man/scons.xml b/doc/man/scons.xml index c72178e..41ef607 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -54,10 +54,10 @@ <corpauthor>Steven Knight and the SCons Development Team</corpauthor> - <pubdate>2004 - 2015</pubdate> + <pubdate>2004 - 2016</pubdate> <copyright> - <year>2004 - 2015</year> + <year>2004 - 2016</year> <holder>The SCons Foundation</holder> </copyright> @@ -1707,6 +1707,16 @@ specifies the type of warnings to be enabled or disabled:</para> </listitem> </varlistentry> <varlistentry> + <term>--warn=cache-version, --warn=no-cache-version</term> + <listitem> +<para>Enables or disables warnings about the cache directory not using +the latest configuration information +<emphasis role="bold">CacheDir</emphasis>(). +These warnings are enabled by default.</para> + + </listitem> + </varlistentry> + <varlistentry> <term>--warn=cache-write-error, --warn=no-cache-write-error</term> <listitem> <para>Enables or disables warnings about errors trying to diff --git a/doc/user/main.xml b/doc/user/main.xml index d2c4c18..451f87d 100644 --- a/doc/user/main.xml +++ b/doc/user/main.xml @@ -74,10 +74,10 @@ <corpauthor>Steven Knight and the SCons Development Team</corpauthor> - <pubdate>2004 - 2015</pubdate> + <pubdate>2004 - 2016</pubdate> <copyright> - <year>2004 - 2015</year> + <year>2004 - 2016</year> <holder>The SCons Foundation</holder> </copyright> diff --git a/src/Announce.txt b/src/Announce.txt index c20d7df..266988f 100644 --- a/src/Announce.txt +++ b/src/Announce.txt @@ -18,36 +18,6 @@ So that everyone using SCons can help each other learn how to use it more effectively, please go to http://scons.org/lists.php#users to sign up for the scons-users mailing list. -==============IMPORTANT NOTICE FOR NEXT VERSION V2.5.0========== -PLEASE READ. CHANGES COMING IN NEXT MAJOR RELEASE V2.5.0 - -We're enhancing implicit language scanning functionality to improve -correctness. SCons now honors scanner keys for implicit dependencies -and correctly changes scanner type (if necessary) when traversing -implicit dependency trees. - -This enhancement resolves missing dependencies -with built-in scanners including SWIG (#2264) and QT: -* http://scons.tigris.org/issues/show_bug.cgi?id=2264 - -This enhancement broadens the horizon for handling heterogeneous -data flow environments (E.G. software builds): -* http://article.gmane.org/gmane.comp.programming.tools.scons.user/26596 -Notes: - -* SCons may find new (and correct) dependencies in cross-langauge contexts. -** Update may cause rebuilds, especially in heterogeneous data environments. -** Update may find previously missed dependencies errors (E.G. cycles). -*** Discovered in some QT test cases. -* SCons handles the SCANNERS variable differently. -** Previously, the Install builder would scan implicit dependencies for - a scanner found in SCANNERS (but not for built-in scanners), but now - the Install builder will not scan recursively regardless in order - to optimize Install behaviour and bring orthogonality to previous behaviour. - -+================================================================= - - RELEASE VERSION/DATE TO BE FILLED IN LATER Please consult the RELEASE.txt file for a summary of changes since the last @@ -55,6 +25,40 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER since last release. This announcement highlights only the important changes. + - Please note the following important changes since release 2.4.1: + We're enhancing implicit language scanning functionality to improve + correctness. SCons now honors scanner keys for implicit dependencies + and correctly changes scanner type (if necessary) when traversing + implicit dependency trees. + + This enhancement resolves missing dependencies + with built-in scanners including SWIG (#2264) and QT: + * http://scons.tigris.org/issues/show_bug.cgi?id=2264 + + - This enhancement broadens the horizon for handling heterogeneous + data flow environments (E.G. software builds): + - http://article.gmane.org/gmane.comp.programming.tools.scons.user/26596 + + - SCons may find new (and correct) dependencies in cross-langauge contexts. + - Update may cause rebuilds, especially in heterogeneous data environments. + - Update may find previously missed dependencies errors (E.G. cycles). + - Discovered in some QT test cases. + - SCons handles the SCANNERS variable differently. + - Previously, the Install builder would scan implicit dependencies for + a scanner found in SCANNERS (but not for built-in scanners), but now + the Install builder will not scan recursively regardless in order + to optimize Install behaviour and bring orthogonality to previous behaviour. + + - SCons handles cache directories a bit differently/ + - Cache files are now stored in 256 subdirectories in the cache directory by + default (this stresses NFS less). Existing cache directories will remain as + current, but SCons will prompt you to run scons-configure-cache which will + allow you to migrate to the new layout, or confirm you want to use the + existing layout. + + - New external tool scons-configurecache which allows some configuration of + how files in the cache are controlled. + Please note the following important changes since release 2.4.0: - Fix to swig tool - pick-up 'swig', 'swig3.0' and 'swig2.0' (in order). - Fix to swig tool - respect env['SWIG'] provided by user. diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 7e1e9fe..4afc80d 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -6,6 +6,13 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER + From John Doe: + + - Whatever John Doe did. + + +RELEASE 2.5.0 - Mon, 09 Apr 2016 11:27:42 -0700 + From Dirk Baechle: - Removed a lot of compatibility methods and workarounds for Python versions < 2.7, in order to prepare the work @@ -40,12 +47,20 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fix posix platform escaping logic to properly handle paths with parens in them "()". (Bug #2225) - From Jakub Pola: - Intel Compiler 2016 (Linux/Mac) update for tool directories. From Adarsh Sanjeev: - - Fix for issue #2494: Added string support for Chmod function. + - Fix for issue #2494: Added string support for Chmod function. + + From Tom Tanner: + - change cache to use 2 character subdirectories, rather than one character, + so as not to give huge directories for large caches, a situation which + causes issues for NFS. + For existing caches, you will need to run the scons-configure-cache.py + script to update them to the new format. You will get a warning every time + you build until you co this. + - Fix a bunch of unit tests on windows RELEASE 2.4.1 - Mon, 07 Nov 2015 10:37:21 -0700 diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 3bff366..ac2b95a 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -1,4 +1,4 @@ - A new SCons checkpoint release, 2.4.3.alpha.yyyymmdd, is now available + A new SCons checkpoint release, 2.6.0.alpha.yyyymmdd, is now available on the SCons download page: http://www.scons.org/download.php diff --git a/src/engine/SCons/CacheDir.py b/src/engine/SCons/CacheDir.py index 3b7d06f..1690674 100644 --- a/src/engine/SCons/CacheDir.py +++ b/src/engine/SCons/CacheDir.py @@ -27,7 +27,8 @@ __doc__ = """ CacheDir support """ -import os.path +import json +import os import stat import sys @@ -72,7 +73,8 @@ CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString) CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None) def CachePushFunc(target, source, env): - if cache_readonly: return + if cache_readonly: + return t = target[0] if t.nocache: @@ -125,6 +127,10 @@ def CachePushFunc(target, source, env): CachePush = SCons.Action.Action(CachePushFunc, None) +# Nasty hack to cut down to one warning for each cachedir path that needs +# upgrading. +warned = dict() + class CacheDir(object): def __init__(self, path): @@ -133,11 +139,63 @@ class CacheDir(object): except ImportError: msg = "No hashlib or MD5 module available, CacheDir() not supported" SCons.Warnings.warn(SCons.Warnings.NoMD5ModuleWarning, msg) - self.path = None - else: - self.path = path + path = None + self.path = path self.current_cache_debug = None self.debugFP = None + self.config = dict() + if path is None: + return + # See if there's a config file in the cache directory. If there is, + # use it. If there isn't, and the directory exists and isn't empty, + # produce a warning. If the directory doesn't exist or is empty, + # write a config file. + config_file = os.path.join(path, 'config') + if not os.path.exists(config_file): + # A note: There is a race hazard here, if two processes start and + # attempt to create the cache directory at the same time. However, + # python doesn't really give you the option to do exclusive file + # creation (it doesn't even give you the option to error on opening + # an existing file for writing...). The ordering of events here + # as an attempt to alleviate this, on the basis that it's a pretty + # unlikely occurence (it'd require two builds with a brand new cache + # directory) + if os.path.isdir(path) and len(os.listdir(path)) != 0: + self.config['prefix_len'] = 1 + # When building the project I was testing this on, the warning + # was output over 20 times. That seems excessive + global warned + if self.path not in warned: + msg = "Please upgrade your cache by running " +\ + " scons-configure-cache.py " + self.path + SCons.Warnings.warn(SCons.Warnings.CacheVersionWarning, msg) + warned[self.path] = True + else: + if not os.path.isdir(path): + try: + os.makedirs(path) + except OSError: + # If someone else is trying to create the directory at + # the same time as me, bad things will happen + msg = "Failed to create cache directory " + path + raise SCons.Errors.EnvironmentError(msg) + + self.config['prefix_len'] = 2 + if not os.path.exists(config_file): + try: + with open(config_file, 'w') as config: + json.dump(self.config, config) + except: + msg = "Failed to write cache configuration for " + path + raise SCons.Errors.EnvironmentError(msg) + else: + try: + with open(config_file) as config: + self.config = json.load(config) + except ValueError: + msg = "Failed to read cache configuration for " + path + raise SCons.Errors.EnvironmentError(msg) + def CacheDebug(self, fmt, target, cachefile): if cache_debug != self.current_cache_debug: @@ -152,7 +210,7 @@ class CacheDir(object): self.debugFP.write(fmt % (target, os.path.split(cachefile)[1])) def is_enabled(self): - return (cache_enabled and not self.path is None) + return cache_enabled and not self.path is None def is_readonly(self): return cache_readonly @@ -164,7 +222,7 @@ class CacheDir(object): return None, None sig = node.get_cachedir_bsig() - subdir = sig[0].upper() + 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 878a87a..8a52928 100644 --- a/src/engine/SCons/CacheDirTests.py +++ b/src/engine/SCons/CacheDirTests.py @@ -83,6 +83,11 @@ class BaseTestCase(unittest.TestCase): #node.binfo.ninfo.bsig = bsig return node + def tearDown(self): + os.remove(os.path.join(self._CacheDir.path, 'config')) + os.rmdir(self._CacheDir.path) + # Should that be shutil.rmtree? + class CacheDirTestCase(BaseTestCase): """ Test calling CacheDir code directly. @@ -98,10 +103,12 @@ class CacheDirTestCase(BaseTestCase): SCons.Util.MD5collect = my_collect try: - f5 = self.File("cd.f5", 'a_fake_bsig') + name = 'a_fake_bsig' + f5 = self.File("cd.f5", name) result = self._CacheDir.cachepath(f5) - dirname = os.path.join('cache', 'A') - filename = os.path.join(dirname, 'a_fake_bsig') + len = self._CacheDir.config['prefix_len'] + dirname = os.path.join('cache', name.upper()[:len]) + filename = os.path.join(dirname, name) assert result == (dirname, filename), result finally: SCons.Util.MD5collect = save_collect diff --git a/src/engine/SCons/SConf.py b/src/engine/SCons/SConf.py index 935eef2..d56b333 100644 --- a/src/engine/SCons/SConf.py +++ b/src/engine/SCons/SConf.py @@ -756,10 +756,10 @@ class CheckContext(object): A typical test is just a callable with an instance of CheckContext as first argument: - def CheckCustom(context, ...) - context.Message('Checking my weird test ... ') - ret = myWeirdTestFunction(...) - context.Result(ret) + def CheckCustom(context, ...): + context.Message('Checking my weird test ... ') + ret = myWeirdTestFunction(...) + context.Result(ret) Often, myWeirdTestFunction will be one of context.TryCompile/context.TryLink/context.TryRun. The results of diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index 5c27825..2495b89 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -41,10 +41,12 @@ class WarningOnByDefault(Warning): # NOTE: If you add a new warning class, add it to the man page, too! - class TargetNotBuiltWarning(Warning): # Should go to OnByDefault pass +class CacheVersionWarning(WarningOnByDefault): + pass + class CacheWriteErrorWarning(Warning): pass diff --git a/src/script/scons-configure-cache.py b/src/script/scons-configure-cache.py new file mode 100644 index 0000000..c1b7d59 --- /dev/null +++ b/src/script/scons-configure-cache.py @@ -0,0 +1,139 @@ +#! /usr/bin/env python
+#
+# SCons - a Software Constructor
+#
+# __COPYRIGHT__
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
+# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
+
+__version__ = "__VERSION__"
+
+__build__ = "__BUILD__"
+
+__buildsys__ = "__BUILDSYS__"
+
+__date__ = "__DATE__"
+
+__developer__ = "__DEVELOPER__"
+
+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
+ 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))
+
+ # Now delete the original directories
+ for dir in old_dirs:
+ os.rmdir(dir)
+
+# This dictionary should have one entry per entry in the cache config
+# Each entry should have 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.
+# 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
+# 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
+ }
+}
+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).
+ '''
+ )
+
+parser.add_argument('cache-dir', help='Path to scons cache directory')
+for param in config_entries:
+ parser.add_argument('--' + param.replace('_', '-'),
+ **config_entries[param]['command-line'])
+parser.add_argument('--version', action='version', version='%(prog)s 1.0')
+
+# Get the command line as a dict without any of the unspecified entries.
+args = dict(filter(lambda x: x[1], vars(parser.parse_args()).items()))
+
+# 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'])
+del args['cache-dir']
+
+if not os.path.exists('config'):
+ # Validate the only files in the directory are directories 0-9, a-f
+ 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")
+ config = dict()
+else:
+ with open('config') as conf:
+ config = json.load(conf)
+
+# Find any keys that aren't currently set but should be
+for key in config_entries:
+ if key not in config:
+ if 'implicit' in config_entries[key]:
+ config[key] = config_entries[key]['implicit']
+ else:
+ config[key] = config_entries[key]['default']
+ 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.
+for key in args:
+ if args[key] != config[key]:
+ if 'converter' in config_entries[key]:
+ config_entries[key]['converter'](config[key], args[key])
+ config[key] = args[key]
+
+# and write the updated config file
+with open('config', 'w') as conf:
+ json.dump(config, conf)
\ No newline at end of file diff --git a/src/script/scons.py b/src/script/scons.py index 0595717..1cf9469 100644 --- a/src/script/scons.py +++ b/src/script/scons.py @@ -190,8 +190,8 @@ sys.path = libs + sys.path if __name__ == "__main__": try: import SCons.Script - except: - print("Import failed. Unable to find SCons files in:") + except ImportError: + print("SCons import failed. Unable to find engine files in:") for path in libs: print(" {}".format(path)) raise diff --git a/test/Actions/pre-post.py b/test/Actions/pre-post.py index 179e914..f6997e2 100644 --- a/test/Actions/pre-post.py +++ b/test/Actions/pre-post.py @@ -188,7 +188,7 @@ def post_action(target, source, env): env = Environment() o = env.Command(['pre-post', 'file.out'], 'file.in', - '%(_python_)s build.py ${TARGETS[1]} $SOURCE') + r'%(_python_)s build.py ${TARGETS[1]} $SOURCE') env.AddPreAction(o, pre_action) env.AddPostAction(o, post_action) """ % locals()) diff --git a/test/Builder/multi/different-environments.py b/test/Builder/multi/different-environments.py index 783b7f9..c3e96c2 100644 --- a/test/Builder/multi/different-environments.py +++ b/test/Builder/multi/different-environments.py @@ -47,7 +47,7 @@ build(sys.argv[1],sys.argv[2],sys.argv[3:]) """) test.write('SConstruct', """\ -B = Builder(action='%(_python_)s build.py $foo $TARGET $SOURCES', multi=1) +B = Builder(action=r'%(_python_)s build.py $foo $TARGET $SOURCES', multi=1) env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'file03.out', source = 'file03a.in', foo=1) env.B(target = 'file03.out', source = 'file03b.in', foo=2) diff --git a/test/Builder/multi/same-overrides.py b/test/Builder/multi/same-overrides.py index 33c4e7b..ee169e4 100644 --- a/test/Builder/multi/same-overrides.py +++ b/test/Builder/multi/same-overrides.py @@ -45,7 +45,7 @@ build(sys.argv[1],sys.argv[2],sys.argv[3:]) """) test.write('SConstruct', """\ -B = Builder(action='%(_python_)s build.py $foo $TARGET $SOURCES', multi=1) +B = Builder(action=r'%(_python_)s build.py $foo $TARGET $SOURCES', multi=1) env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'file4.out', source = 'file4a.in', foo=3) env.B(target = 'file4.out', source = 'file4b.in', foo=3) diff --git a/test/Builder/srcdir.py b/test/Builder/srcdir.py index 63732d7..669c5e1 100644 --- a/test/Builder/srcdir.py +++ b/test/Builder/srcdir.py @@ -50,7 +50,7 @@ o.close() test.write(['src', 'SConstruct'], """\ Command('output', ['file1', File('file2'), r'%(file3)s', 'file4'], - '%(_python_)s cat.py $TARGET $SOURCES', + r'%(_python_)s cat.py $TARGET $SOURCES', srcdir='foo') """ % locals()) diff --git a/test/CacheDir/CacheDir.py b/test/CacheDir/CacheDir.py index 9abe0e0..4c05634 100644 --- a/test/CacheDir/CacheDir.py +++ b/test/CacheDir/CacheDir.py @@ -82,7 +82,8 @@ test.must_not_exist(src_aaa_out) test.must_not_exist(src_bbb_out) test.must_not_exist(src_ccc_out) test.must_not_exist(src_all) -test.fail_test(len(os.listdir(cache))) +# Even if you do -n, the cache will be configured. +test.fail_test(os.listdir(cache) != ['config']) # Verify that a normal build works correctly, and clean up. # This should populate the cache with our derived files. diff --git a/test/CacheDir/environment.py b/test/CacheDir/environment.py index 4fb9b51..1378bb2 100644 --- a/test/CacheDir/environment.py +++ b/test/CacheDir/environment.py @@ -85,7 +85,8 @@ test.must_not_exist(src_aaa_out) test.must_not_exist(src_bbb_out) test.must_not_exist(src_ccc_out) test.must_not_exist(src_all) -test.fail_test(len(os.listdir(cache))) +# Even if you do -n, the cache will be configured. +test.fail_test(os.listdir(cache) != ['config']) # Verify that a normal build works correctly, and clean up. # This should populate the cache with our derived files. diff --git a/test/CacheDir/option--cs.py b/test/CacheDir/option--cs.py index b6bb52a..6d22814 100644 --- a/test/CacheDir/option--cs.py +++ b/test/CacheDir/option--cs.py @@ -35,6 +35,7 @@ import shutil import TestSCons _python_ = TestSCons._python_ + _exe = TestSCons._exe _obj = TestSCons._obj @@ -62,7 +63,7 @@ def cat(env, source, target): f.write(open(str(src), "rb").read()) f.close() env = Environment(BUILDERS={'Internal':Builder(action=cat), - 'External':Builder(action='%(_python_)s build.py $TARGET $SOURCES')}) + 'External':Builder(action=r'%(_python_)s build.py $TARGET $SOURCES')}) env.External('aaa.out', 'aaa.in') env.External('bbb.out', 'bbb.in') env.Internal('ccc.out', 'ccc.in') diff --git a/test/Command.py b/test/Command.py index 74046b1..5f72c94 100644 --- a/test/Command.py +++ b/test/Command.py @@ -63,15 +63,15 @@ def sub(env, target, source): t.close() return 0 -env = Environment(COPY_THROUGH_TEMP = '%(_python_)s build.py .tmp $SOURCE\\n%(_python_)s build.py $TARGET .tmp', +env = Environment(COPY_THROUGH_TEMP = r'%(_python_)s build.py .tmp $SOURCE' + '\\n' + r'%(_python_)s build.py $TARGET .tmp', EXPAND = '$COPY_THROUGH_TEMP') env.Command(target = 'f1.out', source = 'f1.in', action = buildIt) env.Command(target = 'f2.out', source = 'f2.in', action = r'%(_python_)s build.py temp2 $SOURCES' + '\\n' + r'%(_python_)s build.py $TARGET temp2') env.Command(target = 'f3.out', source = 'f3.in', - action = [ [ r'%(python)s', 'build.py', 'temp3', '$SOURCES' ], - [ r'%(python)s', 'build.py', '$TARGET', 'temp3'] ]) + action = [ [ r'%(_python_)s', 'build.py', 'temp3', '$SOURCES' ], + [ r'%(_python_)s', 'build.py', '$TARGET', 'temp3'] ]) Command(target = 'f4.out', source = 'sub', action = sub) env.Command(target = 'f5.out', source = 'f5.in', action = buildIt, XYZZY='XYZZY is set') diff --git a/test/Configure/Builder-call.py b/test/Configure/Builder-call.py index 037a2c7..b85b039 100644 --- a/test/Configure/Builder-call.py +++ b/test/Configure/Builder-call.py @@ -48,7 +48,7 @@ def CustomTest(*args): return 0 conf = env.Configure(custom_tests = {'MyTest' : CustomTest}) if not conf.MyTest(): - env.Command("hello", [], '%(_python_)s mycommand.py $TARGET') + env.Command("hello", [], r'%(_python_)s mycommand.py $TARGET') env = conf.Finish() """ % locals()) diff --git a/test/Configure/custom-tests.py b/test/Configure/custom-tests.py index 687ba48..503eb4e 100644 --- a/test/Configure/custom-tests.py +++ b/test/Configure/custom-tests.py @@ -63,8 +63,8 @@ def CheckCustom(test): retLinkFAIL = test.TryLink( '%(linkFAIL)s', '.c' ) (retRunOK, outputRunOK) = test.TryRun( '%(runOK)s', '.c' ) (retRunFAIL, outputRunFAIL) = test.TryRun( '%(runFAIL)s', '.c' ) - (retActOK, outputActOK) = test.TryAction( '%(_python_)s pyAct.py 0 > $TARGET' ) - (retActFAIL, outputActFAIL) = test.TryAction( '%(_python_)s pyAct.py 1 > $TARGET' ) + (retActOK, outputActOK) = test.TryAction( r'%(_python_)s pyAct.py 0 > $TARGET' ) + (retActFAIL, outputActFAIL) = test.TryAction( r'%(_python_)s pyAct.py 1 > $TARGET' ) resOK = retCompileOK and retLinkOK and retRunOK and outputRunOK=="Hello" resOK = resOK and retActOK and int(outputActOK)==0 resFAIL = retCompileFAIL or retLinkFAIL or retRunFAIL or outputRunFAIL!="" diff --git a/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOM.py b/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOM.py index d5af0ea..8ff4ced 100644 --- a/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOM.py +++ b/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'BitKeeper'], BUILDERS={'Cat':Builder(action=cat)}, - BITKEEPERCOM='%(_python_)s my-bk-get.py $TARGET') + BITKEEPERCOM=r'%(_python_)s my-bk-get.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOMSTR.py b/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOMSTR.py index ef70cb8..5bbdea2 100644 --- a/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOMSTR.py +++ b/test/Deprecated/SourceCode/BitKeeper/BITKEEPERCOMSTR.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(tools = ['default', 'BitKeeper'], BUILDERS={'Cat':Builder(action=cat)}, - BITKEEPERCOM='%(_python_)s my-bk-get.py $TARGET', + BITKEEPERCOM=r'%(_python_)s my-bk-get.py $TARGET', BITKEEPERCOMSTR='Checking out $TARGET from our fake BitKeeper') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/Deprecated/SourceCode/CVS/CVSCOM.py b/test/Deprecated/SourceCode/CVS/CVSCOM.py index a0f8400..f3bd29d 100644 --- a/test/Deprecated/SourceCode/CVS/CVSCOM.py +++ b/test/Deprecated/SourceCode/CVS/CVSCOM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'CVS'], BUILDERS={'Cat':Builder(action=cat)}, - CVSCOM='%(_python_)s my-cvs-co-.py $TARGET') + CVSCOM=r'%(_python_)s my-cvs-co-.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/CVS/CVSCOMSTR.py b/test/Deprecated/SourceCode/CVS/CVSCOMSTR.py index f793d66..483a0ae 100644 --- a/test/Deprecated/SourceCode/CVS/CVSCOMSTR.py +++ b/test/Deprecated/SourceCode/CVS/CVSCOMSTR.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'CVS'], BUILDERS={'Cat':Builder(action=cat)}, - CVSCOM='%(_python_)s my-cvs-co.py $TARGET', + CVSCOM=r'%(_python_)s my-cvs-co.py $TARGET', CVSCOMSTR='Checking out $TARGET from our fake CVS') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/Deprecated/SourceCode/Perforce/P4COM.py b/test/Deprecated/SourceCode/Perforce/P4COM.py index 9b9bab1..e58cb60 100644 --- a/test/Deprecated/SourceCode/Perforce/P4COM.py +++ b/test/Deprecated/SourceCode/Perforce/P4COM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'Perforce'], BUILDERS={'Cat':Builder(action=cat)}, - P4COM='%(_python_)s my-p4.py $TARGET') + P4COM=r'%(_python_)s my-p4.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/Perforce/P4COMSTR.py b/test/Deprecated/SourceCode/Perforce/P4COMSTR.py index 7a24021..7b2fbba 100644 --- a/test/Deprecated/SourceCode/Perforce/P4COMSTR.py +++ b/test/Deprecated/SourceCode/Perforce/P4COMSTR.py @@ -75,7 +75,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'Perforce'], BUILDERS={'Cat':Builder(action=cat)}, - P4COM='%(_python_)s my-p4.py $TARGET', + P4COM=r'%(_python_)s my-p4.py $TARGET', P4COMSTR='Checking out $TARGET from our fake Perforce') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/Deprecated/SourceCode/RCS/RCS_COCOM.py b/test/Deprecated/SourceCode/RCS/RCS_COCOM.py index 765c88c..c5934ac 100644 --- a/test/Deprecated/SourceCode/RCS/RCS_COCOM.py +++ b/test/Deprecated/SourceCode/RCS/RCS_COCOM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'RCS'], BUILDERS={'Cat':Builder(action=cat)}, - RCS_COCOM='%(_python_)s my-rcs-co.py $TARGET') + RCS_COCOM=r'%(_python_)s my-rcs-co.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/RCS/RCS_COCOMSTR.py b/test/Deprecated/SourceCode/RCS/RCS_COCOMSTR.py index 57088fa..cb54202 100644 --- a/test/Deprecated/SourceCode/RCS/RCS_COCOMSTR.py +++ b/test/Deprecated/SourceCode/RCS/RCS_COCOMSTR.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'RCS'], BUILDERS={'Cat':Builder(action=cat)}, - RCS_COCOM='%(_python_)s my-rcs-co.py $TARGET', + RCS_COCOM=r'%(_python_)s my-rcs-co.py $TARGET', RCS_COCOMSTR='Checking out $TARGET from our fake RCS') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/Deprecated/SourceCode/SCCS/SCCSCOM.py b/test/Deprecated/SourceCode/SCCS/SCCSCOM.py index 6ad02ac..ba89d87 100644 --- a/test/Deprecated/SourceCode/SCCS/SCCSCOM.py +++ b/test/Deprecated/SourceCode/SCCS/SCCSCOM.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(TOOLS = ['default', 'SCCS'], BUILDERS={'Cat':Builder(action=cat)}, - SCCSCOM='%(_python_)s my-sccs-get.py $TARGET') + SCCSCOM=r'%(_python_)s my-sccs-get.py $TARGET') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') env.Cat('ccc.out', 'ccc.in') diff --git a/test/Deprecated/SourceCode/SCCS/SCCSCOMSTR.py b/test/Deprecated/SourceCode/SCCS/SCCSCOMSTR.py index a757495..2351c05 100644 --- a/test/Deprecated/SourceCode/SCCS/SCCSCOMSTR.py +++ b/test/Deprecated/SourceCode/SCCS/SCCSCOMSTR.py @@ -74,7 +74,7 @@ def cat(env, source, target): f.close() env = Environment(tools = ['default', 'SCCS'], BUILDERS={'Cat':Builder(action=cat)}, - SCCSCOM='%(_python_)s my-sccs-get.py $TARGET', + SCCSCOM=r'%(_python_)s my-sccs-get.py $TARGET', SCCSCOMSTR='Checking out $TARGET from our fake SCCS') env.Cat('aaa.out', 'aaa.in') env.Cat('bbb.out', 'bbb.in') diff --git a/test/ESCAPE.py b/test/ESCAPE.py index 0651b92..819d60b 100644 --- a/test/ESCAPE.py +++ b/test/ESCAPE.py @@ -51,7 +51,7 @@ def my_escape(s): s = s.replace('file.in', 'file.xxx') return orig_escape(s) env = Environment(ESCAPE = my_escape) -env.Command('file.out', 'file.in', '%(_python_)s cat.py $TARGET $SOURCES') +env.Command('file.out', 'file.in', r'%(_python_)s cat.py $TARGET $SOURCES') """ % locals()) test.write('file.in', "file.in\n") diff --git a/test/Execute.py b/test/Execute.py index 2e53444..e63cad5 100644 --- a/test/Execute.py +++ b/test/Execute.py @@ -45,18 +45,18 @@ sys.exit(exitval) """) test.write('SConstruct', """\ -Execute('%(_python_)s my_copy.py a.in a.out') -Execute(Action('%(_python_)s my_copy.py b.in b.out')) +Execute(r'%(_python_)s my_copy.py a.in a.out') +Execute(Action(r'%(_python_)s my_copy.py b.in b.out')) env = Environment(COPY = 'my_copy.py') -env.Execute('%(_python_)s my_copy.py c.in c.out') -env.Execute(Action('%(_python_)s my_copy.py d.in d.out')) -v = env.Execute('%(_python_)s $COPY e.in e.out') +env.Execute(r'%(_python_)s my_copy.py c.in c.out') +env.Execute(Action(r'%(_python_)s my_copy.py d.in d.out')) +v = env.Execute(r'%(_python_)s $COPY e.in e.out') assert v == 0, v -v = env.Execute(Action('%(_python_)s $COPY f.in f.out')) +v = env.Execute(Action(r'%(_python_)s $COPY f.in f.out')) assert v == 0, v -v = env.Execute('%(_python_)s $COPY g.in g.out 1') +v = env.Execute(r'%(_python_)s $COPY g.in g.out 1') assert v == 1, v -v = env.Execute(Action('%(_python_)s $COPY h.in h.out 2')) +v = env.Execute(Action(r'%(_python_)s $COPY h.in h.out 2')) assert v == 2, v import shutil Execute(lambda target, source, env: shutil.copy('i.in', 'i.out')) diff --git a/test/MSVC/batch.py b/test/MSVC/batch.py index fbb3218..8648292 100644 --- a/test/MSVC/batch.py +++ b/test/MSVC/batch.py @@ -72,8 +72,8 @@ for infile in sys.argv[2:]: """) test.write('SConstruct', """ -cccom = '%(_python_)s fake_cl.py $_MSVC_OUTPUT_FLAG $CHANGED_SOURCES' -linkcom = '%(_python_)s fake_link.py ${TARGET.windows} $SOURCES' +cccom = r'%(_python_)s fake_cl.py $_MSVC_OUTPUT_FLAG $CHANGED_SOURCES' +linkcom = r'%(_python_)s fake_link.py ${TARGET.windows} $SOURCES' env = Environment(tools=['msvc', 'mslink'], CCCOM=cccom, LINKCOM=linkcom, diff --git a/test/Parallel/duplicate-children.py b/test/Parallel/duplicate-children.py index c6c5c29..8b8f4cd 100644 --- a/test/Parallel/duplicate-children.py +++ b/test/Parallel/duplicate-children.py @@ -53,8 +53,8 @@ test.write('SConstruct', """ # Test case for SCons issue #1608 # Create a file "foo.in" in the current directory before running scons. env = Environment() -env.Command('foo.out', ['foo.in'], '%(_python_)s cat.py $TARGET $SOURCE && %(_python_)s sleep.py 3') -env.Command('foobar', ['foo.out'], '%(_python_)s cat.py $TARGET $SOURCES') +env.Command('foo.out', ['foo.in'], r'%(_python_)s cat.py $TARGET $SOURCE && %(_python_)s sleep.py 3') +env.Command('foobar', ['foo.out'], r'%(_python_)s cat.py $TARGET $SOURCES') env.Depends('foobar', 'foo.out') """ % locals()) diff --git a/test/SConsignFile/default.py b/test/SConsignFile/default.py index f38aec8..4d56a5e 100644 --- a/test/SConsignFile/default.py +++ b/test/SConsignFile/default.py @@ -49,7 +49,7 @@ sys.exit(0) # test.write('SConstruct', """ SConsignFile() -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'f1.out', source = 'f1.in') env.B(target = 'f2.out', source = 'f2.in') diff --git a/test/SConsignFile/explicit-file.py b/test/SConsignFile/explicit-file.py index 33963c2..90c2241 100644 --- a/test/SConsignFile/explicit-file.py +++ b/test/SConsignFile/explicit-file.py @@ -49,7 +49,7 @@ file.close() test.write('SConstruct', """ e = Environment(XXX = 'scons') e.SConsignFile('my_${XXX}ign') -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'f5.out', source = 'f5.in') env.B(target = 'f6.out', source = 'f6.in') diff --git a/test/SConsignFile/use-dbhash.py b/test/SConsignFile/use-dbhash.py index bd9b799..f70c8b0 100644 --- a/test/SConsignFile/use-dbhash.py +++ b/test/SConsignFile/use-dbhash.py @@ -55,7 +55,7 @@ test.write('SConstruct', """ import sys import dbhash SConsignFile('.sconsign', dbhash) -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'f1.out', source = 'f1.in') env.B(target = 'f2.out', source = 'f2.in') diff --git a/test/SConsignFile/use-dumbdbm.py b/test/SConsignFile/use-dumbdbm.py index 84f1dd4..02a52da 100644 --- a/test/SConsignFile/use-dumbdbm.py +++ b/test/SConsignFile/use-dumbdbm.py @@ -55,7 +55,7 @@ test.write('SConstruct', """ import sys import dumbdbm SConsignFile('.sconsign', dumbdbm) -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'f1.out', source = 'f1.in') env.B(target = 'f2.out', source = 'f2.in') diff --git a/test/file-names.py b/test/file-names.py index 95b4e4e..d9f9c63 100644 --- a/test/file-names.py +++ b/test/file-names.py @@ -24,6 +24,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import sys import TestSCons test = TestSCons.TestSCons() @@ -38,56 +39,90 @@ test = TestSCons.TestSCons() # parsing and interpretation of redirection and piping. But that # means we have to find ways to work with *all* of their quoting # conventions. -# -# Until we sort that all out, short-circuit this test so we can -# check it in and avoid having to re-invent this wheel later. -test.pass_test() def contents(c): return "|" + c + "|\n" +invalid_chars = '/\0' + if sys.platform == 'win32': - def bad_char(c): - return c in '/\\:' -else: - def bad_char(c): - return c in '/' + invalid_chars = set(invalid_chars) -# Only worry about ASCII characters right now. -# Someone with more Unicode knowledge should enhance this later. -for i in range(1, 255): - c = chr(i) - if not bad_char(c): - test.write("in" + c + "in", contents(c)) + # See the 'naming conventions' section of + # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx + invalid_chars.update([ chr(c) for c in range(32) ]) + invalid_chars.update(r'\/:*?"<>|') + invalid_chars.update(chr(127)) -test.write('SConstruct', r""" -import sys -if sys.platform == 'win32': + # Win32 filesystems are case insensitive so don't do half the alphabet. + import string + invalid_chars.update(string.lowercase) + + # See the 'naming conventions' section of + # https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx def bad_char(c): - return (c == '/' or c == '\\' or c == ':') + return c in invalid_chars + def invalid_leading_char(c): + # the hash character as a leading character is interpreted to mean the project root + return c in ' #' + def invalid_trailing_char(c): + return c in ' .' + commandString = "copy $SOURCE $TARGET" else: + invalid_chars = set(invalid_chars) + invalid_chars.add(chr(10)) + invalid_chars.add(chr(13)) + invalid_chars.add(chr(92)) # forward slash (dirsep) + invalid_chars.add(chr(96)) # backtick + + def bad_char(c): - return (c == '/') -env = Environment() -for i in range(1, 255): - c = chr(i) - if not bad_char(c): - if c in '$': - c = '\\' + c - infile = "in" + c + "in" - env.Command(c + "out", infile, "cp $SOURCE $TARGET") - env.Command("out" + c + "out", infile, "cp $SOURCE $TARGET") - env.Command("out" + c, infile, "cp $SOURCE $TARGET") -""") + return c in invalid_chars + def invalid_leading_char(c): + # the hash character as a leading character is interpreted to mean the project root + return c in '#' + def invalid_trailing_char(c): + return False + commandString = "cp $SOURCE $TARGET" + +goodChars = [ chr(c) for c in range(1, 128) if not bad_char(chr(c)) ] + +def get_filename(ftype,c): + return ftype+"%d"%ord(c[-1])+c+ftype + +for c in goodChars: + test.write(get_filename("in",c), contents(c)) + +def create_command(a, b, c): + a = ('', 'out')[a] + b = ('', 'out')[b] + return 'env.Command("' + a + get_filename('',c) + b + '", "'+get_filename("in",c)+ '","' + commandString + '")' + +sconstruct = [ 'import sys', 'env = Environment()' ] +for c in goodChars: + if c == '$': + c = '$$' + if c == '"': + c = r'\"' + infile = get_filename("in",c) + if not invalid_leading_char(c): + sconstruct.append(create_command(False, True, c)) + sconstruct.append(create_command(True, True, c)) + if not invalid_trailing_char(c): + sconstruct.append(create_command(True, False, c)) +test.write('SConstruct', '\n'.join(sconstruct)) test.run(arguments = '.') -for i in range(1, 255): - c = chr(i) - if not bad_char(c): - test.fail_test(test.read(c + "out") != contents(c)) - test.fail_test(test.read("out" + c + "out") != contents(c)) - test.fail_test(test.read("out" + c) != contents(c)) +for c in goodChars: +# print "Checking %d "%ord(c) + + c_str = ("%d"%ord(c[-1]))+c + if not invalid_leading_char(c): + test.fail_test(test.read(c_str + "out") != contents(c)) + test.fail_test(test.read("out" + c_str + "out") != contents(c)) + if not invalid_trailing_char(c): + test.fail_test(test.read("out" + c_str) != contents(c)) test.pass_test() diff --git a/test/ignore-command.py b/test/ignore-command.py index 1343145..9fd24ab 100644 --- a/test/ignore-command.py +++ b/test/ignore-command.py @@ -49,13 +49,13 @@ sys.exit(1) test.write('SConstruct', """\ env = Environment() -f1 = env.Command('f1.out', 'f1.in', '%(_python_)s build.py $TARGET $SOURCE') -f2 = env.Command('f2.out', 'f2.in', '-%(_python_)s build.py $TARGET $SOURCE') -f3 = env.Command('f3.out', 'f3.in', '- %(_python_)s build.py $TARGET $SOURCE') -f4 = env.Command('f4.out', 'f4.in', '@-%(_python_)s build.py $TARGET $SOURCE') -f5 = env.Command('f5.out', 'f5.in', '@- %(_python_)s build.py $TARGET $SOURCE') -f6 = env.Command('f6.out', 'f6.in', '-@%(_python_)s build.py $TARGET $SOURCE') -f7 = env.Command('f7.out', 'f7.in', '-@ %(_python_)s build.py $TARGET $SOURCE') +f1 = env.Command('f1.out', 'f1.in', r'%(_python_)s build.py $TARGET $SOURCE') +f2 = env.Command('f2.out', 'f2.in', r'-%(_python_)s build.py $TARGET $SOURCE') +f3 = env.Command('f3.out', 'f3.in', r'- %(_python_)s build.py $TARGET $SOURCE') +f4 = env.Command('f4.out', 'f4.in', r'@-%(_python_)s build.py $TARGET $SOURCE') +f5 = env.Command('f5.out', 'f5.in', r'@- %(_python_)s build.py $TARGET $SOURCE') +f6 = env.Command('f6.out', 'f6.in', r'-@%(_python_)s build.py $TARGET $SOURCE') +f7 = env.Command('f7.out', 'f7.in', r'-@ %(_python_)s build.py $TARGET $SOURCE') Default(f2, f3, f4, f5, f6, f7) """ % locals()) diff --git a/test/option/debug-findlibs.py b/test/option/debug-findlibs.py index ce97199..9d5c82a 100644 --- a/test/option/debug-findlibs.py +++ b/test/option/debug-findlibs.py @@ -47,7 +47,7 @@ env = Environment(OBJSUFFIX = '.ooo', PROGSUFFIX = '.xxx', LIBS = ['iii', 'jjj', 'kkk', 'lll', 'mmm'], LIBPREFIXES = ['a-', 'b-', 'c-'], LIBSUFFIXES = ['.aaa', '.bbb', '.ccc'], - LINKCOM = '%(_python_)s cat.py $TARGET $SOURCES') + LINKCOM = r'%(_python_)s cat.py $TARGET $SOURCES') env.Program('foo', 'a.ooo',) """ % locals()) diff --git a/test/redirection.py b/test/redirection.py index 55ffeae..98bfc04 100644 --- a/test/redirection.py +++ b/test/redirection.py @@ -43,13 +43,13 @@ sys.exit(0) test.write('SConstruct', r""" env = Environment() env.Command(target='foo1', source='bar1', - action= '%(_python_)s cat.py $SOURCES > $TARGET') + action= r'%(_python_)s cat.py $SOURCES > $TARGET') env.Command(target='foo2', source='bar2', - action= '%(_python_)s cat.py < $SOURCES > $TARGET') + action= r'%(_python_)s cat.py < $SOURCES > $TARGET') env.Command(target='foo3', source='bar3', - action='%(_python_)s cat.py $SOURCES | %(_python_)s cat.py > $TARGET') + action=r'%(_python_)s cat.py $SOURCES | %(_python_)s cat.py > $TARGET') env.Command(target='foo4', source='bar4', - action='%(_python_)s cat.py <$SOURCES |%(_python_)s cat.py >$TARGET') + action=r'%(_python_)s cat.py <$SOURCES |%(_python_)s cat.py >$TARGET') """ % locals()) test.write('bar1', 'bar1\r\n') diff --git a/test/silent-command.py b/test/silent-command.py index 7704ee5..b0e4a2e 100644 --- a/test/silent-command.py +++ b/test/silent-command.py @@ -48,13 +48,13 @@ fp.close() test.write('SConstruct', """\ env = Environment() -env.Command('f1.out', 'f1.in', '%(_python_)s build.py $TARGET $SOURCE') -env.Command('f2.out', 'f2.in', '@%(_python_)s build.py $TARGET $SOURCE') -env.Command('f3.out', 'f3.in', '@ %(_python_)s build.py $TARGET $SOURCE') -env.Command('f4.out', 'f4.in', '@-%(_python_)s build.py $TARGET $SOURCE') -env.Command('f5.out', 'f5.in', '@- %(_python_)s build.py $TARGET $SOURCE') -env.Command('f6.out', 'f6.in', '-@%(_python_)s build.py $TARGET $SOURCE') -env.Command('f7.out', 'f7.in', '-@ %(_python_)s build.py $TARGET $SOURCE') +env.Command('f1.out', 'f1.in', r'%(_python_)s build.py $TARGET $SOURCE') +env.Command('f2.out', 'f2.in', r'@%(_python_)s build.py $TARGET $SOURCE') +env.Command('f3.out', 'f3.in', r'@ %(_python_)s build.py $TARGET $SOURCE') +env.Command('f4.out', 'f4.in', r'@-%(_python_)s build.py $TARGET $SOURCE') +env.Command('f5.out', 'f5.in', r'@- %(_python_)s build.py $TARGET $SOURCE') +env.Command('f6.out', 'f6.in', r'-@%(_python_)s build.py $TARGET $SOURCE') +env.Command('f7.out', 'f7.in', r'-@ %(_python_)s build.py $TARGET $SOURCE') """ % locals()) test.write('f1.in', "f1.in\n") diff --git a/test/special-filenames.py b/test/special-filenames.py index 00e4a3d..de09a52 100644 --- a/test/special-filenames.py +++ b/test/special-filenames.py @@ -69,7 +69,7 @@ def buildFileStr(fn): xxx = '\n'.join(map(buildFileStr, file_names)) test.write("SConstruct", """ -env=Environment(BUILDERS = {'Build' : Builder(action = '%(_python_)s cat.py $TARGET $SOURCE')}) +env=Environment(BUILDERS = {'Build' : Builder(action = r'%(_python_)s cat.py $TARGET $SOURCE')}) %(xxx)s """ % locals()) diff --git a/test/srcchange.py b/test/srcchange.py index d181297..f2fde91 100644 --- a/test/srcchange.py +++ b/test/srcchange.py @@ -63,7 +63,7 @@ SubRevision = Action(subrevision) env=Environment() content_env=env.Clone() -content_env.Command('revision.in', [], '%(_python_)s getrevision > $TARGET') +content_env.Command('revision.in', [], r'%(_python_)s getrevision > $TARGET') content_env.AlwaysBuild('revision.in') env.Precious('main.c') env.Command('main.c', 'revision.in', SubRevision) diff --git a/test/subdir.py b/test/subdir.py index fa10cff..22d0912 100644 --- a/test/subdir.py +++ b/test/subdir.py @@ -42,7 +42,7 @@ file.close() """) test.write('SConstruct', """ -B = Builder(action = '%(_python_)s build.py $TARGETS $SOURCES') +B = Builder(action = r'%(_python_)s build.py $TARGETS $SOURCES') env = Environment(BUILDERS = { 'B' : B }) env.B(target = 'subdir/f1.out', source = 'subdir/f1.in') env.B(target = 'subdir/f2.out', source = 'subdir/f2.in') |