How do I configure Qt for cross-compilation from Linux to Windows target?
Ok, that makes sense. I now just found another problem, I seem to be mixing native and cross toolchains. The error in my pastebin output seems to be due to calling x86_64-w64-mingw32-as instead of the native one.
I rarely mark an SO question as a favorite but this was a unique and interesting question with a cool answer.
5 Answers 5
Just use M cross environment (MXE). It takes the pain out of the whole process:
$ git clone https://github.com/mxe/mxe.git
$ /usr/i686-pc-mingw32/qt/bin/qmake && make
- Use the master branch of the MXE repository; it appears to get a lot more love from the development team.
- The output is a 32-bit static binary, which will work well on 64-bit Windows.
Before executing $ cd mxe && make qt you should install the requirements. For Debian systems this means sudo apt-get install autoconf automake autopoint bash bison bzip2 cmake flex gettext git g++ gperf intltool libffi-dev libtool libltdl-dev libssl-dev libxml-parser-perl make openssl patch perl pkg-config python ruby scons sed unzip wget xz-utils . For other systems, see mxe.cc/#requirements
(This is an update of @Tshepang’s answer, as MXE has evolved since his answer)
Building Qt
Rather than using make qt to build Qt, you can use MXE_TARGETS to control your target machine and toolchain (32- or 64-bit). MXE started using .static and .shared as a part of the target name to show which type of lib you want to build.
# The following is the same as `make qt`, see explanation on default settings after the code block. make qt MXE_TARGETS=i686-w64-mingw32.static # MinGW-w64, 32-bit, static libs # Other targets you can use: make qt MXE_TARGETS=x86_64-w64-mingw32.static # MinGW-w64, 64-bit, static libs make qt MXE_TARGETS=i686-w64-mingw32.shared # MinGW-w64, 32-bit, shared libs # You can even specify two targets, and they are built in one run: # (And that's why it is MXE_TARGET**S**, not MXE_TARGET ;) # MinGW-w64, both 32- and 64-bit, static libs make qt MXE_TARGETS='i686-w64-mingw32.static x86_64-w64-mingw32.static'
In @Tshepang’s original answer, he did not specify an MXE_TARGETS , and the default is used. At the time he wrote his answer, the default was i686-pc-mingw32 , now it’s i686-w64-mingw32.static . If you explicitly set MXE_TARGETS to i686-w64-mingw32 , omitting .static , a warning is printed because this syntax is now deprecated. If you try to set the target to i686-pc-mingw32 , it will show an error as MXE has removed support for MinGW.org (i.e. i686-pc-mingw32).
Running qmake
As we changed the MXE_TARGETS , the /usr/i686-pc-mingw32/qt/bin/qmake command will no longer work. Now, what you need to do is:
If you didn’t specify MXE_TARGETS , do this:
/usr/i686-w64-mingw32.static/qt/bin/qmake
Update: The new default is now i686-w64-mingw32.static
Как настроить Qt для кросс-компиляции с Linux на целевой Windows?
Я хочу перекрестно скомпилировать библиотеки Qt (и в конечном итоге мое приложение) для целевого объекта Windows x86_64 с использованием хост-компьютера Linux x86_64. Я чувствую, что я близок, но у меня может быть фундаментальное непонимание некоторых частей этого процесса.
Я начал с установки всех пакетов mingw на моем компьютере Fedora и затем изменения файла win32-g++ qmake.conf в соответствии с моей средой. Тем не менее, я, кажется, застрял с некоторыми, казалось бы, очевидными настройками конфигурации для Qt: -platform и -xplatform . Документация Qt гласит, что -platform должна быть архитектурой хост-машины (где вы компилируете), а -xplatform должна быть целевой платформой, для которой вы хотите развернуть. В моем случае я установил -platform linux-g++-64 и -xplatform linux-win32-g++ , где linux-win32-g++ — это моя модифицированная конфигурация win32-g++.
Моя проблема в том, что после выполнения configure с этими параметрами я вижу, что он вызывает мой системный компилятор вместо кросс-компилятора (x86_64-w64-mingw32-gcc). Если я опускаю параметр -xplatform и устанавливаю -platform в свою целевую спецификацию (linux-win32-g++), он вызывает кросс-компилятор, но тогда ошибки, когда он находит некоторые связанные с Unix функции, не определены.
Вот некоторые результаты моей последней попытки: http://pastebin.com/QCpKSNev.
- Если кросс-компилировать что-то вроде Qt для Windows с хоста Linux, должен ли когда-нибудь использоваться собственный компилятор? То есть, во время процесса кросс-компиляции мы не должны использовать только кросс-компилятор? Я не понимаю, почему Qt configure script пытается вызвать мой системный собственный компилятор, когда я указываю опцию -xplatform .
- Если я использую кросс-компилятор mingw, когда мне придется иметь дело со спецификационным файлом? Файлы спецификаций для GCC по-прежнему являются для меня загадкой, поэтому мне интересно, поможет ли мне какой-то фон.
- В общем, помимо указания кросс-компилятора в моем qmake.conf, что еще мне нужно рассмотреть?
ОТВЕТЫ
Ответ 1
Просто используйте M cross environment (MXE). Это снимает боль из всего процесса:
$ git clone https://github.com/mxe/mxe.git
$ /usr/i686-pc-mingw32/qt/bin/qmake && make
Некоторые заметки:
- Использовать основную ветвь репозитория MXE; он, похоже, получает больше любви от команды разработчиков.
- Вывод представляет собой 32-битный статический двоичный файл, который будет хорошо работать на 64-разрядной Windows.
Ответ 2
(Это обновление ответа @Tshepang, поскольку MXE развился после его ответа)
Построение Qt
Вместо того, чтобы использовать make qt для сборки Qt, вы можете использовать MXE_TARGETS для управления вашей целевой машиной и инструментальной цепочкой (32- или 64-разрядной). MXE начал использовать .static и .shared как часть целевого имени, чтобы показать, какой тип библиотеки вы хотите создать.
# The following is the same as `make qt`, see explanation on default settings after the code block. make qt MXE_TARGETS=i686-w64-mingw32.static # MinGW-w64, 32-bit, static libs # Other targets you can use: make qt MXE_TARGETS=x86_64-w64-mingw32.static # MinGW-w64, 64-bit, static libs make qt MXE_TARGETS=i686-w64-mingw32.shared # MinGW-w64, 32-bit, shared libs # You can even specify two targets, and they are built in one run: # (And that why it is MXE_TARGET**S**, not MXE_TARGET ;) # MinGW-w64, both 32- and 64-bit, static libs make qt MXE_TARGETS='i686-w64-mingw32.static x86_64-w64-mingw32.static'
В исходном ответе @Tshepang он не указал MXE_TARGETS , и используется значение по умолчанию. В то время, когда он написал свой ответ, по умолчанию было i686-pc-mingw32 , теперь оно i686-w64-mingw32.static . Если вы явно установили MXE_TARGETS в i686-w64-mingw32 , опуская .static , выводится предупреждение, потому что этот синтаксис теперь устарел. Если вы попытаетесь установить цель на i686-pc-mingw32 , она покажет ошибку, так как MXE удалил поддержку MinGW.org(т.е. I686-pc-mingw32).
Запуск qmake
Когда мы изменили MXE_TARGETS , команда /usr/i686-pc-mingw32/qt/bin/qmake больше не будет работать. Теперь вам нужно сделать следующее:
Если вы не указали MXE_TARGETS , сделайте следующее:
/usr/i686-w64-mingw32.static/qt/bin/qmake
Обновление: Новый по умолчанию теперь i686-w64-mingw32.static
Ответ 3
Похоже, что «изначально» при запуске configure (с -xtarget и т.д.) он настраивается, а затем запускает ваши «хосты» gcc для создания локального двоичного файла. /bin/qmake
./configure -xplatform win32-g++ -device-option CROSS_COMPILE=$cross_prefix_here -nomake examples .
тогда вы запускаете нормальный «make», и он строит его для mingw
- да
- только если вам нужно использовать что-то другое, кроме msvcrt.dll(по умолчанию). Хотя я никогда не использовал ничего другого, поэтому я не знаю наверняка.
- fooobar.com/questions/83972/. перечисляет некоторые параметры конфигурации.
Ответ 4
Чтобы скомпилировать Qt, нужно запустить его configure script, указав платформу хоста с помощью -platform (например, -platform linux-g++-64 , если вы строите на 64-битном Linux с компилятором g++) и целевую платформу с -xplatform (например, -xplatform win32-g++ , если вы перекрестно компилируете в окна).
Я также добавил этот флаг: -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- который указывает префикс используемой инструментальной привязки, которая будет добавлена к gcc или g++ во всех make файлах, которые создают двоичные файлы для окон.
Наконец, у вас могут возникнуть проблемы при построении icd, который, по-видимому, является тем, что используется для добавления поддержки ActiveX в Qt. Вы можете избежать этого, передав флаг -skip qtactiveqt в configure script. У меня есть этот из отчета об ошибке: https://bugreports.qt.io/browse/QTBUG-38223
Здесь вся команда configure, которую я использовал:
cd qt_source_directory mkdir my_build cd my_build ../configure \ -release \ -opensource \ -no-compile-examples \ -platform linux-g++-64 \ -xplatform win32-g++ \ -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- \ -skip qtactiveqt \ -v
1 — Да. Нативный компилятор будет вызываться для создания некоторых инструментов, необходимых в процессе сборки. Возможно, такие вещи, как qconfig или qmake, но я не совсем уверен, какие именно инструменты.
2 — Извините. Я понятия не имею, какие файлы спецификаций находятся в контексте компиляторов =/. Но, насколько я знаю, вам не придется иметь дело с этим.
3 — Вы можете указать префикс кросс-компилятора в командной строке configure вместо того, чтобы делать это в файле qmake.conf, как упоминалось выше. И есть также проблема с idc, обходной путь которой я также упомянул.
Cross-Compiling
- Select Extensions >Qt VS Tools >Qt Versions >to add a new Qt version.
- In the Version field, enter a name for the Qt version. If you add the path to Qt first, this field is filled automatically.
- In Host, select Linux WSL or Linux SSH.
- In the Path field, enter the path to the Qt installation.
- In the Compiler field, enter the cross-compiler to use. The default value is g++.
Compiling on WSL
Using a WSL instance to run the cross-compiler is faster than using an SSH connection to a build host. When using SSH, MSBuild must first upload the source files to the remote host, whereas WSL mounts local drives in /mnt , making file access instantaneous.
MSBuild assumes that paths specified in options are local paths and maps them to corresponding Linux paths rooted on /mnt . For example:
C:\include\foolib maps to /mnt/c/include/foolib
Using absolute Linux paths as value of Extensions > Qt VS Tools > Options > Qt/MSBuild can lead to incorrect mappings. For example, /home/user/raspi maps to /mnt/home/user/raspi .
To avoid this issue, create symbolic links in /mnt to other top-level directories in the WSL instance file system.
© 2022 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.