From 1536284a15743f6ec41d3230177a24d245158a9d Mon Sep 17 00:00:00 2001 From: Tobias Markmann Date: Fri, 13 Jul 2018 17:20:36 +0200 Subject: Update SCons in 3rdParty from 2.4.0 to 3.0.1 This also has our scons patch in 3rdParty/SCons applied. Test-Information: Builds with unit tests on macOS 10.13.6. Change-Id: I25d3662eeec27a76dab10d501ba46dc16f0bef4b diff --git a/3rdParty/SCons/scons-2.4.0/CHANGES.txt b/3rdParty/SCons/scons-2.4.0/CHANGES.txt deleted file mode 100644 index 5f96a23..0000000 --- a/3rdParty/SCons/scons-2.4.0/CHANGES.txt +++ /dev/null @@ -1,5899 +0,0 @@ - - - SCons - a software construction tool - - Change Log - -RELEASE 2.4.0 - Mon, 21 Sep 2015 09:07:51 -0700 - - From Dirk Baechle: - - Switched several core classes to use "slots", to - reduce the overall memory consumption in large - projects (fixes #2180, #2178, #2198) - - Memoizer counting uses decorators now, instead of - the old metaclasses approach. - - From Andrew Featherstone - - Fixed typo in SWIGPATH description - -RELEASE 2.3.6 - Mon, 31 Jul 2015 14:35:03 -0700 - - From Rob Smith: - - Added support for Visual Studio 2015 - -RELEASE 2.3.5 - Mon, 17 Jun 2015 21:07:32 -0700 - - From Stephen Pollard: - - Documentation fixes for libraries.xml and - builders-writing.xml (#2989 and #2990) - - From William Deegan: - - Extended docs for InstallVersionedLib/SharedLibrary, - and added SKIP_WIN_PACKAGES argument to build script - bootstrap.py (PR #230, #3002). - - From William Blevins: - - Fixed symlink support (PR #227, #2395). - - Updated debug-count test case (PR #229). - - From Alexey Klimkin: - - Fixed incomplete LIBS flattening and substitution in - Program scanner(PR #205, #2954). - - From Dirk Baechle: - - Added new method rentry_exists_on_disk to Node.FS (PR #193). - - From Russel Winder: - - Fixed several D tests under the different OS. - - Add support for f08 file extensions for Fortran 2008 code. - - From Anatoly Techtonik: - - Show --config choices if no argument is specified (PR #202). - - Fixed build crash when XML toolchain isn't installed, and - activated compression for ZIP archives. - - From Alexandre Feblot: - - Fix for VersionedSharedLibrary under 'sunos' platform. - - Fixed dll link with precompiled headers on MSVC 2012 - - Added an 'exclude' parameter to Glob() - - From Laurent Marchelli: - - Support for multiple cmdargs (one per variant) in VS project files. - - Various improvements for TempFileMunge class. - - Added an implementation for Visual Studio users files (PR #209). - - From Dan Pidcock: - - Added support for the 'PlatformToolset' tag in VS project files (#2978). - - From James McCoy: - - Added support for '-isystem' to ParseFlags. - -RELEASE 2.3.4 - Mon, 27 Sep 2014 12:50:35 -0400 - - From Bernhard Walle and Dirk Baechle: - - Fixed the interactive mode, in connection with - Configure contexts (#2971). - - From Anatoly Techtonik: - - Fix EnsureSConsVersion warning when running packaged version - - From Russel Winder: - - Fix D tools for building shared libraries - -RELEASE 2.3.3 - Sun, 24 Aug 2014 21:08:33 -0400 - - From Roland Stark: - - Fixed false line length calculation in the TempFileMunge class (#2970). - - From Gary Oberbrunner: - - Improve SWIG detection - - From Russel Winder: - - Fix regression on Windows in D language update - - From Anatoly Techtonik: - - Do not fail on EnsureSConsVersion when running from checkout - - From Kendrick Boyd and Rob Managan: - - Fixed the newglossary action to work with VariantDir (LaTeX). - - From Manuel Francisco Naranjo: - - Added a default for the BUILDERS environment variable, - to prevent not defined exception on a Clone(). - - From Andrew Featherstone: - - Added description of CheckTypeSize method (#1991). - - Fixed handling of CPPDEFINE var in Append() - for several list-dict combinations (#2900). - - From William Blevins: - - Added test for Java derived-source dependency tree generation. - - Added Copy Action symlink soft-copy support (#2395). - - Various contributions to the documentation (UserGuide). - -RELEASE 2.3.2 - - From veon on bitbucket: - - Fixed handling of nested ifs in CPP scanner PreProcessor class. - - From Michael Haubenwallner: - - Respect user's CC/CXX values; don't always overwrite in generate() - - Delegate linker Tool.exists() to CC/CXX Tool.exists(). - - From Amir Szekely: - - Fixed NoClean() for multi-target builders (#2353). - - From Russel Winder: - - Revamp of the D language support. Tools for DMD, GDC and LDC provided - and integrated with the C and C++ linking. NOTE: This is only tested - with D v2. Support for D v1 is now deprecated. - - From Paweł Tomulik: - - Fix SConf tests that write output - - From Gary Oberbrunner: - - get default RPM architecture more robustly when building RPMs - - From Shane Gannon: - - Support for Visual Studio 2013 (12.0) - - From Sye van der Veen: - - Support for Visual Studio 12.0Exp, and fixes for earlier MSVS - versions. - - From Anatoly Techtonik: - - Several improvements for running scons.py from source: - * engine files form source directory take priority over all other - importable versions - * message about scons.py running from source is removed to fix tests - that were failing because of this extra line in the output - * error message when SCons import fails now lists lookup paths - - Remove support for QMTest harness from runtest.py - - Remove RPM and m4 from default tools on Windows - - BitKeeper, CVS, Perforce, RCS, SCCS are deprecated from default - tools and will be removed in future SCons versions to speed up - SCons initialization (it will still be possible to use these tools - explicitly) - - From Dirk Baechle: - - Update XML doc editor configuration - - Fix: Allow varlist to be specified as list of strings for Actions (#2754) - - From Rob Managan: - - Updated the TeX builder to support use of the -synctex=1 - option and the files it creates. - - Updated the TeX builder to correctly clean auxiliary files when - the biblatex package is used. - -RELEASE 2.3.1 - - From Andrew Featherstone: - - Added support for EPUB output format to the DocBook tool. - - From Tom Tanner: - - Stop leaking file handles to subprocesses by switching to using subprocess - always. - - Allow multiple options to be specified with --debug=a,b,c - - Add support for a readonly cache (--cache-readonly) - - Always print stats if requested - - Generally try harder to print out a message on build errors - - Adds a switch to warn on missing targets - - Add Pseudo command to mark targets which should not exist after - they are built. - - From Bogdan Tenea: - - Check for 8.3 filenames on cygwin as well as win32 to make variant_dir work properly. - - From Alexandre Feblot: - - Make sure SharedLibrary depends on all dependent libs (by depending on SHLINKCOM) - - From Stefan Sperling: - - Fixed the setup of linker flags for a versioned SharedLibrary - under OpenBSD (#2916). - - From Antonio Cavallo: - - Improve error if Visual Studio bat file not found. - - From Manuel Francisco Naranjo: - - Allow Subst.Literal string objects to be compared with each other, - so they work better in AddUnique() and Remove(). - - From David Rothenberger: - - Added cyglink linker that uses Cygwin naming conventions for - shared libraries and automatically generates import libraries. - - From Dirk Baechle: - - Update bootstrap.py so it can be used from any dir, to run - SCons from a source (non-installed) dir. - - Count statistics of instances are now collected only when - the --debug=count command-line option is used (#2922). - - Added release_target_info() to File nodes, which helps to - reduce memory consumption in clean builds and update runs - of large projects. - - Fixed the handling of long options in the command-line - parsing (#2929). - - Fixed misspelled variable in intelc.py (#2928). - - From Gary Oberbrunner: - - Test harness: fail_test() can now print a message to help debugging. - - From Anatoly Techtonik: - - Require rpmbuild when building SCons package. - - Print full stack on certain errors, for debugging. - - Improve documentation for Textfile builder. - - From William Deegan: - - VS2012 & VS2010 Resolve initialization issues by adding path to reg.exe - in shell used to run batch files. - - MSVC Support fixed defaulting TARGET_ARCH to HOST_ARCH. It should be - None if not explicitly set. - - MSVC Fixed issue where if more than one Architectures compilers are - detected, it would take the last one found, and not the first. - - From Philipp Kraus: - - Added optional ZIPROOT to Zip tool. - - From Dirk Baechle: - - Replaced old SGML-based documentation toolchain with a more modern - approach, that also requires less external dependencies (programs and - Python packages). Added a customized Docbook XSD for strict validation of - all input XML files. - - From Luca Falavigna: - - Fixed spelling errors in MAN pages (#2897). - - From Michael McDougall: - - Fixed description of ignore_case for EnumVariable in the - MAN page (#2774). - -RELEASE 2.3.0 - Mon, 02 Mar 2013 13:22:29 -0400 - - From Anatoly Techtonik: - - Added ability to run scripts/scons.py directly from source checkout - - Hide deprecated --debug={dtree,stree,tree} from --help output - - Error messages from option parser now include hints about valid choices - - Cleaned up some Python 1.5 and pre-2.3 code, so don't expect SCons - to run on anything less than Python 2.4 anymore - - Several fixes for runtest.py: - * exit with an error if no tests were found - * removed --noqmtest option - this behavior is by default - * replaced `-o FILE --xml` combination with `--xml FILE` - * changed `-o, --output FILE` option to capture stdout/stderr output - from runtest.py - - Remove os_spawnv_fix.diff patch required to enable parallel builds - support prior to Python 2.2 - - From Juan Lang: - - Fix WiX Tool to use .wixobj rather than .wxiobj for compiler output - - Support building with WiX releases after 2.0 - - From Alexey Klimkin: - - Fix nested LIBPATH expansion by flattening sequences in subst_path. - - From eyan on Bitbucket: - - Print target name with command execution time with --debug=time - - From Thomas Berg and Evgeny Podjachev: - - Fix subprocess spawning on Windows. Work around a Windows - bug that can crash python occasionally when using -jN. (#2449) - - From Dirk Baechle: - - Updated test framework to support dir and file fixtures and - added ability to test external (out-of-tree) tools (#2862). - See doc in QMTest/test-framework.rst. - - Fixed several errors in the test suite (Java paths, MSVS version - detection, Tool import), additionally - * provided MinGW command-line support for the CXX, AS and - Fortran tests, - * refactored the detection of the gcc version and the according - Fortran startup library, - * provided a new module rpmutils.py, wrapping the RPM naming rules - for target files and further hardware-dependent info (compatibility, - compiler flags, ...), - * added new test methods must_exist_one_of() and - must_not_exist_any_of() and - * removed Aegis support from runtest.py. (#2872) - - From Gary Oberbrunner: - - Add -jN support to runtest.py to run tests in parallel - - Add MSVC10 and MSVC11 support to get_output low-level bat script runner. - - Fix MSVS solution generation for VS11, and fixed tests. - - From Rob Managan: - - Updated the TeX builder to support the \newglossary command - in LaTeX's glossaries package and the files it creates. - - Improve support for new versions of biblatex in the TeX builder - so biber is called automatically if biblatex requires it. - - Add SHLIBVERSION as an option that tells SharedLibrary to build - a versioned shared library and create the required symlinks. - Add builder InstallVersionedLib to create the required symlinks - installing a versioned shared library. - -RELEASE 2.2.0 - Mon, 05 Aug 2012 15:37:48 +0000 - - From dubcanada on Bitbucket: - - Fix 32-bit Visual Express C++ on 64-bit Windows (generate 32-bit code) - - From Paweł Tomulik: - - Added gettext toolset - - Fixed FindSourceFiles to find final sources (leaf nodes). - - From Greg Ward: - - Allow Node objects in Java path (#2825) - - From Joshua Hughes: - - Make Windows not redefine builtin file as un-inheritable (#2857) - - Fix WINDOWS_INSERT_DEF on MinGW (Windows) (#2856) - - From smallbub on Bitbucket: - - Fix LINKCOMSTR, SHLINKCOMSTR, and LDMODULECOMSTR on Windows (#2833). - - From Mortoray: - - Make -s (silent mode) be silent about entering subdirs (#2976). - - Fix cloning of builders when cloning environment (#2821). - - From Gary Oberbrunner: - - Show valid Visual Studio architectures in error message - when user passes invalid arch. - - From Alexey Petruchik: - - Support for Microsoft Visual Studio 11 (both using it - and generating MSVS11 solution files). - - From Alexey Klimkin: - - Fixed the Taskmaster, curing spurious build failures in - multi-threaded runs (#2720). - - From Dirk Baechle: - - Improved documentation of command-line variables (#2809). - - Fixed scons-doc.py to properly convert main XML files (#2812). - - From Rob Managan: - - Updated the TeX builder to support LaTeX's multibib package. - - Updated the TeX builder to support LaTeX's biblatex package. - - Added support for using biber instead of bibtex by setting - env['BIBTEX'] = 'biber' - - From Arve Knudsen: - - Test for FORTRANPPFILESUFFIXES (#2129). - - -RELEASE 2.1.0 - Mon, 09 Sep 2011 20:54:57 -0700 - - From Anton Lazarev: - - Fix Windows resource compiler scanner to accept DOS line endings. - - From Matthias: - - Update MSVS documents to remove note indicating that only one - project is currently supported per solution file. - - From Grzegorz Bizoń: - - Fix long compile lines in batch mode by using TEMPFILE - - Fix MSVC_BATCH=False (was treating it as true) - - From Justin Gullingsrud: - - support -std=c++0x and related CXXFLAGS in pkgconfig (ParseFlags) - - From Vincent Beffara: - - Support -dylib_file in pkgconfig (ParseFlags) - - From Gary Oberbrunner and Sohail Somani: - - new construction variable WINDOWS_EMBED_MANIFEST to automatically - embed manifests in Windows EXEs and DLLs. - - From Gary Oberbrunner: - - Fix Visual Studio project generation when CPPPATH contains Dir nodes - - Ensure Visual Studio project is regenerated when CPPPATH or CPPDEFINES change - - Fix unicode error when using non-ASCII filenames with Copy or Install - - Put RPATH in LINKCOM rather than LINKFLAGS so resetting - LINKFLAGS doesn't kill RPATH - - Fix precompiled headers on Windows when variant dir name has spaces. - - Adding None to an Action no longer fails (just returns original action) - - New --debug=prepare option to show each target as it's being - prepared, whether or not anything needs to be done for it. - - New debug option --debug=duplicate to print a line for each - unlink/relink (or copy) of a variant file from its source file. - - Improve error message for EnumVariables to show legal values. - - Fix Intel compiler to sort versions >9 correctly (esp. on Linux) - - Fix Install() when the source and target are directories and the - target directory exists. - - From David Garcia Garzon: - - Fix Delete to be able to delete broken symlinks and dir - symlinks. - - From Imran Fanaswala and Robert Lehr: - - Handle .output file generated by bison/yacc properly. Cleaning it - when necessary. - - From Antoine Dechaume: - - Handle SWIG file where there is whitespace after the module name - properly. Previously the generated files would include - the whitespace. - - From Dmitry R.: - - Handle Environment in case __semi_deepcopy is None - - From Benoit Belley: - - - Much improved support for Windows UNC paths (\\SERVERNAME). - - From Jean-Baptiste Lab: - - - Fix problems with appending CPPDEFINES that contain - dictionaries, and related issues with Parse/MergeFlags and - CPPDEFINES. - - From Allen Weeks: - - - Fix for an issue with implicit-cache with multiple targets - when dependencies are removed on disk. - - From Evgeny Podjachev and Alexey Petruchick: - - - Support generation of Microsoft Visual Studio 2008 (9.0) - and 2010 (10.0) project and solution files. - - From Ken Deeter: - - - Fix a problem when FS Entries which are actually Dirs have builders. - - From Luca Falavigna: - - - Support Fortran 03 - - From Gary Oberbrunner: - - - Print the path to the SCons package in scons --version - - From Jean-Fran�ois Colson: - - - Improve Microsoft Visual Studio Solution generation, and fix - various errors in the generated solutions especially when using - MSVS_SCC_PROVIDER, and when generating multiple projects. The - construction variable MSVS_SCC_PROJECT_BASE_PATH, which never - worked properly, is removed. Users can use the new variable - MSVS_SCC_CONNECTION_ROOT instead if desired. - - From Anatoly Techtonik: - - - Use subprocess in bootstrap.py instead of os.execve to avoid - losing output control on Windows (http://bugs.python.org/issue9148) - - - Revert patch for adding SCons to App Paths, because standard cmd - shell doesn't search there. This is confusing, because `scons` can - be executed from explorer, but fail to start from console. - - - Fix broken installation with easy_install on Windows (issue #2051) - SCons traditionally installed in a way that allowed to run multiple - versions side by side. This custom logic was incompatible with - easy_install way of doing things. - - - Use epydoc module for generating API docs in HTML if command line - utility is not found in PATH. Actual for Windows. - - From Alexander Goomenyuk: - - - Add .sx to assembly source scanner list so .sx files - get their header file dependencies detected. - - From Arve Knudsen: - - - Set module metadata when loading site_scons/site_init.py - so it is treated as a proper module; __doc__, __file__ and - __name__ now refer to the site_init.py file. - - From Russel Winder: - - - Users Guide updates explaining that Tools can be packages as - well as python modules. - - From Gary Oberbrunner: - - - New systemwide and per-user site_scons dirs. - - From Dirk Baechle: - - - XML fixes in User's Guide. - - Fixed the detection of 'jar' and 'rmic' during - the initialization of the respective Tools (#2730). - - Improved docs for custom Decider functions and - custom Scanner objects (#2711, #2713). - - Corrected SWIG module names for generated *.i files (#2707). - - From Joe Zuntz: - - - Fixed a case-sensitivity problem with Fortran modules. - - From Bauke Conijn: - - - Added Users Guide example for auto-generated source code - - From Steven Knight: - - - Fix explicit dependencies (Depends()) on Nodes that don't have - attached Builders. - - - Fix use of the global Alias() function with command actions. - - From Matt Hughes: - - - Fix the ability to append to default $*FLAGS values (which are - implemented as CLVar instances) in a copied construction environment - without affecting the original construction environment's value. - - From Rob Managan: - - - Updated the TeX command strings to include a /D on Windows in - case the new directory is on a different drive letter. - - - Fixed the LaTeX scanner so dependencies are found in commands that - are broken across lines with a comment or have embedded spaces. - - - The TeX builders should now work with tex files that are generated - by another program. Thanks to Hans-Martin von Gaudecker for - isolating the cause of this bug. - - - Added support for INDEXSTYLE environment variable so makeindex can - find style files. - - - Added support for the bibunits package so we call bibtex on all - the bu*.aux files. - - - Add support of finding path information on OSX for TeX applications - MacPorts and Fink paths need to be added by the user - - From Russel Winder: - - - Add support for DMD version 2 (the phobos2 library). - - From William Deegan: - - - Add initial support for VS/VC 2010 (express and non-express versions) - - Remove warning for not finding MS VC/VS install. - "scons: warning: No version of Visual Studio compiler found - - C/C++ compilers most likely not set correctly" - - Add support for Linux 3.0 - - -RELEASE 2.0.1 - Mon, 15 Aug 2010 15:46:32 -0700 - - From Dirk Baechle: - - - Fix XML in documentation. - - From Joe Zuntz: - - - Fixed a case-sensitivity problem with Fortran modules. - - From Bauke Conijn: - - - Added Users Guide example for auto-generated source code - - From Steven Knight: - - - Fix explicit dependencies (Depends()) on Nodes that don't have - attached Builders. - - From Matt Hughes: - - - Fix the ability to append to default $*FLAGS values (which are - implemented as CLVar instances) in a copied construction environment - without affecting the original construction environment's value. - - From Rob Managan: - - - Updated the TeX command strings to include a /D on Windows in - case the new directory is on a different drive letter. - - - Fixed the LaTeX scanner so dependencies are found in commands that - are broken across lines with a comment or have embedded spaces. - - -RELEASE 2.0.0.final.0 - Mon, 14 Jun 2010 22:01:37 -0700 - - From Dirk Baechle: - - - Fix XML in documentation. - - From Steven Knight: - - - Provide forward compatibility for the 'profile' module. - - - Provide forward compatibility for the 'pickle' module. - - - Provide forward compatibility for the 'io' module. - - - Provide forward compatibility for the 'queue' module. - - - Provide forward compatibility for the 'collections' module. - - - Provide forward compatibility for the 'builtins' module. - - - Provide forward compatibility for 'sys.intern()'. - - - Convert to os.walk() from of os.path.walk(). - - - Remove compatibility logic no longer needed. - - - Add a '-3' option to runtest to print 3.x incompatibility warnings. - - - Convert old-style classes into new-style classes. - - - Fix "Ignoring corrupt sconsign entry" warnings when building - in a tree with a pre-2.0 .sconsign file. - - - Fix propagation from environment of VS*COMNTOOLS to resolve issues - initializing MSVC/MSVS/SDK issues. - - - Handle detecting Visual C++ on Python verions with upper-case - platform architectures like 'AMD64'. - - From W. Trevor King: - - - Revisions to README. - - From Greg Noel: - - - Apply numerous Python fixers to update code to more modern idioms. - Find where fixers should be applied to code in test strings and - apply the fixers there, too. - - - Write a fixer to convert string functions to string methods. - - - Modify the 'dict' fixer to be less conservative. - - - Modify the 'apply' fixer to handle more cases. - - - Create a modified 'types' fixer that converts types to 2.x - equivalents rather than 3.x equivalents. - - - Write a 'division' fixer to highlight uses of the old-style - division operator. Correct usage where needed. - - - Add forward compatibility for the new 'memoryview' function - (which replaces the 'buffer' function). - - - Add forward compatibility for the 'winreg' module. - - - Remove no-longer-needed 'platform' module. - - - Run tests with the '-3' option to Python 2.6 and clear up - various reported incompatibilities. - - - Comb out code paths specialized to Pythons older than 2.4. - - - Update deprecation warnings; most now become mandatory. - - - Start deprecation cycle for BuildDir() and build_dir. - - - Start deprecation cycle for SourceCode() and related factories - - - Fixed a problem with is_Dict() not identifying some objects derived - from UserDict. - - From Jim Randall: - - - Document the AllowSubstExceptions() function in the User's Guide. - - From William Deegan: - - - Migrate MSVC/MSVS/SDK improvements from 1.3 branch. - - -RELEASE 1.3.0 - Tue, 23 Mar 2010 21:44:19 -0400 - - From Steven Knight: - - - Update man page and documentation. - - From William Deegan (plus minor patch from Gary Oberbrunner): - - - Support Visual Studio 8.0 Express - -RELEASE 1.2.0.d20100306 - Sat, 06 Mar 2010 16:18:33 -0800 - - From Luca Falavigna: - - - Fix typos in the man page. - - From Gottfried Ganssauge: - - - Support execution when SCons is installed via easy_install. - - From Steven Knight: - - - Make the messages for Configure checks of compilers consistent. - - - Issue an error message if a BUILDERS entry is not a Builder - object or a callable wrapper. - - From Rob Managan: - - - Update tex builder to handle the case where a \input{foo} - command tries to work with a directory named foo instead of the - file foo.tex. The builder now ignores a directory and continues - searching to find the correct file. Thanks to Lennart Sauerbeck - for the test case and initial patch - - Also allow the \include of files in subdirectories when variantDir - is used with duplicate=0. Previously latex would crash since - the directory in which the .aux file is written was not created. - Thanks to Stefan Hepp for finding this and part of the solution. - - From James Teh: - - Patches to fix some issues using MS SDK V7.0 - - From William Deegan: - - Lots of testing and minor patches to handle mixed MS VC and SDK - installations, as well as having only the SDK installed. - - -RELEASE 1.2.0.d20100117 - Sun, 17 Jan 2010 14:26:59 -0800 - - From Jim Randall: - - Fixed temp filename race condition on Windows with long cmd lines. - - From David Cournapeau: - - Fixed tryRun when sconf directory is in a variant dir. - - Do not add -fPIC for ifort tool on non-posix platforms (darwin and - windows). - - Fix bug 2294 (spurious CheckCC failures). - - Fix scons bootstrap process on windows 64 (wrong wininst name) - - From William Deegan: - - Final merge from vs_revamp branch to main - - - Added definition and usage of HOST_OS, HOST_ARCH, TARGET_OS, - TARGET_ARCH, currently only defined/used by Visual Studio - Compilers. This will be rolled out to other platforms/tools - in the future. - - - Add check for python >= 3.0.0 and exit gracefully. - For 1.3 python >= 1.5.2 and < 3.0.0 are supported - - - Fix bug 1944 - Handle non-existent .i file in swig emitter, previously - it would crash with an IOError exception. Now it will try to make an - educated guess on the module name based on the filename. - - From Lukas Erlinghagen: - - - Have AddOption() remove variables from the list of - seen-but-unknown variables (which are reported later). - - - An option name and aliases can now be specified as a tuple. - - From Hartmut Goebel: - - - Textfile builder. - - From Jared Grubb: - - - use "is/is not" in comparisons with None instead of "==" or "!=". - - From Jim Hunziker: - - - Avoid adding -gphobos to a command line multiple times - when initializing use of the DMD compiler. - - From Jason Kenney: - - - Sugguested HOST/TARGET OS/ARCH separation. - - From Steven Knight: - - - Fix the -n option when used with VariantDir(duplicate=1) - and the variant directory doesn't already exist. - - - Fix scanning of Unicode files for both UTF-16 endian flavors. - - - Fix a TypeError on #include of file names with Unicode characters. - - - Fix an exception if a null command-line argument is passed in. - - - Evaluate Requires() prerequisites before a Node's direct children - (sources and dependencies). - - From Greg Noel: - - - Remove redundant __metaclass__ initializations in Environment.py. - - - Correct the documentation of text returned by sconf.Result(). - - - Document that filenames with '.' as the first character are - ignored by Glob() by default (matching UNIX glob semantics). - - - Fix SWIG testing infrastructure to work on Mac OS X. - - - Restructure a test that occasionally hung so that the test would - detect when it was stuck and fail instead. - - - Substfile builder. - - From Gary Oberbrunner: - - - When reporting a target that SCons doesn't know how to make, - specify whether it's a File, Dir, etc. - - From Ben Webb: - - - Fix use of $SWIGOUTDIR when generating Python wrappers. - - - Add $SWIGDIRECTORSUFFIX and $SWIGVERSION construction variables. - - From Rob Managan: - - - Add -recorder flag to Latex commands and updated internals to - use the output to find files TeX creates. This allows the MiKTeX - installations to find the created files - - - Notify user of Latex errors that would get buried in the - Latex output - - - Remove LATEXSUFFIXES from environments that don't initialize Tex. - - - Add support for the glossaries package for glossaries and acronyms - - - Fix problem that pdftex, latex, and pdflatex tools by themselves did - not create the actions for bibtex, makeindex,... by creating them - and other environment settings in one routine called by all four - tex tools. - - - Fix problem with filenames of sideeffects when the user changes - the name of the output file from the latex default - - - Add scanning of files included in Latex by means of \lstinputlisting{} - Patch from Stefan Hepp. - - - Change command line for epstopdf to use --outfile= instead of -o - since this works on all platforms. - Patch from Stefan Hepp. - - - Change scanner to properly search for included file from the - directory of the main file instead of the file it is included from. - Also update the emitter to add the .aux file associated with - \include{filename} commands. This makes sure the required directories - if any are created for variantdir cases. - Half of the patch from Stefan Hepp. - -RELEASE 1.2.0.d20090223 - Mon, 23 Feb 2009 08:41:06 -0800 - - From Stanislav Baranov: - - - Make suffix-matching for scanners case-insensitive on Windows. - - From David Cournapeau: - - - Change the way SCons finds versions of Visual C/C++ and Visual - Studio to find and use the Microsoft v*vars.bat files. - - From Robert P. J. Day: - - - User's Guide updates. - - From Dan Eaton: - - - Fix generation of Visual Studio 8 project files on x64 platforms. - - From Allan Erskine: - - - Set IncludeSearchPath and PreprocessorDefinitions in generated - Visual Studio 8 project files, to help IntelliSense work. - - From Mateusz Gruca: - - - Fix deletion of broken symlinks by the --clean option. - - From Steven Knight: - - - Fix the error message when use of a non-existent drive on Windows - is detected. - - - Add sources for files whose targets don't exist in $CHANGED_SOURCES. - - - Detect implicit dependencies on commands even when the command is - quoted. - - - Fix interaction of $CHANGED_SOURCES with the --config=force option. - - - Fix finding #include files when the string contains escaped - backslashes like "C:\\some\\include.h". - - - Pass $CCFLAGS to Visual C/C++ precompiled header compilation. - - - Remove unnecessary nested $( $) around $_LIBDIRFLAGS on link lines - for the Microsoft linker, the OS/2 ilink linker and the Phar Lap - linkloc linker. - - - Spell the Windows environment variables consistently "SystemDrive" - and "SystemRoot" instead of "SYSTEMDRIVE" and "SYSTEMROOT". - - - -RELEASE 1.2.0.d20090113 - Tue, 13 Jan 2009 02:50:30 -0800 - - From Stanislav Baranov, Ted Johnson and Steven Knight: - - - Add support for batch compilation of Visual Studio C/C++ source - files, controlled by a new $MSVC_BATCH construction variable. - - From Steven Knight: - - - Print the message, "scons: Build interrupted." on error output, - not standard output. - - - Add a --warn=future-deprecated option for advance warnings about - deprecated features that still have warnings hidden by default. - - - Fix use of $SOURCE and $SOURCES attributes when there are no - sources specified in the Builder call. - - - Add support for new $CHANGED_SOURCES, $CHANGED_TARGETS, - $UNCHANGED_SOURCES and $UNCHANGED_TARGETS variables. - - - Add general support for batch builds through new batch_key= and - targets= keywords to Action object creation. - - From Arve Knudsen: - - - Make linker tools differentiate properly between SharedLibrary - and LoadableModule. - - - Document TestCommon.shobj_prefix variable. - - - Support $SWIGOUTDIR values with spaces. - - From Rob Managan: - - - Don't automatically try to build .pdf graphics files for - .eps files in \includegraphics{} calls in TeX/LaTeX files - when building with the PDF builder (and thus using pdflatex). - - From Gary Oberbrunner: - - - Allow AppendENVPath() and PrependENVPath() to interpret '#' - for paths relative to the top-level SConstruct directory. - - - Use the Borland ilink -e option to specify the output file name. - - - Document that the msvc Tool module uses $PCH, $PCHSTOP and $PDB. - - - Allow WINDOWS_INSERT_DEF=0 to disable --output-def when linking - under MinGW. - - From Zia Sobhani: - - - Fix typos in the User's Guide. - - From Greg Spencer: - - - Support implicit dependency scanning of files encoded in utf-8 - and utf-16. - - From Roberto de Vecchi: - - - Remove $CCFLAGS from the the default definitions of $CXXFLAGS for - Visual C/C++ and MIPSpro C++ on SGI so, they match other tools - and avoid flag duplication on C++ command lines. - - From Ben Webb: - - - Handle quoted module names in SWIG source files. - - - Emit *_wrap.h when SWIG generates header file for directors - - From Matthew Wesley: - - - Copy file attributes so we identify, and can link a shared library - from, shared object files in a Repository. - - - -RELEASE 1.2.0 - Sat, 20 Dec 2008 22:47:29 -0800 - - From Steven Knight: - - - Don't fail if can't import a _subprocess module on Windows. - - - Add warnings for use of the deprecated Options object. - - - -RELEASE 1.1.0.d20081207 - Sun, 07 Dec 2008 19:17:23 -0800 - - From Benoit Belley: - - - Improve the robustness of GetBuildFailures() by refactoring - SCons exception handling (especially BuildError exceptions). - - - Have the --taskmastertrace= option print information about - individual Task methods, not just the Taskmaster control flow. - - - Eliminate some spurious dependency cycles by being more aggressive - about pruning pending children from the Taskmaster walk. - - - Suppress mistaken reports of a dependency cycle when a child - left on the pending list is a single Node in EXECUTED state. - - From David Cournapeau: - - - Fix $FORTRANMODDIRPREFIX for the ifort (Intel Fortran) tool. - - From Brad Fitzpatrick: - - - Don't pre-generate an exception message (which will likely be - ignored anyway) when an EntryProxy re-raises an AttributeError. - - From Jared Grubb: - - - Clean up coding style and white space in Node/FS.py. - - - Fix a typo in the documentation for $_CPPDEFFLAGS. - - - Issue 2401: Fix usage of comparisons with None. - - From Ludwig H�hne: - - - Handle Java inner classes declared within a method. - - From Steven Knight: - - - Fix label placement by the "scons-time.py func" subcommand - when a profile value was close to (or equal to) 0.0. - - - Fix env.Append() and env.Prepend()'s ability to add a string to - list-like variables like $CCFLAGS under Python 2.6. - - - Other Python2.6 portability: don't use "as" (a Python 2.6 keyword). - Don't use the deprecated Exception.message attribute. - - - Support using the -f option to search for a different top-level - file name when walking up with the -D, -U or -u options. - - - Fix use of VariantDir when the -n option is used and doesn't, - therefore, actually create the variant directory. - - - Fix a stack trace from the --debug=includes option when passed a - static or shared library as an argument. - - - Speed up the internal find_file() function (used for searching - CPPPATH, LIBPATH, etc.). - - - Add support for using the Python "in" keyword on construction - environments (for example, if "CPPPATH" in env: ...). - - - Fix use of Glob() when a repository or source directory contains - an in-memory Node without a corresponding on-disk file or directory. - - - Add a warning about future reservation of $CHANGED_SOURCES, - $CHANGED_TARGETS, $UNCHANGED_SOURCES and $UNCHANGED_TARGETS. - - - Enable by default the existing warnings about setting the resource - $SOURCE, $SOURCES, $TARGET and $TARGETS variable. - - From Rob Managan: - - - Scan for TeX files in the paths specified in the $TEXINPUTS - construction variable and the $TEXINPUTS environment variable. - - - Configure the PDF() and PostScript() Builders as single_source so - they know each source file generates a separate target file. - - - Add $EPSTOPDF, $EPSTOPDFFLAGS and $EPSTOPDFCOM - - - Add .tex as a valid extension for the PDF() builder. - - - Add regular expressions to find \input, \include and - \includegraphics. - - - Support generating a .pdf file from a .eps source. - - - Recursive scan included input TeX files. - - - Handle requiring searched-for TeX input graphics files to have - extensions (to avoid trying to build a .eps from itself, e.g.). - - From Greg Noel: - - - Make the Action() function handle positional parameters consistently. - - - Clarify use of Configure.CheckType(). - - - Make the File.{Dir,Entry,File}() methods create their entries - relative to the calling File's directory, not the SConscript - directory. - - - Use the Python os.devnull variable to discard error output when - looking for the $CC or $CXX version. - - - Mention LoadableModule() in the SharedLibrary() documentation. - - From Gary Oberbrunner: - - - Update the User's Guide to clarify use of the site_scons/ - directory and the site_init.py module. - - - Make env.AppendUnique() and env.PrependUnique remove duplicates - within a passed-in list being added, too. - - From Randall Spangler: - - - Fix Glob() so an on-disk file or directory beginning with '#' - doesn't throw an exception. - - - -RELEASE 1.1.0 - Thu, 09 Oct 2008 08:33:47 -0700 - - From Chris AtLee - - - Use the specified environment when checking for the GCC compiler - version. - - From Ian P. Cardenas: - - - Fix Glob() polluting LIBPATH by returning copy of list - - From David Cournapeau: - - - Add CheckCC, CheckCXX, CheckSHCC and CheckSHCXX tests to - configuration contexts. - - - Have the --profile= argument use the much faster cProfile module - (if it's available in the running Python version). - - - Reorder MSVC compilation arguments so the /Fo is first. - - From Bill Deegan: - - - Add scanning Windows resource (.rc) files for implicit dependencies. - - From John Gozde: - - - When scanning for a #include file, don't use a directory that - has the same name as the file. - - From Ralf W. Grosse-Kunstleve - - - Suppress error output when checking for the GCC compiler version. - - From Jared Grubb: - - - Fix VariantDir duplication of #included files in subdirectories. - - From Ludwig H�hne: - - - Reduce memory usage when a directory is used as a dependency of - another Node (such as an Alias) by returning a concatenation - of the children's signatures + names, not the children's contents, - as the directory contents. - - - Raise AttributeError, not KeyError, when a Builder can't be found. - - - Invalidate cached Node information (such as the contenst returned - by the get_contents() method) when calling actions with Execute(). - - - Avoid object reference cycles from frame objects. - - - Reduce memory usage from Null Executor objects. - - - Compute MD5 checksums of large files without reading the entire - file contents into memory. Add a new --md5-chunksize option to - control the size of each chunk read into memory. - - From Steven Knight: - - - Fix the ability of the add_src_builder() method to add a new - source builder to any other builder. - - - Avoid an infinite loop on non-Windows systems trying to find the - SCons library directory if the Python library directory does not - begin with the string "python". - - - Search for the SCons library directory in "scons-local" (with - no version number) after "scons-local-{VERSION}". - - From Rob Managan: - - - Fix the user's ability to interrupt the TeX build chain. - - - Fix the TeX builder's allowing the user to specify the target name, - instead of always using its default output name based on the source. - - - Iterate building TeX output files until all warning are gone - and the auxiliary files stop changing, or until we reach the - (configurable) maximum number of retries. - - - Add TeX scanner support for: glossaries, nomenclatures, lists of - figures, lists of tables, hyperref and beamer. - - - Use the $BIBINPUTS, $BSTINPUTS, $TEXINPUTS and $TEXPICTS construction - variables as search paths for the relevant types of input file. - - - Fix building TeX with VariantDir(duplicate=0) in effect. - - - Fix the LaTeX scanner to search for graphics on the TEXINPUTS path. - - - Have the PDFLaTeX scanner search for .gif files as well. - - From Greg Noel: - - - Fix typos and format bugs in the man page. - - - Add a first draft of a wrapper module for Python's subprocess - module. - - - Refactor use of the SCons.compat module so other modules don't - have to import it individually. - - - Add .sx as a suffix for assembly language files that use the - C preprocessor. - - From Gary Oberbrunner: - - - Make Glob() sort the returned list of Files or Nodes - to prevent spurious rebuilds. - - - Add a delete_existing keyword argument to the AppendENVPath() - and PrependENVPath() Environment methods. - - - Add ability to use "$SOURCE" when specifying a target to a builder - - From Damyan Pepper: - - - Add a test case to verify that SConsignFile() files can be - created in previously non-existent subdirectories. - - From Jim Randall: - - - Make the subdirectory in which the SConsignFile() file will - live, if the subdirectory doesn't already exist. - - From Ali Tofigh: - - - Add a test to verify duplication of files in VariantDir subdirectories. - - - -RELEASE 1.0.1 - Sat, 06 Sep 2008 07:29:34 -0700 - - From Greg Noel: - - - Add a FindFile() section to the User's Guide. - - - Fix the FindFile() documentation in the man page. - - - Fix formatting errors in the Package() description in the man page. - - - Escape parentheses that appear within variable names when spawning - command lines using os.system(). - - - -RELEASE 1.0.0 - XXX - - From Jared Grubb: - - - Clear the Node state when turning a generic Entry into a Dir. - - From Ludwig H�hne: - - - Fix sporadic output-order failures in test/GetBuildFailures/parallel.py. - - - Document the ParseDepends() function in the User's Guide. - - From khomenko: - - - Create a separate description and long_description for RPM packages. - - From Steven Knight: - - - Document the GetLaunchDir() function in the User's Guide. - - - Have the env.Execute() method print an error message if the - executed command fails. - - - Add a script for creating a standard SCons development system on - Ubuntu Hardy. Rewrite subsidiary scripts for install Python and - SCons versions in Python (from shell). - - From Greg Noel: - - - Handle yacc/bison on newer Mac OS X versions creating file.hpp, - not file.cpp.h. - - - In RPCGEN tests, ignore stderr messages from older versions of - rpcgen on some versions of Mac OS X. - - - Fix typos in man page descriptions of Tag() and Package(), and in - the scons-time man page. - - - Fix documentation of SConf.CheckLibWithHeader and other SConf methods. - - - Update documentation of SConscript(variant_dir) usage. - - - Fix SWIG tests for (some versions of) Mac OS X. - - From Jonas Olsson: - - - Print the warning about -j on Windows being potentially unreliable if - the pywin32 extensions are unavailable or lack file handle operations. - - From Jim Randall: - - - Fix the env.WhereIs() method to expand construction variables. - - From Rogier Schouten: - - - Enable building of shared libraries with the Bordand ilink32 linker. - - - -RELEASE 1.0.0 - Sat, 09 Aug 2008 12:19:44 -0700 - - From Luca Falavigna: - - - Fix SCons man page indentation under Debian's man page macros. - - From Steven Knight: - - - Clarify the man page description of the SConscript(src_dir) argument. - - - User's Guide updates: - - - Document the BUILD_TARGETS, COMMAND_LINE_TARGETS and - DEFAULT_TARGETS variables. - - - Document the AddOption(), GetOption() and SetOption() functions. - - - Document the Requires() function; convert to the Variables - object, its UnknownOptions() method, and its associated - BoolVariable(), EnumVariable(), ListVariable(), PackageVariable() - and PathVariable() functions. - - - Document the Progress() function. - - - Reorganize the chapter and sections describing the different - types of environments and how they interact. Document the - SetDefault() method. Document the PrependENVPath() and - AppendENVPath() functions. - - - Reorganize the command-line arguments chapter. Document the - ARGLIST variable. - - - Collect some miscellaneous sections into a chapter about - configuring build output. - - - Man page updates: - - - Document suggested use of the Visual C/C++ /FC option to fix - the ability to double-click on file names in compilation error - messages. - - - Document the need to use Clean() for any SideEffect() files that - must be explicitly removed when their targets are removed. - - - Explicitly document use of Node lists as input to Dependency(). - - From Greg Noel: - - - Document MergeFlags(), ParseConfig(), ParseFlags() and SideEffect() - in the User's Guide. - - From Gary Oberbrunner: - - - Document use of the GetBuildFailures() function in the User's Guide. - - From Adam Simpkins: - - - Add man page text clarifying the behavior of AddPreAction() and - AddPostAction() when called with multiple targets. - - From Alexey Zezukin: - - - Fix incorrectly swapped man page descriptions of the --warn= options - for duplicate-environment and missing-sconscript. - - - -RELEASE 0.98.5 - Sat, 07 Jun 2008 08:20:35 -0700 - - From Benoit Belley: - - - Fix the Intel C++ compiler ABI specification for EMT64 processors. - - From David Cournapeau: - - - Issue a (suppressable) warning, not an error, when trying to link - C++ and Fortran object files into the same executable. - - From Steven Knight: - - - Update the scons.bat file so that it returns the real exit status - from SCons, even though it uses setlocal + endlocal. - - - Fix the --interactive post-build messages so it doesn't get stuck - mistakenly reporting failures after any individual build fails. - - - Fix calling File() as a File object method in some circumstances. - - - Fix setup.py installation on Mac OS X so SCons gets installed - under /usr/lcoal by default, not in the Mac OS X Python framework. - - - -RELEASE 0.98.4 - Sat, 17 May 2008 22:14:46 -0700 - - From Benoit Belley: - - - Fix calculation of signatures for Python function actions with - closures in Python versions before 2.5. - - From David Cournapeau: - - - Fix the initialization of $SHF77FLAGS so it includes $F77FLAGS. - - From Jonas Olsson: - - - Fix a syntax error in the Intel C compiler support on Windows. - - From Steven Knight: - - - Change how we represent Python Value Nodes when printing and when - stored in .sconsign files (to avoid blowing out memory by storing - huge strings in .sconsign files after multiple runs using Configure - contexts cause the Value strings to be re-escaped each time). - - - Fix a regression in not executing configuration checks after failure - of any configuration check that used the same compiler or other tool. - - - Handle multiple destinations in Visual Studio 8 settings for the - analogues to the INCLUDE, LIBRARY and PATH variables. - - From Greg Noel: - - - Update man page text for VariantDir(). - - - -RELEASE 0.98.3 - Tue, 29 Apr 2008 22:40:12 -0700 - - From Greg Noel: - - - Fix use of $CXXFLAGS when building C++ shared object files. - - From Steven Knight: - - - Fix a regression when a Builder's source_scanner doesn't select - a more specific scanner for the suffix of a specified source file. - - - Fix the Options object backwards compatibility so people can still - "import SCons.Options.{Bool,Enum,List,Package,Path}Option" submodules. - - - Fix searching for implicit dependencies when an Entry Node shows up - in the search path list. - - From Stefano: - - - Fix expansion of $FORTRANMODDIR in the default Fortran command line(s) - when it's set to something like ${TARGET.dir}. - - - -RELEASE 0.98.2 - Sun, 20 Apr 2008 23:38:56 -0700 - - From Steven Knight: - - - Fix a bug in Fortran suffix computation that would cause SCons to - run out of memory on Windows systems. - - - Fix being able to specify --interactive mode command lines with - \ (backslash) path name separators on Windows. - - From Gary Oberbrunner: - - - Document Glob() in the User's Guide. - - - -RELEASE 0.98.1 - Fri, 18 Apr 2008 19:11:58 -0700 - - From Benoit Belley: - - - Speed up the SCons.Util.to_string*() functions. - - - Optimize various Node intialization and calculations. - - - Optimize Executor scanning code. - - - Optimize Taskmaster execution, including dependency-cycle checking. - - - Fix the --debug=stree option so it prints its tree once, not twice. - - From Johan Boul�: - - - Fix the ability to use LoadableModule() under MinGW. - - From David Cournapeau: - - - Various missing Fortran-related construction variables have been added. - - - SCons now uses the program specified in the $FORTRAN construction - variable to link Fortran object files. - - - Fortran compilers on Linux (Intel, g77 and gfortran) now add the -fPIC - option by default when compilling shared objects. - - - New 'sunf77', 'sunf90' and 'sunf95' Tool modules have been added to - support Sun Fortran compilers. On Solaris, the Sun Fortran compilers - are used in preference to other compilers by default. - - - Fortran support now uses gfortran in preference to g77. - - - Fortran file suffixes are now configurable through the - $F77FILESUFFIXES, $F90FILESUFFIXES, $F95FILESUFFIXES and - $FORTRANFILESUFFIXES variables. - - From Steven Knight: - - - Make the -d, -e, -w and --no-print-directory options "Ignored for - compatibility." (We're not going to implement them.) - - - Fix a serious inefficiency in how SCons checks for whether any source - files are missing when a Builder call creates many targets from many - input source files. - - - In Java projects, make the target .class files depend only on the - specific source .java files where the individual classes are defined. - - - Don't store duplicate source file entries in the .sconsign file so - we don't endlessly rebuild the target(s) for no reason. - - - Add a Variables object as the first step towards deprecating the - Options object name. Similarly, add BoolVariable(), EnumVariable(), - ListVariable(), PackageVariable() and PathVariable() functions - as first steps towards replacing BoolOption(), EnumOption(), - ListOption(), PackageOption() and PathOption(). - - - Change the options= keyword argument to the Environment() function - to variables=, to avoid confusion with SCons command-line options. - Continue supporting the options= keyword for backwards compatibility. - - - When $SWIGFLAGS contains the -python flag, expect the generated .py - file to be in the same (sub)directory as the target. - - - When compiling C++ files, allow $CCFLAGS settings to show up on the - command line even when $CXXFLAGS has been redefined. - - - Fix --interactive with -u/-U/-D when a VariantDir() is used. - - From Anatoly Techtonik: - - - Have the scons.bat file add the script execution directory to its - local %PATH% on Windows, so the Python executable can be found. - - From Mike Wake: - - - Fix passing variable names as a list to the Return() function. - - From Matthew Wesley: - - - Add support for the GDC 'D' language compiler. - - - -RELEASE 0.98 - Sun, 30 Mar 2008 23:33:05 -0700 - - From Benoit Belley: - - - Fix the --keep-going flag so it builds all possible targets even when - a later top-level target depends on a child that failed its build. - - - Fix being able to use $PDB and $WINDWOWS_INSERT_MANIFEST together. - - - Don't crash if un-installing the Intel C compiler leaves left-over, - dangling entries in the Windows registry. - - - Improve support for non-standard library prefixes and suffixes by - stripping all prefixes/suffixes from file name string as appropriate. - - - Reduce the default stack size for -j worker threads to 256 Kbytes. - Provide user control over this value by adding --stack-size and - --warn=stack-size options, and a SetOption('stack_size') function. - - - Fix a crash on Linux systems when trying to use the Intel C compiler - and no /opt/intel_cc_* directories are found. - - - Improve using Python functions as actions by incorporating into - a FunctionAction's signature: - - literal values referenced by the byte code. - - values of default arguments - - code of nested functions - - values of variables captured by closures - - names of referenced global variables and functions - - - Fix the closing message when --clean and --keep-going are both - used and no errors occur. - - - Add support for the Intel C compiler on Mac OS X. - - - Speed up reading SConscript files by about 20% (for some - configurations) by: 1) optimizing the SCons.Util.is_*() and - SCons.Util.flatten() functions; 2) avoiding unnecessary os.stat() - calls by using a File's .suffix attribute directly instead of - stringifying it. - - From Jérôme Berger: - - - Have the D language scanner search for .di files as well as .d files. - - - Add a find_include_names() method to the Scanner.Classic class to - abstract out how included names can be generated by subclasses. - - - Allow the D language scanner to detect multiple modules imported by - a single statement. - - From Konstantin Bozhikov: - - - Support expansion of construction variables that contain or refer - to lists of other variables or Nodes within expansions like $CPPPATH. - - - Change variable substitution (the env.subst() method) so that an - input sequence (list or tuple) is preserved as a list in the output. - - From David Cournapeau: - - - Add a CheckDeclaration() call to configure contexts. - - - Improve the CheckTypeSize() code. - - - Add a Define() call to configure contexts, to add arbitrary #define - lines to a generated configure header file. - - - Add a "gfortran" Tool module for the GNU F95/F2003 compiler. - - - Avoid use of -rpath with the Mac OS X linker. - - - Add comment lines to the generated config.h file to describe what - the various #define/#undef lines are doing. - - From Steven Knight: - - - Support the ability to subclass the new-style "str" class as input - to Builders. - - - Improve the performance of our type-checking by using isinstance() - with new-style classes. - - - Fix #include (and other $*PATH variables searches) of files with - absolute path names. Don't die if they don't exist (due to being - #ifdef'ed out or the like). - - - Fix --interactive mode when Default(None) is used. - - - Fix --debug=memoizer to work around a bug in base Python 2.2 metaclass - initialization (by just not allowing Memoization in Python versions - that have the bug). - - - Have the "scons-time time" subcommand handle empty log files, and - log files that contain no results specified by the --which option. - - - Fix the max Y of vertical bars drawn by "scons-time --fmt=gnuplot". - - - On Mac OS X, account for the fact that the header file generated - from a C++ file will be named (e.g.) file.cpp.h, not file.hpp. - - - Fix floating-point numbers confusing the Java parser about - generated .class file names in some configurations. - - - Document (nearly) all the values you can now fetch with GetOption(). - - - Fix use of file names containing strings of multiple spaces when - using ActionFactory instances like the Copy() or Move() function. - - - Fix a 0.97 regression when using a variable expansion (like - $OBJSUFFIX) in a source file name to a builder with attached source - builders that match suffix (like Program()+Object()). - - - Have the Java parser recognize generics (surrounded by angle brackets) - so they don't interfere with identifying anonymous inner classes. - - - Avoid an infinite loop when trying to use saved copies of the - env.Install() or env.InstallAs() after replacing the method - attributes. - - - Improve the performance of setting construction variables. - - - When cloning a construction environment, avoid over-writing an - attribute for an added method if the user explicitly replaced it. - - - Add a warning about deprecated support for Python 1.5, 2.0 and 2.1. - - - Fix being able to SetOption('warn', ...) in SConscript files. - - - Add a warning about env.Copy() being deprecated. - - - Add warnings about the --debug={dtree,stree,tree} options - being deprecated. - - - Add VariantDir() as the first step towards deprecating BuildDir(). - Add the keyword argument "variant_dir" as the replacement for - "build_dir". - - - Add warnings about the {Target,Source}Signatures() methods and - functions being deprecated. - - From Rob Managan: - - - Enhance TeX and LaTeX support to work with BuildDir(duplicate=0). - - - Re-run LaTeX when it issues a package warning that it must be re-run. - - From Leanid Nazdrynau: - - - Have the Copy() action factory preserve file modes and times - when copying individual files. - - From Jan Nijtmans: - - - If $JARCHDIR isn't set explicitly, use the .java_classdir attribute - that was set when the Java() Builder built the .class files. - - From Greg Noel: - - - Document the Dir(), File() and Entry() methods of Dir and File Nodes. - - - Add the parse_flags option when creating Environments - - From Gary Oberbrunner: - - - Make File(), Dir() and Entry() return a list of Nodes when passed - a list of names, instead of trying to make a string from the name - list and making a Node from that string. - - - Fix the ability to build an Alias in --interactive mode. - - - Fix the ability to hash the contents of actions for nested Python - functions on Python versions where the inability to pickle them - returns a TypeError (instead of the documented PicklingError). - - From Jonas Olsson: - - - Fix use of the Intel C compiler when the top compiler directory, - but not the compiler version, is specified. - - - Handle Intel C compiler network license files (port@system). - - From Jim Randall: - - - Fix how Python Value Nodes are printed in --debug=explain output. - - From Adam Simpkins: - - - Add a --interactive option that starts a session for building (or - cleaning) targets without re-reading the SConscript files every time. - - - Fix use of readline command-line editing in --interactive mode. - - - Have the --interactive mode "build" command with no arguments - build the specified Default() targets. - - - Fix the Chmod(), Delete(), Mkdir() and Touch() Action factories to - take a list (of Nodes or strings) as arguments. - - From Vaclav Smilauer: - - - Fix saving and restoring an Options value of 'all' on Python - versions where all() is a builtin function. - - From Daniel Svensson: - - - Code correction in SCons.Util.is_List(). - - From Ben Webb: - - - Support the SWIG %module statement with following modifiers in - parenthese (e.g., '%module(directors="1")'). - - - -RELEASE 0.97.0d20071212 - Wed, 12 Dec 2007 09:29:32 -0600 - - From Benoit Belley: - - - Fix occasional spurious rebuilds and inefficiency when using - --implicit-cache and Builders that produce multiple targets. - - - Allow SCons to not have to know about the builders of generated - files when BuildDir(duplicate=0) is used, potentially allowing some - SConscript files to be ignored for smaller builds. - - From David Cournapeau: - - - Add a CheckTypeSize() call to configure contexts. - - From Ken Deeter: - - - Make the "contents" of Alias Nodes a concatenation of the children's - content signatures (MD5 checksums), not a concatenation of the - children's contents, to avoid using large amounts of memory during - signature calculation. - - From Malte Helmert: - - - Fix a lot of typos in the man page and User's Guide. - - From Geoffrey Irving: - - - Speed up conversion of paths in .sconsign files to File or Dir Nodes. - - From Steven Knight: - - - Add an Options.UnknownOptions() method that returns any settings - (from the command line, or whatever dictionary was passed in) - that aren't known to the Options object. - - - Add a Glob() function. - - - When removing targets with the -c option, use the absolute path (to - avoid problems interpreting BuildDir() when the top-level directory - is the source directory). - - - Fix problems with Install() and InstallAs() when called through a - clone (of a clone, ...) of a cloned construction environment. - - - When executing a file containing Options() settings, add the file's - directory to sys.path (so modules can be imported from there) and - explicity set __name__ to the name of the file so the statement's - in the file can deduce the location if they need to. - - - Fix an O(n^2) performance problem when adding sources to a target - through calls to a multi Builder (including Aliases). - - - Redefine the $WINDOWSPROGMANIFESTSUFFIX and - $WINDOWSSHLIBMANIFESTSUFFIX variables so they pick up changes to - the underlying $SHLIBSUFFIX and $PROGSUFFIX variables. - - - Add a GetBuildFailures() function that can be called from functions - registered with the Python atexit module to print summary information - about any failures encountered while building. - - - Return a NodeList object, not a Python list, when a single_source - Builder like Object() is called with more than one file. - - - When searching for implicit dependency files in the directories - in a $*PATH list, don't create Dir Nodes for directories that - don't actually exist on-disk. - - - Add a Requires() function to allow the specification of order-only - prerequisites, which will be updated before specified "downstream" - targets but which don't actually cause the target to be rebuilt. - - - Restore the FS.{Dir,File,Entry}.rel_path() method. - - - Make the default behavior of {Source,Target}Signatures('timestamp') - be equivalent to 'timestamp-match', not 'timestamp-newer'. - - - Fix use of CacheDir with Decider('timestamp-newer') by updating - the modification time when copying files from the cache. - - - Fix random issues with parallel (-j) builds on Windows when Python - holds open file handles (especially for SCons temporary files, - or targets built by Python function actions) across process creation. - - From Maxim Kartashev: - - - Fix test scripts when run on Solaris. - - From Gary Oberbrunner: - - - Fix Glob() when a pattern is in an explicitly-named subdirectory. - - From Philipp Scholl: - - - Fix setting up targets if multiple Package builders are specified - at once. - - - -RELEASE 0.97.0d20070918 - Tue, 18 Sep 2007 10:51:27 -0500 - - From Steven Knight: - - - Fix the wix Tool module to handle null entries in $PATH variables. - - - Move the documentation of Install() and InstallAs() from the list - of functions to the list of Builders (now that they're implemented - as such). - - - Allow env.CacheDir() to be set per construction environment. The - global CacheDir() function now sets an overridable global default. - - - Add an env.Decider() method and a Node.Decider() method that allow - flexible specification of an arbitrary function to decide if a given - dependency has changed since the last time a target was built. - - - Don't execute Configure actions (while reading SConscript files) - when cleaning (-c) or getting help (-h or -H). - - - Add to each target an implicit dependency on the external command(s) - used to build the target, as found by searching env['ENV']['PATH'] - for the first argument on each executed command line. - - - Add support for a $IMPLICIT_COMMAND_DEPENDENCIES construction - variabe that can be used to disable the automatic implicit - dependency on executed commands. - - - Add an "ensure_suffix" keyword to Builder() definitions that, when - true, will add the configured suffix to the targets even if it looks - like they already have a different suffix. - - - Add a Progress() function that allows for calling a function or string - (or list of strings) to display progress while walking the DAG. - - - Allow ParseConfig(), MergeFlags() and ParseFlags() to handle output - from a *config command with quoted path names that contain spaces. - - - Make the Return() function stop processing the SConscript file and - return immediately. Add a "stop=" keyword argument that can be set - to False to preserve the old behavior. - - - Fix use of exitstatfunc on an Action. - - - Introduce all man page function examples with "Example:" or "Examples:". - - - When a file gets added to a directory, make sure the directory gets - re-scanned for the new implicit dependency. - - - Fix handling a file that's specified multiple times in a target - list so that it doesn't cause dependent Nodes to "disappear" from - the dependency graph walk. - - From Carsten Koch: - - - Avoid race conditions with same-named files and directory creation - when pushing copies of files to CacheDir(). - - From Tzvetan Mikov: - - - Handle $ in Java class names. - - From Gary Oberbrunner: - - - Add support for the Intel C compiler on Windows64. - - - On SGI IRIX, have $SHCXX use $CXX by default (like other platforms). - - From Sohail Somani: - - - When Cloning a construction environment, set any variables before - applying tools (so the tool module can access the configured settings) - and re-set them after (so they end up matching what the user set). - - From Matthias Troffaes: - - - Make sure extra auxiliary files generated by some LaTeX packages - and not ending in .aux also get deleted by scons -c. - - From Greg Ward: - - - Add a $JAVABOOTCLASSPATH variable for directories to be passed to the - javac -bootclasspath option. - - From Christoph Wiedemann: - - - Add implicit dependencies on the commands used to build a target. - - - - -RELEASE 0.97.0d20070809 - Fri, 10 Aug 2007 10:51:27 -0500 - - From Lars Albertsson: - - - Don't error if a #include line happens to match a directory - somewhere on a path (like $CPPPATH, $FORTRANPATH, etc.). - - From Mark Bertoglio: - - - Fix listing multiple projects in Visual Studio 7.[01] solution files, - including generating individual project GUIDs instead of re-using - the solution GUID. - - From Jean Brouwers: - - - Add /opt/SUNWspro/bin to the default execution PATH on Solaris. - - From Allan Erskine: - - - Only expect the Microsoft IDL compiler to emit *_p.c and *_data.c - files if the /proxy and /dlldata switches are used (respectively). - - From Steven Knight: - - - Have --debug=explain report if a target is being rebuilt because - AlwaysBuild() is specified (instead of "unknown reasons"). - - - Support {Get,Set}Option('help') to make it easier for SConscript - files to tell if a help option (-h, --help, etc.) has been specified. - - - Support {Get,Set}Option('random') so random-dependency interaction - with CacheDir() is controllable from SConscript files. - - - Add a new AddOption() function to support user-defined command- - line flags (like --prefix=, --force, etc.). - - - Replace modified Optik version with new optparse compatibility module - for command line processing in Scripts/SConsOptions.py - - - Push and retrieve built symlinks to/from a CacheDir() as actual - symlinks, not by copying the file contents. - - - Fix how the Action module handles stringifying the shared library - generator in the Tool/mingw.py module. - - - When generating a config.h file, print "#define HAVE_{FEATURE} 1" - instad of just "#define HAVE_{FEATURE}", for more compatibility - with Autoconf-style projects. - - - Fix expansion of $TARGET, $TARGETS, $SOURCE and $SOURCES keywords in - Visual C/C++ PDB file names. - - - Fix locating Visual C/C++ PDB files in build directories. - - - Support an env.AddMethod() method and an AddMethod() global function - for adding a new method, respectively, to a construction environment - or an arbitrary object (such as a class). - - - Fix the --debug=time option when the -j option is specified and all - files are up to date. - - - Add a $SWIGOUTDIR variable to allow setting the swig -outdir option, - and use it to identify files created by the swig -java option. - - - Add a $SWIGPATH variable that specifies the path to be searched - for included SWIG files, Also add related $SWIGINCPREFIX and - $SWIGINCSUFFIX variables that specify the prefix and suffix to - be be added to each $SWIGPATH directory when expanded on the SWIG - command line. - - - More efficient copying of construction environments (mostly borrowed - from copy.deepcopy() in the standard Python library). - - - When printing --tree=prune output, don't print [brackets] around - source files, only do so for built targets with children. - - - Fix interpretation of Builder source arguments when the Builder has - a src_suffix *and* a source_builder and the argument has no suffix. - - - Fix use of expansions like ${TARGET.dir} or ${SOURCE.dir} in the - following construction variables: $FORTRANMODDIR, $JARCHDIR, - $JARFLAGS, $LEXFLAGS, $SWIGFLAGS, $SWIGOUTDIR and $YACCFLAGS. - - - Fix dependencies on Java files generated by SWIG so they can be - detected and built in one pass. - - - Fix SWIG when used with a BuildDir(). - - From Leanid Nazdrynau: - - - When applying Tool modules after a construction environment has - already been created, don't overwrite existing $CFILESUFFIX and - $CXXFILESUFFIX value. - - - Support passing the Java() builder a list of explicit .java files - (not only a list of directories to be scanned for .java files). - - - Support passing .java files to the Jar() and JavaH() builders, which - then use the builder underlying the Java() builder to turn them into - .class files. (That is, the Jar()-Java() chain of builders become - multi-step, like the Program()-Object()-CFile() builders.) - - - Support passing SWIG .i files to the Java builders (Java(), - Jar(), JavaH()), to cause intermediate .java files to be created - automatically. - - - Add $JAVACLASSPATH and $JAVASOURCEPATH variables, that get added to - the javac "-classpath" and "-sourcepath" options. (Note that SCons - does *not* currently search these paths for implicit dependencies.) - - - Commonize initialization of Java-related builders. - - From Jan Nijtmans: - - - Find Java anonymous classes when the next token after the name is - an open parenthesis. - - From Gary Oberbrunner: - - - Fix a code example in the man page. - - From Tilo Prutz: - - - Add support for the file names that Java 1.5 (and 1.6) generates for - nested anonymous inner classes, which are different from Java 1.4. - - From Adam Simpkins: - - - Allow worker threads to terminate gracefully when all jobs are - finished. - - From Sohail Somani: - - - Add LaTeX scanner support for finding dependencies specified with - the \usepackage{} directive. - - - -RELEASE 0.97 - Thu, 17 May 2007 08:59:41 -0500 - - From Steven Knight: - - - Fix a bug that would make parallel builds stop in their tracks if - Nodes that depended on lists that contained some Nodes built together - caused the reference count to drop below 0 if the Nodes were visited - and commands finished in the wrong order. - - - Make sure the DirEntryScanner doesn't choke if it's handed something - that's not a directory (Node.FS.Dir) Node. - - - -RELEASE 0.96.96 - Thu, 12 Apr 2007 12:36:25 -0500 - - NOTE: This is (Yet) a(nother) pre-release of 0.97 for testing purposes. - - From Joe Bloggs: - - - Man page fix: remove cut-and-paste sentence in NoCache() description. - - From Dmitry Grigorenko and Gary Oberbrunner: - - - Use the Intel C++ compiler, not $CC, to link C++ source. - - From Helmut Grohne: - - - Fix the man page example of propagating a user's external environment. - - From Steven Knight: - - - Back out (most of) the Windows registry installer patch, which - seems to not work on some versions of Windows. - - - Don't treat Java ".class" attributes as defining an inner class. - - - Fix detecting an erroneous Java anonymous class when the first - non-skipped token after a "new" keyword is a closing brace. - - - Fix a regression when a CPPDEFINES list contains a tuple, the second - item of which (the option value) is a construction variable expansion - (e.g. $VALUE) and the value of the variable isn't a string. - - - Improve the error message if an IOError (like trying to read a - directory as a file) occurs while deciding if a node is up-to-date. - - - Fix "maximum recursion" / "unhashable type" errors in $CPPPATH - PathList expansion if a subsidiary expansion yields a stringable, - non-Node object. - - - Generate API documentation from the docstrings (using epydoc). - - - Fix use of --debug=presub with Actions for out-of-the-box Builders. - - - Fix handling nested lists within $CPPPATH, $LIBPATH, etc. - - - Fix a "builders_used" AttributeError that real-world Qt initialization - triggered in the refactored suffix handling for Builders. - - - Make the reported --debug=time timings meaningful when used with -j. - Better documentation of what the times mean. - - - User Guide updates: --random, AlwaysBuild(), --tree=, - --debug=findlibs, --debug=presub, --debug=stacktrace, - --taskmastertrace. - - - Document (in both man page and User's Guide) that --implicit-cache - ignores changes in $CPPPATH, $LIBPATH, etc. - - From Jean-Baptiste Lab: - - - Remove hard-coded dependency on Python 2.2 from Debian packaging files. - - From Jeff Mahovsky: - - - Handle spaces in the build target name in Visual Studio project files. - - From Rob Managan: - - - Re-run LaTeX after BibTeX has been re-run in response to a changed - .bib file. - - From Joel B. Mohler: - - - Make additional TeX auxiliary files (.toc, .idx and .bbl files) - Precious so their removal doesn't affect whether the necessary - sections are included in output PDF or PostScript files. - - From Gary Oberbrunner: - - - Fix the ability to import modules in the site_scons directory from - a subdirectory. - - From Adam Simpkins: - - - Make sure parallel (-j) builds all targets even if they show up - multiple times in the child list (as a source and a dependency). - - From Matthias Troffaes: - - - Don't re-run TeX if the triggering strings (\makeindex, \bibliography - \tableofcontents) are commented out. - - From Richard Viney: - - - Fix use of custom include and lib paths with Visual Studio 8. - - - Select the default .NET Framework SDK Dir based on the version of - Visual Studio being used. - - - -RELEASE 0.96.95 - Mon, 12 Feb 2007 20:25:16 -0600 - - From Anatoly Techtonik: - - - Add the scons.org URL and a package description to the setup.py - arguments. - - - Have the Windows installer add a registry entry for scons.bat in the - "App Paths" key, so scons.bat can be executed without adding the - directory to the %PATH%. (Python itself works this way.) - - From Anonymous: - - - Fix looking for default paths in Visual Studio 8.0 (and later). - - - Add -lm to the list of default D libraries for linking. - - From Matt Doar: - - - Provide a more complete write-your-own-Scanner example in the man page. - - From Ralf W. Grosse-Kunstleve: - - - Contributed upstream Python change to our copied subprocess.py module - for more efficient standard input processing. - - From Steven Knight: - - - Fix the Node.FS.Base.rel_path() method when the two nodes are on - different drive letters. (This caused an infinite loop when - trying to write .sconsign files.) - - - Fully support Scanners that use a dictionary to map file suffixes - to other scanners. - - - Support delayed evaluation of the $SPAWN variable to allow selection - of a function via ${} string expansions. - - - Add --srcdir as a synonym for -Y/--repository. - - - Document limitations of #include "file.h" with Repository(). - - - Fix use of a toolpath under the source directory of a BuildDir(). - - - Fix env.Install() with a file name portion that begins with '#'. - - - Fix ParseConfig()'s handling of multiple options in a string that's - replaced a *FLAGS construction variable. - - - Have the C++ tools initialize common C compilation variables ($CCFLAGS, - $SHCCFLAGS and $_CCCOMCOM) even if the 'cc' Tool isn't loaded. - - From Leanid Nazdrynau: - - - Fix detection of Java anonymous classes if a newline precedes the - opening brace. - - From Gary Oberbrunner: - - - Document use of ${} to execute arbitrary Python code. - - - Add support for: - 1) automatically adding a site_scons subdirectory (in the top-level - SConstruct directory) to sys.path (PYTHONPATH); - 2) automatically importing site_scons/site_init.py; - 3) automatically adding site_scons/site_tools to the toolpath. - - From John Pye: - - - Change ParseConfig() to preserve white space in arguments passed in - as a list. - - From a smith: - - - Fix adding explicitly-named Java inner class files (and any - other file names that may contain a '$') to Jar files. - - From David Vitek: - - - Add a NoCache() function to mark targets as unsuitable for propagating - to (or retrieving from) a CacheDir(). - - From Ben Webb: - - - If the swig -noproxy option is used, it won't generate a .py file, - so don't emit it as a target that we expect to be built. - - - -RELEASE 0.96.94 - Sun, 07 Jan 2007 18:36:20 -0600 - - NOTE: This is a pre-release of 0.97 for testing purposes. - - From Anonymous: - - - Allow arbitrary white space after a SWIG %module declaration. - - From Paul: - - - When compiling resources under MinGW, make sure there's a space - between the --include-dir option and its argument. - - From Jay Kint: - - - Alleviate long command line issues on Windows by executing command - lines directly via os.spawnv() if the command line doesn't need - shell interpretation (has no pipes, redirection, etc.). - - From Walter Franzini: - - - Exclude additional Debian packaging files from the copyright check. - - From Fawad Halim: - - - Handle the conflict between the impending Python 2.6 'as' keyword - and our Tool/as.py module name. - - From Steven Knight: - - - Speed up the Node.FS.Dir.rel_path() method used to generate path names - that get put into the .sconsign* file(s). - - - Optimize Node.FS.Base.get_suffix() by computing the suffix once, up - front, when we set the Node's name. (Duh...) - - - Reduce the Memoizer's responsibilities to simply counting hits and - misses when the --debug=memoizer option is used, not to actually - handling the key calculation and memoization itself. This speeds - up some configurations significantly, and should cause no functional - differences. - - - Add a new scons-time script with subcommands for generating - consistent timing output from SCons configurations, extracting - various information from those timings, and displaying them in - different formats. - - - Reduce some unnecessary stat() calls from on-disk entry type checks. - - - Fix SideEffect() when used with -j, which was badly broken in 0.96.93. - - - Propagate TypeError exceptions when evaluating construction variable - expansions up the stack, so users can see what's going on. - - - When disambiguating a Node.FS.Entry into a Dir or File, don't look - in the on-disk source directory until we've confirmed there's no - on-disk entry locally and there *is* one in the srcdir. This avoids - creating a phantom Node that can interfere with dependencies on - directory contents. - - - Add an AllowSubstExceptions() function that gives the SConscript - files control over what exceptions cause a string to expand to '' - vs. terminating processing with an error. - - - Allow the f90.py and f95.py Tool modules to compile earlier source - source files of earlier Fortran version. - - - Fix storing signatures of files retrieved from CacheDir() so they're - correctly identified as up-to-date next invocation. - - - Make sure lists of computed source suffixes cached by Builder objects - don't persist across changes to the list of source Builders (so the - addition of suffixes like .ui by the qt.py Tool module take effect). - - - Enhance the bootstrap.py script to allow it to be used to execute - SCons more easily from a checked-out source tree. - - From Ben Leslie: - - - Fix post-Memoizer value caching misspellings in Node.FS._doLookup(). - - From Rob Managan, Dmitry Mikhin and Joel B. Mohler: - - - Handle TeX/LaTeX files in subdirectories by changing directory - before invoking TeX/LaTeX. - - - Scan LaTeX files for \bibliography lines. - - - Support multiple file names in a "\bibliography{file1,file2}" string. - - - Handle TeX warnings about undefined citations. - - - Support re-running LaTeX if necessary due to a Table of Contents. - - From Dmitry Mikhin: - - - Return LaTeX if "Rerun to get citations correct" shows up on the next - line after the "Warning:" string. - - From Gary Oberbrunner: - - - Add #include lines to fix portability issues in two tests. - - - Eliminate some unnecessary os.path.normpath() calls. - - - Add a $CFLAGS variable for C-specific options, leaving $CCFLAGS - for options common to C and C++. - - From Tom Parker: - - - Have the error message print the missing file that Qt can't find. - - From John Pye: - - - Fix env.MergeFlags() appending to construction variable value of None. - - From Steve Robbins: - - - Fix the "sconsign" script when the .sconsign.dblite file is explicitly - specified on the command line (and not intuited from the old way of - calling it with just ".sconsign"). - - From Jose Pablo Ezequiel "Pupeno" Fernandez Silva: - - - Give the 'lex' tool knowledge of the additional target files produced - by the flex "--header-file=" and "--tables-file=" options. - - - Give the 'yacc' tool knowledge of the additional target files produced - by the bison "-g", "--defines=" and "--graph=" options. - - - Generate intermediate files with Objective C file suffixes (.m) when - the lex and yacc source files have appropriate suffixes (.lm and .ym). - - From Sohail Somain: - - - Have the mslink.py Tool only look for a 'link' executable on Windows - systems. - - From Vaclav Smilauer: - - - Add support for a "srcdir" keyword argument when calling a Builder, - which will add a srcdir prefix to all non-relative string sources. - - From Jonathan Ultis: - - - Allow Options converters to take the construction environment as - an optional argument. - - - -RELEASE 0.96.93 - Mon, 06 Nov 2006 00:44:11 -0600 - - NOTE: This is a pre-release of 0.97 for testing purposes. - - From Anonymous: - - - Allow Python Value Nodes to be Builder targets. - - From Matthias: - - - Only filter Visual Studio common filename prefixes on complete - directory names. - - From Chad Austin: - - - Fix the build of the SCons documentation on systems that don't - have "python" in the $PATH. - - From Ken Boortz: - - - Enhance ParseConfig() to recognize options that begin with '+'. - - From John Calcote, Elliot Murphy: - - - Document ways to override the CCPDBFLAGS variable to use the - Microsoft linker's /Zi option instead of the default /Z7. - - From Christopher Drexler: - - - Make SCons aware bibtex must be called if any \include files - cause creation of a bibliography. - - - Make SCons aware that "\bilbiography" in TeX source files means - that related .bbl and .blg bibliography files will be created. - (NOTE: This still needs to search for the string in \include files.) - - From David Gruener: - - - Fix inconsistent handling of Action strfunction arguments. - - - Preserve white space in display Action strfunction strings. - - From James Y. Knight and Gerard Patel: - - - Support creation of shared object files from assembly language. - - From Steven Knight: - - - Speed up the Taskmaster significantly by avoiding unnecessary - re-scans of Nodes to find out if there's work to be done, having it - track the currently-executed top-level target directly and not - through its presence on the target list, and eliminating some other - minor list(s), method(s) and manipulation. - - - Fix the expansion of $TARGET and $SOURCE in the expansion of - $INSTALLSTR displayed for non-environment calls to InstallAs(). - - - Fix the ability to have an Alias() call refer to a directory - name that's not identified as a directory until later. - - - Enhance runtest.py with an option to use QMTest as the harness. - This will become the default behavior as we add more functionality - to the QMTest side. - - - Let linking on mingw use the default function that chooses $CC (gcc) - or $CXX (g++) depending on whether there are any C++ source files. - - - Work around a bug in early versions of the Python 2.4 profile module - that caused the --profile= option to fail. - - - Only call Options validators and converters once when initializing a - construction environment. - - - Fix the ability of env.Append() and env.Prepend(), in all known Python - versions, to handle different input value types when the construction - variable being updated is a dictionary. - - - Add a --cache-debug option for information about what files it's - looking for in a CacheDir(). - - - Document the difference in construction variable expansion between - {Action,Builder}() and env.{Action,Builder}(). - - - Change the name of env.Copy() to env.Clone(), keeping the old name - around for backwards compatibility (with the intention of eventually - phasing it out to avoid confusion with the Copy() Action factory). - - From Arve Knudsen: - - - Support cleaning and scanning SWIG-generated files. - - From Carsten Koch: - - - Allow selection of Visual Studio version by setting $MSVS_VERSION - after construction environment initialization. - - From Jean-Baptiste Lab: - - - Try using zipimport if we can't import Tool or Platform modules - using the normal "imp" module. This allows SCons to be packaged - using py2exe's all-in-one-zip-file approach. - - From Ben Liblit: - - - Do not re-scan files if the scanner returns no implicit dependencies. - - From Sanjoy Mahajan: - - - Change use of $SOURCES to $SOURCE in all TeX-related Tool modules. - - From Joel B. Mohler: - - - Make SCons aware that "\makeindex" in TeX source files means that - related .ilg, .ind and .idx index files will be created. - (NOTE: This still needs to search for the string in \include files.) - - - Prevent scanning the TeX .aux file for additional files from - trying to remove it twice when the -c option is used. - - From Leanid Nazdrynau: - - - Give the MSVC RES (resource) Builder a src_builder list and a .rc - src_suffix so other builders can generate .rc files. - - From Matthew A. Nicholson: - - - Enhance Install() and InstallAs() to handle directory trees as sources. - - From Jan Nijtmans: - - - Don't use the -fPIC flag when using gcc on Windows (e.g. MinGW). - - From Greg Noel: - - - Add an env.ParseFlags() method that provides separate logic for - parsing GNU tool chain flags into a dictionary. - - - Add an env.MergeFlags() method to apply an arbitrary dictionary - of flags to a construction environment's variables. - - From Gary Oberbrunner: - - - Fix parsing tripartite Intel C compiler version numbers on Linux. - - - Extend the ParseConfig() function to recognize -arch and - -isysroot options. - - - Have the error message list the known suffixes when a Builder call - can't build a source file with an unknown suffix. - - From Karol Pietrzak: - - - Avoid recursive calls to main() in the program snippet used by the - SConf subsystem to test linking against libraries. This changes the - default behavior of CheckLib() and CheckLibWithHeader() to print - "Checking for C library foo..." instead of "Checking for main() - in C library foo...". - - From John Pye: - - - Throw an exception if a command called by ParseConfig() or - ParseFlags() returns an error. - - From Stefan Seefeld: - - - Initial infrastructure for running SCons tests under QMTest. - - From Sohail Somani: - - - Fix tests that fail due to gcc warnings. - - From Dobes Vandermeer: - - - In stack traces, print the full paths of SConscript files. - - From Atul Varma: - - - Fix detection of Visual C++ Express Edition. - - From Dobes Vandermeer: - - - Let the src_dir option to the SConscript() function affect all the - the source file paths, instead of treating all source files paths - as relative to the SConscript directory itself. - - From Nicolas Vigier: - - - Fix finding Fortran modules in build directories. - - - Fix use of BuildDir() when the source file in the source directory - is a symlink with a relative path. - - From Edward Wang: - - - Fix the Memoizer when the SCons Python modules are executed from - .pyo files at different locations from where they were compiled. - - From Johan Zander: - - - Fix missing os.path.join() when constructing the $FRAMEWORKSDKDIR/bin. - - - -RELEASE 0.96.92 - Mon, 10 Apr 2006 21:08:22 -0400 - - NOTE: This was a pre-release of 0.97 for testing purposes. - - From Anonymous: - - - Fix the intelc.py Tool module to not throw an exception if the - only installed version is something other than ia32. - - - Set $CCVERSION when using gcc. - - From Matthias: - - - Support generating project and solution files for Microsoft - Visual Studio version 8. - - - Support generating more than one project file for a Microsoft - Visual Studio solution file. - - - Add support for a support "runfile" parameter to Microsoft - Visual Studio project file creation. - - - Put the project GUID, not the solution GUID, in the right spot - in the solution file. - - From Erling Andersen: - - - Fix interpretation of Node.FS objects wrapped in Proxy instances, - allowing expansion of things like ${File(TARGET)} in command lines. - - From Stanislav Baranov: - - - Add a separate MSVSSolution() Builder, with support for the - following new construction variables: $MSVSBUILDCOM, $MSVSCLEANCOM, - $MSVSENCODING, $MSVSREBUILDCOM, $MSVSSCONS, $MSVSSCONSCOM, - $MSVSSCONSFLAGS, $MSVSSCONSCRIPT and $MSVSSOLUTIONCOM. - - From Ralph W. Grosse-Kunstleve and Patrick Mezard: - - - Remove unneceesary (and incorrect) SCons.Util strings on some function - calls in SCons.Util. - - From Bob Halley: - - - Fix C/C++ compiler selection on AIX to not always use the external $CC - environment variable. - - From August Hörandl: - - - Add a scanner for \include and \import files, with support for - searching a directory list in $TEXINPUTS (imported from the external - environment). - - - Support $MAKEINDEX, $MAKEINDEXCOM, $MAKEINDEXCOMSTR and - $MAKEINDEXFLAGS for generating indices from .idx files. - - From Steven Johnson: - - - Add a NoClean() Environment method and function to override removal - of targets during a -c clean, including documentation and tests. - - From Steven Knight: - - - Check for whether files exist on disk by listing the directory - contents, not calling os.path.exists() file by file. This is - somewhat more efficient in general, and may be significantly - more efficient on Windows. - - - Minor speedups in the internal is_Dict(), is_List() and is_String() - functions. - - - Fix a signature refactoring bug that caused Qt header files to - get re-generated every time. - - - Don't fail when writing signatures if the .sconsign.dblite file is - owned by a different user (e.g. root) from a previous run. - - - When deleting variables from stacked OverrideEnvironments, don't - throw a KeyError if we were able to delte the variable from any - Environment in the stack. - - - Get rid of the last indentation tabs in the SCons source files and - add -tt to the Python invocations in the packaging build and the - tests so they don't creep back in. - - - In Visual Studio project files, put quotes around the -C directory - so everything works even if the path has spaces in it. - - - The Intel Fortran compiler uses -object:$TARGET, not "-o $TARGET", - when building object files on Windows. Have the the ifort Tool - modify the default command lines appropriately. - - - Document the --debug=explain option in the man page. (How did we - miss this?) - - - Add a $LATEXRETRIES variable to allow configuration of the number of - times LaTex can be re-called to try to resolve undefined references. - - - Change the order of the arguments to Configure.Checklib() to match - the documentation. - - - Handle signature calculation properly when the Python function used - for a FunctionAction is an object method. - - - On Windows, assume that absolute path names without a drive letter - refer to the drive on which the SConstruct file lives. - - - Add /usr/ccs/bin to the end of the the default external execution - PATH on Solaris. - - - Add $PKGCHK and $PKGINFO variables for use on Solaris when searching - for the SunPRO C++ compiler. Make the default value for $PKGCHK - be /usr/sbin/pgkchk (since /usr/sbin isn't usually on the external - execution $PATH). - - - Fix a man page example of overriding variables when calling - SharedLibrary() to also set the $LIBSUFFIXES variable. - - - Add a --taskmastertrace=FILE option to give some insight on how - the taskmaster decides what Node to build next. - - - Changed the names of the old $WIN32DEFPREFIX, $WIN32DEFSUFFIX, - $WIN32DLLPREFIX and $WIN32IMPLIBPREFIX construction variables to - new $WINDOWSDEFPREFIX, $WINDOWSDEFSUFFIX, $WINDOWSDLLPREFIX and - $WINDOWSIMPLIBPREFIX construction variables. The old names are now - deprecated, but preserved for backwards compatibility. - - - Fix (?) a runtest.py hang on Windows when the --xml option is used. - - - Change the message when an error occurs trying to interact with the - file system to report the target(s) in square brackets (as before) and - the actual file or directory that encountered the error afterwards. - - From Chen Lee: - - - Add x64 support for Microsoft Visual Studio 8. - - From Baptiste Lepilleur: - - - Support the --debug=memory option on Windows when the Python version - has the win32process and win32api modules. - - - Add support for Visual Studio 2005 Pro. - - - Fix portability issues in various tests: test/Case.py, - Test/Java/{JAR,JARCHDIR,JARFLAGS,JAVAC,JAVACFLAGS,JAVAH,RMIC}.py, - test/MSVS/vs-{6.0,7.0,7.1,8.0}-exec.py, - test/Repository/{Java,JavaH,RMIC}.py, - test/QT/{generated-ui,installed,up-to-date,warnings}.py, - test/ZIP/ZIP.py. - - - Ignore pkgchk errors on Solaris when searching for the C++ compiler. - - - Speed up the SCons/EnvironmentTests.py unit tests. - - - Add a --verbose= option to runtest.py to print executed commands - and their output at various levels. - - From Christian Maaser: - - - Add support for Visual Studio Express Editions. - - - Add support for Visual Studio 8 *.manifest files, includng - new $WINDOWS_INSERT_MANIFEST, $WINDOWSPROGMANIFESTSUFFIX, - $WINDOWSPROGMANIFESTPREFIX, $WINDOWSPROGMANIFESTSUFFIX, - $WINDOWSSHLIBMANIFESTPREFIX and $WINDOWSSHLIBMANIFESTSUFFIX - construction variables. - - From Adam MacBeth: - - - Fix detection of additional Java inner classes following use of a - "new" keyword inside an inner class. - - From Sanjoy Mahajan: - - - Correct TeX-related command lines to just $SOURCE, not $SOURCES - - From Patrick Mezard: - - - Execute build commands for a command-line target if any of the - files built along with the target is out of date or non-existent, - not just if the command-line target itself is out of date. - - - Fix the -n option when used with -c to print all of the targets - that will be removed for a multi-target Builder call. - - - If there's no file in the source directory, make sure there isn't - one in the build directory, too, to avoid dangling files left - over from previous runs when a source file is removed. - - - Allow AppendUnique() and PrependUnique() to append strings (and - other atomic objects) to lists. - - From Joel B. Mohler: - - - Extend latex.py, pdflatex.py, pdftex.py and tex.py so that building - from both TeX and LaTeX files uses the same logic to call $BIBTEX - when it's necessary, to call $MAKEINDEX when it's necessary, and to - call $TEX or $LATEX multiple times to handle undefined references. - - - Add an emitter to the various TeX builders so that the generated - .aux and .log files also get deleted by the -c option. - - From Leanid Nazdrynau: - - - Fix the Qt UIC scanner to work with generated .ui files (by using - the FindFile() function instead of checking by-hand for the file). - - From Jan Nieuwenhuizen: - - - Fix a problem with interpreting quoted argument lists on command lines. - - From Greg Noel: - - - Add /sw/bin to the default execution PATH on Mac OS X. - - From Kian Win Ong: - - - When building a .jar file and there is a $JARCHDIR, put the -C - in front of each .class file on the command line. - - - Recognize the Java 1.5 enum keyword. - - From Asfand Yar Qazi: - - - Add /opt/bin to the default execution PATH on all POSIX platforms - (between /usr/local/bin and /bin). - - From Jon Rafkind: - - - Fix the use of Configure() contexts from nested subsidiary - SConscript files. - - From Christoph Schulz: - - - Add support for $CONFIGUREDIR and $CONFIGURELOG variables to control - the directory and logs for configuration tests. - - - Add support for a $INSTALLSTR variable. - - - Add support for $RANLIBCOM and $RANLIBCOMSTR variables (which fixes - a bug when setting $ARCOMSTR). - - From Amir Szekely: - - - Add use of $CPPDEFINES to $RCCOM (resource file compilation) on MinGW. - - From Erick Tryzelaar: - - - Fix the error message when trying to report that a given option is - not gettable/settable from an SConscript file. - - From Dobes Vandermeer: - - - Add support for SCC and other settings in Microsoft Visual - Studio project and solution files: $MSVS_PROJECT_BASE_PATH, - $MSVS_PROJECT_GUID, $MSVS_SCC_AUX_PATH, $MSVS_SCC_LOCAL_PATH, - $MSVS_SCC_PROJECT_NAME, $MSVS_SCC_PROVIDER, - - - Add support for using a $SCONS_HOME variable (imported from the - external environment, or settable internally) to put a shortened - SCons execution line in the Visual Studio project file. - - From David J. Van Maren: - - - Only filter common prefixes from source files names in Visual Studio - project files if the prefix is a complete (sub)directory name. - - From Thad Ward: - - - If $MSVSVERSIONS is already set, don't overwrite it with - information from the registry. - - - -RELEASE 0.96.91 - Thu, 08 Sep 2005 07:18:23 -0400 - - NOTE: This was a pre-release of 0.97 for testing purposes. - - From Chad Austin: - - - Have the environment store the toolpath and re-use it to find Tools - modules during later Copy() or Tool() calls (unless overridden). - - - Normalize the directory path names in SConsignFile() database - files so the same signature file can interoperate on Windows and - non-Windows systems. - - - Make --debug=stacktrace print a stacktrace when a UserError is thrown. - - - Remove an old, erroneous cut-and-paste comment in Scanner/Dir.py. - - From Stanislav Baranov: - - - Make it possible to support with custom Alias (sub-)classes. - - - Allow Builders to take empty source lists when called. - - - Allow access to both TARGET and SOURCE in $*PATH expansions. - - - Allow SConscript files to modify BUILD_TARGETS. - - From Timothee Besset: - - - Add support for Objective C/C++ .m and .mm file suffixes (for - Mac OS X). - - From Charles Crain - - - Fix the PharLap linkloc.py module to use target+source arguments - when calling env.subst(). - - From Bjorn Eriksson: - - - Fix an incorrect Command() keyword argument in the man page. - - - Add a $TEMPFILEPREFIX variable to control the prefix or flag used - to pass a long-command-line-execution tempfile to a command. - - From Steven Knight: - - - Enhanced the SCons setup.py script to install man pages on - UNIX/Linux systems. - - - Add support for an Options.FormatOptionHelpText() method that can - be overridden to customize the format of Options help text. - - - Add a global name for the Entry class (which had already been - documented). - - - Fix re-scanning of generated source files for implicit dependencies - when the -j option is used. - - - Fix a dependency problem that caused $LIBS scans to not be added - to all of the targets in a multiple-target builder call, which - could cause out-of-order builds when the -j option is used. - - - Store the paths of source files and dependencies in the .sconsign* - file(s) relative to the target's directory, not relative to the - top-level SConstruct directory. This starts to make it possible to - subdivide the dependency tree arbitrarily by putting an SConstruct - file in every directory and using content signatures. - - - Add support for $YACCHFILESUFFIX and $YACCHXXFILESUFFIX variables - that accomodate parser generators that write header files to a - different suffix than the hard-coded .hpp when the -d option is used. - - - The default behavior is now to store signature information in a - single .sconsign.dblite file in the top-level SConstruct directory. - The old behavior of a separate .sconsign file in each directory can - be specified by calling SConsignFile(None). - - - Remove line number byte codes within the signature calculation - of Python function actions, so that changing the location of an - otherwise unmodified Python function doesn't cause rebuilds. - - - Fix AddPreAction() and AddPostAction() when an action has more than - one target file: attach the actions to the Executor, not the Node. - - - Allow the source directory of a BuildDir / build_dir to be outside - of the top-level SConstruct directory tree. - - - Add a --debug=nomemoizer option that disables the Memoizer for clearer - looks at the counts and profiles of the underlying function calls, - not the Memoizer wrappers. - - - Print various --debug= stats even if we exit early (e.g. using -h). - - - Really only use the cached content signature value if the file - is older than --max-drift, not just if --max-drift is set. - - - Remove support for conversion from old (pre 0.96) .sconsign formats. - - - Add support for a --diskcheck option to enable or disable various - on-disk checks: that File and Dir nodes match on-disk entries; - whether an RCS file exists for a missing source file; whether an - SCCS file exists for a missing source file. - - - Add a --raw argument to the sconsign script, so it can print a - raw representation of each entry's NodeInfo dictionary. - - - Add the 'f90' and 'f95' tools to the list of Fortran compilers - searched for by default. - - - Add the +Z option by default when compiling shared objects on - HP-UX. - - From Chen Lee: - - - Handle Visual Studio project and solution files in Unicode. - - From Sanjoy Mahajan: - - - Fix a bad use of Copy() in an example in the man page, and a - bad regular expression example in the man page and User's Guide. - - From Shannon Mann: - - - Have the Visual Studio project file(s) echo "Starting SCons" before - executing SCons, mainly to work around a quote-stripping bug in - (some versions of?) the Windows cmd command executor. - - From Georg Mischler: - - - Remove the space after the -o option when invoking the Borland - BCC compiler; some versions apparently require that the file name - argument be concatenated with the option. - - From Leanid Nazdrynau: - - - Fix the Java parser's handling of backslashes in strings. - - From Greg Noel: - - - Add construction variables to support frameworks on Mac OS X: - $FRAMEWORKS, $FRAMEWORKPREFIX, $FRAMEWORKPATH, $FRAMEWORKPATHPREFIX. - - - Re-order link lines so the -o option always comes right after the - command name. - - From Gary Oberbrunner: - - - Add support for Intel C++ beta 9.0 (both 32 and 64 bit versions). - - - Document the new $FRAMEWORK* variables for Mac OS X. - - From Karol Pietrzak: - - - Add $RPATH (-R) support to the Sun linker Tool (sunlink). - - - Add a description of env.subst() to the man page. - - From Chris Prince: - - - Look in the right directory, not always the local directory, for a - same-named file or directory conflict on disk. - - - On Windows, preserve the external environment's %SYSTEMDRIVE% - variable, too. - - From Craig Scott: - - - Have the Fortran module emitter look for Fortan modules to be created - relative to $FORTRANMODDIR, not the top-level directory. - - - When saving Options to a file, run default values through the - converter before comparing them with the set values. This correctly - suppresses Boolean Option values from getting written to the saved - file when they're one of the many synonyms for a default True or - False value. - - - Fix the Fortran Scanner's ability to handle a module being used - in the same file in which it is defined. - - From Steve-o: - - - Add the -KPIC option by default when compiling shared objects on - Solaris. - - - Change the default suffix for Solaris objects to .o, to conform to - Sun WorkShop's expectations. Change the profix to so_ so they can - still be differentiated from static objects in the same directory. - - From Amir Szekely: - - - When calling the resource compiler on MinGW, add --include-dir and - the source directory so it finds the source file. - - - Update EnsureSConsVersion() to support revision numbers. - - From Greg Ward: - - - Fix a misplaced line in the man page. - - - -RELEASE 0.96.90 - Tue, 15 Feb 2005 21:21:12 +0000 - - NOTE: This was a pre-release of 0.97 for testing purposes. - - From Anonymous: - - - Fix Java parsing to avoid erroneously identifying a new array - of class instances as an anonymous inner class. - - - Fix a typo in the man page description of PathIsDirCreate. - - From Chad Austin: - - - Allow Help() to be called multiple times, appending to the help - text each call. - - - Allow Tools found on a toolpath to import Python modules from - their local directory. - - From Steve Christensen: - - - Handle exceptions from Python functions as build actions. - - - Add a set of canned PathOption validators: PathExists (the default), - PathIsFile, PathIsDir and PathIsDirCreate. - - From Matthew Doar: - - - Add support for .lex and .yacc file suffixes for Lex and Yacc files. - - From Eric Frias: - - - Huge performance improvement: wrap the tuples representing an - include path in an object, so that the time it takes to hash the - path doesn't grow porportionally to the length of the path. - - From Gottfried Ganssauge: - - - Fix SCons on SuSE/AMD-64 Linux by having the wrapper script also - check for the build engine in the parent directory of the Python - library directory (/usr/lib64 instead of /usr/lib). - - From Stephen Kennedy: - - - Speed up writing the .sconsign file at the end of a run by only - calling sync() once at the end, not after every entry. - - From Steven Knight: - - - When compiling with Microsoft Visual Studio, don't include the ATL and - MFC directories in the default INCLUDE and LIB environment variables. - - - Remove the following deprecated features: the ParseConfig() - global function (deprecated in 0.93); the misspelled "validater" - keyword to the Options.Add() method (deprecated in 0.91); the - SetBuildSignatureType(), SetContentSignatureType(), SetJobs() and - GetJobs() global functions (deprecated in 0.14). - - - Fix problems with corrupting the .sconsign.dblite file when - interrupting builds by writing to a temporary file and renaming, - not writing the file directly. - - - Fix a 0.96 regression where when running with -k, targets built from - walking dependencies later on the command line would not realize - that a dependency had failed an earlier build attempt, and would - try to rebuild the dependent targets. - - - Change the final messages when using -k and errors occur from - "{building,cleaning} terminated because of errors" to "done - {building,cleaning} targets (errors occurred during {build,clean})." - - - Allow Configure.CheckFunc() to take an optional header argument - (already supported by Conftest.py) to specify text at the top of - the compiled test file. - - - Fix the --debug=explain output when a Python function action changed - so it prints a meaningful string, not the binary representation of - the function contents. - - - Allow a ListOption's default value(s) to be a Python list of specified - values, not just a string containing a comma-separated list of names. - - - Add a ParseDepends() function that will parse up a list of explicit - dependencies from a "make depend" style file. - - - Support the ability to change directory when executing an Action - through "chdir" keyword arguments to Action and Builder creation - and calls. - - - Fix handling of Action ojects (and other callables that don't match - our calling arguments) in construction variable expansions. - - - On Win32, install scons.bat in the Python directory when installing - from setup.py. (The bdist_wininst installer was already doing this.) - - - Fix env.SConscript() when called with a list of SConscipt files. - (The SConscript() global function already worked properly.) - - - Add a missing newline to the end of the --debug=explain "unknown - reasons" message. - - - Enhance ParseConfig() to work properly for spaces in between the -I, - -L and -l options and their arguments. - - - Packaging build fix: Rebuild the files that are use to report the - --version of SCons whenever the development version number changes. - - - Fix the ability to specify a target_factory of Dir() to a Builder, - which the default create-a-directory Builder was interfering with. - - - Mark a directory as built if it's created as part of the preparation - for another target, to avoid trying to build it again when it comes - up in the target list. - - - Allow a function with the right calling signature to be put directly - in an Environment's BUILDERS dictionary, making for easier creation - and use of wrappers (pseudo-Builders) that call other Builders. - - - On Python 2.x, wrap lists of Nodes returned by Builders in a UserList - object that adds a method that makes str() object return a string - with all of the Nodes expanded to their path names. (Builders under - Python 1.5.2 still return lists to avoid TypeErrors when trying - to extend() list, so Python 1.5.2 doesn't get pretty-printing of Node - lists, but everything should still function.) - - - Allow Aliases to have actions that will be executed whenever - any of the expanded Alias targets are out of date. - - - Fix expansion of env.Command() overrides within target and - source file names. - - - Support easier customization of what's displayed by various default - actions by adding lots of new construction variables: $ARCOMSTR, - $ASCOMSTR, $ASPPCOMSTR, $BIBTEXCOMSTR, $BITKEEPERCOMSTR, $CCCOMSTR, - $CVSCOMSTR, $CXXCOMSTR, $DCOMSTR, $DVIPDFCOMSTR, $F77COMSTR, - $F90COMSTR, $F95COMSTR, $FORTRANCOMSTR, $GSCOMSTR, $JARCOMSTR, - $JAVACCOMSTR, $JAVAHCOMSTR, $LATEXCOMSTR, $LEXCOMSTR, $LINKCOMSTR, - $M4COMSTR, $MIDLCOMSTR, $P4COMSTR, $PCHCOMSTR, $PDFLATEXCOMSTR, - $PDFTEXCOMSTR, $PSCOMSTR, $QT_MOCFROMCXXCOMSTR, $QT_MOCFROMHCOMSTR, - $QT_UICCOMSTR, $RCCOMSTR, $REGSVRCOMSTR, $RCS_COCOMSTR, $RMICCOMSTR, - $SCCSCOMSTR, $SHCCCOMSTR, $SHCXXCOMSTR, $SHF77COMSTR, $SHF90COMSTR, - $SHF95COMSTR, $SHFORTRANCOMSTR, $SHLINKCOMSTR, $SWIGCOMSTR, - $TARCOMSTR, $TEXCOMSTR, $YACCCOMSTR and $ZIPCOMSTR. - - - Add an optional "map" keyword argument to ListOption() that takes a - dictionary to map user-specified values to legal values from the list - (like EnumOption() already doee). - - - Add specific exceptions to try:-except: blocks without any listed, - so that they won't catch and mask keyboard interrupts. - - - Make --debug={tree,dtree,stree} print something even when there's - a build failure. - - - Fix how Scanners sort the found dependencies so that it doesn't - matter whether the dependency file is in a Repository or not. - This may cause recompilations upon upgrade to this version. - - - Make AlwaysBuild() work with Alias and Python value Nodes (making - it much simpler to support aliases like "clean" that just invoke - an arbitrary action). - - - Have env.ParseConfig() use AppendUnique() by default to suppress - duplicate entries from multiple calls. Add a "unique" keyword - argument to allow the old behavior to be specified. - - - Allow the library modules imported by an SConscript file to get at - all of the normally-available global functions and variables by saying - "from SCons.Script import *". - - - Add a --debug=memoizer option to print Memoizer hit/mass statistics. - - - Allow more than one --debug= option to be set at a time. - - - Change --debug=count to report object counts before and after - reading SConscript files and before and after building targets. - - - Change --debug=memory output to line up the numbers and to better - match (more or less) the headers on the --debug=count columns. - - - Speed things up when there are lists of targets and/or sources by - getting rid of some N^2 walks of the lists involved. - - - Cache evaluation of LazyActions so we don't create a new object - for each invocation. - - - When scanning, don't create Nodes for include files that don't - actually exist on disk. - - - Make supported global variables CScanner, DScanner, ProgramScanner and - SourceFileScanner. Make SourceFileScanner.add_scanner() a supported - part of the public interface. Keep the old SCons.Defaults.*Scan names - around for a while longer since some people were already using them. - - - By default, don't scan directories for on-disk files. Add a - DirScanner global scanner that can be used in Builders or Command() - calls that want source directory trees scanned for on-disk changes. - Have the Tar() and Zip() Builders use the new DirScanner to preserve - the behavior of rebuilding a .tar or .zip file if any file or - directory under a source tree changes. Add Command() support for - a source_scanner keyword argument to Command() that can be set to - DirScanner to get this behavior. - - - Documentation changes: Explain that $CXXFLAGS contains $CCFLAGS - by default. Fix a bad target_factory example in the man page. - Add appendices to the User's Guide to cover the available Tools, - Builders and construction variables. Comment out the build of - the old Python 10 paper, which doesn't build on all systems and - is old enough at this point that it probably isn't worth the - effort to make it do so. - - From Wayne Lee: - - - Avoid "maximum recursion limit" errors when removing $(-$) pairs - from long command lines. - - From Clive Levinson: - - - Make ParseConfig() recognize and add -mno-cygwin to $LINKFLAGS and - $CCFLAGS, and -mwindows to $LINKFLAGS. - - From Michael McCracken: - - - Add a new "applelink" tool to handle the things like Frameworks and - bundles that Apple has added to gcc for linking. - - - Use more appropriate default search lists of linkers, compilers and - and other tools for the 'darwin' platform. - - - Add a LoadableModule Builder that builds a bundle on Mac OS X (Darwin) - and a shared library on other systems. - - - Improve SWIG tests for use on Mac OS X (Darwin). - - From Elliot Murphy: - - - Enhance the tests to guarantee persistence of ListOption - values in saved options files. - - - Supply the help text when -h is used with the -u, -U or -D options. - - From Christian Neeb: - - - Fix the Java parser's handling of string definitions to avoid ignoring - subsequent code. - - From Han-Wen Nienhuys: - - - Optimize variable expansion by: using the re.sub() method (when - possible); not using "eval" for variables for which we can fetch the - value directory; avoiding slowing substitution logic when there's no - '$' in the string. - - From Gary Oberbrunner: - - - Add an Environment.Dump() method to print the contents of a - construction environment. - - - Allow $LIBS (and similar variables) to contain explicit File Nodes. - - - Change ParseConfig to add the found library names directly to the - $LIBS variable, instead of returning them. - - - Add ParseConfig() support for the -framework GNU linker option. - - - Add a PRINT_CMD_LINE_FUNC construction variable to allow people - to filter (or log) command-line output. - - - Print an internal Python stack trace in response to an otherwise - unexplained error when --debug=stacktrace is specified. - - - Add a --debug=findlibs option to print what's happening when - the scanner is searching for libraries. - - - Allow Tool specifications to be passed a dictionary of keyword - arguments. - - - Support an Options default value of None, in which case the variable - will not be added to the construction environment unless it's set - explicitly by the user or from an Options file. - - - Avoid copying __builtin__ values into a construction environment's - dictionary when evaluating construction variables. - - - Add a new cross-platform intelc.py Tool that can detect and - configure the Intel C++ v8 compiler on both Windows, where it's - named icl, and Linux, where it's named icc. It also checks that - the directory specified in the Windows registry exists, and sets a - new $INTEL_C_COMPILER_VERSION construction variable to identify the - version being used. (Niall Douglas contributed an early prototype - of parts of this module.) - - - Fix the private Conftest._Have() function so it doesn't change - non-alphanumeric characters to underscores. - - - Supply a better error message when a construction variable expansion - has an unknown attribute. - - - Documentation changes: Update the man page to describe use of - filenames or Nodes in $LIBS. - - From Chris Pawling: - - - Have the linkloc tool use $MSVS_VERSION to select the Microsoft - Visual Studio version to use. - - From Kevin Quick: - - - Fix the Builder name returned from ListBuilders and other instances - of subclasses of the BuilderBase class. - - - Add Builders and construction variables to support rpcgen: - RPCGenClient(), RPCGenHeader(), RPCGenService(), RPCGenXDR(), - $RPCGEN, $RPCGENFLAGS, $RPCGENCLIENTFLAGS, $RPCGENHEADERFLAGS, - $RPCGENSERVICEFLAGS, $RPCGENXDRFLAGS. - - - Update the man page to document that prefix and suffix Builder - keyword arguments can be strings, callables or dictionaries. - - - Provide more info in the error message when a user tries to build - a target multiple ways. - - - Fix Delete() when a file doesn't exist and must_exist=1. (We were - unintentionally dependent on a bug in versions of the Python shutil.py - module prior to Python 2.3, which would generate an exception for - a nonexistent file even when ignore_errors was set.) - - - Only replace a Node's builder with a non-null source builder. - - - Fix a stack trace when a suffix selection dictionary is passed - an empty source file list. - - - Allow optional names to be attached to Builders, for default - Builders that don't get attached to construction environments. - - - Fix problems with Parallel Task Exception handling. - - - Build targets in an associated BuildDir even if there are targets - or subdirectories locally in the source directory. - - - If a FunctionAction has a callable class as its underlying Python - function, use its strfunction() method (if any) to display the - action. - - - Fix handling when BuildDir() exists but is unwriteable. Add - "Stop." to those error messages for consistency. - - - Catch incidents of bad builder creation (without an action) and - supply meaningful error messages. - - - Fix handling of src_suffix values that aren't extensions (don't - begin with a '.'). - - - Don't retrieve files from a CacheDir, but report what would happen, - when the -n option is used. - - - Use the source_scanner from the target Node, not the source node - itself. - - - Internal Scanners fixes: Make sure Scanners are only passed Nodes. - Fix how a Scanner.Selector called its base class initialization. - Make comparisons of Scanner objects more robust. Add a name to - an internal default ObjSourceScanner. - - - Add a deprecated warning for use of the old "scanner" keyword argument - to Builder creation. - - - Improve the --debug=explain message when the build action changes. - - - Test enhancements in SourceCode.py, option-n.py, midl.py. Better - Command() and Scanner test coverage. Improved test infrastructure - for -c output. - - - Refactor the interface between Action and Executor objects to treat - Actions atomically. - - - The --debug=presub option will now report the pre-substitution - each action seprately, instead of reporting the entire list before - executing the actions one by one. - - - The --debug=explain option explaining a changed action will now - (more correctly) show pre-substitution action strings, instead of - the commands with substituted file names. - - - A Node (file) will now be rebuilt if its PreAction or PostAction - actions change. - - - Python Function actions now have their calling signature (target, - source, env) reported correctly when displayed. - - - Fix BuildDir()/build_dir handling when the build_dir is underneath - the source directory and trying to use entries from the build_dir - as sources for other targets in the build-dir. - - - Fix hard-coding of JDK path names in various Java tests. - - - Handle Python stack traces consistently (stop at the SConscript stack - frame, by default) even if the Python source code isn't available. - - - Improve the performance of the --debug={tree,dtree} options. - - - Add --debug=objects logging of creation of OverrideWarner, - EnvironmentCopy and EnvironmentOverride objects. - - - Fix command-line expansion of Python Value Nodes. - - - Internal cleanups: Remove an unnecessary scan argument. Associate - Scanners only with Builders, not nodes. Apply overrides once when - a Builder is called, not in multiple places. Cache results from the - Node.FS.get_suffix() and Node.get_build_env() methods. Use the Python - md5 modules' hexdigest() method, if there is one. Have Taskmaster - call get_stat() once for each Node and re-use the value instead of - calling it each time it needs the value. Have Node.depends_on() - re-use the list from the children() method instead of calling it - multiple times. - - - Use the correct scanner if the same source file is used for targets in - two different environments with the same path but different scanners. - - - Collect logic for caching values in memory in a Memoizer class, - which cleans up a lot of special-case code in various methods and - caches additional values to speed up most configurations. - - - Add a PathAccept validator to the list of new canned PathOption - validators. - - From Jeff Squyres: - - - Documentation changes: Use $CPPDEFINES instead of $CCFLAGS in man - page examples. - - From Levi Stephen: - - - Allow $JARCHDIR to be expanded to other construction variables. - - From Christoph Wiedemann: - - - Add an Environment.SetDefault() method that only sets values if - they aren't already set. - - - Have the qt.py Tool not override variables already set by the user. - - - Add separate $QT_BINPATH, $QT_CPPPATH and $QT_LIBPATH variables - so these can be set individually, instead of being hard-wired - relative to $QTDIR. - - - The %TEMP% and %TMP% external environment variables are now propagated - automatically to the command execution environment on Windows systems. - - - A new --config= command-line option allows explicit control of - of when the Configure() tests are run: --config=force forces all - checks to be run, --config=cache uses all previously cached values, - --config=auto (the default) runs tests only when dependency analysis - determines it's necessary. - - - The Configure() subsystem can now write a config.h file with values - like HAVE_STDIO_H, HAVE_LIBM, etc. - - - The Configure() subsystem now executes its checks silently when the - -Q option is specified. - - - The Configure() subsystem now reports if a test result is being - taken from cache, and prints the standard output and error output - of tests even when cached. - - - Configure() test results are now reported as "yes" or "no" instead of - "ok" or "failed." - - - Fixed traceback printing when calling the env.Configure() method - instead of the Configure() global function. - - - The Configure() subsystem now caches build failures in a .sconsign - file in the subdirectory, not a .cache file. This may cause - tests to be re-executed the first time after you install 0.97. - - - Additional significant internal cleanups in the Configure() subsystem - and its tests. - - - Have the Qt Builder make uic-generated files dependent on the .ui.h - file, if one exists. - - - Add a test to make sure that SCons source code does not contain - try:-except: blocks that catch all errors, which potentially catch - and mask keyboard interrupts. - - - Fix us of TargetSignatures('content') with the SConf subsystem. - - From Russell Yanofsky: - - - Add support for the Metrowerks Codewarrior compiler and linker - (mwcc and mwld). - - - -RELEASE 0.96.1 - Mon, 23 Aug 2004 12:55:50 +0000 - - From Craig Bachelor: - - - Handle white space in the executable Python path name within in MSVS - project files by quoting the path. - - - Correct the format of a GUID string in a solution (.dsw) file so - MSVS can correctly "build enable" a project. - - From Steven Knight: - - - Add a must_exist flag to Delete() to let the user control whether - it's an error if the specified entry doesn't exist. The default - behavior is now to silently do nothing if it doesn't exist. - - - Package up the new Platform/darwin.py, mistakenly left out of 0.96. - - - Make the scons.bat REM statements into @REM so they aren't printed. - - - Make the SCons packaging SConscript files platform independent. - - From Anthony Roach: - - - Fix scanning of pre-compiled header (.pch) files for #includes, - broken in 0.96. - - - -RELEASE 0.96 - Wed, 18 Aug 2004 13:36:40 +0000 - - From Chad Austin: - - - Make the CacheDir() directory if it doesn't already exist. - - - Allow construction variable substitutions in $LIBS specifications. - - - Allow the emitter argument to a Builder() to be or expand to a list - of emitter functions, which will be called in sequence. - - - Suppress null values in construction variables like $LIBS that use - the internal _concat() function. - - - Remove .dll files from the construction variables searched for - libraries that can be fed to Win32 compilers. - - From Chad Austin and Christoph Wiedemann: - - - Add support for a $RPATH variable to supply a list of directories - to search for shared libraries when linking a program. Used by - the GNU and IRIX linkers (gnulink and sgilink). - - From Charles Crain: - - - Restore the ability to do construction variable substitutions in all - kinds of *PATH variables, even when the substitution returns a Node - or other object. - - From Tom Epperly: - - - Allow the Java() Builder to take more than one source directory. - - From Ralf W. Grosse-Kunstleve: - - - Have SConsignFile() use, by default, a custom "dblite.py" that we can - control and guarantee to work on all Python versions (or nearly so). - - From Jonathan Gurley: - - - Add support for the newer "ifort" versions of the Intel Fortran - Compiler for Linux. - - From Bob Halley: - - - Make the new *FLAGS variable type work with copied Environments. - - From Chris Hoeppler: - - - Initialize the name of a Scanner.Classic scanner correctly. - - From James Juhasz: - - - Add support for the .dylib shared library suffix and the -dynamiclib - linker option on Mac OS X. - - From Steven Knight: - - - Add an Execute() method for executing actions directly. - - - Support passing environment override keyword arguments to Command(). - - - Fix use of $MSVS_IGNORE_IDE_PATHS, which was broken when we added - support for $MSVS_USE_MFC_DIRS last release. - - - Make env.Append() and env.Prepend() act like the underlying Python - behavior when the variable being appended to is a UserList object. - - - Fix a regression that prevented the Command() global function in - 0.95 from working with command-line strings as actions. - - - Fix checking out a file from a source code management system when - the env.SourceCode() method was called with an individual file name - or node, not a directory name or node. - - - Enhance the Task.make_ready() method to create a list of the - out-of-date Nodes for the task for use by the wrapping interface. - - - Allow Scanners to pull the list of suffixes from the construction - environment when the "skeys" keyword argument is a string containing - a construction variable to be expanded. - - - Support new $CPPSUFFIXES, $DSUFFIXES $FORTRANSUFFIXES, and - $IDLSUFFIXES. construction variables that contain the default list - of suffixes to be scanned by a given type of scanner, allowing these - suffix lists to be easily added to or overridden. - - - Speed up Node creation when calling a Builder by comparing whether two - Environments are the same object, not if their underlying dictionaries - are equivalent. - - - Add a --debug=explain option that reports the reason(s) why SCons - thinks it must rebuild something. - - - Add support for functions that return platform-independent Actions - to Chmod(), Copy(), Delete(), Mkdir(), Move() and Touch() files - and/or directories. Like any other Actions, the returned Action - object may be executed directly using the Execute() global function - or env.Execute() environment method, or may be used as a Builder - action or in an env.Command() action list. - - - Add support for the strfunction argument to all types of Actions: - CommandAction, ListAction, and CommandGeneratorAction. - - - Speed up turning file system Nodes into strings by caching the - values after we're finished reading the SConscript files. - - - Have ParseConfig() recognize and supporting adding the -Wa, -Wl, - and -Wp, flags to ASFLAGS, LINKFLAGS and CPPFLAGS, respectively. - - - Change the .sconsign format and the checks for whether a Node is - up-to-date to make dependency checks more efficient and correct. - - - Add wrapper Actions to SCons.Defaults for $ASCOM, $ASPPCOM, $LINKCOM, - $SHLINKCOM, $ARCOM, $LEXCOM and $YACCCOM. This makes it possible - to replace the default print behavior with a custom strfunction() - for each of these. - - - When a Node has been built, don't walk the whole tree back to delete - the parents's implicit dependencies, let returning up the normal - Taskmaster descent take care of it for us. - - - Add documented support for separate target_scanner and source_scanner - arguments to Builder creation, which allows different scanners to - be applied to source files - - - Don't re-install or (re-generate) .h files when a subsidiary #included - .h file changes. This eliminates incorrect circular dependencies - with .h files generated from other source files. - - - Slim down the internal Sig.Calculator class by eliminating methods - whose functionality is now covered by Node methods. - - - Document use of the target_factory and source_factory keyword - arguments when creating Builder objects. Enhance Dir Nodes so that - they can be created with user-specified Builder objects. - - - Don't blow up with stack trace when the external $PATH environment - variable isn't set. - - - Make Builder calls return lists all the time, even if there's only - one target. This keeps things consistent and easier to program to - across platforms. - - - Add a Flatten() function to make it easier to deal with the Builders - all returning lists of targets, not individual targets. - - - Performance optimizations in Node.FS.__doLookup(). - - - Man page fixes: formatting typos, misspellings, bad example. - - - User's Guide fixes: Fix the signatures of the various example - *Options() calls. Triple-quote properly a multi-line Split example. - - - User's Guide additions: Chapter describing File and Directory - Nodes. Section describing declarative nature of SCons functions in - SConscript files. Better organization and clarification of points - raised by Robert P. J. Day. Chapter describing SConf (Autoconf-like) - functionality. Chapter describing how to install Python and - SCons. Chapter describing Java builds. - - From Chris Murray: - - - Add a .win32 attribute to force file names to expand with - Windows backslash path separators. - - - Fix escaping file names on command lines when the expansion is - concatenated with another string. - - - Add support for Fortran 90 and Fortran 95. This adds $FORTRAN* - variables that specify a default compiler, command-line, flags, - etc. for all Fortran versions, plus separate $F90* and $F95* - variables for when different compilers/flags/etc. must be specified - for different Fortran versions. - - - Have individual tools that create libraries override the default - $LIBPREFIX and $LIBSUFFIX values set by the platform. This makes - it easier to use Microsoft Visual Studio tools on a CygWin platform. - - From Gary Oberbrunner: - - - Add a --debug=presub option to print actions prior to substitution. - - - Add a warning upon use of the override keywords "targets" and - "sources" when calling Builders. These are usually mistakes which - are otherwise silently (and confusingly) turned into construction - variable overrides. - - - Try to find the ICL license file path name in the external environment - and the registry before resorting to the hard-coded path name. - - - Add support for fetching command-line keyword=value arguments in - order from an ARGLIST list. - - - Avoid stack traces when trying to read dangling symlinks. - - - Treat file "extensions" that only contain digits as part of the - file basename. This supports version numbers as part of shared - library names, for example. - - - Avoid problems when there are null entries (None or '') in tool - lists or CPPPATH. - - - Add an example and explanation of how to use "tools = ['default', ..." - when creating a construction environment. - - - Add a section describing File and Directory Nodes and some of their - attributes and methods. - - - Have ParseConfig() add a returned -pthread flag to both $CCFLAGS - and $LINKFLAGS. - - - Fix some test portability issues on Mac OS X (darwin). - - From Simon Perkins: - - - Fix a bug introduced in building shared libraries under MinGW. - - From Kevin Quick: - - - Handling SCons exceptions according to Pythonic standards. - - - Fix test/chained-build.py on systems that execute within one second. - - - Fix tests on systems where 'ar' warns about archive creation. - - From Anthony Roach: - - - Fix use of the --implicit-cache option with timestamp signatures. - - - If Visual Studio is installed, assume the C/C++ compiler, the linker - and the MIDL compiler that comes with it are available, too. - - - Better error messages when evaluating a construction variable - expansion yields a Python syntax error. - - - Change the generation of PDB files when using Visual Studio from - compile time to link time. - - From sam th: - - - Allow SConf.CheckLib() to search a list of libraries, like the - Autoconf AC_SEARCH_LIBS macro. - - - Allow the env.WhereIs() method to take a "reject" argument to - let it weed out specific path names. - - From Christoph Wiedemann: - - - Add new Moc() and Uic() Builders for more explicit control over - Qt builds, plus new construction variables to control them: - $QT_AUTOSCAN, $QT_DEBUG, $QT_MOCCXXPREFIX, $QT_MOCCXXSUFFIX, - $QT_MOCHPREFIX, $QT_MOCHSUFFIX, $QT_UICDECLPREFIX, $QT_UICDECLSUFFIX, - $QT_UICIMPLPREFIX, $QT_UICIMPLSUFFIX and $QT_UISUFFIX. - - - Add a new single_source keyword argument for Builders that enforces - a single source file on calls to the Builder. - - - -RELEASE 0.95 - Mon, 08 Mar 2004 06:43:20 -0600 - - From Chad Austin: - - - Replace print statements with calls to sys.stdout.write() so output - lines stay together when -j is used. - - - Add portability fixes for a number of tests. - - - Accomodate the fact that Cygwin's os.path.normcase() lies about - the underlying system being case-sensitive. - - - Fix an incorrect _concat() call in the $RCINCFLAGS definition for - the mingw Tool. - - - Fix a problem with the msvc tool with Python versions prior to 2.3. - - - Add support for a "toolpath" Tool() and Environment keyword that - allows Tool modules to be found in specified local directories. - - - Work around Cygwin Python's silly fiction that it's using a - case-sensitive file system. - - - More robust handling of data in VCComponents.dat. - - - If the "env" command is available, spawn commands with the more - general "env -" instead of "env -i". - - From Kerim Borchaev: - - - Fix a typo in a msvc.py's registry lookup: "VCComponents.dat", not - "VSComponents.dat". - - From Chris Burghart: - - - Fix the ability to save/restore a PackageOption to a file. - - From Steve Christensen: - - - Update the MSVS .NET and MSVC 6.0/7.0 path detection. - - From David M. Cooke: - - - Make the Fortran scanner case-insensitive for the INCLUDE string. - - From Charles Crain: - - - If no version of MSVC is detected but the tool is specified, - use the MSVC 6.0 paths by default. - - - Ignore any "6.1" version of MSVC found in the registry; this is a - phony version number (created by later service packs?) and would - throw off the logic if the user had any non-default paths configure. - - - Correctly detect if the user has independently configured the MSVC - "include," "lib" or "path" in the registry and use the appropriate - values. Previously, SCons would only use the values if all three - were set in the registry. - - - Make sure side-effect nodes are prepare()d before building their - corresponding target. - - - Preserve the ability to call BuildDir() multiple times with the - same target and source directory arguments. - - From Andy Friesen: - - - Add support for the Digital Mars "D" programming language. - - From Scott Lystig Fritchie: - - - Fix the ability to use a custom _concat() function in the - construction environment when calling _stripixes(). - - - Make the message about ignoring a missing SConscript file into a - suppressable Warning, not a hard-coded sys.stderr.write(). - - - If a builder can be called multiple times for a target (because - the sources and overrides are identical, or it's a builder with the - "multi" flag set), allow the builder to be called through multiple - environments so long as the builders have the same signature for - the environments in questions (that is, they're the same action). - - From Bob Halley: - - - When multiple targets are built by a single action, retrieve all - of them from cache, not just the first target, and exec the build - command if any of the targets isn't present in the cache. - - From Zephaniah Hull: - - - Fix command-line ARGUMENTS with multiple = in them. - - From Steven Knight: - - - Fix EnsureSConsVersion() so it checks against the SCons version, - not the Python version, on Pythons with sys.version_info. - - - Don't swallow the AttributeError when someone uses an expansion like - $TARGET.bak, so we can supply a more informative error message. - - - Fix an odd double-quote escape sequence in the man page. - - - Fix looking up a naked drive letter as a directory (Dir('C:')). - - - Support using File nodes in the LIBS construction variable. - - - Allow the LIBS construction variable to be a single string or File - node, not a list, when only one library is needed. - - - Fix typos in the man page: JAVACHDIR => JARCHDIR; add "for_signature" - to the __call__() example in the "Variable Substitution" section. - - - Correct error message spellings of "non-existant" to "non-existent." - - - When scanning for libraries to link with, don't append $LIBPREFIXES - or $LIBSUFFIXES values to the $LIBS values if they're already present. - - - Add a ZIPCOMPRESSION construction variable to control whether the - internal Python action for the Zip Builder compresses the file or - not. The default value is zipfile.ZIP_DEFLATED, which generates - a compressed file. - - - Refactor construction variable expansion to support recursive - expansion of variables (e.g. CCFLAGS = "$CCFLAGS -g") without going - into an infinite loop. Support this in all construction variable - overrides, as well as when copying Environments. - - - Fix calling Configure() from more than one subsidiary SConscript file. - - - Fix the env.Action() method so it returns the correct type of - Action for its argument(s). - - - Fix specifying .class files as input to JavaH with the .class suffix - when they weren't generated using the Java Builder. - - - Make the check for whether all of the objects going into a - SharedLibrary() are shared work even if the object was built in a - previous run. - - - Supply meaningful error messages, not stack traces, if we try to add - a non-Node as a source, dependency, or ignored dependency of a Node. - - - Generate MSVS Project files that re-invoke SCons properly regardless - of whether the file was built via scons.bat or scons.py. - (Thanks to Niall Douglas for contributing code and testing.) - - - Fix TestCmd.py, runtest.py and specific tests to accomodate being - run from directories whose paths include white space. - - - Provide a more useful error message if a construction variable - expansion contains a syntax error during evaluation. - - - Fix transparent checkout of implicit dependency files from SCCS - and RCS. - - - Added new --debug=count, --debug=memory and --debug=objects options. - --debug=count and --debug=objects only print anything when run - under Python 2.1 or later. - - - Deprecate the "overrides" keyword argument to Builder() creation - in favor of using keyword argument values directly (like we do - for builder execution and the like). - - - Always use the Builder overrides in substitutions, not just if - there isn't a target-specific environment. - - - Add new "rsrcpath" and "rsrcdir" and attributes to $TARGET/$SOURCE, - so Builder command lines can find things in Repository source - directories when using BuildDir. - - - Fix the M4 Builder so that it chdirs to the Repository directory - when the input file is in the source directory of a BuildDir. - - - Save memory at build time by allowing Nodes to delete their build - environments after they've been built. - - - Add AppendUnique() and PrependUnique() Environment methods, which - add values to construction variables like Append() and Prepend() - do, but suppress any duplicate elements in the list. - - - Allow the 'qt' tool to still be used successfully from a copied - Environment. The include and library directories previously ended up - having the same string re-appended to the end, yielding an incorrect - path name. - - - Supply a more descriptive error message when the source for a target - can't be found. - - - Initialize all *FLAGS variables with objects do the right thing with - appending flags as strings or lists. - - - Make things like ${TARGET.dir} work in *PATH construction variables. - - - Allow a $MSVS_USE_MFC_DIRS construction variable to control whether - ATL and MFC directories are included in the default INCLUDE and - LIB paths. - - - Document the dbm_module argument to the SConsignFile() function. - - From Vincent Risi: - - - Add support for the bcc32, ilink32 and tlib Borland tools. - - From Anthony Roach: - - - Supply an error message if the user tries to configure a BuildDir - for a directory that already has one. - - - Remove documentation of the still-unimplemented -e option. - - - Add -H help text listing the legal --debug values. - - - Don't choke if a construction variable is a non-string value. - - - Build Type Libraries in the target directory, not the source - directory. - - - Add an appendix to the User's Guide showing how to accomplish - various common tasks in Python. - - From Greg Spencer: - - - Add support for Microsoft Visual Studio 2003 (version 7.1). - - - Evaluate $MSVSPROJECTSUFFIX and $MSVSSOLUTIONSUFFIX when the Builder - is invoked, not when the tool is initialized. - - From Christoph Wiedemann: - - - When compiling Qt, make sure the moc_*.cc files are compiled using - the flags from the environment used to specify the target, not - the environment that first has the Qt Builders attached. - - - -RELEASE 0.94 - Fri, 07 Nov 2003 05:29:48 -0600 - - From Hartmut Goebel: - - - Add several new types of canned functions to help create options: - BoolOption(), EnumOption(), ListOption(), PackageOption(), - PathOption(). - - From Steven Knight: - - - Fix use of CPPDEFINES with C++ source files. - - - Fix env.Append() when the operand is an object with a __cmp__() - method (like a Scanner instance). - - - Fix subclassing the Environment and Scanner classes. - - - Add BUILD_TARGETS, COMMAND_LINE_TARGETS and DEFAULT_TARGETS variables. - - From Steve Leblanc: - - - SGI fixes: Fix C++ compilation, add a separate Tool/sgic++.py module. - - From Gary Oberbrunner: - - - Fix how the man page un-indents after examples in some browsers. - - From Vincent Risi: - - - Fix the C and C++ tool specifications for AIX. - - - -RELEASE 0.93 - Thu, 23 Oct 2003 07:26:55 -0500 - - From J.T. Conklin: - - - On POSIX, execute commands with the more modern os.spawnvpe() - function, if it's available. - - - Scan .S, .spp and .SPP files for C preprocessor dependencies. - - - Refactor the Job.Parallel() class to use a thread pool without a - condition variable. This improves parallel build performance and - handles keyboard interrupts properly when -j is used. - - From Charles Crain: - - - Add support for a JARCHDIR variable to control changing to a - directory using the jar -C option. - - - Add support for detecting Java manifest files when using jar, - and specifying them using the jar m flag. - - - Fix some Python 2.2 specific things in various tool modules. - - - Support directories as build sources, so that a rebuild of a target - can be triggered if anything underneath the directory changes. - - - Have the scons.bat and scons.py files look for the SCons modules - in site-packages as well. - - From Christian Engel: - - - Support more flexible inclusion of separate C and C++ compilers. - - - Use package management tools on AIX and Solaris to find where - the comilers are installed, and what version they are. - - - Add support for CCVERSION and CXXVERSION variables for a number - of C and C++ compilers. - - From Sergey Fogel: - - - Add test cases for the new capabilities to run bibtex and to rerun - latex as needed. - - From Ralf W. Grosse-Kunstleve: - - - Accomodate anydbm modules that don't have a sync() method. - - - Allow SConsignFile() to take an argument specifying the DBM - module to be used. - - From Stephen Kennedy: - - - Add support for a configurable global .sconsign.dbm file which - can be used to avoid cluttering each directory with an individual - .sconsign file. - - From John Johnson: - - - Fix (re-)scanning of dependencies in generated or installed - header files. - - From Steven Knight: - - - The -Q option suppressed too many messages; fix it so that it only - suppresses the Reading/Building messages. - - - Support #include when there's no space before the opening quote - or angle bracket. - - - Accomodate alphanumeric version strings in EnsurePythonVersion(). - - - Support arbitrary expansion of construction variables within - file and directory arguments to Builder calls and Environment methods. - - - Add Environment-method versions of the following global functions: - Action(), AddPostAction(), AddPreAction(), Alias(), Builder(), - BuildDir(), CacheDir(), Clean(), Configure(), Default(), - EnsurePythonVersion(), EnsureSConsVersion(), Environment(), - Exit(), Export(), FindFile(), GetBuildPath(), GetOption(), Help(), - Import(), Literal(), Local(), Platform(), Repository(), Scanner(), - SConscriptChdir(), SConsignFile(), SetOption(), SourceSignatures(), - Split(), TargetSignatures(), Tool(), Value(). - - - Add the following global functions that correspond to the same-named - Environment methods: AlwaysBuild(), Command(), Depends(), Ignore(), - Install(), InstallAs(), Precious(), SideEffect() and SourceCode(). - - - Add the following global functions that correspond to the default - Builder methods supported by SCons: CFile(), CXXFile(), DVI(), Jar(), - Java(), JavaH(), Library(), M4(), MSVSProject(), Object(), PCH(), - PDF(), PostScript(), Program(), RES(), RMIC(), SharedLibrary(), - SharedObject(), StaticLibrary(), StaticObject(), Tar(), TypeLibrary() - and Zip(). - - - Rearrange the man page to show construction environment methods and - global functions in the same list, and to explain the difference. - - - Alphabetize the explanations of the builder methods in the man page. - - - Rename the Environment.Environment class to Enviroment.Base. - Allow the wrapping interface to extend an Environment by using its own - subclass of Environment.Base and setting a new Environment.Environment - variable as the calling entry point. - - - Deprecate the ParseConfig() global function in favor of a same-named - construction environment method. - - - Allow the Environment.WhereIs() method to take explicit path and - pathext arguments (like the underlying SCons.Util.WhereIs() function). - - - Remove the long-obsolete {Get,Set}CommandHandler() functions. - - - Enhance env.Append() to suppress null values when appropriate. - - - Fix ParseConfig() so it works regardless of initial construction - variable values. - - Extend CheckHeader(), CheckCHeader(), CheckCXXHeader() and - CheckLibWithHeader() to accept a list of header files that will be - #included in the test. The last one in the list is assumed to be - the one being checked for. (Prototype code contributed by Gerard - Patel and Niall Douglas). - - - Supply a warning when -j is used and threading isn't built in to - the current version of Python. - - - First release of the User's Guide (finally, and despite a lot - of things still missing from it...). - - From Clark McGrew: - - - Generalize the action for .tex files so that it will decide whether - a file is TeX or LaTeX, check the .aux output to decide if it should - run bibtex, and check the .log output to re-run LaTeX if needed. - - From Bram Moolenaar: - - - Split the non-SCons-specific functionality from SConf.py to a new, - re-usable Conftest.py module. - - From Gary Oberbrunner: - - - Allow a directory to be the target or source or dependency of a - Depends(), Ignore(), Precious() or SideEffect() call. - - From Gerard Patel: - - - Use the %{_mandir} macro when building our RPM package. - - From Marko Rauhamaa: - - - Have the closing message say "...terminated because of errors" if - there were any. - - From Anthony Roach: - - - On Win32 systems, only use "rm" to delete files if Cygwin is being - used. ("rm" doesn't understand Win32-format path names.) - - From Christoph Wiedemann: - - - Fix test/SWIG.py to find the Python include directory in all cases. - - - Fix a bug in detection of Qt installed on the local system. - - - Support returning Python 2.3 BooleanType values from Configure checks. - - - Provide an error message if someone mistakenly tries to call a - Configure check from within a Builder function. - - - Support calling a Builder when a Configure context is still open. - - - Handle interrupts better by eliminating all try:-except: blocks - which caught any and all exceptions, including KeyboardInterrupt. - - - Add a --duplicate= option to control how files are duplicated. - - - -RELEASE 0.92 - Wed, 20 Aug 2003 03:45:28 -0500 - - From Charles Crain and Gary Oberbrunner: - - - Fix Tool import problems with the Intel and PharLap linkers. - - From Steven Knight - - - Refactor the DictCmdGenerator class to be a Selector subclass. - - - Allow the DefaultEnvironment() function to take arguments and pass - them to instantiation of the default construction environment. - - - Update the Debian package so it uses Python 2.2 and more closely - resembles the currently official Debian packaging info. - - From Gerard Patel - - - When the yacc -d flag is used, take the .h file base name from the - target .c file, not the source (matching what yacc does). - - - -RELEASE 0.91 - Thu, 14 Aug 2003 13:00:44 -0500 - - From Chad Austin: - - - Support specifying a list of tools when calling Environment.Copy(). - - - Give a Value Nodes a timestamp of the system time when they're - created, so they'll work when using timestamp-based signatures. - - - Add a DefaultEnvironment() function that only creates a default - environment on-demand (for fetching source files, e.g.). - - - Portability fix for test/M4.py. - - From Steven Knight: - - - Tighten up the scons -H help output. - - - When the input yacc file ends in .yy and the -d flag is specified, - recognize that a .hpp file (not a .h file) will be created. - - - Make builder prefixes work correctly when deducing a target - from a source file name in another directory. - - - Documentation fixes: typo in the man page; explain up-front about - not propagating the external environment. - - - Use "cvs co -d" instead of "cvs co -p >" when checking out something - from CVS with a specified module name. This avoids zero-length - files when there is a checkout error. - - - Add an "sconsign" script to print the contents of .sconsign files. - - - Speed up maintaining the various lists of Node children by using - dictionaries to avoid "x in list" searches. - - - Cache the computed list of Node children minus those being Ignored - so it's only calculated once. - - - Fix use of the --cache-show option when building a Program() - (or using any other arbitrary action) by making sure all Action - instances have strfunction() methods. - - - Allow the source of Command() to be a directory. - - - Better error handling of things like raw TypeErrors in SConscripts. - - - When installing using "setup.py install --prefix=", suppress the - distutils warning message about adding the (incorrect) library - directory to your search path. - - - Correct the spelling of the "validater" option to "validator." - Add a DeprecatedWarning when the old spelling is used. - - - Allow a Builder's emitter to be a dictionary that maps source file - suffixes to emitter functions, using the suffix of the first file - in the source list to pick the right one. - - - Refactor the creation of the Program, *Object and *Library Builders - so that they're moved out of SCons.Defaults and created on demand. - - - Don't split SConscript file names on white space. - - - Document the SConscript function's "dirs" and "name" keywords. - - - Remove the internal (and superfluous) SCons.Util.argmunge() function. - - - Add /TP to the default CXXFLAGS for msvc, so it can compile all - of the suffixes we use as C++ files. - - - Allow the "prefix" and "suffix" attributes of a Builder to be - callable objects that return generated strings, or dictionaries - that map a source file suffix to the right prefix/suffix. - - - Support a MAXLINELINELENGTH construction variable on Win32 systems - to control when a temporary file is used for long command lines. - - - Make how we build .rpm packages not depend on the installation - locations from the distutils being used. - - - When deducing a target Node, create it directly from the first - source Node, not by trying to create the right string to pass to - arg2nodes(). - - - Add support for SWIG. - - From Bram Moolenaar: - - - Test portability fixes for FreeBSD. - - From Gary Oberbrunner: - - - Report the target being built in error messages when building - multiple sources from different extensions, or when the target file - extension can't be deduced, or when we don't have an action for a - file suffix. - - - Provide helpful error messages when the arguments to env.Install() - are incorrect. - - - Fix the value returned by the Node.prevsiginfo() method to conform - to a previous change when checking whether a node is current. - - - Supply a stack trace if the Taskmaster catches an exception. - - - When using a temporary file for a long link line on Win32 systems, - (also) print the command line that is being executed through the - temporary file. - - - Initialize the LIB environment variable when using the Intel - compiler (icl). - - - Documentation fixes: better explain the AlwaysBuild() function. - - From Laurent Pelecq: - - - When the -debug=pdb option is specified, use pdb.Pdb().runcall() to - call pdb directly, don't call Python recursively. - - From Ben Scott: - - - Add support for a platform-independent CPPDEFINES variable. - - From Christoph Wiedemann: - - - Have the g++ Tool actually use g++ in preference to c++. - - - Have the gcc Tool actually use gcc in preference to cc. - - - Add a gnutools.py test of the GNU tool chain. - - - Be smarter about linking: use $CC by default and $CXX only if we're - linking with any C++ objects. - - - Avoid SCons hanging when a piped command has a lot of output to read. - - - Add QT support for preprocessing .ui files into .c files. - - - -RELEASE 0.90 - Wed, 25 Jun 2003 14:24:52 -0500 - - From Chad Austin: - - - Fix the _concat() documentation, and add a test for it. - - - Portability fixes for non-GNU versions of lex and yacc. - - From Matt Balvin: - - - Fix handling of library prefixes when the subdirectory matches - the prefix. - - From Timothee Bessett: - - - Add an M4 Builder. - - From Charles Crain: - - - Use '.lnk' as the suffix on the temporary file for linking long - command lines (necessary for the Phar Lap linkloc linker). - - - Save non-string Options values as their actual type. - - - Save Options string values that contain a single quote correctly. - - - Save any Options values that are changed from the default - Environment values, not just ones changed on the command line or in - an Options file. - - - Make closing the Options file descriptor exception-safe. - - From Steven Knight: - - - SCons now enforces (with an error) that construction variables - must have the same form as valid Python identifiers. - - - Fix man page bugs: remove duplicate AddPostAction() description; - document no_import_lib; mention that CPPFLAGS does not contain - $_CPPINCFLAGS; mention that F77FLAGS does not contain $_F77INCFLAGS; - mention that LINKFLAGS and SHLINKFLAGS contains neither $_LIBFLAGS - nor $_LIBDIRFLAGS. - - - Eliminate a dependency on the distutils.fancy_getopt module by - copying and pasting its wrap_text() function directly. - - - Make the Script.Options() subclass match the underlying base class - implementation. - - - When reporting a target is up to date, quote the target like make - (backquote-quote) instead of with double quotes. - - - Fix handling of ../* targets when using -U, -D or -u. - - From Steve Leblanc: - - - Don't update the .sconsign files when run with -n. - - From Gary Oberbrunner: - - - Add support for the Intel C Compiler (icl.exe). - - From Anthony Roach - - - Fix Import('*'). - - From David Snopek - - - Fix use of SConf in paths with white space in them. - - - Add CheckFunc and CheckType functionality to SConf. - - - Fix use of SConf with Builders that return a list of nodes. - - From David Snopek and Christoph Wiedemann - - - Fix use of the SConf subsystem with SConscriptChdir(). - - From Greg Spencer - - - Check for the existence of MS Visual Studio on disk before using it, - to avoid getting fooled by leftover junk in the registry. - - - Add support for MSVC++ .NET. - - - Add support for MS Visual Studio project files (DSP, DSW, - SLN and VCPROJ files). - - From Christoph Wiedemann - - - SConf now works correctly when the -n and -q options are used. - - - -RELEASE 0.14 - Wed, 21 May 2003 05:16:32 -0500 - - From Chad Austin: - - - Use .dll (not .so) for shared libraries on Cygwin; use -fPIC - when compiling them. - - - Use 'rm' to remove files under Cygwin. - - - Add a PLATFORM variable to construction environments. - - - Remove the "platform" argument from tool specifications. - - - Propogate PYTHONPATH when running the regression tests so distutils - can be found in non-standard locations. - - - Using MSVC long command-line linking when running Cygwin. - - - Portability fixes for a lot of tests. - - - Add a Value Node class for dependencies on in-core Python values. - - From Allen Bierbaum: - - - Pass an Environment to the Options validator method, and - add an Options.Save() method. - - From Steve Christensen: - - - Add an optional sort function argument to the GenerateHelpText() - Options function. - - - Evaluate the "varlist" variables when computing the signature of a - function action. - - From Charles Crain: - - - Parse the source .java files for class names (including inner class - names) to figure out the target .class files that will be created. - - - Make Java support work with Repositories and SConscriptChdir(0). - - - Pass Nodes, not strings, to Builder emitter functions. - - - Refactor command-line interpolation and signature calculation - so we can use real Node attributes. - - From Steven Knight: - - - Add Java support (javac, javah, jar and rmic). - - - Propagate the external SYSTEMROOT environment variable into ENV on - Win32 systems, so external commands that use sockets will work. - - - Add a .posix attribute to PathList expansions. - - - Check out CVS source files using POSIX path names (forward slashes - as separators) even on Win32. - - - Add Node.clear() and Node.FS.Entry.clear() methods to wipe out a - Node's state, allowing it to be re-evaluated by continuous - integration build interfaces. - - - Change the name of the Set{Build,Content}SignatureType() functions - to {Target,Source}Signatures(). Deprecate the old names but support - them for backwards compatibility. - - - Add internal SCons.Node.FS.{Dir,File}.Entry() methods. - - - Interpolate the null string if an out-of-range subscript is used - for a construction variable. - - - Fix the internal Link function so that it properly links or copies - files in subsidiary BuildDir directories. - - - Refactor the internal representation of a single execution instance - of an action to eliminate redundant signature calculations. - - - Eliminate redundant signature calculations for Nodes. - - - Optimize out calling hasattr() before accessing attributes. - - - Say "Cleaning targets" (not "Building...") when the -c option is - used. - - From Damyan Pepper: - - - Quote the "Entering directory" message like Make. - - From Stefan Reichor: - - - Add support for using Ghostscript to convert Postscript to PDF files. - - From Anthony Roach: - - - Add a standalone "Alias" function (separate from an Environment). - - - Make Export() work for local variables. - - - Support passing a dictionary to Export(). - - - Support Import('*') to import everything that's been Export()ed. - - - Fix an undefined exitvalmap on Win32 systems. - - - Support new SetOption() and GetOption() functions for setting - various command-line options from with an SConscript file. - - - Deprecate the old SetJobs() and GetJobs() functions in favor of - using the new generic {Set,Get}Option() functions. - - - Fix a number of tests that searched for a Fortran compiler using the - external PATH instead of what SCons would use. - - - Fix the interaction of SideEffect() and BuildDir() so that (for - example) PDB files get put correctly in a BuildDir(). - - From David Snopek: - - - Contribute the "Autoscons" code for Autoconf-like checking for - the existence of libraries, header files and the like. - - - Have the Tool() function add the tool name to the $TOOLS - construction variable. - - From Greg Spencer: - - - Support the C preprocessor #import statement. - - - Allow the SharedLibrary() Builder on Win32 systems to be able to - register a newly-built dll using regsvr32. - - - Add a Builder for Windows type library (.tlb) files from IDL files. - - - Add an IDL scanner. - - - Refactor the Fortran, C and IDL scanners to share common logic. - - - Add .srcpath and .srcdir attributes to $TARGET and $SOURCE. - - From Christoph Wiedemann: - - - Integrate David Snopek's "Autoscons" code as the new SConf - configuration subsystem, including caching of values between - runs (using normal SCons dependency mechanisms), tests, and - documentation. - - - -RELEASE 0.13 - Mon, 31 Mar 2003 20:22:00 -0600 - - From Charles Crain: - - - Fix a bug when BuildDir(duplicate=0) is used and SConscript - files are called from within other SConscript files. - - - Support (older) versions of Perforce which don't set the Windows - registry. - - - -RELEASE 0.12 - Thu, 27 Mar 2003 23:52:09 -0600 - - From Charles Crain: - - - Added support for the Perforce source code management system. - - - Fix str(Node.FS) so that it returns a path relative to the calling - SConscript file's directory, not the top-level directory. - - - Added support for a separate src_dir argument to SConscript() - that allows explicit specification of where the source files - for an SConscript file can be found. - - - Support more easily re-usable flavors of command generators by - calling callable variables when strings are expanded. - - From Steven Knight: - - - Added an INSTALL construction variable that can be set to a function - to control how the Install() and InstallAs() Builders install files. - The default INSTALL function now copies, not links, files. - - - Remove deprecated features: the "name" argument to Builder objects, - and the Environment.Update() method. - - - Add an Environment.SourceCode() method to support fetching files - from source code systems. Add factory methods that create Builders - to support BitKeeper, CVS, RCS, and SCCS. Add support for fetching - files from RCS or SCCS transparently (like GNU Make). - - - Make the internal to_String() function more efficient. - - - Make the error message the same as other build errors when there's a - problem unlinking a target file in preparation for it being built. - - - Make TARGET, TARGETS, SOURCE and SOURCES reserved variable names and - warn if the user tries to set them in a construction environment. - - - Add support for Tar and Zip files. - - - Better documentation of the different ways to export variables to a - subsidiary SConscript file. Fix documentation bugs in a tools - example, places that still assumed SCons split strings on white - space, and typos. - - - Support fetching arbitrary files from the TARGETS or SOURCES lists - (e.g. ${SOURCES[2]}) when calculating the build signature of a - command. - - - Don't silently swallow exceptions thrown by Scanners (or other - exceptions while finding a node's dependent children). - - - Push files to CacheDir() before calling the superclass built() - method (which may clear the build signature as part of clearing - cached implicit dependencies, if the file has a source scanner). - (Bug reported by Jeff Petkau.) - - - Raise an internal error if we attempt to push a file to CacheDir() - with a build signature of None. - - - Add an explicit Exit() function for terminating early. - - - Change the documentation to correctly describe that the -f option - doesn't change to the directory in which the specified file lives. - - - Support changing directories locally with SConscript directory - path names relative to any SConstruct file specified with -f. - This allows you to build in another directory by simply changing - there and pointing at the SConstruct file in another directory. - - - Change the default SConscriptChdir() behavior to change to the - SConscript directory while it's being read. - - - Fix an exception thrown when the -U option was used with no - Default() target specified. - - - Fix -u so that it builds things in corresponding build directories - when used in a source directory. - - From Lachlan O'Dea: - - - Add SharedObject() support to the masm tool. - - - Fix WhereIs() to return normalized paths. - - From Jeff Petkau: - - - Don't copy a built file to a CacheDir() if it's already there. - - - Avoid partial copies of built files in a CacheDir() by copying - to a temporary file and renaming. - - From Anthony Roach: - - - Fix incorrect dependency-cycle errors when an Aliased source doesn't - exist. - - - -RELEASE 0.11 - Tue, 11 Feb 2003 05:24:33 -0600 - - From Chad Austin: - - - Add support for IRIX and the SGI MIPSPro tool chain. - - - Support using the MSVC tool chain when running Cygwin Python. - - From Michael Cook: - - - Avoid losing signal bits in the exit status from a command, - helping terminate builds on interrupt (CTRL+C). - - From Charles Crain: - - - Added new AddPreAction() and AddPostAction() functions that support - taking additional actions before or after building specific targets. - - - Add support for the PharLap ETS tool chain. - - From Steven Knight: - - - Allow Python function Actions to specify a list of construction - variables that should be included in the Action's signature. - - - Allow libraries in the LIBS variable to explicitly include the prefix - and suffix, even when using the GNU linker. - (Bug reported by Neal Becker.) - - - Use DOS-standard CR-LF line endings in the scons.bat file. - (Bug reported by Gary Ruben.) - - - Doc changes: Eliminate description of deprecated "name" keyword - argument from Builder definition (reported by Gary Ruben). - - - Support using env.Append() on BUILDERS (and other dictionaries). - (Bug reported by Bj=F6rn Bylander.) - - - Setting the BUILDERS construction variable now properly clears - the previous Builder attributes from the construction Environment. - (Bug reported by Bj=F6rn Bylander.) - - - Fix adding a prefix to a file when the target isn't specified. - (Bug reported by Esa Ilari Vuokko.) - - - Clean up error messages from problems duplicating into read-only - BuildDir directories or into read-only files. - - - Add a CommandAction.strfunction() method, and add an "env" argument - to the FunctionAction.strfunction() method, so that all Action - objects have strfunction() methods, and the functions for building - and returning a string both take the same arguments. - - - Add support for new CacheDir() functionality to share derived files - between builds, with related options --cache-disable, --cache-force, - and --cache-show. - - - Change the default behavior when no targets are specified to build - everything in the current directory and below (like Make). This - can be disabled by specifying Default(None) in an SConscript. - - - Revamp SCons installation to fix a case-sensitive installation - on Win32 systems, and to add SCons-specific --standard-lib, - --standalone-lib, and --version-lib options for easier user - control of where the libraries get installed. - - - Fix the ability to directly import and use Platform and Tool modules - that have been implicitly imported into an Environment(). - - - Add support for allowing an embedding interface to annotate a node - when it's created. - - - Extend the SConscript() function to accept build_dir and duplicate - keyword arguments that function like a BuildDir() call. - - From Steve Leblanc: - - - Fix the output of -c -n when directories are involved, so it - matches -c. - - From Anthony Roach: - - - Use a different shared object suffix (.os) when using gcc so shared - and static objects can exist side-by-side in the same directory. - - - Allow the same object files on Win32 to be linked into either - shared or static libraries. - - - Cache implicit cache values when using --implicit-cache. - - - -RELEASE 0.10 - Thu, 16 Jan 2003 04:11:46 -0600 - - From Derrick 'dman' Hudson: - - - Support Repositories on other file systems by symlinking or - copying files when hard linking won't work. - - From Steven Knight: - - - Remove Python bytecode (*.pyc) files from the scons-local packages. - - - Have FunctionActions print a description of what they're doing - (a representation of the Python call). - - - Fix the Install() method so that, like other actions, it prints - what would have happened when the -n option is used. - - - Don't create duplicate source files in a BuildDir when the -n - option is used. - - - Refactor the Scanner interface to eliminate unnecessary Scanner - calls and make it easier to write efficient scanners. - - - Added a "recursive" flag to Scanner creation that specifies the - Scanner should be invoked recursively on dependency files returned - by the scanner. - - - Significant performance improvement from using a more efficient - check, throughout the code, for whether a Node has a Builder. - - - Fix specifying only the source file to MultiStepBuilders such as - the Program Builder. (Bug reported by Dean Bair.) - - - Fix an exception when building from a file with the same basename as - the subdirectory in which it lives. (Bug reported by Gerard Patel.) - - - Fix automatic deduction of a target file name when there are - multiple source files specified; the target is now deduced from just - the first source file in the list. - - - Documentation fixes: better initial explanation of SConscript files; - fix a misformatted "table" in the StaticObject explanation. - - From Steven Knight and Steve Leblanc: - - - Fix the -c option so it will remove symlinks. - - From Steve Leblanc: - - - Add a Clean() method to support removing user-specified targets - when using the -c option. - - - Add a development script for running SCons through PyChecker. - - - Clean up things found by PyChecker (mostly unnecessary imports). - - - Add a script to use HappyDoc to create HTML class documentation. - - From Lachlan O'Dea: - - - Make the Environment.get() method return None by default. - - From Anthony Roach: - - - Add SetJobs() and GetJobs() methods to allow configuration of the - number of default jobs (still overridden by -j). - - - Convert the .sconsign file format from ASCII to a pickled Python - data structure. - - - Error message cleanups: Made consistent the format of error - messages (now all start with "scons: ***") and warning messages (now - all start with "scons: warning:"). Caught more cases with the "Do - not know how to build" error message. - - - Added support for the MinGW tool chain. - - - Added a --debug=includes option. - - - -RELEASE 0.09 - Thu, 5 Dec 2002 04:48:25 -0600 - - From Chad Austin: - - - Add a Prepend() method to Environments, to append values to - the beginning of construction variables. - - From Matt Balvin: - - - Add long command-line support to the "lib" Tool (Microsoft library - archiver), too. - - From Charles Crain: - - - Allow $$ in a string to be passed through as $. - - - Support file names with odd characters in them. - - - Add support for construction variable substition on scanner - directories (in CPPPATH, F77PATH, LIBPATH, etc.). - - From Charles Crain and Steven Knight: - - - Add Repository() functionality, including the -Y option. - - From Steven Knight: - - - Fix auto-deduction of target names so that deduced targets end - up in the same subdirectory as the source. - - - Don't remove source files specified on the command line! - - - Suport the Intel Fortran Compiler (ifl.exe). - - - Supply an error message if there are no command-line or - Default() targets specified. - - - Fix the ASPPCOM values for the GNU assembler. - (Bug reported by Brett Polivka.) - - - Fix an exception thrown when a Default() directory was specified - when using the -U option. - - - Issue a warning when -c can't remove a target. - - - Eliminate unnecessary Scanner calls by checking for the - existence of a file before scanning it. (This adds a generic - hook to check an arbitrary condition before scanning.) - - - Add explicit messages to tell when we're "Reading SConscript files - ...," "done reading SConscript files," "Building targets," and - "done building targets." Add a -Q option to supress these. - - - Add separate $SHOBJPREFIX and $SHOBJSUFFIX construction variables - (by default, the same as $OBJPREFIX and $OBJSUFFIX). - - - Add Make-like error messages when asked to build a source file, - and before trying to build a file that doesn't have all its source - files (including when an invalid drive letter is used on WIN32). - - - Add an scons-local-{version} package (in both .tar.gz and .zip - flavors) to help people who want to ship SCons as a stand-alone - build tool in their software packages. - - - Prevent SCons from unlinking files in certain situations when - the -n option is used. - - - Change the name of Tool/lib.py to Tool/mslib.py. - - From Steven Knight and Anthony Roach: - - - Man page: document the fact that Builder calls return Node objects. - - From Steve LeBlanc: - - - Refactor option processing to use our own version of Greg Ward's - Optik module, modified to run under Python 1.5.2. - - - Add a ParseConfig() command to modify an environment based on - parsing output from a *-config command. - - From Jeff Petkau: - - - Fix interpretation of '#/../foo' on Win32 systems. - - From Anthony Roach: - - - Fixed use of command lines with spaces in their arguments, - and use of Nodes with spaces in their string representation. - - - Make access and modification times of files in a BuildDir match - the source file, even when hard linking isn't available. - - - Make -U be case insensitive on Win32 systems. - - - Issue a warning and continue when finding a corrupt .sconsign file. - - - Fix using an alias as a dependency of a target so that if one of the - alias' dependencies gets rebuilt, the resulting target will, too. - - - Fix differently ordered targets causing unnecessary rebuilds - on case insensitive systems. - - - Use os.system() to execute external commands whenever the "env" - utility is available, which is much faster than fork()/exec(), - and fixes the -j option on several platforms. - - - Fix use of -j with multiple targets. - - - Add an Options() object for friendlier accomodation of command- - line arguments. - - - Add support for Microsoft VC++ precompiled header (.pch) files, - debugger (.pdb) files, and resource (.rc) files. - - - Don't compute the $_CPPINCFLAGS, $_F77INCFLAGS, $_LIBFLAGS and - $_LIBDIRFLAGS variables each time a command is executed, define - them so they're computed only as needed. Add a new _concat - function to the Environment that allows people to define their - own similar variables. - - - Fix dependency scans when $LIBS is overridden. - - - Add EnsurePythonVersion() and EnsureSConsVersion() functions. - - - Fix the overly-verbose stack trace on ListBuilder build errors. - - - Add a SetContentSignatureType() function, allowing use of file - timestamps instead of MD5 signatures. - - - Make -U and Default('source') fail gracefully. - - - Allow the File() and Dir() methods to take a path-name string as - the starting directory, in addition to a Dir object. - - - Allow the command handler to be selected via the SPAWN, SHELL - and ESCAPE construction variables. - - - Allow construction variables to be overridden when a Builder - is called. - - From sam th: - - - Dynamically check for the existence of utilities with which to - initialize Environments by default. - - - -RELEASE 0.08 - Mon, 15 Jul 2002 12:08:51 -0500 - - From Charles Crain: - - - Fixed a bug with relative CPPPATH dirs when using BuildDir(). - (Bug reported by Bob Summerwill.) - - - Added a warnings framework and a --warn option to enable or - disable warnings. - - - Make the C scanner warn users if files referenced by #include - directives cannot be found and --warn=dependency is specified. - - - The BUILDERS construction variable should now be a dictionary - that maps builder names to actions. Existing uses of lists, - and the Builder name= keyword argument, generate warnings - about use of deprecated features. - - - Removed the "shared" keyword argument from the Object and - Library builders. - - - Added separated StaticObject, SharedObject, StaticLibrary and - SharedLibrary builders. Made Object and Library synonyms for - StaticObject and StaticLibrary, respectively. - - - Add LIBS and LIBPATH dependencies for shared libraries. - - - Removed support for the prefix, suffix and src_suffix arguments - to Builder() to be callable functions. - - - Fix handling file names with multiple dots. - - - Allow a build directory to be outside of the SConstruct tree. - - - Add a FindFile() function that searches for a file node with a - specified name. - - - Add $CPPFLAGS to the shared-object command lines for g++ and gcc. - - From Charles Crain and Steven Knight: - - - Add a "tools=" keyword argument to Environment instantiation, - and a separate Tools() method, for more flexible specification - of tool-specific environment changes. - - From Steven Knight: - - - Add a "platform=" keyword argument to Environment instantiation, - and a separate Platform() method, for more flexible specification - of platform-specific environment changes. - - - Updated README instructions and setup.py code to catch an - installation failure from not having distutils installed. - - - Add descriptions to the -H help text for -D, -u and -U so - people can tell them apart. - - - Remove the old feature of automatically splitting strings - of file names on white space. - - - Add a dependency Scanner for native Fortran "include" statements, - using a new "F77PATH" construction variable. - - - Fix C #include scanning to detect file names with characters like - '-' in them. - - - Add more specific version / build output to the -v option. - - - Add support for the GNU as, Microsoft masm, and nasm assemblers. - - - Allow the "target" argument to a Builder call to be omitted, in - which case the target(s) are deduced from the source file(s) and the - Builder's specified suffix. - - - Add a tar archive builder. - - - Add preliminary support for the OS/2 Platform, including the icc - and ilink Tools. - - From Jeff Petkau: - - - Fix --implicit-cache if the scanner returns an empty list. - - From Anthony Roach: - - - Add a "multi" keyword argument to Builder creation that specifies - it's okay to call the builder multiple times for a target. - - - Set a "multi" on Aliases so multiple calls will append to an Alias. - - - Fix emitter functions' use of path names when using BuildDir or - in subdirectories. - - - Fix --implicit-cache causing redundant rebuilds when the header - file list changed. - - - Fix --implicit-cache when a file has no implicit dependencies and - its source is generated. - - - Make the drive letters on Windows always be the same case, so that - changes in the case of drive letters don't cause a rebuild. - - - Fall back to importing the SCons.TimeStamp module if the SCons.MD5 - module can't be imported. - - - Fix interrupt handling to guarantee that a single interrupt will - halt SCons both when using -j and not. - - - Fix .sconsign signature storage so that output files of one build - can be safely used as input files to another build. - - - Added a --debug=time option to print SCons execution times. - - - Print an error message if a file can't be unlinked before being - built, rather than just silently terminating the build. - - - Add a SideEffect() method that can be used to tell the build - engine that a given file is created as a side effect of building - a target. A file can be specified as a side effect of more than - one build comand, in which case the commands will not be executed - simultaneously. - - - Significant performance gains from not using our own version of - the inefficient stock os.path.splitext() method, caching source - suffix computation, code cleanup in MultiStepBuilder.__call__(), - and replicating some logic in scons_subst(). - - - Add --implicit-deps-changed and --implicit-deps-unchanged options. - - - Add a GetLaunchDir() function. - - - Add a SetBuildSignatureType() function. - - From Zed Shaw: - - - Add an Append() method to Environments, to append values to - construction variables. - - - Change the name of Update() to Replace(). Keep Update() as a - deprecated synonym, at least for now. - - From Terrel Shumway: - - - Use a $PYTHON construction variable, initialized to sys.executable, - when using Python to build parts of the SCons packages. - - - Use sys.prefix, not sys.exec_prefix, to find pdb.py. - - - -RELEASE 0.07 - Thu, 2 May 2002 13:37:16 -0500 - - From Chad Austin: - - - Changes to build SCons packages on IRIX (and other *NIces). - - - Don't create a directory Node when a file already exists there, - and vice versa. - - - Add 'dirs' and 'names' keyword arguments to SConscript for - easier specification of subsidiary SConscript files. - - From Charles Crain: - - - Internal cleanup of environment passing to function Actions. - - - Builders can now take arbitrary keyword arguments to create - attributes to be passed to: command generator functions, - FunctionAction functions, Builder emitter functions (below), - and prefix/suffix generator functions (below). - - - Command generator functions can now return ANYTHING that can be - converted into an Action (a function, a string, a CommandGenerator - instance, even an ActionBase instance). - - - Actions now call get_contents() with the actual target and source - nodes used for the build. - - - A new DictCmdGenerator class replaces CompositeBuilder to support - more flexible Builder behavior internally. - - - Builders can now take an emitter= keyword argument. An emitter - is a function that takes target, source, and env argument, then - return a 2-tuple of (new sources, new targets). The emitter is - called when the Builder is __call__'ed, allowing a user to modify - source and target lists. - - - The prefix, suffix and src_suffix Builder arguments now take a - callable as well a string. The callable is passed the Environment - and any extra Builder keyword arguments and is expected to return - the appropriate prefix or suffix. - - - CommandActions can now be a string, a list of command + argument - strings, or a list of commands (strings or lists). - - - Added shared library support. The Object and Library Builders now - take a "shared=1" keyword argument to specify that a shared object - or shared library should be built. It is an error to try to build - static objects into a shared library or vice versa. - - - Win32 support for .def files has been added. Added the Win32-specific - construction variables $WIN32DEFPREFIX, $WIN32DEFSUFFIX, - $WIN32DLLPREFIX and $WIN32IMPLIBPREFIX. When building a .dll, - the new construction variable $WIN32_INSERT_DEF, controls whether - the appropriately-named .def file is inserted into the target - list (if not already present). A .lib file is always added to - a Library build if not present in the list of targets. - - - ListBuilder now passes all targets to the action, not just the first. - - - Fix so that -c now deletes generated yacc .h files. - - - Builder actions and emitter functions can now be initialized, through - construction variables, to things other than strings. - - - Make top-relative '#/dir' lookups work like '#dir'. - - - Fix for relative CPPPATH directories in subsidiary SConscript files - (broken in 0.06). - - - Add a for_signature argument to command generators, so that - generators that need to can return distinct values for the - command signature and for executing the command. - - From Alex Jacques: - - - Create a better scons.bat file from a py2bat.py script on the Python - mailing list two years ago (modeled after pl2bat.pl). - - From Steven Knight: - - - Fix so that -c -n does *not* remove the targets! - - - Man page: Add a hierarchical libraries + Program example. - - - Support long MSVC linker command lines through a builder action - that writes to a temporary file and uses the magic MSVC "link @file" - argument syntax if the line is longer than 2K characters. - - - Fix F77 command-line options on Win32 (use /Fo instead of -o). - - - Use the same action to build from .c (lower case) and .C (upper - case) files on case-insensitive systems like Win32. - - - Support building a PDF file directly from a TeX or LaTeX file - using pdftex or pdflatex. - - - Add a -x option to runtest.py to specify the script being tested. - A -X option indicates it's an executable, not a script to feed - to the Python interpreter. - - - Add a Split() function (identical to SCons.Util.argmunge()) for use - in the next release, when Builders will no longer automatically split - strings on white space. - - From Steve Leblanc: - - - Add the SConscriptChdir() method. - - From Anthony Roach: - - - Fix --debug=tree when used with directory targets. - - - Significant internal restructuring of Scanners and Taskmaster. - - - Added new --debug=dtree option. - - - Fixes for --profile option. - - - Performance improvement in construction variable substitution. - - - Implemented caching of content signatures, plus added --max-drift - option to control caching. - - - Implemented caching of dependency signatures, enabled by new - --implicit-cache option. - - - Added abspath construction variable modifier. - - - Added $SOURCE variable as a synonym for $SOURCES[0]. - - - Write out .sconsign files on error or interrupt so intermediate - build results are saved. - - - Change the -U option to -D. Make a new -U that builds just the - targets from the local SConscript file. - - - Fixed use of sys.path so Python modules can be imported from - the SConscript directory. - - - Fix for using Aliases with the -u, -U and -D options. - - - Fix so that Nodes can be passed to SConscript files. - - From Moshe Zadka: - - - Changes for official Debian packaging. - - - -RELEASE 0.06 - Thu, 28 Mar 2002 01:24:29 -0600 - - From Charles Crain: - - - Fix command generators to expand construction variables. - - - Make FunctionAction arguments be Nodes, not strings. - - From Stephen Kennedy: - - - Performance: Use a dictionary, not a list, for a Node's parents. - - From Steven Knight: - - - Add .zip files to the packages we build. - - - Man page: document LIBS, fix a typo, document ARGUMENTS. - - - Added RANLIB and RANLIBFLAGS construction variables. Only use them - in ARCOM if there's a "ranlib" program on the system. - - - Add a configurable CFILESUFFIX for the Builder of .l and .y files - into C files. - - - Add a CXXFile Builder that turns .ll and .yy files into .cc files - (configurable via a CXXFILESUFFIX construction variable). - - - Use the POSIX-standard lex -t flag, not the GNU-specific -o flag. - (Bug reported by Russell Christensen.) - - - Fixed an exception when CPPPATH or LIBPATH is a null string. - (Bug reported by Richard Kiss.) - - - Add a --profile=FILE option to make profiling SCons easier. - - - Modify the new DVI builder to create .dvi files from LaTeX (.ltx - and .latex) files. - - - Add support for Aliases (phony targets). - - - Add a WhereIs() method for searching for path names to executables. - - - Add PDF and PostScript document builders. - - - Add support for compiling Fortran programs from a variety of - suffixes (a la GNU Make): .f, .F, .for, .FOR, .fpp and .FPP - - - Support a CPPFLAGS variable on all default commands that use the - C preprocessor. - - From Steve Leblanc: - - - Add support for the -U option. - - - Allow CPPPATH, LIBPATH and LIBS to be specified as white-space - separated strings. - - - Add a document builder to create .dvi files from TeX (.tex) files. - - From Anthony Roach: - - - Fix: Construction variables with values of 0 were incorrectly - interpolated as ''. - - - Support env['VAR'] to fetch construction variable values. - - - Man page: document Precious(). - - - -RELEASE 0.05 - Thu, 21 Feb 2002 16:50:03 -0600 - - From Chad Austin: - - - Set PROGSUFFIX to .exe under Cygwin. - - From Charles Crain: - - - Allow a library to specified as a command-line source file, not just - in the LIBS construction variable. - - - Compensate for a bug in os.path.normpath() that returns '' for './' - on WIN32. - - - More performance optimizations: cache #include lines from files, - eliminate unnecessary calls. - - - If a prefix or suffix contains white space, treat the resulting - concatenation as separate arguments. - - - Fix irregularities in the way we fetch DevStudio information from - the Windows registry, and in our registry error handling. - - From Steven Knight: - - - Flush stdout after print so it intermixes correctly with stderr - when redirected. - - - Allow Scanners to return a list of strings, and document how to - write your own Scanners. - - - Look up implicit (scanned) dependencies relative to the directory - of file being scanned. - - - Make writing .sconsign files more robust by first trying to write - to a temp file that gets renamed. - - - Create all of the directories for a list of targets before trying - to build any of the targets. - - - WIN32 portability fixes in tests. - - - Allow the list of variables exported to an SConscript file to be - a UserList, too. - - - Document the overlooked LIBPATH construction variable. - (Bug reported by Eicke Godehardt.) - - - Fix so that Ignore() ignores indirect, implicit dependencies - (included files), not just direct dependencies. - - - Put the man page in the Debian distribution. - - - Run HTML docs through tidy to clean up the HTML (for Konqueror). - - - Add preliminary support for Unicode strings. - - - Efficiency: don't scan dependencies more than once during the - walk of a tree. - - - Fix the -c option so it doesn't stop removing targets if one doesn't - already exist. - (Bug reported by Paul Connell.) - - - Fix the --debug=pdb option when run on Windows NT. - (Bug reported by Paul Connell.) - - - Add support for the -q option. - - From Steve Leblanc: - - - Add support for the -u option. - - - Add .cc and .hh file suffixes to the C Scanner. - - From Anthony Roach: - - - Make the scons script return an error code on failures. - - - Add support for using code to generate a command to build a target. - - - -RELEASE 0.04 - Wed, 30 Jan 2002 11:09:42 -0600 - - From Charles Crain: - - - Significant performance improvements in the Node.FS and - Scanner subsystems. - - - Fix signatures of binary files on Win32 systems. - - - Allow LIBS and LIBPATH to be strings, not just arrays. - - - Print a traceback if a Python-function builder throws an exception. - - From Steven Knight: - - - Fix using a directory as a Default(), and allow Default() to - support white space in file names for strings in arrays. - - - Man page updates: corrected some mistakes, documented various - missing Environment methods, alphabetized the construction - variables and other functions, defined begin and end macros for - the example sections, regularized white space separation, fixed - the use of Export() in the Multiple Variants example. - - - Function action fixes: None is now a successful return value. - Exceptions are now reported. Document function actions. - - - Add 'Action' and 'Scanner' to the global keywords so SConscript - files can use them too. - - - Removed the Wrapper class between Nodes and Walkers. - - - Add examples using Library, LIBS, and LIBPATH. - - - The C Scanner now always returns a sorted list of dependencies - so order changes don't cause unnecessary rebuilds. - - - Strip $(-$) bracketed text from command lines. Use this to - surround $_INCDIRS and $_LIBDIRS so we don't rebuild in response - to changes to -I or -L options. - - - Add the Ignore() method to ignore dependencies. - - - Provide an error message when a nonexistent target is specified - on the command line. - - - Remove targets before building them, and add an Environment - Precious() method to override that. - - - Eliminate redundant calls to the same builder when the target is a - list of targets: Add a ListBuilder class that wraps Builders to - handle lists atomically. Extend the Task class to support building - and updating multiple targets in a single Task. Simplify the - interface between Task and Taskmaster. - - - Add a --debug=pdb option to re-run SCons under the Python debugger. - - - Only compute a build signature once for each node. - - - Changes to our sys.path[] manipulation to support installation into - an arbitrary --prefix value. - - From Steve Leblanc: - - - Add var=value command-line arguments. - - - -RELEASE 0.03 - Fri, 11 Jan 2002 01:09:30 -0600 - - From Charles Crain: - - - Performance improvements in the Node.FS and Sig.Calculator classes. - - - Add the InstallAs() method. - - - Execute commands through an external interpreter (sh, cmd.exe, or - command.com) to handle redirection metacharacters. - - - Allow the user to supply a command handler. - - From Steven Knight: - - - Search both /usr/lib and /usr/local/lib for scons directories by - adding them both to sys.path, with whichever is in sys.prefix first. - - - Fix interpreting strings of multiple white-space separated file names - as separate file names, allowing prefixes and suffixes to be appended - to each individually. - - - Refactor to move CompositeBuilder initialization logic from the - factory wrapper to the __init__() method, and allow a Builder to - have both an action and a src_builder (or array of them). - - - Refactor BuilderBase.__call__() to separate Node creation/lookup - from initialization of the Node's builder information. - - - Add a CFile Builder object that supports turning lex (.l) and - yacc (.y) files into .c files. - - - Document: variable interpretation attributes; how to propogate - the user's environment variables to executed commands; how to - build variants in multiple BuildDirs. - - - Collect String, Dict, and List type-checking in common utility - routines so we can accept User{String,Dict,List}s all over. - - - Put the Action factory and classes into their own module. - - - Use one CPlusPlusAction in the Object Builder's action dictionary, - instead of letting it create multiple identical instances. - - - Document the Install() and InstallAs() methods. - - From Steve Leblanc: - - - Require that a Builder be given a name argument, supplying a - useful error message when it isn't. - - From Anthony Roach: - - - Add a "duplicate" keyword argument to BuildDir() that can be set - to prevent linking/copying source files into build directories. - - - Add a "--debug=tree" option to print an ASCII dependency tree. - - - Fetch the location of the Microsoft Visual C++ compiler(s) from - the Registry, instead of hard-coding the location. - - - Made Scanner objects take Nodes, not path names. - - - Have the C Scanner cache the #include file names instead of - (re-)scanning the file each time it's called. - - - Created a separate class for parent "nodes" of file system roots, - eliminating the need for separate is-parent-null checks everywhere. - - - Removed defined __hash__() and __cmp() methods from FS.Entry, in - favor of Python's more efficient built-in identity comparisons. - - - -RELEASE 0.02 - Sun, 23 Dec 2001 19:05:09 -0600 - - From Charles Crain: - - - Added the Install(), BuildDir(), and Export() methods. - - - Fix the -C option by delaying setting the top of the FS tree. - - - Avoid putting the directory path on the libraries in the LIBS - construction variable. - - - Added a GetBuildPath() method to return the full path to the - Node for a specified string. - - - Fixed variable substitution in CPPPATH and LIBPATH. - - From Steven Knight: - - - Fixed the version comment in the scons.bat (the UNIX geek used - # instead of @rem). - - - Fix to setup.py so it doesn't require a sys.argv[1] argument. - - - Provide make-like warning message for "command not found" and - similar errors. - - - Added an EXAMPLES section to the man page. - - - Make Default() targets properly relative to their SConscript - file's subdirectory. - - From Anthony Roach: - - - Documented CXXFLAGS, CXXCOM, and CPPPATH. - - - Fixed SCONS_LIB_DIR to work as documented. - - - Made Default() accept Nodes as arguments. - - - Changed Export() to make it easier to use. - - - Added the Import() and Return() methods. - - - -RELEASE 0.01 - Thu Dec 13 19:25:23 CST 2001 - -A brief overview of important functionality available in release 0.01: - - - C and C++ compilation on POSIX and Windows NT. - - - Automatic scanning of C/C++ source files for #include dependencies. - - - Support for building libraries; setting construction variables - allows creation of shared libraries. - - - Library and C preprocessor search paths. - - - File changes detected using MD5 signatures. - - - User-definable Builder objects for building files. - - - User-definable Scanner objects for scanning for dependencies. - - - Parallel build (-j) support. - - - Dependency cycles detected. - - - Linux packages available in RPM and Debian format. - - - Windows installer available. - - - -Copyright (c) 2001 - 2015 The SCons Foundation -src/CHANGES.txt rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog diff --git a/3rdParty/SCons/scons-2.4.0/LICENSE.txt b/3rdParty/SCons/scons-2.4.0/LICENSE.txt deleted file mode 100644 index a0a96a0..0000000 --- a/3rdParty/SCons/scons-2.4.0/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2001 - 2015 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. diff --git a/3rdParty/SCons/scons-2.4.0/MANIFEST b/3rdParty/SCons/scons-2.4.0/MANIFEST deleted file mode 100644 index 9c6504f..0000000 --- a/3rdParty/SCons/scons-2.4.0/MANIFEST +++ /dev/null @@ -1,211 +0,0 @@ -CHANGES.txt -LICENSE.txt -MANIFEST -README.txt -RELEASE.txt -engine/SCons/Action.py -engine/SCons/Builder.py -engine/SCons/CacheDir.py -engine/SCons/Conftest.py -engine/SCons/Debug.py -engine/SCons/Defaults.py -engine/SCons/Environment.py -engine/SCons/Errors.py -engine/SCons/Executor.py -engine/SCons/Job.py -engine/SCons/Memoize.py -engine/SCons/Node/Alias.py -engine/SCons/Node/FS.py -engine/SCons/Node/Python.py -engine/SCons/Node/__init__.py -engine/SCons/Options/BoolOption.py -engine/SCons/Options/EnumOption.py -engine/SCons/Options/ListOption.py -engine/SCons/Options/PackageOption.py -engine/SCons/Options/PathOption.py -engine/SCons/Options/__init__.py -engine/SCons/PathList.py -engine/SCons/Platform/__init__.py -engine/SCons/Platform/aix.py -engine/SCons/Platform/cygwin.py -engine/SCons/Platform/darwin.py -engine/SCons/Platform/hpux.py -engine/SCons/Platform/irix.py -engine/SCons/Platform/os2.py -engine/SCons/Platform/posix.py -engine/SCons/Platform/sunos.py -engine/SCons/Platform/win32.py -engine/SCons/SConf.py -engine/SCons/SConsign.py -engine/SCons/Scanner/C.py -engine/SCons/Scanner/D.py -engine/SCons/Scanner/Dir.py -engine/SCons/Scanner/Fortran.py -engine/SCons/Scanner/IDL.py -engine/SCons/Scanner/LaTeX.py -engine/SCons/Scanner/Prog.py -engine/SCons/Scanner/RC.py -engine/SCons/Scanner/__init__.py -engine/SCons/Script/Interactive.py -engine/SCons/Script/Main.py -engine/SCons/Script/SConsOptions.py -engine/SCons/Script/SConscript.py -engine/SCons/Script/__init__.py -engine/SCons/Sig.py -engine/SCons/Subst.py -engine/SCons/Taskmaster.py -engine/SCons/Tool/386asm.py -engine/SCons/Tool/BitKeeper.py -engine/SCons/Tool/CVS.py -engine/SCons/Tool/DCommon.py -engine/SCons/Tool/FortranCommon.py -engine/SCons/Tool/GettextCommon.py -engine/SCons/Tool/JavaCommon.py -engine/SCons/Tool/MSCommon/__init__.py -engine/SCons/Tool/MSCommon/arch.py -engine/SCons/Tool/MSCommon/common.py -engine/SCons/Tool/MSCommon/netframework.py -engine/SCons/Tool/MSCommon/sdk.py -engine/SCons/Tool/MSCommon/vc.py -engine/SCons/Tool/MSCommon/vs.py -engine/SCons/Tool/Perforce.py -engine/SCons/Tool/PharLapCommon.py -engine/SCons/Tool/RCS.py -engine/SCons/Tool/SCCS.py -engine/SCons/Tool/Subversion.py -engine/SCons/Tool/__init__.py -engine/SCons/Tool/aixc++.py -engine/SCons/Tool/aixcc.py -engine/SCons/Tool/aixf77.py -engine/SCons/Tool/aixlink.py -engine/SCons/Tool/applelink.py -engine/SCons/Tool/ar.py -engine/SCons/Tool/as.py -engine/SCons/Tool/bcc32.py -engine/SCons/Tool/c++.py -engine/SCons/Tool/cc.py -engine/SCons/Tool/cvf.py -engine/SCons/Tool/cyglink.py -engine/SCons/Tool/default.py -engine/SCons/Tool/dmd.py -engine/SCons/Tool/docbook/__init__.py -engine/SCons/Tool/dvi.py -engine/SCons/Tool/dvipdf.py -engine/SCons/Tool/dvips.py -engine/SCons/Tool/f03.py -engine/SCons/Tool/f77.py -engine/SCons/Tool/f90.py -engine/SCons/Tool/f95.py -engine/SCons/Tool/filesystem.py -engine/SCons/Tool/fortran.py -engine/SCons/Tool/g++.py -engine/SCons/Tool/g77.py -engine/SCons/Tool/gas.py -engine/SCons/Tool/gcc.py -engine/SCons/Tool/gdc.py -engine/SCons/Tool/gettext.py -engine/SCons/Tool/gfortran.py -engine/SCons/Tool/gnulink.py -engine/SCons/Tool/gs.py -engine/SCons/Tool/hpc++.py -engine/SCons/Tool/hpcc.py -engine/SCons/Tool/hplink.py -engine/SCons/Tool/icc.py -engine/SCons/Tool/icl.py -engine/SCons/Tool/ifl.py -engine/SCons/Tool/ifort.py -engine/SCons/Tool/ilink.py -engine/SCons/Tool/ilink32.py -engine/SCons/Tool/install.py -engine/SCons/Tool/intelc.py -engine/SCons/Tool/ipkg.py -engine/SCons/Tool/jar.py -engine/SCons/Tool/javac.py -engine/SCons/Tool/javah.py -engine/SCons/Tool/latex.py -engine/SCons/Tool/ldc.py -engine/SCons/Tool/lex.py -engine/SCons/Tool/link.py -engine/SCons/Tool/linkloc.py -engine/SCons/Tool/m4.py -engine/SCons/Tool/masm.py -engine/SCons/Tool/midl.py -engine/SCons/Tool/mingw.py -engine/SCons/Tool/msgfmt.py -engine/SCons/Tool/msginit.py -engine/SCons/Tool/msgmerge.py -engine/SCons/Tool/mslib.py -engine/SCons/Tool/mslink.py -engine/SCons/Tool/mssdk.py -engine/SCons/Tool/msvc.py -engine/SCons/Tool/msvs.py -engine/SCons/Tool/mwcc.py -engine/SCons/Tool/mwld.py -engine/SCons/Tool/nasm.py -engine/SCons/Tool/packaging/__init__.py -engine/SCons/Tool/packaging/ipk.py -engine/SCons/Tool/packaging/msi.py -engine/SCons/Tool/packaging/rpm.py -engine/SCons/Tool/packaging/src_tarbz2.py -engine/SCons/Tool/packaging/src_targz.py -engine/SCons/Tool/packaging/src_zip.py -engine/SCons/Tool/packaging/tarbz2.py -engine/SCons/Tool/packaging/targz.py -engine/SCons/Tool/packaging/zip.py -engine/SCons/Tool/pdf.py -engine/SCons/Tool/pdflatex.py -engine/SCons/Tool/pdftex.py -engine/SCons/Tool/qt.py -engine/SCons/Tool/rmic.py -engine/SCons/Tool/rpcgen.py -engine/SCons/Tool/rpm.py -engine/SCons/Tool/rpmutils.py -engine/SCons/Tool/sgiar.py -engine/SCons/Tool/sgic++.py -engine/SCons/Tool/sgicc.py -engine/SCons/Tool/sgilink.py -engine/SCons/Tool/sunar.py -engine/SCons/Tool/sunc++.py -engine/SCons/Tool/suncc.py -engine/SCons/Tool/sunf77.py -engine/SCons/Tool/sunf90.py -engine/SCons/Tool/sunf95.py -engine/SCons/Tool/sunlink.py -engine/SCons/Tool/swig.py -engine/SCons/Tool/tar.py -engine/SCons/Tool/tex.py -engine/SCons/Tool/textfile.py -engine/SCons/Tool/tlib.py -engine/SCons/Tool/wix.py -engine/SCons/Tool/xgettext.py -engine/SCons/Tool/yacc.py -engine/SCons/Tool/zip.py -engine/SCons/Util.py -engine/SCons/Variables/BoolVariable.py -engine/SCons/Variables/EnumVariable.py -engine/SCons/Variables/ListVariable.py -engine/SCons/Variables/PackageVariable.py -engine/SCons/Variables/PathVariable.py -engine/SCons/Variables/__init__.py -engine/SCons/Warnings.py -engine/SCons/__init__.py -engine/SCons/compat/__init__.py -engine/SCons/compat/_scons_builtins.py -engine/SCons/compat/_scons_collections.py -engine/SCons/compat/_scons_dbm.py -engine/SCons/compat/_scons_hashlib.py -engine/SCons/compat/_scons_io.py -engine/SCons/compat/_scons_sets.py -engine/SCons/compat/_scons_subprocess.py -engine/SCons/cpp.py -engine/SCons/dblite.py -engine/SCons/exitfuncs.py -scons-time.1 -scons.1 -sconsign.1 -script/scons -script/scons-time -script/scons.bat -script/sconsign -setup.cfg -setup.py diff --git a/3rdParty/SCons/scons-2.4.0/PKG-INFO b/3rdParty/SCons/scons-2.4.0/PKG-INFO deleted file mode 100644 index 7a848af..0000000 --- a/3rdParty/SCons/scons-2.4.0/PKG-INFO +++ /dev/null @@ -1,13 +0,0 @@ -Metadata-Version: 1.0 -Name: scons -Version: 2.4.0 -Summary: Open Source next-generation build tool. -Home-page: http://www.scons.org/ -Author: Steven Knight -Author-email: knight@baldmt.com -License: UNKNOWN -Description: Open Source next-generation build tool. - Improved, cross-platform substitute for the classic Make - utility. In short, SCons is an easier, more reliable - and faster way to build software. -Platform: UNKNOWN diff --git a/3rdParty/SCons/scons-2.4.0/README.txt b/3rdParty/SCons/scons-2.4.0/README.txt deleted file mode 100644 index 7f4db66..0000000 --- a/3rdParty/SCons/scons-2.4.0/README.txt +++ /dev/null @@ -1,250 +0,0 @@ - - - SCons - a software construction tool - - Version 2.4.0 - - -This is SCons, a tool for building software (and other files). SCons is -implemented in Python, and its "configuration files" are actually Python -scripts, allowing you to use the full power of a real scripting language -to solve build problems. You do not, however, need to know Python to -use SCons effectively. - -See the RELEASE.txt file for notes about this specific release, -including known problems. See the CHANGES.txt file for a list of -changes since the previous release. - - -LATEST VERSION -============== - -Before going further, you can check that this package you have is -the latest version by checking the SCons download page at: - - http://www.scons.org/download.html - - -EXECUTION REQUIREMENTS -====================== - -Running SCons requires Python version 2.7.*. Currently it does not -run on the Python 3.x release. 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.) - -By default, SCons knows how to search for available programming tools -on various systems--see the SCons man page for details. You may, -of course, override the default SCons choices made by appropriate -configuration of Environment construction variables. - - -INSTALLATION REQUIREMENTS -========================= - -Nothing special. - - -INSTALLATION -============ - -Assuming your system satisfies the installation requirements in the -previous section, install SCons from this package simply by running the -provided Python-standard setup script as follows: - - # python setup.py install - -By default, the above command will do the following: - - -- Install the version-numbered "scons-2.4.0" and "sconsign-2.4.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. - - -- Install scripts named "scons" and "sconsign" scripts in the - default system script directory (/usr/bin or C:\Python*\Scripts, - for example). This can be disabled by specifying the - "--no-scons-script" option on the command line, which is useful - if you want to install and experiment with a new version 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.0" and - "sconsign-2.4.0" scripts by specifying the "--hardlink-scons" - or "--symlink-scons" options on the command line. - - -- Install "scons-2.4.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.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 installing the build - engine library. - - -- Install the troff-format man pages in an appropriate directory - on UNIX or Linux systems (/usr/share/man/man1 or /usr/man/man1, - for example). This can be disabled by specifying the - "--no-install-man" option on the command line. The man pages - can be installed on Windows systems by specifying the - "--install-man" option on the command line. - -Note that, by default, SCons does not install its build engine library -in the standard Python library directories. If you want to be able to -use the SCons library modules (the build engine) in other Python -scripts, specify the "--standard-lib" option on the command line, as -follows: - - # python setup.py install --standard-lib - -This will install the build engine in the standard Python library -directory (/usr/lib/python*/site-packages or -C:\Python*\Lib\site-packages). - -Alternatively, you can have SCons install its build engine library in a -hard-coded standalone library directory, instead of the default -version-numbered directory, by specifying the "--standalone-lib" option -on the command line, as follows: - - # python setup.py install --standalone-lib - -This is usually not recommended, however. - -Note that, to install SCons in any of the above system directories, -you should have system installation privileges (that is, "root" or -"Administrator") when running the setup.py script. If you don't have -system installation privileges, you can use the --prefix option to -specify an alternate installation location, such as your home directory: - - $ python setup.py install --prefix=$HOME - -This will install SCons in the appropriate locations relative to -$HOME--that is, the scons script itself $HOME/bin and the associated -library in $HOME/lib/scons, for example. - - -DOCUMENTATION -============= - -See the RELEASE.txt file for notes about this specific release, -including known problems. See the CHANGES.txt file for a list of -changes since the previous release. - -The scons.1 man page is included in this package, and contains a section -of small examples for getting started using SCons. - -Additional documentation for SCons is available at: - - http://www.scons.org/doc.html - - -LICENSING -========= - -SCons is distributed under the MIT license, a full copy of which is -available in the LICENSE.txt file. The MIT license is an approved Open -Source license, which means: - - This software is OSI Certified Open Source Software. OSI - Certified is a certification mark of the Open Source Initiative. - -More information about OSI certifications and Open Source software is -available at: - - http://www.opensource.org/ - - -REPORTING BUGS -============== - -Please report bugs by following the detailed instructions on our Bug -Submission page: - - http://scons.tigris.org/bug-submission.html - -You can also send mail to the SCons developers' mailing list: - - scons-dev@scons.org - -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. - - -MAILING LISTS -============= - -An active mailing list for users of SCons is available. You may send -questions or comments to the list at: - - scons-users@scons.org - -You may subscribe to the mailing list by sending email to: - - scons-users-join@scons.org - -There is also a low-volume mailing list available for announcements -about SCons. Subscribe by sending email to: - - announce-subscribe@scons.tigris.org - -There are other mailing lists available for SCons developers, for -notification of SCons code changes, and for notification of updated -bug reports and project documents. Please see our mailing lists page -for details. - - -DONATIONS -========= - -If you find SCons helpful, please consider making a donation (of cash, -software, or hardware) to support continued work on the project. -Information is available at: - - http://www.scons.org/donate.html - - -FOR MORE INFORMATION -==================== - -Check the SCons web site at: - - http://www.scons.org/ - - -AUTHOR INFO -=========== -SCons was originally written by Steven Knight, knight at baldmt dot com. -Since around 2010 it has been maintained by the SCons -development team, co-managed by Bill Deegan and Gary Oberbrunner, with -many contributors, including but not at all limited to: - -- Chad Austin -- Dirk Baechle -- Charles Crain -- William Deegan -- Steve Leblanc -- Rob Managan -- Greg Noel -- Gary Oberbrunner -- Anthony Roach -- Greg Spencer -- Tom Tanner -- Anatoly Techtonik -- Christoph Wiedemann -- Russel Winder - -\... and many others. - -Copyright (c) 2001 - 2015 The SCons Foundation diff --git a/3rdParty/SCons/scons-2.4.0/RELEASE.txt b/3rdParty/SCons/scons-2.4.0/RELEASE.txt deleted file mode 100644 index 88d176e..0000000 --- a/3rdParty/SCons/scons-2.4.0/RELEASE.txt +++ /dev/null @@ -1,48 +0,0 @@ - A new SCons release, 2.4.0, is now available - on the SCons download page: - - http://www.scons.org/download.php - - Here is a summary of the changes since 2.3.6: - - NEW FUNCTIONALITY - - - None - - DEPRECATED FUNCTIONALITY - - - None - - CHANGED/ENHANCED EXISTING FUNCTIONALITY - - - None - - FIXES - - - None - - IMPROVEMENTS - - - Switched several core classes to use "slots", to - reduce the overall memory consumption in large - projects (fixes #2180, #2178, #2198) - - Memoizer counting uses decorators now, instead of - the old metaclasses approach. - - PACKAGING - - - Added new amd64 windows 64 bit installer - - DOCUMENTATION - - - None - - DEVELOPMENT - - - None - - Thanks to Dirk Baechle, Andrew Featherstone for their contributions to this release. - Contributors are listed alphabetically by their last name. - -Copyright (c) 2001 - 2015 The SCons Foundation -src/RELEASE.txt rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Action.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Action.py deleted file mode 100644 index 7acde46..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Action.py +++ /dev/null @@ -1,1258 +0,0 @@ -"""SCons.Action - -This encapsulates information about executing any sort of action that -can build one or more target Nodes (typically files) from one or more -source Nodes (also typically files) given a specific Environment. - -The base class here is ActionBase. The base class supplies just a few -OO utility methods and some generic methods for displaying information -about an Action in response to the various commands that control printing. - -A second-level base class is _ActionAction. This extends ActionBase -by providing the methods that can be used to show and perform an -action. True Action objects will subclass _ActionAction; Action -factory class objects will subclass ActionBase. - -The heavy lifting is handled by subclasses for the different types of -actions we might execute: - - CommandAction - CommandGeneratorAction - FunctionAction - ListAction - -The subclasses supply the following public interface methods used by -other modules: - - __call__() - THE public interface, "calling" an Action object executes the - command or Python function. This also takes care of printing - a pre-substitution command for debugging purposes. - - get_contents() - Fetches the "contents" of an Action for signature calculation - plus the varlist. This is what gets MD5 checksummed to decide - if a target needs to be rebuilt because its action changed. - - genstring() - Returns a string representation of the Action *without* - command substitution, but allows a CommandGeneratorAction to - generate the right action based on the specified target, - source and env. This is used by the Signature subsystem - (through the Executor) to obtain an (imprecise) representation - of the Action operation for informative purposes. - - -Subclasses also supply the following methods for internal use within -this module: - - __str__() - Returns a string approximation of the Action; no variable - substitution is performed. - - execute() - The internal method that really, truly, actually handles the - execution of a command or Python function. This is used so - that the __call__() methods can take care of displaying any - pre-substitution representations, and *then* execute an action - without worrying about the specific Actions involved. - - get_presig() - Fetches the "contents" of a subclass for signature calculation. - The varlist is added to this to produce the Action's contents. - - strfunction() - Returns a substituted string representation of the Action. - This is used by the _ActionAction.show() command to display the - command/function that will be executed to generate the target(s). - -There is a related independent ActionCaller class that looks like a -regular Action, and which serves as a wrapper for arbitrary functions -that we want to let the user specify the arguments to now, but actually -execute later (when an out-of-date check determines that it's needed to -be executed, for example). Objects of this class are returned by an -ActionFactory class that provides a __call__() method as a convenient -way for wrapping up the functions. - -""" - -# Copyright (c) 2001 - 2015 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/Action.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import dis -import os -# compat layer imports "cPickle" for us if it's available. -import pickle -import re -import sys -import subprocess - -import SCons.Debug -from SCons.Debug import logInstanceCreation -import SCons.Errors -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 - -class _null(object): - pass - -print_actions = 1 -execute_actions = 1 -print_actions_presub = 0 - -def rfile(n): - try: - return n.rfile() - except AttributeError: - return n - -def default_exitstatfunc(s): - return s - -try: - SET_LINENO = dis.SET_LINENO - HAVE_ARGUMENT = dis.HAVE_ARGUMENT -except AttributeError: - remove_set_lineno_codes = lambda x: x -else: - def remove_set_lineno_codes(code): - result = [] - n = len(code) - i = 0 - while i < n: - c = code[i] - op = ord(c) - if op >= HAVE_ARGUMENT: - if op != SET_LINENO: - result.append(code[i:i+3]) - i = i+3 - else: - result.append(c) - i = i+1 - return ''.join(result) - -strip_quotes = re.compile('^[\'"](.*)[\'"]$') - - -def _callable_contents(obj): - """Return the signature contents of a callable Python object. - """ - try: - # Test if obj is a method. - return _function_contents(obj.im_func) - - except AttributeError: - try: - # Test if obj is a callable object. - return _function_contents(obj.__call__.im_func) - - except AttributeError: - try: - # Test if obj is a code object. - return _code_contents(obj) - - except AttributeError: - # Test if obj is a function object. - return _function_contents(obj) - - -def _object_contents(obj): - """Return the signature contents of any Python object. - - We have to handle the case where object contains a code object - since it can be pickled directly. - """ - try: - # Test if obj is a method. - return _function_contents(obj.im_func) - - except AttributeError: - try: - # Test if obj is a callable object. - return _function_contents(obj.__call__.im_func) - - except AttributeError: - try: - # Test if obj is a code object. - return _code_contents(obj) - - except AttributeError: - try: - # Test if obj is a function object. - return _function_contents(obj) - - except AttributeError: - # Should be a pickable Python object. - try: - return pickle.dumps(obj) - except (pickle.PicklingError, TypeError): - # This is weird, but it seems that nested classes - # are unpickable. The Python docs say it should - # always be a PicklingError, but some Python - # versions seem to return TypeError. Just do - # the best we can. - return str(obj) - - -def _code_contents(code): - """Return the signature contents of a code object. - - By providing direct access to the code object of the - function, Python makes this extremely easy. Hooray! - - Unfortunately, older versions of Python include line - number indications in the compiled byte code. Boo! - So we remove the line number byte codes to prevent - recompilations from moving a Python function. - """ - - contents = [] - - # The code contents depends on the number of local variables - # but not their actual names. - contents.append("%s,%s" % (code.co_argcount, len(code.co_varnames))) - try: - contents.append(",%s,%s" % (len(code.co_cellvars), len(code.co_freevars))) - except AttributeError: - # Older versions of Python do not support closures. - contents.append(",0,0") - - # The code contents depends on any constants accessed by the - # function. Note that we have to call _object_contents on each - # constants because the code object of nested functions can - # show-up among the constants. - # - # Note that we also always ignore the first entry of co_consts - # which contains the function doc string. We assume that the - # function does not access its doc string. - contents.append(',(' + ','.join(map(_object_contents,code.co_consts[1:])) + ')') - - # The code contents depends on the variable names used to - # accessed global variable, as changing the variable name changes - # the variable actually accessed and therefore changes the - # function result. - contents.append(',(' + ','.join(map(_object_contents,code.co_names)) + ')') - - - # The code contents depends on its actual code!!! - contents.append(',(' + str(remove_set_lineno_codes(code.co_code)) + ')') - - return ''.join(contents) - - -def _function_contents(func): - """Return the signature contents of a function.""" - - contents = [_code_contents(func.func_code)] - - # The function contents depends on the value of defaults arguments - if func.func_defaults: - contents.append(',(' + ','.join(map(_object_contents,func.func_defaults)) + ')') - else: - contents.append(',()') - - # The function contents depends on the closure captured cell values. - try: - closure = func.func_closure or [] - except AttributeError: - # Older versions of Python do not support closures. - closure = [] - - #xxx = [_object_contents(x.cell_contents) for x in closure] - try: - xxx = [_object_contents(x.cell_contents) for x in closure] - except AttributeError: - xxx = [] - contents.append(',(' + ','.join(xxx) + ')') - - return ''.join(contents) - - -def _actionAppend(act1, act2): - # This function knows how to slap two actions together. - # Mainly, it handles ListActions by concatenating into - # a single ListAction. - a1 = Action(act1) - a2 = Action(act2) - if a1 is None: - return a2 - if a2 is None: - return a1 - if isinstance(a1, ListAction): - if isinstance(a2, ListAction): - return ListAction(a1.list + a2.list) - else: - return ListAction(a1.list + [ a2 ]) - else: - if isinstance(a2, ListAction): - return ListAction([ a1 ] + a2.list) - else: - return ListAction([ a1, a2 ]) - -def _do_create_keywords(args, kw): - """This converts any arguments after the action argument into - their equivalent keywords and adds them to the kw argument. - """ - v = kw.get('varlist', ()) - # prevent varlist="FOO" from being interpreted as ['F', 'O', 'O'] - if is_String(v): v = (v,) - kw['varlist'] = tuple(v) - if args: - # turn positional args into equivalent keywords - cmdstrfunc = args[0] - if cmdstrfunc is None or is_String(cmdstrfunc): - kw['cmdstr'] = cmdstrfunc - elif callable(cmdstrfunc): - kw['strfunction'] = cmdstrfunc - else: - raise SCons.Errors.UserError( - 'Invalid command display variable type. ' - 'You must either pass a string or a callback which ' - 'accepts (target, source, env) as parameters.') - if len(args) > 1: - kw['varlist'] = tuple(SCons.Util.flatten(args[1:])) + kw['varlist'] - if kw.get('strfunction', _null) is not _null \ - and kw.get('cmdstr', _null) is not _null: - raise SCons.Errors.UserError( - 'Cannot have both strfunction and cmdstr args to Action()') - -def _do_create_action(act, kw): - """This is the actual "implementation" for the - Action factory method, below. This handles the - fact that passing lists to Action() itself has - different semantics than passing lists as elements - of lists. - - The former will create a ListAction, the latter - will create a CommandAction by converting the inner - list elements to strings.""" - - if isinstance(act, ActionBase): - return act - - if is_String(act): - var=SCons.Util.get_environment_var(act) - if var: - # This looks like a string that is purely an Environment - # variable reference, like "$FOO" or "${FOO}". We do - # something special here...we lazily evaluate the contents - # of that Environment variable, so a user could put something - # like a function or a CommandGenerator in that variable - # instead of a string. - return LazyAction(var, kw) - commands = str(act).split('\n') - if len(commands) == 1: - return CommandAction(commands[0], **kw) - # The list of string commands may include a LazyAction, so we - # reprocess them via _do_create_list_action. - return _do_create_list_action(commands, kw) - - if is_List(act): - return CommandAction(act, **kw) - - if callable(act): - try: - gen = kw['generator'] - del kw['generator'] - except KeyError: - gen = 0 - if gen: - action_type = CommandGeneratorAction - else: - action_type = FunctionAction - return action_type(act, kw) - - # Catch a common error case with a nice message: - if isinstance(act, int) or isinstance(act, float): - raise TypeError("Don't know how to create an Action from a number (%s)"%act) - # Else fail silently (???) - return None - -def _do_create_list_action(act, kw): - """A factory for list actions. Convert the input list into Actions - and then wrap them in a ListAction.""" - acts = [] - for a in act: - aa = _do_create_action(a, kw) - if aa is not None: acts.append(aa) - if not acts: - return ListAction([]) - elif len(acts) == 1: - return acts[0] - else: - return ListAction(acts) - -def Action(act, *args, **kw): - """A factory for action objects.""" - # Really simple: the _do_create_* routines do the heavy lifting. - _do_create_keywords(args, kw) - if is_List(act): - return _do_create_list_action(act, kw) - return _do_create_action(act, kw) - -class ActionBase(object): - """Base class for all types of action objects that can be held by - other objects (Builders, Executors, etc.) This provides the - common methods for manipulating and combining those actions.""" - - def __cmp__(self, other): - return cmp(self.__dict__, other) - - def no_batch_key(self, env, target, source): - return None - - batch_key = no_batch_key - - def genstring(self, target, source, env): - return str(self) - - def get_contents(self, target, source, env): - result = [ self.get_presig(target, source, env) ] - # This should never happen, as the Action() factory should wrap - # the varlist, but just in case an action is created directly, - # we duplicate this check here. - vl = self.get_varlist(target, source, env) - if is_String(vl): vl = (vl,) - for v in vl: - # do the subst this way to ignore $(...$) parts: - result.append(env.subst_target_source('${'+v+'}', SCons.Subst.SUBST_SIG, target, source)) - return ''.join(result) - - def __add__(self, other): - return _actionAppend(self, other) - - def __radd__(self, other): - return _actionAppend(other, self) - - def presub_lines(self, env): - # CommandGeneratorAction needs a real environment - # in order to return the proper string here, since - # it may call LazyAction, which looks up a key - # in that env. So we temporarily remember the env here, - # and CommandGeneratorAction will use this env - # when it calls its _generate method. - self.presub_env = env - lines = str(self).split('\n') - self.presub_env = None # don't need this any more - return lines - - def get_varlist(self, target, source, env, executor=None): - return self.varlist - - def get_targets(self, env, executor): - """ - Returns the type of targets ($TARGETS, $CHANGED_TARGETS) used - by this action. - """ - return self.targets - -class _ActionAction(ActionBase): - """Base class for actions that create output objects.""" - def __init__(self, cmdstr=_null, strfunction=_null, varlist=(), - presub=_null, chdir=None, exitstatfunc=None, - batch_key=None, targets='$TARGETS', - **kw): - self.cmdstr = cmdstr - if strfunction is not _null: - if strfunction is None: - self.cmdstr = None - else: - self.strfunction = strfunction - self.varlist = varlist - self.presub = presub - self.chdir = chdir - if not exitstatfunc: - exitstatfunc = default_exitstatfunc - self.exitstatfunc = exitstatfunc - - self.targets = targets - - if batch_key: - if not callable(batch_key): - # They have set batch_key, but not to their own - # callable. The default behavior here will batch - # *all* targets+sources using this action, separated - # for each construction environment. - def default_batch_key(self, env, target, source): - return (id(self), id(env)) - batch_key = default_batch_key - SCons.Util.AddMethod(self, batch_key, 'batch_key') - - def print_cmd_line(self, s, target, source, env): - # In python 3, and in some of our tests, sys.stdout is - # a String io object, and it takes unicode strings only - # In other cases it's a regular Python 2.x file object - # which takes strings (bytes), and if you pass those a - # unicode object they try to decode with 'ascii' codec - # which fails if the cmd line has any hi-bit-set chars. - # This code assumes s is a regular string, but should - # work if it's unicode too. - try: - sys.stdout.write(unicode(s + "\n")) - except UnicodeDecodeError: - sys.stdout.write(s + "\n") - - def __call__(self, target, source, env, - exitstatfunc=_null, - presub=_null, - show=_null, - execute=_null, - chdir=_null, - executor=None): - if not is_List(target): - target = [target] - if not is_List(source): - source = [source] - - if presub is _null: - presub = self.presub - if presub is _null: - presub = print_actions_presub - if exitstatfunc is _null: exitstatfunc = self.exitstatfunc - if show is _null: show = print_actions - if execute is _null: execute = execute_actions - if chdir is _null: chdir = self.chdir - save_cwd = None - if chdir: - save_cwd = os.getcwd() - try: - chdir = str(chdir.get_abspath()) - except AttributeError: - if not is_String(chdir): - if executor: - chdir = str(executor.batches[0].targets[0].dir) - else: - chdir = str(target[0].dir) - if presub: - if executor: - target = executor.get_all_targets() - source = executor.get_all_sources() - t = ' and '.join(map(str, target)) - l = '\n '.join(self.presub_lines(env)) - out = u"Building %s with action:\n %s\n" % (t, l) - sys.stdout.write(out) - cmd = None - if show and self.strfunction: - if executor: - target = executor.get_all_targets() - source = executor.get_all_sources() - try: - cmd = self.strfunction(target, source, env, executor) - except TypeError: - cmd = self.strfunction(target, source, env) - if cmd: - if chdir: - cmd = ('os.chdir(%s)\n' % repr(chdir)) + cmd - try: - get = env.get - except AttributeError: - print_func = self.print_cmd_line - else: - print_func = get('PRINT_CMD_LINE_FUNC') - if not print_func: - print_func = self.print_cmd_line - print_func(cmd, target, source, env) - stat = 0 - if execute: - if chdir: - os.chdir(chdir) - try: - stat = self.execute(target, source, env, executor=executor) - if isinstance(stat, SCons.Errors.BuildError): - s = exitstatfunc(stat.status) - if s: - stat.status = s - else: - stat = s - else: - stat = exitstatfunc(stat) - finally: - if save_cwd: - os.chdir(save_cwd) - if cmd and save_cwd: - print_func('os.chdir(%s)' % repr(save_cwd), target, source, env) - - return stat - - -def _string_from_cmd_list(cmd_list): - """Takes a list of command line arguments and returns a pretty - representation for printing.""" - cl = [] - for arg in map(str, cmd_list): - if ' ' in arg or '\t' in arg: - arg = '"' + arg + '"' - cl.append(arg) - return ' '.join(cl) - -# A fiddlin' little function that has an 'import SCons.Environment' which -# can't be moved to the top level without creating an import loop. Since -# this import creates a local variable named 'SCons', it blocks access to -# the global variable, so we move it here to prevent complaints about local -# variables being used uninitialized. -default_ENV = None -def get_default_ENV(env): - global default_ENV - try: - return env['ENV'] - except KeyError: - if not default_ENV: - import SCons.Environment - # This is a hideously expensive way to get a default shell - # environment. What it really should do is run the platform - # setup to get the default ENV. Fortunately, it's incredibly - # rare for an Environment not to have a shell environment, so - # we're not going to worry about it overmuch. - default_ENV = SCons.Environment.Environment()['ENV'] - return default_ENV - -# This function is still in draft mode. We're going to need something like -# it in the long run as more and more places use subprocess, but I'm sure -# it'll have to be tweaked to get the full desired functionality. -# one special arg (so far?), 'error', to tell what to do with exceptions. -def _subproc(scons_env, cmd, error = 'ignore', **kw): - """Do common setup for a subprocess.Popen() call""" - # allow std{in,out,err} to be "'devnull'" - io = kw.get('stdin') - if is_String(io) and io == 'devnull': - kw['stdin'] = open(os.devnull) - io = kw.get('stdout') - if is_String(io) and io == 'devnull': - kw['stdout'] = open(os.devnull, 'w') - io = kw.get('stderr') - if is_String(io) and io == 'devnull': - kw['stderr'] = open(os.devnull, 'w') - - # Figure out what shell environment to use - ENV = kw.get('env', None) - if ENV is None: ENV = get_default_ENV(scons_env) - - # Ensure that the ENV values are all strings: - new_env = {} - for key, value in ENV.items(): - if is_List(value): - # If the value is a list, then we assume it is a path list, - # because that's a pretty common list-like value to stick - # in an environment variable: - value = SCons.Util.flatten_sequence(value) - new_env[key] = os.pathsep.join(map(str, value)) - else: - # It's either a string or something else. If it's a string, - # we still want to call str() because it might be a *Unicode* - # string, which makes subprocess.Popen() gag. If it isn't a - # string or a list, then we just coerce it to a string, which - # is the proper way to handle Dir and File instances and will - # produce something reasonable for just about everything else: - new_env[key] = str(value) - kw['env'] = new_env - - try: - return subprocess.Popen(cmd, **kw) - except EnvironmentError, e: - if error == 'raise': raise - # return a dummy Popen instance that only returns error - class dummyPopen(object): - def __init__(self, e): self.exception = e - def communicate(self,input=None): return ('','') - def wait(self): return -self.exception.errno - stdin = None - class f(object): - def read(self): return '' - def readline(self): return '' - def __iter__(self): return iter(()) - stdout = stderr = f() - return dummyPopen(e) - -class CommandAction(_ActionAction): - """Class for command-execution actions.""" - def __init__(self, cmd, **kw): - # Cmd can actually be a list or a single item; if it's a - # single item it should be the command string to execute; if a - # list then it should be the words of the command string to - # execute. Only a single command should be executed by this - # object; lists of commands should be handled by embedding - # these objects in a ListAction object (which the Action() - # factory above does). cmd will be passed to - # Environment.subst_list() for substituting environment - # variables. - if SCons.Debug.track_instances: logInstanceCreation(self, 'Action.CommandAction') - - _ActionAction.__init__(self, **kw) - if is_List(cmd): - if list(filter(is_List, cmd)): - raise TypeError("CommandAction should be given only " \ - "a single command") - self.cmd_list = cmd - - def __str__(self): - if is_List(self.cmd_list): - return ' '.join(map(str, self.cmd_list)) - return str(self.cmd_list) - - def process(self, target, source, env, executor=None): - if executor: - result = env.subst_list(self.cmd_list, 0, executor=executor) - else: - result = env.subst_list(self.cmd_list, 0, target, source) - silent = None - ignore = None - while True: - try: c = result[0][0][0] - except IndexError: c = None - if c == '@': silent = 1 - elif c == '-': ignore = 1 - else: break - result[0][0] = result[0][0][1:] - try: - if not result[0][0]: - result[0] = result[0][1:] - except IndexError: - pass - return result, ignore, silent - - def strfunction(self, target, source, env, executor=None): - if self.cmdstr is None: - return None - if self.cmdstr is not _null: - from SCons.Subst import SUBST_RAW - if executor: - c = env.subst(self.cmdstr, SUBST_RAW, executor=executor) - else: - c = env.subst(self.cmdstr, SUBST_RAW, target, source) - if c: - return c - cmd_list, ignore, silent = self.process(target, source, env, executor) - if silent: - return '' - return _string_from_cmd_list(cmd_list[0]) - - def execute(self, target, source, env, executor=None): - """Execute a command action. - - This will handle lists of commands as well as individual commands, - because construction variable substitution may turn a single - "command" into a list. This means that this class can actually - handle lists of commands, even though that's not how we use it - externally. - """ - escape_list = SCons.Subst.escape_list - flatten_sequence = SCons.Util.flatten_sequence - - try: - shell = env['SHELL'] - except KeyError: - raise SCons.Errors.UserError('Missing SHELL construction variable.') - - try: - spawn = env['SPAWN'] - except KeyError: - raise SCons.Errors.UserError('Missing SPAWN construction variable.') - else: - if is_String(spawn): - spawn = env.subst(spawn, raw=1, conv=lambda x: x) - - escape = env.get('ESCAPE', lambda x: x) - - ENV = get_default_ENV(env) - - # Ensure that the ENV values are all strings: - for key, value in ENV.items(): - if not is_String(value): - if is_List(value): - # If the value is a list, then we assume it is a - # path list, because that's a pretty common list-like - # value to stick in an environment variable: - value = flatten_sequence(value) - ENV[key] = os.pathsep.join(map(str, value)) - else: - # If it isn't a string or a list, then we just coerce - # it to a string, which is the proper way to handle - # Dir and File instances and will produce something - # reasonable for just about everything else: - ENV[key] = str(value) - - if executor: - target = executor.get_all_targets() - source = executor.get_all_sources() - cmd_list, ignore, silent = self.process(target, list(map(rfile, source)), env, executor) - - # Use len() to filter out any "command" that's zero-length. - for cmd_line in filter(len, cmd_list): - # Escape the command line for the interpreter we are using. - cmd_line = escape_list(cmd_line, escape) - result = spawn(shell, escape, cmd_line[0], cmd_line, ENV) - if not ignore and result: - msg = "Error %s" % result - return SCons.Errors.BuildError(errstr=msg, - status=result, - action=self, - command=cmd_line) - return 0 - - def get_presig(self, target, source, env, executor=None): - """Return the signature contents of this action's command line. - - This strips $(-$) and everything in between the string, - since those parts don't affect signatures. - """ - from SCons.Subst import SUBST_SIG - cmd = self.cmd_list - if is_List(cmd): - cmd = ' '.join(map(str, cmd)) - else: - cmd = str(cmd) - if executor: - return env.subst_target_source(cmd, SUBST_SIG, executor=executor) - else: - return env.subst_target_source(cmd, SUBST_SIG, target, source) - - def get_implicit_deps(self, target, source, env, executor=None): - icd = env.get('IMPLICIT_COMMAND_DEPENDENCIES', True) - if is_String(icd) and icd[:1] == '$': - icd = env.subst(icd) - if not icd or icd in ('0', 'None'): - return [] - from SCons.Subst import SUBST_SIG - if executor: - cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, executor=executor) - else: - cmd_list = env.subst_list(self.cmd_list, SUBST_SIG, target, source) - res = [] - for cmd_line in cmd_list: - if cmd_line: - d = str(cmd_line[0]) - m = strip_quotes.match(d) - if m: - d = m.group(1) - d = env.WhereIs(d) - if d: - res.append(env.fs.File(d)) - return res - -class CommandGeneratorAction(ActionBase): - """Class for command-generator actions.""" - def __init__(self, generator, kw): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Action.CommandGeneratorAction') - self.generator = generator - self.gen_kw = kw - self.varlist = kw.get('varlist', ()) - self.targets = kw.get('targets', '$TARGETS') - - def _generate(self, target, source, env, for_signature, executor=None): - # ensure that target is a list, to make it easier to write - # generator functions: - if not is_List(target): - target = [target] - - if executor: - target = executor.get_all_targets() - source = executor.get_all_sources() - ret = self.generator(target=target, - source=source, - env=env, - for_signature=for_signature) - gen_cmd = Action(ret, **self.gen_kw) - if not gen_cmd: - raise SCons.Errors.UserError("Object returned from command generator: %s cannot be used to create an Action." % repr(ret)) - return gen_cmd - - def __str__(self): - try: - env = self.presub_env - except AttributeError: - env = None - if env is None: - env = SCons.Defaults.DefaultEnvironment() - act = self._generate([], [], env, 1) - return str(act) - - def batch_key(self, env, target, source): - return self._generate(target, source, env, 1).batch_key(env, target, source) - - def genstring(self, target, source, env, executor=None): - return self._generate(target, source, env, 1, executor).genstring(target, source, env) - - def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, - show=_null, execute=_null, chdir=_null, executor=None): - act = self._generate(target, source, env, 0, executor) - if act is None: - raise SCons.Errors.UserError("While building `%s': " - "Cannot deduce file extension from source files: %s" - % (repr(list(map(str, target))), repr(list(map(str, source))))) - return act(target, source, env, exitstatfunc, presub, - show, execute, chdir, executor) - - def get_presig(self, target, source, env, executor=None): - """Return the signature contents of this action's command line. - - This strips $(-$) and everything in between the string, - since those parts don't affect signatures. - """ - return self._generate(target, source, env, 1, executor).get_presig(target, source, env) - - def get_implicit_deps(self, target, source, env, executor=None): - return self._generate(target, source, env, 1, executor).get_implicit_deps(target, source, env) - - def get_varlist(self, target, source, env, executor=None): - return self._generate(target, source, env, 1, executor).get_varlist(target, source, env, executor) - - def get_targets(self, env, executor): - return self._generate(None, None, env, 1, executor).get_targets(env, executor) - - - -# A LazyAction is a kind of hybrid generator and command action for -# strings of the form "$VAR". These strings normally expand to other -# strings (think "$CCCOM" to "$CC -c -o $TARGET $SOURCE"), but we also -# want to be able to replace them with functions in the construction -# environment. Consequently, we want lazy evaluation and creation of -# an Action in the case of the function, but that's overkill in the more -# normal case of expansion to other strings. -# -# So we do this with a subclass that's both a generator *and* -# a command action. The overridden methods all do a quick check -# of the construction variable, and if it's a string we just call -# the corresponding CommandAction method to do the heavy lifting. -# If not, then we call the same-named CommandGeneratorAction method. -# The CommandGeneratorAction methods work by using the overridden -# _generate() method, that is, our own way of handling "generation" of -# an action based on what's in the construction variable. - -class LazyAction(CommandGeneratorAction, CommandAction): - - def __init__(self, var, kw): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Action.LazyAction') - #FUTURE CommandAction.__init__(self, '${'+var+'}', **kw) - CommandAction.__init__(self, '${'+var+'}', **kw) - self.var = SCons.Util.to_String(var) - self.gen_kw = kw - - def get_parent_class(self, env): - c = env.get(self.var) - if is_String(c) and not '\n' in c: - return CommandAction - return CommandGeneratorAction - - def _generate_cache(self, env): - if env: - c = env.get(self.var, '') - else: - c = '' - gen_cmd = Action(c, **self.gen_kw) - if not gen_cmd: - raise SCons.Errors.UserError("$%s value %s cannot be used to create an Action." % (self.var, repr(c))) - return gen_cmd - - def _generate(self, target, source, env, for_signature, executor=None): - return self._generate_cache(env) - - def __call__(self, target, source, env, *args, **kw): - c = self.get_parent_class(env) - return c.__call__(self, target, source, env, *args, **kw) - - def get_presig(self, target, source, env): - c = self.get_parent_class(env) - return c.get_presig(self, target, source, env) - - def get_varlist(self, target, source, env, executor=None): - c = self.get_parent_class(env) - return c.get_varlist(self, target, source, env, executor) - - -class FunctionAction(_ActionAction): - """Class for Python function actions.""" - - def __init__(self, execfunction, kw): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Action.FunctionAction') - - self.execfunction = execfunction - try: - self.funccontents = _callable_contents(execfunction) - except AttributeError: - try: - # See if execfunction will do the heavy lifting for us. - self.gc = execfunction.get_contents - except AttributeError: - # This is weird, just do the best we can. - self.funccontents = _object_contents(execfunction) - - _ActionAction.__init__(self, **kw) - - def function_name(self): - try: - return self.execfunction.__name__ - except AttributeError: - try: - return self.execfunction.__class__.__name__ - except AttributeError: - return "unknown_python_function" - - def strfunction(self, target, source, env, executor=None): - if self.cmdstr is None: - return None - if self.cmdstr is not _null: - from SCons.Subst import SUBST_RAW - if executor: - c = env.subst(self.cmdstr, SUBST_RAW, executor=executor) - else: - c = env.subst(self.cmdstr, SUBST_RAW, target, source) - if c: - return c - def array(a): - def quote(s): - try: - str_for_display = s.str_for_display - except AttributeError: - s = repr(s) - else: - s = str_for_display() - return s - return '[' + ", ".join(map(quote, a)) + ']' - try: - strfunc = self.execfunction.strfunction - except AttributeError: - pass - else: - if strfunc is None: - return None - if callable(strfunc): - return strfunc(target, source, env) - name = self.function_name() - tstr = array(target) - sstr = array(source) - return "%s(%s, %s)" % (name, tstr, sstr) - - def __str__(self): - name = self.function_name() - if name == 'ActionCaller': - return str(self.execfunction) - return "%s(target, source, env)" % name - - def execute(self, target, source, env, executor=None): - exc_info = (None,None,None) - try: - if executor: - target = executor.get_all_targets() - source = executor.get_all_sources() - rsources = list(map(rfile, source)) - try: - result = self.execfunction(target=target, source=rsources, env=env) - except KeyboardInterrupt, e: - raise - except SystemExit, e: - raise - except Exception, e: - result = e - exc_info = sys.exc_info() - - if result: - result = SCons.Errors.convert_to_BuildError(result, exc_info) - result.node=target - result.action=self - try: - result.command=self.strfunction(target, source, env, executor) - except TypeError: - result.command=self.strfunction(target, source, env) - - # FIXME: This maintains backward compatibility with respect to - # which type of exceptions were returned by raising an - # exception and which ones were returned by value. It would - # probably be best to always return them by value here, but - # some codes do not check the return value of Actions and I do - # not have the time to modify them at this point. - if (exc_info[1] and - not isinstance(exc_info[1],EnvironmentError)): - raise result - - return result - finally: - # Break the cycle between the traceback object and this - # function stack frame. See the sys.exc_info() doc info for - # more information about this issue. - del exc_info - - - def get_presig(self, target, source, env): - """Return the signature contents of this callable action.""" - try: - return self.gc(target, source, env) - except AttributeError: - return self.funccontents - - def get_implicit_deps(self, target, source, env): - return [] - -class ListAction(ActionBase): - """Class for lists of other actions.""" - def __init__(self, actionlist): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Action.ListAction') - def list_of_actions(x): - if isinstance(x, ActionBase): - return x - return Action(x) - self.list = list(map(list_of_actions, actionlist)) - # our children will have had any varlist - # applied; we don't need to do it again - self.varlist = () - self.targets = '$TARGETS' - - def genstring(self, target, source, env): - return '\n'.join([a.genstring(target, source, env) for a in self.list]) - - def __str__(self): - return '\n'.join(map(str, self.list)) - - def presub_lines(self, env): - return SCons.Util.flatten_sequence( - [a.presub_lines(env) for a in self.list]) - - def get_presig(self, target, source, env): - """Return the signature contents of this action list. - - Simple concatenation of the signatures of the elements. - """ - return "".join([x.get_contents(target, source, env) for x in self.list]) - - def __call__(self, target, source, env, exitstatfunc=_null, presub=_null, - show=_null, execute=_null, chdir=_null, executor=None): - if executor: - target = executor.get_all_targets() - source = executor.get_all_sources() - for act in self.list: - stat = act(target, source, env, exitstatfunc, presub, - show, execute, chdir, executor) - if stat: - return stat - return 0 - - def get_implicit_deps(self, target, source, env): - result = [] - for act in self.list: - result.extend(act.get_implicit_deps(target, source, env)) - return result - - def get_varlist(self, target, source, env, executor=None): - result = SCons.Util.OrderedDict() - for act in self.list: - for var in act.get_varlist(target, source, env, executor): - result[var] = True - return list(result.keys()) - -class ActionCaller(object): - """A class for delaying calling an Action function with specific - (positional and keyword) arguments until the Action is actually - executed. - - This class looks to the rest of the world like a normal Action object, - but what it's really doing is hanging on to the arguments until we - have a target, source and env to use for the expansion. - """ - def __init__(self, parent, args, kw): - self.parent = parent - self.args = args - self.kw = kw - - def get_contents(self, target, source, env): - actfunc = self.parent.actfunc - try: - # "self.actfunc" is a function. - contents = str(actfunc.func_code.co_code) - except AttributeError: - # "self.actfunc" is a callable object. - try: - contents = str(actfunc.__call__.im_func.func_code.co_code) - except AttributeError: - # No __call__() method, so it might be a builtin - # or something like that. Do the best we can. - contents = str(actfunc) - contents = remove_set_lineno_codes(contents) - return contents - - def subst(self, s, target, source, env): - # If s is a list, recursively apply subst() - # to every element in the list - if is_List(s): - result = [] - for elem in s: - result.append(self.subst(elem, target, source, env)) - return self.parent.convert(result) - - # Special-case hack: Let a custom function wrapped in an - # ActionCaller get at the environment through which the action - # was called by using this hard-coded value as a special return. - if s == '$__env__': - return env - elif is_String(s): - return env.subst(s, 1, target, source) - return self.parent.convert(s) - - def subst_args(self, target, source, env): - return [self.subst(x, target, source, env) for x in self.args] - - def subst_kw(self, target, source, env): - kw = {} - for key in self.kw.keys(): - kw[key] = self.subst(self.kw[key], target, source, env) - return kw - - def __call__(self, target, source, env, executor=None): - args = self.subst_args(target, source, env) - kw = self.subst_kw(target, source, env) - return self.parent.actfunc(*args, **kw) - - def strfunction(self, target, source, env): - args = self.subst_args(target, source, env) - kw = self.subst_kw(target, source, env) - return self.parent.strfunc(*args, **kw) - - def __str__(self): - return self.parent.strfunc(*self.args, **self.kw) - -class ActionFactory(object): - """A factory class that will wrap up an arbitrary function - as an SCons-executable Action object. - - The real heavy lifting here is done by the ActionCaller class. - We just collect the (positional and keyword) arguments that we're - called with and give them to the ActionCaller object we create, - so it can hang onto them until it needs them. - """ - def __init__(self, actfunc, strfunc, convert=lambda x: x): - self.actfunc = actfunc - self.strfunc = strfunc - self.convert = convert - - def __call__(self, *args, **kw): - ac = ActionCaller(self, args, kw) - action = Action(ac, strfunction=ac.strfunction) - return action - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Builder.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Builder.py deleted file mode 100644 index 4c68d5c..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Builder.py +++ /dev/null @@ -1,869 +0,0 @@ -"""SCons.Builder - -Builder object subsystem. - -A Builder object is a callable that encapsulates information about how -to execute actions to create a target Node (file) from source Nodes -(files), and how to create those dependencies for tracking. - -The main entry point here is the Builder() factory method. This provides -a procedural interface that creates the right underlying Builder object -based on the keyword arguments supplied and the types of the arguments. - -The goal is for this external interface to be simple enough that the -vast majority of users can create new Builders as necessary to support -building new types of files in their configurations, without having to -dive any deeper into this subsystem. - -The base class here is BuilderBase. This is a concrete base class which -does, in fact, represent the Builder objects that we (or users) create. - -There is also a proxy that looks like a Builder: - - CompositeBuilder - - This proxies for a Builder with an action that is actually a - dictionary that knows how to map file suffixes to a specific - action. This is so that we can invoke different actions - (compilers, compile options) for different flavors of source - files. - -Builders and their proxies have the following public interface methods -used by other modules: - - __call__() - THE public interface. Calling a Builder object (with the - use of internal helper methods) sets up the target and source - dependencies, appropriate mapping to a specific action, and the - environment manipulation necessary for overridden construction - variable. This also takes care of warning about possible mistakes - in keyword arguments. - - add_emitter() - Adds an emitter for a specific file suffix, used by some Tool - modules to specify that (for example) a yacc invocation on a .y - can create a .h *and* a .c file. - - add_action() - Adds an action for a specific file suffix, heavily used by - Tool modules to add their specific action(s) for turning - a source file into an object file to the global static - and shared object file Builders. - -There are the following methods for internal use within this module: - - _execute() - The internal method that handles the heavily lifting when a - Builder is called. This is used so that the __call__() methods - can set up warning about possible mistakes in keyword-argument - overrides, and *then* execute all of the steps necessary so that - the warnings only occur once. - - get_name() - Returns the Builder's name within a specific Environment, - primarily used to try to return helpful information in error - messages. - - adjust_suffix() - get_prefix() - get_suffix() - get_src_suffix() - set_src_suffix() - Miscellaneous stuff for handling the prefix and suffix - manipulation we use in turning source file names into target - file names. - -""" - -# -# Copyright (c) 2001 - 2015 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/Builder.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import collections - -import SCons.Action -import SCons.Debug -from SCons.Debug import logInstanceCreation -from SCons.Errors import InternalError, UserError -import SCons.Executor -import SCons.Memoize -import SCons.Util -import SCons.Warnings - -class _Null(object): - pass - -_null = _Null - -def match_splitext(path, suffixes = []): - if suffixes: - matchsuf = [S for S in suffixes if path[-len(S):] == S] - if matchsuf: - suf = max([(len(_f),_f) for _f in matchsuf])[1] - return [path[:-len(suf)], path[-len(suf):]] - return SCons.Util.splitext(path) - -class DictCmdGenerator(SCons.Util.Selector): - """This is a callable class that can be used as a - command generator function. It holds on to a dictionary - mapping file suffixes to Actions. It uses that dictionary - to return the proper action based on the file suffix of - the source file.""" - - def __init__(self, dict=None, source_ext_match=1): - SCons.Util.Selector.__init__(self, dict) - self.source_ext_match = source_ext_match - - def src_suffixes(self): - return list(self.keys()) - - def add_action(self, suffix, action): - """Add a suffix-action pair to the mapping. - """ - self[suffix] = action - - def __call__(self, target, source, env, for_signature): - if not source: - return [] - - if self.source_ext_match: - suffixes = self.src_suffixes() - ext = None - for src in map(str, source): - my_ext = match_splitext(src, suffixes)[1] - if ext and my_ext != ext: - raise UserError("While building `%s' from `%s': Cannot build multiple sources with different extensions: %s, %s" - % (repr(list(map(str, target))), src, ext, my_ext)) - ext = my_ext - else: - ext = match_splitext(str(source[0]), self.src_suffixes())[1] - - if not ext: - #return ext - raise UserError("While building `%s': " - "Cannot deduce file extension from source files: %s" - % (repr(list(map(str, target))), repr(list(map(str, source))))) - - try: - ret = SCons.Util.Selector.__call__(self, env, source, ext) - except KeyError, e: - raise UserError("Ambiguous suffixes after environment substitution: %s == %s == %s" % (e.args[0], e.args[1], e.args[2])) - if ret is None: - raise UserError("While building `%s' from `%s': Don't know how to build from a source file with suffix `%s'. Expected a suffix in this list: %s." % \ - (repr(list(map(str, target))), repr(list(map(str, source))), ext, repr(list(self.keys())))) - return ret - -class CallableSelector(SCons.Util.Selector): - """A callable dictionary that will, in turn, call the value it - finds if it can.""" - def __call__(self, env, source): - value = SCons.Util.Selector.__call__(self, env, source) - if callable(value): - value = value(env, source) - return value - -class DictEmitter(SCons.Util.Selector): - """A callable dictionary that maps file suffixes to emitters. - When called, it finds the right emitter in its dictionary for the - suffix of the first source file, and calls that emitter to get the - right lists of targets and sources to return. If there's no emitter - for the suffix in its dictionary, the original target and source are - returned. - """ - def __call__(self, target, source, env): - emitter = SCons.Util.Selector.__call__(self, env, source) - if emitter: - target, source = emitter(target, source, env) - return (target, source) - -class ListEmitter(collections.UserList): - """A callable list of emitters that calls each in sequence, - returning the result. - """ - def __call__(self, target, source, env): - for e in self.data: - target, source = e(target, source, env) - return (target, source) - -# These are a common errors when calling a Builder; -# they are similar to the 'target' and 'source' keyword args to builders, -# so we issue warnings when we see them. The warnings can, of course, -# be disabled. -misleading_keywords = { - 'targets' : 'target', - 'sources' : 'source', -} - -class OverrideWarner(collections.UserDict): - """A class for warning about keyword arguments that we use as - overrides in a Builder call. - - This class exists to handle the fact that a single Builder call - can actually invoke multiple builders. This class only emits the - warnings once, no matter how many Builders are invoked. - """ - def __init__(self, dict): - collections.UserDict.__init__(self, dict) - if SCons.Debug.track_instances: logInstanceCreation(self, 'Builder.OverrideWarner') - self.already_warned = None - def warn(self): - if self.already_warned: - return - for k in self.keys(): - if k in misleading_keywords: - alt = misleading_keywords[k] - msg = "Did you mean to use `%s' instead of `%s'?" % (alt, k) - SCons.Warnings.warn(SCons.Warnings.MisleadingKeywordsWarning, msg) - self.already_warned = 1 - -def Builder(**kw): - """A factory for builder objects.""" - composite = None - if 'generator' in kw: - if 'action' in kw: - raise UserError("You must not specify both an action and a generator.") - kw['action'] = SCons.Action.CommandGeneratorAction(kw['generator'], {}) - del kw['generator'] - elif 'action' in kw: - source_ext_match = kw.get('source_ext_match', 1) - if 'source_ext_match' in kw: - del kw['source_ext_match'] - if SCons.Util.is_Dict(kw['action']): - composite = DictCmdGenerator(kw['action'], source_ext_match) - kw['action'] = SCons.Action.CommandGeneratorAction(composite, {}) - kw['src_suffix'] = composite.src_suffixes() - else: - kw['action'] = SCons.Action.Action(kw['action']) - - if 'emitter' in kw: - emitter = kw['emitter'] - if SCons.Util.is_String(emitter): - # This allows users to pass in an Environment - # variable reference (like "$FOO") as an emitter. - # We will look in that Environment variable for - # a callable to use as the actual emitter. - var = SCons.Util.get_environment_var(emitter) - if not var: - raise UserError("Supplied emitter '%s' does not appear to refer to an Environment variable" % emitter) - kw['emitter'] = EmitterProxy(var) - elif SCons.Util.is_Dict(emitter): - kw['emitter'] = DictEmitter(emitter) - elif SCons.Util.is_List(emitter): - kw['emitter'] = ListEmitter(emitter) - - result = BuilderBase(**kw) - - if not composite is None: - result = CompositeBuilder(result, composite) - - return result - -def _node_errors(builder, env, tlist, slist): - """Validate that the lists of target and source nodes are - legal for this builder and environment. Raise errors or - issue warnings as appropriate. - """ - - # First, figure out if there are any errors in the way the targets - # were specified. - for t in tlist: - 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: - action = t.builder.action - t_contents = action.get_contents(tlist, slist, t.env) - contents = action.get_contents(tlist, slist, env) - - if t_contents == contents: - 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" % t - raise UserError(msg) - if builder.multi: - if t.builder != builder: - msg = "Two different builders (%s and %s) were specified for the same target: %s" % (t.builder.get_name(env), builder.get_name(env), t) - raise UserError(msg) - # TODO(batch): list constructed each time! - if t.get_executor().get_all_targets() != tlist: - msg = "Two different target lists have a target in common: %s (from %s and from %s)" % (t, list(map(str, t.get_executor().get_all_targets())), list(map(str, tlist))) - raise UserError(msg) - elif t.sources != slist: - msg = "Multiple ways to build the same target were specified for: %s (from %s and from %s)" % (t, list(map(str, t.sources)), list(map(str, slist))) - raise UserError(msg) - - if builder.single_source: - if len(slist) > 1: - raise UserError("More than one source given for single-source builder: targets=%s sources=%s" % (list(map(str,tlist)), list(map(str,slist)))) - -class EmitterProxy(object): - """This is a callable class that can act as a - Builder emitter. It holds on to a string that - is a key into an Environment dictionary, and will - look there at actual build time to see if it holds - a callable. If so, we will call that as the actual - emitter.""" - def __init__(self, var): - self.var = SCons.Util.to_String(var) - - def __call__(self, target, source, env): - emitter = self.var - - # Recursively substitute the variable. - # We can't use env.subst() because it deals only - # in strings. Maybe we should change that? - while SCons.Util.is_String(emitter) and emitter in env: - emitter = env[emitter] - if callable(emitter): - target, source = emitter(target, source, env) - elif SCons.Util.is_List(emitter): - for e in emitter: - target, source = e(target, source, env) - - return (target, source) - - - def __cmp__(self, other): - return cmp(self.var, other.var) - -class BuilderBase(object): - """Base class for Builders, objects that create output - nodes (files) from input nodes (files). - """ - - def __init__(self, action = None, - prefix = '', - suffix = '', - src_suffix = '', - target_factory = None, - source_factory = None, - target_scanner = None, - source_scanner = None, - emitter = None, - multi = 0, - env = None, - single_source = 0, - name = None, - chdir = _null, - is_explicit = 1, - src_builder = None, - ensure_suffix = False, - **overrides): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Builder.BuilderBase') - self._memo = {} - self.action = action - self.multi = multi - if SCons.Util.is_Dict(prefix): - prefix = CallableSelector(prefix) - self.prefix = prefix - if SCons.Util.is_Dict(suffix): - suffix = CallableSelector(suffix) - self.env = env - self.single_source = single_source - if 'overrides' in overrides: - SCons.Warnings.warn(SCons.Warnings.DeprecatedBuilderKeywordsWarning, - "The \"overrides\" keyword to Builder() creation has been deprecated;\n" +\ - "\tspecify the items as keyword arguments to the Builder() call instead.") - overrides.update(overrides['overrides']) - del overrides['overrides'] - if 'scanner' in overrides: - SCons.Warnings.warn(SCons.Warnings.DeprecatedBuilderKeywordsWarning, - "The \"scanner\" keyword to Builder() creation has been deprecated;\n" - "\tuse: source_scanner or target_scanner as appropriate.") - del overrides['scanner'] - self.overrides = overrides - - self.set_suffix(suffix) - self.set_src_suffix(src_suffix) - self.ensure_suffix = ensure_suffix - - self.target_factory = target_factory - self.source_factory = source_factory - self.target_scanner = target_scanner - self.source_scanner = source_scanner - - self.emitter = emitter - - # Optional Builder name should only be used for Builders - # that don't get attached to construction environments. - if name: - self.name = name - self.executor_kw = {} - if not chdir is _null: - self.executor_kw['chdir'] = chdir - self.is_explicit = is_explicit - - if src_builder is None: - src_builder = [] - elif not SCons.Util.is_List(src_builder): - src_builder = [ src_builder ] - self.src_builder = src_builder - - def __nonzero__(self): - raise InternalError("Do not test for the Node.builder attribute directly; use Node.has_builder() instead") - - def get_name(self, env): - """Attempts to get the name of the Builder. - - Look at the BUILDERS variable of env, expecting it to be a - dictionary containing this Builder, and return the key of the - dictionary. If there's no key, then return a directly-configured - name (if there is one) or the name of the class (by default).""" - - try: - index = list(env['BUILDERS'].values()).index(self) - return list(env['BUILDERS'].keys())[index] - except (AttributeError, KeyError, TypeError, ValueError): - try: - return self.name - except AttributeError: - return str(self.__class__) - - def __cmp__(self, other): - return cmp(self.__dict__, other.__dict__) - - def splitext(self, path, env=None): - if not env: - env = self.env - if env: - suffixes = self.src_suffixes(env) - else: - suffixes = [] - return match_splitext(path, suffixes) - - def _adjustixes(self, files, pre, suf, ensure_suffix=False): - if not files: - return [] - result = [] - if not SCons.Util.is_List(files): - files = [files] - - for f in files: - if SCons.Util.is_String(f): - f = SCons.Util.adjustixes(f, pre, suf, ensure_suffix) - result.append(f) - return result - - def _create_nodes(self, env, target = None, source = None): - """Create and return lists of target and source nodes. - """ - src_suf = self.get_src_suffix(env) - - target_factory = env.get_factory(self.target_factory) - source_factory = env.get_factory(self.source_factory) - - source = self._adjustixes(source, None, src_suf) - slist = env.arg2nodes(source, source_factory) - - pre = self.get_prefix(env, slist) - suf = self.get_suffix(env, slist) - - if target is None: - try: - t_from_s = slist[0].target_from_source - except AttributeError: - raise UserError("Do not know how to create a target from source `%s'" % slist[0]) - except IndexError: - tlist = [] - else: - splitext = lambda S: self.splitext(S,env) - tlist = [ t_from_s(pre, suf, splitext) ] - else: - target = self._adjustixes(target, pre, suf, self.ensure_suffix) - tlist = env.arg2nodes(target, target_factory, target=target, source=source) - - if self.emitter: - # The emitter is going to do str(node), but because we're - # being called *from* a builder invocation, the new targets - # don't yet have a builder set on them and will look like - # source files. Fool the emitter's str() calls by setting - # up a temporary builder on the new targets. - new_targets = [] - for t in tlist: - if not t.is_derived(): - t.builder_set(self) - new_targets.append(t) - - orig_tlist = tlist[:] - orig_slist = slist[:] - - target, source = self.emitter(target=tlist, source=slist, env=env) - - # Now delete the temporary builders that we attached to any - # new targets, so that _node_errors() doesn't do weird stuff - # to them because it thinks they already have builders. - for t in new_targets: - if t.builder is self: - # Only delete the temporary builder if the emitter - # didn't change it on us. - t.builder_set(None) - - # Have to call arg2nodes yet again, since it is legal for - # emitters to spit out strings as well as Node instances. - tlist = env.arg2nodes(target, target_factory, - target=orig_tlist, source=orig_slist) - slist = env.arg2nodes(source, source_factory, - target=orig_tlist, source=orig_slist) - - return tlist, slist - - def _execute(self, env, target, source, overwarn={}, executor_kw={}): - # We now assume that target and source are lists or None. - if self.src_builder: - source = self.src_builder_sources(env, source, overwarn) - - if self.single_source and len(source) > 1 and target is None: - result = [] - if target is None: target = [None]*len(source) - for tgt, src in zip(target, source): - if not tgt is None: tgt = [tgt] - if not src is None: src = [src] - result.extend(self._execute(env, tgt, src, overwarn)) - return SCons.Node.NodeList(result) - - overwarn.warn() - - tlist, slist = self._create_nodes(env, target, source) - - # Check for errors with the specified target/source lists. - _node_errors(self, env, tlist, slist) - - # The targets are fine, so find or make the appropriate Executor to - # build this particular list of targets from this particular list of - # sources. - - executor = None - key = None - - if self.multi: - try: - executor = tlist[0].get_executor(create = 0) - except (AttributeError, IndexError): - pass - else: - executor.add_sources(slist) - - if executor is None: - if not self.action: - fmt = "Builder %s must have an action to build %s." - raise UserError(fmt % (self.get_name(env or self.env), - list(map(str,tlist)))) - key = self.action.batch_key(env or self.env, tlist, slist) - if key: - try: - executor = SCons.Executor.GetBatchExecutor(key) - except KeyError: - pass - else: - executor.add_batch(tlist, slist) - - if executor is None: - executor = SCons.Executor.Executor(self.action, env, [], - tlist, slist, executor_kw) - if key: - SCons.Executor.AddBatchExecutor(key, executor) - - # Now set up the relevant information in the target Nodes themselves. - for t in tlist: - t.cwd = env.fs.getcwd() - t.builder_set(self) - t.env_set(env) - t.add_source(slist) - t.set_executor(executor) - t.set_explicit(self.is_explicit) - - return SCons.Node.NodeList(tlist) - - def __call__(self, env, target=None, source=None, chdir=_null, **kw): - # We now assume that target and source are lists or None. - # The caller (typically Environment.BuilderWrapper) is - # responsible for converting any scalar values to lists. - if chdir is _null: - ekw = self.executor_kw - else: - ekw = self.executor_kw.copy() - ekw['chdir'] = chdir - if kw: - if 'srcdir' in kw: - def prependDirIfRelative(f, srcdir=kw['srcdir']): - import os.path - if SCons.Util.is_String(f) and not os.path.isabs(f): - f = os.path.join(srcdir, f) - return f - if not SCons.Util.is_List(source): - source = [source] - source = list(map(prependDirIfRelative, source)) - del kw['srcdir'] - if self.overrides: - env_kw = self.overrides.copy() - env_kw.update(kw) - else: - env_kw = kw - else: - env_kw = self.overrides - env = env.Override(env_kw) - return self._execute(env, target, source, OverrideWarner(kw), ekw) - - def adjust_suffix(self, suff): - if suff and not suff[0] in [ '.', '_', '$' ]: - return '.' + suff - return suff - - def get_prefix(self, env, sources=[]): - prefix = self.prefix - if callable(prefix): - prefix = prefix(env, sources) - return env.subst(prefix) - - def set_suffix(self, suffix): - if not callable(suffix): - suffix = self.adjust_suffix(suffix) - self.suffix = suffix - - def get_suffix(self, env, sources=[]): - suffix = self.suffix - if callable(suffix): - suffix = suffix(env, sources) - return env.subst(suffix) - - def set_src_suffix(self, src_suffix): - if not src_suffix: - src_suffix = [] - elif not SCons.Util.is_List(src_suffix): - src_suffix = [ src_suffix ] - self.src_suffix = [callable(suf) and suf or self.adjust_suffix(suf) for suf in src_suffix] - - def get_src_suffix(self, env): - """Get the first src_suffix in the list of src_suffixes.""" - ret = self.src_suffixes(env) - if not ret: - return '' - return ret[0] - - def add_emitter(self, suffix, emitter): - """Add a suffix-emitter mapping to this Builder. - - This assumes that emitter has been initialized with an - appropriate dictionary type, and will throw a TypeError if - not, so the caller is responsible for knowing that this is an - appropriate method to call for the Builder in question. - """ - self.emitter[suffix] = emitter - - def add_src_builder(self, builder): - """ - Add a new Builder to the list of src_builders. - - This requires wiping out cached values so that the computed - lists of source suffixes get re-calculated. - """ - self._memo = {} - self.src_builder.append(builder) - - def _get_sdict(self, env): - """ - Returns a dictionary mapping all of the source suffixes of all - src_builders of this Builder to the underlying Builder that - should be called first. - - This dictionary is used for each target specified, so we save a - lot of extra computation by memoizing it for each construction - environment. - - Note that this is re-computed each time, not cached, because there - might be changes to one of our source Builders (or one of their - source Builders, and so on, and so on...) that we can't "see." - - The underlying methods we call cache their computed values, - though, so we hope repeatedly aggregating them into a dictionary - like this won't be too big a hit. We may need to look for a - better way to do this if performance data show this has turned - into a significant bottleneck. - """ - sdict = {} - for bld in self.get_src_builders(env): - for suf in bld.src_suffixes(env): - sdict[suf] = bld - return sdict - - def src_builder_sources(self, env, source, overwarn={}): - sdict = self._get_sdict(env) - - src_suffixes = self.src_suffixes(env) - - lengths = list(set(map(len, src_suffixes))) - - def match_src_suffix(name, src_suffixes=src_suffixes, lengths=lengths): - node_suffixes = [name[-l:] for l in lengths] - for suf in src_suffixes: - if suf in node_suffixes: - return suf - return None - - result = [] - for s in SCons.Util.flatten(source): - if SCons.Util.is_String(s): - match_suffix = match_src_suffix(env.subst(s)) - if not match_suffix and not '.' in s: - src_suf = self.get_src_suffix(env) - s = self._adjustixes(s, None, src_suf)[0] - else: - match_suffix = match_src_suffix(s.name) - if match_suffix: - try: - bld = sdict[match_suffix] - except KeyError: - result.append(s) - else: - tlist = bld._execute(env, None, [s], overwarn) - # If the subsidiary Builder returned more than one - # target, then filter out any sources that this - # Builder isn't capable of building. - if len(tlist) > 1: - tlist = [t for t in tlist if match_src_suffix(t.name)] - result.extend(tlist) - else: - result.append(s) - - source_factory = env.get_factory(self.source_factory) - - return env.arg2nodes(result, source_factory) - - def _get_src_builders_key(self, env): - return id(env) - - @SCons.Memoize.CountDictCall(_get_src_builders_key) - def get_src_builders(self, env): - """ - Returns the list of source Builders for this Builder. - - This exists mainly to look up Builders referenced as - strings in the 'BUILDER' variable of the construction - environment and cache the result. - """ - memo_key = id(env) - try: - memo_dict = self._memo['get_src_builders'] - except KeyError: - memo_dict = {} - self._memo['get_src_builders'] = memo_dict - else: - try: - return memo_dict[memo_key] - except KeyError: - pass - - builders = [] - for bld in self.src_builder: - if SCons.Util.is_String(bld): - try: - bld = env['BUILDERS'][bld] - except KeyError: - continue - builders.append(bld) - - memo_dict[memo_key] = builders - return builders - - def _subst_src_suffixes_key(self, env): - return id(env) - - @SCons.Memoize.CountDictCall(_subst_src_suffixes_key) - def subst_src_suffixes(self, env): - """ - The suffix list may contain construction variable expansions, - so we have to evaluate the individual strings. To avoid doing - this over and over, we memoize the results for each construction - environment. - """ - memo_key = id(env) - try: - memo_dict = self._memo['subst_src_suffixes'] - except KeyError: - memo_dict = {} - self._memo['subst_src_suffixes'] = memo_dict - else: - try: - return memo_dict[memo_key] - except KeyError: - pass - suffixes = [env.subst(x) for x in self.src_suffix] - memo_dict[memo_key] = suffixes - return suffixes - - def src_suffixes(self, env): - """ - Returns the list of source suffixes for all src_builders of this - Builder. - - This is essentially a recursive descent of the src_builder "tree." - (This value isn't cached because there may be changes in a - src_builder many levels deep that we can't see.) - """ - sdict = {} - suffixes = self.subst_src_suffixes(env) - for s in suffixes: - sdict[s] = 1 - for builder in self.get_src_builders(env): - for s in builder.src_suffixes(env): - if s not in sdict: - sdict[s] = 1 - suffixes.append(s) - return suffixes - -class CompositeBuilder(SCons.Util.Proxy): - """A Builder Proxy whose main purpose is to always have - a DictCmdGenerator as its action, and to provide access - to the DictCmdGenerator's add_action() method. - """ - - def __init__(self, builder, cmdgen): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Builder.CompositeBuilder') - SCons.Util.Proxy.__init__(self, builder) - - # cmdgen should always be an instance of DictCmdGenerator. - self.cmdgen = cmdgen - self.builder = builder - - __call__ = SCons.Util.Delegate('__call__') - - def add_action(self, suffix, action): - self.cmdgen.add_action(suffix, action) - self.set_src_suffix(self.cmdgen.src_suffixes()) - -def is_a_Builder(obj): - """"Returns True if the specified obj is one of our Builder classes. - - The test is complicated a bit by the fact that CompositeBuilder - is a proxy, not a subclass of BuilderBase. - """ - return (isinstance(obj, BuilderBase) - or isinstance(obj, CompositeBuilder) - or callable(obj)) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/CacheDir.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/CacheDir.py deleted file mode 100644 index 9e3ec6b..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/CacheDir.py +++ /dev/null @@ -1,222 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/CacheDir.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -__doc__ = """ -CacheDir support -""" - -import os.path -import stat -import sys - -import SCons.Action - -cache_enabled = True -cache_debug = False -cache_force = False -cache_show = False -cache_readonly = False - -def CacheRetrieveFunc(target, source, env): - t = target[0] - fs = t.fs - cd = env.get_CacheDir() - cachedir, cachefile = cd.cachepath(t) - if not fs.exists(cachefile): - cd.CacheDebug('CacheRetrieve(%s): %s not in cache\n', t, cachefile) - return 1 - cd.CacheDebug('CacheRetrieve(%s): retrieving from %s\n', t, cachefile) - if SCons.Action.execute_actions: - if fs.islink(cachefile): - fs.symlink(fs.readlink(cachefile), t.get_internal_path()) - else: - env.copy_from_cache(cachefile, t.get_internal_path()) - st = fs.stat(cachefile) - fs.chmod(t.get_internal_path(), stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) - return 0 - -def CacheRetrieveString(target, source, env): - t = target[0] - fs = t.fs - cd = env.get_CacheDir() - cachedir, cachefile = cd.cachepath(t) - if t.fs.exists(cachefile): - return "Retrieved `%s' from cache" % t.get_internal_path() - return None - -CacheRetrieve = SCons.Action.Action(CacheRetrieveFunc, CacheRetrieveString) - -CacheRetrieveSilent = SCons.Action.Action(CacheRetrieveFunc, None) - -def CachePushFunc(target, source, env): - if cache_readonly: return - - t = target[0] - if t.nocache: - return - fs = t.fs - cd = env.get_CacheDir() - cachedir, cachefile = cd.cachepath(t) - if fs.exists(cachefile): - # Don't bother copying it if it's already there. Note that - # usually this "shouldn't happen" because if the file already - # existed in cache, we'd have retrieved the file from there, - # not built it. This can happen, though, in a race, if some - # other person running the same build pushes their copy to - # the cache after we decide we need to build it but before our - # build completes. - cd.CacheDebug('CachePush(%s): %s already exists in cache\n', t, cachefile) - return - - cd.CacheDebug('CachePush(%s): pushing to %s\n', t, cachefile) - - tempfile = cachefile+'.tmp'+str(os.getpid()) - errfmt = "Unable to copy %s to cache. Cache file is %s" - - if not fs.isdir(cachedir): - try: - fs.makedirs(cachedir) - except EnvironmentError: - # We may have received an exception because another process - # has beaten us creating the directory. - if not fs.isdir(cachedir): - msg = errfmt % (str(target), cachefile) - raise SCons.Errors.EnvironmentError(msg) - - try: - if fs.islink(t.get_internal_path()): - fs.symlink(fs.readlink(t.get_internal_path()), tempfile) - else: - fs.copy2(t.get_internal_path(), tempfile) - fs.rename(tempfile, cachefile) - st = fs.stat(t.get_internal_path()) - fs.chmod(cachefile, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) - except EnvironmentError: - # It's possible someone else tried writing the file at the - # same time we did, or else that there was some problem like - # the CacheDir being on a separate file system that's full. - # In any case, inability to push a file to cache doesn't affect - # the correctness of the build, so just print a warning. - msg = errfmt % (str(target), cachefile) - SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning, msg) - -CachePush = SCons.Action.Action(CachePushFunc, None) - -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) - self.path = None - else: - self.path = path - self.current_cache_debug = None - self.debugFP = None - - def CacheDebug(self, fmt, target, cachefile): - if cache_debug != self.current_cache_debug: - if cache_debug == '-': - self.debugFP = sys.stdout - elif cache_debug: - self.debugFP = open(cache_debug, 'w') - else: - self.debugFP = None - self.current_cache_debug = cache_debug - if self.debugFP: - self.debugFP.write(fmt % (target, os.path.split(cachefile)[1])) - - def is_enabled(self): - return (cache_enabled and not self.path is None) - - def is_readonly(self): - return cache_readonly - - def cachepath(self, node): - """ - """ - if not self.is_enabled(): - return None, None - - sig = node.get_cachedir_bsig() - subdir = sig[0].upper() - dir = os.path.join(self.path, subdir) - return dir, os.path.join(dir, sig) - - def retrieve(self, node): - """ - This method is called from multiple threads in a parallel build, - so only do thread safe stuff here. Do thread unsafe stuff in - built(). - - Note that there's a special trick here with the execute flag - (one that's not normally done for other actions). Basically - if the user requested a no_exec (-n) build, then - SCons.Action.execute_actions is set to 0 and when any action - is called, it does its showing but then just returns zero - instead of actually calling the action execution operation. - The problem for caching is that if the file does NOT exist in - cache then the CacheRetrieveString won't return anything to - show for the task, but the Action.__call__ won't call - CacheRetrieveFunc; instead it just returns zero, which makes - the code below think that the file *was* successfully - retrieved from the cache, therefore it doesn't do any - subsequent building. However, the CacheRetrieveString didn't - print anything because it didn't actually exist in the cache, - and no more build actions will be performed, so the user just - sees nothing. The fix is to tell Action.__call__ to always - execute the CacheRetrieveFunc and then have the latter - explicitly check SCons.Action.execute_actions itself. - """ - if not self.is_enabled(): - return False - - env = node.get_build_env() - if cache_show: - if CacheRetrieveSilent(node, [], env, execute=1) == 0: - node.build(presub=0, execute=0) - return True - else: - if CacheRetrieve(node, [], env, execute=1) == 0: - return True - - return False - - def push(self, node): - if self.is_readonly() or not self.is_enabled(): - return - return CachePush(node, [], node.get_build_env()) - - def push_if_forced(self, node): - if cache_force: - return self.push(node) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Conftest.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Conftest.py deleted file mode 100644 index e9702ff..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Conftest.py +++ /dev/null @@ -1,793 +0,0 @@ -"""SCons.Conftest - -Autoconf-like configuration support; low level implementation of tests. -""" - -# -# Copyright (c) 2003 Stichting NLnet Labs -# Copyright (c) 2001, 2002, 2003 Steven Knight -# -# 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. -# - -# -# The purpose of this module is to define how a check is to be performed. -# Use one of the Check...() functions below. -# - -# -# A context class is used that defines functions for carrying out the tests, -# logging and messages. The following methods and members must be present: -# -# context.Display(msg) Function called to print messages that are normally -# displayed for the user. Newlines are explicitly used. -# The text should also be written to the logfile! -# -# context.Log(msg) Function called to write to a log file. -# -# context.BuildProg(text, ext) -# Function called to build a program, using "ext" for the -# file extention. Must return an empty string for -# success, an error message for failure. -# For reliable test results building should be done just -# like an actual program would be build, using the same -# command and arguments (including configure results so -# far). -# -# context.CompileProg(text, ext) -# Function called to compile a program, using "ext" for -# the file extention. Must return an empty string for -# success, an error message for failure. -# For reliable test results compiling should be done just -# like an actual source file would be compiled, using the -# same command and arguments (including configure results -# so far). -# -# context.AppendLIBS(lib_name_list) -# Append "lib_name_list" to the value of LIBS. -# "lib_namelist" is a list of strings. -# Return the value of LIBS before changing it (any type -# can be used, it is passed to SetLIBS() later.) -# -# context.PrependLIBS(lib_name_list) -# Prepend "lib_name_list" to the value of LIBS. -# "lib_namelist" is a list of strings. -# Return the value of LIBS before changing it (any type -# can be used, it is passed to SetLIBS() later.) -# -# context.SetLIBS(value) -# Set LIBS to "value". The type of "value" is what -# AppendLIBS() returned. -# Return the value of LIBS before changing it (any type -# can be used, it is passed to SetLIBS() later.) -# -# context.headerfilename -# Name of file to append configure results to, usually -# "confdefs.h". -# The file must not exist or be empty when starting. -# Empty or None to skip this (some tests will not work!). -# -# context.config_h (may be missing). If present, must be a string, which -# will be filled with the contents of a config_h file. -# -# context.vardict Dictionary holding variables used for the tests and -# stores results from the tests, used for the build -# commands. -# Normally contains "CC", "LIBS", "CPPFLAGS", etc. -# -# context.havedict Dictionary holding results from the tests that are to -# be used inside a program. -# Names often start with "HAVE_". These are zero -# (feature not present) or one (feature present). Other -# variables may have any value, e.g., "PERLVERSION" can -# be a number and "SYSTEMNAME" a string. -# - -import re -from types import IntType - -# -# PUBLIC VARIABLES -# - -LogInputFiles = 1 # Set that to log the input files in case of a failed test -LogErrorMessages = 1 # Set that to log Conftest-generated error messages - -# -# PUBLIC FUNCTIONS -# - -# Generic remarks: -# - When a language is specified which is not supported the test fails. The -# message is a bit different, because not all the arguments for the normal -# message are available yet (chicken-egg problem). - - -def CheckBuilder(context, text = None, language = None): - """ - Configure check to see if the compiler works. - Note that this uses the current value of compiler and linker flags, make - sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. - "language" should be "C" or "C++" and is used to select the compiler. - Default is "C". - "text" may be used to specify the code to be build. - Returns an empty string for success, an error message for failure. - """ - lang, suffix, msg = _lang2suffix(language) - if msg: - context.Display("%s\n" % msg) - return msg - - if not text: - text = """ -int main() { - return 0; -} -""" - - context.Display("Checking if building a %s file works... " % lang) - ret = context.BuildProg(text, suffix) - _YesNoResult(context, ret, None, text) - return ret - -def CheckCC(context): - """ - Configure check for a working C compiler. - - This checks whether the C compiler, as defined in the $CC construction - variable, can compile a C source file. It uses the current $CCCOM value - too, so that it can test against non working flags. - - """ - context.Display("Checking whether the C compiler works... ") - text = """ -int main() -{ - return 0; -} -""" - ret = _check_empty_program(context, 'CC', text, 'C') - _YesNoResult(context, ret, None, text) - return ret - -def CheckSHCC(context): - """ - Configure check for a working shared C compiler. - - This checks whether the C compiler, as defined in the $SHCC construction - variable, can compile a C source file. It uses the current $SHCCCOM value - too, so that it can test against non working flags. - - """ - context.Display("Checking whether the (shared) C compiler works... ") - text = """ -int foo() -{ - return 0; -} -""" - ret = _check_empty_program(context, 'SHCC', text, 'C', use_shared = True) - _YesNoResult(context, ret, None, text) - return ret - -def CheckCXX(context): - """ - Configure check for a working CXX compiler. - - This checks whether the CXX compiler, as defined in the $CXX construction - variable, can compile a CXX source file. It uses the current $CXXCOM value - too, so that it can test against non working flags. - - """ - context.Display("Checking whether the C++ compiler works... ") - text = """ -int main() -{ - return 0; -} -""" - ret = _check_empty_program(context, 'CXX', text, 'C++') - _YesNoResult(context, ret, None, text) - return ret - -def CheckSHCXX(context): - """ - Configure check for a working shared CXX compiler. - - This checks whether the CXX compiler, as defined in the $SHCXX construction - variable, can compile a CXX source file. It uses the current $SHCXXCOM value - too, so that it can test against non working flags. - - """ - context.Display("Checking whether the (shared) C++ compiler works... ") - text = """ -int main() -{ - return 0; -} -""" - ret = _check_empty_program(context, 'SHCXX', text, 'C++', use_shared = True) - _YesNoResult(context, ret, None, text) - return ret - -def _check_empty_program(context, comp, text, language, use_shared = False): - """Return 0 on success, 1 otherwise.""" - if comp not in context.env or not context.env[comp]: - # The compiler construction variable is not set or empty - return 1 - - lang, suffix, msg = _lang2suffix(language) - if msg: - return 1 - - if use_shared: - return context.CompileSharedObject(text, suffix) - else: - return context.CompileProg(text, suffix) - - -def CheckFunc(context, function_name, header = None, language = None): - """ - Configure check for a function "function_name". - "language" should be "C" or "C++" and is used to select the compiler. - Default is "C". - Optional "header" can be defined to define a function prototype, include a - header file or anything else that comes before main(). - Sets HAVE_function_name in context.havedict according to the result. - Note that this uses the current value of compiler and linker flags, make - sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. - Returns an empty string for success, an error message for failure. - """ - - # Remarks from autoconf: - # - Don't include because on OSF/1 3.0 it includes - # which includes which contains a prototype for select. - # Similarly for bzero. - # - assert.h is included to define __stub macros and hopefully few - # prototypes, which can conflict with char $1(); below. - # - Override any gcc2 internal prototype to avoid an error. - # - We use char for the function declaration because int might match the - # return type of a gcc2 builtin and then its argument prototype would - # still apply. - # - The GNU C library defines this for functions which it implements to - # always fail with ENOSYS. Some functions are actually named something - # starting with __ and the normal name is an alias. - - if context.headerfilename: - includetext = '#include "%s"' % context.headerfilename - else: - includetext = '' - if not header: - header = """ -#ifdef __cplusplus -extern "C" -#endif -char %s();""" % function_name - - lang, suffix, msg = _lang2suffix(language) - if msg: - context.Display("Cannot check for %s(): %s\n" % (function_name, msg)) - return msg - - text = """ -%(include)s -#include -%(hdr)s - -int main() { -#if defined (__stub_%(name)s) || defined (__stub___%(name)s) - fail fail fail -#else - %(name)s(); -#endif - - return 0; -} -""" % { 'name': function_name, - 'include': includetext, - 'hdr': header } - - context.Display("Checking for %s function %s()... " % (lang, function_name)) - ret = context.BuildProg(text, suffix) - _YesNoResult(context, ret, "HAVE_" + function_name, text, - "Define to 1 if the system has the function `%s'." %\ - function_name) - return ret - - -def CheckHeader(context, header_name, header = None, language = None, - include_quotes = None): - """ - Configure check for a C or C++ header file "header_name". - Optional "header" can be defined to do something before including the - header file (unusual, supported for consistency). - "language" should be "C" or "C++" and is used to select the compiler. - Default is "C". - Sets HAVE_header_name in context.havedict according to the result. - Note that this uses the current value of compiler and linker flags, make - sure $CFLAGS and $CPPFLAGS are set correctly. - Returns an empty string for success, an error message for failure. - """ - # Why compile the program instead of just running the preprocessor? - # It is possible that the header file exists, but actually using it may - # fail (e.g., because it depends on other header files). Thus this test is - # more strict. It may require using the "header" argument. - # - # Use <> by default, because the check is normally used for system header - # files. SCons passes '""' to overrule this. - - # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. - if context.headerfilename: - includetext = '#include "%s"\n' % context.headerfilename - else: - includetext = '' - if not header: - header = "" - - lang, suffix, msg = _lang2suffix(language) - if msg: - context.Display("Cannot check for header file %s: %s\n" - % (header_name, msg)) - return msg - - if not include_quotes: - include_quotes = "<>" - - text = "%s%s\n#include %s%s%s\n\n" % (includetext, header, - include_quotes[0], header_name, include_quotes[1]) - - context.Display("Checking for %s header file %s... " % (lang, header_name)) - ret = context.CompileProg(text, suffix) - _YesNoResult(context, ret, "HAVE_" + header_name, text, - "Define to 1 if you have the <%s> header file." % header_name) - return ret - - -def CheckType(context, type_name, fallback = None, - header = None, language = None): - """ - Configure check for a C or C++ type "type_name". - Optional "header" can be defined to include a header file. - "language" should be "C" or "C++" and is used to select the compiler. - Default is "C". - Sets HAVE_type_name in context.havedict according to the result. - Note that this uses the current value of compiler and linker flags, make - sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. - Returns an empty string for success, an error message for failure. - """ - - # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. - if context.headerfilename: - includetext = '#include "%s"' % context.headerfilename - else: - includetext = '' - if not header: - header = "" - - lang, suffix, msg = _lang2suffix(language) - if msg: - context.Display("Cannot check for %s type: %s\n" % (type_name, msg)) - return msg - - # Remarks from autoconf about this test: - # - Grepping for the type in include files is not reliable (grep isn't - # portable anyway). - # - Using "TYPE my_var;" doesn't work for const qualified types in C++. - # Adding an initializer is not valid for some C++ classes. - # - Using the type as parameter to a function either fails for K&$ C or for - # C++. - # - Using "TYPE *my_var;" is valid in C for some types that are not - # declared (struct something). - # - Using "sizeof(TYPE)" is valid when TYPE is actually a variable. - # - Using the previous two together works reliably. - text = """ -%(include)s -%(header)s - -int main() { - if ((%(name)s *) 0) - return 0; - if (sizeof (%(name)s)) - return 0; -} -""" % { 'include': includetext, - 'header': header, - 'name': type_name } - - context.Display("Checking for %s type %s... " % (lang, type_name)) - ret = context.BuildProg(text, suffix) - _YesNoResult(context, ret, "HAVE_" + type_name, text, - "Define to 1 if the system has the type `%s'." % type_name) - if ret and fallback and context.headerfilename: - f = open(context.headerfilename, "a") - f.write("typedef %s %s;\n" % (fallback, type_name)) - f.close() - - return ret - -def CheckTypeSize(context, type_name, header = None, language = None, expect = None): - """This check can be used to get the size of a given type, or to check whether - the type is of expected size. - - Arguments: - - type : str - the type to check - - includes : sequence - list of headers to include in the test code before testing the type - - language : str - 'C' or 'C++' - - expect : int - if given, will test wether the type has the given number of bytes. - If not given, will automatically find the size. - - Returns: - status : int - 0 if the check failed, or the found size of the type if the check succeeded.""" - - # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. - if context.headerfilename: - includetext = '#include "%s"' % context.headerfilename - else: - includetext = '' - - if not header: - header = "" - - lang, suffix, msg = _lang2suffix(language) - if msg: - context.Display("Cannot check for %s type: %s\n" % (type_name, msg)) - return msg - - src = includetext + header - if not expect is None: - # Only check if the given size is the right one - context.Display('Checking %s is %d bytes... ' % (type_name, expect)) - - # test code taken from autoconf: this is a pretty clever hack to find that - # a type is of a given size using only compilation. This speeds things up - # quite a bit compared to straightforward code using TryRun - src = src + r""" -typedef %s scons_check_type; - -int main() -{ - static int test_array[1 - 2 * !(((long int) (sizeof(scons_check_type))) == %d)]; - test_array[0] = 0; - - return 0; -} -""" - - st = context.CompileProg(src % (type_name, expect), suffix) - if not st: - context.Display("yes\n") - _Have(context, "SIZEOF_%s" % type_name, expect, - "The size of `%s', as computed by sizeof." % type_name) - return expect - else: - context.Display("no\n") - _LogFailed(context, src, st) - return 0 - else: - # Only check if the given size is the right one - context.Message('Checking size of %s ... ' % type_name) - - # We have to be careful with the program we wish to test here since - # compilation will be attempted using the current environment's flags. - # So make sure that the program will compile without any warning. For - # example using: 'int main(int argc, char** argv)' will fail with the - # '-Wall -Werror' flags since the variables argc and argv would not be - # used in the program... - # - src = src + """ -#include -#include -int main() { - printf("%d", (int)sizeof(""" + type_name + """)); - return 0; -} - """ - st, out = context.RunProg(src, suffix) - try: - size = int(out) - except ValueError: - # If cannot convert output of test prog to an integer (the size), - # something went wront, so just fail - st = 1 - size = 0 - - if not st: - context.Display("yes\n") - _Have(context, "SIZEOF_%s" % type_name, size, - "The size of `%s', as computed by sizeof." % type_name) - return size - else: - context.Display("no\n") - _LogFailed(context, src, st) - return 0 - - return 0 - -def CheckDeclaration(context, symbol, includes = None, language = None): - """Checks whether symbol is declared. - - Use the same test as autoconf, that is test whether the symbol is defined - as a macro or can be used as an r-value. - - Arguments: - symbol : str - the symbol to check - includes : str - Optional "header" can be defined to include a header file. - language : str - only C and C++ supported. - - Returns: - status : bool - True if the check failed, False if succeeded.""" - - # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. - if context.headerfilename: - includetext = '#include "%s"' % context.headerfilename - else: - includetext = '' - - if not includes: - includes = "" - - lang, suffix, msg = _lang2suffix(language) - if msg: - context.Display("Cannot check for declaration %s: %s\n" % (symbol, msg)) - return msg - - src = includetext + includes - context.Display('Checking whether %s is declared... ' % symbol) - - src = src + r""" -int main() -{ -#ifndef %s - (void) %s; -#endif - ; - return 0; -} -""" % (symbol, symbol) - - st = context.CompileProg(src, suffix) - _YesNoResult(context, st, "HAVE_DECL_" + symbol, src, - "Set to 1 if %s is defined." % symbol) - return st - -def CheckLib(context, libs, func_name = None, header = None, - extra_libs = None, call = None, language = None, autoadd = 1, - append = True): - """ - Configure check for a C or C++ libraries "libs". Searches through - the list of libraries, until one is found where the test succeeds. - Tests if "func_name" or "call" exists in the library. Note: if it exists - in another library the test succeeds anyway! - Optional "header" can be defined to include a header file. If not given a - default prototype for "func_name" is added. - Optional "extra_libs" is a list of library names to be added after - "lib_name" in the build command. To be used for libraries that "lib_name" - depends on. - Optional "call" replaces the call to "func_name" in the test code. It must - consist of complete C statements, including a trailing ";". - Both "func_name" and "call" arguments are optional, and in that case, just - linking against the libs is tested. - "language" should be "C" or "C++" and is used to select the compiler. - Default is "C". - Note that this uses the current value of compiler and linker flags, make - sure $CFLAGS, $CPPFLAGS and $LIBS are set correctly. - Returns an empty string for success, an error message for failure. - """ - # Include "confdefs.h" first, so that the header can use HAVE_HEADER_H. - if context.headerfilename: - includetext = '#include "%s"' % context.headerfilename - else: - includetext = '' - if not header: - header = "" - - text = """ -%s -%s""" % (includetext, header) - - # Add a function declaration if needed. - if func_name and func_name != "main": - if not header: - text = text + """ -#ifdef __cplusplus -extern "C" -#endif -char %s(); -""" % func_name - - # The actual test code. - if not call: - call = "%s();" % func_name - - # if no function to test, leave main() blank - text = text + """ -int -main() { - %s -return 0; -} -""" % (call or "") - - if call: - i = call.find("\n") - if i > 0: - calltext = call[:i] + ".." - elif call[-1] == ';': - calltext = call[:-1] - else: - calltext = call - - for lib_name in libs: - - lang, suffix, msg = _lang2suffix(language) - if msg: - context.Display("Cannot check for library %s: %s\n" % (lib_name, msg)) - return msg - - # if a function was specified to run in main(), say it - if call: - context.Display("Checking for %s in %s library %s... " - % (calltext, lang, lib_name)) - # otherwise, just say the name of library and language - else: - context.Display("Checking for %s library %s... " - % (lang, lib_name)) - - if lib_name: - l = [ lib_name ] - if extra_libs: - l.extend(extra_libs) - if append: - oldLIBS = context.AppendLIBS(l) - else: - oldLIBS = context.PrependLIBS(l) - sym = "HAVE_LIB" + lib_name - else: - oldLIBS = -1 - sym = None - - ret = context.BuildProg(text, suffix) - - _YesNoResult(context, ret, sym, text, - "Define to 1 if you have the `%s' library." % lib_name) - if oldLIBS != -1 and (ret or not autoadd): - context.SetLIBS(oldLIBS) - - if not ret: - return ret - - return ret - -# -# END OF PUBLIC FUNCTIONS -# - -def _YesNoResult(context, ret, key, text, comment = None): - """ - Handle the result of a test with a "yes" or "no" result. - "ret" is the return value: empty if OK, error message when not. - "key" is the name of the symbol to be defined (HAVE_foo). - "text" is the source code of the program used for testing. - "comment" is the C comment to add above the line defining the symbol (the - comment is automatically put inside a /* */). If None, no comment is added. - """ - if key: - _Have(context, key, not ret, comment) - if ret: - context.Display("no\n") - _LogFailed(context, text, ret) - else: - context.Display("yes\n") - - -def _Have(context, key, have, comment = None): - """ - Store result of a test in context.havedict and context.headerfilename. - "key" is a "HAVE_abc" name. It is turned into all CAPITALS and non- - alphanumerics are replaced by an underscore. - The value of "have" can be: - 1 - Feature is defined, add "#define key". - 0 - Feature is not defined, add "/* #undef key */". - Adding "undef" is what autoconf does. Not useful for the - compiler, but it shows that the test was done. - number - Feature is defined to this number "#define key have". - Doesn't work for 0 or 1, use a string then. - string - Feature is defined to this string "#define key have". - Give "have" as is should appear in the header file, include quotes - when desired and escape special characters! - """ - key_up = key.upper() - key_up = re.sub('[^A-Z0-9_]', '_', key_up) - context.havedict[key_up] = have - if have == 1: - line = "#define %s 1\n" % key_up - elif have == 0: - line = "/* #undef %s */\n" % key_up - elif isinstance(have, IntType): - line = "#define %s %d\n" % (key_up, have) - else: - line = "#define %s %s\n" % (key_up, str(have)) - - if comment is not None: - lines = "\n/* %s */\n" % comment + line - else: - lines = "\n" + line - - if context.headerfilename: - f = open(context.headerfilename, "a") - f.write(lines) - f.close() - elif hasattr(context,'config_h'): - context.config_h = context.config_h + lines - - -def _LogFailed(context, text, msg): - """ - Write to the log about a failed program. - Add line numbers, so that error messages can be understood. - """ - if LogInputFiles: - context.Log("Failed program was:\n") - lines = text.split('\n') - if len(lines) and lines[-1] == '': - lines = lines[:-1] # remove trailing empty line - n = 1 - for line in lines: - context.Log("%d: %s\n" % (n, line)) - n = n + 1 - if LogErrorMessages: - context.Log("Error message: %s\n" % msg) - - -def _lang2suffix(lang): - """ - Convert a language name to a suffix. - When "lang" is empty or None C is assumed. - Returns a tuple (lang, suffix, None) when it works. - For an unrecognized language returns (None, None, msg). - Where: - lang = the unified language name - suffix = the suffix, including the leading dot - msg = an error message - """ - if not lang or lang in ["C", "c"]: - return ("C", ".c", None) - if lang in ["c++", "C++", "cpp", "CXX", "cxx"]: - return ("C++", ".cpp", None) - - return None, None, "Unsupported language: %s" % lang - - -# vim: set sw=4 et sts=4 tw=79 fo+=l: - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Debug.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Debug.py deleted file mode 100644 index 0aa077d..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Debug.py +++ /dev/null @@ -1,234 +0,0 @@ -"""SCons.Debug - -Code for debugging SCons internal things. Shouldn't be -needed by most users. - -""" - -# -# Copyright (c) 2001 - 2015 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/Debug.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import os -import sys -import time -import weakref -import inspect - -# Global variable that gets set to 'True' by the Main script, -# when the creation of class instances should get tracked. -track_instances = False -# List of currently tracked classes -tracked_classes = {} - -def logInstanceCreation(instance, name=None): - if name is None: - name = instance.__class__.__name__ - if name not in tracked_classes: - tracked_classes[name] = [] - if hasattr(instance, '__dict__'): - tracked_classes[name].append(weakref.ref(instance)) - else: - # weakref doesn't seem to work when the instance - # contains only slots... - tracked_classes[name].append(instance) - -def string_to_classes(s): - if s == '*': - return sorted(tracked_classes.keys()) - else: - return s.split() - -def fetchLoggedInstances(classes="*"): - classnames = string_to_classes(classes) - return [(cn, len(tracked_classes[cn])) for cn in classnames] - -def countLoggedInstances(classes, file=sys.stdout): - for classname in string_to_classes(classes): - file.write("%s: %d\n" % (classname, len(tracked_classes[classname]))) - -def listLoggedInstances(classes, file=sys.stdout): - for classname in string_to_classes(classes): - file.write('\n%s:\n' % classname) - for ref in tracked_classes[classname]: - if inspect.isclass(ref): - obj = ref() - else: - obj = ref - if obj is not None: - file.write(' %s\n' % repr(obj)) - -def dumpLoggedInstances(classes, file=sys.stdout): - for classname in string_to_classes(classes): - file.write('\n%s:\n' % classname) - for ref in tracked_classes[classname]: - obj = ref() - if obj is not None: - file.write(' %s:\n' % obj) - for key, value in obj.__dict__.items(): - file.write(' %20s : %s\n' % (key, value)) - - - -if sys.platform[:5] == "linux": - # Linux doesn't actually support memory usage stats from getrusage(). - def memory(): - mstr = open('/proc/self/stat').read() - mstr = mstr.split()[22] - return int(mstr) -elif sys.platform[:6] == 'darwin': - #TODO really get memory stats for OS X - def memory(): - return 0 -else: - try: - import resource - except ImportError: - try: - import win32process - import win32api - except ImportError: - def memory(): - return 0 - else: - def memory(): - process_handle = win32api.GetCurrentProcess() - memory_info = win32process.GetProcessMemoryInfo( process_handle ) - return memory_info['PeakWorkingSetSize'] - else: - def memory(): - res = resource.getrusage(resource.RUSAGE_SELF) - return res[4] - -# returns caller's stack -def caller_stack(): - import traceback - tb = traceback.extract_stack() - # strip itself and the caller from the output - tb = tb[:-2] - result = [] - for back in tb: - # (filename, line number, function name, text) - key = back[:3] - result.append('%s:%d(%s)' % func_shorten(key)) - return result - -caller_bases = {} -caller_dicts = {} - -# trace a caller's stack -def caller_trace(back=0): - import traceback - tb = traceback.extract_stack(limit=3+back) - tb.reverse() - callee = tb[1][:3] - caller_bases[callee] = caller_bases.get(callee, 0) + 1 - for caller in tb[2:]: - caller = callee + caller[:3] - try: - entry = caller_dicts[callee] - except KeyError: - caller_dicts[callee] = entry = {} - entry[caller] = entry.get(caller, 0) + 1 - callee = caller - -# print a single caller and its callers, if any -def _dump_one_caller(key, file, level=0): - leader = ' '*level - for v,c in sorted([(-v,c) for c,v in caller_dicts[key].items()]): - file.write("%s %6d %s:%d(%s)\n" % ((leader,-v) + func_shorten(c[-3:]))) - if c in caller_dicts: - _dump_one_caller(c, file, level+1) - -# print each call tree -def dump_caller_counts(file=sys.stdout): - for k in sorted(caller_bases.keys()): - file.write("Callers of %s:%d(%s), %d calls:\n" - % (func_shorten(k) + (caller_bases[k],))) - _dump_one_caller(k, file) - -shorten_list = [ - ( '/scons/SCons/', 1), - ( '/src/engine/SCons/', 1), - ( '/usr/lib/python', 0), -] - -if os.sep != '/': - shorten_list = [(t[0].replace('/', os.sep), t[1]) for t in shorten_list] - -def func_shorten(func_tuple): - f = func_tuple[0] - for t in shorten_list: - i = f.find(t[0]) - if i >= 0: - if t[1]: - i = i + len(t[0]) - return (f[i:],)+func_tuple[1:] - return func_tuple - - -TraceFP = {} -if sys.platform == 'win32': - TraceDefault = 'con' -else: - TraceDefault = '/dev/tty' - -TimeStampDefault = None -StartTime = time.time() -PreviousTime = StartTime - -def Trace(msg, file=None, mode='w', tstamp=None): - """Write a trace message to a file. Whenever a file is specified, - it becomes the default for the next call to Trace().""" - global TraceDefault - global TimeStampDefault - global PreviousTime - if file is None: - file = TraceDefault - else: - TraceDefault = file - if tstamp is None: - tstamp = TimeStampDefault - else: - TimeStampDefault = tstamp - try: - fp = TraceFP[file] - except KeyError: - try: - fp = TraceFP[file] = open(file, mode) - except TypeError: - # Assume we were passed an open file pointer. - fp = file - if tstamp: - now = time.time() - fp.write('%8.4f %8.4f: ' % (now - StartTime, now - PreviousTime)) - PreviousTime = now - fp.write(msg) - fp.flush() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Defaults.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Defaults.py deleted file mode 100644 index b4cbb9a..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Defaults.py +++ /dev/null @@ -1,513 +0,0 @@ -"""SCons.Defaults - -Builders and other things for the local site. Here's where we'll -duplicate the functionality of autoconf until we move it into the -installation procedure or use something like qmconf. - -The code that reads the registry to find MSVC components was borrowed -from distutils.msvccompiler. - -""" - -# -# Copyright (c) 2001 - 2015 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 - -__revision__ = "src/engine/SCons/Defaults.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - - -import os -import errno -import shutil -import stat -import time -import sys - -import SCons.Action -import SCons.Builder -import SCons.CacheDir -import SCons.Environment -import SCons.PathList -import SCons.Subst -import SCons.Tool - -# A placeholder for a default Environment (for fetching source files -# from source code management systems and the like). This must be -# initialized later, after the top-level directory is set by the calling -# interface. -_default_env = None - -# Lazily instantiate the default environment so the overhead of creating -# it doesn't apply when it's not needed. -def _fetch_DefaultEnvironment(*args, **kw): - """ - Returns the already-created default construction environment. - """ - global _default_env - return _default_env - -def DefaultEnvironment(*args, **kw): - """ - Initial public entry point for creating the default construction - Environment. - - After creating the environment, we overwrite our name - (DefaultEnvironment) with the _fetch_DefaultEnvironment() function, - which more efficiently returns the initialized default construction - environment without checking for its existence. - - (This function still exists with its _default_check because someone - else (*cough* Script/__init__.py *cough*) may keep a reference - to this function. So we can't use the fully functional idiom of - having the name originally be a something that *only* creates the - construction environment and then overwrites the name.) - """ - global _default_env - if not _default_env: - import SCons.Util - _default_env = SCons.Environment.Environment(*args, **kw) - if SCons.Util.md5: - _default_env.Decider('MD5') - else: - _default_env.Decider('timestamp-match') - global DefaultEnvironment - DefaultEnvironment = _fetch_DefaultEnvironment - _default_env._CacheDir_path = None - return _default_env - -# Emitters for setting the shared attribute on object files, -# and an action for checking that all of the source files -# going into a shared library are, in fact, shared. -def StaticObjectEmitter(target, source, env): - for tgt in target: - tgt.attributes.shared = None - return (target, source) - -def SharedObjectEmitter(target, source, env): - for tgt in target: - tgt.attributes.shared = 1 - return (target, source) - -def SharedFlagChecker(source, target, env): - same = env.subst('$STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME') - if same == '0' or same == '' or same == 'False': - for src in source: - try: - shared = src.attributes.shared - except AttributeError: - shared = None - if not shared: - raise SCons.Errors.UserError("Source file: %s is static and is not compatible with shared target: %s" % (src, target[0])) - -SharedCheck = SCons.Action.Action(SharedFlagChecker, None) - -# Some people were using these variable name before we made -# SourceFileScanner part of the public interface. Don't break their -# SConscript files until we've given them some fair warning and a -# transition period. -CScan = SCons.Tool.CScanner -DScan = SCons.Tool.DScanner -LaTeXScan = SCons.Tool.LaTeXScanner -ObjSourceScan = SCons.Tool.SourceFileScanner -ProgScan = SCons.Tool.ProgramScanner - -# These aren't really tool scanners, so they don't quite belong with -# the rest of those in Tool/__init__.py, but I'm not sure where else -# they should go. Leave them here for now. -import SCons.Scanner.Dir -DirScanner = SCons.Scanner.Dir.DirScanner() -DirEntryScanner = SCons.Scanner.Dir.DirEntryScanner() - -# Actions for common languages. -CAction = SCons.Action.Action("$CCCOM", "$CCCOMSTR") -ShCAction = SCons.Action.Action("$SHCCCOM", "$SHCCCOMSTR") -CXXAction = SCons.Action.Action("$CXXCOM", "$CXXCOMSTR") -ShCXXAction = SCons.Action.Action("$SHCXXCOM", "$SHCXXCOMSTR") - -DAction = SCons.Action.Action("$DCOM", "$DCOMSTR") -ShDAction = SCons.Action.Action("$SHDCOM", "$SHDCOMSTR") - -ASAction = SCons.Action.Action("$ASCOM", "$ASCOMSTR") -ASPPAction = SCons.Action.Action("$ASPPCOM", "$ASPPCOMSTR") - -LinkAction = SCons.Action.Action("$LINKCOM", "$LINKCOMSTR") -ShLinkAction = SCons.Action.Action("$SHLINKCOM", "$SHLINKCOMSTR") - -LdModuleLinkAction = SCons.Action.Action("$LDMODULECOM", "$LDMODULECOMSTR") - -# Common tasks that we allow users to perform in platform-independent -# ways by creating ActionFactory instances. -ActionFactory = SCons.Action.ActionFactory - -def get_paths_str(dest): - # If dest is a list, we need to manually call str() on each element - if SCons.Util.is_List(dest): - elem_strs = [] - for element in dest: - elem_strs.append('"' + str(element) + '"') - return '[' + ', '.join(elem_strs) + ']' - else: - return '"' + str(dest) + '"' - -def chmod_func(dest, mode): - SCons.Node.FS.invalidate_node_memos(dest) - if not SCons.Util.is_List(dest): - dest = [dest] - for element in dest: - os.chmod(str(element), mode) - -def chmod_strfunc(dest, mode): - return 'Chmod(%s, 0%o)' % (get_paths_str(dest), mode) - -Chmod = ActionFactory(chmod_func, chmod_strfunc) - -def copy_func(dest, src, symlinks=True): - """ - If symlinks (is true), then a symbolic link will be - shallow copied and recreated as a symbolic link; otherwise, copying - a symbolic link will be equivalent to copying the symbolic link's - final target regardless of symbolic link depth. - """ - - dest = str(dest) - src = str(src) - - SCons.Node.FS.invalidate_node_memos(dest) - if SCons.Util.is_List(src) and os.path.isdir(dest): - for file in src: - shutil.copy2(file, dest) - return 0 - elif os.path.islink(src): - if symlinks: - return os.symlink(os.readlink(src), dest) - else: - return copy_func(dest, os.path.realpath(src)) - elif os.path.isfile(src): - return shutil.copy2(src, dest) - else: - return shutil.copytree(src, dest, symlinks) - -Copy = ActionFactory( - copy_func, - lambda dest, src, symlinks=True: 'Copy("%s", "%s")' % (dest, src) -) - -def delete_func(dest, must_exist=0): - SCons.Node.FS.invalidate_node_memos(dest) - if not SCons.Util.is_List(dest): - dest = [dest] - for entry in dest: - entry = str(entry) - # os.path.exists returns False with broken links that exist - entry_exists = os.path.exists(entry) or os.path.islink(entry) - if not entry_exists and not must_exist: - continue - # os.path.isdir returns True when entry is a link to a dir - if os.path.isdir(entry) and not os.path.islink(entry): - shutil.rmtree(entry, 1) - continue - os.unlink(entry) - -def delete_strfunc(dest, must_exist=0): - return 'Delete(%s)' % get_paths_str(dest) - -Delete = ActionFactory(delete_func, delete_strfunc) - -def mkdir_func(dest): - SCons.Node.FS.invalidate_node_memos(dest) - if not SCons.Util.is_List(dest): - dest = [dest] - for entry in dest: - try: - os.makedirs(str(entry)) - except os.error, e: - p = str(entry) - if (e.args[0] == errno.EEXIST or - (sys.platform=='win32' and e.args[0]==183)) \ - and os.path.isdir(str(entry)): - pass # not an error if already exists - else: - raise - -Mkdir = ActionFactory(mkdir_func, - lambda dir: 'Mkdir(%s)' % get_paths_str(dir)) - -def move_func(dest, src): - SCons.Node.FS.invalidate_node_memos(dest) - SCons.Node.FS.invalidate_node_memos(src) - shutil.move(src, dest) - -Move = ActionFactory(move_func, - lambda dest, src: 'Move("%s", "%s")' % (dest, src), - convert=str) - -def touch_func(dest): - SCons.Node.FS.invalidate_node_memos(dest) - if not SCons.Util.is_List(dest): - dest = [dest] - for file in dest: - file = str(file) - mtime = int(time.time()) - if os.path.exists(file): - atime = os.path.getatime(file) - else: - open(file, 'w') - atime = mtime - os.utime(file, (atime, mtime)) - -Touch = ActionFactory(touch_func, - lambda file: 'Touch(%s)' % get_paths_str(file)) - -# 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 - in the list using the 'env' dictionary and then calling f on the - list, and finally calling _concat_ixes to concatenate 'prefix' and - 'suffix' onto each element of the list. - """ - if not list: - return list - - l = f(SCons.PathList.PathList(list).subst_path(env, target, source)) - if l is not None: - list = l - - 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 - 'suffix' arguments onto each element of the list. A trailing space - on 'prefix' or leading space on 'suffix' will cause them to be put - into separate list elements rather than being concatenated. - """ - - result = [] - - # ensure that prefix and suffix are strings - prefix = str(env.subst(prefix, SCons.Subst.SUBST_RAW)) - suffix = str(env.subst(suffix, SCons.Subst.SUBST_RAW)) - - for x in list: - if isinstance(x, SCons.Node.FS.File): - result.append(x) - continue - x = str(x) - if x: - - if prefix: - if prefix[-1] == ' ': - result.append(prefix[:-1]) - elif x[:len(prefix)] != prefix: - x = prefix + x - - result.append(x) - - if suffix: - if suffix[0] == ' ': - result.append(suffix[1:]) - elif x[-len(suffix):] != suffix: - result[-1] = result[-1]+suffix - - return result - -def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): - """ - This is a wrapper around _concat()/_concat_ixes() that checks for - the existence of prefixes or suffixes on list items and strips them - where it finds them. This is used by tools (like the GNU linker) - that need to turn something like 'libfoo.a' into '-lfoo'. - """ - - if not itms: - return itms - - if not callable(c): - env_c = env['_concat'] - if env_c != _concat and callable(env_c): - # There's a custom _concat() method in the construction - # environment, and we've allowed people to set that in - # the past (see test/custom-concat.py), so preserve the - # backwards compatibility. - c = env_c - else: - c = _concat_ixes - - stripprefixes = list(map(env.subst, SCons.Util.flatten(stripprefixes))) - stripsuffixes = list(map(env.subst, SCons.Util.flatten(stripsuffixes))) - - stripped = [] - for l in SCons.PathList.PathList(itms).subst_path(env, None, None): - if isinstance(l, SCons.Node.FS.File): - stripped.append(l) - continue - - if not SCons.Util.is_String(l): - l = str(l) - - for stripprefix in stripprefixes: - lsp = len(stripprefix) - if l[:lsp] == stripprefix: - l = l[lsp:] - # Do not strip more than one prefix - break - - for stripsuffix in stripsuffixes: - lss = len(stripsuffix) - if l[-lss:] == stripsuffix: - l = l[:-lss] - # Do not strip more than one suffix - break - - stripped.append(l) - - return c(prefix, stripped, suffix, env) - -def processDefines(defs): - """process defines, resolving strings, lists, dictionaries, into a list of - strings - """ - if SCons.Util.is_List(defs): - l = [] - for d in defs: - if d is None: - continue - elif SCons.Util.is_List(d) or isinstance(d, tuple): - if len(d) >= 2: - l.append(str(d[0]) + '=' + str(d[1])) - else: - l.append(str(d[0])) - elif SCons.Util.is_Dict(d): - for macro,value in d.iteritems(): - if value is not None: - l.append(str(macro) + '=' + str(value)) - else: - l.append(str(macro)) - elif SCons.Util.is_String(d): - l.append(str(d)) - else: - raise SCons.Errors.UserError("DEFINE %s is not a list, dict, string or None."%repr(d)) - elif SCons.Util.is_Dict(defs): - # The items in a dictionary are stored in random order, but - # if the order of the command-line options changes from - # invocation to invocation, then the signature of the command - # line will change and we'll get random unnecessary rebuilds. - # Consequently, we have to sort the keys to ensure a - # consistent order... - l = [] - for k,v in sorted(defs.items()): - if v is None: - l.append(str(k)) - else: - l.append(str(k) + '=' + str(v)) - else: - l = [str(defs)] - return l - -def _defines(prefix, defs, suffix, env, c=_concat_ixes): - """A wrapper around _concat_ixes that turns a list or string - into a list of C preprocessor command-line definitions. - """ - - return c(prefix, env.subst_path(processDefines(defs)), suffix, env) - -class NullCmdGenerator(object): - """This is a callable class that can be used in place of other - command generators if you don't want them to do anything. - - The __call__ method for this class simply returns the thing - you instantiated it with. - - Example usage: - env["DO_NOTHING"] = NullCmdGenerator - env["LINKCOM"] = "${DO_NOTHING('$LINK $SOURCES $TARGET')}" - """ - - def __init__(self, cmd): - self.cmd = cmd - - def __call__(self, target, source, env, for_signature=None): - return self.cmd - -class Variable_Method_Caller(object): - """A class for finding a construction variable on the stack and - calling one of its methods. - - We use this to support "construction variables" in our string - eval()s that actually stand in for methods--specifically, use - of "RDirs" in call to _concat that should actually execute the - "TARGET.RDirs" method. (We used to support this by creating a little - "build dictionary" that mapped RDirs to the method, but this got in - the way of Memoizing construction environments, because we had to - create new environment objects to hold the variables.) - """ - def __init__(self, variable, method): - self.variable = variable - self.method = method - def __call__(self, *args, **kw): - try: 1//0 - except ZeroDivisionError: - # Don't start iterating with the current stack-frame to - # prevent creating reference cycles (f_back is safe). - frame = sys.exc_info()[2].tb_frame.f_back - variable = self.variable - while frame: - if variable in frame.f_locals: - v = frame.f_locals[variable] - if v: - method = getattr(v, self.method) - return method(*args, **kw) - frame = frame.f_back - return None - -ConstructionEnvironment = { - 'BUILDERS' : {}, - 'SCANNERS' : [], - 'CONFIGUREDIR' : '#/.sconf_temp', - 'CONFIGURELOG' : '#/config.log', - 'CPPSUFFIXES' : SCons.Tool.CSuffixes, - '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, - '_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', - '_LIBDIRFLAGS' : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', - '_CPPINCFLAGS' : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', - '_CPPDEFFLAGS' : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', - 'TEMPFILE' : NullCmdGenerator, - 'Dir' : Variable_Method_Caller('TARGET', 'Dir'), - 'Dirs' : Variable_Method_Caller('TARGET', 'Dirs'), - 'File' : Variable_Method_Caller('TARGET', 'File'), - 'RDirs' : Variable_Method_Caller('TARGET', 'RDirs'), -} - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Environment.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Environment.py deleted file mode 100644 index 865c821..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Environment.py +++ /dev/null @@ -1,2448 +0,0 @@ -"""SCons.Environment - -Base class for construction Environments. These are -the primary objects used to communicate dependency and -construction information to the build engine. - -Keyword arguments supplied when the construction Environment -is created are construction variables used to initialize the -Environment -""" - -# -# Copyright (c) 2001 - 2015 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/Environment.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - - -import copy -import os -import sys -import re -import shlex -from collections import UserDict - -import SCons.Action -import SCons.Builder -import SCons.Debug -from SCons.Debug import logInstanceCreation -import SCons.Defaults -import SCons.Errors -import SCons.Memoize -import SCons.Node -import SCons.Node.Alias -import SCons.Node.FS -import SCons.Node.Python -import SCons.Platform -import SCons.SConf -import SCons.SConsign -import SCons.Subst -import SCons.Tool -import SCons.Util -import SCons.Warnings - -class _Null(object): - pass - -_null = _Null - -_warn_copy_deprecated = True -_warn_source_signatures_deprecated = True -_warn_target_signatures_deprecated = True - -CleanTargets = {} -CalculatorArgs = {} - -semi_deepcopy = SCons.Util.semi_deepcopy -semi_deepcopy_dict = SCons.Util.semi_deepcopy_dict - -# Pull UserError into the global name space for the benefit of -# Environment().SourceSignatures(), which has some import statements -# which seem to mess up its ability to reference SCons directly. -UserError = SCons.Errors.UserError - -def alias_builder(env, target, source): - pass - -AliasBuilder = SCons.Builder.Builder(action = alias_builder, - target_factory = SCons.Node.Alias.default_ans.Alias, - source_factory = SCons.Node.FS.Entry, - multi = 1, - is_explicit = None, - name='AliasBuilder') - -def apply_tools(env, tools, toolpath): - # Store the toolpath in the Environment. - if toolpath is not None: - env['toolpath'] = toolpath - - if not tools: - return - # Filter out null tools from the list. - for tool in [_f for _f in tools if _f]: - if SCons.Util.is_List(tool) or isinstance(tool, tuple): - toolname = tool[0] - toolargs = tool[1] # should be a dict of kw args - tool = env.Tool(toolname, **toolargs) - else: - env.Tool(tool) - -# These names are (or will be) controlled by SCons; users should never -# set or override them. This warning can optionally be turned off, -# but scons will still ignore the illegal variable names even if it's off. -reserved_construction_var_names = [ - 'CHANGED_SOURCES', - 'CHANGED_TARGETS', - 'SOURCE', - 'SOURCES', - 'TARGET', - 'TARGETS', - 'UNCHANGED_SOURCES', - 'UNCHANGED_TARGETS', -] - -future_reserved_construction_var_names = [ - #'HOST_OS', - #'HOST_ARCH', - #'HOST_CPU', - ] - -def copy_non_reserved_keywords(dict): - result = semi_deepcopy(dict) - for k in result.keys(): - if k in reserved_construction_var_names: - msg = "Ignoring attempt to set reserved variable `$%s'" - SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg % k) - del result[k] - return result - -def _set_reserved(env, key, value): - msg = "Ignoring attempt to set reserved variable `$%s'" - SCons.Warnings.warn(SCons.Warnings.ReservedVariableWarning, msg % key) - -def _set_future_reserved(env, key, value): - env._dict[key] = value - msg = "`$%s' will be reserved in a future release and setting it will become ignored" - SCons.Warnings.warn(SCons.Warnings.FutureReservedVariableWarning, msg % key) - -def _set_BUILDERS(env, key, value): - try: - bd = env._dict[key] - for k in bd.keys(): - del bd[k] - except KeyError: - bd = BuilderDict(kwbd, env) - env._dict[key] = bd - for k, v in value.items(): - if not SCons.Builder.is_a_Builder(v): - raise SCons.Errors.UserError('%s is not a Builder.' % repr(v)) - bd.update(value) - -def _del_SCANNERS(env, key): - del env._dict[key] - env.scanner_map_delete() - -def _set_SCANNERS(env, key, value): - env._dict[key] = value - env.scanner_map_delete() - -def _delete_duplicates(l, keep_last): - """Delete duplicates from a sequence, keeping the first or last.""" - seen={} - result=[] - if keep_last: # reverse in & out, then keep first - l.reverse() - for i in l: - try: - if i not in seen: - result.append(i) - seen[i]=1 - except TypeError: - # probably unhashable. Just keep it. - result.append(i) - if keep_last: - result.reverse() - return result - - - -# The following is partly based on code in a comment added by Peter -# Shannon at the following page (there called the "transplant" class): -# -# ASPN : Python Cookbook : Dynamically added methods to a class -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/81732 -# -# We had independently been using the idiom as BuilderWrapper, but -# factoring out the common parts into this base class, and making -# BuilderWrapper a subclass that overrides __call__() to enforce specific -# Builder calling conventions, simplified some of our higher-layer code. - -class MethodWrapper(object): - """ - A generic Wrapper class that associates a method (which can - actually be any callable) with an object. As part of creating this - MethodWrapper object an attribute with the specified (by default, - the name of the supplied method) is added to the underlying object. - When that new "method" is called, our __call__() method adds the - object as the first argument, simulating the Python behavior of - supplying "self" on method calls. - - We hang on to the name by which the method was added to the underlying - base class so that we can provide a method to "clone" ourselves onto - a new underlying object being copied (without which we wouldn't need - to save that info). - """ - def __init__(self, object, method, name=None): - if name is None: - name = method.__name__ - self.object = object - self.method = method - self.name = name - setattr(self.object, name, self) - - def __call__(self, *args, **kwargs): - nargs = (self.object,) + args - return self.method(*nargs, **kwargs) - - def clone(self, new_object): - """ - Returns an object that re-binds the underlying "method" to - the specified new object. - """ - return self.__class__(new_object, self.method, self.name) - -class BuilderWrapper(MethodWrapper): - """ - A MethodWrapper subclass that that associates an environment with - a Builder. - - This mainly exists to wrap the __call__() function so that all calls - to Builders can have their argument lists massaged in the same way - (treat a lone argument as the source, treat two arguments as target - then source, make sure both target and source are lists) without - having to have cut-and-paste code to do it. - - As a bit of obsessive backwards compatibility, we also intercept - attempts to get or set the "env" or "builder" attributes, which were - the names we used before we put the common functionality into the - MethodWrapper base class. We'll keep this around for a while in case - people shipped Tool modules that reached into the wrapper (like the - Tool/qt.py module does, or did). There shouldn't be a lot attribute - fetching or setting on these, so a little extra work shouldn't hurt. - """ - def __call__(self, target=None, source=_null, *args, **kw): - if source is _null: - source = target - target = None - if target is not None and not SCons.Util.is_List(target): - target = [target] - if source is not None and not SCons.Util.is_List(source): - source = [source] - return MethodWrapper.__call__(self, target, source, *args, **kw) - - def __repr__(self): - return '' % repr(self.name) - - def __str__(self): - return self.__repr__() - - def __getattr__(self, name): - if name == 'env': - return self.object - elif name == 'builder': - return self.method - else: - raise AttributeError(name) - - def __setattr__(self, name, value): - if name == 'env': - self.object = value - elif name == 'builder': - self.method = value - else: - self.__dict__[name] = value - - # This allows a Builder to be executed directly - # through the Environment to which it's attached. - # In practice, we shouldn't need this, because - # builders actually get executed through a Node. - # But we do have a unit test for this, and can't - # yet rule out that it would be useful in the - # future, so leave it for now. - #def execute(self, **kw): - # kw['env'] = self.env - # self.builder.execute(**kw) - -class BuilderDict(UserDict): - """This is a dictionary-like class used by an Environment to hold - the Builders. We need to do this because every time someone changes - the Builders in the Environment's BUILDERS dictionary, we must - update the Environment's attributes.""" - def __init__(self, dict, env): - # Set self.env before calling the superclass initialization, - # because it will end up calling our other methods, which will - # need to point the values in this dictionary to self.env. - self.env = env - UserDict.__init__(self, dict) - - def __semi_deepcopy__(self): - # These cannot be copied since they would both modify the same builder object, and indeed - # just copying would modify the original builder - raise TypeError( 'cannot semi_deepcopy a BuilderDict' ) - - def __setitem__(self, item, val): - try: - method = getattr(self.env, item).method - except AttributeError: - pass - else: - self.env.RemoveMethod(method) - UserDict.__setitem__(self, item, val) - BuilderWrapper(self.env, val, item) - - def __delitem__(self, item): - UserDict.__delitem__(self, item) - delattr(self.env, item) - - def update(self, dict): - for i, v in dict.items(): - self.__setitem__(i, v) - - - -_is_valid_var = re.compile(r'[_a-zA-Z]\w*$') - -def is_valid_construction_var(varstr): - """Return if the specified string is a legitimate construction - variable. - """ - return _is_valid_var.match(varstr) - - - -class SubstitutionEnvironment(object): - """Base class for different flavors of construction environments. - - This class contains a minimal set of methods that handle contruction - variable expansion and conversion of strings to Nodes, which may or - may not be actually useful as a stand-alone class. Which methods - ended up in this class is pretty arbitrary right now. They're - basically the ones which we've empirically determined are common to - the different construction environment subclasses, and most of the - others that use or touch the underlying dictionary of construction - variables. - - Eventually, this class should contain all the methods that we - determine are necessary for a "minimal" interface to the build engine. - A full "native Python" SCons environment has gotten pretty heavyweight - with all of the methods and Tools and construction variables we've - jammed in there, so it would be nice to have a lighter weight - alternative for interfaces that don't need all of the bells and - whistles. (At some point, we'll also probably rename this class - "Base," since that more reflects what we want this class to become, - but because we've released comments that tell people to subclass - Environment.Base to create their own flavors of construction - environment, we'll save that for a future refactoring when this - class actually becomes useful.) - """ - - def __init__(self, **kw): - """Initialization of an underlying SubstitutionEnvironment class. - """ - if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.SubstitutionEnvironment') - self.fs = SCons.Node.FS.get_default_fs() - self.ans = SCons.Node.Alias.default_ans - self.lookup_list = SCons.Node.arg2nodes_lookups - self._dict = kw.copy() - self._init_special() - self.added_methods = [] - #self._memo = {} - - def _init_special(self): - """Initial the dispatch tables for special handling of - special construction variables.""" - self._special_del = {} - self._special_del['SCANNERS'] = _del_SCANNERS - - self._special_set = {} - for key in reserved_construction_var_names: - self._special_set[key] = _set_reserved - for key in future_reserved_construction_var_names: - self._special_set[key] = _set_future_reserved - self._special_set['BUILDERS'] = _set_BUILDERS - self._special_set['SCANNERS'] = _set_SCANNERS - - # Freeze the keys of self._special_set in a list for use by - # methods that need to check. (Empirically, list scanning has - # gotten better than dict.has_key() in Python 2.5.) - self._special_set_keys = list(self._special_set.keys()) - - def __cmp__(self, other): - return cmp(self._dict, other._dict) - - def __delitem__(self, key): - special = self._special_del.get(key) - if special: - special(self, key) - else: - del self._dict[key] - - def __getitem__(self, key): - return self._dict[key] - - def __setitem__(self, key, value): - # This is heavily used. This implementation is the best we have - # according to the timings in bench/env.__setitem__.py. - # - # The "key in self._special_set_keys" test here seems to perform - # pretty well for the number of keys we have. A hard-coded - # list works a little better in Python 2.5, but that has the - # disadvantage of maybe getting out of sync if we ever add more - # variable names. Using self._special_set.has_key() works a - # little better in Python 2.4, but is worse than this test. - # So right now it seems like a good trade-off, but feel free to - # revisit this with bench/env.__setitem__.py as needed (and - # as newer versions of Python come out). - if key in self._special_set_keys: - self._special_set[key](self, key, value) - else: - # If we already have the entry, then it's obviously a valid - # key and we don't need to check. If we do check, using a - # global, pre-compiled regular expression directly is more - # efficient than calling another function or a method. - if key not in self._dict \ - and not _is_valid_var.match(key): - raise SCons.Errors.UserError("Illegal construction variable `%s'" % key) - self._dict[key] = value - - def get(self, key, default=None): - """Emulates the get() method of dictionaries.""" - return self._dict.get(key, default) - - def has_key(self, key): - return key in self._dict - - def __contains__(self, key): - return self._dict.__contains__(key) - - def items(self): - return list(self._dict.items()) - - def arg2nodes(self, args, node_factory=_null, lookup_list=_null, **kw): - if node_factory is _null: - node_factory = self.fs.File - if lookup_list is _null: - lookup_list = self.lookup_list - - if not args: - return [] - - args = SCons.Util.flatten(args) - - nodes = [] - for v in args: - if SCons.Util.is_String(v): - n = None - for l in lookup_list: - n = l(v) - if n is not None: - break - if n is not None: - if SCons.Util.is_String(n): - # n = self.subst(n, raw=1, **kw) - kw['raw'] = 1 - n = self.subst(n, **kw) - if node_factory: - n = node_factory(n) - if SCons.Util.is_List(n): - nodes.extend(n) - else: - nodes.append(n) - elif node_factory: - # v = node_factory(self.subst(v, raw=1, **kw)) - kw['raw'] = 1 - v = node_factory(self.subst(v, **kw)) - if SCons.Util.is_List(v): - nodes.extend(v) - else: - nodes.append(v) - else: - nodes.append(v) - - return nodes - - def gvars(self): - return self._dict - - def lvars(self): - return {} - - def subst(self, string, raw=0, target=None, source=None, conv=None, executor=None): - """Recursively interpolates construction variables from the - Environment into the specified string, returning the expanded - result. Construction variables are specified by a $ prefix - in the string and begin with an initial underscore or - alphabetic character followed by any number of underscores - or alphanumeric characters. The construction variable names - may be surrounded by curly braces to separate the name from - trailing characters. - """ - gvars = self.gvars() - lvars = self.lvars() - lvars['__env__'] = self - if executor: - lvars.update(executor.get_lvars()) - return SCons.Subst.scons_subst(string, self, raw, target, source, gvars, lvars, conv) - - def subst_kw(self, kw, raw=0, target=None, source=None): - nkw = {} - for k, v in kw.items(): - k = self.subst(k, raw, target, source) - if SCons.Util.is_String(v): - v = self.subst(v, raw, target, source) - nkw[k] = v - return nkw - - def subst_list(self, string, raw=0, target=None, source=None, conv=None, executor=None): - """Calls through to SCons.Subst.scons_subst_list(). See - the documentation for that function.""" - gvars = self.gvars() - lvars = self.lvars() - lvars['__env__'] = self - if executor: - lvars.update(executor.get_lvars()) - return SCons.Subst.scons_subst_list(string, self, raw, target, source, gvars, lvars, conv) - - def subst_path(self, path, target=None, source=None): - """Substitute a path list, turning EntryProxies into Nodes - and leaving Nodes (and other objects) as-is.""" - - if not SCons.Util.is_List(path): - path = [path] - - def s(obj): - """This is the "string conversion" routine that we have our - substitutions use to return Nodes, not strings. This relies - on the fact that an EntryProxy object has a get() method that - returns the underlying Node that it wraps, which is a bit of - architectural dependence that we might need to break or modify - in the future in response to additional requirements.""" - try: - get = obj.get - except AttributeError: - obj = SCons.Util.to_String_for_subst(obj) - else: - obj = get() - return obj - - r = [] - for p in path: - if SCons.Util.is_String(p): - p = self.subst(p, target=target, source=source, conv=s) - if SCons.Util.is_List(p): - if len(p) == 1: - p = p[0] - else: - # We have an object plus a string, or multiple - # objects that we need to smush together. No choice - # but to make them into a string. - p = ''.join(map(SCons.Util.to_String_for_subst, p)) - else: - p = s(p) - r.append(p) - return r - - subst_target_source = subst - - def backtick(self, command): - import subprocess - # common arguments - kw = { 'stdin' : 'devnull', - 'stdout' : subprocess.PIPE, - 'stderr' : subprocess.PIPE, - 'universal_newlines' : True, - } - # if the command is a list, assume it's been quoted - # othewise force a shell - if not SCons.Util.is_List(command): kw['shell'] = True - # run constructed command - p = SCons.Action._subproc(self, command, **kw) - out,err = p.communicate() - status = p.wait() - if err: - sys.stderr.write(unicode(err)) - if status: - raise OSError("'%s' exited %d" % (command, status)) - return out - - def AddMethod(self, function, name=None): - """ - Adds the specified function as a method of this construction - environment with the specified name. If the name is omitted, - the default name is the name of the function itself. - """ - method = MethodWrapper(self, function, name) - self.added_methods.append(method) - - def RemoveMethod(self, function): - """ - Removes the specified function's MethodWrapper from the - added_methods list, so we don't re-bind it when making a clone. - """ - self.added_methods = [dm for dm in self.added_methods if not dm.method is function] - - def Override(self, overrides): - """ - Produce a modified environment whose variables are overriden by - the overrides dictionaries. "overrides" is a dictionary that - will override the variables of this environment. - - This function is much more efficient than Clone() or creating - a new Environment because it doesn't copy the construction - environment dictionary, it just wraps the underlying construction - environment, and doesn't even create a wrapper object if there - are no overrides. - """ - if not overrides: return self - o = copy_non_reserved_keywords(overrides) - if not o: return self - overrides = {} - merges = None - for key, value in o.items(): - if key == 'parse_flags': - merges = value - else: - overrides[key] = SCons.Subst.scons_subst_once(value, self, key) - env = OverrideEnvironment(self, overrides) - if merges: env.MergeFlags(merges) - return env - - def ParseFlags(self, *flags): - """ - Parse the set of flags and return a dict with the flags placed - in the appropriate entry. The flags are treated as a typical - set of command-line flags for a GNU-like toolchain and used to - populate the entries in the dict immediately below. If one of - the flag strings begins with a bang (exclamation mark), it is - assumed to be a command and the rest of the string is executed; - the result of that evaluation is then added to the dict. - """ - dict = { - 'ASFLAGS' : SCons.Util.CLVar(''), - 'CFLAGS' : SCons.Util.CLVar(''), - 'CCFLAGS' : SCons.Util.CLVar(''), - 'CXXFLAGS' : SCons.Util.CLVar(''), - 'CPPDEFINES' : [], - 'CPPFLAGS' : SCons.Util.CLVar(''), - 'CPPPATH' : [], - 'FRAMEWORKPATH' : SCons.Util.CLVar(''), - 'FRAMEWORKS' : SCons.Util.CLVar(''), - 'LIBPATH' : [], - 'LIBS' : [], - 'LINKFLAGS' : SCons.Util.CLVar(''), - 'RPATH' : [], - } - - def do_parse(arg): - # if arg is a sequence, recurse with each element - if not arg: - return - - if not SCons.Util.is_String(arg): - for t in arg: do_parse(t) - return - - # if arg is a command, execute it - if arg[0] == '!': - arg = self.backtick(arg[1:]) - - # utility function to deal with -D option - def append_define(name, dict = dict): - t = name.split('=') - if len(t) == 1: - dict['CPPDEFINES'].append(name) - else: - dict['CPPDEFINES'].append([t[0], '='.join(t[1:])]) - - # Loop through the flags and add them to the appropriate option. - # This tries to strike a balance between checking for all possible - # flags and keeping the logic to a finite size, so it doesn't - # check for some that don't occur often. It particular, if the - # flag is not known to occur in a config script and there's a way - # of passing the flag to the right place (by wrapping it in a -W - # flag, for example) we don't check for it. Note that most - # preprocessor options are not handled, since unhandled options - # are placed in CCFLAGS, so unless the preprocessor is invoked - # separately, these flags will still get to the preprocessor. - # Other options not currently handled: - # -iqoutedir (preprocessor search path) - # -u symbol (linker undefined symbol) - # -s (linker strip files) - # -static* (linker static binding) - # -shared* (linker dynamic binding) - # -symbolic (linker global binding) - # -R dir (deprecated linker rpath) - # IBM compilers may also accept -qframeworkdir=foo - - params = shlex.split(arg) - append_next_arg_to = None # for multi-word args - for arg in params: - if append_next_arg_to: - if append_next_arg_to == 'CPPDEFINES': - append_define(arg) - elif append_next_arg_to == '-include': - t = ('-include', self.fs.File(arg)) - dict['CCFLAGS'].append(t) - elif append_next_arg_to == '-isysroot': - t = ('-isysroot', arg) - dict['CCFLAGS'].append(t) - dict['LINKFLAGS'].append(t) - elif append_next_arg_to == '-isystem': - t = ('-isystem', arg) - dict['CCFLAGS'].append(t) - elif append_next_arg_to == '-arch': - t = ('-arch', arg) - dict['CCFLAGS'].append(t) - dict['LINKFLAGS'].append(t) - else: - dict[append_next_arg_to].append(arg) - append_next_arg_to = None - elif not arg[0] in ['-', '+']: - dict['LIBS'].append(self.fs.File(arg)) - elif arg == '-dylib_file': - dict['LINKFLAGS'].append(arg) - append_next_arg_to = 'LINKFLAGS' - elif arg[:2] == '-L': - if arg[2:]: - dict['LIBPATH'].append(arg[2:]) - else: - append_next_arg_to = 'LIBPATH' - elif arg[:2] == '-l': - if arg[2:]: - dict['LIBS'].append(arg[2:]) - else: - append_next_arg_to = 'LIBS' - elif arg[:2] == '-I': - if arg[2:]: - dict['CPPPATH'].append(arg[2:]) - else: - append_next_arg_to = 'CPPPATH' - elif arg[:4] == '-Wa,': - dict['ASFLAGS'].append(arg[4:]) - dict['CCFLAGS'].append(arg) - elif arg[:4] == '-Wl,': - if arg[:11] == '-Wl,-rpath=': - dict['RPATH'].append(arg[11:]) - elif arg[:7] == '-Wl,-R,': - dict['RPATH'].append(arg[7:]) - elif arg[:6] == '-Wl,-R': - dict['RPATH'].append(arg[6:]) - else: - dict['LINKFLAGS'].append(arg) - elif arg[:4] == '-Wp,': - dict['CPPFLAGS'].append(arg) - elif arg[:2] == '-D': - if arg[2:]: - append_define(arg[2:]) - else: - append_next_arg_to = 'CPPDEFINES' - elif arg == '-framework': - append_next_arg_to = 'FRAMEWORKS' - elif arg[:14] == '-frameworkdir=': - dict['FRAMEWORKPATH'].append(arg[14:]) - elif arg[:2] == '-F': - if arg[2:]: - dict['FRAMEWORKPATH'].append(arg[2:]) - else: - append_next_arg_to = 'FRAMEWORKPATH' - elif arg in ['-mno-cygwin', - '-pthread', - '-openmp', - '-fopenmp']: - dict['CCFLAGS'].append(arg) - dict['LINKFLAGS'].append(arg) - elif arg == '-mwindows': - dict['LINKFLAGS'].append(arg) - elif arg[:5] == '-std=': - if arg[5:].find('++')!=-1: - key='CXXFLAGS' - else: - key='CFLAGS' - dict[key].append(arg) - elif arg[0] == '+': - dict['CCFLAGS'].append(arg) - dict['LINKFLAGS'].append(arg) - elif arg in ['-include', '-isysroot', '-isystem', '-arch']: - append_next_arg_to = arg - else: - dict['CCFLAGS'].append(arg) - - for arg in flags: - do_parse(arg) - return dict - - def MergeFlags(self, args, unique=1, dict=None): - """ - Merge the dict in args into the construction variables of this - env, or the passed-in dict. If args is not a dict, it is - converted into a dict using ParseFlags. If unique is not set, - the flags are appended rather than merged. - """ - - if dict is None: - dict = self - if not SCons.Util.is_Dict(args): - args = self.ParseFlags(args) - if not unique: - self.Append(**args) - return self - for key, value in args.items(): - if not value: - continue - try: - orig = self[key] - except KeyError: - orig = value - else: - if not orig: - orig = value - elif value: - # Add orig and value. The logic here was lifted from - # part of env.Append() (see there for a lot of comments - # about the order in which things are tried) and is - # used mainly to handle coercion of strings to CLVar to - # "do the right thing" given (e.g.) an original CCFLAGS - # string variable like '-pipe -Wall'. - try: - orig = orig + value - except (KeyError, TypeError): - try: - add_to_orig = orig.append - except AttributeError: - value.insert(0, orig) - orig = value - else: - add_to_orig(value) - t = [] - if key[-4:] == 'PATH': - ### keep left-most occurence - for v in orig: - if v not in t: - t.append(v) - else: - ### keep right-most occurence - orig.reverse() - for v in orig: - if v not in t: - t.insert(0, v) - self[key] = t - return self - -# def MergeShellPaths(self, args, prepend=1): -# """ -# Merge the dict in args into the shell environment in env['ENV']. -# Shell path elements are appended or prepended according to prepend. - -# Uses Pre/AppendENVPath, so it always appends or prepends uniquely. - -# Example: env.MergeShellPaths({'LIBPATH': '/usr/local/lib'}) -# prepends /usr/local/lib to env['ENV']['LIBPATH']. -# """ - -# for pathname, pathval in args.items(): -# if not pathval: -# continue -# if prepend: -# self.PrependENVPath(pathname, pathval) -# else: -# self.AppendENVPath(pathname, pathval) - - -def default_decide_source(dependency, target, prev_ni): - f = SCons.Defaults.DefaultEnvironment().decide_source - return f(dependency, target, prev_ni) - -def default_decide_target(dependency, target, prev_ni): - f = SCons.Defaults.DefaultEnvironment().decide_target - return f(dependency, target, prev_ni) - -def default_copy_from_cache(src, dst): - f = SCons.Defaults.DefaultEnvironment().copy_from_cache - return f(src, dst) - -class Base(SubstitutionEnvironment): - """Base class for "real" construction Environments. These are the - primary objects used to communicate dependency and construction - information to the build engine. - - Keyword arguments supplied when the construction Environment - is created are construction variables used to initialize the - Environment. - """ - - ####################################################################### - # This is THE class for interacting with the SCons build engine, - # and it contains a lot of stuff, so we're going to try to keep this - # a little organized by grouping the methods. - ####################################################################### - - ####################################################################### - # Methods that make an Environment act like a dictionary. These have - # the expected standard names for Python mapping objects. Note that - # we don't actually make an Environment a subclass of UserDict for - # performance reasons. Note also that we only supply methods for - # dictionary functionality that we actually need and use. - ####################################################################### - - def __init__(self, - platform=None, - tools=None, - toolpath=None, - variables=None, - parse_flags = None, - **kw): - """ - Initialization of a basic SCons construction environment, - including setting up special construction variables like BUILDER, - PLATFORM, etc., and searching for and applying available Tools. - - Note that we do *not* call the underlying base class - (SubsitutionEnvironment) initialization, because we need to - initialize things in a very specific order that doesn't work - with the much simpler base class initialization. - """ - if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.Base') - self._memo = {} - self.fs = SCons.Node.FS.get_default_fs() - self.ans = SCons.Node.Alias.default_ans - self.lookup_list = SCons.Node.arg2nodes_lookups - self._dict = semi_deepcopy(SCons.Defaults.ConstructionEnvironment) - self._init_special() - self.added_methods = [] - - # We don't use AddMethod, or define these as methods in this - # class, because we *don't* want these functions to be bound - # methods. They need to operate independently so that the - # settings will work properly regardless of whether a given - # target ends up being built with a Base environment or an - # OverrideEnvironment or what have you. - self.decide_target = default_decide_target - self.decide_source = default_decide_source - - self.copy_from_cache = default_copy_from_cache - - self._dict['BUILDERS'] = BuilderDict(self._dict['BUILDERS'], self) - - if platform is None: - platform = self._dict.get('PLATFORM', None) - if platform is None: - platform = SCons.Platform.Platform() - if SCons.Util.is_String(platform): - platform = SCons.Platform.Platform(platform) - self._dict['PLATFORM'] = str(platform) - platform(self) - - self._dict['HOST_OS'] = self._dict.get('HOST_OS',None) - self._dict['HOST_ARCH'] = self._dict.get('HOST_ARCH',None) - - # Now set defaults for TARGET_{OS|ARCH} - self._dict['TARGET_OS'] = self._dict.get('TARGET_OS',None) - self._dict['TARGET_ARCH'] = self._dict.get('TARGET_ARCH',None) - - - # Apply the passed-in and customizable variables to the - # environment before calling the tools, because they may use - # some of them during initialization. - if 'options' in kw: - # Backwards compatibility: they may stll be using the - # old "options" keyword. - variables = kw['options'] - del kw['options'] - self.Replace(**kw) - keys = list(kw.keys()) - if variables: - keys = keys + list(variables.keys()) - variables.Update(self) - - save = {} - for k in keys: - try: - save[k] = self._dict[k] - except KeyError: - # No value may have been set if they tried to pass in a - # reserved variable name like TARGETS. - pass - - SCons.Tool.Initializers(self) - - if tools is None: - tools = self._dict.get('TOOLS', None) - if tools is None: - tools = ['default'] - apply_tools(self, tools, toolpath) - - # Now restore the passed-in and customized variables - # to the environment, since the values the user set explicitly - # should override any values set by the tools. - for key, val in save.items(): - self._dict[key] = val - - # Finally, apply any flags to be merged in - if parse_flags: self.MergeFlags(parse_flags) - - ####################################################################### - # Utility methods that are primarily for internal use by SCons. - # These begin with lower-case letters. - ####################################################################### - - def get_builder(self, name): - """Fetch the builder with the specified name from the environment. - """ - try: - return self._dict['BUILDERS'][name] - except KeyError: - return None - - def get_CacheDir(self): - try: - path = self._CacheDir_path - except AttributeError: - path = SCons.Defaults.DefaultEnvironment()._CacheDir_path - try: - if path == self._last_CacheDir_path: - return self._last_CacheDir - except AttributeError: - pass - cd = SCons.CacheDir.CacheDir(path) - self._last_CacheDir_path = path - self._last_CacheDir = cd - return cd - - def get_factory(self, factory, default='File'): - """Return a factory function for creating Nodes for this - construction environment. - """ - name = default - try: - is_node = issubclass(factory, SCons.Node.FS.Base) - except TypeError: - # The specified factory isn't a Node itself--it's - # most likely None, or possibly a callable. - pass - else: - if is_node: - # The specified factory is a Node (sub)class. Try to - # return the FS method that corresponds to the Node's - # name--that is, we return self.fs.Dir if they want a Dir, - # self.fs.File for a File, etc. - try: name = factory.__name__ - except AttributeError: pass - else: factory = None - if not factory: - # They passed us None, or we picked up a name from a specified - # class, so return the FS method. (Note that we *don't* - # use our own self.{Dir,File} methods because that would - # cause env.subst() to be called twice on the file name, - # interfering with files that have $$ in them.) - factory = getattr(self.fs, name) - return factory - - @SCons.Memoize.CountMethodCall - def _gsm(self): - try: - return self._memo['_gsm'] - except KeyError: - pass - - result = {} - - try: - scanners = self._dict['SCANNERS'] - except KeyError: - pass - else: - # Reverse the scanner list so that, if multiple scanners - # claim they can scan the same suffix, earlier scanners - # in the list will overwrite later scanners, so that - # the result looks like a "first match" to the user. - if not SCons.Util.is_List(scanners): - scanners = [scanners] - else: - scanners = scanners[:] # copy so reverse() doesn't mod original - scanners.reverse() - for scanner in scanners: - for k in scanner.get_skeys(self): - if k and self['PLATFORM'] == 'win32': - k = k.lower() - result[k] = scanner - - self._memo['_gsm'] = result - - return result - - def get_scanner(self, skey): - """Find the appropriate scanner given a key (usually a file suffix). - """ - if skey and self['PLATFORM'] == 'win32': - skey = skey.lower() - return self._gsm().get(skey) - - def scanner_map_delete(self, kw=None): - """Delete the cached scanner map (if we need to). - """ - try: - del self._memo['_gsm'] - except KeyError: - pass - - def _update(self, dict): - """Update an environment's values directly, bypassing the normal - checks that occur when users try to set items. - """ - self._dict.update(dict) - - def get_src_sig_type(self): - try: - return self.src_sig_type - except AttributeError: - t = SCons.Defaults.DefaultEnvironment().src_sig_type - self.src_sig_type = t - return t - - def get_tgt_sig_type(self): - try: - return self.tgt_sig_type - except AttributeError: - t = SCons.Defaults.DefaultEnvironment().tgt_sig_type - self.tgt_sig_type = t - return t - - ####################################################################### - # Public methods for manipulating an Environment. These begin with - # upper-case letters. The essential characteristic of methods in - # this section is that they do *not* have corresponding same-named - # global functions. For example, a stand-alone Append() function - # makes no sense, because Append() is all about appending values to - # an Environment's construction variables. - ####################################################################### - - def Append(self, **kw): - """Append values to existing construction variables - in an Environment. - """ - kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): - # It would be easier on the eyes to write this using - # "continue" statements whenever we finish processing an item, - # but Python 1.5.2 apparently doesn't let you use "continue" - # within try:-except: blocks, so we have to nest our code. - try: - if key == 'CPPDEFINES' and SCons.Util.is_String(self._dict[key]): - self._dict[key] = [self._dict[key]] - orig = self._dict[key] - except KeyError: - # No existing variable in the environment, so just set - # it to the new value. - if key == 'CPPDEFINES' and SCons.Util.is_String(val): - self._dict[key] = [val] - else: - self._dict[key] = val - else: - try: - # Check if the original looks like a dictionary. - # If it is, we can't just try adding the value because - # dictionaries don't have __add__() methods, and - # things like UserList will incorrectly coerce the - # original dict to a list (which we don't want). - update_dict = orig.update - except AttributeError: - try: - # Most straightforward: just try to add them - # together. This will work in most cases, when the - # original and new values are of compatible types. - self._dict[key] = orig + val - except (KeyError, TypeError): - try: - # Check if the original is a list. - add_to_orig = orig.append - except AttributeError: - # The original isn't a list, but the new - # value is (by process of elimination), - # so insert the original in the new value - # (if there's one to insert) and replace - # the variable with it. - if orig: - val.insert(0, orig) - self._dict[key] = val - else: - # The original is a list, so append the new - # value to it (if there's a value to append). - if val: - add_to_orig(val) - else: - # The original looks like a dictionary, so update it - # based on what we think the value looks like. - if SCons.Util.is_List(val): - if key == 'CPPDEFINES': - tmp = [] - for (k, v) in orig.iteritems(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - orig = tmp - orig += val - self._dict[key] = orig - else: - for v in val: - orig[v] = None - else: - try: - update_dict(val) - except (AttributeError, TypeError, ValueError): - if SCons.Util.is_Dict(val): - for k, v in val.items(): - orig[k] = v - else: - orig[val] = None - self.scanner_map_delete(kw) - - # allow Dirs and strings beginning with # for top-relative - # Note this uses the current env's fs (in self). - def _canonicalize(self, path): - if not SCons.Util.is_String(path): # typically a Dir - path = str(path) - if path and path[0] == '#': - path = str(self.fs.Dir(path)) - return path - - def AppendENVPath(self, name, newpath, envname = 'ENV', - sep = os.pathsep, delete_existing=1): - """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 - assure this. This can also handle the case where the env - variable is a list instead of a string. - - If delete_existing is 0, a newpath which is already in the path - will not be moved to the end (it will be left where it is). - """ - - orig = '' - if envname in self._dict and name in self._dict[envname]: - orig = self._dict[envname][name] - - nv = SCons.Util.AppendPath(orig, newpath, sep, delete_existing, - canonicalize=self._canonicalize) - - if envname not in self._dict: - self._dict[envname] = {} - - self._dict[envname][name] = nv - - def AppendUnique(self, delete_existing=0, **kw): - """Append values to existing construction variables - in an Environment, if they're not already there. - If delete_existing is 1, removes existing values first, so - values move to end. - """ - kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): - if SCons.Util.is_List(val): - val = _delete_duplicates(val, delete_existing) - if key not in self._dict or self._dict[key] in ('', None): - self._dict[key] = val - elif SCons.Util.is_Dict(self._dict[key]) and \ - SCons.Util.is_Dict(val): - self._dict[key].update(val) - elif SCons.Util.is_List(val): - dk = self._dict[key] - if key == 'CPPDEFINES': - tmp = [] - for i in val: - if SCons.Util.is_List(i): - if len(i) >= 2: - tmp.append((i[0], i[1])) - else: - tmp.append((i[0],)) - elif SCons.Util.is_Tuple(i): - tmp.append(i) - else: - tmp.append((i,)) - val = tmp - # Construct a list of (key, value) tuples. - if SCons.Util.is_Dict(dk): - tmp = [] - for (k, v) in dk.iteritems(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - dk = tmp - elif SCons.Util.is_String(dk): - dk = [(dk,)] - else: - tmp = [] - for i in dk: - if SCons.Util.is_List(i): - if len(i) >= 2: - tmp.append((i[0], i[1])) - else: - tmp.append((i[0],)) - elif SCons.Util.is_Tuple(i): - tmp.append(i) - else: - tmp.append((i,)) - dk = tmp - else: - if not SCons.Util.is_List(dk): - dk = [dk] - if delete_existing: - dk = [x for x in dk if x not in val] - else: - val = [x for x in val if x not in dk] - self._dict[key] = dk + val - else: - dk = self._dict[key] - if SCons.Util.is_List(dk): - if key == 'CPPDEFINES': - tmp = [] - for i in dk: - if SCons.Util.is_List(i): - if len(i) >= 2: - tmp.append((i[0], i[1])) - else: - tmp.append((i[0],)) - elif SCons.Util.is_Tuple(i): - tmp.append(i) - else: - tmp.append((i,)) - dk = tmp - # Construct a list of (key, value) tuples. - if SCons.Util.is_Dict(val): - tmp = [] - for (k, v) in val.iteritems(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - val = tmp - elif SCons.Util.is_String(val): - val = [(val,)] - if delete_existing: - dk = filter(lambda x, val=val: x not in val, dk) - self._dict[key] = dk + val - else: - dk = [x for x in dk if x not in val] - self._dict[key] = dk + val - else: - # By elimination, val is not a list. Since dk is a - # list, wrap val in a list first. - if delete_existing: - dk = filter(lambda x, val=val: x not in val, dk) - self._dict[key] = dk + [val] - else: - if not val in dk: - self._dict[key] = dk + [val] - else: - if key == 'CPPDEFINES': - if SCons.Util.is_String(dk): - dk = [dk] - elif SCons.Util.is_Dict(dk): - tmp = [] - for (k, v) in dk.iteritems(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - dk = tmp - if SCons.Util.is_String(val): - if val in dk: - val = [] - else: - val = [val] - elif SCons.Util.is_Dict(val): - tmp = [] - for i,j in val.iteritems(): - if j is not None: - tmp.append((i,j)) - else: - tmp.append(i) - val = tmp - if delete_existing: - dk = [x for x in dk if x not in val] - self._dict[key] = dk + val - self.scanner_map_delete(kw) - - def Clone(self, tools=[], toolpath=None, parse_flags = None, **kw): - """Return a copy of a construction Environment. The - copy is like a Python "deep copy"--that is, independent - copies are made recursively of each objects--except that - a reference is copied when an object is not deep-copyable - (like a function). There are no references to any mutable - objects in the original Environment. - """ - - builders = self._dict.get('BUILDERS', {}) - - clone = copy.copy(self) - # BUILDERS is not safe to do a simple copy - clone._dict = semi_deepcopy_dict(self._dict, ['BUILDERS']) - clone._dict['BUILDERS'] = BuilderDict(builders, clone) - - # Check the methods added via AddMethod() and re-bind them to - # the cloned environment. Only do this if the attribute hasn't - # been overwritten by the user explicitly and still points to - # the added method. - clone.added_methods = [] - for mw in self.added_methods: - if mw == getattr(self, mw.name): - clone.added_methods.append(mw.clone(clone)) - - clone._memo = {} - - # Apply passed-in variables before the tools - # so the tools can use the new variables - kw = copy_non_reserved_keywords(kw) - new = {} - for key, value in kw.items(): - new[key] = SCons.Subst.scons_subst_once(value, self, key) - clone.Replace(**new) - - apply_tools(clone, tools, toolpath) - - # apply them again in case the tools overwrote them - clone.Replace(**new) - - # Finally, apply any flags to be merged in - if parse_flags: clone.MergeFlags(parse_flags) - - if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.EnvironmentClone') - return clone - - def Copy(self, *args, **kw): - global _warn_copy_deprecated - if _warn_copy_deprecated: - msg = "The env.Copy() method is deprecated; use the env.Clone() method instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedCopyWarning, msg) - _warn_copy_deprecated = False - return self.Clone(*args, **kw) - - def _changed_build(self, dependency, target, prev_ni): - if dependency.changed_state(target, prev_ni): - return 1 - return self.decide_source(dependency, target, prev_ni) - - def _changed_content(self, dependency, target, prev_ni): - return dependency.changed_content(target, prev_ni) - - def _changed_source(self, dependency, target, prev_ni): - target_env = dependency.get_build_env() - type = target_env.get_tgt_sig_type() - if type == 'source': - return target_env.decide_source(dependency, target, prev_ni) - else: - return target_env.decide_target(dependency, target, prev_ni) - - def _changed_timestamp_then_content(self, dependency, target, prev_ni): - return dependency.changed_timestamp_then_content(target, prev_ni) - - def _changed_timestamp_newer(self, dependency, target, prev_ni): - return dependency.changed_timestamp_newer(target, prev_ni) - - def _changed_timestamp_match(self, dependency, target, prev_ni): - return dependency.changed_timestamp_match(target, prev_ni) - - def _copy_from_cache(self, src, dst): - return self.fs.copy(src, dst) - - def _copy2_from_cache(self, src, dst): - return self.fs.copy2(src, dst) - - def Decider(self, function): - copy_function = self._copy2_from_cache - if function in ('MD5', 'content'): - if not SCons.Util.md5: - raise UserError("MD5 signatures are not available in this version of Python.") - function = self._changed_content - elif function == 'MD5-timestamp': - function = self._changed_timestamp_then_content - elif function in ('timestamp-newer', 'make'): - function = self._changed_timestamp_newer - copy_function = self._copy_from_cache - elif function == 'timestamp-match': - function = self._changed_timestamp_match - elif not callable(function): - raise UserError("Unknown Decider value %s" % repr(function)) - - # We don't use AddMethod because we don't want to turn the - # function, which only expects three arguments, into a bound - # method, which would add self as an initial, fourth argument. - self.decide_target = function - self.decide_source = function - - self.copy_from_cache = copy_function - - def Detect(self, progs): - """Return the first available program in progs. - """ - if not SCons.Util.is_List(progs): - progs = [ progs ] - for prog in progs: - path = self.WhereIs(prog) - if path: return prog - return None - - def Dictionary(self, *args): - if not args: - return self._dict - dlist = [self._dict[x] for x in args] - if len(dlist) == 1: - dlist = dlist[0] - return dlist - - def Dump(self, key = None): - """ - Using the standard Python pretty printer, return the contents of the - scons build environment as a string. - - If the key passed in is anything other than None, then that will - be used as an index into the build environment dictionary and - whatever is found there will be fed into the pretty printer. Note - that this key is case sensitive. - """ - import pprint - pp = pprint.PrettyPrinter(indent=2) - if key: - dict = self.Dictionary(key) - else: - dict = self.Dictionary() - return pp.pformat(dict) - - def FindIxes(self, paths, prefix, suffix): - """ - Search a list of paths for something that matches the prefix and suffix. - - paths - the list of paths or nodes. - prefix - construction variable for the prefix. - suffix - construction variable for the suffix. - """ - - suffix = self.subst('$'+suffix) - prefix = self.subst('$'+prefix) - - for path in paths: - dir,name = os.path.split(str(path)) - if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix: - return path - - def ParseConfig(self, command, function=None, unique=1): - """ - Use the specified function to parse the output of the command - in order to modify the current environment. The 'command' can - be a string or a list of strings representing a command and - its arguments. 'Function' is an optional argument that takes - the environment, the output of the command, and the unique flag. - If no function is specified, MergeFlags, which treats the output - as the result of a typical 'X-config' command (i.e. gtk-config), - will merge the output into the appropriate variables. - """ - if function is None: - def parse_conf(env, cmd, unique=unique): - return env.MergeFlags(cmd, unique) - function = parse_conf - if SCons.Util.is_List(command): - command = ' '.join(command) - command = self.subst(command) - return function(self, self.backtick(command)) - - def ParseDepends(self, filename, must_exist=None, only_one=0): - """ - Parse a mkdep-style file for explicit dependencies. This is - completely abusable, and should be unnecessary in the "normal" - case of proper SCons configuration, but it may help make - the transition from a Make hierarchy easier for some people - to swallow. It can also be genuinely useful when using a tool - that can write a .d file, but for which writing a scanner would - be too complicated. - """ - filename = self.subst(filename) - try: - fp = open(filename, 'r') - 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: - try: - target, depends = line.split(':', 1) - except (AttributeError, ValueError): - # Throws AttributeError if line isn't a string. Can throw - # ValueError if line doesn't split into two or more elements. - pass - else: - tdlist.append((target.split(), depends.split())) - if only_one: - targets = [] - for td in tdlist: - targets.extend(td[0]) - if len(targets) > 1: - raise SCons.Errors.UserError( - "More than one dependency target found in `%s': %s" - % (filename, targets)) - for target, depends in tdlist: - self.Depends(target, depends) - - def Platform(self, platform): - platform = self.subst(platform) - return SCons.Platform.Platform(platform)(self) - - def Prepend(self, **kw): - """Prepend values to existing construction variables - in an Environment. - """ - kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): - # It would be easier on the eyes to write this using - # "continue" statements whenever we finish processing an item, - # but Python 1.5.2 apparently doesn't let you use "continue" - # within try:-except: blocks, so we have to nest our code. - try: - orig = self._dict[key] - except KeyError: - # No existing variable in the environment, so just set - # it to the new value. - self._dict[key] = val - else: - try: - # Check if the original looks like a dictionary. - # If it is, we can't just try adding the value because - # dictionaries don't have __add__() methods, and - # things like UserList will incorrectly coerce the - # original dict to a list (which we don't want). - update_dict = orig.update - except AttributeError: - try: - # Most straightforward: just try to add them - # together. This will work in most cases, when the - # original and new values are of compatible types. - self._dict[key] = val + orig - except (KeyError, TypeError): - try: - # Check if the added value is a list. - add_to_val = val.append - except AttributeError: - # The added value isn't a list, but the - # original is (by process of elimination), - # so insert the the new value in the original - # (if there's one to insert). - if val: - orig.insert(0, val) - else: - # The added value is a list, so append - # the original to it (if there's a value - # to append). - if orig: - add_to_val(orig) - self._dict[key] = val - else: - # The original looks like a dictionary, so update it - # based on what we think the value looks like. - if SCons.Util.is_List(val): - for v in val: - orig[v] = None - else: - try: - update_dict(val) - except (AttributeError, TypeError, ValueError): - if SCons.Util.is_Dict(val): - for k, v in val.items(): - orig[k] = v - else: - orig[val] = None - self.scanner_map_delete(kw) - - def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, - delete_existing=1): - """Prepend 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 - assure this. This can also handle the case where the env - variable is a list instead of a string. - - If delete_existing is 0, a newpath which is already in the path - will not be moved to the front (it will be left where it is). - """ - - orig = '' - if envname in self._dict and name in self._dict[envname]: - orig = self._dict[envname][name] - - nv = SCons.Util.PrependPath(orig, newpath, sep, delete_existing, - canonicalize=self._canonicalize) - - if envname not in self._dict: - self._dict[envname] = {} - - self._dict[envname][name] = nv - - def PrependUnique(self, delete_existing=0, **kw): - """Prepend values to existing construction variables - in an Environment, if they're not already there. - If delete_existing is 1, removes existing values first, so - values move to front. - """ - kw = copy_non_reserved_keywords(kw) - for key, val in kw.items(): - if SCons.Util.is_List(val): - val = _delete_duplicates(val, not delete_existing) - if key not in self._dict or self._dict[key] in ('', None): - self._dict[key] = val - elif SCons.Util.is_Dict(self._dict[key]) and \ - SCons.Util.is_Dict(val): - self._dict[key].update(val) - elif SCons.Util.is_List(val): - dk = self._dict[key] - if not SCons.Util.is_List(dk): - dk = [dk] - if delete_existing: - dk = [x for x in dk if x not in val] - else: - val = [x for x in val if x not in dk] - self._dict[key] = val + dk - else: - dk = self._dict[key] - if SCons.Util.is_List(dk): - # By elimination, val is not a list. Since dk is a - # list, wrap val in a list first. - if delete_existing: - dk = [x for x in dk if x not in val] - self._dict[key] = [val] + dk - else: - if not val in dk: - self._dict[key] = [val] + dk - else: - if delete_existing: - dk = [x for x in dk if x not in val] - self._dict[key] = val + dk - self.scanner_map_delete(kw) - - def Replace(self, **kw): - """Replace existing construction variables in an Environment - with new construction variables and/or values. - """ - try: - kwbd = kw['BUILDERS'] - except KeyError: - pass - else: - kwbd = BuilderDict(kwbd,self) - del kw['BUILDERS'] - self.__setitem__('BUILDERS', kwbd) - kw = copy_non_reserved_keywords(kw) - self._update(semi_deepcopy(kw)) - self.scanner_map_delete(kw) - - def ReplaceIxes(self, path, old_prefix, old_suffix, new_prefix, new_suffix): - """ - Replace old_prefix with new_prefix and old_suffix with new_suffix. - - env - Environment used to interpolate variables. - path - the path that will be modified. - old_prefix - construction variable for the old prefix. - old_suffix - construction variable for the old suffix. - new_prefix - construction variable for the new prefix. - new_suffix - construction variable for the new suffix. - """ - old_prefix = self.subst('$'+old_prefix) - old_suffix = self.subst('$'+old_suffix) - - new_prefix = self.subst('$'+new_prefix) - new_suffix = self.subst('$'+new_suffix) - - dir,name = os.path.split(str(path)) - if name[:len(old_prefix)] == old_prefix: - name = name[len(old_prefix):] - if name[-len(old_suffix):] == old_suffix: - name = name[:-len(old_suffix)] - return os.path.join(dir, new_prefix+name+new_suffix) - - def SetDefault(self, **kw): - for k in kw.keys(): - if k in self._dict: - del kw[k] - self.Replace(**kw) - - def _find_toolpath_dir(self, tp): - return self.fs.Dir(self.subst(tp)).srcnode().get_abspath() - - def Tool(self, tool, toolpath=None, **kw): - if SCons.Util.is_String(tool): - tool = self.subst(tool) - if toolpath is None: - toolpath = self.get('toolpath', []) - toolpath = list(map(self._find_toolpath_dir, toolpath)) - tool = SCons.Tool.Tool(tool, toolpath, **kw) - tool(self) - - def WhereIs(self, prog, path=None, pathext=None, reject=[]): - """Find prog in the path. - """ - if path is None: - try: - path = self['ENV']['PATH'] - except KeyError: - pass - elif SCons.Util.is_String(path): - path = self.subst(path) - if pathext is None: - try: - pathext = self['ENV']['PATHEXT'] - except KeyError: - pass - elif SCons.Util.is_String(pathext): - pathext = self.subst(pathext) - prog = SCons.Util.CLVar(self.subst(prog)) # support "program --with-args" - path = SCons.Util.WhereIs(prog[0], path, pathext, reject) - if path: return path - return None - - ####################################################################### - # Public methods for doing real "SCons stuff" (manipulating - # dependencies, setting attributes on targets, etc.). These begin - # with upper-case letters. The essential characteristic of methods - # in this section is that they all *should* have corresponding - # same-named global functions. - ####################################################################### - - def Action(self, *args, **kw): - def subst_string(a, self=self): - if SCons.Util.is_String(a): - a = self.subst(a) - return a - nargs = list(map(subst_string, args)) - nkw = self.subst_kw(kw) - return SCons.Action.Action(*nargs, **nkw) - - def AddPreAction(self, files, action): - nodes = self.arg2nodes(files, self.fs.Entry) - action = SCons.Action.Action(action) - uniq = {} - for executor in [n.get_executor() for n in nodes]: - uniq[executor] = 1 - for executor in uniq.keys(): - executor.add_pre_action(action) - return nodes - - def AddPostAction(self, files, action): - nodes = self.arg2nodes(files, self.fs.Entry) - action = SCons.Action.Action(action) - uniq = {} - for executor in [n.get_executor() for n in nodes]: - uniq[executor] = 1 - for executor in uniq.keys(): - executor.add_post_action(action) - return nodes - - def Alias(self, target, source=[], action=None, **kw): - tlist = self.arg2nodes(target, self.ans.Alias) - if not SCons.Util.is_List(source): - source = [source] - source = [_f for _f in source if _f] - - if not action: - if not source: - # There are no source files and no action, so just - # return a target list of classic Alias Nodes, without - # any builder. The externally visible effect is that - # this will make the wrapping Script.BuildTask class - # say that there's "Nothing to be done" for this Alias, - # instead of that it's "up to date." - return tlist - - # No action, but there are sources. Re-call all the target - # builders to add the sources to each target. - result = [] - for t in tlist: - bld = t.get_builder(AliasBuilder) - result.extend(bld(self, t, source)) - return result - - nkw = self.subst_kw(kw) - nkw.update({ - 'action' : SCons.Action.Action(action), - 'source_factory' : self.fs.Entry, - 'multi' : 1, - 'is_explicit' : None, - }) - bld = SCons.Builder.Builder(**nkw) - - # Apply the Builder separately to each target so that the Aliases - # stay separate. If we did one "normal" Builder call with the - # whole target list, then all of the target Aliases would be - # associated under a single Executor. - result = [] - for t in tlist: - # Calling the convert() method will cause a new Executor to be - # created from scratch, so we have to explicitly initialize - # it with the target's existing sources, plus our new ones, - # so nothing gets lost. - b = t.get_builder() - if b is None or b is AliasBuilder: - b = bld - else: - nkw['action'] = b.action + action - b = SCons.Builder.Builder(**nkw) - t.convert() - result.extend(b(self, t, t.sources + source)) - return result - - def AlwaysBuild(self, *targets): - tlist = [] - for t in targets: - tlist.extend(self.arg2nodes(t, self.fs.Entry)) - for t in tlist: - t.set_always_build() - return tlist - - def BuildDir(self, *args, **kw): - msg = """BuildDir() and the build_dir keyword have been deprecated;\n\tuse VariantDir() and the variant_dir keyword instead.""" - SCons.Warnings.warn(SCons.Warnings.DeprecatedBuildDirWarning, msg) - if 'build_dir' in kw: - kw['variant_dir'] = kw['build_dir'] - del kw['build_dir'] - return self.VariantDir(*args, **kw) - - def Builder(self, **kw): - nkw = self.subst_kw(kw) - return SCons.Builder.Builder(**nkw) - - def CacheDir(self, path): - import SCons.CacheDir - if path is not None: - path = self.subst(path) - self._CacheDir_path = path - - def Clean(self, targets, files): - global CleanTargets - tlist = self.arg2nodes(targets, self.fs.Entry) - flist = self.arg2nodes(files, self.fs.Entry) - for t in tlist: - try: - CleanTargets[t].extend(flist) - except KeyError: - CleanTargets[t] = flist - - def Configure(self, *args, **kw): - nargs = [self] - if args: - nargs = nargs + self.subst_list(args)[0] - nkw = self.subst_kw(kw) - nkw['_depth'] = kw.get('_depth', 0) + 1 - try: - nkw['custom_tests'] = self.subst_kw(nkw['custom_tests']) - except KeyError: - pass - return SCons.SConf.SConf(*nargs, **nkw) - - def Command(self, target, source, action, **kw): - """Builds the supplied target files from the supplied - source files using the supplied action. Action may - be any type that the Builder constructor will accept - for an action.""" - bkw = { - 'action' : action, - 'target_factory' : self.fs.Entry, - 'source_factory' : self.fs.Entry, - } - try: bkw['source_scanner'] = kw['source_scanner'] - except KeyError: pass - else: del kw['source_scanner'] - bld = SCons.Builder.Builder(**bkw) - return bld(self, target, source, **kw) - - def Depends(self, target, dependency): - """Explicity specify that 'target's depend on 'dependency'.""" - tlist = self.arg2nodes(target, self.fs.Entry) - dlist = self.arg2nodes(dependency, self.fs.Entry) - for t in tlist: - t.add_dependency(dlist) - return tlist - - def Dir(self, name, *args, **kw): - """ - """ - s = self.subst(name) - if SCons.Util.is_Sequence(s): - result=[] - for e in s: - result.append(self.fs.Dir(e, *args, **kw)) - return result - return self.fs.Dir(s, *args, **kw) - - def NoClean(self, *targets): - """Tags a target so that it will not be cleaned by -c""" - tlist = [] - for t in targets: - tlist.extend(self.arg2nodes(t, self.fs.Entry)) - for t in tlist: - t.set_noclean() - return tlist - - def NoCache(self, *targets): - """Tags a target so that it will not be cached""" - tlist = [] - for t in targets: - tlist.extend(self.arg2nodes(t, self.fs.Entry)) - for t in tlist: - t.set_nocache() - return tlist - - def Entry(self, name, *args, **kw): - """ - """ - s = self.subst(name) - if SCons.Util.is_Sequence(s): - result=[] - for e in s: - result.append(self.fs.Entry(e, *args, **kw)) - return result - return self.fs.Entry(s, *args, **kw) - - def Environment(self, **kw): - return SCons.Environment.Environment(**self.subst_kw(kw)) - - def Execute(self, action, *args, **kw): - """Directly execute an action through an Environment - """ - action = self.Action(action, *args, **kw) - result = action([], [], self) - if isinstance(result, SCons.Errors.BuildError): - errstr = result.errstr - if result.filename: - errstr = result.filename + ': ' + errstr - sys.stderr.write("scons: *** %s\n" % errstr) - return result.status - else: - return result - - def File(self, name, *args, **kw): - """ - """ - s = self.subst(name) - if SCons.Util.is_Sequence(s): - result=[] - for e in s: - result.append(self.fs.File(e, *args, **kw)) - return result - return self.fs.File(s, *args, **kw) - - def FindFile(self, file, dirs): - file = self.subst(file) - nodes = self.arg2nodes(dirs, self.fs.Dir) - return SCons.Node.FS.find_file(file, tuple(nodes)) - - def Flatten(self, sequence): - return SCons.Util.flatten(sequence) - - def GetBuildPath(self, files): - result = list(map(str, self.arg2nodes(files, self.fs.Entry))) - if SCons.Util.is_List(files): - return result - else: - return result[0] - - def Glob(self, pattern, ondisk=True, source=False, strings=False, exclude=None): - return self.fs.Glob(self.subst(pattern), ondisk, source, strings, exclude) - - def Ignore(self, target, dependency): - """Ignore a dependency.""" - tlist = self.arg2nodes(target, self.fs.Entry) - dlist = self.arg2nodes(dependency, self.fs.Entry) - for t in tlist: - t.add_ignore(dlist) - return tlist - - def Literal(self, string): - return SCons.Subst.Literal(string) - - def Local(self, *targets): - ret = [] - for targ in targets: - if isinstance(targ, SCons.Node.Node): - targ.set_local() - ret.append(targ) - else: - for t in self.arg2nodes(targ, self.fs.Entry): - t.set_local() - ret.append(t) - return ret - - def Precious(self, *targets): - tlist = [] - for t in targets: - tlist.extend(self.arg2nodes(t, self.fs.Entry)) - for t in tlist: - t.set_precious() - return tlist - - def Pseudo(self, *targets): - tlist = [] - for t in targets: - tlist.extend(self.arg2nodes(t, self.fs.Entry)) - for t in tlist: - t.set_pseudo() - return tlist - - def Repository(self, *dirs, **kw): - dirs = self.arg2nodes(list(dirs), self.fs.Dir) - self.fs.Repository(*dirs, **kw) - - def Requires(self, target, prerequisite): - """Specify that 'prerequisite' must be built before 'target', - (but 'target' does not actually depend on 'prerequisite' - and need not be rebuilt if it changes).""" - tlist = self.arg2nodes(target, self.fs.Entry) - plist = self.arg2nodes(prerequisite, self.fs.Entry) - for t in tlist: - t.add_prerequisite(plist) - return tlist - - def Scanner(self, *args, **kw): - nargs = [] - for arg in args: - if SCons.Util.is_String(arg): - arg = self.subst(arg) - nargs.append(arg) - nkw = self.subst_kw(kw) - return SCons.Scanner.Base(*nargs, **nkw) - - def SConsignFile(self, name=".sconsign", dbm_module=None): - if name is not None: - name = self.subst(name) - if not os.path.isabs(name): - name = os.path.join(str(self.fs.SConstruct_dir), name) - if name: - name = os.path.normpath(name) - sconsign_dir = os.path.dirname(name) - if sconsign_dir and not os.path.exists(sconsign_dir): - self.Execute(SCons.Defaults.Mkdir(sconsign_dir)) - SCons.SConsign.File(name, dbm_module) - - def SideEffect(self, side_effect, target): - """Tell scons that side_effects are built as side - effects of building targets.""" - side_effects = self.arg2nodes(side_effect, self.fs.Entry) - targets = self.arg2nodes(target, self.fs.Entry) - - for side_effect in side_effects: - if side_effect.multiple_side_effect_has_builder(): - raise SCons.Errors.UserError("Multiple ways to build the same target were specified for: %s" % str(side_effect)) - side_effect.add_source(targets) - side_effect.side_effect = 1 - self.Precious(side_effect) - for target in targets: - target.side_effects.append(side_effect) - return side_effects - - def SourceCode(self, entry, builder): - """Arrange for a source code builder for (part of) a tree.""" - msg = """SourceCode() has been deprecated and there is no replacement. -\tIf you need this function, please contact scons-dev@scons.org""" - SCons.Warnings.warn(SCons.Warnings.DeprecatedSourceCodeWarning, msg) - entries = self.arg2nodes(entry, self.fs.Entry) - for entry in entries: - entry.set_src_builder(builder) - return entries - - def SourceSignatures(self, type): - global _warn_source_signatures_deprecated - if _warn_source_signatures_deprecated: - msg = "The env.SourceSignatures() method is deprecated;\n" + \ - "\tconvert your build to use the env.Decider() method instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedSourceSignaturesWarning, msg) - _warn_source_signatures_deprecated = False - type = self.subst(type) - self.src_sig_type = type - if type == 'MD5': - if not SCons.Util.md5: - raise UserError("MD5 signatures are not available in this version of Python.") - self.decide_source = self._changed_content - elif type == 'timestamp': - self.decide_source = self._changed_timestamp_match - else: - raise UserError("Unknown source signature type '%s'" % type) - - def Split(self, arg): - """This function converts a string or list into a list of strings - or Nodes. This makes things easier for users by allowing files to - be specified as a white-space separated list to be split. - The input rules are: - - A single string containing names separated by spaces. These will be - split apart at the spaces. - - A single Node instance - - A list containing either strings or Node instances. Any strings - in the list are not split at spaces. - In all cases, the function returns a list of Nodes and strings.""" - if SCons.Util.is_List(arg): - return list(map(self.subst, arg)) - elif SCons.Util.is_String(arg): - return self.subst(arg).split() - else: - return [self.subst(arg)] - - def TargetSignatures(self, type): - global _warn_target_signatures_deprecated - if _warn_target_signatures_deprecated: - msg = "The env.TargetSignatures() method is deprecated;\n" + \ - "\tconvert your build to use the env.Decider() method instead." - SCons.Warnings.warn(SCons.Warnings.DeprecatedTargetSignaturesWarning, msg) - _warn_target_signatures_deprecated = False - type = self.subst(type) - self.tgt_sig_type = type - if type in ('MD5', 'content'): - if not SCons.Util.md5: - raise UserError("MD5 signatures are not available in this version of Python.") - self.decide_target = self._changed_content - elif type == 'timestamp': - self.decide_target = self._changed_timestamp_match - elif type == 'build': - self.decide_target = self._changed_build - elif type == 'source': - self.decide_target = self._changed_source - else: - raise UserError("Unknown target signature type '%s'"%type) - - def Value(self, value, built_value=None): - """ - """ - return SCons.Node.Python.Value(value, built_value) - - def VariantDir(self, variant_dir, src_dir, duplicate=1): - variant_dir = self.arg2nodes(variant_dir, self.fs.Dir)[0] - src_dir = self.arg2nodes(src_dir, self.fs.Dir)[0] - self.fs.VariantDir(variant_dir, src_dir, duplicate) - - def FindSourceFiles(self, node='.'): - """ returns a list of all source files. - """ - node = self.arg2nodes(node, self.fs.Entry)[0] - - sources = [] - def build_source(ss): - for s in ss: - if isinstance(s, SCons.Node.FS.Dir): - build_source(s.all_children()) - elif s.has_builder(): - build_source(s.sources) - elif isinstance(s.disambiguate(), SCons.Node.FS.File): - sources.append(s) - build_source(node.all_children()) - - def final_source(node): - while (node != node.srcnode()): - node = node.srcnode() - return node - sources = map( final_source, sources ); - # remove duplicates - return list(set(sources)) - - def FindInstalledFiles(self): - """ returns the list of all targets of the Install and InstallAs Builder. - """ - from SCons.Tool import install - if install._UNIQUE_INSTALLED_FILES is None: - install._UNIQUE_INSTALLED_FILES = SCons.Util.uniquer_hashables(install._INSTALLED_FILES) - return install._UNIQUE_INSTALLED_FILES - - -class OverrideEnvironment(Base): - """A proxy that overrides variables in a wrapped construction - environment by returning values from an overrides dictionary in - preference to values from the underlying subject environment. - - This is a lightweight (I hope) proxy that passes through most use of - attributes to the underlying Environment.Base class, but has just - enough additional methods defined to act like a real construction - environment with overridden values. It can wrap either a Base - construction environment, or another OverrideEnvironment, which - can in turn nest arbitrary OverrideEnvironments... - - Note that we do *not* call the underlying base class - (SubsitutionEnvironment) initialization, because we get most of those - from proxying the attributes of the subject construction environment. - But because we subclass SubstitutionEnvironment, this class also - has inherited arg2nodes() and subst*() methods; those methods can't - be proxied because they need *this* object's methods to fetch the - values from the overrides dictionary. - """ - - def __init__(self, subject, overrides={}): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Environment.OverrideEnvironment') - self.__dict__['__subject'] = subject - self.__dict__['overrides'] = overrides - - # Methods that make this class act like a proxy. - def __getattr__(self, name): - return getattr(self.__dict__['__subject'], name) - def __setattr__(self, name, value): - setattr(self.__dict__['__subject'], name, value) - - # Methods that make this class act like a dictionary. - def __getitem__(self, key): - try: - return self.__dict__['overrides'][key] - except KeyError: - return self.__dict__['__subject'].__getitem__(key) - def __setitem__(self, key, value): - if not is_valid_construction_var(key): - raise SCons.Errors.UserError("Illegal construction variable `%s'" % key) - self.__dict__['overrides'][key] = value - def __delitem__(self, key): - try: - del self.__dict__['overrides'][key] - except KeyError: - deleted = 0 - else: - deleted = 1 - try: - result = self.__dict__['__subject'].__delitem__(key) - except KeyError: - if not deleted: - raise - result = None - return result - def get(self, key, default=None): - """Emulates the get() method of dictionaries.""" - try: - return self.__dict__['overrides'][key] - except KeyError: - return self.__dict__['__subject'].get(key, default) - def has_key(self, key): - try: - self.__dict__['overrides'][key] - return 1 - except KeyError: - return key in self.__dict__['__subject'] - def __contains__(self, key): - if self.__dict__['overrides'].__contains__(key): - return 1 - return self.__dict__['__subject'].__contains__(key) - def Dictionary(self): - """Emulates the items() method of dictionaries.""" - d = self.__dict__['__subject'].Dictionary().copy() - d.update(self.__dict__['overrides']) - return d - def items(self): - """Emulates the items() method of dictionaries.""" - return list(self.Dictionary().items()) - - # Overridden private construction environment methods. - def _update(self, dict): - """Update an environment's values directly, bypassing the normal - checks that occur when users try to set items. - """ - self.__dict__['overrides'].update(dict) - - def gvars(self): - return self.__dict__['__subject'].gvars() - - def lvars(self): - lvars = self.__dict__['__subject'].lvars() - lvars.update(self.__dict__['overrides']) - return lvars - - # Overridden public construction environment methods. - def Replace(self, **kw): - 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 -# by subclassing SCons.Environment.Base and then assigning the -# class to SCons.Environment.Environment. - -Environment = Base - -# An entry point for returning a proxy subclass instance that overrides -# the subst*() methods so they don't actually perform construction -# variable substitution. This is specifically intended to be the shim -# layer in between global function calls (which don't want construction -# variable substitution) and the DefaultEnvironment() (which would -# substitute variables if left to its own devices).""" -# -# We have to wrap this in a function that allows us to delay definition of -# the class until it's necessary, so that when it subclasses Environment -# it will pick up whatever Environment subclass the wrapper interface -# might have assigned to SCons.Environment.Environment. - -def NoSubstitutionProxy(subject): - class _NoSubstitutionProxy(Environment): - def __init__(self, subject): - self.__dict__['__subject'] = subject - def __getattr__(self, name): - return getattr(self.__dict__['__subject'], name) - def __setattr__(self, name, value): - return setattr(self.__dict__['__subject'], name, value) - def executor_to_lvars(self, kwdict): - if kwdict.has_key('executor'): - kwdict['lvars'] = kwdict['executor'].get_lvars() - del kwdict['executor'] - else: - kwdict['lvars'] = {} - def raw_to_mode(self, dict): - try: - raw = dict['raw'] - except KeyError: - pass - else: - del dict['raw'] - dict['mode'] = raw - def subst(self, string, *args, **kwargs): - return string - def subst_kw(self, kw, *args, **kwargs): - return kw - def subst_list(self, string, *args, **kwargs): - nargs = (string, self,) + args - nkw = kwargs.copy() - nkw['gvars'] = {} - self.executor_to_lvars(nkw) - self.raw_to_mode(nkw) - return SCons.Subst.scons_subst_list(*nargs, **nkw) - def subst_target_source(self, string, *args, **kwargs): - nargs = (string, self,) + args - nkw = kwargs.copy() - nkw['gvars'] = {} - self.executor_to_lvars(nkw) - self.raw_to_mode(nkw) - return SCons.Subst.scons_subst(*nargs, **nkw) - return _NoSubstitutionProxy(subject) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Errors.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Errors.py deleted file mode 100644 index 998a70d..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Errors.py +++ /dev/null @@ -1,205 +0,0 @@ -# -# Copyright (c) 2001 - 2015 The SCons Foundation -# -# Permission is hereby granted, free of charge, to any person obtaining -# a copy of this software and associated documentation files (the -# "Software"), to deal in the Software without restriction, including -# without limitation the rights to use, copy, modify, merge, publish, -# distribute, sublicense, and/or sell copies of the Software, and to -# permit persons to whom the Software is furnished to do so, subject to -# the following conditions: -# -# The above copyright notice and this permission notice shall be included -# in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY -# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -"""SCons.Errors - -This file contains the exception classes used to handle internal -and user errors in SCons. - -""" - -__revision__ = "src/engine/SCons/Errors.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.Util - -import exceptions - -class BuildError(Exception): - """ Errors occuring while building. - - BuildError have the following attributes: - - Information about the cause of the build error: - ----------------------------------------------- - - errstr : a description of the error message - - status : the return code of the action that caused the build - error. Must be set to a non-zero value even if the - build error is not due to an action returning a - non-zero returned code. - - exitstatus : SCons exit status due to this build error. - Must be nonzero unless due to an explicit Exit() - call. Not always the same as status, since - actions return a status code that should be - respected, but SCons typically exits with 2 - irrespective of the return value of the failed - action. - - filename : The name of the file or directory that caused the - build error. Set to None if no files are associated with - this error. This might be different from the target - being built. For example, failure to create the - directory in which the target file will appear. It - can be None if the error is not due to a particular - filename. - - exc_info : Info about exception that caused the build - error. Set to (None, None, None) if this build - error is not due to an exception. - - - Information about the cause of the location of the error: - --------------------------------------------------------- - - node : the error occured while building this target node(s) - - executor : the executor that caused the build to fail (might - be None if the build failures is not due to the - executor failing) - - action : the action that caused the build to fail (might be - None if the build failures is not due to the an - action failure) - - command : the command line for the action that caused the - build to fail (might be None if the build failures - is not due to the an action failure) - """ - - def __init__(self, - node=None, errstr="Unknown error", status=2, exitstatus=2, - filename=None, executor=None, action=None, command=None, - exc_info=(None, None, None)): - - self.errstr = errstr - self.status = status - self.exitstatus = exitstatus - self.filename = filename - self.exc_info = exc_info - - self.node = node - self.executor = executor - self.action = action - self.command = command - - Exception.__init__(self, node, errstr, status, exitstatus, filename, - executor, action, command, exc_info) - - def __str__(self): - if self.filename: - return self.filename + ': ' + self.errstr - else: - return self.errstr - -class InternalError(Exception): - pass - -class UserError(Exception): - pass - -class StopError(Exception): - pass - -class EnvironmentError(Exception): - pass - -class MSVCError(IOError): - pass - -class ExplicitExit(Exception): - def __init__(self, node=None, status=None, *args): - self.node = node - self.status = status - self.exitstatus = status - Exception.__init__(self, *args) - -def convert_to_BuildError(status, exc_info=None): - """ - Convert any return code a BuildError Exception. - - `status' can either be a return code or an Exception. - The buildError.status we set here will normally be - used as the exit status of the "scons" process. - """ - if not exc_info and isinstance(status, Exception): - exc_info = (status.__class__, status, None) - - if isinstance(status, BuildError): - buildError = status - buildError.exitstatus = 2 # always exit with 2 on build errors - elif isinstance(status, ExplicitExit): - status = status.status - errstr = 'Explicit exit, status %s' % status - buildError = BuildError( - errstr=errstr, - status=status, # might be 0, OK here - exitstatus=status, # might be 0, OK here - exc_info=exc_info) - elif isinstance(status, (StopError, UserError)): - buildError = BuildError( - errstr=str(status), - status=2, - exitstatus=2, - exc_info=exc_info) - elif isinstance(status, exceptions.EnvironmentError): - # If an IOError/OSError happens, raise a BuildError. - # Report the name of the file or directory that caused the - # 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 - buildError = BuildError( - errstr=status.strerror, - status=status.errno, - exitstatus=2, - filename=filename, - exc_info=exc_info) - elif isinstance(status, Exception): - buildError = BuildError( - errstr='%s : %s' % (status.__class__.__name__, status), - status=2, - exitstatus=2, - exc_info=exc_info) - elif SCons.Util.is_String(status): - buildError = BuildError( - errstr=status, - status=2, - exitstatus=2) - else: - buildError = BuildError( - errstr="Error %s" % status, - status=status, - exitstatus=2) - - #import sys - #sys.stderr.write("convert_to_BuildError: status %s => (errstr %s, status %s)"%(status,buildError.errstr, buildError.status)) - return buildError - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Executor.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Executor.py deleted file mode 100644 index 3211fd1..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Executor.py +++ /dev/null @@ -1,678 +0,0 @@ -"""SCons.Executor - -A module for executing actions with specific lists of target and source -Nodes. - -""" - -# -# Copyright (c) 2001 - 2015 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/Executor.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import collections - -import SCons.Debug -from SCons.Debug import logInstanceCreation -import SCons.Errors -import SCons.Memoize - - -class Batch(object): - """Remembers exact association between targets - and sources of executor.""" - - __slots__ = ('targets', - 'sources') - - def __init__(self, targets=[], sources=[]): - self.targets = targets - self.sources = sources - - - -class TSList(collections.UserList): - """A class that implements $TARGETS or $SOURCES expansions by wrapping - an executor Method. This class is used in the Executor.lvars() - to delay creation of NodeList objects until they're needed. - - Note that we subclass collections.UserList purely so that the - is_Sequence() function will identify an object of this class as - a list during variable expansion. We're not really using any - collections.UserList methods in practice. - """ - def __init__(self, func): - self.func = func - def __getattr__(self, attr): - nl = self.func() - return getattr(nl, attr) - def __getitem__(self, i): - nl = self.func() - return nl[i] - def __getslice__(self, i, j): - nl = self.func() - i = max(i, 0); j = max(j, 0) - return nl[i:j] - def __str__(self): - nl = self.func() - return str(nl) - def __repr__(self): - nl = self.func() - return repr(nl) - -class TSObject(object): - """A class that implements $TARGET or $SOURCE expansions by wrapping - an Executor method. - """ - def __init__(self, func): - self.func = func - def __getattr__(self, attr): - n = self.func() - return getattr(n, attr) - def __str__(self): - n = self.func() - if n: - return str(n) - return '' - def __repr__(self): - n = self.func() - if n: - return repr(n) - return '' - -def rfile(node): - """ - A function to return the results of a Node's rfile() method, - if it exists, and the Node itself otherwise (if it's a Value - Node, e.g.). - """ - try: - rfile = node.rfile - except AttributeError: - return node - else: - return rfile() - - -def execute_nothing(obj, target, kw): - return 0 - -def execute_action_list(obj, target, kw): - """Actually execute the action list.""" - env = obj.get_build_env() - kw = obj.get_kw(kw) - status = 0 - for act in obj.get_action_list(): - #args = (self.get_all_targets(), self.get_all_sources(), env) - args = ([], [], env) - status = act(*args, **kw) - if isinstance(status, SCons.Errors.BuildError): - status.executor = obj - raise status - elif status: - msg = "Error %s" % status - raise SCons.Errors.BuildError( - errstr=msg, - node=obj.batches[0].targets, - executor=obj, - action=act) - return status - -_do_execute_map = {0 : execute_nothing, - 1 : execute_action_list} - - -def execute_actions_str(obj): - env = obj.get_build_env() - return "\n".join([action.genstring(obj.get_all_targets(), - obj.get_all_sources(), - env) - for action in obj.get_action_list()]) - -def execute_null_str(obj): - return '' - -_execute_str_map = {0 : execute_null_str, - 1 : execute_actions_str} - - -class Executor(object): - """A class for controlling instances of executing an action. - - This largely exists to hold a single association of an action, - environment, list of environment override dictionaries, targets - and sources for later processing as needed. - """ - - __slots__ = ('pre_actions', - 'post_actions', - 'env', - 'overridelist', - 'batches', - 'builder_kw', - '_memo', - 'lvars', - '_changed_sources_list', - '_changed_targets_list', - '_unchanged_sources_list', - '_unchanged_targets_list', - 'action_list', - '_do_execute', - '_execute_str') - - def __init__(self, action, env=None, overridelist=[{}], - targets=[], sources=[], builder_kw={}): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Executor.Executor') - self.set_action_list(action) - self.pre_actions = [] - self.post_actions = [] - self.env = env - self.overridelist = overridelist - if targets or sources: - self.batches = [Batch(targets[:], sources[:])] - else: - self.batches = [] - self.builder_kw = builder_kw - self._do_execute = 1 - self._execute_str = 1 - self._memo = {} - - def get_lvars(self): - try: - return self.lvars - except AttributeError: - self.lvars = { - 'CHANGED_SOURCES' : TSList(self._get_changed_sources), - 'CHANGED_TARGETS' : TSList(self._get_changed_targets), - 'SOURCE' : TSObject(self._get_source), - 'SOURCES' : TSList(self._get_sources), - 'TARGET' : TSObject(self._get_target), - 'TARGETS' : TSList(self._get_targets), - 'UNCHANGED_SOURCES' : TSList(self._get_unchanged_sources), - 'UNCHANGED_TARGETS' : TSList(self._get_unchanged_targets), - } - return self.lvars - - def _get_changes(self): - cs = [] - ct = [] - us = [] - ut = [] - for b in self.batches: - if b.targets[0].is_up_to_date(): - us.extend(list(map(rfile, b.sources))) - ut.extend(b.targets) - else: - cs.extend(list(map(rfile, b.sources))) - ct.extend(b.targets) - self._changed_sources_list = SCons.Util.NodeList(cs) - self._changed_targets_list = SCons.Util.NodeList(ct) - self._unchanged_sources_list = SCons.Util.NodeList(us) - self._unchanged_targets_list = SCons.Util.NodeList(ut) - - def _get_changed_sources(self, *args, **kw): - try: - return self._changed_sources_list - except AttributeError: - self._get_changes() - return self._changed_sources_list - - def _get_changed_targets(self, *args, **kw): - try: - return self._changed_targets_list - except AttributeError: - self._get_changes() - return self._changed_targets_list - - def _get_source(self, *args, **kw): - #return SCons.Util.NodeList([rfile(self.batches[0].sources[0]).get_subst_proxy()]) - return rfile(self.batches[0].sources[0]).get_subst_proxy() - - def _get_sources(self, *args, **kw): - return SCons.Util.NodeList([rfile(n).get_subst_proxy() for n in self.get_all_sources()]) - - def _get_target(self, *args, **kw): - #return SCons.Util.NodeList([self.batches[0].targets[0].get_subst_proxy()]) - return self.batches[0].targets[0].get_subst_proxy() - - def _get_targets(self, *args, **kw): - return SCons.Util.NodeList([n.get_subst_proxy() for n in self.get_all_targets()]) - - def _get_unchanged_sources(self, *args, **kw): - try: - return self._unchanged_sources_list - except AttributeError: - self._get_changes() - return self._unchanged_sources_list - - def _get_unchanged_targets(self, *args, **kw): - try: - return self._unchanged_targets_list - except AttributeError: - self._get_changes() - return self._unchanged_targets_list - - def get_action_targets(self): - if not self.action_list: - return [] - targets_string = self.action_list[0].get_targets(self.env, self) - if targets_string[0] == '$': - targets_string = targets_string[1:] - return self.get_lvars()[targets_string] - - def set_action_list(self, action): - import SCons.Util - if not SCons.Util.is_List(action): - if not action: - import SCons.Errors - raise SCons.Errors.UserError("Executor must have an action.") - action = [action] - self.action_list = action - - def get_action_list(self): - if self.action_list is None: - return [] - return self.pre_actions + self.action_list + self.post_actions - - def get_all_targets(self): - """Returns all targets for all batches of this Executor.""" - result = [] - for batch in self.batches: - result.extend(batch.targets) - return result - - def get_all_sources(self): - """Returns all sources for all batches of this Executor.""" - result = [] - for batch in self.batches: - result.extend(batch.sources) - return result - - def get_all_children(self): - """Returns all unique children (dependencies) for all batches - of this Executor. - - The Taskmaster can recognize when it's already evaluated a - Node, so we don't have to make this list unique for its intended - canonical use case, but we expect there to be a lot of redundancy - (long lists of batched .cc files #including the same .h files - over and over), so removing the duplicates once up front should - save the Taskmaster a lot of work. - """ - result = SCons.Util.UniqueList([]) - for target in self.get_all_targets(): - result.extend(target.children()) - return result - - def get_all_prerequisites(self): - """Returns all unique (order-only) prerequisites for all batches - of this Executor. - """ - result = SCons.Util.UniqueList([]) - for target in self.get_all_targets(): - if target.prerequisites is not None: - result.extend(target.prerequisites) - return result - - def get_action_side_effects(self): - - """Returns all side effects for all batches of this - Executor used by the underlying Action. - """ - result = SCons.Util.UniqueList([]) - for target in self.get_action_targets(): - result.extend(target.side_effects) - return result - - @SCons.Memoize.CountMethodCall - def get_build_env(self): - """Fetch or create the appropriate build Environment - for this Executor. - """ - try: - return self._memo['get_build_env'] - except KeyError: - pass - - # Create the build environment instance with appropriate - # overrides. These get evaluated against the current - # environment's construction variables so that users can - # add to existing values by referencing the variable in - # the expansion. - overrides = {} - for odict in self.overridelist: - overrides.update(odict) - - import SCons.Defaults - env = self.env or SCons.Defaults.DefaultEnvironment() - build_env = env.Override(overrides) - - self._memo['get_build_env'] = build_env - - return build_env - - def get_build_scanner_path(self, scanner): - """Fetch the scanner path for this executor's targets and sources. - """ - env = self.get_build_env() - try: - cwd = self.batches[0].targets[0].cwd - except (IndexError, AttributeError): - cwd = None - return scanner.path(env, cwd, - self.get_all_targets(), - self.get_all_sources()) - - def get_kw(self, kw={}): - result = self.builder_kw.copy() - result.update(kw) - result['executor'] = self - return result - - # use extra indirection because with new-style objects (Python 2.2 - # and above) we can't override special methods, and nullify() needs - # to be able to do this. - - def __call__(self, target, **kw): - return _do_execute_map[self._do_execute](self, target, kw) - - def cleanup(self): - self._memo = {} - - def add_sources(self, sources): - """Add source files to this Executor's list. This is necessary - for "multi" Builders that can be called repeatedly to build up - a source file list for a given target.""" - # TODO(batch): extend to multiple batches - assert (len(self.batches) == 1) - # TODO(batch): remove duplicates? - sources = [x for x in sources if x not in self.batches[0].sources] - self.batches[0].sources.extend(sources) - - def get_sources(self): - return self.batches[0].sources - - def add_batch(self, targets, sources): - """Add pair of associated target and source to this Executor's list. - This is necessary for "batch" Builders that can be called repeatedly - to build up a list of matching target and source files that will be - used in order to update multiple target files at once from multiple - corresponding source files, for tools like MSVC that support it.""" - self.batches.append(Batch(targets, sources)) - - def prepare(self): - """ - Preparatory checks for whether this Executor can go ahead - and (try to) build its targets. - """ - for s in self.get_all_sources(): - if s.missing(): - msg = "Source `%s' not found, needed by target `%s'." - raise SCons.Errors.StopError(msg % (s, self.batches[0].targets[0])) - - def add_pre_action(self, action): - self.pre_actions.append(action) - - def add_post_action(self, action): - self.post_actions.append(action) - - # another extra indirection for new-style objects and nullify... - - def __str__(self): - return _execute_str_map[self._execute_str](self) - - def nullify(self): - self.cleanup() - self._do_execute = 0 - self._execute_str = 0 - - @SCons.Memoize.CountMethodCall - def get_contents(self): - """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. - """ - try: - return self._memo['get_contents'] - except KeyError: - pass - env = self.get_build_env() - result = "".join([action.get_contents(self.get_all_targets(), - self.get_all_sources(), - env) - for action in self.get_action_list()]) - self._memo['get_contents'] = result - return result - - def get_timestamp(self): - """Fetch a time stamp for this Executor. We don't have one, of - course (only files do), but this is the interface used by the - timestamp module. - """ - return 0 - - def scan_targets(self, scanner): - # TODO(batch): scan by batches - self.scan(scanner, self.get_all_targets()) - - def scan_sources(self, scanner): - # TODO(batch): scan by batches - if self.batches[0].sources: - self.scan(scanner, self.get_all_sources()) - - def scan(self, scanner, node_list): - """Scan a list of this Executor's files (targets or sources) for - implicit dependencies and update all of the targets with them. - This essentially short-circuits an N*M scan of the sources for - each individual target, which is a hell of a lot more efficient. - """ - env = self.get_build_env() - - # TODO(batch): scan by batches) - deps = [] - if scanner: - for node in node_list: - node.disambiguate() - s = scanner.select(node) - if not s: - continue - path = self.get_build_scanner_path(s) - deps.extend(node.get_implicit_deps(env, s, path)) - else: - kw = self.get_kw() - for node in node_list: - node.disambiguate() - scanner = node.get_env_scanner(env, kw) - if not scanner: - continue - scanner = scanner.select(node) - if not scanner: - continue - path = self.get_build_scanner_path(scanner) - deps.extend(node.get_implicit_deps(env, scanner, path)) - - deps.extend(self.get_implicit_deps()) - - for tgt in self.get_all_targets(): - tgt.add_to_implicit(deps) - - def _get_unignored_sources_key(self, node, ignore=()): - return (node,) + tuple(ignore) - - @SCons.Memoize.CountDictCall(_get_unignored_sources_key) - def get_unignored_sources(self, node, ignore=()): - key = (node,) + tuple(ignore) - try: - memo_dict = self._memo['get_unignored_sources'] - except KeyError: - memo_dict = {} - self._memo['get_unignored_sources'] = memo_dict - else: - try: - return memo_dict[key] - except KeyError: - pass - - if node: - # TODO: better way to do this (it's a linear search, - # but it may not be critical path)? - sourcelist = [] - for b in self.batches: - if node in b.targets: - sourcelist = b.sources - break - else: - sourcelist = self.get_all_sources() - if ignore: - idict = {} - for i in ignore: - idict[i] = 1 - sourcelist = [s for s in sourcelist if s not in idict] - - memo_dict[key] = sourcelist - - return sourcelist - - def get_implicit_deps(self): - """Return the executor's implicit dependencies, i.e. the nodes of - the commands to be executed.""" - result = [] - build_env = self.get_build_env() - for act in self.get_action_list(): - deps = act.get_implicit_deps(self.get_all_targets(), - self.get_all_sources(), - build_env) - result.extend(deps) - return result - - - -_batch_executors = {} - -def GetBatchExecutor(key): - return _batch_executors[key] - -def AddBatchExecutor(key, executor): - assert key not in _batch_executors - _batch_executors[key] = executor - -nullenv = None - - -import SCons.Util -class NullEnvironment(SCons.Util.Null): - import SCons.CacheDir - _CacheDir_path = None - _CacheDir = SCons.CacheDir.CacheDir(None) - def get_CacheDir(self): - return self._CacheDir - - -def get_NullEnvironment(): - """Use singleton pattern for Null Environments.""" - global nullenv - - if nullenv is None: - nullenv = NullEnvironment() - return nullenv - -class Null(object): - """A null Executor, with a null build Environment, that does - nothing when the rest of the methods call it. - - This might be able to disappear when we refactor things to - disassociate Builders from Nodes entirely, so we're not - going to worry about unit tests for this--at least for now. - """ - - __slots__ = ('pre_actions', - 'post_actions', - 'env', - 'overridelist', - 'batches', - 'builder_kw', - '_memo', - 'lvars', - '_changed_sources_list', - '_changed_targets_list', - '_unchanged_sources_list', - '_unchanged_targets_list', - 'action_list', - '_do_execute', - '_execute_str') - - def __init__(self, *args, **kw): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Executor.Null') - self.batches = [Batch(kw['targets'][:], [])] - def get_build_env(self): - return get_NullEnvironment() - def get_build_scanner_path(self): - return None - def cleanup(self): - pass - def prepare(self): - pass - def get_unignored_sources(self, *args, **kw): - return tuple(()) - def get_action_targets(self): - return [] - def get_action_list(self): - return [] - def get_all_targets(self): - return self.batches[0].targets - def get_all_sources(self): - return self.batches[0].targets[0].sources - def get_all_children(self): - return self.batches[0].targets[0].children() - def get_all_prerequisites(self): - return [] - def get_action_side_effects(self): - return [] - def __call__(self, *args, **kw): - return 0 - def get_contents(self): - return '' - def _morph(self): - """Morph this Null executor to a real Executor object.""" - batches = self.batches - self.__class__ = Executor - self.__init__([]) - self.batches = batches - - # The following methods require morphing this Null Executor to a - # real Executor object. - - def add_pre_action(self, action): - self._morph() - self.add_pre_action(action) - def add_post_action(self, action): - self._morph() - self.add_post_action(action) - def set_action_list(self, action): - self._morph() - self.set_action_list(action) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Job.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Job.py deleted file mode 100644 index 60aa0ae..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Job.py +++ /dev/null @@ -1,435 +0,0 @@ -"""SCons.Job - -This module defines the Serial and Parallel classes that execute tasks to -complete a build. The Jobs class provides a higher level interface to start, -stop, and wait on jobs. - -""" - -# -# Copyright (c) 2001 - 2015 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/Job.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.compat - -import os -import signal - -import SCons.Errors - -# The default stack size (in kilobytes) of the threads used to execute -# jobs in parallel. -# -# We use a stack size of 256 kilobytes. The default on some platforms -# is too large and prevents us from creating enough threads to fully -# parallelized the build. For example, the default stack size on linux -# is 8 MBytes. - -explicit_stack_size = None -default_stack_size = 256 - -interrupt_msg = 'Build interrupted.' - - -class InterruptState(object): - def __init__(self): - self.interrupted = False - - def set(self): - self.interrupted = True - - def __call__(self): - return self.interrupted - - -class Jobs(object): - """An instance of this class initializes N jobs, and provides - methods for starting, stopping, and waiting on all N jobs. - """ - - def __init__(self, num, taskmaster): - """ - create 'num' jobs using the given taskmaster. - - If 'num' is 1 or less, then a serial job will be used, - otherwise a parallel job with 'num' worker threads will - be used. - - The 'num_jobs' attribute will be set to the actual number of jobs - allocated. If more than one job is requested but the Parallel - class can't do it, it gets reset to 1. Wrapping interfaces that - care should check the value of 'num_jobs' after initialization. - """ - - self.job = None - if num > 1: - stack_size = explicit_stack_size - if stack_size is None: - stack_size = default_stack_size - - try: - self.job = Parallel(taskmaster, num, stack_size) - self.num_jobs = num - except NameError: - pass - if self.job is None: - self.job = Serial(taskmaster) - self.num_jobs = 1 - - def run(self, postfunc=lambda: None): - """Run the jobs. - - postfunc() will be invoked after the jobs has run. It will be - invoked even if the jobs are interrupted by a keyboard - interrupt (well, in fact by a signal such as either SIGINT, - SIGTERM or SIGHUP). The execution of postfunc() is protected - against keyboard interrupts and is guaranteed to run to - completion.""" - self._setup_sig_handler() - try: - self.job.start() - finally: - postfunc() - self._reset_sig_handler() - - def were_interrupted(self): - """Returns whether the jobs were interrupted by a signal.""" - return self.job.interrupted() - - def _setup_sig_handler(self): - """Setup an interrupt handler so that SCons can shutdown cleanly in - various conditions: - - a) SIGINT: Keyboard interrupt - b) SIGTERM: kill or system shutdown - c) SIGHUP: Controlling shell exiting - - We handle all of these cases by stopping the taskmaster. It - turns out that it very difficult to stop the build process - by throwing asynchronously an exception such as - KeyboardInterrupt. For example, the python Condition - variables (threading.Condition) and queue's do not seem to - asynchronous-exception-safe. It would require adding a whole - bunch of try/finally block and except KeyboardInterrupt all - over the place. - - Note also that we have to be careful to handle the case when - SCons forks before executing another process. In that case, we - want the child to exit immediately. - """ - def handler(signum, stack, self=self, parentpid=os.getpid()): - if os.getpid() == parentpid: - self.job.taskmaster.stop() - self.job.interrupted.set() - else: - os._exit(2) - - self.old_sigint = signal.signal(signal.SIGINT, handler) - self.old_sigterm = signal.signal(signal.SIGTERM, handler) - try: - self.old_sighup = signal.signal(signal.SIGHUP, handler) - except AttributeError: - pass - - def _reset_sig_handler(self): - """Restore the signal handlers to their previous state (before the - call to _setup_sig_handler().""" - - signal.signal(signal.SIGINT, self.old_sigint) - signal.signal(signal.SIGTERM, self.old_sigterm) - try: - signal.signal(signal.SIGHUP, self.old_sighup) - except AttributeError: - pass - -class Serial(object): - """This class is used to execute tasks in series, and is more efficient - than Parallel, but is only appropriate for non-parallel builds. Only - one instance of this class should be in existence at a time. - - This class is not thread safe. - """ - - def __init__(self, taskmaster): - """Create a new serial job given a taskmaster. - - The taskmaster's next_task() method should return the next task - that needs to be executed, or None if there are no more tasks. The - taskmaster's executed() method will be called for each task when it - is successfully executed or failed() will be called if it failed to - execute (e.g. execute() raised an exception).""" - - self.taskmaster = taskmaster - self.interrupted = InterruptState() - - def start(self): - """Start the job. This will begin pulling tasks from the taskmaster - and executing them, and return when there are no more tasks. If a task - fails to execute (i.e. execute() raises an exception), then the job will - stop.""" - - while True: - task = self.taskmaster.next_task() - - if task is None: - break - - try: - task.prepare() - if task.needs_execute(): - task.execute() - except: - if self.interrupted(): - try: - raise SCons.Errors.BuildError( - task.targets[0], errstr=interrupt_msg) - except: - task.exception_set() - else: - task.exception_set() - - # Let the failed() callback function arrange for the - # build to stop if that's appropriate. - task.failed() - else: - task.executed() - - task.postprocess() - self.taskmaster.cleanup() - - -# Trap import failure so that everything in the Job module but the -# Parallel class (and its dependent classes) will work if the interpreter -# doesn't support threads. -try: - import queue - import threading -except ImportError: - pass -else: - class Worker(threading.Thread): - """A worker thread waits on a task to be posted to its request queue, - dequeues the task, executes it, and posts a tuple including the task - and a boolean indicating whether the task executed successfully. """ - - def __init__(self, requestQueue, resultsQueue, interrupted): - threading.Thread.__init__(self) - self.setDaemon(1) - self.requestQueue = requestQueue - self.resultsQueue = resultsQueue - self.interrupted = interrupted - self.start() - - def run(self): - while True: - task = self.requestQueue.get() - - if task is None: - # The "None" value is used as a sentinel by - # ThreadPool.cleanup(). This indicates that there - # are no more tasks, so we should quit. - break - - try: - if self.interrupted(): - raise SCons.Errors.BuildError( - task.targets[0], errstr=interrupt_msg) - task.execute() - except: - task.exception_set() - ok = False - else: - ok = True - - self.resultsQueue.put((task, ok)) - - class ThreadPool(object): - """This class is responsible for spawning and managing worker threads.""" - - def __init__(self, num, stack_size, interrupted): - """Create the request and reply queues, and 'num' worker threads. - - One must specify the stack size of the worker threads. The - stack size is specified in kilobytes. - """ - self.requestQueue = queue.Queue(0) - self.resultsQueue = queue.Queue(0) - - try: - prev_size = threading.stack_size(stack_size*1024) - except AttributeError, e: - # Only print a warning if the stack size has been - # explicitly set. - if not explicit_stack_size is None: - msg = "Setting stack size is unsupported by this version of Python:\n " + \ - e.args[0] - SCons.Warnings.warn(SCons.Warnings.StackSizeWarning, msg) - except ValueError, e: - msg = "Setting stack size failed:\n " + str(e) - SCons.Warnings.warn(SCons.Warnings.StackSizeWarning, msg) - - # Create worker threads - self.workers = [] - for _ in range(num): - worker = Worker(self.requestQueue, self.resultsQueue, interrupted) - self.workers.append(worker) - - if 'prev_size' in locals(): - threading.stack_size(prev_size) - - def put(self, task): - """Put task into request queue.""" - self.requestQueue.put(task) - - def get(self): - """Remove and return a result tuple from the results queue.""" - return self.resultsQueue.get() - - def preparation_failed(self, task): - self.resultsQueue.put((task, False)) - - def cleanup(self): - """ - Shuts down the thread pool, giving each worker thread a - chance to shut down gracefully. - """ - # For each worker thread, put a sentinel "None" value - # on the requestQueue (indicating that there's no work - # to be done) so that each worker thread will get one and - # terminate gracefully. - for _ in self.workers: - self.requestQueue.put(None) - - # Wait for all of the workers to terminate. - # - # If we don't do this, later Python versions (2.4, 2.5) often - # seem to raise exceptions during shutdown. This happens - # in requestQueue.get(), as an assertion failure that - # requestQueue.not_full is notified while not acquired, - # seemingly because the main thread has shut down (or is - # in the process of doing so) while the workers are still - # trying to pull sentinels off the requestQueue. - # - # Normally these terminations should happen fairly quickly, - # but we'll stick a one-second timeout on here just in case - # someone gets hung. - for worker in self.workers: - worker.join(1.0) - self.workers = [] - - class Parallel(object): - """This class is used to execute tasks in parallel, and is somewhat - less efficient than Serial, but is appropriate for parallel builds. - - This class is thread safe. - """ - - def __init__(self, taskmaster, num, stack_size): - """Create a new parallel job given a taskmaster. - - The taskmaster's next_task() method should return the next - task that needs to be executed, or None if there are no more - tasks. The taskmaster's executed() method will be called - for each task when it is successfully executed or failed() - will be called if the task failed to execute (i.e. execute() - raised an exception). - - Note: calls to taskmaster are serialized, but calls to - execute() on distinct tasks are not serialized, because - that is the whole point of parallel jobs: they can execute - multiple tasks simultaneously. """ - - self.taskmaster = taskmaster - self.interrupted = InterruptState() - self.tp = ThreadPool(num, stack_size, self.interrupted) - - self.maxjobs = num - - def start(self): - """Start the job. This will begin pulling tasks from the - taskmaster and executing them, and return when there are no - more tasks. If a task fails to execute (i.e. execute() raises - an exception), then the job will stop.""" - - jobs = 0 - - while True: - # Start up as many available tasks as we're - # allowed to. - while jobs < self.maxjobs: - task = self.taskmaster.next_task() - if task is None: - break - - try: - # prepare task for execution - task.prepare() - except: - task.exception_set() - task.failed() - task.postprocess() - else: - if task.needs_execute(): - # dispatch task - self.tp.put(task) - jobs = jobs + 1 - else: - task.executed() - task.postprocess() - - if not task and not jobs: break - - # Let any/all completed tasks finish up before we go - # back and put the next batch of tasks on the queue. - while True: - task, ok = self.tp.get() - jobs = jobs - 1 - - if ok: - task.executed() - else: - if self.interrupted(): - try: - raise SCons.Errors.BuildError( - task.targets[0], errstr=interrupt_msg) - except: - task.exception_set() - - # Let the failed() callback function arrange - # for the build to stop if that's appropriate. - task.failed() - - task.postprocess() - - if self.tp.resultsQueue.empty(): - break - - self.tp.cleanup() - self.taskmaster.cleanup() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Memoize.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Memoize.py deleted file mode 100644 index 77a8e16..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Memoize.py +++ /dev/null @@ -1,245 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/Memoize.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -__doc__ = """Memoizer - -A decorator-based implementation to count hits and misses of the computed -values that various methods cache in memory. - -Use of this modules assumes that wrapped methods be coded to cache their -values in a consistent way. In particular, it requires that the class uses a -dictionary named "_memo" to store the cached values. - -Here is an example of wrapping a method that returns a computed value, -with no input parameters: - - @SCons.Memoize.CountMethodCall - def foo(self): - - try: # Memoization - return self._memo['foo'] # Memoization - except KeyError: # Memoization - pass # Memoization - - result = self.compute_foo_value() - - self._memo['foo'] = result # Memoization - - return result - -Here is an example of wrapping a method that will return different values -based on one or more input arguments: - - def _bar_key(self, argument): # Memoization - return argument # Memoization - - @SCons.Memoize.CountDictCall(_bar_key) - def bar(self, argument): - - memo_key = argument # Memoization - try: # Memoization - memo_dict = self._memo['bar'] # Memoization - except KeyError: # Memoization - memo_dict = {} # Memoization - self._memo['dict'] = memo_dict # Memoization - else: # Memoization - try: # Memoization - return memo_dict[memo_key] # Memoization - except KeyError: # Memoization - pass # Memoization - - result = self.compute_bar_value(argument) - - memo_dict[memo_key] = result # Memoization - - return result - -Deciding what to cache is tricky, because different configurations -can have radically different performance tradeoffs, and because the -tradeoffs involved are often so non-obvious. Consequently, deciding -whether or not to cache a given method will likely be more of an art than -a science, but should still be based on available data from this module. -Here are some VERY GENERAL guidelines about deciding whether or not to -cache return values from a method that's being called a lot: - - -- The first question to ask is, "Can we change the calling code - so this method isn't called so often?" Sometimes this can be - done by changing the algorithm. Sometimes the *caller* should - be memoized, not the method you're looking at. - - -- The memoized function should be timed with multiple configurations - to make sure it doesn't inadvertently slow down some other - configuration. - - -- When memoizing values based on a dictionary key composed of - input arguments, you don't need to use all of the arguments - if some of them don't affect the return values. - -""" - -# A flag controlling whether or not we actually use memoization. -use_memoizer = None - -# Global list of counter objects -CounterList = {} - -class Counter(object): - """ - Base class for counting memoization hits and misses. - - We expect that the initialization in a matching decorator will - fill in the correct class name and method name that represents - the name of the function being counted. - """ - def __init__(self, cls_name, method_name): - """ - """ - self.cls_name = cls_name - self.method_name = method_name - self.hit = 0 - self.miss = 0 - def key(self): - return self.cls_name+'.'+self.method_name - def display(self): - fmt = " %7d hits %7d misses %s()" - print fmt % (self.hit, self.miss, self.key()) - def __cmp__(self, other): - try: - return cmp(self.key(), other.key()) - except AttributeError: - return 0 - -class CountValue(Counter): - """ - A counter class for simple, atomic memoized values. - - A CountValue object should be instantiated in a decorator for each of - the class's methods that memoizes its return value by simply storing - the return value in its _memo dictionary. - """ - def count(self, *args, **kw): - """ Counts whether the memoized value has already been - set (a hit) or not (a miss). - """ - obj = args[0] - if self.method_name in obj._memo: - self.hit = self.hit + 1 - else: - self.miss = self.miss + 1 - -class CountDict(Counter): - """ - A counter class for memoized values stored in a dictionary, with - keys based on the method's input arguments. - - A CountDict object is instantiated in a decorator for each of the - class's methods that memoizes its return value in a dictionary, - indexed by some key that can be computed from one or more of - its input arguments. - """ - def __init__(self, cls_name, method_name, keymaker): - """ - """ - Counter.__init__(self, cls_name, method_name) - self.keymaker = keymaker - def count(self, *args, **kw): - """ Counts whether the computed key value is already present - in the memoization dictionary (a hit) or not (a miss). - """ - obj = args[0] - try: - memo_dict = obj._memo[self.method_name] - except KeyError: - self.miss = self.miss + 1 - else: - key = self.keymaker(*args, **kw) - if key in memo_dict: - self.hit = self.hit + 1 - else: - self.miss = self.miss + 1 - -def Dump(title=None): - """ Dump the hit/miss count for all the counters - collected so far. - """ - if title: - print title - for counter in sorted(CounterList): - CounterList[counter].display() - -def EnableMemoization(): - global use_memoizer - use_memoizer = 1 - -def CountMethodCall(fn): - """ Decorator for counting memoizer hits/misses while retrieving - a simple value in a class method. It wraps the given method - fn and uses a CountValue object to keep track of the - caching statistics. - Wrapping gets enabled by calling EnableMemoization(). - """ - if use_memoizer: - def wrapper(self, *args, **kwargs): - global CounterList - key = self.__class__.__name__+'.'+fn.__name__ - if key not in CounterList: - CounterList[key] = CountValue(self.__class__.__name__, fn.__name__) - CounterList[key].count(self, *args, **kwargs) - return fn(self, *args, **kwargs) - wrapper.__name__= fn.__name__ - return wrapper - else: - return fn - -def CountDictCall(keyfunc): - """ Decorator for counting memoizer hits/misses while accessing - dictionary values with a key-generating function. Like - CountMethodCall above, it wraps the given method - fn and uses a CountDict object to keep track of the - caching statistics. The dict-key function keyfunc has to - get passed in the decorator call and gets stored in the - CountDict instance. - Wrapping gets enabled by calling EnableMemoization(). - """ - def decorator(fn): - if use_memoizer: - def wrapper(self, *args, **kwargs): - global CounterList - key = self.__class__.__name__+'.'+fn.__name__ - if key not in CounterList: - CounterList[key] = CountDict(self.__class__.__name__, fn.__name__, keyfunc) - CounterList[key].count(self, *args, **kwargs) - return fn(self, *args, **kwargs) - wrapper.__name__= fn.__name__ - return wrapper - else: - return fn - return decorator - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/Alias.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/Alias.py deleted file mode 100644 index 7e13b00..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/Alias.py +++ /dev/null @@ -1,181 +0,0 @@ - -"""scons.Node.Alias - -Alias nodes. - -This creates a hash of global Aliases (dummy targets). - -""" - -# -# Copyright (c) 2001 - 2015 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/Node/Alias.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import collections - -import SCons.Errors -import SCons.Node -import SCons.Util - -class AliasNameSpace(collections.UserDict): - def Alias(self, name, **kw): - if isinstance(name, SCons.Node.Alias.Alias): - return name - try: - a = self[name] - except KeyError: - a = SCons.Node.Alias.Alias(name, **kw) - self[name] = a - return a - - def lookup(self, name, **kw): - try: - return self[name] - except KeyError: - return None - -class AliasNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = ('csig',) - current_version_id = 2 - field_list = ['csig'] - def str_to_node(self, s): - return default_ans.Alias(s) - - def __getstate__(self): - """ - Return all fields that shall be pickled. Walk the slots in the class - hierarchy and add those to the state dictionary. If a '__dict__' slot is - available, copy all entries to the dictionary. Also include the version - id, which is fixed for all instances of a class. - """ - state = getattr(self, '__dict__', {}).copy() - for obj in type(self).mro(): - for name in getattr(obj,'__slots__',()): - if hasattr(self, name): - state[name] = getattr(self, name) - - state['_version_id'] = self.current_version_id - try: - del state['__weakref__'] - except KeyError: - pass - - return state - - def __setstate__(self, state): - """ - Restore the attributes from a pickled state. - """ - # TODO check or discard version - del state['_version_id'] - for key, value in state.items(): - if key not in ('__weakref__',): - setattr(self, key, value) - - -class AliasBuildInfo(SCons.Node.BuildInfoBase): - __slots__ = () - current_version_id = 2 - -class Alias(SCons.Node.Node): - - NodeInfo = AliasNodeInfo - BuildInfo = AliasBuildInfo - - def __init__(self, name): - SCons.Node.Node.__init__(self) - self.name = name - self.changed_since_last_build = 1 - self.store_info = 0 - - def str_for_display(self): - return '"' + self.__str__() + '"' - - def __str__(self): - return self.name - - def make_ready(self): - self.get_csig() - - really_build = SCons.Node.Node.build - is_up_to_date = SCons.Node.Node.children_are_up_to_date - - def is_under(self, dir): - # Make Alias nodes get built regardless of - # what directory scons was run from. Alias nodes - # are outside the filesystem: - return 1 - - def get_contents(self): - """The contents of an alias is the concatenation - of the content signatures of all its sources.""" - childsigs = [n.get_csig() for n in self.children()] - return ''.join(childsigs) - - def sconsign(self): - """An Alias is not recorded in .sconsign files""" - pass - - # - # - # - - def build(self): - """A "builder" for aliases.""" - pass - - def convert(self): - try: del self.builder - except AttributeError: pass - self.reset_executor() - self.build = self.really_build - - def get_csig(self): - """ - Generate a node's content signature, the digested signature - of its content. - - node - the node - cache - alternate node to use for the signature cache - returns - the content signature - """ - try: - return self.ninfo.csig - except AttributeError: - pass - - contents = self.get_contents() - csig = SCons.Util.MD5signature(contents) - self.get_ninfo().csig = csig - return csig - -default_ans = AliasNameSpace() - -SCons.Node.arg2nodes_lookups.append(default_ans.lookup) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/FS.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/FS.py deleted file mode 100644 index b6a1bb5..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/FS.py +++ /dev/null @@ -1,3612 +0,0 @@ -"""scons.Node.FS - -File system nodes. - -These Nodes represent the canonical external objects that people think -of when they think of building software: files and directories. - -This holds a "default_fs" variable that should be initialized with an FS -that can be used by scripts or modules looking for the canonical default. - -""" - -# -# Copyright (c) 2001 - 2015 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/Node/FS.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import fnmatch -import os -import re -import shutil -import stat -import sys -import time -import codecs - -import SCons.Action -import SCons.Debug -from SCons.Debug import logInstanceCreation -import SCons.Errors -import SCons.Memoize -import SCons.Node -import SCons.Node.Alias -import SCons.Subst -import SCons.Util -import SCons.Warnings - -from SCons.Debug import Trace - -print_duplicate = 0 - - -def sconsign_none(node): - raise NotImplementedError - -def sconsign_dir(node): - """Return the .sconsign file info for this directory, - creating it first if necessary.""" - if not node._sconsign: - import SCons.SConsign - node._sconsign = SCons.SConsign.ForDirectory(node) - return node._sconsign - -_sconsign_map = {0 : sconsign_none, - 1 : sconsign_dir} - -class EntryProxyAttributeError(AttributeError): - """ - An AttributeError subclass for recording and displaying the name - of the underlying Entry involved in an AttributeError exception. - """ - def __init__(self, entry_proxy, attribute): - AttributeError.__init__(self) - self.entry_proxy = entry_proxy - self.attribute = attribute - def __str__(self): - entry = self.entry_proxy.get() - fmt = "%s instance %s has no attribute %s" - return fmt % (entry.__class__.__name__, - repr(entry.name), - repr(self.attribute)) - -# The max_drift value: by default, use a cached signature value for -# any file that's been untouched for more than two days. -default_max_drift = 2*24*60*60 - -# -# We stringify these file system Nodes a lot. Turning a file system Node -# into a string is non-trivial, because the final string representation -# can depend on a lot of factors: whether it's a derived target or not, -# whether it's linked to a repository or source directory, and whether -# there's duplication going on. The normal technique for optimizing -# calculations like this is to memoize (cache) the string value, so you -# only have to do the calculation once. -# -# A number of the above factors, however, can be set after we've already -# been asked to return a string for a Node, because a Repository() or -# VariantDir() call or the like may not occur until later in SConscript -# files. So this variable controls whether we bother trying to save -# string values for Nodes. The wrapper interface can set this whenever -# they're done mucking with Repository and VariantDir and the other stuff, -# to let this module know it can start returning saved string values -# for Nodes. -# -Save_Strings = None - -def save_strings(val): - global Save_Strings - Save_Strings = val - -# -# Avoid unnecessary function calls by recording a Boolean value that -# tells us whether or not os.path.splitdrive() actually does anything -# on this system, and therefore whether we need to bother calling it -# when looking up path names in various methods below. -# - -do_splitdrive = None -_my_splitdrive =None - -def initialize_do_splitdrive(): - global do_splitdrive - global has_unc - drive, path = os.path.splitdrive('X:/foo') - has_unc = hasattr(os.path, 'splitunc') - - do_splitdrive = not not drive or has_unc - - global _my_splitdrive - if has_unc: - def splitdrive(p): - if p[1:2] == ':': - return p[:2], p[2:] - if p[0:2] == '//': - # Note that we leave a leading slash in the path - # because UNC paths are always absolute. - return '//', p[1:] - return '', p - else: - def splitdrive(p): - if p[1:2] == ':': - return p[:2], p[2:] - return '', p - _my_splitdrive = splitdrive - - # Keep some commonly used values in global variables to skip to - # module look-up costs. - global OS_SEP - global UNC_PREFIX - global os_sep_is_slash - - OS_SEP = os.sep - UNC_PREFIX = OS_SEP + OS_SEP - os_sep_is_slash = OS_SEP == '/' - -initialize_do_splitdrive() - -# Used to avoid invoking os.path.normpath if not necessary. -needs_normpath_check = re.compile( - r''' - # We need to renormalize the path if it contains any consecutive - # '/' characters. - .*// | - - # We need to renormalize the path if it contains a '..' directory. - # Note that we check for all the following cases: - # - # a) The path is a single '..' - # b) The path starts with '..'. E.g. '../' or '../moredirs' - # but we not match '..abc/'. - # c) The path ends with '..'. E.g. '/..' or 'dirs/..' - # d) The path contains a '..' in the middle. - # E.g. dirs/../moredirs - - (.*/)?\.\.(?:/|$) | - - # We need to renormalize the path if it contains a '.' - # directory, but NOT if it is a single '.' '/' characters. We - # do not want to match a single '.' because this case is checked - # for explicitely since this is common enough case. - # - # Note that we check for all the following cases: - # - # a) We don't match a single '.' - # b) We match if the path starts with '.'. E.g. './' or - # './moredirs' but we not match '.abc/'. - # c) We match if the path ends with '.'. E.g. '/.' or - # 'dirs/.' - # d) We match if the path contains a '.' in the middle. - # E.g. dirs/./moredirs - - \./|.*/\.(?:/|$) - - ''', - re.VERBOSE - ) -needs_normpath_match = needs_normpath_check.match - -# -# SCons.Action objects for interacting with the outside world. -# -# The Node.FS methods in this module should use these actions to -# create and/or remove files and directories; they should *not* use -# os.{link,symlink,unlink,mkdir}(), etc., directly. -# -# Using these SCons.Action objects ensures that descriptions of these -# external activities are properly displayed, that the displays are -# suppressed when the -s (silent) option is used, and (most importantly) -# the actions are disabled when the the -n option is used, in which case -# there should be *no* changes to the external file system(s)... -# - -if hasattr(os, 'link'): - def _hardlink_func(fs, src, dst): - # If the source is a symlink, we can't just hard-link to it - # because a relative symlink may point somewhere completely - # different. We must disambiguate the symlink and then - # hard-link the final destination file. - while fs.islink(src): - link = fs.readlink(src) - if not os.path.isabs(link): - src = link - else: - src = os.path.join(os.path.dirname(src), link) - fs.link(src, dst) -else: - _hardlink_func = None - -if hasattr(os, 'symlink'): - def _softlink_func(fs, src, dst): - fs.symlink(src, dst) -else: - _softlink_func = None - -def _copy_func(fs, src, dest): - shutil.copy2(src, dest) - st = fs.stat(src) - fs.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) - - -Valid_Duplicates = ['hard-soft-copy', 'soft-hard-copy', - 'hard-copy', 'soft-copy', 'copy'] - -Link_Funcs = [] # contains the callables of the specified duplication style - -def set_duplicate(duplicate): - # Fill in the Link_Funcs list according to the argument - # (discarding those not available on the platform). - - # Set up the dictionary that maps the argument names to the - # underlying implementations. We do this inside this function, - # not in the top-level module code, so that we can remap os.link - # and os.symlink for testing purposes. - link_dict = { - 'hard' : _hardlink_func, - 'soft' : _softlink_func, - 'copy' : _copy_func - } - - if not duplicate in Valid_Duplicates: - raise SCons.Errors.InternalError("The argument of set_duplicate " - "should be in Valid_Duplicates") - global Link_Funcs - Link_Funcs = [] - for func in duplicate.split('-'): - if link_dict[func]: - 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 ... - src = source[0].get_abspath() - dest = target[0].get_abspath() - dir, file = os.path.split(dest) - if dir and not target[0].fs.isdir(dir): - os.makedirs(dir) - if not Link_Funcs: - # Set a default order of link functions. - set_duplicate('hard-soft-copy') - fs = source[0].fs - # Now link the files with the previously specified order. - for func in Link_Funcs: - try: - func(fs, src, dest) - break - except (IOError, OSError): - # An OSError indicates something happened like a permissions - # problem or an attempt to symlink across file-system - # boundaries. An IOError indicates something like the file - # not existing. In either case, keeping trying additional - # functions in the list and only raise an error if the last - # one failed. - if func == Link_Funcs[-1]: - # exception of the last link method (copy) are fatal - raise - return 0 - -Link = SCons.Action.Action(LinkFunc, None) -def LocalString(target, source, env): - return 'Local copy of %s from %s' % (target[0], source[0]) - -LocalCopy = SCons.Action.Action(LinkFunc, LocalString) - -def UnlinkFunc(target, source, env): - t = target[0] - t.fs.unlink(t.get_abspath()) - return 0 - -Unlink = SCons.Action.Action(UnlinkFunc, None) - -def MkdirFunc(target, source, env): - t = target[0] - if not t.exists(): - t.fs.mkdir(t.get_abspath()) - return 0 - -Mkdir = SCons.Action.Action(MkdirFunc, None, presub=None) - -MkdirBuilder = None - -def get_MkdirBuilder(): - global MkdirBuilder - if MkdirBuilder is None: - import SCons.Builder - import SCons.Defaults - # "env" will get filled in by Executor.get_build_env() - # calling SCons.Defaults.DefaultEnvironment() when necessary. - MkdirBuilder = SCons.Builder.Builder(action = Mkdir, - env = None, - explain = None, - is_explicit = None, - target_scanner = SCons.Defaults.DirEntryScanner, - name = "MkdirBuilder") - return MkdirBuilder - -class _Null(object): - pass - -_null = _Null() - -DefaultSCCSBuilder = None -DefaultRCSBuilder = None - -def get_DefaultSCCSBuilder(): - global DefaultSCCSBuilder - if DefaultSCCSBuilder is None: - import SCons.Builder - # "env" will get filled in by Executor.get_build_env() - # calling SCons.Defaults.DefaultEnvironment() when necessary. - act = SCons.Action.Action('$SCCSCOM', '$SCCSCOMSTR') - DefaultSCCSBuilder = SCons.Builder.Builder(action = act, - env = None, - name = "DefaultSCCSBuilder") - return DefaultSCCSBuilder - -def get_DefaultRCSBuilder(): - global DefaultRCSBuilder - if DefaultRCSBuilder is None: - import SCons.Builder - # "env" will get filled in by Executor.get_build_env() - # calling SCons.Defaults.DefaultEnvironment() when necessary. - act = SCons.Action.Action('$RCS_COCOM', '$RCS_COCOMSTR') - DefaultRCSBuilder = SCons.Builder.Builder(action = act, - env = None, - name = "DefaultRCSBuilder") - return DefaultRCSBuilder - -# Cygwin's os.path.normcase pretends it's on a case-sensitive filesystem. -_is_cygwin = sys.platform == "cygwin" -if os.path.normcase("TeSt") == os.path.normpath("TeSt") and not _is_cygwin: - def _my_normcase(x): - return x -else: - def _my_normcase(x): - return x.upper() - - - -class DiskChecker(object): - def __init__(self, type, do, ignore): - self.type = type - self.do = do - self.ignore = ignore - self.func = do - def __call__(self, *args, **kw): - return self.func(*args, **kw) - def set(self, list): - if self.type in list: - self.func = self.do - else: - self.func = self.ignore - -def do_diskcheck_match(node, predicate, errorfmt): - result = predicate() - try: - # If calling the predicate() cached a None value from stat(), - # remove it so it doesn't interfere with later attempts to - # build this Node as we walk the DAG. (This isn't a great way - # to do this, we're reaching into an interface that doesn't - # really belong to us, but it's all about performance, so - # for now we'll just document the dependency...) - if node._memo['stat'] is None: - del node._memo['stat'] - except (AttributeError, KeyError): - pass - if result: - raise TypeError(errorfmt % node.get_abspath()) - -def ignore_diskcheck_match(node, predicate, errorfmt): - pass - -def do_diskcheck_rcs(node, name): - try: - rcs_dir = node.rcs_dir - except AttributeError: - if node.entry_exists_on_disk('RCS'): - rcs_dir = node.Dir('RCS') - else: - rcs_dir = None - node.rcs_dir = rcs_dir - if rcs_dir: - return rcs_dir.entry_exists_on_disk(name+',v') - return None - -def ignore_diskcheck_rcs(node, name): - return None - -def do_diskcheck_sccs(node, name): - try: - sccs_dir = node.sccs_dir - except AttributeError: - if node.entry_exists_on_disk('SCCS'): - sccs_dir = node.Dir('SCCS') - else: - sccs_dir = None - node.sccs_dir = sccs_dir - if sccs_dir: - return sccs_dir.entry_exists_on_disk('s.'+name) - return None - -def ignore_diskcheck_sccs(node, name): - return None - -diskcheck_match = DiskChecker('match', do_diskcheck_match, ignore_diskcheck_match) -diskcheck_rcs = DiskChecker('rcs', do_diskcheck_rcs, ignore_diskcheck_rcs) -diskcheck_sccs = DiskChecker('sccs', do_diskcheck_sccs, ignore_diskcheck_sccs) - -diskcheckers = [ - diskcheck_match, - diskcheck_rcs, - diskcheck_sccs, -] - -def set_diskcheck(list): - for dc in diskcheckers: - dc.set(list) - -def diskcheck_types(): - return [dc.type for dc in diskcheckers] - - - -class EntryProxy(SCons.Util.Proxy): - - __str__ = SCons.Util.Delegate('__str__') - - def __get_abspath(self): - entry = self.get() - return SCons.Subst.SpecialAttrWrapper(entry.get_abspath(), - entry.name + "_abspath") - - def __get_filebase(self): - name = self.get().name - return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(name)[0], - name + "_filebase") - - def __get_suffix(self): - name = self.get().name - return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(name)[1], - name + "_suffix") - - def __get_file(self): - name = self.get().name - return SCons.Subst.SpecialAttrWrapper(name, name + "_file") - - def __get_base_path(self): - """Return the file's directory and file name, with the - suffix stripped.""" - entry = self.get() - return SCons.Subst.SpecialAttrWrapper(SCons.Util.splitext(entry.get_path())[0], - entry.name + "_base") - - def __get_posix_path(self): - """Return the path with / as the path separator, - regardless of platform.""" - if os_sep_is_slash: - return self - else: - entry = self.get() - r = entry.get_path().replace(OS_SEP, '/') - return SCons.Subst.SpecialAttrWrapper(r, entry.name + "_posix") - - def __get_windows_path(self): - """Return the path with \ as the path separator, - regardless of platform.""" - if OS_SEP == '\\': - return self - else: - entry = self.get() - r = entry.get_path().replace(OS_SEP, '\\') - return SCons.Subst.SpecialAttrWrapper(r, entry.name + "_windows") - - def __get_srcnode(self): - return EntryProxy(self.get().srcnode()) - - def __get_srcdir(self): - """Returns the directory containing the source node linked to this - node via VariantDir(), or the directory of this node if not linked.""" - return EntryProxy(self.get().srcnode().dir) - - def __get_rsrcnode(self): - return EntryProxy(self.get().srcnode().rfile()) - - def __get_rsrcdir(self): - """Returns the directory containing the source node linked to this - node via VariantDir(), or the directory of this node if not linked.""" - return EntryProxy(self.get().srcnode().rfile().dir) - - def __get_dir(self): - return EntryProxy(self.get().dir) - - dictSpecialAttrs = { "base" : __get_base_path, - "posix" : __get_posix_path, - "windows" : __get_windows_path, - "win32" : __get_windows_path, - "srcpath" : __get_srcnode, - "srcdir" : __get_srcdir, - "dir" : __get_dir, - "abspath" : __get_abspath, - "filebase" : __get_filebase, - "suffix" : __get_suffix, - "file" : __get_file, - "rsrcpath" : __get_rsrcnode, - "rsrcdir" : __get_rsrcdir, - } - - def __getattr__(self, name): - # This is how we implement the "special" attributes - # such as base, posix, srcdir, etc. - try: - attr_function = self.dictSpecialAttrs[name] - except KeyError: - try: - attr = SCons.Util.Proxy.__getattr__(self, name) - except AttributeError, e: - # Raise our own AttributeError subclass with an - # overridden __str__() method that identifies the - # name of the entry that caused the exception. - raise EntryProxyAttributeError(self, name) - return attr - else: - return attr_function(self) - -class Base(SCons.Node.Node): - """A generic class for file system entries. This class is for - when we don't know yet whether the entry being looked up is a file - or a directory. Instances of this class can morph into either - Dir or File objects by a later, more precise lookup. - - Note: this class does not define __cmp__ and __hash__ for - efficiency reasons. SCons does a lot of comparing of - Node.FS.{Base,Entry,File,Dir} objects, so those operations must be - as fast as possible, which means we want to use Python's built-in - object identity comparisons. - """ - - __slots__ = ['name', - 'fs', - '_abspath', - '_labspath', - '_path', - '_tpath', - '_path_elements', - 'dir', - 'cwd', - 'duplicate', - '_local', - 'sbuilder', - '_proxy', - '_func_sconsign'] - - def __init__(self, name, directory, fs): - """Initialize a generic Node.FS.Base object. - - Call the superclass initialization, take care of setting up - our relative and absolute paths, identify our parent - directory, and indicate that this node should use - signatures.""" - if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS.Base') - SCons.Node.Node.__init__(self) - - # Filenames and paths are probably reused and are intern'ed to - # save some memory. - - #: Filename with extension as it was specified when the object was - #: created; to obtain filesystem path, use Python str() function - self.name = SCons.Util.silent_intern(name) - self.fs = fs #: Reference to parent Node.FS object - - assert directory, "A directory must be provided" - - self._abspath = None - self._labspath = None - self._path = None - self._tpath = None - self._path_elements = None - - self.dir = directory - self.cwd = None # will hold the SConscript directory for target nodes - self.duplicate = directory.duplicate - self.changed_since_last_build = 2 - self._func_sconsign = 0 - self._func_exists = 2 - self._func_rexists = 2 - self._func_get_contents = 0 - self._func_target_from_source = 1 - self.store_info = 1 - - def str_for_display(self): - return '"' + self.__str__() + '"' - - def must_be_same(self, klass): - """ - This node, which already existed, is being looked up as the - specified klass. Raise an exception if it isn't. - """ - if isinstance(self, klass) or klass is Entry: - return - raise TypeError("Tried to lookup %s '%s' as a %s." %\ - (self.__class__.__name__, self.get_internal_path(), klass.__name__)) - - def get_dir(self): - return self.dir - - def get_suffix(self): - return SCons.Util.splitext(self.name)[1] - - def rfile(self): - return self - - def __getattr__(self, attr): - """ Together with the node_bwcomp dict defined below, - this method provides a simple backward compatibility - layer for the Node attributes 'abspath', 'labspath', - 'path', 'tpath', 'suffix' and 'path_elements'. These Node - attributes used to be directly available in v2.3 and earlier, but - have been replaced by getter methods that initialize the - single variables lazily when required, in order to save memory. - The redirection to the getters lets older Tools and - SConstruct continue to work without any additional changes, - fully transparent to the user. - Note, that __getattr__ is only called as fallback when the - requested attribute can't be found, so there should be no - speed performance penalty involved for standard builds. - """ - if attr in node_bwcomp: - return node_bwcomp[attr](self) - - raise AttributeError("%r object has no attribute %r" % - (self.__class__, attr)) - - def __str__(self): - """A Node.FS.Base object's string representation is its path - name.""" - global Save_Strings - if Save_Strings: - return self._save_str() - return self._get_str() - - @SCons.Memoize.CountMethodCall - def _save_str(self): - try: - return self._memo['_save_str'] - except KeyError: - pass - result = sys.intern(self._get_str()) - self._memo['_save_str'] = result - return result - - def _get_str(self): - global Save_Strings - if self.duplicate or self.is_derived(): - return self.get_path() - srcnode = self.srcnode() - if srcnode.stat() is None and self.stat() is not None: - result = self.get_path() - else: - result = srcnode.get_path() - if not Save_Strings: - # We're not at the point where we're saving the string - # representations of FS Nodes (because we haven't finished - # reading the SConscript files and need to have str() return - # things relative to them). That also means we can't yet - # cache values returned (or not returned) by stat(), since - # Python code in the SConscript files might still create - # or otherwise affect the on-disk file. So get rid of the - # values that the underlying stat() method saved. - try: del self._memo['stat'] - except KeyError: pass - if self is not srcnode: - try: del srcnode._memo['stat'] - except KeyError: pass - return result - - rstr = __str__ - - @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 - self._memo['stat'] = result - return result - - def exists(self): - return SCons.Node._exists_map[self._func_exists](self) - - def rexists(self): - return SCons.Node._rexists_map[self._func_rexists](self) - - def getmtime(self): - st = self.stat() - 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 - - def isdir(self): - st = self.stat() - return st is not None and stat.S_ISDIR(st[stat.ST_MODE]) - - def isfile(self): - st = self.stat() - return st is not None and stat.S_ISREG(st[stat.ST_MODE]) - - if hasattr(os, 'symlink'): - def islink(self): - try: st = self.fs.lstat(self.get_abspath()) - except os.error: return 0 - return stat.S_ISLNK(st[stat.ST_MODE]) - else: - def islink(self): - return 0 # no symlinks - - def is_under(self, dir): - if self is dir: - return 1 - else: - return self.dir.is_under(dir) - - def set_local(self): - self._local = 1 - - def srcnode(self): - """If this node is in a build path, return the node - corresponding to its source file. Otherwise, return - ourself. - """ - srcdir_list = self.dir.srcdir_list() - if srcdir_list: - srcnode = srcdir_list[0].Entry(self.name) - srcnode.must_be_same(self.__class__) - return srcnode - return self - - def get_path(self, dir=None): - """Return path relative to the current working directory of the - Node.FS.Base object that owns us.""" - if not dir: - dir = self.fs.getcwd() - if self == dir: - return '.' - path_elems = self.get_path_elements() - pathname = '' - try: i = path_elems.index(dir) - except ValueError: - for p in path_elems[:-1]: - pathname += p.dirname - else: - for p in path_elems[i+1:-1]: - pathname += p.dirname - return pathname + path_elems[-1].name - - def set_src_builder(self, builder): - """Set the source code builder for this node.""" - self.sbuilder = builder - if not self.has_builder(): - self.builder_set(builder) - - def src_builder(self): - """Fetch the source code builder for this node. - - If there isn't one, we cache the source code builder specified - for the directory (which in turn will cache the value from its - parent directory, and so on up to the file system root). - """ - try: - scb = self.sbuilder - except AttributeError: - scb = self.dir.src_builder() - self.sbuilder = scb - return scb - - def get_abspath(self): - """Get the absolute path of the file.""" - return self.dir.entry_abspath(self.name) - - def get_labspath(self): - """Get the absolute path of the file.""" - return self.dir.entry_labspath(self.name) - - def get_internal_path(self): - if self.dir._path == '.': - return self.name - else: - return self.dir.entry_path(self.name) - - def get_tpath(self): - if self.dir._tpath == '.': - return self.name - else: - return self.dir.entry_tpath(self.name) - - def get_path_elements(self): - return self.dir._path_elements + [self] - - def for_signature(self): - # Return just our name. Even an absolute path would not work, - # because that can change thanks to symlinks or remapped network - # paths. - return self.name - - def get_subst_proxy(self): - try: - return self._proxy - except AttributeError: - ret = EntryProxy(self) - self._proxy = ret - return ret - - def target_from_source(self, prefix, suffix, splitext=SCons.Util.splitext): - """ - - Generates a target entry that corresponds to this entry (usually - a source file) with the specified prefix and suffix. - - Note that this method can be overridden dynamically for generated - files that need different behavior. See Tool/swig.py for - an example. - """ - return SCons.Node._target_from_source_map[self._func_target_from_source](self, prefix, suffix, splitext) - - def _Rfindalldirs_key(self, pathlist): - return pathlist - - @SCons.Memoize.CountDictCall(_Rfindalldirs_key) - def Rfindalldirs(self, pathlist): - """ - Return all of the directories for a given path list, including - corresponding "backing" directories in any repositories. - - The Node lookups are relative to this Node (typically a - directory), so memoizing result saves cycles from looking - up the same path for each target in a given directory. - """ - try: - memo_dict = self._memo['Rfindalldirs'] - except KeyError: - memo_dict = {} - self._memo['Rfindalldirs'] = memo_dict - else: - try: - return memo_dict[pathlist] - except KeyError: - pass - - create_dir_relative_to_self = self.Dir - result = [] - for path in pathlist: - if isinstance(path, SCons.Node.Node): - result.append(path) - else: - dir = create_dir_relative_to_self(path) - result.extend(dir.get_all_rdirs()) - - memo_dict[pathlist] = result - - return result - - def RDirs(self, pathlist): - """Search for a list of directories in the Repository list.""" - cwd = self.cwd or self.fs._cwd - return cwd.Rfindalldirs(pathlist) - - @SCons.Memoize.CountMethodCall - def rentry(self): - try: - return self._memo['rentry'] - except KeyError: - pass - 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: - if dir.entry_exists_on_disk(self.name): - result = dir.Entry(self.name) - break - self._memo['rentry'] = result - return result - - def _glob1(self, pattern, ondisk=True, source=False, strings=False): - return [] - -# Dict that provides a simple backward compatibility -# layer for the Node attributes 'abspath', 'labspath', -# 'path', 'tpath' and 'path_elements'. -# @see Base.__getattr__ above -node_bwcomp = {'abspath' : Base.get_abspath, - 'labspath' : Base.get_labspath, - 'path' : Base.get_internal_path, - 'tpath' : Base.get_tpath, - 'path_elements' : Base.get_path_elements, - 'suffix' : Base.get_suffix} - -class Entry(Base): - """This is the class for generic Node.FS entries--that is, things - that could be a File or a Dir, but we're just not sure yet. - Consequently, the methods in this class really exist just to - transform their associated object into the right class when the - time comes, and then call the same-named method in the transformed - class.""" - - __slots__ = ['scanner_paths', - 'cachedir_csig', - 'cachesig', - 'repositories', - 'srcdir', - 'entries', - 'searched', - '_sconsign', - 'variant_dirs', - 'root', - 'dirname', - 'on_disk_entries', - 'sccs_dir', - 'rcs_dir', - 'released_target_info', - 'contentsig'] - - def __init__(self, name, directory, fs): - Base.__init__(self, name, directory, fs) - self._func_exists = 3 - self._func_get_contents = 1 - - def diskcheck_match(self): - pass - - def disambiguate(self, must_exist=None): - """ - """ - if self.isdir(): - self.__class__ = Dir - self._morph() - elif self.isfile(): - self.__class__ = File - self._morph() - self.clear() - else: - # There was nothing on-disk at this location, so look in - # the src directory. - # - # We can't just use self.srcnode() straight away because - # that would create an actual Node for this file in the src - # directory, and there might not be one. Instead, use the - # dir_on_disk() method to see if there's something on-disk - # with that name, in which case we can go ahead and call - # self.srcnode() to create the right type of entry. - srcdir = self.dir.srcnode() - if srcdir != self.dir and \ - srcdir.entry_exists_on_disk(self.name) and \ - self.srcnode().isdir(): - self.__class__ = Dir - self._morph() - elif must_exist: - msg = "No such file or directory: '%s'" % self.get_abspath() - raise SCons.Errors.UserError(msg) - else: - self.__class__ = File - self._morph() - self.clear() - return self - - def rfile(self): - """We're a generic Entry, but the caller is actually looking for - a File at this point, so morph into one.""" - self.__class__ = File - self._morph() - self.clear() - return File.rfile(self) - - def scanner_key(self): - return self.get_suffix() - - def get_contents(self): - """Fetch the contents of the entry. Returns the exact binary - contents of the file.""" - return SCons.Node._get_contents_map[self._func_get_contents](self) - - def get_text_contents(self): - """Fetch the decoded text contents of a Unicode encoded Entry. - - Since this should return the text contents from the file - system, we check to see into what sort of subclass we should - morph this Entry.""" - try: - self = self.disambiguate(must_exist=1) - except SCons.Errors.UserError: - # There was nothing on disk with which to disambiguate - # this entry. Leave it as an Entry, but return a null - # string so calls to get_text_contents() in emitters and - # the like (e.g. in qt.py) don't have to disambiguate by - # hand or catch the exception. - return '' - else: - return self.get_text_contents() - - def must_be_same(self, klass): - """Called to make sure a Node is a Dir. Since we're an - Entry, we can morph into one.""" - if self.__class__ is not klass: - self.__class__ = klass - self._morph() - self.clear() - - # The following methods can get called before the Taskmaster has - # had a chance to call disambiguate() directly to see if this Entry - # should really be a Dir or a File. We therefore use these to call - # disambiguate() transparently (from our caller's point of view). - # - # Right now, this minimal set of methods has been derived by just - # looking at some of the methods that will obviously be called early - # in any of the various Taskmasters' calling sequences, and then - # empirically figuring out which additional methods are necessary - # to make various tests pass. - - def exists(self): - return SCons.Node._exists_map[self._func_exists](self) - - def rel_path(self, other): - d = self.disambiguate() - if d.__class__ is Entry: - raise Exception("rel_path() could not disambiguate File/Dir") - return d.rel_path(other) - - def new_ninfo(self): - return self.disambiguate().new_ninfo() - - def _glob1(self, pattern, ondisk=True, source=False, strings=False): - return self.disambiguate()._glob1(pattern, ondisk, source, strings) - - def get_subst_proxy(self): - return self.disambiguate().get_subst_proxy() - -# This is for later so we can differentiate between Entry the class and Entry -# the method of the FS class. -_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? - #def chdir(self, path): - # return os.chdir(path) - def chmod(self, path, mode): - return os.chmod(path, mode) - def copy(self, src, dst): - return shutil.copy(src, dst) - def copy2(self, src, dst): - return shutil.copy2(src, dst) - def exists(self, path): - return os.path.exists(path) - def getmtime(self, path): - return os.path.getmtime(path) - def getsize(self, path): - return os.path.getsize(path) - def isdir(self, path): - return os.path.isdir(path) - def isfile(self, path): - return os.path.isfile(path) - def link(self, src, dst): - return os.link(src, dst) - def lstat(self, path): - return os.lstat(path) - def listdir(self, path): - return os.listdir(path) - def makedirs(self, path): - return os.makedirs(path) - def mkdir(self, path): - return os.mkdir(path) - def rename(self, old, new): - return os.rename(old, new) - def stat(self, path): - return os.stat(path) - def symlink(self, src, dst): - return os.symlink(src, dst) - def open(self, path): - return open(path) - def unlink(self, path): - return os.unlink(path) - - if hasattr(os, 'symlink'): - def islink(self, path): - return os.path.islink(path) - else: - def islink(self, path): - return 0 # no symlinks - - if hasattr(os, 'readlink'): - def readlink(self, file): - return os.readlink(file) - else: - def readlink(self, file): - return '' - - -#class RemoteFS: -# # Skeleton for the obvious methods we might need from the -# # abstraction layer for a remote filesystem. -# def upload(self, local_src, remote_dst): -# pass -# def download(self, remote_src, local_dst): -# pass - - -class FS(LocalFS): - - def __init__(self, path = None): - """Initialize the Node.FS subsystem. - - The supplied path is the top of the source tree, where we - expect to find the top-level build file. If no path is - supplied, the current directory is the default. - - The path argument must be a valid absolute path. - """ - if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS') - - self._memo = {} - - self.Root = {} - self.SConstruct_dir = None - self.max_drift = default_max_drift - - self.Top = None - if path is None: - self.pathTop = os.getcwd() - else: - self.pathTop = path - self.defaultDrive = _my_normcase(_my_splitdrive(self.pathTop)[0]) - - self.Top = self.Dir(self.pathTop) - self.Top._path = '.' - self.Top._tpath = '.' - self._cwd = self.Top - - DirNodeInfo.fs = self - FileNodeInfo.fs = self - - def set_SConstruct_dir(self, dir): - self.SConstruct_dir = dir - - def get_max_drift(self): - return self.max_drift - - def set_max_drift(self, max_drift): - self.max_drift = max_drift - - def getcwd(self): - if hasattr(self, "_cwd"): - return self._cwd - else: - return "" - - def chdir(self, dir, change_os_dir=0): - """Change the current working directory for lookups. - If change_os_dir is true, we will also change the "real" cwd - to match. - """ - curr=self._cwd - try: - if dir is not None: - self._cwd = dir - if change_os_dir: - os.chdir(dir.get_abspath()) - except OSError: - self._cwd = curr - raise - - def get_root(self, drive): - """ - Returns the root directory for the specified drive, creating - it if necessary. - """ - drive = _my_normcase(drive) - try: - return self.Root[drive] - except KeyError: - root = RootDir(drive, self) - self.Root[drive] = root - if not drive: - self.Root[self.defaultDrive] = root - elif drive == self.defaultDrive: - self.Root[''] = root - return root - - def _lookup(self, p, directory, fsclass, create=1): - """ - The generic entry point for Node lookup with user-supplied data. - - This translates arbitrary input into a canonical Node.FS object - of the specified fsclass. The general approach for strings is - to turn it into a fully normalized absolute path and then call - the root directory's lookup_abs() method for the heavy lifting. - - If the path name begins with '#', it is unconditionally - interpreted relative to the top-level directory of this FS. '#' - is treated as a synonym for the top-level SConstruct directory, - much like '~' is treated as a synonym for the user's home - directory in a UNIX shell. So both '#foo' and '#/foo' refer - to the 'foo' subdirectory underneath the top-level SConstruct - directory. - - If the path name is relative, then the path is looked up relative - to the specified directory, or the current directory (self._cwd, - typically the SConscript directory) if the specified directory - is None. - """ - if isinstance(p, Base): - # It's already a Node.FS object. Make sure it's the right - # class and return. - p.must_be_same(fsclass) - return p - # str(p) in case it's something like a proxy object - p = str(p) - - if not os_sep_is_slash: - p = p.replace(OS_SEP, '/') - - if p[0:1] == '#': - # There was an initial '#', so we strip it and override - # whatever directory they may have specified with the - # top-level SConstruct directory. - p = p[1:] - directory = self.Top - - # There might be a drive letter following the - # '#'. Although it is not described in the SCons man page, - # the regression test suite explicitly tests for that - # syntax. It seems to mean the following thing: - # - # Assuming the the SCons top dir is in C:/xxx/yyy, - # '#X:/toto' means X:/xxx/yyy/toto. - # - # i.e. it assumes that the X: drive has a directory - # structure similar to the one found on drive C:. - if do_splitdrive: - drive, p = _my_splitdrive(p) - if drive: - root = self.get_root(drive) - else: - root = directory.root - else: - root = directory.root - - # We can only strip trailing after splitting the drive - # since the drive might the UNC '//' prefix. - p = p.strip('/') - - needs_normpath = needs_normpath_match(p) - - # The path is relative to the top-level SCons directory. - if p in ('', '.'): - p = directory.get_labspath() - else: - p = directory.get_labspath() + '/' + p - else: - if do_splitdrive: - drive, p = _my_splitdrive(p) - if drive and not p: - # This causes a naked drive letter to be treated - # as a synonym for the root directory on that - # drive. - p = '/' - else: - drive = '' - - # We can only strip trailing '/' since the drive might the - # UNC '//' prefix. - if p != '/': - p = p.rstrip('/') - - needs_normpath = needs_normpath_match(p) - - if p[0:1] == '/': - # Absolute path - root = self.get_root(drive) - else: - # This is a relative lookup or to the current directory - # (the path name is not absolute). Add the string to the - # appropriate directory lookup path, after which the whole - # thing gets normalized. - if directory: - if not isinstance(directory, Dir): - directory = self.Dir(directory) - else: - directory = self._cwd - - if p in ('', '.'): - p = directory.get_labspath() - else: - p = directory.get_labspath() + '/' + p - - if drive: - root = self.get_root(drive) - else: - root = directory.root - - if needs_normpath is not None: - # Normalize a pathname. Will return the same result for - # equivalent paths. - # - # We take advantage of the fact that we have an absolute - # path here for sure. In addition, we know that the - # components of lookup path are separated by slashes at - # this point. Because of this, this code is about 2X - # faster than calling os.path.normpath() followed by - # replacing os.sep with '/' again. - ins = p.split('/')[1:] - outs = [] - for d in ins: - if d == '..': - try: - outs.pop() - except IndexError: - pass - elif d not in ('', '.'): - outs.append(d) - p = '/' + '/'.join(outs) - - return root._lookup_abs(p, fsclass, create) - - def Entry(self, name, directory = None, create = 1): - """Look up or create a generic Entry node with the specified name. - If the name is a relative path (begins with ./, ../, or a file - name), then it is looked up relative to the supplied directory - node, or to the top level directory of the FS (supplied at - construction time) if no directory is supplied. - """ - return self._lookup(name, directory, Entry, create) - - def File(self, name, directory = None, create = 1): - """Look up or create a File node with the specified name. If - the name is a relative path (begins with ./, ../, or a file name), - then it is looked up relative to the supplied directory node, - or to the top level directory of the FS (supplied at construction - time) if no directory is supplied. - - This method will raise TypeError if a directory is found at the - specified path. - """ - return self._lookup(name, directory, File, create) - - def Dir(self, name, directory = None, create = True): - """Look up or create a Dir node with the specified name. If - the name is a relative path (begins with ./, ../, or a file name), - then it is looked up relative to the supplied directory node, - or to the top level directory of the FS (supplied at construction - time) if no directory is supplied. - - This method will raise TypeError if a normal file is found at the - specified path. - """ - return self._lookup(name, directory, Dir, create) - - def VariantDir(self, variant_dir, src_dir, duplicate=1): - """Link the supplied variant directory to the source directory - for purposes of building files.""" - - if not isinstance(src_dir, SCons.Node.Node): - src_dir = self.Dir(src_dir) - if not isinstance(variant_dir, SCons.Node.Node): - variant_dir = self.Dir(variant_dir) - if src_dir.is_under(variant_dir): - raise SCons.Errors.UserError("Source directory cannot be under variant directory.") - if variant_dir.srcdir: - if variant_dir.srcdir == src_dir: - return # We already did this. - raise SCons.Errors.UserError("'%s' already has a source directory: '%s'."%(variant_dir, variant_dir.srcdir)) - variant_dir.link(src_dir, duplicate) - - def Repository(self, *dirs): - """Specify Repository directories to search.""" - for d in dirs: - if not isinstance(d, SCons.Node.Node): - d = self.Dir(d) - self.Top.addRepository(d) - - def variant_dir_target_climb(self, orig, dir, tail): - """Create targets in corresponding variant directories - - Climb the directory tree, and look up path names - relative to any linked variant directories we find. - - Even though this loops and walks up the tree, we don't memoize - the return value because this is really only used to process - the command-line targets. - """ - targets = [] - message = None - fmt = "building associated VariantDir targets: %s" - start_dir = dir - while dir: - for bd in dir.variant_dirs: - if start_dir.is_under(bd): - # If already in the build-dir location, don't reflect - return [orig], fmt % str(orig) - p = os.path.join(bd._path, *tail) - targets.append(self.Entry(p)) - tail = [dir.name] + tail - dir = dir.up() - if targets: - message = fmt % ' '.join(map(str, targets)) - return targets, message - - def Glob(self, pathname, ondisk=True, source=True, strings=False, exclude=None, cwd=None): - """ - Globs - - This is mainly a shim layer - """ - if cwd is None: - cwd = self.getcwd() - return cwd.glob(pathname, ondisk, source, strings, exclude) - -class DirNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = () - # This should get reset by the FS initialization. - current_version_id = 2 - - fs = None - - def str_to_node(self, s): - top = self.fs.Top - root = top.root - if do_splitdrive: - drive, s = _my_splitdrive(s) - if drive: - root = self.fs.get_root(drive) - if not os.path.isabs(s): - s = top.get_labspath() + '/' + s - return root._lookup_abs(s, Entry) - -class DirBuildInfo(SCons.Node.BuildInfoBase): - __slots__ = () - current_version_id = 2 - -glob_magic_check = re.compile('[*?[]') - -def has_glob_magic(s): - return glob_magic_check.search(s) is not None - -class Dir(Base): - """A class for directories in a file system. - """ - - __slots__ = ['scanner_paths', - 'cachedir_csig', - 'cachesig', - 'repositories', - 'srcdir', - 'entries', - 'searched', - '_sconsign', - 'variant_dirs', - 'root', - 'dirname', - 'on_disk_entries', - 'sccs_dir', - 'rcs_dir', - 'released_target_info', - 'contentsig'] - - NodeInfo = DirNodeInfo - BuildInfo = DirBuildInfo - - def __init__(self, name, directory, fs): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS.Dir') - Base.__init__(self, name, directory, fs) - self._morph() - - def _morph(self): - """Turn a file system Node (either a freshly initialized directory - object or a separate Entry object) into a proper directory object. - - Set up this directory's entries and hook it into the file - system tree. Specify that directories (this Node) don't use - signatures for calculating whether they're current. - """ - - self.repositories = [] - self.srcdir = None - - self.entries = {} - self.entries['.'] = self - self.entries['..'] = self.dir - self.cwd = self - self.searched = 0 - self._sconsign = None - self.variant_dirs = [] - self.root = self.dir.root - self.changed_since_last_build = 3 - self._func_sconsign = 1 - self._func_exists = 2 - self._func_get_contents = 2 - - self._abspath = SCons.Util.silent_intern(self.dir.entry_abspath(self.name)) - self._labspath = SCons.Util.silent_intern(self.dir.entry_labspath(self.name)) - if self.dir._path == '.': - self._path = SCons.Util.silent_intern(self.name) - else: - self._path = SCons.Util.silent_intern(self.dir.entry_path(self.name)) - if self.dir._tpath == '.': - self._tpath = SCons.Util.silent_intern(self.name) - else: - self._tpath = SCons.Util.silent_intern(self.dir.entry_tpath(self.name)) - self._path_elements = self.dir._path_elements + [self] - - # For directories, we make a difference between the directory - # 'name' and the directory 'dirname'. The 'name' attribute is - # used when we need to print the 'name' of the directory or - # when we it is used as the last part of a path. The 'dirname' - # is used when the directory is not the last element of the - # path. The main reason for making that distinction is that - # for RoorDir's the dirname can not be easily inferred from - # the name. For example, we have to add a '/' after a drive - # letter but not after a UNC path prefix ('//'). - self.dirname = self.name + OS_SEP - - # Don't just reset the executor, replace its action list, - # because it might have some pre-or post-actions that need to - # be preserved. - # - # But don't reset the executor if there is a non-null executor - # attached already. The existing executor might have other - # targets, in which case replacing the action list with a - # Mkdir action is a big mistake. - if not hasattr(self, 'executor'): - self.builder = get_MkdirBuilder() - self.get_executor().set_action_list(self.builder.action) - else: - # Prepend MkdirBuilder action to existing action list - l = self.get_executor().action_list - a = get_MkdirBuilder().action - l.insert(0, a) - self.get_executor().set_action_list(l) - - def diskcheck_match(self): - diskcheck_match(self, self.isfile, - "File %s found where directory expected.") - - def __clearRepositoryCache(self, duplicate=None): - """Called when we change the repository(ies) for a directory. - This clears any cached information that is invalidated by changing - the repository.""" - - for node in self.entries.values(): - if node != self.dir: - if node != self and isinstance(node, Dir): - node.__clearRepositoryCache(duplicate) - else: - node.clear() - try: - del node._srcreps - except AttributeError: - pass - if duplicate is not None: - node.duplicate=duplicate - - def __resetDuplicate(self, node): - if node != self: - node.duplicate = node.get_dir().duplicate - - def Entry(self, name): - """ - Looks up or creates an entry node named 'name' relative to - this directory. - """ - return self.fs.Entry(name, self) - - def Dir(self, name, create=True): - """ - Looks up or creates a directory node named 'name' relative to - this directory. - """ - return self.fs.Dir(name, self, create) - - def File(self, name): - """ - Looks up or creates a file node named 'name' relative to - this directory. - """ - return self.fs.File(name, self) - - def link(self, srcdir, duplicate): - """Set this directory as the variant directory for the - supplied source directory.""" - self.srcdir = srcdir - self.duplicate = duplicate - self.__clearRepositoryCache(duplicate) - srcdir.variant_dirs.append(self) - - def getRepositories(self): - """Returns a list of repositories for this directory. - """ - if self.srcdir and not self.duplicate: - return self.srcdir.get_all_rdirs() + self.repositories - return self.repositories - - @SCons.Memoize.CountMethodCall - def get_all_rdirs(self): - try: - return list(self._memo['get_all_rdirs']) - except KeyError: - pass - - result = [self] - fname = '.' - dir = self - while dir: - for rep in dir.getRepositories(): - result.append(rep.Dir(fname)) - if fname == '.': - fname = dir.name - else: - fname = dir.name + OS_SEP + fname - dir = dir.up() - - self._memo['get_all_rdirs'] = list(result) - - return result - - def addRepository(self, dir): - if dir != self and not dir in self.repositories: - self.repositories.append(dir) - dir._tpath = '.' - self.__clearRepositoryCache() - - def up(self): - return self.dir - - def _rel_path_key(self, other): - return str(other) - - @SCons.Memoize.CountDictCall(_rel_path_key) - def rel_path(self, other): - """Return a path to "other" relative to this directory. - """ - - # This complicated and expensive method, which constructs relative - # paths between arbitrary Node.FS objects, is no longer used - # by SCons itself. It was introduced to store dependency paths - # in .sconsign files relative to the target, but that ended up - # being significantly inefficient. - # - # We're continuing to support the method because some SConstruct - # files out there started using it when it was available, and - # we're all about backwards compatibility.. - - try: - memo_dict = self._memo['rel_path'] - except KeyError: - memo_dict = {} - self._memo['rel_path'] = memo_dict - else: - try: - return memo_dict[other] - except KeyError: - pass - - if self is other: - result = '.' - - elif not other in self._path_elements: - try: - other_dir = other.get_dir() - except AttributeError: - result = str(other) - else: - if other_dir is None: - result = other.name - else: - dir_rel_path = self.rel_path(other_dir) - if dir_rel_path == '.': - result = other.name - else: - result = dir_rel_path + OS_SEP + other.name - else: - i = self._path_elements.index(other) + 1 - - path_elems = ['..'] * (len(self._path_elements) - i) \ - + [n.name for n in other._path_elements[i:]] - - result = OS_SEP.join(path_elems) - - memo_dict[other] = result - - return result - - def get_env_scanner(self, env, kw={}): - import SCons.Defaults - return SCons.Defaults.DirEntryScanner - - def get_target_scanner(self): - import SCons.Defaults - return SCons.Defaults.DirEntryScanner - - def get_found_includes(self, env, scanner, path): - """Return this directory's implicit dependencies. - - We don't bother caching the results because the scan typically - shouldn't be requested more than once (as opposed to scanning - .h file contents, which can be requested as many times as the - files is #included by other files). - """ - if not scanner: - return [] - # Clear cached info for this Dir. If we already visited this - # directory on our walk down the tree (because we didn't know at - # that point it was being used as the source for another Node) - # then we may have calculated build signature before realizing - # we had to scan the disk. Now that we have to, though, we need - # to invalidate the old calculated signature so that any node - # dependent on our directory structure gets one that includes - # info about everything on disk. - self.clear() - return scanner(self, env, path) - - # - # Taskmaster interface subsystem - # - - def prepare(self): - pass - - def build(self, **kw): - """A null "builder" for directories.""" - global MkdirBuilder - if self.builder is not MkdirBuilder: - SCons.Node.Node.build(self, **kw) - - # - # - # - - def _create(self): - """Create this directory, silently and without worrying about - whether the builder is the default or not.""" - listDirs = [] - parent = self - while parent: - if parent.exists(): - break - listDirs.append(parent) - p = parent.up() - if p is None: - # Don't use while: - else: for this condition because - # if so, then parent is None and has no .path attribute. - raise SCons.Errors.StopError(parent._path) - parent = p - listDirs.reverse() - for dirnode in listDirs: - try: - # Don't call dirnode.build(), call the base Node method - # directly because we definitely *must* create this - # directory. The dirnode.build() method will suppress - # the build if it's the default builder. - SCons.Node.Node.build(dirnode) - dirnode.get_executor().nullify() - # The build() action may or may not have actually - # created the directory, depending on whether the -n - # option was used or not. Delete the _exists and - # _rexists attributes so they can be reevaluated. - dirnode.clear() - except OSError: - pass - - def multiple_side_effect_has_builder(self): - global MkdirBuilder - return self.builder is not MkdirBuilder and self.has_builder() - - def alter_targets(self): - """Return any corresponding targets in a variant directory. - """ - return self.fs.variant_dir_target_climb(self, self, []) - - def scanner_key(self): - """A directory does not get scanned.""" - return None - - def get_text_contents(self): - """We already emit things in text, so just return the binary - version.""" - return self.get_contents() - - def get_contents(self): - """Return content signatures and names of all our children - separated by new-lines. Ensure that the nodes are sorted.""" - return SCons.Node._get_contents_map[self._func_get_contents](self) - - def get_csig(self): - """Compute the content signature for Directory nodes. In - general, this is not needed and the content signature is not - stored in the DirNodeInfo. However, if get_contents on a Dir - node is called which has a child directory, the child - directory should return the hash of its contents.""" - contents = self.get_contents() - return SCons.Util.MD5signature(contents) - - def do_duplicate(self, src): - pass - - def is_up_to_date(self): - """If any child is not up-to-date, then this directory isn't, - either.""" - if self.builder is not MkdirBuilder and not self.exists(): - return 0 - up_to_date = SCons.Node.up_to_date - for kid in self.children(): - if kid.get_state() > up_to_date: - return 0 - return 1 - - def rdir(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.dir_on_disk(self.name) - if node and node.exists() and \ - (isinstance(dir, Dir) or isinstance(dir, Entry)): - return node - return self - - def sconsign(self): - """Return the .sconsign file info for this directory. """ - return _sconsign_map[self._func_sconsign](self) - - def srcnode(self): - """Dir has a special need for srcnode()...if we - have a srcdir attribute set, then that *is* our srcnode.""" - if self.srcdir: - return self.srcdir - return Base.srcnode(self) - - def get_timestamp(self): - """Return the latest timestamp from among our children""" - stamp = 0 - for kid in self.children(): - if kid.get_timestamp() > stamp: - stamp = kid.get_timestamp() - return stamp - - def get_abspath(self): - """Get the absolute path of the file.""" - return self._abspath - - def get_labspath(self): - """Get the absolute path of the file.""" - return self._labspath - - def get_internal_path(self): - return self._path - - def get_tpath(self): - return self._tpath - - def get_path_elements(self): - return self._path_elements - - def entry_abspath(self, name): - return self._abspath + OS_SEP + name - - def entry_labspath(self, name): - return self._labspath + '/' + name - - def entry_path(self, name): - return self._path + OS_SEP + name - - def entry_tpath(self, name): - return self._tpath + OS_SEP + name - - def entry_exists_on_disk(self, name): - """ Searches through the file/dir entries of the current - directory, and returns True if a physical entry with the given - name could be found. - - @see rentry_exists_on_disk - """ - try: - d = self.on_disk_entries - except AttributeError: - d = {} - try: - entries = os.listdir(self._abspath) - except OSError: - pass - else: - for entry in map(_my_normcase, entries): - d[entry] = True - self.on_disk_entries = d - if sys.platform == 'win32' or sys.platform == 'cygwin': - name = _my_normcase(name) - result = d.get(name) - if result is None: - # Belt-and-suspenders for Windows: check directly for - # 8.3 file names that don't show up in os.listdir(). - result = os.path.exists(self._abspath + OS_SEP + name) - d[name] = result - return result - else: - return name in d - - def rentry_exists_on_disk(self, name): - """ Searches through the file/dir entries of the current - *and* all its remote directories (repos), and returns - True if a physical entry with the given name could be found. - The local directory (self) gets searched first, so - repositories take a lower precedence regarding the - searching order. - - @see entry_exists_on_disk - """ - - rentry_exists = self.entry_exists_on_disk(name) - if not rentry_exists: - # Search through the repository folders - norm_name = _my_normcase(name) - for rdir in self.get_all_rdirs(): - try: - node = rdir.entries[norm_name] - if node: - rentry_exists = True - break - except KeyError: - if rdir.entry_exists_on_disk(name): - rentry_exists = True - break - return rentry_exists - - @SCons.Memoize.CountMethodCall - def srcdir_list(self): - try: - return self._memo['srcdir_list'] - except KeyError: - pass - - result = [] - - dirname = '.' - dir = self - while dir: - if dir.srcdir: - result.append(dir.srcdir.Dir(dirname)) - dirname = dir.name + OS_SEP + dirname - dir = dir.up() - - self._memo['srcdir_list'] = result - - return result - - def srcdir_duplicate(self, name): - for dir in self.srcdir_list(): - if self.is_under(dir): - # We shouldn't source from something in the build path; - # variant_dir is probably under src_dir, in which case - # we are reflecting. - break - if dir.entry_exists_on_disk(name): - srcnode = dir.Entry(name).disambiguate() - if self.duplicate: - node = self.Entry(name).disambiguate() - node.do_duplicate(srcnode) - return node - else: - return srcnode - return None - - def _srcdir_find_file_key(self, filename): - return filename - - @SCons.Memoize.CountDictCall(_srcdir_find_file_key) - def srcdir_find_file(self, filename): - try: - memo_dict = self._memo['srcdir_find_file'] - except KeyError: - memo_dict = {} - self._memo['srcdir_find_file'] = memo_dict - else: - try: - return memo_dict[filename] - except KeyError: - pass - - def func(node): - if (isinstance(node, File) or isinstance(node, Entry)) and \ - (node.is_derived() or node.exists()): - return node - return None - - norm_name = _my_normcase(filename) - - for rdir in self.get_all_rdirs(): - try: node = rdir.entries[norm_name] - except KeyError: node = rdir.file_on_disk(filename) - else: node = func(node) - if node: - result = (node, self) - memo_dict[filename] = result - return result - - for srcdir in self.srcdir_list(): - for rdir in srcdir.get_all_rdirs(): - try: node = rdir.entries[norm_name] - except KeyError: node = rdir.file_on_disk(filename) - else: node = func(node) - if node: - result = (File(filename, self, self.fs), srcdir) - memo_dict[filename] = result - return result - - result = (None, None) - memo_dict[filename] = result - return result - - def dir_on_disk(self, name): - if self.entry_exists_on_disk(name): - try: return self.Dir(name) - except TypeError: pass - node = self.srcdir_duplicate(name) - if isinstance(node, File): - return None - return node - - def file_on_disk(self, name): - if self.entry_exists_on_disk(name) or \ - diskcheck_rcs(self, name) or \ - diskcheck_sccs(self, name): - try: return self.File(name) - except TypeError: pass - node = self.srcdir_duplicate(name) - if isinstance(node, Dir): - return None - return node - - def walk(self, func, arg): - """ - Walk this directory tree by calling the specified function - for each directory in the tree. - - This behaves like the os.path.walk() function, but for in-memory - Node.FS.Dir objects. The function takes the same arguments as - the functions passed to os.path.walk(): - - func(arg, dirname, fnames) - - Except that "dirname" will actually be the directory *Node*, - not the string. The '.' and '..' entries are excluded from - fnames. The fnames list may be modified in-place to filter the - subdirectories visited or otherwise impose a specific order. - The "arg" argument is always passed to func() and may be used - in any way (or ignored, passing None is common). - """ - entries = self.entries - names = list(entries.keys()) - names.remove('.') - names.remove('..') - func(arg, self, names) - for dirname in [n for n in names if isinstance(entries[n], Dir)]: - entries[dirname].walk(func, arg) - - def glob(self, pathname, ondisk=True, source=False, strings=False, exclude=None): - """ - Returns a list of Nodes (or strings) matching a specified - pathname pattern. - - Pathname patterns follow UNIX shell semantics: * matches - any-length strings of any characters, ? matches any character, - and [] can enclose lists or ranges of characters. Matches do - not span directory separators. - - The matches take into account Repositories, returning local - Nodes if a corresponding entry exists in a Repository (either - an in-memory Node or something on disk). - - By defafult, the glob() function matches entries that exist - on-disk, in addition to in-memory Nodes. Setting the "ondisk" - argument to False (or some other non-true value) causes the glob() - function to only match in-memory Nodes. The default behavior is - to return both the on-disk and in-memory Nodes. - - The "source" argument, when true, specifies that corresponding - source Nodes must be returned if you're globbing in a build - directory (initialized with VariantDir()). The default behavior - is to return Nodes local to the VariantDir(). - - The "strings" argument, when true, returns the matches as strings, - not Nodes. The strings are path names relative to this directory. - - The "exclude" argument, if not None, must be a pattern or a list - of patterns following the same UNIX shell semantics. - Elements matching a least one pattern of this list will be excluded - from the result. - - The underlying algorithm is adapted from the glob.glob() function - in the Python library (but heavily modified), and uses fnmatch() - under the covers. - """ - dirname, basename = os.path.split(pathname) - if not dirname: - result = self._glob1(basename, ondisk, source, strings) - else: - if has_glob_magic(dirname): - list = self.glob(dirname, ondisk, source, False, exclude) - else: - list = [self.Dir(dirname, create=True)] - result = [] - for dir in list: - r = dir._glob1(basename, ondisk, source, strings) - if strings: - r = [os.path.join(str(dir), x) for x in r] - result.extend(r) - if exclude: - result = filter(lambda x: not any(fnmatch.fnmatch(str(x), e) for e in SCons.Util.flatten(exclude)), result) - return sorted(result, key=lambda a: str(a)) - - def _glob1(self, pattern, ondisk=True, source=False, strings=False): - """ - Globs for and returns a list of entry names matching a single - pattern in this directory. - - This searches any repositories and source directories for - corresponding entries and returns a Node (or string) relative - to the current directory if an entry is found anywhere. - - TODO: handle pattern with no wildcard - """ - search_dir_list = self.get_all_rdirs() - for srcdir in self.srcdir_list(): - search_dir_list.extend(srcdir.get_all_rdirs()) - - selfEntry = self.Entry - names = [] - for dir in search_dir_list: - # We use the .name attribute from the Node because the keys of - # the dir.entries dictionary are normalized (that is, all upper - # case) on case-insensitive systems like Windows. - node_names = [ v.name for k, v in dir.entries.items() - if k not in ('.', '..') ] - names.extend(node_names) - if not strings: - # Make sure the working directory (self) actually has - # entries for all Nodes in repositories or variant dirs. - for name in node_names: selfEntry(name) - if ondisk: - try: - disk_names = os.listdir(dir._abspath) - except os.error: - continue - names.extend(disk_names) - if not strings: - # We're going to return corresponding Nodes in - # the local directory, so we need to make sure - # those Nodes exist. We only want to create - # Nodes for the entries that will match the - # specified pattern, though, which means we - # need to filter the list here, even though - # the overall list will also be filtered later, - # after we exit this loop. - if pattern[0] != '.': - #disk_names = [ d for d in disk_names if d[0] != '.' ] - disk_names = [x for x in disk_names if x[0] != '.'] - disk_names = fnmatch.filter(disk_names, pattern) - dirEntry = dir.Entry - for name in disk_names: - # Add './' before disk filename so that '#' at - # beginning of filename isn't interpreted. - name = './' + name - node = dirEntry(name).disambiguate() - n = selfEntry(name) - if n.__class__ != node.__class__: - n.__class__ = node.__class__ - n._morph() - - names = set(names) - if pattern[0] != '.': - names = [x for x in names if x[0] != '.'] - names = fnmatch.filter(names, pattern) - - if strings: - return names - - return [self.entries[_my_normcase(n)] for n in names] - -class RootDir(Dir): - """A class for the root directory of a file system. - - This is the same as a Dir class, except that the path separator - ('/' or '\\') is actually part of the name, so we don't need to - add a separator when creating the path names of entries within - this directory. - """ - - __slots__ = ['_lookupDict'] - - def __init__(self, drive, fs): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS.RootDir') - SCons.Node.Node.__init__(self) - - # Handle all the types of drives: - if drive == '': - # No drive, regular UNIX root or Windows default drive. - name = OS_SEP - dirname = OS_SEP - elif drive == '//': - # UNC path - name = UNC_PREFIX - dirname = UNC_PREFIX - else: - # Windows drive letter - name = drive - dirname = drive + OS_SEP - - #: Filename with extension as it was specified when the object was - #: created; to obtain filesystem path, use Python str() function - self.name = SCons.Util.silent_intern(name) - self.fs = fs #: Reference to parent Node.FS object - - self._path_elements = [self] - self.dir = self - self._func_rexists = 2 - self._func_target_from_source = 1 - self.store_info = 1 - - # Now set our paths to what we really want them to be. The - # name should already contain any necessary separators, such - # as the initial drive letter (the name) plus the directory - # separator, except for the "lookup abspath," which does not - # have the drive letter. - self._abspath = dirname - self._labspath = '' - self._path = dirname - self._tpath = dirname - self.dirname = dirname - - self._morph() - - self.duplicate = 0 - self._lookupDict = {} - - self._lookupDict[''] = self - self._lookupDict['/'] = self - self.root = self - # The // entry is necessary because os.path.normpath() - # preserves double slashes at the beginning of a path on Posix - # platforms. - if not has_unc: - self._lookupDict['//'] = self - - def _morph(self): - """Turn a file system Node (either a freshly initialized directory - object or a separate Entry object) into a proper directory object. - - Set up this directory's entries and hook it into the file - system tree. Specify that directories (this Node) don't use - signatures for calculating whether they're current. - """ - - self.repositories = [] - self.srcdir = None - - self.entries = {} - self.entries['.'] = self - self.entries['..'] = self.dir - self.cwd = self - self.searched = 0 - self._sconsign = None - self.variant_dirs = [] - self.changed_since_last_build = 3 - self._func_sconsign = 1 - self._func_exists = 2 - self._func_get_contents = 2 - - # Don't just reset the executor, replace its action list, - # because it might have some pre-or post-actions that need to - # be preserved. - # - # But don't reset the executor if there is a non-null executor - # attached already. The existing executor might have other - # targets, in which case replacing the action list with a - # Mkdir action is a big mistake. - if not hasattr(self, 'executor'): - self.builder = get_MkdirBuilder() - self.get_executor().set_action_list(self.builder.action) - else: - # Prepend MkdirBuilder action to existing action list - l = self.get_executor().action_list - a = get_MkdirBuilder().action - l.insert(0, a) - self.get_executor().set_action_list(l) - - - def must_be_same(self, klass): - if klass is Dir: - return - Base.must_be_same(self, klass) - - def _lookup_abs(self, p, klass, create=1): - """ - Fast (?) lookup of a *normalized* absolute path. - - This method is intended for use by internal lookups with - already-normalized path data. For general-purpose lookups, - use the FS.Entry(), FS.Dir() or FS.File() methods. - - The caller is responsible for making sure we're passed a - normalized absolute path; we merely let Python's dictionary look - up and return the One True Node.FS object for the path. - - If a Node for the specified "p" doesn't already exist, and - "create" is specified, the Node may be created after recursive - invocation to find or create the parent directory or directories. - """ - k = _my_normcase(p) - try: - result = self._lookupDict[k] - except KeyError: - if not create: - msg = "No such file or directory: '%s' in '%s' (and create is False)" % (p, str(self)) - raise SCons.Errors.UserError(msg) - # There is no Node for this path name, and we're allowed - # to create it. - dir_name, file_name = p.rsplit('/',1) - dir_node = self._lookup_abs(dir_name, Dir) - result = klass(file_name, dir_node, self.fs) - - # Double-check on disk (as configured) that the Node we - # created matches whatever is out there in the real world. - result.diskcheck_match() - - self._lookupDict[k] = result - dir_node.entries[_my_normcase(file_name)] = result - dir_node.implicit = None - else: - # There is already a Node for this path name. Allow it to - # complain if we were looking for an inappropriate type. - result.must_be_same(klass) - return result - - def __str__(self): - return self._abspath - - def entry_abspath(self, name): - return self._abspath + name - - def entry_labspath(self, name): - return '/' + name - - def entry_path(self, name): - return self._path + name - - def entry_tpath(self, name): - return self._tpath + name - - def is_under(self, dir): - if self is dir: - return 1 - else: - return 0 - - def up(self): - return None - - def get_dir(self): - return None - - def src_builder(self): - return _null - -class FileNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = ('csig', 'timestamp', 'size') - current_version_id = 2 - - field_list = ['csig', 'timestamp', 'size'] - - # This should get reset by the FS initialization. - fs = None - - def str_to_node(self, s): - top = self.fs.Top - root = top.root - if do_splitdrive: - drive, s = _my_splitdrive(s) - if drive: - root = self.fs.get_root(drive) - if not os.path.isabs(s): - s = top.get_labspath() + '/' + s - return root._lookup_abs(s, Entry) - - def __getstate__(self): - """ - Return all fields that shall be pickled. Walk the slots in the class - hierarchy and add those to the state dictionary. If a '__dict__' slot is - available, copy all entries to the dictionary. Also include the version - id, which is fixed for all instances of a class. - """ - state = getattr(self, '__dict__', {}).copy() - for obj in type(self).mro(): - for name in getattr(obj,'__slots__',()): - if hasattr(self, name): - state[name] = getattr(self, name) - - state['_version_id'] = self.current_version_id - try: - del state['__weakref__'] - except KeyError: - pass - - return state - - def __setstate__(self, state): - """ - Restore the attributes from a pickled state. - """ - # TODO check or discard version - del state['_version_id'] - for key, value in state.items(): - if key not in ('__weakref__',): - setattr(self, key, value) - -class FileBuildInfo(SCons.Node.BuildInfoBase): - __slots__ = () - current_version_id = 2 - - def convert_to_sconsign(self): - """ - Converts this FileBuildInfo object for writing to a .sconsign file - - This replaces each Node in our various dependency lists with its - usual string representation: relative to the top-level SConstruct - directory, or an absolute path if it's outside. - """ - if os_sep_is_slash: - node_to_str = str - else: - def node_to_str(n): - try: - s = n.get_internal_path() - except AttributeError: - s = str(n) - else: - s = s.replace(OS_SEP, '/') - return s - for attr in ['bsources', 'bdepends', 'bimplicit']: - try: - val = getattr(self, attr) - except AttributeError: - pass - else: - setattr(self, attr, list(map(node_to_str, val))) - def convert_from_sconsign(self, dir, name): - """ - Converts a newly-read FileBuildInfo object for in-SCons use - - For normal up-to-date checking, we don't have any conversion to - perform--but we're leaving this method here to make that clear. - """ - pass - def prepare_dependencies(self): - """ - Prepares a FileBuildInfo object for explaining what changed - - The bsources, bdepends and bimplicit lists have all been - stored on disk as paths relative to the top-level SConstruct - directory. Convert the strings to actual Nodes (for use by the - --debug=explain code and --implicit-cache). - """ - attrs = [ - ('bsources', 'bsourcesigs'), - ('bdepends', 'bdependsigs'), - ('bimplicit', 'bimplicitsigs'), - ] - for (nattr, sattr) in attrs: - try: - strings = getattr(self, nattr) - nodeinfos = getattr(self, sattr) - except AttributeError: - continue - if strings is None or nodeinfos is None: - continue - nodes = [] - for s, ni in zip(strings, nodeinfos): - if not isinstance(s, SCons.Node.Node): - s = ni.str_to_node(s) - nodes.append(s) - setattr(self, nattr, nodes) - def format(self, names=0): - result = [] - bkids = self.bsources + self.bdepends + self.bimplicit - bkidsigs = self.bsourcesigs + self.bdependsigs + self.bimplicitsigs - for bkid, bkidsig in zip(bkids, bkidsigs): - result.append(str(bkid) + ': ' + - ' '.join(bkidsig.format(names=names))) - if not hasattr(self,'bact'): - self.bact = "none" - result.append('%s [%s]' % (self.bactsig, self.bact)) - return '\n'.join(result) - -class File(Base): - """A class for files in a file system. - """ - - __slots__ = ['scanner_paths', - 'cachedir_csig', - 'cachesig', - 'repositories', - 'srcdir', - 'entries', - 'searched', - '_sconsign', - 'variant_dirs', - 'root', - 'dirname', - 'on_disk_entries', - 'sccs_dir', - 'rcs_dir', - 'released_target_info', - 'contentsig'] - - NodeInfo = FileNodeInfo - BuildInfo = FileBuildInfo - - md5_chunksize = 64 - - def diskcheck_match(self): - diskcheck_match(self, self.isdir, - "Directory %s found where file expected.") - - def __init__(self, name, directory, fs): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.FS.File') - Base.__init__(self, name, directory, fs) - self._morph() - - def Entry(self, name): - """Create an entry node named 'name' relative to - the directory of this file.""" - return self.dir.Entry(name) - - def Dir(self, name, create=True): - """Create a directory node named 'name' relative to - the directory of this file.""" - return self.dir.Dir(name, create=create) - - def Dirs(self, pathlist): - """Create a list of directories relative to the SConscript - directory of this file.""" - return [self.Dir(p) for p in pathlist] - - def File(self, name): - """Create a file node named 'name' relative to - the directory of this file.""" - return self.dir.File(name) - - #def generate_build_dict(self): - # """Return an appropriate dictionary of values for building - # this File.""" - # return {'Dir' : self.Dir, - # 'File' : self.File, - # 'RDirs' : self.RDirs} - - def _morph(self): - """Turn a file system node into a File object.""" - self.scanner_paths = {} - if not hasattr(self, '_local'): - self._local = 0 - if not hasattr(self, 'released_target_info'): - self.released_target_info = False - - self.store_info = 1 - self._func_exists = 4 - self._func_get_contents = 3 - - # Initialize this Node's decider function to decide_source() because - # every file is a source file until it has a Builder attached... - self.changed_since_last_build = 4 - - # If there was already a Builder set on this entry, then - # we need to make sure we call the target-decider function, - # not the source-decider. Reaching in and doing this by hand - # is a little bogus. We'd prefer to handle this by adding - # an Entry.builder_set() method that disambiguates like the - # other methods, but that starts running into problems with the - # fragile way we initialize Dir Nodes with their Mkdir builders, - # yet still allow them to be overridden by the user. Since it's - # not clear right now how to fix that, stick with what works - # until it becomes clear... - if self.has_builder(): - self.changed_since_last_build = 5 - - def scanner_key(self): - return self.get_suffix() - - def get_contents(self): - return SCons.Node._get_contents_map[self._func_get_contents](self) - - # This attempts to figure out what the encoding of the text is - # based upon the BOM bytes, and then decodes the contents so that - # it's a valid python string. - def get_text_contents(self): - contents = self.get_contents() - # The behavior of various decode() methods and functions - # w.r.t. the initial BOM bytes is different for different - # encodings and/or Python versions. ('utf-8' does not strip - # them, but has a 'utf-8-sig' which does; 'utf-16' seems to - # strip them; etc.) Just sidestep all the complication by - # explicitly stripping the BOM before we decode(). - if contents.startswith(codecs.BOM_UTF8): - return contents[len(codecs.BOM_UTF8):].decode('utf-8') - if contents.startswith(codecs.BOM_UTF16_LE): - return contents[len(codecs.BOM_UTF16_LE):].decode('utf-16-le') - if contents.startswith(codecs.BOM_UTF16_BE): - return contents[len(codecs.BOM_UTF16_BE):].decode('utf-16-be') - return contents - - def get_content_hash(self): - """ - Compute and return the MD5 hash for this file. - """ - if not self.rexists(): - return SCons.Util.MD5signature('') - fname = self.rfile().get_abspath() - try: - cs = SCons.Util.MD5filesignature(fname, - chunksize=SCons.Node.FS.File.md5_chunksize*1024) - except EnvironmentError, e: - if not e.filename: - e.filename = fname - raise - return cs - - @SCons.Memoize.CountMethodCall - def get_size(self): - try: - return self._memo['get_size'] - except KeyError: - pass - - if self.rexists(): - size = self.rfile().getsize() - else: - size = 0 - - self._memo['get_size'] = size - - return size - - @SCons.Memoize.CountMethodCall - def get_timestamp(self): - try: - return self._memo['get_timestamp'] - except KeyError: - pass - - if self.rexists(): - timestamp = self.rfile().getmtime() - else: - timestamp = 0 - - self._memo['get_timestamp'] = timestamp - - return timestamp - - convert_copy_attrs = [ - 'bsources', - 'bimplicit', - 'bdepends', - 'bact', - 'bactsig', - 'ninfo', - ] - - - convert_sig_attrs = [ - 'bsourcesigs', - 'bimplicitsigs', - 'bdependsigs', - ] - - def convert_old_entry(self, old_entry): - # Convert a .sconsign entry from before the Big Signature - # Refactoring, doing what we can to convert its information - # to the new .sconsign entry format. - # - # The old format looked essentially like this: - # - # BuildInfo - # .ninfo (NodeInfo) - # .bsig - # .csig - # .timestamp - # .size - # .bsources - # .bsourcesigs ("signature" list) - # .bdepends - # .bdependsigs ("signature" list) - # .bimplicit - # .bimplicitsigs ("signature" list) - # .bact - # .bactsig - # - # The new format looks like this: - # - # .ninfo (NodeInfo) - # .bsig - # .csig - # .timestamp - # .size - # .binfo (BuildInfo) - # .bsources - # .bsourcesigs (NodeInfo list) - # .bsig - # .csig - # .timestamp - # .size - # .bdepends - # .bdependsigs (NodeInfo list) - # .bsig - # .csig - # .timestamp - # .size - # .bimplicit - # .bimplicitsigs (NodeInfo list) - # .bsig - # .csig - # .timestamp - # .size - # .bact - # .bactsig - # - # The basic idea of the new structure is that a NodeInfo always - # holds all available information about the state of a given Node - # at a certain point in time. The various .b*sigs lists can just - # be a list of pointers to the .ninfo attributes of the different - # dependent nodes, without any copying of information until it's - # time to pickle it for writing out to a .sconsign file. - # - # The complicating issue is that the *old* format only stored one - # "signature" per dependency, based on however the *last* build - # was configured. We don't know from just looking at it whether - # it was a build signature, a content signature, or a timestamp - # "signature". Since we no longer use build signatures, the - # best we can do is look at the length and if it's thirty two, - # assume that it was (or might have been) a content signature. - # If it was actually a build signature, then it will cause a - # rebuild anyway when it doesn't match the new content signature, - # but that's probably the best we can do. - import SCons.SConsign - new_entry = SCons.SConsign.SConsignEntry() - new_entry.binfo = self.new_binfo() - binfo = new_entry.binfo - for attr in self.convert_copy_attrs: - try: - value = getattr(old_entry, attr) - except AttributeError: - continue - setattr(binfo, attr, value) - delattr(old_entry, attr) - for attr in self.convert_sig_attrs: - try: - sig_list = getattr(old_entry, attr) - except AttributeError: - continue - value = [] - for sig in sig_list: - ninfo = self.new_ninfo() - if len(sig) == 32: - ninfo.csig = sig - else: - ninfo.timestamp = sig - value.append(ninfo) - setattr(binfo, attr, value) - delattr(old_entry, attr) - return new_entry - - @SCons.Memoize.CountMethodCall - def get_stored_info(self): - try: - return self._memo['get_stored_info'] - except KeyError: - pass - - try: - sconsign_entry = self.dir.sconsign().get_entry(self.name) - except (KeyError, EnvironmentError): - import SCons.SConsign - sconsign_entry = SCons.SConsign.SConsignEntry() - sconsign_entry.binfo = self.new_binfo() - sconsign_entry.ninfo = self.new_ninfo() - else: - if isinstance(sconsign_entry, FileBuildInfo): - # This is a .sconsign file from before the Big Signature - # Refactoring; convert it as best we can. - sconsign_entry = self.convert_old_entry(sconsign_entry) - try: - delattr(sconsign_entry.ninfo, 'bsig') - except AttributeError: - pass - - self._memo['get_stored_info'] = sconsign_entry - - return sconsign_entry - - def get_stored_implicit(self): - binfo = self.get_stored_info().binfo - binfo.prepare_dependencies() - try: return binfo.bimplicit - except AttributeError: return None - - def rel_path(self, other): - return self.dir.rel_path(other) - - def _get_found_includes_key(self, env, scanner, path): - return (id(env), id(scanner), path) - - @SCons.Memoize.CountDictCall(_get_found_includes_key) - def get_found_includes(self, env, scanner, path): - """Return the included implicit dependencies in this file. - Cache results so we only scan the file once per path - regardless of how many times this information is requested. - """ - memo_key = (id(env), id(scanner), path) - try: - memo_dict = self._memo['get_found_includes'] - except KeyError: - memo_dict = {} - self._memo['get_found_includes'] = memo_dict - else: - try: - return memo_dict[memo_key] - except KeyError: - pass - - if scanner: - # result = [n.disambiguate() for n in scanner(self, env, path)] - result = scanner(self, env, path) - result = [N.disambiguate() for N in result] - else: - result = [] - - memo_dict[memo_key] = result - - return result - - def _createDir(self): - # ensure that the directories for this node are - # created. - self.dir._create() - - def push_to_cache(self): - """Try to push the node into a cache - """ - # This should get called before the Nodes' .built() method is - # called, which would clear the build signature if the file has - # a source scanner. - # - # We have to clear the local memoized values *before* we push - # the node to cache so that the memoization of the self.exists() - # return value doesn't interfere. - if self.nocache: - return - self.clear_memoized_values() - if self.exists(): - self.get_build_env().get_CacheDir().push(self) - - def retrieve_from_cache(self): - """Try to retrieve the node's content from a cache - - This method is called from multiple threads in a parallel build, - so only do thread safe stuff here. Do thread unsafe stuff in - built(). - - Returns true if the node was successfully retrieved. - """ - if self.nocache: - return None - if not self.is_derived(): - return None - return self.get_build_env().get_CacheDir().retrieve(self) - - def visited(self): - if self.exists() and self.executor is not None: - self.get_build_env().get_CacheDir().push_if_forced(self) - - ninfo = self.get_ninfo() - - csig = self.get_max_drift_csig() - if csig: - ninfo.csig = csig - - ninfo.timestamp = self.get_timestamp() - ninfo.size = self.get_size() - - if not self.has_builder(): - # This is a source file, but it might have been a target file - # in another build that included more of the DAG. Copy - # any build information that's stored in the .sconsign file - # into our binfo object so it doesn't get lost. - old = self.get_stored_info() - self.get_binfo().merge(old.binfo) - - SCons.Node.store_info_map[self.store_info](self) - - def release_target_info(self): - """Called just after this node has been marked - up-to-date or was built completely. - - This is where we try to release as many target node infos - as possible for clean builds and update runs, in order - to minimize the overall memory consumption. - - We'd like to remove a lot more attributes like self.sources - and self.sources_set, but they might get used - in a next build step. For example, during configuration - the source files for a built *.o file are used to figure out - which linker to use for the resulting Program (gcc vs. g++)! - That's why we check for the 'keep_targetinfo' attribute, - config Nodes and the Interactive mode just don't allow - an early release of most variables. - - In the same manner, we can't simply remove the self.attributes - here. The smart linking relies on the shared flag, and some - parts of the java Tool use it to transport information - about nodes... - - @see: built() and Node.release_target_info() - """ - if (self.released_target_info or SCons.Node.interactive): - return - - if not hasattr(self.attributes, 'keep_targetinfo'): - # Cache some required values, before releasing - # stuff like env, executor and builder... - self.changed(allowcache=True) - self.get_contents_sig() - self.get_build_env() - # Now purge unneeded stuff to free memory... - self.executor = None - self._memo.pop('rfile', None) - self.prerequisites = None - # Cleanup lists, but only if they're empty - if not len(self.ignore_set): - self.ignore_set = None - if not len(self.implicit_set): - self.implicit_set = None - if not len(self.depends_set): - self.depends_set = None - if not len(self.ignore): - self.ignore = None - if not len(self.depends): - self.depends = None - # Mark this node as done, we only have to release - # the memory once... - self.released_target_info = True - - def find_src_builder(self): - if self.rexists(): - return None - scb = self.dir.src_builder() - if scb is _null: - if diskcheck_sccs(self.dir, self.name): - scb = get_DefaultSCCSBuilder() - elif diskcheck_rcs(self.dir, self.name): - scb = get_DefaultRCSBuilder() - else: - scb = None - if scb is not None: - try: - b = self.builder - except AttributeError: - b = None - if b is None: - self.builder_set(scb) - return scb - - def has_src_builder(self): - """Return whether this Node has a source builder or not. - - If this Node doesn't have an explicit source code builder, this - is where we figure out, on the fly, if there's a transparent - source code builder for it. - - Note that if we found a source builder, we also set the - self.builder attribute, so that all of the methods that actually - *build* this file don't have to do anything different. - """ - try: - scb = self.sbuilder - except AttributeError: - scb = self.sbuilder = self.find_src_builder() - return scb is not None - - def alter_targets(self): - """Return any corresponding targets in a variant directory. - """ - if self.is_derived(): - return [], None - return self.fs.variant_dir_target_climb(self, self.dir, [self.name]) - - def _rmv_existing(self): - self.clear_memoized_values() - if SCons.Node.print_duplicate: - print "dup: removing existing target %s"%self - e = Unlink(self, [], None) - if isinstance(e, SCons.Errors.BuildError): - raise e - - # - # Taskmaster interface subsystem - # - - def make_ready(self): - self.has_src_builder() - self.get_binfo() - - def prepare(self): - """Prepare for this file to be created.""" - SCons.Node.Node.prepare(self) - - if self.get_state() != SCons.Node.up_to_date: - if self.exists(): - if self.is_derived() and not self.precious: - self._rmv_existing() - else: - try: - self._createDir() - except SCons.Errors.StopError, drive: - desc = "No drive `%s' for target `%s'." % (drive, self) - raise SCons.Errors.StopError(desc) - - # - # - # - - def remove(self): - """Remove this file.""" - if self.exists() or self.islink(): - self.fs.unlink(self.get_internal_path()) - return 1 - return None - - def do_duplicate(self, src): - self._createDir() - if SCons.Node.print_duplicate: - print "dup: relinking variant '%s' from '%s'"%(self, src) - Unlink(self, None, None) - e = Link(self, src, None) - if isinstance(e, SCons.Errors.BuildError): - desc = "Cannot duplicate `%s' in `%s': %s." % (src.get_internal_path(), self.dir._path, e.errstr) - raise SCons.Errors.StopError(desc) - self.linked = 1 - # The Link() action may or may not have actually - # created the file, depending on whether the -n - # option was used or not. Delete the _exists and - # _rexists attributes so they can be reevaluated. - self.clear() - - @SCons.Memoize.CountMethodCall - def exists(self): - try: - return self._memo['exists'] - except KeyError: - pass - - result = SCons.Node._exists_map[self._func_exists](self) - self._memo['exists'] = result - return result - - # - # SIGNATURE SUBSYSTEM - # - - def get_max_drift_csig(self): - """ - Returns the content signature currently stored for this node - if it's been unmodified longer than the max_drift value, or the - max_drift value is 0. Returns None otherwise. - """ - old = self.get_stored_info() - mtime = self.get_timestamp() - - max_drift = self.fs.max_drift - if max_drift > 0: - if (time.time() - mtime) > max_drift: - try: - n = old.ninfo - if n.timestamp and n.csig and n.timestamp == mtime: - return n.csig - except AttributeError: - pass - elif max_drift == 0: - try: - return old.ninfo.csig - except AttributeError: - pass - - return None - - def get_csig(self): - """ - Generate a node's content signature, the digested signature - of its content. - - node - the node - cache - alternate node to use for the signature cache - returns - the content signature - """ - ninfo = self.get_ninfo() - try: - return ninfo.csig - except AttributeError: - pass - - csig = self.get_max_drift_csig() - if csig is None: - - try: - if self.get_size() < SCons.Node.FS.File.md5_chunksize: - contents = self.get_contents() - else: - csig = self.get_content_hash() - except IOError: - # This can happen if there's actually a directory on-disk, - # which can be the case if they've disabled disk checks, - # or if an action with a File target actually happens to - # create a same-named directory by mistake. - csig = '' - else: - if not csig: - csig = SCons.Util.MD5signature(contents) - - ninfo.csig = csig - - return csig - - # - # DECISION SUBSYSTEM - # - - def builder_set(self, builder): - SCons.Node.Node.builder_set(self, builder) - self.changed_since_last_build = 5 - - def built(self): - """Called just after this File node is successfully built. - - Just like for 'release_target_info' we try to release - some more target node attributes in order to minimize the - overall memory consumption. - - @see: release_target_info - """ - - SCons.Node.Node.built(self) - - if (not SCons.Node.interactive and - not hasattr(self.attributes, 'keep_targetinfo')): - # Ensure that the build infos get computed and cached... - SCons.Node.store_info_map[self.store_info](self) - # ... then release some more variables. - self._specific_sources = False - self._labspath = None - self._save_str() - self.cwd = None - - self.scanner_paths = None - - def changed(self, node=None, allowcache=False): - """ - Returns if the node is up-to-date with respect to the BuildInfo - stored last time it was built. - - For File nodes this is basically a wrapper around Node.changed(), - but we allow the return value to get cached after the reference - to the Executor got released in release_target_info(). - - @see: Node.changed() - """ - if node is None: - try: - return self._memo['changed'] - except KeyError: - pass - - has_changed = SCons.Node.Node.changed(self, node) - if allowcache: - self._memo['changed'] = has_changed - return has_changed - - def changed_content(self, target, prev_ni): - cur_csig = self.get_csig() - try: - return cur_csig != prev_ni.csig - except AttributeError: - return 1 - - 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): - try: - self.get_ninfo().csig = prev_ni.csig - except AttributeError: - pass - return False - return self.changed_content(target, prev_ni) - - def changed_timestamp_newer(self, target, prev_ni): - try: - return self.get_timestamp() > target.get_timestamp() - except AttributeError: - return 1 - - def changed_timestamp_match(self, target, prev_ni): - try: - return self.get_timestamp() != prev_ni.timestamp - except AttributeError: - return 1 - - def is_up_to_date(self): - T = 0 - if T: Trace('is_up_to_date(%s):' % self) - if not self.exists(): - if T: Trace(' not self.exists():') - # The file doesn't exist locally... - r = self.rfile() - if r != self: - # ...but there is one in a Repository... - if not self.changed(r): - if T: Trace(' changed(%s):' % r) - # ...and it's even up-to-date... - if self._local: - # ...and they'd like a local copy. - e = LocalCopy(self, r, None) - if isinstance(e, SCons.Errors.BuildError): - raise - SCons.Node.store_info_map[self.store_info](self) - if T: Trace(' 1\n') - return 1 - self.changed() - if T: Trace(' None\n') - return None - else: - r = self.changed() - if T: Trace(' self.exists(): %s\n' % r) - return not r - - @SCons.Memoize.CountMethodCall - def rfile(self): - try: - return self._memo['rfile'] - except KeyError: - pass - 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) - if node and node.exists() and \ - (isinstance(node, File) or isinstance(node, Entry) \ - or not node.is_derived()): - result = node - # Copy over our local attributes to the repository - # Node so we identify shared object files in the - # repository and don't assume they're static. - # - # This isn't perfect; the attribute would ideally - # be attached to the object in the repository in - # case it was built statically in the repository - # and we changed it to shared locally, but that's - # rarely the case and would only occur if you - # intentionally used the same suffix for both - # shared and static objects anyway. So this - # should work well in practice. - result.attributes = self.attributes - break - self._memo['rfile'] = result - return result - - def rstr(self): - return str(self.rfile()) - - def get_cachedir_csig(self): - """ - Fetch a Node's content signature for purposes of computing - another Node's cachesig. - - This is a wrapper around the normal get_csig() method that handles - the somewhat obscure case of using CacheDir with the -n option. - Any files that don't exist would normally be "built" by fetching - them from the cache, but the normal get_csig() method will try - to open up the local file, which doesn't exist because the -n - option meant we didn't actually pull the file from cachedir. - But since the file *does* actually exist in the cachedir, we - can use its contents for the csig. - """ - try: - return self.cachedir_csig - except AttributeError: - pass - - cachedir, cachefile = self.get_build_env().get_CacheDir().cachepath(self) - if not self.exists() and cachefile and os.path.exists(cachefile): - self.cachedir_csig = SCons.Util.MD5filesignature(cachefile, \ - SCons.Node.FS.File.md5_chunksize * 1024) - else: - self.cachedir_csig = self.get_csig() - return self.cachedir_csig - - def get_contents_sig(self): - """ - A helper method for get_cachedir_bsig. - - It computes and returns the signature for this - node's contents. - """ - - try: - return self.contentsig - except AttributeError: - pass - - executor = self.get_executor() - - result = self.contentsig = SCons.Util.MD5signature(executor.get_contents()) - return result - - def get_cachedir_bsig(self): - """ - Return the signature for a cached file, including - its children. - - It adds the path of the cached file to the cache signature, - because multiple targets built by the same action will all - have the same build signature, and we have to differentiate - them somehow. - """ - try: - return self.cachesig - except AttributeError: - pass - - # 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 - -default_fs = None - -def get_default_fs(): - global default_fs - if not default_fs: - default_fs = FS() - return default_fs - -class FileFinder(object): - """ - """ - - def __init__(self): - self._memo = {} - - def filedir_lookup(self, p, fd=None): - """ - A helper method for find_file() that looks up a directory for - a file we're trying to find. This only creates the Dir Node if - it exists on-disk, since if the directory doesn't exist we know - we won't find any files in it... :-) - - It would be more compact to just use this as a nested function - with a default keyword argument (see the commented-out version - below), but that doesn't work unless you have nested scopes, - so we define it here just so this work under Python 1.5.2. - """ - if fd is None: - fd = self.default_filedir - dir, name = os.path.split(fd) - drive, d = _my_splitdrive(dir) - if not name and d[:1] in ('/', OS_SEP): - #return p.fs.get_root(drive).dir_on_disk(name) - return p.fs.get_root(drive) - if dir: - p = self.filedir_lookup(p, dir) - if not p: - return None - norm_name = _my_normcase(name) - try: - node = p.entries[norm_name] - except KeyError: - return p.dir_on_disk(name) - if isinstance(node, Dir): - return node - if isinstance(node, Entry): - node.must_be_same(Dir) - return node - return None - - def _find_file_key(self, filename, paths, verbose=None): - return (filename, paths) - - @SCons.Memoize.CountDictCall(_find_file_key) - def find_file(self, filename, paths, verbose=None): - """ - find_file(str, [Dir()]) -> [nodes] - - filename - a filename to find - paths - a list of directory path *nodes* to search in. Can be - represented as a list, a tuple, or a callable that is - called with no arguments and returns the list or tuple. - - returns - the node created from the found file. - - Find a node corresponding to either a derived file or a file - that exists already. - - Only the first file found is returned, and none is returned - if no file is found. - """ - memo_key = self._find_file_key(filename, paths) - try: - memo_dict = self._memo['find_file'] - except KeyError: - memo_dict = {} - self._memo['find_file'] = memo_dict - else: - try: - return memo_dict[memo_key] - except KeyError: - pass - - if verbose and not callable(verbose): - if not SCons.Util.is_String(verbose): - verbose = "find_file" - _verbose = u' %s: ' % verbose - verbose = lambda s: sys.stdout.write(_verbose + s) - - filedir, filename = os.path.split(filename) - if filedir: - # More compact code that we can't use until we drop - # support for Python 1.5.2: - # - #def filedir_lookup(p, fd=filedir): - # """ - # A helper function that looks up a directory for a file - # we're trying to find. This only creates the Dir Node - # if it exists on-disk, since if the directory doesn't - # exist we know we won't find any files in it... :-) - # """ - # dir, name = os.path.split(fd) - # if dir: - # p = filedir_lookup(p, dir) - # if not p: - # return None - # norm_name = _my_normcase(name) - # try: - # node = p.entries[norm_name] - # except KeyError: - # return p.dir_on_disk(name) - # if isinstance(node, Dir): - # return node - # if isinstance(node, Entry): - # node.must_be_same(Dir) - # return node - # if isinstance(node, Dir) or isinstance(node, Entry): - # return node - # return None - #paths = [_f for _f in map(filedir_lookup, paths) if _f] - - self.default_filedir = filedir - paths = [_f for _f in map(self.filedir_lookup, paths) if _f] - - result = None - for dir in paths: - if verbose: - verbose("looking for '%s' in '%s' ...\n" % (filename, dir)) - node, d = dir.srcdir_find_file(filename) - if node: - if verbose: - verbose("... FOUND '%s' in '%s'\n" % (filename, d)) - result = node - break - - memo_dict[memo_key] = result - - return result - -find_file = FileFinder().find_file - - -def invalidate_node_memos(targets): - """ - Invalidate the memoized values of all Nodes (files or directories) - that are associated with the given entries. Has been added to - clear the cache of nodes affected by a direct execution of an - action (e.g. Delete/Copy/Chmod). Existing Node caches become - inconsistent if the action is run through Execute(). The argument - `targets` can be a single Node object or filename, or a sequence - of Nodes/filenames. - """ - from traceback import extract_stack - - # First check if the cache really needs to be flushed. Only - # actions run in the SConscript with Execute() seem to be - # affected. XXX The way to check if Execute() is in the stacktrace - # is a very dirty hack and should be replaced by a more sensible - # solution. - for f in extract_stack(): - if f[2] == 'Execute' and f[0][-14:] == 'Environment.py': - break - else: - # Dont have to invalidate, so return - return - - if not SCons.Util.is_List(targets): - targets = [targets] - - for entry in targets: - # If the target is a Node object, clear the cache. If it is a - # filename, look up potentially existing Node object first. - try: - entry.clear_memoized_values() - except AttributeError: - # Not a Node object, try to look up Node by filename. XXX - # This creates Node objects even for those filenames which - # do not correspond to an existing Node object. - node = get_default_fs().Entry(entry) - if node: - node.clear_memoized_values() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/Python.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/Python.py deleted file mode 100644 index b247ff6..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/Python.py +++ /dev/null @@ -1,164 +0,0 @@ -"""scons.Node.Python - -Python nodes. - -""" - -# -# Copyright (c) 2001 - 2015 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/Node/Python.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.Node - -class ValueNodeInfo(SCons.Node.NodeInfoBase): - __slots__ = ('csig',) - current_version_id = 2 - - field_list = ['csig'] - - def str_to_node(self, s): - return Value(s) - - def __getstate__(self): - """ - Return all fields that shall be pickled. Walk the slots in the class - hierarchy and add those to the state dictionary. If a '__dict__' slot is - available, copy all entries to the dictionary. Also include the version - id, which is fixed for all instances of a class. - """ - state = getattr(self, '__dict__', {}).copy() - for obj in type(self).mro(): - for name in getattr(obj,'__slots__',()): - if hasattr(self, name): - state[name] = getattr(self, name) - - state['_version_id'] = self.current_version_id - try: - del state['__weakref__'] - except KeyError: - pass - - return state - - def __setstate__(self, state): - """ - Restore the attributes from a pickled state. - """ - # TODO check or discard version - del state['_version_id'] - for key, value in state.items(): - if key not in ('__weakref__',): - setattr(self, key, value) - - -class ValueBuildInfo(SCons.Node.BuildInfoBase): - __slots__ = () - current_version_id = 2 - -class Value(SCons.Node.Node): - """A class for Python variables, typically passed on the command line - or generated by a script, but not from a file or some other source. - """ - - NodeInfo = ValueNodeInfo - BuildInfo = ValueBuildInfo - - def __init__(self, value, built_value=None): - SCons.Node.Node.__init__(self) - self.value = value - self.changed_since_last_build = 6 - self.store_info = 0 - if built_value is not None: - self.built_value = built_value - - def str_for_display(self): - return repr(self.value) - - def __str__(self): - return str(self.value) - - def make_ready(self): - self.get_csig() - - def build(self, **kw): - if not hasattr(self, 'built_value'): - SCons.Node.Node.build(self, **kw) - - is_up_to_date = SCons.Node.Node.children_are_up_to_date - - def is_under(self, dir): - # Make Value nodes get built regardless of - # what directory scons was run from. Value nodes - # are outside the filesystem: - return 1 - - def write(self, built_value): - """Set the value of the node.""" - self.built_value = built_value - - def read(self): - """Return the value. If necessary, the value is built.""" - self.build() - if not hasattr(self, 'built_value'): - self.built_value = self.value - return self.built_value - - def get_text_contents(self): - """By the assumption that the node.built_value is a - deterministic product of the sources, the contents of a Value - are the concatenation of all the contents of its sources. As - the value need not be built when get_contents() is called, we - cannot use the actual node.built_value.""" - ###TODO: something reasonable about universal newlines - contents = str(self.value) - for kid in self.children(None): - contents = contents + kid.get_contents() - return contents - - get_contents = get_text_contents ###TODO should return 'bytes' value - - def changed_since_last_build(self, target, prev_ni): - cur_csig = self.get_csig() - try: - return cur_csig != prev_ni.csig - except AttributeError: - return 1 - - 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.""" - try: - return self.ninfo.csig - except AttributeError: - pass - contents = self.get_contents() - self.get_ninfo().csig = contents - return contents - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/__init__.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/__init__.py deleted file mode 100644 index 79db894..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Node/__init__.py +++ /dev/null @@ -1,1718 +0,0 @@ -"""SCons.Node - -The Node package for the SCons software construction utility. - -This is, in many ways, the heart of SCons. - -A Node is where we encapsulate all of the dependency information about -any thing that SCons can build, or about any thing which SCons can use -to build some other thing. The canonical "thing," of course, is a file, -but a Node can also represent something remote (like a web page) or -something completely abstract (like an Alias). - -Each specific type of "thing" is specifically represented by a subclass -of the Node base class: Node.FS.File for files, Node.Alias for aliases, -etc. Dependency information is kept here in the base class, and -information specific to files/aliases/etc. is in the subclass. The -goal, if we've done this correctly, is that any type of "thing" should -be able to depend on any other type of "thing." - -""" - -# -# Copyright (c) 2001 - 2015 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/Node/__init__.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import collections -import copy -from itertools import chain - -import SCons.Debug -from SCons.Debug import logInstanceCreation -import SCons.Executor -import SCons.Memoize -import SCons.Util - -from SCons.Debug import Trace - -print_duplicate = 0 - -def classname(obj): - return str(obj.__class__).split('.')[-1] - -# Set to false if we're doing a dry run. There's more than one of these -# little treats -do_store_info = True - -# Node states -# -# These are in "priority" order, so that the maximum value for any -# child/dependency of a node represents the state of that node if -# it has no builder of its own. The canonical example is a file -# system directory, which is only up to date if all of its children -# were up to date. -no_state = 0 -pending = 1 -executing = 2 -up_to_date = 3 -executed = 4 -failed = 5 - -StateString = { - 0 : "no_state", - 1 : "pending", - 2 : "executing", - 3 : "up_to_date", - 4 : "executed", - 5 : "failed", -} - -# controls whether implicit dependencies are cached: -implicit_cache = 0 - -# controls whether implicit dep changes are ignored: -implicit_deps_unchanged = 0 - -# controls whether the cached implicit deps are ignored: -implicit_deps_changed = 0 - -# A variable that can be set to an interface-specific function be called -# to annotate a Node with information about its creation. -def do_nothing(node): pass - -Annotate = do_nothing - -# Gets set to 'True' if we're running in interactive mode. Is -# currently used to release parts of a target's info during -# clean builds and update runs (see release_target_info). -interactive = False - -def is_derived_none(node): - raise NotImplementedError - -def is_derived_node(node): - """ - Returns true if this node is derived (i.e. built). - """ - return node.has_builder() or node.side_effect - -_is_derived_map = {0 : is_derived_none, - 1 : is_derived_node} - -def exists_none(node): - raise NotImplementedError - -def exists_always(node): - return 1 - -def exists_base(node): - return node.stat() is not None - -def exists_entry(node): - """Return if the Entry exists. Check the file system to see - what we should turn into first. Assume a file if there's no - directory.""" - 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: - src = node.srcnode() - if src is not node: - # At this point, src is meant to be copied in a variant directory. - src = src.rfile() - if src.get_abspath() != node.get_abspath(): - if src.exists(): - node.do_duplicate(src) - # Can't return 1 here because the duplication might - # not actually occur if the -n option is being used. - else: - # 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 - if exists_base(node) or node.islink(): - node.fs.unlink(node.get_internal_path()) - # Return None explicitly because the Base.exists() call - # above will have cached its value if the file existed. - return None - return exists_base(node) - -_exists_map = {0 : exists_none, - 1 : exists_always, - 2 : exists_base, - 3 : exists_entry, - 4 : exists_file} - - -def rexists_none(node): - raise NotImplementedError - -def rexists_node(node): - return node.exists() - -def rexists_base(node): - return node.rfile().exists() - -_rexists_map = {0 : rexists_none, - 1 : rexists_node, - 2 : rexists_base} - -def get_contents_none(node): - raise NotImplementedError - -def get_contents_entry(node): - """Fetch the contents of the entry. Returns the exact binary - contents of the file.""" - try: - node = node.disambiguate(must_exist=1) - except SCons.Errors.UserError: - # There was nothing on disk with which to disambiguate - # this entry. Leave it as an Entry, but return a null - # string so calls to get_contents() in emitters and the - # like (e.g. in qt.py) don't have to disambiguate by hand - # or catch the exception. - return '' - else: - return _get_contents_map[node._func_get_contents](node) - -def get_contents_dir(node): - """Return content signatures and names of all our children - separated by new-lines. Ensure that the nodes are sorted.""" - contents = [] - for n in sorted(node.children(), key=lambda t: t.name): - contents.append('%s %s\n' % (n.get_csig(), n.name)) - return ''.join(contents) - -def get_contents_file(node): - if not node.rexists(): - return '' - fname = node.rfile().get_abspath() - try: - contents = open(fname, "rb").read() - except EnvironmentError, e: - if not e.filename: - e.filename = fname - raise - return contents - -_get_contents_map = {0 : get_contents_none, - 1 : get_contents_entry, - 2 : get_contents_dir, - 3 : get_contents_file} - -def target_from_source_none(node, prefix, suffix, splitext): - raise NotImplementedError - -def target_from_source_base(node, prefix, suffix, splitext): - return node.dir.Entry(prefix + splitext(node.name)[0] + suffix) - -_target_from_source_map = {0 : target_from_source_none, - 1 : target_from_source_base} - -# -# The new decider subsystem for Nodes -# -# We would set and overwrite the changed_since_last_build function -# before, but for being able to use slots (less memory!) we now have -# a dictionary of the different decider functions. Then in the Node -# subclasses we simply store the index to the decider that should be -# used by it. -# - -# -# First, the single decider functions -# -def changed_since_last_build_node(node, target, prev_ni): - """ - - Must be overridden in a specific subclass to return True if this - Node (a dependency) has changed since the last time it was used - to build the specified target. prev_ni is this Node's state (for - example, its file timestamp, length, maybe content signature) - as of the last time the target was built. - - Note that this method is called through the dependency, not the - target, because a dependency Node must be able to use its own - logic to decide if it changed. For example, File Nodes need to - obey if we're configured to use timestamps, but Python Value Nodes - never use timestamps and always use the content. If this method - were called through the target, then each Node's implementation - of this method would have to have more complicated logic to - handle all the different Node types on which it might depend. - """ - raise NotImplementedError - -def changed_since_last_build_alias(node, target, prev_ni): - cur_csig = node.get_csig() - try: - return cur_csig != prev_ni.csig - 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) - -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: - return cur_csig != prev_ni.csig - except AttributeError: - return 1 - - -# -# Now, the mapping from indices to decider functions -# -_decider_map = {0 : changed_since_last_build_node, - 1 : changed_since_last_build_alias, - 2 : changed_since_last_build_entry, - 3 : changed_since_last_build_state_changed, - 4 : decide_source, - 5 : decide_target, - 6 : changed_since_last_build_python} - -do_store_info = True - -# -# The new store_info subsystem for Nodes -# -# We would set and overwrite the store_info function -# before, but for being able to use slots (less memory!) we now have -# a dictionary of the different functions. Then in the Node -# subclasses we simply store the index to the info method that should be -# used by it. -# - -# -# First, the single info functions -# - -def store_info_pass(node): - pass - -def store_info_file(node): - # Merge our build information into the already-stored entry. - # This accommodates "chained builds" where a file that's a target - # in one build (SConstruct file) is a source in a different build. - # See test/chained-build.py for the use case. - if do_store_info: - node.dir.sconsign().store_info(node.name, node) - - -store_info_map = {0 : store_info_pass, - 1 : store_info_file} - -# Classes for signature info for Nodes. - -class NodeInfoBase(object): - """ - The generic base class for signature information for a Node. - - Node subclasses should subclass NodeInfoBase to provide their own - logic for dealing with their own Node-specific signature information. - """ - __slots__ = ('__weakref__',) - current_version_id = 2 - def update(self, node): - try: - field_list = self.field_list - except AttributeError: - return - for f in field_list: - try: - delattr(self, f) - except AttributeError: - pass - try: - func = getattr(node, 'get_' + f) - except AttributeError: - pass - else: - setattr(self, f, func()) - def convert(self, node, val): - pass - def merge(self, other): - """ - Merge the fields of another object into this object. Already existing - information is overwritten by the other instance's data. - WARNING: If a '__dict__' slot is added, it should be updated instead of - replaced. - """ - state = other.__getstate__() - self.__setstate__(state) - def format(self, field_list=None, names=0): - if field_list is None: - try: - field_list = self.field_list - except AttributeError: - field_list = getattr(self, '__dict__', {}).keys() - for obj in type(self).mro(): - for slot in getattr(obj, '__slots__', ()): - if slot not in ('__weakref__', '__dict__'): - field_list.append(slot) - field_list.sort() - fields = [] - for field in field_list: - try: - f = getattr(self, field) - except AttributeError: - f = None - f = str(f) - if names: - f = field + ': ' + f - fields.append(f) - return fields - - def __getstate__(self): - """ - Return all fields that shall be pickled. Walk the slots in the class - hierarchy and add those to the state dictionary. If a '__dict__' slot is - available, copy all entries to the dictionary. Also include the version - id, which is fixed for all instances of a class. - """ - state = getattr(self, '__dict__', {}).copy() - for obj in type(self).mro(): - for name in getattr(obj,'__slots__',()): - if hasattr(self, name): - state[name] = getattr(self, name) - - state['_version_id'] = self.current_version_id - try: - del state['__weakref__'] - except KeyError: - pass - return state - - def __setstate__(self, state): - """ - Restore the attributes from a pickled state. The version is discarded. - """ - # TODO check or discard version - del state['_version_id'] - - for key, value in state.items(): - if key not in ('__weakref__',): - setattr(self, key, value) - - -class BuildInfoBase(object): - """ - The generic base class for build information for a Node. - - This is what gets stored in a .sconsign file for each target file. - It contains a NodeInfo instance for this node (signature information - that's specific to the type of Node) and direct attributes for the - generic build stuff we have to track: sources, explicit dependencies, - implicit dependencies, and action information. - """ - __slots__ = ("bsourcesigs", "bdependsigs", "bimplicitsigs", "bactsig", - "bsources", "bdepends", "bact", "bimplicit", "__weakref__") - current_version_id = 2 - def __init__(self): - # Create an object attribute from the class attribute so it ends up - # in the pickled data in the .sconsign file. - self.bsourcesigs = [] - self.bdependsigs = [] - self.bimplicitsigs = [] - self.bactsig = None - def merge(self, other): - """ - Merge the fields of another object into this object. Already existing - information is overwritten by the other instance's data. - WARNING: If a '__dict__' slot is added, it should be updated instead of - replaced. - """ - state = other.__getstate__() - self.__setstate__(state) - - def __getstate__(self): - """ - Return all fields that shall be pickled. Walk the slots in the class - hierarchy and add those to the state dictionary. If a '__dict__' slot is - available, copy all entries to the dictionary. Also include the version - id, which is fixed for all instances of a class. - """ - state = getattr(self, '__dict__', {}).copy() - for obj in type(self).mro(): - for name in getattr(obj,'__slots__',()): - if hasattr(self, name): - state[name] = getattr(self, name) - - state['_version_id'] = self.current_version_id - try: - del state['__weakref__'] - except KeyError: - pass - return state - - def __setstate__(self, state): - """ - Restore the attributes from a pickled state. - """ - # TODO check or discard version - del state['_version_id'] - for key, value in state.items(): - if key not in ('__weakref__',): - setattr(self, key, value) - -class Node(object): - """The base Node class, for entities that we know how to - build, or use to build other Nodes. - """ - - __slots__ = ['sources', - 'sources_set', - '_specific_sources', - 'depends', - 'depends_set', - 'ignore', - 'ignore_set', - 'prerequisites', - 'implicit', - 'waiting_parents', - 'waiting_s_e', - 'ref_count', - 'wkids', - 'env', - 'state', - 'precious', - 'noclean', - 'nocache', - 'cached', - 'always_build', - 'includes', - 'attributes', - 'side_effect', - 'side_effects', - 'linked', - '_memo', - 'executor', - 'binfo', - 'ninfo', - 'builder', - 'is_explicit', - 'implicit_set', - 'changed_since_last_build', - 'store_info', - 'pseudo', - '_tags', - '_func_is_derived', - '_func_exists', - '_func_rexists', - '_func_get_contents', - '_func_target_from_source'] - - class Attrs(object): - __slots__ = ('shared', '__dict__') - - - def __init__(self): - if SCons.Debug.track_instances: logInstanceCreation(self, 'Node.Node') - # Note that we no longer explicitly initialize a self.builder - # attribute to None here. That's because the self.builder - # attribute may be created on-the-fly later by a subclass (the - # canonical example being a builder to fetch a file from a - # source code system like CVS or Subversion). - - # Each list of children that we maintain is accompanied by a - # dictionary used to look up quickly whether a node is already - # present in the list. Empirical tests showed that it was - # fastest to maintain them as side-by-side Node attributes in - # this way, instead of wrapping up each list+dictionary pair in - # a class. (Of course, we could always still do that in the - # future if we had a good reason to...). - self.sources = [] # source files used to build node - self.sources_set = set() - self._specific_sources = False - self.depends = [] # explicit dependencies (from Depends) - self.depends_set = set() - self.ignore = [] # dependencies to ignore - self.ignore_set = set() - self.prerequisites = None - self.implicit = None # implicit (scanned) dependencies (None means not scanned yet) - self.waiting_parents = set() - self.waiting_s_e = set() - self.ref_count = 0 - self.wkids = None # Kids yet to walk, when it's an array - - self.env = None - self.state = no_state - self.precious = None - self.pseudo = False - self.noclean = 0 - self.nocache = 0 - self.cached = 0 # is this node pulled from cache? - self.always_build = None - self.includes = None - self.attributes = self.Attrs() # Generic place to stick information about the Node. - self.side_effect = 0 # true iff this node is a side effect - self.side_effects = [] # the side effects of building this target - self.linked = 0 # is this node linked to the variant directory? - self.changed_since_last_build = 0 - self.store_info = 0 - self._tags = None - self._func_is_derived = 1 - self._func_exists = 1 - self._func_rexists = 1 - self._func_get_contents = 0 - self._func_target_from_source = 0 - - self.clear_memoized_values() - - # Let the interface in which the build engine is embedded - # annotate this Node with its own info (like a description of - # what line in what file created the node, for example). - Annotate(self) - - def disambiguate(self, must_exist=None): - return self - - def get_suffix(self): - return '' - - @SCons.Memoize.CountMethodCall - def get_build_env(self): - """Fetch the appropriate Environment to build this node. - """ - try: - return self._memo['get_build_env'] - except KeyError: - pass - result = self.get_executor().get_build_env() - self._memo['get_build_env'] = result - return result - - def get_build_scanner_path(self, scanner): - """Fetch the appropriate scanner path for this node.""" - return self.get_executor().get_build_scanner_path(scanner) - - def set_executor(self, executor): - """Set the action executor for this node.""" - self.executor = executor - - def get_executor(self, create=1): - """Fetch the action executor for this node. Create one if - there isn't already one, and requested to do so.""" - try: - executor = self.executor - except AttributeError: - if not create: - raise - try: - act = self.builder.action - except AttributeError: - executor = SCons.Executor.Null(targets=[self]) - else: - executor = SCons.Executor.Executor(act, - self.env or self.builder.env, - [self.builder.overrides], - [self], - self.sources) - self.executor = executor - return executor - - def executor_cleanup(self): - """Let the executor clean up any cached information.""" - try: - executor = self.get_executor(create=None) - except AttributeError: - pass - else: - if executor is not None: - executor.cleanup() - - def reset_executor(self): - "Remove cached executor; forces recompute when needed." - try: - delattr(self, 'executor') - except AttributeError: - pass - - def push_to_cache(self): - """Try to push a node into a cache - """ - pass - - def retrieve_from_cache(self): - """Try to retrieve the node's content from a cache - - This method is called from multiple threads in a parallel build, - so only do thread safe stuff here. Do thread unsafe stuff in - built(). - - Returns true if the node was successfully retrieved. - """ - return 0 - - # - # Taskmaster interface subsystem - # - - def make_ready(self): - """Get a Node ready for evaluation. - - This is called before the Taskmaster decides if the Node is - up-to-date or not. Overriding this method allows for a Node - subclass to be disambiguated if necessary, or for an implicit - source builder to be attached. - """ - pass - - def prepare(self): - """Prepare for this Node to be built. - - This is called after the Taskmaster has decided that the Node - is out-of-date and must be rebuilt, but before actually calling - the method to build the Node. - - This default implementation checks that explicit or implicit - dependencies either exist or are derived, and initializes the - BuildInfo structure that will hold the information about how - this node is, uh, built. - - (The existence of source files is checked separately by the - Executor, which aggregates checks for all of the targets built - by a specific action.) - - Overriding this method allows for for a Node subclass to remove - the underlying file from the file system. Note that subclass - methods should call this base class method to get the child - check and the BuildInfo structure. - """ - if self.depends is not None: - for d in self.depends: - if d.missing(): - msg = "Explicit dependency `%s' not found, needed by target `%s'." - raise SCons.Errors.StopError(msg % (d, self)) - if self.implicit is not None: - for i in self.implicit: - if i.missing(): - msg = "Implicit dependency `%s' not found, needed by target `%s'." - raise SCons.Errors.StopError(msg % (i, self)) - self.binfo = self.get_binfo() - - def build(self, **kw): - """Actually build the node. - - This is called by the Taskmaster after it's decided that the - Node is out-of-date and must be rebuilt, and after the prepare() - method has gotten everything, uh, prepared. - - This method is called from multiple threads in a parallel build, - so only do thread safe stuff here. Do thread unsafe stuff - in built(). - - """ - try: - self.get_executor()(self, **kw) - except SCons.Errors.BuildError, e: - e.node = self - raise - - def built(self): - """Called just after this node is successfully built.""" - - # Clear the implicit dependency caches of any Nodes - # waiting for this Node to be built. - for parent in self.waiting_parents: - parent.implicit = None - - self.clear() - - if self.pseudo: - if self.exists(): - raise SCons.Errors.UserError("Pseudo target " + str(self) + " must not exist") - else: - if not self.exists() and do_store_info: - SCons.Warnings.warn(SCons.Warnings.TargetNotBuiltWarning, - "Cannot find target " + str(self) + " after building") - self.ninfo.update(self) - - def visited(self): - """Called just after this node has been visited (with or - without a build).""" - try: - binfo = self.binfo - except AttributeError: - # Apparently this node doesn't need build info, so - # don't bother calculating or storing it. - pass - else: - self.ninfo.update(self) - SCons.Node.store_info_map[self.store_info](self) - - def release_target_info(self): - """Called just after this node has been marked - up-to-date or was built completely. - - This is where we try to release as many target node infos - as possible for clean builds and update runs, in order - to minimize the overall memory consumption. - - By purging attributes that aren't needed any longer after - a Node (=File) got built, we don't have to care that much how - many KBytes a Node actually requires...as long as we free - the memory shortly afterwards. - - @see: built() and File.release_target_info() - """ - pass - - # - # - # - - def add_to_waiting_s_e(self, node): - self.waiting_s_e.add(node) - - def add_to_waiting_parents(self, node): - """ - Returns the number of nodes added to our waiting parents list: - 1 if we add a unique waiting parent, 0 if not. (Note that the - returned values are intended to be used to increment a reference - count, so don't think you can "clean up" this function by using - True and False instead...) - """ - wp = self.waiting_parents - if node in wp: - return 0 - wp.add(node) - return 1 - - def postprocess(self): - """Clean up anything we don't need to hang onto after we've - been built.""" - self.executor_cleanup() - self.waiting_parents = set() - - def clear(self): - """Completely clear a Node of all its cached state (so that it - can be re-evaluated by interfaces that do continuous integration - builds). - """ - # The del_binfo() call here isn't necessary for normal execution, - # but is for interactive mode, where we might rebuild the same - # target and need to start from scratch. - self.del_binfo() - self.clear_memoized_values() - self.ninfo = self.new_ninfo() - self.executor_cleanup() - try: - delattr(self, '_calculated_sig') - except AttributeError: - pass - self.includes = None - - def clear_memoized_values(self): - self._memo = {} - - def builder_set(self, builder): - self.builder = builder - try: - del self.executor - except AttributeError: - pass - - def has_builder(self): - """Return whether this Node has a builder or not. - - In Boolean tests, this turns out to be a *lot* more efficient - than simply examining the builder attribute directly ("if - node.builder: ..."). When the builder attribute is examined - directly, it ends up calling __getattr__ for both the __len__ - and __nonzero__ attributes on instances of our Builder Proxy - class(es), generating a bazillion extra calls and slowing - things down immensely. - """ - try: - b = self.builder - except AttributeError: - # There was no explicit builder for this Node, so initialize - # the self.builder attribute to None now. - b = self.builder = None - return b is not None - - def set_explicit(self, is_explicit): - self.is_explicit = is_explicit - - def has_explicit_builder(self): - """Return whether this Node has an explicit builder - - This allows an internal Builder created by SCons to be marked - non-explicit, so that it can be overridden by an explicit - builder that the user supplies (the canonical example being - directories).""" - try: - return self.is_explicit - except AttributeError: - self.is_explicit = None - return self.is_explicit - - def get_builder(self, default_builder=None): - """Return the set builder, or a specified default value""" - try: - return self.builder - except AttributeError: - return default_builder - - multiple_side_effect_has_builder = has_builder - - def is_derived(self): - """ - Returns true if this node is derived (i.e. built). - - This should return true only for nodes whose path should be in - the variant directory when duplicate=0 and should contribute their build - signatures when they are used as source files to other derived files. For - example: source with source builders are not derived in this sense, - and hence should not return true. - """ - return _is_derived_map[self._func_is_derived](self) - - def alter_targets(self): - """Return a list of alternate targets for this Node. - """ - return [], None - - def get_found_includes(self, env, scanner, path): - """Return the scanned include lines (implicit dependencies) - found in this node. - - The default is no implicit dependencies. We expect this method - to be overridden by any subclass that can be scanned for - implicit dependencies. - """ - return [] - - def get_implicit_deps(self, env, scanner, path): - """Return a list of implicit dependencies for this node. - - This method exists to handle recursive invocation of the scanner - on the implicit dependencies returned by the scanner, if the - scanner's recursive flag says that we should. - """ - if not scanner: - return [] - - # Give the scanner a chance to select a more specific scanner - # for this Node. - #scanner = scanner.select(self) - - nodes = [self] - seen = {} - seen[self] = 1 - deps = [] - while nodes: - n = nodes.pop(0) - d = [x for x in n.get_found_includes(env, scanner, path) if x not in seen] - if d: - deps.extend(d) - for n in d: - seen[n] = 1 - nodes.extend(scanner.recurse_nodes(d)) - - return deps - - def get_env_scanner(self, env, kw={}): - return env.get_scanner(self.scanner_key()) - - def get_target_scanner(self): - return self.builder.target_scanner - - def get_source_scanner(self, node): - """Fetch the source scanner for the specified node - - NOTE: "self" is the target being built, "node" is - the source file for which we want to fetch the scanner. - - Implies self.has_builder() is true; again, expect to only be - called from locations where this is already verified. - - This function may be called very often; it attempts to cache - the scanner found to improve performance. - """ - scanner = None - try: - scanner = self.builder.source_scanner - except AttributeError: - pass - if not scanner: - # The builder didn't have an explicit scanner, so go look up - # a scanner from env['SCANNERS'] based on the node's scanner - # key (usually the file extension). - scanner = self.get_env_scanner(self.get_build_env()) - if scanner: - scanner = scanner.select(node) - return scanner - - def add_to_implicit(self, deps): - if not hasattr(self, 'implicit') or self.implicit is None: - self.implicit = [] - self.implicit_set = set() - self._children_reset() - self._add_child(self.implicit, self.implicit_set, deps) - - def scan(self): - """Scan this node's dependents for implicit dependencies.""" - # Don't bother scanning non-derived files, because we don't - # care what their dependencies are. - # Don't scan again, if we already have scanned. - if self.implicit is not None: - return - self.implicit = [] - self.implicit_set = set() - self._children_reset() - if not self.has_builder(): - return - - build_env = self.get_build_env() - executor = self.get_executor() - - # Here's where we implement --implicit-cache. - if implicit_cache and not implicit_deps_changed: - implicit = self.get_stored_implicit() - if implicit is not None: - # We now add the implicit dependencies returned from the - # stored .sconsign entry to have already been converted - # to Nodes for us. (We used to run them through a - # source_factory function here.) - - # Update all of the targets with them. This - # essentially short-circuits an N*M scan of the - # sources for each individual target, which is a hell - # of a lot more efficient. - for tgt in executor.get_all_targets(): - tgt.add_to_implicit(implicit) - - if implicit_deps_unchanged or self.is_up_to_date(): - return - # one of this node's sources has changed, - # so we must recalculate the implicit deps for all targets - for tgt in executor.get_all_targets(): - tgt.implicit = [] - tgt.implicit_set = set() - - # Have the executor scan the sources. - executor.scan_sources(self.builder.source_scanner) - - # If there's a target scanner, have the executor scan the target - # node itself and associated targets that might be built. - scanner = self.get_target_scanner() - if scanner: - executor.scan_targets(scanner) - - def scanner_key(self): - return None - - def select_scanner(self, scanner): - """Selects a scanner for this Node. - - This is a separate method so it can be overridden by Node - subclasses (specifically, Node.FS.Dir) that *must* use their - own Scanner and don't select one the Scanner.Selector that's - configured for the target. - """ - return scanner.select(self) - - def env_set(self, env, safe=0): - if safe and self.env: - return - self.env = env - - # - # SIGNATURE SUBSYSTEM - # - - NodeInfo = NodeInfoBase - BuildInfo = BuildInfoBase - - def new_ninfo(self): - ninfo = self.NodeInfo() - return ninfo - - def get_ninfo(self): - try: - return self.ninfo - except AttributeError: - self.ninfo = self.new_ninfo() - return self.ninfo - - def new_binfo(self): - binfo = self.BuildInfo() - return binfo - - def get_binfo(self): - """ - Fetch a node's build information. - - node - the node whose sources will be collected - cache - alternate node to use for the signature cache - returns - the build signature - - This no longer handles the recursive descent of the - node's children's signatures. We expect that they're - already built and updated by someone else, if that's - what's wanted. - """ - try: - return self.binfo - except AttributeError: - pass - - binfo = self.new_binfo() - self.binfo = binfo - - executor = self.get_executor() - ignore_set = self.ignore_set - - if self.has_builder(): - binfo.bact = str(executor) - binfo.bactsig = SCons.Util.MD5signature(executor.get_contents()) - - if self._specific_sources: - sources = [] - for s in self.sources: - if s not in ignore_set: - sources.append(s) - else: - sources = executor.get_unignored_sources(self, self.ignore) - seen = set() - bsources = [] - bsourcesigs = [] - for s in sources: - if not s in seen: - seen.add(s) - bsources.append(s) - bsourcesigs.append(s.get_ninfo()) - binfo.bsources = bsources - binfo.bsourcesigs = bsourcesigs - - depends = self.depends - dependsigs = [] - for d in depends: - if d not in ignore_set: - dependsigs.append(d.get_ninfo()) - binfo.bdepends = depends - binfo.bdependsigs = dependsigs - - implicit = self.implicit or [] - implicitsigs = [] - for i in implicit: - if i not in ignore_set: - implicitsigs.append(i.get_ninfo()) - binfo.bimplicit = implicit - binfo.bimplicitsigs = implicitsigs - - return binfo - - def del_binfo(self): - """Delete the build info from this node.""" - try: - delattr(self, 'binfo') - except AttributeError: - pass - - def get_csig(self): - try: - return self.ninfo.csig - except AttributeError: - ninfo = self.get_ninfo() - ninfo.csig = SCons.Util.MD5signature(self.get_contents()) - return self.ninfo.csig - - def get_cachedir_csig(self): - return self.get_csig() - - def get_stored_info(self): - return None - - def get_stored_implicit(self): - """Fetch the stored implicit dependencies""" - return None - - # - # - # - - def set_precious(self, precious = 1): - """Set the Node's precious value.""" - self.precious = precious - - def set_pseudo(self, pseudo = True): - """Set the Node's precious value.""" - self.pseudo = pseudo - - def set_noclean(self, noclean = 1): - """Set the Node's noclean value.""" - # Make sure noclean is an integer so the --debug=stree - # output in Util.py can use it as an index. - self.noclean = noclean and 1 or 0 - - def set_nocache(self, nocache = 1): - """Set the Node's nocache value.""" - # Make sure nocache is an integer so the --debug=stree - # output in Util.py can use it as an index. - self.nocache = nocache and 1 or 0 - - def set_always_build(self, always_build = 1): - """Set the Node's always_build value.""" - self.always_build = always_build - - def exists(self): - """Does this node exists?""" - return _exists_map[self._func_exists](self) - - def rexists(self): - """Does this node exist locally or in a repositiory?""" - # There are no repositories by default: - return _rexists_map[self._func_rexists](self) - - def get_contents(self): - """Fetch the contents of the entry.""" - return _get_contents_map[self._func_get_contents](self) - - def missing(self): - return not self.is_derived() and \ - not self.linked and \ - not self.rexists() - - def remove(self): - """Remove this Node: no-op by default.""" - return None - - def add_dependency(self, depend): - """Adds dependencies.""" - try: - self._add_child(self.depends, self.depends_set, depend) - except TypeError, e: - e = e.args[0] - if SCons.Util.is_List(e): - s = list(map(str, e)) - else: - s = str(e) - raise SCons.Errors.UserError("attempted to add a non-Node dependency to %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e))) - - def add_prerequisite(self, prerequisite): - """Adds prerequisites""" - if self.prerequisites is None: - self.prerequisites = SCons.Util.UniqueList() - self.prerequisites.extend(prerequisite) - self._children_reset() - - def add_ignore(self, depend): - """Adds dependencies to ignore.""" - try: - self._add_child(self.ignore, self.ignore_set, depend) - except TypeError, e: - e = e.args[0] - if SCons.Util.is_List(e): - s = list(map(str, e)) - else: - s = str(e) - raise SCons.Errors.UserError("attempted to ignore a non-Node dependency of %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e))) - - def add_source(self, source): - """Adds sources.""" - if self._specific_sources: - return - try: - self._add_child(self.sources, self.sources_set, source) - except TypeError, e: - e = e.args[0] - if SCons.Util.is_List(e): - s = list(map(str, e)) - else: - s = str(e) - raise SCons.Errors.UserError("attempted to add a non-Node as source of %s:\n\t%s is a %s, not a Node" % (str(self), s, type(e))) - - def _add_child(self, collection, set, child): - """Adds 'child' to 'collection', first checking 'set' to see if it's - already present.""" - #if type(child) is not type([]): - # child = [child] - #for c in child: - # if not isinstance(c, Node): - # raise TypeError, c - added = None - for c in child: - if c not in set: - set.add(c) - collection.append(c) - added = 1 - if added: - self._children_reset() - - def set_specific_source(self, source): - self.add_source(source) - self._specific_sources = True - - def add_wkid(self, wkid): - """Add a node to the list of kids waiting to be evaluated""" - if self.wkids is not None: - self.wkids.append(wkid) - - def _children_reset(self): - self.clear_memoized_values() - # We need to let the Executor clear out any calculated - # build info that it's cached so we can re-calculate it. - self.executor_cleanup() - - @SCons.Memoize.CountMethodCall - def _children_get(self): - try: - return self._memo['_children_get'] - except KeyError: - pass - - # The return list may contain duplicate Nodes, especially in - # source trees where there are a lot of repeated #includes - # of a tangle of .h files. Profiling shows, however, that - # eliminating the duplicates with a brute-force approach that - # preserves the order (that is, something like: - # - # u = [] - # for n in list: - # if n not in u: - # u.append(n)" - # - # takes more cycles than just letting the underlying methods - # hand back cached values if a Node's information is requested - # multiple times. (Other methods of removing duplicates, like - # using dictionary keys, lose the order, and the only ordered - # dictionary patterns I found all ended up using "not in" - # internally anyway...) - if self.ignore_set: - iter = chain.from_iterable(filter(None, [self.sources, self.depends, self.implicit])) - - children = [] - for i in iter: - if i not in self.ignore_set: - children.append(i) - else: - children = self.all_children(scan=0) - - self._memo['_children_get'] = children - return children - - def all_children(self, scan=1): - """Return a list of all the node's direct children.""" - if scan: - self.scan() - - # The return list may contain duplicate Nodes, especially in - # source trees where there are a lot of repeated #includes - # of a tangle of .h files. Profiling shows, however, that - # eliminating the duplicates with a brute-force approach that - # preserves the order (that is, something like: - # - # u = [] - # for n in list: - # if n not in u: - # u.append(n)" - # - # takes more cycles than just letting the underlying methods - # hand back cached values if a Node's information is requested - # multiple times. (Other methods of removing duplicates, like - # using dictionary keys, lose the order, and the only ordered - # dictionary patterns I found all ended up using "not in" - # internally anyway...) - return list(chain.from_iterable(filter(None, [self.sources, self.depends, self.implicit]))) - - def children(self, scan=1): - """Return a list of the node's direct children, minus those - that are ignored by this node.""" - if scan: - self.scan() - return self._children_get() - - def set_state(self, state): - self.state = state - - def get_state(self): - return self.state - - def get_env(self): - env = self.env - if not env: - import SCons.Defaults - env = SCons.Defaults.DefaultEnvironment() - return env - - def Decider(self, function): - foundkey = None - for k, v in _decider_map.iteritems(): - if v == function: - foundkey = k - break - if not foundkey: - foundkey = len(_decider_map) - _decider_map[foundkey] = function - self.changed_since_last_build = foundkey - - def Tag(self, key, value): - """ Add a user-defined tag. """ - if not self._tags: - self._tags = {} - self._tags[key] = value - - def GetTag(self, key): - """ Return a user-defined tag. """ - if not self._tags: - return None - return self._tags.get(key, None) - - def changed(self, node=None, allowcache=False): - """ - Returns if the node is up-to-date with respect to the BuildInfo - stored last time it was built. The default behavior is to compare - it against our own previously stored BuildInfo, but the stored - BuildInfo from another Node (typically one in a Repository) - can be used instead. - - Note that we now *always* check every dependency. We used to - short-circuit the check by returning as soon as we detected - any difference, but we now rely on checking every dependency - to make sure that any necessary Node information (for example, - the content signature of an #included .h file) is updated. - - The allowcache option was added for supporting the early - release of the executor/builder structures, right after - a File target was built. When set to true, the return - value of this changed method gets cached for File nodes. - Like this, the executor isn't needed any longer for subsequent - calls to changed(). - - @see: FS.File.changed(), FS.File.release_target_info() - """ - t = 0 - if t: Trace('changed(%s [%s], %s)' % (self, classname(self), node)) - if node is None: - node = self - - result = False - - bi = node.get_stored_info().binfo - then = bi.bsourcesigs + bi.bdependsigs + bi.bimplicitsigs - children = self.children() - - diff = len(children) - len(then) - if diff: - # The old and new dependency lists are different lengths. - # This always indicates that the Node must be rebuilt. - # We also extend the old dependency list with enough None - # entries to equal the new dependency list, for the benefit - # of the loop below that updates node information. - then.extend([None] * diff) - if t: Trace(': old %s new %s' % (len(then), len(children))) - 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 - - contents = self.get_executor().get_contents() - if self.has_builder(): - import SCons.Util - newsig = SCons.Util.MD5signature(contents) - if bi.bactsig != newsig: - if t: Trace(': bactsig %s != newsig %s' % (bi.bactsig, newsig)) - result = True - - if not result: - if t: Trace(': up to date') - - if t: Trace('\n') - - return result - - def is_up_to_date(self): - """Default check for whether the Node is current: unknown Node - subtypes are always out of date, so they will always get built.""" - return None - - def children_are_up_to_date(self): - """Alternate check for whether the Node is current: If all of - our children were up-to-date, then this Node was up-to-date, too. - - The SCons.Node.Alias and SCons.Node.Python.Value subclasses - rebind their current() method to this method.""" - # Allow the children to calculate their signatures. - self.binfo = self.get_binfo() - if self.always_build: - return None - state = 0 - for kid in self.children(None): - s = kid.get_state() - if s and (not state or s > state): - state = s - return (state == 0 or state == SCons.Node.up_to_date) - - def is_literal(self): - """Always pass the string representation of a Node to - the command interpreter literally.""" - return 1 - - def render_include_tree(self): - """ - Return a text representation, suitable for displaying to the - user, of the include tree for the sources of this node. - """ - if self.is_derived(): - env = self.get_build_env() - if env: - for s in self.sources: - scanner = self.get_source_scanner(s) - if scanner: - path = self.get_build_scanner_path(scanner) - else: - path = None - def f(node, env=env, scanner=scanner, path=path): - return node.get_found_includes(env, scanner, path) - return SCons.Util.render_tree(s, f, 1) - else: - return None - - def get_abspath(self): - """ - Return an absolute path to the Node. This will return simply - str(Node) by default, but for Node types that have a concept of - relative path, this might return something different. - """ - return str(self) - - def for_signature(self): - """ - Return a string representation of the Node that will always - be the same for this particular Node, no matter what. This - is by contrast to the __str__() method, which might, for - instance, return a relative path for a file Node. The purpose - of this method is to generate a value to be used in signature - calculation for the command line used to build a target, and - we use this method instead of str() to avoid unnecessary - rebuilds. This method does not need to return something that - would actually work in a command line; it can return any kind of - nonsense, so long as it does not change. - """ - return str(self) - - def get_string(self, for_signature): - """This is a convenience function designed primarily to be - used in command generators (i.e., CommandGeneratorActions or - Environment variables that are callable), which are called - with a for_signature argument that is nonzero if the command - generator is being called to generate a signature for the - command line, which determines if we should rebuild or not. - - Such command generators should use this method in preference - to str(Node) when converting a Node to a string, passing - in the for_signature parameter, such that we will call - Node.for_signature() or str(Node) properly, depending on whether - we are calculating a signature or actually constructing a - command line.""" - if for_signature: - return self.for_signature() - return str(self) - - def get_subst_proxy(self): - """ - This method is expected to return an object that will function - exactly like this Node, except that it implements any additional - special features that we would like to be in effect for - Environment variable substitution. The principle use is that - some Nodes would like to implement a __getattr__() method, - but putting that in the Node type itself has a tendency to kill - performance. We instead put it in a proxy and return it from - this method. It is legal for this method to return self - if no new functionality is needed for Environment substitution. - """ - return self - - def explain(self): - if not self.exists(): - return "building `%s' because it doesn't exist\n" % self - - if self.always_build: - return "rebuilding `%s' because AlwaysBuild() is specified\n" % self - - old = self.get_stored_info() - if old is None: - return None - - old = old.binfo - old.prepare_dependencies() - - try: - old_bkids = old.bsources + old.bdepends + old.bimplicit - old_bkidsigs = old.bsourcesigs + old.bdependsigs + old.bimplicitsigs - except AttributeError: - return "Cannot explain why `%s' is being rebuilt: No previous build information found\n" % self - - new = self.get_binfo() - - new_bkids = new.bsources + new.bdepends + new.bimplicit - new_bkidsigs = new.bsourcesigs + new.bdependsigs + new.bimplicitsigs - - osig = dict(zip(old_bkids, old_bkidsigs)) - nsig = dict(zip(new_bkids, new_bkidsigs)) - - # The sources and dependencies we'll want to report are all stored - # as relative paths to this target's directory, but we want to - # report them relative to the top-level SConstruct directory, - # 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 ) : - if hasattr( s, 'dir' ) : - return str(E(s)) - return str(s) - - lines = [] - - removed = [x for x in old_bkids if not x in new_bkids] - if removed: - removed = list(map(stringify, 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)) - - if len(lines) == 0 and old_bkids != new_bkids: - lines.append("the dependency order changed:\n" + - "%sold: %s\n" % (' '*15, list(map(stringify, old_bkids))) + - "%snew: %s\n" % (' '*15, list(map(stringify, new_bkids)))) - - if len(lines) == 0: - def fmt_with_title(title, strlines): - lines = strlines.split('\n') - sep = '\n' + ' '*(15 + len(title)) - return ' '*15 + title + sep.join(lines) + '\n' - if old.bactsig != new.bactsig: - if old.bact == new.bact: - lines.append("the contents of the build action changed\n" + - fmt_with_title('action: ', new.bact)) - else: - lines.append("the build action changed:\n" + - fmt_with_title('old: ', old.bact) + - fmt_with_title('new: ', new.bact)) - - if len(lines) == 0: - return "rebuilding `%s' for unknown reasons\n" % self - - preamble = "rebuilding `%s' because" % self - if len(lines) == 1: - return "%s %s" % (preamble, lines[0]) - else: - lines = ["%s:\n" % preamble] + lines - return ( ' '*11).join(lines) - -class NodeList(collections.UserList): - def __str__(self): - return str(list(map(str, self.data))) - -def get_children(node, parent): return node.children() -def ignore_cycle(node, stack): pass -def do_nothing(node, parent): pass - -class Walker(object): - """An iterator for walking a Node tree. - - This is depth-first, children are visited before the parent. - The Walker object can be initialized with any node, and - returns the next node on the descent with each get_next() call. - 'kids_func' is an optional function that will be called to - get the children of a node instead of calling 'children'. - 'cycle_func' is an optional function that will be called - when a cycle is detected. - - This class does not get caught in node cycles caused, for example, - by C header file include loops. - """ - def __init__(self, node, kids_func=get_children, - cycle_func=ignore_cycle, - eval_func=do_nothing): - self.kids_func = kids_func - self.cycle_func = cycle_func - self.eval_func = eval_func - node.wkids = copy.copy(kids_func(node, None)) - self.stack = [node] - self.history = {} # used to efficiently detect and avoid cycles - self.history[node] = None - - def get_next(self): - """Return the next node for this walk of the tree. - - This function is intentionally iterative, not recursive, - to sidestep any issues of stack size limitations. - """ - - while self.stack: - if self.stack[-1].wkids: - node = self.stack[-1].wkids.pop(0) - if not self.stack[-1].wkids: - self.stack[-1].wkids = None - if node in self.history: - self.cycle_func(node, self.stack) - else: - node.wkids = copy.copy(self.kids_func(node, self.stack[-1])) - self.stack.append(node) - self.history[node] = None - else: - node = self.stack.pop() - del self.history[node] - if node: - if self.stack: - parent = self.stack[-1] - else: - parent = None - self.eval_func(node, parent) - return node - return None - - def is_done(self): - return not self.stack - - -arg2nodes_lookups = [] - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/BoolOption.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/BoolOption.py deleted file mode 100644 index c8d901f..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/BoolOption.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/BoolOption.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 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 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) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/EnumOption.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/EnumOption.py deleted file mode 100644 index 58b99ef..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/EnumOption.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/EnumOption.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 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 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) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/ListOption.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/ListOption.py deleted file mode 100644 index 00c93d9..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/ListOption.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/ListOption.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 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 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) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/PackageOption.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/PackageOption.py deleted file mode 100644 index 56624f0..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/PackageOption.py +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 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/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/PathOption.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/PathOption.py deleted file mode 100644 index a4b81ec..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/PathOption.py +++ /dev/null @@ -1,76 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 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/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/__init__.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/__init__.py deleted file mode 100644 index 5099712..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Options/__init__.py +++ /dev/null @@ -1,67 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 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/3rdParty/SCons/scons-2.4.0/engine/SCons/PathList.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/PathList.py deleted file mode 100644 index b359144..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/PathList.py +++ /dev/null @@ -1,227 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/PathList.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -__doc__ = """SCons.PathList - -A module for handling lists of directory paths (the sort of things -that get set as CPPPATH, LIBPATH, etc.) with as much caching of data and -efficiency as we can while still keeping the evaluation delayed so that we -Do the Right Thing (almost) regardless of how the variable is specified. - -""" - -import os - -import SCons.Memoize -import SCons.Node -import SCons.Util - -# -# Variables to specify the different types of entries in a PathList object: -# - -TYPE_STRING_NO_SUBST = 0 # string with no '$' -TYPE_STRING_SUBST = 1 # string containing '$' -TYPE_OBJECT = 2 # other object - -def node_conv(obj): - """ - This is the "string conversion" routine that we have our substitutions - use to return Nodes, not strings. This relies on the fact that an - EntryProxy object has a get() method that returns the underlying - Node that it wraps, which is a bit of architectural dependence - that we might need to break or modify in the future in response to - additional requirements. - """ - try: - get = obj.get - except AttributeError: - if isinstance(obj, SCons.Node.Node) or SCons.Util.is_Sequence( obj ): - result = obj - else: - result = str(obj) - else: - result = get() - return result - -class _PathList(object): - """ - An actual PathList object. - """ - def __init__(self, pathlist): - """ - Initializes a PathList object, canonicalizing the input and - pre-processing it for quicker substitution later. - - The stored representation of the PathList is a list of tuples - containing (type, value), where the "type" is one of the TYPE_* - variables defined above. We distinguish between: - - strings that contain no '$' and therefore need no - delayed-evaluation string substitution (we expect that there - will be many of these and that we therefore get a pretty - big win from avoiding string substitution) - - strings that contain '$' and therefore need substitution - (the hard case is things like '${TARGET.dir}/include', - which require re-evaluation for every target + source) - - other objects (which may be something like an EntryProxy - that needs a method called to return a Node) - - Pre-identifying the type of each element in the PathList up-front - and storing the type in the list of tuples is intended to reduce - the amount of calculation when we actually do the substitution - over and over for each target. - """ - if SCons.Util.is_String(pathlist): - pathlist = pathlist.split(os.pathsep) - elif not SCons.Util.is_Sequence(pathlist): - pathlist = [pathlist] - - pl = [] - for p in pathlist: - try: - index = p.find('$') - except (AttributeError, TypeError): - type = TYPE_OBJECT - else: - if index == -1: - type = TYPE_STRING_NO_SUBST - else: - type = TYPE_STRING_SUBST - pl.append((type, p)) - - self.pathlist = tuple(pl) - - def __len__(self): return len(self.pathlist) - - def __getitem__(self, i): return self.pathlist[i] - - def subst_path(self, env, target, source): - """ - Performs construction variable substitution on a pre-digested - PathList for a specific target and source. - """ - result = [] - for type, value in self.pathlist: - if type == TYPE_STRING_SUBST: - value = env.subst(value, target=target, source=source, - conv=node_conv) - if SCons.Util.is_Sequence(value): - result.extend(SCons.Util.flatten(value)) - elif value: - result.append(value) - elif type == TYPE_OBJECT: - value = node_conv(value) - if value: - result.append(value) - elif value: - result.append(value) - return tuple(result) - - -class PathListCache(object): - """ - A class to handle caching of PathList lookups. - - This class gets instantiated once and then deleted from the namespace, - so it's used as a Singleton (although we don't enforce that in the - usual Pythonic ways). We could have just made the cache a dictionary - in the module namespace, but putting it in this class allows us to - use the same Memoizer pattern that we use elsewhere to count cache - hits and misses, which is very valuable. - - Lookup keys in the cache are computed by the _PathList_key() method. - Cache lookup should be quick, so we don't spend cycles canonicalizing - all forms of the same lookup key. For example, 'x:y' and ['x', - 'y'] logically represent the same list, but we don't bother to - split string representations and treat those two equivalently. - (Note, however, that we do, treat lists and tuples the same.) - - The main type of duplication we're trying to catch will come from - looking up the same path list from two different clones of the - same construction environment. That is, given - - env2 = env1.Clone() - - both env1 and env2 will have the same CPPPATH value, and we can - cheaply avoid re-parsing both values of CPPPATH by using the - common value from this cache. - """ - def __init__(self): - self._memo = {} - - def _PathList_key(self, pathlist): - """ - Returns the key for memoization of PathLists. - - Note that we want this to be pretty quick, so we don't completely - canonicalize all forms of the same list. For example, - 'dir1:$ROOT/dir2' and ['$ROOT/dir1', 'dir'] may logically - represent the same list if you're executing from $ROOT, but - we're not going to bother splitting strings into path elements, - or massaging strings into Nodes, to identify that equivalence. - We just want to eliminate obvious redundancy from the normal - case of re-using exactly the same cloned value for a path. - """ - if SCons.Util.is_Sequence(pathlist): - pathlist = tuple(SCons.Util.flatten(pathlist)) - return pathlist - - @SCons.Memoize.CountDictCall(_PathList_key) - def PathList(self, pathlist): - """ - Returns the cached _PathList object for the specified pathlist, - creating and caching a new object as necessary. - """ - pathlist = self._PathList_key(pathlist) - try: - memo_dict = self._memo['PathList'] - except KeyError: - memo_dict = {} - self._memo['PathList'] = memo_dict - else: - try: - return memo_dict[pathlist] - except KeyError: - pass - - result = _PathList(pathlist) - - memo_dict[pathlist] = result - - return result - -PathList = PathListCache().PathList - - -del PathListCache - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/__init__.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/__init__.py deleted file mode 100644 index ca4bc9b..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/__init__.py +++ /dev/null @@ -1,264 +0,0 @@ -"""SCons.Platform - -SCons platform selection. - -This looks for modules that define a callable object that can modify a -construction environment as appropriate for a given platform. - -Note that we take a more simplistic view of "platform" than Python does. -We're looking for a single string that determines a set of -tool-independent variables with which to initialize a construction -environment. Consequently, we'll examine both sys.platform and os.name -(and anything else that might come in to play) in order to return some -specification which is unique enough for our purposes. - -Note that because this subsysem just *selects* a callable that can -modify a construction environment, it's possible for people to define -their own "platform specification" in an arbitrary callable function. -No one needs to use or tie in to this subsystem in order to roll -their own platform definition. -""" - -# -# Copyright (c) 2001 - 2015 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/__init__.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.compat - -import imp -import os -import sys -import tempfile - -import SCons.Errors -import SCons.Subst -import SCons.Tool - -def platform_default(): - """Return the platform string for our execution environment. - - The returned value should map to one of the SCons/Platform/*.py - files. Since we're architecture independent, though, we don't - care about the machine architecture. - """ - osname = os.name - if osname == 'java': - osname = os._osType - if osname == 'posix': - if sys.platform == 'cygwin': - return 'cygwin' - elif sys.platform.find('irix') != -1: - return 'irix' - elif sys.platform.find('sunos') != -1: - return 'sunos' - elif sys.platform.find('hp-ux') != -1: - return 'hpux' - elif sys.platform.find('aix') != -1: - return 'aix' - elif sys.platform.find('darwin') != -1: - return 'darwin' - else: - return 'posix' - elif os.name == 'os2': - return 'os2' - else: - return sys.platform - -def platform_module(name = platform_default()): - """Return the imported module for the platform. - - This looks for a module name that matches the specified argument. - If the name is unspecified, we fetch the appropriate default for - our execution environment. - """ - full_name = 'SCons.Platform.' + name - if full_name not in sys.modules: - if os.name == 'java': - eval(full_name) - else: - try: - file, path, desc = imp.find_module(name, - sys.modules['SCons.Platform'].__path__) - try: - mod = imp.load_module(full_name, file, path, desc) - finally: - if file: - file.close() - except ImportError: - try: - import zipimport - importer = zipimport.zipimporter( sys.modules['SCons.Platform'].__path__[0] ) - mod = importer.load_module(full_name) - except ImportError: - raise SCons.Errors.UserError("No platform named '%s'" % name) - 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 - self.generate = generate - - def __call__(self, *args, **kw): - return self.generate(*args, **kw) - - 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 - file substitution on it. This is used to circumvent the long command - line limitation. - - Example usage: - 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 - """ - def __init__(self, cmd, cmdstr = None): - self.cmd = cmd - self.cmdstr = cmdstr - - def __call__(self, target, source, env, for_signature): - if for_signature: - # If we're being called for signature calculation, it's - # because we're being called by the string expansion in - # Subst.py, which has the logic to strip any $( $) that - # may be in the command line we squirreled away. So we - # just return the raw command line and let the upper - # string substitution layers do their thing. - return self.cmd - - # Now we're actually being called because someone is actually - # going to try to execute the command, so we have to do our - # own expansion. - cmd = env.subst_list(self.cmd, SCons.Subst.SUBST_CMD, target, source)[0] - try: - maxline = int(env.subst('$MAXLINELENGTH')) - except ValueError: - maxline = 2048 - - length = 0 - for c in cmd: - length += len(c) - length += len(cmd) - 1 - if length <= maxline: - return self.cmd - - # Check if we already created the temporary file for this target - # It should have been previously done by Action.strfunction() call - node = target[0] if SCons.Util.is_List(target) else target - cmdlist = getattr(node.attributes, 'tempfile_cmdlist', None) \ - if node is not None else None - if 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 - # switch and barfs. - # - # We use 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) - native_tmp = SCons.Util.get_native_path(os.path.normpath(tmp)) - - 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'\\\\') - # In Cygwin, we want to use rm to delete the temporary - # file, because del does not exist in the sh shell. - rm = env.Detect('rm') or 'del' - else: - # Don't use 'rm' if the shell is not sh, because rm won't - # work with the Windows shells (cmd.exe or command.com) or - # Windows path names. - rm = 'del' - - prefix = env.subst('$TEMPFILEPREFIX') - if not prefix: - prefix = '@' - - args = list(map(SCons.Subst.quote_spaces, cmd[1:])) - os.write(fd, " ".join(args) + "\n") - os.close(fd) - # XXX Using the SCons.Action.print_actions value directly - # like this is bogus, but expedient. This class should - # really be rewritten as an Action that defines the - # __call__() and strfunction() methods and lets the - # normal action-execution logic handle whether or not to - # print/execute the action. The problem, though, is all - # of that is decided before we execute this method as - # part of expanding the $TEMPFILE construction variable. - # Consequently, refactoring this will have to wait until - # we get more flexible with allowing Actions to exist - # independently and get strung together arbitrarily like - # Ant tasks. In the meantime, it's going to be more - # user-friendly to not let obsession with architectural - # purity get in the way of just being helpful, so we'll - # reach into SCons.Action directly. - if SCons.Action.print_actions: - cmdstr = env.subst(self.cmdstr, SCons.Subst.SUBST_RAW, target, - 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)) - - # Store the temporary file command list into the target Node.attributes - # to avoid creating two temporary files one for print and one for execute. - cmdlist = [ cmd[0], prefix + native_tmp + '\n' + rm, native_tmp ] - if node is not None: - try : - setattr(node.attributes, 'tempfile_cmdlist', cmdlist) - except AttributeError: - pass - return cmdlist - -def Platform(name = platform_default()): - """Select a canned Platform specification. - """ - module = platform_module(name) - spec = PlatformSpec(name, module.generate) - return spec - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/aix.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/aix.py deleted file mode 100644 index 44bccd1..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/aix.py +++ /dev/null @@ -1,85 +0,0 @@ -"""engine.SCons.Platform.aix - -Platform-specific initialization for IBM AIX systems. - -There normally shouldn't be any need to import this module directly. It -will usually be imported through the generic SCons.Platform.Platform() -selection method. -""" - -# -# Copyright (c) 2001 - 2015 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/aix.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import os -import subprocess - -import posix - -import SCons.Util -import SCons.Action - -def get_xlc(env, xlc=None, packages=[]): - # Use the AIX package installer tool lslpp to figure out where a - # given xl* compiler is installed and what version it is. - xlcPath = None - xlcVersion = None - - if xlc is None: - xlc = env.get('CC', 'xlc') - if SCons.Util.is_List(xlc): - xlc = xlc[0] - for package in packages: - # find the installed filename, which may be a symlink as well - pipe = SCons.Action._subproc(env, ['lslpp', '-fc', package], - stdin = 'devnull', - stderr = 'devnull', - stdout = subprocess.PIPE) - # output of lslpp is something like this: - # #Path:Fileset:File - # /usr/lib/objrepos:vac.C 6.0.0.0:/usr/vac/exe/xlCcpp - # /usr/lib/objrepos:vac.C 6.0.0.0:/usr/vac/bin/xlc_r -> /usr/vac/bin/xlc - for line in pipe.stdout: - if xlcPath: - continue # read everything to let lslpp terminate - fileset, filename = line.split(':')[1:3] - filename = filename.split()[0] - if ('/' in xlc and filename == xlc) \ - or ('/' not in xlc and filename.endswith('/' + xlc)): - xlcVersion = fileset.split()[1] - xlcPath, sep, xlc = filename.rpartition('/') - pass - pass - return (xlcPath, xlc, xlcVersion) - -def generate(env): - posix.generate(env) - #Based on AIX 5.2: ARG_MAX=24576 - 3000 for environment expansion - env['MAXLINELENGTH'] = 21576 - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/cygwin.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/cygwin.py deleted file mode 100644 index d04bbe7..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/cygwin.py +++ /dev/null @@ -1,55 +0,0 @@ -"""SCons.Platform.cygwin - -Platform-specific initialization for Cygwin systems. - -There normally shouldn't be any need to import this module directly. It -will usually be imported through the generic SCons.Platform.Platform() -selection method. -""" - -# -# Copyright (c) 2001 - 2015 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/cygwin.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import posix -from SCons.Platform import TempFileMunge - -def generate(env): - posix.generate(env) - - env['PROGPREFIX'] = '' - env['PROGSUFFIX'] = '.exe' - env['SHLIBPREFIX'] = '' - env['SHLIBSUFFIX'] = '.dll' - env['LIBPREFIXES'] = [ '$LIBPREFIX', '$SHLIBPREFIX' ] - env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ] - env['TEMPFILE'] = TempFileMunge - env['TEMPFILEPREFIX'] = '@' - env['MAXLINELENGTH'] = 2048 - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/darwin.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/darwin.py deleted file mode 100644 index efd8ba4..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/darwin.py +++ /dev/null @@ -1,70 +0,0 @@ -"""engine.SCons.Platform.darwin - -Platform-specific initialization for Mac OS X systems. - -There normally shouldn't be any need to import this module directly. It -will usually be imported through the generic SCons.Platform.Platform() -selection method. -""" - -# -# Copyright (c) 2001 - 2015 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/darwin.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import posix -import os - -def generate(env): - posix.generate(env) - env['SHLIBSUFFIX'] = '.dylib' - # put macports paths at front to override Apple's versions, fink path is after - # For now let people who want Macports or Fink tools specify it! - # env['ENV']['PATH'] = '/opt/local/bin:/opt/local/sbin:' + env['ENV']['PATH'] + ':/sw/bin' - - # Store extra system paths in env['ENV']['PATHOSX'] - - filelist = ['/etc/paths',] - # make sure this works on Macs with Tiger or earlier - try: - dirlist = os.listdir('/etc/paths.d') - except: - dirlist = [] - - for file in dirlist: - filelist.append('/etc/paths.d/'+file) - - for file in filelist: - if os.path.isfile(file): - f = open(file, 'r') - lines = f.readlines() - for line in lines: - if line: - env.AppendENVPath('PATHOSX', line.strip('\n')) - f.close() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/hpux.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/hpux.py deleted file mode 100644 index 2e2fbca..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/hpux.py +++ /dev/null @@ -1,46 +0,0 @@ -"""engine.SCons.Platform.hpux - -Platform-specific initialization for HP-UX systems. - -There normally shouldn't be any need to import this module directly. It -will usually be imported through the generic SCons.Platform.Platform() -selection method. -""" - -# -# Copyright (c) 2001 - 2015 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/hpux.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import posix - -def generate(env): - posix.generate(env) - #Based on HP-UX11i: ARG_MAX=2048000 - 3000 for environment expansion - env['MAXLINELENGTH'] = 2045000 - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/irix.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/irix.py deleted file mode 100644 index 3bedbdf..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/irix.py +++ /dev/null @@ -1,44 +0,0 @@ -"""SCons.Platform.irix - -Platform-specific initialization for SGI IRIX systems. - -There normally shouldn't be any need to import this module directly. It -will usually be imported through the generic SCons.Platform.Platform() -selection method. -""" - -# -# Copyright (c) 2001 - 2015 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/irix.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import posix - -def generate(env): - posix.generate(env) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/os2.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/os2.py deleted file mode 100644 index 82eb163..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/os2.py +++ /dev/null @@ -1,58 +0,0 @@ -"""SCons.Platform.os2 - -Platform-specific initialization for OS/2 systems. - -There normally shouldn't be any need to import this module directly. It -will usually be imported through the generic SCons.Platform.Platform() -selection method. -""" - -# -# Copyright (c) 2001 - 2015 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/os2.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" -import win32 - -def generate(env): - if 'ENV' not in env: - env['ENV'] = {} - env['OBJPREFIX'] = '' - env['OBJSUFFIX'] = '.obj' - env['SHOBJPREFIX'] = '$OBJPREFIX' - env['SHOBJSUFFIX'] = '$OBJSUFFIX' - env['PROGPREFIX'] = '' - env['PROGSUFFIX'] = '.exe' - env['LIBPREFIX'] = '' - env['LIBSUFFIX'] = '.lib' - env['SHLIBPREFIX'] = '' - env['SHLIBSUFFIX'] = '.dll' - env['LIBPREFIXES'] = '$LIBPREFIX' - env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ] - env['HOST_OS'] = 'os2' - env['HOST_ARCH'] = win32.get_architecture().arch - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/posix.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/posix.py deleted file mode 100644 index 8445863..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/posix.py +++ /dev/null @@ -1,124 +0,0 @@ -"""SCons.Platform.posix - -Platform-specific initialization for POSIX (Linux, UNIX, etc.) systems. - -There normally shouldn't be any need to import this module directly. It -will usually be imported through the generic SCons.Platform.Platform() -selection method. -""" - -# -# Copyright (c) 2001 - 2015 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/posix.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import errno -import os -import os.path -import subprocess -import sys -import select - -import SCons.Util -from SCons.Platform import TempFileMunge - -exitvalmap = { - 2 : 127, - 13 : 126, -} - -def escape(arg): - "escape shell special characters" - slash = '\\' - special = '"$()' - - arg = arg.replace(slash, slash+slash) - for c in special: - arg = arg.replace(c, slash+c) - - return '"' + arg + '"' - -def exec_subprocess(l, env): - proc = subprocess.Popen(l, env = env, close_fds = True) - return proc.wait() - -def subprocess_spawn(sh, escape, cmd, args, env): - return exec_subprocess([sh, '-c', ' '.join(args)], env) - -def exec_popen3(l, env, stdout, stderr): - proc = subprocess.Popen(l, env = env, close_fds = True, - stdout = stdout, - stderr = stderr) - return proc.wait() - -def piped_env_spawn(sh, escape, cmd, args, env, stdout, stderr): - # spawn using Popen3 combined with the env command - # the command name and the command's stdout is written to stdout - # the command's stderr is written to stderr - return exec_popen3([sh, '-c', ' '.join(args)], - env, stdout, stderr) - - -def generate(env): - # Bearing in mind we have python 2.4 as a baseline, we can just do this: - spawn = subprocess_spawn - pspawn = piped_env_spawn - # Note that this means that 'escape' is no longer used - - if 'ENV' not in env: - env['ENV'] = {} - env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin' - env['OBJPREFIX'] = '' - env['OBJSUFFIX'] = '.o' - env['SHOBJPREFIX'] = '$OBJPREFIX' - env['SHOBJSUFFIX'] = '$OBJSUFFIX' - env['PROGPREFIX'] = '' - env['PROGSUFFIX'] = '' - env['LIBPREFIX'] = 'lib' - env['LIBSUFFIX'] = '.a' - env['SHLIBPREFIX'] = '$LIBPREFIX' - env['SHLIBSUFFIX'] = '.so' - env['LIBPREFIXES'] = [ '$LIBPREFIX' ] - env['LIBSUFFIXES'] = [ '$LIBSUFFIX', '$SHLIBSUFFIX' ] - env['PSPAWN'] = pspawn - env['SPAWN'] = spawn - env['SHELL'] = 'sh' - env['ESCAPE'] = escape - env['TEMPFILE'] = TempFileMunge - env['TEMPFILEPREFIX'] = '@' - #Based on LINUX: ARG_MAX=ARG_MAX=131072 - 3000 for environment expansion - #Note: specific platforms might rise or lower this value - env['MAXLINELENGTH'] = 128072 - - # This platform supports RPATH specifications. - env['__RPATH'] = '$_RPATH' - - # GDC is GCC family, but DMD and LDC have different options. - # Must be able to have GCC and DMD work in the same build, so: - env['__DRPATH'] = '$_DRPATH' - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/sunos.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/sunos.py deleted file mode 100644 index 1c1d797..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/sunos.py +++ /dev/null @@ -1,50 +0,0 @@ -"""engine.SCons.Platform.sunos - -Platform-specific initialization for Sun systems. - -There normally shouldn't be any need to import this module directly. It -will usually be imported through the generic SCons.Platform.Platform() -selection method. -""" - -# -# Copyright (c) 2001 - 2015 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/sunos.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import posix - -def generate(env): - posix.generate(env) - # Based on sunSparc 8:32bit - # ARG_MAX=1048320 - 3000 for environment expansion - env['MAXLINELENGTH'] = 1045320 - env['PKGINFO'] = 'pkginfo' - env['PKGCHK'] = '/usr/sbin/pkgchk' - env['ENV']['PATH'] = env['ENV']['PATH'] + ':/opt/SUNWspro/bin:/usr/ccs/bin' - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/win32.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/win32.py deleted file mode 100644 index 3bad86b..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Platform/win32.py +++ /dev/null @@ -1,415 +0,0 @@ -"""SCons.Platform.win32 - -Platform-specific initialization for Win32 systems. - -There normally shouldn't be any need to import this module directly. It -will usually be imported through the generic SCons.Platform.Platform() -selection method. -""" - -# -# Copyright (c) 2001 - 2015 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/win32.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import os -import os.path -import sys -import tempfile - -from SCons.Platform.posix import exitvalmap -from SCons.Platform import TempFileMunge -import SCons.Util - -try: - import msvcrt - import win32api - import win32con - - msvcrt.get_osfhandle - win32api.SetHandleInformation - win32con.HANDLE_FLAG_INHERIT -except ImportError: - parallel_msg = \ - "you do not seem to have the pywin32 extensions installed;\n" + \ - "\tparallel (-j) builds may not work reliably with open Python files." -except AttributeError: - parallel_msg = \ - "your pywin32 extensions do not support file handle operations;\n" + \ - "\tparallel (-j) builds may not work reliably with open Python files." -else: - parallel_msg = None - - import builtins - - _builtin_file = builtins.file - _builtin_open = builtins.open - - 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) - - def _scons_open(*args, **kw): - fp = _builtin_open(*args, **kw) - win32api.SetHandleInformation(msvcrt.get_osfhandle(fp.fileno()), - win32con.HANDLE_FLAG_INHERIT, - 0) - return fp - - builtins.file = _scons_file - builtins.open = _scons_open - -try: - import threading - spawn_lock = threading.Lock() - - # This locked version of spawnve works around a Windows - # MSVCRT bug, because its spawnve is not thread-safe. - # 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 - def spawnve(mode, file, args, env): - spawn_lock.acquire() - try: - if mode == os.P_WAIT: - ret = os.spawnve(os.P_NOWAIT, file, args, env) - else: - ret = os.spawnve(mode, file, args, env) - finally: - spawn_lock.release() - if mode == os.P_WAIT: - pid, status = os.waitpid(ret, 0) - ret = status >> 8 - return ret -except ImportError: - # Use the unsafe method of spawnve. - # Please, don't try to optimize this try-except block - # away by assuming that the threading module is always present. - # In the test test/option-j.py we intentionally call SCons with - # a fake threading.py that raises an import exception right away, - # simulating a non-existent package. - def spawnve(mode, file, args, env): - return os.spawnve(mode, file, args, env) - -# The upshot of all this is that, if you are using Python 1.5.2, -# you had better have cmd or command.com in your PATH when you run -# scons. - -def piped_spawn(sh, escape, cmd, args, env, stdout, stderr): - # There is no direct way to do that in python. What we do - # here should work for most cases: - # In case stdout (stderr) is not redirected to a file, - # we redirect it into a temporary file tmpFileStdout - # (tmpFileStderr) and copy the contents of this file - # to stdout (stderr) given in the argument - if not sh: - sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n") - return 127 - else: - # one temporary file for stdout and stderr - tmpFileStdout = os.path.normpath(tempfile.mktemp()) - tmpFileStderr = os.path.normpath(tempfile.mktemp()) - - # check if output is redirected - stdoutRedirected = 0 - stderrRedirected = 0 - for arg in args: - # are there more possibilities to redirect stdout ? - if (arg.find( ">", 0, 1 ) != -1 or - arg.find( "1>", 0, 2 ) != -1): - stdoutRedirected = 1 - # are there more possibilities to redirect stderr ? - if arg.find( "2>", 0, 2 ) != -1: - stderrRedirected = 1 - - # redirect output of non-redirected streams to our tempfiles - if stdoutRedirected == 0: - args.append(">" + str(tmpFileStdout)) - if stderrRedirected == 0: - args.append("2>" + str(tmpFileStderr)) - - # actually do the spawn - try: - args = [sh, '/C', escape(' '.join(args)) ] - ret = spawnve(os.P_WAIT, sh, args, env) - except OSError, e: - # catch any error - try: - ret = exitvalmap[e[0]] - except KeyError: - sys.stderr.write("scons: unknown OSError exception code %d - %s: %s\n" % (e[0], cmd, e[1])) - if stderr is not None: - stderr.write("scons: %s: %s\n" % (cmd, e[1])) - # copy child output from tempfiles to our streams - # and do clean up stuff - if stdout is not None and stdoutRedirected == 0: - try: - stdout.write(open( tmpFileStdout, "r" ).read()) - os.remove( tmpFileStdout ) - except (IOError, OSError): - pass - - if stderr is not None and stderrRedirected == 0: - try: - stderr.write(open( tmpFileStderr, "r" ).read()) - os.remove( tmpFileStderr ) - except (IOError, OSError): - pass - return ret - -def exec_spawn(l, env): - try: - result = spawnve(os.P_WAIT, l[0], l, env) - except OSError, e: - try: - result = exitvalmap[e[0]] - sys.stderr.write("scons: %s: %s\n" % (l[0], e[1])) - except KeyError: - result = 127 - if len(l) > 2: - if len(l[2]) < 1000: - command = ' '.join(l[0:3]) - else: - command = l[0] - else: - command = l[0] - sys.stderr.write("scons: unknown OSError exception code %d - '%s': %s\n" % (e[0], command, e[1])) - return result - -def spawn(sh, escape, cmd, args, env): - if not sh: - sys.stderr.write("scons: Could not find command interpreter, is it in your PATH?\n") - return 127 - return exec_spawn([sh, '/C', escape(' '.join(args))], env) - -# Windows does not allow special characters in file names anyway, so no -# need for a complex escape function, we will just quote the arg, except -# that "cmd /c" requires that if an argument ends with a backslash it -# needs to be escaped so as not to interfere with closing double quote -# that we add. -def escape(x): - if x[-1] == '\\': - x = x + '\\' - return '"' + x + '"' - -# Get the windows system directory name -_system_root = None - -def get_system_root(): - global _system_root - if _system_root is not None: - return _system_root - - # A resonable default if we can't read the registry - val = os.environ.get('SystemRoot', "C:\\WINDOWS") - - if SCons.Util.can_read_reg: - try: - # Look for Windows NT system root - k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, - 'Software\\Microsoft\\Windows NT\\CurrentVersion') - val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot') - except SCons.Util.RegError: - try: - # Okay, try the Windows 9x system root - k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, - 'Software\\Microsoft\\Windows\\CurrentVersion') - val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot') - except KeyboardInterrupt: - raise - except: - pass - _system_root = val - return val - -# Get the location of the program files directory -def get_program_files_dir(): - # Now see if we can look in the registry... - val = '' - if SCons.Util.can_read_reg: - try: - # Look for Windows Program Files directory - k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, - 'Software\\Microsoft\\Windows\\CurrentVersion') - val, tok = SCons.Util.RegQueryValueEx(k, 'ProgramFilesDir') - except SCons.Util.RegError: - val = '' - pass - - if val == '': - # A reasonable default if we can't read the registry - # (Actually, it's pretty reasonable even if we can :-) - val = os.path.join(os.path.dirname(get_system_root()),"Program Files") - - return val - - - -# Determine which windows CPU were running on. -class ArchDefinition(object): - """ - A class for defining architecture-specific settings and logic. - """ - def __init__(self, arch, synonyms=[]): - self.arch = arch - self.synonyms = synonyms - -SupportedArchitectureList = [ - ArchDefinition( - 'x86', - ['i386', 'i486', 'i586', 'i686'], - ), - - ArchDefinition( - 'x86_64', - ['AMD64', 'amd64', 'em64t', 'EM64T', 'x86_64'], - ), - - ArchDefinition( - 'ia64', - ['IA64'], - ), -] - -SupportedArchitectureMap = {} -for a in SupportedArchitectureList: - SupportedArchitectureMap[a.arch] = a - for s in a.synonyms: - SupportedArchitectureMap[s] = a - -def get_architecture(arch=None): - """Returns the definition for the specified architecture string. - - If no string is specified, the system default is returned (as defined - by the PROCESSOR_ARCHITEW6432 or PROCESSOR_ARCHITECTURE environment - variables). - """ - if arch is None: - arch = os.environ.get('PROCESSOR_ARCHITEW6432') - if not arch: - arch = os.environ.get('PROCESSOR_ARCHITECTURE') - return SupportedArchitectureMap.get(arch, ArchDefinition('', [''])) - -def generate(env): - # Attempt to find cmd.exe (for WinNT/2k/XP) or - # command.com for Win9x - cmd_interp = '' - # First see if we can look in the registry... - if SCons.Util.can_read_reg: - try: - # Look for Windows NT system root - k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, - 'Software\\Microsoft\\Windows NT\\CurrentVersion') - val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot') - cmd_interp = os.path.join(val, 'System32\\cmd.exe') - except SCons.Util.RegError: - try: - # Okay, try the Windows 9x system root - k=SCons.Util.RegOpenKeyEx(SCons.Util.hkey_mod.HKEY_LOCAL_MACHINE, - 'Software\\Microsoft\\Windows\\CurrentVersion') - val, tok = SCons.Util.RegQueryValueEx(k, 'SystemRoot') - cmd_interp = os.path.join(val, 'command.com') - except KeyboardInterrupt: - raise - except: - pass - - # For the special case of not having access to the registry, we - # use a temporary path and pathext to attempt to find the command - # interpreter. If we fail, we try to find the interpreter through - # the env's PATH. The problem with that is that it might not - # contain an ENV and a PATH. - if not cmd_interp: - systemroot = get_system_root() - tmp_path = systemroot + os.pathsep + \ - os.path.join(systemroot,'System32') - tmp_pathext = '.com;.exe;.bat;.cmd' - if 'PATHEXT' in os.environ: - tmp_pathext = os.environ['PATHEXT'] - cmd_interp = SCons.Util.WhereIs('cmd', tmp_path, tmp_pathext) - if not cmd_interp: - cmd_interp = SCons.Util.WhereIs('command', tmp_path, tmp_pathext) - - if not cmd_interp: - cmd_interp = env.Detect('cmd') - if not cmd_interp: - cmd_interp = env.Detect('command') - - - if 'ENV' not in env: - env['ENV'] = {} - - # Import things from the external environment to the construction - # environment's ENV. This is a potential slippery slope, because we - # *don't* want to make builds dependent on the user's environment by - # default. We're doing this for SystemRoot, though, because it's - # needed for anything that uses sockets, and seldom changes, and - # for SystemDrive because it's related. - # - # Weigh the impact carefully before adding other variables to this list. - import_env = [ 'SystemDrive', 'SystemRoot', 'TEMP', 'TMP' ] - for var in import_env: - v = os.environ.get(var) - if v: - env['ENV'][var] = v - - if 'COMSPEC' not in env['ENV']: - v = os.environ.get("COMSPEC") - if v: - env['ENV']['COMSPEC'] = v - - env.AppendENVPath('PATH', get_system_root() + '\System32') - - env['ENV']['PATHEXT'] = '.COM;.EXE;.BAT;.CMD' - env['OBJPREFIX'] = '' - env['OBJSUFFIX'] = '.obj' - env['SHOBJPREFIX'] = '$OBJPREFIX' - env['SHOBJSUFFIX'] = '$OBJSUFFIX' - env['PROGPREFIX'] = '' - env['PROGSUFFIX'] = '.exe' - env['LIBPREFIX'] = '' - env['LIBSUFFIX'] = '.lib' - env['SHLIBPREFIX'] = '' - env['SHLIBSUFFIX'] = '.dll' - env['LIBPREFIXES'] = [ '$LIBPREFIX' ] - env['LIBSUFFIXES'] = [ '$LIBSUFFIX' ] - env['PSPAWN'] = piped_spawn - env['SPAWN'] = spawn - env['SHELL'] = cmd_interp - env['TEMPFILE'] = TempFileMunge - env['TEMPFILEPREFIX'] = '@' - env['MAXLINELENGTH'] = 2048 - env['ESCAPE'] = escape - - env['HOST_OS'] = 'win32' - env['HOST_ARCH'] = get_architecture().arch - - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/SConf.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/SConf.py deleted file mode 100644 index 2ef4003..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/SConf.py +++ /dev/null @@ -1,1054 +0,0 @@ -"""SCons.SConf - -Autoconf-like configuration support. - -In other words, SConf allows to run tests on the build machine to detect -capabilities of system and do some things based on result: generate config -files, header files for C/C++, update variables in environment. - -Tests on the build system can detect if compiler sees header files, if -libraries are installed, if some command line options are supported etc. - -""" - -# -# Copyright (c) 2001 - 2015 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/SConf.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.compat - -import io -import os -import re -import sys -import traceback - -import SCons.Action -import SCons.Builder -import SCons.Errors -import SCons.Job -import SCons.Node.FS -import SCons.Taskmaster -import SCons.Util -import SCons.Warnings -import SCons.Conftest - -from SCons.Debug import Trace - -# Turn off the Conftest error logging -SCons.Conftest.LogInputFiles = 0 -SCons.Conftest.LogErrorMessages = 0 - -# Set -build_type = None -build_types = ['clean', 'help'] - -def SetBuildType(type): - global build_type - build_type = type - -# to be set, if we are in dry-run mode -dryrun = 0 - -AUTO=0 # use SCons dependency scanning for up-to-date checks -FORCE=1 # force all tests to be rebuilt -CACHE=2 # force all tests to be taken from cache (raise an error, if necessary) -cache_mode = AUTO - -def SetCacheMode(mode): - """Set the Configure cache mode. mode must be one of "auto", "force", - or "cache".""" - global cache_mode - if mode == "auto": - cache_mode = AUTO - elif mode == "force": - cache_mode = FORCE - elif mode == "cache": - cache_mode = CACHE - else: - raise ValueError("SCons.SConf.SetCacheMode: Unknown mode " + mode) - -progress_display = SCons.Util.display # will be overwritten by SCons.Script -def SetProgressDisplay(display): - """Set the progress display to use (called from SCons.Script)""" - global progress_display - progress_display = display - -SConfFS = None - -_ac_build_counter = 0 # incremented, whenever TryBuild is called -_ac_config_logs = {} # all config.log files created in this build -_ac_config_hs = {} # all config.h files created in this build -sconf_global = None # current sconf object - -def _createConfigH(target, source, env): - t = open(str(target[0]), "w") - defname = re.sub('[^A-Za-z0-9_]', '_', str(target[0]).upper()) - t.write("""#ifndef %(DEFNAME)s_SEEN -#define %(DEFNAME)s_SEEN - -""" % {'DEFNAME' : defname}) - t.write(source[0].get_contents()) - t.write(""" -#endif /* %(DEFNAME)s_SEEN */ -""" % {'DEFNAME' : defname}) - t.close() - -def _stringConfigH(target, source, env): - return "scons: Configure: creating " + str(target[0]) - - -def NeedConfigHBuilder(): - if len(_ac_config_hs) == 0: - return False - else: - return True - -def CreateConfigHBuilder(env): - """Called if necessary just before the building targets phase begins.""" - action = SCons.Action.Action(_createConfigH, - _stringConfigH) - sconfigHBld = SCons.Builder.Builder(action=action) - env.Append( BUILDERS={'SConfigHBuilder':sconfigHBld} ) - for k in _ac_config_hs.keys(): - env.SConfigHBuilder(k, env.Value(_ac_config_hs[k])) - - -class SConfWarning(SCons.Warnings.Warning): - pass -SCons.Warnings.enableWarningClass(SConfWarning) - -# some error definitions -class SConfError(SCons.Errors.UserError): - def __init__(self,msg): - SCons.Errors.UserError.__init__(self,msg) - -class ConfigureDryRunError(SConfError): - """Raised when a file or directory needs to be updated during a Configure - process, but the user requested a dry-run""" - def __init__(self,target): - if not isinstance(target, SCons.Node.FS.File): - msg = 'Cannot create configure directory "%s" within a dry-run.' % str(target) - else: - msg = 'Cannot update configure test "%s" within a dry-run.' % str(target) - SConfError.__init__(self,msg) - -class ConfigureCacheError(SConfError): - """Raised when a use explicitely requested the cache feature, but the test - is run the first time.""" - def __init__(self,target): - SConfError.__init__(self, '"%s" is not yet built and cache is forced.' % str(target)) - -# define actions for building text files -def _createSource( target, source, env ): - fd = open(str(target[0]), "w") - fd.write(source[0].get_contents()) - fd.close() -def _stringSource( target, source, env ): - return (str(target[0]) + ' <-\n |' + - source[0].get_contents().replace( '\n', "\n |" ) ) - -class SConfBuildInfo(SCons.Node.FS.FileBuildInfo): - """ - Special build info for targets of configure tests. Additional members - are result (did the builder succeed last time?) and string, which - contains messages of the original build phase. - """ - __slots__ = ('result', 'string') - - def __init__(self): - self.result = None # -> 0/None -> no error, != 0 error - self.string = None # the stdout / stderr output when building the target - - def set_build_result(self, result, string): - self.result = result - self.string = string - - -class Streamer(object): - """ - 'Sniffer' for a file-like writable object. Similar to the unix tool tee. - """ - def __init__(self, orig): - self.orig = orig - self.s = io.StringIO() - - def write(self, str): - if self.orig: - self.orig.write(str) - try: - self.s.write(str) - except TypeError as e: - # "unicode argument expected" bug in IOStream (python 2.x) - self.s.write(str.decode()) - - def writelines(self, lines): - for l in lines: - self.write(l + '\n') - - def getvalue(self): - """ - Return everything written to orig since the Streamer was created. - """ - return self.s.getvalue() - - def flush(self): - if self.orig: - self.orig.flush() - self.s.flush() - - -class SConfBuildTask(SCons.Taskmaster.AlwaysTask): - """ - This is almost the same as SCons.Script.BuildTask. Handles SConfErrors - correctly and knows about the current cache_mode. - """ - def display(self, message): - if sconf_global.logstream: - sconf_global.logstream.write("scons: Configure: " + message + "\n") - - def display_cached_string(self, bi): - """ - Logs the original builder messages, given the SConfBuildInfo instance - bi. - """ - if not isinstance(bi, SConfBuildInfo): - SCons.Warnings.warn(SConfWarning, - "The stored build information has an unexpected class: %s" % bi.__class__) - else: - self.display("The original builder output was:\n" + - (" |" + str(bi.string)).replace("\n", "\n |")) - - def failed(self): - # check, if the reason was a ConfigureDryRunError or a - # ConfigureCacheError and if yes, reraise the exception - exc_type = self.exc_info()[0] - if issubclass(exc_type, SConfError): - raise - elif issubclass(exc_type, SCons.Errors.BuildError): - # we ignore Build Errors (occurs, when a test doesn't pass) - # Clear the exception to prevent the contained traceback - # to build a reference cycle. - self.exc_clear() - else: - self.display('Caught exception while building "%s":\n' % - self.targets[0]) - try: - excepthook = sys.excepthook - except AttributeError: - # Earlier versions of Python don't have sys.excepthook... - def excepthook(type, value, tb): - traceback.print_tb(tb) - print type, value - excepthook(*self.exc_info()) - return SCons.Taskmaster.Task.failed(self) - - def collect_node_states(self): - # returns (is_up_to_date, cached_error, cachable) - # where is_up_to_date is 1, if the node(s) are up_to_date - # cached_error is 1, if the node(s) are up_to_date, but the - # build will fail - # cachable is 0, if some nodes are not in our cache - T = 0 - changed = False - cached_error = False - cachable = True - for t in self.targets: - if T: Trace('%s' % (t)) - bi = t.get_stored_info().binfo - if isinstance(bi, SConfBuildInfo): - if T: Trace(': SConfBuildInfo') - if cache_mode == CACHE: - t.set_state(SCons.Node.up_to_date) - if T: Trace(': set_state(up_to-date)') - else: - if T: Trace(': get_state() %s' % t.get_state()) - if T: Trace(': changed() %s' % t.changed()) - if (t.get_state() != SCons.Node.up_to_date and t.changed()): - changed = True - if T: Trace(': changed %s' % changed) - cached_error = cached_error or bi.result - else: - if T: Trace(': else') - # the node hasn't been built in a SConf context or doesn't - # exist - cachable = False - changed = ( t.get_state() != SCons.Node.up_to_date ) - if T: Trace(': changed %s' % changed) - if T: Trace('\n') - return (not changed, cached_error, cachable) - - def execute(self): - if not self.targets[0].has_builder(): - return - - sconf = sconf_global - - is_up_to_date, cached_error, cachable = self.collect_node_states() - - if cache_mode == CACHE and not cachable: - raise ConfigureCacheError(self.targets[0]) - elif cache_mode == FORCE: - is_up_to_date = 0 - - if cached_error and is_up_to_date: - self.display("Building \"%s\" failed in a previous run and all " - "its sources are up to date." % str(self.targets[0])) - binfo = self.targets[0].get_stored_info().binfo - self.display_cached_string(binfo) - raise SCons.Errors.BuildError # will be 'caught' in self.failed - elif is_up_to_date: - self.display("\"%s\" is up to date." % str(self.targets[0])) - binfo = self.targets[0].get_stored_info().binfo - self.display_cached_string(binfo) - elif dryrun: - raise ConfigureDryRunError(self.targets[0]) - else: - # note stdout and stderr are the same here - 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.func_code is not force_build.func_code: - env.Decider(force_build) - env['PSTDOUT'] = env['PSTDERR'] = s - try: - sconf.cached = 0 - self.targets[0].build() - finally: - sys.stdout = sys.stderr = env['PSTDOUT'] = \ - env['PSTDERR'] = sconf.logstream - except KeyboardInterrupt: - raise - except SystemExit: - exc_value = sys.exc_info()[1] - raise SCons.Errors.ExplicitExit(self.targets[0],exc_value.code) - except Exception, e: - for t in self.targets: - #binfo = t.get_binfo() - #binfo.__class__ = SConfBuildInfo - binfo = SConfBuildInfo() - binfo.merge(t.get_binfo()) - binfo.set_build_result(1, s.getvalue()) - sconsign_entry = SCons.SConsign.SConsignEntry() - sconsign_entry.binfo = binfo - #sconsign_entry.ninfo = self.get_ninfo() - # We'd like to do this as follows: - # t.store_info(binfo) - # However, we need to store it as an SConfBuildInfo - # object, and store_info() will turn it into a - # regular FileNodeInfo if the target is itself a - # regular File. - sconsign = t.dir.sconsign() - sconsign.set_entry(t.name, sconsign_entry) - sconsign.merge() - raise e - else: - for t in self.targets: - #binfo = t.get_binfo() - #binfo.__class__ = SConfBuildInfo - binfo = SConfBuildInfo() - binfo.merge(t.get_binfo()) - binfo.set_build_result(0, s.getvalue()) - sconsign_entry = SCons.SConsign.SConsignEntry() - sconsign_entry.binfo = binfo - #sconsign_entry.ninfo = self.get_ninfo() - # We'd like to do this as follows: - # t.store_info(binfo) - # However, we need to store it as an SConfBuildInfo - # object, and store_info() will turn it into a - # regular FileNodeInfo if the target is itself a - # regular File. - sconsign = t.dir.sconsign() - sconsign.set_entry(t.name, sconsign_entry) - sconsign.merge() - -class SConfBase(object): - """This is simply a class to represent a configure context. After - creating a SConf object, you can call any tests. After finished with your - tests, be sure to call the Finish() method, which returns the modified - environment. - Some words about caching: In most cases, it is not necessary to cache - Test results explicitely. Instead, we use the scons dependency checking - mechanism. For example, if one wants to compile a test program - (SConf.TryLink), the compiler is only called, if the program dependencies - have changed. However, if the program could not be compiled in a former - SConf run, we need to explicitely cache this error. - """ - - def __init__(self, env, custom_tests = {}, conf_dir='$CONFIGUREDIR', - log_file='$CONFIGURELOG', config_h = None, _depth = 0): - """Constructor. Pass additional tests in the custom_tests-dictinary, - e.g. custom_tests={'CheckPrivate':MyPrivateTest}, where MyPrivateTest - defines a custom test. - Note also the conf_dir and log_file arguments (you may want to - build tests in the VariantDir, not in the SourceDir) - """ - global SConfFS - 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 - self.logstream = None - self.lastTarget = None - self.depth = _depth - self.cached = 0 # will be set, if all test results are cached - - # add default tests - default_tests = { - 'CheckCC' : CheckCC, - 'CheckCXX' : CheckCXX, - 'CheckSHCC' : CheckSHCC, - 'CheckSHCXX' : CheckSHCXX, - 'CheckFunc' : CheckFunc, - 'CheckType' : CheckType, - 'CheckTypeSize' : CheckTypeSize, - 'CheckDeclaration' : CheckDeclaration, - 'CheckHeader' : CheckHeader, - 'CheckCHeader' : CheckCHeader, - 'CheckCXXHeader' : CheckCXXHeader, - 'CheckLib' : CheckLib, - 'CheckLibWithHeader' : CheckLibWithHeader, - } - self.AddTests(default_tests) - self.AddTests(custom_tests) - self.confdir = SConfFS.Dir(env.subst(conf_dir)) - if config_h is not None: - config_h = SConfFS.File(config_h) - self.config_h = config_h - self._startup() - - def Finish(self): - """Call this method after finished with your tests: - env = sconf.Finish() - """ - self._shutdown() - return self.env - - def Define(self, name, value = None, comment = None): - """ - Define a pre processor symbol name, with the optional given value in the - current config header. - - If value is None (default), then #define name is written. If value is not - none, then #define name value is written. - - comment is a string which will be put as a C comment in the - header, to explain the meaning of the value (appropriate C comments /* and - */ will be put automatically.""" - lines = [] - if comment: - comment_str = "/* %s */" % comment - lines.append(comment_str) - - if value is not None: - define_str = "#define %s %s" % (name, value) - else: - define_str = "#define %s" % name - lines.append(define_str) - lines.append('') - - self.config_h_text = self.config_h_text + '\n'.join(lines) - - def BuildNodes(self, nodes): - """ - Tries to build the given nodes immediately. Returns 1 on success, - 0 on error. - """ - if self.logstream is not None: - # override stdout / stderr to write in log file - oldStdout = sys.stdout - sys.stdout = self.logstream - oldStderr = sys.stderr - sys.stderr = self.logstream - - # the engine assumes the current path is the SConstruct directory ... - old_fs_dir = SConfFS.getcwd() - old_os_dir = os.getcwd() - SConfFS.chdir(SConfFS.Top, change_os_dir=1) - - # Because we take responsibility here for writing out our - # own .sconsign info (see SConfBuildTask.execute(), above), - # we override the store_info() method with a null place-holder - # so we really control how it gets written. - for n in nodes: - n.store_info = 0 - if not hasattr(n, 'attributes'): - n.attributes = SCons.Node.Node.Attrs() - n.attributes.keep_targetinfo = 1 - - ret = 1 - - try: - # ToDo: use user options for calc - save_max_drift = SConfFS.get_max_drift() - SConfFS.set_max_drift(0) - tm = SCons.Taskmaster.Taskmaster(nodes, SConfBuildTask) - # we don't want to build tests in parallel - jobs = SCons.Job.Jobs(1, tm ) - jobs.run() - for n in nodes: - state = n.get_state() - if (state != SCons.Node.executed and - state != SCons.Node.up_to_date): - # the node could not be built. we return 0 in this case - ret = 0 - finally: - SConfFS.set_max_drift(save_max_drift) - os.chdir(old_os_dir) - SConfFS.chdir(old_fs_dir, change_os_dir=0) - if self.logstream is not None: - # restore stdout / stderr - sys.stdout = oldStdout - sys.stderr = oldStderr - return ret - - def pspawn_wrapper(self, sh, escape, cmd, args, env): - """Wrapper function for handling piped spawns. - - This looks to the calling interface (in Action.py) like a "normal" - spawn, but associates the call with the PSPAWN variable from - the construction environment and with the streams to which we - want the output logged. This gets slid into the construction - environment as the SPAWN variable so Action.py doesn't have to - know or care whether it's spawning a piped command or not. - """ - return self.pspawn(sh, escape, cmd, args, env, self.logstream, self.logstream) - - - def TryBuild(self, builder, text = None, extension = ""): - """Low level TryBuild implementation. Normally you don't need to - call that - you can use TryCompile / TryLink / TryRun instead - """ - global _ac_build_counter - - # Make sure we have a PSPAWN value, and save the current - # SPAWN value. - try: - self.pspawn = self.env['PSPAWN'] - except KeyError: - raise SCons.Errors.UserError('Missing PSPAWN construction variable.') - try: - save_spawn = self.env['SPAWN'] - except KeyError: - raise SCons.Errors.UserError('Missing SPAWN construction variable.') - - nodesToBeBuilt = [] - - f = "conftest_" + str(_ac_build_counter) - pref = self.env.subst( builder.builder.prefix ) - suff = self.env.subst( builder.builder.suffix ) - target = self.confdir.File(pref + f + suff) - - try: - # Slide our wrapper into the construction environment as - # the SPAWN function. - self.env['SPAWN'] = self.pspawn_wrapper - sourcetext = self.env.Value(text) - - if text is not None: - textFile = self.confdir.File(f + extension) - textFileNode = self.env.SConfSourceBuilder(target=textFile, - source=sourcetext) - nodesToBeBuilt.extend(textFileNode) - source = textFileNode - else: - source = None - - nodes = builder(target = target, source = source) - if not SCons.Util.is_List(nodes): - nodes = [nodes] - nodesToBeBuilt.extend(nodes) - result = self.BuildNodes(nodesToBeBuilt) - - finally: - self.env['SPAWN'] = save_spawn - - _ac_build_counter = _ac_build_counter + 1 - if result: - self.lastTarget = nodes[0] - else: - self.lastTarget = None - - return result - - def TryAction(self, action, text = None, extension = ""): - """Tries to execute the given action with optional source file - contents and optional source file extension , - Returns the status (0 : failed, 1 : ok) and the contents of the - output file. - """ - builder = SCons.Builder.Builder(action=action) - self.env.Append( BUILDERS = {'SConfActionBuilder' : builder} ) - ok = self.TryBuild(self.env.SConfActionBuilder, text, extension) - del self.env['BUILDERS']['SConfActionBuilder'] - if ok: - outputStr = self.lastTarget.get_contents() - return (1, outputStr) - return (0, "") - - def TryCompile( self, text, extension): - """Compiles the program given in text to an env.Object, using extension - as file extension (e.g. '.c'). Returns 1, if compilation was - successful, 0 otherwise. The target is saved in self.lastTarget (for - further processing). - """ - return self.TryBuild(self.env.Object, text, extension) - - def TryLink( self, text, extension ): - """Compiles the program given in text to an executable env.Program, - using extension as file extension (e.g. '.c'). Returns 1, if - compilation was successful, 0 otherwise. The target is saved in - self.lastTarget (for further processing). - """ - return self.TryBuild(self.env.Program, text, extension ) - - def TryRun(self, text, extension ): - """Compiles and runs the program given in text, using extension - as file extension (e.g. '.c'). Returns (1, outputStr) on success, - (0, '') otherwise. The target (a file containing the program's stdout) - is saved in self.lastTarget (for further processing). - """ - ok = self.TryLink(text, extension) - if( ok ): - prog = self.lastTarget - pname = prog.get_internal_path() - output = self.confdir.File(os.path.basename(pname)+'.out') - node = self.env.Command(output, prog, [ [ pname, ">", "${TARGET}"] ]) - ok = self.BuildNodes(node) - if ok: - outputStr = output.get_contents() - return( 1, outputStr) - return (0, "") - - class TestWrapper(object): - """A wrapper around Tests (to ensure sanity)""" - def __init__(self, test, sconf): - self.test = test - self.sconf = sconf - def __call__(self, *args, **kw): - if not self.sconf.active: - raise SCons.Errors.UserError - context = CheckContext(self.sconf) - ret = self.test(context, *args, **kw) - if self.sconf.config_h is not None: - self.sconf.config_h_text = self.sconf.config_h_text + context.config_h - context.Result("error: no result") - return ret - - def AddTest(self, test_name, test_instance): - """Adds test_class to this SConf instance. It can be called with - self.test_name(...)""" - setattr(self, test_name, SConfBase.TestWrapper(test_instance, self)) - - def AddTests(self, tests): - """Adds all the tests given in the tests dictionary to this SConf - instance - """ - for name in tests.keys(): - self.AddTest(name, tests[name]) - - def _createDir( self, node ): - dirName = str(node) - if dryrun: - if not os.path.isdir( dirName ): - raise ConfigureDryRunError(dirName) - else: - if not os.path.isdir( dirName ): - os.makedirs( dirName ) - - def _startup(self): - """Private method. Set up logstream, and set the environment - variables necessary for a piped build - """ - global _ac_config_logs - global sconf_global - global SConfFS - - self.lastEnvFs = self.env.fs - self.env.fs = SConfFS - self._createDir(self.confdir) - self.confdir.up().add_ignore( [self.confdir] ) - - if self.logfile is not None and not dryrun: - # truncate logfile, if SConf.Configure is called for the first time - # in a build - if self.logfile in _ac_config_logs: - log_mode = "a" - else: - _ac_config_logs[self.logfile] = None - log_mode = "w" - fp = open(str(self.logfile), log_mode) - self.logstream = SCons.Util.Unbuffered(fp) - # logfile may stay in a build directory, so we tell - # the build system not to override it with a eventually - # existing file with the same name in the source directory - self.logfile.dir.add_ignore( [self.logfile] ) - - tb = traceback.extract_stack()[-3-self.depth] - old_fs_dir = SConfFS.getcwd() - SConfFS.chdir(SConfFS.Top, change_os_dir=0) - self.logstream.write('file %s,line %d:\n\tConfigure(confdir = %s)\n' % - (tb[0], tb[1], str(self.confdir)) ) - SConfFS.chdir(old_fs_dir) - else: - self.logstream = None - # we use a special builder to create source files from TEXT - action = SCons.Action.Action(_createSource, - _stringSource) - sconfSrcBld = SCons.Builder.Builder(action=action) - self.env.Append( BUILDERS={'SConfSourceBuilder':sconfSrcBld} ) - self.config_h_text = _ac_config_hs.get(self.config_h, "") - self.active = 1 - # only one SConf instance should be active at a time ... - sconf_global = self - - def _shutdown(self): - """Private method. Reset to non-piped spawn""" - global sconf_global, _ac_config_hs - - if not self.active: - raise SCons.Errors.UserError("Finish may be called only once!") - if self.logstream is not None and not dryrun: - 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 ) - self.active = 0 - sconf_global = None - if not self.config_h is None: - _ac_config_hs[self.config_h] = self.config_h_text - self.env.fs = self.lastEnvFs - -class CheckContext(object): - """Provides a context for configure tests. Defines how a test writes to the - screen and log file. - - 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) - - Often, myWeirdTestFunction will be one of - context.TryCompile/context.TryLink/context.TryRun. The results of - those are cached, for they are only rebuild, if the dependencies have - changed. - """ - - def __init__(self, sconf): - """Constructor. Pass the corresponding SConf instance.""" - self.sconf = sconf - self.did_show_result = 0 - - # for Conftest.py: - self.vardict = {} - self.havedict = {} - self.headerfilename = None - self.config_h = "" # config_h text will be stored here - # we don't regenerate the config.h file after each test. That means, - # that tests won't be able to include the config.h file, and so - # they can't do an #ifdef HAVE_XXX_H. This shouldn't be a major - # issue, though. If it turns out, that we need to include config.h - # in tests, we must ensure, that the dependencies are worked out - # correctly. Note that we can't use Conftest.py's support for config.h, - # cause we will need to specify a builder for the config.h file ... - - def Message(self, text): - """Inform about what we are doing right now, e.g. - 'Checking for SOMETHING ... ' - """ - self.Display(text) - self.sconf.cached = 1 - self.did_show_result = 0 - - def Result(self, res): - """Inform about the result of the test. If res is not a string, displays - 'yes' or 'no' depending on whether res is evaluated as true or false. - The result is only displayed when self.did_show_result is not set. - """ - if isinstance(res, str): - text = res - elif res: - text = "yes" - else: - text = "no" - - if self.did_show_result == 0: - # Didn't show result yet, do it now. - self.Display(text + "\n") - self.did_show_result = 1 - - def TryBuild(self, *args, **kw): - return self.sconf.TryBuild(*args, **kw) - - def TryAction(self, *args, **kw): - return self.sconf.TryAction(*args, **kw) - - def TryCompile(self, *args, **kw): - return self.sconf.TryCompile(*args, **kw) - - def TryLink(self, *args, **kw): - return self.sconf.TryLink(*args, **kw) - - def TryRun(self, *args, **kw): - return self.sconf.TryRun(*args, **kw) - - def __getattr__( self, attr ): - if( attr == 'env' ): - return self.sconf.env - elif( attr == 'lastTarget' ): - return self.sconf.lastTarget - else: - raise AttributeError("CheckContext instance has no attribute '%s'" % attr) - - #### Stuff used by Conftest.py (look there for explanations). - - def BuildProg(self, text, ext): - self.sconf.cached = 1 - # TODO: should use self.vardict for $CC, $CPPFLAGS, etc. - return not self.TryBuild(self.env.Program, text, ext) - - def CompileProg(self, text, ext): - self.sconf.cached = 1 - # TODO: should use self.vardict for $CC, $CPPFLAGS, etc. - return not self.TryBuild(self.env.Object, text, ext) - - def CompileSharedObject(self, text, ext): - self.sconf.cached = 1 - # TODO: should use self.vardict for $SHCC, $CPPFLAGS, etc. - return not self.TryBuild(self.env.SharedObject, text, ext) - - def RunProg(self, text, ext): - self.sconf.cached = 1 - # TODO: should use self.vardict for $CC, $CPPFLAGS, etc. - st, out = self.TryRun(text, ext) - return not st, out - - def AppendLIBS(self, lib_name_list): - oldLIBS = self.env.get( 'LIBS', [] ) - self.env.Append(LIBS = lib_name_list) - return oldLIBS - - def PrependLIBS(self, lib_name_list): - oldLIBS = self.env.get( 'LIBS', [] ) - self.env.Prepend(LIBS = lib_name_list) - return oldLIBS - - def SetLIBS(self, val): - oldLIBS = self.env.get( 'LIBS', [] ) - self.env.Replace(LIBS = val) - return oldLIBS - - def Display(self, msg): - if self.sconf.cached: - # We assume that Display is called twice for each test here - # once for the Checking for ... message and once for the result. - # The self.sconf.cached flag can only be set between those calls - msg = "(cached) " + msg - self.sconf.cached = 0 - progress_display(msg, append_newline=0) - self.Log("scons: Configure: " + msg + "\n") - - def Log(self, msg): - if self.sconf.logstream is not None: - self.sconf.logstream.write(msg) - - #### End of stuff used by Conftest.py. - - -def SConf(*args, **kw): - if kw.get(build_type, True): - kw['_depth'] = kw.get('_depth', 0) + 1 - for bt in build_types: - try: - del kw[bt] - except KeyError: - pass - return SConfBase(*args, **kw) - else: - return SCons.Util.Null() - - -def CheckFunc(context, function_name, header = None, language = None): - res = SCons.Conftest.CheckFunc(context, function_name, header = header, language = language) - context.did_show_result = 1 - return not res - -def CheckType(context, type_name, includes = "", language = None): - res = SCons.Conftest.CheckType(context, type_name, - header = includes, language = language) - context.did_show_result = 1 - return not res - -def CheckTypeSize(context, type_name, includes = "", language = None, expect = None): - res = SCons.Conftest.CheckTypeSize(context, type_name, - header = includes, language = language, - expect = expect) - context.did_show_result = 1 - return res - -def CheckDeclaration(context, declaration, includes = "", language = None): - res = SCons.Conftest.CheckDeclaration(context, declaration, - includes = includes, - language = language) - context.did_show_result = 1 - return not res - -def createIncludesFromHeaders(headers, leaveLast, include_quotes = '""'): - # used by CheckHeader and CheckLibWithHeader to produce C - #include - # statements from the specified header (list) - if not SCons.Util.is_List(headers): - headers = [headers] - l = [] - if leaveLast: - lastHeader = headers[-1] - headers = headers[:-1] - else: - lastHeader = None - for s in headers: - l.append("#include %s%s%s\n" - % (include_quotes[0], s, include_quotes[1])) - return ''.join(l), lastHeader - -def CheckHeader(context, header, include_quotes = '<>', language = None): - """ - A test for a C or C++ header file. - """ - prog_prefix, hdr_to_check = \ - createIncludesFromHeaders(header, 1, include_quotes) - res = SCons.Conftest.CheckHeader(context, hdr_to_check, prog_prefix, - language = language, - include_quotes = include_quotes) - context.did_show_result = 1 - return not res - -def CheckCC(context): - res = SCons.Conftest.CheckCC(context) - context.did_show_result = 1 - return not res - -def CheckCXX(context): - res = SCons.Conftest.CheckCXX(context) - context.did_show_result = 1 - return not res - -def CheckSHCC(context): - res = SCons.Conftest.CheckSHCC(context) - context.did_show_result = 1 - return not res - -def CheckSHCXX(context): - res = SCons.Conftest.CheckSHCXX(context) - context.did_show_result = 1 - return not res - -# Bram: Make this function obsolete? CheckHeader() is more generic. - -def CheckCHeader(context, header, include_quotes = '""'): - """ - A test for a C header file. - """ - return CheckHeader(context, header, include_quotes, language = "C") - - -# Bram: Make this function obsolete? CheckHeader() is more generic. - -def CheckCXXHeader(context, header, include_quotes = '""'): - """ - A test for a C++ header file. - """ - return CheckHeader(context, header, include_quotes, language = "C++") - - -def CheckLib(context, library = None, symbol = "main", - header = None, language = None, autoadd = 1): - """ - A test for a library. See also CheckLibWithHeader. - Note that library may also be None to test whether the given symbol - compiles without flags. - """ - - if library == []: - library = [None] - - if not SCons.Util.is_List(library): - library = [library] - - # ToDo: accept path for the library - res = SCons.Conftest.CheckLib(context, library, symbol, header = header, - language = language, autoadd = autoadd) - context.did_show_result = 1 - return not res - -# XXX -# Bram: Can only include one header and can't use #ifdef HAVE_HEADER_H. - -def CheckLibWithHeader(context, libs, header, language, - call = None, autoadd = 1): - # ToDo: accept path for library. Support system header files. - """ - Another (more sophisticated) test for a library. - Checks, if library and header is available for language (may be 'C' - or 'CXX'). Call maybe be a valid expression _with_ a trailing ';'. - As in CheckLib, we support library=None, to test if the call compiles - without extra link flags. - """ - prog_prefix, dummy = \ - createIncludesFromHeaders(header, 0) - if libs == []: - libs = [None] - - if not SCons.Util.is_List(libs): - libs = [libs] - - res = SCons.Conftest.CheckLib(context, libs, None, prog_prefix, - call = call, language = language, autoadd = autoadd) - context.did_show_result = 1 - return not res - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/SConsign.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/SConsign.py deleted file mode 100644 index e31a3eb..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/SConsign.py +++ /dev/null @@ -1,413 +0,0 @@ -"""SCons.SConsign - -Writing and reading information to the .sconsign file or files. - -""" - -# -# Copyright (c) 2001 - 2015 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/SConsign.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.compat - -import os -# compat layer imports "cPickle" for us if it's available. -import pickle - -import SCons.dblite -import SCons.Warnings - -def corrupt_dblite_warning(filename): - SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, - "Ignoring corrupt .sconsign file: %s"%filename) - -SCons.dblite.ignore_corrupt_dbfiles = 1 -SCons.dblite.corruption_warning = corrupt_dblite_warning - -#XXX Get rid of the global array so this becomes re-entrant. -sig_files = [] - -# Info for the database SConsign implementation (now the default): -# "DataBase" is a dictionary that maps top-level SConstruct directories -# to open database handles. -# "DB_Module" is the Python database module to create the handles. -# "DB_Name" is the base name of the database file (minus any -# extension the underlying DB module will add). -DataBase = {} -DB_Module = SCons.dblite -DB_Name = ".sconsign" -DB_sync_list = [] - -def Get_DataBase(dir): - global DataBase, DB_Module, DB_Name - top = dir.fs.Top - if not os.path.isabs(DB_Name) and top.repositories: - mode = "c" - for d in [top] + top.repositories: - if dir.is_under(d): - try: - return DataBase[d], mode - except KeyError: - path = d.entry_abspath(DB_Name) - try: db = DataBase[d] = DB_Module.open(path, mode) - except (IOError, OSError): pass - else: - if mode != "r": - DB_sync_list.append(db) - return db, mode - mode = "r" - try: - return DataBase[top], "c" - except KeyError: - db = DataBase[top] = DB_Module.open(DB_Name, "c") - DB_sync_list.append(db) - return db, "c" - except TypeError: - print "DataBase =", DataBase - raise - -def Reset(): - """Reset global state. Used by unit tests that end up using - SConsign multiple times to get a clean slate for each test.""" - global sig_files, DB_sync_list - sig_files = [] - DB_sync_list = [] - -normcase = os.path.normcase - -def write(): - global sig_files - for sig_file in sig_files: - sig_file.write(sync=0) - for db in DB_sync_list: - try: - syncmethod = db.sync - except AttributeError: - pass # Not all dbm modules have sync() methods. - else: - syncmethod() - try: - closemethod = db.close - except AttributeError: - pass # Not all dbm modules have close() methods. - else: - closemethod() - -class SConsignEntry(object): - """ - Wrapper class for the generic entry in a .sconsign file. - The Node subclass populates it with attributes as it pleases. - - XXX As coded below, we do expect a '.binfo' attribute to be added, - but we'll probably generalize this in the next refactorings. - """ - __slots__ = ("binfo", "ninfo", "__weakref__") - current_version_id = 2 - - def __init__(self): - # Create an object attribute from the class attribute so it ends up - # in the pickled data in the .sconsign file. - #_version_id = self.current_version_id - pass - - def convert_to_sconsign(self): - self.binfo.convert_to_sconsign() - - def convert_from_sconsign(self, dir, name): - self.binfo.convert_from_sconsign(dir, name) - - def __getstate__(self): - state = getattr(self, '__dict__', {}).copy() - for obj in type(self).mro(): - for name in getattr(obj,'__slots__',()): - if hasattr(self, name): - state[name] = getattr(self, name) - - state['_version_id'] = self.current_version_id - try: - del state['__weakref__'] - except KeyError: - pass - return state - - def __setstate__(self, state): - for key, value in state.items(): - if key not in ('_version_id','__weakref__'): - setattr(self, key, value) - -class Base(object): - """ - This is the controlling class for the signatures for the collection of - entries associated with a specific directory. The actual directory - association will be maintained by a subclass that is specific to - the underlying storage method. This class provides a common set of - methods for fetching and storing the individual bits of information - that make up signature entry. - """ - def __init__(self): - self.entries = {} - self.dirty = False - self.to_be_merged = {} - - def get_entry(self, filename): - """ - Fetch the specified entry attribute. - """ - return self.entries[filename] - - def set_entry(self, filename, obj): - """ - Set the entry. - """ - self.entries[filename] = obj - self.dirty = True - - def do_not_set_entry(self, filename, obj): - pass - - def store_info(self, filename, node): - entry = node.get_stored_info() - entry.binfo.merge(node.get_binfo()) - self.to_be_merged[filename] = node - self.dirty = True - - def do_not_store_info(self, filename, node): - pass - - def merge(self): - for key, node in self.to_be_merged.items(): - entry = node.get_stored_info() - try: - ninfo = entry.ninfo - except AttributeError: - # This happens with SConf Nodes, because the configuration - # subsystem takes direct control over how the build decision - # is made and its information stored. - pass - else: - ninfo.merge(node.get_ninfo()) - self.entries[key] = entry - self.to_be_merged = {} - -class DB(Base): - """ - A Base subclass that reads and writes signature information - from a global .sconsign.db* file--the actual file suffix is - determined by the database module. - """ - def __init__(self, dir): - Base.__init__(self) - - self.dir = dir - - db, mode = Get_DataBase(dir) - - # Read using the path relative to the top of the Repository - # (self.dir.tpath) from which we're fetching the signature - # information. - path = normcase(dir.get_tpath()) - try: - rawentries = db[path] - except KeyError: - pass - else: - try: - self.entries = pickle.loads(rawentries) - if not isinstance(self.entries, dict): - self.entries = {} - raise TypeError - except KeyboardInterrupt: - raise - except Exception, e: - SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, - "Ignoring corrupt sconsign entry : %s (%s)\n"%(self.dir.get_tpath(), e)) - for key, entry in self.entries.items(): - entry.convert_from_sconsign(dir, key) - - if mode == "r": - # This directory is actually under a repository, which means - # likely they're reaching in directly for a dependency on - # a file there. Don't actually set any entry info, so we - # won't try to write to that .sconsign.dblite file. - self.set_entry = self.do_not_set_entry - self.store_info = self.do_not_store_info - - global sig_files - sig_files.append(self) - - def write(self, sync=1): - if not self.dirty: - return - - self.merge() - - db, mode = Get_DataBase(self.dir) - - # Write using the path relative to the top of the SConstruct - # directory (self.dir.path), not relative to the top of - # the Repository; we only write to our own .sconsign file, - # not to .sconsign files in Repositories. - path = normcase(self.dir.get_internal_path()) - for key, entry in self.entries.items(): - entry.convert_to_sconsign() - db[path] = pickle.dumps(self.entries, 1) - - if sync: - try: - syncmethod = db.sync - except AttributeError: - # Not all anydbm modules have sync() methods. - pass - else: - syncmethod() - -class Dir(Base): - def __init__(self, fp=None, dir=None): - """ - fp - file pointer to read entries from - """ - Base.__init__(self) - - if not fp: - return - - self.entries = pickle.load(fp) - if not isinstance(self.entries, dict): - self.entries = {} - raise TypeError - - if dir: - for key, entry in self.entries.items(): - entry.convert_from_sconsign(dir, key) - -class DirFile(Dir): - """ - Encapsulates reading and writing a per-directory .sconsign file. - """ - def __init__(self, dir): - """ - dir - the directory for the file - """ - - self.dir = dir - self.sconsign = os.path.join(dir.get_internal_path(), '.sconsign') - - try: - fp = open(self.sconsign, 'rb') - except IOError: - fp = None - - try: - Dir.__init__(self, fp, dir) - except KeyboardInterrupt: - raise - except: - SCons.Warnings.warn(SCons.Warnings.CorruptSConsignWarning, - "Ignoring corrupt .sconsign file: %s"%self.sconsign) - - global sig_files - sig_files.append(self) - - def write(self, sync=1): - """ - Write the .sconsign file to disk. - - Try to write to a temporary file first, and rename it if we - succeed. If we can't write to the temporary file, it's - probably because the directory isn't writable (and if so, - how did we build anything in this directory, anyway?), so - try to write directly to the .sconsign file as a backup. - If we can't rename, try to copy the temporary contents back - to the .sconsign file. Either way, always try to remove - the temporary file at the end. - """ - if not self.dirty: - return - - self.merge() - - temp = os.path.join(self.dir.get_internal_path(), '.scons%d' % os.getpid()) - try: - file = open(temp, 'wb') - fname = temp - except IOError: - try: - file = open(self.sconsign, 'wb') - fname = self.sconsign - except IOError: - return - for key, entry in self.entries.items(): - entry.convert_to_sconsign() - pickle.dump(self.entries, file, 1) - file.close() - if fname != self.sconsign: - try: - mode = os.stat(self.sconsign)[0] - os.chmod(self.sconsign, 0666) - os.unlink(self.sconsign) - except (IOError, OSError): - # Try to carry on in the face of either OSError - # (things like permission issues) or IOError (disk - # or network issues). If there's a really dangerous - # issue, it should get re-raised by the calls below. - pass - try: - os.rename(fname, self.sconsign) - except OSError: - # An OSError failure to rename may indicate something - # like the directory has no write permission, but - # the .sconsign file itself might still be writable, - # so try writing on top of it directly. An IOError - # 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()) - os.chmod(self.sconsign, mode) - try: - os.unlink(temp) - except (IOError, OSError): - pass - -ForDirectory = DB - -def File(name, dbm_module=None): - """ - Arrange for all signatures to be stored in a global .sconsign.db* - file. - """ - global ForDirectory, DB_Name, DB_Module - if name is None: - ForDirectory = DirFile - DB_Module = None - else: - ForDirectory = DB - DB_Name = name - if not dbm_module is None: - DB_Module = dbm_module - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/C.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/C.py deleted file mode 100644 index 33e1145..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/C.py +++ /dev/null @@ -1,132 +0,0 @@ -"""SCons.Scanner.C - -This module implements the depenency scanner for C/C++ code. - -""" - -# -# Copyright (c) 2001 - 2015 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/Scanner/C.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.Node.FS -import SCons.Scanner -import SCons.Util - -import SCons.cpp - -class SConsCPPScanner(SCons.cpp.PreProcessor): - """ - SCons-specific subclass of the cpp.py module's processing. - - We subclass this so that: 1) we can deal with files represented - by Nodes, not strings; 2) we can keep track of the files that are - missing. - """ - def __init__(self, *args, **kw): - SCons.cpp.PreProcessor.__init__(self, *args, **kw) - self.missing = [] - def initialize_result(self, fname): - self.result = SCons.Util.UniqueList([fname]) - def finalize_result(self, fname): - return self.result[1:] - def find_include_file(self, t): - keyword, quote, fname = t - result = SCons.Node.FS.find_file(fname, self.searchpath[quote]) - if not result: - self.missing.append((fname, self.current_file)) - return result - def read_file(self, file): - try: - fp = open(str(file.rfile())) - except EnvironmentError, e: - self.missing.append((file, self.current_file)) - return '' - else: - return fp.read() - -def dictify_CPPDEFINES(env): - cppdefines = env.get('CPPDEFINES', {}) - if cppdefines is None: - return {} - if SCons.Util.is_Sequence(cppdefines): - result = {} - for c in cppdefines: - if SCons.Util.is_Sequence(c): - result[c[0]] = c[1] - else: - result[c] = None - return result - if not SCons.Util.is_Dict(cppdefines): - return {cppdefines : None} - return cppdefines - -class SConsCPPScannerWrapper(object): - """ - The SCons wrapper around a cpp.py scanner. - - This is the actual glue between the calling conventions of generic - SCons scanners, and the (subclass of) cpp.py class that knows how - to look for #include lines with reasonably real C-preprocessor-like - evaluation of #if/#ifdef/#else/#elif lines. - """ - def __init__(self, name, variable): - self.name = name - self.path = SCons.Scanner.FindPathDirs(variable) - def __call__(self, node, env, path = ()): - cpp = SConsCPPScanner(current = node.get_dir(), - cpppath = path, - dict = dictify_CPPDEFINES(env)) - result = cpp(node) - for included, includer in cpp.missing: - fmt = "No dependency generated for file: %s (included from: %s) -- file not found" - SCons.Warnings.warn(SCons.Warnings.DependencyWarning, - fmt % (included, includer)) - return result - - def recurse_nodes(self, nodes): - return nodes - def select(self, node): - return self - -def CScanner(): - """Return a prototype Scanner instance for scanning source files - that use the C pre-processor""" - - # Here's how we would (or might) use the CPP scanner code above that - # knows how to evaluate #if/#ifdef/#else/#elif lines when searching - # for #includes. This is commented out for now until we add the - # right configurability to let users pick between the scanners. - #return SConsCPPScannerWrapper("CScanner", "CPPPATH") - - cs = SCons.Scanner.ClassicCPP("CScanner", - "$CPPSUFFIXES", - "CPPPATH", - '^[ \t]*#[ \t]*(?:include|import)[ \t]*(<|")([^>"]+)(>|")') - return cs - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/D.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/D.py deleted file mode 100644 index 2c51a09..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/D.py +++ /dev/null @@ -1,73 +0,0 @@ -"""SCons.Scanner.D - -Scanner for the Digital Mars "D" programming language. - -Coded by Andy Friesen -17 Nov 2003 - -""" - -# -# Copyright (c) 2001 - 2015 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/Scanner/D.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import re - -import SCons.Scanner - -def DScanner(): - """Return a prototype Scanner instance for scanning D source files""" - ds = D() - return ds - -class D(SCons.Scanner.Classic): - def __init__ (self): - SCons.Scanner.Classic.__init__ (self, - name = "DScanner", - suffixes = '$DSUFFIXES', - path_variable = 'DPATH', - regex = 'import\s+(?:[a-zA-Z0-9_.]+)\s*(?:,\s*(?:[a-zA-Z0-9_.]+)\s*)*;') - - self.cre2 = re.compile ('(?:import\s)?\s*([a-zA-Z0-9_.]+)\s*(?:,|;)', re.M) - - def find_include(self, include, source_dir, path): - # translate dots (package separators) to slashes - inc = include.replace('.', '/') - - i = SCons.Node.FS.find_file(inc + '.d', (source_dir,) + path) - if i is None: - i = SCons.Node.FS.find_file (inc + '.di', (source_dir,) + path) - return i, include - - def find_include_names(self, node): - includes = [] - for i in self.cre.findall(node.get_text_contents()): - includes = includes + self.cre2.findall(i) - return includes - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/Dir.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/Dir.py deleted file mode 100644 index 7565423..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/Dir.py +++ /dev/null @@ -1,109 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/Scanner/Dir.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.Node.FS -import SCons.Scanner - -def only_dirs(nodes): - is_Dir = lambda n: isinstance(n.disambiguate(), SCons.Node.FS.Dir) - return list(filter(is_Dir, nodes)) - -def DirScanner(**kw): - """Return a prototype Scanner instance for scanning - directories for on-disk files""" - kw['node_factory'] = SCons.Node.FS.Entry - kw['recursive'] = only_dirs - return SCons.Scanner.Base(scan_on_disk, "DirScanner", **kw) - -def DirEntryScanner(**kw): - """Return a prototype Scanner instance for "scanning" - directory Nodes for their in-memory entries""" - kw['node_factory'] = SCons.Node.FS.Entry - kw['recursive'] = None - return SCons.Scanner.Base(scan_in_memory, "DirEntryScanner", **kw) - -skip_entry = {} - -skip_entry_list = [ - '.', - '..', - '.sconsign', - # Used by the native dblite.py module. - '.sconsign.dblite', - # Used by dbm and dumbdbm. - '.sconsign.dir', - # Used by dbm. - '.sconsign.pag', - # Used by dumbdbm. - '.sconsign.dat', - '.sconsign.bak', - # Used by some dbm emulations using Berkeley DB. - '.sconsign.db', -] - -for skip in skip_entry_list: - skip_entry[skip] = 1 - skip_entry[SCons.Node.FS._my_normcase(skip)] = 1 - -do_not_scan = lambda k: k not in skip_entry - -def scan_on_disk(node, env, path=()): - """ - Scans a directory for on-disk files and directories therein. - - Looking up the entries will add these to the in-memory Node tree - representation of the file system, so all we have to do is just - that and then call the in-memory scanning function. - """ - try: - flist = node.fs.listdir(node.get_abspath()) - except (IOError, OSError): - return [] - e = node.Entry - for f in filter(do_not_scan, flist): - # Add ./ to the beginning of the file name so if it begins with a - # '#' we don't look it up relative to the top-level directory. - e('./' + f) - return scan_in_memory(node, env, path) - -def scan_in_memory(node, env, path=()): - """ - "Scans" a Node.FS.Dir for its in-memory entries. - """ - try: - entries = node.entries - except AttributeError: - # It's not a Node.FS.Dir (or doesn't look enough like one for - # our purposes), which can happen if a target list containing - # mixed Node types (Dirs and Files, for example) has a Dir as - # the first entry. - return [] - entry_list = sorted(filter(do_not_scan, list(entries.keys()))) - return [entries[n] for n in entry_list] - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/Fortran.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/Fortran.py deleted file mode 100644 index a1f3927..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/Fortran.py +++ /dev/null @@ -1,316 +0,0 @@ -"""SCons.Scanner.Fortran - -This module implements the dependency scanner for Fortran code. - -""" - -# -# Copyright (c) 2001 - 2015 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/Scanner/Fortran.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import re - -import SCons.Node -import SCons.Node.FS -import SCons.Scanner -import SCons.Util -import SCons.Warnings - -class F90Scanner(SCons.Scanner.Classic): - """ - A Classic Scanner subclass for Fortran source files which takes - into account both USE and INCLUDE statements. This scanner will - work for both F77 and F90 (and beyond) compilers. - - Currently, this scanner assumes that the include files do not contain - USE statements. To enable the ability to deal with USE statements - in include files, add logic right after the module names are found - to loop over each include file, search for and locate each USE - statement, and append each module name to the list of dependencies. - Caching the search results in a common dictionary somewhere so that - the same include file is not searched multiple times would be a - smart thing to do. - """ - - def __init__(self, name, suffixes, path_variable, - use_regex, incl_regex, def_regex, *args, **kw): - - self.cre_use = re.compile(use_regex, re.M) - self.cre_incl = re.compile(incl_regex, re.M) - self.cre_def = re.compile(def_regex, re.M) - - def _scan(node, env, path, self=self): - node = node.rfile() - - if not node.exists(): - return [] - - return self.scan(node, env, path) - - kw['function'] = _scan - kw['path_function'] = SCons.Scanner.FindPathDirs(path_variable) - kw['recursive'] = 1 - kw['skeys'] = suffixes - kw['name'] = name - - SCons.Scanner.Current.__init__(self, *args, **kw) - - def scan(self, node, env, path=()): - - # cache the includes list in node so we only scan it once: - if node.includes != None: - mods_and_includes = node.includes - else: - # retrieve all included filenames - includes = self.cre_incl.findall(node.get_text_contents()) - # retrieve all USE'd module names - modules = self.cre_use.findall(node.get_text_contents()) - # retrieve all defined module names - defmodules = self.cre_def.findall(node.get_text_contents()) - - # Remove all USE'd module names that are defined in the same file - # (case-insensitively) - d = {} - for m in defmodules: - d[m.lower()] = 1 - modules = [m for m in modules if m.lower() not in d] - - # Convert module name to a .mod filename - suffix = env.subst('$FORTRANMODSUFFIX') - modules = [x.lower() + suffix for x in modules] - # Remove unique items from the list - mods_and_includes = SCons.Util.unique(includes+modules) - node.includes = mods_and_includes - - # This is a hand-coded DSU (decorate-sort-undecorate, or - # Schwartzian transform) pattern. The sort key is the raw name - # of the file as specifed on the USE or INCLUDE line, which lets - # us keep the sort order constant regardless of whether the file - # is actually found in a Repository or locally. - nodes = [] - source_dir = node.get_dir() - if callable(path): - path = path() - for dep in mods_and_includes: - n, i = self.find_include(dep, source_dir, path) - - if n is None: - SCons.Warnings.warn(SCons.Warnings.DependencyWarning, - "No dependency generated for file: %s (referenced by: %s) -- file not found" % (i, node)) - else: - sortkey = self.sort_key(dep) - nodes.append((sortkey, n)) - - return [pair[1] for pair in sorted(nodes)] - -def FortranScan(path_variable="FORTRANPATH"): - """Return a prototype Scanner instance for scanning source files - for Fortran USE & INCLUDE statements""" - -# The USE statement regex matches the following: -# -# USE module_name -# USE :: module_name -# USE, INTRINSIC :: module_name -# USE, NON_INTRINSIC :: module_name -# -# Limitations -# -# -- While the regex can handle multiple USE statements on one line, -# it cannot properly handle them if they are commented out. -# In either of the following cases: -# -# ! USE mod_a ; USE mod_b [entire line is commented out] -# USE mod_a ! ; USE mod_b [in-line comment of second USE statement] -# -# the second module name (mod_b) will be picked up as a dependency -# even though it should be ignored. The only way I can see -# to rectify this would be to modify the scanner to eliminate -# the call to re.findall, read in the contents of the file, -# treating the comment character as an end-of-line character -# in addition to the normal linefeed, loop over each line, -# weeding out the comments, and looking for the USE statements. -# One advantage to this is that the regex passed to the scanner -# would no longer need to match a semicolon. -# -# -- I question whether or not we need to detect dependencies to -# INTRINSIC modules because these are built-in to the compiler. -# If we consider them a dependency, will SCons look for them, not -# find them, and kill the build? Or will we there be standard -# compiler-specific directories we will need to point to so the -# compiler and SCons can locate the proper object and mod files? - -# Here is a breakdown of the regex: -# -# (?i) : regex is case insensitive -# ^ : start of line -# (?: : group a collection of regex symbols without saving the match as a "group" -# ^|; : matches either the start of the line or a semicolon - semicolon -# ) : end the unsaved grouping -# \s* : any amount of white space -# USE : match the string USE, case insensitive -# (?: : group a collection of regex symbols without saving the match as a "group" -# \s+| : match one or more whitespace OR .... (the next entire grouped set of regex symbols) -# (?: : group a collection of regex symbols without saving the match as a "group" -# (?: : establish another unsaved grouping of regex symbols -# \s* : any amount of white space -# , : match a comma -# \s* : any amount of white space -# (?:NON_)? : optionally match the prefix NON_, case insensitive -# INTRINSIC : match the string INTRINSIC, case insensitive -# )? : optionally match the ", INTRINSIC/NON_INTRINSIC" grouped expression -# \s* : any amount of white space -# :: : match a double colon that must appear after the INTRINSIC/NON_INTRINSIC attribute -# ) : end the unsaved grouping -# ) : end the unsaved grouping -# \s* : match any amount of white space -# (\w+) : match the module name that is being USE'd -# -# - use_regex = "(?i)(?:^|;)\s*USE(?:\s+|(?:(?:\s*,\s*(?:NON_)?INTRINSIC)?\s*::))\s*(\w+)" - - -# The INCLUDE statement regex matches the following: -# -# INCLUDE 'some_Text' -# INCLUDE "some_Text" -# INCLUDE "some_Text" ; INCLUDE "some_Text" -# INCLUDE kind_"some_Text" -# INCLUDE kind_'some_Text" -# -# where some_Text can include any alphanumeric and/or special character -# as defined by the Fortran 2003 standard. -# -# Limitations: -# -# -- The Fortran standard dictates that a " or ' in the INCLUDE'd -# string must be represented as a "" or '', if the quotes that wrap -# the entire string are either a ' or ", respectively. While the -# regular expression below can detect the ' or " characters just fine, -# the scanning logic, presently is unable to detect them and reduce -# them to a single instance. This probably isn't an issue since, -# in practice, ' or " are not generally used in filenames. -# -# -- This regex will not properly deal with multiple INCLUDE statements -# when the entire line has been commented out, ala -# -# ! INCLUDE 'some_file' ; INCLUDE 'some_file' -# -# In such cases, it will properly ignore the first INCLUDE file, -# but will actually still pick up the second. Interestingly enough, -# the regex will properly deal with these cases: -# -# INCLUDE 'some_file' -# INCLUDE 'some_file' !; INCLUDE 'some_file' -# -# To get around the above limitation, the FORTRAN programmer could -# simply comment each INCLUDE statement separately, like this -# -# ! INCLUDE 'some_file' !; INCLUDE 'some_file' -# -# The way I see it, the only way to get around this limitation would -# be to modify the scanning logic to replace the calls to re.findall -# with a custom loop that processes each line separately, throwing -# away fully commented out lines before attempting to match against -# the INCLUDE syntax. -# -# Here is a breakdown of the regex: -# -# (?i) : regex is case insensitive -# (?: : begin a non-saving group that matches the following: -# ^ : either the start of the line -# | : or -# ['">]\s*; : a semicolon that follows a single quote, -# double quote or greater than symbol (with any -# amount of whitespace in between). This will -# allow the regex to match multiple INCLUDE -# statements per line (although it also requires -# the positive lookahead assertion that is -# used below). It will even properly deal with -# (i.e. ignore) cases in which the additional -# INCLUDES are part of an in-line comment, ala -# " INCLUDE 'someFile' ! ; INCLUDE 'someFile2' " -# ) : end of non-saving group -# \s* : any amount of white space -# INCLUDE : match the string INCLUDE, case insensitive -# \s+ : match one or more white space characters -# (?\w+_)? : match the optional "kind-param _" prefix allowed by the standard -# [<"'] : match the include delimiter - an apostrophe, double quote, or less than symbol -# (.+?) : match one or more characters that make up -# the included path and file name and save it -# in a group. The Fortran standard allows for -# any non-control character to be used. The dot -# operator will pick up any character, including -# control codes, but I can't conceive of anyone -# putting control codes in their file names. -# The question mark indicates it is non-greedy so -# that regex will match only up to the next quote, -# double quote, or greater than symbol -# (?=["'>]) : positive lookahead assertion to match the include -# delimiter - an apostrophe, double quote, or -# greater than symbol. This level of complexity -# is required so that the include delimiter is -# not consumed by the match, thus allowing the -# sub-regex discussed above to uniquely match a -# set of semicolon-separated INCLUDE statements -# (as allowed by the F2003 standard) - - include_regex = """(?i)(?:^|['">]\s*;)\s*INCLUDE\s+(?:\w+_)?[<"'](.+?)(?=["'>])""" - -# The MODULE statement regex finds module definitions by matching -# the following: -# -# MODULE module_name -# -# but *not* the following: -# -# MODULE PROCEDURE procedure_name -# -# Here is a breakdown of the regex: -# -# (?i) : regex is case insensitive -# ^\s* : any amount of white space -# MODULE : match the string MODULE, case insensitive -# \s+ : match one or more white space characters -# (?!PROCEDURE) : but *don't* match if the next word matches -# PROCEDURE (negative lookahead assertion), -# case insensitive -# (\w+) : match one or more alphanumeric characters -# that make up the defined module name and -# save it in a group - - def_regex = """(?i)^\s*MODULE\s+(?!PROCEDURE)(\w+)""" - - scanner = F90Scanner("FortranScan", - "$FORTRANSUFFIXES", - path_variable, - use_regex, - include_regex, - def_regex) - return scanner - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/IDL.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/IDL.py deleted file mode 100644 index 6758bd2..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/IDL.py +++ /dev/null @@ -1,48 +0,0 @@ -"""SCons.Scanner.IDL - -This module implements the depenency scanner for IDL (Interface -Definition Language) files. - -""" - -# -# Copyright (c) 2001 - 2015 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/Scanner/IDL.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.Node.FS -import SCons.Scanner - -def IDLScan(): - """Return a prototype Scanner instance for scanning IDL source files""" - cs = SCons.Scanner.ClassicCPP("IDLScan", - "$IDLSUFFIXES", - "CPPPATH", - '^[ \t]*(?:#[ \t]*include|[ \t]*import)[ \t]+(<|")([^>"]+)(>|")') - return cs - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/LaTeX.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/LaTeX.py deleted file mode 100644 index aed074c..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/LaTeX.py +++ /dev/null @@ -1,390 +0,0 @@ -"""SCons.Scanner.LaTeX - -This module implements the dependency scanner for LaTeX code. - -""" - -# -# Copyright (c) 2001 - 2015 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/Scanner/LaTeX.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import os.path -import re - -import SCons.Scanner -import SCons.Util - -# list of graphics file extensions for TeX and LaTeX -TexGraphics = ['.eps', '.ps'] -LatexGraphics = ['.pdf', '.png', '.jpg', '.gif', '.tif'] - -# Used as a return value of modify_env_var if the variable is not set. -class _Null(object): - pass -_null = _Null - -# The user specifies the paths in env[variable], similar to other builders. -# They may be relative and must be converted to absolute, as expected -# by LaTeX and Co. The environment may already have some paths in -# env['ENV'][var]. These paths are honored, but the env[var] paths have -# higher precedence. All changes are un-done on exit. -def modify_env_var(env, var, abspath): - try: - save = env['ENV'][var] - except KeyError: - save = _null - env.PrependENVPath(var, abspath) - try: - if SCons.Util.is_List(env[var]): - env.PrependENVPath(var, [os.path.abspath(str(p)) for p in env[var]]) - else: - # Split at os.pathsep to convert into absolute path - env.PrependENVPath(var, [os.path.abspath(p) for p in str(env[var]).split(os.pathsep)]) - except KeyError: - pass - - # Convert into a string explicitly to append ":" (without which it won't search system - # paths as well). The problem is that env.AppendENVPath(var, ":") - # does not work, refuses to append ":" (os.pathsep). - - if SCons.Util.is_List(env['ENV'][var]): - env['ENV'][var] = os.pathsep.join(env['ENV'][var]) - # Append the trailing os.pathsep character here to catch the case with no env[var] - env['ENV'][var] = env['ENV'][var] + os.pathsep - - return save - -class FindENVPathDirs(object): - """A class to bind a specific *PATH variable name to a function that - will return all of the *path directories.""" - def __init__(self, variable): - self.variable = variable - def __call__(self, env, dir=None, target=None, source=None, argument=None): - import SCons.PathList - try: - path = env['ENV'][self.variable] - except KeyError: - return () - - dir = dir or env.fs._cwd - path = SCons.PathList.PathList(path).subst_path(env, target, source) - return tuple(dir.Rfindalldirs(path)) - - - -def LaTeXScanner(): - """Return a prototype Scanner instance for scanning LaTeX source files - when built with latex. - """ - ds = LaTeX(name = "LaTeXScanner", - suffixes = '$LATEXSUFFIXES', - # in the search order, see below in LaTeX class docstring - graphics_extensions = TexGraphics, - recursive = 0) - return ds - -def PDFLaTeXScanner(): - """Return a prototype Scanner instance for scanning LaTeX source files - when built with pdflatex. - """ - ds = LaTeX(name = "PDFLaTeXScanner", - suffixes = '$LATEXSUFFIXES', - # in the search order, see below in LaTeX class docstring - graphics_extensions = LatexGraphics, - recursive = 0) - return ds - -class LaTeX(SCons.Scanner.Base): - """Class for scanning LaTeX files for included files. - - Unlike most scanners, which use regular expressions that just - return the included file name, this returns a tuple consisting - 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 - 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. - - 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 - $ latex --version - pdfeTeX 3.141592-1.21a-2.2 (Web2C 7.5.4) - kpathsea version 3.5.4 - The order is: - ['.eps', '.ps'] for latex - ['.png', '.pdf', '.jpg', '.tif']. - - Another difference is that the search path is determined by the type - of the file being searched: - env['TEXINPUTS'] for "input" and "include" keywords - env['TEXINPUTS'] for "includegraphics" keyword - env['TEXINPUTS'] for "lstinputlisting" keyword - env['BIBINPUTS'] for "bibliography" keyword - env['BSTINPUTS'] for "bibliographystyle" keyword - env['INDEXSTYLE'] for "makeindex" keyword, no scanning support needed - just allows user to set it if needed. - - FIXME: also look for the class or style in document[class|style]{} - FIXME: also look for the argument of bibliographystyle{} - """ - keyword_paths = {'include': 'TEXINPUTS', - 'input': 'TEXINPUTS', - 'includegraphics': 'TEXINPUTS', - 'bibliography': 'BIBINPUTS', - 'bibliographystyle': 'BSTINPUTS', - 'addbibresource': 'BIBINPUTS', - 'addglobalbib': 'BIBINPUTS', - 'addsectionbib': 'BIBINPUTS', - 'makeindex': 'INDEXSTYLE', - 'usepackage': 'TEXINPUTS', - 'lstinputlisting': 'TEXINPUTS'} - env_variables = SCons.Util.unique(list(keyword_paths.values())) - - def __init__(self, name, suffixes, graphics_extensions, *args, **kw): - - # We have to include \n with the % we exclude from the first part - # part of the regex because the expression is compiled with re.M. - # Without the \n, the ^ could match the beginning of a *previous* - # line followed by one or more newline characters (i.e. blank - # lines), interfering with a match on the next line. - # add option for whitespace before the '[options]' or the '{filename}' - regex = r'^[^%\n]*\\(include|includegraphics(?:\s*\[[^\]]+\])?|lstinputlisting(?:\[[^\]]+\])?|input|bibliography|addbibresource|addglobalbib|addsectionbib|usepackage)\s*{([^}]*)}' - self.cre = re.compile(regex, re.M) - self.comment_re = re.compile(r'^((?:(?:\\%)|[^%\n])*)(.*)$', re.M) - - self.graphics_extensions = graphics_extensions - - def _scan(node, env, path=(), self=self): - node = node.rfile() - if not node.exists(): - return [] - return self.scan_recurse(node, path) - - class FindMultiPathDirs(object): - """The stock FindPathDirs function has the wrong granularity: - it is called once per target, while we need the path that depends - on what kind of included files is being searched. This wrapper - hides multiple instances of FindPathDirs, one per the LaTeX path - variable in the environment. When invoked, the function calculates - and returns all the required paths as a dictionary (converted into - a tuple to become hashable). Then the scan function converts it - back and uses a dictionary of tuples rather than a single tuple - of paths. - """ - def __init__(self, dictionary): - self.dictionary = {} - for k,n in dictionary.items(): - self.dictionary[k] = ( SCons.Scanner.FindPathDirs(n), - FindENVPathDirs(n) ) - - def __call__(self, env, dir=None, target=None, source=None, - argument=None): - di = {} - for k,(c,cENV) in self.dictionary.items(): - di[k] = ( c(env, dir=None, target=None, source=None, - argument=None) , - cENV(env, dir=None, target=None, source=None, - argument=None) ) - # To prevent "dict is not hashable error" - return tuple(di.items()) - - class LaTeXScanCheck(object): - """Skip all but LaTeX source files, i.e., do not scan *.eps, - *.pdf, *.jpg, etc. - """ - def __init__(self, suffixes): - self.suffixes = suffixes - def __call__(self, node, env): - current = not node.has_builder() or node.is_up_to_date() - scannable = node.get_suffix() in env.subst_list(self.suffixes)[0] - # Returning false means that the file is not scanned. - return scannable and current - - kw['function'] = _scan - kw['path_function'] = FindMultiPathDirs(LaTeX.keyword_paths) - kw['recursive'] = 0 - kw['skeys'] = suffixes - kw['scan_check'] = LaTeXScanCheck(suffixes) - kw['name'] = name - - SCons.Scanner.Base.__init__(self, *args, **kw) - - def _latex_names(self, include): - filename = include[1] - if include[0] == 'input': - base, ext = os.path.splitext( filename ) - if ext == "": - return [filename + '.tex'] - if (include[0] == 'include'): - return [filename + '.tex'] - if include[0] == 'bibliography': - base, ext = os.path.splitext( filename ) - if ext == "": - return [filename + '.bib'] - if include[0] == 'usepackage': - base, ext = os.path.splitext( filename ) - if ext == "": - return [filename + '.sty'] - if include[0] == 'includegraphics': - base, ext = os.path.splitext( filename ) - if ext == "": - #return [filename+e for e in self.graphics_extensions + TexGraphics] - # use the line above to find dependencies for the PDF builder - # when only an .eps figure is present. Since it will be found - # if the user tells scons how to make the pdf figure, leave - # it out for now. - return [filename+e for e in self.graphics_extensions] - return [filename] - - def sort_key(self, include): - return SCons.Node.FS._my_normcase(str(include)) - - def find_include(self, include, source_dir, path): - try: - sub_path = path[include[0]] - except (IndexError, KeyError): - sub_path = () - try_names = self._latex_names(include) - for n in try_names: - # see if we find it using the path in env[var] - i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[0]) - if i: - return i, include - # see if we find it using the path in env['ENV'][var] - i = SCons.Node.FS.find_file(n, (source_dir,) + sub_path[1]) - if i: - return i, include - return i, include - - def canonical_text(self, text): - """Standardize an input TeX-file contents. - - Currently: - * removes comments, unwrapping comment-wrapped lines. - """ - out = [] - line_continues_a_comment = False - for line in text.splitlines(): - line,comment = self.comment_re.findall(line)[0] - if line_continues_a_comment == True: - out[-1] = out[-1] + line.lstrip() - else: - out.append(line) - line_continues_a_comment = len(comment) > 0 - return '\n'.join(out).rstrip()+'\n' - - def scan(self, node): - # Modify the default scan function to allow for the regular - # expression to return a comma separated list of file names - # as can be the case with the bibliography keyword. - - # Cache the includes list in node so we only scan it once: - # path_dict = dict(list(path)) - # add option for whitespace (\s) before the '[' - noopt_cre = re.compile('\s*\[.*$') - if node.includes != None: - includes = node.includes - else: - text = self.canonical_text(node.get_text_contents()) - includes = self.cre.findall(text) - # 1. Split comma-separated lines, e.g. - # ('bibliography', 'phys,comp') - # should become two entries - # ('bibliography', 'phys') - # ('bibliography', 'comp') - # 2. Remove the options, e.g., such as - # ('includegraphics[clip,width=0.7\\linewidth]', 'picture.eps') - # should become - # ('includegraphics', 'picture.eps') - split_includes = [] - for include in includes: - inc_type = noopt_cre.sub('', include[0]) - inc_list = include[1].split(',') - for j in range(len(inc_list)): - split_includes.append( (inc_type, inc_list[j]) ) - # - includes = split_includes - node.includes = includes - - return includes - - def scan_recurse(self, node, path=()): - """ do a recursive scan of the top level target file - This lets us search for included files based on the - directory of the main file just as latex does""" - - path_dict = dict(list(path)) - - queue = [] - queue.extend( self.scan(node) ) - seen = {} - - # This is a hand-coded DSU (decorate-sort-undecorate, or - # Schwartzian transform) pattern. The sort key is the raw name - # of the file as specifed on the \include, \input, etc. line. - # TODO: what about the comment in the original Classic scanner: - # """which lets - # us keep the sort order constant regardless of whether the file - # is actually found in a Repository or locally.""" - nodes = [] - source_dir = node.get_dir() - #for include in includes: - while queue: - - include = queue.pop() - try: - if seen[include[1]] == 1: - continue - except KeyError: - seen[include[1]] = 1 - - # - # Handle multiple filenames in include[1] - # - n, i = self.find_include(include, source_dir, path_dict) - if n is None: - # Do not bother with 'usepackage' warnings, as they most - # likely refer to system-level files - if include[0] != 'usepackage': - SCons.Warnings.warn(SCons.Warnings.DependencyWarning, - "No dependency generated for file: %s (included from: %s) -- file not found" % (i, node)) - else: - sortkey = self.sort_key(n) - nodes.append((sortkey, n)) - # recurse down - queue.extend( self.scan(n) ) - - return [pair[1] for pair in sorted(nodes)] - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/Prog.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/Prog.py deleted file mode 100644 index c0511dc..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/Prog.py +++ /dev/null @@ -1,116 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/Scanner/Prog.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.Node -import SCons.Node.FS -import SCons.Scanner -import SCons.Util - -# global, set by --debug=findlibs -print_find_libs = None - -def ProgramScanner(**kw): - """Return a prototype Scanner instance for scanning executable - files for static-lib dependencies""" - kw['path_function'] = SCons.Scanner.FindPathDirs('LIBPATH') - ps = SCons.Scanner.Base(scan, "ProgramScanner", **kw) - return ps - -def _subst_libs(env, libs): - """ - Substitute environment variables and split into list. - """ - if SCons.Util.is_String(libs): - libs = env.subst(libs) - if SCons.Util.is_String(libs): - libs = libs.split() - elif SCons.Util.is_Sequence(libs): - _libs = [] - for l in libs: - _libs += _subst_libs(env, l) - libs = _libs - else: - # libs is an object (Node, for example) - libs = [libs] - return libs - -def scan(node, env, libpath = ()): - """ - This scanner scans program files for static-library - dependencies. It will search the LIBPATH environment variable - for libraries specified in the LIBS variable, returning any - files it finds as dependencies. - """ - try: - libs = env['LIBS'] - except KeyError: - # There are no LIBS in this environment, so just return a null list: - return [] - - libs = _subst_libs(env, libs) - - try: - prefix = env['LIBPREFIXES'] - if not SCons.Util.is_List(prefix): - prefix = [ prefix ] - except KeyError: - prefix = [ '' ] - - try: - suffix = env['LIBSUFFIXES'] - if not SCons.Util.is_List(suffix): - suffix = [ suffix ] - except KeyError: - suffix = [ '' ] - - pairs = [] - for suf in map(env.subst, suffix): - for pref in map(env.subst, prefix): - pairs.append((pref, suf)) - - result = [] - - if callable(libpath): - libpath = libpath() - - find_file = SCons.Node.FS.find_file - adjustixes = SCons.Util.adjustixes - for lib in libs: - if SCons.Util.is_String(lib): - for pref, suf in pairs: - l = adjustixes(lib, pref, suf) - l = find_file(l, libpath, verbose=print_find_libs) - if l: - result.append(l) - else: - result.append(lib) - - return result - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/RC.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/RC.py deleted file mode 100644 index f73b47e..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/RC.py +++ /dev/null @@ -1,55 +0,0 @@ -"""SCons.Scanner.RC - -This module implements the depenency scanner for RC (Interface -Definition Language) files. - -""" - -# -# Copyright (c) 2001 - 2015 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/Scanner/RC.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.Node.FS -import SCons.Scanner -import re - -def RCScan(): - """Return a prototype Scanner instance for scanning RC source files""" - - res_re= r'^(?:\s*#\s*(?:include)|' \ - '.*?\s+(?:ICON|BITMAP|CURSOR|HTML|FONT|MESSAGETABLE|TYPELIB|REGISTRY|D3DFX)' \ - '\s*.*?)' \ - '\s*(<|"| )([^>"\s]+)(?:[>"\s])*$' - resScanner = SCons.Scanner.ClassicCPP( "ResourceScanner", - "$RCSUFFIXES", - "CPPPATH", - res_re ) - - return resScanner - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/__init__.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/__init__.py deleted file mode 100644 index d51cb9e..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Scanner/__init__.py +++ /dev/null @@ -1,413 +0,0 @@ -"""SCons.Scanner - -The Scanner package for the SCons software construction utility. - -""" - -# -# Copyright (c) 2001 - 2015 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/Scanner/__init__.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import re - -import SCons.Node.FS -import SCons.Util - - -class _Null(object): - pass - -# This is used instead of None as a default argument value so None can be -# used as an actual argument value. -_null = _Null - -def Scanner(function, *args, **kw): - """ - Public interface factory function for creating different types - of Scanners based on the different types of "functions" that may - be supplied. - - TODO: Deprecate this some day. We've moved the functionality - inside the Base class and really don't need this factory function - any more. It was, however, used by some of our Tool modules, so - the call probably ended up in various people's custom modules - patterned on SCons code. - """ - if SCons.Util.is_Dict(function): - return Selector(function, *args, **kw) - else: - return Base(function, *args, **kw) - - - -class FindPathDirs(object): - """A class to bind a specific *PATH variable name to a function that - will return all of the *path directories.""" - def __init__(self, variable): - self.variable = variable - def __call__(self, env, dir=None, target=None, source=None, argument=None): - import SCons.PathList - try: - path = env[self.variable] - except KeyError: - return () - - dir = dir or env.fs._cwd - path = SCons.PathList.PathList(path).subst_path(env, target, source) - return tuple(dir.Rfindalldirs(path)) - - - -class Base(object): - """ - The base class for dependency scanners. This implements - straightforward, single-pass scanning of a single file. - """ - - def __init__(self, - function, - name = "NONE", - argument = _null, - skeys = _null, - path_function = None, - # Node.FS.Base so that, by default, it's okay for a - # scanner to return a Dir, File or Entry. - node_class = SCons.Node.FS.Base, - node_factory = None, - scan_check = None, - recursive = None): - """ - Construct a new scanner object given a scanner function. - - 'function' - a scanner function taking two or three - arguments and returning a list of strings. - - 'name' - a name for identifying this scanner object. - - 'argument' - an optional argument that, if specified, will be - passed to both the scanner function and the path_function. - - 'skeys' - an optional list argument that can be used to determine - which scanner should be used for a given Node. In the case of File - nodes, for example, the 'skeys' would be file suffixes. - - 'path_function' - a function that takes four or five arguments - (a construction environment, Node for the directory containing - the SConscript file that defined the primary target, list of - target nodes, list of source nodes, and optional argument for - this instance) and returns a tuple of the directories that can - be searched for implicit dependency files. May also return a - callable() which is called with no args and returns the tuple - (supporting Bindable class). - - 'node_class' - the class of Nodes which this scan will return. - If node_class is None, then this scanner will not enforce any - Node conversion and will return the raw results from the - underlying scanner function. - - 'node_factory' - the factory function to be called to translate - the raw results returned by the scanner function into the - expected node_class objects. - - 'scan_check' - a function to be called to first check whether - this node really needs to be scanned. - - 'recursive' - specifies that this scanner should be invoked - recursively on all of the implicit dependencies it returns - (the canonical example being #include lines in C source files). - May be a callable, which will be called to filter the list - of nodes found to select a subset for recursive scanning - (the canonical example being only recursively scanning - subdirectories within a directory). - - The scanner function's first argument will be a Node that should - be scanned for dependencies, the second argument will be an - Environment object, the third argument will be the tuple of paths - returned by the path_function, and the fourth argument will be - the value passed into 'argument', and the returned list should - contain the Nodes for all the direct dependencies of the file. - - Examples: - - s = Scanner(my_scanner_function) - - s = Scanner(function = my_scanner_function) - - s = Scanner(function = my_scanner_function, argument = 'foo') - - """ - - # Note: this class could easily work with scanner functions that take - # something other than a filename as an argument (e.g. a database - # node) and a dependencies list that aren't file names. All that - # would need to be changed is the documentation. - - self.function = function - self.path_function = path_function - self.name = name - self.argument = argument - - if skeys is _null: - if SCons.Util.is_Dict(function): - skeys = list(function.keys()) - else: - skeys = [] - self.skeys = skeys - - self.node_class = node_class - self.node_factory = node_factory - self.scan_check = scan_check - if callable(recursive): - self.recurse_nodes = recursive - elif recursive: - self.recurse_nodes = self._recurse_all_nodes - else: - self.recurse_nodes = self._recurse_no_nodes - - def path(self, env, dir=None, target=None, source=None): - if not self.path_function: - return () - if not self.argument is _null: - return self.path_function(env, dir, target, source, self.argument) - else: - return self.path_function(env, dir, target, source) - - def __call__(self, node, env, path = ()): - """ - This method scans a single object. 'node' is the node - that will be passed to the scanner function, and 'env' is the - environment that will be passed to the scanner function. A list of - direct dependency nodes for the specified node will be returned. - """ - if self.scan_check and not self.scan_check(node, env): - return [] - - self = self.select(node) - - if not self.argument is _null: - list = self.function(node, env, path, self.argument) - else: - list = self.function(node, env, path) - - kw = {} - if hasattr(node, 'dir'): - kw['directory'] = node.dir - node_factory = env.get_factory(self.node_factory) - nodes = [] - for l in list: - if self.node_class and not isinstance(l, self.node_class): - l = node_factory(l, **kw) - nodes.append(l) - return nodes - - def __cmp__(self, other): - try: - return cmp(self.__dict__, other.__dict__) - except AttributeError: - # other probably doesn't have a __dict__ - return cmp(self.__dict__, other) - - def __hash__(self): - return id(self) - - def __str__(self): - return self.name - - def add_skey(self, skey): - """Add a skey to the list of skeys""" - self.skeys.append(skey) - - def get_skeys(self, env=None): - if env and SCons.Util.is_String(self.skeys): - return env.subst_list(self.skeys)[0] - return self.skeys - - def select(self, node): - if SCons.Util.is_Dict(self.function): - key = node.scanner_key() - try: - return self.function[key] - except KeyError: - return None - else: - return self - - def _recurse_all_nodes(self, nodes): - return nodes - - def _recurse_no_nodes(self, nodes): - return [] - - recurse_nodes = _recurse_no_nodes - - def add_scanner(self, skey, scanner): - self.function[skey] = scanner - self.add_skey(skey) - - -class Selector(Base): - """ - A class for selecting a more specific scanner based on the - scanner_key() (suffix) for a specific Node. - - TODO: This functionality has been moved into the inner workings of - the Base class, and this class will be deprecated at some point. - (It was never exposed directly as part of the public interface, - although it is used by the Scanner() factory function that was - used by various Tool modules and therefore was likely a template - for custom modules that may be out there.) - """ - def __init__(self, dict, *args, **kw): - Base.__init__(self, None, *args, **kw) - self.dict = dict - self.skeys = list(dict.keys()) - - def __call__(self, node, env, path = ()): - return self.select(node)(node, env, path) - - def select(self, node): - try: - return self.dict[node.scanner_key()] - except KeyError: - return None - - def add_scanner(self, skey, scanner): - self.dict[skey] = scanner - self.add_skey(skey) - - -class Current(Base): - """ - A class for scanning files that are source files (have no builder) - or are derived files and are current (which implies that they exist, - either locally or in a repository). - """ - - def __init__(self, *args, **kw): - def current_check(node, env): - return not node.has_builder() or node.is_up_to_date() - kw['scan_check'] = current_check - Base.__init__(self, *args, **kw) - -class Classic(Current): - """ - A Scanner subclass to contain the common logic for classic CPP-style - include scanning, but which can be customized to use different - regular expressions to find the includes. - - Note that in order for this to work "out of the box" (without - overriding the find_include() and sort_key() methods), the regular - expression passed to the constructor must return the name of the - include file in group 0. - """ - - def __init__(self, name, suffixes, path_variable, regex, *args, **kw): - - self.cre = re.compile(regex, re.M) - - def _scan(node, env, path=(), self=self): - node = node.rfile() - if not node.exists(): - return [] - return self.scan(node, path) - - kw['function'] = _scan - kw['path_function'] = FindPathDirs(path_variable) - kw['recursive'] = 1 - kw['skeys'] = suffixes - kw['name'] = name - - Current.__init__(self, *args, **kw) - - def find_include(self, include, source_dir, path): - n = SCons.Node.FS.find_file(include, (source_dir,) + tuple(path)) - return n, include - - def sort_key(self, include): - return SCons.Node.FS._my_normcase(include) - - def find_include_names(self, node): - return self.cre.findall(node.get_text_contents()) - - def scan(self, node, path=()): - - # cache the includes list in node so we only scan it once: - if node.includes is not None: - includes = node.includes - else: - includes = self.find_include_names (node) - # Intern the names of the include files. Saves some memory - # if the same header is included many times. - node.includes = list(map(SCons.Util.silent_intern, includes)) - - # This is a hand-coded DSU (decorate-sort-undecorate, or - # Schwartzian transform) pattern. The sort key is the raw name - # of the file as specifed on the #include line (including the - # " or <, since that may affect what file is found), which lets - # us keep the sort order constant regardless of whether the file - # is actually found in a Repository or locally. - nodes = [] - source_dir = node.get_dir() - if callable(path): - path = path() - for include in includes: - n, i = self.find_include(include, source_dir, path) - - if n is None: - SCons.Warnings.warn(SCons.Warnings.DependencyWarning, - "No dependency generated for file: %s (included from: %s) -- file not found" % (i, node)) - else: - nodes.append((self.sort_key(include), n)) - - return [pair[1] for pair in sorted(nodes)] - -class ClassicCPP(Classic): - """ - A Classic Scanner subclass which takes into account the type of - bracketing used to include the file, and uses classic CPP rules - for searching for the files based on the bracketing. - - Note that in order for this to work, the regular expression passed - to the constructor must return the leading bracket in group 0, and - the contained filename in group 1. - """ - def find_include(self, include, source_dir, path): - if include[0] == '"': - paths = (source_dir,) + tuple(path) - else: - paths = tuple(path) + (source_dir,) - - n = SCons.Node.FS.find_file(include[1], paths) - - i = SCons.Util.silent_intern(include[1]) - return n, i - - def sort_key(self, include): - return SCons.Node.FS._my_normcase(' '.join(include)) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/Interactive.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/Interactive.py deleted file mode 100644 index afcde0c..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/Interactive.py +++ /dev/null @@ -1,384 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/Script/Interactive.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -__doc__ = """ -SCons interactive mode -""" - -# TODO: -# -# This has the potential to grow into something with a really big life -# of its own, which might or might not be a good thing. Nevertheless, -# here are some enhancements that will probably be requested some day -# and are worth keeping in mind (assuming this takes off): -# -# - A command to re-read / re-load the SConscript files. This may -# involve allowing people to specify command-line options (e.g. -f, -# -I, --no-site-dir) that affect how the SConscript files are read. -# -# - Additional command-line options on the "build" command. -# -# Of the supported options that seemed to make sense (after a quick -# pass through the list), the ones that seemed likely enough to be -# used are listed in the man page and have explicit test scripts. -# -# These had code changed in Script/Main.py to support them, but didn't -# seem likely to be used regularly, so had no test scripts added: -# -# build --diskcheck=* -# build --implicit-cache=* -# build --implicit-deps-changed=* -# build --implicit-deps-unchanged=* -# -# These look like they should "just work" with no changes to the -# existing code, but like those above, look unlikely to be used and -# therefore had no test scripts added: -# -# build --random -# -# These I'm not sure about. They might be useful for individual -# "build" commands, and may even work, but they seem unlikely enough -# that we'll wait until they're requested before spending any time on -# writing test scripts for them, or investigating whether they work. -# -# build -q [??? is there a useful analog to the exit status?] -# build --duplicate= -# build --profile= -# build --max-drift= -# build --warn=* -# build --Y -# -# - Most of the SCons command-line options that the "build" command -# supports should be settable as default options that apply to all -# subsequent "build" commands. Maybe a "set {option}" command that -# maps to "SetOption('{option}')". -# -# - Need something in the 'help' command that prints the -h output. -# -# - A command to run the configure subsystem separately (must see how -# this interacts with the new automake model). -# -# - Command-line completion of target names; maybe even of SCons options? -# Completion is something that's supported by the Python cmd module, -# so this should be doable without too much trouble. -# - -import cmd -import copy -import os -import re -import shlex -import sys - -try: - import readline -except ImportError: - pass - -class SConsInteractiveCmd(cmd.Cmd): - """\ - build [TARGETS] Build the specified TARGETS and their dependencies. - 'b' is a synonym. - clean [TARGETS] Clean (remove) the specified TARGETS and their - dependencies. 'c' is a synonym. - exit Exit SCons interactive mode. - help [COMMAND] Prints help for the specified COMMAND. 'h' and - '?' are synonyms. - shell [COMMANDLINE] Execute COMMANDLINE in a subshell. 'sh' and '!' - are synonyms. - version Prints SCons version information. - """ - - synonyms = { - 'b' : 'build', - 'c' : 'clean', - 'h' : 'help', - 'scons' : 'build', - 'sh' : 'shell', - } - - def __init__(self, **kw): - cmd.Cmd.__init__(self) - for key, val in kw.items(): - setattr(self, key, val) - - if sys.platform == 'win32': - self.shell_variable = 'COMSPEC' - else: - self.shell_variable = 'SHELL' - - def default(self, argv): - print "*** Unknown command: %s" % argv[0] - - def onecmd(self, line): - line = line.strip() - if not line: - print self.lastcmd - return self.emptyline() - self.lastcmd = line - if line[0] == '!': - line = 'shell ' + line[1:] - elif line[0] == '?': - line = 'help ' + line[1:] - if os.sep == '\\': - line = line.replace('\\', '\\\\') - argv = shlex.split(line) - argv[0] = self.synonyms.get(argv[0], argv[0]) - if not argv[0]: - return self.default(line) - else: - try: - func = getattr(self, 'do_' + argv[0]) - except AttributeError: - return self.default(argv) - return func(argv) - - def do_build(self, argv): - """\ - build [TARGETS] Build the specified TARGETS and their - dependencies. 'b' is a synonym. - """ - import SCons.Node - import SCons.SConsign - import SCons.Script.Main - - options = copy.deepcopy(self.options) - - options, targets = self.parser.parse_args(argv[1:], values=options) - - SCons.Script.COMMAND_LINE_TARGETS = targets - - if targets: - SCons.Script.BUILD_TARGETS = targets - else: - # If the user didn't specify any targets on the command line, - # use the list of default targets. - SCons.Script.BUILD_TARGETS = SCons.Script._build_plus_default - - nodes = SCons.Script.Main._build_targets(self.fs, - options, - targets, - self.target_top) - - if not nodes: - return - - # Call each of the Node's alter_targets() methods, which may - # provide additional targets that ended up as part of the build - # (the canonical example being a VariantDir() when we're building - # from a source directory) and which we therefore need their - # state cleared, too. - x = [] - for n in nodes: - x.extend(n.alter_targets()[0]) - nodes.extend(x) - - # Clean up so that we can perform the next build correctly. - # - # We do this by walking over all the children of the targets, - # and clearing their state. - # - # We currently have to re-scan each node to find their - # children, because built nodes have already been partially - # cleared and don't remember their children. (In scons - # 0.96.1 and earlier, this wasn't the case, and we didn't - # have to re-scan the nodes.) - # - # Because we have to re-scan each node, we can't clear the - # nodes as we walk over them, because we may end up rescanning - # a cleared node as we scan a later node. Therefore, only - # store the list of nodes that need to be cleared as we walk - # the tree, and clear them in a separate pass. - # - # XXX: Someone more familiar with the inner workings of scons - # may be able to point out a more efficient way to do this. - - SCons.Script.Main.progress_display("scons: Clearing cached node information ...") - - seen_nodes = {} - - def get_unseen_children(node, parent, seen_nodes=seen_nodes): - def is_unseen(node, seen_nodes=seen_nodes): - return node not in seen_nodes - return list(filter(is_unseen, node.children(scan=1))) - - def add_to_seen_nodes(node, parent, seen_nodes=seen_nodes): - seen_nodes[node] = 1 - - # If this file is in a VariantDir and has a - # corresponding source file in the source tree, remember the - # node in the source tree, too. This is needed in - # particular to clear cached implicit dependencies on the - # source file, since the scanner will scan it if the - # VariantDir was created with duplicate=0. - try: - rfile_method = node.rfile - except AttributeError: - return - else: - rfile = rfile_method() - if rfile != node: - seen_nodes[rfile] = 1 - - for node in nodes: - walker = SCons.Node.Walker(node, - kids_func=get_unseen_children, - eval_func=add_to_seen_nodes) - n = walker.get_next() - while n: - n = walker.get_next() - - for node in seen_nodes.keys(): - # Call node.clear() to clear most of the state - node.clear() - # node.clear() doesn't reset node.state, so call - # node.set_state() to reset it manually - node.set_state(SCons.Node.no_state) - node.implicit = None - - # Debug: Uncomment to verify that all Taskmaster reference - # counts have been reset to zero. - #if node.ref_count != 0: - # from SCons.Debug import Trace - # Trace('node %s, ref_count %s !!!\n' % (node, node.ref_count)) - - SCons.SConsign.Reset() - SCons.Script.Main.progress_display("scons: done clearing node information.") - - def do_clean(self, argv): - """\ - clean [TARGETS] Clean (remove) the specified TARGETS - and their dependencies. 'c' is a synonym. - """ - return self.do_build(['build', '--clean'] + argv[1:]) - - def do_EOF(self, argv): - print - self.do_exit(argv) - - def _do_one_help(self, arg): - try: - # If help_() exists, then call it. - func = getattr(self, 'help_' + arg) - except AttributeError: - try: - func = getattr(self, 'do_' + arg) - except AttributeError: - doc = None - else: - doc = self._doc_to_help(func) - if doc: - sys.stdout.write(doc + '\n') - sys.stdout.flush() - else: - doc = self.strip_initial_spaces(func()) - if doc: - sys.stdout.write(doc + '\n') - sys.stdout.flush() - - def _doc_to_help(self, obj): - doc = obj.__doc__ - if doc is None: - return '' - return self._strip_initial_spaces(doc) - - def _strip_initial_spaces(self, s): - #lines = s.split('\n') - lines = s.split('\n') - spaces = re.match(' *', lines[0]).group(0) - #def strip_spaces(l): - # if l.startswith(spaces): - # l = l[len(spaces):] - # return l - #return '\n'.join([ strip_spaces(l) for l in lines ]) - def strip_spaces(l, spaces=spaces): - if l[:len(spaces)] == spaces: - l = l[len(spaces):] - return l - lines = list(map(strip_spaces, lines)) - return '\n'.join(lines) - - def do_exit(self, argv): - """\ - exit Exit SCons interactive mode. - """ - sys.exit(0) - - def do_help(self, argv): - """\ - help [COMMAND] Prints help for the specified COMMAND. 'h' - and '?' are synonyms. - """ - if argv[1:]: - for arg in argv[1:]: - if self._do_one_help(arg): - break - else: - # If bare 'help' is called, print this class's doc - # string (if it has one). - doc = self._doc_to_help(self.__class__) - if doc: - sys.stdout.write(doc + '\n') - sys.stdout.flush() - - def do_shell(self, argv): - """\ - shell [COMMANDLINE] Execute COMMANDLINE in a subshell. 'sh' and - '!' are synonyms. - """ - import subprocess - argv = argv[1:] - if not argv: - argv = os.environ[self.shell_variable] - try: - # Per "[Python-Dev] subprocess insufficiently platform-independent?" - # http://mail.python.org/pipermail/python-dev/2008-August/081979.html "+ - # Doing the right thing with an argument list currently - # requires different shell= values on Windows and Linux. - p = subprocess.Popen(argv, shell=(sys.platform=='win32')) - except EnvironmentError, e: - sys.stderr.write('scons: %s: %s\n' % (argv[0], e.strerror)) - else: - p.wait() - - def do_version(self, argv): - """\ - version Prints SCons version information. - """ - sys.stdout.write(self.parser.version + '\n') - -def interact(fs, parser, options, targets, target_top): - c = SConsInteractiveCmd(prompt = 'scons>>> ', - fs = fs, - parser = parser, - options = options, - targets = targets, - target_top = target_top) - c.cmdloop() - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/Main.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/Main.py deleted file mode 100644 index 6684fbd..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/Main.py +++ /dev/null @@ -1,1437 +0,0 @@ -"""SCons.Script - -This file implements the main() function used by the scons script. - -Architecturally, this *is* the scons script, and will likely only be -called from the external "scons" wrapper. Consequently, anything here -should not be, or be considered, part of the build engine. If it's -something that we expect other software to want to use, it should go in -some other module. If it's specific to the "scons" script invocation, -it goes here. -""" - -unsupported_python_version = (2, 3, 0) -deprecated_python_version = (2, 7, 0) - -# Copyright (c) 2001 - 2015 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/Script/Main.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import SCons.compat - -import os -import sys -import time -import traceback - -# Strip the script directory from sys.path() so on case-insensitive -# (Windows) systems Python doesn't think that the "scons" script is the -# "SCons" package. Replace it with our own version directory so, if -# if they're there, we pick up the right version of the build engine -# modules. -#sys.path = [os.path.join(sys.prefix, -# 'lib', -# 'scons-%d' % SCons.__version__)] + sys.path[1:] - -import SCons.CacheDir -import SCons.Debug -import SCons.Defaults -import SCons.Environment -import SCons.Errors -import SCons.Job -import SCons.Node -import SCons.Node.FS -import SCons.Platform -import SCons.SConf -import SCons.Script -import SCons.Taskmaster -import SCons.Util -import SCons.Warnings - -import SCons.Script.Interactive - -def fetch_win32_parallel_msg(): - # A subsidiary function that exists solely to isolate this import - # so we don't have to pull it in on all platforms, and so that an - # in-line "import" statement in the _main() function below doesn't - # cause warnings about local names shadowing use of the 'SCons' - # globl in nest scopes and UnboundLocalErrors and the like in some - # versions (2.1) of Python. - import SCons.Platform.win32 - return SCons.Platform.win32.parallel_msg - -def revert_io(): - # This call is added to revert stderr and stdout to the original - # ones just in case some build rule or something else in the system - # has redirected them elsewhere. - sys.stderr = sys.__stderr__ - sys.stdout = sys.__stdout__ - -class SConsPrintHelpException(Exception): - pass - -display = SCons.Util.display -progress_display = SCons.Util.DisplayEngine() - -first_command_start = None -last_command_end = None - -class Progressor(object): - prev = '' - count = 0 - target_string = '$TARGET' - - def __init__(self, obj, interval=1, file=None, overwrite=False): - if file is None: - file = sys.stdout - - self.obj = obj - self.file = file - self.interval = interval - self.overwrite = overwrite - - if callable(obj): - self.func = obj - elif SCons.Util.is_List(obj): - self.func = self.spinner - elif obj.find(self.target_string) != -1: - self.func = self.replace_string - else: - self.func = self.string - - def write(self, s): - self.file.write(s) - self.file.flush() - self.prev = s - - def erase_previous(self): - if self.prev: - length = len(self.prev) - if self.prev[-1] in ('\n', '\r'): - length = length - 1 - self.write(' ' * length + '\r') - self.prev = '' - - def spinner(self, node): - self.write(self.obj[self.count % len(self.obj)]) - - def string(self, node): - self.write(self.obj) - - def replace_string(self, node): - self.write(self.obj.replace(self.target_string, str(node))) - - def __call__(self, node): - self.count = self.count + 1 - if (self.count % self.interval) == 0: - if self.overwrite: - self.erase_previous() - self.func(node) - -ProgressObject = SCons.Util.Null() - -def Progress(*args, **kw): - global ProgressObject - ProgressObject = Progressor(*args, **kw) - -# Task control. -# - -_BuildFailures = [] - -def GetBuildFailures(): - return _BuildFailures - -class BuildTask(SCons.Taskmaster.OutOfDateTask): - """An SCons build task.""" - progress = ProgressObject - - def display(self, message): - display('scons: ' + message) - - def prepare(self): - self.progress(self.targets[0]) - return SCons.Taskmaster.OutOfDateTask.prepare(self) - - def needs_execute(self): - if SCons.Taskmaster.OutOfDateTask.needs_execute(self): - return True - if self.top and self.targets[0].has_builder(): - display("scons: `%s' is up to date." % str(self.node)) - return False - - def execute(self): - if print_time: - start_time = time.time() - global first_command_start - if first_command_start is None: - first_command_start = start_time - SCons.Taskmaster.OutOfDateTask.execute(self) - if print_time: - global cumulative_command_time - global last_command_end - finish_time = time.time() - last_command_end = finish_time - cumulative_command_time = cumulative_command_time+finish_time-start_time - sys.stdout.write("Command execution time: %s: %f seconds\n"%(str(self.node), finish_time-start_time)) - - def do_failed(self, status=2): - _BuildFailures.append(self.exception[1]) - global exit_status - global this_build_status - if self.options.ignore_errors: - SCons.Taskmaster.OutOfDateTask.executed(self) - elif self.options.keep_going: - SCons.Taskmaster.OutOfDateTask.fail_continue(self) - exit_status = status - this_build_status = status - else: - SCons.Taskmaster.OutOfDateTask.fail_stop(self) - exit_status = status - this_build_status = status - - def executed(self): - t = self.targets[0] - if self.top and not t.has_builder() and not t.side_effect: - if not t.exists(): - if t.__class__.__name__ in ('File', 'Dir', 'Entry'): - errstr="Do not know how to make %s target `%s' (%s)." % (t.__class__.__name__, t, t.get_abspath()) - else: # Alias or Python or ... - errstr="Do not know how to make %s target `%s'." % (t.__class__.__name__, t) - sys.stderr.write("scons: *** " + errstr) - if not self.options.keep_going: - sys.stderr.write(" Stop.") - sys.stderr.write("\n") - try: - raise SCons.Errors.BuildError(t, errstr) - except KeyboardInterrupt: - raise - except: - self.exception_set() - self.do_failed() - else: - print "scons: Nothing to be done for `%s'." % t - SCons.Taskmaster.OutOfDateTask.executed(self) - else: - SCons.Taskmaster.OutOfDateTask.executed(self) - - def failed(self): - # Handle the failure of a build task. The primary purpose here - # is to display the various types of Errors and Exceptions - # appropriately. - exc_info = self.exc_info() - try: - t, e, tb = exc_info - except ValueError: - t, e = exc_info - tb = None - - if t is None: - # The Taskmaster didn't record an exception for this Task; - # see if the sys module has one. - try: - t, e, tb = sys.exc_info()[:] - except ValueError: - t, e = exc_info - tb = None - - # Deprecated string exceptions will have their string stored - # in the first entry of the tuple. - if e is None: - e = t - - buildError = SCons.Errors.convert_to_BuildError(e) - if not buildError.node: - buildError.node = self.node - - node = buildError.node - if not SCons.Util.is_List(node): - node = [ node ] - nodename = ', '.join(map(str, node)) - - errfmt = "scons: *** [%s] %s\n" - sys.stderr.write(errfmt % (nodename, buildError)) - - if (buildError.exc_info[2] and buildError.exc_info[1] and - not isinstance( - buildError.exc_info[1], - (EnvironmentError, SCons.Errors.StopError, - SCons.Errors.UserError))): - type, value, trace = buildError.exc_info - if tb and print_stacktrace: - sys.stderr.write("scons: internal stack trace:\n") - traceback.print_tb(tb, file=sys.stderr) - traceback.print_exception(type, value, trace) - elif tb and print_stacktrace: - sys.stderr.write("scons: internal stack trace:\n") - traceback.print_tb(tb, file=sys.stderr) - - self.exception = (e, buildError, tb) # type, value, traceback - self.do_failed(buildError.exitstatus) - - self.exc_clear() - - def postprocess(self): - if self.top: - t = self.targets[0] - for tp in self.options.tree_printers: - tp.display(t) - if self.options.debug_includes: - tree = t.render_include_tree() - if tree: - print - print tree - SCons.Taskmaster.OutOfDateTask.postprocess(self) - - def make_ready(self): - """Make a task ready for execution""" - SCons.Taskmaster.OutOfDateTask.make_ready(self) - if self.out_of_date and self.options.debug_explain: - explanation = self.out_of_date[0].explain() - if explanation: - sys.stdout.write("scons: " + explanation) - -class CleanTask(SCons.Taskmaster.AlwaysTask): - """An SCons clean task.""" - def fs_delete(self, path, pathstr, remove=True): - try: - if os.path.lexists(path): - if os.path.isfile(path) or os.path.islink(path): - if remove: os.unlink(path) - display("Removed " + pathstr) - elif os.path.isdir(path) and not os.path.islink(path): - # delete everything in the dir - for e in sorted(os.listdir(path)): - p = os.path.join(path, e) - s = os.path.join(pathstr, e) - if os.path.isfile(p): - if remove: os.unlink(p) - display("Removed " + s) - else: - self.fs_delete(p, s, remove) - # then delete dir itself - if remove: os.rmdir(path) - display("Removed directory " + pathstr) - else: - errstr = "Path '%s' exists but isn't a file or directory." - raise SCons.Errors.UserError(errstr % (pathstr)) - except SCons.Errors.UserError, e: - print e - except (IOError, OSError), e: - print "scons: Could not remove '%s':" % pathstr, e.strerror - - def _get_files_to_clean(self): - result = [] - target = self.targets[0] - if target.has_builder() or target.side_effect: - result = [t for t in self.targets if not t.noclean] - return result - - def _clean_targets(self, remove=True): - target = self.targets[0] - if target in SCons.Environment.CleanTargets: - files = SCons.Environment.CleanTargets[target] - for f in files: - self.fs_delete(f.get_abspath(), str(f), remove) - - def show(self): - for t in self._get_files_to_clean(): - if not t.isdir(): - display("Removed " + str(t)) - self._clean_targets(remove=False) - - def remove(self): - for t in self._get_files_to_clean(): - try: - removed = t.remove() - except OSError, e: - # An OSError may indicate something like a permissions - # issue, an IOError would indicate something like - # the file not existing. In either case, print a - # message and keep going to try to remove as many - # targets aa possible. - print "scons: Could not remove '%s':" % str(t), e.strerror - else: - if removed: - display("Removed " + str(t)) - self._clean_targets(remove=True) - - execute = remove - - # We want the Taskmaster to update the Node states (and therefore - # handle reference counts, etc.), but we don't want to call - # back to the Node's post-build methods, which would do things - # we don't want, like store .sconsign information. - executed = SCons.Taskmaster.Task.executed_without_callbacks - - # Have the taskmaster arrange to "execute" all of the targets, because - # we'll figure out ourselves (in remove() or show() above) whether - # anything really needs to be done. - make_ready = SCons.Taskmaster.Task.make_ready_all - - def prepare(self): - pass - -class QuestionTask(SCons.Taskmaster.AlwaysTask): - """An SCons task for the -q (question) option.""" - def prepare(self): - pass - - def execute(self): - if self.targets[0].get_state() != SCons.Node.up_to_date or \ - (self.top and not self.targets[0].exists()): - global exit_status - global this_build_status - exit_status = 1 - this_build_status = 1 - self.tm.stop() - - def executed(self): - pass - - -class TreePrinter(object): - def __init__(self, derived=False, prune=False, status=False): - self.derived = derived - self.prune = prune - self.status = status - def get_all_children(self, node): - return node.all_children() - def get_derived_children(self, node): - children = node.all_children(None) - return [x for x in children if x.has_builder()] - def display(self, t): - if self.derived: - func = self.get_derived_children - else: - func = self.get_all_children - s = self.status and 2 or 0 - SCons.Util.print_tree(t, func, prune=self.prune, showtags=s) - - -def python_version_string(): - return sys.version.split()[0] - -def python_version_unsupported(version=sys.version_info): - return version < unsupported_python_version - -def python_version_deprecated(version=sys.version_info): - return version < deprecated_python_version - - -# Global variables - -print_objects = 0 -print_memoizer = 0 -print_stacktrace = 0 -print_time = 0 -sconscript_time = 0 -cumulative_command_time = 0 -exit_status = 0 # final exit status, assume success by default -this_build_status = 0 # "exit status" of an individual build -num_jobs = None -delayed_warnings = [] - -class FakeOptionParser(object): - """ - A do-nothing option parser, used for the initial OptionsParser variable. - - During normal SCons operation, the OptionsParser is created right - away by the main() function. Certain tests scripts however, can - introspect on different Tool modules, the initialization of which - can try to add a new, local option to an otherwise uninitialized - OptionsParser object. This allows that introspection to happen - without blowing up. - - """ - class FakeOptionValues(object): - def __getattr__(self, attr): - return None - values = FakeOptionValues() - def add_local_option(self, *args, **kw): - pass - -OptionsParser = FakeOptionParser() - -def AddOption(*args, **kw): - if 'default' not in kw: - kw['default'] = None - result = OptionsParser.add_local_option(*args, **kw) - return result - -def GetOption(name): - return getattr(OptionsParser.values, name) - -def SetOption(name, value): - return OptionsParser.values.set_option(name, value) - -# -class Stats(object): - def __init__(self): - self.stats = [] - self.labels = [] - self.append = self.do_nothing - self.print_stats = self.do_nothing - def enable(self, outfp): - self.outfp = outfp - self.append = self.do_append - self.print_stats = self.do_print - def do_nothing(self, *args, **kw): - pass - -class CountStats(Stats): - def do_append(self, label): - self.labels.append(label) - self.stats.append(SCons.Debug.fetchLoggedInstances()) - def do_print(self): - stats_table = {} - for s in self.stats: - for n in [t[0] for t in s]: - stats_table[n] = [0, 0, 0, 0] - i = 0 - for s in self.stats: - for n, c in s: - stats_table[n][i] = c - i = i + 1 - self.outfp.write("Object counts:\n") - pre = [" "] - post = [" %s\n"] - l = len(self.stats) - fmt1 = ''.join(pre + [' %7s']*l + post) - fmt2 = ''.join(pre + [' %7d']*l + post) - labels = self.labels[:l] - labels.append(("", "Class")) - self.outfp.write(fmt1 % tuple([x[0] for x in labels])) - self.outfp.write(fmt1 % tuple([x[1] for x in labels])) - for k in sorted(stats_table.keys()): - r = stats_table[k][:l] + [k] - self.outfp.write(fmt2 % tuple(r)) - -count_stats = CountStats() - -class MemStats(Stats): - def do_append(self, label): - self.labels.append(label) - self.stats.append(SCons.Debug.memory()) - def do_print(self): - fmt = 'Memory %-32s %12d\n' - for label, stats in zip(self.labels, self.stats): - self.outfp.write(fmt % (label, stats)) - -memory_stats = MemStats() - -# utility functions - -def _scons_syntax_error(e): - """Handle syntax errors. Print out a message and show where the error - occurred. - """ - etype, value, tb = sys.exc_info() - lines = traceback.format_exception_only(etype, value) - for line in lines: - sys.stderr.write(line+'\n') - sys.exit(2) - -def find_deepest_user_frame(tb): - """ - Find the deepest stack frame that is not part of SCons. - - Input is a "pre-processed" stack trace in the form - returned by traceback.extract_tb() or traceback.extract_stack() - """ - - tb.reverse() - - # find the deepest traceback frame that is not part - # of SCons: - for frame in tb: - filename = frame[0] - if filename.find(os.sep+'SCons'+os.sep) == -1: - return frame - return tb[0] - -def _scons_user_error(e): - """Handle user errors. Print out a message and a description of the - error, along with the line number and routine where it occured. - The file and line number will be the deepest stack frame that is - not part of SCons itself. - """ - global print_stacktrace - etype, value, tb = sys.exc_info() - if print_stacktrace: - traceback.print_exception(etype, value, tb) - filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb)) - sys.stderr.write("\nscons: *** %s\n" % value) - sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine)) - sys.exit(2) - -def _scons_user_warning(e): - """Handle user warnings. Print out a message and a description of - the warning, along with the line number and routine where it occured. - The file and line number will be the deepest stack frame that is - not part of SCons itself. - """ - etype, value, tb = sys.exc_info() - filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_tb(tb)) - sys.stderr.write("\nscons: warning: %s\n" % e) - sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine)) - -def _scons_internal_warning(e): - """Slightly different from _scons_user_warning in that we use the - *current call stack* rather than sys.exc_info() to get our stack trace. - This is used by the warnings framework to print warnings.""" - filename, lineno, routine, dummy = find_deepest_user_frame(traceback.extract_stack()) - sys.stderr.write("\nscons: warning: %s\n" % e.args[0]) - sys.stderr.write('File "%s", line %d, in %s\n' % (filename, lineno, routine)) - -def _scons_internal_error(): - """Handle all errors but user errors. Print out a message telling - the user what to do in this case and print a normal trace. - """ - print 'internal error' - traceback.print_exc() - sys.exit(2) - -def _SConstruct_exists(dirname='', repositories=[], filelist=None): - """This function checks that an SConstruct file exists in a directory. - If so, it returns the path of the file. By default, it checks the - current directory. - """ - if not filelist: - filelist = ['SConstruct', 'Sconstruct', 'sconstruct'] - for file in filelist: - sfile = os.path.join(dirname, file) - if os.path.isfile(sfile): - return sfile - if not os.path.isabs(sfile): - for rep in repositories: - if os.path.isfile(os.path.join(rep, sfile)): - return sfile - return None - -def _set_debug_values(options): - global print_memoizer, print_objects, print_stacktrace, print_time - - debug_values = options.debug - - if "count" in debug_values: - # All of the object counts are within "if track_instances:" blocks, - # which get stripped when running optimized (with python -O or - # from compiled *.pyo files). Provide a warning if __debug__ is - # stripped, so it doesn't just look like --debug=count is broken. - enable_count = False - if __debug__: enable_count = True - if enable_count: - count_stats.enable(sys.stdout) - SCons.Debug.track_instances = True - else: - msg = "--debug=count is not supported when running SCons\n" + \ - "\twith the python -O option or optimized (.pyo) modules." - SCons.Warnings.warn(SCons.Warnings.NoObjectCountWarning, msg) - if "dtree" in debug_values: - options.tree_printers.append(TreePrinter(derived=True)) - options.debug_explain = ("explain" in debug_values) - if "findlibs" in debug_values: - SCons.Scanner.Prog.print_find_libs = "findlibs" - options.debug_includes = ("includes" in debug_values) - print_memoizer = ("memoizer" in debug_values) - if "memory" in debug_values: - memory_stats.enable(sys.stdout) - print_objects = ("objects" in debug_values) - if print_objects: - SCons.Debug.track_instances = True - if "presub" in debug_values: - SCons.Action.print_actions_presub = 1 - if "stacktrace" in debug_values: - print_stacktrace = 1 - if "stree" in debug_values: - options.tree_printers.append(TreePrinter(status=True)) - if "time" in debug_values: - print_time = 1 - if "tree" in debug_values: - options.tree_printers.append(TreePrinter()) - if "prepare" in debug_values: - SCons.Taskmaster.print_prepare = 1 - if "duplicate" in debug_values: - SCons.Node.print_duplicate = 1 - -def _create_path(plist): - path = '.' - for d in plist: - if os.path.isabs(d): - path = d - else: - path = path + '/' + d - return path - -def _load_site_scons_dir(topdir, site_dir_name=None): - """Load the site_scons dir under topdir. - Prepends site_scons to sys.path, imports site_scons/site_init.py, - and prepends site_scons/site_tools to default toolpath.""" - if site_dir_name: - err_if_not_found = True # user specified: err if missing - else: - site_dir_name = "site_scons" - err_if_not_found = False - - site_dir = os.path.join(topdir, site_dir_name) - if not os.path.exists(site_dir): - if err_if_not_found: - raise SCons.Errors.UserError("site dir %s not found."%site_dir) - return - - site_init_filename = "site_init.py" - site_init_modname = "site_init" - site_tools_dirname = "site_tools" - # prepend to sys.path - sys.path = [os.path.abspath(site_dir)] + sys.path - site_init_file = os.path.join(site_dir, site_init_filename) - site_tools_dir = os.path.join(site_dir, site_tools_dirname) - if os.path.exists(site_init_file): - import imp, re - # TODO(2.4): turn this into try:-except:-finally: - try: - try: - fp, pathname, description = imp.find_module(site_init_modname, - [site_dir]) - # Load the file into SCons.Script namespace. This is - # opaque and clever; m is the module object for the - # SCons.Script module, and the exec ... in call executes a - # file (or string containing code) in the context of the - # module's dictionary, so anything that code defines ends - # up adding to that module. This is really short, but all - # the error checking makes it longer. - try: - m = sys.modules['SCons.Script'] - except Exception, e: - fmt = 'cannot import site_init.py: missing SCons.Script module %s' - raise SCons.Errors.InternalError(fmt % repr(e)) - try: - sfx = description[0] - modname = os.path.basename(pathname)[:-len(sfx)] - site_m = {"__file__": pathname, "__name__": modname, "__doc__": None} - re_special = re.compile("__[^_]+__") - for k in m.__dict__.keys(): - if not re_special.match(k): - site_m[k] = m.__dict__[k] - - # This is the magic. - exec fp in site_m - except KeyboardInterrupt: - raise - except Exception, e: - fmt = '*** Error loading site_init file %s:\n' - sys.stderr.write(fmt % repr(site_init_file)) - raise - else: - for k in site_m: - if not re_special.match(k): - m.__dict__[k] = site_m[k] - except KeyboardInterrupt: - raise - except ImportError, e: - fmt = '*** cannot import site init file %s:\n' - sys.stderr.write(fmt % repr(site_init_file)) - raise - finally: - if fp: - fp.close() - if os.path.exists(site_tools_dir): - # prepend to DefaultToolpath - SCons.Tool.DefaultToolpath.insert(0, os.path.abspath(site_tools_dir)) - -def _load_all_site_scons_dirs(topdir, verbose=None): - """Load all of the predefined site_scons dir. - Order is significant; we load them in order from most generic - (machine-wide) to most specific (topdir). - The verbose argument is only for testing. - """ - platform = SCons.Platform.platform_default() - - def homedir(d): - return os.path.expanduser('~/'+d) - - if platform == 'win32' or platform == 'cygwin': - # Note we use $ here instead of %...% because older - # pythons (prior to 2.6?) didn't expand %...% on Windows. - # This set of dirs should work on XP, Vista, 7 and later. - sysdirs=[ - os.path.expandvars('$ALLUSERSPROFILE\\Application Data\\scons'), - os.path.expandvars('$USERPROFILE\\Local Settings\\Application Data\\scons')] - appdatadir = os.path.expandvars('$APPDATA\\scons') - if appdatadir not in sysdirs: - sysdirs.append(appdatadir) - sysdirs.append(homedir('.scons')) - - elif platform == 'darwin': # MacOS X - sysdirs=['/Library/Application Support/SCons', - '/opt/local/share/scons', # (for MacPorts) - '/sw/share/scons', # (for Fink) - homedir('Library/Application Support/SCons'), - homedir('.scons')] - elif platform == 'sunos': # Solaris - sysdirs=['/opt/sfw/scons', - '/usr/share/scons', - homedir('.scons')] - else: # Linux, HPUX, etc. - # assume posix-like, i.e. platform == 'posix' - sysdirs=['/usr/share/scons', - homedir('.scons')] - - dirs=sysdirs + [topdir] - for d in dirs: - if verbose: # this is used by unit tests. - print "Loading site dir ", d - _load_site_scons_dir(d) - -def test_load_all_site_scons_dirs(d): - _load_all_site_scons_dirs(d, True) - -def version_string(label, module): - version = module.__version__ - build = module.__build__ - if build: - if build[0] != '.': - build = '.' + build - version = version + build - fmt = "\t%s: v%s, %s, by %s on %s\n" - return fmt % (label, - version, - module.__date__, - module.__developer__, - module.__buildsys__) - -def path_string(label, module): - path = module.__path__ - return "\t%s path: %s\n"%(label,path) - -def _main(parser): - global exit_status - global this_build_status - - options = parser.values - - # Here's where everything really happens. - - # First order of business: set up default warnings and then - # handle the user's warning options, so that we can issue (or - # suppress) appropriate warnings about anything that might happen, - # as configured by the user. - - default_warnings = [ SCons.Warnings.WarningOnByDefault, - SCons.Warnings.DeprecatedWarning, - ] - - for warning in default_warnings: - SCons.Warnings.enableWarningClass(warning) - SCons.Warnings._warningOut = _scons_internal_warning - SCons.Warnings.process_warn_strings(options.warn) - - # Now that we have the warnings configuration set up, we can actually - # issue (or suppress) any warnings about warning-worthy things that - # occurred while the command-line options were getting parsed. - try: - dw = options.delayed_warnings - except AttributeError: - pass - else: - delayed_warnings.extend(dw) - for warning_type, message in delayed_warnings: - SCons.Warnings.warn(warning_type, message) - - if options.diskcheck: - SCons.Node.FS.set_diskcheck(options.diskcheck) - - # Next, we want to create the FS object that represents the outside - # world's file system, as that's central to a lot of initialization. - # To do this, however, we need to be in the directory from which we - # want to start everything, which means first handling any relevant - # options that might cause us to chdir somewhere (-C, -D, -U, -u). - if options.directory: - script_dir = os.path.abspath(_create_path(options.directory)) - else: - script_dir = os.getcwd() - - target_top = None - if options.climb_up: - target_top = '.' # directory to prepend to targets - while script_dir and not _SConstruct_exists(script_dir, - options.repository, - options.file): - script_dir, last_part = os.path.split(script_dir) - if last_part: - target_top = os.path.join(last_part, target_top) - else: - script_dir = '' - - if script_dir and script_dir != os.getcwd(): - if not options.silent: - display("scons: Entering directory `%s'" % script_dir) - try: - os.chdir(script_dir) - except OSError: - sys.stderr.write("Could not change directory to %s\n" % script_dir) - - # Now that we're in the top-level SConstruct directory, go ahead - # and initialize the FS object that represents the file system, - # and make it the build engine default. - fs = SCons.Node.FS.get_default_fs() - - for rep in options.repository: - fs.Repository(rep) - - # Now that we have the FS object, the next order of business is to - # check for an SConstruct file (or other specified config file). - # If there isn't one, we can bail before doing any more work. - scripts = [] - if options.file: - scripts.extend(options.file) - if not scripts: - sfile = _SConstruct_exists(repositories=options.repository, - filelist=options.file) - if sfile: - scripts.append(sfile) - - if not scripts: - if options.help: - # There's no SConstruct, but they specified -h. - # Give them the options usage now, before we fail - # trying to read a non-existent SConstruct file. - raise SConsPrintHelpException - raise SCons.Errors.UserError("No SConstruct file found.") - - if scripts[0] == "-": - d = fs.getcwd() - else: - d = fs.File(scripts[0]).dir - fs.set_SConstruct_dir(d) - - _set_debug_values(options) - SCons.Node.implicit_cache = options.implicit_cache - SCons.Node.implicit_deps_changed = options.implicit_deps_changed - SCons.Node.implicit_deps_unchanged = options.implicit_deps_unchanged - - if options.no_exec: - SCons.SConf.dryrun = 1 - SCons.Action.execute_actions = None - if options.question: - SCons.SConf.dryrun = 1 - if options.clean: - SCons.SConf.SetBuildType('clean') - if options.help: - SCons.SConf.SetBuildType('help') - SCons.SConf.SetCacheMode(options.config) - SCons.SConf.SetProgressDisplay(progress_display) - - if options.no_progress or options.silent: - progress_display.set_mode(0) - - if options.site_dir: - _load_site_scons_dir(d.get_internal_path(), options.site_dir) - elif not options.no_site_dir: - _load_all_site_scons_dirs(d.get_internal_path()) - - if options.include_dir: - sys.path = options.include_dir + sys.path - - # If we're about to start SCons in the interactive mode, - # inform the FS about this right here. Else, the release_target_info - # method could get called on some nodes, like the used "gcc" compiler, - # when using the Configure methods within the SConscripts. - # This would then cause subtle bugs, as already happened in #2971. - if options.interactive: - SCons.Node.interactive = True - - # That should cover (most of) the options. Next, set up the variables - # that hold command-line arguments, so the SConscript files that we - # read and execute have access to them. - targets = [] - xmit_args = [] - for a in parser.largs: - if a[:1] == '-': - continue - if '=' in a: - xmit_args.append(a) - else: - targets.append(a) - SCons.Script._Add_Targets(targets + parser.rargs) - SCons.Script._Add_Arguments(xmit_args) - - # If stdout is not a tty, replace it with a wrapper object to call flush - # after every write. - # - # Tty devices automatically flush after every newline, so the replacement - # isn't necessary. Furthermore, if we replace sys.stdout, the readline - # module will no longer work. This affects the behavior during - # --interactive mode. --interactive should only be used when stdin and - # stdout refer to a tty. - if not hasattr(sys.stdout, 'isatty') or not sys.stdout.isatty(): - sys.stdout = SCons.Util.Unbuffered(sys.stdout) - if not hasattr(sys.stderr, 'isatty') or not sys.stderr.isatty(): - sys.stderr = SCons.Util.Unbuffered(sys.stderr) - - memory_stats.append('before reading SConscript files:') - count_stats.append(('pre-', 'read')) - - # And here's where we (finally) read the SConscript files. - - progress_display("scons: Reading SConscript files ...") - - start_time = time.time() - try: - for script in scripts: - SCons.Script._SConscript._SConscript(fs, script) - except SCons.Errors.StopError, e: - # We had problems reading an SConscript file, such as it - # couldn't be copied in to the VariantDir. Since we're just - # reading SConscript files and haven't started building - # things yet, stop regardless of whether they used -i or -k - # or anything else. - revert_io() - sys.stderr.write("scons: *** %s Stop.\n" % e) - sys.exit(2) - global sconscript_time - sconscript_time = time.time() - start_time - - progress_display("scons: done reading SConscript files.") - - memory_stats.append('after reading SConscript files:') - count_stats.append(('post-', 'read')) - - # Re-{enable,disable} warnings in case they disabled some in - # the SConscript file. - # - # We delay enabling the PythonVersionWarning class until here so that, - # if they explicity disabled it in either in the command line or in - # $SCONSFLAGS, or in the SConscript file, then the search through - # the list of deprecated warning classes will find that disabling - # first and not issue the warning. - #SCons.Warnings.enableWarningClass(SCons.Warnings.PythonVersionWarning) - SCons.Warnings.process_warn_strings(options.warn) - - # Now that we've read the SConscript files, we can check for the - # warning about deprecated Python versions--delayed until here - # in case they disabled the warning in the SConscript files. - if python_version_deprecated(): - msg = "Support for pre-%s Python version (%s) is deprecated.\n" + \ - " If this will cause hardship, contact scons-dev@scons.org" - deprecated_version_string = ".".join(map(str, deprecated_python_version)) - SCons.Warnings.warn(SCons.Warnings.PythonVersionWarning, - msg % (deprecated_version_string, python_version_string())) - - if not options.help: - # [ ] Clarify why we need to create Builder here at all, and - # why it is created in DefaultEnvironment - # https://bitbucket.org/scons/scons/commits/d27a548aeee8ad5e67ea75c2d19a7d305f784e30 - if SCons.SConf.NeedConfigHBuilder(): - SCons.SConf.CreateConfigHBuilder(SCons.Defaults.DefaultEnvironment()) - - # Now re-parse the command-line options (any to the left of a '--' - # argument, that is) with any user-defined command-line options that - # the SConscript files may have added to the parser object. This will - # emit the appropriate error message and exit if any unknown option - # was specified on the command line. - - parser.preserve_unknown_options = False - parser.parse_args(parser.largs, options) - - if options.help: - help_text = SCons.Script.help_text - if help_text is None: - # They specified -h, but there was no Help() inside the - # SConscript files. Give them the options usage. - raise SConsPrintHelpException - else: - print help_text - print "Use scons -H for help about command-line options." - exit_status = 0 - return - - # Change directory to the top-level SConstruct directory, then tell - # the Node.FS subsystem that we're all done reading the SConscript - # files and calling Repository() and VariantDir() and changing - # directories and the like, so it can go ahead and start memoizing - # the string values of file system nodes. - - fs.chdir(fs.Top) - - SCons.Node.FS.save_strings(1) - - # Now that we've read the SConscripts we can set the options - # that are SConscript settable: - SCons.Node.implicit_cache = options.implicit_cache - SCons.Node.FS.set_duplicate(options.duplicate) - fs.set_max_drift(options.max_drift) - - SCons.Job.explicit_stack_size = options.stack_size - - if options.md5_chunksize: - SCons.Node.FS.File.md5_chunksize = options.md5_chunksize - - platform = SCons.Platform.platform_module() - - if options.interactive: - SCons.Script.Interactive.interact(fs, OptionsParser, options, - targets, target_top) - - else: - - # Build the targets - nodes = _build_targets(fs, options, targets, target_top) - if not nodes: - revert_io() - print 'Found nothing to build' - exit_status = 2 - -def _build_targets(fs, options, targets, target_top): - - global this_build_status - this_build_status = 0 - - progress_display.set_mode(not (options.no_progress or options.silent)) - display.set_mode(not options.silent) - SCons.Action.print_actions = not options.silent - SCons.Action.execute_actions = not options.no_exec - SCons.Node.do_store_info = not options.no_exec - SCons.SConf.dryrun = options.no_exec - - if options.diskcheck: - SCons.Node.FS.set_diskcheck(options.diskcheck) - - SCons.CacheDir.cache_enabled = not options.cache_disable - SCons.CacheDir.cache_readonly = options.cache_readonly - SCons.CacheDir.cache_debug = options.cache_debug - SCons.CacheDir.cache_force = options.cache_force - SCons.CacheDir.cache_show = options.cache_show - - if options.no_exec: - CleanTask.execute = CleanTask.show - else: - CleanTask.execute = CleanTask.remove - - lookup_top = None - if targets or SCons.Script.BUILD_TARGETS != SCons.Script._build_plus_default: - # They specified targets on the command line or modified - # BUILD_TARGETS in the SConscript file(s), so if they used -u, - # -U or -D, we have to look up targets relative to the top, - # but we build whatever they specified. - if target_top: - lookup_top = fs.Dir(target_top) - target_top = None - - targets = SCons.Script.BUILD_TARGETS - else: - # There are no targets specified on the command line, - # so if they used -u, -U or -D, we may have to restrict - # what actually gets built. - d = None - if target_top: - if options.climb_up == 1: - # -u, local directory and below - target_top = fs.Dir(target_top) - lookup_top = target_top - elif options.climb_up == 2: - # -D, all Default() targets - target_top = None - lookup_top = None - elif options.climb_up == 3: - # -U, local SConscript Default() targets - target_top = fs.Dir(target_top) - def check_dir(x, target_top=target_top): - if hasattr(x, 'cwd') and not x.cwd is None: - cwd = x.cwd.srcnode() - return cwd == target_top - else: - # x doesn't have a cwd, so it's either not a target, - # or not a file, so go ahead and keep it as a default - # target and let the engine sort it out: - return 1 - d = list(filter(check_dir, SCons.Script.DEFAULT_TARGETS)) - SCons.Script.DEFAULT_TARGETS[:] = d - target_top = None - lookup_top = None - - targets = SCons.Script._Get_Default_Targets(d, fs) - - if not targets: - sys.stderr.write("scons: *** No targets specified and no Default() targets found. Stop.\n") - return None - - def Entry(x, ltop=lookup_top, ttop=target_top, fs=fs): - if isinstance(x, SCons.Node.Node): - node = x - else: - node = None - # Why would ltop be None? Unfortunately this happens. - if ltop is None: ltop = '' - # Curdir becomes important when SCons is called with -u, -C, - # or similar option that changes directory, and so the paths - # of targets given on the command line need to be adjusted. - curdir = os.path.join(os.getcwd(), str(ltop)) - for lookup in SCons.Node.arg2nodes_lookups: - node = lookup(x, curdir=curdir) - if node is not None: - break - if node is None: - node = fs.Entry(x, directory=ltop, create=1) - if ttop and not node.is_under(ttop): - if isinstance(node, SCons.Node.FS.Dir) and ttop.is_under(node): - node = ttop - else: - node = None - return node - - nodes = [_f for _f in map(Entry, targets) if _f] - - task_class = BuildTask # default action is to build targets - opening_message = "Building targets ..." - closing_message = "done building targets." - if options.keep_going: - failure_message = "done building targets (errors occurred during build)." - else: - failure_message = "building terminated because of errors." - if options.question: - task_class = QuestionTask - try: - if options.clean: - task_class = CleanTask - opening_message = "Cleaning targets ..." - closing_message = "done cleaning targets." - if options.keep_going: - failure_message = "done cleaning targets (errors occurred during clean)." - else: - failure_message = "cleaning terminated because of errors." - except AttributeError: - pass - - task_class.progress = ProgressObject - - if options.random: - def order(dependencies): - """Randomize the dependencies.""" - import random - # This is cribbed from the implementation of - # random.shuffle() in Python 2.X. - d = dependencies - for i in range(len(d)-1, 0, -1): - j = int(random.random() * (i+1)) - d[i], d[j] = d[j], d[i] - return d - else: - def order(dependencies): - """Leave the order of dependencies alone.""" - return dependencies - - if options.taskmastertrace_file == '-': - tmtrace = sys.stdout - elif options.taskmastertrace_file: - tmtrace = open(options.taskmastertrace_file, 'wb') - else: - tmtrace = None - taskmaster = SCons.Taskmaster.Taskmaster(nodes, task_class, order, tmtrace) - - # Let the BuildTask objects get at the options to respond to the - # various print_* settings, tree_printer list, etc. - BuildTask.options = options - - global num_jobs - num_jobs = options.num_jobs - jobs = SCons.Job.Jobs(num_jobs, taskmaster) - if num_jobs > 1: - msg = None - if jobs.num_jobs == 1: - msg = "parallel builds are unsupported by this version of Python;\n" + \ - "\tignoring -j or num_jobs option.\n" - elif sys.platform == 'win32': - msg = fetch_win32_parallel_msg() - if msg: - SCons.Warnings.warn(SCons.Warnings.NoParallelSupportWarning, msg) - - memory_stats.append('before building targets:') - count_stats.append(('pre-', 'build')) - - def jobs_postfunc( - jobs=jobs, - options=options, - closing_message=closing_message, - failure_message=failure_message - ): - if jobs.were_interrupted(): - if not options.no_progress and not options.silent: - sys.stderr.write("scons: Build interrupted.\n") - global exit_status - global this_build_status - exit_status = 2 - this_build_status = 2 - - if this_build_status: - progress_display("scons: " + failure_message) - else: - progress_display("scons: " + closing_message) - if not options.no_exec: - if jobs.were_interrupted(): - progress_display("scons: writing .sconsign file.") - SCons.SConsign.write() - - progress_display("scons: " + opening_message) - jobs.run(postfunc = jobs_postfunc) - - memory_stats.append('after building targets:') - count_stats.append(('post-', 'build')) - - return nodes - -def _exec_main(parser, values): - sconsflags = os.environ.get('SCONSFLAGS', '') - all_args = sconsflags.split() + sys.argv[1:] - - options, args = parser.parse_args(all_args, values) - - if isinstance(options.debug, list) and "pdb" in options.debug: - import pdb - pdb.Pdb().runcall(_main, parser) - elif options.profile_file: - # compat layer imports "cProfile" for us if it's available. - from profile import Profile - - # Some versions of Python 2.4 shipped a profiler that had the - # wrong 'c_exception' entry in its dispatch table. Make sure - # we have the right one. (This may put an unnecessary entry - # in the table in earlier versions of Python, but its presence - # shouldn't hurt anything). - try: - dispatch = Profile.dispatch - except AttributeError: - pass - else: - dispatch['c_exception'] = Profile.trace_dispatch_return - - prof = Profile() - try: - prof.runcall(_main, parser) - finally: - prof.dump_stats(options.profile_file) - else: - _main(parser) - -def main(): - global OptionsParser - global exit_status - global first_command_start - - # Check up front for a Python version we do not support. We - # delay the check for deprecated Python versions until later, - # after the SConscript files have been read, in case they - # disable that warning. - if python_version_unsupported(): - msg = "scons: *** SCons version %s does not run under Python version %s.\n" - sys.stderr.write(msg % (SCons.__version__, python_version_string())) - sys.exit(1) - - parts = ["SCons by Steven Knight et al.:\n"] - try: - import __main__ - parts.append(version_string("script", __main__)) - except (ImportError, AttributeError): - # On Windows there is no scons.py, so there is no - # __main__.__version__, hence there is no script version. - pass - parts.append(version_string("engine", SCons)) - parts.append(path_string("engine", SCons)) - parts.append("Copyright (c) 2001 - 2015 The SCons Foundation") - version = ''.join(parts) - - import SConsOptions - parser = SConsOptions.Parser(version) - values = SConsOptions.SConsValues(parser.get_default_values()) - - OptionsParser = parser - - try: - try: - _exec_main(parser, values) - finally: - revert_io() - except SystemExit, s: - if s: - exit_status = s - except KeyboardInterrupt: - print("scons: Build interrupted.") - sys.exit(2) - except SyntaxError, e: - _scons_syntax_error(e) - except SCons.Errors.InternalError: - _scons_internal_error() - except SCons.Errors.UserError, e: - _scons_user_error(e) - except SConsPrintHelpException: - parser.print_help() - exit_status = 0 - except SCons.Errors.BuildError, e: - print e - exit_status = e.exitstatus - except: - # An exception here is likely a builtin Python exception Python - # code in an SConscript file. Show them precisely what the - # problem was and where it happened. - SCons.Script._SConscript.SConscript_exception() - sys.exit(2) - - memory_stats.print_stats() - count_stats.print_stats() - - if print_objects: - SCons.Debug.listLoggedInstances('*') - #SCons.Debug.dumpLoggedInstances('*') - - if print_memoizer: - SCons.Memoize.Dump("Memoizer (memory cache) hits and misses:") - - # Dump any development debug info that may have been enabled. - # These are purely for internal debugging during development, so - # there's no need to control them with --debug= options; they're - # controlled by changing the source code. - SCons.Debug.dump_caller_counts() - SCons.Taskmaster.dump_stats() - - if print_time: - total_time = time.time() - SCons.Script.start_time - if num_jobs == 1: - ct = cumulative_command_time - else: - if last_command_end is None or first_command_start is None: - ct = 0.0 - else: - ct = last_command_end - first_command_start - scons_time = total_time - sconscript_time - ct - print "Total build time: %f seconds"%total_time - print "Total SConscript file execution time: %f seconds"%sconscript_time - print "Total SCons execution time: %f seconds"%scons_time - print "Total command execution time: %f seconds"%ct - - sys.exit(exit_status) - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/SConsOptions.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/SConsOptions.py deleted file mode 100644 index 7e458aa..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/SConsOptions.py +++ /dev/null @@ -1,1020 +0,0 @@ -# -# Copyright (c) 2001 - 2015 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/Script/SConsOptions.py rel_2.4.0:3365:9259ea1c13d7 2015/09/21 14:03:43 bdbaddog" - -import optparse -import re -import sys -import textwrap - -no_hyphen_re = re.compile(r'(\s+|(?<=[\w\!\"\'\&\.\,\?])-{2,}(?=\w))') - -try: - from gettext import gettext -except ImportError: - def gettext(message): - return message -_ = gettext - -import SCons.Node.FS -import SCons.Warnings - -OptionValueError = optparse.OptionValueError -SUPPRESS_HELP = optparse.SUPPRESS_HELP - -diskcheck_all = SCons.Node.FS.diskcheck_types() - -def diskcheck_convert(value): - if value is None: - return [] - if not SCons.Util.is_List(value): - value = value.split(',') - result = [] - for v in value: - v = v.lower() - if v == 'all': - result = diskcheck_all - elif v == 'none': - result = [] - elif v in diskcheck_all: - result.append(v) - else: - raise ValueError(v) - return result - -class SConsValues(optparse.Values): - """ - Holder class for uniform access to SCons options, regardless - of whether or not they can be set on the command line or in the - SConscript files (using the SetOption() function). - - A SCons option value can originate three different ways: - - 1) set on the command line; - 2) set in an SConscript file; - 3) the default setting (from the the op.add_option() - calls in the Parser() function, below). - - The command line always overrides a value set in a SConscript file, - which in turn always overrides default settings. Because we want - to support user-specified options in the SConscript file itself, - though, we may not know about all of the options when the command - line is first parsed, so we can't make all the necessary precedence - decisions at the time the option is configured. - - The solution implemented in this class is to keep these different sets - of settings separate (command line, SConscript file, and default) - and to override the __getattr__() method to check them in turn. - This should allow the rest of the code to just fetch values as - attributes of an instance of this class, without having to worry - about where they came from. - - Note that not all command line options are settable from SConscript - files, and the ones that are must be explicitly added to the - "settable" list in this class, and optionally validated and coerced - in the set_option() method. - """ - - def __init__(self, defaults): - self.__dict__['__defaults__'] = defaults - self.__dict__['__SConscript_settings__'] = {} - - def __getattr__(self, attr): - """ - Fetches an options value, checking first for explicit settings - from the command line (which are direct attributes), then the - SConscript file settings, then the default values. - """ - try: - return self.__dict__[attr] - except KeyError: - try: - return self.__dict__['__SConscript_settings__'][attr] - except KeyError: - return getattr(self.__dict__['__defaults__'], attr) - - settable = [ - 'clean', - 'diskcheck', - 'duplicate', - 'help', - 'implicit_cache', - 'max_drift', - 'md5_chunksize', - 'no_exec', - 'num_jobs', - 'random', - 'stack_size', - 'warn', - ] - - def set_option(self, name, value): - """ - Sets an option from an SConscript file. - """ - if not name in self.settable: - raise SCons.Errors.UserError("This option is not settable from a SConscript file: %s"%name) - - if name == 'num_jobs': - try: - value = int(value) - if value < 1: - raise ValueError - except ValueError: - raise SCons.Errors.UserError("A positive integer is required: %s"%repr(value)) - elif name == 'max_drift': - try: - value = int(value) - except ValueError: - raise SCons.Errors.UserError("An integer is required: %s"%repr(value)) - elif name == 'duplicate': - try: - value = str(value) - except ValueError: - raise SCons.Errors.UserError("A string is required: %s"%repr(value)) - if not value in SCons.Node.FS.Valid_Duplicates: - raise SCons.Errors.UserError("Not a valid duplication style: %s" % value) - # Set the duplicate style right away so it can affect linking - # of SConscript files. - SCons.Node.FS.set_duplicate(value) - elif name == 'diskcheck': - try: - value = diskcheck_convert(value) - except ValueError, v: - raise SCons.Errors.UserError("Not a valid diskcheck value: %s"%v) - if 'diskcheck' not in self.__dict__: - # No --diskcheck= option was specified on the command line. - # Set this right away so it can affect the rest of the - # file/Node lookups while processing the SConscript files. - SCons.Node.FS.set_diskcheck(value) - elif name == 'stack_size': - try: - value = int(value) - except ValueError: - raise SCons.Errors.UserError("An integer is required: %s"%repr(value)) - elif name == 'md5_chunksize': - try: - value = int(value) - except ValueError: - raise SCons.Errors.UserError("An integer is required: %s"%repr(value)) - elif name == 'warn': - if SCons.Util.is_String(value): - value = [value] - value = self.__SConscript_settings__.get(name, []) + value - SCons.Warnings.process_warn_strings(value) - - self.__SConscript_settings__[name] = value - -class SConsOption(optparse.Option): - def convert_value(self, opt, value): - if value is not None: - if self.nargs in (1, '?'): - return self.check_value(opt, value) - else: - return tuple([self.check_value(opt, v) for v in value]) - - def process(self, opt, value, values, parser): - - # First, convert the value(s) to the right type. Howl if any - # value(s) are bogus. - value = self.convert_value(opt, value) - - # And then take whatever action is expected of us. - # This is a separate method to make life easier for - # subclasses to add new actions. - return self.take_action( - self.action, self.dest, opt, value, values, parser) - - def _check_nargs_optional(self): - if self.nargs == '?' and self._short_opts: - fmt = "option %s: nargs='?' is incompatible with short options" - raise SCons.Errors.UserError(fmt % self._short_opts[0]) - - try: - _orig_CONST_ACTIONS = optparse.Option.CONST_ACTIONS - - _orig_CHECK_METHODS = optparse.Option.CHECK_METHODS - - except AttributeError: - # optparse.Option had no CONST_ACTIONS before Python 2.5. - - _orig_CONST_ACTIONS = ("store_const",) - - def _check_const(self): - if self.action not in self.CONST_ACTIONS and self.const is not None: - raise OptionError( - "'const' must not be supplied for action %r" % self.action, - self) - - # optparse.Option collects its list of unbound check functions - # up front. This sucks because it means we can't just override - # the _check_const() function like a normal method, we have to - # actually replace it in the list. This seems to be the most - # straightforward way to do that. - - _orig_CHECK_METHODS = [optparse.Option._check_action, - optparse.Option._check_type, - optparse.Option._check_choice, - optparse.Option._check_dest, - _check_const, - optparse.Option._check_nargs, - optparse.Option._check_callback] - - CHECK_METHODS = _orig_CHECK_METHODS + [_check_nargs_optional] - - CONST_ACTIONS = _orig_CONST_ACTIONS + optparse.Option.TYPED_ACTIONS - -class SConsOptionGroup(optparse.OptionGroup): - """ - A subclass for SCons-specific option groups. - - The only difference between this and the base class is that we print - the group's help text flush left, underneath their own title but - lined up with the normal "SCons Options". - """ - def format_help(self, formatter): - """ - Format an option group's help text, outdenting the title so it's - flush with the "SCons Options" title we print at the top. - """ - formatter.dedent() - result = formatter.format_heading(self.title) - formatter.indent() - result = result + optparse.OptionContainer.format_help(self, formatter) - return result - -class SConsOptionParser(optparse.OptionParser): - preserve_unknown_options = False - - def error(self, msg): - # overriden OptionValueError exception handler - self.print_usage(sys.stderr) - sys.stderr.write("SCons Error: %s\n" % msg) - sys.exit(2) - - def _process_long_opt(self, rargs, values): - """ - SCons-specific processing of long options. - - This is copied directly from the normal - optparse._process_long_opt() method, except that, if configured - to do so, we catch the exception thrown when an unknown option - is encountered and just stick it back on the "leftover" arguments - for later (re-)processing. - """ - arg = rargs.pop(0) - - # Value explicitly attached to arg? Pretend it's the next - # argument. - if "=" in arg: - (opt, next_arg) = arg.split("=", 1) - rargs.insert(0, next_arg) - had_explicit_value = True - else: - opt = arg - had_explicit_value = False - - try: - opt = self._match_long_opt(opt) - except optparse.BadOptionError: - if self.preserve_unknown_options: - # SCons-specific: if requested, add unknown options to - # the "leftover arguments" list for later processing. - self.largs.append(arg) - if had_explicit_value: - # The unknown option will be re-processed later, - # so undo the insertion of the explicit value. - rargs.pop(0) - return - raise - - option = self._long_opt[opt] - if option.takes_value(): - nargs = option.nargs - if nargs == '?': - if had_explicit_value: - value = rargs.pop(0) - else: - value = option.const - elif len(rargs) < nargs: - if nargs == 1: - if not option.choices: - self.error(_("%s option requires an argument") % opt) - else: - msg = _("%s option requires an argument " % opt) - msg += _("(choose from %s)" - % ', '.join(option.choices)) - self.error(msg) - else: - self.error(_("%s option requires %d arguments") - % (opt, nargs)) - elif nargs == 1: - value = rargs.pop(0) - else: - value = tuple(rargs[0:nargs]) - del rargs[0:nargs] - - elif had_explicit_value: - self.error(_("%s option does not take a value") % opt) - - else: - value = None - - option.process(opt, value, values, self) - - def reparse_local_options(self): - """ - Re-parse the leftover command-line options stored - in self.largs, so that any value overridden on the - command line is immediately available if the user turns - around and does a GetOption() right away. - - We mimic the processing of the single args - in the original OptionParser._process_args(), but here we - allow exact matches for long-opts only (no partial - argument names!). - - Else, this would lead to problems in add_local_option() - below. When called from there, we try to reparse the - command-line arguments that - 1. haven't been processed so far (self.largs), but - 2. are possibly not added to the list of options yet. - - So, when we only have a value for "--myargument" yet, - a command-line argument of "--myarg=test" would set it. - Responsible for this behaviour is the method - _match_long_opt(), which allows for partial matches of - the option name, as long as the common prefix appears to - be unique. - This would lead to further confusion, because we might want - to add another option "--myarg" later on (see issue #2929). - - """ - rargs = [] - largs_restore = [] - # Loop over all remaining arguments - skip = False - for l in self.largs: - if skip: - # Accept all remaining arguments as they are - largs_restore.append(l) - else: - if len(l) > 2 and l[0:2] == "--": - # Check long option - lopt = (l,) - if "=" in l: - # Split into option and value - lopt = l.split("=", 1) - - if lopt[0] in self._long_opt: - # Argument is already known - rargs.append('='.join(lopt)) - else: - # Not known yet, so reject for now - largs_restore.append('='.join(lopt)) - else: - if l == "--" or l == "-": - # Stop normal processing and don't - # process the rest of the command-line opts - largs_restore.append(l) - skip = True - else: - rargs.append(l) - - # Parse the filtered list - self.parse_args(rargs, self.values) - # Restore the list of remaining arguments for the - # next call of AddOption/add_local_option... - self.largs = self.largs + largs_restore - - def add_local_option(self, *args, **kw): - """ - Adds a local option to the parser. - - This is initiated by a SetOption() call to add a user-defined - command-line option. We add the option to a separate option - group for the local options, creating the group if necessary. - """ - try: - group = self.local_option_group - except AttributeError: - group = SConsOptionGroup(self, 'Local Options') - group = self.add_option_group(group) - self.local_option_group = group - - result = group.add_option(*args, **kw) - - if result: - # The option was added succesfully. We now have to add the - # default value to our object that holds the default values - # (so that an attempt to fetch the option's attribute will - # yield the default value when not overridden) and then - # we re-parse the leftover command-line options, so that - # any value overridden on the command line is immediately - # available if the user turns around and does a GetOption() - # right away. - setattr(self.values.__defaults__, result.dest, result.default) - self.reparse_local_options() - - return result - -class SConsIndentedHelpFormatter(optparse.IndentedHelpFormatter): - def format_usage(self, usage): - return "usage: %s\n" % usage - - def format_heading(self, heading): - """ - This translates any heading of "options" or "Options" into - "SCons Options." Unfortunately, we have to do this here, - because those titles are hard-coded in the optparse calls. - """ - if heading == 'options': - # The versions of optparse.py shipped with Pythons 2.3 and - # 2.4 pass this in uncapitalized; override that so we get - # consistent output on all versions. - heading = "Options" - if heading == 'Options': - heading = "SCons Options" - return optparse.IndentedHelpFormatter.format_heading(self, heading) - - def format_option(self, option): - """ - A copy of the normal optparse.IndentedHelpFormatter.format_option() - method. This has been snarfed so we can modify text wrapping to - out liking: - - -- add our own regular expression that doesn't break on hyphens - (so things like --no-print-directory don't get broken); - - -- wrap the list of options themselves when it's too long - (the wrapper.fill(opts) call below); - - -- set the subsequent_indent when wrapping the help_text. - """ - # The help for each option consists of two parts: - # * the opt strings and metavars - # eg. ("-x", or "-fFILENAME, --file=FILENAME") - # * the user-supplied help string - # eg. ("turn on expert mode", "read data from FILENAME") - # - # If possible, we write both of these on the same line: - # -x turn on expert mode - # - # But if the opt string list is too long, we put the help - # string on a second line, indented to the same column it would - # start in if it fit on the first line. - # -fFILENAME, --file=FILENAME - # read data from FILENAME - result = [] - - try: - opts = self.option_strings[option] - except AttributeError: - # The Python 2.3 version of optparse attaches this to - # to the option argument, not to this object. - opts = option.option_strings - - opt_width = self.help_position - self.current_indent - 2 - if len(opts) > opt_width: - wrapper = textwrap.TextWrapper(width=self.width, - initial_indent = ' ', - subsequent_indent = ' ') - wrapper.wordsep_re = no_hyphen_re - opts = wrapper.fill(opts) + '\n' - indent_first = self.help_position - else: # start help on same line as opts - opts = "%*s%-*s " % (self.current_indent, "", opt_width, opts) - indent_first = 0 - result.append(opts) - if option.help: - - try: - expand_default = self.expand_default - except AttributeError: - # The HelpFormatter base class in the Python 2.3 version - # of optparse has no expand_default() method. - help_text = option.help - else: - help_text = expand_default(option) - - # SCons: indent every line of the help text but the first. - wrapper = textwrap.TextWrapper(width=self.help_width, - subsequent_indent = ' ') - wrapper.wordsep_re = no_hyphen_re - help_lines = wrapper.wrap(help_text) - result.append("%*s%s\n" % (indent_first, "", help_lines[0])) - for line in help_lines[1:]: - result.append("%*s%s\n" % (self.help_position, "", line)) - elif opts[-1] != "\n": - result.append("\n") - return "".join(result) - - # For consistent help output across Python versions, we provide a - # subclass copy of format_option_strings() and these two variables. - # This is necessary (?) for Python2.3, which otherwise concatenates - # a short option with its metavar. - _short_opt_fmt = "%s %s" - _long_opt_fmt = "%s=%s" - - def format_option_strings(self, option): - """Return a comma-separated list of option strings & metavariables.""" - if option.takes_value(): - metavar = option.metavar or option.dest.upper() - short_opts = [] - for sopt in option._short_opts: - short_opts.append(self._short_opt_fmt % (sopt, metavar)) - long_opts = [] - for lopt in option._long_opts: - long_opts.append(self._long_opt_fmt % (lopt, metavar)) - else: - short_opts = option._short_opts - long_opts = option._long_opts - - if self.short_first: - opts = short_opts + long_opts - else: - opts = long_opts + short_opts - - return ", ".join(opts) - -def Parser(version): - """ - Returns an options parser object initialized with the standard - SCons options. - """ - - formatter = SConsIndentedHelpFormatter(max_help_position=30) - - op = SConsOptionParser(option_class=SConsOption, - add_help_option=False, - formatter=formatter, - usage="usage: scons [OPTION] [TARGET] ...",) - - op.preserve_unknown_options = True - op.version = version - - # Add the options to the parser we just created. - # - # These are in the order we want them to show up in the -H help - # text, basically alphabetical. Each op.add_option() call below - # should have a consistent format: - # - # op.add_option("-L", "--long-option-name", - # nargs=1, type="string", - # dest="long_option_name", default='foo', - # action="callback", callback=opt_long_option, - # help="help text goes here", - # metavar="VAR") - # - # Even though the optparse module constructs reasonable default - # destination names from the long option names, we're going to be - # explicit about each one for easier readability and so this code - # will at least show up when grepping the source for option attribute - # names, or otherwise browsing the source code. - - # options ignored for compatibility - def opt_ignore(option, opt, value, parser): - sys.stderr.write("Warning: ignoring %s option\n" % opt) - op.add_option("-b", "-d", "-e", "-m", "-S", "-t", "-w", - "--environment-overrides", - "--no-keep-going", - "--no-print-directory", - "--print-directory", - "--stop", - "--touch", - action="callback", callback=opt_ignore, - help="Ignored for compatibility.") - - op.add_option('-c', '--clean', '--remove', - dest="clean", default=False, - action="store_true", - help="Remove specified targets and dependencies.") - - op.add_option('-C', '--directory', - nargs=1, type="string", - dest="directory", default=[], - action="append", - help="Change to DIR before doing anything.", - metavar="DIR") - - op.add_option('--cache-debug', - nargs=1, - dest="cache_debug", default=None, - action="store", - help="Print CacheDir debug info to FILE.", - metavar="FILE") - - op.add_option('--cache-disable', '--no-cache', - dest='cache_disable', default=False, - action="store_true", - help="Do not retrieve built targets from CacheDir.") - - op.add_option('--cache-force', '--cache-populate', - dest='cache_force', default=False, - action="store_true", - help="Copy already-built targets into the CacheDir.") - - op.add_option('--cache-readonly', - dest='cache_readonly', default=False, - action="store_true", - help="Do not update CacheDir with built targets.") - - op.add_option('--cache-show', - dest='cache_show', default=False, - action="store_true", - help="Print build actions for files from CacheDir.") - - def opt_invalid(group, value, options): - errmsg = "`%s' is not a valid %s option type, try:\n" % (value, group) - return errmsg + " %s" % ", ".join(options) - - config_options = ["auto", "force" ,"cache"] - - opt_config_help = "Controls Configure subsystem: %s." \ - % ", ".join(config_options) - - op.add_option('--config', - nargs=1, choices=config_options, - dest="config", default="auto", - help = opt_config_help, - metavar="MODE") - - op.add_option('-D', - dest="climb_up", default=None, - action="store_const", const=2, - help="Search up directory tree for SConstruct, " - "build all Default() targets.") - - deprecated_debug_options = { - "dtree" : '; please use --tree=derived instead', - "nomemoizer" : ' and has no effect', - "stree" : '; please use --tree=all,status instead', - "tree" : '; please use --tree=all instead', - } - - debug_options = ["count", "duplicate", "explain", "findlibs", - "includes", "memoizer", "memory", "objects", - "pdb", "prepare", "presub", "stacktrace", - "time"] - - def opt_debug(option, opt, value__, parser, - debug_options=debug_options, - deprecated_debug_options=deprecated_debug_options): - for value in value__.split(','): - if value in debug_options: - parser.values.debug.append(value) - elif value in deprecated_debug_options.keys(): - parser.values.debug.append(value) - try: - parser.values.delayed_warnings - except AttributeError: - parser.values.delayed_warnings = [] - msg = deprecated_debug_options[value] - w = "The --debug=%s option is deprecated%s." % (value, msg) - t = (SCons.Warnings.DeprecatedDebugOptionsWarning, w) - parser.values.delayed_warnings.append(t) - else: - raise OptionValueError(opt_invalid('debug', value, debug_options)) - - opt_debug_help = "Print various types of debugging information: %s." \ - % ", ".join(debug_options) - op.add_option('--debug', - nargs=1, type="string", - dest="debug", default=[], - action="callback", callback=opt_debug, - help=opt_debug_help, - metavar="TYPE") - - def opt_diskcheck(option, opt, value, parser): - try: - diskcheck_value = diskcheck_convert(value) - except ValueError, e: - raise OptionValueError("`%s' is not a valid diskcheck type" % e) - setattr(parser.values, option.dest, diskcheck_value) - - op.add_option('--diskcheck', - nargs=1, type="string", - dest='diskcheck', default=None, - action="callback", callback=opt_diskcheck, - help="Enable specific on-disk checks.", - metavar="TYPE") - - def opt_duplicate(option, opt, value, parser): - if not value in SCons.Node.FS.Valid_Duplicates: - raise OptionValueError(opt_invalid('duplication', value, - SCons.Node.FS.Valid_Duplicates)) - setattr(parser.values, option.dest, value) - # Set the duplicate style right away so it can affect linking - # of SConscript files. - SCons.Node.FS.set_duplicate(value) - - opt_duplicate_help = "Set the preferred duplication methods. Must be one of " \ - + ", ".join(SCons.Node.FS.Valid_Duplicates) - - op.add_option('--duplicate', - nargs=1, type="string", - dest="duplicate", default='hard-soft-copy', - action="callback", callback=opt_duplicate, - help=opt_duplicate_help) - - op.add_option('-f', '--file', '--makefile', '--sconstruct', - nargs=1, type="string", - dest="file", default=[], - action="append", - help="Read FILE as the top-level SConstruct file.") - - op.add_option('-h', '--help', - dest="help", default=False, - action="store_true", - help="Print defined help message, or this one.") - - op.add_option("-H", "--help-options", - action="help", - help="Print this message and exit.") - - op.add_option('-i', '--ignore-errors', - dest='ignore_errors', default=False, - action="store_true", - help="Ignore errors from build actions.") - - op.add_option('-I', '--include-dir', - nargs=1, - dest='include_dir', default=[], - action="append", - help="Search DIR for imported Python modules.", - metavar="DIR") - - op.add_option('--implicit-cache', - dest='implicit_cache', default=False, - action="store_true", - help="Cache implicit dependencies") - - def opt_implicit_deps(option, opt, value, parser): - setattr(parser.values, 'implicit_cache', True) - setattr(parser.values, option.dest, True) - - op.add_option('--implicit-deps-changed', - dest="implicit_deps_changed", default=False, - action="callback", callback=opt_implicit_deps, - help="Ignore cached implicit dependencies.") - - op.add_option('--implicit-deps-unchanged', - dest="implicit_deps_unchanged", default=False, - action="callback", callback=opt_implicit_deps, - help="Ignore changes in implicit dependencies.") - - op.add_option('--interact', '--interactive', - dest='interactive', default=False, - action="store_true", - help="Run in interactive mode.") - - op.add_option('-j', '--jobs', - nargs=1, type="int", - dest="num_jobs", default=1, - action="store", - help="Allow N jobs at once.", - metavar="N") - - op.add_option('-k', '--keep-going', - dest='keep_going', default=False, - action="store_true", - help="Keep going when a target can't be made.") - - op.add_option('--max-drift', - nargs=1, type="int", - dest='max_drift', default=SCons.Node.FS.default_max_drift, - action="store", - help="Set maximum system clock drift to N seconds.", - metavar="N") - - op.add_option('--md5-chunksize', - nargs=1, type="int", - dest='md5_chunksize', default=SCons.Node.FS.File.md5_chunksize, - action="store", - help="Set chunk-size for MD5 signature computation to N kilobytes.", - metavar="N") - - op.add_option('-n', '--no-exec', '--just-print', '--dry-run', '--recon', - dest='no_exec', default=False, - action="store_true", - help="Don't build; just print commands.") - - op.add_option('--no-site-dir', - dest='no_site_dir', default=False, - action="store_true", - help="Don't search or use the usual site_scons dir.") - - op.add_option('--profile', - nargs=1, - dest="profile_file", default=None, - action="store", - help="Profile SCons and put results in FILE.", - metavar="FILE") - - op.add_option('-q', '--question', - dest="question", default=False, - action="store_true", - help="Don't build; exit status says if up to date.") - - op.add_option('-Q', - dest='no_progress', default=False, - action="store_true", - help="Suppress \"Reading/Building\" progress messages.") - - op.add_option('--random', - dest="random", default=False, - action="store_true", - help="Build dependencies in random order.") - - op.add_option('-s', '--silent', '--quiet', - dest="silent", default=False, - action="store_true", - help="Don't print commands.") - - op.add_option('--site-dir', - nargs=1, - dest='site_dir', default=None, - action="store", - help="Use DIR instead of the usual site_scons dir.", - metavar="DIR") - - op.add_option('--stack-size', - nargs=1, type="int", - dest='stack_size', - action="store", - help="Set the stack size of the threads used to run jobs to N kilobytes.", - metavar="N") - - op.add_option('--taskmastertrace', - nargs=1, - dest="taskmastertrace_file", default=None, - action="store", - help="Trace Node evaluation to FILE.", - metavar="FILE") - - tree_options = ["all", "derived", "prune", "status"] - - def opt_tree(option, opt, value, parser, tree_options=tree_options): - import Main - tp = Main.TreePrinter() - for o in value.split(','): - if o == 'all': - tp.derived = False - elif o == 'derived': - tp.derived = True - elif o == 'prune': - tp.prune = True - elif o == 'status': - tp.status = True - else: - raise OptionValueError(opt_invalid('--tree', o, tree_options)) - parser.values.tree_printers.append(tp) - - opt_tree_help = "Print a dependency tree in various formats: %s." \ - % ", ".join(tree_options) - - op.add_option('--tree', - nargs=1, type="string", - dest="tree_printers", default=[], - action="callback", callback=opt_tree, - help=opt_tree_help, - metavar="OPTIONS") - - op.add_option('-u', '--up', '--search-up', - dest="climb_up", default=0, - action="store_const", const=1, - help="Search up directory tree for SConstruct, " - "build targets at or below current directory.") - - op.add_option('-U', - dest="climb_up", default=0, - action="store_const", const=3, - help="Search up directory tree for SConstruct, " - "build Default() targets from local SConscript.") - - def opt_version(option, opt, value, parser): - sys.stdout.write(parser.version + '\n') - sys.exit(0) - op.add_option("-v", "--version", - action="callback", callback=opt_version, - help="Print the SCons version number and exit.") - - def opt_warn(option, opt, value, parser, tree_options=tree_options): - if SCons.Util.is_String(value): - value = value.split(',') - parser.values.warn.extend(value) - - op.add_option('--warn', '--warning', - nargs=1, type="string", - dest="warn", default=[], - action="callback", callback=opt_warn, - help="Enable or disable warnings.", - metavar="WARNING-SPEC") - - op.add_option('-Y', '--repository', '--srcdir', - nargs=1, - dest="repository", default=[], - 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 - # yet implemented" message and don't show up in the help output. - - def opt_not_yet(option, opt, value, parser): - msg = "Warning: the %s option is not yet implemented\n" % opt - sys.stderr.write(msg) - - op.add_option('-l', '--load-average', '--max-load', - nargs=1, type="float", - dest="load_average", default=0, - action="callback", callback=opt_not_yet, - # action="store", - # help="Don't start multiple jobs unless load is below " - # "LOAD-AVERAGE." - help=SUPPRESS_HELP) - op.add_option('--list-actions', - dest="list_actions", - action="callback", callback=opt_not_yet, - # help="Don't build; list files and build actions." - help=SUPPRESS_HELP) - op.add_option('--list-derived', - dest="list_derived", - action="callback", callback=opt_not_yet, - # help="Don't build; list files that would be built." - help=SUPPRESS_HELP) - op.add_option('--list-where', - dest="list_where", - action="callback", callback=opt_not_yet, - # help="Don't build; list files and where defined." - help=SUPPRESS_HELP) - op.add_option('-o', '--old-file', '--assume-old', - nargs=1, type="string", - dest="old_file", default=[], - action="callback", callback=opt_not_yet, - # action="append", - # help = "Consider FILE to be old; don't rebuild it." - help=SUPPRESS_HELP) - op.add_option('--override', - nargs=1, type="string", - action="callback", callback=opt_not_yet, - dest="override", - # help="Override variables as specified in FILE." - help=SUPPRESS_HELP) - op.add_option('-p', - action="callback", callback=opt_not_yet, - dest="p", - # help="Print internal environments/objects." - help=SUPPRESS_HELP) - op.add_option('-r', '-R', '--no-builtin-rules', '--no-builtin-variables', - action="callback", callback=opt_not_yet, - dest="no_builtin_rules", - # help="Clear default environments and variables." - help=SUPPRESS_HELP) - op.add_option('--write-filenames', - nargs=1, type="string", - dest="write_filenames", - action="callback", callback=opt_not_yet, - # help="Write all filenames examined into FILE." - help=SUPPRESS_HELP) - op.add_option('-W', '--new-file', '--assume-new', '--what-if', - nargs=1, type="string", - dest="new_file", - action="callback", callback=opt_not_yet, - # help="Consider FILE to be changed." - help=SUPPRESS_HELP) - op.add_option('--warn-undefined-variables', - dest="warn_undefined_variables", - action="callback", callback=opt_not_yet, - # help="Warn when an undefined variable is referenced." - help=SUPPRESS_HELP) - - return op - -# Local Variables: -# tab-width:4 -# indent-tabs-mode:nil -# End: -# vim: set expandtab tabstop=4 shiftwidth=4: diff --git a/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/SConscript.py b/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/SConscript.py deleted file mode 100644 index ead6f2e..0000000 --- a/3rdParty/SCons/scons-2.4.0/engine/SCons/Script/SConscript.py +++ /dev/null @@ -1,640 +0,0 @@ -"""SCons.Script.SConscript - -This module defines the Python API provided to SConscript and SConstruct -files. - -""" - -# -# Copyright (c) 2001 - 2015 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 HOLDER