[gcr/wip/nielsdg/meson] Support Meson build system



commit a705acc3640e825d9b83bc37663d13950677728c
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Sun Dec 30 00:40:17 2018 +0100

    Support Meson build system

 .gitlab-ci.yml                   |  23 +++
 .gitlab-ci/meson-junit-report.py | 109 ++++++++++++++
 .gitlab-ci/run-tests.sh          |  15 ++
 docs/meson.build                 |   2 +
 docs/reference/gck/meson.build   |  36 +++++
 docs/reference/gcr/meson.build   |  76 ++++++++++
 egg/meson.build                  |  78 ++++++++++
 gck/gck-test.h                   |   4 +
 gck/libgck.map                   |   7 +
 gck/meson.build                  | 208 ++++++++++++++++++++++++++
 gck/test-gck-crypto.c            |   2 +-
 gck/test-gck-enumerator.c        |   2 +-
 gck/test-gck-module.c            |   6 +-
 gck/test-gck-modules.c           |   2 +-
 gck/test-gck-object.c            |   2 +-
 gck/test-gck-session.c           |   2 +-
 gck/test-gck-slot.c              |   2 +-
 gcr/libgcr-base.map              |   8 +
 gcr/meson.build                  | 314 +++++++++++++++++++++++++++++++++++++++
 gcr/test-ssh-askpass.c           |   4 +
 meson.build                      |  96 ++++++++++++
 meson_options.txt                |  15 ++
 meson_post_install.py            |  51 +++++++
 po/meson.build                   |   3 +
 schema/meson.build               |  13 ++
 ui/icons/meson.build             |  33 ++++
 ui/libgcr-ui.map                 |   8 +
 ui/meson.build                   | 253 +++++++++++++++++++++++++++++++
 28 files changed, 1365 insertions(+), 9 deletions(-)
---
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 18825f0..e3c446c 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -5,6 +5,29 @@ stages:
 variables:
   DEPENDENCIES: dbus-x11 diffutils gcc gtk-doc make openssh python redhat-rpm-config
 
+fedora:meson:
+  image: fedora:latest
+  stage: build
+  before_script:
+    - dnf install -y 'dnf-command(builddep)'
+    - dnf builddep -y gcr
+    - dnf install -y $DEPENDENCIES meson ninja-build
+    - dbus-uuidgen --ensure
+  script:
+    - meson _build
+    - ninja -C _build
+    - eval `dbus-launch --sh-syntax`
+    - bash +x ./.gitlab-ci/run-tests.sh
+  artifacts:
+    reports:
+      junit: "_build/${CI_JOB_NAME}-report.xml"
+    name: "gcr-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}"
+    when: always
+    paths:
+      - "_build/config.h"
+      - "_build/meson-logs"
+      - "_build/${CI_JOB_NAME}-report.xml"
+
 fedora:Werror:
   image: fedora:latest
   stage: build
diff --git a/.gitlab-ci/meson-junit-report.py b/.gitlab-ci/meson-junit-report.py
new file mode 100755
index 0000000..248ef6e
--- /dev/null
+++ b/.gitlab-ci/meson-junit-report.py
@@ -0,0 +1,109 @@
+#!/usr/bin/env python3
+
+# Turns a Meson testlog.json file into a JUnit XML report
+#
+# Copyright 2019  GNOME Foundation
+#
+# SPDX-License-Identifier: LGPL-2.1-or-later
+#
+# Original author: Emmanuele Bassi
+
+import argparse
+import datetime
+import json
+import os
+import sys
+import xml.etree.ElementTree as ET
+
+aparser = argparse.ArgumentParser(description='Turns a Meson test log into a JUnit report')
+aparser.add_argument('--project-name', metavar='NAME',
+                     help='The project name',
+                     default='unknown')
+aparser.add_argument('--job-id', metavar='ID',
+                     help='The job ID for the report',
+                     default='Unknown')
+aparser.add_argument('--branch', metavar='NAME',
+                     help='Branch of the project being tested',
+                     default='master')
+aparser.add_argument('--output', metavar='FILE',
+                     help='The output file, stdout by default',
+                     type=argparse.FileType('w', encoding='UTF-8'),
+                     default=sys.stdout)
+aparser.add_argument('infile', metavar='FILE',
+                     help='The input testlog.json, stdin by default',
+                     type=argparse.FileType('r', encoding='UTF-8'),
+                     default=sys.stdin)
+
+args = aparser.parse_args()
+
+outfile = args.output
+
+testsuites = ET.Element('testsuites')
+testsuites.set('id', '{}/{}'.format(args.job_id, args.branch))
+testsuites.set('package', args.project_name)
+testsuites.set('timestamp', datetime.datetime.utcnow().isoformat(timespec='minutes'))
+
+suites = {}
+for line in args.infile:
+    data = json.loads(line)
+    (full_suite, unit_name) = data['name'].split(' / ')
+    (project_name, suite_name) = full_suite.split(':')
+
+    duration = data['duration']
+    return_code = data['returncode']
+    log = data['stdout']
+
+    unit = {
+        'suite': suite_name,
+        'name': unit_name,
+        'duration': duration,
+        'returncode': return_code,
+        'stdout': log,
+    }
+
+    units = suites.setdefault(suite_name, [])
+    units.append(unit)
+
+for name, units in suites.items():
+    print('Processing suite {} (units: {})'.format(name, len(units)))
+
+    def if_failed(unit):
+        if unit['returncode'] != 0:
+            return True
+        return False
+
+    def if_succeded(unit):
+        if unit['returncode'] == 0:
+            return True
+        return False
+
+    successes = list(filter(if_succeded, units))
+    failures = list(filter(if_failed, units))
+    print(' - {}: {} pass, {} fail'.format(name, len(successes), len(failures)))
+
+    testsuite = ET.SubElement(testsuites, 'testsuite')
+    testsuite.set('name', '{}/{}'.format(args.project_name, name))
+    testsuite.set('tests', str(len(units)))
+    testsuite.set('errors', str(len(failures)))
+    testsuite.set('failures', str(len(failures)))
+
+    for unit in successes:
+        testcase = ET.SubElement(testsuite, 'testcase')
+        testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
+        testcase.set('name', unit['name'])
+        testcase.set('time', str(unit['duration']))
+
+    for unit in failures:
+        testcase = ET.SubElement(testsuite, 'testcase')
+        testcase.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
+        testcase.set('name', unit['name'])
+        testcase.set('time', str(unit['duration']))
+
+        failure = ET.SubElement(testcase, 'failure')
+        failure.set('classname', '{}/{}'.format(args.project_name, unit['suite']))
+        failure.set('name', unit['name'])
+        failure.set('type', 'error')
+        failure.text = unit['stdout']
+
+output = ET.tostring(testsuites, encoding='unicode')
+outfile.write(output)
diff --git a/.gitlab-ci/run-tests.sh b/.gitlab-ci/run-tests.sh
new file mode 100755
index 0000000..f6b7dba
--- /dev/null
+++ b/.gitlab-ci/run-tests.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+set +e
+
+meson test -C _build
+
+exit_code=$?
+
+python3 .gitlab-ci/meson-junit-report.py \
+        --project-name=gcr \
+        --job-id "${CI_JOB_NAME}" \
+        --output "_build/${CI_JOB_NAME}-report.xml" \
+        _build/meson-logs/testlog.json
+
+exit $exit_code
diff --git a/docs/meson.build b/docs/meson.build
new file mode 100644
index 0000000..f353516
--- /dev/null
+++ b/docs/meson.build
@@ -0,0 +1,2 @@
+subdir('reference/gck')
+subdir('reference/gcr')
diff --git a/docs/reference/gck/meson.build b/docs/reference/gck/meson.build
new file mode 100644
index 0000000..220d9db
--- /dev/null
+++ b/docs/reference/gck/meson.build
@@ -0,0 +1,36 @@
+version_xml = configure_file(
+  input: 'version.xml.in',
+  output: '@BASENAME@',
+  configuration: { 'VERSION': gck_version },
+)
+
+gck_docs_ignore_headers = [
+  'gck-private.h',
+  'test-suite.h',
+  'gck-mock.h',
+  'gck-test.h',
+  'pkcs11-trust-assertions.h',
+  'pkcs11.h',
+  'pkcs11n.h',
+  'pkcs11x.h',
+  'pkcs11i.h',
+]
+
+gnome.gtkdoc('gck',
+  main_sgml: 'gck-docs.sgml',
+  content_files: files(
+    'gck-pkcs11-links.xml',
+  ),
+  src_dir: [
+    include_directories('../../../gck'),
+  ],
+  ignore_headers: gck_docs_ignore_headers,
+  dependencies: gck_dep,
+  gobject_typesfile: 'gck.types',
+  scan_args: [
+    '--rebuild-types',
+    '--deprecated-guards=GCK_DISABLE_DEPRECATED',
+  ],
+  install: true,
+)
+
diff --git a/docs/reference/gcr/meson.build b/docs/reference/gcr/meson.build
new file mode 100644
index 0000000..831a919
--- /dev/null
+++ b/docs/reference/gcr/meson.build
@@ -0,0 +1,76 @@
+version_xml = configure_file(
+  input: 'version.xml.in',
+  output: '@BASENAME@',
+  configuration: { 'VERSION': gcr_version },
+)
+
+gcr_docs_images = [
+  'images/certificate-widget.png',
+  'images/combo-selector.png',
+  'images/import-button.png',
+  'images/list-selector.png',
+  'images/key-widget.png',
+  'images/tree-selector.png',
+  'images/viewer-widget.png',
+]
+
+gcr_docs_ignore_headers = [
+  'console-interaction.h',
+  'eggimagemenuitem.h',
+  'gcr-callback-output-stream.h',
+  'gcr-certificate-exporter.h',
+  'gcr-certificate-basics-widget.h',
+  'gcr-certificate-details-widget.h',
+  'gcr-certificate-request-renderer.h',
+  'gcr-dbus-constants.h',
+  'gcr-dbus-generated.h',
+  'gcr-deprecated.h',
+  'gcr-deprecated-base.h',
+  'gcr-display-scrolled.h',
+  'gcr-display-view.h',
+  'gcr-failure-renderer.h',
+  'gcr-gnupg-importer.h',
+  'gcr-gnupg-renderer.h',
+  'gcr-icons.h',
+  'gcr-import-dialog.h',
+  'gcr-internal.h',
+  'gcr-live-search.h',
+  'gcr-marshal.h',
+  'gcr-menu-button.h',
+  'gcr-oids.h',
+  'gcr-openpgp.h',
+  'gcr-pkcs11-importer.h',
+  'gcr-pkcs11-import-interaction.h',
+  'gcr-pkcs11-import-dialog.h',
+  'gcr-pkcs11-renderer.h',
+  'gcr-record.h',
+  'gcr-single-collection.h',
+  'gcr-unlock-renderer.h',
+  'gcr-viewer-window.h',
+  'gcr-xxx.h',
+  'gcr-zzz.h',
+]
+
+gnome.gtkdoc('gcr',
+  main_sgml: 'gcr-docs.sgml',
+  content_files: files(
+    'gcr-visual-index.xml',
+  ),
+  src_dir: [
+    include_directories('../../../gcr'),
+    include_directories('../../../ui'),
+  ],
+  ignore_headers: gcr_docs_ignore_headers,
+  dependencies: [ gcr_base_dep, gcr_ui_dep ],
+  gobject_typesfile: 'gcr.types',
+  html_assets: gcr_docs_images,
+  scan_args: [
+    '--rebuild-types',
+    '--deprecated-guards=GCR_DISABLE_DEPRECATED',
+  ],
+  install: true,
+)
+
+install_data(gcr_docs_images,
+  install_dir: gnome.gtkdoc_html_dir('gcr'),
+)
diff --git a/egg/meson.build b/egg/meson.build
new file mode 100644
index 0000000..f0dcab3
--- /dev/null
+++ b/egg/meson.build
@@ -0,0 +1,78 @@
+libegg_sources = [
+  'egg-armor.c',
+  'egg-asn1x.c',
+  'egg-asn1-defs.c',
+  'egg-buffer.c',
+  'egg-dh.c',
+  'egg-dn.c',
+  'egg-decimal.c',
+  'egg-hex.c',
+  'egg-hkdf.c',
+  'egg-libgcrypt.c',
+  'egg-oid.c',
+  'egg-padding.c',
+  'egg-openssl.c',
+  'egg-secure-memory.c',
+  'egg-symkey.c',
+  'egg-testing.c',
+  'egg-timegm.c',
+]
+
+libegg_deps = [
+  glib_deps,
+  libgcrypt_dep,
+]
+
+libegg = static_library('egg',
+  libegg_sources,
+  dependencies: libegg_deps,
+  include_directories: config_h_dir,
+)
+
+libegg_dep = declare_dependency(
+  link_with: libegg,
+  dependencies: libegg_deps,
+)
+
+# Tests
+egg_test_lib = static_library('egg-test',
+  sources: [ 'egg-testing.c', 'mock-interaction.c' ],
+  dependencies: glib_deps,
+  include_directories: config_h_dir,
+)
+
+egg_test_names = [
+  'asn1',
+  'asn1x',
+  'dn',
+  'decimal',
+  'hex',
+  'hkdf',
+  'oid',
+  'secmem',
+  'padding',
+  'symkey',
+  'armor',
+  'openssl',
+  'dh',
+]
+
+egg_test_cflags = [
+  '-DSRCDIR="@0@"'.format(source_root),
+]
+
+foreach _test : egg_test_names
+  _test_name = 'egg-'+_test
+
+  egg_test_bin = executable(_test_name,
+    'test-@0@.c'.format(_test),
+    link_with: egg_test_lib,
+    dependencies: libegg_dep,
+    c_args: egg_test_cflags,
+    include_directories: config_h_dir,
+  )
+
+  test(_test, egg_test_bin,
+    suite: 'egg',
+  )
+endforeach
diff --git a/gck/gck-test.h b/gck/gck-test.h
index dfefbb0..5a8f01b 100644
--- a/gck/gck-test.h
+++ b/gck/gck-test.h
@@ -27,6 +27,10 @@
 #ifndef GCK_TEST_H
 #define GCK_TEST_H
 
+#ifndef _GCK_TEST_MODULE_PATH
+#define _GCK_TEST_MODULE_PATH BUILDDIR "/.libs/libmock-test-module.so"
+#endif
+
 #define         gck_assert_cmprv(v1, cmp, v2) \
                do { CK_RV __v1 = (v1), __v2 = (v2); \
                        if (__v1 cmp __v2) ; else \
diff --git a/gck/libgck.map b/gck/libgck.map
new file mode 100644
index 0000000..b71b7e4
--- /dev/null
+++ b/gck/libgck.map
@@ -0,0 +1,7 @@
+{
+global:
+  gck_*;
+  SECMEM_*;
+local:
+  *;
+};
diff --git a/gck/meson.build b/gck/meson.build
new file mode 100644
index 0000000..917993f
--- /dev/null
+++ b/gck/meson.build
@@ -0,0 +1,208 @@
+gck_headers_install_dir = 'gck-@0@'.format(gck_major_version) / 'gck'
+
+gck_sources_public = files(
+  'gck-attributes.c',
+  'gck-dump.c',
+  'gck-enumerator.c',
+  'gck-misc.c',
+  'gck-module.c',
+  'gck-modules.c',
+  'gck-object.c',
+  'gck-object-cache.c',
+  'gck-password.c',
+  'gck-session.c',
+  'gck-slot.c',
+  'gck-uri.c',
+)
+
+gck_sources_private = files(
+  'gck-call.c',
+  'gck-interaction.c',
+)
+
+gck_headers = files(
+  'gck.h',
+)
+
+# Generated sources
+gck_version_conf = {
+  'GCR_MAJOR': gck_major_version,
+  'GCR_MINOR': gck_minor_version,
+  'GCR_MICRO': gck_micro_version,
+}
+gck_version_h = configure_file(input: 'gck-version.h.in',
+  output: 'gck-version.h',
+  configuration: gck_version_conf,
+)
+
+gck_enums_gen = gnome.mkenums_simple('gck-enum-types',
+  sources: gck_headers,
+  install_header: true,
+  install_dir: get_option('includedir') / gck_headers_install_dir,
+)
+
+gck_marshal_gen = gnome.genmarshal('gck-marshal',
+  sources: 'gck-marshal.list',
+  prefix: '_gck_marshal',
+)
+
+gck_sources = [
+  gck_sources_public,
+  gck_sources_private,
+  gck_enums_gen,
+  gck_marshal_gen,
+]
+
+gck_exported_headers = [
+  gck_headers,
+  gck_version_h,
+  'gck-deprecated.h',
+  'pkcs11.h',
+  'pkcs11n.h',
+  'pkcs11x.h',
+]
+
+install_headers(gck_exported_headers,
+  subdir: gck_headers_install_dir,
+)
+
+gck_deps = [
+  glib_deps,
+  p11kit_dep,
+  libegg_dep,
+]
+
+gck_cflags = [
+  '-DG_LOG_DOMAIN="@0@"'.format('Gck'),
+  '-DGCK_API_SUBJECT_TO_CHANGE',
+  '-DP11_KIT_API_SUBJECT_TO_CHANGE',
+  '-DPKCS11_REGISTRY_DIR="@0@"'.format(get_option('prefix') / get_option('libdir') / 'pkcs11'),
+]
+
+gck_symbolmap = meson.current_source_dir() / 'libgck.map'
+gck_linkflags = cc.get_supported_link_arguments(
+  '-Wl,--version-script,@0@'.format(gck_symbolmap),
+)
+
+gck_lib = shared_library('gck-@0@'.format(gck_major_version),
+  gck_sources,
+  dependencies: gck_deps,
+  c_args: gck_cflags,
+  link_args: gck_linkflags,
+  link_depends: gck_symbolmap,
+  include_directories: config_h_dir,
+  version: gck_soversion,
+  install: true,
+)
+
+gck_dep = declare_dependency(
+  link_with: gck_lib,
+  include_directories: include_directories('..'),
+  sources: gck_enums_gen[1], # Make sure gck-enum-types.h can be included
+)
+
+# We create an extra version of GCK which exposes internal functions
+# (for testing purposes)
+gck_testable_lib = library('gck-testable',
+  gck_sources,
+  dependencies: gck_deps,
+  c_args: gck_cflags,
+  include_directories: config_h_dir,
+)
+
+gck_testable_dep = declare_dependency(
+  link_with: gck_testable_lib,
+  include_directories: include_directories('..'),
+  sources: gck_enums_gen[1], # Make sure gck-enum-types.h can be included
+)
+
+# GObject introspection (GIR) file
+gck_gir_sources = [
+  gck_sources_public,
+  gck_headers,
+  gck_enums_gen[1],
+  gck_version_h,
+]
+
+if get_option('introspection')
+  gck_gir = gnome.generate_gir(gck_lib,
+    sources: gck_gir_sources,
+    namespace: 'Gck',
+    nsversion: '@0@'.format(gck_major_version),
+    packages: gck_deps,
+    export_packages: 'gck-@0@'.format(gck_major_version),
+    includes: [ 'GObject-2.0', 'Gio-2.0' ],
+    header: 'gck/gck.h',
+    extra_args: [
+      '-DGCK_COMPILATION',
+      '-DGCK_API_SUBJECT_TO_CHANGE',
+    ],
+    install: true,
+  )
+
+  gck_vapi = gnome.generate_vapi('gck-@0@'.format(gck_major_version),
+    sources: gck_gir[0],
+    metadata_dirs: meson.current_source_dir(),
+    packages: [ 'glib-2.0', 'gio-2.0' ],
+    install: true,
+  )
+
+  install_data('pkcs11.vapi',
+    install_dir: get_option('datadir') / 'vala' / 'vapi',
+  )
+endif
+
+# pkg-config file
+pkgconfig.generate(gck_lib,
+  description: 'GObject bindings for PKCS#11',
+  subdirs: 'gck-@0@'.format(gck_major_version),
+)
+
+# tests
+gck_test_lib = library('gck-test',
+  sources: [ 'gck-mock.c', 'gck-test.c' ],
+  dependencies: [ gck_deps, gck_testable_dep ],
+  c_args: gck_cflags,
+  include_directories: config_h_dir,
+)
+
+gck_mock_test_lib = shared_library('mock-test-module',
+  sources: 'mock-test-module.c',
+  link_with: gck_test_lib,
+  dependencies: [ gck_deps, gck_dep ],
+  c_args: gck_cflags,
+  include_directories: config_h_dir,
+)
+
+gck_test_names = [
+  'attributes',
+  'module',
+  'slot',
+  'session',
+  'object',
+  'crypto',
+  'uri',
+  'enumerator',
+  'modules',
+]
+
+gck_test_cflags = [
+  '-D_GCK_TEST_MODULE_PATH="@0@"'.format(gck_mock_test_lib.full_path()),
+]
+
+foreach _test : gck_test_names
+  _test_name = 'test-gck-'+_test
+
+  gck_test_bin = executable(_test_name,
+    '@0@.c'.format(_test_name),
+    link_with: [ gck_test_lib, egg_test_lib ],
+    dependencies: [ gck_deps, gck_testable_dep ],
+    c_args: gck_cflags + gck_test_cflags,
+    include_directories: config_h_dir,
+  )
+
+  test(_test, gck_test_bin,
+    suite: 'gck',
+    depends: gck_mock_test_lib,
+  )
+endforeach
diff --git a/gck/test-gck-crypto.c b/gck/test-gck-crypto.c
index 0cb3e2b..8efff23 100644
--- a/gck/test-gck-crypto.c
+++ b/gck/test-gck-crypto.c
@@ -56,7 +56,7 @@ setup (Test *test, gconstpointer unused)
        GckSlot *slot;
 
        /* Successful load */
-       test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
+       test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
        g_assert_no_error (err);
        g_assert (GCK_IS_MODULE (test->module));
        g_object_add_weak_pointer (G_OBJECT (test->module), (gpointer *)&test->module);
diff --git a/gck/test-gck-enumerator.c b/gck/test-gck-enumerator.c
index 13ea19f..73a1386 100644
--- a/gck/test-gck-enumerator.c
+++ b/gck/test-gck-enumerator.c
@@ -48,7 +48,7 @@ setup (Test *test, gconstpointer unused)
        GError *err = NULL;
 
        /* Successful load */
-       test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
+       test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
        g_assert_no_error (err);
        g_assert (GCK_IS_MODULE (test->module));
        g_object_add_weak_pointer (G_OBJECT (test->module), (gpointer *)&test->module);
diff --git a/gck/test-gck-module.c b/gck/test-gck-module.c
index 1b33355..320701b 100644
--- a/gck/test-gck-module.c
+++ b/gck/test-gck-module.c
@@ -41,7 +41,7 @@ setup (Test *test, gconstpointer unused)
        GError *err = NULL;
 
        /* Successful load */
-       test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
+       test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
        g_assert_no_error (err);
        g_assert (test->module);
        g_object_add_weak_pointer (G_OBJECT (test->module), (gpointer *)&test->module);
@@ -70,7 +70,7 @@ test_initialize_async (void)
        GError *error = NULL;
 
        /* Shouldn't be able to load modules */
-       gck_module_initialize_async (BUILDDIR "/.libs/libmock-test-module.so",
+       gck_module_initialize_async (_GCK_TEST_MODULE_PATH,
                                     NULL, fetch_async_result, &result);
 
        egg_test_wait_until (500);
@@ -138,7 +138,7 @@ test_module_props (Test *test, gconstpointer unused)
 
        g_object_get (test->module, "path", &path, NULL);
        g_assert (path != NULL && "no module-path");
-       g_assert (strcmp (BUILDDIR "/.libs/libmock-test-module.so", path) == 0 && "module path wrong");
+       g_assert (strcmp (_GCK_TEST_MODULE_PATH, path) == 0 && "module path wrong");
        g_free (path);
 }
 
diff --git a/gck/test-gck-modules.c b/gck/test-gck-modules.c
index 015c571..19cdaca 100644
--- a/gck/test-gck-modules.c
+++ b/gck/test-gck-modules.c
@@ -47,7 +47,7 @@ setup (Test *test, gconstpointer unused)
        GError *err = NULL;
 
        /* Successful load */
-       module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
+       module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
        g_assert_no_error (err);
        g_assert (GCK_IS_MODULE (module));
 
diff --git a/gck/test-gck-object.c b/gck/test-gck-object.c
index 3f782eb..61a5286 100644
--- a/gck/test-gck-object.c
+++ b/gck/test-gck-object.c
@@ -49,7 +49,7 @@ setup (Test *test, gconstpointer unused)
        GList *slots;
 
        /* Successful load */
-       test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
+       test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
        g_assert_no_error (err);
        g_assert (GCK_IS_MODULE (test->module));
 
diff --git a/gck/test-gck-session.c b/gck/test-gck-session.c
index 6cd4c97..003f30d 100644
--- a/gck/test-gck-session.c
+++ b/gck/test-gck-session.c
@@ -48,7 +48,7 @@ setup (Test *test, gconstpointer unused)
        GList *slots;
 
        /* Successful load */
-       test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
+       test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
        g_assert_no_error (err);
        g_assert (GCK_IS_MODULE (test->module));
        g_object_add_weak_pointer (G_OBJECT (test->module), (gpointer *)&test->module);
diff --git a/gck/test-gck-slot.c b/gck/test-gck-slot.c
index b8bcecf..7a1128b 100644
--- a/gck/test-gck-slot.c
+++ b/gck/test-gck-slot.c
@@ -42,7 +42,7 @@ setup (Test *test, gconstpointer unused)
        GList *slots;
 
        /* Successful load */
-       test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
+       test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
        g_assert_no_error (err);
        g_assert (GCK_IS_MODULE (test->module));
 
diff --git a/gcr/libgcr-base.map b/gcr/libgcr-base.map
new file mode 100644
index 0000000..4a16138
--- /dev/null
+++ b/gcr/libgcr-base.map
@@ -0,0 +1,8 @@
+{
+global:
+  gcr_*;
+  _gcr_*;
+  SECMEM_*;
+local:
+  *;
+};
diff --git a/gcr/meson.build b/gcr/meson.build
new file mode 100644
index 0000000..66126b9
--- /dev/null
+++ b/gcr/meson.build
@@ -0,0 +1,314 @@
+gcr_base_headers_install_dir = 'gcr-@0@'.format(gcr_major_version) / 'gcr'
+
+gcr_base_public_sources = files(
+  'gcr-certificate.c',
+  'gcr-certificate-chain.c',
+  'gcr-certificate-request.c',
+  'gcr-collection.c',
+  'gcr-comparable.c',
+  'gcr-filter-collection.c',
+  'gcr-fingerprint.c',
+  'gcr-icons.c',
+  'gcr-importer.c',
+  'gcr-import-interaction.c',
+  'gcr-library.c',
+  'gcr-mock-prompter.c',
+  'gcr-parser.c',
+  'gcr-pkcs11-certificate.c',
+  'gcr-prompt.c',
+  'gcr-secret-exchange.c',
+  'gcr-secure-memory.c',
+  'gcr-simple-certificate.c',
+  'gcr-simple-collection.c',
+  'gcr-ssh-askpass.c',
+  'gcr-system-prompt.c',
+  'gcr-system-prompter.c',
+  'gcr-trust.c',
+  'gcr-union-collection.c',
+)
+
+gcr_base_private_sources = files(
+  'gcr-callback-output-stream.c',
+  'gcr-certificate-extensions.c',
+  'gcr-column.c',
+  'gcr-gnupg-collection.c',
+  'gcr-gnupg-importer.c',
+  'gcr-gnupg-key.c',
+  'gcr-gnupg-process.c',
+  'gcr-gnupg-records.c',
+  'gcr-gnupg-util.c',
+  'gcr-key-mechanisms.c',
+  'gcr-memory-icon.c',
+  'gcr-openpgp.c',
+  'gcr-openssh.c',
+  'gcr-pkcs11-importer.c',
+  'gcr-record.c',
+  'gcr-single-collection.c',
+  'gcr-subject-public-key.c',
+  'gcr-util.c',
+)
+
+gcr_base_headers = files(
+  'gcr-base.h',
+  'gcr-certificate.h',
+  'gcr-certificate-chain.h',
+  'gcr-certificate-request.h',
+  'gcr-collection.h',
+  'gcr-column.h',
+  'gcr-comparable.h',
+  'gcr-deprecated-base.h',
+  'gcr-fingerprint.h',
+  'gcr-filter-collection.h',
+  'gcr-icons.h',
+  'gcr-importer.h',
+  'gcr-import-interaction.h',
+  'gcr-library.h',
+  'gcr-mock-prompter.h',
+  'gcr-parser.h',
+  'gcr-pkcs11-certificate.h',
+  'gcr-prompt.h',
+  'gcr-secret-exchange.h',
+  'gcr-secure-memory.h',
+  'gcr-simple-certificate.h',
+  'gcr-simple-collection.h',
+  'gcr-ssh-askpass.h',
+  'gcr-system-prompt.h',
+  'gcr-system-prompter.h',
+  'gcr-trust.h',
+  'gcr-types.h',
+  'gcr-union-collection.h',
+  'gcr-unlock-options.h',
+)
+
+# Generated sources
+gcr_version_conf = {
+  'GCR_MAJOR': gcr_major_version,
+  'GCR_MINOR': gcr_minor_version,
+  'GCR_MICRO': gcr_micro_version,
+}
+gcr_version_h = configure_file(input: 'gcr-version.h.in',
+  output: 'gcr-version.h',
+  configuration: gcr_version_conf,
+)
+
+gcr_base_headers += gcr_version_h
+
+gcr_enums_gen = gnome.mkenums_simple('gcr-enum-types-base',
+  sources: gcr_base_headers,
+  install_header: true,
+  install_dir: get_option('includedir') / gcr_base_headers_install_dir,
+)
+
+gcr_marshal_gen = gnome.genmarshal('gcr-marshal',
+  sources: 'gcr-marshal.list',
+  prefix: '_gcr_marshal',
+)
+
+gcr_dbus_gen = gnome.gdbus_codegen('gcr-dbus-generated',
+  sources: 'org.gnome.keyring.Prompter.xml',
+  interface_prefix: 'org.gnome.keyring.internal.',
+  namespace: '_GcrDbus',
+)
+
+gcr_oids = custom_target('gcr-oids',
+  output: [
+    'gcr-oids.c',
+    'gcr-oids.h',
+  ],
+  input: 'gcr-oids.list',
+  command: [ find_program('gcr-mkoids'),
+    '-p', 'GCR',
+    '-c', '@OUTPUT0@',
+    '-h', '@OUTPUT1@',
+    '@INPUT@',
+  ]
+)
+
+gcr_base_sources = [
+  gcr_base_private_sources,
+  gcr_base_public_sources,
+  gcr_enums_gen,
+  gcr_marshal_gen,
+  gcr_dbus_gen,
+  gcr_oids,
+]
+
+gcr_base_deps = [
+  glib_deps,
+  p11kit_dep,
+  libegg_dep,
+  gck_dep,
+]
+
+gcr_base_cflags = [
+  '-DG_LOG_DOMAIN="Gcr"',
+  '-DGCR_COMPILATION',
+  '-DGCR_API_SUBJECT_TO_CHANGE',
+  '-DGCK_API_SUBJECT_TO_CHANGE',
+  '-DP11_KIT_API_SUBJECT_TO_CHANGE',
+]
+
+gcr_base_symbolmap = meson.current_source_dir() / 'libgcr-base.map'
+gcr_base_linkflags = cc.get_supported_link_arguments(
+  '-Wl,--version-script,@0@'.format(gcr_base_symbolmap),
+)
+
+gcr_base_lib = shared_library('gcr-base-@0@'.format(gcr_major_version),
+  gcr_base_sources,
+  dependencies: gcr_base_deps,
+  c_args: gcr_base_cflags,
+  link_args: gcr_base_linkflags,
+  link_depends: gcr_base_symbolmap,
+  include_directories: config_h_dir,
+  version: gcr_soversion,
+  install: true,
+)
+
+install_headers(gcr_base_headers,
+  subdir: gcr_base_headers_install_dir,
+)
+
+if get_option('gtk')
+  install_headers('gcr.h',
+    subdir: gcr_base_headers_install_dir,
+  )
+endif
+
+gcr_base_dep = declare_dependency(
+  link_with: gcr_base_lib,
+  include_directories: include_directories('..'),
+  sources: gcr_enums_gen[1], # Make sure gcr-enum-types-base.h can be included
+)
+
+if get_option('introspection')
+  gcr_gir = gnome.generate_gir(gcr_base_lib,
+    sources: [ gcr_base_public_sources, gcr_base_headers ],
+    namespace: 'Gcr',
+    nsversion: '@0@'.format(gcr_major_version),
+    packages: gcr_base_deps,
+    export_packages: 'gcr-base-@0@'.format(gcr_major_version),
+    includes: [
+      'GObject-2.0',
+      'Gio-2.0',
+      gck_gir[0],
+    ],
+    header: 'gcr/gcr-base.h',
+    extra_args: [
+      '-DGCR_COMPILATION',
+      '-DGCR_API_SUBJECT_TO_CHANGE',
+    ],
+    install: true,
+  )
+
+  gcr_vapi = gnome.generate_vapi('gcr-@0@'.format(gcr_major_version),
+    sources: gcr_gir[0],
+    packages: [ 'glib-2.0', 'gio-2.0' ],
+    metadata_dirs: meson.current_source_dir(),
+    vapi_dirs: [
+      build_root / 'gck',
+    ],
+    gir_dirs: [
+      build_root / 'gck',
+    ],
+    install: true,
+  )
+endif
+
+# pkg-config file
+pkgconfig.generate(gcr_base_lib,
+  description: 'GObject and GUI library for high level crypto parsing and display',
+)
+
+# gcr-ssh-askpass binary
+gcr_ssh_askpass = executable('gcr-ssh-askpass',
+  'gcr-ssh-askpass.c',
+  dependencies: [ glib_deps, libegg_dep ],
+  c_args: [
+    '-DGCR_SSH_ASKPASS_TOOL',
+    '-DGCR_COMPILATION',
+  ],
+  include_directories: config_h_dir,
+  install: true,
+  install_dir: get_option('libexecdir'),
+)
+
+# Services
+gcr_service_files = [
+  'org.gnome.keyring.SystemPrompter.service',
+  'org.gnome.keyring.PrivatePrompter.service',
+]
+
+foreach service_file : gcr_service_files
+  configure_file(
+    output: service_file,
+    input: service_file + '.in',
+    configuration: {
+      'libexecdir': gcr_prefix / get_option('libexecdir'),
+    },
+    install_dir: get_option('datadir') / 'dbus-1' / 'services',
+  )
+endforeach
+
+# Tests
+gcr_test_names = [
+  'util',
+  'filter-collection',
+  'secret-exchange',
+  'simple-certificate',
+  'certificate',
+  'certificate-chain',
+  'subject-public-key',
+  'fingerprint',
+  'pkcs11-certificate',
+  'openpgp',
+  'openssh',
+  'secure-memory',
+  'trust',
+  'parser',
+  'record',
+  'memory-icon',
+  'gnupg-key',
+  'gnupg-collection',
+  'gnupg-process',
+  'system-prompt',
+  'ssh-askpass',
+]
+
+gcr_test_cflags = [
+  '-DSRCDIR="@0@"'.format(source_root),
+  '-D_GCR_TEST_SSH_ASKPASS_PATH="@0@"'.format(gcr_ssh_askpass.full_path()),
+]
+
+foreach _test : gcr_test_names
+  test_bin = executable('test-'+_test,
+    'test-@0@.c'.format(_test),
+    dependencies: [ gcr_base_deps, gcr_base_dep ],
+    link_with: [ gck_test_lib, egg_test_lib ],
+    c_args: [ gcr_base_cflags, gcr_test_cflags ],
+    include_directories: config_h_dir,
+  )
+
+  test(_test, test_bin,
+    suite: 'gcr-base',
+    depends: gcr_ssh_askpass,
+  )
+endforeach
+
+# Example frob programs
+frob_certificate_request = executable('frob-certificate-request',
+  files('frob-certificate-request.c', 'console-interaction.c'),
+  dependencies: [ gcr_base_dep, gcr_base_deps ],
+  c_args: gcr_base_cflags,
+)
+
+frob_openpgp = executable('frob-openpgp',
+  files('frob-openpgp.c'),
+  dependencies: [ gcr_base_dep, gcr_base_deps ],
+  c_args: gcr_base_cflags,
+)
+
+frob_parser = executable('frob-parser',
+  files('frob-parser.c'),
+  dependencies: [ gcr_base_dep, gcr_base_deps ],
+  c_args: gcr_base_cflags,
+)
diff --git a/gcr/test-ssh-askpass.c b/gcr/test-ssh-askpass.c
index a6a4965..786ae25 100644
--- a/gcr/test-ssh-askpass.c
+++ b/gcr/test-ssh-askpass.c
@@ -163,7 +163,11 @@ main (int argc, char **argv)
        g_test_init (&argc, &argv, NULL);
        g_set_prgname ("test-ssh-askpass");
 
+#ifdef _GCR_TEST_SSH_ASKPASS_PATH
+       gcr_ssh_askpass_executable = _GCR_TEST_SSH_ASKPASS_PATH;
+#else
        gcr_ssh_askpass_executable = BUILDDIR "/gcr-ssh-askpass";
+#endif
 
        g_test_add ("/gcr/ssh-askpass/ssh-keygen", Test, "booo", setup, test_ssh_keygen, teardown);
        g_test_add ("/gcr/ssh-askpass/cancelled", Test, NULL, setup, test_cancelled, teardown);
diff --git a/meson.build b/meson.build
new file mode 100644
index 0000000..610bb9f
--- /dev/null
+++ b/meson.build
@@ -0,0 +1,96 @@
+project('gcr', 'c',
+  version: '3.34.0',
+  meson_version: '>= 0.49',
+  license: 'GPL2+',
+)
+
+gnome = import('gnome')
+i18n = import('i18n')
+pkgconfig = import('pkgconfig')
+
+# Versioning
+gcr_version = meson.project_version()
+gcr_soversion = '1.0.0'
+gcr_version_array = gcr_version.split('.')
+gcr_major_version = gcr_version_array[0].to_int()
+gcr_minor_version = gcr_version_array[1].to_int()
+gcr_micro_version = gcr_version_array[2].to_int()
+
+gck_version = '1.0.0'
+gck_soversion = '0.0.0'
+gck_version_array = gck_version.split('.')
+gck_major_version = gck_version_array[0].to_int()
+gck_minor_version = gck_version_array[1].to_int()
+gck_micro_version = gck_version_array[2].to_int()
+
+# Some variables
+source_root = meson.current_source_dir()
+build_root = meson.current_build_dir()
+cc = meson.get_compiler('c')
+
+gcr_prefix = get_option('prefix')
+libexecbindir = gcr_prefix / get_option('libexecdir') / meson.project_name()
+podir = source_root / 'po'
+
+# Dependencies
+min_glib_version = '2.38'
+glib_deps = [
+  dependency('glib-2.0', version: '>=' + min_glib_version),
+  dependency('gmodule-no-export-2.0', version: '>=' + min_glib_version),
+  dependency('gthread-2.0', version: '>=' + min_glib_version),
+  dependency('gobject-2.0', version: '>=' + min_glib_version),
+  dependency('gio-2.0', version: '>=' + min_glib_version),
+  dependency('gio-unix-2.0',version: '>=' + min_glib_version),
+]
+gpg_bin = find_program('gpg2', 'gpg')
+libgcrypt_dep = dependency('libgcrypt', version: '>= 1')
+p11kit_dep = dependency('p11-kit-1', version: '>= 0.19.0')
+p11_system_config_modules = p11kit_dep.get_pkgconfig_variable('p11_system_config_modules')
+if p11_system_config_modules == ''
+  error('Couldn\'t find location for pkcs11 module config')
+endif
+
+if get_option('gtk')
+  gtk_min_version = '3.12'
+  gtk_dep = dependency('gtk+-3.0', version: '>=' + gtk_min_version)
+  gtk_x11_dep = dependency('gtk+-x11-3.0', version: '>=' + gtk_min_version)
+endif
+
+# configuration
+conf = configuration_data()
+conf.set_quoted('VERSION', meson.project_version())
+conf.set_quoted('LIBEXECDIR', libexecbindir)
+conf.set_quoted('LOCALEDIR', gcr_prefix / get_option('localedir'))
+conf.set_quoted('GETTEXT_PACKAGE', meson.project_name())
+conf.set('HAVE_GETTEXT', true)
+conf.set('HAVE_LOCALE_H', cc.has_header('locale.h'))
+conf.set('HAVE_TIMEGM', cc.has_function('timegm'))
+conf.set('HAVE_MLOCK', cc.has_function('mlock'))
+conf.set_quoted('GPG_EXECUTABLE', gpg_bin.path())
+conf.set_quoted('LIBGCRYPT_VERSION', libgcrypt_dep.version())
+config_file = configure_file(
+  output: 'config.h',
+  configuration: conf,
+)
+config_h_dir = include_directories('.')
+
+# subdirs
+subdir('po')
+subdir('egg')
+subdir('gck')
+subdir('gcr')
+subdir('schema')
+if get_option('gtk')
+  subdir('ui')
+endif
+if get_option('gtk_doc')
+  subdir('docs')
+endif
+
+# Post-install scripts
+meson.add_install_script('meson_post_install.py',
+  get_option('datadir'),
+  get_option('libdir'),
+  gcr_major_version.to_string(),
+  gcr_soversion,
+)
diff --git a/meson_options.txt b/meson_options.txt
new file mode 100644
index 0000000..bbdc8e3
--- /dev/null
+++ b/meson_options.txt
@@ -0,0 +1,15 @@
+option('introspection',
+  type: 'boolean',
+  value: true,
+  description: 'Build GObject Introspection (GIR) files',
+)
+option('gtk',
+  type: 'boolean',
+  value: true,
+  description: 'Build code that uses GTK+',
+)
+option('gtk_doc',
+  type: 'boolean',
+  value: true,
+  description: 'Build the reference documentation (requires gtk-doc)',
+)
diff --git a/meson_post_install.py b/meson_post_install.py
new file mode 100755
index 0000000..0166814
--- /dev/null
+++ b/meson_post_install.py
@@ -0,0 +1,51 @@
+#!/usr/bin/env python3
+
+import os
+import subprocess
+import sys
+
+# Env
+install_prefix = os.environ['MESON_INSTALL_DESTDIR_PREFIX']
+
+# Args
+datadir = sys.argv[1]
+libdir = sys.argv[2]
+gcr_major_version = sys.argv[3]
+gcr_soversion = sys.argv[4]
+
+icondir = os.path.join(install_prefix, datadir, 'icons', 'hicolor')
+schemadir = os.path.join(install_prefix, datadir, 'glib-2.0', 'schemas')
+mimedatabasedir = os.path.join(install_prefix, datadir, 'mime')
+
+# We don't want to mess around when packaging environments
+if os.environ.get('DESTDIR'):
+  sys.exit(0)
+
+print('Update icon cache...')
+subprocess.call(['gtk-update-icon-cache', '-f', '-t', icondir])
+
+print('Compiling gsettings schemas...')
+subprocess.call(['glib-compile-schemas', schemadir])
+
+print('Updating MIME database...')
+subprocess.call(['update-mime-database', mimedatabasedir])
+
+# FIXME: after a major version bump, just drop this
+print('Creating symlink for libgcr-{}.so'.format(gcr_major_version))
+
+def _get_path_for_lib(basename):
+    return os.path.join(install_prefix, libdir, basename)
+
+libgcr_ui_basename = 'libgcr-ui-{}.so'.format(gcr_major_version)
+libgcr_basename = 'libgcr-{}.so'.format(gcr_major_version)
+
+subprocess.call(['ln', '-f', '-s', libgcr_ui_basename, _get_path_for_lib(libgcr_basename)])
+
+for v in gcr_soversion.split('.'):
+    libgcr_ui_basename += '.{}'.format(v)
+    libgcr_basename += '.{}'.format(v)
+
+    if not os.path.exists(_get_path_for_lib(libgcr_ui_basename)):
+        continue
+
+    subprocess.call(['ln', '-f', '-s', libgcr_ui_basename, _get_path_for_lib(libgcr_basename)])
diff --git a/po/meson.build b/po/meson.build
new file mode 100644
index 0000000..f904cde
--- /dev/null
+++ b/po/meson.build
@@ -0,0 +1,3 @@
+i18n.gettext(meson.project_name(),
+  preset: 'glib'
+)
diff --git a/schema/meson.build b/schema/meson.build
new file mode 100644
index 0000000..81572a3
--- /dev/null
+++ b/schema/meson.build
@@ -0,0 +1,13 @@
+compiled_schemas = gnome.compile_schemas()
+install_data('org.gnome.crypto.pgp.gschema.xml',
+  install_dir: gcr_prefix / get_option('datadir') / 'glib-2.0' / 'schemas',
+)
+
+# GConf files (legacy)
+gconf_convert_files = [
+  'org.gnome.crypto.pgp.convert',
+  'org.gnome.crypto.pgp_keyservers.convert',
+]
+install_data(gconf_convert_files,
+  install_dir: get_option('datadir') / 'GConf' / 'gsettings',
+)
diff --git a/ui/icons/meson.build b/ui/icons/meson.build
new file mode 100644
index 0000000..fe7953b
--- /dev/null
+++ b/ui/icons/meson.build
@@ -0,0 +1,33 @@
+large_icons = [
+  'gcr-gnupg',
+  'gcr-password',
+  'gcr-smart-card',
+]
+
+small_icons = [
+  'gcr-gnupg',
+  'gcr-key',
+  'gcr-key-pair',
+  'gcr-password',
+  'gcr-smart-card',
+]
+
+foreach size : [ 16, 22, 24, 32, 48 ]
+  size_str = '@0@x@0@'.format(size)
+
+  foreach icon : small_icons
+    install_data(size_str / icon + '.png',
+      install_dir: get_option('datadir') / 'icons' / 'hicolor' / size_str / 'apps',
+    )
+  endforeach
+endforeach
+
+foreach size : [ 256 ]
+  size_str = '@0@x@0@'.format(size)
+
+  foreach icon : large_icons
+    install_data(size_str / icon + '.png',
+      install_dir: get_option('datadir') / 'icons' / 'hicolor' / size_str / 'apps',
+    )
+  endforeach
+endforeach
diff --git a/ui/libgcr-ui.map b/ui/libgcr-ui.map
new file mode 100644
index 0000000..4a16138
--- /dev/null
+++ b/ui/libgcr-ui.map
@@ -0,0 +1,8 @@
+{
+global:
+  gcr_*;
+  _gcr_*;
+  SECMEM_*;
+local:
+  *;
+};
diff --git a/ui/meson.build b/ui/meson.build
new file mode 100644
index 0000000..7bd3794
--- /dev/null
+++ b/ui/meson.build
@@ -0,0 +1,253 @@
+subdir('icons')
+
+gcr_ui_headers_install_dir = 'gcr-@0@'.format(gcr_major_version) / 'ui'
+
+gcr_ui_public_sources = files(
+  'gcr-certificate-renderer.c',
+  'gcr-certificate-widget.c',
+  'gcr-collection-model.c',
+  'gcr-combo-selector.c',
+  'gcr-failure-renderer.c',
+  'gcr-key-renderer.c',
+  'gcr-key-widget.c',
+  'gcr-import-button.c',
+  'gcr-list-selector.c',
+  'gcr-prompt-dialog.c',
+  'gcr-renderer.c',
+  'gcr-secure-entry-buffer.c',
+  'gcr-tree-selector.c',
+  'gcr-unlock-options-widget.c',
+  'gcr-viewer.c',
+  'gcr-viewer-widget.c',
+)
+
+gcr_ui_private_sources = files(
+  'eggimagemenuitem.c',
+  'gcr-certificate-basics-widget.c',
+  'gcr-certificate-details-widget.c',
+  'gcr-certificate-exporter.c',
+  'gcr-certificate-request-renderer.c',
+  'gcr-dialog-util.c',
+  'gcr-display-scrolled.c',
+  'gcr-display-view.c',
+  'gcr-gnupg-renderer.c',
+  'gcr-live-search.c',
+  'gcr-pkcs11-import-dialog.c',
+  'gcr-pkcs11-import-interaction.c',
+  'gcr-unlock-renderer.c',
+  'gcr-viewer-window.c',
+)
+
+gcr_ui_headers = files(
+  'gcr-ui.h',
+  'gcr-certificate-renderer.h',
+  'gcr-certificate-widget.h',
+  'gcr-collection-model.h',
+  'gcr-combo-selector.h',
+  'gcr-deprecated.h',
+  'gcr-failure-renderer.h',
+  'gcr-key-renderer.h',
+  'gcr-key-widget.h',
+  'gcr-import-button.h',
+  'gcr-list-selector.h',
+  'gcr-prompt-dialog.h',
+  'gcr-renderer.h',
+  'gcr-secure-entry-buffer.h',
+  'gcr-tree-selector.h',
+  'gcr-unlock-options-widget.h',
+  'gcr-viewer.h',
+  'gcr-viewer-widget.h',
+)
+
+# Generated sources
+gcr_ui_enums_gen = gnome.mkenums_simple('gcr-enum-types',
+  sources: gcr_ui_headers,
+  install_header: true,
+  install_dir: get_option('includedir') / gcr_ui_headers_install_dir,
+)
+
+gcr_ui_sources = [
+  gcr_ui_private_sources,
+  gcr_ui_public_sources,
+  gcr_ui_enums_gen,
+]
+
+gcr_ui_deps = [
+  glib_deps,
+  p11kit_dep,
+  libegg_dep,
+  gck_dep,
+  gcr_base_dep,
+  gtk_dep,
+  gtk_x11_dep,
+]
+
+gcr_ui_cflags = [
+ '-DG_LOG_DOMAIN="Gcr"',
+ '-DGCR_COMPILATION',
+ '-DGCR_API_SUBJECT_TO_CHANGE',
+ '-DGCK_API_SUBJECT_TO_CHANGE',
+ '-DP11_KIT_API_SUBJECT_TO_CHANGE',
+]
+
+gcr_ui_symbolmap = meson.current_source_dir() / 'libgcr-ui.map'
+gcr_ui_linkflags = cc.get_supported_link_arguments(
+  '-Wl,--version-script,@0@'.format(gcr_ui_symbolmap),
+)
+
+# gcr-XX is just the same as gcr-ui-XX
+gcr_ui_basename = 'gcr-ui-@0@'.format(gcr_major_version)
+gcr_basename = 'gcr-@0@'.format(gcr_major_version)
+
+gcr_ui_lib = shared_library(gcr_ui_basename,
+  gcr_ui_sources,
+  dependencies: gcr_ui_deps,
+  c_args: gcr_ui_cflags,
+  link_args: gcr_ui_linkflags,
+  link_depends: gcr_ui_symbolmap,
+  include_directories: config_h_dir,
+  version: gcr_soversion,
+  install: true,
+)
+
+pkgconfig.generate(gcr_ui_lib,
+  description: 'GObject and GUI library for high level crypto parsing and display',
+)
+pkgconfig.generate(gcr_ui_lib,
+  filebase: gcr_basename,
+  name: gcr_basename,
+  description: 'GObject and GUI library for high level crypto parsing and display',
+)
+
+install_headers(gcr_ui_headers,
+  subdir: gcr_ui_headers_install_dir,
+)
+
+gcr_ui_dep = declare_dependency(
+  link_with: gcr_ui_lib,
+  sources: gcr_ui_enums_gen[1], # Make sure gcr-enum-types.h can be included
+)
+
+if get_option('introspection')
+  gcr_ui_gir = gnome.generate_gir(gcr_ui_lib,
+    sources: [ gcr_ui_headers, gcr_ui_public_sources ],
+    namespace: 'GcrUi',
+    nsversion: '@0@'.format(gcr_major_version),
+    export_packages: 'gcr-ui-@0@'.format(gcr_major_version),
+    identifier_prefix: 'Gcr',
+    symbol_prefix: 'gcr',
+    packages: gcr_ui_deps,
+    includes: [
+      'GObject-2.0',
+      'Gio-2.0',
+      'Gtk-3.0',
+      gck_gir[0],
+      gcr_gir[0],
+    ],
+    header: 'ui/gcr-ui.h',
+    extra_args: [
+      '-DGCR_COMPILATION',
+      '-DGCR_API_SUBJECT_TO_CHANGE',
+    ],
+    install: true,
+  )
+
+  gcr_ui_vapi = gnome.generate_vapi('gcr-ui-@0@'.format(gcr_major_version),
+    sources: gcr_ui_gir[0],
+    packages: [
+      'glib-2.0',
+      'gio-2.0',
+      'gck-@0@'.format(gck_major_version),
+      'gcr-@0@'.format(gcr_major_version),
+      'gtk+-3.0'
+    ],
+    metadata_dirs: meson.current_source_dir(),
+    vapi_dirs: [
+      build_root / 'gck',
+      build_root / 'gcr',
+    ],
+    gir_dirs: [
+      build_root / 'gck',
+      build_root / 'gcr',
+    ],
+    install: true,
+  )
+endif
+
+# gcr-viewer
+gcr_viewer = executable('gcr-viewer',
+  'gcr-viewer-tool.c',
+  dependencies: [ gcr_ui_dep, gcr_ui_deps ],
+  c_args: gcr_ui_cflags,
+  include_directories: config_h_dir,
+  install: true,
+)
+
+i18n.merge_file(
+  input: configure_file(
+    input: 'gcr-viewer.desktop.in.in',
+    output: '@BASENAME@',
+    configuration: { 'bindir': gcr_prefix / get_option('bindir') },
+  ),
+  output: '@BASENAME@',
+  type: 'desktop',
+  po_dir: podir,
+  install: true,
+  install_dir: get_option('datadir') / 'applications',
+)
+
+# gcr-prompter
+gcr_prompter = executable('gcr-prompter',
+  'gcr-prompter-tool.c',
+  dependencies: [ gcr_ui_dep, gcr_ui_deps ],
+  c_args: gcr_ui_cflags,
+  include_directories: config_h_dir,
+  install: true,
+  install_dir: get_option('libexecdir'),
+)
+
+i18n.merge_file(
+  input: configure_file(
+    input: 'gcr-prompter.desktop.in.in',
+    output: '@BASENAME@',
+    configuration: { 'libexecdir': gcr_prefix / get_option('libexecdir') },
+  ),
+  output: '@BASENAME@',
+  type: 'desktop',
+  po_dir: podir,
+  install: true,
+  install_dir: get_option('datadir') / 'applications',
+)
+
+# Register new mime types
+install_data('gcr-crypto-types.xml',
+  install_dir: get_option('datadir') / 'mime' / 'packages',
+)
+
+# Manual UI testing programs
+gcr_ui_manual_tests = [
+  'frob-certificate',
+  'frob-combo-selector',
+  'frob-gnupg-selector',
+  'frob-import-button',
+  'frob-key',
+  'frob-tree-selector',
+  'frob-prompt',
+  'frob-request',
+  'frob-system-prompt',
+  'frob-unlock',
+  'frob-unlock-options',
+]
+
+gcr_ui_test_cflags = [
+  '-DSRCDIR="@0@"'.format(source_root),
+]
+
+foreach _test : gcr_ui_manual_tests
+  test_bin = executable('test-'+_test,
+    '@0@.c'.format(_test),
+    dependencies: [ gcr_ui_deps, gcr_ui_dep ],
+    c_args: [ gcr_ui_cflags, gcr_ui_test_cflags ],
+    include_directories: config_h_dir,
+  )
+endforeach



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]