mirror of
https://git.proxmox.com/git/mirror_lxc
synced 2025-04-28 12:52:23 +00:00

This is purely so that we can do static linking. Linking against libsystemd makes that a challenge because while it's perfectly simple to do, distros tend not to provide a libsystemd.a. Tools that want to (a) link against liblxc and (b) have a statically linked binary to bind into a minimal container are ill served by this. So link against libdbus-1. .github/workflows/build.yml: switch to dbus-1. src/lxc/cgroups/cgfsng.c: replace the unpriv_systemd_create_scope(), start_scope, and enter_scope() systemd code with dbus-1 code. src/tests/oss-fuzz.sh: update from libsystemd-dev to libdbus-1-dev src/tests/oss-fuzz.sh: disable dbus .github/workflows/*: update from libsystemd-dev to libdbus-1-dev meson.build and meson_options.txt: switch from sd_bus to dbus lxc.spec.in: add dbus-1 to BuildRequires Signed-off-by: Serge Hallyn <serge@hallyn.com> Changelog: 03/13: use custom iter type so we can cleanup more easily... Changelog: 03/13: initialize each dbus_iter to { 0 } as mihalicyn suggested.
1006 lines
32 KiB
Meson
1006 lines
32 KiB
Meson
# SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
# Project.
|
|
project(
|
|
'lxc',
|
|
'c',
|
|
version: '5.0.0',
|
|
license: 'LGPLv2+',
|
|
default_options: [
|
|
'b_lto=true',
|
|
'b_lto_mode=thin',
|
|
'b_colorout=always',
|
|
'b_asneeded=false',
|
|
'b_pie=true',
|
|
'b_staticpic=true',
|
|
'c_std=gnu11',
|
|
'warning_level=2',
|
|
],
|
|
meson_version: '>= 0.61')
|
|
|
|
cc = meson.get_compiler('c')
|
|
pkgconfig = import('pkgconfig')
|
|
pkgconfig_libs = []
|
|
|
|
liblxc_dependencies = []
|
|
oss_fuzz_dependencies = []
|
|
|
|
# Version.
|
|
liblxc_version = '1.7.0'
|
|
version_data = configuration_data()
|
|
version_data.set('LXC_VERSION_MAJOR', '5')
|
|
version_data.set('LXC_VERSION_MINOR', '0')
|
|
version_data.set('LXC_VERSION_MICRO', '0')
|
|
version_data.set('LXC_VERSION_BETA', '')
|
|
version_data.set('LXC_ABI', liblxc_version)
|
|
version_data.set('LXC_DEVEL', '1')
|
|
version_data.set('LXC_VERSION', meson.project_version())
|
|
|
|
# Path handling.
|
|
project_source_root = meson.current_source_dir()
|
|
project_build_root = meson.current_build_dir()
|
|
prefixdir = get_option('prefix')
|
|
|
|
apparmorcachedir = get_option('apparmor-cache-path')
|
|
globalconfig = get_option('global-config-path')
|
|
localstatedir = join_paths('/', get_option('localstatedir'))
|
|
logpath = get_option('log-path')
|
|
lxcpathprefix = get_option('data-path')
|
|
rootfsmount = get_option('rootfs-mount-path')
|
|
user_network_db_opt = get_option('usernet-db-path')
|
|
user_network_conf_opt = get_option('usernet-config-path')
|
|
|
|
bashcompletiondir = join_paths('/', 'usr', 'share', 'bash-completion', 'completions')
|
|
bindir = join_paths(prefixdir, get_option('bindir'))
|
|
datadir = join_paths(prefixdir, get_option('datadir'))
|
|
mandir = join_paths(prefixdir, get_option('mandir'))
|
|
docdir = join_paths(datadir, get_option('doc-path'))
|
|
includedir = join_paths(prefixdir, get_option('includedir'))
|
|
libdir = join_paths(prefixdir, get_option('libdir'))
|
|
libexecdir = join_paths(prefixdir, get_option('libexecdir'))
|
|
runtimepath = join_paths(prefixdir, get_option('runtime-path'))
|
|
sbindir = join_paths(prefixdir, get_option('sbindir'))
|
|
sysconfdir = join_paths(prefixdir, get_option('sysconfdir'))
|
|
|
|
lxcapparmorcachedir = join_paths(localstatedir, apparmorcachedir)
|
|
lxcconfdir = join_paths(sysconfdir, globalconfig)
|
|
lxcdefaultconfig = join_paths(lxcconfdir, 'default.conf')
|
|
lxcglobalconfig = join_paths(lxcconfdir, 'lxc.conf')
|
|
lxcexamplesdir = join_paths(docdir, 'examples')
|
|
lxchookbindir = join_paths(libexecdir, 'lxc/hooks')
|
|
lxcinclude = join_paths(includedir, 'lxc')
|
|
lxclibexec = join_paths(libexecdir, 'lxc')
|
|
lxclogpath = join_paths(localstatedir, logpath)
|
|
lxcpath = join_paths(localstatedir, lxcpathprefix)
|
|
lxcrootfsmount = join_paths(libdir, rootfsmount)
|
|
lxcdatadir = join_paths(datadir, 'lxc')
|
|
lxchookdir = join_paths(lxcdatadir, 'hooks')
|
|
lxcselinuxdir = join_paths(lxcdatadir, 'selinux')
|
|
lxctemplateconfdir = join_paths(lxcdatadir, 'config')
|
|
lxctemplateconfcommondir = join_paths(lxctemplateconfdir, 'common.conf.d')
|
|
lxctemplatedir = join_paths(lxcdatadir, 'templates')
|
|
lxc_user_network_conf = join_paths(sysconfdir, user_network_conf_opt)
|
|
lxc_user_network_db = join_paths(runtimepath, user_network_db_opt)
|
|
pam_security = join_paths(libdir, 'security')
|
|
|
|
# Configuration options.
|
|
srcconf = configuration_data()
|
|
srcconf.set('_GNU_SOURCE', true)
|
|
srcconf.set('_FILE_OFFSET_BITS', 64)
|
|
srcconf.set('__STDC_FORMAT_MACROS', true)
|
|
|
|
## This is a hack to prevent any inclusion ofr linux/mount.h which causes
|
|
## conflicts with sys/mount.h all over the place
|
|
srcconf.set('_LINUX_MOUNT_H', true)
|
|
|
|
srcconf.set_quoted('APPARMOR_CACHE_DIR', lxcapparmorcachedir)
|
|
srcconf.set_quoted('LIBEXECDIR', libexecdir)
|
|
srcconf.set_quoted('LOGPATH', lxclogpath)
|
|
srcconf.set_quoted('LXC_DEFAULT_CONFIG', lxcdefaultconfig)
|
|
srcconf.set_quoted('LXC_GLOBAL_CONF', lxcglobalconfig)
|
|
srcconf.set_quoted('LXCINITDIR', libexecdir)
|
|
srcconf.set_quoted('LXCPATH', lxcpath)
|
|
srcconf.set_quoted('LXCROOTFSMOUNT', lxcrootfsmount)
|
|
srcconf.set_quoted('LXCTEMPLATECONFIG', lxctemplateconfdir)
|
|
srcconf.set_quoted('LXCTEMPLATECONFIG', lxctemplateconfdir)
|
|
srcconf.set_quoted('LXCTEMPLATEDIR', lxctemplatedir)
|
|
srcconf.set_quoted('LXC_USERNIC_CONF', lxc_user_network_conf)
|
|
srcconf.set_quoted('LXC_USERNIC_DB', lxc_user_network_db)
|
|
srcconf.set_quoted('RUNTIME_PATH', runtimepath)
|
|
srcconf.set_quoted('SBINDIR', sbindir)
|
|
|
|
conf = configuration_data()
|
|
conf.set('BINDIR', bindir)
|
|
conf.set('LIBEXECDIR', libexecdir)
|
|
conf.set('LOCALSTATEDIR', localstatedir)
|
|
conf.set('LXC_GLOBAL_CONF', lxcglobalconfig)
|
|
conf.set('LXCHOOKDIR', lxchookdir)
|
|
conf.set('LXCINITDIR', libexecdir)
|
|
conf.set('LXCROOTFSMOUNT', lxcrootfsmount)
|
|
conf.set('LXCTEMPLATECONFIG', lxctemplateconfdir)
|
|
conf.set('LXCTEMPLATEDIR', lxctemplatedir)
|
|
conf.set('PACKAGE_VERSION', meson.project_version())
|
|
conf.set('RUNTIME_PATH', runtimepath)
|
|
conf.set('SYSCONFDIR', sysconfdir)
|
|
|
|
# Set sysconfdir
|
|
fs = import('fs')
|
|
distrosysconfdir = get_option('distrosysconfdir')
|
|
if distrosysconfdir != ''
|
|
distrosysconfdir = join_paths(sysconfdir, distrosysconfdir)
|
|
conf.set('LXC_DISTRO_SYSCONF', distrosysconfdir)
|
|
elif fs.is_dir('/etc/sysconfig')
|
|
distrosysconfdir = join_paths(sysconfdir, 'sysconfig')
|
|
conf.set('LXC_DISTRO_SYSCONF', distrosysconfdir)
|
|
elif fs.is_dir('/etc/default')
|
|
distrosysconfdir = join_paths(sysconfdir, 'default')
|
|
conf.set('LXC_DISTRO_SYSCONF', distrosysconfdir)
|
|
else
|
|
error('"distrosysconfdir" is not set')
|
|
endif
|
|
|
|
# Cross-compile on Android.
|
|
srcconf.set10('IS_BIONIC', host_machine.system() == 'android')
|
|
|
|
# Custom configuration.
|
|
cgrouppattern = get_option('cgroup-pattern')
|
|
coverity = get_option('coverity-build')
|
|
init_script = get_option('init-script')
|
|
sanitize = get_option('b_sanitize')
|
|
want_examples = get_option('examples')
|
|
want_io_uring = get_option('io-uring-event-loop')
|
|
want_pam_cgroup = get_option('pam-cgroup')
|
|
want_mans = get_option('man')
|
|
want_tests = get_option('tests')
|
|
want_tools = get_option('tools')
|
|
want_tools_multicall = get_option('tools-multicall')
|
|
want_commands = get_option('commands')
|
|
want_capabilities = get_option('capabilities')
|
|
want_apparmor = get_option('apparmor')
|
|
want_openssl = get_option('openssl')
|
|
want_selinux = get_option('selinux')
|
|
want_oss_fuzz = get_option('oss-fuzz')
|
|
want_seccomp = get_option('seccomp')
|
|
want_thread_safety = get_option('thread-safety')
|
|
want_memfd_rexec = get_option('memfd-rexec')
|
|
want_dbus = get_option('dbus')
|
|
|
|
srcconf.set_quoted('DEFAULT_CGROUP_PATTERN', cgrouppattern)
|
|
if coverity
|
|
srcconf.set('ENABLE_COVERITY_BUILD', 1)
|
|
endif
|
|
|
|
dummy_config_data = configuration_data()
|
|
dummy_config_data.set_quoted('DUMMY_VARIABLE', '1')
|
|
|
|
# Those generate many false positives, and we do not want to change the code to
|
|
# avoid them.
|
|
basic_disabled_warnings = [
|
|
'-Wno-format-signedness',
|
|
'-Wno-missing-field-initializers',
|
|
'-Wno-unused-parameter',
|
|
]
|
|
|
|
# Build flags.
|
|
possible_cc_flags = [
|
|
'-Wvla',
|
|
'-Wimplicit-fallthrough=5',
|
|
'-Wcast-align',
|
|
'-Wstrict-prototypes',
|
|
'-fno-strict-aliasing',
|
|
'-fstack-clash-protection',
|
|
'--param=ssp-buffer-size=4',
|
|
'--mcet -fcf-protection',
|
|
'-Werror=implicit-function-declaration',
|
|
'-Wlogical-op',
|
|
'-Wmissing-include-dirs',
|
|
'-Wold-style-definition',
|
|
'-Winit-self',
|
|
'-Wunused-but-set-variable',
|
|
'-Wno-unused-parameter',
|
|
'-Wfloat-equal',
|
|
'-Wsuggest-attribute=noreturn',
|
|
'-Werror=return-type',
|
|
'-Werror=incompatible-pointer-types',
|
|
'-Wformat=2',
|
|
'-Wshadow',
|
|
'-Wendif-labels',
|
|
'-Werror=overflow',
|
|
'-fdiagnostics-show-option',
|
|
'-Werror=shift-count-overflow',
|
|
'-Werror=shift-overflow=2',
|
|
'-Wdate-time',
|
|
'-Wnested-externs',
|
|
'-fasynchronous-unwind-tables',
|
|
'-fexceptions',
|
|
'-Warray-bounds',
|
|
'-Wrestrict',
|
|
'-Wreturn-local-addr',
|
|
'-fsanitize=cfi',
|
|
'-Wstringop-overflow',
|
|
]
|
|
|
|
possible_link_flags = [
|
|
'-Wl,--no-as-needed',
|
|
'-Wl,--gc-sections',
|
|
'-Wl,-z,relro',
|
|
'-Wl,-z,now',
|
|
'-fstack-protector',
|
|
'-fstack-protector-strong',
|
|
]
|
|
|
|
# The gold linker fails with a bus error on sparc64
|
|
if build_machine.cpu_family() != 'sparc64'
|
|
possible_link_flags += '-Wl,-fuse-ld=gold'
|
|
endif
|
|
|
|
if sanitize == 'none'
|
|
possible_link_flags += '-Wl,--warn-common'
|
|
endif
|
|
|
|
if cc.get_id() == 'clang'
|
|
possible_cc_flags += [
|
|
'-Wno-typedef-redefinition',
|
|
'-Wno-gnu-variable-sized-type-not-at-end',
|
|
]
|
|
endif
|
|
|
|
if meson.version().version_compare('>=0.46')
|
|
add_project_link_arguments(cc.get_supported_link_arguments(possible_link_flags), language: 'c')
|
|
else
|
|
add_project_link_arguments(possible_link_flags, language: 'c')
|
|
endif
|
|
|
|
add_project_arguments(cc.get_supported_arguments(basic_disabled_warnings), language : 'c')
|
|
add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language: 'c')
|
|
|
|
if add_languages('cpp', required : want_oss_fuzz)
|
|
# Used only for tests
|
|
cxx = meson.get_compiler('cpp')
|
|
cxx_cmd = ' '.join(cxx.cmd_array())
|
|
add_project_arguments(cxx.get_supported_arguments(basic_disabled_warnings), language : 'cpp')
|
|
endif
|
|
|
|
# Feature detection
|
|
## I/O uring.
|
|
if want_io_uring
|
|
liburing = dependency('liburing')
|
|
if cc.has_function('io_uring_prep_poll_add', prefix: '#include <liburing.h>', dependencies: liburing) == false
|
|
error('liburing version does not support IORING_POLL_ADD_MULTI')
|
|
endif
|
|
pkgconfig_libs += liburing
|
|
liblxc_dependencies += liburing
|
|
|
|
srcconf.set10('HAVE_LIBURING', true)
|
|
else
|
|
srcconf.set10('HAVE_LIBURING', false)
|
|
endif
|
|
|
|
if want_dbus
|
|
libdbus = dependency('dbus-1', required: true)
|
|
pkgconfig_libs += libdbus
|
|
liblxc_dependencies += libdbus
|
|
srcconf.set10('HAVE_DBUS', libdbus.found())
|
|
else
|
|
srcconf.set10('HAVE_DBUS', false)
|
|
endif
|
|
|
|
## Time EPOCH.
|
|
sh = find_program('sh')
|
|
date = find_program('date')
|
|
git = find_program('git', required: false)
|
|
time_epoch = run_command(sh, '-c', 'echo "$SOURCE_DATE_EPOCH"', check: true).stdout().strip()
|
|
if time_epoch == '' and git.found() and run_command('test', '-e', '.git', check: false).returncode() == 0
|
|
# If we're in a git repository, use the creation time of the latest git tag.
|
|
latest_tag = run_command(git, 'describe', '--abbrev=0', '--tags', check: false).stdout().strip()
|
|
if latest_tag != ''
|
|
time_epoch = run_command(git, 'log', '--no-show-signature', '-1', '--format=%at', latest_tag, check: true).stdout().strip()
|
|
endif
|
|
endif
|
|
|
|
# Fallback to current epoch.
|
|
if time_epoch == ''
|
|
time_epoch = run_command(date, '+%s', check: true).stdout().strip()
|
|
endif
|
|
generate_date = run_command(date, '--utc', '--date=@' + time_epoch, '+%Y-%m-%d', check: true).stdout().strip()
|
|
|
|
## Manpages.
|
|
docconf = configuration_data()
|
|
docconf.set('builddir', '.')
|
|
docconf.set('BINDIR', bindir)
|
|
docconf.set('DATADIR', datadir)
|
|
docconf.set('DOCDIR', docdir)
|
|
docconf.set('LOGPATH', lxclogpath)
|
|
docconf.set('LXC_DEFAULT_CONFIG', lxcdefaultconfig)
|
|
docconf.set('LXC_GENERATE_DATE', generate_date)
|
|
docconf.set('LXC_GLOBAL_CONF', lxcglobalconfig)
|
|
docconf.set('LXCPATH', lxcpath)
|
|
docconf.set('LXCTEMPLATEDIR', lxctemplatedir)
|
|
docconf.set('LXC_USERNIC_CONF', lxc_user_network_conf)
|
|
docconf.set('LXC_USERNIC_DB', lxc_user_network_db)
|
|
docconf.set('PACKAGE_VERSION', version_data.get('LXC_VERSION'))
|
|
docconf.set('docdtd', '"-//OASIS//DTD DocBook XML" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"')
|
|
sgml2man = find_program('docbook2X2man', 'docbook2x-man', 'db2x_docbook2man', 'docbook2man', 'docbook-to-man', required: false, version: '>=0.8')
|
|
if not sgml2man.found()
|
|
sgml2man = find_program('docbook2man', required: false, version: '<0.8')
|
|
if sgml2man.found()
|
|
docconf.set('docdtd', '"-//Davenport//DTD DocBook V3.0//EN"')
|
|
elif want_mans
|
|
error('missing required docbook2x or docbook-utils dependency')
|
|
endif
|
|
endif
|
|
|
|
## Threads.
|
|
threads = dependency('threads')
|
|
liblxc_dependencies += threads
|
|
|
|
## Seccomp.
|
|
if want_seccomp
|
|
libseccomp = dependency('libseccomp', required: false)
|
|
srcconf.set10('HAVE_SECCOMP', libseccomp.found())
|
|
pkgconfig_libs += libseccomp
|
|
liblxc_dependencies += libseccomp
|
|
if libseccomp.found()
|
|
if libseccomp.version().version_compare('>=2.5.0')
|
|
# https://github.com/seccomp/libseccomp/commit/dead12bc788b259b148cc4d93b970ef0bd602b1a
|
|
srcconf.set10('HAVE_DECL_SECCOMP_NOTIFY_FD', true)
|
|
else
|
|
srcconf.set10('HAVE_DECL_SECCOMP_NOTIFY_FD', false)
|
|
endif
|
|
|
|
if libseccomp.version().version_compare('>=2.0.0')
|
|
# https://github.com/seccomp/libseccomp/commit/6220c8c0fc479d97b6d3e3166a4e46fbfe25a3c0
|
|
srcconf.set10('HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH', true)
|
|
else
|
|
srcconf.set10('HAVE_DECL_SECCOMP_SYSCALL_RESOLVE_NAME_ARCH', false)
|
|
endif
|
|
|
|
seccomp_headers = '''
|
|
#include <seccomp.h>
|
|
'''
|
|
|
|
foreach decl: [
|
|
'scmp_filter_ctx',
|
|
'struct seccomp_notif_sizes',
|
|
'struct clone_args',
|
|
]
|
|
|
|
# We get -1 if the size cannot be determined
|
|
if cc.sizeof(decl, prefix: seccomp_headers, args: '-D_GNU_SOURCE', dependencies: libseccomp) > 0
|
|
srcconf.set10('HAVE_' + decl.underscorify().to_upper(), true)
|
|
else
|
|
srcconf.set10('HAVE_' + decl.underscorify().to_upper(), false)
|
|
endif
|
|
endforeach
|
|
endif
|
|
else
|
|
srcconf.set10('HAVE_SECCOMP', false)
|
|
endif
|
|
|
|
## SELinux.
|
|
if want_selinux
|
|
libselinux = dependency('libselinux', required: false)
|
|
srcconf.set10('HAVE_SELINUX', libselinux.found())
|
|
pkgconfig_libs += libselinux
|
|
liblxc_dependencies += libselinux
|
|
else
|
|
srcconf.set10('HAVE_SELINUX', false)
|
|
endif
|
|
|
|
## AppArmor.
|
|
if want_apparmor
|
|
libapparmor = dependency('libapparmor', required: false)
|
|
srcconf.set10('HAVE_APPARMOR', libapparmor.found())
|
|
# We do not use the AppArmor library at runtime, so it's not in our pkg-config.
|
|
liblxc_dependencies += libapparmor
|
|
else
|
|
srcconf.set10('HAVE_APPARMOR', false)
|
|
endif
|
|
|
|
## OpenSSL.
|
|
if want_openssl
|
|
libopenssl = dependency('openssl', required: false)
|
|
srcconf.set10('HAVE_OPENSSL', libopenssl.found())
|
|
pkgconfig_libs += libopenssl
|
|
liblxc_dependencies += libopenssl
|
|
else
|
|
srcconf.set10('HAVE_OPENSSL', false)
|
|
endif
|
|
|
|
## Libcap..
|
|
if want_capabilities
|
|
libcap = dependency('libcap', required: false)
|
|
if not libcap.found()
|
|
# Compat with Ubuntu 14.04 which ships libcap w/o .pc file
|
|
libcap = cc.find_library('cap', required: false)
|
|
else
|
|
have = cc.has_function('cap_get_file', dependencies: libcap, prefix: '#include <sys/capability.h>')
|
|
srcconf.set10('LIBCAP_SUPPORTS_FILE_CAPABILITIES', have)
|
|
endif
|
|
srcconf.set10('HAVE_LIBCAP', libcap.found())
|
|
pkgconfig_libs += libcap
|
|
liblxc_dependencies += libcap
|
|
|
|
libcap_static = dependency('libcap', required: false, static: true)
|
|
if not libcap_static.found()
|
|
# Compat with Ubuntu 14.04 which ships libcap w/o .pc file
|
|
libcap_static = cc.find_library('cap', required: false, static: true)
|
|
endif
|
|
|
|
code = '''
|
|
int main(int argc, char *argv[]) { return 0; };
|
|
'''
|
|
if libcap_static.found()
|
|
libcap_static_linkable = cc.links(code, args: '-static', dependencies: libcap_static)
|
|
else
|
|
libcap_static_linkable = false
|
|
endif
|
|
srcconf.set10('HAVE_STATIC_LIBCAP', libcap_static_linkable)
|
|
else
|
|
libcap_static = []
|
|
libcap_static_linkable = false
|
|
srcconf.set10('HAVE_LIBCAP', false)
|
|
srcconf.set10('HAVE_STATIC_LIBCAP', false)
|
|
endif
|
|
|
|
libutil = cc.find_library('util', required: false)
|
|
|
|
if want_oss_fuzz
|
|
srcconf.set10('FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION', true)
|
|
srcconf.set10('RUN_ON_OSS_FUZZ', true)
|
|
fuzzing_engine = meson.get_compiler('cpp').find_library('FuzzingEngine')
|
|
endif
|
|
|
|
srcconf.set10('ENFORCE_THREAD_SAFETY', want_thread_safety)
|
|
srcconf.set10('ENFORCE_MEMFD_REXEC', want_memfd_rexec)
|
|
|
|
## PAM.
|
|
pam = cc.find_library('pam', has_headers: 'security/pam_modules.h', required: want_pam_cgroup)
|
|
srcconf.set10('HAVE_PAM', pam.found())
|
|
pkgconfig_libs += pam
|
|
|
|
## Others.
|
|
have = cc.has_function('fmemopen', prefix: '#include <stdio.h>', args: '-D_GNU_SOURCE')
|
|
srcconf.set10('HAVE_FMEMOPEN', have)
|
|
|
|
have = cc.has_function('openpty', dependencies: libutil, prefix: '#include <pty.h>')
|
|
srcconf.set10('HAVE_OPENPTY', have)
|
|
if have
|
|
liblxc_dependencies += libutil
|
|
if want_oss_fuzz
|
|
oss_fuzz_dependencies += libutil
|
|
endif
|
|
endif
|
|
|
|
have = cc.has_function('pthread_setcancelstate', prefix: '#include <pthread.h>')
|
|
srcconf.set10('HAVE_PTHREAD_SETCANCELSTATE', have)
|
|
|
|
have = cc.has_function('rand_r')
|
|
srcconf.set10('HAVE_RAND_R', have)
|
|
|
|
have = cc.has_function('strchrnul', prefix: '#include <string.h>', args: '-D_GNU_SOURCE')
|
|
srcconf.set10('HAVE_STRCHRNUL', have)
|
|
|
|
have_func_strerror_r = cc.has_function('strerror_r', prefix: '#include <string.h>', args: '-D_GNU_SOURCE')
|
|
srcconf.set10('HAVE_STRERROR_R', have_func_strerror_r)
|
|
|
|
have_func_strerror_r_char_p = false
|
|
|
|
if have_func_strerror_r
|
|
code = '''
|
|
#define _GNU_SOURCE
|
|
#include <string.h>
|
|
int func (void) {
|
|
char error_string[256];
|
|
char *ptr = strerror_r (-2, error_string, 256);
|
|
char c = *strerror_r (-2, error_string, 256);
|
|
return c != 0 && ptr != (void*) 0L;
|
|
}
|
|
'''
|
|
|
|
have_func_strerror_r_char_p = cc.compiles(code, name : 'strerror_r() returns char *')
|
|
endif
|
|
|
|
srcconf.set10('STRERROR_R_CHAR_P', have_func_strerror_r_char_p)
|
|
|
|
## Compiler attributes.
|
|
foreach ccattr: [
|
|
'fallthrough',
|
|
'nonnull',
|
|
'returns_nonnull',
|
|
]
|
|
|
|
srcconf.set10('HAVE_COMPILER_ATTR_' + ccattr.underscorify().to_upper(), cc.has_function_attribute(ccattr))
|
|
endforeach
|
|
|
|
## Syscalls.
|
|
found_syscalls = []
|
|
missing_syscalls = []
|
|
foreach tuple: [
|
|
['bpf'],
|
|
['close_range'],
|
|
['endmntent'],
|
|
['execveat'],
|
|
['faccessat'],
|
|
['strchrnul'],
|
|
['strerror_r'],
|
|
['fgetln'],
|
|
['fsconfig'],
|
|
['fsmount'],
|
|
['fsopen'],
|
|
['fspick'],
|
|
['getgrgid_r'],
|
|
['getline'],
|
|
['getsubopt'],
|
|
['gettid'],
|
|
['hasmntopt'],
|
|
['kcmp'],
|
|
['keyctl'],
|
|
['memfd_create'],
|
|
['mount_setattr'],
|
|
['move_mount'],
|
|
['openat2'],
|
|
['open_tree'],
|
|
['personality'],
|
|
['pidfd_open'],
|
|
['pidfd_send_signal'],
|
|
['pivot_root'],
|
|
['prlimit'],
|
|
['prlimit64'],
|
|
['renameat2'],
|
|
['sethostname'],
|
|
['setmntent'],
|
|
['setns'],
|
|
['sigdescr_np'],
|
|
['signalfd'],
|
|
['statx'],
|
|
['statvfs'],
|
|
['strlcat'],
|
|
['strlcpy'],
|
|
['unshare'],
|
|
]
|
|
|
|
if tuple.length() >= 2
|
|
cond = tuple[1]
|
|
else
|
|
ident1 = 'HAVE_' + tuple[0].underscorify().to_upper()
|
|
ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper()
|
|
cond = srcconf.get(ident1, 0) == 1 or srcconf.get(ident2, 0) == 1
|
|
endif
|
|
|
|
if cond
|
|
found_syscalls += tuple[0]
|
|
else
|
|
missing_syscalls += tuple[0]
|
|
endif
|
|
endforeach
|
|
|
|
## Types.
|
|
decl_headers = '''
|
|
#include <uchar.h>
|
|
#include <sys/mount.h>
|
|
#include <sys/stat.h>
|
|
#include <linux/if_link.h>
|
|
#include <linux/types.h>
|
|
'''
|
|
|
|
foreach decl: [
|
|
'__aligned_u64',
|
|
'struct clone_args',
|
|
'struct open_how',
|
|
'struct rtnl_link_stats64',
|
|
]
|
|
|
|
# We get -1 if the size cannot be determined
|
|
if cc.sizeof(decl, prefix: decl_headers, args: '-D_GNU_SOURCE') > 0
|
|
srcconf.set10('HAVE_' + decl.underscorify().to_upper(), true)
|
|
else
|
|
srcconf.set10('HAVE_' + decl.underscorify().to_upper(), false)
|
|
endif
|
|
endforeach
|
|
|
|
found_types = []
|
|
missing_types = []
|
|
foreach tuple: [
|
|
['scmp_filter_ctx'],
|
|
['struct seccomp_notif_sizes'],
|
|
['struct clone_args'],
|
|
['__aligned_u64'],
|
|
['struct open_how'],
|
|
['struct rtnl_link_stats64'],
|
|
]
|
|
|
|
if tuple.length() >= 2
|
|
cond = tuple[1]
|
|
else
|
|
ident1 = 'HAVE_' + tuple[0].underscorify().to_upper()
|
|
ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper()
|
|
cond = srcconf.get(ident1, 0) == 1 or srcconf.get(ident2, 0) == 1
|
|
endif
|
|
|
|
if cond
|
|
found_types += tuple[0]
|
|
else
|
|
missing_types += tuple[0]
|
|
endif
|
|
endforeach
|
|
|
|
decl_headers = '''
|
|
#include <sys/mount.h>
|
|
'''
|
|
|
|
# We get -1 if the size cannot be determined
|
|
if cc.sizeof('struct mount_attr', prefix: decl_headers, args: '-D_GNU_SOURCE') > 0
|
|
srcconf.set10('HAVE_' + 'struct mount_attr'.underscorify().to_upper(), true)
|
|
found_types += 'struct mount_attr (sys/mount.h)'
|
|
else
|
|
srcconf.set10('HAVE_' + 'struct mount_attr'.underscorify().to_upper(), false)
|
|
missing_types += 'struct mount_attr (sys/mount.h)' endif
|
|
|
|
## Check if sys/mount.h defines the fsconfig commands
|
|
if cc.get_define('FSCONFIG_SET_FLAG', prefix: decl_headers) != ''
|
|
srcconf.set10('HAVE_' + 'FSCONFIG_SET_FLAG'.underscorify().to_upper(), true)
|
|
found_types += 'FSCONFIG_SET_FLAG (sys/mount.h)'
|
|
else
|
|
srcconf.set10('HAVE_' + 'FSCONFIG_SET_FLAG'.underscorify().to_upper(), false)
|
|
missing_types += 'FSCONFIG_SET_FLAG (sys/mount.h)'
|
|
endif
|
|
|
|
if cc.get_define('FS_CONFIG_SET_STRING', prefix: decl_headers) != ''
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_STRING'.underscorify().to_upper(), true)
|
|
found_types += 'FS_CONFIG_SET_STRING (sys/mount.h)'
|
|
else
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_STRING'.underscorify().to_upper(), false)
|
|
missing_types += 'FS_CONFIG_SET_STRING (sys/mount.h)'
|
|
endif
|
|
|
|
if cc.get_define('FS_CONFIG_SET_BINARY', prefix: decl_headers) != ''
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_BINARY'.underscorify().to_upper(), true)
|
|
found_types += 'FS_CONFIG_SET_BINARY (sys/mount.h)'
|
|
else
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_BINARY'.underscorify().to_upper(), false)
|
|
missing_types += 'FS_CONFIG_SET_BINARY (sys/mount.h)'
|
|
endif
|
|
|
|
if cc.get_define('FS_CONFIG_SET_PATH_EMPTY', prefix: decl_headers) != ''
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_PATH_EMPTY'.underscorify().to_upper(), true)
|
|
found_types += 'FS_CONFIG_SET_PATH_EMPTY (sys/mount.h)'
|
|
else
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_PATH_EMPTY'.underscorify().to_upper(), false)
|
|
missing_types += 'FS_CONFIG_SET_PATH_EMPTY (sys/mount.h)'
|
|
endif
|
|
|
|
if cc.get_define('FS_CONFIG_SET_PATH_FD', prefix: decl_headers) != ''
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_PATH_FD'.underscorify().to_upper(), true)
|
|
found_types += 'FS_CONFIG_SET_PATH_FD (sys/mount.h)'
|
|
else
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_PATH_FD'.underscorify().to_upper(), false)
|
|
missing_types += 'FS_CONFIG_SET_PATH_FD (sys/mount.h)'
|
|
endif
|
|
|
|
if cc.get_define('FS_CONFIG_SET_CMD_CREATE', prefix: decl_headers) != ''
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_CMD_CREATE'.underscorify().to_upper(), true)
|
|
found_types += 'FS_CONFIG_SET_CMD_CREAT (sys/mount.h)'
|
|
else
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_CMD_CREATE'.underscorify().to_upper(), false)
|
|
missing_types += 'FS_CONFIG_SET_CMD_CREATE (sys/mount.h)'
|
|
endif
|
|
|
|
if cc.get_define('FS_CONFIG_SET_CMD_RECONFIGURE', prefix: decl_headers) != ''
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_CMD_RECONFIGURE'.underscorify().to_upper(), true)
|
|
found_types += 'FS_CONFIG_SET_CMD_RECONFIGURE (sys/mount.h)'
|
|
else
|
|
srcconf.set10('HAVE_' + 'FS_CONFIG_SET_CMD_RECONFIGURE'.underscorify().to_upper(), false)
|
|
missing_types += 'FS_CONFIG_SET_CMD_RECONFIGURE (sys/mount.h)'
|
|
endif
|
|
|
|
## Headers.
|
|
foreach ident: [
|
|
['bpf', '''#include <sys/syscall.h>
|
|
#include <unistd.h>'''],
|
|
['close_range', '''#include <unistd.h>'''],
|
|
['execveat', '''#include <unistd.h>'''],
|
|
['endmntent', '''#include <stdio.h>
|
|
#include <mntent.h>'''],
|
|
['faccessat', '''#include <fcntl.h>
|
|
#include <unistd.h>'''],
|
|
['fexecve', '''#include <unistd.h>'''],
|
|
['fgetln', '''#include <stdio.h>'''],
|
|
['fsconfig', '''#include <sys/mount.h>'''],
|
|
['fsmount', '''#include <sys/mount.h>'''],
|
|
['fsopen', '''#include <sys/mount.h>'''],
|
|
['fspick', '''#include <sys/mount.h>'''],
|
|
['getgrgid_r', '''#include <sys/types.h>
|
|
#include <grp.h>'''],
|
|
['getline', '''#include <stdio.h>'''],
|
|
['getsubopt', '''#include <stdlib.h>'''],
|
|
['gettid', '''#include <sys/types.h>
|
|
#include <unistd.h>'''],
|
|
['hasmntopt', '''#include <stdio.h>
|
|
#include <mntent.h>'''],
|
|
['kcmp', '''#include <linux/kcmp.h>'''],
|
|
['keyctl', '''#include <sys/types.h>
|
|
#include <keyutils.h>'''],
|
|
['memfd_create', '''#include <sys/mman.h>'''],
|
|
['mount_setattr', '''#include <sys/mount.h>'''],
|
|
['move_mount', '''#include <sys/mount.h>'''],
|
|
['openat2', '''#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fctnl.h>'''],
|
|
['open_tree', '''#include <sys/mount.h>'''],
|
|
['personality', '''#include <sys/personality.h>'''],
|
|
['pidfd_open', '''#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <sys/wait.h>'''],
|
|
['pidfd_send_signal', '''#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <signal.h>
|
|
#include <sys/wait.h>'''],
|
|
['pivot_root', '''#include <stdlib.h>
|
|
#include <unistd.h>'''], # no known header declares pivot_root
|
|
['prlimit', '''#include <sys/time.h>
|
|
#include <sys/resource.h>'''],
|
|
['prlimit64', '''#include <sys/time.h>
|
|
#include <sys/resource.h>'''],
|
|
['renameat2', '''#include <stdio.h>
|
|
#include <fcntl.h>'''],
|
|
['sethostname', '''#include <unistd.h>'''],
|
|
['setmntent', '''#include <stdio.h>
|
|
#include <mntent.h>'''],
|
|
['setns', '''#include <sched.h>'''],
|
|
['sigdescr_np', '''#include <string.h>'''],
|
|
['signalfd', '''#include <sys/signalfd.h>'''],
|
|
['statvfs', '''#include <sys/statvfs.h>'''],
|
|
['statx', '''#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>'''],
|
|
['strchrnul', '''#include <string.h>'''],
|
|
['strlcat', '''#include <string.h>'''],
|
|
['strlcpy', '''#include <string.h>'''],
|
|
['unshare', '''#include <sched.h>'''],
|
|
]
|
|
|
|
have = cc.has_function(ident[0], prefix: ident[1], args: '-D_GNU_SOURCE')
|
|
srcconf.set10('HAVE_' + ident[0].to_upper(), have)
|
|
endforeach
|
|
|
|
found_headers = []
|
|
missing_headers = []
|
|
foreach tuple: [
|
|
['sys/resource.h'],
|
|
['sys/memfd.h'],
|
|
['sys/personality.h'],
|
|
['sys/pidfd.h'],
|
|
['sys/signalfd.h'],
|
|
['sys/timerfd.h'],
|
|
['pty.h'],
|
|
['utmpx.h'],
|
|
]
|
|
srcconf.set10('HAVE_' + tuple[0].underscorify().to_upper(), cc.has_header(tuple[0]))
|
|
|
|
if tuple.length() >= 2
|
|
cond = tuple[1]
|
|
else
|
|
ident1 = 'HAVE_' + tuple[0].underscorify().to_upper()
|
|
ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper()
|
|
cond = srcconf.get(ident1, 0) == 1 or srcconf.get(ident2, 0) == 1
|
|
endif
|
|
|
|
if cond
|
|
found_headers += tuple[0]
|
|
else
|
|
missing_headers += tuple[0]
|
|
endif
|
|
endforeach
|
|
|
|
## Deps.
|
|
found_deps = []
|
|
missing_deps = []
|
|
foreach tuple: [
|
|
['AppArmor'],
|
|
['SECCOMP'],
|
|
['SELinux'],
|
|
['libcap'],
|
|
['static libcap'],
|
|
['pam'],
|
|
['openssl'],
|
|
['liburing'],
|
|
]
|
|
|
|
if tuple.length() >= 2
|
|
cond = tuple[1]
|
|
else
|
|
ident1 = 'HAVE_' + tuple[0].underscorify().to_upper()
|
|
ident2 = 'ENABLE_' + tuple[0].underscorify().to_upper()
|
|
cond = srcconf.get(ident1, 0) == 1 or srcconf.get(ident2, 0) == 1
|
|
endif
|
|
|
|
if cond
|
|
found_deps += tuple[0]
|
|
else
|
|
missing_deps += tuple[0]
|
|
endif
|
|
endforeach
|
|
|
|
# Generate config.h
|
|
config_h = configure_file(
|
|
output: 'config.h',
|
|
configuration: srcconf)
|
|
|
|
add_project_arguments('-include', 'config.h', language: 'c')
|
|
|
|
# Binaries.
|
|
cmd_programs = []
|
|
hook_programs = []
|
|
public_programs = []
|
|
template_scripts = []
|
|
test_programs = []
|
|
|
|
# Includes.
|
|
liblxc_includes = include_directories(
|
|
'.',
|
|
'src',
|
|
'src/include',
|
|
'src/lxc',
|
|
'src/lxc/cgroups',
|
|
'src/lxc/storage')
|
|
|
|
# Our static sub-project binaries don't (and in fact can't) link to our
|
|
# dependencies directly, but need access to the headers when compiling (most
|
|
# notably seccomp headers).
|
|
liblxc_dependency_headers = []
|
|
foreach dep: liblxc_dependencies
|
|
liblxc_dependency_headers += dep.partial_dependency(compile_args: true)
|
|
endforeach
|
|
|
|
# Early sub-directories.
|
|
subdir('src/include')
|
|
subdir('src/lxc')
|
|
subdir('src/lxc/pam')
|
|
|
|
liblxc_link_whole = [liblxc_static]
|
|
|
|
liblxc = shared_library(
|
|
'lxc',
|
|
version: liblxc_version,
|
|
include_directories: liblxc_includes,
|
|
link_args: ['-DPIC'],
|
|
c_args: ['-DPIC'],
|
|
link_whole: liblxc_link_whole,
|
|
dependencies: liblxc_dependencies,
|
|
install: true)
|
|
|
|
liblxc_dep = declare_dependency(
|
|
link_with: liblxc,
|
|
dependencies: liblxc_dependencies)
|
|
|
|
# Rest of sub-directories.
|
|
if want_apparmor
|
|
subdir('config/apparmor')
|
|
subdir('config/apparmor/abstractions')
|
|
subdir('config/apparmor/profiles')
|
|
endif
|
|
subdir('config/bash')
|
|
subdir('config/etc')
|
|
subdir('config/init/common')
|
|
subdir('config/init/systemd')
|
|
subdir('config/init/sysvinit')
|
|
subdir('config/init/upstart')
|
|
if want_selinux
|
|
subdir('config/selinux')
|
|
endif
|
|
subdir('config/sysconfig')
|
|
subdir('config/templates')
|
|
subdir('config/templates/common.conf.d')
|
|
subdir('config/yum')
|
|
subdir('doc')
|
|
subdir('doc/ja')
|
|
subdir('doc/ko')
|
|
subdir('doc/examples')
|
|
subdir('doc/rootfs')
|
|
subdir('hooks')
|
|
if want_commands
|
|
subdir('src/lxc/cmd')
|
|
endif
|
|
if want_tools or want_tools_multicall
|
|
subdir('src/lxc/tools')
|
|
endif
|
|
subdir('src/lxc/tools/include')
|
|
subdir('src/tests')
|
|
subdir('templates')
|
|
|
|
# Pkg-config.
|
|
pkg_config_file = pkgconfig.generate(liblxc,
|
|
description: 'linux container tools',
|
|
version: version_data.get('LXC_VERSION'),
|
|
url: 'http://linuxcontainers.org',
|
|
libraries: '-lutil -lpthread -ldl',
|
|
libraries_private: pkgconfig_libs,
|
|
)
|
|
|
|
# Empty dirs.
|
|
install_emptydir(join_paths(localstatedir, 'cache', 'lxc'))
|
|
install_emptydir(join_paths(localstatedir, 'lib', 'lxc'))
|
|
|
|
# RPM spec file.
|
|
specconf = configuration_data()
|
|
specconf.set('LXC_VERSION_BASE', meson.project_version())
|
|
specconf.set('LXC_VERSION_BETA', version_data.get('LXC_VERSION_BETA'))
|
|
specconf.set('PACKAGE', meson.project_name())
|
|
specconf.set('LXC_DISTRO_SYSCONF', conf.get('LXC_DISTRO_SYSCONF'))
|
|
|
|
configure_file(
|
|
configuration: specconf,
|
|
input: 'lxc.spec.in',
|
|
output: 'lxc.spec',
|
|
install: false)
|
|
|
|
# Build overview.
|
|
status = [
|
|
'@0@ @1@'.format(meson.project_name(), meson.project_version()),
|
|
|
|
'Meson version: @0@'.format(meson.version()),
|
|
|
|
'prefix directory: @0@'.format(prefixdir),
|
|
'bin directory: @0@'.format(bindir),
|
|
'data directory: @0@'.format(datadir),
|
|
'doc directory: @0@'.format(docdir),
|
|
'include directory: @0@'.format(includedir),
|
|
'lib directory: @0@'.format(libdir),
|
|
'libexec directory: @0@'.format(libexecdir),
|
|
'local state directory: @0@'.format(localstatedir),
|
|
'sbin directory: @0@'.format(sbindir),
|
|
'sysconf directory: @0@'.format(sysconfdir),
|
|
|
|
'lxc cgroup pattern: @0@'.format(cgrouppattern),
|
|
'lxc init directory: @0@'.format(libexecdir),
|
|
'runtime path: @0@'.format(runtimepath),
|
|
|
|
'lxc default config: @0@'.format(lxcdefaultconfig),
|
|
'lxc global config: @0@'.format(lxcglobalconfig),
|
|
'lxc hook directory: @0@'.format(lxchookdir),
|
|
'lxc hook bin directory: @0@'.format(lxchookbindir),
|
|
'lxc rootfs mount directory: @0@'.format(lxcrootfsmount),
|
|
'log path: @0@'.format(lxclogpath),
|
|
'lxc path: @0@'.format(lxcpath),
|
|
'lxc template config: @0@'.format(lxctemplateconfdir),
|
|
'lxc template directory: @0@'.format(lxctemplatedir),
|
|
'lxc user network config: @0@'.format(lxc_user_network_conf),
|
|
'lxc user network database: @0@'.format(lxc_user_network_db)]
|
|
|
|
alt_time_epoch = run_command('date', '-Is', '-u', '-d',
|
|
'@@0@'.format(time_epoch), check: true).stdout().strip()
|
|
status += [
|
|
'time epoch: @0@ (@1@)'.format(time_epoch, alt_time_epoch)]
|
|
|
|
status += [
|
|
'',
|
|
'supported dependencies: @0@'.format(', '.join(found_deps)),
|
|
'',
|
|
'unsupported dependencies: @0@'.format(', '.join(missing_deps)),
|
|
'']
|
|
|
|
status += [
|
|
'',
|
|
'supported headers: @0@'.format(', '.join(found_headers)),
|
|
'',
|
|
'unsupported headers: @0@'.format(', '.join(missing_headers)),
|
|
'']
|
|
|
|
status += [
|
|
'',
|
|
'supported calls: @0@'.format(', '.join(found_syscalls)),
|
|
'',
|
|
'unsupported calls: @0@'.format(', '.join(missing_syscalls)),
|
|
'']
|
|
|
|
status += [
|
|
'',
|
|
'supported types: @0@'.format(', '.join(found_types)),
|
|
'',
|
|
'unsupported types: @0@'.format(', '.join(missing_types)),
|
|
'']
|
|
|
|
message('\n '.join(status))
|