build(posix): wire Windows SITL builds

Add MinGW-w64 toolchain support, Windows-specific POSIX target wiring, and compiler flag handling for MSVC and MinGW.

The build now copies px4-* command executables instead of relying on symlinks, places dynamic modules where tests expect them, forwards ExternalProject toolchain state, and adds a CI cross-build for px4_sitl_default.

Signed-off-by: Nuno Marques <n.marques21@hotmail.com>
This commit is contained in:
Nuno Marques
2026-04-27 15:25:25 -07:00
parent 9abb4ac867
commit 1ed35593a7
11 changed files with 634 additions and 105 deletions
+35 -6
View File
@@ -26,10 +26,35 @@ add_definitions(-DPX4_SOURCE_DIR="${PX4_SOURCE_DIR}" -DPX4_BINARY_DIR="${PX4_BIN
# PX4_INSTALL_PREFIX is set by cmake/package.cmake after this file is processed.
# It is passed via target_compile_definitions on the px4 target from package.cmake.
add_executable(px4
if(WIN32)
include(cmake/windows.cmake)
endif()
set(_px4_main_sources
src/px4/common/main.cpp
apps.cpp
)
)
if(WIN32)
px4_posix_windows_append_sources(_px4_main_sources)
else()
list(APPEND _px4_main_sources src/px4/common/shell_posix.cpp)
endif()
if(WIN32)
px4_posix_windows_configure_link_templates()
endif()
add_executable(px4 ${_px4_main_sources})
set(_px4_posix_math_libraries)
if(NOT MSVC)
list(APPEND _px4_posix_math_libraries m)
endif()
if(WIN32)
px4_posix_windows_configure_target(px4)
endif()
if (BUILD_TESTING)
# Build mavlink fuzz tests. These run other modules and thus cannot be a functional/unit test
@@ -44,7 +69,7 @@ if (BUILD_TESTING)
target_link_libraries(mavlink_fuzz_tests
PRIVATE
${module_libraries}
m
${_px4_posix_math_libraries}
parameters
)
target_compile_options(mavlink_fuzz_tests
@@ -65,20 +90,24 @@ endif()
target_link_libraries(px4
PRIVATE
${module_libraries}
m
${_px4_posix_math_libraries}
parameters
)
if((NOT APPLE) AND (NOT ANDROID))
if((NOT APPLE) AND (NOT ANDROID) AND (NOT WIN32))
target_link_libraries(px4 PRIVATE rt)
endif()
if(NOT ANDROID)
if((NOT ANDROID) AND (NOT WIN32))
target_link_libraries(px4 PRIVATE pthread)
endif()
target_link_libraries(px4 PRIVATE uORB)
if(WIN32)
px4_posix_windows_link_libraries(px4)
endif()
#=============================================================================
# install
#
@@ -0,0 +1,88 @@
############################################################################
#
# PX4 MinGW-w64 x86_64 cross toolchain.
#
# Used to cross-compile px4_sitl_default from a POSIX host to a native
# Windows x86_64 executable via the MinGW-w64 GCC port. Pick the
# *-posix* variant (winpthreads) so std::thread, pthread, and
# std::mutex work.
#
# Usage (from PX4-Autopilot repo root):
# CMAKE_ARGS="-DCMAKE_TOOLCHAIN_FILE=Toolchain-mingw-w64-x86_64" \
# make px4_sitl_default
#
# The bare toolchain name is resolved through CMAKE_MODULE_PATH, which
# cmake/kconfig.cmake extends with platforms/${PX4_PLATFORM}/cmake.
############################################################################
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86_64)
set(TOOLCHAIN_PREFIX x86_64-w64-mingw32)
find_program(MINGW_C_COMPILER NAMES ${TOOLCHAIN_PREFIX}-gcc-posix ${TOOLCHAIN_PREFIX}-gcc)
find_program(MINGW_CXX_COMPILER NAMES ${TOOLCHAIN_PREFIX}-g++-posix ${TOOLCHAIN_PREFIX}-g++)
find_program(MINGW_RC_COMPILER NAMES ${TOOLCHAIN_PREFIX}-windres)
find_program(MINGW_AR NAMES ${TOOLCHAIN_PREFIX}-ar)
find_program(MINGW_RANLIB NAMES ${TOOLCHAIN_PREFIX}-ranlib)
if(NOT MINGW_C_COMPILER OR NOT MINGW_CXX_COMPILER)
message(FATAL_ERROR
"MinGW-w64 (${TOOLCHAIN_PREFIX}) not found. "
"Install with: apt-get install mingw-w64 g++-mingw-w64-x86-64-posix gcc-mingw-w64-x86-64-posix")
endif()
set(CMAKE_C_COMPILER ${MINGW_C_COMPILER})
set(CMAKE_CXX_COMPILER ${MINGW_CXX_COMPILER})
set(CMAKE_RC_COMPILER ${MINGW_RC_COMPILER})
set(CMAKE_AR ${MINGW_AR})
set(CMAKE_RANLIB ${MINGW_RANLIB})
# Find headers/libs only in the target sysroot, but let us run host tools
# (python, etc.) during the build (generators, kconfig, msg-gen).
# PACKAGE uses BOTH so find_package() can locate packages installed by
# nested ExternalProject builds (microcdr under the PX4 build tree) as
# well as packages living in the MinGW sysroot.
set(CMAKE_FIND_ROOT_PATH /usr/${TOOLCHAIN_PREFIX})
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 BOTH)
# MinGW lacks many POSIX headers. Put our shim directory in the search
# path ahead of the MinGW sysroot — do it here (rather than in the posix
# platform layer only) so that nested ExternalProject builds
# (Micro-XRCE-DDS-Client) using this toolchain also resolve <poll.h>,
# <sys/statfs.h>, <netdb.h>, <net/if.h>, <time.h> _r wrappers, etc.
get_filename_component(_px4_windows_shim_dir
"${CMAKE_CURRENT_LIST_DIR}/../include/windows_shim" ABSOLUTE)
include_directories(BEFORE SYSTEM "${_px4_windows_shim_dir}")
# Target Windows 10 (1803+) so AF_UNIX is available in WinSock2.
add_compile_definitions(
_WIN32_WINNT=0x0A00 # Windows 10
WINVER=0x0A00
__PX4_WINDOWS # PX4 platform selector
NOMINMAX # avoid <windows.h> min/max macros
WIN32_LEAN_AND_MEAN
_USE_MATH_DEFINES
__USE_MINGW_ANSI_STDIO=1 # make printf accept PRIu64 / %llu / %zu
)
# PX4 uses `#pragma pack(push, 1)` around structs with multi-bit bitfields
# (e.g. sixteen 11-bit RC channel fields in src/lib/rc/crsf.cpp). MinGW
# defaults to the MSVC bitfield ABI, which lays those out differently
# from Linux GCC (each storage unit padded to the declared type's
# alignment instead of packed bit-adjacent). Force the Itanium/SysV
# layout so decoded wire formats match across platforms.
add_compile_options(-mno-ms-bitfields)
# Produce a statically linked .exe so the user does not need to ship
# libgcc_s, libstdc++, and winpthread DLLs separately.
set(CMAKE_EXE_LINKER_FLAGS_INIT "-static -static-libgcc -static-libstdc++")
set(CMAKE_SHARED_LINKER_FLAGS_INIT "-static-libgcc -static-libstdc++")
# ctest runs the PE binary via wine through the CROSSCOMPILING_EMULATOR
# property set on the px4 target (platforms/posix/CMakeLists.txt),
# rather than CMAKE_CROSSCOMPILING_EMULATOR here, because the latter
# does not reliably propagate across CMake reconfigures.
+116 -11
View File
@@ -210,11 +210,22 @@ function(px4_posix_generate_symlinks)
if (MAIN)
set(ln_name "${PREFIX}${MAIN}")
add_custom_command(TARGET ${TARGET}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink ${TARGET} ${ln_name}
WORKING_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
)
if(WIN32 OR MINGW)
# Windows symlinks require admin; copy the exe instead so that
# px4-<module>.exe can be invoked the same way as on POSIX.
add_custom_command(TARGET ${TARGET}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy
$<TARGET_FILE:${TARGET}>
${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${ln_name}.exe
)
else()
add_custom_command(TARGET ${TARGET}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E create_symlink ${TARGET} ${ln_name}
WORKING_DIRECTORY "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}"
)
endif()
endif()
endforeach()
endfunction()
@@ -231,16 +242,106 @@ endfunction()
#
function(px4_os_add_flags)
add_definitions(
-D__PX4_POSIX
-Dnoreturn_function=__attribute__\(\(noreturn\)\)
)
add_definitions(-D__PX4_POSIX)
if(MSVC)
add_definitions(-Dnoreturn_function=__declspec\(noreturn\))
else()
add_definitions(-Dnoreturn_function=__attribute__\(\(noreturn\)\))
endif()
include_directories(platforms/posix/include)
# When cross-compiling for Windows (MinGW) the shim headers have to
# sit *before* the MinGW sysroot in the search path so our termios.h,
# sys/mman.h, etc. are picked up instead of "no such file". -idirafter
# is not enough — sysroot headers win otherwise.
if(WIN32 OR MINGW)
include_directories(BEFORE platforms/posix/include/windows_shim)
endif()
if ("${PX4_BOARD}" MATCHES "sitl")
if(UNIX AND APPLE)
if(WIN32 OR MINGW)
add_definitions(
-D__PX4_WINDOWS
-D_GNU_SOURCE
-D_WIN32_WINNT=0x0A00
-DWINVER=0x0A00
-DNOMINMAX
-DWIN32_LEAN_AND_MEAN
-D_USE_MATH_DEFINES
)
if(MSVC)
add_definitions(
-D_CRT_SECURE_NO_WARNINGS
-D_CRT_NONSTDC_NO_DEPRECATE
-D_WINSOCK_DEPRECATED_NO_WARNINGS
)
else()
add_definitions(
# Strip __declspec(dllimport) from WinSock prototypes so PX4
# call sites resolve to the bare `bind`/`socket`/etc. symbol
# (a thunk emitted into the executable) rather than going
# through `__imp_<name>`. Required for the linker --wrap
# flags configured in platforms/posix/cmake/windows.cmake (which
# route those bare symbols through the errno-translating
# wrappers in src/px4/windows/posix/net/socket_wrap.cpp) to actually fire.
-DWINSOCK_API_LINKAGE=
)
# Relax a few warning classes that fire in every translation
# unit on MinGW and drown real diagnostics. Note: *do not* use
# -Wno-format here — PX4 globally enables -Wformat-security /
# -Wformat=1 and disabling the parent -Wformat makes those
# flags "ignored without -Wformat", which becomes an error
# under -Wfatal-errors.
add_compile_options(
-Wno-format-nonliteral
-Wno-format-truncation
-Wno-format-zero-length
-Wno-pedantic-ms-format
-Wno-cast-function-type
-Wno-unknown-pragmas
-Wno-attributes
-Wno-unused-variable
-Wno-unused-function
-Wno-unused-but-set-variable
-Wno-missing-field-initializers
-Wno-deprecated-declarations
# Even with __USE_MINGW_ANSI_STDIO=1, GCC's -Wformat still
# checks printf arguments against the ms_printf attribute
# that MinGW bakes into its stdio.h prototype. PX4 uses
# PRIu64/%llu/%zu heavily (via inttypes.h) — downgrade
# format mismatches from error to warning rather than
# mechanically rewriting thousands of call sites.
-Wno-error=format
-Wno-error=format-extra-args
# Cross-compile GCC flags uninitialized-use false positives
# where native GCC doesn't — downgrade, don't rewrite.
-Wno-error=uninitialized
-Wno-error=maybe-uninitialized
# WinSock typedefs SOCKET = unsigned long long; PX4 stores
# sockets in `int _fd` like everyone else. Downgrade the
# resulting narrowing warnings instead of rewriting every
# call site.
-Wno-error=narrowing
# MinGW LLP64: `unsigned long` is 32-bit but a pointer
# is 64-bit. A handful of PX4 call sites cast int->void*
# through `unsigned long`. Accept the warning rather
# than rewriting every cast with uintptr_t.
-Wno-error=int-to-pointer-cast
-Wno-error=pointer-to-int-cast
# Same LLP64 mismatch for C++'s stricter cast-from-pointer
# check. `(unsigned long)&p` truncates on Win64. Let the
# warning through without aborting the build.
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
-Wno-error=shadow
)
endif()
elseif(UNIX AND APPLE)
add_definitions(-D__PX4_DARWIN)
# Silence Apple ld warning about duplicate static libs. CMake intentionally
@@ -262,7 +363,11 @@ function(px4_os_add_flags)
endif()
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wbad-function-cast>)
# -Wbad-function-cast is a C-only warning but it trips on the winsock
# socket() return type vs int on MinGW. Exclude it on Windows.
if(NOT (WIN32 OR MINGW))
add_compile_options($<$<COMPILE_LANGUAGE:C>:-Wbad-function-cast>)
endif()
endfunction()
+6 -6
View File
@@ -30,7 +30,7 @@ foreach(test_name ${tests})
configure_file(${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_template.in ${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_${test_name}_generated)
add_test(NAME ${test_name_prefix}
COMMAND $<TARGET_FILE:px4>
COMMAND px4
-s ${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_${test_name}_generated
-t ${PX4_SOURCE_DIR}/test_data
${PX4_SOURCE_DIR}/ROMFS/px4fmu_test
@@ -57,7 +57,7 @@ foreach(test_name ${cmd_tests})
configure_file(${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_cmd_template.in ${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_${test_name}_generated)
add_test(NAME ${test_name_prefix}
COMMAND $<TARGET_FILE:px4>
COMMAND px4
-s ${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_${test_name}_generated
-t ${PX4_SOURCE_DIR}/test_data
${PX4_SOURCE_DIR}/ROMFS/px4fmu_test
@@ -74,7 +74,7 @@ endforeach()
# IMU filtering
add_test(NAME sitl-imu_filtering
COMMAND $<TARGET_FILE:px4>
COMMAND px4
-s ${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_imu_filtering
-t ${PX4_SOURCE_DIR}/test_data
${PX4_SOURCE_DIR}/ROMFS/px4fmu_test
@@ -89,7 +89,7 @@ sanitizer_fail_test_on_error(sitl-imu_filtering)
# # Shutdown test
# add_test(NAME sitl-shutdown
# COMMAND $<TARGET_FILE:px4>
# COMMAND px4
# -s ${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_shutdown
# -t ${PX4_SOURCE_DIR}/test_data
# ${PX4_SOURCE_DIR}/ROMFS/px4fmu_test
@@ -104,7 +104,7 @@ sanitizer_fail_test_on_error(sitl-imu_filtering)
# Dynamic module loading test
add_test(NAME dyn
COMMAND $<TARGET_FILE:px4> -s "${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_dyn_hello"
COMMAND px4 -s "${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/test_dyn_hello"
WORKING_DIRECTORY ${PX4_BINARY_DIR}/src/examples/dyn_hello
)
set_tests_properties(dyn PROPERTIES PASS_REGULAR_EXPRESSION "1: PASSED")
@@ -122,7 +122,7 @@ foreach(cmd_name ${test_cmds})
configure_file(${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/cmd_template.in ${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/cmd_${cmd_name}_generated)
add_test(NAME posix_${cmd_name}
COMMAND $<TARGET_FILE:px4>
COMMAND px4
${PX4_SOURCE_DIR}/ROMFS/px4fmu_test
-s ${PX4_SOURCE_DIR}/posix-configs/SITL/init/test/cmd_${cmd_name}_generated
-t ${PX4_SOURCE_DIR}/test_data
+157
View File
@@ -0,0 +1,157 @@
############################################################################
#
# Copyright (c) 2026 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
# Windows support here is a Win32 backend for the POSIX platform, not a
# separate PX4 platform. Keep the backend source list and Win32 link policy
# out of platforms/posix/CMakeLists.txt so the top-level POSIX build remains
# about platform selection rather than Win32 implementation detail.
set(PX4_POSIX_WINDOWS_ROOT "${PX4_SOURCE_DIR}/platforms/posix/src/px4/windows")
set(PX4_POSIX_WINDOWS_PRIVATE_INCLUDE_DIR "${PX4_POSIX_WINDOWS_ROOT}/include")
function(px4_posix_windows_append_sources out_var)
list(APPEND ${out_var}
${PX4_POSIX_WINDOWS_ROOT}/runtime/init.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/sys/errno_map.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/sys/ioctl.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/sys/sysconf.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/sys/termios.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/proc/env.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/proc/ids.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/proc/sched.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/proc/user.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/fs/flock.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/fs/mman.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/net/if_query.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/net/resolver.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/net/socket.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/lib/dlfcn.cpp
${PX4_POSIX_WINDOWS_ROOT}/shell/shell.cpp
${PX4_POSIX_WINDOWS_ROOT}/shell/embedded_backend_stub.cpp
)
if(MSVC)
list(APPEND ${out_var}
${PX4_POSIX_WINDOWS_ROOT}/posix/proc/pthread.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/sys/time.cpp
${PX4_POSIX_WINDOWS_ROOT}/posix/net/socket_msvc.cpp
)
else()
list(APPEND ${out_var}
${PX4_POSIX_WINDOWS_ROOT}/posix/net/socket_wrap.cpp
)
endif()
set(${out_var} "${${out_var}}" PARENT_SCOPE)
endfunction()
function(px4_posix_windows_configure_link_templates)
if(MSVC)
return()
endif()
# PX4 links many static archives with cross-archive symbol cycles
# (uORB <-> platform <-> modules, winsock referenced from both daemon
# server and uxrce_dds_client). GNU ld's default single-pass static
# archive resolution can leave unresolved WinSock import symbols.
# Wrap <LINK_LIBRARIES> in a group so ld rescans until convergence.
string(REPLACE "<LINK_LIBRARIES>" "-Wl,--start-group <LINK_LIBRARIES> -Wl,--end-group"
CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE}")
string(REPLACE "<LINK_LIBRARIES>" "-Wl,--start-group <LINK_LIBRARIES> -Wl,--end-group"
CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}")
set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINK_EXECUTABLE}" PARENT_SCOPE)
set(CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINK_EXECUTABLE}" PARENT_SCOPE)
endfunction()
function(px4_posix_windows_configure_target target_name)
target_include_directories(${target_name}
PRIVATE
${PX4_POSIX_WINDOWS_PRIVATE_INCLUDE_DIR}
)
set_target_properties(${target_name} PROPERTIES ENABLE_EXPORTS ON)
if(MSVC)
set_target_properties(${target_name} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
target_compile_options(${target_name} PRIVATE /bigobj)
else()
# Force an import library (`libpx4.dll.a`) to be generated alongside
# px4.exe so DYNAMIC `.px4mod` modules can link against it.
target_link_options(${target_name} PRIVATE -Wl,--export-all-symbols)
# Route bare WinSock calls through socket_wrap.cpp so WSAGetLastError()
# is translated into errno before PX4 logs strerror(errno).
target_link_options(${target_name} PRIVATE
-Wl,--wrap=socket
-Wl,--wrap=bind
-Wl,--wrap=listen
-Wl,--wrap=accept
-Wl,--wrap=connect
-Wl,--wrap=setsockopt
-Wl,--wrap=shutdown
-Wl,--wrap=recv
-Wl,--wrap=send
-Wl,--wrap=recvfrom
-Wl,--wrap=sendto
-Wl,--wrap=strerror
)
endif()
# Make ctest run `wine px4.exe ...` transparently.
find_program(_px4_wine NAMES wine wine64)
if(_px4_wine)
set_target_properties(${target_name} PROPERTIES CROSSCOMPILING_EMULATOR "${_px4_wine}")
endif()
endfunction()
function(px4_posix_windows_link_libraries target_name)
# Keep Win32 import libs at the end of the link line. This is ordering
# only: every PX4 static archive has already been scanned before these
# are used to resolve platform symbols.
target_link_libraries(${target_name}
PRIVATE
ws2_32
iphlpapi
dbghelp
psapi
)
if(NOT MSVC)
target_link_libraries(${target_name} PRIVATE winpthread)
endif()
endfunction()