From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Eli Schwartz Date: Mon, 28 Mar 2022 23:33:28 -0400 Subject: [PATCH] gtk-doc fixes Squashes 4 commits: - fix regression in propagating depends in gtkdoc In commit 68e684d51f1e469e0d9f4b499ffda15146cad98a the function signature was changed, but several places did not adapt. Additionally, we now totally dropped the in-place update of gtkdoc's sole source of dependencies, but didn't propagate them upward to assign the newly collected dependencies anywhere. Fixes building gtkdoc with internal dependencies and failing when specified directly (when building the 'all' target with sufficiently random parallelism, deps may be built on time). Fixes: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1008382 https://gitlab.gnome.org/GNOME/libmediaart/-/issues/4 - gnome: Fix typo in _get_dependencies_flags This was introduced in https://github.com/mesonbuild/meson/commit/823da3990947a8f4a2152826f0d7229f8a7a0159 - gnome: Fix gtkdoc when using multiple Apple frameworks The `-framework Foundation -framework CoreFoundation` ended up de-duplicated by OrderedSet into `-framework Foundation CoreFoundation`. - fix continued breakage in gnome module API In commit 823da3990947a8f4a2152826f0d7229f8a7a0159 we tried to fix disappearing dependencies. Instead, we appended the replacement dependencies to the existing ones. But this, too, was wrong. The function doesn't return new dependencies... it returns a copied list of all the dependencies, then alone of all parts of that API, expects to overwrite the existing variable. (Sadly, part of the internals actually uses the entire list for something.) As a result, we produced a repeatedly growing list, which eventually scaled really badly and e.g. OOMed on gstreamer. Instead, let's just replace the dependencies with the updated copy. --- mesonbuild/modules/gnome.py | 89 ++++++++++++-------- test cases/frameworks/10 gtk-doc/meson.build | 6 ++ test cases/frameworks/10 gtk-doc/test.json | 2 +- 3 files changed, 63 insertions(+), 34 deletions(-) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index 673a781a41de..8bf870aa52a6 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -635,52 +635,50 @@ class GnomeModule(ExtensionModule): link_command.append('-l' + lib.name) return link_command, new_depends - def _get_dependencies_flags( + def _get_dependencies_flags_raw( self, deps: T.Sequence[T.Union['Dependency', build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]], state: 'ModuleState', depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]], - include_rpath: bool = False, - use_gir_args: bool = False, - separate_nodedup: bool = False - ) -> T.Tuple[OrderedSet[str], OrderedSet[str], OrderedSet[str], T.Optional[T.List[str]], OrderedSet[str], + include_rpath: bool, + use_gir_args: bool, + ) -> T.Tuple[OrderedSet[str], OrderedSet[T.Union[str, T.Tuple[str, str]]], OrderedSet[T.Union[str, T.Tuple[str, str]]], OrderedSet[str], T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]]]: cflags: OrderedSet[str] = OrderedSet() - internal_ldflags: OrderedSet[str] = OrderedSet() - external_ldflags: OrderedSet[str] = OrderedSet() # External linker flags that can't be de-duped reliably because they - # require two args in order, such as -framework AVFoundation - external_ldflags_nodedup: T.List[str] = [] + # require two args in order, such as -framework AVFoundation will be stored as a tuple. + internal_ldflags: OrderedSet[T.Union[str, T.Tuple[str, str]]] = OrderedSet() + external_ldflags: OrderedSet[T.Union[str, T.Tuple[str, str]]] = OrderedSet() gi_includes: OrderedSet[str] = OrderedSet() deps = mesonlib.listify(deps) depends = list(depends) for dep in deps: if isinstance(dep, Dependency): girdir = dep.get_variable(pkgconfig='girdir', internal='girdir', default_value='') if girdir: assert isinstance(girdir, str), 'for mypy' gi_includes.update([girdir]) if isinstance(dep, InternalDependency): cflags.update(dep.get_compile_args()) cflags.update(state.get_include_args(dep.include_directories)) for lib in dep.libraries: if isinstance(lib, build.SharedLibrary): _ld, depends = self._get_link_args(state, lib, depends, include_rpath) internal_ldflags.update(_ld) - libdepflags = self._get_dependencies_flags(lib.get_external_deps(), state, depends, include_rpath, - use_gir_args, True) + libdepflags = self._get_dependencies_flags_raw(lib.get_external_deps(), state, depends, include_rpath, + use_gir_args) cflags.update(libdepflags[0]) internal_ldflags.update(libdepflags[1]) external_ldflags.update(libdepflags[2]) - external_ldflags_nodedup += libdepflags[3] - gi_includes.update(libdepflags[4]) - extdepflags = self._get_dependencies_flags(dep.ext_deps, state, depends, include_rpath, - use_gir_args, True) + gi_includes.update(libdepflags[3]) + depends = libdepflags[4] + extdepflags = self._get_dependencies_flags_raw(dep.ext_deps, state, depends, include_rpath, + use_gir_args) cflags.update(extdepflags[0]) internal_ldflags.update(extdepflags[1]) external_ldflags.update(extdepflags[2]) - external_ldflags_nodedup += extdepflags[3] - gi_includes.update(extdepflags[4]) + gi_includes.update(extdepflags[3]) + depends = extdepflags[4] for source in dep.sources: if isinstance(source, GirTarget): gi_includes.update([os.path.join(state.environment.get_build_dir(), @@ -708,32 +706,54 @@ class GnomeModule(ExtensionModule): # If it's a framework arg, slurp the framework name too # to preserve the order of arguments if flag == '-framework': - external_ldflags_nodedup += [flag, next(ldflags)] + external_ldflags.update([(flag, next(ldflags))]) else: external_ldflags.update([flag]) elif isinstance(dep, (build.StaticLibrary, build.SharedLibrary)): cflags.update(state.get_include_args(dep.get_include_dirs())) depends.append(dep) else: mlog.log(f'dependency {dep!r} not handled to build gir files') continue if use_gir_args and self._gir_has_option('--extra-library'): - def fix_ldflags(ldflags: T.Iterable[str]) -> OrderedSet[str]: - fixed_ldflags: OrderedSet[str] = OrderedSet() + def fix_ldflags(ldflags: T.Iterable[T.Union[str, T.Tuple[str, str]]]) -> OrderedSet[T.Union[str, T.Tuple[str, str]]]: + fixed_ldflags: OrderedSet[T.Union[str, T.Tuple[str, str]]] = OrderedSet() for ldflag in ldflags: - if ldflag.startswith("-l"): + if isinstance(ldflag, str) and ldflag.startswith("-l"): ldflag = ldflag.replace('-l', '--extra-library=', 1) fixed_ldflags.add(ldflag) return fixed_ldflags internal_ldflags = fix_ldflags(internal_ldflags) external_ldflags = fix_ldflags(external_ldflags) - if not separate_nodedup: - external_ldflags.update(external_ldflags_nodedup) - return cflags, internal_ldflags, external_ldflags, None, gi_includes, depends - else: - return cflags, internal_ldflags, external_ldflags, external_ldflags_nodedup, gi_includes, depends + return cflags, internal_ldflags, external_ldflags, gi_includes, depends + def _get_dependencies_flags( + self, deps: T.Sequence[T.Union['Dependency', build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]], + state: 'ModuleState', + depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]], + include_rpath: bool = False, + use_gir_args: bool = False, + ) -> T.Tuple[OrderedSet[str], T.List[str], T.List[str], OrderedSet[str], + T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]]]: + + cflags, internal_ldflags_raw, external_ldflags_raw, gi_includes, depends = self._get_dependencies_flags_raw(deps, state, depends, include_rpath, use_gir_args) + internal_ldflags: T.List[str] = [] + external_ldflags: T.List[str] = [] + + # Extract non-deduplicable argument groups out of the tuples. + for ldflag in internal_ldflags_raw: + if isinstance(ldflag, str): + internal_ldflags.append(ldflag) + else: + internal_ldflags.extend(ldflag) + for ldflag in external_ldflags_raw: + if isinstance(ldflag, str): + external_ldflags.append(ldflag) + else: + external_ldflags.extend(ldflag) + + return cflags, internal_ldflags, external_ldflags, gi_includes, depends def _unwrap_gir_target(self, girtarget: T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary], state: 'ModuleState' ) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary]: if not isinstance(girtarget, (build.Executable, build.SharedLibrary, @@ -1105,7 +1125,7 @@ class GnomeModule(ExtensionModule): # ldflags will be misinterpreted by gir scanner (showing # spurious dependencies) but building GStreamer fails if they # are not used here. - dep_cflags, dep_internal_ldflags, dep_external_ldflags, _, gi_includes, depends = \ + dep_cflags, dep_internal_ldflags, dep_external_ldflags, gi_includes, depends = \ self._get_dependencies_flags(deps, state, depends, use_gir_args=True) scan_cflags = [] scan_cflags += list(self._get_scanner_cflags(cflags)) @@ -1456,63 +1476,66 @@ class GnomeModule(ExtensionModule): t_args.append(f'--expand-content-files={"@@".join(abs_filenames(kwargs["expand_content_files"]))}') t_args.append(f'--ignore-headers={"@@".join(kwargs["ignore_headers"])}') t_args.append(f'--installdir={"@@".join(kwargs["install_dir"])}') - t_args += self._get_build_args(kwargs['c_args'], kwargs['include_directories'], - kwargs['dependencies'], state, depends) + build_args, new_depends = self._get_build_args(kwargs['c_args'], kwargs['include_directories'], + kwargs['dependencies'], state, depends) + t_args.extend(build_args) + new_depends.extend(depends) custom_target = build.CustomTarget( targetname, state.subdir, state.subproject, command + t_args, [], [f'{modulename}-decl.txt'], build_always_stale=True, - extra_depends=depends, + extra_depends=new_depends, ) alias_target = build.AliasTarget(targetname, [custom_target], state.subdir, state.subproject) if kwargs['check']: check_cmd = state.find_program('gtkdoc-check') check_env = ['DOC_MODULE=' + modulename, 'DOC_MAIN_SGML_FILE=' + main_file] check_args = (targetname + '-check', check_cmd) check_workdir = os.path.join(state.environment.get_build_dir(), state.subdir) state.test(check_args, env=check_env, workdir=check_workdir, depends=[custom_target]) res: T.List[T.Union[build.Target, build.ExecutableSerialisation]] = [custom_target, alias_target] if kwargs['install']: res.append(state.backend.get_executable_serialisation(command + t_args, tag='doc')) return ModuleReturnValue(custom_target, res) def _get_build_args(self, c_args: T.List[str], inc_dirs: T.List[T.Union[str, build.IncludeDirs]], deps: T.List[T.Union[Dependency, build.SharedLibrary, build.StaticLibrary]], state: 'ModuleState', - depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes']]) -> T.List[str]: + depends: T.Sequence[T.Union[build.BuildTarget, 'build.GeneratedTypes']]) -> T.Tuple[ + T.List[str], T.List[T.Union[build.BuildTarget, 'build.GeneratedTypes', 'FileOrString', build.StructuredSources]]]: args: T.List[str] = [] cflags = c_args.copy() - deps_cflags, internal_ldflags, external_ldflags, *_ = \ + deps_cflags, internal_ldflags, external_ldflags, _gi_includes, new_depends = \ self._get_dependencies_flags(deps, state, depends, include_rpath=True) cflags.extend(deps_cflags) cflags.extend(state.get_include_args(inc_dirs)) ldflags: T.List[str] = [] ldflags.extend(internal_ldflags) ldflags.extend(external_ldflags) cflags.extend(state.environment.coredata.get_external_args(MachineChoice.HOST, 'c')) ldflags.extend(state.environment.coredata.get_external_link_args(MachineChoice.HOST, 'c')) compiler = state.environment.coredata.compilers[MachineChoice.HOST]['c'] compiler_flags = self._get_langs_compilers_flags(state, [('c', compiler)]) cflags.extend(compiler_flags[0]) ldflags.extend(compiler_flags[1]) ldflags.extend(compiler_flags[2]) if compiler: args += ['--cc=%s' % join_args(compiler.get_exelist())] args += ['--ld=%s' % join_args(compiler.get_linker_exelist())] if cflags: args += ['--cflags=%s' % join_args(cflags)] if ldflags: args += ['--ldflags=%s' % join_args(ldflags)] - return args + return args, new_depends @noKwargs @typed_pos_args('gnome.gtkdoc_html_dir', str) diff --git a/test cases/frameworks/10 gtk-doc/meson.build b/test cases/frameworks/10 gtk-doc/meson.build index 339e93f9de16..b49efc0ebc84 100644 --- a/test cases/frameworks/10 gtk-doc/meson.build +++ b/test cases/frameworks/10 gtk-doc/meson.build @@ -31,9 +31,15 @@ libfoo = shared_library('foo', 'foo.c', dependencies: gobject, ) +deps = [] +if host_machine.system() == 'darwin' + deps += dependency('appleframeworks', modules : ['Foundation', 'CoreFoundation']) +endif + foo_dep = declare_dependency( link_with: libfoo, include_directories: inc, + dependencies: deps, ) subdir('doc') diff --git a/test cases/frameworks/10 gtk-doc/test.json b/test cases/frameworks/10 gtk-doc/test.json index f2805d365364..1085b55eeddf 100644 --- a/test cases/frameworks/10 gtk-doc/test.json +++ b/test cases/frameworks/10 gtk-doc/test.json @@ -60,5 +60,5 @@ {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/up.png"}, {"type": "file", "file": "usr/share/gtk-doc/html/foobar3/up-insensitive.png"} ], - "skip_on_jobname": ["azure", "macos", "msys2"] + "skip_on_jobname": ["azure", "msys2"] }