Skip to content

Commit 688e69c

Browse files
bruchar1xclaesse
authored andcommitted
fix generate_gir with BothLibraries dependency
Co-authored-by: Xavier Claessens <[email protected]> (cherry picked from commit d8ea5c4)
1 parent 8f1c7e6 commit 688e69c

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
@@ -770,6 +770,7 @@ def __init__(
770770
}
771771
self.pic = False
772772
self.pie = False
773+
self.both_lib: T.Optional[T.Union[StaticLibrary, SharedLibrary]] = None
773774
# Track build_rpath entries so we can remove them at install time
774775
self.rpath_dirs_to_remove: T.Set[bytes] = set()
775776
self.process_sourcelist(sources)
@@ -1736,16 +1737,20 @@ def process_vs_module_defs_kw(self, kwargs: T.Dict[str, T.Any]) -> None:
17361737
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]:
17371738
bl_type = self.environment.coredata.get_option(OptionKey('default_both_libraries'))
17381739
if bl_type == 'auto':
1739-
bl_type = 'static' if isinstance(self, StaticLibrary) else 'shared'
1740-
1741-
def _resolve_both_libs(lib: LibTypes) -> LibTypes:
1742-
if isinstance(lib, BothLibraries):
1743-
return lib.get(bl_type)
1744-
return lib
1740+
if isinstance(self, StaticLibrary):
1741+
bl_type = 'static'
1742+
elif isinstance(self, SharedLibrary):
1743+
bl_type = 'shared'
17451744

17461745
self_libs: T.List[LibTypes] = self.link_targets if key == 'link_with' else self.link_whole_targets
1747-
lib_list = listify(kwargs.get(key, [])) + self_libs
1748-
return [_resolve_both_libs(t) for t in lib_list]
1746+
1747+
lib_list = []
1748+
for lib in listify(kwargs.get(key, [])) + self_libs:
1749+
if isinstance(lib, (Target, BothLibraries)):
1750+
lib_list.append(lib.get(bl_type))
1751+
else:
1752+
lib_list.append(lib)
1753+
return lib_list
17491754

17501755
def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes:
17511756
"""Base case used by BothLibraries"""
@@ -2200,6 +2205,14 @@ def is_linkable_target(self):
22002205
def is_internal(self) -> bool:
22012206
return not self.install
22022207

2208+
def set_shared(self, shared_library: SharedLibrary) -> None:
2209+
self.both_lib = shared_library
2210+
2211+
def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes:
2212+
if lib_type == 'shared':
2213+
return self.both_lib or self
2214+
return self
2215+
22032216
class SharedLibrary(BuildTarget):
22042217
known_kwargs = known_shlib_kwargs
22052218

@@ -2466,6 +2479,14 @@ def type_suffix(self):
24662479
def is_linkable_target(self):
24672480
return True
24682481

2482+
def set_static(self, static_library: StaticLibrary) -> None:
2483+
self.both_lib = static_library
2484+
2485+
def get(self, lib_type: T.Literal['static', 'shared']) -> LibTypes:
2486+
if lib_type == 'static':
2487+
return self.both_lib or self
2488+
return self
2489+
24692490
# A shared library that is meant to be used with dlopen rather than linking
24702491
# into something else.
24712492
class SharedModule(SharedLibrary):
@@ -2502,7 +2523,7 @@ def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, No
25022523
return self.environment.get_shared_module_dir(), '{moduledir_shared}'
25032524

25042525
class BothLibraries(SecondLevelHolder):
2505-
def __init__(self, shared: SharedLibrary, static: StaticLibrary, preferred_library: Literal['shared', 'static', 'auto']) -> None:
2526+
def __init__(self, shared: SharedLibrary, static: StaticLibrary, preferred_library: Literal['shared', 'static']) -> None:
25062527
self._preferred_library = preferred_library
25072528
self.shared = shared
25082529
self.static = static
@@ -2910,23 +2931,14 @@ class AliasTarget(RunTarget):
29102931

29112932
typename = 'alias'
29122933

2913-
def __init__(self, name: str, dependencies: T.Sequence[T.Union[Target, BothLibraries]],
2934+
def __init__(self, name: str, dependencies: T.Sequence[Target],
29142935
subdir: str, subproject: str, environment: environment.Environment):
2915-
super().__init__(name, [], list(self._deps_generator(dependencies)), subdir, subproject, environment)
2936+
super().__init__(name, [], dependencies, subdir, subproject, environment)
29162937

29172938
def __repr__(self):
29182939
repr_str = "<{0} {1}>"
29192940
return repr_str.format(self.__class__.__name__, self.get_id())
29202941

2921-
@staticmethod
2922-
def _deps_generator(dependencies: T.Sequence[T.Union[Target, BothLibraries]]) -> T.Iterator[Target]:
2923-
for dep in dependencies:
2924-
if isinstance(dep, BothLibraries):
2925-
yield dep.shared
2926-
yield dep.static
2927-
else:
2928-
yield dep
2929-
29302942
class Jar(BuildTarget):
29312943
known_kwargs = known_jar_kwargs
29322944

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

@@ -690,7 +690,6 @@ def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwa
690690
KwargInfo('version', (str, NoneType)),
691691
KwargInfo('objects', ContainerTypeInfo(list, build.ExtractedObjects), listify=True, default=[], since='1.1.0'),
692692
)
693-
@noSecondLevelHolderResolving
694693
def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var],
695694
kwargs: kwtypes.FuncDeclareDependency) -> dependencies.Dependency:
696695
deps = kwargs['dependencies']
@@ -1917,15 +1916,12 @@ def func_jar(self, node: mparser.BaseNode,
19171916
@permittedKwargs(known_build_target_kwargs)
19181917
@typed_pos_args('build_target', str, varargs=SOURCES_VARARGS)
19191918
@typed_kwargs('build_target', *BUILD_TARGET_KWS, allow_unknown=True)
1920-
@noSecondLevelHolderResolving
19211919
def func_build_target(self, node: mparser.BaseNode,
19221920
args: T.Tuple[str, SourcesVarargsType],
19231921
kwargs: kwtypes.BuildTarget
19241922
) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary,
19251923
build.SharedModule, build.BothLibraries, build.Jar]:
19261924
target_type = kwargs['target_type']
1927-
if target_type not in {'both_libraries', 'library'}:
1928-
args, kwargs = resolve_second_level_holders(args, kwargs)
19291925

19301926
if target_type == 'executable':
19311927
return self.build_target(node, args, kwargs, build.Executable)
@@ -2172,13 +2168,19 @@ def func_run_target(self, node: mparser.FunctionNode, args: T.Tuple[str],
21722168
@FeatureNew('alias_target', '0.52.0')
21732169
@typed_pos_args('alias_target', str, varargs=(build.Target, build.BothLibraries), min_varargs=1)
21742170
@noKwargs
2175-
@noSecondLevelHolderResolving
21762171
def func_alias_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[build.Target, build.BothLibraries]]],
21772172
kwargs: TYPE_kwargs) -> build.AliasTarget:
21782173
name, deps = args
21792174
if any(isinstance(d, build.RunTarget) for d in deps):
21802175
FeatureNew.single_use('alias_target that depends on run_targets', '0.60.0', self.subproject)
2181-
tg = build.AliasTarget(name, deps, self.subdir, self.subproject, self.environment)
2176+
real_deps: T.List[build.Target] = []
2177+
for d in deps:
2178+
if isinstance(d, build.BothLibraries):
2179+
real_deps.append(d.shared)
2180+
real_deps.append(d.static)
2181+
else:
2182+
real_deps.append(d)
2183+
tg = build.AliasTarget(name, real_deps, self.subdir, self.subproject, self.environment)
21822184
self.add_target(name, tg)
21832185
return tg
21842186

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

3289+
# Cross reference them to implement as_shared() and as_static() methods.
3290+
shared_lib.set_static(static_lib)
3291+
static_lib.set_shared(shared_lib)
3292+
32873293
return build.BothLibraries(shared_lib, static_lib, preferred_library)
32883294

32893295
def build_library(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library):
32903296
default_library = self.coredata.get_option(OptionKey('default_library', subproject=self.subproject))
32913297
assert isinstance(default_library, str), 'for mypy'
32923298
if default_library == 'shared':
3293-
args, kwargs = resolve_second_level_holders(args, kwargs)
32943299
return self.build_target(node, args, T.cast('kwtypes.StaticLibrary', kwargs), build.SharedLibrary)
32953300
elif default_library == 'static':
3296-
args, kwargs = resolve_second_level_holders(args, kwargs)
32973301
return self.build_target(node, args, T.cast('kwtypes.SharedLibrary', kwargs), build.StaticLibrary)
32983302
elif default_library == 'both':
32993303
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)