Use libraries with the GCC

Libraries are collections of reusable code, which can make coding easier and more effective. Understand library naming conventions and the distinction between static and dynamic linking. Link applications with static or dynamic libraries with GCC, and optimize with Link Time Optimization (LTO).

Library naming conventions

System libraries require consistent naming. A library known as foo is expected to exist as file libfoo.so or libfoo.a. This convention is automatically understood by the linking input options of the GNU Compiler Collection (GCC), but not by the output options:

  • When linking against the library, the library can be specified only by its name foo with the -l option as -lfoo:
    $ gcc ... -lfoo ...
  • When creating the library, the full file name libfoo.so or libfoo.a must be specified.

Static and dynamic linking

When building C or C++ applications, you must use dynamic linking. Static linking reduces compatibility and prevents timely library security updates.

Comparison of static and dynamic linking
Static linking makes libraries part of the resulting executable file. Dynamic linking keeps these libraries as separate files.

Static linking has numerous disadvantages and should be avoided, particularly for whole applications and the glibc and libstdc++ libraries:

Resource use: Static linking results in larger executable files which contain more code. Libraries contribute extra code that is not shared across programs on the system. That behavior increases file system usage and memory usage at run time. Multiple processes running the same statically linked program will still share the code.

However, static applications need fewer runtime relocations, leading to reduced startup time, and require less private resident set size (RSS) memory. Generated code for static linking can be more efficient than for dynamic linking due to the overhead introduced by position-independent code (PIC).

Security: Dynamically linked libraries that provide ABI compatibility can be updated without changing the executable files depending on these libraries. This is especially important for libraries provided by Red Hat as part of Red Hat Enterprise Linux, where Red Hat provides security updates. Static linking against any such libraries is strongly discouraged.

Compatibility: Static linking seems to provide executable files independent of the versions of libraries provided by the operating system. However, most libraries depend on other libraries. With static linking, this dependency becomes inflexible and as a result, both forward and backward compatibility is lost. Static linking is guaranteed to work only on the system where the executable file was built.

Warning

Applications that statically link against the GNU C library (glibc) still need glibc present on the system as a dynamic library.

Furthermore, the glibc dynamic library at run time must exactly match the version present at link time.

As a result, static linking works only on the system where you built the executable file.

Support coverage: Most static libraries provided by Red Hat are in the CodeReady Linux Builder channel and not supported by Red Hat.

Functionality: Some libraries, notably the GNU C Library (glibc), offer reduced functionality when linked statically.

For example, when statically linked, glibc does not support threads and any form of calls to the dlopen() function in the same program.

Cases for static linking

Static linking might be a reasonable choice in some cases, such as:

  • When using a library that is not enabled for dynamic linking.
  • When fully static linking is required for running code in an empty chroot environment or container. However, static linking by using the glibc-static package is not supported by Red Hat.

Library use with GCC

A library is a reusable package of code. A C or C++ library consists of the library code and header files.

Compiling code that uses a library
The header files describe the interface of the library: the functions and variables available in the library. Information from the header files is needed for compiling the code.

Typically, header files of a library will be placed in a different directory than your application’s code. To tell GCC where the header files are, use the -I option:

$ gcc ... -Iinclude_path ...

Replace include_path with the actual path to the header file directory.

For example, to specify a relative path some/interesting/directory:

$ gcc ... -Isome/interesting/directory ...

The -I option can be used multiple times to add multiple directories with header files. When looking for a header file, these directories are searched in the order of their appearance in the -I options.

Linking code that uses a library

When linking the executable file, both the object code of your application and the binary code of the library must be available. The code for static and dynamic libraries is present in different forms:

  • Static libraries are available as archive files. They contain a group of object files. The archive file has a file name extension .a.
  • Dynamic libraries are available as shared objects. They are a form of an executable file. A shared object has a file name extension .so.

To tell GCC where the archives or shared object files of a library are, use the -L option:

$ gcc ... -Llibrary_path -lfoo ...

Replace library_path with the actual path to the library directory.

The -L option can be used multiple times to add multiple directories. When looking for a library, these directories are searched in the order of their -L options.

The order of options matters: GCC cannot link against a library foo unless it knows the directory with this library. Therefore, use the -L options to specify library directories before using the -l options for linking against libraries.

Compiling and linking code which uses a library in one step
When you compile and link in a single gcc command, combine the compile-time and link-time options.

Link static libraries with the GCC

To link static libraries, bundle them as archives that contain object files. After linking, they become part of the resulting executable file. Static linking overrides the default dynamic linking behavior.

Before you begin

  • GCC must be installed on your system. For details, see Installing development tools for C and C++.
  • You must understand static and dynamic linking.
  • You have a set of source or object files forming a valid program, requiring some static library foo and no other libraries.
  • The foo library is available as a file libfoo.a, and no file libfoo.so is provided for dynamic linking.

About this task

Note

Static linking embeds library code in the executable file. When you statically link against libraries that Red Hat Enterprise Linux provides, security updates to those libraries are not applied through routine package updates to shared objects. Use static linking only when you need a self-contained binary or when a library is available for static linking only.

Most libraries that are part of Red Hat Enterprise Linux support dynamic linking only. The remaining steps in this procedure apply only to libraries that do not support dynamic linking.

Procedure

  1. In the command line, go to the directory containing your source or object files and the static library foo (libfoo.a).
  2. Compile the program source files with headers of the foo library:
    $ gcc ... -Iheader_path -c ...

    Replace header_path with a path to a directory containing the header files for the foo library.

  3. Link the program with the foo library:
    $ gcc ... -Llibrary_path -lfoo ...

    Replace library_path with a path to a directory containing the file libfoo.a.

  4. Run the program:
    $ ./program
    Warning

    The -static GCC option related to static linking forbids all dynamic linking. Instead, use the -Wl,-Bstatic and -Wl,-Bdynamic options to control linker behavior more precisely.

Use a dynamic library with the GCC

Dynamic libraries are available as standalone executable files, required at both linking time and run time. They stay independent of your application’s executable file.

Before you begin

  • GCC must be installed on the system. For details, see Installing development tools for C and C++.
  • A set of source or object files forming a valid program, requiring some dynamic library foo and no other libraries.
  • The foo library must be available as a file libfoo.so.

Procedure

  • To link a program against a dynamic library foo:
    $ gcc ... -Llibrary_path -lfoo ...
  • To use a run path value stored in the executable file:

    The run path is a special value saved as a part of an executable file when it is being linked. Later, when the program is loaded from its executable file, the runtime linker uses the run path value to locate the library files.

    1. While linking with GCC, store the path library_path as run path:
      $ gcc ... -Llibrary_path -lfoo -Wl,-run path=library_path ...

      The path library_path must point to a directory containing the file libfoo.so.

      Important

      Do not add a space after the comma in the -Wl,-run path= option.

    2. Run the program:
      $ ./program

      On Red Hat Enterprise Linux 10, the run path encoded in the program during linking is used only if the linked libraries are not found in LD_LIBRARY_PATH. You can use the -Wl,--disable-new-dtags option to restore the old behaviour in Red Hat Enterprise Linux 10, where the run path is searched before the LD_LIBRARY_PATH.

  • To use the LD_LIBRARY_PATH environment variable:

    Another way to set search paths to locate libraries is to use the LD_LIBRARY_PATH environment variable. The value of this variable must be changed for each program. This value should represent the path where the shared library objects are located and must be set for every program invocation.

    1. Set the LD_LIBRARY_PATH environment variable:
      $ export LD_LIBRARY_PATH=library_path:$LD_LIBRARY_PATH
    2. Run the program:
      $ ./program
  • Optional: Place the library into the default directories.

    The runtime linker configuration specifies a number of directories as a default location of dynamic library files. To use this default behaviour, copy your library to the appropriate directory.

Static and dynamic libraries with GCC

Combining static and dynamic linking balances portability and efficiency. The GNU Compiler Collection (GCC) automatically selects shared objects over static archives unless you configure it otherwise. That resolution order determines which library versions to link and which linker options apply.

Static libraries are packaged as libname.a archive files. Dynamic libraries are packaged as libname.so shared objects. Together, those are the two shapes gcc must choose between when both linking modes are available for the same library name.

For each -lfoo option, gcc searches the library directories (including paths from -Lpath) for libfoo.so first and libfoo.a second. Depending on what gcc finds on the search path, linking proceeds in one of these ways:

  • Only the shared object is found, and gcc links against it dynamically.
  • Only the archive is found, and gcc links against it statically.
  • Both the shared object and archive are found, and by default, gcc selects dynamic linking against the shared object.
  • Neither shared object nor archive is found, and linking fails.

Because of these rules, the best way to select the static or dynamic version of a library for linking is having only that version found by gcc. This can be controlled to some extent by using or leaving out directories containing the library versions, when specifying the -Lpath options.

Additionally, because dynamic linking is the default, the only situation where linking must be explicitly specified is when a library with both versions present should be linked statically. There are two possible resolutions: specifying the static libraries by file path instead of the -l option, or using the -Wl option to pass options to the linker.

Specifying the static libraries by file

Usually, gcc is instructed to link against the foo library with the -lfoo option. However, it is possible to specify the full path to file libfoo.a containing the library instead:

$ gcc ... path/to/libfoo.a ...

From the file extension .a, gcc will understand that this is a library to link with the program. However, specifying the full path to the library file is a less flexible method.

Using the -Wl option

The gcc option -Wl is a special option for passing options to the underlying linker. Syntax of this option differs from the other gcc options. The -Wl option is followed by a comma-separated list of linker options, while other gcc options require space-separated list of options.

The ld linker used by gcc offers the -Bstatic option to link libraries following this option statically, and -Bdynamic to link them dynamically. After passing -Bstatic and a library to the linker, the default dynamic linking behaviour must be restored manually for the following libraries to be linked dynamically with the -Bdynamic option.

Link a program with library first statically (libfirst.a) and second dynamically (libsecond.so):

$ gcc ... -Wl,-Bstatic -lfirst -Wl,-Bdynamic -lsecond ...
Note

gcc can be configured to use linkers other than the default ld.