Guix Consensus DocumentsHome

Set search paths without program wrappers

by 宋文武 —
sponsored by Maxim Cournoyer

Withdrawn

Timeline

02 February
drafting
21 February
discussion
19 March
deliberation
02 April
withdrawn

Summary

Currently program wrappers are widely used to set search paths via environment variables. Those wrappers have some problems:

  • environment variables leakage from a process to its child processes;
  • duplicate entries in environment variables;
  • obscured process names.

To address those problems, we propose a way to set search paths with some per-output configuration files, reduce the need of creating program wrappers.

Motivation

To make sure programs work out-of-the-box rather then depend on some external settings, Guix encourages the use of program wrappers when define packages. In particular, both glib-or-gtk-build-system and qt-build-system includes a wrap phase to make program wrappers for every GNOME and KDE program.

Those wrappers have some unsolved issues:

If we managed to find a way to set search paths without using program wappers, then programs will be more robust.

Detailed Design

In addition to environment variables, some programs also allow to set search paths via configuration files, for example you can use path configuration files to set sys.path for Python, and we have a per-output ld.so.cache to load shared libraries efficiently. Inspired by them, we are going to patch some programs and libraries, so that when they build a search path from an environment variable, would also honor a per-output search path configuration file. The details are how to make those search path configuration files and how to find them when an executable is running.

Search path configuration files

We'll create search path configuration files under the etc/search-path.d directory of each package output, with each file specify a search path. The file name and its content are same to the corresponding environment variable. For example the output of the gnome-console package would have:

bin
  kgx
etc
  ld.so.cache
  search-paths.d
    GUIX_XDG_DATA_DIRS
    GUIX_GIO_EXTRA_MODULES
    GUIX_GTK4_PATH
lib
share

The content of its GUIX_XDG_DATA_DIRS file would be: /gnu/store/...-shared-mime-info-2.3/share:/gnu/store/...-glib-2.78.0/share:/gnu/store/...-gsettings-desktop-schemas-44.0/share:/gnu/store/...-libadwaita-1.5.2/share:/gnu/store/...-gtk-4.14.5/share:/gnu/store/...-gnome-console-44.4/share

Those search path configuration files would be created by the package builder, after the install phase, replace usages of wrap-program when possible.

Find the location of the current executable

To find its search path configuration files when an executable is running, we can first find the location of the executable. Conveniently, Linux provides a pseudo-file /proc/self/exe for this exact purpose, which works well for ELF executables. But for an interpreter script, /proc/self/exe would return the file name of its interpreter instead of the script, so we patch interpreters to set 2 environment variables:

  • GUIX_INTERPRETER_FILE: absolute file name of the interpreter
  • GUIX_MAIN_SCRIPT_FILE: absolute file name of the script

And when the executable's /proc/self/exe matches GUIX_INTERPRETER_FILE, we can get the script file name from GUIX_MAIN_SCRIPT_FILE. Alternatively, we can try to construct the script file name from command line arguments, but that won't work when you run a script using a relative file name and its current working directory changed before we figure out the script file name.

Set search paths with configuration files from search-paths.d

Finally, when the program want to build a search path from an environment variable, we patch the code to search its search-paths.d first, the result search path value will include both the content of the search path configuration file and the environment variable. This usually happens in C/C++ libraries like GLib, GTK and Qt with a getenv call, we need patch these getenv calls for each search path we care.

Implementation plan

A WIP implementation can be found in https://issues.guix.gnu.org/75688.

  • Add a new function g_guix_build_search_path_dirs to GLib, which returns a search path as a list of file or directory names from a search path configuration file and an environment variable.
  • Patch GLib to use g_guix_build_search_path_dirs for GUIX_XDG_DATA_DIRS, GUIX_XDG_CONFIG_DIRS, GUIX_GIO_EXTRA_MODULES and GUIX_GSETTINGS_SCHEMA_DIR.
  • Patch Python to set GUIX_INTERPRETER_FILE and GUIX_MAIN_SCRIPT_FILE.
  • Patch Qt to use g_guix_build_search_path_dirs for GUIX_XDG_DATA_DIRS, GUIX_XDG_CONFIG_DIRS, GUIX_QT_PLUGIN_PATH, GUIX_QML_IMPORT_PATH, GUIX_QML2_IMPORT_PATH.
  • Modify glib-or-gtk-build-system to get rid of wrap-program.
  • Modify qt-build-system to get rid of wrap-program.

The Cost Of Reverting

We can revert to program wrappers by manually adding wrap phases on a case by case basic, if needed.

Drawbacks or Open Questions

If implemented, we would likely carry several custom patches for GLib, GTK, Qt, Python, etc. forever.

This proposal focuses solving problems caused by program wrappers in desktop environments, namely GNOME and KDE. Individual wrap-progam usages are not addressed. We plan to handle that in build systems later, for example:

  • Handle GUIX_GI_TYPELIB_PATH and GUIX_GDK_PIXBUF_MODULE_FILES in glib-or-gtk-build-system without wrappers.
  • Handle GUIX_PYTHONPATH in python-build-system without wrappers.

There are still ABI problems caused by environment variables from profiles, which may be addressed later as suggested by Maxime Devos in https://issues.guix.gnu.org/63203#5.