From 2cc9a181f9f39ac8db08a99e84a3fcdaa628d0e2 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Wed, 21 Feb 2024 09:54:22 +0530 Subject: [PATCH] ges, gst-python: Rework libpython loading to be relocatable If we don't specify a path for loading, the runtime linker will search for the library instead, which will use the usual mechanisms: RPATHs, LD_LIBRARY_PATH, PATH (on Windows), etc. Also try harder to load a non-devel libpython using INSTSONAME, if available. Part-of: --- .../gst-editing-services/ges/ges-formatter.c | 6 +- subprojects/gst-editing-services/meson.build | 110 +++++++++--------- subprojects/gst-python/meson.build | 76 +++++++----- 3 files changed, 108 insertions(+), 84 deletions(-) diff --git a/subprojects/gst-editing-services/ges/ges-formatter.c b/subprojects/gst-editing-services/ges/ges-formatter.c index c5b39eb2de..0db4f94684 100644 --- a/subprojects/gst-editing-services/ges/ges-formatter.c +++ b/subprojects/gst-editing-services/ges/ges-formatter.c @@ -566,10 +566,8 @@ load_python_formatters (void) "_Py_NoneStruct", &has_python) && has_python) { GST_LOG ("libpython is already loaded"); } else { - const gchar *libpython_path = - PY_LIB_LOC "/libpython" PYTHON_VERSION PY_ABI_FLAGS "." PY_LIB_SUFFIX; - GST_LOG ("loading libpython from '%s'", libpython_path); - libpython = g_module_open (libpython_path, 0); + GST_LOG ("loading libpython by name: %s", PY_LIB_FNAME); + libpython = g_module_open (PY_LIB_FNAME, 0); if (!libpython) { GST_ERROR ("Couldn't g_module_open libpython. Reason: %s", g_module_error ()); diff --git a/subprojects/gst-editing-services/meson.build b/subprojects/gst-editing-services/meson.build index 13af8ec3e8..3f91dd45c9 100644 --- a/subprojects/gst-editing-services/meson.build +++ b/subprojects/gst-editing-services/meson.build @@ -144,73 +144,79 @@ gir_init_section = [ '--add-init-section=' + \ 'ges_init();', '--quiet'] pymod = import('python') -python = pymod.find_installation(required: get_option('python')) +python_opt = get_option('python') +python = pymod.find_installation(required: python_opt) has_python = false static_build = get_option('default_library') == 'static' if static_build - if get_option('python').enabled() + if python_opt.enabled() error('Want to build python based modules but it is not supported while static building') else message('Disabling python support as it is not supported on static builds') endif -elif build_gir - if python.found() - # Workaround for https://github.com/mesonbuild/meson/issues/5629 - pythonver = python.language_version() - python_dep = dependency('python-@0@-embed'.format(pythonver), version: '>=3', - required: false, include_type: 'system') - if not python_dep.found() - python_dep = python.dependency(required : get_option('python'), - include_type: 'system') - endif - else - python_dep = dependency('', required: false) - endif +elif build_gir and python.found() + python_dep = python.dependency(required : python_opt, embed: true, + include_type: 'system') if python_dep.found() python_abi_flags = python.get_variable('ABIFLAGS', '') + message(f'python_abi_flags = @python_abi_flags@') pylib_loc = get_option('libpython-dir') error_msg = '' if not cc.compiles('#include ', dependencies: [python_dep]) error_msg = 'Could not compile a simple program against python' - elif pylib_loc == '' - fsmod = import('fs') - pylib_loc = python.get_variable('LIBPL', '') - if host_system != 'windows' and host_system != 'darwin' - pylib_ldlibrary = python.get_variable('LDLIBRARY', '') - if not fsmod.exists(pylib_loc / pylib_ldlibrary) - # Workaround for Fedora - pylib_loc = python.get_variable('LIBDIR', '') - message('pylib_loc = @0@'.format(pylib_loc)) - endif - - if not fsmod.exists(pylib_loc / pylib_ldlibrary) - error_msg = '@0@ doesn\' exist, can\'t use python'.format(join_paths(pylib_loc, pylib_ldlibrary)) - endif - endif - if error_msg == '' - pylib_suffix = 'so' - if host_system == 'windows' - pylib_suffix = 'dll' - elif host_system == 'darwin' - pylib_suffix = 'dylib' - endif - - libges_deps = libges_deps + [python_dep, gmodule_dep] - has_python = true - message('python_abi_flags = @0@'.format(python_abi_flags)) - message('pylib_loc = @0@'.format(pylib_loc)) - cdata.set('HAS_PYTHON', true) - cdata.set('PY_LIB_LOC', '"@0@"'.format(pylib_loc)) - cdata.set('PY_ABI_FLAGS', '"@0@"'.format(python_abi_flags)) - cdata.set('PY_LIB_SUFFIX', '"@0@"'.format(pylib_suffix)) - cdata.set('PYTHON_VERSION', '"@0@"'.format(python_dep.version())) + if python_opt.enabled() + error(error_msg) else - if get_option('python').enabled() - error(error_msg) - else - message(error_msg) - endif + message(error_msg) + endif + endif + fsmod = import('fs') + pylib_prefix = 'lib' + pylib_suffix = 'so' + if host_system == 'windows' + if cc.get_argument_syntax() == 'msvc' + pylib_prefix = '' + endif + pylib_suffix = 'dll' + elif host_system == 'darwin' + pylib_suffix = 'dylib' + endif + pylib_fnames = [] + # Library name with soversion, non-devel package + pylib_fnames += python.get_variable('INSTSONAME', []) + # Library name without soversion, devel package, framework, etc. + pylib_fnames += python.get_variable('LDLIBRARY', []) + # Manually construct name as a fallback + pylib_fnames += [ + pylib_prefix + 'python' + python_dep.version() + python_abi_flags + '.' + pylib_suffix + ] + if pylib_loc != '' + pylib_locs = [pylib_loc] + else + pylib_locs = [ + python.get_variable('LIBDIR', ''), + python.get_variable('LIBPL', ''), + ] + endif + foreach loc: pylib_locs + foreach fname: pylib_fnames + if fsmod.exists(loc / fname) + libges_deps = libges_deps + [python_dep, gmodule_dep] + has_python = true + cdata.set('HAS_PYTHON', true) + cdata.set_quoted('PY_LIB_FNAME', fname) + message(f'PY_LIB_FNAME = @fname@ (@loc@)') + break + endif + endforeach + endforeach + if not has_python + error_msg = 'Could not find python library to load' + if python_opt.enabled() + error(error_msg) + else + message(error_msg) endif endif endif diff --git a/subprojects/gst-python/meson.build b/subprojects/gst-python/meson.build index 3eb2d7dfab..432b3475b9 100644 --- a/subprojects/gst-python/meson.build +++ b/subprojects/gst-python/meson.build @@ -10,6 +10,8 @@ version_arr = gst_version.split('.') gst_version_major = version_arr[0] gst_version_minor = version_arr[1] api_version = '@0@.0'.format(gst_version_major) +host_system = host_machine.system() +cc = meson.get_compiler('c') add_project_arguments('-DHAVE_CONFIG_H', language: 'c') @@ -33,30 +35,58 @@ if pythonver.version_compare('<3.7') endif -python_dep = python.dependency(embed:true, required : true) +python_dep = python.dependency(embed: true, required: true) python_abi_flags = python.get_variable('ABIFLAGS', '') +message(f'python_abi_flags = @python_abi_flags@') pylib_loc = get_option('libpython-dir') -if pylib_loc == '' - fsmod = import('fs') - pylib_loc = python.get_variable('LIBPL', '') - if host_machine.system() != 'windows' and host_machine.system() != 'darwin' - pylib_ldlibrary = python.get_variable('LDLIBRARY', '') - if not fsmod.exists(pylib_loc / pylib_ldlibrary) - # Workaround for Fedora - pylib_loc = python.get_variable('LIBDIR', '') - message('pylib_loc = @0@'.format(pylib_loc)) - endif - - if not fsmod.exists(pylib_loc / pylib_ldlibrary) - error('Python dynamic library path could not be determined') +fsmod = import('fs') +pylib_prefix = 'lib' +pylib_suffix = 'so' +if host_system == 'windows' + if cc.get_argument_syntax() == 'msvc' + pylib_prefix = '' + endif + pylib_suffix = 'dll' +elif host_system == 'darwin' + pylib_suffix = 'dylib' +endif +pylib_fnames = [] +# Library name with soversion, non-devel package +pylib_fnames += python.get_variable('INSTSONAME', []) +# Library name without soversion, devel package, framework, etc. +pylib_fnames += python.get_variable('LDLIBRARY', []) +# Manually construct name as a fallback +pylib_fnames += [ + pylib_prefix + 'python' + python_dep.version() + python_abi_flags + '.' + pylib_suffix +] +if pylib_loc != '' + pylib_locs = [pylib_loc] +else + pylib_locs = [ + python.get_variable('LIBDIR', ''), + python.get_variable('LIBPL', ''), + ] +endif +pylib_fname = '' +foreach loc: pylib_locs + foreach fname: pylib_fnames + if fsmod.exists(loc / fname) + pylib_fname = fname + message(f'PY_LIB_FNAME = @fname@ (@loc@)') + break endif + endforeach +endforeach +if pylib_fname == '' + error_msg = 'Could not find python library to load' + if python_opt.enabled() + error(error_msg) + else + message(error_msg) endif endif -message('python_abi_flags = @0@'.format(python_abi_flags)) -message('pylib_loc = @0@'.format(pylib_loc)) - pygi_override_dir = get_option('pygi-overrides-dir') if pygi_override_dir == '' @@ -71,13 +101,6 @@ message('pygobject overrides directory = @0@'.format(pygi_override_dir)) # libdir has to be built from pieces. libdir = get_option('prefix')+'/'+get_option('libdir') - -pylib_suffix = 'so' -if host_machine.system() == 'windows' - pylib_suffix = 'dll' -elif host_machine.system() == 'darwin' - pylib_suffix = 'dylib' -endif cdata = configuration_data() cdata.set('PACKAGE', '"gst-python"') cdata.set('VERSION', '"@0@"'.format(gst_version)) @@ -85,10 +108,7 @@ cdata.set('GST_PACKAGE_NAME', '"GStreamer Python"') cdata.set('PACKAGE_NAME', '"GStreamer Python"') cdata.set('GST_API_VERSION', '"@0@"'.format(api_version)) cdata.set('PLUGINDIR', '"@0@/gstreamer-1.0"'.format(libdir)) -cdata.set('PY_LIB_LOC', '"@0@"'.format(pylib_loc)) -cdata.set('PY_ABI_FLAGS', '"@0@"'.format(python_abi_flags)) -cdata.set('PY_LIB_SUFFIX', '"@0@"'.format(pylib_suffix)) -cdata.set('PYTHON_VERSION', '"@0@"'.format(python_dep.version())) +cdata.set_quoted('PY_LIB_FNAME', pylib_fname) configure_file(output : 'config.h', configuration : cdata) configinc = include_directories('.')