User:MGorny/New eselect-opengl design

This page describes the new design of eselect-opengl (and eselect-opencl) suggested by me.

The problem
Proprietary graphic drivers provided by NVidia and AMD (ATi) tend to require non-standard system libraries (libGL, ...) and Xorg modules. Driver providers also include their own versions of system headers. All those files collide with the implementations provided by Xorg components.

Since we can't get all the three implementations to interoperate properly, we aim to support installing them side-by-side and switching between them easily.

The current solution
Currently the colliding files from the three providers are installed in subdirectories of /usr/lib*/opengl. The files for currently selected implementation are symlinked into the system directories. The symlinks are created and updated by eselect-opengl.

This solution has a few disadvantages:
 * the currently selected implementation affects both libraries used at build and run time, which makes the builds inconsistent in case of different implementation is used,
 * some packages build correctly only against xorg-x11 implementation of the interfaces — they currently need to use extra hacks to enforce that,
 * the relevant files in /usr are unowned and modified outside the package manager.

Assumptions
The design is made with the following assumptions:
 * 1) Applications are to be built against Xorg implementations of the OpenGL/OpenCL interfaces,
 * 2) eselect-opengl should only switch the implementations used at runtime.

Design
Implementation:
 * 1) The Xorg implementation libraries and includes are installed directly into system directories (/usr/{include,lib*}),
 * 2) the Xorg implementation server modules are installed in /usr/lib*/opengl,
 * 3) the remaining implementations are still installed in /usr/lib*/opengl,
 * 4) eselect-opengl switches the implementation by:
 * 5) setting the library path in env.d/ using the LD_PATH variable,
 * 6) adding the module directory in an xorg.conf.d/ file.

The extra files are needed only for non-standard implementations. When switching to the xorg implementation, they can be either removed or blanked.

Explanation
The compiler and linker use paths specified on the command line (-I, -L) and the system default paths. In particular, the binutils linker does not use ld.so.conf. Therefore with no extra magic it will use the libraries and headers for xorg-x11 implementation that are installed in system locations.

The dynamic linker uses search paths from ld.so.conf. We name the file 000* to enforce our paths before the system paths, therefore making the dynamic linker prefer impl-specific libraries over system ones. If we use xorg-x11 implementation, we remove the extra path and ld.so uses the system libraries.

The xorg server uses ModulePaths specified in xorg.conf, in order. If we specify the implementation-specific directory, its extensions will override the ones provided by xorg-x11 implementation. If we use xorg-x11, we remove the extra path and the server finds modules in standard location.

If we're afraid that the user may have other ModulePath set, we may alternatively keep installing the xorg-x11 impl modules in /usr/lib*/opengl and always append the ModulePath. Then the standard paths will lack the necessary modules, so no accidental override will happen.

Advantages

 * 1) Build is always performed using xorg-x11 headers and libraries without any special hackery,
 * 2) implementation switches are atomic,
 * 3) all files in /usr are owned and controlled properly, eselect mangles only /etc.

Credits
The work has been done on request of the Funtoo community, issue FL-1314.