From a3d405f670982eb9c904abb1d41df7e53072f27d Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Tue, 27 Dec 2022 23:55:16 +0530 Subject: [PATCH] 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: --- .gitlab-ci.yml | 6 +- cargo_wrapper.py | 17 +-- docs/meson.build | 2 +- meson.build | 318 ++++++++++++++++++++++++++++------------------ meson_options.txt | 71 +++++++++-- 5 files changed, 262 insertions(+), 152 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0c0f876c..ae034a8a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -255,7 +255,7 @@ meson shared: meson static: extends: .meson script: - - meson build --default-library=static --prefix=$(pwd)/install -Dsodium=built-in + - meson build --default-library=static --prefix=$(pwd)/install -Dsodium-source=built-in - ninja -C build install - ./ci/generate-static-test.py test-static-link-all - cd test-static-link-all @@ -284,7 +284,7 @@ documentation: -Dsharp=disabled -Dgst-examples=disabled -Drs=enabled - -Dgst-plugins-rs:sodium=system + -Dgst-plugins-rs:sodium-source=system -Dgst-docs:fatal_warnings=true -Dorc=disabled script: @@ -339,7 +339,7 @@ documentation: # -Dsharp=disabled # -Dgst-examples=disabled # -Drs=enabled -# -Dgst-plugins-rs:sodium=system +# -Dgst-plugins-rs:sodium-source=system # script: # - P=$(pwd) # - cd .. diff --git a/cargo_wrapper.py b/cargo_wrapper.py index 60885e16..a538f8cd 100644 --- a/cargo_wrapper.py +++ b/cargo_wrapper.py @@ -16,12 +16,13 @@ PARSER.add_argument('build_dir', type=P) PARSER.add_argument('src_dir', type=P) PARSER.add_argument('root_dir', type=P) PARSER.add_argument('target', choices=['release', 'debug']) -PARSER.add_argument('include') PARSER.add_argument('prefix', type=P) PARSER.add_argument('libdir', type=P) PARSER.add_argument('--version', default=None) PARSER.add_argument('--bin', default=None, type=P) -PARSER.add_argument('--exts', nargs="+", default=[]) +PARSER.add_argument('--packages', nargs="+", default=[]) +PARSER.add_argument('--lib-suffixes', nargs="+", default=[]) +PARSER.add_argument('--exe-suffix') PARSER.add_argument('--depfile') PARSER.add_argument('--disable-doc', action="store_true", default=False) @@ -102,7 +103,7 @@ if __name__ == "__main__": cargo_cmd.extend(['--manifest-path', opts.src_dir / 'Cargo.toml']) cargo_cmd.extend(['--prefix', opts.prefix, '--libdir', opts.prefix / opts.libdir]) - for p in opts.include.split(','): + for p in opts.packages: cargo_cmd.extend(['-p', p]) else: cargo_cmd.extend(['--bin', opts.bin.name]) @@ -119,18 +120,14 @@ if __name__ == "__main__": if opts.command == 'build': target_dir = cargo_target_dir / '**' / opts.target if opts.bin: - if opts.exts[0]: - ext = f'.{opts.exts[0]}' - else: - ext = '' - exe = glob.glob(str(target_dir / opts.bin) + ext, recursive=True)[0] + exe = glob.glob(str(target_dir / opts.bin) + opts.exe_suffix, recursive=True)[0] shutil.copy2(exe, opts.build_dir) depfile_content = generate_depfile_for(P(exe)) else: # Copy so files to build dir depfile_content = "" - for ext in opts.exts: - for f in glob.glob(str(target_dir / f'*.{ext}'), recursive=True): + for suffix in opts.lib_suffixes: + for f in glob.glob(str(target_dir / f'*.{suffix}'), recursive=True): libfile = P(f) depfile_content += generate_depfile_for(libfile) diff --git a/docs/meson.build b/docs/meson.build index 1d79a90a..69d5cbf7 100644 --- a/docs/meson.build +++ b/docs/meson.build @@ -9,7 +9,7 @@ if meson.is_cross_build() subdir_done() endif -if static_build +if default_library == 'static' if get_option('doc').enabled() error('Documentation enabled but not supported when building statically.') endif diff --git a/meson.build b/meson.build index e700d2ee..b7312e75 100644 --- a/meson.build +++ b/meson.build @@ -28,9 +28,9 @@ if not cargo_c.found() endif system = build_machine.system() -ext_exe = '' +exe_suffix = '' if system == 'windows' - ext_exe = 'exe' + exe_suffix = '.exe' ext_dynamic = 'dll' ext_static = 'lib' elif system == 'darwin' @@ -41,97 +41,131 @@ else ext_static = 'a' endif -# workspace name -> lib name # kept in the same order as the `members` list in Cargo.toml plugins = { - 'gst-plugin-audiofx': 'libgstrsaudiofx', - 'gst-plugin-claxon': 'libgstclaxon', - # csound has an external dependency, see below - 'gst-plugin-lewton': 'libgstlewton', - 'gst-plugin-spotify': 'libgstspotify', + 'audiofx': { + 'library': 'libgstrsaudiofx', + }, + 'claxon': {'library': 'libgstclaxon'}, + # csound has a non-trivial external dependency, see below + 'lewton': {'library': 'libgstlewton'}, + 'spotify': {'library': 'libgstspotify'}, - 'gst-plugin-file': 'libgstrsfile', - # sodium has an external dependency, see below - 'gst-plugin-threadshare': 'libgstthreadshare', + 'file': {'library': 'libgstrsfile'}, + # sodium can have an external dependency, see below + 'threadshare': { + 'library': 'libgstthreadshare', + }, - 'gst-plugin-mp4': 'libgstmp4', - 'gst-plugin-fmp4': 'libgstfmp4', + 'mp4': {'library': 'libgstmp4'}, + 'fmp4': { + 'library': 'libgstfmp4', + }, - 'gst-plugin-aws': 'libgstaws', - 'gst-plugin-hlssink3': 'libgsthlssink3', - 'gst-plugin-ndi': 'libgstndi', - 'gst-plugin-raptorq': 'libgstraptorq', - 'gst-plugin-reqwest': 'libgstreqwest', - 'gst-plugin-rtp': 'libgstrsrtp', - 'gst-plugin-webrtchttp': 'libgstwebrtchttp', - 'gst-plugin-webrtc': 'libgstrswebrtc', + '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', + }, - 'gst-plugin-textahead': 'libgsttextahead', - 'gst-plugin-json': 'libgstjson', - 'gst-plugin-regex': 'libgstregex', - 'gst-plugin-textwrap': 'libgsttextwrap', + 'textahead': {'library': 'libgsttextahead'}, + 'json': {'library': 'libgstjson'}, + 'regex': {'library': 'libgstregex'}, + 'textwrap': {'library': 'libgsttextwrap'}, - 'gst-plugin-fallbackswitch': 'libgstfallbackswitch', - 'gst-plugin-livesync': 'libgstlivesync', - 'gst-plugin-togglerecord': 'libgsttogglerecord', - 'gst-plugin-tracers': 'libgstrstracers', - 'gst-plugin-uriplaylistbin': 'libgsturiplaylistbin', + 'fallbackswitch': { + 'library': 'libgstfallbackswitch', + }, + 'livesync': { + 'library': 'libgstlivesync', + }, + 'togglerecord': { + 'library': 'libgsttogglerecord', + }, + 'tracers': {'library': 'libgstrstracers'}, + 'uriplaylistbin': { + 'library': 'libgsturiplaylistbin', + }, - 'gst-plugin-cdg': 'libgstcdg', - # closedcaption has an external dependency, see below - # dav1d has an external dependency, see below - 'gst-plugin-ffv1': 'libgstffv1', - 'gst-plugin-flavors': 'libgstrsflv', - 'gst-plugin-gif': 'libgstgif', - # gtk4 has an external dependency, see below - 'gst-plugin-hsv': 'libgsthsv', - 'gst-plugin-png': 'libgstrspng', - 'gst-plugin-rav1e': 'libgstrav1e', - # videofx has an external dependency, see below + '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 -# Remove this check once we update to a version that contains the fix: +# 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 += {'gst-plugin-webp': 'libgstrswebp'} + plugins += {'webp': { + 'library': 'libgstrswebp', + 'extra-deps': {'libwebpdemux': ''}, + }} endif extra_env = {} -if dependency('cairo-gobject', required : get_option('videofx')).found() - plugins += {'gst-plugin-videofx': 'libgstrsvideofx',} -endif - -if dependency('pangocairo', required : get_option('closedcaption')).found() - plugins += {'gst-plugin-closedcaption' : 'libgstrsclosedcaption',} -endif - -if dependency('pangocairo', required : get_option('onvif')).found() - plugins += {'gst-plugin-onvif': 'libgstrsonvif',} -endif - -if dependency('dav1d', version : '>= 1.0.0', required : get_option('dav1d')).found() - plugins += {'gst-plugin-dav1d' : 'libgstdav1d'} -endif - -sodium = get_option ('sodium') -if sodium == 'system' - dependency('libsodium') - plugins += {'gst-plugin-sodium': 'libgstsodium'} - extra_env += {'SODIUM_USE_PKG_CONFIG': '1'} -elif sodium == 'built-in' - plugins += {'gst-plugin-sodium': 'libgstsodium'} +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') -# try first to find csound using pkg-config -csound_dep = dependency('', required: false) -if not csound_dep.found() and not csound_option.disabled() +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) @@ -139,48 +173,70 @@ if not csound_dep.found() and not csound_option.disabled() 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 -if csound_dep.found() - plugins += {'gst-plugin-csound' : 'libgstcsound'} -elif csound_option.enabled() - error('csound option is enabled, but csound64 library could not be found and CSOUND_LIB_DIR was not set') -else - message('csound not found, disabling its plugin') -endif - -if dependency('gtk4', version: '>= 4.6.0', required : get_option('gtk4')).found() - plugins += {'gst-plugin-gtk4' : 'libgstgtk4',} +# 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 = {} -extensions = [] +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 -# Add the plugin file as output -if get_option('default_library') == 'shared' or get_option('default_library') == 'both' - extensions += [ext_dynamic] - foreach p, lib : plugins - output += [lib + '.' + ext_dynamic] - endforeach -endif -static_build = get_option('default_library') == 'static' -if static_build or get_option('default_library') == 'both' - extensions += [ext_static] - foreach p, lib : plugins - output += [lib + '.' + ext_static] - endforeach -endif # 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.18.0' +gst_req = '>= 1.20.0' depends = [] deps = [ @@ -197,9 +253,6 @@ deps = [ ['gstreamer-webrtc-1.0', 'gst-plugins-bad', 'gstwebrtc_dep', 'gstwebrtc'], ] -# 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]]) @@ -252,11 +305,11 @@ rs_plugins = custom_target('gst-plugins-rs', meson.current_source_dir(), meson.global_build_root(), target, - include, get_option('prefix'), get_option('libdir'), + '--packages', packages, '--depfile', '@DEPFILE@', - '--exts', extensions, + '--lib-suffixes', library_suffixes, ] + disable_doc) plugins = rs_plugins.to_list() @@ -269,6 +322,17 @@ 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, @@ -276,9 +340,9 @@ foreach plugin : plugins check: true) foreach dep_name : p.stdout().strip().split(',') dep_name_version = dep_name.split('|') - dep_name = dep_name_version.get(0) + dep_name = dep_name_version.get(0).strip() if dep_name_version.length() > 1 - extras = {'version': dep_name_version.get(1)} + extras = {'version': dep_name_version.get(1).strip()} else extras = {} endif @@ -298,7 +362,7 @@ foreach plugin : plugins ) meson.override_dependency(plugin_name, dep) - if static_build and plugin_name in ['gstcsound', 'gstthreadshare', 'gstgtk4'] + 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 @@ -326,28 +390,28 @@ custom_target('gst-plugins-rs-pc-files', depends: rs_plugins, command: [python, '-c', '""']) - -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@', - '--exts', ext_exe, - '--bin', 'gst-webrtc-signalling-server' - ]) +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, @@ -357,9 +421,9 @@ test('tests', meson.current_source_dir(), meson.global_build_root(), target, - include, get_option('prefix'), - get_option('libdir')], + get_option('libdir'), + '--packages', packages], timeout: 600) summary({ diff --git a/meson_options.txt b/meson_options.txt index b20fd937..a2d62a61 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -1,13 +1,62 @@ -option('videofx', type : 'feature', value : 'auto', description : 'Build videofx plugin') -option('closedcaption', type : 'feature', value : 'auto', description : 'Build closedcaption plugin') -option('onvif', type : 'feature', value : 'auto', description : 'Build onvif plugin') -option('dav1d', type : 'feature', value : 'auto', description : 'Build dav1d plugin') -option('sodium', type : 'combo', - choices : ['system', 'built-in', 'disabled'], value : 'built-in', - description : 'Weither to use libsodium from the system or the built-in version from the sodiumoxide crate') -option('csound', type : 'feature', value : 'auto', description : 'Build csound plugin') -option('gtk4', type : 'feature', value : 'auto', description : 'Build GTK4 plugin') +# Same order as members in Cargo.toml + +# audio +option('audiofx', type: 'feature', value: 'auto', description: 'Build audiofx plugin') +option('claxon', type: 'feature', value: 'auto', description: 'Build claxon plugin') +option('csound', type: 'feature', value: 'auto', description: 'Build csound plugin') +option('lewton', type: 'feature', value: 'auto', description: 'Build lewton plugin') +option('spotify', type: 'feature', value: 'auto', description: 'Build spotify plugin') + +# generic +option('file', type: 'feature', value: 'auto', description: 'Build file plugin') +option('sodium', type: 'feature', value: 'auto', description: 'Build sodium plugin') +option('sodium-source', type: 'combo', + choices: ['system', 'built-in'], value: 'built-in', + description: 'Whether to use libsodium from the system or the built-in version from the sodiumoxide crate') +option('threadshare', type: 'feature', value: 'auto', description: 'Build threadshare plugin') + +# mux +option('flavors', type: 'feature', value: 'auto', description: 'Build flavors plugin') +option('fmp4', type: 'feature', value: 'auto', description: 'Build fmp4 plugin') +option('mp4', type: 'feature', value: 'auto', description: 'Build mp4 plugin') + +# net +option('aws', type: 'feature', value: 'auto', description: 'Build aws plugin') +option('hlssink3', type: 'feature', value: 'auto', description: 'Build hlssink3 plugin') +option('ndi', type: 'feature', value: 'auto', description: 'Build ndi plugin') +option('onvif', type: 'feature', value: 'auto', description: 'Build onvif plugin') +option('raptorq', type: 'feature', value: 'auto', description: 'Build raptorq plugin') +option('reqwest', type: 'feature', value: 'auto', description: 'Build reqwest plugin') +option('rtp', type: 'feature', value: 'auto', description: 'Build rtp plugin') +option('webrtc', type: 'feature', value: 'auto', description: 'Build webrtc plugin') +option('webrtchttp', type: 'feature', value: 'auto', description: 'Build webrtchttp plugin') + +# text +option('textahead', type: 'feature', value: 'auto', description: 'Build textahead plugin') +option('json', type: 'feature', value: 'auto', description: 'Build json plugin') +option('regex', type: 'feature', value: 'auto', description: 'Build regex plugin') +option('textwrap', type: 'feature', value: 'auto', description: 'Build textwrap plugin') + +# utils +option('fallbackswitch', type: 'feature', value: 'auto', description: 'Build fallbackswitch plugin') +option('livesync', type: 'feature', value: 'auto', description: 'Build livesync plugin') +option('togglerecord', type: 'feature', value: 'auto', description: 'Build togglerecord plugin') +option('tracers', type: 'feature', value: 'auto', description: 'Build tracers plugin') +option('uriplaylistbin', type: 'feature', value: 'auto', description: 'Build uriplaylistbin plugin') + +# video +option('cdg', type: 'feature', value: 'auto', description: 'Build cdg plugin') +option('closedcaption', type: 'feature', value: 'auto', description: 'Build closedcaption plugin') +option('dav1d', type: 'feature', value: 'auto', description: 'Build dav1d plugin') +option('ffv1', type: 'feature', value: 'auto', description: 'Build ffv1 plugin') +option('gif', type: 'feature', value: 'auto', description: 'Build gif plugin') +option('gtk4', type: 'feature', value: 'auto', description: 'Build GTK4 plugin') +option('hsv', type: 'feature', value: 'auto', description: 'Build hsv plugin') +option('png', type: 'feature', value: 'auto', description: 'Build png plugin') +option('rav1e', type: 'feature', value: 'auto', description: 'Build rav1e plugin') +option('videofx', type: 'feature', value: 'auto', description: 'Build videofx plugin') +option('webp', type: 'feature', value: 'auto', description: 'Build webp plugin') # Common options -option('doc', type : 'feature', value : 'auto', yield: true, - description: 'Enable documentation.') +option('doc', type: 'feature', value: 'auto', yield: true, + description: 'Enable documentation')