[libc-commits] [libc] [libc] Use `LIBC_COPT_PUBLIC_PACKAGING` for hermetic and integration tests. (PR #79319)
via libc-commits
libc-commits at lists.llvm.org
Sat Jan 27 09:05:59 PST 2024
https://github.com/lntue updated https://github.com/llvm/llvm-project/pull/79319
>From e06588295fb945d64a571f95de5b9b8fad4f6aa1 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Fri, 26 Jan 2024 09:44:58 -0500
Subject: [PATCH 1/8] [libc] Use LIBC_COPT_PUBLIC_PACKAGING for hermetic and
integration tests.
---
libc/cmake/modules/LLVMLibCTestRules.cmake | 112 +++++++++++++++---
libc/test/integration/startup/CMakeLists.txt | 6 +-
.../math/differential_testing/CMakeLists.txt | 5 +-
3 files changed, 107 insertions(+), 16 deletions(-)
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index 0d0a47b33aaeba..d07cec047370ee 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -5,6 +5,7 @@
# Usage:
# get_object_files_for_test(<result var>
# <skipped_entrypoints_var>
+# INTERNAL <internal>
# <target0> [<target1> ...])
#
# The list of object files is collected in <result_var>.
@@ -12,11 +13,24 @@
# set to a true value.
# targetN is either an "add_entrypoint_target" target or an
# "add_object_library" target.
+# If INTERNAL is TRUE, then we collect `target.__internal__` for entry points.
function(get_object_files_for_test result skipped_entrypoints_list)
+ cmake_parse_arguments(
+ GET_OBJ
+ "" # No optional
+ "INTERNAL" # Single-value
+ "" # No multi-value
+ ${ARGN}
+ )
set(object_files "")
set(skipped_list "")
set(checked_list "")
- set(unchecked_list "${ARGN}")
+ set(unchecked_list "${GET_OBJ_UNPARSED_ARGUMENTS}")
+
+ set(check_obj_for_tests "CHECK_OBJ_FOR_TESTS_${GET_OBJ_INTERNAL}")
+ set(object_files_for_tests "OBJECT_FILES_FOR_TESTS_${GET_OBJ_INTERNAL}")
+ set(skipped_list_for_tests "SKIPPED_LIST_FOR_TESTS_${GET_OBJ_INTERNAL}")
+
list(REMOVE_DUPLICATES unchecked_list)
foreach(dep IN LISTS unchecked_list)
@@ -37,19 +51,23 @@ function(get_object_files_for_test result skipped_entrypoints_list)
continue()
endif()
- get_target_property(dep_checked ${dep} "CHECK_OBJ_FOR_TESTS")
+ get_target_property(dep_checked ${dep} ${check_obj_for_tests})
if(dep_checked)
# Target full dependency has already been checked. Just use the results.
- get_target_property(dep_obj ${dep} "OBJECT_FILES_FOR_TESTS")
- get_target_property(dep_skip ${dep} "SKIPPED_LIST_FOR_TESTS")
+ get_target_property(dep_obj ${dep} ${object_files_for_tests})
+ get_target_property(dep_skip ${dep} ${skipped_list_for_tests})
else()
# Target full dependency hasn't been checked. Recursively check its DEPS.
set(dep_obj "${dep}")
set(dep_skip "")
get_target_property(indirect_deps ${dep} "DEPS")
- get_object_files_for_test(dep_obj dep_skip ${indirect_deps})
+ get_object_files_for_test(
+ dep_obj dep_skip
+ INTERNAL ${GET_OBJ_INTERNAL}
+ ${indirect_deps}
+ )
if(${dep_type} STREQUAL ${OBJECT_LIBRARY_TARGET_TYPE})
get_target_property(dep_object_files ${dep} "OBJECT_FILES")
@@ -62,7 +80,11 @@ function(get_object_files_for_test result skipped_entrypoints_list)
list(APPEND dep_skip ${dep})
list(REMOVE_ITEM dep_obj ${dep})
endif()
- get_target_property(object_file_raw ${dep} "OBJECT_FILE_RAW")
+ if(${GET_OBJ_INTERNAL})
+ get_target_property(object_file_raw ${dep} "OBJECT_FILE_RAW")
+ else()
+ get_target_property(object_file_raw ${dep} "OBJECT_FILE")
+ endif()
if(object_file_raw)
list(APPEND dep_obj ${object_file_raw})
endif()
@@ -73,9 +95,9 @@ function(get_object_files_for_test result skipped_entrypoints_list)
endif()
set_target_properties(${dep} PROPERTIES
- OBJECT_FILES_FOR_TESTS "${dep_obj}"
- SKIPPED_LIST_FOR_TESTS "${dep_skip}"
- CHECK_OBJ_FOR_TESTS "YES"
+ "${object_files_for_tests}" "${dep_obj}"
+ "${skipped_list_for_tests}" "${dep_skip}"
+ "${check_obj_for_tests}" "YES"
)
endif()
@@ -140,7 +162,10 @@ function(create_libc_unittest fq_target_name)
endif()
get_object_files_for_test(
- link_object_files skipped_entrypoints_list ${fq_deps_list})
+ link_object_files skipped_entrypoints_list
+ INTERNAL TRUE
+ ${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.
@@ -167,6 +192,15 @@ function(create_libc_unittest fq_target_name)
return()
endif()
+ 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 " ${fq_target_name} depends on ${dep}")
+ endforeach()
+ endif()
+ endif()
+
if(LIBC_UNITTEST_NO_RUN_POSTBUILD)
set(fq_build_target_name ${fq_target_name})
else()
@@ -389,7 +423,10 @@ function(add_libc_fuzzer target_name)
get_fq_target_name(${target_name} fq_target_name)
get_fq_deps_list(fq_deps_list ${LIBC_FUZZER_DEPENDS})
get_object_files_for_test(
- link_object_files skipped_entrypoints_list ${fq_deps_list})
+ link_object_files skipped_entrypoints_list
+ INTERNAL TRUE
+ ${fq_deps_list}
+ )
if(skipped_entrypoints_list)
if(LIBC_CMAKE_VERBOSE_LOGGING)
set(msg "Skipping fuzzer target ${fq_target_name} as it has missing deps: "
@@ -493,6 +530,16 @@ function(add_integration_test test_name)
get_fq_target_name(${test_name}.libc fq_libc_target_name)
get_fq_deps_list(fq_deps_list ${INTEGRATION_TEST_DEPENDS})
+
+ if(SHOW_INTERMEDIATE_OBJECTS)
+ message(STATUS "Adding integration test ${fq_target_name}")
+ if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
+ foreach(dep IN LISTS fq_deps_list)
+ message(STATUS " ${fq_target_name} depends on ${dep}")
+ endforeach()
+ endif()
+ endif()
+
list(APPEND fq_deps_list
# All integration tests use the operating system's startup object with the
# integration test object and need to inherit the same dependencies.
@@ -500,6 +547,7 @@ function(add_integration_test test_name)
libc.test.IntegrationTest.test
# We always add the memory functions objects. This is because the
# compiler's codegen can emit calls to the C memory functions.
+ libc.src.stdlib.atexit
libc.src.string.bcmp
libc.src.string.bzero
libc.src.string.memcmp
@@ -519,7 +567,20 @@ function(add_integration_test test_name)
# 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})
+ link_object_files skipped_entrypoints_list
+ INTERNAL FALSE
+ ${fq_deps_list}
+ )
+
+ if(SHOW_INTERMEDIATE_OBJECTS)
+ message(STATUS "Get objects for test ${fq_target_name}")
+ if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
+ foreach(dep IN LISTS link_object_files)
+ message(STATUS " ${fq_target_name} need object ${dep}")
+ endforeach()
+ endif()
+ endif()
+
if(skipped_entrypoints_list)
if(LIBC_CMAKE_VERBOSE_LOGGING)
set(msg "Skipping integration test ${fq_target_name} as it has missing deps: "
@@ -672,6 +733,16 @@ function(add_libc_hermetic_test test_name)
get_fq_target_name(${test_name}.libc fq_libc_target_name)
get_fq_deps_list(fq_deps_list ${HERMETIC_TEST_DEPENDS})
+
+ if(SHOW_INTERMEDIATE_OBJECTS)
+ message(STATUS "Adding hermetic test ${fq_target_name}")
+ if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
+ foreach(dep IN LISTS fq_deps_list)
+ message(STATUS " ${fq_target_name} depends on ${dep}")
+ endforeach()
+ endif()
+ endif()
+
list(APPEND fq_deps_list
# Hermetic tests use the platform's startup object. So, their deps also
# have to be collected.
@@ -703,8 +774,21 @@ function(add_libc_hermetic_test test_name)
# 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)
+ link_object_files skipped_entrypoints_list
+ INTERNAL FALSE
+ ${fq_deps_list}
+ )
+
+ if(SHOW_INTERMEDIATE_OBJECTS)
+ message(STATUS "Get objects for test ${fq_target_name}")
+ if(${SHOW_INTERMEDIATE_OBJECTS} STREQUAL "DEPS")
+ foreach(dep IN LISTS link_object_files)
+ message(STATUS " ${fq_target_name} need object ${dep}")
+ endforeach()
+ endif()
+ endif()
+
+ if(skipped_entrypoints_list)
set(msg "Skipping hermetic test ${fq_target_name} as it has missing deps: "
"${skipped_entrypoints_list}.")
message(STATUS ${msg})
diff --git a/libc/test/integration/startup/CMakeLists.txt b/libc/test/integration/startup/CMakeLists.txt
index fb5d6bc787cc26..154a6d8a6aa475 100644
--- a/libc/test/integration/startup/CMakeLists.txt
+++ b/libc/test/integration/startup/CMakeLists.txt
@@ -38,7 +38,11 @@ function(add_startup_test target_name)
if(ADD_STARTUP_TEST_DEPENDS)
get_fq_deps_list(fq_deps_list ${ADD_STARTUP_TEST_DEPENDS})
add_dependencies(${fq_target_name} ${fq_deps_list})
- get_object_files_for_test(link_object_files has_skipped_entrypoint_list ${fq_deps_list})
+ get_object_files_for_test(
+ link_object_files has_skipped_entrypoint_list
+ INTERNAL TRUE
+ ${fq_deps_list}
+ )
target_link_libraries(${fq_target_name} ${link_object_files})
endif()
diff --git a/libc/test/src/math/differential_testing/CMakeLists.txt b/libc/test/src/math/differential_testing/CMakeLists.txt
index 72bc2f8fb16aaa..466c53287a5b16 100644
--- a/libc/test/src/math/differential_testing/CMakeLists.txt
+++ b/libc/test/src/math/differential_testing/CMakeLists.txt
@@ -27,7 +27,10 @@ function(add_diff_binary target_name)
get_fq_target_name(${target_name} fq_target_name)
get_fq_deps_list(fq_deps_list ${DIFF_DEPENDS})
get_object_files_for_test(
- link_object_files skipped_entrypoints_list ${fq_deps_list})
+ link_object_files skipped_entrypoints_list
+ INTERNAL TRUE
+ ${fq_deps_list}
+ )
if(skipped_entrypoints_list)
if(LIBC_CMAKE_VERBOSE_LOGGING)
set(msg "Will not build ${fq_target_name} as it has missing deps: "
>From e15ee80bef37c657e90cc979910e309fedf8c19f Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Fri, 26 Jan 2024 09:47:02 -0500
Subject: [PATCH 2/8] Remove extra C functions in LibcTest.cpp,
HermeticTestUtils.cpp, and test.cpp.
---
libc/test/IntegrationTest/test.cpp | 41 ------------------------
libc/test/UnitTest/CMakeLists.txt | 11 ++++++-
libc/test/UnitTest/HermeticTestUtils.cpp | 37 ---------------------
libc/test/UnitTest/LibcTest.cpp | 19 ++++-------
4 files changed, 16 insertions(+), 92 deletions(-)
diff --git a/libc/test/IntegrationTest/test.cpp b/libc/test/IntegrationTest/test.cpp
index 3bdbe89a3fb62d..b5cdaa7fdf9247 100644
--- a/libc/test/IntegrationTest/test.cpp
+++ b/libc/test/IntegrationTest/test.cpp
@@ -9,47 +9,6 @@
#include <stddef.h>
#include <stdint.h>
-// Integration tests rely on the following memory functions. This is because the
-// compiler code generation can emit calls to them. We want to map the external
-// entrypoint to the internal implementation of the function used for testing.
-// This is done manually as not all targets support aliases.
-
-namespace LIBC_NAMESPACE {
-
-int bcmp(const void *lhs, const void *rhs, size_t count);
-void bzero(void *ptr, size_t count);
-int memcmp(const void *lhs, const void *rhs, size_t count);
-void *memcpy(void *__restrict, const void *__restrict, size_t);
-void *memmove(void *dst, const void *src, size_t count);
-void *memset(void *ptr, int value, size_t count);
-int atexit(void (*func)(void));
-
-} // namespace LIBC_NAMESPACE
-
-extern "C" {
-
-int bcmp(const void *lhs, const void *rhs, size_t count) {
- return LIBC_NAMESPACE::bcmp(lhs, rhs, count);
-}
-void bzero(void *ptr, size_t count) { LIBC_NAMESPACE::bzero(ptr, count); }
-int memcmp(const void *lhs, const void *rhs, size_t count) {
- return LIBC_NAMESPACE::memcmp(lhs, rhs, count);
-}
-void *memcpy(void *__restrict dst, const void *__restrict src, size_t count) {
- return LIBC_NAMESPACE::memcpy(dst, src, count);
-}
-void *memmove(void *dst, const void *src, size_t count) {
- return LIBC_NAMESPACE::memmove(dst, src, count);
-}
-void *memset(void *ptr, int value, size_t count) {
- return LIBC_NAMESPACE::memset(ptr, value, count);
-}
-
-// This is needed if the test was compiled with '-fno-use-cxa-atexit'.
-int atexit(void (*func)(void)) { return LIBC_NAMESPACE::atexit(func); }
-
-} // extern "C"
-
// Integration tests cannot use the SCUDO standalone allocator as SCUDO pulls
// various other parts of the libc. Since SCUDO development does not use
// LLVM libc build rules, it is very hard to keep track or pull all that SCUDO
diff --git a/libc/test/UnitTest/CMakeLists.txt b/libc/test/UnitTest/CMakeLists.txt
index 9baa41874a83db..fd0f966495b7f2 100644
--- a/libc/test/UnitTest/CMakeLists.txt
+++ b/libc/test/UnitTest/CMakeLists.txt
@@ -18,6 +18,13 @@ function(add_unittest_framework_library name)
set(library_type STATIC)
endif()
+ # When the clock target is available, it will be used inside the test lib
+ # to indicate the performance of the tests.
+ set(clock_target "")
+ if(TARGET libc.src.time.clock)
+ set(clock_target libc.src.time.clock)
+ endif()
+
foreach(lib IN ITEMS ${name}.unit ${name}.hermetic)
add_library(
${lib}
@@ -28,7 +35,7 @@ function(add_unittest_framework_library name)
)
target_include_directories(${lib} PUBLIC ${LIBC_SOURCE_DIR})
target_compile_options(${lib} PRIVATE -fno-exceptions -fno-rtti)
- if(TARGET libc.src.time.clock)
+ if(${clock_target})
target_compile_definitions(${lib} PRIVATE TARGET_SUPPORTS_CLOCK)
endif()
endforeach()
@@ -70,6 +77,7 @@ add_unittest_framework_library(
libc.src.__support.CPP.type_traits
libc.src.__support.OSUtil.osutil
libc.src.__support.uint128
+ ${clock_target}
)
set(libc_death_test_srcs LibcDeathTestExecutors.cpp)
@@ -114,6 +122,7 @@ add_unittest_framework_library(
libc.src.__support.FPUtil.fpbits_str
libc.src.__support.FPUtil.fenv_impl
libc.src.__support.FPUtil.rounding_mode
+ libc.src.errno.errno
)
add_unittest_framework_library(
diff --git a/libc/test/UnitTest/HermeticTestUtils.cpp b/libc/test/UnitTest/HermeticTestUtils.cpp
index 349c182ff2379f..145683976268a1 100644
--- a/libc/test/UnitTest/HermeticTestUtils.cpp
+++ b/libc/test/UnitTest/HermeticTestUtils.cpp
@@ -9,18 +9,6 @@
#include <stddef.h>
#include <stdint.h>
-namespace LIBC_NAMESPACE {
-
-int bcmp(const void *lhs, const void *rhs, size_t count);
-void bzero(void *ptr, size_t count);
-int memcmp(const void *lhs, const void *rhs, size_t count);
-void *memcpy(void *__restrict, const void *__restrict, size_t);
-void *memmove(void *dst, const void *src, size_t count);
-void *memset(void *ptr, int value, size_t count);
-int atexit(void (*func)(void));
-
-} // namespace LIBC_NAMESPACE
-
namespace {
// Integration tests cannot use the SCUDO standalone allocator as SCUDO pulls
@@ -37,31 +25,6 @@ static uint8_t *ptr = memory;
extern "C" {
-// Hermetic tests rely on the following memory functions. This is because the
-// compiler code generation can emit calls to them. We want to map the external
-// entrypoint to the internal implementation of the function used for testing.
-// This is done manually as not all targets support aliases.
-
-int bcmp(const void *lhs, const void *rhs, size_t count) {
- return LIBC_NAMESPACE::bcmp(lhs, rhs, count);
-}
-void bzero(void *ptr, size_t count) { LIBC_NAMESPACE::bzero(ptr, count); }
-int memcmp(const void *lhs, const void *rhs, size_t count) {
- return LIBC_NAMESPACE::memcmp(lhs, rhs, count);
-}
-void *memcpy(void *__restrict dst, const void *__restrict src, size_t count) {
- return LIBC_NAMESPACE::memcpy(dst, src, count);
-}
-void *memmove(void *dst, const void *src, size_t count) {
- return LIBC_NAMESPACE::memmove(dst, src, count);
-}
-void *memset(void *ptr, int value, size_t count) {
- return LIBC_NAMESPACE::memset(ptr, value, count);
-}
-
-// This is needed if the test was compiled with '-fno-use-cxa-atexit'.
-int atexit(void (*func)(void)) { return LIBC_NAMESPACE::atexit(func); }
-
constexpr uint64_t ALIGNMENT = alignof(uintptr_t);
void *malloc(size_t s) {
diff --git a/libc/test/UnitTest/LibcTest.cpp b/libc/test/UnitTest/LibcTest.cpp
index 201b40a178dca0..83d03f57bf3eae 100644
--- a/libc/test/UnitTest/LibcTest.cpp
+++ b/libc/test/UnitTest/LibcTest.cpp
@@ -13,17 +13,6 @@
#include "src/__support/UInt128.h"
#include "test/UnitTest/TestLogger.h"
-#if __STDC_HOSTED__
-#include <time.h>
-#define LIBC_TEST_USE_CLOCK
-#elif defined(TARGET_SUPPORTS_CLOCK)
-#include <time.h>
-
-#include "src/time/clock.h"
-extern "C" clock_t clock() noexcept { return LIBC_NAMESPACE::clock(); }
-#define LIBC_TEST_USE_CLOCK
-#endif
-
namespace LIBC_NAMESPACE {
namespace testing {
@@ -126,13 +115,17 @@ int Test::runTests(const char *TestFilter) {
continue;
}
tlog << GREEN << "[ RUN ] " << RESET << TestName << '\n';
- [[maybe_unused]] const auto start_time = clock();
+#ifdef LIBC_TEST_USE_CLOCK
+ const auto start_time = clock();
+#endif
RunContext Ctx;
T->SetUp();
T->setContext(&Ctx);
T->Run();
T->TearDown();
- [[maybe_unused]] const auto end_time = clock();
+#ifdef LIBC_TEST_USE_CLOCK
+ const auto end_time = clock();
+#endif // LIBC_TEST_USE_CLOCK
switch (Ctx.status()) {
case RunContext::RunResult::Fail:
tlog << RED << "[ FAILED ] " << RESET << TestName << '\n';
>From 34a5a502170d66298a067f32b3a7c7f6cb99b57a Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Fri, 26 Jan 2024 09:48:36 -0500
Subject: [PATCH 3/8] Update libc_errno to work correctly for both overlay and
full build modes.
---
libc/include/errno.h.def | 8 +++
libc/src/errno/CMakeLists.txt | 11 ++++
libc/src/errno/libc_errno.cpp | 56 +++++++++---------
libc/src/errno/libc_errno.h | 57 ++++++++-----------
libc/test/src/errno/errno_test.cpp | 2 +-
libc/test/src/stdlib/StrtolTest.h | 12 ++--
libc/test/src/sys/mman/linux/madvise_test.cpp | 2 +-
libc/test/src/sys/mman/linux/mmap_test.cpp | 2 +-
.../test/src/sys/mman/linux/mprotect_test.cpp | 2 +-
.../src/sys/mman/linux/posix_madvise_test.cpp | 2 +-
libc/test/src/time/asctime_r_test.cpp | 6 +-
libc/test/src/time/asctime_test.cpp | 12 ++--
12 files changed, 90 insertions(+), 82 deletions(-)
diff --git a/libc/include/errno.h.def b/libc/include/errno.h.def
index d8f79dd47a0d1c..6002707deae9b7 100644
--- a/libc/include/errno.h.def
+++ b/libc/include/errno.h.def
@@ -44,7 +44,15 @@
#endif
#if !defined(__AMDGPU__) && !defined(__NVPTX__)
+
+#ifdef __cplusplus
+extern "C" {
+ extern thread_local int __llvmlibc_errno;
+}
+#else
extern _Thread_local int __llvmlibc_errno;
+#endif // __cplusplus
+
#define errno __llvmlibc_errno
#endif
diff --git a/libc/src/errno/CMakeLists.txt b/libc/src/errno/CMakeLists.txt
index e8868dc48c5e97..e19285809e245c 100644
--- a/libc/src/errno/CMakeLists.txt
+++ b/libc/src/errno/CMakeLists.txt
@@ -1,9 +1,20 @@
+# If we are in full build mode, we will provide the errno definition ourselves,
+# and if we are in overlay mode, we will just re-use the system's errno.
+# We are passing LIBC_FULL_BUILD flag in full build mode so that the
+# implementation of libc_errno will know if we are in full build mode or not.
+set(full_build_flag "")
+if(LLVM_LIBC_FULL_BUILD)
+ set(full_build_flag "-DLIBC_FULL_BUILD")
+endif()
+
add_entrypoint_object(
errno
SRCS
libc_errno.cpp
HDRS
libc_errno.h # Include this
+ COMPILE_OPTIONS
+ ${full_build_flag}
DEPENDS
libc.include.errno
libc.src.__support.common
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index c8f0bffd0962e9..b501f949e4b73e 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -1,4 +1,4 @@
-//===-- Implementation of errno -------------------------------------------===//
+//===-- Implementation of libc_errno --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -6,35 +6,39 @@
//
//===----------------------------------------------------------------------===//
-#include "src/__support/macros/attributes.h"
-#include "src/__support/macros/properties/architectures.h"
-
-namespace LIBC_NAMESPACE {
+#include "libc_errno.h"
#ifdef LIBC_TARGET_ARCH_IS_GPU
-struct ErrnoConsumer {
- void operator=(int) {}
-};
-#endif
+// If we are targeting the GPU we currently don't support 'errno'. We simply
+// consume it.
+void LIBC_NAMESPACE::Errno::operator=(int) {}
+LIBC_NAMESPACE::Errno::operator int() { return 0; }
+
+#elif !defined(LIBC_COPT_PUBLIC_PACKAGING)
+// This mode is for unit testing. We just use our internal errno.
+LIBC_THREAD_LOCAL int __llvmlibc_internal_errno;
+void LIBC_NAMESPACE::Errno::operator=(int a) { __llvmlibc_internal_errno = a; }
+LIBC_NAMESPACE::Errno::operator int() { return __llvmlibc_internal_errno; }
+
+#elif defined(LIBC_FULL_BUILD)
+// This mode is for public libc archive, hermetic, and integration tests.
+// In full build mode, we provide the errno storage ourselves.
extern "C" {
-#ifdef LIBC_COPT_PUBLIC_PACKAGING
-// TODO: Declare __llvmlibc_errno only under LIBC_COPT_PUBLIC_PACKAGING and
-// __llvmlibc_internal_errno otherwise.
-// In overlay mode, this will be an unused thread local variable as libc_errno
-// will resolve to errno from the system libc's errno.h. In full build mode
-// however, libc_errno will resolve to this thread local variable via the errno
-// macro defined in LLVM libc's public errno.h header file.
-// TODO: Use a macro to distinguish full build and overlay build which can be
-// used to exclude __llvmlibc_errno under overlay build.
-#ifdef LIBC_TARGET_ARCH_IS_GPU
-ErrnoConsumer __llvmlibc_errno;
-#else
LIBC_THREAD_LOCAL int __llvmlibc_errno;
-#endif // LIBC_TARGET_ARCH_IS_GPU
+}
+
+void LIBC_NAMESPACE::Errno::operator=(int a) { __llvmlibc_errno = a; }
+LIBC_NAMESPACE::Errno::operator int() { return __llvmlibc_errno; }
+
#else
-LIBC_THREAD_LOCAL int __llvmlibc_internal_errno;
-#endif
-} // extern "C"
+// In overlay mode, we simply use the system errno.
+#include <errno.h>
+
+void LIBC_NAMESPACE::Errno::operator=(int a) { errno = a; }
+LIBC_NAMESPACE::Errno::operator int() { return errno; }
+
+#endif // LIBC_FULL_BUILD
-} // namespace LIBC_NAMESPACE
+// Define the global `libc_errno` instance.
+LIBC_NAMESPACE::Errno libc_errno;
diff --git a/libc/src/errno/libc_errno.h b/libc/src/errno/libc_errno.h
index fbcd1c3395cd1f..c19aadcb865e30 100644
--- a/libc/src/errno/libc_errno.h
+++ b/libc/src/errno/libc_errno.h
@@ -12,45 +12,34 @@
#include "src/__support/macros/attributes.h"
#include "src/__support/macros/properties/architectures.h"
+// TODO: Separate just the definition of errno numbers in
+// include/llvm-libc-macros/* and only include that instead of the system
+// <errno.h>.
#include <errno.h>
-// If we are targeting the GPU we currently don't support 'errno'. We simply
-// consume it.
-#ifdef LIBC_TARGET_ARCH_IS_GPU
-namespace LIBC_NAMESPACE {
-struct ErrnoConsumer {
- void operator=(int) {}
-};
-} // namespace LIBC_NAMESPACE
-#endif
-
-// All of the libc runtime and test code should use the "libc_errno" macro. They
-// should not refer to the "errno" macro directly.
-#ifdef LIBC_COPT_PUBLIC_PACKAGING
-#ifdef LIBC_TARGET_ARCH_IS_GPU
-extern "C" LIBC_NAMESPACE::ErrnoConsumer __llvmlibc_errno;
-#define libc_errno __llvmlibc_errno
-#else
-// This macro will resolve to errno from the errno.h file included above. Under
-// full build, this will be LLVM libc's errno. In overlay build, it will be
-// system libc's errno.
-#define libc_errno errno
-#endif
-#else
-namespace LIBC_NAMESPACE {
+// This header is to be consumed by internal implementations, in which all of
+// them should refer to `libc_errno` instead of using `errno` directly from
+// <errno.h> header.
-// TODO: On the GPU build this will be mapped to a single global value. We need
-// to ensure that tests are not run with multiple threads that depend on errno
-// until we have true 'thread_local' support on the GPU.
-extern "C" LIBC_THREAD_LOCAL int __llvmlibc_internal_errno;
+// Unit and hermetic tests should:
+// - #include "src/errno/libc_errno.h"
+// - DO NOT #include <errno.h>
+// - Only use `libc_errno` in the code
+// - Depend on libc.src.errno.errno
-// TODO: After all of libc/src and libc/test are switched over to use
-// libc_errno, this header file will be "shipped" via an add_entrypoint_object
-// target. At which point libc_errno, should point to __llvmlibc_internal_errno
-// if LIBC_COPT_PUBLIC_PACKAGING is not defined.
-#define libc_errno LIBC_NAMESPACE::__llvmlibc_internal_errno
+// Integration tests should:
+// - DO NOT #include "src/errno/libc_errno.h"
+// - #include <errno.h>
+// - Use regular `errno` in the code
+// - Still depend on libc.src.errno.errno
+namespace LIBC_NAMESPACE {
+struct Errno {
+ void operator=(int);
+ operator int();
+};
} // namespace LIBC_NAMESPACE
-#endif
+
+extern LIBC_NAMESPACE::Errno libc_errno;
#endif // LLVM_LIBC_SRC_ERRNO_LIBC_ERRNO_H
diff --git a/libc/test/src/errno/errno_test.cpp b/libc/test/src/errno/errno_test.cpp
index 33185c2bcf6f54..876ebfc0ac2696 100644
--- a/libc/test/src/errno/errno_test.cpp
+++ b/libc/test/src/errno/errno_test.cpp
@@ -12,5 +12,5 @@
TEST(LlvmLibcErrnoTest, Basic) {
int test_val = 123;
libc_errno = test_val;
- ASSERT_EQ(test_val, libc_errno);
+ ASSERT_ERRNO_EQ(test_val);
}
diff --git a/libc/test/src/stdlib/StrtolTest.h b/libc/test/src/stdlib/StrtolTest.h
index 8f1723b0386120..50ed4cca3950e9 100644
--- a/libc/test/src/stdlib/StrtolTest.h
+++ b/libc/test/src/stdlib/StrtolTest.h
@@ -331,8 +331,7 @@ struct StrtoTest : public LIBC_NAMESPACE::testing::Test {
((is_signed_v<ReturnT> && sizeof(ReturnT) == 4)
? T_MAX
: ReturnT(0xFFFFFFFF)));
- ASSERT_EQ(libc_errno,
- is_signed_v<ReturnT> && sizeof(ReturnT) == 4 ? ERANGE : 0);
+ ASSERT_ERRNO_EQ(is_signed_v<ReturnT> && sizeof(ReturnT) == 4 ? ERANGE : 0);
EXPECT_EQ(str_end - max_32_bit_value, ptrdiff_t(10));
const char *negative_max_32_bit_value = "-0xFFFFFFFF";
@@ -341,8 +340,7 @@ struct StrtoTest : public LIBC_NAMESPACE::testing::Test {
((is_signed_v<ReturnT> && sizeof(ReturnT) == 4)
? T_MIN
: -ReturnT(0xFFFFFFFF)));
- ASSERT_EQ(libc_errno,
- is_signed_v<ReturnT> && sizeof(ReturnT) == 4 ? ERANGE : 0);
+ ASSERT_ERRNO_EQ(is_signed_v<ReturnT> && sizeof(ReturnT) == 4 ? ERANGE : 0);
EXPECT_EQ(str_end - negative_max_32_bit_value, ptrdiff_t(11));
// Max size for signed 32 bit numbers
@@ -368,8 +366,7 @@ struct StrtoTest : public LIBC_NAMESPACE::testing::Test {
(is_signed_v<ReturnT> || sizeof(ReturnT) < 8
? T_MAX
: ReturnT(0xFFFFFFFFFFFFFFFF)));
- ASSERT_EQ(libc_errno,
- (is_signed_v<ReturnT> || sizeof(ReturnT) < 8 ? ERANGE : 0));
+ ASSERT_ERRNO_EQ((is_signed_v<ReturnT> || sizeof(ReturnT) < 8 ? ERANGE : 0));
EXPECT_EQ(str_end - max_64_bit_value, ptrdiff_t(18));
// See the end of CleanBase10Decode for an explanation of how this large
@@ -381,8 +378,7 @@ struct StrtoTest : public LIBC_NAMESPACE::testing::Test {
(is_signed_v<ReturnT>
? T_MIN
: (sizeof(ReturnT) < 8 ? T_MAX : -ReturnT(0xFFFFFFFFFFFFFFFF))));
- ASSERT_EQ(libc_errno,
- (is_signed_v<ReturnT> || sizeof(ReturnT) < 8 ? ERANGE : 0));
+ ASSERT_ERRNO_EQ((is_signed_v<ReturnT> || sizeof(ReturnT) < 8 ? ERANGE : 0));
EXPECT_EQ(str_end - negative_max_64_bit_value, ptrdiff_t(19));
// Max size for signed 64 bit numbers
diff --git a/libc/test/src/sys/mman/linux/madvise_test.cpp b/libc/test/src/sys/mman/linux/madvise_test.cpp
index 83c73f5454de1b..e45cf19f8913ec 100644
--- a/libc/test/src/sys/mman/linux/madvise_test.cpp
+++ b/libc/test/src/sys/mman/linux/madvise_test.cpp
@@ -23,7 +23,7 @@ TEST(LlvmLibcMadviseTest, NoError) {
libc_errno = 0;
void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- EXPECT_EQ(0, libc_errno);
+ ASSERT_ERRNO_SUCCESS();
EXPECT_NE(addr, MAP_FAILED);
EXPECT_THAT(LIBC_NAMESPACE::madvise(addr, alloc_size, MADV_RANDOM),
diff --git a/libc/test/src/sys/mman/linux/mmap_test.cpp b/libc/test/src/sys/mman/linux/mmap_test.cpp
index 9b13b8bd8057f2..b996f26db8605f 100644
--- a/libc/test/src/sys/mman/linux/mmap_test.cpp
+++ b/libc/test/src/sys/mman/linux/mmap_test.cpp
@@ -22,7 +22,7 @@ TEST(LlvmLibcMMapTest, NoError) {
libc_errno = 0;
void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- EXPECT_EQ(0, libc_errno);
+ ASSERT_ERRNO_SUCCESS();
EXPECT_NE(addr, MAP_FAILED);
int *array = reinterpret_cast<int *>(addr);
diff --git a/libc/test/src/sys/mman/linux/mprotect_test.cpp b/libc/test/src/sys/mman/linux/mprotect_test.cpp
index 7127f77714d642..96f625984101dc 100644
--- a/libc/test/src/sys/mman/linux/mprotect_test.cpp
+++ b/libc/test/src/sys/mman/linux/mprotect_test.cpp
@@ -24,7 +24,7 @@ TEST(LlvmLibcMProtectTest, NoError) {
libc_errno = 0;
void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- EXPECT_EQ(0, libc_errno);
+ ASSERT_ERRNO_SUCCESS();
EXPECT_NE(addr, MAP_FAILED);
int *array = reinterpret_cast<int *>(addr);
diff --git a/libc/test/src/sys/mman/linux/posix_madvise_test.cpp b/libc/test/src/sys/mman/linux/posix_madvise_test.cpp
index 59cf01ac746959..d20db69042b7ad 100644
--- a/libc/test/src/sys/mman/linux/posix_madvise_test.cpp
+++ b/libc/test/src/sys/mman/linux/posix_madvise_test.cpp
@@ -23,7 +23,7 @@ TEST(LlvmLibcPosixMadviseTest, NoError) {
libc_errno = 0;
void *addr = LIBC_NAMESPACE::mmap(nullptr, alloc_size, PROT_READ,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
- EXPECT_EQ(0, libc_errno);
+ ASSERT_ERRNO_SUCCESS();
EXPECT_NE(addr, MAP_FAILED);
EXPECT_EQ(LIBC_NAMESPACE::posix_madvise(addr, alloc_size, POSIX_MADV_RANDOM),
diff --git a/libc/test/src/time/asctime_r_test.cpp b/libc/test/src/time/asctime_r_test.cpp
index 1abaa135350c13..f3aadbb39de4d0 100644
--- a/libc/test/src/time/asctime_r_test.cpp
+++ b/libc/test/src/time/asctime_r_test.cpp
@@ -27,17 +27,17 @@ static inline char *call_asctime_r(struct tm *tm_data, int year, int month,
TEST(LlvmLibcAsctimeR, Nullptr) {
char *result;
result = LIBC_NAMESPACE::asctime_r(nullptr, nullptr);
- ASSERT_EQ(EINVAL, libc_errno);
+ ASSERT_ERRNO_EQ(EINVAL);
ASSERT_STREQ(nullptr, result);
char buffer[TimeConstants::ASCTIME_BUFFER_SIZE];
result = LIBC_NAMESPACE::asctime_r(nullptr, buffer);
- ASSERT_EQ(EINVAL, libc_errno);
+ ASSERT_ERRNO_EQ(EINVAL);
ASSERT_STREQ(nullptr, result);
struct tm tm_data;
result = LIBC_NAMESPACE::asctime_r(&tm_data, nullptr);
- ASSERT_EQ(EINVAL, libc_errno);
+ ASSERT_ERRNO_EQ(EINVAL);
ASSERT_STREQ(nullptr, result);
}
diff --git a/libc/test/src/time/asctime_test.cpp b/libc/test/src/time/asctime_test.cpp
index 4b5ceb596aa467..169a7463a3037d 100644
--- a/libc/test/src/time/asctime_test.cpp
+++ b/libc/test/src/time/asctime_test.cpp
@@ -22,7 +22,7 @@ static inline char *call_asctime(struct tm *tm_data, int year, int month,
TEST(LlvmLibcAsctime, Nullptr) {
char *result;
result = LIBC_NAMESPACE::asctime(nullptr);
- ASSERT_EQ(EINVAL, libc_errno);
+ ASSERT_ERRNO_EQ(EINVAL);
ASSERT_STREQ(nullptr, result);
}
@@ -40,7 +40,7 @@ TEST(LlvmLibcAsctime, InvalidWday) {
0, // sec
-1, // wday
0); // yday
- ASSERT_EQ(EINVAL, libc_errno);
+ ASSERT_ERRNO_EQ(EINVAL);
// Test with wday = 7.
call_asctime(&tm_data,
@@ -52,7 +52,7 @@ TEST(LlvmLibcAsctime, InvalidWday) {
0, // sec
7, // wday
0); // yday
- ASSERT_EQ(EINVAL, libc_errno);
+ ASSERT_ERRNO_EQ(EINVAL);
}
// Months are from January to December. Test passing invalid value in month.
@@ -69,7 +69,7 @@ TEST(LlvmLibcAsctime, InvalidMonth) {
0, // sec
4, // wday
0); // yday
- ASSERT_EQ(EINVAL, libc_errno);
+ ASSERT_ERRNO_EQ(EINVAL);
// Test with month = 13.
call_asctime(&tm_data,
@@ -81,7 +81,7 @@ TEST(LlvmLibcAsctime, InvalidMonth) {
0, // sec
4, // wday
0); // yday
- ASSERT_EQ(EINVAL, libc_errno);
+ ASSERT_ERRNO_EQ(EINVAL);
}
TEST(LlvmLibcAsctime, ValidWeekdays) {
@@ -209,6 +209,6 @@ TEST(LlvmLibcAsctime, Max64BitYear) {
50, // sec
2, // wday
50); // yday
- ASSERT_EQ(EOVERFLOW, libc_errno);
+ ASSERT_ERRNO_EQ(EOVERFLOW);
ASSERT_STREQ(nullptr, result);
}
>From 5cc39f05f644e6e6b4e688eb9ff65c39abd37ddd Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Fri, 26 Jan 2024 10:54:18 -0500
Subject: [PATCH 4/8] Switch libc.test.src.unistd.getopt_test to
UNIT_TEST_ONLY.
---
libc/test/src/unistd/CMakeLists.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 8b9a8db374dd45..37cd9ea419bed2 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -432,7 +432,7 @@ add_libc_unittest(
add_libc_test(
getopt_test
- HERMETIC_TEST_ONLY # Uses libc's own stderr
+ UNIT_TEST_ONLY # set_getopt_state only exposed for __internal__ target.
SUITE
libc_unistd_unittests
SRCS
>From f1fc24b3031ff61872bcf9b8fac223d6e8c8bc45 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Fri, 26 Jan 2024 11:54:54 -0500
Subject: [PATCH 5/8] Still use __internal__ target for hermetic tests on GPUs.
---
libc/cmake/modules/LLVMLibCTestRules.cmake | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index d07cec047370ee..b169d28194ec57 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -771,11 +771,18 @@ function(add_libc_hermetic_test test_name)
list(REMOVE_DUPLICATES fq_deps_list)
+ if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
+ # Hermetic tests for GPUs still need to link against __internal__ targets.
+ set(internal_targets TRUE)
+ else
+ set(internal_targets FALSE)
+ endif()
+
# 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
- INTERNAL FALSE
+ INTERNAL ${internal_targets}
${fq_deps_list}
)
>From beaf40ab7b8cc1426d4bdb82de79b38566c58514 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Fri, 26 Jan 2024 12:10:03 -0500
Subject: [PATCH 6/8] Address comments and fix missing parentheses.
---
libc/cmake/modules/LLVMLibCTestRules.cmake | 2 +-
libc/src/errno/libc_errno.cpp | 3 +++
libc/test/src/unistd/CMakeLists.txt | 4 +++-
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index b169d28194ec57..2c4a9bcdb1eec3 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -774,7 +774,7 @@ function(add_libc_hermetic_test test_name)
if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
# Hermetic tests for GPUs still need to link against __internal__ targets.
set(internal_targets TRUE)
- else
+ else()
set(internal_targets FALSE)
endif()
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index b501f949e4b73e..8a282db6724275 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -6,6 +6,9 @@
//
//===----------------------------------------------------------------------===//
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/properties/architectures.h"
+
#include "libc_errno.h"
#ifdef LIBC_TARGET_ARCH_IS_GPU
diff --git a/libc/test/src/unistd/CMakeLists.txt b/libc/test/src/unistd/CMakeLists.txt
index 37cd9ea419bed2..059cff1cdc0c84 100644
--- a/libc/test/src/unistd/CMakeLists.txt
+++ b/libc/test/src/unistd/CMakeLists.txt
@@ -430,9 +430,11 @@ add_libc_unittest(
libc.src.unistd.sysconf
)
+# getopt_test requires access to set_getopt_state which is only available for
+# __internal__ targets, hence the use of UNIT_TEST_ONLY.
add_libc_test(
getopt_test
- UNIT_TEST_ONLY # set_getopt_state only exposed for __internal__ target.
+ UNIT_TEST_ONLY
SUITE
libc_unistd_unittests
SRCS
>From 0f65a11ca4d907bece67953328b0adca50aaed9c Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Fri, 26 Jan 2024 14:34:52 -0500
Subject: [PATCH 7/8] Update integration tests and provide a global errno for
GPU.
---
libc/cmake/modules/LLVMLibCTestRules.cmake | 11 ++++++++---
libc/src/errno/libc_errno.cpp | 12 ++++++++----
libc/src/errno/libc_errno.h | 4 ++--
libc/test/src/string/CMakeLists.txt | 12 ++++++++++++
4 files changed, 30 insertions(+), 9 deletions(-)
diff --git a/libc/cmake/modules/LLVMLibCTestRules.cmake b/libc/cmake/modules/LLVMLibCTestRules.cmake
index 2c4a9bcdb1eec3..b5948b29970dda 100644
--- a/libc/cmake/modules/LLVMLibCTestRules.cmake
+++ b/libc/cmake/modules/LLVMLibCTestRules.cmake
@@ -564,11 +564,16 @@ function(add_integration_test test_name)
list(REMOVE_DUPLICATES fq_deps_list)
- # TODO: Instead of gathering internal object files from entrypoints,
- # collect the object files with public names of entrypoints.
+ if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
+ # Hermetic tests for GPUs still need to link against __internal__ targets.
+ set(internal_targets TRUE)
+ else()
+ set(internal_targets FALSE)
+ endif()
+
get_object_files_for_test(
link_object_files skipped_entrypoints_list
- INTERNAL FALSE
+ INTERNAL ${internal_targets}
${fq_deps_list}
)
diff --git a/libc/src/errno/libc_errno.cpp b/libc/src/errno/libc_errno.cpp
index 8a282db6724275..71ea4a27626a5c 100644
--- a/libc/src/errno/libc_errno.cpp
+++ b/libc/src/errno/libc_errno.cpp
@@ -12,10 +12,14 @@
#include "libc_errno.h"
#ifdef LIBC_TARGET_ARCH_IS_GPU
-// If we are targeting the GPU we currently don't support 'errno'. We simply
-// consume it.
-void LIBC_NAMESPACE::Errno::operator=(int) {}
-LIBC_NAMESPACE::Errno::operator int() { return 0; }
+// LIBC_THREAD_LOCAL on GPU currently does nothing. So essentially this is just
+// a global errno for gpu to use for now.
+extern "C" {
+LIBC_THREAD_LOCAL int __llvmlibc_gpu_errno;
+}
+
+void LIBC_NAMESPACE::Errno::operator=(int a) { __llvmlibc_gpu_errno = a; }
+LIBC_NAMESPACE::Errno::operator int() { return __llvmlibc_gpu_errno; }
#elif !defined(LIBC_COPT_PUBLIC_PACKAGING)
// This mode is for unit testing. We just use our internal errno.
diff --git a/libc/src/errno/libc_errno.h b/libc/src/errno/libc_errno.h
index c19aadcb865e30..143aba5992baf2 100644
--- a/libc/src/errno/libc_errno.h
+++ b/libc/src/errno/libc_errno.h
@@ -23,12 +23,12 @@
// Unit and hermetic tests should:
// - #include "src/errno/libc_errno.h"
-// - DO NOT #include <errno.h>
+// - NOT #include <errno.h>
// - Only use `libc_errno` in the code
// - Depend on libc.src.errno.errno
// Integration tests should:
-// - DO NOT #include "src/errno/libc_errno.h"
+// - NOT #include "src/errno/libc_errno.h"
// - #include <errno.h>
// - Use regular `errno` in the code
// - Still depend on libc.src.errno.errno
diff --git a/libc/test/src/string/CMakeLists.txt b/libc/test/src/string/CMakeLists.txt
index 6088289532d771..a0c50abcee98d7 100644
--- a/libc/test/src/string/CMakeLists.txt
+++ b/libc/test/src/string/CMakeLists.txt
@@ -419,7 +419,18 @@ add_libc_test(
)
# Tests all implementations that can run on the target CPU.
+
+# TODO: For GPUs, hermetic tests still need to get linked against
+# __internal__ targets. Update this test generator so that hermetic tests
+# work on GPUs again.
function(add_libc_multi_impl_test name)
+ if(LIBC_TARGET_ARCHITECTURE_IS_GPU)
+ # Hermetic tests for GPUs still need to link against __internal__ targets.
+ set(unit_test_only "UNIT_TEST_ONLY")
+ else()
+ set(unit_test_only "")
+ endif()
+
get_property(fq_implementations GLOBAL PROPERTY ${name}_implementations)
foreach(fq_config_name IN LISTS fq_implementations)
get_target_property(required_cpu_features ${fq_config_name} REQUIRE_CPU_FEATURES)
@@ -430,6 +441,7 @@ function(add_libc_multi_impl_test name)
string(SUBSTRING ${fq_config_name} ${name_loc} -1 target_name)
add_libc_test(
${target_name}_test
+ ${unit_test_only}
SUITE
libc-string-tests
COMPILE_OPTIONS
>From fdd072d7da639f7196cc319cffb82511d8f665f5 Mon Sep 17 00:00:00 2001
From: Tue Ly <lntue at google.com>
Date: Sat, 27 Jan 2024 12:05:08 -0500
Subject: [PATCH 8/8] Enable C symbol atexit for nVidia GPU target for testing.
---
libc/src/stdlib/CMakeLists.txt | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index a4d51fb9a11eef..bf3b2c321ca9fd 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -363,6 +363,13 @@ add_entrypoint_object(
libc.src.__support.OSUtil.osutil
)
+# Tests for nVidia GPUs need to be compiled with -fno-use-cxa-atexit, so we need
+# to export the C symbol `atexit` also for __internal__ targets.
+set(atexit_compile_options "")
+if(LIBC_GPU_TARGET_ARCHITECTURE_IS_NVPTX)
+ set(atexit_compile_options "-DLIBC_COPT_PUBLIC_PACKAGING")
+endif()
+
add_entrypoint_object(
atexit
SRCS
@@ -371,6 +378,8 @@ add_entrypoint_object(
atexit.h
CXX_STANDARD
20 # For constinit of the atexit callback list.
+ COMPILE_OPTIONS
+ ${atexit_compile_options}
DEPENDS
libc.src.__support.fixedvector
libc.src.__support.blockstore
More information about the libc-commits
mailing list