How to compile for Windows on Linux with gcc/g++?
Categories:
Cross-Compiling for Windows on Linux with GCC/G++

Learn how to set up a MinGW-w64 cross-compilation environment on Linux to build Windows executables using GCC/G++, including OpenGL and GLUT/FreeGLUT applications.
Developing applications for Windows while working on a Linux system can be a common requirement, especially for cross-platform projects or when targeting specific Windows APIs. This article guides you through setting up a cross-compilation toolchain using MinGW-w64 on Linux, enabling you to compile C and C++ code, including graphics applications with OpenGL and GLUT/FreeGLUT, directly for Windows.
Understanding Cross-Compilation with MinGW-w64
Cross-compilation is the process of compiling code on one platform (the host) to run on another platform (the target). For compiling Windows executables on Linux, MinGW-w64 is the de facto standard. MinGW-w64 (Minimalist GNU for Windows 64-bit) provides a complete GCC toolchain that targets Windows, including compilers (gcc, g++), binutils, and Windows API headers and libraries. It supports both 32-bit and 64-bit Windows targets.
flowchart TD A[Linux Host System] --> B{MinGW-w64 Toolchain} B --> C[Source Code (.c/.cpp)] C --> D[Compilation Process] D --> E[Windows Executable (.exe)] E --> F[Windows Target System] B --"Provides"--> G[Windows Headers & Libraries] G --"Linked during"--> D
Cross-Compilation Workflow from Linux to Windows
Setting Up the MinGW-w64 Toolchain on Linux
The first step is to install the MinGW-w64 toolchain on your Linux distribution. The package names might vary slightly depending on your distribution, but the core components remain the same. You'll typically look for packages like mingw-w64
, gcc-mingw-w64
, g++-mingw-w64
, and their associated development files.
Debian/Ubuntu
sudo apt update
sudo apt install mingw-w64
This command installs the necessary compilers and development files for both 32-bit and 64-bit Windows targets.
Fedora
sudo dnf install mingw64-gcc mingw64-gcc-c++
This will install the 64-bit cross-compilers. For 32-bit, you might need mingw32-gcc
and mingw32-gcc-c++
.
Arch Linux
sudo pacman -S mingw-w64-gcc
Arch Linux typically provides a single package that includes both 32-bit and 64-bit toolchains.
x86_64-w64-mingw32-g++
or x86_64-w64-mingw32-gcc
. For 32-bit, it's i686-w64-mingw32-g++
or i686-w64-mingw32-gcc
.Compiling a Basic C++ Application for Windows
Once the toolchain is installed, compiling a simple C++ application is straightforward. You just need to invoke the correct cross-compiler.
// main.cpp
#include <iostream>
int main() {
std::cout << "Hello from Windows (compiled on Linux)!" << std::endl;
return 0;
}
# Compile for 64-bit Windows
x86_64-w64-mingw32-g++ main.cpp -o hello_windows_64.exe
# Compile for 32-bit Windows
i686-w64-mingw32-g++ main.cpp -o hello_windows_32.exe
Compiling OpenGL and GLUT/FreeGLUT Applications
Compiling graphical applications that use OpenGL and GLUT/FreeGLUT requires linking against the appropriate Windows libraries. MinGW-w64 includes the necessary headers and stub libraries for OpenGL (via opengl32.lib
and gdi32.lib
). For GLUT or FreeGLUT, you'll need to obtain the Windows-compatible .lib
and .dll
files and their corresponding headers.
1. Obtain FreeGLUT for MinGW-w64
Download pre-compiled FreeGLUT binaries for MinGW-w64. You can often find these on the FreeGLUT website or through package managers if available (e.g., mingw-w64-freeglut
on Arch Linux). Extract the include
directory (for headers) and the lib
directory (for .a
and .lib
files) to a known location, or directly into your MinGW-w64 installation's x86_64-w64-mingw32/include
and x86_64-w64-mingw32/lib
directories.
2. Write your OpenGL/FreeGLUT code
Create your C++ source file, for example, opengl_cube.cpp
, including FreeGLUT headers and using OpenGL functions.
3. Compile the application
Use the cross-compiler and link against opengl32
, gdi32
, and freeglut
(or glut32
if using GLUT). You might need to specify the path to your FreeGLUT libraries using -L
and headers using -I
if they are not in the default MinGW-w64 paths.
// opengl_cube.cpp
#include <GL/freeglut.h>
#include <GL/gl.h>
void display() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -5.0f);
glRotatef(45.0f, 1.0f, 1.0f, 0.0f);
glutWireCube(2.0f);
glutSwapBuffers();
}
void reshape(int w, int h) {
glViewport(0, 0, w, h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (double)w / (double)h, 1.0, 100.0);
glMatrixMode(GL_MODELVIEW);
}
int main(int argc, char** argv) {
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutCreateWindow("OpenGL Cube");
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glEnable(GL_DEPTH_TEST);
glutMainLoop();
return 0;
}
# Assuming FreeGLUT headers are in /usr/x86_64-w64-mingw32/include/GL
# and libraries are in /usr/x86_64-w64-mingw32/lib
x86_64-w64-mingw32-g++ opengl_cube.cpp -o opengl_cube.exe \
-I/usr/x86_64-w64-mingw32/include \
-L/usr/x86_64-w64-mingw32/lib \
-lfreeglut -lopengl32 -lgdi32 -Wl,--subsystem,windows
# If FreeGLUT is in a custom path, e.g., ~/freeglut-mingw-w64/lib
# x86_64-w64-mingw32-g++ opengl_cube.cpp -o opengl_cube.exe \
# -I~/freeglut-mingw-w64/include \
# -L~/freeglut-mingw-w64/lib \
# -lfreeglut -lopengl32 -lgdi32 -Wl,--subsystem,windows
-Wl,--subsystem,windows
flag is crucial for GUI applications. Without it, Windows will try to open a console window alongside your graphical application. For console applications, omit this flag.Deployment Considerations
When deploying your compiled Windows executable, remember that it might depend on certain DLLs that are not present by default on all Windows systems. For FreeGLUT applications, you will typically need to distribute the freeglut.dll
(or glut32.dll
) alongside your .exe
file. You can find this DLL in the bin
directory of your MinGW-w64 FreeGLUT distribution.

Deployment of a Windows executable with FreeGLUT DLL