Jun 8, 2016

C Programming #63: How to write a static library

C Programming #63: How to write a static library

This article will explain how to write a static C library. We will try to write new library fact which will have function factorial (which as name implies would calculate the factorial of the number). You can find the method and implementation of function in article Function - recursion. This article aim to convert the same function factorial into a library. If a piece of code would be re-used inside a one application we turn into a function, if the same function would be reused accross multiple application such a function should be put in a library. There are two type of libraries.

  • Statically Linked library
  • Dynamically Linked library

This article explains the statically linked library, comparison of both would be done at the end of Dynamically linked library.


Any library needs

  • .h file/files - which can be included by application using this library.
  • .c file/files - which will have actual implementation.

Note for simplicity only one .c and .h will be used. Also note that library won't contain any main. main function should be there in the application which is using the library. For our example lets write library libfact.a using fact.h and fact.c.

fact.h implementation looks like this

#if !defined(__FACT_)
#define __FACT_ 1

/* Function implemeting factorial of a number */
extern int factorial(int x);

#endif /* __FACT_ */

fact.c implementation looks like this

#include "fact.h"
int factorial(int x)
{
   int temp_fact;
   if(x == 1) {
      temp_fact = 1;
   } else {
      temp_fact = x * factorial(x - 1);
   }
   return temp_fact;
}

If you look closely same earlier implementation of factorial is divided into fact.c and fact.h. We need to create now statically linked library using the following command

$ gcc -c fact.c -o fact.o

This would create the object file (machine code) implementation fact.c. Looking to fact.o using nm utility

$ nm fact.o 
0000000000000000 T factorial

Hence fact.o has the symbol definition of function factorial. zero infront of it implies that it is un-allocated.

Library is created by archiving (combining several .o files, in our case it is just one). Command is as follows.

$ ar rcs libfact.a fact.o

output of it would be libfact.a, again nm-ing on it.

$ nm libfact.a 

fact.o:
0000000000000000 T factorial

ar just combines all the .o files. Now libfact.a could be statically linked to any application.

Following is application app.c which will be statically linked to libfact.a

#include <stdio.h>
#include "fact.h"
int main()
{
   int fact, n = 4;

   fact = factorial(n);

   printf("Factorial of n is %d\n", fact);

   return 0;
}

Now static linking is done as follows

$ gcc -static app.c -L. -lfact -o app

It will create a binary app. Which can be run on prompt as follows.

$ ./app
Factorial of n is 24

To know what type of linking we can run file command on app

$ file app
app: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), \
statically linked, for GNU/Linux 2.6.32, \
BuildID[sha1]=eadcaf6ad76b22e5ce20c95786c6dbfaa253edb6, not stripped

Which clearly states that it is statically linked. Statically linked would include the implementation of factiorial inside the binary app. Size of would be appreciably high. (As it would statically link even the libc, which include printf implementation).

$ ls -l app
-rwxrwxr-x   1 hsk            hsk        909144 2016-06-08 19:26 app

No comments :

Post a Comment