📄 dealing-with-libraries.html
字号:
<HTML><HEAD><TITLE>Dealing with Libraries</TITLE><METANAME="GENERATOR"CONTENT="Modular DocBook HTML Stylesheet Version 1.61"><LINKREL="HOME"TITLE="Writing GNOME Applications"HREF="index.html"><LINKREL="UP"TITLE="The GNOME Build Environment"HREF="gnome-build.html"><LINKREL="PREVIOUS"TITLE="Generating Makefiles"HREF="generating-makefiles.html"><LINKREL="NEXT"TITLE="Adding GNOME"HREF="adding-gnome.html"></HEAD><BODYCLASS="SECT1"><DIVCLASS="NAVHEADER"><TABLEWIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><THCOLSPAN="3"ALIGN="center">Writing GNOME Applications</TH></TR><TR><TDWIDTH="10%"ALIGN="left"VALIGN="bottom"><AHREF="generating-makefiles.html">Prev</A></TD><TDWIDTH="80%"ALIGN="center"VALIGN="bottom">Chapter 3. The GNOME Build Environment</TD><TDWIDTH="10%"ALIGN="right"VALIGN="bottom"><AHREF="adding-gnome.html">Next</A></TD></TR></TABLE><HRALIGN="LEFT"WIDTH="100%"></DIV><DIVCLASS="SECT1"><H1CLASS="SECT1"><ANAME="DEALING-WITH-LIBRARIES">Dealing with Libraries</A></H1><P> One of the most useful features of the automake package is its support for creating libraries. In truth, most of this support is provided by another GNU software package, called libtool, distributed separately from automake. However, automake and libtool live quite comfortably together and have grown up in the same backyard, so to speak. </P><P> Because of this close integration, you don't have to do much to build software with complex library needs. Libtool sets things up so that you don't even need to decide between static and shared libraries until compile time. </P><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN515">Libtool Support</A></H2><P> The first thing you need to do to add libtool support to a project is call the AM_PROG_LIBTOOL macro in configure.in, with no parameters. Among other things, this macro adds the --enable-shared and --enable-static flags and their --disable-shared and --disable-static counterparts to the configure script and engages libtool integration with automake. By default, the libtool script creates both shared and static libraries. The system administrator can force the building of only static libraries with the --disable-shared flag, or the building of only shared libraries with the --disable-static flag. </P><P> The changes to Makefile.am are a little more complex, but by no means tricky. libtool makes use of a special automake primary, _LTLIBRARIES. Any libraries built with the _LTLIBRARIES primary will use the libtool wrapper instead of directly calling the standard UNIX library tools, such as ar and ranlib.1 </P><P> Since libtool creates an abstraction wrapper around the library files it builds, it has to be careful what it calls those files. If it used the common .o or .a file extension for files that aren't really linkable object files, it would run the risk of confusing later stages of the build process. To protect you from this danger, the libtool script tags its libraries with the .la file extension. You should follow this convention when referring to libtool libraries in your Makefile.am file. Although the .la files aren't normal binary library files, you should treat them in your makefiles as if they were-but this means you must be very consistent about your use of libtool. If you try to link a .la library into an application without using libtool, your linker will be unable to figure out what to do with the strangely formatted file. The build will grind to a halt. </P><P> Without libtool, your Makefile.am file might contain something like this: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">lib_LIBRARIES=libgrump.alibgrump_a_SOURCES=grump.c </PRE></TD></TR></TABLE><P> If you decided to switch over to libtool, you would have to change these lines to use the .la file extension and the _LTLIBRARIES primary: </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">lib_LTLIBRARIES=libgrump.lalibgrump_la_SOURCES=grump.c </PRE></TD></TR></TABLE><P> An interesting characteristic of shared libraries is revealed when you use the noinst_LTLIBRARIES variable: Shared libraries must always be installed. The shared library is a runtime dependency of the executable. If you install the executable without it, you are installing a broken package. automake realizes this and will always force static libraries when it sees noinst_LTLIBRARIES, to avoid this potential crisis. </P><P> Other useful primaries for dealing with libraries are _LDFLAGS, _LDADD, and _LIBADD. These three variables have very similar names, with closely related functionality. We'll try to unravel the differences here. </P><P> The _LDADD primary is good for adding extra object files and libraries to the link line for a specific binary target. If you define the _LDADD variable for a target, it will override the global LDADD variable that is normally used. You can't pass linker flags, other than -l and -L, with the _LDADD primary; if you try to do so, automake will bail out with a friendly warning message. Furthermore, you can use _LDADD only with executables. If you need to pass extra objects or libraries to a library target, you can use _LIBADD instead. </P><P> The _LDFLAGS primary is used to add miscellaneous linker parameters to libraries or executables, beyond what _LDADD and _LIBADD allow you to pass. You can use it to pass flags directly to the linker, such as the -version-info flag (see Section 3.4.5). </P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN528">libtoolize</A></H2><P> Libtool relies on four shell scripts to query the system and set certain things up: config.guess, config.sub, ltconfig, and ltmain.sh. The first two scripts poll the target system and attempt to distill it down to a single canonical name-for example, "i586-pc-linux-gnu." config.guess makes a guess at the target system's canonical name, and config.sub validates that name and expands it to its fully qualified form. Libtool uses the canonical name to decide which set of rules it should use to create libraries for the target system. This is a very important step because different flavors of UNIX can have radically different ways of carrying out this task. If libtool guesses the wrong target operating system, the shared libraries it creates will not work. </P><P> The ltconfig script creates a special, customized version of the libtool shell script that gives the libtool package its name. The configure script invokes ltconfig for you, as part of the AM_PROG_LIBTOOL macro. The ltconfig script runs several autoconf-like checks on the target system (using config.guess and config.sub), depending on the command line parameters with which configure was invoked. It then writes the results into a newly created libtool script, along with the contents of the ltmain.sh script. Later, during the build process, libtool generates the proper commands to create libraries for that operating system. </P><P> These helper scripts are the backbone of the libtool system. Libtool is shipped with a clever utility, called libtoolize, to add this support to your project. Simply call libtoolize in your top-level source directory, and these four files will be copied (or symbolically linked) into your application directory and properly set up. libtoolize cuts down on some potentially hairy maintenance headaches. You can tweak its behavior quite a bit with command line parameters. See the libtool documents for more information. </P></DIV><DIVCLASS="SECT2"><H2CLASS="SECT2"><ANAME="AEN533">A Grumpy Example</A></H2><P> It's time to take a look at some source code. Let's throw together a little shared library, called libgrump, with a couple of small functions. We'll also build an executable that calls into that shared library. If you've done this the hard way before, creating makefiles by hand, you'll be surprised at how easy it is with automake and libtool. See Listings 3.2 through 3.6 for the source code. </P><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 3.2 Shared Library Header File: grump.h# include <stdlib.h>void grump_some( );void grump_a_lot_more( ); </PRE></TD></TR></TABLE><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 3.3 Shared Library Implementation File: grump.c# include "grump.h"void grump_some( ){ printf("Oh, bother!...\n\n");}void grump_a_lot_more( ){ int i, index; char *grumps[5] = { "Aargh!", "Be gone!", "Sigh...", "Not again!", "Go away!" }; for (i = 0; i < 5; i++) { index = (5.0 * rand( ) / (RAND_MAX + 1.0)); printf("%s\n", grumps[index]); }} </PRE></TD></TR></TABLE><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 3.4 Main-Module Source Code: main.c#include "grump.h"int main(int argc, char *argv[]){ grump_some( ); grump_a_lot_more( );} </PRE></TD></TR></TABLE><TABLEBORDER="0"BGCOLOR="#E0E0E0"WIDTH="100%"><TR><TD><PRECLASS="PROGRAMLISTING">Listing 3.5 configure.in for grumpalotAC_INIT(grump.c)AM_INIT_AUTOMAKE(grump_test, 0.0.1)AC_PROG_CCAM_PROG_LIBTOOLAC_OUTPUT(Makefile) </PRE></TD
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -