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: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6159>
This commit is contained in:
Nirbheek Chauhan 2024-02-21 09:54:22 +05:30 committed by GStreamer Marge Bot
parent ad8ea38e0a
commit 2cc9a181f9
3 changed files with 108 additions and 84 deletions

View file

@ -566,10 +566,8 @@ load_python_formatters (void)
"_Py_NoneStruct", &has_python) && has_python) { "_Py_NoneStruct", &has_python) && has_python) {
GST_LOG ("libpython is already loaded"); GST_LOG ("libpython is already loaded");
} else { } else {
const gchar *libpython_path = GST_LOG ("loading libpython by name: %s", PY_LIB_FNAME);
PY_LIB_LOC "/libpython" PYTHON_VERSION PY_ABI_FLAGS "." PY_LIB_SUFFIX; libpython = g_module_open (PY_LIB_FNAME, 0);
GST_LOG ("loading libpython from '%s'", libpython_path);
libpython = g_module_open (libpython_path, 0);
if (!libpython) { if (!libpython) {
GST_ERROR ("Couldn't g_module_open libpython. Reason: %s", GST_ERROR ("Couldn't g_module_open libpython. Reason: %s",
g_module_error ()); g_module_error ());

View file

@ -144,73 +144,79 @@ gir_init_section = [ '--add-init-section=' + \
'ges_init();', '--quiet'] 'ges_init();', '--quiet']
pymod = import('python') 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 has_python = false
static_build = get_option('default_library') == 'static' static_build = get_option('default_library') == 'static'
if static_build 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') error('Want to build python based modules but it is not supported while static building')
else else
message('Disabling python support as it is not supported on static builds') message('Disabling python support as it is not supported on static builds')
endif endif
elif build_gir elif build_gir and python.found()
if python.found() python_dep = python.dependency(required : python_opt, embed: true,
# Workaround for https://github.com/mesonbuild/meson/issues/5629 include_type: 'system')
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
if python_dep.found() if python_dep.found()
python_abi_flags = python.get_variable('ABIFLAGS', '') python_abi_flags = python.get_variable('ABIFLAGS', '')
message(f'python_abi_flags = @python_abi_flags@')
pylib_loc = get_option('libpython-dir') pylib_loc = get_option('libpython-dir')
error_msg = '' error_msg = ''
if not cc.compiles('#include <Python.h>', dependencies: [python_dep]) if not cc.compiles('#include <Python.h>', dependencies: [python_dep])
error_msg = 'Could not compile a simple program against python' error_msg = 'Could not compile a simple program against python'
elif pylib_loc == '' if python_opt.enabled()
fsmod = import('fs') error(error_msg)
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()))
else else
if get_option('python').enabled() message(error_msg)
error(error_msg) endif
else endif
message(error_msg) fsmod = import('fs')
endif 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 endif
endif endif

View file

@ -10,6 +10,8 @@ version_arr = gst_version.split('.')
gst_version_major = version_arr[0] gst_version_major = version_arr[0]
gst_version_minor = version_arr[1] gst_version_minor = version_arr[1]
api_version = '@0@.0'.format(gst_version_major) 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') add_project_arguments('-DHAVE_CONFIG_H', language: 'c')
@ -33,30 +35,58 @@ if pythonver.version_compare('<3.7')
endif endif
python_dep = python.dependency(embed:true, required : true) python_dep = python.dependency(embed: true, required: true)
python_abi_flags = python.get_variable('ABIFLAGS', '') python_abi_flags = python.get_variable('ABIFLAGS', '')
message(f'python_abi_flags = @python_abi_flags@')
pylib_loc = get_option('libpython-dir') pylib_loc = get_option('libpython-dir')
if pylib_loc == '' fsmod = import('fs')
fsmod = import('fs') pylib_prefix = 'lib'
pylib_loc = python.get_variable('LIBPL', '') pylib_suffix = 'so'
if host_machine.system() != 'windows' and host_machine.system() != 'darwin' if host_system == 'windows'
pylib_ldlibrary = python.get_variable('LDLIBRARY', '') if cc.get_argument_syntax() == 'msvc'
if not fsmod.exists(pylib_loc / pylib_ldlibrary) pylib_prefix = ''
# Workaround for Fedora endif
pylib_loc = python.get_variable('LIBDIR', '') pylib_suffix = 'dll'
message('pylib_loc = @0@'.format(pylib_loc)) elif host_system == 'darwin'
endif pylib_suffix = 'dylib'
endif
if not fsmod.exists(pylib_loc / pylib_ldlibrary) pylib_fnames = []
error('Python dynamic library path could not be determined') # 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 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
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') pygi_override_dir = get_option('pygi-overrides-dir')
if pygi_override_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 has to be built from pieces.
libdir = get_option('prefix')+'/'+get_option('libdir') 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 = configuration_data()
cdata.set('PACKAGE', '"gst-python"') cdata.set('PACKAGE', '"gst-python"')
cdata.set('VERSION', '"@0@"'.format(gst_version)) 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('PACKAGE_NAME', '"GStreamer Python"')
cdata.set('GST_API_VERSION', '"@0@"'.format(api_version)) cdata.set('GST_API_VERSION', '"@0@"'.format(api_version))
cdata.set('PLUGINDIR', '"@0@/gstreamer-1.0"'.format(libdir)) cdata.set('PLUGINDIR', '"@0@/gstreamer-1.0"'.format(libdir))
cdata.set('PY_LIB_LOC', '"@0@"'.format(pylib_loc)) cdata.set_quoted('PY_LIB_FNAME', pylib_fname)
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()))
configure_file(output : 'config.h', configuration : cdata) configure_file(output : 'config.h', configuration : cdata)
configinc = include_directories('.') configinc = include_directories('.')