windows: add clang cross-compile support on Linux

This commit is contained in:
Selim Sandal 2026-02-17 22:17:35 +03:00
parent 278e04ebd6
commit 7a2ea1376e
3 changed files with 108 additions and 14 deletions

View File

@ -113,18 +113,42 @@ function(setup_libftdi_windows)
message(STATUS "Building libftdi for Windows...")
file(MAKE_DIRECTORY ${LIBFTDI_BUILD_DIR})
set(LIBFTDI_CMAKE_ARGS
-DCMAKE_SYSTEM_NAME=Windows
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_INSTALL_PREFIX=${CROSS_DEPS_INSTALL_DIR}
-DCMAKE_PREFIX_PATH=${CROSS_DEPS_INSTALL_DIR}
-DLIBUSB_INCLUDE_DIRS=${CROSS_DEPS_INSTALL_DIR}/include/libusb-1.0
-DLIBUSB_LIBRARIES=${CROSS_DEPS_INSTALL_DIR}/lib/libusb-1.0.a
-DFTDIPP=OFF -DBUILD_TESTS=OFF -DDOCUMENTATION=OFF
-DEXAMPLES=OFF -DFTDI_EEPROM=OFF -DPYTHON_BINDINGS=OFF
-DSTATICLIBS=ON
)
if(CMAKE_RC_COMPILER)
list(APPEND LIBFTDI_CMAKE_ARGS -DCMAKE_RC_COMPILER=${CMAKE_RC_COMPILER})
endif()
foreach(_lang C CXX RC)
if(DEFINED CMAKE_${_lang}_COMPILER_TARGET AND NOT "${CMAKE_${_lang}_COMPILER_TARGET}" STREQUAL "")
list(APPEND LIBFTDI_CMAKE_ARGS "-DCMAKE_${_lang}_COMPILER_TARGET=${CMAKE_${_lang}_COMPILER_TARGET}")
endif()
endforeach()
foreach(_flags_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS)
if(DEFINED ${_flags_var} AND NOT "${${_flags_var}}" STREQUAL "")
list(APPEND LIBFTDI_CMAKE_ARGS "-D${_flags_var}=${${_flags_var}}")
endif()
endforeach()
if(DEFINED CMAKE_SYSROOT AND NOT "${CMAKE_SYSROOT}" STREQUAL "")
list(APPEND LIBFTDI_CMAKE_ARGS -DCMAKE_SYSROOT=${CMAKE_SYSROOT})
endif()
execute_process(
COMMAND ${CMAKE_COMMAND}
-DCMAKE_SYSTEM_NAME=Windows
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_INSTALL_PREFIX=${CROSS_DEPS_INSTALL_DIR}
-DCMAKE_PREFIX_PATH=${CROSS_DEPS_INSTALL_DIR}
-DLIBUSB_INCLUDE_DIRS=${CROSS_DEPS_INSTALL_DIR}/include/libusb-1.0
-DLIBUSB_LIBRARIES=${CROSS_DEPS_INSTALL_DIR}/lib/libusb-1.0.a
-DFTDIPP=OFF -DBUILD_TESTS=OFF -DDOCUMENTATION=OFF
-DEXAMPLES=OFF -DFTDI_EEPROM=OFF -DPYTHON_BINDINGS=OFF
-DSTATICLIBS=ON
${LIBFTDI_CMAKE_ARGS}
${LIBFTDI_SRC_DIR}
WORKING_DIRECTORY ${LIBFTDI_BUILD_DIR}
RESULT_VARIABLE CONFIG_RESULT

View File

@ -0,0 +1,52 @@
# CMake Toolchain file for cross-compiling to Windows x64 using Clang + MinGW-w64
# Usage: cmake -DCMAKE_TOOLCHAIN_FILE=cmake/Toolchain-x86_64-w64-mingw32-clang.cmake ..
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(WINDOWS_TARGET_TRIPLE "x86_64-w64-mingw32")
find_program(CMAKE_C_COMPILER NAMES clang)
find_program(CMAKE_CXX_COMPILER NAMES clang++)
find_program(CMAKE_RC_COMPILER NAMES llvm-rc x86_64-w64-mingw32-windres)
if(NOT CMAKE_C_COMPILER OR NOT CMAKE_CXX_COMPILER)
message(FATAL_ERROR "clang/clang++ not found. Please install clang.")
endif()
set(CMAKE_C_COMPILER_TARGET ${WINDOWS_TARGET_TRIPLE})
set(CMAKE_CXX_COMPILER_TARGET ${WINDOWS_TARGET_TRIPLE})
if(CMAKE_RC_COMPILER AND CMAKE_RC_COMPILER MATCHES "llvm-rc$")
set(CMAKE_RC_COMPILER_TARGET ${WINDOWS_TARGET_TRIPLE})
endif()
# Keep target selection compatible with older CMake versions.
set(CMAKE_C_FLAGS_INIT "--target=${WINDOWS_TARGET_TRIPLE}")
set(CMAKE_CXX_FLAGS_INIT "--target=${WINDOWS_TARGET_TRIPLE}")
option(CROSS_COMPILE_DEPS "Download and build Windows dependencies for cross-compilation" ON)
set(CROSS_DEPS_DIR "${CMAKE_BINARY_DIR}/cross-deps" CACHE PATH "Directory for cross-compiled dependencies")
if(EXISTS "/usr/x86_64-w64-mingw32/sys-root/mingw")
set(MINGW_SYSROOT "/usr/x86_64-w64-mingw32/sys-root/mingw")
elseif(EXISTS "/usr/x86_64-w64-mingw32")
set(MINGW_SYSROOT "/usr/x86_64-w64-mingw32")
else()
set(MINGW_SYSROOT "")
endif()
set(CMAKE_FIND_ROOT_PATH ${CROSS_DEPS_DIR} ${MINGW_SYSROOT})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_EXE_LINKER_FLAGS_INIT "-static -static-libgcc -static-libstdc++")
set(ENABLE_UDEV OFF CACHE BOOL "" FORCE)
set(ENABLE_LIBGPIOD OFF CACHE BOOL "" FORCE)
set(ENABLE_REMOTEBITBANG OFF CACHE BOOL "" FORCE)
set(ENABLE_XILINX_VIRTUAL_CABLE OFF CACHE BOOL "" FORCE)
set(BUILD_STATIC ON CACHE BOOL "" FORCE)

View File

@ -206,9 +206,9 @@ openFPGALoader can be installed via MSYS2:
Cross-compilation from Linux
----------------------------
openFPGALoader can be cross-compiled for Windows from Linux using MinGW-w64.
The build system will automatically download and build the required dependencies
(libusb, libftdi).
openFPGALoader can be cross-compiled for Windows from Linux using MinGW-w64
toolchains (GCC or Clang). The build system will automatically download and
build the required dependencies (libusb, libftdi).
**Prerequisites (Debian/Ubuntu):**
@ -217,6 +217,8 @@ The build system will automatically download and build the required dependencies
sudo apt install \
mingw-w64 \
libz-mingw-w64-dev \
clang \
lld \
cmake \
pkg-config \
p7zip-full
@ -230,11 +232,13 @@ The build system will automatically download and build the required dependencies
mingw64-gcc-c++ \
mingw64-zlib \
mingw64-zlib-static \
clang \
lld \
cmake \
p7zip \
p7zip-plugins
**Build:**
**Build (shared steps):**
.. code-block:: bash
@ -242,9 +246,21 @@ The build system will automatically download and build the required dependencies
cd openFPGALoader
mkdir build-win64
cd build-win64
**Configure + build with GCC (MinGW-w64):**
.. code-block:: bash
cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-x86_64-w64-mingw32.cmake ..
cmake --build . --parallel
**Configure + build with Clang (MinGW-w64 target):**
.. code-block:: bash
cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-x86_64-w64-mingw32-clang.cmake ..
cmake --build . --parallel
The resulting ``openFPGALoader.exe`` will be a statically-linked executable
that only depends on standard Windows system DLLs (KERNEL32, msvcrt, WS2_32).
@ -260,6 +276,8 @@ that only depends on standard Windows system DLLs (KERNEL32, msvcrt, WS2_32).
.. code-block:: bash
x86_64-w64-mingw32-strip openFPGALoader.exe
# or
llvm-strip openFPGALoader.exe
**Cross-compilation options:**