mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-13 07:56:17 +01:00
gdbus-codegen: Add a --glib-min-version argument
This can be used by callers to opt-in to backwards-incompatible changes to the behaviour or output of `gdbus-codegen` in future. This commit doesn’t introduce any such changes, though. Documentation and unit tests included. Signed-off-by: Philip Withnall <withnall@endlessm.com> Helps: #1726
This commit is contained in:
parent
41cabfaa98
commit
90f0733858
@ -50,6 +50,7 @@
|
|||||||
<replaceable>VALUE</replaceable>
|
<replaceable>VALUE</replaceable>
|
||||||
</arg>
|
</arg>
|
||||||
</group>
|
</group>
|
||||||
|
<arg><option>--glib-min-version</option> <replaceable>VERSION</replaceable></arg>
|
||||||
<arg choice="plain">FILE</arg>
|
<arg choice="plain">FILE</arg>
|
||||||
<arg>
|
<arg>
|
||||||
<arg choice="plain" rep="repeat">FILE</arg>
|
<arg choice="plain" rep="repeat">FILE</arg>
|
||||||
@ -420,6 +421,30 @@ gdbus-codegen --c-namespace MyApp \
|
|||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry>
|
||||||
|
<term><option>--glib-min-version</option> <replaceable>VERSION</replaceable></term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Specifies the minimum version of GLib which the code generated by
|
||||||
|
<command>gdbus-codegen</command> can depend on. This may be used to
|
||||||
|
make backwards-incompatible changes in the output or behaviour of
|
||||||
|
<command>gdbus-codegen</command> in future, which users may opt in to
|
||||||
|
by increasing the value they pass for <option>--glib-min-version</option>.
|
||||||
|
If this option is not passed, the output from <command>gdbus-codegen</command>
|
||||||
|
is guaranteed to be compatible with all versions of GLib from 2.30
|
||||||
|
upwards, as that is when <command>gdbus-codegen</command> was first
|
||||||
|
released.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
The version number must be of the form
|
||||||
|
<literal><replaceable>MAJOR</replaceable>.<replaceable>MINOR</replaceable>.<replaceable>MICRO</replaceable></literal>,
|
||||||
|
where all parts are integers. <replaceable>MINOR</replaceable> and
|
||||||
|
<replaceable>MICRO</replaceable> are optional. The version number may not be smaller
|
||||||
|
than <literal>2.30</literal>.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
|
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</refsect1>
|
</refsect1>
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ def generate_header_guard(header_name):
|
|||||||
class HeaderCodeGenerator:
|
class HeaderCodeGenerator:
|
||||||
def __init__(self, ifaces, namespace, generate_objmanager,
|
def __init__(self, ifaces, namespace, generate_objmanager,
|
||||||
generate_autocleanup, header_name, input_files_basenames,
|
generate_autocleanup, header_name, input_files_basenames,
|
||||||
use_pragma, outfile):
|
use_pragma, glib_min_version, outfile):
|
||||||
self.ifaces = ifaces
|
self.ifaces = ifaces
|
||||||
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
||||||
self.generate_objmanager = generate_objmanager
|
self.generate_objmanager = generate_objmanager
|
||||||
@ -70,6 +70,7 @@ class HeaderCodeGenerator:
|
|||||||
self.header_guard = generate_header_guard(header_name)
|
self.header_guard = generate_header_guard(header_name)
|
||||||
self.input_files_basenames = input_files_basenames
|
self.input_files_basenames = input_files_basenames
|
||||||
self.use_pragma = use_pragma
|
self.use_pragma = use_pragma
|
||||||
|
self.glib_min_version = glib_min_version
|
||||||
self.outfile = outfile
|
self.outfile = outfile
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------
|
||||||
@ -618,12 +619,13 @@ class HeaderCodeGenerator:
|
|||||||
# ----------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class InterfaceInfoHeaderCodeGenerator:
|
class InterfaceInfoHeaderCodeGenerator:
|
||||||
def __init__(self, ifaces, namespace, header_name, input_files_basenames, use_pragma, outfile):
|
def __init__(self, ifaces, namespace, header_name, input_files_basenames, use_pragma, glib_min_version, outfile):
|
||||||
self.ifaces = ifaces
|
self.ifaces = ifaces
|
||||||
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
||||||
self.header_guard = generate_header_guard(header_name)
|
self.header_guard = generate_header_guard(header_name)
|
||||||
self.input_files_basenames = input_files_basenames
|
self.input_files_basenames = input_files_basenames
|
||||||
self.use_pragma = use_pragma
|
self.use_pragma = use_pragma
|
||||||
|
self.glib_min_version = glib_min_version
|
||||||
self.outfile = outfile
|
self.outfile = outfile
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------
|
||||||
@ -671,11 +673,12 @@ class InterfaceInfoHeaderCodeGenerator:
|
|||||||
# ----------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
class InterfaceInfoBodyCodeGenerator:
|
class InterfaceInfoBodyCodeGenerator:
|
||||||
def __init__(self, ifaces, namespace, header_name, input_files_basenames, outfile):
|
def __init__(self, ifaces, namespace, header_name, input_files_basenames, glib_min_version, outfile):
|
||||||
self.ifaces = ifaces
|
self.ifaces = ifaces
|
||||||
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
||||||
self.header_name = header_name
|
self.header_name = header_name
|
||||||
self.input_files_basenames = input_files_basenames
|
self.input_files_basenames = input_files_basenames
|
||||||
|
self.glib_min_version = glib_min_version
|
||||||
self.outfile = outfile
|
self.outfile = outfile
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------
|
||||||
@ -903,13 +906,14 @@ class InterfaceInfoBodyCodeGenerator:
|
|||||||
|
|
||||||
class CodeGenerator:
|
class CodeGenerator:
|
||||||
def __init__(self, ifaces, namespace, generate_objmanager, header_name,
|
def __init__(self, ifaces, namespace, generate_objmanager, header_name,
|
||||||
input_files_basenames, docbook_gen, outfile):
|
input_files_basenames, docbook_gen, glib_min_version, outfile):
|
||||||
self.ifaces = ifaces
|
self.ifaces = ifaces
|
||||||
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
self.namespace, self.ns_upper, self.ns_lower = generate_namespace(namespace)
|
||||||
self.generate_objmanager = generate_objmanager
|
self.generate_objmanager = generate_objmanager
|
||||||
self.header_name = header_name
|
self.header_name = header_name
|
||||||
self.input_files_basenames = input_files_basenames
|
self.input_files_basenames = input_files_basenames
|
||||||
self.docbook_gen = docbook_gen
|
self.docbook_gen = docbook_gen
|
||||||
|
self.glib_min_version = glib_min_version
|
||||||
self.outfile = outfile
|
self.outfile = outfile
|
||||||
|
|
||||||
# ----------------------------------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------------------------------
|
||||||
|
@ -167,6 +167,8 @@ def codegen_main():
|
|||||||
help='Use "pragma once" as the inclusion guard')
|
help='Use "pragma once" as the inclusion guard')
|
||||||
arg_parser.add_argument('--annotate', nargs=3, action='append', metavar='WHAT KEY VALUE',
|
arg_parser.add_argument('--annotate', nargs=3, action='append', metavar='WHAT KEY VALUE',
|
||||||
help='Add annotation (may be used several times)')
|
help='Add annotation (may be used several times)')
|
||||||
|
arg_parser.add_argument('--glib-min-version', metavar='VERSION',
|
||||||
|
help='Minimum version of GLib to be supported by the outputted code (default: 2.30)')
|
||||||
|
|
||||||
group = arg_parser.add_mutually_exclusive_group()
|
group = arg_parser.add_mutually_exclusive_group()
|
||||||
group.add_argument('--generate-c-code', metavar='OUTFILES',
|
group.add_argument('--generate-c-code', metavar='OUTFILES',
|
||||||
@ -233,6 +235,27 @@ def codegen_main():
|
|||||||
c_file = args.output
|
c_file = args.output
|
||||||
header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h'
|
header_name = os.path.splitext(os.path.basename(c_file))[0] + '.h'
|
||||||
|
|
||||||
|
# Check the minimum GLib version. The minimum --glib-min-version is 2.30,
|
||||||
|
# because that’s when gdbus-codegen was introduced. Support 1, 2 or 3
|
||||||
|
# component versions, but ignore the micro component if it’s present.
|
||||||
|
if args.glib_min_version:
|
||||||
|
try:
|
||||||
|
parts = args.glib_min_version.split('.', 3)
|
||||||
|
glib_min_version = (int(parts[0]),
|
||||||
|
int(parts[1] if len(parts) > 1 else 0))
|
||||||
|
# Ignore micro component, but still validate it:
|
||||||
|
_ = int(parts[2] if len(parts) > 2 else 0)
|
||||||
|
except (ValueError, IndexError):
|
||||||
|
print_error('Unrecognized --glib-min-version string ‘{}’'.format(
|
||||||
|
args.glib_min_version))
|
||||||
|
|
||||||
|
if glib_min_version[0] < 2 or \
|
||||||
|
(glib_min_version[0] == 2 and glib_min_version[1] < 30):
|
||||||
|
print_error('Invalid --glib-min-version string ‘{}’: minimum '
|
||||||
|
'version is 2.30'.format(args.glib_min_version))
|
||||||
|
else:
|
||||||
|
glib_min_version = (2, 30)
|
||||||
|
|
||||||
all_ifaces = []
|
all_ifaces = []
|
||||||
input_files_basenames = []
|
input_files_basenames = []
|
||||||
for fname in sorted(args.files + args.xml_files):
|
for fname in sorted(args.files + args.xml_files):
|
||||||
@ -262,6 +285,7 @@ def codegen_main():
|
|||||||
header_name,
|
header_name,
|
||||||
input_files_basenames,
|
input_files_basenames,
|
||||||
args.pragma_once,
|
args.pragma_once,
|
||||||
|
glib_min_version,
|
||||||
outfile)
|
outfile)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
@ -273,6 +297,7 @@ def codegen_main():
|
|||||||
header_name,
|
header_name,
|
||||||
input_files_basenames,
|
input_files_basenames,
|
||||||
docbook_gen,
|
docbook_gen,
|
||||||
|
glib_min_version,
|
||||||
outfile)
|
outfile)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
@ -283,6 +308,7 @@ def codegen_main():
|
|||||||
header_name,
|
header_name,
|
||||||
input_files_basenames,
|
input_files_basenames,
|
||||||
args.pragma_once,
|
args.pragma_once,
|
||||||
|
glib_min_version,
|
||||||
outfile)
|
outfile)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
@ -292,6 +318,7 @@ def codegen_main():
|
|||||||
args.c_namespace,
|
args.c_namespace,
|
||||||
header_name,
|
header_name,
|
||||||
input_files_basenames,
|
input_files_basenames,
|
||||||
|
glib_min_version,
|
||||||
outfile)
|
outfile)
|
||||||
gen.generate()
|
gen.generate()
|
||||||
|
|
||||||
|
@ -362,6 +362,41 @@ G_END_DECLS
|
|||||||
# The output should be the same.
|
# The output should be the same.
|
||||||
self.assertEqual(result1.out, result2.out)
|
self.assertEqual(result1.out, result2.out)
|
||||||
|
|
||||||
|
def test_glib_min_version_invalid(self):
|
||||||
|
"""Test running with an invalid --glib-min-version."""
|
||||||
|
with self.assertRaises(subprocess.CalledProcessError):
|
||||||
|
self.runCodegenWithInterface('',
|
||||||
|
'--output', '/dev/stdout',
|
||||||
|
'--body',
|
||||||
|
'--glib-min-version', 'hello mum')
|
||||||
|
|
||||||
|
def test_glib_min_version_too_low(self):
|
||||||
|
"""Test running with a --glib-min-version which is too low (and hence
|
||||||
|
probably a typo)."""
|
||||||
|
with self.assertRaises(subprocess.CalledProcessError):
|
||||||
|
self.runCodegenWithInterface('',
|
||||||
|
'--output', '/dev/stdout',
|
||||||
|
'--body',
|
||||||
|
'--glib-min-version', '2.6')
|
||||||
|
|
||||||
|
def test_glib_min_version_major_only(self):
|
||||||
|
"""Test running with a --glib-min-version which contains only a major version."""
|
||||||
|
result = self.runCodegenWithInterface('',
|
||||||
|
'--output', '/dev/stdout',
|
||||||
|
'--header',
|
||||||
|
'--glib-min-version', '3')
|
||||||
|
self.assertEqual('', result.err)
|
||||||
|
self.assertNotEqual('', result.out.strip())
|
||||||
|
|
||||||
|
def test_glib_min_version_with_micro(self):
|
||||||
|
"""Test running with a --glib-min-version which contains a micro version."""
|
||||||
|
result = self.runCodegenWithInterface('',
|
||||||
|
'--output', '/dev/stdout',
|
||||||
|
'--header',
|
||||||
|
'--glib-min-version', '2.46.2')
|
||||||
|
self.assertEqual('', result.err)
|
||||||
|
self.assertNotEqual('', result.out.strip())
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|
unittest.main(testRunner=taptestrunner.TAPTestRunner())
|
||||||
|
Loading…
Reference in New Issue
Block a user