aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek@centricular.com>2017-04-06 01:40:00 +0530
committerNirbheek Chauhan <nirbheek@centricular.com>2017-04-10 22:32:41 +0530
commitb603aba3ec58355bb3f6924908411c902b6f88d8 (patch)
treed8fe0e7867e26208d027021aca118927f98e7b4b
parent7d5e4012fe7d5984d1039d8647a7cb80fe484e9e (diff)
downloadmeson-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.py6
-rwxr-xr-xrun_unittests.py90
-rw-r--r--test cases/common/22 header in file list/prog.c2
-rw-r--r--test cases/common/64 custom header generator/meson.build2
-rw-r--r--test cases/common/64 custom header generator/somefile.txt0
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