gnome: add mkenums_simple()

99% of all mkenums uses in C libraries use the same basic template,
so add a mkenums_simple() function that takes care of everything for
us based on that template.

Features:
 - optional function declaration decorator such as GLIB_AVAILABLE
 - optional extra header prefix (e.g. for include needed for decorator)
 - optional extra body prefix (e.g. for additional includes)
 - optional function name prefix (e.g. to add leading underscores)

Fixes issue #1384
pull/2190/head
Tim-Philipp Müller 8 years ago committed by Jussi Pakkanen
parent c69a4aee1e
commit 4e476c82f3
  1. 49
      docs/markdown/Gnome-module.md
  2. 7
      docs/markdown/Release-notes-for-0.42.0.md
  3. 105
      mesonbuild/modules/gnome.py
  4. 35
      test cases/frameworks/7 gnome/mkenums/main4.c
  5. 35
      test cases/frameworks/7 gnome/mkenums/main5.c
  6. 2
      test cases/frameworks/7 gnome/mkenums/meson-decls.h
  7. 9
      test cases/frameworks/7 gnome/mkenums/meson.build

@ -72,6 +72,12 @@ Returns an array of two elements which are: `[c_source, header_file]`
Generates enum files for GObject using the `glib-mkenums` tool. The first argument is the base name of the output files. Generates enum files for GObject using the `glib-mkenums` tool. The first argument is the base name of the output files.
This method is essentially a wrapper around the `glib-mkenums` tool's command line API. It is the most featureful method for enum creation.
Typically you either provide template files or you specify the various template sections manually as strings.
Most libraries and applications will be using the same standard template with only minor tweaks, in which case the `gnome.mkenums_simple()` convenience method can be used instead.
Note that if you `#include` the generated header in any of the sources for a build target, you must add the generated header to the build target's list of sources to codify the dependency. This is true for all generated sources, not just `mkenums`. Note that if you `#include` the generated header in any of the sources for a build target, you must add the generated header to the build target's list of sources to codify the dependency. This is true for all generated sources, not just `mkenums`.
* `sources`: the list of sources to make enums with * `sources`: the list of sources to make enums with
@ -93,6 +99,49 @@ Note that if you `#include` the generated header in any of the sources for a bui
Returns an array of two elements which are: `[c_source, header_file]` Returns an array of two elements which are: `[c_source, header_file]`
### gnome.mkenums_simple()
Generates enum `.c` and `.h` files for GObject using the `glib-mkenums` tool
with the standard template used by most GObject-based C libraries. The first
argument is the base name of the output files.
Note that if you `#include` the generated header in any of the sources for a
build target, you must add the generated header to the build target's list of
sources to codify the dependency. This is true for all generated sources, not
just `mkenums_simple`.
* `sources`: the list of sources to make enums with
* `install_header`: if true, install the generated header
* `install_dir`: directory to install the header
* `identifier_prefix`: prefix to use for the identifiers
* `symbol_prefix`: prefix to use for the symbols
* `header_prefix`: additional prefix at the top of the header file, e.g. for extra includes (which may be needed if you specify a decorator for the function declarations)
* `decorator`: optional decorator for the function declarations, e.g. `GTK_AVAILABLE` or `GST_EXPORT`
* `function_prefix`: additional prefix for function names, e.g. in case you want to add a leading underscore to functions used only internally
* `body_prefix`: additional prefix at the top of the body file, e.g. for extra includes
Example:
```meson
gnome = import('gnome')
my_headers = ['myheader1.h', 'myheader2.h']
my_sources = ['mysource1.c', 'mysource2.c']
# will generate myenums.c and myenums.h based on enums in myheader1.h and myheader2.h
enums = gnome.mkenums_simple('myenums', sources : my_headers)
mylib = library('my', my_sources, enums,
include_directories: my_incs,
dependencies: my_deps,
c_args: my_cargs,
install: true)
```
*Added 0.42.0*
Returns an array of two elements which are: `[c_source, header_file]`
### gnome.compile_schemas() ### gnome.compile_schemas()
When called, this method will compile the gschemas in the current directory. Note that this is not When called, this method will compile the gschemas in the current directory. Note that this is not

@ -140,3 +140,10 @@ using the `pcap-config` tool. It is used like any other dependency:
```meson ```meson
pcap_dep = dependency('pcap', version : '>=1.0') pcap_dep = dependency('pcap', version : '>=1.0')
``` ```
## GNOME module mkenums_simple() addition
Most libraries and applications use the same standard templates for
glib-mkenums. There is now a new `mkenums_simple()` convenience method
that passes those default templates to glib-mkenums and allows some tweaks
such as optional function decorators or leading underscores.

@ -13,7 +13,7 @@
# limitations under the License. # limitations under the License.
'''This module provides helper functions for Gnome/GLib related '''This module provides helper functions for Gnome/GLib related
functionality such as gobject-introspection and gresources.''' functionality such as gobject-introspection, gresources and gtk-doc'''
from .. import build from .. import build
import os import os
@ -32,7 +32,6 @@ from . import find_program, get_include_args
from . import ExtensionModule from . import ExtensionModule
from . import noKwargs, permittedKwargs from . import noKwargs, permittedKwargs
# gresource compilation is broken due to the way # gresource compilation is broken due to the way
# the resource compiler and Ninja clash about it # the resource compiler and Ninja clash about it
# #
@ -955,6 +954,108 @@ class GnomeModule(ExtensionModule):
else: else:
return ModuleReturnValue(targets, targets) return ModuleReturnValue(targets, targets)
def mkenums_simple(self, state, args, kwargs):
hdr_filename = args[0] + '.h'
body_filename = args[0] + '.c'
# not really needed, just for sanity checking
forbidden_kwargs = ['c_template', 'h_template', 'eprod', 'fhead',
'fprod', 'ftail', 'vhead', 'vtail', 'comments']
for arg in forbidden_kwargs:
if arg in kwargs:
raise MesonException('mkenums_simple() does not take a %s keyword argument' % (arg, ))
# kwargs to pass as-is from mkenums_simple() to mkenums()
shared_kwargs = ['sources', 'install_header', 'install_dir',
'identifier_prefix', 'symbol_prefix']
mkenums_kwargs = {}
for arg in shared_kwargs:
if arg in kwargs:
mkenums_kwargs[arg] = kwargs[arg]
# .c file generation
c_file_kwargs = copy.deepcopy(mkenums_kwargs)
if 'sources' not in kwargs:
raise MesonException('Missing keyword argument "sources".')
sources = kwargs['sources']
if isinstance(sources, str):
sources = [sources]
elif not isinstance(sources, list):
raise MesonException(
'Sources keyword argument must be a string or array.')
header_prefix = kwargs.get('header_prefix', '')
decl_decorator = kwargs.get('decorator', '')
func_prefix = kwargs.get('function_prefix', '')
body_prefix = kwargs.get('body_prefix', '')
# Maybe we should write our own template files into the build dir
# instead, but that seems like much more work, nice as it would be.
fhead = ''
if body_prefix != '':
fhead += '%s\n' % body_prefix
fhead += '#include "%s"\n' % hdr_filename
for hdr in sources:
fhead += '#include "%s"\n' % hdr
fhead += '''
#define C_ENUM(v) ((gint) v)
#define C_FLAGS(v) ((guint) v)
'''
c_file_kwargs['fhead'] = fhead
c_file_kwargs['fprod'] = '''
/* enumerations from "@basename@" */
'''
c_file_kwargs['vhead'] = '''
GType
%s@enum_name@_get_type (void)
{
static volatile gsize gtype_id = 0;
static const G@Type@Value values[] = {''' % func_prefix
c_file_kwargs['vprod'] = ' { C_@TYPE@(@VALUENAME@), "@VALUENAME@", "@valuenick@" },'
c_file_kwargs['vtail'] = ''' { 0, NULL, NULL }
};
if (g_once_init_enter (&gtype_id)) {
GType new_type = g_@type@_register_static ("@EnumName@", values);
g_once_init_leave (&gtype_id, new_type);
}
return (GType) gtype_id;
}'''
rv = self.mkenums(state, [body_filename], c_file_kwargs)
c_file = rv.return_value
# .h file generation
h_file_kwargs = copy.deepcopy(mkenums_kwargs)
h_file_kwargs['fhead'] = '''#pragma once
#include <glib-object.h>
{}
G_BEGIN_DECLS
'''.format(header_prefix)
h_file_kwargs['fprod'] = '''
/* enumerations from "@basename@" */
'''
h_file_kwargs['vhead'] = '''
{}
GType {}@enum_name@_get_type (void);
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ ({}@enum_name@_get_type())'''.format(decl_decorator, func_prefix, func_prefix)
h_file_kwargs['ftail'] = '''
G_END_DECLS'''
rv = self.mkenums(state, [hdr_filename], h_file_kwargs)
h_file = rv.return_value
return ModuleReturnValue([c_file, h_file], [c_file, h_file])
@staticmethod @staticmethod
def _make_mkenum_custom_target(state, sources, output, cmd, kwargs): def _make_mkenum_custom_target(state, sources, output, cmd, kwargs):
custom_kwargs = { custom_kwargs = {

@ -0,0 +1,35 @@
#include <stdio.h>
#include <string.h>
#include <glib-object.h>
#include "enums4.h"
#include "meson-sample.h"
int main(int argc, char **argv) {
GEnumClass *xenum = g_type_class_ref(MESON_TYPE_THE_XENUM);
GFlagsClass *flags_enum = g_type_class_ref(MESON_TYPE_THE_FLAGS_ENUM);
if (g_enum_get_value_by_name(xenum, "MESON_THE_XVALUE")->value != MESON_THE_XVALUE) {
fprintf(stderr, "Get MESON_THE_XVALUE by name failed.\n");
return 1;
}
if (g_enum_get_value_by_nick(xenum, "the-xvalue")->value != MESON_THE_XVALUE) {
fprintf(stderr, "Get MESON_THE_XVALUE by nick failed.\n");
return 2;
}
if (g_flags_get_value_by_name(flags_enum, "MESON_THE_FIRST_VALUE")->value != MESON_THE_FIRST_VALUE) {
fprintf(stderr, "Get MESON_THE_FIRST_VALUE by name failed.\n");
return 3;
}
if (g_flags_get_value_by_nick(flags_enum, "the-first-value")->value != MESON_THE_FIRST_VALUE) {
fprintf(stderr, "Get MESON_THE_FIRST_VALUE by nick failed.\n");
return 4;
}
/* Make sure that funcs are generated with leading underscore as requested */
if (!_meson_the_xenum_get_type())
g_error ("Bad!");
g_type_class_unref(xenum);
g_type_class_unref(flags_enum);
fprintf(stderr, "All ok.\n");
return 0;
}

@ -0,0 +1,35 @@
#include <stdio.h>
#include <string.h>
#include <glib-object.h>
#include "enums5.h"
#include "meson-sample.h"
int main(int argc, char **argv) {
GEnumClass *xenum = g_type_class_ref(MESON_TYPE_THE_XENUM);
GFlagsClass *flags_enum = g_type_class_ref(MESON_TYPE_THE_FLAGS_ENUM);
if (g_enum_get_value_by_name(xenum, "MESON_THE_XVALUE")->value != MESON_THE_XVALUE) {
fprintf(stderr, "Get MESON_THE_XVALUE by name failed.\n");
return 1;
}
if (g_enum_get_value_by_nick(xenum, "the-xvalue")->value != MESON_THE_XVALUE) {
fprintf(stderr, "Get MESON_THE_XVALUE by nick failed.\n");
return 2;
}
if (g_flags_get_value_by_name(flags_enum, "MESON_THE_FIRST_VALUE")->value != MESON_THE_FIRST_VALUE) {
fprintf(stderr, "Get MESON_THE_FIRST_VALUE by name failed.\n");
return 3;
}
if (g_flags_get_value_by_nick(flags_enum, "the-first-value")->value != MESON_THE_FIRST_VALUE) {
fprintf(stderr, "Get MESON_THE_FIRST_VALUE by nick failed.\n");
return 4;
}
/* Make sure that funcs do not have any extra prefix */
if (!meson_the_xenum_get_type())
g_error ("Bad!");
g_type_class_unref(xenum);
g_type_class_unref(flags_enum);
fprintf(stderr, "All ok.\n");
return 0;
}

@ -0,0 +1,2 @@
#pragma once
#define MESON_EXPORT extern

@ -117,3 +117,12 @@ main = configure_file(
enumexe3 = executable('enumprog3', main, enums_c3, enums_h3, enumexe3 = executable('enumprog3', main, enums_c3, enums_h3,
dependencies : gobj) dependencies : gobj)
test('enum test 3', enumexe3) test('enum test 3', enumexe3)
enums4 = gnome.mkenums_simple('enums4', sources : 'meson-sample.h',
function_prefix : '_')
enumexe4 = executable('enumprog4', 'main4.c', enums4, dependencies : gobj)
enums5 = gnome.mkenums_simple('enums5', sources : 'meson-sample.h',
decorator : 'MESON_EXPORT',
header_prefix : '#include "meson-decls.h"')
enumexe5 = executable('enumprog5', main, enums5, dependencies : gobj)

Loading…
Cancel
Save