Add a Meson build system
This allows bwrap to be built as a subproject in larger Meson projects. When built as a subproject, we install into the --libexecdir and require a program prefix to be specified: for example, Flatpak would use program_prefix=flatpak- to get /usr/libexec/flatpak-bwrap. Verified to be backwards-compatible as far as Meson 0.49.0 (Debian 9 backports). Loosely based on previous work by Jussi Pakkanen (see #133). Differences between the Autotools and Meson builds: The Meson build requires a version of libcap that has pkg-config metadata (introduced in libcap 2.23, in 2013). The Meson build has no equivalent of --with-priv-mode=setuid. On distributions like Debian <= 10 and RHEL <= 7 that require a setuid bwrap executable, the sysadmin or distribution packaging will need to set the correct permissions on the bwrap executable; Debian already did this via packaging rather than the upstream build system. The Meson build supports being used as a subproject, and there is CI for this. It automatically disables shell completions and man pages, moves the bubblewrap executable to ${libexecdir}, and renames the bubblewrap executable according to a program_prefix option that the caller must specify (for example, Flatpak would use -Dprogram_prefix=flatpak- to get /usr/libexec/flatpak-bwrap). See the tests/use-as-subproject/ directory for an example. Signed-off-by: Simon McVittie <smcv@collabora.com>
This commit is contained in:
parent
43c2d32d7f
commit
1927981240
|
@ -10,7 +10,7 @@ on:
|
|||
|
||||
jobs:
|
||||
check:
|
||||
name: Build with gcc and test
|
||||
name: Build with Autotools and gcc, and test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out
|
||||
|
@ -69,6 +69,71 @@ jobs:
|
|||
run: |
|
||||
make -C _build -j $(getconf _NPROCESSORS_ONLN) distcheck VERBOSE=1 BWRAP_MUST_WORK=1
|
||||
|
||||
meson:
|
||||
name: Build with Meson and gcc, and test
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out
|
||||
uses: actions/checkout@v1
|
||||
- name: Install build-dependencies
|
||||
run: sudo ./ci/builddeps.sh
|
||||
- name: Create logs dir
|
||||
run: mkdir test-logs
|
||||
- name: setup
|
||||
run: |
|
||||
meson _build
|
||||
env:
|
||||
CFLAGS: >-
|
||||
-O2
|
||||
-Wp,-D_FORTIFY_SOURCE=2
|
||||
-fsanitize=address
|
||||
-fsanitize=undefined
|
||||
- name: compile
|
||||
run: ninja -C _build -v
|
||||
- name: smoke-test
|
||||
run: |
|
||||
set -x
|
||||
./_build/bwrap --bind / / --tmpfs /tmp true
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=0
|
||||
- name: test
|
||||
run: |
|
||||
BWRAP_MUST_WORK=1 meson test -C _build
|
||||
env:
|
||||
ASAN_OPTIONS: detect_leaks=0
|
||||
- name: Collect overall test logs on failure
|
||||
if: failure()
|
||||
run: mv _build/meson-logs/testlog.txt test-logs/ || true
|
||||
- name: install
|
||||
run: |
|
||||
DESTDIR="$(pwd)/DESTDIR" meson install -C _build
|
||||
( cd DESTDIR && find -ls )
|
||||
- name: dist
|
||||
run: |
|
||||
BWRAP_MUST_WORK=1 meson dist -C _build
|
||||
- name: Collect dist test logs on failure
|
||||
if: failure()
|
||||
run: mv _build/meson-private/dist-build/meson-logs/testlog.txt test-logs/disttestlog.txt || true
|
||||
- name: use as subproject
|
||||
run: |
|
||||
mkdir tests/use-as-subproject/subprojects
|
||||
tar -C tests/use-as-subproject/subprojects -xf _build/meson-dist/bubblewrap-*.tar.xz
|
||||
mv tests/use-as-subproject/subprojects/bubblewrap-* tests/use-as-subproject/subprojects/bubblewrap
|
||||
( cd tests/use-as-subproject && meson _build )
|
||||
ninja -C tests/use-as-subproject/_build -v
|
||||
meson test -C tests/use-as-subproject/_build
|
||||
DESTDIR="$(pwd)/DESTDIR-as-subproject" meson install -C tests/use-as-subproject/_build
|
||||
( cd DESTDIR-as-subproject && find -ls )
|
||||
test -x DESTDIR-as-subproject/usr/local/libexec/not-flatpak-bwrap
|
||||
test ! -e DESTDIR-as-subproject/usr/local/bin/bwrap
|
||||
test ! -e DESTDIR-as-subproject/usr/local/libexec/bwrap
|
||||
- name: Upload test logs
|
||||
uses: actions/upload-artifact@v1
|
||||
if: failure() || cancelled()
|
||||
with:
|
||||
name: test logs
|
||||
path: test-logs
|
||||
|
||||
clang:
|
||||
name: Build with clang and analyze
|
||||
runs-on: ubuntu-latest
|
||||
|
|
10
Makefile.am
10
Makefile.am
|
@ -5,11 +5,21 @@ EXTRA_DIST = \
|
|||
.editorconfig \
|
||||
README.md \
|
||||
autogen.sh \
|
||||
completions/bash/meson.build \
|
||||
completions/meson.build \
|
||||
completions/zsh/meson.build \
|
||||
demos/bubblewrap-shell.sh \
|
||||
demos/flatpak-run.sh \
|
||||
demos/flatpak.bpf \
|
||||
demos/userns-block-fd.py \
|
||||
meson.build \
|
||||
meson_options.txt \
|
||||
packaging/bubblewrap.spec \
|
||||
tests/meson.build \
|
||||
tests/use-as-subproject/README \
|
||||
tests/use-as-subproject/config.h \
|
||||
tests/use-as-subproject/dummy-config.h.in \
|
||||
tests/use-as-subproject/meson.build \
|
||||
uncrustify.cfg \
|
||||
uncrustify.sh \
|
||||
$(NULL)
|
||||
|
|
|
@ -64,6 +64,7 @@ if dpkg-vendor --derives-from Debian; then
|
|||
libcap-dev \
|
||||
libselinux1-dev \
|
||||
libtool \
|
||||
meson \
|
||||
pkg-config \
|
||||
python3 \
|
||||
xsltproc \
|
||||
|
@ -92,6 +93,7 @@ if command -v yum; then
|
|||
libubsan \
|
||||
libxslt \
|
||||
make \
|
||||
meson \
|
||||
redhat-rpm-config \
|
||||
rsync \
|
||||
${NULL+}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
bash_completion_dir = get_option('bash_completion_dir')
|
||||
|
||||
if bash_completion_dir == ''
|
||||
bash_completion = dependency(
|
||||
'bash-completion',
|
||||
version : '>=2.0',
|
||||
required : false,
|
||||
)
|
||||
|
||||
if bash_completion.found()
|
||||
if meson.version().version_compare('>=0.51.0')
|
||||
bash_completion_dir = bash_completion.get_variable(
|
||||
default_value: '',
|
||||
pkgconfig: 'completionsdir',
|
||||
pkgconfig_define: [
|
||||
'prefix', get_option('prefix'),
|
||||
'datadir', get_option('prefix') / get_option('datadir'),
|
||||
],
|
||||
)
|
||||
else
|
||||
bash_completion_dir = bash_completion.get_pkgconfig_variable(
|
||||
'completionsdir',
|
||||
default: '',
|
||||
define_variable: [
|
||||
'prefix', get_option('prefix'),
|
||||
'datadir', get_option('prefix') / get_option('datadir'),
|
||||
],
|
||||
)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
if bash_completion_dir == ''
|
||||
bash_completion_dir = get_option('datadir') / 'bash-completion' / 'completions'
|
||||
endif
|
||||
|
||||
install_data('bwrap', install_dir : bash_completion_dir)
|
|
@ -0,0 +1,7 @@
|
|||
if get_option('bash_completion').enabled()
|
||||
subdir('bash')
|
||||
endif
|
||||
|
||||
if get_option('zsh_completion').enabled()
|
||||
subdir('zsh')
|
||||
endif
|
|
@ -0,0 +1,7 @@
|
|||
zsh_completion_dir = get_option('zsh_completion_dir')
|
||||
|
||||
if zsh_completion_dir == ''
|
||||
zsh_completion_dir = get_option('datadir') / 'zsh' / 'site-functions'
|
||||
endif
|
||||
|
||||
install_data('_bwrap', install_dir : zsh_completion_dir)
|
|
@ -0,0 +1,147 @@
|
|||
project(
|
||||
'bubblewrap',
|
||||
'c',
|
||||
version : '0.5.0',
|
||||
meson_version : '>=0.49.0',
|
||||
default_options : [
|
||||
'warning_level=2',
|
||||
],
|
||||
)
|
||||
|
||||
cc = meson.get_compiler('c')
|
||||
add_project_arguments('-D_GNU_SOURCE', language : 'c')
|
||||
|
||||
# Keep this in sync with ostree, except remove -Wall (part of Meson
|
||||
# warning_level 2) and -Werror=declaration-after-statement
|
||||
add_project_arguments(
|
||||
cc.get_supported_arguments([
|
||||
'-Werror=shadow',
|
||||
'-Werror=empty-body',
|
||||
'-Werror=strict-prototypes',
|
||||
'-Werror=missing-prototypes',
|
||||
'-Werror=implicit-function-declaration',
|
||||
'-Werror=pointer-arith',
|
||||
'-Werror=init-self',
|
||||
'-Werror=missing-declarations',
|
||||
'-Werror=return-type',
|
||||
'-Werror=overflow',
|
||||
'-Werror=int-conversion',
|
||||
'-Werror=parenthesis',
|
||||
'-Werror=incompatible-pointer-types',
|
||||
'-Werror=misleading-indentation',
|
||||
'-Werror=missing-include-dirs',
|
||||
'-Werror=aggregate-return',
|
||||
|
||||
# Extra warnings specific to bubblewrap
|
||||
'-Werror=switch-default',
|
||||
'-Wswitch-enum',
|
||||
|
||||
# Meson warning_level=2 would do this, but we are not fully
|
||||
# signedness-safe yet
|
||||
'-Wno-sign-compare',
|
||||
'-Wno-error=sign-compare',
|
||||
|
||||
# Deliberately not warning about these, ability to zero-initialize
|
||||
# a struct is a feature
|
||||
'-Wno-missing-field-initializers',
|
||||
'-Wno-error=missing-field-initializers',
|
||||
]),
|
||||
language : 'c',
|
||||
)
|
||||
|
||||
if (
|
||||
cc.has_argument('-Werror=format=2')
|
||||
and cc.has_argument('-Werror=format-security')
|
||||
and cc.has_argument('-Werror=format-nonliteral')
|
||||
)
|
||||
add_project_arguments([
|
||||
'-Werror=format=2',
|
||||
'-Werror=format-security',
|
||||
'-Werror=format-nonliteral',
|
||||
], language : 'c')
|
||||
endif
|
||||
|
||||
sh = find_program('sh', required : true)
|
||||
bash = find_program('bash', required : false)
|
||||
|
||||
libcap_dep = dependency('libcap', required : true)
|
||||
|
||||
selinux_dep = dependency(
|
||||
'libselinux',
|
||||
version : '>=2.1.9',
|
||||
# if disabled, Meson will behave as though libselinux was not found
|
||||
required : get_option('selinux'),
|
||||
)
|
||||
|
||||
cdata = configuration_data()
|
||||
cdata.set_quoted(
|
||||
'PACKAGE_STRING',
|
||||
'@0@ @1@'.format(meson.project_name(), meson.project_version()),
|
||||
)
|
||||
|
||||
if selinux_dep.found()
|
||||
cdata.set('HAVE_SELINUX', 1)
|
||||
if selinux_dep.version().version_compare('>=2.3')
|
||||
cdata.set('HAVE_SELINUX_2_3', 1)
|
||||
endif
|
||||
endif
|
||||
|
||||
if get_option('require_userns')
|
||||
cdata.set('ENABLE_REQUIRE_USERNS', 1)
|
||||
endif
|
||||
|
||||
configure_file(
|
||||
output : 'config.h',
|
||||
configuration : cdata,
|
||||
)
|
||||
|
||||
if meson.is_subproject()
|
||||
bwrapdir = get_option('libexecdir')
|
||||
|
||||
if get_option('program_prefix') == ''
|
||||
error('program_prefix option must be set when bwrap is a subproject')
|
||||
endif
|
||||
else
|
||||
bwrapdir = get_option('bindir')
|
||||
endif
|
||||
|
||||
bwrap = executable(
|
||||
get_option('program_prefix') + 'bwrap',
|
||||
[
|
||||
'bubblewrap.c',
|
||||
'bind-mount.c',
|
||||
'network.c',
|
||||
'utils.c',
|
||||
],
|
||||
install : true,
|
||||
install_dir : bwrapdir,
|
||||
dependencies : [selinux_dep, libcap_dep],
|
||||
)
|
||||
|
||||
xsltproc = find_program('xsltproc', required : get_option('man'))
|
||||
|
||||
if xsltproc.found() and not meson.is_subproject()
|
||||
custom_target(
|
||||
'bwrap.1',
|
||||
output : 'bwrap.1',
|
||||
input : 'bwrap.xml',
|
||||
command : [
|
||||
xsltproc,
|
||||
'--nonet',
|
||||
'--stringparam', 'man.output.quietly', '1',
|
||||
'--stringparam', 'funcsynopsis.style', 'ansi',
|
||||
'--stringparam', 'man.th.extra1.suppress', '1',
|
||||
'--stringparam', 'man.authors.section.enabled', '0',
|
||||
'--stringparam', 'man.copyright.section.enabled', '0',
|
||||
'-o', '@OUTPUT@',
|
||||
'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl',
|
||||
'@INPUT@',
|
||||
],
|
||||
install : true,
|
||||
install_dir : get_option('mandir') / 'man1',
|
||||
)
|
||||
endif
|
||||
|
||||
if not meson.is_subproject()
|
||||
subdir('completions')
|
||||
endif
|
|
@ -0,0 +1,47 @@
|
|||
option(
|
||||
'bash_completion',
|
||||
type : 'feature',
|
||||
description : 'install bash completion script',
|
||||
value : 'enabled',
|
||||
)
|
||||
option(
|
||||
'bash_completion_dir',
|
||||
type : 'string',
|
||||
description : 'install bash completion script in this directory',
|
||||
value : '',
|
||||
)
|
||||
option(
|
||||
'man',
|
||||
type : 'feature',
|
||||
description : 'generate man pages',
|
||||
value : 'auto',
|
||||
)
|
||||
option(
|
||||
'program_prefix',
|
||||
type : 'string',
|
||||
description : 'Prepend string to bwrap executable name, for use with subprojects',
|
||||
)
|
||||
option(
|
||||
'require_userns',
|
||||
type : 'boolean',
|
||||
description : 'require user namespaces by default when installed setuid',
|
||||
value : 'false',
|
||||
)
|
||||
option(
|
||||
'selinux',
|
||||
type : 'feature',
|
||||
description : 'enable optional SELINUX support',
|
||||
value : 'auto',
|
||||
)
|
||||
option(
|
||||
'zsh_completion',
|
||||
type : 'feature',
|
||||
description : 'install zsh completion script',
|
||||
value : 'enabled',
|
||||
)
|
||||
option(
|
||||
'zsh_completion_dir',
|
||||
type : 'string',
|
||||
description : 'install zsh completion script in this directory',
|
||||
value : '',
|
||||
)
|
|
@ -0,0 +1,59 @@
|
|||
test_programs = [
|
||||
['test-utils', executable(
|
||||
'test-utils',
|
||||
'test-utils.c',
|
||||
'../utils.c',
|
||||
'../utils.h',
|
||||
dependencies : [selinux_dep],
|
||||
)],
|
||||
]
|
||||
|
||||
test_scripts = [
|
||||
'test-run.sh',
|
||||
'test-seccomp.py',
|
||||
'test-specifying-pidns.sh',
|
||||
'test-specifying-userns.sh',
|
||||
]
|
||||
|
||||
test_env = environment()
|
||||
test_env.set('BWRAP', bwrap.full_path())
|
||||
test_env.set('G_TEST_BUILDDIR', meson.current_build_dir())
|
||||
test_env.set('G_TEST_SRCDIR', meson.current_source_dir())
|
||||
|
||||
foreach pair : test_programs
|
||||
name = pair[0]
|
||||
test_program = pair[1]
|
||||
if meson.version().version_compare('>=0.50.0')
|
||||
test(
|
||||
name,
|
||||
test_program,
|
||||
env : test_env,
|
||||
protocol : 'tap',
|
||||
)
|
||||
else
|
||||
test(
|
||||
name,
|
||||
test_program,
|
||||
env : test_env,
|
||||
)
|
||||
endif
|
||||
endforeach
|
||||
|
||||
foreach test_script : test_scripts
|
||||
if meson.version().version_compare('>=0.50.0')
|
||||
test(
|
||||
test_script,
|
||||
bash,
|
||||
args : [test_script],
|
||||
env : test_env,
|
||||
protocol : 'tap',
|
||||
)
|
||||
else
|
||||
test(
|
||||
test_script,
|
||||
bash,
|
||||
args : [test_script],
|
||||
env : test_env,
|
||||
)
|
||||
endif
|
||||
endforeach
|
|
@ -0,0 +1,2 @@
|
|||
/_build/
|
||||
/subprojects/
|
|
@ -0,0 +1,3 @@
|
|||
This is a simple example of a project that uses bubblewrap as a
|
||||
subproject. The intention is that if this project can successfully build
|
||||
bubblewrap as a subproject, then so could Flatpak.
|
|
@ -0,0 +1 @@
|
|||
#error Should not use superproject config.h to compile bubblewrap
|
|
@ -0,0 +1 @@
|
|||
#error Should not use superproject generated config.h to compile bubblewrap
|
|
@ -0,0 +1,19 @@
|
|||
project(
|
||||
'use-bubblewrap-as-subproject',
|
||||
'c',
|
||||
version : '0',
|
||||
meson_version : '>=0.49.0',
|
||||
)
|
||||
|
||||
configure_file(
|
||||
output : 'config.h',
|
||||
input : 'dummy-config.h.in',
|
||||
configuration : configuration_data(),
|
||||
)
|
||||
|
||||
subproject(
|
||||
'bubblewrap',
|
||||
default_options : [
|
||||
'program_prefix=not-flatpak-',
|
||||
],
|
||||
)
|
Loading…
Reference in New Issue