Getting Started with CMake for C/C++

CMakeCross Make is a build tool for building software, commonly for C/C++. Though, it can be used in many other languages such as Latex for instance, and many more. It has its own markup language that will translate the CMake code into the respective build language. Like Make, Ninja, Visual Studio Project, and many more, see the full list at CMake documentation Website.

The language itself is not case sensitive, thus both add_executable and ADD_EXECUTABLE will be read exactly the same by the CMake program.

When executing the CMake program with a valid CMake markup script, the script will be read through, and during this process, it will generate internal files. Furthermore, it will generate cache and other files for keeping track of all the files associated with the project. So that if a CMake source file is edit, it will automatically rerun the CMake program on the CMake file.

The CMake source code associated with building projects is named CMakeLists.txt. Though, CMake modules filename are any valid filename with the extension *.cmake. It could be, for instance, FindOpenGL.cmake. These modules are used for adding additional functionalities without having to write custom code for each project for common functionalities. In the case of FindOpenGL.cmake, it will provide variables for the library and include the file path for the OpenGL on the current system.

The CMake’s default name is CMakeLists.txt, this is important.


CMake Examples

The following show some simple example of how the CMake script code can look like and what each part does.

Simple Executable Example

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

# set the project name
PROJECT(HelloWorldApp)

# add the executable
ADD_EXECUTABLE(HelloWorld helloworld.c)

Let us take a look at creating a simple executable program with CMake. This is the simplest type of CMake, see the following for what each command does in the code.

  • CMAKE_MINIMUM_REQUIRED – Specificy which minimum CMake version the code will require. Thus, if the current CMake version is lower, it will fail running.
  • PROJECT – This specifies the name of the project, this does not affect how the CMake works, but
  • ADD_EXECUTABLE – Set the executable target and its list of source files that will be compiled and linked together.

Finally, the source code for helloworld.c that will print hello world to the command line.

#include<stdio.h>

int main(int argc, const char* argv){
    printf("Hello World");
}

Simple Library Example

Creating a library is very similar to the simple executable, the only difference is that instead of using ADD_EXECUTABLE, ADD_LIRARY is used. The ADD_LIRARY, similar to the executable adds the source files. Though, in addition, it can be specified directly what kind of library, STATIC, SHARED, and MODULE.

CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

# set the project name
PROJECT(HelloWorldLib)

# add the library
ADD_LIBRARY(HelloWorld SHARED helloworld.h helloworld.c)

For the source code, the main function is removed since there is no need for an entry point. Instead, a dedicated function is added. This function can then be called from another project by including the header file.

#ifndef _MY_LIB_PRINT_H_
#define _MY_LIB_PRINT_H_

extern int print_hello(void);

#endif
#include<stdio.h>

int print_hello(){
    printf("Hello World");
}

Resolve Path

Though, having looked at the simple case example for both library and executable. They do however miss an important component when using CMake, handling of paths. This is a common problem in computer programming. By using some of the built-in variables in CMake, it can be easily be resolved. The four following are some of the more important variables.

  • CMAKE_CURRENT_SOURCE_DIR – The current directory where the current CMake source file is located.
  • CMAKE_SOURCE_DIR – The top-level directory, simply the root CMakeLists.txt file is located.
  • CMAKE_CURRENT_BINARY_DIR – The current directory where the build is taking place in respect to the root build directory.
  • CMAKE_BINARY_DIR – The root directory for where the build data is stored. If the build is done in the same directory as the root CMakeLists.txt, it will equal CMAKE_SOURCE_DIR.
CMAKE_MINIMUM_REQUIRED(VERSION 3.10)

# set the project name
PROJECT(HelloWorldApp)

# add the executable
ADD_EXECUTABLE(HelloWorld ${CMAKE_CURRENT_SOURCE_DIR}/helloworld.c)

Building From Command Line – Linux

CMake can be both found as a command-line tool, including integrated with many integrated development environments (IDE) that support C/C++. However, using the command line version is very simple. Many projects that use CMake for building the project usually only require the following commands. Though, note that the last command make, is for when the CMake is configured to generate makefile as its build system. It can then differ depending on what build system has been specified to be generated. Usually on Linux makefile is the default build system.

mkdir build
cd build
cmake ..
make

The reason for creating a dedicated directory to where it is built when building the program is simply to allow a better structure of the project.