Commit 9e20dff3 authored by Niels De Graef's avatar Niels De Graef

WIP: Support Meson build system

parent 8bb1dc8d
Pipeline #84721 failed with stages
in 10 minutes and 23 seconds
......@@ -5,6 +5,28 @@ stages:
variables:
DEPENDENCIES: dbus-x11 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
- 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
......
#!/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)
#!/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
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',
]
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,
include_directories: config_h_dir,
)
test(_test, egg_test_bin,
suite: 'egg',
)
endforeach
gck_sources_public = [
'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 = [
'gck-call.c',
'gck-interaction.c',
]
gck_exported_headers = [
'gck.h',
]
# Generated sources
gck_version_conf = configuration_data()
gck_version_conf.set_quoted('GCR_MAJOR', gck_major_version)
gck_version_conf.set_quoted('GCR_MINOR', gck_minor_version)
gck_version_conf.set_quoted('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_exported_headers,
)
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_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(libdir / 'pkcs11'),
]
gck_lib = library('gck-@0@'.format(gck_major_version),
gck_sources,
dependencies: gck_deps,
c_args: gck_cflags,
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
)
# GObject intospection file
gck_gir_sources = [
gck_sources_public,
gck_exported_headers,
gck_enums_gen[1],
]
if get_option('introspection')
gck_gir = gnome.generate_gir(gck_lib,
sources: gck_gir_sources,
namespace: 'Gck',
nsversion: gck_major_version,
packages: gck_deps,
export_packages: 'gck-@0@'.format(gck_major_version),
includes: [ 'GObject-2.0', 'Gio-2.0' ],
extra_args: [
'-DGCK_COMPILATION',
'-DGCK_API_SUBJECT_TO_CHANGE',
'--c-include=gck/gck.h'.format(meson.current_source_dir()),
],
install: true,
)
gck_vapi = gnome.generate_vapi('gck-@0@'.format(gck_major_version),
sources: gck_gir[0],
packages: [ 'glib-2.0', 'gio-2.0' ],
install: true,
)
endif
# tests
gck_test_lib = library('gck-testable',
sources: [ 'gck-mock.c', 'gck-test.c' ],
dependencies: [ gck_deps, gck_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_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
# pkg-config file
gck_pc_config = configuration_data()
gck_pc_config.set('prefix', gcr_prefix)
gck_pc_config.set('exec_prefix', '${prefix}')
gck_pc_config.set('libdir', join_paths('${exec_prefix}/lib'))
gck_pc_config.set('includedir', join_paths('${prefix}/include'))
gck_pc_config.set('datarootdir', join_paths('${prefix}/share'))
gck_pc_config.set('datadir', join_paths('${datarootdir}'))
gck_pc_config.set('sysconfdir', join_paths('${prefix}/etc'))
gck_pc_config.set('GCK_MAJOR', gck_major_version)
gck_pc_config.set('VERSION', gcr_version)
configure_file(input: 'gck.pc.in',
output: 'gck.pc',
configuration: gck_pc_config,
)
......@@ -56,7 +56,11 @@ setup (Test *test, gconstpointer unused)
GckSlot *slot;
/* Successful load */
#ifdef _GCK_TEST_MODULE_PATH
test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
#else
test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
#endif
g_assert_no_error (err);
g_assert (GCK_IS_MODULE (test->module));
g_object_add_weak_pointer (G_OBJECT (test->module), (gpointer *)&test->module);
......
......@@ -48,7 +48,11 @@ setup (Test *test, gconstpointer unused)
GError *err = NULL;
/* Successful load */
#ifdef _GCK_TEST_MODULE_PATH
test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
#else
test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
#endif
g_assert_no_error (err);
g_assert (GCK_IS_MODULE (test->module));
g_object_add_weak_pointer (G_OBJECT (test->module), (gpointer *)&test->module);
......
......@@ -41,7 +41,11 @@ setup (Test *test, gconstpointer unused)
GError *err = NULL;
/* Successful load */
#ifdef _GCK_TEST_MODULE_PATH
test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
#else
test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
#endif
g_assert_no_error (err);
g_assert (test->module);
g_object_add_weak_pointer (G_OBJECT (test->module), (gpointer *)&test->module);
......@@ -70,8 +74,13 @@ test_initialize_async (void)
GError *error = NULL;
/* Shouldn't be able to load modules */
#ifdef _GCK_TEST_MODULE_PATH
gck_module_initialize_async (_GCK_TEST_MODULE_PATH,
NULL, fetch_async_result, &result);
#else
gck_module_initialize_async (BUILDDIR "/.libs/libmock-test-module.so",
NULL, fetch_async_result, &result);
#endif
egg_test_wait_until (500);
g_assert (result != NULL);
......@@ -138,7 +147,11 @@ test_module_props (Test *test, gconstpointer unused)
g_object_get (test->module, "path", &path, NULL);
g_assert (path != NULL && "no module-path");
#ifdef _GCK_TEST_MODULE_PATH
g_assert (strcmp (_GCK_TEST_MODULE_PATH, path) == 0 && "module path wrong");
#else
g_assert (strcmp (BUILDDIR "/.libs/libmock-test-module.so", path) == 0 && "module path wrong");
#endif
g_free (path);
}
......
......@@ -47,7 +47,11 @@ setup (Test *test, gconstpointer unused)
GError *err = NULL;
/* Successful load */
#ifdef _GCK_TEST_MODULE_PATH
module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
#else
module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
#endif
g_assert_no_error (err);
g_assert (GCK_IS_MODULE (module));
......
......@@ -49,7 +49,11 @@ setup (Test *test, gconstpointer unused)
GList *slots;
/* Successful load */
#ifdef _GCK_TEST_MODULE_PATH
test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
#else
test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
#endif
g_assert_no_error (err);
g_assert (GCK_IS_MODULE (test->module));
......
......@@ -48,7 +48,11 @@ setup (Test *test, gconstpointer unused)
GList *slots;
/* Successful load */
#ifdef _GCK_TEST_MODULE_PATH
test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
#else
test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
#endif
g_assert_no_error (err);
g_assert (GCK_IS_MODULE (test->module));
g_object_add_weak_pointer (G_OBJECT (test->module), (gpointer *)&test->module);
......
......@@ -42,7 +42,11 @@ setup (Test *test, gconstpointer unused)
GList *slots;
/* Successful load */
#ifdef _GCK_TEST_MODULE_PATH
test->module = gck_module_initialize (_GCK_TEST_MODULE_PATH, NULL, &err);
#else
test->module = gck_module_initialize (BUILDDIR "/.libs/libmock-test-module.so", NULL, &err);
#endif
g_assert_no_error (err);
g_assert (GCK_IS_MODULE (test->module));
......
gcr_public_sources = [
'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_private_sources = [
'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_headers = [
'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 = configuration_data()
gcr_version_conf.set('GCR_MAJOR', gcr_major_version)
gcr_version_conf.set('GCR_MINOR', gcr_minor_version)
gcr_version_conf.set('GCR_MICRO', gcr_micro_version)
gcr_version_h = configure_file(input: 'gcr-version.h.in',
output: 'gcr-version.h',
configuration: gcr_version_conf,
)
gcr_enums_gen = gnome.mkenums_simple('gcr-enum-types-base',
sources: gcr_headers + [ gcr_version_h ],
)
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_sources = [
gcr_private_sources,
gcr_public_sources,
gcr_enums_gen,
gcr_marshal_gen,
gcr_dbus_gen,
gcr_oids,
]
gcr_deps = [
glib_deps,
p11kit_dep,
libegg_dep,
gck_dep,
]
gcr_cflags = [
'-DG_LOG_DOMAIN="Gcr"',
'-DGCR_COMPILATION',
'-DGCR_API_SUBJECT_TO_CHANGE',
'-DGCK_API_SUBJECT_TO_CHANGE',
'-DP11_KIT_API_SUBJECT_TO_CHANGE',
]
gcr_lib = library('gcr-@0@'.format(gcr_major_version),
gcr_sources,
dependencies: gcr_deps,
c_args: gcr_cflags,
include_directories: config_h_dir,
version: gcr_soversion,
)
gcr_dep = declare_dependency(
link_with: gcr_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_lib,
sources: gcr_public_sources,
namespace: 'Gcr',
nsversion: gcr_major_version,
packages: gcr_deps,
export_packages: 'gcr-@0@'.format(gcr_major_version),
includes: [ 'GObject-2.0', 'Gio-2.0' ],
extra_args: [
'-DGCR_COMPILATION',
'-DGCR_API_SUBJECT_TO_CHANGE',
'--c-include=gcr/gcr.h'.format(meson.current_source_dir()),
],
install: true,
)
gcr_vapi = gnome.generate_vapi('gcr-@0@'.format(gcr_major_version),
sources: gcr_gir[0],
packages: [ 'glib-2.0', 'gio-2.0' ],
install: true,
)
endif
# 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,
)
# 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 = [
'-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_deps, gcr_dep ],
link_with: [ gck_test_lib, egg_test_lib ],
c_args: [ gcr_cflags, gcr_test_cflags ],
include_directories: config_h_dir,
)
test(_test, test_bin,
suite: 'gcr',
depends: gcr_ssh_askpass,
)
endforeach
......@@ -163,7 +163,11 @@ main (int argc, char **argv)