| # slibtool: a skinny 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. |
| - `-export-symbols`, which exports symbols listed in a given file, and |
| `-export-symbols-regex`, which exports symbols matching a regex; |
| both are unimplemented because similar functionality has long been |
| provided by the compiler or toolchain; `gcc` has supported setting ELF |
| visibility since v4.0, for instance, and PE import library support is |
| provided by slibtool via the --output-def linker switch and a subsequent |
| invocation of dlltool. |
| - `-no-install`, which considers the executable wrapper to be optional; |
| this switch is not needed on modern systems, and is accordingly ignored. |
| |
| - No `libltdl`. |
| libltdl is nowadays no longer needed; it serves to provide a `dlopen()` |
| functionality on systems which do not offer it, i.e. HP-UX and BeOS, |
| however since neither HP-UX nor BeOS is currently supported by slibtool, |
| there exists no urgent need to provide equivalent functionality. |
| |
| ## Development |
| |
| Major changes to slibtool should be discussed on [#midipix] 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]. |
| |
| [MIT license]: http://git.foss21.org/slibtool/tree/COPYING.SLIBTOOL |
| [libltdl]: https://www.gnu.org/software/libtool/manual/html_node/Using-libltdl.html#Using-libltdl |
| [dlopen()]: http://pubs.opengroup.org/onlinepubs/9699919799/functions/dlopen.html |
| [CONTRIB]: http://git.foss21.org/slibtool/tree/CONTRIB |
| [libtool]: https://www.gnu.org/software/libtool/ |
| [#midipix]: irc://irc.freenode.net/#midipix |
| [cparser]: http://pp.ipd.kit.edu/git/cparser/ |
| [94d109f]: http://git.foss21.org/slibtool/commit/?id=94d109fa418c024c214a50d645624e2e2935e6d1 |
| [1142bf2]: http://git.foss21.org/slibtool/commit/?id=1142bf2e13f411cf967c1ed8b4060d7829eb13bb |
| [55c95a8]: http://git.foss21.org/slibtool/commit/?id=55c95a829928ae9f053678a58a2145276cad9c08 |