summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Deegan <bill@baddogconsulting.com>2023-01-23 11:18:15 -0800
committerGitHub <noreply@github.com>2023-01-23 11:18:15 -0800
commit5f8809c94126383295aa701511643a3bbb0a5c1d (patch)
tree53473aa6844ed74ba922606e2cfcec110e368f7f
parent0c2cdf3e2202360d37a3d93b047a67f6e92505bb (diff)
parent1dcd4345669dab44309f0bbc7569628d9d3172e0 (diff)
downloadscons-git-5f8809c94126383295aa701511643a3bbb0a5c1d.tar.gz
Merge branch 'master' into doc/msvs
-rw-r--r--.appveyor.yml47
-rw-r--r--.appveyor/exclude_tests.ps1 (renamed from .appveyor/disable_msvc_10.ps1)3
-rw-r--r--.appveyor/install-cov.bat2
-rw-r--r--.appveyor/install.bat9
-rw-r--r--CHANGES.txt21
-rw-r--r--RELEASE.txt11
-rw-r--r--SCons/ActionTests.py18
-rw-r--r--SCons/CacheDir.py40
-rw-r--r--SCons/Scanner/Java.py9
-rw-r--r--SCons/Scanner/JavaTests.py64
-rw-r--r--SCons/Tool/fortran.xml8
-rw-r--r--SCons/Tool/gfortran.py23
-rw-r--r--SCons/Tool/javac.py4
-rw-r--r--SCons/Tool/javac.xml28
-rw-r--r--SCons/Tool/linkCommon/__init__.py13
-rw-r--r--SCons/Tool/msvc.xml305
-rw-r--r--requirements-dev.txt4
-rw-r--r--requirements-pkg.txt2
-rw-r--r--setup.cfg2
-rw-r--r--test/Fortran/F95FLAGS.py72
-rw-r--r--test/Fortran/SHF95FLAGS.py69
-rw-r--r--test/Fortran/link-with-cxx.py57
-rw-r--r--test/Java/JAVAPROCESSORPATH.py95
-rw-r--r--test/Java/inner-cacheable-live.py77
-rw-r--r--test/rebuild-generated.py2
25 files changed, 740 insertions, 245 deletions
diff --git a/.appveyor.yml b/.appveyor.yml
index 030212249..a8db5e9f9 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -17,31 +17,33 @@ cache:
- C:\ProgramData\chocolatey\lib -> appveyor.yml
install:
- # add python and python user-base to path for pip installs
+ # direct choco install supposed to work, but not? still doing in install.bat
+ #- cinst: dmd ldc swig vswhere ixsltproc winflexbison3
- cmd: .\.appveyor\install.bat
+ - cmd: if %COVERAGE% equ 1 .\.appveyor\install-cov.bat
-# build matrix will be number of images multiplied by each '-' below,
-# less any exclusions.
-# split builds into sets of four jobs due to appveyor per-job time limit
-# Leaving the Coverage build on VS2017 for build-time reasons (1hr time limit)
-# Maybe move this one somewhere else in future to restore some flexibility.
+# Build matrix will be number of images multiplied by #entries in matrix:,
+# less any excludes.
+#
+# "Build" is kind of a misnomer - we are actually running the test suite,
+# and this is slow on Windows, so keep the matrix as small as possible.
+# Leaving the Coverage build on VS2017 for build-time reasons (1hr time limit).
+# maybe move coverage to github in future to restore some flexibility?
environment:
+ COVERAGE: 0
+ SCONS_CACHE_MSVC_CONFIG: "true"
matrix:
-
+ # Test oldest and newest supported Pythons, and a subset in between.
+ # Skipping 3.7 and 3.9 at this time
- WINPYTHON: "Python311"
- COVERAGE: 0
- WINPYTHON: "Python310"
- COVERAGE: 0
- WINPYTHON: "Python38"
- COVERAGE: 0
-
+
- WINPYTHON: "Python36"
COVERAGE: 1
- # skipping 3.7 and 3.9 at this time
-
# remove sets of build jobs based on criteria below
# to fine tune the number and platforms tested
matrix:
@@ -68,21 +70,23 @@ matrix:
- image: Visual Studio 2022
WINPYTHON: "Python38"
-# remove some binaries we don't want to be found
+# Remove some binaries we don't want to be found
+# Note this is no longer needed, git-windows bin/ is quite minimal now.
before_build:
- ps: .\.appveyor\ignore_git_bins.ps1
build: off
build_script:
-
- # exclude VS 10.0 because it hangs the testing until this is resolved:
- # https://help.appveyor.com/discussions/problems/19283-visual-studio-2010-trial-license-has-expired
- - ps: .\.appveyor\disable_msvc_10.ps1
+ # Image version-based excludes:
+ # No excludes at the moment, but the exclude script generates the
+ # (possibly empty) exclude_list.txt which is used in the following step,
+ # so leave the scheme in place in case we need to put back excludes later.
+ - ps: .\.appveyor\exclude_tests.ps1
# setup coverage by creating the coverage config file, and adding coverage
# to the sitecustomize so that all python processes start with coverage
- - ps: .\.appveyor\coverage_setup.ps1
+ - ps: if ($env:COVERAGE -eq 1) { .\.appveyor\coverage_setup.ps1 }
# NOTE: running powershell from cmd is intended because
# it formats the output correctly
@@ -90,8 +94,7 @@ build_script:
# run coverage even if there was a test failure
on_finish:
- - ps: .\.appveyor\coverage_report.ps1
- # running codecov in powershell causes an error so running in platform
- # shells
+ - ps: if ($env:COVERAGE -eq 1) { .\.appveyor\coverage_report.ps1 }
+ # running codecov in powershell causes an error so running in cmd
- cmd: if %COVERAGE% equ 1 codecov -X gcov --file coverage_xml.xml
diff --git a/.appveyor/disable_msvc_10.ps1 b/.appveyor/exclude_tests.ps1
index 086f1e4b4..6006a5cb5 100644
--- a/.appveyor/disable_msvc_10.ps1
+++ b/.appveyor/exclude_tests.ps1
@@ -1,4 +1,7 @@
New-Item -Name exclude_list.txt -ItemType File;
+
+# exclude VS 10.0 because it hangs the testing until this is resolved:
+# https://help.appveyor.com/discussions/problems/19283-visual-studio-2010-trial-license-has-expired
$workaround_image = "Visual Studio 2015";
if ($env:APPVEYOR_BUILD_WORKER_IMAGE -eq $workaround_image) {
Add-Content -Path 'exclude_list.txt' -Value 'test\MSVS\vs-10.0-exec.py';
diff --git a/.appveyor/install-cov.bat b/.appveyor/install-cov.bat
new file mode 100644
index 000000000..7dbc9457e
--- /dev/null
+++ b/.appveyor/install-cov.bat
@@ -0,0 +1,2 @@
+for /F "tokens=*" %%g in ('C:\\%WINPYTHON%\\python.exe -c "import sys; print(sys.path[-1])"') do (set PYSITEDIR=%%g)
+C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off coverage codecov
diff --git a/.appveyor/install.bat b/.appveyor/install.bat
index b014dc711..95f51155f 100644
--- a/.appveyor/install.bat
+++ b/.appveyor/install.bat
@@ -1,12 +1,13 @@
C:\\%WINPYTHON%\\python.exe --version
for /F "tokens=*" %%g in ('C:\\%WINPYTHON%\\python.exe -c "import sys; print(sys.path[-1])"') do (set PYSITEDIR=%%g)
REM use mingw 32 bit until #3291 is resolved
+REM add python and python user-base to path for pip installs
set PATH=C:\\%WINPYTHON%;C:\\%WINPYTHON%\\Scripts;C:\\ProgramData\\chocolatey\\bin;C:\\MinGW\\bin;C:\\MinGW\\msys\\1.0\\bin;C:\\cygwin\\bin;C:\\msys64\\usr\\bin;C:\\msys64\\mingw64\\bin;%PATH%
C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off pip setuptools wheel
-C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off coverage codecov
-set STATIC_DEPS=true & C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off lxml
+
+REM requirements-dev.txt will skip installing lxml for windows and py 3.11+, where there's
+REM no current binary wheel
C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off -r requirements-dev.txt
-REM install 3rd party tools to test with
+
choco install --allow-empty-checksums dmd ldc swig vswhere xsltproc winflexbison3
-set SCONS_CACHE_MSVC_CONFIG=true
set
diff --git a/CHANGES.txt b/CHANGES.txt
index ecc82a497..07f0022ed 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -42,6 +42,10 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
command lines using the generated tempfile for long command lines, instead of the full command line for
the compilation step for the source/target pair.
+ From David H:
+ - Added JAVAPROCESSORPATH construction variable which populates -processorpath.
+ - Updated JavaScanner to scan JAVAPROCESSORPATH.
+
From Dan Mezhiborsky:
- Add newline to end of compilation db (compile_commands.json).
@@ -98,7 +102,22 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
over 2100 lines.
- Add a zipapp package of scons-local: can use SCons from a local
file which does not need unpacking.
-
+ - Fix a problem (present in 4.4.0 only) where a Java inner class could
+ not be cached because the emitted filename contained a '$' and when
+ looked up through a node ended up generating a Python SyntaxError
+ because it was passed through scons_subst().
+ - Have the gfortran tool do a better job of honoring user preferences
+ for the dialect tools (F77, F90, F03 and F09, as well as the shared-library
+ equivalents SHF77, SHF90, SHF03, SHF09). Previously these were
+ unconditionally overwritten to 'gfortran'; the change should be more
+ in line with expectations of how these variables should work.
+ Also cleaned a few Fortran tests - test behavior does not change.
+ - Updated MSVC documentation - adds "version added" annotations on recently
+ added construction variables and provides a version-mapping table.
+ - Add Python 3.12 support, and indicate 3.11/3.12 support in package.
+ 3.12 is in alpha for this SCons release, the bytecode sequences
+ embedded in SCons/ActionTests.py may need to change later, but
+ based on what is known now, 3.12 itself should work with this release.
RELEASE 4.4.0 - Sat, 30 Jul 2022 14:08:29 -0700
diff --git a/RELEASE.txt b/RELEASE.txt
index 0ffe50b86..302e49468 100644
--- a/RELEASE.txt
+++ b/RELEASE.txt
@@ -43,6 +43,7 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY
octal modes using the modern Python syntax (0o755 rather than 0755).
- Migrated logging logic for --taskmastertrace to use Python's logging module. Added logging
to NewParallel Job class (Andrew Morrow's new parallel job implementation)
+- Preliminary support for Python 3.12.
FIXES
@@ -69,6 +70,14 @@ FIXES
- Fixed Issue #4275 - when outputting compilation db and TEMPFILE was in use, the compilation db would have
command lines using the generated tempfile for long command lines, instead of the full command line for
the compilation step for the source/target pair.
+- A refactor in the caching logic for version 4.4.0 left Java inner classes
+ failing with an exception when a CacheDir was enabled. This is now corrected.
+- When using the gfortran tool (the default on most platforms as long as a GNU
+ toolchain is installed), the user setting of the "dialect" compilers
+ (F77, F90, F03 and F09, as well as the shared-library equivalents SHF77,
+ SHF90, SHF03, SHF09) is now honored; previously the tool overwrote the
+ settings to 'gfortran', which made it difficult reference a cross-compile
+ version for dialects.
IMPROVEMENTS
@@ -116,6 +125,8 @@ DOCUMENTATION
explanation, and the introduction of terms like "out of tree" that
may help in forming a mental model.
- Additional explanations for MSVSProject and MSVSSolution builders.
+- Updated MSVC documentation - adds "version added" annotations on recently
+ added construction variables and provides a version-mapping table.
DEVELOPMENT
-----------
diff --git a/SCons/ActionTests.py b/SCons/ActionTests.py
index 101953bd6..88bb36fc2 100644
--- a/SCons/ActionTests.py
+++ b/SCons/ActionTests.py
@@ -1541,6 +1541,7 @@ class CommandGeneratorActionTestCase(unittest.TestCase):
(3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 11): bytearray(b'0, 0, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
+ (3, 12): bytearray(b'0, 0, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
}
meth_matches = [
@@ -1719,6 +1720,7 @@ class FunctionActionTestCase(unittest.TestCase):
(3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 11): bytearray(b'0, 0, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
+ (3, 12): bytearray(b'0, 0, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
}
@@ -1730,6 +1732,7 @@ class FunctionActionTestCase(unittest.TestCase):
(3, 9): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 10): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 11): bytearray(b'1, 1, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
+ (3, 12): bytearray(b'1, 1, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
}
def factory(act, **kw):
@@ -1974,6 +1977,7 @@ class LazyActionTestCase(unittest.TestCase):
(3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'),
(3, 11): bytearray(b'0, 0, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
+ (3, 12): bytearray(b'0, 0, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()'),
}
meth_matches = [
@@ -2039,6 +2043,7 @@ class ActionCallerTestCase(unittest.TestCase):
(3, 9): b'd\x00S\x00',
(3, 10): b'd\x00S\x00',
(3, 11): b'\x97\x00d\x00S\x00',
+ (3, 12): b'\x97\x00d\x00S\x00',
}
af = SCons.Action.ActionFactory(GlobalFunc, strfunc)
@@ -2250,6 +2255,7 @@ class ObjectContentsTestCase(unittest.TestCase):
bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()'),
), # 3.10.1, 3.10.2
(3, 11): bytearray(b'3, 3, 0, 0,(),(),(\x97\x00|\x00S\x00),(),()'),
+ (3, 12): bytearray(b'3, 3, 0, 0,(),(),(\x97\x00|\x00S\x00),(),()'),
}
c = SCons.Action._function_contents(func1)
@@ -2288,7 +2294,11 @@ class ObjectContentsTestCase(unittest.TestCase):
b"{TestClass:__main__}[[[(<class \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<class \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(d\x01|\x00_\x00d\x02|\x00_\x01d\x00S\x00),(),(),2, 2, 0, 0,(),(),(d\x00S\x00),(),()}}{{{a=a,b=b}}}"
),
(3, 11): bytearray(
- b"{TestClass:__main__}[[[(<class \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<class \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(\x97\x00d\x01|\x00_\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x02|\x00_\x01\x00\x00\x00\x00\x00\x00\x00\x00d\x00S\x00),(),(),2, 2, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()}}{{{a=a,b=b}}}"),
+ b"{TestClass:__main__}[[[(<class \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<class \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(\x97\x00d\x01|\x00_\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x02|\x00_\x01\x00\x00\x00\x00\x00\x00\x00\x00d\x00S\x00),(),(),2, 2, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()}}{{{a=a,b=b}}}"
+ ),
+ (3, 12): bytearray(
+ b"{TestClass:__main__}[[[(<class \'object\'>, ()), [(<class \'__main__.TestClass\'>, (<class \'object\'>,))]]]]{{1, 1, 0, 0,(a,b),(a,b),(\x97\x00d\x01|\x00_\x00\x00\x00\x00\x00\x00\x00\x00\x00d\x02|\x00_\x01\x00\x00\x00\x00\x00\x00\x00\x00d\x00S\x00),(),(),2, 2, 0, 0,(),(),(\x97\x00d\x00S\x00),(),()}}{{{a=a,b=b}}}"
+ ),
}
assert c == expected[sys.version_info[:2]], f"Got\n{c!r}\nExpected\n" + repr(
@@ -2322,7 +2332,11 @@ class ObjectContentsTestCase(unittest.TestCase):
b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'
),
(3, 11): bytearray(
- b'0, 0, 0, 0,(Hello, World!),(print),(\x97\x00\x02\x00e\x00d\x00\xa6\x01\x00\x00\xab\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00d\x01S\x00)'),
+ b'0, 0, 0, 0,(Hello, World!),(print),(\x97\x00\x02\x00e\x00d\x00\xa6\x01\x00\x00\xab\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00d\x01S\x00)'
+ ),
+ (3, 12): bytearray(
+ b'0, 0, 0, 0,(Hello, World!),(print),(\x97\x00\x02\x00e\x00d\x00\xab\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00d\x01S\x00)'
+ ),
}
assert c == expected[sys.version_info[:2]], f"Got\n{c!r}\nExpected\n" + repr(
diff --git a/SCons/CacheDir.py b/SCons/CacheDir.py
index 14e52ad2b..70c4f38a8 100644
--- a/SCons/CacheDir.py
+++ b/SCons/CacheDir.py
@@ -211,35 +211,42 @@ class CacheDir:
(self.requests, self.hits, self.misses, self.hit_ratio))
@classmethod
- def copy_from_cache(cls, env, src, dst):
+ def copy_from_cache(cls, env, src, dst) -> str:
+ """Copy a file from cache."""
if env.cache_timestamp_newer:
return env.fs.copy(src, dst)
else:
return env.fs.copy2(src, dst)
@classmethod
- def copy_to_cache(cls, env, src, dst):
+ def copy_to_cache(cls, env, src, dst) -> str:
+ """Copy a file to cache.
+
+ Just use the FS copy2 ("with metadata") method, except do an additional
+ check and if necessary a chmod to ensure the cachefile is writeable,
+ to forestall permission problems if the cache entry is later updated.
+ """
try:
result = env.fs.copy2(src, dst)
- fs = env.File(src).fs
- st = fs.stat(src)
- fs.chmod(dst, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE)
+ st = stat.S_IMODE(os.stat(result).st_mode)
+ if not st | stat.S_IWRITE:
+ os.chmod(dst, st | stat.S_IWRITE)
return result
except AttributeError as ex:
raise EnvironmentError from ex
@property
- def hit_ratio(self):
+ def hit_ratio(self) -> float:
return (100.0 * self.hits / self.requests if self.requests > 0 else 100)
@property
- def misses(self):
+ def misses(self) -> int:
return self.requests - self.hits
- def is_enabled(self):
+ def is_enabled(self) -> bool:
return cache_enabled and self.path is not None
- def is_readonly(self):
+ def is_readonly(self) -> bool:
return cache_readonly
def get_cachedir_csig(self, node):
@@ -247,18 +254,21 @@ class CacheDir:
if cachefile and os.path.exists(cachefile):
return SCons.Util.hash_file_signature(cachefile, SCons.Node.FS.File.hash_chunksize)
- def cachepath(self, node):
- """
+ def cachepath(self, node) -> tuple:
+ """Return where to cache a file.
+
+ Given a Node, obtain the configured cache directory and
+ the path to the cached file, which is generated from the
+ node's build signature. If caching is not enabled for the
+ None, return a tuple of None.
"""
if not self.is_enabled():
return None, None
sig = node.get_cachedir_bsig()
-
subdir = sig[:self.config['prefix_len']].upper()
-
- dir = os.path.join(self.path, subdir)
- return dir, os.path.join(dir, sig)
+ cachedir = os.path.join(self.path, subdir)
+ return cachedir, os.path.join(cachedir, sig)
def retrieve(self, node):
"""
diff --git a/SCons/Scanner/Java.py b/SCons/Scanner/Java.py
index 8c31bc144..e6c2db978 100644
--- a/SCons/Scanner/Java.py
+++ b/SCons/Scanner/Java.py
@@ -59,9 +59,9 @@ def _collect_classes(classlist, dirname, files):
def scan(node, env, libpath=()) -> list:
- """Scan for files on the JAVACLASSPATH.
+ """Scan for files both on JAVACLASSPATH and JAVAPROCESSORPATH.
- JAVACLASSPATH path can contain:
+ JAVACLASSPATH/JAVAPROCESSORPATH path can contain:
- Explicit paths to JAR/Zip files
- Wildcards (*)
- Directories which contain classes in an unnamed package
@@ -70,8 +70,9 @@ def scan(node, env, libpath=()) -> list:
Class path entries that are neither directories nor archives (.zip
or JAR files) nor the asterisk (*) wildcard character are ignored.
"""
- classpath = env.get('JAVACLASSPATH', [])
- classpath = _subst_paths(env, classpath)
+ classpath = []
+ for var in ['JAVACLASSPATH', 'JAVAPROCESSORPATH']:
+ classpath += _subst_paths(env, env.get(var, []))
result = []
for path in classpath:
diff --git a/SCons/Scanner/JavaTests.py b/SCons/Scanner/JavaTests.py
index 77cd56089..faa0c49ea 100644
--- a/SCons/Scanner/JavaTests.py
+++ b/SCons/Scanner/JavaTests.py
@@ -179,6 +179,70 @@ class JavaScannerSearchPathClasspath(unittest.TestCase):
deps_match(self, deps, expected)
+class JavaScannerEmptyProcessorpath(unittest.TestCase):
+ def runTest(self):
+ path = []
+ env = DummyEnvironment(JAVASUFFIXES=['.java'], JAVAPROCESSORPATH=path)
+ s = SCons.Scanner.Java.JavaScanner()
+ deps = s(DummyNode('dummy'), env)
+ expected = []
+ deps_match(self, deps, expected)
+
+
+class JavaScannerProcessorpath(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment(JAVASUFFIXES=['.java'],
+ JAVAPROCESSORPATH=[test.workpath('classpath.jar')])
+ s = SCons.Scanner.Java.JavaScanner()
+ deps = s(DummyNode('dummy'), env)
+ expected = ['classpath.jar']
+ deps_match(self, deps, expected)
+
+
+class JavaScannerWildcardProcessorpath(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment(JAVASUFFIXES=['.java'],
+ JAVAPROCESSORPATH=[test.workpath('*')])
+ s = SCons.Scanner.Java.JavaScanner()
+ deps = s(DummyNode('dummy'), env)
+ expected = ['bootclasspath.jar', 'classpath.jar', 'Test.class']
+ deps_match(self, deps, expected)
+
+
+class JavaScannerDirProcessorpath(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment(JAVASUFFIXES=['.java'],
+ JAVAPROCESSORPATH=[test.workpath()])
+ s = SCons.Scanner.Java.JavaScanner()
+ deps = s(DummyNode('dummy'), env)
+ expected = ['Test.class', 'com/Test.class', 'java space/Test.class']
+ deps_match(self, deps, expected)
+
+
+class JavaScannerNamedDirProcessorpath(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment(
+ JAVASUFFIXES=['.java'],
+ JAVAPROCESSORPATH=[test.workpath('com'), test.workpath('java space')],
+ )
+ s = SCons.Scanner.Java.JavaScanner()
+ deps = s(DummyNode('dummy'), env)
+ expected = ['com/Test.class', 'java space/Test.class']
+ deps_match(self, deps, expected)
+
+
+class JavaScannerSearchPathProcessorpath(unittest.TestCase):
+ def runTest(self):
+ env = DummyEnvironment(
+ JAVASUFFIXES=['.java'],
+ JAVAPROCESSORPATH=os.pathsep.join([test.workpath('com'), test.workpath('java space')]),
+ )
+ s = SCons.Scanner.Java.JavaScanner()
+ deps = s(DummyNode('dummy'), env)
+ expected = ['com/Test.class', 'java space/Test.class']
+ deps_match(self, deps, expected)
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/SCons/Tool/fortran.xml b/SCons/Tool/fortran.xml
index 5bb1bd28f..4a092ecea 100644
--- a/SCons/Tool/fortran.xml
+++ b/SCons/Tool/fortran.xml
@@ -111,9 +111,8 @@ contain
(or similar) include or module search path options
that scons generates automatically from &cv-link-FORTRANPATH;.
See
-&cv-link-_FORTRANINCFLAGS; and &cv-link-_FORTRANMODFLAG;,
-below,
-for the variables that expand those options.
+&cv-link-_FORTRANINCFLAGS; and &cv-link-_FORTRANMODFLAG;
+for the &consvars; that expand those options.
</para>
</summary>
</cvar>
@@ -123,8 +122,9 @@ for the variables that expand those options.
<para>
General user-specified options that are passed to the Fortran compiler.
Similar to &cv-link-FORTRANFLAGS;,
-but this variable is applied to all dialects.
+but this &consvar; is applied to all dialects.
</para>
+<para><emphasis>New in version 4.4.</emphasis></para>
</summary>
</cvar>
diff --git a/SCons/Tool/gfortran.py b/SCons/Tool/gfortran.py
index 3c7e8b5bb..f9c0a4535 100644
--- a/SCons/Tool/gfortran.py
+++ b/SCons/Tool/gfortran.py
@@ -29,24 +29,27 @@ It will usually be imported through the generic SCons.Tool.Tool()
selection method.
"""
-import SCons.Util
+from SCons.Util import CLVar
from . import fortran
def generate(env):
- """Add Builders and construction variables for gfortran to an
- Environment."""
+ """Add Builders and construction variables for gfortran."""
fortran.generate(env)
- for dialect in ['F77', 'F90', 'FORTRAN', 'F95', 'F03', 'F08']:
- env[f'{dialect}'] = 'gfortran'
- env[f'SH{dialect}'] = f'${dialect}'
- if env['PLATFORM'] in ['cygwin', 'win32']:
- env[f'SH{dialect}FLAGS'] = SCons.Util.CLVar(f'${dialect}FLAGS')
- else:
- env[f'SH{dialect}FLAGS'] = SCons.Util.CLVar(f'${dialect}FLAGS -fPIC')
+ # fill in other dialects (FORTRAN dialect set by fortran.generate(),
+ # but don't overwrite if they have been set manually.
+ for dialect in ['F77', 'F90', 'F95', 'F03', 'F08']:
+ if dialect not in env:
+ env[f'{dialect}'] = 'gfortran'
+ if f'SH{dialect}' not in env:
+ env[f'SH{dialect}'] = f'${dialect}'
+ # The fortran module always sets the shlib FLAGS, but does not
+ # include -fPIC, which is needed for the GNU tools. Rewrite if needed.
+ if env['PLATFORM'] not in ['cygwin', 'win32']:
+ env[f'SH{dialect}FLAGS'] = CLVar(f'${dialect}FLAGS -fPIC')
env[f'INC{dialect}PREFIX'] = "-I"
env[f'INC{dialect}SUFFIX'] = ""
diff --git a/SCons/Tool/javac.py b/SCons/Tool/javac.py
index 9e1896415..1b331253b 100644
--- a/SCons/Tool/javac.py
+++ b/SCons/Tool/javac.py
@@ -231,13 +231,15 @@ def generate(env):
JAVABOOTCLASSPATH=[],
JAVACLASSPATH=[],
JAVASOURCEPATH=[],
+ JAVAPROCESSORPATH=[],
)
env['_javapathopt'] = pathopt
env['_JAVABOOTCLASSPATH'] = '${_javapathopt("-bootclasspath", "JAVABOOTCLASSPATH")} '
+ env['_JAVAPROCESSORPATH'] = '${_javapathopt("-processorpath", "JAVAPROCESSORPATH")} '
env['_JAVACLASSPATH'] = '${_javapathopt("-classpath", "JAVACLASSPATH")} '
env['_JAVASOURCEPATH'] = '${_javapathopt("-sourcepath", "JAVASOURCEPATH", "_JAVASOURCEPATHDEFAULT")} '
env['_JAVASOURCEPATHDEFAULT'] = '${TARGET.attributes.java_sourcedir}'
- env['_JAVACCOM'] = '$JAVAC $JAVACFLAGS $_JAVABOOTCLASSPATH $_JAVACLASSPATH -d ${TARGET.attributes.java_classdir} $_JAVASOURCEPATH $SOURCES'
+ env['_JAVACCOM'] = '$JAVAC $JAVACFLAGS $_JAVABOOTCLASSPATH $_JAVAPROCESSORPATH $_JAVACLASSPATH -d ${TARGET.attributes.java_classdir} $_JAVASOURCEPATH $SOURCES'
env['JAVACCOM'] = "${TEMPFILE('$_JAVACCOM','$JAVACCOMSTR')}"
def exists(env):
diff --git a/SCons/Tool/javac.xml b/SCons/Tool/javac.xml
index 014d905e9..6f48356e4 100644
--- a/SCons/Tool/javac.xml
+++ b/SCons/Tool/javac.xml
@@ -152,6 +152,34 @@ env['ENV']['LANG'] = 'en_GB.UTF-8'
</summary>
</cvar>
+ <cvar name="JAVAPROCESSORPATH">
+ <summary>
+ <para>
+ Specifies the location of the annotation processor class files.
+ Can be specified as a string or Node object,
+ or as a list of strings or Node objects.
+ </para>
+ <para>
+ The value will be added to the JDK command lines
+ via the <option>-processorpath</option> option,
+ which requires a system-specific search path separator.
+ This will be supplied by &SCons; as needed when it
+ constructs the command line if &cv-JAVAPROCESSORPATH; is
+ provided in list form.
+ If &cv-JAVAPROCESSORPATH; is a single string containing
+ search path separator characters
+ (<literal>:</literal> for POSIX systems or
+ <literal>;</literal> for Windows), it will not be modified;
+ and so is inherently system-specific;
+ to supply the path in a system-independent manner,
+ give &cv-JAVAPROCESSORPATH; as a list of paths instead.
+ </para>
+ <para>
+ <emphasis>New in version 4.5.0</emphasis>
+ </para>
+ </summary>
+ </cvar>
+
<cvar name="JAVAINCLUDES">
<summary>
<para>
diff --git a/SCons/Tool/linkCommon/__init__.py b/SCons/Tool/linkCommon/__init__.py
index 7aaffab92..5461ad3db 100644
--- a/SCons/Tool/linkCommon/__init__.py
+++ b/SCons/Tool/linkCommon/__init__.py
@@ -137,11 +137,14 @@ def smart_link(source, target, env, for_signature):
if has_cplusplus and has_fortran and not has_d:
global issued_mixed_link_warning
if not issued_mixed_link_warning:
- msg = "Using $CXX to link Fortran and C++ code together.\n\t" + \
- "This may generate a buggy executable if the '%s'\n\t" + \
- "compiler does not know how to deal with Fortran runtimes."
- SCons.Warnings.warn(SCons.Warnings.FortranCxxMixWarning,
- msg % env.subst('$CXX'))
+ msg = (
+ "Using $CXX to link Fortran and C++ code together.\n"
+ " This may generate a buggy executable if the '%s'\n"
+ " compiler does not know how to deal with Fortran runtimes."
+ )
+ SCons.Warnings.warn(
+ SCons.Warnings.FortranCxxMixWarning, msg % env.subst('$CXX')
+ )
issued_mixed_link_warning = True
return '$CXX'
elif has_d:
diff --git a/SCons/Tool/msvc.xml b/SCons/Tool/msvc.xml
index c26c20da8..bf2e26734 100644
--- a/SCons/Tool/msvc.xml
+++ b/SCons/Tool/msvc.xml
@@ -1,31 +1,10 @@
<?xml version="1.0"?>
<!--
- MIT License
-
- Copyright 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.
-
+SPDX-License-Identifier: MIT
+SPDX-FileCopyrightText: Copyright The SCons Foundation
+SPDX-FileType: DOCUMENTATION
This file is processed by the bin/SConsDoc.py module.
-See its __doc__ string for a discussion of the format.
-->
<!DOCTYPE sconsdoc [
@@ -48,7 +27,7 @@ See its __doc__ string for a discussion of the format.
<tool name="msvc">
<summary>
<para>
-Sets construction variables for the Microsoft Visual C/C++ compiler.
+Sets &consvars; for the Microsoft Visual C/C++ compiler.
</para>
</summary>
<sets>
@@ -96,7 +75,17 @@ Sets construction variables for the Microsoft Visual C/C++ compiler.
<item>PCH</item>
<item>PCHSTOP</item>
<item>PDB</item>
+<item>MSVC_VERSION</item>
+<item>MSVC_USE_SCRIPT</item>
+<item>MSVC_USE_SCRIPT_ARGS</item>
+<item>MSVC_USE_SETTINGS</item>
<item>MSVC_NOTFOUND_POLICY</item>
+<item>MSVC_SCRIPTERROR_POLICY</item>
+<item>MSVC_SCRIPT_ARGS</item>
+<item>MSVC_SDK_VERSION</item>
+<item>MSVC_TOOLSET_VERSION</item>
+<item>MSVC_SPECTRE_LIBS</item>
+
</uses>
</tool>
@@ -110,7 +99,7 @@ file as the second element. Normally the object file is ignored.
This builder is only
provided when Microsoft Visual C++ is being used as the compiler.
The &b-PCH; builder is generally used in
-conjunction with the &cv-link-PCH; construction variable to force object files to use
+conjunction with the &cv-link-PCH; &consvar; to force object files to use
the precompiled header:
</para>
@@ -148,7 +137,7 @@ Options added to the compiler command line
to support building with precompiled headers.
The default value expands expands to the appropriate
Microsoft Visual C++ command-line options
-when the &cv-link-PCH; construction variable is set.
+when the &cv-link-PCH; &consvar; is set.
</para>
</summary>
</cvar>
@@ -161,7 +150,7 @@ to support storing debugging information in a
Microsoft Visual C++ PDB file.
The default value expands expands to appropriate
Microsoft Visual C++ command-line options
-when the &cv-link-PDB; construction variable is set.
+when the &cv-link-PDB; &consvar; is set.
</para>
<para>
@@ -208,11 +197,11 @@ compilation of object files
when calling the Microsoft Visual C/C++ compiler.
All compilations of source files from the same source directory
that generate target files in a same output directory
-and were configured in SCons using the same construction environment
+and were configured in SCons using the same &consenv;
will be built in a single call to the compiler.
Only source files that have changed since their
object files were built will be passed to each compiler invocation
-(via the &cv-link-CHANGED_SOURCES; construction variable).
+(via the &cv-link-CHANGED_SOURCES; &consvar;).
Any compilations where the object (target) file base name
(minus the <filename>.obj</filename>)
does not match the source file base name
@@ -261,9 +250,9 @@ If this is not set, then &cv-link-PCHCOM; (the command line) is displayed.
<cvar name="PCHPDBFLAGS">
<summary>
<para>
-A construction variable that, when expanded,
+A &consvar; that, when expanded,
adds the <option>/yD</option> flag to the command line
-only if the &cv-link-PDB; construction variable is set.
+only if the &cv-link-PDB; &consvar; is set.
</para>
</summary>
</cvar>
@@ -324,7 +313,7 @@ The flags passed to the resource compiler by the &b-link-RES; builder.
<cvar name="RCINCFLAGS">
<summary>
<para>
-An automatically-generated construction variable
+An automatically-generated &consvar;
containing the command-line options
for specifying directories to be searched
by the resource compiler.
@@ -343,7 +332,7 @@ of each directory in &cv-link-CPPPATH;.
The prefix (flag) used to specify an include directory
on the resource compiler command line.
This will be prepended to the beginning of each directory
-in the &cv-link-CPPPATH; construction variable
+in the &cv-link-CPPPATH; &consvar;
when the &cv-link-RCINCFLAGS; variable is expanded.
</para>
</summary>
@@ -355,7 +344,7 @@ when the &cv-link-RCINCFLAGS; variable is expanded.
The suffix used to specify an include directory
on the resource compiler command line.
This will be appended to the end of each directory
-in the &cv-link-CPPPATH; construction variable
+in the &cv-link-CPPPATH; &consvar;
when the &cv-link-RCINCFLAGS; variable is expanded.
</para>
</summary>
@@ -365,12 +354,10 @@ when the &cv-link-RCINCFLAGS; variable is expanded.
<summary>
<para>
Sets the preferred version of Microsoft Visual C/C++ to use.
-</para>
-
-<para>
+If the specified version is unavailable (not installed,
+or not discoverable), tool initialization will fail.
If &cv-MSVC_VERSION; is not set, SCons will (by default) select the
-latest version of Visual C/C++ installed on your system. If the
-specified version isn't installed, tool initialization will fail.
+latest version of Visual C/C++ installed on your system.
</para>
<para>
@@ -383,28 +370,186 @@ loaded into the environment.
</para>
<para>
-Valid values for Windows are
-<literal>14.3</literal>,
-<literal>14.2</literal>,
-<literal>14.1</literal>,
-<literal>14.1Exp</literal>,
-<literal>14.0</literal>,
-<literal>14.0Exp</literal>,
-<literal>12.0</literal>,
-<literal>12.0Exp</literal>,
-<literal>11.0</literal>,
-<literal>11.0Exp</literal>,
-<literal>10.0</literal>,
-<literal>10.0Exp</literal>,
-<literal>9.0</literal>,
-<literal>9.0Exp</literal>,
-<literal>8.0</literal>,
-<literal>8.0Exp</literal>,
-<literal>7.1</literal>,
-<literal>7.0</literal>,
-and <literal>6.0</literal>.
-Versions ending in <literal>Exp</literal> refer to "Express" or
-"Express for Desktop" editions.
+The valid values for &cv-MSVC_VERSION; represent major versions
+of the compiler, except that versions ending in <literal>Exp</literal>
+refer to "Express" or "Express for Desktop" Visual Studio editions,
+which require distict entries because they use a different
+filesystem layout and have some feature limitations compared to
+the full version.
+The following table shows correspondence
+of the selector string to various version indicators
+('x' is used as a placeholder for
+a single digit that can vary).
+Note that it is not necessary to install Visual Studio
+to build with &SCons; (for example, you can install only
+Build Tools), but if Visual Studio is installed,
+additional builders such as &b-link-MSVSSolution; and
+&b-link-MSVSProject; become avaialable and will
+correspond to the indicated versions.
+</para>
+
+<informaltable>
+ <tgroup cols="5">
+ <colspec align="left" />
+ <colspec align="center" />
+ <colspec align="center" />
+ <colspec align="left" />
+ <colspec align="center" />
+ <thead>
+ <row>
+ <entry> SCons Key </entry>
+ <entry> MSVC++ Version </entry>
+ <entry> <literal>_MSVC_VER</literal> </entry>
+ <entry> VS Product </entry>
+ <entry> MSBuild/VS Version </entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry> <literal>14.3</literal> </entry>
+ <entry> 14.3x </entry>
+ <entry> 193x </entry>
+ <entry> Visual Studio 2022 </entry>
+ <entry> 17.x </entry>
+ </row>
+ <row>
+ <entry> <literal>14.2</literal> </entry>
+ <entry> 14.2x </entry>
+ <entry> 192x </entry>
+ <entry> Visual Studio 2019 </entry>
+ <entry> 16.x, 16.1x </entry>
+ </row>
+ <row>
+ <entry> <literal>14.1</literal> </entry>
+ <entry> 14.1 or 14.1x </entry>
+ <entry> 191x </entry>
+ <entry> Visual Studio 2017 </entry>
+ <entry> 15.x </entry>
+ </row>
+ <row>
+ <entry> <literal>14.1Exp</literal> </entry>
+ <entry> 14.1 </entry>
+ <entry> 1910 </entry>
+ <entry> Visual Studio 2017 Express </entry>
+ <entry> 15.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>14.0</literal> </entry>
+ <entry> 14.0 </entry>
+ <entry> 1900 </entry>
+ <entry> Visual Studio 2015 </entry>
+ <entry> 14.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>14.0Exp</literal> </entry>
+ <entry> 14.0 </entry>
+ <entry> 1900 </entry>
+ <entry> Visual Studio 2015 Express </entry>
+ <entry> 14.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>12.0</literal> </entry>
+ <entry> 12.0 </entry>
+ <entry> 1800 </entry>
+ <entry> Visual Studio 2013 </entry>
+ <entry> 12.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>12.0Exp</literal> </entry>
+ <entry> 12.0 </entry>
+ <entry> 1800 </entry>
+ <entry> Visual Studio 2013 Express </entry>
+ <entry> 12.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>11.0</literal> </entry>
+ <entry> 11.0 </entry>
+ <entry> 1700 </entry>
+ <entry> Visual Studio 2012 </entry>
+ <entry> 11.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>11.0Exp</literal> </entry>
+ <entry> 11.0 </entry>
+ <entry> 1700 </entry>
+ <entry> Visual Studio 2012 Express </entry>
+ <entry> 11.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>10.0</literal> </entry>
+ <entry> 10.0 </entry>
+ <entry> 1600 </entry>
+ <entry> Visual Studio 2010 </entry>
+ <entry> 10.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>10.0Exp</literal> </entry>
+ <entry> 10.0 </entry>
+ <entry> 1600 </entry>
+ <entry> Visual C++ Express 2010 </entry>
+ <entry> 10.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>9.0</literal> </entry>
+ <entry> 9.0 </entry>
+ <entry> 1500 </entry>
+ <entry> Visual Studio 2008 </entry>
+ <entry> 9.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>9.0Exp</literal> </entry>
+ <entry> 9.0 </entry>
+ <entry> 1500 </entry>
+ <entry> Visual C++ Express 2008 </entry>
+ <entry> 9.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>8.0</literal> </entry>
+ <entry> 8.0 </entry>
+ <entry> 1400 </entry>
+ <entry> Visual Studio 2005 </entry>
+ <entry> 8.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>8.0Exp</literal> </entry>
+ <entry> 8.0 </entry>
+ <entry> 1400 </entry>
+ <entry> Visual C++ Express 2005 </entry>
+ <entry> 8.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>7.1</literal> </entry>
+ <entry> 7.1 </entry>
+ <entry> 1300 </entry>
+ <entry> Visual Studio .NET 2003 </entry>
+ <entry> 7.1 </entry>
+ </row>
+ <row>
+ <entry> <literal>7.0</literal> </entry>
+ <entry> 7.0 </entry>
+ <entry> 1200 </entry>
+ <entry> Visual Studio .NET 2002 </entry>
+ <entry> 7.0 </entry>
+ </row>
+ <row>
+ <entry> <literal>6.0</literal> </entry>
+ <entry> 6.0 </entry>
+ <entry> 1100 </entry>
+ <entry> Visual Studio 6.0 </entry>
+ <entry> 6.0 </entry>
+ </row>
+ </tbody>
+ </tgroup>
+</informaltable>
+
+<para>
+The compilation environment can be further or more precisely specified through the
+use of several other &consvars;: see the descriptions of
+&cv-link-MSVC_TOOLSET_VERSION;,
+&cv-link-MSVC_SDK_VERSION;,
+&cv-link-MSVC_USE_SCRIPT;,
+&cv-link-MSVC_USE_SCRIPT_ARGS;,
+and &cv-link-MSVC_USE_SETTINGS;.
</para>
</summary>
@@ -433,7 +578,7 @@ This can be useful to force the use of a compiler version that
Setting
&cv-MSVC_USE_SCRIPT; to <constant>None</constant> bypasses the
Visual Studio autodetection entirely;
-use this if you are running SCons in a Visual Studio <command>cmd</command>
+use this if you are running &SCons; in a Visual Studio <command>cmd</command>
window and importing the shell's environment variables - that
is, if you are sure everything is set correctly already and
you don't want &SCons; to change anything.
@@ -441,6 +586,12 @@ you don't want &SCons; to change anything.
<para>
&cv-MSVC_USE_SCRIPT; ignores &cv-link-MSVC_VERSION; and &cv-link-TARGET_ARCH;.
</para>
+
+<para><emphasis>Changed in version 4.4:</emphasis>
+new &cv-link-MSVC_USE_SCRIPT_ARGS; provides a
+way to pass arguments.
+</para>
+
</summary>
</cvar>
@@ -449,6 +600,9 @@ you don't want &SCons; to change anything.
<para>
Provides arguments passed to the script &cv-link-MSVC_USE_SCRIPT;.
</para>
+
+<para><emphasis>New in version 4.4</emphasis></para>
+
</summary>
</cvar>
@@ -529,11 +683,15 @@ therefore may change at any time.
</emphasis>
The burden is on the user to ensure the dictionary contents are minimally sufficient to
ensure successful builds.
-</para></listitem>
+</para>
+
+</listitem>
</itemizedlist>
</para>
+<para><emphasis>New in version 4.4</emphasis></para>
+
</summary>
</cvar>
@@ -780,6 +938,8 @@ When &cv-MSVC_NOTFOUND_POLICY; is not specified, the default &scons; behavior is
subject to the conditions listed above. The default &scons; behavior may change in the future.
</para>
+<para><emphasis>New in version 4.4</emphasis></para>
+
</summary>
</cvar>
@@ -831,6 +991,9 @@ Issue a warning when msvc batch file errors are detected.
<para>
Suppress msvc batch file error messages.
</para>
+
+<para><emphasis>New in version 4.4</emphasis></para>
+
</listitem>
</varlistentry>
@@ -905,6 +1068,8 @@ when setting the script error policy to raise an exception (e.g., <literal>'Erro
</itemizedlist>
</para>
+<para><emphasis>New in version 4.4</emphasis></para>
+
</summary>
</cvar>
@@ -916,8 +1081,8 @@ Pass user-defined arguments to the Visual C++ batch file determined via autodete
<para>
&cv-MSVC_SCRIPT_ARGS; is available for msvc batch file arguments that do not have first-class support
-via construction variables or when there is an issue with the appropriate construction variable validation.
-When available, it is recommended to use the appropriate construction variables (e.g., &cv-link-MSVC_TOOLSET_VERSION;)
+via &consvars; or when there is an issue with the appropriate &consvar; validation.
+When available, it is recommended to use the appropriate &consvars; (e.g., &cv-link-MSVC_TOOLSET_VERSION;)
rather than &cv-MSVC_SCRIPT_ARGS; arguments.
</para>
@@ -1041,6 +1206,8 @@ and compatible with the version of msvc selected.
</itemizedlist>
</para>
+<para><emphasis>New in version 4.4</emphasis></para>
+
</summary>
</cvar>
@@ -1159,6 +1326,8 @@ specify a Windows 10 SDK (e.g., <literal>'10.0.20348.0'</literal>) for the build
</itemizedlist>
</para>
+<para><emphasis>New in version 4.4</emphasis></para>
+
</summary>
</cvar>
@@ -1329,6 +1498,8 @@ The burden is on the user to ensure the requisite toolset target architecture bu
</itemizedlist>
</para>
+<para><emphasis>New in version 4.4</emphasis></para>
+
</summary>
</cvar>
@@ -1409,6 +1580,8 @@ The burden is on the user to ensure the requisite libraries with spectre mitigat
</itemizedlist>
</para>
+<para><emphasis>New in version 4.4</emphasis></para>
+
</summary>
</cvar>
diff --git a/requirements-dev.txt b/requirements-dev.txt
index 6f9855fc1..82faa28e5 100644
--- a/requirements-dev.txt
+++ b/requirements-dev.txt
@@ -4,7 +4,9 @@
# for now keep pinning "known working" lxml,
# it's been a troublesome component in the past.
-lxml==4.9.1
+# Skip lxml for win32 as no tests which require it currently pass on win32
+lxml==4.9.2; python_version < '3.12' and sys_platform != 'win32'
+
ninja
# Needed for test/Parallel/failed-build/failed-build.py
diff --git a/requirements-pkg.txt b/requirements-pkg.txt
index 10b53933e..ae71cde0d 100644
--- a/requirements-pkg.txt
+++ b/requirements-pkg.txt
@@ -8,6 +8,6 @@
readme-renderer
# sphinx pinned because it has broken several times on new releases
-sphinx>=5.1.1
+sphinx < 6.0
sphinx-book-theme
rst2pdf
diff --git a/setup.cfg b/setup.cfg
index 941db3419..f177d6f11 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -31,6 +31,8 @@ classifiers =
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
+ Programming Language :: Python :: 3.11
+ Programming Language :: Python :: 3.12
Environment :: Console
Intended Audience :: Developers
License :: OSI Approved :: MIT License
diff --git a/test/Fortran/F95FLAGS.py b/test/Fortran/F95FLAGS.py
index 2853cc924..e70626419 100644
--- a/test/Fortran/F95FLAGS.py
+++ b/test/Fortran/F95FLAGS.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -20,9 +22,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons
@@ -31,26 +30,30 @@ _python_ = TestSCons._python_
test = TestSCons.TestSCons()
_exe = TestSCons._exe
+# ref: test/fixture/mylink.py
test.file_fixture('mylink.py')
+# ref: test/Fortran/fixture/myfortran_flags.py
test.file_fixture(['fixture', 'myfortran_flags.py'])
test.write('SConstruct', """
-env = Environment(LINK = r'%(_python_)s mylink.py',
- LINKFLAGS = [],
- F95 = r'%(_python_)s myfortran_flags.py g95',
- F95FLAGS = '-x',
- FORTRAN = r'%(_python_)s myfortran_flags.py fortran',
- FORTRANFLAGS = '-y')
-env.Program(target = 'test01', source = 'test01.f')
-env.Program(target = 'test02', source = 'test02.F')
-env.Program(target = 'test03', source = 'test03.for')
-env.Program(target = 'test04', source = 'test04.FOR')
-env.Program(target = 'test05', source = 'test05.ftn')
-env.Program(target = 'test06', source = 'test06.FTN')
-env.Program(target = 'test07', source = 'test07.fpp')
-env.Program(target = 'test08', source = 'test08.FPP')
-env.Program(target = 'test13', source = 'test13.f95')
-env.Program(target = 'test14', source = 'test14.F95')
+env = Environment(
+ LINK=r'%(_python_)s mylink.py',
+ LINKFLAGS=[],
+ F95=r'%(_python_)s myfortran_flags.py g95',
+ F95FLAGS='-x',
+ FORTRAN=r'%(_python_)s myfortran_flags.py fortran',
+ FORTRANFLAGS='-y',
+)
+env.Program(target='test01', source='test01.f')
+env.Program(target='test02', source='test02.F')
+env.Program(target='test03', source='test03.for')
+env.Program(target='test04', source='test04.FOR')
+env.Program(target='test05', source='test05.ftn')
+env.Program(target='test06', source='test06.FTN')
+env.Program(target='test07', source='test07.fpp')
+env.Program(target='test08', source='test08.FPP')
+env.Program(target='test13', source='test13.f95')
+env.Program(target='test14', source='test14.F95')
""" % locals())
test.write('test01.f', "This is a .f file.\n#link\n#fortran\n")
@@ -80,24 +83,22 @@ test.must_match('test14' + _exe, " -c -x\nThis is a .F95 file.\n")
fc = 'f95'
g95 = test.detect_tool(fc)
-
-
if g95:
test.subdir('x')
-
test.write(['x','dummy.i'],
"""
# Exists only such that -Ix finds the directory...
""")
+ # ref: test/fixture/wrapper.py
test.file_fixture('wrapper.py')
test.write('SConstruct', """
-foo = Environment(F95 = '%(fc)s')
+foo = Environment(F95='%(fc)s')
f95 = foo.Dictionary('F95')
-bar = foo.Clone(F95 = r'%(_python_)s wrapper.py ' + f95, F95FLAGS = '-Ix')
-foo.Program(target = 'foo', source = 'foo.f95')
-bar.Program(target = 'bar', source = 'bar.f95')
+bar = foo.Clone(F95=r'%(_python_)s wrapper.py ' + f95, F95FLAGS='-Ix')
+foo.Program(target='foo', source='foo.f95')
+bar.Program(target='bar', source='bar.f95')
""" % locals())
test.write('foo.f95', r"""
@@ -114,21 +115,18 @@ bar.Program(target = 'bar', source = 'bar.f95')
END
""")
-
- test.run(arguments = 'foo' + _exe, stderr = None)
-
- test.run(program = test.workpath('foo'), stdout = " foo.f95\n")
-
+ test.run(arguments='foo' + _exe, stderr=None)
+ test.run(program=test.workpath('foo'), stdout=" foo.f95\n")
test.must_not_exist('wrapper.out')
import sys
- if sys.platform[:5] == 'sunos':
- test.run(arguments = 'bar' + _exe, stderr = None)
- else:
- test.run(arguments = 'bar' + _exe)
- test.run(program = test.workpath('bar'), stdout = " bar.f95\n")
+ if sys.platform.startswith('sunos'):
+ test.run(arguments='bar' + _exe, stderr=None)
+ else:
+ test.run(arguments='bar' + _exe)
+ test.run(program=test.workpath('bar'), stdout=" bar.f95\n")
test.must_match('wrapper.out', "wrapper.py\n")
test.pass_test()
diff --git a/test/Fortran/SHF95FLAGS.py b/test/Fortran/SHF95FLAGS.py
index 56744d626..dcec49bf7 100644
--- a/test/Fortran/SHF95FLAGS.py
+++ b/test/Fortran/SHF95FLAGS.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -20,9 +22,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
import TestSCons
@@ -32,23 +31,25 @@ _obj = TestSCons._shobj
obj_ = TestSCons.shobj_
test = TestSCons.TestSCons()
+# ref: test/Fortran/fixture/myfortran_flags.py
test.file_fixture(['fixture', 'myfortran_flags.py'])
test.write('SConstruct', """
-env = Environment(SHF95 = r'%(_python_)s myfortran_flags.py g95',
- SHFORTRAN = r'%(_python_)s myfortran_flags.py fortran')
-env.Append(SHF95FLAGS = '-x',
- SHFORTRANFLAGS = '-y')
-env.SharedObject(target = 'test01', source = 'test01.f')
-env.SharedObject(target = 'test02', source = 'test02.F')
-env.SharedObject(target = 'test03', source = 'test03.for')
-env.SharedObject(target = 'test04', source = 'test04.FOR')
-env.SharedObject(target = 'test05', source = 'test05.ftn')
-env.SharedObject(target = 'test06', source = 'test06.FTN')
-env.SharedObject(target = 'test07', source = 'test07.fpp')
-env.SharedObject(target = 'test08', source = 'test08.FPP')
-env.SharedObject(target = 'test13', source = 'test13.f95')
-env.SharedObject(target = 'test14', source = 'test14.F95')
+env = Environment(
+ SHF95=r'%(_python_)s myfortran_flags.py g95',
+ SHFORTRAN=r'%(_python_)s myfortran_flags.py fortran',
+)
+env.Append(SHF95FLAGS='-x', SHFORTRANFLAGS='-y')
+env.SharedObject(target='test01', source='test01.f')
+env.SharedObject(target='test02', source='test02.F')
+env.SharedObject(target='test03', source='test03.for')
+env.SharedObject(target='test04', source='test04.FOR')
+env.SharedObject(target='test05', source='test05.ftn')
+env.SharedObject(target='test06', source='test06.FTN')
+env.SharedObject(target='test07', source='test07.fpp')
+env.SharedObject(target='test08', source='test08.FPP')
+env.SharedObject(target='test13', source='test13.f95')
+env.SharedObject(target='test14', source='test14.F95')
""" % locals())
test.write('test01.f', "This is a .f file.\n#fortran\n")
@@ -62,8 +63,7 @@ test.write('test08.FPP', "This is a .FPP file.\n#fortran\n")
test.write('test13.f95', "This is a .f95 file.\n#g95\n")
test.write('test14.F95', "This is a .F95 file.\n#g95\n")
-test.run(arguments = '.', stderr = None)
-
+test.run(arguments='.', stderr=None)
test.must_match(obj_ + 'test01' + _obj, " -c -y\nThis is a .f file.\n")
test.must_match(obj_ + 'test02' + _obj, " -c -y\nThis is a .F file.\n")
test.must_match(obj_ + 'test03' + _obj, " -c -y\nThis is a .for file.\n")
@@ -75,29 +75,24 @@ test.must_match(obj_ + 'test08' + _obj, " -c -y\nThis is a .FPP file.\n")
test.must_match(obj_ + 'test13' + _obj, " -c -x\nThis is a .f95 file.\n")
test.must_match(obj_ + 'test14' + _obj, " -c -x\nThis is a .F95 file.\n")
-
-
fc = 'f95'
g95 = test.detect_tool(fc)
-
if g95:
-
test.subdir('x')
-
test.write(['x','dummy.i'],
"""
# Exists only such that -Ix finds the directory...
""")
+ # ref: test/fixture/wrapper.py
test.file_fixture('wrapper.py')
-
test.write('SConstruct', """
-foo = Environment(SHF95 = '%(fc)s')
+foo = Environment(SHF95='%(fc)s')
shf95 = foo.Dictionary('SHF95')
-bar = foo.Clone(SHF95 = r'%(_python_)s wrapper.py ' + shf95)
-bar.Append(SHF95FLAGS = '-Ix')
-foo.SharedLibrary(target = 'foo/foo', source = 'foo.f95')
-bar.SharedLibrary(target = 'bar/bar', source = 'bar.f95')
+bar = foo.Clone(SHF95=r'%(_python_)s wrapper.py ' + shf95)
+bar.Append(SHF95FLAGS='-Ix')
+foo.SharedLibrary(target='foo/foo', source='foo.f95')
+bar.SharedLibrary(target='bar/bar', source='bar.f95')
""" % locals())
test.write('foo.f95', r"""
@@ -114,17 +109,15 @@ bar.SharedLibrary(target = 'bar/bar', source = 'bar.f95')
END
""")
-
- test.run(arguments = 'foo', stderr = None)
-
+ test.run(arguments='foo', stderr=None)
test.must_not_exist('wrapper.out')
import sys
- if sys.platform[:5] == 'sunos':
- test.run(arguments = 'bar', stderr = None)
- else:
- test.run(arguments = 'bar')
+ if sys.platform.startswith('sunos'):
+ test.run(arguments='bar', stderr=None)
+ else:
+ test.run(arguments='bar')
test.must_match('wrapper.out', "wrapper.py\n")
test.pass_test()
diff --git a/test/Fortran/link-with-cxx.py b/test/Fortran/link-with-cxx.py
index 22d90815e..2f19e828e 100644
--- a/test/Fortran/link-with-cxx.py
+++ b/test/Fortran/link-with-cxx.py
@@ -1,6 +1,8 @@
#!/usr/bin/env python
#
-# __COPYRIGHT__
+# MIT License
+#
+# Copyright The SCons Foundation
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -20,9 +22,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-#
-
-__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__"
"""
Verify the smart_link() warning messages used when attempting to link
@@ -41,6 +40,7 @@ test = TestSCons.TestSCons(match = TestSCons.match_re)
test.write('test_linker.py', """\
import sys
+
if sys.argv[1] == '-o':
with open(sys.argv[2], 'wb') as ofp:
for infile in sys.argv[3:]:
@@ -54,9 +54,9 @@ elif sys.argv[1][:5] == '/OUT:':
sys.exit(0)
""")
-
test.write('test_fortran.py', """\
import sys
+
with open(sys.argv[2], 'wb') as ofp:
for infile in sys.argv[4:]:
with open(infile, 'rb') as ifp:
@@ -64,35 +64,35 @@ with open(sys.argv[2], 'wb') as ofp:
sys.exit(0)
""")
-
test.write('SConstruct', """
import SCons.Tool.link
+
def copier(target, source, env):
s = str(source[0])
t = str(target[0])
with open(t, 'wb') as ofp, open(s, 'rb') as ifp:
ofp.write(ifp.read())
-env = Environment(CXX = r'%(_python_)s test_linker.py',
- CXXCOM = Action(copier),
- SMARTLINK = SCons.Tool.link.smart_link,
- LINK = r'$SMARTLINK',
- LINKFLAGS = '',
- # 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 = Environment(
+ CXX=r'%(_python_)s test_linker.py',
+ CXXCOM=Action(copier),
+ SMARTLINK=SCons.Tool.link.smart_link,
+ LINK=r'$SMARTLINK',
+ LINKFLAGS='',
+ # 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'])
+ SetOption('warn', ['no-link'])
if ARGUMENTS.get('NO_MIX'):
- # Can remove no-deprecated when we drop Python1.5
- SetOption('warn', ['no-fortran-cxx-mix', 'no-deprecated'])
+ SetOption('warn', ['no-fortran-cxx-mix'])
""" % locals())
test.write('f1.cpp', "f1.cpp\n")
@@ -100,52 +100,43 @@ 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.
+ This may generate a buggy executable if the '%s test_linker.py'
+ compiler 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")
diff --git a/test/Java/JAVAPROCESSORPATH.py b/test/Java/JAVAPROCESSORPATH.py
new file mode 100644
index 000000000..2b8f04dc5
--- /dev/null
+++ b/test/Java/JAVAPROCESSORPATH.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+#
+# MIT License
+#
+# Copyright 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.
+
+"""
+Verify that use of $JAVAPROCESSORPATH sets the -processorpath option
+on javac compilations.
+"""
+
+import os
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+
+where_javac, java_version = test.java_where_javac()
+
+test.write('SConstruct', """
+DefaultEnvironment(tools=[])
+env = Environment(tools=['javac'], JAVAPROCESSORPATH=['dir1', 'dir2'])
+j1 = env.Java(target='class', source='com/Example1.java')
+j2 = env.Java(target='class', source='com/Example2.java')
+""")
+
+test.subdir('com')
+
+test.write(['com', 'Example1.java'], """\
+package com;
+
+public class Example1
+{
+
+ public static void main(String[] args)
+ {
+
+ }
+
+}
+""")
+
+test.write(['com', 'Example2.java'], """\
+package com;
+
+public class Example2
+{
+
+ public static void main(String[] args)
+ {
+
+ }
+
+}
+""")
+
+# Setting -processorpath messes with the Java runtime environment, so
+# we'll just take the easy way out and examine the -n output to see if
+# the expected option shows up on the command line.
+
+processorpath = os.pathsep.join(['dir1', 'dir2'])
+
+expect = """\
+javac -processorpath %(processorpath)s -d class -sourcepath com com.Example1\\.java
+javac -processorpath %(processorpath)s -d class -sourcepath com com.Example2\\.java
+""" % locals()
+
+test.run(arguments = '-Q -n .', stdout = expect, match=TestSCons.match_re)
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/Java/inner-cacheable-live.py b/test/Java/inner-cacheable-live.py
new file mode 100644
index 000000000..e0391d2f7
--- /dev/null
+++ b/test/Java/inner-cacheable-live.py
@@ -0,0 +1,77 @@
+#!/usr/bin/env python
+#
+# MIT License
+#
+# Copyright 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.
+
+"""
+Test Java inner classes can be cached. Requires a working JDK.
+
+Regression test: one iteration of CacheDir left it unable to deal
+with class names from the emitter which contained an embedded '$'.
+Led to error like:
+
+SyntaxError `invalid syntax (<string>, line 1)' trying to evaluate `$Inner.class'
+"""
+
+import TestSCons
+
+test = TestSCons.TestSCons()
+where_javac, java_version = test.java_where_javac()
+
+# Work around javac 1.4 not reporting its version:
+java_version = java_version or "1.4"
+
+# Skip this test as SCons doesn't (currently) predict the generated
+# inner/anonymous class generated .class files generated by gcj
+# and so will always fail.
+if test.javac_is_gcj:
+ test.skip_test('Test not valid for gcj (gnu java); skipping test(s).\n')
+
+test.write(
+ 'SConstruct',
+ """
+DefaultEnvironment(tools=[])
+env = Environment()
+env.CacheDir("cache")
+env.Java("classes", "source")
+""",
+)
+
+test.subdir('source')
+
+test.write(
+ ['source', 'Test.java'],
+ """\
+class Test { class Inner {} }
+""",
+)
+
+test.run(arguments='.')
+
+test.pass_test()
+
+# Local Variables:
+# tab-width:4
+# indent-tabs-mode:nil
+# End:
+# vim: set expandtab tabstop=4 shiftwidth=4:
diff --git a/test/rebuild-generated.py b/test/rebuild-generated.py
index 0b3659ea4..91b4e1e7c 100644
--- a/test/rebuild-generated.py
+++ b/test/rebuild-generated.py
@@ -83,7 +83,7 @@ env = Environment()
kernelDefines = env.Command("header.hh", "header.hh.in", Copy('$TARGET', '$SOURCE'))
kernelImporterSource = env.Command("generated.cc", ["%s"], "%s")
kernelImporter = env.Program(kernelImporterSource + ["main.cc"])
-kernelImports = env.Command("KernelImport.hh", kernelImporter, ".%s$SOURCE > $TARGET")
+kernelImports = env.Command("KernelImport.hh", kernelImporter, r".%s$SOURCE > $TARGET")
osLinuxModule = env.StaticObject(["target.cc"])
""" % (generator_name, kernel_action, sep))