diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 428e3b92..751a829d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -43,7 +43,7 @@ stages: .debian:11-stable: extends: .debian:11 variables: - FDO_DISTRIBUTION_TAG: '$GST_RS_STABLE-${GST_RS_IMG_TAG}_2022-07-19.0' + FDO_DISTRIBUTION_TAG: '$GST_RS_STABLE-${GST_RS_IMG_TAG}_2022-08-31.1' FDO_BASE_IMAGE: "registry.freedesktop.org/gstreamer/gstreamer-rs/debian/bullseye-slim:$GST_RS_STABLE-$GST_RS_IMG_TAG" .debian:11-msrv: @@ -63,11 +63,12 @@ stages: - .fdo.container-build@debian stage: prep variables: - FDO_DISTRIBUTION_PACKAGES: "libcsound64-dev llvm clang nasm libsodium-dev" + FDO_DISTRIBUTION_PACKAGES: "libcsound64-dev llvm clang nasm libsodium-dev libwebp-dev python3-pip" FDO_DISTRIBUTION_EXEC: >- bash ci/install-dav1d.sh && apt clean && - bash ./ci/install-rust-ext.sh + bash ./ci/install-rust-ext.sh && + pip install tomli rules: - if: '$UPDATE_IMG == null' @@ -216,6 +217,22 @@ gst-build: - if: $CI_PIPELINE_SOURCE == "merge_request_event" when: 'manual' allow_failure: true + variables: + MESON_ARGS: > + -Domx=disabled + -Dpython=disabled + -Dlibav=disabled + -Dlibnice=disabled + -Dugly=disabled + -Dbad=disabled + -Ddevtools=disabled + -Dges=disabled + -Drtsp_server=disabled + -Dvaapi=disabled + -Dsharp=disabled + -Dgst-examples=disabled + -Drs=enabled + -Dgst-plugins-rs:sodium=system script: - P=$(pwd) - cd .. @@ -223,13 +240,18 @@ gst-build: - git clone --depth 1 https://gitlab.freedesktop.org/gstreamer/gstreamer.git --branch main - cd gstreamer - ln -s $P subprojects/gst-plugins-rs - - meson build -Domx=disabled -Dpython=disabled -Dlibav=disabled -Dlibnice=disabled -Dugly=disabled -Dbad=disabled -Ddevtools=disabled -Dges=disabled -Drtsp_server=disabled -Dvaapi=disabled -Dsharp=disabled -Dgst-examples=disabled -Drs=enabled -Dgst-plugins-rs:sodium=system + - meson build $MESON_ARGS - ninja -C build + # Check static Rust plugins can be linked into gst-full + - meson build-gst-full --default-library=static $MESON_ARGS + - ninja -C build-gst-full + - meson devenv -C build-gst-full gst-inspect-1.0 rsaudiofx artifacts: expire_in: '7 days' when: always paths: - 'build/meson-logs/' + - 'build-gst-full/meson-logs/' rustfmt: extends: .img-stable diff --git a/dependencies.py b/dependencies.py new file mode 100755 index 00000000..85fa04cf --- /dev/null +++ b/dependencies.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +# Parse Cargo.toml files for each plugin to collect their external dependencies. +# Meson will lookup those dependencies using pkg-config to be able to link +# static Rust plugins into gst-full. + +from argparse import ArgumentParser +from pathlib import Path + +try: + # Python11 stdlib + import tomllib +except ImportError: + import tomli as tomllib + + +PARSER = ArgumentParser() +PARSER.add_argument('src_dir', type=Path) +PARSER.add_argument('plugins', nargs='*') + + +# Map plugin name to directory name, for those that does not match. +RENAMES = { + 'rsaudiofx': 'audiofx', + 'rsfile': 'file', + 'rsflv': 'flavors', + 'rstextwrap': 'wrap', + 'rsjson': 'json', + 'rsregex': 'regex', + 'rswebp': 'webp', + 'textahead': 'ahead', + 'rsonvif': 'onvif', + 'rstracers': 'tracers', + 'rsclosedcaption': 'closedcaption', + 'rsdav1d': 'dav1d', +} + + +if __name__ == "__main__": + opts = PARSER.parse_args() + + deps = set() + for p in opts.plugins: + assert p.startswith('gst') + name = p[3:] + name = RENAMES.get(name, name) + files = list(opts.src_dir.glob(f'**/{name}/Cargo.toml')) + assert len(files) == 1 + with files[0].open('rb') as f: + data = tomllib.load(f) + try: + requires = data['package']['metadata']['capi']['pkg_config']['requires_private'] + except KeyError: + continue + deps.update([i.strip() for i in requires.split(',')]) + print(','.join(deps)) diff --git a/meson.build b/meson.build index 0bbc8f0f..cf1d7977 100644 --- a/meson.build +++ b/meson.build @@ -5,6 +5,7 @@ project('gst-plugins-rs', meson_version : '>= 0.60') python = import('python').find_installation() +fs = import('fs') if get_option('debug') target = 'debug' @@ -137,12 +138,6 @@ if static_build or get_option('default_library') == 'both' endforeach endif -pc_files = [] -foreach p, lib : plugins - # skip the 'lib' prefix in plugin name - pc_files += [lib.substring(3) + '.pc'] -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 @@ -164,10 +159,14 @@ deps = [ ['gstreamer-webrtc-1.0', 'gst-plugins-bad', 'gstwebrtc_dep', 'gstwebrtc_dep'], ] +# Used to not lookup the same dependency multiple times which clutters logs +deps_cache = {} + 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 @@ -216,6 +215,38 @@ rs_plugins = custom_target('gst-plugins-rs', plugins = rs_plugins.to_list() +# This is used by GStreamer to static link Rust plugins into gst-full +gst_plugins = [] +pc_files = [] +foreach plugin : plugins + # skip the 'lib' prefix and extension from plugin path + plugin_name = fs.stem(plugin.full_path()).substring(3) + + # 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(',') + if deps_cache.has_key(dep_name) + plugin_deps += deps_cache[dep_name] + else + dep = dependency(dep_name, required: false) + 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) + gst_plugins += dep + pc_files += [plugin_name + '.pc'] +endforeach + subdir('docs') # We don't need to pass a command as we depends on the target above