Qt & Ubuntu. Настраиваем среду для компиляции win32-приложений
Эта мини-статья рассказывает об одном из способов осуществления кросс-компиляции приложений Qt для платформы win32.
Приступим, друзья
Начнем с того, что скачаем и установим родной Qt SDK (для Linux).
Как вариант — выполним в консоли:
Я поставил Qt SDK Linux в папку “/home/caiiiycuk/qt-cross/qt-linux”, так что будьте внимательны к путям.
Следующий этап, пожалуй, самый проблематичный — нам нужно раздобыть скомпилированные библиотеки Qt для целевой платформы (windows). Есть два варианта: либо скомпилировать их с помощью кросс-компиляции из исходников (что, как мне кажется, будет очень не просто); либо поставить Qt SDK на какую-нибудь win-машину, а затем заботливо перенести папочку с Qt в родную систему. Я пошел вторым путем и Qt SDK для Windows уютно обосновалося в папочке /home/caiiiycuk/qt-cross/qt-win.
Отлично, теперь настроим среду компиляции windows. Установим mingw-компилятор из репозитория Ubuntu:
sudo apt-get install mingw32
По окончании установки станет доступен тулкит i586-mingw32msvc-*, которым мы и будем компилировать под win32-платформу.
В качестве приложения для примера кросс-компиляции я использую fancybrowser (qt-linux/qt/examples/webkit/fancybrowser), скопированный в папку “/home/caiiiycuk/qt-cross/fancybrowser”. Как вы понимаете, можно использовать любой другой проект — просто глаз на него упал у меня 🙂
- Qt SDK для Linux, в папке “/home/caiiiycuk/qt-cross/qt-linux”
- Qt SDK для Windows, в папке “/home/caiiiycuk/qt-cross/qt-win”
- Тестовое приложение «fancybrowser», в папке “/home/caiiiycuk/qt-cross/fancybrowser”
- Компилятор gcc/g++ 4.4.3 (поставляется вместе с Ubuntu)
- Компилятор i586-mingw32msvc-gcc/i586-mingw32msvc-g++ (установили из репозитория Ubuntu)
Хорошо, начнем с простого — скомпилируем проект используя qt-linux (т.е. для linux системы):
//действия выполняются из каталога /home/caiiiycuk/qt-cross/fancybrowser
export QTDIR=/home/caiiiycuk/qt-cross/qt-linux/qt
export QMAKESPEC=/home/caiiiycuk/qt-cross/qt-linux/qt/mkspecs/linux-g++-32
$QTDIR/bin/qmake
make clean
make
Просто, не так ли? 🙂 На выходе получем исполняемый файл fancybrowser. Запустив его, увидим что-то вроде:
Компилируем под Windows
Вот и настало время компилировать под win32. Для начала создадим файл спецификации, объясняющий Qt как выполнять компиляцию под Windows. Для облегчения себе жизни скопируем уже существующий файл спецификации win32-g++
cd qt-win/qt/mkspecs/
mkdir win32-x-g++
cp win32-g++/* win32-x-g++/
Внесем необходимые исправления в файл win32-x-g++/qmake.conf:
QMAKE_SH = sh
…
QMAKE_CC = i586-mingw32msvc-gcc
…
QMAKE_CXX = i586-mingw32msvc-g++
…
QMAKE_INCDIR_QT = /home/caiiiycuk/qt-cross/qt-win/qt/include
QMAKE_LIBDIR_QT = /home/caiiiycuk/qt-cross/qt-win/qt/lib
…
QMAKE_LINK = i586-mingw32msvc-g++
QMAKE_LINK_C = i586-mingw32msvc-gcc
QMAKE_LFLAGS = -mthreads -Wl,-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -mwindows
…
QMAKE_MOC = /home/caiiiycuk/qt-cross/qt-linux/qt/bin/moc
QMAKE_UIC = /home/caiiiycuk/qt-cross/qt-linux/qt/bin/uic
QMAKE_IDC = /home/caiiiycuk/qt-cross/qt-linux/qt/bin/idc
…
QMAKE_RC = i586-mingw32msvc-windres
…
QMAKE_STRIP = i586-mingw32msvc-strip
…
Теперь можно компилировать:
//действия выполняются из каталога /home/caiiiycuk/qt-cross/fancybrow
export QTDIR=/home/caiiiycuk/qt-cross/qt-win/qt
export QMAKESPEC=/home/caiiiycuk/qt-cross/qt-win/qt/mkspecs/win32-x-g++
/home/caiiiycuk/qt-cross/qt-linux/qt/bin/qmake
make clean
make
После успешной компиляции в папке release будет лежать заветный fancybrowser.exe. Всего и делов 🙂
Не забываем, что для запуска необходимо иметь требуемые dll (для fancybrowser — QtCore4.dll QtGui4.dll QtNetwork4.dll QtWebKit4.dll QtXmlPatterns4.dll phonon4.dll mingwm10.dll libgcc_s_dw2-1.dll). Эти библиотеки можно взять из папки qt-win/qt/bin но не из папки qt-win/bin. В результате должно получиться это:
Я не могу гарантировать, что это «true way» для кросс-компиляции qt-приложений, это только мои изыскания. Буду благодарен за любую критику 🙂 Работоспособность этого метода так же была проверена на OpenSuse и CentOS. Ubuntu была лучше лишь тем, что в её репозитории лежит mingw32 более поздней версии. Уж не знаю с чем это связанно — мелочь, а приятно.
Эти скрипты (для компиляции) могут быть легко интегрированны в Hudson, для облегчения сборки кросс-платформенных продуктов, но это уже тема для отдельной статьи. Всем спасибо 🙂
Кросс-компиляция и отладка C++ Windows-приложения под Linux
Показали мне недавно интересное приложение, под которое можно разрабатывать плагины. Приложение оказалось очень полезным для научной работы, но вот незадача — приложение разработано под Windows, у меня стоит Ubuntu. Windows для разработки под это приложение от лаборатории получить пока не удалось. Чтобы не тратить время, решил освоить кросс-компиляцию и отладку этого приложения.
Итого, имеется:
Ubuntu 12.10 x64
Не-юникодное приложение Мастерская Граф-Моделей (МГМ) (В командах консоли будет называться gmw.exe)
Нужно:
Разрабатывать и отлаживать плагины (dll-библиотеки), не устанавливая Windows.
И тут нам помогут Wine, Code::Blocks, портированное GDB, и boost.
Wine, не юникодное приложение, английский интерфейс Ubuntu и русский язык
При попытке открыть не юникодное приложение под Wine
wine gmw.exe
получаются зюки следующего вида:
На эту проблему интернет очень быстро дает следующую подсказку:
LC_ALL=ru_RU.UTF-8 wine gmw.exe
В моём случае, данный подход не улучшил ситуацию ни на йоту.
Как выяснилось, русских локалей в системе не было добавлено (тыц).
sudo echo "ru_RU.UTF-8 UTF-8" >> /var/lib/locales/supported.d/ru sudo locale-gen ru
Теперь запускаем с выше-указанной подсказкой
LC_ALL=ru_RU.UTF-8 wine gmw.exe
И, вуаля, запускается приложение с читаемым русским текстом:
Настройка IDE Code::Blocks для кросс-компиляции и отладки
Установка Code::Blocks
В дальнейшем для отладки нам потребуется менять код плагина отладки поэтому лучше сразу взять версию Code::Blocks из под svn.
Устанавливаем svn:
sudo apt-get install subversion
С помощью svn получаем код C::B, для этого переходим в папку, в которую хотим сохранить код C::B, где и набираем:
svn checkout svn://svn.berlios.de/codeblocks/trunk
Переходим в полученную папку ‘trunk’.
Компиляция C::B происходит с помощью g++, autotools, automake и некоторых других утилит, которые необходимо установить:
sudo apt-get install libtool autotools-dev automake autoconf g++ libhunspell-dev libgtk2.0-dev libgamin-dev libboost-dev
Кроме того Code::Blocks зависит от wxWidgets:
sudo apt-get install libwxgtk2.8-dev
Подстраиваем установщик под компьютер (можно запускать единожды):
sudo ./bootstrap
И дальше, устанавливаем сам codeblocks (ключ –prefix можно упустить для использования настроек по-умолчанию):
sudo ./configure --prefix= --with-contrib-plugins=all sudo make sudo make install
Более подробно можно посмотреть по ссылке.
Настройка компиляции и линковки
Выполняем пункты с 1 по 5 с форума Code::Blocks. После этого компиляция программ должна работать, если не используется линковка к платформо-зависмым библиотекам (линковка с boost::regexp будет рассмотрена позже).
(*) В новом Code::Blocks немного изменилось меню по сравнению с инструкцией. Настройки искать нужно в ‘Settings->Compiler. ‘. Для старого Code::Blocks (10.05) пункт 5 нужно выполнить полностью, для нового же (12.11) настройку касающуюся gdb в 5 пункте пока трогать не будем.
Если используется boost его лучше положить отдельно от /usr/include, т.к. по этому адресу лежит много linux-специфичных заголовочных файлов, которые мы не хотим включать в проект при компиляции под Windows.
UPD: При настройке линковки в поле «Other Linker Options» имеет смысл добавить опцию “-Wl,–subsystem,windows,–kill-at”, которая помечает, что это реально Windows DLL, и, что самое главное, запрещает использовать декорирование символов (–kill-at) при экспорте функций с соглашением вызова __stdcall. Подрбнее здесь и здесь.
Начиная с пункта 7 по ссылке выше, описывается кросс-отладка, но, к сожалению, insight.exe, упоминающийся в инструкциях, найти не удается. Поэтому пойдем своим путем.
Кросс-отладка в Code::Blocks & MingW32 gdb для Windows
gdb, который является родным для линукса частично умеет отлаживать Windows приложения, правда, умеет он только останавливаться на исключениях и почти всегда игнорирует точки останова. Чтобы справиться с этими проблемами скачиваем gdb в пакете mingw32 под Windows. Для этого скачиваем и затем распаковываем и переходим в подпапку ‘bin’. Устанавливаем gdb под Windows:
wine mingw-get.exe install gdb
Теперь в этой же папке bin появился файл gdb.exe, он-то нам и нужен.
Создаем скрипт для имитации обычного gdb для этого в файл /usr/bin/i586-mingw32msvc-gdb
sudo gedit /usr/bin/i586-mingw32msvc-gdb
Заносим следующие строки:
#!/bin/sh wine /bin/gdb.exe $@
Для старого C::B все уже настроенно, для нового же отладчик нужно настроить дополнительно. В пункте ‘Settings->Debugger’ кликаем по ‘GDB/CDB debugger’ затем по ‘Create Config’. В новом конфиге меняем команду запуска отладчика на ‘/usr/bin/i586-mingw32msvc-gdb’, остальные настройки по желанию. После этого идем в ‘Settings->Compiler. “, в пункте ‘Selected Compiler’ выбираем тот компилятор, который настраивали до этого и затем на вкладке ‘Toolchain executables’ меняем ‘Debugger’ на наш свежесозданный конфиг. Теперь отладчик будет останавливаться на точках останова, хотя и остановить программу в произволльный момент не сможет (данная проблема пока еще не решена). Правда при попытке отладить,C::B выдает следующую ошибку:
The program has stopped on a breakpoint but the breakpoint format is not recognized: 0x1A0x1AZ:/SamplePlugin.cpp:48:948:beg:0x68087599
Эта ошибка говорит о том, что плагин отладчика в C::B не понимает выдачу отладчика gdb.exe. Как выяснилось при ближайшем рассмотрении плагин отладчика имеет платформо-зависимый код, и вот тут-то и нужно вспомнить что у нас есть исходники C::B. Мы сейчас слегка подкоррекируем код этого плагина. Нужно будет поменять код только одного файла ‘/src/plugins/debuggergdb/gdb_driver.cpp’
Для этого нужно перейти в корень проекта C::B (откуда запускалась команды ./bootstrap), по умолчанию это папка ‘trunk’. И накактить патч:
patch --unified --strip=0 --forward --input=gdb_driver.cpp.patch
Ну и пересобираем Code::Blocks:
sudo ./configure --prefix= --with-contrib-plugins=all sudo make sudo make install
И почти все готово, остается только создать проект. Шаги 12-13 по ссылке. Если же вы хотите создать проект dll-библиотеки, то указывайти создание динамической библиотеки в мастере и переименовывайте разширение в dll.
Проверям, что в настройках проекта стоит выбранная нами цепь компилятор-линкер-отладчик. ‘-Build Options. ‘ пункт ‘Selected compiler’, и можно радоваться и отлаживаться. Напомню, что по какой-то причине отладчик не может быть прерван во время исполнения, т.е. все отладочные действия могут буть применены только во время останова программы. В частности нельзя поставить новую точку останова, если программа не стоит на какой-либо другой точке останова…
Линкование статической библиотеки boost’а
Библиотека boost в основном является набором заголовочных файлов, и потому никаких проблем с линковкой обычно не возникает. Но для некоторых частей boost’а необходимо линковаться к статической библиотеке, например, boost::regex. Пробуем собрать проект и получаем:
/boost/regex/v4/cpp_regex_traits.hpp|1059|undefined reference to `boost::scoped_static_mutex_lock::scoped_static_mutex_lock(boost::static_mutex&, bool)'
Ошибка возникает из-за того, что мы пытаемся прилинковаться к linux билиотеке, для того чтобы построить windows-приложение.
Чтобы слинковаться нужно скомпилировать boost::regex с помощью MingW32 (про кросс-компиляцию). Скачиваем boost, распаковываем и переходим в папку с распаковынным boost’ом. Создаем файл user-config.jam в корне домашней директории:
gedit ~/user-config.jam
Со следующим содержанием:
using gcc : : i586-mingw32msvc-g++ ;
Дальше настраиваем сборку и собираем:
sudo ./bootstrap.sh --with-libraries=regex --without-icu sudo ./b2
После выполнения последней команды у меня были ошибки «failed updating 1 target», что, правда, не мешает собираться программам.
В результате, у нас есть полностью подготовленная среда для написания, сборки и отладки Windows-приложений или Windows-библиотек из под Linux. Теперь можно приступать к работе…
При подготовке материала использовались источники:
https://habr.com/ru/articles/98131/
https://habr.com/ru/articles/162171/