pipewire/meson.build

632 lines
23 KiB
Meson
Raw Normal View History

2019-01-08 12:18:45 +01:00
project('pipewire', ['c' ],
2025-03-11 15:14:03 +01:00
version : '1.5.0',
2021-05-14 12:09:33 +02:00
license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ],
meson_version : '>= 0.61.1',
2020-04-01 12:51:42 +02:00
default_options : [ 'warning_level=3',
'c_std=gnu11',
'cpp_std=c++20',
'b_pie=true',
#'b_sanitize=address,undefined',
2016-09-26 12:15:52 +02:00
'buildtype=debugoptimized' ])
2017-05-23 19:15:33 +02:00
pipewire_version = meson.project_version()
version_arr = pipewire_version.split('.')
pipewire_version_major = version_arr[0]
pipewire_version_minor = version_arr[1]
pipewire_version_micro = version_arr[2]
2016-09-26 12:15:52 +02:00
if version_arr.length() == 4
2017-05-23 19:15:33 +02:00
pipewire_version_nano = version_arr[3]
2016-09-26 12:15:52 +02:00
else
2017-05-23 19:15:33 +02:00
pipewire_version_nano = 0
2016-09-26 12:15:52 +02:00
endif
spaversion = '0.2'
apiversion = '0.3'
soversion = 0
libversion_minor = pipewire_version_major.to_int() * 1000 + pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int()
libversion = '@0@.@1@.0'.format(soversion, libversion_minor)
2016-09-26 12:15:52 +02:00
# LADI/jack
# 3, for PipeWire being the third JACK implementation, after JACK1 and jackdmp/JACK2)
jack_version_major = 3
jack_version_minor = libversion_minor
# libjack[server] version has 0 for major (for compatibility with other implementations),
# 3 for minor, and "1000*major + 100*minor + micro" as micro version (the minor libpipewire soversion number)
libjackversion = '@0@.@1@.@2@'.format(soversion, jack_version_major, jack_version_minor)
# jack[server] version has 3 for major
# and pipewire's "1000*major + 100*minor + micro" as minor version
jackversion = '@0@.@1@.@2@'.format(jack_version_major, jack_version_minor, 0)
pipewire_name = 'pipewire-@0@'.format(apiversion)
spa_name = 'spa-@0@'.format(spaversion)
2016-09-26 12:15:52 +02:00
prefix = get_option('prefix')
pipewire_bindir = prefix / get_option('bindir')
pipewire_datadir = prefix / get_option('datadir')
pipewire_libdir = prefix / get_option('libdir')
pipewire_libexecdir = prefix / get_option('libexecdir')
pipewire_localedir = prefix / get_option('localedir')
pipewire_sysconfdir = prefix / get_option('sysconfdir')
2016-09-26 12:15:52 +02:00
pipewire_configdir = pipewire_sysconfdir / 'pipewire'
pipewire_confdatadir = pipewire_datadir / 'pipewire'
modules_install_dir = pipewire_libdir / pipewire_name
cc = meson.get_compiler('c')
cc_native = meson.get_compiler('c', native: true)
if cc.has_header('features.h') and cc.get_define('__GLIBC__', prefix: '#include <features.h>') != ''
# glibc ld.so interprets ${LIB} in a library loading path with an
# appropriate value for the current architecture, typically something
# like lib, lib64 or lib/x86_64-linux-gnu.
# This allows the same pw-jack script to work for both 32- and 64-bit
# applications on biarch/multiarch distributions, by setting something
# like LD_LIBRARY_PATH='/usr/${LIB}/pipewire-0.3/jack'.
# Note that ${LIB} is a special token expanded by the runtime linker,
# not an environment variable, and must be passed through literally.
modules_install_dir_dlopen = prefix / '${LIB}' / pipewire_name
else
modules_install_dir_dlopen = modules_install_dir
endif
spa_plugindir = pipewire_libdir / spa_name
spa_datadir = pipewire_datadir / spa_name
alsadatadir = pipewire_datadir / 'alsa-card-profile' / 'mixer'
pipewire_headers_dir = pipewire_name / 'pipewire'
pkgconfig = import('pkgconfig')
2016-09-26 12:15:52 +02:00
common_flags = [
'-fvisibility=hidden',
'-fno-strict-aliasing',
'-fno-strict-overflow',
'-Werror=suggest-attribute=format',
'-Wsign-compare',
'-Wpointer-arith',
'-Wpointer-sign',
2024-06-27 14:40:31 +02:00
'-Werror=format',
'-Wno-error=format-overflow', # avoid some "%s directive argument is null"
'-Wformat-security',
'-Wimplicit-fallthrough',
'-Wmissing-braces',
'-Wtype-limits',
'-Wvariadic-macros',
'-Wmaybe-uninitialized',
'-Wno-missing-field-initializers',
'-Wno-unused-parameter',
'-Wno-pedantic',
'-Wdeprecated-declarations',
'-Wunused-result',
2023-07-03 04:52:44 +02:00
'-Werror=return-type',
'-Werror=float-conversion',
'-Werror=constant-conversion',
]
cc_flags = common_flags + [
'-D_GNU_SOURCE',
'-DFASTPATH',
# '-DSPA_DEBUG_MEMCPY',
'-Werror=implicit-function-declaration',
'-Werror=incompatible-pointer-types',
'-Werror=int-conversion',
'-Werror=old-style-declaration',
'-Werror=old-style-definition',
2023-07-03 04:51:47 +02:00
'-Werror=missing-parameter-type',
'-Werror=strict-prototypes',
]
add_project_arguments(cc.get_supported_arguments(cc_flags), language: 'c')
cc_flags_native = cc_native.get_supported_arguments(cc_flags)
have_cpp = add_languages('cpp', native: false, required : false)
if have_cpp
cxx = meson.get_compiler('cpp')
cxx_flags = common_flags + [ '-Wno-c99-designator' ]
add_project_arguments(cxx.get_supported_arguments(cxx_flags), language: 'cpp')
2019-01-07 18:02:36 +01:00
endif
2016-09-26 12:15:52 +02:00
have_sse = false
have_sse2 = false
have_ssse3 = false
have_sse41 = false
have_fma = false
have_avx = false
have_avx2 = false
if host_machine.cpu_family() in ['x86', 'x86_64']
sse_args = '-msse'
sse2_args = '-msse2'
ssse3_args = '-mssse3'
sse41_args = '-msse4.1'
fma_args = '-mfma'
avx_args = '-mavx'
avx2_args = '-mavx2'
have_sse = cc.has_argument(sse_args)
have_sse2 = cc.has_argument(sse2_args)
have_ssse3 = cc.has_argument(ssse3_args)
have_sse41 = cc.has_argument(sse41_args)
have_fma = cc.has_argument(fma_args)
have_avx = cc.has_argument(avx_args)
have_avx2 = cc.has_argument(avx2_args)
endif
2020-03-27 08:27:11 -04:00
have_neon = false
if host_machine.cpu_family() == 'aarch64'
if cc.compiles('''
#include <arm_neon.h>
int main () {
float *s;
asm volatile(
" ld1 { v0.4s }, [%[s]], #16\n"
" fcvtzs v0.4s, v0.4s, #31\n"
: [s] "+r" (s) : :);
}
''',
name : 'aarch64 Neon Support')
neon_args = []
have_neon = true
endif
elif cc.has_argument('-mfpu=neon')
if cc.compiles('''
#include <arm_neon.h>
int main () {
float *s;
asm volatile(
" vld1.32 { q0 }, [%[s]]!\n"
" vcvt.s32.f32 q0, q0, #31\n"
: [s] "+r" (s) : :);
}
''',
args: '-mfpu=neon',
name : 'arm Neon Support')
neon_args = ['-mfpu=neon']
have_neon = true
endif
2020-03-27 08:27:11 -04:00
endif
have_rvv = false
if host_machine.cpu_family() == 'riscv64'
if cc.compiles('''
int main() {
__asm__ __volatile__ (
".option arch, +v\nvsetivli zero, 0, e8, m1, ta, ma"
);
}
''',
name : 'riscv64 V Support')
have_rvv = true
endif
endif
libatomic = cc.find_library('atomic', required : false)
test_8_byte_atomic = '''
#include <stdint.h>
int main(void)
{
int64_t eight;
__atomic_fetch_add(&eight, 123, __ATOMIC_SEQ_CST);
return 0;
}
'''
# We currently assume that libatomic is unnecessary for 4-byte atomic
# operations on any reasonable architecture.
if cc.links(
test_8_byte_atomic,
name : '8-byte __atomic_fetch_add without libatomic')
atomic_dep = dependency('', required: false)
elif cc.links(
test_8_byte_atomic,
dependencies : libatomic,
name : '8-byte __atomic_fetch_add with libatomic')
atomic_dep = libatomic
else
error('8-byte atomic operations are required')
endif
2020-03-27 08:27:11 -04:00
versiondata = configuration_data()
versiondata.set('PIPEWIRE_VERSION_MAJOR', pipewire_version_major)
versiondata.set('PIPEWIRE_VERSION_MINOR', pipewire_version_minor)
versiondata.set('PIPEWIRE_VERSION_MICRO', pipewire_version_micro)
versiondata.set('PIPEWIRE_VERSION_NANO', pipewire_version_nano)
versiondata.set_quoted('PIPEWIRE_API_VERSION', apiversion)
2016-09-26 12:15:52 +02:00
cdata = configuration_data()
2023-05-08 10:45:53 +02:00
cdata.set_quoted('PREFIX', prefix)
cdata.set_quoted('PIPEWIRE_CONFDATADIR', pipewire_confdatadir)
cdata.set_quoted('LOCALEDIR', pipewire_localedir)
cdata.set_quoted('LIBDIR', pipewire_libdir)
cdata.set_quoted('GETTEXT_PACKAGE', meson.project_name())
cdata.set_quoted('PACKAGE', 'pipewire')
cdata.set_quoted('PACKAGE_NAME', 'PipeWire')
cdata.set_quoted('PACKAGE_STRING', 'PipeWire @0@'.format(pipewire_version))
cdata.set_quoted('PACKAGE_TARNAME', 'pipewire')
cdata.set_quoted('PACKAGE_URL', 'https://pipewire.org')
cdata.set_quoted('PACKAGE_VERSION', pipewire_version)
cdata.set_quoted('MODULEDIR', modules_install_dir)
cdata.set_quoted('PIPEWIRE_CONFIG_DIR', pipewire_configdir)
cdata.set_quoted('PLUGINDIR', spa_plugindir)
cdata.set_quoted('SPADATADIR', spa_datadir)
cdata.set_quoted('PA_ALSA_DATA_DIR', alsadatadir)
cdata.set('RTPRIO_SERVER', get_option('rtprio-server'))
cdata.set('RTPRIO_CLIENT', get_option('rtprio-client'))
2016-09-26 12:15:52 +02:00
if host_machine.endian() == 'big'
cdata.set('WORDS_BIGENDIAN', 1)
endif
2016-09-26 12:15:52 +02:00
check_headers = [
['sys/auxv.h', 'HAVE_SYS_AUXV_H'],
['sys/mount.h', 'HAVE_SYS_MOUNT_H'],
2016-09-26 12:15:52 +02:00
['sys/param.h', 'HAVE_SYS_PARAM_H'],
['sys/random.h', 'HAVE_SYS_RANDOM_H'],
['sys/vfs.h', 'HAVE_SYS_VFS_H'],
['pwd.h', 'HAVE_PWD_H'],
['grp.h', 'HAVE_GRP_H'],
2016-09-26 12:15:52 +02:00
]
foreach h : check_headers
cdata.set(h.get(1), cc.has_header(h.get(0)))
2016-09-26 12:15:52 +02:00
endforeach
cdata.set('HAVE_PIDFD_OPEN',
cc.get_define('SYS_pidfd_open', prefix: '#include <sys/syscall.h>') != '')
2021-06-10 15:12:12 +10:00
meson.build: rework `systemd` related options One issues is that the `systemd-{system,user}-service` feature options do not anything without the `systemd` option. This makes it more complicated to arrive at the desired build configuration since there are 3^3 = 27 possible ways to set each of them, but if `systemd=disabled`, then the other two are just ignored. Secondly, the `systemd` option also influences whether or not libsystemd will be used or not. This is not strictly necessary, since the "systemd" and "libsystemd" pkg-config files might be split, and one might wish to disable any kind of service file generation, but use libsystemd. Solve the first issues by using the `systemd-{system,user}-service` options when looking up the "systemd" dependency for generating service files. This means that the corresponding option is in full control, no secondary options are necessary. This means that the "systemd" dependency is looked up potentially twice, but that should not be a significant issue since meson caches dependecy lookups. And solve the second issue by renaming the now unused `systemd` option to `libsystemd` and using it solely to control whether or not libsystemd will be used. Furthermore, the default value of `systemd-user-service` is set to "auto" to prevent the dependency lookup from failing on non-systemd systemd out of the box. And the journal tests in "test-support" are extended to return "skip" if `sd_journal_open()` returns `ENOSYS`, which is needed because "elogind" ships the systemd pkg-config files and headers.
2025-05-10 17:43:28 +02:00
systemd_dep = dependency('libsystemd', required: get_option('libsystemd'))
summary({'libsystemd': systemd_dep.found()}, bool_yn: true)
meson.build: rework `systemd` related options One issues is that the `systemd-{system,user}-service` feature options do not anything without the `systemd` option. This makes it more complicated to arrive at the desired build configuration since there are 3^3 = 27 possible ways to set each of them, but if `systemd=disabled`, then the other two are just ignored. Secondly, the `systemd` option also influences whether or not libsystemd will be used or not. This is not strictly necessary, since the "systemd" and "libsystemd" pkg-config files might be split, and one might wish to disable any kind of service file generation, but use libsystemd. Solve the first issues by using the `systemd-{system,user}-service` options when looking up the "systemd" dependency for generating service files. This means that the corresponding option is in full control, no secondary options are necessary. This means that the "systemd" dependency is looked up potentially twice, but that should not be a significant issue since meson caches dependecy lookups. And solve the second issue by renaming the now unused `systemd` option to `libsystemd` and using it solely to control whether or not libsystemd will be used. Furthermore, the default value of `systemd-user-service` is set to "auto" to prevent the dependency lookup from failing on non-systemd systemd out of the box. And the journal tests in "test-support" are extended to return "skip" if `sd_journal_open()` returns `ENOSYS`, which is needed because "elogind" ships the systemd pkg-config files and headers.
2025-05-10 17:43:28 +02:00
cdata.set('HAVE_SYSTEMD', systemd_dep.found())
logind_dep = dependency(get_option('logind-provider'), required: get_option('logind'))
summary({'logind': logind_dep.found()}, bool_yn: true)
cdata.set('HAVE_LOGIND', logind_dep.found())
selinux_dep = dependency('libselinux', required: get_option('selinux'))
summary({'libselinux': selinux_dep.found()}, bool_yn: true)
cdata.set('HAVE_SELINUX', selinux_dep.found())
2016-09-26 12:15:52 +02:00
configinc = include_directories('.')
includes_inc = include_directories('include')
2017-07-11 15:57:20 +02:00
pipewire_inc = include_directories('src')
2016-09-26 12:15:52 +02:00
makedata = configuration_data()
makedata.set('BUILD_ROOT', meson.project_build_root())
makedata.set('SOURCE_ROOT', meson.project_source_root())
makedata.set('VERSION', pipewire_version)
if version_arr.length() == 4
makedata.set('TAG', 'HEAD')
else
makedata.set('TAG', pipewire_version)
endif
configure_file(input : 'Makefile.in',
output : 'Makefile',
configuration : makedata)
2016-09-26 12:15:52 +02:00
# Find dependencies
mathlib = cc.find_library('m', required : false)
mathlib_native = cc_native.find_library('m', required : false)
rt_lib = cc.find_library('rt', required : false) # clock_gettime
dl_lib = cc.find_library('dl', required : false)
pthread_lib = dependency('threads')
dbus_dep = dependency('dbus-1', required : get_option('dbus'))
summary({'dbus (Bluetooth, rt, portal, pw-reserve)': dbus_dep.found()}, bool_yn: true, section: 'Misc dependencies')
cdata.set('HAVE_DBUS', dbus_dep.found())
sdl_dep = dependency('sdl2', required : get_option('sdl2'))
2022-01-21 16:29:29 +01:00
summary({'SDL2 (video examples)': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies')
drm_dep = dependency('libdrm', required : false)
fftw_dep = dependency('fftw3f', required : get_option('fftw'))
summary({'fftw3f (filter-chain convolver)': fftw_dep.found()}, bool_yn: true, section: 'Misc dependencies')
cdata.set('HAVE_FFTW', fftw_dep.found())
if get_option('readline').disabled()
readline_dep = dependency('', required: false)
else
readline_dep = dependency('readline', required : false)
if not readline_dep.found()
readline_dep = cc.find_library('readline', required : get_option('readline'))
endif
endif
# Both the FFmpeg SPA plugin and the pw-cat FFmpeg integration use libavcodec.
# But only the latter also needs libavformat and libavutil.
# Search for these libraries here, globally, so both of these subprojects can reuse the results.
pw_cat_ffmpeg = get_option('pw-cat-ffmpeg')
ffmpeg = get_option('ffmpeg')
if pw_cat_ffmpeg.allowed() or ffmpeg.allowed()
avcodec_dep = dependency('libavcodec', required: pw_cat_ffmpeg.enabled() or ffmpeg.enabled())
avformat_dep = dependency('libavformat', required: pw_cat_ffmpeg.enabled())
avfilter_dep = dependency('libavfilter', required: ffmpeg.enabled())
avutil_dep = dependency('libavutil', required: pw_cat_ffmpeg.enabled() or ffmpeg.enabled())
swscale_dep = dependency('libswscale', required: pw_cat_ffmpeg.enabled() or ffmpeg.enabled())
else
avcodec_dep = dependency('', required: false)
2025-06-10 11:23:15 +02:00
avfilter_dep = dependency('', required: false)
endif
cdata.set('HAVE_PW_CAT_FFMPEG_INTEGRATION', pw_cat_ffmpeg.allowed())
2023-03-10 17:39:51 +01:00
opus_dep = dependency('opus', required : get_option('opus'))
summary({'opus (Bluetooth, RTP)': opus_dep.found()}, bool_yn: true, section: 'Misc dependencies')
cdata.set('HAVE_OPUS', opus_dep.found())
2023-03-10 17:39:51 +01:00
summary({'readline (for pw-cli)': readline_dep.found()}, bool_yn: true, section: 'Misc dependencies')
cdata.set('HAVE_READLINE', readline_dep.found())
ncurses_dep = dependency('ncursesw', required : false)
sndfile_dep = dependency('sndfile', version : '>= 1.0.20', required : get_option('sndfile'))
summary({'sndfile': sndfile_dep.found()}, bool_yn: true, section: 'pw-cat/pw-play/pw-dump/filter-chain')
cdata.set('HAVE_SNDFILE', sndfile_dep.found())
pulseaudio_dep = dependency('libpulse', required : get_option('libpulse'))
summary({'libpulse': pulseaudio_dep.found()}, bool_yn: true, section: 'Streaming between daemons')
avahi_dep = dependency('avahi-client', required : get_option('avahi'))
summary({'Avahi DNS-SD (Zeroconf)': avahi_dep.found()}, bool_yn: true,
section: 'Streaming between daemons')
2017-11-13 20:08:29 +01:00
x11_dep = dependency('x11-xcb', required : get_option('x11'))
summary({'X11 (x11-bell)': x11_dep.found()}, bool_yn: true,
section: 'Misc dependencies')
xfixes_dep = dependency('xfixes', required : get_option('x11-xfixes'), version: '>= 6')
cdata.set('HAVE_XFIXES_6', xfixes_dep.found())
canberra_dep = dependency('libcanberra', required : get_option('libcanberra'))
summary({'libcanberra (x11-bell)': canberra_dep.found()}, bool_yn: true,
section: 'Misc dependencies')
libusb_dep = dependency('libusb-1.0', required : get_option('libusb'))
summary({'libusb (Bluetooth quirks)': libusb_dep.found()}, bool_yn: true, section: 'Backend')
cdata.set('HAVE_LIBUSB', libusb_dep.found())
glib2_dep = dependency('glib-2.0', required : get_option('flatpak'))
summary({'GLib-2.0 (Flatpak support)': glib2_dep.found()}, bool_yn: true, section: 'Misc dependencies')
flatpak_support = glib2_dep.found()
cdata.set('HAVE_GLIB2', flatpak_support)
gsettings_gio_dep = dependency('gio-2.0', version : '>= 2.26.0', required : get_option('gsettings'))
summary({'GIO (GSettings)': gsettings_gio_dep.found()}, bool_yn: true, section: 'Misc dependencies')
if not gsettings_gio_dep.found() and get_option('gsettings-pulse-schema').enabled()
error('`gsettings-pulse-schema` is enabled but `gio` was not found.')
endif
gst_option = get_option('gstreamer')
gst_deps_def = {
'glib-2.0': {'version': '>=2.32.0'},
'gobject-2.0': {},
'gmodule-2.0': {},
'gio-2.0': {},
'gio-unix-2.0': {},
'gstreamer-1.0': {'version': '>= 1.10.0'},
'gstreamer-base-1.0': {},
'gstreamer-video-1.0': {},
'gstreamer-audio-1.0': {},
'gstreamer-allocators-1.0': {},
}
2018-06-01 11:38:18 +02:00
gst_dep = []
gst_dma_drm_found = false
gst_shm_allocator_found = false
foreach depname, kwargs: gst_deps_def
dep = dependency(depname, required: gst_option, kwargs: kwargs)
summary({depname: dep.found()}, bool_yn: true, section: 'GStreamer modules')
if not dep.found()
# Beware, there's logic below depending on the array clear here!
gst_dep = []
if get_option('gstreamer-device-provider').enabled()
error('`gstreamer-device-provider` is enabled but `@0@` was not found.'.format(depname))
endif
break
endif
gst_dep += [dep]
if depname == 'gstreamer-allocators-1.0' and dep.version().version_compare('>= 1.23.1')
gst_dma_drm_found = true
gst_shm_allocator_found = true
endif
endforeach
summary({'gstreamer SHM allocator': gst_shm_allocator_found}, bool_yn: true, section: 'Backend')
cdata.set('HAVE_GSTREAMER_SHM_ALLOCATOR', gst_shm_allocator_found)
# This code relies on the array being empty if any dependency was not found
gst_dp_found = gst_dep.length() > 0
summary({'gstreamer-device-provider': gst_dp_found}, bool_yn: true, section: 'Backend')
cdata.set('HAVE_GSTREAMER_DEVICE_PROVIDER', get_option('gstreamer-device-provider').allowed())
summary({'gstreamer DMA_DRM support': gst_dma_drm_found}, bool_yn: true, section: 'Backend')
cdata.set('HAVE_GSTREAMER_DMA_DRM', gst_dma_drm_found)
meson: fix webrtc-audio-processing dependency ignoring configure args Most dependencies use meson "feature" options for optional functionality. This allows people to disable them, if they don't want them, through the power of tristate decision-making. This particular dependency does something a bit more complicated than can be described by simply passing feature options to the required kwarg. It: - tries to look for two different names of the dependency - selects different version ranges, depending on the dependency name - has a hole in the middle of the versions Unfortunately, `required: false` for the first dependency isn't equivalent to a tristate decision-making process. We have to manually code the logic ourselves. The problem is that when we look up the first name, we cannot pass the feature option in because if the option is force enabled, then the dependency lookup fails and configuration never tries to find the older version instead. But also, we can't just say it *isn't* required, because if the option is force *disabled* but it is installed on the system, we still find it and build against it. One solution would be using meson 0.60's support for multiple dependency names: ``` dependency('webrtc-audio-processing-1', 'webrtc-audio-processing', version : ['>= 0.2'], required: get_option('echo-cancel-webrtc'), ) ``` Unfortunately, this too doesn't work since we could end up detecting 1.1 (the hole in the middle) which is invalid. Instead, we do a bit of checking for tristate values before deciding to invoke `dependency()`. This lets us guarantee that disabled dependencies are well and truly disabled. Bug: https://bugs.gentoo.org/933218 Fixes: #3678
2024-05-30 19:44:38 -04:00
if get_option('echo-cancel-webrtc').disabled()
webrtc_dep = dependency('', required: false)
summary({'WebRTC Echo Canceling': webrtc_dep.found()}, bool_yn: false, section: 'Misc dependencies')
else
webrtc_dep = dependency('webrtc-audio-processing-2',
version : ['>= 2.0' ],
meson: fix webrtc-audio-processing dependency ignoring configure args Most dependencies use meson "feature" options for optional functionality. This allows people to disable them, if they don't want them, through the power of tristate decision-making. This particular dependency does something a bit more complicated than can be described by simply passing feature options to the required kwarg. It: - tries to look for two different names of the dependency - selects different version ranges, depending on the dependency name - has a hole in the middle of the versions Unfortunately, `required: false` for the first dependency isn't equivalent to a tristate decision-making process. We have to manually code the logic ourselves. The problem is that when we look up the first name, we cannot pass the feature option in because if the option is force enabled, then the dependency lookup fails and configuration never tries to find the older version instead. But also, we can't just say it *isn't* required, because if the option is force *disabled* but it is installed on the system, we still find it and build against it. One solution would be using meson 0.60's support for multiple dependency names: ``` dependency('webrtc-audio-processing-1', 'webrtc-audio-processing', version : ['>= 0.2'], required: get_option('echo-cancel-webrtc'), ) ``` Unfortunately, this too doesn't work since we could end up detecting 1.1 (the hole in the middle) which is invalid. Instead, we do a bit of checking for tristate values before deciding to invoke `dependency()`. This lets us guarantee that disabled dependencies are well and truly disabled. Bug: https://bugs.gentoo.org/933218 Fixes: #3678
2024-05-30 19:44:38 -04:00
required : false)
cdata.set('HAVE_WEBRTC2', webrtc_dep.found())
meson: fix webrtc-audio-processing dependency ignoring configure args Most dependencies use meson "feature" options for optional functionality. This allows people to disable them, if they don't want them, through the power of tristate decision-making. This particular dependency does something a bit more complicated than can be described by simply passing feature options to the required kwarg. It: - tries to look for two different names of the dependency - selects different version ranges, depending on the dependency name - has a hole in the middle of the versions Unfortunately, `required: false` for the first dependency isn't equivalent to a tristate decision-making process. We have to manually code the logic ourselves. The problem is that when we look up the first name, we cannot pass the feature option in because if the option is force enabled, then the dependency lookup fails and configuration never tries to find the older version instead. But also, we can't just say it *isn't* required, because if the option is force *disabled* but it is installed on the system, we still find it and build against it. One solution would be using meson 0.60's support for multiple dependency names: ``` dependency('webrtc-audio-processing-1', 'webrtc-audio-processing', version : ['>= 0.2'], required: get_option('echo-cancel-webrtc'), ) ``` Unfortunately, this too doesn't work since we could end up detecting 1.1 (the hole in the middle) which is invalid. Instead, we do a bit of checking for tristate values before deciding to invoke `dependency()`. This lets us guarantee that disabled dependencies are well and truly disabled. Bug: https://bugs.gentoo.org/933218 Fixes: #3678
2024-05-30 19:44:38 -04:00
if webrtc_dep.found()
summary({'WebRTC Echo Canceling >= 2.0': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
meson: fix webrtc-audio-processing dependency ignoring configure args Most dependencies use meson "feature" options for optional functionality. This allows people to disable them, if they don't want them, through the power of tristate decision-making. This particular dependency does something a bit more complicated than can be described by simply passing feature options to the required kwarg. It: - tries to look for two different names of the dependency - selects different version ranges, depending on the dependency name - has a hole in the middle of the versions Unfortunately, `required: false` for the first dependency isn't equivalent to a tristate decision-making process. We have to manually code the logic ourselves. The problem is that when we look up the first name, we cannot pass the feature option in because if the option is force enabled, then the dependency lookup fails and configuration never tries to find the older version instead. But also, we can't just say it *isn't* required, because if the option is force *disabled* but it is installed on the system, we still find it and build against it. One solution would be using meson 0.60's support for multiple dependency names: ``` dependency('webrtc-audio-processing-1', 'webrtc-audio-processing', version : ['>= 0.2'], required: get_option('echo-cancel-webrtc'), ) ``` Unfortunately, this too doesn't work since we could end up detecting 1.1 (the hole in the middle) which is invalid. Instead, we do a bit of checking for tristate values before deciding to invoke `dependency()`. This lets us guarantee that disabled dependencies are well and truly disabled. Bug: https://bugs.gentoo.org/933218 Fixes: #3678
2024-05-30 19:44:38 -04:00
else
webrtc_dep = dependency('webrtc-audio-processing-1',
version : ['>= 1.2' ],
required : false)
cdata.set('HAVE_WEBRTC1', webrtc_dep.found())
if webrtc_dep.found()
summary({'WebRTC Echo Canceling >= 1.2': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
else
webrtc_dep = dependency('webrtc-audio-processing',
version : ['>= 0.2', '< 1.0'],
required : false)
cdata.set('HAVE_WEBRTC', webrtc_dep.found())
if webrtc_dep.found()
summary({'WebRTC Echo Canceling < 1.0': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
else
# If deps are not found on the system but it's enabled, try to fallback to the subproject
webrtc_dep = dependency('webrtc-audio-processing-2',
version : ['>= 2.0' ],
required : get_option('echo-cancel-webrtc'))
cdata.set('HAVE_WEBRTC2', webrtc_dep.found())
summary({'WebRTC Echo Canceling > 2.0': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies')
endif
endif
meson: fix webrtc-audio-processing dependency ignoring configure args Most dependencies use meson "feature" options for optional functionality. This allows people to disable them, if they don't want them, through the power of tristate decision-making. This particular dependency does something a bit more complicated than can be described by simply passing feature options to the required kwarg. It: - tries to look for two different names of the dependency - selects different version ranges, depending on the dependency name - has a hole in the middle of the versions Unfortunately, `required: false` for the first dependency isn't equivalent to a tristate decision-making process. We have to manually code the logic ourselves. The problem is that when we look up the first name, we cannot pass the feature option in because if the option is force enabled, then the dependency lookup fails and configuration never tries to find the older version instead. But also, we can't just say it *isn't* required, because if the option is force *disabled* but it is installed on the system, we still find it and build against it. One solution would be using meson 0.60's support for multiple dependency names: ``` dependency('webrtc-audio-processing-1', 'webrtc-audio-processing', version : ['>= 0.2'], required: get_option('echo-cancel-webrtc'), ) ``` Unfortunately, this too doesn't work since we could end up detecting 1.1 (the hole in the middle) which is invalid. Instead, we do a bit of checking for tristate values before deciding to invoke `dependency()`. This lets us guarantee that disabled dependencies are well and truly disabled. Bug: https://bugs.gentoo.org/933218 Fixes: #3678
2024-05-30 19:44:38 -04:00
endif
endif
# On FreeBSD and MidnightBSD, epoll-shim library is required for eventfd() and timerfd()
epoll_shim_dep = (host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
? dependency('epoll-shim', required: true)
: dependency('', required: false))
libinotify_dep = (host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
? dependency('libinotify', required: true)
: dependency('', required: false))
# On FreeBSD and MidnightBSD, libintl library is required for gettext
libintl_dep = cc.find_library('intl', required: false)
if not libintl_dep.found()
libintl_dep = dependency('intl', required: false)
endif
summary({'intl support': libintl_dep.found()}, bool_yn: true)
need_alsa = get_option('pipewire-alsa').enabled() or 'media-session' in get_option('session-managers')
alsa_dep = dependency('alsa', version : '>=1.2.6', required: need_alsa)
summary({'pipewire-alsa': alsa_dep.found()}, bool_yn: true)
if host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd'
# On FreeBSD and MidnightBSD the OpenSSL library may come from base or a package.
# Check for a package first and fallback to the base library if we can't find it via pkgconfig
openssl_lib = dependency('openssl', required: false)
if not openssl_lib.found()
openssl_lib = declare_dependency(link_args : [ '-lssl', '-lcrypto'])
endif
else
openssl_lib = dependency('openssl', required: get_option('raop'))
endif
summary({'OpenSSL (for raop-sink)': openssl_lib.found()}, bool_yn: true)
2021-11-11 11:42:16 +01:00
2023-05-28 15:49:09 +02:00
libffado_dep = dependency('libffado', required: get_option('libffado'))
summary({'ffado': libffado_dep.found()}, bool_yn: true)
pipewire-pulse: add snap permissions support SNAP containers have two main "audio" security rules: * audio-playback: the applications inside the container can send audio samples into a sink * audio-record: the applications inside the container can get audio samples from a source Also, old SNAP containers had the "pulseaudio" rule, which just exposed the pulseaudio socket directly, without limits. This is similar to the current Flatpak audio permissions. In the pulseaudio days, a specific pulseaudio module was used that checked the permissions given to the application and allowed or forbade access to the pulseaudio operations. With the change to pipewire, this functionality must be implemented in pipewire-pulse to guarantee the sandbox security. This patch adds support for sandboxing permissions in the pulseaudio module, and implements support for the SNAP audio security model, thus forbiding a SNAP application to record audio unless it has permissions to do so. The current code for pipewire-pulseaudio checks the permissions of the snap and adds three properties to each new client: * pipewire.snap.id: contains the Snap ID of the client. * pipewire.snap.audio.playback: its value is 'true' if the client has permission to play audio, or 'false' if not. * pipewire.snap.audio.record: its value is 'true' if the client has permission to record audio, or 'false' if not. These properties must be processed by wireplumber to add or remove access permissions to the corresponding nodes. That code is available in a separate patch: https://gitlab.freedesktop.org/pipewire/wireplumber/-/merge_requests/567
2023-11-22 11:26:16 +01:00
glib2_snap_dep = dependency('glib-2.0', required : get_option('snap'))
gio2_snap_dep = dependency('gio-2.0', required : get_option('snap'))
apparmor_snap_dep = dependency('libapparmor', required : get_option('snap'))
if dependency('snapd-glib-2', required: false).found()
snap_dep = dependency('snapd-glib-2', required : get_option('snap'))
else
snap_dep = dependency('snapd-glib', required : get_option('snap'))
endif
if snap_dep.found() and glib2_snap_dep.found() and gio2_snap_dep.found() and apparmor_snap_dep.found()
2023-11-22 12:30:32 +00:00
cdata.set('HAVE_SNAP', true)
pipewire-pulse: add snap permissions support SNAP containers have two main "audio" security rules: * audio-playback: the applications inside the container can send audio samples into a sink * audio-record: the applications inside the container can get audio samples from a source Also, old SNAP containers had the "pulseaudio" rule, which just exposed the pulseaudio socket directly, without limits. This is similar to the current Flatpak audio permissions. In the pulseaudio days, a specific pulseaudio module was used that checked the permissions given to the application and allowed or forbade access to the pulseaudio operations. With the change to pipewire, this functionality must be implemented in pipewire-pulse to guarantee the sandbox security. This patch adds support for sandboxing permissions in the pulseaudio module, and implements support for the SNAP audio security model, thus forbiding a SNAP application to record audio unless it has permissions to do so. The current code for pipewire-pulseaudio checks the permissions of the snap and adds three properties to each new client: * pipewire.snap.id: contains the Snap ID of the client. * pipewire.snap.audio.playback: its value is 'true' if the client has permission to play audio, or 'false' if not. * pipewire.snap.audio.record: its value is 'true' if the client has permission to record audio, or 'false' if not. These properties must be processed by wireplumber to add or remove access permissions to the corresponding nodes. That code is available in a separate patch: https://gitlab.freedesktop.org/pipewire/wireplumber/-/merge_requests/567
2023-11-22 11:26:16 +01:00
snap_deps = [glib2_snap_dep, gio2_snap_dep, snap_dep, apparmor_snap_dep]
endif
summary({'GLib-2.0 (Snap support)': glib2_snap_dep.found()}, bool_yn: true, section: 'Misc dependencies')
summary({'Gio-2.0 (Snap support)': gio2_snap_dep.found()}, bool_yn: true, section: 'Misc dependencies')
summary({'Apparmor (Snap support)': apparmor_snap_dep.found()}, bool_yn: true, section: 'Misc dependencies')
summary({'Snapd-glib (Snap support)': snap_dep.found()}, bool_yn: true, section: 'Misc dependencies')
2023-05-28 15:49:09 +02:00
check_functions = [
['gettid', '#include <unistd.h>', ['-D_GNU_SOURCE'], []],
['memfd_create', '#include <sys/mman.h>', ['-D_GNU_SOURCE'], []],
['getrandom', '#include <stddef.h>\n#include <sys/random.h>', ['-D_GNU_SOURCE'], []],
['random_r', '#include <stdlib.h>', ['-D_GNU_SOURCE'], []],
['reallocarray', '#include <stdlib.h>', ['-D_GNU_SOURCE'], []],
['sigabbrev_np', '#include <string.h>', ['-D_GNU_SOURCE'], []],
['XSetIOErrorExitHandler', '#include <X11/Xlib.h>', [], [x11_dep]],
2023-10-04 10:59:26 +02:00
['malloc_trim', '#include <malloc.h>', [], []],
['malloc_info', '#include <malloc.h>', [], []],
]
foreach f : check_functions
cdata.set('HAVE_' + f.get(0).to_upper(),
cc.has_function(f.get(0),
prefix: f.get(1),
args: f.get(2),
dependencies: f.get(3)))
endforeach
installed_tests_metadir = pipewire_datadir / 'installed-tests' / pipewire_name
installed_tests_execdir = pipewire_libexecdir / 'installed-tests' / pipewire_name
installed_tests_enabled = get_option('installed_tests').allowed()
installed_tests_template = files('template.test.in')
if get_option('tests').allowed()
gstack = find_program('gstack', required : false)
cdata.set('HAVE_GSTACK', gstack.found())
endif
2021-01-08 10:26:46 +01:00
subdir('po')
subdir('spa')
2017-07-11 15:57:20 +02:00
subdir('src')
if get_option('tests').allowed()
subdir('test')
endif
configure_file(output : 'config.h',
configuration : cdata)
if get_option('pipewire-jack').allowed()
subdir('pipewire-jack')
endif
if get_option('pipewire-v4l2').allowed()
subdir('pipewire-v4l2')
endif
if alsa_dep.found()
subdir('pipewire-alsa/alsa-plugins')
2020-05-02 10:42:44 +02:00
subdir('pipewire-alsa/conf')
subdir('pipewire-alsa/tests')
endif
2016-09-26 12:15:52 +02:00
generate_docs = get_option('man').enabled() or get_option('docs').enabled()
if get_option('man').allowed() or get_option('docs').allowed()
doxygen = find_program('doxygen', required : generate_docs, version : '>=1.9')
pymod = import('python')
python = pymod.find_installation('python3', required: generate_docs)
generate_docs = doxygen.found() and python.found()
endif
install_docs = get_option('docs').require(generate_docs).allowed()
install_man = get_option('man').require(generate_docs).allowed()
summary({'Documentation ': install_docs}, bool_yn: true)
summary({'Man pages ': install_man}, bool_yn: true)
if generate_docs
subdir('doc')
endif
setenv = find_program('pw-uninstalled.sh')
2021-10-13 14:37:55 +10:00
run_target('pw-uninstalled',
command : [setenv,
'-b@0@'.format(meson.project_build_root()),
2021-10-13 14:37:55 +10:00
'-v@0@'.format(pipewire_version)]
)
devenv = environment()
builddir = meson.project_build_root()
srcdir = meson.project_source_root()
devenv.set('PIPEWIRE_CONFIG_DIR', pipewire_dep.get_variable('confdatadir'))
devenv.set('PIPEWIRE_MODULE_DIR', pipewire_dep.get_variable('moduledir'))
devenv.set('SPA_PLUGIN_DIR', spa_dep.get_variable('plugindir'))
devenv.set('SPA_DATA_DIR', spa_dep.get_variable('datadir'))
devenv.set('ACP_PATHS_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'paths')
devenv.set('ACP_PROFILES_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'profile-sets')
devenv.prepend('GST_PLUGIN_PATH', builddir / 'src'/ 'gst')
devenv.prepend('ALSA_PLUGIN_DIR', builddir / 'pipewire-alsa' / 'alsa-plugins')
devenv.prepend('LD_LIBRARY_PATH', builddir / 'pipewire-jack' / 'src')
devenv.set('PIPEWIRE_LOG_SYSTEMD', 'false')
devenv.set('PW_UNINSTALLED', '1')
devenv.set('PW_BUILDDIR', meson.project_build_root())
meson.add_devenv(devenv)