¿Cómo configuro Qt para la compilación cruzada desde el destino de Linux a Windows?

81

Quiero realizar una compilación cruzada de las bibliotecas Qt (y eventualmente mi aplicación) para un destino Windows x86_64 usando una máquina host Linux x86_64. Siento que estoy cerca, pero puedo tener un malentendido fundamental de algunas partes de este proceso.

Comencé instalando todos los paquetes mingw en mi máquina Fedora y luego modificando el win32-g++archivo qmake.conf para que se ajustara a mi entorno. Sin embargo, parece que me estoy quedando atascado con algunas opciones de configuración aparentemente obvias para Qt: -platformy -xplatform. La documentación de Qt dice que -platformdebería ser la arquitectura de la máquina host (donde está compilando) y -xplatformdebería ser la plataforma de destino para la que desea implementar. En mi caso, configuré -platform linux-g++-64y -xplatform linux-win32-g++donde linux-win32-g ++ es mi configuración win32-g ++ modificada.

Mi problema es que, después de ejecutar configure con estas opciones, veo que invoca el compilador de mi sistema en lugar del compilador cruzado (x86_64-w64-mingw32-gcc). Si omito la -xplatformopción y la configuro -platformen mi especificación de destino (linux-win32-g ++), invoca el compilador cruzado pero luego los errores cuando encuentra algunas funciones relacionadas con Unix no están definidas.

Aquí hay algunos resultados de mi último intento: http://pastebin.com/QCpKSNev .

Preguntas:

  1. Cuando compilación cruzada algo así como Qt para Windows desde un servidor Linux, si el compilador nativo jamás invocarse? Es decir, durante un proceso de compilación cruzada, ¿no deberíamos usar solo el compilador cruzado? No veo por qué el script de configuración de Qt intenta invocar el compilador nativo de mi sistema cuando especifico la -xplatformopción.

  2. Si estoy usando un compilador cruzado mingw, ¿cuándo tendré que lidiar con un archivo de especificaciones? Los archivos de especificaciones para GCC siguen siendo un misterio para mí, así que me pregunto si algunos antecedentes aquí me ayudarán.

  3. En general, más allá de especificar un compilador cruzado en mi qmake.conf, ¿qué más debo considerar?

Sr. Shickadance
fuente
2
Creo que necesita una compilación local de qmake para arrancar el resto de la compilación. vea también los enlaces en stackoverflow.com/questions/1025687/…
Martin Beckett
Ok, eso tiene sentido. Ahora acabo de encontrar otro problema, parece que estoy mezclando cadenas de herramientas nativas y cruzadas. El error en mi salida de pastebin parece deberse a una llamada en x86_64-w64-mingw32-aslugar de la nativa.
Sr.Shickadance
2
Rara vez marco una pregunta SO como favorita, pero esta fue una pregunta única e interesante con una respuesta genial.
jdi

Respuestas:

70

Simplemente use M cross environment (MXE) . Elimina el dolor de todo el proceso:

  • Consíguelo:

    $ git clone https://github.com/mxe/mxe.git
    
  • Instalar dependencias de compilación

  • Build Qt para Windows, sus dependencias y las herramientas de construcción cruzada; esto llevará aproximadamente una hora en una máquina rápida con acceso a Internet decente; la descarga es de unos 500 MB:

    $ cd mxe && make qt
    
  • Vaya al directorio de su aplicación y agregue las herramientas de construcción cruzada a la variable de entorno PATH :

    $ export PATH=<mxe root>/usr/bin:$PATH
    
  • Ejecute la herramienta generadora Qt Makefile y luego compile:

    $ <mxe root>/usr/i686-pc-mingw32/qt/bin/qmake && make
    
  • Debería encontrar el binario en el directorio ./release:

    $ wine release/foo.exe
    

Algunas notas :

  • Utilice la rama maestra del repositorio MXE; parece recibir mucho más cariño por parte del equipo de desarrollo.

  • La salida es un binario estático de 32 bits, que funcionará bien en Windows de 64 bits.

tshepang
fuente
17
nota : estas instrucciones se aplican a Qt 4; para Qt 5, consulte stackoverflow.com/a/14170591
tshepang
Antes de ejecutar $ cd mxe && make qtdebe instalar los requisitos. Para los sistemas Debian esto significa 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. Para otros sistemas, consulte mxe.cc/#requirements
Martin Thoma
16

(Esta es una actualización de la respuesta de @ Tshepang, ya que MXE ha evolucionado desde su respuesta)

Edificio Qt

En lugar de usarlo make qtpara construir Qt, puede usarlo MXE_TARGETSpara controlar su máquina objetivo y cadena de herramientas (32 o 64 bits). MXE comenzó a usar .staticy .sharedcomo parte del nombre de destino para mostrar qué tipo de biblioteca desea construir.

# 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'

En la respuesta original de @ Tshepang, no especificó un MXE_TARGETS, y se usa el predeterminado. En el momento en que escribió su respuesta, el valor predeterminado era i686-pc-mingw32, ahora lo es i686-w64-mingw32.static. Si establece explícitamente MXE_TARGETSen i686-w64-mingw32, omitiendo .static, se imprime una advertencia porque esta sintaxis ahora está en desuso. Si intenta establecer el destino en i686-pc-mingw32, mostrará un error ya que MXE ha eliminado el soporte para MinGW.org (es decir, i686-pc-mingw32).

Corriendo qmake

A medida que cambiamos el MXE_TARGETS, el <mxe root>/usr/i686-pc-mingw32/qt/bin/qmakecomando ya no funcionará. Ahora, lo que debes hacer es:

<mxe root>/usr/<TARGET>/qt/bin/qmake

Si no especificó MXE_TARGETS, haga esto:

<mxe root>/usr/i686-w64-mingw32.static/qt/bin/qmake

Actualización: el nuevo valor predeterminado es ahorai686-w64-mingw32.static

Timothy Gu
fuente
Muchas gracias por la actualización. También es bueno que alguien que trabaja directamente en el proyecto responda.
tshepang
3
Esto debería haber sido una edición / actualización de la otra respuesta, no una nueva.
WhyNotHugo
3
@Hugo La página de edición dice: Cómo editar: ► corregir errores gramaticales o de ortografía ► aclarar el significado sin cambiarlo ► corregir errores menores ► agregar recursos o enlaces relacionados ► respetar siempre al autor original Esto no es ninguno de esos. Es una extensión de la respuesta de Tshepang.
Timothy Gu
No entiendo esta respuesta, cuando escribo "make qt ...." simplemente responde con "no hay regla para hacer qt objetivo".
Mía
4

Ok, creo que lo tengo resuelto.

Basado en parte en https://github.com/mxe/mxe/blob/master/src/qt.mk y https://www.videolan.org/developers/vlc/contrib/src/qt4/rules.mak

Parece que "inicialmente" cuando ejecuta configure (con -xtarget, etc.), configura y luego ejecuta su "hosts" gcc para construir el archivo binario local ./bin/qmake

 ./configure -xplatform win32-g++ -device-option CROSS_COMPILE=$cross_prefix_here -nomake examples ...

luego ejecuta "make" normal y lo construye para mingw

  make
  make install

entonces

  1. si

  2. solo si necesita usar algo que no sea msvcrt.dll (por defecto). Aunque nunca he usado nada más, no lo sé con certeza.

  3. https://stackoverflow.com/a/18792925/32453 enumera algunos parámetros de configuración.

Rogerdpack
fuente
4

Para compilar Qt, uno debe ejecutar su configurescript, especificando la plataforma de host con -platform(por ejemplo, -platform linux-g++-64si está construyendo en un linux de 64 bits con el compilador g ++) y la plataforma de destino con -xplatform(por ejemplo, -xplatform win32-g++si está compilando de forma cruzada a Windows ).

También agregué esta bandera: -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- que especifica el prefijo de la cadena de herramientas que estoy usando, que se antepondrá a 'gcc' o 'g ++' en todos los archivos MAKE que están construyendo binarios para Windows.

Por último, es posible que tenga problemas al compilar icd , que aparentemente es algo que se usa para agregar soporte ActiveX a Qt. Puede evitarlo pasando la bandera -skip qtactiveqtal script de configuración. Tengo este de este informe de error: https://bugreports.qt.io/browse/QTBUG-38223

Aquí está todo el comando de configuración que he usado:

    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

En cuanto a sus preguntas:

1 - Sí. Se llamará al compilador nativo para construir algunas herramientas necesarias en el proceso de construcción. Quizás cosas como qconfig o qmake, pero no estoy del todo seguro de qué herramientas exactamente.

2 - Lo siento. No tengo idea de qué archivos de especificaciones están en el contexto de compiladores = /. Pero hasta donde yo sé, no tendrías que lidiar con eso.

3 - Puede especificar el prefijo del compilador cruzado en la línea de comandos de configuración en lugar de hacerlo en el archivo qmake.conf, como se mencionó anteriormente. Y también está ese problema con idc, cuya solución también he mencionado.

usuario986730
fuente
4

Otra forma de compilar software para Windows en Linux es la cadena de herramientas mingw-w64 en Archlinux. Es fácil de usar y mantener, y proporciona versiones recientes del compilador y muchas bibliotecas. Personalmente, lo encuentro más fácil que MXE y parece adoptar versiones más nuevas de bibliotecas más rápido.

Primero, necesitará una máquina basada en arco (la máquina virtual o el contenedor acoplable serán suficientes). No tiene que ser Arch Linux, los derivados también lo harán. Usé Manjaro Linux. La mayoría de los paquetes mingw-w64 no están disponibles en los repositorios oficiales de Arch, pero hay muchos en AUR . El administrador de paquetes predeterminado para Arch (pacman) no admite la instalación directamente desde AUR, por lo que deberá instalar y usar un contenedor AUR como yay o yaourt. Luego, instalar la versión mingw-w64 de las bibliotecas Qt5 y Boost es tan fácil como:

yay -Sy mingw-w64-qt5-base mingw-w64-boost
#yaourt -Sy mingw-w64-qt5-base mingw-w64-qt5-boost #if you use yaourt

Esto también instalará la cadena de herramientas mingw-w64 ( mingw-w64-gcc) y otras dependencias. La compilación cruzada de un proyecto Qt para Windows (x64) es tan simple como:

x86_64-w64-mingw32-qmake-qt5
make

Para implementar su programa, deberá copiar las DLL correspondientes de /usr/x86_64-w64-mingw32/bin/. Por ejemplo, normalmente necesitará copiar /usr/x86_64-w64-mingw32/lib/qt/plugins/platforms/qwindows.dlla program.exe_dir/platforms/qwindows.dll.

Para obtener una versión de 32 bits, simplemente necesita usarla i686-w64-mingw32-qmake-qt5. Los proyectos basados ​​en Cmake funcionan igual de fácil con x86_64-w64-mingw32-cmake. Este enfoque funcionó muy bien para mí, fue el más fácil de configurar, mantener y ampliar. También va bien con los servicios de integración continua. También hay imágenes de Docker disponibles.

Por ejemplo, digamos que quiero crear la GUI del descargador de subtítulos de QNapi. Podría hacerlo en dos pasos:

  1. Inicie el contenedor Docker:

    sudo docker run -it burningdaylight / docker-mingw-qt5 / bin / bash

  2. Clonar y compilar QNapi

    git clone --recursive 'https://github.com/QNapi/qnapi.git' cd qnapi / x86_64-w64-mingw32-qmake-qt5 make

¡Eso es! En muchos casos será así de fácil. Agregar sus propias bibliotecas al repositorio de paquetes (AUR) también es sencillo. Necesitaría escribir un archivo PKBUILD , que es lo más intuitivo posible, vea mingw-w64-rapidjson , por ejemplo.

Mykola Dimura
fuente
Para la implementación, debe copiar todas las DLL de Qt necesarias (o doc.qt.io/qt-5/windows-deployment.html ). Asegúrese de que /mingw64/share/qt5/plugins/platforms/qwindows.dll se copie en las plataformas / qwindows.dll.
develCuy