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])