[Openmp-commits] [compiler-rt] [libclc] [libcxx] [libcxxabi] [libunwind] [llvm] [openmp] [CMake] Remove the use of AddLLVM from runtimes (PR #217502)

Petr Hosek via Openmp-commits openmp-commits at lists.llvm.org
Sun Aug 23 16:44:57 PDT 2026


https://github.com/petrhosek updated https://github.com/llvm/llvm-project/pull/217502

>From a6090bf4ee29d8c06803e894065b88f0d54c0467 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Thu, 20 Aug 2026 01:36:18 +0000
Subject: [PATCH 1/3] [CMake] Remove the use of AddLLVM from runtimes

AddLLVM primarily contains utility functions needed for LLVM based
tools, but runtimes are not LLVM tools. The only part of AddLLVM that's
relevant to runtimes is the support for lit. This change extracts the
lit support into a new top-level AddLit module and replaces all uses of
AddLLVM in runtimes with this new module.
---
 cmake/Modules/AddLit.cmake                    | 427 +++++++++++++++++
 cmake/Modules/GetSubprojectTitle.cmake        |  14 +
 compiler-rt/CMakeLists.txt                    |   2 +-
 .../CompilerRTMockLLVMCMakeConfig.cmake       |   2 +-
 compiler-rt/cmake/config-ix.cmake             |   1 -
 compiler-rt/test/CMakeLists.txt               |   2 +-
 compiler-rt/unittests/CMakeLists.txt          |   2 +-
 libclc/CMakeLists.txt                         |  33 +-
 libcxx/test/CMakeLists.txt                    |   2 +-
 libcxxabi/test/CMakeLists.txt                 |   2 +-
 libunwind/test/CMakeLists.txt                 |   2 +-
 llvm/cmake/modules/AddLLVM.cmake              | 442 +-----------------
 llvm/cmake/modules/AddOCaml.cmake             |   1 +
 llvm/cmake/modules/AddSphinxTarget.cmake      |   1 +
 llvm/cmake/modules/CMakeLists.txt             |   8 +
 llvm/cmake/modules/CrossCompile.cmake         |   1 +
 .../modules/LLVMDistributionSupport.cmake     |   1 +
 llvm/cmake/modules/TableGen.cmake             |   1 +
 llvm/runtimes/CMakeLists.txt                  |   7 +
 runtimes/CMakeLists.txt                       |   2 +-
 20 files changed, 482 insertions(+), 471 deletions(-)
 create mode 100644 cmake/Modules/AddLit.cmake
 create mode 100644 cmake/Modules/GetSubprojectTitle.cmake

diff --git a/cmake/Modules/AddLit.cmake b/cmake/Modules/AddLit.cmake
new file mode 100644
index 0000000000000..2595ee504cb8f
--- /dev/null
+++ b/cmake/Modules/AddLit.cmake
@@ -0,0 +1,427 @@
+include(GetSubprojectTitle)
+
+
+# This function canonicalize the CMake variables passed by names
+# from CMake boolean to 0/1 suitable for passing into Python or C++,
+# in place.
+function(llvm_canonicalize_cmake_booleans)
+  foreach(var ${ARGN})
+    if(${var})
+      set(${var} 1 PARENT_SCOPE)
+    else()
+      set(${var} 0 PARENT_SCOPE)
+    endif()
+  endforeach()
+endfunction(llvm_canonicalize_cmake_booleans)
+
+macro(set_llvm_build_mode)
+  # Configuration-time: See Unit/lit.site.cfg.in
+  if (CMAKE_CFG_INTDIR STREQUAL ".")
+    set(LLVM_BUILD_MODE ".")
+  else ()
+    set(LLVM_BUILD_MODE "%(build_mode)s")
+  endif ()
+endmacro()
+
+# Takes a list of path names in pathlist and a base directory, and returns
+# a list of paths relative to the base directory in out_pathlist.
+# Paths that are on a different drive than the basedir (on Windows) or that
+# contain symlinks are returned absolute.
+# Use with LLVM_LIT_PATH_FUNCTION below.
+function(make_paths_relative out_pathlist basedir pathlist)
+  # Passing ARG_PATH_VALUES as-is to execute_process() makes cmake strip
+  # empty list entries. So escape the ;s in the list and do the splitting
+  # ourselves. cmake has no relpath function, so use Python for that.
+  string(REPLACE ";" "\\;" pathlist_escaped "${pathlist}")
+  execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "\n
+import os, sys\n
+base = sys.argv[1]
+def haslink(p):\n
+    if not p or p == os.path.dirname(p): return False\n
+    return os.path.islink(p) or haslink(os.path.dirname(p))\n
+def relpath(p):\n
+    if not p: return ''\n
+    if os.path.splitdrive(p)[0] != os.path.splitdrive(base)[0]: return p\n
+    if haslink(p) or haslink(base): return p\n
+    return os.path.relpath(p, base)\n
+if len(sys.argv) < 3: sys.exit(0)\n
+sys.stdout.write(';'.join(relpath(p) for p in sys.argv[2].split(';')))"
+    ${basedir}
+    ${pathlist_escaped}
+    OUTPUT_VARIABLE pathlist_relative
+    ERROR_VARIABLE error
+    RESULT_VARIABLE result)
+  if (NOT result EQUAL 0)
+    message(FATAL_ERROR "make_paths_relative() failed due to error '${result}', with stderr\n${error}")
+  endif()
+  set(${out_pathlist} "${pathlist_relative}" PARENT_SCOPE)
+endfunction()
+
+# Converts a file that's relative to the current python file to an absolute
+# path. Since this uses __file__, it has to be emitted into python files that
+# use it and can't be in a lit module. Use with make_paths_relative().
+string(CONCAT LLVM_LIT_PATH_FUNCTION
+  "# Allow generated file to be relocatable.\n"
+  "import os\n"
+  "import platform\n"
+  "def path(p):\n"
+  "    if not p: return ''\n"
+  "    # Follows lit.util.abs_path_preserve_drive, which cannot be imported here.\n"
+  "    if platform.system() == 'Windows':\n"
+  "        return os.path.abspath(os.path.join(os.path.dirname(__file__), p))\n"
+  "    else:\n"
+  "        return os.path.realpath(os.path.join(os.path.dirname(__file__), p))\n"
+  )
+
+# This function provides an automatic way to 'configure'-like generate a file
+# based on a set of common and custom variables, specifically targeting the
+# variables needed for the 'lit.site.cfg' files. This function bundles the
+# common variables that any Lit instance is likely to need, and custom
+# variables can be passed in.
+# The keyword PATHS is followed by a list of cmake variable names that are
+# mentioned as `path("@varname@")` in the lit.cfg.py.in file. Variables in that
+# list are treated as paths that are relative to the directory the generated
+# lit.cfg.py file is in, and the `path()` function converts the relative
+# path back to absolute form. This makes it possible to move a build directory
+# containing lit.cfg.py files from one machine to another.
+function(configure_lit_site_cfg site_in site_out)
+  cmake_parse_arguments(ARG "" "" "MAIN_CONFIG;PATHS" ${ARGN})
+
+  if ("${ARG_MAIN_CONFIG}" STREQUAL "")
+    get_filename_component(INPUT_DIR ${site_in} DIRECTORY)
+    set(ARG_MAIN_CONFIG "${INPUT_DIR}/lit.cfg")
+  endif()
+
+  foreach(c ${LLVM_TARGETS_TO_BUILD})
+    set(TARGETS_BUILT "${TARGETS_BUILT} ${c}")
+  endforeach(c)
+  set(TARGETS_TO_BUILD ${TARGETS_BUILT})
+
+  set(SHLIBEXT "${LTDL_SHLIB_EXT}")
+
+  set_llvm_build_mode()
+
+  # For standalone builds of subprojects, these might not be the build tree but
+  # a provided binary tree.
+  set(LLVM_SOURCE_DIR ${LLVM_MAIN_SRC_DIR})
+  set(LLVM_BINARY_DIR ${LLVM_BINARY_DIR})
+  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" LLVM_TOOLS_DIR "${LLVM_TOOLS_BINARY_DIR}")
+  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" LLVM_LIBS_DIR  "${LLVM_LIBRARY_DIR}")
+  # Like LLVM_{TOOLS,LIBS}_DIR, but pointing at the build tree.
+  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" CURRENT_TOOLS_DIR "${LLVM_RUNTIME_OUTPUT_INTDIR}")
+  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" CURRENT_LIBS_DIR  "${LLVM_LIBRARY_OUTPUT_INTDIR}")
+  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" SHLIBDIR "${LLVM_SHLIB_OUTPUT_INTDIR}")
+
+  # FIXME: "ENABLE_SHARED" doesn't make sense, since it is used just for
+  # plugins. We may rename it.
+  if(LLVM_ENABLE_PLUGINS)
+    set(ENABLE_SHARED "1")
+  else()
+    set(ENABLE_SHARED "0")
+  endif()
+
+  if(LLVM_ENABLE_ASSERTIONS)
+    set(ENABLE_ASSERTIONS "1")
+  else()
+    set(ENABLE_ASSERTIONS "0")
+  endif()
+
+  set(HOST_OS ${CMAKE_SYSTEM_NAME})
+  set(HOST_ARCH ${CMAKE_SYSTEM_PROCESSOR})
+
+  set(HOST_CC "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}")
+  set(HOST_CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}")
+  set(HOST_LDFLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+
+  string(CONCAT LIT_SITE_CFG_IN_HEADER
+    "# Autogenerated from ${site_in}\n# Do not edit!\n\n"
+    "${LLVM_LIT_PATH_FUNCTION}"
+    )
+
+  # Override config_target_triple (and the env)
+  if(LLVM_TARGET_TRIPLE_ENV)
+    # This is expanded into the heading.
+    string(CONCAT LIT_SITE_CFG_IN_HEADER "${LIT_SITE_CFG_IN_HEADER}"
+      "import os\n"
+      "target_env = \"${LLVM_TARGET_TRIPLE_ENV}\"\n"
+      "config.target_triple = config.environment[target_env] = os.environ.get(target_env, \"${LLVM_TARGET_TRIPLE}\")\n"
+      )
+
+    # This is expanded to; config.target_triple = ""+config.target_triple+""
+    set(LLVM_TARGET_TRIPLE "\"+config.target_triple+\"")
+  endif()
+
+  if (ARG_PATHS)
+    # Walk ARG_PATHS and collect the current value of the variables in there.
+    # list(APPEND) ignores empty elements exactly if the list is empty,
+    # so start the list with a dummy element and drop it, to make sure that
+    # even empty values make it into the values list.
+    set(ARG_PATH_VALUES "dummy")
+    foreach(path ${ARG_PATHS})
+      list(APPEND ARG_PATH_VALUES "${${path}}")
+    endforeach()
+    list(REMOVE_AT ARG_PATH_VALUES 0)
+
+    get_filename_component(OUTPUT_DIR ${site_out} DIRECTORY)
+    make_paths_relative(
+        ARG_PATH_VALUES_RELATIVE "${OUTPUT_DIR}" "${ARG_PATH_VALUES}")
+
+    list(LENGTH ARG_PATHS len_paths)
+    list(LENGTH ARG_PATH_VALUES len_path_values)
+    list(LENGTH ARG_PATH_VALUES_RELATIVE len_path_value_rels)
+    if ((NOT ${len_paths} EQUAL ${len_path_values}) OR
+        (NOT ${len_paths} EQUAL ${len_path_value_rels}))
+      message(SEND_ERROR "PATHS lengths got confused")
+    endif()
+
+    # Transform variables mentioned in ARG_PATHS to relative paths for
+    # the configure_file() call. Variables are copied to subscopeds by cmake,
+    # so this only modifies the local copy of the variables.
+    math(EXPR arg_path_limit "${len_paths} - 1")
+    foreach(i RANGE ${arg_path_limit})
+      list(GET ARG_PATHS ${i} val1)
+      list(GET ARG_PATH_VALUES_RELATIVE ${i} val2)
+      set(${val1} ${val2})
+    endforeach()
+  endif()
+
+  configure_file(${site_in} ${site_out} @ONLY)
+
+  if (EXISTS "${ARG_MAIN_CONFIG}")
+    # Remember main config / generated site config for llvm-lit.in.
+    get_property(LLVM_LIT_CONFIG_FILES GLOBAL PROPERTY LLVM_LIT_CONFIG_FILES)
+    list(APPEND LLVM_LIT_CONFIG_FILES "${ARG_MAIN_CONFIG}" "${site_out}")
+    set_property(GLOBAL PROPERTY LLVM_LIT_CONFIG_FILES ${LLVM_LIT_CONFIG_FILES})
+  endif()
+endfunction()
+
+function(dump_all_cmake_variables)
+  get_cmake_property(_variableNames VARIABLES)
+  foreach (_variableName ${_variableNames})
+    message(STATUS "${_variableName}=${${_variableName}}")
+  endforeach()
+endfunction()
+
+function(get_llvm_lit_path base_dir file_name)
+  cmake_parse_arguments(ARG "ALLOW_EXTERNAL" "" "" ${ARGN})
+
+  if (ARG_ALLOW_EXTERNAL)
+    set (LLVM_EXTERNAL_LIT "" CACHE STRING "Command used to spawn lit")
+    if ("${LLVM_EXTERNAL_LIT}" STREQUAL "")
+      set(LLVM_EXTERNAL_LIT "${LLVM_DEFAULT_EXTERNAL_LIT}")
+    endif()
+
+    if (NOT "${LLVM_EXTERNAL_LIT}" STREQUAL "")
+      if (EXISTS ${LLVM_EXTERNAL_LIT})
+        get_filename_component(LIT_FILE_NAME ${LLVM_EXTERNAL_LIT} NAME)
+        get_filename_component(LIT_BASE_DIR ${LLVM_EXTERNAL_LIT} DIRECTORY)
+        set(${file_name} ${LIT_FILE_NAME} PARENT_SCOPE)
+        set(${base_dir} ${LIT_BASE_DIR} PARENT_SCOPE)
+        return()
+      elseif (NOT DEFINED CACHE{LLVM_EXTERNAL_LIT_MISSING_WARNED_ONCE})
+        message(WARNING "LLVM_EXTERNAL_LIT set to ${LLVM_EXTERNAL_LIT}, but the path does not exist.")
+        set(LLVM_EXTERNAL_LIT_MISSING_WARNED_ONCE YES CACHE INTERNAL "")
+      endif()
+    endif()
+  endif()
+
+  set(lit_file_name "llvm-lit")
+  if (CMAKE_HOST_WIN32 AND NOT CYGWIN)
+    # llvm-lit needs suffix.py for multiprocess to find a main module.
+    set(lit_file_name "${lit_file_name}.py")
+  endif ()
+  set(${file_name} ${lit_file_name} PARENT_SCOPE)
+
+  get_property(LLVM_LIT_BASE_DIR GLOBAL PROPERTY LLVM_LIT_BASE_DIR)
+  if (NOT "${LLVM_LIT_BASE_DIR}" STREQUAL "")
+    set(${base_dir} ${LLVM_LIT_BASE_DIR} PARENT_SCOPE)
+  endif()
+
+  # Allow individual projects to provide an override
+  if (NOT "${LLVM_LIT_OUTPUT_DIR}" STREQUAL "")
+    set(LLVM_LIT_BASE_DIR ${LLVM_LIT_OUTPUT_DIR})
+  elseif(NOT "${LLVM_RUNTIME_OUTPUT_INTDIR}" STREQUAL "")
+    set(LLVM_LIT_BASE_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
+  else()
+    set(LLVM_LIT_BASE_DIR "")
+  endif()
+
+  # Cache this so we don't have to do it again and have subsequent calls
+  # potentially disagree on the value.
+  set_property(GLOBAL PROPERTY LLVM_LIT_BASE_DIR ${LLVM_LIT_BASE_DIR})
+  set(${base_dir} ${LLVM_LIT_BASE_DIR} PARENT_SCOPE)
+endfunction()
+
+# A raw function to create a lit target. This is used to implement the testuite
+# management functions.
+function(add_lit_target target comment)
+  cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
+  set(LIT_ARGS "${ARG_ARGS} ${LLVM_LIT_ARGS}")
+  separate_arguments(LIT_ARGS)
+  if (NOT CMAKE_CFG_INTDIR STREQUAL ".")
+    list(APPEND LIT_ARGS --param build_mode=${CMAKE_CFG_INTDIR})
+  endif ()
+
+  # Get the path to the lit to *run* tests with.  This can be overriden by
+  # the user by specifying -DLLVM_EXTERNAL_LIT=<path-to-lit.py>
+  get_llvm_lit_path(
+    lit_base_dir
+    lit_file_name
+    ALLOW_EXTERNAL
+    )
+
+  set(LIT_COMMAND "${Python3_EXECUTABLE};${lit_base_dir}/${lit_file_name}")
+  list(APPEND LIT_COMMAND ${LIT_ARGS})
+  foreach(param ${ARG_PARAMS})
+    list(APPEND LIT_COMMAND --param ${param})
+  endforeach()
+  if (ARG_UNPARSED_ARGUMENTS)
+    add_custom_target(${target}
+      COMMAND ${LIT_COMMAND} ${ARG_UNPARSED_ARGUMENTS}
+      COMMENT "${comment}"
+      USES_TERMINAL
+      )
+  else()
+    add_custom_target(${target}
+      COMMAND ${CMAKE_COMMAND} -E echo "${target} does nothing, no tools built.")
+    message(STATUS "${target} does nothing.")
+  endif()
+  get_subproject_title(subproject_title)
+  set_target_properties(${target} PROPERTIES FOLDER "${subproject_title}/Tests")
+
+  if (ARG_DEPENDS)
+    add_dependencies(${target} ${ARG_DEPENDS})
+  endif()
+
+  # Tests should be excluded from "Build Solution".
+  set_target_properties(${target} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
+  set_target_properties(${target} PROPERTIES XCODE_GENERATE_SCHEME ON)
+endfunction()
+
+# Convert a target name like check-clang to a variable name like CLANG.
+function(umbrella_lit_testsuite_var target outvar)
+  if (NOT target MATCHES "^check-")
+    message(FATAL_ERROR "umbrella lit suites must be check-*, not '${target}'")
+  endif()
+  string(SUBSTRING "${target}" 6 -1 var)
+  string(REPLACE "-" "_" var ${var})
+  string(TOUPPER "${var}" var)
+  set(${outvar} "${var}" PARENT_SCOPE)
+endfunction()
+
+# Start recording all lit test suites for a combined 'check-foo' target.
+# The recording continues until umbrella_lit_testsuite_end() creates the target.
+function(umbrella_lit_testsuite_begin target)
+  umbrella_lit_testsuite_var(${target} name)
+  set_property(GLOBAL APPEND PROPERTY LLVM_LIT_UMBRELLAS ${name})
+endfunction()
+
+# Create a combined 'check-foo' target for a set of related test suites.
+# It runs all suites added since the matching umbrella_lit_testsuite_end() call.
+# Tests marked EXCLUDE_FROM_CHECK_ALL are not gathered.
+function(umbrella_lit_testsuite_end target)
+  umbrella_lit_testsuite_var(${target} name)
+
+  get_property(testsuites GLOBAL PROPERTY LLVM_${name}_LIT_TESTSUITES)
+  get_property(params GLOBAL PROPERTY LLVM_${name}_LIT_PARAMS)
+  get_property(depends GLOBAL PROPERTY LLVM_${name}_LIT_DEPENDS)
+  get_property(extra_args GLOBAL PROPERTY LLVM_${name}_LIT_EXTRA_ARGS)
+  # Additional test targets are not gathered, but may be set externally.
+  get_property(additional_test_targets
+               GLOBAL PROPERTY LLVM_${name}_ADDITIONAL_TEST_TARGETS)
+
+  string(TOLOWER ${name} name)
+  add_lit_target(${target}
+    "Running ${name} regression tests"
+    ${testsuites}
+    PARAMS ${params}
+    DEPENDS ${depends} ${additional_test_targets}
+    ARGS ${extra_args}
+    )
+endfunction()
+
+# A function to add a set of lit test suites to be driven through 'check-*' targets.
+function(add_lit_testsuite target comment)
+  cmake_parse_arguments(ARG "EXCLUDE_FROM_CHECK_ALL" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
+
+  # EXCLUDE_FROM_ALL excludes the test ${target} out of check-all.
+  if(NOT ARG_EXCLUDE_FROM_CHECK_ALL)
+    get_property(gather_names GLOBAL PROPERTY LLVM_LIT_UMBRELLAS)
+    foreach(name ${gather_names})
+    # Register the testsuites, params and depends for the umbrella check rule.
+      set_property(GLOBAL APPEND PROPERTY LLVM_${name}_LIT_TESTSUITES ${ARG_UNPARSED_ARGUMENTS})
+      set_property(GLOBAL APPEND PROPERTY LLVM_${name}_LIT_PARAMS ${ARG_PARAMS})
+      set_property(GLOBAL APPEND PROPERTY LLVM_${name}_LIT_DEPENDS ${ARG_DEPENDS})
+      set_property(GLOBAL APPEND PROPERTY LLVM_${name}_LIT_EXTRA_ARGS ${ARG_ARGS})
+    endforeach()
+  endif()
+
+  # Produce a specific suffixed check rule.
+  add_lit_target(${target} ${comment}
+    ${ARG_UNPARSED_ARGUMENTS}
+    PARAMS ${ARG_PARAMS}
+    DEPENDS ${ARG_DEPENDS}
+    ARGS ${ARG_ARGS}
+    )
+endfunction()
+
+function(add_lit_testsuites project directory)
+  if (NOT LLVM_ENABLE_IDE)
+    cmake_parse_arguments(ARG
+      "EXCLUDE_FROM_CHECK_ALL"
+      "FOLDER;BINARY_DIR"
+      "PARAMS;DEPENDS;ARGS;SKIP"
+      ${ARGN}
+      )
+
+    if (NOT ARG_FOLDER)
+      get_subproject_title(subproject_title)
+      set(ARG_FOLDER "${subproject_title}/Tests/LIT Testsuites")
+    endif()
+
+    # Search recursively for test directories by assuming anything not
+    # in a directory called Inputs contains tests.
+    file(GLOB_RECURSE to_process LIST_DIRECTORIES true ${directory}/*)
+    foreach(lit_suite ${to_process})
+      if(NOT IS_DIRECTORY ${lit_suite})
+        continue()
+      endif()
+      string(FIND ${lit_suite} Inputs is_inputs)
+      string(FIND ${lit_suite} Output is_output)
+      if (NOT (is_inputs EQUAL -1 AND is_output EQUAL -1))
+        continue()
+      endif()
+
+      # Create a check- target for the directory.
+      string(REPLACE "${directory}/" "" name_slash ${lit_suite})
+      set(_should_skip FALSE)
+      foreach(skip IN LISTS ARG_SKIP)
+        if(name_slash MATCHES "${skip}")
+          set(_should_skip TRUE)
+          break()
+        endif()
+      endforeach()
+      if (_should_skip)
+        continue()
+      endif()
+      if (name_slash)
+        set(filter ${name_slash})
+        string(REPLACE "/" "-" name_slash ${name_slash})
+        string(REPLACE "\\" "-" name_dashes ${name_slash})
+        string(TOLOWER "${project}-${name_dashes}" name_var)
+        set(lit_args ${lit_suite})
+        if (ARG_BINARY_DIR)
+          set(lit_args ${ARG_BINARY_DIR} --filter=${filter})
+        endif()
+        add_lit_target("check-${name_var}" "Running lit suite ${lit_suite}"
+          ${lit_args}
+          ${EXCLUDE_FROM_CHECK_ALL}
+          PARAMS ${ARG_PARAMS}
+          DEPENDS ${ARG_DEPENDS}
+          ARGS ${ARG_ARGS}
+        )
+        set_target_properties(check-${name_var} PROPERTIES FOLDER ${ARG_FOLDER})
+      endif()
+    endforeach()
+  endif()
+endfunction()
diff --git a/cmake/Modules/GetSubprojectTitle.cmake b/cmake/Modules/GetSubprojectTitle.cmake
new file mode 100644
index 0000000000000..00890f87d2d94
--- /dev/null
+++ b/cmake/Modules/GetSubprojectTitle.cmake
@@ -0,0 +1,14 @@
+# get_subproject_title(titlevar)
+#   Set ${outvar} to the title of the current LLVM subproject (Clang, MLIR ...)
+#
+# The title is set in the subproject's top-level using the variable
+# LLVM_SUBPROJECT_TITLE. If it does not exist, it is assumed it is LLVM itself.
+# The title is not semantically significant, but use to create folders in
+# CMake-generated IDE projects (Visual Studio/XCode).
+function(get_subproject_title outvar)
+  if (LLVM_SUBPROJECT_TITLE)
+    set(${outvar} "${LLVM_SUBPROJECT_TITLE}" PARENT_SCOPE)
+  else ()
+    set(${outvar} "LLVM" PARENT_SCOPE)
+  endif ()
+endfunction(get_subproject_title)
diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt
index 9e45a43b34287..95989bf20ed38 100644
--- a/compiler-rt/CMakeLists.txt
+++ b/compiler-rt/CMakeLists.txt
@@ -919,7 +919,7 @@ if(COMPILER_RT_INCLUDE_TESTS)
     # by specifying -DLLVM_EXTERNAL_LIT, but we generate it regardless.
     if (EXISTS ${LLVM_MAIN_SRC_DIR}/utils/llvm-lit)
       # Needed for lit support in standalone builds.
-      include(AddLLVM)
+      include(AddLit)
       add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/llvm-lit ${CMAKE_CURRENT_BINARY_DIR}/llvm-lit)
       # Ensure that the testsuite uses the local lit rather than
       # LLVM_INSTALL_DIR/bin/llvm-lit (which probably does not exist).
diff --git a/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake b/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake
index be14992b2944f..afce40f1e9077 100644
--- a/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake
+++ b/compiler-rt/cmake/Modules/CompilerRTMockLLVMCMakeConfig.cmake
@@ -76,5 +76,5 @@ endfunction()
 
 macro(compiler_rt_mock_llvm_cmake_config_include_cmake_files)
   # Some compiler-rt CMake code needs to call code in this file.
-  include("${LLVM_CMAKE_DIR}/AddLLVM.cmake")
+  include(AddLit)
 endmacro()
diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake
index 3b86ba26f8a84..02ca4be011579 100644
--- a/compiler-rt/cmake/config-ix.cmake
+++ b/compiler-rt/cmake/config-ix.cmake
@@ -1,5 +1,4 @@
 include(CMakePushCheckState)
-include(AddLLVM)
 include(CheckCCompilerFlag)
 include(CheckCXXCompilerFlag)
 include(CheckIncludeFiles)
diff --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt
index fa2847c1b7dd0..1e4bee6135e07 100644
--- a/compiler-rt/test/CMakeLists.txt
+++ b/compiler-rt/test/CMakeLists.txt
@@ -1,5 +1,5 @@
 # Needed for lit support in standalone builds.
-include(AddLLVM)
+include(AddLit)
 
 pythonize_bool(COMPILER_RT_TEST_STANDALONE_BUILD_LIBS)
 
diff --git a/compiler-rt/unittests/CMakeLists.txt b/compiler-rt/unittests/CMakeLists.txt
index 88f9865a6e7d7..b01354ca7655c 100644
--- a/compiler-rt/unittests/CMakeLists.txt
+++ b/compiler-rt/unittests/CMakeLists.txt
@@ -1,5 +1,5 @@
 # Needed for lit support in standalone builds.
-include(AddLLVM)
+include(AddLit)
 
 configure_compiler_rt_lit_site_cfg(
   ${CMAKE_CURRENT_SOURCE_DIR}/lit.common.unit.configured.in
diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
index 5829bd9b39eac..66d5d89debb11 100644
--- a/libclc/CMakeLists.txt
+++ b/libclc/CMakeLists.txt
@@ -56,13 +56,7 @@ if( LIBCLC_STANDALONE_BUILD OR CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DI
   set( LIBCLC_STANDALONE_BUILD TRUE )
 
   find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}")
-  include(AddLLVM)
-
-  foreach( tool IN ITEMS llvm-link opt )
-    find_program( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
-    set( ${tool}_exe ${LLVM_TOOL_${tool}} )
-    set( ${tool}_target )
-  endforeach()
+  include(AddLit)
 
   # Setup the paths where libclc runtimes should be stored.
   set( LIBCLC_OUTPUT_LIBRARY_DIR ${CMAKE_CURRENT_BINARY_DIR} )
@@ -82,9 +76,6 @@ else()
     set( PACKAGE_VERSION "${LLVM_PACKAGE_VERSION}" )
   endif()
 
-  get_host_tool_path( llvm-link LLVM_LINK llvm-link_exe llvm-link_target )
-  get_host_tool_path( opt OPT opt_exe opt_target )
-
   # Setup the paths where libclc runtimes should be stored. By default, in an
   # in-tree build we place the libraries in clang's resource driectory.
   include(GetClangResourceDir)
@@ -95,16 +86,20 @@ else()
   )
 endif()
 
+foreach( tool IN ITEMS llvm-link opt )
+  find_program( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
+  if( NOT LLVM_TOOL_${tool} )
+    message( FATAL_ERROR "libclc toolchain incomplete - missing tool ${tool}!" )
+  endif()
+  set( ${tool}_exe ${LLVM_TOOL_${tool}} )
+endforeach()
+
 if( NOT LIBCLC_USE_SPIRV_BACKEND )
   # llvm-spirv is an optional dependency, used to build spirv-* targets when
   # the SPIR-V backend hasn't been requested. It may be provided in-tree or
   # externally.
-  if( TARGET llvm-spirv )
-    get_host_tool_path( llvm-spirv LLVM_SPIRV llvm-spirv_exe llvm-spirv_target )
-  else()
-    find_program( LLVM_SPIRV llvm-spirv HINTS ${LLVM_TOOLS_BINARY_DIR} )
-    set( llvm-spirv_exe "${LLVM_SPIRV}" )
-  endif()
+  find_program( LLVM_SPIRV llvm-spirv HINTS ${LLVM_TOOLS_BINARY_DIR} )
+  set( llvm-spirv_exe "${LLVM_SPIRV}" )
 endif()
 
 message(STATUS "libclc target '${LIBCLC_TARGET}' is enabled")
@@ -124,12 +119,6 @@ if(LIBCLC_TARGET_ARCH IN_LIST LIBCLC_ARCHS_SPIRV)
   endif()
 endif()
 
-foreach( tool IN ITEMS opt llvm-link )
-  if( NOT EXISTS "${${tool}_exe}" AND "${${tool}_target}" STREQUAL "" )
-    message( FATAL_ERROR "libclc toolchain incomplete - missing tool ${tool}!" )
-  endif()
-endforeach()
-
 # Determine the clang target triple.
 set(clang_triple ${LIBCLC_TARGET})
 
diff --git a/libcxx/test/CMakeLists.txt b/libcxx/test/CMakeLists.txt
index 8fd34c086a992..de50d6863c9e3 100644
--- a/libcxx/test/CMakeLists.txt
+++ b/libcxx/test/CMakeLists.txt
@@ -53,7 +53,7 @@ endif()
 
 serialize_lit_params_list(SERIALIZED_LIT_PARAMS LIBCXX_TEST_PARAMS)
 
-include(AddLLVM) # for configure_lit_site_cfg and add_lit_testsuite
+include(AddLit) # for configure_lit_site_cfg and add_lit_testsuite
 
 # The test suite is driven by a generated lit.site.cfg that loads the various other configuration
 # files needed by it. In order:
diff --git a/libcxxabi/test/CMakeLists.txt b/libcxxabi/test/CMakeLists.txt
index bc0902054a3be..7a6af2f3f3e69 100644
--- a/libcxxabi/test/CMakeLists.txt
+++ b/libcxxabi/test/CMakeLists.txt
@@ -1,4 +1,4 @@
-include(AddLLVM) # for configure_lit_site_cfg and add_lit_testsuite
+include(AddLit) # for configure_lit_site_cfg and add_lit_testsuite
 include(HandleLitArguments)
 macro(pythonize_bool var)
   if (${var})
diff --git a/libunwind/test/CMakeLists.txt b/libunwind/test/CMakeLists.txt
index 780be2f13b85c..fb1c8e456a1c1 100644
--- a/libunwind/test/CMakeLists.txt
+++ b/libunwind/test/CMakeLists.txt
@@ -1,4 +1,4 @@
-include(AddLLVM) # for add_lit_testsuite
+include(AddLit) # for add_lit_testsuite
 include(HandleLitArguments)
 macro(pythonize_bool var)
   if (${var})
diff --git a/llvm/cmake/modules/AddLLVM.cmake b/llvm/cmake/modules/AddLLVM.cmake
index a267166eb6c2d..20545b55220d1 100644
--- a/llvm/cmake/modules/AddLLVM.cmake
+++ b/llvm/cmake/modules/AddLLVM.cmake
@@ -3,21 +3,8 @@ include(LLVMDistributionSupport)
 include(LLVMProcessSources)
 include(LLVM-Config)
 include(DetermineGCCCompatible)
-
-# get_subproject_title(titlevar)
-#   Set ${outvar} to the title of the current LLVM subproject (Clang, MLIR ...)
-#
-# The title is set in the subproject's top-level using the variable
-# LLVM_SUBPROJECT_TITLE. If it does not exist, it is assumed it is LLVM itself.
-# The title is not semantically significant, but use to create folders in
-# CMake-generated IDE projects (Visual Studio/XCode).
-function(get_subproject_title outvar)
-  if (LLVM_SUBPROJECT_TITLE)
-    set(${outvar} "${LLVM_SUBPROJECT_TITLE}" PARENT_SCOPE)
-  else ()
-    set(${outvar} "LLVM" PARENT_SCOPE)
-  endif ()
-endfunction(get_subproject_title)
+include(GetSubprojectTitle)
+include(AddLit)
 
 # Determine required flags to enable/disable RTTI.
 set(LLVM_CXXFLAGS_RTTI_DISABLE "")
@@ -1967,431 +1954,6 @@ function(add_benchmark benchmark_name)
   target_link_libraries(${benchmark_name} PRIVATE benchmark)
 endfunction()
 
-# This function canonicalize the CMake variables passed by names
-# from CMake boolean to 0/1 suitable for passing into Python or C++,
-# in place.
-function(llvm_canonicalize_cmake_booleans)
-  foreach(var ${ARGN})
-    if(${var})
-      set(${var} 1 PARENT_SCOPE)
-    else()
-      set(${var} 0 PARENT_SCOPE)
-    endif()
-  endforeach()
-endfunction(llvm_canonicalize_cmake_booleans)
-
-macro(set_llvm_build_mode)
-  # Configuration-time: See Unit/lit.site.cfg.in
-  if (CMAKE_CFG_INTDIR STREQUAL ".")
-    set(LLVM_BUILD_MODE ".")
-  else ()
-    set(LLVM_BUILD_MODE "%(build_mode)s")
-  endif ()
-endmacro()
-
-# Takes a list of path names in pathlist and a base directory, and returns
-# a list of paths relative to the base directory in out_pathlist.
-# Paths that are on a different drive than the basedir (on Windows) or that
-# contain symlinks are returned absolute.
-# Use with LLVM_LIT_PATH_FUNCTION below.
-function(make_paths_relative out_pathlist basedir pathlist)
-  # Passing ARG_PATH_VALUES as-is to execute_process() makes cmake strip
-  # empty list entries. So escape the ;s in the list and do the splitting
-  # ourselves. cmake has no relpath function, so use Python for that.
-  string(REPLACE ";" "\\;" pathlist_escaped "${pathlist}")
-  execute_process(COMMAND "${Python3_EXECUTABLE}" "-c" "\n
-import os, sys\n
-base = sys.argv[1]
-def haslink(p):\n
-    if not p or p == os.path.dirname(p): return False\n
-    return os.path.islink(p) or haslink(os.path.dirname(p))\n
-def relpath(p):\n
-    if not p: return ''\n
-    if os.path.splitdrive(p)[0] != os.path.splitdrive(base)[0]: return p\n
-    if haslink(p) or haslink(base): return p\n
-    return os.path.relpath(p, base)\n
-if len(sys.argv) < 3: sys.exit(0)\n
-sys.stdout.write(';'.join(relpath(p) for p in sys.argv[2].split(';')))"
-    ${basedir}
-    ${pathlist_escaped}
-    OUTPUT_VARIABLE pathlist_relative
-    ERROR_VARIABLE error
-    RESULT_VARIABLE result)
-  if (NOT result EQUAL 0)
-    message(FATAL_ERROR "make_paths_relative() failed due to error '${result}', with stderr\n${error}")
-  endif()
-  set(${out_pathlist} "${pathlist_relative}" PARENT_SCOPE)
-endfunction()
-
-# Converts a file that's relative to the current python file to an absolute
-# path. Since this uses __file__, it has to be emitted into python files that
-# use it and can't be in a lit module. Use with make_paths_relative().
-string(CONCAT LLVM_LIT_PATH_FUNCTION
-  "# Allow generated file to be relocatable.\n"
-  "import os\n"
-  "import platform\n"
-  "def path(p):\n"
-  "    if not p: return ''\n"
-  "    # Follows lit.util.abs_path_preserve_drive, which cannot be imported here.\n"
-  "    if platform.system() == 'Windows':\n"
-  "        return os.path.abspath(os.path.join(os.path.dirname(__file__), p))\n"
-  "    else:\n"
-  "        return os.path.realpath(os.path.join(os.path.dirname(__file__), p))\n"
-  )
-
-# This function provides an automatic way to 'configure'-like generate a file
-# based on a set of common and custom variables, specifically targeting the
-# variables needed for the 'lit.site.cfg' files. This function bundles the
-# common variables that any Lit instance is likely to need, and custom
-# variables can be passed in.
-# The keyword PATHS is followed by a list of cmake variable names that are
-# mentioned as `path("@varname@")` in the lit.cfg.py.in file. Variables in that
-# list are treated as paths that are relative to the directory the generated
-# lit.cfg.py file is in, and the `path()` function converts the relative
-# path back to absolute form. This makes it possible to move a build directory
-# containing lit.cfg.py files from one machine to another.
-function(configure_lit_site_cfg site_in site_out)
-  cmake_parse_arguments(ARG "" "" "MAIN_CONFIG;PATHS" ${ARGN})
-
-  if ("${ARG_MAIN_CONFIG}" STREQUAL "")
-    get_filename_component(INPUT_DIR ${site_in} DIRECTORY)
-    set(ARG_MAIN_CONFIG "${INPUT_DIR}/lit.cfg")
-  endif()
-
-  foreach(c ${LLVM_TARGETS_TO_BUILD})
-    set(TARGETS_BUILT "${TARGETS_BUILT} ${c}")
-  endforeach(c)
-  set(TARGETS_TO_BUILD ${TARGETS_BUILT})
-
-  set(SHLIBEXT "${LTDL_SHLIB_EXT}")
-
-  set_llvm_build_mode()
-
-  # For standalone builds of subprojects, these might not be the build tree but
-  # a provided binary tree.
-  set(LLVM_SOURCE_DIR ${LLVM_MAIN_SRC_DIR})
-  set(LLVM_BINARY_DIR ${LLVM_BINARY_DIR})
-  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" LLVM_TOOLS_DIR "${LLVM_TOOLS_BINARY_DIR}")
-  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" LLVM_LIBS_DIR  "${LLVM_LIBRARY_DIR}")
-  # Like LLVM_{TOOLS,LIBS}_DIR, but pointing at the build tree.
-  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" CURRENT_TOOLS_DIR "${LLVM_RUNTIME_OUTPUT_INTDIR}")
-  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" CURRENT_LIBS_DIR  "${LLVM_LIBRARY_OUTPUT_INTDIR}")
-  string(REPLACE "${CMAKE_CFG_INTDIR}" "${LLVM_BUILD_MODE}" SHLIBDIR "${LLVM_SHLIB_OUTPUT_INTDIR}")
-
-  # FIXME: "ENABLE_SHARED" doesn't make sense, since it is used just for
-  # plugins. We may rename it.
-  if(LLVM_ENABLE_PLUGINS)
-    set(ENABLE_SHARED "1")
-  else()
-    set(ENABLE_SHARED "0")
-  endif()
-
-  if(LLVM_ENABLE_ASSERTIONS)
-    set(ENABLE_ASSERTIONS "1")
-  else()
-    set(ENABLE_ASSERTIONS "0")
-  endif()
-
-  set(HOST_OS ${CMAKE_SYSTEM_NAME})
-  set(HOST_ARCH ${CMAKE_SYSTEM_PROCESSOR})
-
-  set(HOST_CC "${CMAKE_C_COMPILER} ${CMAKE_C_COMPILER_ARG1}")
-  set(HOST_CXX "${CMAKE_CXX_COMPILER} ${CMAKE_CXX_COMPILER_ARG1}")
-  set(HOST_LDFLAGS "${CMAKE_EXE_LINKER_FLAGS}")
-
-  string(CONCAT LIT_SITE_CFG_IN_HEADER
-    "# Autogenerated from ${site_in}\n# Do not edit!\n\n"
-    "${LLVM_LIT_PATH_FUNCTION}"
-    )
-
-  # Override config_target_triple (and the env)
-  if(LLVM_TARGET_TRIPLE_ENV)
-    # This is expanded into the heading.
-    string(CONCAT LIT_SITE_CFG_IN_HEADER "${LIT_SITE_CFG_IN_HEADER}"
-      "import os\n"
-      "target_env = \"${LLVM_TARGET_TRIPLE_ENV}\"\n"
-      "config.target_triple = config.environment[target_env] = os.environ.get(target_env, \"${LLVM_TARGET_TRIPLE}\")\n"
-      )
-
-    # This is expanded to; config.target_triple = ""+config.target_triple+""
-    set(LLVM_TARGET_TRIPLE "\"+config.target_triple+\"")
-  endif()
-
-  if (ARG_PATHS)
-    # Walk ARG_PATHS and collect the current value of the variables in there.
-    # list(APPEND) ignores empty elements exactly if the list is empty,
-    # so start the list with a dummy element and drop it, to make sure that
-    # even empty values make it into the values list.
-    set(ARG_PATH_VALUES "dummy")
-    foreach(path ${ARG_PATHS})
-      list(APPEND ARG_PATH_VALUES "${${path}}")
-    endforeach()
-    list(REMOVE_AT ARG_PATH_VALUES 0)
-
-    get_filename_component(OUTPUT_DIR ${site_out} DIRECTORY)
-    make_paths_relative(
-        ARG_PATH_VALUES_RELATIVE "${OUTPUT_DIR}" "${ARG_PATH_VALUES}")
-
-    list(LENGTH ARG_PATHS len_paths)
-    list(LENGTH ARG_PATH_VALUES len_path_values)
-    list(LENGTH ARG_PATH_VALUES_RELATIVE len_path_value_rels)
-    if ((NOT ${len_paths} EQUAL ${len_path_values}) OR
-        (NOT ${len_paths} EQUAL ${len_path_value_rels}))
-      message(SEND_ERROR "PATHS lengths got confused")
-    endif()
-
-    # Transform variables mentioned in ARG_PATHS to relative paths for
-    # the configure_file() call. Variables are copied to subscopeds by cmake,
-    # so this only modifies the local copy of the variables.
-    math(EXPR arg_path_limit "${len_paths} - 1")
-    foreach(i RANGE ${arg_path_limit})
-      list(GET ARG_PATHS ${i} val1)
-      list(GET ARG_PATH_VALUES_RELATIVE ${i} val2)
-      set(${val1} ${val2})
-    endforeach()
-  endif()
-
-  configure_file(${site_in} ${site_out} @ONLY)
-
-  if (EXISTS "${ARG_MAIN_CONFIG}")
-    # Remember main config / generated site config for llvm-lit.in.
-    get_property(LLVM_LIT_CONFIG_FILES GLOBAL PROPERTY LLVM_LIT_CONFIG_FILES)
-    list(APPEND LLVM_LIT_CONFIG_FILES "${ARG_MAIN_CONFIG}" "${site_out}")
-    set_property(GLOBAL PROPERTY LLVM_LIT_CONFIG_FILES ${LLVM_LIT_CONFIG_FILES})
-  endif()
-endfunction()
-
-function(dump_all_cmake_variables)
-  get_cmake_property(_variableNames VARIABLES)
-  foreach (_variableName ${_variableNames})
-    message(STATUS "${_variableName}=${${_variableName}}")
-  endforeach()
-endfunction()
-
-function(get_llvm_lit_path base_dir file_name)
-  cmake_parse_arguments(ARG "ALLOW_EXTERNAL" "" "" ${ARGN})
-
-  if (ARG_ALLOW_EXTERNAL)
-    set (LLVM_EXTERNAL_LIT "" CACHE STRING "Command used to spawn lit")
-    if ("${LLVM_EXTERNAL_LIT}" STREQUAL "")
-      set(LLVM_EXTERNAL_LIT "${LLVM_DEFAULT_EXTERNAL_LIT}")
-    endif()
-
-    if (NOT "${LLVM_EXTERNAL_LIT}" STREQUAL "")
-      if (EXISTS ${LLVM_EXTERNAL_LIT})
-        get_filename_component(LIT_FILE_NAME ${LLVM_EXTERNAL_LIT} NAME)
-        get_filename_component(LIT_BASE_DIR ${LLVM_EXTERNAL_LIT} DIRECTORY)
-        set(${file_name} ${LIT_FILE_NAME} PARENT_SCOPE)
-        set(${base_dir} ${LIT_BASE_DIR} PARENT_SCOPE)
-        return()
-      elseif (NOT DEFINED CACHE{LLVM_EXTERNAL_LIT_MISSING_WARNED_ONCE})
-        message(WARNING "LLVM_EXTERNAL_LIT set to ${LLVM_EXTERNAL_LIT}, but the path does not exist.")
-        set(LLVM_EXTERNAL_LIT_MISSING_WARNED_ONCE YES CACHE INTERNAL "")
-      endif()
-    endif()
-  endif()
-
-  set(lit_file_name "llvm-lit")
-  if (CMAKE_HOST_WIN32 AND NOT CYGWIN)
-    # llvm-lit needs suffix.py for multiprocess to find a main module.
-    set(lit_file_name "${lit_file_name}.py")
-  endif ()
-  set(${file_name} ${lit_file_name} PARENT_SCOPE)
-
-  get_property(LLVM_LIT_BASE_DIR GLOBAL PROPERTY LLVM_LIT_BASE_DIR)
-  if (NOT "${LLVM_LIT_BASE_DIR}" STREQUAL "")
-    set(${base_dir} ${LLVM_LIT_BASE_DIR} PARENT_SCOPE)
-  endif()
-
-  # Allow individual projects to provide an override
-  if (NOT "${LLVM_LIT_OUTPUT_DIR}" STREQUAL "")
-    set(LLVM_LIT_BASE_DIR ${LLVM_LIT_OUTPUT_DIR})
-  elseif(NOT "${LLVM_RUNTIME_OUTPUT_INTDIR}" STREQUAL "")
-    set(LLVM_LIT_BASE_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR})
-  else()
-    set(LLVM_LIT_BASE_DIR "")
-  endif()
-
-  # Cache this so we don't have to do it again and have subsequent calls
-  # potentially disagree on the value.
-  set_property(GLOBAL PROPERTY LLVM_LIT_BASE_DIR ${LLVM_LIT_BASE_DIR})
-  set(${base_dir} ${LLVM_LIT_BASE_DIR} PARENT_SCOPE)
-endfunction()
-
-# A raw function to create a lit target. This is used to implement the testuite
-# management functions.
-function(add_lit_target target comment)
-  cmake_parse_arguments(ARG "" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
-  set(LIT_ARGS "${ARG_ARGS} ${LLVM_LIT_ARGS}")
-  separate_arguments(LIT_ARGS)
-  if (NOT CMAKE_CFG_INTDIR STREQUAL ".")
-    list(APPEND LIT_ARGS --param build_mode=${CMAKE_CFG_INTDIR})
-  endif ()
-
-  # Get the path to the lit to *run* tests with.  This can be overriden by
-  # the user by specifying -DLLVM_EXTERNAL_LIT=<path-to-lit.py>
-  get_llvm_lit_path(
-    lit_base_dir
-    lit_file_name
-    ALLOW_EXTERNAL
-    )
-
-  set(LIT_COMMAND "${Python3_EXECUTABLE};${lit_base_dir}/${lit_file_name}")
-  list(APPEND LIT_COMMAND ${LIT_ARGS})
-  foreach(param ${ARG_PARAMS})
-    list(APPEND LIT_COMMAND --param ${param})
-  endforeach()
-  if (ARG_UNPARSED_ARGUMENTS)
-    add_custom_target(${target}
-      COMMAND ${LIT_COMMAND} ${ARG_UNPARSED_ARGUMENTS}
-      COMMENT "${comment}"
-      USES_TERMINAL
-      )
-  else()
-    add_custom_target(${target}
-      COMMAND ${CMAKE_COMMAND} -E echo "${target} does nothing, no tools built.")
-    message(STATUS "${target} does nothing.")
-  endif()
-  get_subproject_title(subproject_title)
-  set_target_properties(${target} PROPERTIES FOLDER "${subproject_title}/Tests")
-
-  if (ARG_DEPENDS)
-    add_dependencies(${target} ${ARG_DEPENDS})
-  endif()
-
-  # Tests should be excluded from "Build Solution".
-  set_target_properties(${target} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
-  set_target_properties(${target} PROPERTIES XCODE_GENERATE_SCHEME ON)
-endfunction()
-
-# Convert a target name like check-clang to a variable name like CLANG.
-function(umbrella_lit_testsuite_var target outvar)
-  if (NOT target MATCHES "^check-")
-    message(FATAL_ERROR "umbrella lit suites must be check-*, not '${target}'")
-  endif()
-  string(SUBSTRING "${target}" 6 -1 var)
-  string(REPLACE "-" "_" var ${var})
-  string(TOUPPER "${var}" var)
-  set(${outvar} "${var}" PARENT_SCOPE)
-endfunction()
-
-# Start recording all lit test suites for a combined 'check-foo' target.
-# The recording continues until umbrella_lit_testsuite_end() creates the target.
-function(umbrella_lit_testsuite_begin target)
-  umbrella_lit_testsuite_var(${target} name)
-  set_property(GLOBAL APPEND PROPERTY LLVM_LIT_UMBRELLAS ${name})
-endfunction()
-
-# Create a combined 'check-foo' target for a set of related test suites.
-# It runs all suites added since the matching umbrella_lit_testsuite_end() call.
-# Tests marked EXCLUDE_FROM_CHECK_ALL are not gathered.
-function(umbrella_lit_testsuite_end target)
-  umbrella_lit_testsuite_var(${target} name)
-
-  get_property(testsuites GLOBAL PROPERTY LLVM_${name}_LIT_TESTSUITES)
-  get_property(params GLOBAL PROPERTY LLVM_${name}_LIT_PARAMS)
-  get_property(depends GLOBAL PROPERTY LLVM_${name}_LIT_DEPENDS)
-  get_property(extra_args GLOBAL PROPERTY LLVM_${name}_LIT_EXTRA_ARGS)
-  # Additional test targets are not gathered, but may be set externally.
-  get_property(additional_test_targets
-               GLOBAL PROPERTY LLVM_${name}_ADDITIONAL_TEST_TARGETS)
-
-  string(TOLOWER ${name} name)
-  add_lit_target(${target}
-    "Running ${name} regression tests"
-    ${testsuites}
-    PARAMS ${params}
-    DEPENDS ${depends} ${additional_test_targets}
-    ARGS ${extra_args}
-    )
-endfunction()
-
-# A function to add a set of lit test suites to be driven through 'check-*' targets.
-function(add_lit_testsuite target comment)
-  cmake_parse_arguments(ARG "EXCLUDE_FROM_CHECK_ALL" "" "PARAMS;DEPENDS;ARGS" ${ARGN})
-
-  # EXCLUDE_FROM_ALL excludes the test ${target} out of check-all.
-  if(NOT ARG_EXCLUDE_FROM_CHECK_ALL)
-    get_property(gather_names GLOBAL PROPERTY LLVM_LIT_UMBRELLAS)
-    foreach(name ${gather_names})
-    # Register the testsuites, params and depends for the umbrella check rule.
-      set_property(GLOBAL APPEND PROPERTY LLVM_${name}_LIT_TESTSUITES ${ARG_UNPARSED_ARGUMENTS})
-      set_property(GLOBAL APPEND PROPERTY LLVM_${name}_LIT_PARAMS ${ARG_PARAMS})
-      set_property(GLOBAL APPEND PROPERTY LLVM_${name}_LIT_DEPENDS ${ARG_DEPENDS})
-      set_property(GLOBAL APPEND PROPERTY LLVM_${name}_LIT_EXTRA_ARGS ${ARG_ARGS})
-    endforeach()
-  endif()
-
-  # Produce a specific suffixed check rule.
-  add_lit_target(${target} ${comment}
-    ${ARG_UNPARSED_ARGUMENTS}
-    PARAMS ${ARG_PARAMS}
-    DEPENDS ${ARG_DEPENDS}
-    ARGS ${ARG_ARGS}
-    )
-endfunction()
-
-function(add_lit_testsuites project directory)
-  if (NOT LLVM_ENABLE_IDE)
-    cmake_parse_arguments(ARG
-      "EXCLUDE_FROM_CHECK_ALL"
-      "FOLDER;BINARY_DIR"
-      "PARAMS;DEPENDS;ARGS;SKIP"
-      ${ARGN}
-      )
-
-    if (NOT ARG_FOLDER)
-      get_subproject_title(subproject_title)
-      set(ARG_FOLDER "${subproject_title}/Tests/LIT Testsuites")
-    endif()
-
-    # Search recursively for test directories by assuming anything not
-    # in a directory called Inputs contains tests.
-    file(GLOB_RECURSE to_process LIST_DIRECTORIES true ${directory}/*)
-    foreach(lit_suite ${to_process})
-      if(NOT IS_DIRECTORY ${lit_suite})
-        continue()
-      endif()
-      string(FIND ${lit_suite} Inputs is_inputs)
-      string(FIND ${lit_suite} Output is_output)
-      if (NOT (is_inputs EQUAL -1 AND is_output EQUAL -1))
-        continue()
-      endif()
-
-      # Create a check- target for the directory.
-      string(REPLACE "${directory}/" "" name_slash ${lit_suite})
-      set(_should_skip FALSE)
-      foreach(skip IN LISTS ARG_SKIP)
-        if(name_slash MATCHES "${skip}")
-          set(_should_skip TRUE)
-          break()
-        endif()
-      endforeach()
-      if (_should_skip)
-        continue()
-      endif()
-      if (name_slash)
-        set(filter ${name_slash})
-        string(REPLACE "/" "-" name_slash ${name_slash})
-        string(REPLACE "\\" "-" name_dashes ${name_slash})
-        string(TOLOWER "${project}-${name_dashes}" name_var)
-        set(lit_args ${lit_suite})
-        if (ARG_BINARY_DIR)
-          set(lit_args ${ARG_BINARY_DIR} --filter=${filter})
-        endif()
-        add_lit_target("check-${name_var}" "Running lit suite ${lit_suite}"
-          ${lit_args}
-          ${EXCLUDE_FROM_CHECK_ALL}
-          PARAMS ${ARG_PARAMS}
-          DEPENDS ${ARG_DEPENDS}
-          ARGS ${ARG_ARGS}
-        )
-        set_target_properties(check-${name_var} PROPERTIES FOLDER ${ARG_FOLDER})
-      endif()
-    endforeach()
-  endif()
-endfunction()
-
 function(llvm_install_library_symlink name dest type)
   cmake_parse_arguments(ARG "FULL_DEST" "COMPONENT" "" ${ARGN})
   foreach(path ${CMAKE_MODULE_PATH})
diff --git a/llvm/cmake/modules/AddOCaml.cmake b/llvm/cmake/modules/AddOCaml.cmake
index 9a393ae3b7474..ef4171cdbd8d0 100644
--- a/llvm/cmake/modules/AddOCaml.cmake
+++ b/llvm/cmake/modules/AddOCaml.cmake
@@ -1,4 +1,5 @@
 # CMake build rules for the OCaml language.
+include(GetSubprojectTitle)
 # Assumes FindOCaml is used.
 # http://ocaml.org/
 #
diff --git a/llvm/cmake/modules/AddSphinxTarget.cmake b/llvm/cmake/modules/AddSphinxTarget.cmake
index 02a869b7941a9..55e8d556347e0 100644
--- a/llvm/cmake/modules/AddSphinxTarget.cmake
+++ b/llvm/cmake/modules/AddSphinxTarget.cmake
@@ -1,4 +1,5 @@
 include(GNUInstallDirs)
+include(GetSubprojectTitle)
 
 # Create sphinx target
 if (LLVM_ENABLE_SPHINX)
diff --git a/llvm/cmake/modules/CMakeLists.txt b/llvm/cmake/modules/CMakeLists.txt
index ef4cfa3acdb59..d9c8f0c69188c 100644
--- a/llvm/cmake/modules/CMakeLists.txt
+++ b/llvm/cmake/modules/CMakeLists.txt
@@ -113,6 +113,12 @@ file(COPY .
   PATTERN CMakeFiles EXCLUDE
   PATTERN llvm-driver-template.cpp.in
   )
+file(COPY
+  ${LLVM_COMMON_CMAKE_UTILS}/Modules/AddLit.cmake
+  ${LLVM_COMMON_CMAKE_UTILS}/Modules/GetSubprojectTitle.cmake
+  DESTINATION ${llvm_cmake_builddir}
+  NO_SOURCE_PERMISSIONS
+  )
 
 #
 # Generate LLVMConfig.cmake for the install tree.
@@ -170,6 +176,8 @@ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
     ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/LLVMConfig.cmake
     ${llvm_cmake_builddir}/LLVMConfigVersion.cmake
     LLVM-Config.cmake
+    ${LLVM_COMMON_CMAKE_UTILS}/Modules/AddLit.cmake
+    ${LLVM_COMMON_CMAKE_UTILS}/Modules/GetSubprojectTitle.cmake
     DESTINATION ${LLVM_INSTALL_PACKAGE_DIR}
     COMPONENT cmake-exports)
 
diff --git a/llvm/cmake/modules/CrossCompile.cmake b/llvm/cmake/modules/CrossCompile.cmake
index 0a0be5336c74c..ae6ae68bbbea4 100644
--- a/llvm/cmake/modules/CrossCompile.cmake
+++ b/llvm/cmake/modules/CrossCompile.cmake
@@ -1,4 +1,5 @@
 include(AddLLVM)
+include(GetSubprojectTitle)
 include(LLVMExternalProjectUtils)
 
 
diff --git a/llvm/cmake/modules/LLVMDistributionSupport.cmake b/llvm/cmake/modules/LLVMDistributionSupport.cmake
index 03c6773570231..d0dad77932658 100644
--- a/llvm/cmake/modules/LLVMDistributionSupport.cmake
+++ b/llvm/cmake/modules/LLVMDistributionSupport.cmake
@@ -1,5 +1,6 @@
 # Utility functions for packaging an LLVM distribution. See the
 # BuildingADistribution documentation for more details.
+include(GetSubprojectTitle)
 
 # These functions assume a number of conventions that are common across all LLVM
 # subprojects:
diff --git a/llvm/cmake/modules/TableGen.cmake b/llvm/cmake/modules/TableGen.cmake
index 397089a2d3efe..2b85ccf083f73 100644
--- a/llvm/cmake/modules/TableGen.cmake
+++ b/llvm/cmake/modules/TableGen.cmake
@@ -3,6 +3,7 @@
 # Extra parameters for `tblgen' may come after `ofn' parameter.
 # Adds the name of the generated file to TABLEGEN_OUTPUT.
 include(LLVMDistributionSupport)
+include(GetSubprojectTitle)
 
 function(tablegen project ofn)
   cmake_parse_arguments(ARG "" "" "DEPENDS;EXTRA_INCLUDES" ${ARGN})
diff --git a/llvm/runtimes/CMakeLists.txt b/llvm/runtimes/CMakeLists.txt
index c2607393d1bb9..ca1fcb7aa8f50 100644
--- a/llvm/runtimes/CMakeLists.txt
+++ b/llvm/runtimes/CMakeLists.txt
@@ -636,6 +636,13 @@ if(build_runtimes)
       endif()
     endif()
   endif()
+  if("libclc" IN_LIST LLVM_ENABLE_RUNTIMES)
+    foreach(dep opt llvm-link clang)
+      if(TARGET ${dep})
+        list(APPEND extra_deps ${dep})
+      endif()
+    endforeach()
+  endif()
   if("libsycl" IN_LIST LLVM_ENABLE_RUNTIMES)
     foreach(dep clang-linker-wrapper clang-sycl-linker clang llvm-offload-binary)
       if(TARGET ${dep})
diff --git a/runtimes/CMakeLists.txt b/runtimes/CMakeLists.txt
index 61cf25af22870..3c5fcfbbbdb64 100644
--- a/runtimes/CMakeLists.txt
+++ b/runtimes/CMakeLists.txt
@@ -223,7 +223,7 @@ endif()
 set(LLVM_COMPILER_CHECKED ON)
 
 # Handle common options used by all runtimes.
-include(AddLLVM)
+include(AddLit)
 include(HandleLLVMOptions)
 
 # Loot at the PATH first to avoid a version mismatch between the command-line

>From 7c1b3e2908bd5fdae59aa9e0d8a9da2f0297eb5e Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Sun, 23 Aug 2026 22:30:34 +0000
Subject: [PATCH 2/3] Address review feedback and builder failures

---
 libclc/CMakeLists.txt                |   2 +-
 libclc/cmake/modules/AddLibclc.cmake |   4 +-
 third-party/unittest/CMakeLists.txt  | 135 +++++++++++++--------------
 3 files changed, 70 insertions(+), 71 deletions(-)

diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
index 66d5d89debb11..4aa677abcc93a 100644
--- a/libclc/CMakeLists.txt
+++ b/libclc/CMakeLists.txt
@@ -87,7 +87,7 @@ else()
 endif()
 
 foreach( tool IN ITEMS llvm-link opt )
-  find_program( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
+  find_program( LLVM_TOOL_${tool} ${tool} PATHS ${LLVM_NATIVE_TOOL_DIR} NO_DEFAULT_PATH )
   if( NOT LLVM_TOOL_${tool} )
     message( FATAL_ERROR "libclc toolchain incomplete - missing tool ${tool}!" )
   endif()
diff --git a/libclc/cmake/modules/AddLibclc.cmake b/libclc/cmake/modules/AddLibclc.cmake
index d84101f71d2f9..0eb3648aac5da 100644
--- a/libclc/cmake/modules/AddLibclc.cmake
+++ b/libclc/cmake/modules/AddLibclc.cmake
@@ -128,7 +128,7 @@ function(libclc_add_library target_name)
   # Link the object files, using a temporary library for internalization.
   set(linked_bc ${CMAKE_CURRENT_BINARY_DIR}/${target_name}.linked.bc)
   set(link_cmd ${llvm-link_exe})
-  set(link_deps ${llvm-link_target})
+  set(link_deps "")
 
   add_library(${target_name}-src STATIC)
   target_link_libraries(${target_name}-src PRIVATE ${ARG_SOURCE_TARGET})
@@ -183,7 +183,7 @@ function(libclc_add_library target_name)
     set(builtins_lib ${library_dir}/${ARG_OUTPUT_FILENAME}.bc)
     add_custom_command(OUTPUT ${builtins_lib}
       COMMAND ${opt_exe} ${ARG_OPT_FLAGS} -o ${builtins_lib} ${linked_bc}
-      DEPENDS ${opt_target} ${linked_bc}
+      DEPENDS ${linked_bc}
     )
   endif()
 
diff --git a/third-party/unittest/CMakeLists.txt b/third-party/unittest/CMakeLists.txt
index 79535a1de4616..51fa8bdcfa105 100644
--- a/third-party/unittest/CMakeLists.txt
+++ b/third-party/unittest/CMakeLists.txt
@@ -13,32 +13,6 @@
 
 set(LLVM_SUBPROJECT_TITLE "Third-Party/Google Test")
 
-if(LLVM_RUNTIMES_BUILD)
-  # This instance of GTest is use for unittests for the runtime libraries. It
-  # must not link to LLVMSupport (used for llvm::raw_ostream and llvm::cl
-  # support) of the host build: It may be a different architecture and/or
-  # using a different C++ ABI such as libcxx/libstdc++.
-  set(GTEST_LLVM_COMPONENTS "")
-
-  # We cannot use llvm_gtest for the target; it would clash with
-  # find_package(LLVM) with LLVM_EXPORT_GTEST=ON. Instead, we define an alias
-  # default_gtest that points to llvm_gtest in the LLVM build and
-  # runtimes_gtest in an runtimes build.
-  set(gtest_name "runtimes_gtest")
-
-  # Override locally; never install the runtimes-GTest.
-  set(LLVM_INSTALL_GTEST OFF)
-
-  # Build the library containing main() so unittests need less boilerplate.
-  # UnitTestMain/TestMain.cpp always needs LLVMSupport, use GTest's original
-  # main when unavailable.
-  set(gtest_main_src googletest/src/gtest_main.cc)
-else()
-  set(GTEST_LLVM_COMPONENTS "Support")
-  set(gtest_name "llvm_gtest")
-  set(gtest_main_src UnitTestMain/TestMain.cpp)
-endif()
-
 if(WIN32)
   add_definitions(-DGTEST_OS_WINDOWS=1)
 endif()
@@ -72,44 +46,51 @@ if (LLVM_INSTALL_GTEST)
   set(BUILDTREE_ONLY "")
 endif ()
 
-add_llvm_library("${gtest_name}"
-  googletest/src/gtest-all.cc
-  googlemock/src/gmock-all.cc
+if (LLVM_RUNTIMES_BUILD)
+  # We cannot use llvm_gtest for the target; it would clash with
+  # find_package(LLVM) with LLVM_EXPORT_GTEST=ON. Instead, we define an alias
+  # default_gtest that points to llvm_gtest in the LLVM build and
+  # runtimes_gtest in an runtimes build.
+  set(gtest_name "runtimes_gtest")
 
-  LINK_LIBS
-  ${LIBS}
+  # This instance of GTest is use for unittests for the runtime libraries. It
+  # must not link to LLVMSupport (used for llvm::raw_ostream and llvm::cl
+  # support) of the host build: It may be a different architecture and/or
+  # using a different C++ ABI such as libcxx/libstdc++.
+  add_library("${gtest_name}" STATIC
+    googletest/src/gtest-all.cc
+    googlemock/src/gmock-all.cc
+  )
+  target_compile_definitions("${gtest_name}" PUBLIC GTEST_NO_LLVM_SUPPORT=1)
+  target_link_libraries("${gtest_name}"
+    PUBLIC # STATIC -OR- PRIVATE for SHARED
+      ${LIBS}
+  )
 
-  LINK_COMPONENTS
-  ${GTEST_LLVM_COMPONENTS}
+  add_library("${gtest_name}_main" STATIC
+    googletest/src/gtest_main.cc
+  )
+  target_link_libraries("${gtest_name}_main"
+    PUBLIC
+      ${gtest_name}
+  )
+else()
+  set(gtest_name "llvm_gtest")
 
-  # This is a library meant only for the build tree.
-  ${BUILDTREE_ONLY}
-)
+  add_llvm_library("${gtest_name}"
+    googletest/src/gtest-all.cc
+    googlemock/src/gmock-all.cc
 
-# The googletest and googlemock sources don't presently use the 'override'
-# keyword, which leads to lots of warnings from -Wsuggest-override. Disable
-# that warning here for any targets that link to gtest.
-if(CXX_SUPPORTS_SUGGEST_OVERRIDE_FLAG)
-  add_definitions("-Wno-suggest-override")
-  set_target_properties("${gtest_name}" PROPERTIES INTERFACE_COMPILE_OPTIONS "-Wno-suggest-override")
-endif()
+    LINK_LIBS
+    ${LIBS}
 
-if (NOT LLVM_ENABLE_THREADS)
-  target_compile_definitions("${gtest_name}" PUBLIC GTEST_HAS_PTHREAD=0)
-endif ()
+    LINK_COMPONENTS
+    Support
 
-target_include_directories("${gtest_name}"
-  PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/googletest/include>
-         $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/googlemock/include>
-         $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/>
-         $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/llvm-gtest/>
-         $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/llvm-gmock/>
-  PRIVATE googletest googlemock
+    # This is a library meant only for the build tree.
+    ${BUILDTREE_ONLY}
   )
 
-if(LLVM_RUNTIMES_BUILD)
-  target_compile_definitions("${gtest_name}" PUBLIC GTEST_NO_LLVM_SUPPORT=1)
-else()
   # When used from the buildtree, also force use of buildtree LLVM headers,
   # (instead locally installed version)
   # FIXME: Shouldn't this be done for all LLVM libraries? Currently, LLVM uses a
@@ -118,27 +99,45 @@ else()
   target_include_directories("${gtest_name}" BEFORE
     PUBLIC $<BUILD_INTERFACE:${LLVM_SOURCE_DIR}/include>
            $<BUILD_INTERFACE:${LLVM_BINARY_DIR}/include>
-    )
-endif()
-
+  )
 
-add_llvm_library("${gtest_name}_main"
-  ${gtest_main_src}
+  add_llvm_library("${gtest_name}_main"
+    UnitTestMain/TestMain.cpp
 
-  LINK_LIBS
-  "${gtest_name}"
+    LINK_LIBS
+    "${gtest_name}"
 
-  LINK_COMPONENTS
-  ${GTEST_LLVM_COMPONENTS}
+    LINK_COMPONENTS
+    Support
 
-  ${BUILDTREE_ONLY}
-)
+    ${BUILDTREE_ONLY}
+  )
 
-if (LLVM_INSTALL_GTEST)
   install(DIRECTORY googletest/include/gtest/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/llvm-gtest/gtest/" COMPONENT "${gtest_name}")
   install(DIRECTORY googlemock/include/gmock/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/llvm-gmock/gmock/" COMPONENT "${gtest_name}")
 endif()
 
+# The googletest and googlemock sources don't presently use the 'override'
+# keyword, which leads to lots of warnings from -Wsuggest-override. Disable
+# that warning here for any targets that link to gtest.
+if(CXX_SUPPORTS_SUGGEST_OVERRIDE_FLAG)
+  add_definitions("-Wno-suggest-override")
+  set_target_properties("${gtest_name}" PROPERTIES INTERFACE_COMPILE_OPTIONS "-Wno-suggest-override")
+endif()
+
+if (NOT LLVM_ENABLE_THREADS)
+  target_compile_definitions("${gtest_name}" PUBLIC GTEST_HAS_PTHREAD=0)
+endif ()
+
+target_include_directories("${gtest_name}"
+  PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/googletest/include>
+         $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/googlemock/include>
+         $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/>
+         $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/llvm-gtest/>
+         $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/llvm-gmock/>
+  PRIVATE googletest googlemock
+  )
+
 # When LLVM_LINK_LLVM_DYLIB is enabled, libLLVM.so is added to the interface
 # link libraries for gtest and gtest_main.  This means that any target, like
 # unittests for example, that links against gtest will be forced to link

>From 9af9c8443186762afab94e1e711aba258eeb51c8 Mon Sep 17 00:00:00 2001
From: Petr Hosek <phosek at google.com>
Date: Sun, 23 Aug 2026 23:44:19 +0000
Subject: [PATCH 3/3] Drop LLVM_EXPORTS from openmp runtime

---
 openmp/runtime/src/CMakeLists.txt | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/openmp/runtime/src/CMakeLists.txt b/openmp/runtime/src/CMakeLists.txt
index 69def2b03b1b4..9f801af7e6e21 100644
--- a/openmp/runtime/src/CMakeLists.txt
+++ b/openmp/runtime/src/CMakeLists.txt
@@ -405,11 +405,6 @@ if(NOT WIN32 AND NOT APPLE)
 endif()
 add_dependencies(libomp-micro-tests libomp-test-deps)
 
-# `omp` needs to be exported if in-tree build.
-set(export_to_llvmexports)
-get_target_export_arg(omp LLVM export_to_llvmexports)
-set_property(GLOBAL APPEND PROPERTY LLVM_EXPORTS omp)
-
 # Install rules
 # We want to install libomp in ${DESTDIR}/${CMAKE_INSTALL_FULL_LIBDIR}
 # We want to install headers in ${DESTDIR}/${CMAKE_INSTALL_FULL_INCLUDEDIR}



More information about the Openmp-commits mailing list