c-cpp-cookies
  • Полезные материалы
    • About
  • Настройка окружения
    • Git
      • Git CLI
      • Git GUI
      • Git Web
      • Git в среде разработке
        • Visual Studio
        • Visual Studio Code
        • CLion
        • Qt Creator
    • Стандарты (они же ISO)
    • Qt about
    • IDE
      • Visual Studio Code
        • Код в Visual Studio Code
        • Разработка в Visual Studio Code
      • Visual Studio
        • Настройки Visual Studio и проектов
        • Код в Visual Studio
        • Visual Studio + GitHub
      • Qt + Qt Creator
        • Установка Qt и QtCreator
        • Примеры проектов на Qt
      • CLion
        • Настройки CLion
        • Код в CLion
        • CLion + GitHub
    • Компиляторы
      • Clang + Visual Studio
      • Clang + CLion
  • Best practices
    • Антипаттерны и способы улучшения кода
      • 0. Освобождение ресурсов
      • 1. Чтение данных из файла
      • 2. Открытие файлов
      • 3. Объявление переменных
      • 4. Выделение памяти
      • 5. Необдуманный код
      • 6. Глубокие if
      • 7. Длинные if
      • 9. Non-void функции
      • 10. Создание массивов
      • 11. Проверка формата файла
  • Сборка программы
    • Сборка программы
    • Системы сборки / Build systems
      • Проект и решение
      • Make
      • Ninja
      • CMake
      • MSBuild
    • Подключение внешних библиотек
    • Библиотеки
  • Отладка
    • Отладка / Debugging
    • Запуск программы
    • Точки останова / Breakpoints
      • Обычные точки останова / General breakpoint
      • Условные точки останова / Conditional breakpoint
      • Зависимые точки останова / Dependent breakpoint
      • Временные точки останова / Temporary breakpoint
      • Точки трассировки / Breakpoint actions и tracepoints
    • Стек вызовов / Call stack
    • Локальные переменные / Locals
    • Просмотр области памяти / Memory view
    • Исключения / Exceptions
  • Анализ
    • Поиск утечек памяти
    • Санитайзеры
  • Возможности IDE
    • Возможности IDE
    • Продвинутый текстовый редактор
    • Закладки / Bookmarks
    • Платформы / Platforms
    • Конфигурации сборки / Build configurations
    • Шаблонные проекты / Project templates
    • Терминал / Terminal
    • Сборка / Build
    • Запуск программы / Run program
    • Code style
    • Работа с Github Actions
  • Тестирование
    • Тестирование
    • Google test
      • Gtest в VS
      • Gtest в CLion
      • Gtest в VSCode
    • Покрытие кода (code coverage)
Powered by GitBook
On this page
  1. Сборка программы
  2. Системы сборки / Build systems

CMake

PreviousNinjaNextMSBuild

Last updated 1 month ago

CMake – кроссплатформенная автоматизированная система сборки проектов. Непосредственно сборкой она не занимается, а только генерирует Makefile, который потом будет выполнен утилитой make.

Использует текстовый файл CMakeLists.txt для описания зависимостей и настроек для сборки проекта.

Минимальный CMakeLists.txt для создания исполняемого файла

# Создает исполняемый файл с именем main из исходника main.c
add_executable(test_project main.c)  
"cmake.exe" --build ...\cmake-build-release --target DebuggingExample -j 25
[1/2] Building C object CMakeFiles/DebuggingExample.dir/main.c.obj
[2/2] Linking C executable DebuggingExample.exe

Build finished

Также можно указать минимальную необходимую версию утилиты:

cmake_minimum_required(VERSION 3.10)

Проекты в CMake задаются конструкцией project. Также можно добавить версию проекта.

project(cmake_test_project)
project(cmake_test_project VERSION 1.0)

Версия стандарта указывается через конструкцию set:

# C standart
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_STANDARD_REQUIRED True)

# C++ standart
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED True)

Можно создавать текстовые переменные. Затем созданные переменные можно использовать в дальнейших конструкциях

set(SOURCES test.c)
add_executable(cmake_test_project ${SOURCES})

Preprocessor definitions

add_definitions(-DMY_DEBUG_MACROS)

Добавление флагов компиляции:

set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -O2")

Целью сборки может быть не только исполняемый файл, но и библиотека:

add_library(libjpegtools STATIC JpegTools.h JpegTools.c) # статическая библиотека
add_library(libjpegtools SHARED JpegTools.h JpegTools.c) # динамическая библиотека

Указание include directories:

include_directories("headers/" "include/") # задание для всех целей проекта
# target_include_directories(myTarget PUBLIC ./include)  # для определённой цели

Указание libraries directories:

link_directories(${OpenCL_LIBRARY}) # задание для всех целей проекта
# target_link_directories(myTarget PUBLIC opencv_world3416.lib)  # для определённой цели

Вы можете выбирать область видимости настройки: PUBLIC делает настройку видимой для текущей цели и для всех зависящих от неё целей, PRIVATE делает настройку видимой только для текущей цели и INTERFACE делает настройку видимой только для всех зависящих от неё целей.

Пример с подключением заголовочных и библиотеки

cmake_minimum_required(VERSION 3.20)
project(ocl1 C)

set(CMAKE_C_STANDARD 17)

set(OpenCL_INCLUDE_DIRS "$ENV{OCL_ROOT_x64}/include")
set(OpenCL_LIBRARY "$ENV{OCL_ROOT_x64}/lib")

find_package(OpenCL 1.2 REQUIRED)
include_directories(${OpenCL_INCLUDE_DIRS})
link_directories(${OpenCL_LIBRARY})

add_executable(ocl1 opencl_example.c)
target_include_directories (ocl1 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries (ocl1 "OpenCL.lib")

CMake по умолчанию создаёт таргеты в поддиректориях (build/Debug, build/Release и пр.). Для удобства можно задать post-build событие для вызова команды копирования exe-файла в удобное место. Например, скопировать к исходникам можно следующим способом:

add_custom_command(TARGET ocl1 POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:ocl1> ${PROJECT_SOURCE_DIR}/ocl1.exe
    COMMENT "Created ${PROJECT_SOURCE_DIR}/ocl1.exe"
)

find_package() - принимает имя библиотеки как аргумент и обращается к CMake, чтобы найти скрипт для настройки переменных данной библиотеки. За поиск библиотек отвечают модули, называющиеся FindNAME.cmake, где NAME – имя библиотеки. При успешном нахождении компонента будут добавлены переменные, хранящие пути поиска заголовков, имена библиотек для линкера и пр. В примере ниже при нахождении OpenMP добавляются переменные ${OpenMP_C_FLAGS} и ${OpenMP_CXX_FLAGS}.

OPTION (USE_OpenMP "Use OpenMP" ON)
IF(USE_OpenMP)
   FIND_PACKAGE(OpenMP)
   IF(OPENMP_FOUND)
       SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
       SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
   ENDIF()
ENDIF()

Пример с Boost (весь, без указания конкретных компонентов):

find_package(Boost REQUIRED)
# После этого становятся доступны:
  # Boost_INCLUDE_DIRS: пути к заголовочным файлам
  # Boost_LIBRARY_DIRS: пути к библиотекам
  # Boost_LIBRARIES: список файлов библиотек

Конфигурация и сборка

После настройки CMakeLists.txt настроить конфигурацию и затем уже запустить процесс сборки.

Single-config системы сборки. Ниже приведён пример конфигурации сборки в режимах Debug и Release.

# Configure the build
cmake -S . -B build/ -D CMAKE_BUILD_TYPE=Debug

# Actually build the binaries
cmake --build build/
# Configure a release build
cmake -S . -B build/ -D CMAKE_BUILD_TYPE=Release

# Build release binaries
cmake --build build/

Multi-configuration generators. Конфигурация указывается при сборке.

# Configure the build
cmake -S . -B build

# Build debug binaries
cmake --build build --config Debug

# Build release binaries
cmake --build build --config Release

Конфигурация настраивается следующим образом: указываются пути до исходников и до результатов сборки (промежуточных файлов и результата сборки). Дополнительно можно указать переменные для CMake (, build_type и пр.).

generator
CMake Tutorial — CMake 3.26.2 Documentation
Logo