Skip to content

Commit d8ea5c4

Browse files
bruchar1xclaesse
authored andcommitted
fix generate_gir with BothLibraries dependency
Co-authored-by: Xavier Claessens <xclaesse@gmail.com>
1 parent 2fd0dac commit d8ea5c4

File tree

9 files changed

+111
-33
lines changed

9 files changed

+111
-33
lines changed

mesonbuild/build.py

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -774,6 +774,7 @@ def __init__(
774774
}
775775
self.pic = False
776776
self.pie = False
777+
self.both_lib: T.Optional[T.Union[StaticLibrary, SharedLibrary]] = None
777778
# Track build_rpath entries so we can remove them at install time
778779
self.rpath_dirs_to_remove: T.Set[bytes] = set()
779780
self.process_sourcelist(sources)
@@ -1740,16 +1741,20 @@ def process_vs_module_defs_kw(self, kwargs: T.Dict[str, T.Any]) -> None:
17401741
def extract_targets_as_list(self, kwargs: T.Dict[str, T.Union[LibTypes, T.Sequence[LibTypes]]], key: T.Literal['link_with', 'link_whole']) -> T.List[LibTypes]:
17411742
bl_type = self.environment.coredata.get_option(OptionKey('default_both_libraries'))
17421743
if bl_type == 'auto':
1743-
bl_type = 'static' if isinstance(self, StaticLibrary) else 'shared'
1744-
1745-
def _resolve_both_libs(lib: LibTypes) -> LibTypes:
1746-
if isinstance(lib, BothLibraries):
1747-
return lib.get(bl_type)
1748-
return lib
1744+
if isinstance(self, StaticLibrary):
1745+
bl_type = 'static'
1746+
elif isinstance(self, SharedLibrary):
1747+
bl_type = 'shared'
17491748

17501749
self_libs: T.List[LibTypes] = self.link_targets if key == 'link_with' else self.link_whole_targets
1751-
lib_list = listify(kwargs.get(key, [])) + self_libs
1752-
return [_resolve_both_libs(t) for t in lib_list]
1750+
1751+
lib_list = []
1752+
for lib in listify(kwargs.get(key, [])) + self_libs:
1753+
if isinstance(lib, (Target, BothLibraries)):
1754+
lib_list.append(lib.get(bl_type))
1755+
else:
1756+
lib_list.append(lib)
1757+
return lib_list
17531758

17541759
def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes:
17551760
"""Base case used by BothLibraries"""
@@ -2204,6 +2209,14 @@ def is_linkable_target(self):
22042209
def is_internal(self) -> bool:
22052210
return not self.install
22062211

2212+
def set_shared(self, shared_library: SharedLibrary) -> None:
2213+
self.both_lib = shared_library
2214+
2215+
def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes:
2216+
if lib_type == 'shared':
2217+
return self.both_lib or self
2218+
return self
2219+
22072220
class SharedLibrary(BuildTarget):
22082221
known_kwargs = known_shlib_kwargs
22092222

@@ -2470,6 +2483,14 @@ def type_suffix(self):
24702483
def is_linkable_target(self):
24712484
return True
24722485

2486+
def set_static(self, static_library: StaticLibrary) -> None:
2487+
self.both_lib = static_library
2488+
2489+
def get(self, lib_type: T.Literal['static', 'shared']) -> LibTypes:
2490+
if lib_type == 'static':
2491+
return self.both_lib or self
2492+
return self
2493+
24732494
# A shared library that is meant to be used with dlopen rather than linking
24742495
# into something else.
24752496
class SharedModule(SharedLibrary):
@@ -2506,7 +2527,7 @@ def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, No
25062527
return self.environment.get_shared_module_dir(), '{moduledir_shared}'
25072528

25082529
class BothLibraries(SecondLevelHolder):
2509-
def __init__(self, shared: SharedLibrary, static: StaticLibrary, preferred_library: Literal['shared', 'static', 'auto']) -> None:
2530+
def __init__(self, shared: SharedLibrary, static: StaticLibrary, preferred_library: Literal['shared', 'static']) -> None:
25102531
self._preferred_library = preferred_library
25112532
self.shared = shared
25122533
self.static = static
@@ -2914,23 +2935,14 @@ class AliasTarget(RunTarget):
29142935

29152936
typename = 'alias'
29162937

2917-
def __init__(self, name: str, dependencies: T.Sequence[T.Union[Target, BothLibraries]],
2938+
def __init__(self, name: str, dependencies: T.Sequence[Target],
29182939
subdir: str, subproject: str, environment: environment.Environment):
2919-
super().__init__(name, [], list(self._deps_generator(dependencies)), subdir, subproject, environment)
2940+
super().__init__(name, [], dependencies, subdir, subproject, environment)
29202941

29212942
def __repr__(self):
29222943
repr_str = "<{0} {1}>"
29232944
return repr_str.format(self.__class__.__name__, self.get_id())
29242945

2925-
@staticmethod
2926-
def _deps_generator(dependencies: T.Sequence[T.Union[Target, BothLibraries]]) -> T.Iterator[Target]:
2927-
for dep in dependencies:
2928-
if isinstance(dep, BothLibraries):
2929-
yield dep.shared
2930-
yield dep.static
2931-
else:
2932-
yield dep
2933-
29342946
class Jar(BuildTarget):
29352947
known_kwargs = known_jar_kwargs
29362948

mesonbuild/interpreter/interpreter.py

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
from ..interpreterbase import Disabler, disablerIfNotFound
3232
from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs
3333
from ..interpreterbase import ObjectHolder, ContextManagerObject
34-
from ..interpreterbase import stringifyUserArguments, resolve_second_level_holders
34+
from ..interpreterbase import stringifyUserArguments
3535
from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule
3636
from ..optinterpreter import optname_regex
3737

@@ -681,7 +681,6 @@ def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwa
681681
KwargInfo('version', (str, NoneType)),
682682
KwargInfo('objects', ContainerTypeInfo(list, build.ExtractedObjects), listify=True, default=[], since='1.1.0'),
683683
)
684-
@noSecondLevelHolderResolving
685684
def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var],
686685
kwargs: kwtypes.FuncDeclareDependency) -> dependencies.Dependency:
687686
deps = kwargs['dependencies']
@@ -1906,15 +1905,12 @@ def func_jar(self, node: mparser.BaseNode,
19061905
@permittedKwargs(known_build_target_kwargs)
19071906
@typed_pos_args('build_target', str, varargs=SOURCES_VARARGS)
19081907
@typed_kwargs('build_target', *BUILD_TARGET_KWS, allow_unknown=True)
1909-
@noSecondLevelHolderResolving
19101908
def func_build_target(self, node: mparser.BaseNode,
19111909
args: T.Tuple[str, SourcesVarargsType],
19121910
kwargs: kwtypes.BuildTarget
19131911
) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary,
19141912
build.SharedModule, build.BothLibraries, build.Jar]:
19151913
target_type = kwargs['target_type']
1916-
if target_type not in {'both_libraries', 'library'}:
1917-
args, kwargs = resolve_second_level_holders(args, kwargs)
19181914

19191915
if target_type == 'executable':
19201916
return self.build_target(node, args, kwargs, build.Executable)
@@ -2176,13 +2172,19 @@ def func_run_target(self, node: mparser.FunctionNode, args: T.Tuple[str],
21762172
@FeatureNew('alias_target', '0.52.0')
21772173
@typed_pos_args('alias_target', str, varargs=(build.Target, build.BothLibraries), min_varargs=1)
21782174
@noKwargs
2179-
@noSecondLevelHolderResolving
21802175
def func_alias_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[build.Target, build.BothLibraries]]],
21812176
kwargs: TYPE_kwargs) -> build.AliasTarget:
21822177
name, deps = args
21832178
if any(isinstance(d, build.RunTarget) for d in deps):
21842179
FeatureNew.single_use('alias_target that depends on run_targets', '0.60.0', self.subproject)
2185-
tg = build.AliasTarget(name, deps, self.subdir, self.subproject, self.environment)
2180+
real_deps: T.List[build.Target] = []
2181+
for d in deps:
2182+
if isinstance(d, build.BothLibraries):
2183+
real_deps.append(d.shared)
2184+
real_deps.append(d.static)
2185+
else:
2186+
real_deps.append(d)
2187+
tg = build.AliasTarget(name, real_deps, self.subdir, self.subproject, self.environment)
21862188
self.add_target(name, tg)
21872189
return tg
21882190

@@ -3286,16 +3288,18 @@ def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, Source
32863288
# Keep only compilers used for linking
32873289
static_lib.compilers = {k: v for k, v in static_lib.compilers.items() if k in compilers.clink_langs}
32883290

3291+
# Cross reference them to implement as_shared() and as_static() methods.
3292+
shared_lib.set_static(static_lib)
3293+
static_lib.set_shared(shared_lib)
3294+
32893295
return build.BothLibraries(shared_lib, static_lib, preferred_library)
32903296

32913297
def build_library(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library):
32923298
default_library = self.coredata.get_option(OptionKey('default_library', subproject=self.subproject))
32933299
assert isinstance(default_library, str), 'for mypy'
32943300
if default_library == 'shared':
3295-
args, kwargs = resolve_second_level_holders(args, kwargs)
32963301
return self.build_target(node, args, T.cast('kwtypes.StaticLibrary', kwargs), build.SharedLibrary)
32973302
elif default_library == 'static':
3298-
args, kwargs = resolve_second_level_holders(args, kwargs)
32993303
return self.build_target(node, args, T.cast('kwtypes.SharedLibrary', kwargs), build.StaticLibrary)
33003304
elif default_library == 'both':
33013305
return self.build_both_libraries(node, args, kwargs)

mesonbuild/interpreter/interpreterobjects.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1001,8 +1001,6 @@ class SharedLibraryHolder(BuildTargetHolder[build.SharedLibrary]):
10011001

10021002
class BothLibrariesHolder(BuildTargetHolder[build.BothLibraries]):
10031003
def __init__(self, libs: build.BothLibraries, interp: 'Interpreter'):
1004-
# FIXME: This build target always represents the shared library, but
1005-
# that should be configurable.
10061004
super().__init__(libs, interp)
10071005
self.methods.update({'get_shared_lib': self.get_shared_lib_method,
10081006
'get_static_lib': self.get_static_lib_method,
@@ -1017,12 +1015,16 @@ def __repr__(self) -> str:
10171015
@noPosargs
10181016
@noKwargs
10191017
def get_shared_lib_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.SharedLibrary:
1020-
return self.held_object.shared
1018+
lib = copy.copy(self.held_object.shared)
1019+
lib.both_lib = None
1020+
return lib
10211021

10221022
@noPosargs
10231023
@noKwargs
10241024
def get_static_lib_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.StaticLibrary:
1025-
return self.held_object.static
1025+
lib = copy.copy(self.held_object.static)
1026+
lib.both_lib = None
1027+
return lib
10261028

10271029
class SharedModuleHolder(BuildTargetHolder[build.SharedModule]):
10281030
pass
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#include "bar.h"
2+
#include "foo.h"
3+
4+
int bar_func(void)
5+
{
6+
return foo_func() + 42;
7+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int bar_func(void);
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include "foo.h"
2+
3+
int foo_func(void)
4+
{
5+
return 42;
6+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
int foo_func(void);
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
project('gir both libraries', 'c')
2+
3+
gir = dependency('gobject-introspection-1.0', required: false)
4+
if not gir.found()
5+
error('MESON_SKIP_TEST gobject-introspection not found.')
6+
endif
7+
8+
if host_machine.system() == 'cygwin'
9+
# FIXME: g-ir-scanner seems broken on cygwin:
10+
# ERROR: can't resolve libraries to shared libraries: foo++
11+
error('MESON_SKIP_TEST g-ir-scanner is broken on cygwin.')
12+
endif
13+
14+
gnome = import('gnome')
15+
16+
# Regression test simulating how GStreamer generate its GIRs.
17+
# Generated gobject-introspection binaries for every GStreamer libraries must
18+
# first call gst_init() defined in the main libgstreamer, which means they need
19+
# to link on that lib.
20+
# A regression caused by https://github.com/mesonbuild/meson/pull/12632 made
21+
# Meson not link the binary generated for bar with libfoo in the case it uses
22+
# both_libraries().
23+
24+
libfoo = both_libraries('foo', 'foo.c')
25+
foo_gir = gnome.generate_gir(libfoo,
26+
namespace: 'foo',
27+
nsversion: '1.0',
28+
sources: ['foo.c', 'foo.h'],
29+
)
30+
foo_dep = declare_dependency(
31+
link_with: libfoo,
32+
sources: foo_gir,
33+
)
34+
35+
libbar = both_libraries('bar', 'bar.c', dependencies: foo_dep)
36+
gnome.generate_gir(libbar,
37+
namespace: 'bar',
38+
nsversion: '1.0',
39+
sources: ['bar.c', 'bar.h'],
40+
extra_args: '--add-init-section=extern void foo_func(void);foo_func();',
41+
dependencies: foo_dep,
42+
)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"expect_skip_on_jobname": ["azure", "macos", "msys2", "cygwin"]
3+
}

0 commit comments

Comments
 (0)