toolbox/meson.build

116 lines
3.3 KiB
Meson
Raw Normal View History

project(
'toolbox',
'c',
version: '0.0.99.4',
license: 'ASL 2.0',
Support subordinate user and group ID ranges on enterprise set-ups On enterprise FreeIPA set-ups, the subordinate user and group IDs are provided by SSSD's sss plugin for the GNU Name Service Switch (or NSS) functionality of the GNU C Library. They are not listed in /etc/subuid and /etc/subgid. Therefore, its necessary to use libsubid.so to check the subordinate ID ranges. The CGO interaction with libsubid.so is loosely based on 'readSubid' in github.com/containers/storage/pkg/idtools [1]. However, unlike 'readSubid', this code considers the absence of any range (ie., nRanges == 0) to be an error as well. More importantly, this code uses dlopen(3) and friends to dynamically load the symbols from libsubid.so, instead of linking to libsubid.so at build-time and having the dependency noted in the /usr/bin/toolbox binary. This is done because libsubid.so itself depends on several other shared libraries, and indirect dependencies can't be influenced by the RUNPATH [2] embedded in the /usr/bin/toolbox binary [3]. Hence, when the binary is used inside Toolbx containers (eg., as the entry point), those indirect dependencies won't be picked from the host's runtime against which the binary was built. This can render the binary useless due to ABI compatibility issues. Using dlopen(3) avoids this problem, especially because libsubid.so is only used when running on the host. Care was taken to not load and link libsubid.so twice to separately validate the subordinate ID ranges for the user and the group. Note that libsubid_init() must be passed a FILE pointer for logging. Otherwise, it will create it's own for logging, and there's no way to close it during dlclose(3). Version 4 of the libsubid.so API/ABI [4] was released in Shadow 4.10, which is newer than the versions shipped on RHEL 8 and Debian 10 [5], and even that newer version had some problems [6]. Therefore, support for older versions, with the relevant workarounds, is necessary. Fortunately, the oldest that needs to be support is Shadow 4.9 because that's when libsubid.so was introduced [7]. Note that SUBID_ABI_VERSION was only introduced with version 4 of the libsubid.so API/ABI released in Shadow 4.10 [8]. The first release of libsubid.so in Shadow 4.9 already had an ABI version of 3.0.0 [9], since it was bumped a few times during development, so that's what's assumed when SUBID_ABI_VERSION is absent. This code doesn't set the public variables Prog and shadow_logfd that older Shadow versions used to expect for logging, because from Shadow 4.9 onwards there's a separate function [4,10] to specify these. This can be changed if there are libsubid.so versions in the wild that really do need those public variables to be set. Finally, ISO C99 is required because of the use of <stdbool.h> in the libsubid.so API. Some changes by Debarshi Ray. [1] https://github.com/containers/storage/blob/main/pkg/idtools/idtools_supported.go [2] https://man7.org/linux/man-pages/man8/ld.so.8.html [3] Commit 6063eb27b9893994 https://github.com/containers/toolbox/issues/821 [4] Shadow commit 32f641b207f6ddff https://github.com/shadow-maint/shadow/commit/32f641b207f6ddff https://github.com/shadow-maint/shadow/issues/443 [5] https://packages.debian.org/source/buster/shadow [6] Shadow commit 79157cbad87f42cd https://github.com/shadow-maint/shadow/commit/79157cbad87f42cd https://github.com/shadow-maint/shadow/issues/465 [7] Shadow commit 0a7888b1fad613a0 https://github.com/shadow-maint/shadow/commit/0a7888b1fad613a0 https://github.com/shadow-maint/shadow/issues/154 [8] Shadow commit 0c9f64140852e8d5 https://github.com/shadow-maint/shadow/commit/0c9f64140852e8d5 https://github.com/shadow-maint/shadow/pull/449 [9] Shadow commit 3d670ba7ed58f910 https://github.com/shadow-maint/shadow/commit/3d670ba7ed58f910 https://github.com/shadow-maint/shadow/issues/339 [10] Shadow commit 2b22a6909dba60d https://github.com/shadow-maint/shadow/commit/2b22a6909dba60d https://github.com/shadow-maint/shadow/issues/325 https://github.com/containers/toolbox/issues/1074 Signed-off-by: Martin Jackson <martjack@redhat.com>
2022-11-28 22:45:42 +00:00
default_options: 'c_std=c99',
meson_version: '>= 0.58.0',
)
build: Call 'systemd-tmpfiles --create' when installing It's only necessary to call 'systemd-tmpfiles --create' when building and installing from source on the host operating system. It's not needed when using a pre-built binary downstream package, because: * When 'meson install' is called as part of building the package, that's not when the temporary files need to be created. They need to be created when the binary package is later downloaded and installed by the user. * Downstream tools can sometimes handle it automatically. eg., on Fedora, the systemd RPM installs a trigger that tells RPM to call 'systemd-tmpfiles --create' automatically when a tmpfiles.d snippet is installed. It's also not needed when installing inside a toolbox container because the files that 'systemd-tmpfiles --create' is supposed to create are meant to be on the host. Downstream distributors set the DESTDIR environment variable when building their packages. Therefore, it's used to detect when a downstream package is being built. Unfortunately, environment variables are messy and, generally, Meson doesn't support accessing them inside its scripts [1]. Therefore, this adds a spurious build-time dependency on systemd for downstream distributors. However, that's probably not a big problem because all supported downstream operating systems are already expected to use systemd for the tmpfiles.d(5) snippets to work. [1] https://github.com/mesonbuild/meson/issues/9 https://github.com/containers/toolbox/issues/955
2021-12-17 16:45:43 +00:00
fs = import('fs')
cc = meson.get_compiler('c')
if not cc.has_argument('-print-file-name=libc.so')
error('C compiler does not support the -print-file-name argument.')
endif
Support subordinate user and group ID ranges on enterprise set-ups On enterprise FreeIPA set-ups, the subordinate user and group IDs are provided by SSSD's sss plugin for the GNU Name Service Switch (or NSS) functionality of the GNU C Library. They are not listed in /etc/subuid and /etc/subgid. Therefore, its necessary to use libsubid.so to check the subordinate ID ranges. The CGO interaction with libsubid.so is loosely based on 'readSubid' in github.com/containers/storage/pkg/idtools [1]. However, unlike 'readSubid', this code considers the absence of any range (ie., nRanges == 0) to be an error as well. More importantly, this code uses dlopen(3) and friends to dynamically load the symbols from libsubid.so, instead of linking to libsubid.so at build-time and having the dependency noted in the /usr/bin/toolbox binary. This is done because libsubid.so itself depends on several other shared libraries, and indirect dependencies can't be influenced by the RUNPATH [2] embedded in the /usr/bin/toolbox binary [3]. Hence, when the binary is used inside Toolbx containers (eg., as the entry point), those indirect dependencies won't be picked from the host's runtime against which the binary was built. This can render the binary useless due to ABI compatibility issues. Using dlopen(3) avoids this problem, especially because libsubid.so is only used when running on the host. Care was taken to not load and link libsubid.so twice to separately validate the subordinate ID ranges for the user and the group. Note that libsubid_init() must be passed a FILE pointer for logging. Otherwise, it will create it's own for logging, and there's no way to close it during dlclose(3). Version 4 of the libsubid.so API/ABI [4] was released in Shadow 4.10, which is newer than the versions shipped on RHEL 8 and Debian 10 [5], and even that newer version had some problems [6]. Therefore, support for older versions, with the relevant workarounds, is necessary. Fortunately, the oldest that needs to be support is Shadow 4.9 because that's when libsubid.so was introduced [7]. Note that SUBID_ABI_VERSION was only introduced with version 4 of the libsubid.so API/ABI released in Shadow 4.10 [8]. The first release of libsubid.so in Shadow 4.9 already had an ABI version of 3.0.0 [9], since it was bumped a few times during development, so that's what's assumed when SUBID_ABI_VERSION is absent. This code doesn't set the public variables Prog and shadow_logfd that older Shadow versions used to expect for logging, because from Shadow 4.9 onwards there's a separate function [4,10] to specify these. This can be changed if there are libsubid.so versions in the wild that really do need those public variables to be set. Finally, ISO C99 is required because of the use of <stdbool.h> in the libsubid.so API. Some changes by Debarshi Ray. [1] https://github.com/containers/storage/blob/main/pkg/idtools/idtools_supported.go [2] https://man7.org/linux/man-pages/man8/ld.so.8.html [3] Commit 6063eb27b9893994 https://github.com/containers/toolbox/issues/821 [4] Shadow commit 32f641b207f6ddff https://github.com/shadow-maint/shadow/commit/32f641b207f6ddff https://github.com/shadow-maint/shadow/issues/443 [5] https://packages.debian.org/source/buster/shadow [6] Shadow commit 79157cbad87f42cd https://github.com/shadow-maint/shadow/commit/79157cbad87f42cd https://github.com/shadow-maint/shadow/issues/465 [7] Shadow commit 0a7888b1fad613a0 https://github.com/shadow-maint/shadow/commit/0a7888b1fad613a0 https://github.com/shadow-maint/shadow/issues/154 [8] Shadow commit 0c9f64140852e8d5 https://github.com/shadow-maint/shadow/commit/0c9f64140852e8d5 https://github.com/shadow-maint/shadow/pull/449 [9] Shadow commit 3d670ba7ed58f910 https://github.com/shadow-maint/shadow/commit/3d670ba7ed58f910 https://github.com/shadow-maint/shadow/issues/339 [10] Shadow commit 2b22a6909dba60d https://github.com/shadow-maint/shadow/commit/2b22a6909dba60d https://github.com/shadow-maint/shadow/issues/325 https://github.com/containers/toolbox/issues/1074 Signed-off-by: Martin Jackson <martjack@redhat.com>
2022-11-28 22:45:42 +00:00
subid_dep = cc.find_library('subid', has_headers: ['shadow/subid.h'])
go = find_program('go')
go_md2man = find_program('go-md2man')
bats = find_program('bats', required: false)
codespell = find_program('codespell', required: false)
htpasswd = find_program('htpasswd', required: false)
openssl = find_program('openssl', required: false)
podman = find_program('podman', required: false)
shellcheck = find_program('shellcheck', required: false)
skopeo = find_program('skopeo', required: false)
build: Enable changing the completion paths & drop install_completions The bash-completion and fish dependencies were already optional - the shell completions for Bash and fish won't be generated and installed if they are absent; and there's no dependency required for Z shell. So the install_completions build option wasn't reducing the dependency burden. The build option was a way to disable the generation and installation of the shell completions, regardless of whether the necessary dependencies are present or not. The only use-case for this is when installing to a non-system-wide prefix while hacking on Toolbox as a non-root user, because the locations for the completions advertised by the shells' APIs might not be accessible. Being able to disable the completions prevents the installation from failing. A different way of ensuring a smooth developer experience for a Toolbx hacker is to offer a way to change the locations where the shell completions are installed, which is necessary and beneficial for other use-cases. Z shell, unlike Bash's bash-completion.pc and fish's fish.pc, doesn't offer an API to detect the location for the shell completions. This means that Debian and Fedora use different locations [1, 2]. Namely, /usr/share/zsh/vendor-completions and /usr/share/zsh/site-functions. An option to specify the locations for the shell completions can optimize the build, if there's an alternate API for the location that doesn't involve using bash-completion.pc and fish.pc as build dependencies. eg., Fedora provides the _tmpfilesdir RPM macro to specify the location for vendor-supplied tmpfiles.d(5) files, which makes it possible to avoid having systemd.pc as a build dependency [3]. Fallout from bafbbe81c9220cb3749a19a244e45a61477553a6 [1] Debian zsh commit bf0a44a8744469b5 https://salsa.debian.org/debian/zsh/-/commit/bf0a44a8744469b5 https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=620452 [2] https://src.fedoraproject.org/rpms/zsh/blob/f37/f/zsh.spec [3] Fedora toolbox commit 9bebde5bb60f36e3 https://src.fedoraproject.org/rpms/toolbox/c/9bebde5bb60f36e3 https://github.com/containers/toolbox/pull/1123 https://github.com/containers/toolbox/pull/840
2022-09-09 11:25:52 +00:00
bashcompletionsdir = get_option('bash_completions_dir')
if bashcompletionsdir == ''
bash_completion_dep = dependency('bash-completion', required: false)
if bash_completion_dep.found()
bashcompletionsdir = bash_completion_dep.get_variable(pkgconfig: 'completionsdir')
endif
endif
fishcompletionsdir = get_option('fish_completions_dir')
if fishcompletionsdir == ''
fish_completion_dep = dependency('fish', required: false)
if fish_completion_dep.found()
fishcompletionsdir = fish_completion_dep.get_variable(pkgconfig: 'completionsdir')
endif
endif
zshcompletionsdir = get_option('zsh_completions_dir')
if zshcompletionsdir == ''
zshcompletionsdir = get_option('datadir') / 'zsh' / 'site-functions'
endif
migration_path_for_coreos_toolbox = get_option('migration_path_for_coreos_toolbox')
profiledir = get_option('profile_dir')
tmpfilesdir = get_option('tmpfiles_dir')
build: Call 'systemd-tmpfiles --create' when installing It's only necessary to call 'systemd-tmpfiles --create' when building and installing from source on the host operating system. It's not needed when using a pre-built binary downstream package, because: * When 'meson install' is called as part of building the package, that's not when the temporary files need to be created. They need to be created when the binary package is later downloaded and installed by the user. * Downstream tools can sometimes handle it automatically. eg., on Fedora, the systemd RPM installs a trigger that tells RPM to call 'systemd-tmpfiles --create' automatically when a tmpfiles.d snippet is installed. It's also not needed when installing inside a toolbox container because the files that 'systemd-tmpfiles --create' is supposed to create are meant to be on the host. Downstream distributors set the DESTDIR environment variable when building their packages. Therefore, it's used to detect when a downstream package is being built. Unfortunately, environment variables are messy and, generally, Meson doesn't support accessing them inside its scripts [1]. Therefore, this adds a spurious build-time dependency on systemd for downstream distributors. However, that's probably not a big problem because all supported downstream operating systems are already expected to use systemd for the tmpfiles.d(5) snippets to work. [1] https://github.com/mesonbuild/meson/issues/9 https://github.com/containers/toolbox/issues/955
2021-12-17 16:45:43 +00:00
if tmpfilesdir == '' or not fs.exists('/run/.containerenv')
systemd_dep = dependency('systemd')
build: Call 'systemd-tmpfiles --create' when installing It's only necessary to call 'systemd-tmpfiles --create' when building and installing from source on the host operating system. It's not needed when using a pre-built binary downstream package, because: * When 'meson install' is called as part of building the package, that's not when the temporary files need to be created. They need to be created when the binary package is later downloaded and installed by the user. * Downstream tools can sometimes handle it automatically. eg., on Fedora, the systemd RPM installs a trigger that tells RPM to call 'systemd-tmpfiles --create' automatically when a tmpfiles.d snippet is installed. It's also not needed when installing inside a toolbox container because the files that 'systemd-tmpfiles --create' is supposed to create are meant to be on the host. Downstream distributors set the DESTDIR environment variable when building their packages. Therefore, it's used to detect when a downstream package is being built. Unfortunately, environment variables are messy and, generally, Meson doesn't support accessing them inside its scripts [1]. Therefore, this adds a spurious build-time dependency on systemd for downstream distributors. However, that's probably not a big problem because all supported downstream operating systems are already expected to use systemd for the tmpfiles.d(5) snippets to work. [1] https://github.com/mesonbuild/meson/issues/9 https://github.com/containers/toolbox/issues/955
2021-12-17 16:45:43 +00:00
if tmpfilesdir == ''
tmpfilesdir = systemd_dep.get_variable(pkgconfig: 'tmpfilesdir')
endif
endif
Give access to removable devices and other temporary mounts Currently, when udisks is configured to use /run/media instead of /media, on most operating systems, the /run/media directory is created by udisks itself when the first mount is handled [1]. This causes problems when creating the toolbox container, if nothing has been mounted after the current boot, because a missing directory cannot be bind mounted. Fedora Silverblue is a significant exception to the above, where rpm-ostree takes care of creating /run/media with systemd-tmpfiles [2] during boot. The correct long-term solution is to get udisks to create /run/media during boot with systemd-tmpfiles by installing a snippet in tmpfiles.d [3, 4]. Until that happens, and is widely deployed, the toolbox needs to provide the snippet itself to make things work on the majority of operating systems. Note that, in case udisks is configured to use /media instead of /run/media, then this will create an unused /run/media directory. This is probably fine because /run/media is the default setting for udisks. Moreover, an unused directory is way better than not being able to access mount points from a toolbox container or having 'podman create' fail due to a missing directory. Based on 4a2a15f2eb3a6b810fcf9b699272fcc9a7871c6e and as suggested by Daniel J Walsh. [1] UDisks commit aa02e5fc53efdeaf https://github.com/storaged-project/udisks/commit/aa02e5fc53efdeaf [2] rpm-ostree commit 958dfa435e4e4a3e https://github.com/projectatomic/rpm-ostree/commit/958dfa435e4e4a3e [3] https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html [4] https://github.com/storaged-project/udisks/pull/641 https://github.com/debarshiray/toolbox/issues/3
2019-03-12 17:45:19 +00:00
toolbox_sh = files('toolbox')
if codespell.found()
test(
'codespell',
codespell,
args: [
'--check-filenames',
'--check-hidden',
'--context', '3',
'--exclude-file', meson.project_source_root() / '.codespellexcludefile',
'--skip', meson.project_build_root(),
'--skip', meson.project_source_root() / '.git',
'--skip', meson.project_source_root() / 'test/system/libs/bats-assert',
'--skip', meson.project_source_root() / 'test/system/libs/bats-support',
meson.project_source_root(),
],
)
endif
if shellcheck.found()
test('shellcheck toolbox (deprecated)', shellcheck, args: [toolbox_sh])
endif
install_subdir(
'test',
install_dir: get_option('datadir') / meson.project_name(),
exclude_files: [
'system/libs/bats-assert/.git',
'system/libs/bats-assert/.gitignore',
'system/libs/bats-assert/.travis.yml',
'system/libs/bats-assert/package.json',
'system/libs/bats-support/.git',
'system/libs/bats-support/.gitignore',
'system/libs/bats-support/.travis.yml',
'system/libs/bats-support/package.json'
],
exclude_directories: [
'system/libs/bats-assert/.git',
'system/libs/bats-assert/script',
'system/libs/bats-assert/test',
'system/libs/bats-support/.git',
'system/libs/bats-support/script',
'system/libs/bats-support/test'
]
)
Give access to removable devices and other temporary mounts Currently, when udisks is configured to use /run/media instead of /media, on most operating systems, the /run/media directory is created by udisks itself when the first mount is handled [1]. This causes problems when creating the toolbox container, if nothing has been mounted after the current boot, because a missing directory cannot be bind mounted. Fedora Silverblue is a significant exception to the above, where rpm-ostree takes care of creating /run/media with systemd-tmpfiles [2] during boot. The correct long-term solution is to get udisks to create /run/media during boot with systemd-tmpfiles by installing a snippet in tmpfiles.d [3, 4]. Until that happens, and is widely deployed, the toolbox needs to provide the snippet itself to make things work on the majority of operating systems. Note that, in case udisks is configured to use /media instead of /run/media, then this will create an unused /run/media directory. This is probably fine because /run/media is the default setting for udisks. Moreover, an unused directory is way better than not being able to access mount points from a toolbox container or having 'podman create' fail due to a missing directory. Based on 4a2a15f2eb3a6b810fcf9b699272fcc9a7871c6e and as suggested by Daniel J Walsh. [1] UDisks commit aa02e5fc53efdeaf https://github.com/storaged-project/udisks/commit/aa02e5fc53efdeaf [2] rpm-ostree commit 958dfa435e4e4a3e https://github.com/projectatomic/rpm-ostree/commit/958dfa435e4e4a3e [3] https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html [4] https://github.com/storaged-project/udisks/pull/641 https://github.com/debarshiray/toolbox/issues/3
2019-03-12 17:45:19 +00:00
subdir('data')
subdir('doc')
subdir('profile.d')
subdir('src')
build: Call 'systemd-tmpfiles --create' when installing It's only necessary to call 'systemd-tmpfiles --create' when building and installing from source on the host operating system. It's not needed when using a pre-built binary downstream package, because: * When 'meson install' is called as part of building the package, that's not when the temporary files need to be created. They need to be created when the binary package is later downloaded and installed by the user. * Downstream tools can sometimes handle it automatically. eg., on Fedora, the systemd RPM installs a trigger that tells RPM to call 'systemd-tmpfiles --create' automatically when a tmpfiles.d snippet is installed. It's also not needed when installing inside a toolbox container because the files that 'systemd-tmpfiles --create' is supposed to create are meant to be on the host. Downstream distributors set the DESTDIR environment variable when building their packages. Therefore, it's used to detect when a downstream package is being built. Unfortunately, environment variables are messy and, generally, Meson doesn't support accessing them inside its scripts [1]. Therefore, this adds a spurious build-time dependency on systemd for downstream distributors. However, that's probably not a big problem because all supported downstream operating systems are already expected to use systemd for the tmpfiles.d(5) snippets to work. [1] https://github.com/mesonbuild/meson/issues/9 https://github.com/containers/toolbox/issues/955
2021-12-17 16:45:43 +00:00
meson.add_install_script('meson_post_install.py')