diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2017-04-06 01:40:00 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2017-04-10 22:32:41 +0530 |
commit | b603aba3ec58355bb3f6924908411c902b6f88d8 (patch) | |
tree | d8fe0e7867e26208d027021aca118927f98e7b4b | |
parent | 7d5e4012fe7d5984d1039d8647a7cb80fe484e9e (diff) | |
download | meson-b603aba3ec58355bb3f6924908411c902b6f88d8.zip meson-b603aba3ec58355bb3f6924908411c902b6f88d8.tar.gz meson-b603aba3ec58355bb3f6924908411c902b6f88d8.tar.bz2 |
Add tests for target and custom_target rebuild
Test that changing src tree headers rebuilds targets, and test that
changing any file used in a custom_target will rebuild it.
-rw-r--r-- | mesonbuild/build.py | 6 | ||||
-rwxr-xr-x | run_unittests.py | 90 | ||||
-rw-r--r-- | test cases/common/22 header in file list/prog.c | 2 | ||||
-rw-r--r-- | test cases/common/64 custom header generator/meson.build | 2 | ||||
-rw-r--r-- | test cases/common/64 custom header generator/somefile.txt | 0 |
5 files changed, 93 insertions, 7 deletions
diff --git a/mesonbuild/build.py b/mesonbuild/build.py index df3f37b..6493684 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -1318,12 +1318,16 @@ class CustomTarget(Target): for c in cmd: if hasattr(c, 'held_object'): c = c.held_object - if isinstance(c, (str, File)): + if isinstance(c, str): + final_cmd.append(c) + elif isinstance(c, File): + self.depend_files.append(c) final_cmd.append(c) elif isinstance(c, dependencies.ExternalProgram): if not c.found(): m = 'Tried to use not-found external program {!r} in "command"' raise InvalidArguments(m.format(c.name)) + self.depend_files.append(File.from_absolute_file(c.get_path())) final_cmd += c.get_command() elif isinstance(c, (BuildTarget, CustomTarget)): self.dependencies.append(c) diff --git a/run_unittests.py b/run_unittests.py index 4599b2b..6cb9340 100755 --- a/run_unittests.py +++ b/run_unittests.py @@ -346,7 +346,21 @@ class BasePlatformTests(unittest.TestCase): self.vala_test_dir = os.path.join(src_root, 'test cases/vala') self.framework_test_dir = os.path.join(src_root, 'test cases/frameworks') self.unit_test_dir = os.path.join(src_root, 'test cases/unit') + # Misc stuff self.orig_env = os.environ.copy() + if self.backend is Backend.ninja: + self.no_rebuild_stdout = 'ninja: no work to do.' + else: + # VS doesn't have a stable output when no changes are done + # XCode backend is untested with unit tests, help welcome! + self.no_rebuild_stdout = 'UNKNOWN BACKEND {!r}'.format(self.backend.name) + + def ensure_backend_detects_changes(self): + # This is needed to increase the difference between build.ninja's + # timestamp and the timestamp of whatever you changed due to a Ninja + # bug: https://github.com/ninja-build/ninja/issues/371 + if self.backend is Backend.ninja: + time.sleep(1) def _print_meson_log(self): log = os.path.join(self.logdir, 'meson-log.txt') @@ -395,7 +409,7 @@ class BasePlatformTests(unittest.TestCase): # Add arguments for building the target (if specified), # and using the build dir (if required, with VS) args = get_builddir_target_args(self.backend, self.builddir, target) - self._run(self.build_command + args + extra_args, workdir=self.builddir) + return self._run(self.build_command + args + extra_args, workdir=self.builddir) def clean(self): dir_args = get_builddir_target_args(self.backend, self.builddir, None) @@ -421,16 +435,17 @@ class BasePlatformTests(unittest.TestCase): return self.build(target=target) def setconf(self, arg, will_build=True): - # This is needed to increase the difference between build.ninja's - # timestamp and coredata.dat's timestamp due to a Ninja bug. - # https://github.com/ninja-build/ninja/issues/371 if will_build: - time.sleep(1) + self.ensure_backend_detects_changes() self._run(self.mconf_command + [arg, self.builddir]) def wipe(self): shutil.rmtree(self.builddir) + def utime(self, f): + self.ensure_backend_detects_changes() + os.utime(f) + def get_compdb(self): if self.backend is not Backend.ninja: raise unittest.SkipTest('Compiler db not available with {} backend'.format(self.backend.name)) @@ -484,6 +499,40 @@ class BasePlatformTests(unittest.TestCase): path_basename = PurePath(path).parts[-1] self.assertEqual(PurePath(path_basename), PurePath(basename), msg) + def assertBuildIsNoop(self): + ret = self.build() + if self.backend is Backend.ninja: + self.assertEqual(ret.split('\n')[-2], self.no_rebuild_stdout) + elif self.backend is Backend.vs: + # Ensure that some target said that no rebuild was done + self.assertIn('CustomBuild:\n All outputs are up-to-date.', ret) + self.assertIn('ClCompile:\n All outputs are up-to-date.', ret) + self.assertIn('Link:\n All outputs are up-to-date.', ret) + # Ensure that no targets were built + clre = re.compile('ClCompile:\n [^\n]*cl', flags=re.IGNORECASE) + linkre = re.compile('Link:\n [^\n]*link', flags=re.IGNORECASE) + self.assertNotRegex(ret, clre) + self.assertNotRegex(ret, linkre) + elif self.backend is Backend.xcode: + raise unittest.SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError('Invalid backend: {!r}'.format(self.backend.name)) + + def assertRebuiltTarget(self, target): + ret = self.build() + if self.backend is Backend.ninja: + self.assertIn('Linking target {}'.format(target), ret) + elif self.backend is Backend.vs: + # Ensure that this target was rebuilt + clre = re.compile('ClCompile:\n [^\n]*cl[^\n]*' + target, flags=re.IGNORECASE) + linkre = re.compile('Link:\n [^\n]*link[^\n]*' + target, flags=re.IGNORECASE) + self.assertRegex(ret, clre) + self.assertRegex(ret, linkre) + elif self.backend is Backend.xcode: + raise unittest.SkipTest('Please help us fix this test on the xcode backend') + else: + raise RuntimeError('Invalid backend: {!r}'.format(self.backend.name)) + class AllPlatformTests(BasePlatformTests): ''' @@ -977,6 +1026,37 @@ class AllPlatformTests(BasePlatformTests): meson_exe_dat2 = glob(os.path.join(self.privatedir, 'meson_exe*.dat')) self.assertListEqual(meson_exe_dat1, meson_exe_dat2) + def test_source_changes_cause_rebuild(self): + ''' + Test that changes to sources and headers cause rebuilds, but not + changes to unused files (as determined by the dependency file) in the + input files list. + ''' + testdir = os.path.join(self.common_test_dir, '22 header in file list') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of header.h should rebuild everything + self.utime(os.path.join(testdir, 'header.h')) + self.assertRebuiltTarget('prog') + + def test_custom_target_changes_cause_rebuild(self): + ''' + Test that in a custom target, changes to the input files, the + ExternalProgram, and any File objects on the command-line cause + a rebuild. + ''' + testdir = os.path.join(self.common_test_dir, '64 custom header generator') + self.init(testdir) + self.build() + # Immediately rebuilding should not do anything + self.assertBuildIsNoop() + # Changing mtime of these should rebuild everything + for f in ('input.def', 'makeheader.py', 'somefile.txt'): + self.utime(os.path.join(testdir, f)) + self.assertRebuiltTarget('prog') + class WindowsTests(BasePlatformTests): ''' diff --git a/test cases/common/22 header in file list/prog.c b/test cases/common/22 header in file list/prog.c index 0314ff1..fbedab8 100644 --- a/test cases/common/22 header in file list/prog.c +++ b/test cases/common/22 header in file list/prog.c @@ -1 +1,3 @@ +#include "header.h" + int main(int argc, char **argv) { return 0; } diff --git a/test cases/common/64 custom header generator/meson.build b/test cases/common/64 custom header generator/meson.build index b422401..bcc9a53 100644 --- a/test cases/common/64 custom header generator/meson.build +++ b/test cases/common/64 custom header generator/meson.build @@ -5,7 +5,7 @@ gen = find_program('makeheader.py') generated_h = custom_target('makeheader.py', output : 'myheader.lh', # Suffix not .h to ensure this works with custom suffixes, too. input : 'input.def', -command : [gen, '@INPUT0@', '@OUTPUT0@']) +command : [gen, '@INPUT0@', '@OUTPUT0@', files('somefile.txt')]) prog = executable('prog', 'prog.c', generated_h) test('gentest', prog) diff --git a/test cases/common/64 custom header generator/somefile.txt b/test cases/common/64 custom header generator/somefile.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/test cases/common/64 custom header generator/somefile.txt |