From c02d7fe119b8f936d10741e73abbc40a4a450ce5 Mon Sep 17 00:00:00 2001 From: Dylan Baker Date: Wed, 24 Aug 2022 13:11:00 -0700 Subject: [PATCH] backend/ninja: properly track objects extracted from fortran sources We need this to ensure that .mod files are created before we start compiling, and to ensure that the proper include directory arguments are generated. --- mesonbuild/backend/backends.py | 23 ++++++++++++-------- mesonbuild/backend/ninjabackend.py | 33 +++++++++++++++++++++++------ mesonbuild/backend/vs2010backend.py | 2 +- 3 files changed, 41 insertions(+), 17 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 42f625539..6723b9737 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -305,7 +305,7 @@ class Backend: elif isinstance(t, build.CustomTargetIndex): filename = t.get_outputs()[0] else: - assert isinstance(t, build.BuildTarget) + assert isinstance(t, build.BuildTarget), t filename = t.get_filename() return os.path.join(self.get_target_dir(t), filename) @@ -452,18 +452,20 @@ class Backend: return os.path.relpath(os.path.join('dummyprefixdir', todir), os.path.join('dummyprefixdir', fromdir)) - def flatten_object_list(self, target: build.BuildTarget, proj_dir_to_build_root: str = '') -> T.List[str]: - obj_list = self._flatten_object_list(target, target.get_objects(), proj_dir_to_build_root) - return list(dict.fromkeys(obj_list)) + def flatten_object_list(self, target: build.BuildTarget, proj_dir_to_build_root: str = '' + ) -> T.Tuple[T.List[str], T.List[build.BuildTargetTypes]]: + obj_list, deps = self._flatten_object_list(target, target.get_objects(), proj_dir_to_build_root) + return list(dict.fromkeys(obj_list)), deps def determine_ext_objs(self, objects: build.ExtractedObjects, proj_dir_to_build_root: str = '') -> T.List[str]: - obj_list = self._flatten_object_list(objects.target, [objects], proj_dir_to_build_root) + obj_list, _ = self._flatten_object_list(objects.target, [objects], proj_dir_to_build_root) return list(dict.fromkeys(obj_list)) def _flatten_object_list(self, target: build.BuildTarget, objects: T.Sequence[T.Union[str, 'File', build.ExtractedObjects]], - proj_dir_to_build_root: str) -> T.List[str]: + proj_dir_to_build_root: str) -> T.Tuple[T.List[str], T.List[build.BuildTargetTypes]]: obj_list: T.List[str] = [] + deps: T.List[build.BuildTargetTypes] = [] for obj in objects: if isinstance(obj, str): o = os.path.join(proj_dir_to_build_root, @@ -480,11 +482,14 @@ class Backend: obj_list.append(obj.rel_to_builddir(o)) elif isinstance(obj, build.ExtractedObjects): if obj.recursive: - obj_list += self._flatten_object_list(obj.target, obj.objlist, proj_dir_to_build_root) - obj_list += self._determine_ext_objs(obj, proj_dir_to_build_root) + objs, d = self._flatten_object_list(obj.target, obj.objlist, proj_dir_to_build_root) + obj_list.extend(objs) + deps.extend(d) + obj_list.extend(self._determine_ext_objs(obj, proj_dir_to_build_root)) + deps.append(obj.target) else: raise MesonException('Unknown data type in object list.') - return obj_list + return obj_list, deps @staticmethod def is_swift_target(target: build.BuildTarget) -> bool: diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 1a90c480b..a1ba7b92e 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -859,6 +859,16 @@ class NinjaBackend(backends.Backend): else: pch_objects = [] + o, od = self.flatten_object_list(target) + obj_targets = [t for t in od if t.uses_fortran()] + obj_list.extend(o) + + fortran_order_deps = [self.get_target_filename(t) for t in obj_targets] + fortran_inc_args: T.List[str] = [] + if target.uses_fortran(): + fortran_inc_args = mesonlib.listify([target.compilers['fortran'].get_include_args( + self.get_target_private_dir(t), is_system=False) for t in obj_targets]) + # Generate compilation targets for C sources generated from Vala # sources. This can be extended to other $LANG->C compilers later if # necessary. This needs to be separate for at least Vala @@ -898,15 +908,17 @@ class NinjaBackend(backends.Backend): src.rel_to_builddir(self.build_to_src)) unity_src.append(abs_src) else: - o, s = self.generate_single_compile(target, src, False, [], header_deps + d_generated_deps) + o, s = self.generate_single_compile(target, src, False, [], + header_deps + d_generated_deps + fortran_order_deps, + fortran_inc_args) obj_list.append(o) compiled_sources.append(s) source2object[s] = o - obj_list += self.flatten_object_list(target) if is_unity: for src in self.generate_unity_files(target, unity_src): - o, s = self.generate_single_compile(target, src, True, unity_deps + header_deps + d_generated_deps) + o, s = self.generate_single_compile(target, src, True, unity_deps + header_deps + d_generated_deps, + fortran_order_deps, fortran_inc_args) obj_list.append(o) compiled_sources.append(s) source2object[s] = o @@ -916,7 +928,7 @@ class NinjaBackend(backends.Backend): else: final_obj_list = obj_list elem = self.generate_link(target, outname, final_obj_list, linker, pch_objects, stdlib_args=stdlib_args) - self.generate_dependency_scan_target(target, compiled_sources, source2object, generated_source_files) + self.generate_dependency_scan_target(target, compiled_sources, source2object, generated_source_files, fortran_order_deps) self.add_build(elem) def should_use_dyndeps_for_target(self, target: 'build.BuildTarget') -> bool: @@ -941,7 +953,8 @@ class NinjaBackend(backends.Backend): return False return True - def generate_dependency_scan_target(self, target, compiled_sources, source2object, generated_source_files: T.List[mesonlib.File]): + def generate_dependency_scan_target(self, target, compiled_sources, source2object, generated_source_files: T.List[mesonlib.File], + object_deps: T.List[str]) -> None: if not self.should_use_dyndeps_for_target(target): return depscan_file = self.get_dep_scan_file_for(target) @@ -963,6 +976,7 @@ class NinjaBackend(backends.Backend): # that those sources are present for g in generated_source_files: elem.orderdeps.add(g.relative_name()) + elem.orderdeps.update(object_deps) scaninfo = TargetDependencyScannerInfo(self.get_target_private_dir(target), source2object) with open(pickle_abs, 'wb') as p: pickle.dump(scaninfo, p) @@ -2605,7 +2619,10 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) commands += compiler.get_include_args(self.get_target_private_dir(target), False) return commands - def generate_single_compile(self, target, src, is_generated=False, header_deps=None, order_deps=None): + def generate_single_compile(self, target: build.BuildTarget, src, + is_generated=False, header_deps=None, + order_deps: T.Optional[T.List[str]] = None, + extra_args: T.Optional[T.List[str]] = None) -> None: """ Compiles C/C++, ObjC/ObjC++, Fortran, and D sources """ @@ -2692,6 +2709,8 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) rel_obj) self.add_build(depelem) commands += compiler.get_module_outdir_args(self.get_target_private_dir(target)) + if extra_args is not None: + commands.extend(extra_args) element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) self.add_header_deps(target, element, header_deps) @@ -2910,7 +2929,7 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=47485''')) for dep in target.link_whole_targets: l = dep.extract_all_objects(False) objects_from_static_libs += self.determine_ext_objs(l, '') - objects_from_static_libs.extend(self.flatten_object_list(dep)) + objects_from_static_libs.extend(self.flatten_object_list(dep)[0]) return objects_from_static_libs else: diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 571140432..030ef75c0 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -1279,7 +1279,7 @@ class Vs2010Backend(backends.Backend): for lib in self.get_custom_target_provided_libraries(target): additional_links.append(self.relpath(lib, self.get_target_dir(target))) additional_objects = [] - for o in self.flatten_object_list(target, down): + for o in self.flatten_object_list(target, down)[0]: assert isinstance(o, str) additional_objects.append(o) for o in custom_objs: