Проект в Visual Studio
Откроешь проект в Visual Studio и соберёшь его там.
Окно Visual Studio
Отдельные файлы ты в Visual Studio уже писал. Теперь открой в Visual Studio весь проект.
Прежде чем писать код, выключи в Visual Studio серые подсказки. Пока ты печатаешь, справа от курсора может появляться бледный серый текст: это
Большую часть курса ты будешь проводить в этом окне. Окно знакомое, но проект, открытый как папка с CMakeLists.txt, устроен иначе, чем проект из мастера Visual Studio, а в знакомых панелях есть полезное, мимо чего обычно проходят. Пройди по частям окна.
Из чего состоит окно Visual Studio
cmake_minimum_required(VERSION 3.28)project(Engine LANGUAGES CXX)add_executable(app main.cpp)add_executable после main.cpp через пробел, получится add_executable(app main.cpp Window.cpp), и сохранить CMakeLists.txt. При сохранении Visual Studio сама запустит cmake -S . -B build: CMake читает CMakeLists.txt и записывает в папку build список дел для сборщика и другие файлы. Visual Studio выполняет эту команду сама, поэтому в окне OutputВывод бегут те же строки, что и в консоли.В обозревателе решений над деревом файлов стоит строка кнопок, и в ней есть кнопка с листом и фиолетовым значком, Switch Views. Эта кнопка переключает представление — то, в каком виде обозреватель показывает проект. Какое представление выбрано, написано в заголовке обозревателя после названия панели: сейчас это Folder View, дерево папки на диске.
Щелчок по кнопке Switch Views заменяет дерево списком представлений, а в заголовке обозревателя вместо имени представления появляется слово Views. В списке четыре строки:
- Open a solution, folder, or other item — заголовок списка, сама эта строка ничего не делает;
- Folder View выделено жирным, потому что это представление выбрано сейчас;
- CMake Targets View показывает проект так, как его видит CMake;
- Engine.slnx — файл решения, который CMake записал в папку build, когда ты
настраивал проект из консоли . Visual Studio нашла этот файл в папке и предлагает открыть проект через него. В этом курсе проект открыт как папка, поэтому строка Engine.slnx не нужна.Командой настройки, которая стояла в папке проекта:
PowerShell PS D:\dev\MyEngine> cmake -S . -B buildГенератор Visual Studio записал в папку build файл решения Engine.slnx и файлы проектов .vcxproj.
Двойной щелчок по строке CMake Targets View в списке представлений покажет вместо папки проект CMake. В этом дереве:
- Engine Project — сам проект, имя взято из
команды project в CMakeLists.txt;CMakeLists.txtкоммит 3f85b6a cmake_minimum_required(VERSION 3.28)project(Engine LANGUAGES CXX)add_executable(app main.cpp) - app (executable) —
цель appиз командыadd_executable, а слово executable значит, что из этой цели получится программа .exe. Внутри узла цели лежат файлы, которые CMake отдаёт целиapp. Так видно, попадёт ли файл в программу: файла, который ты создал, но не дописал вadd_executable, в узле app (executable) не будет; - CMakeLists.txt лежит в узле проекта, а не в узле цели: этот файл описывает весь проект;
- Pinned Targets — закреплённые цели. Когда целей в движке станет много, нужные можно закрепить здесь, чтобы не искать нужную цель в дереве.
Чтобы вернуться к папке на диске, снова нажми Switch Views и дважды щёлкни по строке Folder View.
Остальные кнопки в строке кнопок обозревателя решений нужны реже, а три из них пригодятся каждый день:
- кнопка со стрелками в обе стороны, Sync with Active DocumentСинхронизировать с активным документом, Ctrl+[, затем S, раскрывает дерево до файла, открытого в редакторе, и выделяет этот файл. Когда в движке появятся десятки файлов в разных папках, так проще всего узнать, где лежит файл, который ты сейчас правишь;
- кнопка с двумя уголками вверх, Collapse AllСвернуть все, сворачивает все раскрытые папки дерева одним щелчком;
- поле поиска под кнопками, Ctrl+;, оставляет в дереве только файлы, в имени которых есть набранные буквы: набери
main, и в дереве останется main.cpp.
std::cout написано std::cot. Ошибку редактор отмечает красной волнистой линией, а предупреждение — зелёной. Сделай такую же опечатку у себя и наведи указатель мыши на линию: всплывёт текст ошибки. Полоска внизу редактора показывает, сколько таких мест в открытом файле, и строку, на которой стоит курсор. Потом верни std::cout.Пока ты печатаешь имя, список подсказок предлагает варианты, которые есть в подключённых файлах. Здесь набрано std::co, и список показал имена из std, которые начинаются с этих букв. Поэтому если нужного имени в списке нет, чаще всего не хватает строки #include с нужным файлом. Если список закрылся, Ctrl+Space открывает его снова.
Подсказки работают и после того, как имя набрано. Наведи указатель мыши на cout, и всплывёт его описание. Когда откроешь скобку после имени функции, появится подсказка с её параметрами. Клавиша F12 на слове откроет файл, где это имя объявлено: так видно, откуда взялось чужое имя. А Alt+F12 покажет то же в маленьком окне над кодом, не уводя тебя из твоего файла.
Сборкой управляют четыре элемента верхней полосы:
- список x64-Debug выбирает
конфигурацию , и у каждой конфигурации своя папка сборки;Набор настроек сборки под одним именем: для какого процессора собирать, какой вариант (Debug или Release), в какую папку. - список app.exe выбирает, что запускать. Visual Studio заполняет его
целями из CMakeLists.txt, поэтому надпись Select Startup ItemВыбрать элемент запуска вместо имени значит, что настройка CMake ещё идёт или закончилась ошибкой; - закрашенный треугольник, он же F5, собирает программу и запускает её под
отладчиком ;Программа, которая запускает твою программу и может остановить её на любой строке, чтобы ты посмотрел, что происходит внутри. - контурный треугольник, он же Ctrl+F5, собирает и запускает без отладчика.
Пока программа стоит, верхняя полоса меняется: вместо кнопок запуска там появляется панель отладки. Слева направо на ней такие кнопки:
- две полоски, Break AllПрервать все, останавливают работающую программу на той строке, где она сейчас; пока программа уже стоит, как сейчас, кнопка серая;
- красный квадрат, Stop DebuggingОстановить отладку, Shift+F5, завершает программу совсем;
- круговая стрелка, RestartПерезапустить, Ctrl+Shift+F5, останавливает программу и запускает заново;
- стрелка вправо, Show Next StatementПоказать следующий оператор, возвращает редактор к жёлтой стрелке, если ты ушёл смотреть другой файл;
- синяя стрелка дугой над точкой, Step OverШаг с обходом, F10, выполняет строку, на которой стоит жёлтая стрелка, и переходит к следующей. Строка 5 печатает приветствие, поэтому после этого шага в консоли появится
Hello, Engine!.
std::cot осталась и ты запустил сборку. Причины сбоя собраны на вкладке Error ListСписок ошибок: код ошибки, описание, файл и номер строки. Читай сверху и исправляй первую ошибку от компилятора: следующие часто оказываются её следствием. Здесь C2039 сообщает, что в std нет имени cot, а C2065 говорит о том же слове ещё раз, поэтому исправление опечатки уберёт обе ошибки. Двойной щелчок по строке таблицы откроет файл на нужной строке, а щелчок по коду ошибки откроет её описание на сайте Microsoft.На вкладке OutputВывод одно окно хранит несколько журналов, а показывает один: его выбирает список Show output fromПоказать выходные данные из. Для нашей работы нужны два журнала:
- журнал CMake хранит вывод
настройки ;Первый шаг. Visual Studio делает этот шаг сама, когда открывает папку и когда ты сохраняешь CMakeLists.txt: CMake читает этот файл и записывает в папку out\build\ список дел для сборщика. Последняя строка этого журнала —x64-Debug CMake generation finished.. - журнал Build хранит вывод
сборки .Второй шаг, по зелёному треугольнику или Ctrl+Shift+B. Сборщик Ninja запускает компилятор cl.exe для каждого файла .cpp, а затем линкер link.exe. Каждая из этих программ пишет свои сообщения в журнал Build, поэтому там вперемешку строки сборщика, компилятора и линкера, а также любых других программ, которые сборщик запускает по ходу дела. Ошибки компилятора начинаются с C, ошибки линкера — с LNK.
Если в окне OutputВывод нет нужных строк, сначала проверь список Show output fromПоказать выходные данные из: возможно, открыт не тот журнал. Сюда стоит заглянуть за тем, чего нет в таблице ошибок: строки с note уточняют ошибку, например показывают, где объявлено std. Двойной щелчок по строке с error здесь тоже открывает файл на нужной строке.
Меню Build и Project нужны, когда сборка ведёт себя странно. Меню BuildСборка отвечает за сборку:
- Build AllСобрать все, Ctrl+Shift+B, собирает весь проект, но компилирует только изменившиеся файлы;
- Rebuild AllПерестроить все компилирует всё заново, а Clean AllОчистить все только удаляет результаты прошлой сборки, ничего не собирая;
- Build app.exeСобрать app.exe, Ctrl+B, собирает одну цель
app, а CompileКомпилировать компилирует только открытый файл и линкер не запускает;
Меню ProjectПроект отвечает за настройку CMake:
- Configure CacheНастроить кэш запускает
настройку заново;Первый шаг сборки: CMake читает CMakeLists.txt и записывает список дел для сборщика. Visual Studio делает этот шаг сама. - Delete Cache and ReconfigureУдалить кэш и выполнить перенастройку удаляет
кэш CMake и настраивает с нуля.Файл CMakeCache.txt в папке сборки. В этот файл CMake записывает то, что нашёл при настройке, например путь к компилятору, и при следующей настройке берёт значения оттуда.
Панели Visual Studio можно расставить по-своему: перетащить мышью к другому краю окна, сложить вкладками в одну панель или вынести в отдельное окно, например на второй монитор. Так можно дать списку ошибок и выводу больше места или держать обозреватель решений справа, ближе к редактору. Сцена ниже показывает все три способа на примере обозревателя решений.
Как перетащить и закрепить панель в Visual Studio
Настройка в Visual Studio
В консоли ты собрал проект Первая настраивает проект, вторая собирает программу. Обе выполнялись в консоли, которая стоит в папке проекта:PS D:\dev\MyEngine> cmake -S . -B buildPS D:\dev\MyEngine> cmake --build build
Что делает Visual Studio, когда открывает CMake-проект
1> CMake generation started for default configuration: 'x64-Debug'.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 "Ninja" -DCMAKE_BUILD_TYPE:STRING="Debug" -DCMAKE_INSTALL_PREFIX:PATH="D:\dev\MyEngine\out\install\x64-Debug" -DCMAKE_C_COMPILER:FILEPATH="C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.51.36231/bin/Hostx64/x64/cl.exe" -DCMAKE_CXX_COMPILER:FILEPATH="C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/MSVC/14.51.36231/bin/Hostx64/x64/cl.exe" -DCMAKE_MAKE_PROGRAM="C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\CommonExtensions\Microsoft\CMake\Ninja\ninja.exe" "D:\dev\MyEngine" 2>&1"1> Working directory: D:\dev\MyEngine\out\build\x64-Debug1> [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.6s)1> [CMake] -- Generating done (0.0s)1> [CMake] CMake Warning:1> [CMake] Manually-specified variables were not used by the project:1> [CMake]1> [CMake] CMAKE_C_COMPILER1> [CMake]1> [CMake]1> [CMake] -- Build files have been written to: D:/dev/MyEngine/out/build/x64-Debug1> 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.cmake -S . -B build. Строки с [CMake] пишет CMake, остальные — Visual Studio.x64-Debug сама, если ты не задал свою.x64-Debug состоит из двух частей: x64 означает программу для 64-битной Windows, Debug — вариант с проверками и отладочными сведениями, удобный для поиска ошибок. Так как других конфигураций у тебя нет, настройка выполняется только для этой. Это же имя стоит в Command line — команда, которую Visual Studio выполнила за тебя. Запускает Visual Studio свой cmake.exe, а не тот, что ты ставил отдельно: он приходит вместе с -G “Ninja” — другой
Почему же Visual Studio берёт Ninja, а не MSBuild, которым ты собирал проект в консоли? Сам по себе MSBuild для Visual Studio родной: когда в ней создают обычный проект C++ без CMake, она записывает файлы .slnx и .vcxproj и собирает проект именно MSBuild. Но здесь открыта папка с CMakeLists.txt, и Ninja подходит ей лучше по двум причинам:
- Ninja проще. MSBuild работает с файлами в формате Visual Studio: описанием всего проекта в
файле решения .slnx и описанием каждойФайл с расширением .slnx. Решение в Visual Studio — это набор проектов, которые открываются и собираются вместе. В файле записано, какие проекты в него входят.цели в файле app.vcxproj. Когда Visual Studio открывает просто папку, этих файлов в ней нет, и пришлось бы создавать их. Ninja обходится одним небольшим файлом build.ninja, в котором только список команд. Ninja сразу запускает эти команды, поэтому после правки одного файла проект пересобирается быстрее.То, что собирается из файлов проекта: у нас это программа app.exe. Цель создаёт командаadd_executableв CMakeLists.txt; для каждой цели CMake записывает свой файл .vcxproj. - Ninja есть на Linux и macOS. Один и тот же проект собирается там точно так же, как в Windows, поэтому для папки с CMakeLists.txt Visual Studio выбирает Ninja по умолчанию.
LANGUAGES CXXcmake_minimum_required(VERSION 3.28)project(Engine LANGUAGES CXX)add_executable(app main.cpp)Extracted… — после настройки Visual Studio спрашивает у CMake, что он узнал о проекте, и запоминает ответы. Вот что Visual Studio спросила у CMake:
- CMake variables — настройки CMake, например выбранный компилятор;
- source files and headers — файлы проекта: у нас main.cpp;
- code model —
модель кода . У нас однаОписание проекта, которое CMake передаёт Visual Studio: какие в нём цели и из каких файлов каждая собирается.цель ,app , поэтому вCMakeLists.txtкоммит 3f85b6a cmake_minimum_required(VERSION 3.28)project(Engine LANGUAGES CXX)add_executable(app main.cpp)списке запуска появился app.exe; - toolchain configurations — компилятор и его настройки;
- includes paths — папки с файлами для
#include : по ним Visual Studiomain.cppкоммит 157d8bd #include <iostream>int main(){ std::cout << "Hello, Engine!\n"; return 0;}автодополняет код.Когда ты печатаешь начало имени, Visual Studio сама предлагает варианты, напримерstd::cout, из подключённых файлов. Остаётся выбрать нужный.
Сборка и запуск
>------ Build started: Project: CMakeLists, Configuration: Debug ------[1/2] Building CXX object CMakeFiles\app.dir\main.cpp.obj[2/2] Linking CXX executable app.exeЭто вывод Ninja. Вывод Ninja короче, чем вывод MSBuild: один шаг сборки — одна строка. В начале строки в квадратных скобках два числа: [1/2] значит «шаг 1 из 2», [2/2] — «шаг 2 из 2». Здесь шагов два: сначала компиляция, потом линковка.
[1/2] Building CXX object— первый шаг: Ninja запустилcl.exe , и из main.cpp получилсяобъектный файл main.cpp.obj. Это тот же main.obj, что при сборке в консоли, только Ninja оставляет в имени.cpp.[2/2] Linking CXX executable— второй шаг:link.exe соединил main.cpp.obj состандартной библиотекой и записал готовую программу в файл app.exe.
Hello, Engine! D:\dev\MyEngine\out\build\x64-Debug\app.exe (process 27816) exited with code 0 (0x0).Press any key to close this window . . .Программа напечатала свою строку и завершилась. Остальное дописала Visual Studio:
- путь D:\
dev\ — это другой app.exe: он из папки out, которую создала Visual Studio, а не из build\MyEngine\ out\ build\ x64-Debug\ app.exe Debug , которую создала консоль; exited with code 0— тот жекод возврата , что ты видел через$LASTEXITCODE;- окно ждёт нажатия клавиши, чтобы ты успел прочитать вывод.