The first step to write a C library is to pick a directory for the library, i chose ~/.c. Lets start with a basic directory structure with include/, lib/, and test/. These directories are not a requirement but they’ll make the project more organized. Each directory has its own purpose:

  • include/ contains function prototypes, struct definitions, and preprocessor directives
  • lib/ contains the actual library code (function, etc)
  • test/ tests the library code

lets ignore test/ for a moment and focus on include/ and lib/. This is an overview of the project’s root directory:

.c
├── include
│   ├── crc.h
├── lib
│   ├── crc.c
│   ├── crc.o
│   ├── libcrc.a
│   └── Makefile
└── Makefile

the file contents are:

> cat include/crc.h
#ifndef CRC_H
#define CRC_H 1
int max(int a, int b);
#endif

> cat lib/crc.c
#include <crc.h>
int max(int a, int b)
{
    return a>b?a:b;
}

The library is quite simple and contains a single function, max(). Now lets compile it:

gcc -Wall -g -c -o crc.c -o crc.o

create the static library file:

ar ruv libfirst.a first1.o first2.o

and that’s it. Now the library is ready to be included in C programs. For example the following program uses the newly created crc library:

#include <stdio.h>
#include <crc.h>
void main(void) { printf("%d\n",max(1,2)); }

compile and run the progam:

$ gcc -o max_tset max_test.c -I$HOME/.c/include -L$HOME/.c/lib -lcrc
$ ./max_test
2

it works.

Last thing is to answer the question: Why are libraries useful? To quote from Wikipedia:

The value of a library lies in the reuse of the behavior. When a program invokes a library, it gains the behavior implemented inside that library without having to implement that behavior itself. Libraries encourage the sharing of code in a modular fashion, and ease the distribution of the code.

In a future post i’ll cover how to test C library code.