From 75f49071e57af45dbca6bba53b2546f9b1e579fa Mon Sep 17 00:00:00 2001 From: Chris B Date: Thu, 16 Jul 2026 14:00:53 -0500 Subject: [PATCH 1/4] Support standalone builds of the offload test suite This change allows the offload test suite to be built against a prebuilt LLVM distribution which is built with the included CMake cache file. With this build it takes ~10 seconds to build the offloader, api-query and unit test binaries against the provided LLVM distribution. To use this build LLVM with a command like so: ``` cmake -C /cmake/caches/OffloadDistribution.cmake \ -DCMAKE_INSTALL_PREFIX= \ ninja install-distribution ``` Then configure and build the offload test suite with a command like so: ``` cmake -DCMAKE_PREFIX_PATH=/lib/cmake/llvm \ -DLLVM_MAIN_SRC_DIR=/llvm \ -DDXC_DIR= \ -DOFFLOAD_TEST_TEST_CLANG=On \ -DGOLDENIMAGE_DIR= \ ninja check-hlsl ``` --- CMakeLists.txt | 59 +++++++++++++++++++++ cmake/caches/OffloadDistribution.cmake | 39 ++++++++++++++ {lib => include}/Support/OffloadMigration.h | 0 lib/API/DX/Device.cpp | 3 +- lib/Support/OffloadMigration.cpp | 2 +- test/CMakeLists.txt | 2 +- test/lit.cfg.py | 6 ++- test/lit.site.cfg.py.in | 1 + 8 files changed, 106 insertions(+), 6 deletions(-) create mode 100644 cmake/caches/OffloadDistribution.cmake rename {lib => include}/Support/OffloadMigration.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 32f96e2a6..1e9300f78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,66 @@ # This project is only buildable as a subproject of LLVM. +cmake_minimum_required(VERSION 3.31.0) project(OffloadTest) +# If we are not building as a part of LLVM, build Clang as an +# standalone project, using LLVM as an external library: +if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR) + set(OFFLOADTEST_BUILT_STANDALONE TRUE) +endif() + +if (OFFLOADTEST_BUILT_STANDALONE) + find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}") + list(APPEND CMAKE_MODULE_PATH "${LLVM_DIR}") + + include(AddLLVM) + + find_package(Python3 ${LLVM_MINIMUM_PYTHON_VERSION} REQUIRED + COMPONENTS Interpreter) + + set(CMAKE_CXX_STANDARD 17 CACHE STRING "C++ standard to conform to") + set(CMAKE_CXX_STANDARD_REQUIRED YES) + set(CMAKE_CXX_EXTENSIONS NO) + + # They are used as destination of target generators. + set(LLVM_RUNTIME_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/bin) + set(LLVM_LIBRARY_OUTPUT_INTDIR ${CMAKE_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX}) + if(WIN32 OR CYGWIN) + # DLL platform -- put DLLs into bin. + set(LLVM_SHLIB_OUTPUT_INTDIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) + else() + set(LLVM_SHLIB_OUTPUT_INTDIR ${LLVM_LIBRARY_OUTPUT_INTDIR}) + endif() + + set(LLVM_TOOLS_DIR ${LLVM_TOOLS_BINARY_DIR}) + include_directories(${LLVM_INCLUDE_DIRS}) + link_directories("${LLVM_LIBRARY_DIR}") + + # Seek installed Lit. + find_program(LLVM_LIT + NAMES llvm-lit lit.py lit + PATHS "${LLVM_MAIN_SRC_DIR}/utils/lit" + DOC "Path to lit.py") + + if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/lit/lit.py) + # Note: path not really used, except for checking if lit was found + if(EXISTS ${LLVM_MAIN_SRC_DIR}/utils/llvm-lit) + add_subdirectory(${LLVM_MAIN_SRC_DIR}/utils/llvm-lit utils/llvm-lit) + endif() + endif() + + if (NOT LLVM_THIRD_PARTY_DIR) + set(LLVM_THIRD_PARTY_DIR "${LLVM_MAIN_SRC_DIR}/../third-party") + endif() + if (NOT TARGET llvm_gtest) + add_subdirectory(${LLVM_THIRD_PARTY_DIR}/unittest ${CMAKE_CURRENT_BINARY_DIR}/third-party/unittest) + endif() +endif() + +# Setting this allows the offload-test-suite to have a separate tools directory +# from the llvm-provided tools. +set(OFFLOADTEST_TOOLS_DIR ${LLVM_RUNTIME_OUTPUT_INTDIR}) + # Add path for custom modules list(INSERT CMAKE_MODULE_PATH 0 "${CMAKE_CURRENT_SOURCE_DIR}/cmake" diff --git a/cmake/caches/OffloadDistribution.cmake b/cmake/caches/OffloadDistribution.cmake new file mode 100644 index 000000000..3c405b44e --- /dev/null +++ b/cmake/caches/OffloadDistribution.cmake @@ -0,0 +1,39 @@ +# Including the native target is important because some of LLVM's tests fail if +# you don't. +set(LLVM_TARGETS_TO_BUILD "Native;SPIRV" CACHE STRING "") + +# Include the DirectX target for DXIL code generation. +set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD "DirectX" CACHE STRING "") + +set(LLVM_ENABLE_PROJECTS "clang;clang-tools-extra" CACHE STRING "") + +set(CLANG_ENABLE_HLSL On CACHE BOOL "") + +set(LLVM_INSTALL_UTILS ON CACHE BOOL "") +set(LLVM_INSTALL_TOOLCHAIN_ONLY OFF CACHE BOOL "") +set(LLVM_DISTRIBUTION_COMPONENTS + clang + hlsl-resource-headers + FileCheck + split-file + obj2yaml + not + llvm-headers + LLVMSupport + LLVMDemangle # Dependency of LLVMSupport + LLVMObject + # Dependencies of LLVMObject + LLVMBitReader + LLVMBitstreamReader # Dependency of LLVMBitReader + LLVMCore + LLVMRemarks # Dependency of LLVMCore + LLVMMC + LLVMDebugInfoDWARFLowLevel # Dependency of LLVMMC + LLVMIRReader + LLVMAsmParser # Dependency of LLVMIRReader + LLVMBinaryFormat + LLVMMCParser + LLVMTargetParser + LLVMTextAPI + cmake-exports + CACHE STRING "") diff --git a/lib/Support/OffloadMigration.h b/include/Support/OffloadMigration.h similarity index 100% rename from lib/Support/OffloadMigration.h rename to include/Support/OffloadMigration.h diff --git a/lib/API/DX/Device.cpp b/lib/API/DX/Device.cpp index 60949a287..f175b574f 100644 --- a/lib/API/DX/Device.cpp +++ b/lib/API/DX/Device.cpp @@ -36,6 +36,7 @@ #include "API/Encoder.h" #include "API/FormatConversion.h" #include "DXFeatures.h" +#include "Support/OffloadMigration.h" #include "Support/Pipeline.h" #include "Support/WinError.h" @@ -50,8 +51,6 @@ #include "../Util.h" -#include "../Support/OffloadMigration.h" - #include #include #include diff --git a/lib/Support/OffloadMigration.cpp b/lib/Support/OffloadMigration.cpp index 008009d80..00052ea7e 100644 --- a/lib/Support/OffloadMigration.cpp +++ b/lib/Support/OffloadMigration.cpp @@ -1,4 +1,4 @@ -#include "OffloadMigration.h" +#include "Support/OffloadMigration.h" #include "API/Device.h" #include "API/FormatConversion.h" diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index f47ed2a74..e7e11ab71 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -67,7 +67,7 @@ list(APPEND OFFLOADTEST_DEPS obj2yaml not) -if (OFFLOADTEST_TEST_CLANG) +if (OFFLOADTEST_TEST_CLANG AND NOT OFFLOADTEST_BUILT_STANDALONE) list(APPEND OFFLOADTEST_DEPS clang) endif() diff --git a/test/lit.cfg.py b/test/lit.cfg.py index 1db5316a2..5b0713143 100644 --- a/test/lit.cfg.py +++ b/test/lit.cfg.py @@ -41,6 +41,8 @@ # Tweak the PATH to include the tools dir. llvm_config.with_environment("PATH", config.llvm_tools_dir, append_path=True) +tool_dirs = [config.llvm_tools_dir, config.offloadtest_tools_dir] + llvm_config.with_system_environment( [ @@ -329,9 +331,9 @@ def setDeviceFeatures(config, device, compiler): tools.append(ToolSubst("obj2yaml", FindTool("obj2yaml"))) -llvm_config.add_tool_substitutions(tools, config.llvm_tools_dir) +llvm_config.add_tool_substitutions(tools, tool_dirs) -api_query = os.path.join(config.llvm_tools_dir, "api-query") +api_query = os.path.join(config.offloadtest_tools_dir, "api-query") query_string = subprocess.check_output(api_query) devices = yaml.safe_load(query_string) target_device = None diff --git a/test/lit.site.cfg.py.in b/test/lit.site.cfg.py.in index e99663e07..c9d0599a4 100644 --- a/test/lit.site.cfg.py.in +++ b/test/lit.site.cfg.py.in @@ -4,6 +4,7 @@ import sys config.offloadtest_obj_root = path(r"@OFFLOADTEST_BINARY_DIR@") config.offloadtest_src_root = path(r"@OFFLOADTEST_TEST_ROOT@") +config.offloadtest_tools_dir = lit_config.substitute(path(r"@OFFLOADTEST_TOOLS_DIR@")) config.llvm_tools_dir = lit_config.substitute(path(r"@LLVM_TOOLS_DIR@")) config.offloadtest_dxc = '"' + path(r"@DXC_EXECUTABLE@") + '"' config.offloadtest_supports_spirv = @SUPPORTS_SPIRV@ From 7b05b4bb10af2d37ed93e7e6437947eaef869639 Mon Sep 17 00:00:00 2001 From: Chris B Date: Fri, 17 Jul 2026 10:10:39 -0500 Subject: [PATCH 2/4] Add an explicit check for LLVM_MAIN_SRC_DIR --- CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1e9300f78..f76a5cd49 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,10 @@ if (OFFLOADTEST_BUILT_STANDALONE) include_directories(${LLVM_INCLUDE_DIRS}) link_directories("${LLVM_LIBRARY_DIR}") + if (NOT LLVM_MAIN_SRC_DIR OR NOT EXISTS "${LLVM_MAIN_SRC_DIR}") + message(FATAL_ERROR "LLVM_MAIN_SRC_DIR is not set or invalid. Please set it to the root of the LLVM source tree.") + endif() + # Seek installed Lit. find_program(LLVM_LIT NAMES llvm-lit lit.py lit From c6be26c6db2b1ed46ee32ab3d3541cc2253fcebb Mon Sep 17 00:00:00 2001 From: Chris B Date: Fri, 17 Jul 2026 10:53:59 -0500 Subject: [PATCH 3/4] Update docs and rename cache file --- cmake/caches/StandaloneDistribution.cmake | 39 +++++++++++++++++++++ docs/offload-distribution.md | 41 +++++++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 cmake/caches/StandaloneDistribution.cmake diff --git a/cmake/caches/StandaloneDistribution.cmake b/cmake/caches/StandaloneDistribution.cmake new file mode 100644 index 000000000..3c405b44e --- /dev/null +++ b/cmake/caches/StandaloneDistribution.cmake @@ -0,0 +1,39 @@ +# Including the native target is important because some of LLVM's tests fail if +# you don't. +set(LLVM_TARGETS_TO_BUILD "Native;SPIRV" CACHE STRING "") + +# Include the DirectX target for DXIL code generation. +set(LLVM_EXPERIMENTAL_TARGETS_TO_BUILD "DirectX" CACHE STRING "") + +set(LLVM_ENABLE_PROJECTS "clang;clang-tools-extra" CACHE STRING "") + +set(CLANG_ENABLE_HLSL On CACHE BOOL "") + +set(LLVM_INSTALL_UTILS ON CACHE BOOL "") +set(LLVM_INSTALL_TOOLCHAIN_ONLY OFF CACHE BOOL "") +set(LLVM_DISTRIBUTION_COMPONENTS + clang + hlsl-resource-headers + FileCheck + split-file + obj2yaml + not + llvm-headers + LLVMSupport + LLVMDemangle # Dependency of LLVMSupport + LLVMObject + # Dependencies of LLVMObject + LLVMBitReader + LLVMBitstreamReader # Dependency of LLVMBitReader + LLVMCore + LLVMRemarks # Dependency of LLVMCore + LLVMMC + LLVMDebugInfoDWARFLowLevel # Dependency of LLVMMC + LLVMIRReader + LLVMAsmParser # Dependency of LLVMIRReader + LLVMBinaryFormat + LLVMMCParser + LLVMTargetParser + LLVMTextAPI + cmake-exports + CACHE STRING "") diff --git a/docs/offload-distribution.md b/docs/offload-distribution.md index d2859adb3..6bc525aec 100644 --- a/docs/offload-distribution.md +++ b/docs/offload-distribution.md @@ -185,3 +185,44 @@ The reusable workflow `.github/workflows/build-and-test-callable.yaml` implements this flow when invoked with `SplitBuild=true`. The build job produces two artifacts (`build--` and `dxc--`) and the test job consumes both. + +## Standalone Build Distribution + +An alternate approach for separating the build and test flow in the offload test +suite is using the "standalone" build mode. With this build flow, LLVM (and +optionally Clang) are built separately from the offload-test suite, and the +offload-test-suite is configured as the top-level CMake entry. + +A sample configuration for this flow is provided in the +`cmake/caches/StandaloneDistribution.cmake` cache script. In this build +configuration, the LLVM build contributes Clang, the llvm testing tools, and the +subset of LLVM component libraries that the offload-test-suite's tools depend +on. + +Using this flow LLVM and Clang are configured using a command like: + +``` +cmake -C /cmake/caches/StandaloneDistribution.cmake \ + -DCMAKE_INSTALL_PREFIX= \ + +ninja install-distribution +``` + +Then configure and build the offload test suite with a command like so: + +``` +cmake -DCMAKE_PREFIX_PATH=/lib/cmake/llvm \ + -DLLVM_MAIN_SRC_DIR=/llvm \ + -DDXC_DIR= \ + -DOFFLOAD_TEST_TEST_CLANG=On \ + -DGOLDENIMAGE_DIR= \ + +ninja check-hlsl +``` + +In this configuration the offload-test-suite will build its tools against the +already built LLVM libraries which dramatically reduces build time. This +configuration does still require a checkout of the LLVM source tree to pull LIT +and the third-party unit testing libraries. If clone/checkout time or disk space +is a concern this could be a sparse checkout or future changes could allow this +to use LIT from pip and a stock googletest framework. From beea8d8f3edd2cf2b4ec20bbfcdbf1444793bdf8 Mon Sep 17 00:00:00 2001 From: Chris Bieneman Date: Fri, 24 Jul 2026 17:33:38 -0500 Subject: [PATCH 4/4] Update configure-test-suite script used by CI --- utils/configure-test-suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/utils/configure-test-suite.py b/utils/configure-test-suite.py index 4d233466f..d2d2168eb 100644 --- a/utils/configure-test-suite.py +++ b/utils/configure-test-suite.py @@ -244,6 +244,7 @@ def main(): # layout it's the install share dir. "OFFLOADTEST_TEST_ROOT": str(test_src_root.parent), "LLVM_TOOLS_DIR": str(bin_dir), + "OFFLOADTEST_TOOLS_DIR": str(bin_dir), "DXC_EXECUTABLE": str(dxc_path) if dxc_path is not None else "", "SUPPORTS_SPIRV": "True" if vk else "False", "FORCE_CLANG": "True" if clang else "False",