Libraries with code instead of books-

All about static libraries in C

Soledad Frechou
7 min readOct 12, 2020

Libraries? In programming?

These so called libraries kind of have a similarity with real life libraries in that they include a lot of functions (books) that can be referenced any time. There is no need for you to have every single book available at home, you can make use of the public library in order to read or reference whichever book you’re interested in. The same goes with libraries in C, they hold functions, variables and more, which you could reference and make use of at any time in your program without having to define them every time.

Writing code is all about optimization, so when creating your program or application, the more code and functions you can reuse, the better and cleaner your final product. In order to reuse functions, libraries are a must and will become your new best friends. Libraries can be standard and global — included in the operating system by default for you to reference whenever, or they can be created with whichever functions you want.

To get into a more technical language, in programming, libraries are files that contain objects that will be compiled together with a program file. Each library has many objects inside that are referenced in the same file. These objects could be functions, variables, and more, that are used within the program and defined in the header files. The word ‘object’ does not mean that it is object-oriented as in a ‘thing’. In programming, ‘object’ refers to an intermediate compiler output language, with an .o extension.

The libraries are compiled to the program file in the Linking step of compilation. For more information on the compilation process, check out this blog entry.

See last step: Linking

There are two main types of libraries in C: Static and Dynamic. In this article we’ll focus on Static Libraries, but will define both for pure knowledge purposes:

  • Static library. (lib) A Static library or statically-linked library is a set of routines, external functions and variables which are resolved in a caller at compile-time and copied into a target application by a compiler, linker, or binder, producing an object file and a stand-alone executable. This executable and the process of compiling it are both known as a static build of the program. Historically, libraries could only be static.
    They are usually faster than the shared libraries because a set of commonly used object files is put into a single library executable file. One can build multiple executables without the need to recompile the file. Because it is a single file to be built, use of link commands are simpler than shared library link commands, because you specify the name of the static library.
  • Dynamic or Shared libraries are .so (or in Windows .dll, or in OS X .dylib) files.
    These are linked dynamically simply including the address of the library. Dynamic linking links the libraries at the run-time. Therefore, all the functions are in a special place in memory space, and every program can access them, without having multiple copies of them.
image from: https://medium.com/swlh/linux-basics-static-libraries-vs-dynamic-libraries-a7bcf8157779

Easily put, functions used in files could be defined and coded within the same program file. If only one function is used, this is no problem, but when using more than one, defining many functions within the same program could result in a long tedious and confusing code. Also, this would mean that every function needs to be defined in every program file that uses it. This is not optimal and adds up hundreds of lines of bulky code.

Why use libraries?

This is where libraries come in handy. Instead of defining functions in every file, functions can be bundled up in a library file. This file can then be called within the program once and the functions can be used as many times as needed in the program.

Libraries are like a collection of functions and objects used over and over again or that are of common use and there is no need to reinvent every time we want to make use of these functions. Instead, we use the ones already in existence in order to focus on the program we are creating with them.

As programmers, optimization is key in several aspects of our work, such as team working/sharing code, executable file sizes and program run time, use less memory, and save up on disk space.

How do they work?

Libraries can be default by the system or user created. Either way, they have to be declared in a header file and included atop the program where the library is being used.

When compiling, the libraries are included in the executable file in the Linker phase at once, in a single file. This means that the code for these functions becomes available for the program to use. Again, this is better and faster as far as system performance, instead of compiling functions from different spaces in memory. This also means that the executable file has the function code included and does not depend on any external file to work and run.

Then, users can reference them and use as many times as needed without having to define the functions every time, instead just by declaring the library within the program.

How to create a static library?

The first step to create a static library is to gather all the .c files we want to include in out library and place them in the same directory. Like so:

This is a big collection of functions that carry out different actions such as identifying if a letter is upper or lowercase, if a chracter is a digit, the length of a string and more. If we were to need these functions within any program, it would be time consuming to write them out every time. Instead, we will zip them in a library to reference every time we want to use them.

To do so, we have to to compile these .c files — but stop after the Assembler phase, by adding the -c option to our gcc compilation. The output will be our .c files transformed into objects (.o files, not objects as “things” but objects as an intermediate compilation state of file in a specific language, like we said before.)

gcc -c *.c Where the -c flag stops after the Assembler and *.c will compile all the files with a .c extension. Now, we can see all our previous .c files have an .o extension:

Static libraries are created using the ar command (for archiver). This command is used in Linux to create, modify, and extract files from archives. An archive is a collection of files that have a similar structure from which the individual files can be extracted.

ar takes object files .o , as many as we want to include in the library and mashes them up all together into a .a file — our static library! We will run the ar command with the following flags and options:

ar -rc mylibrary.a <filename>.o

Where:

  • The rflag will replace older object files in the library, with the new object files, and the cflag tells ar to create the library if it doesn’t already exist.
  • mylibrary is the name of the library to be created with my original functions inside. This means that if I wanted to use my functions, instead of defining every function inside my code or linking each function independently, I could use them through the library.
  • <filename>.o is every name of every object file I want to include in my library.

After an archive is created, or modified, it is recommended to index it. Some archivers will do so automatically, depending on the operating system, but just to be sure it is best to run the command. This index is later used by the compiler to speed up symbol-lookup inside the library, and to make sure that the order of the symbols in the library won’t matter during compilation.

The command used to create or update the index is called ranlib, and is used as follows:

ranlib mylibrary.a

So now that we’ve created our object files from our program files, compressed them in up an library and indexed it, we can now make use of the library.

How to use a static library?

Now that the library is created with whatever functions we wanted to include, it is now available to use by any other user and program.

To do so, just run the compilation command with the specific options and flags that allow the use of the library. For example:

gcc my_program.c -L. -lmylibrary -o my_program

Where:

  • gcc is the compilation command
  • my_program.c is the program I want to compliate
  • -L. will tell the compilator to look in this directory for library files. It opens the option that a library will be looked for.
  • -l (mind the caps!) will be followed by the name of the library we created (without the “lib” and the extension “.a”- -l will handle this info)
  • -o my_program indicates the output file name.

— — — — — — — — — — — — — — —

Libraries are a very optimal way of using and reusing existing functions in order to further reduce the amount of lines of code written per program, improve memory usage and the overall program run-time. They are easy to create and hopefully this article clarified further more their existance and usage alltogether.

Please feel free to use the comment section for any additions or notations on what stated here, and if you made it this far, thanks for reading!

:)

--

--