diff options
author | Daniel <dmoody256@gmail.com> | 2020-05-08 17:44:27 (GMT) |
---|---|---|
committer | William Deegan <bill@baddogconsulting.com> | 2021-04-13 20:53:54 (GMT) |
commit | 6eb1818c7b9b85e4645cd87e9e78c70f35fed35d (patch) | |
tree | 0a040625d61c357a23872dee01e61efea6c10c04 | |
parent | ec8c313126709a4bca17f97ee53a3619ca23ef5d (diff) | |
download | SCons-6eb1818c7b9b85e4645cd87e9e78c70f35fed35d.zip SCons-6eb1818c7b9b85e4645cd87e9e78c70f35fed35d.tar.gz SCons-6eb1818c7b9b85e4645cd87e9e78c70f35fed35d.tar.bz2 |
update tests to work on windows, added some environment support for windows and msvc
-rw-r--r-- | src/engine/SCons/Tool/ninja.py | 47 | ||||
-rw-r--r-- | test/ninja/build_libraries.py | 41 | ||||
-rw-r--r-- | test/ninja/copy_function_command.py | 10 | ||||
-rw-r--r-- | test/ninja/generate_and_build.py | 9 | ||||
-rw-r--r-- | test/ninja/generate_source.py | 22 | ||||
-rw-r--r-- | test/ninja/iterative_speedup.py | 19 | ||||
-rw-r--r-- | test/ninja/multi_env.py | 18 | ||||
-rw-r--r-- | test/ninja/ninja-fixture/bar.c | 2 | ||||
-rw-r--r-- | test/ninja/ninja-fixture/foo.c | 2 | ||||
-rw-r--r-- | test/ninja/ninja-fixture/test1.c | 13 | ||||
-rw-r--r-- | test/ninja/ninja-fixture/test_impl.c | 15 | ||||
-rw-r--r-- | test/ninja/shell_command.py | 20 |
12 files changed, 142 insertions, 76 deletions
diff --git a/src/engine/SCons/Tool/ninja.py b/src/engine/SCons/Tool/ninja.py index bf399e2..10e27f3 100644 --- a/src/engine/SCons/Tool/ninja.py +++ b/src/engine/SCons/Tool/ninja.py @@ -77,8 +77,8 @@ def _mkdir_action_function(env, node): # to an invalid ninja file. "variables": { # On Windows mkdir "-p" is always on - "cmd": "{mkdir} $out".format( - mkdir="mkdir" if env["PLATFORM"] == "win32" else "mkdir -p", + "cmd": "{mkdir}".format( + mkdir="mkdir $out & exit 0" if env["PLATFORM"] == "win32" else "mkdir -p $out", ), }, } @@ -383,6 +383,7 @@ class NinjaState: def __init__(self, env, ninja_file, writer_class): self.env = env self.ninja_file = ninja_file + self.ninja_bin_path = '' self.writer_class = writer_class self.__generated = False self.translator = SConsToNinjaTranslator(env) @@ -752,7 +753,7 @@ class NinjaState: pool="console", implicit=[str(self.ninja_file)], variables={ - "cmd": "ninja -f {} -t compdb CC CXX > compile_commands.json".format( + "cmd": "{}/ninja -f {} -t compdb CC CXX > compile_commands.json".format(self.ninja_bin_path, str(self.ninja_file) ) }, @@ -1044,15 +1045,32 @@ def ninja_builder(env, target, source): generated_build_ninja = target[0].get_abspath() NINJA_STATE.generate() + + if env["PLATFORM"] == "win32": + # this is not great, it executes everytime + # and its doesn't consider specific node environments + # also a bit quirky to use, but usually MSVC is not + # setup system wide for command line use so this is needed + # on the standard MSVC setup, this is only needed if + # running ninja directly from a command line that hasn't + # had the environment setup (vcvarsall.bat) + # todo: hook this into a command so that it only regnerates + # the .bat if the env['ENV'] changes + with open('ninja_env.bat', 'w') as f: + for key in env['ENV']: + f.write('set {}={}\n'.format(key, env['ENV'][key])) + if not env.get("DISABLE_AUTO_NINJA"): print("Executing:", str(target[0])) def execute_ninja(): - proc = subprocess.Popen( ['ninja', '-f', generated_build_ninja], - stderr=subprocess.STDOUT, + env.AppendENVPath('PATH', NINJA_STATE.ninja_bin_path) + proc = subprocess.Popen(['ninja', '-f', generated_build_ninja], + stderr=sys.stderr, stdout=subprocess.PIPE, - universal_newlines=True + universal_newlines=True, + env=env['ENV'] ) for stdout_line in iter(proc.stdout.readline, ""): yield stdout_line @@ -1060,12 +1078,17 @@ def ninja_builder(env, target, source): return_code = proc.wait() if return_code: raise subprocess.CalledProcessError(return_code, 'ninja') - + erase_previous = False for output in execute_ninja(): output = output.strip() - sys.stdout.write('\x1b[2K') # erase previous line - sys.stdout.write(output + "\r") + if erase_previous: + sys.stdout.write('\x1b[2K') # erase previous line + sys.stdout.write("\r") + else: + sys.stdout.write(os.linesep) + sys.stdout.write(output) sys.stdout.flush() + erase_previous = output.startswith('[') # pylint: disable=too-few-public-methods class AlwaysExecAction(SCons.Action.FunctionAction): @@ -1311,7 +1334,7 @@ def generate(env): if env["PLATFORM"] == "win32": from SCons.Tool.mslink import compositeLinkAction - if env["LINKCOM"] == compositeLinkAction: + if env.get("LINKCOM", None) == compositeLinkAction: env[ "LINKCOM" ] = '${TEMPFILE("$LINK $LINKFLAGS /OUT:$TARGET.windows $_LIBDIRFLAGS $_LIBFLAGS $_PDB $SOURCES.windows", "$LINKCOMSTR")}' @@ -1459,10 +1482,10 @@ def generate(env): ninja_syntax = importlib.import_module(ninja_syntax_mod_name) else: ninja_syntax = importlib.import_module(".ninja_syntax", package='ninja') - + if NINJA_STATE is None: NINJA_STATE = NinjaState(env, ninja_file[0], ninja_syntax.Writer) - + NINJA_STATE.ninja_bin_path = os.path.abspath(os.path.join(ninja_syntax.__file__, os.pardir, 'data', 'bin')) # Here we will force every builder to use an emitter which makes the ninja # file depend on it's target. This forces the ninja file to the bottom of # the DAG which is required so that we walk every target, and therefore add diff --git a/test/ninja/build_libraries.py b/test/ninja/build_libraries.py index 7e0ec23..5e491cc 100644 --- a/test/ninja/build_libraries.py +++ b/test/ninja/build_libraries.py @@ -26,6 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import TestSCons +from TestCmd import IS_WINDOWS _python_ = TestSCons._python_ _exe = TestSCons._exe @@ -39,35 +40,38 @@ ninja = test.where_is('ninja', os.environ['PATH']) if not ninja: test.skip_test("Could not find ninja in environment") +lib_suffix = '.lib' if IS_WINDOWS else '.so' +staticlib_suffix = '.lib' if IS_WINDOWS else '.a' +lib_prefix = '' if IS_WINDOWS else 'lib' + +win32 = ", 'WIN32'" if IS_WINDOWS else '' + test.write('SConstruct', """ env = Environment() env.Tool('ninja') -shared_lib = env.SharedLibrary(target = 'test_impl', source = 'test_impl.c') -env.Program(target = 'test', source = 'test1.c', LIBS=[shared_lib], LIBPATH=['.'], RPATH='.') +shared_lib = env.SharedLibrary(target = 'test_impl', source = 'test_impl.c', CPPDEFINES=['LIBRARY_BUILD'%(win32)s]) +env.Program(target = 'test', source = 'test1.c', LIBS=['test_impl'], LIBPATH=['.'], RPATH='.') -static_lib = env.StaticLibrary(target = 'test_impl_static', source = 'test_impl.c') -static_obj = env.Object(target = 'test_static.o', source = 'test1.c') +static_obj = env.Object(target = 'test_impl_static', source = 'test_impl.c') +static_lib = env.StaticLibrary(target = 'test_impl_static', source = static_obj) +static_obj = env.Object(target = 'test_static', source = 'test1.c') env.Program(target = 'test_static', source = static_obj, LIBS=[static_lib], LIBPATH=['.']) -""") +""" % locals()) # generate simple build test.run(stdout=None) test.must_contain_all_lines(test.stdout(), ['Generating: build.ninja', 'Executing: build.ninja']) -test.run(program = test.workpath('test'), stdout="library_function" + os.linesep) -test.run(program = test.workpath('test_static'), stdout="library_function" + os.linesep) +test.run(program = test.workpath('test'), stdout="library_function") +test.run(program = test.workpath('test_static'), stdout="library_function") # clean build and ninja files test.run(arguments='-c', stdout=None) test.must_contain_all_lines(test.stdout(), [ - 'Removed test_impl.os', - 'Removed libtest_impl.so', - 'Removed test1.o', - 'Removed test', - 'Removed test_impl.o', - 'Removed libtest_impl_static.a', - 'Removed test_static.o', - 'Removed test_static', + ('Removed %stest_impl' % lib_prefix) + lib_suffix, + 'Removed test' + _exe, + ('Removed %stest_impl_static' % lib_prefix) + staticlib_suffix, + 'Removed test_static' + _exe, 'Removed build.ninja']) # only generate the ninja file @@ -78,9 +82,10 @@ test.must_not_contain_any_line(test.stdout(), ['Executing: build.ninja']) # run ninja independently -test.run(program = ninja, stdout=None) -test.run(program = test.workpath('test'), stdout="library_function" + os.linesep) -test.run(program = test.workpath('test_static'), stdout="library_function" + os.linesep) +program = ['ninja_env.bat', '&', ninja] if IS_WINDOWS else ninja +test.run(program = program, stdout=None) +test.run(program = test.workpath('test'), stdout="library_function") +test.run(program = test.workpath('test_static'), stdout="library_function") test.pass_test() diff --git a/test/ninja/copy_function_command.py b/test/ninja/copy_function_command.py index a1e72b7..06991d3 100644 --- a/test/ninja/copy_function_command.py +++ b/test/ninja/copy_function_command.py @@ -26,6 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import TestSCons +from TestCmd import IS_WINDOWS _python_ = TestSCons._python_ _exe = TestSCons._exe @@ -50,14 +51,14 @@ env.Program(target = 'foo', source = 'foo2.c') test.run(stdout=None) test.must_contain_all_lines(test.stdout(), ['Generating: build.ninja', 'Executing: build.ninja']) -test.run(program = test.workpath('foo'), stdout="foo.c" + os.linesep) +test.run(program = test.workpath('foo'), stdout="foo.c") # clean build and ninja files test.run(arguments='-c', stdout=None) test.must_contain_all_lines(test.stdout(), [ 'Removed foo2.o', 'Removed foo2.c', - 'Removed foo', + 'Removed foo' + _exe, 'Removed build.ninja']) # only generate the ninja file @@ -68,8 +69,9 @@ test.must_not_contain_any_line(test.stdout(), ['Executing: build.ninja']) # run ninja independently -test.run(program = ninja, stdout=None) -test.run(program = test.workpath('foo'), stdout="foo.c" + os.linesep) +program = ['ninja_env.bat', '&', ninja] if IS_WINDOWS else ninja +test.run(program = program, stdout=None) +test.run(program = test.workpath('foo'), stdout="foo.c") test.pass_test() diff --git a/test/ninja/generate_and_build.py b/test/ninja/generate_and_build.py index 82aab5e..904e46a 100644 --- a/test/ninja/generate_and_build.py +++ b/test/ninja/generate_and_build.py @@ -26,6 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import TestSCons +from TestCmd import IS_WINDOWS _python_ = TestSCons._python_ _exe = TestSCons._exe @@ -45,11 +46,12 @@ env.Tool('ninja') env.Program(target = 'foo', source = 'foo.c') """) + # generate simple build test.run(stdout=None) test.must_contain_all_lines(test.stdout(), ['Generating: build.ninja', 'Executing: build.ninja']) -test.run(program = test.workpath('foo'), stdout="foo.c" + os.linesep) +test.run(program = test.workpath('foo' + _exe), stdout="foo.c") # clean build and ninja files test.run(arguments='-c', stdout=None) @@ -66,8 +68,9 @@ test.must_not_contain_any_line(test.stdout(), ['Executing: build.ninja']) # run ninja independently -test.run(program = ninja, stdout=None) -test.run(program = test.workpath('foo'), stdout="foo.c" + os.linesep) +program = ['ninja_env.bat', '&', ninja] if IS_WINDOWS else ninja +test.run(program = program, stdout=None) +test.run(program = test.workpath('foo' + _exe), stdout="foo.c") test.pass_test() diff --git a/test/ninja/generate_source.py b/test/ninja/generate_source.py index d1bfe34..298d227 100644 --- a/test/ninja/generate_source.py +++ b/test/ninja/generate_source.py @@ -26,6 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import TestSCons +from TestCmd import IS_WINDOWS _python_ = TestSCons._python_ _exe = TestSCons._exe @@ -39,13 +40,15 @@ ninja = test.where_is('ninja', os.environ['PATH']) if not ninja: test.skip_test("Could not find ninja in environment") +shell = '' if IS_WINDOWS else './' + test.write('SConstruct', """ env = Environment() env.Tool('ninja') -env.Program(target = 'generate_source', source = 'generate_source.c') -env.Command('generated_source.c', ['generate_source'], './generate_source') +prog = env.Program(target = 'generate_source', source = 'generate_source.c') +env.Command('generated_source.c', prog, '%(shell)sgenerate_source%(_exe)s') env.Program(target = 'generated_source', source = 'generated_source.c') -""") +""" % locals()) test.write('generate_source.c', """ #include <stdio.h> @@ -60,7 +63,7 @@ int main(int argc, char *argv[]) { fprintf(fp, "int\\n"); fprintf(fp, "main(int argc, char *argv[])\\n"); fprintf(fp, "{\\n"); - fprintf(fp, " printf(\\"generated_source.c\\\\n\\");\\n"); + fprintf(fp, " printf(\\"generated_source.c\\");\\n"); fprintf(fp, " exit (0);\\n"); fprintf(fp, "}\\n"); fclose(fp); @@ -69,16 +72,16 @@ int main(int argc, char *argv[]) { # generate simple build test.run(stdout=None) -test.run(program = test.workpath('generated_source'), stdout="generated_source.c" + os.linesep) +test.run(program = test.workpath('generated_source' + _exe), stdout="generated_source.c") # clean build and ninja files test.run(arguments='-c', stdout=None) test.must_contain_all_lines(test.stdout(), [ 'Removed generate_source.o', - 'Removed generate_source', + 'Removed generate_source' + _exe, 'Removed generated_source.c', 'Removed generated_source.o', - 'Removed generated_source', + 'Removed generated_source' + _exe, 'Removed build.ninja']) # only generate the ninja file @@ -89,8 +92,9 @@ test.must_not_contain_any_line(test.stdout(), ['Executing: build.ninja']) # run ninja independently -test.run(program = ninja, stdout=None) -test.run(program = test.workpath('generated_source'), stdout="generated_source.c" + os.linesep) +program = ['ninja_env.bat', '&', ninja] if IS_WINDOWS else ninja +test.run(program = program, stdout=None) +test.run(program = test.workpath('generated_source' + _exe), stdout="generated_source.c") test.pass_test() diff --git a/test/ninja/iterative_speedup.py b/test/ninja/iterative_speedup.py index cf999d8..6675bf3 100644 --- a/test/ninja/iterative_speedup.py +++ b/test/ninja/iterative_speedup.py @@ -28,6 +28,7 @@ import os import time import random import TestSCons +from TestCmd import IS_WINDOWS _python_ = TestSCons._python_ _exe = TestSCons._exe @@ -49,7 +50,8 @@ test.write('source_0.c', """ int print_function0() { - printf("main print\\n"); + printf("main print"); + return 0; } """) @@ -92,7 +94,7 @@ def generate_source(parent_source, current_source): int print_function%(current_source)s() { - print_function%(parent_source)s(); + return print_function%(parent_source)s(); } """ % locals()) @@ -132,7 +134,7 @@ def mod_source_orig(test_num): int print_function%(test_num)s() { - print_function%(parent_source)s(); + return print_function%(parent_source)s(); } """ % locals()) @@ -148,6 +150,7 @@ int main() { print_function%(num_source)s(); + exit(0); } """ % locals()) @@ -171,17 +174,19 @@ for _ in range(10): tests_mods += [random.randrange(1, num_source, 1)] jobs = '-j' + str(get_num_cpus()) +ninja_program = [test.workpath('ninja_env.bat'), '&', ninja, jobs] if IS_WINDOWS else [ninja, jobs] + start = time.perf_counter() test.run(arguments='--disable-auto-ninja', stdout=None) -test.run(program = ninja, arguments=[jobs], stdout=None) +test.run(program = ninja_program, stdout=None) stop = time.perf_counter() ninja_times += [stop - start] -test.run(program = test.workpath('print_bin'), stdout="main print" + os.linesep) +test.run(program = test.workpath('print_bin'), stdout="main print") for test_mod in tests_mods: mod_source_return(test_mod) start = time.perf_counter() - test.run(program = ninja, arguments=[jobs], stdout=None) + test.run(program = ninja_program, stdout=None) stop = time.perf_counter() ninja_times += [stop - start] @@ -197,7 +202,7 @@ start = time.perf_counter() test.run(arguments = ["-f", "SConstruct_no_ninja", jobs], stdout=None) stop = time.perf_counter() scons_times += [stop - start] -test.run(program = test.workpath('print_bin'), stdout="main print" + os.linesep) +test.run(program = test.workpath('print_bin'), stdout="main print") for test_mod in tests_mods: mod_source_return(test_mod) diff --git a/test/ninja/multi_env.py b/test/ninja/multi_env.py index 5360fd2..087d392 100644 --- a/test/ninja/multi_env.py +++ b/test/ninja/multi_env.py @@ -26,6 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import TestSCons +from TestCmd import IS_WINDOWS _python_ = TestSCons._python_ _exe = TestSCons._exe @@ -53,16 +54,16 @@ env2.Program(target = 'bar', source = 'bar.c') test.run(stdout=None) test.must_contain_all_lines(test.stdout(), ['Generating: build.ninja', 'Executing: build.ninja']) -test.run(program = test.workpath('foo'), stdout="foo.c" + os.linesep) -test.run(program = test.workpath('bar'), stdout="bar.c" + os.linesep) +test.run(program = test.workpath('foo' + _exe), stdout="foo.c") +test.run(program = test.workpath('bar' + _exe), stdout="bar.c") # clean build and ninja files test.run(arguments='-c', stdout=None) test.must_contain_all_lines(test.stdout(), [ 'Removed foo.o', - 'Removed foo', + 'Removed foo' + _exe, 'Removed bar.o', - 'Removed bar', + 'Removed bar' + _exe, 'Removed build.ninja']) # only generate the ninja file @@ -73,11 +74,10 @@ test.must_not_contain_any_line(test.stdout(), ['Executing: build.ninja']) # run ninja independently -test.run(program = ninja, stdout=None) -test.run(program = test.workpath('foo'), stdout="foo.c" + os.linesep) -test.run(program = test.workpath('bar'), stdout="bar.c" + os.linesep) - - +program = ['ninja_env.bat', '&', ninja] if IS_WINDOWS else ninja +test.run(program = program, stdout=None) +test.run(program = test.workpath('foo' + _exe), stdout="foo.c") +test.run(program = test.workpath('bar' + _exe), stdout="bar.c") test.pass_test() diff --git a/test/ninja/ninja-fixture/bar.c b/test/ninja/ninja-fixture/bar.c index 3767857..15b2ecc 100644 --- a/test/ninja/ninja-fixture/bar.c +++ b/test/ninja/ninja-fixture/bar.c @@ -5,6 +5,6 @@ int main(int argc, char *argv[]) { argv[argc++] = "--"; - printf("bar.c\n"); + printf("bar.c"); exit (0); } diff --git a/test/ninja/ninja-fixture/foo.c b/test/ninja/ninja-fixture/foo.c index de1e6e5..ba35c68 100644 --- a/test/ninja/ninja-fixture/foo.c +++ b/test/ninja/ninja-fixture/foo.c @@ -5,6 +5,6 @@ int main(int argc, char *argv[]) { argv[argc++] = "--"; - printf("foo.c\n"); + printf("foo.c"); exit (0); } diff --git a/test/ninja/ninja-fixture/test1.c b/test/ninja/ninja-fixture/test1.c index c53f54a..678461f 100644 --- a/test/ninja/ninja-fixture/test1.c +++ b/test/ninja/ninja-fixture/test1.c @@ -1,10 +1,21 @@ #include <stdio.h> #include <stdlib.h> -extern int library_function(void); +#ifdef WIN32 +#ifdef LIBRARY_BUILD +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT __declspec(dllimport) +#endif +#else +#define DLLEXPORT +#endif + +DLLEXPORT extern int library_function(void); int main(int argc, char *argv[]) { library_function(); + exit(0); } diff --git a/test/ninja/ninja-fixture/test_impl.c b/test/ninja/ninja-fixture/test_impl.c index ae5effc..89c26ed 100644 --- a/test/ninja/ninja-fixture/test_impl.c +++ b/test/ninja/ninja-fixture/test_impl.c @@ -1,8 +1,19 @@ #include <stdio.h> #include <stdlib.h> -int +#ifdef WIN32 +#ifdef LIBRARY_BUILD +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT __declspec(dllimport) +#endif +#else +#define DLLEXPORT +#endif + + +DLLEXPORT int library_function(void) { - printf("library_function\n"); + printf("library_function"); } diff --git a/test/ninja/shell_command.py b/test/ninja/shell_command.py index b5c8323..5d49164 100644 --- a/test/ninja/shell_command.py +++ b/test/ninja/shell_command.py @@ -26,6 +26,7 @@ __revision__ = "__FILE__ __REVISION__ __DATE__ __DEVELOPER__" import os import TestSCons +from TestCmd import IS_WINDOWS _python_ = TestSCons._python_ _exe = TestSCons._exe @@ -39,24 +40,26 @@ ninja = test.where_is('ninja', os.environ['PATH']) if not ninja: test.skip_test("Could not find ninja in environment") +shell = '' if IS_WINDOWS else './' + test.write('SConstruct', """ env = Environment() env.Tool('ninja') -env.Program(target = 'foo', source = 'foo.c') -env.Command('foo.out', ['foo'], './foo > foo.out') -""") +prog = env.Program(target = 'foo', source = 'foo.c') +env.Command('foo.out', prog, '%(shell)sfoo%(_exe)s > foo.out') +""" % locals()) # generate simple build test.run(stdout=None) test.must_contain_all_lines(test.stdout(), ['Generating: build.ninja', 'Executing: build.ninja']) -test.must_match('foo.out', 'foo.c' + os.linesep) +test.must_match('foo.out', 'foo.c') # clean build and ninja files test.run(arguments='-c', stdout=None) test.must_contain_all_lines(test.stdout(), [ 'Removed foo.o', - 'Removed foo', + 'Removed foo%(_exe)s' % locals(), 'Removed foo.out', 'Removed build.ninja']) @@ -68,10 +71,9 @@ test.must_not_contain_any_line(test.stdout(), ['Executing: build.ninja']) # run ninja independently -test.run(program = ninja, stdout=None) -test.must_match('foo.out', 'foo.c' + os.linesep) - - +program = ['ninja_env.bat', '&', ninja] if IS_WINDOWS else ninja +test.run(program = program, stdout=None) +test.must_match('foo.out', 'foo.c') test.pass_test() |