interpreter: store correct files for project regeneration

Right now sub-sub projects are not correctly registered, because we
don't have a way to pass up past the first level of subproject. This
patch changes that by making the build_Def_files as defined in the
Interpreter initializer accurate for translated dependencies, ie, cmake
dependencies won't define a dependency on a non-existent meson.build.
This means that it can always add the subi.build_def_files because they
are always accurate.
pull/7914/merge
Dylan Baker 4 years ago committed by Jussi Pakkanen
parent d4eec9664b
commit 47d071a34f
  1. 22
      mesonbuild/interpreter.py
  2. 14
      run_unittests.py
  3. 3
      test cases/unit/85 nested subproject regenerate depends/main.c
  4. 6
      test cases/unit/85 nested subproject regenerate depends/meson.build
  5. 4
      test cases/unit/85 nested subproject regenerate depends/subprojects/sub1/meson.build
  6. 1
      test cases/unit/85 nested subproject regenerate depends/subprojects/sub2/CMakeLists.txt

@ -2383,6 +2383,7 @@ class Interpreter(InterpreterBase):
default_project_options: T.Optional[T.Dict[str, str]] = None, default_project_options: T.Optional[T.Dict[str, str]] = None,
mock: bool = False, mock: bool = False,
ast: T.Optional[mparser.CodeBlockNode] = None, ast: T.Optional[mparser.CodeBlockNode] = None,
is_translated: bool = False,
) -> None: ) -> None:
super().__init__(build.environment.get_source_dir(), subdir, subproject) super().__init__(build.environment.get_source_dir(), subdir, subproject)
self.an_unpicklable_object = mesonlib.an_unpicklable_object self.an_unpicklable_object = mesonlib.an_unpicklable_object
@ -2421,8 +2422,16 @@ class Interpreter(InterpreterBase):
self.default_project_options = {} self.default_project_options = {}
self.project_default_options = {} self.project_default_options = {}
self.build_func_dict() self.build_func_dict()
# build_def_files needs to be defined before parse_project is called # build_def_files needs to be defined before parse_project is called
self.build_def_files = [os.path.join(self.subdir, environment.build_filename)] #
# For non-meson subprojects, we'll be using the ast. Even if it does
# exist we don't want to add a dependency on it, it's autogenerated
# from the actual build files, and is just for reference.
self.build_def_files = []
build_filename = os.path.join(self.subdir, environment.build_filename)
if not is_translated:
self.build_def_files.append(build_filename)
if not mock: if not mock:
self.parse_project() self.parse_project()
self._redetect_machines() self._redetect_machines()
@ -2941,11 +2950,14 @@ external dependencies (including libraries) must go to "dependencies".''')
return self.disabled_subproject(subp_name, exception=e) return self.disabled_subproject(subp_name, exception=e)
raise e raise e
def _do_subproject_meson(self, subp_name, subdir, default_options, kwargs, ast=None, build_def_files=None): def _do_subproject_meson(self, subp_name: str, subdir: str, default_options, kwargs,
ast: T.Optional[mparser.CodeBlockNode] = None,
build_def_files: T.Optional[T.List[str]] = None,
is_translated: bool = False) -> SubprojectHolder:
with mlog.nested(): with mlog.nested():
new_build = self.build.copy() new_build = self.build.copy()
subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir, subi = Interpreter(new_build, self.backend, subp_name, subdir, self.subproject_dir,
self.modules, default_options, ast=ast) self.modules, default_options, ast=ast, is_translated=is_translated)
subi.subprojects = self.subprojects subi.subprojects = self.subprojects
subi.subproject_stack = self.subproject_stack + [subp_name] subi.subproject_stack = self.subproject_stack + [subp_name]
@ -2971,7 +2983,7 @@ external dependencies (including libraries) must go to "dependencies".''')
# Duplicates are possible when subproject uses files from project root # Duplicates are possible when subproject uses files from project root
if build_def_files: if build_def_files:
self.build_def_files = list(set(self.build_def_files + build_def_files)) self.build_def_files = list(set(self.build_def_files + build_def_files))
else: # We always need the subi.build_def_files, to propgate sub-sub-projects
self.build_def_files = list(set(self.build_def_files + subi.build_def_files)) self.build_def_files = list(set(self.build_def_files + subi.build_def_files))
self.build.merge(subi.build) self.build.merge(subi.build)
self.build.subprojects[subp_name] = subi.project_version self.build.subprojects[subp_name] = subi.project_version
@ -3016,7 +3028,7 @@ external dependencies (including libraries) must go to "dependencies".''')
mlog.cmd_ci_include(meson_filename) mlog.cmd_ci_include(meson_filename)
mlog.log() mlog.log()
result = self._do_subproject_meson(subp_name, subdir, default_options, kwargs, ast, cm_int.bs_files) result = self._do_subproject_meson(subp_name, subdir, default_options, kwargs, ast, cm_int.bs_files, is_translated=True)
result.cm_interpreter = cm_int result.cm_interpreter = cm_int
mlog.log() mlog.log()

@ -5247,6 +5247,20 @@ recommended as it is not supported on some platforms''')
wrap = PackageDefinition(redirect_wrap) wrap = PackageDefinition(redirect_wrap)
self.assertEqual(wrap.get('url'), 'http://invalid') self.assertEqual(wrap.get('url'), 'http://invalid')
@skip_if_no_cmake
def test_nested_cmake_rebuild(self) -> None:
# This checks a bug where if a non-meson project is used as a third
# level (or deeper) subproject it doesn't cause a rebuild if the build
# files for that project are changed
testdir = os.path.join(self.unit_test_dir, '85 nested subproject regenerate depends')
cmakefile = Path(testdir) / 'subprojects' / 'sub2' / 'CMakeLists.txt'
self.init(testdir)
self.build()
with cmakefile.open('a') as f:
os.utime(str(cmakefile))
self.assertReconfiguredBuildIsNoop()
class FailureTests(BasePlatformTests): class FailureTests(BasePlatformTests):
''' '''
Tests that test failure conditions. Build files here should be dynamically Tests that test failure conditions. Build files here should be dynamically

@ -0,0 +1,6 @@
project('nested subproject regenerate depends', 'c')
s = subproject('sub1')
# This is needed to make msbuild noop check work correctly
executable('exe', 'main.c')

@ -0,0 +1,4 @@
project('sub1')
cmake = import('cmake')
cmake.subproject('sub2')
Loading…
Cancel
Save