From ed6636eef565968a7212fd631cc98e8b798977e3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 31 Aug 2020 10:12:48 -0400 Subject: Move aix and hpux specific SHLIBSUFFIX to their platform initialization modules --- SCons/Platform/aix.py | 1 + SCons/Platform/hpux.py | 2 ++ SCons/Tool/link.py | 7 +------ 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/SCons/Platform/aix.py b/SCons/Platform/aix.py index 247437a..e5b4d03 100644 --- a/SCons/Platform/aix.py +++ b/SCons/Platform/aix.py @@ -78,6 +78,7 @@ def generate(env): posix.generate(env) #Based on AIX 5.2: ARG_MAX=24576 - 3000 for environment expansion env['MAXLINELENGTH'] = 21576 + env['SHLIBSUFFIX'] = '.a' # Local Variables: # tab-width:4 diff --git a/SCons/Platform/hpux.py b/SCons/Platform/hpux.py index 701be8a..2f455c0 100644 --- a/SCons/Platform/hpux.py +++ b/SCons/Platform/hpux.py @@ -39,6 +39,8 @@ def generate(env): #Based on HP-UX11i: ARG_MAX=2048000 - 3000 for environment expansion env['MAXLINELENGTH'] = 2045000 + env['SHLIBSUFFIX'] = '.sl' + # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/SCons/Tool/link.py b/SCons/Tool/link.py index de377ac..c71ef9d 100644 --- a/SCons/Tool/link.py +++ b/SCons/Tool/link.py @@ -98,7 +98,7 @@ def _lib_emitter(target, source, env, **kw): if symlinks: EmitLibSymlinks(env, symlinks, target[0]) target[0].attributes.shliblinks = symlinks - return (target, source) + return target, source def shlib_emitter(target, source, env): @@ -336,11 +336,6 @@ def generate(env): env['LIBLINKPREFIX'] = '-l' env['LIBLINKSUFFIX'] = '' - if env['PLATFORM'] == 'hpux': - env['SHLIBSUFFIX'] = '.sl' - elif env['PLATFORM'] == 'aix': - env['SHLIBSUFFIX'] = '.a' - # For most platforms, a loadable module is the same as a shared # library. Platforms which are different can override these, but # setting them the same means that LoadableModule works everywhere. -- cgit v0.12 From bb4fa3b232618b8c85f868d552cca0032d45f8b8 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 31 Aug 2020 10:42:10 -0400 Subject: Move sunlink specific versioned library settings into sunlink.py --- SCons/Tool/link.py | 8 ++------ SCons/Tool/sunlink.py | 11 +++++------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/SCons/Tool/link.py b/SCons/Tool/link.py index c71ef9d..5f7ecb3 100644 --- a/SCons/Tool/link.py +++ b/SCons/Tool/link.py @@ -293,12 +293,8 @@ def _setup_versioned_lib_variables(env, **kw): # when VERSIONED library is built (see __SHLIBVERSIONFLAGS in SCons/Defaults.py). if use_soname: # If the linker uses SONAME, then we need this little automata - if tool == 'sunlink': - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -h $_SHLIBSONAME' - env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -h $_LDMODULESONAME' - else: - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' - env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' + env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' + env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' env['_SHLIBSONAME'] = '${ShLibSonameGenerator(__env__,TARGET)}' env['_LDMODULESONAME'] = '${LdModSonameGenerator(__env__,TARGET)}' env['ShLibSonameGenerator'] = ShLibSonameGenerator diff --git a/SCons/Tool/sunlink.py b/SCons/Tool/sunlink.py index 39d9ec2..9fe25a8 100644 --- a/SCons/Tool/sunlink.py +++ b/SCons/Tool/sunlink.py @@ -8,8 +8,6 @@ selection method. """ # -# __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 @@ -30,9 +28,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import os import os.path import SCons.Util @@ -67,7 +62,11 @@ def generate(env): env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}' # Support for versioned libraries - link._setup_versioned_lib_variables(env, tool = 'sunlink', use_soname = True) + link._setup_versioned_lib_variables(env, tool = 'sunlink', use_soname=True) + + env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -h $_SHLIBSONAME' + env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -h $_LDMODULESONAME' + env['LINKCALLBACKS'] = link._versioned_lib_callbacks() def exists(env): -- cgit v0.12 From b366af5f4518839fc03809c1d0ac5a3e470562ca Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 31 Aug 2020 11:52:11 -0400 Subject: refactor common link logic from link.py -> linkCommon --- SCons/Tool/applelink.py | 8 +- SCons/Tool/cyglink.py | 13 +- SCons/Tool/gnulink.py | 5 +- SCons/Tool/link.py | 273 +------------------------------------- SCons/Tool/linkCommon/__init__.py | 269 ++++++++++++++++++++++++++++++++++++- SCons/Tool/sunlink.py | 5 +- 6 files changed, 287 insertions(+), 286 deletions(-) diff --git a/SCons/Tool/applelink.py b/SCons/Tool/applelink.py index aec8b93..9463308 100644 --- a/SCons/Tool/applelink.py +++ b/SCons/Tool/applelink.py @@ -33,6 +33,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import SCons.Tool.linkCommon import SCons.Util # Even though the Mac is based on the GNU toolchain, it doesn't understand @@ -85,7 +86,8 @@ def _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, name_f def _applelib_versioned_shlib_soname(env, libnode, version, prefix, suffix): - return _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, link._versioned_shlib_name) + return _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, + SCons.Tool.linkCommon._versioned_shlib_name) # User programmatically describes how SHLIBVERSION maps to values for compat/current. @@ -197,8 +199,8 @@ def generate(env): env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' # see: http://docstore.mik.ua/orelly/unix3/mac/ch05_04.htm for proper naming - link._setup_versioned_lib_variables(env, tool='applelink') #, use_soname=True) - env['LINKCALLBACKS'] = link._versioned_lib_callbacks() + SCons.Tool.linkCommon._setup_versioned_lib_variables(env, tool='applelink', use_soname=True) + env['LINKCALLBACKS'] = SCons.Tool.linkCommon._versioned_lib_callbacks() env['LINKCALLBACKS']['VersionedShLibSuffix'] = _applelib_versioned_lib_suffix env['LINKCALLBACKS']['VersionedShLibSoname'] = _applelib_versioned_shlib_soname diff --git a/SCons/Tool/cyglink.py b/SCons/Tool/cyglink.py index 08b8a98..fd8c1fd 100644 --- a/SCons/Tool/cyglink.py +++ b/SCons/Tool/cyglink.py @@ -12,6 +12,7 @@ import re import os import SCons.Action +import SCons.Tool.linkCommon from SCons.Tool.linkCommon import ImpLibSymlinkGenerator, StringizeLibSymlinks, EmitLibSymlinks, ImpLibPrefixGenerator, \ ImpLibSuffixGenerator, ImpLibNameGenerator import SCons.Util @@ -156,10 +157,10 @@ def _versioned_lib_suffix(env, suffix, version): def _versioned_implib_name(env, libnode, version, prefix, suffix, **kw): - return link._versioned_lib_name(env, libnode, version, prefix, suffix, - ImpLibPrefixGenerator, - ImpLibSuffixGenerator, - implib_libtype=kw['libtype']) + return SCons.Tool.linkCommon._versioned_lib_name(env, libnode, version, prefix, suffix, + ImpLibPrefixGenerator, + ImpLibSuffixGenerator, + implib_libtype=kw['libtype']) def _versioned_implib_symlinks(env, libnode, version, prefix, suffix, **kw): @@ -230,8 +231,8 @@ def generate(env): 'VersionedShLibSuffix': _versioned_lib_suffix, 'VersionedLdModSuffix': _versioned_lib_suffix, 'VersionedImpLibSuffix': _versioned_lib_suffix, - 'VersionedShLibName': link._versioned_shlib_name, - 'VersionedLdModName': link._versioned_ldmod_name, + 'VersionedShLibName': SCons.Tool.linkCommon._versioned_shlib_name, + 'VersionedLdModName': SCons.Tool.linkCommon._versioned_ldmod_name, 'VersionedShLibImpLibName': lambda *args: _versioned_implib_name(*args, libtype='ShLib'), 'VersionedLdModImpLibName': lambda *args: _versioned_implib_name(*args, libtype='LdMod'), 'VersionedShLibImpLibSymlinks': lambda *args: _versioned_implib_symlinks(*args, libtype='ShLib'), diff --git a/SCons/Tool/gnulink.py b/SCons/Tool/gnulink.py index 5372322..51932da 100644 --- a/SCons/Tool/gnulink.py +++ b/SCons/Tool/gnulink.py @@ -33,6 +33,7 @@ selection method. __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +import SCons.Tool.linkCommon import SCons.Util import SCons.Tool import sys @@ -55,8 +56,8 @@ def generate(env): # OpenBSD doesn't usually use SONAME for libraries use_soname = not sys.platform.startswith('openbsd') - link._setup_versioned_lib_variables(env, tool='gnulink', use_soname=use_soname) - env['LINKCALLBACKS'] = link._versioned_lib_callbacks() + SCons.Tool.linkCommon._setup_versioned_lib_variables(env, tool='gnulink', use_soname=use_soname) + env['LINKCALLBACKS'] = SCons.Tool.linkCommon._versioned_lib_callbacks() # # For backward-compatibility with older SCons versions # env['SHLIBVERSIONFLAGS'] = SCons.Util.CLVar('') diff --git a/SCons/Tool/link.py b/SCons/Tool/link.py index 5f7ecb3..9d6caef 100644 --- a/SCons/Tool/link.py +++ b/SCons/Tool/link.py @@ -29,282 +29,11 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -import sys -import re -import os - import SCons.Tool import SCons.Util import SCons.Warnings -from SCons.Tool.FortranCommon import isfortran - -from SCons.Tool.DCommon import isD - -from SCons.Tool.cxx import iscplusplus - -from SCons.Tool.linkCommon import StringizeLibSymlinks, ShLibSonameGenerator, EmitLibSymlinks, ShLibSymlinkGenerator, \ - LdModSymlinkGenerator, ShLibPrefixGenerator, ShLibSuffixGenerator, LdModPrefixGenerator, LdModSuffixGenerator, \ - LdModSonameGenerator - -issued_mixed_link_warning = False - - -def smart_link(source, target, env, for_signature): - has_cplusplus = iscplusplus(source) - has_fortran = isfortran(env, source) - has_d = isD(env, source) - 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')) - issued_mixed_link_warning = True - return '$CXX' - elif has_d: - env['LINKCOM'] = env['DLINKCOM'] - env['SHLINKCOM'] = env['SHDLINKCOM'] - return '$DC' - elif has_fortran: - return '$FORTRAN' - elif has_cplusplus: - return '$CXX' - return '$CC' - - -def _lib_emitter(target, source, env, **kw): - Verbose = False - if Verbose: - print("_lib_emitter: target[0]={!r}".format(target[0].get_path())) - for tgt in target: - if SCons.Util.is_String(tgt): - tgt = env.File(tgt) - tgt.attributes.shared = 1 - - try: - symlink_generator = kw['symlink_generator'] - except KeyError: - pass - else: - if Verbose: - print("_lib_emitter: symlink_generator={!r}".format(symlink_generator)) - symlinks = symlink_generator(env, target[0]) - if Verbose: - print("_lib_emitter: symlinks={!r}".format(symlinks)) - - if symlinks: - EmitLibSymlinks(env, symlinks, target[0]) - target[0].attributes.shliblinks = symlinks - return target, source - - -def shlib_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator=ShLibSymlinkGenerator) - - -def ldmod_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator=LdModSymlinkGenerator) - - -# This is generic enough to be included here... -def _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw): - """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so'""" - Verbose = False - - if Verbose: - print("_versioned_lib_name: libnode={!r}".format(libnode.get_path())) - print("_versioned_lib_name: version={!r}".format(version)) - print("_versioned_lib_name: prefix={!r}".format(prefix)) - print("_versioned_lib_name: suffix={!r}".format(suffix)) - print("_versioned_lib_name: suffix_generator={!r}".format(suffix_generator)) - - versioned_name = os.path.basename(libnode.get_path()) - if Verbose: - print("_versioned_lib_name: versioned_name={!r}".format(versioned_name)) - - versioned_prefix = prefix_generator(env, **kw) - versioned_suffix = suffix_generator(env, **kw) - if Verbose: - print("_versioned_lib_name: versioned_prefix={!r}".format(versioned_prefix)) - print("_versioned_lib_name: versioned_suffix={!r}".format(versioned_suffix)) - - versioned_prefix_re = '^' + re.escape(versioned_prefix) - versioned_suffix_re = re.escape(versioned_suffix) + '$' - name = re.sub(versioned_prefix_re, prefix, versioned_name) - name = re.sub(versioned_suffix_re, suffix, name) - if Verbose: - print("_versioned_lib_name: name={!r}".format(name)) - return name - - -def _versioned_shlib_name(env, libnode, version, prefix, suffix, **kw): - prefix_generator = ShLibPrefixGenerator - suffix_generator = ShLibSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) - - -def _versioned_ldmod_name(env, libnode, version, prefix, suffix, **kw): - prefix_generator = LdModPrefixGenerator - suffix_generator = LdModSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) - - -def _versioned_lib_suffix(env, suffix, version): - """For suffix='.so' and version='0.1.2' it returns '.so.0.1.2'""" - Verbose = False - if Verbose: - print("_versioned_lib_suffix: suffix={!r}".format(suffix)) - print("_versioned_lib_suffix: version={!r}".format(version)) - if not suffix.endswith(version): - suffix = suffix + '.' + version - if Verbose: - print("_versioned_lib_suffix: return suffix={!r}".format(suffix)) - return suffix - - -def _versioned_lib_soname(env, libnode, version, prefix, suffix, name_func): - """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so.X'""" - Verbose = False - if Verbose: - print("_versioned_lib_soname: version={!r}".format(version)) - name = name_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_versioned_lib_soname: name={!r}".format(name)) - major = version.split('.')[0] - - # if a desired SONAME was supplied, use that, otherwise create - # a default from the major version - if env.get('SONAME'): - soname = ShLibSonameGenerator(env, libnode) - else: - soname = name + '.' + major - if Verbose: - print("_versioned_lib_soname: soname={!r}".format(soname)) - return soname - - -def _versioned_shlib_soname(env, libnode, version, prefix, suffix): - return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_shlib_name) - - -def _versioned_ldmod_soname(env, libnode, version, prefix, suffix): - return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_ldmod_name) - - -def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func): - """Generate link names that should be created for a versioned shared library. - Returns a dictionary in the form { linkname : linktarget } - """ - Verbose = False - - if Verbose: - print("_versioned_lib_symlinks: libnode={!r}".format(libnode.get_path())) - print("_versioned_lib_symlinks: version={!r}".format(version)) - - if sys.platform.startswith('openbsd'): - # OpenBSD uses x.y shared library versioning numbering convention - # and doesn't use symlinks to backwards-compatible libraries - if Verbose: - print("_versioned_lib_symlinks: return symlinks={!r}".format(None)) - return None - - linkdir = libnode.get_dir() - if Verbose: - print("_versioned_lib_symlinks: linkdir={!r}".format(linkdir.get_path())) - - name = name_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_versioned_lib_symlinks: name={!r}".format(name)) - - soname = soname_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_versioned_lib_symlinks: soname={!r}".format(soname)) - - link0 = env.fs.File(soname, linkdir) - link1 = env.fs.File(name, linkdir) - - # We create direct symlinks, not daisy-chained. - if link0 == libnode: - # This enables SHLIBVERSION without periods (e.g. SHLIBVERSION=1) - symlinks = [(link1, libnode)] - else: - # This handles usual SHLIBVERSION, i.e. '1.2', '1.2.3', etc. - symlinks = [(link0, libnode), (link1, libnode)] - - if Verbose: - print("_versioned_lib_symlinks: return symlinks={!r}".format( - StringizeLibSymlinks(symlinks))) - - return symlinks - - -def _versioned_shlib_symlinks(env, libnode, version, prefix, suffix): - name_func = env['LINKCALLBACKS']['VersionedShLibName'] - soname_func = env['LINKCALLBACKS']['VersionedShLibSoname'] - - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) - - -def _versioned_ldmod_symlinks(env, libnode, version, prefix, suffix): - name_func = _versioned_ldmod_name - soname_func = _versioned_ldmod_soname - - name_func = env['LINKCALLBACKS']['VersionedLdModName'] - soname_func = env['LINKCALLBACKS']['VersionedLdModSoname'] - - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) - - -def _versioned_lib_callbacks(): - return { - 'VersionedShLibSuffix': _versioned_lib_suffix, - 'VersionedLdModSuffix': _versioned_lib_suffix, - 'VersionedShLibSymlinks': _versioned_shlib_symlinks, - 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, - 'VersionedShLibName': _versioned_shlib_name, - 'VersionedLdModName': _versioned_ldmod_name, - 'VersionedShLibSoname': _versioned_shlib_soname, - 'VersionedLdModSoname': _versioned_ldmod_soname, - }.copy() - - -def _setup_versioned_lib_variables(env, **kw): - """ - Setup all variables required by the versioning machinery - """ - - tool = None - try: - tool = kw['tool'] - except KeyError: - pass - - use_soname = False - try: - use_soname = kw['use_soname'] - except KeyError: - pass - - # The $_SHLIBVERSIONFLAGS define extra commandline flags used when - # building VERSIONED shared libraries. It's always set, but used only - # when VERSIONED library is built (see __SHLIBVERSIONFLAGS in SCons/Defaults.py). - if use_soname: - # If the linker uses SONAME, then we need this little automata - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' - env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' - env['_SHLIBSONAME'] = '${ShLibSonameGenerator(__env__,TARGET)}' - env['_LDMODULESONAME'] = '${LdModSonameGenerator(__env__,TARGET)}' - env['ShLibSonameGenerator'] = ShLibSonameGenerator - env['LdModSonameGenerator'] = LdModSonameGenerator - else: - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' - env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS' - - # LDOMDULVERSIONFLAGS should always default to $SHLIBVERSIONFLAGS - env['LDMODULEVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' +from SCons.Tool.linkCommon import smart_link, shlib_emitter, ldmod_emitter def generate(env): diff --git a/SCons/Tool/linkCommon/__init__.py b/SCons/Tool/linkCommon/__init__.py index f11aa14..c3ccd7a 100644 --- a/SCons/Tool/linkCommon/__init__.py +++ b/SCons/Tool/linkCommon/__init__.py @@ -23,7 +23,15 @@ Common link/shared library logic # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import os +import re +import sys from typing import Callable + +import SCons.Util +import SCons.Warnings +from SCons.Tool.DCommon import isD +from SCons.Tool.FortranCommon import isfortran +from SCons.Tool.cxx import iscplusplus from SCons.Util import is_List @@ -500,4 +508,263 @@ def _call_env_subst(env, string, *args, **kw): kw2[k] = kw[k] except KeyError: pass - return env.subst(string, *args, **kw2) \ No newline at end of file + return env.subst(string, *args, **kw2) + + +def smart_link(source, target, env, for_signature): + has_cplusplus = iscplusplus(source) + has_fortran = isfortran(env, source) + has_d = isD(env, source) + 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')) + issued_mixed_link_warning = True + return '$CXX' + elif has_d: + env['LINKCOM'] = env['DLINKCOM'] + env['SHLINKCOM'] = env['SHDLINKCOM'] + return '$DC' + elif has_fortran: + return '$FORTRAN' + elif has_cplusplus: + return '$CXX' + return '$CC' + + +def _lib_emitter(target, source, env, **kw): + Verbose = False + if Verbose: + print("_lib_emitter: target[0]={!r}".format(target[0].get_path())) + for tgt in target: + if SCons.Util.is_String(tgt): + tgt = env.File(tgt) + tgt.attributes.shared = 1 + + try: + symlink_generator = kw['symlink_generator'] + except KeyError: + pass + else: + if Verbose: + print("_lib_emitter: symlink_generator={!r}".format(symlink_generator)) + symlinks = symlink_generator(env, target[0]) + if Verbose: + print("_lib_emitter: symlinks={!r}".format(symlinks)) + + if symlinks: + EmitLibSymlinks(env, symlinks, target[0]) + target[0].attributes.shliblinks = symlinks + return target, source + + +def shlib_emitter(target, source, env): + return _lib_emitter(target, source, env, symlink_generator=ShLibSymlinkGenerator) + + +def ldmod_emitter(target, source, env): + return _lib_emitter(target, source, env, symlink_generator=LdModSymlinkGenerator) + + +def _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw): + """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so'""" + Verbose = False + + if Verbose: + print("_versioned_lib_name: libnode={!r}".format(libnode.get_path())) + print("_versioned_lib_name: version={!r}".format(version)) + print("_versioned_lib_name: prefix={!r}".format(prefix)) + print("_versioned_lib_name: suffix={!r}".format(suffix)) + print("_versioned_lib_name: suffix_generator={!r}".format(suffix_generator)) + + versioned_name = os.path.basename(libnode.get_path()) + if Verbose: + print("_versioned_lib_name: versioned_name={!r}".format(versioned_name)) + + versioned_prefix = prefix_generator(env, **kw) + versioned_suffix = suffix_generator(env, **kw) + if Verbose: + print("_versioned_lib_name: versioned_prefix={!r}".format(versioned_prefix)) + print("_versioned_lib_name: versioned_suffix={!r}".format(versioned_suffix)) + + versioned_prefix_re = '^' + re.escape(versioned_prefix) + versioned_suffix_re = re.escape(versioned_suffix) + '$' + name = re.sub(versioned_prefix_re, prefix, versioned_name) + name = re.sub(versioned_suffix_re, suffix, name) + if Verbose: + print("_versioned_lib_name: name={!r}".format(name)) + return name + + +def _versioned_shlib_name(env, libnode, version, prefix, suffix, **kw): + prefix_generator = ShLibPrefixGenerator + suffix_generator = ShLibSuffixGenerator + return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) + + +def _versioned_ldmod_name(env, libnode, version, prefix, suffix, **kw): + prefix_generator = LdModPrefixGenerator + suffix_generator = LdModSuffixGenerator + return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) + + +def _versioned_lib_suffix(env, suffix, version): + """For suffix='.so' and version='0.1.2' it returns '.so.0.1.2'""" + Verbose = False + if Verbose: + print("_versioned_lib_suffix: suffix={!r}".format(suffix)) + print("_versioned_lib_suffix: version={!r}".format(version)) + if not suffix.endswith(version): + suffix = suffix + '.' + version + if Verbose: + print("_versioned_lib_suffix: return suffix={!r}".format(suffix)) + return suffix + + +def _versioned_lib_soname(env, libnode, version, prefix, suffix, name_func): + """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so.X'""" + Verbose = False + if Verbose: + print("_versioned_lib_soname: version={!r}".format(version)) + name = name_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_versioned_lib_soname: name={!r}".format(name)) + major = version.split('.')[0] + + # if a desired SONAME was supplied, use that, otherwise create + # a default from the major version + if env.get('SONAME'): + soname = ShLibSonameGenerator(env, libnode) + else: + soname = name + '.' + major + if Verbose: + print("_versioned_lib_soname: soname={!r}".format(soname)) + return soname + + +def _versioned_shlib_soname(env, libnode, version, prefix, suffix): + return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_shlib_name) + + +def _versioned_ldmod_soname(env, libnode, version, prefix, suffix): + return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_ldmod_name) + + +def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func): + """Generate link names that should be created for a versioned shared library. + Returns a dictionary in the form { linkname : linktarget } + """ + Verbose = False + + if Verbose: + print("_versioned_lib_symlinks: libnode={!r}".format(libnode.get_path())) + print("_versioned_lib_symlinks: version={!r}".format(version)) + + if sys.platform.startswith('openbsd'): + # OpenBSD uses x.y shared library versioning numbering convention + # and doesn't use symlinks to backwards-compatible libraries + if Verbose: + print("_versioned_lib_symlinks: return symlinks={!r}".format(None)) + return None + + linkdir = libnode.get_dir() + if Verbose: + print("_versioned_lib_symlinks: linkdir={!r}".format(linkdir.get_path())) + + name = name_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_versioned_lib_symlinks: name={!r}".format(name)) + + soname = soname_func(env, libnode, version, prefix, suffix) + if Verbose: + print("_versioned_lib_symlinks: soname={!r}".format(soname)) + + link0 = env.fs.File(soname, linkdir) + link1 = env.fs.File(name, linkdir) + + # We create direct symlinks, not daisy-chained. + if link0 == libnode: + # This enables SHLIBVERSION without periods (e.g. SHLIBVERSION=1) + symlinks = [(link1, libnode)] + else: + # This handles usual SHLIBVERSION, i.e. '1.2', '1.2.3', etc. + symlinks = [(link0, libnode), (link1, libnode)] + + if Verbose: + print("_versioned_lib_symlinks: return symlinks={!r}".format( + StringizeLibSymlinks(symlinks))) + + return symlinks + + +def _versioned_shlib_symlinks(env, libnode, version, prefix, suffix): + name_func = env['LINKCALLBACKS']['VersionedShLibName'] + soname_func = env['LINKCALLBACKS']['VersionedShLibSoname'] + + return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) + + +def _versioned_ldmod_symlinks(env, libnode, version, prefix, suffix): + name_func = _versioned_ldmod_name + soname_func = _versioned_ldmod_soname + + name_func = env['LINKCALLBACKS']['VersionedLdModName'] + soname_func = env['LINKCALLBACKS']['VersionedLdModSoname'] + + return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) + + +def _versioned_lib_callbacks(): + return { + 'VersionedShLibSuffix': _versioned_lib_suffix, + 'VersionedLdModSuffix': _versioned_lib_suffix, + 'VersionedShLibSymlinks': _versioned_shlib_symlinks, + 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, + 'VersionedShLibName': _versioned_shlib_name, + 'VersionedLdModName': _versioned_ldmod_name, + 'VersionedShLibSoname': _versioned_shlib_soname, + 'VersionedLdModSoname': _versioned_ldmod_soname, + }.copy() + + +issued_mixed_link_warning = False + + +def _setup_versioned_lib_variables(env, **kw): + """ + Setup all variables required by the versioning machinery + """ + + tool = None + try: + tool = kw['tool'] + except KeyError: + pass + + use_soname = False + try: + use_soname = kw['use_soname'] + except KeyError: + pass + + # The $_SHLIBVERSIONFLAGS define extra commandline flags used when + # building VERSIONED shared libraries. It's always set, but used only + # when VERSIONED library is built (see __SHLIBVERSIONFLAGS in SCons/Defaults.py). + if use_soname: + # If the linker uses SONAME, then we need this little automata + env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' + env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' + env['_SHLIBSONAME'] = '${ShLibSonameGenerator(__env__,TARGET)}' + env['_LDMODULESONAME'] = '${LdModSonameGenerator(__env__,TARGET)}' + env['ShLibSonameGenerator'] = ShLibSonameGenerator + env['LdModSonameGenerator'] = LdModSonameGenerator + else: + env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' + env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS' + + # LDOMDULVERSIONFLAGS should always default to $SHLIBVERSIONFLAGS + env['LDMODULEVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' \ No newline at end of file diff --git a/SCons/Tool/sunlink.py b/SCons/Tool/sunlink.py index 9fe25a8..c33ba5a 100644 --- a/SCons/Tool/sunlink.py +++ b/SCons/Tool/sunlink.py @@ -30,6 +30,7 @@ selection method. import os.path +import SCons.Tool.linkCommon import SCons.Util from . import link @@ -62,12 +63,12 @@ def generate(env): env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}' # Support for versioned libraries - link._setup_versioned_lib_variables(env, tool = 'sunlink', use_soname=True) + SCons.Tool.linkCommon._setup_versioned_lib_variables(env, tool ='sunlink', use_soname=True) env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -h $_SHLIBSONAME' env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -h $_LDMODULESONAME' - env['LINKCALLBACKS'] = link._versioned_lib_callbacks() + env['LINKCALLBACKS'] = SCons.Tool.linkCommon._versioned_lib_callbacks() def exists(env): return ccLinker -- cgit v0.12 From e1604ea37594031fa5440bd9ba8d33d712ee63a0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 31 Aug 2020 14:51:55 -0400 Subject: refactor cleanup. circular import issues resolved by moving isolated imports into the few functions they are used in rather than globally in the module --- SCons/Defaults.py | 3 --- SCons/Tool/FortranCommon.py | 6 ++--- SCons/Tool/aixlink.py | 9 +++---- SCons/Tool/applelink.py | 4 --- SCons/Tool/cxx.py | 5 ---- SCons/Tool/cyglink.py | 9 +++---- SCons/Tool/gnulink.py | 11 +++----- SCons/Tool/hplink.py | 5 ---- SCons/Tool/ilink.py | 4 --- SCons/Tool/linkCommon/README.md | 56 +++++++++++++++++++++++++++++++++++++++ SCons/Tool/linkCommon/__init__.py | 9 ++++--- SCons/Tool/mslink.py | 3 --- SCons/Tool/sgilink.py | 3 --- SCons/Tool/sunlink.py | 6 ++--- 14 files changed, 76 insertions(+), 57 deletions(-) create mode 100644 SCons/Tool/linkCommon/README.md diff --git a/SCons/Defaults.py b/SCons/Defaults.py index b3f6d1d..c23d564 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -10,8 +10,6 @@ from distutils.msvccompiler. """ # -# __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 @@ -31,7 +29,6 @@ from distutils.msvccompiler. # 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 os diff --git a/SCons/Tool/FortranCommon.py b/SCons/Tool/FortranCommon.py index bfa1c1c..f8d9fdc 100644 --- a/SCons/Tool/FortranCommon.py +++ b/SCons/Tool/FortranCommon.py @@ -5,8 +5,6 @@ Stuff for processing Fortran, common to all fortran dialects. """ # -# __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 @@ -26,13 +24,11 @@ Stuff for processing Fortran, common to all fortran dialects. # 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 re import os.path import SCons.Action -import SCons.Defaults import SCons.Scanner.Fortran import SCons.Tool import SCons.Util @@ -78,10 +74,12 @@ def _fortranEmitter(target, source, env): return (target, source) def FortranEmitter(target, source, env): + import SCons.Defaults target, source = _fortranEmitter(target, source, env) return SCons.Defaults.StaticObjectEmitter(target, source, env) def ShFortranEmitter(target, source, env): + import SCons.Defaults target, source = _fortranEmitter(target, source, env) return SCons.Defaults.SharedObjectEmitter(target, source, env) diff --git a/SCons/Tool/aixlink.py b/SCons/Tool/aixlink.py index fed4342..dc0de2a 100644 --- a/SCons/Tool/aixlink.py +++ b/SCons/Tool/aixlink.py @@ -8,8 +8,6 @@ selection method. """ # -# __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 @@ -30,8 +28,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import os import os.path @@ -42,7 +38,6 @@ from . import link import SCons.Tool.cxx cplusplus = SCons.Tool.cxx -#cplusplus = __import__('cxx', globals(), locals(), []) def smart_linkflags(source, target, env, for_signature): @@ -52,6 +47,7 @@ def smart_linkflags(source, target, env, for_signature): return '-qtempinc=' + os.path.join(build_dir, 'tempinc') return '' + def generate(env): """ Add Builders and construction variables for Visual Age linker to @@ -64,12 +60,13 @@ def generate(env): env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -qmkshrobj -qsuppress=1501-218') env['SHLIBSUFFIX'] = '.a' + def exists(env): # TODO: sync with link.smart_link() to choose a linker linkers = { 'CXX': ['aixc++'], 'CC': ['aixcc'] } alltools = [] for langvar, linktools in linkers.items(): - if langvar in env: # use CC over CXX when user specified CC but not CXX + if langvar in env: # use CC over CXX when user specified CC but not CXX return SCons.Tool.FindTool(linktools, env) alltools.extend(linktools) return SCons.Tool.FindTool(alltools, env) diff --git a/SCons/Tool/applelink.py b/SCons/Tool/applelink.py index 9463308..f51a6af 100644 --- a/SCons/Tool/applelink.py +++ b/SCons/Tool/applelink.py @@ -9,8 +9,6 @@ selection method. """ # -# __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 @@ -31,8 +29,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import SCons.Tool.linkCommon import SCons.Util diff --git a/SCons/Tool/cxx.py b/SCons/Tool/cxx.py index 430851c..128cdc4 100644 --- a/SCons/Tool/cxx.py +++ b/SCons/Tool/cxx.py @@ -8,8 +8,6 @@ selection method. """ # -# __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 @@ -30,11 +28,8 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import os.path -import SCons.Tool import SCons.Defaults import SCons.Util diff --git a/SCons/Tool/cyglink.py b/SCons/Tool/cyglink.py index fd8c1fd..e85797b 100644 --- a/SCons/Tool/cyglink.py +++ b/SCons/Tool/cyglink.py @@ -12,14 +12,13 @@ import re import os import SCons.Action -import SCons.Tool.linkCommon +import SCons.Tool.linkCommon as linkCommon from SCons.Tool.linkCommon import ImpLibSymlinkGenerator, StringizeLibSymlinks, EmitLibSymlinks, ImpLibPrefixGenerator, \ ImpLibSuffixGenerator, ImpLibNameGenerator import SCons.Util import SCons.Tool from . import gnulink -from . import link def _lib_generator(target, source, env, for_signature, **kw): @@ -157,7 +156,7 @@ def _versioned_lib_suffix(env, suffix, version): def _versioned_implib_name(env, libnode, version, prefix, suffix, **kw): - return SCons.Tool.linkCommon._versioned_lib_name(env, libnode, version, prefix, suffix, + return linkCommon._versioned_lib_name(env, libnode, version, prefix, suffix, ImpLibPrefixGenerator, ImpLibSuffixGenerator, implib_libtype=kw['libtype']) @@ -231,8 +230,8 @@ def generate(env): 'VersionedShLibSuffix': _versioned_lib_suffix, 'VersionedLdModSuffix': _versioned_lib_suffix, 'VersionedImpLibSuffix': _versioned_lib_suffix, - 'VersionedShLibName': SCons.Tool.linkCommon._versioned_shlib_name, - 'VersionedLdModName': SCons.Tool.linkCommon._versioned_ldmod_name, + 'VersionedShLibName': linkCommon._versioned_shlib_name, + 'VersionedLdModName': linkCommon._versioned_ldmod_name, 'VersionedShLibImpLibName': lambda *args: _versioned_implib_name(*args, libtype='ShLib'), 'VersionedLdModImpLibName': lambda *args: _versioned_implib_name(*args, libtype='LdMod'), 'VersionedShLibImpLibSymlinks': lambda *args: _versioned_implib_symlinks(*args, libtype='ShLib'), diff --git a/SCons/Tool/gnulink.py b/SCons/Tool/gnulink.py index 51932da..2b09549 100644 --- a/SCons/Tool/gnulink.py +++ b/SCons/Tool/gnulink.py @@ -9,8 +9,6 @@ selection method. """ # -# __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 @@ -31,7 +29,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Tool.linkCommon import SCons.Util @@ -39,6 +36,7 @@ import SCons.Tool import sys from . import link +import SCons.Tool.linkCommon as linkCommon def generate(env): @@ -56,11 +54,8 @@ def generate(env): # OpenBSD doesn't usually use SONAME for libraries use_soname = not sys.platform.startswith('openbsd') - SCons.Tool.linkCommon._setup_versioned_lib_variables(env, tool='gnulink', use_soname=use_soname) - env['LINKCALLBACKS'] = SCons.Tool.linkCommon._versioned_lib_callbacks() - - # # For backward-compatibility with older SCons versions - # env['SHLIBVERSIONFLAGS'] = SCons.Util.CLVar('') + linkCommon._setup_versioned_lib_variables(env, tool='gnulink', use_soname=use_soname) + env['LINKCALLBACKS'] = linkCommon._versioned_lib_callbacks() def exists(env): diff --git a/SCons/Tool/hplink.py b/SCons/Tool/hplink.py index 10ef30b..ba182f1 100644 --- a/SCons/Tool/hplink.py +++ b/SCons/Tool/hplink.py @@ -8,8 +8,6 @@ selection method. """ # -# __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 @@ -30,9 +28,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -import os import os.path import SCons.Util diff --git a/SCons/Tool/ilink.py b/SCons/Tool/ilink.py index aa6bcaa..4112825 100644 --- a/SCons/Tool/ilink.py +++ b/SCons/Tool/ilink.py @@ -9,8 +9,6 @@ selection method. """ # -# __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 @@ -31,8 +29,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import SCons.Defaults import SCons.Tool import SCons.Util diff --git a/SCons/Tool/linkCommon/README.md b/SCons/Tool/linkCommon/README.md new file mode 100644 index 0000000..26bc9a5 --- /dev/null +++ b/SCons/Tool/linkCommon/README.md @@ -0,0 +1,56 @@ + + +# Versioned Shared Library and Loadable modules requirements + +The following env variables can affect the command line and created files for these + +* `SHLIBVERSION` +* `SONAME` +* `SOVERSION` +* `APPLELINK_NO_CURRENT_VERSION` (applelink only) +* `APPLELINK_CURRENT_VERSION` (applelink only) +* `APPLELINK_COMPATIBILITY_VERSION` (applelink only) + +In most cases the linker will create a file named as + +`${SHLIBPREFIX}lib_name${SHLIBVERSION}${SHLIBSUFFIX}` + +Which will have a soname baked into it as one of the + +* `${SONAME}` +* `${SHLIBPREFIX}lib_name${SOVERSION}${SHLIBSUFFIX}` +* (for applelink only) + * `${SHLIBPREFIX}lib_name${major version only from SHLIBVERSION}${SHLIBSUFFIX}` + * `-Wl,-compatibility_version,%s` + * `-Wl,-current_version,%s` + +For **applelink** the version has to follow these rules to verify that the version # is valid. + +* For version # = X[.Y[.Z]] +* where X 0-65535 +* where Y either not specified or 0-255 +* where Z either not specified or 0-255 + + + +For most platforms this will lead to a series of symlinks eventually pointing to the actual shared library (or loadable module file). +1. `${SHLIBPREFIX}lib_name${SHLIBSUFFIX} -> ${SHLIBPREFIX}lib_name${SHLIBVERSION}${SHLIBSUFFIX}` +1. `${SHLIBPREFIX}lib_name${SOVERSION}${SHLIBSUFFIX} -> ${SHLIBPREFIX}lib_name${SHLIBVERSION}${SHLIBSUFFIX}` + +For **openbsd** the following rules for symlinks apply + + * OpenBSD uses x.y shared library versioning numbering convention and doesn't use symlinks to backwards-compatible libraries + + +The current code provides the following hooks a compiler can use to customize: + +``` + 'VersionedShLibSuffix': _versioned_lib_suffix, + 'VersionedLdModSuffix': _versioned_lib_suffix, + 'VersionedShLibSymlinks': _versioned_shlib_symlinks, + 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, + 'VersionedShLibName': _versioned_shlib_name, + 'VersionedLdModName': _versioned_ldmod_name, + 'VersionedShLibSoname': _versioned_shlib_soname, + 'VersionedLdModSoname': _versioned_ldmod_soname, +``` \ No newline at end of file diff --git a/SCons/Tool/linkCommon/__init__.py b/SCons/Tool/linkCommon/__init__.py index c3ccd7a..c787e0c 100644 --- a/SCons/Tool/linkCommon/__init__.py +++ b/SCons/Tool/linkCommon/__init__.py @@ -30,8 +30,6 @@ from typing import Callable import SCons.Util import SCons.Warnings from SCons.Tool.DCommon import isD -from SCons.Tool.FortranCommon import isfortran -from SCons.Tool.cxx import iscplusplus from SCons.Util import is_List @@ -512,8 +510,11 @@ def _call_env_subst(env, string, *args, **kw): def smart_link(source, target, env, for_signature): - has_cplusplus = iscplusplus(source) - has_fortran = isfortran(env, source) + import SCons.Tool.cxx + import SCons.Tool.fortran + + has_cplusplus = SCons.Tool.cxx.iscplusplus(source) + has_fortran = SCons.Tool.fortran.isfortran(env, source) has_d = isD(env, source) if has_cplusplus and has_fortran and not has_d: global issued_mixed_link_warning diff --git a/SCons/Tool/mslink.py b/SCons/Tool/mslink.py index bab78d8..8fd7922 100644 --- a/SCons/Tool/mslink.py +++ b/SCons/Tool/mslink.py @@ -9,8 +9,6 @@ selection method. """ # -# __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 @@ -30,7 +28,6 @@ selection method. # 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 os import os.path diff --git a/SCons/Tool/sgilink.py b/SCons/Tool/sgilink.py index b1e7921..e92c7b9 100644 --- a/SCons/Tool/sgilink.py +++ b/SCons/Tool/sgilink.py @@ -9,8 +9,6 @@ selection method. """ # -# __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 @@ -31,7 +29,6 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import SCons.Util diff --git a/SCons/Tool/sunlink.py b/SCons/Tool/sunlink.py index c33ba5a..f668903 100644 --- a/SCons/Tool/sunlink.py +++ b/SCons/Tool/sunlink.py @@ -30,7 +30,7 @@ selection method. import os.path -import SCons.Tool.linkCommon +import SCons.Tool.linkCommon as linkCommon import SCons.Util from . import link @@ -63,12 +63,12 @@ def generate(env): env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}' # Support for versioned libraries - SCons.Tool.linkCommon._setup_versioned_lib_variables(env, tool ='sunlink', use_soname=True) + linkCommon._setup_versioned_lib_variables(env, tool='sunlink', use_soname=True) env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -h $_SHLIBSONAME' env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -h $_LDMODULESONAME' - env['LINKCALLBACKS'] = SCons.Tool.linkCommon._versioned_lib_callbacks() + env['LINKCALLBACKS'] = linkCommon._versioned_lib_callbacks() def exists(env): return ccLinker -- cgit v0.12 From 4c3cc667056cec3b8841840f01be908531460a3c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 31 Aug 2020 15:01:11 -0400 Subject: Fix local imports --- SCons/Tool/linkCommon/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCons/Tool/linkCommon/__init__.py b/SCons/Tool/linkCommon/__init__.py index c787e0c..d96362a 100644 --- a/SCons/Tool/linkCommon/__init__.py +++ b/SCons/Tool/linkCommon/__init__.py @@ -511,10 +511,10 @@ def _call_env_subst(env, string, *args, **kw): def smart_link(source, target, env, for_signature): import SCons.Tool.cxx - import SCons.Tool.fortran + import SCons.Tool.FortranCommon has_cplusplus = SCons.Tool.cxx.iscplusplus(source) - has_fortran = SCons.Tool.fortran.isfortran(env, source) + has_fortran = SCons.Tool.FortranCommon.isfortran(env, source) has_d = isD(env, source) if has_cplusplus and has_fortran and not has_d: global issued_mixed_link_warning -- cgit v0.12 From c014008bfa4db6a5266e94a725fd1b983f837931 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Wed, 7 Oct 2020 15:09:32 -0700 Subject: incremental checkin. Updates to README for other developers to review --- SCons/Tool/link.py | 23 +++++++++++++---------- SCons/Tool/linkCommon/README.md | 8 ++++++-- SCons/Tool/linkCommon/__init__.py | 13 ++++++++----- test/LINK/SHLIBVERSIONFLAGS.py | 29 ++++++++++++++++++++++++----- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/SCons/Tool/link.py b/SCons/Tool/link.py index 9d6caef..c552273 100644 --- a/SCons/Tool/link.py +++ b/SCons/Tool/link.py @@ -1,13 +1,7 @@ -"""SCons.Tool.link - -Tool-specific initialization for the generic Posix linker. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - +# +# 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 @@ -28,6 +22,15 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +""" +Tool-specific initialization for the generic Posix linker. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" + import SCons.Tool import SCons.Util diff --git a/SCons/Tool/linkCommon/README.md b/SCons/Tool/linkCommon/README.md index 26bc9a5..8136490 100644 --- a/SCons/Tool/linkCommon/README.md +++ b/SCons/Tool/linkCommon/README.md @@ -4,7 +4,7 @@ The following env variables can affect the command line and created files for these -* `SHLIBVERSION` +* `SHLIBVERSION` - If this is not set, the all of the following will be ignored? * `SONAME` * `SOVERSION` * `APPLELINK_NO_CURRENT_VERSION` (applelink only) @@ -19,6 +19,7 @@ Which will have a soname baked into it as one of the * `${SONAME}` * `${SHLIBPREFIX}lib_name${SOVERSION}${SHLIBSUFFIX}` +* `-Wl,-soname=$_SHLIBSONAME` (for gnulink as similar) * (for applelink only) * `${SHLIBPREFIX}lib_name${major version only from SHLIBVERSION}${SHLIBSUFFIX}` * `-Wl,-compatibility_version,%s` @@ -31,12 +32,15 @@ For **applelink** the version has to follow these rules to verify that the versi * where Y either not specified or 0-255 * where Z either not specified or 0-255 - For most platforms this will lead to a series of symlinks eventually pointing to the actual shared library (or loadable module file). 1. `${SHLIBPREFIX}lib_name${SHLIBSUFFIX} -> ${SHLIBPREFIX}lib_name${SHLIBVERSION}${SHLIBSUFFIX}` 1. `${SHLIBPREFIX}lib_name${SOVERSION}${SHLIBSUFFIX} -> ${SHLIBPREFIX}lib_name${SHLIBVERSION}${SHLIBSUFFIX}` +These symlinks are stored by the emitter in the following +`target[0].attributes.shliblinks = symlinks` +This means that those values are fixed a the time SharedLibrary() is called (generally) + For **openbsd** the following rules for symlinks apply * OpenBSD uses x.y shared library versioning numbering convention and doesn't use symlinks to backwards-compatible libraries diff --git a/SCons/Tool/linkCommon/__init__.py b/SCons/Tool/linkCommon/__init__.py index d96362a..413b13e 100644 --- a/SCons/Tool/linkCommon/__init__.py +++ b/SCons/Tool/linkCommon/__init__.py @@ -1,8 +1,6 @@ -"""SCons.Tool.linkCommon - -Common link/shared library logic -""" - +# 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 @@ -22,6 +20,11 @@ Common link/shared library logic # 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. + +""" +Common link/shared library logic +""" + import os import re import sys diff --git a/test/LINK/SHLIBVERSIONFLAGS.py b/test/LINK/SHLIBVERSIONFLAGS.py index 6cf7290..7bcabf0 100644 --- a/test/LINK/SHLIBVERSIONFLAGS.py +++ b/test/LINK/SHLIBVERSIONFLAGS.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 @@ -22,10 +24,7 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" -import os -import re import TestSCons import SCons.Platform @@ -69,15 +68,35 @@ test.write('SConstruct', "SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3')\n") test.run(stdout = versionflags, match = TestSCons.match_re_dotall) test.run(arguments = ['-c']) -# stdout must contain SHLIBVERSIONFLAGS if there is SHLIBVERSION provided +# stdout must contain SONAME if there is SONAME provided test = TestSCons.TestSCons() test.write('foo.c', foo_c_src) test.write('SConstruct', """ SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3',SONAME='%s') """ % soname) test.run(stdout = sonameVersionFlags, match = TestSCons.match_re_dotall) +test.must_exist(test.workpath(soname)) test.run(arguments = ['-c']) +# stdout must contain SOVERSION if there is SOVERSION provided +test = TestSCons.TestSCons() +test.write('foo.c', foo_c_src) +test.write('SConstruct', """ +SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3',SOVERSION='4') +""") +test.run(stdout = sonameVersionFlags, match = TestSCons.match_re_dotall) +test.must_exist(test.workpath(soname)) +test.run(arguments = ['-c']) + +# test if both SONAME and SOVERSION are used +test = TestSCons.TestSCons() +test.write('foo.c', foo_c_src) +test.write('SConstruct', """ +SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3',SONAME='%s',SOVERSION='4') +""" % soname) +test.run(status=2,stderr=None) +test.must_contain_all_lines(test.stderr(), ['Ambiguous library .so naming']) + test.pass_test() # Local Variables: -- cgit v0.12 From aff086d5ef28af0ec6ce05fc2fde4f8aa9626598 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 8 Nov 2020 16:16:12 -0800 Subject: Updated WIP linkCommon README --- SCons/Tool/linkCommon/README.md | 45 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/SCons/Tool/linkCommon/README.md b/SCons/Tool/linkCommon/README.md index 8136490..add1246 100644 --- a/SCons/Tool/linkCommon/README.md +++ b/SCons/Tool/linkCommon/README.md @@ -57,4 +57,47 @@ The current code provides the following hooks a compiler can use to customize: 'VersionedLdModName': _versioned_ldmod_name, 'VersionedShLibSoname': _versioned_shlib_soname, 'VersionedLdModSoname': _versioned_ldmod_soname, -``` \ No newline at end of file +``` + + +User can request: +env.SharedLibrary('a',sources, SHLIBVERSION) +env.SharedLibrary('liba.so',sources, SHLIBVERSION) +Ideally we'll keep the 'a' for use in constructing all follow on. To do this we have to do it in the Builder() or at +least prevent BuilderBase._create_nodes() from discarding this info if it's available. + + +Firstly check if [SH|LD]LIBNOVERSIONSYMLINKS defined or if [SH|LD]LIBVERSION is not defined, if so we do nothing special + +The emitter can calculate the filename stem 'a' above and store it on the target node. Then also create the symlinks +and store those on the node. We should have all the information needed by the time the emitter is called. +Same should apply for loadable modules.. +This should be vastly simpler. +Unfortunately we cannot depend on the target having an OverrideEnvironment() which we could populate all the related +env variables in the emitter... +Maybe we can force one at that point? + + +SOVERSION can be specified, if not, then defaults to major portion of SHLIBVERSION +SONAME can be specified, if not defaults to ${SHLIBPREFIX}lib_name${SOVERSION} + +NOTE: mongodb uses Append(SHLIBEMITTER=.. ) for their libdeps stuff. (So test +with that once you have new logic working) + + +TODO: +1. Generate proper naming for: + * shared library (altered by emitter if SHLIBVERSION is set) + * soname'd library (for symlink) - SHLIB_SONAME_SYMLINK + * non versioned shared library (for symlink) - SHLIB_NOVERSION_SYMLINK +2. in emitter also, actually create the symlinks (if SHLIBVERSION is set) and + add to node.attributes.symlinks. (note bsd doesn't do this so skip if on bsd) +3. We need to check somewhere if SONAME and SOVERSION are both set and thrown an error. + Probably in the emitter to it will traceback to where the SharedLibrary() which + yielded the issue is located. +4. Generate proper linker soname compiler construct (-Wl,soname=libxyz.1.so for example) + +hrm.. tricky. +SHLIBSUFFIX needs to have .${SHLIBVERSION}${SHLIBSUFFIX} as it's value when +fixing a sharedlibrary()'s target file name (from a -> liba.1.2.3.so) +But when creating the symlinks for the rest, we need to drop the versioned SHLIBSUFFIX \ No newline at end of file -- cgit v0.12 From f11bf4212220db1ae95cee7a1171085ac8c46777 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 8 Dec 2020 13:16:27 -0800 Subject: Fix no_import_lib for versioned cygwin/cyglink shared libraries. Was referencing the import lib to create symlinks even if import lib wasn't to be created --- SCons/Tool/cyglink.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/SCons/Tool/cyglink.py b/SCons/Tool/cyglink.py index e85797b..363a602 100644 --- a/SCons/Tool/cyglink.py +++ b/SCons/Tool/cyglink.py @@ -120,14 +120,14 @@ def _lib_emitter(target, source, env, **kw): implib_target.attributes.shared = 1 target.append(implib_target) - symlinks = ImpLibSymlinkGenerator(env, implib_target, - implib_libtype=libtype, - generator_libtype=libtype + 'ImpLib') - if Verbose: - print("_lib_emitter: implib symlinks=%r" % StringizeLibSymlinks(symlinks)) - if symlinks: - EmitLibSymlinks(env, symlinks, implib_target, clean_targets=target[0]) - implib_target.attributes.shliblinks = symlinks + symlinks = ImpLibSymlinkGenerator(env, implib_target, + implib_libtype=libtype, + generator_libtype=libtype + 'ImpLib') + if Verbose: + print("_lib_emitter: implib symlinks=%r" % StringizeLibSymlinks(symlinks)) + if symlinks: + EmitLibSymlinks(env, symlinks, implib_target, clean_targets=target[0]) + implib_target.attributes.shliblinks = symlinks return (target, source) -- cgit v0.12 From 2b583646718acda52481b71f15c9a6723fb3eb81 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 8 Dec 2020 13:18:04 -0800 Subject: docstrings and minor code cleanup --- SCons/Builder.py | 1 + SCons/Defaults.py | 10 +++++++++- SCons/Environment.py | 2 +- SCons/Tool/cyglink.py | 1 + 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/SCons/Builder.py b/SCons/Builder.py index d54ef24..5f51078 100644 --- a/SCons/Builder.py +++ b/SCons/Builder.py @@ -504,6 +504,7 @@ class BuilderBase: splitext = lambda S: self.splitext(S,env) tlist = [ t_from_s(pre, suf, splitext) ] else: + orig_target = target target = self._adjustixes(target, pre, suf, self.ensure_suffix) tlist = env.arg2nodes(target, target_factory, target=target, source=source) diff --git a/SCons/Defaults.py b/SCons/Defaults.py index c23d564..143342e 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -545,8 +545,14 @@ class Variable_Method_Caller: frame = frame.f_back return None -# if $version_var is not empty, returns env[flags_var], otherwise returns None def __libversionflags(env, version_var, flags_var): + """ + if $version_var is not empty, returns env[flags_var], otherwise returns None + :param env: + :param version_var: + :param flags_var: + :return: + """ try: if env.subst('$'+version_var): return env[flags_var] @@ -554,6 +560,8 @@ def __libversionflags(env, version_var, flags_var): pass return None + + ConstructionEnvironment = { 'BUILDERS' : {}, 'SCANNERS' : [ SCons.Tool.SourceFileScanner ], diff --git a/SCons/Environment.py b/SCons/Environment.py index bb57e37..13eaf3c 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -1606,7 +1606,7 @@ class Base(SubstitutionEnvironment): prefix = self.subst('$'+prefix) for path in paths: - dir,name = os.path.split(str(path)) + name = os.path.basename(str(path)) if name[:len(prefix)] == prefix and name[-len(suffix):] == suffix: return path diff --git a/SCons/Tool/cyglink.py b/SCons/Tool/cyglink.py index 363a602..595cc2e 100644 --- a/SCons/Tool/cyglink.py +++ b/SCons/Tool/cyglink.py @@ -120,6 +120,7 @@ def _lib_emitter(target, source, env, **kw): implib_target.attributes.shared = 1 target.append(implib_target) + # Only create the symlinks if there is actually an import library symlinks = ImpLibSymlinkGenerator(env, implib_target, implib_libtype=libtype, generator_libtype=libtype + 'ImpLib') -- cgit v0.12 From f729f569e1e6100ff01c8ecf8b62943c48143691 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 15 Dec 2020 10:22:25 -0700 Subject: Build up manpage information on sconscript files. Tweaked introductory section with a few more details. Added a new subsection to begin the Confguration File Reference section, called Configuration Files, mainly as a better home for the information on alternate SConstruct names, which seemed a distraction at the top of the file, as well as to introduce the concept that sconscript files are independent of each other, which does not appear to be explicitly stated (although you could gather the information by reading some Function entries). Also provides quick links to other Config File subsections - manpage is hard to navigate as it's so long. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 133 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 101 insertions(+), 32 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 45bc9bd..70f47af 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -102,35 +102,49 @@ orchestrates the construction of software (and other tangible products such as documentation files) by determining which component pieces must be built or rebuilt and invoking the necessary -commands to build them. +commands to build them. +&SCons; offers many features to improve developer productivity +such as parallel builds, caching of build artefacts, and +a database of information about previous builds so details do +not have to be recalculated each run. + -You instruct -&scons; by writing a configuration file -which specifies the files to be built (targets), -and, if necessary, the rules to build those files. Premade -rules exist for building many common software components +You set up an &SCons; +build system by writing a configuration file +that describes things to build (targets), and, +if necessary, the rules to build those files (actions). +&SCons; comes with a collection of Builder methods +which apply premade rules for building many common software components such as executable programs, object files and libraries, so that for many software projects, -only the target and input files (sources) -need be specified. +only the targets and input files (sources) +need be specified in a call to a builder. +&scons; thus can operate at a level of abstraction above that of pure files. +For example if you specify a library target named "foo", +&scons; keeps track of the actual operating system dependent filename +(for example libfoo.so on a GNU/Linux system), +and how to refer to that library in later construction steps +that want to use it, so you don't have to specify that precise +information yourself. +&scons; can also scan automatically for dependency information, +such as header files included by source code files, +so this does not have to be specified manually. + When invoked, &scons; -searches for a file named +looks for a file named &SConstruct; -(it also checks alternate spellings -&Sconstruct;, &sconstruct;, &SConstruct.py;, &Sconstruct.py; -and &sconstruct.py; -in that order) in the current directory and reads its -configuration from that file. -An alternate file name may be -specified via the - -option. +in the current directory and reads the +build configuration from that file +(other names are possible, +see for more information). +An &SConstruct; file is required: +&scons; will quit if it does not find one. The &SConstruct; -file can specify subsidiary +file may specify subsidiary configuration files by calling the -&SConscriptFunc; function. +&f-link-SConscript; function. By convention, these subsidiary files are named &SConscript;, @@ -156,9 +170,10 @@ finds to the Python module search path (sys.path), thus allowing modules in such directories to be imported in the normal Python way in SConscript files. For each found site directory, -if it contains a file site_init.py -it is evaluated, and if it contains a directory -site_tools the path to it +(1) if it contains a file site_init.py +that file is evaluated, +and (2) if it contains a directory +site_tools the path to that directory is prepended to the default toolpath. See the @@ -169,18 +184,24 @@ controlling the site directories. -&scons; configuration files are written in the +SConscript files are written in the Python programming language, although it is normally not necessary to be a Python programmer to use &scons; effectively. +SConscript files are invoked in a context that makes +the facilities described in this manual page available +in their local namespace without any special steps. Standard Python scripting capabilities such as flow control, data manipulation, and imported Python libraries are available to use to handle complicated build situations. +Other Python files can be made a part of the build system, +but they do not automatically have the &SCons; context and +need to import it if they need access (described later). &scons; -reads and executes all of the SConscript files +reads and executes all of the included SConscript files before it begins building any targets. To make this clear, @@ -344,7 +365,7 @@ If there are no targets from the previous steps, &scons; selects the current directory for scanning, unless command-line options which affect the target scan are detected (, -, , ). +, , ). Since targets thus selected were not the result of user instructions, this target list is not made available for direct inspection; use the @@ -2156,8 +2177,57 @@ repositories are searched in the order specified. CONFIGURATION FILE REFERENCE - - + + +Configuration Files + +The build configuration consists of one or more configuration files +(SConscript files). +The main file is named SConstruct by +default, though if necessary, &scons; also checks for alternate spellings +&Sconstruct;, &sconstruct;, &SConstruct.py;, &Sconstruct.py; +and &sconstruct.py; +in that order. +An alternate file name (including a path to another +directory) may be specified via the option. +Except for the main file, +these files are not searched for automatically by &scons; - +additional configuration files are added to the build +through calls to the &f-link-SConscript; function. +This allows parts of the build to be conditionally +included or excluded at run-time depending on how &scons; is invoked. + + + +Each SConscript file in a build configuration is invoked +independently in a separate context. +This provides necessary isolation so that different parts of +the build don't accidentally step on each other. +You have to be explicit about sharing information, +by using the &f-link-Export; function or the &exports; argument +to the &SConscript; function, as well as the &f-link-Return; function +in a called SConscript file, and comsume shared information by using the +&f-link-Import; function. + + + +The following sections describe the various &SCons; facilities +that can be used in SConscript files. Quick links: + + + + Construction Environments + Tools + Builder Methods + Methods and Functions to do Things + SConscript Variables + Construction Variables + Configure Contexts + Command-Line Construction Variables + Node Objects + + + Construction Environments @@ -3351,12 +3421,11 @@ from SCons.Script import * A &consenv; has an associated dictionary of &consvars; that are used by built-in or user-supplied build rules. -&Consvar; naming must follow the same rules as for +&Consvar; naming must follow the same rules as used for Python identifiers: the initial character must be an underscore or letter, -followed by any number of underscores, letters, or digits. - -A &consenv; is not a Python dictionary, +followed by any number of underscores, letters, or digits. +A &consenv; is not a Python dictionary itself, but it can be indexed like one to access a &consvar;: -- cgit v0.12 From 0b0f7780bcf1ec7a39bfd5e6a741c47ff964ab0c Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 19 Dec 2020 12:47:54 -0700 Subject: [PR #3844] adjust man wordings per review [ski appveyor] Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 45 +++++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 70f47af..df38788 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -110,7 +110,7 @@ not have to be recalculated each run. You set up an &SCons; -build system by writing a configuration file +build system by writing a script that describes things to build (targets), and, if necessary, the rules to build those files (actions). &SCons; comes with a collection of Builder methods @@ -138,9 +138,7 @@ looks for a file named in the current directory and reads the build configuration from that file (other names are possible, -see for more information). -An &SConstruct; file is required: -&scons; will quit if it does not find one. +see for more information). The &SConstruct; file may specify subsidiary configuration files by calling the @@ -2175,25 +2173,28 @@ repositories are searched in the order specified. - -CONFIGURATION FILE REFERENCE + +SCONSCRIPT FILE REFERENCE - -Configuration Files + +SConscript Files -The build configuration consists of one or more configuration files -(SConscript files). -The main file is named SConstruct by -default, though if necessary, &scons; also checks for alternate spellings +The build configuration is described by one or more files, +known as SConscript files. +There must be at least one file for a valid build +(&scons; will quit if it does not find one). +&scons; by default looks for this file by the name +SConstruct +in the directory from which you run &scons;, +though if necessary, also looks for alternative file names &Sconstruct;, &sconstruct;, &SConstruct.py;, &Sconstruct.py; -and &sconstruct.py; -in that order. -An alternate file name (including a path to another -directory) may be specified via the option. -Except for the main file, -these files are not searched for automatically by &scons; - -additional configuration files are added to the build -through calls to the &f-link-SConscript; function. +and &sconstruct.py; in that order. +A different file name (which can include a pathname part) +may be specified via the option. +Except for the SConstruct file, +these files are not searched for automatically; +you add additional configuration files to the build +by calling the &f-link-SConscript; function. This allows parts of the build to be conditionally included or excluded at run-time depending on how &scons; is invoked. @@ -3421,8 +3422,8 @@ from SCons.Script import * A &consenv; has an associated dictionary of &consvars; that are used by built-in or user-supplied build rules. -&Consvar; naming must follow the same rules as used for -Python identifiers: +&Consvar; naming must follow the same rules as +Python identifier naming: the initial character must be an underscore or letter, followed by any number of underscores, letters, or digits. A &consenv; is not a Python dictionary itself, -- cgit v0.12 From 5e6fe1a165f2e9a8c9db23a8ea958704200e95de Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 20 Dec 2020 18:21:45 -0800 Subject: initial checkin of versioned shared library rewrite --- SCons/Defaults.py | 145 +++++--- SCons/Tool/__init__.py | 11 +- SCons/Tool/applelink.py | 86 ++--- SCons/Tool/cyglink.py | 314 +++++++--------- SCons/Tool/dmd.py | 12 +- SCons/Tool/gnulink.py | 11 +- SCons/Tool/ldc.py | 13 +- SCons/Tool/link.py | 33 +- SCons/Tool/linkCommon/LoadableModule.py | 97 +++++ SCons/Tool/linkCommon/SharedLibrary.py | 153 ++++++++ SCons/Tool/linkCommon/__init__.py | 622 +------------------------------- SCons/Tool/sunlink.py | 13 +- SCons/__init__.py | 6 +- test/LINK/SHLIBVERSIONFLAGS.py | 35 +- 14 files changed, 570 insertions(+), 981 deletions(-) create mode 100644 SCons/Tool/linkCommon/LoadableModule.py create mode 100644 SCons/Tool/linkCommon/SharedLibrary.py diff --git a/SCons/Defaults.py b/SCons/Defaults.py index c59fbcf..2bacc10 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -31,12 +31,12 @@ The code that reads the registry to find MSVC components was borrowed from distutils.msvccompiler. """ -import os import errno +import os import shutil import stat -import time import sys +import time import SCons.Action import SCons.Builder @@ -52,6 +52,7 @@ import SCons.Tool # interface. _default_env = None + # Lazily instantiate the default environment so the overhead of creating # it doesn't apply when it's not needed. def _fetch_DefaultEnvironment(*args, **kw): @@ -59,6 +60,7 @@ def _fetch_DefaultEnvironment(*args, **kw): global _default_env return _default_env + def DefaultEnvironment(*args, **kw): """ Initial public entry point for creating the default construction @@ -88,6 +90,7 @@ def DefaultEnvironment(*args, **kw): _default_env._CacheDir_path = None return _default_env + # Emitters for setting the shared attribute on object files, # and an action for checking that all of the source files # going into a shared library are, in fact, shared. @@ -96,11 +99,13 @@ def StaticObjectEmitter(target, source, env): tgt.attributes.shared = None return (target, source) + def SharedObjectEmitter(target, source, env): for tgt in target: tgt.attributes.shared = 1 return (target, source) + def SharedFlagChecker(source, target, env): same = env.subst('$STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME') if same == '0' or same == '' or same == 'False': @@ -110,7 +115,9 @@ def SharedFlagChecker(source, target, env): except AttributeError: shared = None if not shared: - raise SCons.Errors.UserError("Source file: %s is static and is not compatible with shared target: %s" % (src, target[0])) + raise SCons.Errors.UserError( + "Source file: %s is static and is not compatible with shared target: %s" % (src, target[0])) + SharedCheck = SCons.Action.Action(SharedFlagChecker, None) @@ -128,6 +135,7 @@ ProgScan = SCons.Tool.ProgramScanner # the rest of those in Tool/__init__.py, but I'm not sure where else # they should go. Leave them here for now. import SCons.Scanner.Dir + DirScanner = SCons.Scanner.Dir.DirScanner() DirEntryScanner = SCons.Scanner.Dir.DirEntryScanner() @@ -152,6 +160,7 @@ LdModuleLinkAction = SCons.Action.Action("$LDMODULECOM", "$LDMODULECOMSTR") # ways by creating ActionFactory instances. ActionFactory = SCons.Action.ActionFactory + def get_paths_str(dest): # If dest is a list, we need to manually call str() on each element if SCons.Util.is_List(dest): @@ -162,24 +171,26 @@ def get_paths_str(dest): else: return '"' + str(dest) + '"' + permission_dic = { - 'u':{ - 'r':stat.S_IRUSR, - 'w':stat.S_IWUSR, - 'x':stat.S_IXUSR + 'u': { + 'r': stat.S_IRUSR, + 'w': stat.S_IWUSR, + 'x': stat.S_IXUSR }, - 'g':{ - 'r':stat.S_IRGRP, - 'w':stat.S_IWGRP, - 'x':stat.S_IXGRP + 'g': { + 'r': stat.S_IRGRP, + 'w': stat.S_IWGRP, + 'x': stat.S_IXGRP }, - 'o':{ - 'r':stat.S_IROTH, - 'w':stat.S_IWOTH, - 'x':stat.S_IXOTH + 'o': { + 'r': stat.S_IROTH, + 'w': stat.S_IWOTH, + 'x': stat.S_IXOTH } } + def chmod_func(dest, mode): import SCons.Util from string import digits @@ -223,6 +234,7 @@ def chmod_func(dest, mode): elif operator == "-": os.chmod(str(element), curr_perm & ~new_perm) + def chmod_strfunc(dest, mode): import SCons.Util if not SCons.Util.is_String(mode): @@ -230,8 +242,10 @@ def chmod_strfunc(dest, mode): else: return 'Chmod(%s, "%s")' % (get_paths_str(dest), str(mode)) + Chmod = ActionFactory(chmod_func, chmod_strfunc) + def copy_func(dest, src, symlinks=True): """ If symlinks (is true), then a symbolic link will be @@ -262,11 +276,13 @@ def copy_func(dest, src, symlinks=True): # A error is raised in both cases, so we can just return 0 for success return 0 + Copy = ActionFactory( copy_func, lambda dest, src, symlinks=True: 'Copy("%s", "%s")' % (dest, src) ) + def delete_func(dest, must_exist=0): SCons.Node.FS.invalidate_node_memos(dest) if not SCons.Util.is_List(dest): @@ -283,11 +299,14 @@ def delete_func(dest, must_exist=0): continue os.unlink(entry) + def delete_strfunc(dest, must_exist=0): return 'Delete(%s)' % get_paths_str(dest) + Delete = ActionFactory(delete_func, delete_strfunc) + def mkdir_func(dest): SCons.Node.FS.invalidate_node_memos(dest) if not SCons.Util.is_List(dest): @@ -298,24 +317,28 @@ def mkdir_func(dest): except os.error as e: p = str(entry) if (e.args[0] == errno.EEXIST or - (sys.platform=='win32' and e.args[0]==183)) \ + (sys.platform == 'win32' and e.args[0] == 183)) \ and os.path.isdir(str(entry)): - pass # not an error if already exists + pass # not an error if already exists else: raise + Mkdir = ActionFactory(mkdir_func, lambda dir: 'Mkdir(%s)' % get_paths_str(dir)) + def move_func(dest, src): SCons.Node.FS.invalidate_node_memos(dest) SCons.Node.FS.invalidate_node_memos(src) shutil.move(src, dest) + Move = ActionFactory(move_func, lambda dest, src: 'Move("%s", "%s")' % (dest, src), convert=str) + def touch_func(dest): SCons.Node.FS.invalidate_node_memos(dest) if not SCons.Util.is_List(dest): @@ -330,9 +353,11 @@ def touch_func(dest): atime = mtime os.utime(file, (atime, mtime)) + Touch = ActionFactory(touch_func, lambda file: 'Touch(%s)' % get_paths_str(file)) + # Internal utility functions @@ -386,7 +411,7 @@ def _concat_ixes(prefix, list, suffix, env): if suffix[0] == ' ': result.append(suffix[1:]) elif x[-len(suffix):] != suffix: - result[-1] = result[-1]+suffix + result[-1] = result[-1] + suffix return result @@ -443,6 +468,7 @@ def _stripixes(prefix, itms, suffix, stripprefixes, stripsuffixes, env, c=None): return c(prefix, stripped, suffix, env) + def processDefines(defs): """process defines, resolving strings, lists, dictionaries, into a list of strings @@ -458,7 +484,7 @@ def processDefines(defs): else: l.append(str(d[0])) elif SCons.Util.is_Dict(d): - for macro,value in d.items(): + for macro, value in d.items(): if value is not None: l.append(str(macro) + '=' + str(value)) else: @@ -466,7 +492,7 @@ def processDefines(defs): elif SCons.Util.is_String(d): l.append(str(d)) else: - raise SCons.Errors.UserError("DEFINE %s is not a list, dict, string or None."%repr(d)) + raise SCons.Errors.UserError("DEFINE %s is not a list, dict, string or None." % repr(d)) elif SCons.Util.is_Dict(defs): # The items in a dictionary are stored in random order, but # if the order of the command-line options changes from @@ -475,7 +501,7 @@ def processDefines(defs): # Consequently, we have to sort the keys to ensure a # consistent order... l = [] - for k,v in sorted(defs.items()): + for k, v in sorted(defs.items()): if v is None: l.append(str(k)) else: @@ -524,11 +550,14 @@ class Variable_Method_Caller: the way of Memoizing construction environments, because we had to create new environment objects to hold the variables.) """ + def __init__(self, variable, method): self.variable = variable self.method = method + def __call__(self, *args, **kw): - try: 1//0 + try: + 1 // 0 except ZeroDivisionError: # Don't start iterating with the current stack-frame to # prevent creating reference cycles (f_back is safe). @@ -543,6 +572,7 @@ class Variable_Method_Caller: frame = frame.f_back return None + def __libversionflags(env, version_var, flags_var): """ if $version_var is not empty, returns env[flags_var], otherwise returns None @@ -552,42 +582,59 @@ def __libversionflags(env, version_var, flags_var): :return: """ try: - if env.subst('$'+version_var): + if env.subst('$' + version_var): return env[flags_var] except KeyError: pass return None +def __lib_either_version_flag(env, version_var1, version_var2, flags_var): + """ + if $version_var1 or $version_var2 is not empty, returns env[flags_var], otherwise returns None + :param env: + :param version_var1: + :param version_var2: + :param flags_var: + :return: + """ + try: + if env.subst('$' + version_var1) or env.subst('$' + version_var2): + return env[flags_var] + except KeyError: + pass + return None + ConstructionEnvironment = { - 'BUILDERS' : {}, - 'SCANNERS' : [ SCons.Tool.SourceFileScanner ], - 'CONFIGUREDIR' : '#/.sconf_temp', - 'CONFIGURELOG' : '#/config.log', - 'CPPSUFFIXES' : SCons.Tool.CSuffixes, - 'DSUFFIXES' : SCons.Tool.DSuffixes, - 'ENV' : {}, - 'IDLSUFFIXES' : SCons.Tool.IDLSuffixes, - '_concat' : _concat, - '_defines' : _defines, - '_stripixes' : _stripixes, - '_LIBFLAGS' : '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', - '_LIBDIRFLAGS' : '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', - '_CPPINCFLAGS' : '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', - '_CPPDEFFLAGS' : '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', - - '__libversionflags' : __libversionflags, - '__SHLIBVERSIONFLAGS' : '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}', - '__LDMODULEVERSIONFLAGS' : '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}', - '__DSHLIBVERSIONFLAGS' : '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}', - - 'TEMPFILE' : NullCmdGenerator, + 'BUILDERS': {}, + 'SCANNERS': [SCons.Tool.SourceFileScanner], + 'CONFIGUREDIR': '#/.sconf_temp', + 'CONFIGURELOG': '#/config.log', + 'CPPSUFFIXES': SCons.Tool.CSuffixes, + 'DSUFFIXES': SCons.Tool.DSuffixes, + 'ENV': {}, + 'IDLSUFFIXES': SCons.Tool.IDLSuffixes, + '_concat': _concat, + '_defines': _defines, + '_stripixes': _stripixes, + '_LIBFLAGS': '${_concat(LIBLINKPREFIX, LIBS, LIBLINKSUFFIX, __env__)}', + '_LIBDIRFLAGS': '$( ${_concat(LIBDIRPREFIX, LIBPATH, LIBDIRSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_CPPINCFLAGS': '$( ${_concat(INCPREFIX, CPPPATH, INCSUFFIX, __env__, RDirs, TARGET, SOURCE)} $)', + '_CPPDEFFLAGS': '${_defines(CPPDEFPREFIX, CPPDEFINES, CPPDEFSUFFIX, __env__)}', + + '__libversionflags': __libversionflags, + '__SHLIBVERSIONFLAGS': '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}', + '__LDMODULEVERSIONFLAGS': '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}', + '__DSHLIBVERSIONFLAGS': '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}', + '__lib_either_version_flag': __lib_either_version_flag, + + 'TEMPFILE': NullCmdGenerator, 'TEMPFILEARGJOIN': ' ', - 'Dir' : Variable_Method_Caller('TARGET', 'Dir'), - 'Dirs' : Variable_Method_Caller('TARGET', 'Dirs'), - 'File' : Variable_Method_Caller('TARGET', 'File'), - 'RDirs' : Variable_Method_Caller('TARGET', 'RDirs'), + 'Dir': Variable_Method_Caller('TARGET', 'Dir'), + 'Dirs': Variable_Method_Caller('TARGET', 'Dirs'), + 'File': Variable_Method_Caller('TARGET', 'File'), + 'RDirs': Variable_Method_Caller('TARGET', 'RDirs'), } # Local Variables: diff --git a/SCons/Tool/__init__.py b/SCons/Tool/__init__.py index 87139f1..7c78dba 100644 --- a/SCons/Tool/__init__.py +++ b/SCons/Tool/__init__.py @@ -50,8 +50,7 @@ import SCons.Scanner.D import SCons.Scanner.LaTeX import SCons.Scanner.Prog import SCons.Scanner.SWIG -from SCons.Tool.linkCommon import ShLibPrefixGenerator, LdModPrefixGenerator, ShLibSuffixGenerator, \ - LdModSuffixGenerator, LibSymlinksActionFunction, LibSymlinksStrFun +from SCons.Tool.linkCommon import LibSymlinksActionFunction, LibSymlinksStrFun DefaultToolpath = [] @@ -348,8 +347,8 @@ def createSharedLibBuilder(env): LibSymlinksAction] shared_lib = SCons.Builder.Builder(action=action_list, emitter="$SHLIBEMITTER", - prefix=ShLibPrefixGenerator, - suffix=ShLibSuffixGenerator, + prefix="$SHLIBPREFIX", + suffix="$_SHLIBSUFFIX", target_scanner=ProgramScanner, src_suffix='$SHOBJSUFFIX', src_builder='SharedObject') @@ -374,8 +373,8 @@ def createLoadableModuleBuilder(env): LibSymlinksAction] ld_module = SCons.Builder.Builder(action=action_list, emitter="$LDMODULEEMITTER", - prefix=LdModPrefixGenerator, - suffix=LdModSuffixGenerator, + prefix="$LDMODULEPREFIX", + suffix="$_LDMODULESUFFIX", target_scanner=ProgramScanner, src_suffix='$SHOBJSUFFIX', src_builder='SharedObject') diff --git a/SCons/Tool/applelink.py b/SCons/Tool/applelink.py index f51a6af..6a4a37c 100644 --- a/SCons/Tool/applelink.py +++ b/SCons/Tool/applelink.py @@ -9,6 +9,10 @@ selection method. """ # +# 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 @@ -29,14 +33,14 @@ selection method. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -import SCons.Tool.linkCommon -import SCons.Util - # Even though the Mac is based on the GNU toolchain, it doesn't understand # the -rpath option, so we use the "link" tool instead of "gnulink". +from SCons.Util import CLVar + from . import link -from .linkCommon import ShLibSonameGenerator +# User programmatically describes how SHLIBVERSION maps to values for compat/current. +_APPLELIB_MAX_VERSION_VALUES = (65535, 255, 255) class AppleLinkInvalidCurrentVersionException(Exception): @@ -47,49 +51,6 @@ class AppleLinkInvalidCompatibilityVersionException(Exception): pass -def _applelib_versioned_lib_suffix(env, suffix, version): - """For suffix='.dylib' and version='0.1.2' it returns '.0.1.2.dylib'""" - Verbose = False - if Verbose: - print("_applelib_versioned_lib_suffix: suffix={!r}".format(suffix)) - print("_applelib_versioned_lib_suffix: version={!r}".format(version)) - if version not in suffix: - suffix = "." + version + suffix - if Verbose: - print("_applelib_versioned_lib_suffix: return suffix={!r}".format(suffix)) - return suffix - - -def _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, name_func): - """For libnode='/optional/dir/libfoo.X.Y.Z.dylib' it returns 'libfoo.X.dylib'""" - Verbose = False - if Verbose: - print("_applelib_versioned_lib_soname: version={!r}".format(version)) - name = name_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_applelib_versioned_lib_soname: name={!r}".format(name)) - major = version.split('.')[0] - (libname, _suffix) = name.split('.') - # if a desired SONAME was supplied, use that, otherwise create - # a default from the major version - if env.get('SONAME'): - soname = ShLibSonameGenerator(env, libnode) - else: - soname = '.'.join([libname, major, _suffix]) - if Verbose: - print("_applelib_versioned_lib_soname: soname={!r}".format(soname)) - return soname - - -def _applelib_versioned_shlib_soname(env, libnode, version, prefix, suffix): - return _applelib_versioned_lib_soname(env, libnode, version, prefix, suffix, - SCons.Tool.linkCommon._versioned_shlib_name) - - -# User programmatically describes how SHLIBVERSION maps to values for compat/current. -_applelib_max_version_values = (65535, 255, 255) - - def _applelib_check_valid_version(version_string): """ Check that the version # is valid. @@ -111,9 +72,9 @@ def _applelib_check_valid_version(version_string): p_i = int(p) except ValueError: return False, "Version component %s (from %s) is not a number" % (p, version_string) - if p_i < 0 or p_i > _applelib_max_version_values[i]: + if p_i < 0 or p_i > _APPLELIB_MAX_VERSION_VALUES[i]: return False, "Version component %s (from %s) is not valid value should be between 0 and %d" % ( - p, version_string, _applelib_max_version_values[i]) + p, version_string, _APPLELIB_MAX_VERSION_VALUES[i]) return True, "" @@ -191,15 +152,9 @@ def generate(env): env['_FRAMEWORKS'] = '${_concat("-framework ", FRAMEWORKS, "", __env__)}' env['LINKCOM'] = env['LINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' - env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -dynamiclib') + env['SHLINKFLAGS'] = CLVar('$LINKFLAGS -dynamiclib') env['SHLINKCOM'] = env['SHLINKCOM'] + ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' - # see: http://docstore.mik.ua/orelly/unix3/mac/ch05_04.htm for proper naming - SCons.Tool.linkCommon._setup_versioned_lib_variables(env, tool='applelink', use_soname=True) - env['LINKCALLBACKS'] = SCons.Tool.linkCommon._versioned_lib_callbacks() - env['LINKCALLBACKS']['VersionedShLibSuffix'] = _applelib_versioned_lib_suffix - env['LINKCALLBACKS']['VersionedShLibSoname'] = _applelib_versioned_shlib_soname - env['_APPLELINK_CURRENT_VERSION'] = _applelib_currentVersionFromSoVersion env['_APPLELINK_COMPATIBILITY_VERSION'] = _applelib_compatVersionFromSoVersion env['_SHLIBVERSIONFLAGS'] = '$_APPLELINK_CURRENT_VERSION $_APPLELINK_COMPATIBILITY_VERSION ' @@ -210,10 +165,21 @@ def generate(env): # pre/suffixes: env['LDMODULEPREFIX'] = '' env['LDMODULESUFFIX'] = '' - env['LDMODULEFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -bundle') - env['LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' - - env['__SHLIBVERSIONFLAGS'] = '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}' + env['LDMODULEFLAGS'] = CLVar('$LINKFLAGS -bundle') + env[ + 'LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS' \ + ' $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' + + # New stuff + # + env['_SHLIBSUFFIX'] = '${_SHLIBVERSION}${SHLIBSUFFIX}' + + env[ + '__SHLIBVERSIONFLAGS'] = '${__lib_either_version_flag(__env__,' \ + '"SHLIBVERSION","_APPLELINK_CURRENT_VERSION", "_SHLIBVERSIONFLAGS")}' + env[ + '__LDMODULEVERSIONFLAGS'] = '${__lib_either_version_flag(__env__,' \ + '"LDMODULEVERSION","_APPLELINK_CURRENT_VERSION", "_LDMODULEVERSIONFLAGS")}' def exists(env): diff --git a/SCons/Tool/cyglink.py b/SCons/Tool/cyglink.py index 595cc2e..1995ac3 100644 --- a/SCons/Tool/cyglink.py +++ b/SCons/Tool/cyglink.py @@ -8,211 +8,153 @@ selection method. """ -import re -import os - -import SCons.Action -import SCons.Tool.linkCommon as linkCommon -from SCons.Tool.linkCommon import ImpLibSymlinkGenerator, StringizeLibSymlinks, EmitLibSymlinks, ImpLibPrefixGenerator, \ - ImpLibSuffixGenerator, ImpLibNameGenerator -import SCons.Util -import SCons.Tool - +from SCons.Tool.linkCommon import StringizeLibSymlinks, EmitLibSymlinks +from SCons.Util import CLVar from . import gnulink -def _lib_generator(target, source, env, for_signature, **kw): - try: - cmd = kw['cmd'] - except KeyError: - cmd = SCons.Util.CLVar(['$SHLINK']) - - try: - vp = kw['varprefix'] - except KeyError: - vp = 'SHLIB' - - dll = env.FindIxes(target, '%sPREFIX' % vp, '%sSUFFIX' % vp) - if dll: cmd.extend(['-o', dll]) +def cyglink_lib_emitter(target, source, env, **kw): + verbose = True - cmd.extend(['$SHLINKFLAGS', '$__%sVERSIONFLAGS' % vp, '$__RPATH']) - - implib = env.FindIxes(target, 'IMPLIBPREFIX', 'IMPLIBSUFFIX') - if implib: - cmd.extend([ - '-Wl,--out-implib=' + implib.get_string(for_signature), - '-Wl,--export-all-symbols', - '-Wl,--enable-auto-import', - '-Wl,--whole-archive', '$SOURCES', - '-Wl,--no-whole-archive', '$_LIBDIRFLAGS', '$_LIBFLAGS' - ]) + if 'variable_prefix' in kw: + var_prefix = kw['variable_prefix'] else: - cmd.extend(['$SOURCES', '$_LIBDIRFLAGS', '$_LIBFLAGS']) - - return [cmd] - + var_prefix = 'SHLIB' -def shlib_generator(target, source, env, for_signature): - return _lib_generator(target, source, env, for_signature, - varprefix='SHLIB', - cmd=SCons.Util.CLVar(['$SHLINK'])) + no_import_lib = env.get('no_import_lib', False) + if verbose: + print("cyglink_lib_emitter: target[0]={!r}".format(target[0].get_path())) -def ldmod_generator(target, source, env, for_signature): - return _lib_generator(target, source, env, for_signature, - varprefix='LDMODULE', - cmd=SCons.Util.CLVar(['$LDMODULE'])) - - -def _lib_emitter(target, source, env, **kw): - Verbose = False - - if Verbose: - print("_lib_emitter: target[0]=%r" % target[0].get_path()) + if not no_import_lib: + # Specify import lib and add to targets - try: - vp = kw['varprefix'] - except KeyError: - vp = 'SHLIB' + import_lib = env.subst('$%s_IMPLIBNAME' % var_prefix, target=target, source=source) + import_lib_target = env.fs.File(import_lib) + import_lib_target.attributes.shared = 1 + target.append(import_lib_target) - try: - libtype = kw['libtype'] - except KeyError: - libtype = 'ShLib' + if verbose: + print("cyglink_lib_emitter: import_lib={}".format(import_lib)) + print("cyglink_lib_emitter: target=%s" % target) - dll = env.FindIxes(target, '%sPREFIX' % vp, '%sSUFFIX' % vp) - no_import_lib = env.get('no_import_lib', 0) + for tgt in target: + if is_String(tgt): + tgt = env.File(tgt) + tgt.attributes.shared = 1 - if Verbose: - print("_lib_emitter: dll=%r" % dll.get_path()) + return target, source - if not dll or len(target) > 1: - raise SCons.Errors.UserError( - "A shared library should have exactly one target with the suffix: %s" % env.subst("$%sSUFFIX" % vp)) - # Remove any "lib" after the prefix - pre = env.subst('$%sPREFIX' % vp) - if dll.name[len(pre):len(pre) + 3] == 'lib': - dll.name = pre + dll.name[len(pre) + 3:] +def cyglink_ldmodule_emitter(target, source, env, **kw): + return cyglink_lib_emitter(target, source, env, variable_prefix='LDMODULE') - if Verbose: - print("_lib_emitter: dll.name=%r" % dll.name) - orig_target = target - target = [env.fs.File(dll)] - target[0].attributes.shared = 1 +def cyglink_shlib_symlink_emitter(target, source, env, **kw): + """ + On cygwin, we only create a symlink from the non-versioned implib to the versioned implib. + We don't version the shared library itself. + :param target: + :param source: + :param env: + :param kw: + :return: + """ + verbose = True - if Verbose: - print("_lib_emitter: after target=[env.fs.File(dll)]: target[0]=%r" % target[0].get_path()) + if 'variable_prefix' in kw: + var_prefix = kw['variable_prefix'] + else: + var_prefix = 'SHLIB' - # Append an import lib target - if not no_import_lib: - # Create list of target libraries as strings - target_strings = env.ReplaceIxes(orig_target[0], - '%sPREFIX' % vp, '%sSUFFIX' % vp, - 'IMPLIBPREFIX', 'IMPLIBSUFFIX') - if Verbose: - print("_lib_emitter: target_strings=%r" % target_strings) - - implib_target = env.fs.File(target_strings) - if Verbose: - print("_lib_emitter: implib_target=%r" % implib_target.get_path()) - implib_target.attributes.shared = 1 - target.append(implib_target) - - # Only create the symlinks if there is actually an import library - symlinks = ImpLibSymlinkGenerator(env, implib_target, - implib_libtype=libtype, - generator_libtype=libtype + 'ImpLib') - if Verbose: - print("_lib_emitter: implib symlinks=%r" % StringizeLibSymlinks(symlinks)) - if symlinks: - EmitLibSymlinks(env, symlinks, implib_target, clean_targets=target[0]) - implib_target.attributes.shliblinks = symlinks + no_import_lib = env.get('no_import_lib', False) + if no_import_lib in ['1', 'True', 'true', True]: + if verbose: + print("cyglink_shlib_symlink_emitter: no_import_lib=%s" % no_import_lib) + return target, source - return (target, source) + no_symlinks = env.subst('$%sNOVERSIONSYMLINKS' % var_prefix) + if no_symlinks in ['1', 'True', 'true', True]: + return target, source + shlibversion = env.subst('$%sVERSION' % var_prefix) + if shlibversion: + if verbose: + print("cyglink_shlib_symlink_emitter: %sVERSION=%s" % (var_prefix, shlibversion)) -def shlib_emitter(target, source, env): - return _lib_emitter(target, source, env, varprefix='SHLIB', libtype='ShLib') + # The implib (added by the cyglink_lib_emitter) + imp_lib_node = target[1] + shlib_noversion_symlink = env.subst('$%s_NOVERSION_SYMLINK' % var_prefix, target=target[0], source=source) + if verbose: + print("cyglink_shlib_symlink_emitter: shlib_noversion_symlink :%s" % shlib_noversion_symlink) + print("cyglink_shlib_symlink_emitter: imp_lib_node :%s" % imp_lib_node) -def ldmod_emitter(target, source, env): - return _lib_emitter(target, source, env, varprefix='LDMODULE', libtype='LdMod') + symlinks = [(env.File(shlib_noversion_symlink), imp_lib_node)] + if verbose: + print("cyglink_shlib_symlink_emitter: symlinks={!r}".format( + ', '.join(["%r->%r" % (k, v) for k, v in StringizeLibSymlinks(symlinks)]) + )) -def _versioned_lib_suffix(env, suffix, version): - """Generate versioned shared library suffix from a unversioned one. - If suffix='.dll', and version='0.1.2', then it returns '-0-1-2.dll'""" - Verbose = False - if Verbose: - print("_versioned_lib_suffix: suffix= ", suffix) - print("_versioned_lib_suffix: version= ", version) - cygversion = re.sub(r'\.', '-', version) - if not suffix.startswith('-' + cygversion): - suffix = '-' + cygversion + suffix - if Verbose: - print("_versioned_lib_suffix: return suffix= ", suffix) - return suffix + if symlinks: + # This does the actual symlinking + EmitLibSymlinks(env, symlinks, target[0]) + # This saves the information so if the versioned shared library is installed + # it can faithfully reproduce the correct symlinks + target[0].attributes.shliblinks = symlinks -def _versioned_implib_name(env, libnode, version, prefix, suffix, **kw): - return linkCommon._versioned_lib_name(env, libnode, version, prefix, suffix, - ImpLibPrefixGenerator, - ImpLibSuffixGenerator, - implib_libtype=kw['libtype']) + return target, source -def _versioned_implib_symlinks(env, libnode, version, prefix, suffix, **kw): - """Generate link names that should be created for a versioned shared library. - Returns a list in the form [ (link, linktarget), ... ] - """ - Verbose = False +def cyglink_ldmod_symlink_emitter(target, source, env, **kw): + return cyglink_shlib_symlink_emitter(target, source, env, variable_prefix='LDMODULE') - if Verbose: - print("_versioned_implib_symlinks: libnode=%r" % libnode.get_path()) - print("_versioned_implib_symlinks: version=%r" % version) - try: - libtype = kw['libtype'] - except KeyError: - libtype = 'ShLib' +def cyglink_shlibversion(target, source, env, for_signature): + var_prefix = 'SHLIB' + var = '%sVERSION' % var_prefix + if var not in env: + return '' - linkdir = os.path.dirname(libnode.get_path()) - if Verbose: - print("_versioned_implib_symlinks: linkdir=%r" % linkdir) + version = env.subst("$%s" % var, target=target, source=source) + version = version.replace('.', '-') + return "." + version - name = ImpLibNameGenerator(env, libnode, - implib_libtype=libtype, - generator_libtype=libtype + 'ImpLib') - if Verbose: - print("_versioned_implib_symlinks: name=%r" % name) - major = version.split('.')[0] +def cyglink_ldmodule_version(target, source, env, for_signature): + var_prefix = 'LDMODULE' + var = '%sVERSION' % var_prefix + if var not in env: + return '' - link0 = env.fs.File(os.path.join(linkdir, name)) - symlinks = [(link0, libnode)] + version = env.subst("$%s" % var, target=target, source=source) + version = version.replace('.', '-') + return "." + version - if Verbose: - print("_versioned_implib_symlinks: return symlinks=%r" % StringizeLibSymlinks(symlinks)) - return symlinks +def _implib_pre_flags(target, source, env, for_signature): + no_import_lib = env.get('no_import_lib', False) + if no_import_lib in ['1', 'True', 'true', True]: + return '' + else: + return '-Wl,--out-implib=${TARGETS[1]} -Wl,--export-all-symbols -Wl,--enable-auto-import -Wl,--whole-archive' -shlib_action = SCons.Action.Action(shlib_generator, generator=1) -ldmod_action = SCons.Action.Action(ldmod_generator, generator=1) +def _implib_post_flags(target, source, env, for_signature): + no_import_lib = env.get('no_import_lib', False) + if no_import_lib in ['1', 'True', 'true', True]: + return '' + else: + return '-Wl,--no-whole-archive' def generate(env): """Add Builders and construction variables for cyglink to an Environment.""" gnulink.generate(env) - env['LINKFLAGS'] = SCons.Util.CLVar('-Wl,-no-undefined') - - env['SHLINKCOM'] = shlib_action - env['LDMODULECOM'] = ldmod_action - env.Append(SHLIBEMITTER=[shlib_emitter]) - env.Append(LDMODULEEMITTER=[ldmod_emitter]) + env['LINKFLAGS'] = CLVar('-Wl,-no-undefined') env['SHLIBPREFIX'] = 'cyg' env['SHLIBSUFFIX'] = '.dll' @@ -221,33 +163,43 @@ def generate(env): env['IMPLIBSUFFIX'] = '.dll.a' # Variables used by versioned shared libraries + # SHLIBVERSIONFLAGS and LDMODULEVERSIONFLAGS are same as in gnulink... env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS' - # SHLIBVERSIONFLAGS and LDMODULEVERSIONFLAGS are same as in gnulink... + env['_IMPLIB_PRE_SOURCES'] = _implib_pre_flags + env['_IMPLIB_POST_SOURCES'] = _implib_post_flags + env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH ' \ + '$_IMPLIB_PRE_SOURCES $SOURCES $_IMPLIB_POST_SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + env['LDMODULECOM'] = '$LDMODULE -o $TARGET $SHLINKFLAGS $__LDMODULEVERSIONFLAGS $__RPATH ' \ + '$_IMPLIB_PRE_SOURCES $SOURCES $_IMPLIB_POST_SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + + # Overwrite emitters. Cyglink does things differently when creating symlinks + env['SHLIBEMITTER'] = [cyglink_lib_emitter, cyglink_shlib_symlink_emitter] + env['LDMODULEEMITTER'] = [cyglink_ldmodule_emitter, cyglink_ldmod_symlink_emitter] + + # This is the non versioned shlib filename + # If SHLIBVERSION is defined then this will symlink to $SHLIBNAME + env['SHLIB_NOVERSION_SYMLINK'] = '${IMPLIBPREFIX}$_get_shlib_stem${IMPLIBSUFFIX}' + env['LDMODULE_NOVERSION_SYMLINK'] = '${IMPLIBPREFIX}$_get_ldmodule_stem${IMPLIBSUFFIX}' + + env['SHLIB_IMPLIBNAME'] = '${IMPLIBPREFIX}$_get_shlib_stem${_SHLIB_IMPLIBSUFFIX}' + env['LDMODULE_IMPLIBNAME'] = '${IMPLIBPREFIX}$_get_ldmodule_stem${_LDMODULE_IMPLIBSUFFIX}' + + env['_cyglink_shlibversion'] = cyglink_shlibversion + env['_SHLIB_IMPLIBSUFFIX'] = '${_cyglink_shlibversion}${IMPLIBSUFFIX}' + env['_SHLIBSUFFIX'] = '${_cyglink_shlibversion}${SHLIBSUFFIX}' + + env['_cyglink_ldmodule_version'] = cyglink_ldmodule_version - # LINKCALLBACKS are NOT inherited from gnulink - env['LINKCALLBACKS'] = { - 'VersionedShLibSuffix': _versioned_lib_suffix, - 'VersionedLdModSuffix': _versioned_lib_suffix, - 'VersionedImpLibSuffix': _versioned_lib_suffix, - 'VersionedShLibName': linkCommon._versioned_shlib_name, - 'VersionedLdModName': linkCommon._versioned_ldmod_name, - 'VersionedShLibImpLibName': lambda *args: _versioned_implib_name(*args, libtype='ShLib'), - 'VersionedLdModImpLibName': lambda *args: _versioned_implib_name(*args, libtype='LdMod'), - 'VersionedShLibImpLibSymlinks': lambda *args: _versioned_implib_symlinks(*args, libtype='ShLib'), - 'VersionedLdModImpLibSymlinks': lambda *args: _versioned_implib_symlinks(*args, libtype='LdMod'), - } + env['_LDMODULESUFFIX'] = '${_cyglink_ldmodule_version}${LDMODULESUFFIX}' + env['_LDMODULE_IMPLIBSUFFIX'] = '${_cyglink_ldmodule_version}${IMPLIBSUFFIX}' + # Remove variables set by default initialization which aren't needed/used by cyglink # these variables were set by gnulink but are not used in cyglink - try: - del env['_SHLIBSONAME'] - except KeyError: - pass - try: - del env['_LDMODULESONAME'] - except KeyError: - pass + for rv in ['_SHLIBSONAME', '_LDMODULESONAME']: + if rv in env: + del env[rv] def exists(env): diff --git a/SCons/Tool/dmd.py b/SCons/Tool/dmd.py index 5970246..05c54ec 100644 --- a/SCons/Tool/dmd.py +++ b/SCons/Tool/dmd.py @@ -77,7 +77,6 @@ import SCons.Scanner.D import SCons.Tool import SCons.Tool.DCommon as DCommon -from SCons.Tool.linkCommon import ShLibSonameGenerator def generate(env): @@ -150,10 +149,13 @@ def generate(env): # Support for versioned libraries env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -L-soname=$_SHDLIBSONAME' - env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' - # NOTE: this is a quick hack, the soname will only work if there is - # c/c++ linker loaded which provides callback for the ShLibSonameGenerator - env['DShLibSonameGenerator'] = ShLibSonameGenerator + + # TODO: Fix this with new logic + # env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' + # # NOTE: this is a quick hack, the soname will only work if there is + # # c/c++ linker loaded which provides callback for the ShLibSonameGenerator + # env['DShLibSonameGenerator'] = ShLibSonameGenerator + # NOTE: this is only for further reference, currently $SHDLIBVERSION does # not work, the user must use $SHLIBVERSION env['SHDLIBVERSION'] = '$SHLIBVERSION' diff --git a/SCons/Tool/gnulink.py b/SCons/Tool/gnulink.py index 2b09549..fb5acd0 100644 --- a/SCons/Tool/gnulink.py +++ b/SCons/Tool/gnulink.py @@ -9,6 +9,10 @@ selection method. """ # +# 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 @@ -33,10 +37,8 @@ selection method. import SCons.Tool.linkCommon import SCons.Util import SCons.Tool -import sys from . import link -import SCons.Tool.linkCommon as linkCommon def generate(env): @@ -52,11 +54,6 @@ def generate(env): env['RPATHSUFFIX'] = '' env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}' - # OpenBSD doesn't usually use SONAME for libraries - use_soname = not sys.platform.startswith('openbsd') - linkCommon._setup_versioned_lib_variables(env, tool='gnulink', use_soname=use_soname) - env['LINKCALLBACKS'] = linkCommon._versioned_lib_callbacks() - def exists(env): # TODO: sync with link.smart_link() to choose a linker diff --git a/SCons/Tool/ldc.py b/SCons/Tool/ldc.py index d893841..342f3f0 100644 --- a/SCons/Tool/ldc.py +++ b/SCons/Tool/ldc.py @@ -51,7 +51,6 @@ import SCons.Scanner.D import SCons.Tool import SCons.Tool.DCommon as DCommon -from SCons.Tool.linkCommon import ShLibSonameGenerator def generate(env): @@ -124,10 +123,14 @@ def generate(env): # Support for versioned libraries env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -L-soname=$_SHDLIBSONAME' - env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' - # NOTE: this is a quick hack, the soname will only work if there is - # c/c++ linker loaded which provides callback for the ShLibSonameGenerator - env['DShLibSonameGenerator'] = ShLibSonameGenerator + + # TODO: Fix to work with new logic + # env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' + # # NOTE: this is a quick hack, the soname will only work if there is + # # c/c++ linker loaded which provides callback for the ShLibSonameGenerator + # env['DShLibSonameGenerator'] = ShLibSonameGenerator + # + # NOTE: this is only for further reference, currently $SHDLIBVERSION does # not work, the user must use $SHLIBVERSION env['SHDLIBVERSION'] = '$SHLIBVERSION' diff --git a/SCons/Tool/link.py b/SCons/Tool/link.py index c552273..efc84f1 100644 --- a/SCons/Tool/link.py +++ b/SCons/Tool/link.py @@ -31,26 +31,21 @@ selection method. """ - import SCons.Tool import SCons.Util import SCons.Warnings - -from SCons.Tool.linkCommon import smart_link, shlib_emitter, ldmod_emitter +from SCons.Tool import createProgBuilder +from SCons.Tool.linkCommon import smart_link +from SCons.Tool.linkCommon.LoadableModule import setup_loadable_module_logic +from SCons.Tool.linkCommon.SharedLibrary import setup_shared_lib_logic def generate(env): """Add Builders and construction variables for gnulink to an Environment.""" - SCons.Tool.createSharedLibBuilder(env) - SCons.Tool.createProgBuilder(env) + createProgBuilder(env) - env['SHLINK'] = '$LINK' - env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared') - env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' - - # don't set up the emitter, because AppendUnique will generate a list - # starting with None :-( - env.Append(SHLIBEMITTER=[shlib_emitter]) + setup_shared_lib_logic(env) + setup_loadable_module_logic(env) env['SMARTLINK'] = smart_link env['LINK'] = "$SMARTLINK" @@ -64,20 +59,6 @@ def generate(env): env['LIBLINKPREFIX'] = '-l' env['LIBLINKSUFFIX'] = '' - # For most platforms, a loadable module is the same as a shared - # library. Platforms which are different can override these, but - # setting them the same means that LoadableModule works everywhere. - SCons.Tool.createLoadableModuleBuilder(env) - env['LDMODULE'] = '$SHLINK' - env.Append(LDMODULEEMITTER=[ldmod_emitter]) - env['LDMODULEPREFIX'] = '$SHLIBPREFIX' - env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' - env['LDMODULEFLAGS'] = '$SHLINKFLAGS' - env[ - 'LDMODULECOM'] = '$LDMODULE -o $TARGET $LDMODULEFLAGS $__LDMODULEVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' - env['LDMODULEVERSION'] = '$SHLIBVERSION' - env['LDMODULENOVERSIONSYMLINKS'] = '$SHLIBNOVERSIONSYMLINKS' - def exists(env): # This module isn't really a Tool on its own, it's common logic for diff --git a/SCons/Tool/linkCommon/LoadableModule.py b/SCons/Tool/linkCommon/LoadableModule.py new file mode 100644 index 0000000..36921f6 --- /dev/null +++ b/SCons/Tool/linkCommon/LoadableModule.py @@ -0,0 +1,97 @@ +from SCons.Tool import createLoadableModuleBuilder +from .SharedLibrary import shlib_symlink_emitter +from . import lib_emitter + + +def ldmod_symlink_emitter(target, source, env, **kw): + return shlib_symlink_emitter(target, source, env, variable_prefix='LDMODULE') + + +def _get_ldmodule_stem(target, source, env, for_signature): + """ + Get the basename for a library (so for libxyz.so, return xyz) + :param target: + :param source: + :param env: + :param for_signature: + :return: + """ + target_name = str(target) + ldmodule_prefix = env.subst('$LDMODULEPREFIX') + ldmodule_suffix = env.subst("$_LDMODULESUFFIX") + + if target_name.startswith(ldmodule_prefix): + target_name = target_name[len(ldmodule_prefix):] + + if target_name.endswith(ldmodule_suffix): + target_name = target_name[:-len(ldmodule_suffix)] + + return target_name + + +def _ldmodule_soversion(target, source, env, for_signature): + """Function to determine what to use for SOVERSION""" + + if 'SOVERSION' in env: + return '.$SOVERSION' + elif 'LDMODULEVERSION' in env: + ldmod_version = env.subst('$LDMODULEVERSION') + # We use only the most significant digit of LDMODULEVERSION + return '.' + ldmod_version.split('.')[0] + else: + return '' + + +def _ldmodule_soname(target, source, env, for_signature): + if 'SONAME' in env: + return '$SONAME' + else: + return "$LDMODULEPREFIX$_get_ldmodule_stem$_LDMODULESOVERSION${LDMODULESUFFIX}" + + +def setup_loadable_module_logic(env): + """ + Just the logic for loadable modules + + For most platforms, a loadable module is the same as a shared + library. Platforms which are different can override these, but + setting them the same means that LoadableModule works everywhere. + + :param env: + :return: + """ + + createLoadableModuleBuilder(env) + + env['_get_ldmodule_stem'] = _get_ldmodule_stem + env['_LDMODULESOVERSION'] = _ldmodule_soversion + env['_LDMODULESONAME'] = _ldmodule_soname + + env['LDMODULENAME'] = '${LDMODULEPREFIX}$_get_ldmodule_stem${_LDMODULESUFFIX}' + + # This is the non versioned LDMODULE filename + # If LDMODULEVERSION is defined then this will symlink to $LDMODULENAME + env['LDMODULE_NOVERSION_SYMLINK'] = '${LDMODULEPREFIX}$_get_ldmodule_stem${LDMODULESUFFIX}' + + # This is the sonamed file name + # If LDMODULEVERSION is defined then this will symlink to $LDMODULENAME + env['LDMODULE_SONAME_SYMLINK'] = '$_LDMODULESONAME' + + env['_LDMODULEVERSION'] = "${LDMODULEVERSION and '.'+LDMODULEVERSION or ''}" + env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' + + env['LDMODULEEMITTER'] = [lib_emitter, ldmod_symlink_emitter] + + env['LDMODULEPREFIX'] = '$SHLIBPREFIX' + env['_LDMODULESUFFIX'] = '${_LDMODULEVERSION}${LDMODULESUFFIX}' + env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' + + env['LDMODULE'] = '$SHLINK' + + env['LDMODULEFLAGS'] = '$SHLINKFLAGS' + + env['LDMODULECOM'] = '$LDMODULE -o $TARGET $LDMODULEFLAGS $__LDMODULEVERSIONFLAGS $__RPATH $SOURCES ' \ + '$_LIBDIRFLAGS $_LIBFLAGS ' + + env['LDMODULEVERSION'] = '$SHLIBVERSION' + env['LDMODULENOVERSIONSYMLINKS'] = '$SHLIBNOVERSIONSYMLINKS' \ No newline at end of file diff --git a/SCons/Tool/linkCommon/SharedLibrary.py b/SCons/Tool/linkCommon/SharedLibrary.py new file mode 100644 index 0000000..d8f780d --- /dev/null +++ b/SCons/Tool/linkCommon/SharedLibrary.py @@ -0,0 +1,153 @@ +from SCons.Tool import createSharedLibBuilder +from SCons.Util import CLVar +from . import lib_emitter, EmitLibSymlinks, StringizeLibSymlinks + + +def shlib_symlink_emitter(target, source, env, **kw): + verbose = False + + if 'variable_prefix' in kw: + var_prefix = kw['variable_prefix'] + else: + var_prefix = 'SHLIB' + + do_symlinks = env.subst('$%sNOVERSIONSYMLINKS' % var_prefix) + if do_symlinks in ['1', 'True', 'true', True]: + return target, source + + shlibversion = env.subst('$%sVERSION' % var_prefix) + if shlibversion: + if verbose: + print("shlib_symlink_emitter: %sVERSION=%s" % (var_prefix, shlibversion)) + + libnode = target[0] + linkdir = libnode.get_dir() + shlib_soname_symlink = env.subst('$%s_SONAME_SYMLINK' % var_prefix, target=target, source=source) + shlib_noversion_symlink = env.subst('$%s_NOVERSION_SYMLINK' % var_prefix, target=target, source=source) + + if verbose: + print("shlib_soname_symlink :%s" % shlib_soname_symlink) + print("shlib_noversion_symlink :%s" % shlib_noversion_symlink) + print("libnode :%s" % libnode) + + symlinks = [(env.File(shlib_soname_symlink), libnode), + (env.File(shlib_noversion_symlink), libnode)] + + if verbose: + print("_lib_emitter: symlinks={!r}".format( + ', '.join(["%r->%r" % (k, v) for k, v in StringizeLibSymlinks(symlinks)]) + )) + + if symlinks: + # This does the actual symlinking + EmitLibSymlinks(env, symlinks, target[0]) + + # This saves the information so if the versioned shared library is installed + # it can faithfully reproduce the correct symlinks + target[0].attributes.shliblinks = symlinks + + return target, source + + +def _soversion(target, source, env, for_signature): + """Function to determine what to use for SOVERSION""" + + if 'SOVERSION' in env: + return '.$SOVERSION' + elif 'SHLIBVERSION' in env: + shlibversion = env.subst('$SHLIBVERSION') + # We use only the most significant digit of SHLIBVERSION + return '.' + shlibversion.split('.')[0] + else: + return '' + + +def _soname(target, source, env, for_signature): + + if 'SONAME' in env: + # Now verify that SOVERSION is not also set as that is not allowed + if 'SOVERSION' in env: + raise SCons.Errors.UserError('Ambiguous library .so naming, both SONAME: %s and SOVERSION: %s are defined. ' + 'Only one can be defined for a target library.' % (env['SONAME'], env['SOVERSION'])) + return '$SONAME' + else: + return "$_get_shlib_dir$SHLIBPREFIX$_get_shlib_stem$_SHLIBSOVERSION${SHLIBSUFFIX}" + + +def _get_shlib_stem(target, source, env, for_signature): + """ + Get the basename for a library (so for libxyz.so, return xyz) + :param target: + :param source: + :param env: + :param for_signature: + :return: + """ + verbose = False + + target_name = str(target.name) + shlibprefix = env.subst('$SHLIBPREFIX') + shlibsuffix = env.subst("$_SHLIBSUFFIX") + + if verbose and not for_signature: + print("_get_shlib_stem: target_name:%s shlibprefix:%s shlibsuffix:%s"%(target_name, shlibprefix, shlibsuffix)) + + if target_name.startswith(shlibprefix): + target_name = target_name[len(shlibprefix):] + + if target_name.endswith(shlibsuffix): + target_name = target_name[:-len(shlibsuffix)] + + if verbose and not for_signature: + print("_get_shlib_stem: target_name:%s AFTER"%(target_name,)) + + return target_name + + +def _get_shlib_dir(target, source, env, for_signature): + """ + Get the directory the shlib is in. + """ + if target.dir: + return "%s/"%str(target.dir) + else: + return "" + +def setup_shared_lib_logic(env): + """ + Just the logic for shared libraries + :param env: + :return: + """ + createSharedLibBuilder(env) + + env['_get_shlib_stem'] = _get_shlib_stem + env['_get_shlib_dir'] = _get_shlib_dir + env['_SHLIBSOVERSION'] = _soversion + env['_SHLIBSONAME'] = _soname + + env['SHLIBNAME'] = '${_get_shlib_dir}${SHLIBPREFIX}$_get_shlib_stem${_SHLIBSUFFIX}' + + # This is the non versioned shlib filename + # If SHLIBVERSION is defined then this will symlink to $SHLIBNAME + env['SHLIB_NOVERSION_SYMLINK'] = '${_get_shlib_dir}${SHLIBPREFIX}$_get_shlib_stem${SHLIBSUFFIX}' + + # This is the sonamed file name + # If SHLIBVERSION is defined then this will symlink to $SHLIBNAME + env['SHLIB_SONAME_SYMLINK'] = '$_SHLIBSONAME' + + # Note this is gnu style + env['SHLIBSONAMEFLAGS'] = '-Wl,-soname=$_SHLIBSONAME' + env['_SHLIBVERSION'] = "${SHLIBVERSION and '.'+SHLIBVERSION or ''}" + env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' + + env['SHLIBEMITTER'] = [lib_emitter, shlib_symlink_emitter] + + env['SHLIBPREFIX'] = 'lib' + env['_SHLIBSUFFIX'] = '${SHLIBSUFFIX}${_SHLIBVERSION}' + + env['SHLINKFLAGS'] = CLVar('$LINKFLAGS -shared') + + env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' + env['SHLINKCOMSTR'] = '$SHLINKCOM' + env['SHLINK'] = '$LINK' diff --git a/SCons/Tool/linkCommon/__init__.py b/SCons/Tool/linkCommon/__init__.py index c49bc23..7aaffab 100644 --- a/SCons/Tool/linkCommon/__init__.py +++ b/SCons/Tool/linkCommon/__init__.py @@ -25,396 +25,12 @@ Common link/shared library logic """ -import os -import re -import sys -from typing import Callable - import SCons.Util import SCons.Warnings from SCons.Tool.DCommon import isD from SCons.Util import is_List - -def _call_linker_cb(env, callback, args, result=None): - """Returns the result of env['LINKCALLBACKS'][callback](*args) - if env['LINKCALLBACKS'] is a dictionary and env['LINKCALLBACKS'][callback] - is callable. If these conditions are not met, return the value provided as - the *result* argument. This function is mainly used for generating library - info such as versioned suffixes, symlink maps, sonames etc. by delegating - the core job to callbacks configured by current linker tool""" - - Verbose = False - - if Verbose: - print('_call_linker_cb: args=%r' % args) - print('_call_linker_cb: callback=%r' % callback) - - try: - cbfun = env['LINKCALLBACKS'][callback] - except (KeyError, TypeError): - if Verbose: - print('_call_linker_cb: env["LINKCALLBACKS"][%r] not found or can not be used' % callback) - else: - if Verbose: - print('_call_linker_cb: env["LINKCALLBACKS"][%r] found' % callback) - print('_call_linker_cb: env["LINKCALLBACKS"][%r]=%r' % (callback, cbfun)) - if isinstance(cbfun, Callable): - if Verbose: - print('_call_linker_cb: env["LINKCALLBACKS"][%r] is callable' % callback) - result = cbfun(env, *args) - return result - - -class _ShLibInfoSupport: - @property - def libtype(self): - return 'ShLib' - - def get_lib_prefix(self, env, *args, **kw): - return _call_env_subst(env, '$SHLIBPREFIX', *args, **kw) - - def get_lib_suffix(self, env, *args, **kw): - return _call_env_subst(env, '$SHLIBSUFFIX', *args, **kw) - - def get_lib_version(self, env, *args, **kw): - return _call_env_subst(env, '$SHLIBVERSION', *args, **kw) - - def get_lib_noversionsymlinks(self, env, *args, **kw): - return _call_env_subst(env, '$SHLIBNOVERSIONSYMLINKS', *args, **kw) - - -class _LdModInfoSupport: - @property - def libtype(self): - return 'LdMod' - - def get_lib_prefix(self, env, *args, **kw): - return _call_env_subst(env, '$LDMODULEPREFIX', *args, **kw) - - def get_lib_suffix(self, env, *args, **kw): - return _call_env_subst(env, '$LDMODULESUFFIX', *args, **kw) - - def get_lib_version(self, env, *args, **kw): - return _call_env_subst(env, '$LDMODULEVERSION', *args, **kw) - - def get_lib_noversionsymlinks(self, env, *args, **kw): - return _call_env_subst(env, '$LDMODULENOVERSIONSYMLINKS', *args, **kw) - - -class _ImpLibInfoSupport: - @property - def libtype(self): - return 'ImpLib' - - def get_lib_prefix(self, env, *args, **kw): - return _call_env_subst(env, '$IMPLIBPREFIX', *args, **kw) - - def get_lib_suffix(self, env, *args, **kw): - return _call_env_subst(env, '$IMPLIBSUFFIX', *args, **kw) - - def get_lib_version(self, env, *args, **kw): - version = _call_env_subst(env, '$IMPLIBVERSION', *args, **kw) - if not version: - try: - lt = kw['implib_libtype'] - except KeyError: - pass - else: - if lt == 'ShLib': - version = _call_env_subst(env, '$SHLIBVERSION', *args, **kw) - elif lt == 'LdMod': - version = _call_env_subst(env, '$LDMODULEVERSION', *args, **kw) - return version - - def get_lib_noversionsymlinks(self, env, *args, **kw): - disable = None - try: - env['IMPLIBNOVERSIONSYMLINKS'] - except KeyError: - try: - lt = kw['implib_libtype'] - except KeyError: - pass - else: - if lt == 'ShLib': - disable = _call_env_subst(env, '$SHLIBNOVERSIONSYMLINKS', *args, **kw) - elif lt == 'LdMod': - disable = _call_env_subst(env, '$LDMODULENOVERSIONSYMLINKS', *args, **kw) - else: - disable = _call_env_subst(env, '$IMPLIBNOVERSIONSYMLINKS', *args, **kw) - return disable - - -class _LibInfoGeneratorBase: - """Generator base class for library-related info such as suffixes for - versioned libraries, symlink maps, sonames etc. It handles commonities - of SharedLibrary and LoadableModule - """ - _support_classes = {'ShLib': _ShLibInfoSupport, - 'LdMod': _LdModInfoSupport, - 'ImpLib': _ImpLibInfoSupport} - - def __init__(self, libtype, infoname): - self.libtype = libtype - self.infoname = infoname - - @property - def libtype(self): - return self._support.libtype - - @libtype.setter - def libtype(self, libtype): - try: - support_class = self._support_classes[libtype] - except KeyError: - raise ValueError('unsupported libtype %r' % libtype) - self._support = support_class() - - def get_lib_prefix(self, env, *args, **kw): - return self._support.get_lib_prefix(env, *args, **kw) - - def get_lib_suffix(self, env, *args, **kw): - return self._support.get_lib_suffix(env, *args, **kw) - - def get_lib_version(self, env, *args, **kw): - return self._support.get_lib_version(env, *args, **kw) - - def get_lib_noversionsymlinks(self, env, *args, **kw): - return self._support.get_lib_noversionsymlinks(env, *args, **kw) - - def get_versioned_lib_info_generator(self, **kw): - """ - Returns name of generator linker callback that will be used to generate - our info for a versioned library. For example, if our libtype is 'ShLib' - and infoname is 'Prefix', it would return 'VersionedShLibPrefix'. - """ - try: - libtype = kw['generator_libtype'] - except KeyError: - libtype = self.libtype - return 'Versioned%s%s' % (libtype, self.infoname) - - def generate_versioned_lib_info(self, env, args, result=None, **kw): - callback = self.get_versioned_lib_info_generator(**kw) - return _call_linker_cb(env, callback, args, result) - - -class _LibPrefixGenerator(_LibInfoGeneratorBase): - """Library prefix generator, used as target_prefix in SharedLibrary and - LoadableModule builders""" - - def __init__(self, libtype): - super(_LibPrefixGenerator, self).__init__(libtype, 'Prefix') - - def __call__(self, env, sources=None, **kw): - Verbose = False - - if sources and 'source' not in kw: - kw2 = kw.copy() - kw2['source'] = sources - else: - kw2 = kw - - prefix = self.get_lib_prefix(env, **kw2) - if Verbose: - print("_LibPrefixGenerator: input prefix=%r" % prefix) - - version = self.get_lib_version(env, **kw2) - if Verbose: - print("_LibPrefixGenerator: version=%r" % version) - - if version: - prefix = self.generate_versioned_lib_info(env, [prefix, version], prefix, **kw2) - - if Verbose: - print("_LibPrefixGenerator: return prefix=%r" % prefix) - return prefix - - -ShLibPrefixGenerator = _LibPrefixGenerator('ShLib') -LdModPrefixGenerator = _LibPrefixGenerator('LdMod') -ImpLibPrefixGenerator = _LibPrefixGenerator('ImpLib') - - -class _LibSuffixGenerator(_LibInfoGeneratorBase): - """Library suffix generator, used as target_suffix in SharedLibrary and - LoadableModule builders""" - - def __init__(self, libtype): - super(_LibSuffixGenerator, self).__init__(libtype, 'Suffix') - - def __call__(self, env, sources=None, **kw): - Verbose = False - - if sources and 'source' not in kw: - kw2 = kw.copy() - kw2['source'] = sources - else: - kw2 = kw - - suffix = self.get_lib_suffix(env, **kw2) - if Verbose: - print("_LibSuffixGenerator: input suffix=%r" % suffix) - - version = self.get_lib_version(env, **kw2) - if Verbose: - print("_LibSuffixGenerator: version=%r" % version) - - if version: - suffix = self.generate_versioned_lib_info(env, [suffix, version], suffix, **kw2) - - if Verbose: - print("_LibSuffixGenerator: return suffix=%r" % suffix) - return suffix - - -ShLibSuffixGenerator = _LibSuffixGenerator('ShLib') -LdModSuffixGenerator = _LibSuffixGenerator('LdMod') -ImpLibSuffixGenerator = _LibSuffixGenerator('ImpLib') - - -class _LibSymlinkGenerator(_LibInfoGeneratorBase): - """Library symlink map generator. It generates a list of symlinks that - should be created by SharedLibrary or LoadableModule builders""" - - def __init__(self, libtype): - super(_LibSymlinkGenerator, self).__init__(libtype, 'Symlinks') - - def __call__(self, env, libnode, **kw): - Verbose = False - - if libnode and 'target' not in kw: - kw2 = kw.copy() - kw2['target'] = libnode - else: - kw2 = kw - - if Verbose: - print("_LibSymLinkGenerator: libnode=%r" % libnode.get_path()) - - symlinks = None - - version = self.get_lib_version(env, **kw2) - disable = self.get_lib_noversionsymlinks(env, **kw2) - if Verbose: - print('_LibSymlinkGenerator: version=%r' % version) - print('_LibSymlinkGenerator: disable=%r' % disable) - - if version and not disable: - prefix = self.get_lib_prefix(env, **kw2) - suffix = self.get_lib_suffix(env, **kw2) - symlinks = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) - - if Verbose: - print('_LibSymlinkGenerator: return symlinks=%r' % StringizeLibSymlinks(symlinks)) - return symlinks - - -ShLibSymlinkGenerator = _LibSymlinkGenerator('ShLib') -LdModSymlinkGenerator = _LibSymlinkGenerator('LdMod') -ImpLibSymlinkGenerator = _LibSymlinkGenerator('ImpLib') - - -class _LibNameGenerator(_LibInfoGeneratorBase): - """Generates "unmangled" library name from a library file node. - - Generally, it's thought to revert modifications done by prefix/suffix - generators (_LibPrefixGenerator/_LibSuffixGenerator) used by a library - builder. For example, on gnulink the suffix generator used by SharedLibrary - builder appends $SHLIBVERSION to $SHLIBSUFFIX producing node name which - ends with "$SHLIBSUFFIX.$SHLIBVERSION". Correspondingly, the implementation - of _LibNameGenerator replaces "$SHLIBSUFFIX.$SHLIBVERSION" with - "$SHLIBSUFFIX" in the node's basename. So that, if $SHLIBSUFFIX is ".so", - $SHLIBVERSION is "0.1.2" and the node path is "/foo/bar/libfoo.so.0.1.2", - the _LibNameGenerator shall return "libfoo.so". Other link tools may - implement it's own way of library name unmangling. - """ - - def __init__(self, libtype): - super(_LibNameGenerator, self).__init__(libtype, 'Name') - - def __call__(self, env, libnode, **kw): - """Returns "demangled" library name""" - Verbose = False - - if libnode and 'target' not in kw: - kw2 = kw.copy() - kw2['target'] = libnode - else: - kw2 = kw - - if Verbose: - print("_LibNameGenerator: libnode=%r" % libnode.get_path()) - - version = self.get_lib_version(env, **kw2) - if Verbose: - print('_LibNameGenerator: version=%r' % version) - - name = None - if version: - prefix = self.get_lib_prefix(env, **kw2) - suffix = self.get_lib_suffix(env, **kw2) - name = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) - - if not name: - name = os.path.basename(libnode.get_path()) - - if Verbose: - print('_LibNameGenerator: return name=%r' % name) - - return name - - -ShLibNameGenerator = _LibNameGenerator('ShLib') -LdModNameGenerator = _LibNameGenerator('LdMod') -ImpLibNameGenerator = _LibNameGenerator('ImpLib') - - -class _LibSonameGenerator(_LibInfoGeneratorBase): - """Library soname generator. Returns library soname (e.g. libfoo.so.0) for - a given node (e.g. /foo/bar/libfoo.so.0.1.2)""" - - def __init__(self, libtype): - super(_LibSonameGenerator, self).__init__(libtype, 'Soname') - - def __call__(self, env, libnode, **kw): - """Returns a SONAME based on a shared library's node path""" - Verbose = False - - if libnode and 'target' not in kw: - kw2 = kw.copy() - kw2['target'] = libnode - else: - kw2 = kw - - if Verbose: - print("_LibSonameGenerator: libnode=%r" % libnode.get_path()) - - soname = _call_env_subst(env, '$SONAME', **kw2) - if not soname: - version = self.get_lib_version(env, **kw2) - if Verbose: - print("_LibSonameGenerator: version=%r" % version) - if version: - prefix = self.get_lib_prefix(env, **kw2) - suffix = self.get_lib_suffix(env, **kw2) - soname = self.generate_versioned_lib_info(env, [libnode, version, prefix, suffix], **kw2) - - if not soname: - # fallback to library name (as returned by appropriate _LibNameGenerator) - soname = _LibNameGenerator(self.libtype)(env, libnode) - if Verbose: - print("_LibSonameGenerator: FALLBACK: soname=%r" % soname) - - if Verbose: - print("_LibSonameGenerator: return soname=%r" % soname) - - return soname - - -ShLibSonameGenerator = _LibSonameGenerator('ShLib') -LdModSonameGenerator = _LibSonameGenerator('LdMod') +issued_mixed_link_warning = False def StringizeLibSymlinks(symlinks): @@ -455,8 +71,8 @@ def CreateLibSymlinks(env, symlinks): form [ (link, linktarget), ... ], where link and linktarget are SCons nodes. """ - Verbose = False + for link, linktgt in symlinks: linktgt = link.get_dir().rel_path(linktgt) link = link.get_path() @@ -491,13 +107,13 @@ def LibSymlinksStrFun(target, source, env, *args): if symlinks: if cmd is None: cmd = "" if cmd: cmd += "\n" - cmd += "Create symlinks for: %r" % tgt.get_path() + cmd += "Create symlinks for: %r\n " % tgt.get_path() try: - linkstr = ', '.join(["%r->%r" % (k, v) for k, v in StringizeLibSymlinks(symlinks)]) + linkstr = '\n '.join(["%r->%r" % (k, v) for k, v in StringizeLibSymlinks(symlinks)]) except (KeyError, ValueError): pass else: - cmd += ": %s" % linkstr + cmd += "%s" % linkstr return cmd @@ -539,235 +155,13 @@ def smart_link(source, target, env, for_signature): return '$CC' -def _lib_emitter(target, source, env, **kw): - Verbose = False - if Verbose: +def lib_emitter(target, source, env, **kw): + verbose = False + if verbose: print("_lib_emitter: target[0]={!r}".format(target[0].get_path())) for tgt in target: if SCons.Util.is_String(tgt): tgt = env.File(tgt) tgt.attributes.shared = 1 - try: - symlink_generator = kw['symlink_generator'] - except KeyError: - pass - else: - if Verbose: - print("_lib_emitter: symlink_generator={!r}".format(symlink_generator)) - symlinks = symlink_generator(env, target[0]) - if Verbose: - print("_lib_emitter: symlinks={!r}".format(symlinks)) - - if symlinks: - EmitLibSymlinks(env, symlinks, target[0]) - target[0].attributes.shliblinks = symlinks return target, source - - -def shlib_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator=ShLibSymlinkGenerator) - - -def ldmod_emitter(target, source, env): - return _lib_emitter(target, source, env, symlink_generator=LdModSymlinkGenerator) - - -def _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw): - """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so'""" - Verbose = False - - if Verbose: - print("_versioned_lib_name: libnode={!r}".format(libnode.get_path())) - print("_versioned_lib_name: version={!r}".format(version)) - print("_versioned_lib_name: prefix={!r}".format(prefix)) - print("_versioned_lib_name: suffix={!r}".format(suffix)) - print("_versioned_lib_name: suffix_generator={!r}".format(suffix_generator)) - - versioned_name = os.path.basename(libnode.get_path()) - if Verbose: - print("_versioned_lib_name: versioned_name={!r}".format(versioned_name)) - - versioned_prefix = prefix_generator(env, **kw) - versioned_suffix = suffix_generator(env, **kw) - if Verbose: - print("_versioned_lib_name: versioned_prefix={!r}".format(versioned_prefix)) - print("_versioned_lib_name: versioned_suffix={!r}".format(versioned_suffix)) - - versioned_prefix_re = '^' + re.escape(versioned_prefix) - versioned_suffix_re = re.escape(versioned_suffix) + '$' - name = re.sub(versioned_prefix_re, prefix, versioned_name) - name = re.sub(versioned_suffix_re, suffix, name) - if Verbose: - print("_versioned_lib_name: name={!r}".format(name)) - return name - - -def _versioned_shlib_name(env, libnode, version, prefix, suffix, **kw): - prefix_generator = ShLibPrefixGenerator - suffix_generator = ShLibSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) - - -def _versioned_ldmod_name(env, libnode, version, prefix, suffix, **kw): - prefix_generator = LdModPrefixGenerator - suffix_generator = LdModSuffixGenerator - return _versioned_lib_name(env, libnode, version, prefix, suffix, prefix_generator, suffix_generator, **kw) - - -def _versioned_lib_suffix(env, suffix, version): - """For suffix='.so' and version='0.1.2' it returns '.so.0.1.2'""" - Verbose = False - if Verbose: - print("_versioned_lib_suffix: suffix={!r}".format(suffix)) - print("_versioned_lib_suffix: version={!r}".format(version)) - if not suffix.endswith(version): - suffix = suffix + '.' + version - if Verbose: - print("_versioned_lib_suffix: return suffix={!r}".format(suffix)) - return suffix - - -def _versioned_lib_soname(env, libnode, version, prefix, suffix, name_func): - """For libnode='/optional/dir/libfoo.so.X.Y.Z' it returns 'libfoo.so.X'""" - Verbose = False - if Verbose: - print("_versioned_lib_soname: version={!r}".format(version)) - name = name_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_versioned_lib_soname: name={!r}".format(name)) - major = version.split('.')[0] - - # if a desired SONAME was supplied, use that, otherwise create - # a default from the major version - if env.get('SONAME'): - soname = ShLibSonameGenerator(env, libnode) - else: - soname = name + '.' + major - if Verbose: - print("_versioned_lib_soname: soname={!r}".format(soname)) - return soname - - -def _versioned_shlib_soname(env, libnode, version, prefix, suffix): - return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_shlib_name) - - -def _versioned_ldmod_soname(env, libnode, version, prefix, suffix): - return _versioned_lib_soname(env, libnode, version, prefix, suffix, _versioned_ldmod_name) - - -def _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func): - """Generate link names that should be created for a versioned shared library. - Returns a dictionary in the form { linkname : linktarget } - """ - Verbose = False - - if Verbose: - print("_versioned_lib_symlinks: libnode={!r}".format(libnode.get_path())) - print("_versioned_lib_symlinks: version={!r}".format(version)) - - if sys.platform.startswith('openbsd'): - # OpenBSD uses x.y shared library versioning numbering convention - # and doesn't use symlinks to backwards-compatible libraries - if Verbose: - print("_versioned_lib_symlinks: return symlinks={!r}".format(None)) - return None - - linkdir = libnode.get_dir() - if Verbose: - print("_versioned_lib_symlinks: linkdir={!r}".format(linkdir.get_path())) - - name = name_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_versioned_lib_symlinks: name={!r}".format(name)) - - soname = soname_func(env, libnode, version, prefix, suffix) - if Verbose: - print("_versioned_lib_symlinks: soname={!r}".format(soname)) - - link0 = env.fs.File(soname, linkdir) - link1 = env.fs.File(name, linkdir) - - # We create direct symlinks, not daisy-chained. - if link0 == libnode: - # This enables SHLIBVERSION without periods (e.g. SHLIBVERSION=1) - symlinks = [(link1, libnode)] - else: - # This handles usual SHLIBVERSION, i.e. '1.2', '1.2.3', etc. - symlinks = [(link0, libnode), (link1, libnode)] - - if Verbose: - print("_versioned_lib_symlinks: return symlinks={!r}".format( - StringizeLibSymlinks(symlinks))) - - return symlinks - - -def _versioned_shlib_symlinks(env, libnode, version, prefix, suffix): - name_func = env['LINKCALLBACKS']['VersionedShLibName'] - soname_func = env['LINKCALLBACKS']['VersionedShLibSoname'] - - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) - - -def _versioned_ldmod_symlinks(env, libnode, version, prefix, suffix): - name_func = _versioned_ldmod_name - soname_func = _versioned_ldmod_soname - - name_func = env['LINKCALLBACKS']['VersionedLdModName'] - soname_func = env['LINKCALLBACKS']['VersionedLdModSoname'] - - return _versioned_lib_symlinks(env, libnode, version, prefix, suffix, name_func, soname_func) - - -def _versioned_lib_callbacks(): - return { - 'VersionedShLibSuffix': _versioned_lib_suffix, - 'VersionedLdModSuffix': _versioned_lib_suffix, - 'VersionedShLibSymlinks': _versioned_shlib_symlinks, - 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, - 'VersionedShLibName': _versioned_shlib_name, - 'VersionedLdModName': _versioned_ldmod_name, - 'VersionedShLibSoname': _versioned_shlib_soname, - 'VersionedLdModSoname': _versioned_ldmod_soname, - }.copy() - - -issued_mixed_link_warning = False - - -def _setup_versioned_lib_variables(env, **kw): - """ - Setup all variables required by the versioning machinery - """ - - tool = None - try: - tool = kw['tool'] - except KeyError: - pass - - use_soname = False - try: - use_soname = kw['use_soname'] - except KeyError: - pass - - # The $_SHLIBVERSIONFLAGS define extra commandline flags used when - # building VERSIONED shared libraries. It's always set, but used only - # when VERSIONED library is built (see __SHLIBVERSIONFLAGS in SCons/Defaults.py). - if use_soname: - # If the linker uses SONAME, then we need this little automata - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' - env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' - env['_SHLIBSONAME'] = '${ShLibSonameGenerator(__env__,TARGET)}' - env['_LDMODULESONAME'] = '${LdModSonameGenerator(__env__,TARGET)}' - env['ShLibSonameGenerator'] = ShLibSonameGenerator - env['LdModSonameGenerator'] = LdModSonameGenerator - else: - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' - env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS' - - # LDOMDULVERSIONFLAGS should always default to $SHLIBVERSIONFLAGS - env['LDMODULEVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' \ No newline at end of file diff --git a/SCons/Tool/sunlink.py b/SCons/Tool/sunlink.py index f668903..b0c9816 100644 --- a/SCons/Tool/sunlink.py +++ b/SCons/Tool/sunlink.py @@ -8,6 +8,10 @@ selection method. """ # +# 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 @@ -30,9 +34,7 @@ selection method. import os.path -import SCons.Tool.linkCommon as linkCommon import SCons.Util - from . import link ccLinker = None @@ -52,23 +54,20 @@ for d in dirs: ccLinker = linker break + def generate(env): """Add Builders and construction variables for Forte to an Environment.""" link.generate(env) - + env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -G') env['RPATHPREFIX'] = '-R' env['RPATHSUFFIX'] = '' env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}' - # Support for versioned libraries - linkCommon._setup_versioned_lib_variables(env, tool='sunlink', use_soname=True) - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -h $_SHLIBSONAME' env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -h $_LDMODULESONAME' - env['LINKCALLBACKS'] = linkCommon._versioned_lib_callbacks() def exists(env): return ccLinker diff --git a/SCons/__init__.py b/SCons/__init__.py index fcd665e..c9ca70f 100644 --- a/SCons/__init__.py +++ b/SCons/__init__.py @@ -1,9 +1,9 @@ __version__="4.0.1.9998" __copyright__="Copyright (c) 2001 - 2020 The SCons Foundation" __developer__="bdbaddog" -__date__="2020-10-09 19:00:35" +__date__="2020-12-21 01:23:32" __buildsys__="ProDog2020" -__revision__="93525bed88d19a00f5de400086c0046011d3b833" -__build__="93525bed88d19a00f5de400086c0046011d3b833" +__revision__="78292be9cbb471101e6ed4ec5f6da0161730c656" +__build__="78292be9cbb471101e6ed4ec5f6da0161730c656" # make sure compatibility is always in place import SCons.compat # noqa \ No newline at end of file diff --git a/test/LINK/SHLIBVERSIONFLAGS.py b/test/LINK/SHLIBVERSIONFLAGS.py index 7bcabf0..7832862 100644 --- a/test/LINK/SHLIBVERSIONFLAGS.py +++ b/test/LINK/SHLIBVERSIONFLAGS.py @@ -25,10 +25,10 @@ # - import TestSCons -import SCons.Platform + import SCons.Defaults +import SCons.Platform foo_c_src = "void foo() {}\n" @@ -39,34 +39,33 @@ tool_list = SCons.Platform.DefaultToolList(platform, env) test = TestSCons.TestSCons() if 'gnulink' in tool_list: versionflags = r".+ -Wl,-soname=libfoo.so.1( .+)+" - soname='libfoo.so.4' - sonameVersionFlags=r".+ -Wl,-soname=%s( .+)+" % soname + soname = 'libfoo.so.4' + sonameVersionFlags = r".+ -Wl,-soname=%s( .+)+" % soname elif 'sunlink' in tool_list: versionflags = r".+ -h libfoo.so.1( .+)+" - soname='libfoo.so.4' - sonameVersionFlags=r".+ -h %s( .+)+" % soname + soname = 'libfoo.so.4' + sonameVersionFlags = r".+ -h %s( .+)+" % soname elif 'applelink' in tool_list: - versionflags = r".+ 'libfoo.1.dylib'->'libfoo.1.2.3.dylib'(.+)+" - soname='libfoo.4.dylib' - sonameVersionFlags=r".+ '%s'->'libfoo.1.2.3.dylib'(.+)+" % soname + versionflags = r" 'libfoo.1.dylib'->'libfoo.1.2.3.dylib'" + soname = 'libfoo.4.dylib' + sonameVersionFlags = r" '%s'->'libfoo.1.2.3.dylib'(.+)+" % soname else: test.skip_test('No testable linkers found, skipping the test\n') - # stdout must not contain SHLIBVERSIONFLAGS if there is no SHLIBVERSION provided test.write('foo.c', foo_c_src) test.write('SConstruct', "SharedLibrary('foo','foo.c')\n") test.run() test.fail_test(test.match_re_dotall(test.stdout(), versionflags)) -test.run(arguments = ['-c']) +test.run(arguments=['-c']) # stdout must contain SHLIBVERSIONFLAGS if there is SHLIBVERSION provided test = TestSCons.TestSCons() test.write('foo.c', foo_c_src) test.write('SConstruct', "SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3')\n") -test.run(stdout = versionflags, match = TestSCons.match_re_dotall) -test.run(arguments = ['-c']) +test.run(stdout=versionflags, match=TestSCons.match_re_dotall) +test.run(arguments=['-c']) # stdout must contain SONAME if there is SONAME provided test = TestSCons.TestSCons() @@ -74,9 +73,9 @@ test.write('foo.c', foo_c_src) test.write('SConstruct', """ SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3',SONAME='%s') """ % soname) -test.run(stdout = sonameVersionFlags, match = TestSCons.match_re_dotall) +test.run(stdout=sonameVersionFlags, match=TestSCons.match_re_dotall) test.must_exist(test.workpath(soname)) -test.run(arguments = ['-c']) +test.run(arguments=['-c']) # stdout must contain SOVERSION if there is SOVERSION provided test = TestSCons.TestSCons() @@ -84,9 +83,9 @@ test.write('foo.c', foo_c_src) test.write('SConstruct', """ SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3',SOVERSION='4') """) -test.run(stdout = sonameVersionFlags, match = TestSCons.match_re_dotall) +test.run(stdout=sonameVersionFlags, match=TestSCons.match_re_dotall) test.must_exist(test.workpath(soname)) -test.run(arguments = ['-c']) +test.run(arguments=['-c']) # test if both SONAME and SOVERSION are used test = TestSCons.TestSCons() @@ -94,7 +93,7 @@ test.write('foo.c', foo_c_src) test.write('SConstruct', """ SharedLibrary('foo','foo.c',SHLIBVERSION='1.2.3',SONAME='%s',SOVERSION='4') """ % soname) -test.run(status=2,stderr=None) +test.run(status=2, stderr=None) test.must_contain_all_lines(test.stderr(), ['Ambiguous library .so naming']) test.pass_test() -- cgit v0.12 From 336963aef7214188da046f47774fbbee773f039c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 20 Dec 2020 19:31:43 -0800 Subject: Address sider issues --- SCons/Builder.py | 2 +- SCons/Tool/cyglink.py | 2 +- SCons/Tool/linkCommon/SharedLibrary.py | 14 +++++++------- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/SCons/Builder.py b/SCons/Builder.py index 035196d..82b6b7e 100644 --- a/SCons/Builder.py +++ b/SCons/Builder.py @@ -503,7 +503,7 @@ class BuilderBase: splitext = lambda S: self.splitext(S,env) tlist = [ t_from_s(pre, suf, splitext) ] else: - orig_target = target + # orig_target = target target = self._adjustixes(target, pre, suf, self.ensure_suffix) tlist = env.arg2nodes(target, target_factory, target=target, source=source) diff --git a/SCons/Tool/cyglink.py b/SCons/Tool/cyglink.py index 1995ac3..bb5cd10 100644 --- a/SCons/Tool/cyglink.py +++ b/SCons/Tool/cyglink.py @@ -9,7 +9,7 @@ selection method. """ from SCons.Tool.linkCommon import StringizeLibSymlinks, EmitLibSymlinks -from SCons.Util import CLVar +from SCons.Util import CLVar, is_String from . import gnulink diff --git a/SCons/Tool/linkCommon/SharedLibrary.py b/SCons/Tool/linkCommon/SharedLibrary.py index d8f780d..bddcb42 100644 --- a/SCons/Tool/linkCommon/SharedLibrary.py +++ b/SCons/Tool/linkCommon/SharedLibrary.py @@ -1,3 +1,4 @@ +from SCons.Errors import UserError from SCons.Tool import createSharedLibBuilder from SCons.Util import CLVar from . import lib_emitter, EmitLibSymlinks, StringizeLibSymlinks @@ -21,7 +22,6 @@ def shlib_symlink_emitter(target, source, env, **kw): print("shlib_symlink_emitter: %sVERSION=%s" % (var_prefix, shlibversion)) libnode = target[0] - linkdir = libnode.get_dir() shlib_soname_symlink = env.subst('$%s_SONAME_SYMLINK' % var_prefix, target=target, source=source) shlib_noversion_symlink = env.subst('$%s_NOVERSION_SYMLINK' % var_prefix, target=target, source=source) @@ -63,12 +63,11 @@ def _soversion(target, source, env, for_signature): def _soname(target, source, env, for_signature): - if 'SONAME' in env: # Now verify that SOVERSION is not also set as that is not allowed if 'SOVERSION' in env: - raise SCons.Errors.UserError('Ambiguous library .so naming, both SONAME: %s and SOVERSION: %s are defined. ' - 'Only one can be defined for a target library.' % (env['SONAME'], env['SOVERSION'])) + raise UserError('Ambiguous library .so naming, both SONAME: %s and SOVERSION: %s are defined. ' + 'Only one can be defined for a target library.' % (env['SONAME'], env['SOVERSION'])) return '$SONAME' else: return "$_get_shlib_dir$SHLIBPREFIX$_get_shlib_stem$_SHLIBSOVERSION${SHLIBSUFFIX}" @@ -90,7 +89,7 @@ def _get_shlib_stem(target, source, env, for_signature): shlibsuffix = env.subst("$_SHLIBSUFFIX") if verbose and not for_signature: - print("_get_shlib_stem: target_name:%s shlibprefix:%s shlibsuffix:%s"%(target_name, shlibprefix, shlibsuffix)) + print("_get_shlib_stem: target_name:%s shlibprefix:%s shlibsuffix:%s" % (target_name, shlibprefix, shlibsuffix)) if target_name.startswith(shlibprefix): target_name = target_name[len(shlibprefix):] @@ -99,7 +98,7 @@ def _get_shlib_stem(target, source, env, for_signature): target_name = target_name[:-len(shlibsuffix)] if verbose and not for_signature: - print("_get_shlib_stem: target_name:%s AFTER"%(target_name,)) + print("_get_shlib_stem: target_name:%s AFTER" % (target_name,)) return target_name @@ -109,10 +108,11 @@ def _get_shlib_dir(target, source, env, for_signature): Get the directory the shlib is in. """ if target.dir: - return "%s/"%str(target.dir) + return "%s/" % str(target.dir) else: return "" + def setup_shared_lib_logic(env): """ Just the logic for shared libraries -- cgit v0.12 From 931bb95beb5fd5c05cd3271e8e7fe0f5e026960e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 20 Dec 2020 19:44:59 -0800 Subject: temporarily comment out D shared lib support --- SCons/Tool/gdc.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/SCons/Tool/gdc.py b/SCons/Tool/gdc.py index 12c327e..f2d439f 100644 --- a/SCons/Tool/gdc.py +++ b/SCons/Tool/gdc.py @@ -118,10 +118,12 @@ def generate(env): # Support for versioned libraries env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -Wl,-soname=$_SHDLIBSONAME' - env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' - # NOTE: this is a quick hack, the soname will only work if there is - # c/c++ linker loaded which provides callback for the ShLibSonameGenerator - env['DShLibSonameGenerator'] = SCons.Tool.linkCommon.ShLibSonameGenerator + + # TODO: Fix with new versioned shared lib logic + # env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' + # # NOTE: this is a quick hack, the soname will only work if there is + # # c/c++ linker loaded which provides callback for the ShLibSonameGenerator + # env['DShLibSonameGenerator'] = SCons.Tool.linkCommon.ShLibSonameGenerator # NOTE: this is only for further reference, currently $SHDLIBVERSION does # not work, the user must use $SHLIBVERSION env['SHDLIBVERSION'] = '$SHLIBVERSION' -- cgit v0.12 From 6550042afb66dbe4ba4dcfefb8943ddb7a8208a6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 20 Dec 2020 20:04:31 -0800 Subject: Update copyrights, remove obsoleted env vars from docs for D compilers --- SCons/Tool/DCommon.py | 21 +++++++++------------ SCons/Tool/__init__.py | 35 +++++++++++++++++----------------- SCons/Tool/dmd.py | 43 ++++++++++++++++++++++-------------------- SCons/Tool/dmd.xml | 1 - SCons/Tool/gdc.py | 51 +++++++++++++++++++++++++------------------------- SCons/Tool/gdc.xml | 1 - SCons/Tool/ldc.py | 45 ++++++++++++++++++++++++-------------------- SCons/Tool/ldc.xml | 1 - 8 files changed, 100 insertions(+), 98 deletions(-) diff --git a/SCons/Tool/DCommon.py b/SCons/Tool/DCommon.py index d29db3a..128e561 100644 --- a/SCons/Tool/DCommon.py +++ b/SCons/Tool/DCommon.py @@ -1,13 +1,6 @@ -"""SCons.Tool.DCommon - -Common code for the various D tools. - -Coded by Russel Winder (russel@winder.org.uk) -2012-09-06 -""" - +# MIT License # -# __COPYRIGHT__ +# 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 @@ -27,9 +20,14 @@ Coded by Russel Winder (russel@winder.org.uk) # 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__" +"""SCons.Tool.DCommon + +Common code for the various D tools. + +Coded by Russel Winder (russel@winder.org.uk) +2012-09-06 +""" import os.path @@ -59,7 +57,6 @@ def allAtOnceEmitter(target, source, env): env.Clean(target[0], str(target[0]) + '.o') return target, source - # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/SCons/Tool/__init__.py b/SCons/Tool/__init__.py index 7c78dba..2b25e3a 100644 --- a/SCons/Tool/__init__.py +++ b/SCons/Tool/__init__.py @@ -1,20 +1,6 @@ -"""SCons.Tool - -SCons tool selection. - -This looks for modules that define a callable object that can modify -a construction environment as appropriate for a given tool (or tool -chain). - -Note that because this subsystem just *selects* a callable that can -modify a construction environment, it's possible for people to define -their own "tool specification" in an arbitrary callable function. No -one needs to use or tie in to this subsystem in order to roll their own -tool specifications. -""" - +# MIT License # -# __COPYRIGHT__ +# 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 @@ -35,7 +21,22 @@ tool specifications. # 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__" +"""SCons.Tool + +SCons tool selection. + +This looks for modules that define a callable object that can modify +a construction environment as appropriate for a given tool (or tool +chain). + +Note that because this subsystem just *selects* a callable that can +modify a construction environment, it's possible for people to define +their own "tool specification" in an arbitrary callable function. No +one needs to use or tie in to this subsystem in order to roll their own +tool specifications. +""" + + import sys import os diff --git a/SCons/Tool/dmd.py b/SCons/Tool/dmd.py index 05c54ec..76fcf51 100644 --- a/SCons/Tool/dmd.py +++ b/SCons/Tool/dmd.py @@ -1,3 +1,26 @@ +# 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. + """SCons.Tool.dmd Tool-specific initialization for the Digital Mars D compiler. @@ -49,26 +72,6 @@ LIBS """ -# -# 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. -# import SCons.Action import SCons.Builder diff --git a/SCons/Tool/dmd.xml b/SCons/Tool/dmd.xml index 13284ec..1ee0edb 100644 --- a/SCons/Tool/dmd.xml +++ b/SCons/Tool/dmd.xml @@ -65,7 +65,6 @@ Sets construction variables for D language compiler DMD. DLINKFLAGSUFFIX DRPATHPREFIX DRPATHSUFFIX -DShLibSonameGenerator SHDLIBVERSION SHDLIBVERSIONFLAGS diff --git a/SCons/Tool/gdc.py b/SCons/Tool/gdc.py index f2d439f..0341fef 100644 --- a/SCons/Tool/gdc.py +++ b/SCons/Tool/gdc.py @@ -1,3 +1,26 @@ +# 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. + """SCons.Tool.gdc Tool-specific initialization for the GDC compiler. @@ -23,31 +46,6 @@ Lib tool variables: LIBS - Same as for the linker. (libraries to pull into the .lib) """ -# -# __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__" - import SCons.Action import SCons.Defaults import SCons.Tool @@ -117,7 +115,8 @@ def generate(env): env['_RPATH'] = '${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}' # Support for versioned libraries - env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -Wl,-soname=$_SHDLIBSONAME' + env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' +' # TODO: Fix with new versioned shared lib logic # env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' diff --git a/SCons/Tool/gdc.xml b/SCons/Tool/gdc.xml index c5aed60..8248026 100644 --- a/SCons/Tool/gdc.xml +++ b/SCons/Tool/gdc.xml @@ -65,7 +65,6 @@ Sets construction variables for the D language compiler GDC. DLINKFLAGSUFFIX DRPATHPREFIX DRPATHSUFFIX -DShLibSonameGenerator SHDLIBVERSION SHDLIBVERSIONFLAGS diff --git a/SCons/Tool/ldc.py b/SCons/Tool/ldc.py index 342f3f0..23cc837 100644 --- a/SCons/Tool/ldc.py +++ b/SCons/Tool/ldc.py @@ -1,3 +1,27 @@ +# 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. + + """SCons.Tool.ldc Tool-specific initialization for the LDC compiler. @@ -23,26 +47,7 @@ Lib tool variables: LIBS - Same as for the linker. (libraries to pull into the .lib) """ -# -# 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. -# + import SCons.Action import SCons.Builder diff --git a/SCons/Tool/ldc.xml b/SCons/Tool/ldc.xml index 5f3a3b2..5802751 100644 --- a/SCons/Tool/ldc.xml +++ b/SCons/Tool/ldc.xml @@ -65,7 +65,6 @@ Sets construction variables for the D language compiler LDC2. DLINKFLAGSUFFIX DRPATHPREFIX DRPATHSUFFIX -DShLibSonameGenerator SHDLIBVERSION SHDLIBVERSIONFLAGS -- cgit v0.12 From 120480fec29a2a3d169b4a7c52f89bd512ba3a5c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 21 Dec 2020 05:09:34 +0000 Subject: Fix versioned shared library naming so numbering is after SHLIBSUFFIX. Handle the case where the library name and the SONAME match and don't symlink them together --- SCons/Tool/linkCommon/LoadableModule.py | 6 +- SCons/Tool/linkCommon/SharedLibrary.py | 122 +++++++++++++++++++------------- 2 files changed, 77 insertions(+), 51 deletions(-) diff --git a/SCons/Tool/linkCommon/LoadableModule.py b/SCons/Tool/linkCommon/LoadableModule.py index 36921f6..6d893e6 100644 --- a/SCons/Tool/linkCommon/LoadableModule.py +++ b/SCons/Tool/linkCommon/LoadableModule.py @@ -46,7 +46,7 @@ def _ldmodule_soname(target, source, env, for_signature): if 'SONAME' in env: return '$SONAME' else: - return "$LDMODULEPREFIX$_get_ldmodule_stem$_LDMODULESOVERSION${LDMODULESUFFIX}" + return "$LDMODULEPREFIX$_get_ldmodule_stem${LDMODULESUFFIX}$_LDMODULESOVERSION" def setup_loadable_module_logic(env): @@ -71,11 +71,11 @@ def setup_loadable_module_logic(env): # This is the non versioned LDMODULE filename # If LDMODULEVERSION is defined then this will symlink to $LDMODULENAME - env['LDMODULE_NOVERSION_SYMLINK'] = '${LDMODULEPREFIX}$_get_ldmodule_stem${LDMODULESUFFIX}' + env['LDMODULE_NOVERSION_SYMLINK'] = '$_get_shlib_dir${LDMODULEPREFIX}$_get_ldmodule_stem${LDMODULESUFFIX}' # This is the sonamed file name # If LDMODULEVERSION is defined then this will symlink to $LDMODULENAME - env['LDMODULE_SONAME_SYMLINK'] = '$_LDMODULESONAME' + env['LDMODULE_SONAME_SYMLINK'] = '$_get_shlib_dir$_LDMODULESONAME' env['_LDMODULEVERSION'] = "${LDMODULEVERSION and '.'+LDMODULEVERSION or ''}" env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' diff --git a/SCons/Tool/linkCommon/SharedLibrary.py b/SCons/Tool/linkCommon/SharedLibrary.py index bddcb42..9214939 100644 --- a/SCons/Tool/linkCommon/SharedLibrary.py +++ b/SCons/Tool/linkCommon/SharedLibrary.py @@ -7,36 +7,51 @@ from . import lib_emitter, EmitLibSymlinks, StringizeLibSymlinks def shlib_symlink_emitter(target, source, env, **kw): verbose = False - if 'variable_prefix' in kw: - var_prefix = kw['variable_prefix'] + if "variable_prefix" in kw: + var_prefix = kw["variable_prefix"] else: - var_prefix = 'SHLIB' + var_prefix = "SHLIB" - do_symlinks = env.subst('$%sNOVERSIONSYMLINKS' % var_prefix) - if do_symlinks in ['1', 'True', 'true', True]: + do_symlinks = env.subst("$%sNOVERSIONSYMLINKS" % var_prefix) + if do_symlinks in ["1", "True", "true", True]: return target, source - shlibversion = env.subst('$%sVERSION' % var_prefix) + shlibversion = env.subst("$%sVERSION" % var_prefix) if shlibversion: if verbose: print("shlib_symlink_emitter: %sVERSION=%s" % (var_prefix, shlibversion)) libnode = target[0] - shlib_soname_symlink = env.subst('$%s_SONAME_SYMLINK' % var_prefix, target=target, source=source) - shlib_noversion_symlink = env.subst('$%s_NOVERSION_SYMLINK' % var_prefix, target=target, source=source) + shlib_soname_symlink = env.subst( + "$%s_SONAME_SYMLINK" % var_prefix, target=target, source=source + ) + shlib_noversion_symlink = env.subst( + "$%s_NOVERSION_SYMLINK" % var_prefix, target=target, source=source + ) if verbose: print("shlib_soname_symlink :%s" % shlib_soname_symlink) print("shlib_noversion_symlink :%s" % shlib_noversion_symlink) print("libnode :%s" % libnode) - symlinks = [(env.File(shlib_soname_symlink), libnode), - (env.File(shlib_noversion_symlink), libnode)] + shlib_soname_symlink = env.File(shlib_soname_symlink) + shlib_noversion_symlink = env.File(shlib_noversion_symlink) + + symlinks = [] + if shlib_soname_symlink != libnode: + # If soname and library name machine, don't symlink them together + symlinks.append((env.File(shlib_soname_symlink), libnode)) + + symlinks.append((env.File(shlib_noversion_symlink), libnode)) if verbose: - print("_lib_emitter: symlinks={!r}".format( - ', '.join(["%r->%r" % (k, v) for k, v in StringizeLibSymlinks(symlinks)]) - )) + print( + "_lib_emitter: symlinks={!r}".format( + ", ".join( + ["%r->%r" % (k, v) for k, v in StringizeLibSymlinks(symlinks)] + ) + ) + ) if symlinks: # This does the actual symlinking @@ -52,25 +67,28 @@ def shlib_symlink_emitter(target, source, env, **kw): def _soversion(target, source, env, for_signature): """Function to determine what to use for SOVERSION""" - if 'SOVERSION' in env: - return '.$SOVERSION' - elif 'SHLIBVERSION' in env: - shlibversion = env.subst('$SHLIBVERSION') + if "SOVERSION" in env: + return ".$SOVERSION" + elif "SHLIBVERSION" in env: + shlibversion = env.subst("$SHLIBVERSION") # We use only the most significant digit of SHLIBVERSION - return '.' + shlibversion.split('.')[0] + return "." + shlibversion.split(".")[0] else: - return '' + return "" def _soname(target, source, env, for_signature): - if 'SONAME' in env: + if "SONAME" in env: # Now verify that SOVERSION is not also set as that is not allowed - if 'SOVERSION' in env: - raise UserError('Ambiguous library .so naming, both SONAME: %s and SOVERSION: %s are defined. ' - 'Only one can be defined for a target library.' % (env['SONAME'], env['SOVERSION'])) - return '$SONAME' + if "SOVERSION" in env: + raise UserError( + "Ambiguous library .so naming, both SONAME: %s and SOVERSION: %s are defined. " + "Only one can be defined for a target library." + % (env["SONAME"], env["SOVERSION"]) + ) + return "$SONAME" else: - return "$_get_shlib_dir$SHLIBPREFIX$_get_shlib_stem$_SHLIBSOVERSION${SHLIBSUFFIX}" + return "$SHLIBPREFIX$_get_shlib_stem${SHLIBSUFFIX}$_SHLIBSOVERSION" def _get_shlib_stem(target, source, env, for_signature): @@ -82,20 +100,23 @@ def _get_shlib_stem(target, source, env, for_signature): :param for_signature: :return: """ - verbose = False + verbose = True target_name = str(target.name) - shlibprefix = env.subst('$SHLIBPREFIX') + shlibprefix = env.subst("$SHLIBPREFIX") shlibsuffix = env.subst("$_SHLIBSUFFIX") if verbose and not for_signature: - print("_get_shlib_stem: target_name:%s shlibprefix:%s shlibsuffix:%s" % (target_name, shlibprefix, shlibsuffix)) + print( + "_get_shlib_stem: target_name:%s shlibprefix:%s shlibsuffix:%s" + % (target_name, shlibprefix, shlibsuffix) + ) if target_name.startswith(shlibprefix): - target_name = target_name[len(shlibprefix):] + target_name = target_name[len(shlibprefix) :] if target_name.endswith(shlibsuffix): - target_name = target_name[:-len(shlibsuffix)] + target_name = target_name[: -len(shlibsuffix)] if verbose and not for_signature: print("_get_shlib_stem: target_name:%s AFTER" % (target_name,)) @@ -107,7 +128,8 @@ def _get_shlib_dir(target, source, env, for_signature): """ Get the directory the shlib is in. """ - if target.dir: + if target.dir and str(target.dir) != ".": + print("target.dir:%s" % target.dir) return "%s/" % str(target.dir) else: return "" @@ -121,33 +143,37 @@ def setup_shared_lib_logic(env): """ createSharedLibBuilder(env) - env['_get_shlib_stem'] = _get_shlib_stem - env['_get_shlib_dir'] = _get_shlib_dir - env['_SHLIBSOVERSION'] = _soversion - env['_SHLIBSONAME'] = _soname + env["_get_shlib_stem"] = _get_shlib_stem + env["_get_shlib_dir"] = _get_shlib_dir + env["_SHLIBSOVERSION"] = _soversion + env["_SHLIBSONAME"] = _soname - env['SHLIBNAME'] = '${_get_shlib_dir}${SHLIBPREFIX}$_get_shlib_stem${_SHLIBSUFFIX}' + env["SHLIBNAME"] = "${_get_shlib_dir}${SHLIBPREFIX}$_get_shlib_stem${_SHLIBSUFFIX}" # This is the non versioned shlib filename # If SHLIBVERSION is defined then this will symlink to $SHLIBNAME - env['SHLIB_NOVERSION_SYMLINK'] = '${_get_shlib_dir}${SHLIBPREFIX}$_get_shlib_stem${SHLIBSUFFIX}' + env[ + "SHLIB_NOVERSION_SYMLINK" + ] = "${_get_shlib_dir}${SHLIBPREFIX}$_get_shlib_stem${SHLIBSUFFIX}" # This is the sonamed file name # If SHLIBVERSION is defined then this will symlink to $SHLIBNAME - env['SHLIB_SONAME_SYMLINK'] = '$_SHLIBSONAME' + env["SHLIB_SONAME_SYMLINK"] = "${_get_shlib_dir}$_SHLIBSONAME" # Note this is gnu style - env['SHLIBSONAMEFLAGS'] = '-Wl,-soname=$_SHLIBSONAME' - env['_SHLIBVERSION'] = "${SHLIBVERSION and '.'+SHLIBVERSION or ''}" - env['_SHLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' + env["SHLIBSONAMEFLAGS"] = "-Wl,-soname=$_SHLIBSONAME" + env["_SHLIBVERSION"] = "${SHLIBVERSION and '.'+SHLIBVERSION or ''}" + env["_SHLIBVERSIONFLAGS"] = "$SHLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME" - env['SHLIBEMITTER'] = [lib_emitter, shlib_symlink_emitter] + env["SHLIBEMITTER"] = [lib_emitter, shlib_symlink_emitter] - env['SHLIBPREFIX'] = 'lib' - env['_SHLIBSUFFIX'] = '${SHLIBSUFFIX}${_SHLIBVERSION}' + env["SHLIBPREFIX"] = "lib" + env["_SHLIBSUFFIX"] = "${SHLIBSUFFIX}${_SHLIBVERSION}" - env['SHLINKFLAGS'] = CLVar('$LINKFLAGS -shared') + env["SHLINKFLAGS"] = CLVar("$LINKFLAGS -shared") - env['SHLINKCOM'] = '$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS' - env['SHLINKCOMSTR'] = '$SHLINKCOM' - env['SHLINK'] = '$LINK' + env[ + "SHLINKCOM" + ] = "$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS" + env["SHLINKCOMSTR"] = "$SHLINKCOM" + env["SHLINK"] = "$LINK" -- cgit v0.12 From a49035b16ff50a01906ea9e763b5ec0bbe3b9815 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 21 Dec 2020 08:23:13 -0700 Subject: [PR #3844] change a spelling per review comment [ci skip] Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index df38788..9272484 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -104,9 +104,9 @@ by determining which component pieces must be built or rebuilt and invoking the necessary commands to build them. &SCons; offers many features to improve developer productivity -such as parallel builds, caching of build artefacts, and -a database of information about previous builds so details do -not have to be recalculated each run. +such as parallel builds, caching of build artifacts, +and a database of information about previous builds so +details do not have to be recalculated each run. You set up an &SCons; -- cgit v0.12 From b8b2787d609935c191f444192fb3d6ad966fadb6 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 21 Dec 2020 19:30:21 +0000 Subject: Fix typo in gdc. Swap out subst logic with python function to calculate .LDMODULEVERSION vs '' --- SCons/Tool/gdc.py | 1 - SCons/Tool/linkCommon/LoadableModule.py | 15 +++++++++++++-- SCons/Tool/mingw.py | 24 +++++++++++------------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/SCons/Tool/gdc.py b/SCons/Tool/gdc.py index 0341fef..09b6d26 100644 --- a/SCons/Tool/gdc.py +++ b/SCons/Tool/gdc.py @@ -116,7 +116,6 @@ def generate(env): # Support for versioned libraries env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' -' # TODO: Fix with new versioned shared lib logic # env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' diff --git a/SCons/Tool/linkCommon/LoadableModule.py b/SCons/Tool/linkCommon/LoadableModule.py index 6d893e6..e9c31dc 100644 --- a/SCons/Tool/linkCommon/LoadableModule.py +++ b/SCons/Tool/linkCommon/LoadableModule.py @@ -48,6 +48,16 @@ def _ldmodule_soname(target, source, env, for_signature): else: return "$LDMODULEPREFIX$_get_ldmodule_stem${LDMODULESUFFIX}$_LDMODULESOVERSION" +def _LDMODULEVERSION(target, source, env, for_signature): + """ + Return "." + version if it's set, otherwise just a blank + """ + value = env.subst('$LDMODULEVERSION', target=target, source=source) + # print("_has_LDMODULEVERSION:%s"%value) + if value: + return "."+value + else: + return "" def setup_loadable_module_logic(env): """ @@ -77,13 +87,14 @@ def setup_loadable_module_logic(env): # If LDMODULEVERSION is defined then this will symlink to $LDMODULENAME env['LDMODULE_SONAME_SYMLINK'] = '$_get_shlib_dir$_LDMODULESONAME' - env['_LDMODULEVERSION'] = "${LDMODULEVERSION and '.'+LDMODULEVERSION or ''}" + env['_LDMODULEVERSION'] = _LDMODULEVERSION + env['_LDMODULEVERSIONFLAGS'] = '$LDMODULEVERSIONFLAGS -Wl,-soname=$_LDMODULESONAME' env['LDMODULEEMITTER'] = [lib_emitter, ldmod_symlink_emitter] env['LDMODULEPREFIX'] = '$SHLIBPREFIX' - env['_LDMODULESUFFIX'] = '${_LDMODULEVERSION}${LDMODULESUFFIX}' + env['_LDMODULESUFFIX'] = '${LDMODULESUFFIX}${_LDMODULEVERSION}' env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' env['LDMODULE'] = '$SHLINK' diff --git a/SCons/Tool/mingw.py b/SCons/Tool/mingw.py index d6a27ae..5e2b82f 100644 --- a/SCons/Tool/mingw.py +++ b/SCons/Tool/mingw.py @@ -1,15 +1,6 @@ -"""SCons.Tool.gcc - -Tool-specific initialization for MinGW (http://www.mingw.org/) - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - +# MIT License # -# __COPYRIGHT__ +# 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 @@ -29,9 +20,16 @@ selection method. # 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__" +"""SCons.Tool.gcc + +Tool-specific initialization for MinGW (http://www.mingw.org/) + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" import os import os.path -- cgit v0.12 From 99f4cad4cc96fa9f3c686d0ef8c28247eb36a5ee Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 20 Dec 2020 16:12:51 -0700 Subject: Adjust CompilationDatase documentation [skip appveyor] Try to be a bit more descriptive about compilation databases. Two of the User Guide examples now use the scons_examples style to show a little more what happens. Fixes #3845. Signed-off-by: Mats Wichmann --- SCons/Tool/compilation_db.xml | 75 +++++++++++------ doc/generated/examples/external_cdb_ex1_1.xml | 5 ++ doc/generated/examples/external_cdb_ex2_1.xml | 3 + doc/user/external.xml | 117 +++++++++++++++++++++----- 4 files changed, 157 insertions(+), 43 deletions(-) create mode 100644 doc/generated/examples/external_cdb_ex1_1.xml create mode 100644 doc/generated/examples/external_cdb_ex2_1.xml diff --git a/SCons/Tool/compilation_db.xml b/SCons/Tool/compilation_db.xml index 40a104e..aac1ed2 100644 --- a/SCons/Tool/compilation_db.xml +++ b/SCons/Tool/compilation_db.xml @@ -31,12 +31,12 @@ See its __doc__ string for a discussion of the format. COMPILATIONDB_COMSTR - +--> COMPILATIONDB_USE_ABSPATH COMPILATIONDB_PATH_FILTER @@ -45,30 +45,55 @@ See its __doc__ string for a discussion of the format. - The &b-CompilationDatabase; builder writes a JSON formatted compilation - database according to the - LLVM specification - which is consumed by a number of clang tools, editors, and other tools. - - - If you don't specify any files, the builder will default to compile_commands.json. + &b-CompilationDatabase; is a special builder which + adds a target to create a JSON formatted + compilation database compatible with + clang tooling + (see the + LLVM specification). + This database is suitable for consumption by various + tools and editors who can use it to obtain build and + dependency information which otherwise would be + internal to &SCons;. + The builder does not require any source files to be specified, + rather it arranges to emit information about all + of the C, C++ and assembler source/output pairs + identified in the build that are not excluded by the + optional filter &cv-link-COMPILATIONDB_PATH_FILTER;. + The target is subject to the usual &SCons; target + selection rules. - If you specify a single file as below - -env.CompilationDatabase('my_output.json') - - SCons will automatically use that as the target file. - If you specify more than one source, the source list will be ignored. + If called with no arguments, + the builder will default to a target name of + compile_commands.json. - You should not specify source files. The &b-CompilationDatabase; builder instruments SCons to collect them from all - the C, C++, assembly source/output pairs. + If called with a single positional argument, + &scons; will "deduce" the target name from that source + argument, giving it the same name, and then + ignore the source. + This is the usual way to call the builder if a + non-default target name is wanted. - NOTE: You must load the &t-compilation_db; tool prior to specifying any part of your build or some source/output - files will not show up in your output file. + If called with either the target= + or source= keyword arguments, + the value of the argument is taken as the target name. + If called with both, the target= + value is used and source= is ignored. + If called with multiple sources, + the source list will be ignored, + since there is no way to deduce what the intent was; + in this case the default target name will be used. + + + You must load the &t-compilation_db; tool prior to specifying + any part of your build or some source/output + files will not show up in the compilation database. + + Available since &scons; 4.0. @@ -78,7 +103,8 @@ env.CompilationDatabase('my_output.json') - The string displayed when CompilationDatabase builder's action is run. + The string displayed when the &b-CompilationDatabase; + builder's action is run. @@ -86,9 +112,10 @@ env.CompilationDatabase('my_output.json') - This is a boolean flag to instruct &b-link-CompilationDatabase; to - write the file and output members - in the compilation database with absolute or relative paths. + A boolean flag to instruct &b-link-CompilationDatabase; + whether to write the file and + output members + in the compilation database using absolute or relative paths. The default value is False (use relative paths) @@ -99,7 +126,7 @@ env.CompilationDatabase('my_output.json') - This is a string which instructs &b-link-CompilationDatabase; to + A string which instructs &b-link-CompilationDatabase; to only include entries where the output member matches the pattern in the filter string using fnmatch, which uses glob style wildcards. diff --git a/doc/generated/examples/external_cdb_ex1_1.xml b/doc/generated/examples/external_cdb_ex1_1.xml new file mode 100644 index 0000000..0d26c02 --- /dev/null +++ b/doc/generated/examples/external_cdb_ex1_1.xml @@ -0,0 +1,5 @@ +% scons -Q +Building compilation database compile_commands.json +cc -o hello.o -c hello.c +cc -o hello hello.o + diff --git a/doc/generated/examples/external_cdb_ex2_1.xml b/doc/generated/examples/external_cdb_ex2_1.xml new file mode 100644 index 0000000..25f32d1 --- /dev/null +++ b/doc/generated/examples/external_cdb_ex2_1.xml @@ -0,0 +1,3 @@ +% scons -Q cdb +Building compilation database compile_database.json + diff --git a/doc/user/external.xml b/doc/user/external.xml index 3d55a8c..9900e93 100644 --- a/doc/user/external.xml +++ b/doc/user/external.xml @@ -70,7 +70,7 @@ - Tooling which wants to perform analysis and modification + Tooling to perform analysis and modification of source code often needs to know not only the source code itself, but also how it will be compiled, as the compilation line affects the behavior of macros, includes, etc. &SCons; has a @@ -93,7 +93,7 @@ compilation database in this format by enabling the &t-link-compilation_db; tool and calling the &b-link-CompilationDatabase; builder - (available since 4.0). + (available since &scons; 4.0). @@ -107,12 +107,12 @@ which defaults to False. The entries in this file can be filtered by using - COMPILATIONDB_PATH_FILTER='fnmatch pattern' - where the filter string is a + COMPILATIONDB_PATH_FILTER='pattern' + where the filter pattern is a string following the Python - fnmatch + fnmatch - based pattern which is a typical file glob syntax. + syntax. This filtering can be used for outputting different build variants to different compilation database files. @@ -120,38 +120,104 @@ - Example of absolute paths for output and source: + The following example illustrates generating a compilation + database containing absolute paths: - + + env = Environment(COMPILATIONDB_USE_ABSPATH=True) env.Tool('compilation_db') -env.CompilationDatabase('compile_commands.json') - +env.CompilationDatabase() +env.Program('hello.c') + + +int main( int argc, char* argv[] ) +{ + return 0; +} + + + + + scons -Q + + + compile_commands.json contains: [ { - "command": "gcc -o test_main.o -c test_main.c", + "command": "gcc -o hello.o -c hello.c", "directory": "/home/user/sandbox", - "file": "/home/user/sandbox/test_main.c", - "output": "/home/user/sandbox/test_main.o" + "file": "/home/user/sandbox/hello.c", + "output": "/home/user/sandbox/hello.o" } ] - Example of relative paths for output and source: + Notice that the generated database contains only an entry for + the hello.c/hello.o pairing, + and nothing for the generation of the final executable + hello - the transformation of + hello.o to hello + does not have any information that affects interpretation + of the source code, + so it is not interesting to the compilation database. - + + + Although it can be a little surprising at first glance, + a compilation database target is, like any other target, + subject to &scons; target selection rules. + This means if you set a default target (that does not + include the compilation database), or use command-line + targets, it might not be selected for building. + This can actually be an advantage, since you don't + necessarily want to regenerate the compilation database + every build. + The following example + shows selecting relative paths (the default) + for output and source, + and also giving a non-default name to the database. + In order to be able to generate the database separately from building, + an alias is set referring to the database, + which can then be used as a target - here we are only + building the compilation database target, not the code. + + + + + env = Environment() env.Tool('compilation_db') -env.CompilationDatabase('compile_commands.json') - +cdb = env.CompilationDatabase('compile_database.json') +Alias('cdb', cdb) +env.Program('test_main.c') + + +#include "test_main.h" +int main( int argc, char* argv[] ) +{ + return 0; +} + + +/* dummy include file */ + + + + + scons -Q cdb + + + compile_database.json contains: + [ { @@ -165,7 +231,15 @@ env.CompilationDatabase('compile_commands.json') - Example of using filtering for build variants: + The following (incomplete) example shows using filtering + to separate build variants. + In the case of using variants, + you want different compilation databases for each, + since the build parameters differ, so the code analysis + needs to see the correct build lines for the 32-bit build + and 64-bit build hinted at here. + For simplicity of presentation, + the example omits the setup details of the variant directories: @@ -181,6 +255,9 @@ env2 = env.Clone() env2['COMPILATIONDB_PATH_FILTER'] = 'build/linux64/*' env2.CompilationDatabase('compile_commands-linux64.json') + + compile_commands-linux32.json contains: + [ { @@ -191,6 +268,9 @@ env2.CompilationDatabase('compile_commands-linux64.json') } ] + + compile_commands-linux64.json contains: + [ { @@ -203,5 +283,4 @@ env2.CompilationDatabase('compile_commands-linux64.json') - -- cgit v0.12 From b286f7a7ddc84b93adefd1f01de92c473865f25a Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 25 Dec 2020 16:47:55 -0700 Subject: Create github workflow for scons build/doc Try to enable a github Action workflow Signed-off-by: Mats Wichmann --- .github/workflows/scons-package.yml | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 .github/workflows/scons-package.yml diff --git a/.github/workflows/scons-package.yml b/.github/workflows/scons-package.yml new file mode 100644 index 0000000..fc9ab5d --- /dev/null +++ b/.github/workflows/scons-package.yml @@ -0,0 +1,47 @@ +# This action builds SCons, mainly to make sure the docs generate. + +name: SCons Build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + + runs-on: ubuntu-20.04 + + steps: + - uses: actions/checkout@v2 + - name: Set up Python 3.8 + uses: actions/setup-python@v2 + with: + python-version: 3.8 + - name: Install dependencies + run: | + python -m pip install --upgrade pip setuptools wheel + #python -m pip install flake8 pytest + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + sudo apt-get update + sudo apt-get -y install docbook-xml docbook-xsl xsltproc fop docbook-xsl-doc-pdf + # try to keeo the texlive install as small as we can to save some time/space + sudo apt-get -y --no-install-recommends install texlive biber texmaker ghostscript texlive-latex-base texlive-latex-extra texlive-bibtex-extra texlive-font-utils latexmk + # This is disabled until the run can be configured to only + # check the code that matters, else we fail on non-essentials + # like the bench/ stuff. + #- name: Lint with flake8 + # run: | + # # stop the build if there are Python syntax errors or undefined names + # flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics + # # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide + # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics + - name: Build SCons and docs + run: | + python bin/docs-update-generated.py + python bin/docs-validate.py + python bin/docs-create-example-outputs.py + python scripts/scons.py + ls -l build/dist + python build/scons-local/scons.py --version -- cgit v0.12 From a92b61d69a9066b500df7ff1d24611cc1ed1948b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 26 Dec 2020 17:37:46 -0800 Subject: Allow callers of createSharedLibBuilder() and createLoadableModuleBuilder() to explicitly override the default suffix for the created builder --- SCons/Tool/__init__.py | 16 ++++++++++++---- SCons/Tool/mslink.py | 4 ++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/SCons/Tool/__init__.py b/SCons/Tool/__init__.py index 2b25e3a..63f6a59 100644 --- a/SCons/Tool/__init__.py +++ b/SCons/Tool/__init__.py @@ -332,11 +332,15 @@ def createStaticLibBuilder(env): return static_lib -def createSharedLibBuilder(env): +def createSharedLibBuilder(env, shlib_suffix='$_SHLIBSUFFIX'): """This is a utility function that creates the SharedLibrary Builder in an Environment if it is not there already. If it is already there, we return the existing one. + + Args: + shlib_suffix: The suffix specified for the shared library builder + """ try: @@ -349,7 +353,7 @@ def createSharedLibBuilder(env): shared_lib = SCons.Builder.Builder(action=action_list, emitter="$SHLIBEMITTER", prefix="$SHLIBPREFIX", - suffix="$_SHLIBSUFFIX", + suffix=shlib_suffix, target_scanner=ProgramScanner, src_suffix='$SHOBJSUFFIX', src_builder='SharedObject') @@ -358,11 +362,15 @@ def createSharedLibBuilder(env): return shared_lib -def createLoadableModuleBuilder(env): +def createLoadableModuleBuilder(env, loadable_module_suffix='$_LDMODULESUFFIX'): """This is a utility function that creates the LoadableModule Builder in an Environment if it is not there already. If it is already there, we return the existing one. + + Args: + loadable_module_suffix: The suffix specified for the loadable module builder + """ try: @@ -375,7 +383,7 @@ def createLoadableModuleBuilder(env): ld_module = SCons.Builder.Builder(action=action_list, emitter="$LDMODULEEMITTER", prefix="$LDMODULEPREFIX", - suffix="$_LDMODULESUFFIX", + suffix=loadable_module_suffix, target_scanner=ProgramScanner, src_suffix='$SHOBJSUFFIX', src_builder='SharedObject') diff --git a/SCons/Tool/mslink.py b/SCons/Tool/mslink.py index 8fd7922..795807c 100644 --- a/SCons/Tool/mslink.py +++ b/SCons/Tool/mslink.py @@ -251,7 +251,7 @@ compositeLinkAction = exeLinkAction + embedManifestExeCheckAction def generate(env): """Add Builders and construction variables for ar to an Environment.""" - SCons.Tool.createSharedLibBuilder(env) + SCons.Tool.createSharedLibBuilder(env, shlib_suffix='$SHLIBSUFFIX') SCons.Tool.createProgBuilder(env) env['SHLINK'] = '$LINK' @@ -313,7 +313,7 @@ def generate(env): # are subject to different build parameters (LDMODULE* variables). # Therefore LDMODULE* variables correspond as much as possible to # SHLINK*/SHLIB* ones. - SCons.Tool.createLoadableModuleBuilder(env) + SCons.Tool.createLoadableModuleBuilder(env, loadable_module_suffix='$LDMODULESUFFIX') env['LDMODULE'] = '$SHLINK' env['LDMODULEPREFIX'] = '$SHLIBPREFIX' env['LDMODULESUFFIX'] = '$SHLIBSUFFIX' -- cgit v0.12 From be9faad84daa0ad459e84c676c48b14816c1d247 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 26 Dec 2020 17:41:47 -0800 Subject: Address some comments from the PR regarding formatting, and license text block --- SCons/Tool/FortranCommon.py | 6 ++++-- SCons/Tool/applelink.py | 9 +++------ test/CC/SHCCFLAGS.py | 1 + 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SCons/Tool/FortranCommon.py b/SCons/Tool/FortranCommon.py index f8d9fdc..16b75e2 100644 --- a/SCons/Tool/FortranCommon.py +++ b/SCons/Tool/FortranCommon.py @@ -4,6 +4,9 @@ Stuff for processing Fortran, common to all fortran dialects. """ +# 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 @@ -22,8 +25,7 @@ Stuff for processing Fortran, common to all fortran dialects. # 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. -# +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. import re import os.path diff --git a/SCons/Tool/applelink.py b/SCons/Tool/applelink.py index 6a4a37c..2cdbd50 100644 --- a/SCons/Tool/applelink.py +++ b/SCons/Tool/applelink.py @@ -166,19 +166,16 @@ def generate(env): env['LDMODULEPREFIX'] = '' env['LDMODULESUFFIX'] = '' env['LDMODULEFLAGS'] = CLVar('$LINKFLAGS -bundle') - env[ - 'LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS' \ + env['LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS' \ ' $SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS' # New stuff # env['_SHLIBSUFFIX'] = '${_SHLIBVERSION}${SHLIBSUFFIX}' - env[ - '__SHLIBVERSIONFLAGS'] = '${__lib_either_version_flag(__env__,' \ + env['__SHLIBVERSIONFLAGS'] = '${__lib_either_version_flag(__env__,' \ '"SHLIBVERSION","_APPLELINK_CURRENT_VERSION", "_SHLIBVERSIONFLAGS")}' - env[ - '__LDMODULEVERSIONFLAGS'] = '${__lib_either_version_flag(__env__,' \ + env['__LDMODULEVERSIONFLAGS'] = '${__lib_either_version_flag(__env__,' \ '"LDMODULEVERSION","_APPLELINK_CURRENT_VERSION", "_LDMODULEVERSIONFLAGS")}' diff --git a/test/CC/SHCCFLAGS.py b/test/CC/SHCCFLAGS.py index 0bb349b..71ed1c0 100644 --- a/test/CC/SHCCFLAGS.py +++ b/test/CC/SHCCFLAGS.py @@ -40,6 +40,7 @@ if sys.platform.find('irix') > -1: os.environ['LD_LIBRARYN32_PATH'] = '.' test.write('SConstruct', """ +DefaultEnvironment(tools=[]) foo = Environment(SHCCFLAGS = '%s', WINDOWS_INSERT_DEF=1) bar = Environment(SHCCFLAGS = '%s', WINDOWS_INSERT_DEF=1) -- cgit v0.12 From a251629aa5e103f357f7d13b2920cbce59853d3f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 26 Dec 2020 21:05:25 -0800 Subject: Fix mingw to reset _SHLIBSUFFIX to --- SCons/Tool/mingw.py | 3 +++ test/MinGW/MinGWSharedLibrary.py | 1 + 2 files changed, 4 insertions(+) diff --git a/SCons/Tool/mingw.py b/SCons/Tool/mingw.py index 5e2b82f..b8337db 100644 --- a/SCons/Tool/mingw.py +++ b/SCons/Tool/mingw.py @@ -187,6 +187,9 @@ def generate(env): env['LIBSUFFIX'] = '.a' env['PROGSUFFIX'] = '.exe' + # Handle new versioned shared library logic + env['_SHLIBSUFFIX'] = '$SHLIBSUFFIX' + def exists(env): mingw = SCons.Tool.find_program_path(env, key_program, default_paths=mingw_paths) diff --git a/test/MinGW/MinGWSharedLibrary.py b/test/MinGW/MinGWSharedLibrary.py index 86ddd43..badfcb9 100644 --- a/test/MinGW/MinGWSharedLibrary.py +++ b/test/MinGW/MinGWSharedLibrary.py @@ -56,6 +56,7 @@ int abc(int a) { """) test.write('SConstruct', """ +DefaultEnvironment(tools=[]) env = Environment(tools=['mingw','link','g++']) #env.Tool('mingw') env.SharedLibrary('foobar', 'foobar.cc') -- cgit v0.12 From 91e60397c7792d33b2df9f39608aec51d383d118 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 27 Dec 2020 21:17:46 -0800 Subject: Fix test\win32\mingw.py. Note still need to track down why _LIBDIRFLAGS is evaluating to $( $) in the new code, but not in master --- SCons/Tool/clang.py | 25 ++++++++++++------------- SCons/Tool/gcc.py | 24 +++++++++++------------- SCons/Tool/gnulink.py | 18 ++++++++---------- SCons/Tool/linkCommon/SharedLibrary.py | 10 +++------- SCons/Tool/mingw.py | 9 +++++++++ test/Clang/clang_shared_library.py | 6 +++--- test/MinGW/MinGWSharedLibrary.py | 7 +++---- test/Win32/mingw.py | 16 +++++++++------- 8 files changed, 58 insertions(+), 57 deletions(-) diff --git a/SCons/Tool/clang.py b/SCons/Tool/clang.py index e39c742..e033cfa 100644 --- a/SCons/Tool/clang.py +++ b/SCons/Tool/clang.py @@ -1,17 +1,8 @@ # -*- coding: utf-8; -*- - -"""SCons.Tool.clang - -Tool-specific initialization for clang. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - # -# __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 @@ -32,8 +23,16 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +"""SCons.Tool.clang + +Tool-specific initialization for clang. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" -# __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" # Based on SCons/Tool/gcc.py by PaweÅ‚ Tomulik 2014 as a separate tool. # Brought into the SCons mainline by Russel Winder 2017. diff --git a/SCons/Tool/gcc.py b/SCons/Tool/gcc.py index 37626ef..6470002 100644 --- a/SCons/Tool/gcc.py +++ b/SCons/Tool/gcc.py @@ -1,15 +1,6 @@ -"""SCons.Tool.gcc - -Tool-specific initialization for gcc. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - +# MIT License # -# __COPYRIGHT__ +# 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 @@ -29,9 +20,16 @@ selection method. # 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__" +"""SCons.Tool.gcc + +Tool-specific initialization for gcc. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" from . import cc import re diff --git a/SCons/Tool/gnulink.py b/SCons/Tool/gnulink.py index fb5acd0..e8b668f 100644 --- a/SCons/Tool/gnulink.py +++ b/SCons/Tool/gnulink.py @@ -1,13 +1,3 @@ -"""SCons.Tool.gnulink - -Tool-specific initialization for the gnu linker. - -There normally shouldn't be any need to import this module directly. -It will usually be imported through the generic SCons.Tool.Tool() -selection method. - -""" - # # MIT License # @@ -32,7 +22,15 @@ selection method. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +"""SCons.Tool.gnulink +Tool-specific initialization for the gnu linker. + +There normally shouldn't be any need to import this module directly. +It will usually be imported through the generic SCons.Tool.Tool() +selection method. + +""" import SCons.Tool.linkCommon import SCons.Util diff --git a/SCons/Tool/linkCommon/SharedLibrary.py b/SCons/Tool/linkCommon/SharedLibrary.py index 9214939..38f0c61 100644 --- a/SCons/Tool/linkCommon/SharedLibrary.py +++ b/SCons/Tool/linkCommon/SharedLibrary.py @@ -41,7 +41,7 @@ def shlib_symlink_emitter(target, source, env, **kw): if shlib_soname_symlink != libnode: # If soname and library name machine, don't symlink them together symlinks.append((env.File(shlib_soname_symlink), libnode)) - + symlinks.append((env.File(shlib_noversion_symlink), libnode)) if verbose: @@ -152,9 +152,7 @@ def setup_shared_lib_logic(env): # This is the non versioned shlib filename # If SHLIBVERSION is defined then this will symlink to $SHLIBNAME - env[ - "SHLIB_NOVERSION_SYMLINK" - ] = "${_get_shlib_dir}${SHLIBPREFIX}$_get_shlib_stem${SHLIBSUFFIX}" + env["SHLIB_NOVERSION_SYMLINK"] = "${_get_shlib_dir}${SHLIBPREFIX}$_get_shlib_stem${SHLIBSUFFIX}" # This is the sonamed file name # If SHLIBVERSION is defined then this will symlink to $SHLIBNAME @@ -172,8 +170,6 @@ def setup_shared_lib_logic(env): env["SHLINKFLAGS"] = CLVar("$LINKFLAGS -shared") - env[ - "SHLINKCOM" - ] = "$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS" + env["SHLINKCOM"] = "$SHLINK -o $TARGET $SHLINKFLAGS $__SHLIBVERSIONFLAGS $__RPATH $SOURCES $_LIBDIRFLAGS $_LIBFLAGS" env["SHLINKCOMSTR"] = "$SHLINKCOM" env["SHLINK"] = "$LINK" diff --git a/SCons/Tool/mingw.py b/SCons/Tool/mingw.py index b8337db..f72c64d 100644 --- a/SCons/Tool/mingw.py +++ b/SCons/Tool/mingw.py @@ -48,6 +48,7 @@ mingw_paths = [ r'C:\msys64\mingw64\bin', r'C:\cygwin\bin', r'C:\msys', + r'C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin' ] @@ -141,6 +142,11 @@ def generate(env): mingw = SCons.Tool.find_program_path(env, key_program, default_paths=mingw_paths) if mingw: mingw_bin_dir = os.path.dirname(mingw) + + # Adjust path if we found it in a chocolatey install + if mingw_bin_dir == r'C:\ProgramData\chocolatey\bin': + mingw_bin_dir = r'C:\ProgramData\chocolatey\lib\mingw\tools\install\mingw64\bin' + env.AppendENVPath('PATH', mingw_bin_dir) # Most of mingw is the same as gcc and friends... @@ -161,6 +167,7 @@ def generate(env): env['SHCXXFLAGS'] = SCons.Util.CLVar('$CXXFLAGS') env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -shared') env['SHLINKCOM'] = shlib_action + env['SHLINKCOMSTR'] = shlib_generator env['LDMODULECOM'] = ldmodule_action env.Append(SHLIBEMITTER=[shlib_emitter]) env.Append(LDMODULEEMITTER=[shlib_emitter]) @@ -189,6 +196,8 @@ def generate(env): # Handle new versioned shared library logic env['_SHLIBSUFFIX'] = '$SHLIBSUFFIX' + env["SHLIBPREFIX"] = "" + def exists(env): diff --git a/test/Clang/clang_shared_library.py b/test/Clang/clang_shared_library.py index 83fa4dd..4f3e50d 100644 --- a/test/Clang/clang_shared_library.py +++ b/test/Clang/clang_shared_library.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 @@ -22,8 +24,6 @@ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import TestSCons from SCons.Environment import Base diff --git a/test/MinGW/MinGWSharedLibrary.py b/test/MinGW/MinGWSharedLibrary.py index badfcb9..f563909 100644 --- a/test/MinGW/MinGWSharedLibrary.py +++ b/test/MinGW/MinGWSharedLibrary.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__" """ Test the ability to configure the $RCCOM construction variable diff --git a/test/Win32/mingw.py b/test/Win32/mingw.py index ca31f6b..c45b7c6 100644 --- a/test/Win32/mingw.py +++ b/test/Win32/mingw.py @@ -1,10 +1,7 @@ -""" -This tests the MinGW C/C++ compiler support. -""" - #!/usr/bin/env python +# MIT License # -# __COPYRIGHT__ +# 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 @@ -24,9 +21,10 @@ This tests the MinGW C/C++ compiler support. # 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. -# +""" +This tests the MinGW C/C++ compiler support. +""" -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import sys @@ -45,6 +43,9 @@ if sys.platform != 'win32': test.write('SConstruct',""" from SCons.Tool.mingw import exists import sys + +DefaultEnvironment(tools=[]) + env = Environment() if exists(env): print('mingw exists') @@ -59,6 +60,7 @@ test.subdir('header') # Do the actual testing: test.write('SConstruct',""" +DefaultEnvironment(tools=[]) env=Environment(tools=['mingw']) assert env['CC'] == 'gcc' env.StaticLibrary('static', 'static.cpp') -- cgit v0.12 From 4e7d63db7ec28c0bf2e384ec8d26107bdf8be0c5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 27 Dec 2020 22:02:32 -0800 Subject: Fix link to not overwrite already set SHLIBPREFIX. This prevents mingw from having shared libraries prefixed with LIB --- SCons/Tool/MSCommon/vc.py | 9 +++++---- SCons/Tool/linkCommon/SharedLibrary.py | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/SCons/Tool/MSCommon/vc.py b/SCons/Tool/MSCommon/vc.py index e50277d..87a1064 100644 --- a/SCons/Tool/MSCommon/vc.py +++ b/SCons/Tool/MSCommon/vc.py @@ -1,5 +1,7 @@ # -# __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,6 +22,7 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # +"""Module for Visual C/C++ detection and configuration. # TODO: # * gather all the information from a single vswhere call instead @@ -33,10 +36,8 @@ # * test on 64 bits XP + VS 2005 (and VS 6 if possible) # * SDK # * Assembly -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - -__doc__ = """Module for Visual C/C++ detection and configuration. """ + import SCons.compat import SCons.Util diff --git a/SCons/Tool/linkCommon/SharedLibrary.py b/SCons/Tool/linkCommon/SharedLibrary.py index 38f0c61..1e98499 100644 --- a/SCons/Tool/linkCommon/SharedLibrary.py +++ b/SCons/Tool/linkCommon/SharedLibrary.py @@ -165,7 +165,8 @@ def setup_shared_lib_logic(env): env["SHLIBEMITTER"] = [lib_emitter, shlib_symlink_emitter] - env["SHLIBPREFIX"] = "lib" + # If it's already set, then don't overwrite. + env["SHLIBPREFIX"] = env.get('SHLIBPREFIX',"lib") env["_SHLIBSUFFIX"] = "${SHLIBSUFFIX}${_SHLIBVERSION}" env["SHLINKFLAGS"] = CLVar("$LINKFLAGS -shared") -- cgit v0.12 From 04340876d205824bc3e53b56ff6e98f77ed5783d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sun, 3 Jan 2021 17:24:07 -0800 Subject: Fix comment and move import to top of file --- SCons/Defaults.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCons/Defaults.py b/SCons/Defaults.py index 2bacc10..ab8a825 100644 --- a/SCons/Defaults.py +++ b/SCons/Defaults.py @@ -45,6 +45,7 @@ import SCons.Environment import SCons.PathList import SCons.Subst import SCons.Tool +import SCons.Scanner.Dir # A placeholder for a default Environment (for fetching source files # from source code management systems and the like). This must be @@ -134,7 +135,6 @@ ProgScan = SCons.Tool.ProgramScanner # These aren't really tool scanners, so they don't quite belong with # the rest of those in Tool/__init__.py, but I'm not sure where else # they should go. Leave them here for now. -import SCons.Scanner.Dir DirScanner = SCons.Scanner.Dir.DirScanner() DirEntryScanner = SCons.Scanner.Dir.DirEntryScanner() @@ -575,7 +575,7 @@ class Variable_Method_Caller: def __libversionflags(env, version_var, flags_var): """ - if $version_var is not empty, returns env[flags_var], otherwise returns None + if version_var is not empty, returns env[flags_var], otherwise returns None :param env: :param version_var: :param flags_var: -- cgit v0.12 From 2d1bebd6f093bef2bae4d89d2063724a4ca3e102 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 1 Jan 2021 15:32:58 -0700 Subject: Fix awkward consvar code from ancient Python The Append* and Prepend* environment methods which add to existing construction variables had some deeply nested try blocks because according to the comments, Python 1.5.2 would not allow a continue statement inside a try block. This has now been aligned to more modern usage for better readability. Signed-off-by: Mats Wichmann --- CHANGES.txt | 3 +- SCons/Environment.py | 248 ++++++++++++++++++++++++--------------------------- 2 files changed, 121 insertions(+), 130 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 611023e..0604514 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -99,7 +99,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fix cut-n-paste error in msvc debug printout and make some debug output in msvs and msvsTests.py be off until needed (uncomment to use) - Fix Issue #3014 - Empty file and missing file have same csig - + - Refactor env.Append/Prepend to remove Py 1.5 era need to nest + try blocks, can now "continue" at the appropriate places. diff --git a/SCons/Environment.py b/SCons/Environment.py index 4ebd515..2b9b294 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -407,9 +407,8 @@ class SubstitutionEnvironment: # key and we don't need to check. If we do check, using a # global, pre-compiled regular expression directly is more # efficient than calling another function or a method. - if key not in self._dict \ - and not _is_valid_var.match(key): - raise UserError("Illegal construction variable `%s'" % key) + if key not in self._dict and not _is_valid_var.match(key): + raise UserError("Illegal construction variable `%s'" % key) self._dict[key] = value def get(self, key, default=None): @@ -635,7 +634,7 @@ class SubstitutionEnvironment: Parse ``flags`` and return a dict with the flags distributed into the appropriate construction variable names. The flags are treated as a typical set of command-line flags for a GNU-like toolchain, - such as might have been generated by one of the \*-config scripts, + such as might have been generated by one of the {foo}-config scripts, and used to populate the entries based on knowledge embedded in this method - the choices are not expected to be portable to other toolchains. @@ -1173,92 +1172,85 @@ class Base(SubstitutionEnvironment): ####################################################################### def Append(self, **kw): - """Append values to existing construction variables in an Environment.""" + """Append values to construction variables in an Environment. + + The variable is created if it is not already present. + """ + kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): - # It would be easier on the eyes to write this using - # "continue" statements whenever we finish processing an item, - # but Python 1.5.2 apparently doesn't let you use "continue" - # within try:-except: blocks, so we have to nest our code. try: if key == 'CPPDEFINES' and is_String(self._dict[key]): self._dict[key] = [self._dict[key]] orig = self._dict[key] except KeyError: - # No existing variable in the environment, so just set - # it to the new value. + # No existing var in the environment, so set to the new value. if key == 'CPPDEFINES' and is_String(val): self._dict[key] = [val] else: self._dict[key] = val - else: + continue + + try: + # Check if the original looks like a dict: has .update? + update_dict = orig.update + except AttributeError: try: - # Check if the original looks like a dictionary. - # If it is, we can't just try adding the value because - # dictionaries don't have __add__() methods, and - # things like UserList will incorrectly coerce the - # original dict to a list (which we don't want). - update_dict = orig.update - except AttributeError: + # Just try to add them together. This will work + # in most cases, when the original and new values + # are compatible types. + self._dict[key] = orig + val + except (KeyError, TypeError): try: - # Most straightforward: just try to add them - # together. This will work in most cases, when the - # original and new values are of compatible types. - self._dict[key] = orig + val - except (KeyError, TypeError): - try: - # Check if the original is a list. - add_to_orig = orig.append - except AttributeError: - # The original isn't a list, but the new - # value is (by process of elimination), - # so insert the original in the new value - # (if there's one to insert) and replace - # the variable with it. - if orig: - val.insert(0, orig) - self._dict[key] = val + # Check if the original is a list: has .append? + add_to_orig = orig.append + except AttributeError: + # The original isn't a list, but the new + # value is (by process of elimination), + # so insert the original in the new value + # (if there's one to insert) and replace + # the variable with it. + if orig: + val.insert(0, orig) + self._dict[key] = val + else: + # The original is a list, so append the new + # value to it (if there's a value to append). + if val: + add_to_orig(val) + continue + + # The original looks like a dictionary, so update it + # based on what we think the value looks like. + # We can't just try adding the value because + # dictionaries don't have __add__() methods, and + # things like UserList will incorrectly coerce the + # original dict to a list (which we don't want). + if is_List(val): + if key == 'CPPDEFINES': + tmp = [] + for (k, v) in orig.items(): + if v is not None: + tmp.append((k, v)) else: - # The original is a list, so append the new - # value to it (if there's a value to append). - if val: - add_to_orig(val) + tmp.append((k,)) + orig = tmp + orig += val + self._dict[key] = orig else: - # The original looks like a dictionary, so update it - # based on what we think the value looks like. - if is_List(val): - if key == 'CPPDEFINES': - tmp = [] - for (k, v) in orig.items(): - if v is not None: - tmp.append((k, v)) - else: - tmp.append((k,)) - orig = tmp - orig += val - self._dict[key] = orig - else: - for v in val: - orig[v] = None + for v in val: + orig[v] = None + else: + try: + update_dict(val) + except (AttributeError, TypeError, ValueError): + if is_Dict(val): + for k, v in val.items(): + orig[k] = v else: - try: - update_dict(val) - except (AttributeError, TypeError, ValueError): - if is_Dict(val): - for k, v in val.items(): - orig[k] = v - else: - orig[val] = None - self.scanner_map_delete(kw) + orig[val] = None - # allow Dirs and strings beginning with # for top-relative - # Note this uses the current env's fs (in self). - def _canonicalize(self, path): - if not is_String(path): # typically a Dir - path = str(path) - if path and path[0] == '#': - path = str(self.fs.Dir(path)) - return path + self.scanner_map_delete(kw) def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, delete_existing=0): @@ -1295,8 +1287,7 @@ class Base(SubstitutionEnvironment): val = _delete_duplicates(val, delete_existing) if key not in self._dict or self._dict[key] in ('', None): self._dict[key] = val - elif is_Dict(self._dict[key]) and \ - is_Dict(val): + elif is_Dict(self._dict[key]) and is_Dict(val): self._dict[key].update(val) elif is_List(val): dk = self._dict[key] @@ -1682,68 +1673,68 @@ class Base(SubstitutionEnvironment): return SCons.Platform.Platform(platform)(self) def Prepend(self, **kw): - """Prepend values to existing construction variables - in an Environment. + """Prepend values to construction variables in an Environment. + + The variable is created if it is not already present. """ + kw = copy_non_reserved_keywords(kw) for key, val in kw.items(): - # It would be easier on the eyes to write this using - # "continue" statements whenever we finish processing an item, - # but Python 1.5.2 apparently doesn't let you use "continue" - # within try:-except: blocks, so we have to nest our code. try: orig = self._dict[key] except KeyError: - # No existing variable in the environment, so just set - # it to the new value. + # No existing var in the environment so set to the new value. self._dict[key] = val - else: + continue + + try: + # Check if the original looks like a dict: has .update? + update_dict = orig.update + except AttributeError: try: - # Check if the original looks like a dictionary. - # If it is, we can't just try adding the value because - # dictionaries don't have __add__() methods, and - # things like UserList will incorrectly coerce the - # original dict to a list (which we don't want). - update_dict = orig.update - except AttributeError: + # Just try to add them together. This will work + # in most cases, when the original and new values + # are compatible types. + self._dict[key] = val + orig + except (KeyError, TypeError): try: - # Most straightforward: just try to add them - # together. This will work in most cases, when the - # original and new values are of compatible types. - self._dict[key] = val + orig - except (KeyError, TypeError): - try: - # Check if the added value is a list. - add_to_val = val.append - except AttributeError: - # The added value isn't a list, but the - # original is (by process of elimination), - # so insert the the new value in the original - # (if there's one to insert). - if val: - orig.insert(0, val) - else: - # The added value is a list, so append - # the original to it (if there's a value - # to append). - if orig: - add_to_val(orig) - self._dict[key] = val - else: - # The original looks like a dictionary, so update it - # based on what we think the value looks like. - if is_List(val): - for v in val: - orig[v] = None + # Check if the added value is a list: has .append? + add_to_val = val.append + except AttributeError: + # The added value isn't a list, but the + # original is (by process of elimination), + # so insert the the new value in the original + # (if there's one to insert). + if val: + orig.insert(0, val) else: - try: - update_dict(val) - except (AttributeError, TypeError, ValueError): - if is_Dict(val): - for k, v in val.items(): - orig[k] = v - else: - orig[val] = None + # The added value is a list, so append + # the original to it (if there's a value + # to append) and replace the original. + if orig: + add_to_val(orig) + self._dict[key] = val + continue + + # The original looks like a dictionary, so update it + # based on what we think the value looks like. + # We can't just try adding the value because + # dictionaries don't have __add__() methods, and + # things like UserList will incorrectly coerce the + # original dict to a list (which we don't want). + if is_List(val): + for v in val: + orig[v] = None + else: + try: + update_dict(val) + except (AttributeError, TypeError, ValueError): + if is_Dict(val): + for k, v in val.items(): + orig[k] = v + else: + orig[val] = None + self.scanner_map_delete(kw) def PrependENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, @@ -1782,8 +1773,7 @@ class Base(SubstitutionEnvironment): val = _delete_duplicates(val, not delete_existing) if key not in self._dict or self._dict[key] in ('', None): self._dict[key] = val - elif is_Dict(self._dict[key]) and \ - is_Dict(val): + elif is_Dict(self._dict[key]) and is_Dict(val): self._dict[key].update(val) elif is_List(val): dk = self._dict[key] -- cgit v0.12 From b00cfec0f5d7236bd1d2b4d5a50407152c32a739 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Mon, 4 Jan 2021 12:52:21 -0700 Subject: Add back accidentally removed env._canonicalize() Signed-off-by: Mats Wichmann --- SCons/Environment.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/SCons/Environment.py b/SCons/Environment.py index 2b9b294..5352b6e 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -1252,6 +1252,17 @@ class Base(SubstitutionEnvironment): self.scanner_map_delete(kw) + def _canonicalize(self, path): + """Allow Dirs and strings beginning with # for top-relative. + + Note this uses the current env's fs (in self). + """ + if not is_String(path): # typically a Dir + path = str(path) + if path and path[0] == '#': + path = str(self.fs.Dir(path)) + return path + def AppendENVPath(self, name, newpath, envname = 'ENV', sep = os.pathsep, delete_existing=0): """Append path elements to the path 'name' in the 'ENV' -- cgit v0.12 From ab166424306583f2ba2eb56f975a83b3cf9fd612 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 5 Jan 2021 15:49:00 -0500 Subject: Don't allow duplicate side effects to be added SCons disallows adding duplicate sources, but does not place any limits on adding duplicate side effects. This change adds code to not allow adding duplicate side effects. I considered mimicking Node.sources_set by adding Node.side_effects_set but it seemed unnecessary and would make it harder for Environment.SideEffect to only return the list of side effects that were actually added. --- SCons/Environment.py | 7 +++++-- SCons/EnvironmentTests.py | 6 ++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/SCons/Environment.py b/SCons/Environment.py index 4ebd515..0c1315c 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -2249,6 +2249,7 @@ class Base(SubstitutionEnvironment): side_effects = self.arg2nodes(side_effect, self.fs.Entry) targets = self.arg2nodes(target, self.fs.Entry) + added_side_effects = [] for side_effect in side_effects: if side_effect.multiple_side_effect_has_builder(): raise UserError("Multiple ways to build the same target were specified for: %s" % str(side_effect)) @@ -2256,8 +2257,10 @@ class Base(SubstitutionEnvironment): side_effect.side_effect = 1 self.Precious(side_effect) for target in targets: - target.side_effects.append(side_effect) - return side_effects + if side_effect not in target.side_effects: + target.side_effects.append(side_effect) + added_side_effects.append(side_effect) + return added_side_effects def Split(self, arg): """This function converts a string or list into a list of strings diff --git a/SCons/EnvironmentTests.py b/SCons/EnvironmentTests.py index 53dd9a7..e7381ab 100644 --- a/SCons/EnvironmentTests.py +++ b/SCons/EnvironmentTests.py @@ -3326,6 +3326,12 @@ def generate(env): assert ggg.side_effects == [s], ggg.side_effects assert ccc.side_effects == [s], ccc.side_effects + # Verify that duplicate side effects are not allowed. + before = len(ggg.side_effects) + s = env.SideEffect('mymmm.pdb', ggg) + assert len(s) == 0, len(s) + assert len(ggg.side_effects) == before, len(ggg.side_effects) + def test_Split(self): """Test the Split() method""" env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') -- cgit v0.12 From 16fad657267b692528059ecbb1b7ef3069322046 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 5 Jan 2021 15:52:58 -0500 Subject: Update CHANGES.txt --- CHANGES.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 7d11cb9..06318b1 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -40,6 +40,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER when running multiple tests with multiple jobs. - Fix incorrect cache hits and/or misses when running in interactive mode by having SCons.Node.Node.clear() clear out all caching-related state. + - Change Environment.SideEffect() to not add duplicate side effects. The list of returned + side effects will not include any duplicate side effects. From Jason Kenny - Fix python3 crash when Value node get_text_content when child content does not have decode() -- cgit v0.12 From 6ae20eb0265a21927029a45190f03dabec81776f Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 5 Jan 2021 16:03:34 -0500 Subject: Document the change to SideEffect --- SCons/Environment.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SCons/Environment.xml b/SCons/Environment.xml index d594bdf..e004158 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -2920,6 +2920,12 @@ or &f-env-Clean; function. + + +This function returns the list of side effects that were successfully added. +If the list of side effects contained any side effects that had already been added, +they are not added and included in the returned list. + -- cgit v0.12 From 1209ce9ec631c41a281dd1158928c8dd2292d668 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 5 Jan 2021 16:06:26 -0500 Subject: Update CHANGES.txt for clarity --- CHANGES.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 06318b1..a1ed1a0 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -40,8 +40,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER when running multiple tests with multiple jobs. - Fix incorrect cache hits and/or misses when running in interactive mode by having SCons.Node.Node.clear() clear out all caching-related state. - - Change Environment.SideEffect() to not add duplicate side effects. The list of returned - side effects will not include any duplicate side effects. + - Change Environment.SideEffect() to not add duplicate side effects. + NOTE: The list of returned side effects will not include any duplicate side effects. From Jason Kenny - Fix python3 crash when Value node get_text_content when child content does not have decode() -- cgit v0.12 From f5a7ae701a6a8ee898236fa0c996101cf9814483 Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 5 Jan 2021 16:11:02 -0500 Subject: Update RELEASE.txt --- RELEASE.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE.txt b/RELEASE.txt index 1410e35..340c3d5 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -39,8 +39,8 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY - - List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug + - Environment.SideEffect() no longer adds duplicate side effects. + NOTE: The list of returned side effects will not include any duplicate side effects. FIXES -- cgit v0.12 From 97d424e9d5094127a04382de9339cf4db3ab5e8e Mon Sep 17 00:00:00 2001 From: Adam Gross Date: Tue, 5 Jan 2021 16:39:19 -0500 Subject: Fix bug where SideEffect() was returning duplicate entries My code was adding the side effect to the return list inside of a "for target in targets" loop, causing duplicate entries if there were multiple targets. Fix this by adding outside of the loop. --- SCons/Environment.py | 5 ++++- SCons/EnvironmentTests.py | 12 +++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/SCons/Environment.py b/SCons/Environment.py index 0c1315c..3b720c8 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -2256,10 +2256,13 @@ class Base(SubstitutionEnvironment): side_effect.add_source(targets) side_effect.side_effect = 1 self.Precious(side_effect) + added = False for target in targets: if side_effect not in target.side_effects: target.side_effects.append(side_effect) - added_side_effects.append(side_effect) + added = True + if added: + added_side_effects.append(side_effect) return added_side_effects def Split(self, arg): diff --git a/SCons/EnvironmentTests.py b/SCons/EnvironmentTests.py index e7381ab..e57807b 100644 --- a/SCons/EnvironmentTests.py +++ b/SCons/EnvironmentTests.py @@ -3301,7 +3301,9 @@ def generate(env): foo = env.Object('foo.obj', 'foo.cpp')[0] bar = env.Object('bar.obj', 'bar.cpp')[0] - s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj'])[0] + s = env.SideEffect('mylib.pdb', ['foo.obj', 'bar.obj']) + assert len(s) == 1, len(s) + s = s[0] assert s.__class__.__name__ == 'Entry', s.__class__.__name__ assert s.get_internal_path() == 'mylib.pdb' assert s.side_effect @@ -3310,7 +3312,9 @@ def generate(env): fff = env.Object('fff.obj', 'fff.cpp')[0] bbb = env.Object('bbb.obj', 'bbb.cpp')[0] - s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj'])[0] + s = env.SideEffect('my${LIB}.pdb', ['${FOO}.obj', '${BAR}.obj']) + assert len(s) == 1, len(s) + s = s[0] assert s.__class__.__name__ == 'File', s.__class__.__name__ assert s.get_internal_path() == 'mylll.pdb' assert s.side_effect @@ -3319,7 +3323,9 @@ def generate(env): ggg = env.Object('ggg.obj', 'ggg.cpp')[0] ccc = env.Object('ccc.obj', 'ccc.cpp')[0] - s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj'])[0] + s = env.SideEffect('mymmm.pdb', ['ggg.obj', 'ccc.obj']) + assert len(s) == 1, len(s) + s = s[0] assert s.__class__.__name__ == 'Dir', s.__class__.__name__ assert s.get_internal_path() == 'mymmm.pdb' assert s.side_effect -- cgit v0.12 From 854322f6dc85cb2308e45f7d5775c16e7b9cf5a2 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 5 Jan 2021 18:18:12 -0800 Subject: split out steps to name them each --- .github/workflows/scons-package.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/scons-package.yml b/.github/workflows/scons-package.yml index fc9ab5d..b124592 100644 --- a/.github/workflows/scons-package.yml +++ b/.github/workflows/scons-package.yml @@ -37,11 +37,15 @@ jobs: # flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics # # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide # flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - - name: Build SCons and docs + - name: Update Doc sources (some parts are generated) run: | python bin/docs-update-generated.py python bin/docs-validate.py python bin/docs-create-example-outputs.py + - name: Build SCons packages + run: | python scripts/scons.py + - name: Verify package + run: | ls -l build/dist python build/scons-local/scons.py --version -- cgit v0.12 From e3d4125e9bd599b58e7b86320abeda26baff423c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 5 Jan 2021 20:09:10 -0800 Subject: [ci skip] Add github actions badge --- README.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.rst b/README.rst index 1d7b858..219151c 100755 --- a/README.rst +++ b/README.rst @@ -25,6 +25,10 @@ SCons - a software construction tool :target: https://codecov.io/gh/SCons/scons :alt: CodeCov Coverage Status +.. image:: https://github.com/SCons/scons/workflows/SCons%20Build/badge.svg + :target: https://github.com/SCons/scons/actions?query=workflow%3A%22SCons+Build%22 + :alt: Github Actions + Welcome to the SCons development tree. The real purpose of this tree is to package SCons for production distribution in a variety of formats, not just to -- cgit v0.12 From d853fd512fa280f4b2602cf0f72a9a5ebc66987c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 5 Jan 2021 20:17:51 -0800 Subject: [ci skip] Clarify that Node objects are returned from SideEffect() --- CHANGES.txt | 2 +- RELEASE.txt | 2 +- SCons/Environment.xml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index a1ed1a0..4b5970b 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -41,7 +41,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fix incorrect cache hits and/or misses when running in interactive mode by having SCons.Node.Node.clear() clear out all caching-related state. - Change Environment.SideEffect() to not add duplicate side effects. - NOTE: The list of returned side effects will not include any duplicate side effects. + NOTE: The list of returned side effect Nodes will not include any duplicate side effect Nodes. From Jason Kenny - Fix python3 crash when Value node get_text_content when child content does not have decode() diff --git a/RELEASE.txt b/RELEASE.txt index 340c3d5..a9f286e 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -40,7 +40,7 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY - Environment.SideEffect() no longer adds duplicate side effects. - NOTE: The list of returned side effects will not include any duplicate side effects. + NOTE: The list of returned side effect Nodes will not include any duplicate side effect Nodes. FIXES diff --git a/SCons/Environment.xml b/SCons/Environment.xml index e004158..a185815 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -2922,7 +2922,7 @@ function. -This function returns the list of side effects that were successfully added. +This function returns the list of side effect Node objects that were successfully added. If the list of side effects contained any side effects that had already been added, they are not added and included in the returned list. -- cgit v0.12 From 9969aea73ecc5b3dd657ee584b51f6edfc1639a3 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 6 Jan 2021 11:20:16 -0700 Subject: Update manpage section of Fortran suffixes [ci skip] The section mentioned only the .F suffix, added mention of the other variants and a brief note on what the difference means. Added some markup in the individual Fortran tools Doc-only change. Signed-off-by: Mats Wichmann --- SCons/Tool/f03.xml | 4 ++-- SCons/Tool/f08.xml | 4 ++-- SCons/Tool/f77.xml | 4 ++-- SCons/Tool/f90.xml | 4 ++-- SCons/Tool/f95.xml | 4 ++-- SCons/Tool/fortran.xml | 4 ++-- doc/man/scons.xml | 36 ++++++++++++++++++++++++++++++------ 7 files changed, 42 insertions(+), 18 deletions(-) diff --git a/SCons/Tool/f03.xml b/SCons/Tool/f03.xml index 97de0ad..fc14ace 100644 --- a/SCons/Tool/f03.xml +++ b/SCons/Tool/f03.xml @@ -89,7 +89,7 @@ If not set, then &cv-link-F03COM; or &cv-link-FORTRANCOM; The list of file extensions for which the F03 dialect will be used. By -default, this is ['.f03'] +default, this is ['.f03'] @@ -98,7 +98,7 @@ default, this is ['.f03'] The list of file extensions for which the compilation + preprocessor pass for -F03 dialect will be used. By default, this is empty +F03 dialect will be used. By default, this is empty. diff --git a/SCons/Tool/f08.xml b/SCons/Tool/f08.xml index 3f91f3c..fa7f633 100644 --- a/SCons/Tool/f08.xml +++ b/SCons/Tool/f08.xml @@ -89,7 +89,7 @@ If not set, then &cv-link-F08COM; or &cv-link-FORTRANCOM; The list of file extensions for which the F08 dialect will be used. By -default, this is ['.f08'] +default, this is ['.f08'] @@ -98,7 +98,7 @@ default, this is ['.f08'] The list of file extensions for which the compilation + preprocessor pass for -F08 dialect will be used. By default, this is empty +F08 dialect will be used. By default, this is empty. diff --git a/SCons/Tool/f77.xml b/SCons/Tool/f77.xml index ce69828..cade57f 100644 --- a/SCons/Tool/f77.xml +++ b/SCons/Tool/f77.xml @@ -91,7 +91,7 @@ for all Fortran versions. The list of file extensions for which the F77 dialect will be used. By -default, this is ['.f77'] +default, this is ['.f77'] @@ -100,7 +100,7 @@ default, this is ['.f77'] The list of file extensions for which the compilation + preprocessor pass for -F77 dialect will be used. By default, this is empty +F77 dialect will be used. By default, this is empty. diff --git a/SCons/Tool/f90.xml b/SCons/Tool/f90.xml index c57c28b..343aefe 100644 --- a/SCons/Tool/f90.xml +++ b/SCons/Tool/f90.xml @@ -89,7 +89,7 @@ If not set, then &cv-link-F90COM; or &cv-link-FORTRANCOM; The list of file extensions for which the F90 dialect will be used. By -default, this is ['.f90'] +default, this is ['.f90'] @@ -98,7 +98,7 @@ default, this is ['.f90'] The list of file extensions for which the compilation + preprocessor pass for -F90 dialect will be used. By default, this is empty +F90 dialect will be used. By default, this is empty. diff --git a/SCons/Tool/f95.xml b/SCons/Tool/f95.xml index f628ab1..3f38030 100644 --- a/SCons/Tool/f95.xml +++ b/SCons/Tool/f95.xml @@ -89,7 +89,7 @@ If not set, then &cv-link-F95COM; or &cv-link-FORTRANCOM; The list of file extensions for which the F95 dialect will be used. By -default, this is ['.f95'] +default, this is ['.f95'] @@ -98,7 +98,7 @@ default, this is ['.f95'] The list of file extensions for which the compilation + preprocessor pass for -F95 dialect will be used. By default, this is empty +F95 dialect will be used. By default, this is empty. diff --git a/SCons/Tool/fortran.xml b/SCons/Tool/fortran.xml index 560a484..a4f0cec 100644 --- a/SCons/Tool/fortran.xml +++ b/SCons/Tool/fortran.xml @@ -85,7 +85,7 @@ If not set, then &cv-link-FORTRANCOM; The list of file extensions for which the FORTRAN dialect will be used. By -default, this is ['.f', '.for', '.ftn'] +default, this is ['.f', '.for', '.ftn'] @@ -94,7 +94,7 @@ default, this is ['.f', '.for', '.ftn'] The list of file extensions for which the compilation + preprocessor pass for -FORTRAN dialect will be used. By default, this is ['.fpp', '.FPP'] +FORTRAN dialect will be used. By default, this is ['.fpp', '.FPP'] diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 45bc9bd..688225b 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -6879,20 +6879,35 @@ suffix as a C source file. -.F file suffix +Fortran file suffixes -&scons; handles the upper-case -.F -file suffix differently, +&scons; handles upper-case +Fortran file suffixes differently depending on the capabilities of the underlying system. On a case-sensitive system such as Linux or UNIX, &scons; treats a file with a .F -suffix as a Fortran source file +as a Fortran source file that is to be first run through -the standard C preprocessor. +the standard C preprocessor, +while the lower-case version is not. +This matches the convention of gfortran, +which may also be followed by other Fortran compilers. +This also applies to other naming variants, +.FOR, +.FTN, +.F90, +.F95, +.F03 and +.F08; +files suffixed with +.FPP +and .fpp +are both run through the preprocessor, +as indicated by the pp +part of the name. On a case-insensitive system such as Windows, &scons; treats a file with a @@ -6900,6 +6915,15 @@ such as Windows, suffix as a Fortran source file that should not be run through the C preprocessor. + +Run through the C preprocessor +here means that a different set of &consvars; will +be applied in constructed commands, for example +&cv-link-FORTRANPPCOM; and &cv-link-FORTRANPPCOMSTR; +instead of +&cv-link-FORTRANCOM; and &cv-link-FORTRANCOMSTR;. +See the Fortran-related &consvars; for more details. + -- cgit v0.12 From 4d9d1a67bd34c30c11df2fb773748308919507f4 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 7 Jan 2021 23:43:56 +0000 Subject: Bump lxml from 4.5.0 to 4.6.2 Bumps [lxml](https://github.com/lxml/lxml) from 4.5.0 to 4.6.2. - [Release notes](https://github.com/lxml/lxml/releases) - [Changelog](https://github.com/lxml/lxml/blob/master/CHANGES.txt) - [Commits](https://github.com/lxml/lxml/compare/lxml-4.5.0...lxml-4.6.2) Signed-off-by: dependabot[bot] --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index cc94763..16ac5a4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,5 +6,5 @@ readme-renderer sphinx sphinx_rtd_theme -lxml==4.5.0 +lxml==4.6.2 rst2pdf \ No newline at end of file -- cgit v0.12 From 0d8e8b49865b13a25d462e51496275d7c98d53a2 Mon Sep 17 00:00:00 2001 From: Daniel Moody Date: Fri, 8 Jan 2021 13:30:55 -0600 Subject: remove unnecessary python check swig test --- test/SWIG/recursive-includes-cpp.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/SWIG/recursive-includes-cpp.py b/test/SWIG/recursive-includes-cpp.py index 1a9091f..fd896f9 100644 --- a/test/SWIG/recursive-includes-cpp.py +++ b/test/SWIG/recursive-includes-cpp.py @@ -40,9 +40,8 @@ DefaultEnvironment( tools = [ 'swig' ] ) test = TestSCons.TestSCons() # Check for prerequisites of this test. -for pre_req in ['swig', 'python']: - if not test.where_is(pre_req): - test.skip_test('Can not find installed "' + pre_req + '", skipping test.%s' % os.linesep) +if not test.where_is('swig'): + test.skip_test('Can not find installed "swig", skipping test.%s' % os.linesep) python, python_include, python_libpath, python_lib = \ test.get_platform_python_info(python_h_required=True) -- cgit v0.12 From 53b5bc1faa9d185a0f6f4c1e7057e6a0b89262f3 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 18 Dec 2020 09:20:00 -0700 Subject: Switch travis-ci 3.9 to released + 20.04 [skip appveyor] Signed-off-by: Mats Wichmann --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 10bc138..5a4aae9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -59,8 +59,8 @@ jobs: dist: bionic # required for Python >= 3.8 - <<: *test_job - python: 3.9-dev - dist: bionic # required for Python >= 3.8 + python: 3.9 + dist: focal # required for Python >= 3.8 - &coverage_jobs dist: bionic -- cgit v0.12 From cfede5f08fb9c5e3c859d6b40c26a5d7ea9e6c11 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 18 Dec 2020 16:38:41 -0700 Subject: Change travis-ci install of ldc2 [skip appveyor] Signed-off-by: Mats Wichmann --- .travis/install.sh | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.travis/install.sh b/.travis/install.sh index 92c80c8..2c1d6f5 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -50,11 +50,13 @@ else # sudo apt-get update && sudo apt-get -y --allow-unauthenticated install dmd-bin # dependencies for ldc tests - export SCONS_LDC_VERSION=1.21.0 - wget https://github.com/ldc-developers/ldc/releases/download/v${SCONS_LDC_VERSION}/ldc2-${SCONS_LDC_VERSION}-linux-x86_64.tar.xz -# wget https://github.com/ldc-developers/ldc/releases/download/v1.15.0/ldc2-1.15.0-linux-x86_64.tar.xz - tar xf ldc2-${SCONS_LDC_VERSION}-linux-x86_64.tar.xz - sudo cp -rf ldc2-${SCONS_LDC_VERSION}-linux-x86_64/* / + # this install method basically worked until 20.04, though a little messy. + # rather than further tweaking, replace it with the recommended snap install + #export SCONS_LDC_VERSION=1.21.0 + #wget https://github.com/ldc-developers/ldc/releases/download/v${SCONS_LDC_VERSION}/ldc2-${SCONS_LDC_VERSION}-linux-x86_64.tar.xz + #tar xf ldc2-${SCONS_LDC_VERSION}-linux-x86_64.tar.xz + #sudo cp -rf ldc2-${SCONS_LDC_VERSION}-linux-x86_64/* / + sudo snap install ldc2 --classic # Failing.. ? # ls -l /usr/lib*/*python*{so,a}* -- cgit v0.12 From 8a7723e5b00b03acac519dfb5eb1e9a80be36292 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 19 Dec 2020 09:00:42 -0700 Subject: [PR #3847] Make tests pass again on Travis [skip appveyor] With the Travis build switched to install the ldc compiler through a snap, scons needs to be able to find a binary in /snap/bin too. On 10.x gdc compilers (part of the GNU Compiler Collection), the erorr message for an "unrecognized command line option" changed to "unrecognized command-line option". Wilcarded the changed character in the expectations of the one test which failed. Updated docs to indicate /opt/bin is part of env['PATH'] - it was not included, and added /snap/bin to accomodate this change. Signed-off-by: Mats Wichmann --- CHANGES.txt | 4 +++- SCons/Platform/posix.py | 2 +- doc/user/environments.xml | 2 +- test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py | 7 ++++--- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 868a6d9..47d7d06 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -108,7 +108,9 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fix Issue #3014 - Empty file and missing file have same csig - Refactor env.Append/Prepend to remove Py 1.5 era need to nest try blocks, can now "continue" at the appropriate places. - + - Add /snap/bin to env['PATH'] on POSIX, although this is only + really useful for a subset of POSIX systems that use snaps. + Was needed for CI builds, which run on Ubuntu LTS images. RELEASE 4.0.1 - Mon, 16 Jul 2020 16:06:40 -0700 diff --git a/SCons/Platform/posix.py b/SCons/Platform/posix.py index 4a5db10..4c9f8f9 100644 --- a/SCons/Platform/posix.py +++ b/SCons/Platform/posix.py @@ -84,7 +84,7 @@ def generate(env): if 'ENV' not in env: env['ENV'] = {} - env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin' + env['ENV']['PATH'] = '/usr/local/bin:/opt/bin:/bin:/usr/bin:/snap/bin' env['OBJPREFIX'] = '' env['OBJSUFFIX'] = '.o' env['SHOBJPREFIX'] = '$OBJPREFIX' diff --git a/doc/user/environments.xml b/doc/user/environments.xml index 40bcd31..5bcffbc 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -1770,7 +1770,7 @@ void main() { The default value of the &PATH; environment variable on a POSIX system - is /usr/local/bin:/bin:/usr/bin. + is /usr/local/bin:/opt/bin:/bin:/usr/bin:/snap/bin. The default value of the &PATH; environment variable on a Windows system comes from the Windows registry value for the command interpreter. diff --git a/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py b/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py index 2632f87..cc1dc4f 100644 --- a/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py +++ b/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py @@ -1,6 +1,7 @@ """ -These tests verify that SCons fails appropriately where the user has tried to supply multiple command line -options via a single string rather than providing a list of strings, one string per option. +These tests verify that SCons fails appropriately where the user has +tried to supply multiple command line options via a single string rather +than providing a list of strings, one string per option. """ # @@ -53,7 +54,7 @@ def testForTool(tool): result = { 'dmd': ".*unrecognized switch '-m64 -O'.*", - 'gdc': ".*unrecognized command line option.*", + 'gdc': ".*unrecognized command.line option.*", 'ldc': ".*Unknown command line argument '-m64 -O'.*", }[tool] -- cgit v0.12 From ce5f7483c14f323ee54472ed967cee822cad928f Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 6 Jan 2021 12:01:17 -0700 Subject: Drop scons-build from Travis CI After PR #3850, the SCons package/doc build is now done in a github workflow (action), so no longer needed in the Travis setup. Signed-off-by: Mats Wichmann --- .travis.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5a4aae9..bdf3e0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -77,19 +77,3 @@ jobs: - coverage report - coverage xml -i -o coverage_xml.xml - codecov -X gcov --file coverage_xml.xml - - - &scons_build_job - name: SCons Build - python: 3.7 - install: - - sudo apt-get -y install docbook-xml docbook-xsl xsltproc libxml2-dev libxslt-dev fop docbook-xsl-doc-pdf - - sudo apt-get -y --no-install-recommends install texlive texlive-latex3 biber texmaker ghostscript texlive-bibtex-extra texlive-latex-extra texlive-font-utils latexmk - - pip install -r requirements.txt - script: - - python bin/docs-update-generated.py - - python bin/docs-validate.py - - python bin/docs-create-example-outputs.py - - python scripts/scons.py - - ls -l build/dist - - python build/scons-local/scons.py --version - - ./.travis/verify_packages.sh -- cgit v0.12 From 2eddaa50dad5d96306b46bbc541f34d5460d9810 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 9 Jan 2021 08:22:34 -0700 Subject: Update RELEASE.txt for /snap/bin addition [ci skip] Signed-off-by: Mats Wichmann --- RELEASE.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASE.txt b/RELEASE.txt index a9f286e..df76cde 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -40,7 +40,9 @@ CHANGED/ENHANCED EXISTING FUNCTIONALITY - Environment.SideEffect() no longer adds duplicate side effects. - NOTE: The list of returned side effect Nodes will not include any duplicate side effect Nodes. + NOTE: The list of returned side effect Nodes will not include any + duplicate side effect Nodes. + - /snap/bin is added to the default search path for the 'posix' platform. FIXES -- cgit v0.12 From d3c6a4a199beff6e4d28725da9c0b0a052349359 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Tue, 12 Jan 2021 07:48:33 -0700 Subject: Work around Py3.10 optimizing out a builder test BuilderBase class traps __bool__ call and raises InternalError. On Py 3.10a the unit test for this got optimized out, avoid this. While we're at it, eliminate remaining references to __nonzero__, which was a Py2-ism, replaced by __bool__. Closes #3860 Signed-off-by: Mats Wichmann --- CHANGES.txt | 2 ++ SCons/Builder.py | 5 +---- SCons/BuilderTests.py | 17 ++++++++++++----- SCons/Environment.py | 2 +- SCons/Node/__init__.py | 2 +- SCons/Util.py | 7 +------ 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 47d7d06..26dc188 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -111,6 +111,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Add /snap/bin to env['PATH'] on POSIX, although this is only really useful for a subset of POSIX systems that use snaps. Was needed for CI builds, which run on Ubuntu LTS images. + - Eliminate Py2-ism __nonzero__ (now __bool__). Work around issue #3860 + where a check for BuilderBase raising exc. on __bool__ was optimized out. RELEASE 4.0.1 - Mon, 16 Jul 2020 16:06:40 -0700 diff --git a/SCons/Builder.py b/SCons/Builder.py index a0df272..4c2ad7f 100644 --- a/SCons/Builder.py +++ b/SCons/Builder.py @@ -430,11 +430,8 @@ class BuilderBase: src_builder = [ src_builder ] self.src_builder = src_builder - def __nonzero__(self): - raise InternalError("Do not test for the Node.builder attribute directly; use Node.has_builder() instead") - def __bool__(self): - return self.__nonzero__() + raise InternalError("Do not test for the Node.builder attribute directly; use Node.has_builder() instead") def get_name(self, env): """Attempts to get the name of the Builder. diff --git a/SCons/BuilderTests.py b/SCons/BuilderTests.py index 0e46194..8d616f1 100644 --- a/SCons/BuilderTests.py +++ b/SCons/BuilderTests.py @@ -207,13 +207,14 @@ class BuilderTestCase(unittest.TestCase): x = builder.overrides['OVERRIDE'] assert x == 'x', x - def test__nonzero__(self): - """Test a builder raising an exception when __nonzero__ is called - """ + def test__bool__(self): + """Test a builder raising an exception when __bool__ is called. """ + + # basic test: explicitly call it builder = SCons.Builder.Builder(action="foo") exc_caught = None try: - builder.__nonzero__() + builder.__bool__() except SCons.Errors.InternalError: exc_caught = 1 assert exc_caught, "did not catch expected InternalError exception" @@ -221,12 +222,18 @@ class BuilderTestCase(unittest.TestCase): class Node: pass + # the interesting test: checking the attribute this way + # should call back to Builder.__bool__ - so we can tell + # people not to check that way (for performance). + # TODO: workaround #3860: with just a "pass" in the check body, + # py3.10a optimizes out the whole thing, so add a "real" stmt n = Node() n.builder = builder exc_caught = None try: if n.builder: - pass + #pass + _ = True except SCons.Errors.InternalError: exc_caught = 1 assert exc_caught, "did not catch expected InternalError exception" diff --git a/SCons/Environment.py b/SCons/Environment.py index 0b8a20a..61128af 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -1538,7 +1538,7 @@ class Base(SubstitutionEnvironment): def Dictionary(self, *args): - """Return construction variables from an environment. + r"""Return construction variables from an environment. Args: \*args (optional): variable names to look up diff --git a/SCons/Node/__init__.py b/SCons/Node/__init__.py index 3685af3..491c6b8 100644 --- a/SCons/Node/__init__.py +++ b/SCons/Node/__init__.py @@ -886,7 +886,7 @@ class Node(object, metaclass=NoSlotsPyPy): than simply examining the builder attribute directly ("if node.builder: ..."). When the builder attribute is examined directly, it ends up calling __getattr__ for both the __len__ - and __nonzero__ attributes on instances of our Builder Proxy + and __bool__ attributes on instances of our Builder Proxy class(es), generating a bazillion extra calls and slowing things down immensely. """ diff --git a/SCons/Util.py b/SCons/Util.py index fae2d64..0f26fb1 100644 --- a/SCons/Util.py +++ b/SCons/Util.py @@ -125,11 +125,8 @@ class NodeList(UserList): # self.data = [ initlist,] - def __nonzero__(self): - return len(self.data) != 0 - def __bool__(self): - return self.__nonzero__() + return len(self.data) != 0 def __str__(self): return ' '.join(map(str, self.data)) @@ -1563,8 +1560,6 @@ class Null: return self def __repr__(self): return "Null(0x%08X)" % id(self) - def __nonzero__(self): - return False def __bool__(self): return False def __getattr__(self, name): -- cgit v0.12 From 3e219eba1311807bde43348c86967d96c5379217 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 12 Jan 2021 11:18:29 -0800 Subject: [ci skip] Add note to PR about it being a Py 3.10.0a4 workaround --- CHANGES.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.txt b/CHANGES.txt index 26dc188..133fcb9 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -113,6 +113,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER Was needed for CI builds, which run on Ubuntu LTS images. - Eliminate Py2-ism __nonzero__ (now __bool__). Work around issue #3860 where a check for BuilderBase raising exc. on __bool__ was optimized out. + This issue was found due to a bug in Python 3.10.0a4. See issue #3860 for details. RELEASE 4.0.1 - Mon, 16 Jul 2020 16:06:40 -0700 -- cgit v0.12 From da23ac719cf6509bc9c7c650b7047d8c8987a88d Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Wed, 13 Jan 2021 13:08:11 -0700 Subject: UGuide: fix two erroneous uses of Append [ci skip] In the SConf chapter, one use was not as a keyword argument, while the other set a "-DVAR=value" form to append to CPPDEFINES, which aren't supposed to be given the prefix - that's the whole reason for CPPDEFINES. Both changed to CCFLAGS, to match other usage in the chapter. Signed-off-by: Mats Wichmann --- doc/user/sconf.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml index 5611bbf..7d86e6f 100644 --- a/doc/user/sconf.xml +++ b/doc/user/sconf.xml @@ -166,7 +166,7 @@ if not conf.CheckCHeader('math.h'): print('Math.h must be installed!') Exit(1) if conf.CheckCHeader('foo.h'): - conf.env.Append('-DHAS_FOO_H') + conf.env.Append(CCFLAGS='-DHAS_FOO_H') env = conf.Finish() @@ -221,7 +221,7 @@ env = Environment() conf = Configure(env) if not conf.CheckFunc('strcpy'): print('Did not find strcpy(), using local version') - conf.env.Append(CPPDEFINES='-Dstrcpy=my_local_strcpy') + conf.env.Append(CCFLAGS='-Dstrcpy=my_local_strcpy') env = conf.Finish() -- cgit v0.12 From 40ad600f0fb5201ad6ec1251cf90879f96f730af Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 14 Jan 2021 18:04:22 -0800 Subject: fix copyright text, remove SHDLIBVERSION entirely. Never worked before, and doesn't make sense. Use SHLIBVERSION instead. TODO: Fix soname generation for command line --- SCons/Tool/DCommon.xml | 7 ------- SCons/Tool/dmd.py | 13 +----------- SCons/Tool/dmd.xml | 1 - SCons/Tool/gdc.py | 10 ---------- SCons/Tool/gdc.xml | 1 - SCons/Tool/ldc.py | 15 ++------------ SCons/Tool/ldc.xml | 1 - SCons/Tool/linkCommon/LoadableModule.py | 23 ++++++++++++++++++++++ SCons/Tool/linkCommon/SharedLibrary.py | 23 ++++++++++++++++++++++ test/D/DMD.py | 7 +++---- test/D/GDC.py | 7 +++---- .../Common/singleStringCannotBeMultipleOptions.py | 20 +++++++++---------- ...test-singleStringCannotBeMultipleOptions_gdc.py | 13 ++++++------ test/D/LDC.py | 7 +++---- test/D/SharedObjects/Common/common.py | 7 ++----- test/D/SharedObjects/sconstest-dmd.py | 6 ++---- test/D/Support/executablesSearch.py | 15 ++++++-------- 17 files changed, 84 insertions(+), 92 deletions(-) diff --git a/SCons/Tool/DCommon.xml b/SCons/Tool/DCommon.xml index a4efd7b..fd1e4a5 100644 --- a/SCons/Tool/DCommon.xml +++ b/SCons/Tool/DCommon.xml @@ -319,13 +319,6 @@ See also &cv-link-DCOMSTR; for compiling to static objects. - - - -SHDLIBVERSION. - - - diff --git a/SCons/Tool/dmd.py b/SCons/Tool/dmd.py index 76fcf51..67ed43e 100644 --- a/SCons/Tool/dmd.py +++ b/SCons/Tool/dmd.py @@ -151,18 +151,7 @@ def generate(env): env['_DRPATH'] = '${_concat(DRPATHPREFIX, RPATH, DRPATHSUFFIX, __env__)}' # Support for versioned libraries - env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -L-soname=$_SHDLIBSONAME' - - # TODO: Fix this with new logic - # env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' - # # NOTE: this is a quick hack, the soname will only work if there is - # # c/c++ linker loaded which provides callback for the ShLibSonameGenerator - # env['DShLibSonameGenerator'] = ShLibSonameGenerator - - # NOTE: this is only for further reference, currently $SHDLIBVERSION does - # not work, the user must use $SHLIBVERSION - env['SHDLIBVERSION'] = '$SHLIBVERSION' - env['SHDLIBVERSIONFLAGS'] = [] + env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -L-soname=$_SHLIBSONAME' env['BUILDERS']['ProgramAllAtOnce'] = SCons.Builder.Builder( action='$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -of$TARGET $DLINKFLAGS $__DRPATH $SOURCES $_DLIBDIRFLAGS $_DLIBFLAGS', diff --git a/SCons/Tool/dmd.xml b/SCons/Tool/dmd.xml index 1ee0edb..be9f23d 100644 --- a/SCons/Tool/dmd.xml +++ b/SCons/Tool/dmd.xml @@ -65,7 +65,6 @@ Sets construction variables for D language compiler DMD. DLINKFLAGSUFFIX DRPATHPREFIX DRPATHSUFFIX -SHDLIBVERSION SHDLIBVERSIONFLAGS diff --git a/SCons/Tool/gdc.py b/SCons/Tool/gdc.py index 09b6d26..0728c6f 100644 --- a/SCons/Tool/gdc.py +++ b/SCons/Tool/gdc.py @@ -117,16 +117,6 @@ def generate(env): # Support for versioned libraries env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -Wl,-soname=$_SHLIBSONAME' - # TODO: Fix with new versioned shared lib logic - # env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' - # # NOTE: this is a quick hack, the soname will only work if there is - # # c/c++ linker loaded which provides callback for the ShLibSonameGenerator - # env['DShLibSonameGenerator'] = SCons.Tool.linkCommon.ShLibSonameGenerator - # NOTE: this is only for further reference, currently $SHDLIBVERSION does - # not work, the user must use $SHLIBVERSION - env['SHDLIBVERSION'] = '$SHLIBVERSION' - env['SHDLIBVERSIONFLAGS'] = '$SHLIBVERSIONFLAGS' - env['BUILDERS']['ProgramAllAtOnce'] = SCons.Builder.Builder( action='$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -o $TARGET $DLINKFLAGS $__DRPATH $SOURCES $_DLIBDIRFLAGS $_DLIBFLAGS', emitter=DCommon.allAtOnceEmitter, diff --git a/SCons/Tool/gdc.xml b/SCons/Tool/gdc.xml index 8248026..fd4cae7 100644 --- a/SCons/Tool/gdc.xml +++ b/SCons/Tool/gdc.xml @@ -65,7 +65,6 @@ Sets construction variables for the D language compiler GDC. DLINKFLAGSUFFIX DRPATHPREFIX DRPATHSUFFIX -SHDLIBVERSION SHDLIBVERSIONFLAGS diff --git a/SCons/Tool/ldc.py b/SCons/Tool/ldc.py index 23cc837..fa02bf8 100644 --- a/SCons/Tool/ldc.py +++ b/SCons/Tool/ldc.py @@ -127,19 +127,8 @@ def generate(env): env['_DRPATH'] = '${_concat(DRPATHPREFIX, RPATH, DRPATHSUFFIX, __env__)}' # Support for versioned libraries - env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -L-soname=$_SHDLIBSONAME' - - # TODO: Fix to work with new logic - # env['_SHDLIBSONAME'] = '${DShLibSonameGenerator(__env__,TARGET)}' - # # NOTE: this is a quick hack, the soname will only work if there is - # # c/c++ linker loaded which provides callback for the ShLibSonameGenerator - # env['DShLibSonameGenerator'] = ShLibSonameGenerator - # - - # NOTE: this is only for further reference, currently $SHDLIBVERSION does - # not work, the user must use $SHLIBVERSION - env['SHDLIBVERSION'] = '$SHLIBVERSION' - env['SHDLIBVERSIONFLAGS'] = [] + env['_SHDLIBVERSIONFLAGS'] = '$SHDLIBVERSIONFLAGS -L-soname=$_SHLIBSONAME' + env['BUILDERS']['ProgramAllAtOnce'] = SCons.Builder.Builder( action='$DC $_DINCFLAGS $_DVERFLAGS $_DDEBUGFLAGS $_DFLAGS -of=$TARGET $DLINKFLAGS $__DRPATH $SOURCES $_DLIBDIRFLAGS $_DLIBFLAGS', diff --git a/SCons/Tool/ldc.xml b/SCons/Tool/ldc.xml index 5802751..d584466 100644 --- a/SCons/Tool/ldc.xml +++ b/SCons/Tool/ldc.xml @@ -65,7 +65,6 @@ Sets construction variables for the D language compiler LDC2. DLINKFLAGSUFFIX DRPATHPREFIX DRPATHSUFFIX -SHDLIBVERSION SHDLIBVERSIONFLAGS diff --git a/SCons/Tool/linkCommon/LoadableModule.py b/SCons/Tool/linkCommon/LoadableModule.py index e9c31dc..c8124a0 100644 --- a/SCons/Tool/linkCommon/LoadableModule.py +++ b/SCons/Tool/linkCommon/LoadableModule.py @@ -1,3 +1,26 @@ +# 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. + from SCons.Tool import createLoadableModuleBuilder from .SharedLibrary import shlib_symlink_emitter from . import lib_emitter diff --git a/SCons/Tool/linkCommon/SharedLibrary.py b/SCons/Tool/linkCommon/SharedLibrary.py index 1e98499..cfeddbb 100644 --- a/SCons/Tool/linkCommon/SharedLibrary.py +++ b/SCons/Tool/linkCommon/SharedLibrary.py @@ -1,3 +1,26 @@ +# 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. + from SCons.Errors import UserError from SCons.Tool import createSharedLibBuilder from SCons.Util import CLVar diff --git a/test/D/DMD.py b/test/D/DMD.py index 2d9333a..8e09de4 100644 --- a/test/D/DMD.py +++ b/test/D/DMD.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,12 +22,9 @@ # 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. -# # Amended by Russel Winder 2010-05-05 -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import TestSCons import sys diff --git a/test/D/GDC.py b/test/D/GDC.py index b548b94..b73c09c 100644 --- a/test/D/GDC.py +++ b/test/D/GDC.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,12 +22,9 @@ # 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. -# # Amended by Russel Winder 2010-05-05 -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import TestSCons _exe = TestSCons._exe diff --git a/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py b/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py index 2632f87..65ad61a 100644 --- a/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py +++ b/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py @@ -1,10 +1,6 @@ -""" -These tests verify that SCons fails appropriately where the user has tried to supply multiple command line -options via a single string rather than providing a list of strings, one string per option. -""" - +# MIT License # -# __COPYRIGHT__ +# 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 @@ -24,9 +20,11 @@ options via a single string rather than providing a list of strings, one string # 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__" +""" +These tests verify that SCons fails appropriately where the user has tried to supply multiple command line +options via a single string rather than providing a list of strings, one string per option. +""" import TestSCons @@ -49,7 +47,6 @@ def testForTool(tool): config = f.read().format(tool) test.write('SConstruct', config) - test.run(status=2, stdout=None, stderr=None) result = { 'dmd': ".*unrecognized switch '-m64 -O'.*", @@ -57,11 +54,14 @@ def testForTool(tool): 'ldc': ".*Unknown command line argument '-m64 -O'.*", }[tool] + from SCons.Environment import Base if tool == 'dmd' and Base()['DC'] == 'gdmd': result = ".*unrecognized command line option '-m64 -O'.*" - test.fail_test(not test.match_re_dotall(test.stderr(), result)) + test.run(status=2, stdout=None, stderr=result, match=TestSCons.match_re_dotall) + + # test.fail_test(not test.match_re_dotall(test.stderr(), result)) test.pass_test() diff --git a/test/D/HSTeoh/sconstest-singleStringCannotBeMultipleOptions_gdc.py b/test/D/HSTeoh/sconstest-singleStringCannotBeMultipleOptions_gdc.py index d65495a..30eefbc 100644 --- a/test/D/HSTeoh/sconstest-singleStringCannotBeMultipleOptions_gdc.py +++ b/test/D/HSTeoh/sconstest-singleStringCannotBeMultipleOptions_gdc.py @@ -1,9 +1,6 @@ -""" -Test compiling and executing using the gdc tool. -""" - +# MIT License # -# __COPYRIGHT__ +# 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 @@ -23,9 +20,11 @@ Test compiling and executing using the gdc tool. # 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__" +""" +Test compiling and executing using the gdc tool. +""" +import pdb; pdb.set_trace() from Common.singleStringCannotBeMultipleOptions import testForTool testForTool('gdc') diff --git a/test/D/LDC.py b/test/D/LDC.py index 19070a5..aa242c1 100644 --- a/test/D/LDC.py +++ b/test/D/LDC.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,12 +22,9 @@ # 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. -# # Amended by Russel Winder 2010-05-05 -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import TestSCons from os.path import abspath, dirname diff --git a/test/D/SharedObjects/Common/common.py b/test/D/SharedObjects/Common/common.py index 5113cc4..d5588be 100644 --- a/test/D/SharedObjects/Common/common.py +++ b/test/D/SharedObjects/Common/common.py @@ -1,9 +1,9 @@ """ Support functions for all the tests. """ - +# MIT License # -# __COPYRIGHT__ +# 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 @@ -23,9 +23,6 @@ Support functions for all the tests. # 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 diff --git a/test/D/SharedObjects/sconstest-dmd.py b/test/D/SharedObjects/sconstest-dmd.py index df6ddeb..7dca880 100644 --- a/test/D/SharedObjects/sconstest-dmd.py +++ b/test/D/SharedObjects/sconstest-dmd.py @@ -2,8 +2,9 @@ Test compiling and executing using the dmd tool. """ +# MIT License # -# __COPYRIGHT__ +# 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 @@ -23,9 +24,6 @@ Test compiling and executing using the dmd tool. # 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__" from Common.common import testForTool testForTool('dmd') diff --git a/test/D/Support/executablesSearch.py b/test/D/Support/executablesSearch.py index e24601c..c7da4ff 100755 --- a/test/D/Support/executablesSearch.py +++ b/test/D/Support/executablesSearch.py @@ -1,11 +1,6 @@ -#! /usr/bin/env python - -""" -Support functions for all the tests. -""" - +# MIT License # -# __COPYRIGHT__ +# 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 @@ -25,9 +20,11 @@ Support functions for all the tests. # 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. -# +#! /usr/bin/env python -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +""" +Support functions for all the tests. +""" if __name__ == '__main__': import sys -- cgit v0.12 From a4efe5deb3c5522ee89b79b6a34465f5946233f2 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 19:57:09 +0000 Subject: Remove old test verification logic --- test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py b/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py index 8060b61..5838505 100644 --- a/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py +++ b/test/D/HSTeoh/Common/singleStringCannotBeMultipleOptions.py @@ -63,8 +63,6 @@ def testForTool(tool): test.run(status=2, stdout=None, stderr=result, match=TestSCons.match_re_dotall) - # test.fail_test(not test.match_re_dotall(test.stderr(), result)) - test.pass_test() # Local Variables: -- cgit v0.12 From 48ea8aad37fc9c0196bb95b299809e6c53d4a012 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 19:58:15 +0000 Subject: Add generating versioned shared library to D SharedObject tests (in addition to existing plain shared library test. --- test/D/SharedObjects/Common/common.py | 7 ++++--- test/D/SharedObjects/Image/SConstruct_template | 7 +++++-- test/LINK/VersionedLib.py | 8 ++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/test/D/SharedObjects/Common/common.py b/test/D/SharedObjects/Common/common.py index d5588be..d026658 100644 --- a/test/D/SharedObjects/Common/common.py +++ b/test/D/SharedObjects/Common/common.py @@ -1,6 +1,3 @@ -""" -Support functions for all the tests. -""" # MIT License # # Copyright The SCons Foundation @@ -23,6 +20,10 @@ Support functions for all the tests. # 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. +""" +Support functions for all the tests. +""" + import TestSCons diff --git a/test/D/SharedObjects/Image/SConstruct_template b/test/D/SharedObjects/Image/SConstruct_template index f731a33..96b44ca 100644 --- a/test/D/SharedObjects/Image/SConstruct_template +++ b/test/D/SharedObjects/Image/SConstruct_template @@ -3,8 +3,11 @@ # The core difference between this test and the one of SharedObjectSuffixIssue # is that here we explicitly use the relevant D tool and things work. -environment = Environment( +DefaultEnvironment(tools=[]) +env = Environment( tools=['{0}', 'link'] ) -environment.SharedLibrary('answer', 'code.d') +shobj = env.SharedObject('code.d') +env.SharedLibrary('answer', shobj) +env.SharedLibrary('answer_versioned', shobj, SHLIBVERSION='1.1.1', SONAME='1') diff --git a/test/LINK/VersionedLib.py b/test/LINK/VersionedLib.py index 5f74f92..44cd0ee 100644 --- a/test/LINK/VersionedLib.py +++ b/test/LINK/VersionedLib.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 @@ -21,8 +23,6 @@ # 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 os import TestSCons @@ -218,7 +218,7 @@ for t in test_plan: instfiles = t['instfiles'] test.write('SConstruct', """\ -import os +DefaultEnvironment(tools=[]) env = Environment() objs = env.SharedObject('test.c') mylib = env.SharedLibrary('test', objs, SHLIBVERSION = '%s') -- cgit v0.12 From 6e93cc055eb627c63ea4f9438c770844b1ebb8e3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 20:17:46 +0000 Subject: add logic to test D SHLIBVERSION and SOVERSION --- SCons/Tool/linkCommon/SharedLibrary.py | 2 +- test/D/SharedObjects/Common/common.py | 1 + test/D/SharedObjects/Image/SConstruct_template | 9 ++++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/SCons/Tool/linkCommon/SharedLibrary.py b/SCons/Tool/linkCommon/SharedLibrary.py index cfeddbb..e28addc 100644 --- a/SCons/Tool/linkCommon/SharedLibrary.py +++ b/SCons/Tool/linkCommon/SharedLibrary.py @@ -123,7 +123,7 @@ def _get_shlib_stem(target, source, env, for_signature): :param for_signature: :return: """ - verbose = True + verbose = False target_name = str(target.name) shlibprefix = env.subst("$SHLIBPREFIX") diff --git a/test/D/SharedObjects/Common/common.py b/test/D/SharedObjects/Common/common.py index d026658..1bb2d50 100644 --- a/test/D/SharedObjects/Common/common.py +++ b/test/D/SharedObjects/Common/common.py @@ -88,6 +88,7 @@ def testForTool(tool): test.must_exist(test.workpath(code_name)) test.must_exist(test.workpath(library_name)) + test.pass_test() # Local Variables: diff --git a/test/D/SharedObjects/Image/SConstruct_template b/test/D/SharedObjects/Image/SConstruct_template index 96b44ca..7ae1c8d 100644 --- a/test/D/SharedObjects/Image/SConstruct_template +++ b/test/D/SharedObjects/Image/SConstruct_template @@ -10,4 +10,11 @@ env = Environment( shobj = env.SharedObject('code.d') env.SharedLibrary('answer', shobj) -env.SharedLibrary('answer_versioned', shobj, SHLIBVERSION='1.1.1', SONAME='1') +ver_lib = env.SharedLibrary('answer_versioned', shobj, SHLIBVERSION='1.1.1', SOVERSION='4') + +shlibfile = ver_lib[0] +try: + for (f,t) in ver_lib[0].attributes.shliblinks: + print("SYMLINK:%s,%s"%(f,t)) +except AttributeError: + print("NOSYMLINK") -- cgit v0.12 From ca31e1ef989e731a2f59129ee0a490e832e8f3bd Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 21:00:57 +0000 Subject: updating readme on implmentation --- SCons/Tool/linkCommon/README.md | 46 ++++++++++++++--------------------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/SCons/Tool/linkCommon/README.md b/SCons/Tool/linkCommon/README.md index add1246..4a83c16 100644 --- a/SCons/Tool/linkCommon/README.md +++ b/SCons/Tool/linkCommon/README.md @@ -1,3 +1,19 @@ +# Current implementation details + +The code has been simplified to use Subst expansion do most of the work. + +The following internal env vars have been added which are python functions (note also ldmodule where shlib is below) +* `_get_shlib_stem` - given a library name `libxyz.so.1.1.0` it will retrievve `xyz` +* `_get_shlib_dir` - given a library with a path `DEF/a/b/libxyz.so.1.1.0` it will retrieve `DEF` +* `_SHLIBSOVERSION` - will look for `SOVERSION` and then `SHLIBVERSION` to determine the `SOVERSION` to be used in file naming +* `_SHLIBSONAME` - will check for and error if both `SONAME` and `SOVERSION` are defined, otherwise will generate the proper filenaming for SONAME +* `_SHLIBVERSION` - will return `SHLIBVERSION` or "" if SHLIBVERSION is defined +* `_SHLIBVERSIONFLAGS` - will return proper compiler flags for SHLIBVERSION +* `__SHLIBVERSIONFLAGS` - compiler defined proper versioned shared library flags +* `SHLIB_SONAME_SYMLINK` - this is the symlink for SONAME to be used (`libxyz.1.so`) +* `SHLIB_NOVERSION_SYMLINK` - this is the symlink for non-versioned filename (`libxyz.so`) +Shared library file nodes will have `node.attributes.shliblinks` which is a tuple of the symlinks to be created + # Versioned Shared Library and Loadable modules requirements @@ -46,19 +62,6 @@ For **openbsd** the following rules for symlinks apply * OpenBSD uses x.y shared library versioning numbering convention and doesn't use symlinks to backwards-compatible libraries -The current code provides the following hooks a compiler can use to customize: - -``` - 'VersionedShLibSuffix': _versioned_lib_suffix, - 'VersionedLdModSuffix': _versioned_lib_suffix, - 'VersionedShLibSymlinks': _versioned_shlib_symlinks, - 'VersionedLdModSymlinks': _versioned_ldmod_symlinks, - 'VersionedShLibName': _versioned_shlib_name, - 'VersionedLdModName': _versioned_ldmod_name, - 'VersionedShLibSoname': _versioned_shlib_soname, - 'VersionedLdModSoname': _versioned_ldmod_soname, -``` - User can request: env.SharedLibrary('a',sources, SHLIBVERSION) @@ -84,20 +87,3 @@ SONAME can be specified, if not defaults to ${SHLIBPREFIX}lib_name${SOVERSION} NOTE: mongodb uses Append(SHLIBEMITTER=.. ) for their libdeps stuff. (So test with that once you have new logic working) - -TODO: -1. Generate proper naming for: - * shared library (altered by emitter if SHLIBVERSION is set) - * soname'd library (for symlink) - SHLIB_SONAME_SYMLINK - * non versioned shared library (for symlink) - SHLIB_NOVERSION_SYMLINK -2. in emitter also, actually create the symlinks (if SHLIBVERSION is set) and - add to node.attributes.symlinks. (note bsd doesn't do this so skip if on bsd) -3. We need to check somewhere if SONAME and SOVERSION are both set and thrown an error. - Probably in the emitter to it will traceback to where the SharedLibrary() which - yielded the issue is located. -4. Generate proper linker soname compiler construct (-Wl,soname=libxyz.1.so for example) - -hrm.. tricky. -SHLIBSUFFIX needs to have .${SHLIBVERSION}${SHLIBSUFFIX} as it's value when -fixing a sharedlibrary()'s target file name (from a -> liba.1.2.3.so) -But when creating the symlinks for the rest, we need to drop the versioned SHLIBSUFFIX \ No newline at end of file -- cgit v0.12 From 025ae0d19b2e3b8bb487eea2a8231faac0a0caa3 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 21:06:31 +0000 Subject: updated CHANGES.txt and RELEASE.txt --- CHANGES.txt | 1 + RELEASE.txt | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 133fcb9..4681889 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -29,6 +29,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Remove using pywin32 to retrieve peak memory usage on Win32 for `--debug=memory` - Fix Issue #3759 - include scons.1, sconsign.1, scons-time.1 manpages in sdist and wheel packages. - Change SCons's build so the generated `SCons/__init__.py` is no longer removed by `scons -c` + - Completely rewrote versioned shared libraries logic. Added support for SOVERSION via dmoody's initial PR #3733 From MichaÅ‚ Górny: - Fix dvipdf test failure due to passing incorrect flag to dvipdf. diff --git a/RELEASE.txt b/RELEASE.txt index df76cde..4e899dc 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -43,6 +43,9 @@ NOTE: The list of returned side effect Nodes will not include any duplicate side effect Nodes. - /snap/bin is added to the default search path for the 'posix' platform. + - Completely rewrote versioned shared libraries logic. + - Added support for SOVERSION + FIXES -- cgit v0.12 From e6d4a1a12a55aa738e3a9c7a915d9852dccc0fc1 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 22:57:00 +0000 Subject: [ci skip]Updated generated docs, Updated docs --- SCons/Tool/DCommon.xml | 12 +- SCons/Tool/link.xml | 18 + doc/generated/builders.gen | 173 ++++--- doc/generated/examples/caching_ex-random_1.xml | 4 +- doc/generated/examples/troubleshoot_Dump_1.xml | 3 +- doc/generated/examples/troubleshoot_Dump_2.xml | 3 +- doc/generated/examples/troubleshoot_Dump_ENV_1.xml | 2 +- doc/generated/examples/troubleshoot_explain1_3.xml | 2 +- .../examples/troubleshoot_stacktrace_2.xml | 8 +- doc/generated/functions.gen | 520 +++++++++++---------- doc/generated/tools.gen | 17 +- doc/generated/tools.mod | 2 - doc/generated/variables.gen | 183 ++++---- doc/generated/variables.mod | 8 +- 14 files changed, 528 insertions(+), 427 deletions(-) diff --git a/SCons/Tool/DCommon.xml b/SCons/Tool/DCommon.xml index fd1e4a5..55da85d 100644 --- a/SCons/Tool/DCommon.xml +++ b/SCons/Tool/DCommon.xml @@ -257,14 +257,6 @@ DRPATHSUFFIX. - - - -DShLibSonameGenerator. - - - - @@ -323,7 +315,9 @@ See also &cv-link-DCOMSTR; for compiling to static objects. -SHDLIBVERSIONFLAGS. +Extra flags added to &cv-link-SHDLINKCOM; when building versioned +&b-link-SharedLibrary;. These flags are only used when &cv-link-SHLIBVERSION; is +set. diff --git a/SCons/Tool/link.xml b/SCons/Tool/link.xml index 4eab92c..f90a33b 100644 --- a/SCons/Tool/link.xml +++ b/SCons/Tool/link.xml @@ -387,6 +387,24 @@ The variable is used, for example, by &t-link-gnulink; linker tool. + + + +This will construct the SONAME using on the base library name +(test in the example below) and use specified SOVERSION +to create SONAME. + +env.SharedLibrary('test', 'test.c', SHLIBVERSION='0.1.2', SOVERSION='2') + +The variable is used, for example, by &t-link-gnulink; linker tool. + + +In the example above SONAME would be libtest.so.2 +which would be a symlink and point to libtest.so.0.1.2 + + + + diff --git a/doc/generated/builders.gen b/doc/generated/builders.gen index 94c8eff..bfb1ff1 100644 --- a/doc/generated/builders.gen +++ b/doc/generated/builders.gen @@ -54,30 +54,55 @@ for the calling syntax and details. CompilationDatabase() env.CompilationDatabase() - The &b-CompilationDatabase; builder writes a JSON formatted compilation - database according to the - LLVM specification - which is consumed by a number of clang tools, editors, and other tools. + &b-CompilationDatabase; is a special builder which + adds a target to create a JSON formatted + compilation database compatible with + clang tooling + (see the + LLVM specification). + This database is suitable for consumption by various + tools and editors who can use it to obtain build and + dependency information which otherwise would be + internal to &SCons;. + The builder does not require any source files to be specified, + rather it arranges to emit information about all + of the C, C++ and assembler source/output pairs + identified in the build that are not excluded by the + optional filter &cv-link-COMPILATIONDB_PATH_FILTER;. + The target is subject to the usual &SCons; target + selection rules. - If you don't specify any files, the builder will default to compile_commands.json. + If called with no arguments, + the builder will default to a target name of + compile_commands.json. - If you specify a single file as below - -env.CompilationDatabase('my_output.json') - - SCons will automatically use that as the target file. - If you specify more than one source, the source list will be ignored. + If called with a single positional argument, + &scons; will "deduce" the target name from that source + argument, giving it the same name, and then + ignore the source. + This is the usual way to call the builder if a + non-default target name is wanted. - You should not specify source files. The &b-CompilationDatabase; builder instruments SCons to collect them from all - the C, C++, assembly source/target pairs. - - - NOTE: You must load the &t-compilation_db; tool prior to specifying any part of your build or some source/target - files will not show up in your output file. + If called with either the target= + or source= keyword arguments, + the value of the argument is taken as the target name. + If called with both, the target= + value is used and source= is ignored. + If called with multiple sources, + the source list will be ignored, + since there is no way to deduce what the intent was; + in this case the default target name will be used. + + + You must load the &t-compilation_db; tool prior to specifying + any part of your build or some source/output + files will not show up in the compilation database. + + Available since &scons; 4.0. @@ -1206,58 +1231,83 @@ builder method. Package() env.Package() -Builds a Binary Package of the given source files. +Builds software distribution packages. +A Package is a container format which +includes files to install along with metadata. +Packaging is optional, and must be enabled by specifying +the &t-link-packaging; tool. For example: -env.Package(source = FindInstalledFiles()) +env = Environment(tools=['default', 'packaging']) + -Builds software distribution packages. -Packages consist of files to install and packaging information. -The former may be specified with the &source; parameter and may be left out, -in which case the &FindInstalledFiles; function will collect -all files that have an &b-Install; or &b-InstallAs; Builder attached. -If the ⌖ is not specified -it will be deduced from additional information given to this Builder. +&SCons; can build packages in a number of well known packaging formats. +The target package type may be selected with the +the &cv-link-PACKAGETYPE; construction variable +or the command line option. +The package type may be a list, in which case &SCons; will attempt +to build packages for each type in the list. Example: + + + +env.Package(PACKAGETYPE=['src_zip', 'src_targz'], ...other args...) + + + +The currently supported packagers are: + + + +msiMicrosoft Installer package +rpmRPM Package Manger package +ipkgItsy Package Management package +tarbz2bzip2-compressed tar file +targzgzip-compressed tar file +tarxzxz-compressed tar file +zipzip file +src_tarbz2bzip2-compressed tar file suitable as source to another packager +src_targzgzip-compressed tar file suitable as source to another packager +src_tarxzxz-compressed tar file suitable as source to another packager +src_zipzip file suitable as source to another packager + + + + -The packaging information is specified -with the help of construction variables documented below. -This information is called a tag to stress that -some of them can also be attached to files with the &Tag; function. -The mandatory ones will complain if they were not specified. -They vary depending on chosen target packager. +The file list to include in the package may be specified with +the &source; keyword argument. If omitted, +the &f-link-FindInstalledFiles; function is called behind the scenes +to select all files that have an &b-link-Install;, &b-link-InstallAs; +or &b-link-InstallVersionedLib; Builder attached. +If the ⌖ keyword argument is omitted, the target name(s) +will be deduced from the package type(s). -The target packager may be selected with the "PACKAGETYPE" command line -option or with the &cv-PACKAGETYPE; construction variable. Currently -the following packagers available: +The metadata comes partly from attributes of the files to be packaged, +and partly from packaging tags. +Tags can be passed as keyword arguments +to the &b-Package; builder call, +and may also be attached to files +(or more accurately, Nodes representing files) +with the &f-link-Tag; function. +Some package-level tags are mandatory, and will lead to errors if omitted. +The mandatory tags vary depending on the package type. + -
- -msi - Microsoft Installer -rpm - RPM Package Manger -ipkg - Itsy Package Management System -tarbz2 - bzip2 compressed tar -targz - gzip compressed tar -tarxz - xz compressed tar -zip - zip file -src_tarbz2 - bzip2 compressed tar source -src_targz - gzip compressed tar source -src_tarxz - xz compressed tar source -src_zip - zip file source - -
+ +While packaging, the builder uses a temporary location named +by the value of the &cv-link-PACKAGEROOT; variable - +the package sources are copied there before packaging. + -An updated list is always available under the -package_type option when -running scons --help -on a project that has packaging activated. +Packaging example: @@ -1275,6 +1325,21 @@ env.Package( SOURCE_URL="http://foo.org/foo-1.2.3.tar.gz", ) + + +In this example, the target /bin/my_program +created by the &b-Install; call would not be built by default +since it is not under the project top directory. +However, since no source +is specified to the &b-Package; builder, +it is selected for packaging by the default sources rule. +Since packaging is done using &cv-PACKAGEROOT;, no write is +actually done to the system's /bin directory, +and the target will be selected since +after rebasing to underneath &cv-PACKAGEROOT; it is now under +the top directory of the project. + +
diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index 1910505..2031006 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,8 +1,8 @@ % scons -Q cc -o f5.o -c f5.c -cc -o f1.o -c f1.c +cc -o f4.o -c f4.c cc -o f2.o -c f2.c cc -o f3.o -c f3.c -cc -o f4.o -c f4.c +cc -o f1.o -c f1.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/examples/troubleshoot_Dump_1.xml b/doc/generated/examples/troubleshoot_Dump_1.xml index cb0ab4a..0b7bd05 100644 --- a/doc/generated/examples/troubleshoot_Dump_1.xml +++ b/doc/generated/examples/troubleshoot_Dump_1.xml @@ -28,7 +28,7 @@ scons: Reading SConscript files ... 'DSUFFIXES': ['.d'], 'Dir': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, 'Dirs': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, - 'ENV': {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'}, + 'ENV': {'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin:/snap/bin'}, 'ESCAPE': <function escape at 0x700000>, 'File': <SCons.Defaults.Variable_Method_Caller object at 0x700000>, 'HOST_ARCH': None, @@ -73,6 +73,7 @@ scons: Reading SConscript files ... '__LDMODULEVERSIONFLAGS': '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}', '__RPATH': '$_RPATH', '__SHLIBVERSIONFLAGS': '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}', + '__lib_either_version_flag': <function __lib_either_version_flag at 0x700000>, '__libversionflags': <function __libversionflags at 0x700000>, '_concat': <function _concat at 0x700000>, '_defines': <function _defines at 0x700000>, diff --git a/doc/generated/examples/troubleshoot_Dump_2.xml b/doc/generated/examples/troubleshoot_Dump_2.xml index 5080822..ab18e58 100644 --- a/doc/generated/examples/troubleshoot_Dump_2.xml +++ b/doc/generated/examples/troubleshoot_Dump_2.xml @@ -91,7 +91,7 @@ scons: Reading SConscript files ... 'SHCXXCOM': '${TEMPFILE("$SHCXX $_MSVC_OUTPUT_FLAG /c $CHANGED_SOURCES ' '$SHCXXFLAGS $SHCCFLAGS $_CCCOMCOM","$SHCXXCOMSTR")}', 'SHCXXFLAGS': ['$CXXFLAGS'], - 'SHELL': 'command', + 'SHELL': None, 'SHLIBPREFIX': '', 'SHLIBSUFFIX': '.dll', 'SHOBJPREFIX': '$OBJPREFIX', @@ -117,6 +117,7 @@ scons: Reading SConscript files ... '__DSHLIBVERSIONFLAGS': '${__libversionflags(__env__,"DSHLIBVERSION","_DSHLIBVERSIONFLAGS")}', '__LDMODULEVERSIONFLAGS': '${__libversionflags(__env__,"LDMODULEVERSION","_LDMODULEVERSIONFLAGS")}', '__SHLIBVERSIONFLAGS': '${__libversionflags(__env__,"SHLIBVERSION","_SHLIBVERSIONFLAGS")}', + '__lib_either_version_flag': <function __lib_either_version_flag at 0x700000>, '__libversionflags': <function __libversionflags at 0x700000>, '_concat': <function _concat at 0x700000>, '_defines': <function _defines at 0x700000>, diff --git a/doc/generated/examples/troubleshoot_Dump_ENV_1.xml b/doc/generated/examples/troubleshoot_Dump_ENV_1.xml index 9fb88cf..1d00911 100644 --- a/doc/generated/examples/troubleshoot_Dump_ENV_1.xml +++ b/doc/generated/examples/troubleshoot_Dump_ENV_1.xml @@ -1,6 +1,6 @@ % scons scons: Reading SConscript files ... -{'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin'} +{'PATH': '/usr/local/bin:/opt/bin:/bin:/usr/bin:/snap/bin'} scons: done reading SConscript files. scons: Building targets ... scons: `.' is up to date. diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 6b90e1c..ad88b6b 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -2,5 +2,5 @@ cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/Users/bdbaddog/devel/scons/git/as_scons/scripts/scons.py", line 96, in <module> +File "/home/bdeegan/devel/scons/git/scons-pr-3553/scripts/scons.py", line 96, in <module> diff --git a/doc/generated/examples/troubleshoot_stacktrace_2.xml b/doc/generated/examples/troubleshoot_stacktrace_2.xml index 66a7abb..41e53c5 100644 --- a/doc/generated/examples/troubleshoot_stacktrace_2.xml +++ b/doc/generated/examples/troubleshoot_stacktrace_2.xml @@ -1,12 +1,12 @@ % scons -Q --debug=stacktrace scons: *** [prog.o] Source `prog.c' not found, needed by target `prog.o'. scons: internal stack trace: - File "SCons/Job.py", line 199, in start + File "SCons/Job.py", line 195, in start task.prepare() - File "SCons/Script/Main.py", line 190, in prepare + File "SCons/Script/Main.py", line 177, in prepare return SCons.Taskmaster.OutOfDateTask.prepare(self) - File "SCons/Taskmaster.py", line 195, in prepare + File "SCons/Taskmaster.py", line 186, in prepare executor.prepare() - File "SCons/Executor.py", line 429, in prepare + File "SCons/Executor.py", line 424, in prepare raise SCons.Errors.StopError(msg % (s, self.batches[0].targets[0])) diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index 9743daa..382315e 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -44,31 +44,22 @@ until the Action object is actually used. AddMethod(object, function, [name]) env.AddMethod(function, [name]) -When called with the -AddMethod() -form, -adds the specified -function -to the specified -object -as the specified method -name. -When called using the -&f-env-AddMethod; form, -adds the specified -function -to the construction environment -env -as the specified method -name. -In both cases, if -name -is omitted or -None, -the name of the -specified -function -itself is used for the method name. +Adds function to an object as a method. +function will be called with an instance +object as the first argument as for other methods. +If name is given, it is used as +the name of the new method, else the name of +function is used. + + +When the global function &f-AddMethod; is called, +the object to add the method to must be passed as the first argument; +typically this will be &Environment;, +in order to create a method which applies to all &consenvs; +subsequently constructed. +When called using the &f-env-AddMethod; form, +the method is added to the specified &consenv; only. +Added methods propagate through &f-env-Clone; calls. @@ -76,22 +67,17 @@ Examples: -# Note that the first argument to the function to -# be attached as a method must be the object through -# which the method will be called; the Python -# convention is to call it 'self'. +# Function to add must accept an instance argument. +# The Python convention is to call this 'self'. def my_method(self, arg): print("my_method() got", arg) -# Use the global AddMethod() function to add a method -# to the Environment class. This +# Use the global function to add a method to the Environment class: AddMethod(Environment, my_method) env = Environment() env.my_method('arg') -# Add the function as a method, using the function -# name for the method call. -env = Environment() +# Use the optional name argument to set the name of the method: env.AddMethod(my_method, 'other_method_name') env.other_method_name('another arg') @@ -106,13 +92,13 @@ are the same as those supported by the add_option method in the standard Python library module optparse, with a few additional capabilities noted below. See the documentation for -optparse +optparse for a thorough discussion of its option-processing capabities.
In addition to the arguments and values supported by the -optparse +optparse add_option method, &f-AddOption; allows setting the @@ -150,10 +136,10 @@ it will recognize , and so forth as long as there is no other option which could also match to the same abbreviation. Options added via -AddOption do not support +&f-AddOption; do not support the automatic recognition of abbreviations. Instead, to allow specific abbreviations, -include them in the &f-AddOption; call. +include them as synonyms in the &f-AddOption; call itself. @@ -169,7 +155,7 @@ options added with &f-AddOption;. The value may also be set using &f-SetOption; or -env.SetOption(), +&f-env.SetOption;, if conditions in a &SConscript; require overriding any default value. @@ -597,7 +583,7 @@ caching by calling &f-env-CacheDir;. -When derived-file caching +When derived-file caching is being used and &scons; finds a derived file that needs to be rebuilt, @@ -658,7 +644,7 @@ the first time a cache_dir is used for a build, or to bring a cache up to date after -a build with cache updating disabled +a build with cache updating disabled ( or ) has been done. @@ -1369,7 +1355,7 @@ Returns a JSON-formatted string representation of the environment. -If key is +If key is None (the default) the entire dictionary of &consvars; is serialized. If supplied, it is taken as the name of a &consvar; @@ -1471,6 +1457,14 @@ Return a new construction environment initialized with the specified key=value pairs. +The keyword arguments +parse_flags, +platform, +toolpath, +tools +and variables +are also specially recognized. +See the manpage section "Construction Environments" for more details. @@ -3341,8 +3335,8 @@ Return('val1 val2') - Scanner(function, [argument, keys, path_function, node_class, node_factory, scan_check, recursive]) - env.Scanner(function, [argument, keys, path_function, node_class, node_factory, scan_check, recursive]) + Scanner(function, [name, argument, skeys, path_function, node_class, node_factory, scan_check, recursive]) + env.Scanner(function, [name, argument, skeys, path_function, node_class, node_factory, scan_check, recursive]) Creates a Scanner object for the specified @@ -3636,57 +3630,75 @@ SConscript('bar/SConscript') # will chdir to bar - SConsignFile([file, dbm_module]) - env.SConsignFile([file, dbm_module]) + SConsignFile([name, dbm_module]) + env.SConsignFile([name, dbm_module]) -This tells -&scons; -to store all file signatures -in the specified database -file. -If the -file -name is omitted, -.sconsign -is used by default. -(The actual file name(s) stored on disk -may have an appropriated suffix appended -by the -dbm_module.) -If -file -is not an absolute path name, -the file is placed in the same directory as the top-level -&SConstruct; -file. +Specify where to store the &SCons; file signature database, +and which database format to use. +This may be useful to specify alternate +database files and/or file locations for different types of builds. + + +The optional name argument +is the base name of the database file(s). +If not an absolute path name, +these are placed relative to the directory containing the +top-level &SConstruct; file. +The default is +.sconsign. +The actual database file(s) stored on disk +may have an appropriate suffix appended +by the chosen +dbm_module + + +The optional dbm_module +argument specifies which +Python database module to use +for reading/writing the file. +The module must be imported first; +then the imported module name +is passed as the argument. +The default is a custom +SCons.dblite +module that uses pickled +Python data structures, +which works on all Python versions. +See documentation of the Python +dbm module +for other available types. + + +If called with no arguments, +the database will default to +.sconsign.dblite +in the top directory of the project, +which is also the default if +if &f-SConsignFile; is not called. + + +The setting is global, so the only difference +between the global function and the environment method form +is variable expansion on name. +There should only be one active call to this +function/method in a given build setup. - If -file -is +name +is set to None, -then &scons; will store file signatures in a separate .sconsign file in each directory, -not in one global database file. -(This was the default behavior -prior to SCons 0.96.91 and 0.97.) - - - -The optional -dbm_module -argument can be used to specify -which Python database module -The default is to use a custom -SCons.dblite -module that uses pickled -Python data structures, -and which works on all Python versions. +not in a single combined database file. +This is a backwards-compatibility meaure to support +what was the default behavior +prior to &SCons; 0.97 (i.e. before 2008). +Use of this mode is discouraged and may be +deprecated in a future &SCons; release. @@ -3695,20 +3707,25 @@ Examples: # Explicitly stores signatures in ".sconsign.dblite" -# in the top-level SConstruct directory (the -# default behavior). +# in the top-level SConstruct directory (the default behavior). SConsignFile() # Stores signatures in the file "etc/scons-signatures" # relative to the top-level SConstruct directory. +# SCons will add a database suffix to this name. SConsignFile("etc/scons-signatures") # Stores signatures in the specified absolute file name. +# SCons will add a database suffix to this name. SConsignFile("/home/me/SCons/signatures") # Stores signatures in a separate .sconsign file # in each directory. SConsignFile(None) + +# Stores signatures in a GNU dbm format .sconsign file +import dbm.gnu +SConsignFile(dbm_module=dbm.gnu) @@ -3731,123 +3748,132 @@ if 'FOO' not in env: env['FOO'] = 'foo' SetOption(name, value) env.SetOption(name, value) -This function provides a way to set a select subset of the scons command -line options from a SConscript file. The options supported are: - - - - - -clean - - -which corresponds to , -and ; - - - - -duplicate - - -which corresponds to ; - - - - -help - - -which corresponds to and ; - - - - -implicit_cache - - -which corresponds to ; - - - - -max_drift - - -which corresponds to ; - - - - -no_exec - - -which corresponds to , , -, -and ; - - - - -num_jobs - - -which corresponds to and ; - - - - -random - - -which corresponds to ; and - - - - -silent - - -which corresponds to . - - - - -no_progress - - -which corresponds to -Q. - - - Note: The initial progress output will still be output as this is done before the SConstruct/SConscript which contains the SetOption is processed - scons: Reading SConscript files ... - -Available since &scons; 4.0. - - - -stack_size - - -which corresponds to --stack-size. - - - - +Sets &scons; option variable name +to value. +These options are all also settable via +&scons; command-line options but the variable name +may differ from the command-line option name (see table). +A value set via command-line option will take +precedence over one set with &f-SetOption;, which +allows setting a project default in the scripts and +temporarily overriding it via command line. +Options which affect the reading and processing of SConscript files +are not settable this way, since those files must +be read in order to find the &f-SetOption; call. + + + +The settable variables with their associated command-line options are: + + + + + +VariableCommand-line options + + + +clean + +, , + + +diskcheck + + + + +duplicate + + + + +help + +, + + +implicit_cache + + + + + +max_drift + + + + +md5_chunksize + + + + +no_exec + +, , +, , + + + +no_progress + + + + +num_jobs + +, + + +random + + + + +silent + +. + + +stack_size + + + + +warn + +. + + + + + + +See the documentation in the manpage for the +corresponding command line option for information about each specific option. +Option values which are boolean in nature (that is, they are +either on or off) should be set to a true value (True, +1) or a false value (False, +0). + -See the documentation for the -corresponding command line option for information about each specific -option. +If no_progress is set via &f-SetOption; +there will still be initial progress output as &SCons; has +to start reading SConscript files before it can see the +&f-SetOption; in an SConscript file: +scons: Reading SConscript files ... + Example: -SetOption('max_drift', 1) +SetOption('max_drift', True) @@ -3909,6 +3935,12 @@ or &f-env-Clean; function. + + +This function returns the list of side effect Node objects that were successfully added. +If the list of side effects contained any side effects that had already been added, +they are not added and included in the returned list. + @@ -4054,7 +4086,7 @@ Annotates file or directory Nodes with information about how the &b-link-Package; Builder should package those files or directories. -All tags are optional. +All Node-level tags are optional. @@ -4062,12 +4094,11 @@ Examples: -# makes sure the built library will be installed with 0o644 file -# access mode -Tag( Library( 'lib.c' ), UNIX_ATTR="0o644" ) +# makes sure the built library will be installed with 644 file access mode +Tag(Library('lib.c'), UNIX_ATTR="0o644") # marks file2.txt to be a documentation file -Tag( 'file2.txt', DOC ) +Tag('file2.txt', DOC) @@ -4181,8 +4212,8 @@ def create(target, source, env): # A function that will write a 'prefix=$SOURCE' # string into the file name specified as the # $TARGET. - f = open(str(target[0]), 'wb') - f.write('prefix=' + source[0].get_contents()) + with open(str(target[0]), 'wb') as f: + f.write('prefix=' + source[0].get_contents()) # Fetch the prefix= argument, if any, from the command # line, and use /usr/local as the default. @@ -4213,90 +4244,75 @@ env.UpdateValue(target = Value(output), source = Value(input)) VariantDir(variant_dir, src_dir, [duplicate]) env.VariantDir(variant_dir, src_dir, [duplicate]) -Use the -&f-VariantDir; -function to create a copy of your sources in another location: -if a name under -variant_dir -is not found but exists under -src_dir, -the file or directory is copied to -variant_dir. -Target files can be built in a different directory -than the original sources by simply refering to the sources (and targets) -within the variant tree. - - - +Sets up an alternate build location. +When building in the variant_dir, +&SCons; backfills as needed with files from src_dir +to create a complete build directory. &f-VariantDir; can be called multiple times with the same src_dir to set up multiple builds with different options -(variants). +(variants). + + + The -src_dir -location must be in or underneath the SConstruct file's directory, and -variant_dir +variant +location must be in or underneath the project top directory, +and src_dir may not be underneath -src_dir. - +variant_dir. -The default behavior is for -&scons; -to physically duplicate the source files in the variant tree. +By default, &SCons; +physically duplicates the source files and SConscript files +as needed into the variant tree. Thus, a build performed in the variant tree is guaranteed to be identical to a build performed in the source tree even if intermediate source files are generated during the build, -or preprocessors or other scanners search for included files +or if preprocessors or other scanners search for included files relative to the source file, -or individual compilers or other invoked tools are hard-coded +or if individual compilers or other invoked tools are hard-coded to put derived files in the same directory as source files. +Only the files &SCons; calculates are needed for the build are +duplicated into variant_dir. If possible on the platform, -the duplication is performed by linking rather than copying; -see also the +the duplication is performed by linking rather than copying. +This behavior is affected by the command-line option. -Moreover, only the files needed for the build are duplicated; -files and directories that are not used are not present in -variant_dir. -Duplicating the source tree may be disabled by setting the -duplicate +Duplicating the source files may be disabled by setting the +duplicate argument to -0 -(zero). +False. This will cause -&scons; +&SCons; to invoke Builders using the path names of source files in src_dir and the path names of derived files within variant_dir. -This is always more efficient than -duplicate=1, -and is usually safe for most builds -(but see above for cases that may cause problems). +This is more efficient than +duplicate=True, +and is safe for most builds; +revert to True +if it causes problems. -Note that &f-VariantDir; -works most naturally with a subsidiary SConscript file. -However, you would then call the subsidiary SConscript file -not in the source directory, but in the +works most naturally with used with a subsidiary SConscript file. +The subsidiary SConscript file is called as if it +were in variant_dir, regardless of the value of -duplicate. +duplicate. This is how you tell &scons; which variant of a source tree to build: @@ -4326,15 +4342,11 @@ Examples: # use names in the build directory, not the source directory VariantDir('build', 'src', duplicate=0) Program('build/prog', 'build/source.c') - - # this builds both the source and docs in a separate subtree VariantDir('build', '.', duplicate=0) SConscript(dirs=['build/src','build/doc']) - - # same as previous example, but only uses SConscript SConscript(dirs='src', variant_dir='build/src', duplicate=0) SConscript(dirs='doc', variant_dir='build/doc', duplicate=0) diff --git a/doc/generated/tools.gen b/doc/generated/tools.gen index 6353c6f..625e7d7 100644 --- a/doc/generated/tools.gen +++ b/doc/generated/tools.gen @@ -103,7 +103,7 @@ Set construction variables for the Clang C++ compiler. Sets up &b-link-CompilationDatabase; builder which generates a clang tooling compatible compilation database. - Sets: &cv-link-COMPILATIONDB_COMSTR;, &cv-link-COMPILATIONDB_USE_ABSPATH;. + Sets: &cv-link-COMPILATIONDB_COMSTR;, &cv-link-COMPILATIONDB_PATH_FILTER;, &cv-link-COMPILATIONDB_USE_ABSPATH;. cvf @@ -221,7 +221,7 @@ source code (see Sets construction variables for D language compiler DMD. -Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. +Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. docbook @@ -447,7 +447,7 @@ Set construction variables for the &gcc; C compiler. Sets construction variables for the D language compiler GDC. -Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. +Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. gettext @@ -646,7 +646,7 @@ Sets construction variables for the &latex; utility. Sets construction variables for the D language compiler LDC2. -Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DShLibSonameGenerator;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSION;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. +Sets: &cv-link-DC;, &cv-link-DCOM;, &cv-link-DDEBUG;, &cv-link-DDEBUGPREFIX;, &cv-link-DDEBUGSUFFIX;, &cv-link-DFILESUFFIX;, &cv-link-DFLAGPREFIX;, &cv-link-DFLAGS;, &cv-link-DFLAGSUFFIX;, &cv-link-DINCPREFIX;, &cv-link-DINCSUFFIX;, &cv-link-DLIB;, &cv-link-DLIBCOM;, &cv-link-DLIBDIRPREFIX;, &cv-link-DLIBDIRSUFFIX;, &cv-link-DLIBFLAGPREFIX;, &cv-link-DLIBFLAGSUFFIX;, &cv-link-DLIBLINKPREFIX;, &cv-link-DLIBLINKSUFFIX;, &cv-link-DLINK;, &cv-link-DLINKCOM;, &cv-link-DLINKFLAGPREFIX;, &cv-link-DLINKFLAGS;, &cv-link-DLINKFLAGSUFFIX;, &cv-link-DPATH;, &cv-link-DRPATHPREFIX;, &cv-link-DRPATHSUFFIX;, &cv-link-DVERPREFIX;, &cv-link-DVERSIONS;, &cv-link-DVERSUFFIX;, &cv-link-SHDC;, &cv-link-SHDCOM;, &cv-link-SHDLIBVERSIONFLAGS;, &cv-link-SHDLINK;, &cv-link-SHDLINKCOM;, &cv-link-SHDLINKFLAGS;. lex @@ -799,14 +799,9 @@ Sets construction variables for the packaging -A framework for building binary and source packages. - - - - - Packaging - Sets construction variables for the &b-Package; Builder. +If this tool is enabled, the +command-line option is also enabled. diff --git a/doc/generated/tools.mod b/doc/generated/tools.mod index c32d6ff..78aa9ef 100644 --- a/doc/generated/tools.mod +++ b/doc/generated/tools.mod @@ -80,7 +80,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwld"> nasm"> packaging"> -Packaging"> pdf"> pdflatex"> pdftex"> @@ -186,7 +185,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. mwld"> nasm"> packaging"> -Packaging"> pdf"> pdflatex"> pdftex"> diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index f19c14c..fb79fd9 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -324,28 +324,38 @@ and typesetter and the LaTeX structured formatter and typesetter. A dictionary mapping the names of the builders -available through this environment -to underlying Builder objects. -Builders named -Alias, CFile, CXXFile, DVI, Library, Object, PDF, PostScript, and Program -are available by default. -If you initialize this variable when an -Environment is created: +available through the &consenv; to underlying Builder objects. +Custom builders need to be added to this to make them available. + + + +A platform-dependent default list of builders such as +&b-link-Program;, &b-link-Library; etc. is used to +populate this &consvar; when the &consenv; is initialized +via the presence/absence of the tools those builders depend on. +&cv-BUILDERS; can be examined to learn which builders will +actually be available at run-time. + + + +Note that if you initialize this &consvar; through +assignment when the &consenv; is created, +that value for &cv-BUILDERS; will override any defaults: -env = Environment(BUILDERS = {'NewBuilder' : foo}) +bld = Builder(action='foobuild < $SOURCE > $TARGET') +env = Environment(BUILDERS={'NewBuilder': bld}) -the default Builders will no longer be available. -To use a new Builder object in addition to the default Builders, +To instead use a new Builder object in addition to the default Builders, add your new Builder object like this: env = Environment() -env.Append(BUILDERS = {'NewBuilder' : foo}) +env.Append(BUILDERS={'NewBuilder': bld}) @@ -354,7 +364,7 @@ or this: env = Environment() -env['BUILDERS']['NewBuilder'] = foo +env['BUILDERS']['NewBuilder'] = bld @@ -562,7 +572,24 @@ section of the RPM COMPILATIONDB_COMSTR - The string displayed when CompilationDatabase builder's action is run. + The string displayed when the &b-CompilationDatabase; + builder's action is run. + + + + + + COMPILATIONDB_PATH_FILTER + + + A string which instructs &b-link-CompilationDatabase; to + only include entries where the output member + matches the pattern in the filter string using fnmatch, which + uses glob style wildcards. + + + + The default value is an empty string '', which disables filtering. @@ -571,9 +598,10 @@ section of the RPM COMPILATIONDB_USE_ABSPATH - This is a boolean flag to instruct &b-link-CompilationDatabase; to - write the file and target members - in the compilation database with absolute or relative paths. + A boolean flag to instruct &b-link-CompilationDatabase; + whether to write the file and + output members + in the compilation database using absolute or relative paths. The default value is False (use relative paths) @@ -1479,15 +1507,6 @@ DRPATHSUFFIX. - - - DShLibSonameGenerator - - -DShLibSonameGenerator. - - - DSUFFIXES @@ -1696,7 +1715,7 @@ If not set, then &cv-link-F03COM; or &cv-link-FORTRANCOM; The list of file extensions for which the F03 dialect will be used. By -default, this is ['.f03'] +default, this is ['.f03'] @@ -1834,7 +1853,7 @@ If not set, then &cv-link-F03PPCOM; or &cv-link-FORTRANPPCOM; The list of file extensions for which the compilation + preprocessor pass for -F03 dialect will be used. By default, this is empty +F03 dialect will be used. By default, this is empty. @@ -1884,7 +1903,7 @@ If not set, then &cv-link-F08COM; or &cv-link-FORTRANCOM; The list of file extensions for which the F08 dialect will be used. By -default, this is ['.f08'] +default, this is ['.f08'] @@ -2022,7 +2041,7 @@ If not set, then &cv-link-F08PPCOM; or &cv-link-FORTRANPPCOM; The list of file extensions for which the compilation + preprocessor pass for -F08 dialect will be used. By default, this is empty +F08 dialect will be used. By default, this is empty. @@ -2072,7 +2091,7 @@ If not set, then &cv-link-F77COM; or &cv-link-FORTRANCOM; The list of file extensions for which the F77 dialect will be used. By -default, this is ['.f77'] +default, this is ['.f77'] @@ -2210,7 +2229,7 @@ If not set, then &cv-link-F77PPCOM; or &cv-link-FORTRANPPCOM; The list of file extensions for which the compilation + preprocessor pass for -F77 dialect will be used. By default, this is empty +F77 dialect will be used. By default, this is empty. @@ -2260,7 +2279,7 @@ If not set, then &cv-link-F90COM; or &cv-link-FORTRANCOM; The list of file extensions for which the F90 dialect will be used. By -default, this is ['.f90'] +default, this is ['.f90'] @@ -2397,7 +2416,7 @@ If not set, then &cv-link-F90PPCOM; or &cv-link-FORTRANPPCOM; The list of file extensions for which the compilation + preprocessor pass for -F90 dialect will be used. By default, this is empty +F90 dialect will be used. By default, this is empty. @@ -2447,7 +2466,7 @@ If not set, then &cv-link-F95COM; or &cv-link-FORTRANCOM; The list of file extensions for which the F95 dialect will be used. By -default, this is ['.f95'] +default, this is ['.f95'] @@ -2585,7 +2604,7 @@ If not set, then &cv-link-F95PPCOM; or &cv-link-FORTRANPPCOM; The list of file extensions for which the compilation + preprocessor pass for -F95 dialect will be used. By default, this is empty +F95 dialect will be used. By default, this is empty. @@ -2643,7 +2662,7 @@ If not set, then &cv-link-FORTRANCOM; The list of file extensions for which the FORTRAN dialect will be used. By -default, this is ['.f', '.for', '.ftn'] +default, this is ['.f', '.for', '.ftn'] @@ -2859,7 +2878,7 @@ If not set, then &cv-link-FORTRANPPCOM; The list of file extensions for which the compilation + preprocessor pass for -FORTRAN dialect will be used. By default, this is ['.fpp', '.FPP'] +FORTRAN dialect will be used. By default, this is ['.fpp', '.FPP'] @@ -3046,7 +3065,7 @@ is -dNOPAUSE -dBATCH -sDEVICE=pdfwrite Currently only set for Win32. -Sets the host architecture for Visual Studio compiler. If not set, +Sets the host architecture for the Visual C++ compiler. If not set, default to the detected host architecture: note that this may depend on the python you are using. This variable must be passed as an argument to the Environment() @@ -4589,7 +4608,7 @@ will be compiled separately. MSVC_USE_SCRIPT -Use a batch script to set up Microsoft Visual Studio compiler. +Use a batch script to set up the Microsoft Visual C++ compiler. @@ -4608,7 +4627,7 @@ This can be useful to force the use of a compiler version that Setting &cv-MSVC_USE_SCRIPT; to None bypasses the Visual Studio autodetection entirely; -use this if you are running SCons in a Visual Studio cmd +use this if you are running SCons in a Visual Studio cmd 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. @@ -4627,8 +4646,8 @@ Build libraries for a Universal Windows Platform (UWP) Application. -If &cv-MSVC_UWP_APP; is set, the Visual Studio environment will be set up to point -to the Windows Store compatible libraries and Visual Studio runtimes. In doing so, +If &cv-MSVC_UWP_APP; is set, the Visual C++ environment will be set up to point +to the Windows Store compatible libraries and Visual C++ runtimes. In doing so, any libraries that are built will be able to be used in a UWP App and published to the Windows Store. This flag will only have an effect with Visual Studio 2015 or later. @@ -4654,7 +4673,7 @@ Sets the preferred version of Microsoft Visual C/C++ to use. 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. -This variable must be passed as an argument to the Environment() +This variable must be passed as an argument to the &f-link-Environment; constructor; setting it later has no effect. @@ -5129,27 +5148,13 @@ placed if applicable. The default value is "$NAME-$VERSION". PACKAGETYPE -Selects the package type to build. Currently these are available: +Selects the package type to build when using the &b-link-Package; +builder. May be a string or list of strings. See the docuentation +for the builder for the currently supported types. -
- -msi - Microsoft Installer -rpm - RPM Package Manger -ipkg - Itsy Package Management System -tarbz2 - bzip2 compressed tar -targz - gzip compressed tar -tarxz - xz compressed tar -zip - zip file -src_tarbz2 - bzip2 compressed tar source -src_targz - gzip compressed tar source -src_tarxz - xz compressed tar source -src_zip - zip file source - -
- -This may be overridden with the +&cv-PACKAGETYPE; may be overridden with the command line option.
@@ -5191,7 +5196,7 @@ env['PCH'] = 'StdAfx.pch' The command line used by the -&b-PCH; +&b-link-PCH; builder to generated a precompiled header. @@ -5212,8 +5217,8 @@ If this is not set, then &cv-link-PCHCOM; (the command line) is displayed. A construction variable that, when expanded, -adds the /yD flag to the command line -only if the &cv-PDB; construction variable is set. +adds the flag to the command line +only if the &cv-link-PDB; construction variable is set. @@ -6056,9 +6061,9 @@ for specifying directories to be searched by the resource compiler. The value of &cv-RCINCFLAGS; is created by respectively prepending and appending -&cv-RCINCPREFIX; and &cv-RCINCSUFFIX; +&cv-link-RCINCPREFIX; and &cv-link-RCINCSUFFIX; to the beginning and end -of each directory in &cv-CPPPATH;. +of each directory in &cv-link-CPPPATH;.
@@ -6070,8 +6075,8 @@ of each directory in &cv-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-CPPPATH; construction variable -when the &cv-RCINCFLAGS; variable is expanded. +in the &cv-link-CPPPATH; construction variable +when the &cv-link-RCINCFLAGS; variable is expanded. @@ -6083,8 +6088,8 @@ when the &cv-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-CPPPATH; construction variable -when the &cv-RCINCFLAGS; variable is expanded. +in the &cv-link-CPPPATH; construction variable +when the &cv-link-RCINCFLAGS; variable is expanded. @@ -6498,21 +6503,14 @@ See also &cv-link-DCOMSTR; for compiling to static objects. - - - SHDLIBVERSION - - -SHDLIBVERSION. - - - SHDLIBVERSIONFLAGS -SHDLIBVERSIONFLAGS. +Extra flags added to &cv-link-SHDLINKCOM; when building versioned +&b-link-SharedLibrary;. These flags are only used when &cv-link-SHLIBVERSION; is +set. @@ -7292,6 +7290,25 @@ for more information). + + + SOVERSION + + +This will construct the SONAME using on the base library name +(test in the example below) and use specified SOVERSION +to create SONAME. + +env.SharedLibrary('test', 'test.c', SHLIBVERSION='0.1.2', SOVERSION='2') + +The variable is used, for example, by &t-link-gnulink; linker tool. + + +In the example above SONAME would be libtest.so.2 +which would be a symlink and point to libtest.so.0.1.2 + + + SPAWN @@ -7672,7 +7689,7 @@ for more information). Currently only set for Win32. -Sets the target architecture for Visual Studio compiler (i.e. the arch +Sets the target architecture for the Visual C++ compiler (i.e. the arch of the binaries generated by the compiler). If not set, default to &cv-link-HOST_ARCH;, or, if that is unset, to the architecture of the running machine's OS (note that the python build or architecture has no @@ -7699,8 +7716,8 @@ for 32-bit targets and and ia64 (Itanium) for 64-bit targets. Note that not all target architectures are -supported for all Visual Studio / MSVC versions -check the relevant Microsoft documentation. +supported for all Visual Studio / MSVC versions. +Check the relevant Microsoft documentation. diff --git a/doc/generated/variables.mod b/doc/generated/variables.mod index 4ef5e88..56b1d52 100644 --- a/doc/generated/variables.mod +++ b/doc/generated/variables.mod @@ -47,6 +47,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $CHANGED_TARGETS"> $CHANGELOG"> $COMPILATIONDB_COMSTR"> +$COMPILATIONDB_PATH_FILTER"> $COMPILATIONDB_USE_ABSPATH"> $_concat"> $CONFIGUREDIR"> @@ -118,7 +119,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $DPATH"> $DRPATHPREFIX"> $DRPATHSUFFIX"> -$DShLibSonameGenerator"> $DSUFFIXES"> $DVERPREFIX"> $DVERSIONS"> @@ -461,7 +461,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $SHDC"> $SHDCOM"> $SHDCOMSTR"> -$SHDLIBVERSION"> $SHDLIBVERSIONFLAGS"> $SHDLINK"> $SHDLINKCOM"> @@ -521,6 +520,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $SOURCE"> $SOURCE_URL"> $SOURCES"> +$SOVERSION"> $SPAWN"> $STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME"> $SUBST_DICT"> @@ -690,6 +690,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $CHANGED_TARGETS"> $CHANGELOG"> $COMPILATIONDB_COMSTR"> +$COMPILATIONDB_PATH_FILTER"> $COMPILATIONDB_USE_ABSPATH"> $_concat"> $CONFIGUREDIR"> @@ -761,7 +762,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $DPATH"> $DRPATHPREFIX"> $DRPATHSUFFIX"> -$DShLibSonameGenerator"> $DSUFFIXES"> $DVERPREFIX"> $DVERSIONS"> @@ -1104,7 +1104,6 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $SHDC"> $SHDCOM"> $SHDCOMSTR"> -$SHDLIBVERSION"> $SHDLIBVERSIONFLAGS"> $SHDLINK"> $SHDLINKCOM"> @@ -1164,6 +1163,7 @@ THIS IS AN AUTOMATICALLY-GENERATED FILE. DO NOT EDIT. $SOURCE"> $SOURCE_URL"> $SOURCES"> +$SOVERSION"> $SPAWN"> $STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME"> $SUBST_DICT"> -- cgit v0.12 From f29e0abc88094661b9508986e346c07966e8fcfb Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 23:31:52 +0000 Subject: [ci skip] Add that we no longer automatically disable setting SONAME on OpenBSD. Looks like OpenBSD changed their practice on this in 2017 --- CHANGES.txt | 1 + RELEASE.txt | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index 4681889..a09c35c 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -30,6 +30,7 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Fix Issue #3759 - include scons.1, sconsign.1, scons-time.1 manpages in sdist and wheel packages. - Change SCons's build so the generated `SCons/__init__.py` is no longer removed by `scons -c` - Completely rewrote versioned shared libraries logic. Added support for SOVERSION via dmoody's initial PR #3733 + - No longer automatically disable setting SONAME on shared libraries on OpenBSD. From Michał Górny: - Fix dvipdf test failure due to passing incorrect flag to dvipdf. diff --git a/RELEASE.txt b/RELEASE.txt index 4e899dc..c78a581 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -45,6 +45,8 @@ - /snap/bin is added to the default search path for the 'posix' platform. - Completely rewrote versioned shared libraries logic. - Added support for SOVERSION + - No longer automatically disable setting SONAME on shared libraries on OpenBSD. + FIXES -- cgit v0.12 From e66a758ad087334076fb098993b7ee67ebd4dc61 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 18:12:46 -0800 Subject: New solution to issue described in PR 3114. This should resolve an issue when creating a new cachedir and building -j > 1 which can cause a race condition --- CHANGES.txt | 5 +++++ SCons/Environment.py | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index a09c35c..887608e 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -31,6 +31,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Change SCons's build so the generated `SCons/__init__.py` is no longer removed by `scons -c` - Completely rewrote versioned shared libraries logic. Added support for SOVERSION via dmoody's initial PR #3733 - No longer automatically disable setting SONAME on shared libraries on OpenBSD. + - Fix race condition bug when initializing a scons cache directory at the + same time from multiple threads or processes. Problem described in PR #3114. + This is a simpler fix which should avoid some problems identified with the initial PR. + (Credit to Fredrik Medley for reporting the issue, the initial PR, and discussing and testing + this solution) From Michał Górny: - Fix dvipdf test failure due to passing incorrect flag to dvipdf. diff --git a/SCons/Environment.py b/SCons/Environment.py index 312530a..89bfa76 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -2000,6 +2000,11 @@ class Base(SubstitutionEnvironment): path = self.subst(path) self._CacheDir_path = path + # Now initialized the CacheDir and prevent a race condition which can + # happen when there's no existing cache dir and you are building with + # multiple threads, but initializing it before the task walk starts + self.get_CacheDir() + def Clean(self, targets, files): global CleanTargets tlist = self.arg2nodes(targets, self.fs.Entry) -- cgit v0.12 From 76abaccb97274694d78ba5050e32efcb2f28869c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 21:16:19 -0800 Subject: update cachedir tests to workin a test.workpath(), and also verify that the config file is constructed when CacheDir() is called --- SCons/EnvironmentTests.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/SCons/EnvironmentTests.py b/SCons/EnvironmentTests.py index e57807b..6d0ef82 100644 --- a/SCons/EnvironmentTests.py +++ b/SCons/EnvironmentTests.py @@ -2797,13 +2797,24 @@ def generate(env): def test_CacheDir(self): """Test the CacheDir() method""" - env = self.TestEnvironment(CD = 'CacheDir') - env.CacheDir('foo') - assert env._CacheDir_path == 'foo', env._CacheDir_path + test = TestCmd.TestCmd(workdir = '') + save = os.getcwd() + + test_cachedir = os.path.join(test.workpath(),'CacheDir') + test_cachedir_config = os.path.join(test_cachedir, 'config') + test_foo = os.path.join(test.workpath(), 'foo-cachedir') + test_foo_config = os.path.join(test_foo,'config') + + env = self.TestEnvironment(CD = test_cachedir) + + env.CacheDir(test_foo) + assert env._CacheDir_path == test_foo, env._CacheDir_path + assert os.path.isfile(test_foo_config), "No file %s"%test_foo_config env.CacheDir('$CD') - assert env._CacheDir_path == 'CacheDir', env._CacheDir_path + assert env._CacheDir_path == test_cachedir, env._CacheDir_path + assert os.path.isfile(test_cachedir_config), "No file %s"%test_cachedir_config def test_Clean(self): """Test the Clean() method""" -- cgit v0.12 From fa24170ac8434d289d1a3061f88eb0556671032e Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 15 Jan 2021 21:19:34 -0800 Subject: resolve sider issue --- SCons/EnvironmentTests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/SCons/EnvironmentTests.py b/SCons/EnvironmentTests.py index 6d0ef82..6e65f54 100644 --- a/SCons/EnvironmentTests.py +++ b/SCons/EnvironmentTests.py @@ -2799,7 +2799,6 @@ def generate(env): """Test the CacheDir() method""" test = TestCmd.TestCmd(workdir = '') - save = os.getcwd() test_cachedir = os.path.join(test.workpath(),'CacheDir') test_cachedir_config = os.path.join(test_cachedir, 'config') -- cgit v0.12 From 8b0079f4d48e8a60aaa4b5f8ddd78cccc0c84e79 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 16 Jan 2021 07:19:53 -0700 Subject: Update doc uses of CCFLAGS to CPPDEFINES [ci skip] After discussion, it seemed like we should set a proper example, so the Append and Prepend examples that used *FLAGS to set a -Dstring value now use CPPDEFINES (without the -D). Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 2 +- doc/user/environments.xml | 16 ++++++++++------ doc/user/sconf.xml | 8 ++++---- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 688225b..ea38469 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -3560,7 +3560,7 @@ if not conf.CheckCHeader("math.h"): Exit(1) if conf.CheckLibWithHeader("qt", "qapp.h", "c++", "QApplication qapp(0,0);"): # do stuff for qt - usage, e.g. - conf.env.Append(CPPFLAGS="-DWITH_QT") + conf.env.Append(CPPDEFINES="WITH_QT") env = conf.Finish() diff --git a/doc/user/environments.xml b/doc/user/environments.xml index 5bcffbc..405fcfa 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -1420,8 +1420,8 @@ env.SetDefault(SPECIAL_FLAG='-extra-option') -env = Environment(CCFLAGS = ['-DMY_VALUE']) -env.Append(CCFLAGS = ['-DLAST']) +env = Environment(CPPDEFINES=['MY_VALUE']) +env.Append(CPPDEFINES=['LAST']) env.Program('foo.c') @@ -1431,7 +1431,9 @@ int main() { } - &SCons; then supplies both the -DMY_VALUE and + &SCons; then adjusts both the &CPPDEFINES; values with the correct + prefix/suffix, so that on Linux or POSIX, it will emit the + -DMY_VALUE and -DLAST flags when compiling the object file: @@ -1520,8 +1522,8 @@ env.AppendUnique(CCFLAGS=['-g']) -env = Environment(CCFLAGS=['-DMY_VALUE']) -env.Prepend(CCFLAGS=['-DFIRST']) +env = Environment(CPPDEFINES=['MY_VALUE']) +env.Prepend(CPPDEFINES=['FIRST']) env.Program('foo.c') @@ -1531,7 +1533,9 @@ int main() { } - &SCons; then supplies both the -DFIRST and + &SCons; then adjusts both the &CPPDEFINES; values with the correct + prefix/suffix, so that on Linux or POSIX, it will emit the + -DFIRST and -DMY_VALUE flags when compiling the object file: diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml index 7d86e6f..e00f4d2 100644 --- a/doc/user/sconf.xml +++ b/doc/user/sconf.xml @@ -166,7 +166,7 @@ if not conf.CheckCHeader('math.h'): print('Math.h must be installed!') Exit(1) if conf.CheckCHeader('foo.h'): - conf.env.Append(CCFLAGS='-DHAS_FOO_H') + conf.env.Append(CPPDEFINES='HAS_FOO_H') env = conf.Finish() @@ -221,7 +221,7 @@ env = Environment() conf = Configure(env) if not conf.CheckFunc('strcpy'): print('Did not find strcpy(), using local version') - conf.env.Append(CCFLAGS='-Dstrcpy=my_local_strcpy') + conf.env.Append(CPPDEFINES='strcpy=my_local_strcpy') env = conf.Finish() @@ -295,7 +295,7 @@ env = Environment() conf = Configure(env) if not conf.CheckType('off_t'): print('Did not find off_t typedef, assuming int') - conf.env.Append(CCFLAGS='-Doff_t=int') + conf.env.Append(CPPDEFINES='off_t=int') env = conf.Finish() @@ -314,7 +314,7 @@ env = Environment() conf = Configure(env) if not conf.CheckType('off_t', '#include <sys/types.h>\n'): print('Did not find off_t typedef, assuming int') - conf.env.Append(CCFLAGS='-Doff_t=int') + conf.env.Append(CPPDEFINES='off_t=int') env = conf.Finish() -- cgit v0.12 From ea7f260bead374ee572763093ad8268233f335fa Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 16 Jan 2021 13:59:06 -0800 Subject: Ensure that when user runs scons -n/--no_exec the CacheDir's config file is not created --- SCons/CacheDir.py | 1 - SCons/Environment.py | 11 ++++++----- SCons/EnvironmentTests.py | 12 +++++++++++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/SCons/CacheDir.py b/SCons/CacheDir.py index 879c21b..d0c7e5f 100644 --- a/SCons/CacheDir.py +++ b/SCons/CacheDir.py @@ -194,7 +194,6 @@ class CacheDir: msg = "Failed to read cache configuration for " + path raise SCons.Errors.SConsEnvironmentError(msg) - def CacheDebug(self, fmt, target, cachefile): if cache_debug != self.current_cache_debug: if cache_debug == '-': diff --git a/SCons/Environment.py b/SCons/Environment.py index 89bfa76..9e2870c 100644 --- a/SCons/Environment.py +++ b/SCons/Environment.py @@ -1995,15 +1995,16 @@ class Base(SubstitutionEnvironment): return SCons.Builder.Builder(**nkw) def CacheDir(self, path): - import SCons.CacheDir if path is not None: path = self.subst(path) self._CacheDir_path = path - # Now initialized the CacheDir and prevent a race condition which can - # happen when there's no existing cache dir and you are building with - # multiple threads, but initializing it before the task walk starts - self.get_CacheDir() + if SCons.Action.execute_actions: + # Only initialize the CacheDir if -n/-no_exec was NOT specified. + # Now initialized the CacheDir and prevent a race condition which can + # happen when there's no existing cache dir and you are building with + # multiple threads, but initializing it before the task walk starts + self.get_CacheDir() def Clean(self, targets, files): global CleanTargets diff --git a/SCons/EnvironmentTests.py b/SCons/EnvironmentTests.py index 6e65f54..a67ed83 100644 --- a/SCons/EnvironmentTests.py +++ b/SCons/EnvironmentTests.py @@ -31,7 +31,6 @@ import unittest from collections import UserDict as UD, UserList as UL import TestCmd -import TestUnit from SCons.Environment import ( Environment, @@ -42,6 +41,7 @@ from SCons.Environment import ( ) import SCons.Warnings + def diff_env(env1, env2): s1 = "env1 = {\n" s2 = "env2 = {\n" @@ -2804,6 +2804,8 @@ def generate(env): test_cachedir_config = os.path.join(test_cachedir, 'config') test_foo = os.path.join(test.workpath(), 'foo-cachedir') test_foo_config = os.path.join(test_foo,'config') + test_foo1 = os.path.join(test.workpath(), 'foo1-cachedir') + test_foo1_config = os.path.join(test_foo1, 'config') env = self.TestEnvironment(CD = test_cachedir) @@ -2815,6 +2817,14 @@ def generate(env): assert env._CacheDir_path == test_cachedir, env._CacheDir_path assert os.path.isfile(test_cachedir_config), "No file %s"%test_cachedir_config + # Now verify that -n/-no_exec wil prevent the CacheDir/config from being created + import SCons.Action + SCons.Action.execute_actions = False + env.CacheDir(test_foo1) + assert env._CacheDir_path == test_foo1, env._CacheDir_path + assert not os.path.isfile(test_foo1_config), "No file %s"%test_foo1_config + + def test_Clean(self): """Test the Clean() method""" env = self.TestEnvironment(FOO = 'fff', BAR = 'bbb') -- cgit v0.12 From fda865786b2d82ee906240ec11c30c36624698c9 Mon Sep 17 00:00:00 2001 From: David H <1810493+djh82@users.noreply.github.com> Date: Wed, 13 Jan 2021 09:59:10 +0000 Subject: feat: Adds ZIP_OVERRIDE_TIMESTAMP --- CHANGES.txt | 5 +++ SCons/Tool/zip.py | 48 ++++++++++++++++++++------- SCons/Tool/zip.xml | 16 +++++++++ test/ZIP/ZIP.py | 41 +++++------------------ test/ZIP/ZIPROOT.py | 46 ++++++++------------------ test/ZIP/ZIP_OVERRIDE_TIMESTAMP.py | 68 ++++++++++++++++++++++++++++++++++++++ testing/framework/TestSCons.py | 36 ++++++++++++++++++-- 7 files changed, 179 insertions(+), 81 deletions(-) create mode 100644 test/ZIP/ZIP_OVERRIDE_TIMESTAMP.py diff --git a/CHANGES.txt b/CHANGES.txt index 133fcb9..c1d7fd9 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -43,6 +43,11 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Change Environment.SideEffect() to not add duplicate side effects. NOTE: The list of returned side effect Nodes will not include any duplicate side effect Nodes. + From David H: + - Add ZIP_OVERRIDE_TIMESTAMP env option to Zip builder which allows for overriding of the file + modification times in the archive. + - Fix Zip builder not rebuilding when ZIPROOT env option was changed. + From Jason Kenny - Fix python3 crash when Value node get_text_content when child content does not have decode() NOTE: If you depend on Value node's get_text_content returning concatenated contents of it's diff --git a/SCons/Tool/zip.py b/SCons/Tool/zip.py index cbf2c16..f3d38fe 100644 --- a/SCons/Tool/zip.py +++ b/SCons/Tool/zip.py @@ -8,8 +8,9 @@ selection method. """ +# MIT License # -# __COPYRIGHT__ +# 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 @@ -29,39 +30,62 @@ selection method. # 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 os.path +import os import SCons.Builder import SCons.Defaults import SCons.Node.FS import SCons.Util +import time import zipfile + zip_compression = zipfile.ZIP_DEFLATED -def zip(target, source, env): - compression = env.get('ZIPCOMPRESSION', 0) - zf = zipfile.ZipFile(str(target[0]), 'w', compression) +def _create_zipinfo_for_file(fname, arcname, date_time, compression): + st = os.stat(fname) + if not date_time: + mtime = time.localtime(st.st_mtime) + date_time = mtime[0:6] + zinfo = zipfile.ZipInfo(filename=arcname, date_time=date_time) + zinfo.external_attr = (st.st_mode & 0xFFFF) << 16 # Unix attributes + zinfo.compress_type = compression + zinfo.file_size = st.st_size + return zinfo + + +def zip_builder(target, source, env): + compression = env.get('ZIPCOMPRESSION', zipfile.ZIP_STORED) + zip_root = str(env.get('ZIPROOT', '')) + date_time = env.get('ZIP_OVERRIDE_TIMESTAMP') + + files = [] for s in source: if s.isdir(): for dirpath, dirnames, filenames in os.walk(str(s)): for fname in filenames: path = os.path.join(dirpath, fname) if os.path.isfile(path): - zf.write(path, os.path.relpath(path, str(env.get('ZIPROOT', '')))) + files.append(path) else: - zf.write(str(s), os.path.relpath(str(s), str(env.get('ZIPROOT', '')))) - zf.close() + files.append(str(s)) + + with zipfile.ZipFile(str(target[0]), 'w', compression) as zf: + for fname in files: + arcname = os.path.relpath(fname, zip_root) + # TODO: Switch to ZipInfo.from_file when 3.6 becomes the base python version + zinfo = _create_zipinfo_for_file(fname, arcname, date_time, compression) + with open(fname, "rb") as f: + zf.writestr(zinfo, f.read()) + # Fix PR #3569 - If you don't specify ZIPCOM and ZIPCOMSTR when creating # env, then it will ignore ZIPCOMSTR set afterwards. -zipAction = SCons.Action.Action(zip, "$ZIPCOMSTR", varlist=['ZIPCOMPRESSION']) +zipAction = SCons.Action.Action(zip_builder, "$ZIPCOMSTR", + varlist=['ZIPCOMPRESSION', 'ZIPROOT', 'ZIP_OVERRIDE_TIMESTAMP']) ZipBuilder = SCons.Builder.Builder(action=SCons.Action.Action('$ZIPCOM', '$ZIPCOMSTR'), source_factory=SCons.Node.FS.Entry, diff --git a/SCons/Tool/zip.xml b/SCons/Tool/zip.xml index 8cf03f4..f9f01d9 100644 --- a/SCons/Tool/zip.xml +++ b/SCons/Tool/zip.xml @@ -164,4 +164,20 @@ containing a file with the name
+ + + + +An optional timestamp which overrides the last modification time of +the file when stored inside the Zip archive. This is a tuple of six values: + +Year (>= 1980) +Month (one-based) +Day of month (one-based) +Hours (zero-based) +Minutes (zero-based) +Seconds (zero-based) + + + diff --git a/test/ZIP/ZIP.py b/test/ZIP/ZIP.py index f842caf..b79173c 100644 --- a/test/ZIP/ZIP.py +++ b/test/ZIP/ZIP.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 os import stat @@ -33,30 +32,6 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -try: - import zipfile -except ImportError: - x = "Python version has no 'ziplib' module; skipping tests.\n" - test.skip_test(x) - -def zipfile_contains(zipfilename, names): - """Returns True if zipfilename contains all the names, False otherwise.""" - zf=zipfile.ZipFile(zipfilename, 'r') - if type(names)==type(''): - names=[names] - for name in names: - try: - info=zf.getinfo(name) - except KeyError as e: # name not found - zf.close() - return False - return True - -def zipfile_files(fname): - """Returns all the filenames in zip file fname.""" - zf = zipfile.ZipFile(fname, 'r') - return [x.filename for x in zf.infolist()] - test.subdir('sub1') test.write('SConstruct', """ @@ -78,12 +53,12 @@ test.write(['sub1', 'file6'], "sub1/file6\n") test.run(arguments = 'aaa.zip', stderr = None) test.must_exist('aaa.zip') -test.fail_test(not zipfile_contains('aaa.zip', ['file1', 'file2', 'file3'])) +test.fail_test(not test.zipfile_contains('aaa.zip', ['file1', 'file2', 'file3'])) test.run(arguments = 'bbb.zip', stderr = None) test.must_exist('bbb.zip') -test.fail_test(not zipfile_contains('bbb.zip', ['sub1/file5', 'sub1/file6', 'file4'])) +test.fail_test(not test.zipfile_contains('bbb.zip', ['sub1/file5', 'sub1/file6', 'file4'])) ###### @@ -136,11 +111,11 @@ test.run(arguments = '.', stderr = None) test.must_not_exist(test.workpath('f3.zip')) test.must_exist(test.workpath('f3.xyzzy')) -test.fail_test(zipfile_files("f1.zip") != ['file10', 'file11', 'file12']) +test.fail_test(test.zipfile_files("f1.zip") != ['file10', 'file11', 'file12']) -test.fail_test(zipfile_files("f2.zip") != ['file13', 'file14', 'file15']) +test.fail_test(test.zipfile_files("f2.zip") != ['file13', 'file14', 'file15']) -test.fail_test(zipfile_files("f3.xyzzy") != ['file16', 'file17', 'file18']) +test.fail_test(test.zipfile_files("f3.xyzzy") != ['file16', 'file17', 'file18']) f4_size = os.stat('f4.zip')[stat.ST_SIZE] f4stored_size = os.stat('f4stored.zip')[stat.ST_SIZE] diff --git a/test/ZIP/ZIPROOT.py b/test/ZIP/ZIPROOT.py index 24e82eb..10e01d9 100644 --- a/test/ZIP/ZIPROOT.py +++ b/test/ZIP/ZIPROOT.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 @@ -33,23 +32,6 @@ test = TestSCons.TestSCons() import zipfile -def zipfile_contains(zipfilename, names): - """Returns True if zipfilename contains all the names, False otherwise.""" - zf=zipfile.ZipFile(zipfilename, 'r') - if type(names)==type(''): - names=[names] - for name in names: - try: - info=zf.getinfo(name) - except KeyError as e: # name not found - zf.close() - return False - return True - -def zipfile_files(fname): - """Returns all the filenames in zip file fname.""" - zf = zipfile.ZipFile(fname, 'r') - return [x.filename for x in zf.infolist()] test.subdir('sub1') test.subdir(['sub1', 'sub2']) @@ -69,13 +51,12 @@ test.run(arguments = 'aaa.zip', stderr = None) test.must_exist('aaa.zip') # TEST: Zip file should contain 'file1', not 'sub1/file1', because of ZIPROOT. -zf=zipfile.ZipFile('aaa.zip', 'r') -test.fail_test(zf.testzip() is not None) -zf.close() +with zipfile.ZipFile('aaa.zip', 'r') as zf: + test.fail_test(zf.testzip() is not None) -files=zipfile_files('aaa.zip') -test.fail_test(zipfile_files('aaa.zip') != ['file1'], - message='Zip file aaa.zip has wrong files: %s'%repr(files)) +files = test.zipfile_files('aaa.zip') +test.fail_test(test.zipfile_files('aaa.zip') != ['file1'], + message='Zip file aaa.zip has wrong files: %s' % repr(files)) ### @@ -84,13 +65,12 @@ test.run(arguments = 'bbb.zip', stderr = None) test.must_exist('bbb.zip') # TEST: Zip file should contain 'sub2/file2', not 'sub1/sub2/file2', because of ZIPROOT. -zf=zipfile.ZipFile('bbb.zip', 'r') -test.fail_test(zf.testzip() is not None) -zf.close() +with zipfile.ZipFile('bbb.zip', 'r') as zf: + test.fail_test(zf.testzip() is not None) -files=zipfile_files('bbb.zip') -test.fail_test(zipfile_files('bbb.zip') != ['file2', 'sub2/file2'], - message='Zip file bbb.zip has wrong files: %s'%repr(files)) +files = test.zipfile_files('bbb.zip') +test.fail_test(test.zipfile_files('bbb.zip') != ['file2', 'sub2/file2'], + message='Zip file bbb.zip has wrong files: %s' % repr(files)) test.pass_test() diff --git a/test/ZIP/ZIP_OVERRIDE_TIMESTAMP.py b/test/ZIP/ZIP_OVERRIDE_TIMESTAMP.py new file mode 100644 index 0000000..8904944 --- /dev/null +++ b/test/ZIP/ZIP_OVERRIDE_TIMESTAMP.py @@ -0,0 +1,68 @@ +#!/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. + + +import TestSCons + +_python_ = TestSCons._python_ + +test = TestSCons.TestSCons() + +import zipfile + + +def zipfile_get_file_datetime(zipfilename, fname): + """Returns the date_time of the given file with the archive.""" + with zipfile.ZipFile(zipfilename, 'r') as zf: + for info in zf.infolist(): + if info.filename == fname: + return info.date_time + + raise Exception("Unable to find %s" % fname) + + +test.write('SConstruct', """ +env = Environment(tools = ['zip']) +env.Zip(target = 'aaa.zip', source = ['file1'], ZIP_OVERRIDE_TIMESTAMP=(1983,3,11,1,2,2)) +""" % locals()) + +test.write(['file1'], "file1\n") + +test.run(arguments = 'aaa.zip', stderr = None) + +test.must_exist('aaa.zip') + +with zipfile.ZipFile('aaa.zip', 'r') as zf: + test.fail_test(zf.testzip() is not None) + +files = test.zipfile_files('aaa.zip') +test.fail_test(files != ['file1'], + message='Zip file aaa.zip has wrong files: %s' % repr(files)) + +date_time = zipfile_get_file_datetime('aaa.zip', 'file1') +test.fail_test(date_time != (1983, 3, 11, 1, 2, 2), + message="Zip file aaa.zip#file1 has wrong date_time: %s" % repr(date_time)) + +test.pass_test() diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index 36b9df4..d1143e0 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -12,9 +12,28 @@ from those classes, as well as any overridden or additional methods or attributes defined in this subclass. """ -# __COPYRIGHT__ - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" +# 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. import os import re @@ -22,6 +41,7 @@ import shutil import sys import time import subprocess +import zipfile from collections import namedtuple from TestCommon import * @@ -1604,6 +1624,16 @@ else: else: return True + def zipfile_contains(self, zipfilename, names): + """Returns True if zipfilename contains all the names, False otherwise.""" + with zipfile.ZipFile(zipfilename, 'r') as zf: + return all(elem in zf.namelist() for elem in names) + + def zipfile_files(self, fname): + """Returns all the filenames in zip file fname.""" + with zipfile.ZipFile(fname, 'r') as zf: + return zf.namelist() + class Stat: def __init__(self, name, units, expression, convert=None): -- cgit v0.12 From 37a6eaf5bc845e50f87766471cd3322aa5433a9b Mon Sep 17 00:00:00 2001 From: William Deegan Date: Mon, 18 Jan 2021 18:17:57 -0800 Subject: [ci skip] update CPPDEFINES to use tuples for -Doff_t=int --- doc/user/environments.xml | 12 ++++++------ doc/user/sconf.xml | 10 ++++++---- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/doc/user/environments.xml b/doc/user/environments.xml index 405fcfa..2dae752 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -1431,10 +1431,10 @@ int main() { } - &SCons; then adjusts both the &CPPDEFINES; values with the correct - prefix/suffix, so that on Linux or POSIX, it will emit the + &SCons; then generates the preprocessor define arguments from &CPPDEFINES; values with the correct + prefix/suffix. For example on Linux or POSIX, the following arguments would be generated: -DMY_VALUE and - -DLAST flags when compiling the object file: + -DLAST @@ -1533,10 +1533,10 @@ int main() { } - &SCons; then adjusts both the &CPPDEFINES; values with the correct - prefix/suffix, so that on Linux or POSIX, it will emit the + &SCons; then generates the preprocessor define arguments from &CPPDEFINES; values with the correct + prefix/suffix. For example on Linux or POSIX, the following arguments would be generated: -DFIRST and - -DMY_VALUE flags when compiling the object file: + -DMY_VALUE diff --git a/doc/user/sconf.xml b/doc/user/sconf.xml index e00f4d2..b677548 100644 --- a/doc/user/sconf.xml +++ b/doc/user/sconf.xml @@ -21,7 +21,9 @@ - 2004 - 2020 + 2004 - 2021 - 2004 - 2020 + 2004 - 2021 The SCons Foundation diff --git a/doc/user/main.xml b/doc/user/main.xml index fd643b5..1869a91 100644 --- a/doc/user/main.xml +++ b/doc/user/main.xml @@ -51,16 +51,16 @@ User Guide - Steven - Knight + SCons + Development Team - Steven Knight and the SCons Development Team + The SCons Development Team - 2004 - 2020 + 2004 - 2021 - 2004 - 2020 + 2004 - 2021 The SCons Foundation -- cgit v0.12 From bf167880c7490a054fdc1ab25f0699ff74c54404 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 19 Jan 2021 10:18:01 -0800 Subject: updates for 4.1.0 release --- RELEASE.txt | 28 ++-------------------------- ReleaseConfig | 9 ++++----- 2 files changed, 6 insertions(+), 31 deletions(-) diff --git a/RELEASE.txt b/RELEASE.txt index 4bac83a..188e639 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -1,33 +1,9 @@ - A new SCons checkpoint release, 2.0.0ayyyymmdd, is now available + A new SCons release, 4.1.0, is now available on the SCons download page: https://scons.org/pages/download.html - XXX The primary purpose of this release ... XXX - - A SCons "checkpoint release" is intended to provide early access to - new features so they can be tested in the field before being released - for adoption by other software distributions. - - Note that a checkpoint release is developed using the same test-driven - development methodology as all SCons releases. Existing SCons - functionality should all work as it does in previous releases (except - for any changes identified in the release notes) and early adopters - should be able to use a checkpoint release safely for production work - with existing SConscript files. If not, it represents not only a bug - in SCons but also a hole in the regression test suite, and we want to - hear about it. - - New features may be more lightly tested than in past releases, - especially as concerns their interaction with all of the other - functionality in SCons. We are especially interested in hearing bug - reports about new functionality. - - We do not recommend that downstream distributions (Debian, Fedora, - etc.) package a checkpoint release, mainly to avoid confusing the - "public" release numbering with the long checkpoint release names. - - Here is a summary of the changes since 1.3.0: + Here is a summary of the changes since 4.0.1: NEW FUNCTIONALITY diff --git a/ReleaseConfig b/ReleaseConfig index b58aad7..ac70455 100755 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -1,5 +1,6 @@ +# MIT License # -# __COPYRIGHT__ +# 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,8 +21,6 @@ # 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__" - # # After updating this file, run bin/update-release-info.py . # @@ -32,7 +31,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" # 'final', the patchlevel is set to the release date. This value is # mandatory and must be present in this file. #version_tuple = (2, 2, 0, 'final', 0) -version_tuple = (4, 0, 2, 'a', 0) +version_tuple = (4, 1, 0) # Python versions prior to unsupported_python_version cause a fatal error # when that version is used. Python versions prior to deprecate_python_version @@ -51,7 +50,7 @@ deprecated_python_version = (3, 4, 0) #month_year = 'December 2012' # If copyright years is not given, the release year is used as the end. -copyright_years = '2001 - 2020' +copyright_years = '2001 - 2021' # Local Variables: # tab-width:4 -- cgit v0.12 From aee5793fdea4cc6a31e5346ddbd847c9ba23d64d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 19 Jan 2021 10:19:06 -0800 Subject: more updates on release version and date/timestamp --- CHANGES.txt | 2 +- debian/changelog | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index d9a677e..7cc7635 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -6,7 +6,7 @@ NOTE: The 4.0.0 Release of SCons dropped Python 2.7 Support -RELEASE VERSION/DATE TO BE FILLED IN LATER +RELEASE 4.1.0 - Tues, 19 Jan 2021 15:04:42 -0700 From James Benton: - Add COMPILATIONDB_PATH_FILTER env option for CompilationDatabase() builder which allows diff --git a/debian/changelog b/debian/changelog index fb80b22..6e8030f 100755 --- a/debian/changelog +++ b/debian/changelog @@ -2,7 +2,7 @@ scons (4.1.0) unstable; urgency=low * Feature release - -- William Deegan Thu, 19 Jan 2021 15:04:42 -0700 + -- William Deegan Tues, 19 Jan 2021 15:04:42 -0700 scons (4.0.1) unstable; urgency=low -- cgit v0.12 From 215860fd4f6bea67896c145660a035fad20cc41c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 19 Jan 2021 10:29:37 -0800 Subject: Updated __init__.py with 4.1.0 --- SCons/__init__.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/SCons/__init__.py b/SCons/__init__.py index c9ca70f..b5a5c28 100644 --- a/SCons/__init__.py +++ b/SCons/__init__.py @@ -1,9 +1,9 @@ -__version__="4.0.1.9998" -__copyright__="Copyright (c) 2001 - 2020 The SCons Foundation" +__version__="4.1.0" +__copyright__="Copyright (c) 2001 - 2021 The SCons Foundation" __developer__="bdbaddog" -__date__="2020-12-21 01:23:32" +__date__="2021-01-19 18:19:30" __buildsys__="ProDog2020" -__revision__="78292be9cbb471101e6ed4ec5f6da0161730c656" -__build__="78292be9cbb471101e6ed4ec5f6da0161730c656" +__revision__="aee5793fdea4cc6a31e5346ddbd847c9ba23d64d" +__build__="aee5793fdea4cc6a31e5346ddbd847c9ba23d64d" # make sure compatibility is always in place import SCons.compat # noqa \ No newline at end of file -- cgit v0.12 From dc58c175da659d6c0bb3e049ba56fb42e77546cd Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 19 Jan 2021 12:10:56 -0800 Subject: update API doc version to 4.1.0 and add some more dependencies on the api target to include the sphinx config files --- SCons/__init__.py | 6 +++--- doc/sphinx/conf.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SCons/__init__.py b/SCons/__init__.py index b5a5c28..6e1dd87 100644 --- a/SCons/__init__.py +++ b/SCons/__init__.py @@ -1,9 +1,9 @@ __version__="4.1.0" __copyright__="Copyright (c) 2001 - 2021 The SCons Foundation" __developer__="bdbaddog" -__date__="2021-01-19 18:19:30" +__date__="2021-01-19 20:03:01" __buildsys__="ProDog2020" -__revision__="aee5793fdea4cc6a31e5346ddbd847c9ba23d64d" -__build__="aee5793fdea4cc6a31e5346ddbd847c9ba23d64d" +__revision__="215860fd4f6bea67896c145660a035fad20cc41c" +__build__="215860fd4f6bea67896c145660a035fad20cc41c" # make sure compatibility is always in place import SCons.compat # noqa \ No newline at end of file diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index 91b511d..27e18b7 100644 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -78,9 +78,9 @@ author = 'SCons Project Team' # # TODO: fill these in externally # The short X.Y version. -version = '4.0' +version = '4.1' # The full version, including alpha/beta/rc tags. -release = '4.0.0' +release = '4.1.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -- cgit v0.12 From b9e70b2701c47a45e7317cd64cc1d50857885f8a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 19 Jan 2021 12:17:11 -0800 Subject: [ci skip] update post release --- CHANGES.txt | 7 ++ RELEASE.txt | 141 ++++++++++++++--------------------------- ReleaseConfig | 2 +- SConstruct | 2 +- testing/framework/TestSCons.py | 2 +- 5 files changed, 58 insertions(+), 96 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 7cc7635..c2faede 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -6,6 +6,13 @@ NOTE: The 4.0.0 Release of SCons dropped Python 2.7 Support +RELEASE VERSION/DATE TO BE FILLED IN LATER + + From John Doe: + + - Whatever John Doe did. + + RELEASE 4.1.0 - Tues, 19 Jan 2021 15:04:42 -0700 From James Benton: diff --git a/RELEASE.txt b/RELEASE.txt index 188e639..1410e35 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -1,118 +1,73 @@ - A new SCons release, 4.1.0, is now available + A new SCons checkpoint release, 2.0.0ayyyymmdd, is now available on the SCons download page: https://scons.org/pages/download.html - Here is a summary of the changes since 4.0.1: + XXX The primary purpose of this release ... XXX + + A SCons "checkpoint release" is intended to provide early access to + new features so they can be tested in the field before being released + for adoption by other software distributions. + + Note that a checkpoint release is developed using the same test-driven + development methodology as all SCons releases. Existing SCons + functionality should all work as it does in previous releases (except + for any changes identified in the release notes) and early adopters + should be able to use a checkpoint release safely for production work + with existing SConscript files. If not, it represents not only a bug + in SCons but also a hole in the regression test suite, and we want to + hear about it. + + New features may be more lightly tested than in past releases, + especially as concerns their interaction with all of the other + functionality in SCons. We are especially interested in hearing bug + reports about new functionality. + + We do not recommend that downstream distributions (Debian, Fedora, + etc.) package a checkpoint release, mainly to avoid confusing the + "public" release numbering with the long checkpoint release names. + + Here is a summary of the changes since 1.3.0: NEW FUNCTIONALITY - - Add COMPILATIONDB_PATH_FILTER env option for CompilationDatabase() builder which allows - filtering of entries based on the output file paths using glob style file matching (issue #3742). - - Add ZIP_OVERRIDE_TIMESTAMP env option to Zip builder which allows for overriding of the file - modification times in the archive. - - Raise an error if an option (not otherwise consumed) is used which - looks like an abbreviation of one one added by AddOption. (#3653) + - List new features (presumably why a checkpoint is being released) + DEPRECATED FUNCTIONALITY - CHANGED/ENHANCED EXISTING FUNCTIONALITY + - List anything that's been deprecated since the last release - - Completely rewrote versioned shared libraries logic. - Added support for SOVERSION via dmoody's initial PR #3733 - - No longer automatically disable setting SONAME on shared libraries on OpenBSD. - - - Environment.SideEffect() no longer adds duplicate side effects. - NOTE: The list of returned side effect Nodes will not include any - duplicate side effect Nodes. - - /snap/bin is added to the default search path for the 'posix' platform. - - Completely rewrote versioned shared libraries logic. - - Added support for SOVERSION - - No longer automatically disable setting SONAME on shared libraries on OpenBSD. - - Switch to use ctypes instead of pywin32 (requiring an extra pip install) - Fixes Github Issue #2291 - - pywin32 no longer necessary for SCons install. (pip install SCons will no longer also require pywin32 on win32) - - Remove pywin32 usage from SCons.Util where it was used for accessing the registry. Python native winreg - library already includes this functionality. - - Remove using pywin32 to retrieve peak memory usage on Win32 for `--debug=memory` - - Tool module not found will now raise a UserError to more clearly indicate this is - probably an SConscript problem, and to make the traceback more relevant. - - Fix three issues with MergeFlags: - - Signature/return did not match documentation or existing usage - the implementation - now no longer returns the passed env - - merging --param arguments did not work (issue #3107); - - passing a dict to merge where the values are strings failed (issue #2961). - - Only try to initialize the wix tool by default (or when tool `default` is explicitly installed) - on Windows based systems. - - Add /snap/bin to env['PATH'] on POSIX, although this is only - really useful for a subset of POSIX systems that use snaps. - Was needed for CI builds, which run on Ubuntu LTS images. + CHANGED/ENHANCED EXISTING FUNCTIONALITY + - List modifications to existing features, where the previous behavior + wouldn't actually be considered a bug FIXES - - Fix yacc tool, not respecting YACC set at time of tool initialization. - - Fix race condition bug when initializing a scons cache directory at the - same time from multiple threads or processes. Problem described in PR #3114. - This is a simpler fix which should avoid some problems identified with the initial PR. - (Credit to Fredrik Medley for reporting the issue, the initial PR, and discussing and testing - this solution) - - Fix incorrect cache hits and/or misses when running in interactive mode by having - SCons.Node.Node.clear() clear out all caching-related state. - - Fix Zip builder not rebuilding when ZIPROOT env option was changed. - - Fix python3 crash when Value node get_text_content when child content does not have decode() - NOTE: If you depend on Value node's get_text_content returning concatenated contents of it's - children. This may break your code. It now concatenates the csig() of all children. - - Fix Zip tool to respect ZIPCOMSTR. Previously all zip builder calls would yield something - like zip(["test.zip"], ["zip_scons.py"]) and ignore ZIPCOMSTR if ZIPCOM and ZIPCOMSTR - weren't set after the Environment/Tool is initialized. (Explained in PR #3659) - - Fix issue where java parsed a class incorrectly from lambdas used after a new. - - Fix using TEMPFILE in multiple actions in an action list. Previously a builder, or command - with an action list like this: - ['${TEMPFILE("xxx.py -otempfile $SOURCE")}', '${TEMPFILE("yyy.py -o$TARGET tempfile")}'] - Could yield a single tempfile with the first TEMPFILE's contents, used by both steps - in the action list. - - Cleanup in SCons.Util.AddMethod. If called with an environment instance - as the object to modify, the method would not be correctly set up in - any Clone of that instance. Now tries to detect this and calls - MethodWrapper to set up the method the same way env.AddMethod does. - MethodWrapper moved to Util to avoid a circular import. Fixes #3028. - - Fix Issue #3014 - Empty file and missing file have same csig + - List fixes of outright bugs + IMPROVEMENTS + + - List improvements that wouldn't be visible to the user in the + documentation: performance improvements (describe the circumstances + under which they would be observed), or major code cleanups PACKAGING - - Fix Issue #3759 - include scons.1, sconsign.1, scons-time.1 manpages in sdist and wheel packages. - - Pick a better "Topic" Trove classifier for SCons: SW Dev / Build Tools + - List changes in the way SCons is packaged and/or released DOCUMENTATION - - Include previously-excluded SideEffect section in User Guide. + - List any significant changes to the documentation (not individual + typo fixes, even if they're mentioned in src/CHANGES.txt to give + the contributor credit) DEVELOPMENT - - Rework runtest.py to use argparse for arg handling (was a mix - of hand-coded and optparse, with a stated intent to "gradually port"). - - Add options to runtest to generate/not generate a log of failed tests, - and to rerun such tests. Useful when an error cascades through several - tests, can quickly try if a change improves all the fails. Dropped - runtest test for fallback from qmtest, not needed; added new tests. - - Thanks to the following contributors listed below for their contributions to this release. - -git shortlog --no-merges -ns 4.0.1..HEAD - 115 Mats Wichmann - 83 William Deegan - 14 Adam Gross - 4 Joseph Brill - 3 Joachim Kuebart - 2 GIT - 2 Daniel Moody - 2 James Benton - 1 Unknown - 1 Daniel - 1 anatoly techtonik - 1 Dirk Baechle - 1 dependabot[bot] - 1 David H - 1 Michał Górny - 1 Simon Tegelid + - List visible changes in the way SCons is developed + + Thanks to CURLY, LARRY, and MOE for their contributions to this release. + Contributors are listed alphabetically by their last name. +__COPYRIGHT__ +__FILE__ __REVISION__ __DATE__ __DEVELOPER__ diff --git a/ReleaseConfig b/ReleaseConfig index ac70455..fa4a24b 100755 --- a/ReleaseConfig +++ b/ReleaseConfig @@ -31,7 +31,7 @@ # 'final', the patchlevel is set to the release date. This value is # mandatory and must be present in this file. #version_tuple = (2, 2, 0, 'final', 0) -version_tuple = (4, 1, 0) +version_tuple = (4, 1, 1, 'a', 0) # Python versions prior to unsupported_python_version cause a fatal error # when that version is used. Python versions prior to deprecate_python_version diff --git a/SConstruct b/SConstruct index 8af13f8..26b9607 100644 --- a/SConstruct +++ b/SConstruct @@ -38,7 +38,7 @@ month_year = strftime('%B %Y') project = 'scons' -default_version = '4.1.0' +default_version = '4.1.1a' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years # diff --git a/testing/framework/TestSCons.py b/testing/framework/TestSCons.py index d1143e0..0783da4 100644 --- a/testing/framework/TestSCons.py +++ b/testing/framework/TestSCons.py @@ -55,7 +55,7 @@ from TestCmd import PIPE # here provides some independent verification that what we packaged # conforms to what we expect. -default_version = '4.0.2ayyyymmdd' +default_version = '4.1.1ayyyymmdd' python_version_unsupported = (3, 4, 0) python_version_deprecated = (3, 4, 0) -- cgit v0.12 From f2ce47e286fb46f6c61937ee9f8993945705ecdc Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 19 Jan 2021 14:08:24 -0800 Subject: update RELEASE.TXT template and current version of it to be restructured text friendly --- RELEASE.txt | 89 ++++++++++++++++++++++------------------------------ template/RELEASE.txt | 89 ++++++++++++++++++++++------------------------------ 2 files changed, 74 insertions(+), 104 deletions(-) diff --git a/RELEASE.txt b/RELEASE.txt index 1410e35..89d634c 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -1,73 +1,58 @@ - A new SCons checkpoint release, 2.0.0ayyyymmdd, is now available - on the SCons download page: +A new SCons release, 4.1.0, is now available +on the SCons download page: - https://scons.org/pages/download.html + https://scons.org/pages/download.html - XXX The primary purpose of this release ... XXX - A SCons "checkpoint release" is intended to provide early access to - new features so they can be tested in the field before being released - for adoption by other software distributions. +Here is a summary of the changes since 4.1.0: - Note that a checkpoint release is developed using the same test-driven - development methodology as all SCons releases. Existing SCons - functionality should all work as it does in previous releases (except - for any changes identified in the release notes) and early adopters - should be able to use a checkpoint release safely for production work - with existing SConscript files. If not, it represents not only a bug - in SCons but also a hole in the regression test suite, and we want to - hear about it. +NEW FUNCTIONALITY +----------------- - New features may be more lightly tested than in past releases, - especially as concerns their interaction with all of the other - functionality in SCons. We are especially interested in hearing bug - reports about new functionality. +- List new features (presumably why a checkpoint is being released) - We do not recommend that downstream distributions (Debian, Fedora, - etc.) package a checkpoint release, mainly to avoid confusing the - "public" release numbering with the long checkpoint release names. +DEPRECATED FUNCTIONALITY +------------------------ - Here is a summary of the changes since 1.3.0: +- List anything that's been deprecated since the last release - NEW FUNCTIONALITY +CHANGED/ENHANCED EXISTING FUNCTIONALITY +--------------------------------------- - - List new features (presumably why a checkpoint is being released) +- List modifications to existing features, where the previous behavior + wouldn't actually be considered a bug - DEPRECATED FUNCTIONALITY +FIXES +----- - - List anything that's been deprecated since the last release +- List fixes of outright bugs - CHANGED/ENHANCED EXISTING FUNCTIONALITY +IMPROVEMENTS +------------ - - List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug +- List improvements that wouldn't be visible to the user in the + documentation: performance improvements (describe the circumstances + under which they would be observed), or major code cleanups - FIXES +PACKAGING +--------- - - List fixes of outright bugs +- List changes in the way SCons is packaged and/or released - IMPROVEMENTS +DOCUMENTATION +------------- - - List improvements that wouldn't be visible to the user in the - documentation: performance improvements (describe the circumstances - under which they would be observed), or major code cleanups +- List any significant changes to the documentation (not individual + typo fixes, even if they're mentioned in src/CHANGES.txt to give + the contributor credit) - PACKAGING +DEVELOPMENT +----------- - - List changes in the way SCons is packaged and/or released +- List visible changes in the way SCons is developed - DOCUMENTATION +Thanks to the following contributors listed below for their contributions to this release. +========================================================================================== +.. code-block:: text - - List any significant changes to the documentation (not individual - typo fixes, even if they're mentioned in src/CHANGES.txt to give - the contributor credit) - - DEVELOPMENT - - - List visible changes in the way SCons is developed - - Thanks to CURLY, LARRY, and MOE for their contributions to this release. - Contributors are listed alphabetically by their last name. - -__COPYRIGHT__ -__FILE__ __REVISION__ __DATE__ __DEVELOPER__ + git shortlog --no-merges -ns 4.0.1..HEAD diff --git a/template/RELEASE.txt b/template/RELEASE.txt index 1410e35..89d634c 100755 --- a/template/RELEASE.txt +++ b/template/RELEASE.txt @@ -1,73 +1,58 @@ - A new SCons checkpoint release, 2.0.0ayyyymmdd, is now available - on the SCons download page: +A new SCons release, 4.1.0, is now available +on the SCons download page: - https://scons.org/pages/download.html + https://scons.org/pages/download.html - XXX The primary purpose of this release ... XXX - A SCons "checkpoint release" is intended to provide early access to - new features so they can be tested in the field before being released - for adoption by other software distributions. +Here is a summary of the changes since 4.1.0: - Note that a checkpoint release is developed using the same test-driven - development methodology as all SCons releases. Existing SCons - functionality should all work as it does in previous releases (except - for any changes identified in the release notes) and early adopters - should be able to use a checkpoint release safely for production work - with existing SConscript files. If not, it represents not only a bug - in SCons but also a hole in the regression test suite, and we want to - hear about it. +NEW FUNCTIONALITY +----------------- - New features may be more lightly tested than in past releases, - especially as concerns their interaction with all of the other - functionality in SCons. We are especially interested in hearing bug - reports about new functionality. +- List new features (presumably why a checkpoint is being released) - We do not recommend that downstream distributions (Debian, Fedora, - etc.) package a checkpoint release, mainly to avoid confusing the - "public" release numbering with the long checkpoint release names. +DEPRECATED FUNCTIONALITY +------------------------ - Here is a summary of the changes since 1.3.0: +- List anything that's been deprecated since the last release - NEW FUNCTIONALITY +CHANGED/ENHANCED EXISTING FUNCTIONALITY +--------------------------------------- - - List new features (presumably why a checkpoint is being released) +- List modifications to existing features, where the previous behavior + wouldn't actually be considered a bug - DEPRECATED FUNCTIONALITY +FIXES +----- - - List anything that's been deprecated since the last release +- List fixes of outright bugs - CHANGED/ENHANCED EXISTING FUNCTIONALITY +IMPROVEMENTS +------------ - - List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug +- List improvements that wouldn't be visible to the user in the + documentation: performance improvements (describe the circumstances + under which they would be observed), or major code cleanups - FIXES +PACKAGING +--------- - - List fixes of outright bugs +- List changes in the way SCons is packaged and/or released - IMPROVEMENTS +DOCUMENTATION +------------- - - List improvements that wouldn't be visible to the user in the - documentation: performance improvements (describe the circumstances - under which they would be observed), or major code cleanups +- List any significant changes to the documentation (not individual + typo fixes, even if they're mentioned in src/CHANGES.txt to give + the contributor credit) - PACKAGING +DEVELOPMENT +----------- - - List changes in the way SCons is packaged and/or released +- List visible changes in the way SCons is developed - DOCUMENTATION +Thanks to the following contributors listed below for their contributions to this release. +========================================================================================== +.. code-block:: text - - List any significant changes to the documentation (not individual - typo fixes, even if they're mentioned in src/CHANGES.txt to give - the contributor credit) - - DEVELOPMENT - - - List visible changes in the way SCons is developed - - Thanks to CURLY, LARRY, and MOE for their contributions to this release. - Contributors are listed alphabetically by their last name. - -__COPYRIGHT__ -__FILE__ __REVISION__ __DATE__ __DEVELOPER__ + git shortlog --no-merges -ns 4.0.1..HEAD -- cgit v0.12 From 12f24df0004ced8b91e758f29cd6396e60f37f5a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Tue, 19 Jan 2021 20:53:20 -0800 Subject: Bump version to 4.1.0.post1 and fix non-wheel packaging of manpages --- SCons/__init__.py | 8 ++++---- SConstruct | 2 +- setup.cfg | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/SCons/__init__.py b/SCons/__init__.py index 6e1dd87..d169eef 100644 --- a/SCons/__init__.py +++ b/SCons/__init__.py @@ -1,9 +1,9 @@ -__version__="4.1.0" +__version__="4.1.0.post1" __copyright__="Copyright (c) 2001 - 2021 The SCons Foundation" __developer__="bdbaddog" -__date__="2021-01-19 20:03:01" +__date__="2021-01-20 04:32:28" __buildsys__="ProDog2020" -__revision__="215860fd4f6bea67896c145660a035fad20cc41c" -__build__="215860fd4f6bea67896c145660a035fad20cc41c" +__revision__="dc58c175da659d6c0bb3e049ba56fb42e77546cd" +__build__="dc58c175da659d6c0bb3e049ba56fb42e77546cd" # make sure compatibility is always in place import SCons.compat # noqa \ No newline at end of file diff --git a/SConstruct b/SConstruct index 8af13f8..6ccc350 100644 --- a/SConstruct +++ b/SConstruct @@ -38,7 +38,7 @@ month_year = strftime('%B %Y') project = 'scons' -default_version = '4.1.0' +default_version = '4.1.0.post1' copyright = "Copyright (c) %s The SCons Foundation" % copyright_years # diff --git a/setup.cfg b/setup.cfg index 421542f..c39f2de 100644 --- a/setup.cfg +++ b/setup.cfg @@ -66,9 +66,9 @@ SCons.Tool.docbook = *.* [options.data_files] -. = build/doc/man/scons.1 - build/doc/man/scons-time.1 - build/doc/man/sconsign.1 +. = scons.1 + scons-time.1 + sconsign.1 [sdist] dist-dir=build/dist -- cgit v0.12 From 426885c8929b93944edcf8a0962331d36fbcdc73 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 21 Jan 2021 08:47:38 -0700 Subject: Some small doc fiddles [ci skip] * Use os.environ.copy() in examples - better not to get the Python proxy class that is os.environ, and instead a real dict. * Fix spelling on a python dict method: set_default -> setdefault * Update some wording on prepending in the user guide (where it still said "append to the beginning") * Change the rather oblique note in the recently modified section on Append of values to CPPDEFINES with something more explicit. * And, modify the sphinx config to get the version from SCons rather than hardcoding. Fixes #3867 Signed-off-by: Mats Wichmann --- SCons/Environment.xml | 6 +++--- doc/generated/variables.gen | 4 ++-- doc/man/scons.xml | 16 ++++++++-------- doc/sphinx/conf.py | 9 +++++---- doc/user/environments.xml | 21 +++++++++++---------- 5 files changed, 29 insertions(+), 27 deletions(-) diff --git a/SCons/Environment.xml b/SCons/Environment.xml index a185815..cfa99db 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -87,7 +87,7 @@ Note that, by default, &scons; does not -propagate the environment in force when you +propagate the environment in effect when you execute &scons; to the commands used to build target files. @@ -108,7 +108,7 @@ you must do so explicitly: import os -env = Environment(ENV = os.environ) +env = Environment(ENV=os.environ.copy()) @@ -126,7 +126,7 @@ as the invoking shell (or other process): import os -env = Environment(ENV = {'PATH' : os.environ['PATH']}) +env = Environment(ENV={'PATH': os.environ['PATH']})
diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index a16efae..1ac53fe 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -1636,7 +1636,7 @@ you must do so explicitly: import os -env = Environment(ENV = os.environ) +env = Environment(ENV=os.environ.copy()) @@ -1654,7 +1654,7 @@ as the invoking shell (or other process): import os -env = Environment(ENV = {'PATH' : os.environ['PATH']}) +env = Environment(ENV={'PATH': os.environ['PATH']}) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 8da4cc9..57bd209 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -269,7 +269,7 @@ complete external environment: import os -env = Environment(ENV=os.environ) +env = Environment(ENV=os.environ.copy()) This comes at the expense of making your build @@ -2574,7 +2574,7 @@ A nested tool name uses a dot to represent a directory separator # namespaced builder -env = Environment(ENV=os.environ, tools=['SubDir1.SubDir2.SomeTool']) +env = Environment(ENV=os.environ.copy(), tools=['SubDir1.SubDir2.SomeTool']) env.SomeTool(targets, sources) # Search Paths @@ -5060,7 +5060,7 @@ arguments must not both be used for the same Builder.
prefix -The prefix that will be prepended to the target file name. +The prefix to prepend to the target file name. prefix may be: @@ -5098,13 +5098,13 @@ b = Builder("build_it < $SOURCE > $TARGET", suffix -The suffix that will be appended to the target file name. +The suffix to append to the target file name. This may be specified in the same manner as the prefix above. If the suffix is a string, then &scons; -will append a '.' to the beginning of the suffix if it's not already -there. The string returned by callable object (or obtained from the -dictionary) is untouched and must append its own '.' to the beginning +prepends a '.' to the suffix if it's not already there. +The string returned by the callable object (or obtained from the +dictionary) is untouched and you need to manually prepend a '.' if one is desired. @@ -6961,7 +6961,7 @@ such as Linux or UNIX, .F as a Fortran source file that is to be first run through -the standard C preprocessor, +the standard C preprocessor, while the lower-case version is not. This matches the convention of gfortran, which may also be followed by other Fortran compilers. diff --git a/doc/sphinx/conf.py b/doc/sphinx/conf.py index 27e18b7..517af50 100644 --- a/doc/sphinx/conf.py +++ b/doc/sphinx/conf.py @@ -76,11 +76,12 @@ author = 'SCons Project Team' # |version| and |release|, also used in various other places throughout the # built documents. # -# TODO: fill these in externally +from SCons import __version__ +# The full version, including alpha/beta/rc tags: +release = __version__ # The short X.Y version. -version = '4.1' -# The full version, including alpha/beta/rc tags. -release = '4.1.0' +major, minor, _ = __version__.split('.') +version = '.'.join([major, minor]) # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/doc/user/environments.xml b/doc/user/environments.xml index 2dae752..3c3eeae 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -1383,7 +1383,7 @@ int main() { } set to a value only if the construction environment does not already have that variable defined You can do this with the &f-link-env-SetDefault; method, - which behaves similarly to the set_default + which behaves similarly to the setdefault method of &Python; dictionary objects: @@ -1431,10 +1431,11 @@ int main() { } - &SCons; then generates the preprocessor define arguments from &CPPDEFINES; values with the correct - prefix/suffix. For example on Linux or POSIX, the following arguments would be generated: - -DMY_VALUE and - -DLAST + Note &cv-link-CPPDEFINES; is the preferred way to set preprocessor defines, + as &SCons; will generate the command line arguments using the correct + prefix/suffix for the platform, leaving the usage portable. + If you use &cv-link-CCFLAGS; and &cv-link-SHCCFLAGS;, + you need to include them in their final form, which is less portable. @@ -1487,7 +1488,7 @@ print("NEW_VARIABLE = %s"%env['NEW_VARIABLE']) - Some times it's useful to add a new value + Sometimes it's useful to add a new value only if the existing construction variable doesn't already contain the value. This can be done using the &f-link-env-AppendUnique; method: @@ -1510,11 +1511,11 @@ env.AppendUnique(CCFLAGS=['-g'])
- Appending to the Beginning of Values: the &Prepend; Method + Prepending to the Beginning of Values: the &Prepend; Method - You can append a value to the beginning of + You can prepend a value to the beginning of an existing construction variable using the &f-link-env-Prepend; method: @@ -1912,7 +1913,7 @@ env = Environment(ENV={'PATH': os.environ['PATH']}) import os -env = Environment(ENV=os.environ) +env = Environment(ENV=os.environ.copy()) @@ -1959,7 +1960,7 @@ env = Environment(ENV=os.environ) -env = Environment(ENV=os.environ) +env = Environment(ENV=os.environ.copy()) env.PrependENVPath('PATH', '/usr/local/bin') env.AppendENVPath('LIB', '/usr/local/lib') -- cgit v0.12 From 9ca3fa2dfde9ea0eec0deb758af4bc262c8200de Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 21 Jan 2021 19:07:28 -0800 Subject: For systems with symlink, use existing Base.lstat()'s logic instead of repeating it. Also use False return value to indicate false, instead of 0 --- SCons/Node/FS.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SCons/Node/FS.py b/SCons/Node/FS.py index 290fcb3..3b320df 100644 --- a/SCons/Node/FS.py +++ b/SCons/Node/FS.py @@ -757,12 +757,11 @@ class Base(SCons.Node.Node): if hasattr(os, 'symlink'): def islink(self): - try: st = self.fs.lstat(self.get_abspath()) - except os.error: return 0 - return stat.S_ISLNK(st[stat.ST_MODE]) + st = self.lstat() + return st is not None and stat.S_ISLNK(st[stat.ST_MODE]) else: def islink(self): - return 0 # no symlinks + return False # no symlinks def is_under(self, dir): if self is dir: -- cgit v0.12 From c3e965d9bc6deb3790d93755f32c32cf05a50674 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 21 Jan 2021 19:08:29 -0800 Subject: cleanup whitespace in appveyor file --- .appveyor.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 6689594..a654337 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -74,8 +74,8 @@ build_script: # 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 - - # NOTE: running powershell from cmd is intended because + + # NOTE: running powershell from cmd is intended because # it formats the output correctly - cmd: powershell -Command "& { if($env:COVERAGE -eq 1) { coverage run -p --rcfile=$($env:COVERAGE_PROCESS_START) runtest.py -j 2 -t --exclude-list exclude_list.txt -a } else { C:\\%WINPYTHON%\\python.exe runtest.py -j 2 -t --exclude-list exclude_list.txt -a }; if($LastExitCode -eq 2 -Or $LastExitCode -eq 0) { $host.SetShouldExit(0 )} else {$host.SetShouldExit(1)}}" @@ -85,4 +85,4 @@ on_finish: # running codecov in powershell causes an error so running in platform # shells - cmd: if %COVERAGE% equ 1 codecov -X gcov --file coverage_xml.xml - + -- cgit v0.12 From 1fb86149bbdf91efebefc3a63819de6ae98f2219 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 21 Jan 2021 19:09:52 -0800 Subject: install all pip packages from requirements.txt for appveyor build --- .appveyor/install.bat | 1 + 1 file changed, 1 insertion(+) diff --git a/.appveyor/install.bat b/.appveyor/install.bat index 3dea66a..d009e54 100644 --- a/.appveyor/install.bat +++ b/.appveyor/install.bat @@ -5,6 +5,7 @@ set PATH=C:\\%WINPYTHON%;C:\\%WINPYTHON%\\Scripts;C:\\ProgramData\\chocolatey\\b 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 +C:\\%WINPYTHON%\\python.exe -m pip install -U --progress-bar off -r requirements.txt REM install 3rd party tools to test with choco install --allow-empty-checksums dmd ldc swig vswhere xsltproc winflexbison set SCONS_CACHE_MSVC_CONFIG=true -- cgit v0.12 From 7040b4e9fdef304c20939aceea68e2afb531ff2d Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 21 Jan 2021 19:10:25 -0800 Subject: cleanup whitespace --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index bdf3e0c..48f4d4f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ jobs: # allow coverage to fail, so we can still do testing for all platforms allow_failures: - python: pypy3 - + include: - &test_job script: python runtest.py -a -t -j 2 || if [[ $? == 2 ]]; then true; else false; fi @@ -49,7 +49,7 @@ jobs: - <<: *test_job python: 3.6 - + - <<: *test_job python: 3.7 dist: xenial # required for Python >= 3.7 -- cgit v0.12 From 3a600176a859ee4bfbf2a174d25867258208d0b5 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 21 Jan 2021 19:11:11 -0800 Subject: cleanup whitespace --- SCons/Script/SConscript.py | 1 + 1 file changed, 1 insertion(+) diff --git a/SCons/Script/SConscript.py b/SCons/Script/SConscript.py index b8dfd93..c47ace3 100644 --- a/SCons/Script/SConscript.py +++ b/SCons/Script/SConscript.py @@ -287,6 +287,7 @@ def _SConscript(fs, *files, **kw): if old_file is not None: call_stack[-1].globals.update({__file__:old_file}) + else: handle_missing_SConscript(f, kw.get('must_exist', None)) -- cgit v0.12 From bc339562305df8cff3bc2e6663a87d8cd343b665 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 21 Jan 2021 13:51:35 -0700 Subject: Initial support in tests for Python 3.10 Expected bytecode and one changed expected exception message. Change some more regexes to be specified as rawstrings in response to DeprecationWarnings. Signed-off-by: Mats Wichmann --- CHANGES.txt | 8 ++++++-- SCons/Action.py | 2 +- SCons/ActionTests.py | 9 +++++++++ SCons/SubstTests.py | 4 +++- SCons/Tool/docbook/__init__.py | 8 ++++---- SCons/Variables/__init__.py | 2 +- test/Interactive/configure.py | 6 +++--- 7 files changed, 27 insertions(+), 12 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index c2faede..67a2bad 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,9 +8,13 @@ NOTE: The 4.0.0 Release of SCons dropped Python 2.7 Support RELEASE VERSION/DATE TO BE FILLED IN LATER - From John Doe: + From John Doe: + - Whatever John Doe did. - - Whatever John Doe did. + From Mats Wichmann: + - Initial support in tests for Python 3.10 - expected bytecode and + one changed expected exception message. Change some more regexes + to be specified as rawstrings in response to DeprecationWarnings. RELEASE 4.1.0 - Tues, 19 Jan 2021 15:04:42 -0700 diff --git a/SCons/Action.py b/SCons/Action.py index d7f10df..97309e6 100644 --- a/SCons/Action.py +++ b/SCons/Action.py @@ -145,7 +145,7 @@ def rfile(n): def default_exitstatfunc(s): return s -strip_quotes = re.compile('^[\'"](.*)[\'"]$') +strip_quotes = re.compile(r'^[\'"](.*)[\'"]$') def _callable_contents(obj): diff --git a/SCons/ActionTests.py b/SCons/ActionTests.py index c03e87f..e665472 100644 --- a/SCons/ActionTests.py +++ b/SCons/ActionTests.py @@ -1516,6 +1516,7 @@ class CommandGeneratorActionTestCase(unittest.TestCase): (3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), (3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), (3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + (3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), } meth_matches = [ @@ -1695,6 +1696,7 @@ class FunctionActionTestCase(unittest.TestCase): (3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), (3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), (3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + (3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), } @@ -1704,6 +1706,7 @@ class FunctionActionTestCase(unittest.TestCase): (3, 7): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), (3, 8): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), (3, 9): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), + (3, 10): bytearray(b'1, 1, 0, 0,(),(),(d\x00S\x00),(),()'), } def factory(act, **kw): @@ -1949,6 +1952,7 @@ class LazyActionTestCase(unittest.TestCase): (3, 7): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), (3, 8): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), (3, 9): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), + (3, 10): bytearray(b'0, 0, 0, 0,(),(),(d\x00S\x00),(),()'), } meth_matches = [ @@ -2008,6 +2012,7 @@ class ActionCallerTestCase(unittest.TestCase): (3, 7): b'd\x00S\x00', (3, 8): b'd\x00S\x00', (3, 9): b'd\x00S\x00', + (3, 10): b'd\x00S\x00', } @@ -2209,6 +2214,7 @@ class ObjectContentsTestCase(unittest.TestCase): (3, 7): bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()'), (3, 8): bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()'), (3, 9): bytearray(b'3, 3, 0, 0,(),(),(|\x00S\x00),(),()'), + (3, 10): bytearray(b'3, 3, 0, 0,(N.),(),(|\x00S\x00),(),()'), } c = SCons.Action._function_contents(func1) @@ -2236,6 +2242,8 @@ class ObjectContentsTestCase(unittest.TestCase): b"{TestClass:__main__}[[[(, ()), [(, (,))]]]]{{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, 9): bytearray( b"{TestClass:__main__}[[[(, ()), [(, (,))]]]]{{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, 10): bytearray( + b"{TestClass:__main__}[[[(, ()), [(, (,))]]]]{{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}}}"), } assert c == expected[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + "\n" + repr( @@ -2254,6 +2262,7 @@ class ObjectContentsTestCase(unittest.TestCase): (3, 7): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), (3, 8): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), (3, 9): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), + (3, 10): bytearray(b'0, 0, 0, 0,(Hello, World!),(print),(e\x00d\x00\x83\x01\x01\x00d\x01S\x00)'), } assert c == expected[sys.version_info[:2]], "Got\n" + repr(c) + "\nExpected \n" + "\n" + repr(expected[ diff --git a/SCons/SubstTests.py b/SCons/SubstTests.py index be62db0..bdeb01e 100644 --- a/SCons/SubstTests.py +++ b/SCons/SubstTests.py @@ -590,7 +590,9 @@ class scons_subst_TestCase(SubstTestCase): except SCons.Errors.UserError as e: expect = [ # Python 3.5 (and 3.x?) - "TypeError `func() missing 2 required positional arguments: 'b' and 'c'' trying to evaluate `${func(1)}'" + "TypeError `func() missing 2 required positional arguments: 'b' and 'c'' trying to evaluate `${func(1)}'", + # Python 3.10 + "TypeError `scons_subst_TestCase.test_subst_type_errors..func() missing 2 required positional arguments: 'b' and 'c'' trying to evaluate `${func(1)}'", ] assert str(e) in expect, repr(str(e)) else: diff --git a/SCons/Tool/docbook/__init__.py b/SCons/Tool/docbook/__init__.py index 366dff4..450860d 100644 --- a/SCons/Tool/docbook/__init__.py +++ b/SCons/Tool/docbook/__init__.py @@ -62,8 +62,8 @@ except Exception: prefer_xsltproc = False # Regexs for parsing Docbook XML sources of MAN pages -re_manvolnum = re.compile("([^<]*)") -re_refname = re.compile("([^<]*)") +re_manvolnum = re.compile(r"([^<]*)") +re_refname = re.compile(r"([^<]*)") # # Helper functions @@ -203,8 +203,8 @@ def _detect(env): # # Scanners # -include_re = re.compile('fileref\\s*=\\s*["|\']([^\\n]*)["|\']') -sentity_re = re.compile('') +include_re = re.compile(r'fileref\\s*=\\s*["|\']([^\\n]*)["|\']') +sentity_re = re.compile(r'') def __xml_scan(node, env, path, arg): """ Simple XML file scanner, detecting local images and XIncludes as implicit dependencies. """ diff --git a/SCons/Variables/__init__.py b/SCons/Variables/__init__.py index 2c32310..4a30a91 100644 --- a/SCons/Variables/__init__.py +++ b/SCons/Variables/__init__.py @@ -111,7 +111,7 @@ class Variables: return [o.key for o in self.options] def Add(self, key, help="", default=None, validator=None, converter=None, **kw): - """Add an option. + r"""Add an option. Args: key: the name of the variable, or a list or tuple of arguments diff --git a/test/Interactive/configure.py b/test/Interactive/configure.py index dfe1c7f..ebb4262 100644 --- a/test/Interactive/configure.py +++ b/test/Interactive/configure.py @@ -53,9 +53,9 @@ import re # The order of this list is related to the order of the counts below expected_patterns = [ - re.compile("^scons>>> .*foo\.cpp.*$"), - re.compile("^scons>>> scons: `foo.obj' is up to date\.$"), - re.compile("^scons>>>\s*$"), + re.compile(r"^scons>>> .*foo\.cpp.*$"), + re.compile(r"^scons>>> scons: `foo.obj' is up to date\.$"), + re.compile(r"^scons>>>\s*$"), ] # The order of this list is related to the order of the regular expressions above -- cgit v0.12 From 1dee7ee7b72bfa8c521b11d6cadf696ece98168c Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 22 Jan 2021 12:12:33 -0700 Subject: Add a run on Py 3.10-dev [skip appveyor] Signed-off-by: Mats Wichmann --- .travis.yml | 17 ++++++++++++----- CHANGES.txt | 3 --- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 48f4d4f..a7e86c1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,6 +36,7 @@ jobs: # allow coverage to fail, so we can still do testing for all platforms allow_failures: - python: pypy3 + - python: 3.10-dev include: - &test_job @@ -49,18 +50,24 @@ jobs: - <<: *test_job python: 3.6 + dist: xenial - - <<: *test_job - python: 3.7 - dist: xenial # required for Python >= 3.7 + # to keep number of runs down, skip this since tested in 'coverage' + #- <<: *test_job + # python: 3.7 + # dist: xenial # required for Python >= 3.7 - <<: *test_job python: 3.8 - dist: bionic # required for Python >= 3.8 + dist: bionic - <<: *test_job python: 3.9 - dist: focal # required for Python >= 3.8 + dist: focal + + - <<: *test_job + python: 3.10-dev + dist: focal - &coverage_jobs dist: bionic diff --git a/CHANGES.txt b/CHANGES.txt index 67a2bad..f3e2b2a 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,9 +8,6 @@ NOTE: The 4.0.0 Release of SCons dropped Python 2.7 Support RELEASE VERSION/DATE TO BE FILLED IN LATER - From John Doe: - - Whatever John Doe did. - From Mats Wichmann: - Initial support in tests for Python 3.10 - expected bytecode and one changed expected exception message. Change some more regexes -- cgit v0.12 From c6d23b256bf548a664dd659be1da7c244c56abdf Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 23 Jan 2021 16:31:11 -0800 Subject: Add logic to force rebuild of lxml and cython from git versions for python 3.10 --- .travis.yml | 1 + .travis/install.sh | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/.travis.yml b/.travis.yml index a7e86c1..054945d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -68,6 +68,7 @@ jobs: - <<: *test_job python: 3.10-dev dist: focal + env: BUILD_LXML_FROM_GIT=1 - &coverage_jobs dist: bionic diff --git a/.travis/install.sh b/.travis/install.sh index 2c1d6f5..1cd0489 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -45,6 +45,18 @@ else sudo apt-get -y --allow-unauthenticated install --reinstall d-apt-keyring sudo apt-get update && sudo apt-get install dmd-compiler dub + + if [[ "$BUILD_LXML_FROM_GIT" == "1" ]]; then + pip uninstall lxml + # for ubuntu 20.04 needed this as well + sudo apt install libxslt1-dev + + # then use git versions of cythong and lxml (lxml's cython build uses xslt1-config which is why the above was needed) + pip install git+https://github.com/cython/cython.git@0.29.x + pip install git+https://github.com/lxml/lxml.git + fi + + # sudo wget http://master.dl.sourceforge.net/project/d-apt/files/d-apt.list -O /etc/apt/sources.list.d/d-apt.list # wget -qO - https://dlang.org/d-keyring.gpg | sudo apt-key add - # sudo apt-get update && sudo apt-get -y --allow-unauthenticated install dmd-bin -- cgit v0.12 From cadf26201c295c8f8cc1a3c8dbdf99f85f3dc3f1 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 23 Jan 2021 17:28:51 -0800 Subject: [appveyor skip] fix hanging pip uninstall --- .travis/install.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis/install.sh b/.travis/install.sh index 1cd0489..93e446e 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -47,7 +47,9 @@ else if [[ "$BUILD_LXML_FROM_GIT" == "1" ]]; then - pip uninstall lxml + pip uninstall -y lxml + pip cache purge + # for ubuntu 20.04 needed this as well sudo apt install libxslt1-dev -- cgit v0.12 From 3d698e0c3f03349573eba8c0d19f3984a5d53dbf Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 23 Jan 2021 18:12:02 -0800 Subject: [ci skip] fix typo --- .travis/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis/install.sh b/.travis/install.sh index 93e446e..601a74f 100755 --- a/.travis/install.sh +++ b/.travis/install.sh @@ -53,7 +53,7 @@ else # for ubuntu 20.04 needed this as well sudo apt install libxslt1-dev - # then use git versions of cythong and lxml (lxml's cython build uses xslt1-config which is why the above was needed) + # then use git versions of cython and lxml (lxml's cython build uses xslt1-config which is why the above was needed) pip install git+https://github.com/cython/cython.git@0.29.x pip install git+https://github.com/lxml/lxml.git fi -- cgit v0.12 From cf6581576273815aaaa41967deb96d229de7f549 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 31 Jan 2021 10:33:28 -0700 Subject: Adding-emitter example for User Guide [ci skip] Add an example on adding an emitter to an existing builder, based on a mailing-list discussion with Jeremy Elson. Also: * Try to model "best practice" by changing instances of hand-modifying env['ENV']['PATH'] in examples to using AppendENVPath function. * Fixed a couple of Py2-style print statements. * Tweaked markup on a couple of instances of site_scons. * Black-formatted examples in the two userguide sections that were otherwise modified. * Dropped old cons doc content which was included as a big comment at the fromt of builders-writing.xml. Signed-off-by: Mats Wichmann --- CHANGES.txt | 2 + SCons/Environment.xml | 8 +- .../examples/builders_adding_emitter_1.xml | 13 + doc/man/scons.xml | 6 +- doc/user/builders-writing.xml | 332 ++++++++++++--------- doc/user/factories.xml | 122 ++++---- doc/user/file-removal.xml | 3 +- 7 files changed, 276 insertions(+), 210 deletions(-) create mode 100644 doc/generated/examples/builders_adding_emitter_1.xml diff --git a/CHANGES.txt b/CHANGES.txt index f3e2b2a..c3ffef6 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -12,6 +12,8 @@ RELEASE VERSION/DATE TO BE FILLED IN LATER - Initial support in tests for Python 3.10 - expected bytecode and one changed expected exception message. Change some more regexes to be specified as rawstrings in response to DeprecationWarnings. + - Add an example of adding an emitter to User Guide (concept + from Jeremy Elson) RELEASE 4.1.0 - Tues, 19 Jan 2021 15:04:42 -0700 diff --git a/SCons/Environment.xml b/SCons/Environment.xml index cfa99db..8900791 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -546,10 +546,10 @@ Example: -print 'before:',env['ENV']['INCLUDE'] +print('before:', env['ENV']['INCLUDE']) include_path = '/foo/bar:/foo' env.AppendENVPath('INCLUDE', include_path) -print 'after:',env['ENV']['INCLUDE'] +print('after:', env['ENV']['INCLUDE']) yields: before: /foo:/biz @@ -2501,10 +2501,10 @@ Example: -print 'before:',env['ENV']['INCLUDE'] +print('before:', env['ENV']['INCLUDE']) include_path = '/foo/bar:/foo' env.PrependENVPath('INCLUDE', include_path) -print 'after:',env['ENV']['INCLUDE'] +print('after:', env['ENV']['INCLUDE']) diff --git a/doc/generated/examples/builders_adding_emitter_1.xml b/doc/generated/examples/builders_adding_emitter_1.xml new file mode 100644 index 0000000..261b428 --- /dev/null +++ b/doc/generated/examples/builders_adding_emitter_1.xml @@ -0,0 +1,13 @@ +% scons -Q --tree=prune +cc -o hello.o -c hello.c +cc -o hello -Wl,-Map=hello.map,--cref hello.o ++-. + +-SConstruct + +-hello + | +-hello.o + | +-hello.c + +-hello.c + +-hello.map + | +-[hello.o] + +-[hello.o] + diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 57bd209..459d84d 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -1522,7 +1522,7 @@ any out-of-date target files, but do not execute the commands. Prevents the automatic addition of the standard -site_scons +site_scons dirs to sys.path. Also prevents loading the @@ -1656,7 +1656,7 @@ Also suppresses SCons status messages. Uses the named dir as the site directory rather than the default -site_scons +site_scons directories. This directory will be prepended to sys.path, the module @@ -1666,7 +1666,7 @@ will be loaded if it exists, and will be added to the default toolpath. The default set of -site_scons +site_scons directories used when is not specified depends on the system platform, as follows. diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml index d9a155f..8586853 100644 --- a/doc/user/builders-writing.xml +++ b/doc/user/builders-writing.xml @@ -45,78 +45,6 @@ --> - - Although &SCons; provides many useful methods @@ -188,9 +116,8 @@ bld = Builder(action = 'foobuild < $SOURCE > $TARGET') bld = Builder(action = 'foobuild < $SOURCE > $TARGET') -env = Environment(BUILDERS = {'Foo' : bld}) -import os -env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() +env = Environment(BUILDERS={'Foo': bld}) +env.AppendENVPath('PATH', os.getcwd()) env.Foo('file.foo', 'file.input') @@ -203,7 +130,7 @@ cat bld = Builder(action = 'foobuild < $SOURCE > $TARGET') -env = Environment(BUILDERS = {'Foo' : bld}) +env = Environment(BUILDERS={'Foo': bld}) @@ -261,14 +188,17 @@ env.Foo('file.foo', 'file.input') --> -import SCons.Defaults; SCons.Defaults.ConstructionEnvironment['TOOLS'] = {}; bld = Builder(action = 'foobuild < $SOURCE > $TARGET') -env = Environment(BUILDERS = {'Foo' : bld}) +import SCons.Defaults + +SCons.Defaults.ConstructionEnvironment['TOOLS'] = {} +bld = Builder(action='foobuild < $SOURCE > $TARGET') +env = Environment(BUILDERS={'Foo': bld}) env.Foo('file.foo', 'file.input') env.Program('hello.c') -bld = Builder(action = 'foobuild < $SOURCE > $TARGET') -env = Environment(BUILDERS = {'Foo' : bld}) +bld = Builder(action='foobuild < $SOURCE > $TARGET') +env = Environment(BUILDERS={'Foo': bld}) env.Foo('file.foo', 'file.input') env.Program('hello.c') @@ -296,10 +226,9 @@ hello.c env = Environment() -import os -env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() -bld = Builder(action = 'foobuild < $SOURCE > $TARGET') -env.Append(BUILDERS = {'Foo' : bld}) +env.AppendENVPath('PATH', os.getcwd()) +bld = Builder(action='foobuild < $SOURCE > $TARGET') +env.Append(BUILDERS={'Foo': bld}) env.Foo('file.foo', 'file.input') env.Program('hello.c') @@ -316,8 +245,8 @@ cat env = Environment() -bld = Builder(action = 'foobuild < $SOURCE > $TARGET') -env.Append(BUILDERS = {'Foo' : bld}) +bld = Builder(action='foobuild < $SOURCE > $TARGET') +env.Append(BUILDERS={'Foo': bld}) env.Foo('file.foo', 'file.input') env.Program('hello.c') @@ -331,7 +260,7 @@ env.Program('hello.c') env = Environment() -bld = Builder(action = 'foobuild < $SOURCE > $TARGET') +bld = Builder(action='foobuild < $SOURCE > $TARGET') env['BUILDERS']['Foo'] = bld env.Foo('file.foo', 'file.input') env.Program('hello.c') @@ -374,12 +303,13 @@ env.Program('hello.c') -bld = Builder(action = 'foobuild < $SOURCE > $TARGET', - suffix = '.foo', - src_suffix = '.input') -env = Environment(BUILDERS = {'Foo' : bld}) -import os -env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() +bld = Builder( + action='foobuild < $SOURCE > $TARGET', + suffix='.foo', + src_suffix='.input', +) +env = Environment(BUILDERS={'Foo': bld}) +env.AppendENVPath('PATH', os.getcwd()) env.Foo('file1') env.Foo('file2') @@ -395,10 +325,12 @@ cat -bld = Builder(action = 'foobuild < $SOURCE > $TARGET', - suffix = '.foo', - src_suffix = '.input') -env = Environment(BUILDERS = {'Foo' : bld}) +bld = Builder( + action='foobuild < $SOURCE > $TARGET', + suffix='.foo', + src_suffix='.input', +) +env = Environment(BUILDERS={'Foo': bld}) env.Foo('file1') env.Foo('file2') @@ -525,10 +457,13 @@ def build_function(target, source, env): def build_function(target, source, env): # Code to build "target" from "source" return None -bld = Builder(action = build_function, - suffix = '.foo', - src_suffix = '.input') -env = Environment(BUILDERS = {'Foo' : bld}) + +bld = Builder( + action=build_function, + suffix='.foo', + src_suffix='.input', +) +env = Environment(BUILDERS={'Foo': bld}) env.Foo('file') @@ -673,12 +608,14 @@ def generate_actions(source, target, env, for_signature): def generate_actions(source, target, env, for_signature): return 'foobuild < %s > %s' % (source[0], target[0]) -bld = Builder(generator = generate_actions, - suffix = '.foo', - src_suffix = '.input') -env = Environment(BUILDERS = {'Foo' : bld}) -import os -env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + +bld = Builder( + generator=generate_actions, + suffix='.foo', + src_suffix='.input', +) +env = Environment(BUILDERS={'Foo': bld}) +env.AppendENVPath('PATH', os.getcwd()) env.Foo('file') @@ -692,10 +629,13 @@ cat def generate_actions(source, target, env, for_signature): return 'foobuild < %s > %s' % (source[0], target[0]) -bld = Builder(generator = generate_actions, - suffix = '.foo', - src_suffix = '.input') -env = Environment(BUILDERS = {'Foo' : bld}) + +bld = Builder( + generator=generate_actions, + suffix='.foo', + src_suffix='.input', +) +env = Environment(BUILDERS={'Foo': bld}) env.Foo('file') @@ -736,7 +676,7 @@ env.Foo('file') For example, suppose you want to define a Builder - that always calls a foobuild program, + that always calls a foobuild program, and you want to automatically add a new target file named new_target @@ -753,13 +693,15 @@ def modify_targets(target, source, env): target.append('new_target') source.append('new_source') return target, source -bld = Builder(action = 'foobuild $TARGETS - $SOURCES', - suffix = '.foo', - src_suffix = '.input', - emitter = modify_targets) -env = Environment(BUILDERS = {'Foo' : bld}) -import os -env['ENV']['PATH'] = env['ENV']['PATH'] + os.pathsep + os.getcwd() + +bld = Builder( + action='foobuild $TARGETS - $SOURCES', + suffix='.foo', + src_suffix='.input', + emitter=modify_targets, +) +env = Environment(BUILDERS={'Foo': bld}) +env.AppendENVPath('PATH', os.getcwd()) env.Foo('file') @@ -778,11 +720,14 @@ def modify_targets(target, source, env): target.append('new_target') source.append('new_source') return target, source -bld = Builder(action = 'foobuild $TARGETS - $SOURCES', - suffix = '.foo', - src_suffix = '.input', - emitter = modify_targets) -env = Environment(BUILDERS = {'Foo' : bld}) + +bld = Builder( + action='foobuild $TARGETS - $SOURCES', + suffix='.foo', + src_suffix='.input', + emitter=modify_targets, +) +env = Environment(BUILDERS={'Foo': bld}) env.Foo('file') @@ -805,7 +750,7 @@ env.Foo('file') To do this, specify a string containing a construction variable expansion as the emitter when you call - the &Builder; function, + the &f-link-Builder; function, and set that construction variable to the desired emitter function in different construction environments: @@ -815,18 +760,21 @@ env.Foo('file') -bld = Builder(action = './my_command $SOURCES > $TARGET', - suffix = '.foo', - src_suffix = '.input', - emitter = '$MY_EMITTER') +bld = Builder( + action='./my_command $SOURCES > $TARGET', + suffix='.foo', + src_suffix='.input', + emitter='$MY_EMITTER', +) + def modify1(target, source, env): return target, source + ['modify1.in'] + def modify2(target, source, env): return target, source + ['modify2.in'] -env1 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify1) -env2 = Environment(BUILDERS = {'Foo' : bld}, - MY_EMITTER = modify2) + +env1 = Environment(BUILDERS={'Foo': bld}, MY_EMITTER=modify1) +env2 = Environment(BUILDERS={'Foo': bld}, MY_EMITTER=modify2) env1.Foo('file1') env2.Foo('file2') @@ -863,7 +811,92 @@ cat
- -import os -denv = DefaultEnvironment() -denv.AppendENVPath('PATH', os.getcwd()) +def_env = DefaultEnvironment() +def_env.AppendENVPath('PATH', Dir('.')) SConscript('S') file.in @@ -230,10 +230,10 @@ Command( ], ) + -import os -denv = DefaultEnvironment() -denv.AppendENVPath('PATH', os.getcwd()) +def_env = DefaultEnvironment() +def_env.AppendENVPath('PATH', Dir('.')) SConscript('S') file.in @@ -330,10 +330,10 @@ Command( ], ) + -import os -denv = DefaultEnvironment() -denv.AppendENVPath('PATH', os.getcwd()) +def_env = DefaultEnvironment() +def_env.AppendENVPath('PATH', Dir('.')) SConscript('S') file.in @@ -377,9 +377,6 @@ Command( ) -import os -denv = DefaultEnvironment() -denv.AppendENVPath('PATH', os.getcwd()) SConscript('S') file.in @@ -427,10 +424,10 @@ Command( ], ) + -import os -denv = DefaultEnvironment() -denv.AppendENVPath('PATH', os.getcwd()) +def_env = DefaultEnvironment() +def_env.AppendENVPath('PATH', Dir('.')) SConscript('S') file.in diff --git a/doc/user/file-removal.xml b/doc/user/file-removal.xml index b6bd096..6eb688d 100644 --- a/doc/user/file-removal.xml +++ b/doc/user/file-removal.xml @@ -202,10 +202,10 @@ int f3() { } t = Command('foo.out', 'foo.in', 'build -o $TARGET $SOURCE') Clean(t, 'foo.log') + -import os -denv = DefaultEnvironment() -denv.AppendENVPath('PATH', os.getcwd()) +def_env = DefaultEnvironment() +def_env.AppendENVPath('PATH', Dir('.')) SConscript('S') -- cgit v0.12 From 80722dbc5dad63e27ae01e1fa86b403dfaff89b8 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Thu, 18 Feb 2021 09:47:12 -0700 Subject: Move LIBS warning from Builders to LIBS definition [skip appveor] [skip travis] The previous commit for PR #3888 added a warning about using improper values for LIBS in the section on Builder Methods. Per review comments, moved this to the definition of the LIBS construction variable. Work in that area led to several wording changes, and link-ifying some consvar references. Signed-off-by: Mats Wichmann --- SCons/Defaults.xml | 216 +++++++++++++++++++++++++------------------- SCons/Platform/Platform.xml | 4 +- doc/man/scons.xml | 10 +- 3 files changed, 128 insertions(+), 102 deletions(-) diff --git a/SCons/Defaults.xml b/SCons/Defaults.xml index 6b034d9..da45cdb 100644 --- a/SCons/Defaults.xml +++ b/SCons/Defaults.xml @@ -72,14 +72,13 @@ file. -An automatically-generated construction variable +An automatically-generated &consvar; containing the C preprocessor command-line options to define values. The value of &cv-_CPPDEFFLAGS; is created by respectively prepending and appending -&cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; -to the beginning and end -of each definition in &cv-CPPDEFINES;. +&cv-link-CPPDEFPREFIX; and &cv-link-CPPDEFSUFFIX; +to each definition in &cv-link-CPPDEFINES;. @@ -90,7 +89,7 @@ of each definition in &cv-CPPDEFINES;. A platform independent specification of C preprocessor definitions. The definitions will be added to command lines through the automatically-generated -&cv-_CPPDEFFLAGS; construction variable (see above), +&cv-link-_CPPDEFFLAGS; &consvar; (see above), which is constructed according to the type of value of &cv-CPPDEFINES;:
@@ -98,10 +97,9 @@ the type of value of &cv-CPPDEFINES;: If &cv-CPPDEFINES; is a string, the values of the -&cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; -construction variables -will be respectively prepended and appended to the beginning and end -of each definition in &cv-CPPDEFINES;. +&cv-link-CPPDEFPREFIX; and &cv-link-CPPDEFSUFFIX; &consvars; +will be respectively prepended and appended to +each definition in &cv-CPPDEFINES;. @@ -113,10 +111,9 @@ env = Environment(CPPDEFINES='xyz') If &cv-CPPDEFINES; is a list, the values of the -&cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; -construction variables -will be respectively prepended and appended to the beginning and end -of each element in the list. +&cv-link-CPPDEFPREFIX; and &cv-link-CPPDEFSUFFIX; &consvars; +will be respectively prepended and appended to +each element in the list. If any element is a list or tuple, then the first item is the name being defined and the second item is its value: @@ -131,10 +128,9 @@ env = Environment(CPPDEFINES=[('B', 2), 'A']) If &cv-CPPDEFINES; is a dictionary, the values of the -&cv-CPPDEFPREFIX; and &cv-CPPDEFSUFFIX; -construction variables -will be respectively prepended and appended to the beginning and end -of each item from the dictionary. +&cv-link-CPPDEFPREFIX; and &cv-link-CPPDEFSUFFIX; &consvars; +will be respectively prepended and appended to +each item from the dictionary. The key of each dictionary item is a name being defined to the dictionary item's corresponding value; @@ -161,9 +157,9 @@ env = Environment(CPPDEFINES={'B':2, 'A':None}) The prefix used to specify preprocessor definitions on the C compiler command line. -This will be prepended to the beginning of each definition -in the &cv-CPPDEFINES; construction variable -when the &cv-_CPPDEFFLAGS; variable is automatically generated. +This will be prepended to each definition +in the &cv-link-CPPDEFINES; &consvar; +when the &cv-link-_CPPDEFFLAGS; variable is automatically generated. @@ -173,9 +169,9 @@ when the &cv-_CPPDEFFLAGS; variable is automatically generated. The suffix used to specify preprocessor definitions on the C compiler command line. -This will be appended to the end of each definition -in the &cv-CPPDEFINES; construction variable -when the &cv-_CPPDEFFLAGS; variable is automatically generated. +This will be appended to each definition +in the &cv-link-CPPDEFINES; &consvar; +when the &cv-link-_CPPDEFFLAGS; variable is automatically generated. @@ -183,13 +179,13 @@ when the &cv-_CPPDEFFLAGS; variable is automatically generated. -An automatically-generated construction variable +An automatically-generated &consvar; containing the C preprocessor command-line options for specifying directories to be searched for include files. The value of &cv-_CPPINCFLAGS; is created -by respectively prepending and appending &cv-INCPREFIX; and &cv-INCSUFFIX; -to the beginning and end -of each directory in &cv-CPPPATH;. +by respectively prepending and appending +&cv-link-INCPREFIX; and &cv-link-INCSUFFIX; +to each directory in &cv-link-CPPPATH;. @@ -199,13 +195,24 @@ of each directory in &cv-CPPPATH;. The list of directories that the C preprocessor will search for include directories. The C/C++ implicit dependency scanner will search these -directories for include files. Don't explicitly put include directory -arguments in CCFLAGS or CXXFLAGS because the result will be non-portable -and the directories will not be searched by the dependency scanner. Note: -directory names in CPPPATH will be looked-up relative to the SConscript -directory when they are used in a command. To force -&scons; -to look-up a directory relative to the root of the source tree use #: +directories for include files. +Do not put include directory directives +directly into &cv-link-CCFLAGS; or &cv-link-CXXFLAGS; +as the result will be non-portable +and the directories will not be searched by the dependency scanner. +&cv-CPPPATH; should be a list of path strings, +or a single string, not a pathname list joined by +Python's os.sep. + + + +Note: +directory names in &cv-link-CPPPATH; +will be looked-up relative to the directory of the SConscript file +when they are used in a command. +To force &scons; +to look-up a directory relative to the root of the source tree use +the # prefix: @@ -214,7 +221,7 @@ env = Environment(CPPPATH='#/include') The directory look-up can also be forced using the -&Dir;() +&f-link-Dir; function: @@ -226,17 +233,14 @@ env = Environment(CPPPATH=include) The directory list will be added to command lines through the automatically-generated -&cv-_CPPINCFLAGS; -construction variable, +&cv-link-_CPPINCFLAGS; &consvar;, which is constructed by -respectively prepending and appending the value of the -&cv-INCPREFIX; and &cv-INCSUFFIX; -construction variables -to the beginning and end -of each directory in &cv-CPPPATH;. +respectively prepending and appending the values of the +&cv-link-INCPREFIX; and &cv-link-INCSUFFIX; &consvars; +to each directory in &cv-link-CPPPATH;. Any command lines you define that need -the CPPPATH directory list should -include &cv-_CPPINCFLAGS;: +the &cv-CPPPATH; directory list should +include &cv-link-_CPPINCFLAGS;: @@ -302,9 +306,9 @@ The default list is: The prefix used to specify an include directory on the C compiler command line. -This will be prepended to the beginning of each directory -in the &cv-CPPPATH; and &cv-FORTRANPATH; construction variables -when the &cv-_CPPINCFLAGS; and &cv-_FORTRANINCFLAGS; +This will be prepended to each directory +in the &cv-link-CPPPATH; and &cv-link-FORTRANPATH; &consvars; +when the &cv-link-_CPPINCFLAGS; and &cv-link-_FORTRANINCFLAGS; variables are automatically generated. @@ -315,9 +319,9 @@ variables are automatically generated. The suffix used to specify an include directory on the C compiler command line. -This will be appended to the end of each directory -in the &cv-CPPPATH; and &cv-FORTRANPATH; construction variables -when the &cv-_CPPINCFLAGS; and &cv-_FORTRANINCFLAGS; +This will be appended to each directory +in the &cv-link-CPPPATH; and &cv-link-FORTRANPATH; &consvars; +when the &cv-link-_CPPINCFLAGS; and &cv-link-_FORTRANINCFLAGS; variables are automatically generated. @@ -386,9 +390,9 @@ An automatically-generated construction variable containing the linker command-line options for specifying directories to be searched for library. The value of &cv-_LIBDIRFLAGS; is created -by respectively prepending and appending &cv-LIBDIRPREFIX; and &cv-LIBDIRSUFFIX; -to the beginning and end -of each directory in &cv-LIBPATH;. +by respectively prepending and appending &cv-link-LIBDIRPREFIX; +and &cv-link-LIBDIRSUFFIX; +to each directory in &cv-link-LIBPATH;. @@ -397,9 +401,9 @@ of each directory in &cv-LIBPATH;. The prefix used to specify a library directory on the linker command line. -This will be prepended to the beginning of each directory -in the &cv-LIBPATH; construction variable -when the &cv-_LIBDIRFLAGS; variable is automatically generated. +This will be prepended to each directory +in the &cv-link-LIBPATH; construction variable +when the &cv-link-_LIBDIRFLAGS; variable is automatically generated. @@ -408,9 +412,9 @@ when the &cv-_LIBDIRFLAGS; variable is automatically generated. The suffix used to specify a library directory on the linker command line. -This will be appended to the end of each directory -in the &cv-LIBPATH; construction variable -when the &cv-_LIBDIRFLAGS; variable is automatically generated. +This will be appended to each directory +in the &cv-link-LIBPATH; construction variable +when the &cv-link-_LIBDIRFLAGS; variable is automatically generated. @@ -421,10 +425,10 @@ when the &cv-_LIBDIRFLAGS; variable is automatically generated. An automatically-generated construction variable containing the linker command-line options for specifying libraries to be linked with the resulting target. -The value of &cv-_LIBFLAGS; is created -by respectively prepending and appending &cv-LIBLINKPREFIX; and &cv-LIBLINKSUFFIX; -to the beginning and end -of each filename in &cv-LIBS;. +The value of &cv-link-_LIBFLAGS; is created +by respectively prepending and appending &cv-link-LIBLINKPREFIX; +and &cv-link-LIBLINKSUFFIX; +to each filename in &cv-link-LIBS;. @@ -433,9 +437,9 @@ of each filename in &cv-LIBS;. The prefix used to specify a library to link on the linker command line. -This will be prepended to the beginning of each library -in the &cv-LIBS; construction variable -when the &cv-_LIBFLAGS; variable is automatically generated. +This will be prepended to each library +in the &cv-link-LIBS; construction variable +when the &cv-link-_LIBFLAGS; variable is automatically generated. @@ -444,9 +448,9 @@ when the &cv-_LIBFLAGS; variable is automatically generated. The suffix used to specify a library to link on the linker command line. -This will be appended to the end of each library -in the &cv-LIBS; construction variable -when the &cv-_LIBFLAGS; variable is automatically generated. +This will be appended to each library +in the &cv-link-LIBS; construction variable +when the &cv-link-_LIBFLAGS; variable is automatically generated. @@ -454,16 +458,33 @@ when the &cv-_LIBFLAGS; variable is automatically generated. -The list of directories that will be searched for libraries. +The list of directories that will be searched for libraries +specified by the &cv-link-LIBS; &consvar;. +&cv-LIBPATH; should be a list of path strings, +or a single string, not a pathname list joined by +Python's os.sep. + + +Do not put library search directives directly +into &cv-LINKFLAGS; or &cv-SHLINKFLAGS; +as the result will be non-portable. + + + + +Note: +directory names in &cv-LIBPATH; will be looked-up relative to the +directory of the SConscript file +when they are used in a command. +To force &scons; +to look-up a directory relative to the root of the source tree use +the # prefix: @@ -472,8 +493,7 @@ env = Environment(LIBPATH='#/libs') The directory look-up can also be forced using the -&Dir;() -function: +&f-link-Dir; function: @@ -484,16 +504,15 @@ env = Environment(LIBPATH=libs) The directory list will be added to command lines through the automatically-generated -&cv-_LIBDIRFLAGS; +&cv-link-_LIBDIRFLAGS; construction variable, which is constructed by respectively prepending and appending the values of the -&cv-LIBDIRPREFIX; and &cv-LIBDIRSUFFIX; +&cv-link-LIBDIRPREFIX; and &cv-link-LIBDIRSUFFIX; construction variables -to the beginning and end -of each directory in &cv-LIBPATH;. +to each directory in &cv-LIBPATH;. Any command lines you define that need -the LIBPATH directory list should +the &cv-LIBPATH; directory list should include &cv-_LIBDIRFLAGS;: @@ -509,22 +528,33 @@ env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE A list of one or more libraries that will be linked with any executable programs -created by this environment. +created by this environment, +or if used in an override, +executable programs created by the Builder for which +the override is in effect. +String-valued library names should include +only the library base names +(without prefixes such as lib +or suffixes such as .so or .dll). The library list will be added to command lines through the automatically-generated -&cv-_LIBFLAGS; -construction variable, +&cv-_LIBFLAGS; &consvar; which is constructed by respectively prepending and appending the values of the -&cv-LIBLINKPREFIX; and &cv-LIBLINKSUFFIX; -construction variables -to the beginning and end -of each filename in &cv-LIBS;. +&cv-LIBLINKPREFIX; and &cv-LIBLINKSUFFIX; &consvars; +to each library name in &cv-LIBS;. +Library name strings should not include a +path component, instead the compiler will be +directed to look for libraries in the paths +specified by &cv-link-LIBPATH;. + + + Any command lines you define that need -the LIBS library list should +the &cv-LIBS; library list should include &cv-_LIBFLAGS;: @@ -534,12 +564,12 @@ env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE If you add a -File +File object to the &cv-LIBS; list, the name of that file will be added to &cv-_LIBFLAGS;, -and thus the link line, as is, without +and thus to the link line, as-is, without &cv-LIBLINKPREFIX; or &cv-LIBLINKSUFFIX;. diff --git a/SCons/Platform/Platform.xml b/SCons/Platform/Platform.xml index b150906..f1c2e74 100644 --- a/SCons/Platform/Platform.xml +++ b/SCons/Platform/Platform.xml @@ -53,7 +53,7 @@ A list of all legal prefixes for library file names. When searching for library dependencies, SCons will look for files with these prefixes, the base library name, -and suffixes in the &cv-LIBSUFFIXES; list. +and suffixes from the &cv-link-LIBSUFFIXES; list. @@ -76,7 +76,7 @@ to reflect the names of the libraries they create. A list of all legal suffixes for library file names. When searching for library dependencies, -SCons will look for files with prefixes, in the &cv-LIBPREFIXES; list, +SCons will look for files with prefixes from the &cv-link-LIBPREFIXES; list, the base library name, and these suffixes. diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 2705163..691b815 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -2881,20 +2881,16 @@ to the Python module:
from SCons.Script import * -Builder methods return a Node-list, +Builder methods return a NodeList a list-like object whose elements are Nodes, &SCons;' internal representation of build targets or sources. See for more information. -The returned Node-list object +The returned iNodeList object can be passed to other builder methods as source(s) or passed to any &SCons; function or method where a filename would normally be accepted. -Node-lists should not be used to set &consvars; -such as &cv-link-LIBS; that expect to do transformation -on strings - for that case, -use the base name of the library as a string. For example, @@ -2951,7 +2947,7 @@ operator (+ or +=) to append builder results to a Python list. Because the list and the object are different types, Python will not update the original list in place, -but will instead create a new Node-list object +but will instead create a new NodeList object containing the concatenation of the list elements and the builder results. This will cause problems for any other Python variables -- cgit v0.12 From ccd3e3312ae8c00e407b14589d48ee65466eb4a3 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 19 Feb 2021 09:24:49 -0700 Subject: Fix env = Program usage in docs [skip appveyor] [skip travis] Two dodgy bits of example code were discovered which do "env = Program(....)", fixed up. Signed-off-by: Mats Wichmann --- doc/man/scons.xml | 2 +- doc/user/environments.xml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 57bd209..589fd06 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -2828,7 +2828,7 @@ broken into individual settings and merged into the appropriate &consvars;. -env = Program('hello', 'hello.c', parse_flags='-Iinclude -DEBUG -lm') +env.Program('hello', 'hello.c', parse_flags='-Iinclude -DEBUG -lm') This example adds 'include' to diff --git a/doc/user/environments.xml b/doc/user/environments.xml index 3c3eeae..2bcc7fc 100644 --- a/doc/user/environments.xml +++ b/doc/user/environments.xml @@ -1702,7 +1702,8 @@ void main() { } -env = Program('hello', 'hello.c', parse_flags='-Iinclude -DEBUG -lm') +env = Environment() +env.Program('hello', 'hello.c', parse_flags='-Iinclude -DEBUG -lm') #include <stdio.h> -- cgit v0.12 From 42475223c5d41f5868007c9602cd42a127c5528c Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 21 Feb 2021 10:25:41 -0700 Subject: [PR #3888] builder doc changes per review comments [skip appveyor] [skip travis] Don't try to expand on overrides concept in cv-LIBS, put something in the construction var section introduction instead. Rearrange some more things in the builder methods section. Signed-off-by: Mats Wichmann --- SCons/Defaults.xml | 15 +++++------ doc/man/scons.xml | 79 +++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 61 insertions(+), 33 deletions(-) diff --git a/SCons/Defaults.xml b/SCons/Defaults.xml index da45cdb..bb52823 100644 --- a/SCons/Defaults.xml +++ b/SCons/Defaults.xml @@ -526,19 +526,16 @@ env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE A list of one or more libraries -that will be linked with -any executable programs -created by this environment, -or if used in an override, -executable programs created by the Builder for which -the override is in effect. +that will be added to the link line +for linking with any executable program +created by the &consenv; or override. String-valued library names should include -only the library base names -(without prefixes such as lib -or suffixes such as .so or .dll). +only the library base names, +without prefixes such as lib +or suffixes such as .so or .dll. The library list will be added to command lines through the automatically-generated &cv-_LIBFLAGS; &consvar; diff --git a/doc/man/scons.xml b/doc/man/scons.xml index 691b815..9369542 100644 --- a/doc/man/scons.xml +++ b/doc/man/scons.xml @@ -2614,9 +2614,9 @@ env.SomeTool(targets, sources) You tell &scons; what to build by calling Builders, functions which take -particular actions to produce a particular result type -(conventionally described by the builder name) -when given source files of a particular type. +particular action(s) to produce a particular result type +(conventionally described by the builder name such as &b-Program;) +when given source files of a particular type. Calling a builder defines one or more targets to the build system; whether the targets are actually built on a given invocation is determined by command-line options, @@ -2630,7 +2630,7 @@ defines a number of builders, and you can also write your own. Builders are attached to a &consenv; as methods, and the available builder methods are listed as key-value pairs in the -BUILDERS attribute of the &consenv;. +BUILDERS attribute of the &consenv;. The available builders can be displayed like this for debugging purposes: @@ -2642,16 +2642,23 @@ print("Builders:", list(env['BUILDERS'])) Builder methods take two required arguments: -target -(a target or a list of targets to be built) +target and -source -(a source or list of sources to be used as input -when building), -although in some circumstances, -the target argument can be omitted (see below). +source. +Either can be passed as a scalar or as a list. +The target and source arguments +can be specified either as positional arguments, +in which case target comes first, or as +keyword arguments, using target= +and source=. +Although both arguments are required, +in one particular case the target argument can actually be omitted +because it can be inferred and &SCons; supplies it (see below). Builder methods also take a variety of keyword arguments, described below. + + + The builder may add other targets beyond those requested if indicated by an Emitter (see and, for example, @@ -2671,11 +2678,6 @@ strings of white-space characters as the delimiter. method, but succeeds even if the input isn't a string.) -The target and source arguments to a builder method -can be specified either as positional arguments, -in which case the target comes first, or as -keyword arguments, using target= -and source=. The following are equivalent examples of calling the &Program; builder method: @@ -2703,6 +2705,7 @@ contains separator characters, the search follows down from the starting point, which is the top of the directory tree for an absolute path and the current directory for a relative path. + &scons; recognizes a third way to specify path strings: if the string begins with @@ -2881,26 +2884,24 @@ to the Python module: from SCons.Script import * -Builder methods return a NodeList +Builder methods return a NodeList, a list-like object whose elements are Nodes, &SCons;' internal representation of build targets or sources. See for more information. - - -The returned iNodeList object +The returned NodeList object can be passed to other builder methods as source(s) or passed to any &SCons; function or method where a filename would normally be accepted. - For example, + For example, to add a specific preprocessor define when compiling one specific object file but not the others: bar_obj_list = env.StaticObject('bar.c', CPPDEFINES='-DBAR') -env.Program(source=['foo.c', bar_obj_list, 'main.c']) +env.Program("prog", ['foo.c', bar_obj_list, 'main.c']) Using a Node as in this example @@ -2910,6 +2911,16 @@ a platform-specific object suffix when calling the &Program; builder method. +The NodeList object +is also convenient to pass to the &f-link-Default; function, +for the same reason of avoiding a platform-specific name: + + + +tgt = env.Program("prog", ["foo.c", "bar.c", "main.c"]) +Default(tgt) + + Builder calls will automatically "flatten" lists passed as source and target, so they are free to contain elements which are themselves lists, such as @@ -3476,14 +3487,34 @@ env = Environment(CC="cc") env2 = env.Clone(CC="cl.exe") + +&Consvars; can also be supplied as keyword +arguments to a builder, in which case those settings +affect only the work done by that builder call, +and not the &consenv; as a whole. +This concept is called an override: + + + +env.Program('hello', 'hello.c', LIBS=['gl', 'glut']) + + A number of useful &consvars; are automatically defined by scons for each supported platform, and additional &consvars; can be defined by the user. The following is a list of the possible -automatically defined &consvars;. The actual list available +automatically defined &consvars;. + + +Note the actual list available at execution time will not include all of these, as the ones detected as not being useful (wrong platform, necessary external command or files not installed, etc.) will not be set up. -: +Correct build setups should be resilient to the possible +absence of certain &consvars; before using them, +for example by using a &Python; dictionary +get method to retrieve the value and +taking alternative action if the return indicates the variable is unset. + -- cgit v0.12 From a21828dbffe74bcf8357248bc8b9ba7675da923d Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sun, 21 Feb 2021 11:07:08 -0700 Subject: Tweaks to Packaging docs [skip appveyor] [skip travis] Fixed the pointer to opensource.org to actually be a live link. Many construction vars didn't really have context - most notably the LICENSING one. It's hard to remember that while there's plenty of context in the packaging.xml doc, the consvars will be sorted separately from the builder and tool definitions, and will be sorted alphabetically. Addressed by adding reference to the Package builder, as being a cheaper fix than figuring out rewording. Where there were large sequences of cvars, added to the first one (X_RPM and X_IPK), they'll Signed-off-by: Mats Wichmann --- SCons/Tool/packaging/packaging.xml | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/SCons/Tool/packaging/packaging.xml b/SCons/Tool/packaging/packaging.xml index 8c22503..59eb52f 100644 --- a/SCons/Tool/packaging/packaging.xml +++ b/SCons/Tool/packaging/packaging.xml @@ -26,7 +26,7 @@ See its __doc__ string for a discussion of the format. -Sets construction variables for the &b-Package; Builder. +Sets construction variables for the &b-link-Package; Builder. If this tool is enabled, the command-line option is also enabled. @@ -131,7 +131,7 @@ env.Package( SUMMARY="balalalalal", DESCRIPTION="this should be really really long", X_RPM_GROUP="Application/fu", - SOURCE_URL="http://foo.org/foo-1.2.3.tar.gz", + SOURCE_URL="https://foo.org/foo-1.2.3.tar.gz", ) @@ -142,7 +142,7 @@ since it is not under the project top directory. However, since no source is specified to the &b-Package; builder, it is selected for packaging by the default sources rule. -Since packaging is done using &cv-PACKAGEROOT;, no write is +Since packaging is done using &cv-link-PACKAGEROOT;, no write is actually done to the system's /bin directory, and the target will be selected since after rebasing to underneath &cv-PACKAGEROOT; it is now under @@ -167,6 +167,7 @@ and the BuildArch: field in the RPM .spec file, as well as forming part of the name of a generated RPM package file. +See the &b-link-Package; builder. @@ -180,6 +181,7 @@ the .wxs for MSI). If set, the function will be called after the SCons template for the file has been written. +See the &b-link-Package; builder. @@ -193,6 +195,7 @@ This is included as the section of the RPM .spec file. +See the &b-link-Package; builder. @@ -203,6 +206,7 @@ A long description of the project being packaged. This is included in the relevant section of the file that controls the packaging build. +See the &b-link-Package; builder. @@ -216,6 +220,7 @@ This is used to populate a section of an RPM .spec file. +See the &b-link-Package; builder. @@ -224,9 +229,12 @@ section of an RPM The abbreviated name, preferably the SPDX code, of the license under which this project is released (GPL-3.0, LGPL-2.1, BSD-2-Clause etc.). -See http://www.opensource.org/licenses/alphabetical +See + +http://www.opensource.org/licenses/alphabetical for a list of license names and SPDX codes. +See the &b-link-Package; builder. @@ -235,6 +243,7 @@ for a list of license names and SPDX codes. Specfies the name of the project to package. +See the &b-link-Package; builder. @@ -242,8 +251,9 @@ Specfies the name of the project to package. Specifies the directory where all files in resulting archive will be -placed if applicable. The default value is "$NAME-$VERSION". +placed if applicable. The default value is &cv-NAME;-&cv-VERSION;. +See the &b-link-Package; builder. @@ -259,6 +269,7 @@ for the builder for the currently supported types. &cv-PACKAGETYPE; may be overridden with the command line option. +See the &b-link-Package; builder. @@ -270,6 +281,7 @@ This is currently only used by the rpm packager and should reflect changes in the packaging, not the underlying project code itself. +See the &b-link-Package; builder. @@ -283,6 +295,7 @@ This is used to fill in the Source: field in the controlling information for Ipkg and RPM packages. +See the &b-link-Package; builder. @@ -297,6 +310,7 @@ and as the Description: field in MSI packages. +See the &b-link-Package; builder. @@ -311,6 +325,7 @@ and the Manufacturer: field in the controlling information for MSI packages. +See the &b-link-Package; builder. @@ -319,6 +334,7 @@ field in the controlling information for MSI packages. The version of the project, specified as a string. +See the &b-link-Package; builder. @@ -330,6 +346,7 @@ This is used to fill in the Depends: field in the controlling information for Ipkg packages. +See the &b-link-Package; builder. @@ -340,7 +357,7 @@ This is used to fill in the Description: field in the controlling information for Ipkg packages. The default value is -$SUMMARY\n$DESCRIPTION +&cv-SUMMARY;\n&cv-DESCRIPTION; @@ -375,8 +392,6 @@ field in the controlling information for Ipkg packages. - - @@ -384,6 +399,7 @@ This is used to fill in the Language: attribute in the controlling information for MSI packages. +See the &b-link-Package; builder. @@ -394,6 +410,7 @@ The text of the software license in RTF format. Carriage return characters will be replaced with the RTF equivalent \\par. +See the &b-link-Package; builder. @@ -414,6 +431,7 @@ This is used to fill in the field in the RPM .spec file. +See the &b-link-Package; builder. @@ -470,7 +488,7 @@ field in the RPM This value is used as the default attributes for the files in the RPM package. The default value is -(-,root,root). +(-,root,root). -- cgit v0.12 From 1f50f1ad84d2dbe0f1b7411b9cfc834b570b6bed Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 12 Feb 2021 12:27:13 -0700 Subject: Update documentation for env.Append family [ci skip] Try to be more descriptive of what happens in some special cases. CPPDEFINES, LIBS, and the *PATH variables are mentioned. Don't duplicate descriptions - AppendUnique, Prepend, PrependUnique all point back to Append for the body of the description - the idea is to avoid divergence. The same should happen for the implementation, but that's a different PR. Reformat examples with Black to continue getting example style self-consistent within the docs (lots to go here!) Signed-off-by: Mats Wichmann --- SCons/Defaults.xml | 6 +- SCons/Environment.xml | 342 +++++++++++++++++++++++++++++++++----------------- 2 files changed, 229 insertions(+), 119 deletions(-) diff --git a/SCons/Defaults.xml b/SCons/Defaults.xml index 6b034d9..8983ac0 100644 --- a/SCons/Defaults.xml +++ b/SCons/Defaults.xml @@ -87,7 +87,7 @@ of each definition in &cv-CPPDEFINES;. -A platform independent specification of C preprocessor definitions. +A platform independent specification of C preprocessor macro definitions. The definitions will be added to command lines through the automatically-generated &cv-_CPPDEFFLAGS; construction variable (see above), @@ -159,7 +159,7 @@ env = Environment(CPPDEFINES={'B':2, 'A':None}) -The prefix used to specify preprocessor definitions +The prefix used to specify preprocessor macro definitions on the C compiler command line. This will be prepended to the beginning of each definition in the &cv-CPPDEFINES; construction variable @@ -171,7 +171,7 @@ when the &cv-_CPPDEFFLAGS; variable is automatically generated. -The suffix used to specify preprocessor definitions +The suffix used to specify preprocessor macro definitions on the C compiler command line. This will be appended to the end of each definition in the &cv-CPPDEFINES; construction variable diff --git a/SCons/Environment.xml b/SCons/Environment.xml index cfa99db..e061280 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -486,41 +486,144 @@ Multiple targets can be passed in to a single call to -Appends the specified keyword arguments -to the end of construction variables in the environment. -If the Environment does not have -the specified construction variable, -it is simply added to the environment. -If the values of the construction variable -and the keyword argument are the same type, -then the two values will be simply added together. -Otherwise, the construction variable -and the value of the keyword argument -are both coerced to lists, -and the lists are added together. -(See also the &Prepend; method). +Intelligently append values to &consvars; in the current &consenv;. +The &consvars; and values to add to them are passed as +key=val pairs (Python keyword arguments). +&f-env-Append; is designed to allow adding values +without normally having to know the data type of an existing &consvar;. +Regular Python syntax can also be used to manipulate the &consvar;, +but for that you must know the type of the &consvar;: +for example, different Python syntax is needed to combine +a list of values with a single string value, or vice versa. +Some pre-defined &consvars; do have type expectations +based on how &SCons; will use them, +for example &cv-link-CPPDEFINES; is normally a string +or list of strings, while &cv-link-LIBEMITTER; +would expect a callable or list of callables, +and &cv-link-BUILDERS; would expect a mapping type. + + + +The following descriptions apply to both the append +and prepend functions, the only difference being +the insertion point of the added values. + + +If the &consenv; does not have the &consvar; +indicated by key, +val +is added to the environment under that key as-is. + + + +val can be almost any type, +and &SCons; will combine it with an existing value into an appropriate type, +but there are a few special cases to be aware of. +When two strings are combined, +the result is normally a new string, +with the caller responsible for supplying any needed separation. +The exception to this is the &consvar; &cv-link-CPPDEFINES; +and so is treated as lists of strings, that is, +adding a string will result in a separate string entry, +not a combined string. For &cv-CPPDEFINES; as well as +for &cv-link-LIBS;, and the various *PATH +variables, &SCons; will supply the compiler-specific +syntax (e.g. adding -D or /D +for &cv-CPPDEFINES;, so this syntax should be omitted when +adding values to these variables. +Example (gcc syntax shown in the expansion of &CPPDEFINES;): + +env = Environment(CXXFLAGS="-std=c11", CPPDEFINES="RELEASE") +print("CXXFLAGS={}, CPPDEFINES={}".format(env['CXXFLAGS'], env['CPPDEFINES'])) +# notice including a leading space in CXXFLAGS value +env.Append(CXXFLAGS=" -O", CPPDEFINES="EXTRA") +print("CXXFLAGS={}, CPPDEFINES={}".format(env['CXXFLAGS'], env['CPPDEFINES'])) +print("CPPDEFINES will expand to {}".format(env.subst("$_CPPDEFFLAGS"))) + + + +$ scons -Q +CXXFLAGS=-std=c11, CPPDEFINES=RELEASE +CXXFLAGS=-std=c11 -O, CPPDEFINES=['RELEASE', 'EXTRA'] +CPPDEFINES will expand to -DRELEASE -DEXTRA +scons: `.' is up to date. + + -Example: +Because &cv-link-CPPDEFINES; is intended to +describe C/C++ pre-processor macro definitions, +it accepts additional syntax. +Preprocessor macros can be valued, or un-valued, as in +-DBAR=1 or +-DFOO. +The macro can be be supplied as a complete string including the value, +or as a tuple/list of macro/value, or as a dictionary. +Example (again gcc syntax in the expanded defines): -env.Append(CCFLAGS = ' -g', FOO = ['foo.yyy']) +env = Environment(CPPDEFINES="FOO") +print("CPPDEFINES={}".format(env['CPPDEFINES'])) +env.Append(CPPDEFINES="BAR=1") +print("CPPDEFINES={}".format(env['CPPDEFINES'])) +env.Append(CPPDEFINES=("OTHER", 2)) +print("CPPDEFINES={}".format(env['CPPDEFINES'])) +env.Append(CPPDEFINES={"EXTRA": "arg"}) +print("CPPDEFINES={}".format(env['CPPDEFINES'])) +print("CPPDEFINES will expand to {}".format(env.subst("$_CPPDEFFLAGS"))) + +$ scons -Q +CPPDEFINES=FOO +CPPDEFINES=['FOO', 'BAR=1'] +CPPDEFINES=['FOO', 'BAR=1', ('OTHER', 2)] +CPPDEFINES=['FOO', 'BAR=1', ('OTHER', 2), {'EXTRA': 'arg'}] +CPPDEFINES will expand to -DFOO -DBAR=1 -DOTHER=2 -DEXTRA=arg +scons: `.' is up to date. + + +Adding a string val +to a dictonary &consvar; will enter +val as the key in the dict, +and None as its value. +Using a tuple type to supply a key + value only works +for the special case of &cv-link-CPPDEFINES; +described above. + + +Although most combinations of types work without +needing to know the details, some combinations +do not make sense and a Python exception will be raised. + + +When using &f-env-Append; to modify &consvars; +which are path specifications (normally, +those names which end in PATH), +it is recommended to add the values as a list of strings, +even if there is only a single string to add. +The same goes for adding library names to &cv-LIBS;. + + +env.Append(CPPPATH=["#/include"]) + +See also &f-link-env-AppendUnique;, +&f-link-env-Prepend; and &f-link-env-PrependUnique;. + + -(name, newpath, [envname, sep, delete_existing]) +(name, newpath, [envname, sep, delete_existing=True]) -This appends new path elements to the given path in the -specified external environment -(ENV -by default). +Append new path elements to the given path in the +specified external environment (&cv-link-ENV; by default). This will only add any particular path once (leaving the last one it encounters and ignoring the rest, to preserve path order), @@ -537,7 +640,7 @@ string, in which case a list will be returned instead of a string. If delete_existing -is 0, then adding a path that already exists +is False, then adding a path that already exists will not move it to the end; it will stay where it is in the list. @@ -546,37 +649,36 @@ Example: -print 'before:',env['ENV']['INCLUDE'] +print('before:', env['ENV']['INCLUDE']) include_path = '/foo/bar:/foo' env.AppendENVPath('INCLUDE', include_path) -print 'after:',env['ENV']['INCLUDE'] +print('after:', env['ENV']['INCLUDE']) + -yields: +Yields: + before: /foo:/biz after: /biz:/foo/bar:/foo - + -(key=val, [...], delete_existing=0) +(key=val, [...], delete_existing=False) -Appends the specified keyword arguments -to the end of construction variables in the environment. -If the Environment does not have -the specified construction variable, -it is simply added to the environment. -If the construction variable being appended to is a list, -then any value(s) that already exist in the -construction variable will -not -be added again to the list. -However, if delete_existing is 1, -existing matching values are removed first, so -existing values in the arg list move to the end of the list. +Append values to &consvars; in the current &consenv;, +maintaining uniqueness. +Works like &f-link-env-Append; (see for details), +except that values already present in the &consvar; +will not be added again. +If delete_existing +is True, +the existing matching value is first removed, +and the requested value is added, +having the effect of moving such values to the end. @@ -584,8 +686,14 @@ Example: -env.AppendUnique(CCFLAGS = '-g', FOO = ['foo.yyy']) +env.AppendUnique(CCFLAGS='-g', FOO=['foo.yyy']) + + +See also &f-link-env-Append;, +&f-link-env-Prepend; +and &f-link-env-PrependUnique;. + @@ -612,7 +720,7 @@ including the argument, at the time it is called using the construction variables in the -env +env construction environment through which &f-env-Builder; was called. The @@ -819,7 +927,7 @@ Example: env2 = env.Clone() -env3 = env.Clone(CCFLAGS = '-g') +env3 = env.Clone(CCFLAGS='-g') @@ -828,8 +936,10 @@ the &f-link-Environment; constructor: -def MyTool(env): env['FOO'] = 'bar' -env4 = env.Clone(tools = ['msvc', MyTool]) +def MyTool(env): + env['FOO'] = 'bar' + +env4 = env.Clone(tools=['msvc', MyTool]) @@ -1293,9 +1403,9 @@ Find an executable from one or more choices: Returns the first value from progs that was found, or None. Executable is searched by checking the paths specified -by env['ENV']['PATH']. +by env['ENV']['PATH']. On Windows systems, additionally applies the filename suffixes found in -env['ENV']['PATHEXT'] +env['ENV']['PATHEXT'] but will not include any such extension in the return value. &f-env-Detect; is a wrapper around &f-link-env-WhereIs;. @@ -1426,7 +1536,7 @@ While this SConstruct: -env=Environment() +env = Environment() print(env.Dump()) @@ -1615,16 +1725,16 @@ Example: -Install( '/bin', [ 'executable_a', 'executable_b' ] ) +Install('/bin', ['executable_a', 'executable_b']) # will return the file node list -# [ '/bin/executable_a', '/bin/executable_b' ] +# ['/bin/executable_a', '/bin/executable_b'] FindInstalledFiles() -Install( '/lib', [ 'some_library' ] ) +Install('/lib', ['some_library']) # will return the file node list -# [ '/bin/executable_a', '/bin/executable_b', '/lib/some_library' ] +# ['/bin/executable_a', '/bin/executable_b', '/lib/some_library'] FindInstalledFiles() @@ -1655,15 +1765,15 @@ Example: -Program( 'src/main_a.c' ) -Program( 'src/main_b.c' ) -Program( 'main_c.c' ) +Program('src/main_a.c') +Program('src/main_b.c') +Program('main_c.c') # returns ['main_c.c', 'src/main_a.c', 'SConstruct', 'src/main_b.c'] FindSourceFiles() # returns ['src/main_b.c', 'src/main_a.c' ] -FindSourceFiles( 'src' ) +FindSourceFiles('src') @@ -1931,8 +2041,8 @@ Examples: env.Ignore('foo', 'foo.c') env.Ignore('bar', ['bar1.h', 'bar2.h']) -env.Ignore('.','foobar.obj') -env.Ignore('bar','bar/foobar.obj') +env.Ignore('.', 'foobar.obj') +env.Ignore('bar', 'bar/foobar.obj') @@ -2009,9 +2119,9 @@ Examples: # Prepend a path to the shell PATH. -env.MergeShellPaths({'PATH':'/usr/local/bin'} ) +env.MergeShellPaths({'PATH': '/usr/local/bin'}) # Append two dirs to the shell INCLUDE. -env.MergeShellPaths({'INCLUDE':['c:/inc1', 'c:/inc2']}, prepend=0 ) +env.MergeShellPaths({'INCLUDE': ['c:/inc1', 'c:/inc2']}, prepend=0) @@ -2398,7 +2508,7 @@ Example: -env = Environment(platform = Platform('win32')) +env = Environment(platform=Platform('win32')) @@ -2440,19 +2550,10 @@ will work on Windows systems. -Appends the specified keyword arguments -to the beginning of construction variables in the environment. -If the Environment does not have -the specified construction variable, -it is simply added to the environment. -If the values of the construction variable -and the keyword argument are the same type, -then the two values will be simply added together. -Otherwise, the construction variable -and the value of the keyword argument -are both coerced to lists, -and the lists are added together. -(See also the Append method, above.) +Prepend values to &consvars; in the current &consenv;, +Works like &f-link-env-Append; (see for details), +except that values are added to the front, +rather than the end, of any existing value of the &consvar; @@ -2460,8 +2561,14 @@ Example: -env.Prepend(CCFLAGS = '-g ', FOO = ['foo.yyy']) +env.Prepend(CCFLAGS='-g ', FOO=['foo.yyy']) + + +See also &f-link-env-Append;, +&f-link-env-AppendUnique; +and &f-link-env-PrependUnique;. + @@ -2471,18 +2578,16 @@ env.Prepend(CCFLAGS = '-g ', FOO = ['foo.yyy']) -This appends new path elements to the given path in the -specified external environment -(&cv-ENV; -by default). +Prepend new path elements to the given path in the +specified external environment (&cv-link-ENV; by default). This will only add any particular path once (leaving the first one it encounters and ignoring the rest, to preserve path order), and to help assure this, will normalize all paths (using -os.path.normpath +os.path.normpath and -os.path.normcase). +os.path.normcase). This can also handle the case where the given old path variable is a list instead of a string, in which case a list will be returned instead of a string. @@ -2491,7 +2596,8 @@ string, in which case a list will be returned instead of a string. If delete_existing -is 0, then adding a path that already exists +is False, +then adding a path that already exists will not move it to the beginning; it will stay where it is in the list. @@ -2501,42 +2607,39 @@ Example: -print 'before:',env['ENV']['INCLUDE'] +print('before:', env['ENV']['INCLUDE']) include_path = '/foo/bar:/foo' env.PrependENVPath('INCLUDE', include_path) -print 'after:',env['ENV']['INCLUDE'] +print('after:', env['ENV']['INCLUDE']) - -The above example will print: - +Yields: - + before: /biz:/foo after: /foo/bar:/foo:/biz - + -(key=val, delete_existing=0, [...]) +(key=val, delete_existing=False, [...]) -Appends the specified keyword arguments -to the beginning of construction variables in the environment. -If the Environment does not have -the specified construction variable, -it is simply added to the environment. -If the construction variable being appended to is a list, -then any value(s) that already exist in the -construction variable will -not -be added again to the list. -However, if delete_existing is 1, -existing matching values are removed first, so -existing values in the arg list move to the front of the list. +Prepend values to &consvars; in the current &consenv;, +maintaining uniqueness. +Works like &f-link-env-Append; (see for details), +except that values are added to the front, +rather than the end, of any existing value of the the &consvar;, +and values already present in the &consvar; +will not be added again. +If delete_existing +is True, +the existing matching value is first removed, +and the requested value is inserted, +having the effect of moving such values to the front. @@ -2544,8 +2647,14 @@ Example: -env.PrependUnique(CCFLAGS = '-g', FOO = ['foo.yyy']) +env.PrependUnique(CCFLAGS='-g', FOO=['foo.yyy']) + + +See also &f-link-env-Append;, +&f-link-env-AppendUnique; +and &f-link-env-Prepend;. + @@ -2587,7 +2696,7 @@ Example: -env.Replace(CCFLAGS = '-g', FOO = 'foo.xxx') +env.Replace(CCFLAGS='-g', FOO='foo.xxx') @@ -2853,9 +2962,9 @@ The following statements are equivalent: -env.SetDefault(FOO = 'foo') - -if 'FOO' not in env: env['FOO'] = 'foo' +env.SetDefault(FOO='foo') +if 'FOO' not in env: + env['FOO'] = 'foo' @@ -3060,12 +3169,13 @@ Example: print(env.subst("The C compiler is: $CC")) def compile(target, source, env): - sourceDir = env.subst("${SOURCE.srcdir}", - target=target, - source=source) + sourceDir = env.subst( + "${SOURCE.srcdir}", + target=target, + source=source + ) -source_nodes = env.subst('$EXPAND_TO_NODELIST', - conv=lambda x: x) +source_nodes = env.subst('$EXPAND_TO_NODELIST', conv=lambda x: x) @@ -3348,11 +3458,11 @@ searches the paths in the path keyword argument, or if None (the default) the paths listed in the &consenv; -(env['ENV']['PATH']). +(env['ENV']['PATH']). The external environment's path list (os.environ['PATH']) is used as a fallback if the key -env['ENV']['PATH'] +env['ENV']['PATH'] does not exist. @@ -3361,11 +3471,11 @@ programs with any of the file extensions listed in the pathext keyword argument, or if None (the default) the pathname extensions listed in the &consenv; -(env['ENV']['PATHEXT']). +(env['ENV']['PATHEXT']). The external environment's pathname extensions list (os.environ['PATHEXT']) is used as a fallback if the key -env['ENV']['PATHEXT'] +env['ENV']['PATHEXT'] does not exist. -- cgit v0.12 From af3af1910440bfa8a8793dae3bec0d5c6598a6da Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Sat, 13 Feb 2021 12:39:43 -0700 Subject: [PR #3886] push a missed commit to Append docs [ci skip] Signed-off-by: Mats Wichmann --- SCons/Environment.xml | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/SCons/Environment.xml b/SCons/Environment.xml index e061280..c5c8d4d 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -486,7 +486,8 @@ Multiple targets can be passed in to a single call to -Intelligently append values to &consvars; in the current &consenv;. +Intelligently append values to &consvars; in the &consenv; +named by env. The &consvars; and values to add to them are passed as key=val pairs (Python keyword arguments). &f-env-Append; is designed to allow adding values @@ -501,6 +502,7 @@ for example &cv-link-CPPDEFINES; is normally a string or list of strings, while &cv-link-LIBEMITTER; would expect a callable or list of callables, and &cv-link-BUILDERS; would expect a mapping type. +Consult the documentation for the various &consvars; for more details. @@ -509,7 +511,7 @@ and prepend functions, the only difference being the insertion point of the added values. -If the &consenv; does not have the &consvar; +If env. does not have a &consvar; indicated by key, val is added to the environment under that key as-is. @@ -523,13 +525,14 @@ When two strings are combined, the result is normally a new string, with the caller responsible for supplying any needed separation. The exception to this is the &consvar; &cv-link-CPPDEFINES; -and so is treated as lists of strings, that is, +in which each entry will be postprocessed, +so the contents are treated as a list of strings, that is, adding a string will result in a separate string entry, not a combined string. For &cv-CPPDEFINES; as well as for &cv-link-LIBS;, and the various *PATH variables, &SCons; will supply the compiler-specific syntax (e.g. adding -D or /D -for &cv-CPPDEFINES;, so this syntax should be omitted when +for &cv-CPPDEFINES;), so this syntax should be omitted when adding values to these variables. Example (gcc syntax shown in the expansion of &CPPDEFINES;): @@ -574,6 +577,7 @@ env.Append(CPPDEFINES={"EXTRA": "arg"}) print("CPPDEFINES={}".format(env['CPPDEFINES'])) print("CPPDEFINES will expand to {}".format(env.subst("$_CPPDEFFLAGS"))) + $ scons -Q CPPDEFINES=FOO @@ -583,6 +587,7 @@ CPPDEFINES=['FOO', 'BAR=1', ('OTHER', 2), {'EXTRA': 'arg'}] CPPDEFINES will expand to -DFOO -DBAR=1 -DOTHER=2 -DEXTRA=arg scons: `.' is up to date. + Adding a string val to a dictonary &consvar; will enter @@ -592,11 +597,13 @@ Using a tuple type to supply a key + value only works for the special case of &cv-link-CPPDEFINES; described above. + Although most combinations of types work without needing to know the details, some combinations do not make sense and a Python exception will be raised. + When using &f-env-Append; to modify &consvars; which are path specifications (normally, @@ -605,9 +612,11 @@ it is recommended to add the values as a list of strings, even if there is only a single string to add. The same goes for adding library names to &cv-LIBS;. + env.Append(CPPPATH=["#/include"]) - + See also &f-link-env-AppendUnique;, &f-link-env-Prepend; and &f-link-env-PrependUnique;. -- cgit v0.12 From 21470ff129d38680ac3d5d25098ee9428a4c6856 Mon Sep 17 00:00:00 2001 From: Mats Wichmann Date: Fri, 26 Feb 2021 11:31:01 -0700 Subject: Further minor tweak on CPPDEFINES usage [skip appveyor] [skip travis] Signed-off-by: Mats Wichmann --- SCons/Environment.xml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/SCons/Environment.xml b/SCons/Environment.xml index c5c8d4d..5b039ff 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -488,7 +488,7 @@ Multiple targets can be passed in to a single call to Intelligently append values to &consvars; in the &consenv; named by env. -The &consvars; and values to add to them are passed as +The &consvars; and values to add to them are passed as key=val pairs (Python keyword arguments). &f-env-Append; is designed to allow adding values without normally having to know the data type of an existing &consvar;. @@ -524,15 +524,16 @@ but there are a few special cases to be aware of. When two strings are combined, the result is normally a new string, with the caller responsible for supplying any needed separation. -The exception to this is the &consvar; &cv-link-CPPDEFINES; -in which each entry will be postprocessed, +The exception to this is the &consvar; &cv-link-CPPDEFINES;, +in which each item will be postprocessed by adding a prefix +and/or suffix, so the contents are treated as a list of strings, that is, adding a string will result in a separate string entry, not a combined string. For &cv-CPPDEFINES; as well as for &cv-link-LIBS;, and the various *PATH variables, &SCons; will supply the compiler-specific -syntax (e.g. adding -D or /D -for &cv-CPPDEFINES;), so this syntax should be omitted when +syntax (e.g. adding a -D or /D +prefix for &cv-CPPDEFINES;), so this syntax should be omitted when adding values to these variables. Example (gcc syntax shown in the expansion of &CPPDEFINES;): @@ -562,7 +563,7 @@ Preprocessor macros can be valued, or un-valued, as in -DBAR=1 or -DFOO. The macro can be be supplied as a complete string including the value, -or as a tuple/list of macro/value, or as a dictionary. +or as a tuple (or list) of macro, value, or as a dictionary. Example (again gcc syntax in the expanded defines): -- cgit v0.12 From 01e55464940442697105c646e22dc700ac102854 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 26 Feb 2021 14:48:20 -0800 Subject: update example to simplify map_filename and relocate emitter to after that variable is set as it uses it --- SCons/__init__.py | 8 ++++---- doc/generated/examples/builderswriting_ex2_1.xml | 2 +- doc/generated/examples/caching_ex-random_1.xml | 6 +++--- doc/generated/examples/troubleshoot_explain1_3.xml | 2 +- doc/generated/functions.gen | 8 ++++---- doc/generated/variables.gen | 2 +- doc/user/builders-writing.xml | 5 +++-- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/SCons/__init__.py b/SCons/__init__.py index d169eef..e9e0684 100644 --- a/SCons/__init__.py +++ b/SCons/__init__.py @@ -1,9 +1,9 @@ -__version__="4.1.0.post1" +__version__="4.1.1a" __copyright__="Copyright (c) 2001 - 2021 The SCons Foundation" __developer__="bdbaddog" -__date__="2021-01-20 04:32:28" +__date__="2021-02-26 22:38:25" __buildsys__="ProDog2020" -__revision__="dc58c175da659d6c0bb3e049ba56fb42e77546cd" -__build__="dc58c175da659d6c0bb3e049ba56fb42e77546cd" +__revision__="3fa309f8fc5472fa067d7c04481fd0a5d3e86352" +__build__="3fa309f8fc5472fa067d7c04481fd0a5d3e86352" # make sure compatibility is always in place import SCons.compat # noqa \ No newline at end of file diff --git a/doc/generated/examples/builderswriting_ex2_1.xml b/doc/generated/examples/builderswriting_ex2_1.xml index 3391653..f19cb80 100644 --- a/doc/generated/examples/builderswriting_ex2_1.xml +++ b/doc/generated/examples/builderswriting_ex2_1.xml @@ -1,5 +1,5 @@ % scons -Q AttributeError: 'SConsEnvironment' object has no attribute 'Program': - File "/home/my/project/SConstruct", line 4: + File "/home/my/project/SConstruct", line 7: env.Program('hello.c') diff --git a/doc/generated/examples/caching_ex-random_1.xml b/doc/generated/examples/caching_ex-random_1.xml index e215ac5..27c8771 100644 --- a/doc/generated/examples/caching_ex-random_1.xml +++ b/doc/generated/examples/caching_ex-random_1.xml @@ -1,8 +1,8 @@ % scons -Q +cc -o f4.o -c f4.c +cc -o f5.o -c f5.c cc -o f3.o -c f3.c -cc -o f1.o -c f1.c cc -o f2.o -c f2.c -cc -o f5.o -c f5.c -cc -o f4.o -c f4.c +cc -o f1.o -c f1.c cc -o prog f1.o f2.o f3.o f4.o f5.o diff --git a/doc/generated/examples/troubleshoot_explain1_3.xml b/doc/generated/examples/troubleshoot_explain1_3.xml index 6b90e1c..85556b1 100644 --- a/doc/generated/examples/troubleshoot_explain1_3.xml +++ b/doc/generated/examples/troubleshoot_explain1_3.xml @@ -2,5 +2,5 @@ cp file.in file.oout scons: warning: Cannot find target file.out after building -File "/Users/bdbaddog/devel/scons/git/as_scons/scripts/scons.py", line 96, in <module> +File "/Users/bdbaddog/devel/scons/git/scons-bugfixes-3/scripts/scons.py", line 96, in <module> diff --git a/doc/generated/functions.gen b/doc/generated/functions.gen index 382315e..61b1fed 100644 --- a/doc/generated/functions.gen +++ b/doc/generated/functions.gen @@ -481,10 +481,10 @@ Example: -print 'before:',env['ENV']['INCLUDE'] +print('before:', env['ENV']['INCLUDE']) include_path = '/foo/bar:/foo' env.AppendENVPath('INCLUDE', include_path) -print 'after:',env['ENV']['INCLUDE'] +print('after:', env['ENV']['INCLUDE']) yields: before: /foo:/biz @@ -2973,10 +2973,10 @@ Example: -print 'before:',env['ENV']['INCLUDE'] +print('before:', env['ENV']['INCLUDE']) include_path = '/foo/bar:/foo' env.PrependENVPath('INCLUDE', include_path) -print 'after:',env['ENV']['INCLUDE'] +print('after:', env['ENV']['INCLUDE']) diff --git a/doc/generated/variables.gen b/doc/generated/variables.gen index 1ac53fe..84ef3b1 100644 --- a/doc/generated/variables.gen +++ b/doc/generated/variables.gen @@ -1615,7 +1615,7 @@ Note that, by default, &scons; does not -propagate the environment in force when you +propagate the environment in effect when you execute &scons; to the commands used to build target files. diff --git a/doc/user/builders-writing.xml b/doc/user/builders-writing.xml index 6b32068..942bc35 100644 --- a/doc/user/builders-writing.xml +++ b/doc/user/builders-writing.xml @@ -864,12 +864,13 @@ cat +env = Environment() +map_filename = "${TARGET.name}.map" + def map_emitter(target, source, env): target.append(map_filename) return target, source -env = Environment() -map_filename = "${TARGET.name}" + ".map" env.Append(LINKFLAGS="-Wl,-Map={},--cref".format(map_filename)) env.Append(PROGEMITTER=map_emitter) env.Program('hello.c') -- cgit v0.12 From 826880ba2ef98d231598ca07b83031f7ff0f7af4 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 26 Feb 2021 15:03:04 -0800 Subject: a few updates. Soften wording advising aginst adding library inclusion directives in LINKFLAGS. There are some reasons, but they are mainly for advanced SCons users using them with caution. Added to LIBS that it can also affect shared libraries and loadable modules --- SCons/Defaults.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SCons/Defaults.xml b/SCons/Defaults.xml index bb52823..16b79ff 100644 --- a/SCons/Defaults.xml +++ b/SCons/Defaults.xml @@ -196,7 +196,7 @@ to each directory in &cv-link-CPPPATH;. The list of directories that the C preprocessor will search for include directories. The C/C++ implicit dependency scanner will search these directories for include files. -Do not put include directory directives +In general it's not advised to put include directory directives directly into &cv-link-CCFLAGS; or &cv-link-CXXFLAGS; as the result will be non-portable and the directories will not be searched by the dependency scanner. @@ -527,7 +527,7 @@ env = Environment(LINKCOM="my_linker $_LIBDIRFLAGS $_LIBFLAGS -o $TARGET $SOURCE A list of one or more libraries that will be added to the link line -for linking with any executable program +for linking with any executable program, shared library, or loadable module created by the &consenv; or override. -- cgit v0.12 From 699532f0e73793d31324f37dade3e9a423ef7ea7 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Fri, 26 Feb 2021 15:42:14 -0800 Subject: resolve a couple outstanding comments from PR --- SCons/Environment.xml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/SCons/Environment.xml b/SCons/Environment.xml index 5b039ff..d006fb7 100644 --- a/SCons/Environment.xml +++ b/SCons/Environment.xml @@ -498,8 +498,11 @@ for example, different Python syntax is needed to combine a list of values with a single string value, or vice versa. Some pre-defined &consvars; do have type expectations based on how &SCons; will use them, -for example &cv-link-CPPDEFINES; is normally a string -or list of strings, while &cv-link-LIBEMITTER; +for example &cv-link-CPPDEFINES; is normally a string or a list of strings, +but can be a string, +a list of strings, +a list of tuples, +or a dictionary, while &cv-link-LIBEMITTER; would expect a callable or list of callables, and &cv-link-BUILDERS; would expect a mapping type. Consult the documentation for the various &consvars; for more details. @@ -628,7 +631,7 @@ See also &f-link-env-AppendUnique;, -(name, newpath, [envname, sep, delete_existing=True]) +(name, newpath, [envname, sep, delete_existing=False]) -- cgit v0.12 From c7a5f84dd8e742a3fc622f94eca6a9c51c8ef92c Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 27 Feb 2021 13:11:31 -0800 Subject: update subst callable checking to include the expected args in the list to compare regardless of if they have defaults specified or not --- SCons/Subst.py | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/SCons/Subst.py b/SCons/Subst.py index ea756ff..eda514e 100644 --- a/SCons/Subst.py +++ b/SCons/Subst.py @@ -25,9 +25,9 @@ import collections import re -from inspect import signature -import SCons.Errors +from inspect import signature, Parameter +import SCons.Errors from SCons.Util import is_String, is_Sequence # Indexed by the SUBST_* constants below. @@ -328,6 +328,8 @@ def subst_dict(target, source): return dict +_callable_args_set = {'target', 'source', 'env', 'for_signature'} + class StringSubber: """A class to construct the results of a scons_subst() call. @@ -335,6 +337,8 @@ class StringSubber: source with two methods (substitute() and expand()) that handle the expansion. """ + + def __init__(self, env, mode, conv, gvars): self.env = env self.mode = mode @@ -419,8 +423,11 @@ class StringSubber: # SCons has the unusual Null class where any __getattr__ call returns it's self, # which does not work the signature module, and the Null class returns an empty # string if called on, so we make an exception in this condition for Null class - if (isinstance(s, SCons.Util.Null) or - set(signature(s).parameters.keys()) == set(['target', 'source', 'env', 'for_signature'])): + # Also allow callables where the only non default valued args match the expected defaults + # this should also allow functools.partial's to work. + if isinstance(s, SCons.Util.Null) or set([k for k, v in signature(s).parameters.items() if k in _callable_args_set or + v.default == Parameter.empty]) == _callable_args_set: + s = s(target=lvars['TARGETS'], source=lvars['SOURCES'], env=self.env, @@ -593,8 +600,12 @@ class ListSubber(collections.UserList): # SCons has the unusual Null class where any __getattr__ call returns it's self, # which does not work the signature module, and the Null class returns an empty # string if called on, so we make an exception in this condition for Null class - if (isinstance(s, SCons.Util.Null) or - set(signature(s).parameters.keys()) == set(['target', 'source', 'env', 'for_signature'])): + # Also allow callables where the only non default valued args match the expected defaults + # this should also allow functools.partial's to work. + if isinstance(s, SCons.Util.Null) or set( + [k for k, v in signature(s).parameters.items() if k in _callable_args_set or + v.default == Parameter.empty]) == _callable_args_set: + s = s(target=lvars['TARGETS'], source=lvars['SOURCES'], env=self.env, -- cgit v0.12 From 9c9a35402b537e6ce9e14a4db07a82433b62e475 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 27 Feb 2021 13:14:33 -0800 Subject: switch to using set comprehension in subst callable arg checking logic, instead of set([ list comprehension]) --- SCons/Subst.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/SCons/Subst.py b/SCons/Subst.py index eda514e..f23b2d0 100644 --- a/SCons/Subst.py +++ b/SCons/Subst.py @@ -425,8 +425,8 @@ class StringSubber: # string if called on, so we make an exception in this condition for Null class # Also allow callables where the only non default valued args match the expected defaults # this should also allow functools.partial's to work. - if isinstance(s, SCons.Util.Null) or set([k for k, v in signature(s).parameters.items() if k in _callable_args_set or - v.default == Parameter.empty]) == _callable_args_set: + if isinstance(s, SCons.Util.Null) or {k for k, v in signature(s).parameters.items() if + k in _callable_args_set or v.default == Parameter.empty} == _callable_args_set: s = s(target=lvars['TARGETS'], source=lvars['SOURCES'], @@ -602,9 +602,8 @@ class ListSubber(collections.UserList): # string if called on, so we make an exception in this condition for Null class # Also allow callables where the only non default valued args match the expected defaults # this should also allow functools.partial's to work. - if isinstance(s, SCons.Util.Null) or set( - [k for k, v in signature(s).parameters.items() if k in _callable_args_set or - v.default == Parameter.empty]) == _callable_args_set: + if isinstance(s, SCons.Util.Null) or {k for k, v in signature(s).parameters.items() if + k in _callable_args_set or v.default == Parameter.empty} == _callable_args_set: s = s(target=lvars['TARGETS'], source=lvars['SOURCES'], -- cgit v0.12 From dbb62489819ca608ecb1e90d4c1c8d614859ff9f Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 27 Feb 2021 13:22:28 -0800 Subject: Add tests for callable with extra default arg, same but using partial to set that value, then a function with extraneous arg which is then set by a functools.partial --- SCons/SubstTests.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/SCons/SubstTests.py b/SCons/SubstTests.py index bdeb01e..b2951fb 100644 --- a/SCons/SubstTests.py +++ b/SCons/SubstTests.py @@ -25,6 +25,7 @@ import SCons.compat import os import unittest +from functools import partial import SCons.Errors @@ -92,6 +93,23 @@ class CmdGen2: assert for_signature == self.expect_for_signature, for_signature return [ self.mystr, env.Dictionary('BAR') ] + +def CallableWithDefault(target, source, env, for_signature, other_value="default"): + assert str(target) == 't', target + assert str(source) == 's', source + return "CallableWithDefault: %s"%other_value + +PartialCallable = partial(CallableWithDefault, other_value="partial") + +def CallableWithNoDefault(target, source, env, for_signature, other_value): + assert str(target) == 't', target + assert str(source) == 's', source + return "CallableWithNoDefault: %s"%other_value + +PartialCallableNoDefault = partial(CallableWithNoDefault, other_value="partialNoDefault") + + + if os.sep == '/': def cvt(str): return str @@ -190,6 +208,10 @@ class SubstTestCase(unittest.TestCase): 'CMDGEN1' : CmdGen1, 'CMDGEN2' : CmdGen2, + 'CallableWithDefault': CallableWithDefault, + 'PartialCallable' : PartialCallable, + 'PartialCallableNoDefault' : PartialCallableNoDefault, + 'LITERALS' : [ Literal('foo\nwith\nnewlines'), Literal('bar\nwith\nnewlines') ], @@ -238,6 +260,7 @@ class SubstTestCase(unittest.TestCase): 'gvars' : env.Dictionary()} failed = 0 + case_count = 0 while cases: input, expect = cases[:2] expect = convert(expect) @@ -250,12 +273,14 @@ class SubstTestCase(unittest.TestCase): else: if result != expect: if failed == 0: print() - print(" input %s => \n%s did not match \n%s" % (repr(input), repr(result), repr(expect))) + print("[%4d] input %s => \n%s did not match \n%s" % (case_count, repr(input), repr(result), repr(expect))) failed = failed + 1 del cases[:2] + case_count += 1 fmt = "%d %s() cases failed" assert failed == 0, fmt % (failed, function.__name__) + class scons_subst_TestCase(SubstTestCase): # Basic tests of substitution functionality. @@ -518,6 +543,35 @@ class scons_subst_TestCase(SubstTestCase): gvars=gvars) assert newcom == "test foo bar with spaces.out s t", newcom + def test_subst_callable_with_default_expansion(self): + """Test scons_subst(): expanding a callable with a default value arg""" + env = DummyEnv(self.loc) + gvars = env.Dictionary() + newcom = scons_subst("test $CallableWithDefault $SOURCES $TARGETS", env, + target=self.MyNode('t'), source=self.MyNode('s'), + gvars=gvars) + assert newcom == "test CallableWithDefault: default s t", newcom + + def test_subst_partial_callable_with_default_expansion(self): + """Test scons_subst(): expanding a functools.partial callable which sets + the default value in the callable""" + env = DummyEnv(self.loc) + gvars = env.Dictionary() + newcom = scons_subst("test $PartialCallable $SOURCES $TARGETS", env, + target=self.MyNode('t'), source=self.MyNode('s'), + gvars=gvars) + assert newcom == "test CallableWithDefault: partial s t", newcom + + def test_subst_partial_callable_with_no_default_expansion(self): + """Test scons_subst(): expanding a functools.partial callable which sets + the value for extraneous function argument""" + env = DummyEnv(self.loc) + gvars = env.Dictionary() + newcom = scons_subst("test $PartialCallableNoDefault $SOURCES $TARGETS", env, + target=self.MyNode('t'), source=self.MyNode('s'), + gvars=gvars) + assert newcom == "test CallableWithNoDefault: partialNoDefault s t", newcom + def test_subst_attribute_errors(self): """Test scons_subst(): handling attribute errors""" env = DummyEnv(self.loc) -- cgit v0.12 From ab533414196ee43718929414cc6328dadf123da0 Mon Sep 17 00:00:00 2001 From: William Deegan Date: Sat, 27 Feb 2021 13:25:25 -0800 Subject: Add to CHANGES.txt and RELEASE.txt info on the changes for this PR --- CHANGES.txt | 6 ++++++ RELEASE.txt | 6 ++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 3384bb7..72a32d5 100755 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,12 @@ NOTE: The 4.0.0 Release of SCons dropped Python 2.7 Support RELEASE VERSION/DATE TO BE FILLED IN LATER + From William Deegan: + - Improve Subst()'s logic to check for proper callable function or class's argument list. + It will now allow callables with expected args, and any extra args as long as they + have default arguments. Additionally functions with no defaults for extra arguments + as long as they are set using functools.partial to create a new callable which set them. + From Daniel Moody: - Update CacheDir to use uuid for tmpfile uniqueness instead of pid. This fixes cases for shared cache where two systems write to the same diff --git a/RELEASE.txt b/RELEASE.txt index 89d634c..f794a82 100755 --- a/RELEASE.txt +++ b/RELEASE.txt @@ -19,8 +19,10 @@ DEPRECATED FUNCTIONALITY CHANGED/ENHANCED EXISTING FUNCTIONALITY --------------------------------------- -- List modifications to existing features, where the previous behavior - wouldn't actually be considered a bug + - Improve Subst()'s logic to check for proper callable function or class's argument list. + It will now allow callables with expected args, and any extra args as long as they + have default arguments. Additionally functions with no defaults for extra arguments + as long as they are set using functools.partial to create a new callable which set them. FIXES ----- -- cgit v0.12