The Pairing-Based Cryptography Library

Programming in Linux

This guide is aimed at developers who are familiar with using Linux but are less acquainted with typical Linux development tools, and who do not have root access to the box they are working on. It is written with PBC in mind, but should work for most libraries.

This Program Library HOWTO contains a thorough explanation of why libraries are setup the way they are in Linux.

For information on how to use the PBC library, please consult the manual. One of the chapters is a tutorial.

You can skim most of the text and just type in what you see in the examples.

Compiling and Installing Libraries

For most libraries, once you have decompressed the source package, type the following to install it to the .local subdirectory of your home directory.

 $ ./configure --prefix=$HOME/.local
 $ make
 $ make install

Occasionally a library does not conform to this standard, in which case you may have to edit a Makefile or similar to tell it where to install. In this case, there ought to be documentation specifying how to do this.

We call the destination directory .local because it functions as the system-wide /usr/local directory (except that it’s for your user account only), and the preceding period prevents it from cluttering directory listings. (Of course, if you prefer to see everything in your directory listings you don’t need the period, and in this case you may even wish to use --prefix=$HOME.)

If everything worked, you should see new files in assorted subdirectories of $HOME/.local with names such as include, lib and bin.

Compiling Your Code

A PBC program foo.c might look like the following.

#include "pbc.h"

int main(void)
{
    /* call PBC functions */
    return 0;
}

Simply typing gcc -o foo foo.c will fail for two reasons.

Firstly, gcc does not know where to find the include file pbc.h. You must explicitly tell gcc where to do this, using the -I option, because gcc normally only searches the standard system-wide include directories.

However, even if this is done correctly, the compilation still fails, this time because the library file (which contains the compiled library routines) has not been mentioned in any way. Not only do you have to mention which library you want to link with using the -l option, you must also tell gcc where to find it because the library is somewhere in your home directory and not in a standard location. This can be done with the -L option.

But even if you did all this, although your program would compile, it would not run. This is because it is dynamically linked (that is, the library routines are not placed in the binary so when run, the program needs to know where to find the library).

There are two ways around this. One is to use the -static option which will put all the required library routines in your binary. Your binary will be a lot bigger, and every time you upgrade your library you have to recompile the binary. On the other hand, it may be faster.

The other way is to embed the location of the library in the binary. This can only be done by the linker, not the compiler, so we use the -Wl option to pass another option on to the linker. The linker option we want is the -rpath option (which is sometimes called the -R option).

Thus to compile foo.c type:

 $ gcc -o foo foo.c -I ~/.local/include/pbc -L ~/.local/lib -Wl,-rpath ~/.local/lib  -l pbc

LD_LIBRARY_PATH

Actually, there is another way, but it is considered harmful.

If you add $HOME/.local/lib to the environment variable named LD_LIBRARY_PATH all binaries will now look in that directory for any libraries they need.

I recommend only doing this in special situations. For example, if you moved the library to a different location and want to test a binary without recompiling, or if you forgot to use the rpath option and you want to test the binary without recompiling.

Makefiles

Typing in all these options is an annoyance. You can eliminate the need for the -L and -rpath options with environment variables LDFLAGS or LD_RUN_PATH, but you still have to type the other ones.

One solution to this is to use the make program. You should eventually follow a proper make tutorial, but for now, create a file named Makefile with the following contents.

target:
        gcc -o foo foo.c -I ~/.local/include/pbc -L ~/.local/lib -Wl,-rpath ~/.local/lib  -l pbc

The second line must begin with a tab and not spaces, otherwise it will not work.

Now running make will compile your program.

But Why…

You may be wondering why there’s a pbc on the end of the -I option but not the -L option. This is PBC’s fault: instead of having a single header file named "pbc.h", there are many other header files that the developer never needs to know about, and to stop them messing up the include directory, all the PBC header files are placed in a separate subdirectory of their own. Other libraries also follow this convention.

It might seem pointless to have an rpath option. Why not have the binary automatically search for the library in the directory specified by the -L option? While this may suit you now, situations where this behaviour is undesirable can easily occur. For example, say you don’t have root access on the system you develop on and the "Foo" library is not installed (so you need the L option), but on the target systems that your binaries end up on, the "Foo" library is always found in a standard location (so you don’t want the rpath option). Or maybe "Foo" is located somewhere special on the target machine, so you want rpath to point to a different directory altogether.