Движок с нуля
Часть 1 · Старт · глава 1.3

Сборка и запуск из консоли

Соберёшь проект двумя командами и запустишь свою первую программу.

В папке D:\dev\MyEngine лежат код и описание сборки. Теперь с помощью CMake ты сделаешь из них программу. Превращение кода в программу и называется сборкой. В консоли сборка — это две команды, и у каждой свой шаг:

  1. настроить — CMake читает CMakeLists.txt, выясняет, какие инструменты есть на компьютере, и пишет файлы для сборки;
  2. собрать — сборщик читает эти файлы и запускает компилятор и линкер, которые делают из кода файл app.exe.

Первая команда: настройка

Если не получилось3
CMake Error: The source directory "C:/Users/user" does not appear to contain CMakeLists.txt. Путь в кавычках у тебя будет другой: это папка, в которой сейчас стоит консоль.
Почему
В команде cmake -S . -B build точка после -S означает «текущая папка», и CMake ищет CMakeLists.txt именно в ней. Консоль стоит не в папке проекта, поэтому файла там нет.
Что сделать

Перейди в папку проекта командой cd D:\dev\MyEngine и выполни cmake -S . -B build ещё раз.

CMake Error at CMakeLists.txt:5 (add_executabl): Unknown CMake command "add_executabl". Номер строки после двоеточия и название команды в скобках у тебя могут быть другими. В конце вывода — Configuring incomplete, errors occurred!.
Почему
CMake читает CMakeLists.txt сверху вниз и выполняет команды по одной. Название команды написано с опечаткой, такой команды CMake не знает и останавливается. Дойти до записи файлов он не успел, поэтому в папке build файлов для сборки нет.
Что сделать

Открой CMakeLists.txt и перейди к строке, номер которой стоит после двоеточия в сообщении. Сравни название команды с названием в образце, исправь опечатку, сохрани файл и снова выполни cmake -S . -B build.

Cannot find source file: main.cpp Перед этим в выводе есть Configuring done, а в конце — CMake Generate step failed..
Почему
Сам CMakeLists.txt написан верно, поэтому настройка дошла до конца. Ошибка возникла при записи файлов: CMake проверил, что main.cpp, названный в CMakeLists.txt, лежит рядом с ним, и не нашёл его.
Что сделать

Проверь, что main.cpp лежит в папке D:\dev\MyEngine, рядом с CMakeLists.txt, а не во вложенной папке, и что имя написано без опечаток. Проводник может скрывать расширение, тогда файл на деле называется main.cpp.txt. Исправь и снова выполни cmake -S . -B build.

Вот что CMake пишет по ходу работы.

Что делает команда cmake -S . -B build

PowerShell
PS D:\dev\MyEngine> cmake -S . -B build-- Building for: Visual Studio 18 2026-- Selecting Windows SDK version 10.0.26100.0 to target Windows 10.0.26300.-- The CXX compiler identification is MSVC 19.51.36260.0-- Detecting CXX compiler ABI info-- Detecting CXX compiler ABI info - done-- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.51.36231/bin/Hostx64/x64/cl.exe - skipped-- Detecting CXX compile features-- Detecting CXX compile features - done-- Configuring done (1.9s)-- Generating done (0.0s)-- Build files have been written to: D:/dev/MyEngine/build
На схеме твой проект — папка, где лежат CMakeLists.txt и main.cpp, — CMake и папка build — её создал CMake по флагу -B. На схеме папка пока пустая: CMake заполнит папку по ходу вывода. Отдельно — Visual Studio: в ней CMake найдёт всё, что нужно для сборки. Каждая строка вывода начинается с -- — так CMake отмечает свои сообщения.
Сначала вся цепочка целиком. В CMake есть генератор Visual Studio, и CMake пишет список дел — файл app.vcxproj, в котором записано, что собрать, из каких файлов и в каком порядке. Этот файл читает MSBuild, сборщик из Visual Studio, и по списку запускает компилятор и линкер. Путь состоит из двух половин. Первая — часть схемы с CMake: CMake прочитал CMakeLists.txt, нашёл на компьютере Visual Studio и записал список дел app.vcxproj в папку build. Вторая — часть схемы с Visual Studio: MSBuild читает этот список, запускает компилятор и линкер, и получается программа app.exe. Команда cmake -S . -B build, которую ты запустил, проходит только первую половину. Список дел написан, но MSBuild его ещё не выполнял и компилятор с линкером не запускал, поэтому программы пока нет. Вторую половину пройдёт вторая команда, сборка.
Building for: Visual Studio 18 2026 — CMake выбрал генератор. Теперь по частям. Сам CMake ничего не компилирует: CMake пишет список дел: что собрать, из каких файлов и в каком порядке.
Выполняет этот список другая программа — сборщик. Сборщиков несколько, и каждый читает список только в своём формате: сборщик MSBuild — файлы .vcxproj, Ninja — build.ninja, Make — Makefile.
Значит, CMake должен заранее решить, для какого сборщика писать. Этим и занят генератор: он записывает список дел в формате одного сборщика. Таких генераторов в CMake много. Наш генератор — Visual Studio 18 2026, об этом и говорит строка Building for. Генератор мы не указывали: CMake сам нашёл Visual Studio на компьютере и выбрал её генератором по умолчанию для Windows. Поэтому список дел будет записан для сборщика MSBuild, который и выполнит этот список.
Selecting Windows SDK version 10.0.26100.0 — CMake выбрал Windows SDK: файлы, через которые программа обращается к Windows. Даже текст в консоль в конце концов выводит Windows. Без этих файлов компилятор не знал бы, какие функции Windows существуют и как их вызывать. Последнее число в строке — версия твоей Windows. У SDK своя версия, и совпадать они не обязаны.
The CXX compiler identification is MSVC 19.51 — CMake нашёл компилятор C++. Искать компилятор велела строка project(Engine LANGUAGES CXX) в твоём CMakeLists.txt. Нашёлся cl.exe из Visual Studio — его полный путь виден ниже. 19.51 — версия компилятора.
Detecting… и Check for working… — проверки. CMake собирает крошечные пробные программы и смотрит, что вышло: как именно компилятор записывает программу в машинный код (ABI) и какие возможности C++ он знает. Слово skipped в строке с путём к cl.exe — не ошибка: проверка Detecting CXX compiler ABI info уже собрала пробную программу компилятором cl.exe, значит компилятор работает, и отдельную проверку CMake пропускает.

Configuring done — закончилась первая часть настройки: CMake прочитал CMakeLists.txt до конца и понял, что собирать. Из CMakeLists.txt CMake узнал, что в проекте есть цель app, которая собирается из кода, написанного в файле main.cpp, и что код на C++. В скобках — сколько секунд занял шаг.

Generating done — генерация закончилась: CMake записал в файлы на языке сборщика MSBuild всё, что выяснил при настройке: цель app, которая собирается из main.cpp, компилятор cl.exe и Windows SDK. Предыдущая строка, Configuring done, говорила только о том, что CMake понял, что собирать, а файлов ещё не было. Файлов несколько, главные два:

  • app.vcxproj — список дел для сборщика по цели app. В этом файле записано: перевести main.cpp в машинный код компилятором, затем соединить результат в app.exe. Файл текстовый, и открыть файл можно в Блокноте. Назван по цели app из твоего CMakeLists.txt;
  • Engine.slnx — файл решения. Назван по имени проекта Engine из CMakeLists.txt.

Третий файл, CMakeCache.txt, не список дел, а память CMake. В CMakeCache.txt записано, что CMake выяснил о компьютере: генератор и путь к компилятору. Следующие запуски настройки и сборка читают этот файл и не ищут всё заново.

Build files have been written to: D:/dev/MyEngine/build — последней строкой CMake сообщает, куда положил результат своей работы: в папку сборки build. Там теперь лежат все сгенерированные файлы из шага Generating done. А app.exe там ещё нет: CMake только подготовил задание, собирать будет вторая команда. Пути CMake пишет через /, как в Linux. Windows понимает оба варианта.

Вторая команда: сборка

Список дел app.vcxproj записан, но программы ещё нет. Вторая команда передаст файлы из папки build сборщику MSBuild, и MSBuild запустит компилятор и линкер.

Если не получилось2
Error: could not load cache
Почему
Команда cmake --build build берёт из папки build то, что записала настройка, в том числе файл CMakeCache.txt. Файла CMakeCache.txt там нет: либо консоль стоит не в папке проекта, и CMake ищет папку build не там, либо первая команда не дошла до конца и ничего не записала.
Что сделать

Перейди в папку проекта командой cd D:\dev\MyEngine. Проверь, что после первой команды последней строкой было Build files have been written to: D:/dev/MyEngine/build. Если такой строки нет, сначала исправь сбой первой команды, а потом снова выполни cmake --build build.

Вывод остановился на строке с error, например main.cpp(6,5): error C2143, а строки app.vcxproj -> …\app.exe нет.
Почему
Компилятор cl.exe не смог перевести main.cpp в машинный код: в твоём коде ошибка. Сборка остановилась на этом шаге, линкер не запускался, и поэтому app.exe не появился.
Что сделать

После имени файла в скобках стоят номер строки и номер символа в ней: main.cpp(6,5) значит «строка 6, символ 5». Открой main.cpp и найди эту строку. Чаще всего ошибка сидит в предыдущей строке: там не хватает точки с запятой в конце, а компилятор замечает это только на следующей. Сверь код с образцом, исправь, сохрани файл и снова выполни cmake --build build. Настройку повторять не нужно.

Вывод короче, чем у настройки, но за ним стоит больше работы.

Что делает cmake --build и кто компилирует проект

PowerShell
PS D:\dev\MyEngine> cmake --build buildВерсия MSBuild 18.10.1-1.26427.6+3cd27c13e для .NET Framework 1>Checking Build SystemBuilding Custom Rule D:/dev/MyEngine/CMakeLists.txtmain.cppapp.vcxproj -> D:\dev\MyEngine\build\Debug\app.exeBuilding Custom Rule D:/dev/MyEngine/CMakeLists.txt
CMake и в этот раз ничего не компилирует сам: он запускает сборщика. Какого именно, CMake знает ещё с настройки. При настройке CMake записал в файл CMakeCache.txt в папке build, какой генератор выбран. По этой записи CMake находит нужного сборщика и запускает сборщик на файлах из папки build, среди которых и список дел app.vcxproj. Дальше всю работу делает сборщик, а CMake лишь показывает его вывод в консоли. Это вторая половина пути, который показан в реплике про всю цепочку: MSBuild читает список, запускает компилятор и линкер.

Версия MSBuild 18.10.1 — первая строка вывода, и написал её уже не CMake, а сборщик MSBuild, которого CMake только что запустил. Так программа при старте сообщает свою версию. MSBuild входит в Visual Studio, но это отдельная программа, поэтому дальше в консоли идёт её собственный вывод.

Среди файлов из папки build MSBuild находит app.vcxproj — файл, который CMake записал при настройке, — и дальше собирает программу по нему.

В конце строки стоит .NET Framework, и на сборку это не влияет. Вывод MSBuild частично на русском («Версия»), частично на английском: так он работает в русской Windows.

Checking Build System — «проверка системы сборки». Сначала MSBuild проверяет, не менялся ли CMakeLists.txt после того, как его прочитал CMake. Для этого CMake при настройке оставил в папке build отметку со временем, а MSBuild сравнивает с ней время последнего изменения файла.

Если файл изменился, MSBuild сам запускает CMake, и тот делает то же, что при первой команде: заново читает CMakeLists.txt и перезаписывает файлы в папке build, в том числе app.vcxproj. Сборка идёт уже по новому списку дел, поэтому повторять настройку вручную не нужно.

Сейчас файл не менялся, CMake не запускается, и строки Building Custom Rule … CMakeLists.txt проходят вхолостую. Строк Building Custom Rule две, потому что такая проверка есть в двух проектах из папки build: app.vcxproj и ALL_BUILD.vcxproj. 1> в начале строки — номер задачи у MSBuild.

main.cpp — MSBuild перешёл к первому делу из списка: перевести этот файл в машинный код. Для этого MSBuild запустил cl.exe и передал ему main.cpp. Компилятор печатает только имя файла, над которым работает, а если ошибок нет, больше ничего не пишет.

Результат работы компилятора — файл main.obj. Это объектный файл: машинный код твоей функции main. Запустить main.obj нельзя. В main.cpp ты только вызываешь std::cout, а сам код, который выводит текст в консоль, написан не тобой: он лежит в готовой стандартной библиотеке. Поэтому в main.obj есть только ссылка «здесь нужен вывод в консоль», а самого кода нет. Заполнить пустую ссылку должен линкер.

app.vcxproj -> — последний шаг сборки. MSBuild запустил link.exe, и тот взял main.obj и стандартную библиотеку, где лежит код вывода текста, на который ссылался std::cout. Линкер записал на место пустой ссылки, где в библиотеке лежит этот код, и сохранил результат в один файл app.exe.

Стрелка в строке вывода показывает результат: слева проект app.vcxproj, справа — файл, который по нему собрался.

D:\dev\MyEngine\build\Debug\app.exe — путь к готовой программе. Программа лежит в папке сборки build, в подпапке Debug, а имя файла app.exe совпадает с именем цели app из твоего CMakeLists.txt. Теперь программу можно запустить.

Debug — вариант сборки для поиска ошибок. Мы не просили другой, поэтому собрался именно он, и программа лежит в подпапке с таким названием.

Запуск

Если не получилось1
Имя "build\Debug\app.exe" не распознано как имя командлета, функции, файла сценария или выполняемой программы.
Почему
По этому пути нет файла app.exe. Либо вторая команда не дошла до конца и программа не собралась, либо консоль стоит не в папке проекта: путь build\Debug\app.exe считается от текущей папки.
Что сделать

Перейди в папку проекта командой cd D:\dev\MyEngine и посмотри, что лежит в папке сборки: dir build\Debug. Если app.exe там нет, вернись ко второй команде: в выводе второй команды должна быть строка, которая кончается на app.vcxproj -> D:\dev\MyEngine\build\Debug\app.exe. Если такой строки нет, исправь сбой сборки и выполни cmake --build build ещё раз.