📜 ⬆️ ⬇️

Cross-compiling Qt5 for Linux for Win x32 / x64 / static / shared

Purpose of the article


Documenting the cross-compilation system under Linux for Windows x32 / x64 / static / shared and building it at the time of Qt 5.4.1 description in a light version (for the four purposes). For myself, deeply adored, well, for the benefit of society.

Purpose


Many developers come to the conclusion that using * nix (in particular Linux) is more preferable for developing applications using the Qt framework. And for good reason. Qt was originally focused on * nix tools, such as autotool, make, perl ... And the second point, under the Nix, there is a great tool - valgrind , under the port's Windows, I have not yet seen it. And the last reason: it is just convenient to have a set of tools for creating applications for different target platforms - in one place.

Why light version of Qt5


The Qt framework has a modular structure, but, alas, not quite perfect. Some dependencies on external libraries are “hung” not on the module that requires these libraries, but on Qt5Core. In other words, whether you need this library or not - take it out and put it in the distribution kit. An example of this “monster” is the ICU library. It weighs almost 25 meters! The dependency hangs, as I mentioned above, on Qt5Core ... and it is required by its Qt5WebKit module (which in fact is not used in 99% of cases, at least by me). What are we doing? Cut and cut. Want to get a full version of Qt5? I will mention this in conclusion. Go.

0. Build script


All steps are done consistently. It is advisable not to combine all the scripts in a sequential assembly due to the need for intermediate "humane" control. Different Linux distributions, different execution environments, toolkits ... A simple algorithm: took another step, made sure there were no errors, went to do the next one. So, the script itself:
')


1. Preliminary preparation


You have a Linux distribution installed. It is desirable to do all this on a production computer (not on live Linux), but installed in a virtual machine. I for example, use VMWare, but this is a matter of taste. The choice of a Linux distribution is also a matter of taste. Personally, I prefer Gentoo Linux , in fact, under it all this kitchen and set up. If there are difficulties in setting up, I have a small article on this issue: "Installing and configuring Linux Gentoo under VMWare . "

So, you have a customized Linux and you are not working under the root! For further work, you need to check the presence of the following installed packages, or install it:

$ 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 

All further installation will be done in the $ HOME / dev directory . If you have one, either rename it or carefully edit the scripts that will be given below. For all manipulations with downloadable external files / scripts / libraries, the $ HOME / setup directory will be used. All comments above regarding $ HOME / dev are valid for this directory.

2. Install the MXE cross-compile environment


Preliminary note about MXE. This is an excellent cross-compilation toolchain build system. But there is one "but." There is currently no stable branch. For the time being, the authors kept two branches in their git repository - stable and “developmental”. Now the branches are merged. The development goes very well, the changes are reset almost once or again 1-3 days. And this is fraught with the fact that "the assembly works, it does not work." Some libraries that are important to me, in particular the PostgreSQL client part, are compiled without errors, but in a non-working state. Spent a week not exploring obvious shoals. We correct these "shortcomings". So:

 $ 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 

You should get the following set of scripts in the $ HOME / setup directory:

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 


The scripts will not have the attribute "executable" just for security reasons - to prevent the "unintended accidental" launch. Run the first script 1.setup-first.sh . It will create a $ HOME / dev ... subdirectory structure, deflate the mxe cross-compilation system, double-build the gcc tulcheins (to ensure posix-threads support), build the main core libraries, patch it and build the PostgreSQL library.

Important: If your ABI host system is different from x86_64-pc-linux-gnu, manually remove the ABI patch in the script. We are looking for the comment "# patch file definition of the ABI project of the MXE project". And better write yours.

 $ sh 1.setup-first.sh 

3. Download and configure Qt 5.4.1


Run the script 2.setup-qt5.sh . Its task is to download the sources of Qt 5.4.1, deploy them to the qt5 / subdirectory and patch the necessary ones.

 $ sh 2.setup-qt5.sh 


4. Build Qt 5.4.1 Kits for Four Purposes


For, in fact, the assembly of four types of Qt 5.4.1 are the rest of the scripts:



The launch is performed in the same way as in the previous paragraph:

 $ sh  

However, there is an important remark that can save you time to build. If you have a multi-core computer, it makes sense to run the assembly in parallel. To do this, you open the second (third, fourth) terminal, and launch the next script in the terminal. Personally, I find it convenient to carry out all actions in an additional ssh client. As practice has shown, on my Core i7 (4 cores, with hyper trading) - the increase in the total assembly time is observed with two concurrently working assemblies. If more - productivity does not increase, but more often it drops.

So, all four scripts have worked. What did we get as a result?

$ HOME / dev / cross / mxe / usr / bin - here are collected executable modules of all four tulcheynov
$ HOME / dev / cross / mxe / usr / tulchein - here are the headers and lines of tulcheins
$ HOME / dev / stuff / builds - here are collected all kinds of Qt for further cross-compiling

It remains to connect all this to use.

5. Registration collected in QtCreator


You independently download Qt 5.4.1 for your linux (link to x32 or x64 ), do the installation yourself. Check the performance.

After that register collected by you. Open QtCreator, select in the main menu “Tools” ► “Options” ► “Build and Run”. Further, the entire registration involves three steps:

1) Registration of compilers (“Compilers” tab)
2) Registration of Qt profiles (Qt Profiles tab)
3) Registration of kits (“Kits” tab)

Step 1

When adding another compiler, choose the type “Special”. We are looking for the necessary compiler in $ HOME / dev / cross / mxe / usr / bin of type bla-bla-bla-g ++. Below we specify the path to the system make utility, such as / usr / bin / make. Further we expose ABI. If you chose the static version, at the bottom add mkspec - “win32-g ++. Static” (without quotes). The remaining fields are irrelevant. Zaregali all four types of compilers, click "Apply"

Step-2

Switch to the Qt Profiles tab. Adding profiles look for them in $ HOME / dev / stuff / bla-bla-bla / bin / qmake. Zaregali all four profiles, click "Apply"

Step-3

Switch to the "Kits" tab. Add the next bundle, choosing the right compiler + Qt profile. In the kits, where the static assembly is desirable to register and mkspecs as in step-1. Zaregali all four sets, click "Apply"

Conclusion


Fully aware - collected may contain certain errors, because Far from being the author of neither Qt nor PostgreSQL, not even a member of the MXE project. And the absence of the simplest checks at the time of assembly, not to mention unit tests, assumes that you are aware of the “dampness” of what has been done. However, after receiving this set of toolchains, I tested my projects, examples from the Qt delivery. I didn’t find any errors in the modules I’m interested in (UI, PostgreSQL, http, QtScript, and several others).

... The promised about the full assembly. If you are very lucky, and MXE, at the time of your interest will be in a stable condition, it is very easy to get a full build:

 $ 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 

Vanguyu, in this version of the assembly you will be disappointed with a probability of 87.14%, but if everything is without jambs, then the resulting Qt5 assemblies will be placed in $ HOME / dev / cross / mxe / usr / <toolchain> / qt5

All successful coding.

Source: https://habr.com/ru/post/258951/


All Articles