This is an automated email from the ASF dual-hosted git repository.

tqchen pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git


The following commit(s) were added to refs/heads/main by this push:
     new 59a1f8fe [BUILD][ORCJIT] Use the PyPI LLVM static SDK (#877)
59a1f8fe is described below

commit 59a1f8fe6f667f6ac4cb2a783681bf348115eeb8
Author: Yaxing Cai <[email protected]>
AuthorDate: Mon Oct 26 01:26:28 2026 +0800

    [BUILD][ORCJIT] Use the PyPI LLVM static SDK (#877)
    
    ORC JIT builds currently download an LLVM release tarball on Linux and
    install LLVM through Conda on macOS/Windows. Use the published
    `mlc-llvm-static==23.1.1` SDK as the build dependency across the
    existing platform matrix.
    
    - Discover the SDK with the build environment's Python and link LLVM's
    exported CMake targets. Their transitive dependencies supply static
    zlib/zstd and platform system libraries, replacing the manual
    `llvm-config` queries, library searches, and linker-flag filtering.
    - Require the packaged SDK directly, with its native profile. External
    LLVM installations and build-time `LLVM_PREFIX`, `LLVM_DIR`, and
    `ORC_RT_PATH` overrides are no longer supported. Linux builds embed the
    matching SDK `liborc_rt` and fail if it is absent. Runtime
    custom-archive arguments remain supported.
    - Clear old system-zlib discovery results so incremental builds also
    link the SDK's static zlib. Require CMake 3.24+, which supports
    `ZLIB_USE_STATIC_LIBS`.
    - Remove the release download, mount, cache, Conda setup, and obsolete
    macOS libc++ fixup. The shared wheel action installs the SDK from PyPI,
    builds/tests against the in-tree core, installs Clang separately in
    manylinux, and uses the SDK's macOS 14 deployment floor.
    - Update the source-build instructions and custom-runtime tests to use
    the packaged SDK. Use the Apache-approved cibuildwheel v4.2.1 pin
    already used by core wheel builds.
    
    The native SDK supplies the backend used by ORC JIT;
    `mlc-llvm-static-extra-targets` is unnecessary. LLVM/zlib/zstd remain
    statically linked. The SDK is a build dependency, with no new runtime
    dependency in the addon wheel.
    
    Validation of the simplified CMake setup on macOS arm64:
    
    - Clean isolated wheel build from declared PyPI build dependencies:
    `apache_tvm_ffi_orcjit-0.1.2-py3-none-macosx_14_0_arm64.whl`.
    - Incremental build against the current in-tree core, including
    migration from the old cached system-zlib lookup: **136 passed, 54
    skipped** in the full addon suite under pytest-xdist.
    - C and C++ quick-start examples passed.
    - `otool -L` shows only TVM-FFI and system C/C++ runtimes, with no
    dynamic LLVM/zlib/zstd.
    - SDK paths containing spaces configure and build successfully; a
    missing SDK fails configuration immediately.
    - All applicable repository pre-commit hooks and `git diff --check`
    passed.
    
    The [upstream CI run for the SDK-only imported-target
    implementation](https://github.com/apache/tvm-ffi/actions/runs/40203992826)
    passes all four ORC JIT wheel jobs, including their examples:
    
    | Platform | Addon tests |
    | --- | --- |
    | Linux x86_64 | 180 passed, 10 skipped |
    | Linux aarch64 | 178 passed, 12 skipped |
    | macOS arm64 | 136 passed, 54 skipped |
    | Windows AMD64 | 82 passed, 39 skipped |
    
    Local uv builds use a package-specific cutoff override for the SDK
    because it was published within the repository's 14-day `exclude-newer`
    window.
    
    AI assistance: This change was prepared with OpenAI Codex.
---
 .github/actions/build-orcjit-wheel/action.yml      | 101 ++----------
 .github/workflows/ci_test.yml                      |  11 +-
 addons/tvm_ffi_orcjit/CMakeLists.txt               | 171 ++++-----------------
 addons/tvm_ffi_orcjit/README.md                    |  42 +++--
 addons/tvm_ffi_orcjit/pyproject.toml               |   8 +-
 .../tests/test_session_load_module.py              |  18 +--
 6 files changed, 73 insertions(+), 278 deletions(-)

diff --git a/.github/actions/build-orcjit-wheel/action.yml 
b/.github/actions/build-orcjit-wheel/action.yml
index d3d6195c..2009fdb4 100644
--- a/.github/actions/build-orcjit-wheel/action.yml
+++ b/.github/actions/build-orcjit-wheel/action.yml
@@ -18,7 +18,7 @@
 name: Build OrcJIT Wheel
 description: >
   Build and test OrcJIT wheels for a given OS/architecture combination.
-  Handles LLVM caching, conda installation, and cibuildwheel execution.
+  Installs the LLVM static SDK from PyPI and runs cibuildwheel.
 
 inputs:
   arch:
@@ -31,16 +31,9 @@ inputs:
     description: "Branch, tag, or SHA to check out before building"
     required: true
   llvm_version:
-    description: "LLVM version (selects the release tag / conda pin)"
+    description: "mlc-llvm-static version (keep in sync with the addon build 
requirements)"
     default: "23.1.1"
     required: false
-  llvm_release_repo:
-    description: >
-      GitHub repo hosting the prebuilt LLVM release assets (Linux only). The
-      asset llvm-<version>-linux-<arch>.tar.zst is downloaded from the
-      llvm-<version> tag. Point at a fork to validate before the canonical 
repo.
-    default: "mlc-ai/package"
-    required: false
 
 runs:
   using: "composite"
@@ -54,80 +47,9 @@ runs:
     - uses: ./.github/actions/detect-env-vars
       id: env_vars
 
-    # ---- Acquire LLVM prefix ----
-    # Linux: downloaded as a prebuilt tarball from a GitHub Release (built from
-    #   source with the manylinux gcc-toolset so the ABI stays under the floor)
-    #   and extracted to /opt/llvm. Permanent storage -- no actions/cache 
lifetime.
-    # macOS/Windows: no GLIBCXX floor -- keep the conda-forge binaries, cached.
-    - name: Cache LLVM (macOS/Windows)
-      if: runner.os != 'Linux'
-      uses: actions/cache@v4
-      id: llvm-cache
-      with:
-        path: ${{ runner.os == 'Windows' && 'C:/opt/llvm' || '/opt/llvm' }}
-        key: llvm-${{ inputs.llvm_version }}-${{ runner.os }}-${{ inputs.arch 
}}-v4
-
-    - name: Download prebuilt LLVM (Linux)
-      if: runner.os == 'Linux'
-      shell: bash
-      run: |
-        set -euo pipefail
-        asset="llvm-${{ inputs.llvm_version }}-linux-${{ inputs.arch 
}}.tar.zst"
-        base="https://github.com/${{ inputs.llvm_release_repo 
}}/releases/download"
-        url="${base}/llvm-${{ inputs.llvm_version }}/${asset}"
-        echo "Downloading $url"
-        curl -fL --retry 5 --retry-all-errors -o "$RUNNER_TEMP/$asset" "$url"
-        sudo mkdir -p /opt/llvm
-        sudo tar --zstd -xf "$RUNNER_TEMP/$asset" -C /opt/llvm
-        sudo chown -R "$(id -u):$(id -g)" /opt/llvm
-
-    - name: Verify LLVM prefix (Linux)
-      if: runner.os == 'Linux'
-      shell: bash
-      run: |
-        test -x /opt/llvm/bin/llvm-config \
-          || { echo "::error::LLVM prefix missing; the release download must 
succeed first"; exit 1; }
-        /opt/llvm/bin/llvm-config --version
-
-    # ---- Install LLVM via conda (macOS/Windows, cache miss only) ----
-    - name: Setup conda
-      if: steps.llvm-cache.outputs.cache-hit != 'true' && runner.os != 'Linux'
-      uses: 
conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167  # 
v3.3.0
-      continue-on-error: true
-      id: conda1
-      with:
-        miniforge-version: latest
-
-    - name: Setup conda (retry with tar.bz2)
-      if: steps.llvm-cache.outputs.cache-hit != 'true' && runner.os != 'Linux' 
&& steps.conda1.outcome == 'failure'
-      uses: 
conda-incubator/setup-miniconda@fc2d68f6413eb2d87b895e92f8584b5b94a10167  # 
v3.3.0
-      with:
-        miniforge-version: latest
-        use-only-tar-bz2: true
-
-    - name: Create /opt/llvm (macOS)
-      if: steps.llvm-cache.outputs.cache-hit != 'true' && runner.os == 'macOS'
-      shell: bash
-      run: sudo mkdir -p /opt/llvm && sudo chown -R $(whoami) /opt/llvm
-
-    - name: Install LLVM (macOS)
-      if: steps.llvm-cache.outputs.cache-hit != 'true' && runner.os == 'macOS'
-      shell: bash -l {0}
-      run: |
-        conda create -q -p /opt/llvm -c conda-forge \
-          llvmdev=${{ inputs.llvm_version }} clangdev=${{ inputs.llvm_version 
}} \
-          compiler-rt=${{ inputs.llvm_version }} zlib zstd-static \
-          -y
-
-    - name: Install LLVM (Windows)
-      if: steps.llvm-cache.outputs.cache-hit != 'true' && runner.os == 
'Windows'
-      shell: cmd /C call {0}
-      run: |
-        conda create -q -p C:\opt\llvm -c conda-forge llvmdev=${{ 
inputs.llvm_version }} zlib zstd-static -y
-
     # ---- Build and test wheels ----
     - name: Build and test wheels
-      uses: pypa/cibuildwheel@294735312765b09d24a2fbec22660ce817587d55  # 
v4.1.0
+      uses: pypa/cibuildwheel@e090b81e30c4d855ea63bf4b6e59204c09a101ae  # 
v4.2.1
       with:
         package-dir: addons/tvm_ffi_orcjit
         output-dir: wheelhouse
@@ -136,20 +58,23 @@ runs:
         CIBW_ARCHS_LINUX: ${{ inputs.arch }}
         CIBW_ARCHS_MACOS: ${{ inputs.arch }}
         CIBW_ARCHS_WINDOWS: ${{ inputs.arch }}
-        # Link inside manylinux_2_28 -- the same image family the downloaded 
LLVM
-        # was built in (gcc-toolset-14). An older image couldn't consume its 
libs.
+        # The PyPI SDK is built for the manylinux_2_28 ABI floor.
         CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
         CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28
+        # Match the deployment floor of the macOS SDK wheel.
+        CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=14.0
         CIBW_BUILD_VERBOSITY: 1
         CMAKE_BUILD_PARALLEL_LEVEL: ${{ steps.env_vars.outputs.cpu_count }}
-        CIBW_ENVIRONMENT: LLVM_PREFIX=/opt/llvm
-        CIBW_ENVIRONMENT_WINDOWS: LLVM_PREFIX="C:/opt/llvm"
-        CIBW_CONTAINER_ENGINE: "docker; create_args: --volume 
/opt/llvm:/opt/llvm"
         # Build against the in-tree core (not PyPI) so the addon's tvm_ffi ABI
         # matches the core the tests reinstall; a mismatch segfaults the JIT.
-        CIBW_BEFORE_BUILD: pip install "scikit-build-core>=0.10.0" cmake ninja 
"{project}"
+        CIBW_BEFORE_BUILD: >-
+          pip install "scikit-build-core>=0.10.0" cmake ninja
+          "mlc-llvm-static==${{ inputs.llvm_version }}" "{project}"
         CIBW_BUILD_FRONTEND: "pip; args: --no-build-isolation"
-        CIBW_TEST_REQUIRES: pytest pytest-xdist ninja
+        # The SDK contains libraries and headers; compilers remain separate 
test tools.
+        CIBW_BEFORE_ALL_LINUX: dnf install -y clang
+        # The SDK supplies liborc_rt for the custom-runtime tests; it is not a 
runtime dependency.
+        CIBW_TEST_REQUIRES: pytest pytest-xdist ninja mlc-llvm-static==${{ 
inputs.llvm_version }}
         CIBW_TEST_COMMAND: >-
           pip install --force-reinstall {project} &&
           pytest {project}/addons/tvm_ffi_orcjit/tests -v &&
diff --git a/.github/workflows/ci_test.yml b/.github/workflows/ci_test.yml
index 4dcb3902..bc3110cc 100644
--- a/.github/workflows/ci_test.yml
+++ b/.github/workflows/ci_test.yml
@@ -225,11 +225,7 @@ jobs:
           git diff --exit-code -- rust/src/generated
           cd rust && cargo run
 
-  # Build + test the orcjit wheel. On Linux the action downloads a prebuilt 
LLVM
-  # tarball from a GitHub Release (built from source under the manylinux
-  # gcc-toolset so the ABI stays under the floor); macOS/Windows install LLVM 
via
-  # conda inside the action. The LLVM release is produced out-of-band (rarely, 
on
-  # version bump) by mlc-ai/package's build_llvm workflow -- not on every CI 
run.
+  # Build and test the OrcJIT wheel using the LLVM static SDK from PyPI.
   orcjit:
     needs: [lint, prepare]
     if: >
@@ -240,10 +236,6 @@ jobs:
     runs-on: ${{ matrix.os }}
     env:
       LLVM_VERSION: "23.1.1"
-      # Repo hosting the prebuilt LLVM release assets consumed on Linux. Built
-      # out-of-band from source in a manylinux image so the ABI stays under the
-      # manylinux_2_28 floor; see that repo's build_llvm workflow.
-      LLVM_RELEASE_REPO: "mlc-ai/package"
     strategy:
       fail-fast: false
       matrix:
@@ -265,7 +257,6 @@ jobs:
           build: ${{ matrix.build }}
           checkout_ref: ${{ github.sha }}
           llvm_version: ${{ env.LLVM_VERSION }}
-          llvm_release_repo: ${{ env.LLVM_RELEASE_REPO }}
 
       - uses: actions/upload-artifact@v4
         with:
diff --git a/addons/tvm_ffi_orcjit/CMakeLists.txt 
b/addons/tvm_ffi_orcjit/CMakeLists.txt
index b9993073..aa68ca71 100644
--- a/addons/tvm_ffi_orcjit/CMakeLists.txt
+++ b/addons/tvm_ffi_orcjit/CMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.20)
+cmake_minimum_required(VERSION 3.24)
 project(
   tvm_ffi_orcjit
   VERSION 0.1.2
@@ -10,28 +10,30 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 
-# ---- LLVM_PREFIX handling ----
-# scikit-build-core overrides CMAKE_PREFIX_PATH via its init cache, so we read 
LLVM_PREFIX from the
-# environment instead.
-if (DEFINED ENV{LLVM_PREFIX})
-  list(APPEND CMAKE_PREFIX_PATH "$ENV{LLVM_PREFIX}")
-  if (EXISTS "$ENV{LLVM_PREFIX}/Library")
-    list(APPEND CMAKE_PREFIX_PATH "$ENV{LLVM_PREFIX}/Library")
-  endif ()
-endif ()
-
-# ---- Find packages ----
-find_package(LLVM REQUIRED CONFIG)
-if (LLVM_PACKAGE_VERSION VERSION_LESS 23.1.1)
-  message(FATAL_ERROR "tvm_ffi_orcjit requires LLVM 23.1.1 or newer; found 
${LLVM_PACKAGE_VERSION}")
-endif ()
-message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION} in ${LLVM_DIR}")
-
 find_package(
   Python
   COMPONENTS Interpreter
   REQUIRED
 )
+
+# ---- LLVM static SDK ----
+execute_process(
+  COMMAND "${Python_EXECUTABLE}" -m mlc_llvm_static.config --prefix
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+  OUTPUT_VARIABLE _llvm_prefix COMMAND_ERROR_IS_FATAL ANY
+)
+list(PREPEND CMAKE_PREFIX_PATH "${_llvm_prefix}")
+set(LLVM_DIR "${_llvm_prefix}/lib/cmake/llvm")
+set(zstd_DIR "${_llvm_prefix}/lib/cmake/zstd") # cmake-lint: disable=C0103
+set(ZLIB_USE_STATIC_LIBS ON)
+# Discard system-zlib results cached by builds using the old manual link setup.
+unset(ZLIB_INCLUDE_DIR CACHE)
+unset(ZLIB_LIBRARY_RELEASE CACHE)
+unset(ZLIB_LIBRARY_DEBUG CACHE)
+set(MLC_LLVM_STATIC_PROFILE native)
+find_package(LLVM REQUIRED CONFIG)
+message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION} in ${LLVM_DIR}")
+
 execute_process(
   COMMAND "${Python_EXECUTABLE}" -m tvm_ffi.config --cmakedir
   OUTPUT_STRIP_TRAILING_WHITESPACE
@@ -62,115 +64,12 @@ set_target_properties(
 target_include_directories(
   tvm_ffi_orcjit PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src ${LLVM_INCLUDE_DIRS}
 )
-separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND ${LLVM_DEFINITIONS})
+separate_arguments(LLVM_DEFINITIONS_LIST NATIVE_COMMAND "${LLVM_DEFINITIONS}")
 target_compile_definitions(tvm_ffi_orcjit PRIVATE ${LLVM_DEFINITIONS_LIST})
 
-# ---- Static LLVM linking via llvm-config ----
-set(_llvm_config_hints ${LLVM_TOOLS_BINARY_DIR} "${LLVM_DIR}/../../../bin")
-if (DEFINED ENV{LLVM_PREFIX})
-  list(APPEND _llvm_config_hints "$ENV{LLVM_PREFIX}/bin" 
"$ENV{LLVM_PREFIX}/Library/bin")
-endif ()
-find_program(
-  LLVM_CONFIG_EXE
-  NAMES llvm-config-${LLVM_VERSION_MAJOR} llvm-config
-  HINTS ${_llvm_config_hints}
-)
-if (NOT LLVM_CONFIG_EXE)
-  message(FATAL_ERROR "llvm-config not found")
-endif ()
-
-execute_process(
-  COMMAND ${LLVM_CONFIG_EXE} --link-static --libs Core OrcJIT Support native
-  OUTPUT_STRIP_TRAILING_WHITESPACE
-  OUTPUT_VARIABLE _llvm_libs
-  ERROR_VARIABLE _llvm_libs_error
-  RESULT_VARIABLE _llvm_libs_rc
-)
-if (NOT _llvm_libs_rc EQUAL 0)
-  message(FATAL_ERROR "llvm-config --link-static --libs failed: 
${_llvm_libs_error}")
-endif ()
-execute_process(
-  COMMAND ${LLVM_CONFIG_EXE} --link-static --ldflags
-  OUTPUT_STRIP_TRAILING_WHITESPACE
-  OUTPUT_VARIABLE _llvm_ldflags
-  ERROR_VARIABLE _llvm_ldflags_error
-  RESULT_VARIABLE _llvm_ldflags_rc
-)
-if (NOT _llvm_ldflags_rc EQUAL 0)
-  message(FATAL_ERROR "llvm-config --link-static --ldflags failed: 
${_llvm_ldflags_error}")
-endif ()
-separate_arguments(_llvm_libs_list NATIVE_COMMAND "${_llvm_libs}")
-separate_arguments(_llvm_ldflags_list NATIVE_COMMAND "${_llvm_ldflags}")
-
-# ---- zlib (static, from LLVM prefix) ----
-cmake_path(GET LLVM_DIR PARENT_PATH _llvm_prefix)
-cmake_path(GET _llvm_prefix PARENT_PATH _llvm_prefix)
-cmake_path(GET _llvm_prefix PARENT_PATH _llvm_prefix)
-set(_lib_hints "${_llvm_prefix}/lib" "${_llvm_prefix}/lib64" 
"${_llvm_prefix}/Library/lib")
-
-if (WIN32)
-  find_library(
-    ZLIB_STATIC
-    NAMES zlibstatic z
-    HINTS ${_lib_hints} REQUIRED
-  )
-else ()
-  find_library(
-    ZLIB_STATIC
-    NAMES libz.a
-    HINTS ${_lib_hints} REQUIRED
-  )
-endif ()
-
-# ---- zstd (static, from LLVM prefix) ----
-if (WIN32)
-  find_library(
-    ZSTD_STATIC
-    NAMES zstd_static zstd
-    HINTS ${_lib_hints} REQUIRED
-  )
-else ()
-  find_library(
-    ZSTD_STATIC
-    NAMES libzstd.a
-    HINTS ${_lib_hints} REQUIRED
-  )
-endif ()
-
-# ---- Link everything ----
-target_link_libraries(
-  tvm_ffi_orcjit PRIVATE tvm_ffi::header tvm_ffi::shared ${_llvm_ldflags_list} 
${_llvm_libs_list}
-                         ${ZLIB_STATIC} ${ZSTD_STATIC}
-)
-
-# LLVM system libs (ntdll/psapi on Windows, rt/dl on Linux), minus zlib/zstd 
(linked above).
-execute_process(
-  COMMAND ${LLVM_CONFIG_EXE} --system-libs
-  OUTPUT_STRIP_TRAILING_WHITESPACE
-  OUTPUT_VARIABLE _sys_libs
-  RESULT_VARIABLE _sys_libs_rc
-)
-if (_sys_libs_rc EQUAL 0 AND _sys_libs)
-  separate_arguments(_sys_libs_list NATIVE_COMMAND "${_sys_libs}")
-  list(FILTER _sys_libs_list EXCLUDE REGEX "(zstd|^-lz$|^z\\.lib$|xml2)")
-  target_link_libraries(tvm_ffi_orcjit PRIVATE ${_sys_libs_list})
-endif ()
-
-# ---- Platform-specific fixups ----
-if (APPLE)
-  add_custom_command(
-    TARGET tvm_ffi_orcjit
-    POST_BUILD
-    COMMAND install_name_tool -change @rpath/libc++.1.dylib 
/usr/lib/libc++.1.dylib
-            $<TARGET_FILE:tvm_ffi_orcjit>
-    COMMENT "Fixing libc++ rpath to use system library"
-  )
-endif ()
-
-# libstdc++/libgcc are linked DYNAMICALLY on Linux. The prebuilt LLVM this 
addon links against is
-# built inside the manylinux image with its gcc-toolset, so the toolchain 
already sits at the
-# manylinux ABI floor and no too-recent GLIBCXX_* symbol is imported -- the 
-static-libstdc++
-# workaround the older conda-forge LLVM required is no longer needed.
+# Imported targets carry the static compression libraries and platform system 
dependencies.
+llvm_map_components_to_libnames(LLVM_LIBS Core OrcJIT Support native)
+target_link_libraries(tvm_ffi_orcjit PRIVATE tvm_ffi::header tvm_ffi::shared 
${LLVM_LIBS})
 
 # Export only the explicit initialization API. In particular, do not publish 
symbols from the
 # statically linked LLVM/zlib/zstd archives: the addon is loaded into host 
processes that may carry
@@ -199,22 +98,14 @@ endif ()
 # * macOS: MachOPlatform is skipped to sidestep the compact-unwind delta bug 
(see
 #   src/ffi/orcjit_session.cc); liborc_rt is unused.
 # * Windows: COFFPlatform is not hooked up; liborc_rt is unused.
-set(ORC_RT_PATH "")
-if (NOT APPLE AND NOT WIN32)
-  if (DEFINED ENV{ORC_RT_PATH})
-    set(ORC_RT_PATH "$ENV{ORC_RT_PATH}")
-  else ()
-    file(GLOB_RECURSE _orc_rt_candidates 
"${_llvm_prefix}/lib/clang/*/lib/liborc_rt*.a")
-    if (_orc_rt_candidates)
-      list(GET _orc_rt_candidates 0 ORC_RT_PATH)
-    endif ()
-  endif ()
-  if (NOT ORC_RT_PATH)
-    message(WARNING "Could not find liborc_rt. Linux ORC platform lifecycle 
will be disabled.")
+if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
+  file(GLOB_RECURSE _orc_rt_candidates
+       "${_llvm_prefix}/lib/clang/${LLVM_VERSION_MAJOR}/lib/liborc_rt*.a"
+  )
+  if (NOT _orc_rt_candidates)
+    message(FATAL_ERROR "mlc-llvm-static is missing the Linux liborc_rt 
archive")
   endif ()
-endif ()
-
-if (ORC_RT_PATH)
+  list(GET _orc_rt_candidates 0 ORC_RT_PATH)
   message(STATUS "Embedding liborc_rt: ${ORC_RT_PATH}")
   enable_language(ASM)
   configure_file(
diff --git a/addons/tvm_ffi_orcjit/README.md b/addons/tvm_ffi_orcjit/README.md
index 4e5988d6..300ca3e9 100644
--- a/addons/tvm_ffi_orcjit/README.md
+++ b/addons/tvm_ffi_orcjit/README.md
@@ -64,26 +64,18 @@ pip install apache-tvm-ffi apache-tvm_ffi_orcjit
 
 #### Prerequisites
 
-- Python 3.10+, CMake 3.20+, C++17 compiler
-- LLVM 23.1.1+ development libraries (`llvmdev`, `llvm-config`)
-- Static `zlib` and `zstd` libraries (in the same prefix as LLVM)
+- Python 3.10+, CMake 3.24+, C++17 compiler
 
-#### Install LLVM via conda-forge
+The build automatically installs 
[mlc-llvm-static](https://pypi.org/project/mlc-llvm-static/)
+from PyPI. It supplies LLVM 23.1.1, static zlib/zstd, and the Linux ORC 
runtime.
+CMake uses the SDK in the build environment and links its exported static 
targets.
+A separate LLVM installation is not used. The SDK is linked statically and is 
not a
+runtime dependency of the resulting addon wheel.
 
-The easiest way to get all dependencies is via conda-forge:
-
-```bash
-conda create -p /opt/llvm -c conda-forge \
-  llvmdev=23.1.1 clangdev=23.1.1 compiler-rt=23.1.1 zlib zstd-static -y
-export LLVM_PREFIX=/opt/llvm
-```
-
-On Windows:
-
-```cmd
-conda create -p C:\opt\llvm -c conda-forge llvmdev=23.1.1 zlib zstd-static -y
-set LLVM_PREFIX=C:\opt\llvm
-```
+The base SDK contains the native backend used by ORC JIT.
+`mlc-llvm-static-extra-targets` adds cross-compilation backends and is not 
required
+for this addon. Clang and other compilers are separate tools; the SDK does not
+include them.
 
 #### Build and install
 
@@ -99,9 +91,9 @@ cd addons/tvm_ffi_orcjit
 pip install -e .
 ```
 
-The `LLVM_PREFIX` environment variable tells CMake where to find LLVM. If
-LLVM is installed in a conda env or a standard system path, CMake can
-auto-discover it and `LLVM_PREFIX` is not needed.
+For a build with `--no-build-isolation`, install the build requirements, 
including
+`mlc-llvm-static==23.1.1`, into the same Python environment first. 
`LLVM_PREFIX`
+and `LLVM_DIR` do not select a different SDK.
 
 On Linux, each `load_module` call follows the same default compiler selection
 as `tvm_ffi.cpp.build`: `$CXX`, or `c++` when unset. ORC asks that compiler for
@@ -259,12 +251,14 @@ for C++, or `__tvm_ffi_` prefix for C).
 MSVC/clang-cl objects must be compiled with `/GS-` to disable buffer security
 checks (`__security_cookie`) which are CRT symbols the JIT cannot resolve.
 
-### LLVM version mismatch
+### LLVM SDK discovery failure
 
-The package requires LLVM 23.1.1+. Set `LLVM_PREFIX` to the LLVM install 
prefix:
+Source builds require the pinned `mlc-llvm-static` package in the build
+interpreter's environment. Normal isolated builds install it automatically.
+For builds with `--no-build-isolation`, install it explicitly:
 
 ```bash
-export LLVM_PREFIX=/path/to/llvm
+pip install mlc-llvm-static==23.1.1
 ```
 
 ### Reclaiming unused JIT memory on Linux
diff --git a/addons/tvm_ffi_orcjit/pyproject.toml 
b/addons/tvm_ffi_orcjit/pyproject.toml
index 61089fa2..0f9f4c15 100644
--- a/addons/tvm_ffi_orcjit/pyproject.toml
+++ b/addons/tvm_ffi_orcjit/pyproject.toml
@@ -16,7 +16,11 @@
 # under the License.
 
 [build-system]
-requires = ["scikit-build-core>=0.10.0", "apache-tvm-ffi>=0.1.14.post1"]
+requires = [
+  "scikit-build-core>=0.10.0",
+  "apache-tvm-ffi>=0.1.14.post1",
+  "mlc-llvm-static==23.1.1",
+]
 build-backend = "scikit_build_core.build"
 
 [project]
@@ -76,8 +80,6 @@ build = "cp312-*"
 skip = "*-win32 *-manylinux_i686 *-musllinux*"
 
 [tool.cibuildwheel.linux]
-# LLVM_PREFIX is unnecessary when LLVM is installed in a conda env
-# (cmake auto-discovers via CONDA_PREFIX) or in a standard system path.
 repair-wheel-command = "auditwheel repair --exclude libtvm_ffi.so -w 
{dest_dir} {wheel}"
 
 [tool.cibuildwheel.macos]
diff --git a/addons/tvm_ffi_orcjit/tests/test_session_load_module.py 
b/addons/tvm_ffi_orcjit/tests/test_session_load_module.py
index 59c59f4b..5b916d72 100644
--- a/addons/tvm_ffi_orcjit/tests/test_session_load_module.py
+++ b/addons/tvm_ffi_orcjit/tests/test_session_load_module.py
@@ -53,20 +53,12 @@ def obj(name: str) -> str:
 
 
 def _find_orc_rt_archive() -> str:
-    """Locate a liborc_rt archive under LLVM_PREFIX, or skip.
-
-    Used only by the custom-``orc_rt`` override tests. There is no bundled copy
-    next to the extension anymore (the runtime is embedded), so these tests 
fall
-    back to the archive shipped with the build's LLVM.
-    """
-    import os  # noqa: PLC0415
-
-    prefix = os.environ.get("LLVM_PREFIX")
-    if not prefix:
-        pytest.skip("LLVM_PREFIX not set; cannot locate a liborc_rt archive")
-    matches = sorted(Path(prefix).glob("lib/clang/*/lib/*/liborc_rt*.a"))
+    """Locate the SDK's liborc_rt archive for custom-runtime override tests."""
+    llvm = pytest.importorskip("mlc_llvm_static")
+    prefix = llvm.get_prefix()
+    matches = sorted(Path(prefix).glob("lib/clang/*/lib/**/liborc_rt*.a"))
     if not matches:
-        pytest.skip("no liborc_rt archive found under LLVM_PREFIX")
+        pytest.skip("no liborc_rt archive found in mlc-llvm-static")
     return str(matches[0])
 
 

Reply via email to