Skip to content

Commit c624773

Browse files
committed
Merge branch 'master' into jbrill-msvc-detect
Manually resolved conflicts: * CHANGES.txt * RELEASE.txt * test/MSVS/vs-14.3-exec.py
2 parents 56e1769 + bcf7158 commit c624773

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+1479
-1092
lines changed

CHANGES.txt

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,26 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
6464
added to the default vswhere executable search list after the Chocolatey
6565
installation location.
6666

67-
From Mats Wichmann:
67+
From Thaddeus Crews:
68+
- GetSConsVersion() to grab the latest SCons version without needing to
69+
access SCons internals.
70+
71+
From Raymond Li:
72+
- Fix issue #3935: OSErrors are now no longer hidden during execution of
73+
Actions. All exceptions during the execution of an Action are now
74+
returned by value rather than by raising an exception, for more
75+
consistent behavior.
76+
NOTE: With this change, user created Actions should now catch and handle
77+
expected exceptions (whereas previously many of these were silently
78+
caught and suppressed by the SCons Action exection code).
79+
80+
From Ryan Carsten Schmidt:
81+
- Teach ParseFlags to put a --stdlib=libname argument into CXXFLAGS.
82+
If placed in CCFLAGS (the default location), it could be fed to the
83+
C compiler (gcc, clang) where it is not applicable and causes a
84+
warning message.
6885

86+
From Mats Wichmann:
6987
- Updated Value Node docs and tests.
7088
- Python 3.13 compat: re.sub deprecated count, flags as positional args,
7189
caused update-release-info test to fail.
@@ -74,6 +92,30 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER
7492
json output is also sorted, to match the default display.
7593
- Python 3.13 (alpha) changes the behavior of isabs() on Windows. Adjust
7694
SCons usage of in NodeInfo classes to match. Fixes #4502, #4504.
95+
- Drop duplicated __getstate__ and __setstate__ methods in AliasNodeInfo,
96+
FileNodeInfo and ValueNodeInfo classes, as they are identical to the
97+
ones in parent NodeInfoBase and can just be inherited.
98+
- Update manpage for Tools, and for TOOL, which also gets a minor
99+
tweak for how it's handled (should be more accurate in a few situations).
100+
- Test framework now uses a subdirectory named "scons" below the base
101+
temporary directory. This gives something invariant to tell antivirus
102+
to ignore without having to exclude tmpdir itself. Fixes #4509.
103+
- MSVS "live" tests of project files adjusted to look for the generated
104+
executable with an exe sufffix
105+
- Documentation build now properly passes through skipping the PDF
106+
(and EPUB) builds of manpage and user guide; this can also be done
107+
manually if directly calling doc/man/SConstruct and doc/user/SConstruct
108+
by adding SKIP_PDF=1. This should help with distro packaging of SCons,
109+
which now does not need "fop" and other tools to be set up in order to
110+
build pdf versions which are then ignored.
111+
- Add the ability to print a Variables object for debugging purposes
112+
(provides a __str__ method in the class).
113+
- Mark Python 3.6 support as deprecated.
114+
- Clean up Variables: more consistently call them variables (finish the
115+
old change from Options) in docstrings, etc.; some typing and other
116+
tweaks. Update manpage and user guide for Variables usage.
117+
- Regularize internal usage of Python version strings and drop one
118+
old Python 2-only code block in a test.
77119

78120

79121
RELEASE 4.7.0 - Sun, 17 Mar 2024 17:22:20 -0700

RELEASE.txt

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@ Here is a summary of the changes since 4.7.0:
1616
NEW FUNCTIONALITY
1717
-----------------
1818

19-
- List new features (presumably why a checkpoint is being released)
19+
- GetSConsVersion() added to retrieve the SCons version.
2020

2121
DEPRECATED FUNCTIONALITY
2222
------------------------
2323

24-
- List anything that's been deprecated since the last release
24+
- Mark Python 3.6 support as deprecated. Use --warn=no-python-version
25+
to quiet the warning.
2526

2627
CHANGED/ENHANCED EXISTING FUNCTIONALITY
2728
---------------------------------------
@@ -31,6 +32,18 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY
3132
json output is also sorted, to match the default display.
3233
- Python 3.13 changes the behavior of isabs() on Windows. Adjust SCons
3334
usage of this in NodeInfo classes to avoid test problems.
35+
- Drop duplicated __getstate__ and __setstate__ methods in AliasNodeInfo,
36+
FileNodeInfo and ValueNodeInfo classes, as they are identical to the
37+
ones in parent NodeInfoBase and can just be inherited.
38+
- All exceptions during the execution of an Action are now returned by value
39+
rather than by raising an exception, for more consistent behavior.
40+
NOTE: With this change, user created Actions should now catch and handle
41+
expected exceptions (whereas previously many of these were silently caught
42+
and suppressed by the SCons Action exection code).
43+
- ParseFlags now sorts a --stdlib=libname argument into CXXFLAGS instead
44+
of CCFLAGS; the latter variable could cause a compiler warning.
45+
- The implementation of Variables was slightly refactored, there should
46+
not be user-visible changes.
3447
- MSVC: For msvc version specifications without an 'Exp' suffix, an express
3548
installation is used when no other edition is detected for the msvc version.
3649
This was the behavior for Visual Studio 2008 (9.0) through Visual Studio 2015
@@ -44,6 +57,7 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY
4457
FIXES
4558
-----
4659

60+
- OSErrors are now no longer hidden during the execution of Actions.
4761
- MSVC: Visual Studio 2010 (10.0) could be inadvertently detected due to an
4862
sdk-only install of Windows SDK 7.1. An sdk-only install of Visual Studio
4963
2010 is ignored as the msvc batch files will fail. The installed files are
@@ -77,6 +91,9 @@ FIXES
7791
IMPROVEMENTS
7892
------------
7993

94+
- Make the testing framework a little more resilient: the temporary
95+
directory for tests now includes a component named "scons" which can
96+
be given to antivirus software to exclude.
8097
- MSVC: Visual Studio 2015 Express (14.0Exp) does not support the sdk version
8198
argument. Visual Studio 2015 Express does not support the store argument for
8299
target architectures other than x86. Script argument validation now takes into
@@ -99,13 +116,21 @@ DOCUMENTATION
99116
-------------
100117

101118
- Updated Value Node docs.
119+
- Update manpage for Tools, and for the TOOL variable.
120+
- Update manpage and user guide for Variables usage.
102121

103122

104123

105124
DEVELOPMENT
106125
-----------
107126

108-
- List visible changes in the way SCons is developed
127+
- Documentation build now properly passes through skipping the PDF
128+
(and EPUB) builds of manpage and user guide; this can also be done
129+
manually if directly calling doc/man/SConstruct and doc/user/SConstruct
130+
by adding SKIP_PDF=1. This should help with distro packaging of SCons,
131+
which now does not need "fop" and other tools to be set up in order to
132+
build pdf versions which are then ignored.
133+
109134

110135
Thanks to the following contributors listed below for their contributions to this release.
111136
==========================================================================================

SCons/Action.py

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -892,10 +892,10 @@ def scons_subproc_run(scons_env, *args, **kwargs) -> subprocess.CompletedProcess
892892
kwargs['check'] = check
893893

894894
# TODO: Python version-compat stuff: remap/remove too-new args if needed
895-
if 'text' in kwargs and sys.version_info[:3] < (3, 7):
895+
if 'text' in kwargs and sys.version_info < (3, 7):
896896
kwargs['universal_newlines'] = kwargs.pop('text')
897897

898-
if 'capture_output' in kwargs and sys.version_info[:3] < (3, 7):
898+
if 'capture_output' in kwargs and sys.version_info < (3, 7):
899899
capture_output = kwargs.pop('capture_output')
900900
if capture_output:
901901
kwargs['stdout'] = kwargs['stderr'] = PIPE
@@ -1454,16 +1454,6 @@ def execute(self, target, source, env, executor: Optional[ExecutorType] = None):
14541454
except TypeError:
14551455
result.command=self.strfunction(target, source, env)
14561456

1457-
# FIXME: This maintains backward compatibility with respect to
1458-
# which type of exceptions were returned by raising an
1459-
# exception and which ones were returned by value. It would
1460-
# probably be best to always return them by value here, but
1461-
# some codes do not check the return value of Actions and I do
1462-
# not have the time to modify them at this point.
1463-
if (exc_info[1] and
1464-
not isinstance(exc_info[1], EnvironmentError)):
1465-
raise result
1466-
14671457
return result
14681458
finally:
14691459
# Break the cycle between the traceback object and this

SCons/CacheDirTests.py

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ def __setitem__(self, name, value) -> None:
164164
# so that _readconfig* will try to rewrite it
165165
old_config = os.path.join(self._CacheDir.path, "config")
166166
os.remove(old_config)
167-
167+
168168
try:
169169
self._CacheDir._readconfig(self._CacheDir.path)
170170
assert False, "Should have raised exception and did not"
@@ -315,23 +315,17 @@ def mkdir(dir, mode: int=0) -> None:
315315
old_warn_exceptions = SCons.Warnings.warningAsException(1)
316316
SCons.Warnings.enableWarningClass(SCons.Warnings.CacheWriteErrorWarning)
317317

318-
try:
319-
cd_f7 = self.test.workpath("cd.f7")
320-
self.test.write(cd_f7, "cd.f7\n")
321-
f7 = self.File(cd_f7, 'f7_bsig')
322-
323-
warn_caught = 0
324-
try:
325-
f7.push_to_cache()
326-
except SCons.Errors.BuildError as e:
327-
assert e.exc_info[0] == SCons.Warnings.CacheWriteErrorWarning
328-
warn_caught = 1
329-
assert warn_caught
330-
finally:
331-
shutil.copy2 = save_copy2
332-
os.mkdir = save_mkdir
333-
SCons.Warnings.warningAsException(old_warn_exceptions)
334-
SCons.Warnings.suppressWarningClass(SCons.Warnings.CacheWriteErrorWarning)
318+
cd_f7 = self.test.workpath("cd.f7")
319+
self.test.write(cd_f7, "cd.f7\n")
320+
f7 = self.File(cd_f7, 'f7_bsig')
321+
322+
warn_caught = 0
323+
r = f7.push_to_cache()
324+
assert r.exc_info[0] == SCons.Warnings.CacheWriteErrorWarning
325+
shutil.copy2 = save_copy2
326+
os.mkdir = save_mkdir
327+
SCons.Warnings.warningAsException(old_warn_exceptions)
328+
SCons.Warnings.suppressWarningClass(SCons.Warnings.CacheWriteErrorWarning)
335329

336330
def test_no_strfunction(self) -> None:
337331
"""Test handling no strfunction() for an action."""

SCons/Defaults.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,15 @@ def copy_func(dest, src, symlinks: bool=True) -> int:
291291

292292
elif os.path.islink(src):
293293
if symlinks:
294-
os.symlink(os.readlink(src), dest)
294+
try:
295+
os.symlink(os.readlink(src), dest)
296+
except FileExistsError:
297+
raise SCons.Errors.BuildError(
298+
errstr=(
299+
f'Error: Copy() called to create symlink at "{dest}",'
300+
' but a file already exists at that location.'
301+
)
302+
)
295303
return 0
296304

297305
return copy_func(dest, os.path.realpath(src))

SCons/Environment.py

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
import shlex
3838
from collections import UserDict, UserList, deque
3939
from subprocess import PIPE, DEVNULL
40-
from typing import Optional, Sequence
40+
from typing import Callable, Collection, Optional, Sequence, Union
4141

4242
import SCons.Action
4343
import SCons.Builder
@@ -881,11 +881,11 @@ def ParseFlags(self, *flags) -> dict:
881881
'RPATH' : [],
882882
}
883883

884-
def do_parse(arg) -> None:
885-
# if arg is a sequence, recurse with each element
884+
def do_parse(arg: Union[str, Sequence]) -> None:
886885
if not arg:
887886
return
888887

888+
# if arg is a sequence, recurse with each element
889889
if not is_String(arg):
890890
for t in arg: do_parse(t)
891891
return
@@ -902,7 +902,7 @@ def append_define(name, mapping=mapping) -> None:
902902
else:
903903
mapping['CPPDEFINES'].append([t[0], '='.join(t[1:])])
904904

905-
# Loop through the flags and add them to the appropriate option.
905+
# Loop through the flags and add them to the appropriate variable.
906906
# This tries to strike a balance between checking for all possible
907907
# flags and keeping the logic to a finite size, so it doesn't
908908
# check for some that don't occur often. It particular, if the
@@ -926,6 +926,8 @@ def append_define(name, mapping=mapping) -> None:
926926
append_next_arg_to = None # for multi-word args
927927
for arg in params:
928928
if append_next_arg_to:
929+
# these are the second pass for options where the
930+
# option-argument follows as a second word.
929931
if append_next_arg_to == 'CPPDEFINES':
930932
append_define(arg)
931933
elif append_next_arg_to == '-include':
@@ -1022,6 +1024,8 @@ def append_define(name, mapping=mapping) -> None:
10221024
else:
10231025
key = 'CFLAGS'
10241026
mapping[key].append(arg)
1027+
elif arg.startswith('-stdlib='):
1028+
mapping['CXXFLAGS'].append(arg)
10251029
elif arg[0] == '+':
10261030
mapping['CCFLAGS'].append(arg)
10271031
mapping['LINKFLAGS'].append(arg)
@@ -1250,9 +1254,11 @@ def __init__(
12501254
SCons.Tool.Initializers(self)
12511255

12521256
if tools is None:
1253-
tools = self._dict.get('TOOLS', None)
1254-
if tools is None:
1255-
tools = ['default']
1257+
tools = self._dict.get('TOOLS', ['default'])
1258+
else:
1259+
# for a new env, if we didn't use TOOLS, make sure it starts empty
1260+
# so it only shows tools actually initialized.
1261+
self._dict['TOOLS'] = []
12561262
apply_tools(self, tools, toolpath)
12571263

12581264
# Now restore the passed-in and customized variables
@@ -2014,11 +2020,20 @@ def SetDefault(self, **kw) -> None:
20142020
def _find_toolpath_dir(self, tp):
20152021
return self.fs.Dir(self.subst(tp)).srcnode().get_abspath()
20162022

2017-
def Tool(self, tool, toolpath=None, **kwargs) -> SCons.Tool.Tool:
2023+
def Tool(
2024+
self, tool: Union[str, Callable], toolpath: Optional[Collection[str]] = None, **kwargs
2025+
) -> Callable:
20182026
"""Find and run tool module *tool*.
20192027
2028+
*tool* is generally a string, but can also be a callable object,
2029+
in which case it is just called, without any of the setup.
2030+
The skipped setup includes storing *kwargs* into the created
2031+
:class:`~SCons.Tool.Tool` instance, which is extracted and used
2032+
when the instance is called, so in the skip case, the called
2033+
object will not get the *kwargs*.
2034+
20202035
.. versionchanged:: 4.2
2021-
returns the tool module rather than ``None``.
2036+
returns the tool object rather than ``None``.
20222037
"""
20232038
if is_String(tool):
20242039
tool = self.subst(tool)

0 commit comments

Comments
 (0)