C++ Libraries: Linking and Compiling

What is the -I, the -L, and the –(little L)? Why am I getting so many errors? What’s going on underneath?

C and C++ libraries can be thought of as a conglomeration of functions and new keywords that you are able to use in your code.

To truly understand what libraries are made of, we should first refresh on header and source files.


Header and Source File Example

Header files contain declarations of functions and variables and often have the file extension .h.

Source files contain the definitions of these functions and often have the file extension .cpp or .cc.

As a brief refresher the example below contains a header, source file, and main file for displaying a Birthday.

SP Libraries 1



Declares a class called birthday.





SP Libraries 2



Defines the two Birthday functions specified above.




SP Libraries 3



Creates an instance of the birthday class, and calls the function printDate.




SP Libraries 4


The file structure consists of a main directory containing the .cpp files and the Makefile, and then a separate subdirectory containing the header file as shown:



Here is the Makefile to compile and run the code:

SP Libraries 5



SP Libraries 6

The Makefile is splitting up the compilation process into two stages.

First the .cpp files are being turned into object files with a .o extension, then there is a linking stage where the main.o and the Birthday.o files are linked together to create an executable.

But why was the $(INC) there? When is the $(INC) necessary?

In C++, the #include macro at the beginning of programs tells the preprocessor to replace the instance of #include with the contents of the file.

For example, the main.cpp file includes the Birthday.h header file so that it can reference the declarations of the functions Birthday and printDate.

These functions are not fully defined by the header file, but they are prototyped and able to be referenced without throwing syntax errors.

The new file main.cpp file after being preprocessed is pictured below:

SP Libraries 7

Understanding this, we realize that the preprocessor must be able to access the included file in the compilation.

The file is referenced as Birthday.h, and if the pre-processor were to search the current directory for the file, it would be unable to find it because relative to the main directory the Birthday.h file has the path Headers/Birthday.h.

Therefore, the -I flag tells the preprocessor where it should search for files when compiling.

In this case the flag is including the Headers folder, resulting in the discovery of the file and the replacement of the #include.

The Birthday.o file is created the same way with the same -I, as it must also reference the Birthday.h file for the function declarations it is defining.

Next, linking occurs. After the two object files are created, the Birthday.o object contains functions that the main.o file calls.

The Birthday.o object file now contains both the declaration and the definitions after the preprocessor inserted the contents of the .h file.

Now, we must “link” the two object files together so that the functions called by main.o can be executed from the definitions in Birthday.o.

There is no flag for this linking. They are simply linked together by listing the name of the files.

g++ main.o Birthday.o -o executable


Back to Libraries

How does this relate to libraries? Libraries are just a grouped together set of .o files.

This means that when compiling they require inclusion of library header files when you create a .o file, as well as a linking stage when creating an executable.

Let’s take a look at how we can link to a library called Google test, which performs modular code testing for files. For more information on Google testing visit our post here.

SP Libraries 8
Example file using #include

This file will simply run the Test to check to see if two plus two equals 4. This can be compiled by:

g++ -I(path to googletest)/include/ -c Test.cc

(Creates object file. The full path to the gtest.h header file is (path to googletest)/include/gtest/gtest.h)

g++ -pthread Test.o (path to libgtest.a)/libgtest.a

(Links to the library the same way as before, it is just a precompiled set of object files)

*Google testing uses pthreading underneath and the -pthread flag is unrelated to this tutorial


An alternate way to link to the library is with the -L and -l commands.

g++ -I(path to googletest)/include/ -c Test.c

(Same as before.)

g++ -pthread Test.o -L(path to libgtest.a) -lgtest

(-L path to library *not including the library name* -l library name *excluding the prefix, lib, and suffix, .a*)

SP Libraries 9

The creation of an object file and linking must occur in two different steps.

The first step includes the preprocessor replacing all header files and checking for syntax/function references (the -I flag).

The next step is the actual linking to the definitions of the function references(the -L and -l flag).

There are ways that you can try to do these steps together, and sometimes it will work with flags like -WL, and -Wl, but this practice is considered unscalable, unprofessional, and tenuous, potentially outputting many cryptic errors.


Some libraries do not require explicit inclusion or linking becuase the compiler g++ already knows where to search.

For example, iostream is actually a header file which operates the same way as any other library.

It’s placement is computer specific, but mine is stored in /usr/include/c++/4.8/iostream along with other standard c++ header files.

The library itself is stored elsewhere, for me it is in usr/lib/gcc/x86_64-linux-gnu/4.8/libstdc++.a or libstdc++.so.

There are system variables in place which predefine search paths and linking paths for the compiler to follow by default.

In the case of iostream and the c++ library, the compiler already knows to include the header files and link automatically so that you don’t have to explicitly link for each program.

These default paths can be output to the console and the default paths can be adjusted for making it easier to link to a library for a project.

cpp -v

SP Libraries 11

(The default include path for your system)

ld –verbose | grep SEARCH

SP Libraries 10

(The default library search path *Takes the place of -L*)

One final important concept in this tutorial is that of static and dynamic libraries. As shown, some libraries can be linked to without using the -L and -l flags, simply by specifying the path to the library.

A static library can be compiled either way specified above, but a shared library cannot.

The major difference is that shared object libraries are loaded into a program at run time whereas static libraries are preloaded into the executable itself.

This make an executable compiled with a .a library self-contained whereas a program compiled with a .so library must be able to access the .so at runtime.

A .so library ALWAYS requires the -L and -l syntax because of the compilers need to know where the library is located and to link to it.

Because .a libraries can also function using the -L and -l flags, it is recommended that you stick with them for every link to a library.

Learning how to deal with libraries is crucial to figuring out how IDE’s are working underneath and can be an invaluable skill for any Linux based software development job.

I hope you enjoyed the tutorial and if you have further questions please post them below!

Google Testing: Example and CMake Integration

The Google testing environment is frequently used in software engineering projects as a means of ensuring the functionality of your code.

It is a framework that highlights the fundamentals of the iterative development work flow with the ability to confirm a set of tests as you are developing, thereby increasing the reliability of your final product and reducing time spent trouble shooting overall.

The main tests that the framework allows for is assertions. An assertion simply checks to see if something is true, if two statements are equal, or if something ran as expected.

Confirming the functionality of your code is about using these assertions to explore the problem space of whatever function or operation you are implementing.

This means checking the bound cases of inputs, unexpected inputs, and fringe cases of behavior. If these tests fail, you iteratively adjust your code and continue improving it.

The Google testing environment is generally comprised of three parts: your code, your test case, and the Google testing library.

Your code is generally contained in an external file which you #include into the test file. Let’s check out an example on a Linux environment:

Download and build Google test at https://github.com/google/googletest


Example Program

SP Test 1

This header file declares a function Add which will be tested in our test file.


SP Test 2

Add.cc defines the function declared in Add.h


SP Test 3

This file defines a test with the macro, TEST. There are two names inside of the parentheses which specify the name for the series of tests, AddTest, and the specific test name, TwoAndTwo.

This is the output to the console when the test passes or fails (see below). An assertion is used to check equality between 4 and the call of the function Add with arguments (2, 2).

Then, main initializes the testing environment and runs all tests.



g++ -I(path to googletest)/include/ -I(.h directory) -c Test.cc Add.cc
g++ -pthread *.o libgtest.a

Google testing uses pthreading and -pthread must be passed as a flag when linking. For more information on compiling, check out our other post here.

SP Test 4


If we change the source code to reflect a test that fails, we get a different output.

SP Test 5
UNTRUE example that will fail: Assert that Add(2,2) is equal to 5.


SP Test 6

This very verbose output makes it easy to understand which function caused the failure and what to do to fix it.

Google testing can very easily be integrated into a personal project or homework assignment to add an air of high quality and professionalism.


Integrating with CMake

In a large software development project, there are often many test files which are stored in a testing directory.

The following shows how you can adjust your CMakeLists.txt file to allow for automatic testing in a large framework.

In CMakeLists.txt, insert the following:

SP Test 7

This calls the Google testing module and specifies that all .cc files in the test directory should be run.

The Google testing module will download Google testing locally to your project. It is stored in a cmake folder as cmake/gtest.cmake:

SP Test 8

After setting up the environment and building, running the executable titled ProjectName_test in the build directory will yield the following result after printing out results for each test.

SP Test 9

It should be noted that when using this framework the main() function should be omitted from each test file.

This scalable framework will run all tests in the test directory, allowing you to modularly make sure that each file is working.

I hope you enjoyed this Google testing tutorial, if you have further questions please post them below!