<para><command>glib-mkenums</command> is a small utility that parses C code to
extract enum definitions and produces enum descriptions based on text templates
specified by the user. Typically, you can use this tool to generate enumeration
-types for the GType type system, for #GObject properties and signal marshalling;
-additionally, you can use it to generate enumeration values of #GSettings schemas.
+types for the GType type system, for GObject properties and signal marshalling;
+additionally, you can use it to generate enumeration values of GSettings schemas.
</para>
<para><command>glib-mkenums</command> takes a list of valid C code files as
input. The options specified control the text that generated, substituting various
-keywords enclosed in @ characters in the templates.
+keywords enclosed in <literal>@</literal> characters in the templates.
</para>
<refsect2><title>Production text substitutions</title>
<para>
-Certain keywords enclosed in @ characters will be substituted in the
+Certain keywords enclosed in <literal>@</literal> characters will be substituted in the
emitted text. For the substitution examples of the keywords below,
the following example enum definition is assumed:
+</para>
<informalexample><programlisting>
typedef enum
{
</programlisting></informalexample>
<variablelist>
<varlistentry>
-<term>@EnumName@</term>
+<term><literal>@EnumName@</literal>></term>
<listitem><para>
The name of the enum currently being processed, enum names are assumed to be
properly namespaced and to use mixed capitalization to separate
</varlistentry>
<varlistentry>
-<term>@enum_name@</term>
+<term><literal>@enum_name@</literal></term>
<listitem><para>
The enum name with words lowercase and word-separated by underscores
(e.g. <literal>prefix_the_xenum</literal>).
</varlistentry>
<varlistentry>
-<term>@ENUMNAME@</term>
+<term><literal>@ENUMNAME@</literal></term>
<listitem><para>
The enum name with words uppercase and word-separated by underscores
(e.g. <literal>PREFIX_THE_XENUM</literal>).
</varlistentry>
<varlistentry>
-<term>@ENUMSHORT@</term>
+<term><literal>@ENUMSHORT@</literal></term>
<listitem><para>
The enum name with words uppercase and word-separated by underscores,
prefix stripped (e.g. <literal>THE_XENUM</literal>).
</varlistentry>
<varlistentry>
-<term>@ENUMPREFIX@</term>
+<term><literal>@ENUMPREFIX@</literal></term>
<listitem><para>
The prefix of the enum name (e.g. <literal>PREFIX</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
-<term>@VALUENAME@</term>
+<term><literal>@VALUENAME@</literal></term>
<listitem><para>
The enum value name currently being processed with words uppercase and
word-separated by underscores,
</varlistentry>
<varlistentry>
-<term>@valuenick@</term>
+<term><literal>@valuenick@</literal></term>
<listitem><para>
A nick name for the enum value currently being processed, this is usually
generated by stripping common prefix words of all the enum values of the
</varlistentry>
<varlistentry>
-<term>@valuenum@</term>
+<term><literal>@valuenum@</literal></term>
<listitem><para>
The integer value for the enum value currently being processed. If the
evaluation fails then <command>glib-mkenums</command> will exit with an
</varlistentry>
<varlistentry>
-<term>@type@</term>
+<term><literal>@type@</literal></term>
<listitem><para>
This is substituted either by "enum" or "flags", depending on whether the
-enum value definitions contained bit-shift operators or not (e.g. flags).
+enum value definitions contained bit-shift operators or not (e.g. <literal>flags</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
-<term>@Type@</term>
+<term><literal>@Type@</literal></term>
<listitem><para>
-The same as <literal>@type@</literal> with the first letter capitalized (e.g. Flags).
+The same as <literal>@type@</literal> with the first letter capitalized (e.g. <literal>Flags</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
-<term>@TYPE@</term>
+<term><literal>@TYPE@</literal></term>
<listitem><para>
-The same as <literal>@type@</literal> with all letters uppercased (e.g. FLAGS).
+The same as <literal>@type@</literal> with all letters uppercased (e.g. <literal>FLAGS</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
-<term>@filename@</term>
+<term><literal>@filename@</literal></term>
<listitem><para>
-The name of the input file currently being processed (e.g. foo.h).
+The full path of the input file currently being processed (e.g. <literal>/build/environment/project/src/foo.h</literal>).
</para></listitem>
</varlistentry>
<varlistentry>
-<term>@basename@</term>
+<term><literal>@basename@</literal></term>
<listitem><para>
-The base name of the input file currently being processed (e.g. foo.h). Typically
-you want to use <literal>@basename@</literal> in place of <literal>@filename@</literal> in your templates, to improve the reproducibility of the build. (Since: 2.22)
+The base name of the input file currently being processed (e.g. <literal>foo.h</literal>).
+Typically you want to use <literal>@basename@</literal> in place of <literal>@filename@</literal>
+in your templates, to improve the reproducibility of the build. (Since: 2.22)
</para></listitem>
</varlistentry>
</variablelist>
-</para>
</refsect2>
<refsect2><title>Trigraph extensions</title>
<para>
Some C comments are treated specially in the parsed enum definitions,
such comments start out with the trigraph sequence <literal>/*<</literal>
and end with the trigraph sequence <literal>>*/</literal>.
-Per enum definition, the options "skip" and "flags" can be specified, to
-indicate this enum definition to be skipped, or for it to be treated as
-a flags definition, or to specify the common prefix to be stripped from
-all values to generate value nicknames, respectively. The "underscore_name"
-option can be used to specify the word separation used in the *_get_type()
-function. For instance, <literal>/*< underscore_name=gnome_vfs_uri_hide_options >*/</literal>.
</para>
-<para>
-Per value definition, the options "skip" and "nick" are supported.
-The former causes the value to be skipped, and the latter can be used to
-specify the otherwise auto-generated nickname.
-Examples:
+
+<para>The following options can be specified per enum definition:</para>
+<variablelist>
+<varlistentry>
+<term><literal>skip</literal></term>
+<listitem><para>
+Indicates this enum definition should be skipped.
+</para></listitem>
+</varlistentry>
+<varlistentry>
+<term><literal>flags</literal></term>
+<listitem><para>
+Indicates this enum should be treated as a flags definition.
+</para></listitem>
+</varlistentry>
+<varlistentry>
+<term><literal>underscore_name</literal></term>
+<listitem><para>
+Specifies the word separation used in the <function>*_get_type()</function>
+function. For instance, <literal>/*< underscore_name=gnome_vfs_uri_hide_options >*/</literal>.
+</para></listitem>
+</varlistentry>
+<varlistentry>
+<term><literal>since</literal></term>
+<listitem><para>
+Specifies the version tag that will be used to substitute the <literal>@enumsince@</literal>
+keyword in the template, useful when documenting methods generated from the enums
+(e.g. <literal>Since: @enumsince@</literal>). (Since: 2.66)
+</para></listitem>
+</varlistentry>
+</variablelist>
+
+<para>The following options can be specified per value definition:</para>
+<variablelist>
+<varlistentry>
+<term><literal>skip</literal></term>
+<listitem><para>
+Indicates the value should be skipped.
+</para></listitem>
+</varlistentry>
+<varlistentry>
+<term><literal>nick</literal></term>
+<listitem><para>
+Specifies the otherwise auto-generated nickname.
+</para></listitem>
+</varlistentry>
+</variablelist>
+
+<para>Examples:</para>
<informalexample><programlisting>
typedef enum /*< skip >*/
{
PREFIX_FOO
} PrefixThisEnumWillBeSkipped;
-typedef enum /*< flags,prefix=PREFIX >*/
+typedef enum /*< flags,prefix=PREFIX,since=1.0 >*/
{
PREFIX_THE_ZEROTH_VALUE, /*< skip >*/
PREFIX_THE_FIRST_VALUE,
PREFIX_THE_THIRD_VALUE, /*< nick=the-last-value >*/
} PrefixTheFlagsEnum;
</programlisting></informalexample>
-</para>
</refsect2>
</refsect1>
<term><option>--template</option> <replaceable>FILE</replaceable></term>
<listitem><para>
Read templates from the given file. The templates are enclosed in
-specially-formatted C comments
+specially-formatted C comments:
+</para>
<informalexample><programlisting>
/*** BEGIN section ***/
/*** END section ***/
</programlisting></informalexample>
-where section may be <literal>file-header</literal>,
+<para>
+<replaceable>section</replaceable> may be <literal>file-header</literal>,
<literal>file-production</literal>, <literal>file-tail</literal>,
<literal>enumeration-production</literal>, <literal>value-header</literal>,
<literal>value-production</literal>, <literal>value-tail</literal> or
</variablelist>
</refsect1>
-<refsect1><title>Using glib-mkenums with Autotools</title>
+<refsect1><title>Using templates</title>
<para>
-In order to use <command>glib-mkenums</command> in your project when using
-Autotools as the build system, you will first need to modify your
-<filename>configure.ac</filename> file to ensure you find the appropriate
-command using <command>pkg-config</command>, similarly as to how you discover
-the compiler and linker flags for GLib.
-</para>
-<informalexample><programlisting>
-PKG_PROG_PKG_CONFIG([0.28])
-
-PKG_CHECK_VAR([GLIB_MKENUMS], [glib-2.0], [glib_mkenums])
-</programlisting></informalexample>
-<para>
-In your <filename>Makefile.am</filename> file you will typically use rules
-like these:
+Instead of passing the various sections of the generated file to the command
+line of <command>glib-mkenums</command>, it's strongly recommended to use a
+template file, especially for generating C sources.
</para>
-<informalexample><programlisting>
-# A list of headers to inspect
-project_headers = \
- project-foo.h \
- project-bar.h \
- project-baz.h
-
-enum-types.h: $(project_headers) enum-types.h.in
- $(AM_V_GEN)$(GLIB_MKENUMS) \
- --template=enum-types.h.in \
- --output=$@ \
- $(project_headers)
-
-enum-types.c: $(project_headers) enum-types.c.in enum-types.h
- $(AM_V_GEN)$(GLIB_MKENUMS) \
- --template=enum-types.c.in \
- --output=$@ \
- $(project_headers)
-BUILT_SOURCES += enum-types.h enum-types.c
-CLEANFILES += enum-types.h enum-types.c
-EXTRA_DIST += enum-types.h.in enum-types.c.in
-</programlisting></informalexample>
<para>
-In the example above, we have a variable called <literal>project_headers</literal>
-where we reference all header files we want to inspect for generating enumeration
-GTypes. In the <filename>enum-types.h</filename> rule we use <command>glib-mkenums</command>
-with a template called <filename>enum-types.h.in</filename> in order to generate the
-header file; a header template file will typically look like this:
+A C header template file will typically look like this:
</para>
<informalexample><programlisting>
/*** BEGIN file-header ***/
/*** BEGIN file-production ***/
-/* enumerations from "@filename@" */
+/* enumerations from "@basename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
G_END_DECLS
/*** END file-tail ***/
</programlisting></informalexample>
+
<para>
-The <filename>enum-types.c</filename> rule is similar to the rule for the
-header file, but will use a different <filename>enum-types.c.in</filename> template
-file, similar to this:
+A C source template file will typically look like this:
</para>
<informalexample><programlisting>
/*** BEGIN file-header ***/
/*** END file-header ***/
/*** BEGIN file-production ***/
-/* enumerations from "@filename@" */
+/* enumerations from "@basename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
{
- static volatile gsize g_@type@_type_id__volatile;
+ static gsize static_g_@type@_type_id;
- if (g_once_init_enter (&g_define_type_id__volatile))
+ if (g_once_init_enter (&static_g_@type@_type_id))
{
static const G@Type@Value values[] = {
/*** END value-header ***/
GType g_@type@_type_id =
g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
- g_once_init_leave (&g_@type@_type_id__volatile, g_@type@_type_id);
+ g_once_init_leave (&static_g_@type@_type_id, g_@type@_type_id);
}
- return g_@type@_type_id__volatile;
+ return static_g_@type@_type_id;
}
/*** END value-tail ***/
</programlisting></informalexample>
+
+<para>
+Template files are easier to modify and update, and can be used
+to generate various types of outputs using the same command line
+or tools during the build.
+</para>
+</refsect1>
+
+<refsect1><title>Using glib-mkenums with Meson</title>
+<para>
+Meson supports generating enumeration types using <command>glib-mkenums</command>
+out of the box in its "gnome" module.
+</para>
+
+<para>
+In your <filename>meson.build</filename> file you will typically call the
+<literal>gnome.mkenums_simple()</literal> method to generate idiomatic enumeration
+types from a list of headers to inspect:
+</para>
+<informalexample><programlisting>
+project_headers = [
+ 'project-foo.h',
+ 'project-bar.h',
+ 'project-baz.h',
+]
+
+gnome = import('gnome')
+enum_files = gnome.mkenums_simple('enum-types',
+ sources: project_headers,
+)
+</programlisting></informalexample>
+
+<para>
+The <literal>enum_files</literal> variable will contain an array of two elements
+in the following order:
+</para>
+<itemizedlist>
+ <listitem><para>a build target for the source file</para></listitem>
+ <listitem><para>a build target for the header file</para></listitem>
+</itemizedlist>
+<para>
+You should use the returned objects to provide a dependency on every other
+build target that references the source or header file; for instance, if you
+are using the source to build a library:
+</para>
+<informalexample><programlisting>
+mainlib = library('project',
+ sources: project_sources + enum_files,
+ ...
+)
+</programlisting></informalexample>
+<para>
+Additionally, if you are including the generated header file inside a build
+target that depends on the library you just built, you must ensure that the
+internal dependency includes the generated header as a required source file:
+</para>
+<informalexample><programlisting>
+mainlib_dep = declare_dependency(sources: enum_files[1], link_with: mainlib)
+</programlisting></informalexample>
+<para>
+You should not include the generated source file as well, otherwise it will
+be built separately for every target that depends on it, causing build
+failures. To know more about why all this is required, please refer to the
+<ulink url="https://mesonbuild.com/FAQ.html#how-do-i-tell-meson-that-my-sources-use-generated-headers">
+corresponding Meson FAQ entry</ulink>.
+</para>
+
+<para>
+If you are generating C header and source files that require special
+templates, you can use <literal>gnome.mkenums()</literal> to provide those
+headers, for instance:
+</para>
+<informalexample><programlisting>
+enum_files = gnome.mkenums('enum-types',
+ sources: project_headers,
+ h_template: 'enum-types.h.in',
+ c_template: 'enum-types.c.in',
+ install_header: true,
+)
+</programlisting></informalexample>
+<para>
+For more information, see the <ulink url="https://mesonbuild.com/Gnome-module.html#gnomegenmarshal">Meson
+documentation for <literal>gnome.mkenums()</literal></ulink>.
+</para>
+</refsect1>
+
+<refsect1><title>Using glib-mkenums with Autotools</title>
+<para>
+In order to use <command>glib-mkenums</command> in your project when using
+Autotools as the build system, you will first need to modify your
+<filename>configure.ac</filename> file to ensure you find the appropriate
+command using <command>pkg-config</command>, similarly as to how you discover
+the compiler and linker flags for GLib.
+</para>
+<informalexample><programlisting>
+PKG_PROG_PKG_CONFIG([0.28])
+
+PKG_CHECK_VAR([GLIB_MKENUMS], [glib-2.0], [glib_mkenums])
+</programlisting></informalexample>
+<para>
+In your <filename>Makefile.am</filename> file you will typically use rules
+like these:
+</para>
+<informalexample><programlisting>
+# A list of headers to inspect
+project_headers = \
+ project-foo.h \
+ project-bar.h \
+ project-baz.h
+
+enum-types.h: $(project_headers) enum-types.h.in
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --template=enum-types.h.in \
+ --output=$@ \
+ $(project_headers)
+
+enum-types.c: $(project_headers) enum-types.c.in enum-types.h
+ $(AM_V_GEN)$(GLIB_MKENUMS) \
+ --template=enum-types.c.in \
+ --output=$@ \
+ $(project_headers)
+
+# Build the enum types files before every other target
+BUILT_SOURCES += enum-types.h enum-types.c
+CLEANFILES += enum-types.h enum-types.c
+EXTRA_DIST += enum-types.h.in enum-types.c.in
+</programlisting></informalexample>
+<para>
+In the example above, we have a variable called <literal>project_headers</literal>
+where we reference all header files we want to inspect for generating enumeration
+GTypes. In the <filename>enum-types.h</filename> rule we use <command>glib-mkenums</command>
+with a template called <filename>enum-types.h.in</filename> in order to generate the
+header file; similarly, in the <filename>enum-types.c</filename> rule we use a
+template called <filename>enum-types.c.in</filename>.
+</para>
</refsect1>
<refsect1><title>See also</title>