05. Первое приложение
Чтобы начать работать с теорией, вам нужно создать выполнить эту инструкцию.
В итоге у вас должен быть создан такой репозиторий:
В нём должно быть три коммита:
Initial commit
- содержит три файла:.gitignore
,CMakeLists.txt
иmain.cpp
. Причём при загрузке он должен корректно собираться в бинарникgitignore changed
- в файле.gitignore
добавить строчку/.idea/
readme added
- добавьтеreadme.md
файл
## Тестовый репозиторий
Он создан для проверки работы `.gitignore`.
А сам проект в clion
должен выглядеть так:
Все задания можно выполнять в удобной вам среде разработки. Хотя я советую Clion
.
Для альтернативных сред будут даваться консольные команды. Если вы работаете
в Clion
, просто игнорируйте их.
CMake
Чтобы собирать сложные приложения на C++, которые используют сторонние библиотеки,
используется специальная консольная программа cmake
.
Инструкции для неё пишутся в файле CMakeLists.txt
Первая строка указывает, какая минимальная версия cmake
может собирать проект по инструкциям в этом
файле
cmake_minimum_required(VERSION 3.21)
Вторая строка указывает название проекта
project(test_cmake)
Следующая строка указывает версию стандарта(языка) cmake
set(CMAKE_CXX_STANDARD 14)
Последняя добавляет сборку бинарника
add_executable(test_cmake main.cpp)
где test_cmake
- название бинарника, main.cpp
- исходники
Если в проекте набирается много файлов, то считается хорошим тоном разделять их по модулям. Тогда вместо компиляции всего проекта, можно собирать только изменившийся модуль.
К тому же, модули могут вообще собираться из удалённых репозиториев. Об этом будет рассказано ниже.
Пока что мы создадим только один модуль с нашим исходником, который просто выводит на
экран Hello, World!
.
Для этого создайте папку src
, переместите (можно перетащить) в него файл main.cpp
и
создайте в этой папке файл CMakeList.txt
. Для каждого модуля нужно указывать свой
список команд сборки.
Теперь нам нужно поменять главный CMakeList.txt
так, чтобы он просто подключал модуль src
:
- CMakeList.txt
cmake_minimum_required(VERSION 3.21)
project(test_cmake)
set(CMAKE_CXX_STANDARD 14)
add_subdirectory(src)
В созданном нами новом CMakeList.txt
нужно написать всего одну строчку
- src/CMakeList.txt
add_executable(example main.cpp)
Теперь снова откройте главный файл CMakeList.txt
. Clion
предложит автоматически
обрабатывать его изменения. Вам нужно это разрешить. Для этого кликните Enable Auto-Reload
.
После того, как clion
обработает изменения, название приложения должно поменяться на example
:
Запустите приложение. У вас снова должна вывестись фраза Hello, World!
:
Теперь вам нужно создать новый коммит и отправить его на сервер.
Для этого нажмите Ctrl+K
, введите название коммита main.cpp moved to module
и нажмите Commit and Push...
В следующем окне нажмите Push
.
Теперь ваш репозиторий должен будет выглядеть так:
Если перейти в папку src
, то её содержимое будет таким:
Сборка в консоли*
Если вы используете clion, то можете пропустить этот раздел и переходить к следующему.
Чтобы собрать проект с помощью cmake
через консоль, вам нужно создать папку для сборки,
обычно её называют build
.
Перейдите в папку build
и, зажав Shift
клинките правой кнопкой мыши по
свободной области внутри открытой папки и в контекстном меню выберите Открыть окно PowerShell здесь
Выполните команду:
cmake ../
Она подготавливает в текущей папке файлы для сборки, который находится по указанному пути. В нашем случае - это
путь ../
Дождитесь, пока закончится подготовка файлов закончится
Теперь нужно запустить непосредственную сборку
cmake --build .
Теперь можно запустить собранную нами программу
.\src\Debug\example.exe
Бинарник собирается в папке src\Debug\example.exe
Зависимости
Для подключения внешних зависимостей мы будем использовать FetchContent
. Этот способ может загружать
исходники из репозиториев. Другой способ - это подмодули git
. Подробнее о них можно почитать
здесь.
Чтобы добавить зависимость, создадим ещё одну папку dependencies
,
а в ней создадим файл CMakeList.txt
:
Первой зависимость, которую мы так подключим, будет sfml
.
Для этого сам файл нужно заполнить следующими строками:
- dependencies/CMakeList.txt
include(FetchContent)
# SFML
FetchContent_Declare(
sfml
URL https://github.com/SFML/SFML/archive/refs/tags/2.5.1.zip
URL_MD5 2c4438b3e5b2d81a6e626ecf72bf75be
)
add_subdirectory(sfml)
В этом файле мы будем указывать все зависимости. Первая команда
include(FetchContent)
выполняет импорт FetchContent
.
Вторая команда иммет несколько аругментов:
# SFML
FetchContent_Declare(
sfml
URL https://github.com/SFML/SFML/archive/refs/tags/2.5.1.zip
URL_MD5 2c4438b3e5b2d81a6e626ecf72bf75be
)
Первый аргумент - это название модуля, второй аргумент - путь к исходнику, третий - контрольная сумма.
Последняя команда добавляет модуль sfml
, который мы пока что не прописали.
Чтобы это сделать, создаёте папку sfml
в папке dependencies
, а внутри папки sfml
создайте
новый CMakeList.txt
файл.
Сам файл заполните следующими строками:
- dependencies/sfml/CMakeList.txt
message(STATUS "Fetching SFML...")
# No need to build audio and network modules
set(SFML_BUILD_AUDIO FALSE)
set(SFML_BUILD_NETWORK FALSE)
FetchContent_MakeAvailable(sfml)
Первая команда выводит сообщение в лог сборки уровня STATUS
строку, которая указана в
кавычках. В нашем случае - это Fetching SFML...
message(STATUS "Fetching SFML...")
Вторая и третья команда - это просто флаги, говорящие CMake
, что не нужно собирать аудио
и сетевые модули
# No need to build audio and network modules
set(SFML_BUILD_AUDIO FALSE)
set(SFML_BUILD_NETWORK FALSE)
Последняя команда - это просто связывание удалённого репозитория с нашим CMake
проектом
FetchContent_MakeAvailable(sfml)
Т.к. мы собираем библиотеку, то нам нужно связать её заголовочные файлы с объектными.
Для этого используется команда
target_link_libraries(example PRIVATE sfml-graphics)
Также нужно прописать для Windows
автоматическое копирование собранных DLL
библиотек
в папку с бинарником. В этой команде просто перечисляется, что и куда скопировать после сборки
бинарника example
# Copy DLLs needed for runtime on Windows
if(WIN32)
if (BUILD_SHARED_LIBS)
add_custom_command(TARGET example POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:sfml-graphics>
$<TARGET_FILE:sfml-window>
$<TARGET_FILE:sfml-system>
$<TARGET_FILE_DIR:example>)
endif()
endif()
Если эту команду не дописать, то на Windows
мы получим такую ошибку:
Весь файл src/CMakeList.txt
теперь будет таким:
- src/CMakeList.txt
add_executable(example main.cpp)
target_link_libraries(example PRIVATE sfml-graphics)
# Copy DLLs needed for runtime on Windows
if(WIN32)
if (BUILD_SHARED_LIBS)
add_custom_command(TARGET example POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:sfml-graphics>
$<TARGET_FILE:sfml-window>
$<TARGET_FILE:sfml-system>
$<TARGET_FILE_DIR:example>)
endif()
endif()
В главном файле CMakeList.txt
нужно добавить строчку
add_subdirectory(dependencies)
Весь файл будет теперь таким:
- CMakeList.txt
cmake_minimum_required(VERSION 3.21)
project(test_cmake)
set(CMAKE_CXX_STANDARD 14)
add_subdirectory(dependencies)
add_subdirectory(src)
Сначала должно идти подключение папкиdependencies
и только потом - src
.
В противном случае приложение у вас запустится с ошибкой.
Если после сохранения главного файла у вас не началась автоматическая пересборка, то
вам нужно вручную пересобрать проект. Для этого в верхнем меню выберите Build
->Rebuild Project
.
Начнётся сборка
Когда сборка закончится, Clion
выдаст сообщение Build finished
Теперь запустите снова ваше приложение, чтобы удостовериться в корректности настроек
Программа снова должна вывести Hello, World!
Замените теперь код main.cpp
:
- src/main.cpp
#include <SFML/Graphics.hpp>
int main() {
sf::RenderWindow window(sf::VideoMode(200, 200), "SFML works!");
sf::CircleShape shape(100.f);
shape.setFillColor(sf::Color::Green);
while (window.isOpen()) {
sf::Event event;
while (window.pollEvent(event)) {
if (event.type == sf::Event::Closed)
window.close();
}
window.clear();
window.draw(shape);
window.display();
}
return 0;
}
Запустите приложение, оно должно нарисовать зелёный круг:
Если программа всё ещё выводит Hello, World
, значит, вам нужно пересобрать проект Build
->Rebuild project
.
После успешного запуска кода sfml
вам нужно создать новый коммит sfml connected
и отправить
его на сервер.
Теперь репозиторий будет выглядеть примерно так:
Dear ImGui
Эта библиотека упрощает создание графических интерфейсов, правда, для использования в ней sfml
нужно подключить вспомогательную библиотеку imgui-sfml
.
Чтобы её подключить, нужно переписать dependencies/CMakeLists.txt
:
- dependencies/CMakeList.txt
include(FetchContent)
# SFML
FetchContent_Declare(
sfml
URL https://github.com/SFML/SFML/archive/refs/tags/2.5.1.zip
URL_MD5 2c4438b3e5b2d81a6e626ecf72bf75be
)
add_subdirectory(sfml)
# Dear ImGui
FetchContent_Declare(
imgui
GIT_REPOSITORY https://github.com/ocornut/imgui
GIT_TAG 35b1148efb839381b84de9290d9caf0b66ad7d03 # 1.82
)
FetchContent_MakeAvailable(imgui)
# ImGui-SFML
FetchContent_Declare(
imgui-sfml
GIT_REPOSITORY https://github.com/eliasdaler/imgui-sfml
GIT_TAG 82dc2033e51b8323857c3ae1cf1f458b3a933c35 # 2.3
)
add_subdirectory(imgui-sfml)
Также нужно создать папку imgui-sfml
, а в ней файл CMakeLists.txt
Его заполните следующими строками:
- dependency/imgui-sfml/CMakeLists.txt
message(STATUS "Fetching ImGui-SFML...")
set(IMGUI_DIR ${imgui_SOURCE_DIR})
set(IMGUI_SFML_FIND_SFML OFF)
set(IMGUI_SFML_IMGUI_DEMO ON)
FetchContent_MakeAvailable(imgui-sfml)
Также нужно добавить копирование DLL
- dependency/imgui-sfml/CMakeLists.txt
add_executable(example main.cpp)
target_link_libraries(example PRIVATE ImGui-SFML::ImGui-SFML)
# Copy DLLs needed for runtime on Windows
if(WIN32)
if (BUILD_SHARED_LIBS)
add_custom_command(TARGET example POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
$<TARGET_FILE:ImGui-SFML::ImGui-SFML>
$<TARGET_FILE:sfml-graphics>
$<TARGET_FILE:sfml-window>
$<TARGET_FILE:sfml-system>
$<TARGET_FILE_DIR:example>)
endif()
endif()
Замените теперь код main.cpp
:
- src/main.cpp
#include <SFML/Graphics/RenderWindow.hpp>
#include <SFML/System/Clock.hpp>
#include <SFML/Window/Event.hpp>
#include <imgui-SFML.h>
#include <imgui.h>
// главный метод
int main() {
// создаём окно для рисования
sf::RenderWindow window(sf::VideoMode(1280, 720), "ImGui + SFML = <3");
// задаём частоту перерисовки окна
window.setFramerateLimit(60);
// инициализация imgui+sfml
ImGui::SFML::Init(window);
// переменная таймера
sf::Clock deltaClock;
// пока окно открыто, запускаем бесконечный цикл
while (window.isOpen()) {
// создаём событие sfml
sf::Event event;
// пока окно принимает события
while (window.pollEvent(event)) {
// отправляем события на обработку sfml
ImGui::SFML::ProcessEvent(event);
// если событие - это закрытие окна
if (event.type == sf::Event::Closed) {
// закрываем окно
window.close();
}
}
// запускаем обновление окна по таймеру с заданной частотой
ImGui::SFML::Update(window, deltaClock.restart());
// рисуем демонстрационное окно
ImGui::ShowDemoWindow();
// очищаем окно
window.clear();
// рисуем по окну средствами imgui+sfml
ImGui::SFML::Render(window);
// отображаем изменения на окне
window.display();
}
// завершаем работу imgui+sfml
ImGui::SFML::Shutdown();
return 0;
}
Перезапустите сборку проекта и запустите программу example
. У вас должно запуститься
демонстрационное окно ImGui
Создайте новый коммит с названием imgui connected
и отправьте его на сервер.
Теперь ваш репозиторий будет выглядеть примерно так
Теперь поменяйте readme
, как показано в образце, создайте новый коммит readme changed
и отправьте на сервер.
- readme.md
## Шаблон проекта SFML+ImGui
Этот репозиторий - прототип программ для создания графических приложений средствами `SFML` и
`ImGui`.
Теперь ваш репозиторий должен будет выглядеть примерно так:
Задание
Это задание выдаётся только на урок, оно оценивается по последнему коммиту,
сделанному во время урока. Если вы выполнили все блоки теории в этой главе, то вам останется
только опубликовать ваш локальный репозиторий на сервере github
.
Вам необходимо создать свой репозиторий, в котором добавлены следующие коммиты (для каждого сначала указывается название, потом требования):
В нём должно быть три коммита:
Initial commit
- содержит три файла:.gitignore
,CMakeLists.txt
иmain.cpp
. Причём при загрузке он должен корректно собираться в бинарникgitignore changed
- в файле.gitignore
добавить строчку/.idea/
readme added
- добавьтеreadme.md
файл
## Тестовый репозиторий
Он создан для проверки работы `.gitignore`.
main.cpp moved to module
- переделайте проект под сборку модуляsrc
(одинCMakeLists.txt
для всего проекта, один - для модуляsrc
)sfml connected
- создайте папку зависимостейdependencies
, а внутри неё модульsfml
, который собирает библиотеку изgit
-репозитория, перепишите файлmain.cpp
, а такжеCMakeLists.txt
так, чтобы средствамиsfml
в окне рисовался зелёный круг.imgui connected
- подключите библиотекуimgui
таким же образом, как иsfml
, перепишитеmain.cpp
так, чтобы рисовалось демонстрационное окноImGui
.
Ссылку на github-репозиторий необходимо отправить в поле ввода задания на сайте mdl.