Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision |
msys2_mingw [2020/04/25 22:53] – [Введение] admin | msys2_mingw [2024/03/14 12:34] – [OpenGL через SD2L] admin |
---|
<html><h1>Установка и использование MSYS2 и Mingw-w64 под Windows</h1></html> | <html><h1>Установка и использование MSYS2 и Mingw-w64 под Windows</h1></html> |
Текст был первоналаьно сделан для сайта "[[https://www.phantom.sannata.org/viewtopic.php?p=500339#p500339|Железные призраки прошлого]]", но затем невозбранно перенесен на эту Wiki и теперь живет тут. | Текст был первоначально написан для сайта "[[https://www.phantom.sannata.org/viewtopic.php?p=500339#p500339|Железные призраки прошлого]]", но затем невозбранно перенесен на эту Wiki и теперь живет тут. |
| |
==== Введение ==== | ==== Введение ==== |
| |
Иногда возникает желание "что-нибудь скомпилировать под Windows". Ага, ага. Вот и у меня однажды возникала | В целях ретрокомпьютинга иногда возникает необходимость "что-нибудь скомпилировать под 32-битный Windows" с минимальными затратами. Ага, ага. Вот и у меня однажды возникала |
такая же ситуация. Когда-то давно мне довелось пользоваться компилятором **[[https://ru.wikipedia.org/wiki/MinGW|Mingw]]** и оболочкой **MSYS**, так что я попробовал их найти и установить. Оказалось, что там "всё не так, как раньше". | такая же ситуация. Когда-то давно я пользовался компилятором **[[https://ru.wikipedia.org/wiki/MinGW|Mingw]]** и оболочкой **MSYS**, так что я попробовал снова их найти и установить. Оказалось, что там "всё не так, как раньше". Вобщем, сейчас ситуация такая: "простой" MinGW и "классический" MSYS обновляться перестали и они зачахли где-то в районе 2015 года. |
Вобщем, сейчас ситуация такая: "простой" MinGW и "классический" MSYS обновляться перестали | |
и они зачахли где-то в районе 2015. | |
| |
**ПРИМЕЧАНИЕ:** Надеюсь, читатели понимают разницу между **[[https://ru.wikipedia.org/wiki/Cygwin|Cygwin]]** и **[[https://ru.wikipedia.org/wiki/MinGW|Mingw]]**. Кратко: **Cygwin** пытается воссоздать наиболее полную "среду" UNIX/POSIX на Windows, со всеми её фишками, типа //fork()//, особенностей файловой системы, сигналами, псевдотерминалами и т.д. в то время как **Mingw** - это (изначально) просто перенос компилятора **GCC** на Windows, без вот этого всего. А **MSYS** - это набор утилит для сборки, главные из которых - пожалуй ''make'' и ''bash''. [[https://github.com/msys2/msys2/wiki/How-does-MSYS2-differ-from-Cygwin|Подробности]]. | Дак вот, оказывается, нынче текущая версия **MSYS** - это **[[https://www.msys2.org/|MSYS2]]**. Это такой странный гибрид |
| из **Cygwin** и старого **MSYS**. Что там нового ? Подобно **Cygwin** он делает замену путей в стиле UNIX, маскирует расширение *.exe, |
Текущая версия **MSYS** - это **[[https://www.msys2.org/|MSYS2]]**. Это такой странный гибрид | поддерживает псевдотерминалы, UNIX-сигналы и еще много чего. Это, с одной стороны, облегчает процесс сборки |
из **Cygwin** и старого **MSYS**. | всяких нетривиальных UNIX программ, а с другой стороны, теперь все MSYS2-программы, в отличии от старого **MSYS** тянут за собой |
Подобно *Cygwin** он делает замену путей в стиле UNIX, маскирует расширение *.exe, | |
поддерживает псевдотерминалы, UNIX-сигналы и еще много чего. Это, с одной стороны, облегчает перенос и build-инг | |
всяких нетривиальных UNIX программ, с другой стороны, все msys-программы теперь тянут за собой | |
DLL-ку: ''msys-2.0.dll'' . | DLL-ку: ''msys-2.0.dll'' . |
| |
Компилятор с тулзами теперь называется **[[http://mingw-w64.org/|Mingw-w64]]**. Это вовсе не значит, что он 64-битный, | А компилятор с тулзами нынче называется **[[http://mingw-w64.org/|Mingw-w64]]**. Это вовсе не значит, что он 64-битный, |
это просто __такое имя__. Он существует во всех возможных комбинациях: 32-битный (т.е. работающий на 32-бит винде) | это просто __такое имя__. Он существует во всех возможных комбинациях: 32-битный (т.е. работающий на 32-бит Windows) |
для билда 32-битных программ, 64-битный для билдинга 64-битных программ, и все промежуточные | для билда 32-битных программ, 64-битный для билдинга 64-битных программ, и все промежуточные |
варианты, то есть 32-битный для построения 64-битных и наоборот, 64-битный для 32-бит. | варианты, то есть 32-битный для построения 64-битных и наоборот, 64-битный для 32-бит. |
Вы еще не запутались ? Держитесь, это только начало... :) | Вы еще не запутались ? Держитесь, это только начало... :) |
| |
**MSYS2** теперь поддерживает два вида терминалов (т.е. тула для отрисовки) - один новомодный **[[https://en.wikipedia.org/wiki/Mintty|Mintty]]**, | **MSYS2** теперь поддерживает несколько видов терминалов (т.е. программ для отрисовки "текстового" экрана) - один новомодный **[[https://en.wikipedia.org/wiki/Mintty|Mintty]]**, |
утащенный с того же **Cygwin**, который типа лучше поддерживает механизмы терминала UNIX, но опять | утащенный с того же **Cygwin**, который типа лучше поддерживает механизмы терминала UNIX, но опять |
же, тянет за собой всякое... Другой - почти классическая Windows консоль почти без обвеса (**[[https://ru.wikipedia.org/wiki/ConEmu|ConEmu]]**) | же, тянет за собой всякое... Другой - почти классическая Windows-консоль почти без обвеса (**[[https://ru.wikipedia.org/wiki/ConEmu|ConEmu]]**) |
но зато с закладками (Tabs). На самом деле, есть еще третий вид терминала (defterm), но он не совсем поддерживается... | но зато с закладками (Tabs). На самом деле, есть еще третий вид терминала (defterm), но он не совсем поддерживается... |
[[https://github.com/msys2/msys2/wiki/Terminals|Подробности]]. | [[https://www.msys2.org/wiki/Terminals/|Подробности]]. |
Чтобы запустить **MSYS2** c нужным терминалом, надо стартовый ''msys2_shell.cmd'' запустить с нужным | Чтобы запустить **MSYS2** c нужным терминалом, надо стартовый ''msys2_shell.cmd'' запустить с нужным |
ключиком. По-умолчанию запускается **Mintty**. | ключиком. По-умолчанию запускается **Mintty**. |
| |
Да, сама **MSYS2** тоже бывает 32-битная и 64-битная. К счастью на сайте **MSYS2** есть нужный инсталлятор, | **ПРИМЕЧАНИЕ:** Надеюсь, читатели понимают разницу между **[[https://ru.wikipedia.org/wiki/Cygwin|Cygwin]]** и **[[https://ru.wikipedia.org/wiki/MinGW|Mingw]]**. Кратко: **Cygwin** пытается воссоздать наиболее полную "среду" UNIX/POSIX на Windows, со всеми её фишками, типа //fork()//, особенностями файловой системы, сигналами, псевдотерминалами и т.д. в то время как **Mingw** - это (изначально) просто перенос компилятора **GCC** на Windows, без вот этого всего. А **MSYS** - это "оболочка", то есть набор утилит __для сборки__, главные из которых - пожалуй ''make'' и ''bash''. [[https://www.msys2.org/wiki/How-does-MSYS2-differ-from-Cygwin/|Подробности]]. Надо добавить, что вся эта магия имеется только в среде **MSYS2**, а полученная программа билдится с MSVCRT.DLL и большинство этих фишек не поддерживает. |
(''msys2-i686'' или ''msys2-x86_64'') - огромный файл, у которого внутри целый архив соответствующих программ. | |
**MSYS2** 32-битная ставится в ''C:\msys32'', 64-битная - в ''C:\msys64''. Можете попробовать поменять имя, | Да, надо дабавить, что сама по себе **MSYS2** тоже бывает 64-битная и 32-битная (была). К счастью на сайте **MSYS2** [[https://repo.msys2.org/distrib/|есть]] нужный инсталлятор, |
но тогда никто ничего не гарантирует... Но вот беда - инсталлятор старый и первое, что нужно сделать - | (''msys2-x86_64'' или ''msys2-i686'') - это такой огромный файл .EXE, у которого внутри целый архив соответствующих программ. |
это обновиться: ''pacman -Syuu'' | **MSYS2** 64-битная по умолчанию ставится в ''C:\msys64'', а 32-битная - в ''C:\msys32''. Можете попробовать поменять каталог, |
| но тогда никто ничего не гарантирует... Но вот беда - инсталлятор старый и первое, что нужно сделать - это обновиться командой: ''pacman -Syuu'' |
Этот ''pacman'' первым делом обновит сам себя, так что ОБЯЗАТЕЛЬНО надо прибить всё окно! НЕ выходя!!! | Этот ''pacman'' первым делом обновит сам себя, так что ОБЯЗАТЕЛЬНО надо прибить всё окно! НЕ выходя!!! |
И запустить ''pacman -Syuu'' еще раз. | И запустить ''pacman -Syuu'' еще раз. |
| |
Вы еще тут ? Я еще держусь, но с трудом... :) | Вы еще тут ? Я еще держусь, но с трудом... :) |
| |
| **ПРИМЕЧАНИЕ:** С мая 2020 32-битную **MSYS2** стали [[https://www.msys2.org/news/#2020-05-17-32-bit-msys2-no-longer-actively-supported|потихоньку сворачивать]]. Она еще поддерживается, но пакеты для нее выходят крайне редко, а начальный инсталлятор для 32-битной версии **MSYS2** убрали с главной стравницы [[http://repo.msys2.org/distrib/i686/|сюда]]. Следите за [[https://www.msys2.org/news/|новостями]]. Таким образом, даже для сборки 32-битных приложений нужно использовать 64-битную ОС и 64-битную ''MSYS2''. Этакая кросс-система. Увы. |
| |
| [[https://www.msys2.org/news/#2022-04-06-windows-7-8-support-will-be-dropped-late-2022-or-early-2023|2022-04-06 - Windows 7 / 8 support will be dropped late 2022 or early 2023]] |
| |
| [[https://www.msys2.org/news/#2023-01-15-dropping-support-for-windows-7-and-80|2023-01-15 - Dropping support for Windows 7 and 8.0]] |
| |
==== Компилятор и его запуск ==== | ==== Компилятор и его запуск ==== |
| |
Ну вот например поставили мы 32-битную **MSYS2**. Давайте попробуем наконец скомпилить HelloWorld | Ну вот например поставили мы **MSYS2** (без разницы, 64-битную или 32-битную) и обновились. Давайте попробуем, наконец, скомпилить HelloWorld |
под Windows консоль. А вот хрен вам! Оказывается, теперь есть НЕ ОДИН компилятор, точнее не одна build-система, а несколько. | под Windows-консоль. А вот хрен вам! Оказывается, теперь есть НЕ ОДИН компилятор, точнее не одна build-система (среда, namespace e.t.c.), а несколько. |
Из них первая - для компиляции программ под __САМУ__ **MSYS2** (вы же помните, что она тащит за собой теперь как | Из них первая - для компиляции программ под __САМУ__ **MSYS2** (вы же помните, что она тащит за собой теперь как |
минимум DLL ''msys-2.0.dl'' и работает с UNIX-путями), а вторая build-система - для "обычных" Windows программ, | минимум DLL ''msys-2.0.dll'' и работает с UNIX-путями), а остальные build-системы - для обычных "голых" Windows программ, |
как в старом **Mingw**. Компилятор и там и там - **Mingw-w64**, но по-разному настроенный. Да, | как в старом добром **Mingw**. Компилятор и там и там - знакомый **Mingw-w64**, но по-разному настроенный. Да, |
не забываем что всё это может существовать в 32-бит, 64-бит и все комбинации между ними! | не забываем что всё это может существовать в 32-бит, 64-бит и все комбинации между ними! |
Так что на самом деле у нас бывает (как минимум!) __ТРИ__ build системы: ''msys2'', ''mingw32'' и ''mingw64''. | Так что на самом деле у нас бывает (как минимум!) __ТРИ__ build системы: ''msys2'', ''mingw32'' и ''mingw64''. |
Все три ставить не обязательно. Например, если нам надо только собирать "чистые" 32-битные программы | Все три ставить не обязательно. Например, если нам надо только собирать "чистые" 32-битные программы |
на 32-битной винде то можно поставить 32-битную **MSYS2** без её компиляторов и build-систему ''mingw32''. | на 64-битной винде то можно поставить 64-битную **MSYS2** __без__ её собственных компиляторов и build-систему ''mingw32''. |
(как понимаете, на самом деле это будет 32-битный компилятор **Mingw-w64** работающий под 32-битной **MSYS2** и который умеет | (как понимаете, на самом деле это будет 64-битный компилятор по имени **Mingw-w64** работающий под 64-битной **MSYS2** и который умеет |
делать 32-битные "чистые" программы под Windows. Надеюсь крыша у вас еще не поехала...) | делать 32-битные "чистые" программы под Windows. Надеюсь крыша у вас еще не поехала...) |
| |
Давайте сначала установим тулзы для сборки: ''pacman -S base-devel'' | Итак, давайте сначала установим тулзы для сборки: ''pacman %%--%%needed -S base-devel'' |
Это установит всякие полезные для сборки утилиты в нашу **MSYS2** (любой битности). | Это установит всякие полезные для сборки утилиты в нашу **MSYS2** (любой битности). |
Установщик ''pacman'' знает про себя, 32-бита он или 64, берёт правильные пакеты и ставит | Установщик ''pacman'' знает про себя, 32-бита он или 64, берёт правильные пакеты и ставит |
в правильный каталог. Репозиторий для любой **MSYS2** всегда называется просто ''msys2'' :) | в правильный каталог. Репозиторий для любой **MSYS2** всегда называется просто ''msys2'' :) |
Компилятор для **MSYS2** в base-devel не входит, да он нам и не нужен. | Компилятор для самой **MSYS2** в base-devel не входит, да он нам и не нужен. |
| |
{{ start-menu.jpg?nolink|MSYS2 Menu}} | {{ start-menu.jpg?nolink|MSYS2 Menu}} |
А вот теперь аккуратнее! Чтобы установить build-систему, которая делает 32-бит программы | А вот теперь аккуратнее! Чтобы установить build-систему, которая делает 32-бит программы |
надо установить группу ''mingw-w64-i686-toolchain''. То есть компилятор называется **Mingw-w64** | надо установить группу ''mingw-w64-i686-toolchain''. То есть компилятор называется **Mingw-w64** |
(помним, что это просто название такое). Ставится он на текущую **MSYS2** и будет | (помним, что это просто название такое). Ставится он на нашу текущую **MSYS2** и будет |
генерить 32-битные программы (хвостик ''-i686''). Делаем: ''pacman -S mingw-w64-i686-toolchain'' | генерить 32-битные программы (хвостик ''-i686''). Делаем ''pacman -S %%--%%needed mingw-w64-i686-toolchain''. |
Пакеты скачаются (из репозитория ''mingw32'') и будут установлены. | Пакеты компилятора скачаются (из репозитория ''mingw32'') и будут установлены. |
Вот только никакого компилятора не появится! | Вот только никакого компилятора не появится! |
| |
Чтобы воспользоваться нужным компилятором, надо запустить нашу **MSYS2** особым образом. | Чтобы воспользоваться нужным компилятором, надо __запустить__ нашу **MSYS2** особым образом. |
Если вы откроете кнопку Пуск --> Все программы --> "MSYS2 32bit" то увидите __три__ разных "среды": | Если вы откроете кнопку Пуск --> Все программы --> "MSYS2 32bit" то увидите __три__ разных "среды": |
"MSYS2 MinGW 32bit", "MSYS2 MinGW 64bit" и "MSYS2 MSYS". По крайней мере, на Windows7 так, | "MSYS2 MSYS", "MSYS2 MinGW 32bit" и "MSYS2 MinGW 64bit" (а в новых добавились еще clang и [[https://learn.microsoft.com/en-us/cpp/porting/upgrade-your-code-to-the-universal-crt/|ucrt]]). По крайней мере, на Windows7 так. |
Где эта папка на Windows10 - не знаю. Вот эти три разные режима запуска и делают всю магию. | На Windows10 эти программы расположены в главном меню под буквой "M". Вот эти __три разные режима запуска__ и делают всю магию. |
Альтернативный путь - запускать ''C:\msys32\msys2_shell.cmd'' с ключами ''-mingw32'', ''-mingw64'' | Альтернативный путь - запускать напрямую программы из папки ''C:\msys64\......exe'' или скрипт ''C:\msys64\msys2_shell.cmd'' с ключами ''-mingw32'', ''-mingw64'' |
или ''-msys2''. Это точно то же самое. | или ''-msys2''. Это точно то же самое. |
| |
Давайте запустим "MSYS2 MinGW 32bit". Теперь у нас доступен компилятор **gcc**, причем он полностью | [[https://www.msys2.org/docs/environments/| Табличка с "окружениями"]] |
| |
| Давайте запустим "MSYS2 MinGW 32bit". Вот теперь у нас доступен нужный компилятор **gcc**, причем он полностью |
настроен, с указанием папки ''include'', линкера и пути к библиотекам. Ура! | настроен, с указанием папки ''include'', линкера и пути к библиотекам. Ура! |
| |
==== Пишем программы ==== | ==== Пишем программы ==== |
| |
Создадим Си-шный файлик ''hello.c'' со стандартным библиотечным вызовом: | Создадим Си-шный файлик ''hello.c'' со стандартным библиотечным вызовом //printf()//: |
#include <stdio.h> | #include <stdio.h> |
| |
откомпилим его: | откомпилим его: |
$ gcc -o hello hello.c | $ gcc -o hello hello.c |
и запустим ПРЯМО ИЗ CMD.EXE (то есть из другого окна CMD, не из MSYS2): | и запустим ИЗ CMD.EXE (то есть из __другого__ окна CMD, а не из оболочки MSYS2) или из PowerShell: |
C:\TEMP\TEST>hello | C:\TEMP\TEST>hello |
Hello, World! | Hello, World! |
Есть и недостатки - полученный EXE-шник имеет размер почти 300Kb! Воспользуемся командой | Есть и недостатки - полученный EXE-шник имеет размер почти 300Kb! Воспользуемся командой |
''strip'' и удалим из него все лишнее. Получится EXE-шник около 16К, что гораздо лучше. | ''strip'' и удалим из него все лишнее. Получится EXE-шник около 16К, что гораздо лучше. |
Посмотрим, что у нас получилось: | Посмотрим, что у нас получилось (пример из Windows 7): |
$ file hello.exe | $ file hello.exe |
hello.exe: PE32 executable (console) Intel 80386, for MS Windows | hello.exe: PE32 executable (console) Intel 80386, for MS Windows |
Как и требовалось, это "чистое" автономное 32-битное консольное Win32 приложение, которое использует только | Как и требовалось, это "чистое" автономное 32-битное консольное Win32 приложение, которое использует только |
стандартные библиотеки 32-битного Windows (можно поспорить насчет стандартности | стандартные библиотеки 32-битного Windows (можно поспорить насчет стандартности |
MSVCRT.DLL, но по факту, она есть практически везде). Скорее всего программа будет | MSVCRT.DLL, в котором и располагается //printf(//)), но по факту, она есть практически везде. На 64-битном Windows вывод ''ldd'' будет несколько другой, поскольку там другая архитектура запуска 32-битных программ WindowsOnWindows (WoW). Скорее всего, эта программа будет |
работать даже в Windows 95 (не пробовал). | работать даже в Windows 95, поскольку формат PE-файла не изменился (не пробовал). |
| |
В данном пакете сразу включен [[https://en.wikipedia.org/wiki/Microsoft_Windows_SDK|Windows SDK]], поэтому можно писать программы на Win32 API, | В данном пакете сразу включен [[https://en.wikipedia.org/wiki/Microsoft_Windows_SDK|Windows SDK]], поэтому можно писать программы на Win32 API, |
как невинные типа [[https://eax.me/winapi-console-app/|Пишем простое консольное приложение на чистом WinAPI]] так и более | как невинные так и более |
серьезные, типа CreateFile( L"\\\\.\\PhysicalDrive0"... | серьезные, типа CreateFile( L"\\\\.\\PhysicalDrive0"... |
| |
Давайте теперь напишем оконную программку под Windows (точнее под Win32). Вытащим | Давайте теперь напишем оконную программку под Windows (точнее под Win32). Вытащим |
пример из старика Петзольда (Charles Petzold. Programming Windows): | пример из старика [[https://ru.wikipedia.org/wiki/Петцольд, Чарльз|Петзольда]] (Charles Petzold. Programming Windows): |
#include <windows.h> | #include <windows.h> |
| |
процессора, а тут его приспособили для указания "подсистемы". Если в программе есть //WinMain()//, | процессора, а тут его приспособили для указания "подсистемы". Если в программе есть //WinMain()//, |
то даже ''-mwindows'' указывать не обязательно, компилятор сам понимает, но на всякий случай укажем. | то даже ''-mwindows'' указывать не обязательно, компилятор сам понимает, но на всякий случай укажем. |
| |
| **ПРИМЕЧАНИЕ1:** Обратите внимание, что наша программа собирается со штатной библиотекой MSVCRT.DLL. Не стоит ждать многого от нее. В MSVCRT.DLL реализован далеко не полный набор функций ''libc''. |
| Кроме явного отсутствия "юниксовых" возможностей типа //fork()//, вида слешей в путях к файлам и т.д. расхождения могут быть совсем неожиданные (и в разных версиях Windows - разные). |
| Например, //printf()// не поддерживает формат ''%zd'' для типа ''size_t'', поддержка UTF-8 довольно странная и другие неожиданные вещи. Компилятор |
| **Mingw-w64** знает много таких особенностей и по мере возможностей дает предупреждения. [[https://www.msys2.org/wiki/Porting/|Подробности]]. Несколько больше возможностей предоставляет новомодная [[https://learn.microsoft.com/en-us/cpp/porting/upgrade-your-code-to-the-universal-crt?view=msvc-170|UCRT]]. Если же нужны юниксовые фишки и не пугает зависимости от DLL - всегда можно собрать программу под оболочку **MSYS2**. |
| |
| **ПРИМЕЧАНИЕ2:** Компиляторы **gcc**, а особенно **g++** иногда создают код, который зависит от библиотек |
| ''libgcc'' и ''libstdc++''. Чтобы полученное приложение не требовало соответствующих DLL, в командную |
| строку можно добавить опции ''-static-libgcc'' и ''-static-libstdc++''. Библиотеки же, которые являются "стандартными" |
| для Windows, умный **Mingw-w64** всегда делает динамическими, даже несмотря на присутствие опции ''-static'' |
| в опциях компилятора. |
| |
| ==== Консольные полноэкранные/CLI приложения ==== |
| |
| **TODO**. Параграф не дописан! Имеются проблемы со сборкой pdcurses! |
| |
| При портировании UNIX-приложений на **MSYS2** часто возникают сложности с работой "полноэкранных" текстовых приложений, TUI (Text User Interface) т.е. требущих управления экраном и управления курсором в консоли Windows. |
| |
| Тут надо сначала немного углубиться в теорию. С точки зрения UNIX мы имеем две сложно-взаимодействующих абстракции: |
| - [[https://ru.wikipedia.org/wiki/Стандартные потоки|Стандартные потоки]] STDIN/STDOUT/STDERR. Это заранее открытые псевдо-файлы, которые передаются при старте UNIX программы, с номерами файловых десткрипторов 0,1, и 2. Довольно часто, это не терминал, а вывод из предыдущей программы (pipe) или реальный файл. |
| - Терминал TTY. У терминала в UNIX имеется множество функций и атрибутов. Например, имеется API управления дисциплиной линии (всякие RTS/CTS), различные режимы ввода (с эхо или без) [[https://man7.org/linux/man-pages/man3/termios.3.html|termio/termios]], возможность переключения raw/cooked режимов, а также специальные функции управления заданиями (job control, например обработка CTRL-C, CTRL-Z) и т.д. Кроме того, у каждой разновидности терминала имеется база, описывающая его систему команд, в основном через ESC-последовательности (termcap/terminfo). |
| |
| На Windows - совершенно другая идеология управления консолью (WinAPI Console). (Пример: [[https://eax.me/winapi-console-app/|Пишем простое консольное приложение на чистом WinAPI]]). Поэтому и возникает необходимость в эмуляторе терминала и промежуточной библиотеке типа ''msys-2.0.dll'' или ''cygwin.dll'', которая имитирует (с разной степенью успешности) поведение UNIX системы. Тем или иным способом в оболочках типа **MSYS2** и **CYGWIN** эта проблема решена. Но с "автономными" консольными Windows приложениями неколько сложнее. На это накладывается взаимодействие программы через ''MSVCRT.DLL'', которая имитирует файловые потоки STDIN/STDOUT/STDERR и также вносит свои особенности. |
| |
| Как же быть ? |
| |
| Можно предложить такое неожиданное решение. Как правило, управление терминалом в UNIX-программах редко делают напрямую, на нижнем уровне через API терминала termio/termios. Как правило, используют готовые библиотеки, например [[https://ru.wikipedia.org/wiki/Termcap|Termcap]] или [[https://ru.wikipedia.org/wiki/Curses|Curses]]. Такую UNIX программу намного легче портировать в консольное "автономное" Windows приложение. Доверимся авторам **MSYS2** в надежде, что они корректно перенесли на Windows и отладили эти библиотеки. |
| |
| Надо сказать, что современных реализаций библиотеки curses есть целых две. Одна из них - ncurses, другая - pdcurses. Давайте установим ncurses для нашей 32-битной сборки: ''pacman -S mingw-w64-i686-ncurses''. |
| |
| **ПРИМЕЧАНИЕ**: Как было написано выше, управление консолью в Windows устроено совсем иначе, чем в UNIX, так что не обходится без глюков. Библиотека ncurses реализована таким образом, что она "чувствует", под какой консолью она работает и включает "магию". Если мы запускаем одну и ту же прогрмамму под UNIX-подобной консолью, она начинает управлять экраном через ESC-последовательности, а если из CMD или PowerShell - через API Windows Console. Но фокус в том, что для ESC-последовательностей нужна база терминалов, а она не всегда доступна. Это дает неприятный результат: программа на ncurses неадекватно работает из "оболочки" **MSYS2 Mingw64** в которой мы ее только что откомпилировали. А из обычных CMD или PowerShell работает нормально. Как это обойти ? Если нужна программа для среды **MSYS2** - скомпилируйте ее в оболочке **MSYS2 MSYS** с ее библиотеками, а если "чистая виндовая" - в среде **MSYS2 Mingw64**. |
| |
| Давайте создадим простую ncurses программу для Windows (конечно же статическую): |
| |
| #include <curses.h> |
| |
| int main() |
| { |
| initscr(); /* Start curses mode */ |
| printw("Hello World !!!"); /* Print Hello World */ |
| refresh(); /* Print it on to the real screen */ |
| getch(); /* Wait for user input */ |
| endwin(); /* End curses mode */ |
| |
| return 0; |
| } |
| |
| |
| $ gcc -static -o curses.exe curses.c -I /usr/include/ncurses -l ncurses -DNCURSES_STATIC |
| |
| Обратите внимание, на ''#include'' - тут подключается заголовочный файл ''curses.h'', в стиле UNIX SYSVr4. Там компилятор обычно ищет ''curses.h'' прямо в ///usr/include// . В нашем случае это не работает, потому что у наc ДВЕ реализации curses и их заголовочные файлы лежат в разных каталогах. Так что нужно добавить ключ -I компилятору для поиска. |
| |
| При запуске этой программы в CMD или PowerShell (или кликом из Проводника) все работает как надо - пишет "Hello World !!!" в верхнем левом углу, а при запуске из **MSYS2 Mingw64 X86** программа вылетает (как и предупреждали): |
| |
| [USER@HOST test]$ uname |
| MINGW32_NT-10.0-17134 |
| [USER@HOST test]$ ./curses.exe |
| Error opening terminal: xterm. |
| |
| Для дальнейшего погружения в ncurses есть неплохое [[https://tldp.org/HOWTO/NCURSES-Programming-HOWTO/|NCURSES Programming HOWTO]]. Также большое количество документации и примеров содержится в [[https://invisible-island.net/archives/ncurses/|исходниках ncurses]]. |
| |
| Другая реализация curses - [[https://pdcurses.org/|pdcurses]] сделана еще более интересно. Она может выводить текстовый TUI интерфейс с поддержкой текстовых окошек не только в текстовую консоль, но даже в окно X11, в окно SDL, использовать графику и т.д. Имеется даже [[https://github.com/Bill-Gray/PDCursesMod|форк pdcurses]], который может отрисовывать текст с управлением терминалом в других оконных системах, от Windows GDI до OpenGL. |
| |
| /не дописано т.к. имеются проблемы с pdcurses/ |
| |
| Еще одна популярная библиотека, требующих прямого управления консолью - [[https://ru.wikipedia.org/wiki/GNU_Readline|readline]]. Библиотека GNU Readline очень удобна для ввода и используеся довольно широко. Самый известные примеры - ''bash'' и ''gdb''. Давайте установим: ''pacman -S mingw-w64-i686-readline''. |
| |
| В поставке readline идет несколько примеров. Лежат они (для нашей среды) в ///mingw32/share/readline/// . Можно собрать простейший пример rlbasic.c |
| |
| $ cp /mingw32/share/readline/rlbasic.c . |
| $ gcc -static -o rlbasic.exe rlbasic.c -l readline -l ncurses -DNCURSES_STATIC |
| |
| Опять же, при запуске полученной программы из среды **MSYS2** программа работает странно (трижды выводит всю строку и редактирование не работает), а при запуске из CMD или PowerShell - нормально (позволяет редактировать строку и ловит команду "exit"). Библиотека GNU readline подерживает множество функций, например историю ввода, которая в этом примере не обрабатывается. |
| |
| Полная документация по [[https://web.mit.edu/gnu/doc/html/rlman_toc.html|GNU Readline Library]]. |
| |
| Библиотекой readline можно управлять с помощью файла''.inputrc'' (под Windows ??) |
| |
| Конец недописанного параграфа. |
| |
| |
==== SDL ==== | ==== SDL ==== |
| |
Если мы хотим быть современными динамичными программистами, то лучше писать на каком-нибудь | Если вы хотите быть современным молодым динамичным программистом, то лучше писать на каком-нибудь |
Framework (как етто по рюски? Каркас?). Например, очень большое число разных эмуляторов | Framework :) (как етто по рюсcки? Каркас?). Например, очень большое число разных эмуляторов |
винтажных систем написано на **[[https://www.libsdl.org/|SDL]]**. | винтажных систем написано на **[[https://www.libsdl.org/|SDL]]**. |
| |
По **SDL** в сети просто огромное число примеров, туториалов, введений и т.д. **SDL** рисует, | По **SDL** в сети гуляет просто огромное число примеров, туториалов, введений и т.д. **SDL** рисует, |
поёт, поддерживает джойстик и сеть, может быть даже варит кофе... Текущая версия: **SDL2**. | играет музыку, поддерживает джойстик и сеть, может быть даже варит кофе... ;-) Текущая версия: **SDL2**. |
Давайте поставим себе **SDL2** вместе со всеми её запчастями :\\ | Давайте поставим себе **SDL2** вместе со всеми её запчастями :\\ |
''pacman -S mingw-w64-i686-SDL2 mingw-w64-i686-SDL2_gfx mingw-w64-i686-SDL2_image | ''pacman -S mingw-w64-i686-SDL2 mingw-w64-i686-SDL2_gfx mingw-w64-i686-SDL2_image |
| |
Давайте просто подключим вывод в свою командную строку (это делается с помощью | Давайте просто подключим вывод в свою командную строку (это делается с помощью |
обратного апострофа: **`** . Читается как "Использовать ВЫВОД команды" ) | обратного апострофа: **`** . Читается как "Использовать ВЫВОД команды". Подробности в ''man bash'' секция "Command Substitution" ) |
$ gcc -o hellosdl hellosdl.c `sdl2-config --cflags --libs` | $ gcc -o hellosdl hellosdl.c `sdl2-config --cflags --libs` |
Если мы попытаемся теперь запустить эту программу из CMD.EXE, мы получим ошибку:\\ | Все откомпилировалось. НО! Если мы попытаемся теперь запустить эту программу из CMD.EXE (или просто кликнуть из проводника Windows), мы получим ошибку:\\ |
"Запуск программы невозможен, так как на компьютере отсутствует SDL2.dll .\\ | "Запуск программы невозможен, так как на компьютере отсутствует SDL2.dll .\\ |
Попробуйте переустановить программу."\\ | Попробуйте переустановить программу."\\ |
Это неудивительно, так как полученная программа требует для своей работы ''SDL2.DLL'', | Это неудивительно, так как полученная программа требует для своей работы ''SDL2.DLL'', |
а она пока доступна только "изнутри" среды **MSYS2**. Можно пойти двумя путями: первый - установить | а она пока доступна только "изнутри" среды **MSYS2**. Можно пойти двумя путями: первый - установить |
''SDL2.DLL'' "в систему", второй: просто положить ''SDL2.DLL'' в каталог с программой. Тогда за | ''SDL2.DLL'' "в систему" (в C:\Windows\System32), второй: просто положить ''SDL2.DLL'' в каталог с программой. Тогда за |
счет известной особенности Windows "use local DLL" программа при запуске найдет нужную | счет известной особенности Windows "use local DLL" программа при запуске найдет нужную |
DLL и подключит. Скачаем нужный runtime (например 32-битный) на сайте | DLL и подключит. Скачаем нужный runtime (например 32-битный) на сайте |
но сильно мешает создавать "автономные" приложения Windows на Mingw. Используйте "официальную" SDL2.DLL\\ | но сильно мешает создавать "автономные" приложения Windows на Mingw. Используйте "официальную" SDL2.DLL\\ |
Второе. Можно даже саму SDL2.DLL вкомпилить статически. Можно. Но сейчас SDL2 употребляется настолько часто, | Второе. Можно даже саму SDL2.DLL вкомпилить статически. Можно. Но сейчас SDL2 употребляется настолько часто, |
что автор считает допустимым использовать такие "инфраструктурные" компоненты, типа QT или той же SDL2 в форме DLL. Дело вкуса. | что автор считает допустимым использовать такие "инфраструктурные" компоненты, типа QT или той же SDL2 в форме DLL и ставить их "в систему". Дело вкуса. |
| |
==== OpenGL ==== | ==== OpenGL ==== |
будут только от "стандартных" DLL имеющихся в Windows. | будут только от "стандартных" DLL имеющихся в Windows. |
| |
==== OpenGL через SDL ==== | ==== OpenGL через SD2L ==== |
| |
Наконец, существует возможность - использовать уже знакомую нам SDL для "склейки" операционной | Наконец, существует возможность - использовать уже знакомую нам SDL2 для "склейки" операционной |
системы и OpenGL. Это намного удобнее т.к. в SDL имеются функции ввода, управления | системы и OpenGL вместо GLU или GLUT. Это намного удобнее т.к. в SDL2 имеются функции ввода, управления |
манипуляторами, звуком и т.д. и самое главное - обе библиотеки кросс-платформенные. | манипуляторами, звуком, сетью и т.д. и самое главное - обе библиотеки кросс-платформенные. |
| |
<to be continued...> | <to be continued...> |
| |
==== Дополнительное чтение ==== | https://ps-group.github.io/opengl/ |
| |
**ПРИМЕЧАНИЕ:** Компиляторы **gcc**, а особенно **g++** иногда создают код, который зависит от библиотек | https://ps-group.github.io/opengl/lesson_1 |
''libgcc'' и ''libstdc++''. Чтобы полученное приложение не требовало соответствующих DLL, в командную | |
строку можно добавить опции ''-static-libgcc'' и ''-static-libstdc++''. Библиотеки же, которые являются "стандартными" | ==== Интеграция MSYS2 и VSCode ==== |
для Windows, **Mingw-w64** всегда делает динамическими, даже несмотря на присутствие опции ''-static'' | |
в опциях компилятора. | Для удобства программирования будет полезным использовать новомодную "оболочку" [[https://code.visualstudio.com/|VSCode]]. |
| |
| VSCode для Windows поставляется как минимум двух разновидностей: "системная" и "юзеровская". Ставьте системную (скачайте "System Installer" на [[https://code.visualstudio.com/download|странице загрузки]]). Она пропишет себя в путь PATH и т.д. Чтобы **MSYS2** брала системые пути из PATH, нужно в соотвествующем .ini файле (например C:\msys64\mingw32.ini) раскомментировать параметр ''MSYS2_PATH_TYPE=inherit'' |
| |
| Для работы надо запускать VSCode **из MSYS2** а точнее, прямо из командной строки той среды, под которую мы собираем (например "MSYS2 MinGW 32bit"). Это даст VSCode возможность правильно найти пути к нужным компиляторам и библиотекам. |
| |
| Запускать VSCode надо прямо из папки (workspace), в которой мы ведем разработку, то есть "''cd myproject ; Code . &''" (обратите внимание на точку ''.'' что означает: взять текущий каталог как workspace. Знак ''&'' применяется для запуска VSCode в фоне и "отсоединения" консоли). При первом запуске будет создан подкаталог ".vscode" в котором будут лежать файлы .json конфигурации проекта. |
| |
| Для среды **MSYS2 MinGW 32bit** и т.д. VSCode во встроенном терминале будет использоваться PowerShell в качестве оболочки вместо ''sh'', поскольку мы собираем виндовую, независимую от **MSYS2** программу. (Если мы будем собирать под среду **MSYS2 MSYS** то будет использоваться родной ''sh''). |
| |
| [[https://code.visualstudio.com/docs/cpp/config-mingw|Get Started with C++ and MinGW-w64 and Visual Studio Code]] |
| ==== Дополнительное чтение ==== |
| |
**ПРИМЕЧАНИЕ2:** Не стоит ждать многого от библиотеки MSVCRT.DLL . Это далеко не полная реализация ''libc''. | |
Кроме явного отсутствия "юниксовых" возможнотей типа //fork()// и т.д. расхождения могут быть совсем неожиданные. | |
Напаример, //printf|()// не поддерживает формат ''%zd'' для типа ''size_t'' и другие неожиданные вещи. Компилятор | |
**Mingw-w64** знает много таких особенностей и по мере возможностей дает предупреждения. | |
| |
| |