пятница, 6 июня 2014 г.

[prog.c++] Безболезненная компиляция ACE с помощью MinGW

Есть такая большая C++ная библиотека -- ACE. И есть порты GNU GCC под Windows под общим названием MinGW (на самом деле их много, об этом ниже). Долгое время для меня был большой вопрос: как же работать с ACE вместе с MinGW?

Дело в том, что с оригинальным MinGW я уже много лет предпочитаю не связываться. Во-первых, какая-то там была очень мудреная система распространения -- сначала общие архивы со всем-всем-всем. Затем, напротив, куча мелких пакетиков. Хорошо хоть, в последнее время графический инсталлятор всего этого добра был доведен до работающего состояния. Во-вторых, сам оригинальный MinGW, как мне казалось, весьма сильно отстает от релизов unix-овских версий GCC. Например, насколько я могу судить, на mingw.org до сих пор лежат 32-битовые версии компилятора. Хотя альтернативные сборки (MinGW-w64, Win-builds, Nuwem, TDM-GCC) уже давно кроме 32- предоставляют и 64-битовые версии (в том числе GCC 4.8.3 и 4.9.0).

Поэтому, если мне нужно было что-то проверять под Windows GNU-тым компилятором, то я использовал Cygwin (который так же очень давно есть и в 32- и в 64-х битах).

Ну а вот на днях принципиально захотелось, чтобы ACE и SObjectizer собирались без проблем именно MinGW, а не Cygwin-ом. В итоге разобрался, что для этого нужно. В принципе, все это описано в штатной документации к ACE, но есть нюансы.

К сожалению, ключевой компонент, необходимый для нормальной компиляции ACE -- это MSYS, минималистическая имитация Unix-ового окружения под Windows. Я долгое время пытался вместо MSYS использовать Cygwin-овское окружение, но не прокатило. Поэтому без MSYS никуда и MSYS нужно брать с mingw.org.

Больше с mingw.org ничего не нужно, компилятор и библиотеки можно взять в другом месте. А вот MSYS придется искать и качать на mingw.org. Дабы не разбираться с кучей всего, что есть среди дистрибутивов mingw.org, можно воспользоваться графическим инсталлятором, в котором выбрать MSYS и позволить ему скачать и распаковать все самостоятельно.

После установки MSYS можно пойти двумя способами. Либо запускать MSYS среду посредством имеющегося в MSYS для этих целей bat-файла (у меня это C:\Original-MinGW\msys\1.0\msys.bat) и оказаться в готовом shell-е, а уже там настраивать все остальные пути. Либо же прописать в свой PATH путь к bin-каталогу MSYS-а (у меня это, соответственно, C:\Original-MinGW\msys\1.0\bin). Я пошел по второму пути, ниже объясню почему.
Upd. Можно воспользоваться и MSYS2. Я скачал msys2-base-x86_64, распаковал архив, прописал путь к msys2/bin в PATH. Далее через pacman установил пакет make, т.к. для ACE нужен GNU make, который идет в составе MSYS сразу, а вот в msys2-base его нет.
Сам же компилятор MinGW можно брать любой. Поскольку практически все перечисленные мной выше альтернативы оригинальному MinGW базируются на MinGW-w64, то можно только MinGW-w64 и ограничиться. Хотя у других дистрибутивов есть свои плюшки. Например, Nuwem вместе с MinGW-w64 ставит git, Boost и еще кучу всякой полезной в хозяйстве всячины. Win-builds так же вместе с MinGW-w64 предоставляет кучу библиотек, компиляция некоторых из них под Windows то еще удовольствие, так что к вариантам Nuwem и Win-builds рекомендую пристально присмотреться, если вам нужен не только ACE.

Для меня удобство MinGW-w64 состоит в том, что он распространяется в виде 7z-архива. Распаковываешь его куда удобно (в моем случае C:\mingw64) и все! Потом только добавляешь путь к его bin-каталогу в PATH. Если нужно обновить, то просто качаешь новую версию и распаковываешь ее.

Поскольку мне для компиляции SObjectizer вместе с ACE кроме MSYS и MinGW нужен еще и Ruby, то я настраиваю пути ко всему этому хозяйству в одном bat-файле, который содержит что-то вроде:

@set PATH=%PATH%;C:\ruby-2.0.0-p481-x64-mingw32\bin
@set PATH=%PATH%;C:\Original-MinGW\msys\1.0\bin
@set PATH=%PATH%;C:\mingw64\bin

После запуска своего bat-файла я получаю среду, в которой доступен компилятор MinGW и Unix-овые утилиты, необходимые для компиляции ACE.

Следующий очень важный шаг -- это определение переменной среды ACE_ROOT. Когда ACE компилируется под Visual C++ про ACE_ROOT можно забыть, а вот для MinGW его нужно выставлять. У меня для компиляции SObjectizer это делает Ruby-новый скрипт в рамках build-процесса внутри Mxx_ru. Но если вы компилируете ACE сами, то ACE_ROOT нужно прописывать ручками. Для этого удобно задействовать shell из MSYS, т.к. там проще работать с переменными среды, например, с $PWD.

Если ACE_ROOT выставлена правильно, то остается еще один важный нюанс: в make-правилах для компиляции ACE по умолчанию для GCC выставляется флаг -mtune=pentiumpro. И попытка собрать ACE 64-битовым GCC завершится сообщением об ошибке, т.к. модель оптимизации pentiumpro не совместима с режимом x86-64. Чтобы этой проблемы не было, компиляцию ACE нужно запускать задавая для make параметр TCPU=:

make TCPU= shared_libs=1 debug=0

Итак, резюмируя: обязательно нужен MSYS или MSYS2+make, обязательно нужно выставить переменную среды ACE_ROOT. И, при компиляции в x86-64 задать свое значение для TCPU при запуске make.

PS. Если ставить вручную MSYS и MinGW, то можно легко установить рядом 32-х и 64-х битовые версии MinGW, просто нужно иметь разные настройки для PATH. Это позволит проверять работу своих приложений как в 32-, так и в 64-х битовых режимах.

PPS. В составе MinGW-w64 есть дистрибутивы, помеченные как win32 и posix. Я проверял на win32-вариантах с SEH-обработкой исключений. ЕМНИП, с posix-вариантами ACE не компилируется, а выдает кучу ошибок по поводу ACE_WCHAR_T и char.

Комментариев нет: