Merge pull request #627 from selimsandal/master

Fix cross compile on ubuntu 24.04.4 and add clang cross compile support
This commit is contained in:
Gwenhael Goavec-Merou 2026-02-18 09:00:07 +01:00 committed by GitHub
commit a21207c48a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 155 additions and 23 deletions

View File

@ -18,6 +18,7 @@ option(ENABLE_OPTIM "Enable build with -O3 optimization level"
option(BUILD_STATIC "Whether or not to build with static libraries" OFF) option(BUILD_STATIC "Whether or not to build with static libraries" OFF)
option(USE_PKGCONFIG "Use pkgconfig to find libraries" ON) option(USE_PKGCONFIG "Use pkgconfig to find libraries" ON)
option(LINK_CMAKE_THREADS "Use CMake find_package to link the threading library" OFF) option(LINK_CMAKE_THREADS "Use CMake find_package to link the threading library" OFF)
option(WINDOWS_STATIC_ZLIB "Link zlib statically for Windows builds" ON)
if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
set(ENABLE_UDEV OFF) set(ENABLE_UDEV OFF)
@ -223,16 +224,44 @@ if (USE_PKGCONFIG)
endif() endif()
# zlib support (gzip) # zlib support (gzip)
pkg_check_modules(ZLIB zlib) if (${CMAKE_SYSTEM_NAME} MATCHES "Windows")
if (NOT ZLIB_FOUND) if (WINDOWS_STATIC_ZLIB)
# try zlib-ng set(ZLIB_USE_STATIC_LIBS ON)
pkg_check_modules(ZLIB zlib-ng)
if (ZLIB_FOUND)
add_definitions(-DHAS_ZLIBNG)
else()
message(FATAL_ERROR "Could find ZLIB")
endif() endif()
endif(NOT ZLIB_FOUND)
# Use CMake zlib finder for Windows builds to avoid host pkg-config contamination
# during cross-compilation and to allow static linking selection.
find_package(ZLIB QUIET)
if (NOT ZLIB_FOUND)
if (windows_crosscompile)
message(FATAL_ERROR
"zlib for Windows target not found. Install MinGW zlib development files "
"(for example: libz-mingw-w64-dev on Debian/Ubuntu or mingw64-zlib on Fedora).")
else()
message(FATAL_ERROR
"zlib for Windows build not found. Install zlib development files for your "
"Windows toolchain.")
endif()
endif()
if (WINDOWS_STATIC_ZLIB AND ZLIB_LIBRARIES MATCHES "\\.dll\\.a$")
message(FATAL_ERROR
"Static zlib requested (WINDOWS_STATIC_ZLIB=ON), but CMake selected "
"'${ZLIB_LIBRARIES}'. Install static zlib (for example mingw64-zlib-static) "
"or set -DWINDOWS_STATIC_ZLIB=OFF.")
endif()
else()
pkg_check_modules(ZLIB zlib)
if (NOT ZLIB_FOUND)
# try zlib-ng
pkg_check_modules(ZLIB zlib-ng)
if (ZLIB_FOUND)
add_definitions(-DHAS_ZLIBNG)
else()
message(FATAL_ERROR "Could find ZLIB")
endif()
endif(NOT ZLIB_FOUND)
endif()
if (ENABLE_UDEV) if (ENABLE_UDEV)
pkg_check_modules(LIBUDEV libudev) pkg_check_modules(LIBUDEV libudev)

View File

@ -113,18 +113,42 @@ function(setup_libftdi_windows)
message(STATUS "Building libftdi for Windows...") message(STATUS "Building libftdi for Windows...")
file(MAKE_DIRECTORY ${LIBFTDI_BUILD_DIR}) 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( execute_process(
COMMAND ${CMAKE_COMMAND} COMMAND ${CMAKE_COMMAND}
-DCMAKE_SYSTEM_NAME=Windows ${LIBFTDI_CMAKE_ARGS}
-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_SRC_DIR} ${LIBFTDI_SRC_DIR}
WORKING_DIRECTORY ${LIBFTDI_BUILD_DIR} WORKING_DIRECTORY ${LIBFTDI_BUILD_DIR}
RESULT_VARIABLE CONFIG_RESULT 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 Cross-compilation from Linux
---------------------------- ----------------------------
openFPGALoader can be cross-compiled for Windows from Linux using MinGW-w64. openFPGALoader can be cross-compiled for Windows from Linux using MinGW-w64
The build system will automatically download and build the required dependencies toolchains (GCC or Clang). The build system will automatically download and
(libusb, libftdi). build the required dependencies (libusb, libftdi).
**Prerequisites (Debian/Ubuntu):** **Prerequisites (Debian/Ubuntu):**
@ -216,6 +216,9 @@ The build system will automatically download and build the required dependencies
sudo apt install \ sudo apt install \
mingw-w64 \ mingw-w64 \
libz-mingw-w64-dev \
clang \
lld \
cmake \ cmake \
pkg-config \ pkg-config \
p7zip-full p7zip-full
@ -229,11 +232,13 @@ The build system will automatically download and build the required dependencies
mingw64-gcc-c++ \ mingw64-gcc-c++ \
mingw64-zlib \ mingw64-zlib \
mingw64-zlib-static \ mingw64-zlib-static \
clang \
lld \
cmake \ cmake \
p7zip \ p7zip \
p7zip-plugins p7zip-plugins
**Build:** **Build (shared steps):**
.. code-block:: bash .. code-block:: bash
@ -241,22 +246,44 @@ The build system will automatically download and build the required dependencies
cd openFPGALoader cd openFPGALoader
mkdir build-win64 mkdir build-win64
cd 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 -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-x86_64-w64-mingw32.cmake ..
cmake --build . --parallel 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 The resulting ``openFPGALoader.exe`` will be a statically-linked executable
that only depends on standard Windows system DLLs (KERNEL32, msvcrt, WS2_32). that only depends on standard Windows system DLLs (KERNEL32, msvcrt, WS2_32).
.. NOTE::
``zlib`` for the Windows target is required. Configuration fails if it is
missing (install ``libz-mingw-w64-dev`` on Debian/Ubuntu or
``mingw64-zlib`` on Fedora/RHEL/Rocky).
``zlib`` is linked statically by default on Windows builds
(``-DWINDOWS_STATIC_ZLIB=ON``).
**Optional: Strip debug symbols to reduce size:** **Optional: Strip debug symbols to reduce size:**
.. code-block:: bash .. code-block:: bash
x86_64-w64-mingw32-strip openFPGALoader.exe x86_64-w64-mingw32-strip openFPGALoader.exe
# or
llvm-strip openFPGALoader.exe
**Cross-compilation options:** **Cross-compilation options:**
- ``-DCROSS_COMPILE_DEPS=OFF`` - Disable automatic dependency download (use system libraries) - ``-DCROSS_COMPILE_DEPS=OFF`` - Disable automatic dependency download (use system libraries)
- ``-DENABLE_CMSISDAP=ON`` - Enable CMSIS-DAP support (requires manually providing hidapi) - ``-DENABLE_CMSISDAP=ON`` - Enable CMSIS-DAP support (requires manually providing hidapi)
- ``-DWINDOWS_STATIC_ZLIB=OFF`` - Allow dynamic zlib linkage (produces ``zlib1.dll`` runtime dependency)
Common Common
====== ======