diff options
author | William Deegan <bill@baddogconsulting.com> | 2022-02-01 19:12:46 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-02-01 19:12:46 (GMT) |
commit | 6789d9b6467158229d0eb8044cafc37014e8942d (patch) | |
tree | 6429c5d6d3e15e73646c45e08786c247b8d05356 | |
parent | de52cc83605dd49eb2f0a72dfb74a948735555bc (diff) | |
parent | 9cfc3e65cc14dbffc16da5a1ba31c6695dbbacdf (diff) | |
download | SCons-6789d9b6467158229d0eb8044cafc37014e8942d.zip SCons-6789d9b6467158229d0eb8044cafc37014e8942d.tar.gz SCons-6789d9b6467158229d0eb8044cafc37014e8942d.tar.bz2 |
Merge branch 'SCons:master' into fix_py_3_9_resourceWarnings
32 files changed, 649 insertions, 706 deletions
diff --git a/SCons/CacheDir.py b/SCons/CacheDir.py index 8be6643..14e52ad 100644 --- a/SCons/CacheDir.py +++ b/SCons/CacheDir.py @@ -125,7 +125,7 @@ def CachePushFunc(target, source, env): # In any case, inability to push a file to cache doesn't affect # the correctness of the build, so just print a warning. msg = errfmt % (str(t), cachefile) - cd.CacheDebug(errfmt, str(t), cachefile) + cd.CacheDebug(errfmt + '\n', str(t), cachefile) SCons.Warnings.warn(SCons.Warnings.CacheWriteErrorWarning, msg) CachePush = SCons.Action.Action(CachePushFunc, None) diff --git a/SCons/Tool/jar.py b/SCons/Tool/jar.py index a19c40a..ae44ff3 100644 --- a/SCons/Tool/jar.py +++ b/SCons/Tool/jar.py @@ -29,15 +29,19 @@ selection method. """ import os +from typing import List +import SCons.Node +import SCons.Node.FS import SCons.Subst +import SCons.Tool import SCons.Util import SCons.Warnings from SCons.Node.FS import _my_normcase from SCons.Tool.JavaCommon import get_java_install_dirs -def jarSources(target, source, env, for_signature): +def jarSources(target, source, env, for_signature) -> List[str]: """Only include sources that are not a manifest file.""" try: env['JARCHDIR'] @@ -51,21 +55,22 @@ def jarSources(target, source, env, for_signature): result = [] for src in source: contents = src.get_text_contents() - if not contents.startswith("Manifest-Version"): - if jarchdir_set: - _chdir = jarchdir - else: - try: - _chdir = src.attributes.java_classdir - except AttributeError: - _chdir = None - if _chdir: - # If we are changing the dir with -C, then sources should - # be relative to that directory. - src = SCons.Subst.Literal(src.get_path(_chdir)) - result.append('-C') - result.append(_chdir) - result.append(src) + if contents.startswith("Manifest-Version"): + continue + if jarchdir_set: + _chdir = jarchdir + else: + try: + _chdir = src.attributes.java_classdir + except AttributeError: + _chdir = None + if _chdir: + # If we are changing the dir with -C, then sources should + # be relative to that directory. + src = SCons.Subst.Literal(src.get_path(_chdir)) + result.append('-C') + result.append(_chdir) + result.append(src) return result def jarManifest(target, source, env, for_signature): @@ -76,7 +81,7 @@ def jarManifest(target, source, env, for_signature): return src return '' -def jarFlags(target, source, env, for_signature): +def jarFlags(target, source, env, for_signature) -> str: """If we have a manifest, make sure that the 'm' flag is specified.""" jarflags = env.subst('$JARFLAGS', target=target, source=source) @@ -88,11 +93,14 @@ def jarFlags(target, source, env, for_signature): break return jarflags -def Jar(env, target = None, source = [], *args, **kw): - """ - A pseudo-Builder wrapper around the separate Jar sources{File,Dir} - Builders. +def Jar(env, target=None, source=[], *args, **kw): + """The Jar Builder. + + This is a pseudo-Builder wrapper around the separate jar builders + depending on whether the sources are a file list or a directory. """ + # TODO: W1113: Keyword argument before variable positional arguments list in the definition of Jar function + # TODO: W0102: Dangerous default value [] as argument # jar target should not be a list so assume they passed # no target and want implicit target to be made and the arg @@ -105,14 +113,14 @@ def Jar(env, target = None, source = [], *args, **kw): source = target target = None - # mutiple targets pass so build each target the same from the + # mutiple targets passed so build each target the same from the # same source #TODO Maybe this should only be done once, and the result copied # for each target since it should result in the same? if SCons.Util.is_List(target) and SCons.Util.is_List(source): jars = [] for single_target in target: - jars += env.Jar( target = single_target, source = source, *args, **kw) + jars += env.Jar(target=single_target, source=source, *args, **kw) return jars # they passed no target so make a target implicitly @@ -121,6 +129,7 @@ def Jar(env, target = None, source = [], *args, **kw): # make target from the first source file target = os.path.splitext(str(source[0]))[0] + env.subst('$JARSUFFIX') except: + # TODO: W0702: No exception type(s) specified # something strange is happening but attempt anyways SCons.Warnings.warn( SCons.Warnings.SConsWarning, @@ -143,68 +152,68 @@ def Jar(env, target = None, source = [], *args, **kw): # if its already a class file then it can be used as a # source for jar, otherwise turn it into a class file then # return the source - def file_to_class(s): - if _my_normcase(str(s)).endswith(java_suffix): - return env.JavaClassFile(source = s, *args, **kw) - else: - return [env.fs.File(s)] + def file_to_class(src): + if _my_normcase(str(src)).endswith(java_suffix): + return env.JavaClassFile(source=src, *args, **kw) + return [env.fs.File(src)] # function for calling the JavaClassDir builder if a directory is # passed as a source to Jar builder. The JavaClassDir builder will - # return an empty list if there were not target classes built from + # return an empty list if there were no target classes built from # the directory, in this case assume the user wanted the directory # copied into the jar as is (it contains other files such as - # resources or class files compiled from proir commands) + # resources or class files compiled from prior commands) # TODO: investigate the expexcted behavior for directories that # have mixed content, such as Java files along side other files # files. - def dir_to_class(s): - dir_targets = env.JavaClassDir(source = s, *args, **kw) + def dir_to_class(src): + dir_targets = env.JavaClassDir(source=src, *args, **kw) if dir_targets == []: # no classes files could be built from the source dir # so pass the dir as is. - return [env.fs.Dir(s)] - else: - return dir_targets + return [env.fs.Dir(src)] + return dir_targets # loop through the sources and handle each accordingly # the goal here is to get all the source files into a class # file or a directory that contains class files - for s in SCons.Util.flatten(source): - s = env.subst(s) - if isinstance(s, SCons.Node.FS.Base): - if isinstance(s, SCons.Node.FS.File): + for src in SCons.Util.flatten(source): + src = env.subst(src) + if isinstance(src, SCons.Node.FS.Base): + if isinstance(src, SCons.Node.FS.File): # found a file so make sure its a class file - target_nodes.extend(file_to_class(s)) + target_nodes.extend(file_to_class(src)) else: # found a dir so get the class files out of it - target_nodes.extend(dir_to_class(s)) + target_nodes.extend(dir_to_class(src)) else: try: # source is string try to convert it to file - target_nodes.extend(file_to_class(env.fs.File(s))) + target_nodes.extend(file_to_class(env.fs.File(src))) continue except: + # TODO: W0702: No exception type(s) specified pass try: # source is string try to covnert it to dir - target_nodes.extend(dir_to_class(env.fs.Dir(s))) + target_nodes.extend(dir_to_class(env.fs.Dir(src))) continue except: + # TODO: W0702: No exception type(s) specified pass SCons.Warnings.warn( SCons.Warnings.SConsWarning, - ("File: " + str(s) + ("File: " + str(src) + " could not be identified as File or Directory, skipping.") ) - # at this point all our sources have been converted to classes or directories of class - # so pass it to the Jar builder - return env.JarFile(target = target, source = target_nodes, *args, **kw) + # at this point all our sources have been converted to classes or + # directories of class so pass it to the Jar builder + return env.JarFile(target=target, source=target_nodes, *args, **kw) -def generate(env): +def generate(env) -> None: """Add Builders and construction variables for jar to an Environment.""" SCons.Tool.CreateJarBuilder(env) @@ -222,14 +231,14 @@ def generate(env): jar_bin_dir = os.path.dirname(jar) env.AppendENVPath('PATH', jar_bin_dir) - env['JAR'] = 'jar' - env['JARFLAGS'] = SCons.Util.CLVar('cf') - env['_JARFLAGS'] = jarFlags + env['JAR'] = 'jar' + env['JARFLAGS'] = SCons.Util.CLVar('cf') + env['_JARFLAGS'] = jarFlags env['_JARMANIFEST'] = jarManifest env['_JARSOURCES'] = jarSources - env['_JARCOM'] = '$JAR $_JARFLAGS $TARGET $_JARMANIFEST $_JARSOURCES' - env['JARCOM'] = "${TEMPFILE('$_JARCOM','$JARCOMSTR')}" - env['JARSUFFIX'] = '.jar' + env['_JARCOM'] = '$JAR $_JARFLAGS $TARGET $_JARMANIFEST $_JARSOURCES' + env['JARCOM'] = "${TEMPFILE('$_JARCOM','$JARCOMSTR')}" + env['JARSUFFIX'] = '.jar' def exists(env): # As reported by Jan Nijtmans in issue #2730, the simple @@ -238,7 +247,7 @@ def exists(env): # stop trying to detect an executable (analogous to the # javac Builder). # TODO: Come up with a proper detect() routine...and enable it. - return 1 + return True # Local Variables: # tab-width:4 diff --git a/test/AS/fixture/myas.py b/test/AS/fixture/myas.py index 3d05c79..a348ace 100644 --- a/test/AS/fixture/myas.py +++ b/test/AS/fixture/myas.py @@ -1,6 +1,7 @@ import sys -if sys.platform == 'win32': + +def my_win32_as(): args = sys.argv[1:] inf = None while args: @@ -10,29 +11,41 @@ if sys.platform == 'win32': args = args[2:] continue args = args[1:] - if not a[0] in "/-": + if not a[0] in '/-': if not inf: inf = a continue - if a[:3] == '/Fo': out = a[3:] + if a[:3] == '/Fo': + out = a[3:] + with open(inf, 'rb') as ifp, open(out, 'wb') as ofp: - for l in ifp.readlines(): - if l[:3] != b'#as': - ofp.write(l) - sys.exit(0) + for line in ifp: + if not line.startswith(b'#as'): + ofp.write(line) + -else: +def my_as(): import getopt + try: opts, args = getopt.getopt(sys.argv[1:], 'co:') except getopt.GetoptError: # we may be called with --version, just quit if so sys.exit(0) for opt, arg in opts: - if opt == '-o': out = arg + if opt == '-o': + out = arg + if args: with open(args[0], 'rb') as ifp, open(out, 'wb') as ofp: - for l in ifp.readlines(): - if l[:3] != b'#as': - ofp.write(l) + for line in ifp: + if not line.startswith(b'#as'): + ofp.write(line) + + +if __name__ == "__main__": + if sys.platform == 'win32': + my_win32_as() + else: + my_as() sys.exit(0) diff --git a/test/AS/fixture/myas_args.py b/test/AS/fixture/myas_args.py index 24d68dc..7a5e6fa 100644 --- a/test/AS/fixture/myas_args.py +++ b/test/AS/fixture/myas_args.py @@ -1,6 +1,7 @@ import sys -if sys.platform == 'win32': + +def my_win32_as(): args = sys.argv[1:] inf = None optstring = '' @@ -21,25 +22,38 @@ if sys.platform == 'win32': out = a[3:] continue optstring = optstring + ' ' + a + with open(inf, 'rb') as ifp, open(out, 'wb') as ofp: - ofp.write(bytearray(optstring + "\n",'utf-8')) - for l in ifp.readlines(): - if l[:3] != b'#as': - ofp.write(l) - sys.exit(0) -else: + optstring = optstring + "\n" + ofp.write(optstring.encode('utf-8')) + for line in ifp: + if not line.startswith(b'#as'): + ofp.write(line) + + +def my_as(): import getopt + opts, args = getopt.getopt(sys.argv[1:], 'co:x') optstring = '' for opt, arg in opts: - if opt == '-o': out = arg - else: optstring = optstring + ' ' + opt + if opt == '-o': + out = arg + else: + optstring = optstring + ' ' + opt with open(args[0], 'rb') as ifp, open(out, 'wb') as ofp: - ofp.write(bytearray(optstring + "\n",'utf-8')) - for l in ifp.readlines(): - if l[:3] != b'#as': - ofp.write(l) + optstring = optstring + "\n" + ofp.write(optstring.encode('utf-8')) + for line in ifp: + if not line.startswith(b'#as'): + ofp.write(line) + +if __name__ == "__main__": + if sys.platform == 'win32': + my_win32_as() + else: + my_as() sys.exit(0) diff --git a/test/CC/CC-fixture/.exclude_tests b/test/CC/CC-fixture/.exclude_tests new file mode 100644 index 0000000..3f2bc0f --- /dev/null +++ b/test/CC/CC-fixture/.exclude_tests @@ -0,0 +1 @@ +mycc.py diff --git a/test/CC/CC-fixture/mycc.py b/test/CC/CC-fixture/mycc.py new file mode 100644 index 0000000..eb11c87 --- /dev/null +++ b/test/CC/CC-fixture/mycc.py @@ -0,0 +1,55 @@ +""" +Phony cc command for testing SCons. + +Copies its source file to the target file, dropping lines that match +a pattern, so we can recognize the tool has made a modification. +Intended for use as the $CXX construction variable. + +Note: mycc.py differs from the general fixture file mycompile.py +in arg handling: that one is intended for use as a *COM consvar, +where no compiler consvars will be passed on, this one is intended +for use as $CC, where arguments like -o come into play. +""" +import getopt +import sys + +def fake_win32_cc(): + args = sys.argv[1:] + inf = None + while args: + arg = args[0] + if arg == '-o': + out = args[1] + args = args[2:] + continue + args = args[1:] + if arg[0] not in '/-': + if not inf: + inf = arg + continue + if arg.startswith('/Fo'): + out = arg[3:] + + with open(inf, 'rb') as infile, open(out, 'wb') as outfile: + for line in infile: + if not line.startswith(b'/*cc*/'): + outfile.write(line) + +def fake_cc(): + opts, args = getopt.getopt(sys.argv[1:], 'co:') + for opt, arg in opts: + if opt == '-o': + out = arg + + with open(args[0], 'rb') as infile, open(out, 'wb') as outfile: + for line in infile: + if not line.startswith(b'/*cc*/'): + outfile.write(line) + +if __name__ == '__main__': + print(f"DEBUG: {sys.argv[0]}: {sys.argv[1:]}") + if sys.platform == 'win32': + fake_win32_cc() + else: + fake_cc() + sys.exit(0) diff --git a/test/CC/CC-fixture/test1.c b/test/CC/CC-fixture/test1.c index 7535b0a..6748e2c 100644 --- a/test/CC/CC-fixture/test1.c +++ b/test/CC/CC-fixture/test1.c @@ -1,3 +1,3 @@ This is a .c file. /*cc*/ -/*link*/ +#link diff --git a/test/CC/CC-fixture/test2.C b/test/CC/CC-fixture/test2.C index a1ee9e3..388133b 100644 --- a/test/CC/CC-fixture/test2.C +++ b/test/CC/CC-fixture/test2.C @@ -1,3 +1,3 @@ This is a .C file. /*cc*/ -/*link*/ +#link diff --git a/test/CC/CC.py b/test/CC/CC.py index 6363273..a548421 100644 --- a/test/CC/CC.py +++ b/test/CC/CC.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,106 +22,29 @@ # 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 sys import TestSCons _python_ = TestSCons._python_ -_exe = TestSCons._exe +_exe = TestSCons._exe test = TestSCons.TestSCons() test.dir_fixture('CC-fixture') - -if sys.platform == 'win32': - - test.write('mylink.py', r""" -import sys -args = sys.argv[1:] -while args: - a = args[0] - if a == '-o': - out = args[1] - args = args[2:] - continue - if not a[0] in '/-': - break - args = args[1:] - if a[:5].lower() == '/out:': out = a[5:] -infile = open(args[0], 'rb') -outfile = open(out, 'wb') -for l in infile.readlines(): - if l[:8] != b'/*link*/': - outfile.write(l) -sys.exit(0) -""") - - test.write('mycc.py', r""" -import sys -args = sys.argv[1:] -inf = None -while args: - a = args[0] - if a == '-o': - out = args[1] - args = args[2:] - continue - args = args[1:] - if not a[0] in '-/': - if not inf: - inf = a - continue - if a[:3] == '/Fo': out = a[3:] -infile = open(inf, 'rb') -outfile = open(out, 'wb') -for l in infile.readlines(): - if l[:6] != b'/*cc*/': - outfile.write(l) -sys.exit(0) -""") - -else: - - test.write('mylink.py', r""" -import getopt -import sys -opts, args = getopt.getopt(sys.argv[1:], 'o:') -for opt, arg in opts: - if opt == '-o': out = arg -infile = open(args[0], 'rb') -outfile = open(out, 'wb') -for l in infile.readlines(): - if l[:8] != b'/*link*/': - outfile.write(l) -sys.exit(0) -""") - - test.write('mycc.py', r""" -import getopt -import sys -opts, args = getopt.getopt(sys.argv[1:], 'co:') -for opt, arg in opts: - if opt == '-o': out = arg -infile = open(args[0], 'rb') -outfile = open(out, 'wb') -for l in infile.readlines(): - if l[:6] != b'/*cc*/': - outfile.write(l) -sys.exit(0) -""") +test.file_fixture('mylink.py') test.write('SConstruct', """ cc = Environment().Dictionary('CC') -env = Environment(LINK = r'%(_python_)s mylink.py', - LINKFLAGS = [], - CC = r'%(_python_)s mycc.py', - CXX = cc, - CXXFLAGS = []) -env.Program(target = 'test1', source = 'test1.c') +env = Environment( + LINK=r'%(_python_)s mylink.py', + LINKFLAGS=[], + CC=r'%(_python_)s mycc.py', + CXX=cc, + CXXFLAGS=[], +) +env.Program(target='test1', source='test1.c') """ % locals()) test.run(arguments = '.', stderr = None) @@ -130,10 +55,12 @@ if os.path.normcase('.c') == os.path.normcase('.C'): test.write('SConstruct', """ cc = Environment().Dictionary('CC') -env = Environment(LINK = r'%(_python_)s mylink.py', - CC = r'%(_python_)s mycc.py', - CXX = cc) -env.Program(target = 'test2', source = 'test2.C') +env = Environment( + LINK=r'%(_python_)s mylink.py', + CC=r'%(_python_)s mycc.py', + CXX=cc, +) +env.Program(target='test2', source='test2.C') """ % locals()) test.run(arguments = '.', stderr = None) @@ -144,9 +71,9 @@ test.file_fixture('wrapper.py') test.write('SConstruct', """ foo = Environment() cc = foo.Dictionary('CC') -bar = Environment(CC = r'%(_python_)s wrapper.py ' + cc) -foo.Program(target = 'foo', source = 'foo.c') -bar.Program(target = 'bar', source = 'bar.c') +bar = Environment(CC=r'%(_python_)s wrapper.py ' + cc) +foo.Program(target='foo', source='foo.c') +bar.Program(target='bar', source='bar.c') """ % locals()) test.run(arguments = 'foo' + _exe) diff --git a/test/CFILESUFFIX.py b/test/CFILESUFFIX.py index 0a62307..2d24e25 100644 --- a/test/CFILESUFFIX.py +++ b/test/CFILESUFFIX.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" """ Verify that we can set CFILESUFFIX to arbitrary values. @@ -35,32 +34,19 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -test.write('mylex.py', """ -import getopt -import sys -if sys.platform == 'win32': - longopts = ['nounistd'] -else: - longopts = [] -cmd_opts, args = getopt.getopt(sys.argv[1:], 't', longopts) -for a in args: - with open(a, 'rb') as f: - contents = f.read() - sys.stdout.write((contents.replace(b'LEX', b'mylex.py')).decode()) -sys.exit(0) -""") +test.file_fixture('mylex.py') test.write('SConstruct', """ -env = Environment(LEX = r'%(_python_)s mylex.py', tools = ['lex']) -env.CFile(target = 'foo', source = 'foo.l') -env.Clone(CFILESUFFIX = '.xyz').CFile(target = 'bar', source = 'bar.l') +env = Environment(LEX=r'%(_python_)s mylex.py', tools=['lex']) +env.CFile(target='foo', source='foo.l') +env.Clone(CFILESUFFIX='.xyz').CFile(target='bar', source='bar.l') # Make sure that calling a Tool on a construction environment *after* # we've set CFILESUFFIX doesn't overwrite the value. -env2 = Environment(tools = [], CFILESUFFIX = '.env2') +env2 = Environment(tools=[], CFILESUFFIX='.env2') env2.Tool('lex') env2['LEX'] = r'%(_python_)s mylex.py' -env2.CFile(target = 'f3', source = 'f3.l') +env2.CFile(target='f3', source='f3.l') """ % locals()) input = r""" diff --git a/test/CPPFLAGS.py b/test/CPPFLAGS.py index 2808a53..ebae2df 100644 --- a/test/CPPFLAGS.py +++ b/test/CPPFLAGS.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 sys @@ -38,25 +37,22 @@ test = TestSCons.TestSCons() if sys.platform == 'win32': test.skip_test('Skipping on win32.\n') -if sys.platform == 'win32': - test.file_fixture('mylink_win32.py', 'mylink.py') -else: - test.file_fixture('mylink.py') - +test.file_fixture('mylink.py') test.file_fixture('mygcc.py') - test.write('SConstruct', """ -env = Environment(CPPFLAGS = '-x', - LINK = r'%(_python_)s mylink.py', - LINKFLAGS = [], - CC = r'%(_python_)s mygcc.py cc', - CXX = r'%(_python_)s mygcc.py c++', - CXXFLAGS = [], - FORTRAN = r'%(_python_)s mygcc.py g77', - OBJSUFFIX = '.obj', - PROGSUFFIX = '.exe') -env.Program(target = 'foo', source = Split('test1.c test2.cpp test3.F')) +env = Environment( + CPPFLAGS='-x', + LINK=r'%(_python_)s mylink.py', + LINKFLAGS=[], + CC=r'%(_python_)s mygcc.py cc', + CXX=r'%(_python_)s mygcc.py c++', + CXXFLAGS=[], + FORTRAN=r'%(_python_)s mygcc.py g77', + OBJSUFFIX='.obj', + PROGSUFFIX='.exe', +) +env.Program(target='foo', source=Split('test1.c test2.cpp test3.F')) """ % locals()) test.write('test1.c', r"""test1.c @@ -86,19 +82,20 @@ else: test.must_match('mygcc.out', "cc\nc++\n") test.write('SConstruct', """ -env = Environment(CPPFLAGS = '-x', - SHLINK = r'%(_python_)s mylink.py', - SHLINKFLAGS = [], - CC = r'%(_python_)s mygcc.py cc', - CXX = r'%(_python_)s mygcc.py c++', - CXXFLAGS = [], - FORTRAN = r'%(_python_)s mygcc.py g77', - OBJSUFFIX = '.obj', - SHOBJPREFIX = '', - SHOBJSUFFIX = '.shobj', - PROGSUFFIX = '.exe') -env.SharedLibrary(target = File('foo.bar'), - source = Split('test1.c test2.cpp test3.F')) +env = Environment( + CPPFLAGS='-x', + SHLINK=r'%(_python_)s mylink.py', + SHLINKFLAGS=[], + CC=r'%(_python_)s mygcc.py cc', + CXX=r'%(_python_)s mygcc.py c++', + CXXFLAGS=[], + FORTRAN=r'%(_python_)s mygcc.py g77', + OBJSUFFIX='.obj', + SHOBJPREFIX='', + SHOBJSUFFIX='.shobj', + PROGSUFFIX='.exe', +) +env.SharedLibrary(target=File('foo.bar'), source=Split('test1.c test2.cpp test3.F')) """ % locals()) test.write('test1.c', r"""test1.c diff --git a/test/CXX/CXX-fixture/.exclude_tests b/test/CXX/CXX-fixture/.exclude_tests new file mode 100644 index 0000000..9e0e6ff --- /dev/null +++ b/test/CXX/CXX-fixture/.exclude_tests @@ -0,0 +1 @@ +myc++.py diff --git a/test/CXX/CXX-fixture/myc++.py b/test/CXX/CXX-fixture/myc++.py new file mode 100644 index 0000000..d369f61 --- /dev/null +++ b/test/CXX/CXX-fixture/myc++.py @@ -0,0 +1,55 @@ +""" +Phony c++ command for testing SCons. + +Copies its source file to the target file, dropping lines that match +a pattern, so we can recognize the tool has made a modification. +Intended for use as the $CXX construction variable. + +Note: mycxx.py differs from the general fixture file mycompile.py +in arg handling: that one is intended for use as a *COM consvar, +where no compiler consvars will be passed on, this one is intended +for use as $CXX, where arguments like -o come into play. +""" +import getopt +import sys + +def fake_win32_cxx(): + args = sys.argv[1:] + inf = None + while args: + arg = args[0] + if arg == '-o': + out = args[1] + args = args[2:] + continue + args = args[1:] + if arg[0] not in '/-': + if not inf: + inf = arg + continue + if arg.startswith('/Fo'): + out = arg[3:] + + with open(inf, 'rb') as infile, open(out, 'wb') as outfile: + for line in infile: + if not line.startswith(b'/*c++*/'): + outfile.write(line) + +def fake_cxx(): + opts, args = getopt.getopt(sys.argv[1:], 'co:') + for opt, arg in opts: + if opt == '-o': + out = arg + + with open(args[0], 'rb') as infile, open(out, 'wb') as outfile: + for line in infile: + if not line.startswith(b'/*c++*/'): + outfile.write(line) + +if __name__ == '__main__': + print(f"DEBUG: {sys.argv[0]}: {sys.argv[1:]}") + if sys.platform == 'win32': + fake_win32_cxx() + else: + fake_cxx() + sys.exit(0) diff --git a/test/CXX/CXX.py b/test/CXX/CXX.py index 4be4199..ad00b55 100644 --- a/test/CXX/CXX.py +++ b/test/CXX/CXX.py @@ -1,6 +1,8 @@ #!/usr/bin/env python # -# __COPYRIGHT__ +# MIT License +# +# Copyright The SCons Foundation # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -20,9 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import sys import TestSCons @@ -32,120 +31,46 @@ _exe = TestSCons._exe test = TestSCons.TestSCons() - - -if sys.platform == 'win32': - - test.write('mylink.py', r""" -import sys -args = sys.argv[1:] -while args: - a = args[0] - if a == '-o': - out = args[1] - args = args[2:] - continue - if not a[0] in '/-': - break - args = args[1:] - if a[:5].lower() == '/out:': out = a[5:] -infile = open(args[0], 'r') -outfile = open(out, 'w') -for l in infile.readlines(): - if l[:8] != '/*link*/': - outfile.write(l) -sys.exit(0) -""") - - test.write('myc++.py', r""" -import sys -args = sys.argv[1:] -inf = None -while args: - a = args[0] - if a == '-o': - out = args[1] - args = args[2:] - continue - args = args[1:] - if not a[0] in '/-': - if not inf: - inf = a - continue - if a[:3] == '/Fo': out = a[3:] -infile = open(inf, 'r') -outfile = open(out, 'w') -for l in infile.readlines(): - if l[:7] != '/*c++*/': - outfile.write(l) -sys.exit(0) -""") - -else: - - test.write('mylink.py', r""" -import getopt -import sys -opts, args = getopt.getopt(sys.argv[1:], 'o:') -for opt, arg in opts: - if opt == '-o': out = arg -infile = open(args[0], 'r') -outfile = open(out, 'w') -for l in infile.readlines(): - if l[:8] != '/*link*/': - outfile.write(l) -sys.exit(0) -""") - - test.write('myc++.py', r""" -import getopt -import sys -opts, args = getopt.getopt(sys.argv[1:], 'co:') -for opt, arg in opts: - if opt == '-o': out = arg -infile = open(args[0], 'r') -outfile = open(out, 'w') -for l in infile.readlines(): - if l[:7] != '/*c++*/': - outfile.write(l) -sys.exit(0) -""") +test.file_fixture('mylink.py') +test.dir_fixture('CXX-fixture') test.write('SConstruct', """ -env = Environment(LINK = r'%(_python_)s mylink.py', - LINKFLAGS = [], - CXX = r'%(_python_)s myc++.py', - CXXFLAGS = []) -env.Program(target = 'test1', source = 'test1.cc') -env.Program(target = 'test2', source = 'test2.cpp') -env.Program(target = 'test3', source = 'test3.cxx') -env.Program(target = 'test4', source = 'test4.c++') -env.Program(target = 'test5', source = 'test5.C++') +env = Environment( + LINK=r'%(_python_)s mylink.py', + LINKFLAGS=[], + CXX=r'%(_python_)s myc++.py', + CXXFLAGS=[], +) +env.Program(target='test1', source='test1.cc') +env.Program(target='test2', source='test2.cpp') +env.Program(target='test3', source='test3.cxx') +env.Program(target='test4', source='test4.c++') +env.Program(target='test5', source='test5.C++') """ % locals()) test.write('test1.cc', r"""This is a .cc file. /*c++*/ -/*link*/ +#link """) test.write('test2.cpp', r"""This is a .cpp file. /*c++*/ -/*link*/ +#link """) test.write('test3.cxx', r"""This is a .cxx file. /*c++*/ -/*link*/ +#link """) test.write('test4.c++', r"""This is a .c++ file. /*c++*/ -/*link*/ +#link """) test.write('test5.C++', r"""This is a .C++ file. /*c++*/ -/*link*/ +#link """) test.run(arguments = '.', stderr = None) @@ -161,35 +86,32 @@ test.must_match('test4' + _exe, "This is a .c++ file.\n", mode='r') test.must_match('test5' + _exe, "This is a .C++ file.\n", mode='r') if TestSCons.case_sensitive_suffixes('.c', '.C'): - test.write('SConstruct', """ -env = Environment(LINK = r'%(_python_)s mylink.py', - LINKFLAGS = [], - CXX = r'%(_python_)s myc++.py', - CXXFLAGS = []) -env.Program(target = 'test6', source = 'test6.C') +env = Environment( + LINK=r'%(_python_)s mylink.py', + LINKFLAGS=[], + CXX=r'%(_python_)s myc++.py', + CXXFLAGS=[], +) +env.Program(target='test6', source='test6.C') """ % locals()) test.write('test6.C', r"""This is a .C file. /*c++*/ -/*link*/ +#link """) test.run(arguments = '.', stderr = None) - test.must_match('test6' + _exe, "This is a .C file.\n", mode='r') - - - test.file_fixture('wrapper.py') test.write('SConstruct', """ foo = Environment() cxx = foo.Dictionary('CXX') -bar = Environment(CXX = r'%(_python_)s wrapper.py ' + cxx) -foo.Program(target = 'foo', source = 'foo.cxx') -bar.Program(target = 'bar', source = 'bar.cxx') +bar = Environment(CXX=r'%(_python_)s wrapper.py ' + cxx) +foo.Program(target='foo', source='foo.cxx') +bar.Program(target='bar', source='bar.cxx') """ % locals()) test.write('foo.cxx', r""" diff --git a/test/CXX/CXXFILESUFFIX.py b/test/CXX/CXXFILESUFFIX.py index 0ae5827..1c55106 100644 --- a/test/CXX/CXXFILESUFFIX.py +++ b/test/CXX/CXXFILESUFFIX.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,10 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import TestSCons @@ -31,32 +29,19 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -test.write('mylex.py', """ -import getopt -import sys -if sys.platform == 'win32': - longopts = ['nounistd'] -else: - longopts = [] -cmd_opts, args = getopt.getopt(sys.argv[1:], 't', longopts) -for a in args: - with open(a, 'r') as f: - contents = f.read() - sys.stdout.write(contents.replace('LEX', 'mylex.py')) -sys.exit(0) -""") +test.file_fixture('mylex.py') test.write('SConstruct', """ -env = Environment(LEX = r'%(_python_)s mylex.py', tools = ['lex']) -env.CXXFile(target = 'foo', source = 'foo.ll') -env.Clone(CXXFILESUFFIX = '.xyz').CXXFile(target = 'bar', source = 'bar.ll') +env = Environment(LEX=r'%(_python_)s mylex.py', tools=['lex']) +env.CXXFile(target='foo', source='foo.ll') +env.Clone(CXXFILESUFFIX='.xyz').CXXFile(target='bar', source='bar.ll') # Make sure that calling a Tool on a construction environment *after* # we've set CXXFILESUFFIX doesn't overwrite the value. -env2 = Environment(tools = [], CXXFILESUFFIX = '.env2') +env2 = Environment(tools=[], CXXFILESUFFIX='.env2') env2.Tool('lex') env2['LEX'] = r'%(_python_)s mylex.py' -env2.CXXFile(target = 'f3', source = 'f3.ll') +env2.CXXFile(target='f3', source='f3.ll') """ % locals()) input = r""" diff --git a/test/Java/JAR.py b/test/Java/JAR.py index bc52a89..2d67717 100644 --- a/test/Java/JAR.py +++ b/test/Java/JAR.py @@ -23,6 +23,12 @@ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +""" +Test Jar builder. + +These tests require a findable/working Java subsystem. +""" + import os import TestSCons @@ -30,115 +36,23 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -# Keep this logic because it skips the test if javac or jar not found. where_javac, java_version = test.java_where_javac() where_jar = test.java_where_jar() -test.write('myjar.py', r""" -import sys -args = sys.argv[1:] -while args: - a = args[0] - if a == 'cf': - out = args[1] - args = args[1:] - else: - break - args = args[1:] -outfile = open(out, 'w') -for file in args: - infile = open(file, 'r') - for l in infile.readlines(): - if l[:7] != '/*jar*/': - outfile.write(l) -sys.exit(0) -""") - -test.write('SConstruct', """ -DefaultEnvironment(tools=[]) -env = Environment(tools = ['jar'], - JAR = r'%(_python_)s myjar.py') -env.Jar(target = 'test1.jar', source = 'test1.class') -""" % locals()) - -test.write('test1.class', """\ -test1.class -/*jar*/ -line 3 -""") - -test.run(arguments='.', stderr=None) - -test.must_match('test1.jar', "test1.class\nline 3\n", mode='r') - -if os.path.normcase('.class') == os.path.normcase('.CLASS'): - - test.write('SConstruct', """ -DefaultEnvironment(tools=[]) -env = Environment(tools = ['jar'], - JAR = r'%(_python_)s myjar.py') -env.Jar(target = 'test2.jar', source = 'test2.CLASS') -""" % locals()) - - test.write('test2.CLASS', """\ -test2.CLASS -/*jar*/ -line 3 -""") - - test.run(arguments='.', stderr=None) - - test.must_match('test2.jar', "test2.CLASS\nline 3\n", mode='r') - -test.write('myjar2.py', r""" -import sys -f=open(sys.argv[2], 'w') -f.write(" ".join(sys.argv[1:])) -f.write("\n") -f.close() -sys.exit(0) -""") - -test.write('SConstruct', """ -DefaultEnvironment(tools=[]) -env = Environment(tools = ['jar'], - JAR = r'%(_python_)s myjar2.py', - JARFLAGS='cvf') -env.Jar(target = 'classes.jar', source = [ 'testdir/bar.class', - 'foo.mf' ], - TESTDIR='testdir', - JARCHDIR='$TESTDIR') -""" % locals()) - -test.subdir('testdir') -test.write(['testdir', 'bar.class'], 'foo') -test.write('foo.mf', - """Manifest-Version : 1.0 - blah - blah - blah - """) -test.run(arguments='classes.jar') -test.must_match('classes.jar', - 'cvfm classes.jar foo.mf -C testdir bar.class\n', mode='r') - test.file_fixture('wrapper_with_args.py') -test.write('SConstruct', """ +test.write('SConstruct', """\ DefaultEnvironment(tools=[]) -foo = Environment(tools = ['javac', 'jar']) +foo = Environment(tools=['javac', 'jar']) # jar = foo.Dictionary('JAR') -bar = foo.Clone(JAR = r'%(_python_)s wrapper_with_args.py jar') -foo.Java(target = 'classes', source = 'com/sub/foo') -bar.Java(target = 'classes', source = 'com/sub/bar') -foo.Jar(target = 'foo', source = 'classes/com/sub/foo') -bar.Jar(target = 'bar', source = Dir('classes/com/sub/bar')) +bar = foo.Clone(JAR=r'%(_python_)s wrapper_with_args.py jar') +foo.Java(target='classes', source='com/sub/foo') +bar.Java(target='classes', source='com/sub/bar') +foo.Jar(target='foo', source='classes/com/sub/foo') +bar.Jar(target='bar', source=Dir('classes/com/sub/bar')) """ % locals()) -test.subdir('com', - ['com', 'sub'], - ['com', 'sub', 'foo'], - ['com', 'sub', 'bar']) +test.subdir('com', ['com', 'sub'], ['com', 'sub', 'foo'], ['com', 'sub', 'bar']) test.write(['com', 'sub', 'foo', 'Example1.java'], """\ package com.sub.foo; @@ -228,13 +142,12 @@ test.run(arguments = '.') expected_wrapper_out = "wrapper_with_args.py jar cf bar.jar classes/com/sub/bar\n" expected_wrapper_out = expected_wrapper_out.replace('/', os.sep) -test.must_match('wrapper.out', - expected_wrapper_out % locals(), mode='r') +test.must_match('wrapper.out', expected_wrapper_out % locals(), mode='r') test.must_exist('foo.jar') test.must_exist('bar.jar') -test.up_to_date(arguments = '.') +test.up_to_date(arguments='.') ####### # test java source files as source to Jar builder @@ -250,22 +163,43 @@ test.write(['testdir2', 'SConstruct'], """ DefaultEnvironment(tools=[]) foo = Environment() -foo.Jar(target = 'foobar', source = [ - 'com/javasource/JavaFile1.java', - 'com/javasource/JavaFile2.java', - 'com/javasource/JavaFile3.java' -]) -foo.Jar(target = ['foo', 'bar'], source = [ - 'com/javasource/JavaFile1.java', - 'com/javasource/JavaFile2.java', - 'com/javasource/JavaFile3.java' -]) -foo.Command("foobarTest", [], Mkdir("foobarTest") ) -foo.Command('foobarTest/com/javasource/JavaFile3.java', 'foobar.jar', foo['JAR'] + ' xvf ../foobar.jar', chdir='foobarTest') -foo.Command("fooTest", [], Mkdir("fooTest") ) -foo.Command('fooTest/com/javasource/JavaFile3.java', 'foo.jar', foo['JAR'] + ' xvf ../foo.jar', chdir='fooTest') -foo.Command("barTest", [], Mkdir("barTest") ) -foo.Command('barTest/com/javasource/JavaFile3.java', 'bar.jar', foo['JAR'] + ' xvf ../bar.jar', chdir='barTest') +foo.Jar( + target='foobar', + source=[ + 'com/javasource/JavaFile1.java', + 'com/javasource/JavaFile2.java', + 'com/javasource/JavaFile3.java', + ], +) +foo.Jar( + target=['foo', 'bar'], + source=[ + 'com/javasource/JavaFile1.java', + 'com/javasource/JavaFile2.java', + 'com/javasource/JavaFile3.java', + ], +) +foo.Command("foobarTest", [], Mkdir("foobarTest")) +foo.Command( + 'foobarTest/com/javasource/JavaFile3.java', + 'foobar.jar', + foo['JAR'] + ' xvf ../foobar.jar', + chdir='foobarTest', +) +foo.Command("fooTest", [], Mkdir("fooTest")) +foo.Command( + 'fooTest/com/javasource/JavaFile3.java', + 'foo.jar', + foo['JAR'] + ' xvf ../foo.jar', + chdir='fooTest', +) +foo.Command("barTest", [], Mkdir("barTest")) +foo.Command( + 'barTest/com/javasource/JavaFile3.java', + 'bar.jar', + foo['JAR'] + ' xvf ../bar.jar', + chdir='barTest', +) """) test.write(['testdir2', 'com', 'javasource', 'JavaFile1.java'], """\ @@ -309,11 +243,7 @@ public class JavaFile3 # use regex . for dirsep so this will work on both windows and other platforms. expect = ".*jar cf foo.jar -C com.javasource.JavaFile1 com.javasource.JavaFile1.class -C com.javasource.JavaFile2 com.javasource.JavaFile2.class -C com.javasource.JavaFile3 com.javasource.JavaFile3.class.*" -test.run(chdir='testdir2', - match=TestSCons.match_re_dotall, - stdout = expect) - - +test.run(chdir='testdir2', match=TestSCons.match_re_dotall, stdout=expect) #test single target jar test.must_exist(['testdir2','foobar.jar']) @@ -338,12 +268,14 @@ test.must_exist(['testdir2', 'barTest', 'com', 'javasource', 'JavaFile3.class']) # test list of lists # make some directories to test in -test.subdir('listOfLists', - ['manifest_dir'], - ['listOfLists', 'src'], - ['listOfLists', 'src', 'com'], - ['listOfLists', 'src', 'com', 'javasource'], - ['listOfLists', 'src', 'com', 'resource']) +test.subdir( + 'listOfLists', + ['manifest_dir'], + ['listOfLists', 'src'], + ['listOfLists', 'src', 'com'], + ['listOfLists', 'src', 'com', 'javasource'], + ['listOfLists', 'src', 'com', 'resource'], +) # test varient dir and lists of lists test.write(['listOfLists', 'SConstruct'], """ @@ -352,15 +284,26 @@ DefaultEnvironment(tools=[]) foo = Environment() foo.VariantDir('build', 'src', duplicate=0) foo.VariantDir('test', '../manifest_dir', duplicate=0) -sourceFiles = ["src/com/javasource/JavaFile1.java", "src/com/javasource/JavaFile2.java", "src/com/javasource/JavaFile3.java",] +sourceFiles = [ + "src/com/javasource/JavaFile1.java", + "src/com/javasource/JavaFile2.java", + "src/com/javasource/JavaFile3.java", +] list_of_class_files = foo.Java('build', source=sourceFiles) resources = ['build/com/resource/resource1.txt', 'build/com/resource/resource2.txt'] for resource in resources: - foo.Command(resource, list_of_class_files, Copy(resource, resource.replace('build','src'))) + foo.Command( + resource, list_of_class_files, Copy(resource, resource.replace('build', 'src')) + ) contents = [list_of_class_files, resources] -foo.Jar(target = 'lists', source = contents + ['test/MANIFEST.mf'], JARCHDIR='build') -foo.Command("listsTest", [], Mkdir("listsTest") ) -foo.Command('listsTest/src/com/javasource/JavaFile3.java', 'lists.jar', foo['JAR'] + ' xvf ../lists.jar', chdir='listsTest') +foo.Jar(target='lists', source=contents + ['test/MANIFEST.mf'], JARCHDIR='build') +foo.Command("listsTest", [], Mkdir("listsTest")) +foo.Command( + 'listsTest/src/com/javasource/JavaFile3.java', + 'lists.jar', + foo['JAR'] + ' xvf ../lists.jar', + chdir='listsTest', +) """) test.write(['listOfLists', 'src', 'com', 'javasource', 'JavaFile1.java'], """\ @@ -431,25 +374,34 @@ test.must_contain(['listOfLists', 'listsTest', 'META-INF', 'MANIFEST.MF'], b"MyM # test different style of passing in dirs # make some directories to test in -test.subdir('testdir3', - ['testdir3', 'com'], - ['testdir3', 'com', 'sub'], - ['testdir3', 'com', 'sub', 'foo'], - ['testdir3', 'com', 'sub', 'bar']) +test.subdir( + 'testdir3', + ['testdir3', 'com'], + ['testdir3', 'com', 'sub'], + ['testdir3', 'com', 'sub', 'foo'], + ['testdir3', 'com', 'sub', 'bar'], +) # Create the jars then extract them back to check contents test.write(['testdir3', 'SConstruct'], """ DefaultEnvironment(tools=[]) foo = Environment() -bar = foo.Clone() -foo.Java(target = 'classes', source = 'com/sub/foo') -bar.Java(target = 'classes', source = 'com/sub/bar') -foo.Jar(target = 'foo', source = 'classes/com/sub/foo', JARCHDIR='classes') -bar.Jar(target = 'bar', source = Dir('classes/com/sub/bar'), JARCHDIR='classes') -foo.Command("fooTest", 'foo.jar', Mkdir("fooTest") ) +foo_cls = foo.Java(target='classes', source='com/sub/foo') +foo_res = 'classes/com/sub/foo/NonJava.txt' +foo_res_src = 'com/sub/foo/NonJava.txt' +foo.Command(foo_res, foo_cls, Copy(foo_res, foo_res_src)) +foo.Jar(target='foo', source='classes/com/sub/foo', JARCHDIR='classes') +foo.Command("fooTest", 'foo.jar', Mkdir("fooTest")) foo.Command('doesnt_exist1', "fooTest", foo['JAR'] + ' xvf ../foo.jar', chdir='fooTest') -bar.Command("barTest", 'bar.jar', Mkdir("barTest") ) + +bar = foo.Clone() +bar_cls = bar.Java(target='classes', source='com/sub/bar') +bar_res = 'classes/com/sub/bar/NonJava.txt' +bar_res_src = 'com/sub/bar/NonJava.txt' +bar.Command(bar_res, bar_cls, Copy(bar_res, bar_res_src)) +bar.Jar(target='bar', source=Dir('classes/com/sub/bar'), JARCHDIR='classes') +bar.Command("barTest", 'bar.jar', Mkdir("barTest")) bar.Command('doesnt_exist2', 'barTest', bar['JAR'] + ' xvf ../bar.jar', chdir='barTest') """) @@ -549,7 +501,6 @@ test.run(chdir='testdir3') # check the output and make sure the java files got converted to classes - # make sure there are class in the jar test.must_exist(['testdir3','foo.jar']) test.must_exist(['testdir3', 'fooTest', 'com', 'sub', 'foo', 'Example1.class']) @@ -557,7 +508,7 @@ test.must_exist(['testdir3', 'fooTest', 'com', 'sub', 'foo', 'Example2.class']) test.must_exist(['testdir3', 'fooTest', 'com', 'sub', 'foo', 'Example3.class']) # TODO: determine expected behavior with resource files, should they be # automatically copied in or specified in seperate commands -#test.must_exist(['testdir3', 'fooTest', 'com', 'sub', 'foo', 'NonJava.txt']) +test.must_exist(['testdir3', 'fooTest', 'com', 'sub', 'foo', 'NonJava.txt']) # make sure both jars got createds test.must_exist(['testdir3','bar.jar']) @@ -566,11 +517,10 @@ test.must_exist(['testdir3', 'barTest', 'com', 'sub', 'bar', 'Example5.class']) test.must_exist(['testdir3', 'barTest', 'com', 'sub', 'bar', 'Example6.class']) # TODO: determine expected behavior with resource files, should they be # automatically copied in or specified in seperate commands -#test.must_exist(['testdir3', 'fooTest', 'com', 'sub', 'bar', 'NonJava.txt']) +test.must_exist(['testdir3', 'barTest', 'com', 'sub', 'bar', 'NonJava.txt']) test.pass_test() - # Local Variables: # tab-width:4 # indent-tabs-mode:nil diff --git a/test/Java/JAVAC.py b/test/Java/JAVAC.py index 20f7f96..f303e87 100644 --- a/test/Java/JAVAC.py +++ b/test/Java/JAVAC.py @@ -25,6 +25,8 @@ """ Test setting the JAVAC variable. + +This test does not require a JDK to operate. """ import os @@ -35,33 +37,11 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() +test.file_fixture(['Java-fixture', 'myjavac.py']) - -test.write('myjavac.py', r""" -import sys -args = sys.argv[1:] -while args: - a = args[0] - if a == '-d': - args = args[1:] - elif a == '-sourcepath': - args = args[1:] - else: - break - args = args[1:] -for file in args: - infile = open(file, 'r') - outfile = open(file[:-5] + '.class', 'w') - for l in infile.readlines(): - if l[:9] != '/*javac*/': - outfile.write(l) -sys.exit(0) -""") - -test.write('SConstruct', """ -env = Environment(tools = ['javac'], - JAVAC = r'%(_python_)s myjavac.py') -env.Java(target = '.', source = '.') +test.write('SConstruct', """\ +env = Environment(tools=['javac'], JAVAC=r'%(_python_)s myjavac.py') +env.Java(target='.', source='.') """ % locals()) test.write('test1.java', """\ @@ -71,15 +51,12 @@ line 3 """) test.run(arguments='.', stderr=None) - test.must_match('test1.class', "test1.java\nline 3\n", mode='r') if os.path.normcase('.java') == os.path.normcase('.JAVA'): - test.write('SConstruct', """\ -env = Environment(tools = ['javac'], - JAVAC = r'%(_python_)s myjavac.py') -env.Java(target = '.', source = '.') +env = Environment(tools=['javac'], JAVAC=r'%(_python_)s myjavac.py') +env.Java(target='.', source='.') """ % locals()) test.write('test2.JAVA', """\ @@ -89,11 +66,8 @@ line 3 """) test.run(arguments='.', stderr=None) - test.must_match('test2.class', "test2.JAVA\nline 3\n", mode='r') - - test.pass_test() # Local Variables: diff --git a/test/Java/Java-fixture/.exclude_tests b/test/Java/Java-fixture/.exclude_tests new file mode 100644 index 0000000..37004e6 --- /dev/null +++ b/test/Java/Java-fixture/.exclude_tests @@ -0,0 +1,2 @@ +myjar.py +myjavac.py diff --git a/test/Java/Java-fixture/myjar.py b/test/Java/Java-fixture/myjar.py new file mode 100644 index 0000000..a47e3b0 --- /dev/null +++ b/test/Java/Java-fixture/myjar.py @@ -0,0 +1,19 @@ +import fileinput +import sys + +args = sys.argv[1:] +while args: + arg = args[0] + if arg == 'cf': + out = args[1] + args = args[1:] + else: + break + args = args[1:] + +with open(out, 'wb') as ofp, fileinput.input(files=args, mode='rb') as ifp: + for line in ifp: + if not line.startswith(b'/*jar*/'): + ofp.write(line) + +sys.exit(0) diff --git a/test/Java/Java-fixture/myjavac.py b/test/Java/Java-fixture/myjavac.py new file mode 100644 index 0000000..1c7fdea --- /dev/null +++ b/test/Java/Java-fixture/myjavac.py @@ -0,0 +1,21 @@ +import sys + +args = sys.argv[1:] +while args: + arg = args[0] + if arg == '-d': + args = args[1:] + elif arg == '-sourcepath': + args = args[1:] + else: + break + args = args[1:] + +for file in args: + out = file.lower().replace('.java', '.class') + with open(file, 'rb') as infile, open(out, 'wb') as outfile: + for line in infile: + if not line.startswith(b'/*javac*/'): + outfile.write(line) + +sys.exit(0) diff --git a/test/Java/jar_not_in_PATH.py b/test/Java/jar_not_in_PATH.py index 26e92ce..b890ba1 100644 --- a/test/Java/jar_not_in_PATH.py +++ b/test/Java/jar_not_in_PATH.py @@ -35,33 +35,17 @@ _python_ = TestSCons._python_ test = TestSCons.TestSCons() -test.write('myjar.py', r""" -import sys -args = sys.argv[1:] -while args: - a = args[0] - if a == 'cf': - out = args[1] - args = args[1:] - else: - break - args = args[1:] -outfile = open(out, 'wb') -for file in args: - infile = open(file, 'rb') - for l in infile.readlines(): - if l[:7] != '/*jar*/': - outfile.write(l) -sys.exit(0) -""") +test.file_fixture(['Java-fixture', 'myjar.py']) -test.write('SConstruct', """ +test.write('SConstruct', """\ import os -oldpath = os.environ.get('PATH','') -env = Environment(ENV = {'PATH' : ['.']}) + +oldpath = os.environ.get('PATH', '') +DefaultEnvironment(tools=[]) +env = Environment(ENV={'PATH': ['.']}, tools=['javac', 'jar']) env['ENV']['PATH'] = oldpath env['JAR'] = r'%(_python_)s ./myjar.py' -env.Jar(target = 'test1.jar', source = 'test1.class') +env.Jar(target='test1.jar', source='test1.class') """ % locals()) test.write('test1.class', """\ @@ -70,7 +54,7 @@ test1.class line 3 """) -test.run(arguments = '.', stderr = None) +test.run(arguments='.', stderr=None) test.must_exist('test1.jar') diff --git a/test/Java/rmic_not_in_PATH.py b/test/Java/rmic_not_in_PATH.py index ac3f28e..68a2c30 100644 --- a/test/Java/rmic_not_in_PATH.py +++ b/test/Java/rmic_not_in_PATH.py @@ -63,11 +63,13 @@ sys.exit(0) test.write('SConstruct', """ import os -oldpath = os.environ.get('PATH','') -env = Environment(ENV = {'PATH' : ['.']}) + +oldpath = os.environ.get('PATH', '') +DefaultEnvironment(tools=[]) +env = Environment(ENV={'PATH': ['.']}, tools=['javac', 'rmic']) env['ENV']['PATH'] = oldpath env['RMIC'] = r'%(_python_)s myrmic.py' -env.RMIC(target = 'outdir', source = 'test1.java') +env.RMIC(target='outdir', source='test1.java') """ % locals()) test.write('test1.java', """\ diff --git a/test/LEX/LEX.py b/test/LEX/LEX.py index 79d8359..7dc8436 100644 --- a/test/LEX/LEX.py +++ b/test/LEX/LEX.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,10 +22,6 @@ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# - -__revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" - import TestSCons @@ -32,46 +30,29 @@ _exe = TestSCons._exe test = TestSCons.TestSCons() - - -test.write('mylex.py', """ -import getopt -import sys -if sys.platform == 'win32': - longopts = ['nounistd'] -else: - longopts = [] -cmd_opts, args = getopt.getopt(sys.argv[1:], 't', longopts) -for a in args: - with open(a, 'rb') as f: - contents = f.read() - sys.stdout.write(contents.replace(b'LEX', b'mylex.py').decode()) -sys.exit(0) -""") +test.file_fixture('mylex.py') test.write('SConstruct', """ -env = Environment(LEX = r'%(_python_)s mylex.py', tools=['default', 'lex']) -env.CFile(target = 'aaa', source = 'aaa.l') -env.CFile(target = 'bbb', source = 'bbb.lex') -env.CXXFile(target = 'ccc', source = 'ccc.ll') -env.CXXFile(target = 'ddd', source = 'ddd.lm') +env = Environment(LEX=r'%(_python_)s mylex.py', tools=['default', 'lex']) +env.CFile(target='aaa', source='aaa.l') +env.CFile(target='bbb', source='bbb.lex') +env.CXXFile(target='ccc', source='ccc.ll') +env.CXXFile(target='ddd', source='ddd.lm') """ % locals()) -test.write('aaa.l', "aaa.l\nLEX\n") -test.write('bbb.lex', "bbb.lex\nLEX\n") -test.write('ccc.ll', "ccc.ll\nLEX\n") -test.write('ddd.lm', "ddd.lm\nLEX\n") +test.write('aaa.l', "aaa.l\nLEX\n") +test.write('bbb.lex', "bbb.lex\nLEX\n") +test.write('ccc.ll', "ccc.ll\nLEX\n") +test.write('ddd.lm', "ddd.lm\nLEX\n") -test.run(arguments = '.', stderr = None) +test.run(arguments='.', stderr=None) # Read in with mode='r' because mylex.py implicitley wrote to stdout # with mode='w'. -test.must_match('aaa.c', "aaa.l\nmylex.py\n", mode='r') -test.must_match('bbb.c', "bbb.lex\nmylex.py\n", mode='r') -test.must_match('ccc.cc', "ccc.ll\nmylex.py\n", mode='r') -test.must_match('ddd.m', "ddd.lm\nmylex.py\n", mode='r') - - +test.must_match('aaa.c', "aaa.l\nmylex.py\n", mode='r') +test.must_match('bbb.c', "bbb.lex\nmylex.py\n", mode='r') +test.must_match('ccc.cc', "ccc.ll\nmylex.py\n", mode='r') +test.must_match('ddd.m', "ddd.lm\nmylex.py\n", mode='r') test.pass_test() diff --git a/test/LEX/LEXFLAGS.py b/test/LEX/LEXFLAGS.py index efcf9c4..f7d16c1 100644 --- a/test/LEX/LEXFLAGS.py +++ b/test/LEX/LEXFLAGS.py @@ -35,28 +35,7 @@ test = TestSCons.TestSCons() test.subdir('in') -test.write('mylex.py', """ -import getopt -import sys -import os -if sys.platform == 'win32': - longopts = ['nounistd'] -else: - longopts = [] -cmd_opts, args = getopt.getopt(sys.argv[1:], 'I:tx', longopts) -opt_string = '' -i_arguments = '' -for opt, arg in cmd_opts: - if opt == '-I': i_arguments = i_arguments + ' ' + arg - else: opt_string = opt_string + ' ' + opt -for a in args: - with open(a, 'r') as f: - contents = f.read() - contents = contents.replace('LEXFLAGS', opt_string) - contents = contents.replace('I_ARGS', i_arguments) - sys.stdout.write(contents) -sys.exit(0) -""") +test.file_fixture('mylex.py') test.write('SConstruct', """ env = Environment( @@ -76,9 +55,7 @@ if sys.platform == 'win32' and not sysconfig.get_platform() in ("mingw",): lexflags = ' --nounistd' + lexflags # Read in with mode='r' because mylex.py implicitley wrote to stdout # with mode='w'. -test.must_match(['out', 'aaa.c'], "aaa.l\n%s\n out in\n" % lexflags, mode='r') - - +test.must_match(['out', 'aaa.c'], "aaa.l\n%s\n out in\n" % lexflags, mode='r') test.pass_test() diff --git a/test/fixture/mycompile.py b/test/fixture/mycompile.py index 0f37d19..15a1c6f 100644 --- a/test/fixture/mycompile.py +++ b/test/fixture/mycompile.py @@ -1,19 +1,30 @@ -r""" -Phony "compiler" for testing SCons. +""" +Phony compiler for testing SCons. + +Copies its source files to the target file, dropping lines that match +a pattern, so we can recognize the tool has made a modification. +Intended for use as a *COM construction variable. + +Calling convention is: + argv[1] the function of the script (cc, c++, as, link etc.) + argv[2] the output file to write + argv[3:] one or more input files to "compile" -Copies its source files to the target file, dropping lines -that match a pattern, so we can recognize the tool -has made a modification. +Invocation often looks like: + Environment(CCCOM = r'%(_python_)s mycompile.py cc $TARGET $SOURCE', ... """ +import fileinput import sys +def fake_compile(): + skipline = f"/*{sys.argv[1]}*/\n".encode("utf-8") + with open(sys.argv[2], 'wb') as ofp, fileinput.input(files=sys.argv[3:], mode='rb') as ifp: + for line in ifp: + if line != skipline: + ofp.write(line) + + if __name__ == '__main__': - line = ('/*' + sys.argv[1] + '*/\n').encode() - with open(sys.argv[2], 'wb') as ofp: - for f in sys.argv[3:]: - with open(f, 'rb') as ifp: - lines = [ln for ln in ifp if ln != line] - for ln in lines: - ofp.write(ln) + fake_compile() sys.exit(0) diff --git a/test/fixture/mygcc.py b/test/fixture/mygcc.py index ceb10e5..91ca386 100644 --- a/test/fixture/mygcc.py +++ b/test/fixture/mygcc.py @@ -1,18 +1,35 @@ +""" +Phony compiler for testing SCons. + +Copies its source file to the target file, dropping lines that match +a pattern, so we can recognize the tool has made a modification. + +The first argument is the language (cc, c__, g77, etc.). + +Recognizes a -x option to append the language to 'mygcc.out' +for tracing purposes. + +Intended for use as $CC, $CXX, etc. +""" + import getopt import sys -compiler = sys.argv[1] -clen = len(compiler) + 1 -opts, args = getopt.getopt(sys.argv[2:], 'co:xf:K:') -for opt, arg in opts: - if opt == '-o': - out = arg - elif opt == '-x': - with open('mygcc.out', 'a') as f: - f.write(compiler + "\n") - -with open(out, 'w') as ofp, open(args[0], 'r') as ifp: - for line in ifp.readlines(): - if line[:clen] != '#' + compiler: - ofp.write(line) -sys.exit(0) +def fake_gcc(): + compiler = sys.argv[1].encode('utf-8') + opts, args = getopt.getopt(sys.argv[2:], 'co:xf:K:') + for opt, arg in opts: + if opt == '-o': + out = arg + elif opt == '-x': + with open('mygcc.out', 'ab') as logfile: + logfile.write(compiler + b"\n") + + with open(out, 'wb') as ofp, open(args[0], 'rb') as ifp: + for line in ifp: + if not line.startswith(b'#' + compiler): + ofp.write(line) + +if __name__ == '__main__': + fake_gcc() + sys.exit(0) diff --git a/test/fixture/mylex.py b/test/fixture/mylex.py new file mode 100644 index 0000000..8f47049 --- /dev/null +++ b/test/fixture/mylex.py @@ -0,0 +1,36 @@ +""" +Phony lex for testing SCons. + +Writes the contents of input file to stdout, +after "substituting" $LEXFLAGS and $I_ARGS + +Intended for use as $LEX +""" + +import getopt +import sys + +def fake_lex(): + if sys.platform == 'win32': + longopts = ['nounistd'] + else: + longopts = [] + cmd_opts, args = getopt.getopt(sys.argv[1:], 'I:tx', longopts) + opt_string = '' + i_arguments = '' + for opt, arg in cmd_opts: + if opt == '-I': + i_arguments = f'{i_arguments} {arg}' + else: + opt_string = f'{opt_string} {opt}' + for arg in args: + with open(arg, 'rb') as ifp: + contents = ifp.read().decode(encoding='utf-8') + contents = contents.replace('LEXFLAGS', opt_string) + contents = contents.replace('LEX', 'mylex.py') + contents = contents.replace('I_ARGS', i_arguments) + sys.stdout.write(contents) + +if __name__ == '__main__': + fake_lex() + sys.exit(0) diff --git a/test/fixture/mylink.py b/test/fixture/mylink.py index 19969f0..f462655 100644 --- a/test/fixture/mylink.py +++ b/test/fixture/mylink.py @@ -1,6 +1,11 @@ """ -Dummy linker for use by tests" +Phony linker for testing SCons. + +Copies its source files to the target file, dropping lines that match +a pattern, so we can recognize the tool has made a modification. +Intended for use as the $LINK construction variable. """ +import fileinput import getopt import sys @@ -10,34 +15,32 @@ def fake_link(): if opt == '-o': out = arg - with open(out, 'w') as ofp: - for f in args: - with open(f, 'r') as ifp: - for line in ifp.readlines(): - if line[:5] != '#link': - ofp.write(line) - sys.exit(0) + with open(out, 'wb') as ofp, fileinput.input(files=args, mode='rb') as ifp: + for line in ifp: + if not line.startswith(b'#link'): + ofp.write(line) def fake_win32_link(): args = sys.argv[1:] while args: - a = args[0] - if a == '-o': + arg = args[0] + if arg == '-o': out = args[1] args = args[2:] continue - if not a[0] in '/-': + if arg[0] not in '/-': break args = args[1:] - if a[:5].lower() == '/out:': out = a[5:] + if arg.lower().startswith('/out:'): + out = arg[5:] with open(args[0], 'rb') as ifp, open(out, 'wb') as ofp: - for line in ifp.readlines(): + for line in ifp: if not line.startswith(b'#link'): ofp.write(line) - sys.exit(0) if __name__ == '__main__': if sys.platform == 'win32': fake_win32_link() else: fake_link() + sys.exit(0) diff --git a/test/fixture/mylink_win32.py b/test/fixture/mylink_win32.py deleted file mode 100644 index 477fc95..0000000 --- a/test/fixture/mylink_win32.py +++ /dev/null @@ -1,16 +0,0 @@ -import sys - -args = sys.argv[1:] -while args: - a = args[0] - if a[0] != '/': - break - args.pop(0) - if a[:5] == '/OUT:': - out = a[5:] - -with open(out, 'w') as ofp, open(args[0], 'r') as ifp: - for line in ifp.readlines(): - if line[:5] != '#link': - ofp.write(line) -sys.exit(0) diff --git a/test/fixture/myrewrite.py b/test/fixture/myrewrite.py index 6914611..eb83cac 100644 --- a/test/fixture/myrewrite.py +++ b/test/fixture/myrewrite.py @@ -2,16 +2,19 @@ r""" Phony tool to modify a file in place for testing SCons. Drops lines that match a pattern. Currently used to test -ranlib-related behavior without invoking ranlib. +ranlib and ar behavior without actually invoking those tools. """ import sys -if __name__ == '__main__': - line = ('/*' + sys.argv[1] + '*/\n').encode() +def rewrite(): + line = ('/*' + sys.argv[1] + '*/\n').encode('utf-8') with open(sys.argv[2], 'rb') as ifp: lines = [ln for ln in ifp if ln != line] with open(sys.argv[2], 'wb') as ofp: - for ln in lines: - ofp.write(ln) + ofp.writelines(lines) + + +if __name__ == '__main__': + rewrite() sys.exit(0) diff --git a/test/fixture/wrapper.py b/test/fixture/wrapper.py index 112186e..c266cfa 100644 --- a/test/fixture/wrapper.py +++ b/test/fixture/wrapper.py @@ -1,3 +1,10 @@ +""" +Command wrapper, for testing SCons. + +Writes the command name to file "wrapper.out", +then passes the command line on to subprocess. +No checking is done. +""" import os import sys import subprocess @@ -7,4 +14,4 @@ if __name__ == '__main__': if '--version' not in sys.argv and '-dumpversion' not in sys.argv: with open(path, 'wb') as f: f.write(b"wrapper.py\n") - subprocess.run(sys.argv[1:]) + subprocess.run(sys.argv[1:], check=False) diff --git a/test/fixture/wrapper_with_args.py b/test/fixture/wrapper_with_args.py index b8d6ae5..769aea4 100644 --- a/test/fixture/wrapper_with_args.py +++ b/test/fixture/wrapper_with_args.py @@ -1,3 +1,10 @@ +""" +Command wrapper taking arguments, for testing SCons. + +Writes the command name and argument list to file "wrapper.out", +then passes the command line on to subprocess. +No checking is done. +""" import os import sys import subprocess @@ -6,4 +13,4 @@ if __name__ == '__main__': path = os.path.join(os.path.dirname(os.path.relpath(__file__)), 'wrapper.out') with open(path, 'a') as f: f.write("wrapper_with_args.py %s\n" % " ".join(sys.argv[1:])) - subprocess.run(sys.argv[1:]) + subprocess.run(sys.argv[1:], check=False) |