Files
flatpak/meson.build
2025-12-15 19:36:46 +01:00

534 lines
15 KiB
Meson

# Copyright 2022 Collabora Ltd.
# SPDX-License-Identifier: LGPL-2.1-or-later
project(
'flatpak',
'c',
version : '1.17.3',
default_options: [
'warning_level=2',
],
meson_version : '>=0.53.0',
)
flatpak_major_version = 1
flatpak_minor_version = 17
flatpak_micro_version = 3
flatpak_extra_version = ''
flatpak_interface_age = 0
flatpak_binary_age = (
10000 * flatpak_major_version
+ 100 * flatpak_minor_version
+ flatpak_micro_version
)
if '@0@.@1@.@2@@3@'.format(
flatpak_major_version,
flatpak_minor_version,
flatpak_micro_version,
flatpak_extra_version,
) != meson.project_version()
error('Project version does not match parts')
endif
required_glib = '2.46'
# Before increasing this, update subprojects/bubblewrap.wrap
required_bwrap = '0.10.0'
# Before increasing this, update subprojects/dbus-proxy.wrap
required_dbus_proxy = '0.1.0'
required_libostree = '2020.8'
fs = import('fs')
gnome = import('gnome')
i18n = import('i18n')
pkgconfig = import('pkgconfig')
# TODO: We can replace these with meson.project_foo_root()
# when we depend on meson 0.56
project_build_root = meson.current_build_dir()
project_source_root = meson.current_source_dir()
if meson.version().version_compare('>=0.58')
global_source_root = meson.global_source_root()
else
global_source_root = meson.source_root()
endif
if meson.version().version_compare('>=0.55.0')
can_run_host_binaries = meson.can_run_host_binaries()
else
can_run_host_binaries = meson.has_exe_wrapper() or not meson.is_cross_build()
endif
cc = meson.get_compiler('c')
add_project_arguments('-include', 'config.h', language : 'c')
common_include_directories = include_directories(
'.',
'common',
)
# 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',
# Meson warning_level=2 would do this, but we are not fully
# signedness-safe yet
'-Wno-sign-compare',
'-Wno-error=sign-compare',
# Meson warning_level=2 would do this
'-Wno-cast-function-type',
'-Wno-error=cast-function-type',
# Deliberately not warning about these, ability to zero-initialize
# a struct is a feature
'-Wno-missing-field-initializers',
'-Wno-error=missing-field-initializers',
# Deliberately not warning about these
'-Wno-unused-parameter',
'-Wno-error=unused-parameter',
]),
language : 'c',
)
# Flatpak is Linux-specific, so for now we assume that -fvisibility=hidden
# is always supported
add_project_arguments('-fvisibility=hidden', 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
dbus_config_dir = get_option('dbus_config_dir')
if dbus_config_dir == ''
dbus_config_dir = get_option('datadir') / 'dbus-1' / 'system.d'
endif
dbus_service_dir = get_option('dbus_service_dir')
if dbus_service_dir == ''
dbus_service_dir = get_option('datadir') / 'dbus-1' / 'services'
endif
profile_dir = get_option('profile_dir')
if profile_dir == ''
profile_dir = get_option('sysconfdir') / 'profile.d'
endif
system_install_dir = get_option('system_install_dir')
if system_install_dir == ''
system_install_dir = get_option('localstatedir') / 'lib' / 'flatpak'
endif
docdir = get_option('docdir')
if docdir == ''
docdir = get_option('datadir') / 'doc' / 'flatpak'
endif
if not cc.check_header('sys/xattr.h')
error('You must have sys/xattr.h from glibc')
endif
libglnx = subproject(
'libglnx',
default_options : [
'warning_level=1',
'tests=false',
],
)
not_found = dependency('', required : false)
threads_dep = dependency('threads')
bison = find_program('bison')
libcap_dep = dependency('libcap')
libglnx_dep = libglnx.get_variable('libglnx_dep')
libglnx_testlib_dep = libglnx.get_variable('libglnx_testlib_dep')
libarchive_dep = dependency('libarchive', version : '>=2.8.0')
glib_dep = dependency('glib-2.0', version : '>=' + required_glib)
gio_dep = dependency('gio-2.0', version : '>=' + required_glib)
gio_unix_dep = dependency('gio-unix-2.0', version : '>=' + required_glib)
libcurl_dep = dependency('libcurl', version : '>=7.29.0')
libxml_dep = dependency('libxml-2.0', version : '>=2.4')
libzstd_dep = dependency('libzstd', version : '>=0.8.1', required : get_option('libzstd'))
dconf_dep = dependency('dconf', version : '>=0.26', required : get_option('dconf'))
libsystemd_dep = dependency('libsystemd', required : get_option('systemd'))
malcontent_dep = dependency('malcontent-0', version : '>=0.5.0', required : get_option('malcontent'))
polkit_agent_dep = dependency('polkit-agent-1', version : '>=0.98', required : get_option('system_helper'))
build_system_helper = polkit_agent_dep.found()
fuse_dep = dependency('fuse3', version : '>=3.1.1', required : false)
if fuse_dep.found()
fuse_api = 31
else
fuse_dep = dependency('fuse', version : '>=2.9.2')
fuse_api = 26
endif
fusermount = get_option('system_fusermount')
if fusermount == ''
if fuse_api >= 30
fusermount_program = find_program('fusermount3', required: true)
else
fusermount_program = find_program('fusermount', required: true)
endif
if meson.version().version_compare('>=0.55')
fusermount = fusermount_program.full_path()
else
fusermount = fusermount_program.path()
endif
endif
xau_dep = dependency('xau', required : get_option('xauth'))
libostree_dep = dependency('ostree-1', version : '>=' + required_libostree)
json_glib_dep = dependency('json-glib-1.0')
appstream_dep = dependency('appstream', version : '>=0.12.0')
gdk_pixbuf_dep = dependency('gdk-pixbuf-2.0')
libseccomp_dep = dependency('libseccomp', required : get_option('seccomp'))
gir_dep = dependency('gobject-introspection-1.0', version : '>=1.40.0', required : get_option('gir'))
gtkdoc_dep = dependency('gtk-doc', required : get_option('gtkdoc'), native : true)
build_gtk_doc = gtkdoc_dep.found()
wayland_client = dependency('wayland-client', required : get_option('wayland_security_context'))
wayland_scanner = dependency('wayland-scanner', version : '>= 1.15', required : get_option('wayland_security_context'), native : true)
wayland_protocols = dependency('wayland-protocols', version : '>= 1.32', required : get_option('wayland_security_context'))
build_wayland_security_context = wayland_client.found() and wayland_scanner.found() and wayland_protocols.found()
base_deps = [glib_dep, gio_dep, gio_unix_dep]
gpgme_dep = dependency('gpgme', version : '>=1.8.0')
if get_option('selinux_module').disabled()
build_selinux_module = false
else
build_selinux_module = fs.is_file('/usr/share/selinux/devel/Makefile')
if get_option('selinux_module').enabled() and not build_selinux_module
error('selinux-policy-devel needed to build selinux module')
endif
endif
manpages_xsl = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
xsltproc = find_program('xsltproc', required : get_option('man'))
build_man_pages = false
if xsltproc.found()
if run_command([
xsltproc, '--nonet', manpages_xsl,
], check : false).returncode() == 0
message('Docbook XSL found')
build_man_pages = true
elif get_option('man').enabled()
error('Man page requested, but Docbook XSL stylesheets not found')
else
message('Docbook XSL not found, man page disabled automatically')
endif
endif
xmlto = find_program('xmlto', required : get_option('docbook_docs'))
if run_command(
'python3', '-c', 'import pyparsing',
check : false
).returncode() != 0
error('python3 "pyparsing" module is required')
endif
foreach system_executable : [
['bubblewrap', required_bwrap, 'system_bubblewrap'],
['xdg-dbus-proxy', required_dbus_proxy, 'system_dbus_proxy'],
]
name = system_executable[0]
required = system_executable[1]
option_name = system_executable[2]
value = get_option(option_name)
if value != ''
version = ''
if can_run_host_binaries
result = run_command(
value, '--version',
capture : true,
check : true,
)
output = result.stdout()
if output.startswith(name + ' ')
version = output.split()[1]
endif
endif
if version == ''
# Cross-compiling, or unable to parse --version output
warning(
'Unable to determine version of @0@ (@1@), please ensure it is >= @2@'.format(
name, value, required,
)
)
elif version.version_compare('<' + required)
error(
'@0@ must be version >= @1@ (found: @2@)'.format(
option_name, required, version,
)
)
endif
endif
endforeach
# We don't actually need this, but we do need the polkit daemon itself,
# and they're generally packaged together.
find_program('pkcheck', required : get_option('tests'))
find_program('socat', required : get_option('tests'))
if get_option('installed_tests') and not get_option('tests')
error('-Dinstalled_tests=true is incompatible with -Dtests=false')
endif
cdata = configuration_data()
cdata.set('_GNU_SOURCE', 1)
cdata.set('FLATPAK_COMPILATION', 1)
cdata.set('PACKAGE_MAJOR_VERSION', flatpak_major_version)
cdata.set('PACKAGE_MINOR_VERSION', flatpak_minor_version)
cdata.set('PACKAGE_MICRO_VERSION', flatpak_micro_version)
cdata.set('PACKAGE_EXTRA_VERSION', flatpak_extra_version)
cdata.set_quoted(
'PACKAGE_STRING',
'Flatpak @0@'.format(meson.project_version()),
)
cdata.set_quoted('PACKAGE_VERSION', meson.project_version())
cdata.set_quoted(
'FLATPAK_BINDIR',
get_option('prefix') / get_option('bindir'),
)
cdata.set_quoted(
'FLATPAK_SYSTEMDIR',
get_option('prefix') / system_install_dir,
)
cdata.set_quoted(
'FLATPAK_CONFIGDIR',
get_option('prefix') / get_option('sysconfdir') / 'flatpak',
)
cdata.set_quoted(
'FLATPAK_DATADIR',
get_option('prefix') / get_option('datadir') / 'flatpak',
)
cdata.set_quoted('LIBEXECDIR', get_option('prefix') / get_option('libexecdir'))
cdata.set_quoted('DATADIR', get_option('prefix') / get_option('datadir'))
cdata.set_quoted('LOCALEDIR', get_option('prefix') / get_option('localedir'))
cdata.set_quoted('SYSTEM_FONTS_DIR', get_option('system_fonts_dir'))
cdata.set_quoted('SYSTEM_HELPER_USER', get_option('system_helper_user'))
cdata.set_quoted(
'SYSTEM_FONT_CACHE_DIRS',
':'.join(get_option('system_font_cache_dirs')),
)
cdata.set_quoted('G_LOG_DOMAIN', 'flatpak')
cdata.set_quoted('GETTEXT_PACKAGE', 'flatpak')
cdata.set('FUSE_USE_VERSION', fuse_api)
cdata.set_quoted('FUSERMOUNT', fusermount)
if get_option('internal_tests')
cdata.set('INCLUDE_INTERNAL_TESTS', 1)
endif
if get_option('system_bubblewrap') == ''
cdata.set_quoted('HELPER', get_option('prefix') / get_option('libexecdir') / 'flatpak-bwrap')
else
cdata.set_quoted('HELPER', get_option('system_bubblewrap'))
endif
if get_option('system_dbus_proxy') == ''
cdata.set_quoted('DBUSPROXY', get_option('prefix') / get_option('libexecdir') / 'flatpak-dbus-proxy')
else
cdata.set_quoted('DBUSPROXY', get_option('system_dbus_proxy'))
endif
# Flatpak is Linux-specific, so we assume this is always supported
cdata.set('FLATPAK_EXTERN', '__attribute__((visibility("default"))) extern')
if glib_dep.version().version_compare('>=2.60')
# Ignore massive GTimeVal deprecation warnings in 2.62
cdata.set('GLIB_VERSION_MIN_REQUIRED', 'GLIB_VERSION_2_60')
endif
if dconf_dep.found()
cdata.set('HAVE_DCONF', 1)
endif
if libseccomp_dep.found()
cdata.set('ENABLE_SECCOMP', 1)
endif
if libsystemd_dep.found()
cdata.set('HAVE_LIBSYSTEMD', 1)
endif
if libzstd_dep.found()
cdata.set('HAVE_ZSTD', 1)
endif
if malcontent_dep.found()
cdata.set('HAVE_LIBMALCONTENT', 1)
endif
if xau_dep.found()
cdata.set('ENABLE_XAUTH', 1)
endif
if build_wayland_security_context
cdata.set('ENABLE_WAYLAND_SECURITY_CONTEXT', 1)
endif
if not get_option('sandboxed_triggers')
cdata.set('DISABLE_SANDBOXED_TRIGGERS', 1)
endif
if cc.has_function(
'archive_read_support_filter_all',
dependencies : libarchive_dep,
prefix : '#include <archive.h>',
)
cdata.set('HAVE_ARCHIVE_READ_SUPPORT_FILTER_ALL', 1)
endif
if build_system_helper
cdata.set('USE_SYSTEM_HELPER', '1')
endif
configure_file(
output : 'config.h',
configuration : cdata,
)
# TODO: When we depend on Meson >= 0.57.0, we can print dependencies
# as themselves rather than as booleans if we want to.
summary(
{
'Build system helper' : build_system_helper,
'Build selinux module' : build_selinux_module,
'Build bubblewrap' : (get_option('system_bubblewrap') == ''),
'Build dbus-proxy' : (get_option('system_dbus_proxy') == ''),
'fusermount executable' : fusermount,
'Use sandboxed triggers' : get_option('sandboxed_triggers'),
'Use seccomp' : libseccomp_dep.found(),
'Privileged group' : get_option('privileged_group'),
'Use dconf' : dconf_dep.found(),
'Use libsystemd' : libsystemd_dep.found(),
'Use libmalcontent' : malcontent_dep.found(),
'Use libzstd' : libzstd_dep.found(),
'Use auto sideloading' : get_option('auto_sideloading'),
'Wayland security context' : build_wayland_security_context,
},
bool_yn : true,
)
if get_option('system_bubblewrap') == ''
subproject(
'bubblewrap',
default_options : [
'program_prefix=flatpak-',
'tests=false',
],
)
endif
if get_option('system_dbus_proxy') == ''
subproject(
'dbus-proxy',
default_options : [
'warning_level=1',
'program_prefix=flatpak-',
'tests=false',
],
)
endif
# Used for .service files in multiple subdirectories
service_conf_data = configuration_data()
service_conf_data.set('libexecdir', get_option('prefix') / get_option('libexecdir'))
service_conf_data.set('localstatedir', get_option('prefix') / get_option('localstatedir'))
service_conf_data.set('media_dir', get_option('prefix') / get_option('run_media_dir'))
service_conf_data.set('extraargs', '')
subdir('common')
subdir('data')
subdir('app')
subdir('env.d')
subdir('profile')
subdir('icon-validator')
subdir('oci-authenticator')
subdir('portal')
subdir('revokefs')
subdir('session-helper')
subdir('scripts')
subdir('completion')
subdir('doc')
subdir('po')
subdir('triggers')
if get_option('auto_sideloading')
subdir('sideload-repos-systemd')
endif
if build_selinux_module
subdir('selinux')
endif
if build_system_helper
subdir('system-helper')
endif
if get_option('tests')
subdir('tests')
endif
pkgconfig_variables = []
# TODO: These can be dropped when we require Meson >= 0.62.0
pkgconfig_variables += 'exec_prefix=${prefix}'
pkgconfig_variables += 'datadir=' + ('${prefix}' / get_option('datadir'))
pkgconfig_variables += 'datarootdir=' + ('${prefix}' / get_option('datadir'))
pkgconfig_variables += 'interfaces_dir=${datadir}/dbus-1/interfaces/'
pkgconfig.generate(
libflatpak,
description : 'Application sandboxing framework',
subdirs : 'flatpak',
requires : [
'glib-2.0',
'gio-2.0',
'ostree-1',
],
requires_private : [
'gio-unix-2.0',
],
variables : pkgconfig_variables,
)