I compiled Windows target on Linux, but is there a standard way to do it?
-
Managed to Compile my Windows target on Linux
It runs in Windows but it is compile with mingw gcc 9.3.
Since Qt is build using gcc 8.1.0, I wonder how this is working at all?And..., Is there a standard solution for this by Qt?
I have not found it yet.
There are apparently multiple sets of cmake-files for different platforms which I did not expect.
My Procedure to make it work
- Install the same Qt version (mine is 6.2.0 ) on a Windows Machine (mine is a virtual machine VirtualBox)
- Copy only the
./Qt/6.2.0/mingw81_64
directory to your Linux box. - Replace cmake files where Qt finds its tools. (find cmake-files with ".exe" in it)
- Add symlink for libexec sub dir needed for the Linux tools.
- Install mingw 64 bit on Linux (packages gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64)
- Create a Windows Tool Chain cmake-file and include it in the
CMakeLists.txt
project. - Since I used the STL in my project I needed to add the gcc 9.3
libstdc++-6.dll
file in the exe-directory.
The PATH environment variable was added the Qt path for DLL's (mine isP:\Qt\6.2.0\mingw81_64\bin
)
Using:C:\Windows\System32\rundll32.exe sysdm.cpl,EditEnvironmentVariables
.
CMake Windows tool chain file
WindowsToolChain.cmake
# Notify that this file was loaded. message("Linux compiling for Windows.") # Allow cmake to find the Qt library (this could be automated and version independent) list(APPEND CMAKE_PREFIX_PATH "/mnt/server/userdata/project/PROG/Qt/6.2.0/mingw81_64/lib/cmake/") # Targeted operating system. set(CMAKE_SYSTEM_NAME Windows) # Use mingw 64-bit compilers. set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-c++-posix) set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32/) # Adjust the default behavior of the find commands: # search headers and libraries in the target environment set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # Search programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
CMake addition to invoke tool chain file when
CROSS_WINDOWS
is defined--- # Check if this is a cross compile for windows. (cmake -DCROSS_WINDOWS=ON) if (DEFINED CROSS_WINDOWS) set(CMAKE_TOOLCHAIN_FILE com/cmake/SfWindowsToolChain.cmake) endif () ---
Bash script having all the parts that were done to make it happen
#!/bin/bash ## ## Install only 64bit compilers. ## sudo apt install gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 # Directory where the Linux Qt library cmake files are located. DIR_FROM="${HOME}/lib/Qt/6.2.0/gcc_64/lib/cmake" # Root for the Windows Qt installed MinGW files. ROOT_DIR="/mnt/server/userdata/project/PROG/Qt/6.2.0/mingw81_64" # Directory where the Windows Qt library cmake files are located. DIR_TO="${ROOT_DIR}/lib/cmake" ## ## Create symlink in from ~/lib/Qt/6.2.0/gcc_64/libexec to ${ROOT_DIR} ## ln -s "${HOME}/lib/Qt/6.2.0/gcc_64/libexec" "${ROOT_DIR}/libexec" ## ## Replace all cmake files referencing windows EXE-tools. ## Found using (could be automated): ## find /mnt/server/userdata/project/PROG/Qt/6.2.0/mingw81_64 -type f -name "*.cmake" -exec grep -li "\.exe" {} \; ## declare -a MODULES=( "Qt6AxContainerTools/Qt6AxContainerToolsTargets-relwithdebinfo.cmake" "Qt6AxServerTools/Qt6AxServerToolsTargets-relwithdebinfo.cmake" "Qt6DBusTools/Qt6DBusToolsTargets-relwithdebinfo.cmake" "Qt6GuiTools/win/Qt6GuiToolsTargets-relwithdebinfo.cmake" "Qt6LinguistTools/Qt6LinguistToolsTargets-relwithdebinfo.cmake" "Qt6QmlTools/Qt6QmlToolsTargets-relwithdebinfo.cmake" "Qt6RemoteObjectsTools/Qt6RemoteObjectsToolsTargets-relwithdebinfo.cmake" "Qt6ScxmlTools/Qt6ScxmlToolsTargets-relwithdebinfo.cmake" "Qt6SerialBusTools/Qt6SerialBusToolsTargets-relwithdebinfo.cmake" "Qt6ToolsTools/Qt6ToolsToolsTargets-relwithdebinfo.cmake" "Qt6WidgetsTools/Qt6WidgetsToolsTargets-relwithdebinfo.cmake" ) # Iterate the string array using for loop for fn in "${MODULES[@]}" ; do cp "${DIR_FROM}/${fn}" "${DIR_TO}/${fn}" done
-
Managed to Compile my Windows target on Linux
It runs in Windows but it is compile with mingw gcc 9.3.
Since Qt is build using gcc 8.1.0, I wonder how this is working at all?And..., Is there a standard solution for this by Qt?
I have not found it yet.
There are apparently multiple sets of cmake-files for different platforms which I did not expect.
My Procedure to make it work
- Install the same Qt version (mine is 6.2.0 ) on a Windows Machine (mine is a virtual machine VirtualBox)
- Copy only the
./Qt/6.2.0/mingw81_64
directory to your Linux box. - Replace cmake files where Qt finds its tools. (find cmake-files with ".exe" in it)
- Add symlink for libexec sub dir needed for the Linux tools.
- Install mingw 64 bit on Linux (packages gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64)
- Create a Windows Tool Chain cmake-file and include it in the
CMakeLists.txt
project. - Since I used the STL in my project I needed to add the gcc 9.3
libstdc++-6.dll
file in the exe-directory.
The PATH environment variable was added the Qt path for DLL's (mine isP:\Qt\6.2.0\mingw81_64\bin
)
Using:C:\Windows\System32\rundll32.exe sysdm.cpl,EditEnvironmentVariables
.
CMake Windows tool chain file
WindowsToolChain.cmake
# Notify that this file was loaded. message("Linux compiling for Windows.") # Allow cmake to find the Qt library (this could be automated and version independent) list(APPEND CMAKE_PREFIX_PATH "/mnt/server/userdata/project/PROG/Qt/6.2.0/mingw81_64/lib/cmake/") # Targeted operating system. set(CMAKE_SYSTEM_NAME Windows) # Use mingw 64-bit compilers. set(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix) set(CMAKE_CXX_COMPILER x86_64-w64-mingw32-c++-posix) set(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32/) # Adjust the default behavior of the find commands: # search headers and libraries in the target environment set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # Search programs in the host environment set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
CMake addition to invoke tool chain file when
CROSS_WINDOWS
is defined--- # Check if this is a cross compile for windows. (cmake -DCROSS_WINDOWS=ON) if (DEFINED CROSS_WINDOWS) set(CMAKE_TOOLCHAIN_FILE com/cmake/SfWindowsToolChain.cmake) endif () ---
Bash script having all the parts that were done to make it happen
#!/bin/bash ## ## Install only 64bit compilers. ## sudo apt install gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 # Directory where the Linux Qt library cmake files are located. DIR_FROM="${HOME}/lib/Qt/6.2.0/gcc_64/lib/cmake" # Root for the Windows Qt installed MinGW files. ROOT_DIR="/mnt/server/userdata/project/PROG/Qt/6.2.0/mingw81_64" # Directory where the Windows Qt library cmake files are located. DIR_TO="${ROOT_DIR}/lib/cmake" ## ## Create symlink in from ~/lib/Qt/6.2.0/gcc_64/libexec to ${ROOT_DIR} ## ln -s "${HOME}/lib/Qt/6.2.0/gcc_64/libexec" "${ROOT_DIR}/libexec" ## ## Replace all cmake files referencing windows EXE-tools. ## Found using (could be automated): ## find /mnt/server/userdata/project/PROG/Qt/6.2.0/mingw81_64 -type f -name "*.cmake" -exec grep -li "\.exe" {} \; ## declare -a MODULES=( "Qt6AxContainerTools/Qt6AxContainerToolsTargets-relwithdebinfo.cmake" "Qt6AxServerTools/Qt6AxServerToolsTargets-relwithdebinfo.cmake" "Qt6DBusTools/Qt6DBusToolsTargets-relwithdebinfo.cmake" "Qt6GuiTools/win/Qt6GuiToolsTargets-relwithdebinfo.cmake" "Qt6LinguistTools/Qt6LinguistToolsTargets-relwithdebinfo.cmake" "Qt6QmlTools/Qt6QmlToolsTargets-relwithdebinfo.cmake" "Qt6RemoteObjectsTools/Qt6RemoteObjectsToolsTargets-relwithdebinfo.cmake" "Qt6ScxmlTools/Qt6ScxmlToolsTargets-relwithdebinfo.cmake" "Qt6SerialBusTools/Qt6SerialBusToolsTargets-relwithdebinfo.cmake" "Qt6ToolsTools/Qt6ToolsToolsTargets-relwithdebinfo.cmake" "Qt6WidgetsTools/Qt6WidgetsToolsTargets-relwithdebinfo.cmake" ) # Iterate the string array using for loop for fn in "${MODULES[@]}" ; do cp "${DIR_FROM}/${fn}" "${DIR_TO}/${fn}" done
@A-v-O said in I compiled Windows target on Linux, but is there a standard way to do it?:
Install the same Qt version (mine is 6.2.0 ) on a Windows Machine (mine is a virtual machine VirtualBox)
Why don't you simply build your app on that Windows machine?
If you want to cross compile you actually would need to cross compile Qt with MinGW. But I never did this as it is way easier to simply build on Windows. -
@jsulm said in I compiled Windows target on Linux, but is there a standard way to do it?:
If you want to cross compile you actually would need to cross compile Qt with MinGW. But I never did this as it is way easier to simply build on Windows.
I did till now build on Windows, but it is to much of a hassle switch between Linux and Windows.
Now I can easily select in my CLion IDE what target to compile with 2 clicks.WDebug is the cross compile version
And it is easy to check if changes made in Linux als can be compiled in Windows. (#if WIN32 #else #endif)
Even run the compiled code from the VM to check the result.My code is on a Linux server mounted on my workstation system with nfs.
I tried compiling through Linux samba share on Windows which made it not happy being remote.
Because of that you need local sources and use git creating unnecessary commits that are not even squashable before a push.
The VM is on the server too by the way which I connect to on my workstation.All in all, it is less time consuming this way.
The Windows build from Linux is also a lot faster.
-
@jsulm said in I compiled Windows target on Linux, but is there a standard way to do it?:
If you want to cross compile you actually would need to cross compile Qt with MinGW. But I never did this as it is way easier to simply build on Windows.
I did till now build on Windows, but it is to much of a hassle switch between Linux and Windows.
Now I can easily select in my CLion IDE what target to compile with 2 clicks.WDebug is the cross compile version
And it is easy to check if changes made in Linux als can be compiled in Windows. (#if WIN32 #else #endif)
Even run the compiled code from the VM to check the result.My code is on a Linux server mounted on my workstation system with nfs.
I tried compiling through Linux samba share on Windows which made it not happy being remote.
Because of that you need local sources and use git creating unnecessary commits that are not even squashable before a push.
The VM is on the server too by the way which I connect to on my workstation.All in all, it is less time consuming this way.
The Windows build from Linux is also a lot faster.
@A-v-O No problem!
Thanks for sharing! -
Update on Cross-Compiling
In the mean time I created GitHub repository which demonstrates the use of a privately hosted Docker image assembled by using this GitHub repository and its script
cpp-builder.sh
. (It is a lot easier to download/pull the Docker image fromnexus.scanframe.com:8090/gnu-cpp:dev
)
It accommodates building Qt Linux and Windows targets as well as performing unit testing.
A GitLab runner uses it to execute a pipeline which executes a CMakePreset-workflow.
The same Docker image is used to build, run, debug and test locally by mounting the X-server socket into the Docker VM.
Preset allow workflows and individual presets to be executed using the script docker-build.sh.Hopefully someone can benefit from my work on this :)