Qt & Ubuntu. Настраиваем среду для компиляции win32-приложений

image
Эта мини-статья рассказывает об одном из способов осуществления кросс-компиляции приложений Qt для платформы win32.



Приступим, друзья

Начнем с того, что скачаем и установим родной Qt SDK (для Linux).
Как вариант — выполним в консоли:
wget get.qt.nokia.com/qtsdk/qt-sdk-linux-x86-opensource-2010.04.bin
chmod 777 qt-sdk-linux-x86-opensource-2010.04.bin
./qt-sdk-linux-x86-opensource-2010.04.bin
Я поставил 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)

Компилируем под Linux

Хорошо, начнем с простого — скомпилируем проект используя 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, для облегчения сборки кросс-платформенных продуктов, но это уже тема для отдельной статьи. Всем спасибо :)
+64
3 июля 2010, 11:10
98
Caiiiycuk 60,6

комментарии (49)

0
namezys #
полезно. можно выкинуть винду
0
oe24 #
Её давно пора выкинуть! :)
+1
namezys #
Да дело даже не в самой винде. мы пользуемся билд-машинами… а они под винду не очень работают

правда есть другая проблема… там еще коло 3 библиотек надосбирать
+1
naum #
Ну соль того же билдбота как раз в том, чтобы собирать платформонезависимо. Какие билд машины используете? Посмотрите на организацию сборщика у ScummVM (это отличный пример действительно кроссплатформенного приложения)
0
namezys #
мы с помощью биттема (точно не помню, как он завется — у нас админ делает)

дело в том, что нам надо еще и буст
0
naum #
Вроде особых проблем нет, да и не должно быть. Посмотрите в сторону BuildBot'a, к примеру, возможно, решит какие-то проблемы с виндой.
0
namezys #
как бы проблем нет — билдится
я тут подумал, что переход на линух с винды невозможен хотя бы потому, что надо тестировать компилируемость кода
+1
LeNsTR #
Поясните, пожалуйста, зачем? Тестировать под wine будете?
+9
Caiiiycuk #
Преследовалось несколько целей. Самая главная из них — централизованная сборка, т.е. кросс-компиляция позволяет нам выделить одну машину (в нашем случае linux-сервер с OpenSuse), на которой осуществляется сборка приложения под все поддерживаемые операционные системы. Таким образом мы избавляемся от гетерогенности, и поддержка процесса сборки упрощается. Тестировать безусловно необходимо в Windows, после сборки приложение тестируется в родных системах.

Представьте — я разработчик и работаю в среде Ubuntu, я меняю что-то в исходных кодах. Теперь мне нужно проверить не сломалась ли при этом приложение в Windows, я просто кросс-компилирую, вместо того что бы держать еще одну полностью настроенную win-машину только для компиляции. Быстрее и удобнее. К слову можно делать кросс-компиляцию из win в nix, естественно.
0
LeNsTR #
Хм, насчет сервера кросскомпиляции я с вам соглашусь. Но как насчет идентичности окружения сборки и его влияния на получившийся бинарник? Есть ли какие-нибудь подводные камни?
0
Caiiiycuk #
Думаю есть как и везде. Например версия mingw компилятора из репозитория постоянно отстает от актуальной (не знаю уж насколько это критично). Не могу больше ничего плохого сказать, пока проблем не возникало (уже 4 месяца пользуюсь этой схемой компиляции). Могу предположить что могут быть проблемы если Вы захотите использовать какой-то специфичный функционал Windows, который не поддерживается mingw.
0
Gorthauer87 #
В Генте наоборот, самый последний компилятор в minGW, который опережает по версии тот, что идет в windows SDK.
Если захочется специфичный функционал Виндовс использовать, ну например win7 superbar, то проблемы и с обычным minGW почти нерешаемые возникнут(((
0
Gorthauer87 #
Я пробовал. Подводных камней никаких, в общем-то окружение идентичное — тот же самый ming32, и кстати есть возможность заюзать mingw64 и собирать под win64. А еще приятный бонус: компилятор и Qtшные утилиты навроде moc'а работают из Линукса процентов на 50 быстрее.
+1
foe_nix #
ну да — а протестировать работу можно и в виртуалке. Вот чтоб компилить в виртуалке — это надо маньяком быть.
0
oe24 #
Пользуясь случаем, хочу спросить:
Я начинающий программист на QT. При компиляции и запуске получившегося exe-файла, у меня выскакивает системная ошибка о требовании библиотек. Когда я кидаю в папку с exe-шником необходимые dll-файлы, приложение запускается нормально.
ВОПРОС: Неужели придется таскать за exe-шником эти все примерно 130 Мб библиотек?
+4
LeNsTR #
Не 130 а ~10 в полной комплектации. И таки да, придется.
+2
Caiiiycuk #
Добавлю еще, что как Вы возможно заметили есть библиотеки с постфиксом «d», эти библиотеки нужны для режима отладки, и таскать их с собой не надо, они как раз и составляют большую часть от тех 130 мб ;)
+1
Caiiiycuk #
Можете использовать dependencywalker (http://www.dependencywalker.com/), что бы понять какие библиотеки Вам нужны.
+1
DZhon #
Частой практикой является статическая линковка под Windows. Т.о. еще и сама Qt должна быть собрана с ключом -static.
+3
ixSci #
Тогда можно забыть о лицензии своего кода, отличной от LGPL.
0
DZhon #
Позвольте, а как же Opera (старых версий) и Skype? :)
+2
ixSci #
значит они купили Qt
0
GreyCat #
От GPL, а не LGPL.
+5
GreyCat #
Библиотека, о которой Вы говорите, называется «Qt». А «QT» — это общепринятая аббревиатура для QuickTime.
0
Gorthauer87 #
Кстати, строго аналогичным образом (но чуть сложнее) создается среда для кросскомпиляции под Симбиан. Работает этот зверек ну раз в 10 быстрее, чем родной SDK, запущенный из под Виндовса.
0
KL7 #
А Вы не знаете, с чем связана такая медленная работа виндового SDK? А то это ужасно напрягает. Сборка элементарного проекта занимает весьма ощутимое время.
+1
Gorthauer87 #
По моим ощущениям тут виноват
1) Крайне тормозной перл
2) Какая-то ерунда с порождением процессов в Винде
3) Эта гадость начинает обсчитывать зачем-то все зависимости для сборки у каждого файла, в то время как в Линуксе она просто берет и пытается собрать.
4) windows SDK однопоточен!
+1
naryl #
Про многопоточность винды на примере прикручвания нитей к sbcl можете узнать много интересного в блоге широко известного в узких кругах dmitry_vk: dmitry-vk.livejournal.com/tag/win32
0
chemikadze #
А можно ли просто поставить в wine SDK для винды?
0
Cancel #
Раньше я так делал. Как сейчас, не в курсе.
+1
evgenyk #
Я и сейчас так делаю. Возможно это медленнее компилирует, чем описываемый здесь способ, но при установке меньше заморочек.
+1
Sicness #
> Компилятор gcc/g++ 4.4.3 (поставляется вместе с Ubuntu)
На сколько я помню — не в ходит в базовый дистрибутив, а так же ставится с репозитория. Просто его привычно ставим при первой же необходимости.
0
energycsdx #
неужеле в убунту нет способа по проще?
и зачем ставить родное сдк?
в федоре: yum install mingw32-qt mingw32-qt-qmake
0
Caiiiycuk #
Родное SDK нужно, для:
0
Caiiiycuk #
Сорри, продолжаю, для запуска:
1. qmake
2. moc
3. uic
4. idc
0
Gorthauer87 #
При юзании системных qmake,moc, etc могут быть грабли, я бы рекомендовал скачать сырцы Qt для нужной платформы и сделать
configure -platform linux-g++ -xplatform нужная спека
После чего руками собрать qmake, moc,uic, и т.д. Остальное уже можно не собирать, а взять из Windows или Symbian SDK.
+1
hoxnox #
Вообще, для любых приложений процесс кросскомпиляции (относится как к win-nix, так и к nix-win) сводится к следующему:
1. Компиляция mingw (набор из компилятора, сборщика, ассемблера и прочих низкоуровневых утилит) с вашей платформы на целевую.
2. Компиляция всех зависимостей (ВСЕ библиотеки, включая популярные iconv, gettext, zlib, ...) под целевую платформу.
3. Компиляция самого приложения под целевую платформу.

GNU-тые утилиты и приложения использующие automake и autoconf, позволяют легко сконфигурировать исходники для кросскомпиляции путем задания скрипту ./configure ключей build и target. В самом запущенном случае придется лезть в Makfile'ы и править кое-что ручками.
Пункт 2 сложен, но позволяет получить приложение, в котором вы определяете все параметры сборки, включая static, поддержку nls и прочие.
+1
Gorthauer87 #
>GNU-тые утилиты и приложения использующие automake и autoconf, позволяют легко сконфигурировать исходники для кросскомпиляции путем задания скрипту ./configure ключей build и target. В самом запущенном случае придется лезть в Makfile'ы и править кое-что ручками.

В половине случаев гнутый autohell какой-то мрак генерит вместо makefile'ов
0
hoxnox #
Так ведь для конфигурирования и компиляции autohell (не слышал такого варианта, спасибо — повеселили) и не нужен. С ними мучаются разработчики, а клиенту остается лишь наковырять в консоли нужный configure и все…

К примеру для кросскомпиляции с 32 разрядной винды в 64-разрядную будет как-то так: ./configure --target=x86_64-w64-mingw32 --host=i686-pc-mingw32 при том, что minw для 64 разрядной платформы собран и лежит в нужном месте.
0
Gorthauer87 #
Знаю я, что в идеале так, а вот в реальности берет и не собирается((( Я так замаялся в свое время в Генте пытаться кросскомпилить libpurple и так и не смог справиться
0
zugzwang #
Остается еще вопрос как при кроссплатформенной сборке собрать инсталлятор. Будут ли NSIS или Inno Setup нормально работать под wine?
0
Caiiiycuk #
Nsis 100% нормально работает под wine, мы как раз им собираем установщик для win версии. Главное кодировку nsi файла соблюсти (CP1251) и все будет хорошо.
0
Terror #
Большое Вам спасибо за статью. За что люблю Хабр, вот только озадачишься какой-нибудь темой, как какой-нибудь добрый человек, вроде Вас, напишет статью и все разжует все :)
–1
oe24 #
Почему QT Creator не компилирует приложения под Ubuntu? Просит компилятор. Как ему его дать?
0
cblp #
Qt Creator не является компилятором. Под какой системой ты его запускаешь? Если тоже под Ubuntu, то установи g++.
0
oe24 #
А после установки g++ как прописать его в настройках QT Creator? ОС — Ubuntu.
0
cblp #
Теоретически должен сам подхватить. Если нет, смотри в терминале пути к программам и вписывай.

Например, вот так можно посмотреть пути к g++ и make:
cblp@helium:~$ which g++
/usr/bin/g++
cblp@helium:~$ which make
/usr/bin/make
0
AlexZaharow #
либо скомпилировать их с помощью кросс-компиляции из исходников (что, как мне кажется, будет очень не просто)


Ух сколько я потратил на это времени… но собрал, но без phonon'а, к сожалению. Мда, в самом деле — не просто. Потом в справочной системе прочитал, что phonon под mingw не собирается. Windows SDK ему подавай.

0
AlexZaharow #
А кто-нибудь собирал cross gcc x86-64 -> i686?

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.