X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=gst-env.py;h=c64042d92bd706adbad45b073b74cc610f3db311;hb=fb4be45e6f9ae9edb69614c6e4f04e0a7376520f;hp=775a41852bc38ffaecd103a00084cdcb1ea0c32d;hpb=84e01411e41625f2f905c584e9dd31b8fb42614e;p=platform%2Fupstream%2Fgstreamer.git diff --git a/gst-env.py b/gst-env.py index 775a418..c64042d 100755 --- a/gst-env.py +++ b/gst-env.py @@ -15,7 +15,8 @@ import sys import tempfile import pathlib import signal -from pathlib import PurePath +from functools import lru_cache +from pathlib import PurePath, Path from distutils.sysconfig import get_python_lib from distutils.util import strtobool @@ -27,10 +28,12 @@ from scripts.common import get_wine_shortpath SCRIPTDIR = os.path.dirname(os.path.realpath(__file__)) PREFIX_DIR = os.path.join(SCRIPTDIR, 'prefix') -# Use '_build' as the builddir instead of 'build' +# Look for the following build dirs: `build` `_build` `builddir` DEFAULT_BUILDDIR = os.path.join(SCRIPTDIR, 'build') if not os.path.exists(DEFAULT_BUILDDIR): DEFAULT_BUILDDIR = os.path.join(SCRIPTDIR, '_build') +if not os.path.exists(DEFAULT_BUILDDIR): + DEFAULT_BUILDDIR = os.path.join(SCRIPTDIR, 'builddir') TYPELIB_REG = re.compile(r'.*\.typelib$') SHAREDLIB_REG = re.compile(r'\.so|\.dylib|\.dll') @@ -40,6 +43,18 @@ SHAREDLIB_REG = re.compile(r'\.so|\.dylib|\.dll') GSTPLUGIN_FILEPATH_REG_TEMPLATE = r'.*/{libdir}/gstreamer-1.0/[^/]+$' GSTPLUGIN_FILEPATH_REG = None +BC_RC = ''' +BASH_COMPLETION_SCRIPTS="{bash_completions}" +BASH_COMPLETION_PATHS="{bash_completions_paths}" +for p in $BASH_COMPLETION_PATHS; do +for f in $BASH_COMPLETION_SCRIPTS; do + [ -f "$p/$f" ] && . "$p/$f" +done +done +''' +BASH_COMPLETION_PATHS = [SCRIPTDIR + '/subprojects/gstreamer/data/bash-completion/completions'] +BASH_COMPLETION_PATHS += [SCRIPTDIR + '/subprojects/gst-devtools/validate/data/bash-completion/completions'] + def listify(o): if isinstance(o, str): return [o] @@ -57,6 +72,8 @@ def stringify(o): raise AssertionError('Object {!r} must be a string or a list'.format(o)) def prepend_env_var(env, var, value, sysroot): + if var is None: + return if value.startswith(sysroot): value = value[len(sysroot):] # Try not to exceed maximum length limits for env vars on Windows @@ -70,28 +87,72 @@ def prepend_env_var(env, var, value, sysroot): env[var] = val + env_val env[var] = env[var].replace(os.pathsep + os.pathsep, os.pathsep).strip(os.pathsep) +def get_target_install_filename(target, filename): + ''' + Checks whether this file is one of the files installed by the target + ''' + basename = os.path.basename(filename) + for install_filename in listify(target['install_filename']): + if install_filename.endswith(basename): + return install_filename + return None + +def get_pkgconfig_variable_from_pcfile(pcfile, varname): + variables = {} + substre = re.compile('\$\{[^${}]+\}') + with pcfile.open('r', encoding='utf-8') as f: + for line in f: + if '=' not in line: + continue + key, value = line[:-1].split('=', 1) + subst = {} + for each in substre.findall(value): + substkey = each[2:-1] + subst[each] = variables.get(substkey, '') + for k, v in subst.items(): + value = value.replace(k, v) + variables[key] = value + return variables.get(varname, '') + +@lru_cache() +def get_pkgconfig_variable(builddir, pcname, varname): + ''' + Parsing isn't perfect, but it's good enough. + ''' + pcfile = Path(builddir) / 'meson-private' / (pcname + '.pc') + if pcfile.is_file(): + return get_pkgconfig_variable_from_pcfile(pcfile, varname) + return subprocess.check_output(['pkg-config', pcname, '--variable=' + varname], + universal_newlines=True, encoding='utf-8') + + +def is_gio_module(target, filename, builddir): + if target['type'] != 'shared module': + return False + install_filename = get_target_install_filename(target, filename) + if not install_filename: + return False + giomoduledir = PurePath(get_pkgconfig_variable(builddir, 'gio-2.0', 'giomoduledir')) + fpath = PurePath(install_filename) + if fpath.parent != giomoduledir: + return False + return True + def is_library_target_and_not_plugin(target, filename): ''' Don't add plugins to PATH/LD_LIBRARY_PATH because: 1. We don't need to 2. It causes us to exceed the PATH length limit on Windows and Wine ''' - if not target['type'].startswith('shared'): - return False - if not target['installed']: + if target['type'] != 'shared library': return False # Check if this output of that target is a shared library if not SHAREDLIB_REG.search(filename): return False # Check if it's installed to the gstreamer plugin location - for install_filename in listify(target['install_filename']): - if install_filename.endswith(os.path.basename(filename)): - break - else: - # None of the installed files in the target correspond to the built - # filename, so skip + install_filename = get_target_install_filename(target, filename) + if not install_filename: return False - global GSTPLUGIN_FILEPATH_REG if GSTPLUGIN_FILEPATH_REG is None: GSTPLUGIN_FILEPATH_REG = re.compile(GSTPLUGIN_FILEPATH_REG_TEMPLATE) @@ -102,15 +163,9 @@ def is_library_target_and_not_plugin(target, filename): def is_binary_target_and_in_path(target, filename, bindir): if target['type'] != 'executable': return False - if not target['installed']: - return False # Check if this file installed by this target is installed to bindir - for install_filename in listify(target['install_filename']): - if install_filename.endswith(os.path.basename(filename)): - break - else: - # None of the installed files in the target correspond to the built - # filename, so skip + install_filename = get_target_install_filename(target, filename) + if not install_filename: return False fpath = PurePath(install_filename) if fpath.parent != bindir: @@ -137,27 +192,35 @@ def get_wine_subprocess_env(options, env): return env def setup_gdb(options): - bdir = os.path.realpath(options.builddir) python_paths = set() + + if not shutil.which('gdb'): + return python_paths + + bdir = pathlib.Path(options.builddir).resolve() for libpath, gdb_path in [ - ("subprojects/gstreamer/gst/", "subprojects/gstreamer/libs/gst/helpers/"), - ("subprojects/glib/gobject", None), - ("subprojects/glib/glib", None)]: + (os.path.join("subprojects", "gstreamer", "gst"), + os.path.join("subprojects", "gstreamer", "libs", "gst", "helpers")), + (os.path.join("subprojects", "glib", "gobject"), None), + (os.path.join("subprojects", "glib", "glib"), None)]: if not gdb_path: gdb_path = libpath - autoload_path = os.path.join(bdir, "gdb-auto-load/", bdir[1:], libpath) - os.makedirs(autoload_path, exist_ok=True) - for gdb_helper in glob.glob(os.path.join(bdir, gdb_path, "*-gdb.py")): - python_paths.add(os.path.join(bdir, gdb_path)) + autoload_path = (pathlib.Path(bdir) / 'gdb-auto-load').joinpath(*bdir.parts[1:]) / libpath + autoload_path.mkdir(parents=True, exist_ok=True) + for gdb_helper in glob.glob(str(bdir / gdb_path / "*-gdb.py")): + python_paths.add(str(bdir / gdb_path)) python_paths.add(os.path.join(options.srcdir, gdb_path)) try: - os.symlink(gdb_helper, os.path.join(autoload_path, os.path.basename(gdb_helper))) - except FileExistsError: + if os.name == 'nt': + shutil.copy(gdb_helper, str(autoload_path / os.path.basename(gdb_helper))) + else: + os.symlink(gdb_helper, str(autoload_path / os.path.basename(gdb_helper))) + except (FileExistsError, shutil.SameFileError): pass - gdbinit_line = 'add-auto-load-scripts-directory %s' % os.path.join(bdir, 'gdb-auto-load\n') + gdbinit_line = 'add-auto-load-scripts-directory {}\n'.format(bdir / 'gdb-auto-load') try: with open(os.path.join(options.srcdir, '.gdbinit'), 'r') as f: if gdbinit_line in f.readlines(): @@ -170,24 +233,35 @@ def setup_gdb(options): return python_paths +def is_bash_completion_available (options): + return os.path.exists(os.path.join(options.builddir, 'subprojects/gstreamer/data/bash-completion/helpers/gst')) def get_subprocess_env(options, gst_version): env = os.environ.copy() env["CURRENT_GST"] = os.path.normpath(SCRIPTDIR) env["GST_VERSION"] = gst_version - env["GST_VALIDATE_SCENARIOS_PATH"] = os.path.normpath( - "%s/subprojects/gst-devtools/validate/data/scenarios" % SCRIPTDIR) + prepend_env_var (env, "GST_VALIDATE_SCENARIOS_PATH", os.path.normpath( + "%s/subprojects/gst-devtools/validate/data/scenarios" % SCRIPTDIR), + options.sysroot) env["GST_VALIDATE_PLUGIN_PATH"] = os.path.normpath( "%s/subprojects/gst-devtools/validate/plugins" % options.builddir) - env["GST_VALIDATE_APPS_DIR"] = os.path.normpath( - "%s/subprojects/gst-editing-services/tests/validate" % SCRIPTDIR) + prepend_env_var (env, "GST_VALIDATE_APPS_DIR", os.path.normpath( + "%s/subprojects/gst-editing-services/tests/validate" % SCRIPTDIR), + options.sysroot) env["GST_ENV"] = 'gst-' + gst_version env["GST_REGISTRY"] = os.path.normpath(options.builddir + "/registry.dat") prepend_env_var(env, "PATH", os.path.normpath( "%s/subprojects/gst-devtools/validate/tools" % options.builddir), options.sysroot) + prepend_env_var (env, "GST_VALIDATE_SCENARIOS_PATH", os.path.normpath( + "%s/subprojects/gst-examples/webrtc/check/validate/scenarios" % + SCRIPTDIR), options.sysroot) + prepend_env_var (env, "GST_VALIDATE_APPS_DIR", os.path.normpath( + "%s/subprojects/gst-examples/webrtc/check/validate/apps" % + SCRIPTDIR), options.sysroot) + if options.wine: return get_wine_subprocess_env(options, env) @@ -203,7 +277,8 @@ def get_subprocess_env(options, gst_version): if os.name == 'nt': lib_path_envvar = 'PATH' elif platform.system() == 'Darwin': - lib_path_envvar = 'DYLD_LIBRARY_PATH' + # RPATH is sufficient on macOS, and DYLD_LIBRARY_PATH can cause issues with dynamic linker path priority + lib_path_envvar = None else: lib_path_envvar = 'LD_LIBRARY_PATH' @@ -227,7 +302,7 @@ def get_subprocess_env(options, gst_version): options.sysroot) # gst-indent - prepend_env_var(env, "PATH", os.path.join(SCRIPTDIR, 'gstreamer', 'tools'), + prepend_env_var(env, "PATH", os.path.join(SCRIPTDIR, 'scripts'), options.sysroot) # tools: gst-launch-1.0, gst-inspect-1.0 @@ -272,6 +347,8 @@ def get_subprocess_env(options, gst_version): for target in targets: filenames = listify(target['filename']) + if not target['installed']: + continue for filename in filenames: root = os.path.dirname(filename) if srcdir_path / "subprojects/gst-devtools/validate/plugins" in (srcdir_path / root).parents: @@ -288,23 +365,28 @@ def get_subprocess_env(options, gst_version): options.sysroot) elif is_binary_target_and_in_path(target, filename, bindir): paths.add(os.path.join(options.builddir, root)) + elif is_gio_module(target, filename, options.builddir): + prepend_env_var(env, 'GIO_EXTRA_MODULES', + os.path.join(options.builddir, root), + options.sysroot) - with open(os.path.join(options.builddir, 'GstPluginsPath.json')) as f: + with open(os.path.join(options.gstbuilddir, 'GstPluginsPath.json')) as f: for plugin_path in json.load(f): prepend_env_var(env, 'GST_PLUGIN_PATH', plugin_path, options.sysroot) - for p in paths: + # Sort to iterate in a consistent order (`set`s and `hash`es are randomized) + for p in sorted(paths): prepend_env_var(env, 'PATH', p, options.sysroot) if os.name != 'nt': - for p in mono_paths: + for p in sorted(mono_paths): prepend_env_var(env, "MONO_PATH", p, options.sysroot) presets = set() encoding_targets = set() - pkg_dirs = set() python_dirs = setup_gdb(options) + overrides_dirs = set() if '--installed' in subprocess.check_output(meson + ['introspect', '-h']).decode(): installed_s = subprocess.check_output(meson + ['introspect', options.builddir, '--installed']) for path, installpath in json.loads(installed_s.decode()).items(): @@ -325,45 +407,47 @@ def get_subprocess_env(options, gst_version): if 'site-packages' in installpath_parts: install_subpath = os.path.join(*installpath_parts[installpath_parts.index('site-packages') + 1:]) if path.endswith(install_subpath): - python_dirs.add(path[:len (install_subpath) * -1]) + if os.path.commonprefix(["gi/overrides", install_subpath]): + overrides_dirs.add(os.path.dirname(path)) + else: + python_dirs.add(path[:len (install_subpath) * -1]) if path.endswith('.prs'): presets.add(os.path.dirname(path)) elif path.endswith('.gep'): encoding_targets.add( os.path.abspath(os.path.join(os.path.dirname(path), '..'))) - elif path.endswith('.pc'): - # Is there a -uninstalled pc file for this file? - uninstalled = "{0}-uninstalled.pc".format(path[:-3]) - if os.path.exists(uninstalled): - pkg_dirs.add(os.path.dirname(path)) if path.endswith('gstomx.conf'): prepend_env_var(env, 'GST_OMX_CONFIG_DIR', os.path.dirname(path), options.sysroot) - for p in presets: + for p in sorted(presets): prepend_env_var(env, 'GST_PRESET_PATH', p, options.sysroot) - for t in encoding_targets: + for t in sorted(encoding_targets): prepend_env_var(env, 'GST_ENCODING_TARGET_PATH', t, options.sysroot) - for pkg_dir in pkg_dirs: - prepend_env_var(env, "PKG_CONFIG_PATH", pkg_dir, options.sysroot) - prepend_env_var(env, "PKG_CONFIG_PATH", os.path.join(options.builddir, - 'subprojects', - 'gst-plugins-good', - 'pkgconfig'), - options.sysroot) + # Check if meson has generated -uninstalled pkgconfig files + meson_uninstalled = pathlib.Path(options.builddir) / 'meson-uninstalled' + if meson_uninstalled.is_dir(): + prepend_env_var(env, 'PKG_CONFIG_PATH', str(meson_uninstalled), options.sysroot) - for python_dir in python_dirs: + for python_dir in sorted(python_dirs): prepend_env_var(env, 'PYTHONPATH', python_dir, options.sysroot) + for python_dir in sorted(overrides_dirs): + prepend_env_var(env, '_GI_OVERRIDES_PATH', python_dir, options.sysroot) + mesonpath = os.path.join(SCRIPTDIR, "meson") if os.path.join(mesonpath): # Add meson/ into PYTHONPATH if we are using a local meson prepend_env_var(env, 'PYTHONPATH', mesonpath, options.sysroot) + # Ensure that gst-python/gi is used first + prepend_env_var(env, "PYTHONPATH", os.path.join(SCRIPTDIR, 'subprojects', 'gst-python'), + options.sysroot) + # For devhelp books if 'XDG_DATA_DIRS' not in env or not env['XDG_DATA_DIRS']: # Preserve default paths when empty @@ -385,16 +469,20 @@ def get_subprocess_env(options, gst_version): return env def get_windows_shell(): - command = ['powershell.exe' ,'-noprofile', '-executionpolicy', 'bypass', '-file', 'cmd_or_ps.ps1'] + command = ['powershell.exe' ,'-noprofile', '-executionpolicy', 'bypass', '-file', + os.path.join(SCRIPTDIR, 'data', 'misc', 'cmd_or_ps.ps1')] result = subprocess.check_output(command) return result.decode().strip() if __name__ == "__main__": - parser = argparse.ArgumentParser(prog="gstreamer-uninstalled") + parser = argparse.ArgumentParser(prog="gst-env") parser.add_argument("--builddir", default=DEFAULT_BUILDDIR, help="The meson build directory") + parser.add_argument("--gstbuilddir", + default=None, + help="The meson GStreamer build directory (defaults to builddir)") parser.add_argument("--srcdir", default=SCRIPTDIR, help="The top level source directory") @@ -417,7 +505,16 @@ if __name__ == "__main__": print("GStreamer not built in %s\n\nBuild it and try again" % options.builddir) exit(1) + + if options.gstbuilddir and not os.path.exists(options.gstbuilddir): + print("GStreamer is not built in %s\n\nBuild it and try again" % + options.gstbuilddir) + exit(1) + elif not options.gstbuilddir: + options.gstbuilddir = options.builddir + options.builddir = os.path.abspath(options.builddir) + options.gstbuilddir = os.path.abspath(options.gstbuilddir) if not os.path.exists(options.srcdir): print("The specified source dir does not exist" % @@ -425,8 +522,11 @@ if __name__ == "__main__": exit(1) # The following incantation will retrieve the current branch name. - gst_version = git("rev-parse", "--symbolic-full-name", "--abbrev-ref", "HEAD", - repository_path=options.srcdir).strip('\n') + try: + gst_version = git("rev-parse", "--symbolic-full-name", "--abbrev-ref", "HEAD", + repository_path=options.srcdir).strip('\n') + except subprocess.CalledProcessError: + gst_version = "unknown" if options.wine: gst_version += '-' + os.path.basename(options.wine) @@ -454,6 +554,14 @@ if __name__ == "__main__": shutil.copyfileobj(src, tmprc) tmprc.write('\nexport PS1="[gst-%s] $PS1"' % gst_version) tmprc.flush() + if is_bash_completion_available(options): + bash_completions_files = [] + for p in BASH_COMPLETION_PATHS: + if os.path.exists(p): + bash_completions_files += os.listdir(path=p) + bc_rc = BC_RC.format(bash_completions=' '.join(bash_completions_files), bash_completions_paths=' '.join(BASH_COMPLETION_PATHS)) + tmprc.write(bc_rc) + tmprc.flush() args.append("--rcfile") args.append(tmprc.name) elif args[0].endswith('fish'): @@ -485,6 +593,10 @@ if __name__ == "__main__": print('{}={}'.format(name, shlex.quote(value))) print('export {}'.format(name)) else: + if os.environ.get("CI_PROJECT_NAME"): + print("Ignoring SIGINT when running on the CI," + " as we get spurious sigint in there for some reason.") + signal.signal(signal.SIGINT, signal.SIG_IGN) exit(subprocess.call(args, close_fds=False, env=env)) except subprocess.CalledProcessError as e: