[libcxx] [libcxxabi] [libunwind] [llvm] [libc++] Build Google Benchmark directly from Lit (PR #160367)

Louis Dionne via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 12 05:54:35 PST 2026


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/160367

>From f76c478d74daf83bbb3924968e3a99282970c6b4 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Thu, 11 Sep 2025 23:57:28 -0400
Subject: [PATCH] [libc++][WIP] Build Google Benchmark directly from Lit

This removes a weird interconnection between libc++'s own build
and the configuration of the test suite, which should be disjoint.
After this patch, Google Benchmark gets built using the same flags
used for the rest of the test suite, which provides additional
flexibility.
---
 libcxx/test/CMakeLists.txt                 |  1 -
 libcxx/test/benchmarks/CMakeLists.txt      | 48 ----------------------
 libcxx/test/configs/cmake-bridge.cfg.in    |  1 -
 libcxx/utils/libcxx/test/config.py         |  2 +-
 libcxx/utils/libcxx/test/format.py         | 23 ++++++++---
 libcxxabi/test/configs/cmake-bridge.cfg.in |  1 -
 libunwind/test/configs/cmake-bridge.cfg.in |  1 -
 third-party/benchmark/CMakeLists.txt       |  4 +-
 8 files changed, 20 insertions(+), 61 deletions(-)
 delete mode 100644 libcxx/test/benchmarks/CMakeLists.txt

diff --git a/libcxx/test/CMakeLists.txt b/libcxx/test/CMakeLists.txt
index 39d383922e1df..a7a671c793db9 100644
--- a/libcxx/test/CMakeLists.txt
+++ b/libcxx/test/CMakeLists.txt
@@ -26,7 +26,6 @@ set(SERIALIZED_LIT_PARAMS "# Lit parameters serialized here for llvm-lit to pick
 serialize_lit_string_param(SERIALIZED_LIT_PARAMS compiler "${CMAKE_CXX_COMPILER}")
 
 if (LIBCXX_INCLUDE_BENCHMARKS)
-  add_subdirectory(benchmarks)
   set(_libcxx_benchmark_mode "dry-run")
 else()
   serialize_lit_string_param(SERIALIZED_LIT_PARAMS enable_benchmarks "no")
diff --git a/libcxx/test/benchmarks/CMakeLists.txt b/libcxx/test/benchmarks/CMakeLists.txt
deleted file mode 100644
index b0fe600623d96..0000000000000
--- a/libcxx/test/benchmarks/CMakeLists.txt
+++ /dev/null
@@ -1,48 +0,0 @@
-#==============================================================================
-# Build Google Benchmark
-#==============================================================================
-
-include(ExternalProject)
-set(BENCHMARK_COMPILE_FLAGS
-    -Wno-unused-command-line-argument
-    -nostdinc++
-    -isystem "${LIBCXX_GENERATED_INCLUDE_DIR}"
-    -L${LIBCXX_LIBRARY_DIR}
-    -Wl,-rpath,${LIBCXX_LIBRARY_DIR}
-    ${SANITIZER_FLAGS}
-    )
-if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-  list(APPEND BENCHMARK_COMPILE_FLAGS
-    -isystem "${LIBCXX_GENERATED_INCLUDE_TARGET_DIR}")
-endif()
-if (DEFINED LIBCXX_CXX_ABI_LIBRARY_PATH)
-  list(APPEND BENCHMARK_COMPILE_FLAGS
-          -L${LIBCXX_CXX_ABI_LIBRARY_PATH}
-          -Wl,-rpath,${LIBCXX_CXX_ABI_LIBRARY_PATH})
-endif()
-split_list(BENCHMARK_COMPILE_FLAGS)
-
-set(BENCHMARK_CXX_LIBRARIES)
-list(APPEND BENCHMARK_CXX_LIBRARIES c++)
-if (NOT LIBCXX_ENABLE_SHARED)
-  list(APPEND BENCHMARK_CXX_LIBRARIES c++abi)
-endif()
-
-ExternalProject_Add(google-benchmark
-        EXCLUDE_FROM_ALL ON
-        DEPENDS cxx cxx-headers
-        PREFIX google-benchmark
-        SOURCE_DIR ${LLVM_THIRD_PARTY_DIR}/benchmark
-        INSTALL_DIR ${CMAKE_CURRENT_BINARY_DIR}/google-benchmark
-        CMAKE_CACHE_ARGS
-          -DCMAKE_C_COMPILER:FILEPATH=${CMAKE_C_COMPILER}
-          -DCMAKE_CXX_COMPILER:FILEPATH=${CMAKE_CXX_COMPILER}
-          -DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}
-          -DCMAKE_BUILD_TYPE:STRING=RELEASE
-          -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
-          -DCMAKE_CXX_FLAGS:STRING=${BENCHMARK_COMPILE_FLAGS}
-          -DBENCHMARK_USE_LIBCXX:BOOL=ON
-          -DBENCHMARK_ENABLE_TESTING:BOOL=OFF
-          -DBENCHMARK_CXX_LIBRARIES:STRING=${BENCHMARK_CXX_LIBRARIES})
-
-add_dependencies(cxx-test-depends google-benchmark)
diff --git a/libcxx/test/configs/cmake-bridge.cfg.in b/libcxx/test/configs/cmake-bridge.cfg.in
index 20b7c1e9bc357..1207c25cd7c9c 100644
--- a/libcxx/test/configs/cmake-bridge.cfg.in
+++ b/libcxx/test/configs/cmake-bridge.cfg.in
@@ -33,5 +33,4 @@ config.substitutions.append(('%{target-include-dir}', '@LIBCXX_TESTING_INSTALL_P
 config.substitutions.append(('%{lib-dir}', '@LIBCXX_TESTING_INSTALL_PREFIX@/@LIBCXX_INSTALL_LIBRARY_DIR@'))
 config.substitutions.append(('%{module-dir}', '@LIBCXX_TESTING_INSTALL_PREFIX@/@LIBCXX_INSTALL_MODULES_DIR@'))
 config.substitutions.append(('%{test-tools-dir}', '@LIBCXX_TEST_TOOLS_PATH@'))
-config.substitutions.append(('%{benchmark_flags}', '-I @LIBCXX_BINARY_DIR@/test/benchmarks/google-benchmark/include -L @LIBCXX_BINARY_DIR@/test/benchmarks/google-benchmark/lib -L @LIBCXX_BINARY_DIR@/test/benchmarks/google-benchmark/lib64 -l benchmark'))
 config.substitutions.append(("%{python}", shlex.quote(sys.executable)))
diff --git a/libcxx/utils/libcxx/test/config.py b/libcxx/utils/libcxx/test/config.py
index 00fab6a73ba68..7f3e6383599ca 100644
--- a/libcxx/utils/libcxx/test/config.py
+++ b/libcxx/utils/libcxx/test/config.py
@@ -51,7 +51,7 @@ def configure(parameters, features, config, lit_config):
             )
 
     # Print the basic substitutions
-    for sub in ("%{cxx}", "%{flags}", "%{compile_flags}", "%{link_flags}", "%{benchmark_flags}", "%{exec}"):
+    for sub in ("%{cxx}", "%{flags}", "%{compile_flags}", "%{link_flags}", "%{exec}"):
         note("Using {} substitution: '{}'".format(sub, _getSubstitution(sub, config)))
 
     # Print all available features
diff --git a/libcxx/utils/libcxx/test/format.py b/libcxx/utils/libcxx/test/format.py
index 76e9115295b99..ee63cdf5968e4 100644
--- a/libcxx/utils/libcxx/test/format.py
+++ b/libcxx/utils/libcxx/test/format.py
@@ -31,7 +31,7 @@ def _getTempPaths(test):
 
 def _checkBaseSubstitutions(substitutions):
     substitutions = [s for (s, _) in substitutions]
-    for s in ["%{cxx}", "%{compile_flags}", "%{link_flags}", "%{benchmark_flags}", "%{flags}", "%{exec}"]:
+    for s in ["%{cxx}", "%{compile_flags}", "%{link_flags}", "%{flags}", "%{exec}"]:
         assert s in substitutions, "Required substitution {} was not provided".format(s)
 
 def _executeScriptInternal(test, litConfig, commands):
@@ -231,10 +231,6 @@ class CxxStandardLibraryTest(lit.formats.FileBasedTest):
         %{compile_flags}   - Flags to use when compiling a test case
         %{link_flags}      - Flags to use when linking a test case
         %{flags}           - Flags to use either when compiling or linking a test case
-        %{benchmark_flags} - Flags to use when compiling benchmarks. These flags should provide access to
-                             GoogleBenchmark but shouldn't hardcode any optimization level or other settings,
-                             since the benchmarks should be run under the same configuration as the rest of
-                             the test suite.
         %{exec}            - A command to prefix the execution of executables
 
     Note that when building an executable (as opposed to only compiling a source
@@ -355,8 +351,23 @@ def execute(self, test, litConfig):
                         test.getFullName()
                     ),
                 )
+            # TODO: %{libcxx-dir} is not a base substitution
+            # TODO: We're building Google Benchmark for every test, which is super wasteful
+            configure = ['cmake', '-S', '%{libcxx-dir}/../third-party/benchmark', '-B', '%T/gbench-build']
+            configure += ['-D', 'CMAKE_INSTALL_PREFIX=%T/gbench']
+            configure += ['-D', 'CMAKE_CXX_COMPILER=%{cxx}']
+            configure += ['-D', 'CMAKE_BUILD_TYPE=Release']
+            configure += ['-D', 'CMAKE_CXX_FLAGS="%{flags} %{compile_flags} %{link_flags} -Wno-error"']
+            configure += ['-D', 'BENCHMARK_ENABLE_TESTING=OFF']
+            configure += ['-D', 'BENCHMARK_ENABLE_WERROR=OFF']
+            configure += ['-D', 'BENCHMARK_INSTALL_DOCS=OFF']
+            build = ['cmake', '--build', '%T/gbench-build', '--target', 'install']
+
             steps = [
-                "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{benchmark_flags} %{link_flags} -o %t.exe",
+                "rm -rf %T/gbench %T/gbench-build",
+                "%dbg(CONFIGURING GBENCH) " + " ".join(configure),
+                "%dbg(BUILDING GBENCH) " + " ".join(build),
+                "%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{link_flags} -I %T/gbench/include -L %T/gbench/lib -l benchmark -o %t.exe",
             ]
             if "enable-benchmarks=run" in test.config.available_features:
                 steps += ["%dbg(EXECUTED AS) %{exec} %t.exe --benchmark_out=%{temp}/benchmark-result.json --benchmark_out_format=json"]
diff --git a/libcxxabi/test/configs/cmake-bridge.cfg.in b/libcxxabi/test/configs/cmake-bridge.cfg.in
index f81dd8afb1091..a2fa847f2d6c6 100644
--- a/libcxxabi/test/configs/cmake-bridge.cfg.in
+++ b/libcxxabi/test/configs/cmake-bridge.cfg.in
@@ -34,7 +34,6 @@ config.substitutions.append(('%{include}', '@LIBCXXABI_TESTING_INSTALL_PREFIX@/i
 config.substitutions.append(('%{cxx-include}', '@LIBCXXABI_TESTING_INSTALL_PREFIX@/@LIBCXXABI_INSTALL_INCLUDE_DIR@'))
 config.substitutions.append(('%{cxx-target-include}', '@LIBCXXABI_TESTING_INSTALL_PREFIX@/@LIBCXXABI_INSTALL_INCLUDE_TARGET_DIR@'))
 config.substitutions.append(('%{lib}', '@LIBCXXABI_TESTING_INSTALL_PREFIX@/@LIBCXXABI_INSTALL_LIBRARY_DIR@'))
-config.substitutions.append(('%{benchmark_flags}', ''))
 
 if @LIBCXXABI_USE_LLVM_UNWINDER@:
     config.substitutions.append(('%{maybe-include-libunwind}', '-I "@LIBCXXABI_LIBUNWIND_INCLUDES_INTERNAL@"'))
diff --git a/libunwind/test/configs/cmake-bridge.cfg.in b/libunwind/test/configs/cmake-bridge.cfg.in
index e40497bfa9976..a2cf4f20a11ef 100644
--- a/libunwind/test/configs/cmake-bridge.cfg.in
+++ b/libunwind/test/configs/cmake-bridge.cfg.in
@@ -33,7 +33,6 @@ if not @LIBUNWIND_ENABLE_THREADS@:
 config.substitutions.append(('%{install-prefix}', '@LIBUNWIND_TESTING_INSTALL_PREFIX@'))
 config.substitutions.append(('%{include}', '@LIBUNWIND_TESTING_INSTALL_PREFIX@/include'))
 config.substitutions.append(('%{lib}', '@LIBUNWIND_TESTING_INSTALL_PREFIX@/@LIBUNWIND_INSTALL_LIBRARY_DIR@'))
-config.substitutions.append(('%{benchmark_flags}', ''))
 
 # Check for objcopy tools
 objcopy_path = which('llvm-objcopy', '@LLVM_BUILD_BINARY_DIR@/bin')
diff --git a/third-party/benchmark/CMakeLists.txt b/third-party/benchmark/CMakeLists.txt
index d9bcc6a4939be..b4ecd2cea02e4 100644
--- a/third-party/benchmark/CMakeLists.txt
+++ b/third-party/benchmark/CMakeLists.txt
@@ -197,8 +197,8 @@ else()
     # Disable warning when compiling tests as gtest does not use 'override'.
     add_cxx_compiler_flag(-Wsuggest-override)
   endif()
-  add_cxx_compiler_flag(-pedantic)
-  add_cxx_compiler_flag(-pedantic-errors)
+  # add_cxx_compiler_flag(-pedantic)
+  # add_cxx_compiler_flag(-pedantic-errors)
   add_cxx_compiler_flag(-Wshorten-64-to-32)
   add_cxx_compiler_flag(-fstrict-aliasing)
   # Disable warnings regarding deprecated parts of the library while building



More information about the cfe-commits mailing list