diff --git a/docs/reference/gio/gdbus-codegen.xml b/docs/reference/gio/gdbus-codegen.xml index 9d62c3757..9687681fd 100644 --- a/docs/reference/gio/gdbus-codegen.xml +++ b/docs/reference/gio/gdbus-codegen.xml @@ -51,6 +51,7 @@ VERSION + VERSION FILE FILE @@ -460,6 +461,27 @@ gdbus-codegen --c-namespace MyApp \ + + VERSION + + + Specifies the maximum version of GLib which the code generated by + gdbus-codegen can depend on. This may be used to + ensure that code generated by gdbus-codegen is + compilable with specific older versions of GLib that your software has + to support. + + + The version number must be of the form + MAJOR.MINOR.MICRO, + where all parts are integers. MINOR and + MICRO are optional. The version number must + be greater than or equal to that passed to . + It defaults to the version of GLib which provides this gdbus-codegen. + + + + diff --git a/gio/gdbus-2.0/codegen/codegen_main.py b/gio/gdbus-2.0/codegen/codegen_main.py index 60e1ae042..c938640e7 100644 --- a/gio/gdbus-2.0/codegen/codegen_main.py +++ b/gio/gdbus-2.0/codegen/codegen_main.py @@ -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)) diff --git a/gio/gdbus-2.0/codegen/config.py.in b/gio/gdbus-2.0/codegen/config.py.in index a91178a95..4e6df5a09 100644 --- a/gio/gdbus-2.0/codegen/config.py.in +++ b/gio/gdbus-2.0/codegen/config.py.in @@ -20,3 +20,5 @@ # Author: David Zeuthen VERSION = "@VERSION@" +MAJOR_VERSION = @MAJOR_VERSION@ +MINOR_VERSION = @MINOR_VERSION@ diff --git a/gio/gdbus-2.0/codegen/meson.build b/gio/gdbus-2.0/codegen/meson.build index 121e9e6bb..ff5edb977 100644 --- a/gio/gdbus-2.0/codegen/meson.build +++ b/gio/gdbus-2.0/codegen/meson.build @@ -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) diff --git a/gio/tests/codegen.py b/gio/tests/codegen.py index bbb51117d..51de0ede4 100644 --- a/gio/tests/codegen.py +++ b/gio/tests/codegen.py @@ -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.