uninstalled: Add support for GStreamer and GLib gdb scripts
[platform/upstream/gstreamer.git] / gst-env.py
index d368a21..775a418 100755 (executable)
@@ -2,16 +2,20 @@
 
 import argparse
 import contextlib
+import glob
 import json
 import os
 import platform
 import re
 import site
+import shlex
 import shutil
 import subprocess
 import sys
 import tempfile
 import pathlib
+import signal
+from pathlib import PurePath
 
 from distutils.sysconfig import get_python_lib
 from distutils.util import strtobool
@@ -56,7 +60,7 @@ def prepend_env_var(env, var, value, sysroot):
     if value.startswith(sysroot):
         value = value[len(sysroot):]
     # Try not to exceed maximum length limits for env vars on Windows
-    if os.name is 'nt':
+    if os.name == 'nt':
         value = win32_get_short_path_name(value)
     env_val = env.get(var, '')
     val = os.pathsep + value + os.pathsep
@@ -95,6 +99,24 @@ def is_library_target_and_not_plugin(target, filename):
         return False
     return True
 
+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
+        return False
+    fpath = PurePath(install_filename)
+    if fpath.parent != bindir:
+        return False
+    return True
+
 
 def get_wine_subprocess_env(options, env):
     with open(os.path.join(options.builddir, 'meson-info', 'intro-buildoptions.json')) as f:
@@ -114,6 +136,40 @@ def get_wine_subprocess_env(options, env):
 
     return env
 
+def setup_gdb(options):
+    bdir = os.path.realpath(options.builddir)
+    python_paths = set()
+    for libpath, gdb_path in [
+            ("subprojects/gstreamer/gst/", "subprojects/gstreamer/libs/gst/helpers/"),
+            ("subprojects/glib/gobject", None),
+            ("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))
+            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:
+                pass
+
+    gdbinit_line = 'add-auto-load-scripts-directory %s' % os.path.join(bdir, 'gdb-auto-load\n')
+    try:
+        with open(os.path.join(options.srcdir, '.gdbinit'), 'r') as f:
+            if gdbinit_line in f.readlines():
+                return python_paths
+    except FileNotFoundError:
+        pass
+
+    with open(os.path.join(options.srcdir, '.gdbinit'), 'a') as f:
+        f.write(gdbinit_line)
+
+    return python_paths
+
 
 def get_subprocess_env(options, gst_version):
     env = os.environ.copy()
@@ -144,7 +200,7 @@ def get_subprocess_env(options, gst_version):
     env["GST_PTP_HELPER"] = os.path.normpath(
         "%s/subprojects/gstreamer/libs/gst/helpers/gst-ptp-helper" % options.builddir)
 
-    if os.name is 'nt':
+    if os.name == 'nt':
         lib_path_envvar = 'PATH'
     elif platform.system() == 'Darwin':
         lib_path_envvar = 'DYLD_LIBRARY_PATH'
@@ -205,10 +261,14 @@ def get_subprocess_env(options, gst_version):
     build_options_s = subprocess.check_output(meson + ['introspect', options.builddir, '--buildoptions'])
     build_options = json.loads(build_options_s.decode())
     libdir, = [o['value'] for o in build_options if o['name'] == 'libdir']
-    libdir = libdir.replace('\\', '/')
+    libdir = PurePath(libdir)
+    prefix, = [o['value'] for o in build_options if o['name'] == 'prefix']
+    bindir, = [o['value'] for o in build_options if o['name'] == 'bindir']
+    prefix = PurePath(prefix)
+    bindir = prefix / bindir
 
     global GSTPLUGIN_FILEPATH_REG_TEMPLATE
-    GSTPLUGIN_FILEPATH_REG_TEMPLATE = GSTPLUGIN_FILEPATH_REG_TEMPLATE.format(libdir=libdir)
+    GSTPLUGIN_FILEPATH_REG_TEMPLATE = GSTPLUGIN_FILEPATH_REG_TEMPLATE.format(libdir=libdir.as_posix())
 
     for target in targets:
         filenames = listify(target['filename'])
@@ -226,7 +286,7 @@ def get_subprocess_env(options, gst_version):
                 prepend_env_var(env, lib_path_envvar,
                                 os.path.join(options.builddir, root),
                                 options.sysroot)
-            elif target['type'] == 'executable' and target['installed']:
+            elif is_binary_target_and_in_path(target, filename, bindir):
                 paths.add(os.path.join(options.builddir, root))
 
     with open(os.path.join(options.builddir, 'GstPluginsPath.json')) as f:
@@ -244,7 +304,7 @@ def get_subprocess_env(options, gst_version):
     presets = set()
     encoding_targets = set()
     pkg_dirs = set()
-    python_dirs = set(["%s/subprojects/gstreamer/libs/gst/helpers/" % options.srcdir])
+    python_dirs = setup_gdb(options)
     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():
@@ -305,7 +365,7 @@ def get_subprocess_env(options, gst_version):
         prepend_env_var(env, 'PYTHONPATH', mesonpath, options.sysroot)
 
     # For devhelp books
-    if not 'XDG_DATA_DIRS' in env or not env['XDG_DATA_DIRS']:
+    if 'XDG_DATA_DIRS' not in env or not env['XDG_DATA_DIRS']:
         # Preserve default paths when empty
         prepend_env_var(env, 'XDG_DATA_DIRS', '/usr/local/share/:/usr/share/', '')
 
@@ -315,6 +375,13 @@ def get_subprocess_env(options, gst_version):
                                                         'GStreamer-doc'),
                      options.sysroot)
 
+    if 'XDG_CONFIG_DIRS' not in env or not env['XDG_CONFIG_DIRS']:
+        # Preserve default paths when empty
+        prepend_env_var(env, 'XDG_CONFIG_DIRS', '/etc/local/xdg:/etc/xdg', '')
+
+    prepend_env_var(env, "XDG_CONFIG_DIRS", os.path.join(PREFIX_DIR, 'etc', 'xdg'),
+                    options.sysroot)
+
     return env
 
 def get_windows_shell():
@@ -339,7 +406,11 @@ if __name__ == "__main__":
                         help="Build a wine env based on specified wine command")
     parser.add_argument("--winepath",
                         default='',
-                        help="Exra path to set to WINEPATH.")
+                        help="Extra path to set to WINEPATH.")
+    parser.add_argument("--only-environment",
+                        action='store_true',
+                        default=False,
+                        help="Do not start a shell, only print required environment.")
     options, args = parser.parse_known_args()
 
     if not os.path.exists(options.builddir):
@@ -360,8 +431,9 @@ if __name__ == "__main__":
     if options.wine:
         gst_version += '-' + os.path.basename(options.wine)
 
+    env = get_subprocess_env(options, gst_version)
     if not args:
-        if os.name is 'nt':
+        if os.name == 'nt':
             shell = get_windows_shell()
             if shell == 'powershell.exe':
                 args = ['powershell.exe']
@@ -373,7 +445,8 @@ if __name__ == "__main__":
                 args += ['/k', 'prompt [gst-{}] $P$G'.format(gst_version)]
         else:
             args = [os.environ.get("SHELL", os.path.realpath("/bin/sh"))]
-        if "bash" in args[0] and not strtobool(os.environ.get("GST_BUILD_DISABLE_PS1_OVERRIDE", r"FALSE")):
+        if args[0].endswith('bash') and not strtobool(os.environ.get("GST_BUILD_DISABLE_PS1_OVERRIDE", r"FALSE")):
+            # Let the GC remove the tmp file
             tmprc = tempfile.NamedTemporaryFile(mode='w')
             bashrc = os.path.expanduser('~/.bashrc')
             if os.path.exists(bashrc):
@@ -381,11 +454,38 @@ if __name__ == "__main__":
                     shutil.copyfileobj(src, tmprc)
             tmprc.write('\nexport PS1="[gst-%s] $PS1"' % gst_version)
             tmprc.flush()
-            # Let the GC remove the tmp file
             args.append("--rcfile")
             args.append(tmprc.name)
+        elif args[0].endswith('fish'):
+            # Ignore SIGINT while using fish as the shell to make it behave
+            # like other shells such as bash and zsh.
+            # See: https://gitlab.freedesktop.org/gstreamer/gst-build/issues/18
+            signal.signal(signal.SIGINT, lambda x, y: True)
+            # Set the prompt
+            args.append('--init-command')
+            prompt_cmd = '''functions --copy fish_prompt original_fish_prompt
+            function fish_prompt
+                echo -n '[gst-{}] '(original_fish_prompt)
+            end'''.format(gst_version)
+            args.append(prompt_cmd)
+        elif args[0].endswith('zsh'):
+            tmpdir = tempfile.TemporaryDirectory()
+            # Let the GC remove the tmp file
+            tmprc = open(os.path.join(tmpdir.name, '.zshrc'), 'w')
+            zshrc = os.path.expanduser('~/.zshrc')
+            if os.path.exists(zshrc):
+                with open(zshrc, 'r') as src:
+                    shutil.copyfileobj(src, tmprc)
+            tmprc.write('\nexport PROMPT="[gst-{}] $PROMPT"'.format(gst_version))
+            tmprc.flush()
+            env['ZDOTDIR'] = tmpdir.name
     try:
-        exit(subprocess.call(args, close_fds=False,
-                             env=get_subprocess_env(options, gst_version)))
+        if options.only_environment:
+            for name, value in env.items():
+                print('{}={}'.format(name, shlex.quote(value)))
+                print('export {}'.format(name))
+        else:
+            exit(subprocess.call(args, close_fds=False, env=env))
+
     except subprocess.CalledProcessError as e:
         exit(e.returncode)