diff options
31 files changed, 686 insertions, 74 deletions
diff --git a/QMTest/TestSCons.py b/QMTest/TestSCons.py index 10145be..33aa9f8 100644 --- a/QMTest/TestSCons.py +++ b/QMTest/TestSCons.py @@ -42,7 +42,7 @@ from TestCommon import __all__ # here provides some independent verification that what we packaged # conforms to what we expect. -default_version = '0.98.4' +default_version = '0.98.5' copyright_years = '2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008' @@ -83,11 +83,11 @@ In this case, your options are: -- (Optional.) Install from a pre-packaged SCons package that does not require distutils: - Red Hat Linux scons-0.98.4.noarch.rpm + Red Hat Linux scons-0.98.5.noarch.rpm Debian GNU/Linux use apt-get to get the official package - Windows scons-0.98.4.win32.exe + Windows scons-0.98.5.win32.exe -- (Recommended.) Download the latest distutils package from the following URL: @@ -159,7 +159,7 @@ And on Windows: By default, the above commands will do the following: - -- Install the version-numbered "scons-0.98.4" and "sconsign-0.98.4" + -- Install the version-numbered "scons-0.98.5" and "sconsign-0.98.5" 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 @@ -173,24 +173,24 @@ By default, the above commands will do the following: making it the default on your system. On UNIX or Linux systems, you can have the "scons" and "sconsign" - scripts be hard links or symbolic links to the "scons-0.98.4" and - "sconsign-0.98.4" scripts by specifying the "--hardlink-scons" or + scripts be hard links or symbolic links to the "scons-0.98.5" and + "sconsign-0.98.5" scripts by specifying the "--hardlink-scons" or "--symlink-scons" options on the command line. - -- Install "scons-0.98.4.bat" and "scons.bat" wrapper scripts in the + -- Install "scons-0.98.5.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-0.98.4.bat" and "scons.bat" files installed + specified to have "scons-0.98.5.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-0.98.4 or C:\Python*\scons-0.98.4, for example). + (/usr/lib/scons-0.98.5 or C:\Python*\scons-0.98.5, for example). See below for more options related to installing the build engine library. @@ -527,18 +527,18 @@ On Windows: Depending on the utilities installed on your system, any or all of the following packages will be built: - build/dist/scons-0.98.4-1.noarch.rpm - build/dist/scons-0.98.4-1.src.rpm - build/dist/scons-0.98.4.linux-i686.tar.gz - build/dist/scons-0.98.4.tar.gz - build/dist/scons-0.98.4.win32.exe - build/dist/scons-0.98.4.zip - build/dist/scons-doc-0.98.4.tar.gz - build/dist/scons-local-0.98.4.tar.gz - build/dist/scons-local-0.98.4.zip - build/dist/scons-src-0.98.4.tar.gz - build/dist/scons-src-0.98.4.zip - build/dist/scons_0.98.4-1_all.deb + build/dist/scons-0.98.5-1.noarch.rpm + build/dist/scons-0.98.5-1.src.rpm + build/dist/scons-0.98.5.linux-i686.tar.gz + build/dist/scons-0.98.5.tar.gz + build/dist/scons-0.98.5.win32.exe + build/dist/scons-0.98.5.zip + build/dist/scons-doc-0.98.5.tar.gz + build/dist/scons-local-0.98.5.tar.gz + build/dist/scons-local-0.98.5.zip + build/dist/scons-src-0.98.5.tar.gz + build/dist/scons-src-0.98.5.zip + build/dist/scons_0.98.5-1_all.deb The SConstruct file is supposed to be smart enough to avoid trying to build packages for which you don't have the proper utilities installed. @@ -9,7 +9,7 @@ copyright_years = '2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008' # This gets inserted into the man pages to reflect the month of release. -month_year = 'May 2008' +month_year = 'June 2008' # # __COPYRIGHT__ @@ -45,7 +45,7 @@ import sys import tempfile project = 'scons' -default_version = '0.98.4' +default_version = '0.98.5' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years SConsignFile() diff --git a/bin/xmlagenda.py b/bin/xmlagenda.py new file mode 100755 index 0000000..7f63d79 --- /dev/null +++ b/bin/xmlagenda.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +# Download the issues from Issuzilla as XML; this creates a file named +# 'issues.xml'. Run this script to translate 'issues.xml' into a CSV +# file named 'editlist.csv'. Upload the CSV into a Google spreadsheet. + +# In the spreadsheet, select the last column and delete it (added by the +# upload to allow for expansion; we don't need it). +# Select all the columns and pick "align-->top" +# Select the ID and votes columns and pick "align-->right" +# Select the priority column and pick "align-->center" +# Select the first row and click on the "bold" button +# Grab the lines between the column headers to adjust the column widths +# Grab the sort bar on the far left (just above the "1" for row one) +# and move it down one row. (Row one becomes a floating header) +# Voila! + +# The team members +# FIXME: These names really should be external to this script +team = 'Bill Greg Steven Gary Ken Brandon Sohail Jim'.split() +team.sort() + +# The elements to be picked out of the issue +PickList = [ + # sort key -- these are used to sort the entry + 'target_milestone', 'priority', 'votes_desc', 'creation_ts', + # payload -- these are displayed + 'issue_id', 'votes', 'issue_type', 'target_milestone', + 'priority', 'assigned_to', 'short_desc', + ] + +# Conbert a leaf element into its value as a text string +# We assume it's "short enough" that there's only one substring +def Value(element): + v = element.firstChild + if v is None: return '' + return v.nodeValue + +# Parse the XML issues file and produce a DOM for it +# FIXME: parameterize the input file name +from xml.dom.minidom import parse +xml = parse('issues.xml') + +# Go through the issues in the DOM, pick out the elements we want, +# and put them in our list of issues. +issues = [] +for issuezilla in xml.childNodes: + # The Issuezilla element contains the issues + if issuezilla.nodeType != issuezilla.ELEMENT_NODE: continue + for issue in issuezilla.childNodes: + # The issue elements contain the info for an issue + if issue.nodeType != issue.ELEMENT_NODE: continue + # Accumulate the pieces we want to include + d = {} + for element in issue.childNodes: + if element.nodeName in PickList: + d[element.nodeName] = Value(element) + # convert 'votes' to numeric, ascending and descending + try: + v = int('0' + d['votes']) + except KeyError: + pass + else: + d['votes_desc'] = -v + d['votes'] = v + # Marshal the elements and add them to the list + issues.append([ d[ix] for ix in PickList ]) +issues.sort() + +# Transcribe the issues into comma-separated values. +# FIXME: parameterize the output file name +import csv +writer = csv.writer(open('editlist.csv', 'w')) +# header +writer.writerow(['ID', 'Votes', 'Type/Member', 'Milestone', + 'Pri', 'Owner', 'Summary/Comments']) +for issue in issues: + row = issue[4:] # strip off sort key + #row[0] = """=hyperlink("http://scons.tigris.org/issues/show_bug.cgi?id=%s","%s")""" % (row[0],row[0]) + if row[3] == '-unspecified-': row[3] = 'triage' + writer.writerow(['','','','','','','']) + writer.writerow(row) + writer.writerow(['','','consensus','','','','']) + writer.writerow(['','','','','','','']) + for member in team: writer.writerow(['','',member,'','','','']) diff --git a/doc/man/scons.1 b/doc/man/scons.1 index cbc2569..a4e470f 100644 --- a/doc/man/scons.1 +++ b/doc/man/scons.1 @@ -1359,6 +1359,16 @@ method. Enables or disables warnings about missing SConscript files. .TP +--warn=fortran-cxx-mix, --warn=no-fortran-cxx-mix +Enables or disables the specific warning about linking +Fortran and C++ object files in a single executable, +which can yield unpredictable behavior with some compilers. + +.TP +--warn=link, --warn=no-link +Enables or disables warnings about link steps. + +.TP --warn=misleading-keywords, --warn=no-misleading-keywords Enables or disables warnings about use of the misspelled keywords .B targets @@ -4360,7 +4370,7 @@ Interpreted options and the construction variables they affect are as specified for the .BR env.ParseFlags () -method (which thie method calls). +method (which this method calls). See that method's description, below, for a table of options and construction variables. @@ -8434,9 +8444,9 @@ Execute(Mkdir('/tmp/outputdir')) env.Command('foo.out', 'foo.in', [Mkdir('/tmp/builddir', - Copy('$SOURCE', '/tmp/builddir') - "cd /tmp/builddir && ]) - + Copy('$SOURCE', '/tmp/builddir/foo.in') + "cd /tmp/builddir && make", + Copy('/tmp/builddir/foo.out', '$TARGET')]) .EE .TP diff --git a/doc/user/add-method.in b/doc/user/add-method.in index a0a6039..8997efb 100644 --- a/doc/user/add-method.in +++ b/doc/user/add-method.in @@ -55,7 +55,7 @@ </para> <scons_output example="ex1"> - <scons_output_command>scons -Q</scons_output_command> + <scons_output_command>scons -Q /</scons_output_command> </scons_output> <para> diff --git a/doc/user/add-method.xml b/doc/user/add-method.xml index 7e84b80..b6a597b 100644 --- a/doc/user/add-method.xml +++ b/doc/user/add-method.xml @@ -50,10 +50,11 @@ </para> <screen> - % <userinput>scons -Q</userinput> + % <userinput>scons -Q /</userinput> cc -o hello.o -c hello.c cc -o hello hello.o Install file: "hello" as "install/bin/hello" + Install file: "hello" as "/usr/bin/hello" </screen> <para> diff --git a/doc/user/builders-writing.in b/doc/user/builders-writing.in index 67a95f9..eefbb31 100644 --- a/doc/user/builders-writing.in +++ b/doc/user/builders-writing.in @@ -864,7 +864,7 @@ This functionality could be invoked as in the following example: <file name="site_scons/my_utils.py" printme=1> def build_id(): """Return a build ID (stub version)""" - return "100" + return "100" </file> <file name="SConscript"> import my_utils diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml index df3affa..6a5a7c1 100644 --- a/doc/user/builders-writing.xml +++ b/doc/user/builders-writing.xml @@ -752,7 +752,7 @@ This functionality could be invoked as in the following example: <programlisting> def build_id(): """Return a build ID (stub version)""" - return "100" + return "100" </programlisting> <para> diff --git a/src/CHANGES.txt b/src/CHANGES.txt index 17da625..4430191 100644 --- a/src/CHANGES.txt +++ b/src/CHANGES.txt @@ -8,6 +8,32 @@ +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: diff --git a/src/RELEASE.txt b/src/RELEASE.txt index 234c0ff..e5e383e 100644 --- a/src/RELEASE.txt +++ b/src/RELEASE.txt @@ -20,11 +20,39 @@ more effectively, please sign up for the scons-users mailing list at: -RELEASE 0.98.4 - Sat, 17 May 2008 22:14:46 -0700 +RELEASE 0.98.5 - Sat, 07 Jun 2008 08:20:35 -0700 This is a release candidate for SCons 1.0. Please consult the CHANGES.txt file for a list of specific changes since last release. + Please note the following important changes since release 0.98.4: + + -- scons.bat NOW RETURNS THE REAL SCONS EXIT STATUS + + The scons.bat script shipped with SCons used to exit with + a status of 1 when it detected any failed (non-zero) exit + status from the underlying Python execution of SCons itself. + The scons.bat script now exits with the actual status + returned by SCons. + + -- SCONS NOW WARNS WHEN TRYING TO LINK C++ AND FORTRAN OBJECT FILES + + Some C++ toolchains do not understand Fortran runtimes and create + unpredictable executables when linking C++ and Fortran object + files together. SCons now issues a warning if you try to link + C++ and Fortran object files into the same executable: + + scons: warning: Using $CXX to link Fortran and C++ code together. + This may generate a buggy executable if the '/usr/bin/gcc' + compiler does not know how to deal with Fortran runtimes. + + The warning may be suppressed with either the --warning=no-link + or --warning=no-fortran-cxx-mix command line options, or by + adding either of the following lines to a SConscript file: + + SetOption('warn', 'no-link') + SetOption('warn', 'no-fortran-cxx-mix') + Please note the following important changes since release 0.98: -- SCONS NO LONGER SETS THE GNU TOOLCHAIN -fPIC FLAG IN $SHCXXFLAGS diff --git a/src/engine/SCons/Node/FS.py b/src/engine/SCons/Node/FS.py index b154e34..99ae822 100644 --- a/src/engine/SCons/Node/FS.py +++ b/src/engine/SCons/Node/FS.py @@ -2150,12 +2150,14 @@ class File(Base): def Entry(self, name): """Create an entry node named 'name' relative to the SConscript directory of this file.""" - return self.cwd.Entry(name) + cwd = self.cwd or self.fs._cwd + return cwd.Entry(name) def Dir(self, name, create=True): """Create a directory node named 'name' relative to the SConscript directory of this file.""" - return self.cwd.Dir(name, create) + cwd = self.cwd or self.fs._cwd + return cwd.Dir(name, create) def Dirs(self, pathlist): """Create a list of directories relative to the SConscript @@ -2165,7 +2167,8 @@ class File(Base): def File(self, name): """Create a file node named 'name' relative to the SConscript directory of this file.""" - return self.cwd.File(name) + cwd = self.cwd or self.fs._cwd + return cwd.File(name) #def generate_build_dict(self): # """Return an appropriate dictionary of values for building diff --git a/src/engine/SCons/Script/Main.py b/src/engine/SCons/Script/Main.py index 75d0117..ec00737 100644 --- a/src/engine/SCons/Script/Main.py +++ b/src/engine/SCons/Script/Main.py @@ -195,14 +195,17 @@ class BuildTask(SCons.Taskmaster.Task): 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.Task.executed(self) elif self.options.keep_going: SCons.Taskmaster.Task.fail_continue(self) exit_status = status + this_build_status = status else: SCons.Taskmaster.Task.fail_stop(self) exit_status = status + this_build_status = status def executed(self): t = self.targets[0] @@ -384,7 +387,9 @@ class QuestionTask(SCons.Taskmaster.Task): 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): @@ -428,7 +433,8 @@ print_stacktrace = 0 print_time = 0 sconscript_time = 0 cumulative_command_time = 0 -exit_status = 0 # exit status, assume success by default +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 = [] @@ -714,6 +720,7 @@ def version_string(label, module): def _main(parser): global exit_status + global this_build_status options = parser.values @@ -727,6 +734,7 @@ def _main(parser): default_warnings = [ SCons.Warnings.CorruptSConsignWarning, SCons.Warnings.DeprecatedWarning, SCons.Warnings.DuplicateEnvironmentWarning, + SCons.Warnings.LinkWarning, SCons.Warnings.MissingSConscriptWarning, SCons.Warnings.NoMD5ModuleWarning, SCons.Warnings.NoMetaclassSupportWarning, @@ -734,6 +742,7 @@ def _main(parser): SCons.Warnings.NoParallelSupportWarning, SCons.Warnings.MisleadingKeywordsWarning, SCons.Warnings.StackSizeWarning, ] + for warning in default_warnings: SCons.Warnings.enableWarningClass(warning) SCons.Warnings._warningOut = _scons_internal_warning @@ -974,6 +983,9 @@ def _main(parser): 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 @@ -1143,9 +1155,11 @@ def _build_targets(fs, options, targets, target_top): if jobs.were_interrupted(): progress_display("scons: Build interrupted.") global exit_status + global this_build_status exit_status = 2 + this_build_status = 2 - if exit_status: + if this_build_status: progress_display("scons: " + failure_message) else: progress_display("scons: " + closing_message) diff --git a/src/engine/SCons/Tool/intelc.py b/src/engine/SCons/Tool/intelc.py index 020a6f7..d6f19c2 100644 --- a/src/engine/SCons/Tool/intelc.py +++ b/src/engine/SCons/Tool/intelc.py @@ -101,8 +101,8 @@ def check_abi(abi): valid_abis = {'ia32' : 'ia32', 'x86' : 'ia32', 'ia64' : 'ia64', - 'em64t' : 'ia32e', - 'amd64' : 'ia32e'} + 'em64t' : 'em64t', + 'amd64' : 'em64t'} if is_linux: valid_abis = {'ia32' : 'ia32', 'x86' : 'ia32', diff --git a/src/engine/SCons/Tool/link.py b/src/engine/SCons/Tool/link.py index 866df08..4522ba1 100644 --- a/src/engine/SCons/Tool/link.py +++ b/src/engine/SCons/Tool/link.py @@ -36,18 +36,27 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Defaults import SCons.Tool import SCons.Util -import SCons.Errors +import SCons.Warnings from SCons.Tool.FortranCommon import isfortran cplusplus = __import__('c++', globals(), locals(), []) +issued_mixed_link_warning = False + def smart_link(source, target, env, for_signature): has_cplusplus = cplusplus.iscplusplus(source) has_fortran = isfortran(env, source) if has_cplusplus and has_fortran: - raise SCons.Errors.InternalError( - "Sorry, scons cannot yet link c++ and fortran code together.") + global issued_mixed_link_warning + if not issued_mixed_link_warning: + msg = "Using $CXX to link Fortran and C++ code together.\n\t" + \ + "This may generate a buggy executable if the %s\n\t" + \ + "compiler does not know how to deal with Fortran runtimes." + SCons.Warnings.warn(SCons.Warnings.FortranCxxMixWarning, + msg % repr(env.subst('$CXX'))) + issued_mixed_link_warning = True + return '$CXX' elif has_fortran: return '$FORTRAN' elif has_cplusplus: diff --git a/src/engine/SCons/Tool/msvs.py b/src/engine/SCons/Tool/msvs.py index ca1b5f6..e9d73da 100644 --- a/src/engine/SCons/Tool/msvs.py +++ b/src/engine/SCons/Tool/msvs.py @@ -1393,14 +1393,12 @@ def get_msvs_install_dirs(version = None, vs8suite = None): # since version numbers aren't really floats... aa = a[1:] bb = b[1:] - aal = aa.split('.') - bbl = bb.split('.') - c = int(bbl[0]) - int(aal[0]) - if c == 0: - c = int(bbl[1]) - int(aal[1]) - if c == 0: - c = int(bbl[2]) - int(aal[2]) - return c + aal = string.split(aa, '.') + bbl = string.split(bb, '.') + # sequence comparison in python is lexicographical + # which is exactly what we want. + # Note we sort backwards so the highest version is first. + return cmp(bbl,aal) installed_framework_versions.sort(versrt) diff --git a/src/engine/SCons/Tool/sunc++.py b/src/engine/SCons/Tool/sunc++.py index 36316cb..95b4516 100644 --- a/src/engine/SCons/Tool/sunc++.py +++ b/src/engine/SCons/Tool/sunc++.py @@ -42,21 +42,37 @@ cplusplus = __import__('c++', globals(), locals(), []) # use the package installer tool lslpp to figure out where cppc and what # version of it is installed def get_cppc(env): - cppcPath = env.get('CXX', None) + cxx = env.get('CXX', None) + if cxx: + cppcPath = os.path.dirname(cxx) + else: + cppcPath = None + cppcVersion = None pkginfo = env.subst('$PKGINFO') pkgchk = env.subst('$PKGCHK') - for package in ['SPROcpl']: - cmd = "%s -l %s 2>/dev/null | grep '^ *VERSION:'" % (pkginfo, package) - line = os.popen(cmd).readline() - if line: - cppcVersion = line.split()[-1] - cmd = "%s -l %s 2>/dev/null | grep '^Pathname:.*/bin/CC$' | grep -v '/SC[0-9]*\.[0-9]*/'" % (pkgchk, package) + def look_pkg_db(pkginfo=pkginfo, pkgchk=pkgchk): + version = None + path = None + for package in ['SPROcpl']: + cmd = "%s -l %s 2>/dev/null | grep '^ *VERSION:'" % (pkginfo, package) line = os.popen(cmd).readline() - cppcPath = os.path.dirname(line.split()[-1]) - break + if line: + version = line.split()[-1] + cmd = "%s -l %s 2>/dev/null | grep '^Pathname:.*/bin/CC$' | grep -v '/SC[0-9]*\.[0-9]*/'" % (pkgchk, package) + line = os.popen(cmd).readline() + if line: + path = os.path.dirname(line.split()[-1]) + break + + return path, version + + path, version = look_pkg_db() + if path and version: + cppcPath, cppcVersion = path, version + return (cppcPath, 'CC', 'CC', cppcVersion) def generate(env): diff --git a/src/engine/SCons/Warnings.py b/src/engine/SCons/Warnings.py index c9b8a26..5af9263 100644 --- a/src/engine/SCons/Warnings.py +++ b/src/engine/SCons/Warnings.py @@ -64,6 +64,9 @@ class DeprecatedTargetSignaturesWarning(DeprecatedWarning): class DuplicateEnvironmentWarning(Warning): pass +class LinkWarning(Warning): + pass + class MisleadingKeywordsWarning(Warning): pass @@ -91,6 +94,9 @@ class ReservedVariableWarning(Warning): class StackSizeWarning(Warning): pass +class FortranCxxMixWarning(LinkWarning): + pass + _warningAsException = 0 # The below is a list of 2-tuples. The first element is a class object. diff --git a/src/script/scons.bat b/src/script/scons.bat index 56443c8..f0ffa9a 100644 --- a/src/script/scons.bat +++ b/src/script/scons.bat @@ -1,20 +1,31 @@ @REM __COPYRIGHT__
@REM __FILE__ __REVISION__ __DATE__ __DEVELOPER__
@echo off
+set SCONS_ERRORLEVEL=
if "%OS%" == "Windows_NT" goto WinNT
-REM for 9x/Me you better not have more than 9 args
+
+@REM for 9x/Me you better not have more than 9 args
python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %1 %2 %3 %4 %5 %6 %7 %8 %9
@REM no way to set exit status of this script for 9x/Me
goto endscons
+
+@REM Credit where credit is due: we return the exit code despite our
+@REM use of setlocal+endlocal using a technique from Bear's Journal:
+@REM http://code-bear.com/bearlog/2007/06/01/getting-the-exit-code-from-a-batch-file-that-is-run-from-a-python-program/
+
:WinNT
setlocal
@REM ensure the script will be executed with the Python it was installed for
set path=%~dp0;%~dp0..;%path%
python -c "from os.path import join; import sys; sys.path = [ join(sys.prefix, 'Lib', 'site-packages', 'scons-__VERSION__'), join(sys.prefix, 'Lib', 'site-packages', 'scons'), join(sys.prefix, 'scons-__VERSION__'), join(sys.prefix, 'scons')] + sys.path; import SCons.Script; SCons.Script.main()" %*
-if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto endsconsnt
+endlocal & set SCONS_ERRORLEVEL=%ERRORLEVEL%
+
+if NOT "%COMSPEC%" == "%SystemRoot%\system32\cmd.exe" goto returncode
if errorlevel 9009 echo you do not have python in your PATH
-@REM color 00 causes this script to exit with non-zero exit status
-if errorlevel 1 color 00
-:endsconsnt
-endlocal
+goto endscons
+
+:returncode
+exit /B %SCONS_ERRORLEVEL%
+
:endscons
+call :returncode %SCONS_ERRORLEVEL%
diff --git a/src/setup.py b/src/setup.py index 5b2212c..b49a7af 100644 --- a/src/setup.py +++ b/src/setup.py @@ -210,9 +210,22 @@ def get_scons_prefix(libdir, is_win32): return os.path.join(drive + head) return libdir +def force_to_usr_local(self): + """ + A hack to decide if we need to "force" the installation directories + to be under /usr/local. This is because Mac Os X Tiger and + Leopard, by default, put the libraries and scripts in their own + directories under /Library or /System/Library. + """ + return (sys.platform[:6] == 'darwin' and + (self.install_dir[:9] == '/Library/' or + self.install_dir[:16] == '/System/Library/')) + class install_lib(_install_lib): def finalize_options(self): _install_lib.finalize_options(self) + if force_to_usr_local(self): + self.install_dir = '/usr/local/lib' args = self.distribution.script_args if not set_explicitly("lib", args): # They didn't explicitly specify the installation @@ -233,6 +246,8 @@ class install_lib(_install_lib): class install_scripts(_install_scripts): def finalize_options(self): _install_scripts.finalize_options(self) + if force_to_usr_local(self): + self.install_dir = '/usr/local/bin' self.build_dir = os.path.join('build', 'scripts') msg = "Installed SCons scripts into %s" % self.install_dir Installed.append(msg) @@ -332,6 +347,8 @@ class install_data(_install_data): _install_data.initialize_options(self) def finalize_options(self): _install_data.finalize_options(self) + if force_to_usr_local(self): + self.install_dir = '/usr/local' if Options.install_man: if is_win32: dir = 'Doc' diff --git a/test/CXX/CCFLAGS.py b/test/CXX/CCFLAGS.py index a867340..deaa2b6 100644 --- a/test/CXX/CCFLAGS.py +++ b/test/CXX/CCFLAGS.py @@ -51,7 +51,7 @@ test.write('prog.cpp', r""" int main(int argc, char *argv[]) { - argv[argc++] = "--"; + argv[argc++] = (char *)"--"; #ifdef FOO printf("prog.c: FOO\n"); #endif diff --git a/test/CXX/CXXFILESUFFIX.py b/test/CXX/CXXFILESUFFIX.py index fbc34ff..d2a70c3 100644 --- a/test/CXX/CXXFILESUFFIX.py +++ b/test/CXX/CXXFILESUFFIX.py @@ -62,7 +62,7 @@ input = r""" int main(int argc, char *argv[]) { - argv[argc++] = "--"; + argv[argc++] = (char *)"--"; printf("LEX\n"); printf("%s\n"); exit (0); diff --git a/test/CXX/CXXFLAGS.py b/test/CXX/CXXFLAGS.py index 86f14f0..f37cdbb 100644 --- a/test/CXX/CXXFLAGS.py +++ b/test/CXX/CXXFLAGS.py @@ -120,7 +120,7 @@ test.write('prog.cpp', r""" int main(int argc, char *argv[]) { - argv[argc++] = "--"; + argv[argc++] = (char *)"--"; #ifdef FOO printf("prog.c: FOO\n"); #endif diff --git a/test/File.py b/test/File.py index 6f634cf..583e6b4 100644 --- a/test/File.py +++ b/test/File.py @@ -25,9 +25,11 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ -Verify that the File() global function and environment method work -correctly, and that the former does not try to expand construction -variables. +Verify that: + + -- the File() global function and environment method work correctly; + -- the former does not try to expand construction variables; + -- calling File() as a method of a File() object works correctly. """ import TestSCons @@ -42,17 +44,25 @@ print File('${BAR}_$BAR') print env.File('eee') print env.File('$FOO') print env.File('${BAR}_$BAR') +f1 = env.File('f1') +print f1 +f2 = f1.File('f2') +print f2 """) -test.run(stdout = test.wrap_stdout(read_str = """\ +expect = test.wrap_stdout(read_str = """\ ddd $FOO ${BAR}_$BAR eee fff bbb_bbb +f1 +f2 """, build_str = """\ scons: `.' is up to date. -""")) +""") + +test.run(stdout = expect) test.pass_test() diff --git a/test/Fortran/link-with-cxx.py b/test/Fortran/link-with-cxx.py new file mode 100644 index 0000000..6c05ae1 --- /dev/null +++ b/test/Fortran/link-with-cxx.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify the warnings message used when attempting to link C++ and +Fortran object files, and the ability to suppress them with the +right --warn= options. +""" + +import re + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons(match = TestSCons.match_re) + + +test.write('test_linker.py', r""" +import sys +outfile = open(sys.argv[2], 'wb') +for infile in sys.argv[3:]: + outfile.write(open(infile, 'rb').read()) +outfile.close() +sys.exit(0) +""") + + +test.write('test_fortran.py', r""" +import sys +outfile = open(sys.argv[2], 'wb') +for infile in sys.argv[4:]: + outfile.write(open(infile, 'rb').read()) +outfile.close() +sys.exit(0) +""") + + +test.write('SConstruct', """ +def copier(target, source, env): + s = str(source[0]) + t = str(target[0]) + open(t, 'wb').write(open(s, 'rb').read()) +env = Environment(CXX = r'%(_python_)s test_linker.py', + CXXCOM = Action(copier), + # We want to re-define this as follows (so as to + # not rely on a real Fortran compiler) but can't + # because $FORTRANCOM is defined with an extra space + # so it ends up as a CommandAction, not a LazyAction. + # Must look into changing that after 1.0 is out. + #FORTRANCOM = Action(copier)) + FORTRAN = r'%(_python_)s test_fortran.py') +env.Program('prog1.exe', ['f1.cpp', 'f2.f']) +env.Program('prog2.exe', ['f1.cpp', 'f2.f']) +if ARGUMENTS.get('NO_LINK'): + # Can remove no-deprecated when we drop Python1.5 + SetOption('warn', ['no-link', 'no-deprecated']) +if ARGUMENTS.get('NO_MIX'): + # Can remove no-deprecated when we drop Python1.5 + SetOption('warn', ['no-fortran-cxx-mix', 'no-deprecated']) +""" % locals()) + +test.write('f1.cpp', "f1.cpp\n") +test.write('f2.f', "f2.f\n") + +expect = (""" +scons: warning: Using \\$CXX to link Fortran and C\\+\\+ code together. +\tThis may generate a buggy executable if the '%s test_linker.py' +\tcompiler does not know how to deal with Fortran runtimes. +""" % re.escape(_python_)) + TestSCons.file_expr + +test.run(arguments = '.', stderr=expect) + +test.must_match('prog1.exe', "f1.cpp\nf2.f\n") +test.must_match('prog2.exe', "f1.cpp\nf2.f\n") + +test.run(arguments = '-c .', stderr=expect) + +test.must_not_exist('prog1.exe') +test.must_not_exist('prog2.exe') + +test.run(arguments = '--warning=no-link .') + +test.must_match('prog1.exe', "f1.cpp\nf2.f\n") +test.must_match('prog2.exe', "f1.cpp\nf2.f\n") + +test.run(arguments = '-c .', stderr=expect) + +test.must_not_exist('prog1.exe') +test.must_not_exist('prog2.exe') + +test.run(arguments = '--warning=no-fortran-cxx-mix .') + +test.must_match('prog1.exe', "f1.cpp\nf2.f\n") +test.must_match('prog2.exe', "f1.cpp\nf2.f\n") + +test.run(arguments = '-c .', stderr=expect) + +test.must_not_exist('prog1.exe') +test.must_not_exist('prog2.exe') + +test.run(arguments = 'NO_LINK=1 .') + +test.must_match('prog1.exe', "f1.cpp\nf2.f\n") +test.must_match('prog2.exe', "f1.cpp\nf2.f\n") + +test.run(arguments = '-c .', stderr=expect) + +test.must_not_exist('prog1.exe') +test.must_not_exist('prog2.exe') + +test.run(arguments = 'NO_MIX=1 .') + +test.must_match('prog1.exe', "f1.cpp\nf2.f\n") +test.must_match('prog2.exe', "f1.cpp\nf2.f\n") + +test.pass_test() diff --git a/test/Interactive/failure.py b/test/Interactive/failure.py new file mode 100644 index 0000000..75f460f --- /dev/null +++ b/test/Interactive/failure.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +""" +Verify that when a build fails, later builds correctly report +that their builds succeeded, and that we don't get "stuck" on +reporting the earlier build failure. +""" + +import TestSCons + +test = TestSCons.TestSCons() + +test.write('SConstruct', """\ +def fail(target, source, env): + return 1 +Command('f1.out', 'f1.in', Action(fail)) +Command('f2.out', 'f2.in', Copy('$TARGET', '$SOURCE')) +Command('1', [], Touch('$TARGET')) +Command('2', [], Touch('$TARGET')) +Command('3', [], Touch('$TARGET')) +Command('4', [], Touch('$TARGET')) +""") + +test.write('f1.in', "f1.in 1\n") +test.write('f2.in', "f2.in 1\n") + + + +scons = test.start(arguments = '--interactive') + +scons.send("build f1.out\n") + +scons.send("build 1\n") + +test.wait_for(test.workpath('1')) + +test.must_not_exist(test.workpath('f1.out')) + + + +scons.send("build f2.out\n") + +scons.send("build 2\n") + +test.wait_for(test.workpath('2')) + +test.must_match(test.workpath('f2.out'), "f2.in 1\n") + + + +scons.send("build f1.out\n") + +scons.send("build 3\n") + +test.wait_for(test.workpath('3')) + +test.must_not_exist(test.workpath('f1.out')) + + + +test.write('f2.in', "f2.in 2\n") + +scons.send("build f2.out\n") + +scons.send("build 4\n") + +test.wait_for(test.workpath('4')) + +test.must_match(test.workpath('f2.out'), "f2.in 2\n") + + + +expect_stdout = """\ +scons: Reading SConscript files ... +scons: done reading SConscript files. +scons>>> scons: Building targets ... +fail(["f1.out"], ["f1.in"]) +scons: building terminated because of errors. +scons: Clearing cached node information ... +scons: done clearing node information. +scons>>> scons: Building targets ... +Touch("1") +scons: done building targets. +scons: Clearing cached node information ... +scons: done clearing node information. +scons>>> scons: Building targets ... +Copy("f2.out", "f2.in") +scons: done building targets. +scons: Clearing cached node information ... +scons: done clearing node information. +scons>>> scons: Building targets ... +Touch("2") +scons: done building targets. +scons: Clearing cached node information ... +scons: done clearing node information. +scons>>> scons: Building targets ... +fail(["f1.out"], ["f1.in"]) +scons: building terminated because of errors. +scons: Clearing cached node information ... +scons: done clearing node information. +scons>>> scons: Building targets ... +Touch("3") +scons: done building targets. +scons: Clearing cached node information ... +scons: done clearing node information. +scons>>> scons: Building targets ... +Copy("f2.out", "f2.in") +scons: done building targets. +scons: Clearing cached node information ... +scons: done clearing node information. +scons>>> scons: Building targets ... +Touch("4") +scons: done building targets. +scons: Clearing cached node information ... +scons: done clearing node information. +scons>>> +""" + +expect_stderr = """\ +scons: *** [f1.out] Error 1 +scons: *** [f1.out] Error 1 +""" + +test.finish(scons, stdout = expect_stdout, stderr = expect_stderr) + + + +test.pass_test() diff --git a/test/KeyboardInterrupt.py b/test/KeyboardInterrupt.py index 5a06119..d5010dd 100644 --- a/test/KeyboardInterrupt.py +++ b/test/KeyboardInterrupt.py @@ -114,3 +114,5 @@ for i in range(2): runtest('-j16 --random') runtest('-j32 --random') runtest('-j64 --random') + +test.pass_test() diff --git a/test/default-drive.py b/test/Win32/default-drive.py index a57cde7..94d8377 100644 --- a/test/default-drive.py +++ b/test/Win32/default-drive.py @@ -40,7 +40,8 @@ import TestSCons test = TestSCons.TestSCons() if sys.platform != 'win32': - test.pass_test() + msg = "Skipping drive-letter test on non-Windows platform '%s'\n" % sys.platform + test.skip_test(msg) test.subdir('src') diff --git a/test/mingw.py b/test/Win32/mingw.py index fac8910..fac8910 100644 --- a/test/mingw.py +++ b/test/Win32/mingw.py diff --git a/test/Win32/scons-bat-error.py b/test/Win32/scons-bat-error.py new file mode 100644 index 0000000..d39858b --- /dev/null +++ b/test/Win32/scons-bat-error.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python +# +# __COPYRIGHT__ +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +""" +Verify that the scons.bat file returns error codes as we expect. +""" + +__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" + +import os +import sys + +import TestSCons + +test = TestSCons.TestSCons() + +if sys.platform != 'win32': + msg = "Skipping scons.bat test on non-Windows platform '%s'\n" % sys.platform + test.skip_test(msg) + +python = test.where_is('python') + +if not python: + msg = "Skipping scons.bat test; python is not on %PATH%.\n" + test.skip_test(msg) + +scons_bat = os.path.splitext(test.program)[0] + '.bat' + +if not os.path.exists(scons_bat): + msg = "Skipping scons.bat test; %s does not exist.\n" % scons_bat + test.skip_test(msg) + +test.write('scons.bat', test.read(scons_bat)) + +# The scons.bat file tries to import SCons.Script from its sys.prefix +# directories first (i.e., site-packages) which means this test might +# end up using an installed SCons in preference to something local. +# If so, create a SConstruct file that will exit with our expected +# error status. If there is *not* an installed SCons, we still want +# this test to work, so we make a "SCons" package in the local +# directory with a Script.py module that contains a main() function +# that just exits with the expected status. + +test.subdir('SCons') + +test.write(['SCons', '__init__.py'], "") + +test.write(['SCons', 'Script.py'], """\ +import sys +def main(): + sys.exit(7) +""") + +test.write('SConstruct', """\ +import sys +sys.exit(7) +""") + +test.run(program = 'scons.bat', status = 7) + + + +test.pass_test() diff --git a/test/win32pathmadness.py b/test/Win32/win32pathmadness.py index df350eb..df350eb 100644 --- a/test/win32pathmadness.py +++ b/test/Win32/win32pathmadness.py |