Setting Up Your First CMake Project
cmake_minimum_required(VERSION 3.20)
project(Hello)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(Hello hello.cpp)
project(<PROJECT-NAME>
[VERSION <major>[.<minor>[.<patch>[.<tweak>]]]]
[DESCRIPTION <project-description-string>]
[HOMEPAGE_URL <url-string>]
[LANGUAGES <language-name>...])
cmake_minimum_required(VERSION 3.20.0)
project(Rental CXX)
add_executable(Rental
main.cpp
cars/car.cpp
# more files in other directories
)
Working with Targets
Essentially, it’s a recipe that a buildsystem uses to compile a list of files into another file. It can be a .cpp
implementation file compiled into an .o
object file, a group of .o
files packaged into an .a
static library, and many other combinations.
All that’s required is an add_executable()
command with the name of the executable target and a list of the files that are to be its elements
In CMake, we can create a target using one of three commands:
add_executable()
add_library()
add_custom_target()
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[<source>...])
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...])
for build you can specify a target or build all project
--build binary_directroy --target [all|target]
add source to target
add_executable(main main.cpp)
if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
target_sources(main PRIVATE gui_linux.cpp)
elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows")
target_sources(main PRIVATE gui_windows.cpp)
endif()
preprocessing definitions
add paths to include
target_include_directories(<target> [SYSTEM] [AFTER|BEFORE]
<INTERFACE|PUBLIC|PRIVATE> [item1...]
[<INTERFACE|PUBLIC|PRIVATE> [item2...] ...])
add definition
set(VAR 8)
add_executable(defined definitions.cpp)
target_compile_definitions(defined PRIVATE ABC
"DEF=${VAR}")
int main() {
#if defined(ABC)
std::cout << "ABC is defined!" << std::endl;
#endif
#if (DEF < 2*4-3)
std::cout << "DEF is greater than 5!" << std::endl;
#endif
}
compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -DNO_DEBUG")
set(CMAKE_CXX_FLAGS "-Wall -Wextra")
set(CMAKE_CXX_FLAGS_DEBUG "-g")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
Managing Dependencies with CMake
- A static library has a
.a
extension on Unix-like systems and.lib
on Windows. - Shared libraries have a
.so
extension on Unix-like systems and.dll
on Windows.
if you install library like
apt install protobuf-compiler libprotobuf-dev
find_package(Protobuf REQUIRED)
target_link_libraries(main PRIVATE ${Protobuf_LIBRARIES})
target_include_directories(main PRIVATE
${Protobuf_INCLUDE_DIRS}
${CMAKE_CURRENT_BINARY_DIR})
find_package(Protobuf REQUIRED)
asks CMake to run the bundled FindProtobuf.cmake
find-module and set up the Protobuf library for us. That find-module will scan commonly used paths and (because we provided the REQUIRED
keyword) terminate if a library is not found. It will also specify useful variables and functions (such as the one on the next line).target_link_libraries
adds libraries (static or shared) found by find_package()
to the linking command of our main
target.
<PKG_NAME>_FOUND
<PKG_NAME>_INCLUDE_DIRS
or<PKG_NAME>_INCLUDES
<PKG_NAME>_LIBRARIES
or<PKG_NAME>_LIBRARIES
or<PKG_NAME>_LIBS
<PKG_NAME>_DEFINITIONS
IMPORTED
targets specified by the find-module or config-file
find_package(<Name> [version] [EXACT] [QUIET] [REQUIRED])
for cmake files have format <package>Config.cmake
find_package(Foo CONFIG REQUIRED)
target_link_libraries(boo foo)
add_library(MyLib SHARED ./lib/MyLib.cpp)
target_link_directories(MyLib PUBLIC ./lib)
target_include_directories(MyLib PUBLIC ./lib)
find_package(TBB REQUIRED)
target_link_libraries(MyLib PUBLIC tbb)
#libraries linked to MyLib target like tbb will used inside test target because it linked with MyLib and MyLib is public link with tbb
add_executable(test main.cpp ${res_files})
find_package(Qt6 REQUIRED COMPONENTS Core)
target_link_libraries(test PRIVATE Qt6::Core)
target_link_libraries(test PUBLIC MyLib)