Let’s dive into a short bit of C source code:
#include <stdio.h>int main(void)
At the top, we included <stdio.h>, the standard input output header, in which the printf function is declared.
What Are Header Files and What Are Libraries
Header files, such as stdio.h, contain function declarations and macro definitions to be shared between source files. They tell the compiler how to call some functionality, without knowing how the functionality works.
Libraries are where the actual functionality is implemented because they contain the function definition. Libraries have two types:
- Static (we’ll discuss static libraries in this blog post)
- Dynamic (to be discussed at a later time)
A library is essentially a collection of functions, variables, and symbols.
What Do C Static Libraries Have in Common With Your Kitchen
Imagine that your family likes to eat jerk chicken, meat lasagna, and pumpkin pie every week. They are picky eaters and you make it the same way every week because you know that the recipe works.
Now you want easy and fast access to your recipes, so you keep them together and even index them.
Static libraries are like the recipes you use in your kitchen because you can keep a collection of functions in an easily accessible, indexed, and reusable manner.
Reasons to Use Static Libraries:
- As programs grow, using libraries makes it easier to manage code.
- You don’t have to keep rewriting the same functions that you use frequently.
- They are great for reusability, as well as collaborating with other programmers.
- If your object files are in a library and indexed, fewer files need to be searched and opened, and access is faster.
How Do Static Libraries Work
Recall the four steps of compilation.
- Preprocessing: removes comments and deals with # directives
- Compilation: pre-processed code is converted to assembly code
- Assembly: code is converted to machine code (zeros and ones), also known as object code
- Linking: produces the executable
In Step 4, linking tries to resolve referenced symbols and locate in which object file the symbols are defined. The object code in your program is copied into the executable.
If we have a static library with object files and an index of defined symbols (versus object files on different disks), the linking process is faster. Our program is also more portable because we don’t have to depend on the particular libraries that are on the system.
How to Create Static Libraries
- Create a header file with your function prototypes and include the header file in your C source files.
#define WENDYBLOGTECH_Hint _putchar(char c);
int _isalpha(int c);
int _abs(int n);
int _strlen(char *s);
void _puts(char *s);
char *_strcpy(char *dest, char *src);
char *_strcat(char *dest, char *src);
char *_strncat(char *dest, char *src, int n);
int _strcmp(char *s1, char *s2);
char *_memcpy(char *dest, char *src, unsigned int n);
char *_strstr(char *haystack, char *needle);#endif
2. Compile your C source files without linking by using the gcc
gcc -Wall -pedantic -Werror -Wextra -c *.c
The -c flag compiles your C source files but does not link. You’ll now see files with .o extension in your directory.
3. Create a static library (archive) with the
ar -rc <libraryname.a> *.oexample: ar -rc libwendyblogtech.a *.o
-rflag creates a new archive and then adds the objects to the archive. The
-cflag suppresses the output that says we’re creating a new archive.
4. Use the
artool with the
-tflag to display a list of the contents of the archive.
ar -t <libraryname.a>example: ar -t libwendyblogtech.a
ranlibto generate an index to the contents of the archive.
ranlib <libraryname.a>example: ranlib libwendyblogtech.a
nmto list symbols from the object files.
$ nm libwendyblogtech.a0-strcat.o:
0000000000000000 T _strcat1-memcpy.o:
0000000000000000 T _memcpy1-strncat.o:
0000000000000000 T _strncat2-strlen.o:
0000000000000000 T _strlen2-strncpy.o:
0000000000000000 T _strncpy3-puts.o:
0000000000000000 T _puts3-strcmp.o:
0000000000000000 T _strcmp4-isalpha.o:
0000000000000000 T _isalpha5-strstr.o:
0000000000000000 T _strstr6-abs.o:
0000000000000000 T _abs_putchar.o:
0000000000000000 T _putchar
How to Use Static Libraries
Now that we have our static library, let’s invoke the library after writing a program that uses the _puts function from the library.
Note that at the top, we put the filename in “ ” quotes instead of <> brackets because wendyblogtech.h is our own header file and not a system header file.
#include "wendyblogtech.h"int main(void)
_puts("\"That's how you create a static libary.\"");
Invoking a library:
Example of invoking libwendyblogtech.a:gcc quote.c -L. -lwendyblogtech -o quote
-Llooks in the directory for library files and because we have a period right after it, it will look in the current directory.
-llinks the library file and automatically adds the lib prefix and the .a, hence the reason why we don’t type the entire libwendyblogtech.a
Now we run our executable program
./quote and see the output:
"That's how you create a static library."
There you have it… static libraries are like the recipes you use in your kitchen because you can keep a collection of functions in an easily accessible, indexed, and reusable manner.