mmote.ru/content/posts/fltk-msys2-cmake/index.md

261 lines
8.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: "FLTK - упрощаем себе жизнь с msys2"
date: 2023-01-03T16:55:31+03:00
draft: false
categories: ["cpp"]
featured_image: thumb.png
---
Обновление статейки по созданию [приложений на FLTK](/fltk-apps), так как нынче установка
библиотек и компилятора стала проще.
<!--more-->
Содержание:
{{< toc >}}
## Часть первая установка msys2
Начнём. Скачиваем установщик msys2 с [официального сайта](https://www.msys2.org):
![download](download.png)
Устанавливаем. Я оставил все параметры по-умолчанию:
![install-msys2](install-msys2.png)
Вводим команду для обновления всех пакетов:
```bash
pacman -Syu
```
Соглашаемся со всем. В конце msys2 попросит перезапустить себя:
![update-phase-1](update-phase-1.png)
Снова выполняем:
```bash
pacman -Syu
```
и обновляем оставшуюся часть пакетов:
![update-phase-2](update-phase-2.png)
Готово! msys2 и его компоненты теперь последней версии и готовы к работе.
## Часть вторая установка инструментария разработчика
Осталось установить компилятор, базовые инструменты для компиляции, cmake, fltk.
Мне кажется, если вы выбрали fltk, то вас интересует поддержка старых машин. Поэтому устанавливаем 32-битные версии компилятора и библиотек. Если вас интересует платформа x64, то вместо **i686** в названиях пакетов используйте **x86_64** (например, mingw-w64-**x86_64**-fltk).
Выполняем:
```bash
pacman -S base-devel mingw-w64-i686-gcc mingw-w64-i686-cmake mingw-w64-i686-fltk
```
![install-devtools](install-devtools.png)
## Часть третья - пишем и собираем приложения
### Пример приложения
В этот раз будет программа, считающая нажатия на кнопку:
```cpp
#include <cstdio>
#include <FL/Fl.H>
#include <Fl/Fl_Window.H>
#include <Fl/Fl_Box.H>
#include <Fl/Fl_Button.H>
class MainWindow : public Fl_Window {
public:
MainWindow(int w, int h, char const *title) : Fl_Window(w, h, title), m_counter(0) {
// Создаём кнопку
m_button = new Fl_Button(34, 34, 133, 56, "i++");
// Присваиваем обработчик кнопки, при этом пробрасываем текущее окно
m_button->callback(button_click, this);
// Создаём надпись-счётчик
m_label = new Fl_Box(34, 177, 133, 56);
// Выставляем размер шрифта
m_label->labelsize(50);
// Сразу обновляем текст счётчика
update_label();
// Заканчиваем добавлять виджеты
end();
}
protected:
void update_label() {
// Преобразуем число в строку
std::snprintf(m_label_text, sizeof(m_label_text), "%d", m_counter);
m_label->label(m_label_text);
}
static void button_click(Fl_Widget *w, void *data) {
// Получаем окно, которое передали обработчику
MainWindow *mw = static_cast<MainWindow *>(data);
// Увеличиваем счётчик
mw->m_counter++;
// Обновляем надпись
mw->update_label();
}
private:
Fl_Box *m_label;
Fl_Button *m_button;
char m_label_text[16];
int m_counter;
};
int main(void) {
// Задаём тему для виджетов (none, base, plastic, gtk+, gleam)
// Fl::scheme("gleam");
// Создаём окно
MainWindow *window = new MainWindow(200, 300, "i++");
// Показываем окно
window->show();
// Запускаем event loop
return Fl::run();
}
```
### Сборка напрямую
Для начала пробуем всё собрать напрямую компилятором, без систем сборки. Мой проект находится в D:/code. Поэтому нужно перейти в этот каталог.
```bash
cd /d/code
```
Пробуем собрать наше приложение. Меня в первую очередь интересовала статическая сборка, когда все зависимости интегрируются в один исполняемый файл.
```bash
g++ main.cpp -o main.exe -O2 -DWIN32 -static -lfltk -lole32 -luuid -lcomctl32 -mwindows
```
**-DWIN32** указываем FLTK, что мы под Windows.
**-mwindows** убираем чёрное окно команд у приложения и подключаем некоторые системные библиотеки.
**-static** статическая сборка.
**-lfltk -lole32 -luuid -lcomctl32** подключение необходимых библиотек.
Никакого вывода команда не выдаёт.
Проверяем, что наше приложение не требует никаких дополнительных библиотек.
```bash
ldd main.exe
```
Ничего кроме системных путей тут быть не должно:
![ldd](ldd.png)
После этого можно запускать приложение.
![app](app.gif)
### Сборка через CMake
#### Вариант 1 - внутри msys2
Для cmake хорошим тоном является создавать директорию сборки вне директории проекта. Поэтому немного изменим структуру нашего проекта:
```
D:\code
├───build
└───fltk-app
├───CmakeLists.txt
└───main.cpp
```
Создаём CmakeLists.txt, который также будет поддерживать статическую сборку:
```cmake
cmake_minimum_required(VERSION 3.2)
project(fltk-app)
option(STATIC_BUILD "Enable static build" ON)
# Конфигурируем статическую сборку для mingw
if(MINGW)
if(STATIC_BUILD)
set(BUILD_SHARED_LIBS OFF)
set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")
endif()
# Отключаем окно команд
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -mwindows")
endif()
# Ищем библиотеку fltk в системе
# При успешном поиске станут доступны переменные, описанные здесь:
# https://cmake.org/cmake/help/latest/module/FindFLTK.html
find_package(FLTK REQUIRED)
# Указываем исходные файлы проекта
add_executable(fltk-app main.cpp)
# Добавляем путь к заготовкам fltk для компиляции (в случаях, когда они находятся в произвольном месте)
target_include_directories(fltk-app PUBLIC ${FLTK_INCLUDE_DIRS})
# Подключаем библиотеки
target_link_libraries(fltk-app ${FLTK_BASE_LIBRARY})
# Также добавляем необходимые библиотеки при сборке на windows
if(WIN32)
target_link_libraries(fltk-app comctl32)
endif()
```
> Файл проекта пока что адаптирован только для windows.
Переходим в каталог сборки:
```bash
cd /d/code/build
```
Далее необходимо создать файлы для конкретной системы сборки. У нас это **MSYS Makefiles**:
```bash
cmake -G "MSYS Makefiles" /d/code/fltk-app
```
![cmake-msys-gen](cmake-msys-gen.png)
Затем собираем проект:
```bash
cmake --build .
```
![cmake-msys-build](cmake-msys-build.png)
Проверяем, не появилось ли зависимостей:
```bash
ldd /d/code/build/fltk-app.exe
```
![cmake-msys-ldd](cmake-msys-ldd.png)
#### Вариант 2 - вне msys2
Сборка через msys2 удобна тогда, когда у нас уже есть готовый проект.
Однако когда речь идёт о разработке, то мало какая IDE позволит себе роскошь запускать сборку в окружении msys2.
Чтобы избавиться от необходимости его использования, необходимо выполнить всего лишь...