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, для облегчения сборки кросс-платформенных продуктов, но это уже тема для отдельной статьи. Всем спасибо :)
    Метки:
    Поделиться публикацией
    Похожие публикации
    Комментарии 49
    • 0
      полезно. можно выкинуть винду
      • 0
        Её давно пора выкинуть! :)
        • +1
          Да дело даже не в самой винде. мы пользуемся билд-машинами… а они под винду не очень работают

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

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

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

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

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

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

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


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

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

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