| <html> | |
| <head> | |
| <title>Libtool Inter-library Dependencies</title> | |
| <body bgcolor="#ffffff"> | |
| <center><h1><img src="/graphics/libtool.gif" width=477 height=192 | |
| alt="Libtool"></h1></center> | |
| <h1>Inter-library Dependencies</h1> | |
| <p>About twice a week, for the last five weeks, I've been receiving | |
| bug reports which tell me that libtool's inter-library dependency | |
| handling is broken. | |
| <p>I know. I broke it intentionally, until I have the time to fix it | |
| myself, or somebody else takes the time to help me with it. | |
| <p>These same people often give me a simple one-line patch which | |
| re-enables my old, simplistic inter-library dependencies, but nobody | |
| seems to want to test things thoroughly and come up with a real | |
| solution. | |
| <p>If you don't care about the history, and you just want to help me | |
| out, jump to <a href="#solution">the bottom of this document</a>. | |
| <h2>Background</h2> | |
| <p>Libtool's basic premise is to make static and shared libraries | |
| behave the same way from a programmer's point of view. This allows | |
| users to build a libtoolized package with or without shared libraries, | |
| determined at configuration time. It does this by using a | |
| <dfn>libtool object</dfn> (<samp>.lo</samp>) and <dfn>libtool | |
| archive</dfn> (<samp>.la</samp>) abstraction, so that the package | |
| maintainer can use libtool to operate on these files without making | |
| any assumptions about their underlying representation. | |
| <p>For the most part, this abstraction works well, and has made | |
| libtool as popular as it is today. Without this abstraction, it would | |
| be significantly harder to port libtool to new platforms. | |
| <p>Unfortunately, what this abstraction has also done is reveal some | |
| fundamental inconsistencies with most shared library implementations. | |
| Every shared library implementation works well for `hello world'-type | |
| examples, but very few are robust and well-designed so that libtool | |
| doesn't need special tricks in order to build correct, featureful | |
| shared libraries. | |
| <p>Providing inter-library dependencies is one feature that has | |
| revealed these kinds of inconsistencies. | |
| <h2>The problem</h2> | |
| <p>My original inter-library dependency code received rigourous testing | |
| in beta releases of <a href="http://www.red-bean.com/guile/">GNU | |
| Guile</a>. As soon as the Guile people started using my code, I | |
| received a flood of bug reports. People were reporting that | |
| <samp>libguile</samp> (Guile's main shared library) was failing to | |
| link, or that programs linked against <samp>libguile</samp> were | |
| dumping core. | |
| <p>Not good. | |
| <p>The Guile people chased this bug down to the following scenario: | |
| <ol> | |
| <li>The user's system has a static regexp library installed, | |
| <samp>librx.a</samp>. | |
| <li>Guile's <samp>configure</samp> script detects that the | |
| <samp>-lrx</samp> linker option can be used to link in | |
| <samp>librx</samp>. | |
| <li>When <samp>libguile</samp> is built, the <samp>-lrx</samp> linker | |
| option is used. | |
| <li>Some linkers fail at this point, because they don't allow shared | |
| libraries to contain or depend on static libraries. | |
| <li>If the linker didn't fail, then a few programs are linked against | |
| <samp>libguile</samp>. | |
| <li>On some systems, these programs core dump because | |
| <samp>libguile</samp> is a shared library that contains non-PIC code | |
| (from <samp>librx</samp>). | |
| </ol> | |
| <h2>The interim solution</h2> | |
| <p>I needed some way to respond to these reports. I saw my options (in | |
| order of my preference) as: | |
| <ol> | |
| <li>Write code in <samp>ltmain.sh</samp> to prevent static libraries | |
| from appearing in inter-library dependencies. This would take some | |
| work, but obviously is the best solution. | |
| <li>Find the systems that fail, and turn off inter-library | |
| dependencies on only those systems. | |
| <li>Force the package maintainer to guarantee that static libraries | |
| never appear in inter-library dependencies. | |
| </ol> | |
| <p>I immediately vetoed the last solution, because that would violate | |
| the whole point of using libtool, and would cause a lot of people to | |
| waste time solving a problem that really should be fixed by libtool. | |
| <p>I preferred the first solution, but at the time of the reports, I | |
| didn't see an obviously simple mechanism for detecting the difference | |
| between shared and static libraries. | |
| <p>So, in the meantime, I tried turning off inter-library dependencies | |
| on the systems that failed. | |
| <p>I quickly discovered, to my chagrin, that many systems fail. So, | |
| it was be simpler for me to turn off <em>all</em> inter-library | |
| dependencies, then find out which systems work, rather than vice | |
| versa. | |
| <h2>The current situation</h2> | |
| <p>I've been busy trying to avoid bankruptcy. It's been over three | |
| months since I first turned off inter-library dependencies, and I | |
| still haven't completed the solution I want. | |
| <p>I've been gearing up for the 1.1 release of libtool, because there | |
| is a high demand for a stable public release. So, I'm not going to | |
| introduce any destabilizing changes to the inter-library dependency | |
| code until after 1.1 is released. | |
| <h2><a name="solution">The solution</a></h2> | |
| <p>So, I want to tell you how you can help me solve the various | |
| dilemmas surrounding this issue: | |
| <ol> | |
| <li>I need to find out more about the nature of the problems I ran | |
| into with Guile. Unfortunately, I cannot reproduce them in simple | |
| tests on my own platform (i586-pc-linux-gnulibc1), even though I think | |
| they were reported here. I need to find out which platforms already | |
| have perfect inter-library dependency support, how to work around the | |
| problem on other platforms, and, more importantly, exactly | |
| <em>why</em> some systems give me problems and others don't. | |
| <p>On correct platforms, you can link <em>any</em> static library | |
| against a shared library via the <samp>-lNAME</samp> option without | |
| the linker complaining, then link a program against this library and | |
| run it without dumping core. I know that this scenario will always | |
| work fine on the following systems: | |
| <ul> | |
| <li>None reported yet. | |
| </ul> | |
| <p>I also know that on some systems, you can create a shared library | |
| linked against a static one, but running programs linked against such | |
| a library will dump core: | |
| <ul> | |
| <li>None reported yet. | |
| </ul> | |
| <p>Finally, there are some systems which won't even allow you to link | |
| a shared library against a static one: | |
| <ul> | |
| <li>Solaris 2.x | |
| </ul> | |
| <li>Help me figure out a good, portable way to detect if a given | |
| <samp>-lNAME</samp> option refers to a shared library or not, since | |
| that is needed as a workaround to the problem. Some suggestions so | |
| far have been: | |
| <ul> | |
| <li>Link the library against a tiny test program, and: | |
| <ul> | |
| <li>run <samp>ldd(1)</samp> on the test program and search for | |
| <samp>libNAME</samp> in the ldd output. | |
| <li>use the <samp>-verbose</samp> flag for GNU ld in order to see | |
| which library is actually linked. | |
| <li>run some sort of other program to determine if the library was | |
| dynamic. | |
| </ul> | |
| <li>Track the <samp>-LDIR</samp> flags, do a search for the library, | |
| and then check whether it is shared by: | |
| <ul> | |
| <li>using the <samp>file(1)</samp> program. | |
| <li>looking at its suffix. | |
| </ul> | |
| </ul> | |
| <li>Contact any people you know who might be interested, get them to | |
| read this page, so that they can help me solve the problem. | |
| <li>Send me money, so that I can devote more of my time to solving the | |
| problem. | |
| </ol> | |
| <p>Thank you for your help, and have fun. | |
| <hr> | |
| <a href="http://www.gimp.org/"><img src="/graphics/gfx_by_gimp.gif" | |
| align="right" border=0></a> | |
| <p><a href="libtool.html">Back to the libtool home page.</a> | |
| <address> | |
| Gordon Matzigkeit <a href="mailto:gord@profitpress.com"><gord@profitpress.com></a> | |
| </address> | |
| </html> |