Skip to content

Fixes for MinGW cross compilation on Linux to generate Windows binaries (Part 3) and MSVC compatibility - #1504

Open
Nightwalker-87 wants to merge 8 commits into
testingfrom
fix/win_binaries
Open

Fixes for MinGW cross compilation on Linux to generate Windows binaries (Part 3) and MSVC compatibility#1504
Nightwalker-87 wants to merge 8 commits into
testingfrom
fix/win_binaries

Conversation

@Nightwalker-87

@Nightwalker-87 Nightwalker-87 commented Aug 1, 2026

Copy link
Copy Markdown
Member

Restored cross-compiling for Windows binaries (i686 and x86-64) & major refactoring of cmake build configuration

  1. Major refactoring for cmake build configuration
  • New subfolder stlink-env for system-specific sources, headers and libraries
  • System-specific definitions, header files and libraries relocated and condensed in subordinate CMakeLists.txt
  • Simplified environment-specific compilation of function init_chipids( )
  • Corrected system-specific include in map_file.h
  1. Fixes for cross-compiling and native compiling on Windows (WIN32, MSVC, MINGW)
  • Fixes for cmake build configuration
  • Removed duplicate libusb build routine
  • Fix for getopt: compile-time constants
  • Fixed filepath issue for chipid files
  • Added missing include guard for win32_socket.h
  • Fixed includes in trace.h, remote.h, gdb-remote.h
  • Minor formatting fixes
  • Fixes for native compiling on Windows (MinGW)
  • Fixed MSVC compatibility: Use vcpkg with MSVC (contribution by [slyshykO])
  1. Fixed libusb compilation with autotools
  • Fixed broken Multi-COMMAND-execute_process()-pipe in Findlibusb.cmake, causing race conditions
  • Updated shell script gen_binaries_win.sh

(Closes #1472) (Closes #1478) (Closes #1497) (Closes #1501)

- New subfolder stlink-env for system-specific sources, headers and libraries
- System-specific definitions, header files and libraries relocated and condensed in subordinate CMakeLists.txt
- Simplified environment-specific compilation of function init_chipids( )
- Corrected system-specific include in map_file.h
- Fixes for cmake build configuration
- Removed duplicate libusb build routine
- Fix for getopt: compile-time constants
- Fixed filepath issue for chipid files
- Added missing include guard for win32_socket.h
- Fixed includes in trace.h, remote.h, gdb-remote.h
- Minor formatting fixes
- Fixed broken Multi-COMMAND-execute_process()-pipe in Findlibusb.cmake, causing race conditions
- Updated shell script gen_binaries_win.sh
@Nightwalker-87

Copy link
Copy Markdown
Member Author

Could someone please review this PR and test the changes in a native Windows environment?

@Nightwalker-87
Nightwalker-87 requested a review from klonyyy August 15, 2026 15:00
@klonyyy

klonyyy commented Aug 15, 2026

Copy link
Copy Markdown
Collaborator

Hey @Nightwalker-87, I can go through the changes and test the compilation on my Windows machine - apart from compiling and running the stlink lib do you have any other tests you'd like me to perform?

@Nightwalker-87

Nightwalker-87 commented Aug 15, 2026

Copy link
Copy Markdown
Member Author

@klonyyy Thank you for your help. I have tested the cross-complining intensively on Debian, but my possibilities on running and actively using the toolset is very limited due to VM use. This it would be great to have people there to test it more intensively on a native Windows system.
The focus should be set on compilation, proper placing of all dependencies and files and the focus on error messages and notifications - in short the issues people came across in the last release v1.8.0. I hope these are all resolved by now. Please also let me know, if there are any inconsistencies in this PR.

I am aware of that there are quite a few changes to review though...
If you have any specific questions, please let me know.

@Nightwalker-87

Nightwalker-87 commented Aug 28, 2026

Copy link
Copy Markdown
Member Author

Waiting for at least a second reviewer here...
ping @slyshykO

@slyshykO

Copy link
Copy Markdown
Collaborator

@Nightwalker-87, sorry for the delay and my detachment from the project.
Can you tell me if we still need to support building with MSVC, cause this branch doesn't support it?
libusb wasn't downloaded.

Comment thread src/stlink-lib/remote.h Outdated
Comment thread src/stlink-lib/remote.h Outdated
@Nightwalker-87

Nightwalker-87 commented Sep 10, 2026

Copy link
Copy Markdown
Member Author

@Nightwalker-87, sorry for the delay and my detachment from the project. Can you tell me if we still need to support building with MSVC, cause this branch doesn't support it? libusb wasn't downloaded.

I haven't tested MSVC and focussed on the original approach which was present before this was added.

@slyshykO Add the following code block in Findlibusb.cmake to see if this is applicable:

# Windows (native MSVC or MinGW without cross-compiling)
elseif(MSVC OR (WIN32 AND NOT EXISTS "/etc/debian_version"))
    # Fix for missing ssize_t on Windows (required by libusb)
    add_compile_definitions(_SSIZE_T_DEFINED ssize_t=int64_t)

    # Try to locate an existing Windows installation of libusb
    find_path(LIBUSB_INCLUDE_DIR
        NAMES libusb.h
        HINTS "C:/Program Files/libusb-1.0/include" "C:/Program Files (x86)/libusb-1.0/include"
        PATH_SUFFIXES libusb-1.0
    )

    find_library(LIBUSB_LIBRARY
        NAMES usb-1.0 libusb-1.0
        HINTS "C:/Program Files/libusb-1.0" "C:/Program Files (x86)/libusb-1.0"
    )

    # Nothing found locally -> fetch and build libusb via the community-maintained "libusb-cmake" wrapper,
    # since upstream libusb ships no native CMake build system for MSVC
    if(NOT LIBUSB_INCLUDE_DIR OR NOT LIBUSB_LIBRARY)
      message(STATUS "libusb-1.0 not found locally. Downloading and building from source via FetchContent...")

      set(LIBUSB_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
      set(LIBUSB_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
      set(LIBUSB_BUILD_TESTING OFF CACHE BOOL "" FORCE)
      set(LIBUSB_INSTALL_TARGETS OFF CACHE BOOL "" FORCE)

      FetchContent_Declare(
        libusb_cmake
        GIT_REPOSITORY "https://github.com/libusb/libusb-cmake.git"
        GIT_TAG "v1.0.30-0"
      )
      FetchContent_MakeAvailable(libusb_cmake)

      # libusb-cmake exposes the target "libusb::usb-1.0" - alias it to "libusb::libusb" so downstream
      # CMakeLists.txt files in this project can keep linking against the same target name on every
      # platform (Unix, MinGW and now MSVC)
      if(NOT TARGET libusb::libusb)
        add_library(libusb::libusb ALIAS libusb::usb-1.0)
      endif()
 
      set(LIBUSB_FOUND TRUE)
    endif()

I need feedback and external testing to address this.

@slyshykO

Copy link
Copy Markdown
Collaborator

@Nightwalker-87, sorry for the delay and my detachment from the project. Can you tell me if we still need to support building with MSVC, cause this branch doesn't support it? libusb wasn't downloaded.

I haven't tested MSVC and focussed on the original approach which was present before this was added.

@slyshykO Add the following code block in Findlibusb.cmake to see if this is applicable:

# Windows (native MSVC or MinGW without cross-compiling)
elseif(MSVC OR (WIN32 AND NOT EXISTS "/etc/debian_version"))
    # Fix for missing ssize_t on Windows (required by libusb)
    add_compile_definitions(_SSIZE_T_DEFINED ssize_t=int64_t)

    # Try to locate an existing Windows installation of libusb
    find_path(LIBUSB_INCLUDE_DIR
        NAMES libusb.h
        HINTS "C:/Program Files/libusb-1.0/include" "C:/Program Files (x86)/libusb-1.0/include"
        PATH_SUFFIXES libusb-1.0
    )

    find_library(LIBUSB_LIBRARY
        NAMES usb-1.0 libusb-1.0
        HINTS "C:/Program Files/libusb-1.0" "C:/Program Files (x86)/libusb-1.0"
    )

    # Nothing found locally -> fetch and build libusb via the community-maintained "libusb-cmake" wrapper,
    # since upstream libusb ships no native CMake build system for MSVC
    if(NOT LIBUSB_INCLUDE_DIR OR NOT LIBUSB_LIBRARY)
      message(STATUS "libusb-1.0 not found locally. Downloading and building from source via FetchContent...")

      set(LIBUSB_BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
      set(LIBUSB_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
      set(LIBUSB_BUILD_TESTING OFF CACHE BOOL "" FORCE)
      set(LIBUSB_INSTALL_TARGETS OFF CACHE BOOL "" FORCE)

      FetchContent_Declare(
        libusb_cmake
        GIT_REPOSITORY "https://github.com/libusb/libusb-cmake.git"
        GIT_TAG "v1.0.30-0"
      )
      FetchContent_MakeAvailable(libusb_cmake)

      # libusb-cmake exposes the target "libusb::usb-1.0" - alias it to "libusb::libusb" so downstream
      # CMakeLists.txt files in this project can keep linking against the same target name on every
      # platform (Unix, MinGW and now MSVC)
      if(NOT TARGET libusb::libusb)
        add_library(libusb::libusb ALIAS libusb::usb-1.0)
      endif()
 
      set(LIBUSB_FOUND TRUE)
    endif()

I need feedback and external testing to address this.

This didn't work. Along with libusb, we also need the pthread library, so adding only libusb didn't allow us to build the project with MSVC.
I successfully built the project with the support of vcpkg.
So, let's fix the include issues and push this PR.

@a-michelis

Copy link
Copy Markdown
Collaborator

Hello all, I can test MSVC support and assist on it, but using the toolset is impossible for me due to lack of devices currently

@Nightwalker-87

Nightwalker-87 commented Sep 13, 2026

Copy link
Copy Markdown
Member Author

This didn't work. Along with libusb, we also need the pthread library, so adding only libusb didn't allow us to build the project with MSVC. I successfully built the project with the support of vcpkg. So, let's fix the include issues and push this PR.

Ok, if vcpkg is the cleaner way of getting this resolved, we should make use of it and also include this in this PR to ensure everything remains functional. I'd like to avoid Post-Release issues regarding installation in this context.

@a-michelis Thx for popping in. Please assist @slyshykO to allow for independent testing and updating the documentation for MSVC which you contributed earlier.

@Nightwalker-87

Nightwalker-87 commented Sep 13, 2026

Copy link
Copy Markdown
Member Author

Proposal:

  1. New file vcpkg.json in project root directory:
{
  "name": "stlink",
  "dependencies": [
    "libusb",
    "pthreads"
  ]
}
  1. cmake/modules/Findlibusb.cmake
 # Windows (native MSVC or MinGW without cross-compiling)
 elseif(MSVC OR (WIN32 AND NOT EXISTS "/etc/debian_version"))
     # Fix for missing ssize_t on Windows (required by libusb)
     add_compile_definitions(_SSIZE_T_DEFINED ssize_t=int64_t)

     # Try to locate an existing Windows installation of libusb
     find_path(LIBUSB_INCLUDE_DIR
         NAMES libusb.h
         HINTS "C:/Program Files/libusb-1.0/include" "C:/Program Files (x86)/libusb-1.0/include"
         PATH_SUFFIXES libusb-1.0
     )

     find_library(LIBUSB_LIBRARY
         NAMES usb-1.0 libusb-1.0
         HINTS "C:/Program Files/libusb-1.0" "C:/Program Files (x86)/libusb-1.0"
     )
+
+    # Nothing found locally -> libusb does not ship a CMake config file (neither
+    # upstream nor via vcpkg), only a pkg-config (.pc) file, so fall back to the
+    # same pkg-config lookup already used below for other Unix-like systems.
+    # This also picks up a vcpkg-provided pkgconf/libusb installation when the
+    # vcpkg toolchain file is passed via -DCMAKE_TOOLCHAIN_FILE.
+    if(NOT LIBUSB_INCLUDE_DIR OR NOT LIBUSB_LIBRARY)
+        find_package(PkgConfig QUIET)
+        if(PKG_CONFIG_FOUND)
+            pkg_search_module(PC_LIBUSB QUIET libusb-1.0)
+        endif()
+
+        find_path(LIBUSB_INCLUDE_DIR
+            NAMES libusb.h
+            HINTS ${PC_LIBUSB_INCLUDE_DIRS}
+            PATH_SUFFIXES libusb-1.0
+        )
+
+        find_library(LIBUSB_LIBRARY
+            NAMES usb-1.0
+            HINTS ${PC_LIBUSB_LIBRARY_DIRS}
+        )
+    endif()
  1. doc/compiling.md
 ### Installation

 1. Install `Build Tools for Visual Studio` from <https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022>
 2. Install `cmake` from <https://cmake.org/download/#latest> --> Binary distributions --> Windows x64 Installer<br />
    Ensure that you add cmake to the $PATH system variable when following the instructions by the setup assistant.
    Follow the installation instructions on the website.
 3. Fetch the project source files by running `git clone https://github.com/stlink-org/stlink.git` from the command-line (`cmd.exe`/`powershell.exe`)<br />
    or download and extract (`7zip`) the latest stlink `.zip` release from the Release page on GitHub.
+4. Install `vcpkg` (provides `libusb` and `pthreads` for MSVC, since neither ships a native MSVC build):
+   1. `git clone https://github.com/microsoft/vcpkg.git`
+   2. `cd vcpkg && .\bootstrap-vcpkg.bat`
+   3. `.\vcpkg install libusb pthreads --triplet x64-windows`

 ### Building

 1. Open the command-line (`cmd.exe`/`powershell.exe`) with administrator privileges
 2. Move to the `stlink` directory with `cd C:\$Path-to-your-stlink-folder$\`
 3. Create a new `build` subdirectory and move into it with `cd .\build`.
-4. Configure the project, using the following command: `cmake -G "Visual Studio 17 2022" .. -DCMAKE_BUILD_TYPE="Release"`
+4. Configure the project, using the following command:<br />
+   `cmake -G "Visual Studio 17 2022" .. -DCMAKE_BUILD_TYPE="Release" -DCMAKE_TOOLCHAIN_FILE="C:\$Path-to-your-vcpkg-folder$\scripts\buildsystems\vcpkg.cmake"`
 5. Build the project, using the following command: `cmake --build . --target ALL_BUILD`

What remains open/untested (I can't conclusively clarify this without a real MSVC environment):

  • Whether find_package(Threads REQUIRED) in the main CMakeLists.txt is automatically covered by the vcpkg pthreads port, or whether an additional explicit find_package(pthreads REQUIRED) call is needed for that.
  • Whether pkg_search_module, within the vcpkg toolchain context, correctly finds PKG_CONFIG_PATH pointing to <vcpkg>\installed\x64-windows\lib\pkgconfig, or whether PKG_CONFIG_EXECUTABLE/PKG_CONFIG_PATH also need to be set manually for that.

Could you investigate that?

@slyshykO

Copy link
Copy Markdown
Collaborator

Proposal:

1. New file `vcpkg.json` in project root directory:
{
  "name": "stlink",
  "dependencies": [
    "libusb",
    "pthreads"
  ]
}
2. `cmake/modules/Findlibusb.cmake`
 # Windows (native MSVC or MinGW without cross-compiling)
 elseif(MSVC OR (WIN32 AND NOT EXISTS "/etc/debian_version"))
     # Fix for missing ssize_t on Windows (required by libusb)
     add_compile_definitions(_SSIZE_T_DEFINED ssize_t=int64_t)

     # Try to locate an existing Windows installation of libusb
     find_path(LIBUSB_INCLUDE_DIR
         NAMES libusb.h
         HINTS "C:/Program Files/libusb-1.0/include" "C:/Program Files (x86)/libusb-1.0/include"
         PATH_SUFFIXES libusb-1.0
     )

     find_library(LIBUSB_LIBRARY
         NAMES usb-1.0 libusb-1.0
         HINTS "C:/Program Files/libusb-1.0" "C:/Program Files (x86)/libusb-1.0"
     )
+
+    # Nothing found locally -> libusb does not ship a CMake config file (neither
+    # upstream nor via vcpkg), only a pkg-config (.pc) file, so fall back to the
+    # same pkg-config lookup already used below for other Unix-like systems.
+    # This also picks up a vcpkg-provided pkgconf/libusb installation when the
+    # vcpkg toolchain file is passed via -DCMAKE_TOOLCHAIN_FILE.
+    if(NOT LIBUSB_INCLUDE_DIR OR NOT LIBUSB_LIBRARY)
+        find_package(PkgConfig QUIET)
+        if(PKG_CONFIG_FOUND)
+            pkg_search_module(PC_LIBUSB QUIET libusb-1.0)
+        endif()
+
+        find_path(LIBUSB_INCLUDE_DIR
+            NAMES libusb.h
+            HINTS ${PC_LIBUSB_INCLUDE_DIRS}
+            PATH_SUFFIXES libusb-1.0
+        )
+
+        find_library(LIBUSB_LIBRARY
+            NAMES usb-1.0
+            HINTS ${PC_LIBUSB_LIBRARY_DIRS}
+        )
+    endif()
3. `doc/compiling.md`
 ### Installation

 1. Install `Build Tools for Visual Studio` from <https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022>
 2. Install `cmake` from <https://cmake.org/download/#latest> --> Binary distributions --> Windows x64 Installer<br />
    Ensure that you add cmake to the $PATH system variable when following the instructions by the setup assistant.
    Follow the installation instructions on the website.
 3. Fetch the project source files by running `git clone https://github.com/stlink-org/stlink.git` from the command-line (`cmd.exe`/`powershell.exe`)<br />
    or download and extract (`7zip`) the latest stlink `.zip` release from the Release page on GitHub.
+4. Install `vcpkg` (provides `libusb` and `pthreads` for MSVC, since neither ships a native MSVC build):
+   1. `git clone https://github.com/microsoft/vcpkg.git`
+   2. `cd vcpkg && .\bootstrap-vcpkg.bat`
+   3. `.\vcpkg install libusb pthreads --triplet x64-windows`

 ### Building

 1. Open the command-line (`cmd.exe`/`powershell.exe`) with administrator privileges
 2. Move to the `stlink` directory with `cd C:\$Path-to-your-stlink-folder$\`
 3. Create a new `build` subdirectory and move into it with `cd .\build`.
-4. Configure the project, using the following command: `cmake -G "Visual Studio 17 2022" .. -DCMAKE_BUILD_TYPE="Release"`
+4. Configure the project, using the following command:<br />
+   `cmake -G "Visual Studio 17 2022" .. -DCMAKE_BUILD_TYPE="Release" -DCMAKE_TOOLCHAIN_FILE="C:\$Path-to-your-vcpkg-folder$\scripts\buildsystems\vcpkg.cmake"`
 5. Build the project, using the following command: `cmake --build . --target ALL_BUILD`

What remains open/untested (I can't conclusively clarify this without a real MSVC environment):

* Whether `find_package(Threads REQUIRED)` in the main `CMakeLists.txt` is automatically covered by the vcpkg `pthreads` port, or whether an additional explicit `find_package(pthreads REQUIRED)` call is needed for that.

* Whether `pkg_search_module`, within the vcpkg toolchain context, correctly finds `PKG_CONFIG_PATH` pointing to `<vcpkg>\installed\x64-windows\lib\pkgconfig`, or whether `PKG_CONFIG_EXECUTABLE`/`PKG_CONFIG_PATH` also need to be set manually for that.

Could you investigate that?

this is my fixes - slyshykO@bbbd07b#diff-a883cf46cbd8aa22e92cee2d199e16bf8c02d8d5edbadb9572f806175ca25ad8

@Nightwalker-87

Copy link
Copy Markdown
Member Author

As feared cross-compilation is not successful anymore. It now fails for x86-64.

CMake Error at cmake/modules/Findlibusb.cmake:114 (message):
  libusb make failed with code 2
Call Stack (most recent call first):
  src/stlink-env/CMakeLists.txt:53 (find_package)

@a-michelis

Copy link
Copy Markdown
Collaborator

Tested 43db600 on native Windows with MSVC + vcpkg. Setup: Windows 11 Pro (26200), CMake 3.28.3, vcpkg 2026-07-27, VS 2022 Preview 17.14.36119.2 (MSVC 19.44) and VS 18 Build Tools 18.6.11806.211. No ST-LINK hardware here, so this is build/packaging only.

MSVC + vcpkg works. Configuring with -G "Visual Studio 17 2022" -A x64 plus the vcpkg toolchain succeeds; vcpkg pulls libusb 1.0.30 and pthreads 3.0.0#14. Release and Debug both build with 0 errors and 0 warnings, and st-info --probe runs in both. @slyshykO's per-config libusb selection is correct: LIBUSB_LIBRARY_RELEASE and _DEBUG both resolve and each configuration links the matching lib, with the right pthreadVC3/pthreadVC3d DLL copied beside the exes.


On the x86-64 cross-compilation failure at Findlibusb.cmake:114

I think the cause is four lines above, at line 98:

COMMAND ./configure --host=i686-w64-mingw${ARCH} --prefix=...

ARCH is 64 or 32 and is used in only this one place, so it expands to:

  • ARCH=32 -> i686-w64-mingw32 (valid)
  • ARCH=64 -> i686-w64-mingw64 (not a real triple)

The 64-bit triple is x86_64-w64-mingw32. The 32 in mingw32 refers to the Win32 API rather than the word size, so it should stay 32 while the prefix changes from i686 to x86_64. As written, the prefix is never switched.

That also explains why make fails rather than configure: with a --host whose ${host}-gcc does not exist, autoconf falls back to the native gcc with a warning and exits 0, then make fails building libusb's Windows backend against native Linux headers. Error code 2 fits.

This predates the MSVC work (git log -L points at dd2f03a / 2be6fd7), so it is probably not a regression from #1507. My guess is that splitting the chained COMMANDs into separate execute_process calls in 2be6fd7 is what finally lets the build reach make, exposing the bad triple. I have no Debian cross environment to confirm, but the one-line change to try is --host=x86_64-w64-mingw32 for the 64-bit case.


4 MSVC issues at 43db600

1. gen_binaries_msvc.bat fails when VS18 is installed but CMake is older than 4.2. The vswhere [18.0,19.0) probe matched my VS 18 Build Tools, so the script selected Visual Studio 18 2026 and CMake 3.28.3 aborted with "Could not create named generator". It does not fall back to the VS 17 generator that is installed and supported. The CMake 4.2 requirement is documented in prose but not enforced by the script.
2. cmake --install produces an installation that cannot run. Installed bin/st-info.exe imports libusb-1.0.dll and pthreadVC3.dll, and neither is installed, so the tools fail to start. libusb.h and getopt.h are also absent while the installed libusb_settings.h and unistd.h include them, which leaves lib/stlink-static.lib and the installed headers unusable downstream. v1.8.0 shipped include/libusb-1.0/libusb.h and lib/libusb-1.0.lib. Dropping the install step from compiling.md hides this, but the INSTALL target and cmake/packaging are still present.
3. Without the vcpkg toolchain, configure fails at CMakeLists.txt:95 with "Could not find a package configuration file provided by PThreads4W" and no hint that vcpkg is needed. find_package(PThreads4W QUIET) plus an explicit FATAL_ERROR pointing at doc/compiling.md would be friendlier.
4. The winsock v1/v2 conflict is latent rather than fixed. It works because libusb >= 1.0.30 dropped its #include <winsock.h> and the vcpkg port is exactly 1.0.30. The MSVC find_path/find_library fallback can still select an older system libusb -- a previous stlink release's bundled copy did exactly that on my machine -- and then every TU where libusb.h precedes win32_socket.h fails with ~60 C2011/C2375 redefinitions of sockaddr/timeval/fd_set and the socket functions. c1763e0 addresses this per-TU by reordering includes, which has to be repeated for every new TU. Adding -D_WINSOCKAPI_ to the WIN32 definitions in src/stlink-env/CMakeLists.txt suppresses winsock.h v1 globally and independently of include order, since winsock2.h guards on WINSOCK2API and defines WINSOCKAPI itself.

On the two open questions

  • find_package(Threads REQUIRED) is not covered by the vcpkg pthreads port. @slyshykO's commit already resolves it: FindThreads accepts native Win32 threads while usb.c uses the pthread API. The port ships a PThreads4W CMake config and find_package(PThreads4W REQUIRED) works, resolving both configurations.
  • pkg_search_module never runs on the vcpkg path: the new branch keys on VCPKG_TARGET_TRIPLET and reads VCPKG_INSTALLED_DIR directly, so PkgConfig is not invoked at all. The proposed pkg-config fallback is not needed here.

A few words on the old build-from-source approach of libusb

on Win32 there is no standard location for third-party libraries that aren't shipped through a platform mechanism, so build systems targeting Windows usually ship them directly. Anything else pushes the user into manually adding install directories to PATH. This repo already shows both halves of that: the find_path/find_library hints in Findlibusb.cmake invent a C:/Program Files/libusb-1.0 convention rather than following one, and the libusb that find_library actually picked up on my machine was C:/Program Files (x86)/stlink/include/libusb-1.0 - the copy bundled by our own v1.8.0 release. (That also caused the winsock clash in item 4, since the bundled copy is older than 1.0.30.)

To be clear, this is not an argument against vcpkg. vcpkg builds libusb and pthreads from source into the build tree and copies the DLLs next to the binaries, so it is per-project vendoring too - the difference is who curates the recipe, and outsourcing that to vcpkg is a reasonable trade - if we don't mind requiring users to install a separate package manager, essentially.

What I would like to keep from the older approach is the property that the shipped artifacts are self-contained. With statically vendored libusb, stlink.dll imported only WSOCK32/WS2_32/KERNEL32 and the CRT, and the tools ran with nothing added to PATH. That property is what item 2 in the issues i'm bringing loses: the installed exes now import libusb-1.0.dll and pthreadVC3.dll and neither is installed. Whichever dependency source we settle on, I think cmake --install should keep producing a tree that runs as-is, and packaging under cmake/packaging depends on that too.

@Nightwalker-87

Copy link
Copy Markdown
Member Author

This predates the MSVC work (git log -L points at dd2f03a / 2be6fd7), so it is probably not a regression from #1507. My guess is that splitting the chained COMMANDs into separate execute_process calls in 2be6fd7 is what finally lets the build reach make, exposing the bad triple. I have no Debian cross environment to confirm, but the one-line change to try is --host=x86_64-w64-mingw32 for the 64-bit case.

From what I can tell, it just worked again before one started to address the MSVC issue.

@a-michelis

Copy link
Copy Markdown
Collaborator

This predates the MSVC work (git log -L points at dd2f03a / 2be6fd7), so it is probably not a regression from #1507. My guess is that splitting the chained COMMANDs into separate execute_process calls in 2be6fd7 is what finally lets the build reach make, exposing the bad triple. I have no Debian cross environment to confirm, but the one-line change to try is --host=x86_64-w64-mingw32 for the 64-bit case.

From what I can tell, it just worked again before one started to address the MSVC issue.

Inability to build due to arch errors is what prompted me to do the previous PR in the first place, - if my memory is intact, the zip archive downloaded by the older approach gave errors depending on the arch (some calculated zip path was off).

But maybe I was the one doing something wrong back then!

@Nightwalker-87

Copy link
Copy Markdown
Member Author

I have now removed any potential remnants of previous build approaches and restarted a clean build from scratch. Both variants now compile successfully.

https://pastebin.com/vbu5QSpq

@a-michelis

Copy link
Copy Markdown
Collaborator

I have now removed any potential remnants of previous build approaches and restarted a clean build from scratch. Both variants now compile successfully.

https://pastebin.com/vbu5QSpq

Worth noting though that your log shows the triple is still malformed and is just being papered over:

    32-bit: checking host system type... i686-w64-mingw32
            checking for i686-w64-mingw32-gcc... /usr/bin/i686-w64-mingw32-gcc

    64-bit: checking host system type... i686-w64-mingw64
            checking for i686-w64-mingw64-gcc... /usr/bin/x86_64-w64-mingw32-gcc
            checking for i686-w64-mingw64-g++... no
            configure: WARNING: using cross tools not prefixed with host triplet

@Nightwalker-87

Nightwalker-87 commented Sep 13, 2026

Copy link
Copy Markdown
Member Author

I have now removed any potential remnants of previous build approaches and restarted a clean build from scratch. Both variants now compile successfully.
https://pastebin.com/vbu5QSpq

Worth noting though that your log shows the triple is still malformed and is just being papered over:

    32-bit: checking host system type... i686-w64-mingw32
            checking for i686-w64-mingw32-gcc... /usr/bin/i686-w64-mingw32-gcc

    64-bit: checking host system type... i686-w64-mingw64
            checking for i686-w64-mingw64-gcc... /usr/bin/x86_64-w64-mingw32-gcc
            checking for i686-w64-mingw64-g++... no
            configure: WARNING: using cross tools not prefixed with host triplet

This would subsequently result in:

# Windows-Build with MinGW via cross-compiling on Debian-Linux
elseif(MINGW AND EXISTS "/etc/debian_version")
    # Architecture: 64-bit or 32-bit?
    if (CMAKE_SIZEOF_VOID_P EQUAL 8)
        message(STATUS "=== Building for Windows (x86-64) ===")
        set(ARCH x86_64)
    else ()
        message(STATUS "=== Building for Windows (i686) ===")
        set(ARCH i686)
    endif ()

and

# Configure
execute_process(
    COMMAND ./configure --host=${ARCH}-w64-mingw32 --prefix=${libusb_BINARY_DIR}/install
                        --enable-static --disable-shared --disable-udev
    WORKING_DIRECTORY ${libusb_SOURCE_DIR}
    RESULT_VARIABLE CONFIGURE_RESULT
)

@Nightwalker-87

Nightwalker-87 commented Sep 13, 2026

Copy link
Copy Markdown
Member Author

4 MSVC issues at 43db600

1. gen_binaries_msvc.bat fails when VS18 is installed but CMake is older than 4.2. The vswhere [18.0,19.0) probe matched my VS 18 Build Tools, so the script selected Visual Studio 18 2026 and CMake 3.28.3 aborted with "Could not create named generator". It does not fall back to the VS 17 generator that is installed and supported. The CMake 4.2 requirement is documented in prose but not enforced by the script.
2. cmake --install produces an installation that cannot run. Installed bin/st-info.exe imports libusb-1.0.dll and pthreadVC3.dll, and neither is installed, so the tools fail to start. libusb.h and getopt.h are also absent while the installed libusb_settings.h and unistd.h include them, which leaves lib/stlink-static.lib and the installed headers unusable downstream. v1.8.0 shipped include/libusb-1.0/libusb.h and lib/libusb-1.0.lib. Dropping the install step from compiling.md hides this, but the INSTALL target and cmake/packaging are still present.
3. Without the vcpkg toolchain, configure fails at CMakeLists.txt:95 with "Could not find a package configuration file provided by PThreads4W" and no hint that vcpkg is needed. find_package(PThreads4W QUIET) plus an explicit FATAL_ERROR pointing at doc/compiling.md would be friendlier.
4. The winsock v1/v2 conflict is latent rather than fixed. It works because libusb >= 1.0.30 dropped its #include <winsock.h> and the vcpkg port is exactly 1.0.30. The MSVC find_path/find_library fallback can still select an older system libusb -- a previous stlink release's bundled copy did exactly that on my machine -- and then every TU where libusb.h precedes win32_socket.h fails with ~60 C2011/C2375 redefinitions of sockaddr/timeval/fd_set and the socket functions. c1763e0 addresses this per-TU by reordering includes, which has to be repeated for every new TU. Adding -D_WINSOCKAPI_ to the WIN32 definitions in src/stlink-env/CMakeLists.txt suppresses winsock.h v1 globally and independently of include order, since winsock2.h guards on WINSOCK2API and defines WINSOCKAPI itself.

A few words on the old build-from-source approach of libusb

on Win32 there is no standard location for third-party libraries that aren't shipped through a platform mechanism, so build systems targeting Windows usually ship them directly. Anything else pushes the user into manually adding install directories to PATH. This repo already shows both halves of that: the find_path/find_library hints in Findlibusb.cmake invent a C:/Program Files/libusb-1.0 convention rather than following one, and the libusb that find_library actually picked up on my machine was C:/Program Files (x86)/stlink/include/libusb-1.0 - the copy bundled by our own v1.8.0 release. (That also caused the winsock clash in item 4, since the bundled copy is older than 1.0.30.)

To be clear, this is not an argument against vcpkg. vcpkg builds libusb and pthreads from source into the build tree and copies the DLLs next to the binaries, so it is per-project vendoring too - the difference is who curates the recipe, and outsourcing that to vcpkg is a reasonable trade - if we don't mind requiring users to install a separate package manager, essentially.

What I would like to keep from the older approach is the property that the shipped artifacts are self-contained. With statically vendored libusb, stlink.dll imported only WSOCK32/WS2_32/KERNEL32 and the CRT, and the tools ran with nothing added to PATH. That property is what item 2 in the issues i'm bringing loses: the installed exes now import libusb-1.0.dll and pthreadVC3.dll and neither is installed. Whichever dependency source we settle on, I think cmake --install should keep producing a tree that runs as-is, and packaging under cmake/packaging depends on that too.

Please fix this properly without further complicating or changing the existing routines.
The intention was to simplify and streamline the compilation in terms of refactoring along with fixing persistent bugs.
We need to avoid moving in the opposite direction again...

Here are my thoughts on this:

MSVC support policy

  1. No special-casing. Support is pinned to the current libusb/CMake compatibility baseline. Which MSVC versions are considered compatible follows Microsoft's own support lifecycle for MSVC, together with the current minimum system requirements of CMake and libusb (or version availability in vcpkg). If a given MSVC version doesn't fit that baseline, it's simply not supported - versions that fall out of support are dropped immediately, no fallback logic.
  2. Winsock migration: Wherever winsock.h (legacy API) is currently included, replace it with winsock2.h — a straight API swap, nothing else changed at each call site for now. Target compatibility: Windows 10+.
  3. MSVC + vcpkg only: The only supported combination is MSVC with the vcpkg toolchain. This is documented as a hard requirement, so no runtime detection or fallback checks are needed.
  4. Should this approach result in notable extra efforts in maintenance for the upcoming months and years due to external circumstances, support will be cut down again.

Scope note: the MinGW cross-compile build (the actual purpose of this PR) stays exactly as self-contained as before — statically linked, single executable, nothing added to PATH. MSVC users accept vcpkg's vendoring model as part of choosing that toolchain (e.g. via VCPKG_APPLOCAL_DEPS to place DLLs next to the binaries).

@Nightwalker-87 Nightwalker-87 changed the title Fixes for MinGW cross compilation on Linux to generate Windows binaries (Part 3) Fixes for MinGW cross compilation on Linux to generate Windows binaries (Part 3) and MSVC compatibility Sep 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

Windows binaries [STM32F746G DISCOVERY]: st-util.exe doesn't run

4 participants