Banner: ZumGuy Publications and Network

ZumGuy Publications and Network

Making C++ libraries

Posted by Sean on Monday, 2nd October 2017 21:19
If you use C++, you've almost certainly already used a library of some kind. Even the classic "Hello world" program requires one:
#include <iostream> // include the iostream library

int main() {
	std::cout << "Hello world!";
	return 0;
But what if we wanted to write our own? This has several advantages. First off, if we have a function (or many) we want to use in several projects, we can wrap it (or them) in a neat library, and use it time and time again, without tedious copy/pasting. Secondly, if you're working on a big project, it gets messy if you have everything crammed into one
file! We can use libraries to break our functionality up into simpler, more manageable chunks. And last but not least, if we have lots and lots of code, this can take a long time to compile, and this can get wasteful if we're only working on a small part of our project. A library is precompiled, and can save us lots of development time!

Creating the library source code

Lets create a simple library to wrap one function, called
, which takes two numbers and squared them. First off, we want to create our function file,

#include "square.h"

double square(double x) {
	return x*x;
Pretty straightforward. You can already see that we are including another file,
. So we'll create this too:
// square.h

double square(double);
This is what is called a header file. It contains only the declaration of our function
Before we move on to the next step, we want to make a small improvement to our file, with what is called a header guard:

#ifndef SQUARE_H
#define SQUARE_H

double square(double);

This uses preprocessor directives to prevent declaring our functions twice, in case
is somehow included twice. What happens is that the code between the lines
#ifndef SQUARE_H
is only executed if the preprocessor constant
is undefined. If that is the case, define that constant and declare all our functions (just one in this case) - this way declarations will only happen once, because if
is included a second time,
will be defined and the declarations will be skipped.

Now that we have our little library source code ready, let's place it in a folder called
. It could be called anything - in fact it's not even necessary to create it at all - but this name is a popular choice, and it keeps our files nice and tidy.

Let's create a file
outside of
to use our library:
#include <iostream>
#include "lib/square.h"

int main() {
	std::cout << square(5);
	return 0;
As far as the source goes, that's it! Now we have to compile our files to make an executable.

Compiling a file with the library

If we attempt to simply compile our file
we will get an error:
$ g++ main.cpp -o main
/tmp/cc0V8dkz.o: In function 'main':
main.cpp:(.text+0x1c): undefined reference to 'square(double)'
collect2: error: ld returned 1 exit status
can't find the definition of
. What we must do is compile the files separately but without linking them. Linking is the final step in the compilation process, in which all binary files of the various libraries are crammed into one executable. Here's how:
$ g++ -c main.cpp -o  main.o
$ g++ -c lib/square.cpp -o lib/square.o
These two commands will compile the files
, without linking them. Note that this also prevents the compiler from complaining about
not having a
Then we need to line the files manually:
$ g++ main.o lib/square.o -o main
Now we can execute our
file with
and it will behave as expected!

Making a proper library

But what if we have many files we would like to include? This compilation process takes multiple steps and gets very tedious very quickly. We can group many
files into one as follows:
$ ar ruc lib/libsquare.a lib/square.o lib/file2.o [...]
$ ranlib lib/libsquare.a
will create an index for the library and is not required by all systems. The file must be called
in order for it to work.

Finally, we can compile our
file using our library:
$ g++ main.cpp -Ilib -Llib -lsquare -o main
specifies the drectory where the header file
is located,
the location where the library is located, and
specifies to look for the library
Of course, this entire process can be automated with
Posted by Andrew on Wednesday, 4th October 2017 08:53

This will help me a lot. Thank you!

You must be logged in to post messages.