HOW TO CREATE A LIBRARY OF YOUR OWN C FUNCTIONS

INTRODUCTION

After you have written the canonical "Hello World!" program or one that blinks LEDs, you will probably start to collect a number of home-grown functions that you use repeatedly. You've probably added the source for these to each of your programs that use them, but find that updating them is time-consuming and prone to error or worse, allows the code for your functions to diverge over time.

Now is the time to take the next step and create a library that contains all your functions in a form that can be linked at compile time. This means a single central library of your functions with the ability for any program to link and use them. At the same time you should create a set of corresponding header files that, as a minimum, declare your function names.

This page does not explain the intricacies of separating function source code and header files, nor details on using extern.

THINGS TO CONSIDER

You need to decide whether to create a static or dynamic library.

Here, we will use dynamically-linked libraries. Dynamic libraries have a .so suffix, static ones a .a suffix.

Sort out and correct your C functions, adding extern if you are splitting them up and need to share variables. extern means that some other file will define the variable but this function needs to be able to reference it. An extern variable declaration can be placed in, say, a header file and the actual definition added (without the extern or static attributes) to a source file somewhere else.

Create a C header file (.h) and put in it a declaration of the function with its correct return and argument types. If the function uses any #defines then put them in the header file with protection around them to stop attempts to #define them more than once. Use #ifndef something-unique and #endif to prevent duplicate #defines and put a #define something-unique just before the #endif to prevent any attempts to redefine them later. You must decide what to use for something-unique as it must not conflict with anything else associated with your program or anything that the system uses. There's a good explanation here.

Compile your C function with the options for compile-only and position-independent-code:

gcc func.c -c -fpic

This creates a file func.o that contains object code.

Create shared library from the object file. Library files usually begin with lib. If they do, this means that when you compile a program you can link it with your library by specifying -lname rather than giving the whole name - the lib and .so are implied.

gcc -shared -o libfunc.so func.o

This creates a library called libfunc.so. The linker needs to be told where to find libraries; you have a number of options. You can:

  1. use the gcc option -L followed immediately by the path to libfunc.so when you compile your program
  2. add to the environment variable LD_LIBRARY_PATH the path to the directory where your library is located
  3. copy or move your library to one of the default library folders, e.g. /usr/local/lib. This requires some additional work that is explained later

You can now compile a program and link it with your library. The linker presumes that the library name ends with .so, so you can omit that along with the lib part. The following three methods are all equivalent:

  1. If your library is in your home directory:

    gcc prog.c -o prog -lfunc -L/home/~

  2. If you have added the path to the directory where your library is located to the environment variable LD_LIBRARY_PATH:

    gcc prog.c -o prog -lfunc

  3. If you have copied the library to a default directory and updated the config file and cache:

    gcc prog.c -o prog -lfunc

At this point you have compiled your C function, created a library and put it in a default location or changed the LD_LIBRARY_PATH to point to the it. The next step is to put the header file in the correct location. The best place is in /usr/include. Using this location means you can put #include <libfunc.h> in your C source rather than #include "potentially-long-path-to-your-file.h".

Once your header file is completed and tested, you can simply copy it to its final location:

cp libfunc.h /usr/include

Making your library available across the system

You will need admin privileges for this - prefix each command with sudo. Copy the library to /usr/local/lib. Note that /usr/lib is reserved for libraries that come with the system while /usr/local/lib is intended for third party libraries like yours.

sudo cp /home/~/libfunc.so /usr/local/lib

Change the mode so that other users have read and execute access but not write:

sudo chmod 0755 /usr/local/lib/libfunc.so

Create a link to the new library and update the cache so that it is available for use immediately:

sudo ldconfig

The last step is to check that your library is configured for use. You can do this using the ldconfig -p command and piping the output to grep to filter it. If your library is not listed then there's a problem with its name, location or an error with the ldconfig command.

ldconfig -p | grep libfunc

      libfunc.so (libc6,hard-float) => /usr/local/lib/libfunc.so