1. Основные понятия

1.1. Артефакты сборки

1.2. Зависимости реального времени

[nix-shell] % ldd /nix/store/9f89z51na7w931aja8lqlmhqny9h16cj-gnugrep-3.1/bin/grep
    linux-vdso.so.1 (0x00007ffc5cde0000)
    libpcre.so.1 => /nix/store/pcre-8.42/lib/libpcre.so.1 (0x00007f48f3e86000)
    libc.so.6 => /nix/store/glibc-2.27/lib/libc.so.6 (0x00007f48f3ad2000)
    libpthread.so.0 => /nix/store/glibc-2.27/lib/libpthread.so.0 (0x00007f48f38b3000)
    /nix/store/glibc-2.27/lib/ld-linux-x86-64.so.2 => /nix/store/glibc-2.27/lib64/ld-linux-x86-64.so.2 (0x00007f48f40f8000)

1.3. Этапы сборки программ и библиотек

  1. Препроцессинг — замена #define, #include и макросов
  2. Компиляция — получение объектного кода
  3. Архивирование (необязательно) — получение статической библиотеки
  4. Линковка — сборка всего в исполняемый файл или динамическую библиотек

1.4. Пример этапов сборки

cluster0 Уровень исполнения cluster1 Уровень компиляции cluster2 Уровень кода cluster3 Уровень препроцессинга app0 app0 liba liba.so app0->liba ld-linux, link libc libc.a app0->libc link obj5 main0.o app0->obj5 link app1 app1 app1->liba ld-linux, link obj6 main1.o app1->obj6 link libd libd.a liba->libd link obj0 obj0.o libc->obj0 archive obj1 obj1.o libc->obj1 archive obj2 obj2.o libc->obj2 archive obj3 obj3.o libd->obj3 archive obj4 obj4.o libd->obj4 archive src0 src0.c obj0->src0 compile src1 src1.c obj1->src1 compile src2 src2.c obj2->src2 compile src3 src3.cpp obj3->src3 compile src4 src4.cpp obj4->src4 compile main0 main0.c obj5->main0 compile main1 main1.cpp obj6->main1 compile hdr0 hdr0.h src0->hdr0 preprocess main0->hdr0 preprocess hdr1 hdr1.hpp main1->hdr1 preprocess

2. Введение в CMake

2.1. Ссылки

2.2. Структура проекта для CMake

2.3. Цели по умолчанию

3. Синтаксис языка CMake

3.1. Синтаксис CMake

3.2. Переменные

4. Примеры

4.1. MWE (Minimal Workable Example)

cmake_minimum_required(VERSION 3.9)
project(example VERSION 0.1.0 LANGUAGES CXX DESCRIPTION "la-la-la")

set(CMAKE_CXX_STANDARD 17)

include(CTest)

file(GLOB SOURCES src/*.cpp)
add_library(unit STATIC ${SOURCES}) # libunit.a
target_include_directories(unit PUBLIC include)

add_executable(example app/main.cpp)
target_link_libraries(example PUBLIC unit m dl)

add_test(NAME simple_test COMMAND example --filter sim --dir /tmp)
set_tests_properties(simple_test PROPERTIES PASS_REGULAR_EXPRESSION "hello world")

4.2. Пример создания пакета

include(GNUInstallDirs)

install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
install(TARGETS example unit
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

list(APPEND CPACK_GENERATOR TGZ)
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
set(CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR})
set(CPACK_PACKAGE_CONTACT "MIET")
set(CPACK_DEBIAN_PACKAGE_DEPENDS "libfuse3 (>= 3.2.0)")
include(CPack)

5. Связывание проектов

5.1. Экспорты

5.2. Install-дерево и export

target_include_directories(unit PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>)

install(TARGETS example unit EXPORT ${PROJECT_NAME}-config
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(EXPORT ${PROJECT_NAME}-config NAMESPACE my:: DESTINATION ${CMAKE_INSTALL_DATADIR}/cmake/${PROJECT_NAME})

export(TARGETS example unit NAMESPACE my:: FILE ${PROJECT_NAME}-config.cmake)
export(PACKAGE ${PROJECT_NAME})

5.3. Использование в стороннем проекте

find_package(example REQUIRED)

add_executable(myprog ${SRCS})
target_link_libraries(myprog my::unit)

Если проект example установлен по нестандартному пути /path/to/example, его можно указать в переменной окружения CMAKE_PREFIX_PATH:

$ export CMAKE_PREFIX_PATH+=:/path/to/example

5.4. Экспорты для сторонних библиотек

# Файл cmake/FindFuse.cmake
find_path(FUSE_INC fuse3/fuse.h)
find_library(FUSE_LIBS fuse3)

add_library(Fuse::fuse3 INTERFACE IMPORTED)
set_target_properties(Fuse::fuse3 PROPERTIES
    INTERFACE_LINK_LIBRARIES ${FUSE_LIBS}
    INTERFACE_INCLUDE_DIRECTORIES ${FUSE_INC}
)
Использование
list(APPNED CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
#list(APPEND CMAKE_MODULE_PATH $ENV{CMAKE_MODULE_PATH})

find_package(Fuse REQUIRED)
target_link_libraries(myprog PUBLIC Fuse::fuse3)

6. Дополнительная функциональность

6.1. Подкаталоги

cmake_minimum_required(VERSION 3.9)
project(example CXX)

file(GLOB SRCS src/*cpp)
add_library(unit ${SRCS})
add_subdirectory(tests)
# tests/CMakeLists.txt
add_executable(testengine main.cpp)
target_link_libraries(testengine unit)

add_test(first testengine -i one)
add_test(second testengine -i two)
add_test(third testengine -i three)

6.2. Тесты