Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix gir gst regression #13837

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 32 additions & 20 deletions mesonbuild/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,7 @@ def __init__(
}
self.pic = False
self.pie = False
self.both_lib: T.Optional[T.Union[StaticLibrary, SharedLibrary]] = None
# Track build_rpath entries so we can remove them at install time
self.rpath_dirs_to_remove: T.Set[bytes] = set()
self.process_sourcelist(sources)
Expand Down Expand Up @@ -1735,16 +1736,20 @@ def process_vs_module_defs_kw(self, kwargs: T.Dict[str, T.Any]) -> None:
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]:
bl_type = self.environment.coredata.get_option(OptionKey('default_both_libraries'))
if bl_type == 'auto':
bl_type = 'static' if isinstance(self, StaticLibrary) else 'shared'

def _resolve_both_libs(lib: LibTypes) -> LibTypes:
if isinstance(lib, BothLibraries):
return lib.get(bl_type)
return lib
if isinstance(self, StaticLibrary):
bl_type = 'static'
elif isinstance(self, SharedLibrary):
bl_type = 'shared'

self_libs: T.List[LibTypes] = self.link_targets if key == 'link_with' else self.link_whole_targets
lib_list = listify(kwargs.get(key, [])) + self_libs
return [_resolve_both_libs(t) for t in lib_list]

lib_list = []
for lib in listify(kwargs.get(key, [])) + self_libs:
if isinstance(lib, (Target, BothLibraries)):
lib_list.append(lib.get(bl_type))
else:
lib_list.append(lib)
return lib_list

def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes:
"""Base case used by BothLibraries"""
Expand Down Expand Up @@ -2199,6 +2204,14 @@ def is_linkable_target(self):
def is_internal(self) -> bool:
return not self.install

def set_shared(self, shared_library: SharedLibrary) -> None:
self.both_lib = shared_library

def get(self, lib_type: T.Literal['static', 'shared', 'auto']) -> LibTypes:
if lib_type == 'shared':
return self.both_lib or self
return self

class SharedLibrary(BuildTarget):
known_kwargs = known_shlib_kwargs

Expand Down Expand Up @@ -2465,6 +2478,14 @@ def type_suffix(self):
def is_linkable_target(self):
return True

def set_static(self, static_library: StaticLibrary) -> None:
self.both_lib = static_library

def get(self, lib_type: T.Literal['static', 'shared']) -> LibTypes:
if lib_type == 'static':
return self.both_lib or self
return self

# A shared library that is meant to be used with dlopen rather than linking
# into something else.
class SharedModule(SharedLibrary):
Expand Down Expand Up @@ -2501,7 +2522,7 @@ def get_default_install_dir(self) -> T.Union[T.Tuple[str, str], T.Tuple[None, No
return self.environment.get_shared_module_dir(), '{moduledir_shared}'

class BothLibraries(SecondLevelHolder):
def __init__(self, shared: SharedLibrary, static: StaticLibrary, preferred_library: Literal['shared', 'static', 'auto']) -> None:
def __init__(self, shared: SharedLibrary, static: StaticLibrary, preferred_library: Literal['shared', 'static']) -> None:
self._preferred_library = preferred_library
self.shared = shared
self.static = static
Expand Down Expand Up @@ -2909,23 +2930,14 @@ class AliasTarget(RunTarget):

typename = 'alias'

def __init__(self, name: str, dependencies: T.Sequence[T.Union[Target, BothLibraries]],
def __init__(self, name: str, dependencies: T.Sequence[Target],
subdir: str, subproject: str, environment: environment.Environment):
super().__init__(name, [], list(self._deps_generator(dependencies)), subdir, subproject, environment)
super().__init__(name, [], dependencies, subdir, subproject, environment)

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

@staticmethod
def _deps_generator(dependencies: T.Sequence[T.Union[Target, BothLibraries]]) -> T.Iterator[Target]:
for dep in dependencies:
if isinstance(dep, BothLibraries):
yield dep.shared
yield dep.static
else:
yield dep

class Jar(BuildTarget):
known_kwargs = known_jar_kwargs

Expand Down
22 changes: 13 additions & 9 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from ..interpreterbase import Disabler, disablerIfNotFound
from ..interpreterbase import FeatureNew, FeatureDeprecated, FeatureBroken, FeatureNewKwargs
from ..interpreterbase import ObjectHolder, ContextManagerObject
from ..interpreterbase import stringifyUserArguments, resolve_second_level_holders
from ..interpreterbase import stringifyUserArguments
from ..modules import ExtensionModule, ModuleObject, MutableModuleObject, NewExtensionModule, NotFoundExtensionModule
from ..optinterpreter import optname_regex

Expand Down Expand Up @@ -690,7 +690,6 @@ def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwa
KwargInfo('version', (str, NoneType)),
KwargInfo('objects', ContainerTypeInfo(list, build.ExtractedObjects), listify=True, default=[], since='1.1.0'),
)
@noSecondLevelHolderResolving
def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var],
kwargs: kwtypes.FuncDeclareDependency) -> dependencies.Dependency:
deps = kwargs['dependencies']
Expand Down Expand Up @@ -1916,15 +1915,12 @@ def func_jar(self, node: mparser.BaseNode,
@permittedKwargs(known_build_target_kwargs)
@typed_pos_args('build_target', str, varargs=SOURCES_VARARGS)
@typed_kwargs('build_target', *BUILD_TARGET_KWS, allow_unknown=True)
@noSecondLevelHolderResolving
def func_build_target(self, node: mparser.BaseNode,
args: T.Tuple[str, SourcesVarargsType],
kwargs: kwtypes.BuildTarget
) -> T.Union[build.Executable, build.StaticLibrary, build.SharedLibrary,
build.SharedModule, build.BothLibraries, build.Jar]:
target_type = kwargs['target_type']
if target_type not in {'both_libraries', 'library'}:
args, kwargs = resolve_second_level_holders(args, kwargs)

if target_type == 'executable':
return self.build_target(node, args, kwargs, build.Executable)
Expand Down Expand Up @@ -2186,13 +2182,19 @@ def func_run_target(self, node: mparser.FunctionNode, args: T.Tuple[str],
@FeatureNew('alias_target', '0.52.0')
@typed_pos_args('alias_target', str, varargs=(build.Target, build.BothLibraries), min_varargs=1)
@noKwargs
@noSecondLevelHolderResolving
def func_alias_target(self, node: mparser.BaseNode, args: T.Tuple[str, T.List[T.Union[build.Target, build.BothLibraries]]],
kwargs: TYPE_kwargs) -> build.AliasTarget:
name, deps = args
if any(isinstance(d, build.RunTarget) for d in deps):
FeatureNew.single_use('alias_target that depends on run_targets', '0.60.0', self.subproject)
tg = build.AliasTarget(name, deps, self.subdir, self.subproject, self.environment)
real_deps: T.List[build.Target] = []
for d in deps:
if isinstance(d, build.BothLibraries):
real_deps.append(d.shared)
real_deps.append(d.static)
else:
real_deps.append(d)
tg = build.AliasTarget(name, real_deps, self.subdir, self.subproject, self.environment)
self.add_target(name, tg)
return tg

Expand Down Expand Up @@ -3298,16 +3300,18 @@ def build_both_libraries(self, node: mparser.BaseNode, args: T.Tuple[str, Source
# Keep only compilers used for linking
static_lib.compilers = {k: v for k, v in static_lib.compilers.items() if k in compilers.clink_langs}

# Cross reference them to implement as_shared() and as_static() methods.
shared_lib.set_static(static_lib)
static_lib.set_shared(shared_lib)

return build.BothLibraries(shared_lib, static_lib, preferred_library)

def build_library(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargsType], kwargs: kwtypes.Library):
default_library = self.coredata.get_option(OptionKey('default_library', subproject=self.subproject))
assert isinstance(default_library, str), 'for mypy'
if default_library == 'shared':
args, kwargs = resolve_second_level_holders(args, kwargs)
return self.build_target(node, args, T.cast('kwtypes.StaticLibrary', kwargs), build.SharedLibrary)
elif default_library == 'static':
args, kwargs = resolve_second_level_holders(args, kwargs)
return self.build_target(node, args, T.cast('kwtypes.SharedLibrary', kwargs), build.StaticLibrary)
elif default_library == 'both':
return self.build_both_libraries(node, args, kwargs)
Expand Down
10 changes: 6 additions & 4 deletions mesonbuild/interpreter/interpreterobjects.py
Original file line number Diff line number Diff line change
Expand Up @@ -1001,8 +1001,6 @@ class SharedLibraryHolder(BuildTargetHolder[build.SharedLibrary]):

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

@noPosargs
@noKwargs
def get_static_lib_method(self, args: T.List[TYPE_var], kwargs: TYPE_kwargs) -> build.StaticLibrary:
return self.held_object.static
lib = copy.copy(self.held_object.static)
lib.both_lib = None
return lib

class SharedModuleHolder(BuildTargetHolder[build.SharedModule]):
pass
Expand Down
7 changes: 7 additions & 0 deletions test cases/frameworks/38 gir both_libraries/bar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "bar.h"
#include "foo.h"

int bar_func(void)
{
return foo_func() + 42;
}
1 change: 1 addition & 0 deletions test cases/frameworks/38 gir both_libraries/bar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int bar_func(void);
6 changes: 6 additions & 0 deletions test cases/frameworks/38 gir both_libraries/foo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "foo.h"

int foo_func(void)
{
return 42;
}
1 change: 1 addition & 0 deletions test cases/frameworks/38 gir both_libraries/foo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
int foo_func(void);
42 changes: 42 additions & 0 deletions test cases/frameworks/38 gir both_libraries/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
project('gir both libraries', 'c')

gir = dependency('gobject-introspection-1.0', required: false)
if not gir.found()
error('MESON_SKIP_TEST gobject-introspection not found.')
endif

if host_machine.system() == 'cygwin'
# FIXME: g-ir-scanner seems broken on cygwin:
# ERROR: can't resolve libraries to shared libraries: foo++
error('MESON_SKIP_TEST g-ir-scanner is broken on cygwin.')
endif

gnome = import('gnome')

# Regression test simulating how GStreamer generate its GIRs.
# Generated gobject-introspection binaries for every GStreamer libraries must
# first call gst_init() defined in the main libgstreamer, which means they need
# to link on that lib.
# A regression caused by https://github.com/mesonbuild/meson/pull/12632 made
# Meson not link the binary generated for bar with libfoo in the case it uses
# both_libraries().

libfoo = both_libraries('foo', 'foo.c')
foo_gir = gnome.generate_gir(libfoo,
namespace: 'foo',
nsversion: '1.0',
sources: ['foo.c', 'foo.h'],
)
foo_dep = declare_dependency(
link_with: libfoo,
sources: foo_gir,
)

libbar = both_libraries('bar', 'bar.c', dependencies: foo_dep)
gnome.generate_gir(libbar,
namespace: 'bar',
nsversion: '1.0',
sources: ['bar.c', 'bar.h'],
extra_args: '--add-init-section=extern void foo_func(void);foo_func();',
dependencies: foo_dep,
)
3 changes: 3 additions & 0 deletions test cases/frameworks/38 gir both_libraries/test.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"expect_skip_on_jobname": ["azure", "macos", "msys2", "cygwin"]
}
Loading