mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-10 06:39:25 +08:00
build(testing): skip fuzztest on MSVC-driver toolchains
fuzztest's CMakeLists hard-fails with a FATAL_ERROR for any compiler
that is not GCC, AppleClang, or Clang (test/fuzztest/CMakeLists.txt:30).
Native MSVC (cl.exe, CMAKE_CXX_COMPILER_ID="MSVC") trips that branch
directly. clang-cl (CMAKE_CXX_COMPILER_ID="Clang",
CMAKE_CXX_SIMULATE_ID="MSVC") makes it past that gate, but then
abseil/re2/fuzztest end up emitting unresolved external references
to `_mm_loadu_si128`, `_mm_set1_epi8`, and other SSE intrinsics that
the LLVM driver does not inline through the MSVC link.exe pipeline.
Treat both MSVC-driver toolchains the same way: introduce a
PX4_HAS_FUZZTEST flag that turns OFF whenever
CMAKE_CXX_COMPILER_ID == MSVC OR CMAKE_CXX_SIMULATE_ID == MSVC
(WIN32 only). When fuzztest is off:
- skip add_subdirectory(test) and FetchContent a standalone
googletest 1.12.1 instead so px4_add_unit_gtest() targets still
have gtest/gtest_main to link against;
- stub link_fuzztest()/link_fuzztest_core() so existing call sites
compile cleanly and route to gtest_main;
- emit a minimal test_results target so `ctest` still runs;
- gate platforms/posix/CMakeLists.txt and
platforms/posix/src/px4/common/CMakeLists.txt's references to the
fuzztest-only mavlink_fuzz_tests / gtest_runner subdirectory on
PX4_HAS_FUZZTEST so configure does not reference targets that
were never built;
- gate px4_add_functional_gtest() on PX4_HAS_FUZZTEST so
functional tests are skipped (they pull fuzztest::fuzztest
directly).
Suppress the `-Wcharacter-conversion` error that googletest 1.12.1's
gtest-printers.h triggers under clang-cl (the implicit char8_t ->
char32_t conversion is fixed in newer gtest releases). The flag is
applied only when CMAKE_CXX_COMPILER_ID == "Clang", so cl.exe never
sees the unknown switch.
Signed-off-by: Nuno Marques <n.marques21@hotmail.com>
This commit is contained in:
+81
-9
@@ -422,16 +422,88 @@ set(TESTFILTER "" CACHE STRING "Filter string for ctest to selectively only run
|
||||
|
||||
include(px4_add_gtest)
|
||||
if(BUILD_TESTING)
|
||||
# Setting FUZZTEST_FUZZING_MODE=on enables ASAN, and is only supported with Clang.
|
||||
# clang-cl on Windows uses the MSVC driver: ASAN there is incompatible with the
|
||||
# debug C runtime (/MDd) emitted by CMake's Debug config, so keep fuzzing mode
|
||||
# off on that combination and just compile fuzztest as a plain dependency.
|
||||
if ((("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang"))
|
||||
AND NOT (WIN32 AND "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC"))
|
||||
set(FUZZTEST_FUZZING_MODE ON)
|
||||
# fuzztest's CMakeLists hard-fails with FATAL_ERROR on any compiler that
|
||||
# is not GCC, AppleClang, or Clang (test/fuzztest/CMakeLists.txt:30).
|
||||
# Native MSVC (cl.exe) trips that branch directly, and clang-cl (which
|
||||
# fuzztest does configure for) pulls in abseil/re2/fuzztest with
|
||||
# inline SSE intrinsics that the LLVM driver leaves as unresolved
|
||||
# externals against the MSVC link.exe. Skip the fuzztest subdirectory
|
||||
# entirely on either MSVC-driver toolchain and fetch a standalone
|
||||
# googletest so the unit-test targets still get gtest/gtest_main.
|
||||
if(WIN32 AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC"
|
||||
OR "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC"))
|
||||
set(PX4_HAS_FUZZTEST OFF)
|
||||
else()
|
||||
set(PX4_HAS_FUZZTEST ON)
|
||||
endif()
|
||||
|
||||
if(PX4_HAS_FUZZTEST)
|
||||
# Setting FUZZTEST_FUZZING_MODE=on enables ASAN, and is only supported with Clang.
|
||||
# clang-cl on Windows uses the MSVC driver: ASAN there is incompatible with the
|
||||
# debug C runtime (/MDd) emitted by CMake's Debug config, so keep fuzzing mode
|
||||
# off on that combination and just compile fuzztest as a plain dependency.
|
||||
if ((("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang"))
|
||||
AND NOT (WIN32 AND "${CMAKE_CXX_SIMULATE_ID}" STREQUAL "MSVC"))
|
||||
set(FUZZTEST_FUZZING_MODE ON)
|
||||
endif()
|
||||
add_subdirectory(test)
|
||||
fuzztest_setup_fuzzing_flags()
|
||||
else()
|
||||
# MSVC fallback: pull in googletest directly so px4_add_unit_gtest()
|
||||
# targets can still link gtest/gtest_main. Provide no-op stubs for
|
||||
# the fuzztest helpers so existing call sites compile cleanly.
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
googletest
|
||||
GIT_REPOSITORY https://github.com/google/googletest.git
|
||||
GIT_TAG release-1.12.1
|
||||
)
|
||||
# Match the runtime that CMake selects for our targets so gtest can
|
||||
# be linked into the test executables without C-runtime mismatch.
|
||||
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
|
||||
FetchContent_MakeAvailable(googletest)
|
||||
|
||||
# googletest 1.12.1 contains an implicit char8_t -> char32_t
|
||||
# conversion in gtest-printers.h that clang-cl flags as
|
||||
# -Wcharacter-conversion (and the Clang frontend defaults
|
||||
# -Werror for it). Newer googletest releases fix this; suppress
|
||||
# it on clang-cl only so we don't have to bump the pinned
|
||||
# version just for the unit-test fallback path. Real cl.exe
|
||||
# does not understand the flag, so guard it.
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
if(TARGET gtest)
|
||||
target_compile_options(gtest PRIVATE -Wno-character-conversion)
|
||||
endif()
|
||||
if(TARGET gtest_main)
|
||||
target_compile_options(gtest_main PRIVATE -Wno-character-conversion)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
function(link_fuzztest name)
|
||||
# fuzztest is unavailable on this toolchain; tests still need a
|
||||
# main(), so wire them to the stock gtest entry point.
|
||||
target_link_libraries(${name} PRIVATE gtest_main)
|
||||
endfunction()
|
||||
function(link_fuzztest_core name)
|
||||
target_link_libraries(${name} PRIVATE gtest_main)
|
||||
endfunction()
|
||||
macro(fuzztest_setup_fuzzing_flags)
|
||||
endmacro()
|
||||
|
||||
# Mirror the test_results plumbing that test/CMakeLists.txt would
|
||||
# otherwise add, minus the fuzztest dependency that we cannot build.
|
||||
if(TESTFILTER)
|
||||
set(TESTFILTERARG "-R")
|
||||
else()
|
||||
set(TESTFILTERARG "")
|
||||
endif()
|
||||
add_custom_target(test_results
|
||||
COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure -T Test ${TESTFILTERARG} ${TESTFILTER}
|
||||
USES_TERMINAL
|
||||
COMMENT "Running tests"
|
||||
WORKING_DIRECTORY ${PX4_BINARY_DIR})
|
||||
set_target_properties(test_results PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
endif()
|
||||
add_subdirectory(test)
|
||||
fuzztest_setup_fuzzing_flags()
|
||||
endif()
|
||||
|
||||
#=============================================================================
|
||||
|
||||
@@ -88,6 +88,14 @@ function(px4_add_unit_gtest)
|
||||
endfunction()
|
||||
|
||||
function(px4_add_functional_gtest)
|
||||
# Functional tests link fuzztest::fuzztest directly (without
|
||||
# link_fuzztest() so they pull only the runtime, not the gtest main).
|
||||
# When fuzztest is unavailable for the active toolchain (e.g. native
|
||||
# MSVC) we skip these definitions entirely so configure does not
|
||||
# reference targets that were never built.
|
||||
if(NOT PX4_HAS_FUZZTEST)
|
||||
return()
|
||||
endif()
|
||||
# skip if unit testing is not configured
|
||||
if(BUILD_TESTING)
|
||||
# parse source file and library dependencies from arguments
|
||||
|
||||
@@ -56,7 +56,7 @@ if(WIN32)
|
||||
px4_posix_windows_configure_target(px4)
|
||||
endif()
|
||||
|
||||
if (BUILD_TESTING)
|
||||
if (BUILD_TESTING AND PX4_HAS_FUZZTEST)
|
||||
# Build mavlink fuzz tests. These run other modules and thus cannot be a functional/unit test
|
||||
add_executable(mavlink_fuzz_tests EXCLUDE_FROM_ALL
|
||||
src/px4/common/mavlink_fuzz_tests.cpp
|
||||
|
||||
@@ -69,5 +69,11 @@ endif()
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(test_stubs)
|
||||
add_subdirectory(gtest_runner)
|
||||
# gtest_runner provides gtest_functional_main which links
|
||||
# fuzztest::init_fuzztest. On toolchains without fuzztest (e.g.
|
||||
# native MSVC) we skip it because px4_add_functional_gtest() is
|
||||
# also gated off there, so nothing references the target.
|
||||
if(PX4_HAS_FUZZTEST)
|
||||
add_subdirectory(gtest_runner)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
Reference in New Issue
Block a user