Цель статьи


Документирование получения системы кросс-компиляции под Linux для Windows x32/x64/static/shared и сборка последней на момент описания Qt 5.4.1 в лайт-версии (для указанных четырех целей). Для себя, глубоко-обожаемого, ну и для пользы обществу.

Назначение


Многие разработчики приходят к выводу, что использование *nix (в частности Linux) более предпочтительно для разработки приложений, используя фрэймворк Qt. И тому есть причины. Qt изначально ориентирована на *nix инструментарий, типа autotool, make, perl… И второй момент, под никсами есть прекрасный инструмент — valgrind, под виндой порта пока его не видел. Ну и последняя причина: просто удобно иметь набор инструментария для создания приложений под различные целевые платформы — в одном месте.

Почему лайт-версия Qt5


Фрэймворк-Qt имеет модульную структуру, но, увы, не совсем совершенную. Некоторые зависимости от внешних библиотек «вешаются» не на модуль, требующий эти библиотеки, а на Qt5Core. Иными словами, нужна вам эта библиотека, или нет — вынь да положЪ в дистрибутив. Пример тому «монстрик» — библиотека ICU. Весит она почти 25 метров! Зависимость вешается, как я упоминал выше, на Qt5Core… а требует ее модуль Qt5WebKit (который по сути в 99% случаев не используется, по крайней мере мной). Что делаем? Вырезаем и отрезаем. Хотите получить фулл-версию Qt5? Об этом упомяну в заключении. Поехали.

0. Сценарий сборки


Все шаги делаем последовательно. Желательно не объединять все скрипты в последовательную сборку по причине необходимости промежуточного «человечного» контроля. Разные дистрибутивы Линуха, разные среды исполнения, наборы инструментариев… Простой алгоритм: сделал очередной шаг, убедился в отсутствии ошибок, пошел делать следующий. Итак, сам сценарий:

  • 1. Предварительная подготовка
  • 2. Установка среды кросс-компиляции MXE
  • 3. Загрузка и настройка Qt 5.4.1
  • 4. Сборка комплектов Qt 5.4.1 для четырех целей (см. сабж)
  • 5. Прописка собранного в QtCreator


1. Предварительная подготовка


У вас установлен дистрибутив Линукса. Желательно все это делать на на продакшен-компе (не на живом Линуксе), а установленном в виртуальную машину. Я например, пользуюсь VMWare, но это дело вкуса. Выбор дистрибутива Линукса — так же дело вкуса. Лично я предпочитаю Gentoo Linux, собственно под ним всю эту кухню и настраиваю. Если есть сложности в настройке, у меня есть небольшая статейка по этому вопросу: «Установка и настройка Linux Gentoo под VMWare».

Итак, у вас есть настроенный Линукс и вы работаете не под рутом! Для дальнейшей работы вам нужно проверить присутствие следующих установленных пакетов, или доустановить:

$ sudo emerge app-arch/bzip2 app-arch/unzip app-arch/xz-utils app-shells/bash dev-lang/ruby dev-libs/libffi dev-libs/openssl dev-perl/XML-Parser dev-util/cmake dev-util/intltool dev-util/pkgconfig dev-util/scons dev-vcs/git sys-devel/autoconf sys-devel/automake sys-devel/bison sys-devel/flex sys-devel/gettext sys-devel/libtool sys-devel/patch net-misc/ntp www-client/lynx

Вся дальнейшая установка будет производиться в каталог $HOME/dev. Если у вас таковой присутствует — либо переименовываете его, либо внимательно правите скрипты, которые будут приведены далее. Для всех манипуляций со скачиваемыми внешними файлами/скриптами/библиотеками будет использован каталог $HOME/setup. Все замечания выше относительно $HOME/dev — в силе и к этому каталогу.

2. Установка среды кросс-компиляции MXE


Предварительное замечание об MXE. Это отличнейшая система сборки тулчейнов для кросс-компиляции. Но есть одно «но». В данный момент не существует стабильной ветки. Авторы до поры до времени вели две ветки в своем git-репозитарии — стабильную и «разработческую». Сейчас ветки объединены. Разработка идет ну очень активно — изменения сбрасываются чуть ли не раз 1-3 дня. А это чревато тем, что «то работает сборка, то не работает». Некоторые важные для меня библиотеки, в частности клиентская часть PostgreSQL, собираются без ошибок, но в нерабочем состоянии. Потратил неделю не исследование явных косяков. Исправляем эти «недочеты». Итак:

$ mkdir -p $HOME/setup
$ cd $HOME/setup
$ wget http://majestio.tk/stuff/setup-scripts.tar.xz
$ tar -xf setup-scripts.tar.xz
$ rm -f setup-scripts.tar.xz

Должны получить в каталоге $HOME/setup следующий набор скриптов:

1.setup-first.sh
#!/bin/sh

###########################################################################
##                                                                       ## 
## Скрипт 1. Создание структуры каталогов для разворачивания системы     ##
##           кросс-компиляции средствами MXE (http://mxe.cc),            ##
##           собственно загрузку и первоначальную сборку                 ##
##                                                                       ## 
##                                       Majestio (C) http://majestio.tk ##    
###########################################################################

#
# Порядок установки:
#
# 1. Создать в $HOME подкаталог, например $HOME/Setup 
# 2. Скопировать туда этот скрипт и запустить
# 3. Дождаться завершения
# 
# Структура подкаталогов будет в $HOME/dev
# Набор тулчейнов MXE ищем в $HOME/dev/cross/mxe
#
# .........................................................................

if [ "$(whoami)" == 'root' ]; then 
  echo "Ахтунг: под учетной записью рута работать отказываюсь!" 
  exit 1 
fi

RETDIR=`pwd`
MXEHOME=$HOME/dev/cross/mxe

# создаем структуру каталогов и вынимаем MXE из git-репозитария -----------

mkdir -p $HOME/dev/{cross,projests,src,stuff,tools}
cd $HOME/dev/cross

#    можно так: 
# git clone https://github.com/mxe/mxe.git
#    но лучше так:
# wget http://majestio.tk/stuff/mxe-empty-26.05.2015.tar.xz
# tar -xf mxe-empty-26.05.2015.tar.xz
# rm -f mxe-empty-26.05.2015.tar.xz

wget http://majestio.tk/stuff/mxe-empty-26.05.2015.tar.xz
tar -xf mxe-empty-26.05.2015.tar.xz
rm -f mxe-empty-26.05.2015.tar.xz

# патчим файлик определения ABI проекта MXE -------------------------------

echo "#!/bin/sh" > $HOME/dev/cross/mxe/ext/config.guess
echo "echo \"x86_64-pc-linux-gnu\"" >> $HOME/dev/cross/mxe/ext/config.guess

# делаем первоначальную сборку MXE с типом нитей win32 --------------------

cd $MXEHOME
make MXE_TARGETS='x86_64-w64-mingw32.shared '`   
                `'x86_64-w64-mingw32.static '`  
                `'i686-w64-mingw32.shared '`    
                `'i686-w64-mingw32.static ' gcc gmp winpthreads -j4 JOBS=4

# патчим mxe/src/gcc.mk на предмет добавления posix-threads ---------------

GCCMK=$MXEHOME/src/gcc.mk
PLTMP=$$-$RANDOM.pl
echo "open(F,\"$GCCMK\") || die \"Holy shit!\\n\";"                                                 >  $PLTMP
echo "@In = <F>;"                                                                                   >> $PLTMP
echo "close(F);"                                                                                    >> $PLTMP
echo "open(F,\">$GCCMK\") || die \"Holy shit!\\n\";"                                                >> $PLTMP
echo "foreach \$I(@In) {"                                                                           >> $PLTMP
echo "  \$I =~ s/^(\\\$\(PKG\)_DEPS.+)\$/\$1 winpthreads/;"                                         >> $PLTMP
echo "  \$I =~ s/^(.+?--libdir='\\\$\(PREFIX\).+)\$/\$1\n        --enable-shared=libstdc\+\+ \\\/;" >> $PLTMP
echo "  \$I =~ s/^(.+?--enable-threads=)win32(.*)\$/\$1posix\$2/;"                                  >> $PLTMP
echo "  print F \$I;"                                                                               >> $PLTMP
echo "}"                                                                                            >> $PLTMP
echo "close(F);"                                                                                    >> $PLTMP
perl $PLTMP && rm -f $PLTMP

# пересобираем GCC с поддержкой posix-threads -----------------------------

cd $MXEHOME
make MXE_TARGETS='x86_64-w64-mingw32.shared '`   
                `'x86_64-w64-mingw32.static '`  
                `'i686-w64-mingw32.shared '`    
                `'i686-w64-mingw32.static ' gcc -j4 JOBS=4

# делаем промежуточный архив "пустой" системы кросс-компиляции ------------

echo "Делаем промежуточную архивацию ..."
cd ..           
tar -cJf mxe-winpthreads-empty.tar.xz ./mxe

# собираем дополнительные либы --------------------------------------------

cd $MXEHOME
make MXE_TARGETS='x86_64-w64-mingw32.shared '`   
                `'x86_64-w64-mingw32.static '`  
                `'i686-w64-mingw32.shared '`    
                `'i686-w64-mingw32.static ' zlib xz sqlite dbus                 libiconv libodbc++ -j4 JOBS=4

# патчим и собираем PostgreSQL --------------------------------------------

cd $MXEHOME/src
wget http://majestio.tk/stuff/postgresql-3-socket.patch
PQSQL=$MXEHOME/src/postgresql.mk
PLTMP=$$-$RANDOM.pl
echo "open(F,\"$PQSQL\") || die \"Holy shit!\\n\";"                                                 >  $PLTMP
echo "@In = <F>;"                                                                                   >> $PLTMP
echo "close(F);"                                                                                    >> $PLTMP
echo "open(F,\">$PQSQL\") || die \"Holy shit!\\n\";"                                                >> $PLTMP
echo "foreach \$I(@In) {"                                                                           >> $PLTMP
echo "  \$I =~ s/^(.+?--disable-rpath.+)\$/\$1\n        --disable-thread-safety \\\/;"              >> $PLTMP
echo "  print F \$I;"                                                                               >> $PLTMP
echo "}"                                                                                            >> $PLTMP
echo "close(F);"                                                                                    >> $PLTMP
perl $PLTMP && rm -f $PLTMP

cd $MXEHOME
make MXE_TARGETS='x86_64-w64-mingw32.shared '`   
                `'x86_64-w64-mingw32.static '`  
                `'i686-w64-mingw32.shared '`    
                `'i686-w64-mingw32.static ' postgresql -j4 JOBS=4

for PREFIX in "x86_64-w64-mingw32.shared" "x86_64-w64-mingw32.static"               "i686-w64-mingw32.shared" "i686-w64-mingw32.static" ; do 
   echo "Description: PostgreSQL libpq library" > $MXEHOME/usr/$PREFIX/lib/pkgconfig/libpq.pc
   echo "Url: http://www.postgresql.org/" >> $MXEHOME/usr/$PREFIX/lib/pkgconfig/libpq.pc
   echo "Version: 9.2.4" >> $MXEHOME/usr/$PREFIX/lib/pkgconfig/libpq.pc
   echo "Requires: " >> $MXEHOME/usr/$PREFIX/lib/pkgconfig/libpq.pc
   echo "Requires.private: " >> $MXEHOME/usr/$PREFIX/lib/pkgconfig/libpq.pc
   echo "Cflags: -I$MXEHOME/usr/$PREFIX/include" >> $MXEHOME/usr/$PREFIX/lib/pkgconfig/libpq.pc
   echo "Libs: -L$MXEHOME/usr/$PREFIX/lib -lpq" >> $MXEHOME/usr/$PREFIX/lib/pkgconfig/libpq.pc
   echo "Libs.private:  -lssl -lcrypto -lshell32 -lwsock32 -lws2_32 -lsecur32" >> $MXEHOME/usr/$PREFIX/lib/pkgconfig/libpq.pc
   chmod 0644 $MXEHOME/usr/$PREFIX/lib/pkgconfig/libpq.pc
done

cd $RETDIR        

2.setup-qt5.sh
#!/bin/sh

###########################################################################
##                                                                       ## 
## Скрипт 2. Выкачка Qt 5.4.1 + небольшие косметические правки           ##
##                                                                       ## 
##                                       Majestio (C) http://majestio.tk ##    
###########################################################################

#
# Порядок установки:
#
# 1. Зайти в каталог установки $HOME/Setup
# 2. Скопировать туда этот скрипт и запустить
# 3. Дождаться завершения
# 
# На выходе будет каталог qt5
#

# -------------------------------------------------------------------------

if [ "$(whoami)" == 'root' ]; then 
  echo "Ахтунг: под учетной записью рута работать отказываюсь!" 
  exit 1 
fi

wget http://download.qt.io/official_releases/qt/5.4/5.4.1/single/qt-everywhere-opensource-src-5.4.1.tar.gz
tar -xf qt-everywhere-opensource-src-5.4.1.tar.gz
mv qt-everywhere-opensource-src-5.4.1 qt5
cd qt5/qtbase/mkspecs
wget http://majestio.tk/stuff/win32-g++.static.tar.xz
tar -xf win32-g++.static.tar.xz
rm -f win32-g++.static.tar.xz
cd ../..
wget http://majestio.tk/stuff/qt-5.4.1.patch
patch -p1 -u < qt-5.4.1.patch
rm -f qt-5.4.1.patch
cd ..

3.1.build-qt-x32-shared.sh
#!/bin/sh

###########################################################################
##                                                                       ## 
## Скрипт 3.1 Создание сборки Qt 5.4.1 для Win x32 (shared)              ##
##                                                                       ## 
##                                       Majestio (C) http://majestio.tk ##    
###########################################################################

#
# Порядок установки:
#
# 1. Зайти в каталог установки $HOME/Setup
# 2. Скопировать туда этот скрипт и запустить
# 3. Дождаться завершения
# 
# На выходе будет готовая сборка, размещенная в %HOME/dev/stuff
#

# -------------------------------------------------------------------------

if [ "$(whoami)" == 'root' ]; then 
  echo "Ахтунг: под учетной записью рута работать отказываюсь!" 
  exit 1 
fi

TARGET="i686-w64-mingw32.shared"
MXE="$HOME/dev/cross/mxe/usr"
PREFIX="$HOME/dev/stuff/qt5-$TARGET"
export PATH=$MXE/bin:$PATH

PWD="`pwd`"
LOG="$PWD/$TARGET-qt5.log___________"

mkdir "$TARGET-qt5.build"
cd "$TARGET-qt5.build"

clear

OPENSSL_LIBS="`''"$TARGET"'-pkg-config' --libs-only-l openssl`" PSQL_LIBS="-lpq -lsecur32 `''"$TARGET"'-pkg-config' --libs-only-l openssl` -lws2_32" ../qt5/configure -prefix $PREFIX -opensource -confirm-license -release -shared -opengl desktop -force-pkg-config -no-use-gold-linker -no-glib -openssl -dbus -plugin-sql-psql -plugin-sql-sqlite -plugin-sql-odbc -qt-libpng -qt-libjpeg -qt-pcre -zlib -qt-freetype -no-kms -no-pch -nomake examples -nomake tests -silent -skip webkit -xplatform win32-g++ -device-option CROSS_COMPILE=$TARGET- -device-option PKG_CONFIG="$TARGET-pkg-config" 2>&1 | tee $LOG
make -j4 2>&1 | tee -a $LOG
make install 2>&1 | tee -a $LOG

3.2.build-qt-x32-static.sh
#!/bin/sh

###########################################################################
##                                                                       ## 
## Скрипт 3.2 Создание сборки Qt 5.4.1 для Win x32 (static)              ##
##                                                                       ## 
##                                       Majestio (C) http://majestio.tk ##    
###########################################################################

#
# Порядок установки:
#
# 1. Зайти в каталог установки $HOME/Setup
# 2. Скопировать туда этот скрипт и запустить
# 3. Дождаться завершения
# 
# На выходе будет готовая сборка, размещенная в %HOME/dev/stuff
#

# -------------------------------------------------------------------------

if [ "$(whoami)" == 'root' ]; then 
  echo "Ахтунг: под учетной записью рута работать отказываюсь!" 
  exit 1 
fi

TARGET="i686-w64-mingw32.static"
MXE="$HOME/dev/cross/mxe/usr"
PREFIX="$HOME/dev/stuff/qt5-$TARGET"

PWD="`pwd`"
LOG="$PWD/$TARGET-qt5.log___________"

mkdir "$TARGET-qt5.build"
cd "$TARGET-qt5.build"
clear

export PATH=$MXE/bin:$PATH
#../qt5/configure --help|less
#exit
OPENSSL_LIBS="`''"$TARGET"'-pkg-config' --libs-only-l openssl`" PSQL_LIBS="-lpq -lsecur32 `''"$TARGET"'-pkg-config' --libs-only-l openssl` -lws2_32" ../qt5/configure -prefix $PREFIX -opensource -confirm-license -release -static -opengl desktop -force-pkg-config -no-use-gold-linker -no-glib -openssl-linked -dbus-linked -qt-sql-psql -qt-sql-sqlite -qt-sql-odbc -qt-libpng -qt-libjpeg -qt-pcre -zlib -qt-freetype -no-kms -no-pch -nomake examples -nomake tests -silent -skip webkit -xplatform win32-g++ -device-option CROSS_COMPILE=$TARGET- -device-option PKG_CONFIG="$TARGET-pkg-config" 2>&1 | tee $LOG
make -j4 2>&1 | tee -a $LOG
make install 2>&1 | tee -a $LOG

3.3.build-qt-x64-shared.sh
#!/bin/sh

###########################################################################
##                                                                       ## 
## Скрипт 3.3 Создание сборки Qt 5.4.1 для Win x64 (shared)              ##
##                                                                       ## 
##                                       Majestio (C) http://majestio.tk ##    
###########################################################################

#
# Порядок установки:
#
# 1. Зайти в каталог установки $HOME/Setup
# 2. Скопировать туда этот скрипт и запустить
# 3. Дождаться завершения
# 
# На выходе будет готовая сборка, размещенная в %HOME/dev/stuff
#

# -------------------------------------------------------------------------

if [ "$(whoami)" == 'root' ]; then 
  echo "Ахтунг: под учетной записью рута работать отказываюсь!" 
  exit 1 
fi

TARGET="x86_64-w64-mingw32.shared"
MXE="$HOME/dev/cross/mxe/usr"
PREFIX="$HOME/dev/stuff/qt5-$TARGET"
export PATH=$MXE/bin:$PATH

PWD="`pwd`"
LOG="$PWD/$TARGET-qt5.log___________"

mkdir "$TARGET-qt5.build"
cd "$TARGET-qt5.build"

clear

OPENSSL_LIBS="`''"$TARGET"'-pkg-config' --libs-only-l openssl`" PSQL_LIBS="-lpq -lsecur32 `''"$TARGET"'-pkg-config' --libs-only-l openssl` -lws2_32" ../qt5/configure -prefix $PREFIX -opensource -confirm-license -release -shared -opengl desktop -force-pkg-config -no-use-gold-linker -no-glib -openssl -dbus -plugin-sql-psql -plugin-sql-sqlite -plugin-sql-odbc -qt-libpng -qt-libjpeg -qt-pcre -zlib -qt-freetype -no-kms -no-pch -nomake examples -nomake tests -silent -skip webkit -xplatform win32-g++ -device-option CROSS_COMPILE=$TARGET- -device-option PKG_CONFIG="$TARGET-pkg-config" 2>&1 | tee $LOG
make -j4 2>&1 | tee -a $LOG
make install 2>&1 | tee -a $LOG

3.4.build-qt-x64-static.sh
#!/bin/sh

###########################################################################
##                                                                       ## 
## Скрипт 3.4 Создание сборки Qt 5.4.1 для Win x64 (static)              ##
##                                                                       ## 
##                                       Majestio (C) http://majestio.tk ##    
###########################################################################

#
# Порядок установки:
#
# 1. Зайти в каталог установки $HOME/Setup
# 2. Скопировать туда этот скрипт и запустить
# 3. Дождаться завершения
# 
# На выходе будет готовая сборка, размещенная в %HOME/dev/stuff
#

# -------------------------------------------------------------------------

if [ "$(whoami)" == 'root' ]; then 
  echo "Ахтунг: под учетной записью рута работать отказываюсь!" 
  exit 1 
fi

TARGET="x86_64-w64-mingw32.static"
MXE="$HOME/dev/cross/mxe/usr"
PREFIX="$HOME/dev/stuff/qt5-$TARGET"

PWD="`pwd`"
LOG="$PWD/$TARGET-qt5.log___________"

mkdir "$TARGET-qt5.build"
cd "$TARGET-qt5.build"
clear

export PATH=$MXE/bin:$PATH
#../qt5/configure --help|less
#exit
OPENSSL_LIBS="`''"$TARGET"'-pkg-config' --libs-only-l openssl`" PSQL_LIBS="-lpq -lsecur32 `''"$TARGET"'-pkg-config' --libs-only-l openssl` -lws2_32" ../qt5/configure -prefix $PREFIX -opensource -confirm-license -release -static -opengl desktop -force-pkg-config -no-use-gold-linker -no-glib -openssl-linked -dbus-linked -qt-sql-psql -qt-sql-sqlite -qt-sql-odbc -qt-libpng -qt-libjpeg -qt-pcre -zlib -qt-freetype -no-kms -no-pch -nomake examples -nomake tests -silent -skip webkit -xplatform win32-g++ -device-option CROSS_COMPILE=$TARGET- -device-option PKG_CONFIG="$TARGET-pkg-config" 2>&1 | tee $LOG
make -j4 2>&1 | tee -a $LOG
make install 2>&1 | tee -a $LOG


Скрипты не будут иметь атрибута «исполняемый» просто в целях безопасности — предотвращения «непреднамеренного случайного» запуска. Запускаем первый скрипт 1.setup-first.sh. Он создаст структуру подкаталогов $HOME/dev…, выкачает систему кросс-компиляции mxe, делает двойную сборку gcc тулчейнов (для обеспечения поддержки posix-threads), соберет основные базовые библиотеки, пропатчит и соберет клиентскую часть библиотеки PostgreSQL.

Важно: Если ваша хостовая система по ABI отличается от «x86_64-pc-linux-gnu», в скрипте вручную удалите патч ABI. Ищем по комментарию "# патчим файлик определения ABI проекта MXE". А лучше пропишете ваш.

$ sh 1.setup-first.sh

3. Загрузка и настройка Qt 5.4.1


Запускаем скрипт 2.setup-qt5.sh. Его задача выкачать исходники Qt 5.4.1, развернуть их в подкаталог qt5/ и пропатчить нужное.

$ sh 2.setup-qt5.sh


4. Сборка комплектов Qt 5.4.1 для четырех целей


Для, собственно, сборки четырех видов Qt 5.4.1 предназначены остальные скрипты:

  • 3.1.build-qt-x32-shared.sh
  • 3.2.build-qt-x32-static.sh
  • 3.3.build-qt-x64-shared.sh
  • 3.4.build-qt-x64-static.sh


Запуск производиться точно так же как и в предыдущем пункте:

$ sh скрипт

Однако есть важное замечание, могущее помочь вам сэкономить время на сборку. Если у вас многоядерный компьютер — имеет смысл запускать сборки параллельно. Для этого вы открываете второй(третий, четвертый) терминал, и в терминале запускаете очередной скрипт. Лично мне удобно все действия проводить в дополнительном ssh-клиенте. Как показала практика, на моем Core i7 (4 ядра, с гипертрейдингом) — прирост общего времени сборки наблюдается при двух параллельно работающих сборках. Если более — производительность не возрастает, а чаще всего падает.

Итак, все четыре скрипта отработали. Что мы получили в результате?

$HOME/dev/cross/mxe/usr/bin — тут собраны исполняемые модули всех четырех тулчейнов
$HOME/dev/cross/mxe/usr/тулчейн — тут собраны заголовки и либы тулчейнов
$HOME/dev/stuff/сборки — тут собраны все виды Qt для последующей кросс-компиляции

Осталось все это подключить к использованию.

5. Прописка собранного в QtCreator


Самостоятельно выкачиваете Qt 5.4.1 для вашего линуха (ссылка на x32 или x64), самостоятельно производите установку. Проверяете работоспособность.

После этого регистрируете собранное вами. Открываем QtCreator, выбираем в главном меню «Инструменты» > «Параметры» > «Сборка и запуск». Далее, вся регистрация предусматривает три шага:

1) Регистрация компиляторов (Закладка «Компиляторы»)
2) Регистрация профилей Qt (Закладка «Профили Qt»)
3) Регистрация комплектов (Закладка «Комплекты»)

Шаг-1

Добавляя очередной компилятор, выбирайте тип «Особый». Нужный компилятор ищем в $HOME/dev/cross/mxe/usr/bin типа bla-bla-bla-g++. Ниже указываем путь к системной утилите make, типа /usr/bin/make. Далее выставляем ABI. Если выбрали static-версию, внизу добавьте mkspec — «win32-g++.static» (без кавычек). Остальные поля несущественны. Зарегали все четыре вида компиляторов, нажимаем «Применить»

Шаг-2

Переключаемся на закладку «Профили Qt». Добавляя профили ищем их в $HOME/dev/stuff/bla-bla-bla/bin/qmake. Зарегали все четыре профиля, нажимаем «Применить»

Шаг-3

Переключаемся на закладку «Комплекты». Добавляем очередной комплект, выбирая нужный компилятор + профиль Qt. В комплектах, где статическая сборка желательно прописать и mkspecs как на шаге-1. Зарегали все четыре комплекта, нажимаем «Применить»

Заключение


Вполне отдаю себе отчет — собранное может содержать определенные ошибки, т.к. собиралось далеко не автором ни Qt, ни PostgreSQL, даже не участником проекта MXE. Да и отсутствие простейших проверок во время сборки, не говоря уж о юнит-тестах, предполагает, что вы осознаете «сырость» сделанного. Тем не менее, после получения данного набора тулчейнов, я протестировал свои проекты, примеры из поставки Qt. В интересующих меня модулях (UI, PostgreSQL, http, QtScript, и ряда других) ошибок не обнаружил.

… Обещанное про фулл-сборку. Если вам очень повезет, и MXE, на момент вашего интереса будет в стабильном состоянии, получить фулл сборку очень просто:

$ mkdir -p $HOME/dev/{cross,src,stuff,projects}
$ cd $HOME/dev/cross
$ git clone https://github.com/mxe/mxe.git
$ make MXE_TARGETS='x86_64-w64-mingw32.shared' gcc -j4 JOBS=4
$ make MXE_TARGETS='x86_64-w64-mingw32.static' gcc -j4 JOBS=4
$ make MXE_TARGETS='i686-w64-mingw32.shared' gcc -j4 JOBS=4
$ make MXE_TARGETS='i686-w64-mingw32.static' gcc -j4 JOBS=4
#
# чтобы PostgreSQL-либа была рабочей - положите в каталог $HOME/dev/cross/mxe/src 
# патчик, полученный из http://majestio.tk/stuff/postgresql-3-socket.patch
#
$ make MXE_TARGETS='x86_64-w64-mingw32.shared' qt5 -j4 JOBS=4
$ make MXE_TARGETS='x86_64-w64-mingw32.static' qt5 -j4 JOBS=4
$ make MXE_TARGETS='i686-w64-mingw32.shared' qt5 -j4 JOBS=4
$ make MXE_TARGETS='i686-w64-mingw32.static' qt5 -j4 JOBS=4

Вангую, по этому варианту сборки вас ждет разочарование с вероятностью 87.14%, но если все будет без косяков, то полученные сборки Qt5 будут размещены в $HOME/dev/cross/mxe/usr/<тулчейн>/qt5

Всем удачного кодинга.

Комментарии (33)


  1. RPG18
    27.05.2015 18:50
    -1

    С ICU вы не правы.


    1. splav_asv
      27.05.2015 21:43
      +1

      По вашей ссылке:

      The decision to no longer use ICU was made as a result of discussions at QtCS and on the development list.


    1. Majestio Автор
      28.05.2015 13:09

      Возможно. До некоторого времени было именно так, как я написал в статье. Возможно я не ознакомился с «новостями»


  1. slonopotamus
    27.05.2015 20:02
    +3

    Предварительное замечание об MXE. Это отличнейшая система сборки тулчейнов для кросс-компиляции.


    Чем она лучше по сравнению с crossdev, раз уж вы говорите про Gentoo? crossdev позволяет сказать «crossdev x86_64-pc-mingw32» и получить на выходе готовый тулчейн. Причем без скачивания подозрительный shell-скриптов и с регистрацией в системном менеджере пакетов (что позволяет безнапряжно обновлять/удалять тулчейны). Куда отличнее-то?


    1. EXL
      28.05.2015 00:55
      +1

      Ещё напомню про такую вещь, как crosstool-ng, хорошая альтернатива MXE, если вы используете дистрибутив отличный от Gentoo.


    1. Majestio Автор
      28.05.2015 13:11
      +1

      Она лучше crossdev тем, что уже имеет набор пропатченных и проверенных конфигураций сборки различных сторонних библиотек. Ели я не ошибаюсь, пользуя crossdev, вы сами должны заниматься конфигурацией и поиском нужных патчей. А тут все «из коробки». Это, имхо, удобнее.


    1. Gorthauer87
      28.05.2015 13:22
      +1

      С помощью crossdev можно собирать штуки уровня zlib, он вообще не пригоден для сборки mingw окружения.


  1. DaylightIsBurning
    27.05.2015 20:08
    +4

    Какое-то время мучился с крос-компиляцией, пробуя и ручную сборку всего и вся, MXE, сборку всего под виндой отдельно. Остановился на очень простом, легко настраиваемом (10 минут) и хорошо расширяемом (а если нужны другие библиотеки...) варианте: Arch Linux MinGW-w64 repository. Под арчем процесс кросс-компиляции под винду упрощается донемогу.
    Установка тулкита:

    • Установить Arch Linux на ВМ (например). Если вручную лень, есть Evo/Lution.
    • Добавить MinGW-w64 repository.
    • Установить нужные библиотеки (доступно 419 готовых пакетов) с суффиксом -mingw-w64. Например так:
      pacman -S mingw-w64-qt5-base mingw-w64-cmake mingw-w64-zlib mingw-w64-openssl mingw-w64-boost
    • Профит!

    Дальше можно собирать нужные проекты так:
    x86_64-w64-mingw32-cmake ..
    make
    или так:
    x86_64-w64-mingw32-qmake-qt5
    make

    И всё, остаётся только задеплоить нужные dll-ки из /usr/x86_64-w64-mingw32/bin/


    1. DeXPeriX
      27.05.2015 21:21
      +1

      Спасибо огромное за информацию! Так гораздо удобнее.


    1. yanchick
      28.05.2015 07:04
      +3

      а подобное под apt-get не встречали?


      1. monah_tuk
        28.05.2015 10:35
        +1

        Чем мне до сих пор нравится Арч, так это простотой создания пакетов. Для Deb нашёл только launchpad.net/~tobydox/+archive/ubuntu/mingw-x-trusty для ванильного Debian вообще как-то пусто.


        1. DaylightIsBurning
          28.05.2015 10:43

          это уже что-то. Шаг в нужном направлении, но готовых пакетов слишком мало, даже буста нет :(.


      1. DaylightIsBurning
        28.05.2015 10:40
        +1

        К большому моему сожалению, для deb подобных репозиториев отыскать не удалось.


    1. Gorthauer87
      28.05.2015 13:26

      Кстати, а в mxe был скрипт для автодеплоя либ, но он почему-то работал лишь для i686, но не очень сложно его можно навелосипедить поверх objdump, который умеет pe заголовки.


  1. Sap_ru
    28.05.2015 01:18

    Но оно же отлично собирается без ICU! Там и ключик в configure указан. Всё будет работать, но WebKit, да, не удастся собрать без ICU. Собрал, вот себе под Linux без всяких ICU — всё работает. Или это только для сборки под Win?


    1. Majestio Автор
      28.05.2015 13:15

      В статье я указал именно сборку Qt5 используя MXE. А там, если просто указать цель qt5 — соберется абсолютно все. Внизу статьи есть пример этому. Поэтому Qt5 я собирал вручную, и только то, что мне было нужно.


  1. EXL
    28.05.2015 03:25
    +7

    Спасибо за информацию. Я статический Qt 5 (мне нужны были только QtWidgets) собирал для Windows прямо в Windows, не было под рукой машинки с дистрибутивом GNU/Linux (даже виртуальной).

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

    Необходимо следующее:

    1. MinGW-w64 32-bit.
      Идеальный вариант — использовать тот, что идёт в бандле Qt 5 с MinGW под Windows, наверняка этот бандл у вас уже установлен. Если нет — не забудьте отметить инструментарий MinGW при установке.
    2. Python 2.x.x.
      Он потребуется системе сборки Qt для генерации некоторых заголовочных файлов. Я использовал Python версии 2.7.9.
    3. Исходники Qt 5.


    И в принципе, для Qt Widgets и QtQuick этого более чем достаточно. Далее устанавливаем Python и распаковываем архив с исходниками в удобное для сборки место. Выше по уровню создаём директорию build-Qt5-static, картина должна быть такая:

    build_place/                                # Удобное для сборки место
       |
       +---build-Qt5-static                     # Тут каталог для сборки
       |
       +---qt-everywhere-opensource-src-5.4.1   # Тут исходники Qt
    


    Для того, чтобы каталог с исходниками остался чистым и можно было легко переконфигурировать Qt5 при какой-либо ошибке, лучше всего использовать теневую сборку (это когда сборка осуществляется за пределами каталога с исходным кодом), благо система сборки Qt её поддерживает.

    Здесь есть важный момент. Если вы хотите, чтобы исполнительны файлы ваших приложений были полностью статические и автономные, то вам необходимо отредактировать файл qt-everywhere-opensource-src-5.4.1/qtbase/mkspecs/win32-g++/qmake.conf следующим образом:

    diff -Naur qt-everywhere-opensource-src-5.4.1.orig/qtbase/mkspecs/win32-g++/qmake.conf qt-everywhere-opensource-src-5.4.1/qtbase/mkspecs/win32-g++/qmake.conf
    --- qt-everywhere-opensource-src-5.4.1.orig/qtbase/mkspecs/win32-g++/qmake.conf	2013-06-07 12:17:00 +0700
    +++ qt-everywhere-opensource-src-5.4.1/qtbase/mkspecs/win32-g++/qmake.conf	2013-08-29 23:40:45 +0700
    @@ -15,7 +15,7 @@
     TEMPLATE		= app
     CONFIG			+= qt warn_on release link_prl copy_dir_files debug_and_release debug_and_release_target precompile_header
     QT			+= core gui
    -DEFINES		+= UNICODE
    +DEFINES		+= UNICODE QT_STATIC_BUILD
     QMAKE_COMPILER_DEFINES  += __GNUC__ WIN32
     
     QMAKE_EXT_OBJ           = .o
    @@ -32,7 +32,7 @@
     QMAKE_CFLAGS_DEPS	= -M
     QMAKE_CFLAGS_WARN_ON	= -Wall -Wextra
     QMAKE_CFLAGS_WARN_OFF	= -w
    -QMAKE_CFLAGS_RELEASE	= -O2
    +QMAKE_CFLAGS_RELEASE	= -O2 -Os
     QMAKE_CFLAGS_DEBUG	= -g
     QMAKE_CFLAGS_YACC	= -Wno-unused -Wno-parentheses
     
    @@ -70,7 +70,7 @@
     
     QMAKE_LINK		= $${CROSS_COMPILE}g++
     QMAKE_LINK_C		= $${CROSS_COMPILE}gcc
    -QMAKE_LFLAGS		=
    +QMAKE_LFLAGS		= -static -static-libgcc -static-libstdc++
     QMAKE_LFLAGS_EXCEPTIONS_ON = -mthreads
     QMAKE_LFLAGS_EXCEPTIONS_OFF =
     QMAKE_LFLAGS_RELEASE	= -Wl,-s
    

    Это «отвяжет» ваши исполнительные файлы от таких библиотек, как:

    • libgcc_s_dw2-1.dll
    • libstdc++-6.dll
    • libwinpthread-1.dll

    Так как они будут влинкованы статически. На выходе получится автономный исполнительный файл, который должен запускаться и работать в любой операционной системе Windows, начиная с Windows 2000 (или XP).

    Теперь, когда всё готово к конфигурированию и компиляции, можно запускать процесс. Лично я для этого воспользовался таким вот простеньким bat-сценарием, назовём его Qt5.4.1-build-static.bat:

    SET QTDIR=D:\Dev\Toolkits\Qt\Qt5.4.1-static
    SET PATH=D:\Dev\Toolkits\Qt\Qt5.4.1\Tools\mingw491_32\bin;D:\Dev\Toolkits\Python;D:\Dev\Toolkits\Python\Scripts;%PATH%
    
    ..\qt-everywhere-opensource-src-5.4.1\configure -opensource -release -static -confirm-license -c++11 -ltcg -no-compile-examples -no-nis -no-neon -no-iconv -no-evdev -no-mtdev -no-inotify -no-eventfd -largefile -no-fontconfig -no-system-proxies -no-icu -no-freetype -no-harfbuzz -no-angle -no-incredibuild-xge -no-plugin-manifests -rtti -strip -no-ssl -no-openssl -no-dbus -no-qml-debug -audio-backend -no-directwrite -no-direct2d -no-style-fusion -no-mp -nomake examples -nomake tools -platform win32-g++ -opengl desktop -prefix %QTDIR%
    
    mingw32-make -j19
    
    mingw32-make install
    

    Объясню некоторые очевидные вещи. Переменная окружения QTDIR определяет то, куда будет установлен наш статически собранный Qt 5; исправьте эту переменную в соответствии со своими предпочтениями. Переменная окружения PATH задаёт путь до исполнительных файлов инструментария MinGW-w64 (компиляторы, линковщики, архиваторы и прочие утилиты), кроме того, в PATH определён путь до установленного Python и его скриптов. Задайте значение этой переменной в соответствии с установленным в вашу систему окружением для сборки. Далее идёт длинная команда конфигурирования (список всех параметров можно посмотреть в документации или выполнив configure.bat -help), команда сборки (опция -jX используется для распараллеливания, рекомендуемое значение зависит от характеристик вашего компьютера и рассчитывается по формуле X = N + 1, где N — число ядер вашего процессора); и завершается сценарий командой установки, которая скопирует скомпилированные библиотеки и инструменты в директорию, определённую в QTDIR.

    Файл Qt5.4.1-build-static.bat, с вашими установками, кидаем в директорию build-Qt5-static и запускаем. Запускать bat-сценарий лучше всего не двойным кликом по нему, а из командной строки, чтобы иметь возможность среагировать на ошибку. Для этого: заходим с помощью проводника в директорию build-Qt5-static, и держа зажатой клавишу Shift, кликаем на пустое место в директории правой кнопкой мышки. В появившемся контекстном меню выбираем пункт «Открыть окно команд». В командной строке вводим имя bat-сценария: Qt5.4.1-build-static.bat и нажимаем клавишу Enter для запуска продолжительной процедуры сборки. Пока Qt 5 собирается можно выпить чашку кофе. Я бы даже сказал, много чашек кофе.

    Небольшой совет. Если сборка завершилась с ошибкой, а вы использовали параллельную компиляцию (mingw32-make c опцией -jX), то часто возникает ситуация, что ошибка компиляции «улетела далеко наверх» и её не видно в окне и буфере командной строки. Для того, чтобы посмотреть на чём же всё-таки прервалась компиляция, достаточно повторно запустить mingw32-make без опции -jX. Через некоторое время (когда цели mingw32-make соберутся и он перейдёт на ту, что приводит к ошибке компиляции), в выхлопе появится и досадная ошибка.

    Подробнее про сборку Qt 5 для Windows можно почитать официальную документацию и страничку в официальной Wiki.


    1. mapron
      28.05.2015 15:02

      … и естественно, для всего вышеперечисленного, нужно обладать коммерческой лицензией на Qt либо публиковать свои исходники.


      1. Majestio Автор
        28.05.2015 17:20

        Если политика лицензирования в последнее время не менялась, то коммерческая лицензия нужна только в случае статической линковки Qt


        1. mapron
          29.05.2015 08:47

          Человек, которому я отвечал, про нее и рассказывал.


          1. Majestio Автор
            29.05.2015 09:06

            Ясно, значит я перепутал, к кому было обращение


      1. Gorthauer87
        29.05.2015 09:37

        Можно обойтись объектниками, чтобы была возможность перелинковать приложение с другой версией Qt.


    1. DaylightIsBurning
      28.05.2015 17:37

      Если не секрет, что у Вас за юзкейс, что необходима статическая линковка?


      1. Majestio Автор
        28.05.2015 18:05

        Статические версии сделаны «на всякий пожарный» ) Я пользуюсь shared-сборками.


      1. EXL
        29.05.2015 16:24

        Вообще мне, как и наверняка большинству, потребовалась пересборка Qt 5 не ради статической линковки, а ради освобождения QtCore от зависимости в виде тяжёлых ICU-библиотек. Я посчитал неприемлемым то, что вместе с программой тянутся целых ~30MB библиотек, функции которых программка по сути дела вообще не использует. Ну и раз не обойтись без пересборки фреймворка, было решено попробовать ещё и статическую линковку. Утилитка (кстати OpenSource) маленькая, поэтому собирать для неё что-то вроде установщика, было бы дико. Распространение с помощью единого исполнительного файла на мой взгляд очень удобно для простенькой программы. Кстати, я заметил что статическая линковка сейчас «в моде»: некоторые популярные Qt-приложения используют именно её, например, так делают IM-мессенджер Telegram и качалка torrent'ов — qBittorrent (кстати советую, отличная штука).

        Вернёмся к ICU-библиотекам. Как оказалось, принудительная зависимость QtCore от них — это косяк билд-фермы Qt, тянущийся ещё с самого выхода Qt 5. Подробнее об этом можно почитать информацию в тикете багртрекера. В котором и пообещали исправить положение дел в будущем минорном релизе.

        Мне даже не верится, что спустя столько времени, в Qt 5.5.0 библиотека QtCore по-умолчанию наконец-то освободится от зависимости далеко не аскетичных ICU-библиотек; и они будут необходимы лишь для работы QtWebkit/QtWebEngine, как и предполагалось изначально.


        1. Majestio Автор
          30.05.2015 00:13

          Я думаю — все ж дело времени.Рано или позно, многое меняется. К примеру тренд замены OpenSSL на LibreSSL. *BSD системы осознали и начали процесс «модернизации». Надо уметь ждать :)


  1. EXL
    28.05.2015 03:36
    +2

    И ещё спрошу следующий интересующий меня момент.
    У кого имеется статическая сборка Qt 5 под Windows, ответьте пожалуйста на следующие вопросы:
    1. Зависит ли ваш исполнительный файл от таких библиотек, как:

    • libgcc_s_dw2-1.dll
    • libstdc++-6.dll
    • libwinpthread-1.dll

    ?
    2. Сколько МБ занимает у вас исполнительный файл с простой пустой формой QMainWindow и библиотеками указанными выше? Влинковать статически оные библиотеки можно добавив в ваш проектный файл строку:

    QMAKE_LFLAGS += -static -static-libgcc -static-libstdc++

    Спасибо.


    1. Majestio Автор
      28.05.2015 13:17

      Статические сборки x32/x64, сделанные по моей статье — полностью статические :) т.е.отвязаны от всех внешних библиотек, в том числе и идущих с GCC


    1. Majestio Автор
      28.05.2015 14:30
      +1

      Пустую форму не делал. Но, к примеру, калькулятор из примеров (x64,static) — весит 17 метров


      1. EXL
        29.05.2015 15:20

        Да, у меня тоже 17MB получилось. Странно то, что получилось так много. Если этот калькулятор собирать с использованием статической Qt 4, то получается всего 9МБ.


        1. Majestio Автор
          29.05.2015 18:16

          Без понятия. Все либы вроде «пострипаны», хотя нужно проверить.


  1. Paulus
    31.05.2015 03:18
    -5

    Ничего не понял :)
    Qt отлично компилируется под Win x32/x64/static/shared безо всяких линуксов.
    valgring на фоне возможностей MS Studio уныл до безобразия.
    QtCreator тоже не фонтан


  1. Majestio Автор
    31.05.2015 05:06
    +1

    Значит для вас эта статья бесполезна — постарайтесь развидеть ее :))))