In my last post I talked about some recent discoveries I’ve had with using CMake. I decided today I would take the time to talk a little about what I learned. This will be the first part of a few posts that will walk through one way I have found to use CMake in a logical, and helpful manner.
There are plenty of people that talk about CMake, but when I was learning how to use it I struggled to find a cohesive free source on building projects with CMake. This post is my attempt to create some helpful information on getting started with CMake, and some clean ways I have discovered to use it.
What is CMake?
Well, according to their website:
CMake is an open-source, cross-platform family of tools designed to build, test and package software. CMake is used to control the software compilation process using simple platform and compiler independent configuration files, and generate native makefiles and workspaces that can be used in the compiler environment of your choice. The suite of CMake tools were created by Kitware in response to the need for a powerful, cross-platform build environment for open-source projects such as ITK and VTK.
Great, so what does that mean to the average user and why would you want to use CMake?
- CMake is a Makefile generator (or Makefile equivalent).
- CMake is platform-independent.
- CMake should make your life easier.
CMake is a makefile generator. When you use CMake, it will automatically generate a Makefile (or Makefile equivalent on non *NIX systems) which you can use to compile your program. But why would I do that when I can just write a Makefile?
CMake is platform-independent. The reason you would want to use CMake to generate your Makefiles is that you no-longer have to define specifics in your Makefile for different compilers and or operating systems. You can write out the things you would like to do, and let CMake handle all of the platform-dependent nonsense.
CMake should make your life easier. I say should because there’s a lot of hoopla surrounding CMake and how to use it. The CMake Tutorial helps with a few specific cases, but doesn’t do anything to teach you how to actually use the software. Once you figure out how to do what you want, however, CMake is a very valuable tool. CMake can make building and, even testing, a breeze and has some pretty sweet features.
Basic CMake Usage
The complete source code for the following HelloSimple program can be found in my GitHub repository: http://github.com/jhbell/cmake-wyntk
CMake is run using files called
CMakeLists.txt. Inside of these files is
where you will specify the configuration options that you would normally use
in a Makefile. Furthermore, CMake allows for the use of multiple
CMakeLists.txt files to allow for better organization. Here is an example of
the simplest CMake project you can make.
HelloSimple |-- CMakeLists.txt |-- Hello.cpp |-- Hello.h |-- RunHello.cpp
Hello.cpp to print “Hello,
world!” to standard output. We have written the code necessary to do so, and
now we are ready to compile our program.
We will start by creating our
CMakeLists.txt file containing the following
cmake_minimum_required(VERSION 3.5) project(HelloSimple CXX) set(CMAKE_CXX_STANDARD 14) add_executable(RunHello RunHello.cpp Hello.cpp)
Notice that each line looks like a call to a function. These “functions” can all be found in the CMake documentation, and are referred to as “commands”. Let’s take a look at what each one of these commands means, starting with the first line:
As you can imagine, this first line defines the minimum required version of CMake we need to build this project as version 3.5. Again, as you would think, you can change the version number (here 3.5) to be whatever version you need to support the CMake commands you will be using.
The second command specifies the name of the project and the language of
the project. I decided to go with the project name of
HelloSimple. Since I am
using C++, I wanted to specify that the language as being C++ by putting
CXX as the next parameter.
This third command sets a variable to a given value. In this case, we are
setting one of CMake’s known variables called
variable controls the C++ standard that should be used when compiling, and is
equivalent to using the
-std=c++14 flag on g++. There are other ways to
specify the C++ standard, but this one I have found to be the most concise.
The values 98, 11, or 14 can be used.
add_executable(RunHello RunHello.cpp Hello.cpp)
The last line specifies the name of the executable to be created (-o flag on
gcc/g++) and the list of source files to compile. Here we are naming the
executable RunHello, and compiling the .cpp files
Hello.cpp for the HelloSimple program.
Building and Running with CMake
Building your CMake project is now quite simple. Again, there are various ways to accomplish this task, but the following is what I have found to be easiest to remember.
- Make a new directory inside of your project folder. I, personally, like
using the name
buildfor this. Once this is done, the directory structure from before should look like this:
HelloSimple |-- build/ <= New! |-- CMakeLists.txt |-- Hello.cpp |-- Hello.h |-- RunHello.cpp
Change directories into the newly created directory.
Execute the cmake command on your project direcotry. The CMake command line tool simply requires a path to the project source, or a path to a previous build. We obviously don’t have a previous build, so we want to pass in the root directory for our project which contains our highest level
CMakeLists.txtfile. This command becomes
cmake ..in our example.
Run make in the build directory. The
cmakecommand generates a
Makefileinto your current directory. You will also notice a file called
CMakeCache.txtand a directory called
CMakeCache.txtfile is an editable file containing some defaults for your program’s build process. You can open this file to learn more about it. The
CMakeFilesdirectory contains all of the sorcery done by CMake along with the binaries for each source file.
Run your program as you normally would after a make. In this example, I simply have to type
./RunHellosince RunHello is the name I gave to my executable using the
From here on out, to recompile your program, you simply need to run
again. Only after making changes to the CMakeLists.txt file do you need to
cmake command again.
In summary, the commands to execute this build process from the HelloSimple directory are:
mkdir build cd build cmake .. make ./RunHello
As you can see, there is a lot to learn about the fundamentals of CMake. CMake is growing in popularity and is even the basis for JetBrains’ CLion IDE. Similar to using an IDE, the more you let the software do, the less you know about what is actually going on. That being said, if you want a platform independent build process, look no further. This is about as simple as you can get beyond clicking a green play button in an IDE. If you already have a ton of Makefiles that do exactly what you want, however, maybe switching your entire project over to CMake isn’t necessary.
In some future posts, I will go over creating more elaborate project setups with CMake where we will begin to see some of the features that make CMake much easier to use than Makefiles. As we have already seen, we can use CMake to generate a fully equipped Makefile with just four commands. The future posts will go into more complex directory structures, how to include libraries, and testing with GoogleTest. Until then, happy hacking!