firasuke
Firas Khalil Khanamaintainer
# slibtool: a strong libtool implementation, written in C `slibtool` is an independent reimplementation of the widely used libtool, written in C. `slibtool` is designed to be a clean, fast, easy-to-use libtool drop-in replacement, and is accordingly aimed at package authors, distro developers, and system integrators. `slibtool` maintains compatibility with libtool in nearly every aspect of the tool's functionality as well as semantics, leaving out (or turning into a no-op) only a small number of features that are no longer needed on modern systems. Being a compiled binary, and although not primarily written for the sake of performance, building a package with `slibtool` is often faster than with its script-based counterpart. The resulting performance gain would normally vary between packages, and is most noticeable in builds that invoke libtool a large number of times, and which are characterized by the short compilation duration of individual translation units. ## why reimplement libtool? Midipix targets use the PE binary format, and so require import library integration on the one hand, yet follow ELF naming conventions (i.e. libfoo.so.x.y.z) on the other. In consequence, midipix shared libraries are not fully supported by existing libtool implementations. As an interim solution used for the porting of gcc, a libtool script generated by ltmain.sh was hand-edited so that it would correctly produce the host's shared libraries as part of the toolchain build process. Bypassing the libtool script generated by a package's ltmain.sh requires overriding the `LIBTOOL` variable as part of invoking `make(1)`. In that sense, and unless midipix support is added to every single ltmain.sh in every single package that uses autotools, it does not truly matter whether the surrogate libtool that one chooses be a script, a program written in C, or something else. At the time of this writing, an average libtool script consists of about `10K lines of code` with `several hundred case-esac statements` and a similar number of `if-then blocks`. In view of the length of the generated script, and in light of its challenging logic and overall complexity, a rewrite of the tool in C seemed to be the right choice not only with respect to quality, readability, and anticipated performance, but also in terms of development effort, ease of customization, and long-term maintenance. ## Requirements for building slibtool - a C toolchain, consisting of - a C compiler such as gcc, clang, or [cparser]; - the compiler should support -std=c99; - the system's libc should support -D_XOPEN_SOURCE=700. If building for (native) mingw development, please cross-build slibtool under your posix environment of choice (e.g. midipix, cygwin, msys2) and install it alongside the rest of your (cross-built) mingw toolchain. If your system libc only supports -D_XOPEN_SOURCE=600 then you should be able to build slibtool after slightly tweaking the code and/or setting a few config-time environment variables (such as CFLAGS and LDFLAGS). ## Usage With most packages, simply adding `LIBTOOL=slibtool` to the `make` invocation should suffice. To have `slibtool` operate in debug mode (outputting a colorized raw argument vector), use `LIBTOOL=dlibtool` instead, or alternatively add `--debug` to the libtool flags inside of your Makefile. ### Corner cases Some programs which make heavy use of recursive `make` are known to drop the `LIBTOOL` value at some point in the process, and as such you may additionally need to export the environment variable; `export MAKE="make LIBTOOL=slibtool"`. `slibtool` additionally installs two symlinks that are the equivalent of `-disable-shared` and `-disable-static`, named `slibtool-static` and `slibtool-shared`, respectively. These symlinks should be used when building packages that have the above switches hard-coded into the generated libtool script; two examples of such packages are `binutils` and `gdb`, which both have shared library builds disabled by default. A quick way to determine whether this invocation form is appropriate with a specific package is to run `./libtool --features` from the build directory, then check whether the output has either shared or static library builds disabled. When slibtool is invoked as a basic tool (i.e. slibtool, dlibtool, etc.), then building of both a shared library and a static archive is enabled by default. ## Differences from GNU libtool While `slibtool` aims to be compatible with all common usages of libtool at the build system level, there exist several differences at the implementation level that should be noted. - `.la wrappers` are always generated, but by default are never installed; `.la wrappers` contain key information that is provided to libtool when generating a shared library or static archive, and which is needed when passing the archive or library as an input argument in .la form to the compiler driver in subsequent link steps. Since `slibtool` is entirely independent of the above wrappers with respect to its own functionality, and given its announced goal to remain compatible with the script-based libtool as much as possible, `slibtool`'s behavior is to always produce `.la wrappers` on the one hand, yet fully ignore their content on the other. Despite their internal nature, installed .la wrappers are often [ab]used in strange and mysterious ways by distro-related tools other than libtool itself. For the sake of distributions that depend on the aforementioned wrappers, slibtool comes with three special symlinks named `clibtool`, `clibtool-shared`, and `clibtool-static`, respectively. The `'c'` in `clibtool` stands for `compatible`, and accordingly indicates an end-user's preference towards perfect emulation of legacy behavior. - `-rpath` argument values are passed to the compiler and linker as needed only; `-rpath` is often [mis]used by libtool to add redundant paths to a program's linker search path. When using slibtool, `-rpath` argument values are only forwarded to the compiler and linker when pointing to non-default linker directories, and are accordingly filtered out when pointing to default library locations (i.e. `/usr/lib`, `/lib`, and so on). - no-ops - `-R`, which adds a path to the generated program's run-time search path; this switch is currently not needed, and is accordingly ignored. - `-no-install`, which considers the executable wrapper to be optional; this switch is not needed on modern systems, and is accordingly ignored. ## Development Major changes to slibtool should be discussed on [#slibtool] prior to pursuing a considerable effort, and patches should be sent, gpg-signed, to the project maintainer; before hacking on slibtool, please take a moment of your time and read the [CONTRIB] document. As you finalize your changes to the code, please consider building at least once with `cparser` as the compiler. cparser is excellent at catching logical errors and semantic flaws, and as of the time of this writing is capable of spotting bugs that go unnoticed by other major compilers. For a few examples of such hidden bugs, see commits [94d109f], [1142bf2], and [55c95a8]. ## License `slibtool` is distributed under a permissive [MIT license]. [#slibtool]: ircs://irc.oftc.net/#slibtool [MIT license]: https://git.foss21.org/slibtool/tree/COPYING.SLIBTOOL [CONTRIB]: https://git.foss21.org/slibtool/tree/CONTRIB [libltdl]: https://www.gnu.org/software/libtool/manual/html_node/Using-libltdl.html#Using-libltdl [libtool]: https://www.gnu.org/software/libtool/ [cparser]: https://pp.ipd.kit.edu/git/cparser/ [dlopen()]: https://pubs.opengroup.org/onlinepubs/9699919799/functions/dlopen.html [94d109f]: https://git.foss21.org/slibtool/commit/?id=94d109fa418c024c214a50d645624e2e2935e6d1 [1142bf2]: https://git.foss21.org/slibtool/commit/?id=1142bf2e13f411cf967c1ed8b4060d7829eb13bb [55c95a8]: https://git.foss21.org/slibtool/commit/?id=55c95a829928ae9f053678a58a2145276cad9c08