From a2bd1ffe9aadbd9fbbe8d400616483f4acaf5dbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Corentin=20No=C3=ABl?= Date: Mon, 4 May 2026 17:45:06 +0200 Subject: [PATCH 1/2] Add Meson build system Add the Meson build system alongside autotools allowing to keep the current build system working until the port is validated by distributors. The Meson build system has a syntax easier to understand than autotools, build faster and allow to use ninja instead of make. It also makes things safer for cross-compilation and dependencies handling. --- INSTALL => INSTALL.autotools | 0 README | 42 ++++++------- doc/meson.build | 4 ++ gdbus/meson.build | 9 +++ include/meson.build | 31 ++++++++++ meson.build | 112 +++++++++++++++++++++++++++++++++++ meson.options | 19 ++++++ se/meson.build | 54 +++++++++++++++++ src/meson.build | 85 ++++++++++++++++++++++++++ src/near/meson.build | 25 ++++++++ test/meson.build | 11 ++++ tools/meson.build | 37 ++++++++++++ tools/nfctool/meson.build | 14 +++++ unit/meson.build | 47 +++++++++++++++ 14 files changed, 469 insertions(+), 21 deletions(-) rename INSTALL => INSTALL.autotools (100%) create mode 100644 doc/meson.build create mode 100644 gdbus/meson.build create mode 100644 include/meson.build create mode 100644 meson.build create mode 100644 meson.options create mode 100644 se/meson.build create mode 100644 src/meson.build create mode 100644 src/near/meson.build create mode 100644 test/meson.build create mode 100644 tools/meson.build create mode 100644 tools/nfctool/meson.build create mode 100644 unit/meson.build diff --git a/INSTALL b/INSTALL.autotools similarity index 100% rename from INSTALL rename to INSTALL.autotools diff --git a/README b/README index aca7476..3b8ded7 100644 --- a/README +++ b/README @@ -11,49 +11,49 @@ In order to compile neard you need following software packages: - GCC compiler - D-Bus library - GLib library - - Netlink (libnl) library, version 1 or 2. + - Netlink (libnl) library, version 3, 2, or 1. + +neard uses the Meson build system and requires at least version 1.1. To configure run: - ./configure --prefix=/usr + meson setup builddir --prefix=/usr -Configure automatically searches for all required components and packages. +Meson automatically searches for all required components and packages. To compile and install run: - make && make install + meson compile -C builddir + meson install -C builddir Configuration and options ========================= By default all neard plugins and features are built in. They can be -disabled with the following configuration options: - - --disable-nfctype1 +adjusted with the following configuration options, passed as +-Doption=value to meson setup (or changed later with meson configure): - Disable support for type 1 NFC tags. + -Dnfctypes=nfctype1,nfctype2,nfctype3,nfctype4,nfctype5 - --disable-nfctype2 + Select which NFC Forum tag types (1 to 5) to support. - Disable support for type 2 NFC tags. + -Dp2p=true|false - --disable-nfctype3 + Enable or disable support for peer to peer mode. - Disable support for type 3 NFC tags. + -Dese=true|false - --disable-nfctype4 + Enable or disable embedded Secure Element support. - Disable support for type 4 NFC tags. + -Dsystemd=auto|enabled|disabled - --disable-nfctype5 + Install the systemd service file. - Disable support for type 5 ISO 15693 tags. + -Dtools=true|false - --disable-p2p + Build testing tools (nfctool, nciattach). - Disable support for peer to peer mode. + -Dtest=true|false -Running ./bootstrap-configure will build the configure script and then -run it, with maintainer mode enabled. bootstrap-configure will configure -neard with all features enabled. + Install test/example scripts. Bugs and contributing ===================== diff --git a/doc/meson.build b/doc/meson.build new file mode 100644 index 0000000..585f1ba --- /dev/null +++ b/doc/meson.build @@ -0,0 +1,4 @@ +install_man('neard.8', 'neard.conf.5') +if opt_tools + install_man('nfctool.1') +endif \ No newline at end of file diff --git a/gdbus/meson.build b/gdbus/meson.build new file mode 100644 index 0000000..a632057 --- /dev/null +++ b/gdbus/meson.build @@ -0,0 +1,9 @@ +gdbus_inc = include_directories('.') + +gdbus_sources = files( + 'mainloop.c', + 'watch.c', + 'object.c', + 'client.c', + 'polkit.c', +) diff --git a/include/meson.build b/include/meson.build new file mode 100644 index 0000000..bf41280 --- /dev/null +++ b/include/meson.build @@ -0,0 +1,31 @@ +include_files = files( + 'adapter.h', + 'dbus.h', + 'device.h', + 'log.h', + 'ndef.h', + 'nfc_copy.h', + 'plugin.h', + 'setting.h', + 'snep.h', + 'tag.h', + 'tlv.h', + 'types.h', +) + +version_h_in = files('version.h.in') + +install_headers( + 'adapter.h', + 'device.h', + 'log.h', + 'ndef.h', + 'nfc_copy.h', + 'plugin.h', + 'setting.h', + 'snep.h', + 'tag.h', + 'tlv.h', + 'types.h', + subdir : 'near', +) diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..1055974 --- /dev/null +++ b/meson.build @@ -0,0 +1,112 @@ +project('neard', 'c', + version : '0.20', + license : 'GPL-2.0-only', + meson_version : '>= 1.1', + default_options : ['warning_level=1'], +) + +cc = meson.get_compiler('c') +pkgconfig = import('pkgconfig') + +prefix = get_option('prefix') +libexecdir = prefix / get_option('libexecdir') +pkglibexecdir = libexecdir / 'nfc' +libdir = prefix / get_option('libdir') +pkglibdir = libdir / meson.project_name() +plugindir = pkglibdir / 'plugins' +sysconfdir = get_option('sysconfdir') +configdir = sysconfdir / 'neard' +includedir = prefix / get_option('includedir') + +opt_nfctypes = get_option('nfctypes') +opt_p2p = get_option('p2p') +opt_ese = get_option('ese') +opt_systemd = get_option('systemd') +opt_tools = get_option('tools') +opt_test_scripts = get_option('test') + +glib_dep = dependency('glib-2.0', version : '>= 2.28') +dbus_dep = dependency('dbus-1', version : '>= 1.2') +dl_dep = cc.find_library('dl') +systemd_dep = dependency('systemd', required : opt_systemd) + +# Netlink: prefer libnl-3.0, fall back to libnl-2.0, then libnl-1 +libnl3_dep = dependency('libnl-3.0', required : false) +libnl_genl3_dep = dependency('libnl-genl-3.0', required : false) +if libnl3_dep.found() and libnl_genl3_dep.found() + netlink_dep = [libnl3_dep, libnl_genl3_dep] + netlink_deps_str = 'libnl-3.0 libnl-genl-3.0' + need_libnl_compat = false +else + libnl2_dep = dependency('libnl-2.0', required : false) + if libnl2_dep.found() + netlink_dep = [libnl2_dep] + netlink_deps_str = 'libnl-2.0' + need_libnl_compat = false + else + libnl1_dep = dependency('libnl-1', required : true) + netlink_dep = [libnl1_dep] + netlink_deps_str = 'libnl-1' + need_libnl_compat = true + endif +endif + +conf = configuration_data() +conf.set_quoted('VERSION', meson.project_version()) +conf.set_quoted('PACKAGE', meson.project_name()) +conf.set_quoted('PACKAGE_VERSION', meson.project_version()) +if need_libnl_compat + conf.set('NEED_LIBNL_COMPAT', 1) +endif +config_h = configure_file(output : 'config.h', configuration : conf) +config_dep = declare_dependency( + include_directories: include_directories(), + sources: config_h, + compile_args: ['-DHAVE_CONFIG_H'], +) + +top_inc = include_directories('.') + +subdir('include') +subdir('gdbus') + +builtin_modules = opt_nfctypes +builtin_sources = [] + +sources_per_type = { + 'nfctype1': files('plugins/nfctype1.c'), + 'nfctype2': files('plugins/nfctype2.c', 'plugins/mifare.c'), + 'nfctype3': files('plugins/nfctype3.c'), + 'nfctype4': files('plugins/nfctype4.c'), + 'nfctype5': files('plugins/nfctype5.c'), +} + +foreach nfctype : opt_nfctypes + builtin_sources += sources_per_type[nfctype] +endforeach + +if opt_p2p + builtin_modules += ['p2p'] + builtin_sources += files( + 'plugins/p2p.c', + 'plugins/npp.c', + 'plugins/snep.c', + 'plugins/snep-validation.c', + 'plugins/llcp-validation.c', + 'plugins/handover.c', + 'plugins/phdc.c', + ) +endif + +subdir('src') +subdir('doc') +subdir('unit') +if opt_tools + subdir('tools') +endif +if opt_test_scripts + subdir('test') +endif +if opt_ese + subdir('se') +endif diff --git a/meson.options b/meson.options new file mode 100644 index 0000000..78e6eaa --- /dev/null +++ b/meson.options @@ -0,0 +1,19 @@ +option('nfctypes', type : 'array', + choices : ['nfctype1', 'nfctype2', 'nfctype3', 'nfctype4', 'nfctype5'], + value : ['nfctype1', 'nfctype2', 'nfctype3', 'nfctype4', 'nfctype5'], + description: 'Enable NFC Forum Type 1, 2, 3, 4 or 5 tag support') + +option('p2p', type: 'boolean', value: true, + description: 'Enable NFC peer-to-peer support') + +option('ese', type: 'boolean', value: false, + description: 'Enable embedded Secure Element support') + +option('systemd', type: 'feature', value: 'auto', + description: 'Install systemd service file') + +option('tools', type: 'boolean', value: false, + description: 'Build testing tools (nfctool, nciattach)') + +option('test', type: 'boolean', value: false, + description: 'Install test/example scripts') diff --git a/se/meson.build b/se/meson.build new file mode 100644 index 0000000..91cb095 --- /dev/null +++ b/se/meson.build @@ -0,0 +1,54 @@ +# seeld - Secure Element daemon + +seeld_builtin_h = configure_file( + output : 'builtin.h', + command : [genbuiltin, 'nfc'], + capture : true, +) + +se_inc = include_directories('.') + +seeld_c_args = [ + '-DNEAR_PLUGIN_BUILTIN', + '-DPLUGINDIR="' + (prefix / get_option('libdir') / meson.project_name() / 'plugins-se') + '"', + '-DCONFIGDIR="' + configdir + '"', +] + +executable('seeld', + 'ace.c', + 'apdu.c', + 'channel.c', + 'driver.c', + 'main.c', + 'manager.c', + 'plugins/nfc.c', + 'se.c', + '../src/dbus.c', + '../src/error.c', + '../src/log.c', + '../src/plugin.c', + gdbus_sources, + seeld_builtin_h, + c_args : seeld_c_args, + include_directories : [se_inc, top_inc, src_inc, gdbus_inc], + dependencies : [glib_dep, dbus_dep, netlink_dep, dl_dep, config_dep], + link_args : ['-Wl,--export-dynamic'], + install : true, + install_dir : pkglibexecdir, +) + +install_data( + 'org.neard.se.conf', + install_dir : get_option('sysconfdir') / 'dbus-1' / 'system.d', +) + +pkgconfig.generate( + name : 'seeld', + description : 'Secure Element daemon', + version : meson.project_version(), + requires : [glib_dep, dbus_dep], + libraries : ['-module', '-avoid-version', '-export-symbols-regex', 'seeld_plugin_desc'], + variables : { + 'plugindir' : '${libdir}/seeld/plugins', + }, +) diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..f28b00c --- /dev/null +++ b/src/meson.build @@ -0,0 +1,85 @@ +subdir('near') + +src_inc = include_directories('.') + +genbuiltin = find_program('genbuiltin') +builtin_h = configure_file( + output : 'builtin.h', + command : [genbuiltin] + builtin_modules, + capture : true, +) + +neard_c_args = [ + '-DNEAR_PLUGIN_BUILTIN', + '-DPLUGINDIR="@0@"'.format(plugindir), + '-DCONFIGDIR="@0@"'.format(configdir), +] + +neard_deps = [ + glib_dep, + dbus_dep, + netlink_dep, + dl_dep, + config_dep, +] + +neard = executable('neard', + 'adapter.c', + 'agent.c', + 'bluetooth.c', + 'dbus.c', + 'device.c', + 'error.c', + 'log.c', + 'main.c', + 'manager.c', + 'ndef.c', + 'netlink.c', + 'plugin.c', + 'snep.c', + 'tag.c', + 'tlv.c', + builtin_h, + builtin_sources, + config_h, + gdbus_sources, + c_args : neard_c_args, + include_directories : [top_inc, gdbus_inc], + dependencies : neard_deps, + install : true, + install_dir : pkglibexecdir, +) + +pkgconfig.generate( + name : 'neard', + description : 'NFC daemon', + version : meson.project_version(), + requires : [glib_dep, dbus_dep, netlink_dep], + libraries : ['-module', '-avoid-version', '-export-symbols-regex', 'neard_plugin_desc'], + variables : { + 'pkglibdir' : '${libdir}/' + meson.project_name(), + 'plugindir' : '${libdir}/' + meson.project_name() + '/plugins', + }, +) + +if systemd_dep.found() + systemd_unitdir = systemd_dep.get_variable('systemdsystemunitdir') + service_conf = configuration_data() + service_conf.set('pkglibexecdir', pkglibexecdir) + service_file = configure_file( + input : 'neard.service.in', + output : 'neard.service', + configuration : service_conf, + ) + install_data(service_file, install_dir : systemd_unitdir) +endif + +install_data( + 'org.neard.conf', + install_dir : sysconfdir / 'dbus-1' / 'system.d', +) + +install_data( + 'main.conf', + install_dir : configdir, +) diff --git a/src/near/meson.build b/src/near/meson.build new file mode 100644 index 0000000..91fd81a --- /dev/null +++ b/src/near/meson.build @@ -0,0 +1,25 @@ +# Generate near/ headers in the build directory so that +# "#include " resolves at compile time. +# include_directories('src') in the root meson.build adds both +# /src and /src to the compiler search path, +# so files generated here (/src/near/*.h) are found as +# . + +foreach file : include_files + configure_file( + input : file, + output : '@PLAINNAME@', + copy : true, + ) +endforeach + +version_conf = configuration_data() +version_conf.set('VERSION', meson.project_version()) + +version_h = configure_file( + input : version_h_in, + output : '@BASENAME@', + configuration : version_conf, + install : true, + install_dir : get_option('includedir') / 'near', +) diff --git a/test/meson.build b/test/meson.build new file mode 100644 index 0000000..9b94141 --- /dev/null +++ b/test/meson.build @@ -0,0 +1,11 @@ +install_data( + 'bt-handover', + 'handover-agent', + 'monitor-near', + 'neardutils.py', + 'phdc-simple-manager', + 'test-adapter', + 'test-device', + 'test-tag', + install_dir : pkglibdir / 'test', +) diff --git a/tools/meson.build b/tools/meson.build new file mode 100644 index 0000000..7182c38 --- /dev/null +++ b/tools/meson.build @@ -0,0 +1,37 @@ +tool_c_args = [ + '-DNEAR_PLUGIN_BUILTIN', + '-DPLUGINDIR="@0@"'.format(plugindir), + '-DCONFIGDIR="@0@"'.format(configdir), +] + +# nciattach: only needs C stdlib at link time; glib/dbus headers are pulled +# in transitively through src/near.h but no glib/dbus symbols are used. +nciattach_deps = [] +foreach dep : [glib_dep, dbus_dep] + netlink_dep + nciattach_deps += dep.partial_dependency(compile_args : true, link_args : false) +endforeach + +executable('nciattach', + 'nciattach.c', + c_args : tool_c_args, + include_directories : [top_inc, src_inc], + dependencies : [nciattach_deps, config_dep], + install : true, +) + +# snep-send: internal test tool, not installed +executable('snep-send', + 'snep-send.c', + '../src/agent.c', + '../src/bluetooth.c', + '../src/dbus.c', + '../src/error.c', + '../src/log.c', + '../src/ndef.c', + gdbus_sources, + c_args : ['-DCONFIGDIR="@0@"'.format(configdir)], + include_directories : [top_inc, gdbus_inc, src_inc], + dependencies : [glib_dep, dbus_dep, config_dep], +) + +subdir('nfctool') diff --git a/tools/nfctool/meson.build b/tools/nfctool/meson.build new file mode 100644 index 0000000..7ead772 --- /dev/null +++ b/tools/nfctool/meson.build @@ -0,0 +1,14 @@ +executable('nfctool', + 'adapter.c', + 'display.c', + 'llcp-decode.c', + 'main.c', + 'ndef-decode.c', + 'netlink.c', + 'snep-decode.c', + 'sniffer.c', + c_args : tool_c_args, + include_directories : [top_inc, src_inc], + dependencies : [glib_dep, netlink_dep, config_dep], + install : true, +) diff --git a/unit/meson.build b/unit/meson.build new file mode 100644 index 0000000..d15c8c0 --- /dev/null +++ b/unit/meson.build @@ -0,0 +1,47 @@ +test_base_sources = [ + gdbus_sources, + files( + '../src/log.c', + '../src/dbus.c', + '../src/error.c', + '../src/agent.c', + '../src/bluetooth.c', + '../src/ndef.c', + ), +] + +test_c_args = ['-DCONFIGDIR="@0@"'.format(configdir)] +test_deps = [glib_dep, dbus_dep, config_dep] + +test_ndef_parse = executable('test-ndef-parse', + 'test-ndef-parse.c', + test_base_sources, + c_args : test_c_args, + include_directories : [top_inc, src_inc, gdbus_inc], + dependencies : test_deps, + build_by_default : false, +) + +test_ndef_build = executable('test-ndef-build', + 'test-ndef-build.c', + test_base_sources, + c_args : test_c_args, + include_directories : [top_inc, src_inc, gdbus_inc], + dependencies : test_deps, + build_by_default : false, +) + +test_snep_read = executable('test-snep-read', + 'test-snep-read.c', + 'test-utils.c', + '../src/snep.c', + test_base_sources, + c_args : test_c_args, + include_directories : [top_inc, src_inc, gdbus_inc], + dependencies : test_deps, + build_by_default : false, +) + +test('test-ndef-parse', test_ndef_parse) +test('test-ndef-build', test_ndef_build) +test('test-snep-read', test_snep_read) From 5c3e98f54aff9ded4df8b4d7a7457de6fa61e336 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Corentin=20No=C3=ABl?= Date: Wed, 6 May 2026 16:17:12 +0200 Subject: [PATCH 2/2] Add meson build system to the CI Keep the autotools CI working as we need both to be proven to work. --- .github/workflows/ci-meson.yml | 426 +++++++++++++++++++++++++++++++ ci/alpine.meson.sh | 39 +++ ci/archlinux.meson.sh | 27 ++ ci/debian.meson.cross-compile.sh | 31 +++ ci/debian.meson.i386.sh | 27 ++ ci/debian.meson.sanitizers.sh | 20 ++ ci/debian.meson.sh | 49 ++++ ci/fedora.meson.sh | 31 +++ ci/ubuntu.meson.cross-compile.sh | 1 + ci/ubuntu.meson.i386.sh | 1 + ci/ubuntu.meson.sanitizers.sh | 1 + ci/ubuntu.meson.sh | 1 + 12 files changed, 654 insertions(+) create mode 100644 .github/workflows/ci-meson.yml create mode 100755 ci/alpine.meson.sh create mode 100755 ci/archlinux.meson.sh create mode 100755 ci/debian.meson.cross-compile.sh create mode 100755 ci/debian.meson.i386.sh create mode 100755 ci/debian.meson.sanitizers.sh create mode 100755 ci/debian.meson.sh create mode 100755 ci/fedora.meson.sh create mode 120000 ci/ubuntu.meson.cross-compile.sh create mode 120000 ci/ubuntu.meson.i386.sh create mode 120000 ci/ubuntu.meson.sanitizers.sh create mode 120000 ci/ubuntu.meson.sh diff --git a/.github/workflows/ci-meson.yml b/.github/workflows/ci-meson.yml new file mode 100644 index 0000000..48d0441 --- /dev/null +++ b/.github/workflows/ci-meson.yml @@ -0,0 +1,426 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2021 Canonical Ltd. +# Copyright (c) 2023-2024 Linaro Ltd. +# Author: Krzysztof Kozlowski +# +# Copyright (c) 2025 Krzysztof Kozlowski +# Loosely based on https://github.com/linux-test-project/ltp +# +name: "Builds (meson)" +on: + pull_request: + push: + schedule: + # Run at 1:01 AM, every Tuesday + - cron: '1 1 * * 2' + workflow_dispatch: + +jobs: + job: + name: Build + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + + strategy: + fail-fast: false + matrix: + arch: [x86-64] + compiler: [gcc, clang] + container: + - alpine:latest + - archlinux:latest + - debian:testing + - debian:stable + - debian:forky + - debian:trixie + - debian:bookworm + # Fails on configure on GCC and clang (process restrictions?) + # - fedora:rawhide + - fedora:latest + - fedora:44 + - fedora:43 + - ubuntu:latest + - ubuntu:resolute + - ubuntu:noble + - ubuntu:jammy + cross_compile: [""] + mode: [maintainer, no-maintainer] + variant: [""] + include: + # Debian 32-bit builds + - container: "debian:testing" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: maintainer + variant: i386 + + - container: "debian:testing" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: no-maintainer + variant: i386 + + - container: "debian:stable" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: maintainer + variant: i386 + + - container: "debian:stable" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: no-maintainer + variant: i386 + + - container: "debian:trixie" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: maintainer + variant: i386 + + - container: "debian:trixie" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: no-maintainer + variant: i386 + + - container: "debian:forky" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: maintainer + variant: i386 + + - container: "debian:forky" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: no-maintainer + variant: i386 + + - container: "debian:bookworm" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: maintainer + variant: i386 + + - container: "debian:bookworm" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: no-maintainer + variant: i386 + + # Debian cross compilation builds + - container: "debian:stable" + arch: armhf + compiler: arm-linux-gnueabihf-gcc + cross_compile: arm-linux-gnueabihf + mode: maintainer + variant: cross-compile + + - container: "debian:stable" + arch: arm64 + compiler: aarch64-linux-gnu-gcc + cross_compile: aarch64-linux-gnu + mode: maintainer + variant: cross-compile + + - container: "debian:stable" + arch: ppc64el + compiler: powerpc64le-linux-gnu-gcc + cross_compile: powerpc64le-linux-gnu + mode: maintainer + variant: cross-compile + + - container: "debian:stable" + arch: s390x + compiler: s390x-linux-gnu-gcc + cross_compile: s390x-linux-gnu + mode: maintainer + variant: cross-compile + + - container: "debian:bookworm" + arch: armhf + compiler: arm-linux-gnueabihf-gcc + cross_compile: arm-linux-gnueabihf + mode: maintainer + variant: cross-compile + + - container: "debian:bookworm" + arch: arm64 + compiler: aarch64-linux-gnu-gcc + cross_compile: aarch64-linux-gnu + mode: maintainer + variant: cross-compile + + - container: "debian:bookworm" + arch: ppc64el + compiler: powerpc64le-linux-gnu-gcc + cross_compile: powerpc64le-linux-gnu + mode: maintainer + variant: cross-compile + + - container: "debian:bookworm" + arch: s390x + compiler: s390x-linux-gnu-gcc + cross_compile: s390x-linux-gnu + mode: maintainer + variant: cross-compile + + # Debian GCC sanitizer builds + - container: "debian:testing" + arch: x86-64 + compiler: gcc + mode: maintainer + variant: sanitizers + + - container: "debian:stable" + arch: x86-64 + compiler: gcc + mode: maintainer + variant: sanitizers + + - container: "debian:trixie" + arch: x86-64 + compiler: gcc + mode: maintainer + variant: sanitizers + + - container: "debian:forky" + arch: x86-64 + compiler: gcc + mode: maintainer + variant: sanitizers + + # Ubuntu 32-bit builds + - container: "ubuntu:latest" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: maintainer + variant: i386 + + - container: "ubuntu:latest" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: no-maintainer + variant: i386 + + - container: "ubuntu:resolute" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: maintainer + variant: i386 + + - container: "ubuntu:resolute" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: no-maintainer + variant: i386 + + - container: "ubuntu:noble" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: maintainer + variant: i386 + + - container: "ubuntu:noble" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: no-maintainer + variant: i386 + + - container: "ubuntu:jammy" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: maintainer + variant: i386 + + - container: "ubuntu:jammy" + arch: i386 + compiler: gcc -m32 + cross_compile: i686-linux-gnu + mode: no-maintainer + variant: i386 + + # Ubuntu GCC sanitizer builds + - container: "ubuntu:latest" + arch: x86-64 + compiler: gcc + mode: maintainer + variant: sanitizers + + - container: "ubuntu:resolute" + arch: x86-64 + compiler: gcc + mode: maintainer + variant: sanitizers + + - container: "ubuntu:noble" + arch: x86-64 + compiler: gcc + mode: maintainer + variant: sanitizers + + - container: "ubuntu:jammy" + arch: x86-64 + compiler: gcc + mode: maintainer + variant: sanitizers + + container: + image: ${{ matrix.container }} + env: + ARCH: ${{ matrix.arch }} + CC: ${{ matrix.compiler }} + CROSS_COMPILE: ${{ matrix.cross_compile }} + MODE: ${{ matrix.mode }} + VARIANT: ${{ matrix.variant }} + + steps: + - name: Show OS + run: cat /etc/os-release + + - name: Show env (matrix settings) + run: | + echo "ARCH: $ARCH" + echo "CC: $CC" + echo "CROSS_COMPILE: $CROSS_COMPILE" + echo "MODE: $MODE" + echo "VARIANT: $VARIANT" + + - name: Git checkout + uses: actions/checkout@v6 + + - name: Install additional packages + run: | + INSTALL=${{ matrix.container }} + INSTALL="${INSTALL%%:*}" + INSTALL="${INSTALL%%/*}" + echo "Running ./ci/$INSTALL.meson.sh" + ./ci/$INSTALL.meson.sh + if [ "$VARIANT" ]; then + echo "Running ./ci/$INSTALL.meson.$VARIANT.sh" + ./ci/$INSTALL.meson.$VARIANT.sh; + fi + + - name: Compiler version + run: $CC --version + + - name: Display environment and Linux version + run: | + test -f /etc/issue && cat /etc/issue + echo "############################################" + lsb_release -a || true + echo "############################################" + cat /usr/include/linux/version.h + echo "############################################" + uname -a + echo "############################################" + cat /proc/cmdline + echo "############################################" + printenv + + - name: Display nfc.h differences between local and Linux kernel headers + run: diff -uBb /usr/include/linux/nfc.h include/nfc_copy.h || true + + - name: Configure + id: configure + run: | + SETUP_ARGS="" + if [ "$VARIANT" = "sanitizers" ]; then + SETUP_ARGS="-Db_sanitize=address,undefined -Db_pie=true" + fi + if [ "$MODE" = "maintainer" ]; then + SETUP_ARGS="$SETUP_ARGS --werror" + fi + CROSS_FILE_ARGS="" + if [ "$CROSS_COMPILE" ]; then + case "$ARCH" in + i386) CPU_FAMILY=x86; CPU=i686; ENDIAN=little; MULTIARCH=i386-linux-gnu ;; + armhf) CPU_FAMILY=arm; CPU=armv7; ENDIAN=little; MULTIARCH=arm-linux-gnueabihf ;; + arm64) CPU_FAMILY=aarch64; CPU=aarch64; ENDIAN=little; MULTIARCH=aarch64-linux-gnu ;; + ppc64el) CPU_FAMILY=ppc64; CPU=powerpc64le; ENDIAN=little; MULTIARCH=powerpc64le-linux-gnu ;; + s390x) CPU_FAMILY=s390x; CPU=s390x; ENDIAN=big; MULTIARCH=s390x-linux-gnu ;; + esac + CC=$CC \ + PKG_CONFIG=pkg-config \ + PKG_CONFIG_LIBDIR="/usr/lib/${MULTIARCH}/pkgconfig:/usr/share/pkgconfig" \ + meson env2mfile --cross \ + --system linux \ + --subsystem linux \ + --kernel linux \ + --cpu-family $CPU_FAMILY \ + --cpu $CPU \ + --endian $ENDIAN \ + -o /tmp/cross.ini + CROSS_FILE_ARGS="--cross-file /tmp/cross.ini" + fi + CC=$CC meson setup build \ + --prefix=/usr \ + --sysconfdir=/etc \ + -Dese=true \ + -Dtools=true \ + -Dsystemd=disabled \ + $SETUP_ARGS \ + $CROSS_FILE_ARGS + + - name: Get configure logs + run: cat build/meson-logs/meson-log.txt + if: ${{ always() && ((steps.configure.outcome == 'failure') || + (steps.configure.outcome == 'success')) }} + + - name: Compile + run: meson compile -C build + + - name: Run unit tests + id: unit_tests + run: meson test -C build + if: ${{ (matrix.arch == 'x86-64') || (matrix.arch == 'i386') }} + + - name: Get unit tests logs + run: cat build/meson-logs/testlog.txt + if: ${{ always() && ((steps.unit_tests.outcome == 'failure') || + (steps.unit_tests.outcome == 'success')) }} + + - name: Check final binary + run: | + file build/src/neard + ARCH_CHECK="$ARCH" + case "$ARCH" in + armhf) ARCH_CHECK="ARM, EABI";; + arm64) ARCH_CHECK="aarch64";; + # Glibc 2.41 seems to use "Intel i386" + i386) ARCH_CHECK="Intel 80386|Intel i386";; + ppc64el) ARCH_CHECK="64-bit PowerPC";; + s390x) ARCH_CHECK="IBM S/390";; + *) ARCH_CHECK="x86-64";; + esac + echo "Checking for built matching architecture: $ARCH_CHECK" + file build/src/neard | grep -E "$ARCH_CHECK" + if [ "$VARIANT" = "sanitizers" ]; then + echo "Checking for linking against sanitizer libraries" + ldd build/src/neard | grep libasan.so + # liblsan won't appear if asan is used + ldd build/src/neard | grep libubsan.so + fi + + - name: Install + run: meson install -C build diff --git a/ci/alpine.meson.sh b/ci/alpine.meson.sh new file mode 100755 index 0000000..46c6377 --- /dev/null +++ b/ci/alpine.meson.sh @@ -0,0 +1,39 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2019-2021 Petr Vorel +# Copyright (c) 2021 Canonical Ltd. +# Author: Krzysztof Kozlowski +# +# Copyright (c) 2026 Krzysztof Kozlowski +# + +set -ex + +apk update + +PKGS_CC="gcc" +case $CC in + clang*) + # On Alpine v3.14 clang fails without gcc: + # cannot find crtbeginS.o: No such file or directory + PKGS_CC="clang gcc" + ;; +esac + +# Packages needed by CI +PKGS_MORE="file" + +apk add \ + binutils \ + dbus-dev \ + glib-dev \ + libnl3-dev \ + meson \ + musl-dev \ + ninja \ + pkgconfig \ + $PKGS_CC \ + $PKGS_MORE + +echo "Install finished: $0" diff --git a/ci/archlinux.meson.sh b/ci/archlinux.meson.sh new file mode 100755 index 0000000..94da489 --- /dev/null +++ b/ci/archlinux.meson.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2021 Canonical Ltd. +# Author: Krzysztof Kozlowski +# +# + +set -ex + +PKGS_CC="gcc" +case $CC in + clang*) + PKGS_CC="clang" + ;; +esac + +pacman -Syu --noconfirm \ + dbus \ + glib2 \ + libnl \ + meson \ + ninja \ + pkg-config \ + $PKGS_CC + +echo "Install finished: $0" diff --git a/ci/debian.meson.cross-compile.sh b/ci/debian.meson.cross-compile.sh new file mode 100755 index 0000000..c88f54f --- /dev/null +++ b/ci/debian.meson.cross-compile.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2018-2020 Petr Vorel +# Copyright (c) 2021 Canonical Ltd. +# Author: Krzysztof Kozlowski +# +# Copyright (c) 2025 Krzysztof Kozlowski +# + +set -ex + +if [ -z "$ARCH" ]; then + echo "missing \$ARCH!" >&2 + exit 1 +fi + +dpkg --add-architecture $ARCH +apt update + +apt install -y --no-install-recommends \ + libc6-dev-${ARCH}-cross + +apt install -y --no-install-recommends \ + libdbus-1-dev:${ARCH} \ + libglib2.0-dev:${ARCH} \ + libnl-3-dev:${ARCH} \ + libnl-genl-3-dev:${ARCH} \ + gcc-`dpkg-architecture -a ${ARCH} -q DEB_TARGET_GNU_TYPE` + +echo "Install finished: $0" diff --git a/ci/debian.meson.i386.sh b/ci/debian.meson.i386.sh new file mode 100755 index 0000000..773da42 --- /dev/null +++ b/ci/debian.meson.i386.sh @@ -0,0 +1,27 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2021 Canonical Ltd. +# Author: Krzysztof Kozlowski +# +# + +set -ex + +dpkg --add-architecture i386 +apt update + +# gcc-multilib are also needed for clang 32-bit builds +PKGS_CC="gcc-multilib" + +apt install -y --no-install-recommends \ + linux-libc-dev:i386 + +apt install -y --no-install-recommends \ + libdbus-1-dev:i386 \ + libglib2.0-dev:i386 \ + libnl-3-dev:i386 \ + libnl-genl-3-dev:i386 \ + $PKGS_CC + +echo "Install finished: $0" diff --git a/ci/debian.meson.sanitizers.sh b/ci/debian.meson.sanitizers.sh new file mode 100755 index 0000000..f165531 --- /dev/null +++ b/ci/debian.meson.sanitizers.sh @@ -0,0 +1,20 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2021 Canonical Ltd. +# Author: Krzysztof Kozlowski +# +# Copyright (c) 2025 Krzysztof Kozlowski +# + +set -ex + +apt install -y --no-install-recommends \ + liblsan0 \ + libubsan1 + +apt install -y --no-install-recommends libasan8 || \ + apt install -y --no-install-recommends libasan6 || \ + apt install -y --no-install-recommends libasan5 + +echo "Install finished: $0" diff --git a/ci/debian.meson.sh b/ci/debian.meson.sh new file mode 100755 index 0000000..9595e01 --- /dev/null +++ b/ci/debian.meson.sh @@ -0,0 +1,49 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2021 Canonical Ltd. +# Author: Krzysztof Kozlowski +# +# + +set -ex + +apt update + +# Some distros (e.g. Ubuntu Hirsute) might pull tzdata which asks questions +export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true + +# Choose some random place in Europe +echo "tzdata tzdata/Areas select Europe +tzdata tzdata/Zones/Europe select Berlin +" > /tmp/tzdata-preseed.txt +debconf-set-selections /tmp/tzdata-preseed.txt + +PKGS_CC="build-essential" +case $CC in + clang*) + PKGS_CC="clang" + ;; +esac + +apt install -y --no-install-recommends \ + file \ + libdbus-1-dev \ + libglib2.0-dev \ + libnl-3-dev \ + libnl-genl-3-dev \ + meson \ + ninja-build \ + pkg-config \ + python3-pip \ + $PKGS_CC + +# Meson >= 1.1 is required. If the packaged version is older, install via pip. +MIN_MESON="1.1.0" +MESON_VER=$(meson --version 2>/dev/null || echo "0.0.0") +if dpkg --compare-versions "$MESON_VER" lt "$MIN_MESON"; then + pip3 install "meson>=$MIN_MESON" 2>/dev/null || \ + pip3 install --break-system-packages "meson>=$MIN_MESON" +fi + +echo "Install finished: $0" diff --git a/ci/fedora.meson.sh b/ci/fedora.meson.sh new file mode 100755 index 0000000..d04f657 --- /dev/null +++ b/ci/fedora.meson.sh @@ -0,0 +1,31 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2021 Canonical Ltd. +# Author: Krzysztof Kozlowski +# +# + +set -ex + +PKGS_CC="gcc" +case $CC in + clang*) + PKGS_CC="clang" + ;; +esac + +# Packages needed by CI +PKGS_MORE="file" + +dnf -y install \ + dbus-devel \ + glib2-devel \ + libnl3-devel \ + meson \ + ninja-build \ + pkg-config \ + $PKGS_CC \ + $PKGS_MORE + +echo "Install finished: $0" diff --git a/ci/ubuntu.meson.cross-compile.sh b/ci/ubuntu.meson.cross-compile.sh new file mode 120000 index 0000000..30e87c2 --- /dev/null +++ b/ci/ubuntu.meson.cross-compile.sh @@ -0,0 +1 @@ +debian.meson.cross-compile.sh \ No newline at end of file diff --git a/ci/ubuntu.meson.i386.sh b/ci/ubuntu.meson.i386.sh new file mode 120000 index 0000000..c6f5422 --- /dev/null +++ b/ci/ubuntu.meson.i386.sh @@ -0,0 +1 @@ +debian.meson.i386.sh \ No newline at end of file diff --git a/ci/ubuntu.meson.sanitizers.sh b/ci/ubuntu.meson.sanitizers.sh new file mode 120000 index 0000000..95e8d8e --- /dev/null +++ b/ci/ubuntu.meson.sanitizers.sh @@ -0,0 +1 @@ +debian.meson.sanitizers.sh \ No newline at end of file diff --git a/ci/ubuntu.meson.sh b/ci/ubuntu.meson.sh new file mode 120000 index 0000000..bf14e8a --- /dev/null +++ b/ci/ubuntu.meson.sh @@ -0,0 +1 @@ +debian.meson.sh \ No newline at end of file