from here: https://github.com/mortennobel/CMake-Cheatsheet
Quick example
Assume following source tree, where the source files in Features are to be compiled into a static library, which in turn is required by Application:
. +-- Features | +-- feature1.cpp | +-- feature1.hpp | +-- feature2.cpp | `-- feature2.hpp `-- Application `-- main.cpp
Then, create two CMake script files:
Features/CMakeLists.txt:
cmake_minimum_required (VERSION 3.8) project(Features) file(GLOB sourcefiles feature1.* feature2.*) add_library(Features STATIC ${sourcefiles}) install(TARGETS Features DESTINATION ${CMAKE_CURRENT_LIST_DIR}/lib)
Application/CMakeLists.txt:
cmake_minimum_required (VERSION 3.8) project(Application) set(Features_include ${CMAKE_CURRENT_LIST_DIR}/..) set(Features_libpath ${CMAKE_CURRENT_LIST_DIR}/../Features/lib) include_directories(${Features_include}) link_directories(${Features_libpath}) add_executable(Application main.cpp) target_link_libraries(Application Features) install(TARGETS Application DESTINATION ${CMAKE_CURRENT_LIST_DIR}/bin)
Finally, cd into Features and do:
mkdir .build cd .build cmake .. cmake --build . --target install
Then, cd into Application and do the same.
This can be automated with a Makefile:
all: build .build/CMakeCache.txt: CMakeLists.txt cmake -E make_directory .build cmake -E remove .build/CMakeCache.txt cmake -E chdir .build cmake .. build: .build/CMakeCache.txt cmake -E chdir .build cmake --build . --target install clean: cmake -E remove_directory .build cmake -E remove_directory bin cmake -E remove_directory lib help: @cmake -E echo "usage:" @cmake -E echo @cmake -E echo "make [all] Creates CMake configuration and builds the project." @cmake -E echo "make clean Removes build directory and installation targets." .PHONY: all build clean help Makefile: ; CMakeLists.txt: ;
A more advanced example
Here we have a library with multiple targets: the library itself and two example applications that use the library.
. +-- CMakeLists.txt `-- src +-- lib | +-- feature1.cpp | +-- feature1.hpp | +-- feature2.cpp | `-- feature2.hpp `-- apps +-- example1.cpp `-- example2.cpp
All targets in one CMake script:
cmake_minimum_required (VERSION 3.17) set(project-name project) project(${project-name}) set(CMAKE_CXX_STANDARD 17) include_directories(src/lib) # library set(library-name ${project-name}-2.0) file(GLOB header-files src/lib/*.h) file(GLOB source-files src/lib/*.cc src/lib/*.h) add_library(${library-name} STATIC ${source-files}) install(TARGETS ${library-name} DESTINATION lib) install(FILES ${header-files} DESTINATION include/${project-name}) # applications foreach(app-name example1 example2) add_executable(${app-name} src/apps/${app-name}.cc) target_link_libraries(${app-name} ${library-name}) install(TARGETS ${app-name} DESTINATION bin) endforeach()
Advanced Makefile
CONF=Release CMAKE_CONF = -DCMAKE_BUILD_TYPE=$(CONF) ifeq ($(CONF), Release) BUILD_DIR = .build-release else ifeq ($(CONF), Debug) BUILD_DIR = .build-debug else $(error unknown configuration "$(CONF)") endif all: install $(BUILD_DIR)/CMakeCache.txt: CMakeLists.txt rm -f $@ cmake -S. -B$(BUILD_DIR) $(CMAKE_CONF) build: $(BUILD_DIR)/CMakeCache.txt make -C $(BUILD_DIR) install: build make -C $(BUILD_DIR) install clean: rm -rf $(BUILD_DIR) help: @echo "usage:" @echo @echo "make [CONF={Release|Debug}] [all] Same as make install." @echo @echo "make [CONF={Release|Debug}] install Generates build system," @echo " then builds and installs project." @echo @echo "make [CONF={Release|Debug}] build Generates build system," @echo " then builds project." @echo @echo "make [CONF={Release|Debug}] clean Removes build system." @echo " Does NOT uninstall project." @echo @echo "Default CONF is Release." .PHONY: all build install clean help Makefile: ; CMakeLists.txt: ;
solution CMakeLists.txt
cmake_minimum_required (VERSION 3.16) project(project-name) ## each subdirectory has its own CMake script; # # cmake derives the order automatically from the dependence among targets # (which is defined by the libraries passed to the linker) # library projects add_subdirectory(lib1) add_subdirectory(lib2) # executable projects add_subdirectory(app1) add_subdirectory(app2)
reference
dependence between targets
add_dependencies(<TARGET_A> <TARGET_A_DEPENDS_ON> ...)
execute pre-build commands
add_custom_target(info-message COMMAND echo "Build started: target ${target-lib}") add_dependencies(${target-lib} info-message)
execute post-build commands
add_custom_command(TARGET ${target-lib} POST_BUILD COMMAND echo "Build successful: target ${target-lib}")
for Qt projects
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) find_package(Qt5 REQUIRED COMPONENTS Widgets Core Gui) add_library(lib-name STATIC <FILES> <QT-RESOURCE>.qrc) add_executable(app-name <FILES> <QT-RESOURCE>.qrc)