diff --git a/docs/markdown/Porting-from-autotools.md b/docs/markdown/Porting-from-autotools.md index dc489af70fe8..962b02b5c2eb 100644 --- a/docs/markdown/Porting-from-autotools.md +++ b/docs/markdown/Porting-from-autotools.md @@ -603,7 +603,8 @@ gnome.generate_gir(asglib, identifier_prefix : 'As', export_packages : 'appstream-glib', includes : ['GObject-2.0', 'Gio-2.0', 'GdkPixbuf-2.0'], - install : true + install : true, + use_gi_repository_compile: true ) ``` diff --git a/mesonbuild/modules/__init__.py b/mesonbuild/modules/__init__.py index f9374cc1d48c..e4314d08a40b 100644 --- a/mesonbuild/modules/__init__.py +++ b/mesonbuild/modules/__init__.py @@ -80,7 +80,7 @@ def find_program(self, prog: T.Union[mesonlib.FileOrString, T.List[mesonlib.File return self._interpreter.find_program_impl(prog, required=required, version_func=version_func, wanted=wanted, silent=silent, for_machine=for_machine) - def find_tool(self, name: str, depname: str, varname: str, required: bool = True, + def find_tool(self, name: str, depname: str, varname: T.Optional[str] = None, required: bool = True, wanted: T.Optional[str] = None) -> T.Union['build.Executable', ExternalProgram, 'OverrideProgram']: # Look in overrides in case it's built as subproject progobj = self._interpreter.program_from_overrides([name], []) @@ -94,7 +94,7 @@ def find_tool(self, name: str, depname: str, varname: str, required: bool = True # Check if pkgconfig has a variable dep = self.dependency(depname, native=True, required=False, wanted=wanted) - if dep.found() and dep.type_name == 'pkgconfig': + if dep.found() and dep.type_name == 'pkgconfig' and varname: value = dep.get_variable(pkgconfig=varname) if value: progobj = ExternalProgram(value) diff --git a/mesonbuild/modules/gnome.py b/mesonbuild/modules/gnome.py index e0c1214d0851..7c9b36c5f262 100644 --- a/mesonbuild/modules/gnome.py +++ b/mesonbuild/modules/gnome.py @@ -97,6 +97,7 @@ class GenerateGir(TypedDict): nsversion: str sources: T.List[T.Union[FileOrString, build.GeneratedTypes]] symbol_prefix: T.List[str] + use_gi_repository_compile: bool class GtkDoc(TypedDict): @@ -252,6 +253,7 @@ class GnomeModule(ExtensionModule): def __init__(self, interpreter: 'Interpreter') -> None: super().__init__(interpreter) self.gir_dep: T.Optional[Dependency] = None + self.girepository_dep: T.Optional[Dependency] = None self.giscanner: T.Optional[T.Union[ExternalProgram, Executable, OverrideProgram]] = None self.gicompiler: T.Optional[T.Union[ExternalProgram, Executable, OverrideProgram]] = None self.install_glib_compile_schemas = False @@ -307,17 +309,18 @@ def _print_gdbus_warning() -> None: @staticmethod def _find_tool(state: 'ModuleState', tool: str) -> 'ToolType': tool_map = { - 'gio-querymodules': 'gio-2.0', - 'glib-compile-schemas': 'gio-2.0', - 'glib-compile-resources': 'gio-2.0', - 'gdbus-codegen': 'gio-2.0', - 'glib-genmarshal': 'glib-2.0', - 'glib-mkenums': 'glib-2.0', - 'g-ir-scanner': 'gobject-introspection-1.0', - 'g-ir-compiler': 'gobject-introspection-1.0', + 'gio-querymodules': ('gio-2.0', 'gio_querymodules'), + 'glib-compile-schemas': ('gio-2.0', 'glib_compile_schemas'), + 'glib-compile-resources': ('gio-2.0', 'glib_compile_resources'), + 'gdbus-codegen': ('gio-2.0', 'gdbus_codegen'), + 'glib-genmarshal': ('glib-2.0', 'glib_genmarshal'), + 'glib-mkenums': ('glib-2.0', 'glib_mkenums'), + # TODO: Use gi_compile_repository once GLib exposes it + 'gi-compile-repository': ('girepository-2.0', None), + 'g-ir-scanner': ('gobject-introspection-1.0', 'g_ir_scanner'), + 'g-ir-compiler': ('gobject-introspection-1.0', 'g_ir_compiler'), } - depname = tool_map[tool] - varname = tool.replace('-', '_') + depname, varname = tool_map[tool] return state.find_tool(tool, depname, varname) @typed_kwargs( @@ -763,7 +766,7 @@ def _get_dependencies_flags( return cflags, internal_ldflags, external_ldflags, gi_includes, depends - def _unwrap_gir_target(self, girtarget: T.Union[Executable, build.StaticLibrary, build.SharedLibrary], state: 'ModuleState' + def _unwrap_gir_target(self, girtarget: T.Union[Executable, build.StaticLibrary, build.SharedLibrary], state: 'ModuleState', use_gi_repository_compile: bool ) -> T.Union[Executable, build.StaticLibrary, build.SharedLibrary]: if not isinstance(girtarget, (Executable, build.SharedLibrary, build.StaticLibrary)): @@ -772,7 +775,7 @@ def _unwrap_gir_target(self, girtarget: T.Union[Executable, build.StaticLibrary, STATIC_BUILD_REQUIRED_VERSION = ">=1.58.1" if isinstance(girtarget, (build.StaticLibrary)) and \ not mesonlib.version_compare( - self._get_gir_dep(state)[0].get_version(), + self._get_gir_dep(state, use_gi_repository_compile=use_gi_repository_compile)[0].get_version(), STATIC_BUILD_REQUIRED_VERSION): raise MesonException('Static libraries can only be introspected with GObject-Introspection ' + STATIC_BUILD_REQUIRED_VERSION) @@ -787,12 +790,28 @@ def postconf_hook(self, b: build.Build) -> None: if self.devenv is not None: b.devenv.append(self.devenv) - def _get_gir_dep(self, state: 'ModuleState') -> T.Tuple[Dependency, T.Union[Executable, 'ExternalProgram', 'OverrideProgram'], - T.Union[Executable, 'ExternalProgram', 'OverrideProgram']]: + def _supports_girepository2(self, state: 'ModuleState'): + glib_version = self._get_native_glib_version(state) + + return mesonlib.version_compare(glib_version, '>= 2.79.2') + + def _get_gir_dep(self, state: 'ModuleState', use_gi_repository_compile: bool + ) -> T.Tuple[Dependency, T.Union[Executable, 'ExternalProgram', 'OverrideProgram'], + T.Union[Executable, 'ExternalProgram', 'OverrideProgram']]: + supports_girepository_2 = self._supports_girepository2(state) + if supports_girepository_2 and not self.girepository_dep and use_gi_repository_compile: + self.girepository_dep = state.dependency('girepository-2.0') + if not self.gir_dep: self.gir_dep = state.dependency('gobject-introspection-1.0') self.giscanner = self._find_tool(state, 'g-ir-scanner') - self.gicompiler = self._find_tool(state, 'g-ir-compiler') + + if not self.gicompiler: + if use_gi_repository_compile and supports_girepository_2: + self.gicompiler = self._find_tool(state, 'gi-compile-repository') + else: + self.gicompiler = self._find_tool(state, 'g-ir-compiler') + return self.gir_dep, self.giscanner, self.gicompiler @functools.lru_cache(maxsize=None) @@ -1112,6 +1131,7 @@ def _get_scanner_ldflags(ldflags: T.Iterable[str]) -> T.Iterable[str]: KwargInfo('install_dir_gir', (str, bool, NoneType), deprecated_values={False: ('0.61.0', 'Use install_gir to disable installation')}, validator=lambda x: 'as boolean can only be false' if x is True else None), + KwargInfo('use_gi_repository_compile', (bool), default=False), KwargInfo('install_typelib', (bool, NoneType), since='0.61.0'), KwargInfo('install_dir_typelib', (str, bool, NoneType), deprecated_values={False: ('0.61.0', 'Use install_typelib to disable installation')}, @@ -1127,11 +1147,13 @@ def generate_gir(self, state: 'ModuleState', args: T.Tuple[T.List[T.Union[Execut # Ensure we have a C compiler even in C++ projects. state.add_language('c', MachineChoice.HOST) - girtargets = [self._unwrap_gir_target(arg, state) for arg in args[0]] + use_gi_repository_compile = kwargs['use_gi_repository_compile'] + + girtargets = [self._unwrap_gir_target(arg, state, use_gi_repository_compile=use_gi_repository_compile) for arg in args[0]] if len(girtargets) > 1 and any(isinstance(el, Executable) for el in girtargets): raise MesonException('generate_gir only accepts a single argument when one of the arguments is an executable') - gir_dep, giscanner, gicompiler = self._get_gir_dep(state) + gir_dep, giscanner, gicompiler = self._get_gir_dep(state, use_gi_repository_compile=use_gi_repository_compile) ns = kwargs['namespace'] nsversion = kwargs['nsversion'] diff --git a/test cases/frameworks/39 gnome glib compile repository/copyfile.py b/test cases/frameworks/39 gnome glib compile repository/copyfile.py new file mode 100644 index 000000000000..7e44c48dd1a5 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/copyfile.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copy(sys.argv[1], sys.argv[2]) diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/copy.py b/test cases/frameworks/39 gnome glib compile repository/gir/copy.py new file mode 100755 index 000000000000..e92deaf5db24 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/copy.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2021 Intel Corporation + +import argparse +import shutil + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('src') + parser.add_argument('dest') + args = parser.parse_args() + + shutil.copy(args.src, args.dest) + + +if __name__ == "__main__": + main() diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep1.c b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep1.c new file mode 100644 index 000000000000..8d4ca4bfe4f8 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep1.c @@ -0,0 +1,56 @@ +#include "dep1.h" + +struct _MesonDep1 +{ + GObject parent_instance; +}; + +G_DEFINE_TYPE (MesonDep1, meson_dep1, G_TYPE_OBJECT) + +/** + * meson_dep1_new: + * + * Allocates a new #MesonDep1. + * + * Returns: (transfer full): a #MesonDep1. + */ +MesonDep1 * +meson_dep1_new (void) +{ + return g_object_new (MESON_TYPE_DEP1, NULL); +} + +static void +meson_dep1_finalize (GObject *object) +{ + G_OBJECT_CLASS (meson_dep1_parent_class)->finalize (object); +} + +static void +meson_dep1_class_init (MesonDep1Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_dep1_finalize; +} + +static void +meson_dep1_init (MesonDep1 *self) +{ +} + +/** + * meson_dep1_just_return_it: + * @dep: a #MesonDep2. + * + * Returns the #MesonDep2 that is passed in + * + * Returns: (transfer none): a #MesonDep2 + */ +MesonDep2* +meson_dep1_just_return_it (MesonDep1 *self, MesonDep2 *dep) +{ + g_return_val_if_fail (MESON_IS_DEP1 (self), NULL); + + return dep; +} diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep1.h b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep1.h new file mode 100644 index 000000000000..5e6591b2cd39 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep1.h @@ -0,0 +1,23 @@ +#ifndef MESON_DEP1_H +#define MESON_DEP1_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#include +#include "dep2/dep2.h" + +G_BEGIN_DECLS + +#define MESON_TYPE_DEP1 (meson_dep1_get_type()) + +G_DECLARE_FINAL_TYPE (MesonDep1, meson_dep1, MESON, DEP1, GObject) + +MesonDep1 *meson_dep1_new (void); +MesonDep2 *meson_dep1_just_return_it (MesonDep1 *self, + MesonDep2 *dep); + +G_END_DECLS + +#endif /* MESON_DEP1_H */ diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep2/dep2.c b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep2/dep2.c new file mode 100644 index 000000000000..754c6d7f794f --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep2/dep2.c @@ -0,0 +1,124 @@ +#include "dep2.h" + +struct _MesonDep2 +{ + GObject parent_instance; + + gchar *msg; +}; + +G_DEFINE_TYPE (MesonDep2, meson_dep2, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_MSG, + LAST_PROP +}; + +static GParamSpec *gParamSpecs [LAST_PROP]; + +/** + * meson_dep2_new: + * @msg: The message to set. + * + * Allocates a new #MesonDep2. + * + * Returns: (transfer full): a #MesonDep2. + */ +MesonDep2 * +meson_dep2_new (const gchar *msg) +{ + g_return_val_if_fail (msg != NULL, NULL); + + return g_object_new (MESON_TYPE_DEP2, + "message", msg, + NULL); +} + +static void +meson_dep2_finalize (GObject *object) +{ + MesonDep2 *self = (MesonDep2 *)object; + + g_clear_pointer (&self->msg, g_free); + + G_OBJECT_CLASS (meson_dep2_parent_class)->finalize (object); +} + +static void +meson_dep2_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MesonDep2 *self = MESON_DEP2 (object); + + switch (prop_id) + { + case PROP_MSG: + g_value_set_string (value, self->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep2_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MesonDep2 *self = MESON_DEP2 (object); + + switch (prop_id) + { + case PROP_MSG: + self->msg = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep2_class_init (MesonDep2Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_dep2_finalize; + object_class->get_property = meson_dep2_get_property; + object_class->set_property = meson_dep2_set_property; + + gParamSpecs [PROP_MSG] = + g_param_spec_string ("message", + "Message", + "The message to print.", + NULL, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs); +} + +static void +meson_dep2_init (MesonDep2 *self) +{ +} + +/** + * meson_dep2_return_message: + * @self: a #MesonDep2. + * + * Returns the message. + * + * Returns: (transfer none): a const gchar* + */ +const gchar* +meson_dep2_return_message (MesonDep2 *self) +{ + g_return_val_if_fail (MESON_IS_DEP2 (self), NULL); + + return (const gchar*) self->msg; +} diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep2/dep2.h b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep2/dep2.h new file mode 100644 index 000000000000..128b243a8868 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep2/dep2.h @@ -0,0 +1,21 @@ +#ifndef MESON_DEP2_H +#define MESON_DEP2_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#include + +G_BEGIN_DECLS + +#define MESON_TYPE_DEP2 (meson_dep2_get_type()) + +G_DECLARE_FINAL_TYPE (MesonDep2, meson_dep2, MESON, DEP2, GObject) + +MesonDep2 *meson_dep2_new (const gchar *msg); +const gchar *meson_dep2_return_message (MesonDep2 *self); + +G_END_DECLS + +#endif /* MESON_DEP2_H */ diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep2/meson.build b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep2/meson.build new file mode 100644 index 000000000000..94c008a13981 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep2/meson.build @@ -0,0 +1,23 @@ +dep2sources = ['dep2.c', 'dep2.h'] + +dep2lib = shared_library( + 'dep2lib', + sources : dep2sources, + dependencies : gobj, + install : true +) + +dep2gir = gnome.generate_gir( + dep2lib, + sources : dep2sources, + nsversion : '1.0', + namespace : 'MesonDep2', + symbol_prefix : 'meson', + identifier_prefix : 'Meson', + includes : ['GObject-2.0'], + install : true, + use_gi_repository_compile: true +) + +dep2_dep = declare_dependency(link_with : dep2lib, + sources : [dep2gir]) diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep3/dep3.c b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep3/dep3.c new file mode 100644 index 000000000000..ee5c5e123ceb --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep3/dep3.c @@ -0,0 +1,124 @@ +#include "dep3.h" + +struct _MesonDep3 +{ + GObject parent_instance; + + gchar *msg; +}; + +G_DEFINE_TYPE (MesonDep3, meson_dep3, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_MSG, + LAST_PROP +}; + +static GParamSpec *gParamSpecs [LAST_PROP]; + +/** + * meson_dep3_new: + * @msg: The message to set. + * + * Allocates a new #MesonDep3. + * + * Returns: (transfer full): a #MesonDep3. + */ +MesonDep3 * +meson_dep3_new (const gchar *msg) +{ + g_return_val_if_fail (msg != NULL, NULL); + + return g_object_new (MESON_TYPE_DEP3, + "message", msg, + NULL); +} + +static void +meson_dep3_finalize (GObject *object) +{ + MesonDep3 *self = (MesonDep3 *)object; + + g_clear_pointer (&self->msg, g_free); + + G_OBJECT_CLASS (meson_dep3_parent_class)->finalize (object); +} + +static void +meson_dep3_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MesonDep3 *self = MESON_DEP3 (object); + + switch (prop_id) + { + case PROP_MSG: + g_value_set_string (value, self->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep3_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MesonDep3 *self = MESON_DEP3 (object); + + switch (prop_id) + { + case PROP_MSG: + self->msg = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep3_class_init (MesonDep3Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_dep3_finalize; + object_class->get_property = meson_dep3_get_property; + object_class->set_property = meson_dep3_set_property; + + gParamSpecs [PROP_MSG] = + g_param_spec_string ("message", + "Message", + "The message to print.", + NULL, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs); +} + +static void +meson_dep3_init (MesonDep3 *self) +{ +} + +/** + * meson_dep3_return_message: + * @self: a #MesonDep3. + * + * Returns the message. + * + * Returns: (transfer none): a const gchar* + */ +const gchar* +meson_dep3_return_message (MesonDep3 *self) +{ + g_return_val_if_fail (MESON_IS_DEP3 (self), NULL); + + return (const gchar*) self->msg; +} diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep3/dep3.h b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep3/dep3.h new file mode 100644 index 000000000000..4392bad83392 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep3/dep3.h @@ -0,0 +1,21 @@ +#ifndef MESON_DEP3_H +#define MESON_DEP3_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#include + +G_BEGIN_DECLS + +#define MESON_TYPE_DEP3 (meson_dep3_get_type()) + +G_DECLARE_FINAL_TYPE (MesonDep3, meson_dep3, MESON, DEP3, GObject) + +MesonDep3 *meson_dep3_new (const gchar *msg); +const gchar *meson_dep3_return_message (MesonDep3 *self); + +G_END_DECLS + +#endif /* MESON_DEP3_H */ diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep3/meson.build b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep3/meson.build new file mode 100644 index 000000000000..23fb28465e65 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/dep3/meson.build @@ -0,0 +1,23 @@ +dep3sources = ['dep3.c', 'dep3.h'] + +dep3lib = shared_library( + 'dep3lib', + sources : dep3sources, + dependencies : gobj, + install : true +) + +dep3gir = gnome.generate_gir( + dep3lib, + sources : dep3sources, + nsversion : '1.0', + namespace : 'MesonDep3', + symbol_prefix : 'meson', + identifier_prefix : 'Meson', + includes : ['GObject-2.0'], + install : true, + use_gi_repository_compile: true +) + +dep3_dep = declare_dependency(link_with : dep3lib, + sources : [dep3gir]) diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/dep1/meson.build b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/meson.build new file mode 100644 index 000000000000..c5d72c8cda7c --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/dep1/meson.build @@ -0,0 +1,32 @@ +subdir('dep2') +subdir('dep3') + +dep1sources = ['dep1.c', 'dep1.h'] + +# Do not need to link to dep2lib because we don't use any symbols from it +dep1lib = shared_library( + 'dep1lib', + sources : dep1sources, + dependencies : gobj, + install : true +) + +# But the gir does need it because it we use the MesonDep2* structure defined +# in the header +dep1gir = gnome.generate_gir( + dep1lib, + sources : dep1sources, + nsversion : '1.0', + namespace : 'MesonDep1', + symbol_prefix : 'meson', + identifier_prefix : 'Meson', + header: 'dep1.h', + includes : ['GObject-2.0', 'MesonDep2-1.0', dep3gir[0]], + dependencies : [dep2_dep], + install : true, + use_gi_repository_compile: true +) + +dep1_dep = declare_dependency(link_with : dep1lib, + dependencies : [dep2_dep, dep3_dep], + sources : [dep1gir]) diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample.c b/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample.c new file mode 100644 index 000000000000..850b850cf703 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample.c @@ -0,0 +1,121 @@ +#include "meson-sample.h" + +struct _MesonSample +{ + GObject parent_instance; + + gchar *msg; +}; + +G_DEFINE_TYPE (MesonSample, meson_sample, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_MSG, + LAST_PROP +}; + +static GParamSpec *gParamSpecs [LAST_PROP]; + +/** + * meson_sample_new: + * + * Allocates a new #MesonSample. + * + * Returns: (transfer full): a #MesonSample. + */ +MesonSample * +meson_sample_new (void) +{ + return g_object_new (MESON_TYPE_SAMPLE, NULL); +} + +static void +meson_sample_finalize (GObject *object) +{ + MesonSample *self = (MesonSample *)object; + + g_clear_pointer (&self->msg, g_free); + + G_OBJECT_CLASS (meson_sample_parent_class)->finalize (object); +} + +static void +meson_sample_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MesonSample *self = MESON_SAMPLE (object); + + switch (prop_id) + { + case PROP_MSG: + g_value_set_string (value, self->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_sample_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MesonSample *self = MESON_SAMPLE (object); + + switch (prop_id) + { + case PROP_MSG: + self->msg = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_sample_class_init (MesonSampleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_sample_finalize; + object_class->get_property = meson_sample_get_property; + object_class->set_property = meson_sample_set_property; + + gParamSpecs [PROP_MSG] = + g_param_spec_string ("message", + "Message", + "The message to print.", + NULL, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs); +} + +static void +meson_sample_init (MesonSample *self) +{ +} + +/** + * meson_sample_print_message: + * @self: a #MesonSample. + * + * Prints the message. + * + * Returns: Nothing. + */ +void +meson_sample_print_message (MesonSample *self, MesonDep1 *dep1, MesonDep2 *dep2) +{ + MesonDep2 *samedep; + g_return_if_fail (MESON_IS_SAMPLE (self)); + + samedep = meson_dep1_just_return_it (dep1, dep2); + g_print ("Message: %s\n", meson_dep2_return_message (samedep)); +} diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample.h b/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample.h new file mode 100644 index 000000000000..74681305111b --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample.h @@ -0,0 +1,28 @@ +#ifndef MESON_SAMPLE_H +#define MESON_SAMPLE_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#if !defined (MESON_TEST_2) +#error "MESON_TEST_2 not defined." +#endif + +#include +#include "dep1/dep1.h" + +G_BEGIN_DECLS + +#define MESON_TYPE_SAMPLE (meson_sample_get_type()) + +G_DECLARE_FINAL_TYPE (MesonSample, meson_sample, MESON, SAMPLE, GObject) + +MesonSample *meson_sample_new (void); +void meson_sample_print_message (MesonSample *self, + MesonDep1 *dep1, + MesonDep2 *dep2); + +G_END_DECLS + +#endif /* MESON_SAMPLE_H */ diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample2.c b/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample2.c new file mode 100644 index 000000000000..f76bc1629126 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample2.c @@ -0,0 +1,45 @@ +#include "meson-sample2.h" + +struct _MesonSample2 +{ + GObject parent_instance; +}; + +G_DEFINE_TYPE (MesonSample2, meson_sample2, G_TYPE_OBJECT) + +/** + * meson_sample2_new: + * + * Allocates a new #MesonSample2. + * + * Returns: (transfer full): a #MesonSample2. + */ +MesonSample2 * +meson_sample2_new (void) +{ + return g_object_new (MESON_TYPE_SAMPLE2, NULL); +} + +static void +meson_sample2_class_init (MesonSample2Class *klass) +{ +} + +static void +meson_sample2_init (MesonSample2 *self) +{ +} + +/** + * meson_sample2_print_message: + * @self: a #MesonSample2. + * + * Prints Hello. + * + * Returns: Nothing. + */ +void +meson_sample2_print_message (MesonSample2 *self) +{ + g_print ("Message: Hello\n"); +} diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample2.h b/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample2.h new file mode 100644 index 000000000000..f3bcd39e968a --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/meson-sample2.h @@ -0,0 +1,21 @@ +#ifndef MESON_SAMPLE2_H +#define MESON_SAMPLE2_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#include + +G_BEGIN_DECLS + +#define MESON_TYPE_SAMPLE2 (meson_sample2_get_type()) + +G_DECLARE_FINAL_TYPE (MesonSample2, meson_sample2, MESON, SAMPLE2, GObject) + +MesonSample2 *meson_sample2_new (void); +void meson_sample2_print_message (MesonSample2 *self); + +G_END_DECLS + +#endif /* MESON_SAMPLE2_H */ diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/meson.build b/test cases/frameworks/39 gnome glib compile repository/gir/meson.build new file mode 100644 index 000000000000..c069ea5e0cdb --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/meson.build @@ -0,0 +1,64 @@ +subdir('dep1') + +libsources = ['meson-sample.c', 'meson-sample.h'] +lib2sources = ['meson-sample2.c', 'meson-sample2.h'] + +gen_source = custom_target( + 'meson_sample3.h', + input : 'meson-sample.h', + output : 'meson-sample3.h', + command : [find_program('copy.py'), '@INPUT@', '@OUTPUT@'], + build_by_default : false, # this will force a race condition if one exists +) + +girlib = shared_library( + 'gir_lib', + sources : libsources, + c_args: '-DMESON_TEST_2', + dependencies : [gobj, dep1_dep], + install : true +) + +girlib2 = shared_library( + 'gir_lib2', + sources : lib2sources, + dependencies : [gobj], + install : true +) + +girexe = executable( + 'girprog', + sources : 'prog.c', + c_args: '-DMESON_TEST_2', + dependencies : [glib, gobj, gir, dep1_dep], + link_with : girlib +) + +fake_dep = dependency('no-way-this-exists', required: false) + +gnome.generate_gir( + girlib, girlib2, + sources : [libsources, lib2sources, gen_source], + env : {'CPPFLAGS': '-DMESON_TEST_2'}, + nsversion : '1.0', + namespace : 'Meson', + symbol_prefix : 'meson', + identifier_prefix : 'Meson', + includes : ['GObject-2.0', 'MesonDep1-1.0'], + # dep1_dep pulls in dep2_dep for us + dependencies : [[fake_dep, dep1_dep]], + install : true, + build_by_default : true, + use_gi_repository_compile: true +) + +test('gobject introspection/c', girexe) +gir_paths = ':'.join([girlib.outdir(), dep1lib.outdir(), dep2lib.outdir(), dep3lib.outdir()]) +envdata = environment() +envdata.append('GI_TYPELIB_PATH', gir_paths, separator : ':') +envdata.append('LD_LIBRARY_PATH', gir_paths) +if ['windows', 'cygwin'].contains(host_machine.system()) + envdata.append('PATH', gir_paths) +endif +test('gobject introspection/py', find_program('prog.py'), + env : envdata) diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/prog.c b/test cases/frameworks/39 gnome glib compile repository/gir/prog.c new file mode 100644 index 000000000000..001f6d0b9e16 --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/prog.c @@ -0,0 +1,35 @@ +#include + +#include "meson-sample.h" + +gint +main (gint argc, + gchar *argv[]) +{ + GError * error = NULL; + + GOptionContext * ctx = g_option_context_new (NULL); + g_option_context_add_group (ctx, g_irepository_get_option_group ()); + + if (!g_option_context_parse (ctx, &argc, &argv, &error)) { + g_print ("sample: %s\n", error->message); + g_option_context_free (ctx); + if (error) { + g_error_free (error); + } + + return 1; + } + + MesonSample * i = meson_sample_new (); + MesonDep1 * dep1 = meson_dep1_new (); + MesonDep2 * dep2 = meson_dep2_new ("Hello, meson/c!"); + meson_sample_print_message (i, dep1, dep2); + + g_object_unref (i); + g_object_unref (dep1); + g_object_unref (dep2); + g_option_context_free (ctx); + + return 0; +} diff --git a/test cases/frameworks/39 gnome glib compile repository/gir/prog.py b/test cases/frameworks/39 gnome glib compile repository/gir/prog.py new file mode 100755 index 000000000000..aa1f9a7744cb --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/gir/prog.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +from gi.repository import Meson, MesonDep1, MesonDep2 + +if __name__ == "__main__": + s = Meson.Sample.new() + dep1 = MesonDep1.Dep1.new() + dep2 = MesonDep2.Dep2.new("Hello, meson/py!") + s.print_message(dep1, dep2) + + s2 = Meson.Sample2.new() + s2.print_message() diff --git a/test cases/frameworks/39 gnome glib compile repository/meson.build b/test cases/frameworks/39 gnome glib compile repository/meson.build new file mode 100644 index 000000000000..751c1cec8f9f --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/meson.build @@ -0,0 +1,66 @@ +project('gobject-introspection', 'c') + +copyfile = find_program('copyfile.py') +copyfile_gen = generator(copyfile, + output: '@BASENAME@Gen.xml', + arguments : ['@INPUT@', '@OUTPUT@']) + +glib = dependency('glib-2.0', required: false) +if not glib.found() + error('MESON_SKIP_TEST glib not found.') +endif + +gir = dependency('gobject-introspection-1.0', required: false) +if not gir.found() + error('MESON_SKIP_TEST gobject-introspection not found.') +endif + +python3 = import('python3') +py3 = python3.find_python() +if run_command(py3, '-c', 'import gi;', check: false).returncode() != 0 + error('MESON_SKIP_TEST python3-gi not found') +endif + +cc = meson.get_compiler('c') + +add_global_arguments('-DMESON_TEST_1', language : 'c') +if cc.get_id() == 'intel' + # Ignore invalid GCC pragma warnings from glib + # https://bugzilla.gnome.org/show_bug.cgi?id=776562 + add_global_arguments('-wd2282', language : 'c') +endif + +py3 = import('python3').find_python() +pycode = '''import os, sys +if "MESON_UNIT_TEST_PRETEND_GLIB_OLD" in os.environ: + sys.exit(0) +sys.exit(1) +''' + +pretend_glib_old = false +res = run_command(py3, '-c', pycode, check: false) +if res.returncode() == 0 + pretend_glib_old = true +endif + +gnome = import('gnome') +gio = dependency('gio-2.0') +giounix = dependency('gio-unix-2.0') +glib = dependency('glib-2.0') +gobj = dependency('gobject-2.0') +gir = dependency('gobject-introspection-1.0') +gmod = dependency('gmodule-2.0') + +# GLib >= 2.76 removed slice allocator which causes a leak in g-i to now be +# visible to asan. The leak should be fixed in g-i >= 1.76.2: +# https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/411 +if get_option('b_sanitize') != 'none' and \ + gir.version().version_compare('<=1.76.1') and \ + glib.version().version_compare('>=2.76') + error('MESON_SKIP_TEST gobject-introspection >=1.76.2 is required with address sanitizer.') +endif + +# Test that static deps don't error out when static libraries aren't found +glib_static = dependency('glib-2.0', static : true) + +subdir('gir') diff --git a/test cases/frameworks/39 gnome glib compile repository/test.json b/test cases/frameworks/39 gnome glib compile repository/test.json new file mode 100644 index 000000000000..a0a061113efa --- /dev/null +++ b/test cases/frameworks/39 gnome glib compile repository/test.json @@ -0,0 +1,23 @@ +{ + "installed": [ + {"type": "expr", "file": "usr/lib/?libgir_lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgir_lib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libgir_lib2.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgir_lib2.dll.a"}, + {"type": "expr", "file": "usr/lib/?libdep1lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep1lib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libdep2lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep2lib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libdep3lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep3lib.dll.a"}, + {"type": "file", "file": "usr/lib/girepository-1.0/Meson-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep1-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep2-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep3-1.0.typelib"}, + {"type": "file", "file": "usr/share/gir-1.0/Meson-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonDep1-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonDep2-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonDep3-1.0.gir"} + ], + "expect_skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "pypy", "bionic"] +}