[llvm-branch-commits] [libunwind] 45bc9c1 - Revert "[libc++] Build GoogleBenchmark directly from Lit (#224192)"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Sep 23 00:30:42 PDT 2026
Author: Haowei
Date: 2026-09-23T00:30:36-07:00
New Revision: 45bc9c1acced1f6dfb20daf41a475433572dda8e
URL: https://github.com/llvm/llvm-project/commit/45bc9c1acced1f6dfb20daf41a475433572dda8e
DIFF: https://github.com/llvm/llvm-project/commit/45bc9c1acced1f6dfb20daf41a475433572dda8e.diff
LOG: Revert "[libc++] Build GoogleBenchmark directly from Lit (#224192)"
This reverts commit 1bfe9893f3dc12f1c0f9546564519f02601b2192.
Added:
libcxx/test/benchmarks/CMakeLists.txt
Modified:
libcxx/test/CMakeLists.txt
libcxx/test/configs/harness-configuration.cfg.in
libcxx/utils/libcxx/test/config.py
libcxx/utils/libcxx/test/format.py
libcxxabi/test/configs/cmake-bridge.cfg.in
libunwind/test/configs/cmake-bridge.cfg.in
Removed:
libcxx/test/benchmarks/lit.local.cfg
libcxx/utils/libcxx/test/googlebenchmark.py
################################################################################
diff --git a/libcxx/test/CMakeLists.txt b/libcxx/test/CMakeLists.txt
index 85fa6aacc7796f..8fd34c086a9928 100644
--- a/libcxx/test/CMakeLists.txt
+++ b/libcxx/test/CMakeLists.txt
@@ -26,6 +26,7 @@ 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
new file mode 100644
index 00000000000000..b3f881a008b808
--- /dev/null
+++ b/libcxx/test/benchmarks/CMakeLists.txt
@@ -0,0 +1,48 @@
+#==============================================================================
+# 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)
+ 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/benchmarks/lit.local.cfg b/libcxx/test/benchmarks/lit.local.cfg
deleted file mode 100644
index 07a15e4ae5df95..00000000000000
--- a/libcxx/test/benchmarks/lit.local.cfg
+++ /dev/null
@@ -1,11 +0,0 @@
-# Build the GoogleBenchmark library using the current Lit configuration so
-# that benchmarks can link against it.
-
-import libcxx.test.googlebenchmark
-
-if "enable-benchmarks=no" in config.available_features:
- config.substitutions.append(("%{benchmark_flags}", ""))
-else:
- config.substitutions.append(
- ("%{benchmark_flags}", libcxx.test.googlebenchmark.prepare(config, lit_config))
- )
diff --git a/libcxx/test/configs/harness-configuration.cfg.in b/libcxx/test/configs/harness-configuration.cfg.in
index fab0ee69255014..c527d60c64af5d 100644
--- a/libcxx/test/configs/harness-configuration.cfg.in
+++ b/libcxx/test/configs/harness-configuration.cfg.in
@@ -26,4 +26,5 @@ config.test_exec_root = os.path.join('@LIBCXX_BINARY_DIR@', 'test')
# Add substitutions for bootstrapping the test suite configuration
config.substitutions.append(('%{libcxx-dir}', '@LIBCXX_SOURCE_DIR@'))
+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 c71e81cf9573ac..fd6f1bf5accd67 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}", "%{exec}"):
+ for sub in ("%{cxx}", "%{flags}", "%{compile_flags}", "%{link_flags}", "%{benchmark_flags}", "%{exec}"):
debug("Using {} substitution: '{}'".format(sub, _getSubstitution(sub, config.substitutions)))
# Print all available features
diff --git a/libcxx/utils/libcxx/test/format.py b/libcxx/utils/libcxx/test/format.py
index 3e24e435e7c07b..2f449e234e6d5e 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}", "%{flags}", "%{exec}"]:
+ for s in ["%{cxx}", "%{compile_flags}", "%{link_flags}", "%{benchmark_flags}", "%{flags}", "%{exec}"]:
assert s in substitutions, "Required substitution {} was not provided".format(s)
def _executeScriptInternal(test, litConfig, commands):
@@ -235,6 +235,10 @@ 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,13 +359,6 @@ def execute(self, test, litConfig):
test.getFullName()
),
)
- substitutions = [s for (s, _) in test.config.substitutions]
- if "%{benchmark_flags}" not in substitutions:
- return lit.Test.Result(
- lit.Test.UNRESOLVED,
- "Test {} is a benchmark, but the %{{benchmark_flags}} substitution "
- "isn't provided by the configuration.".format(test.getFullName()),
- )
steps = [
"%dbg(COMPILED WITH) %{cxx} %s %{flags} %{compile_flags} %{benchmark_flags} %{link_flags} -o %t.exe",
]
diff --git a/libcxx/utils/libcxx/test/googlebenchmark.py b/libcxx/utils/libcxx/test/googlebenchmark.py
deleted file mode 100644
index b5fe708e67f8cc..00000000000000
--- a/libcxx/utils/libcxx/test/googlebenchmark.py
+++ /dev/null
@@ -1,223 +0,0 @@
-# ===----------------------------------------------------------------------===##
-#
-# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-# See https://llvm.org/LICENSE.txt for license information.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-#
-# ===----------------------------------------------------------------------===##
-
-"""
-Support for building GoogleBenchmark from the Lit configuration.
-
-The benchmarks in the test suite are linked against GoogleBenchmark, which must be
-built with the same Standard Library (and more generally with the same ABI-affecting
-flags) as the benchmarks themselves. This allows building GoogleBenchmark on-demand
-from Lit using the flags of the configuration being tested.
-
-The result is cached inside the build directory so that subsequent invocations are
-cheap.
-"""
-
-import hashlib
-import os
-import shlex
-import subprocess
-
-import lit.TestRunner
-
-import libcxx.test.config
-import libcxx.test.dsl
-
-THIS_FILE = os.path.abspath(__file__)
-LIBCXX_UTILS = os.path.dirname(os.path.dirname(os.path.dirname(THIS_FILE)))
-MONOREPO_ROOT = os.path.dirname(os.path.dirname(LIBCXX_UTILS))
-SOURCE_DIR = os.path.join(MONOREPO_ROOT, "third-party", "benchmark")
-
-# Flags used by the test suite that must not be used when building GoogleBenchmark.
-# Anything that isn't listed here is forwarded verbatim.
-#
-# -Werror
-# Avoid failing GoogleBenchmark's build due to warnings.
-# -D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER
-# Only relevant when testing libc++ itself.
-# -fmodules, -fcxx-modules, -fmodules-cache-path=
-# Modules are irrelevant when building a third-party static library, and sharing a
-# module cache with the test suite is undesirable.
-# -std=
-# GoogleBenchmark sets CMAKE_CXX_STANDARD itself and requires C++17.
-_DROPPED_FLAGS = {
- "-Werror",
- "-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER",
- "-fmodules",
- "-fcxx-modules",
-}
-
-_DROPPED_FLAG_PREFIXES = (
- "-std=",
- "-fmodules-cache-path=",
-)
-
-# Flags that are dropped along with the '-Xclang' that introduces them.
-_DROPPED_XCLANG_FLAGS = {
- "-fmodules-local-submodule-visibility",
-}
-
-
-def _expand(config, string):
- """
- Expand the Lit substitutions in the given string, recursively.
- """
- (expanded,) = lit.TestRunner.applySubstitutions(
- [string],
- config.substitutions,
- recursion_limit=config.recursiveExpansionLimit,
- )
- return expanded
-
-
-def _filterFlags(flags):
- """
- Remove the flags that must not be used when building GoogleBenchmark.
- """
- result = []
- flags = iter(flags)
- for flag in flags:
- if flag == "-Xclang":
- arg = next(flags, None)
- if arg is None:
- result.append(flag)
- elif arg not in _DROPPED_XCLANG_FLAGS:
- result += [flag, arg]
- elif flag not in _DROPPED_FLAGS and not flag.startswith(_DROPPED_FLAG_PREFIXES):
- result.append(flag)
- return result
-
-
-def _getFlags(config, substitutions):
- """
- Return the flags contained in the given substitutions, based on the flags used by the
- configuration under test.
- """
- flags = []
- for substitution in substitutions:
- expanded = _expand(config, _getSubstitution(substitution, config))
- flags += shlex.split(expanded)
- return _filterFlags(flags)
-
-
-def _splitLibraries(flags):
- """
- Split the given link flags into (flags, libraries), where libraries contains the
- name of the libraries that were being linked against.
-
- We can't simply hand the libraries over to CMake as part of CMAKE_CXX_FLAGS, since
- CMake puts those flags before the object files on the link line.
- """
- result = []
- libraries = []
- flags = iter(flags)
- for flag in flags:
- if flag == "-l":
- library = next(flags, None)
- if library is None:
- result.append(flag)
- else:
- libraries.append(library)
- elif flag.startswith("-l"):
- libraries.append(flag[len("-l") :])
- else:
- result.append(flag)
- return (result, libraries)
-
-
-def _getSubstitution(substitution, config):
- return libcxx.test.config._getSubstitution(substitution, config.substitutions)
-
-
-def _fingerprint(config, flags, libraries):
- """
- Return an opaque value identifying this GoogleBenchmark build.
-
- This changes whenever the compiler is rebuilt or whenever the flags used to build
- GoogleBenchmark change.
- """
- compiler = libcxx.test.dsl._compilerFingerprint(config)
- return hashlib.sha256(repr((compiler, flags, libraries)).encode()).hexdigest()[:16]
-
-
-def _run(litConfig, what, command, cwd):
- result = subprocess.run(
- command,
- cwd=cwd,
- stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT,
- universal_newlines=True,
- )
- if result.returncode != 0:
- pretty = " ".join(shlex.quote(arg) for arg in command)
- litConfig.fatal(
- "Failed to {} GoogleBenchmark.\n"
- "Command was:\n{}\n\n"
- "Output was:\n{}".format(what, pretty, result.stdout)
- )
-
-
-def prepare(config, litConfig):
- """
- Make GoogleBenchmark available to the test suite and return the flags required to
- build the benchmarks against it.
-
- GoogleBenchmark is built using the same flags as the rest of the test suite, and the
- result is cached inside the build directory. The cache is keyed on the flags being
- used, so
diff erent Lit configurations do not interfere with each other.
- """
- flags, libraries = _splitLibraries(
- _getFlags(config, ("%{flags}", "%{compile_flags}", "%{link_flags}"))
- )
- root = os.path.join(config.test_exec_root, "__gbench__")
- prefix = os.path.join(root, _fingerprint(config, flags, libraries))
- buildDir = os.path.join(prefix, "build")
- installDir = os.path.join(prefix, "install")
- os.makedirs(root, exist_ok=True)
-
- cmake = os.environ.get("CMAKE", "cmake")
-
- if not os.path.exists(os.path.join(buildDir, "CMakeCache.txt")):
- litConfig.note("Configuring GoogleBenchmark in {}".format(buildDir))
- compiler = _expand(config, _getSubstitution("%{cxx}", config))
- _run(
- litConfig,
- "configure",
- [
- cmake,
- "-S", SOURCE_DIR,
- "-B", buildDir,
- "-DCMAKE_BUILD_TYPE=Release",
- "-DCMAKE_CXX_COMPILER={}".format(compiler),
- "-DCMAKE_CXX_FLAGS={}".format(" ".join(flags)),
- # Set CMAKE_EXE_LINKER_FLAGS in addition to BENCHMARK_CXX_LIBRARIES since we
- # need CMake's own probe executables to have the right linker flags.
- "-DCMAKE_EXE_LINKER_FLAGS={}".format(" ".join("-l{}".format(lib) for lib in libraries)),
- "-DCMAKE_INSTALL_PREFIX={}".format(installDir),
- "-DCMAKE_INSTALL_LIBDIR=lib",
- "-DBENCHMARK_CXX_LIBRARIES={}".format(";".join(libraries)),
- "-DBENCHMARK_ENABLE_TESTING=OFF",
- "-DBENCHMARK_ENABLE_WERROR=OFF",
- "-DBENCHMARK_INSTALL_DOCS=OFF",
- ],
- cwd=root,
- )
-
- # Always build: GoogleBenchmark is compiled against the headers of the library
- # under test, so it must be rebuilt when those change. This is a no-op when
- # nothing changed.
- _run(
- litConfig,
- "build",
- [cmake, "--build", buildDir, "--target", "install", "--parallel", str(os.cpu_count() or 1)],
- cwd=root,
- )
-
- include = os.path.join(installDir, "include")
- lib = os.path.join(installDir, "lib")
- return "-isystem {} -L {} -l benchmark".format(include, lib)
diff --git a/libcxxabi/test/configs/cmake-bridge.cfg.in b/libcxxabi/test/configs/cmake-bridge.cfg.in
index a2fa847f2d6c66..f81dd8afb10915 100644
--- a/libcxxabi/test/configs/cmake-bridge.cfg.in
+++ b/libcxxabi/test/configs/cmake-bridge.cfg.in
@@ -34,6 +34,7 @@ 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 98e7d8d653f5dc..ed0b2afbc0c0d2 100644
--- a/libunwind/test/configs/cmake-bridge.cfg.in
+++ b/libunwind/test/configs/cmake-bridge.cfg.in
@@ -45,6 +45,7 @@ config.substitutions.append(('%{libcxx}', '@LIBUNWIND_LIBCXX_PATH@'))
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')
More information about the llvm-branch-commits
mailing list