Linking(3)

Linking with Static Libraries 

 In practice, all compilation systems provide a mechanism for packaging related object modules into a single file called a static library, which can then be supplied as input to the linker. When it builds the output executable, the linker copies only the object modules in the library that are referenced by the application program. 

ANSI C

They(I/O, string manipulation etc) are available to every C program in the libc.a library. ANSI C also defines an extensive collection of floating-point math functions such as sin, cos, and sqrt in the libm.a library. 

why static libraries are needed:

Without static libraries, (1) One approach would be to have the compiler recognize calls to the standard functions and to generate the appropriate code directly.  Because of the large number of standard functions defined by the C standard. It would add significant complexity to the compiler and would require a new compiler version each time a function was added, deleted, or modified. To application programmers, however, this approach would be quite convenient because the standard functions would always be available. 

(2)Another approach would be to put all of the standard C functions in a single relocatable object module, say, libc.o, that application programmers could link into their executables: 

unix> gcc main.c /usr/lib/libc.o

This approach has the advantage that it would decouple the implementation of the standard functions from the implementation of the compiler, and would still be reasonably convenient for programmers. 

However, a big disadvantage is that every executable file in a system would now contain a complete copy of the collection of standard functions, which would be extremely wasteful of disk space. (On a typical system, libc.a is about 8 MB and libm.a is about 1 MB.)

Worse, each running program would now contain its own copy of these functions in memory, which would be extremely wasteful of memory.  

Another big disadvantage is that any change to any standard function, no matter how small, would require the library developer to recompile the entire source file, a time- consuming operation that would complicate the development and maintenance of the standard functions. 

(3) We could address some of these problems by creating a separate relocatable file for each standard function and storing them in a well-known directory. How- ever, this approach would require application programmers to explicitly link the appropriate object modules into their executables, a process that would be error prone and time consuming

unix> gcc main.c /usr/lib/printf.o /usr/lib/scanf.o ...

a static library :

Related functions can be compiled into separate object modules and then packaged in a single static library file.

Application programs can then use any of the functions defined in the library by specifying a single file name on the command line.

For example, a program that uses functions from the standard C library and the math library could be compiled and linked with a command of the form:

unix> gcc main.c /usr/lib/libm.a /usr/lib/libc.a

At link time, the linker will only copy the object modules that are referenced by the program, which reduces the size of the executable on disk and in memory.

On the other hand, the application programmer only needs to include the names of a few library files.

(In fact, C compiler drivers always pass libc.a to the linker, so the reference to libc.a mentioned previously is unnecessary.) 

On Unix systems, static libraries are stored on disk in a particular file format known as an archive.  

An archive is a collection of concatenated relocatable object files, with a header that describes the size and location of each member object file. Archive filenames are denoted with the .a suffix.  

To make our discussion of libraries concrete, suppose that we want to provide the vector routines in Figure 7.5 in a static library called libvector.a. 

To create the library, we would use the ar tool as follows: 

unix> gcc -c addvec.c multvec.c
unix> ar rcs libvector.a addvec.o multvec.o

To use the library, we might write an application such as main2.c in Figure 7.6, which invokes the addvec library routine.

(The include (header) file vector.h defines the function prototypes for the routines in libvector.a.) 

To build the executable, we would compile and link the input files main.o and libvector.a: 

unix> gcc -O2 -c main2.c
unix> gcc -static -o p2 main2.o ./libvector.a

The -static argument tells the compiler driver that the linker should build a fully linked executable object file that can be loaded into memory and run without any further linking at load time. 

When the linker runs, it determines that the addvec symbol defined by addvec.o is referenced by main.o, so it copies addvec.o into the executable.

Since the program doesn’t reference any symbols defined by multvec.o, the linker does not copy this module into the executable.

The linker also copies the printf.o module from libc.a, along with a number of other modules from the C run-time system. 

How Linkers Use Static Libraries to Resolve References 

 During the symbol resolution phase, the linker scans the relocatable object files and archives left to right in the same sequential order that they appear on the compiler driver’s command line. 

(The driver automatically translates any .c files on the command line into .o files.)  

 

situations:

1 If the library that defines a symbol appears on the command line before the object file that references that symbol, then the reference will not be resolved and linking will fail.

For example, consider the following: 

unix> gcc -static ./libvector.a main2.c
/tmp/cc9XH6Rp.o: In function ‘main’:
/tmp/cc9XH6Rp.o(.text+0x18): undefined reference to ‘addvec’

2 The general rule for libraries is to place them at the end of the command line.

If the members of the different libraries are independent, in that no member references a symbol defined by another member, then the libraries can be placed at the end of the command line in any order. 

3 If, on the other hand, the libraries are not independent, then they must be ordered so that for each symbols that is referenced externally by a member of an archive,

at least one definition of s follows a reference to s on the command line. For example, suppose foo.c calls functions in libx.a and libz.a that call func- tions in liby.a.

Then libx.a and libz.a must precede liby.a on the command line: 

unix> gcc foo.c libx.a libz.a liby.a

4 Libraries can be repeated on the command line if necessary to satisfy the dependence requirements.

For example, suppose foo.c calls a function in libx.a that calls a function in liby.a that calls a function in libx.a. Then libx.a must be repeated on the command line: 

unix> gcc foo.c libx.a liby.a libx.a

Alternatively, we could combine libx.a and liby.a into a single archive. 

posted @ 2018-06-24 16:32  geeklove  阅读(257)  评论(0编辑  收藏  举报