Using CMAKE for your C++ projects

Benji Tigg
Level Up Coding
Published in
4 min readJul 23, 2021

--

If you’re anything like me, the minute I heard that I was going to need to learn a whole other language so that your code would compile, just seemed too much effort. So like the weakling I was, I crawled back to visual studio where everything is in solutions. This all changed when I was working on a project that was written outside of visual studio and so it used CMAKE, so I thought it might be a good idea to learn CMAKE so I can understand what's going on.

Photo by Shahadat Rahman on Unsplash

A starting point

To get started we first need to create a CMakeLists.txt file. We also need to specify a CMAKE version to use, what our project name is and add what we are trying to run.

CMakeLists.txtcmake_minimum_required(VERSION 3.10)project(Application)add_executable(Application application.cpp)

So taking this a step further, we might want to specify what version of C++ is required and we might want to specify what version of our project this is.

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD_17)
set(CMAKE_CXX_REQUIRED ON)
project(Application VERSION 1.0)add_executable(Application application.cpp)

This is all well and good for small, single file projects but what if you want to add classes to your project. We can’t just leave the CMakeLists file as it is, granted the CMakeLists file will compile but the project won’t build as it doesn’t know where the header file is located. To add header files to a CMAKE file we must specify where that file is located.

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD_17)
set(CMAKE_CXX_REQUIRED ON)
project(Application VERSION 1.0)
add_executable(Application application.cpp)
target_include_directories(Application PUBLIC "${PROJECT_BINARY_DIR}")

However, are above implementation assumes that your functions are all inline functions and so there is no need to add the source file. If you did have a header and a cpp file for your class you would need to include it in the CMakeLists file. There is two ways of doing this, the first method is the CMake approved method, and the second is not.

Approved method

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD_17)
set(CMAKE_CXX_REQUIRED ON)
project(Application VERSION 1.0)
add_executable(Application application.cpp class_1.cpp)
target_include_directories(Application PUBLIC "${PROJECT_BINARY_DIR}")

2nd method

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD_17)
set(CMAKE_CXX_REQUIRED ON)
project(Application VERSION 1.0)file(GLOB_RECURSE SRC FILES src/*.cpp)
add_executable(Application application.cpp ${SRC FILES})
target_include_directories(Application PUBLIC "${PROJECT_BINARY_DIR}")

When working on larger project, such as a rendering engine, you’re going to need to use some libraries, for example your graphics API.

add_library(glew STATIC IMPORTED GLOBAL)set_target_properties(glew PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/dependencies/glew/lib/windows/glew32s.lib)
set_target_properites(glew PROPERTIES INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/dependencies/glew/include)
target_link_libraries(${PROJECT_NAME} PUBLIC glew)

Some external libraries, like the one above have different files for different operating systems. You could write different CMakeLists files for every OS you put your project on, or you could put some logic into your CMakeLists file to import different parts of the library depending on what OS you are on.

if(CMAKE_SYTEM_NAME MATCHES WIN32)
#Import windows stuff
elseif(CMAKE_SYSTEM_NAME MATCHES Linux)
#Import linux stuff
elseif(CMAKE_SYSTEM_NAME MATHCES UNIX) #UNIX is MacOS
#Import UNIX stuff

It’s also important to know that using CMAKE we can create our own libraries from our own source files, this could come in useful if you intend on using pieces of code elsewhere or your creating a very large project, such as a game engine, where you are going to need multiple pieces of software to come together.

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD_17)
set(CMAKE_CXX_REQUIRED ON)
project(Application VERSION 1.0)
add_library(Library_1 STATIC class1/class_1.cpp)
target_include_directories(Library_1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/class1/include)
add_executable(Application application.cpp ${SRC FILES}
target_link_libraries(Application PUBLIC Library_1)

We could do this for every library we create and always do it in the top CMakeLists file or (and this will make our managing of CMAKE files easier) we could make a CMAKE file in the subdirectory.

class1/CMakeLists.txt

add_library(Library_1 STATIC class_1.cpp)
target_include_directories(Library_1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD_17)
set(CMAKE_CXX_REQUIRED ON)
add_subdirectory(Library_1)add_executable(Application application.cpp ${SRC FILES}
target_link_libraries(Application PUBLIC Library_1)

As you can see this is a much cleaner way of doing things.

Finally if you want to distribute your program to other people, it would make sense to include a installer in your project, to do this we just have to use CPACK. To use CPACK we need to add a couple of lines to the bottom of our main CMakeLists file, and add a license to our project, more information about licensing code can be found here.

cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD_17)
set(CMAKE_CXX_REQUIRED ON)
add_subdirectory(Library_1)add_executable(Application application.cpp ${SRC FILES}
target_link_libraries(Application PUBLIC Library_1)
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${APPLICATION_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${APPLICATION_VERSION_MINOR}")
include(CPack)

Hopefully this article has shown you that CMAKE isn’t something that should be feared but something that should be embraced into your C++ projects. This article really only looked at the tip of the iceberg in terms of what CMAKE can do, it can be quite useful when used correctly. To look at CMAKE in more detail there is a plethora of videos and article online, I would also recommend looking at the CMAKE documentation found here.

--

--

A student who likes to dabble in subjects outside of their learning