From 695a1a276787080497f1249819896efde9000f47 Mon Sep 17 00:00:00 2001 From: sewn Date: Mon, 11 Dec 2023 12:52:45 +0300 Subject: [PATCH] initial gnome module --- .github/workflows/ubuntu.yml | 3 +- src/script/meson.build | 1 + src/script/modules/gnome.meson | 561 ++++++++++++++++++ tests/project/meson.build | 3 + tests/project/modules/gnome/copyfile.py | 6 + .../gnome/gdbus/data/com.example.Sample.xml | 14 + tests/project/modules/gnome/gdbus/gdbusprog.c | 8 + tests/project/modules/gnome/gdbus/meson.build | 105 ++++ .../modules/gnome/genmarshal/main.c.in | 102 ++++ .../modules/gnome/genmarshal/marshaller.list | 3 + .../modules/gnome/genmarshal/meson.build | 70 +++ tests/project/modules/gnome/gir/copy.py | 18 + tests/project/modules/gnome/gir/dep1/dep1.c | 56 ++ tests/project/modules/gnome/gir/dep1/dep1.h | 23 + .../modules/gnome/gir/dep1/dep2/dep2.c | 124 ++++ .../modules/gnome/gir/dep1/dep2/dep2.h | 21 + .../modules/gnome/gir/dep1/dep2/meson.build | 21 + .../modules/gnome/gir/dep1/dep3/dep3.c | 124 ++++ .../modules/gnome/gir/dep1/dep3/dep3.h | 21 + .../modules/gnome/gir/dep1/dep3/meson.build | 21 + .../modules/gnome/gir/dep1/meson.build | 33 ++ .../project/modules/gnome/gir/meson-sample.c | 121 ++++ .../project/modules/gnome/gir/meson-sample.h | 28 + .../project/modules/gnome/gir/meson-sample2.c | 45 ++ .../project/modules/gnome/gir/meson-sample2.h | 21 + tests/project/modules/gnome/gir/meson.build | 65 ++ tests/project/modules/gnome/gir/prog.c | 35 ++ tests/project/modules/gnome/gir/prog.py | 11 + tests/project/modules/gnome/meson.build | 78 +++ .../project/modules/gnome/mkenums/enums.c.in | 41 ++ .../project/modules/gnome/mkenums/enums.h.in | 24 + .../project/modules/gnome/mkenums/enums2.c.in | 41 ++ .../project/modules/gnome/mkenums/enums2.h.in | 24 + tests/project/modules/gnome/mkenums/main.c | 30 + tests/project/modules/gnome/mkenums/main4.c | 35 ++ tests/project/modules/gnome/mkenums/main5.c | 35 ++ .../modules/gnome/mkenums/meson-decls.h | 2 + .../modules/gnome/mkenums/meson-sample.h | 20 + .../project/modules/gnome/mkenums/meson.build | 176 ++++++ .../modules/gnome/mkenums/subdir/h2.h.in | 5 + .../project/modules/gnome/mkenums/subdir/h3.h | 5 + .../modules/gnome/mkenums/subdir/meson.build | 2 + .../modules/gnome/resources-data/meson.build | 19 + .../modules/gnome/resources-data/res1.txt | 1 + .../modules/gnome/resources-data/res3.txt.in | 1 + .../gnome/resources-data/subdir/meson.build | 8 + .../gnome/resources-data/subdir/res2.txt | 1 + .../gnome/resources-data/subdir/res4.txt.in | 1 + .../modules/gnome/resources/generated-main.c | 26 + .../gnome/resources/generated.gresource.xml | 9 + .../gnome/resources/generated/meson.build | 5 + .../modules/gnome/resources/meson.build | 87 +++ .../gnome/resources/myresource.gresource.xml | 9 + .../project/modules/gnome/resources/res3.txt | 1 + .../modules/gnome/resources/resources.py | 10 + .../modules/gnome/resources/simple-main.c | 27 + .../gnome/resources/simple.gresource.xml | 7 + .../schemas/com.github.meson.gschema.xml | 12 + .../project/modules/gnome/schemas/meson.build | 8 + .../modules/gnome/schemas/schemaprog.c | 47 ++ tests/project/modules/gnome/test.json | 40 ++ 61 files changed, 2500 insertions(+), 1 deletion(-) create mode 100644 src/script/modules/gnome.meson create mode 100644 tests/project/modules/gnome/copyfile.py create mode 100644 tests/project/modules/gnome/gdbus/data/com.example.Sample.xml create mode 100644 tests/project/modules/gnome/gdbus/gdbusprog.c create mode 100644 tests/project/modules/gnome/gdbus/meson.build create mode 100644 tests/project/modules/gnome/genmarshal/main.c.in create mode 100644 tests/project/modules/gnome/genmarshal/marshaller.list create mode 100644 tests/project/modules/gnome/genmarshal/meson.build create mode 100755 tests/project/modules/gnome/gir/copy.py create mode 100644 tests/project/modules/gnome/gir/dep1/dep1.c create mode 100644 tests/project/modules/gnome/gir/dep1/dep1.h create mode 100644 tests/project/modules/gnome/gir/dep1/dep2/dep2.c create mode 100644 tests/project/modules/gnome/gir/dep1/dep2/dep2.h create mode 100644 tests/project/modules/gnome/gir/dep1/dep2/meson.build create mode 100644 tests/project/modules/gnome/gir/dep1/dep3/dep3.c create mode 100644 tests/project/modules/gnome/gir/dep1/dep3/dep3.h create mode 100644 tests/project/modules/gnome/gir/dep1/dep3/meson.build create mode 100644 tests/project/modules/gnome/gir/dep1/meson.build create mode 100644 tests/project/modules/gnome/gir/meson-sample.c create mode 100644 tests/project/modules/gnome/gir/meson-sample.h create mode 100644 tests/project/modules/gnome/gir/meson-sample2.c create mode 100644 tests/project/modules/gnome/gir/meson-sample2.h create mode 100644 tests/project/modules/gnome/gir/meson.build create mode 100644 tests/project/modules/gnome/gir/prog.c create mode 100755 tests/project/modules/gnome/gir/prog.py create mode 100644 tests/project/modules/gnome/meson.build create mode 100644 tests/project/modules/gnome/mkenums/enums.c.in create mode 100644 tests/project/modules/gnome/mkenums/enums.h.in create mode 100644 tests/project/modules/gnome/mkenums/enums2.c.in create mode 100644 tests/project/modules/gnome/mkenums/enums2.h.in create mode 100644 tests/project/modules/gnome/mkenums/main.c create mode 100644 tests/project/modules/gnome/mkenums/main4.c create mode 100644 tests/project/modules/gnome/mkenums/main5.c create mode 100644 tests/project/modules/gnome/mkenums/meson-decls.h create mode 100644 tests/project/modules/gnome/mkenums/meson-sample.h create mode 100644 tests/project/modules/gnome/mkenums/meson.build create mode 100644 tests/project/modules/gnome/mkenums/subdir/h2.h.in create mode 100644 tests/project/modules/gnome/mkenums/subdir/h3.h create mode 100644 tests/project/modules/gnome/mkenums/subdir/meson.build create mode 100644 tests/project/modules/gnome/resources-data/meson.build create mode 100644 tests/project/modules/gnome/resources-data/res1.txt create mode 100644 tests/project/modules/gnome/resources-data/res3.txt.in create mode 100644 tests/project/modules/gnome/resources-data/subdir/meson.build create mode 100644 tests/project/modules/gnome/resources-data/subdir/res2.txt create mode 100644 tests/project/modules/gnome/resources-data/subdir/res4.txt.in create mode 100644 tests/project/modules/gnome/resources/generated-main.c create mode 100644 tests/project/modules/gnome/resources/generated.gresource.xml create mode 100644 tests/project/modules/gnome/resources/generated/meson.build create mode 100644 tests/project/modules/gnome/resources/meson.build create mode 100644 tests/project/modules/gnome/resources/myresource.gresource.xml create mode 100644 tests/project/modules/gnome/resources/res3.txt create mode 100644 tests/project/modules/gnome/resources/resources.py create mode 100644 tests/project/modules/gnome/resources/simple-main.c create mode 100644 tests/project/modules/gnome/resources/simple.gresource.xml create mode 100644 tests/project/modules/gnome/schemas/com.github.meson.gschema.xml create mode 100644 tests/project/modules/gnome/schemas/meson.build create mode 100644 tests/project/modules/gnome/schemas/schemaprog.c create mode 100644 tests/project/modules/gnome/test.json diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index d16c69504..a6aee4b40 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -62,9 +62,10 @@ jobs: - uses: actions/checkout@master with: fetch-depth: 0 + # Required for gnome module tests. - name: Install dependencies run: | - sudo apt install libpkgconf-dev + sudo apt install libpkgconf-dev libglib2.0-0 libglib2.0-dev libgirepository1.0-dev # Bootstrap basic build. - name: Bootstrap diff --git a/src/script/meson.build b/src/script/meson.build index 0c6aaba81..a0cb16ab6 100644 --- a/src/script/meson.build +++ b/src/script/meson.build @@ -17,6 +17,7 @@ foreach s : [ 'modules/_test.meson', 'modules/i18n.meson', + 'modules/gnome.meson', ] scripts_input += s scripts_cmdline += files(s) + [s] diff --git a/src/script/modules/gnome.meson b/src/script/modules/gnome.meson new file mode 100644 index 000000000..0ec101eeb --- /dev/null +++ b/src/script/modules/gnome.meson @@ -0,0 +1,561 @@ +# SPDX-FileCopyrightText: sewn +# SPDX-License-Identifier: GPL-3.0-only + +# TODO: investigate void kwarg in custom_target + +fs = import('fs') + +# TODO: investigate +func post_install( + glib_compile_schemas bool: false, + gio_querymodules listify[str]:, + gtk_update_icon_cache bool: false, + update_desktop_database bool: false, + update_mime_database bool: false, +) + return false +endfunc + +func compile_resources( + target_name str, + input custom_tgt|file|generated_list|str, + build_by_default bool: true, + c_name str:, + dependencies listify[custom_tgt|file]: [], + export bool: false, + extra_args listify[str]:, + gresource_bundle bool: false, + install bool: false, + install_header bool: false, + install_dir str:, + source_dir listify[str]:, +) -> list[custom_tgt] + cmd = [ + find_program('glib-compile-resources'), + '@INPUT@', + is_void(c_name) ? [] : ['--c-name', c_name], + export ? [] : ['--internal'], + '--generate', + '--target', '@OUTPUT@', + is_void(extra_args) ? [] : extra_args, + ] + + depends = [] + + foreach sd : source_dir + sd = fs.relative_to(meson.current_build_dir(), fs.make_absolute(sd)) + endforeach + + foreach d : dependencies + # is 'subdir' meson member struct or 'get_subdir' meson method fs.parent? + if typeof(d) == 'custom_tgt' + source_dir += fs.parent(d.full_path()) + elif typeof(d) == 'file' + source_dir += fs.parent(d) + depends += d + else + source_dir += fs.parent(d) + endif + endforeach + + source_dir += meson.current_build_dir() + + foreach sd : source_dir + cmd += ['--sourcedir', sd] + endforeach + + proj = meson.project() + if not gresource_bundle + output = target_name + '.gresource' + name = target_name + '_gresource' + elif not is_void(proj['compilers']['c']) + output = target_name + '.c' + name = target_name + '_c' + elif not is_void(proj['compilers']['c++']) + output = target_name + '.cpp' + name = target_name + '_cpp' + else + error( + 'compiling gresources into code is only supported in c and c++ projects', + ) + endif + + if install and not gresource_bundle + error( + 'the install kwarg only applies to gresource bundles, see install_header', + ) + elif install_header and gresource_bundle + error('the install_header kwarg does not apply to gresource bundles') + elif install_header and not export + error('gresource header is installed yet export is not enabled') + endif + + resources = [] + resources += custom_target( + name, + build_by_default: build_by_default, + depfile: output + '.d', + input: input, + install: install, + install_dir: is_void(install_dir) ? '' : install_dir, + install_tag: 'runtime', + output: output, + command: [ + cmd, + '--generate-source', + '--dependency-file', '@DEPFILE@', + ], + ) + + if gresource_bundle + return resources + endif + + resources += custom_target( + name + '_h', + build_by_default: build_by_default, + input: input, + install: install_header, + install_dir: is_void(install_dir) ? get_option('includedir') : install_dir, + install_tag: 'devel', + output: name + '.h', + command: [ + cmd, + '--generate-header', + ], + ) + + return resources +endfunc + +# TODO: implement generate_gir properly, upstream Meson is messy +# func generate_gir( +# targets glob[exe|both_libs], +# install bool: false, +# build_by_default bool: true, +# extra_args listify[str]: , +# dependencies listify[dep]: , +# export_packages listify[list|str]: , +# fatal_warnings bool: false, +# header listify[list|str]: , +# identifier_prefix listify[list|str]: , +# include_directories listify[str]: , +# install_gir bool: , +# install_typelib bool: , +# link_with listify[both_libs]: , +# namespace str: , +# nsversion str: , +# sources listify[custom_tgt|file|generated_list|str]: , +# symbol_prefix listify[str]: , +# ) -> list[custom_tgt] +# if is_void(namespace) +# error('namespace kwarg required') +# endif +# +# if is_void(nsversion) +# error('nsversion kwarg required') +# endif +# +# add_language('c') +# +# if len(targets) > 1 +# isexe = false +# foreach t : targets +# if typeof(t) == 'exe' +# isexe = true +# endif +# endforeach +# if not isexe +# error('generate_gir only accepts a single argument when one of the arguments is an executable') +# endif +# endif +# +# gir_dep = dependency('gobject-introspection-1.0') +# scanner = find_program('g-ir-scanner') +# compiler = find_program('g-ir-compiler') +# +# file = '@0@-@1@.gir'.format(namepsace, nsversion) +# depends = [ targets, gir_dep.sources ] +# +# langs_compilers = [] +# cflags = [] +# internal_ldflags = [] +# external_ldflags = [] +# +# foreach t : targets +# foreach lang, compiler : t +# if lang in ['c', 'cpp', 'objc', 'objcpp', 'd'] +# langs_compilers += [lang, compiler] +# cflags += +# endif +# endforeach +# endforeach +# endfunc + +func compile_schemas( + build_by_default bool: true, + depend_files listify[file|list[file|str]|str]: [], +) -> custom_tgt + name = 'gsettings-compile' + srcdir = meson.current_source_dir() + if srcdir != '' + name += srcdir.replace('/', '_') + endif + + return custom_target( + name, + build_by_default: build_by_default, + depend_files: depend_files, + output: 'gschemas.compiled', + command: [ + find_program('glib-compile-schemas'), + ], + ) +endfunc + +# TODO: implement yelp +# TODO: implement gtkdoc +# TODO: implement gtkdoc_html_dir + +# TODO: check glib >= 2.49.1 for autocleanup +# TODO: check glib >= 2.56.2 for --body and --output +# TODO: check glib >= 2.51.3 for --generate-c-code and --output-directory +func gdbus_codegen( + name str, + input glob[custom_tgt|file|generated_list|str], + sources listify[custom_tgt|file|str]: [], + interface_prefix str:, + namespace str:, + extra_args listify[str]:, + autocleanup str: 'default', + object_manager bool: false, + annotations list[list[str]]: [], + docbook str:, + build_by_default bool: true, + install_dir str: get_option('includedir'), + install_header bool: false, +) -> list[custom_tgt] + if autocleanup not in ['default', 'all', 'none', 'objects'] + error('autocleanup must be one of default, all, none, objects') + endif + + cmd = [ + find_program('gdbus-codegen'), + '--c-generate-autocleanup', [autocleanup == 'default' ? 'all' : autocleanup], + is_void(interface_prefix) ? [] : [ + '--interface-prefix', interface_prefix, + ], + is_void(namespace) ? [] : ['--c-namespace', namespace], + object_manager ? ['--c-generate-object-manager'] : [], + ] + + xml_files = input + xml_files += sources + + foreach annot : annotations + cmd += ['--annotate', annot] + endforeach + + body = custom_target( + name + '_c', + build_by_default: build_by_default, + input: xml_files, + install: install_header, + install_dir: is_void(install_dir) ? '' : install_dir, + output: name + '.c', + command: [ + cmd, + '--output', '@OUTPUT@', + '--body', '@INPUT@', + ], + ) + + header = custom_target( + name + '_h', + build_by_default: build_by_default, + input: xml_files, + install: install_header, + install_dir: is_void(install_dir) ? '' : install_dir, + install_tag: 'devel', + output: name + '.h', + command: [ + cmd, + '--output', '@OUTPUT@', + '--header', '@INPUT@', + ], + ) + + targets = [body, header] + + if not is_void(docbook) + outputs = [] + + foreach xml : xml_files + outputs += '@0@.@1@'.format(docbook, fs.name(xml)) + endforeach + + doc = custom_target( + name + '-docbook', + depends: body, + build_by_default: build_by_default, + input: xml_files, + output: outputs, + command: [ + cmd, + '--output-directory', '@OUTDIR@', + '--generate-docbook', docbook, + '@INPUT@', + ], + ) + + targets += doc + endif + + return targets +endfunc + +func mkenums( + name str, + c_template file|str:, + comments str:, + h_template file|str:, + identifier_prefix str:, + install_header bool: false, + install_dir str:, + depends listify[build_tgt|custom_tgt]: [], + sources listify[custom_tgt|file|generated_list|str]:, + symbol_prefix str:, + eprod str:, + fhead str:, + fprod str:, + ftail str:, + vhead str:, + vprod str:, + vtail str:, +) -> list[custom_tgt] + if is_void(sources) + error('sources kwarg required') + endif + + cmd = [find_program('glib-mkenums')] + + known_kwargs = { + 'comments': comments, + 'eprod': eprod, + 'fhead': fhead, + 'fprod': fprod, + 'ftail': ftail, + 'identifier-prefix': identifier_prefix, + 'symbol-prefix': symbol_prefix, + 'vhead': vhead, + 'vprod': vprod, + 'vtail': vtail, + } + + foreach kwarg, value : known_kwargs + if not is_void(value) + cmd += ['--' + kwarg, value.replace('@', '\@')] + endif + endforeach + + enums = [] + enums += custom_target( + name + '_h', + capture: true, + depends: depends, + input: sources, + install: install_header, + install_dir: is_void(install_dir) ? '' : install_dir, + output: name + '.h', + command: [ + cmd, + is_void(h_template) ? [] : ['--template', h_template], + '@INPUT@', + ], + ) + + enums += custom_target( + name + '_c', + capture: true, + input: sources, + depends: depends, + install: install_header, + install_dir: is_void(install_dir) ? '' : install_dir, + output: name + '.c', + command: [ + cmd, + is_void(c_template) ? [] : ['--template', c_template], + '@INPUT@', + ], + ) + + return enums +endfunc + +func mkenums_simple( + name str, + identifier_prefix str:, + install_header bool: false, + install_dir str:, + symbol_prefix str:, + sources listify[file|str]:, + header_prefix str: '', + function_prefix str: '', + body_prefix str: '', + decorator str: '', +) -> list[custom_tgt] + cmd = [ + find_program('glib-mkenums'), + is_void(identifier_prefix) ? [] : [ + '--identifier-prefix', identifier_prefix, + ], + is_void(symbol_prefix) ? [] : ['--symbol-prefix', symbol_prefix], + ] + + fhead = body_prefix + '\n' + '#include "@0@"\n'.format(name + '.h') + foreach s : sources + h_path = fs.relative_to( + meson.current_build_dir(), + typeof(s) == 'file' ? s.full_path() : files(s)[0].full_path(), + ) + fhead += '#include "@0@"'.format(h_path) + endforeach + fhead += '\n#define C_ENUM(v) ((gint) v)\n#define C_FLAGS(v) ((guint) v)\n' + + c_file = custom_target( + name + '.c', + capture: true, + input: sources, + install: install_header, + install_dir: is_void(install_dir) ? '' : install_dir, + output: name + '.c', + command: [ + cmd, + '--fhead', fhead, + '--fprod', '\n/* enumerations from "\@basename\@" */\n', + '--vhead', '\nGType\n' + + function_prefix + + '\@enum_name\@_get_type (void)\n{{\nstatic gsize gtype_id = 0;\nstatic const G\@Type\@Value values[] = {{', + '--vprod', '\n { C_\@TYPE\@(\@VALUENAME\@), "\@VALUENAME\@", "\@valuenick\@" },])', + '--vtail', '\n { 0, NULL, NULL }\nif (g_once_init_enter (>ype_id)) {\nGType new_type = g_\@type\@_register_static (g_intern_static_string ("\@EnumName\@"), values);\ng_once_init_leave (>ype_id, new_type);\n}\nreturn (GType) gtype_id;\n}', + '@INPUT@', + ], + ) + + h_file = custom_target( + name + '.h', + capture: true, + input: sources, + install: install_header, + install_dir: is_void(install_dir) ? '' : install_dir, + output: name + '.h', + command: [ + cmd, + '--fhead', '#pragma once\n#include \n' + + header_prefix + + '\nG_BEGIN_DECLS\n', + '--fprod', '\n/* enumerations from "\@basename\@" */\n', + '--vhead', '\n' + + decorator + + ' \nGType ' + + function_prefix + + '\@enum_name\@_get_type (void);\n#define \@ENUMPREFIX\@_TYPE_\@ENUMSHORT\@ (' + + function_prefix + + '\@enum_name\@_get_type())', + '--ftail', '\nG_END_DECLS', + '@INPUT@', + ], + ) + + return [c_file, h_file] +endfunc + +# TODO: check glib >2.53.4 for --include-header +# TODO: check glib >2.53.3 for extra_args and --pragma-once +# TODO: check glib >2.51.0 for --output +func genmarshal( + name str, + depends listify[build_tgt|custom_tgt]: [], + depend_files listify[file|str]: [], + extra_args listify[str]:, + install_header bool: false, + install_dir str:, + internal bool: false, + nostdinc bool: false, + prefix str:, + skip_source bool: false, + sources listify[file|str]:, + stdinc bool: false, + valist_marshallers bool: false, +) -> list[custom_tgt] + if is_void(sources) + error('sources kwarg required') + endif + + cmd = [ + find_program('glib-genmarshal'), + is_void(prefix) ? [] : ['--prefix', prefix], + '--output', '@OUTPUT@', + extra_args, + ] + + known_kwargs = { + 'internal': internal, + 'nostdinc': nostdinc, + 'skip-source': skip_source, + 'stdinc': stdinc, + 'valist-marshallers': valist_marshallers, + } + + foreach kwarg, value : known_kwargs + if not is_void(value) + cmd += ['--' + kwarg] + endif + endforeach + + header_file = name + '.h' + + header = custom_target( + name + '_h', + input: sources, + depends: depends, + depend_files: depend_files, + install: install_header, + install_dir: is_void(install_dir) ? '' : install_dir, + output: header_file, + command: [ + cmd, + '--header', '@INPUT@', + '--pragma-once', + ], + ) + + body = custom_target( + name + '_c', + input: sources, + depends: depends + header, + depend_files: depend_files, + install: install_header, + install_dir: is_void(install_dir) ? '' : install_dir, + output: name + '.c', + command: [ + cmd, + '--body', '@INPUT@', + '--include-header', header_file, + ], + ) + + return [body, header] +endfunc + +# TODO: implement generate_vapi + +return { + 'post_install': post_install, + 'compile_resources': compile_resources, + 'compile_schemas': compile_schemas, + 'gdbus_codegen': gdbus_codegen, + 'mkenums': mkenums, + 'mkenums_simple': mkenums_simple, + 'genmarshal': genmarshal, +} diff --git a/tests/project/meson.build b/tests/project/meson.build index e3de367eb..230a6f0bb 100644 --- a/tests/project/meson.build +++ b/tests/project/meson.build @@ -15,6 +15,9 @@ tests = [ ['muon/python', ['python']], ['muon/script_module'], + # module tests imported from meson + ['modules/gnome', ['skip_analyze', 'glib']], + # project tests imported from meson ['common/1 trivial'], ['common/2 cpp'], diff --git a/tests/project/modules/gnome/copyfile.py b/tests/project/modules/gnome/copyfile.py new file mode 100644 index 000000000..7e44c48dd --- /dev/null +++ b/tests/project/modules/gnome/copyfile.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import sys +import shutil + +shutil.copy(sys.argv[1], sys.argv[2]) diff --git a/tests/project/modules/gnome/gdbus/data/com.example.Sample.xml b/tests/project/modules/gnome/gdbus/data/com.example.Sample.xml new file mode 100644 index 000000000..d7adc30f1 --- /dev/null +++ b/tests/project/modules/gnome/gdbus/data/com.example.Sample.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + diff --git a/tests/project/modules/gnome/gdbus/gdbusprog.c b/tests/project/modules/gnome/gdbus/gdbusprog.c new file mode 100644 index 000000000..b42b6fe24 --- /dev/null +++ b/tests/project/modules/gnome/gdbus/gdbusprog.c @@ -0,0 +1,8 @@ +#include"generated-gdbus.h" + +int main(int argc, char **argv) { + SampleComExample *s; + s = sample_com_example_skeleton_new(); + g_object_unref(s); + return 0; +} diff --git a/tests/project/modules/gnome/gdbus/meson.build b/tests/project/modules/gnome/gdbus/meson.build new file mode 100644 index 000000000..50a0bbecd --- /dev/null +++ b/tests/project/modules/gnome/gdbus/meson.build @@ -0,0 +1,105 @@ +gdbus_src = gnome.gdbus_codegen( + 'generated-gdbus-no-docbook', + 'data/com.example.Sample.xml', + interface_prefix: 'com.example.', + namespace: 'Sample', + annotations: [ + ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true'], + ], +) + +# check that empty annotations work +gdbus_src2 = gnome.gdbus_codegen( + 'generated-gdbus-no-docbook2', + 'data/com.example.Sample.xml', + interface_prefix: 'com.example.', + namespace: 'Sample', + annotations: [], +) + +assert(gdbus_src.length() == 2, 'expected 2 targets') +assert(gdbus_src[0].full_path().endswith('.c'), 'expected 1 c source file') +assert(gdbus_src[1].full_path().endswith('.h'), 'expected 1 c header file') + +sample_xml = configure_file( + input: 'data/com.example.Sample.xml', + output: 'com.example.Sample.xml', + copy: true, +) + +gdbus_src = gnome.gdbus_codegen( + 'generated-gdbus-no-docbook-files-posarg', + sample_xml, + interface_prefix: 'com.example.', + namespace: 'Sample', + annotations: [ + ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true'], + ], +) +assert(gdbus_src.length() == 2, 'expected 2 targets') +assert(gdbus_src[0].full_path().endswith('.c'), 'expected 1 c source file') +assert(gdbus_src[1].full_path().endswith('.h'), 'expected 1 c header file') + +gdbus_src = gnome.gdbus_codegen( + 'generated-gdbus', + sources: files('data/com.example.Sample.xml'), + interface_prefix: 'com.example.', + namespace: 'Sample', + annotations: [ + ['com.example.Hello()', 'org.freedesktop.DBus.Deprecated', 'true'], + ['com.example.Bye()', 'org.freedesktop.DBus.Deprecated', 'true'], + ], + docbook: 'generated-gdbus-doc', + install_header: true, + install_dir: get_option('includedir'), +) +assert(gdbus_src.length() == 3, 'expected 3 targets') +assert(gdbus_src[0].full_path().endswith('.c'), 'expected 1 c source file') +assert(gdbus_src[1].full_path().endswith('.h'), 'expected 1 c header file') + +if not pretend_glib_old and glib.version().version_compare('>=2.51.3') + includes = [] +else + includes = include_directories('..') +endif + +# check that custom targets work +gdbus_xml_ct = custom_target( + 'built xml sources for gdbus', + output: 'com.example.SampleCustomTarget.xml', + input: 'data/com.example.Sample.xml', + command: [copyfile, '@INPUT@', '@OUTPUT@'], +) + +gdbus_src_ct = gnome.gdbus_codegen( + 'generated-gdbus-customtarget-src', + gdbus_xml_ct, + interface_prefix: 'com.example.', + namespace: 'Sample', + annotations: [], +) +gdbus_src_cti = gnome.gdbus_codegen( + 'generated-gdbus-customtargetindex-src', + gdbus_xml_ct[0], + interface_prefix: 'com.example.', + namespace: 'Sample', + annotations: [], +) + +gdbus_src_gen = gnome.gdbus_codegen( + 'generated-gdbus-generator-src', + copyfile_gen.process('data/com.example.Sample.xml'), + interface_prefix: 'com.example.', + namespace: 'Sample', + annotations: [], +) + +gdbus_exe = executable( + 'gdbus-test', + 'gdbusprog.c', + gdbus_src, + include_directories: includes, + dependencies: giounix, +) + +test('gdbus', gdbus_exe) diff --git a/tests/project/modules/gnome/genmarshal/main.c.in b/tests/project/modules/gnome/genmarshal/main.c.in new file mode 100644 index 000000000..8e3ca7a4b --- /dev/null +++ b/tests/project/modules/gnome/genmarshal/main.c.in @@ -0,0 +1,102 @@ +#include +#include +#include +#include @MARSHALLER_HEADER@ + +static int singleton = 42; + +void foo(gpointer user_data, gpointer data) { + if (user_data != &singleton) { + fprintf(stderr, "Invoked foo function was passed incorrect user data.\n"); + exit(1); + } +} + +void bar(gpointer user_data, gint param1, gpointer data) { + if (param1 != singleton) { + fprintf(stderr, "Invoked bar function was passed incorrect param1, but %d.\n", param1); + exit(2); + } + if (user_data != &singleton) { + fprintf(stderr, "Invoked bar function was passed incorrect user data.\n"); + exit(3); + } +} + +gfloat baz(gpointer user_data, gboolean param1, guchar param2, gpointer data) { + if (param1 != TRUE) { + fprintf(stderr, "Invoked baz function was passed incorrect param1.\n"); + exit(4); + } + if (param2 != singleton) { + fprintf(stderr, "Invoked baz function was passed incorrect param2.\n"); + exit(5); + } + if (user_data != &singleton) { + fprintf(stderr, "Invoked baz function was passed incorrect user data.\n"); + exit(6); + } + return (gfloat)param2; +} + +int main(int argc, char **argv) { + GClosure *cc_foo, *cc_bar, *cc_baz; + GValue return_value = G_VALUE_INIT; + GValue param_values[3] = {G_VALUE_INIT, G_VALUE_INIT, G_VALUE_INIT}; + + fprintf(stderr, "Invoking foo function.\n"); + cc_foo = g_cclosure_new(G_CALLBACK(foo), NULL, NULL); + g_closure_set_marshal(cc_foo, g_cclosure_user_marshal_VOID__VOID); + g_value_init(¶m_values[0], G_TYPE_POINTER); + g_value_set_pointer(¶m_values[0], &singleton); + g_closure_invoke(cc_foo, &return_value, 1, param_values, NULL); + if (G_VALUE_TYPE(&return_value) != G_TYPE_INVALID) { + fprintf(stderr, "Invoked foo function did not return empty value, but %s.\n", + G_VALUE_TYPE_NAME(&return_value)); + return 7; + } + g_value_unset(¶m_values[0]); + g_value_unset(&return_value); + g_closure_unref(cc_foo); + + fprintf(stderr, "Invoking bar function.\n"); + cc_bar = g_cclosure_new(G_CALLBACK(bar), NULL, NULL); + g_closure_set_marshal(cc_bar, g_cclosure_user_marshal_VOID__INT); + g_value_init(¶m_values[0], G_TYPE_POINTER); + g_value_set_pointer(¶m_values[0], &singleton); + g_value_init(¶m_values[1], G_TYPE_INT); + g_value_set_int(¶m_values[1], 42); + g_closure_invoke(cc_bar, &return_value, 2, param_values, NULL); + if (G_VALUE_TYPE(&return_value) != G_TYPE_INVALID) { + fprintf(stderr, "Invoked bar function did not return empty value.\n"); + return 8; + } + g_value_unset(¶m_values[0]); + g_value_unset(¶m_values[1]); + g_value_unset(&return_value); + g_closure_unref(cc_bar); + + fprintf(stderr, "Invoking baz function.\n"); + cc_baz = g_cclosure_new(G_CALLBACK(baz), NULL, NULL); + g_closure_set_marshal(cc_baz, g_cclosure_user_marshal_FLOAT__BOOLEAN_UCHAR); + g_value_init(¶m_values[0], G_TYPE_POINTER); + g_value_set_pointer(¶m_values[0], &singleton); + g_value_init(¶m_values[1], G_TYPE_BOOLEAN); + g_value_set_boolean(¶m_values[1], TRUE); + g_value_init(¶m_values[2], G_TYPE_UCHAR); + g_value_set_uchar(¶m_values[2], 42); + g_value_init(&return_value, G_TYPE_FLOAT); + g_closure_invoke(cc_baz, &return_value, 3, param_values, NULL); + if (g_value_get_float(&return_value) != 42.0f) { + fprintf(stderr, "Invoked baz function did not return expected value.\n"); + return 9; + } + g_value_unset(¶m_values[0]); + g_value_unset(¶m_values[1]); + g_value_unset(¶m_values[2]); + g_value_unset(&return_value); + g_closure_unref(cc_baz); + + fprintf(stderr, "All ok.\n"); + return 0; +} diff --git a/tests/project/modules/gnome/genmarshal/marshaller.list b/tests/project/modules/gnome/genmarshal/marshaller.list new file mode 100644 index 000000000..a29f6c9de --- /dev/null +++ b/tests/project/modules/gnome/genmarshal/marshaller.list @@ -0,0 +1,3 @@ +VOID:VOID +VOID:INT +FLOAT:BOOLEAN,UCHAR diff --git a/tests/project/modules/gnome/genmarshal/meson.build b/tests/project/modules/gnome/genmarshal/meson.build new file mode 100644 index 000000000..a7708b795 --- /dev/null +++ b/tests/project/modules/gnome/genmarshal/meson.build @@ -0,0 +1,70 @@ +gnome = import('gnome') + +m_list = configure_file(input: 'marshaller.list', output: 'm.list', copy: true) + +idx = 0 +mlists = ['marshaller.list', files('marshaller.list'), m_list] + +foreach mlist : mlists + marshallers = gnome.genmarshal( + 'marshaller-@0@'.format(idx), + sources: mlist, + install_header: true, + install_dir: get_option('includedir') / 'subdir-@0@'.format(idx), + extra_args: ['-UG_ENABLE_DEBUG', '--prototypes'], + ) + + marshaller_c = marshallers[0] + marshaller_h = marshallers[1] + + cdata = configuration_data() + cdata.set_quoted('MARSHALLER_HEADER', 'marshaller-@0@.h'.format(idx)) + + main_c = configure_file( + input: 'main.c.in', + output: 'main-@0@.c'.format(idx), + configuration: cdata, + ) + + genmarshalexe = executable( + 'genmarshalprog-@0@'.format(idx), + main_c, + marshaller_c, + marshaller_h, + dependencies: gobj, + ) + test('genmarshal test @0@'.format(idx), genmarshalexe) + idx += 1 +endforeach + +foreach mlist : mlists + marshallers = gnome.genmarshal( + 'marshaller-@0@'.format(idx), + sources: [mlist], + install_header: true, + install_dir: get_option('includedir') / 'subdir-@0@'.format(idx), + extra_args: ['-UG_ENABLE_DEBUG', '--prototypes'], + ) + + marshaller_c = marshallers[0] + marshaller_h = marshallers[1] + + cdata = configuration_data() + cdata.set_quoted('MARSHALLER_HEADER', 'marshaller-@0@.h'.format(idx)) + + main_c = configure_file( + input: 'main.c.in', + output: 'main-@0@.c'.format(idx), + configuration: cdata, + ) + + genmarshalexe = executable( + 'genmarshalprog-@0@'.format(idx), + main_c, + marshaller_c, + marshaller_h, + dependencies: gobj, + ) + test('genmarshal test @0@'.format(idx), genmarshalexe) + idx += 1 +endforeach diff --git a/tests/project/modules/gnome/gir/copy.py b/tests/project/modules/gnome/gir/copy.py new file mode 100755 index 000000000..e92deaf5d --- /dev/null +++ b/tests/project/modules/gnome/gir/copy.py @@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# SPDX-License-Identifier: Apache-2.0 +# Copyright © 2021 Intel Corporation + +import argparse +import shutil + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument('src') + parser.add_argument('dest') + args = parser.parse_args() + + shutil.copy(args.src, args.dest) + + +if __name__ == "__main__": + main() diff --git a/tests/project/modules/gnome/gir/dep1/dep1.c b/tests/project/modules/gnome/gir/dep1/dep1.c new file mode 100644 index 000000000..8d4ca4bfe --- /dev/null +++ b/tests/project/modules/gnome/gir/dep1/dep1.c @@ -0,0 +1,56 @@ +#include "dep1.h" + +struct _MesonDep1 +{ + GObject parent_instance; +}; + +G_DEFINE_TYPE (MesonDep1, meson_dep1, G_TYPE_OBJECT) + +/** + * meson_dep1_new: + * + * Allocates a new #MesonDep1. + * + * Returns: (transfer full): a #MesonDep1. + */ +MesonDep1 * +meson_dep1_new (void) +{ + return g_object_new (MESON_TYPE_DEP1, NULL); +} + +static void +meson_dep1_finalize (GObject *object) +{ + G_OBJECT_CLASS (meson_dep1_parent_class)->finalize (object); +} + +static void +meson_dep1_class_init (MesonDep1Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_dep1_finalize; +} + +static void +meson_dep1_init (MesonDep1 *self) +{ +} + +/** + * meson_dep1_just_return_it: + * @dep: a #MesonDep2. + * + * Returns the #MesonDep2 that is passed in + * + * Returns: (transfer none): a #MesonDep2 + */ +MesonDep2* +meson_dep1_just_return_it (MesonDep1 *self, MesonDep2 *dep) +{ + g_return_val_if_fail (MESON_IS_DEP1 (self), NULL); + + return dep; +} diff --git a/tests/project/modules/gnome/gir/dep1/dep1.h b/tests/project/modules/gnome/gir/dep1/dep1.h new file mode 100644 index 000000000..5e6591b2c --- /dev/null +++ b/tests/project/modules/gnome/gir/dep1/dep1.h @@ -0,0 +1,23 @@ +#ifndef MESON_DEP1_H +#define MESON_DEP1_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#include +#include "dep2/dep2.h" + +G_BEGIN_DECLS + +#define MESON_TYPE_DEP1 (meson_dep1_get_type()) + +G_DECLARE_FINAL_TYPE (MesonDep1, meson_dep1, MESON, DEP1, GObject) + +MesonDep1 *meson_dep1_new (void); +MesonDep2 *meson_dep1_just_return_it (MesonDep1 *self, + MesonDep2 *dep); + +G_END_DECLS + +#endif /* MESON_DEP1_H */ diff --git a/tests/project/modules/gnome/gir/dep1/dep2/dep2.c b/tests/project/modules/gnome/gir/dep1/dep2/dep2.c new file mode 100644 index 000000000..754c6d7f7 --- /dev/null +++ b/tests/project/modules/gnome/gir/dep1/dep2/dep2.c @@ -0,0 +1,124 @@ +#include "dep2.h" + +struct _MesonDep2 +{ + GObject parent_instance; + + gchar *msg; +}; + +G_DEFINE_TYPE (MesonDep2, meson_dep2, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_MSG, + LAST_PROP +}; + +static GParamSpec *gParamSpecs [LAST_PROP]; + +/** + * meson_dep2_new: + * @msg: The message to set. + * + * Allocates a new #MesonDep2. + * + * Returns: (transfer full): a #MesonDep2. + */ +MesonDep2 * +meson_dep2_new (const gchar *msg) +{ + g_return_val_if_fail (msg != NULL, NULL); + + return g_object_new (MESON_TYPE_DEP2, + "message", msg, + NULL); +} + +static void +meson_dep2_finalize (GObject *object) +{ + MesonDep2 *self = (MesonDep2 *)object; + + g_clear_pointer (&self->msg, g_free); + + G_OBJECT_CLASS (meson_dep2_parent_class)->finalize (object); +} + +static void +meson_dep2_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MesonDep2 *self = MESON_DEP2 (object); + + switch (prop_id) + { + case PROP_MSG: + g_value_set_string (value, self->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep2_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MesonDep2 *self = MESON_DEP2 (object); + + switch (prop_id) + { + case PROP_MSG: + self->msg = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep2_class_init (MesonDep2Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_dep2_finalize; + object_class->get_property = meson_dep2_get_property; + object_class->set_property = meson_dep2_set_property; + + gParamSpecs [PROP_MSG] = + g_param_spec_string ("message", + "Message", + "The message to print.", + NULL, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs); +} + +static void +meson_dep2_init (MesonDep2 *self) +{ +} + +/** + * meson_dep2_return_message: + * @self: a #MesonDep2. + * + * Returns the message. + * + * Returns: (transfer none): a const gchar* + */ +const gchar* +meson_dep2_return_message (MesonDep2 *self) +{ + g_return_val_if_fail (MESON_IS_DEP2 (self), NULL); + + return (const gchar*) self->msg; +} diff --git a/tests/project/modules/gnome/gir/dep1/dep2/dep2.h b/tests/project/modules/gnome/gir/dep1/dep2/dep2.h new file mode 100644 index 000000000..128b243a8 --- /dev/null +++ b/tests/project/modules/gnome/gir/dep1/dep2/dep2.h @@ -0,0 +1,21 @@ +#ifndef MESON_DEP2_H +#define MESON_DEP2_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#include + +G_BEGIN_DECLS + +#define MESON_TYPE_DEP2 (meson_dep2_get_type()) + +G_DECLARE_FINAL_TYPE (MesonDep2, meson_dep2, MESON, DEP2, GObject) + +MesonDep2 *meson_dep2_new (const gchar *msg); +const gchar *meson_dep2_return_message (MesonDep2 *self); + +G_END_DECLS + +#endif /* MESON_DEP2_H */ diff --git a/tests/project/modules/gnome/gir/dep1/dep2/meson.build b/tests/project/modules/gnome/gir/dep1/dep2/meson.build new file mode 100644 index 000000000..24d973c0d --- /dev/null +++ b/tests/project/modules/gnome/gir/dep1/dep2/meson.build @@ -0,0 +1,21 @@ +dep2sources = ['dep2.c', 'dep2.h'] + +dep2lib = shared_library( + 'dep2lib', + sources: dep2sources, + dependencies: gobj, + install: true, +) + +dep2gir = gnome.generate_gir( + dep2lib, + sources: dep2sources, + nsversion: '1.0', + namespace: 'MesonDep2', + symbol_prefix: 'meson', + identifier_prefix: 'Meson', + includes: ['GObject-2.0'], + install: true, +) + +dep2_dep = declare_dependency(link_with: dep2lib, sources: [dep2gir]) diff --git a/tests/project/modules/gnome/gir/dep1/dep3/dep3.c b/tests/project/modules/gnome/gir/dep1/dep3/dep3.c new file mode 100644 index 000000000..ee5c5e123 --- /dev/null +++ b/tests/project/modules/gnome/gir/dep1/dep3/dep3.c @@ -0,0 +1,124 @@ +#include "dep3.h" + +struct _MesonDep3 +{ + GObject parent_instance; + + gchar *msg; +}; + +G_DEFINE_TYPE (MesonDep3, meson_dep3, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_MSG, + LAST_PROP +}; + +static GParamSpec *gParamSpecs [LAST_PROP]; + +/** + * meson_dep3_new: + * @msg: The message to set. + * + * Allocates a new #MesonDep3. + * + * Returns: (transfer full): a #MesonDep3. + */ +MesonDep3 * +meson_dep3_new (const gchar *msg) +{ + g_return_val_if_fail (msg != NULL, NULL); + + return g_object_new (MESON_TYPE_DEP3, + "message", msg, + NULL); +} + +static void +meson_dep3_finalize (GObject *object) +{ + MesonDep3 *self = (MesonDep3 *)object; + + g_clear_pointer (&self->msg, g_free); + + G_OBJECT_CLASS (meson_dep3_parent_class)->finalize (object); +} + +static void +meson_dep3_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MesonDep3 *self = MESON_DEP3 (object); + + switch (prop_id) + { + case PROP_MSG: + g_value_set_string (value, self->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep3_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MesonDep3 *self = MESON_DEP3 (object); + + switch (prop_id) + { + case PROP_MSG: + self->msg = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_dep3_class_init (MesonDep3Class *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_dep3_finalize; + object_class->get_property = meson_dep3_get_property; + object_class->set_property = meson_dep3_set_property; + + gParamSpecs [PROP_MSG] = + g_param_spec_string ("message", + "Message", + "The message to print.", + NULL, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs); +} + +static void +meson_dep3_init (MesonDep3 *self) +{ +} + +/** + * meson_dep3_return_message: + * @self: a #MesonDep3. + * + * Returns the message. + * + * Returns: (transfer none): a const gchar* + */ +const gchar* +meson_dep3_return_message (MesonDep3 *self) +{ + g_return_val_if_fail (MESON_IS_DEP3 (self), NULL); + + return (const gchar*) self->msg; +} diff --git a/tests/project/modules/gnome/gir/dep1/dep3/dep3.h b/tests/project/modules/gnome/gir/dep1/dep3/dep3.h new file mode 100644 index 000000000..4392bad83 --- /dev/null +++ b/tests/project/modules/gnome/gir/dep1/dep3/dep3.h @@ -0,0 +1,21 @@ +#ifndef MESON_DEP3_H +#define MESON_DEP3_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#include + +G_BEGIN_DECLS + +#define MESON_TYPE_DEP3 (meson_dep3_get_type()) + +G_DECLARE_FINAL_TYPE (MesonDep3, meson_dep3, MESON, DEP3, GObject) + +MesonDep3 *meson_dep3_new (const gchar *msg); +const gchar *meson_dep3_return_message (MesonDep3 *self); + +G_END_DECLS + +#endif /* MESON_DEP3_H */ diff --git a/tests/project/modules/gnome/gir/dep1/dep3/meson.build b/tests/project/modules/gnome/gir/dep1/dep3/meson.build new file mode 100644 index 000000000..1f05e7cc2 --- /dev/null +++ b/tests/project/modules/gnome/gir/dep1/dep3/meson.build @@ -0,0 +1,21 @@ +dep3sources = ['dep3.c', 'dep3.h'] + +dep3lib = shared_library( + 'dep3lib', + sources: dep3sources, + dependencies: gobj, + install: true, +) + +dep3gir = gnome.generate_gir( + dep3lib, + sources: dep3sources, + nsversion: '1.0', + namespace: 'MesonDep3', + symbol_prefix: 'meson', + identifier_prefix: 'Meson', + includes: ['GObject-2.0'], + install: true, +) + +dep3_dep = declare_dependency(link_with: dep3lib, sources: [dep3gir]) diff --git a/tests/project/modules/gnome/gir/dep1/meson.build b/tests/project/modules/gnome/gir/dep1/meson.build new file mode 100644 index 000000000..579d5926b --- /dev/null +++ b/tests/project/modules/gnome/gir/dep1/meson.build @@ -0,0 +1,33 @@ +subdir('dep2') +subdir('dep3') + +dep1sources = ['dep1.c', 'dep1.h'] + +# Do not need to link to dep2lib because we don't use any symbols from it +dep1lib = shared_library( + 'dep1lib', + sources: dep1sources, + dependencies: gobj, + install: true, +) + +# But the gir does need it because it we use the MesonDep2* structure defined +# in the header +dep1gir = gnome.generate_gir( + dep1lib, + sources: dep1sources, + nsversion: '1.0', + namespace: 'MesonDep1', + symbol_prefix: 'meson', + identifier_prefix: 'Meson', + header: 'dep1.h', + includes: ['GObject-2.0', 'MesonDep2-1.0', dep3gir[0]], + dependencies: [dep2_dep], + install: true, +) + +dep1_dep = declare_dependency( + link_with: dep1lib, + dependencies: [dep2_dep, dep3_dep], + sources: [dep1gir], +) diff --git a/tests/project/modules/gnome/gir/meson-sample.c b/tests/project/modules/gnome/gir/meson-sample.c new file mode 100644 index 000000000..850b850cf --- /dev/null +++ b/tests/project/modules/gnome/gir/meson-sample.c @@ -0,0 +1,121 @@ +#include "meson-sample.h" + +struct _MesonSample +{ + GObject parent_instance; + + gchar *msg; +}; + +G_DEFINE_TYPE (MesonSample, meson_sample, G_TYPE_OBJECT) + +enum { + PROP_0, + PROP_MSG, + LAST_PROP +}; + +static GParamSpec *gParamSpecs [LAST_PROP]; + +/** + * meson_sample_new: + * + * Allocates a new #MesonSample. + * + * Returns: (transfer full): a #MesonSample. + */ +MesonSample * +meson_sample_new (void) +{ + return g_object_new (MESON_TYPE_SAMPLE, NULL); +} + +static void +meson_sample_finalize (GObject *object) +{ + MesonSample *self = (MesonSample *)object; + + g_clear_pointer (&self->msg, g_free); + + G_OBJECT_CLASS (meson_sample_parent_class)->finalize (object); +} + +static void +meson_sample_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MesonSample *self = MESON_SAMPLE (object); + + switch (prop_id) + { + case PROP_MSG: + g_value_set_string (value, self->msg); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_sample_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MesonSample *self = MESON_SAMPLE (object); + + switch (prop_id) + { + case PROP_MSG: + self->msg = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +meson_sample_class_init (MesonSampleClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meson_sample_finalize; + object_class->get_property = meson_sample_get_property; + object_class->set_property = meson_sample_set_property; + + gParamSpecs [PROP_MSG] = + g_param_spec_string ("message", + "Message", + "The message to print.", + NULL, + (G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs); +} + +static void +meson_sample_init (MesonSample *self) +{ +} + +/** + * meson_sample_print_message: + * @self: a #MesonSample. + * + * Prints the message. + * + * Returns: Nothing. + */ +void +meson_sample_print_message (MesonSample *self, MesonDep1 *dep1, MesonDep2 *dep2) +{ + MesonDep2 *samedep; + g_return_if_fail (MESON_IS_SAMPLE (self)); + + samedep = meson_dep1_just_return_it (dep1, dep2); + g_print ("Message: %s\n", meson_dep2_return_message (samedep)); +} diff --git a/tests/project/modules/gnome/gir/meson-sample.h b/tests/project/modules/gnome/gir/meson-sample.h new file mode 100644 index 000000000..746813051 --- /dev/null +++ b/tests/project/modules/gnome/gir/meson-sample.h @@ -0,0 +1,28 @@ +#ifndef MESON_SAMPLE_H +#define MESON_SAMPLE_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#if !defined (MESON_TEST_2) +#error "MESON_TEST_2 not defined." +#endif + +#include +#include "dep1/dep1.h" + +G_BEGIN_DECLS + +#define MESON_TYPE_SAMPLE (meson_sample_get_type()) + +G_DECLARE_FINAL_TYPE (MesonSample, meson_sample, MESON, SAMPLE, GObject) + +MesonSample *meson_sample_new (void); +void meson_sample_print_message (MesonSample *self, + MesonDep1 *dep1, + MesonDep2 *dep2); + +G_END_DECLS + +#endif /* MESON_SAMPLE_H */ diff --git a/tests/project/modules/gnome/gir/meson-sample2.c b/tests/project/modules/gnome/gir/meson-sample2.c new file mode 100644 index 000000000..f76bc1629 --- /dev/null +++ b/tests/project/modules/gnome/gir/meson-sample2.c @@ -0,0 +1,45 @@ +#include "meson-sample2.h" + +struct _MesonSample2 +{ + GObject parent_instance; +}; + +G_DEFINE_TYPE (MesonSample2, meson_sample2, G_TYPE_OBJECT) + +/** + * meson_sample2_new: + * + * Allocates a new #MesonSample2. + * + * Returns: (transfer full): a #MesonSample2. + */ +MesonSample2 * +meson_sample2_new (void) +{ + return g_object_new (MESON_TYPE_SAMPLE2, NULL); +} + +static void +meson_sample2_class_init (MesonSample2Class *klass) +{ +} + +static void +meson_sample2_init (MesonSample2 *self) +{ +} + +/** + * meson_sample2_print_message: + * @self: a #MesonSample2. + * + * Prints Hello. + * + * Returns: Nothing. + */ +void +meson_sample2_print_message (MesonSample2 *self) +{ + g_print ("Message: Hello\n"); +} diff --git a/tests/project/modules/gnome/gir/meson-sample2.h b/tests/project/modules/gnome/gir/meson-sample2.h new file mode 100644 index 000000000..f3bcd39e9 --- /dev/null +++ b/tests/project/modules/gnome/gir/meson-sample2.h @@ -0,0 +1,21 @@ +#ifndef MESON_SAMPLE2_H +#define MESON_SAMPLE2_H + +#if !defined (MESON_TEST_1) +#error "MESON_TEST_1 not defined." +#endif + +#include + +G_BEGIN_DECLS + +#define MESON_TYPE_SAMPLE2 (meson_sample2_get_type()) + +G_DECLARE_FINAL_TYPE (MesonSample2, meson_sample2, MESON, SAMPLE2, GObject) + +MesonSample2 *meson_sample2_new (void); +void meson_sample2_print_message (MesonSample2 *self); + +G_END_DECLS + +#endif /* MESON_SAMPLE2_H */ diff --git a/tests/project/modules/gnome/gir/meson.build b/tests/project/modules/gnome/gir/meson.build new file mode 100644 index 000000000..40ca725f0 --- /dev/null +++ b/tests/project/modules/gnome/gir/meson.build @@ -0,0 +1,65 @@ +subdir('dep1') + +libsources = ['meson-sample.c', 'meson-sample.h'] +lib2sources = ['meson-sample2.c', 'meson-sample2.h'] + +gen_source = custom_target( + 'meson_sample3.h', + input: 'meson-sample.h', + output: 'meson-sample3.h', + command: [find_program('copy.py'), '@INPUT@', '@OUTPUT@'], + build_by_default: false, # this will force a race condition if one exists +) + +girlib = shared_library( + 'gir_lib', + sources: libsources, + c_args: '-DMESON_TEST_2', + dependencies: [gobj, dep1_dep], + install: true, +) + +girlib2 = shared_library( + 'gir_lib2', + sources: lib2sources, + dependencies: [gobj], + install: true, +) + +girexe = executable( + 'girprog', + sources: 'prog.c', + c_args: '-DMESON_TEST_2', + dependencies: [glib, gobj, gir, dep1_dep], + link_with: girlib, +) + +fake_dep = dependency('no-way-this-exists', required: false) + +gnome.generate_gir( + girlib, + girlib2, + sources: [libsources, lib2sources, gen_source], + env: {'CPPFLAGS': '-DMESON_TEST_2'}, + nsversion: '1.0', + namespace: 'Meson', + symbol_prefix: 'meson', + identifier_prefix: 'Meson', + includes: ['GObject-2.0', 'MesonDep1-1.0'], + # dep1_dep pulls in dep2_dep for us + dependencies: [[fake_dep, dep1_dep]], + install: true, + build_by_default: true, +) + +test('gobject introspection/c', girexe) +gir_paths = ':'.join( + [girlib.outdir(), dep1lib.outdir(), dep2lib.outdir(), dep3lib.outdir()], +) +envdata = environment() +envdata.append('GI_TYPELIB_PATH', gir_paths, separator: ':') +envdata.append('LD_LIBRARY_PATH', gir_paths) +if ['windows', 'cygwin'].contains(host_machine.system()) + envdata.append('PATH', gir_paths) +endif +test('gobject introspection/py', find_program('prog.py'), env: envdata) diff --git a/tests/project/modules/gnome/gir/prog.c b/tests/project/modules/gnome/gir/prog.c new file mode 100644 index 000000000..001f6d0b9 --- /dev/null +++ b/tests/project/modules/gnome/gir/prog.c @@ -0,0 +1,35 @@ +#include + +#include "meson-sample.h" + +gint +main (gint argc, + gchar *argv[]) +{ + GError * error = NULL; + + GOptionContext * ctx = g_option_context_new (NULL); + g_option_context_add_group (ctx, g_irepository_get_option_group ()); + + if (!g_option_context_parse (ctx, &argc, &argv, &error)) { + g_print ("sample: %s\n", error->message); + g_option_context_free (ctx); + if (error) { + g_error_free (error); + } + + return 1; + } + + MesonSample * i = meson_sample_new (); + MesonDep1 * dep1 = meson_dep1_new (); + MesonDep2 * dep2 = meson_dep2_new ("Hello, meson/c!"); + meson_sample_print_message (i, dep1, dep2); + + g_object_unref (i); + g_object_unref (dep1); + g_object_unref (dep2); + g_option_context_free (ctx); + + return 0; +} diff --git a/tests/project/modules/gnome/gir/prog.py b/tests/project/modules/gnome/gir/prog.py new file mode 100755 index 000000000..aa1f9a774 --- /dev/null +++ b/tests/project/modules/gnome/gir/prog.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 +from gi.repository import Meson, MesonDep1, MesonDep2 + +if __name__ == "__main__": + s = Meson.Sample.new() + dep1 = MesonDep1.Dep1.new() + dep2 = MesonDep2.Dep2.new("Hello, meson/py!") + s.print_message(dep1, dep2) + + s2 = Meson.Sample2.new() + s2.print_message() diff --git a/tests/project/modules/gnome/meson.build b/tests/project/modules/gnome/meson.build new file mode 100644 index 000000000..66a4eef50 --- /dev/null +++ b/tests/project/modules/gnome/meson.build @@ -0,0 +1,78 @@ +project('gobject-introspection', 'c') + +copyfile = find_program('copyfile.py') +copyfile_gen = generator( + copyfile, + output: '@BASENAME@Gen.xml', + arguments: ['@INPUT@', '@OUTPUT@'], +) + +glib = dependency('glib-2.0', required: false) +if not glib.found() + error('MESON_SKIP_TEST glib not found.') +endif + +# gir = dependency('gobject-introspection-1.0', required: false) +# if not gir.found() +# error('MESON_SKIP_TEST gobject-introspection not found.') +# endif + +python3 = import('python3') +py3 = python3.find_python() +if run_command(py3, '-c', 'import gi;', check: false).returncode() != 0 + error('MESON_SKIP_TEST python3-gi not found') +endif + +cc = meson.get_compiler('c') + +add_global_arguments('-DMESON_TEST_1', language: 'c') +if cc.get_id() == 'intel' + # Ignore invalid GCC pragma warnings from glib + # https://bugzilla.gnome.org/show_bug.cgi?id=776562 + add_global_arguments('-wd2282', language: 'c') +endif + +py3 = import('python3').find_python() +pycode = '''import os, sys +if "MESON_UNIT_TEST_PRETEND_GLIB_OLD" in os.environ: + sys.exit(0) +sys.exit(1) +''' + +pretend_glib_old = false +res = run_command(py3, '-c', pycode, check: false) +if res.returncode() == 0 + pretend_glib_old = true +endif + +gnome = import('gnome') +gio = dependency('gio-2.0') +giounix = dependency('gio-unix-2.0') +glib = dependency('glib-2.0') +gobj = dependency('gobject-2.0') +# gir = dependency('gobject-introspection-1.0') +gmod = dependency('gmodule-2.0') + +# GLib >= 2.76 removed slice allocator which causes a leak in g-i to now be +# visible to asan. The leak should be fixed in g-i >= 1.76.2: +# https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/411 +if ( + get_option('b_sanitize') != 'none' + and gir.version().version_compare('<=1.76.1') + and glib.version().version_compare('>=2.76') +) + error( + 'MESON_SKIP_TEST gobject-introspection >=1.76.2 is required with address sanitizer.', + ) +endif + +# Test that static deps don't error out when static libraries aren't found +glib_static = dependency('glib-2.0', static: true) + +subdir('resources-data') +subdir('resources') +# subdir('gir') +subdir('schemas') +subdir('gdbus') +subdir('mkenums') +subdir('genmarshal') diff --git a/tests/project/modules/gnome/mkenums/enums.c.in b/tests/project/modules/gnome/mkenums/enums.c.in new file mode 100644 index 000000000..1c19d8ffa --- /dev/null +++ b/tests/project/modules/gnome/mkenums/enums.c.in @@ -0,0 +1,41 @@ +/*** BEGIN file-header ***/ + +#include "enums.h" + +/*** END file-header ***/ +/*** BEGIN file-production ***/ + +/* enumerations from "@basename@" */ +#include "@basename@" + +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type(void) { + static gsize static_g_define_type_id = 0; + + if(g_once_init_enter(&static_g_define_type_id)) { + static const G@Type@Value values [] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + + GType g_define_type_id = + g_@type@_register_static(g_intern_static_string("@EnumName@"), values); + g_once_init_leave(&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ +/*** END file-tail ***/ diff --git a/tests/project/modules/gnome/mkenums/enums.h.in b/tests/project/modules/gnome/mkenums/enums.h.in new file mode 100644 index 000000000..479867fd1 --- /dev/null +++ b/tests/project/modules/gnome/mkenums/enums.h.in @@ -0,0 +1,24 @@ +/*** BEGIN file-header ***/ +#ifndef MESON_ENUMS_H +#define MESON_ENUMS_H + +#include + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@basename@" */ +/*** END file-production ***/ +/*** BEGIN value-header ***/ +GType @enum_name@_get_type(void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ + +G_END_DECLS + +#endif /* MESON_ENUMS_H */ +/*** END file-tail ***/ diff --git a/tests/project/modules/gnome/mkenums/enums2.c.in b/tests/project/modules/gnome/mkenums/enums2.c.in new file mode 100644 index 000000000..1c19d8ffa --- /dev/null +++ b/tests/project/modules/gnome/mkenums/enums2.c.in @@ -0,0 +1,41 @@ +/*** BEGIN file-header ***/ + +#include "enums.h" + +/*** END file-header ***/ +/*** BEGIN file-production ***/ + +/* enumerations from "@basename@" */ +#include "@basename@" + +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type(void) { + static gsize static_g_define_type_id = 0; + + if(g_once_init_enter(&static_g_define_type_id)) { + static const G@Type@Value values [] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { @VALUENAME@, "@VALUENAME@", "@valuenick@" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + + GType g_define_type_id = + g_@type@_register_static(g_intern_static_string("@EnumName@"), values); + g_once_init_leave(&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} + +/*** END value-tail ***/ + +/*** BEGIN file-tail ***/ +/*** END file-tail ***/ diff --git a/tests/project/modules/gnome/mkenums/enums2.h.in b/tests/project/modules/gnome/mkenums/enums2.h.in new file mode 100644 index 000000000..479867fd1 --- /dev/null +++ b/tests/project/modules/gnome/mkenums/enums2.h.in @@ -0,0 +1,24 @@ +/*** BEGIN file-header ***/ +#ifndef MESON_ENUMS_H +#define MESON_ENUMS_H + +#include + +G_BEGIN_DECLS +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +/* enumerations from "@basename@" */ +/*** END file-production ***/ +/*** BEGIN value-header ***/ +GType @enum_name@_get_type(void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) +/*** END value-header ***/ + +/*** BEGIN file-tail ***/ + +G_END_DECLS + +#endif /* MESON_ENUMS_H */ +/*** END file-tail ***/ diff --git a/tests/project/modules/gnome/mkenums/main.c b/tests/project/modules/gnome/mkenums/main.c new file mode 100644 index 000000000..d257185dd --- /dev/null +++ b/tests/project/modules/gnome/mkenums/main.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include"meson-sample.h" +#include"@ENUM_FILE@" + +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; + } + g_type_class_unref(xenum); + g_type_class_unref(flags_enum); + fprintf(stderr, "All ok.\n"); + return 0; +} diff --git a/tests/project/modules/gnome/mkenums/main4.c b/tests/project/modules/gnome/mkenums/main4.c new file mode 100644 index 000000000..3df4dd88c --- /dev/null +++ b/tests/project/modules/gnome/mkenums/main4.c @@ -0,0 +1,35 @@ +#include +#include +#include +#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; +} diff --git a/tests/project/modules/gnome/mkenums/main5.c b/tests/project/modules/gnome/mkenums/main5.c new file mode 100644 index 000000000..ed1ccfd27 --- /dev/null +++ b/tests/project/modules/gnome/mkenums/main5.c @@ -0,0 +1,35 @@ +#include +#include +#include +#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; +} diff --git a/tests/project/modules/gnome/mkenums/meson-decls.h b/tests/project/modules/gnome/mkenums/meson-decls.h new file mode 100644 index 000000000..ba94eb94b --- /dev/null +++ b/tests/project/modules/gnome/mkenums/meson-decls.h @@ -0,0 +1,2 @@ +#pragma once +#define MESON_EXPORT extern diff --git a/tests/project/modules/gnome/mkenums/meson-sample.h b/tests/project/modules/gnome/mkenums/meson-sample.h new file mode 100644 index 000000000..ee7b5cbfb --- /dev/null +++ b/tests/project/modules/gnome/mkenums/meson-sample.h @@ -0,0 +1,20 @@ +#pragma once + +typedef enum +{ + MESON_THE_XVALUE, + MESON_ANOTHER_VALUE +} MesonTheXEnum; + +typedef enum /*< skip >*/ +{ + MESON_FOO +} MesonThisEnumWillBeSkipped; + +typedef enum /*< flags,prefix=MESON >*/ +{ + MESON_THE_ZEROTH_VALUE, /*< skip >*/ + MESON_THE_FIRST_VALUE, + MESON_THE_SECOND_VALUE, + MESON_THE_THIRD_VALUE, /*< nick=the-last-value >*/ +} MesonTheFlagsEnum; diff --git a/tests/project/modules/gnome/mkenums/meson.build b/tests/project/modules/gnome/mkenums/meson.build new file mode 100644 index 000000000..ed40a2eb2 --- /dev/null +++ b/tests/project/modules/gnome/mkenums/meson.build @@ -0,0 +1,176 @@ +# Generate both header and source via template together. + +myenums = gnome.mkenums( + 'abc1', + sources: 'meson-sample.h', + h_template: 'enums.h.in', + c_template: 'enums.c.in', + install_header: true, + install_dir: get_option('includedir'), +) + +enums_c1 = myenums[0] +enums_h1 = myenums[1] + +conf = configuration_data() +conf.set('ENUM_FILE', 'enums.h') +main = configure_file(input: 'main.c', output: 'main1.c', configuration: conf) + +enumexe1 = executable('enumprog1', main, enums_c1, enums_h1, dependencies: gobj) +test('enum test 1', enumexe1) + +# Generate both header and source via template individually and overriding. + +enums_h2 = gnome.mkenums( + 'abc2', + sources: 'meson-sample.h', + h_template: 'enums2.h.in', + ftail: '/* trailing header file info */', + install_header: true, + install_dir: get_option('includedir'), +) + +enums_c2 = gnome.mkenums( + 'abc2', + sources: 'meson-sample.h', + depends: [enums_h1, enums_h2], + c_template: 'enums2.c.in', + ftail: '/* trailing source file info */', +) +# explicitly don't set install_dir here, for bug testing +# See https://github.com/mesonbuild/meson/issues/9472 + +conf = configuration_data() +conf.set('ENUM_FILE', 'enums2.h') +main = configure_file(input: 'main.c', output: 'main2.c', configuration: conf) + +enumexe2 = executable('enumprog2', main, enums_c2, enums_h2, dependencies: gobj) +test('enum test 2', enumexe2) + +# Generate both header and source by options only. +# These are specified in a way that should produce the same result as above +# (modulo any filename changes.) + +enums_h3 = gnome.mkenums( + 'enums3.h', + sources: 'meson-sample.h', + fhead: '''#ifndef MESON_ENUMS_H +#define MESON_ENUMS_H + +#include + +G_BEGIN_DECLS +''', + fprod: ''' +/* enumerations from "@basename@" */ +''', + vhead: '''GType @enum_name@_get_type(void) G_GNUC_CONST; +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) +''', + ftail: ''' +G_END_DECLS + +#endif /* MESON_ENUMS_H */ +''', + install_header: true, + install_dir: get_option('includedir'), +) + +enums_c3 = gnome.mkenums( + 'enums3.c', + sources: 'meson-sample.h', + depends: enums_h3, + fhead: '''#include "enums3.h" +''', + fprod: ''' + +/* enumerations from "@basename@" */ +#include "@basename@" +''', + vhead: ''' +GType +@enum_name@_get_type(void) { + static gsize static_g_define_type_id = 0; + + if(g_once_init_enter(&static_g_define_type_id)) { + static const G@Type@Value values [] = { +''', + vprod: ''' { @VALUENAME@, "@VALUENAME@", "@valuenick@" },''', + vtail: ''' { 0, NULL, NULL } + }; + + GType g_define_type_id = + g_@type@_register_static(g_intern_static_string("@EnumName@"), values); + g_once_init_leave(&static_g_define_type_id, g_define_type_id); + } + + return static_g_define_type_id; +} +''', +) + +conf = configuration_data() +conf.set('ENUM_FILE', 'enums3.h') +main = configure_file(input: 'main.c', output: 'main3.c', configuration: conf) + +enumexe3 = executable('enumprog3', main, enums_c3, enums_h3, dependencies: gobj) +test('enum test 3', enumexe3) + +enums4 = gnome.mkenums_simple( + 'enums4', + sources: files('meson-sample.h'), + function_prefix: '_', +) +enumexe4 = executable('enumprog4', 'main4.c', enums4, dependencies: gobj) + +enums5 = gnome.mkenums_simple( + 'enums5', + sources: 'meson-sample.h', + install_header: true, + decorator: 'MESON_EXPORT', + header_prefix: '#include "meson-decls.h"', +) + +conf = configuration_data() +conf.set('ENUM_FILE', 'enums5.h') +main = configure_file(input: 'main.c', output: 'main5.c', configuration: conf) + +enumexe5 = executable('enumprog5', main, enums5, dependencies: gobj) + +# Generate template then use as input to mkenums + +# Simple trick to copy the file without substitutions, can be +# removed when https://github.com/mesonbuild/meson/pull/3383 is fixed +gen_h_template = configure_file( + input: 'enums.h.in', + output: 'enums6.h.in', + configuration: configuration_data(), + format: 'cmake', +) + +enums_h6 = gnome.mkenums( + 'enums6', + sources: 'meson-sample.h', + h_template: gen_h_template, + ftail: '/* trailing header file info */', + install_header: true, + install_dir: get_option('includedir'), +) + +conf = configuration_data() +conf.set('ENUM_FILE', 'enums6.h') +main = configure_file(input: 'main.c', output: 'main6.c', configuration: conf) + +enumexe6 = executable('enumprog6', main, enums_c2, enums_h6, dependencies: gobj) +test('enum test 4', enumexe6) + +# Test with headers coming from other directories +# https://github.com/mesonbuild/meson/pull/10855 +subdir('subdir') +enums7 = gnome.mkenums_simple('enums7', sources: ['meson-sample.h', h2, h3]) +main = configure_file( + input: 'main.c', + output: 'mai7.c', + configuration: {'ENUM_FILE': 'enums7.h'}, +) +test('enums7 test', executable('enumprog7', main, enums7, dependencies: gobj)) diff --git a/tests/project/modules/gnome/mkenums/subdir/h2.h.in b/tests/project/modules/gnome/mkenums/subdir/h2.h.in new file mode 100644 index 000000000..7b40c4be1 --- /dev/null +++ b/tests/project/modules/gnome/mkenums/subdir/h2.h.in @@ -0,0 +1,5 @@ +#pragma once + +typedef enum { + MESON_SUBDIR_FOO, +} MesonSubdir; diff --git a/tests/project/modules/gnome/mkenums/subdir/h3.h b/tests/project/modules/gnome/mkenums/subdir/h3.h new file mode 100644 index 000000000..9049d5c22 --- /dev/null +++ b/tests/project/modules/gnome/mkenums/subdir/h3.h @@ -0,0 +1,5 @@ +#pragma once + +typedef enum { + MESON_SUBDIR2_FOO, +} MesonSubdir2; diff --git a/tests/project/modules/gnome/mkenums/subdir/meson.build b/tests/project/modules/gnome/mkenums/subdir/meson.build new file mode 100644 index 000000000..0b03846f2 --- /dev/null +++ b/tests/project/modules/gnome/mkenums/subdir/meson.build @@ -0,0 +1,2 @@ +h2 = configure_file(input: 'h2.h.in', output: 'h2.h', copy: true) +h3 = files('h3.h') diff --git a/tests/project/modules/gnome/resources-data/meson.build b/tests/project/modules/gnome/resources-data/meson.build new file mode 100644 index 000000000..1c51f27d2 --- /dev/null +++ b/tests/project/modules/gnome/resources-data/meson.build @@ -0,0 +1,19 @@ +subdir('subdir') + +python3 = import('python3').find_python() + +fake_generator_script = ''' +import os, sys +assert os.path.exists(sys.argv[1]), "File %s not found" % sys.argv[1] +print("This is a generated resource.") +''' + +# Generate file res3.txt from file res3.txt.in. This is then included +# in a GResource file, driven by resources/meson.build. +res3_txt = custom_target( + 'res3', + input: 'res3.txt.in', + output: 'res3.txt', + command: [python3, '-c', fake_generator_script, '@INPUT@'], + capture: true, +) diff --git a/tests/project/modules/gnome/resources-data/res1.txt b/tests/project/modules/gnome/resources-data/res1.txt new file mode 100644 index 000000000..e10afea83 --- /dev/null +++ b/tests/project/modules/gnome/resources-data/res1.txt @@ -0,0 +1 @@ +This is a resource. diff --git a/tests/project/modules/gnome/resources-data/res3.txt.in b/tests/project/modules/gnome/resources-data/res3.txt.in new file mode 100644 index 000000000..077a8e301 --- /dev/null +++ b/tests/project/modules/gnome/resources-data/res3.txt.in @@ -0,0 +1 @@ +This content is ignored, but Meson doesn't need to know that. diff --git a/tests/project/modules/gnome/resources-data/subdir/meson.build b/tests/project/modules/gnome/resources-data/subdir/meson.build new file mode 100644 index 000000000..b3eeb3893 --- /dev/null +++ b/tests/project/modules/gnome/resources-data/subdir/meson.build @@ -0,0 +1,8 @@ +cdata = configuration_data() +cdata.set('NOISE', 'BARK') + +res4_txt = configure_file( + input: 'res4.txt.in', + output: 'res4.txt', + configuration: cdata, +) diff --git a/tests/project/modules/gnome/resources-data/subdir/res2.txt b/tests/project/modules/gnome/resources-data/subdir/res2.txt new file mode 100644 index 000000000..d297899bb --- /dev/null +++ b/tests/project/modules/gnome/resources-data/subdir/res2.txt @@ -0,0 +1 @@ +This is a resource in a subdirectory. diff --git a/tests/project/modules/gnome/resources-data/subdir/res4.txt.in b/tests/project/modules/gnome/resources-data/subdir/res4.txt.in new file mode 100644 index 000000000..c0ec6f2a2 --- /dev/null +++ b/tests/project/modules/gnome/resources-data/subdir/res4.txt.in @@ -0,0 +1 @@ +@NOISE@ @NOISE@ @NOISE@ diff --git a/tests/project/modules/gnome/resources/generated-main.c b/tests/project/modules/gnome/resources/generated-main.c new file mode 100644 index 000000000..d1026044b --- /dev/null +++ b/tests/project/modules/gnome/resources/generated-main.c @@ -0,0 +1,26 @@ +#include +#include +#include +#include"generated-resources.h" + +#define EXPECTED "This is a generated resource.\n" + +int main(int argc, char **argv) { + generated_resources_get_resource(); + GError *err = NULL; + GBytes *data = g_resources_lookup_data("/com/example/myprog/res3.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, &err); + + if(data == NULL) { + fprintf(stderr, "Data lookup failed: %s\n", err->message); + return 1; + } + if(strcmp(g_bytes_get_data(data, NULL), EXPECTED) != 0) { + fprintf(stderr, "Resource contents are wrong:\n %s\n", + (const char*)g_bytes_get_data(data, NULL)); + return 1; + } + fprintf(stdout, "All ok.\n"); + g_bytes_unref(data); + return 0; +} diff --git a/tests/project/modules/gnome/resources/generated.gresource.xml b/tests/project/modules/gnome/resources/generated.gresource.xml new file mode 100644 index 000000000..7a242d702 --- /dev/null +++ b/tests/project/modules/gnome/resources/generated.gresource.xml @@ -0,0 +1,9 @@ + + + + res1.txt + subdir/res2.txt + res3.txt + subdir/res4.txt + + diff --git a/tests/project/modules/gnome/resources/generated/meson.build b/tests/project/modules/gnome/resources/generated/meson.build new file mode 100644 index 000000000..ab7eaf291 --- /dev/null +++ b/tests/project/modules/gnome/resources/generated/meson.build @@ -0,0 +1,5 @@ +ct_simple_gresource = custom_target( + input: '../simple.gresource.xml', + output: 'simple-ct.gresource.xml', + command: [copyfile, '@INPUT@', '@OUTPUT@'], +) diff --git a/tests/project/modules/gnome/resources/meson.build b/tests/project/modules/gnome/resources/meson.build new file mode 100644 index 000000000..4aad29081 --- /dev/null +++ b/tests/project/modules/gnome/resources/meson.build @@ -0,0 +1,87 @@ +# There are two tests here, because the 2nd one depends on a version of +# GLib (2.51.1) that is very recent at the time of writing. + +simple_gresource = configure_file( + input: 'simple.gresource.xml', + output: 'simple-gen.gresource.xml', + command: [copyfile, '@INPUT@', '@OUTPUT@'], +) + +simple_resources = gnome.compile_resources( + 'simple-resources', + simple_gresource, + install_header: true, + export: true, + source_dir: '../resources-data', + c_name: 'simple_resources', +) + +simple_res_exe = executable( + 'simple-resources-test', + 'simple-main.c', + simple_resources, + dependencies: gio, +) +test('simple resource test', simple_res_exe) + +gnome.compile_resources( + 'simple-resources', + 'simple.gresource.xml', + gresource_bundle: true, + install: true, + install_dir: get_option('datadir'), + source_dir: '../resources-data', +) +test('simple resource test (gresource)', find_program('resources.py')) + +if not pretend_glib_old and glib.version().version_compare('>= 2.52.0') + # This test cannot pass if GLib version is too old. Generated resource + # dependencies do not work correctly and Meson will raise an error if the + # user tries to use either the 'dependencies' kwarg or a gresource file that + # is itself generated. + generated_resources = gnome.compile_resources( + 'generated-resources', + 'generated.gresource.xml', + source_dir: '../resources-data', + c_name: 'generated_resources', + dependencies: [res3_txt, res4_txt], + ) + + generated_res_exe = executable( + 'generated-resources-test', + 'generated-main.c', + generated_resources, + dependencies: gio, + ) + test('generated resource test', generated_res_exe) + + # Test with a CustomTarget + subdir('generated') + + ct_resources = gnome.compile_resources( + 'ct-resources', + ct_simple_gresource, + install_header: true, + export: true, + source_dir: '../resources-data', + c_name: 'simple_resources', + ) + + cti_resources = gnome.compile_resources( + 'cti-resources', + ct_simple_gresource[0], + install_header: true, + export: true, + source_dir: '../resources-data', + c_name: 'simple_resources', + ) +endif + +# Test build_by_default +gnome.compile_resources( + 'build-resources', + 'simple.gresource.xml', + gresource_bundle: true, + build_by_default: true, + source_dir: '../resources-data', +) diff --git a/tests/project/modules/gnome/resources/myresource.gresource.xml b/tests/project/modules/gnome/resources/myresource.gresource.xml new file mode 100644 index 000000000..7a242d702 --- /dev/null +++ b/tests/project/modules/gnome/resources/myresource.gresource.xml @@ -0,0 +1,9 @@ + + + + res1.txt + subdir/res2.txt + res3.txt + subdir/res4.txt + + diff --git a/tests/project/modules/gnome/resources/res3.txt b/tests/project/modules/gnome/resources/res3.txt new file mode 100644 index 000000000..aeed4a552 --- /dev/null +++ b/tests/project/modules/gnome/resources/res3.txt @@ -0,0 +1 @@ +This file is from the wrong directory. diff --git a/tests/project/modules/gnome/resources/resources.py b/tests/project/modules/gnome/resources/resources.py new file mode 100644 index 000000000..0855ef744 --- /dev/null +++ b/tests/project/modules/gnome/resources/resources.py @@ -0,0 +1,10 @@ +#!/usr/bin/env python3 +import os +from gi.repository import Gio + +if __name__ == '__main__': + res = Gio.resource_load(os.path.join('resources', 'simple-resources.gresource')) + Gio.Resource._register(res) + + data = Gio.resources_lookup_data('/com/example/myprog/res1.txt', Gio.ResourceLookupFlags.NONE) + assert data.get_data() == b'This is a resource.\n' diff --git a/tests/project/modules/gnome/resources/simple-main.c b/tests/project/modules/gnome/resources/simple-main.c new file mode 100644 index 000000000..c021a546c --- /dev/null +++ b/tests/project/modules/gnome/resources/simple-main.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include"simple-resources.h" + +#define EXPECTED "This is a resource.\n" + +int main(int argc, char **argv) { + simple_resources_get_resource(); + + GError *err = NULL; + GBytes *data = g_resources_lookup_data("/com/example/myprog/res1.txt", + G_RESOURCE_LOOKUP_FLAGS_NONE, &err); + + if(data == NULL) { + fprintf(stderr, "Data lookup failed: %s\n", err->message); + return 1; + } + if(strcmp(g_bytes_get_data(data, NULL), EXPECTED) != 0) { + fprintf(stderr, "Resource contents are wrong:\n %s\n", + (const char*)g_bytes_get_data(data, NULL)); + return 1; + } + fprintf(stdout, "All ok.\n"); + g_bytes_unref(data); + return 0; +} diff --git a/tests/project/modules/gnome/resources/simple.gresource.xml b/tests/project/modules/gnome/resources/simple.gresource.xml new file mode 100644 index 000000000..6e5591051 --- /dev/null +++ b/tests/project/modules/gnome/resources/simple.gresource.xml @@ -0,0 +1,7 @@ + + + + res1.txt + subdir/res2.txt + + diff --git a/tests/project/modules/gnome/schemas/com.github.meson.gschema.xml b/tests/project/modules/gnome/schemas/com.github.meson.gschema.xml new file mode 100644 index 000000000..741518dba --- /dev/null +++ b/tests/project/modules/gnome/schemas/com.github.meson.gschema.xml @@ -0,0 +1,12 @@ + + + + + "Hello" + A greeting + + Sample text to test schema compilation + + + + \ No newline at end of file diff --git a/tests/project/modules/gnome/schemas/meson.build b/tests/project/modules/gnome/schemas/meson.build new file mode 100644 index 000000000..92b2ea38c --- /dev/null +++ b/tests/project/modules/gnome/schemas/meson.build @@ -0,0 +1,8 @@ +compiled = gnome.compile_schemas(build_by_default: true) +install_data( + 'com.github.meson.gschema.xml', + install_dir: 'share/glib-2.0/schemas', +) + +schemaexe = executable('schemaprog', 'schemaprog.c', dependencies: gio) +test('schema test', schemaexe) diff --git a/tests/project/modules/gnome/schemas/schemaprog.c b/tests/project/modules/gnome/schemas/schemaprog.c new file mode 100644 index 000000000..17dab6514 --- /dev/null +++ b/tests/project/modules/gnome/schemas/schemaprog.c @@ -0,0 +1,47 @@ +#include +#include +#include + +int main(int argc, char **argv) { + GSettingsSchemaSource *src; + GSettingsSchema *schema; + GSettings *settings; + GVariant *value; + + GError *error = NULL; + src = g_settings_schema_source_new_from_directory("schemas", + g_settings_schema_source_get_default(), TRUE, &error); + if(error) { + fprintf(stderr, "Fail: %s\n", error->message); + g_error_free(error); + return 1; + } + + schema = g_settings_schema_source_lookup(src, "com.github.meson", FALSE); + if(!schema) { + fprintf(stderr, "Could not get schema from source.\n"); + return 2; + } + + settings = g_settings_new_full(schema, NULL, NULL); + if(!settings) { + fprintf(stderr, "Could not get settings object.\n"); + return 3; + } + + value = g_settings_get_value(settings, "greeting"); + if(!value) { + fprintf(stderr, "Could not get value from settings.\n"); + return 4; + } + + if(strcmp("Hello", g_variant_get_string(value, NULL)) != 0) { + fprintf(stderr, "Value of setting is incorrect.\n"); + return 5; + } + g_variant_unref(value); + g_object_unref(settings); + g_settings_schema_unref(schema); + g_settings_schema_source_unref(src); + return 0; +} diff --git a/tests/project/modules/gnome/test.json b/tests/project/modules/gnome/test.json new file mode 100644 index 000000000..f75ba131d --- /dev/null +++ b/tests/project/modules/gnome/test.json @@ -0,0 +1,40 @@ +{ + "installed": [ + {"type": "file", "file": "usr/include/ct-resources.h"}, + {"type": "file", "file": "usr/include/cti-resources.h"}, + {"type": "file", "file": "usr/include/enums.h"}, + {"type": "file", "file": "usr/include/enums2.h"}, + {"type": "file", "file": "usr/include/enums3.h"}, + {"type": "file", "file": "usr/include/enums5.h"}, + {"type": "file", "file": "usr/include/subdir-0/marshaller-0.h"}, + {"type": "file", "file": "usr/include/subdir-1/marshaller-1.h"}, + {"type": "file", "file": "usr/include/subdir-2/marshaller-2.h"}, + {"type": "file", "file": "usr/include/subdir-3/marshaller-3.h"}, + {"type": "file", "file": "usr/include/subdir-4/marshaller-4.h"}, + {"type": "file", "file": "usr/include/subdir-5/marshaller-5.h"}, + {"type": "expr", "file": "usr/lib/?libgir_lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgir_lib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libgir_lib2.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libgir_lib2.dll.a"}, + {"type": "expr", "file": "usr/lib/?libdep1lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep1lib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libdep2lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep2lib.dll.a"}, + {"type": "expr", "file": "usr/lib/?libdep3lib.so"}, + {"type": "file", "platform": "cygwin", "file": "usr/lib/libdep3lib.dll.a"}, + {"type": "file", "file": "usr/lib/girepository-1.0/Meson-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep1-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep2-1.0.typelib"}, + {"type": "file", "file": "usr/lib/girepository-1.0/MesonDep3-1.0.typelib"}, + {"type": "file", "file": "usr/share/gir-1.0/Meson-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonDep1-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonDep2-1.0.gir"}, + {"type": "file", "file": "usr/share/gir-1.0/MesonDep3-1.0.gir"}, + {"type": "file", "file": "usr/share/glib-2.0/schemas/com.github.meson.gschema.xml"}, + {"type": "file", "file": "usr/share/simple-resources.gresource"}, + {"type": "file", "file": "usr/include/enums6.h"}, + {"type": "file", "file": "usr/include/simple-resources.h"}, + {"type": "file", "file": "usr/include/generated-gdbus.h"} + ], + "skip_on_jobname": ["azure", "cygwin", "macos", "msys2", "pypy"] +}