gdbus-codegen: Add --glib-max-allowed argument

This complements the `--glib-min-required` argument, just like the
`GLIB_MIN_REQUIRED` and `GLIB_MAX_ALLOWED` preprocessor defines which
control access to APIs in C.

Currently, it doesn’t affect code generation at all. When we next change
code generation, we will need to gate any new API usage on this
argument.

Signed-off-by: Philip Withnall <withnall@endlessm.com>

Fixes: #1993
This commit is contained in:
Philip Withnall 2020-01-27 10:36:03 +00:00
parent 4d1c3e15f9
commit 9734e4854e
5 changed files with 101 additions and 1 deletions

View File

@ -51,6 +51,7 @@
</arg>
</group>
<arg><option>--glib-min-required</option> <replaceable>VERSION</replaceable></arg>
<arg><option>--glib-max-allowed</option> <replaceable>VERSION</replaceable></arg>
<arg choice="plain">FILE</arg>
<arg>
<arg choice="plain" rep="repeat">FILE</arg>
@ -460,6 +461,27 @@ gdbus-codegen --c-namespace MyApp \
</listitem>
</varlistentry>
<varlistentry>
<term><option>--glib-max-allowed</option> <replaceable>VERSION</replaceable></term>
<listitem>
<para>
Specifies the maximum version of GLib which the code generated by
<command>gdbus-codegen</command> can depend on. This may be used to
ensure that code generated by <command>gdbus-codegen</command> is
compilable with specific older versions of GLib that your software has
to support.
</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 must
be greater than or equal to that passed to <option>--glib-min-required</option>.
It defaults to the version of GLib which provides this <command>gdbus-codegen</command>.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>

View File

@ -169,6 +169,8 @@ def codegen_main():
help='Add annotation (may be used several times)')
arg_parser.add_argument('--glib-min-required', metavar='VERSION',
help='Minimum version of GLib to be supported by the outputted code (default: 2.30)')
arg_parser.add_argument('--glib-max-allowed', metavar='VERSION',
help='Maximum version of GLib to be used by the outputted code (default: current GLib version)')
group = arg_parser.add_mutually_exclusive_group()
group.add_argument('--generate-c-code', metavar='OUTFILES',
@ -256,6 +258,28 @@ def codegen_main():
else:
glib_min_required = (2, 30)
# And the maximum GLib version.
if args.glib_max_allowed:
try:
parts = args.glib_max_allowed.split('.', 3)
glib_max_allowed = (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-max-allowed string {}'.format(
args.glib_max_allowed))
else:
glib_max_allowed = (config.MAJOR_VERSION, config.MINOR_VERSION)
# Round --glib-max-allowed up to the next stable release.
glib_max_allowed = \
(glib_max_allowed[0], glib_max_allowed[1] + (glib_max_allowed[1] % 2))
if glib_max_allowed < glib_min_required:
print_error('Invalid versions: --glib-min-required ({}) must be '
'less than or equal to --glib-max-allowed ({})'.format(glib_min_required, glib_max_allowed))
glib_min_required_is_2_64 = (glib_min_required[0] > 2 or
(glib_min_required[0] == 2 and
glib_min_required[1] >= 64))

View File

@ -20,3 +20,5 @@
# Author: David Zeuthen <davidz@redhat.com>
VERSION = "@VERSION@"
MAJOR_VERSION = @MAJOR_VERSION@
MINOR_VERSION = @MINOR_VERSION@

View File

@ -10,6 +10,8 @@ gdbus_codegen_files = [
gdbus_codegen_conf = configuration_data()
gdbus_codegen_conf.set('VERSION', glib_version)
gdbus_codegen_conf.set('MAJOR_VERSION', major_version)
gdbus_codegen_conf.set('MINOR_VERSION', minor_version)
gdbus_codegen_conf.set('PYTHON', python_name)
gdbus_codegen_conf.set('DATADIR', glib_datadir)

View File

@ -384,7 +384,8 @@ G_END_DECLS
result = self.runCodegenWithInterface('',
'--output', '/dev/stdout',
'--header',
'--glib-min-required', '3')
'--glib-min-required', '3',
'--glib-max-allowed', '3.2')
self.assertEqual('', result.err)
self.assertNotEqual('', result.out.strip())
@ -397,6 +398,55 @@ G_END_DECLS
self.assertEqual('', result.err)
self.assertNotEqual('', result.out.strip())
def test_glib_max_allowed_too_low(self):
"""Test running with a --glib-max-allowed which is too low (and hence
probably a typo)."""
with self.assertRaises(subprocess.CalledProcessError):
self.runCodegenWithInterface('',
'--output', '/dev/stdout',
'--body',
'--glib-max-allowed', '2.6')
def test_glib_max_allowed_major_only(self):
"""Test running with a --glib-max-allowed which contains only a major version."""
result = self.runCodegenWithInterface('',
'--output', '/dev/stdout',
'--header',
'--glib-max-allowed', '3')
self.assertEqual('', result.err)
self.assertNotEqual('', result.out.strip())
def test_glib_max_allowed_with_micro(self):
"""Test running with a --glib-max-allowed which contains a micro version."""
result = self.runCodegenWithInterface('',
'--output', '/dev/stdout',
'--header',
'--glib-max-allowed', '2.46.2')
self.assertEqual('', result.err)
self.assertNotEqual('', result.out.strip())
def test_glib_max_allowed_unstable(self):
"""Test running with a --glib-max-allowed which is unstable. It should
be rounded up to the next stable version number, and hence should not
end up less than --glib-min-required."""
result = self.runCodegenWithInterface('',
'--output', '/dev/stdout',
'--header',
'--glib-max-allowed', '2.63',
'--glib-min-required', '2.64')
self.assertEqual('', result.err)
self.assertNotEqual('', result.out.strip())
def test_glib_max_allowed_less_than_min_required(self):
"""Test running with a --glib-max-allowed which is less than
--glib-min-required."""
with self.assertRaises(subprocess.CalledProcessError):
self.runCodegenWithInterface('',
'--output', '/dev/stdout',
'--body',
'--glib-max-allowed', '2.62',
'--glib-min-required', '2.64')
def test_unix_fd_types_and_annotations(self):
"""Test an interface with `h` arguments, no annotation, and GLib < 2.64.