CMake Tutorial
This tutorial cover the following:
- Build the project using simple
c++(1)andmake(1). - Build the project using
cmake(1). - Build the project using
cmake(1)with third party library.
In this tutorial we will use the following project structure:
cmake-tutorial/
├── CMakeLists.txt
├── README.md
├── lib
│ └── googletest
├── src
│ ├── main.cc
│ ├── math.cc
│ └── math.h
└── test
└── math_test.cc
Directory structure:
lib: Directory for third party library.src: Directory for source code.test: Directory for test.
src/main.cc is our main executable and src/math.{cc,h} is an internal
library that used by src/main.cc.
We will start from the basic on how to build the project using c++(1) only
and a simple Makefile. Then we define the build in CMakeLists.txt and
using cmake(1) to generate complex Makefile for us.
Install CMake
First of all, you need to install cmake.
On Ubuntu:
sudo apt-get install cmake
On macOS:
brew install cmake
Make sure the cmake is installed correctly:
% cmake --version
cmake version 3.10.2
CMake suite maintained and supported by Kitware (kitware.com/cmake).
Compiling & Linking
We can build this project using the following command:
c++ src/main.cc src/math.cc -o cmake-tutorial
Or we can do the compile and linking on the separate steps
c++ -c src/math.cc -o math.o
c++ src/main.cc math.o -o cmake-tutorial
Using Makefile
We can automate the step to compile and link above using Makefile.
First we need to write a Makefile with the following content:
math.o: src/math.cc src/math.h
c++ -c src/math.cc -o math.o
cmake-tutorial: math.o
c++ src/main.cc math.o -o cmake-tutorial
build: cmake-tutorial
Now we can run:
make build
to build cmake-tutorial binary. If there are no changes in
src/{main,math}.cc and src/math.h, the subsequent command
will do nothing:
% make build
make: Nothing to be done for `build'.
this is usefull when working on larger project, we only compile the object that changes.
Using CMake
Now we know how to perform compiling and linking using the C++ and
make command. Now we can use cmake to do all of this for us.
Create new CMakeLists.txt with the following content:
cmake_minimum_required (VERSION 3.10)
# Define the project
project(cmake-tutorial)
# Add definition for math library
add_library(math src/math.cc)
# Add definition for the cmake-tutorial binary
add_executable(cmake-tutorial src/main.cc)
target_link_libraries(cmake-tutorial math)
We can generate the Makefile based on the definition above using the following
command:
cmake .
Now we can run make cmake-tutorial to build the binary.
% make cmake-tutorial
Scanning dependencies of target math
[ 25%] Building CXX object CMakeFiles/math.dir/src/math.cc.o
[ 50%] Linking CXX static library libmath.a
[ 50%] Built target math
Scanning dependencies of target cmake-tutorial
[ 75%] Building CXX object CMakeFiles/cmake-tutorial.dir/src/main.cc.o
[100%] Linking CXX executable cmake-tutorial
[100%] Built target cmake-tutorial
Using CMake with 3rd-party library
Suppose that we want to write a unit test for math::add(a, b). We will use a
googletest library to create and run the
unit test.
Add the following definition to CMakeLists.txt:
# Third-party library
add_subdirectory(lib/googletest)
# Test
add_executable(math_test test/math_test.cc)
target_link_libraries(math_test gtest)
target_link_libraries(math_test math)
Re-generate the build files using the following command:
cmake .
Build the unit test:
make math_test
Run the test:
% ./math_test
[==========] Running 1 test from 1 test case.
[----------] Global test environment set-up.
[----------] 1 test from MathAddTest
[ RUN ] MathAddTest.PositiveNum
[ OK ] MathAddTest.PositiveNum (0 ms)
[----------] 1 test from MathAddTest (0 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test case ran. (0 ms total)
[ PASSED ] 1 test.
Done.
IDE Support
If you are using CLion, the google test will automatically detected.
