Jak skonfigurować Qt do cross-kompilacji z systemu Linux do systemu Windows?

81

Chcę skompilować krzyżowo biblioteki Qt (i ostatecznie moją aplikację) dla docelowego systemu Windows x86_64 przy użyciu hosta Linux x86_64. Czuję, że jestem blisko, ale mogę mieć fundamentalne niezrozumienie niektórych części tego procesu.

Zacząłem od zainstalowania wszystkich pakietów mingw na moim komputerze Fedora, a następnie zmodyfikowania win32-g++pliku qmake.conf, aby pasował do mojego środowiska. Jednak wydaje mi się, że utknąłem z niektórymi pozornie oczywistymi opcjami konfiguracyjnymi dla Qt: -platformi -xplatform. Dokumentacja Qt mówi, że -platformpowinna to być architektura komputera hosta (na którym kompilujesz) i -xplatformpowinna być platformą docelową, dla której chcesz wdrożyć. W moim przypadku ustawiam -platform linux-g++-64i -xplatform linux-win32-g++gdzie linux-win32-g ++ jest moją zmodyfikowaną konfiguracją win32-g ++.

Mój problem polega na tym, że po wykonaniu konfiguracji z tymi opcjami widzę, że wywołuje kompilator mojego systemu zamiast kompilatora krzyżowego (x86_64-w64-mingw32-gcc). Jeśli pominę tę -xplatformopcję i ustawię -platformna moją specyfikację docelową (linux-win32-g ++), wywoła kompilator krzyżowy, ale wtedy błędy, gdy znajdzie niektóre funkcje związane z Uniksem, nie są zdefiniowane.

Oto niektóre wyniki mojej ostatniej próby: http://pastebin.com/QCpKSNev .

Pytania:

  1. Czy podczas kompilacji krzyżowej czegoś takiego jak Qt dla systemu Windows z hosta systemu Linux należy kiedykolwiek wywoływać kompilator natywny ? To znaczy, czy podczas procesu kompilacji krzyżowej nie powinniśmy używać tylko kompilatora krzyżowego? Nie rozumiem, dlaczego skrypt konfiguracyjny Qt próbuje wywołać natywny kompilator mojego systemu, gdy określę-xplatform opcję.

  2. Jeśli używam cross-kompilatora mingw, kiedy będę musiał radzić sobie z plikiem specyfikacji? Pliki specyfikacji dla GCC wciąż są dla mnie tajemnicą, więc zastanawiam się, czy jakieś tło tutaj mi pomoże.

  3. Ogólnie rzecz biorąc, poza określeniem kompilatora krzyżowego w moim qmake.conf, co jeszcze powinienem wziąć pod uwagę?

Panie Shickadance
źródło
2
Uważam, że do załadowania pozostałej części kompilacji potrzebna jest lokalna kompilacja qmake. zobacz także linki na stackoverflow.com/questions/1025687/…
Martin Beckett
Ok, to ma sens. Właśnie znalazłem inny problem, wydaje mi się, że mieszam natywne i krzyżowe łańcuchy narzędzi. Wydaje się, że błąd w moich wynikach wklejania jest spowodowany wywołaniem x86_64-w64-mingw32-aszamiast natywnego.
Pan Shickadance,
2
Rzadko oznaczam pytanie SO jako ulubione, ale było to wyjątkowe i interesujące pytanie z fajną odpowiedzią.
jdi

Odpowiedzi:

70

Po prostu użyj środowiska M cross environment (MXE) . Eliminuje ból z całego procesu:

  • Zdobyć:

    $ git clone https://github.com/mxe/mxe.git
    
  • Zainstaluj zależności kompilacji

  • Kompiluj Qt dla systemu Windows, jego zależności i narzędzia kompilacji krzyżowej; zajmie to około godziny na szybkiej maszynie z przyzwoitym dostępem do Internetu; pobieranie to około 500 MB:

    $ cd mxe && make qt
    
  • Przejdź do katalogu swojej aplikacji i dodaj narzędzia cross-build do zmiennej środowiskowej PATH :

    $ export PATH=<mxe root>/usr/bin:$PATH
    
  • Uruchom narzędzie generatora Qt Makefile, a następnie skompiluj:

    $ <mxe root>/usr/i686-pc-mingw32/qt/bin/qmake && make
    
  • Plik binarny powinieneś znaleźć w katalogu ./release:

    $ wine release/foo.exe
    

Kilka uwag :

  • Użyj głównej gałęzi repozytorium MXE; wydaje się, że zespół programistów cieszy się o wiele większym uznaniem.

  • Dane wyjściowe to 32-bitowy statyczny plik binarny, który będzie dobrze działać w 64-bitowym systemie Windows.

tshepang
źródło
17
uwaga : te instrukcje dotyczą Qt 4; dla Qt 5, patrz stackoverflow.com/a/14170591
tshepang
Przed wykonaniem $ cd mxe && make qtnależy zainstalować wymagania. W przypadku systemów Debian oznacza to 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. W przypadku innych systemów patrz mxe.cc/#requirements
Martin Thoma
16

(To jest aktualizacja odpowiedzi @ Tshepang, ponieważ MXE ewoluowało od czasu jego odpowiedzi)

Budynek Qt

Zamiast używać make qtdo budowania Qt, możesz użyć MXE_TARGETSdo sterowania maszyną docelową i łańcuchem narzędzi (32- lub 64-bitowe). MXE zaczęło używać .statici .sharedjako części nazwy docelowej, aby pokazać, jaki typ biblioteki chcesz zbudować.

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

W pierwotnej odpowiedzi @ Tshepang nie określił znaku MXE_TARGETSi używana jest wartość domyślna. W chwili, gdy pisał swoją odpowiedź, domyślnym było i686-pc-mingw32, teraz jest i686-w64-mingw32.static. Jeśli jawnie ustawiona MXE_TARGETSna i686-w64-mingw32, pomijając .static, ostrzeżenie zostanie wydrukowany ponieważ składnia jest teraz przestarzała. Jeśli spróbujesz ustawić cel na i686-pc-mingw32, wyświetli się błąd, ponieważ MXE usunęło obsługę MinGW.org (tj. I686-pc-mingw32).

Bieganie qmake

Jak zmienił MXE_TARGETSThe <mxe root>/usr/i686-pc-mingw32/qt/bin/qmakekomenda nie będzie działać. Teraz musisz zrobić:

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

Jeśli nie określiłeś MXE_TARGETS, zrób to:

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

Aktualizacja: nowe ustawienie domyślne to terazi686-w64-mingw32.static

Timothy Gu
źródło
Dziękuję bardzo za aktualizację. Dobrze jest też mieć kogoś, kto pracuje bezpośrednio nad projektem.
tshepang
3
Powinna to być zmiana / aktualizacja drugiej odpowiedzi, a nie nowa.
WhyNotHugo
3
@Hugo Strona edycji mówi: Jak edytować: ► popraw błędy gramatyczne lub ortograficzne ► wyjaśnij znaczenie bez zmiany ► popraw drobne błędy ► dodaj powiązane zasoby lub linki ► zawsze szanuj oryginalnego autora To nie jest żaden z tych. Jest to rozszerzenie odpowiedzi Tshepanga.
Timothy Gu
Nie rozumiem tej odpowiedzi, kiedy piszę „make qt…”, odpowiada po prostu „brak reguły tworzenia docelowej qt”.
Mój
4

Ok, myślę, że już to rozgryzłem.

Oparty częściowo na https://github.com/mxe/mxe/blob/master/src/qt.mk i https://www.videolan.org/developers/vlc/contrib/src/qt4/rules.mak

Wygląda na to, że "początkowo", kiedy uruchamiasz configure (z -xtarget itp.), Konfiguruje, a następnie uruchamia gcc "hostów", aby zbudować lokalny plik binarny ./bin/qmake

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

następnie uruchamiasz normalne "make" i buduje je dla mingw

  make
  make install

więc

  1. tak

  2. tylko jeśli potrzebujesz użyć czegoś innego niż msvcrt.dll (jest to ustawienie domyślne). Chociaż nigdy nie korzystałem z niczego innego, więc nie wiem na pewno.

  3. https://stackoverflow.com/a/18792925/32453 zawiera listę niektórych parametrów konfiguracji.

rogerdpack
źródło
4

Aby skompilować Qt, należy uruchomić jego configureskrypt, podając platformę hosta -platform(np. -platform linux-g++-64Jeśli budujesz na 64-bitowym Linuksie z kompilatorem g ++) i platformę docelową -xplatform(np.-xplatform win32-g++ Jeśli kompilujesz cross do Windows ).

Dodałem również tę flagę: -device-option CROSS_COMPILE=/usr/bin/x86_64-w64-mingw32- która określa przedrostek łańcucha narzędzi, którego używam, który zostanie dodany do „gcc” lub „g ++” we wszystkich plikach Makefile, które budują pliki binarne dla systemu Windows.

Wreszcie, możesz napotkać problemy podczas budowania icd , co najwyraźniej jest czymś, co jest używane do dodawania obsługi ActiveX do Qt. Możesz tego uniknąć, przekazując flagę -skip qtactiveqtdo skryptu konfiguracji. Mam ten z tego raportu o błędzie: https://bugreports.qt.io/browse/QTBUG-38223

Oto całe polecenie konfiguracji, którego użyłem:

    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

A jeśli chodzi o pytania:

1 - Tak. Natywny kompilator zostanie wywołany w celu zbudowania niektórych narzędzi potrzebnych w procesie kompilacji. Może takie rzeczy jak qconfig lub qmake, ale nie jestem do końca pewien, które dokładnie narzędzia.

2 - Przepraszam. Nie mam pojęcia, jakie pliki specyfikacji są w kontekście kompilatorów = /. Ale o ile wiem, nie musiałbyś się tym zajmować.

3 - Możesz określić przedrostek kompilatora krzyżowego w linii poleceń konfiguracji zamiast robić to w pliku qmake.conf, jak wspomniano powyżej. Jest też ten problem z idc, którego obejście również wspomniałem.

user986730
źródło
4

Innym sposobem kompilacji krzyżowej oprogramowania dla systemu Windows w systemie Linux jest łańcuch narzędzi MinGW-w64 w Archlinux. Jest łatwy w obsłudze i utrzymaniu oraz udostępnia najnowsze wersje kompilatora i wiele bibliotek. Osobiście uważam to za łatwiejsze niż MXE i wydaje się, że szybciej adaptuje nowsze wersje bibliotek.

Po pierwsze, będziesz potrzebować maszyny opartej na architekturze arch (wystarczy maszyna wirtualna lub kontener docker). Nie musi to być Arch Linux, nadadzą się też pochodne. Użyłem Manjaro Linux. Większość pakietów MinGW-w64 nie jest dostępna w oficjalnych repozytoriach Arch, ale jest ich mnóstwo w AUR . Domyślny menedżer pakietów dla Arch (Pacman) nie obsługuje instalacji bezpośrednio z AUR, więc będziesz musiał zainstalować i używać opakowania AUR, takiego jak yay lub yaourt. Następnie instalacja bibliotek Qt5 i Boost w wersji MinGW-w64 jest tak prosta, jak:

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

Spowoduje to również zainstalowanie narzędzia MinGW-w64 toolchain ( mingw-w64-gcc) i innych zależności. Kompilowanie krzyżowe projektu Qt dla Windows (x64) jest wtedy tak proste, jak:

x86_64-w64-mingw32-qmake-qt5
make

Aby wdrożyć program, musisz skopiować odpowiednie biblioteki DLL z /usr/x86_64-w64-mingw32/bin/. Na przykład, można zazwyczaj trzeba skopiować /usr/x86_64-w64-mingw32/lib/qt/plugins/platforms/qwindows.dlldo program.exe_dir/platforms/qwindows.dll.

Aby uzyskać wersję 32-bitową, wystarczy użyć i686-w64-mingw32-qmake-qt5zamiast tego. Projekty oparte na Cmake działają równie łatwo z x86_64-w64-mingw32-cmake. To podejście zadziałało dla mnie wyjątkowo dobrze, było najłatwiejsze do skonfigurowania, utrzymania i rozszerzenia. Dobrze sprawdza się również w przypadku usług ciągłej integracji. Dostępne są również obrazy dockera .

Na przykład, powiedzmy, że chcę zbudować GUI programu do pobierania napisów QNapi. Mogłem to zrobić w dwóch krokach:

  1. Uruchom kontener Docker:

    sudo docker run -it burningdaylight / mingw-arch: qt / bin / bash

  2. Klonuj i kompiluj QNapi

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

Otóż ​​to! W wielu przypadkach będzie to takie proste. Dodanie własnych bibliotek do repozytorium pakietów (AUR) jest również proste. Musiałbyś napisać plik PKBUILD , który jest tak intuicyjny, jak to tylko możliwe, zobacz na przykład mingw-w64-rapidjson .

Mykoła Dimura
źródło
W celu wdrożenia należy skopiować wszystkie wymagane biblioteki DLL Qt (lub doc.qt.io/qt-5/windows-deployment.html ). Upewnij się, że plik /mingw64/share/qt5/plugins/platforms/qwindows.dll zostanie skopiowany do platform / qwindows.dll.
develCuy