Сборка проекта на C++ через CMake с нуля: первый работающий билд
Как за полчаса собрать первый проект на C++ с помощью CMake: минимальный CMakeLists.txt, папка сборки, подключение библиотеки и что делать, если конфигурация упала с ошибкой.

В конце у вас будет проект на C++, который собирается одной командой на Linux, macOS и Windows, без ручного вызова компилятора. Мы напишем минимальный CMakeLists.txt, соберём исполняемый файл, подключим внешнюю библиотеку и разберём типичные ошибки конфигурации. На всё уходит 20–40 минут. Статья написана для CMake 3.20 и новее (проверялось на 3.28); синтаксис ниже работает и в свежих 3.x-релизах.
Что нужно до начала
CMake — это генератор сборки: он не компилирует код сам, а создаёт файлы для другого инструмента (Make, Ninja, Visual Studio) и следит за зависимостями. Поэтому кроме CMake нужен ещё и компилятор.
- CMake 3.20+. Проверьте:
cmake --version. Если команды нет — ставьте с cmake.org или через пакетный менеджер (apt install cmake,brew install cmake). - Компилятор C++: GCC, Clang или MSVC. На Linux обычно уже есть
g++, на macOS ставится черезxcode-select --install, на Windows — вместе с Visual Studio Build Tools. - Система сборки: Make (Linux/macOS по умолчанию) или Ninja. Ninja быстрее, ставится отдельно, но не обязателен для первого билда.
Если cmake --version выводит номер версии, а g++ --version или clang++ --version тоже что-то печатает — всё готово.
Шаг 1. Заведите структуру папок
Создайте папку проекта и файл с исходником:
myapp/
├── CMakeLists.txt
└── src/
└── main.cpp
Содержимое src/main.cpp — самое простое, чтобы было что собирать:
#include <iostream>
int main() {
std::cout << "Сборка работает\n";
return 0;
}
Проверка: файлы на месте, в main.cpp есть функция main.
Шаг 2. Напишите CMakeLists.txt
Это управляющий файл проекта. Минимальный рабочий вариант:
# Минимальная версия CMake, ниже которой сборка не поддерживается
cmake_minimum_required(VERSION 3.20)
# Имя проекта и язык
project(myapp LANGUAGES CXX)
# Стандарт C++ и требование его соблюдать
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Создаём исполняемый файл myapp из указанных исходников
add_executable(myapp src/main.cpp)
Три строки делают всё: project() объявляет проект, set(CMAKE_CXX_STANDARD 17) фиксирует диалект языка, add_executable() говорит, что собрать и из чего.
Проверка: файл сохранён в корне myapp/, а не внутри src/.
Шаг 3. Сконфигурируйте сборку
CMake требует держать сборку отдельно от исходников — так называемый out-of-source build. Из корня проекта выполните:
cmake -S . -B build
Флаг -S . указывает на исходники (текущая папка), -B build — куда положить сгенерированные файлы. CMake создаст папку build/, найдёт компилятор и напишет в конце что-то вроде Generating done.
Папкуbuild/не коммитят в git. Добавьте её в.gitignoreсразу — иначе репозиторий распухнет от временных файлов конкретной машины.
Проверка: появилась папка build/ с файлом CMakeCache.txt внутри, в консоли нет строки со словом Error.
Шаг 4. Соберите проект
Не вызывайте make напрямую — используйте универсальную команду, она работает одинаково с любым генератором:
cmake --build build
После сборки бинарник лежит в build/ (на Windows с MSVC — в подпапке вроде build/Debug/). Запустите:
./build/myapp
Проверка: в терминале появилась строка Сборка работает. Первый билд готов.
Шаг 5. Подключите внешнюю библиотеку
Одиночный main.cpp редко бывает целью. Покажем два способа подключить зависимость — они закрывают большинство случаев новичка.
Библиотека уже установлена в системе
Если библиотека поставляется с CMake-конфигом (так делают многие: fmt, spdlog, Boost), используйте find_package:
find_package(fmt REQUIRED)
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE fmt::fmt)
REQUIRED заставит CMake упасть на конфигурации, если библиотека не найдена, — это лучше, чем ошибка компоновщика на этапе сборки. Имя цели (fmt::fmt) смотрите в документации самой библиотеки, не угадывайте.
Библиотеки в системе нет
Тогда её можно скачать во время конфигурации через FetchContent — модуль входит в поставку CMake:
include(FetchContent)
FetchContent_Declare(
fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 10.2.1 # фиксируйте тег, а не master
)
FetchContent_MakeAvailable(fmt)
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE fmt::fmt)
Первая конфигурация будет дольше — CMake склонирует репозиторий. Точный тег версии проверяйте в релизах проекта на GitHub, а не подставляйте по памяти.
Проверка: после cmake -S . -B build в логе видно скачивание, а #include <fmt/core.h> в коде компилируется без ошибки «файл не найден».
Debug и Release: одна забытая деталь
По умолчанию с генераторами Make и Ninja сборка идёт без оптимизаций и без отладочной информации. Тип задаётся на этапе конфигурации:
| Тип | Команда конфигурации | Когда |
|---|---|---|
| Debug | cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug | отладка, работа под gdb/lldb |
| Release | cmake -S . -B build -DCMAKE_BUILD_TYPE=Release | сборка для запуска, замеры скорости |
С Visual Studio и другими multi-config генераторами тип задаётся не здесь, а при сборке: cmake --build build --config Release. Это частый источник путаницы между платформами.
Если не получилось
CMake Error: CMAKE_CXX_COMPILER not set— CMake не нашёл компилятор. Установите GCC/Clang или, на Windows, запускайте из «x64 Native Tools Command Prompt», где переменные окружения MSVC уже настроены.The source directory does not appear to contain CMakeLists.txt— вы запустилиcmakeне из той папки или указали неверный путь после-S. Проверьте, чтоCMakeLists.txtлежит в директории, переданной в-S.Could not find a package configuration file provided by "fmt"—find_packageне нашёл библиотеку. Либо её нет в системе (перейдите наFetchContent), либо она стоит в нестандартном месте — тогда подскажите путь через-DCMAKE_PREFIX_PATH=/путь.- Меняли CMakeLists.txt, а изменения «не подхватываются» — иногда кеш конфигурации ломается. Удалите папку
build/целиком и сконфигурируйте заново. Это безопасно: исходники там не хранятся. undefined referenceна этапе сборки — забылиtarget_link_librariesили указали неверное имя цели библиотеки. Компилятор нашёл заголовки, но линковщик — не нашёл код.
Что делать дальше
Первый билд собирается — дальше стоит навести порядок. Разбейте код на несколько файлов и соберите из них статическую библиотеку через add_library, подключив её к исполняемому файлу тем же target_link_libraries. Посмотрите пресеты (CMakePresets.json) — они хранят наборы флагов конфигурации в файле, чтобы не набирать длинные команды руками. Когда появятся тесты — подключите enable_testing() и add_test, чтобы гонять их командой ctest. Официальная документация по всем командам живёт на cmake.org/documentation — сверяйтесь с ней для вашей версии, поведение отдельных модулей между 3.x-релизами менялось.
Карточки для маркетплейсов: Таблица товаров и папка фотографий на входе — комплект слайдов и описаний на выходе, по требованиям Wildberries и Ozon.
Спросить за 5 ₽Источники: CMake Documentation (официальная документация), CMake Tutorial — официальное руководство
Частые вопросы
У меня CMake 3.16, а в статье 3.20 — сработает ли?
Обязательно ли выносить сборку в отдельную папку build?
Чем cmake --build build лучше, чем просто make?
Не собирается на Windows: пишет, что компилятор не найден. Что делать?
Как задать флаги компилятора, например -Wall?
Изменил CMakeLists.txt, но сборка ведёт себя по-старому. Это баг?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.