More on g++
Introduction
g++
is a tool for preprocessing, compilation, assembly and linking of source code to generate an executable file or library.
Installation
As easy as:
sudo apt update
sudo apt install g++
General Syntax
General syntax to run g++ compiler is:
g++ <flags_with_params> <source_files>
The above command takes a bunch of source files along with some flags and generates an executable file or a library file.
Flags are very important because they can control the way compilation occurs.
For example, if we have a single source file
main.cpp
and need to generate an executable file namedout
, the basic syntax for this task isg++ main.cpp -o out
Here,
main.cpp
is a source file and-o
is a flag to specify the output filename.out
is the name of the output executable file.Command can be as complex as
g++ -Wall -std=c++14 -I/some/path/to/include/dir -O3 -c -fpermissive -fPIE -o objectfile.o sourcefile1.cpp sourcefile2.cpp sourcefile2.cpp -L/path/to/library/dir -lsomelibrary1 lsomelibrary2
Here,
-W -std -O -c -f -o -L -l
are the flags along with their parameters andsourcefile1.cpp sourcefile2.cpp sourcefile2.cpp
are three source files.
Some important flags
-o
Specifies the output filename-I
Specifies the dir to look for header files-L
Specifies the dir to look for libraries-l
Specifies the name of a library to link to-g
To enable debugging-std
Specifies the C++ language standard-O
Specifies the Optimization level-W
Specifies the Warning option
Order doesn’t matter (except in few cases)
flags
andsource files
can be written in any order. (with some exceptions while linking libraries, discussed below)Take a simple C++ code
main.cpp
1
2
3
4
5
6
7
int main()
{
std::cout << "Hello, world!" << std::endl;
return 0;
}Any of the following commands can be used to generate the executable file
main
g++ main.cpp -o main
g++ -o main main.cpp
g++ main.cpp -omain
g++ -omain main.cpp
As you can see, it doesn’t matter in what order you keep
-o
flag and source filemain.cpp
Moreover, it doen’t matter if you keep a space after
-o
flag or not.Now, lets add some more flags:
-Wall
to show all the warnings,-g
to enable debugging, and-std
to specify C++ standard.All the commands below produces identical output:
g++ -Wall -g -std=c++14 main.cpp -o main
g++ -Wall main.cpp -g -omain -std=c++14
g++ main.cpp -Wall -omain -g -std=c++14
Now, lets try this with more than one source file
We can compile this with any of following commands:
g++ main.cpp add.cpp subtract.cpp -o main
(Simplest way)g++ -g -std=c++14 -Wall main.cpp add.cpp subtract.cpp -o main
(With some flags)g++ -Wall add.cpp -std=c++14 -o main main.cpp -g subtract.cpp
(Jumble up everything and it still works)
Creating Library
- Executable file is a standalone file, which can be executed i.e run as a program. Whereas a library is a collection of stuff that can be invoked from the executable files.
- All the examples above show how to create an executable file.
- There are two types of library:
- Static Library
- Dynamic Library
Creating Static Library
- Static library is nothing but a precompiled source file that can be linked to generate an executable file or other library.
First flow chart shows how an executable is generated by processing all the source files via the whole pipeline.
Second flow chart shows object files are generated in intermediate steps and are linked later to generate an executable file.
These object files can be viewed as static libraries that are linked to main.o to produce an executable file.
This can be done using following commands:
g++ -c main.cpp add.cpp subtract.cpp
(Generate Object files)g++ main.o add.o subtract.o -o main
(Generate executable from object files)Moreover, we can mix up source files and object files while generating executable file:
g++ -c add.cpp subtract.cpp
g++ main.cpp add.o subtract.o -o main
Here, add.o and subtract.o are the object files acting as library for main.cpp
Now, lets try to bundle up these object files into a single file, which we can call Static Library
g++ -c add.cpp subtract.cpp
(first generate add.o and subtract.o)ar rc my_first_library add.o subtract.o
(Bundle/Archive the object files to a single file my_first_library)g++ main.cpp my_first_library -o main
(Now, use this library to produce the executable file)Thats it! You have sucessfully created and used your first Static Library.
ar
is called archiver. A tool used to create, modify, and extract from archives.You can see the list of files in archive using:
ar -t my_first_library
Still some work left …
Well, now let’s look into some naming conventions and standard ways of linking a static library.
Generally, static library is named as:
lib<library_name>.a
And is linked as:
g++ <source_files> -o <output_filename> -L<path/to/lib> -l<name_of_lib>
So, correct way of linking a static library in above example is:
g++ -c add.cpp subtract.cpp
(first generate add.o and subtract.o)ar rc libmy_first_library.a add.o subtract.o
(Bundle/Archive the object files to a single file)g++ main.cpp -o main -L. -lmy_first_library
(Now, use this library to produce the executable file)
Creating Dynamic Library
Dynamic library are not linked with the executable file during compilation process. They are linked during execution. i.e. linked dynamically.
Dynamic library is named as:
lib<library_name>.so
Commands to create dynamic library for above example are:
g++ -c add.cpp subtract.cpp
(First generate object files as before)g++ -shared add.o subtract.o -o libmy_first_shared_library.so
(generate a shared library form the object files)g++ main.cpp -o main -L. -lmy_first_shared_library
(Now create an executable by linking the dynamic library)Now, if you run
./main
, it will probably give an error.That’s because the executable
main
needs to know where to search for librarylibmy_first_shared_library.so
.We can add the search path to the environment variable
LD_LIBRARY_PATH
so thatmain
finds it.export LD_LIBRARY_PATH=/path/to/dynamic_library
Now, when you run
./main
, it should work perfectly.You can also see all the dynamic dependencies/libraries linked to
main
by using commandldd main
. i.e. List Dynamic Dependencies of executable filemain
Order Matters here..
While generating the executable
main
by linking static or dynamic library in above example, we have used:g++ main.cpp -o main -L. -lname_of_lib
But as the flags are position independent, we may try to compile with:
g++ -o main -L. -lname_of_lib main.cpp
But this time, it shows error stating
undefined reference
The source file
main.cpp
uses the functionsadd
andsubtract
, which is found inside the linked library.g++
is designed in such a way that dependent stuff must be mentioned beforehand.As
main.cpp
is dependent on-lname_of_lib
,main.cpp
must be written before-lname_of_lib
Other flags can be kept anywhere.