- Compiling C++ application for Windows target under Linux
- Installing MinGW toolchain
- General configuration
- Using pkg-config
- Adding runtime libraries to Wine
- Running with Wine under Clion
- How do I invoke the MinGW cross-compiler on Linux?
- 4 Answers 4
- How to compile for Windows on Linux with gcc/g++?
- 7 Answers 7
- Компиляция приложений Windows в Linux
Compiling C++ application for Windows target under Linux
Originally published on 2018-10-14 , updated on 2023-05-26 .
Since forever, I have used Arch Linux for day-to-day computing. Nonetheless, from time to time I need to write some simple code in C++ for Windows. Switching back and forth between operating systems is cumbersome, so compiling under a virtual machine is as well.
The Windows port of GCC is named MinGW (Minimalistic GNU for Windows). Quite surprisingly, it is available in the repositories of major Linux distributions, with a wealth of open-source libraries cross-compiled for the Windows platform.
Leveraging this tool, writing multi-platform software can be almost frictionless. It works well in the IDE CLion too. For demonstration purposes, I provide a sample repository which contains a CMake project of a DLL and Windows executables built with MinGW.
Installing MinGW toolchain
Using Arch Linux, I recommend using the ownstuff unofficial repository. The compiler is packaged in a group named mingw-w64 . You might try compiling it from the AUR, but it can be a real pain. There are also many packages available for various dependency libraries; all package names start with mingw-w64- . For more details, please refer to the Arch Wiki.
MinGW is also available in the official repository under Debian — the meta-package gcc-mingw-w64 . There are numerous precompiled libraries, all having mingw in their package names. There is also an entry on the Debian Wiki about this topic.
General configuration
The most important thing is to define the compiler executables and set CMAKE_SYSTEM_NAME :
cmake_minimum_required(VERSION 3.0) project(mingw-test) set(CMAKE_SYSTEM_NAME Windows) SET(CMAKE_C_COMPILER i686-w64-mingw32-gcc) SET(CMAKE_CXX_COMPILER i686-w64-mingw32-g++) SET(CMAKE_RC_COMPILER i686-w64-mingw32-windres) set(CMAKE_RANLIB i686-w64-mingw32-ranlib) set(CMAKE_CXX_FLAGS "$ -std=c++14") set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS)
Then, you simply define the executable. This requires no further comments.
add_executable(example example.cpp)
To cross-compile a dynamic loadable library, you use add_library . However, for convenience, it is better to set PREFIX and SUFFIX to empty strings. This way, you can use the whole filename (with the .dll extension) as the target name.
add_library(shared_lib.dll SHARED shared_lib.cpp shared_lib.h) set_target_properties(shared_lib.dll PROPERTIES PREFIX "" SUFFIX "" LINK_FLAGS "-Wl,--add-stdcall-alias" POSITION_INDEPENDENT_CODE 0 # this is to avoid MinGW warning; # MinGW generates position-independent-code for DLL by default )
To link the executable with the aforementioned DLL, you add:
target_link_libraries(example shared_lib.dll)
Using pkg-config
The common way of defining library compilation flags and directories under Unix is using the pkg-config tool. This way, your codebase is not dependent on the exact layout of directories of the distribution. Each library provides a .pc file with build parameters such as header locations, compiler flags, etc. Many packages compiled for MinGW also provide .pc files, at least under Debian and Arch Linux.
For example, let’s add zlib as a dependency:
Load PkgConfig package and find zlib:
include(FindPkgConfig) find_package(PkgConfig REQUIRED) pkg_check_modules(ZLIB "zlib")
Add dependencies to example executable:
include_directories($ZLIB_INCLUDE_DIRS>) target_link_libraries(example $ZLIB_LIBRARIES>)
Adding runtime libraries to Wine
When you try to run your freshly cross-compiled program under Wine, it will probably fail with a message like this:
0009:err:module:import_dll Library libstdc++-6.dll (which is needed by L"your-program.exe") not found
It means that Wine cannot find the runtime libraries on which your program depends. They are usually located under /usr/i686-w64-mingw32/bin . You’ll need to add this path to the PATH variable within the Wine subsystem.
To do so, edit the file ~/.wine/system.reg . This file represents the Windows Registry under Wine. Find the PATH variable definition under [System\\CurrentControlSet\\Control\\Session Manager\\Environment] section. Append the library path translated into a Windows-like path: Z:\usr\i686-w64-mingw32\bin so it looks like this:
"PATH"=str(2):"C:\\windows\\system32;C:\\windows;C:\\windows\\system32\\wbem;Z:\\usr\\i686-w64-mingw32\\bin"
Running with Wine under Clion
Your CMake project should be loaded by Clion without issues. Windows-specific headers like windows.h are also available. The build will configure itself automatically, but running the target executables will not. Fortunately, you can modify the generated Run/Debug configurations to call Wine, as shown in the picture:
Atom/RSS feed. Copyright by Michał Słomkowski. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License. This website is a perpetual work in progress. Last compilation: 2023-07-07 .
Michał Słomkowski — software developer, tinkerer and hardware enthusiast . Based in Poznań, Poland . Feel free to contact me if you have any questions or ideas. If you’re a human being, you can easily decode my e-mail: michal [‘at’ character] domain this site is hosted on. Please inform me about any errors and inaccuracies you stumble upon.
How do I invoke the MinGW cross-compiler on Linux?
and downloaded 500 MB of packages, but I cannot find out how to actually run it. There is no mingw executable, so how do I actually compile with it?
If you run the following command from a terminal it should tell you the executable of the compiler ( g++ in this example case ). You can then edit your makefile appropriately. «locate mingw | grep g++»
@gipi In cmake I just issue a «cmake -G «MinGW Makefiles» for compiling on windows and «cmake -G «Unix Makefiles» when compiling on my linux box to have the Makefile built. Is this what you’re after? If not, you’ll need to elaborate 🙂
4 Answers 4
If you look at the file lists on the Ubuntu package webserver for mingw-w64 ‘s constituent packages:
You can see that mingw-w64 provides a toolchain, i.e. a set of alternative tools (compiler, linker, headers, etc.) used to compile your code for another system.
Assuming you want to compile C++ code for a 64-bit system, you’ll need to use /usr/bin/x86_64-w64-mingw32-g++-win32 . You can use the CXX environment variable to tell most Makefiles to use that compiler to compile code.
There is no variable for toolchain, but you can set variables for C and C++ compilers: CC and CXX respectively.
Another option is to take a look at Mingw Cross Environment (MXE), which is specifically targetting at cross compiling from Linux to Windows (and lately also to Mac). The package has bult-in xupport for a large number of libraries and is actively being developed. Just take a look at the website to find out if it suits your needs.
By the way,it is suggested you use the development rather than the release version. This is because release versions are generally outdated very fast, due to package maintainers (of the libraries) changing URLs resulting in the MXE release version becoming broken. The development version is generally more up-to-date.
There’s no mention about Mac on the website? This seems pretty neat, I’m new to this, so I’m guessing your tool creates the «cross-compiler» first, and then I just have to use your created toolchain to compile things.
Well, it’s not «mine», but that’s pretty much what it does. Not sure about the current state regarding Mac support (I haven’t used mxe in a while). It has been mentioned in the past that they were working on support, but I have no idea if it’s actually been implemented.
How to compile for Windows on Linux with gcc/g++?
So I was wondering if it is possible to have g++ make static compiled Windows executables that contains everything needed? I don’t have Windows, so it would be really cool, if I could do that on Linux 🙂
@AndiDog, «First dose for free», right. Anyway, setting up automated build process on Windows machine, while you have a completed and working one for Linux, is unnecessary.
@el.pescado, building and testing are completely different tasks. Windows is unnecessary for the former.
7 Answers 7
mingw32 exists as a package for Linux. You can cross-compile and -link Windows applications with it. There’s a tutorial here at the Code::Blocks forum. Mind that the command changes to x86_64-w64-mingw32-gcc-win32 , for example.
Ubuntu, for example, has MinGW in its repositories:
$ apt-cache search mingw [. ] g++-mingw-w64 - GNU C++ compiler for MinGW-w64 gcc-mingw-w64 - GNU C compiler for MinGW-w64 mingw-w64 - Development environment targeting 32- and 64-bit Windows [. ]
If you use debian, mingw32 is already in the repository, together with few precompiled libraries too.
Well, there’s a cross-compilation environment at nongnu.org/mingw-cross-env. It includes freeglut, for example. But I haven’t used this, so don’t ask me about it 😉
Does the «32» in mingw32 mean that I can only produce a 32-bit binary? Is there a solution to produce a 64-bit binary as well?
bluenote10: there are variants that build for x64, such as «x86_64-w64-mingw32-g++». The base «mingw32» may or may not be capable, but it’s easy enough to install/use the variants by name. ar2015: Does it not support C++11 at all or are you talking about a problem you had with it? I’m working on getting a project to build with mingw as we speak and this would be good information to know. Other threads indicate that it does support c++11 (e.g. stackoverflow.com/questions/16136142/…). Of course I’d be happy to help, but a separate post would be best for that.
Suggested method gave me error on Ubuntu 16.04: E: Unable to locate package mingw32
To install this package on Ubuntu please use following:
sudo apt-get install mingw-w64
After install you can use it:
For 64-bit use: x86_64-w64-mingw32-g++
For 32-bit use: i686-w64-mingw32-g++
I tried. It just throws all sort of errors regarding DWORD, LPVOID, WORD, BYTE and so on. Isn’t doing anything cross-compilation
@RichardMcFriendOluwamuyiwa Looks like you missed some headers to compile it on linux. It could generate binaries for running on Win machine. Please update your sources.
I made it work by including the windows.h before the winbase.h header. VS code was automatically rearranging the includes and leading to error so I had to force the order by empty comment lines
One option of compiling for Windows in Linux is via mingw. I found a very helpful tutorial here.
To install mingw32 on Debian based systems, run the following command:
sudo apt-get install mingw32
To compile your code, you can use something like:
i586-mingw32msvc-g++ -o myApp.exe myApp.cpp
You’ll sometimes want to test the new Windows application directly in Linux. You can use wine for that, although you should always keep in mind that wine could have bugs. This means that you might not be sure that a bug is in wine, your program, or both, so only use wine for general testing.
To install wine, run:
sudo apt-get install wine
Компиляция приложений Windows в Linux
Одна из потрясающих особенностей Linux состоит в том, что, работая в нем, вы можете создавать приложения Windows. Такую возможность обеспечивает пакет mingw-w64. В его состав входят компиляторы для создания 32- и 64-битного кода С и С++ для систем Windows. После установки пакета mingw-w64 генерация кода Windows осуществляется следующим образом:
# C i686-w64-mingw32-gcc hello.c -o hello32.exe # 32-bit x86_64-w64-mingw32-gcc hello.c -o hello64.exe # 64-bit # C++ i686-w64-mingw32-g++ hello.cc -o hello32.exe # 32-bit x86_64-w64-mingw32-g++ hello.cc -o hello64.exe # 64-bit
Компиляторы имеют сложные названия, поэтому лучше всего оформить их в виде make-файла или скрипта.
Компилируемые программы на C будут зависеть от библиотек kernel32.dll и msvcrt.dll. Первая является неотъемлемой частью ОС Windows. Вторая представляет собой стандартную библиотеку времени выполнения C от компании Microsoft и обычно также входит в состав ее операционной системы.
Программы на C++ будут также зависеть от библиотек libstdC++-6.dll и libgcc_s_sjlj-1.dll. Это библиотеки компиляторов Mingw. Они находятся в каталоге /usr/lib/gcc/x86_64-w64-mingw32/. Для того, чтобы статически включить их в состав вашего исполняемого модуля укажите при компиляции ключи:
-static-libgcc -static-libstdc++
P.S. при написании этого поста использовались материалы блога arrayfire (точнее статьи).
P.P.S. кто-нибудь может назвать мне хотя бы один компилятор в Windows, позволяющий создавать двоичный код для Linux?