Skip to content

Commit

Permalink
Add a Meson build system
Browse files Browse the repository at this point in the history
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.

Loosely based on previous work by Jussi Pakkanen (see containers#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>
  • Loading branch information
smcv committed Feb 18, 2022
1 parent 43c2d32 commit 46788f3
Show file tree
Hide file tree
Showing 14 changed files with 405 additions and 1 deletion.
67 changes: 66 additions & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions ci/builddeps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ if dpkg-vendor --derives-from Debian; then
libcap-dev \
libselinux1-dev \
libtool \
meson \
pkg-config \
python3 \
xsltproc \
Expand Down Expand Up @@ -92,6 +93,7 @@ if command -v yum; then
libubsan \
libxslt \
make \
meson \
redhat-rpm-config \
rsync \
${NULL+}
Expand Down
37 changes: 37 additions & 0 deletions completions/bash/meson.build
Original file line number Diff line number Diff line change
@@ -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)
7 changes: 7 additions & 0 deletions completions/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
if get_option('bash_completion').enabled()
subdir('bash')
endif

if get_option('zsh_completion').enabled()
subdir('zsh')
endif
7 changes: 7 additions & 0 deletions completions/zsh/meson.build
Original file line number Diff line number Diff line change
@@ -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)
144 changes: 144 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
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', 'bubblewrap')

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
47 changes: 47 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
@@ -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 : '',
)
Loading

0 comments on commit 46788f3

Please sign in to comment.