What is 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
Source files contain the definitions of these functions and often have the file extension
As a brief refresher the example below contains a header, source file, and main file for displaying a Birthday.
Declares a class called
Defines the two
Birthday functions specified above.
Creates an instance of the
birthday class, and calls the function
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:
Makefile is splitting up the compilation process into two stages.
.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
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
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:
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
-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
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.
Birthday.o object file now contains both the declaration and the definitions after the preprocessor inserted the contents of the
Now, we must “link” the two object files together so that the functions called by
main.o can be executed from the definitions in
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
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.
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
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,
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
The next step is the actual linking to the definitions of the function references(the
There are ways that you can try to do these steps together, and sometimes it will work with flags like
-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.
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
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.
include path for your system)
ld –verbose | grep SEARCH
(The default library search path *Takes the place of
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 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.
.so library ALWAYS requires the
-l syntax because of the compilers need to know where the library is located and to link to it.
.a libraries can also function using the
-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!