[libc] [llvm] [libc] Change LIBC_THREAD_LOCAL to be dependent on LIBC_THREAD_MODE (PR #151527)

William Huynh via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 5 06:42:40 PDT 2025


https://github.com/saturn691 updated https://github.com/llvm/llvm-project/pull/151527

>From dde7b220f1187b3b682aa86edb4c796efd92976e Mon Sep 17 00:00:00 2001
From: William Huynh <William.Huynh at arm.com>
Date: Tue, 5 Aug 2025 14:39:43 +0100
Subject: [PATCH 1/2] Try and get CI to pass again

---
 libc/CMakeLists.txt                    |  71 -----------------
 libc/cmake/modules/LibcConfig.cmake    | 103 +++++++++++++++++++++++++
 libc/shared/libc_common.h              |   9 +--
 libc/src/__support/macros/attributes.h |   2 +-
 libc/src/__support/threads/mutex.h     |   6 +-
 5 files changed, 111 insertions(+), 80 deletions(-)

diff --git a/libc/CMakeLists.txt b/libc/CMakeLists.txt
index 4f3704ec9aa9b..07623adff2e49 100644
--- a/libc/CMakeLists.txt
+++ b/libc/CMakeLists.txt
@@ -34,7 +34,6 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
   add_definitions("-D_DEBUG")
 endif()
 
-
 # Default to C++17
 set(CMAKE_CXX_STANDARD 17)
 
@@ -131,13 +130,6 @@ endif()
 
 # Defines LIBC_TARGET_ARCHITECTURE and associated macros.
 set(LIBC_TARGET_TRIPLE "" CACHE STRING "The target triple for the libc build.")
-include(LLVMLibCArchitectures)
-
-# Some targets can only support the full build.
-set(default_to_full_build OFF)
-if(LIBC_TARGET_OS_IS_GPU)
-  set(default_to_full_build ON)
-endif()
 
 option(LLVM_LIBC_FULL_BUILD "Build and test LLVM libc as if it is the full libc" ${default_to_full_build})
 option(LLVM_LIBC_IMPLEMENTATION_DEFINED_TEST_BEHAVIOR "Build LLVM libc tests assuming our implementation-defined behavior" ON)
@@ -151,24 +143,6 @@ set(LIBC_ENABLE_HERMETIC_TESTS ${LLVM_LIBC_FULL_BUILD})
 
 set(LIBC_CONFIG_JSON_FILE_LIST "")
 
-if(NOT LIBC_CONFIG_PATH)
-  list(APPEND LIBC_CONFIG_JSON_FILE_LIST "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}")
-  if(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}")
-    list(APPEND LIBC_CONFIG_JSON_FILE_LIST "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}")
-    set(LIBC_CONFIG_PATH "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}")
-  elseif(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}")
-    set(LIBC_CONFIG_PATH "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}")
-  endif()
-else()
-  list(APPEND LIBC_CONFIG_JSON_FILE_LIST "${LIBC_CONFIG_PATH}")
-endif()
-
-if(NOT LIBC_CONFIG_PATH)
-  message(FATAL_ERROR "Configs for the platform '${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}' do not exist and LIBC_CONFIG_PATH is not set.")
-elseif(LIBC_CMAKE_VERBOSE_LOGGING)
-  message(STATUS "Path for config files is: ${LIBC_CONFIG_PATH}")
-endif()
-
 # option(LIBC_ENABLE_WIDE_CHARACTERS
 # "Whether to enable wide character functions on supported platforms. This may
 # also set flags to enable or disable wide character support within other
@@ -177,51 +151,6 @@ endif()
 #TODO: Add carve-out specific config files to the list here.
 
 include(LibcConfig)
-# Config loading happens in three steps:
-# 1. Load the config file config/config.json and set up config vars.
-# 2. Load config/${LIBC_TARGET_OS}/config.json if available and override
-#    vars as suitable.
-# 3. Load config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCH}/config.json is
-#    available and override vars as suitable.
-# All the three steps will not override options already set from the
-# CMake command line. That is, the CMake command line option values take
-# precedence over the values in config.json files.
-set(main_config_file ${LIBC_SOURCE_DIR}/config/config.json)
-read_libc_config(${main_config_file} global_config)
-foreach(opt IN LISTS global_config)
-  string(JSON opt_name ERROR_VARIABLE json_error MEMBER ${opt} 0)
-  if(json_error)
-    message(FATAL_ERROR ${json_error})
-  endif()
-  if(DEFINED ${opt_name})
-    # The option is already defined from the command line so we ignore it here.
-    # We still make note of it so that further config load can also ignore
-    # this option.
-    message(STATUS "${opt_name}: ${${opt_name}} (from command line)")
-    list(APPEND cmd_line_conf ${opt_name})
-    continue()
-  endif()
-
-  string(JSON opt_object ERROR_VARIABLE json_error GET ${opt} ${opt_name})
-  if(json_error)
-    message(FATAL_ERROR "Error reading info of option '${opt_name}': ${json_error}")
-  endif()
-  string(JSON opt_value ERROR_VARIABLE json_error GET ${opt_object} "value")
-  if(json_error)
-    message(FATAL_ERROR ${json_error})
-  endif()
-  message(STATUS "${opt_name}: ${opt_value}")
-  set(${opt_name} ${opt_value})
-endforeach()
-generate_config_doc(${main_config_file} ${LIBC_SOURCE_DIR}/docs/configure.rst)
-
-# Load each target specific config.
-foreach(config_path IN LISTS LIBC_CONFIG_JSON_FILE_LIST)
-  if(LIBC_CMAKE_VERBOSE_LOGGING)
-    message(STATUS "Loading additional config: '${config_path}/config.json'")
-  endif()
-  load_libc_config(${config_path}/config.json ${cmd_line_conf})
-endforeach()
 
 if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR)
   set(LIBC_TARGET_SUBDIR ${LLVM_DEFAULT_TARGET_TRIPLE})
diff --git a/libc/cmake/modules/LibcConfig.cmake b/libc/cmake/modules/LibcConfig.cmake
index da166dd6cc3fc..be6e5c7518c01 100644
--- a/libc/cmake/modules/LibcConfig.cmake
+++ b/libc/cmake/modules/LibcConfig.cmake
@@ -106,6 +106,7 @@ endfunction()
 #   argument. Typically, these will be the options specified on the CMake
 #   command line.
 function(load_libc_config config_file)
+  set(changed_vars "")
   read_libc_config(${config_file} file_opts)
   foreach(opt IN LISTS file_opts)
     string(JSON opt_name ERROR_VARIABLE json_error MEMBER ${opt} 0)
@@ -132,7 +133,9 @@ function(load_libc_config config_file)
     endif()
     message(STATUS "Overriding - ${opt_name}: ${opt_value} (Previous value: ${${opt_name}})")
     set(${opt_name} ${opt_value} PARENT_SCOPE)
+    list(APPEND changed_vars ${opt_name})
   endforeach()
+  set(changed_vars "${changed_vars}" PARENT_SCOPE)
 endfunction()
 
 function(generate_config_doc config_file doc_file)
@@ -215,3 +218,103 @@ function(generate_config_doc config_file doc_file)
   message(STATUS "Writing config doc to ${doc_file}")
   file(WRITE ${doc_file} ${doc_string})
 endfunction()
+
+#--------------------------
+# Entry point (shared between libc/libcxx)
+#--------------------------
+
+if(NOT DEFINED LIBC_SOURCE_DIR)
+  set(LIBC_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
+  message(WARNING "LIBC_SOURCE_DIR: ${LIBC_SOURCE_DIR}")
+endif()
+
+include(LLVMLibCArchitectures)
+
+# Some targets can only support the full build.
+set(default_to_full_build OFF)
+if(LIBC_TARGET_OS_IS_GPU)
+  set(default_to_full_build ON)
+endif()
+
+if(NOT LIBC_CONFIG_PATH)
+  list(APPEND LIBC_CONFIG_JSON_FILE_LIST "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}")
+  if(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}")
+    list(APPEND LIBC_CONFIG_JSON_FILE_LIST "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}")
+    set(LIBC_CONFIG_PATH "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}")
+  elseif(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}")
+    set(LIBC_CONFIG_PATH "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}")
+  endif()
+else()
+  list(APPEND LIBC_CONFIG_JSON_FILE_LIST "${LIBC_CONFIG_PATH}")
+endif()
+
+if(NOT LIBC_CONFIG_PATH)
+  message(FATAL_ERROR "Configs for the platform '${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}' do not exist and LIBC_CONFIG_PATH is not set.")
+elseif(LIBC_CMAKE_VERBOSE_LOGGING)
+  message(STATUS "Path for config files is: ${LIBC_CONFIG_PATH}")
+endif()
+
+# Config loading happens in three steps:
+# 1. Load the config file config/config.json and set up config vars.
+# 2. Load config/${LIBC_TARGET_OS}/config.json if available and override
+#    vars as suitable.
+# 3. Load config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCH}/config.json is
+#    available and override vars as suitable.
+# All the three steps will not override options already set from the
+# CMake command line. That is, the CMake command line option values take
+# precedence over the values in config.json files.
+set(main_config_file ${LIBC_SOURCE_DIR}/config/config.json)
+read_libc_config(${main_config_file} global_config)
+foreach(opt IN LISTS global_config)
+  string(JSON opt_name ERROR_VARIABLE json_error MEMBER ${opt} 0)
+  if(json_error)
+    message(FATAL_ERROR ${json_error})
+  endif()
+  if(DEFINED ${opt_name})
+    # The option is already defined from the command line so we ignore it here.
+    # We still make note of it so that further config load can also ignore
+    # this option.
+    message(STATUS "${opt_name}: ${${opt_name}} (from command line)")
+    list(APPEND cmd_line_conf ${opt_name})
+    continue()
+  endif()
+
+  string(JSON opt_object ERROR_VARIABLE json_error GET ${opt} ${opt_name})
+  if(json_error)
+    message(FATAL_ERROR "Error reading info of option '${opt_name}': ${json_error}")
+  endif()
+  string(JSON opt_value ERROR_VARIABLE json_error GET ${opt_object} "value")
+  if(json_error)
+    message(FATAL_ERROR ${json_error})
+  endif()
+  message(STATUS "${opt_name}: ${opt_value}")
+  set(${opt_name} ${opt_value})
+  set(${opt_name} ${opt_value} PARENT_SCOPE)
+endforeach()
+generate_config_doc(${main_config_file} ${LIBC_SOURCE_DIR}/docs/configure.rst)
+
+message(WARNING "LIBC_SOURCE_DIR: ${LIBC_SOURCE_DIR}")
+message(WARNING "LIBC_CONFIG_PATH: ${LIBC_CONFIG_PATH}")
+if(NOT LIBC_CONFIG_PATH)
+  list(APPEND LIBC_CONFIG_JSON_FILE_LIST "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}")
+  if(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}")
+    list(APPEND LIBC_CONFIG_JSON_FILE_LIST "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}")
+    set(LIBC_CONFIG_PATH "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}/${LIBC_TARGET_ARCHITECTURE}")
+  elseif(EXISTS "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}")
+    set(LIBC_CONFIG_PATH "${LIBC_SOURCE_DIR}/config/${LIBC_TARGET_OS}")
+  endif()
+else()
+  list(APPEND LIBC_CONFIG_JSON_FILE_LIST "${LIBC_CONFIG_PATH}")
+endif()
+
+# Load each target specific config.
+foreach(config_path IN LISTS LIBC_CONFIG_JSON_FILE_LIST)
+  if(LIBC_CMAKE_VERBOSE_LOGGING)
+    message(STATUS "Loading additional config: '${config_path}/config.json'")
+  endif()
+  load_libc_config(${config_path}/config.json ${cmd_line_conf})
+  # Proprogate changed_vars
+  foreach(var IN LISTS changed_vars)
+    set(${var} "${${var}}" PARENT_SCOPE)
+  endforeach()
+endforeach()
diff --git a/libc/shared/libc_common.h b/libc/shared/libc_common.h
index c4560bbb02763..87a907108a50a 100644
--- a/libc/shared/libc_common.h
+++ b/libc/shared/libc_common.h
@@ -9,13 +9,12 @@
 #ifndef LLVM_LIBC_SHARED_LIBC_COMMON_H
 #define LLVM_LIBC_SHARED_LIBC_COMMON_H
 
+#include "src/__support/libc_errno.h"    // LIBC_ERRNO_MODE_*
+#include "src/__support/threads/mutex.h" // LIBC_THREAD_MODE_*
+
 // Use system errno.
 #ifdef LIBC_ERRNO_MODE
-#if LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM_INLINE
-#error                                                                         \
-    "LIBC_ERRNO_MODE was set to something different from LIBC_ERRNO_MODE_SYSTEM_INLINE."
-#endif // LIBC_ERRNO_MODE != LIBC_ERRNO_MODE_SYSTEM_INLINE
-#else
+#undef LIBC_ERRNO_MODE
 #define LIBC_ERRNO_MODE LIBC_ERRNO_MODE_SYSTEM_INLINE
 #endif // LIBC_ERRNO_MODE
 
diff --git a/libc/src/__support/macros/attributes.h b/libc/src/__support/macros/attributes.h
index c6474673de85a..23f973827b6f9 100644
--- a/libc/src/__support/macros/attributes.h
+++ b/libc/src/__support/macros/attributes.h
@@ -28,7 +28,7 @@
 #define LIBC_INLINE_ASM __asm__ __volatile__
 #define LIBC_UNUSED __attribute__((unused))
 
-#ifdef LIBC_TARGET_ARCH_IS_GPU
+#if LIBC_THREAD_MODE == LIBC_THREAD_MODE_SINGLE
 #define LIBC_THREAD_LOCAL
 #else
 #define LIBC_THREAD_LOCAL thread_local
diff --git a/libc/src/__support/threads/mutex.h b/libc/src/__support/threads/mutex.h
index cbef0d00009b2..fe9c41be4a4f1 100644
--- a/libc/src/__support/threads/mutex.h
+++ b/libc/src/__support/threads/mutex.h
@@ -9,9 +9,6 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_THREADS_MUTEX_H
 #define LLVM_LIBC_SRC___SUPPORT_THREADS_MUTEX_H
 
-#include "src/__support/macros/attributes.h"
-#include "src/__support/macros/config.h"
-
 // Uses the platform specific specialization
 #define LIBC_THREAD_MODE_PLATFORM 0
 
@@ -34,6 +31,9 @@ LIBC_THREAD_MODE_SINGLE, \
 LIBC_THREAD_MODE_EXTERNAL.
 #endif
 
+#include "src/__support/macros/attributes.h"
+#include "src/__support/macros/config.h"
+
 #if LIBC_THREAD_MODE == LIBC_THREAD_MODE_PLATFORM
 
 // Platform independent code will include this header file which pulls

>From d325e192e75c19032bfa4ff0d64617327d019cfa Mon Sep 17 00:00:00 2001
From: William Huynh <William.Huynh at arm.com>
Date: Tue, 5 Aug 2025 14:42:30 +0100
Subject: [PATCH 2/2] More CMake

---
 cmake/Modules/FindLibcCommonUtils.cmake | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/cmake/Modules/FindLibcCommonUtils.cmake b/cmake/Modules/FindLibcCommonUtils.cmake
index 95426c51a6041..d5ac62a45b116 100644
--- a/cmake/Modules/FindLibcCommonUtils.cmake
+++ b/cmake/Modules/FindLibcCommonUtils.cmake
@@ -8,8 +8,13 @@
 
 if(NOT TARGET llvm-libc-common-utilities)
   set(libc_path ${CMAKE_CURRENT_LIST_DIR}/../../libc)
+  list(APPEND CMAKE_MODULE_PATH "${libc_path}/cmake/modules")
   if (EXISTS ${libc_path} AND IS_DIRECTORY ${libc_path})
     add_library(llvm-libc-common-utilities INTERFACE)
+    include(LibcConfig)
+    include(LLVMLibCCompileOptionRules)
+    _get_compile_options_from_config(compile_options)
+    target_compile_options(llvm-libc-common-utilities INTERFACE ${compile_options})
     # TODO: Reorganize the libc shared section so that it can be included without
     # adding the root "libc" directory to the include path.
     target_include_directories(llvm-libc-common-utilities INTERFACE ${libc_path})



More information about the llvm-commits mailing list