\[ \newcommand\inv{^{-1}}\newcommand\invt{^{-t}} \newcommand\bbP{\mathbb{P}} \newcommand\bbR{\mathbb{R}} \newcommand\defined{ \mathrel{\lower 5pt \hbox{${\equiv\atop\mathrm{\scriptstyle D}}$}}} \] Back to Table of Contents

24 Compilers and libraries

24.1 An introduction to binary files

Top > An introduction to binary files

In this section you will be introduced to the different types of binary files that you encounter while programming.

One of the first things you become aware of when you start programming is the distinction between the readable source code, and the unreadable, but executable, program code. In this tutorial you will learn about a couple more file types:

You will now learn how these types of files are created and used.

24.2 Simple compilation

Top > Simple compilation

In this section you will learn about executables and object files.

Let's start with a simple program that has the whole source in one file. \listing{One file: hello.c}{tutorials/compile/c/hello.c} Compile this program with your favourite compiler; we will use gcc in this tutorial, but substitute your own as desired. As a result of the compilation, a file a.out is created, which is the executable.

hello world
You can get a more sensible program name with the -o option:
hello world

Now we move on to a program that is in more than one source file. \listing{Main program: fooprog.c}{tutorials/compile/c/fooprog.c} \listing{Subprogram: fooprog.c}{tutorials/compile/c/foosub.c} As before, you can make the program with one command.

hello world
However, you can also do it in steps, compiling each file separately and then linking them together.
hello world
The -c option tells the compiler to compile the source file, giving an object file . The third command than acts as the linker , tieing together the object files into an executable. (With programs that are spread over several files there is always the danger of editing a subroutine definition and then forgetting to update all the places it is used. See the `make' tutorial, section  , for a way of dealing with this.)

24.3 Libraries

Top > Libraries

In this section you will learn about libraries.

If you have written some subprograms, and you want to share them with other people (perhaps by selling them), then handing over individual object files is inconvenient. Instead, the solution is to combine them into a library. First we look at static libraries , for which the archive utility ar is used. A~static library is linked into your executable, becoming part of it. This may lead to large executables; you will learn about shared libraries next, which do not suffer from this problem.

Create a directory to contain your library (depending on what your library is for this can be a system directory such as /usr/bin), and create the library file there.

\indextermtt{nm} command tells you what's in the library:

00000000 T _bar
         U _printf
Line with T indicate functions defined in the library file; a~U indicates a function that is used.

The library can be linked into your executable by explicitly giving its name, or by specifying a library path:

# or
hello world
A third possibility is to use the LD_LIBRARY_PATH shell variable. Read the man page of your compiler for its use, and give the commandlines that create the foo executable, linking the library through this path.

Although they are somewhat more complicated to use, shared libraries have several advantages. For instance, since they are not linked into the executable but only loaded at runtime, they lead to (much) smaller executables. They are not created with ar, but through the compiler. For instance:

../lib/libfoo.so(single module):
00000fc4 t __dyld_func_lookup
00000000 t __mh_dylib_header
00000fd2 T _bar
         U _printf
00001000 d dyld__mach_header
00000fb0 t dyld_stub_binding_helper
Shared libraries are not actually linked into the executable; instead, the executable will contain the information where the library is to be found at execution time:
hello world
The link line now contains the library path twice: \begin{enumerate}

  • once with the -L directive so that the linker can resolve

    all references, and

  • once with the linker directive \verb+-Wl,-rpath,`pwd`/../lib+ which stores the path into the executable so that it can be found at runtime. \end{enumerate} Build the executable again, but without the -Wl directive. Where do things go wrong and why? You can also fix this problem by using LD_LIBRARY_PATH. Explore this.

    Use the command ldd to get information about what shared libraries your executable uses. (On Mac OS~X, use otool -L instead.) Back to Table of Contents