Build C++ Application with GNU GCC by Command Line, GNU make and Cmake
There are many toolsets used to build C++ applications such as GCC, Visual C++, Borland… Today, I want to share about GNU GCC and how to build a complex C++ application with GCC since it’s a popular toolset for C++ developers, and it supports both Windows and Unix.
Overview
2. Building C++ App by Command Line
Install GCC C/C++ Compiler
- To install GCC: https://gcc.gnu.org/install/binaries.html
- Check GCC version by command line:
gcc -v
To understand the build process, I’ve made a project which has four modules: a simple executable helloworld, a static library, a dynamic library, and an executable. You can pull it from here
.├── helloworld
│ └── helloworld.cpp
├── phone
│ └── phone.cpp
├── dynamiclib
│ ├── include
│ │ └── software
│ │ ├── gmail.hpp
│ │ ├── googlemap.hpp
│ │ └── software.hpp
│ └── src
│ ├── gmail.cpp
│ ├── googlemap.cpp
│ └── software.cpp
└── staticlib
├── include
│ └── hardware
│ ├── camera.hpp
│ ├── hardware.hpp
│ └── screen.hpp
└── src
├── camera.cpp
├── hardware.cpp
└── screen.cpp
Building C++ App by Command Line
Helloworld:
Let’s start with helloworld example:
$ cd helloworld# -o : output file
$ g++ -o hello helloworld.cpp$ ls
hello helloworld.cpp$ ./hello
Hello, World!
Simple! right? Now let’s try a more complex application including static library and dynamic library:
Static library:
$ cd staticlib# Compile source file to object without linking
# -c: Only run preprocess, compile, and assemble steps (without linking)
# -I: Add directory to include search path
$ g++ -c -o camera.o src/camera.cpp -I include/hardware
$ g++ -c -o screen.o src/screen.cpp -I include/hardware
$ g++ -c -o hardware.o src/hardware.cpp -I include/hardware# Link the object files into a static library
$ ar ru libhardware.a screen.o camera.o hardware.o
$ ranlib libhardware.a
Dynamic library:
$ cd dynamiclib# Compile source file to object without linking
$ g++ -c -o gmail.o src/gmail.cpp -I include/software
$ g++ -c -o googlemap.o src/googlemap.cpp -I include/software
$ g++ -c -o software.o src/software.cpp -I include/software# create dynamic library
$ g++ -shared -fPIC -o libsoftware.dylib gmail.o googlemap.o software.o
An executable:
$ cd phone# Compile source file to object without linking
$ g++ -c -o phone.o phone.cpp -I ../staticlib/include -I ../dynamiclib/include# linking the application with static and dynamic library
$ g++ -o phone phone.o -L../staticlib -L../dynamiclib -lhardware -lsoftwareOr$ g++ -o phone phone.o ../staticlib/libhardware.a ../dynamiclib/libsoftware..dylib# remember copy dynamic library to executable file or install in in directory where the system can read it. then run your application$ ./phoneThe list software:
Gmail
GoogleMap
The list hardware
Camera
Screen
Building C++ App by makefile
With large C++ projects — which can involve thousands of separate files, including source files, object files, libraries, and executables — building from the command line is a hard task. That’s why GNU also provides an automation tool — GNU Make.
Why should we use make? check here.
A simple makefile consists of rules with the following syntax:
target ... : prerequisites (dependencies) ...
recipe (system command)
...
The makefile to build helloworld:
Helloworld:
$ cd helloworld
$ touch makefile$ vi makefile
# create the makefile as below$ make
g++ -o hello helloworld.cpp$ make install$ make clean
Static library:
$ cd staticlib
$ touch makefile$ vi makefile
# create the makefile as below$ make
g++ -I include/hardware -c -o src/camera.o src/camera.cpp
g++ -I include/hardware -c -o src/screen.o src/screen.cpp
g++ -I include/hardware -c -o src/hardware.o src/hardware.cpp
ar ru libhardware.a src/camera.o src/screen.o src/hardware.o
ar: creating archive libhardware.a
ranlib libhardware.a$ make install$ make clean
Dynamic library:
$ cd dynamiclib
$ touch makefile$ vi makefile
# create the makefile as below$ make
g++ -I include/software -c -o src/gmail.o src/gmail.cpp
g++ -I include/software -c -o src/googlemap.o src/googlemap.cpp
g++ -I include/software -c -o src/software.o src/software.cpp
c++ -shared -fPIC -I include/software -o libsoftware.dylib src/gmail.o src/googlemap.o src/software.o$ make install$ make clean
An executable:
$ cd phone
$ touch makefile$ vi makefile
# create the makefile as below$ make
g++ -I ../staticlib/include -I ../dynamiclib/include -c -o phone.o phone.cpp
g++ -o phone phone.o ../staticlib/libhardware.a ../dynamiclib/libsoftware.dylib$ make install$ make clean
Next, create a top-level makefile in the directory containing software, hardware, phone, and binaries:
$ touch makefile$ vi makefile
# create the makefile as below$ make$ make cmd=install
$ make cmd=clean
# run binary file$ cd binaries$ ./phone
The list software:
Gmail
GoogleMap
The list hardware:
Camera
Screen
You can pull the detail makefile at here:
Using Cmake to generate makefile
We have a makefile that works perfectly on Unix. But makefile is only for experienced developers, who are familiar with the building process as well as working with command line.
That why Cmake was born and became popular. Cmake is used to generate standard build files (e.g., makefiles on Unix and projects/workspaces in Windows MSVC) which can compatible with almost platforms (Window, Linux, macOS), IDE (Codex, MSVS, Eclipse …).
Here is the reason why we need Cmake.
In this post, I will share how to write a CMakeLists.txt to build/install this project. You also can use the Cmake GUI to generate CMakeLists.txt
Helloworld:
Static library:
Dynamic library:
An executable:
Next, create a top-level CmakeLists to build whole projects
# build directory
$ mkdir build && cd build# generate building files
$ cmake ..
...
-- Generating done# build
$ make
Scanning dependencies of target hello
[ 8%] Building CXX object helloworld/CMakeFiles/hello.dir/helloworld.cpp.o
...
[100%] Built target phone# run
$ ./phone/phone
The list software:
Gmail
GoogleMap
The list hardware:
Camera
Screen
You can pull the detail CmakeList.txt at here
With my sharing, I hope you will understand the building processes for C++ App and how to build a large C++ project. This will help you a lot to troubleshoot problems in compiling and running an application.