CMake - Compile in Linux, Execute in Windows

Viewed 5353

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.

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 packets 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.

Related