Introduction

For ease of usage and re-usability we can compile C procedures using GCC and distribute as library. Static libraries are bundled directly with executable program, for that program size increases but don’t have to worry about library runtime dependencies.

Usage

For this article we will use a simple program. First we will run the program, then will split into files and reuse some part as static library.

// main.c
#include <stdio.h>

void printDecorated(char* message) {
    printf("- %s -\n", message);
}

void printGreetings(int n) {
    for (int i = 0; i < n; i++) {
        printDecorated("Hello");
    }
}

int main () {
    printGreetings(3);
    return 0;
}

Now we can compile and run using following commands, -o for naming executable name:

$ gcc -o main main.c
$ ./main
- Hello -
- Hello -
- Hello -

Now we can reorganize the functions in separate files. Lets move printDecorate function in decorate.c and printGreetings in greeter.c file. We also create a header file with these function prototypes greet.h and update include statements.

// greet.h
void printGreetings(int);
void printDecorated(char *);
// decorate.c
#include <stdio.h>

void printDecorated(char* message) {
    printf("- %s -\n", message);
}
// greeter.c
#include <stdio.h>
#include "greet.h"

void printGreetings(int n) {
    for (int i = 0; i < n; i++) {
        printDecorated("Hello");
    }
}
// main.c
#include <stdio.h>
#include "greet.h"

int main () {
    printGreetings(3);
    return 0;
}

For compiling and running we use following commnads:

$ gcc -o main decorate.c greeter.c main.c
$ ./main
- Hello -
- Hello -
- Hello -

Note we have included using "greet.h" not <greet.h>. This will work as long as greet.h is in same folder. By default gcc searches for include files in /usr/include/ or /usr/local/include/. We can also add additional path using gcc -I option.

Now if we change the include statement of main.c and greeter.c to <greet.h>. We can compile like below:

$ gcc -I "$PWD" -o main decorate.c greeter.c main.c

Or we can copy greet.h in /usr/include/ or /usr/local/include/, then we can compiler directly.

$ gcc -o main decorate.c greeter.c main.c

For creating reusable library first we have to compile only the files we want to include in library using -c option. Then all object file are bundled using ar command. -s option is added for creating index in archive. Indexing a library fasten linking. Library must be prefixed with lib and ar binary ends with .a.

$ gcc -I "$PWD" -c greeter.c decorate.c
$ ls
decorate.c decorate.o greeter.c greeter.o greet.h main.c

# Create archive named 'libgreet.a'
$ ar -rsc libgreet.a decorate.o greeter.o

# We can view the symbol table using nm -s
$ nm -s libgreet.a

Archive index:
printDecorated in decorate.o
printGreetings in greeter.o

decorate.o:
                 U _GLOBAL_OFFSET_TABLE_
0000000000000000 T printDecorated
                 U printf

greeter.o:
                 U _GLOBAL_OFFSET_TABLE_
                 U printDecorated
0000000000000000 T printGreetings

Now we can compile using libgreet.a. libgreet.a must be after main.c for successful compilation.

$ gcc -I "$PWD" -o main main.c ./libgreet.a

We can also add library reference using -l option. This will search for library in /usr/lib/ and /usr/local/lib. We can add additional path using -L option.

# Note added as -lgreet not libgreet
$ gcc -I "$PWD" -L "$PWD" -o main main.c -lgreet

Now if we copy the libgreet.a in /usr/local/lib/ or /usr/lib/ and copy greet.h in /us/local/include/ or /usr/include/, then we can compile like below.

$ gcc -o main main.c -lgreet

Now lets write these steps in a make file. Create a file Makefile in same directory and copy following code.

.DEFAULT_GOAL:= run
.SILENT:

libgreet.a: greeter.c decorate.c greet.h
	gcc -I. -c greeter.c decorate.c
	ar -rsc libgreet.a greeter.o decorate.o

build: greet.h main.c libgreet.a
	gcc -I. main.c libgreet.a -o main

clean:
	rm -f greeter.o decorate.o libgreet.a main

run: build
	./main && make -s clean

Now run using following command:

$ make

Tools Version

  • gcc (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0
  • GNU Make 4.1

Bookmarks