[libc-commits] [libc] [libc][cmake] Unify unit and hermetic test rules into add_libc_test (PR #233512)
via libc-commits
libc-commits at lists.llvm.org
Tue Oct 20 21:13:39 PDT 2026
https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/233512
>From 77f94fe1daba183a06c92ab64bf66c5e1ec9a6f0 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 15 Sep 2026 17:40:13 +0000
Subject: [PATCH 1/3] [libc][cmake] Unify unit and hermetic test rules into
add_libc_test
- Consolidate _add_libc_unittest and add_libc_hermetic into mode-aware
add_libc_test and create_libc_test rules using llvm_libc_parse_arguments
and forward_arguments (#232089), keeping add_libc_unittest,
add_libc_hermetic, and add_fp_unittest as thin forwarding wrappers.
- Replace separate libc-unit-tests and libc-hermetic-tests with unified
libc-tests and libc-tests-build targets.
- Introduce add_libc_testsuite to create both <suite> and <suite>-build
targets wired into libc-tests and libc-tests-build.
- Move add_fp_unittest into LLVMLibCTestRules.cmake via the FP_TEST option
and rename MPFR/MPC helper libraries to follow standard libc target
naming (libc.utils.MPCommon, libc.utils.MPFRWrapper, libc.utils.MPCWrapper).
- Streamline _add_libc_test_runner: replace $<TARGET_FILE:...> with
configure-time binary paths, fast-path .params generation, and define
test runner targets directly via add_custom_target(... COMMAND ... JOB_POOL ...)
instead of intermediate .cmd stamp rules.
- Update docs and GPU benchmarks to use the unified test targets and rules.
---
libc/benchmarks/gpu/CMakeLists.txt | 9 +-
libc/cmake/modules/LLVMLibCTestRules.cmake | 1080 ++++++++++----------
libc/docs/dev/code_coverage.md | 12 +-
libc/docs/full_cross_build.md | 6 +-
libc/docs/gpu/testing.rst | 4 +-
libc/test/CMakeLists.txt | 10 +-
libc/test/include/CMakeLists.txt | 3 +-
libc/test/shared/CMakeLists.txt | 2 +-
libc/test/src/CMakeLists.txt | 77 --
libc/test/src/__support/CMakeLists.txt | 3 +-
libc/test/src/math/CMakeLists.txt | 5 +-
libc/test/src/math/smoke/CMakeLists.txt | 3 +-
libc/utils/MPCWrapper/CMakeLists.txt | 20 +-
libc/utils/MPFRWrapper/CMakeLists.txt | 33 +-
14 files changed, 600 insertions(+), 667 deletions(-)
diff --git a/libc/benchmarks/gpu/CMakeLists.txt b/libc/benchmarks/gpu/CMakeLists.txt
index e7ad4f59bf7180..c7befd869fe27e 100644
--- a/libc/benchmarks/gpu/CMakeLists.txt
+++ b/libc/benchmarks/gpu/CMakeLists.txt
@@ -14,9 +14,10 @@ function(add_benchmark benchmark_name)
if(NOT libc.src.time.clock IN_LIST TARGET_LLVMLIBC_ENTRYPOINTS)
message(FATAL_ERROR "target does not support clock")
endif()
- add_libc_hermetic(
+ add_libc_test(
${benchmark_name}
IS_GPU_BENCHMARK
+ FULL_BUILD_ONLY
LINK_LIBRARIES
LibcGpuBenchmark
${BENCHMARK_LINK_LIBRARIES}
@@ -28,9 +29,9 @@ function(add_benchmark benchmark_name)
-flto
)
get_fq_target_name(${benchmark_name} fq_target_name)
- set(fq_build_target_name ${fq_target_name}.__build__)
-
- add_dependencies(gpu-benchmark ${fq_target_name})
+ if(TARGET ${fq_target_name})
+ add_dependencies(gpu-benchmark ${fq_target_name})
+ endif()
endfunction()
function(add_benchmark_framework_library name)
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index 56a51e161fcdd2..e6736153256fb2 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -286,66 +286,453 @@ function(get_link_options link_options)
set(${link_options} "${link_opts}" PARENT_SCOPE)
endfunction()
-# Rule to add a libc unittest.
-# Usage
-# create_libc_unittest(
-# <target name>
-# SUITE <name of the suite this test belongs to>
-# SRCS <list of .cpp files for the test>
-# HDRS <list of .h files for the test>
-# DEPENDS <list of dependencies>
-# ENV <list of environment variables to set before running the test>
-# COMPILE_OPTIONS <list of special compile options for this target>
-# LINK_LIBRARIES <list of linking libraries for this target>
-# )
-function(create_libc_unittest fq_target_name)
- if(NOT LLVM_INCLUDE_TESTS)
- return()
+# Get libgcc_s to be used in hermetic and integration tests.
+if(NOT MSVC AND NOT LIBC_CC_SUPPORTS_NOSTDLIBPP)
+ execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=libgcc_s.so.1
+ OUTPUT_VARIABLE LIBGCC_S_LOCATION)
+ string(STRIP ${LIBGCC_S_LOCATION} LIBGCC_S_LOCATION)
+endif()
+
+# Hermetic and integration tests link with -nodefaultlibs, so the compiler
+# runtime builtins have to be linked explicitly. -print-libgcc-file-name
+# reports whichever library the driver would use (libgcc.a or
+# libclang_rt.builtins.a). The query uses the same flags as the test link so
+# that the driver selects the same multilib. GPU and UEFI targets do not link a
+# compiler runtime.
+if(LLVM_INCLUDE_TESTS AND LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_GPU AND
+ NOT LIBC_TARGET_OS_IS_UEFI AND
+ NOT LIBC_TEST_BUILTINS_LIBRARY AND NOT LIBC_TEST_BUILTINS_TARGET)
+ separate_arguments(libc_cxx_flags NATIVE_COMMAND "${CMAKE_CXX_FLAGS}")
+ execute_process(
+ COMMAND ${CMAKE_CXX_COMPILER} ${libc_cxx_flags}
+ ${LIBC_COMPILE_OPTIONS_DEFAULT} ${LIBC_TEST_LINK_OPTIONS_DEFAULT}
+ -print-libgcc-file-name
+ OUTPUT_VARIABLE LIBC_TEST_BUILTINS_LIBRARY
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+ if(NOT EXISTS "${LIBC_TEST_BUILTINS_LIBRARY}")
+ message(FATAL_ERROR "Compiler runtime builtins library "
+ "'${LIBC_TEST_BUILTINS_LIBRARY}' not found. Set "
+ "LIBC_TEST_BUILTINS_LIBRARY or LIBC_TEST_BUILTINS_TARGET.")
endif()
+endif()
- cmake_parse_arguments(
- "LIBC_UNITTEST"
- "NO_RUN_POSTBUILD;C_TEST" # Optional arguments
- "SUITE;CXX_STANDARD" # Single value arguments
- "SRCS;HDRS;DEPENDS;ENV;COMPILE_OPTIONS;LINK_LIBRARIES;FLAGS" # Multi-value arguments
- ${ARGN}
- )
- if(NOT LIBC_UNITTEST_SRCS)
- message(FATAL_ERROR "'create_libc_unittest' target requires a SRCS list of .cpp "
- "files.")
+# Rule to add a test suite in the hierarchy.
+# Automatically creates <suite_name> (run target) and <suite_name>-build (build target).
+# Connects them to libc-tests and libc-tests-build.
+function(add_libc_testsuite suite_name)
+ if(NOT TARGET ${suite_name})
+ add_custom_target(${suite_name})
endif()
- if(NOT LIBC_UNITTEST_DEPENDS)
- message(FATAL_ERROR "'create_libc_unittest' target requires a DEPENDS list of "
- "'add_entrypoint_object' targets.")
+
+ set(created_build_target FALSE)
+ if(NOT TARGET ${suite_name}-build)
+ add_custom_target(${suite_name}-build)
+ set(created_build_target TRUE)
endif()
- get_fq_deps_list(fq_deps_list ${LIBC_UNITTEST_DEPENDS})
- list(APPEND fq_deps_list libc.test.UnitTest.LibcTest)
- if(LIBC_UNITTEST_C_TEST)
+ if(created_build_target)
+ if(TARGET libc-tests)
+ add_dependencies(libc-tests ${suite_name})
+ endif()
+ if(TARGET libc-tests-build)
+ add_dependencies(libc-tests-build ${suite_name}-build)
+ endif()
+ endif()
+endfunction()
+
+function(add_libc_exhaustive_testsuite suite_name)
+ add_libc_testsuite(${suite_name})
+ add_dependencies(exhaustive-check-libc ${suite_name})
+endfunction()
+
+function(add_libc_long_running_testsuite suite_name)
+ add_libc_testsuite(${suite_name})
+ add_dependencies(libc-long-running-tests ${suite_name})
+endfunction()
+
+# Helper function for create_libc_test: returns the list of libc entrypoints
+# needed to support code coverage profiling in hermetic/full-build mode.
+function(_get_libc_coverage_dependencies output_var)
+ set(${output_var}
+ libc.src.stdio.fclose
+ libc.src.stdio.fdopen
+ libc.src.stdio.feof
+ libc.src.stdio.fflush
+ libc.src.stdio.fileno
+ libc.src.stdio.fopen
+ libc.src.stdio.fprintf
+ libc.src.stdio.fread
+ libc.src.stdio.fseek
+ libc.src.stdio.ftell
+ libc.src.stdio.fwrite
+ libc.src.stdio.snprintf
+ libc.src.stdio.stderr
+ libc.src.stdio.vfprintf
+ libc.src.stdio.vsnprintf
+ libc.src.fcntl.fcntl
+ libc.src.fcntl.open
+ libc.src.stdlib.getenv
+ libc.src.stdlib.setenv
+ libc.src.stdlib.strtol
+ libc.src.string.strchr
+ libc.src.string.strcmp
+ libc.src.string.strdup
+ libc.src.string.strerror
+ libc.src.string.strlen
+ libc.src.string.strncpy
+ libc.src.string.strrchr
+ libc.src.sys.mman.madvise
+ libc.src.sys.mman.mmap
+ libc.src.sys.mman.munmap
+ libc.src.sys.prctl.prctl
+ libc.src.sys.stat.mkdir
+ libc.src.sys.utsname.uname
+ libc.src.unistd.fork
+ libc.src.unistd.ftruncate
+ libc.src.unistd.getpagesize
+ libc.src.unistd.getpid
+ PARENT_SCOPE
+ )
+endfunction()
+
+# Helper function for create_libc_test: collects fully qualified dependencies
+# for a test target, including base test framework libraries, hermetic runtime
+# entrypoints, subprocess support, and coverage dependencies.
+function(_get_libc_test_dependencies output_var user_depends startup_target_dep is_c_test)
+ get_fq_deps_list(fq_deps_list ${user_depends})
+ list(APPEND fq_deps_list
+ libc.src.__support.StringUtil.error_to_string
+ libc.test.UnitTest.ErrnoSetterMatcher
+ libc.test.UnitTest.LibcTest
+ )
+ if(is_c_test)
list(APPEND fq_deps_list libc.test.UnitTest.LibcCTest)
else()
+ list(APPEND fq_deps_list libc.test.UnitTest.LibcDeathTestExecutors)
+ endif()
+
+ if(LLVM_LIBC_FULL_BUILD)
list(APPEND fq_deps_list
- libc.src.__support.StringUtil.error_to_string
- libc.test.UnitTest.ErrnoSetterMatcher
- libc.test.UnitTest.LibcDeathTestExecutors
+ ${startup_target_dep}
+ libc.src.string.memcmp
+ libc.src.string.memcpy
+ libc.src.string.memmove
+ libc.src.string.memset
+ libc.src.strings.bcmp
+ libc.src.strings.bzero
+ libc.test.UnitTest.HermeticTestUtils
)
+ if(LIBC_TARGET_ARCHITECTURE_IS_AARCH64 AND NOT(LIBC_TARGET_OS_IS_BAREMETAL))
+ list(APPEND fq_deps_list libc.src.sys.auxv.getauxval)
+ endif()
+ if(LIBC_TEST_SUBPROCESS_TESTS AND NOT is_c_test)
+ list(APPEND fq_deps_list
+ libc.src.poll.poll
+ libc.src.signal.kill
+ libc.src.stdio.fflush
+ libc.src.stdio.stderr
+ libc.src.stdio.stdout
+ libc.src.stdlib.exit
+ libc.src.string.strsignal
+ libc.src.sys.wait.waitpid
+ libc.src.unistd.close
+ libc.src.unistd.fork
+ libc.src.unistd.pipe
+ )
+ endif()
+ if(NOT LLVM_LIBC_HERMETIC_TEST_USE_INTERNAL_STARTUP AND LIBC_TARGET_OS_IS_BAREMETAL)
+ # External baremetal startup objects still need libc's process startup and
+ # termination entrypoints, even when the test itself does not depend on them.
+ list(APPEND fq_deps_list
+ libc.src.stdlib.atexit
+ libc.src.stdlib.exit
+ libc.startup.baremetal.init
+ )
+ endif()
+ if(libc.src.compiler.__stack_chk_fail IN_LIST TARGET_LLVMLIBC_ENTRYPOINTS)
+ list(APPEND fq_deps_list libc.src.compiler.__stack_chk_fail)
+ endif()
+ if(libc.src.time.clock IN_LIST TARGET_LLVMLIBC_ENTRYPOINTS)
+ list(APPEND fq_deps_list libc.src.time.clock)
+ endif()
+ if(LIBC_ENABLE_COVERAGE)
+ _get_libc_coverage_dependencies(coverage_deps)
+ list(APPEND fq_deps_list ${coverage_deps})
+ endif()
endif()
list(REMOVE_DUPLICATES fq_deps_list)
+ set(${output_var} ${fq_deps_list} PARENT_SCOPE)
+endfunction()
+
+# Helper function for create_libc_test: inspects dependencies and extracts
+# standard CMake library targets (STATIC, SHARED, INTERFACE) that do not have
+# a custom TARGET_TYPE (e.g. libc.utils.MPFRWrapper, libc.utils.MPCWrapper).
+function(_get_libc_test_link_libraries output_var fq_deps_list)
+ set(link_libs "")
+ foreach(dep IN LISTS fq_deps_list)
+ if(TARGET ${dep})
+ get_target_property(aliased_target ${dep} "ALIASED_TARGET")
+ if(aliased_target)
+ set(dep ${aliased_target})
+ endif()
+ get_target_property(dep_type ${dep} "TARGET_TYPE")
+ get_target_property(cmake_type ${dep} TYPE)
+ if(NOT dep_type AND cmake_type MATCHES ".*_LIBRARY")
+ list(APPEND link_libs ${dep})
+ endif()
+ endif()
+ endforeach()
+ if(link_libs)
+ list(REMOVE_DUPLICATES link_libs)
+ endif()
+ set(${output_var} ${link_libs} PARENT_SCOPE)
+endfunction()
+
+# Helper function for create_libc_test: configures linking for full-build hermetic
+# tests by creating the static .__libc__ archive, setting hermetic/GPU link
+# options, and wiring link libraries and compiler runtime.
+function(_link_libc_hermetic_test fq_target_name fq_build_target_name startup_target_dep link_object_files test_link_libraries)
+ if(LIBC_ENABLE_COVERAGE)
+ _get_libc_coverage_dependencies(coverage_deps)
+ foreach(cov_dep IN LISTS coverage_deps)
+ get_target_property(is_alias ${cov_dep} "IS_ALIAS")
+ if(is_alias)
+ get_target_property(real_target ${cov_dep} "DEPS")
+ else()
+ set(real_target ${cov_dep})
+ endif()
+ string(REPLACE "${real_target}.__internal__" "${real_target}" link_object_files "${link_object_files}")
+ endforeach()
+ endif()
+
+ add_library(
+ ${fq_target_name}.__libc__
+ STATIC
+ EXCLUDE_FROM_ALL
+ ${link_object_files}
+ )
+ set_target_properties(${fq_target_name}.__libc__
+ PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ set_target_properties(${fq_target_name}.__libc__
+ PROPERTIES ARCHIVE_OUTPUT_NAME ${fq_target_name}.libc)
+
+ set(compiler_runtime "")
+ if(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU)
+ target_link_options(${fq_build_target_name} PRIVATE
+ ${LIBC_COMPILE_OPTIONS_DEFAULT} -Wno-multi-gpu
+ -mcpu=${LIBC_GPU_TARGET_ARCHITECTURE} -flto -nostdlib -static
+ "-Wl,-mllvm,-amdhsa-code-object-version=${LIBC_GPU_CODE_OBJECT_VERSION}")
+ elseif(LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
+ target_link_options(${fq_build_target_name} PRIVATE
+ ${LIBC_COMPILE_OPTIONS_DEFAULT} -Wno-multi-gpu
+ "-Wl,--suppress-stack-size-warning"
+ "-Wl,-mllvm,-nvptx-emit-init-fini-kernel"
+ -march=${LIBC_GPU_TARGET_ARCHITECTURE} -nostdlib -static
+ "--cuda-path=${LIBC_CUDA_ROOT}")
+ elseif(LIBC_CC_SUPPORTS_NOSTDLIBPP)
+ set(link_options
+ -nostartfiles
+ -nodefaultlibs
+ -nostdlib++
+ -static
+ ${LIBC_LINK_OPTIONS_DEFAULT}
+ ${LIBC_TEST_LINK_OPTIONS_DEFAULT}
+ )
+ if(LIBC_ENABLE_COVERAGE)
+ list(APPEND link_options
+ -noprofilelib
+ -u__llvm_profile_runtime
+ )
+ endif()
+ target_link_options(${fq_build_target_name} PRIVATE ${link_options})
+ else()
+ # Older version of gcc does not support `nostdlib++` flag. We use
+ # `nostdlib` and link against libgcc_s, which cannot be linked statically.
+ set(link_options
+ -nostartfiles
+ -nodefaultlibs
+ -nostdlib
+ ${LIBC_LINK_OPTIONS_DEFAULT}
+ ${LIBC_TEST_LINK_OPTIONS_DEFAULT}
+ )
+ if(LIBC_ENABLE_COVERAGE)
+ list(APPEND link_options
+ -noprofilelib
+ -u__llvm_profile_runtime
+ )
+ endif()
+ target_link_options(${fq_build_target_name} PRIVATE ${link_options})
+ list(APPEND compiler_runtime ${LIBGCC_S_LOCATION})
+ endif()
- _get_common_test_compile_options(compile_options "${LIBC_UNITTEST_C_TEST}"
- "${LIBC_UNITTEST_FLAGS}")
+ set(coverage_link_libs "")
+ if(LIBC_ENABLE_COVERAGE)
+ set(coverage_link_libs
+ "${LIBC_CLANG_PROFILE_LIB}"
+ ${fq_target_name}.__libc__
+ )
+ endif()
+ target_link_libraries(
+ ${fq_build_target_name}
+ PRIVATE
+ ${startup_target_dep}
+ ${test_link_libraries}
+ ${fq_target_name}.__libc__
+ ${coverage_link_libs}
+ ${LIBC_TEST_BUILTINS_LIBRARY}
+ ${compiler_runtime}
+ )
+ if(LIBC_TEST_BUILTINS_TARGET)
+ target_link_libraries(${fq_build_target_name} PRIVATE $<TARGET_FILE:${LIBC_TEST_BUILTINS_TARGET}>)
+ add_dependencies(${fq_build_target_name} ${LIBC_TEST_BUILTINS_TARGET})
+ endif()
+endfunction()
+
+# Helper function for create_libc_test: configures linking for overlay mode tests
+# using host link options and linking object files and extra libraries.
+function(_link_libc_overlay_test fq_build_target_name compile_options link_object_files test_link_libraries)
get_link_options(link_options
${compile_options}
${LIBC_LINK_OPTIONS_DEFAULT}
${LIBC_TEST_LINK_OPTIONS_DEFAULT}
)
- list(APPEND compile_options ${LIBC_UNITTEST_COMPILE_OPTIONS})
+ target_link_options(${fq_build_target_name} PRIVATE ${link_options})
+
+ set(link_libraries ${link_object_files})
+ list(APPEND link_libraries ${test_link_libraries})
+ target_link_libraries(${fq_build_target_name} PRIVATE ${link_libraries})
+endfunction()
+
+# Helper function for create_libc_test: sets up the post-build custom target
+# and command to run the test binary (handling emulators, argument passing,
+# and parameter files).
+function(_add_libc_test_runner fq_target_name fq_build_target_name test_args loader_args test_env)
+ set(test_binary "${CMAKE_CURRENT_BINARY_DIR}/${fq_build_target_name}${CMAKE_EXECUTABLE_SUFFIX}")
+ if(LIBC_TEST_CMD)
+ string(REPLACE "@BINARY@" "${test_binary}" test_cmd_parsed ${LIBC_TEST_CMD})
+ string(REPLACE " " ";" test_cmd "${test_cmd_parsed}")
+ else()
+ set(test_cmd ${test_env})
+ if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
+ list(APPEND test_cmd "LIBOMPTARGET_STACK_SIZE=3072")
+ endif()
+ list(APPEND test_cmd
+ ${CMAKE_CROSSCOMPILING_EMULATOR} ${loader_args}
+ "${test_binary}" ${test_args})
+ endif()
+
+ if(loader_args OR test_args OR test_env OR LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
+ set(_params_content "")
+ foreach(_arg IN LISTS loader_args)
+ string(APPEND _params_content "${_arg}\n")
+ endforeach()
+ string(APPEND _params_content "---\n")
+ foreach(_arg IN LISTS test_args)
+ string(APPEND _params_content "${_arg}\n")
+ endforeach()
+ string(APPEND _params_content "---\n")
+ foreach(_env_entry IN LISTS test_env)
+ string(APPEND _params_content "${_env_entry}\n")
+ endforeach()
+ if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
+ string(APPEND _params_content "LIBOMPTARGET_STACK_SIZE=3072\n")
+ endif()
+
+ file(GENERATE
+ OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${fq_build_target_name}.params"
+ CONTENT "${_params_content}"
+ )
+ endif()
+
+ add_custom_target(
+ ${fq_target_name}
+ COMMAND ${test_cmd}
+ COMMAND_EXPAND_LISTS
+ DEPENDS ${fq_build_target_name}
+ COMMENT "Running test ${fq_target_name}"
+ ${LIBC_HERMETIC_TEST_JOB_POOL}
+ )
+endfunction()
+
+# Helper function for create_libc_test: registers the test and its build target
+# with the appropriate test suite (or libc-tests / libc-tests-build).
+function(_register_libc_test_with_suite fq_target_name fq_build_target_name suite)
+ if(suite)
+ add_libc_testsuite(${suite})
+ add_dependencies(${suite} ${fq_target_name})
+ if(TARGET ${suite}-build)
+ add_dependencies(${suite}-build ${fq_build_target_name})
+ endif()
+ else()
+ if(TARGET libc-tests)
+ add_dependencies(libc-tests ${fq_target_name})
+ endif()
+ if(TARGET libc-tests-build)
+ add_dependencies(libc-tests-build ${fq_build_target_name})
+ endif()
+ endif()
+endfunction()
+
+# Core rule to create a libc test executable and runner (overlay or hermetic).
+function(create_libc_test fq_target_name)
+ if(NOT LLVM_INCLUDE_TESTS)
+ return()
+ endif()
+
+ llvm_libc_parse_arguments(TEST ${ARGN})
+
+ # 1. Validate build mode and target platform
+ if(LLVM_LIBC_FULL_BUILD AND TEST_OVERLAY_ONLY)
+ return()
+ endif()
+ if(NOT LLVM_LIBC_FULL_BUILD AND TEST_FULL_BUILD_ONLY)
+ return()
+ endif()
+
+ set(startup_target_dep "")
+ if(LLVM_LIBC_FULL_BUILD)
+ set(startup_target libc.startup.${LIBC_TARGET_OS}.crt1)
+ if(LLVM_LIBC_HERMETIC_TEST_USE_INTERNAL_STARTUP)
+ if(TEST_STARTUP)
+ message(FATAL_ERROR
+ "Hermetic test ${fq_target_name} provides an external STARTUP target "
+ "while internal startup is enabled.")
+ endif()
+ if(NOT TARGET ${startup_target})
+ if(LIBC_CMAKE_VERBOSE_LOGGING)
+ message(STATUS "Skipping ${fq_target_name} as ${startup_target} is not available on ${LIBC_TARGET_OS}.")
+ endif()
+ return()
+ endif()
+ set(startup_target_dep ${startup_target})
+ elseif(TEST_STARTUP)
+ get_fq_dep_name(startup_target_dep ${TEST_STARTUP})
+ if(NOT TARGET ${startup_target_dep})
+ message(FATAL_ERROR
+ "Hermetic test ${fq_target_name} startup target ${startup_target_dep} does not exist.")
+ endif()
+ endif()
+
+ if(NOT startup_target_dep AND NOT LIBC_TEST_LINK_OPTIONS_DEFAULT)
+ if(LIBC_CMAKE_VERBOSE_LOGGING)
+ message(STATUS "Skipping ${fq_target_name} as it has no startup provider.")
+ endif()
+ return()
+ endif()
+ endif()
+
+ if(NOT TEST_SRCS)
+ message(FATAL_ERROR "'create_libc_test' target requires a SRCS list of .cpp files.")
+ endif()
+
+ # 2. Resolve dependencies and link objects
+ _get_libc_test_dependencies(fq_deps_list "${TEST_DEPENDS}" "${startup_target_dep}" "${TEST_C_TEST}")
if(SHOW_INTERMEDIATE_OBJECTS)
- message(STATUS "Adding unit test ${fq_target_name}")
- if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
- foreach(dep IN LISTS LIBC_UNITTEST_DEPENDS)
+ message(STATUS "Adding test ${fq_target_name}")
+ if("${SHOW_INTERMEDIATE_OBJECTS}" STREQUAL "DEPS")
+ foreach(dep IN LISTS TEST_DEPENDS)
message(STATUS " ${fq_target_name} depends on ${dep}")
endforeach()
endif()
@@ -354,32 +741,24 @@ function(create_libc_unittest fq_target_name)
get_object_files_for_test(
link_object_files skipped_entrypoints_list ${fq_deps_list})
if(skipped_entrypoints_list)
- # If a test is OS/target machine independent, it has to be skipped if the
- # OS/target machine combination does not provide any dependent entrypoints.
- # If a test is OS/target machine specific, then such a test will live is a
- # OS/target machine specific directory and will be skipped at the directory
- # level if required.
- #
- # There can potentially be a setup like this: A unittest is setup for a
- # OS/target machine independent object library, which in turn depends on a
- # machine specific object library. Such a test would be testing internals of
- # the libc and it is assumed that they will be rare in practice. So, they
- # can be skipped in the corresponding CMake files using platform specific
- # logic. This pattern is followed in the startup tests for example.
- #
- # Another pattern that is present currently is to detect machine
- # capabilities and add entrypoints and tests accordingly. That approach is
- # much lower level approach and is independent of the kind of skipping that
- # is happening here at the entrypoint level.
if(LIBC_CMAKE_VERBOSE_LOGGING)
- set(msg "Skipping unittest ${fq_target_name} as it has missing deps: "
+ set(msg "Skipping test ${fq_target_name} as it has missing deps: "
"${skipped_entrypoints_list}.")
message(STATUS ${msg})
endif()
return()
endif()
+ list(REMOVE_DUPLICATES link_object_files)
- if(LIBC_UNITTEST_NO_RUN_POSTBUILD)
+ # Collect standard library targets from dependencies that do not provide raw object files.
+ _get_libc_test_link_libraries(dep_link_libraries "${fq_deps_list}")
+ list(APPEND TEST_LINK_LIBRARIES ${dep_link_libraries})
+ if(TEST_LINK_LIBRARIES)
+ list(REMOVE_DUPLICATES TEST_LINK_LIBRARIES)
+ endif()
+
+ # 3. Create the test executable
+ if(TEST_NO_RUN_POSTBUILD)
set(fq_build_target_name ${fq_target_name})
else()
set(fq_build_target_name ${fq_target_name}.__build__)
@@ -388,80 +767,86 @@ function(create_libc_unittest fq_target_name)
add_executable(
${fq_build_target_name}
EXCLUDE_FROM_ALL
- ${LIBC_UNITTEST_SRCS}
- ${LIBC_UNITTEST_HDRS}
+ ${TEST_SRCS}
+ ${TEST_HDRS}
)
+
target_include_directories(${fq_build_target_name} SYSTEM PRIVATE ${LIBC_INCLUDE_DIR})
target_include_directories(${fq_build_target_name} PRIVATE ${LIBC_SOURCE_DIR})
target_include_directories(${fq_build_target_name} PRIVATE ${LIBC_BUILD_DIR})
+
+ if(LLVM_LIBC_FULL_BUILD)
+ _get_hermetic_test_compile_options(compile_options "${TEST_C_TEST}"
+ "${TEST_FLAGS}")
+ else()
+ _get_common_test_compile_options(compile_options "${TEST_C_TEST}"
+ "${TEST_FLAGS}")
+ endif()
+ list(APPEND compile_options ${TEST_COMPILE_OPTIONS})
target_compile_options(${fq_build_target_name} PRIVATE ${compile_options})
- target_link_options(${fq_build_target_name} PRIVATE ${link_options})
- if(NOT LIBC_UNITTEST_CXX_STANDARD)
- set(LIBC_UNITTEST_CXX_STANDARD ${CMAKE_CXX_STANDARD})
+ if(NOT TEST_CXX_STANDARD)
+ set(TEST_CXX_STANDARD ${CMAKE_CXX_STANDARD})
endif()
set_target_properties(
${fq_build_target_name}
PROPERTIES
- CXX_STANDARD ${LIBC_UNITTEST_CXX_STANDARD}
+ RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ CXX_STANDARD ${TEST_CXX_STANDARD}
)
- set(link_libraries ${link_object_files})
- # Test object files will depend on LINK_LIBRARIES passed down from `add_fp_unittest`
- list(APPEND link_libraries ${LIBC_UNITTEST_LINK_LIBRARIES})
-
- set_target_properties(${fq_build_target_name}
- PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+ # 4. Configure linking
+ if(LLVM_LIBC_FULL_BUILD)
+ _link_libc_hermetic_test(
+ ${fq_target_name}
+ ${fq_build_target_name}
+ "${startup_target_dep}"
+ "${link_object_files}"
+ "${TEST_LINK_LIBRARIES}"
+ )
+ else()
+ _link_libc_overlay_test(
+ ${fq_build_target_name}
+ "${compile_options}"
+ "${link_object_files}"
+ "${TEST_LINK_LIBRARIES}"
+ )
+ endif()
add_dependencies(
${fq_build_target_name}
${fq_deps_list}
)
- target_link_libraries(${fq_build_target_name} PRIVATE ${link_libraries})
-
- if(NOT LIBC_UNITTEST_NO_RUN_POSTBUILD)
- add_custom_target(
+ # 5. Add test runner target if post-build run is enabled
+ if(NOT TEST_NO_RUN_POSTBUILD)
+ _add_libc_test_runner(
${fq_target_name}
- COMMAND ${LIBC_UNITTEST_ENV} ${CMAKE_CROSSCOMPILING_EMULATOR} ${CMAKE_CURRENT_BINARY_DIR}/${fq_build_target_name}
- COMMENT "Running unit test ${fq_target_name}"
- DEPENDS ${fq_build_target_name}
+ ${fq_build_target_name}
+ "${TEST_ARGS}"
+ "${TEST_LOADER_ARGS}"
+ "${TEST_ENV}"
)
endif()
- # The SUITE variable can be used to group tests into a custom target.
- # If a target named ${LIBC_UNITTEST_SUITE}-build exists, we add the
- # test executable to it as a dependency. This allows building the
- # test binaries for Lit without triggering their execution.
- if(LIBC_UNITTEST_SUITE)
- add_dependencies(${LIBC_UNITTEST_SUITE} ${fq_target_name})
- if(TARGET ${LIBC_UNITTEST_SUITE}-build)
- add_dependencies(${LIBC_UNITTEST_SUITE}-build ${fq_build_target_name})
+ # 6. Register with test suite
+ if(TEST_IS_GPU_BENCHMARK)
+ if(TEST_SUITE)
+ add_dependencies(${TEST_SUITE} ${fq_target_name})
endif()
- endif()
- add_dependencies(libc-unit-tests ${fq_target_name})
- if(TARGET libc-unit-tests-build)
- add_dependencies(libc-unit-tests-build ${fq_build_target_name})
+ else()
+ _register_libc_test_with_suite(${fq_target_name} ${fq_build_target_name} "${TEST_SUITE}")
endif()
endfunction()
-function(_add_libc_unittest target_name)
+function(_add_libc_test target_name)
add_target_with_flags(
${target_name}
- CREATE_TARGET create_libc_unittest
+ CREATE_TARGET create_libc_test
${ARGN}
)
endfunction()
-function(add_libc_exhaustive_testsuite suite_name)
- add_custom_target(${suite_name})
- add_dependencies(exhaustive-check-libc ${suite_name})
-endfunction()
-
-function(add_libc_long_running_testsuite suite_name)
- add_custom_target(${suite_name})
- add_dependencies(libc-long-running-tests ${suite_name})
-endfunction()
# Rule to add a fuzzer test.
# Usage
@@ -472,13 +857,7 @@ endfunction()
# DEPENDS <list of dependencies>
# )
function(add_libc_fuzzer target_name)
- cmake_parse_arguments(
- "LIBC_FUZZER"
- "NEED_MPFR" # Optional arguments
- "" # Single value arguments
- "SRCS;HDRS;DEPENDS;COMPILE_OPTIONS;LINK_LIBRARIES" # Multi-value arguments
- ${ARGN}
- )
+ llvm_libc_parse_arguments(LIBC_FUZZER ${ARGN})
if(NOT LIBC_FUZZER_SRCS)
message(FATAL_ERROR "'add_libc_fuzzer' target requires a SRCS list of .cpp "
"files.")
@@ -546,39 +925,10 @@ function(add_libc_fuzzer target_name)
PRIVATE
${LIBC_FUZZER_COMPILE_OPTIONS})
-endfunction()
-
-# Get libgcc_s to be used in hermetic and integration tests.
-if(NOT MSVC AND NOT LIBC_CC_SUPPORTS_NOSTDLIBPP)
- execute_process(COMMAND ${CMAKE_CXX_COMPILER} -print-file-name=libgcc_s.so.1
- OUTPUT_VARIABLE LIBGCC_S_LOCATION)
- string(STRIP ${LIBGCC_S_LOCATION} LIBGCC_S_LOCATION)
-endif()
-
-# Hermetic and integration tests link with -nodefaultlibs, so the compiler
-# runtime builtins have to be linked explicitly. -print-libgcc-file-name
-# reports whichever library the driver would use (libgcc.a or
-# libclang_rt.builtins.a). The query uses the same flags as the test link so
-# that the driver selects the same multilib. GPU and UEFI targets do not link a
-# compiler runtime.
-if(LLVM_INCLUDE_TESTS AND LLVM_LIBC_FULL_BUILD AND NOT LIBC_TARGET_OS_IS_GPU AND
- NOT LIBC_TARGET_OS_IS_UEFI AND
- NOT LIBC_TEST_BUILTINS_LIBRARY AND NOT LIBC_TEST_BUILTINS_TARGET)
- separate_arguments(libc_cxx_flags NATIVE_COMMAND "${CMAKE_CXX_FLAGS}")
- execute_process(
- COMMAND ${CMAKE_CXX_COMPILER} ${libc_cxx_flags}
- ${LIBC_COMPILE_OPTIONS_DEFAULT} ${LIBC_TEST_LINK_OPTIONS_DEFAULT}
- -print-libgcc-file-name
- OUTPUT_VARIABLE LIBC_TEST_BUILTINS_LIBRARY
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- if(NOT EXISTS "${LIBC_TEST_BUILTINS_LIBRARY}")
- message(FATAL_ERROR "Compiler runtime builtins library "
- "'${LIBC_TEST_BUILTINS_LIBRARY}' not found. Set "
- "LIBC_TEST_BUILTINS_LIBRARY or LIBC_TEST_BUILTINS_TARGET.")
- endif()
-endif()
+endfunction()
+
-# DEPRECATED: Use add_hermetic_test instead.
+# DEPRECATED: Use add_libc_test instead.
#
# Rule to add an integration test. An integration test is like a unit test
# but does not use the system libc. Not even the startup objects from the
@@ -607,13 +957,7 @@ function(add_integration_test test_name)
message(STATUS "Skipping ${fq_target_name} as it is not available on ${LIBC_TARGET_OS}.")
return()
endif()
- cmake_parse_arguments(
- "INTEGRATION_TEST"
- "" # No optional arguments
- "SUITE" # Single value arguments
- "SRCS;HDRS;DEPENDS;ARGS;ENV;COMPILE_OPTIONS;LOADER_ARGS" # Multi-value arguments
- ${ARGN}
- )
+ llvm_libc_parse_arguments(INTEGRATION_TEST ${ARGN})
if(NOT INTEGRATION_TEST_SUITE)
message(FATAL_ERROR "SUITE not specified for ${fq_target_name}")
@@ -802,420 +1146,84 @@ function(add_integration_test test_name)
endif()
endfunction()
-# Rule to add a hermetic program. A hermetic program is one whose executable is fully
-# statically linked and consists of pieces drawn only from LLVM's libc. Nothing,
-# including the startup objects, come from the system libc.
-#
-# For the GPU, these can be either tests or benchmarks, depending on the value
-# of the LINK_LIBRARIES arg.
-#
-# Usage:
-# add_libc_hermetic(
-# <target name>
-# SUITE <the suite to which the test should belong>
-# SRCS <src1.cpp> [src2.cpp ...]
-# HDRS [hdr1.cpp ...]
-# DEPENDS <list of entrypoint or other object targets>
-# ARGS <list of command line arguments to be passed to the test>
-# ENV <list of environment variables to set before running the test>
-# COMPILE_OPTIONS <list of special compile options for the test>
-# LINK_LIBRARIES <list of linking libraries for this target>
-# LOADER_ARGS <list of special args to loaders (like the GPU loader)>
-# STARTUP <startup object target used when internal startup is disabled>
-# )
-function(add_libc_hermetic test_name)
- get_fq_target_name(${test_name} fq_target_name)
- get_fq_target_name(${test_name}.libc fq_libc_target_name)
-
- cmake_parse_arguments(
- "HERMETIC_TEST"
- "IS_GPU_BENCHMARK;NO_RUN_POSTBUILD;C_TEST" # Optional arguments
- "SUITE;CXX_STANDARD;STARTUP" # Single value arguments
- "SRCS;HDRS;DEPENDS;ARGS;ENV;COMPILE_OPTIONS;LINK_LIBRARIES;FLAGS;LOADER_ARGS" # Multi-value arguments
- ${ARGN}
- )
+# A unified function to add a libc test.
+# FULL_BUILD_ONLY: skip test in overlay mode.
+# OVERLAY_ONLY: skip test in full build mode.
+# FP_TEST: add floating-point test helper dependencies.
+# NEED_MPFR / NEED_MPFR_F80 / NEED_MPFR_F128: link against MPFR; tests requiring MPFR run only in overlay mode.
+# NEED_MPC: link against MPC and MPFR; tests requiring MPC run only in overlay mode.
+function(add_libc_test test_name)
+ llvm_libc_parse_arguments(LIBC_TEST ${ARGN})
- set(startup_target libc.startup.${LIBC_TARGET_OS}.crt1)
- set(startup_target_dep "")
- if(LLVM_LIBC_HERMETIC_TEST_USE_INTERNAL_STARTUP)
- if(HERMETIC_TEST_STARTUP)
- message(FATAL_ERROR
- "Hermetic test ${fq_target_name} provides an external STARTUP target "
- "while internal startup is enabled.")
- endif()
- if(NOT TARGET ${startup_target})
- if(LIBC_CMAKE_VERBOSE_LOGGING)
- message(STATUS "Skipping ${fq_target_name} as ${startup_target} is not available on ${LIBC_TARGET_OS}.")
- endif()
+ if(LIBC_TEST_NEED_MPC)
+ set(LIBC_TEST_NEED_MPFR TRUE)
+ if(NOT LIBC_TESTS_CAN_USE_MPC)
+ message(VERBOSE "Complex test ${test_name} will be skipped as MPC library is not available.")
return()
endif()
- set(startup_target_dep ${startup_target})
- elseif(HERMETIC_TEST_STARTUP)
- get_fq_dep_name(startup_target_dep ${HERMETIC_TEST_STARTUP})
- if(NOT TARGET ${startup_target_dep})
- message(FATAL_ERROR
- "Hermetic test ${fq_target_name} startup target ${startup_target_dep} does not exist.")
- endif()
+ list(APPEND LIBC_TEST_DEPENDS libc.utils.MPCWrapper)
endif()
- if(NOT startup_target_dep AND NOT LIBC_TEST_LINK_OPTIONS_DEFAULT)
- if(LIBC_CMAKE_VERBOSE_LOGGING)
- message(STATUS "Skipping ${fq_target_name} as it has no startup provider.")
+ if(LIBC_TEST_NEED_MPFR_F80)
+ set(LIBC_TEST_NEED_MPFR TRUE)
+ if(NOT LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
+ message(VERBOSE "Math test ${test_name} will be skipped as float80 support in MPFR is not available.")
+ return()
endif()
- return()
- endif()
-
- if(NOT HERMETIC_TEST_SUITE)
- message(FATAL_ERROR "SUITE not specified for ${fq_target_name}")
- endif()
- if(NOT HERMETIC_TEST_SRCS)
- message(FATAL_ERROR "The SRCS list for add_integration_test is missing.")
- endif()
-
- get_fq_deps_list(fq_deps_list ${HERMETIC_TEST_DEPENDS})
- list(APPEND fq_deps_list
- # Hermetic tests use the platform's startup object. So, their deps also
- # have to be collected.
- ${startup_target_dep}
- # We always add the memory functions objects. This is because the
- # compiler's codegen can emit calls to the C memory functions.
- libc.src.__support.StringUtil.error_to_string
- libc.src.string.memcmp
- libc.src.string.memcpy
- libc.src.string.memmove
- libc.src.string.memset
- libc.src.strings.bcmp
- libc.src.strings.bzero
- libc.test.UnitTest.ErrnoSetterMatcher
- libc.test.UnitTest.LibcTest
- libc.test.UnitTest.HermeticTestUtils
- )
- if(HERMETIC_TEST_C_TEST)
- list(APPEND fq_deps_list libc.test.UnitTest.LibcCTest)
- endif()
- if(LIBC_TARGET_ARCHITECTURE_IS_AARCH64 AND NOT(LIBC_TARGET_OS_IS_BAREMETAL))
- list(APPEND fq_deps_list libc.src.sys.auxv.getauxval)
- endif()
-
- # Syscalls used by death tests.
- if(LIBC_TEST_SUBPROCESS_TESTS AND NOT HERMETIC_TEST_C_TEST)
- list(APPEND fq_deps_list
- libc.test.UnitTest.LibcDeathTestExecutors
- libc.src.poll.poll
- libc.src.signal.kill
- libc.src.stdio.fflush
- libc.src.stdio.stderr
- libc.src.stdio.stdout
- libc.src.stdlib.exit
- libc.src.string.strsignal
- libc.src.sys.wait.waitpid
- libc.src.unistd.close
- libc.src.unistd.fork
- libc.src.unistd.pipe
- )
- endif()
-
- if(NOT LLVM_LIBC_HERMETIC_TEST_USE_INTERNAL_STARTUP AND LIBC_TARGET_OS_IS_BAREMETAL)
- # External baremetal startup objects still need libc's process startup and
- # termination entrypoints, even when the test itself does not depend on them.
- list(APPEND fq_deps_list
- libc.src.stdlib.atexit
- libc.src.stdlib.exit
- libc.startup.baremetal.init
- )
- endif()
-
- if(libc.src.compiler.__stack_chk_fail IN_LIST TARGET_LLVMLIBC_ENTRYPOINTS)
- # __stack_chk_fail should always be included if supported to allow building
- # libc with the stack protector enabled.
- list(APPEND fq_deps_list libc.src.compiler.__stack_chk_fail)
- endif()
-
- if(libc.src.time.clock IN_LIST TARGET_LLVMLIBC_ENTRYPOINTS)
- # We will link in the 'clock' implementation if it exists for test timing.
- list(APPEND fq_deps_list libc.src.time.clock)
- endif()
-
- if(LIBC_ENABLE_COVERAGE)
- set(coverage_deps
- libc.src.stdio.fclose
- libc.src.stdio.fdopen
- libc.src.stdio.feof
- libc.src.stdio.fflush
- libc.src.stdio.fileno
- libc.src.stdio.fopen
- libc.src.stdio.fprintf
- libc.src.stdio.fread
- libc.src.stdio.fseek
- libc.src.stdio.ftell
- libc.src.stdio.fwrite
- libc.src.stdio.snprintf
- libc.src.stdio.stderr
- libc.src.stdio.vfprintf
- libc.src.stdio.vsnprintf
- libc.src.fcntl.fcntl
- libc.src.fcntl.open
- libc.src.stdlib.getenv
- libc.src.stdlib.setenv
- libc.src.stdlib.strtol
- libc.src.string.strchr
- libc.src.string.strcmp
- libc.src.string.strdup
- libc.src.string.strerror
- libc.src.string.strlen
- libc.src.string.strncpy
- libc.src.string.strrchr
- libc.src.sys.mman.madvise
- libc.src.sys.mman.mmap
- libc.src.sys.mman.munmap
- libc.src.sys.prctl.prctl
- libc.src.sys.stat.mkdir
- libc.src.sys.utsname.uname
- libc.src.unistd.fork
- libc.src.unistd.ftruncate
- libc.src.unistd.getpagesize
- libc.src.unistd.getpid
- )
- list(APPEND fq_deps_list ${coverage_deps})
endif()
- list(REMOVE_DUPLICATES fq_deps_list)
-
- # TODO: Instead of gathering internal object files from entrypoints,
- # collect the object files with public names of entrypoints.
- get_object_files_for_test(
- link_object_files skipped_entrypoints_list ${fq_deps_list})
- if(skipped_entrypoints_list)
- if(LIBC_CMAKE_VERBOSE_LOGGING)
- set(msg "Skipping hermetic test ${fq_target_name} as it has missing deps: "
- "${skipped_entrypoints_list}.")
- message(STATUS ${msg})
+ # TODO: To be removed when we find a workaround to run MPFR tests for
+ # emulated type where compiler doesn't support the native float128
+ # TODO: Check mpfr_buildopt_float128_p() returns non-zero.
+ if(LIBC_TEST_NEED_MPFR_F128)
+ set(LIBC_TEST_NEED_MPFR TRUE)
+ if(NOT LIBC_TYPES_HAS_NATIVE_FLOAT128)
+ message(VERBOSE "Math test ${test_name} will be skipped as native float128 support in MPFR is not available.")
+ return()
endif()
- return()
- endif()
- list(REMOVE_DUPLICATES link_object_files)
-
- if(LIBC_ENABLE_COVERAGE)
- foreach(cov_dep IN LISTS coverage_deps)
- get_target_property(is_alias ${cov_dep} "IS_ALIAS")
- if(is_alias)
- get_target_property(real_target ${cov_dep} "DEPS")
- else()
- set(real_target ${cov_dep})
- endif()
- string(REPLACE "${real_target}.__internal__" "${real_target}" link_object_files "${link_object_files}")
- endforeach()
- endif()
-
- # Make a library of all deps
- add_library(
- ${fq_target_name}.__libc__
- STATIC
- EXCLUDE_FROM_ALL
- ${link_object_files}
- )
- set_target_properties(${fq_target_name}.__libc__
- PROPERTIES ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
- set_target_properties(${fq_target_name}.__libc__
- PROPERTIES ARCHIVE_OUTPUT_NAME ${fq_target_name}.libc)
-
- if(HERMETIC_TEST_NO_RUN_POSTBUILD)
- set(fq_build_target_name ${fq_target_name})
- else()
- set(fq_build_target_name ${fq_target_name}.__build__)
- endif()
-
- add_executable(
- ${fq_build_target_name}
- EXCLUDE_FROM_ALL
- ${HERMETIC_TEST_SRCS}
- ${HERMETIC_TEST_HDRS}
- )
-
- if(NOT HERMETIC_TEST_CXX_STANDARD)
- set(HERMETIC_TEST_CXX_STANDARD ${CMAKE_CXX_STANDARD})
endif()
- set_target_properties(${fq_build_target_name}
- PROPERTIES
- RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
- CXX_STANDARD ${HERMETIC_TEST_CXX_STANDARD}
- )
-
- target_include_directories(${fq_build_target_name} SYSTEM PRIVATE ${LIBC_INCLUDE_DIR})
- target_include_directories(${fq_build_target_name} PRIVATE ${LIBC_SOURCE_DIR})
- _get_hermetic_test_compile_options(compile_options "${HERMETIC_TEST_C_TEST}"
- "${HERMETIC_TEST_FLAGS}")
- target_compile_options(${fq_build_target_name} PRIVATE
- ${compile_options}
- ${HERMETIC_TEST_COMPILE_OPTIONS})
-
- set(compiler_runtime "")
- if(LIBC_TARGET_ARCHITECTURE_IS_AMDGPU)
- target_link_options(${fq_build_target_name} PRIVATE
- ${LIBC_COMPILE_OPTIONS_DEFAULT} -Wno-multi-gpu
- -mcpu=${LIBC_GPU_TARGET_ARCHITECTURE} -flto -nostdlib -static
- "-Wl,-mllvm,-amdhsa-code-object-version=${LIBC_GPU_CODE_OBJECT_VERSION}")
- elseif(LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
- target_link_options(${fq_build_target_name} PRIVATE
- ${LIBC_COMPILE_OPTIONS_DEFAULT} -Wno-multi-gpu
- "-Wl,--suppress-stack-size-warning"
- "-Wl,-mllvm,-nvptx-emit-init-fini-kernel"
- -march=${LIBC_GPU_TARGET_ARCHITECTURE} -nostdlib -static
- "--cuda-path=${LIBC_CUDA_ROOT}")
- elseif(LIBC_CC_SUPPORTS_NOSTDLIBPP)
- set(link_options
- -nostartfiles
- -nodefaultlibs
- -nostdlib++
- -static
- ${LIBC_LINK_OPTIONS_DEFAULT}
- ${LIBC_TEST_LINK_OPTIONS_DEFAULT}
- )
- if(LIBC_ENABLE_COVERAGE)
- list(APPEND link_options
- -noprofilelib
- -u__llvm_profile_runtime
- )
+ if(LIBC_TEST_NEED_MPFR)
+ if(LIBC_TEST_FULL_BUILD_ONLY)
+ message(FATAL_ERROR "Full-build test cannot require MPFR.")
endif()
- target_link_options(${fq_build_target_name} PRIVATE ${link_options})
- else()
- # Older version of gcc does not support `nostdlib++` flag. We use
- # `nostdlib` and link against libgcc_s, which cannot be linked statically.
- set(link_options
- -nostartfiles
- -nodefaultlibs
- -nostdlib
- ${LIBC_LINK_OPTIONS_DEFAULT}
- ${LIBC_TEST_LINK_OPTIONS_DEFAULT}
- )
- if(LIBC_ENABLE_COVERAGE)
- list(APPEND link_options
- -noprofilelib
- -u__llvm_profile_runtime
- )
+ if(NOT LIBC_TESTS_CAN_USE_MPFR)
+ message(VERBOSE "Test ${test_name} will be skipped as MPFR library is not available.")
+ return()
endif()
- target_link_options(${fq_build_target_name} PRIVATE ${link_options})
- list(APPEND compiler_runtime ${LIBGCC_S_LOCATION})
+ set(LIBC_TEST_OVERLAY_ONLY TRUE)
+ list(APPEND LIBC_TEST_DEPENDS libc.utils.MPFRWrapper)
endif()
- set(coverage_link_libs "")
- if(LIBC_ENABLE_COVERAGE)
- set(coverage_link_libs
- "${LIBC_CLANG_PROFILE_LIB}"
- ${fq_target_name}.__libc__
+ if(LIBC_TEST_FP_TEST)
+ list(APPEND LIBC_TEST_DEPENDS
+ libc.hdr.math_macros
+ libc.test.UnitTest.FPTestHelpers
+ libc.hdr.stdint_proxy
)
endif()
- target_link_libraries(
- ${fq_build_target_name}
- PRIVATE
- ${startup_target_dep}
- ${HERMETIC_TEST_LINK_LIBRARIES}
- ${fq_target_name}.__libc__
- ${coverage_link_libs}
- ${LIBC_TEST_BUILTINS_LIBRARY}
- ${compiler_runtime}
- )
- if(LIBC_TEST_BUILTINS_TARGET)
- target_link_libraries(${fq_build_target_name} PRIVATE $<TARGET_FILE:${LIBC_TEST_BUILTINS_TARGET}>)
- add_dependencies(${fq_build_target_name} ${LIBC_TEST_BUILTINS_TARGET})
+ if(LLVM_LIBC_FULL_BUILD AND LIBC_TEST_OVERLAY_ONLY)
+ return()
endif()
- add_dependencies(${fq_build_target_name} ${fq_deps_list})
-
- if(NOT HERMETIC_TEST_NO_RUN_POSTBUILD)
- if(LIBC_TEST_CMD)
- # In the form of "<command> binary=@BINARY@", e.g. "qemu-system-arm -loader$<COMMA>file=@BINARY@"
- string(REPLACE "@BINARY@" "$<TARGET_FILE:${fq_build_target_name}>" test_cmd_parsed ${LIBC_TEST_CMD})
- string(REPLACE " " ";" test_cmd "${test_cmd_parsed}")
- else()
- set(test_cmd ${HERMETIC_TEST_ENV}
- $<$<BOOL:${LIBC_TARGET_ARCHITECTURE_IS_NVPTX}>:LIBOMPTARGET_STACK_SIZE=3072>
- ${CMAKE_CROSSCOMPILING_EMULATOR} ${HERMETIC_TEST_LOADER_ARGS}
- $<TARGET_FILE:${fq_build_target_name}> ${HERMETIC_TEST_ARGS})
- endif()
-
- set(_params_content "")
- foreach(_arg IN LISTS HERMETIC_TEST_LOADER_ARGS)
- string(APPEND _params_content "${_arg}\n")
- endforeach()
- string(APPEND _params_content "---\n")
- foreach(_arg IN LISTS HERMETIC_TEST_ARGS)
- string(APPEND _params_content "${_arg}\n")
- endforeach()
- string(APPEND _params_content "---\n")
- foreach(_env_entry IN LISTS HERMETIC_TEST_ENV)
- string(APPEND _params_content "${_env_entry}\n")
- endforeach()
- if(LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
- string(APPEND _params_content "LIBOMPTARGET_STACK_SIZE=3072\n")
- endif()
-
- if(HERMETIC_TEST_LOADER_ARGS OR HERMETIC_TEST_ARGS OR HERMETIC_TEST_ENV OR LIBC_TARGET_ARCHITECTURE_IS_NVPTX)
- file(GENERATE
- OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${fq_build_target_name}.params"
- CONTENT "${_params_content}"
- )
- endif()
-
- add_custom_target(
- ${fq_target_name}
- DEPENDS ${fq_target_name}.__cmd__
- )
-
- add_custom_command(
- OUTPUT ${fq_target_name}.__cmd__
- COMMAND ${test_cmd}
- COMMAND_EXPAND_LISTS
- COMMENT "Running hermetic test ${fq_target_name}"
- ${LIBC_HERMETIC_TEST_JOB_POOL}
- )
-
- set_source_files_properties(${fq_target_name}.__cmd__
- PROPERTIES
- SYMBOLIC "TRUE"
- )
+ if(NOT LLVM_LIBC_FULL_BUILD AND LIBC_TEST_FULL_BUILD_ONLY)
+ return()
endif()
- add_dependencies(${HERMETIC_TEST_SUITE} ${fq_target_name})
- if(NOT ${HERMETIC_TEST_IS_GPU_BENCHMARK})
- # If it is a benchmark, it will already have been added to the
- # gpu-benchmark target
- add_dependencies(libc-hermetic-tests ${fq_target_name})
- if(LIBC_HERMETIC_TEST_SUITE)
- add_dependencies(${LIBC_HERMETIC_TEST_SUITE} ${fq_target_name})
- # If a target named ${LIBC_HERMETIC_TEST_SUITE}-build exists, we add the
- # test executable to it as a dependency. This allows building the
- # test binaries for Lit without triggering their execution.
- if(TARGET ${LIBC_HERMETIC_TEST_SUITE}-build)
- add_dependencies(${LIBC_HERMETIC_TEST_SUITE}-build ${fq_build_target_name})
- endif()
- endif()
- if(TARGET libc-hermetic-tests-build)
- add_dependencies(libc-hermetic-tests-build ${fq_build_target_name})
- endif()
- endif()
+ forward_arguments(LIBC_TEST forwarded_args)
+ _add_libc_test(
+ ${test_name}
+ ${forwarded_args}
+ ${LIBC_TEST_UNPARSED_ARGUMENTS}
+ )
endfunction()
-# A convenience function to add both a unit test as well as a hermetic test.
-function(add_libc_test test_name)
- cmake_parse_arguments(
- "LIBC_TEST"
- "FULL_BUILD_ONLY;OVERLAY_BUILD_ONLY" # Optional arguments
- "" # Single value arguments
- "" # Multi-value arguments
+function(add_fp_unittest test_name)
+ add_libc_test(
+ ${test_name}
+ FP_TEST
${ARGN}
)
- if(LLVM_LIBC_FULL_BUILD)
- if(NOT LIBC_TEST_OVERLAY_BUILD_ONLY)
- add_libc_hermetic(${test_name} ${LIBC_TEST_UNPARSED_ARGUMENTS})
- endif()
- else()
- # Overlay mode
- if(NOT LIBC_TEST_FULL_BUILD_ONLY)
- _add_libc_unittest(${test_name} ${LIBC_TEST_UNPARSED_ARGUMENTS})
- endif()
- endif()
endfunction()
# Tests all implementations that can run on the target CPU.
diff --git a/libc/docs/dev/code_coverage.md b/libc/docs/dev/code_coverage.md
index 8e58ca5d14ffdf..344c7a9033a97a 100644
--- a/libc/docs/dev/code_coverage.md
+++ b/libc/docs/dev/code_coverage.md
@@ -170,19 +170,19 @@ export LLVM_PROFDATA="$PWD/build-clang/bin/llvm-profdata"
export LLVM_COV="$PWD/build-clang/bin/llvm-cov"
```
-### 4. Build and Execute Hermetic Tests
+### 4. Build and Execute Tests
-Compiles and executes the full hermetic test suite:
+Compiles and executes the test suite:
```bash
-ninja -k 0 -C build-cov libc-hermetic-tests
+ninja -k 0 -C build-cov libc-tests
```
:::{note}
The `-k 0` flag ensures Ninja continues executing all remaining test targets
even if an individual edge-case test encounters an error. To only compile test
binaries without executing them, use
-`ninja -C build-cov libc-hermetic-tests-build`.
+`ninja -C build-cov libc-tests-build`.
:::
### 5. Merge Profile Counters
@@ -295,13 +295,13 @@ export LLVM_PROFDATA="$PWD/build-clang/bin/llvm-profdata"
export LLVM_COV="$PWD/build-clang/bin/llvm-cov"
```
-### 4. Build and Execute Hermetic Tests
+### 4. Build and Execute Tests
Compiles and executes test executables in parallel with MC/DC instrumentation
enabled:
```bash
-ninja -k 0 -C build-cov-mcdc libc-hermetic-tests
+ninja -k 0 -C build-cov-mcdc libc-tests
```
### 5. Merge Profile Counters
diff --git a/libc/docs/full_cross_build.md b/libc/docs/full_cross_build.md
index 3506609521b2a6..4783b203184eac 100644
--- a/libc/docs/full_cross_build.md
+++ b/libc/docs/full_cross_build.md
@@ -217,11 +217,11 @@ You can then build the libc using:
ninja -C build libc
```
-To run the tests for the cross-compiled libc, you must use the hermetic test
-suite, which is entirely self-hosted.
+To run the tests for the cross-compiled libc, you can run `libc-tests`,
+which executes self-hosted tests in full-build mode:
```sh
-ninja -C build libc-hermetic-tests
+ninja -C build libc-tests
```
:::{note}
diff --git a/libc/docs/gpu/testing.rst b/libc/docs/gpu/testing.rst
index c34467346b7987..2e5a87dfea23ac 100644
--- a/libc/docs/gpu/testing.rst
+++ b/libc/docs/gpu/testing.rst
@@ -108,11 +108,11 @@ The CMake target depends on how the library was built.
$> ninja check-libc
- #. Hermetic tests - You can run hermetic with tests the command:
+ #. Libc tests - You can run libc tests with the command:
.. code-block:: sh
- $> ninja libc-hermetic-tests
+ $> ninja libc-tests
#. Integration tests - You can run integration tests by the command:
diff --git a/libc/test/CMakeLists.txt b/libc/test/CMakeLists.txt
index dd8db9a5166c0d..19fb6ea4a369ff 100644
--- a/libc/test/CMakeLists.txt
+++ b/libc/test/CMakeLists.txt
@@ -1,14 +1,11 @@
-add_custom_target(libc-unit-tests)
-add_custom_target(libc-hermetic-tests)
+add_custom_target(libc-tests)
add_custom_target(exhaustive-check-libc)
add_custom_target(libc-long-running-tests)
# Build-only targets for lit (don't run tests, just build executables)
-add_custom_target(libc-unit-tests-build)
-add_custom_target(libc-hermetic-tests-build)
+add_custom_target(libc-tests-build)
add_custom_target(libc-integration-tests-build)
-add_custom_target(libc_include_tests-build)
# Configure the site config file for lit
configure_lit_site_cfg(
@@ -37,8 +34,7 @@ if(TARGET check-hdrgen)
add_dependencies(check-libc check-hdrgen)
endif()
-add_dependencies(check-libc-build libc-unit-tests-build)
-add_dependencies(check-libc-build libc-hermetic-tests-build)
+add_dependencies(check-libc-build libc-tests-build)
add_subdirectory(UnitTest)
diff --git a/libc/test/include/CMakeLists.txt b/libc/test/include/CMakeLists.txt
index b2fb07f9c3def0..a63e1638418467 100644
--- a/libc/test/include/CMakeLists.txt
+++ b/libc/test/include/CMakeLists.txt
@@ -1,5 +1,4 @@
-add_custom_target(libc_include_tests)
-add_dependencies(check-libc libc_include_tests-build)
+add_libc_testsuite(libc_include_tests)
add_libc_test(
alloca_test
diff --git a/libc/test/shared/CMakeLists.txt b/libc/test/shared/CMakeLists.txt
index 74eda7cdaf065e..6a4a0b68b2c926 100644
--- a/libc/test/shared/CMakeLists.txt
+++ b/libc/test/shared/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_custom_target(libc-shared-tests)
+add_libc_testsuite(libc-shared-tests)
# Shared math tests include the entire math library headers into a single file
# so it might take some time to compile the tests. We do have dedicated
diff --git a/libc/test/src/CMakeLists.txt b/libc/test/src/CMakeLists.txt
index b4120fa5fe268b..b3ca7a0d366374 100644
--- a/libc/test/src/CMakeLists.txt
+++ b/libc/test/src/CMakeLists.txt
@@ -1,80 +1,3 @@
-function(add_fp_unittest name)
- cmake_parse_arguments(
- "MATH_UNITTEST"
- "NEED_MPFR;NEED_MPFR_F80;NEED_MPFR_F128;NEED_MPC;FULL_BUILD_ONLY;OVERLAY_BUILD_ONLY" # Optional arguments
- "" # Single value arguments
- "LINK_LIBRARIES;DEPENDS" # Multi-value arguments
- ${ARGN}
- )
-
- if(MATH_UNITTEST_NEED_MPC)
- set(MATH_UNITTEST_NEED_MPFR TRUE)
- if(NOT LIBC_TESTS_CAN_USE_MPC)
- message(VERBOSE "Complex test ${name} will be skipped as MPC library is not available.")
- return()
- endif()
- list(APPEND MATH_UNITTEST_LINK_LIBRARIES libcMPCWrapper)
- endif()
-
- if(MATH_UNITTEST_NEED_MPFR_F80)
- set(MATH_UNITTEST_NEED_MPFR TRUE)
- if(NOT LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
- message(VERBOSE "Math test ${name} will be skipped as float80 support in MPFR is not available.")
- return()
- endif()
- endif()
-
- # TODO: To be removed when we find a workaround to run MPFR tests for
- # emulated type where compiler doesn't support the native float128
- # TODO: Check mpfr_buildopt_float128_p() returns non-zero.
- if(MATH_UNITTEST_NEED_MPFR_F128)
- set(MATH_UNITTEST_NEED_MPFR TRUE)
- if(NOT LIBC_TYPES_HAS_NATIVE_FLOAT128)
- message(VERBOSE "Math test ${name} will be skipped as native float128 support in MPFR is not available.")
- return()
- endif()
- endif()
-
- if(MATH_UNITTEST_NEED_MPFR)
- if(NOT LIBC_TESTS_CAN_USE_MPFR)
- message(VERBOSE "Math test ${name} will be skipped as MPFR library is not available.")
- return()
- endif()
- endif()
-
- if(MATH_UNITTEST_FULL_BUILD_ONLY)
- set(test_type FULL_BUILD_ONLY)
- elseif(MATH_UNITTEST_OVERLAY_BUILD_ONLY)
- set(test_type OVERLAY_BUILD_ONLY)
- endif()
- if(MATH_UNITTEST_NEED_MPFR)
- if(MATH_UNITTEST_FULL_BUILD_ONLY)
- message(FATAL_ERROR "Full-build math test cannot require MPFR.")
- endif()
- set(test_type OVERLAY_BUILD_ONLY)
- list(APPEND MATH_UNITTEST_LINK_LIBRARIES libcMPFRWrapper -lmpfr -lgmp)
- if(NOT(LIBC_TARGET_OS_IS_DARWIN) AND NOT(LIBC_TARGET_OS_IS_FREEBSD))
- # macOS/FreeBSD does not have libatomic.
- list(APPEND MATH_UNITTEST_LINK_LIBRARIES -latomic)
- endif()
- endif()
-
- set(deps libc.hdr.math_macros libc.test.UnitTest.FPTestHelpers)
- if(MATH_UNITTEST_DEPENDS)
- list(APPEND deps ${MATH_UNITTEST_DEPENDS})
- endif()
-
- add_libc_test(
- ${name}
- ${test_type}
- LINK_LIBRARIES "${MATH_UNITTEST_LINK_LIBRARIES}"
- "${MATH_UNITTEST_UNPARSED_ARGUMENTS}"
- DEPENDS
- libc.hdr.stdint_proxy
- "${deps}"
- )
-endfunction()
-
add_subdirectory(__support)
add_subdirectory(arpa)
add_subdirectory(complex)
diff --git a/libc/test/src/__support/CMakeLists.txt b/libc/test/src/__support/CMakeLists.txt
index 765eec6b421780..6f97334657158a 100644
--- a/libc/test/src/__support/CMakeLists.txt
+++ b/libc/test/src/__support/CMakeLists.txt
@@ -308,8 +308,9 @@ if(LIBC_TARGET_OS_IS_BAREMETAL AND
minimal_external_crt1_for_test.cpp
)
- add_libc_hermetic(
+ add_libc_test(
external_startup_link_test
+ FULL_BUILD_ONLY
NO_RUN_POSTBUILD
STARTUP
.minimal_external_crt1_for_test
diff --git a/libc/test/src/math/CMakeLists.txt b/libc/test/src/math/CMakeLists.txt
index bb3e568c2d4c9f..0478477eead1d8 100644
--- a/libc/test/src/math/CMakeLists.txt
+++ b/libc/test/src/math/CMakeLists.txt
@@ -1,4 +1,4 @@
-add_custom_target(libc-math-unittests)
+add_libc_testsuite(libc-math-unittests)
add_fp_unittest(
cosf_test
@@ -3926,6 +3926,9 @@ add_fp_unittest(
add_subdirectory(smoke)
+add_custom_target(libc-math-all-tests)
+add_dependencies(libc-math-all-tests libc-math-smoke-tests libc-math-unittests)
+
if(NOT LLVM_LIBC_FULL_BUILD)
add_subdirectory(exhaustive)
add_subdirectory(performance_testing)
diff --git a/libc/test/src/math/smoke/CMakeLists.txt b/libc/test/src/math/smoke/CMakeLists.txt
index a1f85df34e4c7d..661027844a3711 100644
--- a/libc/test/src/math/smoke/CMakeLists.txt
+++ b/libc/test/src/math/smoke/CMakeLists.txt
@@ -1,5 +1,4 @@
-add_custom_target(libc-math-smoke-tests)
-add_dependencies(libc-math-unittests libc-math-smoke-tests)
+add_libc_testsuite(libc-math-smoke-tests)
add_fp_unittest(
cosf_test
diff --git a/libc/utils/MPCWrapper/CMakeLists.txt b/libc/utils/MPCWrapper/CMakeLists.txt
index d06ec2b3664a53..321e72bbcce547 100644
--- a/libc/utils/MPCWrapper/CMakeLists.txt
+++ b/libc/utils/MPCWrapper/CMakeLists.txt
@@ -1,15 +1,15 @@
if(LIBC_TESTS_CAN_USE_MPC)
- add_library(libcMPCWrapper STATIC
+ add_library(libc.utils.MPCWrapper STATIC
MPCUtils.cpp
MPCUtils.h
mpc_inc.h
)
_get_common_test_compile_options(compile_options "" "")
list(REMOVE_ITEM compile_options "-ffreestanding")
- target_compile_options(libcMPCWrapper PRIVATE -O3 ${compile_options})
+ target_compile_options(libc.utils.MPCWrapper PRIVATE -O3 ${compile_options})
add_dependencies(
- libcMPCWrapper
- libcMPCommon
+ libc.utils.MPCWrapper
+ libc.utils.MPCommon
libc.hdr.stdint_proxy
libc.src.__support.CPP.array
libc.src.__support.CPP.string
@@ -21,15 +21,15 @@ if(LIBC_TESTS_CAN_USE_MPC)
libc.test.UnitTest.LibcTest
)
if(EXISTS ${LLVM_LIBC_MPFR_INSTALL_PATH})
- target_include_directories(libcMPCWrapper PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/include)
- target_link_directories(libcMPCWrapper PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/lib)
+ target_include_directories(libc.utils.MPCWrapper PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/include)
+ target_link_directories(libc.utils.MPCWrapper PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/lib)
endif()
if(EXISTS ${LIBC_MPC_INSTALL_PATH})
- target_include_directories(libcMPCWrapper PUBLIC ${LIBC_MPC_INSTALL_PATH}/include)
- target_link_directories(libcMPCWrapper PUBLIC ${LIBC_MPC_INSTALL_PATH}/lib)
+ target_include_directories(libc.utils.MPCWrapper PUBLIC ${LIBC_MPC_INSTALL_PATH}/include)
+ target_link_directories(libc.utils.MPCWrapper PUBLIC ${LIBC_MPC_INSTALL_PATH}/lib)
endif()
- target_include_directories(libcMPCWrapper PUBLIC ${LIBC_SOURCE_DIR})
- target_link_libraries(libcMPCWrapper PUBLIC libcMPCommon mpc)
+ target_include_directories(libc.utils.MPCWrapper PUBLIC ${LIBC_SOURCE_DIR})
+ target_link_libraries(libc.utils.MPCWrapper PUBLIC libc.utils.MPCommon mpc)
elseif(NOT LIBC_TARGET_OS_IS_GPU AND NOT LLVM_LIBC_FULL_BUILD)
message(WARNING "Math tests using MPC will be skipped.")
endif()
diff --git a/libc/utils/MPFRWrapper/CMakeLists.txt b/libc/utils/MPFRWrapper/CMakeLists.txt
index 53ad5ef4aa48cd..f4bc87c822a002 100644
--- a/libc/utils/MPFRWrapper/CMakeLists.txt
+++ b/libc/utils/MPFRWrapper/CMakeLists.txt
@@ -1,5 +1,5 @@
if(LIBC_TESTS_CAN_USE_MPFR OR LIBC_TESTS_CAN_USE_MPC)
- add_library(libcMPCommon STATIC
+ add_library(libc.utils.MPCommon STATIC
MPCommon.cpp
MPCommon.h
mpfr_inc.h
@@ -7,9 +7,9 @@ if(LIBC_TESTS_CAN_USE_MPFR OR LIBC_TESTS_CAN_USE_MPC)
_get_common_test_compile_options(compile_options "" "")
# mpfr/gmp headers do not work with -ffreestanding flag.
list(REMOVE_ITEM compile_options "-ffreestanding")
- target_compile_options(libcMPCommon PRIVATE -O3 ${compile_options})
+ target_compile_options(libc.utils.MPCommon PRIVATE -O3 ${compile_options})
add_dependencies(
- libcMPCommon
+ libc.utils.MPCommon
libc.hdr.stdint_proxy
libc.src.__support.CPP.string
libc.src.__support.CPP.string_view
@@ -21,27 +21,30 @@ if(LIBC_TESTS_CAN_USE_MPFR OR LIBC_TESTS_CAN_USE_MPC)
libc.test.UnitTest.FPTestHelpers
)
if(EXISTS ${LLVM_LIBC_MPFR_INSTALL_PATH})
- target_include_directories(libcMPCommon PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/include)
- target_link_directories(libcMPCommon PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/lib)
+ target_include_directories(libc.utils.MPCommon PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/include)
+ target_link_directories(libc.utils.MPCommon PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/lib)
+ endif()
+ target_include_directories(libc.utils.MPCommon PUBLIC ${LIBC_SOURCE_DIR})
+ target_link_libraries(libc.utils.MPCommon PUBLIC mpfr gmp)
+ if(NOT LIBC_TARGET_OS_IS_DARWIN AND NOT LIBC_TARGET_OS_IS_FREEBSD)
+ target_link_libraries(libc.utils.MPCommon PUBLIC -latomic)
endif()
- target_include_directories(libcMPCommon PUBLIC ${LIBC_SOURCE_DIR})
- target_link_libraries(libcMPCommon PUBLIC mpfr gmp)
elseif(NOT LIBC_TARGET_OS_IS_GPU AND NOT LLVM_LIBC_FULL_BUILD)
message(WARNING "Math tests using MPFR will be skipped.")
endif()
if(LIBC_TESTS_CAN_USE_MPFR)
- add_library(libcMPFRWrapper STATIC
+ add_library(libc.utils.MPFRWrapper STATIC
MPFRUtils.cpp
MPFRUtils.h
)
_get_common_test_compile_options(compile_options "" "")
# mpfr/gmp headers do not work with -ffreestanding flag.
list(REMOVE_ITEM compile_options "-ffreestanding")
- target_compile_options(libcMPFRWrapper PRIVATE ${libc_opt_high_flag} ${compile_options})
+ target_compile_options(libc.utils.MPFRWrapper PRIVATE ${libc_opt_high_flag} ${compile_options})
add_dependencies(
- libcMPFRWrapper
- libcMPCommon
+ libc.utils.MPFRWrapper
+ libc.utils.MPCommon
libc.hdr.stdint_proxy
libc.src.__support.CPP.array
libc.src.__support.CPP.stringstream
@@ -52,11 +55,11 @@ if(LIBC_TESTS_CAN_USE_MPFR)
libc.test.UnitTest.LibcTest
)
if(EXISTS ${LLVM_LIBC_MPFR_INSTALL_PATH})
- target_include_directories(libcMPFRWrapper PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/include)
- target_link_directories(libcMPFRWrapper PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/lib)
+ target_include_directories(libc.utils.MPFRWrapper PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/include)
+ target_link_directories(libc.utils.MPFRWrapper PUBLIC ${LLVM_LIBC_MPFR_INSTALL_PATH}/lib)
endif()
- target_include_directories(libcMPFRWrapper PUBLIC ${LIBC_SOURCE_DIR})
- target_link_libraries(libcMPFRWrapper PUBLIC libcMPCommon)
+ target_include_directories(libc.utils.MPFRWrapper PUBLIC ${LIBC_SOURCE_DIR})
+ target_link_libraries(libc.utils.MPFRWrapper PUBLIC libc.utils.MPCommon)
elseif(NOT LIBC_TARGET_OS_IS_GPU AND NOT LLVM_LIBC_FULL_BUILD)
message(WARNING "Math tests using MPFR will be skipped.")
endif()
>From 34bb92f1eded272b93f62d4e34dc5c4bb7439113 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Mon, 19 Oct 2026 17:55:08 +0000
Subject: [PATCH 2/3] Do not pass TEST_COMPILE_OPTIONS to linker in overlay
tests.
---
libc/cmake/modules/LLVMLibCTestRules.cmake | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index e6736153256fb2..b02c45f69a4578 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -782,8 +782,7 @@ function(create_libc_test fq_target_name)
_get_common_test_compile_options(compile_options "${TEST_C_TEST}"
"${TEST_FLAGS}")
endif()
- list(APPEND compile_options ${TEST_COMPILE_OPTIONS})
- target_compile_options(${fq_build_target_name} PRIVATE ${compile_options})
+ target_compile_options(${fq_build_target_name} PRIVATE ${compile_options} ${TEST_COMPILE_OPTIONS})
if(NOT TEST_CXX_STANDARD)
set(TEST_CXX_STANDARD ${CMAKE_CXX_STANDARD})
>From 6dcb48f4cff7136c4e2d4dbfda6fe94e1de27c2f Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue.h at gmail.com>
Date: Tue, 20 Oct 2026 22:33:43 +0000
Subject: [PATCH 3/3] [libc][cmake] Move FP/MPFR/MPC handling into
create_libc_test and simplify suite checks
---
libc/cmake/modules/LLVMLibCTestRules.cmake | 184 +++++++--------------
1 file changed, 64 insertions(+), 120 deletions(-)
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index b02c45f69a4578..bc3adc79644ec9 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -324,19 +324,10 @@ function(add_libc_testsuite suite_name)
add_custom_target(${suite_name})
endif()
- set(created_build_target FALSE)
if(NOT TARGET ${suite_name}-build)
add_custom_target(${suite_name}-build)
- set(created_build_target TRUE)
- endif()
-
- if(created_build_target)
- if(TARGET libc-tests)
- add_dependencies(libc-tests ${suite_name})
- endif()
- if(TARGET libc-tests-build)
- add_dependencies(libc-tests-build ${suite_name}-build)
- endif()
+ add_dependencies(libc-tests ${suite_name})
+ add_dependencies(libc-tests-build ${suite_name}-build)
endif()
endfunction()
@@ -398,7 +389,7 @@ endfunction()
# Helper function for create_libc_test: collects fully qualified dependencies
# for a test target, including base test framework libraries, hermetic runtime
# entrypoints, subprocess support, and coverage dependencies.
-function(_get_libc_test_dependencies output_var user_depends startup_target_dep is_c_test)
+function(_get_libc_test_dependencies output_var user_depends startup_target_dep is_c_test is_fp_test)
get_fq_deps_list(fq_deps_list ${user_depends})
list(APPEND fq_deps_list
libc.src.__support.StringUtil.error_to_string
@@ -410,6 +401,13 @@ function(_get_libc_test_dependencies output_var user_depends startup_target_dep
else()
list(APPEND fq_deps_list libc.test.UnitTest.LibcDeathTestExecutors)
endif()
+ if(is_fp_test)
+ list(APPEND fq_deps_list
+ libc.hdr.math_macros
+ libc.hdr.stdint_proxy
+ libc.test.UnitTest.FPTestHelpers
+ )
+ endif()
if(LLVM_LIBC_FULL_BUILD)
list(APPEND fq_deps_list
@@ -464,30 +462,6 @@ function(_get_libc_test_dependencies output_var user_depends startup_target_dep
set(${output_var} ${fq_deps_list} PARENT_SCOPE)
endfunction()
-# Helper function for create_libc_test: inspects dependencies and extracts
-# standard CMake library targets (STATIC, SHARED, INTERFACE) that do not have
-# a custom TARGET_TYPE (e.g. libc.utils.MPFRWrapper, libc.utils.MPCWrapper).
-function(_get_libc_test_link_libraries output_var fq_deps_list)
- set(link_libs "")
- foreach(dep IN LISTS fq_deps_list)
- if(TARGET ${dep})
- get_target_property(aliased_target ${dep} "ALIASED_TARGET")
- if(aliased_target)
- set(dep ${aliased_target})
- endif()
- get_target_property(dep_type ${dep} "TARGET_TYPE")
- get_target_property(cmake_type ${dep} TYPE)
- if(NOT dep_type AND cmake_type MATCHES ".*_LIBRARY")
- list(APPEND link_libs ${dep})
- endif()
- endif()
- endforeach()
- if(link_libs)
- list(REMOVE_DUPLICATES link_libs)
- endif()
- set(${output_var} ${link_libs} PARENT_SCOPE)
-endfunction()
-
# Helper function for create_libc_test: configures linking for full-build hermetic
# tests by creating the static .__libc__ archive, setting hermetic/GPU link
# options, and wiring link libraries and compiler runtime.
@@ -661,16 +635,10 @@ function(_register_libc_test_with_suite fq_target_name fq_build_target_name suit
if(suite)
add_libc_testsuite(${suite})
add_dependencies(${suite} ${fq_target_name})
- if(TARGET ${suite}-build)
- add_dependencies(${suite}-build ${fq_build_target_name})
- endif()
+ add_dependencies(${suite}-build ${fq_build_target_name})
else()
- if(TARGET libc-tests)
- add_dependencies(libc-tests ${fq_target_name})
- endif()
- if(TARGET libc-tests-build)
- add_dependencies(libc-tests-build ${fq_build_target_name})
- endif()
+ add_dependencies(libc-tests ${fq_target_name})
+ add_dependencies(libc-tests-build ${fq_build_target_name})
endif()
endfunction()
@@ -682,7 +650,47 @@ function(create_libc_test fq_target_name)
llvm_libc_parse_arguments(TEST ${ARGN})
- # 1. Validate build mode and target platform
+ # 1. Validate build mode, target platform, and external library requirements
+ if(TEST_NEED_MPC)
+ set(TEST_NEED_MPFR TRUE)
+ if(NOT LIBC_TESTS_CAN_USE_MPC)
+ message(VERBOSE "Complex test ${fq_target_name} will be skipped as MPC library is not available.")
+ return()
+ endif()
+ list(APPEND TEST_LINK_LIBRARIES libc.utils.MPCWrapper)
+ endif()
+
+ if(TEST_NEED_MPFR_F80)
+ set(TEST_NEED_MPFR TRUE)
+ if(NOT LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
+ message(VERBOSE "Math test ${fq_target_name} will be skipped as float80 support in MPFR is not available.")
+ return()
+ endif()
+ endif()
+
+ # TODO: To be removed when we find a workaround to run MPFR tests for
+ # emulated type where compiler doesn't support the native float128
+ # TODO: Check mpfr_buildopt_float128_p() returns non-zero.
+ if(TEST_NEED_MPFR_F128)
+ set(TEST_NEED_MPFR TRUE)
+ if(NOT LIBC_TYPES_HAS_NATIVE_FLOAT128)
+ message(VERBOSE "Math test ${fq_target_name} will be skipped as native float128 support in MPFR is not available.")
+ return()
+ endif()
+ endif()
+
+ if(TEST_NEED_MPFR)
+ if(TEST_FULL_BUILD_ONLY)
+ message(FATAL_ERROR "Full-build test cannot require MPFR.")
+ endif()
+ if(NOT LIBC_TESTS_CAN_USE_MPFR)
+ message(VERBOSE "Test ${fq_target_name} will be skipped as MPFR library is not available.")
+ return()
+ endif()
+ set(TEST_OVERLAY_ONLY TRUE)
+ list(APPEND TEST_LINK_LIBRARIES libc.utils.MPFRWrapper)
+ endif()
+
if(LLVM_LIBC_FULL_BUILD AND TEST_OVERLAY_ONLY)
return()
endif()
@@ -727,7 +735,13 @@ function(create_libc_test fq_target_name)
endif()
# 2. Resolve dependencies and link objects
- _get_libc_test_dependencies(fq_deps_list "${TEST_DEPENDS}" "${startup_target_dep}" "${TEST_C_TEST}")
+ _get_libc_test_dependencies(
+ fq_deps_list
+ "${TEST_DEPENDS}"
+ "${startup_target_dep}"
+ "${TEST_C_TEST}"
+ "${TEST_FP_TEST}"
+ )
if(SHOW_INTERMEDIATE_OBJECTS)
message(STATUS "Adding test ${fq_target_name}")
@@ -749,10 +763,6 @@ function(create_libc_test fq_target_name)
return()
endif()
list(REMOVE_DUPLICATES link_object_files)
-
- # Collect standard library targets from dependencies that do not provide raw object files.
- _get_libc_test_link_libraries(dep_link_libraries "${fq_deps_list}")
- list(APPEND TEST_LINK_LIBRARIES ${dep_link_libraries})
if(TEST_LINK_LIBRARIES)
list(REMOVE_DUPLICATES TEST_LINK_LIBRARIES)
endif()
@@ -838,14 +848,6 @@ function(create_libc_test fq_target_name)
endif()
endfunction()
-function(_add_libc_test target_name)
- add_target_with_flags(
- ${target_name}
- CREATE_TARGET create_libc_test
- ${ARGN}
- )
-endfunction()
-
# Rule to add a fuzzer test.
# Usage
@@ -1152,68 +1154,10 @@ endfunction()
# NEED_MPFR / NEED_MPFR_F80 / NEED_MPFR_F128: link against MPFR; tests requiring MPFR run only in overlay mode.
# NEED_MPC: link against MPC and MPFR; tests requiring MPC run only in overlay mode.
function(add_libc_test test_name)
- llvm_libc_parse_arguments(LIBC_TEST ${ARGN})
-
- if(LIBC_TEST_NEED_MPC)
- set(LIBC_TEST_NEED_MPFR TRUE)
- if(NOT LIBC_TESTS_CAN_USE_MPC)
- message(VERBOSE "Complex test ${test_name} will be skipped as MPC library is not available.")
- return()
- endif()
- list(APPEND LIBC_TEST_DEPENDS libc.utils.MPCWrapper)
- endif()
-
- if(LIBC_TEST_NEED_MPFR_F80)
- set(LIBC_TEST_NEED_MPFR TRUE)
- if(NOT LIBC_TYPES_LONG_DOUBLE_IS_X86_FLOAT80)
- message(VERBOSE "Math test ${test_name} will be skipped as float80 support in MPFR is not available.")
- return()
- endif()
- endif()
-
- # TODO: To be removed when we find a workaround to run MPFR tests for
- # emulated type where compiler doesn't support the native float128
- # TODO: Check mpfr_buildopt_float128_p() returns non-zero.
- if(LIBC_TEST_NEED_MPFR_F128)
- set(LIBC_TEST_NEED_MPFR TRUE)
- if(NOT LIBC_TYPES_HAS_NATIVE_FLOAT128)
- message(VERBOSE "Math test ${test_name} will be skipped as native float128 support in MPFR is not available.")
- return()
- endif()
- endif()
-
- if(LIBC_TEST_NEED_MPFR)
- if(LIBC_TEST_FULL_BUILD_ONLY)
- message(FATAL_ERROR "Full-build test cannot require MPFR.")
- endif()
- if(NOT LIBC_TESTS_CAN_USE_MPFR)
- message(VERBOSE "Test ${test_name} will be skipped as MPFR library is not available.")
- return()
- endif()
- set(LIBC_TEST_OVERLAY_ONLY TRUE)
- list(APPEND LIBC_TEST_DEPENDS libc.utils.MPFRWrapper)
- endif()
-
- if(LIBC_TEST_FP_TEST)
- list(APPEND LIBC_TEST_DEPENDS
- libc.hdr.math_macros
- libc.test.UnitTest.FPTestHelpers
- libc.hdr.stdint_proxy
- )
- endif()
-
- if(LLVM_LIBC_FULL_BUILD AND LIBC_TEST_OVERLAY_ONLY)
- return()
- endif()
- if(NOT LLVM_LIBC_FULL_BUILD AND LIBC_TEST_FULL_BUILD_ONLY)
- return()
- endif()
-
- forward_arguments(LIBC_TEST forwarded_args)
- _add_libc_test(
+ add_target_with_flags(
${test_name}
- ${forwarded_args}
- ${LIBC_TEST_UNPARSED_ARGUMENTS}
+ CREATE_TARGET create_libc_test
+ ${ARGN}
)
endfunction()
More information about the libc-commits
mailing list