- Cross-Compiling wxWidgets code from Linux to Windows
- Cross Compile to Windows From Linux
- Caveats
- MinGW GCC vc GCC: Not as Smart with Templates
- C/C++ Standard Library Dependencies
- External Dependencies
- Using a Prebuilt DLL From Windows (libpng)
- Cross-compiling from Linux to Windows with Clang
- Cross-compile a Rust application from Linux to Windows
- 6 Answers 6
- Static compile sdl2
- Let’s cross-compile examples from rust-sdl2 project from Ubuntu to Windows x86_64
- Run in cmd.exe
- Features
- Dependencies
- Installation
- Usage
- How do I configure Qt for cross-compilation from Linux to Windows target?
- 5 Answers 5
- Building Qt
- Running qmake
Cross-Compiling wxWidgets code from Linux to Windows
I use Code::Blocks IDE with wxWidgets in Debian 8.9 Jessie (x86-64).
When I use the GNU GCC Compiler everything works fine thus compiling nice wxWidgets executable for Linux.
But I need to have my program working on Windows platforms so I have to do cross-compiling.
I have installed mingw32 and followed the cross-compiling instructions given here.
I did my wxWidgets build configuration as follows:
This is so because the MinGW compiler I have is i686-w64-mingw32 , located in the folder /usr/i686-w64-mingw32 , and wxWidgets version is 3.1. My compiler set-up in Code::Blocks should be correct because I managed to do cross-compiling for simple console applications and those run properly on Windows 10.0. But when it comes to wxWidgets applications there are several problems:
The compiler gives me the error (it happens when —static is added to Other compiler options in the build options for the project):
Now since wx directory in question is in the path /usr/i686-w64-mingw32/include/wx-3.1 I added this path to the search directories for the project (the build target only for the moment). This worked fine to proceed further.
My compiler settings are: wx-config —host=i686-w64-mingw32 —static —cflags
The compiler swears again (not surprised though :-)):
Ok I’ve found this one in /usr/i686-w64-mingw32/lib/wx/include/i686-w64-mingw32-msw-unicode-static-3.1 , so added this path to the compiler search directories.
The linker is swearing this time (creeping on my nerves):
for the build target:
for the release target:
My linker settings are wx-config —host=i686-w64-mingw32 —static —libs
I tried hard to fix this with several different build options for the wxWidgets library but with no effect on the result. So please, someone help!
Cross Compile to Windows From Linux
Why did I not know about this? It’s like I just discovered the screw driver!
Granted, this isn’t a silver bullet, but rather a quick way to get a Windows build of platform independent code that you might already have running in Linux. I’ve found that this approach makes it easy to get binaries out the door in a hurry when it’s hard to get a project building with Visual Studio or even on the Windows platform itself (due to, say, a complex build system).
I cover some quick solutions to the most common caveats I’ve run into, below.
Caveats
MinGW GCC vc GCC: Not as Smart with Templates
Whatever the reason, the Debian-packaged mingw flavor of gcc has a tendency to omit the instantiation of templates in many cases leading to missing symbols when linking. For instance, something like the following might sometimes complain that variants of scale can’t be found on link,
A horrible (but effective) solution I’ve found is to push the compile along with a dead function containing references to the template instantiations that you need,
C/C++ Standard Library Dependencies
When compiling C projects, use
When compiling a C++ project, you must use
When shipping a C++ project, you’ll need to include LIBSTDC++-6.DLL and/or LIBGCC_S_SJLJ-1.DLL with your install. You can grab these from your Linux install where you’re performing the build in the associated MinGW directory, e.g., /usr/lib/gcc/x86_64-w64-mingw32/4.6/ . Note that you can have gcc include these libraries statically by including the flags, -static-libgcc and -static-libstdc++ .
External Dependencies
If your project depends on external libraries, you’ll need them available on your Linux machine during your build. I give some quick notes for the case where you’d like to use a pre-built (mingw) windows library and specific notes for Boost.
Note that except for purely C external libraries, the libraries themselves must have been built with MinGW. The naming conventions of C++ symbols differ between MingGW and Visual Studio.
Getting a MinGW build going for each project you might want to use is different. tinc’s cross compilation page gives instructions for a few libraries that it requires. You’ll need to consult the documentation on a project-by-project basis for each of your dependencies.
Using a Prebuilt DLL From Windows (libpng)
LibPNG provides pre-built windows binaries (albeit ancient). To build with the library, download both the binary and developer packages and extract into the same directory. Do the same for zlib since LibPNG depends on it, as well.
To build, give the compiler access to the appropriate include directories and link to the seemingly static .dll.a files. Do not attempt to link to the .dll files. Recall that linking to DLL’s on Windows requires a .lib file at build-time; by convention (at least for GNU projects), these are named with a .dll.a extension,
Cross-compiling from Linux to Windows with Clang
I am trying to cross-compile C applications from Linux (64 bit) to Windows (64 bit) using Clang. I read the page on cross-compilation, which wasn’t too helpful.
As a simple test, I have the following code in test.c :
My best guess so far is clang -o test -target x86_64-win64-?ABI? test.c . However, I have no idea what ABI Windows 64 bit uses. When I run clang with the target triple x86_64-win64-abcdefg , it seems to compile fine—that is, it finishes without error and results in something that is a somewhat-valid binary. That doesn’t make any sense, considering abcdefg is definitely not a valid ABI. The resulting binary is far too big for such a small program, and Windows seems to think it’s a 16-bit program (. ). Disassembling it reveals references to «linux» and «gnu», so it would seem Clang is not even trying to compile for Windows.
Targeting win32 ( x86_64-win32-. ABI. ) results in the following error message:
This error, if I’m not mistaken, is the result of it not knowing where to look for system files. I assume Clang does store Windows header files somewhere, since it claims to be able to cross-compile; but where? If it doesn’t, is there somewhere I can download them?
Is there a list of all the architectures, systems, and ABI’s Clang supports somewhere? The list on the cross-compilation page is not comprehensive.
The page also suggests using -mcpu=. , but a warning suggests that is outdated. Instead, as the warning recommends, I tried -mtune=x86_64 . This seems to have no effect. Is this even necessary, considering the architecture is specified in the target triple?
I have seen some literature that suggests I need lld , LLVM’s experimental linker. Is this the case? I have had some issues compiling lld, and would like to avoid it if possible.
Cross-compile a Rust application from Linux to Windows
Basically I’m trying to compile the simplest code to Windows while I am developing on Linux.
I found these commands by searching the internet:
Sadly, none of them work. It gives me an error about the std crate missing
Is there a way to compile code on Linux that will run on Windows?
6 Answers 6
Other answers, while technically correct, are more difficult than they need to be. There’s no need to use rustc (in fact it’s discouraged, just use cargo ), you only need rustup , cargo and your distribution’s mingw-w64.
Add the target (you can also change this for whatever target you’re cross compiling for):
You can build your crate easily with:
No need for messing around with
/.cargo/config or anything else.
EDIT: Just wanted to add that while you can use the above it can also sometimes be a headache. I wanted to add that the rust tools team also maintains a project called cross: https://github.com/rust-embedded/cross This might be another solution that you want to look into
The Rust distribution only provides compiled libraries for the host system. However, according to Arch Linux’s wiki page on Rust, you could copy the compiled libraries from the Windows packages in the download directory (note that there are i686 and x86-64 packages) in the appropriate place on your system (in /usr/lib/rustlib or /usr/local/lib/rustlib , depending on where Rust is installed), install mingw-w64-gcc and Wine and you should be able to cross-compile.
If you’re using Cargo, you can tell Cargo where to look for ar and the linker by adding this to
/.cargo/config (where $ARCH is the architecture you use):
Note: the exact paths can vary based on your distribution. Check the list of files for the mingw-w64 package(s) (GCC and binutils) in your distribution.
Then you can use Cargo like this:
UPDATE 2019-06-11
This fails for me with:
Static compile sdl2
There is option to static-compile sdl but it didn’t work for me.
Let’s cross-compile examples from rust-sdl2 project from Ubuntu to Windows x86_64
Build examples at once
Or stop after first fail:
cargo build will put binaries in target/x86_64-pc-windows-gnu/debug/examples/
Copy needed files:
Then copy directory target/x86_64-pc-windows-gnu/debug/examples/ to your Windows machine and run exe files.
Run in cmd.exe
If you want to see the console output when running exe files, you may run them from cmd.exe .
To open cmd.exe in current directory in file explorer, right click with shift on empty place in window and choose Open command window here .
Backtraces with mingw should work now — if not use msvc https://github.com/rust-lang/rust/pull/39234
/rust-sdl), (b) it uses the tip of the master branch of rust-sdl2, which no longer works with SDL2 2.0.4, and (c) sine.wav has moved. But after some minor fixes it does indeed work! – Tom Anderson Jan 11 ’19 at 10:13
There is Docker based solution called cross. All the required tools are in virtualized environment so you don’t need to install additional packages for your machine. See Supported targets list.
From project’s README:
Features
- cross will provide all the ingredients needed for cross compilation without touching your system installation.
- cross provides an environment, cross toolchain and cross compiled libraries, that produces the most portable binaries.
- “cross testing”, cross can test crates for architectures other than i686 and x86_64.
- The stable, beta and nightly channels are supported.
Dependencies
- rustup
- A Linux kernel with binfmt_misc support is required for cross testing.
One of these container engines is required. If both are installed, cross will default to docker.
- Docker. Note that on Linux non-sudo users need to be in the docker group. Read the official post-installation steps. Requires version 1.24 or later.
- Podman. Requires version 1.6.3 or later.
Installation
Usage
cross has the exact same CLI as Cargo but as it relies on Docker you’ll have to start the daemon before you can use it.
I’ve had success on Debian (testing) without using Mingw and Wine just following the official instructions. They look scary, but in the end it didn’t hurt that much.
The official instructions also contain info on how to cross-compile C/C++ code. I haven’t needed that, so it’s something I haven’t actually tested.
A couple of remarks for individual points in the official instructions. The numbers match the numbers in the official instructions.
- Debian: sudo apt-get install lld
- Make a symlink named lld-link to lld somewhere in your $PATH. Example: ln -s /usr/bin/lld local_bin/lld-link
- I don’t cross-compile C/C++, haven’t used this point personally.
This is probably the most annoying part. I installed Rust on a Windows box via rustup, and copied the libraries from the directories named in the official docs to the Linux box. Beware, there were sometimes uppercase library filenames, but lld wants them all lowercase (Windows isn’t case-sensitive, Linux is). I’ve used the following to rename all files in current directory to lowercase:
Personally, I’ve needed both Kit directories and just one of the VC dirs.
- rustup target add i686-pc-windows-msvc
- rustup target add x86_64-pc-windows-msvc
For cross-building itself, I’m using the following simple script (32-bit version):
I’m using the script the same way I would use cargo build
How do I configure Qt for cross-compilation from Linux to Windows target?
I want to cross compile the Qt libraries (and eventually my application) for a Windows x86_64 target using a Linux x86_64 host machine. I feel like I am close, but I may have a fundamental misunderstanding of some parts of this process.
I began by installing all the mingw packages on my Fedora machine and then modifying the win32-g++ qmake.conf file to fit my environment. However, I seem to be getting stuck with some seemingly obvious configure options for Qt: -platform and -xplatform . Qt documentation says that -platform should be the host machine architecture (where you are compiling) and -xplatform should be the target platform for which you wish to deploy. In my case, I set -platform linux-g++-64 and -xplatform linux-win32-g++ where linux-win32-g++ is my modified win32-g++ configuration.
My problem is that, after executing configure with these options, I see that it invokes my system’s compiler instead of the cross compiler (x86_64-w64-mingw32-gcc). If I omit the -xplatform option and set -platform to my target spec (linux-win32-g++), it invokes the cross compiler but then errors when it finds some Unix related functions aren’t defined.
Here is some output from my latest attempt: http://pastebin.com/QCpKSNev.
When cross-compiling something like Qt for Windows from a Linux host, should the native compiler ever be invoked? That is, during a cross compilation process, shouldn’t we use only the cross compiler? I don’t see why Qt’s configure script tries to invoke my system’s native compiler when I specify the -xplatform option.
If I’m using a mingw cross-compiler, when will I have to deal with a specs file? Spec files for GCC are still sort of a mystery to me, so I am wondering if some background here will help me.
In general, beyond specifying a cross compiler in my qmake.conf, what else might I need to consider?
5 Answers 5
Just use M cross environment (MXE). It takes the pain out of the whole process:
Build Qt for Windows, its dependencies, and the cross-build tools; this will take about an hour on a fast machine with decent internet access; the download is about 500MB:
Go to the directory of your app and add the cross-build tools to the PATH environment variable:
Run the Qt Makefile generator tool then build:
You should find the binary in the ./release directory:
Some notes:
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.
(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.
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:
Update: The new default is now i686-w64-mingw32.static
Another way to cross-compile software for Windows on Linux is the MinGW-w64 toolchain on Archlinux. It is easy to use and maintain, and it provides recent versions of the compiler and many libraries. I personally find it easier than MXE and it seems to adopt newer versions of libraries faster.
First, you will need an arch-based machine (virtual machine or docker container will suffice). It does not have to be Arch Linux, derivatives will do as well. I used Manjaro Linux. Most of the MinGW-w64 packages are not available at the official Arch repositories, but there is plenty in AUR. The default package manager for Arch (Pacman) does not support installation directly from AUR, so you will need to install and use an AUR wrapper like yay or yaourt. Then installing MinGW-w64 version of Qt5 and Boost libraries is as easy as:
This will also install the MinGW-w64 toolchain ( mingw-w64-gcc ) and other dependencies. Cross-compiling a Qt project for windows (x64) is then as simple as:
To deploy your program you will need to copy corresponding dlls from /usr/x86_64-w64-mingw32/bin/ . For example, you will typically need to copy /usr/x86_64-w64-mingw32/lib/qt/plugins/platforms/qwindows.dll to program.exe_dir/platforms/qwindows.dll .
To get a 32bit version you simply need to use i686-w64-mingw32-qmake-qt5 instead. Cmake-based projects work just as easily with x86_64-w64-mingw32-cmake . This approach worked extremely well for me, was the easiest to set-up, maintain, and extend. It also goes well with continuous integration services. There are docker images available too.
For example, let’s say I want to build QNapi subtitle downloader GUI. I could do it in two steps:
Start the docker container:
sudo docker run -it burningdaylight/mingw-arch:qt /bin/bash
Clone and compile QNapi
git clone —recursive ‘https://github.com/QNapi/qnapi.git’ cd qnapi/ x86_64-w64-mingw32-qmake-qt5 make
That’s it! In many cases, it will be that easy. Adding your own libraries to the package repository (AUR) is also straightforward. You would need to write a PKBUILD file, which is as intuitive as it can get, see mingw-w64-rapidjson, for example.