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

Пресеты сборки

Запишешь настройки сборки в один файл, чтобы консоль и Visual Studio собирали одинаково.

Сейчас у одного проекта две сборки. Консоль настроила проект генератором Visual Studio в папку build, а Visual Studio — генератором Ninja в папку out\build\x64-Debug. Так вышло потому, что каждая программа брала свои настройки по умолчанию, а умолчания у них разные.

Вспомни команду, которой ты настраивал проект в консоли: cmake -S . -B build. В этой команде мы задали только две настройки: флаг -S — где лежит CMakeLists.txt, флаг -B — в какую папку класть сборку. Генератор и процессор мы не указывали, и CMake выбрал их сам, по умолчанию. Но генератор и процессор тоже можно задать флагами: -G задаёт генератор, -A — процессор, для которого собирать программу. Если записать все настройки явно, команда станет такой:

cmake -S . -B build "Visual Studio 18 2026"

Visual Studio так и делает: в её выводе, в строке Command line, была команда с флагами, например -G "Ninja". Visual Studio составляет такую команду сама, а в консоли её пришлось бы набирать вручную при каждой настройке: это долго, и в ней легко ошибиться.

Исправим это неудобство: запишем настройки один раз в файл проекта, который читают обе программы: и cmake в консоли, и Visual Studio. Набор настроек с именем называется пресет, а файл с пресетами — CMakePresets.json.

Файл с настройками

Как устроен файл CMakePresets.json

CMakePresets.jsonкоммит 15bc245
{  "version": 6,  "cmakeMinimumRequired": { "major": 3, "minor": 28, "patch": 0 },  "configurePresets": [    {      "name": "vs2026",      "displayName": "Visual Studio 2026 (x64)",      "generator": "Visual Studio 18 2026",      "architecture": "x64",      "binaryDir": "${sourceDir}/out/build/vs2026"    }  ],  "buildPresets": [    {      "name": "debug",      "displayName": "Debug",      "configurePreset": "vs2026",      "configuration": "Debug"    },    {      "name": "release",      "displayName": "Release",      "configurePreset": "vs2026",      "configuration": "Release"    }  ]}
Файл CMakePresets.json читают двое: CMake в консоли и Visual Studio. Оба берут из него одни и те же настройки и поэтому складывают сборку в одну папку. Файл записан в формате JSON: имена полей в кавычках, после двоеточия — значение. На сцене видны две команды консоли, cmake --preset vs2026 и cmake --build --preset debug. Эти команды ты наберёшь, когда файл будет записан: первая команда настраивает проект, вторая собирает программу. В каждой вместо длинного набора флагов стоит имя пресета из этого файла: в первой — имя пресета настройки, во второй — имя пресета сборки.
“version”: 6 — номер формата, по которому записан файл. Со временем CMake учился понимать в файле всё больше имён настроек, которые стоят слева от двоеточия, например “generator” или “binaryDir”. Набор имён, который понимает данный формат, получил свой номер. Номер 6 говорит CMake: «читай этот файл по правилам шестого формата». Такой формат понимает CMake версии 3.25 и новее, а более старый CMake откажется читать файл. “cmakeMinimumRequired” — то же, что строка cmake_minimum_required в CMakeLists.txt: для этого файла нужен CMake 3.28 или новее. Версия записана по частям: major — 3, minor — 28, patch — 0.
“configurePresets” — список пресетов настройки. Квадратные скобки обозначают список, а фигурные скобки внутри — один пресет. У нас пресет один, но их можно завести несколько, например отдельно для Ninja и для Visual Studio, и выбирать нужный по имени.
“name”: “vs2026” — имя пресета настройки. По этому имени консоль находит нужный пресет: ты пишешь имя в команде после флага --preset, и команда cmake –preset vs2026 настраивает проект по пресету с этим именем. Эта команда заменяет длинную команду, где генератор, процессор и папка сборки записаны флагами: cmake -S . -B out/build/vs2026 -G "Visual Studio 18 2026" -A x64. Всё, что в длинной команде задают флаги, CMake возьмёт из пресета. Имя выбираешь сам, латиницей и без пробелов. Мы назвали пресет по генератору: Visual Studio 2026.
“displayName” — подпись пресета для людей. Имя из “name” короткое, чтобы набирать такое имя в команде, и по нему не всегда понятно, что внутри пресета. В подписи можно писать пробелы и скобки, поэтому программы показывают именно подпись в списках, где человек выбирает нужный пресет. Например, команда cmake --list-presets выводит список всех пресетов настройки вместе с подписью каждого пресета.
“generator”: “Visual Studio 18 2026” — генератор. Это тот же генератор, который CMake в консоли раньше выбирал сам, по умолчанию. В команде настройки генератор задаётся флагом -G: после флага стоит имя генератора. В консоли мы этот флаг не писали, поэтому CMake взял умолчание. В Visual Studio работает свой встроенный CMake, и сама Visual Studio запускает его с флагом -G и генератором Ninja: это умолчание Visual Studio. Теперь генератор записан в файле. Прочитав строку “generator”: “Visual Studio 18 2026”, CMake, и в консоли, и внутри Visual Studio, больше не берёт умолчание, а строго следует файлу: он напишет список дел для сборщика MSBuild в файле app.vcxproj. Этот сборщик входит в Visual Studio и выполнит список дел.
“architecture”: “x64” — процессор, для которого собирать программу. x64 — самый обычный выбор. В команде настройки процессор задаётся флагом -A: после флага стоит имя архитектуры, например -A x64. В консоли мы этот флаг не писали, поэтому генератор Visual Studio выбрал x64 по умолчанию. Теперь процессор записан в файле. Прочитав строку “architecture”: “x64”, CMake больше не берёт умолчание, а строго следует файлу: на любом компьютере программа будет собрана для x64.
“binaryDir” — папка сборки, то есть то, что раньше задавал флаг -B. ${sourceDir} — макрос: вместо него CMake подставит папку проекта. Получится D:\dev\MyEngine\out\build\vs2026: последняя часть пути, vs2026, у нас совпадает с именем пресета, потому что мы сами так записали путь: имя пресета в путь само не попадает. Если завести ещё один пресет настройки, например с именем ninja, сборка этого пресета ляжет в отдельную папку out\build\ninja.

“buildPresets” — список пресетов сборки. Пресет сборки отвечает на два вопроса:

  • что собирать — какой проект. Пресет сборки в поле “configurePreset”: “vs2026” называет пресет настройки, а у этого пресета настройки записана папка сборки, куда настройка уже положила файлы проекта. Из этой папки CMake и собирает;
  • как собирать — в варианте Debug или Release.

Команда cmake –build –preset debug заменяет cmake --build build и берёт пресет сборки с именем “debug”. Пресетов сборки у нас два: debug и release.

“configurePreset”: “vs2026” — какой пресет настройки собирать. Сам пресет сборки не знает ни генератора, ни папки: он ссылается на пресет настройки по name этого пресета и берёт эти настройки оттуда. Поэтому имя в ссылке должно совпадать с значением поля name буква в букву, иначе CMake не найдёт пресет настройки.
“configuration” — какой вариант собрать: Debug или Release. Debug удобен для поиска ошибок, Release работает быстрее. Программы ложатся в разные подпапки: out\build\vs2026\Debug и out\build\vs2026\Release. В Visual Studio эти два пресета становятся пунктами списка конфигураций, и в списке видно их displayName.
Итог: настройки записаны один раз, в файле проекта. Консоль и Visual Studio читают их оттуда, и у проекта теперь одна папка сборки вместо двух. Файл хранится вместе с кодом, поэтому любой, кто скачает проект, соберёт его так же.

Консоль по пресету

Теперь соберём проект по файлу CMakePresets.json, который ты записал. Начнём с консоли: одной командой с именем пресета настройки настроим проект, а другой, с именем пресета сборки, соберём программу.

Если не получилось2
CMake Error: Could not read presets from D:/dev/MyEngine: JSON parse error Путь в сообщении у тебя будет свой: это папка, в которой стоит консоль.
Почему
CMake читает CMakePresets.json строго по правилам формата JSON. Одна пропущенная или лишняя запятая, незакрытая кавычка или скобка — и файл прочитать нельзя, поэтому CMake останавливается ещё до настройки проекта.
Что сделать

Открой CMakePresets.json в Visual Studio и сравни его с текстом из карточки. Чаще всего не хватает запятой после закрывающей фигурной или квадратной скобки, если за ней идёт ещё один элемент, или запятая стоит после последнего элемента. Исправь, сохрани файл и снова выполни команду.

CMake Error: No such preset in D:/dev/MyEngine: "vs2026" Вместо vs2026 может стоять debug, если ошибка при сборке.
Почему
CMake ищет пресет с таким именем в файле CMakePresets.json, который лежит в папке, где стоит консоль. Либо там нет самого файла, либо имя в команде не совпадает с полем name в файле. Файла нет, если консоль стоит не в папке проекта, если файл сохранён в другую папку или если Windows добавила к имени лишнее расширение и получился CMakePresets.json.txt.
Что сделать

Перейди в папку проекта командой cd D:\dev\MyEngine. Проверь в Проводнике, что CMakePresets.json лежит рядом с CMakeLists.txt и у него нет второго расширения .txt. Потом сравни имя из команды с полем name в файле: совпадать должна каждая буква.

PowerShell: вывод настройки
PS D:\dev\MyEngine> cmake --preset vs2026-- 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 (4.0s)-- Generating done (0.0s)-- Build files have been written to: D:/dev/MyEngine/out/build/vs2026

Вывод настройки почти такой же, как без пресета: CMake выбрал Windows SDK, нашёл компилятор, проверил, что компилятор работает. Отличаются две вещи. Пропала строка -- Building for: Visual Studio 18 2026: генератор CMake больше не выбирает сам, а берёт из пресета. И настройка записана в папку из пресета.

PowerShell: вывод сборки
PS D:\dev\MyEngine> cmake --build --preset debugВерсия 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\out\build\vs2026\Debug\app.exeBuilding Custom Rule D:/dev/MyEngine/CMakeLists.txt

Вывод сборки тоже почти прежний: собирал MSBuild, потому что генератор в пресете — Visual Studio. Программа лежит в out\build\vs2026\Debug\app.exe, а не в build\Debug\app.exe.

Visual Studio по пресету

Теперь то же самое сделаем в Visual Studio: откроем папку проекта заново, и Visual Studio настроит проект по файлу CMakePresets.json, а не по своим умолчаниям.

Если не получилось1
В списке конфигураций по-прежнему x64-Debug, а Debug и Release нет, или в окне Output нет строки CMake generation finished.
Почему
Visual Studio ищет CMakePresets.json в папке, которую ты открыл. Если файла там нет или в нём ошибка в записи JSON, Visual Studio не может взять из него пресеты и настраивает проект по-старому, со своими умолчаниями.
Что сделать

Проверь, что CMakePresets.json лежит прямо в D:\dev\MyEngine, рядом с CMakeLists.txt, а не в подпапке. Открой CMakePresets.json в Visual Studio: места с ошибкой подчёркнуты красной волнистой линией. Исправь эти места, сохрани файл, и Visual Studio настроит проект заново.

Visual Studio запустила настройку заново. Сравни новый вывод Visual Studio с тем, что Visual Studio писала, когда открывала папку до файла CMakePresets.json: наведи на строку — сцена покажет, что изменилось; щёлкни — откроется реплика про неё.

Как Visual Studio использует CMakePresets.json

Output
1> CMake generation started for configuration: 'vs2026-debug'.1> Environment settings:1>     INCLUDE=C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.51.36231\include;…;C:\Program Files (x86)\Windows Kits\10\include\10.0.26100.0\ucrt;…1>     LIB=C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.51.36231\lib\x64;…;C:\Program Files (x86)\Windows Kits\10\lib\10.0.26100.0\um\x641>     Path=C:\Program Files\Microsoft Visual Studio\18\Community\VC\Tools\MSVC\14.51.36231\bin\HostX64\x64;…1>     …1> Command line: "C:\WINDOWS\system32\cmd.exe" /c ""C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe"  -G "Visual Studio 18 2026" -A x64    "D:\dev\MyEngine" 2>&1"1> Working directory: D:/dev/MyEngine/out/build/vs20261> [CMake] -- Selecting Windows SDK version 10.0.26100.0 to target Windows 10.0.26300.1> [CMake] -- The CXX compiler identification is MSVC 19.51.36260.01> [CMake] -- Detecting CXX compiler ABI info1> [CMake] -- Detecting CXX compiler ABI info - done1> [CMake] -- Check for working CXX compiler: C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.51.36231/bin/Hostx64/x64/cl.exe - skipped1> [CMake] -- Detecting CXX compile features1> [CMake] -- Detecting CXX compile features - done1> [CMake] -- Configuring done (2.4s)1> [CMake] -- Generating done (0.1s)1> [CMake] -- Build files have been written to: D:/dev/MyEngine/out/build/vs20261> Extracted CMake variables.1> Extracted source files and headers.1> Extracted code model.1> Extracted toolchain configurations.1> Extracted includes paths.1> CMake generation finished.
Сверху — твой CMakePresets.json, в середине — Visual Studio, внизу — папка сборки. Теперь Visual Studio не придумывает настройки сама, а берёт их из файла пресетов. Поэтому вывод Visual Studio изменился в пяти местах: имя конфигурации, блок переменных среды, строка Command line, папка сборки и строка про Windows SDK.
configuration: ‘vs2026-debug’ — имя конфигурации. Без пресета на этом месте было x64-Debug: такую конфигурацию Visual Studio создавала сама. Теперь имя сложено из двух твоих пресетов: из пресета настройки vs2026 и пресета сборки debug.
Environment settings — новый длинный блок. В этом блоке переменные среды, которые Visual Studio передаёт CMake и компилятору. Здесь оставлены три важные: INCLUDE — папки, где компилятор ищет файлы для #include, среди них папка Windows SDK; LIB — папки, где линкер ищет библиотеки; Path — папки, где Windows ищет программы по имени; первая в списке — папка с cl.exe. У тебя этот блок будет длиннее и со своими путями.
В строке Command line теперь флаги -G “Visual Studio 18 2026” -A x64 — ровно то, что записано в пресете: генератор и процессор. Флага -G “Ninja” больше нет. Компиляторы Visual Studio тоже больше не передаёт, поэтому пропало предупреждение про CMAKE_C_COMPILER, которое было в выводе без пресета.
Working directory: D:/dev/MyEngine/out/build/vs2026 — папка сборки. Visual Studio взяла её из поля binaryDir пресета. Из того же поля взяла папку и консоль, когда ты запускал в консоли cmake --preset vs2026. Поэтому обе программы настраивают проект в одну папку, и сборка получается одна на двоих. До пресета было две: консоль настраивала в build, а Visual Studio — в out\build\x64-Debug.
Строка Selecting Windows SDK version вернулась. С генератором Ninja её не было: тогда Windows SDK выбирала сама Visual Studio. С генератором Visual Studio SDK снова выбирает CMake, который работает внутри Visual Studio. В консоли было так же: CMake, запущенный командой cmake --preset vs2026, тоже взял генератор из файла CMakePresets.json и сам выбрал SDK.
CMake generation finished — настройка закончена. Итог: консоль и Visual Studio взяли настройки из одного файла, одним генератором настроили проект в одну папку out\build\vs2026. Собирать теперь можно и в консоли командой cmake --build --preset debug, и кнопкой запуска в Visual Studio, а результат будет один и тот же.

В верхней полосе окна Visual Studio, в списке слева от зелёной кнопки запуска, вместо x64-Debug теперь написано Debug. Если раскрыть этот список, в нём будут два пункта, Debug и Release, — это displayName твоих пресетов сборки. Выбери Release, и следующая сборка запишет программу в out\build\vs2026\Release.

В соседнем списке, справа от зелёной кнопки, теперь написано app.exe (Debug\app.exe). В скобках — путь к программе внутри папки сборки: Visual Studio запустит app.exe из подпапки Debug, потому что выбрана конфигурация Debug.

Старые папки сборки

Если не получилось2
PowerShell пишет, что файл занят другим процессом.
Почему
Visual Studio держит открытыми файлы в папке out\build\x64-Debug, пока папка проекта открыта в Visual Studio, поэтому Windows не даёт их удалить.
Что сделать

Закрой Visual Studio и выполни команду ещё раз.

PowerShell пишет, что не может найти путь build или out\build\x64-Debug.
Почему
Пути в команде считаются от папки, в которой стоит консоль. Либо консоль стоит не в папке проекта, либо одна из папок уже удалена.
Что сделать

Перейди в папку проекта командой cd D:\dev\MyEngine и выполни команду ещё раз. Если PowerShell снова не находит только одну из папок, значит её уже нет, и удалять ничего не нужно.