Set search paths without program wrappers
by 宋文武 —
sponsored by Maxim Cournoyer
Withdrawn
Timeline
02 February
drafting21 February
discussion19 March
deliberation02 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:
- Program crash due to leaked environment variables
- Duplicate entries in various environment variables
- Ansible & others' problems with wrapped '.ansible-real' scripts
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 interpreterGUIX_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
forGUIX_XDG_DATA_DIRS
,GUIX_XDG_CONFIG_DIRS
,GUIX_GIO_EXTRA_MODULES
andGUIX_GSETTINGS_SCHEMA_DIR
. - Patch Python to set
GUIX_INTERPRETER_FILE
andGUIX_MAIN_SCRIPT_FILE
. - Patch Qt to use
g_guix_build_search_path_dirs
forGUIX_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 ofwrap-program
. - Modify
qt-build-system
to get rid ofwrap-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
andGUIX_GDK_PIXBUF_MODULE_FILES
inglib-or-gtk-build-system
without wrappers. - Handle
GUIX_PYTHONPATH
inpython-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.