gst-plugins-rs/meson.build
Nirbheek Chauhan a3d405f670 meson: Add options for all plugins
Required a slight rework of the build file, and how options are passed
to cargo_wrapper.py

Necessitated a bump of the required gstreamer version to 1.20, which
should be fine for the meson build since its primary function is to be
built as part of the gstreamer monorepo build to get a dev env.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1028>
2022-12-28 22:30:11 +05:30

432 lines
12 KiB
Meson

project('gst-plugins-rs',
'rust',
'c',
version: '0.9.0-alpha.1',
meson_version : '>= 0.60')
# dependencies.py needs a toml parsing module
python = import('python').find_installation(modules: ['tomllib'], required: false)
if not python.found()
python = import('python').find_installation(modules: ['tomli'])
endif
fs = import('fs')
host_system = host_machine.system()
if get_option('debug')
target = 'debug'
else
target = 'release'
endif
cargo = find_program('cargo', version:'>=1.40')
cargo_wrapper = find_program('cargo_wrapper.py')
cargo_c = find_program('cargo-cbuild', version:'>=0.9.3', required: false)
rustc = find_program('rustc', version:'>=1.52')
if not cargo_c.found()
error('cargo-c missing, install it with: \'cargo install cargo-c\'')
endif
system = build_machine.system()
exe_suffix = ''
if system == 'windows'
exe_suffix = '.exe'
ext_dynamic = 'dll'
ext_static = 'lib'
elif system == 'darwin'
ext_dynamic = 'dylib'
ext_static = 'a'
else
ext_dynamic = 'so'
ext_static = 'a'
endif
# kept in the same order as the `members` list in Cargo.toml
plugins = {
'audiofx': {
'library': 'libgstrsaudiofx',
},
'claxon': {'library': 'libgstclaxon'},
# csound has a non-trivial external dependency, see below
'lewton': {'library': 'libgstlewton'},
'spotify': {'library': 'libgstspotify'},
'file': {'library': 'libgstrsfile'},
# sodium can have an external dependency, see below
'threadshare': {
'library': 'libgstthreadshare',
},
'mp4': {'library': 'libgstmp4'},
'fmp4': {
'library': 'libgstfmp4',
},
'aws': {
'library': 'libgstaws',
'extra-deps': {'openssl': '>=1.1'},
},
'hlssink3': {'library': 'libgsthlssink3'},
'ndi': {'library': 'libgstndi'},
'onvif': {
'library': 'libgstrsonvif',
'extra-deps': {'pangocairo': ''},
},
'raptorq': {'library': 'libgstraptorq'},
'reqwest': {'library': 'libgstreqwest'},
'rtp': {'library': 'libgstrsrtp'},
'webrtchttp': {'library': 'libgstwebrtchttp'},
'webrtc': {
'library': 'libgstrswebrtc',
},
'textahead': {'library': 'libgsttextahead'},
'json': {'library': 'libgstjson'},
'regex': {'library': 'libgstregex'},
'textwrap': {'library': 'libgsttextwrap'},
'fallbackswitch': {
'library': 'libgstfallbackswitch',
},
'livesync': {
'library': 'libgstlivesync',
},
'togglerecord': {
'library': 'libgsttogglerecord',
},
'tracers': {'library': 'libgstrstracers'},
'uriplaylistbin': {
'library': 'libgsturiplaylistbin',
},
'cdg': {'library': 'libgstcdg'},
'closedcaption': {
'library': 'libgstrsclosedcaption',
'extra-deps': {
'pango': '',
'pangocairo': '',
'cairo-gobject': '',
}
},
'dav1d': {
'library': 'libgstdav1d',
'extra-deps': {'dav1d': '>=1.0'},
},
'ffv1': {'library': 'libgstffv1'},
'flavors': {'library': 'libgstrsflv'},
'gif': {
'library': 'libgstgif',
},
'gtk4': {
'library': 'libgstgtk4',
'extra-deps': {'gtk4': '>=4.6'},
},
'hsv': {'library': 'libgsthsv'},
'png': {
'library': 'libgstrspng',
},
'rav1e': {'library': 'libgstrav1e'},
'videofx': {
'library': 'libgstrsvideofx',
'extra-deps': {'cairo-gobject': ''},
},
}
# Won't build on platforms where it bundles the sources because of:
# https://github.com/qnighy/libwebp-sys2-rs/issues/12
# the fix is:
# https://github.com/qnighy/libwebp-sys2-rs/pull/13
if host_system not in ['windows', 'darwin']
# FIXME: libwebp-sys2 will build its bundled version on msvc and apple platforms
# https://github.com/qnighy/libwebp-sys2-rs/issues/4
plugins += {'webp': {
'library': 'libgstrswebp',
'extra-deps': {'libwebpdemux': ''},
}}
endif
extra_env = {}
sodium_opt = get_option('sodium')
if sodium_opt.allowed()
sodium_plugin = {'sodium': {
'library': 'libgstsodium',
}}
if get_option('sodium-source') == 'system'
sodium_dep = dependency('libsodium', required: sodium_opt.enabled())
extra_env += {'SODIUM_USE_PKG_CONFIG': '1'}
if sodium_dep.found()
plugins += sodium_plugin
endif
else
plugins += sodium_plugin
endif
endif
cc = meson.get_compiler('c')
csound_option = get_option('csound')
if csound_option.allowed()
# if csound isn't distributed with pkg-config then user needs to define CSOUND_LIB_DIR with its location
res = run_command(python, '-c', 'import os; print(os.environ["CSOUND_LIB_DIR"])', check: false)
if res.returncode() == 0
csound_libdir = res.stdout().strip()
csound_dep = cc.find_library('csound64', dirs: csound_libdir, required: false)
if csound_dep.found()
plugins += {'csound': {
'library': 'libgstcsound',
}}
extra_env += {'CSOUND_LIB_DIR': csound_libdir}
elif csound_option.enabled()
error('csound option is enabled, but csound64 library could not be found and CSOUND_LIB_DIR was not set')
endif
endif
endif
# Process plugins list
default_library = get_option('default_library')
library_suffixes = []
if default_library in ['shared', 'both']
library_suffixes += [ext_dynamic]
endif
if default_library in ['static', 'both']
library_suffixes += [ext_static]
endif
# cargo packages (plugins) to build
packages = []
# Add the plugin library files as output
output = []
# Used to not lookup the same dependency multiple times which clutters logs
deps_cache = {}
foreach plugin_name, details: plugins
plugin_opt = get_option(plugin_name)
if plugin_opt.allowed()
plugin_deps_found = true
foreach dep_name, dep_ver: details.get('extra-deps', {})
if dep_ver != ''
dep = dependency(dep_name, version: dep_ver, required: plugin_opt)
else
dep = dependency(dep_name, required: plugin_opt)
endif
deps_cache += {dep_name: dep}
if not dep.found()
plugin_deps_found = false
endif
endforeach
if plugin_deps_found
packages += f'gst-plugin-@plugin_name@'
lib = details.get('library')
if default_library in ['shared', 'both']
output += [lib + '.' + ext_dynamic]
endif
if default_library in ['static', 'both']
output += [lib + '.' + ext_static]
endif
endif
endif
endforeach
# Need to depends on all gstreamer-rs deps to ensure they are built
# before gstreamer-rs when building with gst-build.
# Custom targets can't depend on dependency() objects so we have to depend
# on the library variable from the subproject instead.
gst_req = '>= 1.20.0'
depends = []
deps = [
# name, subproject name, subproject dep, library object
['gstreamer-1.0', 'gstreamer', 'gst_dep', 'libgst'],
['gstreamer-app-1.0', 'gst-plugins-base', 'app_dep', 'gstapp'],
['gstreamer-audio-1.0', 'gst-plugins-base', 'audio_dep', 'gstaudio'],
['gstreamer-base-1.0', 'gstreamer', 'gst_base_dep', 'gst_base'],
['gstreamer-check-1.0', 'gstreamer', 'gst_check_dep', 'gst_check'],
['gstreamer-net-1.0', 'gstreamer', 'gst_net_dep', 'gst_net'],
['gstreamer-rtp-1.0', 'gst-plugins-base', 'rtp_dep', 'gst_rtp'],
['gstreamer-video-1.0', 'gst-plugins-base', 'video_dep', 'gstvideo'],
['gstreamer-sdp-1.0', 'gst-plugins-base', 'sdp_dep', 'gstsdp'],
['gstreamer-webrtc-1.0', 'gst-plugins-bad', 'gstwebrtc_dep', 'gstwebrtc'],
]
foreach d: deps
dep = dependency(d[0], version : gst_req,
fallback : [d[1], d[2]])
set_variable(d[2], dep)
deps_cache += {d[0]: dep}
if dep.type_name() == 'internal'
lib = subproject(d[1]).get_variable(d[3])
depends += lib
endif
endforeach
include = ','.join(plugins.keys())
plugins_install_dir = get_option('libdir') / 'gstreamer-1.0'
pkgconfig_install_dir = get_option('libdir') / 'pkgconfig'
if get_option('doc').disabled()
disable_doc = ['--disable-doc']
else
disable_doc = []
endif
# 'pkgconfig' is the entry in the machine file, if specified
pkg_config = find_program('pkgconfig', required: false)
if pkg_config.found()
extra_env += {'PKG_CONFIG': pkg_config.full_path()}
endif
pkg_config_path = get_option('pkg_config_path')
if pkg_config_path.length() > 0
pathsep = ':'
if host_system == 'windows'
pathsep = ';'
endif
extra_env += {'PKG_CONFIG_PATH': pathsep.join(pkg_config_path)}
endif
rs_plugins = custom_target('gst-plugins-rs',
build_by_default: true,
output: output,
console: true,
install: true,
install_dir: plugins_install_dir,
depends: depends,
depfile: 'gst-plugins-rs.dep',
env: extra_env,
command: [cargo_wrapper,
'build',
meson.current_build_dir(),
meson.current_source_dir(),
meson.global_build_root(),
target,
get_option('prefix'),
get_option('libdir'),
'--packages', packages,
'--depfile', '@DEPFILE@',
'--lib-suffixes', library_suffixes,
] + disable_doc)
plugins = rs_plugins.to_list()
# This is used by GStreamer to static link Rust plugins into gst-full
gst_plugins = []
pc_files = []
plugin_names = []
foreach plugin : plugins
# skip the 'lib' prefix and extension from plugin path
plugin_name = fs.stem(plugin.full_path()).substring(3)
option_name = plugin_name.substring(3)
if option_name.startswith('rs')
option_name = option_name.substring(2)
endif
if option_name == 'flv'
option_name = 'flavors'
endif
if not get_option(option_name).allowed()
continue
endif
# Extract plugin dependencies from their Cargo.toml file
plugin_deps = []
p = run_command('dependencies.py', meson.current_source_dir(), plugin_name,
capture: true,
check: true)
foreach dep_name : p.stdout().strip().split(',')
dep_name_version = dep_name.split('|')
dep_name = dep_name_version.get(0).strip()
if dep_name_version.length() > 1
extras = {'version': dep_name_version.get(1).strip()}
else
extras = {}
endif
if deps_cache.has_key(dep_name)
plugin_deps += deps_cache[dep_name]
else
dep = dependency(dep_name, required: false, kwargs: extras)
plugin_deps += dep
deps_cache += {dep_name: dep}
endif
endforeach
dep = declare_dependency(
link_with: plugin,
dependencies: plugin_deps,
variables: {'full_path': plugin.full_path()},
)
meson.override_dependency(plugin_name, dep)
if default_library == 'static' and plugin_name in ['gstcsound', 'gstthreadshare', 'gstgtk4']
warning('Static plugin @0@ is known to fail. It will not be included in libgstreamer-full.'.format(plugin_name))
else
gst_plugins += dep
pc_files += [plugin_name + '.pc']
if plugin_name.startswith('gst')
plugin_names += [plugin_name.substring(3)]
else
plugin_names += [plugin_name]
endif
endif
endforeach
subdir('docs')
# We don't need to pass a command as we depends on the target above
# but it is currently mandatory ( https://github.com/mesonbuild/meson/issues/8059 )
# so use python as it's guaranteed to be present on any setup
custom_target('gst-plugins-rs-pc-files',
build_by_default: true,
output: pc_files,
console: true,
install: true,
install_dir: pkgconfig_install_dir,
depends: rs_plugins,
command: [python, '-c', '""'])
if get_option('webrtc').allowed()
custom_target('gst-webrtc-signalling-server',
build_by_default: true,
output: 'gst-webrtc-signalling-server',
console: true,
install: true,
install_dir: get_option('bindir'),
depfile: 'gst-webrtc-signalling-server.dep',
env: extra_env,
command: [cargo_wrapper,
'build',
meson.current_build_dir(),
meson.current_source_dir(),
meson.global_build_root(),
target,
get_option('prefix'),
get_option('libdir'),
'--depfile', '@DEPFILE@',
'--bin', 'gst-webrtc-signalling-server',
'--exe-suffix', exe_suffix,
])
endif
test('tests',
cargo_wrapper,
env: extra_env,
args: ['test',
meson.current_build_dir(),
meson.current_source_dir(),
meson.global_build_root(),
target,
get_option('prefix'),
get_option('libdir'),
'--packages', packages],
timeout: 600)
summary({
'Plugins': plugin_names,
}, list_sep: ', ')