CMake Template for Simple Projects

CMake can be seen as a tool for automatically generating Makefiles, but it is actually a programming language with a scripting style:
  • Cross-platform support: CMake supports multiple operating systems and compilers, allowing the same build configuration to be used in different environments.
  • Simplified configuration: Through the CMakeLists.txt file, users can define project structure, dependencies, compilation options, etc., without manually writing complex build scripts.
  • Automated building: CMake can automatically detect libraries and tools on the system, reducing the manual configuration workload.
  • Flexibility: Supports multiple build types and configurations (such as Debug, Release) and allows users to customize build options and modules.
CMake Template for Simple Projects

CMake Basics

File Structure and Basic Syntax:

  1. Specify the minimum required version of CMake:
cmake_minimum_required(VERSION <version>) 
cmake_minimum_required(VERSION 3.10)
  1. Define the project name and the programming languages used:
project(<project_name> [<language>...])
project(MyProject CXX)
  1. Specify the executable to be generated and its source files:
add_executable( ...) 
add_executable(MyExecutable main.cpp other_file.cpp)
  1. Create a library (static or dynamic) and its source files:
add_library( ...) 
add_library(MyLibrary STATIC library.cpp)
  1. Link target files with other libraries:
target_link_libraries( ...) 
target_link_libraries(MyExecutable MyLibrary)
  1. Add header file search paths:
include_directories(...) 
include_directories(${PROJECT_SOURCE_DIR}/include)
  1. Set the value of variables:
set( ...) 
set(CMAKE_CXX_STANDARD 11)
  1. Set target properties:
target_include_directories(TARGET target_name
                          [BEFORE | AFTER]
                          [SYSTEM] [PUBLIC | PRIVATE | INTERFACE]
                          [items1...])
target_include_directories(MyExecutable PRIVATE ${PROJECT_SOURCE_DIR}/include)
  1. Installation rules:
install(TARGETS target1 [target2 ...]
        [RUNTIME DESTINATION dir]
        [LIBRARY DESTINATION dir]
        [ARCHIVE DESTINATION dir]
        [INCLUDES DESTINATION [dir ...]]
        [PRIVATE_HEADER DESTINATION dir]
        [PUBLIC_HEADER DESTINATION dir])
install(TARGETS MyExecutable RUNTIME DESTINATION bin)
  1. Conditional statements (if, elseif, else, endif commands)
if(expression)
  #Commands
elseif(expression)
  #Commands
else()
#Commands
endif()
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
  message("Debug build")
endif()

11. Custom commands (add_custom_command command):

add_custom_command(
   TARGET target
   PRE_BUILD | PRE_LINK | POST_BUILD
   COMMAND command1 [ARGS] [WORKING_DIRECTORY dir]
   [COMMAND command2 [ARGS]]
   [DEPENDS [depend1 [depend2 ...]]]
   [COMMENT comment]
   [VERBATIM]
)
For example:
add_custom_command(
   TARGET MyExecutable POST_BUILD
   COMMAND ${CMAKE_COMMAND} -E echo "Build completed."
)

Variables and Cache

CMake uses variables to store and pass information, which can be defined and used in the CMakeLists.txt file. Variables can be divided into regular variables and cache variables.

Variable Definition and Usage

Defining a variable:

set(MY_VAR "Hello World")

Using a variable:

message(STATUS "Variable MY_VAR is ${MY_VAR}")

Cache Variables

Cache variables are stored in CMake’s cache file, and users can modify these values during CMake configuration. Cache variables are typically used for user-input settings, such as compilation options and paths.

Defining a cache variable:

set(MY_CACHE_VAR "DefaultValue" CACHE STRING "A cache variable")

Using a cache variable:

message(STATUS "Cache variable MY_CACHE_VAR is ${MY_CACHE_VAR}")

Finding Libraries and Packages

CMake can automatically detect and configure external libraries and packages using the find_package() directive.

Commonly used to find system-installed libraries or third-party libraries.

find_package() directive

Basic usage:

find_package(Boost REQUIRED)

Specify version:

find_package(Boost 1.80 REQUIRED)

Find libraries and specify paths:

find_package(OpenCV REQUIRED PATHS /path/to/opencv)

Using the found libraries:

target_link_libraries(MyExecutable Boost::Boost)

Setting include directories and link directories:

include_directories(${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})

Using third-party libraries

Assuming you want to use the Boost library in your project, the CMakeLists.txt file might look like this:

cmake_minimum_required(VERSION 3.10)
project(MyProject CXX)
# Find Boost library
find_package(Boost REQUIRED)
# Add source files
add_executable(MyExecutable main.cpp)
# Link Boost library
target_link_libraries(MyExecutable Boost::Boost)

File Tree

my_project/
├── CMakeLists.txt
├── src/
│   ├── main.cpp
│   ├── module1.cpp
│   └── module1.hpp
├── include/
│   └── my_project/
│       └── module2.hpp
└── build/

A simple CMakeLists.txt template file example:

# Set minimum version required
cmake_minimum_required(VERSION 3.20)
# Define project name and version
project(CMAKE_Learn VERSION 1.0)
# Set C++ standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Find all source files
file(GLOB_RECURSE SOURCES "src/*.cpp" "src/*.c")
file(GLOB_RECURSE HEADERS "include/**/*.hpp" "include/**/*.h")
# Add include directories
include_directories(include)
# Create executable
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
# Link libraries, here add
# target_link_libraries(${PROJECT_NAME} PRIVATE needed_library)
# Header-only library
breUtils
target_link_directories(${PROJECT_NAME} PRIVATE /home/breeze/cpp/a_forwork/BreUtils)
# ffmpeg
target_link_directories(${PROJECT_NAME} PRIVATE /usr/local/lib)
target_link_libraries(${PROJECT_NAME} PRIVATE     avcodec    avformat    avutil    swscale    swresample    avfilter    avdevice    postproc)
# boost
target_link_directories(${PROJECT_NAME} PRIVATE /usr/local/lib)
target_link_libraries(${PROJECT_NAME} PRIVATE     boost_system    boost_filesystem)
# libjsoncpp
find_package(jsoncpp CONFIG REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE jsoncpp_lib)
# mysqlcppconn
# set(MYSQL_INCLUDE_DIR /usr/include/mysql-cppconn)
# set(MYSQL_LIBRARY /usr/lib/x86_64-linux-gnu/libmysqlcppconn.so.10)
find_package(mysql-concpp REQUIRED)
target_link_libraries(${PROJECT_NAME} PRIVATE mysqlcppconn)
# macOS
if(APPLE)    enable_language(OBJCXX)    # Add system libraries and frameworks    target_link_libraries(${PROJECT_NAME} PRIVATE         "-framework Foundation"    )endif()
# Windows
if(WIN32)    # Add Windows-specific settings or librariesendif()
# Linux
if(UNIX AND NOT APPLE)    # Add Linux-specific settings or librariesendif()
# Install targets
# install(TARGETS ${PROJECT_NAME} DESTINATION bin)
# install(DIRECTORY include/ DESTINATION include/${PROJECT_NAME})
Related Links
  • CMake Official Website https://cmake.org/CMake
  • Official Documentation: https://cmake.org/cmake/help/latest/guide/tutorial/index.html
  • Rookie: https://www.runoob.com/cmake/cmake-tutorial.html

Leave a Comment