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

gnome: Add support for gi-compile-repository for generate_gir #13997

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
3 changes: 2 additions & 1 deletion docs/markdown/Porting-from-autotools.md
Original file line number Diff line number Diff line change
Expand Up @@ -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_glib_to_compile_repositories: true
)
```

Expand Down
4 changes: 2 additions & 2 deletions mesonbuild/modules/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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], [])
Expand All @@ -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)
Expand Down
47 changes: 31 additions & 16 deletions mesonbuild/modules/gnome.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ class GenerateGir(TypedDict):
nsversion: str
sources: T.List[T.Union[FileOrString, build.GeneratedTypes]]
symbol_prefix: T.List[str]
use_glib_to_compile_repositories: bool

class GtkDoc(TypedDict):

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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),
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code as-written does not allow looking up tools which are not in pkg-config, this adapts the code to allow finding tools via binary lookup only

'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(
Expand Down Expand Up @@ -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_glib_to_compile_repositories: bool
) -> T.Union[Executable, build.StaticLibrary, build.SharedLibrary]:
if not isinstance(girtarget, (Executable, build.SharedLibrary,
build.StaticLibrary)):
Expand All @@ -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_glib_to_compile_repositories=use_glib_to_compile_repositories)[0].get_version(),
STATIC_BUILD_REQUIRED_VERSION):
raise MesonException('Static libraries can only be introspected with GObject-Introspection ' + STATIC_BUILD_REQUIRED_VERSION)

Expand All @@ -787,12 +790,21 @@ 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'],
def _get_gir_dep(self, state: 'ModuleState', use_glib_to_compile_repositories: bool) -> T.Tuple[Dependency, T.Union[Executable, 'ExternalProgram', 'OverrideProgram'],
T.Union[Executable, 'ExternalProgram', 'OverrideProgram']]:
if not self.girepository_dep and use_glib_to_compile_repositories:
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 and not use_glib_to_compile_repositories:
self.gicompiler = self._find_tool(state, 'gi-compile-repository')

if not self.gicompiler and use_glib_to_compile_repositories:
self.gicompiler = self._find_tool(state, 'gi-compile-repository')

return self.gir_dep, self.giscanner, self.gicompiler

@functools.lru_cache(maxsize=None)
Expand Down Expand Up @@ -1112,6 +1124,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_glib_to_compile_repositories', (bool), default=False),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not just a long name, it's an unfortunately long name...

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')},
Expand All @@ -1127,11 +1140,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_glib_to_compile_repositories = kwargs['use_glib_to_compile_repositories']

girtargets = [self._unwrap_gir_target(arg, state, use_glib_to_compile_repositories=use_glib_to_compile_repositories) 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_glib_to_compile_repositories=use_glib_to_compile_repositories)

ns = kwargs['namespace']
nsversion = kwargs['nsversion']
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env python3

import sys
import shutil

shutil.copy(sys.argv[1], sys.argv[2])
Original file line number Diff line number Diff line change
@@ -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()
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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 <glib-object.h>
#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 */
Original file line number Diff line number Diff line change
@@ -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;
}
Original file line number Diff line number Diff line change
@@ -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 <glib-object.h>

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 */
Loading
Loading