CMake is a generator of build systems that can produce Makefiles for Unix like systems, Visual Studio Solutions for Windows and XCode projects for Mac OS. All these from the same base – a single CMakeLists.txt file. But any magic – not just advanced technology – can be understood if we break it into stages. CMake is a tool for defining and managing code builds, primarily for C. CMake is a cross-platform tool; the idea is to have a single definition of how the project is built - which translates into specific build definitions for any supported platform. CMake is a powerful and robust build system. You specify what you want done, not how to do it. CMake then takes that information and generates the files needed to build the system. For example, CMake can generate solution (.sln) and project files (.vcxproj) that Visual Studio and Visual Studio Code use on Windows. CMake is a powerful and robust build system. You specify what you want done, not how to do it. CMake then takes that information and generates the files needed to build the system. For example, CMake can generate solution (.sln) and project files (.vcxproj) that Visual.
Recently, we have had several customers who decided to compile our C++ library under Linux. This process is documented in the README file and there is a post explaining how to compile the library with the Code::Blocks IDE. However, we hadn't yet documented how to use CMake to compile the library and use it in a program. This week, we are tackling this issue.
Note: we assume that you already have a minimal knowledge of the C++ language and of our programming libraries. If it is not the case, we recommend that you start by reading our post 'How to start in C++ with Yoctopuce modules' which explains how our library works.
First of all, a few words on CMake. CMake is neither a compiler nor an IDE, but it is a 'tool for managing the build process of software'. In other words, the role of CMake is not to actually build the executable, but to prepare a list of commands to be performed to generate the executable. Usually under Linux, one uses CMake to generate a GNU make file which then uses gcc or g++ to compile the source file and to create the executable.
CMake generates makefiles which enable you to compile the application with gcc
A CMake project is composed of source files and of one or several CMakeLists.txt files containing the required information to compile the application, such as the location of the source files, the name of the executable, the libraries to be used, and so on.
We could wonder why not using GNU make directly. Indeed, GNU make already enables us to describe the commands to be run to transform a .cpp file into an executable, but its syntax is very complex and becomes almost incomprehensible for large projects. As we are going to see below, the CMake syntax is much simpler, making the life of the developer easier as well.
Moreover, CMake is open source and is available on almost all platforms.
For these reasons, since version 1.10.42060 of our C++ library, we added a CMakeLists.txt file in the Sources subdirectory. This file contains all the compilation rules for our library. To use our C++ library in a CMake project, you only need to include this file and to reference our library with the yoctolib name.
A short example
In order to illustrate what we are saying, we are going to see all the steps to compile the following code:
int main(int argc, constchar* argv)
cerr<<'RegisterHub error: '<< errmsg <<endl;
cout<<'Device list: '<<endl;
cout<< module->get_serialNumber()<<' ';
module = module->nextModule();
This code displays the serial number and the product name of all the Yoctopuce modules connected on the USB ports of the machine. For more information on the functions that are used in this example, you can read the documentation of the C++ library. We save this code in a main.cpp file that we are going to compile.
To compile this code, you must have g++, CMake, and libusb-1.0-dev installed on the machine. On a Debian or Ubuntu based distribution, you can install all these packages with the following commands:
sudo apt-get update sudo apt-get install cmake sudo apt-get install build-essential gdb sudo apt-get install libusb-1.0-0-dev
Then, you must download the Yoctopuce C++ library. You can do so with Git or directly from our web site. The Sources subdirectory contains all the source files to be compiled to use our library, as well as the CMakeLists.txt file which is used by CMake.
Note the path of this directory, because you will need it later on. In our case, the library is unzipped in the /home/yocto/Yoctolib.CPP/ directory and we therefore need the /home/yocto/Yoctolib.CPP/Source path.
The CMakeLists.txt file
Now that we have our main.cpp file and all the dependencies installed on the machine, we can start to write the CMakeLists.txt file for our demo application. As explained above, this file contains all the instructions to compile the application.
We start by checking that the installed version of CMake is recent enough and by giving a name to the project, in our case the project is called 'Demo' and we need version 3.16 of CMake.
cmake_minimum_required (VERSION 3.16) project (Demo)
Then, we define the name of the executable and the source files to be compiled. In our case, the name of the executable is demo and there is only one source file: main.cpp. There is no need to add the source files of our C++ library, as we are going to include the CMakeLists.txt file of the library.
We are only missing the instructions to include the Yoctopuce C++ library. This task is easy because we already have a CMakeLists.txt file in the Sources subdirectory. This files contains the list of all the files of the library which must be compiled as well as the flags to pass to the compiler or to the linker to generate the executable.
Note: this file is present only since version 1.10.42060 of the library. If it is not present in your version, you must simply use a more recent version of our library.
The add_subdirectory command with the path of the Sources subdirectory of the library enables us to add the library. In our case, the path is /home/yocto/Yoctolib.CPP/Sources/. The second parameter compiled_yoctolib defines a subdirectory that CMake uses to compile the library.
Finally, we must specify that the demo executable uses the Yoctopuce library (Yoctolib).
Here is the complete CMakeLists.txt file:
cmake_minimum_required (VERSION 3.16)
# Adds the executable called 'demo' that is built from the source files 'main.cpp'.
add_executable (demo main.cpp)
# Adds the Sources subfolder of the Yoctopuce C++ library.
add_subdirectory (/home/yocto/Yoctolib.CPP/Sources/ compiled_yoctolib)
# Links the executable to the Yoctopuce C++ library (YoctoLib).
target_link_libraries (demo LINK_PUBLIC YoctoLib)
To generate the compilation files, you must run cmake:
[email protected]:~/tmp$ cmake . -- The C compiler identification is GNU 9.3.0 -- The CXX compiler identification is GNU 9.3.0 -- Check for working C compiler: /usr/bin/cc -- Check for working C compiler: /usr/bin/cc -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Detecting C compile features -- Detecting C compile features - done -- Check for working CXX compiler: /usr/bin/c++ -- Check for working CXX compiler: /usr/bin/c++ -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /home/yocto/tmp
To actually compile the application, you must use GNU make with the make command:
[email protected]:~/tmp$ make Scanning dependencies of target YoctoLib [ 1%] Building CXX object compiled_yoctolib/CMakeFiles/YoctoLib.dir/yocto_accelerometer.cpp.o .. [ 97%] Linking CXX static library libYoctoLib.a [ 97%] Built target YoctoLib Scanning dependencies of target demo [ 98%] Building CXX object CMakeFiles/demo.dir/main.cpp.o [100%] Linking CXX executable demo [100%] Built target demo
There you are! the application is compiled and you can launch it with the ./demo command:
[email protected]:~/tmp$ sudo ./demo Device list: YLTCHRL1-CD28D Yocto-LatchedRelay
You can find the source code of this example on GitHub: https://github.com/yoctopuce-examples/cmake_example
CMake is a very handy tool when you code in C++. It is more convivial than GNU make. For comparison purposes, the CMakeLists.txt file of our C++ library is only 14 lines long while the GNU makefile is made of 938 lines..Skip to main content
C++ project setup with CMake & unit tests (google test)
Published: 01-10-2019 Last update: 06-11-2019 Author: Remy van Elst Text only version of this article
❗ This post is over one year old. It may no longer be up to date. Opinions may have changed.
Table of Contents
- Add some (example) source code and tests
This guide will show you how to setup a new C++ project with CMake and unit testsvia Google's test framework. With this setup you can get started right away with test-driven-development in C++. It is also simple enough to look and figureout how to add gtest to your existing project and start doing TDD on your legacy (existing) codebase.
Consider sponsoring me on Github. It means the world to me if you show your appreciation and you'll help pay the server costs.
You can also sponsor me by getting a Digital Ocean VPS. With this referral link you'll get $100 credit for 60 days.
The picture below shows the end result, a running unit test:
There are a million different ways to 'do' C++ projects, but using
CMake andthe google testing framework has my preference. That's not to say that using a
Makefile or Boost Unit Test is bad, use whatever suits your needs. This guide however will focus on just
It assumes a system running Ubuntu (18.04). It also works on Windows with
mingw,but I haven't tested in with MSVC.
My preferred code editor is CLion from Jetbrains, which has most of this built in. This guide however focusses on the manual / command line way since CLion isnonfree (and paid) software.
The process is not that complicated:
- Install software (cmake and googletest)
- Create folder structure
- Create the
- Create some sample code and sample tests
- Compile everything
- Run the tests
Install cmake & googletest
I assume you already have your compiler installed and working. Installing cmakecan be done with the package manager on Ubuntu:
On Windows, you can use MinGW or
cygwin to install your development tools including CMake. Clion offers a nice GUI for that.
Googletest is available as a git repository which you can clone and then copyinto your project. You could go all fancy with CMake scripts to download itif it's not already in your project, but since you can clone once and copy later on I choose not to automate it. Clone the repository:
gtest comes with a
CMakeLists.txt so integrating it in your project is easy.
Create your C++ project folder. I like to keep the following structure for simpleprojects:
Here is a oneliner to create the folders:
googletest repository folder your cloned earlier into the
If you have multiple components you can create extra sub folders, but that doesrequire tweaking the
CMakeLists.txt files to work with multiple libraries.
Most of my personal projects are simple enough to fit into one folder as above.
tst folder the unit tests reside. I try to keep the tests limited to the same function in seperate files. In the above example I have
Formula.cpp, which house the example
Formula class. All unit tests relatedto this class thus should reside in
CMakeLists.txt contains a set of directives and instructionsdescribing the project's source files and targets (executable, library, orboth). This can get quite complex quite fast, CMake has many options. I try tokeep it simple in this guide.
I'm using a non-recommended way to include files. For simple projects with a few files you should use the following:
I'm using this:
That is a recursive search to include all
*.h in the folder. Inmy IDE I have auto-reload enabled, that way I can't forget to add a fileto
CMakeLists.txt every time. Is cleanmymac worth buying. For proper administration you should not use thissince it just includes everything, could have unwanted side-effects.
Update 2019-11-07: If you want Boost in this setup, read this article from me.
Each subdirectory in our case also needs a
Main folder CMakeLists.txt
The name of the project is
ExampleProject, that variable is used in other files.The rest of the file just includes the different subfolders. If you omit the
include_directories(src), your tests will not be able to find the header files.
src folder CMakeLists.txt:
The name of the compiled program will be
ExampleProject_run, which is whatwe defined in
add_library is used to include the codein the unit tests.
tst folder CMakeLists.txt:
This list used the
src defined library and adds the tests as a target. The compiled executable file is named
Add some (example) source code and tests
Cmake Command Not Found
At this point you start developing. But since this is a example setup, I'll adda simple class file to show you how to do the unit tests.
Copy the below code into your project:
This function returns the given
int multiplied by 2.
The following code is to setup the unit tests.
This file will run all the tests and since we recursively included everythingwith CMake, it will effectively run all tests in all files in this folder.
The Google Test Primer is a great starting point to learn more on the specificsof the testing framework.
Compile all the things
Now that we have sourcecode and testcode in place we can compile everything (both the binary and the tests).
Do note that you should do this in the
build folder. If you do it in the main folder it will work, but it will litter up the directory.
There are now a bunch of files and folders in the
build folder, most important,the
Makefile. You can now compile the project:
You now have two executable files, as defined in the
Cmake C 14
Run all the things
If all went well, the code should run:
The tests as well:
A quick one-liner to compile and run the tests. You can run this wheneveryou want to re-run the tests (after changing code for example):
As you can see I changed a unit test so that it failed.Tags: boost, c++, cmake, cpp, development, googletest, linux, software, testing, ttd, tutorials