Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake - Compile in Linux, Execute in Windows

I have a large codebase with Linux dependencies, and I would like to use CMake to compile my code into an executable that can be run on Windows, i.e. I want CMake to produce an ".exe" file or something of that nature.

I have tried using the solution provided on the CMake website: https://cmake.org/cmake/help/v3.4/manual/cmake-toolchains.7.html#cross-compiling however it has not worked...

Here is my CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(myProject VERSION 1.0 LANGUAGES C CXX)
set(CMAKE_CROSSCOMPILING true)
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_VERSION 10.0)
set(CMAKE_SYSTEM_PROCESSOR arm)
find_package(... *all my required packages* REQUIRED)
include(... *required include files*)
add_executable(${PROJECT_NAME} ...)
target_link_libraries(${PROJECT_NAME} ...)

It compiles and will execute on Linux, however I want it to produce a Windows compatible executable.

like image 598
Nikolai Long Avatar asked Apr 25 '26 05:04

Nikolai Long


1 Answers

You need a mingw-w64 toolchain in Linux to do this, for example on Arch Linux you can get all the necessary mingw-w64-... packages through AUR, including mingw-w64-cmake. These packages should get you going:

  • mingw-w64-binutils-symlinks
  • mingw-w64-gcc
  • mingw-w64-cmake

Install others to fulfill any dependencies of your software.

Then you can just run mingw-w64-cmake instead of cmake using your regular CMakeLists.txt. E.g.:

mkdir build-mingw; cd build-mingw
x86_64-w64-mingw32-cmake ../
make

However typically it is a good idea to use a static build so your executable will work standalone. Here is how I do it:

# STATIC stuff (Windows)
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
        set(BUILD_FOR_WIN TRUE)
endif()
option(STATIC_BUILD "Build a static binary." ${BUILD_FOR_WIN})

if (STATIC_BUILD)
        set(CMAKE_EXE_LINKER_FLAGS "-static")
        set(CMAKE_FIND_LIBRARY_SUFFIXES ".a" CONFIG)
        set(BUILD_SHARED_LIBS OFF)
endif()

Which creates a variable, STATIC_BUILD, that the user can set, and is defaulted to ON if compiling for Windows.

There is not much more you need to adapt in your CMake files. For example I need to include extra Qt platform plugins when building Qt:

if (STATIC_BUILD AND ${CMAKE_SYSTEM_NAME} MATCHES "Windows")
        # include plugins into static build on windows
        # (we lack support for static on other platforms right now)
        set(QT_PLUGINS SvgIcon WindowsIntegration WindowsVistaStyle)
endif()

The key takeaway here for you is first to get the proper environment on your system.

like image 188
ypnos Avatar answered Apr 28 '26 07:04

ypnos