From 5a9c3f01f6a057ae13ba0ba765f2c786f7947f1f Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Wed, 22 Jul 2026 16:26:56 +0800 Subject: [PATCH 01/19] Refactor Python packaging around scikit-build-core --- .github/workflows/build_wheel.yml | 28 +- .github/workflows/build_wheel_mac.yml | 35 +- .github/workflows/ci.yml | 15 +- .github/workflows/ci_sim.yml | 14 +- CMakeLists.txt | 51 ++ _ptoas_build_backend.py | 375 -------------- docker/Dockerfile | 27 +- docker/collect_ptoas_dist.sh | 88 ++-- docker/collect_ptoas_dist_mac.sh | 77 ++- docker/copy_ptoas_deps.sh | 148 ------ docker/create_wheel.sh | 309 ------------ docker/setup.py | 54 --- docker/setup_mac.py | 64 --- docker/test_wheel_imports.sh | 28 +- docker/validate_wheel_payload.py | 22 +- docs/designs/ptoas-python-launcher-layout.md | 154 +++--- lib/Bindings/Python/CMakeLists.txt | 2 + packaging/ptoas-vmi/pyproject.toml | 60 +++ ptodsl/CMakeLists.txt | 21 +- ptodsl/ptoas/__init__.py | 3 +- ptodsl/ptoas/_cli.py | 100 ++++ ptodsl/ptoas/_launcher.py | 21 - ptodsl/ptoas/_runtime_entry.py | 144 ------ ptodsl/ptoas_wheel_bootstrap.py | 190 -------- ptodsl/tests/CMakeLists.txt | 1 + ptodsl/tests/test_docs_as_test.py | 18 +- .../tests/test_pipe_surface_sample_compile.py | 19 +- ptodsl/tests/test_ptoas_cli.py | 119 +++++ ptodsl/tests/test_ptoas_frontend_verify.py | 18 +- ptodsl/tests/test_ptoas_launcher_shim.py | 45 -- ptodsl/tests/test_ptoas_runtime_entry.py | 249 ---------- ptodsl/tests/test_ptoas_tree_wrapper.py | 459 +++--------------- ptodsl/tests/test_ptoas_wheel_bootstrap.py | 319 ------------ pyproject.toml | 59 ++- quick_install.sh | 37 +- test/python/test_docker_runtime_packaging.py | 69 +-- test/python/test_ptoas_build_backend.py | 126 ----- test/python/test_scikit_build_config.py | 120 +++++ test/python/test_validate_wheel_payload.py | 82 ++-- tools/ptoas/CMakeLists.txt | 90 ++-- tools/ptoas/NativeModule.cpp | 37 ++ tools/ptoas/driver.cpp | 8 +- tools/ptoas/ptoas.h | 4 +- tools/ptoas/ptoas_wrapper.py | 118 +---- 44 files changed, 964 insertions(+), 3063 deletions(-) delete mode 100644 _ptoas_build_backend.py delete mode 100644 docker/copy_ptoas_deps.sh delete mode 100755 docker/create_wheel.sh delete mode 100644 docker/setup.py delete mode 100644 docker/setup_mac.py create mode 100644 packaging/ptoas-vmi/pyproject.toml create mode 100644 ptodsl/ptoas/_cli.py delete mode 100644 ptodsl/ptoas/_launcher.py delete mode 100644 ptodsl/ptoas/_runtime_entry.py delete mode 100644 ptodsl/ptoas_wheel_bootstrap.py create mode 100644 ptodsl/tests/test_ptoas_cli.py delete mode 100644 ptodsl/tests/test_ptoas_launcher_shim.py delete mode 100644 ptodsl/tests/test_ptoas_runtime_entry.py delete mode 100644 ptodsl/tests/test_ptoas_wheel_bootstrap.py delete mode 100644 test/python/test_ptoas_build_backend.py create mode 100644 test/python/test_scikit_build_config.py create mode 100644 tools/ptoas/NativeModule.cpp diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index 98a8ac0c9f..02e776ac42 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -130,12 +130,13 @@ jobs: export PATH="${PY_PATH}/bin:$PATH" # LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x # (see pybind11 static_assert on def_property + keep_alive). - pip install --no-cache-dir numpy 'pybind11<3' nanobind setuptools wheel auditwheel + pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' auditwheel - - name: Test PEP 517 build backend + - name: Validate PEP 517 project metadata run: | export PATH="${PY_PATH}/bin:$PATH" - PYTHONPATH="$GITHUB_WORKSPACE" python test/python/test_ptoas_build_backend.py + python -m scikit_build_core.build project-table + (cd packaging/ptoas-vmi && python -m scikit_build_core.build project-table) - name: Set build directories run: | @@ -215,16 +216,19 @@ jobs: CMAKE_BUILD_PARALLEL_LEVEL: "2" run: | export PATH="${PY_PATH}/bin:$PATH" + if [ "${PTOAS_PYTHON_PACKAGE_NAME}" = "ptoas-vmi" ]; then + PTOAS_WHEEL_SOURCE_DIR="${PTO_SOURCE_DIR}/packaging/ptoas-vmi" + else + PTOAS_WHEEL_SOURCE_DIR="${PTO_SOURCE_DIR}" + fi + rm -rf "${PTO_SOURCE_DIR}/build/wheel-dist" + mkdir -p "${PTO_SOURCE_DIR}/build/wheel-dist" PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_CLI_VERSION}" \ - pip install . --no-build-isolation - - - name: Create Python wheel - if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' - run: | - export PATH="${PY_PATH}/bin:$PATH" - export PTOAS_PYTHON_PACKAGE_NAME="${PTOAS_PYTHON_PACKAGE_NAME}" - export PTOAS_PYTHON_PACKAGE_VERSION="${PTOAS_VERSION}" - bash $PTO_SOURCE_DIR/docker/create_wheel.sh + SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}" \ + python -m pip wheel "${PTOAS_WHEEL_SOURCE_DIR}" \ + --no-build-isolation --no-deps \ + --wheel-dir "${PTO_SOURCE_DIR}/build/wheel-dist" + cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" - name: Validate wheel payload and launcher contract if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' diff --git a/.github/workflows/build_wheel_mac.yml b/.github/workflows/build_wheel_mac.yml index 9948a32759..a473cc9c4c 100644 --- a/.github/workflows/build_wheel_mac.yml +++ b/.github/workflows/build_wheel_mac.yml @@ -133,7 +133,7 @@ jobs: run: | # LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x # (see pybind11 static_assert on def_property + keep_alive). - pip install --no-cache-dir numpy 'pybind11<3' nanobind setuptools wheel delocate + pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' delocate - name: Set build directories run: | @@ -209,26 +209,27 @@ jobs: - name: Build PTOAS run: | - PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_CLI_VERSION}" \ - pip install . --no-build-isolation - - - name: Create Python wheel - if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' - run: | - export PTO_WHEEL_DIST_DIR=$PTO_SOURCE_DIR/build/wheel-dist - export PTOAS_PYTHON_PACKAGE_NAME="${PTOAS_PYTHON_PACKAGE_NAME}" - export PTOAS_PYTHON_PACKAGE_VERSION="${PTOAS_VERSION}" + if [ "${PTOAS_PYTHON_PACKAGE_NAME}" = "ptoas-vmi" ]; then + PTOAS_WHEEL_SOURCE_DIR="${PTO_SOURCE_DIR}/packaging/ptoas-vmi" + else + PTOAS_WHEEL_SOURCE_DIR="${PTO_SOURCE_DIR}" + fi if [ "${{ matrix.arch }}" = "x86_64" ]; then TARGET_ARCH="x86_64" else TARGET_ARCH="arm64" fi - # setup-python may provide a universal2 interpreter on macOS. - # Force a single-arch wheel tag to match the matrix target and delocate checks. - export WHEEL_PLAT_NAME=$(python "$PTO_SOURCE_DIR/docker/get_macos_wheel_plat_name.py" "$TARGET_ARCH") - bash $PTO_SOURCE_DIR/docker/create_wheel.sh + export _PYTHON_HOST_PLATFORM="$(python "$PTO_SOURCE_DIR/docker/get_macos_wheel_plat_name.py" "$TARGET_ARCH")" + rm -rf "${PTO_SOURCE_DIR}/build/wheel-dist" + mkdir -p "${PTO_SOURCE_DIR}/build/wheel-dist" + PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_CLI_VERSION}" \ + SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}" \ + python -m pip wheel "${PTOAS_WHEEL_SOURCE_DIR}" \ + --no-build-isolation --no-deps \ + --wheel-dir "${PTO_SOURCE_DIR}/build/wheel-dist" + cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" shopt -s nullglob - built_wheels=("$PTO_WHEEL_DIST_DIR"/ptoas*.whl) + built_wheels=("$PTO_SOURCE_DIR"/build/wheel-dist/ptoas*.whl) if [ "${#built_wheels[@]}" -gt 0 ]; then printf 'Built wheel file: %s\n' "$(basename "${built_wheels[0]}")" fi @@ -354,8 +355,8 @@ jobs: tar -xzf "$GITHUB_WORKSPACE/ptoas-bin-macos-${{ matrix.arch }}.tar.gz" -C "$TEST_DIR/extracted" test -x "$TEST_DIR/extracted/bin/ptoas" - test -f "$TEST_DIR/extracted/ptoas/_runtime_entry.py" - test -f "$TEST_DIR/extracted/ptoas_wheel_bootstrap.py" + test -f "$TEST_DIR/extracted/ptoas/_cli.py" + compgen -G "$TEST_DIR/extracted/ptoas/_native*.so" >/dev/null env -u PYTHONPATH -u DYLD_LIBRARY_PATH -u LD_LIBRARY_PATH \ "$TEST_DIR/extracted/bin/ptoas" --version diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2122c799bf..6a0cb90e87 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -133,7 +133,7 @@ jobs: libedit-dev zlib1g-dev libxml2-dev libzstd-dev python3 -m pip install --upgrade pip # LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x. - python3 -m pip install setuptools wheel 'pybind11<3' nanobind numpy + python3 -m pip install 'scikit-build-core>=0.12.2,<2' 'pybind11<3' nanobind numpy - name: Define payload paths shell: bash @@ -269,7 +269,7 @@ jobs: rm -rf "${PTOAS_VENV}" python3 -m venv "${PTOAS_VENV}" "${PTOAS_VENV}/bin/python" -m pip install --upgrade pip - "${PTOAS_VENV}/bin/pip" install setuptools wheel 'pybind11<3' nanobind numpy ml-dtypes + "${PTOAS_VENV}/bin/pip" install 'scikit-build-core>=0.12.2,<2' 'pybind11<3' nanobind numpy ml-dtypes - name: Build PTOAS wheel run: | @@ -278,13 +278,14 @@ jobs: rm -rf "${PTO_INSTALL_DIR}" rm -rf "${PTO_WHEELHOUSE}" mkdir -p "${PTO_WHEELHOUSE}" - # LLVM_BUILD_DIR is the env var read by the build backend (_ptoas_build_backend.py). + # scikit-build-core reuses this build tree so the following CTest and + # lit steps exercise the exact sources used to produce the wheel. LLVM_BUILD_DIR="${LLVM_DIR}" \ - PTO_BUILD_DIR="${PTO_BUILD_DIR}" \ - CMAKE_C_COMPILER="${PTOAS_CMAKE_C_COMPILER}" \ - CMAKE_CXX_COMPILER="${PTOAS_CMAKE_CXX_COMPILER}" \ - PTO_INSTALL_DIR="${PTO_INSTALL_DIR}" \ + SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}" \ + CC="${PTOAS_CMAKE_C_COMPILER}" \ + CXX="${PTOAS_CMAKE_CXX_COMPILER}" \ "${PTOAS_VENV}/bin/python" -m pip wheel . --no-build-isolation --no-deps --wheel-dir "${PTO_WHEELHOUSE}" + cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" - name: Install PTOAS wheel into test venv shell: bash diff --git a/.github/workflows/ci_sim.yml b/.github/workflows/ci_sim.yml index ca8ed9b7ee..13b41f5236 100644 --- a/.github/workflows/ci_sim.yml +++ b/.github/workflows/ci_sim.yml @@ -191,14 +191,14 @@ jobs: need_pip_install=0 python3 -c "import numpy" >/dev/null 2>&1 || need_pip_install=1 - python3 -c "import setuptools, wheel" >/dev/null 2>&1 || need_pip_install=1 + python3 -c "import scikit_build_core" >/dev/null 2>&1 || need_pip_install=1 python3 -m pybind11 --cmakedir >/dev/null 2>&1 || need_pip_install=1 python3 -m nanobind --cmake_dir >/dev/null 2>&1 || need_pip_install=1 python3 -c "import ml_dtypes" >/dev/null 2>&1 || need_pip_install=1 if [[ "${need_pip_install}" -eq 1 ]]; then python3 -m pip install --upgrade pip - python3 -m pip install setuptools wheel 'pybind11<3' nanobind numpy ml-dtypes + python3 -m pip install 'scikit-build-core>=0.12.2,<2' 'pybind11<3' nanobind numpy ml-dtypes fi - name: Resolve LLVM directories @@ -323,11 +323,10 @@ jobs: # Pin system compilers for the same reason as LLVM above. export CC=gcc export CXX=g++ - # LLVM_BUILD_DIR / PTO_INSTALL_DIR are read by the build backend - # while producing the wheel payload and staging native runtime bits. LLVM_BUILD_DIR="${LLVM_DIR}" \ - PTO_INSTALL_DIR="${PTO_INSTALL_DIR}" \ + SKBUILD_BUILD_DIR="${GITHUB_WORKSPACE}/build" \ python3 -m pip wheel . --no-build-isolation --no-deps --wheel-dir "${PTO_WHEELHOUSE}" + cmake --install "${GITHUB_WORKSPACE}/build" --prefix "${PTO_INSTALL_DIR}" - name: Create PTOAS simulator venv shell: bash @@ -605,6 +604,7 @@ jobs: deps = [ ("setuptools", "setuptools"), ("wheel", "wheel"), + ("scikit_build_core", "scikit-build-core>=0.12.2,<2"), ("nanobind", "nanobind"), ("numpy", "numpy"), ("ml_dtypes", "ml-dtypes"), @@ -795,9 +795,9 @@ jobs: export CC=gcc export CXX=g++ LLVM_BUILD_DIR="${PTO_DSL_ST_LLVM_DIR}" \ - PTO_BUILD_DIR="${PTO_DSL_ST_BUILD_DIR}" \ - PTO_INSTALL_DIR="${PTO_DSL_ST_INSTALL_DIR}" \ + SKBUILD_BUILD_DIR="${PTO_DSL_ST_BUILD_DIR}" \ "${PTO_DSL_ST_PYTHON_BIN}" -m pip wheel . --no-build-isolation --no-deps --wheel-dir "${PTO_DSL_ST_WHEELHOUSE}" + cmake --install "${PTO_DSL_ST_BUILD_DIR}" --prefix "${PTO_DSL_ST_INSTALL_DIR}" - name: Install PTODSL PTOAS wheel shell: bash diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fbd38cf68..a6f75436c9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -76,11 +76,42 @@ function(ptoas_preseed_compilers_from_llvm_cache) endif() endfunction() +# Standard Python build backends pass environment variables through to CMake +# but do not synthesize project-specific cache arguments. Accept the existing +# LLVM_BUILD_DIR convention directly so `pip wheel .` and `pip install .` can +# use the same configured LLVM tree as developer CMake builds. +if((NOT DEFINED LLVM_DIR OR LLVM_DIR STREQUAL "") + AND DEFINED ENV{LLVM_BUILD_DIR} + AND NOT "$ENV{LLVM_BUILD_DIR}" STREQUAL "") + set(LLVM_DIR "$ENV{LLVM_BUILD_DIR}/lib/cmake/llvm" CACHE PATH + "LLVM package directory derived from LLVM_BUILD_DIR") +endif() +if((NOT DEFINED MLIR_DIR OR MLIR_DIR STREQUAL "") + AND DEFINED ENV{LLVM_BUILD_DIR} + AND NOT "$ENV{LLVM_BUILD_DIR}" STREQUAL "") + set(MLIR_DIR "$ENV{LLVM_BUILD_DIR}/lib/cmake/mlir" CACHE PATH + "MLIR package directory derived from LLVM_BUILD_DIR") +endif() +if((NOT DEFINED MLIR_PYTHON_PACKAGE_DIR + OR MLIR_PYTHON_PACKAGE_DIR STREQUAL "") + AND DEFINED ENV{LLVM_BUILD_DIR} + AND NOT "$ENV{LLVM_BUILD_DIR}" STREQUAL "") + set(MLIR_PYTHON_PACKAGE_DIR + "$ENV{LLVM_BUILD_DIR}/tools/mlir/python_packages/mlir_core" + CACHE PATH "MLIR Python package derived from LLVM_BUILD_DIR") +endif() + ptoas_preseed_compilers_from_llvm_cache() project(ptoas VERSION 0.53) set(PTOAS_VMI_VERSION "0.1.4") +# Wheel builds carry the same Linux hardening policy as release CMake builds. +# Including the cache settings here keeps the policy backend-independent. +if(SKBUILD AND CMAKE_SYSTEM_NAME STREQUAL "Linux") + include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/LinuxHardeningCache.cmake") +endif() + option(PTOAS_VALIDATE_CMAKE4_FETCHCONTENT_COMPAT "Validate CMake 4 compatibility for legacy FetchContent users" OFF) if(PTOAS_VALIDATE_CMAKE4_FETCHCONTENT_COMPAT) @@ -242,6 +273,25 @@ if(PTO_ENABLE_PYTHON_BINDING) find_package(Python3 COMPONENTS Interpreter Development.Module REQUIRED) find_package(pybind11 CONFIG REQUIRED) + # A wheel must include the base MLIR Python package in addition to PTOAS's + # generated dialect modules. Normal CMake installs continue to use the LLVM + # installation supplied by the user and therefore do not duplicate it. + if(SKBUILD) + if(NOT MLIR_PYTHON_PACKAGE_DIR + OR NOT EXISTS "${MLIR_PYTHON_PACKAGE_DIR}/mlir") + message(FATAL_ERROR + "MLIR_PYTHON_PACKAGE_DIR must contain the MLIR Python package when " + "building a PTOAS wheel") + endif() + install( + DIRECTORY "${MLIR_PYTHON_PACKAGE_DIR}/mlir" + DESTINATION "." + COMPONENT PTOAS_Python + PATTERN "__pycache__" EXCLUDE + PATTERN "*.pyc" EXCLUDE + ) + endif() + # 设置 Python 扩展的输出目录,方便调试 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python/pto) @@ -280,6 +330,7 @@ if(BUILD_TESTING) "PYTHONPATH=${_pto_python_test_pythonpath}" "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:${_llvm_root}/lib:${CMAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}" "PATH=${CMAKE_BINARY_DIR}/tools/ptoas:${CMAKE_INSTALL_PREFIX}/bin:${_pto_python_bin_dir}:$ENV{PATH}" + "PTOAS_BIN=${CMAKE_BINARY_DIR}/tools/ptoas/ptoas" ) add_subdirectory(ptodsl/tests) diff --git a/_ptoas_build_backend.py b/_ptoas_build_backend.py deleted file mode 100644 index 1dfea891db..0000000000 --- a/_ptoas_build_backend.py +++ /dev/null @@ -1,375 +0,0 @@ -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -""" -PEP 517 build backend for ptoas. - -Runs the CMake build (assuming LLVM is already built), then delegates -wheel packaging to docker/create_wheel.sh. - -Environment variables (all optional): - LLVM_BUILD_DIR Path to LLVM build dir - (default: /llvm-workspace/llvm-project/build-shared) - PTO_BUILD_DIR Path to PTOAS build dir (default: /build) - PTO_INSTALL_DIR Install prefix (default: /install) - CMAKE_C_COMPILER Optional C compiler passed through to CMake - CMAKE_CXX_COMPILER Optional C++ compiler passed through to CMake - PTOAS_PYTHON_PACKAGE_NAME Wheel project-name override - PTOAS_PYTHON_PACKAGE_VERSION Wheel version override -""" -from __future__ import annotations - -import base64 -import glob -import hashlib -import io -import os -import re -import shutil -import subprocess -import sys -import zipfile -from pathlib import Path - -_REPO = Path(__file__).parent.resolve() - -def _find_llvm_dir(): - """Return an LLVM install or build-tree prefix, resolving in order: - - 1. ``LLVM_BUILD_DIR`` / ``LLVM_INSTALL_DIR`` env vars - 2. Auto-detect common install locations by probing ``lib/cmake/llvm`` - 3. Default build-tree path - """ - for key in ("LLVM_BUILD_DIR", "LLVM_INSTALL_DIR"): - if key in os.environ: - return Path(os.environ[key]) - - for cand in ("/usr/local/llvm", "/usr/local/Ascend/latest/compiler", - "/opt/llvm"): - if (Path(cand) / "lib" / "cmake" / "llvm").is_dir(): - return Path(cand) - - return Path("/llvm-workspace/llvm-project/build-shared") - - -_LLVM_BUILD_DIR = _find_llvm_dir() -_PTO_INSTALL_DIR = Path( - os.environ.get("PTO_INSTALL_DIR", str(_REPO / "install")) -) -_BUILD_DIR = Path(os.environ.get("PTO_BUILD_DIR", str(_REPO / "build"))) -_PTODSL_SOURCE_ROOT = _REPO / "ptodsl" -_MLIR_PY_PKG = None -if "MLIR_PYTHON_PACKAGE_DIR" in os.environ: - _MLIR_PY_PKG = Path(os.environ["MLIR_PYTHON_PACKAGE_DIR"]) -elif "LLVM_INSTALL_DIR" in os.environ: - _MLIR_PY_PKG = Path(os.environ["LLVM_INSTALL_DIR"]) / "python_packages" / "mlir_core" -else: - _installed = _LLVM_BUILD_DIR / "python_packages" / "mlir_core" - _build_tree = _LLVM_BUILD_DIR / "tools" / "mlir" / "python_packages" / "mlir_core" - _MLIR_PY_PKG = _installed if _installed.exists() else _build_tree -_WHEEL_DIST_DIR = _BUILD_DIR / "wheel-dist" -_PROJECT_VERSION_RE = re.compile( - r"project\s*\(\s*ptoas\s+VERSION\s+([0-9]+\.[0-9]+)\s*\)" -) -_PACKAGE_NAME_RE = re.compile( - r"^[A-Za-z0-9]+(?:[-_.][A-Za-z0-9]+)*$" -) - - -def _default_ptoas_package_name() -> str: - package_name = os.environ.get("PTOAS_PYTHON_PACKAGE_NAME", "").strip() - if not package_name: - return "ptoas" - if not _PACKAGE_NAME_RE.fullmatch(package_name): - raise RuntimeError( - "invalid PTOAS Python package name override " - f"{package_name!r}; expected a normalized project name" - ) - return package_name - - -def _wheel_distribution_name(package_name: str) -> str: - return re.sub(r"[-_.]+", "_", package_name) - - -def _assert_installed_ptodsl_payload() -> None: - """Fail fast if the root install tree did not stage the PTODSL package.""" - installed_init = _PTO_INSTALL_DIR / "ptodsl" / "__init__.py" - if installed_init.exists(): - return - raise RuntimeError( - "PTODSL is missing from the PTOAS install tree. " - f"Expected to find {installed_init}. " - "Root CMake install rules must stage the public 'ptodsl' package " - "before wheel assembly or installed-environment validation." - ) - - -def _assert_installed_ptoas_shared_module() -> None: - installed_shared_module = _PTO_INSTALL_DIR / "lib" / "ptoas.so" - if ( - installed_shared_module.is_file() - and installed_shared_module.stat().st_size > 0 - ): - return - raise RuntimeError( - "PTOAS shared launcher module is missing or empty in the PTOAS install tree. " - f"Expected to find {installed_shared_module}. " - "Wheel assembly now packages the shared module from the install tree." - ) - - -def _assert_editable_ptodsl_source() -> None: - """Fail fast if the editable install cannot point at the PTODSL source.""" - source_init = _PTODSL_SOURCE_ROOT / "ptodsl" / "__init__.py" - if source_init.exists(): - return - raise RuntimeError( - "PTODSL editable source is missing from the repository checkout. " - f"Expected to find {source_init}. " - "Root editable installs must expose the in-repo PTODSL sources." - ) - - -def _default_ptoas_version() -> str: - version = os.environ.get("PTOAS_PYTHON_PACKAGE_VERSION", "").strip() - if version: - return version - cmake_file = _REPO / "CMakeLists.txt" - match = _PROJECT_VERSION_RE.search(cmake_file.read_text(encoding="utf-8")) - if not match: - raise RuntimeError(f"could not find PTOAS version in {cmake_file}") - return match.group(1) - - -def get_requires_for_build_wheel(config_settings=None): - return ["setuptools>=68", "wheel", "pybind11<3"] - - -def get_requires_for_build_editable(config_settings=None): - return ["setuptools>=68", "wheel", "pybind11<3"] - - -def get_requires_for_build_sdist(config_settings=None): - return [] - - -def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None): - """Return wheel metadata without running the full build.""" - import email.message - - package_name = _default_ptoas_package_name() - dist_name = _wheel_distribution_name(package_name) - version = _default_ptoas_version() - dist_info = Path(metadata_directory) / f"{dist_name}-{version}.dist-info" - dist_info.mkdir(parents=True, exist_ok=True) - - meta = email.message.Message() - meta["Metadata-Version"] = "2.1" - meta["Name"] = package_name - meta["Version"] = version - meta["Summary"] = "PTO Assembler & Optimizer" - meta["Requires-Python"] = ">=3.9" - meta["License"] = "Apache-2.0" - meta["Requires-Dist"] = "numpy" - (dist_info / "METADATA").write_text(str(meta)) - (dist_info / "WHEEL").write_text( - "Wheel-Version: 1.0\nGenerator: _ptoas_build_backend\n" - "Root-Is-Purelib: True\nTag: py3-none-any\n" - ) - return dist_info.name - - -prepare_metadata_for_build_editable = prepare_metadata_for_build_wheel - - -def build_sdist(sdist_directory, config_settings=None): - raise NotImplementedError( - "ptoas does not support sdist. Use `pip install .` to build a wheel." - ) - - -def _should_use_linux_hardening_cache() -> bool: - return sys.platform.startswith("linux") - - -def _cmake_configure_and_build(skip_install=False): - """CMake configure + build + install.""" - _BUILD_DIR.mkdir(parents=True, exist_ok=True) - - pybind11_dir = subprocess.check_output( - [sys.executable, "-m", "pybind11", "--cmakedir"], text=True - ).strip() - - cmake_cmd = [ - "cmake", "-GNinja", - f"-S{_REPO}", f"-B{_BUILD_DIR}", - "-DCMAKE_BUILD_TYPE=Release", - "-DPTO_ENABLE_PYTHON_BINDING=ON", - f"-DLLVM_DIR={_LLVM_BUILD_DIR}/lib/cmake/llvm", - f"-DMLIR_DIR={_LLVM_BUILD_DIR}/lib/cmake/mlir", - f"-DPython3_ROOT_DIR={sys.prefix}", - f"-DPython3_EXECUTABLE={sys.executable}", - "-DPython3_FIND_STRATEGY=LOCATION", - f"-Dpybind11_DIR={pybind11_dir}", - f"-DMLIR_PYTHON_PACKAGE_DIR={_MLIR_PY_PKG}", - f"-DCMAKE_INSTALL_PREFIX={_PTO_INSTALL_DIR}", - ] - - for compiler_var in ("CMAKE_C_COMPILER", "CMAKE_CXX_COMPILER"): - compiler = os.environ.get(compiler_var, "").strip() - if compiler: - cmake_cmd.append(f"-D{compiler_var}={compiler}") - - release_version = os.environ.get("PTOAS_RELEASE_VERSION_OVERRIDE", "") - if release_version: - cmake_cmd.append(f"-DPTOAS_RELEASE_VERSION_OVERRIDE={release_version}") - - hardening_cache = _REPO / "cmake" / "LinuxHardeningCache.cmake" - if _should_use_linux_hardening_cache() and hardening_cache.exists(): - cmake_cmd.insert(1, f"-C{hardening_cache}") - - subprocess.check_call(cmake_cmd) - subprocess.check_call(["cmake", "--build", str(_BUILD_DIR)]) - if not skip_install: - subprocess.check_call( - ["cmake", "--build", str(_BUILD_DIR), "--target", "install"] - ) - _assert_installed_ptodsl_payload() - _assert_installed_ptoas_shared_module() - - -def build_wheel(wheel_directory, config_settings=None, metadata_directory=None): - _cmake_configure_and_build() - - package_name = _default_ptoas_package_name() - dist_name = _wheel_distribution_name(package_name) - env = os.environ.copy() - env.update({ - "PTO_SOURCE_DIR": str(_REPO), - "PTO_INSTALL_DIR": str(_PTO_INSTALL_DIR), - "PTO_BUILD_DIR": str(_BUILD_DIR), - "LLVM_BUILD_DIR": str(_LLVM_BUILD_DIR), - "PTO_WHEEL_DIST_DIR": str(_WHEEL_DIST_DIR), - # Keep wheel packaging on the same interpreter pip used to invoke the - # backend. This avoids drifting to a different `python3` on PATH in - # conda/self-hosted CI environments. - "PYTHON": sys.executable, - }) - subprocess.check_call( - ["bash", str(_REPO / "docker" / "create_wheel.sh")], - env=env, - ) - - wheels = sorted( - glob.glob(str(_WHEEL_DIST_DIR / f"{dist_name}-*.whl")), - key=os.path.getmtime, - ) - if not wheels: - raise RuntimeError( - f"No {dist_name}-*.whl found in {_WHEEL_DIST_DIR} after build." - ) - - wheel_path = Path(wheels[-1]) - dest = Path(wheel_directory) / wheel_path.name - shutil.copy2(wheel_path, dest) - return dest.name - - -def build_editable(wheel_directory, config_settings=None, metadata_directory=None): - """PEP 660 editable install. - - Builds the C++ extensions in-place, then produces a minimal wheel that - installs a .pth file pointing sys.path at the local PTODSL sources plus - the installed/runtime build outputs. No files are copied into - site-packages except the .pth file itself. - """ - _cmake_configure_and_build(skip_install=True) - _assert_editable_ptodsl_source() - - package_name = _default_ptoas_package_name() - dist_name = _wheel_distribution_name(package_name) - version = _default_ptoas_version() - - # Paths that must be on sys.path for the package to be importable - pth_paths = [ - # mlir.* namespace + _pto.so (installed there by CMake) - str(_MLIR_PY_PKG), - # Prefer the repository PTODSL sources so editable installs pick up - # local Python edits instead of staged/install-tree copies. - str(_PTODSL_SOURCE_ROOT), - # Handwritten Python sources (pto/dialects/pto.py, etc.). - str(_REPO / "python"), - # Installed PTOAS runtime overlay (TileOps/resources when present). - str(_PTO_INSTALL_DIR), - # Generated files (_pto.so, _pto_ops_gen.py) under mlir/ namespace. - str(_BUILD_DIR / "python"), - ] - - # Use executable .pth content so editable installs can deterministically - # prepend the repository PTODSL sources ahead of pre-existing build-tree - # entries in the caller's Python environment. - pth_content = ( - "import sys; " - f"pth_paths = {pth_paths!r}; " - "[sys.path.remove(path) for path in pth_paths if path in sys.path]; " - "sys.path[:0] = pth_paths\n" - ) - pth_filename = f"{dist_name}-editable.pth" - - # ---- Build the editable wheel (a zip with .pth + dist-info) ---- - tag = f"py3-none-any" - wheel_name = f"{dist_name}-{version}-{tag}.whl" - wheel_path = Path(wheel_directory) / wheel_name - - dist_info_dir = f"{dist_name}-{version}.dist-info" - - def _sha256_record(data: bytes) -> str: - digest = hashlib.sha256(data).digest() - b64 = base64.urlsafe_b64encode(digest).rstrip(b"=").decode() - return f"sha256={b64}" - - pth_bytes = pth_content.encode() - wheel_meta = ( - "Wheel-Version: 1.0\n" - "Generator: _ptoas_build_backend\n" - "Root-Is-Purelib: True\n" - f"Tag: {tag}\n" - "Build: editable\n" - ).encode() - entry_points = ( - "[console_scripts]\n" - "ptoas=ptoas_wheel_bootstrap:main\n" - ).encode() - metadata_content = ( - "Metadata-Version: 2.1\n" - f"Name: {package_name}\n" - f"Version: {version}\n" - "Summary: PTO Assembler & Optimizer\n" - "Requires-Python: >=3.9\n" - "License: Apache-2.0\n" - "Requires-Dist: numpy\n" - ).encode() - - record_lines = [ - f"{pth_filename},{_sha256_record(pth_bytes)},{len(pth_bytes)}", - f"{dist_info_dir}/WHEEL,{_sha256_record(wheel_meta)},{len(wheel_meta)}", - f"{dist_info_dir}/entry_points.txt,{_sha256_record(entry_points)},{len(entry_points)}", - f"{dist_info_dir}/METADATA,{_sha256_record(metadata_content)},{len(metadata_content)}", - f"{dist_info_dir}/RECORD,,", - ] - record_content = "\n".join(record_lines).encode() - - with zipfile.ZipFile(wheel_path, "w", compression=zipfile.ZIP_DEFLATED) as zf: - zf.writestr(pth_filename, pth_bytes) - zf.writestr(f"{dist_info_dir}/WHEEL", wheel_meta) - zf.writestr(f"{dist_info_dir}/entry_points.txt", entry_points) - zf.writestr(f"{dist_info_dir}/METADATA", metadata_content) - zf.writestr(f"{dist_info_dir}/RECORD", record_content) - - return wheel_name diff --git a/docker/Dockerfile b/docker/Dockerfile index 6d8f2fd1f3..aac5865981 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -20,7 +20,7 @@ ENV PATH="${PY_PATH}/bin:${PATH}" # dependency RUN dnf install -y ninja-build cmake git ccache gcc-c++ lld zip binutils patchelf chrpath && dnf clean all -RUN pip install --no-cache-dir numpy 'pybind11<3' nanobind setuptools wheel auditwheel +RUN pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' auditwheel COPY cmake/LinuxHardeningCache.cmake /tmp/LinuxHardeningCache.cmake @@ -31,7 +31,6 @@ ENV LLVM_BUILD_DIR=$LLVM_SOURCE_DIR/build-release ENV PTO_SOURCE_DIR=$WORKSPACE_DIR/PTOAS ENV PTO_BUILD_DIR=$PTO_SOURCE_DIR/build-release -ENV PTO_INSTALL_DIR=$PTO_SOURCE_DIR/install-release # build LLVM WORKDIR $WORKSPACE_DIR @@ -52,33 +51,19 @@ RUN cmake -C /tmp/LinuxHardeningCache.cmake -G Ninja -S llvm -B $LLVM_BUILD_DIR RUN ninja -C $LLVM_BUILD_DIR -# build ptoas +# build the ptoas wheel through the standard PEP 517 backend WORKDIR $WORKSPACE_DIR RUN git clone https://github.com/zhangstevenunity/PTOAS.git # TODO: tag git commit of PTOAS repo WORKDIR $PTO_SOURCE_DIR -RUN cmake -C /tmp/LinuxHardeningCache.cmake -G Ninja \ - -S . \ - -B $PTO_BUILD_DIR \ - -DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \ - -DMLIR_DIR=$LLVM_BUILD_DIR/lib/cmake/mlir \ - -DPython3_ROOT_DIR=${PY_PATH} \ - -DPython3_EXECUTABLE=${PY_PATH}/bin/python \ - -DPython3_FIND_STRATEGY=LOCATION \ - -Dpybind11_DIR=$(python -m pybind11 --cmakedir) \ - -DMLIR_PYTHON_PACKAGE_DIR=${LLVM_BUILD_DIR}/tools/mlir/python_packages/mlir_core \ - -DCMAKE_INSTALL_PREFIX=${PTO_INSTALL_DIR} \ - -DCMAKE_BUILD_TYPE=Release - -RUN ninja -C $PTO_BUILD_DIR && ninja -C $PTO_BUILD_DIR install - -# create python wheel ENV PTO_WHEEL_DIST_DIR=$PTO_SOURCE_DIR/build/wheel-dist -RUN bash "$PTO_SOURCE_DIR/docker/create_wheel.sh" +RUN SKBUILD_BUILD_DIR=$PTO_BUILD_DIR \ + python -m pip wheel . --no-build-isolation --no-deps \ + --wheel-dir "$PTO_WHEEL_DIST_DIR" # fix missing so -RUN export LD_LIBRARY_PATH=$LLVM_BUILD_DIR/lib:$PTO_INSTALL_DIR/lib:$LD_LIBRARY_PATH \ +RUN export LD_LIBRARY_PATH=$LLVM_BUILD_DIR/lib:$LD_LIBRARY_PATH \ && auditwheel repair --plat manylinux_2_34_${ARCH} "$PTO_WHEEL_DIST_DIR"/ptoas*.whl -w /wheelhouse RUN pip install /wheelhouse/ptoas*.whl diff --git a/docker/collect_ptoas_dist.sh b/docker/collect_ptoas_dist.sh index 83f9f7299f..798260e036 100755 --- a/docker/collect_ptoas_dist.sh +++ b/docker/collect_ptoas_dist.sh @@ -13,18 +13,14 @@ # # Required environment variables: # LLVM_BUILD_DIR - Path to LLVM build directory -# PTO_BUILD_DIR - Path to PTO build directory (optional, defaults to PTO_SOURCE_DIR/build) # PTO_INSTALL_DIR - Path to PTO install directory # PTO_SOURCE_DIR - Path to PTO source directory # # Output structure: # / -# bin/ptoas - Python wrapper entrypoint -# ptoas/ - Launcher package used by the wrapper -# ptoas_wheel_bootstrap.py - Compatibility bootstrap module -# lib/ptoas.so - Shared runtime loaded by the launcher +# bin/ptoas - Python console wrapper +# ptoas/ - CLI package and native extension # lib/*.so* - Required shared library dependencies -# share/ptoas/TileOps - TileLang template library # tilelang_dsl/ - TileLang DSL Python package # # This compiler-oriented binary artifact intentionally does not bundle the @@ -49,37 +45,21 @@ done export LD_LIBRARY_PATH="${LLVM_BUILD_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}" -PTO_BUILD_DIR="${PTO_BUILD_DIR:-${PTO_SOURCE_DIR}/build}" -PTOAS_BIN="${PTO_BUILD_DIR}/tools/ptoas/ptoas" -PTOAS_SHARED_MODULE="${PTO_INSTALL_DIR}/lib/ptoas.so" +PTOAS_BIN="${PTO_INSTALL_DIR}/bin/ptoas" +PTOAS_PACKAGE_SRC_DIR="${PTO_INSTALL_DIR}/ptoas" +PTOAS_PACKAGE_DIST_DIR="${PTOAS_DIST_DIR}/ptoas" PTOAS_DEPS_DIR="${PTOAS_DIST_DIR}/lib" -PTOAS_SHARED_MODULE_DIST_PATH="${PTOAS_DEPS_DIR}/ptoas.so" -PTOAS_TILEOPS_SRC_DIR="${PTO_INSTALL_DIR}/share/ptoas/TileOps" -PTOAS_TILEOPS_DIST_DIR="${PTOAS_DIST_DIR}/share/ptoas/TileOps" PTOAS_TILELANG_DSL_SRC_DIR="${PTO_INSTALL_DIR}/tilelang_dsl" PTOAS_TILELANG_DSL_DIST_DIR="${PTOAS_DIST_DIR}/tilelang_dsl" -PTOAS_WRAPPER_PKG_SRC_DIR="${PTO_INSTALL_DIR}/ptoas" -PTOAS_WRAPPER_PKG_DIST_DIR="${PTOAS_DIST_DIR}/ptoas" -PTOAS_WHEEL_BOOTSTRAP_SRC="${PTO_INSTALL_DIR}/ptoas_wheel_bootstrap.py" -PTOAS_WHEEL_BOOTSTRAP_DIST_PATH="${PTOAS_DIST_DIR}/ptoas_wheel_bootstrap.py" if [ ! -f "$PTOAS_BIN" ]; then - echo "Error: ptoas wrapper not found at $PTOAS_BIN" >&2 + echo "Error: installed ptoas wrapper not found at $PTOAS_BIN" >&2 exit 1 fi -if [ ! -f "$PTOAS_SHARED_MODULE" ]; then - echo "Error: shared launcher module not found at $PTOAS_SHARED_MODULE" >&2 +if [ ! -d "$PTOAS_PACKAGE_SRC_DIR" ]; then + echo "Error: installed ptoas package not found at $PTOAS_PACKAGE_SRC_DIR" >&2 exit 1 fi -if [ ! -d "$PTOAS_WRAPPER_PKG_SRC_DIR" ]; then - echo "Error: ptoas Python package not found at $PTOAS_WRAPPER_PKG_SRC_DIR" >&2 - exit 1 -fi -if [ ! -f "$PTOAS_WHEEL_BOOTSTRAP_SRC" ]; then - echo "Error: ptoas wheel bootstrap module not found at $PTOAS_WHEEL_BOOTSTRAP_SRC" >&2 - exit 1 -fi - remove_rpath() { local path="$1" if ! has_rpath "$path"; then @@ -163,21 +143,19 @@ harden_elf() { # Create output directories mkdir -p \ "${PTOAS_DIST_DIR}/bin" \ - "${PTOAS_DEPS_DIR}" \ - "$(dirname "${PTOAS_TILEOPS_DIST_DIR}")" -rm -rf "${PTOAS_WRAPPER_PKG_DIST_DIR}" "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}" -cp -R "${PTOAS_WRAPPER_PKG_SRC_DIR}" "${PTOAS_WRAPPER_PKG_DIST_DIR}" -cp "${PTOAS_WHEEL_BOOTSTRAP_SRC}" "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}" - -# Copy ptoas binary -echo "Copying ptoas wrapper..." -cp "$PTOAS_BIN" "${PTOAS_DIST_DIR}/bin/" + "${PTOAS_DEPS_DIR}" +rm -rf "${PTOAS_PACKAGE_DIST_DIR}" +cp -R "${PTOAS_PACKAGE_SRC_DIR}" "${PTOAS_PACKAGE_DIST_DIR}" +cp "$PTOAS_BIN" "${PTOAS_DIST_DIR}/bin/ptoas" chmod +x "${PTOAS_DIST_DIR}/bin/ptoas" -echo "Copying ptoas shared runtime..." -cp -fL "$PTOAS_SHARED_MODULE" "${PTOAS_SHARED_MODULE_DIST_PATH}" +PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}" -maxdepth 1 -type f -name '_native*.so' -print -quit)" +if [ -z "${PTOAS_NATIVE_MODULE}" ]; then + echo "Error: packaged ptoas._native extension not found" >&2 + exit 1 +fi -# Collect non-system *.so dependencies needed by the packaged shared runtime. +# Collect non-system dependencies needed by the Python extension. echo "Collecting shared library dependencies..." linux_runtime_dep_paths() { local path="$1" @@ -216,28 +194,28 @@ while read -r res; do [[ -n "$res" ]] || continue should_bundle_linux_dep "$res" || continue copy_so "$res" -done < <(linux_runtime_dep_paths "$PTOAS_BIN") -while read -r res; do - [[ -n "$res" ]] || continue - should_bundle_linux_dep "$res" || continue - copy_so "$res" -done < <(linux_runtime_dep_paths "$PTOAS_SHARED_MODULE") +done < <(linux_runtime_dep_paths "${PTOAS_NATIVE_MODULE}") while read -r packaged; do harden_elf "$packaged" done < <(find "${PTOAS_DEPS_DIR}" -type f | sort) -echo "Copying TileLang runtime resources..." -if [ ! -d "${PTOAS_TILEOPS_SRC_DIR}" ]; then - echo "Error: TileOps resource directory not found at ${PTOAS_TILEOPS_SRC_DIR}" >&2 +if ! command -v patchelf >/dev/null 2>&1; then + echo "Error: patchelf is required to make the ptoas archive relocatable" >&2 exit 1 fi +while read -r packaged; do + patchelf --set-rpath '$ORIGIN' "$packaged" +done < <(find "${PTOAS_DEPS_DIR}" -type f | sort) +harden_elf "${PTOAS_NATIVE_MODULE}" +patchelf --set-rpath '$ORIGIN/../lib' "${PTOAS_NATIVE_MODULE}" + +echo "Copying TileLang runtime resources..." if [ ! -d "${PTOAS_TILELANG_DSL_SRC_DIR}" ]; then echo "Error: tilelang_dsl package directory not found at ${PTOAS_TILELANG_DSL_SRC_DIR}" >&2 exit 1 fi -rm -rf "${PTOAS_TILEOPS_DIST_DIR}" "${PTOAS_TILELANG_DSL_DIST_DIR}" -cp -R "${PTOAS_TILEOPS_SRC_DIR}" "${PTOAS_TILEOPS_DIST_DIR}" +rm -rf "${PTOAS_TILELANG_DSL_DIST_DIR}" cp -R "${PTOAS_TILELANG_DSL_SRC_DIR}" "${PTOAS_TILELANG_DSL_DIST_DIR}" echo "Smoke testing packaged ptoas dist..." @@ -255,11 +233,9 @@ else echo "$VERSION_OUTPUT" | grep -Eq '^ptoas [0-9]+\.[0-9]+$' fi -test -d "${PTOAS_TILEOPS_DIST_DIR}" +test -f "${PTOAS_PACKAGE_DIST_DIR}/_cli.py" +test -d "${PTOAS_PACKAGE_DIST_DIR}/_runtime/share/ptoas/TileOps" test -f "${PTOAS_TILELANG_DSL_DIST_DIR}/__init__.py" -test -f "${PTOAS_SHARED_MODULE_DIST_PATH}" -test -f "${PTOAS_WRAPPER_PKG_DIST_DIR}/_runtime_entry.py" -test -f "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}" if [ -e "${PTOAS_DIST_DIR}/ptodsl" ]; then echo "Error: compiler-oriented ptoas dist must not bundle PTODSL" >&2 exit 1 @@ -270,7 +246,7 @@ echo "" echo "=== ptoas distribution contents ===" ls -la "${PTOAS_DIST_DIR}/" ls -la "${PTOAS_DIST_DIR}/bin/" -ls -la "${PTOAS_DIST_DIR}/share/ptoas/" +ls -la "${PTOAS_PACKAGE_DIST_DIR}/" ls -la "${PTOAS_TILELANG_DSL_DIST_DIR}" SO_COUNT=$(find "${PTOAS_DEPS_DIR}" -name "*.so*" 2>/dev/null | wc -l) echo "=== Collected .so dependencies (${SO_COUNT} files) ===" diff --git a/docker/collect_ptoas_dist_mac.sh b/docker/collect_ptoas_dist_mac.sh index ee4a1f1f7e..a3fb2c13d2 100644 --- a/docker/collect_ptoas_dist_mac.sh +++ b/docker/collect_ptoas_dist_mac.sh @@ -13,18 +13,14 @@ # # Required environment variables: # LLVM_BUILD_DIR - Path to LLVM build directory -# PTO_BUILD_DIR - Path to PTO build directory (optional, defaults to PTO_SOURCE_DIR/build) # PTO_INSTALL_DIR - Path to PTO install directory # PTO_SOURCE_DIR - Path to PTO source directory # # Output structure: # / -# bin/ptoas - Python wrapper entrypoint -# ptoas/ - Launcher package used by the wrapper -# ptoas_wheel_bootstrap.py - Compatibility bootstrap module -# lib/ptoas.so - Shared runtime loaded by the launcher +# bin/ptoas - Python console wrapper +# ptoas/ - CLI package and native extension # lib/*.dylib - Required shared library dependencies -# share/ptoas/TileOps - TileLang template library # tilelang_dsl/ - TileLang DSL Python package # # This compiler-oriented binary artifact intentionally does not bundle the @@ -47,48 +43,35 @@ for var in LLVM_BUILD_DIR PTO_INSTALL_DIR PTO_SOURCE_DIR; do fi done -PTO_BUILD_DIR="${PTO_BUILD_DIR:-${PTO_SOURCE_DIR}/build}" -PTOAS_BIN="${PTO_BUILD_DIR}/tools/ptoas/ptoas" -PTOAS_SHARED_MODULE="${PTO_INSTALL_DIR}/lib/ptoas.so" +PTOAS_BIN="${PTO_INSTALL_DIR}/bin/ptoas" +PTOAS_PACKAGE_SRC_DIR="${PTO_INSTALL_DIR}/ptoas" +PTOAS_PACKAGE_DIST_DIR="${PTOAS_DIST_DIR}/ptoas" PTOAS_DEPS_DIR="${PTOAS_DIST_DIR}/lib" -PTOAS_SHARED_MODULE_DIST_PATH="${PTOAS_DEPS_DIR}/ptoas.so" -PTOAS_TILEOPS_SRC_DIR="${PTO_INSTALL_DIR}/share/ptoas/TileOps" -PTOAS_TILEOPS_DIST_DIR="${PTOAS_DIST_DIR}/share/ptoas/TileOps" PTOAS_TILELANG_DSL_SRC_DIR="${PTO_INSTALL_DIR}/tilelang_dsl" PTOAS_TILELANG_DSL_DIST_DIR="${PTOAS_DIST_DIR}/tilelang_dsl" -PTOAS_WRAPPER_PKG_SRC_DIR="${PTO_INSTALL_DIR}/ptoas" -PTOAS_WRAPPER_PKG_DIST_DIR="${PTOAS_DIST_DIR}/ptoas" -PTOAS_WHEEL_BOOTSTRAP_SRC="${PTO_INSTALL_DIR}/ptoas_wheel_bootstrap.py" -PTOAS_WHEEL_BOOTSTRAP_DIST_PATH="${PTOAS_DIST_DIR}/ptoas_wheel_bootstrap.py" UNRESOLVED_NON_SYSTEM_COUNT=0 if [ ! -f "$PTOAS_BIN" ]; then - echo "Error: ptoas wrapper not found at $PTOAS_BIN" >&2 + echo "Error: installed ptoas wrapper not found at $PTOAS_BIN" >&2 exit 1 fi -if [ ! -f "$PTOAS_SHARED_MODULE" ]; then - echo "Error: shared launcher module not found at $PTOAS_SHARED_MODULE" >&2 +if [ ! -d "$PTOAS_PACKAGE_SRC_DIR" ]; then + echo "Error: installed ptoas package not found at $PTOAS_PACKAGE_SRC_DIR" >&2 exit 1 fi -if [ ! -d "$PTOAS_WRAPPER_PKG_SRC_DIR" ]; then - echo "Error: ptoas Python package not found at $PTOAS_WRAPPER_PKG_SRC_DIR" >&2 - exit 1 -fi -if [ ! -f "$PTOAS_WHEEL_BOOTSTRAP_SRC" ]; then - echo "Error: ptoas wheel bootstrap module not found at $PTOAS_WHEEL_BOOTSTRAP_SRC" >&2 - exit 1 -fi - mkdir -p \ "${PTOAS_DIST_DIR}/bin" \ - "${PTOAS_DEPS_DIR}" \ - "$(dirname "${PTOAS_TILEOPS_DIST_DIR}")" -rm -rf "${PTOAS_WRAPPER_PKG_DIST_DIR}" "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}" -cp -R "${PTOAS_WRAPPER_PKG_SRC_DIR}" "${PTOAS_WRAPPER_PKG_DIST_DIR}" -cp "${PTOAS_WHEEL_BOOTSTRAP_SRC}" "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}" -cp -fL "$PTOAS_BIN" "${PTOAS_DIST_DIR}/bin/" + "${PTOAS_DEPS_DIR}" +rm -rf "${PTOAS_PACKAGE_DIST_DIR}" +cp -R "${PTOAS_PACKAGE_SRC_DIR}" "${PTOAS_PACKAGE_DIST_DIR}" +cp -fL "$PTOAS_BIN" "${PTOAS_DIST_DIR}/bin/ptoas" chmod +x "${PTOAS_DIST_DIR}/bin/ptoas" -cp -fL "$PTOAS_SHARED_MODULE" "${PTOAS_SHARED_MODULE_DIST_PATH}" + +PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}" -maxdepth 1 -type f -name '_native*.so' -print -quit)" +if [ -z "${PTOAS_NATIVE_MODULE}" ]; then + echo "Error: packaged ptoas._native extension not found" >&2 + exit 1 +fi # Resolve @rpath / @loader_path / @executable_path / absolute install names. resolve_dep_path() { @@ -189,6 +172,7 @@ from pathlib import Path dist_dir = Path(sys.argv[1]).resolve() deps_dir = Path(sys.argv[2]).resolve() bin_dir = (dist_dir / "bin").resolve() +package_dir = (dist_dir / "ptoas").resolve() allowed_prefixes = ( "@loader_path/", "@rpath/", @@ -209,13 +193,15 @@ def is_under(path: Path, root: Path) -> bool: def packaged_dep_ref(owner: Path, dep_base: str) -> str: if is_under(owner, bin_dir): return f"@loader_path/../lib/{dep_base}" + if is_under(owner, package_dir): + return f"@loader_path/../lib/{dep_base}" if is_under(owner, deps_dir): return f"@loader_path/{dep_base}" return f"@loader_path/{dep_base}" def iter_targets(): - for root in (bin_dir, deps_dir): + for root in (package_dir, deps_dir): if not root.exists(): continue for base, _, files in os.walk(root): @@ -272,19 +258,14 @@ PY } echo "Collecting dylib dependencies..." -collect_dylibs "${PTOAS_SHARED_MODULE_DIST_PATH}" +collect_dylibs "${PTOAS_NATIVE_MODULE}" echo "Copying TileLang runtime resources..." -if [[ ! -d "${PTOAS_TILEOPS_SRC_DIR}" ]]; then - echo "Error: TileOps resource directory not found at ${PTOAS_TILEOPS_SRC_DIR}" >&2 - exit 1 -fi if [[ ! -d "${PTOAS_TILELANG_DSL_SRC_DIR}" ]]; then echo "Error: tilelang_dsl package directory not found at ${PTOAS_TILELANG_DSL_SRC_DIR}" >&2 exit 1 fi -rm -rf "${PTOAS_TILEOPS_DIST_DIR}" "${PTOAS_TILELANG_DSL_DIST_DIR}" -cp -R "${PTOAS_TILEOPS_SRC_DIR}" "${PTOAS_TILEOPS_DIST_DIR}" +rm -rf "${PTOAS_TILELANG_DSL_DIST_DIR}" cp -R "${PTOAS_TILELANG_DSL_SRC_DIR}" "${PTOAS_TILELANG_DSL_DIST_DIR}" if [[ -e "${PTOAS_DIST_DIR}/ptodsl" ]]; then echo "Error: compiler-oriented ptoas dist must not bundle PTODSL" >&2 @@ -350,7 +331,7 @@ fi echo "Ad-hoc signing packaged binaries and dylibs..." shopt -s nullglob -SIGN_TARGETS=("${PTOAS_DEPS_DIR}"/*.so "${PTOAS_DEPS_DIR}"/*.dylib) +SIGN_TARGETS=("${PTOAS_NATIVE_MODULE}" "${PTOAS_DEPS_DIR}"/*.so "${PTOAS_DEPS_DIR}"/*.dylib) for target in "${SIGN_TARGETS[@]}"; do codesign --force --sign - --timestamp=none "$target" done @@ -375,11 +356,9 @@ if [ -n "${EXPECTED_PTOAS_CLI_VERSION}" ]; then else echo "$VERSION_OUTPUT" | grep -Eq '^ptoas [0-9]+\.[0-9]+$' fi -test -d "${PTOAS_TILEOPS_DIST_DIR}" +test -f "${PTOAS_PACKAGE_DIST_DIR}/_cli.py" +test -d "${PTOAS_PACKAGE_DIST_DIR}/_runtime/share/ptoas/TileOps" test -f "${PTOAS_TILELANG_DSL_DIST_DIR}/__init__.py" -test -f "${PTOAS_SHARED_MODULE_DIST_PATH}" -test -f "${PTOAS_WRAPPER_PKG_DIST_DIR}/_runtime_entry.py" -test -f "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}" env -u DYLD_LIBRARY_PATH -u LD_LIBRARY_PATH \ "${PTOAS_DIST_DIR}/bin/ptoas" \ "${PTO_SOURCE_DIR}/test/lit/pto/kernel_kind_vector_scf_while_emitc.pto" \ @@ -389,7 +368,7 @@ echo "" echo "=== ptoas distribution contents ===" ls -la "${PTOAS_DIST_DIR}/" ls -la "${PTOAS_DIST_DIR}/bin/" -ls -la "${PTOAS_DIST_DIR}/share/ptoas/" +ls -la "${PTOAS_PACKAGE_DIST_DIR}/" ls -la "${PTOAS_TILELANG_DSL_DIST_DIR}" DYLIB_COUNT=$(find "${PTOAS_DEPS_DIR}" -name "*.dylib" 2>/dev/null | wc -l) echo "=== Collected .dylib dependencies (${DYLIB_COUNT} files) ===" diff --git a/docker/copy_ptoas_deps.sh b/docker/copy_ptoas_deps.sh deleted file mode 100644 index 6ddc187138..0000000000 --- a/docker/copy_ptoas_deps.sh +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -# Collect only non-system *.so actually needed by the packaged ptoas shared -# runtime. The `ptoas` wrapper is a Python script, so dependency discovery must -# start from `ptoas.so` instead of running `ldd` on the wrapper itself. -# -# Expects: LLVM_BUILD_DIR, PTO_INSTALL_DIR, PTOAS_DEPS_DIR - -set -euo pipefail - -export LD_LIBRARY_PATH="${LLVM_BUILD_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}" -PTOAS_SHARED_MODULE="${PTO_INSTALL_DIR}/lib/ptoas.so" - -if [[ ! -f "${PTOAS_SHARED_MODULE}" ]]; then - echo "Error: shared launcher module not found at ${PTOAS_SHARED_MODULE}" >&2 - exit 1 -fi - -remove_rpath() { - local path="$1" - if ! has_rpath "$path"; then - return - fi - if ! can_scrub_rpath; then - echo "WARN: skipping RPATH/RUNPATH scrub for ${path}; install patchelf or chrpath to harden local dist artifacts" >&2 - return - fi - if command -v patchelf >/dev/null 2>&1; then - patchelf --remove-rpath "$path" - fi - if has_rpath "$path" && command -v chrpath >/dev/null 2>&1; then - chrpath -d "$path" - fi - if has_rpath "$path"; then - echo "Error: failed to scrub RPATH/RUNPATH from ${path}" >&2 - exit 1 - fi -} - -strip_symbols() { - local path="$1" - strip --strip-unneeded "$path" -} - -has_rpath() { - local path="$1" - if command -v patchelf >/dev/null 2>&1; then - local rpath_value - rpath_value="$(patchelf --print-rpath "$path" 2>/dev/null || true)" - [[ -n "$rpath_value" ]] - return - fi - readelf -d "$path" 2>/dev/null | grep -Eq '(RPATH|RUNPATH)' -} - -can_scrub_rpath() { - command -v patchelf >/dev/null 2>&1 || command -v chrpath >/dev/null 2>&1 -} - -assert_relro() { - local path="$1" - if ! readelf -l "$path" 2>/dev/null | grep -q 'GNU_RELRO'; then - echo "WARN: RELRO segment missing in ${path}" >&2 - return - fi - if ! readelf -d "$path" 2>/dev/null | grep -Eq '(BIND_NOW|FLAGS.*NOW|FLAGS_1.*NOW)'; then - echo "WARN: NOW binding missing in ${path}" >&2 - fi -} - -assert_no_symtab() { - local path="$1" - if readelf -S "$path" 2>/dev/null | grep -Eq '[[:space:]]\\.symtab[[:space:]]'; then - echo "Error: symbol table still present in ${path}" >&2 - exit 1 - fi -} - -assert_no_rpath() { - local path="$1" - if ! can_scrub_rpath; then - return - fi - if has_rpath "$path"; then - echo "Error: runtime search path still present in ${path}" >&2 - exit 1 - fi -} - -harden_elf() { - local path="$1" - remove_rpath "$path" - strip_symbols "$path" - assert_relro "$path" - assert_no_symtab "$path" - assert_no_rpath "$path" -} - -copy_so() { - local f="$1" - [[ -f "$f" ]] || return 0 - local name - name=$(basename "$f") - [[ -f "${PTOAS_DEPS_DIR}/${name}" ]] && return 0 - cp -L -n "$f" "${PTOAS_DEPS_DIR}/" 2>/dev/null || true - harden_elf "${PTOAS_DEPS_DIR}/${name}" - while read -r res; do - [[ -n "$res" ]] || continue - should_bundle_linux_dep "$res" || continue - copy_so "$res" - done < <(linux_runtime_dep_paths "$f") -} - -linux_runtime_dep_paths() { - local path="$1" - ldd "$path" 2>/dev/null | awk ' - /=> \// { print $3 } - /^\// { print $1 } - ' -} - -should_bundle_linux_dep() { - local path="$1" - case "$path" in - /lib/*|/lib64/*|/usr/lib/*|/usr/lib64/*) - return 1 - ;; - esac - return 0 -} - -mkdir -p "$PTOAS_DEPS_DIR" -while read -r res; do - [[ -n "$res" ]] || continue - should_bundle_linux_dep "$res" || continue - copy_so "$res" -done < <(linux_runtime_dep_paths "$PTOAS_SHARED_MODULE") - -while read -r packaged; do - harden_elf "$packaged" -done < <(find "$PTOAS_DEPS_DIR" -type f | sort) diff --git a/docker/create_wheel.sh b/docker/create_wheel.sh deleted file mode 100755 index 36a9f8fa6d..0000000000 --- a/docker/create_wheel.sh +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -set -euo pipefail - -for var in PTO_SOURCE_DIR PTO_INSTALL_DIR LLVM_BUILD_DIR; do - if [[ -z "${!var:-}" ]]; then - echo "Error: $var environment variable is not set" >&2 - exit 1 - fi -done - -WHEEL_STAGING_DIR="${PTO_WHEEL_STAGING_DIR:-${PTO_SOURCE_DIR}/build/wheel-staging}" -WHEEL_DIST_DIR="${PTO_WHEEL_DIST_DIR:-${PTO_SOURCE_DIR}/build/wheel-dist}" -RUNTIME_STAGING_DIR="${PTO_RUNTIME_STAGING_DIR:-${PTO_SOURCE_DIR}/build/runtime-staging}" -PTO_BUILD_DIR="${PTO_BUILD_DIR:-${PTO_SOURCE_DIR}/build}" -PYTHON_BIN="${PYTHON:-python3}" -PTOAS_PYTHON_PACKAGE_NAME="${PTOAS_PYTHON_PACKAGE_NAME:-ptoas}" -PTOAS_PYTHON_PACKAGE_VERSION="${PTOAS_PYTHON_PACKAGE_VERSION:-${PTOAS_VERSION:-}}" -PTOAS_CLI_VERSION="${PTOAS_CLI_VERSION:-${PTOAS_VERSION:-}}" -if [[ ! "${PTOAS_PYTHON_PACKAGE_NAME}" =~ ^[A-Za-z0-9]+([-_.][A-Za-z0-9]+)*$ ]]; then - echo "Error: invalid PTOAS_PYTHON_PACKAGE_NAME '${PTOAS_PYTHON_PACKAGE_NAME}'; expected a normalized project name" >&2 - exit 1 -fi -PTOAS_WHEEL_DISTRIBUTION_NAME="$(printf '%s' "${PTOAS_PYTHON_PACKAGE_NAME}" | sed -E 's/[-_.]+/_/g')" -PTOAS_WRAPPER_PKG_DIR="${PTO_SOURCE_DIR}/ptodsl/ptoas" -PTOAS_WHEEL_BOOTSTRAP="${PTO_SOURCE_DIR}/ptodsl/ptoas_wheel_bootstrap.py" -PTODSL_INSTALL_DIR="${PTO_INSTALL_DIR}/ptodsl" -MLIR_PYTHON_PACKAGE_DIR="${LLVM_BUILD_DIR}/tools/mlir/python_packages/mlir_core" - -if [[ -z "${PTOAS_PYTHON_PACKAGE_VERSION}" ]]; then - PTOAS_PYTHON_PACKAGE_VERSION="$("${PYTHON_BIN}" "${PTO_SOURCE_DIR}/.github/scripts/compute_ptoas_version.py" \ - --cmake-file "${PTO_SOURCE_DIR}/CMakeLists.txt" --mode dev)" -fi -export PTOAS_PYTHON_PACKAGE_VERSION - -linux_runtime_dep_paths() { - local path="$1" - local library_path="${2:-}" - if [[ -n "${library_path}" ]]; then - env LD_LIBRARY_PATH="${library_path}" ldd "$path" 2>/dev/null | awk ' - /=> \// { print $3 } - /^\// { print $1 } - ' - return - fi - ldd "$path" 2>/dev/null | awk ' - /=> \// { print $3 } - /^\// { print $1 } - ' -} - -should_bundle_linux_dep() { - local path="$1" - case "$path" in - /lib/*|/lib64/*|/usr/lib/*|/usr/lib64/*) - return 1 - ;; - esac - return 0 -} - -assemble_linux_wheel_runtime() { - local ptoas_wrapper="${PTO_INSTALL_DIR}/bin/ptoas" - if [[ ! -f "${ptoas_wrapper}" ]]; then - ptoas_wrapper="${PTO_BUILD_DIR}/tools/ptoas/ptoas" - fi - if [[ ! -f "${ptoas_wrapper}" ]]; then - echo "Error: ptoas wrapper not found in build tree or install tree" >&2 - exit 1 - fi - if [[ ! -d "${PTO_INSTALL_DIR}/share/ptoas/TileOps" ]]; then - echo "Error: TileOps resource directory not found at ${PTO_INSTALL_DIR}/share/ptoas/TileOps" >&2 - exit 1 - fi - - mkdir -p "${RUNTIME_STAGING_DIR}/lib" "${RUNTIME_STAGING_DIR}/share/ptoas" - cp -R "${PTO_INSTALL_DIR}/share/ptoas/TileOps" "${RUNTIME_STAGING_DIR}/share/ptoas/TileOps" - cp "${PTO_INSTALL_DIR}/lib/ptoas.so" "${RUNTIME_STAGING_DIR}/lib/ptoas.so" - - # Resolve transitive MLIR/LLVM dependencies through the build tree so - # ldd can discover non-installed libs such as libMLIRMlirOptMain.so.*. - local dep_ld_library_path="${LLVM_BUILD_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}" - while read -r dep_path; do - [[ -n "${dep_path}" ]] || continue - should_bundle_linux_dep "${dep_path}" || continue - cp -L -n "${dep_path}" "${RUNTIME_STAGING_DIR}/lib/" - done < <(linux_runtime_dep_paths "${PTO_INSTALL_DIR}/lib/ptoas.so" "${dep_ld_library_path}" | sort -u) - - local version_output - local version_ld_library_path="${LLVM_BUILD_DIR}/lib:${RUNTIME_STAGING_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}" - version_output="$( - env -u PYTHONPATH -u DYLD_LIBRARY_PATH \ - LD_LIBRARY_PATH="${version_ld_library_path}" \ - "${ptoas_wrapper}" --version | tr -d '\r' - )" - echo "${version_output}" - if [[ -n "${PTOAS_CLI_VERSION:-}" ]]; then - local expected_version_output="ptoas ${PTOAS_CLI_VERSION}" - if [[ "${version_output}" != "${expected_version_output}" ]]; then - echo "Error: expected '${expected_version_output}', got '${version_output}'" >&2 - exit 1 - fi - else - echo "${version_output}" | grep -Eq '^ptoas [0-9]+\.[0-9]+$' - fi -} - -echo "Creating Python wheel..." -echo "Wheel package version: ${PTOAS_PYTHON_PACKAGE_VERSION}" - -rm -rf "${WHEEL_STAGING_DIR}" "${WHEEL_DIST_DIR}" "${RUNTIME_STAGING_DIR}" -mkdir -p "${WHEEL_STAGING_DIR}" "${WHEEL_DIST_DIR}" - -echo "Assembling unified runtime staging tree..." -case "$(uname -s)" in - Darwin) - bash "${PTO_SOURCE_DIR}/docker/collect_ptoas_dist_mac.sh" "${RUNTIME_STAGING_DIR}" - ;; - *) - assemble_linux_wheel_runtime - ;; -esac - -echo "Copying MLIR Python package into wheel staging..." -cp -a "${MLIR_PYTHON_PACKAGE_DIR}/." "${WHEEL_STAGING_DIR}/" - -echo "Overlaying PTO dialect files..." -mkdir -p "${WHEEL_STAGING_DIR}/mlir/dialects" -find "${PTO_INSTALL_DIR}/mlir/dialects" -maxdepth 1 -type f -name '*.py' -exec cp {} "${WHEEL_STAGING_DIR}/mlir/dialects/" \; - -echo "Overlaying PTO native extension..." -mkdir -p "${WHEEL_STAGING_DIR}/mlir/_mlir_libs" -find "${PTO_INSTALL_DIR}/mlir/_mlir_libs" -maxdepth 1 -type f -name '_pto*' -exec cp {} "${WHEEL_STAGING_DIR}/mlir/_mlir_libs/" \; - -echo "Copying TileLang resources..." -rm -rf "${WHEEL_STAGING_DIR}/tilelang_dsl" "${WHEEL_STAGING_DIR}/TileOps" -cp -R "${PTO_INSTALL_DIR}/tilelang_dsl" "${WHEEL_STAGING_DIR}/tilelang_dsl" -cp -R "${PTO_INSTALL_DIR}/share/ptoas/TileOps" "${WHEEL_STAGING_DIR}/TileOps" - -echo "Copying ptodsl package..." -if [[ ! -d "${PTODSL_INSTALL_DIR}" ]]; then - echo "Error: ptodsl package directory not found at ${PTODSL_INSTALL_DIR}" >&2 - exit 1 -fi -if [[ ! -f "${PTODSL_INSTALL_DIR}/__init__.py" ]]; then - echo "Error: ptodsl package is missing ${PTODSL_INSTALL_DIR}/__init__.py" >&2 - exit 1 -fi -rm -rf "${WHEEL_STAGING_DIR}/ptodsl" -cp -R "${PTODSL_INSTALL_DIR}" "${WHEEL_STAGING_DIR}/ptodsl" - -echo "Copying ptoas wheel wrapper package..." -if [[ ! -d "${PTOAS_WRAPPER_PKG_DIR}" ]]; then - echo "Error: ptoas wrapper package directory not found at ${PTOAS_WRAPPER_PKG_DIR}" >&2 - exit 1 -fi -if [[ ! -f "${PTOAS_WRAPPER_PKG_DIR}/__init__.py" ]]; then - echo "Error: ptoas wrapper package is missing ${PTOAS_WRAPPER_PKG_DIR}/__init__.py" >&2 - exit 1 -fi -cp -R "${PTOAS_WRAPPER_PKG_DIR}" "${WHEEL_STAGING_DIR}/ptoas" -if [[ ! -f "${PTOAS_WHEEL_BOOTSTRAP}" ]]; then - echo "Error: ptoas wheel bootstrap module not found at ${PTOAS_WHEEL_BOOTSTRAP}" >&2 - exit 1 -fi -cp "${PTOAS_WHEEL_BOOTSTRAP}" "${WHEEL_STAGING_DIR}/ptoas_wheel_bootstrap.py" - -echo "Embedding unified runtime payload for wheel-side ptoas launcher..." -mkdir -p "${WHEEL_STAGING_DIR}/ptoas/_runtime" -cp -R "${RUNTIME_STAGING_DIR}/share" "${WHEEL_STAGING_DIR}/ptoas/_runtime/share" -cp -R "${RUNTIME_STAGING_DIR}/lib" "${WHEEL_STAGING_DIR}/ptoas/_runtime/lib" - -echo "Removing packaging residue..." -find "${WHEEL_STAGING_DIR}" \( -name '*.egg-info' -o -name '*.dist-info' \) -prune -exec rm -rf {} + -find "${WHEEL_STAGING_DIR}" -name '__pycache__' -prune -exec rm -rf {} + - -export PTO_WHEEL_STAGING_DIR="${WHEEL_STAGING_DIR}" -export PTO_WHEEL_DIST_DIR="${WHEEL_DIST_DIR}" -export PTOAS_PYTHON_PACKAGE_NAME -export PTOAS_PYTHON_PACKAGE_VERSION -export PTOAS_WHEEL_DISTRIBUTION_NAME - -echo "Building wheel archive directly..." -"${PYTHON_BIN}" - <<'PY' -import base64 -import csv -import hashlib -import os -import platform -import re -import sys -import zipfile -from pathlib import Path - -staging = Path(os.environ["PTO_WHEEL_STAGING_DIR"]) -dist = Path(os.environ["PTO_WHEEL_DIST_DIR"]) -project_name = os.environ["PTOAS_PYTHON_PACKAGE_NAME"] -version = os.environ["PTOAS_PYTHON_PACKAGE_VERSION"] -dist_name = os.environ.get("PTOAS_WHEEL_DISTRIBUTION_NAME") or re.sub( - r"[-_.]+", "_", project_name -) - -py_tag = f"cp{sys.version_info.major}{sys.version_info.minor}" -if sys.platform == "darwin": - platform_tag = os.environ.get("WHEEL_PLAT_NAME") or "macosx_11_0_arm64" -else: - arch = platform.machine().lower().replace("-", "_") - platform_tag = os.environ.get("WHEEL_PLAT_NAME") or f"linux_{arch}" - -wheel_name = f"{dist_name}-{version}-{py_tag}-{py_tag}-{platform_tag}.whl" -wheel_path = dist / wheel_name -dist_info = f"{dist_name}-{version}.dist-info" - -metadata = "\n".join([ - "Metadata-Version: 2.1", - f"Name: {project_name}", - f"Version: {version}", - "Summary: PTO Assembler & Optimizer", - "Requires-Python: >=3.9", - "License: Apache-2.0", - "Requires-Dist: numpy", - "", -]).encode("utf-8") - -wheel = "\n".join([ - "Wheel-Version: 1.0", - "Generator: create_wheel.sh", - "Root-Is-Purelib: false", - f"Tag: {py_tag}-{py_tag}-{platform_tag}", - "", -]).encode("utf-8") - -record_rows = [] -has_ptodsl_init = False -has_ptoas_shared_module = False - -def hash_bytes(data: bytes) -> str: - digest = hashlib.sha256(data).digest() - return "sha256=" + base64.urlsafe_b64encode(digest).rstrip(b"=").decode("ascii") - -with zipfile.ZipFile(wheel_path, "w", compression=zipfile.ZIP_DEFLATED) as zf: - for path in sorted(staging.rglob("*")): - if not path.is_file(): - continue - rel = path.relative_to(staging).as_posix() - data = path.read_bytes() - zf.write(path, rel) - record_rows.append((rel, hash_bytes(data), str(len(data)))) - if rel == "ptodsl/__init__.py": - has_ptodsl_init = True - if rel == "ptoas/_runtime/lib/ptoas.so": - has_ptoas_shared_module = True - - entry_points = "\n".join([ - "[console_scripts]", - "ptoas=ptoas_wheel_bootstrap:main", - "", - ]).encode("utf-8") - - for rel, data in [ - (f"{dist_info}/METADATA", metadata), - (f"{dist_info}/WHEEL", wheel), - (f"{dist_info}/entry_points.txt", entry_points), - ]: - zf.writestr(rel, data) - record_rows.append((rel, hash_bytes(data), str(len(data)))) - - record_rel = f"{dist_info}/RECORD" - from io import StringIO - buf = StringIO() - writer = csv.writer(buf, lineterminator="\n") - for row in record_rows: - writer.writerow(row) - writer.writerow((record_rel, "", "")) - record_bytes = buf.getvalue().encode("utf-8") - zf.writestr(record_rel, record_bytes) - -if not has_ptodsl_init: - raise SystemExit("Wheel staging payload is missing ptodsl/__init__.py") -if not has_ptoas_shared_module: - raise SystemExit("Wheel staging payload is missing ptoas/_runtime/lib/ptoas.so") - -with zipfile.ZipFile(wheel_path) as zf: - if "ptodsl/__init__.py" not in zf.namelist(): - raise SystemExit("Built wheel is missing ptodsl/__init__.py") - if "ptoas/_runtime/lib/ptoas.so" not in zf.namelist(): - raise SystemExit("Built wheel is missing ptoas/_runtime/lib/ptoas.so") - if "ptoas/_runtime/bin/ptoas" in zf.namelist(): - raise SystemExit("Built wheel unexpectedly contains ptoas/_runtime/bin/ptoas") - -print(f"Wheel created at {wheel_path}") -PY - -echo "Wheel package name: ${PTOAS_PYTHON_PACKAGE_NAME}" -echo "Wheel created at ${WHEEL_DIST_DIR}/" -ls -la "${WHEEL_DIST_DIR}/"*.whl - -EXPECTED_WHEEL_GLOB="${WHEEL_DIST_DIR}/${PTOAS_WHEEL_DISTRIBUTION_NAME}-${PTOAS_PYTHON_PACKAGE_VERSION}-"*.whl -if ! compgen -G "${EXPECTED_WHEEL_GLOB}" >/dev/null 2>&1; then - echo "Error: expected wheel matching ${EXPECTED_WHEEL_GLOB}" >&2 - exit 1 -fi diff --git a/docker/setup.py b/docker/setup.py deleted file mode 100644 index e6820d5faf..0000000000 --- a/docker/setup.py +++ /dev/null @@ -1,54 +0,0 @@ -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import os -import pathlib -import re - -from setuptools import setup, find_namespace_packages - - -_PROJECT_VERSION_RE = re.compile( - r"project\s*\(\s*ptoas\s+VERSION\s+([0-9]+\.[0-9]+)\s*\)" -) - - -def read_package_name() -> str: - package_name = os.environ.get("PTOAS_PYTHON_PACKAGE_NAME", "").strip() - return package_name or "ptoas" - - -def read_package_version() -> str: - version = os.environ.get("PTOAS_PYTHON_PACKAGE_VERSION", "").strip() - if version: - return version - cmake_file = pathlib.Path(__file__).resolve().parents[1] / "CMakeLists.txt" - match = _PROJECT_VERSION_RE.search(cmake_file.read_text(encoding="utf-8")) - if not match: - raise RuntimeError(f"could not find PTOAS version in {cmake_file}") - return match.group(1) - -setup( - name=read_package_name(), - version=read_package_version(), - description="PTO Assembler & Optimizer", - # NOTE: find_namespace_packages detects folders even without __init__.py - packages=find_namespace_packages(), - # NOTE: The * at the end captures .so.22, .so.22.1, etc. - package_data={ - "mlir": [ - "**/*.so*", - "**/*.pyd", - "**/*.py", - "_mlir_libs/*.so*", - ], - }, - include_package_data=True, - zip_safe=False, - python_requires=">=3.9", -) diff --git a/docker/setup_mac.py b/docker/setup_mac.py deleted file mode 100644 index c61ad3e1a5..0000000000 --- a/docker/setup_mac.py +++ /dev/null @@ -1,64 +0,0 @@ -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import os -import pathlib -import re - -from setuptools import find_namespace_packages, setup -from setuptools.dist import Distribution - - -class BinaryDistribution(Distribution): - """Force a platform-tagged wheel for macOS artifacts.""" - - def has_ext_modules(self): - return True - - -def read_package_name() -> str: - package_name = os.environ.get("PTOAS_PYTHON_PACKAGE_NAME", "").strip() - return package_name or "ptoas" - - -def read_package_version() -> str: - version = os.environ.get("PTOAS_PYTHON_PACKAGE_VERSION", "").strip() - if version: - return version - cmake_file = pathlib.Path(__file__).resolve().parents[1] / "CMakeLists.txt" - project_version_re = re.compile( - r"project\s*\(\s*ptoas\s+VERSION\s+([0-9]+\.[0-9]+)\s*\)" - ) - match = project_version_re.search(cmake_file.read_text(encoding="utf-8")) - if not match: - raise RuntimeError(f"could not find PTOAS version in {cmake_file}") - return match.group(1) - -setup( - name=read_package_name(), - version=read_package_version(), - description="PTO Assembler & Optimizer", - # NOTE: find_namespace_packages detects folders even without __init__.py - packages=find_namespace_packages(), - # Include native libraries used by macOS wheels (.dylib), while keeping - # existing patterns so this file remains robust across build layouts. - package_data={ - "mlir": [ - "**/*.dylib", - "_mlir_libs/*.dylib", - "**/*.so*", - "**/*.pyd", - "**/*.py", - "_mlir_libs/*.so*", - ], - }, - include_package_data=True, - zip_safe=False, - python_requires=">=3.9", - distclass=BinaryDistribution, -) diff --git a/docker/test_wheel_imports.sh b/docker/test_wheel_imports.sh index 50d20694a0..f06b6938b4 100755 --- a/docker/test_wheel_imports.sh +++ b/docker/test_wheel_imports.sh @@ -89,6 +89,7 @@ echo "Testing ptodsl public imports..." "$PYTHON_BIN" -c "from ptodsl import pto, scalar; print('ptodsl public imports imported successfully')" echo "Testing installed ptoas console entry..." +"$PYTHON_BIN" -c "from ptoas import _native; print(f'ptoas native extension imported successfully from {_native.__file__}')" PTOAS_VERSION_OUTPUT="$(ptoas --version | tr -d '\r')" echo "${PTOAS_VERSION_OUTPUT}" EXPECTED_PTOAS_CLI_VERSION="${PTOAS_CLI_VERSION:-${PTOAS_VERSION:-}}" @@ -102,33 +103,6 @@ else echo "${PTOAS_VERSION_OUTPUT}" | grep -Eq '^ptoas [0-9]+\.[0-9]+$' fi -echo "Testing installed ptoas console entry under polluted Python and LLVM paths..." -POLLUTED_ENV_DIR="${TEST_TMPDIR}/polluted-env" -mkdir -p "${POLLUTED_ENV_DIR}/ptoas" -cat > "${POLLUTED_ENV_DIR}/ptoas/__init__.py" <<'PY' -raise RuntimeError("shadow ptoas package must not be imported") -PY -cat > "${POLLUTED_ENV_DIR}/ptoas/_runtime_entry.py" <<'PY' -raise RuntimeError("shadow runtime entry must not be imported") -PY -POLLUTED_PTOAS_VERSION_OUTPUT="$( - env \ - PYTHONPATH="${POLLUTED_ENV_DIR}" \ - LD_LIBRARY_PATH="/tmp/polluted-llvm" \ - DYLD_LIBRARY_PATH="/tmp/polluted-dylib" \ - "${PTOAS_ENTRYPOINT}" --version | tr -d '\r' -)" -echo "${POLLUTED_PTOAS_VERSION_OUTPUT}" -if [[ -n "${EXPECTED_PTOAS_CLI_VERSION}" ]]; then - EXPECTED_VERSION_OUTPUT="ptoas ${EXPECTED_PTOAS_CLI_VERSION}" - if [[ "${POLLUTED_PTOAS_VERSION_OUTPUT}" != "${EXPECTED_VERSION_OUTPUT}" ]]; then - echo "Error: expected '${EXPECTED_VERSION_OUTPUT}', got '${POLLUTED_PTOAS_VERSION_OUTPUT}'" >&2 - exit 1 - fi -else - echo "${POLLUTED_PTOAS_VERSION_OUTPUT}" | grep -Eq '^ptoas [0-9]+\.[0-9]+$' -fi - echo "Testing installed ptoas console entry in a clean environment..." CLEAN_ENV_DIR="${TEST_TMPDIR}/clean-env" CLEAN_ENV_PTO="${CLEAN_ENV_DIR}/wheel-clean-env-probe.pto" diff --git a/docker/validate_wheel_payload.py b/docker/validate_wheel_payload.py index 15da0c69cc..2d4879d0d6 100644 --- a/docker/validate_wheel_payload.py +++ b/docker/validate_wheel_payload.py @@ -12,22 +12,25 @@ from __future__ import annotations import argparse +import importlib.machinery import zipfile from pathlib import Path REQUIRED_FILES = { - "ptoas_wheel_bootstrap.py", "ptoas/__init__.py", - "ptoas/_launcher.py", - "ptoas/_runtime_entry.py", - "ptoas/_runtime/lib/ptoas.so", + "ptoas/_cli.py", + "ptoas/_runtime/share/ptoas/TileOps/__init__.py", } FORBIDDEN_FILES = { "ptoas/_runtime/bin/ptoas", } -PTOAS_ENTRYPOINT_TARGET = "ptoas_wheel_bootstrap:main" +PTOAS_ENTRYPOINT_TARGET = "ptoas._cli:main" WHEEL_GLOB = "ptoas*.whl" +NATIVE_MODULE_PATHS = { + f"ptoas/_native{suffix}" + for suffix in importlib.machinery.EXTENSION_SUFFIXES +} def _resolve_wheel(candidate: str) -> Path: @@ -83,6 +86,13 @@ def validate_wheel_payload(wheel: Path) -> None: if missing: raise SystemExit(f"wheel is missing required payload files: {missing}") + native_modules = sorted(NATIVE_MODULE_PATHS & names) + if len(native_modules) != 1: + raise SystemExit( + "wheel must contain exactly one importable ptoas._native extension, " + f"found {native_modules}" + ) + present_forbidden = sorted(FORBIDDEN_FILES & names) if present_forbidden: raise SystemExit( @@ -107,7 +117,7 @@ def validate_wheel_payload(wheel: Path) -> None: if console_scripts.get("ptoas") != PTOAS_ENTRYPOINT_TARGET: raise SystemExit( "wheel entry points do not route ptoas through " - "ptoas_wheel_bootstrap:main" + f"{PTOAS_ENTRYPOINT_TARGET}" ) diff --git a/docs/designs/ptoas-python-launcher-layout.md b/docs/designs/ptoas-python-launcher-layout.md index 3cf5a59d42..382cf1cd4e 100644 --- a/docs/designs/ptoas-python-launcher-layout.md +++ b/docs/designs/ptoas-python-launcher-layout.md @@ -12,122 +12,102 @@ This document records the internal launcher contract for the Python-backed `ptoas` command. The user-facing README should describe how to install and run -PTOAS, but it should not expose this implementation detail. - -The wheel launcher intentionally uses a Python wrapper instead of packaging the -native `ptoas` executable as the console entry. This avoids auditwheel / -manylinux handling issues for native executables while still letting the wheel -ship the native compiler implementation as a shared library. - -## Goals - -- Keep wheel, build-tree, and install-tree startup deterministic. -- Resolve Python packages and runtime payloads from the current distribution - layout only. -- Avoid falling back to unrelated source checkouts, editable installs, or - ambient `PYTHONPATH` entries. -- Avoid loading duplicated LLVM/MLIR shared libraries inside one Python process. -- Keep `ptoas._launcher` importable temporarily as a compatibility shim, but do - not treat it as a stable public API. +PTOAS without exposing these implementation details. ## Entry Model -The launcher has three layers: +The wheel, build-tree, and install-tree launchers use the standard Python +console-script and native-extension model: ```text -distribution-specific entry - -> layout resolver - -> ptoas._runtime_entry.launch() - -> ctypes loads ptoas.so - -> calls ptoas_entrypoint(argc, argv) +console script or CMake tree wrapper + -> ptoas._cli.main() + -> import ptoas._native + -> ptoas._native.main(argv) ``` -`ptoas._runtime_entry` is the shared execution layer. It should not guess which -distribution layout is active; callers pass a resolved `PTOASRuntimeLayout`. +`ptoas._native` is built with `pybind11_add_module`. CMake and Python therefore +own the platform and ABI-specific filename. Launcher and packaging code refer to +the import name and never construct `.so`, `.dylib`, or `.pyd` paths. -## Wheel Layout - -Wheel console scripts point to the top-level `ptoas_wheel_bootstrap:main` -module, not to `ptoas._launcher:main`. +The LLVM-based driver implementation is compiled as an object library so it +can use LLVM's RTTI and exception settings independently from pybind11. Those +objects are linked into the Python extension; no separate native executable is +produced. Wheel and standalone-archive entrypoints therefore use the same +extension and CLI module. -The bootstrap module lives outside the `ptoas` package so that the console entry -can identify the installed wheel root before importing `ptoas`. This prevents a -polluted `PYTHONPATH` from resolving a shadow `ptoas` package from a source -checkout or another environment. +## Wheel Layout -Wheel startup is a two-stage process: +Wheel console scripts point directly to `ptoas._cli:main`. The CLI imports the +native extension through Python's normal package machinery and resolves TileOps +package data relative to the installed extension. It does not re-execute itself, +load modules by file path, rewrite `PYTHONPATH`, or override Python's standard +package precedence rules. -1. Stage 1 resolves the wheel-owned package root and runtime root. -2. Stage 1 `execve`s the same console script with a sanitized environment. -3. Stage 2 imports the wheel-owned `ptoas._runtime_entry`. -4. Stage 2 calls the shared `ptoas_entrypoint` from - `ptoas/_runtime/lib/ptoas.so`. +Editable installs use scikit-build-core's redirect mode. The backend maps the +Python sources to the checkout and the CMake-installed native extension to the +editable build output without package-local path manipulation. -In stage 2, the environment is isolated: +Auditwheel and delocate discover the native extension through the standard +wheel binary scan, bundle its dependencies, and rewrite its runtime search +paths. The launcher does not preload or enumerate those libraries. -- `PYTHONPATH` is set to the wheel site-packages root. -- `LD_LIBRARY_PATH` is set to `ptoas/_runtime/lib`. -- `DYLD_LIBRARY_PATH` is set to `ptoas/_runtime/lib`. +Wheel and editable builds use `scikit-build-core` directly as the PEP 517/660 +backend. Project metadata and the console entry point live in `pyproject.toml`; +wheel tags, metadata, RECORD generation, CMake configure/build/install, and +editable redirects are owned by the backend rather than repository scripts. -Wheel mode must not preload every shared library under `ptoas/_runtime/lib` -before loading `ptoas.so`. Auditwheel may rewrite `ptoas.so` dependencies to -hashed libraries under `.libs`. If the launcher preloads the -unhashed runtime copies first and `ptoas.so` then loads the auditwheel-rewritten -copies, LLVM/MLIR command-line options can be registered twice in the same -process. +The main `pyproject.toml` has the static distribution name `ptoas`. +`packaging/ptoas-vmi/pyproject.toml` is a second static PEP 621 project for the +mutually exclusive `ptoas-vmi` distribution. Both projects build the same CMake +source and install the same `ptoas` import package. This keeps project names +standards-compliant because PEP 621 does not permit a dynamic `project.name`. -Therefore wheel mode lets the dynamic loader resolve `ptoas.so` dependencies -from the already-sanitized process environment and the auditwheel RPATH. +CMake's `PTOAS_Python` install component contains only the generated/native +wheel payload. Python source packages are declared through +`tool.scikit-build.wheel.packages`, which also lets editable installs redirect +imports to the source tree without namespace-package or custom `.pth` logic. ## Build-Tree Layout -The build-tree wrapper is generated for one build directory and resolves only -that tree's staged payload: +The build-tree wrapper resolves only its own generated outputs: - wrapper: `/tools/ptoas/ptoas` - Python root: `/python` -- runtime root: `/runtime-staging` -- shared entry: `/runtime-staging/lib/ptoas.so` +- native module: importable as `ptoas._native` from the Python root +- TileOps: `/python/ptoas/_runtime/share/ptoas/TileOps` -If the staged Python package or runtime payload is missing, the wrapper fails -with a layout error. It must not repair startup by searching unrelated Python -roots or source checkouts. - -Build-tree mode prepends the tree-owned Python and library paths to the current -environment. Because changing `LD_LIBRARY_PATH` after process startup is not a -reliable way to affect subsequent `dlopen` resolution on glibc, build-tree mode -may preload runtime libraries before loading `ptoas.so`. +Missing Python packages or TileOps resources are hard layout errors. The +wrapper only adds `/python` to `sys.path`; `ptoas._cli` owns the common +runtime-resource resolution and native invocation. ## Install-Tree Layout -The install-tree wrapper resolves only files installed under the same prefix: +The install-tree wrapper resolves only files under the same prefix: - wrapper: `/bin/ptoas` -- Python root: the installed PTOAS Python package root under that prefix -- runtime root: the installed PTOAS runtime payload under that prefix -- shared entry: `/lib/ptoas.so` - -As with build-tree mode, missing installed payloads are hard layout errors, not -signals to search another checkout or wheel. - -Install-tree mode follows the same dynamic-library policy as build-tree mode: -it may preload runtime libraries before loading `ptoas.so` because the process -was not re-execed with a fully isolated library environment. +- Python root: `` +- native module: importable as `ptoas._native` from the Python root +- TileOps: `/ptoas/_runtime/share/ptoas/TileOps` -## Compatibility Shim +The install-tree wrapper only adds `` to `sys.path`, then delegates to +the same `ptoas._cli` module used by wheels. -`ptoas._launcher` remains importable for a transition period and forwards to the -new launcher path. New code should invoke the `ptoas` command instead of -importing `ptoas._launcher` directly. +## Standalone Archive Layout -The shim exists only to keep older internal scripts from breaking immediately. -It should not grow new layout-resolution logic. +Standalone compiler archives contain the installed Python wrapper and package: -## Non-Goals +```text +bin/ptoas +ptoas/_cli.py +ptoas/_native..so +ptoas/_runtime/share/ptoas/TileOps +lib/ +tilelang_dsl/ +``` -- Support installing `ptoas` and `ptoas-vmi` into the same Python environment. - Those distributions share the same import package and console script and are - intentionally mutually exclusive. -- Support arbitrary `PTOAS_PYTHON_ROOT` fallback search in normal launcher - operation. -- Replace the wheel Python wrapper with a native executable console entry. +The archive requires a Python interpreter compatible with the packaged +extension ABI. `bin/ptoas` adds the archive root to `sys.path`, then uses the +same `ptoas._cli -> ptoas._native` path as the install tree. Linux archives set +the extension runtime path to `$ORIGIN/../lib`; macOS archives rewrite the +extension's install names relative to its package directory. diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index 4e484668bd..215f385a8e 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -71,6 +71,7 @@ endif() install(TARGETS _pto LIBRARY DESTINATION "mlir/_mlir_libs" + COMPONENT PTOAS_Python ) # ---- 2) Generate ODS Python op bindings: _pto_ops_gen.py ---- @@ -103,6 +104,7 @@ install(FILES "${PTO_PY_SRC}" "${CMAKE_CURRENT_BINARY_DIR}/_pto_ops_gen.py" DESTINATION mlir/dialects + COMPONENT PTOAS_Python ) # Keep the MLIR build-tree Python package self-consistent as well. When users diff --git a/packaging/ptoas-vmi/pyproject.toml b/packaging/ptoas-vmi/pyproject.toml new file mode 100644 index 0000000000..d9c28bd5e4 --- /dev/null +++ b/packaging/ptoas-vmi/pyproject.toml @@ -0,0 +1,60 @@ +# Copyright (c) 2026 Huawei Technologies Co., Ltd. +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of +# CANN Open Software License Agreement Version 2.0 (the "License"). +# Please refer to the License for details. You may not use this file except in compliance with the License. +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE in the root of the software repository for the full text of the License. + +# The VMI distribution intentionally installs the same `ptoas` import package +# and console script as the main distribution. The two wheels are mutually +# exclusive; this separate static PEP 621 project supplies the distribution +# name required by package indexes without a custom build backend. + +[build-system] +requires = ["scikit-build-core>=0.12.2,<2", "pybind11<3"] +build-backend = "scikit_build_core.build" + +[project] +name = "ptoas-vmi" +dynamic = ["version"] +description = "PTO Assembler & Optimizer with VMI support" +requires-python = ">=3.9" +license = "Apache-2.0" +dependencies = [ + "numpy", +] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", +] + +[project.scripts] +ptoas = "ptoas._cli:main" + +[tool.scikit-build] +minimum-version = "build-system.requires" +cmake.source-dir = "../.." +cmake.version = "CMakeLists.txt" +ninja.version = ">=1.10" +build.verbose = false +editable.mode = "redirect" +install.components = ["PTOAS_Python"] + +[tool.scikit-build.wheel.packages] +ptodsl = "../../ptodsl/ptodsl" +ptoas = "../../ptodsl/ptoas" +tilelang_dsl = "../../tilelang-dsl/python/tilelang_dsl" + +[tool.scikit-build.cmake.define] +PTOAS_RELEASE_VERSION_OVERRIDE = { env = "PTOAS_RELEASE_VERSION_OVERRIDE", default = "" } + +[tool.scikit-build.metadata.version] +provider = "scikit_build_core.metadata.regex" +input = "../../docs/release/VMI_VERSION" +regex = '^(?P[0-9]+\.[0-9]+\.[0-9]+)\s*$' diff --git a/ptodsl/CMakeLists.txt b/ptodsl/CMakeLists.txt index 4123b99996..ef602d320f 100644 --- a/ptodsl/CMakeLists.txt +++ b/ptodsl/CMakeLists.txt @@ -12,29 +12,16 @@ set(PTODSL_PACKAGE_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ptodsl") -set(PTOAS_PY_PACKAGE_SRC_DIR - "${CMAKE_CURRENT_SOURCE_DIR}/ptoas") -set(PTOAS_WHEEL_BOOTSTRAP_SOURCE - "${CMAKE_CURRENT_SOURCE_DIR}/ptoas_wheel_bootstrap.py") set(PTODSL_BUILD_ROOT "${CMAKE_BINARY_DIR}/python") set(PTODSL_BUILD_PACKAGE_DIR "${PTODSL_BUILD_ROOT}/ptodsl") -set(PTOAS_PY_BUILD_PACKAGE_DIR - "${PTODSL_BUILD_ROOT}/ptoas") add_custom_target(PTODSLPackage ALL COMMAND ${CMAKE_COMMAND} -E make_directory "${PTODSL_BUILD_ROOT}" COMMAND ${CMAKE_COMMAND} -E remove_directory "${PTODSL_BUILD_PACKAGE_DIR}" - COMMAND ${CMAKE_COMMAND} -E remove_directory "${PTOAS_PY_BUILD_PACKAGE_DIR}" COMMAND ${CMAKE_COMMAND} -E copy_directory "${PTODSL_PACKAGE_SRC_DIR}" "${PTODSL_BUILD_PACKAGE_DIR}" - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${PTOAS_PY_PACKAGE_SRC_DIR}" - "${PTOAS_PY_BUILD_PACKAGE_DIR}" - COMMAND ${CMAKE_COMMAND} -E copy - "${PTOAS_WHEEL_BOOTSTRAP_SOURCE}" - "${PTODSL_BUILD_ROOT}/ptoas_wheel_bootstrap.py" COMMENT "Staging ptodsl package into build/python" VERBATIM ) @@ -48,15 +35,9 @@ install( ) install( - DIRECTORY "${PTOAS_PY_PACKAGE_SRC_DIR}" + DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ptoas" DESTINATION "." COMPONENT PTOAS_Runtime PATTERN "__pycache__" EXCLUDE PATTERN "*.pyc" EXCLUDE ) - -install( - FILES "${PTOAS_WHEEL_BOOTSTRAP_SOURCE}" - DESTINATION "." - COMPONENT PTOAS_Runtime -) diff --git a/ptodsl/ptoas/__init__.py b/ptodsl/ptoas/__init__.py index 20c98a7808..e7a40405e2 100644 --- a/ptodsl/ptoas/__init__.py +++ b/ptodsl/ptoas/__init__.py @@ -6,5 +6,4 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -"""PTOAS wheel runtime helpers.""" - +"""Python package for the PTOAS command-line interface.""" diff --git a/ptodsl/ptoas/_cli.py b/ptodsl/ptoas/_cli.py new file mode 100644 index 0000000000..dbc2ce2468 --- /dev/null +++ b/ptodsl/ptoas/_cli.py @@ -0,0 +1,100 @@ +# Copyright (c) 2026 Huawei Technologies Co., Ltd. +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of +# CANN Open Software License Agreement Version 2.0 (the "License"). +# Please refer to the License for details. You may not use this file except in compliance with the License. +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE in the root of the software repository for the full text of the License. + +"""Standard Python console entry point for PTOAS.""" + +from __future__ import annotations + +import os +import shutil +import sys +from pathlib import Path +from typing import Sequence + + +def _resolve_wrapper_path(argv0: str | None = None) -> Path: + candidate = argv0 if argv0 is not None else sys.argv[0] + wrapper = Path(candidate) + if wrapper.exists(): + return wrapper.resolve() + + found = shutil.which(wrapper.name or "ptoas") + if found: + return Path(found).resolve() + + raise SystemExit(f"unable to locate the active ptoas entry point: {candidate}") + + +def _load_native_module(): + from ptoas import _native + + return _native + + +def _resolve_runtime_paths(native_module) -> tuple[Path, Path]: + module_file = getattr(native_module, "__file__", None) + if not module_file: + raise SystemExit("ptoas._native does not expose a module file") + + package_root = Path(module_file).resolve().parent + python_root = package_root.parent + runtime_root = package_root / "_runtime" + tileops_dir = runtime_root / "share" / "ptoas" / "TileOps" + if not tileops_dir.is_dir(): + raise SystemExit( + "unable to locate packaged PTOAS TileOps resources: expected " + f"{tileops_dir}" + ) + return python_root, tileops_dir.resolve() + + +def _has_cli_option(arguments: Sequence[str], option: str) -> bool: + option_with_value = f"{option}=" + return any( + argument == option or argument.startswith(option_with_value) + for argument in arguments + ) + + +def _prepend_path(name: str, value: Path) -> None: + current = os.environ.get(name, "") + parts = [part for part in current.split(os.pathsep) if part] + rendered = str(value) + if rendered in parts: + parts.remove(rendered) + parts.insert(0, rendered) + os.environ[name] = os.pathsep.join(parts) + + +def launch(user_args: Sequence[str], *, wrapper: Path | None = None) -> int: + native_module = _load_native_module() + python_root, tileops_dir = _resolve_runtime_paths(native_module) + wrapper = wrapper.resolve() if wrapper is not None else _resolve_wrapper_path() + + os.environ["PTOAS_BIN"] = str(wrapper) + os.environ["PTOAS_PYTHON_EXE"] = sys.executable + _prepend_path("PATH", wrapper.parent) + + argv = [str(wrapper)] + if not _has_cli_option(user_args, "--tilelang-path"): + argv.extend(["--tilelang-path", str(tileops_dir)]) + if not _has_cli_option(user_args, "--tilelang-pkg-path"): + argv.extend(["--tilelang-pkg-path", str(python_root)]) + if not _has_cli_option(user_args, "--ptodsl-pkg-path"): + argv.extend(["--ptodsl-pkg-path", str(python_root)]) + argv.extend(user_args) + + return int(native_module.main(argv)) + + +def main() -> int: + return launch(sys.argv[1:]) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/ptodsl/ptoas/_launcher.py b/ptodsl/ptoas/_launcher.py deleted file mode 100644 index a830bbf4ac..0000000000 --- a/ptodsl/ptoas/_launcher.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -"""Compatibility shim for legacy `ptoas._launcher` imports.""" - -from __future__ import annotations - -from ptoas_wheel_bootstrap import main as _wheel_bootstrap_main - - -def main() -> None: - _wheel_bootstrap_main() - - -if __name__ == "__main__": - main() diff --git a/ptodsl/ptoas/_runtime_entry.py b/ptodsl/ptoas/_runtime_entry.py deleted file mode 100644 index 2fa032727d..0000000000 --- a/ptodsl/ptoas/_runtime_entry.py +++ /dev/null @@ -1,144 +0,0 @@ -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -"""Shared runtime entry helpers for `ptoas` Python launchers. - -This module owns the common in-process ctypes launch contract. Thin entry -wrappers such as the wheel console entry and the build/install-tree wrapper -should resolve their own filesystem layouts, then delegate here for -environment setup and `ptoas_entrypoint` execution. -""" - -from __future__ import annotations - -import ctypes -import os -import sys -from dataclasses import dataclass -from pathlib import Path -from typing import MutableMapping, Sequence - - -@dataclass(frozen=True) -class PTOASRuntimeLayout: - wrapper: Path - runtime_root: Path - python_root: Path - shared_module: Path - tileops_dir: Path - isolated_env: bool - - -def _prepend_env_path(env: MutableMapping[str, str], name: str, value: Path) -> None: - if not value.exists(): - return - current = env.get(name, "") - rendered = str(value) - parts = [part for part in current.split(os.pathsep) if part] - if rendered in parts: - parts.remove(rendered) - parts.insert(0, rendered) - env[name] = os.pathsep.join(parts) - - -def _has_cli_option(argv: Sequence[str], option: str) -> bool: - option_with_value = f"{option}=" - for arg in argv: - if arg == option or arg.startswith(option_with_value): - return True - return False - - -def _iter_runtime_library_files(runtime_lib_dir: Path) -> list[Path]: - if not runtime_lib_dir.is_dir(): - return [] - - libraries: dict[Path, None] = {} - for pattern in ("*.so", "*.so.*", "*.dylib", "*.dylib.*"): - for candidate in sorted(runtime_lib_dir.glob(pattern)): - if candidate.is_file(): - libraries[candidate.resolve()] = None - return list(libraries) - - -def _preload_runtime_libraries(shared_module: Path, runtime_lib_dir: Path) -> None: - runtime_lib_dir = runtime_lib_dir.resolve() - if not runtime_lib_dir.is_dir(): - return - - shared_module = shared_module.resolve() - pending = [ - path for path in _iter_runtime_library_files(runtime_lib_dir) - if path != shared_module and path.name != shared_module.name - ] - if not pending: - return - - mode = getattr(ctypes, "RTLD_GLOBAL", 0) - last_error: OSError | None = None - while pending: - next_pending: list[Path] = [] - made_progress = False - for candidate in pending: - try: - ctypes.CDLL(str(candidate), mode=mode) - made_progress = True - except OSError as exc: - last_error = exc - next_pending.append(candidate) - if not next_pending: - return - if not made_progress: - if last_error is not None: - raise last_error - raise OSError(f"unable to preload runtime libraries from {runtime_lib_dir}") - pending = next_pending - - -def _load_shared_entrypoint(shared_module: Path, runtime_lib_dir: Path, *, preload_runtime_libraries: bool): - if preload_runtime_libraries: - _preload_runtime_libraries(shared_module, runtime_lib_dir) - library = ctypes.CDLL(str(shared_module), mode=getattr(ctypes, "RTLD_GLOBAL", 0)) - entrypoint = library.ptoas_entrypoint - entrypoint.argtypes = [ctypes.c_int, ctypes.POINTER(ctypes.c_char_p)] - entrypoint.restype = ctypes.c_int - return entrypoint - - -def launch(layout: PTOASRuntimeLayout, user_args: Sequence[str]) -> int: - env = os.environ - env["PTOAS_HOME"] = str(layout.runtime_root) - env["PTOAS_BIN"] = str(layout.wrapper) - env["PTOAS_TILEOPS_DIR"] = str(layout.tileops_dir) - env["PTOAS_PYTHON_EXE"] = sys.executable - - _prepend_env_path(env, "PATH", layout.wrapper.parent) - runtime_lib_dir = layout.runtime_root / "lib" - # Keep the wheel-owned packages and libraries first, while preserving - # host paths needed by injected runtimes such as CANN/MSProf. - _prepend_env_path(env, "PYTHONPATH", layout.python_root) - _prepend_env_path(env, "LD_LIBRARY_PATH", runtime_lib_dir) - _prepend_env_path(env, "DYLD_LIBRARY_PATH", runtime_lib_dir) - - argv = [str(layout.wrapper)] - if not _has_cli_option(user_args, "--tilelang-path"): - argv.extend(["--tilelang-path", str(layout.tileops_dir)]) - if not _has_cli_option(user_args, "--tilelang-pkg-path"): - argv.extend(["--tilelang-pkg-path", str(layout.python_root)]) - if not _has_cli_option(user_args, "--ptodsl-pkg-path"): - argv.extend(["--ptodsl-pkg-path", str(layout.python_root)]) - argv.extend(user_args) - - entrypoint = _load_shared_entrypoint( - layout.shared_module, - runtime_lib_dir, - preload_runtime_libraries=not layout.isolated_env, - ) - argv_bytes = [os.fsencode(arg) for arg in argv] - c_argv = (ctypes.c_char_p * len(argv_bytes))(*argv_bytes) - return int(entrypoint(len(argv_bytes), c_argv)) diff --git a/ptodsl/ptoas_wheel_bootstrap.py b/ptodsl/ptoas_wheel_bootstrap.py deleted file mode 100644 index d9da235a63..0000000000 --- a/ptodsl/ptoas_wheel_bootstrap.py +++ /dev/null @@ -1,190 +0,0 @@ -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -"""Shadow-safe wheel bootstrap for the `ptoas` console entry. - -The console script must not import `ptoas._launcher` directly because caller -environments may prepend unrelated `ptoas` packages via `PYTHONPATH`, editable -checkouts, or build-tree staging directories. This bootstrap has a unique -top-level module name, resolves the active wrapper's sibling site-packages -payload, then loads the wheel-owned `ptoas._runtime_entry` helper by file path. -""" - -from __future__ import annotations - -import importlib.util -import os -import shutil -import sys -import sysconfig -from pathlib import Path -from types import ModuleType -from typing import NoReturn - - -def _resolve_wrapper_path(argv0: str | None = None) -> Path: - candidate = argv0 if argv0 is not None else sys.argv[0] - wrapper = Path(candidate) - if wrapper.exists(): - return wrapper.resolve() - - found = shutil.which(wrapper.name or "ptoas") - if found: - return Path(found).resolve() - - raise SystemExit(f"unable to locate the installed ptoas wrapper: {candidate}") - - -def _unique_paths(paths: list[Path]) -> list[Path]: - unique: list[Path] = [] - seen: set[Path] = set() - for path in paths: - candidate = path.resolve() - if candidate in seen: - continue - seen.add(candidate) - unique.append(candidate) - return unique - - -def _prepend_env_path(env: dict[str, str], name: str, value: Path) -> None: - if not value.exists(): - return - rendered = str(value.resolve()) - parts = [part for part in env.get(name, "").split(os.pathsep) if part] - if rendered in parts: - parts.remove(rendered) - parts.insert(0, rendered) - env[name] = os.pathsep.join(parts) - - -def _candidate_wheel_python_roots(wrapper: Path, module_file: str | None = None) -> list[Path]: - candidates: list[Path] = [] - - if module_file: - candidates.append(Path(module_file).resolve().parent) - - for scheme_name in ("purelib", "platlib"): - scheme_path = sysconfig.get_path(scheme_name) - if scheme_path: - candidates.append(Path(scheme_path)) - - if len(wrapper.parents) >= 2: - prefix = wrapper.parents[1] - py_version = f"python{sys.version_info.major}.{sys.version_info.minor}" - candidates.extend( - [ - prefix / "lib" / py_version / "site-packages", - prefix / "lib" / py_version / "dist-packages", - prefix / "lib64" / py_version / "site-packages", - prefix / "Lib" / "site-packages", - ] - ) - - return _unique_paths(candidates) - - -def _resolve_wheel_python_root(wrapper: Path, module_file: str | None = None) -> tuple[Path, Path]: - searched: list[str] = [] - for python_root in _candidate_wheel_python_roots(wrapper, module_file): - package_root = python_root / "ptoas" - runtime_entry = package_root / "_runtime_entry.py" - runtime_root = package_root / "_runtime" - searched.append(str(package_root)) - if runtime_entry.is_file() and runtime_root.is_dir(): - return python_root, package_root - - rendered = ", ".join(searched) if searched else "" - raise SystemExit( - "unable to locate the wheel-installed ptoas package next to the active wrapper; " - "expected /ptoas/_runtime_entry.py and /ptoas/_runtime. " - f"Searched: {rendered}. This usually means an external PYTHONPATH is shadowing the installed wheel." - ) - - -def _resolve_wheel_layout(runtime_entry: ModuleType, package_root: Path, wrapper: Path): - package_root = package_root.resolve() - wrapper = wrapper.resolve() - runtime_root = package_root / "_runtime" - if not runtime_root.is_dir(): - raise SystemExit( - "wheel-installed ptoas is missing the packaged runtime root: " - "expected ptoas/_runtime" - ) - - shared_module = runtime_root / "lib" / "ptoas.so" - if not shared_module.is_file() or shared_module.stat().st_size <= 0: - raise SystemExit( - "wheel-installed ptoas is missing the packaged shared module: " - "expected ptoas/_runtime/lib/ptoas.so" - ) - - tileops_dir = runtime_root / "share" / "ptoas" / "TileOps" - if not tileops_dir.is_dir(): - raise SystemExit( - "wheel-installed ptoas is missing the packaged TileOps directory: " - "expected ptoas/_runtime/share/ptoas/TileOps" - ) - - return runtime_entry.PTOASRuntimeLayout( - wrapper=wrapper, - runtime_root=runtime_root.resolve(), - python_root=package_root.parent.resolve(), - shared_module=shared_module.resolve(), - tileops_dir=tileops_dir.resolve(), - isolated_env=True, - ) - - -def _load_runtime_entry(python_root: Path, package_root: Path) -> ModuleType: - python_root_text = str(python_root) - if python_root_text in sys.path: - sys.path.remove(python_root_text) - sys.path.insert(0, python_root_text) - - runtime_entry_path = package_root / "_runtime_entry.py" - module_name = "_ptoas_wheel_runtime_entry" - spec = importlib.util.spec_from_file_location(module_name, runtime_entry_path) - if spec is None or spec.loader is None: - raise SystemExit(f"unable to load ptoas runtime entry helper from {runtime_entry_path}") - module = importlib.util.module_from_spec(spec) - sys.modules[module_name] = module - spec.loader.exec_module(module) - return module - - -def _prepare_stage2_env(python_root: Path, package_root: Path) -> dict[str, str]: - runtime_lib_dir = package_root / "_runtime" / "lib" - env = os.environ.copy() - env["PTOAS_WHEEL_STAGE2"] = "1" - # Put wheel paths first without discarding host paths required by native - # integrations such as CANN/MSProf. - _prepend_env_path(env, "PYTHONPATH", python_root) - _prepend_env_path(env, "LD_LIBRARY_PATH", runtime_lib_dir) - _prepend_env_path(env, "DYLD_LIBRARY_PATH", runtime_lib_dir) - return env - - -def _maybe_reexec_isolated_process(wrapper: Path, python_root: Path, package_root: Path) -> None: - if os.environ.get("PTOAS_WHEEL_STAGE2") == "1": - return - env = _prepare_stage2_env(python_root, package_root) - os.execve(str(wrapper), [str(wrapper), *sys.argv[1:]], env) - - -def main() -> NoReturn: - wrapper = _resolve_wrapper_path() - python_root, package_root = _resolve_wheel_python_root(wrapper, __file__) - _maybe_reexec_isolated_process(wrapper, python_root, package_root) - runtime_entry = _load_runtime_entry(python_root, package_root) - layout = _resolve_wheel_layout(runtime_entry, package_root, wrapper) - raise SystemExit(runtime_entry.launch(layout, sys.argv[1:])) - - -if __name__ == "__main__": - main() diff --git a/ptodsl/tests/CMakeLists.txt b/ptodsl/tests/CMakeLists.txt index 3f4542216f..1722bf5d08 100644 --- a/ptodsl/tests/CMakeLists.txt +++ b/ptodsl/tests/CMakeLists.txt @@ -19,6 +19,7 @@ if(NOT DEFINED _pto_python_test_env) "PYTHONPATH=${_ptodsl_test_pythonpath}" "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:${_llvm_root}/lib:${CMAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}" "PATH=${CMAKE_BINARY_DIR}/tools/ptoas:${CMAKE_INSTALL_PREFIX}/bin:${_pto_python_bin_dir}:$ENV{PATH}" + "PTOAS_BIN=${CMAKE_BINARY_DIR}/tools/ptoas/ptoas" ) endif() diff --git a/ptodsl/tests/test_docs_as_test.py b/ptodsl/tests/test_docs_as_test.py index 6520d2f296..dccd1e5746 100644 --- a/ptodsl/tests/test_docs_as_test.py +++ b/ptodsl/tests/test_docs_as_test.py @@ -14,7 +14,6 @@ import json import linecache import re -import shutil import subprocess import sys import tempfile @@ -26,6 +25,7 @@ from ptodsl import pto, scalar from ptodsl._bootstrap import make_context from ptodsl._runtime.launch import LaunchHandle, _marshal_launch_args +from ptodsl._runtime.toolchain import resolve_ptoas_binary from mlir.ir import Module from support.docs_fragment_fixtures import FRAGMENT_FIXTURES, render_fragment_fixture @@ -131,22 +131,6 @@ def block_label(block: MarkdownCodeBlock, symbol: Optional[str] = None) -> str: return format_doc_context(block.path, block.start_line, symbol) -def resolve_ptoas_binary() -> Path: - candidates = [ - REPO_ROOT / "build" / "tools" / "ptoas" / "ptoas", - REPO_ROOT / "install" / "bin" / "ptoas", - ] - for candidate in candidates: - if candidate.is_file(): - return candidate - - from_path = shutil.which("ptoas") - if from_path: - return Path(from_path) - - raise FileNotFoundError("unable to locate a ptoas binary under build/, install/, or PATH") - - def expect_parse_roundtrip_and_verify(text: str, label: str) -> None: with make_context() as ctx: parsed = Module.parse(text, ctx) diff --git a/ptodsl/tests/test_pipe_surface_sample_compile.py b/ptodsl/tests/test_pipe_surface_sample_compile.py index 9ae6391a5a..88541a3635 100644 --- a/ptodsl/tests/test_pipe_surface_sample_compile.py +++ b/ptodsl/tests/test_pipe_surface_sample_compile.py @@ -11,11 +11,12 @@ from importlib.util import module_from_spec, spec_from_file_location from pathlib import Path -import shutil import subprocess import sys import tempfile +from ptodsl._runtime.toolchain import resolve_ptoas_binary as resolve_runtime_ptoas_binary + REPO_ROOT = Path(__file__).resolve().parents[2] SAMPLE = REPO_ROOT / "test" / "samples" / "TPushTPop" / "ptodsl" / "local_c2v" / "kernel.py" @@ -36,18 +37,10 @@ def load_sample_module(): def resolve_ptoas_binary() -> Path | None: - candidates = [ - REPO_ROOT / "build" / "tools" / "ptoas" / "ptoas", - REPO_ROOT / "install" / "bin" / "ptoas", - ] - for candidate in candidates: - if candidate.is_file(): - return candidate - - from_path = shutil.which("ptoas") - if from_path: - return Path(from_path) - return None + try: + return resolve_runtime_ptoas_binary() + except FileNotFoundError: + return None def run_ptoas_frontend(ptoas_bin: Path, mlir_text: str) -> str: diff --git a/ptodsl/tests/test_ptoas_cli.py b/ptodsl/tests/test_ptoas_cli.py new file mode 100644 index 0000000000..4e4f9dfa50 --- /dev/null +++ b/ptodsl/tests/test_ptoas_cli.py @@ -0,0 +1,119 @@ +#!/usr/bin/env python3 +# Copyright (c) 2026 Huawei Technologies Co., Ltd. +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of +# CANN Open Software License Agreement Version 2.0 (the "License"). +# Please refer to the License for details. You may not use this file except in compliance with the License. +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE in the root of the software repository for the full text of the License. + +import os +import tempfile +import unittest +from pathlib import Path +from types import SimpleNamespace +from unittest import mock + +from ptoas import _cli + + +class PTOASCLITests(unittest.TestCase): + def _make_native_module(self, package_root: Path): + return SimpleNamespace( + __file__=str(package_root / "_native.fake.so"), + main=mock.Mock(return_value=0), + ) + + def test_launch_uses_standard_native_module_and_packaged_resources(self): + with tempfile.TemporaryDirectory() as temp_dir: + package_root = Path(temp_dir) / "site-packages" / "ptoas" + tileops_dir = package_root / "_runtime" / "share" / "ptoas" / "TileOps" + wrapper = Path(temp_dir) / "bin" / "ptoas" + tileops_dir.mkdir(parents=True) + wrapper.parent.mkdir(parents=True) + wrapper.write_text("", encoding="utf-8") + native_module = self._make_native_module(package_root) + + with mock.patch.object( + _cli, "_load_native_module", return_value=native_module + ), mock.patch.dict( + _cli.os.environ, + {"PATH": "/usr/bin"}, + clear=True, + ): + exit_code = _cli.launch(["--version"], wrapper=wrapper) + environment = dict(_cli.os.environ) + + self.assertEqual(exit_code, 0) + native_module.main.assert_called_once_with( + [ + str(wrapper.resolve()), + "--tilelang-path", + str(tileops_dir.resolve()), + "--tilelang-pkg-path", + str(package_root.parent.resolve()), + "--ptodsl-pkg-path", + str(package_root.parent.resolve()), + "--version", + ] + ) + self.assertEqual(environment["PTOAS_BIN"], str(wrapper.resolve())) + self.assertEqual(environment["PTOAS_PYTHON_EXE"], _cli.sys.executable) + self.assertEqual( + environment["PATH"], + str(wrapper.parent.resolve()) + os.pathsep + "/usr/bin", + ) + + def test_explicit_resource_options_are_not_overridden(self): + with tempfile.TemporaryDirectory() as temp_dir: + package_root = Path(temp_dir) / "install" / "ptoas" + (package_root / "_runtime" / "share" / "ptoas" / "TileOps").mkdir( + parents=True + ) + wrapper = Path(temp_dir) / "install" / "bin" / "ptoas" + wrapper.parent.mkdir(parents=True) + wrapper.write_text("", encoding="utf-8") + native_module = self._make_native_module(package_root) + arguments = [ + "--tilelang-path=/custom/tileops", + "--tilelang-pkg-path", + "/custom/tilelang", + "--ptodsl-pkg-path=/custom/ptodsl", + "--version", + ] + + with mock.patch.object( + _cli, "_load_native_module", return_value=native_module + ): + _cli.launch(arguments, wrapper=wrapper) + + native_module.main.assert_called_once_with( + [str(wrapper.resolve()), *arguments] + ) + + def test_build_tree_uses_the_same_packaged_resource_layout(self): + with tempfile.TemporaryDirectory() as temp_dir: + build_root = Path(temp_dir) / "build" + package_root = build_root / "python" / "ptoas" + tileops_dir = package_root / "_runtime" / "share" / "ptoas" / "TileOps" + tileops_dir.mkdir(parents=True) + native_module = self._make_native_module(package_root) + + python_root, resolved_tileops = _cli._resolve_runtime_paths( + native_module + ) + + self.assertEqual(python_root, package_root.parent.resolve()) + self.assertEqual(resolved_tileops, tileops_dir.resolve()) + + def test_missing_tileops_resources_is_an_error(self): + with tempfile.TemporaryDirectory() as temp_dir: + package_root = Path(temp_dir) / "site-packages" / "ptoas" + native_module = self._make_native_module(package_root) + + with self.assertRaisesRegex(SystemExit, "TileOps"): + _cli._resolve_runtime_paths(native_module) + + +if __name__ == "__main__": + unittest.main() diff --git a/ptodsl/tests/test_ptoas_frontend_verify.py b/ptodsl/tests/test_ptoas_frontend_verify.py index 18661544bc..083ef4daa5 100644 --- a/ptodsl/tests/test_ptoas_frontend_verify.py +++ b/ptodsl/tests/test_ptoas_frontend_verify.py @@ -8,7 +8,6 @@ # See LICENSE in the root of the software repository for the full text of the License. from pathlib import Path -import shutil import subprocess import sys import tempfile @@ -19,6 +18,7 @@ from ptodsl import pto from ptodsl import scalar from ptodsl._bootstrap import make_context +from ptodsl._runtime.toolchain import resolve_ptoas_binary from mlir.ir import Module @@ -27,22 +27,6 @@ def expect(condition: bool, message: str) -> None: raise AssertionError(message) -def resolve_ptoas_binary() -> Path: - candidates = [ - REPO_ROOT / "build" / "tools" / "ptoas" / "ptoas", - REPO_ROOT / "install" / "bin" / "ptoas", - ] - for candidate in candidates: - if candidate.is_file(): - return candidate - - from_path = shutil.which("ptoas") - if from_path: - return Path(from_path) - - raise FileNotFoundError("unable to locate a ptoas binary under build/, install/, or PATH") - - def emit_example_mlir(example_path: Path) -> str: result = subprocess.run( [sys.executable, str(example_path), "--emit-mlir"], diff --git a/ptodsl/tests/test_ptoas_launcher_shim.py b/ptodsl/tests/test_ptoas_launcher_shim.py deleted file mode 100644 index b56d2fc8e7..0000000000 --- a/ptodsl/tests/test_ptoas_launcher_shim.py +++ /dev/null @@ -1,45 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import unittest -import importlib.util -import sys -from pathlib import Path -from unittest import mock - -REPO_ROOT = Path(__file__).resolve().parents[2] -LAUNCHER_SOURCE = REPO_ROOT / "ptodsl" / "ptoas" / "_launcher.py" - - -def _load_source_launcher(): - spec = importlib.util.spec_from_file_location("test_ptoas_launcher_shim_source", LAUNCHER_SOURCE) - assert spec is not None - assert spec.loader is not None - module = importlib.util.module_from_spec(spec) - saved_sys_path = list(sys.path) - try: - sys.path.insert(0, str(REPO_ROOT / "ptodsl")) - spec.loader.exec_module(module) - finally: - sys.path = saved_sys_path - return module - - -class LauncherShimTests(unittest.TestCase): - def test_main_forwards_directly_to_wheel_bootstrap(self): - launcher = _load_source_launcher() - - with mock.patch.object(launcher, "_wheel_bootstrap_main") as wheel_main: - launcher.main() - - wheel_main.assert_called_once_with() - - -if __name__ == "__main__": - unittest.main() diff --git a/ptodsl/tests/test_ptoas_runtime_entry.py b/ptodsl/tests/test_ptoas_runtime_entry.py deleted file mode 100644 index 11def2f490..0000000000 --- a/ptodsl/tests/test_ptoas_runtime_entry.py +++ /dev/null @@ -1,249 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import os -import tempfile -import unittest -from pathlib import Path -from unittest import mock - -from ptoas import _runtime_entry - - -class RuntimeEntryTests(unittest.TestCase): - def test_launch_injects_runtime_environment_and_calls_shared_entrypoint(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - wrapper = temp_root / "bin" / "ptoas" - runtime_root = temp_root / "runtime" - python_root = temp_root / "python" - tileops_dir = runtime_root / "share" / "ptoas" / "TileOps" - shared_module = runtime_root / "lib" / "ptoas.so" - wrapper.parent.mkdir(parents=True, exist_ok=True) - runtime_root.mkdir(parents=True, exist_ok=True) - python_root.mkdir(parents=True, exist_ok=True) - tileops_dir.mkdir(parents=True, exist_ok=True) - shared_module.parent.mkdir(parents=True, exist_ok=True) - shared_module.write_text("fake shared module", encoding="utf-8") - - layout = _runtime_entry.PTOASRuntimeLayout( - wrapper=wrapper, - runtime_root=runtime_root, - python_root=python_root, - shared_module=shared_module, - tileops_dir=tileops_dir, - isolated_env=False, - ) - entrypoint = mock.Mock(return_value=0) - - with mock.patch.dict( - _runtime_entry.os.environ, - { - "PYTHONPATH": "/tmp/external-python", - "LD_LIBRARY_PATH": "/tmp/external-lib", - "DYLD_LIBRARY_PATH": "/tmp/external-dylib", - }, - clear=True, - ), mock.patch.object( - _runtime_entry, - "_load_shared_entrypoint", - return_value=entrypoint, - ) as load_shared_entrypoint: - exit_code = _runtime_entry.launch(layout, ["--version"]) - env = dict(_runtime_entry.os.environ) - - self.assertEqual(exit_code, 0) - load_shared_entrypoint.assert_called_once_with( - layout.shared_module, - layout.runtime_root / "lib", - preload_runtime_libraries=True, - ) - argc, c_argv = entrypoint.call_args.args - self.assertEqual( - [c_argv[i].decode("utf-8") for i in range(argc)], - [ - str(layout.wrapper), - "--tilelang-path", - str(layout.tileops_dir), - "--tilelang-pkg-path", - str(layout.python_root), - "--ptodsl-pkg-path", - str(layout.python_root), - "--version", - ], - ) - self.assertEqual(env["PTOAS_HOME"], str(layout.runtime_root)) - self.assertEqual(env["PTOAS_BIN"], str(layout.wrapper)) - self.assertEqual(env["PTOAS_TILEOPS_DIR"], str(layout.tileops_dir)) - self.assertEqual(env["PYTHONPATH"], str(layout.python_root) + os.pathsep + "/tmp/external-python") - self.assertEqual(env["LD_LIBRARY_PATH"], str(layout.runtime_root / "lib") + os.pathsep + "/tmp/external-lib") - self.assertEqual(env["DYLD_LIBRARY_PATH"], str(layout.runtime_root / "lib") + os.pathsep + "/tmp/external-dylib") - - def test_launch_prioritizes_runtime_environment_for_wheel_layout(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - wrapper = temp_root / "bin" / "ptoas" - runtime_root = temp_root / "runtime" - python_root = temp_root / "python" - tileops_dir = runtime_root / "share" / "ptoas" / "TileOps" - shared_module = runtime_root / "lib" / "ptoas.so" - wrapper.parent.mkdir(parents=True, exist_ok=True) - runtime_root.mkdir(parents=True, exist_ok=True) - python_root.mkdir(parents=True, exist_ok=True) - tileops_dir.mkdir(parents=True, exist_ok=True) - shared_module.parent.mkdir(parents=True, exist_ok=True) - shared_module.write_text("fake shared module", encoding="utf-8") - - layout = _runtime_entry.PTOASRuntimeLayout( - wrapper=wrapper, - runtime_root=runtime_root, - python_root=python_root, - shared_module=shared_module, - tileops_dir=tileops_dir, - isolated_env=True, - ) - entrypoint = mock.Mock(return_value=0) - - with mock.patch.dict( - _runtime_entry.os.environ, - { - "PYTHONPATH": "/tmp/external-python", - "LD_LIBRARY_PATH": "/tmp/external-lib", - "DYLD_LIBRARY_PATH": "/tmp/external-dylib", - }, - clear=True, - ), mock.patch.object( - _runtime_entry, - "_load_shared_entrypoint", - return_value=entrypoint, - ) as load_shared_entrypoint: - exit_code = _runtime_entry.launch(layout, ["--help"]) - env = dict(_runtime_entry.os.environ) - - self.assertEqual(exit_code, 0) - load_shared_entrypoint.assert_called_once_with( - layout.shared_module, - layout.runtime_root / "lib", - preload_runtime_libraries=False, - ) - self.assertEqual( - env["PYTHONPATH"], - str(layout.python_root) + os.pathsep + "/tmp/external-python", - ) - self.assertEqual( - env["LD_LIBRARY_PATH"], - str(layout.runtime_root / "lib") + os.pathsep + "/tmp/external-lib", - ) - self.assertEqual( - env["DYLD_LIBRARY_PATH"], - str(layout.runtime_root / "lib") + os.pathsep + "/tmp/external-dylib", - ) - - def test_load_shared_entrypoint_configures_in_process_ctypes_call(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - runtime_lib_dir = temp_root / "runtime" / "lib" - runtime_lib_dir.mkdir(parents=True, exist_ok=True) - dep = runtime_lib_dir / "libMLIRMlirOptMain.so.21.1" - dep.write_text("fake dep", encoding="utf-8") - shared_module = temp_root / "runtime" / "pto" / "ptoas.so" - shared_module.parent.mkdir(parents=True, exist_ok=True) - shared_module.write_text("fake shared module", encoding="utf-8") - - dep_library = mock.Mock() - shared_library = mock.Mock() - with mock.patch.object( - _runtime_entry.ctypes, "CDLL", side_effect=[dep_library, shared_library] - ) as load_library: - entrypoint = _runtime_entry._load_shared_entrypoint( - shared_module, - runtime_lib_dir, - preload_runtime_libraries=True, - ) - - self.assertEqual( - [call.args[0] for call in load_library.call_args_list], - [str(dep.resolve()), str(shared_module.resolve())], - ) - self.assertTrue( - all( - call.kwargs["mode"] == getattr(_runtime_entry.ctypes, "RTLD_GLOBAL", 0) - for call in load_library.call_args_list - ) - ) - self.assertIs(entrypoint, shared_library.ptoas_entrypoint) - self.assertEqual( - entrypoint.argtypes, - [_runtime_entry.ctypes.c_int, _runtime_entry.ctypes.POINTER(_runtime_entry.ctypes.c_char_p)], - ) - self.assertIs(entrypoint.restype, _runtime_entry.ctypes.c_int) - - def test_load_shared_entrypoint_can_skip_preloading_runtime_libraries(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - runtime_lib_dir = temp_root / "runtime" / "lib" - runtime_lib_dir.mkdir(parents=True, exist_ok=True) - dep = runtime_lib_dir / "libLLVMOption.so.21.1" - dep.write_text("fake dep", encoding="utf-8") - shared_module = runtime_lib_dir / "ptoas.so" - shared_module.write_text("fake shared module", encoding="utf-8") - - shared_library = mock.Mock() - with mock.patch.object(_runtime_entry.ctypes, "CDLL", return_value=shared_library) as load_library: - entrypoint = _runtime_entry._load_shared_entrypoint( - shared_module, - runtime_lib_dir, - preload_runtime_libraries=False, - ) - - load_library.assert_called_once_with( - str(shared_module), - mode=getattr(_runtime_entry.ctypes, "RTLD_GLOBAL", 0), - ) - self.assertIs(entrypoint, shared_library.ptoas_entrypoint) - - def test_preload_runtime_libraries_retries_until_dependencies_resolve(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - runtime_lib_dir = temp_root / "runtime" / "lib" - runtime_lib_dir.mkdir(parents=True, exist_ok=True) - dep_a = runtime_lib_dir / "libA.so.1" - dep_b = runtime_lib_dir / "libB.so.1" - dep_a.write_text("fake dep a", encoding="utf-8") - dep_b.write_text("fake dep b", encoding="utf-8") - shared_module = temp_root / "runtime" / "pto" / "ptoas.so" - shared_module.parent.mkdir(parents=True, exist_ok=True) - shared_module.write_text("fake shared module", encoding="utf-8") - - loaded: list[str] = [] - dep_b_attempts = 0 - - def fake_cdll(path: str, *, mode: int): - nonlocal dep_b_attempts - loaded.append(path) - if Path(path).resolve() == dep_b.resolve() and dep_b_attempts == 0: - dep_b_attempts += 1 - raise OSError("missing libA dependency") - return mock.Mock() - - with mock.patch.object(_runtime_entry.ctypes, "CDLL", side_effect=fake_cdll): - _runtime_entry._preload_runtime_libraries(shared_module, runtime_lib_dir) - - self.assertEqual( - loaded, - [ - str(dep_a.resolve()), - str(dep_b.resolve()), - str(dep_b.resolve()), - ], - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/ptodsl/tests/test_ptoas_tree_wrapper.py b/ptodsl/tests/test_ptoas_tree_wrapper.py index acf983e353..59f5545873 100644 --- a/ptodsl/tests/test_ptoas_tree_wrapper.py +++ b/ptodsl/tests/test_ptoas_tree_wrapper.py @@ -17,411 +17,90 @@ REPO_ROOT = Path(__file__).resolve().parents[2] WRAPPER_SOURCE = REPO_ROOT / "tools" / "ptoas" / "ptoas_wrapper.py" - -class TreeWrapperTests(unittest.TestCase): - def test_build_tree_wrapper_bootstraps_runtime_entry_and_delegates_shared_launcher(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - build_root = temp_root / "build" - build_python_root = build_root / "python" - package_root = build_python_root / "ptoas" - package_root.mkdir(parents=True, exist_ok=True) - (package_root / "__init__.py").write_text("", encoding="utf-8") - (package_root / "_runtime_entry.py").write_text( - """ -from dataclasses import dataclass - +FAKE_CLI = """ calls = [] - -@dataclass(frozen=True) -class PTOASRuntimeLayout: - wrapper: object - runtime_root: object - python_root: object - shared_module: object - tileops_dir: object - isolated_env: bool - - -def launch(layout, user_args): - calls.append(("launch", layout, list(user_args))) +def launch(user_args, *, wrapper=None): + calls.append((list(user_args), wrapper)) return 17 -""".strip() - + "\n", - encoding="utf-8", - ) - - runtime_root = build_root / "runtime-staging" - (runtime_root / "lib").mkdir(parents=True, exist_ok=True) - (runtime_root / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (runtime_root / "lib" / "ptoas.so").write_text("fake shared module", encoding="utf-8") - install_root = temp_root / "install" - (install_root / "lib").mkdir(parents=True, exist_ok=True) - (install_root / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (install_root / "ptoas").mkdir(parents=True, exist_ok=True) - (install_root / "lib" / "ptoas.so").write_text("install shared module", encoding="utf-8") - (install_root / "ptoas" / "_runtime_entry.py").write_text("", encoding="utf-8") - wrapper_path = temp_root / "build" / "tools" / "ptoas" / "ptoas" - wrapper_path.parent.mkdir(parents=True, exist_ok=True) - wrapper_path.write_text("", encoding="utf-8") - - spec = importlib.util.spec_from_file_location("test_ptoas_wrapper", WRAPPER_SOURCE) - self.assertIsNotNone(spec) - self.assertIsNotNone(spec.loader) - wrapper_module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(wrapper_module) - - wrapper_module.__file__ = str(wrapper_path) - - saved_sys_path = list(sys.path) - saved_argv = list(sys.argv) - saved_ptoas = sys.modules.pop("ptoas", None) - saved_runtime_entry = sys.modules.pop("ptoas._runtime_entry", None) - try: - sys.path = [entry for entry in sys.path if entry != str(build_python_root)] - sys.argv = [str(wrapper_path), "--version"] - - with self.assertRaises(SystemExit) as exc: - wrapper_module.main() - - self.assertEqual(exc.exception.code, 17) - self.assertEqual(sys.path[0], str(build_python_root)) - - runtime_entry = sys.modules["ptoas._runtime_entry"] - self.assertEqual( - runtime_entry.calls, - [ - ( - "launch", - runtime_entry.PTOASRuntimeLayout( - wrapper=wrapper_path.resolve(), - runtime_root=runtime_root.resolve(), - python_root=build_python_root.resolve(), - shared_module=(runtime_root / "lib" / "ptoas.so").resolve(), - tileops_dir=(runtime_root / "share" / "ptoas" / "TileOps").resolve(), - isolated_env=False, - ), - ["--version"], - ), - ], - ) - finally: - sys.path = saved_sys_path - sys.argv = saved_argv - sys.modules.pop("ptoas", None) - sys.modules.pop("ptoas._runtime_entry", None) - if saved_ptoas is not None: - sys.modules["ptoas"] = saved_ptoas - if saved_runtime_entry is not None: - sys.modules["ptoas._runtime_entry"] = saved_runtime_entry - - def test_install_tree_wrapper_bootstraps_install_prefix_and_delegates_shared_launcher(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - build_root = temp_root / "build" - build_python_root = build_root / "python" - (build_python_root / "ptoas").mkdir(parents=True, exist_ok=True) - (build_python_root / "ptoas" / "_runtime_entry.py").write_text("", encoding="utf-8") - (build_root / "runtime-staging" / "lib").mkdir(parents=True, exist_ok=True) - (build_root / "runtime-staging" / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (build_root / "runtime-staging" / "lib" / "ptoas.so").write_text("build shared module", encoding="utf-8") - - install_root = temp_root / "install" - install_python_root = install_root - package_root = install_python_root / "ptoas" - package_root.mkdir(parents=True, exist_ok=True) - (package_root / "__init__.py").write_text("", encoding="utf-8") - (package_root / "_runtime_entry.py").write_text( - """ -from dataclasses import dataclass - -calls = [] - - -@dataclass(frozen=True) -class PTOASRuntimeLayout: - wrapper: object - runtime_root: object - python_root: object - shared_module: object - tileops_dir: object - isolated_env: bool - - -def launch(layout, user_args): - calls.append(("launch", layout, list(user_args))) - return 23 -""".strip() - + "\n", - encoding="utf-8", - ) - (install_root / "lib").mkdir(parents=True, exist_ok=True) - (install_root / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (install_root / "lib" / "ptoas.so").write_text("install shared module", encoding="utf-8") - wrapper_path = install_root / "bin" / "ptoas" - wrapper_path.parent.mkdir(parents=True, exist_ok=True) - wrapper_path.write_text("", encoding="utf-8") - - spec = importlib.util.spec_from_file_location("test_ptoas_wrapper_install", WRAPPER_SOURCE) - self.assertIsNotNone(spec) - self.assertIsNotNone(spec.loader) - wrapper_module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(wrapper_module) - - wrapper_module.__file__ = str(wrapper_path) - - saved_sys_path = list(sys.path) - saved_argv = list(sys.argv) - saved_ptoas = sys.modules.pop("ptoas", None) - saved_runtime_entry = sys.modules.pop("ptoas._runtime_entry", None) - try: - sys.path = [entry for entry in sys.path if entry != str(install_python_root)] - sys.argv = [str(wrapper_path), "--help"] - - with self.assertRaises(SystemExit) as exc: - wrapper_module.main() +""".lstrip() - self.assertEqual(exc.exception.code, 23) - self.assertEqual(sys.path[0], str(install_python_root)) - runtime_entry = sys.modules["ptoas._runtime_entry"] - self.assertEqual( - runtime_entry.calls, - [ - ( - "launch", - runtime_entry.PTOASRuntimeLayout( - wrapper=wrapper_path.resolve(), - runtime_root=install_root.resolve(), - python_root=install_python_root.resolve(), - shared_module=(install_root / "lib" / "ptoas.so").resolve(), - tileops_dir=(install_root / "share" / "ptoas" / "TileOps").resolve(), - isolated_env=False, - ), - ["--help"], - ), - ], - ) - finally: - sys.path = saved_sys_path - sys.argv = saved_argv - sys.modules.pop("ptoas", None) - sys.modules.pop("ptoas._runtime_entry", None) - if saved_ptoas is not None: - sys.modules["ptoas"] = saved_ptoas - if saved_runtime_entry is not None: - sys.modules["ptoas._runtime_entry"] = saved_runtime_entry - - def test_build_tree_wrapper_does_not_fall_back_to_install_prefix_python_root(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - build_root = temp_root / "build" - (build_root / "runtime-staging" / "lib").mkdir(parents=True, exist_ok=True) - (build_root / "runtime-staging" / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (build_root / "runtime-staging" / "lib" / "ptoas.so").write_text("fake shared module", encoding="utf-8") - - install_root = temp_root / "install" - (install_root / "lib").mkdir(parents=True, exist_ok=True) - (install_root / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (install_root / "ptoas").mkdir(parents=True, exist_ok=True) - (install_root / "lib" / "ptoas.so").write_text("install shared module", encoding="utf-8") - (install_root / "ptoas" / "_runtime_entry.py").write_text("", encoding="utf-8") - wrapper_path = temp_root / "build" / "tools" / "ptoas" / "ptoas" - wrapper_path.parent.mkdir(parents=True, exist_ok=True) - wrapper_path.write_text("", encoding="utf-8") - - spec = importlib.util.spec_from_file_location("test_ptoas_wrapper_build_fallback", WRAPPER_SOURCE) - self.assertIsNotNone(spec) - self.assertIsNotNone(spec.loader) - wrapper_module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(wrapper_module) - wrapper_module.__file__ = str(wrapper_path) - - saved_sys_path = list(sys.path) - saved_argv = list(sys.argv) - try: - sys.path = [entry for entry in sys.path if entry != str(install_root)] - sys.argv = [str(wrapper_path), "--version"] - - with self.assertRaises(SystemExit) as exc: - wrapper_module.main() - - self.assertIn("build-tree ptoas Python package root", str(exc.exception)) - finally: - sys.path = saved_sys_path - sys.argv = saved_argv - - def test_build_tree_wrapper_fails_when_build_runtime_layout_is_missing(self): +class TreeWrapperTests(unittest.TestCase): + def _load_wrapper(self, wrapper_path: Path, module_name: str): + spec = importlib.util.spec_from_file_location(module_name, WRAPPER_SOURCE) + self.assertIsNotNone(spec) + self.assertIsNotNone(spec.loader) + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + module.__file__ = str(wrapper_path) + return module + + def _run_wrapper(self, wrapper_module, python_root: Path, wrapper: Path): + saved_sys_path = list(sys.path) + saved_argv = list(sys.argv) + saved_modules = { + name: sys.modules.pop(name, None) + for name in ("ptoas", "ptoas._cli") + } + try: + sys.path = [entry for entry in sys.path if entry != str(python_root)] + sys.argv = [str(wrapper), "--version"] + with self.assertRaises(SystemExit) as exc: + wrapper_module.main() + self.assertEqual(exc.exception.code, 17) + return sys.modules["ptoas._cli"] + finally: + sys.path = saved_sys_path + sys.argv = saved_argv + for name in ("ptoas._cli", "ptoas"): + sys.modules.pop(name, None) + if saved_modules[name] is not None: + sys.modules[name] = saved_modules[name] + + def _make_package(self, python_root: Path) -> None: + package_root = python_root / "ptoas" + package_root.mkdir(parents=True) + (package_root / "__init__.py").write_text("", encoding="utf-8") + (package_root / "_cli.py").write_text(FAKE_CLI, encoding="utf-8") + + def test_build_tree_wrapper_delegates_to_cli_module(self): with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - build_root = temp_root / "build" - build_python_root = build_root / "python" - package_root = build_python_root / "ptoas" - package_root.mkdir(parents=True, exist_ok=True) - (package_root / "__init__.py").write_text("", encoding="utf-8") - (package_root / "_runtime_entry.py").write_text( - """ -from dataclasses import dataclass - - -@dataclass(frozen=True) -class PTOASRuntimeLayout: - wrapper: object - runtime_root: object - python_root: object - shared_module: object - tileops_dir: object - isolated_env: bool - - -def launch(layout, user_args): - raise AssertionError("missing runtime layout must fail before launch") -""".strip() - + "\n", - encoding="utf-8", - ) - install_root = temp_root / "install" - (install_root / "lib").mkdir(parents=True, exist_ok=True) - (install_root / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (install_root / "lib" / "ptoas.so").write_text("install shared module", encoding="utf-8") - wrapper_path = build_root / "tools" / "ptoas" / "ptoas" - wrapper_path.parent.mkdir(parents=True, exist_ok=True) - wrapper_path.write_text("", encoding="utf-8") + build_root = Path(temp_dir) / "build" + python_root = build_root / "python" + wrapper = build_root / "tools" / "ptoas" / "ptoas" + self._make_package(python_root) + wrapper.parent.mkdir(parents=True) + wrapper.write_text("", encoding="utf-8") - spec = importlib.util.spec_from_file_location("test_ptoas_wrapper_build_missing_runtime", WRAPPER_SOURCE) - self.assertIsNotNone(spec) - self.assertIsNotNone(spec.loader) - wrapper_module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(wrapper_module) - wrapper_module.__file__ = str(wrapper_path) + module = self._load_wrapper(wrapper, "test_ptoas_build_wrapper") + cli = self._run_wrapper(module, python_root, wrapper) - saved_sys_path = list(sys.path) - saved_argv = list(sys.argv) - saved_ptoas = sys.modules.pop("ptoas", None) - saved_runtime_entry = sys.modules.pop("ptoas._runtime_entry", None) - try: - sys.path = [entry for entry in sys.path if entry != str(build_python_root)] - sys.argv = [str(wrapper_path), "--version"] + self.assertEqual(cli.calls, [(["--version"], wrapper.resolve())]) - with self.assertRaises(SystemExit) as exc: - wrapper_module.main() - - self.assertIn("ptoas runtime tree", str(exc.exception)) - self.assertIn(str(build_root / "runtime-staging"), str(exc.exception)) - finally: - sys.path = saved_sys_path - sys.argv = saved_argv - sys.modules.pop("ptoas", None) - sys.modules.pop("ptoas._runtime_entry", None) - if saved_ptoas is not None: - sys.modules["ptoas"] = saved_ptoas - if saved_runtime_entry is not None: - sys.modules["ptoas._runtime_entry"] = saved_runtime_entry - - def test_install_tree_wrapper_does_not_fall_back_to_build_tree_python_root(self): + def test_install_tree_wrapper_delegates_to_cli_module(self): with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - build_root = temp_root / "build" - build_python_root = build_root / "python" - (build_python_root / "ptoas").mkdir(parents=True, exist_ok=True) - (build_python_root / "ptoas" / "_runtime_entry.py").write_text("", encoding="utf-8") - (build_root / "runtime-staging" / "lib").mkdir(parents=True, exist_ok=True) - (build_root / "runtime-staging" / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (build_root / "runtime-staging" / "lib" / "ptoas.so").write_text("build shared module", encoding="utf-8") - - install_root = temp_root / "install" - wrapper_path = install_root / "bin" / "ptoas" - wrapper_path.parent.mkdir(parents=True, exist_ok=True) - wrapper_path.write_text("", encoding="utf-8") - - spec = importlib.util.spec_from_file_location("test_ptoas_wrapper_install_fallback", WRAPPER_SOURCE) - self.assertIsNotNone(spec) - self.assertIsNotNone(spec.loader) - wrapper_module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(wrapper_module) - wrapper_module.__file__ = str(wrapper_path) + install_root = Path(temp_dir) / "install" + wrapper = install_root / "bin" / "ptoas" + self._make_package(install_root) + wrapper.parent.mkdir(parents=True) + wrapper.write_text("", encoding="utf-8") - saved_sys_path = list(sys.path) - saved_argv = list(sys.argv) - try: - sys.path = [entry for entry in sys.path if entry != str(build_python_root)] - sys.argv = [str(wrapper_path), "--help"] + module = self._load_wrapper(wrapper, "test_ptoas_install_wrapper") + cli = self._run_wrapper(module, install_root, wrapper) - with self.assertRaises(SystemExit) as exc: - wrapper_module.main() + self.assertEqual(cli.calls, [(["--version"], wrapper.resolve())]) - self.assertIn("install-tree ptoas Python package root", str(exc.exception)) - finally: - sys.path = saved_sys_path - sys.argv = saved_argv - - def test_install_tree_wrapper_fails_when_install_runtime_layout_is_missing(self): + def test_wrapper_requires_cli_module(self): with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - build_root = temp_root / "build" - (build_root / "runtime-staging" / "lib").mkdir(parents=True, exist_ok=True) - (build_root / "runtime-staging" / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (build_root / "runtime-staging" / "lib" / "ptoas.so").write_text("build shared module", encoding="utf-8") - - install_root = temp_root / "install" - package_root = install_root / "ptoas" - package_root.mkdir(parents=True, exist_ok=True) - (package_root / "__init__.py").write_text("", encoding="utf-8") - (package_root / "_runtime_entry.py").write_text( - """ -from dataclasses import dataclass - - -@dataclass(frozen=True) -class PTOASRuntimeLayout: - wrapper: object - runtime_root: object - python_root: object - shared_module: object - tileops_dir: object - isolated_env: bool - - -def launch(layout, user_args): - raise AssertionError("missing runtime layout must fail before launch") -""".strip() - + "\n", - encoding="utf-8", + python_root = Path(temp_dir) / "python" + python_root.mkdir() + module = self._load_wrapper( + Path(temp_dir) / "build" / "tools" / "ptoas" / "ptoas", + "test_ptoas_missing_cli", ) - wrapper_path = install_root / "bin" / "ptoas" - wrapper_path.parent.mkdir(parents=True, exist_ok=True) - wrapper_path.write_text("", encoding="utf-8") - - spec = importlib.util.spec_from_file_location("test_ptoas_wrapper_install_missing_runtime", WRAPPER_SOURCE) - self.assertIsNotNone(spec) - self.assertIsNotNone(spec.loader) - wrapper_module = importlib.util.module_from_spec(spec) - spec.loader.exec_module(wrapper_module) - wrapper_module.__file__ = str(wrapper_path) - - saved_sys_path = list(sys.path) - saved_argv = list(sys.argv) - saved_ptoas = sys.modules.pop("ptoas", None) - saved_runtime_entry = sys.modules.pop("ptoas._runtime_entry", None) - try: - sys.path = [entry for entry in sys.path if entry != str(install_root)] - sys.argv = [str(wrapper_path), "--help"] - - with self.assertRaises(SystemExit) as exc: - wrapper_module.main() - - self.assertIn("ptoas runtime tree", str(exc.exception)) - self.assertIn(str(install_root), str(exc.exception)) - finally: - sys.path = saved_sys_path - sys.argv = saved_argv - sys.modules.pop("ptoas", None) - sys.modules.pop("ptoas._runtime_entry", None) - if saved_ptoas is not None: - sys.modules["ptoas"] = saved_ptoas - if saved_runtime_entry is not None: - sys.modules["ptoas._runtime_entry"] = saved_runtime_entry + with self.assertRaisesRegex(SystemExit, "ptoas/_cli.py"): + module._require_python_root(python_root, context="test") if __name__ == "__main__": diff --git a/ptodsl/tests/test_ptoas_wheel_bootstrap.py b/ptodsl/tests/test_ptoas_wheel_bootstrap.py deleted file mode 100644 index cd04d23bff..0000000000 --- a/ptodsl/tests/test_ptoas_wheel_bootstrap.py +++ /dev/null @@ -1,319 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import json -import os -import subprocess -import sys -import tempfile -import textwrap -import unittest -from dataclasses import dataclass -from pathlib import Path -from types import SimpleNamespace -from unittest import mock - -import ptoas_wheel_bootstrap as wheel_bootstrap - - -class WheelBootstrapTests(unittest.TestCase): - def _make_runtime_tree(self, temp_root: Path) -> tuple[Path, Path]: - python_root = temp_root / "site-packages" - package_root = python_root / "ptoas" - runtime_root = package_root / "_runtime" - package_root.mkdir(parents=True, exist_ok=True) - (package_root / "_runtime_entry.py").write_text("", encoding="utf-8") - (runtime_root / "lib").mkdir(parents=True, exist_ok=True) - (runtime_root / "share" / "ptoas" / "TileOps").mkdir(parents=True, exist_ok=True) - (runtime_root / "lib" / "ptoas.so").write_text("fake shared module", encoding="utf-8") - bootstrap = python_root / "ptoas_wheel_bootstrap.py" - bootstrap.write_text("", encoding="utf-8") - wrapper = temp_root / "bin" / "ptoas" - wrapper.parent.mkdir(parents=True, exist_ok=True) - wrapper.write_text("", encoding="utf-8") - return bootstrap, wrapper - - def test_stage1_reexecs_with_prioritized_python_and_library_paths(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - bootstrap, wrapper = self._make_runtime_tree(temp_root) - - with mock.patch.dict( - wheel_bootstrap.os.environ, - { - "PYTHONPATH": "/tmp/external-python", - "LD_LIBRARY_PATH": "/tmp/external-lib", - "DYLD_LIBRARY_PATH": "/tmp/external-dylib", - }, - clear=True, - ), mock.patch.object( - wheel_bootstrap, - "__file__", - str(bootstrap), - ), mock.patch.object( - wheel_bootstrap.sys, - "argv", - [str(wrapper), "--version"], - ), mock.patch.object( - wheel_bootstrap.os, - "execve", - side_effect=SystemExit(19), - ) as execve: - with self.assertRaises(SystemExit) as exc: - wheel_bootstrap.main() - - self.assertEqual(exc.exception.code, 19) - execve.assert_called_once() - invoked_path, invoked_argv, invoked_env = execve.call_args.args - self.assertEqual(invoked_path, str(wrapper.resolve())) - self.assertEqual(invoked_argv, [str(wrapper.resolve()), "--version"]) - self.assertEqual(invoked_env["PTOAS_WHEEL_STAGE2"], "1") - self.assertEqual( - invoked_env["PYTHONPATH"], - str(bootstrap.parent.resolve()) + os.pathsep + "/tmp/external-python", - ) - self.assertEqual( - invoked_env["LD_LIBRARY_PATH"], - str((bootstrap.parent / "ptoas" / "_runtime" / "lib").resolve()) - + os.pathsep - + "/tmp/external-lib", - ) - self.assertEqual( - invoked_env["DYLD_LIBRARY_PATH"], - str((bootstrap.parent / "ptoas" / "_runtime" / "lib").resolve()) - + os.pathsep - + "/tmp/external-dylib", - ) - - def test_stage2_loads_runtime_entry_without_reexec(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - bootstrap, wrapper = self._make_runtime_tree(temp_root) - @dataclass(frozen=True) - class FakeLayout: - wrapper: Path - runtime_root: Path - python_root: Path - shared_module: Path - tileops_dir: Path - isolated_env: bool - - runtime_entry = SimpleNamespace( - PTOASRuntimeLayout=FakeLayout, - launch=mock.Mock(return_value=7), - ) - - with mock.patch.dict( - wheel_bootstrap.os.environ, - {"PTOAS_WHEEL_STAGE2": "1"}, - clear=True, - ), mock.patch.object( - wheel_bootstrap, - "__file__", - str(bootstrap), - ), mock.patch.object( - wheel_bootstrap.sys, - "argv", - [str(wrapper), "--help"], - ), mock.patch.object( - wheel_bootstrap, - "_load_runtime_entry", - return_value=runtime_entry, - ) as load_runtime_entry, mock.patch.object( - wheel_bootstrap.os, - "execve", - ) as execve: - with self.assertRaises(SystemExit) as exc: - wheel_bootstrap.main() - - self.assertEqual(exc.exception.code, 7) - execve.assert_not_called() - load_runtime_entry.assert_called_once_with(bootstrap.parent.resolve(), (bootstrap.parent / "ptoas").resolve()) - runtime_entry.launch.assert_called_once_with( - FakeLayout( - wrapper=wrapper.resolve(), - runtime_root=(bootstrap.parent / "ptoas" / "_runtime").resolve(), - python_root=bootstrap.parent.resolve(), - shared_module=(bootstrap.parent / "ptoas" / "_runtime" / "lib" / "ptoas.so").resolve(), - tileops_dir=(bootstrap.parent / "ptoas" / "_runtime" / "share" / "ptoas" / "TileOps").resolve(), - isolated_env=True, - ), - ["--help"], - ) - - def test_resolve_wheel_python_root_prefers_installed_package_when_shadowed(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - bootstrap, wrapper = self._make_runtime_tree(temp_root) - package_root = bootstrap.parent / "ptoas" - shadow_launcher = temp_root / "shadow" / "ptoas" / "_launcher.py" - shadow_launcher.parent.mkdir(parents=True, exist_ok=True) - shadow_launcher.write_text("", encoding="utf-8") - - def fake_get_path(name: str) -> str: - if name in ("purelib", "platlib"): - return str(package_root.parent) - return "" - - with mock.patch.object( - wheel_bootstrap.sysconfig, - "get_path", - side_effect=fake_get_path, - ): - python_root, resolved_package_root = wheel_bootstrap._resolve_wheel_python_root( - wrapper, - str(shadow_launcher), - ) - - self.assertEqual(python_root, package_root.parent.resolve()) - self.assertEqual(resolved_package_root, package_root.resolve()) - - def test_console_entry_reexec_prioritizes_wheel_paths(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - wheel_root = temp_root / "wheel-site" - package_root = wheel_root / "ptoas" - runtime_root = package_root / "_runtime" - runtime_lib_dir = runtime_root / "lib" - tileops_dir = runtime_root / "share" / "ptoas" / "TileOps" - result_path = temp_root / "launch-result.json" - wrapper = temp_root / "venv" / "bin" / "ptoas" - - package_root.mkdir(parents=True, exist_ok=True) - runtime_lib_dir.mkdir(parents=True, exist_ok=True) - tileops_dir.mkdir(parents=True, exist_ok=True) - (runtime_lib_dir / "ptoas.so").write_text("fake shared module", encoding="utf-8") - (wheel_root / "ptoas_wheel_bootstrap.py").write_text( - Path(wheel_bootstrap.__file__).read_text(encoding="utf-8"), - encoding="utf-8", - ) - (package_root / "_runtime_entry.py").write_text( - textwrap.dedent( - """ - import json - import os - from dataclasses import dataclass - from pathlib import Path - - @dataclass(frozen=True) - class PTOASRuntimeLayout: - wrapper: Path - runtime_root: Path - python_root: Path - shared_module: Path - tileops_dir: Path - isolated_env: bool - - def launch(layout, user_args): - result = { - "user_args": list(user_args), - "env": { - "PTOAS_WHEEL_STAGE2": os.environ.get("PTOAS_WHEEL_STAGE2"), - "PYTHONPATH": os.environ.get("PYTHONPATH"), - "LD_LIBRARY_PATH": os.environ.get("LD_LIBRARY_PATH"), - "DYLD_LIBRARY_PATH": os.environ.get("DYLD_LIBRARY_PATH"), - }, - "layout": { - "wrapper": str(layout.wrapper), - "runtime_root": str(layout.runtime_root), - "python_root": str(layout.python_root), - "shared_module": str(layout.shared_module), - "tileops_dir": str(layout.tileops_dir), - "isolated_env": layout.isolated_env, - }, - } - Path(os.environ["PTOAS_TEST_RESULT"]).write_text( - json.dumps(result, sort_keys=True), - encoding="utf-8", - ) - return 23 - """ - ).lstrip(), - encoding="utf-8", - ) - - shadow_root = temp_root / "shadow-site" - shadow_package = shadow_root / "ptoas" - shadow_package.mkdir(parents=True, exist_ok=True) - (shadow_package / "__init__.py").write_text( - "raise RuntimeError('shadow ptoas package must not be imported')\n", - encoding="utf-8", - ) - (shadow_package / "_runtime_entry.py").write_text( - "raise RuntimeError('shadow runtime entry must not be imported')\n", - encoding="utf-8", - ) - - wrapper.parent.mkdir(parents=True, exist_ok=True) - wrapper.write_text( - textwrap.dedent( - f""" - #!{sys.executable} - import sys - sys.path.insert(0, {str(wheel_root)!r}) - import ptoas_wheel_bootstrap - ptoas_wheel_bootstrap.main() - """ - ).lstrip(), - encoding="utf-8", - ) - wrapper.chmod(0o755) - - env = os.environ.copy() - env.pop("PTOAS_WHEEL_STAGE2", None) - env["PYTHONPATH"] = os.pathsep.join([str(shadow_root), str(wheel_root)]) - env["LD_LIBRARY_PATH"] = "/tmp/polluted-llvm" - env["DYLD_LIBRARY_PATH"] = "/tmp/polluted-dylib" - env["PTOAS_TEST_RESULT"] = str(result_path) - - completed = subprocess.run( - [str(wrapper), "--version"], - env=env, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True, - check=False, - ) - - self.assertEqual( - completed.returncode, - 23, - msg=f"stdout:\n{completed.stdout}\nstderr:\n{completed.stderr}", - ) - result = json.loads(result_path.read_text(encoding="utf-8")) - - self.assertEqual(result["user_args"], ["--version"]) - self.assertEqual(result["env"]["PTOAS_WHEEL_STAGE2"], "1") - self.assertEqual( - result["env"]["PYTHONPATH"], - str(wheel_root.resolve()) + os.pathsep + str(shadow_root), - ) - self.assertEqual( - result["env"]["LD_LIBRARY_PATH"], - str(runtime_lib_dir.resolve()) + os.pathsep + "/tmp/polluted-llvm", - ) - self.assertEqual( - result["env"]["DYLD_LIBRARY_PATH"], - str(runtime_lib_dir.resolve()) + os.pathsep + "/tmp/polluted-dylib", - ) - self.assertEqual( - result["layout"], - { - "wrapper": str(wrapper.resolve()), - "runtime_root": str(runtime_root.resolve()), - "python_root": str(wheel_root.resolve()), - "shared_module": str((runtime_lib_dir / "ptoas.so").resolve()), - "tileops_dir": str(tileops_dir.resolve()), - "isolated_env": True, - }, - ) - - -if __name__ == "__main__": - unittest.main() diff --git a/pyproject.toml b/pyproject.toml index b34908352a..100b364b39 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,29 +1,22 @@ -# pyproject.toml - Project metadata -# -# Build flow (requires LLVM already built): -# pip install . -# -# This will: -# 1. CMake configure + Ninja build + install -# 2. Package Python bindings into a wheel via docker/create_wheel.sh -# -# Environment variables (all optional): -# LLVM_BUILD_DIR Path to LLVM build dir -# (default: /llvm-workspace/llvm-project/build-shared) -# PTO_BUILD_DIR Path to PTOAS build dir (default: /build) -# PTO_INSTALL_DIR Install prefix (default: /install) -# CMAKE_C_COMPILER Optional C compiler passed through to CMake -# CMAKE_CXX_COMPILER Optional C++ compiler passed through to CMake -# PTOAS_PYTHON_PACKAGE_VERSION Wheel version override +# Copyright (c) 2026 Huawei Technologies Co., Ltd. +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of +# CANN Open Software License Agreement Version 2.0 (the "License"). +# Please refer to the License for details. You may not use this file except in compliance with the License. +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE in the root of the software repository for the full text of the License. + +# Standard PEP 517 configuration for the `ptoas` distribution. Set +# LLVM_BUILD_DIR to an existing LLVM/MLIR build. SKBUILD_BUILD_DIR can be used +# when a persistent CMake build tree is required by tests or development tools. [build-system] -requires = ["setuptools>=68", "wheel"] -build-backend = "_ptoas_build_backend" -backend-path = ["."] +requires = ["scikit-build-core>=0.12.2,<2", "pybind11<3"] +build-backend = "scikit_build_core.build" [project] name = "ptoas" -version = "0.51" +dynamic = ["version"] description = "PTO Assembler & Optimizer" readme = "README.md" requires-python = ">=3.9" @@ -40,3 +33,27 @@ classifiers = [ "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] + +[project.scripts] +ptoas = "ptoas._cli:main" + +[tool.scikit-build] +minimum-version = "build-system.requires" +cmake.version = "CMakeLists.txt" +ninja.version = ">=1.10" +build.verbose = false +editable.mode = "redirect" +install.components = ["PTOAS_Python"] + +[tool.scikit-build.wheel.packages] +ptodsl = "ptodsl/ptodsl" +ptoas = "ptodsl/ptoas" +tilelang_dsl = "tilelang-dsl/python/tilelang_dsl" + +[tool.scikit-build.cmake.define] +PTOAS_RELEASE_VERSION_OVERRIDE = { env = "PTOAS_RELEASE_VERSION_OVERRIDE", default = "" } + +[tool.scikit-build.metadata.version] +provider = "scikit_build_core.metadata.regex" +input = "CMakeLists.txt" +regex = 'project\s*\(\s*ptoas\s+VERSION\s+(?P[0-9]+\.[0-9]+)\s*\)' diff --git a/quick_install.sh b/quick_install.sh index 38509b61d5..ec72e2830e 100755 --- a/quick_install.sh +++ b/quick_install.sh @@ -9,7 +9,7 @@ # For quick development, build and install ptoas and its python bindings # on top of Docker image https://github.com/learning-chip/agent_docker_npu/pull/8 -# assume MLIR is already installed to save time, takes <3min to finish the build of pto extension +# assume MLIR is already installed to save time # # Optional env: # LLVM_BUILD_DIR - default: ${LLVM_SOURCE_DIR:-/llvm-workspace/llvm-project}/build-shared @@ -23,13 +23,10 @@ PTO_INSTALL_DIR="${PTO_INSTALL_DIR:-${PTO_SOURCE_DIR}/install}" LLVM_SOURCE_DIR="${LLVM_SOURCE_DIR:-/llvm-workspace/llvm-project}" LLVM_BUILD_DIR="${LLVM_BUILD_DIR:-${LLVM_SOURCE_DIR}/build-shared}" -PY_ROOT="$(python -c 'import sys; print(sys.prefix)')" - for d in "$LLVM_BUILD_DIR/lib/cmake/llvm" "$LLVM_BUILD_DIR/lib/cmake/mlir"; do test -d "$d" || { echo "error: missing $d (set LLVM_BUILD_DIR?)" >&2; exit 1; } done -PYBIND11_DIR="$(python -m pybind11 --cmakedir)" MLIR_PY_PKG="${LLVM_BUILD_DIR}/tools/mlir/python_packages/mlir_core" test -d "$MLIR_PY_PKG" || { echo "error: MLIR python package dir missing: $MLIR_PY_PKG" >&2; exit 1; } @@ -37,30 +34,20 @@ PTOAS_VERSION="${PTOAS_VERSION:-$(python "${PTO_SOURCE_DIR}/.github/scripts/comp cd "$PTO_SOURCE_DIR" -cmake -C "${PTO_SOURCE_DIR}/cmake/LinuxHardeningCache.cmake" -G Ninja \ - -S . \ - -B build \ - -DLLVM_DIR="${LLVM_BUILD_DIR}/lib/cmake/llvm" \ - -DMLIR_DIR="${LLVM_BUILD_DIR}/lib/cmake/mlir" \ - -DPython3_ROOT_DIR="${PY_ROOT}" \ - -DPython3_EXECUTABLE=python \ - -DPython3_FIND_STRATEGY=LOCATION \ - -Dpybind11_DIR="${PYBIND11_DIR}" \ - -DMLIR_PYTHON_PACKAGE_DIR="${MLIR_PY_PKG}" \ - -DPTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_VERSION}" \ - -DCMAKE_INSTALL_PREFIX="${PTO_INSTALL_DIR}" - -ninja -C build -ninja -C build install - -export PTO_SOURCE_DIR PTO_INSTALL_DIR LLVM_BUILD_DIR -export PTOAS_PYTHON_PACKAGE_VERSION="${PTOAS_PYTHON_PACKAGE_VERSION:-${PTOAS_VERSION}}" -bash "${PTO_SOURCE_DIR}/docker/create_wheel.sh" +PTO_WHEEL_DIR="${PTO_SOURCE_DIR}/build/wheel-dist" +rm -rf "${PTO_WHEEL_DIR}" +mkdir -p "${PTO_WHEEL_DIR}" +LLVM_BUILD_DIR="${LLVM_BUILD_DIR}" \ +PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_VERSION}" \ +SKBUILD_BUILD_DIR="${PTO_SOURCE_DIR}/build" \ + python -m pip wheel . --no-deps --wheel-dir "${PTO_WHEEL_DIR}" + +cmake --install "${PTO_SOURCE_DIR}/build" --prefix "${PTO_INSTALL_DIR}" shopt -s nullglob -wheels=("${MLIR_PY_PKG}/dist/ptoas-"*.whl) +wheels=("${PTO_WHEEL_DIR}/ptoas-"*.whl) shopt -u nullglob -((${#wheels[@]} > 0)) || { echo "error: no ptoas-*.whl under ${MLIR_PY_PKG}/dist" >&2; exit 1; } +((${#wheels[@]} > 0)) || { echo "error: no ptoas-*.whl under ${PTO_WHEEL_DIR}" >&2; exit 1; } pip install --force-reinstall "${wheels[0]}" export PATH="${PTO_SOURCE_DIR}/build/tools/ptoas:${PATH}" diff --git a/test/python/test_docker_runtime_packaging.py b/test/python/test_docker_runtime_packaging.py index 646d621db3..a3b1768163 100644 --- a/test/python/test_docker_runtime_packaging.py +++ b/test/python/test_docker_runtime_packaging.py @@ -13,14 +13,25 @@ REPO_ROOT = Path(__file__).resolve().parents[2] DOCKERFILE = REPO_ROOT / "docker" / "Dockerfile" -COPY_DEPS_SCRIPT = REPO_ROOT / "docker" / "copy_ptoas_deps.sh" COLLECT_DIST_SCRIPT = REPO_ROOT / "docker" / "collect_ptoas_dist.sh" COLLECT_DIST_MAC_SCRIPT = REPO_ROOT / "docker" / "collect_ptoas_dist_mac.sh" +PTOAS_CMAKE = REPO_ROOT / "tools" / "ptoas" / "CMakeLists.txt" BUILD_WHEEL_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "build_wheel.yml" BUILD_WHEEL_MAC_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "build_wheel_mac.yml" class DockerRuntimePackagingTests(unittest.TestCase): + def test_runtime_uses_standard_python_extension_without_native_cli(self): + cmake = PTOAS_CMAKE.read_text(encoding="utf-8") + + self.assertIn( + "pybind11_add_module(ptoas_runtime MODULE", + cmake, + ) + self.assertIn('OUTPUT_NAME "_native"', cmake) + self.assertNotIn("add_executable(ptoas_native_cli", cmake) + self.assertNotIn('OUTPUT_NAME "ptoas-native"', cmake) + def test_runtime_image_uses_wheel_entrypoint_instead_of_copied_wrapper(self): dockerfile = DOCKERFILE.read_text(encoding="utf-8") @@ -35,41 +46,35 @@ def test_runtime_image_uses_wheel_entrypoint_instead_of_copied_wrapper(self): ) self.assertNotIn("/usr/local/lib/ptoas", dockerfile) - def test_dependency_collection_roots_at_shared_module(self): - script = COPY_DEPS_SCRIPT.read_text(encoding="utf-8") + def test_docker_builds_wheel_through_standard_pep517_backend(self): + dockerfile = DOCKERFILE.read_text(encoding="utf-8") - self.assertIn('PTOAS_SHARED_MODULE="${PTO_INSTALL_DIR}/lib/ptoas.so"', script) - self.assertIn('done < <(linux_runtime_dep_paths "$PTOAS_SHARED_MODULE")', script) - self.assertNotIn('PTOAS_BIN="${PTO_BUILD_DIR}/tools/ptoas/ptoas"', script) - self.assertNotIn('done < <(linux_runtime_dep_paths "$PTOAS_BIN")', script) + self.assertIn("python -m pip wheel .", dockerfile) + self.assertIn("SKBUILD_BUILD_DIR=$PTO_BUILD_DIR", dockerfile) + self.assertNotIn("create_wheel.sh", dockerfile) + self.assertNotIn("_ptoas_build_backend", dockerfile) - def test_linux_dist_stages_install_tree_python_root(self): + def test_linux_dist_packages_python_wrapper_and_native_extension(self): script = COLLECT_DIST_SCRIPT.read_text(encoding="utf-8") - self.assertIn('PTOAS_WRAPPER_PKG_SRC_DIR="${PTO_INSTALL_DIR}/ptoas"', script) - self.assertIn('PTOAS_WRAPPER_PKG_DIST_DIR="${PTOAS_DIST_DIR}/ptoas"', script) - self.assertIn('PTOAS_WHEEL_BOOTSTRAP_SRC="${PTO_INSTALL_DIR}/ptoas_wheel_bootstrap.py"', script) - self.assertIn('cp "${PTOAS_WHEEL_BOOTSTRAP_SRC}" "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}"', script) - self.assertIn('test -f "${PTOAS_WRAPPER_PKG_DIST_DIR}/_runtime_entry.py"', script) - self.assertIn('test -f "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}"', script) + self.assertIn('PTOAS_BIN="${PTO_INSTALL_DIR}/bin/ptoas"', script) + self.assertIn('PTOAS_PACKAGE_SRC_DIR="${PTO_INSTALL_DIR}/ptoas"', script) + self.assertIn('PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}"', script) + self.assertIn("patchelf --set-rpath '$ORIGIN/../lib' \"${PTOAS_NATIVE_MODULE}\"", script) self.assertIn('"${PTOAS_DIST_DIR}/bin/ptoas" --version', script) - self.assertNotIn("PTOAS_PYTHON_ROOT_DIST_DIR", script) - self.assertNotIn("export PTOAS_PYTHON_ROOT", script) - self.assertNotIn('cat > "${PTOAS_DIST_DIR}/ptoas"', script) + self.assertNotIn("ptoas-native", script) + self.assertNotIn("ptoas.so", script) - def test_macos_dist_stages_install_tree_python_root(self): + def test_macos_dist_packages_python_wrapper_and_native_extension(self): script = COLLECT_DIST_MAC_SCRIPT.read_text(encoding="utf-8") - self.assertIn('PTOAS_SHARED_MODULE="${PTO_INSTALL_DIR}/lib/ptoas.so"', script) - self.assertIn('PTOAS_WRAPPER_PKG_SRC_DIR="${PTO_INSTALL_DIR}/ptoas"', script) - self.assertIn('PTOAS_WRAPPER_PKG_DIST_DIR="${PTOAS_DIST_DIR}/ptoas"', script) - self.assertIn('PTOAS_WHEEL_BOOTSTRAP_SRC="${PTO_INSTALL_DIR}/ptoas_wheel_bootstrap.py"', script) - self.assertIn('cp "${PTOAS_WHEEL_BOOTSTRAP_SRC}" "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}"', script) - self.assertIn('collect_dylibs "${PTOAS_SHARED_MODULE_DIST_PATH}"', script) - self.assertIn('test -f "${PTOAS_WRAPPER_PKG_DIST_DIR}/_runtime_entry.py"', script) - self.assertIn('test -f "${PTOAS_WHEEL_BOOTSTRAP_DIST_PATH}"', script) + self.assertIn('PTOAS_BIN="${PTO_INSTALL_DIR}/bin/ptoas"', script) + self.assertIn('PTOAS_PACKAGE_SRC_DIR="${PTO_INSTALL_DIR}/ptoas"', script) + self.assertIn('PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}"', script) + self.assertIn('collect_dylibs "${PTOAS_NATIVE_MODULE}"', script) self.assertIn('"${PTOAS_DIST_DIR}/bin/ptoas" --version', script) - self.assertNotIn('cat > "${PTOAS_DIST_DIR}/ptoas"', script) + self.assertNotIn("ptoas-native", script) + self.assertNotIn("ptoas.so", script) def test_dist_archives_use_bin_entrypoint(self): linux_workflow = BUILD_WHEEL_WORKFLOW.read_text(encoding="utf-8") @@ -82,15 +87,11 @@ def test_dist_archives_use_bin_entrypoint(self): self.assertIn('"$TEST_DIR/extracted/bin/ptoas" --version', mac_workflow) self.assertNotIn('"$TEST_DIR/extracted/ptoas" --version', mac_workflow) - def test_wheel_import_smoke_covers_polluted_ptoas_version(self): + def test_wheel_import_smoke_imports_native_extension(self): script = (REPO_ROOT / "docker" / "test_wheel_imports.sh").read_text(encoding="utf-8") - self.assertIn("Testing installed ptoas console entry under polluted Python and LLVM paths...", script) - self.assertIn("POLLUTED_ENV_DIR=\"${TEST_TMPDIR}/polluted-env\"", script) - self.assertIn('PYTHONPATH="${POLLUTED_ENV_DIR}"', script) - self.assertIn("POLLUTED_PTOAS_VERSION_OUTPUT", script) - self.assertIn('"/tmp/polluted-llvm"', script) - self.assertIn('"/tmp/polluted-dylib"', script) + self.assertIn("from ptoas import _native", script) + self.assertNotIn("POLLUTED_PTOAS_VERSION_OUTPUT", script) if __name__ == "__main__": diff --git a/test/python/test_ptoas_build_backend.py b/test/python/test_ptoas_build_backend.py deleted file mode 100644 index 09ea739f14..0000000000 --- a/test/python/test_ptoas_build_backend.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import tempfile -import unittest -import zipfile -from pathlib import Path -from unittest import mock - -import _ptoas_build_backend as build_backend - - -class PtoasBuildBackendTests(unittest.TestCase): - def test_prepare_metadata_honors_package_name_override(self): - with tempfile.TemporaryDirectory() as temp_dir, mock.patch.dict( - build_backend.os.environ, - { - "PTOAS_PYTHON_PACKAGE_NAME": "ptoas-vmi", - "PTOAS_PYTHON_PACKAGE_VERSION": "0.1.0", - }, - clear=False, - ): - dist_info_name = build_backend.prepare_metadata_for_build_wheel(temp_dir) - - dist_info = Path(temp_dir) / dist_info_name - metadata = (dist_info / "METADATA").read_text(encoding="utf-8") - - self.assertEqual(dist_info_name, "ptoas_vmi-0.1.0.dist-info") - self.assertIn("Name: ptoas-vmi", metadata) - self.assertIn("Version: 0.1.0", metadata) - - def test_cmake_build_driver_is_used_for_build_and_install(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - repo = temp_root / "repo" - build_dir = temp_root / "build" - llvm_build = temp_root / "llvm-build" - install_dir = temp_root / "install" - (repo / "cmake").mkdir(parents=True) - (install_dir / "lib").mkdir(parents=True) - (install_dir / "lib" / "ptoas.so").write_bytes(b"fake shared module") - - check_call_args = [] - - def fake_check_call(args): - check_call_args.append(args) - - with mock.patch.object(build_backend, "_REPO", repo), mock.patch.object( - build_backend, "_BUILD_DIR", build_dir - ), mock.patch.object( - build_backend, "_LLVM_BUILD_DIR", llvm_build - ), mock.patch.object( - build_backend, "_PTO_INSTALL_DIR", install_dir - ), mock.patch.object( - build_backend, - "_should_use_linux_hardening_cache", - return_value=False, - ), mock.patch.object( - build_backend.subprocess, - "check_output", - return_value="/tmp/pybind11-cmake", - ), mock.patch.object( - build_backend.subprocess, - "check_call", - side_effect=fake_check_call, - ), mock.patch.object( - build_backend, - "_assert_installed_ptodsl_payload", - ): - build_backend._cmake_configure_and_build() - - self.assertEqual( - check_call_args[-2], - ["cmake", "--build", str(build_dir)], - ) - self.assertEqual( - check_call_args[-1], - ["cmake", "--build", str(build_dir), "--target", "install"], - ) - - def test_installed_shared_module_must_be_non_empty(self): - with tempfile.TemporaryDirectory() as temp_dir: - install_dir = Path(temp_dir) / "install" - shared_module = install_dir / "lib" / "ptoas.so" - shared_module.parent.mkdir(parents=True) - shared_module.write_bytes(b"") - - with mock.patch.object(build_backend, "_PTO_INSTALL_DIR", install_dir): - with self.assertRaisesRegex(RuntimeError, "missing or empty"): - build_backend._assert_installed_ptoas_shared_module() - - def test_build_editable_routes_console_entry_through_wheel_bootstrap(self): - with tempfile.TemporaryDirectory() as temp_dir, mock.patch.dict( - build_backend.os.environ, - { - "PTOAS_PYTHON_PACKAGE_NAME": "ptoas", - "PTOAS_PYTHON_PACKAGE_VERSION": "0.1.0", - }, - clear=False, - ), mock.patch.object( - build_backend, - "_cmake_configure_and_build", - ) as cmake_build: - wheel_dir = Path(temp_dir) / "wheel" - wheel_dir.mkdir(parents=True, exist_ok=True) - - wheel_name = build_backend.build_editable(str(wheel_dir)) - wheel_path = wheel_dir / wheel_name - - with zipfile.ZipFile(wheel_path) as zf: - entry_points = zf.read("ptoas-0.1.0.dist-info/entry_points.txt").decode("utf-8") - - cmake_build.assert_called_once_with(skip_install=True) - - self.assertIn("ptoas=ptoas_wheel_bootstrap:main", entry_points) - self.assertNotIn("ptoas._launcher", entry_points) - - -if __name__ == "__main__": - unittest.main() diff --git a/test/python/test_scikit_build_config.py b/test/python/test_scikit_build_config.py new file mode 100644 index 0000000000..3f013e71dc --- /dev/null +++ b/test/python/test_scikit_build_config.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# Copyright (c) 2026 Huawei Technologies Co., Ltd. +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of +# CANN Open Software License Agreement Version 2.0 (the "License"). +# Please refer to the License for details. You may not use this file except in compliance with the License. +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE in the root of the software repository for the full text of the License. + +import json +import subprocess +import sys +import tomllib +import unittest +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +PTOAS_PYPROJECT = REPO_ROOT / "pyproject.toml" +VMI_PROJECT_DIR = REPO_ROOT / "packaging" / "ptoas-vmi" +VMI_PYPROJECT = VMI_PROJECT_DIR / "pyproject.toml" +PTOAS_PACKAGE_INIT = REPO_ROOT / "ptodsl" / "ptoas" / "__init__.py" + + +def _read_pyproject(path: Path) -> dict: + with path.open("rb") as file: + return tomllib.load(file) + + +def _project_table(project_dir: Path) -> dict: + result = subprocess.run( + [ + sys.executable, + "-m", + "scikit_build_core.build", + "project-table", + ], + cwd=project_dir, + capture_output=True, + text=True, + check=False, + ) + if result.returncode != 0: + raise AssertionError(result.stderr or result.stdout) + return json.loads(result.stdout) + + +class ScikitBuildConfigTests(unittest.TestCase): + def test_root_project_uses_standard_backend_and_console_script(self): + config = _read_pyproject(PTOAS_PYPROJECT) + + self.assertEqual( + config["build-system"]["build-backend"], + "scikit_build_core.build", + ) + self.assertIn("scikit-build-core>=0.12.2,<2", config["build-system"]["requires"]) + self.assertEqual(config["project"]["name"], "ptoas") + self.assertEqual(config["project"]["scripts"]["ptoas"], "ptoas._cli:main") + self.assertEqual( + config["tool"]["scikit-build"]["install"]["components"], + ["PTOAS_Python"], + ) + + def test_static_projects_resolve_expected_distribution_metadata(self): + ptoas = _project_table(REPO_ROOT) + vmi = _project_table(VMI_PROJECT_DIR) + + self.assertEqual((ptoas["name"], ptoas["version"]), ("ptoas", "0.51")) + self.assertEqual((vmi["name"], vmi["version"]), ("ptoas-vmi", "0.1.3")) + self.assertEqual(ptoas["scripts"]["ptoas"], "ptoas._cli:main") + self.assertEqual(vmi["scripts"]["ptoas"], "ptoas._cli:main") + + def test_projects_share_python_package_sources(self): + ptoas = _read_pyproject(PTOAS_PYPROJECT) + vmi = _read_pyproject(VMI_PYPROJECT) + + self.assertEqual( + ptoas["tool"]["scikit-build"]["wheel"]["packages"], + { + "ptodsl": "ptodsl/ptodsl", + "ptoas": "ptodsl/ptoas", + "tilelang_dsl": "tilelang-dsl/python/tilelang_dsl", + }, + ) + self.assertEqual( + vmi["tool"]["scikit-build"]["cmake"]["source-dir"], + "../..", + ) + + def test_editable_install_uses_backend_redirect_without_package_path_hacks(self): + ptoas = _read_pyproject(PTOAS_PYPROJECT) + package_init = PTOAS_PACKAGE_INIT.read_text(encoding="utf-8") + + self.assertEqual( + ptoas["tool"]["scikit-build"]["editable"]["mode"], + "redirect", + ) + self.assertNotIn("extend_path", package_init) + + def test_cmake_python_payload_uses_dedicated_install_component(self): + cmake_files = [ + REPO_ROOT / "CMakeLists.txt", + REPO_ROOT / "lib" / "Bindings" / "Python" / "CMakeLists.txt", + REPO_ROOT / "tools" / "ptoas" / "CMakeLists.txt", + ] + combined = "\n".join(path.read_text(encoding="utf-8") for path in cmake_files) + + self.assertIn("COMPONENT PTOAS_Python", combined) + self.assertIn("if(SKBUILD)", combined) + self.assertIn('DIRECTORY "${MLIR_PYTHON_PACKAGE_DIR}/mlir"', combined) + + def test_legacy_wheel_builders_are_removed(self): + self.assertFalse((REPO_ROOT / "_ptoas_build_backend.py").exists()) + self.assertFalse((REPO_ROOT / "docker" / "create_wheel.sh").exists()) + self.assertFalse((REPO_ROOT / "docker" / "setup.py").exists()) + self.assertFalse((REPO_ROOT / "docker" / "setup_mac.py").exists()) + + +if __name__ == "__main__": + unittest.main() diff --git a/test/python/test_validate_wheel_payload.py b/test/python/test_validate_wheel_payload.py index 5b02a6e95e..318d1a6fde 100644 --- a/test/python/test_validate_wheel_payload.py +++ b/test/python/test_validate_wheel_payload.py @@ -11,12 +11,12 @@ import tempfile import unittest import zipfile +import importlib.machinery from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[2] VALIDATOR = REPO_ROOT / "docker" / "validate_wheel_payload.py" -CREATE_WHEEL = REPO_ROOT / "docker" / "create_wheel.sh" LINUX_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "build_wheel.yml" MAC_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "build_wheel_mac.yml" WHEEL_IMPORTS = REPO_ROOT / "docker" / "test_wheel_imports.sh" @@ -29,23 +29,25 @@ def _make_wheel( self, root: Path, *, - include_runtime_so: bool, - include_runtime_entry: bool = True, - include_bootstrap: bool = True, - entry_points_text: str = "[console_scripts]\nptoas=ptoas_wheel_bootstrap:main\n", + include_native_module: bool, + include_cli: bool = True, + include_tileops: bool = True, + entry_points_text: str = "[console_scripts]\nptoas=ptoas._cli:main\n", wheel_stem: str = "ptoas", dist_info_stem: str = "ptoas", ) -> Path: wheel = root / f"{wheel_stem}-1.2.3-cp311-cp311-linux_x86_64.whl" with zipfile.ZipFile(wheel, "w") as zf: - if include_bootstrap: - zf.writestr("ptoas_wheel_bootstrap.py", "") zf.writestr("ptoas/__init__.py", "") - zf.writestr("ptoas/_launcher.py", "") - if include_runtime_entry: - zf.writestr("ptoas/_runtime_entry.py", "") - if include_runtime_so: - zf.writestr("ptoas/_runtime/lib/ptoas.so", "fake") + if include_cli: + zf.writestr("ptoas/_cli.py", "") + if include_tileops: + zf.writestr( + "ptoas/_runtime/share/ptoas/TileOps/__init__.py", "" + ) + if include_native_module: + suffix = importlib.machinery.EXTENSION_SUFFIXES[0] + zf.writestr(f"ptoas/_native{suffix}", "fake") zf.writestr( f"{dist_info_stem}-1.2.3.dist-info/entry_points.txt", entry_points_text, @@ -54,7 +56,7 @@ def _make_wheel( def test_validator_accepts_current_runtime_payload_layout(self): with tempfile.TemporaryDirectory() as temp_dir: - wheel = self._make_wheel(Path(temp_dir), include_runtime_so=True) + wheel = self._make_wheel(Path(temp_dir), include_native_module=True) result = subprocess.run( ["python3", str(VALIDATOR), str(wheel)], capture_output=True, @@ -65,9 +67,9 @@ def test_validator_accepts_current_runtime_payload_layout(self): self.assertEqual(result.returncode, 0, result.stderr) self.assertIn("validated wheel payload and launcher contract", result.stdout) - def test_validator_rejects_missing_runtime_shared_module(self): + def test_validator_rejects_missing_native_module(self): with tempfile.TemporaryDirectory() as temp_dir: - wheel = self._make_wheel(Path(temp_dir), include_runtime_so=False) + wheel = self._make_wheel(Path(temp_dir), include_native_module=False) result = subprocess.run( ["python3", str(VALIDATOR), str(wheel)], capture_output=True, @@ -76,14 +78,14 @@ def test_validator_rejects_missing_runtime_shared_module(self): ) self.assertNotEqual(result.returncode, 0) - self.assertIn("ptoas/_runtime/lib/ptoas.so", result.stderr) + self.assertIn("ptoas._native", result.stderr) - def test_validator_rejects_missing_runtime_entry_module(self): + def test_validator_rejects_missing_cli_module(self): with tempfile.TemporaryDirectory() as temp_dir: wheel = self._make_wheel( Path(temp_dir), - include_runtime_so=True, - include_runtime_entry=False, + include_native_module=True, + include_cli=False, ) result = subprocess.run( ["python3", str(VALIDATOR), str(wheel)], @@ -93,14 +95,14 @@ def test_validator_rejects_missing_runtime_entry_module(self): ) self.assertNotEqual(result.returncode, 0) - self.assertIn("ptoas/_runtime_entry.py", result.stderr) + self.assertIn("ptoas/_cli.py", result.stderr) - def test_validator_rejects_missing_wheel_bootstrap_module(self): + def test_validator_rejects_missing_packaged_tileops(self): with tempfile.TemporaryDirectory() as temp_dir: wheel = self._make_wheel( Path(temp_dir), - include_runtime_so=True, - include_bootstrap=False, + include_native_module=True, + include_tileops=False, ) result = subprocess.run( ["python3", str(VALIDATOR), str(wheel)], @@ -110,14 +112,14 @@ def test_validator_rejects_missing_wheel_bootstrap_module(self): ) self.assertNotEqual(result.returncode, 0) - self.assertIn("ptoas_wheel_bootstrap.py", result.stderr) + self.assertIn("TileOps/__init__.py", result.stderr) - def test_validator_rejects_legacy_ptoas_launcher_entrypoint(self): + def test_validator_rejects_legacy_bootstrap_entrypoint(self): with tempfile.TemporaryDirectory() as temp_dir: wheel = self._make_wheel( Path(temp_dir), - include_runtime_so=True, - entry_points_text="[console_scripts]\nptoas=ptoas._launcher:main\n", + include_native_module=True, + entry_points_text="[console_scripts]\nptoas=ptoas_wheel_bootstrap:main\n", ) result = subprocess.run( ["python3", str(VALIDATOR), str(wheel)], @@ -127,14 +129,14 @@ def test_validator_rejects_legacy_ptoas_launcher_entrypoint(self): ) self.assertNotEqual(result.returncode, 0) - self.assertIn("ptoas_wheel_bootstrap:main", result.stderr) + self.assertIn("ptoas._cli:main", result.stderr) def test_validator_accepts_normalized_entrypoint_spacing(self): with tempfile.TemporaryDirectory() as temp_dir: wheel = self._make_wheel( Path(temp_dir), - include_runtime_so=True, - entry_points_text="[console_scripts]\nptoas = ptoas_wheel_bootstrap:main\n", + include_native_module=True, + entry_points_text="[console_scripts]\nptoas = ptoas._cli:main\n", ) result = subprocess.run( ["python3", str(VALIDATOR), str(wheel)], @@ -149,7 +151,7 @@ def test_validator_accepts_vmi_distribution_name(self): with tempfile.TemporaryDirectory() as temp_dir: wheel = self._make_wheel( Path(temp_dir), - include_runtime_so=True, + include_native_module=True, wheel_stem="ptoas_vmi", dist_info_stem="ptoas_vmi", ) @@ -196,7 +198,8 @@ def test_release_workflows_separate_cli_and_wheel_versions(self): ) self.assertIn('PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}"', linux_workflow) self.assertIn('PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_CLI_VERSION}"', linux_workflow) - self.assertIn('export PTOAS_PYTHON_PACKAGE_VERSION="${PTOAS_VERSION}"', linux_workflow) + self.assertIn('PTOAS_WHEEL_SOURCE_DIR="${PTO_SOURCE_DIR}/packaging/ptoas-vmi"', linux_workflow) + self.assertIn('SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}"', linux_workflow) self.assertIn("workflow_dispatch:", mac_workflow) self.assertIn("release_kind:", mac_workflow) @@ -212,19 +215,8 @@ def test_release_workflows_separate_cli_and_wheel_versions(self): ) self.assertIn('PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}"', mac_workflow) self.assertIn('PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_CLI_VERSION}"', mac_workflow) - self.assertIn('export PTOAS_PYTHON_PACKAGE_VERSION="${PTOAS_VERSION}"', mac_workflow) - - def test_create_wheel_script_validates_package_name(self): - script = CREATE_WHEEL.read_text(encoding="utf-8") - - self.assertIn( - "if [[ ! \"${PTOAS_PYTHON_PACKAGE_NAME}\" =~ ^[A-Za-z0-9]+([-_.][A-Za-z0-9]+)*$ ]]; then", - script, - ) - self.assertIn( - "Error: invalid PTOAS_PYTHON_PACKAGE_NAME", - script, - ) + self.assertIn('PTOAS_WHEEL_SOURCE_DIR="${PTO_SOURCE_DIR}/packaging/ptoas-vmi"', mac_workflow) + self.assertIn('SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}"', mac_workflow) def test_wheel_imports_script_keeps_clean_env_ptoas_smoke(self): script = WHEEL_IMPORTS.read_text(encoding="utf-8") diff --git a/tools/ptoas/CMakeLists.txt b/tools/ptoas/CMakeLists.txt index 1e2918bd5a..0d4ede0c40 100644 --- a/tools/ptoas/CMakeLists.txt +++ b/tools/ptoas/CMakeLists.txt @@ -6,11 +6,6 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - set(PTOAS_RUNTIME_SOURCES ptoas.cpp driver.cpp @@ -45,18 +40,12 @@ function(ptoas_configure_runtime_target target_name) PTOAS_DEFAULT_TILELANG_PATH="${CMAKE_SOURCE_DIR}/lib/TileOps" PTOAS_DEFAULT_TILELANG_PKG_PATH="${CMAKE_SOURCE_DIR}/tilelang-dsl/python" PTOAS_DEFAULT_PTODSL_PKG_PATH="${CMAKE_SOURCE_DIR}/ptodsl" - ${ARGN} ) - target_link_libraries(${target_name} PRIVATE - # === 你的本地库 (请确认 lib/PTO/*/CMakeLists.txt 里的定义名) === - PTOIR # 替代 MLIRPTODialect - PTOTransforms # 替代 MLIRPTOTransforms + target_link_libraries(${target_name} PUBLIC + PTOIR + PTOTransforms ptobc_lib - - # === MLIR 基础设施 === - MLIRMlirOptMain # [重要] 包含了 main 函数入口逻辑,通常必须链接 - - # === MLIR 标准库 === + MLIRMlirOptMain MLIRBufferizationTransforms MLIRArithTransforms MLIRTensorTransforms @@ -86,43 +75,54 @@ function(ptoas_configure_runtime_target target_name) ) endfunction() -add_library(ptoas_runtime SHARED ${PTOAS_RUNTIME_SOURCES}) -# Keep the shared runtime's compile mode aligned with LLVM/MLIR so RTTI, -# exceptions, and visibility expectations match the libraries it links to. -llvm_update_compile_flags(ptoas_runtime) +# Keep the LLVM-based driver sources under LLVM's RTTI/exception compile mode. +# The pybind11 translation unit must retain the Python extension's normal RTTI +# and exception mode, so it is compiled by the module target separately. +add_library(ptoas_runtime_objects OBJECT ${PTOAS_RUNTIME_SOURCES}) +llvm_update_compile_flags(ptoas_runtime_objects) +ptoas_configure_runtime_target(ptoas_runtime_objects) + +# Build the normal Python extension used by wheel, build-tree, install-tree, +# and Python-based standalone distributions. Linking the object library pulls +# in the driver implementation and propagates its native link dependencies. +pybind11_add_module(ptoas_runtime MODULE NativeModule.cpp) +target_link_libraries(ptoas_runtime PRIVATE ptoas_runtime_objects) set_target_properties(ptoas_runtime PROPERTIES - OUTPUT_NAME "ptoas" - PREFIX "" -) -ptoas_configure_runtime_target(ptoas_runtime - PTOAS_BUILD_SHARED_LIBRARY=1 + OUTPUT_NAME "_native" + LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/python-module" ) -set(PTOAS_BUILD_RUNTIME_STAGING_DIR "${CMAKE_BINARY_DIR}/runtime-staging") -add_custom_target(ptoas_runtime_staging ALL - COMMAND ${CMAKE_COMMAND} -E make_directory - "${PTOAS_BUILD_RUNTIME_STAGING_DIR}/lib" - "${PTOAS_BUILD_RUNTIME_STAGING_DIR}/share/ptoas" +set(PTOAS_BUILD_PYTHON_PACKAGE_DIR "${CMAKE_BINARY_DIR}/python/ptoas") +add_custom_target(PTOASPythonPackage ALL + COMMAND ${CMAKE_COMMAND} -E remove_directory + "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}" + COMMAND ${CMAKE_COMMAND} -E copy_directory + "${CMAKE_SOURCE_DIR}/ptodsl/ptoas" + "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}" COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" - "${PTOAS_BUILD_RUNTIME_STAGING_DIR}/lib/ptoas.so" - COMMAND ${CMAKE_COMMAND} -E remove_directory - "${PTOAS_BUILD_RUNTIME_STAGING_DIR}/share/ptoas/TileOps" + "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}/$" + COMMAND ${CMAKE_COMMAND} -E make_directory + "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}/_runtime/share/ptoas" COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_SOURCE_DIR}/lib/TileOps" - "${PTOAS_BUILD_RUNTIME_STAGING_DIR}/share/ptoas/TileOps" + "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}/_runtime/share/ptoas/TileOps" + COMMAND ${CMAKE_COMMAND} -E remove_directory + "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}/_runtime/share/ptoas/TileOps/__pycache__" DEPENDS ptoas_runtime - COMMENT "Staging ptoas runtime into build/runtime-staging" + COMMENT "Staging the ptoas Python package" VERBATIM ) - if(TARGET PTODSLPackage) - # The build-tree launcher imports ptoas._runtime_entry from build/python. - # Keep that package staging coupled to every runtime staging entrypoint, - # including partial builds such as tools/ptoas/all. - add_dependencies(ptoas_runtime_staging PTODSLPackage) + add_dependencies(PTOASPythonPackage PTODSLPackage) endif() +# Keep the historical aggregate target name for existing developer commands; +# the actual runtime payload now lives in the staged Python package. +add_custom_target(ptoas_runtime_staging ALL + DEPENDS PTOASPythonPackage +) + if(TARGET ptoas_runtime_deps) add_dependencies(ptoas_runtime_deps ptoas_runtime_staging) endif() @@ -133,6 +133,14 @@ install(PROGRAMS "${PTOAS_WRAPPER_BINARY}" ) install(TARGETS ptoas_runtime - LIBRARY DESTINATION lib - COMPONENT PTOAS_Runtime + LIBRARY DESTINATION ptoas + COMPONENT PTOAS_Python +) + +install( + DIRECTORY "${CMAKE_SOURCE_DIR}/lib/TileOps" + DESTINATION "ptoas/_runtime/share/ptoas" + COMPONENT PTOAS_Python + PATTERN "__pycache__" EXCLUDE + PATTERN "*.pyc" EXCLUDE ) diff --git a/tools/ptoas/NativeModule.cpp b/tools/ptoas/NativeModule.cpp new file mode 100644 index 0000000000..54bfc26e41 --- /dev/null +++ b/tools/ptoas/NativeModule.cpp @@ -0,0 +1,37 @@ +// Copyright (c) 2026 Huawei Technologies Co., Ltd. +// This program is free software, you can redistribute it and/or modify it under the terms and conditions of +// CANN Open Software License Agreement Version 2.0 (the "License"). +// Please refer to the License for details. You may not use this file except in compliance with the License. +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// See LICENSE in the root of the software repository for the full text of the License. + +#include "ptoas.h" + +#include "pybind11/pybind11.h" +#include "pybind11/stl.h" + +#include +#include + +namespace py = pybind11; + +namespace { + +int runPTOASFromPython(const std::vector &arguments) { + std::vector storage = arguments; + std::vector argv; + argv.reserve(storage.size()); + for (std::string &argument : storage) + argv.push_back(argument.data()); + + py::gil_scoped_release release; + return mlir::pto::runPTOAS(static_cast(argv.size()), argv.data()); +} + +} // namespace + +PYBIND11_MODULE(_native, module) { + module.doc() = "Native PTOAS command-line entrypoint"; + module.def("main", &runPTOASFromPython, py::arg("argv")); +} diff --git a/tools/ptoas/driver.cpp b/tools/ptoas/driver.cpp index 6caa23ce33..5c6e81b79e 100644 --- a/tools/ptoas/driver.cpp +++ b/tools/ptoas/driver.cpp @@ -1284,12 +1284,6 @@ static int runPTOASDriver(int argc, char **argv) { return 1; } -extern "C" int ptoas_entrypoint(int argc, char **argv) { +int mlir::pto::runPTOAS(int argc, char **argv) { return runPTOASDriver(argc, argv); } - -#ifndef PTOAS_BUILD_SHARED_LIBRARY -int main(int argc, char **argv) { - return runPTOASDriver(argc, argv); -} -#endif diff --git a/tools/ptoas/ptoas.h b/tools/ptoas/ptoas.h index 92ce03ecee..ba422628a8 100644 --- a/tools/ptoas/ptoas.h +++ b/tools/ptoas/ptoas.h @@ -125,8 +125,8 @@ void registerPTOASDialects(DialectRegistry ®istry); void registerPTOASPassesAndCLOptions(); void loadPTOASDialects(MLIRContext &context); -// Shared-library entrypoint for wheel-installed in-process launching. -extern "C" int ptoas_entrypoint(int argc, char **argv); +// Reusable driver entry shared by the Python extension and standalone CLI. +int runPTOAS(int argc, char **argv); // Attach textual-.pto SSA name hints (function args, block args, op results) // to the parsed module's Locations as debug metadata. Called by the driver diff --git a/tools/ptoas/ptoas_wrapper.py b/tools/ptoas/ptoas_wrapper.py index 3dadc46d16..fb07afaf9b 100644 --- a/tools/ptoas/ptoas_wrapper.py +++ b/tools/ptoas/ptoas_wrapper.py @@ -7,12 +7,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -"""Build/install-tree wrapper for the `ptoas` entrypoint. - -This script is configured into the build tree and installed as `bin/ptoas`. -It bootstraps the Python package root for tree layouts, then delegates to the -shared in-process runtime entry contract in `ptoas._runtime_entry`. -""" +"""Add a CMake tree's Python root, then run the regular PTOAS CLI module.""" from __future__ import annotations @@ -34,115 +29,46 @@ def _resolve_wrapper_path(argv0: str | None = None) -> Path: raise SystemExit(f"unable to locate the installed ptoas wrapper: {candidate}") -def _build_tree_root(wrapper: Path) -> Path | None: - if len(wrapper.parents) < 3: - return None - return wrapper.parents[2] - - -def _install_tree_root(wrapper: Path) -> Path | None: - if len(wrapper.parents) < 2: - return None - return wrapper.parents[1] - - def _is_build_tree_wrapper(wrapper: Path) -> bool: return len(wrapper.parents) >= 2 and wrapper.parents[1].name == "tools" def _require_python_root(python_root: Path, *, context: str) -> Path: - helper = python_root / "ptoas" / "_runtime_entry.py" + helper = python_root / "ptoas" / "_cli.py" if helper.is_file(): return python_root.resolve() raise SystemExit( f"unable to locate the {context} ptoas Python package root: " - f"expected {python_root}/ptoas/_runtime_entry.py" + f"expected {python_root}/ptoas/_cli.py" ) -def _require_runtime_root(runtime_root: Path) -> Path: - shared_module = runtime_root / "lib" / "ptoas.so" - tileops_dir = runtime_root / "share" / "ptoas" / "TileOps" - if shared_module.is_file() and shared_module.stat().st_size > 0 and tileops_dir.is_dir(): - return runtime_root.resolve() - raise SystemExit( - "unable to locate the ptoas runtime tree: expected " - f"{runtime_root}/lib/ptoas.so and {runtime_root}/share/ptoas/TileOps" - ) - - -def _resolve_build_tree_layout(wrapper: Path): - from ptoas import _runtime_entry - - build_root = _build_tree_root(wrapper) - if build_root is None: - raise SystemExit("unable to locate the build-tree layout for ptoas") - - python_root = _require_python_root(build_root / "python", context="build-tree") - runtime_root = _require_runtime_root(build_root / "runtime-staging") - - return _runtime_entry.PTOASRuntimeLayout( - wrapper=wrapper, - runtime_root=runtime_root, - python_root=python_root, - shared_module=(runtime_root / "lib" / "ptoas.so").resolve(), - tileops_dir=(runtime_root / "share" / "ptoas" / "TileOps").resolve(), - isolated_env=False, - ) - - -def _resolve_install_tree_layout(wrapper: Path): - from ptoas import _runtime_entry - - install_root = _install_tree_root(wrapper) - if install_root is None: - raise SystemExit("unable to locate the install-tree layout for ptoas") - - python_root = _require_python_root(install_root, context="install-tree") - runtime_root = _require_runtime_root(install_root) - - return _runtime_entry.PTOASRuntimeLayout( - wrapper=wrapper, - runtime_root=runtime_root, - python_root=python_root, - shared_module=(runtime_root / "lib" / "ptoas.so").resolve(), - tileops_dir=(runtime_root / "share" / "ptoas" / "TileOps").resolve(), - isolated_env=False, - ) - - -def _bootstrap_python_path(wrapper: Path) -> None: +def _bootstrap_python_path(wrapper: Path) -> Path: if _is_build_tree_wrapper(wrapper): - build_root = _build_tree_root(wrapper) - if build_root is not None: - root = build_root / "python" - _require_python_root(root, context="build-tree") - root_text = str(root) - if root_text not in sys.path: - sys.path.insert(0, root_text) - return - raise SystemExit("unable to locate the build-tree layout for ptoas") - - install_root = _install_tree_root(wrapper) - if install_root is not None: - _require_python_root(install_root, context="install-tree") - root_text = str(install_root) - if root_text not in sys.path: - sys.path.insert(0, root_text) - return - raise SystemExit("unable to locate the ptoas Python package root for the build/install-tree wrapper") + if len(wrapper.parents) < 3: + raise SystemExit("unable to locate the build-tree root for ptoas") + python_root = _require_python_root( + wrapper.parents[2] / "python", context="build-tree" + ) + else: + if len(wrapper.parents) < 2: + raise SystemExit("unable to locate the install-tree root for ptoas") + python_root = _require_python_root( + wrapper.parents[1], context="install-tree" + ) + + python_root_text = str(python_root) + if python_root_text not in sys.path: + sys.path.insert(0, python_root_text) + return python_root def main() -> None: wrapper = _resolve_wrapper_path() _bootstrap_python_path(wrapper) - from ptoas import _runtime_entry + from ptoas import _cli - if _is_build_tree_wrapper(wrapper): - layout = _resolve_build_tree_layout(wrapper) - else: - layout = _resolve_install_tree_layout(wrapper) - raise SystemExit(_runtime_entry.launch(layout, sys.argv[1:])) + raise SystemExit(_cli.launch(sys.argv[1:], wrapper=wrapper)) if __name__ == "__main__": From 2d549d74e54f41b08dd5baafeecd57e5cd98cbe5 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Wed, 22 Jul 2026 17:57:45 +0800 Subject: [PATCH 02/19] Remove runtime path bootstrap fallbacks --- docs/designs/ptoas-python-launcher-layout.md | 26 +++- ptodsl/README.md | 18 ++- ptodsl/ptoas/_cli.py | 17 -- ptodsl/ptodsl/_bootstrap.py | 145 ------------------ ptodsl/ptodsl/_builtin_vector.py | 1 - ptodsl/ptodsl/_context.py | 30 ++++ ptodsl/ptodsl/_control_flow.py | 1 - ptodsl/ptodsl/_ops.py | 1 - ptodsl/ptodsl/_runtime/codegen.py | 2 +- ptodsl/ptodsl/_runtime/toolchain.py | 26 +--- ptodsl/ptodsl/_source_loader.py | 2 +- ptodsl/ptodsl/_surface_types.py | 2 - ptodsl/ptodsl/_tracing/runtime.py | 2 +- ptodsl/ptodsl/_types.py | 2 - ptodsl/ptodsl/scalar.py | 1 - ptodsl/ptodsl/tilelib/_render_runtime.py | 2 +- ptodsl/tests/test_ast_rewrite_example_ir.py | 2 +- ptodsl/tests/test_bootstrap_runtime_env.py | 92 ----------- ptodsl/tests/test_context.py | 23 +++ ptodsl/tests/test_docs_as_test.py | 2 +- .../test_flash_attention_demo_compile.py | 2 +- ptodsl/tests/test_jit_compile.py | 2 +- ptodsl/tests/test_ptoas_cli.py | 6 +- ptodsl/tests/test_ptoas_frontend_verify.py | 2 +- ptodsl/tests/test_runtime_toolchain.py | 36 +++-- ptodsl/tests/test_tileop.py | 2 +- ptodsl/tests/test_vector_cube_ops.py | 2 +- tools/ptoas/ptoas_wrapper.py | 11 +- 28 files changed, 124 insertions(+), 336 deletions(-) delete mode 100644 ptodsl/ptodsl/_bootstrap.py create mode 100644 ptodsl/ptodsl/_context.py delete mode 100644 ptodsl/tests/test_bootstrap_runtime_env.py create mode 100644 ptodsl/tests/test_context.py diff --git a/docs/designs/ptoas-python-launcher-layout.md b/docs/designs/ptoas-python-launcher-layout.md index 382cf1cd4e..171b5b7187 100644 --- a/docs/designs/ptoas-python-launcher-layout.md +++ b/docs/designs/ptoas-python-launcher-layout.md @@ -20,10 +20,9 @@ The wheel, build-tree, and install-tree launchers use the standard Python console-script and native-extension model: ```text -console script or CMake tree wrapper - -> ptoas._cli.main() - -> import ptoas._native - -> ptoas._native.main(argv) +wheel console script -> ptoas._cli.main() +CMake tree wrapper -> add its own Python root -> ptoas._cli.launch() +both -> import ptoas._native -> ptoas._native.main(argv) ``` `ptoas._native` is built with `pybind11_add_module`. CMake and Python therefore @@ -93,6 +92,11 @@ The install-tree wrapper resolves only files under the same prefix: The install-tree wrapper only adds `` to `sys.path`, then delegates to the same `ptoas._cli` module used by wheels. +Both tree wrappers are CMake packaging adapters, not general runtime discovery +helpers. Each wrapper adds exactly the Python root belonging to its own tree; +it never scans repositories, neighboring build directories, or environment +variables for another installation. + ## Standalone Archive Layout Standalone compiler archives contain the installed Python wrapper and package: @@ -111,3 +115,17 @@ extension ABI. `bin/ptoas` adds the archive root to `sys.path`, then uses the same `ptoas._cli -> ptoas._native` path as the install tree. Linux archives set the extension runtime path to `$ORIGIN/../lib`; macOS archives rewrite the extension's install names relative to its package directory. + +## PTODSL and TileLib Runtime + +PTODSL imports MLIR and the PTO dialect through normal Python package +resolution. Wheel and editable installs provide those packages through their +declared installation layout. CTest and direct developer-tree runs must set an +explicit matching `PYTHONPATH`; PTODSL does not guess repository, LLVM build, +or PTOAS install paths at import time. + +TileOp expansion remains a lazy, separate daemon process. The PTOAS CLI passes +the packaged PTODSL root and the active Python executable to the native driver, +which starts the daemon only when expansion is required. Keeping the daemon out +of the compiler process also prevents independently packaged MLIR/LLVM Python +bindings from registering runtime state in the native PTOAS process. diff --git a/ptodsl/README.md b/ptodsl/README.md index db05638333..7a5ecaf333 100644 --- a/ptodsl/README.md +++ b/ptodsl/README.md @@ -18,7 +18,7 @@ ptodsl/ │ ├── __init__.py # exports: pto, scalar │ ├── pto.py # main PTO DSL namespace │ ├── scalar.py # top-level scalar.* helper namespace -│ ├── _bootstrap.py # MLIR path setup + context factory +│ ├── _context.py # MLIR context factory │ ├── _types.py # lazy dtype descriptors and type constructors │ ├── _ops.py # PTO operation wrappers │ ├── _control_flow.py # for_, if_, yield_ context managers @@ -62,7 +62,11 @@ python3 -c "import ptodsl; from ptodsl import pto, scalar; print(ptodsl.__file__ Not supported: - `cd ptodsl && pip install -e .` -- repo-walk / `PYTHONPATH` / `sys.path` repair just to locate the `ptodsl` package +- runtime repository walks or `sys.path` repair to locate MLIR/PTO bindings + +Direct CTest/developer-tree execution must provide the matching MLIR and PTO +Python roots explicitly through the test environment or `PYTHONPATH`; PTODSL +does not search nearby build and install directories at import time. Artifact boundary: @@ -89,11 +93,11 @@ ptoas --pto-arch=a5 --pto-backend=vpto --emit-vpto \ input.pto -o - ``` -The source-tree build bakes in `$PTOAS_REPO_ROOT/ptodsl` as the package root. -The `PTODSL_PYTHON_ROOT` environment variable from `scripts/ptoas_env.sh` -overrides that default. Use `--ptodsl-pkg-path=/path/to/package/root` for an -explicit command-line override. PTODSL daemon failures are reported as errors -and never fall back to the TileLang implementation. Use +Wheel and CMake-tree launchers pass the Python root containing their own +installed or staged `ptodsl` package to the native driver. Use +`--ptodsl-pkg-path=/path/to/package/root` for an explicit command-line +override. PTODSL daemon failures are reported as errors and never fall back to +the TileLang implementation. Use `--tile-lib-backend=tilelang` only when explicitly comparing against the legacy TileLangDSL template library. diff --git a/ptodsl/ptoas/_cli.py b/ptodsl/ptoas/_cli.py index dbc2ce2468..7cb3132679 100644 --- a/ptodsl/ptoas/_cli.py +++ b/ptodsl/ptoas/_cli.py @@ -11,7 +11,6 @@ from __future__ import annotations import os -import shutil import sys from pathlib import Path from typing import Sequence @@ -23,10 +22,6 @@ def _resolve_wrapper_path(argv0: str | None = None) -> Path: if wrapper.exists(): return wrapper.resolve() - found = shutil.which(wrapper.name or "ptoas") - if found: - return Path(found).resolve() - raise SystemExit(f"unable to locate the active ptoas entry point: {candidate}") @@ -61,16 +56,6 @@ def _has_cli_option(arguments: Sequence[str], option: str) -> bool: ) -def _prepend_path(name: str, value: Path) -> None: - current = os.environ.get(name, "") - parts = [part for part in current.split(os.pathsep) if part] - rendered = str(value) - if rendered in parts: - parts.remove(rendered) - parts.insert(0, rendered) - os.environ[name] = os.pathsep.join(parts) - - def launch(user_args: Sequence[str], *, wrapper: Path | None = None) -> int: native_module = _load_native_module() python_root, tileops_dir = _resolve_runtime_paths(native_module) @@ -78,8 +63,6 @@ def launch(user_args: Sequence[str], *, wrapper: Path | None = None) -> int: os.environ["PTOAS_BIN"] = str(wrapper) os.environ["PTOAS_PYTHON_EXE"] = sys.executable - _prepend_path("PATH", wrapper.parent) - argv = [str(wrapper)] if not _has_cli_option(user_args, "--tilelang-path"): argv.extend(["--tilelang-path", str(tileops_dir)]) diff --git a/ptodsl/ptodsl/_bootstrap.py b/ptodsl/ptodsl/_bootstrap.py deleted file mode 100644 index 86d8954d48..0000000000 --- a/ptodsl/ptodsl/_bootstrap.py +++ /dev/null @@ -1,145 +0,0 @@ -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. -""" -MLIR path bootstrap and context factory. - -Discovers local LLVM MLIR Python bindings plus PTO Python dialect artifacts so -that ``ptodsl`` can import ``mlir`` / ``mlir.dialects.pto`` directly from a -developer workspace without requiring the caller to pre-seed ``PYTHONPATH``. -When the current interpreter already has a complete installed MLIR/PTO stack, -leave ``sys.path`` untouched so wheel installs do not accidentally mix in a -developer checkout from environment variables or nearby directories. -""" - -import importlib.util -import os -import sys -from pathlib import Path - - -def _path_has(path: Path, relative: str) -> bool: - try: - return (path / relative).exists() - except OSError: - return False - - -def _pythonpath_already_provides_mlir_and_pto() -> bool: - """Return true when the caller has already configured compatible MLIR/PTO roots. - - Lit preserves ``PYTHONPATH`` but not the convenience environment variables - used by ``ptoas_env.sh``. In that case we should not prepend repository - default fallbacks like ``build/python`` / ``install`` because they may belong - to an older build tree and can mix Python/native MLIR bindings. - """ - has_mlir_core = False - has_pto_dialect = False - for entry in sys.path: - if not entry: - continue - path = Path(entry) - has_mlir_core = has_mlir_core or _path_has(path, "mlir/ir.py") - has_pto_dialect = has_pto_dialect or _path_has( - path, "mlir/dialects/pto.py" - ) - if has_mlir_core and has_pto_dialect: - return True - return False - - -def _candidate_python_roots() -> list[Path]: - here = Path(__file__).resolve() - repo_root = here.parents[2] - owner_root = repo_root.parent - github_root = owner_root.parent - env_roots = [] - has_explicit_pto_root = False - for env_name in ( - "MLIR_PYTHON_ROOT", - "PTO_PYTHON_BUILD_ROOT", - "PTO_PYTHON_ROOT", - "PTO_INSTALL_DIR", - ): - raw = os.environ.get(env_name) - if raw: - env_roots.append(Path(raw)) - if env_name != "MLIR_PYTHON_ROOT": - has_explicit_pto_root = True - - if not env_roots and _pythonpath_already_provides_mlir_and_pto(): - return [] - - fallback_roots = [ - github_root / "llvm" / "llvm-project" / "build" / "tools" / "mlir" / "python_packages" / "mlir_core", - github_root / "llvm" / "llvm-project" / "install" / "python_packages" / "mlir_core", - github_root / "llvm" / "llvm-project" / "build-shared" / "tools" / "mlir" / "python_packages" / "mlir_core", - ] - if not has_explicit_pto_root: - fallback_roots = [ - repo_root / "build" / "python", - repo_root / "install", - *fallback_roots, - ] - - return [ - *env_roots, - *fallback_roots, - ] - - -def _bootstrap_python_paths() -> None: - ordered_roots: list[str] = [] - seen = set() - for root in _candidate_python_roots(): - if not root or not root.is_dir(): - continue - if not (root / "mlir").exists(): - continue - root_text = str(root) - if root_text in seen: - continue - ordered_roots.append(root_text) - seen.add(root_text) - for root_text in reversed(ordered_roots): - if root_text in sys.path: - sys.path.remove(root_text) - sys.path.insert(0, root_text) - - -def _can_import_active_python_mlir() -> bool: - required_modules = ("mlir.ir", "mlir.dialects.pto") - for module_name in required_modules: - try: - if importlib.util.find_spec(module_name) is None: - return False - except (ImportError, ValueError, ModuleNotFoundError): - return False - return True - - -if not _can_import_active_python_mlir(): - _bootstrap_python_paths() - -from mlir.dialects import pto as _pto_dialect # noqa: E402 -try: - from mlir.dialects import llvm as _llvm_dialect # noqa: E402 -except Exception: # pragma: no cover - depends on the installed MLIR package. - _llvm_dialect = None -from mlir.ir import Context, Location # noqa: E402 - - -def make_context() -> Context: - """Create a fresh MLIR Context with the PTO dialect loaded.""" - ctx = Context() - _pto_dialect.register_dialect(ctx, load=True) - if _llvm_dialect is not None and hasattr(_llvm_dialect, "register_dialect"): - _llvm_dialect.register_dialect(ctx, load=True) - return ctx - - -__all__ = ["make_context"] diff --git a/ptodsl/ptodsl/_builtin_vector.py b/ptodsl/ptodsl/_builtin_vector.py index 6daf049a8d..544b66470b 100644 --- a/ptodsl/ptodsl/_builtin_vector.py +++ b/ptodsl/ptodsl/_builtin_vector.py @@ -7,7 +7,6 @@ # See LICENSE in the root of the software repository for the full text of the License. """Builtin MLIR vector helpers for PTODSL scalar-contiguous access.""" -from ._bootstrap import make_context # ensure MLIR is on sys.path # noqa: F401 from ._scalar_coercion import coerce_scalar_to_type from ._surface_values import VecValue, unwrap_surface_value from ._types import _resolve, _validate_vec_size, vec_type diff --git a/ptodsl/ptodsl/_context.py b/ptodsl/ptodsl/_context.py new file mode 100644 index 0000000000..efdc47af59 --- /dev/null +++ b/ptodsl/ptodsl/_context.py @@ -0,0 +1,30 @@ +# Copyright (c) 2026 Huawei Technologies Co., Ltd. +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of +# CANN Open Software License Agreement Version 2.0 (the "License"). +# Please refer to the License for details. You may not use this file except in compliance with the License. +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE in the root of the software repository for the full text of the License. + +"""MLIR context construction for an installed or explicitly configured PTODSL.""" + +from mlir.dialects import pto as _pto_dialect + +try: + from mlir.dialects import llvm as _llvm_dialect +except Exception: # pragma: no cover - depends on the installed MLIR package. + _llvm_dialect = None + +from mlir.ir import Context + + +def make_context() -> Context: + """Create a fresh MLIR context with the PTO dialect loaded.""" + ctx = Context() + _pto_dialect.register_dialect(ctx, load=True) + if _llvm_dialect is not None and hasattr(_llvm_dialect, "register_dialect"): + _llvm_dialect.register_dialect(ctx, load=True) + return ctx + + +__all__ = ["make_context"] diff --git a/ptodsl/ptodsl/_control_flow.py b/ptodsl/ptodsl/_control_flow.py index c71f1f24a0..77b2c9bdb1 100644 --- a/ptodsl/ptodsl/_control_flow.py +++ b/ptodsl/ptodsl/_control_flow.py @@ -21,7 +21,6 @@ ``const_expr(value)`` – trace-time ``if`` escape hatch for AST rewrite """ -from ._bootstrap import make_context # noqa: F401 from ._runtime_index_ops import coerce_runtime_index from ._scalar_coercion import coerce_scalar_to_type from ._surface_types import const_expr diff --git a/ptodsl/ptodsl/_ops.py b/ptodsl/ptodsl/_ops.py index c557c0c664..20a0b5af7f 100644 --- a/ptodsl/ptodsl/_ops.py +++ b/ptodsl/ptodsl/_ops.py @@ -24,7 +24,6 @@ from functools import wraps -from ._bootstrap import make_context # noqa: F401 – ensure MLIR on sys.path from ._diagnostics import ( explicit_mode_required_with_context_error, make_tensor_view_invalid_layout_error, diff --git a/ptodsl/ptodsl/_runtime/codegen.py b/ptodsl/ptodsl/_runtime/codegen.py index ba93106c25..768a11155b 100644 --- a/ptodsl/ptodsl/_runtime/codegen.py +++ b/ptodsl/ptodsl/_runtime/codegen.py @@ -9,7 +9,7 @@ from __future__ import annotations -from .._bootstrap import make_context +from .._context import make_context from mlir.ir import BF16Type, F16Type, F32Type, IndexType, IntegerType from .._kernel_signature import DeviceParameterSpec, RuntimeScalarParameterSpec diff --git a/ptodsl/ptodsl/_runtime/toolchain.py b/ptodsl/ptodsl/_runtime/toolchain.py index b41ef53a54..5e774a14de 100644 --- a/ptodsl/ptodsl/_runtime/toolchain.py +++ b/ptodsl/ptodsl/_runtime/toolchain.py @@ -27,36 +27,12 @@ def resolve_ptoas_binary() -> Path: f"PTOAS_BIN is set but does not resolve to an existing executable: {env_override}" ) - for var in ("PTO_BUILD_DIR", "PTO_INSTALL_DIR"): - if var in os.environ: - cand = Path(os.environ[var]) / "tools" / "ptoas" / "ptoas" - if cand.is_file(): - return cand - cand2 = Path(os.environ[var]) / "bin" / "ptoas" - if cand2.is_file(): - return cand2 - - repo_root = Path(__file__).resolve().parents[4] - candidates = [ - repo_root / "build" / "tools" / "ptoas" / "ptoas", - repo_root / "install" / "bin" / "ptoas", - ] - for candidate in candidates: - if candidate.is_file(): - return candidate - - for start in [Path.cwd()] + list(Path.cwd().parents): - for pattern in [start / "build" / "tools" / "ptoas" / "ptoas", - start / "install" / "bin" / "ptoas"]: - if pattern.is_file(): - return pattern - from_path = shutil.which("ptoas") if from_path: return Path(from_path) raise FileNotFoundError( - "unable to locate ptoas; build ptoas or add it to PATH after sourcing scripts/ptoas_env.sh" + "unable to locate ptoas; install it, add it to PATH, or set PTOAS_BIN" ) diff --git a/ptodsl/ptodsl/_source_loader.py b/ptodsl/ptodsl/_source_loader.py index b936937ddf..f4bac6f730 100644 --- a/ptodsl/ptodsl/_source_loader.py +++ b/ptodsl/ptodsl/_source_loader.py @@ -13,7 +13,7 @@ from dataclasses import dataclass from pathlib import Path -from ._bootstrap import make_context +from ._context import make_context from ._diagnostics import ( jit_source_abi_error, jit_source_entry_error, diff --git a/ptodsl/ptodsl/_surface_types.py b/ptodsl/ptodsl/_surface_types.py index 7a79fcded1..9ec4d95142 100644 --- a/ptodsl/ptodsl/_surface_types.py +++ b/ptodsl/ptodsl/_surface_types.py @@ -9,8 +9,6 @@ from enum import Enum -from ._bootstrap import make_context # noqa: F401 - from mlir.dialects import pto as _pto diff --git a/ptodsl/ptodsl/_tracing/runtime.py b/ptodsl/ptodsl/_tracing/runtime.py index e876c25f05..4a22c6b462 100644 --- a/ptodsl/ptodsl/_tracing/runtime.py +++ b/ptodsl/ptodsl/_tracing/runtime.py @@ -13,7 +13,7 @@ from .module_builder import create_kernel_module from .session import TraceSession from .._diagnostics import kernel_module_return_value_error -from .._bootstrap import make_context +from .._context import make_context from .._types import _resolve from mlir.dialects import func diff --git a/ptodsl/ptodsl/_types.py b/ptodsl/ptodsl/_types.py index bbfd8141f8..a89e887bf7 100644 --- a/ptodsl/ptodsl/_types.py +++ b/ptodsl/ptodsl/_types.py @@ -19,8 +19,6 @@ def softmax(arg0: pto.ptr(pto.float32, "GM"), ...): the actual type is materialised later by the ``@pto.jit`` decorator. """ -from ._bootstrap import make_context # ensure MLIR is on sys.path - from mlir.dialects import pto as _pto from mlir.dialects import arith from mlir.dialects.builtin import UnrealizedConversionCastOp diff --git a/ptodsl/ptodsl/scalar.py b/ptodsl/ptodsl/scalar.py index 10b2d3f58e..3e18343b8e 100644 --- a/ptodsl/ptodsl/scalar.py +++ b/ptodsl/ptodsl/scalar.py @@ -15,7 +15,6 @@ address views such as `tile[row, col]` and `tile.as_ptr() + offset`. """ -from ._bootstrap import make_context # ensure MLIR is on sys.path # noqa: F401 from ._scalar_coercion import coerce_scalar_to_type from ._scalar_adaptation import classify_runtime_scalar_type from ._runtime_scalar_ops import ( diff --git a/ptodsl/ptodsl/tilelib/_render_runtime.py b/ptodsl/ptodsl/tilelib/_render_runtime.py index fc9bd8aa8e..b87dafe8ae 100644 --- a/ptodsl/ptodsl/tilelib/_render_runtime.py +++ b/ptodsl/ptodsl/tilelib/_render_runtime.py @@ -28,7 +28,7 @@ from .metadata import ScalarSpec, TileSpec, VectorSpec, ViewSpec, scalar_descriptor from .._ast_rewrite import rewrite_jit_function -from .._bootstrap import make_context +from .._context import make_context from .._surface_types import Tile from .._surface_values import PartitionTensorViewValue, TensorViewValue, TileValue from .._tracing import KernelModuleSpec, ModuleStyle, TracingRuntime diff --git a/ptodsl/tests/test_ast_rewrite_example_ir.py b/ptodsl/tests/test_ast_rewrite_example_ir.py index e30a094eaf..bc6d6242cc 100644 --- a/ptodsl/tests/test_ast_rewrite_example_ir.py +++ b/ptodsl/tests/test_ast_rewrite_example_ir.py @@ -14,7 +14,7 @@ REPO_ROOT = Path(__file__).resolve().parents[2] from ptodsl import pto -from ptodsl._bootstrap import make_context +from ptodsl._context import make_context from mlir.ir import Module diff --git a/ptodsl/tests/test_bootstrap_runtime_env.py b/ptodsl/tests/test_bootstrap_runtime_env.py deleted file mode 100644 index ffcf1f9eb2..0000000000 --- a/ptodsl/tests/test_bootstrap_runtime_env.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import importlib.util -import sys -import types -import unittest -from pathlib import Path -from unittest import mock - - -class BootstrapRuntimeEnvTests(unittest.TestCase): - def test_bootstrap_keeps_installed_mlir_environment_unchanged(self): - repo_root = Path(__file__).resolve().parents[2] - bootstrap_path = repo_root / "ptodsl" / "ptodsl" / "_bootstrap.py" - module_name = "_test_ptodsl_bootstrap_runtime_env" - spec = importlib.util.spec_from_file_location(module_name, bootstrap_path) - self.assertIsNotNone(spec) - self.assertIsNotNone(spec.loader) - - mlir_module = types.ModuleType("mlir") - mlir_module.__path__ = [] - mlir_dialects_module = types.ModuleType("mlir.dialects") - mlir_dialects_module.__path__ = [] - mlir_pto_module = types.ModuleType("mlir.dialects.pto") - mlir_llvm_module = types.ModuleType("mlir.dialects.llvm") - mlir_ir_module = types.ModuleType("mlir.ir") - - class FakeContext: - pass - - class FakeLocation: - pass - - def register_pto_dialect(ctx, load=False): - ctx.pto_loaded = load - - def register_llvm_dialect(ctx, load=False): - ctx.llvm_loaded = load - - mlir_ir_module.Context = FakeContext - mlir_ir_module.Location = FakeLocation - mlir_pto_module.register_dialect = register_pto_dialect - mlir_llvm_module.register_dialect = register_llvm_dialect - mlir_dialects_module.pto = mlir_pto_module - mlir_dialects_module.llvm = mlir_llvm_module - mlir_module.dialects = mlir_dialects_module - mlir_module.ir = mlir_ir_module - - fake_sys_modules = { - "mlir": mlir_module, - "mlir.dialects": mlir_dialects_module, - "mlir.dialects.pto": mlir_pto_module, - "mlir.dialects.llvm": mlir_llvm_module, - "mlir.ir": mlir_ir_module, - } - - required_specs = { - "mlir.ir": object(), - "mlir.dialects.pto": object(), - } - original_find_spec = importlib.util.find_spec - original_sys_path = list(sys.path) - - def fake_find_spec(name, package=None): - if name in required_specs: - return required_specs[name] - return original_find_spec(name, package) - - with mock.patch.object(sys, "path", list(original_sys_path)), mock.patch.dict( - sys.modules, fake_sys_modules, clear=False - ), mock.patch("importlib.util.find_spec", side_effect=fake_find_spec): - module = importlib.util.module_from_spec(spec) - sys.modules.pop(module_name, None) - try: - spec.loader.exec_module(module) - self.assertEqual(sys.path, original_sys_path) - ctx = module.make_context() - self.assertTrue(getattr(ctx, "pto_loaded", False)) - self.assertTrue(getattr(ctx, "llvm_loaded", False)) - finally: - sys.modules.pop(module_name, None) - - -if __name__ == "__main__": - unittest.main() diff --git a/ptodsl/tests/test_context.py b/ptodsl/tests/test_context.py new file mode 100644 index 0000000000..b7d9b71800 --- /dev/null +++ b/ptodsl/tests/test_context.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# Copyright (c) 2026 Huawei Technologies Co., Ltd. +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of +# CANN Open Software License Agreement Version 2.0 (the "License"). +# Please refer to the License for details. You may not use this file except in compliance with the License. +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE in the root of the software repository for the full text of the License. + +import unittest + +from ptodsl._context import make_context + + +class ContextTests(unittest.TestCase): + def test_make_context_loads_pto_dialect(self): + context = make_context() + + self.assertIsNotNone(context) + + +if __name__ == "__main__": + unittest.main() diff --git a/ptodsl/tests/test_docs_as_test.py b/ptodsl/tests/test_docs_as_test.py index dccd1e5746..7e03b8debe 100644 --- a/ptodsl/tests/test_docs_as_test.py +++ b/ptodsl/tests/test_docs_as_test.py @@ -23,7 +23,7 @@ REPO_ROOT = Path(__file__).resolve().parents[2] USER_GUIDE_ROOT = REPO_ROOT / "ptodsl" / "docs" / "user_guide" from ptodsl import pto, scalar -from ptodsl._bootstrap import make_context +from ptodsl._context import make_context from ptodsl._runtime.launch import LaunchHandle, _marshal_launch_args from ptodsl._runtime.toolchain import resolve_ptoas_binary from mlir.ir import Module diff --git a/ptodsl/tests/test_flash_attention_demo_compile.py b/ptodsl/tests/test_flash_attention_demo_compile.py index ef4d5ee234..00bb6eadf1 100644 --- a/ptodsl/tests/test_flash_attention_demo_compile.py +++ b/ptodsl/tests/test_flash_attention_demo_compile.py @@ -11,7 +11,7 @@ from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[2] -from ptodsl._bootstrap import make_context +from ptodsl._context import make_context from mlir.ir import Module diff --git a/ptodsl/tests/test_jit_compile.py b/ptodsl/tests/test_jit_compile.py index 00252d3d46..32987848a0 100644 --- a/ptodsl/tests/test_jit_compile.py +++ b/ptodsl/tests/test_jit_compile.py @@ -22,7 +22,7 @@ from ptodsl import _types as pto_types import ptodsl._vmi_namespace as vmi_namespace from ptodsl._ast_rewrite import PTODSLAstRewriteError -from ptodsl._bootstrap import make_context +from ptodsl._context import make_context from ptodsl._kernel_signature import DeviceParameterSpec, HelperMarkerParameterSpec, RuntimeScalarParameterSpec from ptodsl._tracing.runtime import SignatureTracingRuntime from ptodsl._runtime import native_build as native_build_runtime diff --git a/ptodsl/tests/test_ptoas_cli.py b/ptodsl/tests/test_ptoas_cli.py index 4e4f9dfa50..9afd21e42c 100644 --- a/ptodsl/tests/test_ptoas_cli.py +++ b/ptodsl/tests/test_ptoas_cli.py @@ -7,7 +7,6 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -import os import tempfile import unittest from pathlib import Path @@ -59,10 +58,7 @@ def test_launch_uses_standard_native_module_and_packaged_resources(self): ) self.assertEqual(environment["PTOAS_BIN"], str(wrapper.resolve())) self.assertEqual(environment["PTOAS_PYTHON_EXE"], _cli.sys.executable) - self.assertEqual( - environment["PATH"], - str(wrapper.parent.resolve()) + os.pathsep + "/usr/bin", - ) + self.assertEqual(environment["PATH"], "/usr/bin") def test_explicit_resource_options_are_not_overridden(self): with tempfile.TemporaryDirectory() as temp_dir: diff --git a/ptodsl/tests/test_ptoas_frontend_verify.py b/ptodsl/tests/test_ptoas_frontend_verify.py index 083ef4daa5..b3e80a4687 100644 --- a/ptodsl/tests/test_ptoas_frontend_verify.py +++ b/ptodsl/tests/test_ptoas_frontend_verify.py @@ -17,7 +17,7 @@ REPO_ROOT = Path(__file__).resolve().parents[2] from ptodsl import pto from ptodsl import scalar -from ptodsl._bootstrap import make_context +from ptodsl._context import make_context from ptodsl._runtime.toolchain import resolve_ptoas_binary from mlir.ir import Module diff --git a/ptodsl/tests/test_runtime_toolchain.py b/ptodsl/tests/test_runtime_toolchain.py index bea4a0fcc3..f9c1797899 100644 --- a/ptodsl/tests/test_runtime_toolchain.py +++ b/ptodsl/tests/test_runtime_toolchain.py @@ -49,33 +49,41 @@ def test_native_launch_flags_use_target_arch(self): class ResolvePtoasBinaryTests(unittest.TestCase): - def test_env_override_wins_over_repo_default(self): + def test_env_override_wins_over_path(self): with tempfile.TemporaryDirectory() as temp_dir: temp_root = Path(temp_dir) env_ptoas = temp_root / "env-ptoas" env_ptoas.write_text("", encoding="utf-8") - repo_build_ptoas = temp_root / "build" / "tools" / "ptoas" / "ptoas" - repo_build_ptoas.parent.mkdir(parents=True, exist_ok=True) - repo_build_ptoas.write_text("", encoding="utf-8") + path_ptoas = temp_root / "path-ptoas" - fake_toolchain_file = ( - temp_root / "repo" / "ptodsl" / "ptodsl" / "_runtime" / "toolchain.py" - ) - fake_toolchain_file.parent.mkdir(parents=True, exist_ok=True) - fake_toolchain_file.write_text("", encoding="utf-8") - - with mock.patch.dict(os.environ, {"PTOAS_BIN": str(env_ptoas)}, clear=False), mock.patch.object( - toolchain, "__file__", str(fake_toolchain_file) - ): + with mock.patch.dict( + os.environ, {"PTOAS_BIN": str(env_ptoas)}, clear=True + ), mock.patch.object( + toolchain.shutil, "which", return_value=str(path_ptoas) + ) as which: resolved = toolchain.resolve_ptoas_binary() self.assertEqual(resolved, env_ptoas) + which.assert_not_called() + + def test_path_is_used_without_env_override(self): + with tempfile.TemporaryDirectory() as temp_dir: + path_ptoas = Path(temp_dir) / "path-ptoas" + with mock.patch.dict(os.environ, {}, clear=True), mock.patch.object( + toolchain.shutil, "which", return_value=str(path_ptoas) + ) as which: + resolved = toolchain.resolve_ptoas_binary() + + self.assertEqual(resolved, path_ptoas) + which.assert_called_once_with("ptoas") def test_invalid_env_override_raises(self): with tempfile.TemporaryDirectory() as temp_dir: missing = Path(temp_dir) / "missing-ptoas" - with mock.patch.dict(os.environ, {"PTOAS_BIN": str(missing)}, clear=False): + with mock.patch.dict( + os.environ, {"PTOAS_BIN": str(missing)}, clear=True + ), mock.patch.object(toolchain.shutil, "which", return_value=None): with self.assertRaises(FileNotFoundError): toolchain.resolve_ptoas_binary() diff --git a/ptodsl/tests/test_tileop.py b/ptodsl/tests/test_tileop.py index 0c55ddc671..6b30cb88fc 100644 --- a/ptodsl/tests/test_tileop.py +++ b/ptodsl/tests/test_tileop.py @@ -10,7 +10,7 @@ """Focused tracing coverage for the public ``@pto.tileop`` surface.""" from ptodsl import pto -from ptodsl._bootstrap import make_context +from ptodsl._context import make_context from mlir.ir import Module diff --git a/ptodsl/tests/test_vector_cube_ops.py b/ptodsl/tests/test_vector_cube_ops.py index 91d4011a88..9bca1f9167 100644 --- a/ptodsl/tests/test_vector_cube_ops.py +++ b/ptodsl/tests/test_vector_cube_ops.py @@ -13,7 +13,7 @@ import ptodsl._ops as _ops import ptodsl._pipe_namespace as _pipe_namespace -from ptodsl._bootstrap import make_context +from ptodsl._context import make_context from ptodsl import pto from mlir.ir import F32Type def _identity(value): diff --git a/tools/ptoas/ptoas_wrapper.py b/tools/ptoas/ptoas_wrapper.py index fb07afaf9b..07a8d423d7 100644 --- a/tools/ptoas/ptoas_wrapper.py +++ b/tools/ptoas/ptoas_wrapper.py @@ -11,7 +11,6 @@ from __future__ import annotations -import shutil import sys from pathlib import Path @@ -22,11 +21,7 @@ def _resolve_wrapper_path(argv0: str | None = None) -> Path: if wrapper.exists(): return wrapper.resolve() - found = shutil.which(wrapper.name or "ptoas") - if found: - return Path(found).resolve() - - raise SystemExit(f"unable to locate the installed ptoas wrapper: {candidate}") + raise SystemExit(f"unable to locate the ptoas tree wrapper: {candidate}") def _is_build_tree_wrapper(wrapper: Path) -> bool: @@ -43,7 +38,7 @@ def _require_python_root(python_root: Path, *, context: str) -> Path: ) -def _bootstrap_python_path(wrapper: Path) -> Path: +def _add_tree_python_root(wrapper: Path) -> Path: if _is_build_tree_wrapper(wrapper): if len(wrapper.parents) < 3: raise SystemExit("unable to locate the build-tree root for ptoas") @@ -65,7 +60,7 @@ def _bootstrap_python_path(wrapper: Path) -> Path: def main() -> None: wrapper = _resolve_wrapper_path() - _bootstrap_python_path(wrapper) + _add_tree_python_root(wrapper) from ptoas import _cli raise SystemExit(_cli.launch(sys.argv[1:], wrapper=wrapper)) From eb235fe9ac0e10d8978dfdff60005669e26d084b Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Thu, 23 Jul 2026 18:31:55 +0800 Subject: [PATCH 03/19] Harden Python wheel developer workflow --- .github/workflows/build_wheel.yml | 13 +++++ .github/workflows/build_wheel_mac.yml | 13 ++++- .github/workflows/ci.yml | 4 +- docker/test_ptoas_cli.sh | 27 +++------ test/python/test_docker_runtime_packaging.py | 26 ++++----- test/python/test_validate_wheel_payload.py | 60 +------------------- tools/ptoas/CMakeLists.txt | 6 ++ 7 files changed, 54 insertions(+), 95 deletions(-) diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index 02e776ac42..0a4505e789 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -230,6 +230,18 @@ jobs: --wheel-dir "${PTO_SOURCE_DIR}/build/wheel-dist" cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" + - name: Install built wheel for Python sample generation + run: | + export PATH="${PY_PATH}/bin:$PATH" + shopt -s nullglob + wheels=("$PTO_SOURCE_DIR"/build/wheel-dist/ptoas*.whl) + if [ "${#wheels[@]}" -ne 1 ]; then + echo "Expected exactly one wheel in $PTO_SOURCE_DIR/build/wheel-dist, found ${#wheels[@]}" >&2 + printf ' %s\n' "${wheels[@]}" >&2 + exit 1 + fi + python -m pip install --no-deps --force-reinstall "${wheels[0]}" + - name: Validate wheel payload and launcher contract if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | @@ -256,6 +268,7 @@ jobs: - name: Test ptoas CLI run: | export PATH="${PY_PATH}/bin:$PATH" + export PTOAS_BIN="${PTO_BUILD_DIR}/tools/ptoas/ptoas" bash $PTO_SOURCE_DIR/docker/test_ptoas_cli.sh - name: Upload wheel artifact diff --git a/.github/workflows/build_wheel_mac.yml b/.github/workflows/build_wheel_mac.yml index a473cc9c4c..b78213a34f 100644 --- a/.github/workflows/build_wheel_mac.yml +++ b/.github/workflows/build_wheel_mac.yml @@ -234,6 +234,17 @@ jobs: printf 'Built wheel file: %s\n' "$(basename "${built_wheels[0]}")" fi + - name: Install built wheel for Python sample generation + run: | + shopt -s nullglob + wheels=("$PTO_SOURCE_DIR"/build/wheel-dist/ptoas*.whl) + if [ "${#wheels[@]}" -ne 1 ]; then + echo "Expected exactly one wheel in $PTO_SOURCE_DIR/build/wheel-dist, found ${#wheels[@]}" >&2 + printf ' %s\n' "${wheels[@]}" >&2 + exit 1 + fi + python -m pip install --no-deps --force-reinstall "${wheels[0]}" + - name: Validate wheel payload and launcher contract if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | @@ -324,7 +335,7 @@ jobs: - name: Test ptoas CLI run: | - export DYLD_LIBRARY_PATH=$LLVM_BUILD_DIR/lib:$PTO_INSTALL_DIR/lib:${DYLD_LIBRARY_PATH} + export PTOAS_BIN="${PTO_BUILD_DIR}/tools/ptoas/ptoas" bash $PTO_SOURCE_DIR/docker/test_ptoas_cli.sh - name: Upload wheel artifact diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6a0cb90e87..7d2393c5e8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -262,7 +262,7 @@ jobs: -DCMAKE_CXX_COMPILER="${PTOAS_CMAKE_CXX_COMPILER}" \ -Werror=dev - - name: Create PTOAS test venv + - name: Create PTOAS developer environment shell: bash run: | set -euo pipefail @@ -298,7 +298,7 @@ jobs: exit 1 fi - "${PTOAS_VENV}/bin/pip" install --force-reinstall "${ptoas_wheels[0]}" + "${PTOAS_VENV}/bin/pip" install --no-deps --force-reinstall "${ptoas_wheels[0]}" PATH="${PTOAS_VENV}/bin:${PATH}" bash docker/test_wheel_imports.sh - name: Run PTODSL Python tests diff --git a/docker/test_ptoas_cli.sh b/docker/test_ptoas_cli.sh index 6902d679ae..8ce29e1b87 100755 --- a/docker/test_ptoas_cli.sh +++ b/docker/test_ptoas_cli.sh @@ -13,35 +13,22 @@ # # Required environment variables: # PTO_SOURCE_DIR - Path to PTO source directory -# PTO_BUILD_DIR - Path to PTO build directory -# LLVM_BUILD_DIR - Path to LLVM build directory -# PTO_INSTALL_DIR - Path to PTO install directory -# PTOAS_BIN - Path to the Python ptoas wrapper (optional) +# PTOAS_BIN - Exact ptoas entrypoint under test -set -e +set -euo pipefail # Validate required environment variables -for var in PTO_SOURCE_DIR PTO_BUILD_DIR LLVM_BUILD_DIR PTO_INSTALL_DIR; do - if [ -z "${!var}" ]; then +for var in PTO_SOURCE_DIR PTOAS_BIN; do + if [ -z "${!var:-}" ]; then echo "Error: $var environment variable is not set" >&2 exit 1 fi done -# Setup environment -export PATH="${PTO_BUILD_DIR}/tools/ptoas:${PATH}" -export LD_LIBRARY_PATH="${LLVM_BUILD_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH}" -export DYLD_LIBRARY_PATH="${LLVM_BUILD_DIR}/lib:${PTO_INSTALL_DIR}/lib:${DYLD_LIBRARY_PATH}" - -if [ -n "${PTOAS_BIN:-}" ]; then - if [ ! -x "${PTOAS_BIN}" ]; then - echo "Error: PTOAS_BIN is not executable: ${PTOAS_BIN}" >&2 - exit 1 - fi -else - PTOAS_BIN="$(command -v ptoas)" +if [ ! -x "${PTOAS_BIN}" ]; then + echo "Error: PTOAS_BIN is not executable: ${PTOAS_BIN}" >&2 + exit 1 fi - echo "Testing ptoas CLI..." echo "${PTOAS_BIN}" diff --git a/test/python/test_docker_runtime_packaging.py b/test/python/test_docker_runtime_packaging.py index a3b1768163..a56475ae74 100644 --- a/test/python/test_docker_runtime_packaging.py +++ b/test/python/test_docker_runtime_packaging.py @@ -16,8 +16,7 @@ COLLECT_DIST_SCRIPT = REPO_ROOT / "docker" / "collect_ptoas_dist.sh" COLLECT_DIST_MAC_SCRIPT = REPO_ROOT / "docker" / "collect_ptoas_dist_mac.sh" PTOAS_CMAKE = REPO_ROOT / "tools" / "ptoas" / "CMakeLists.txt" -BUILD_WHEEL_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "build_wheel.yml" -BUILD_WHEEL_MAC_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "build_wheel_mac.yml" +PTOAS_CLI_TEST = REPO_ROOT / "docker" / "test_ptoas_cli.sh" class DockerRuntimePackagingTests(unittest.TestCase): @@ -29,6 +28,8 @@ def test_runtime_uses_standard_python_extension_without_native_cli(self): cmake, ) self.assertIn('OUTPUT_NAME "_native"', cmake) + self.assertIn('BUILD_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}"', cmake) + self.assertIn('INSTALL_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}"', cmake) self.assertNotIn("add_executable(ptoas_native_cli", cmake) self.assertNotIn('OUTPUT_NAME "ptoas-native"', cmake) @@ -76,23 +77,22 @@ def test_macos_dist_packages_python_wrapper_and_native_extension(self): self.assertNotIn("ptoas-native", script) self.assertNotIn("ptoas.so", script) - def test_dist_archives_use_bin_entrypoint(self): - linux_workflow = BUILD_WHEEL_WORKFLOW.read_text(encoding="utf-8") - mac_workflow = BUILD_WHEEL_MAC_WORKFLOW.read_text(encoding="utf-8") - - self.assertIn('chmod +x "$GITHUB_WORKSPACE/ptoas-dist/bin/ptoas"', linux_workflow) - self.assertNotIn('chmod +x "$GITHUB_WORKSPACE/ptoas-dist/ptoas"', linux_workflow) - self.assertIn('chmod +x "$GITHUB_WORKSPACE/ptoas-dist/bin/ptoas"', mac_workflow) - self.assertNotIn('chmod +x "$GITHUB_WORKSPACE/ptoas-dist/ptoas"', mac_workflow) - self.assertIn('"$TEST_DIR/extracted/bin/ptoas" --version', mac_workflow) - self.assertNotIn('"$TEST_DIR/extracted/ptoas" --version', mac_workflow) - def test_wheel_import_smoke_imports_native_extension(self): script = (REPO_ROOT / "docker" / "test_wheel_imports.sh").read_text(encoding="utf-8") self.assertIn("from ptoas import _native", script) self.assertNotIn("POLLUTED_PTOAS_VERSION_OUTPUT", script) + def test_build_tree_cli_test_receives_explicit_test_environment(self): + script = PTOAS_CLI_TEST.read_text(encoding="utf-8") + + self.assertIn("for var in PTO_SOURCE_DIR PTOAS_BIN", script) + self.assertIn("python ./tmatmulk.py", script) + self.assertIn("python ./abs.py", script) + self.assertNotIn("PYTHON_BIN", script) + self.assertNotIn('command -v ptoas', script) + self.assertNotIn('export PATH="${PTO_BUILD_DIR}', script) + self.assertNotIn('export LD_LIBRARY_PATH="${LLVM_BUILD_DIR}', script) if __name__ == "__main__": unittest.main() diff --git a/test/python/test_validate_wheel_payload.py b/test/python/test_validate_wheel_payload.py index 318d1a6fde..5b99367026 100644 --- a/test/python/test_validate_wheel_payload.py +++ b/test/python/test_validate_wheel_payload.py @@ -17,11 +17,7 @@ REPO_ROOT = Path(__file__).resolve().parents[2] VALIDATOR = REPO_ROOT / "docker" / "validate_wheel_payload.py" -LINUX_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "build_wheel.yml" -MAC_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "build_wheel_mac.yml" WHEEL_IMPORTS = REPO_ROOT / "docker" / "test_wheel_imports.sh" -CI_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "ci.yml" -CI_SIM_WORKFLOW = REPO_ROOT / ".github" / "workflows" / "ci_sim.yml" class ValidateWheelPayloadTests(unittest.TestCase): @@ -165,59 +161,12 @@ def test_validator_accepts_vmi_distribution_name(self): self.assertEqual(result.returncode, 0, result.stderr) self.assertIn("validated wheel payload and launcher contract", result.stdout) - def test_workflows_and_shell_probe_reuse_shared_validator(self): - validator_call = 'python "$PTO_SOURCE_DIR/docker/validate_wheel_payload.py" "$PTO_SOURCE_DIR/build/wheel-dist"' - self.assertIn( - validator_call, - LINUX_WORKFLOW.read_text(encoding="utf-8"), - ) - self.assertIn( - validator_call, - MAC_WORKFLOW.read_text(encoding="utf-8"), - ) + def test_shell_probe_reuses_shared_validator(self): self.assertIn( '"${PYTHON_BIN}" "${REPO_ROOT}/docker/validate_wheel_payload.py" "${TEST_WHEEL}"', WHEEL_IMPORTS.read_text(encoding="utf-8"), ) - def test_release_workflows_separate_cli_and_wheel_versions(self): - linux_workflow = LINUX_WORKFLOW.read_text(encoding="utf-8") - mac_workflow = MAC_WORKFLOW.read_text(encoding="utf-8") - - self.assertIn("workflow_dispatch:", linux_workflow) - self.assertIn("release_kind:", linux_workflow) - self.assertIn('type: choice', linux_workflow) - self.assertIn('--mode release)', linux_workflow) - self.assertIn( - "if: github.event_name != 'release' || startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'ptoas-v')", - linux_workflow, - ) - self.assertIn( - "if: (github.event_name == 'release' && (startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'ptoas-v'))) || github.event_name == 'schedule'", - linux_workflow, - ) - self.assertIn('PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}"', linux_workflow) - self.assertIn('PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_CLI_VERSION}"', linux_workflow) - self.assertIn('PTOAS_WHEEL_SOURCE_DIR="${PTO_SOURCE_DIR}/packaging/ptoas-vmi"', linux_workflow) - self.assertIn('SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}"', linux_workflow) - - self.assertIn("workflow_dispatch:", mac_workflow) - self.assertIn("release_kind:", mac_workflow) - self.assertIn('type: choice', mac_workflow) - self.assertIn('--mode release)', mac_workflow) - self.assertIn( - "if: github.event_name != 'release' || startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'ptoas-v')", - mac_workflow, - ) - self.assertIn( - "if: (github.event_name == 'release' && (startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'ptoas-v'))) || github.event_name == 'schedule'", - mac_workflow, - ) - self.assertIn('PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}"', mac_workflow) - self.assertIn('PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_CLI_VERSION}"', mac_workflow) - self.assertIn('PTOAS_WHEEL_SOURCE_DIR="${PTO_SOURCE_DIR}/packaging/ptoas-vmi"', mac_workflow) - self.assertIn('SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}"', mac_workflow) - def test_wheel_imports_script_keeps_clean_env_ptoas_smoke(self): script = WHEEL_IMPORTS.read_text(encoding="utf-8") @@ -242,12 +191,5 @@ def test_wheel_imports_script_keeps_clean_env_ptoas_smoke(self): self.assertIn('grep -q "TileLib daemon started successfully" "${CLEAN_ENV_LOG}"', script) self.assertIn('grep -q "TileLib daemon stopped" "${CLEAN_ENV_LOG}"', script) - def test_ci_workflows_accept_generic_ptoas_wheel_glob(self): - self.assertIn("name 'ptoas*.whl'", CI_WORKFLOW.read_text(encoding="utf-8")) - ci_sim_text = CI_SIM_WORKFLOW.read_text(encoding="utf-8") - self.assertIn("name 'ptoas*.whl'", ci_sim_text) - self.assertNotIn("name 'ptoas-*.whl'", ci_sim_text) - - if __name__ == "__main__": unittest.main() diff --git a/tools/ptoas/CMakeLists.txt b/tools/ptoas/CMakeLists.txt index 0d4ede0c40..75db33c55a 100644 --- a/tools/ptoas/CMakeLists.txt +++ b/tools/ptoas/CMakeLists.txt @@ -90,6 +90,12 @@ target_link_libraries(ptoas_runtime PRIVATE ptoas_runtime_objects) set_target_properties(ptoas_runtime PROPERTIES OUTPUT_NAME "_native" LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/python-module" + # Keep the external LLVM/MLIR build discoverable for build-tree and + # editable Python installs. Release wheels are subsequently repaired by + # auditwheel, which replaces this machine-local path with wheel-local + # dependencies and a relative RPATH. + BUILD_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}" + INSTALL_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}" ) set(PTOAS_BUILD_PYTHON_PACKAGE_DIR "${CMAKE_BINARY_DIR}/python/ptoas") From 1b74097c8b4c3fc70f30d13aac79a1c9c9e5f234 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Thu, 23 Jul 2026 19:33:10 +0800 Subject: [PATCH 04/19] Fix compiler archive Python selection --- .github/workflows/build_wheel.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index 0a4505e789..a670aba41d 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -281,6 +281,7 @@ jobs: - name: Collect ptoas binary and dependencies if: matrix.python == '3.11' run: | + export PATH="${PY_PATH}/bin:$PATH" bash $PTO_SOURCE_DIR/docker/collect_ptoas_dist.sh $GITHUB_WORKSPACE/ptoas-dist - name: Archive ptoas binary artifact From ca4b27ad29d9cb99a098e95a86ebc0941e44adc8 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Thu, 23 Jul 2026 19:37:49 +0800 Subject: [PATCH 05/19] Persist selected manylinux Python on PATH --- .github/workflows/build_wheel.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index a670aba41d..8f6be18831 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -67,6 +67,7 @@ jobs: esac echo "PY_VER=$PY_VER" >> $GITHUB_ENV echo "PY_PATH=/opt/python/$PY_VER" >> $GITHUB_ENV + echo "/opt/python/$PY_VER/bin" >> $GITHUB_PATH - name: Compute PTOAS CLI version run: | @@ -127,14 +128,12 @@ jobs: - name: Install Python dependencies run: | - export PATH="${PY_PATH}/bin:$PATH" # LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x # (see pybind11 static_assert on def_property + keep_alive). pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' auditwheel - name: Validate PEP 517 project metadata run: | - export PATH="${PY_PATH}/bin:$PATH" python -m scikit_build_core.build project-table (cd packaging/ptoas-vmi && python -m scikit_build_core.build project-table) @@ -187,7 +186,6 @@ jobs: - name: Build LLVM/MLIR if: steps.cache-llvm.outputs.cache-hit != 'true' run: | - export PATH="${PY_PATH}/bin:$PATH" cd $LLVM_SOURCE_DIR cmake -C "$PTO_SOURCE_DIR/cmake/LinuxHardeningCache.cmake" -G Ninja -S llvm -B $LLVM_BUILD_DIR \ -DLLVM_ENABLE_PROJECTS="mlir;clang" \ @@ -215,7 +213,6 @@ jobs: env: CMAKE_BUILD_PARALLEL_LEVEL: "2" run: | - export PATH="${PY_PATH}/bin:$PATH" if [ "${PTOAS_PYTHON_PACKAGE_NAME}" = "ptoas-vmi" ]; then PTOAS_WHEEL_SOURCE_DIR="${PTO_SOURCE_DIR}/packaging/ptoas-vmi" else @@ -232,7 +229,6 @@ jobs: - name: Install built wheel for Python sample generation run: | - export PATH="${PY_PATH}/bin:$PATH" shopt -s nullglob wheels=("$PTO_SOURCE_DIR"/build/wheel-dist/ptoas*.whl) if [ "${#wheels[@]}" -ne 1 ]; then @@ -245,13 +241,11 @@ jobs: - name: Validate wheel payload and launcher contract if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | - export PATH="${PY_PATH}/bin:$PATH" python "$PTO_SOURCE_DIR/docker/validate_wheel_payload.py" "$PTO_SOURCE_DIR/build/wheel-dist" - name: Repair wheel with auditwheel if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | - export PATH="${PY_PATH}/bin:$PATH" export PTO_WHEEL_DIST_DIR=$PTO_SOURCE_DIR/build/wheel-dist export PTO_WHEELHOUSE=$GITHUB_WORKSPACE/wheelhouse export LD_LIBRARY_PATH=$LLVM_BUILD_DIR/lib:$PTO_INSTALL_DIR/lib:$LD_LIBRARY_PATH @@ -261,13 +255,11 @@ jobs: - name: Test wheel installation if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | - export PATH="${PY_PATH}/bin:$PATH" pip install $GITHUB_WORKSPACE/wheelhouse/ptoas*.whl bash $PTO_SOURCE_DIR/docker/test_wheel_imports.sh - name: Test ptoas CLI run: | - export PATH="${PY_PATH}/bin:$PATH" export PTOAS_BIN="${PTO_BUILD_DIR}/tools/ptoas/ptoas" bash $PTO_SOURCE_DIR/docker/test_ptoas_cli.sh @@ -281,7 +273,6 @@ jobs: - name: Collect ptoas binary and dependencies if: matrix.python == '3.11' run: | - export PATH="${PY_PATH}/bin:$PATH" bash $PTO_SOURCE_DIR/docker/collect_ptoas_dist.sh $GITHUB_WORKSPACE/ptoas-dist - name: Archive ptoas binary artifact From f7590e73091013337647d0cdafa7eb3c98179dfb Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Thu, 23 Jul 2026 20:57:41 +0800 Subject: [PATCH 06/19] Make lit tests self-contained for MLIR Python --- test/lit/lit.cfg.py | 11 +++++++++++ test/lit/lit.site.cfg.py.in | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/test/lit/lit.cfg.py b/test/lit/lit.cfg.py index 6565d6b06c..1d3691d62d 100644 --- a/test/lit/lit.cfg.py +++ b/test/lit/lit.cfg.py @@ -51,6 +51,17 @@ 'ASCEND_HOME_PATH', 'ASCEND_OPP_PATH', 'ASCEND_AICPU_PATH', 'ASCEND_TOOLKIT_HOME', 'LD_LIBRARY_PATH', 'PYTHONPATH']) +# Keep build-tree lit tests self-contained. PTOAS contributes an overlay +# under the build tree (generated dialect Python plus the PTO extension), +# while the base ``mlir.ir`` package comes from the LLVM/MLIR build. MLIR's +# own lit setup wires these paths from its CMake-generated site configuration; +# do the same here instead of requiring developers to export PYTHONPATH. +if getattr(config, 'enable_bindings_python', False): + python_paths = [config.ptoas_python_dir] + if config.mlir_python_package_dir: + python_paths.append(config.mlir_python_package_dir) + llvm_config.with_environment('PYTHONPATH', python_paths, append_path=True) + llvm_config.use_default_substitutions() # excludes: A list of directories to exclude from the testsuite. The 'Inputs' diff --git a/test/lit/lit.site.cfg.py.in b/test/lit/lit.site.cfg.py.in index dd78286f55..7babeaa197 100644 --- a/test/lit/lit.site.cfg.py.in +++ b/test/lit/lit.site.cfg.py.in @@ -19,7 +19,10 @@ config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" config.mlir_obj_dir = "@MLIR_BINARY_DIR@" config.mlir_lib_dir = "@MLIR_LIB_DIR@" config.python_executable = "@Python3_EXECUTABLE@" -# config.enable_bindings_python = @MLIR_ENABLE_BINDINGS_PYTHON@ +config.enable_bindings_python = "@PTO_ENABLE_PYTHON_BINDING@" == "ON" +config.ptoas_python_dir = path(r"@CMAKE_BINARY_DIR@/python") +config.mlir_python_package_dir = lit_config.substitute( + path(r"@MLIR_PYTHON_PACKAGE_DIR@")) config.ptoir_src_root = "@CMAKE_SOURCE_DIR@" config.ptoir_obj_root = "@CMAKE_BINARY_DIR@" From 3fc76cea582c92e6557f4c7b175d3f3e9d5c83de Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Thu, 23 Jul 2026 22:21:34 +0800 Subject: [PATCH 07/19] Streamline editable developer builds --- .github/workflows/ci_sim.yml | 28 ++++++++++++-- lib/Bindings/Python/CMakeLists.txt | 32 ---------------- pyproject.toml | 5 ++- quick_install.sh | 59 ++++++++---------------------- 4 files changed, 42 insertions(+), 82 deletions(-) diff --git a/.github/workflows/ci_sim.yml b/.github/workflows/ci_sim.yml index 13b41f5236..06a3dfdf45 100644 --- a/.github/workflows/ci_sim.yml +++ b/.github/workflows/ci_sim.yml @@ -201,6 +201,24 @@ jobs: python3 -m pip install 'scikit-build-core>=0.12.2,<2' 'pybind11<3' nanobind numpy ml-dtypes fi + - name: Configure ccache + shell: bash + run: | + set -euo pipefail + if ! command -v ccache >/dev/null 2>&1; then + if command -v sudo >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1; then + sudo apt-get update + sudo apt-get install -y ccache + else + echo "ccache is unavailable; continuing without a compiler launcher" + exit 0 + fi + fi + + ccache --version + echo "CMAKE_C_COMPILER_LAUNCHER=ccache" >> "${GITHUB_ENV}" + echo "CMAKE_CXX_COMPILER_LAUNCHER=ccache" >> "${GITHUB_ENV}" + - name: Resolve LLVM directories shell: bash run: | @@ -324,8 +342,9 @@ jobs: export CC=gcc export CXX=g++ LLVM_BUILD_DIR="${LLVM_DIR}" \ - SKBUILD_BUILD_DIR="${GITHUB_WORKSPACE}/build" \ - python3 -m pip wheel . --no-build-isolation --no-deps --wheel-dir "${PTO_WHEELHOUSE}" + python3 -m pip wheel . --no-build-isolation --no-deps \ + --config-settings="build-dir=${GITHUB_WORKSPACE}/build" \ + --wheel-dir "${PTO_WHEELHOUSE}" cmake --install "${GITHUB_WORKSPACE}/build" --prefix "${PTO_INSTALL_DIR}" - name: Create PTOAS simulator venv @@ -795,8 +814,9 @@ jobs: export CC=gcc export CXX=g++ LLVM_BUILD_DIR="${PTO_DSL_ST_LLVM_DIR}" \ - SKBUILD_BUILD_DIR="${PTO_DSL_ST_BUILD_DIR}" \ - "${PTO_DSL_ST_PYTHON_BIN}" -m pip wheel . --no-build-isolation --no-deps --wheel-dir "${PTO_DSL_ST_WHEELHOUSE}" + "${PTO_DSL_ST_PYTHON_BIN}" -m pip wheel . --no-build-isolation --no-deps \ + --config-settings="build-dir=${PTO_DSL_ST_BUILD_DIR}" \ + --wheel-dir "${PTO_DSL_ST_WHEELHOUSE}" cmake --install "${PTO_DSL_ST_BUILD_DIR}" --prefix "${PTO_DSL_ST_INSTALL_DIR}" - name: Install PTODSL PTOAS wheel diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index 215f385a8e..06b3829b44 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -106,35 +106,3 @@ install(FILES DESTINATION mlir/dialects COMPONENT PTOAS_Python ) - -# Keep the MLIR build-tree Python package self-consistent as well. When users -# import `mlir.dialects.pto` directly from MLIR_PYTHON_PACKAGE_DIR, the wrapper -# modules must be updated alongside the native `_pto` extension during normal -# builds, not just during `cmake --install`. -add_custom_command(TARGET _pto POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory - "${MLIR_PYTHON_PACKAGE_DIR}/mlir/dialects" - COMMAND ${CMAKE_COMMAND} -E make_directory - "${MLIR_PYTHON_PACKAGE_DIR}/mlir/_mlir_libs" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${PTO_PY_SRC}" - "${MLIR_PYTHON_PACKAGE_DIR}/mlir/dialects/pto.py" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${CMAKE_CURRENT_BINARY_DIR}/_pto_ops_gen.py" - "${MLIR_PYTHON_PACKAGE_DIR}/mlir/dialects/_pto_ops_gen.py" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${MLIR_PYTHON_PACKAGE_DIR}/mlir/_mlir_libs/$" - VERBATIM -) - -add_custom_command(TARGET _pto POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory - "${CMAKE_BINARY_DIR}/python/mlir/_mlir_libs" - COMMAND ${CMAKE_COMMAND} -E make_directory - "${MLIR_PYTHON_PACKAGE_DIR}/mlir/_mlir_libs" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${MLIR_PYTHON_PACKAGE_DIR}/mlir/_mlir_libs/$" - VERBATIM -) diff --git a/pyproject.toml b/pyproject.toml index 100b364b39..31a339e328 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,8 +7,9 @@ # See LICENSE in the root of the software repository for the full text of the License. # Standard PEP 517 configuration for the `ptoas` distribution. Set -# LLVM_BUILD_DIR to an existing LLVM/MLIR build. SKBUILD_BUILD_DIR can be used -# when a persistent CMake build tree is required by tests or development tools. +# LLVM_BUILD_DIR to an existing LLVM/MLIR build. Pass +# `--config-settings=build-dir=` when tests or development tools require +# a persistent CMake build tree. [build-system] requires = ["scikit-build-core>=0.12.2,<2", "pybind11<3"] diff --git a/quick_install.sh b/quick_install.sh index ec72e2830e..78a05bbe24 100755 --- a/quick_install.sh +++ b/quick_install.sh @@ -7,60 +7,31 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -# For quick development, build and install ptoas and its python bindings -# on top of Docker image https://github.com/learning-chip/agent_docker_npu/pull/8 -# assume MLIR is already installed to save time +# Build and install PTOAS in editable mode against an existing LLVM/MLIR +# build. The persistent build directory can subsequently be used with Ninja, +# for example: ninja -C build check-pto. # # Optional env: # LLVM_BUILD_DIR - default: ${LLVM_SOURCE_DIR:-/llvm-workspace/llvm-project}/build-shared -# PTO_INSTALL_DIR - default: /install +# PTO_BUILD_DIR - default: /build +# PYTHON_BIN - default: python set -euo pipefail PTO_SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PTO_INSTALL_DIR="${PTO_INSTALL_DIR:-${PTO_SOURCE_DIR}/install}" - LLVM_SOURCE_DIR="${LLVM_SOURCE_DIR:-/llvm-workspace/llvm-project}" LLVM_BUILD_DIR="${LLVM_BUILD_DIR:-${LLVM_SOURCE_DIR}/build-shared}" +PTO_BUILD_DIR="${PTO_BUILD_DIR:-${PTO_SOURCE_DIR}/build}" +PYTHON_BIN="${PYTHON_BIN:-python}" -for d in "$LLVM_BUILD_DIR/lib/cmake/llvm" "$LLVM_BUILD_DIR/lib/cmake/mlir"; do - test -d "$d" || { echo "error: missing $d (set LLVM_BUILD_DIR?)" >&2; exit 1; } -done - -MLIR_PY_PKG="${LLVM_BUILD_DIR}/tools/mlir/python_packages/mlir_core" -test -d "$MLIR_PY_PKG" || { echo "error: MLIR python package dir missing: $MLIR_PY_PKG" >&2; exit 1; } - -PTOAS_VERSION="${PTOAS_VERSION:-$(python "${PTO_SOURCE_DIR}/.github/scripts/compute_ptoas_version.py" --cmake-file "${PTO_SOURCE_DIR}/CMakeLists.txt" --mode dev)}" +if command -v ccache >/dev/null 2>&1; then + export CMAKE_C_COMPILER_LAUNCHER="${CMAKE_C_COMPILER_LAUNCHER:-ccache}" + export CMAKE_CXX_COMPILER_LAUNCHER="${CMAKE_CXX_COMPILER_LAUNCHER:-ccache}" +fi -cd "$PTO_SOURCE_DIR" - -PTO_WHEEL_DIR="${PTO_SOURCE_DIR}/build/wheel-dist" -rm -rf "${PTO_WHEEL_DIR}" -mkdir -p "${PTO_WHEEL_DIR}" LLVM_BUILD_DIR="${LLVM_BUILD_DIR}" \ -PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_VERSION}" \ -SKBUILD_BUILD_DIR="${PTO_SOURCE_DIR}/build" \ - python -m pip wheel . --no-deps --wheel-dir "${PTO_WHEEL_DIR}" - -cmake --install "${PTO_SOURCE_DIR}/build" --prefix "${PTO_INSTALL_DIR}" - -shopt -s nullglob -wheels=("${PTO_WHEEL_DIR}/ptoas-"*.whl) -shopt -u nullglob -((${#wheels[@]} > 0)) || { echo "error: no ptoas-*.whl under ${PTO_WHEEL_DIR}" >&2; exit 1; } -pip install --force-reinstall "${wheels[0]}" - -export PATH="${PTO_SOURCE_DIR}/build/tools/ptoas:${PATH}" -export LD_LIBRARY_PATH="${LLVM_BUILD_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}" - -python -c "import mlir.ir" -python -c "from mlir.dialects import pto" - -which ptoas - -PTOAS_ENV_TMP="${PTO_SOURCE_DIR}/tmp/set_ptoas_env" -mkdir -p "${PTOAS_ENV_TMP}/MatMul" "${PTOAS_ENV_TMP}/Abs" -(cd "${PTO_SOURCE_DIR}/test/samples/MatMul" && python ./tmatmulk.py > "${PTOAS_ENV_TMP}/MatMul/tmatmulk.pto" && ptoas "${PTOAS_ENV_TMP}/MatMul/tmatmulk.pto" -o "${PTOAS_ENV_TMP}/MatMul/tmatmulk.cpp") -(cd "${PTO_SOURCE_DIR}/test/samples/Abs" && python ./abs.py > "${PTOAS_ENV_TMP}/Abs/abs.pto" && ptoas --enable-insert-sync "${PTOAS_ENV_TMP}/Abs/abs.pto" -o "${PTOAS_ENV_TMP}/Abs/abs.cpp") + "${PYTHON_BIN}" -m pip install --editable "${PTO_SOURCE_DIR}" \ + --config-settings="build-dir=${PTO_BUILD_DIR}" -echo "quick_install.sh: OK" +echo "PTOAS editable install complete." +echo "Build directory: ${PTO_BUILD_DIR}" From c2519a071359510df2ce4bbd7950ae727f2cc8d9 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Thu, 23 Jul 2026 23:18:41 +0800 Subject: [PATCH 08/19] Use editable installs in CI workflows --- .github/workflows/ci.yml | 28 ++++++---------- .github/workflows/ci_sim.yml | 64 ++++++++++-------------------------- 2 files changed, 27 insertions(+), 65 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d2393c5e8..d1e13b742e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -103,7 +103,6 @@ jobs: LLVM_DIR: ${{ github.workspace }}/llvm-project/llvm/build-assert PTO_BUILD_DIR: ${{ github.workspace }}/build-assert PTO_INSTALL_DIR: ${{ github.workspace }}/install-assert - PTO_WHEELHOUSE: ${{ github.workspace }}/wheelhouse-assert PTOAS_VENV: ${{ github.workspace }}/.venv-ptoas-assert MLIR_PYTHONPATH: ${{ github.workspace }}/llvm-project/llvm/build-assert/tools/mlir/python_packages/mlir_core LLVM_CACHE_FLAVOR: llvm21-assert-shared-mlirpy-hardening-v1 @@ -271,35 +270,28 @@ jobs: "${PTOAS_VENV}/bin/python" -m pip install --upgrade pip "${PTOAS_VENV}/bin/pip" install 'scikit-build-core>=0.12.2,<2' 'pybind11<3' nanobind numpy ml-dtypes - - name: Build PTOAS wheel + - name: Install PTOAS editable run: | set -euo pipefail rm -rf "${PTO_BUILD_DIR}" rm -rf "${PTO_INSTALL_DIR}" - rm -rf "${PTO_WHEELHOUSE}" - mkdir -p "${PTO_WHEELHOUSE}" - # scikit-build-core reuses this build tree so the following CTest and - # lit steps exercise the exact sources used to produce the wheel. + # Keep a persistent CMake build tree for CTest and lit while exposing + # the current sources and Python extension through the developer venv. LLVM_BUILD_DIR="${LLVM_DIR}" \ - SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}" \ CC="${PTOAS_CMAKE_C_COMPILER}" \ CXX="${PTOAS_CMAKE_CXX_COMPILER}" \ - "${PTOAS_VENV}/bin/python" -m pip wheel . --no-build-isolation --no-deps --wheel-dir "${PTO_WHEELHOUSE}" + "${PTOAS_VENV}/bin/python" -m pip install --editable . \ + --no-build-isolation --no-deps \ + --config-settings="build-dir=${PTO_BUILD_DIR}" cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" - - name: Install PTOAS wheel into test venv + - name: Test PTOAS editable install shell: bash run: | set -euo pipefail - readarray -t ptoas_wheels < <(find "${PTO_WHEELHOUSE}" -maxdepth 1 -type f -name 'ptoas*.whl' | sort) - if [[ "${#ptoas_wheels[@]}" -ne 1 ]]; then - echo "ERROR: expected exactly one PTOAS wheel in ${PTO_WHEELHOUSE}, found ${#ptoas_wheels[@]}" >&2 - printf ' %s\n' "${ptoas_wheels[@]}" >&2 - exit 1 - fi - - "${PTOAS_VENV}/bin/pip" install --no-deps --force-reinstall "${ptoas_wheels[0]}" - PATH="${PTOAS_VENV}/bin:${PATH}" bash docker/test_wheel_imports.sh + PATH="${PTOAS_VENV}/bin:${PATH}" \ + PYTHON="${PTOAS_VENV}/bin/python" \ + bash docker/test_wheel_imports.sh - name: Run PTODSL Python tests shell: bash diff --git a/.github/workflows/ci_sim.yml b/.github/workflows/ci_sim.yml index 06a3dfdf45..0c22024524 100644 --- a/.github/workflows/ci_sim.yml +++ b/.github/workflows/ci_sim.yml @@ -112,7 +112,6 @@ jobs: LLVM_REPO: https://github.com/vpto-dev/llvm-project.git LLVM_REF: feature-vpto-llvm21 PTO_INSTALL_DIR: ${{ github.workspace }}/install - PTO_WHEELHOUSE: ${{ github.workspace }}/.work/ptoas-wheelhouse PTOAS_VENV: ${{ github.workspace }}/.work/ptoas-sim-venv VPTO_SIM_WORKSPACE: ${{ github.workspace }}/.work/vpto-sim-ci TILELANG_DSL_WORKSPACE: ${{ github.workspace }}/.work/tilelang-dsl-ci @@ -233,7 +232,6 @@ jobs: set -euo pipefail echo "PTO_DSL_ST_BUILD_DIR=${GITHUB_WORKSPACE}/build-ptodsl" >> "${GITHUB_ENV}" echo "PTO_DSL_ST_INSTALL_DIR=${GITHUB_WORKSPACE}/install-ptodsl" >> "${GITHUB_ENV}" - echo "PTO_DSL_ST_WHEELHOUSE=${GITHUB_WORKSPACE}/.work/ptodsl-wheelhouse" >> "${GITHUB_ENV}" - name: Resolve LLVM cache key id: llvm-cache-key @@ -267,8 +265,6 @@ jobs: rm -rf "${GITHUB_WORKSPACE}/build-ptodsl" rm -rf "${PTO_INSTALL_DIR}" rm -rf "${PTO_DSL_ST_INSTALL_DIR}" - rm -rf "${PTO_DSL_ST_WHEELHOUSE}" - rm -rf "${PTO_WHEELHOUSE}" rm -rf "${PTOAS_VENV}" rm -rf "${VPTO_SIM_WORKSPACE}" rm -rf "${TILELANG_DSL_WORKSPACE}" @@ -331,39 +327,28 @@ jobs: path: ${{ env.LLVM_DIR }} key: ${{ steps.llvm-cache-key.outputs.key }} - - name: Build PTOAS wheel + - name: Install PTOAS editable in simulator venv shell: bash run: | set -euo pipefail rm -rf "${PTO_INSTALL_DIR}" - rm -rf "${PTO_WHEELHOUSE}" - mkdir -p "${PTO_WHEELHOUSE}" + rm -rf "${PTOAS_VENV}" + python3 -m venv "${PTOAS_VENV}" + "${PTOAS_VENV}/bin/python" -m pip install --upgrade pip + "${PTOAS_VENV}/bin/pip" install \ + 'scikit-build-core>=0.12.2,<2' 'pybind11<3' \ + nanobind numpy ml-dtypes # Pin system compilers for the same reason as LLVM above. export CC=gcc export CXX=g++ LLVM_BUILD_DIR="${LLVM_DIR}" \ - python3 -m pip wheel . --no-build-isolation --no-deps \ - --config-settings="build-dir=${GITHUB_WORKSPACE}/build" \ - --wheel-dir "${PTO_WHEELHOUSE}" + "${PTOAS_VENV}/bin/python" -m pip install --editable . \ + --no-build-isolation --no-deps \ + --config-settings="build-dir=${GITHUB_WORKSPACE}/build" cmake --install "${GITHUB_WORKSPACE}/build" --prefix "${PTO_INSTALL_DIR}" - - - name: Create PTOAS simulator venv - shell: bash - run: | - set -euo pipefail - rm -rf "${PTOAS_VENV}" - python3 -m venv "${PTOAS_VENV}" - "${PTOAS_VENV}/bin/python" -m pip install --upgrade pip - - readarray -t ptoas_wheels < <(find "${PTO_WHEELHOUSE}" -maxdepth 1 -type f -name 'ptoas*.whl' | sort) - if [[ "${#ptoas_wheels[@]}" -ne 1 ]]; then - echo "ERROR: expected exactly one PTOAS wheel in ${PTO_WHEELHOUSE}, found ${#ptoas_wheels[@]}" >&2 - printf ' %s\n' "${ptoas_wheels[@]}" >&2 - exit 1 - fi - - "${PTOAS_VENV}/bin/pip" install numpy ml-dtypes "${ptoas_wheels[0]}" - PATH="${PTOAS_VENV}/bin:${PATH}" bash docker/test_wheel_imports.sh + PATH="${PTOAS_VENV}/bin:${PATH}" \ + PYTHON="${PTOAS_VENV}/bin/python" \ + bash docker/test_wheel_imports.sh - name: Checkout PyPTO uses: actions/checkout@v4 @@ -804,34 +789,19 @@ jobs: path: ${{ env.PTO_DSL_ST_LLVM_DIR }} key: llvm-build-${{ steps.llvm-cache-key.outputs.sha }}-assert-${{ env.PTO_DSL_ST_PYTHON_TAG }}-v2 - - name: Build PTODSL PTOAS wheel + - name: Install PTODSL PTOAS editable shell: bash run: | set -euo pipefail rm -rf "${PTO_DSL_ST_BUILD_DIR}" "${PTO_DSL_ST_INSTALL_DIR}" - rm -rf "${PTO_DSL_ST_WHEELHOUSE}" - mkdir -p "${PTO_DSL_ST_WHEELHOUSE}" export CC=gcc export CXX=g++ LLVM_BUILD_DIR="${PTO_DSL_ST_LLVM_DIR}" \ - "${PTO_DSL_ST_PYTHON_BIN}" -m pip wheel . --no-build-isolation --no-deps \ - --config-settings="build-dir=${PTO_DSL_ST_BUILD_DIR}" \ - --wheel-dir "${PTO_DSL_ST_WHEELHOUSE}" + "${PTO_DSL_ST_PYTHON_BIN}" -m pip install --editable . \ + --no-build-isolation --no-deps \ + --config-settings="build-dir=${PTO_DSL_ST_BUILD_DIR}" cmake --install "${PTO_DSL_ST_BUILD_DIR}" --prefix "${PTO_DSL_ST_INSTALL_DIR}" - - name: Install PTODSL PTOAS wheel - shell: bash - run: | - set -euo pipefail - readarray -t ptodsl_wheels < <(find "${PTO_DSL_ST_WHEELHOUSE}" -maxdepth 1 -type f -name 'ptoas*.whl' | sort) - if [[ "${#ptodsl_wheels[@]}" -ne 1 ]]; then - echo "ERROR: expected exactly one PTOAS wheel in ${PTO_DSL_ST_WHEELHOUSE}, found ${#ptodsl_wheels[@]}" >&2 - printf ' %s\n' "${ptodsl_wheels[@]}" >&2 - exit 1 - fi - - "${PTO_DSL_ST_PYTHON_BIN}" -m pip install --force-reinstall "${ptodsl_wheels[0]}" - - name: Probe PTODSL runtime Python shell: bash run: | From 73ebc965e5bd91317de06516ec2fcf62d5b7ad19 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Thu, 23 Jul 2026 23:28:42 +0800 Subject: [PATCH 09/19] Run wheel repair in pull request CI --- .github/workflows/build_wheel.yml | 18 ++---------------- .github/workflows/build_wheel_mac.yml | 19 +++---------------- 2 files changed, 5 insertions(+), 32 deletions(-) diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index 8f6be18831..2730cd6634 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -227,24 +227,11 @@ jobs: --wheel-dir "${PTO_SOURCE_DIR}/build/wheel-dist" cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" - - name: Install built wheel for Python sample generation - run: | - shopt -s nullglob - wheels=("$PTO_SOURCE_DIR"/build/wheel-dist/ptoas*.whl) - if [ "${#wheels[@]}" -ne 1 ]; then - echo "Expected exactly one wheel in $PTO_SOURCE_DIR/build/wheel-dist, found ${#wheels[@]}" >&2 - printf ' %s\n' "${wheels[@]}" >&2 - exit 1 - fi - python -m pip install --no-deps --force-reinstall "${wheels[0]}" - - name: Validate wheel payload and launcher contract - if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | python "$PTO_SOURCE_DIR/docker/validate_wheel_payload.py" "$PTO_SOURCE_DIR/build/wheel-dist" - name: Repair wheel with auditwheel - if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | export PTO_WHEEL_DIST_DIR=$PTO_SOURCE_DIR/build/wheel-dist export PTO_WHEELHOUSE=$GITHUB_WORKSPACE/wheelhouse @@ -253,10 +240,9 @@ jobs: auditwheel repair --plat manylinux_2_34_${{ matrix.arch }} "$PTO_WHEEL_DIST_DIR"/ptoas*.whl -w "$PTO_WHEELHOUSE" - name: Test wheel installation - if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | - pip install $GITHUB_WORKSPACE/wheelhouse/ptoas*.whl - bash $PTO_SOURCE_DIR/docker/test_wheel_imports.sh + PTO_TEST_WHEEL_PATH="$GITHUB_WORKSPACE/wheelhouse/ptoas*.whl" \ + bash $PTO_SOURCE_DIR/docker/test_wheel_imports.sh - name: Test ptoas CLI run: | diff --git a/.github/workflows/build_wheel_mac.yml b/.github/workflows/build_wheel_mac.yml index b78213a34f..0e2ffc4058 100644 --- a/.github/workflows/build_wheel_mac.yml +++ b/.github/workflows/build_wheel_mac.yml @@ -12,6 +12,7 @@ on: push: tags-ignore: - '**' + pull_request: # Nightly build & publish (UTC time, offset from Linux workflow). schedule: - cron: "40 17 * * *" @@ -234,24 +235,11 @@ jobs: printf 'Built wheel file: %s\n' "$(basename "${built_wheels[0]}")" fi - - name: Install built wheel for Python sample generation - run: | - shopt -s nullglob - wheels=("$PTO_SOURCE_DIR"/build/wheel-dist/ptoas*.whl) - if [ "${#wheels[@]}" -ne 1 ]; then - echo "Expected exactly one wheel in $PTO_SOURCE_DIR/build/wheel-dist, found ${#wheels[@]}" >&2 - printf ' %s\n' "${wheels[@]}" >&2 - exit 1 - fi - python -m pip install --no-deps --force-reinstall "${wheels[0]}" - - name: Validate wheel payload and launcher contract - if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | python "$PTO_SOURCE_DIR/docker/validate_wheel_payload.py" "$PTO_SOURCE_DIR/build/wheel-dist" - name: Repair wheel with delocate - if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | set -euo pipefail export PTO_WHEEL_DIST_DIR=$PTO_SOURCE_DIR/build/wheel-dist @@ -327,11 +315,10 @@ jobs: ls -lh "$PTO_WHEELHOUSE" - name: Test wheel installation - if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' run: | - pip install $GITHUB_WORKSPACE/wheelhouse/ptoas*.whl export DYLD_LIBRARY_PATH=$LLVM_BUILD_DIR/lib:$PTO_INSTALL_DIR/lib:${DYLD_LIBRARY_PATH} - bash $PTO_SOURCE_DIR/docker/test_wheel_imports.sh + PTO_TEST_WHEEL_PATH="$GITHUB_WORKSPACE/wheelhouse/ptoas*.whl" \ + bash $PTO_SOURCE_DIR/docker/test_wheel_imports.sh - name: Test ptoas CLI run: | From 2647bda59cb647f34ac3e0168646edbdaa82380e Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Fri, 24 Jul 2026 02:00:35 +0800 Subject: [PATCH 10/19] ci: streamline wheel packaging checks --- .github/workflows/build_wheel.yml | 33 ++-- .github/workflows/build_wheel_mac.yml | 67 ++----- docker/Dockerfile | 2 +- packaging/ptoas-vmi/pyproject.toml | 3 +- pyproject.toml | 3 +- test/python/test_docker_runtime_packaging.py | 98 ---------- test/python/test_scikit_build_config.py | 120 ------------ test/python/test_validate_wheel_payload.py | 195 ------------------- 8 files changed, 40 insertions(+), 481 deletions(-) delete mode 100644 test/python/test_docker_runtime_packaging.py delete mode 100644 test/python/test_scikit_build_config.py delete mode 100644 test/python/test_validate_wheel_payload.py diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index 2730cd6634..8952245bde 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -10,8 +10,8 @@ name: Build Wheel on: push: - tags-ignore: - - '**' + branches: + - main pull_request: # Nightly build & publish (UTC time). schedule: @@ -29,7 +29,11 @@ on: types: [prereleased, released] permissions: - contents: write + contents: read + +concurrency: + group: build-wheel-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }} env: LLVM_REPO: https://github.com/vpto-dev/llvm-project.git @@ -41,7 +45,7 @@ jobs: if: github.event_name != 'release' || startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'ptoas-v') # Non-release runs keep a single-Python matrix for faster gates; # release/nightly runs fan out to publish the full wheel set plus binary artifacts. - name: Build ptoas-bin (${{ matrix.arch }}, py${{ matrix.python }}) + name: Build ptoas wheel (${{ matrix.arch }}, py${{ matrix.python }}) runs-on: ${{ matrix.arch == 'x86_64' && 'ubuntu-latest' || 'ubuntu-24.04-arm' }} strategy: fail-fast: false @@ -59,11 +63,13 @@ jobs: - name: Set Python version run: | case "${{ matrix.python }}" in - "3.9") PY_VER="cp39-cp39" ;; "3.10") PY_VER="cp310-cp310" ;; "3.11") PY_VER="cp311-cp311" ;; "3.12") PY_VER="cp312-cp312" ;; - *) PY_VER="cp311-cp311" ;; + *) + echo "Unsupported Python version: ${{ matrix.python }}" >&2 + exit 1 + ;; esac echo "PY_VER=$PY_VER" >> $GITHUB_ENV echo "PY_PATH=/opt/python/$PY_VER" >> $GITHUB_ENV @@ -123,7 +129,7 @@ jobs: - name: Install system dependencies run: | - dnf install -y ninja-build cmake git ccache gcc-c++ lld zip binutils patchelf chrpath + dnf install -y ninja-build cmake git gcc-c++ lld zip binutils patchelf chrpath dnf clean all - name: Install Python dependencies @@ -172,8 +178,8 @@ jobs: git remote add origin "${LLVM_REPO}" fi git remote set-url origin "${LLVM_REPO}" - git fetch --depth 1 origin "${LLVM_REF}" - git checkout --force FETCH_HEAD + git fetch --depth 1 origin "${{ steps.llvm-source.outputs.sha }}" + git checkout --force "${{ steps.llvm-source.outputs.sha }}" - name: Warn when default-branch cache is missing for PR/release runs if: steps.cache-llvm.outputs.cache-hit != 'true' && (github.event_name == 'pull_request' || github.event_name == 'release') @@ -244,11 +250,6 @@ jobs: PTO_TEST_WHEEL_PATH="$GITHUB_WORKSPACE/wheelhouse/ptoas*.whl" \ bash $PTO_SOURCE_DIR/docker/test_wheel_imports.sh - - name: Test ptoas CLI - run: | - export PTOAS_BIN="${PTO_BUILD_DIR}/tools/ptoas/ptoas" - bash $PTO_SOURCE_DIR/docker/test_ptoas_cli.sh - - name: Upload wheel artifact if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' uses: actions/upload-artifact@v4 @@ -280,6 +281,8 @@ jobs: if: (github.event_name == 'release' && (startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'ptoas-v'))) || github.event_name == 'schedule' needs: build_wheel runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Compute release metadata @@ -370,6 +373,8 @@ jobs: if: github.event_name == 'release' && github.event.action == 'released' && (startsWith(github.ref_name, 'ptoas-v') || (startsWith(github.ref_name, 'v') && !startsWith(github.ref_name, 'vmi-v'))) needs: upload_release_assets runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Checkout default branch diff --git a/.github/workflows/build_wheel_mac.yml b/.github/workflows/build_wheel_mac.yml index 0e2ffc4058..5ac014e9dc 100644 --- a/.github/workflows/build_wheel_mac.yml +++ b/.github/workflows/build_wheel_mac.yml @@ -10,8 +10,8 @@ name: Build Wheel (macOS) on: push: - tags-ignore: - - '**' + branches: + - main pull_request: # Nightly build & publish (UTC time, offset from Linux workflow). schedule: @@ -29,7 +29,11 @@ on: types: [prereleased, released] permissions: - contents: write + contents: read + +concurrency: + group: build-wheel-macos-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'push' || github.event_name == 'pull_request' }} env: LLVM_REPO: https://github.com/vpto-dev/llvm-project.git @@ -41,16 +45,13 @@ jobs: if: github.event_name != 'release' || startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'ptoas-v') # Non-release runs keep a single-Python matrix for faster gates; # release/nightly runs fan out to publish the full wheel set plus binary artifacts. - name: Build ptoas-bin (macOS ${{ matrix.arch }}, py${{ matrix.python }}) + name: Build ptoas wheel (macOS ${{ matrix.arch }}, py${{ matrix.python }}) runs-on: ${{ matrix.arch == 'x86_64' && 'macos-15-intel' || 'macos-26' }} strategy: fail-fast: false matrix: python: ${{ fromJson((github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && '["3.10","3.11","3.12"]' || '["3.11"]') }} arch: ["x86_64", "aarch64"] - exclude: - - python: "3.10" - arch: "x86_64" steps: - name: Checkout repository @@ -128,7 +129,7 @@ jobs: - name: Install system dependencies run: | - brew install ninja ccache + brew install ninja - name: Install Python dependencies run: | @@ -136,6 +137,11 @@ jobs: # (see pybind11 static_assert on def_property + keep_alive). pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' delocate + - name: Validate PEP 517 project metadata + run: | + python -m scikit_build_core.build project-table + (cd packaging/ptoas-vmi && python -m scikit_build_core.build project-table) + - name: Set build directories run: | echo "WORKSPACE_DIR=${RUNNER_TEMP}/llvm-workspace" >> $GITHUB_ENV @@ -171,8 +177,8 @@ jobs: git remote add origin "${LLVM_REPO}" fi git remote set-url origin "${LLVM_REPO}" - git fetch --depth 1 origin "${LLVM_REF}" - git checkout --force FETCH_HEAD + git fetch --depth 1 origin "${{ steps.llvm-source.outputs.sha }}" + git checkout --force "${{ steps.llvm-source.outputs.sha }}" - name: Warn when default-branch cache is missing for PR/release runs if: steps.cache-llvm.outputs.cache-hit != 'true' && (github.event_name == 'pull_request' || github.event_name == 'release') @@ -316,15 +322,9 @@ jobs: - name: Test wheel installation run: | - export DYLD_LIBRARY_PATH=$LLVM_BUILD_DIR/lib:$PTO_INSTALL_DIR/lib:${DYLD_LIBRARY_PATH} PTO_TEST_WHEEL_PATH="$GITHUB_WORKSPACE/wheelhouse/ptoas*.whl" \ bash $PTO_SOURCE_DIR/docker/test_wheel_imports.sh - - name: Test ptoas CLI - run: | - export PTOAS_BIN="${PTO_BUILD_DIR}/tools/ptoas/ptoas" - bash $PTO_SOURCE_DIR/docker/test_ptoas_cli.sh - - name: Upload wheel artifact if: github.event_name == 'release' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' uses: actions/upload-artifact@v4 @@ -363,39 +363,6 @@ jobs: "$PTO_SOURCE_DIR/test/lit/pto/kernel_kind_vector_scf_while_emitc.pto" \ >/dev/null - - name: Smoke test wheel imports after collecting artifacts - if: (github.event_name == 'release' || github.event_name == 'schedule') && matrix.python == '3.11' - run: | - # Test the copied wheel artifact from an isolated env with no build-tree - # paths, so post-collect/release regressions (e.g. ARM cs_invalid_page) - # are caught before upload. - brew install uv - uv python install 3.11 - TEST_DIR="$RUNNER_TEMP/wheel-smoke-test" - VENV_DIR="$TEST_DIR/.venv" - mkdir -p "$TEST_DIR" - cd "$TEST_DIR" - uv venv --python 3.11 "$VENV_DIR" - source "$VENV_DIR/bin/activate" - - unset PYTHONPATH - unset DYLD_LIBRARY_PATH - unset LD_LIBRARY_PATH - - shopt -s nullglob - wheels=("$GITHUB_WORKSPACE"/wheelhouse/ptoas*.whl) - if [ "${#wheels[@]}" -ne 1 ]; then - echo "Expected exactly one wheel in \$GITHUB_WORKSPACE/wheelhouse, found ${#wheels[@]}:" - printf ' %s\n' "${wheels[@]}" - exit 1 - fi - uv pip install "${wheels[0]}" - - if [ "${{ matrix.arch }}" = "aarch64" ]; then - export DYLD_PRINT_LIBRARIES=1 - fi - bash "$GITHUB_WORKSPACE/docker/test_wheel_imports.sh" - - name: Upload ptoas binary artifact if: matrix.python == '3.11' uses: actions/upload-artifact@v4 @@ -408,6 +375,8 @@ jobs: if: (github.event_name == 'release' && (startsWith(github.ref_name, 'v') || startsWith(github.ref_name, 'ptoas-v'))) || github.event_name == 'schedule' needs: build_wheel runs-on: ubuntu-latest + permissions: + contents: write steps: - name: Compute release metadata diff --git a/docker/Dockerfile b/docker/Dockerfile index aac5865981..0911fdb594 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -19,7 +19,7 @@ ENV PY_PATH="/opt/python/${PY_VER}" ENV PATH="${PY_PATH}/bin:${PATH}" # dependency -RUN dnf install -y ninja-build cmake git ccache gcc-c++ lld zip binutils patchelf chrpath && dnf clean all +RUN dnf install -y ninja-build cmake git gcc-c++ lld zip binutils patchelf chrpath && dnf clean all RUN pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' auditwheel COPY cmake/LinuxHardeningCache.cmake /tmp/LinuxHardeningCache.cmake diff --git a/packaging/ptoas-vmi/pyproject.toml b/packaging/ptoas-vmi/pyproject.toml index d9c28bd5e4..c5bf63ca99 100644 --- a/packaging/ptoas-vmi/pyproject.toml +++ b/packaging/ptoas-vmi/pyproject.toml @@ -19,7 +19,7 @@ build-backend = "scikit_build_core.build" name = "ptoas-vmi" dynamic = ["version"] description = "PTO Assembler & Optimizer with VMI support" -requires-python = ">=3.9" +requires-python = ">=3.10" license = "Apache-2.0" dependencies = [ "numpy", @@ -28,7 +28,6 @@ classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/pyproject.toml b/pyproject.toml index 31a339e328..072d2fb95f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ name = "ptoas" dynamic = ["version"] description = "PTO Assembler & Optimizer" readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.10" license = "Apache-2.0" dependencies = [ "numpy", @@ -29,7 +29,6 @@ classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", diff --git a/test/python/test_docker_runtime_packaging.py b/test/python/test_docker_runtime_packaging.py deleted file mode 100644 index a56475ae74..0000000000 --- a/test/python/test_docker_runtime_packaging.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import unittest -from pathlib import Path - - -REPO_ROOT = Path(__file__).resolve().parents[2] -DOCKERFILE = REPO_ROOT / "docker" / "Dockerfile" -COLLECT_DIST_SCRIPT = REPO_ROOT / "docker" / "collect_ptoas_dist.sh" -COLLECT_DIST_MAC_SCRIPT = REPO_ROOT / "docker" / "collect_ptoas_dist_mac.sh" -PTOAS_CMAKE = REPO_ROOT / "tools" / "ptoas" / "CMakeLists.txt" -PTOAS_CLI_TEST = REPO_ROOT / "docker" / "test_ptoas_cli.sh" - - -class DockerRuntimePackagingTests(unittest.TestCase): - def test_runtime_uses_standard_python_extension_without_native_cli(self): - cmake = PTOAS_CMAKE.read_text(encoding="utf-8") - - self.assertIn( - "pybind11_add_module(ptoas_runtime MODULE", - cmake, - ) - self.assertIn('OUTPUT_NAME "_native"', cmake) - self.assertIn('BUILD_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}"', cmake) - self.assertIn('INSTALL_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}"', cmake) - self.assertNotIn("add_executable(ptoas_native_cli", cmake) - self.assertNotIn('OUTPUT_NAME "ptoas-native"', cmake) - - def test_runtime_image_uses_wheel_entrypoint_instead_of_copied_wrapper(self): - dockerfile = DOCKERFILE.read_text(encoding="utf-8") - - self.assertIn("COPY --from=builder /wheelhouse/ptoas*.whl /tmp/", dockerfile) - self.assertIn( - "RUN pip install --no-cache-dir /tmp/ptoas*.whl && rm /tmp/ptoas*.whl", - dockerfile, - ) - self.assertNotIn( - "COPY --from=builder /llvm-workspace/PTOAS/build-release/tools/ptoas/ptoas /usr/local/bin/ptoas", - dockerfile, - ) - self.assertNotIn("/usr/local/lib/ptoas", dockerfile) - - def test_docker_builds_wheel_through_standard_pep517_backend(self): - dockerfile = DOCKERFILE.read_text(encoding="utf-8") - - self.assertIn("python -m pip wheel .", dockerfile) - self.assertIn("SKBUILD_BUILD_DIR=$PTO_BUILD_DIR", dockerfile) - self.assertNotIn("create_wheel.sh", dockerfile) - self.assertNotIn("_ptoas_build_backend", dockerfile) - - def test_linux_dist_packages_python_wrapper_and_native_extension(self): - script = COLLECT_DIST_SCRIPT.read_text(encoding="utf-8") - - self.assertIn('PTOAS_BIN="${PTO_INSTALL_DIR}/bin/ptoas"', script) - self.assertIn('PTOAS_PACKAGE_SRC_DIR="${PTO_INSTALL_DIR}/ptoas"', script) - self.assertIn('PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}"', script) - self.assertIn("patchelf --set-rpath '$ORIGIN/../lib' \"${PTOAS_NATIVE_MODULE}\"", script) - self.assertIn('"${PTOAS_DIST_DIR}/bin/ptoas" --version', script) - self.assertNotIn("ptoas-native", script) - self.assertNotIn("ptoas.so", script) - - def test_macos_dist_packages_python_wrapper_and_native_extension(self): - script = COLLECT_DIST_MAC_SCRIPT.read_text(encoding="utf-8") - - self.assertIn('PTOAS_BIN="${PTO_INSTALL_DIR}/bin/ptoas"', script) - self.assertIn('PTOAS_PACKAGE_SRC_DIR="${PTO_INSTALL_DIR}/ptoas"', script) - self.assertIn('PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}"', script) - self.assertIn('collect_dylibs "${PTOAS_NATIVE_MODULE}"', script) - self.assertIn('"${PTOAS_DIST_DIR}/bin/ptoas" --version', script) - self.assertNotIn("ptoas-native", script) - self.assertNotIn("ptoas.so", script) - - def test_wheel_import_smoke_imports_native_extension(self): - script = (REPO_ROOT / "docker" / "test_wheel_imports.sh").read_text(encoding="utf-8") - - self.assertIn("from ptoas import _native", script) - self.assertNotIn("POLLUTED_PTOAS_VERSION_OUTPUT", script) - - def test_build_tree_cli_test_receives_explicit_test_environment(self): - script = PTOAS_CLI_TEST.read_text(encoding="utf-8") - - self.assertIn("for var in PTO_SOURCE_DIR PTOAS_BIN", script) - self.assertIn("python ./tmatmulk.py", script) - self.assertIn("python ./abs.py", script) - self.assertNotIn("PYTHON_BIN", script) - self.assertNotIn('command -v ptoas', script) - self.assertNotIn('export PATH="${PTO_BUILD_DIR}', script) - self.assertNotIn('export LD_LIBRARY_PATH="${LLVM_BUILD_DIR}', script) - -if __name__ == "__main__": - unittest.main() diff --git a/test/python/test_scikit_build_config.py b/test/python/test_scikit_build_config.py deleted file mode 100644 index 3f013e71dc..0000000000 --- a/test/python/test_scikit_build_config.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import json -import subprocess -import sys -import tomllib -import unittest -from pathlib import Path - - -REPO_ROOT = Path(__file__).resolve().parents[2] -PTOAS_PYPROJECT = REPO_ROOT / "pyproject.toml" -VMI_PROJECT_DIR = REPO_ROOT / "packaging" / "ptoas-vmi" -VMI_PYPROJECT = VMI_PROJECT_DIR / "pyproject.toml" -PTOAS_PACKAGE_INIT = REPO_ROOT / "ptodsl" / "ptoas" / "__init__.py" - - -def _read_pyproject(path: Path) -> dict: - with path.open("rb") as file: - return tomllib.load(file) - - -def _project_table(project_dir: Path) -> dict: - result = subprocess.run( - [ - sys.executable, - "-m", - "scikit_build_core.build", - "project-table", - ], - cwd=project_dir, - capture_output=True, - text=True, - check=False, - ) - if result.returncode != 0: - raise AssertionError(result.stderr or result.stdout) - return json.loads(result.stdout) - - -class ScikitBuildConfigTests(unittest.TestCase): - def test_root_project_uses_standard_backend_and_console_script(self): - config = _read_pyproject(PTOAS_PYPROJECT) - - self.assertEqual( - config["build-system"]["build-backend"], - "scikit_build_core.build", - ) - self.assertIn("scikit-build-core>=0.12.2,<2", config["build-system"]["requires"]) - self.assertEqual(config["project"]["name"], "ptoas") - self.assertEqual(config["project"]["scripts"]["ptoas"], "ptoas._cli:main") - self.assertEqual( - config["tool"]["scikit-build"]["install"]["components"], - ["PTOAS_Python"], - ) - - def test_static_projects_resolve_expected_distribution_metadata(self): - ptoas = _project_table(REPO_ROOT) - vmi = _project_table(VMI_PROJECT_DIR) - - self.assertEqual((ptoas["name"], ptoas["version"]), ("ptoas", "0.51")) - self.assertEqual((vmi["name"], vmi["version"]), ("ptoas-vmi", "0.1.3")) - self.assertEqual(ptoas["scripts"]["ptoas"], "ptoas._cli:main") - self.assertEqual(vmi["scripts"]["ptoas"], "ptoas._cli:main") - - def test_projects_share_python_package_sources(self): - ptoas = _read_pyproject(PTOAS_PYPROJECT) - vmi = _read_pyproject(VMI_PYPROJECT) - - self.assertEqual( - ptoas["tool"]["scikit-build"]["wheel"]["packages"], - { - "ptodsl": "ptodsl/ptodsl", - "ptoas": "ptodsl/ptoas", - "tilelang_dsl": "tilelang-dsl/python/tilelang_dsl", - }, - ) - self.assertEqual( - vmi["tool"]["scikit-build"]["cmake"]["source-dir"], - "../..", - ) - - def test_editable_install_uses_backend_redirect_without_package_path_hacks(self): - ptoas = _read_pyproject(PTOAS_PYPROJECT) - package_init = PTOAS_PACKAGE_INIT.read_text(encoding="utf-8") - - self.assertEqual( - ptoas["tool"]["scikit-build"]["editable"]["mode"], - "redirect", - ) - self.assertNotIn("extend_path", package_init) - - def test_cmake_python_payload_uses_dedicated_install_component(self): - cmake_files = [ - REPO_ROOT / "CMakeLists.txt", - REPO_ROOT / "lib" / "Bindings" / "Python" / "CMakeLists.txt", - REPO_ROOT / "tools" / "ptoas" / "CMakeLists.txt", - ] - combined = "\n".join(path.read_text(encoding="utf-8") for path in cmake_files) - - self.assertIn("COMPONENT PTOAS_Python", combined) - self.assertIn("if(SKBUILD)", combined) - self.assertIn('DIRECTORY "${MLIR_PYTHON_PACKAGE_DIR}/mlir"', combined) - - def test_legacy_wheel_builders_are_removed(self): - self.assertFalse((REPO_ROOT / "_ptoas_build_backend.py").exists()) - self.assertFalse((REPO_ROOT / "docker" / "create_wheel.sh").exists()) - self.assertFalse((REPO_ROOT / "docker" / "setup.py").exists()) - self.assertFalse((REPO_ROOT / "docker" / "setup_mac.py").exists()) - - -if __name__ == "__main__": - unittest.main() diff --git a/test/python/test_validate_wheel_payload.py b/test/python/test_validate_wheel_payload.py deleted file mode 100644 index 5b99367026..0000000000 --- a/test/python/test_validate_wheel_payload.py +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import subprocess -import tempfile -import unittest -import zipfile -import importlib.machinery -from pathlib import Path - - -REPO_ROOT = Path(__file__).resolve().parents[2] -VALIDATOR = REPO_ROOT / "docker" / "validate_wheel_payload.py" -WHEEL_IMPORTS = REPO_ROOT / "docker" / "test_wheel_imports.sh" - - -class ValidateWheelPayloadTests(unittest.TestCase): - def _make_wheel( - self, - root: Path, - *, - include_native_module: bool, - include_cli: bool = True, - include_tileops: bool = True, - entry_points_text: str = "[console_scripts]\nptoas=ptoas._cli:main\n", - wheel_stem: str = "ptoas", - dist_info_stem: str = "ptoas", - ) -> Path: - wheel = root / f"{wheel_stem}-1.2.3-cp311-cp311-linux_x86_64.whl" - with zipfile.ZipFile(wheel, "w") as zf: - zf.writestr("ptoas/__init__.py", "") - if include_cli: - zf.writestr("ptoas/_cli.py", "") - if include_tileops: - zf.writestr( - "ptoas/_runtime/share/ptoas/TileOps/__init__.py", "" - ) - if include_native_module: - suffix = importlib.machinery.EXTENSION_SUFFIXES[0] - zf.writestr(f"ptoas/_native{suffix}", "fake") - zf.writestr( - f"{dist_info_stem}-1.2.3.dist-info/entry_points.txt", - entry_points_text, - ) - return wheel - - def test_validator_accepts_current_runtime_payload_layout(self): - with tempfile.TemporaryDirectory() as temp_dir: - wheel = self._make_wheel(Path(temp_dir), include_native_module=True) - result = subprocess.run( - ["python3", str(VALIDATOR), str(wheel)], - capture_output=True, - text=True, - check=False, - ) - - self.assertEqual(result.returncode, 0, result.stderr) - self.assertIn("validated wheel payload and launcher contract", result.stdout) - - def test_validator_rejects_missing_native_module(self): - with tempfile.TemporaryDirectory() as temp_dir: - wheel = self._make_wheel(Path(temp_dir), include_native_module=False) - result = subprocess.run( - ["python3", str(VALIDATOR), str(wheel)], - capture_output=True, - text=True, - check=False, - ) - - self.assertNotEqual(result.returncode, 0) - self.assertIn("ptoas._native", result.stderr) - - def test_validator_rejects_missing_cli_module(self): - with tempfile.TemporaryDirectory() as temp_dir: - wheel = self._make_wheel( - Path(temp_dir), - include_native_module=True, - include_cli=False, - ) - result = subprocess.run( - ["python3", str(VALIDATOR), str(wheel)], - capture_output=True, - text=True, - check=False, - ) - - self.assertNotEqual(result.returncode, 0) - self.assertIn("ptoas/_cli.py", result.stderr) - - def test_validator_rejects_missing_packaged_tileops(self): - with tempfile.TemporaryDirectory() as temp_dir: - wheel = self._make_wheel( - Path(temp_dir), - include_native_module=True, - include_tileops=False, - ) - result = subprocess.run( - ["python3", str(VALIDATOR), str(wheel)], - capture_output=True, - text=True, - check=False, - ) - - self.assertNotEqual(result.returncode, 0) - self.assertIn("TileOps/__init__.py", result.stderr) - - def test_validator_rejects_legacy_bootstrap_entrypoint(self): - with tempfile.TemporaryDirectory() as temp_dir: - wheel = self._make_wheel( - Path(temp_dir), - include_native_module=True, - entry_points_text="[console_scripts]\nptoas=ptoas_wheel_bootstrap:main\n", - ) - result = subprocess.run( - ["python3", str(VALIDATOR), str(wheel)], - capture_output=True, - text=True, - check=False, - ) - - self.assertNotEqual(result.returncode, 0) - self.assertIn("ptoas._cli:main", result.stderr) - - def test_validator_accepts_normalized_entrypoint_spacing(self): - with tempfile.TemporaryDirectory() as temp_dir: - wheel = self._make_wheel( - Path(temp_dir), - include_native_module=True, - entry_points_text="[console_scripts]\nptoas = ptoas._cli:main\n", - ) - result = subprocess.run( - ["python3", str(VALIDATOR), str(wheel)], - capture_output=True, - text=True, - check=False, - ) - - self.assertEqual(result.returncode, 0, result.stderr) - - def test_validator_accepts_vmi_distribution_name(self): - with tempfile.TemporaryDirectory() as temp_dir: - wheel = self._make_wheel( - Path(temp_dir), - include_native_module=True, - wheel_stem="ptoas_vmi", - dist_info_stem="ptoas_vmi", - ) - result = subprocess.run( - ["python3", str(VALIDATOR), str(wheel)], - capture_output=True, - text=True, - check=False, - ) - - self.assertEqual(result.returncode, 0, result.stderr) - self.assertIn("validated wheel payload and launcher contract", result.stdout) - - def test_shell_probe_reuses_shared_validator(self): - self.assertIn( - '"${PYTHON_BIN}" "${REPO_ROOT}/docker/validate_wheel_payload.py" "${TEST_WHEEL}"', - WHEEL_IMPORTS.read_text(encoding="utf-8"), - ) - - def test_wheel_imports_script_keeps_clean_env_ptoas_smoke(self): - script = WHEEL_IMPORTS.read_text(encoding="utf-8") - - self.assertIn('EXPECTED_PTOAS_CLI_VERSION="${PTOAS_CLI_VERSION:-${PTOAS_VERSION:-}}"', script) - self.assertIn('env -i \\', script) - self.assertIn('CLEAN_ENV_PTO="${CLEAN_ENV_PTO}" \\', script) - self.assertIn('CLEAN_ENV_LOG="${CLEAN_ENV_DIR}/wheel-clean-env-probe.log"', script) - self.assertIn('CLEAN_ENV_PTO_IR="${CLEAN_ENV_DIR}/wheel-clean-env-probe.pto.ir"', script) - self.assertIn('def wheel_clean_env_probe():', script) - self.assertIn('pto.alloc_tile(shape=[1, 16], dtype=pto.f32, addr=0)', script) - self.assertIn('pto.castptr(pto.const(0, dtype=pto.ui64), pto.ptr(pto.f32, "gm"))', script) - self.assertIn('pto.tile.load(a_view, a_tile)', script) - self.assertIn('pto.tile.store(o_tile, o_view)', script) - self.assertIn('--emit-pto-ir "${CLEAN_ENV_PTO}" -o "${CLEAN_ENV_PTO_IR}"', script) - self.assertIn('def wheel_clean_env_probe(', script) - self.assertIn('"${PTOAS_ENTRYPOINT}" --pto-arch=a5 --pto-backend=vpto --pto-level=level3 --enable-tile-op-expand --emit-pto-ir "${CLEAN_ENV_PTO}" -o "${CLEAN_ENV_PTO_IR}"', script) - self.assertIn('>"${CLEAN_ENV_LOG}" 2>&1', script) - self.assertIn('grep -q "wheel_clean_env_probe" "${CLEAN_ENV_PTO_IR}"', script) - self.assertIn('grep -q "pto.tload" "${CLEAN_ENV_PTO_IR}"', script) - self.assertIn('grep -q "pto.tstore" "${CLEAN_ENV_PTO_IR}"', script) - self.assertIn('grep -q "candidates = " "${CLEAN_ENV_PTO_IR}"', script) - self.assertIn('grep -q "TileLib daemon started successfully" "${CLEAN_ENV_LOG}"', script) - self.assertIn('grep -q "TileLib daemon stopped" "${CLEAN_ENV_LOG}"', script) - -if __name__ == "__main__": - unittest.main() From 938498cfcf694739d4293110d7b4118deadb2158 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Fri, 24 Jul 2026 02:51:33 +0800 Subject: [PATCH 11/19] build: streamline Python development workflow --- .github/workflows/ci.yml | 4 +- .github/workflows/ci_sim.yml | 6 +-- CMakeLists.txt | 1 - README.md | 59 +++++++----------------------- README_en.md | 42 ++++++++------------- lib/Bindings/Python/CMakeLists.txt | 6 +++ python/CMakeLists.txt | 27 -------------- quick_install.sh | 5 +++ 8 files changed, 46 insertions(+), 104 deletions(-) delete mode 100644 python/CMakeLists.txt diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d1e13b742e..4466730b55 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -197,8 +197,8 @@ jobs: fi git remote set-url origin "${LLVM_REPO}" - git fetch --depth 1 origin "${LLVM_REF}" - git checkout --force FETCH_HEAD + git fetch --depth 1 origin "${LLVM_SOURCE_SHA}" + git checkout --force "${LLVM_SOURCE_SHA}" - name: Build LLVM/MLIR (only if cache miss) if: steps.cache-llvm.outputs.cache-hit != 'true' diff --git a/.github/workflows/ci_sim.yml b/.github/workflows/ci_sim.yml index 0c22024524..f57be126c2 100644 --- a/.github/workflows/ci_sim.yml +++ b/.github/workflows/ci_sim.yml @@ -286,9 +286,9 @@ jobs: fi git remote set-url origin "${LLVM_REPO}" - ref="${LLVM_TAG:-${LLVM_REF}}" - git fetch --depth 1 origin "${ref}" - git checkout --force FETCH_HEAD + sha="${{ steps.llvm-cache-key.outputs.sha }}" + git fetch --depth 1 origin "${sha}" + git checkout --force "${sha}" - name: Build LLVM/MLIR if: steps.llvm-cache.outputs.cache-hit != 'true' diff --git a/CMakeLists.txt b/CMakeLists.txt index a6f75436c9..1eb0afc4c3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -295,7 +295,6 @@ if(PTO_ENABLE_PYTHON_BINDING) # 设置 Python 扩展的输出目录,方便调试 set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python/pto) - add_subdirectory(python) add_subdirectory(ptodsl) add_subdirectory(tilelang-dsl) endif() diff --git a/README.md b/README.md index 608bf263cd..b1d834813a 100644 --- a/README.md +++ b/README.md @@ -68,10 +68,10 @@ mkdir -p $WORKSPACE_DIR * **OS**: Linux (Ubuntu 20.04+ 推荐) * **Compiler**: GCC >= 9 或 Clang (支持 C++17) * **Build System**: CMake >= 3.20, Ninja -* **Python**: 3.8+ -* **Python Packages**: `pybind11<3`, `nanobind`, `numpy` +* **Python**: 3.10+ +* **Python Packages**: `scikit-build-core`, `pybind11<3`, `nanobind`, `numpy` ```bash -python3 -m pip install 'pybind11<3' nanobind numpy +python3 -m pip install 'scikit-build-core>=0.12.2,<2' 'pybind11<3' nanobind numpy ``` @@ -123,52 +123,21 @@ cd $WORKSPACE_DIR git clone https://gitcode.com/cann/pto-as.git PTOAS cd $PTO_SOURCE_DIR -# 2. 获取 pybind11 的 CMake 路径 -export PYBIND11_CMAKE_DIR=$(python3 -m pybind11 --cmakedir) +# 2. 安装到当前 Python 环境,并保留可增量构建的 build tree +PYTHON_BIN=python3 \ +LLVM_BUILD_DIR="$LLVM_BUILD_DIR" \ +PTO_BUILD_DIR="$PTO_SOURCE_DIR/build" \ + ./quick_install.sh -# 3. 配置 CMake -# 注意:此处直接使用了 3.0 章节中定义的变量,无需手动修改 -cmake -G Ninja \ - -S . \ - -B build \ - -DLLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm \ - -DMLIR_DIR=$LLVM_BUILD_DIR/lib/cmake/mlir \ - -DPython3_EXECUTABLE=$(which python3) \ - -DPython3_FIND_STRATEGY=LOCATION \ - -Dpybind11_DIR="${PYBIND11_CMAKE_DIR}" \ - -DMLIR_ENABLE_BINDINGS_PYTHON=ON \ - -DMLIR_PYTHON_PACKAGE_DIR=$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core \ - -DCMAKE_INSTALL_PREFIX="$PTO_INSTALL_DIR" - -# 4. 编译并安装 -ninja -C build-llvm21 -ninja -C build-llvm21 install - -# 5. 检查构建产物 -# build 输出(便于本地开发/调试) -$PTO_SOURCE_DIR/build-llvm21/python/ -├── mlir -│ ├── _mlir_libs -│ │ └── _pto.cpython-*.so -│ └── dialects -│ ├── pto.py -│ └── _pto_ops_gen.py - -# install 输出(Python 方言文件和原生扩展) -$PTO_INSTALL_DIR/ -└── mlir - ├── dialects - │ ├── pto.py - │ └── _pto_ops_gen.py - └── _mlir_libs - └── _pto.cpython-*.so - -# CLI 工具 -$PTO_SOURCE_DIR/build-llvm21/tools/ptoas/ptoas -$PTO_SOURCE_DIR/build-llvm21/tools/ptobc/ptobc +# 3. 后续可直接复用同一个 build tree +ninja -C "$PTO_SOURCE_DIR/build" check-pto ``` +`quick_install.sh` 使用 editable install,并关闭 build isolation,避免把临时 +构建环境中的 pybind11 路径写入持久化 `CMakeCache.txt`。`ptoas` 会直接安装到 +`PYTHON_BIN` 对应的当前环境中。 + ### 3.4 Python 安装合同 (Python Distribution Contract) 如果你要使用 Python 绑定、PTODSL资源,推荐使用仓库根目录 diff --git a/README_en.md b/README_en.md index 81d2fb8ab8..2dc0de52fe 100644 --- a/README_en.md +++ b/README_en.md @@ -66,11 +66,11 @@ mkdir -p $WORKSPACE_DIR * **OS**: Linux (Ubuntu 20.04+ recommended) * **Compiler**: GCC >= 9 or Clang (C++17 support required) * **Build System**: CMake >= 3.20, Ninja -* **Python**: 3.8+ -* **Python Packages**: `pybind11<3`, `nanobind`, `numpy` +* **Python**: 3.10+ +* **Python Packages**: `scikit-build-core`, `pybind11<3`, `nanobind`, `numpy` ```bash -python3 -m pip install "pybind11<3" nanobind numpy +python3 -m pip install "scikit-build-core>=0.12.2,<2" "pybind11<3" nanobind numpy ``` > **Note**: The current LLVM/MLIR Python bindings are not compatible with `pybind11` 3.x. @@ -113,32 +113,22 @@ cd $WORKSPACE_DIR git clone https://gitcode.com/cann/pto-as.git PTOAS cd $PTO_SOURCE_DIR -# 2. Build and install via pip -# The build backend (pyproject.toml) drives CMake + Ninja automatically. -pip install . --no-build-isolation -``` - -This produces the same artifacts as a manual CMake build: +# 2. Install into the current Python environment while keeping a persistent, +# incrementally reusable build tree. +PYTHON_BIN=python3 \ +LLVM_BUILD_DIR="$LLVM_BUILD_DIR" \ +PTO_BUILD_DIR="$PTO_SOURCE_DIR/build" \ + ./quick_install.sh -```text -# CLI tools -$PTO_SOURCE_DIR/build/tools/ptoas/ptoas -$PTO_SOURCE_DIR/build/tools/ptobc/ptobc - -# Native extension installed into the MLIR Python package -$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core/ -└── mlir - └── _mlir_libs - └── _pto.cpython-*.so - -# Python dialect files -$PTO_INSTALL_DIR/ -└── mlir - └── dialects - ├── pto.py - └── _pto_ops_gen.py +# 3. Reuse the same build tree for subsequent test or development builds. +ninja -C "$PTO_SOURCE_DIR/build" check-pto ``` +`quick_install.sh` uses an editable install with build isolation disabled so a +temporary build environment's pybind11 path is not persisted in +`CMakeCache.txt`. The `ptoas` command is installed into the environment that +owns `PYTHON_BIN`. + ### 3.4 Step 3: Supported Python Install Flows If you want to use Python bindings or PTODSL, prefer the repository-root diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index 06b3829b44..f167cc3791 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -86,6 +86,12 @@ mlir_tablegen(_pto_ops_gen.py add_public_tablegen_target(PTOPythonGen) add_dependencies(_pto PTOPythonGen) +# Stable aggregate target used by CTest and developer workflows. Keep the +# dialect binding generation owned by this directory so there is only one +# _pto_ops_gen.py producer. +add_custom_target(PTOPythonModules) +add_dependencies(PTOPythonModules _pto) + # ---- 3) Copy generated python + handwritten pto.py into build/python ---- set(PTO_PY_SRC "${CMAKE_SOURCE_DIR}/python/pto/dialects/pto.py") diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt deleted file mode 100644 index a044a0049b..0000000000 --- a/python/CMakeLists.txt +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -# ========================================================= -# Python Package Configuration -# ========================================================= - -add_custom_target(PTOPythonModules) - -# [修改] 依赖必须指向 lib/Bindings/Python 中定义的 Target (_pto) -add_dependencies(PTOPythonModules _pto) - -# 生成 TableGen 绑定代码 -set(LLVM_TARGET_DEFINITIONS pto/dialects/PTOOps.td) -mlir_tablegen(pto/dialects/_pto_ops_gen.py - -gen-python-op-bindings - -bind-dialect=pto - -I${PROJECT_SOURCE_DIR}/include -) -add_public_tablegen_target(PTOOpsPyGen) - -add_dependencies(PTOPythonModules PTOOpsPyGen) diff --git a/quick_install.sh b/quick_install.sh index 78a05bbe24..9c3767a28b 100755 --- a/quick_install.sh +++ b/quick_install.sh @@ -29,8 +29,13 @@ if command -v ccache >/dev/null 2>&1; then export CMAKE_CXX_COMPILER_LAUNCHER="${CMAKE_CXX_COMPILER_LAUNCHER:-ccache}" fi +"${PYTHON_BIN}" -m pip install \ + 'scikit-build-core>=0.12.2,<2' \ + 'pybind11<3' + LLVM_BUILD_DIR="${LLVM_BUILD_DIR}" \ "${PYTHON_BIN}" -m pip install --editable "${PTO_SOURCE_DIR}" \ + --no-build-isolation \ --config-settings="build-dir=${PTO_BUILD_DIR}" echo "PTOAS editable install complete." From 2ccd00a1cf500175eb2eaaedc8e4f98a9a853503 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Mon, 27 Jul 2026 09:20:56 +0800 Subject: [PATCH 12/19] build: standardize MLIR Python package integration --- .github/workflows/build_wheel_mac.yml | 2 +- .github/workflows/ci.yml | 5 +- .github/workflows/ci_sim.yml | 2 - CMakeLists.txt | 176 ++-------------- README.md | 10 +- docker/collect_ptoas_dist.sh | 4 +- docker/collect_ptoas_dist_mac.sh | 4 +- docker/test_wheel_imports.sh | 2 +- docker/validate_wheel_payload.py | 4 +- docs/build_with_installed_llvm.md | 23 +-- docs/designs/ci-board-validation-guide.md | 7 +- docs/designs/ptoas-python-launcher-layout.md | 23 ++- docs/no_npu_compile_only_guide_zh.md | 2 +- lib/Bindings/Python/CMakeLists.txt | 194 +++++++++--------- lib/Bindings/Python/PTOModule.cpp | 16 +- lib/Bindings/Python/PTOModule.h | 22 ++ lib/Bindings/Python/PythonRegistration.cpp | 28 +++ packaging/ptoas-vmi/pyproject.toml | 2 +- ptodsl/CMakeLists.txt | 20 +- .../tilelib-debugging-playbook.md | 2 +- ptodsl/ptoas/_cli.py | 6 +- ptodsl/tests/CMakeLists.txt | 10 +- ptodsl/tests/test_allreduce.py | 5 - ptodsl/tests/test_ptoas_cli.py | 2 +- ptodsl/tests/test_ptoas_tree_wrapper.py | 27 ++- ptodsl/tests/test_vmi_vmull.py | 6 - ptodsl/tests/test_vmi_vshr_signedness.py | 6 - pyproject.toml | 2 +- python/pto/dialects/pto.py | 77 +------ quick_install.sh | 3 +- scripts/ptoas_env.sh | 9 +- test/lit/lit.cfg.py | 14 +- test/lit/lit.site.cfg.py.in | 2 - test/tilelib-st/README.md | 16 +- tilelang-dsl/CMakeLists.txt | 20 +- .../python/tilelang_dsl/env_config.py | 23 +-- .../python/tilelang_dsl/pybind_renderer.py | 13 +- .../tests/backend/test_e2e_pybind_backend.py | 4 +- tools/ptoas/CMakeLists.txt | 135 +++++++----- tools/ptoas/NativeModule.cpp | 8 +- tools/ptoas/ptoas_wrapper.py | 37 ++-- 41 files changed, 407 insertions(+), 566 deletions(-) create mode 100644 lib/Bindings/Python/PTOModule.h create mode 100644 lib/Bindings/Python/PythonRegistration.cpp diff --git a/.github/workflows/build_wheel_mac.yml b/.github/workflows/build_wheel_mac.yml index 5ac014e9dc..d422cf433e 100644 --- a/.github/workflows/build_wheel_mac.yml +++ b/.github/workflows/build_wheel_mac.yml @@ -354,7 +354,7 @@ jobs: test -x "$TEST_DIR/extracted/bin/ptoas" test -f "$TEST_DIR/extracted/ptoas/_cli.py" - compgen -G "$TEST_DIR/extracted/ptoas/_native*.so" >/dev/null + compgen -G "$TEST_DIR/extracted/ptoas/_core*.so" >/dev/null env -u PYTHONPATH -u DYLD_LIBRARY_PATH -u LD_LIBRARY_PATH \ "$TEST_DIR/extracted/bin/ptoas" --version diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4466730b55..4f5aaffaaf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,7 +104,6 @@ jobs: PTO_BUILD_DIR: ${{ github.workspace }}/build-assert PTO_INSTALL_DIR: ${{ github.workspace }}/install-assert PTOAS_VENV: ${{ github.workspace }}/.venv-ptoas-assert - MLIR_PYTHONPATH: ${{ github.workspace }}/llvm-project/llvm/build-assert/tools/mlir/python_packages/mlir_core LLVM_CACHE_FLAVOR: llvm21-assert-shared-mlirpy-hardening-v1 steps: - name: Checkout @@ -251,11 +250,9 @@ jobs: -DPython3_EXECUTABLE="${cmake4_venv}/bin/python" \ -DPython3_FIND_STRATEGY=LOCATION \ -Dpybind11_DIR="$("${cmake4_venv}/bin/python" -m pybind11 --cmakedir)" \ + -Dnanobind_DIR="$("${cmake4_venv}/bin/python" -m nanobind --cmake_dir)" \ -DMLIR_ENABLE_BINDINGS_PYTHON=ON \ - -DMLIR_PYTHON_PACKAGE_DIR="${MLIR_PYTHONPATH}" \ -DPTO_ENABLE_PYTHON_BINDING=ON \ - -DPTOAS_VALIDATE_CMAKE4_FETCHCONTENT_COMPAT=ON \ - -DPTOAS_ENABLE_WERROR=OFF \ -DBUILD_TESTING=ON \ -DCMAKE_C_COMPILER="${PTOAS_CMAKE_C_COMPILER}" \ -DCMAKE_CXX_COMPILER="${PTOAS_CMAKE_CXX_COMPILER}" \ diff --git a/.github/workflows/ci_sim.yml b/.github/workflows/ci_sim.yml index f57be126c2..b04add1de8 100644 --- a/.github/workflows/ci_sim.yml +++ b/.github/workflows/ci_sim.yml @@ -224,7 +224,6 @@ jobs: set -euo pipefail echo "LLVM_ROOT=${RUNNER_TOOL_CACHE}/llvm-project" >> "${GITHUB_ENV}" echo "LLVM_DIR=${RUNNER_TOOL_CACHE}/llvm-project/llvm/build-assert" >> "${GITHUB_ENV}" - echo "MLIR_PYTHONPATH=${RUNNER_TOOL_CACHE}/llvm-project/llvm/build-assert/tools/mlir/python_packages/mlir_core" >> "${GITHUB_ENV}" - name: Resolve PTODSL build directories shell: bash @@ -707,7 +706,6 @@ jobs: set -euo pipefail mkdir -p "${TILELANG_DSL_WORKSPACE}" export LLVM_BUILD_DIR="${LLVM_DIR}" - export MLIR_PYTHON_ROOT="${MLIR_PYTHONPATH}" if [[ "${{ github.event_name }}" == "pull_request" ]]; then ASCEND_HOME_PATH="${ASCEND_HOME_PATH}" \ PTOAS_BIN="${PTOAS_BIN}" \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eb0afc4c3..46999b107a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,64 +18,6 @@ if(POLICY CMP0169) set(CMAKE_POLICY_DEFAULT_CMP0169 OLD) endif() -function(ptoas_get_cmake_cache_value cache_file variable out_var) - if(NOT EXISTS "${cache_file}") - set(${out_var} "" PARENT_SCOPE) - return() - endif() - - file(STRINGS "${cache_file}" cache_lines - REGEX "^${variable}:[^=]*=") - if(cache_lines) - list(GET cache_lines 0 cache_line) - string(REGEX REPLACE "^[^=]*=" "" cache_value "${cache_line}") - set(${out_var} "${cache_value}" PARENT_SCOPE) - else() - set(${out_var} "" PARENT_SCOPE) - endif() -endfunction() - -function(ptoas_get_llvm_build_dir_from_llvm_dir out_var) - if(NOT DEFINED LLVM_DIR OR LLVM_DIR STREQUAL "") - set(${out_var} "" PARENT_SCOPE) - return() - endif() - - get_filename_component(llvm_cmake_dir "${LLVM_DIR}" REALPATH) - get_filename_component(llvm_build_dir "${llvm_cmake_dir}/../../.." REALPATH) - if(EXISTS "${llvm_build_dir}/CMakeCache.txt") - set(${out_var} "${llvm_build_dir}" PARENT_SCOPE) - else() - set(${out_var} "" PARENT_SCOPE) - endif() -endfunction() - -function(ptoas_preseed_compilers_from_llvm_cache) - ptoas_get_llvm_build_dir_from_llvm_dir(llvm_build_dir) - if(llvm_build_dir STREQUAL "") - return() - endif() - - set(llvm_cache "${llvm_build_dir}/CMakeCache.txt") - if(NOT DEFINED CMAKE_C_COMPILER AND "$ENV{CC}" STREQUAL "") - ptoas_get_cmake_cache_value("${llvm_cache}" "CMAKE_C_COMPILER" - llvm_c_compiler) - if(llvm_c_compiler AND EXISTS "${llvm_c_compiler}") - set(CMAKE_C_COMPILER "${llvm_c_compiler}" CACHE FILEPATH - "C compiler inherited from the configured LLVM build" FORCE) - endif() - endif() - - if(NOT DEFINED CMAKE_CXX_COMPILER AND "$ENV{CXX}" STREQUAL "") - ptoas_get_cmake_cache_value("${llvm_cache}" "CMAKE_CXX_COMPILER" - llvm_cxx_compiler) - if(llvm_cxx_compiler AND EXISTS "${llvm_cxx_compiler}") - set(CMAKE_CXX_COMPILER "${llvm_cxx_compiler}" CACHE FILEPATH - "C++ compiler inherited from the configured LLVM build" FORCE) - endif() - endif() -endfunction() - # Standard Python build backends pass environment variables through to CMake # but do not synthesize project-specific cache arguments. Accept the existing # LLVM_BUILD_DIR convention directly so `pip wheel .` and `pip install .` can @@ -92,16 +34,6 @@ if((NOT DEFINED MLIR_DIR OR MLIR_DIR STREQUAL "") set(MLIR_DIR "$ENV{LLVM_BUILD_DIR}/lib/cmake/mlir" CACHE PATH "MLIR package directory derived from LLVM_BUILD_DIR") endif() -if((NOT DEFINED MLIR_PYTHON_PACKAGE_DIR - OR MLIR_PYTHON_PACKAGE_DIR STREQUAL "") - AND DEFINED ENV{LLVM_BUILD_DIR} - AND NOT "$ENV{LLVM_BUILD_DIR}" STREQUAL "") - set(MLIR_PYTHON_PACKAGE_DIR - "$ENV{LLVM_BUILD_DIR}/tools/mlir/python_packages/mlir_core" - CACHE PATH "MLIR Python package derived from LLVM_BUILD_DIR") -endif() - -ptoas_preseed_compilers_from_llvm_cache() project(ptoas VERSION 0.53) set(PTOAS_VMI_VERSION "0.1.4") @@ -112,28 +44,6 @@ if(SKBUILD AND CMAKE_SYSTEM_NAME STREQUAL "Linux") include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/LinuxHardeningCache.cmake") endif() -option(PTOAS_VALIDATE_CMAKE4_FETCHCONTENT_COMPAT - "Validate CMake 4 compatibility for legacy FetchContent users" OFF) -if(PTOAS_VALIDATE_CMAKE4_FETCHCONTENT_COMPAT) - set(_ptoas_cmp0169_check_dir "${CMAKE_BINARY_DIR}/cmake-cmp0169-compat") - file(MAKE_DIRECTORY "${_ptoas_cmp0169_check_dir}/nested/cann-cmake") - file(WRITE "${_ptoas_cmp0169_check_dir}/nested/cann-cmake/CMakeLists.txt" - "cmake_minimum_required(VERSION 3.20)\n" - "project(ptoas_cmp0169_cann_cmake_fixture NONE)\n") - file(WRITE "${_ptoas_cmp0169_check_dir}/nested/CMakeLists.txt" [=[ -cmake_minimum_required(VERSION 3.20) -project(ptoas_cmp0169_nested_fixture NONE) -include(FetchContent) -FetchContent_Declare(cann-cmake SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/cann-cmake") -FetchContent_GetProperties(cann-cmake) -if(NOT cann-cmake_POPULATED) - FetchContent_Populate(cann-cmake) -endif() -]=]) - add_subdirectory("${_ptoas_cmp0169_check_dir}/nested" - "${_ptoas_cmp0169_check_dir}/nested-build") -endif() - set(PTOAS_RELEASE_VERSION_OVERRIDE "" CACHE STRING "Override the version printed by ptoas --version") set(PTOAS_EXACT_GIT_TAG_VERSION "") @@ -186,33 +96,6 @@ if(NOT LLVM_VERSION_MAJOR STREQUAL "21") "LLVM ${LLVM_PACKAGE_VERSION}. Please point LLVM_DIR/MLIR_DIR to an " "LLVM 21 build, for example vpto-dev/llvm-project:feature-vpto-llvm21.") endif() -get_filename_component(PTO_LLVM_BUILD_LIBRARY_DIR - "${LLVM_BUILD_LIBRARY_DIR}" REALPATH) -ptoas_get_llvm_build_dir_from_llvm_dir(PTO_LLVM_BUILD_DIR) -if(PTO_LLVM_BUILD_DIR) - ptoas_get_cmake_cache_value("${PTO_LLVM_BUILD_DIR}/CMakeCache.txt" - "CMAKE_CXX_COMPILER" - PTO_LLVM_CXX_COMPILER) -endif() -if(PTO_LLVM_CXX_COMPILER AND EXISTS "${PTO_LLVM_CXX_COMPILER}") - execute_process( - COMMAND "${PTO_LLVM_CXX_COMPILER}" --version - OUTPUT_VARIABLE PTO_LLVM_CXX_VERSION_TEXT - ERROR_VARIABLE PTO_LLVM_CXX_VERSION_TEXT - OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_STRIP_TRAILING_WHITESPACE) - if(PTO_LLVM_CXX_VERSION_TEXT MATCHES "[Cc]lang" - AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - message(FATAL_ERROR - "PTOAS is being configured with GNU C++ (${CMAKE_CXX_COMPILER}), " - "but the selected LLVM build was compiled with a Clang-compatible " - "compiler (${PTO_LLVM_CXX_COMPILER}). MLIR TypeID fallback strings are " - "compiler-family sensitive across shared libraries; use " - "-DCMAKE_CXX_COMPILER=${PTO_LLVM_CXX_COMPILER} or leave the compiler " - "unset so PTOAS can inherit it from LLVM_DIR.") - endif() -endif() - # 将 LLVM 模块路径加入 CMake 搜索路径 list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") @@ -235,13 +118,14 @@ include(AddMLIR) # 3. 配置构建环境 # ========================================================= # Keep warning policy in CMake so CI, wheel, and external build entrypoints -# all enforce the same diagnostics contract. +# all enforce the same diagnostics contract. Warnings are errors by default; +# directories that compile only third-party sources may opt out narrowly. option(PTOAS_ENABLE_WERROR "Treat PTOAS warnings as errors" ON) if(PTOAS_ENABLE_WERROR) if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") - add_compile_options($<$:-Werror>) + add_compile_options("$<$:-Werror>") elseif(MSVC) - add_compile_options($<$:/WX>) + add_compile_options("$<$:/WX>") endif() endif() @@ -253,12 +137,12 @@ if(APPLE) endforeach() endif() -include_directories(${LLVM_INCLUDE_DIRS}) -include_directories(${MLIR_INCLUDE_DIRS}) +include_directories(SYSTEM ${LLVM_INCLUDE_DIRS}) +include_directories(SYSTEM ${MLIR_INCLUDE_DIRS}) include_directories(${PROJECT_SOURCE_DIR}/include) include_directories(${PROJECT_BINARY_DIR}/include) -link_directories(${PTO_LLVM_BUILD_LIBRARY_DIR}) +link_directories(${LLVM_BUILD_LIBRARY_DIR}) add_definitions(${LLVM_DEFINITIONS}) # ========================================================= @@ -270,30 +154,9 @@ include(CTest) option(PTO_ENABLE_PYTHON_BINDING "Enable Python bindings" ON) if(PTO_ENABLE_PYTHON_BINDING) - find_package(Python3 COMPONENTS Interpreter Development.Module REQUIRED) - find_package(pybind11 CONFIG REQUIRED) - - # A wheel must include the base MLIR Python package in addition to PTOAS's - # generated dialect modules. Normal CMake installs continue to use the LLVM - # installation supplied by the user and therefore do not duplicate it. - if(SKBUILD) - if(NOT MLIR_PYTHON_PACKAGE_DIR - OR NOT EXISTS "${MLIR_PYTHON_PACKAGE_DIR}/mlir") - message(FATAL_ERROR - "MLIR_PYTHON_PACKAGE_DIR must contain the MLIR Python package when " - "building a PTOAS wheel") - endif() - install( - DIRECTORY "${MLIR_PYTHON_PACKAGE_DIR}/mlir" - DESTINATION "." - COMPONENT PTOAS_Python - PATTERN "__pycache__" EXCLUDE - PATTERN "*.pyc" EXCLUDE - ) - endif() - - # 设置 Python 扩展的输出目录,方便调试 - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/python/pto) + include(MLIRDetectPythonEnv) + include(AddMLIRPython) + mlir_configure_python_dev_packages() add_subdirectory(ptodsl) add_subdirectory(tilelang-dsl) @@ -303,8 +166,8 @@ endif() # 4. 添加子目录 # ========================================================= if(BUILD_TESTING AND NOT TARGET ptoas_runtime_deps) - # Define this aggregate target before tools/ptoas runs so it can attach - # ptoas_runtime as a dependency during configure. + # Define this aggregate target before tools/ptoas runs so it can attach the + # staged ptoas._core package as a dependency during configure. add_custom_target(ptoas_runtime_deps) endif() add_subdirectory(include) @@ -317,17 +180,13 @@ add_subdirectory(tools) if(BUILD_TESTING) enable_testing() if(PTO_ENABLE_PYTHON_BINDING) - get_filename_component(_llvm_root "${LLVM_DIR}/../../.." ABSOLUTE) get_filename_component(_pto_python_bin_dir "${Python3_EXECUTABLE}" DIRECTORY) set(_pto_python_test_pythonpath - "${CMAKE_BINARY_DIR}/python:${MLIR_PYTHON_PACKAGE_DIR}:${CMAKE_INSTALL_PREFIX}:$ENV{PYTHONPATH}" + "${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH}" ) - if(DEFINED ENV{PTO_INSTALL_DIR} AND NOT "$ENV{PTO_INSTALL_DIR}" STREQUAL "") - set(_pto_python_test_pythonpath "$ENV{PTO_INSTALL_DIR}:${_pto_python_test_pythonpath}") - endif() set(_pto_python_test_env "PYTHONPATH=${_pto_python_test_pythonpath}" - "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:${_llvm_root}/lib:${CMAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}" + "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:${LLVM_BUILD_LIBRARY_DIR}:${CMAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}" "PATH=${CMAKE_BINARY_DIR}/tools/ptoas:${CMAKE_INSTALL_PREFIX}/bin:${_pto_python_bin_dir}:$ENV{PATH}" "PTOAS_BIN=${CMAKE_BINARY_DIR}/tools/ptoas/ptoas" ) @@ -372,7 +231,12 @@ if(BUILD_TESTING) add_subdirectory(test/lit) set(_pto_check_ctest_depends) - foreach(_target IN ITEMS PTOPythonModules ptoas_runtime_deps ptobc) + foreach(_target IN ITEMS + PTOAS_Python + PTODSLPackage + TileLangDSLPackage + ptoas_runtime_deps + ptobc) if(TARGET ${_target}) list(APPEND _pto_check_ctest_depends ${_target}) endif() diff --git a/README.md b/README.md index b1d834813a..e17ca864b3 100644 --- a/README.md +++ b/README.md @@ -190,7 +190,7 @@ from mlir.dialects import pto as mlir_pto 下面这组环境变量主要用于**直接消费 build/install tree** 的场景,例如: - 不走 pip 安装,直接调试 CMake install 输出 -- 调试 `ptoas` CLI、动态库搜索路径或 MLIR Python overlay +- 调试 `ptoas` CLI、动态库搜索路径或 build-tree Python package - 复用仓库脚本做 compile-only / simulator / sample 生成 您可以将以下命令添加到 `.bashrc` 或启动脚本中。 @@ -198,11 +198,9 @@ from mlir.dialects import pto as mlir_pto ```bash # --- 运行时变量配置 (基于之前定义的路径) --- -# 1. Python Path: 拼接 MLIR Core 和 PTO Core -# 这样在 python 中 import mlir.dialects.pto 时能正确找到 -export MLIR_PYTHON_ROOT=$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core -export PTO_PYTHON_ROOT=$PTO_INSTALL_DIR/ -export PYTHONPATH=$PTO_PYTHON_ROOT:$MLIR_PYTHON_ROOT:$PYTHONPATH +# 1. Python Path: PTOAS 的 build/install tree 已包含统一的 MLIR + PTO package +export PTO_PYTHON_ROOT=$PTO_INSTALL_DIR +export PYTHONPATH=$PTO_PYTHON_ROOT:$PYTHONPATH # 2. Library Path: 确保能加载 LLVM 和 PTO 的动态库 export LD_LIBRARY_PATH=$LLVM_BUILD_DIR/lib:$PTO_INSTALL_DIR/lib:$LD_LIBRARY_PATH diff --git a/docker/collect_ptoas_dist.sh b/docker/collect_ptoas_dist.sh index 798260e036..d682f842bd 100755 --- a/docker/collect_ptoas_dist.sh +++ b/docker/collect_ptoas_dist.sh @@ -149,9 +149,9 @@ cp -R "${PTOAS_PACKAGE_SRC_DIR}" "${PTOAS_PACKAGE_DIST_DIR}" cp "$PTOAS_BIN" "${PTOAS_DIST_DIR}/bin/ptoas" chmod +x "${PTOAS_DIST_DIR}/bin/ptoas" -PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}" -maxdepth 1 -type f -name '_native*.so' -print -quit)" +PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}" -maxdepth 1 -type f -name '_core*.so' -print -quit)" if [ -z "${PTOAS_NATIVE_MODULE}" ]; then - echo "Error: packaged ptoas._native extension not found" >&2 + echo "Error: packaged ptoas._core extension not found" >&2 exit 1 fi diff --git a/docker/collect_ptoas_dist_mac.sh b/docker/collect_ptoas_dist_mac.sh index a3fb2c13d2..6685930f5f 100644 --- a/docker/collect_ptoas_dist_mac.sh +++ b/docker/collect_ptoas_dist_mac.sh @@ -67,9 +67,9 @@ cp -R "${PTOAS_PACKAGE_SRC_DIR}" "${PTOAS_PACKAGE_DIST_DIR}" cp -fL "$PTOAS_BIN" "${PTOAS_DIST_DIR}/bin/ptoas" chmod +x "${PTOAS_DIST_DIR}/bin/ptoas" -PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}" -maxdepth 1 -type f -name '_native*.so' -print -quit)" +PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}" -maxdepth 1 -type f -name '_core*.so' -print -quit)" if [ -z "${PTOAS_NATIVE_MODULE}" ]; then - echo "Error: packaged ptoas._native extension not found" >&2 + echo "Error: packaged ptoas._core extension not found" >&2 exit 1 fi diff --git a/docker/test_wheel_imports.sh b/docker/test_wheel_imports.sh index f06b6938b4..df2a30487c 100755 --- a/docker/test_wheel_imports.sh +++ b/docker/test_wheel_imports.sh @@ -89,7 +89,7 @@ echo "Testing ptodsl public imports..." "$PYTHON_BIN" -c "from ptodsl import pto, scalar; print('ptodsl public imports imported successfully')" echo "Testing installed ptoas console entry..." -"$PYTHON_BIN" -c "from ptoas import _native; print(f'ptoas native extension imported successfully from {_native.__file__}')" +"$PYTHON_BIN" -c "from ptoas import _core; print(f'ptoas native extension imported successfully from {_core.__file__}')" PTOAS_VERSION_OUTPUT="$(ptoas --version | tr -d '\r')" echo "${PTOAS_VERSION_OUTPUT}" EXPECTED_PTOAS_CLI_VERSION="${PTOAS_CLI_VERSION:-${PTOAS_VERSION:-}}" diff --git a/docker/validate_wheel_payload.py b/docker/validate_wheel_payload.py index 2d4879d0d6..0ddcda8a3d 100644 --- a/docker/validate_wheel_payload.py +++ b/docker/validate_wheel_payload.py @@ -28,7 +28,7 @@ PTOAS_ENTRYPOINT_TARGET = "ptoas._cli:main" WHEEL_GLOB = "ptoas*.whl" NATIVE_MODULE_PATHS = { - f"ptoas/_native{suffix}" + f"ptoas/_core{suffix}" for suffix in importlib.machinery.EXTENSION_SUFFIXES } @@ -89,7 +89,7 @@ def validate_wheel_payload(wheel: Path) -> None: native_modules = sorted(NATIVE_MODULE_PATHS & names) if len(native_modules) != 1: raise SystemExit( - "wheel must contain exactly one importable ptoas._native extension, " + "wheel must contain exactly one importable ptoas._core extension, " f"found {native_modules}" ) diff --git a/docs/build_with_installed_llvm.md b/docs/build_with_installed_llvm.md index 7b09173b27..807485d898 100644 --- a/docs/build_with_installed_llvm.md +++ b/docs/build_with_installed_llvm.md @@ -73,15 +73,15 @@ README 第 3.2 节是 LLVM/MLIR 的下载和编译步骤。当前场景下 LLVM 这里沿用 README 第 3.3 节的流程,但 `LLVM_DIR` 和 `MLIR_DIR` 需要改为 `/opt/llvm/lib/cmake/...`。 -`MLIR_PYTHON_PACKAGE_DIR` 仍然指向 LLVM 的 MLIR Python package。PTOAS 的 -`pto.py`、`_pto_ops_gen.py` 和 `_pto.cpython-*.so` 会安装到 -`CMAKE_INSTALL_PREFIX`,不会写入共享的 LLVM 安装目录。 +PTOAS 使用 MLIR 导出的 Python source-set 在自己的 build/install tree 中 +组装完整的 `mlir` package,不再复制或 overlay LLVM build tree 中已经生成的 +Python package。 ```bash cd "$PTO_SOURCE_DIR" -# 1. 获取 pybind11 的 CMake 路径 -export PYBIND11_CMAKE_DIR=$(python3 -m pybind11 --cmakedir) +# 1. 安装 MLIR Python binding 的构建依赖 +python3 -m pip install 'pybind11<3' 'nanobind>=2.4' # 2. 配置 CMake cmake -G Ninja \ @@ -91,9 +91,7 @@ cmake -G Ninja \ -DMLIR_DIR=$LLVM_INSTALL_DIR/lib/cmake/mlir \ -DPython3_EXECUTABLE=$(which python3) \ -DPython3_FIND_STRATEGY=LOCATION \ - -Dpybind11_DIR="${PYBIND11_CMAKE_DIR}" \ -DMLIR_ENABLE_BINDINGS_PYTHON=ON \ - -DMLIR_PYTHON_PACKAGE_DIR="$LLVM_INSTALL_DIR/python_packages/mlir_core" \ -DCMAKE_INSTALL_PREFIX="$PTO_INSTALL_DIR" # 3. 编译并安装 @@ -108,11 +106,11 @@ cmake --install build - build 目录: - `$PTO_SOURCE_DIR/build/tools/ptoas/ptoas` - `$PTO_SOURCE_DIR/build/tools/ptobc/ptobc` - - `$PTO_SOURCE_DIR/build/python/mlir/_mlir_libs/_pto.cpython-*.so` + - `$PTO_SOURCE_DIR/build/python/ptoas/_core.cpython-*.so` - `$PTO_SOURCE_DIR/build/python/mlir/dialects/pto.py` - install 目录: - `$PTO_INSTALL_DIR/bin/ptoas` - - `$PTO_INSTALL_DIR/mlir/_mlir_libs/_pto.cpython-*.so` + - `$PTO_INSTALL_DIR/ptoas/_core.cpython-*.so` - `$PTO_INSTALL_DIR/mlir/dialects/pto.py` - `$PTO_INSTALL_DIR/share/ptoas/oplib/level3` @@ -122,7 +120,7 @@ cmake --install build ```bash export PATH=$PTO_SOURCE_DIR/build/tools/ptoas:$PATH -export PYTHONPATH=$LLVM_INSTALL_DIR/python_packages/mlir_core:$PTO_SOURCE_DIR/build/python:$PYTHONPATH +export PYTHONPATH=$PTO_SOURCE_DIR/build/python:$PYTHONPATH export LD_LIBRARY_PATH=$LLVM_INSTALL_DIR/lib:$PTO_SOURCE_DIR/build/lib:$LD_LIBRARY_PATH ``` @@ -130,7 +128,7 @@ export LD_LIBRARY_PATH=$LLVM_INSTALL_DIR/lib:$PTO_SOURCE_DIR/build/lib:$LD_LIBRA ```bash export PATH=$PTO_INSTALL_DIR/bin:$PATH -export PYTHONPATH=$LLVM_INSTALL_DIR/python_packages/mlir_core:$PTO_INSTALL_DIR:$PYTHONPATH +export PYTHONPATH=$PTO_INSTALL_DIR:$PYTHONPATH export LD_LIBRARY_PATH=$LLVM_INSTALL_DIR/lib:$PTO_INSTALL_DIR/lib:$LD_LIBRARY_PATH ``` @@ -145,12 +143,11 @@ export LD_LIBRARY_PATH=$LLVM_INSTALL_DIR/lib:$PTO_INSTALL_DIR/lib:$LD_LIBRARY_PA - `LLVM_DIR=/opt/llvm/lib/cmake/llvm` - `MLIR_DIR=/opt/llvm/lib/cmake/mlir` -- `MLIR_PYTHON_PACKAGE_DIR=/opt/llvm/python_packages/mlir_core` - `CMAKE_INSTALL_PREFIX=$PTO_INSTALL_DIR` 最小验证结果: - build 版 `ptoas --version` 输出 `ptoas 0.22` - build 版 `ptoas` 可成功处理 `test/lit/pto/empty_func.pto` -- install 版 Python 绑定可在 `PYTHONPATH=/opt/llvm/python_packages/mlir_core:$PTO_INSTALL_DIR` 下正常导入 +- install 版 Python 绑定可在 `PYTHONPATH=$PTO_INSTALL_DIR` 下正常导入 - 若 install 版 `ptoas` 配合 `LD_LIBRARY_PATH=/opt/llvm/lib:$PTO_INSTALL_DIR/lib`,可正常执行 diff --git a/docs/designs/ci-board-validation-guide.md b/docs/designs/ci-board-validation-guide.md index bb963841d9..ea02051bfc 100644 --- a/docs/designs/ci-board-validation-guide.md +++ b/docs/designs/ci-board-validation-guide.md @@ -103,16 +103,14 @@ ninja -C llvm/build-shared ```bash export LLVM_DIR=$PWD/llvm-project/llvm/build-shared export PTO_INSTALL_DIR=$PWD/install -export PYBIND11_CMAKE_DIR="$(python3 -m pybind11 --cmakedir)" +python3 -m pip install 'pybind11<3' 'nanobind>=2.4' cmake -G Ninja -S . -B build \ -DLLVM_DIR="$LLVM_DIR/lib/cmake/llvm" \ -DMLIR_DIR="$LLVM_DIR/lib/cmake/mlir" \ -DPython3_EXECUTABLE=python3 \ -DPython3_FIND_STRATEGY=LOCATION \ - -Dpybind11_DIR="$PYBIND11_CMAKE_DIR" \ -DMLIR_ENABLE_BINDINGS_PYTHON=ON \ - -DMLIR_PYTHON_PACKAGE_DIR="$LLVM_DIR/tools/mlir/python_packages/mlir_core" \ -DCMAKE_INSTALL_PREFIX="$PTO_INSTALL_DIR" \ -DCMAKE_BUILD_TYPE=Release @@ -124,9 +122,8 @@ ninja -C build install ### 3.3 跑样例生成链路 ```bash -export MLIR_PYTHON_ROOT=$PWD/llvm-project/llvm/build-shared/tools/mlir/python_packages/mlir_core export PTO_PYTHON_ROOT=$PWD/install -export PYTHONPATH="$MLIR_PYTHON_ROOT:$PTO_PYTHON_ROOT:${PYTHONPATH:-}" +export PYTHONPATH="$PTO_PYTHON_ROOT:${PYTHONPATH:-}" export LD_LIBRARY_PATH="$LLVM_DIR/lib:$PTO_INSTALL_DIR/lib:${LD_LIBRARY_PATH:-}" export PTOAS_BIN=$PWD/build/tools/ptoas/ptoas diff --git a/docs/designs/ptoas-python-launcher-layout.md b/docs/designs/ptoas-python-launcher-layout.md index 171b5b7187..f85b9014e4 100644 --- a/docs/designs/ptoas-python-launcher-layout.md +++ b/docs/designs/ptoas-python-launcher-layout.md @@ -16,18 +16,21 @@ PTOAS without exposing these implementation details. ## Entry Model -The wheel, build-tree, and install-tree launchers use the standard Python -console-script and native-extension model: +The wheel launcher uses the standard Python console-script and native-extension +model. Build-tree and install-tree entrypoints are narrow CMake adapters around +the same Python CLI and native extension: ```text wheel console script -> ptoas._cli.main() CMake tree wrapper -> add its own Python root -> ptoas._cli.launch() -both -> import ptoas._native -> ptoas._native.main(argv) +both -> import ptoas._core -> ptoas._core.main(argv) ``` -`ptoas._native` is built with `pybind11_add_module`. CMake and Python therefore -own the platform and ABI-specific filename. Launcher and packaging code refer to -the import name and never construct `.so`, `.dylib`, or `.pyd` paths. +`ptoas._core` is the single PTOAS-owned native extension. It provides the +compiler entry point and the native PTO dialect bindings used by the public +`mlir.dialects.pto` facade. CMake and Python own the platform and ABI-specific +filename. Launcher and packaging code refer to the import name and never +construct `.so`, `.dylib`, or `.pyd` paths. The LLVM-based driver implementation is compiled as an object library so it can use LLVM's RTTI and exception settings independently from pybind11. Those @@ -73,7 +76,7 @@ The build-tree wrapper resolves only its own generated outputs: - wrapper: `/tools/ptoas/ptoas` - Python root: `/python` -- native module: importable as `ptoas._native` from the Python root +- native module: importable as `ptoas._core` from the Python root - TileOps: `/python/ptoas/_runtime/share/ptoas/TileOps` Missing Python packages or TileOps resources are hard layout errors. The @@ -86,7 +89,7 @@ The install-tree wrapper resolves only files under the same prefix: - wrapper: `/bin/ptoas` - Python root: `` -- native module: importable as `ptoas._native` from the Python root +- native module: importable as `ptoas._core` from the Python root - TileOps: `/ptoas/_runtime/share/ptoas/TileOps` The install-tree wrapper only adds `` to `sys.path`, then delegates to @@ -104,7 +107,7 @@ Standalone compiler archives contain the installed Python wrapper and package: ```text bin/ptoas ptoas/_cli.py -ptoas/_native..so +ptoas/_core..so ptoas/_runtime/share/ptoas/TileOps lib/ tilelang_dsl/ @@ -112,7 +115,7 @@ tilelang_dsl/ The archive requires a Python interpreter compatible with the packaged extension ABI. `bin/ptoas` adds the archive root to `sys.path`, then uses the -same `ptoas._cli -> ptoas._native` path as the install tree. Linux archives set +same `ptoas._cli -> ptoas._core` path as the install tree. Linux archives set the extension runtime path to `$ORIGIN/../lib`; macOS archives rewrite the extension's install names relative to its package directory. diff --git a/docs/no_npu_compile_only_guide_zh.md b/docs/no_npu_compile_only_guide_zh.md index a23b8024ff..6f2b5b75cd 100644 --- a/docs/no_npu_compile_only_guide_zh.md +++ b/docs/no_npu_compile_only_guide_zh.md @@ -187,7 +187,7 @@ export PTOAS_BIN=$PWD/build/tools/ptoas/ptoas export PTOBC_BIN=$PWD/build/tools/ptobc/ptobc export PYTHON_BIN=/usr/bin/python3 export PTOAS_OUT_DIR="$PAYLOAD_ROOT/test/samples" -export PYTHONPATH="$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core:$PTO_INSTALL_DIR:${PYTHONPATH:-}" +export PYTHONPATH="$PTO_INSTALL_DIR:${PYTHONPATH:-}" export LD_LIBRARY_PATH="$LLVM_BUILD_DIR/lib:$PTO_INSTALL_DIR/lib:${LD_LIBRARY_PATH:-}" export SOC_VERSION="$TARGET_SOC_VERSION" diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index f167cc3791..c0bd2b19d4 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -6,109 +6,117 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -# lib/Bindings/Python/CMakeLists.txt - -find_package(Python3 COMPONENTS Interpreter Development.Module REQUIRED) -find_package(pybind11 CONFIG REQUIRED) - -include(TableGen) -include(AddMLIR) - -get_filename_component(PTO_LLVM_BUILD_LIBRARY_DIR - "${LLVM_BUILD_LIBRARY_DIR}" REALPATH) - -# ---- 1) Python native extension: mlir._mlir_libs._pto ---- -pybind11_add_module(_pto MODULE - PTOModule.cpp -) - -target_include_directories(_pto PRIVATE - ${CMAKE_SOURCE_DIR}/include -) +include(AddMLIRPython) + +# This directory materializes C++ sources exported by upstream MLIR. PTOAS +# keeps -Werror enabled globally, but upstream sources are not part of the +# project warning contract. Scope the exception to this directory; the +# project-owned ptoas._core extension is built in tools/ptoas and therefore +# remains under -Werror. +if(PTOAS_ENABLE_WERROR) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") + add_compile_options("$<$:-Wno-error>") + elseif(MSVC) + add_compile_options("$<$:/WX->") + endif() +endif() -target_link_options(_pto PRIVATE) +# Build the `mlir` Python package from MLIR's exported source declarations and +# add PTOAS's dialect to the same package. This is the composition mechanism +# supported by AddMLIRPython and avoids copying or overlaying another build's +# package tree. +set(PTOAS_MLIR_PYTHON_PACKAGE_DIR "${CMAKE_BINARY_DIR}/python/mlir") -target_link_libraries(_pto PRIVATE +declare_mlir_python_sources(PTOASPythonSources) - PTOCAPI - PTOIR - MLIRIR - MLIRCAPIIR - MLIRSupport - MLIRArithDialect - MLIRMemRefDialect - MLIRSCFDialect - MLIRDestinationStyleOpInterface - MLIRInferTypeOpInterface - MLIRSideEffectInterfaces - MLIRCallInterfaces - MLIRControlFlowInterfaces - MLIRLoopLikeInterface - MLIRViewLikeInterface - MLIRFunctionInterfaces - MLIRLLVMDialect +declare_mlir_dialect_python_bindings( + ADD_TO_PARENT PTOASPythonSources + ROOT_DIR "${CMAKE_SOURCE_DIR}/python/pto" + TD_FILE dialects/PTOOps.td + SOURCES dialects/pto.py + DIALECT_NAME pto ) -# 关键:放到 mlir/_mlir_libs 下(匹配 MLIR dialect python 的 import 习惯) -set_target_properties(_pto PROPERTIES - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/python/mlir/_mlir_libs" - BUILD_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}" - INSTALL_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}" +# Use MLIR's standard site-initializer hook to seed each Python Context with +# the selected upstream dialects shipped by PTOAS. Declaring the extension in +# the Python source graph lets AddMLIRPython own its build, installation, and +# common-CAPI dependency collection. +set(PTOAS_PYTHON_REGISTRATION_SOURCE + "${CMAKE_CURRENT_SOURCE_DIR}/PythonRegistration.cpp") +declare_mlir_python_extension(PTOASPythonSources.Registration + MODULE_NAME _site_initialize_0 + ADD_TO_PARENT PTOASPythonSources + ROOT_DIR "${CMAKE_CURRENT_SOURCE_DIR}" + PYTHON_BINDINGS_LIBRARY nanobind + SOURCES PythonRegistration.cpp + EMBED_CAPI_LINK_LIBS + MLIRCAPIArith + MLIRCAPIFunc + MLIRCAPILLVM + MLIRCAPIMath + MLIRCAPIMemRef + MLIRCAPISCF ) -# macOS: 避免 ld 警告 "-undefined suppress is deprecated",仅保留 -undefined dynamic_lookup -if(APPLE) - target_link_options(_pto PRIVATE "LINKER:-undefined,dynamic_lookup") -endif() -if(NOT MLIR_PYTHON_PACKAGE_DIR) - message(FATAL_ERROR "MLIR_PYTHON_PACKAGE_DIR must be set when PTO_ENABLE_PYTHON_BINDING=ON") +# This directory otherwise materializes only upstream MLIR/nanobind C++ +# sources under -Wno-error. Keep the project-owned registration source under +# PTOAS's default strict warning policy while retaining one declarative Python +# package graph. +if(PTOAS_ENABLE_WERROR) + if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang|AppleClang") + set_property(SOURCE "${PTOAS_PYTHON_REGISTRATION_SOURCE}" APPEND PROPERTY + COMPILE_OPTIONS -Werror) + elseif(MSVC) + set_property(SOURCE "${PTOAS_PYTHON_REGISTRATION_SOURCE}" APPEND PROPERTY + COMPILE_OPTIONS /WX) + endif() endif() -install(TARGETS _pto - LIBRARY DESTINATION "mlir/_mlir_libs" - COMPONENT PTOAS_Python -) - -# ---- 2) Generate ODS Python op bindings: _pto_ops_gen.py ---- -set(PTO_TD_DIR "${CMAKE_SOURCE_DIR}/include/PTO/IR") -set(LLVM_TARGET_DEFINITIONS ${PTO_TD_DIR}/PTOOps.td) - -mlir_tablegen(_pto_ops_gen.py - -gen-python-op-bindings - --bind-dialect=pto +# Package only the upstream Python APIs used by PTOAS and PTODSL. In +# particular, do not instantiate MLIRPythonSources or RegisterEverything: +# downstream MLIR packages are expected to select their public dialect set +# explicitly rather than linking every upstream dialect, translation and pass. +set(PTOAS_MLIR_PYTHON_SOURCE_SETS + MLIRPythonSources.Core + MLIRPythonSources.Dialects.arith + MLIRPythonSources.Dialects.builtin + MLIRPythonSources.Dialects.func + MLIRPythonSources.Dialects.llvm + MLIRPythonSources.Dialects.math + MLIRPythonSources.Dialects.memref + MLIRPythonSources.Dialects.scf ) -add_public_tablegen_target(PTOPythonGen) -add_dependencies(_pto PTOPythonGen) - -# Stable aggregate target used by CTest and developer workflows. Keep the -# dialect binding generation owned by this directory so there is only one -# _pto_ops_gen.py producer. -add_custom_target(PTOPythonModules) -add_dependencies(PTOPythonModules _pto) - -# ---- 3) Copy generated python + handwritten pto.py into build/python ---- -set(PTO_PY_SRC "${CMAKE_SOURCE_DIR}/python/pto/dialects/pto.py") - -add_custom_command(TARGET _pto POST_BUILD - COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/python/mlir/dialects" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${PTO_PY_SRC}" - "${CMAKE_BINARY_DIR}/python/mlir/dialects/pto.py" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "${CMAKE_CURRENT_BINARY_DIR}/_pto_ops_gen.py" - "${CMAKE_BINARY_DIR}/python/mlir/dialects/_pto_ops_gen.py" - VERBATIM +# Keep one common CAPI DSO for the upstream MLIR Python package. PTOAS owns a +# single ptoas._core extension, built in tools/ptoas, which links this common +# CAPI and contains both the PTO dialect implementation and compiler driver. +add_mlir_python_common_capi_library(PTOASPythonCAPI + INSTALL_COMPONENT PTOAS_Python + INSTALL_DESTINATION "mlir/_mlir_libs" + OUTPUT_DIRECTORY "${PTOAS_MLIR_PYTHON_PACKAGE_DIR}/_mlir_libs" + RELATIVE_INSTALL_ROOT "../../../.." + DECLARED_HEADERS + MLIRPythonCAPI.HeaderSources + DECLARED_SOURCES + ${PTOAS_MLIR_PYTHON_SOURCE_SETS} + PTOASPythonSources + # MLIRPythonExtension.Core currently obtains its rewrite CAPI through + # RegisterEverything. PTOAS deliberately omits RegisterEverything, so retain + # the missing direct dependency until upstream Core declares it itself. + EMBED_LIBS + MLIRCAPITransforms ) - -install(FILES - "${PTO_PY_SRC}" - "${CMAKE_CURRENT_BINARY_DIR}/_pto_ops_gen.py" - DESTINATION mlir/dialects - COMPONENT PTOAS_Python +# Imported MLIR aggregate objects do not expose a source language from which +# CMake can infer the linker driver. The common CAPI is C++, matching MLIR's +# own in-tree target. +set_property(TARGET PTOASPythonCAPI PROPERTY LINKER_LANGUAGE CXX) + +add_mlir_python_modules(PTOAS_Python + ROOT_PREFIX "${PTOAS_MLIR_PYTHON_PACKAGE_DIR}" + INSTALL_PREFIX mlir + DECLARED_SOURCES + ${PTOAS_MLIR_PYTHON_SOURCE_SETS} + PTOASPythonSources + COMMON_CAPI_LINK_LIBS + PTOASPythonCAPI ) diff --git a/lib/Bindings/Python/PTOModule.cpp b/lib/Bindings/Python/PTOModule.cpp index 432d08e262..8d6d061b29 100644 --- a/lib/Bindings/Python/PTOModule.cpp +++ b/lib/Bindings/Python/PTOModule.cpp @@ -8,14 +8,13 @@ //===- DialectPTO.cpp -----------------------------------------------------===// // -// Python bindings for the PTO dialect types (pybind11 version). -// -// This file is intended to be built via declare_mlir_python_extension(...) -// with PYTHON_BINDINGS_LIBRARY pybind11, and linked with MLIRCAPIPTO. +// Python bindings for the PTO dialect types in the project-owned ptoas._core +// extension. The public Python facade remains mlir.dialects.pto. // //===----------------------------------------------------------------------===// -#include "pybind11/pybind11.h" +#include "PTOModule.h" + #include "pybind11/stl.h" #include "mlir/Bindings/Python/PybindAdaptors.h" #include "mlir/CAPI/IR.h" @@ -119,8 +118,7 @@ void populatePTODialectSubmodule(pybind11::module &m) { (void)m; } -static void bindPTOModule(pybind11::module &m) { - m.doc() = "PTO dialect Python bindings (pybind11)."; +void mlir::pto::python::populatePTODialectBindings(pybind11::module_ &m) { // -------------------------------------------------------------------------- // Dialect registration helper @@ -1440,7 +1438,3 @@ static void bindPTOModule(pybind11::module &m) { populatePTODialectSubmodule(m); } - -PYBIND11_MODULE(_pto, m) { - bindPTOModule(m); -} diff --git a/lib/Bindings/Python/PTOModule.h b/lib/Bindings/Python/PTOModule.h new file mode 100644 index 0000000000..6fdf04a2b4 --- /dev/null +++ b/lib/Bindings/Python/PTOModule.h @@ -0,0 +1,22 @@ +// Copyright (c) 2026 Huawei Technologies Co., Ltd. +// This program is free software, you can redistribute it and/or modify it under the terms and conditions of +// CANN Open Software License Agreement Version 2.0 (the "License"). +// Please refer to the License for details. You may not use this file except in compliance with the License. +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// See LICENSE in the root of the software repository for the full text of the License. + +#ifndef PTOAS_LIB_BINDINGS_PYTHON_PTOMODULE_H +#define PTOAS_LIB_BINDINGS_PYTHON_PTOMODULE_H + +#include "pybind11/pybind11.h" + +namespace mlir::pto::python { + +/// Adds PTO dialect types, attributes, enums, and registration helpers to the +/// project-owned ptoas._core extension module. +void populatePTODialectBindings(pybind11::module_ &module); + +} // namespace mlir::pto::python + +#endif // PTOAS_LIB_BINDINGS_PYTHON_PTOMODULE_H diff --git a/lib/Bindings/Python/PythonRegistration.cpp b/lib/Bindings/Python/PythonRegistration.cpp new file mode 100644 index 0000000000..5fec0b0e7e --- /dev/null +++ b/lib/Bindings/Python/PythonRegistration.cpp @@ -0,0 +1,28 @@ +// Copyright (c) 2026 Huawei Technologies Co., Ltd. +// This program is free software, you can redistribute it and/or modify it under the terms and conditions of +// CANN Open Software License Agreement Version 2.0 (the "License"). +// Please refer to the License for details. You may not use this file except in compliance with the License. +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// See LICENSE in the root of the software repository for the full text of the License. + +#include "mlir-c/Dialect/Arith.h" +#include "mlir-c/Dialect/Func.h" +#include "mlir-c/Dialect/LLVM.h" +#include "mlir-c/Dialect/Math.h" +#include "mlir-c/Dialect/MemRef.h" +#include "mlir-c/Dialect/SCF.h" +#include "mlir-c/IR.h" +#include "mlir/Bindings/Python/NanobindAdaptors.h" + +NB_MODULE(_site_initialize_0, module) { + module.doc() = "PTOAS MLIR dialect registration"; + module.def("register_dialects", [](MlirDialectRegistry registry) { + mlirDialectHandleInsertDialect(mlirGetDialectHandle__arith__(), registry); + mlirDialectHandleInsertDialect(mlirGetDialectHandle__func__(), registry); + mlirDialectHandleInsertDialect(mlirGetDialectHandle__llvm__(), registry); + mlirDialectHandleInsertDialect(mlirGetDialectHandle__math__(), registry); + mlirDialectHandleInsertDialect(mlirGetDialectHandle__memref__(), registry); + mlirDialectHandleInsertDialect(mlirGetDialectHandle__scf__(), registry); + }); +} diff --git a/packaging/ptoas-vmi/pyproject.toml b/packaging/ptoas-vmi/pyproject.toml index c5bf63ca99..c5de369d66 100644 --- a/packaging/ptoas-vmi/pyproject.toml +++ b/packaging/ptoas-vmi/pyproject.toml @@ -12,7 +12,7 @@ # name required by package indexes without a custom build backend. [build-system] -requires = ["scikit-build-core>=0.12.2,<2", "pybind11<3"] +requires = ["scikit-build-core>=0.12.2,<2", "pybind11<3", "nanobind>=2.4"] build-backend = "scikit_build_core.build" [project] diff --git a/ptodsl/CMakeLists.txt b/ptodsl/CMakeLists.txt index ef602d320f..4be1601179 100644 --- a/ptodsl/CMakeLists.txt +++ b/ptodsl/CMakeLists.txt @@ -12,19 +12,19 @@ set(PTODSL_PACKAGE_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ptodsl") -set(PTODSL_BUILD_ROOT "${CMAKE_BINARY_DIR}/python") set(PTODSL_BUILD_PACKAGE_DIR - "${PTODSL_BUILD_ROOT}/ptodsl") + "${CMAKE_BINARY_DIR}/python/ptodsl") -add_custom_target(PTODSLPackage ALL - COMMAND ${CMAKE_COMMAND} -E make_directory "${PTODSL_BUILD_ROOT}" - COMMAND ${CMAKE_COMMAND} -E remove_directory "${PTODSL_BUILD_PACKAGE_DIR}" - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${PTODSL_PACKAGE_SRC_DIR}" - "${PTODSL_BUILD_PACKAGE_DIR}" - COMMENT "Staging ptodsl package into build/python" - VERBATIM +declare_mlir_python_sources(PTODSLPythonSources + ROOT_DIR "${PTODSL_PACKAGE_SRC_DIR}" + SOURCES_GLOB "*.py" ) +add_mlir_python_sources_target(PTODSLPackageStage + OUTPUT_DIRECTORY "${PTODSL_BUILD_PACKAGE_DIR}" + SOURCES_TARGETS PTODSLPythonSources +) +add_custom_target(PTODSLPackage ALL) +add_dependencies(PTODSLPackage PTODSLPackageStage) install( DIRECTORY "${PTODSL_PACKAGE_SRC_DIR}" diff --git a/ptodsl/docs/developer_guide/tilelib-debugging-playbook.md b/ptodsl/docs/developer_guide/tilelib-debugging-playbook.md index db519c5165..324764b93d 100644 --- a/ptodsl/docs/developer_guide/tilelib-debugging-playbook.md +++ b/ptodsl/docs/developer_guide/tilelib-debugging-playbook.md @@ -12,7 +12,7 @@ usually live in different layers. Build PTOAS after C++ or TableGen changes: ```bash -cmake --build build-llvm21 --target ptoas_runtime +cmake --build build-llvm21 --target PTOASPythonCore ``` Stage PTODSL after Python package changes: diff --git a/ptodsl/ptoas/_cli.py b/ptodsl/ptoas/_cli.py index 7cb3132679..7798275f28 100644 --- a/ptodsl/ptoas/_cli.py +++ b/ptodsl/ptoas/_cli.py @@ -26,15 +26,15 @@ def _resolve_wrapper_path(argv0: str | None = None) -> Path: def _load_native_module(): - from ptoas import _native + from ptoas import _core - return _native + return _core def _resolve_runtime_paths(native_module) -> tuple[Path, Path]: module_file = getattr(native_module, "__file__", None) if not module_file: - raise SystemExit("ptoas._native does not expose a module file") + raise SystemExit("ptoas._core does not expose a module file") package_root = Path(module_file).resolve().parent python_root = package_root.parent diff --git a/ptodsl/tests/CMakeLists.txt b/ptodsl/tests/CMakeLists.txt index 1722bf5d08..1bbb4076d2 100644 --- a/ptodsl/tests/CMakeLists.txt +++ b/ptodsl/tests/CMakeLists.txt @@ -7,17 +7,13 @@ # See LICENSE in the root of the software repository for the full text of the License. if(NOT DEFINED _pto_python_test_env) - get_filename_component(_llvm_root "${LLVM_DIR}/../../.." ABSOLUTE) get_filename_component(_pto_python_bin_dir "${Python3_EXECUTABLE}" DIRECTORY) set(_ptodsl_test_pythonpath - "${CMAKE_BINARY_DIR}/python:${MLIR_PYTHON_PACKAGE_DIR}:${CMAKE_INSTALL_PREFIX}:$ENV{PYTHONPATH}" + "${CMAKE_BINARY_DIR}/python:$ENV{PYTHONPATH}" ) - if(DEFINED ENV{PTO_INSTALL_DIR} AND NOT "$ENV{PTO_INSTALL_DIR}" STREQUAL "") - set(_ptodsl_test_pythonpath "$ENV{PTO_INSTALL_DIR}:${_ptodsl_test_pythonpath}") - endif() set(_pto_python_test_env "PYTHONPATH=${_ptodsl_test_pythonpath}" - "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:${_llvm_root}/lib:${CMAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}" + "LD_LIBRARY_PATH=${CMAKE_BINARY_DIR}/lib:${LLVM_BUILD_LIBRARY_DIR}:${CMAKE_INSTALL_PREFIX}/lib:$ENV{LD_LIBRARY_PATH}" "PATH=${CMAKE_BINARY_DIR}/tools/ptoas:${CMAKE_INSTALL_PREFIX}/bin:${_pto_python_bin_dir}:$ENV{PATH}" "PTOAS_BIN=${CMAKE_BINARY_DIR}/tools/ptoas/ptoas" ) @@ -60,7 +56,7 @@ endforeach() if(NOT TARGET check-dsl) set(_ptodsl_check_depends) - foreach(_target IN ITEMS PTODSLPackage PTOPythonModules ptoas_runtime_deps) + foreach(_target IN ITEMS PTODSLPackage PTOAS_Python ptoas_runtime_deps) if(TARGET ${_target}) list(APPEND _ptodsl_check_depends ${_target}) endif() diff --git a/ptodsl/tests/test_allreduce.py b/ptodsl/tests/test_allreduce.py index 533ba62750..78bac49288 100644 --- a/ptodsl/tests/test_allreduce.py +++ b/ptodsl/tests/test_allreduce.py @@ -7,11 +7,6 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from pathlib import Path -import sys - -sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "ptodsl")) - from ptodsl import pto diff --git a/ptodsl/tests/test_ptoas_cli.py b/ptodsl/tests/test_ptoas_cli.py index 9afd21e42c..7917a2ccb3 100644 --- a/ptodsl/tests/test_ptoas_cli.py +++ b/ptodsl/tests/test_ptoas_cli.py @@ -19,7 +19,7 @@ class PTOASCLITests(unittest.TestCase): def _make_native_module(self, package_root: Path): return SimpleNamespace( - __file__=str(package_root / "_native.fake.so"), + __file__=str(package_root / "_core.fake.so"), main=mock.Mock(return_value=0), ) diff --git a/ptodsl/tests/test_ptoas_tree_wrapper.py b/ptodsl/tests/test_ptoas_tree_wrapper.py index 59f5545873..5bea72f01c 100644 --- a/ptodsl/tests/test_ptoas_tree_wrapper.py +++ b/ptodsl/tests/test_ptoas_tree_wrapper.py @@ -27,13 +27,22 @@ def launch(user_args, *, wrapper=None): class TreeWrapperTests(unittest.TestCase): - def _load_wrapper(self, wrapper_path: Path, module_name: str): + def _load_wrapper( + self, + wrapper_path: Path, + module_name: str, + *, + python_root_mode: str, + python_root: Path, + ): spec = importlib.util.spec_from_file_location(module_name, WRAPPER_SOURCE) self.assertIsNotNone(spec) self.assertIsNotNone(spec.loader) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) module.__file__ = str(wrapper_path) + module._PYTHON_ROOT_MODE = python_root_mode + module._PYTHON_ROOT = python_root return module def _run_wrapper(self, wrapper_module, python_root: Path, wrapper: Path): @@ -73,7 +82,12 @@ def test_build_tree_wrapper_delegates_to_cli_module(self): wrapper.parent.mkdir(parents=True) wrapper.write_text("", encoding="utf-8") - module = self._load_wrapper(wrapper, "test_ptoas_build_wrapper") + module = self._load_wrapper( + wrapper, + "test_ptoas_build_wrapper", + python_root_mode="absolute", + python_root=python_root, + ) cli = self._run_wrapper(module, python_root, wrapper) self.assertEqual(cli.calls, [(["--version"], wrapper.resolve())]) @@ -86,7 +100,12 @@ def test_install_tree_wrapper_delegates_to_cli_module(self): wrapper.parent.mkdir(parents=True) wrapper.write_text("", encoding="utf-8") - module = self._load_wrapper(wrapper, "test_ptoas_install_wrapper") + module = self._load_wrapper( + wrapper, + "test_ptoas_install_wrapper", + python_root_mode="wrapper-relative", + python_root=Path(".."), + ) cli = self._run_wrapper(module, install_root, wrapper) self.assertEqual(cli.calls, [(["--version"], wrapper.resolve())]) @@ -98,6 +117,8 @@ def test_wrapper_requires_cli_module(self): module = self._load_wrapper( Path(temp_dir) / "build" / "tools" / "ptoas" / "ptoas", "test_ptoas_missing_cli", + python_root_mode="absolute", + python_root=python_root, ) with self.assertRaisesRegex(SystemExit, "ptoas/_cli.py"): module._require_python_root(python_root, context="test") diff --git a/ptodsl/tests/test_vmi_vmull.py b/ptodsl/tests/test_vmi_vmull.py index 3fbf2972a4..fad01a208c 100644 --- a/ptodsl/tests/test_vmi_vmull.py +++ b/ptodsl/tests/test_vmi_vmull.py @@ -7,12 +7,6 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from pathlib import Path -import sys - - -sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "ptodsl")) - from ptodsl import pto diff --git a/ptodsl/tests/test_vmi_vshr_signedness.py b/ptodsl/tests/test_vmi_vshr_signedness.py index f4dfe09340..848ddec81a 100644 --- a/ptodsl/tests/test_vmi_vshr_signedness.py +++ b/ptodsl/tests/test_vmi_vshr_signedness.py @@ -7,12 +7,6 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from pathlib import Path -import sys - - -sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "ptodsl")) - from ptodsl import pto diff --git a/pyproject.toml b/pyproject.toml index 072d2fb95f..beaed1b33b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ # a persistent CMake build tree. [build-system] -requires = ["scikit-build-core>=0.12.2,<2", "pybind11<3"] +requires = ["scikit-build-core>=0.12.2,<2", "pybind11<3", "nanobind>=2.4"] build-backend = "scikit_build_core.build" [project] diff --git a/python/pto/dialects/pto.py b/python/pto/dialects/pto.py index 3e66f0bdb1..f2038d060a 100644 --- a/python/pto/dialects/pto.py +++ b/python/pto/dialects/pto.py @@ -6,12 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -import importlib -import importlib.util import functools -import os -from pathlib import Path -import sys from typing import Optional from mlir import ir as _ods_ir @@ -22,77 +17,7 @@ get_op_result_or_value as _get_op_result_or_value, get_op_results_or_values as _get_op_results_or_values, ) - - -def _candidate_pto_ext_dirs(): - # Prefer the extension shipped next to the active wrapper so installed - # wheels stay self-consistent even if the caller also exported a developer - # PTO_INSTALL_DIR / PTO_PYTHON_ROOT in the environment. - candidates = [Path(__file__).resolve().parent.parent / "_mlir_libs"] - env_roots = ( - os.environ.get("PTO_PYTHON_BUILD_ROOT"), - os.environ.get("PTO_PYTHON_ROOT"), - os.environ.get("PTO_INSTALL_DIR"), - ) - for root in env_roots: - if not root: - continue - candidates.append(Path(root) / "mlir" / "_mlir_libs") - - seen = set() - ordered = [] - for candidate in candidates: - candidate = candidate.resolve() - candidate_text = str(candidate) - if candidate_text in seen: - continue - seen.add(candidate_text) - ordered.append(candidate) - return ordered - - -def _load_local_pto_ext(): - module_name = "mlir._mlir_libs._pto" - cached = sys.modules.get(module_name) - if cached is not None: - return cached - - candidates = [] - for lib_dir in _candidate_pto_ext_dirs(): - for suffix in ("*.so", "*.pyd", "*.dll", "*.dylib"): - candidates.extend(lib_dir.glob(f"_pto{suffix}")) - if not candidates: - raise FileNotFoundError("cannot locate local _pto extension in candidate _mlir_libs directories") - - first_error = None - for so_path in candidates: - try: - spec = importlib.util.spec_from_file_location( - module_name, so_path - ) - if spec and spec.loader: - mod = importlib.util.module_from_spec(spec) - previous = sys.modules.get(module_name) - sys.modules[module_name] = mod - try: - spec.loader.exec_module(mod) - except Exception: - if previous is None: - sys.modules.pop(module_name, None) - else: - sys.modules[module_name] = previous - raise - return mod - except ImportError as exc: - if first_error is None: - first_error = exc - raise ImportError("failed to load local _pto extension from candidate _mlir_libs directories") from first_error - - -try: - _pto_mod = _load_local_pto_ext() -except FileNotFoundError: - _pto_mod = importlib.import_module(".._mlir_libs._pto", __package__) +from ptoas import _core as _pto_mod def _export_generated_symbols(): diff --git a/quick_install.sh b/quick_install.sh index 9c3767a28b..253f5713ab 100755 --- a/quick_install.sh +++ b/quick_install.sh @@ -31,7 +31,8 @@ fi "${PYTHON_BIN}" -m pip install \ 'scikit-build-core>=0.12.2,<2' \ - 'pybind11<3' + 'pybind11<3' \ + 'nanobind>=2.4' LLVM_BUILD_DIR="${LLVM_BUILD_DIR}" \ "${PYTHON_BIN}" -m pip install --editable "${PTO_SOURCE_DIR}" \ diff --git a/scripts/ptoas_env.sh b/scripts/ptoas_env.sh index b5e814ccda..1686ba1bc0 100644 --- a/scripts/ptoas_env.sh +++ b/scripts/ptoas_env.sh @@ -41,7 +41,6 @@ export PTO_INSTALL_DIR="${PTO_INSTALL_DIR:-${PTO_SOURCE_DIR}/install}" export PTO_ISA_PATH="${PTO_ISA_PATH:-${WORKSPACE_DIR}/pto-isa}" export ASCEND_HOME_PATH="${ASCEND_HOME_PATH:-${HOME}/cann}" -export MLIR_PYTHON_ROOT="${MLIR_PYTHON_ROOT:-${LLVM_BUILD_DIR}/tools/mlir/python_packages/mlir_core}" if [[ -z "${PTOAS_PYTHON_SITE:-}" ]]; then PTOAS_PYTHON_SITE="$( PTO_INSTALL_DIR="${PTO_INSTALL_DIR}" python3 - <<'PY' 2>/dev/null || true @@ -57,7 +56,6 @@ export PTOAS_PYTHON_SITE export PTO_PYTHON_ROOT="${PTO_PYTHON_ROOT:-${PTO_INSTALL_DIR}}" export PTO_PYTHON_BUILD_ROOT="${PTO_PYTHON_BUILD_ROOT:-${PTO_SOURCE_DIR}/build/python}" export PTODSL_PYTHON_ROOT="${PTODSL_PYTHON_ROOT:-${PTO_SOURCE_DIR}/ptodsl}" -export PYBIND11_CMAKE_DIR=$(python3 -m pybind11 --cmakedir) export PTOAS_FLAGS="${PTOAS_FLAGS:-}" export PTOAS_OUT_DIR="${PTOAS_OUT_DIR:-${PTO_SOURCE_DIR}/build/output}" @@ -110,13 +108,12 @@ _ptoas_run_legacy_smoke_test() { echo "test set_env: OK" } -# Prefer the in-tree PTO Python overlay plus LLVM's full MLIR package first. -# The install prefix may only contain the PTO overlay fragments, and when it is -# placed ahead of mlir_core it can shadow the real MLIR Python bindings. +# PTOAS stages a complete MLIR + PTO package in its build and install trees. +# Prefer the build tree for active development, while retaining install-tree +# fallbacks for scripts that consume a direct CMake installation. _ptoas_prepend_path PYTHONPATH "${PTO_INSTALL_DIR}" _ptoas_prepend_path PYTHONPATH "${PTO_PYTHON_ROOT}" _ptoas_prepend_path PYTHONPATH "${PTOAS_PYTHON_SITE}" -_ptoas_prepend_path PYTHONPATH "${MLIR_PYTHON_ROOT}" _ptoas_prepend_path PYTHONPATH "${PTO_PYTHON_BUILD_ROOT}" _ptoas_prepend_path PYTHONPATH "${PTODSL_PYTHON_ROOT}" diff --git a/test/lit/lit.cfg.py b/test/lit/lit.cfg.py index 1d3691d62d..6617267ab7 100644 --- a/test/lit/lit.cfg.py +++ b/test/lit/lit.cfg.py @@ -51,16 +51,12 @@ 'ASCEND_HOME_PATH', 'ASCEND_OPP_PATH', 'ASCEND_AICPU_PATH', 'ASCEND_TOOLKIT_HOME', 'LD_LIBRARY_PATH', 'PYTHONPATH']) -# Keep build-tree lit tests self-contained. PTOAS contributes an overlay -# under the build tree (generated dialect Python plus the PTO extension), -# while the base ``mlir.ir`` package comes from the LLVM/MLIR build. MLIR's -# own lit setup wires these paths from its CMake-generated site configuration; -# do the same here instead of requiring developers to export PYTHONPATH. +# Keep build-tree lit tests self-contained. The PTOAS build stages the complete +# MLIR Python runtime together with generated PTO dialect modules and the PTO +# extension under one build-tree Python root. if getattr(config, 'enable_bindings_python', False): - python_paths = [config.ptoas_python_dir] - if config.mlir_python_package_dir: - python_paths.append(config.mlir_python_package_dir) - llvm_config.with_environment('PYTHONPATH', python_paths, append_path=True) + llvm_config.with_environment( + 'PYTHONPATH', [config.ptoas_python_dir], append_path=True) llvm_config.use_default_substitutions() diff --git a/test/lit/lit.site.cfg.py.in b/test/lit/lit.site.cfg.py.in index 7babeaa197..b3b81a7464 100644 --- a/test/lit/lit.site.cfg.py.in +++ b/test/lit/lit.site.cfg.py.in @@ -21,8 +21,6 @@ config.mlir_lib_dir = "@MLIR_LIB_DIR@" config.python_executable = "@Python3_EXECUTABLE@" config.enable_bindings_python = "@PTO_ENABLE_PYTHON_BINDING@" == "ON" config.ptoas_python_dir = path(r"@CMAKE_BINARY_DIR@/python") -config.mlir_python_package_dir = lit_config.substitute( - path(r"@MLIR_PYTHON_PACKAGE_DIR@")) config.ptoir_src_root = "@CMAKE_SOURCE_DIR@" config.ptoir_obj_root = "@CMAKE_BINARY_DIR@" diff --git a/test/tilelib-st/README.md b/test/tilelib-st/README.md index 43cda3d89f..c9cc31e2ef 100644 --- a/test/tilelib-st/README.md +++ b/test/tilelib-st/README.md @@ -213,7 +213,6 @@ export PTOAS_REPO="$PWD" export PTOAS_BUILD="$PTOAS_REPO/build-sim" export ASCEND_HOME_PATH=/path/to/cann export LLVM_BUILD_DIR=/path/to/vpto-llvm/build -export MLIR_PYTHON_ROOT="$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core" export PYTHON_BIN=/path/to/python-with-torch-npu export PTO_PYTHON_BIN="$PYTHON_BIN" export PTOAS_ENV_SKIP_SMOKE_TEST=1 @@ -233,7 +232,6 @@ Check the simulator, LLVM, and Python prerequisites: command -v msprof test -d "$LLVM_BUILD_DIR/lib/cmake/llvm" test -d "$LLVM_BUILD_DIR/lib/cmake/mlir" -test -d "$MLIR_PYTHON_ROOT" "$PYTHON_BIN" - <<'PY' import nanobind @@ -264,27 +262,20 @@ PTOAS Python bindings must have the same Python ABI as the runtime Python that will run the ST cases: ```bash -PYBIND11_CMAKE_DIR="$("$PYTHON_BIN" -m pybind11 --cmakedir)" -NANOBIND_CMAKE_DIR="$("$PYTHON_BIN" -m nanobind --cmake_dir)" - cmake -S "$PTOAS_REPO" -B "$PTOAS_BUILD" -G Ninja \ -DLLVM_DIR="$LLVM_BUILD_DIR/lib/cmake/llvm" \ -DMLIR_DIR="$LLVM_BUILD_DIR/lib/cmake/mlir" \ -DPython3_EXECUTABLE="$PYTHON_BIN" \ -DPython3_FIND_STRATEGY=LOCATION \ - -Dpybind11_DIR="$PYBIND11_CMAKE_DIR" \ - -Dnanobind_DIR="$NANOBIND_CMAKE_DIR" \ -DMLIR_ENABLE_BINDINGS_PYTHON=ON \ - -DMLIR_PYTHON_PACKAGE_DIR="$MLIR_PYTHON_ROOT" \ -DPTO_ENABLE_PYTHON_BINDING=ON \ - -DPTOAS_ENABLE_WERROR=OFF \ -DBUILD_TESTING=ON ``` Build the compiler and PTO Python bindings: ```bash -ninja -C "$PTOAS_BUILD" ptoas PTOPythonModules +ninja -C "$PTOAS_BUILD" ptoas PTOAS_Python ``` Export the runtime lookup paths. `PTOAS_BIN` is useful, but PTODSL native build @@ -293,7 +284,7 @@ also resolves `ptoas` through `PATH`, so keep the freshly built binary first: ```bash export PTOAS_BIN="$PTOAS_BUILD/tools/ptoas/ptoas" export PATH="$PTOAS_BUILD/tools/ptoas:$PATH" -export PYTHONPATH="$PTOAS_BUILD/python:$PTOAS_REPO/ptodsl:$MLIR_PYTHON_ROOT:${PYTHONPATH:-}" +export PYTHONPATH="$PTOAS_BUILD/python:$PTOAS_REPO/ptodsl:${PYTHONPATH:-}" export LD_LIBRARY_PATH="$LLVM_BUILD_DIR/lib:$PTOAS_BUILD/lib:${LD_LIBRARY_PATH:-}" ``` @@ -343,7 +334,6 @@ Example path layout: ```bash export ASCEND_HOME_PATH=/opt/ascend/cann export LLVM_BUILD_DIR=/opt/vpto-llvm/build -export MLIR_PYTHON_ROOT="$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core" export PYTHON_BIN=/opt/ptodsl-runtime/bin/python ``` @@ -357,5 +347,5 @@ Common failures: - `No TileLib ST cases discovered`: pass the case root through `scripts/sim_dsl.sh ... run_tilelib_st.py -- test/tilelib-st/a5`, keeping the `--` separator. -- Stale compiler behavior: rebuild `ptoas PTOPythonModules`, put +- Stale compiler behavior: rebuild `ptoas PTOAS_Python`, put `$PTOAS_BUILD/tools/ptoas` first in `PATH`, and verify `$PTOAS_BIN --version`. diff --git a/tilelang-dsl/CMakeLists.txt b/tilelang-dsl/CMakeLists.txt index 2bbca7c3dc..db11784d6f 100644 --- a/tilelang-dsl/CMakeLists.txt +++ b/tilelang-dsl/CMakeLists.txt @@ -12,19 +12,19 @@ set(TILELANG_DSL_PACKAGE_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/python/tilelang_dsl") -set(TILELANG_DSL_BUILD_ROOT "${CMAKE_BINARY_DIR}/python") set(TILELANG_DSL_BUILD_PACKAGE_DIR - "${TILELANG_DSL_BUILD_ROOT}/tilelang_dsl") + "${CMAKE_BINARY_DIR}/python/tilelang_dsl") -add_custom_target(TileLangDSLPackage ALL - COMMAND ${CMAKE_COMMAND} -E make_directory "${TILELANG_DSL_BUILD_ROOT}" - COMMAND ${CMAKE_COMMAND} -E remove_directory "${TILELANG_DSL_BUILD_PACKAGE_DIR}" - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${TILELANG_DSL_PACKAGE_SRC_DIR}" - "${TILELANG_DSL_BUILD_PACKAGE_DIR}" - COMMENT "Staging tilelang_dsl package into build/python" - VERBATIM +declare_mlir_python_sources(TileLangDSLPythonSources + ROOT_DIR "${TILELANG_DSL_PACKAGE_SRC_DIR}" + SOURCES_GLOB "*.py" ) +add_mlir_python_sources_target(TileLangDSLPackageStage + OUTPUT_DIRECTORY "${TILELANG_DSL_BUILD_PACKAGE_DIR}" + SOURCES_TARGETS TileLangDSLPythonSources +) +add_custom_target(TileLangDSLPackage ALL) +add_dependencies(TileLangDSLPackage TileLangDSLPackageStage) install( DIRECTORY "${TILELANG_DSL_PACKAGE_SRC_DIR}" diff --git a/tilelang-dsl/python/tilelang_dsl/env_config.py b/tilelang-dsl/python/tilelang_dsl/env_config.py index 00dc0e66e5..47fdd9b7ef 100644 --- a/tilelang-dsl/python/tilelang_dsl/env_config.py +++ b/tilelang-dsl/python/tilelang_dsl/env_config.py @@ -34,10 +34,10 @@ def check_pto_dialect_available() -> bool: """Check if PTO dialect bindings are available. Returns: - True if pto.dialects.pto module can be imported, False otherwise. + True if mlir.dialects.pto can be imported, False otherwise. """ try: - from pto.dialects import pto + from mlir.dialects import pto return True except ImportError: return False @@ -64,28 +64,23 @@ def print_environment_help() -> None: print("PybindBackend Environment Configuration Guide") print("=" * 60) print() - print("PybindBackend requires MLIR Python bindings from LLVM build.") + print("PybindBackend requires the MLIR Python package built by PTOAS.") print() print("To set up the environment, add the following to PYTHONPATH:") print() - print("1. LLVM MLIR Python package:") - print(" $LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core") - print() - print("2. PTO dialect bindings (optional, for PTO ops):") - print(" $PTOAS_BUILD_DIR/python/mlir") + print("1. PTOAS build-tree Python package:") + print(" $PTOAS_BUILD_DIR/python") print(" OR") - print(" $PTO_INSTALL_DIR/mlir") + print("2. PTOAS install tree:") + print(" $PTO_INSTALL_DIR") print() print("Example setup:") print() - print(" # Assuming LLVM is built at ~/llvm-workspace/llvm-project/build-shared") - print(" export LLVM_BUILD_DIR=~/llvm-workspace/llvm-project/build-shared") - print() print(" # Assuming PTOAS is at ~/llvm-workspace/pto-as") print(" export PTOAS_BUILD_DIR=~/llvm-workspace/pto-as/build") print() print(" # Set PYTHONPATH") - print(" export PYTHONPATH=$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core:$PTOAS_BUILD_DIR/python") + print(" export PYTHONPATH=$PTOAS_BUILD_DIR/python") print() print("After setup, verify with:") print(" python3 -c 'from mlir import ir; print(\"MLIR bindings OK\")'") @@ -128,4 +123,4 @@ def verify_environment() -> bool: "get_environment_status", "print_environment_help", "verify_environment", -] \ No newline at end of file +] diff --git a/tilelang-dsl/python/tilelang_dsl/pybind_renderer.py b/tilelang-dsl/python/tilelang_dsl/pybind_renderer.py index 8b9ad249c0..a817cec884 100644 --- a/tilelang-dsl/python/tilelang_dsl/pybind_renderer.py +++ b/tilelang-dsl/python/tilelang_dsl/pybind_renderer.py @@ -14,16 +14,15 @@ Phase 2 implementation: core framework with basic stmt/expr rendering. Dependencies: - - mlir.ir: MLIR Python bindings from LLVM build + - mlir.ir: MLIR Python bindings assembled by the PTOAS build - mlir.dialects.func, arith, scf: Standard MLIR dialects - mlir.dialects.pto: PTO dialect bindings from PTOAS build -To use this module, ensure PYTHONPATH includes: - 1. LLVM MLIR Python package: $LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core - 2. PTOAS Python bindings: $PTOAS_BUILD_DIR/python +To use this module from a build tree, ensure PYTHONPATH includes: + $PTOAS_BUILD_DIR/python Example: - export PYTHONPATH="$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core:$PTOAS_BUILD_DIR/python" + export PYTHONPATH="$PTOAS_BUILD_DIR/python" """ from __future__ import annotations @@ -67,8 +66,8 @@ def _ensure_mlir_bindings() -> None: except ImportError as exc: raise ImportError( "MLIR Python bindings not found. Please ensure PYTHONPATH includes " - "the MLIR Python package from your LLVM build. " - "Example: export PYTHONPATH=$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core " + "the Python package assembled by your PTOAS build. " + "Example: export PYTHONPATH=$PTOAS_BUILD_DIR/python " "See README.md for build instructions." ) from exc diff --git a/tilelang-dsl/tests/backend/test_e2e_pybind_backend.py b/tilelang-dsl/tests/backend/test_e2e_pybind_backend.py index c660cb64ee..a3b6088b93 100644 --- a/tilelang-dsl/tests/backend/test_e2e_pybind_backend.py +++ b/tilelang-dsl/tests/backend/test_e2e_pybind_backend.py @@ -18,7 +18,7 @@ python3 tests/backend/test_e2e_pybind_backend.py Environment setup (optional for PybindBackend): - export PYTHONPATH=$LLVM_BUILD_DIR/tools/mlir/python_packages/mlir_core:$PTOAS_BUILD_DIR/python + export PYTHONPATH=$PTOAS_BUILD_DIR/python """ import sys @@ -309,4 +309,4 @@ def main(): if __name__ == "__main__": success = main() - sys.exit(0 if success else 1) \ No newline at end of file + sys.exit(0 if success else 1) diff --git a/tools/ptoas/CMakeLists.txt b/tools/ptoas/CMakeLists.txt index 75db33c55a..0ec5afe766 100644 --- a/tools/ptoas/CMakeLists.txt +++ b/tools/ptoas/CMakeLists.txt @@ -16,19 +16,38 @@ set(PTOAS_RUNTIME_SOURCES set(PTOAS_WRAPPER_SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/ptoas_wrapper.py") set(PTOAS_WRAPPER_BINARY "${CMAKE_CURRENT_BINARY_DIR}/ptoas") +set(PTOAS_INSTALL_WRAPPER_BINARY "${CMAKE_CURRENT_BINARY_DIR}/ptoas-install") +set(PTOAS_WRAPPER_PYTHON_ROOT_MODE "absolute") +set(PTOAS_WRAPPER_PYTHON_ROOT "${CMAKE_BINARY_DIR}/python") configure_file( "${PTOAS_WRAPPER_SOURCE}" "${PTOAS_WRAPPER_BINARY}" @ONLY ) -file(CHMOD "${PTOAS_WRAPPER_BINARY}" - PERMISSIONS - OWNER_READ OWNER_WRITE OWNER_EXECUTE - GROUP_READ GROUP_EXECUTE - WORLD_READ WORLD_EXECUTE + +# CMake install prefixes may be overridden at install time. Resolve the +# installed package relative to bin/ptoas instead of baking in the configure +# prefix. +set(PTOAS_WRAPPER_PYTHON_ROOT_MODE "wrapper-relative") +set(PTOAS_WRAPPER_PYTHON_ROOT "..") +configure_file( + "${PTOAS_WRAPPER_SOURCE}" + "${PTOAS_INSTALL_WRAPPER_BINARY}" + @ONLY ) +foreach(_ptoas_wrapper IN ITEMS + "${PTOAS_WRAPPER_BINARY}" + "${PTOAS_INSTALL_WRAPPER_BINARY}") + file(CHMOD "${_ptoas_wrapper}" + PERMISSIONS + OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE + WORLD_READ WORLD_EXECUTE + ) +endforeach() + function(ptoas_configure_runtime_target target_name) target_compile_definitions(${target_name} PRIVATE PTOAS_RELEASE_VERSION="${PTOAS_CLI_VERSION}" @@ -82,67 +101,79 @@ add_library(ptoas_runtime_objects OBJECT ${PTOAS_RUNTIME_SOURCES}) llvm_update_compile_flags(ptoas_runtime_objects) ptoas_configure_runtime_target(ptoas_runtime_objects) -# Build the normal Python extension used by wheel, build-tree, install-tree, -# and Python-based standalone distributions. Linking the object library pulls -# in the driver implementation and propagates its native link dependencies. -pybind11_add_module(ptoas_runtime MODULE NativeModule.cpp) -target_link_libraries(ptoas_runtime PRIVATE ptoas_runtime_objects) -set_target_properties(ptoas_runtime PROPERTIES - OUTPUT_NAME "_native" - LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/python-module" - # Keep the external LLVM/MLIR build discoverable for build-tree and - # editable Python installs. Release wheels are subsequently repaired by - # auditwheel, which replaces this machine-local path with wheel-local - # dependencies and a relative RPATH. - BUILD_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}" - INSTALL_RPATH "${PTO_LLVM_BUILD_LIBRARY_DIR}" +# Build the single PTOAS-owned Python extension. It contains both the compiler +# driver and PTO dialect bindings, while linking MLIR's shared common CAPI so +# Python-created MLIR objects and the compiler use the same MLIR runtime. +set(PTOAS_BUILD_PYTHON_PACKAGE_DIR "${CMAKE_BINARY_DIR}/python/ptoas") +add_mlir_python_extension(PTOASPythonCore _core + INSTALL_COMPONENT PTOAS_Python + INSTALL_DIR ptoas + OUTPUT_DIRECTORY "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}" + PYTHON_BINDINGS_LIBRARY pybind11 + SOURCES + NativeModule.cpp + "${CMAKE_SOURCE_DIR}/lib/Bindings/Python/PTOModule.cpp" + LINK_LIBS + ptoas_runtime_objects + PTOCAPI + PTOASPythonCAPI +) +target_include_directories(PTOASPythonCore PRIVATE + "${CMAKE_SOURCE_DIR}/lib/Bindings/Python" ) +mlir_python_setup_extension_rpath(PTOASPythonCore) -set(PTOAS_BUILD_PYTHON_PACKAGE_DIR "${CMAKE_BINARY_DIR}/python/ptoas") -add_custom_target(PTOASPythonPackage ALL - COMMAND ${CMAKE_COMMAND} -E remove_directory - "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}" - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${CMAKE_SOURCE_DIR}/ptodsl/ptoas" - "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}" - COMMAND ${CMAKE_COMMAND} -E copy_if_different - "$" - "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}/$" - COMMAND ${CMAKE_COMMAND} -E make_directory - "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}/_runtime/share/ptoas" - COMMAND ${CMAKE_COMMAND} -E copy_directory - "${CMAKE_SOURCE_DIR}/lib/TileOps" - "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}/_runtime/share/ptoas/TileOps" - COMMAND ${CMAKE_COMMAND} -E remove_directory - "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}/_runtime/share/ptoas/TileOps/__pycache__" - DEPENDS ptoas_runtime - COMMENT "Staging the ptoas Python package" - VERBATIM +if(APPLE) + set_property(TARGET PTOASPythonCore PROPERTY INSTALL_RPATH + "@loader_path;@loader_path/../mlir/_mlir_libs") +elseif(UNIX) + set_property(TARGET PTOASPythonCore PROPERTY INSTALL_RPATH + "$ORIGIN;$ORIGIN/../mlir/_mlir_libs") +endif() + +declare_mlir_python_sources(PTOASRuntimePythonSources + ROOT_DIR "${CMAKE_SOURCE_DIR}/ptodsl/ptoas" + SOURCES_GLOB "*.py" +) +add_mlir_python_sources_target(PTOASRuntimePythonSourcesStage + OUTPUT_DIRECTORY "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}" + SOURCES_TARGETS PTOASRuntimePythonSources +) + +declare_mlir_python_sources(PTOASTileOpsPythonSources + ROOT_DIR "${CMAKE_SOURCE_DIR}/lib/TileOps" + SOURCES_GLOB "*.py" +) +add_mlir_python_sources_target(PTOASTileOpsPythonSourcesStage + OUTPUT_DIRECTORY + "${PTOAS_BUILD_PYTHON_PACKAGE_DIR}/_runtime/share/ptoas/TileOps" + SOURCES_TARGETS PTOASTileOpsPythonSources +) + +add_custom_target(PTOASPythonPackage ALL) +add_dependencies(PTOASPythonPackage + PTOASPythonCore + PTOAS_Python + PTOASRuntimePythonSourcesStage + PTOASTileOpsPythonSourcesStage ) if(TARGET PTODSLPackage) add_dependencies(PTOASPythonPackage PTODSLPackage) endif() - -# Keep the historical aggregate target name for existing developer commands; -# the actual runtime payload now lives in the staged Python package. -add_custom_target(ptoas_runtime_staging ALL - DEPENDS PTOASPythonPackage -) +if(TARGET TileLangDSLPackage) + add_dependencies(PTOASPythonPackage TileLangDSLPackage) +endif() if(TARGET ptoas_runtime_deps) - add_dependencies(ptoas_runtime_deps ptoas_runtime_staging) + add_dependencies(ptoas_runtime_deps PTOASPythonPackage) endif() -install(PROGRAMS "${PTOAS_WRAPPER_BINARY}" +install(PROGRAMS "${PTOAS_INSTALL_WRAPPER_BINARY}" DESTINATION bin + RENAME ptoas COMPONENT PTOAS_Runtime ) -install(TARGETS ptoas_runtime - LIBRARY DESTINATION ptoas - COMPONENT PTOAS_Python -) - install( DIRECTORY "${CMAKE_SOURCE_DIR}/lib/TileOps" DESTINATION "ptoas/_runtime/share/ptoas" diff --git a/tools/ptoas/NativeModule.cpp b/tools/ptoas/NativeModule.cpp index 54bfc26e41..e0097e0641 100644 --- a/tools/ptoas/NativeModule.cpp +++ b/tools/ptoas/NativeModule.cpp @@ -8,6 +8,8 @@ #include "ptoas.h" +#include "PTOModule.h" + #include "pybind11/pybind11.h" #include "pybind11/stl.h" @@ -31,7 +33,9 @@ int runPTOASFromPython(const std::vector &arguments) { } // namespace -PYBIND11_MODULE(_native, module) { - module.doc() = "Native PTOAS command-line entrypoint"; +PYBIND11_MODULE(_core, module) { + module.doc() = "PTOAS compiler and PTO dialect native bindings"; + py::module_::import("mlir.ir"); + mlir::pto::python::populatePTODialectBindings(module); module.def("main", &runPTOASFromPython, py::arg("argv")); } diff --git a/tools/ptoas/ptoas_wrapper.py b/tools/ptoas/ptoas_wrapper.py index 07a8d423d7..3b1e96ad25 100644 --- a/tools/ptoas/ptoas_wrapper.py +++ b/tools/ptoas/ptoas_wrapper.py @@ -7,7 +7,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -"""Add a CMake tree's Python root, then run the regular PTOAS CLI module.""" +"""Run the regular PTOAS CLI from a configured CMake package tree.""" from __future__ import annotations @@ -15,6 +15,10 @@ from pathlib import Path +_PYTHON_ROOT_MODE = "@PTOAS_WRAPPER_PYTHON_ROOT_MODE@" +_PYTHON_ROOT = Path(r"@PTOAS_WRAPPER_PYTHON_ROOT@") + + def _resolve_wrapper_path(argv0: str | None = None) -> Path: candidate = argv0 if argv0 is not None else sys.argv[0] wrapper = Path(candidate) @@ -24,10 +28,6 @@ def _resolve_wrapper_path(argv0: str | None = None) -> Path: raise SystemExit(f"unable to locate the ptoas tree wrapper: {candidate}") -def _is_build_tree_wrapper(wrapper: Path) -> bool: - return len(wrapper.parents) >= 2 and wrapper.parents[1].name == "tools" - - def _require_python_root(python_root: Path, *, context: str) -> Path: helper = python_root / "ptoas" / "_cli.py" if helper.is_file(): @@ -38,19 +38,18 @@ def _require_python_root(python_root: Path, *, context: str) -> Path: ) -def _add_tree_python_root(wrapper: Path) -> Path: - if _is_build_tree_wrapper(wrapper): - if len(wrapper.parents) < 3: - raise SystemExit("unable to locate the build-tree root for ptoas") - python_root = _require_python_root( - wrapper.parents[2] / "python", context="build-tree" - ) - else: - if len(wrapper.parents) < 2: - raise SystemExit("unable to locate the install-tree root for ptoas") - python_root = _require_python_root( - wrapper.parents[1], context="install-tree" - ) +def _configured_python_root(wrapper: Path) -> Path: + if _PYTHON_ROOT_MODE == "absolute": + return _PYTHON_ROOT + if _PYTHON_ROOT_MODE == "wrapper-relative": + return wrapper.parent / _PYTHON_ROOT + raise SystemExit(f"unsupported PTOAS wrapper mode: {_PYTHON_ROOT_MODE}") + + +def _add_configured_python_root(wrapper: Path) -> Path: + python_root = _require_python_root( + _configured_python_root(wrapper), context="configured" + ) python_root_text = str(python_root) if python_root_text not in sys.path: @@ -60,7 +59,7 @@ def _add_tree_python_root(wrapper: Path) -> Path: def main() -> None: wrapper = _resolve_wrapper_path() - _add_tree_python_root(wrapper) + _add_configured_python_root(wrapper) from ptoas import _cli raise SystemExit(_cli.launch(sys.argv[1:], wrapper=wrapper)) From f89290ffa63fabdbf67eb05b4116e11efdc54454 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Mon, 27 Jul 2026 11:43:52 +0800 Subject: [PATCH 13/19] build: clean up editable CI and wheel RPATHs --- .github/workflows/build_wheel.yml | 7 +++- .github/workflows/build_wheel_mac.yml | 6 ++- .github/workflows/ci.yml | 46 +++++++------------- .github/workflows/ci_sim.yml | 60 ++++++++++----------------- lib/Bindings/Python/CMakeLists.txt | 12 ++++++ tools/ptoas/CMakeLists.txt | 12 ++++++ 6 files changed, 72 insertions(+), 71 deletions(-) diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index 8952245bde..c309932bc5 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -231,7 +231,6 @@ jobs: python -m pip wheel "${PTOAS_WHEEL_SOURCE_DIR}" \ --no-build-isolation --no-deps \ --wheel-dir "${PTO_SOURCE_DIR}/build/wheel-dist" - cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" - name: Validate wheel payload and launcher contract run: | @@ -241,8 +240,11 @@ jobs: run: | export PTO_WHEEL_DIST_DIR=$PTO_SOURCE_DIR/build/wheel-dist export PTO_WHEELHOUSE=$GITHUB_WORKSPACE/wheelhouse - export LD_LIBRARY_PATH=$LLVM_BUILD_DIR/lib:$PTO_INSTALL_DIR/lib:$LD_LIBRARY_PATH mkdir -p "$PTO_WHEELHOUSE" + # The raw wheel intentionally keeps package-relative RPATHs. Give + # auditwheel the external LLVM build only while resolving and + # bundling its shared dependencies. + export LD_LIBRARY_PATH="${LLVM_BUILD_DIR}/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}" auditwheel repair --plat manylinux_2_34_${{ matrix.arch }} "$PTO_WHEEL_DIST_DIR"/ptoas*.whl -w "$PTO_WHEELHOUSE" - name: Test wheel installation @@ -260,6 +262,7 @@ jobs: - name: Collect ptoas binary and dependencies if: matrix.python == '3.11' run: | + cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" bash $PTO_SOURCE_DIR/docker/collect_ptoas_dist.sh $GITHUB_WORKSPACE/ptoas-dist - name: Archive ptoas binary artifact diff --git a/.github/workflows/build_wheel_mac.yml b/.github/workflows/build_wheel_mac.yml index d422cf433e..b3e96f8ff5 100644 --- a/.github/workflows/build_wheel_mac.yml +++ b/.github/workflows/build_wheel_mac.yml @@ -234,7 +234,6 @@ jobs: python -m pip wheel "${PTOAS_WHEEL_SOURCE_DIR}" \ --no-build-isolation --no-deps \ --wheel-dir "${PTO_SOURCE_DIR}/build/wheel-dist" - cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" shopt -s nullglob built_wheels=("$PTO_SOURCE_DIR"/build/wheel-dist/ptoas*.whl) if [ "${#built_wheels[@]}" -gt 0 ]; then @@ -272,6 +271,10 @@ jobs: echo "delocate dependency summary:" delocate-listdeps "${wheels[0]}" || true + # The raw wheel intentionally keeps package-relative RPATHs. Give + # delocate the external LLVM build only while resolving and bundling + # its shared dependencies. + export DYLD_LIBRARY_PATH="${LLVM_BUILD_DIR}/lib${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}}" delocate-wheel \ --require-archs "${REQUIRED_ARCH}" \ --wheel-dir "$PTO_WHEELHOUSE" \ @@ -335,6 +338,7 @@ jobs: - name: Collect ptoas binary and dependencies if: matrix.python == '3.11' run: | + cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" bash "$PTO_SOURCE_DIR/docker/collect_ptoas_dist_mac.sh" "$GITHUB_WORKSPACE/ptoas-dist" - name: Archive ptoas binary artifact diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f5aaffaaf..9c2e3ddb64 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -102,9 +102,8 @@ jobs: LLVM_BUILD_DIR: ${{ github.workspace }}/llvm-project/llvm/build-assert LLVM_DIR: ${{ github.workspace }}/llvm-project/llvm/build-assert PTO_BUILD_DIR: ${{ github.workspace }}/build-assert - PTO_INSTALL_DIR: ${{ github.workspace }}/install-assert PTOAS_VENV: ${{ github.workspace }}/.venv-ptoas-assert - LLVM_CACHE_FLAVOR: llvm21-assert-shared-mlirpy-hardening-v1 + LLVM_CACHE_FLAVOR: llvm21-assert-shared-mlirpy-hardening-v2 steps: - name: Checkout uses: actions/checkout@v4 @@ -112,7 +111,7 @@ jobs: fetch-depth: 1 persist-credentials: false - - name: Install dependencies + - name: Install dependencies and create developer environment run: | # GitHub-hosted runners may include Microsoft apt sources unrelated to # PTOAS; these can intermittently return 403 and break apt-get update. @@ -129,9 +128,13 @@ jobs: python3 python3-pip python3-venv \ clang-${PTOAS_CLANG_MAJOR} lld-${PTOAS_CLANG_MAJOR} \ libedit-dev zlib1g-dev libxml2-dev libzstd-dev - python3 -m pip install --upgrade pip + rm -rf "${PTOAS_VENV}" + python3 -m venv "${PTOAS_VENV}" + "${PTOAS_VENV}/bin/python" -m pip install --upgrade pip # LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x. - python3 -m pip install 'scikit-build-core>=0.12.2,<2' 'pybind11<3' nanobind numpy + "${PTOAS_VENV}/bin/pip" install \ + 'scikit-build-core>=0.12.2,<2' 'pybind11<3' \ + nanobind numpy ml-dtypes - name: Define payload paths shell: bash @@ -208,10 +211,10 @@ jobs: -DBUILD_SHARED_LIBS=ON \ -DLLVM_ENABLE_ASSERTIONS=ON \ -DMLIR_ENABLE_BINDINGS_PYTHON=ON \ - -DPython3_EXECUTABLE=python3 \ - -DPython_EXECUTABLE=python3 \ - -Dpybind11_DIR="$(python3 -m pybind11 --cmakedir)" \ - -Dnanobind_DIR="$(python3 -m nanobind --cmake_dir)" \ + -DPython3_EXECUTABLE="${PTOAS_VENV}/bin/python" \ + -DPython_EXECUTABLE="${PTOAS_VENV}/bin/python" \ + -Dpybind11_DIR="$("${PTOAS_VENV}/bin/python" -m pybind11 --cmakedir)" \ + -Dnanobind_DIR="$("${PTOAS_VENV}/bin/python" -m nanobind --cmake_dir)" \ -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_C_COMPILER="${PTOAS_CMAKE_C_COMPILER}" \ -DCMAKE_CXX_COMPILER="${PTOAS_CMAKE_CXX_COMPILER}" \ @@ -258,20 +261,10 @@ jobs: -DCMAKE_CXX_COMPILER="${PTOAS_CMAKE_CXX_COMPILER}" \ -Werror=dev - - name: Create PTOAS developer environment - shell: bash - run: | - set -euo pipefail - rm -rf "${PTOAS_VENV}" - python3 -m venv "${PTOAS_VENV}" - "${PTOAS_VENV}/bin/python" -m pip install --upgrade pip - "${PTOAS_VENV}/bin/pip" install 'scikit-build-core>=0.12.2,<2' 'pybind11<3' nanobind numpy ml-dtypes - - name: Install PTOAS editable run: | set -euo pipefail rm -rf "${PTO_BUILD_DIR}" - rm -rf "${PTO_INSTALL_DIR}" # Keep a persistent CMake build tree for CTest and lit while exposing # the current sources and Python extension through the developer venv. LLVM_BUILD_DIR="${LLVM_DIR}" \ @@ -280,7 +273,6 @@ jobs: "${PTOAS_VENV}/bin/python" -m pip install --editable . \ --no-build-isolation --no-deps \ --config-settings="build-dir=${PTO_BUILD_DIR}" - cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" - name: Test PTOAS editable install shell: bash @@ -294,20 +286,16 @@ jobs: shell: bash env: LLVM_DIR: ${{ env.LLVM_DIR }} - PTO_INSTALL_DIR: ${{ env.PTO_INSTALL_DIR }} run: | - export PATH="${PTOAS_VENV}/bin:${LLVM_DIR}/bin:${PTO_INSTALL_DIR}/bin:${PATH}" - export LD_LIBRARY_PATH="${LLVM_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}" + export PATH="${PTOAS_VENV}/bin:${LLVM_DIR}/bin:${PATH}" ctest --test-dir "${PTO_BUILD_DIR}" --output-on-failure -L PTODSL - name: Run lit tests shell: bash env: LLVM_DIR: ${{ env.LLVM_DIR }} - PTO_INSTALL_DIR: ${{ env.PTO_INSTALL_DIR }} run: | - export PATH="${PTOAS_VENV}/bin:${LLVM_DIR}/bin:${PTO_INSTALL_DIR}/bin:${PATH}" - export LD_LIBRARY_PATH="${LLVM_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}" + export PATH="${PTOAS_VENV}/bin:${LLVM_DIR}/bin:${PATH}" ninja -C "${PTO_BUILD_DIR}" check-pto - name: Run sample tests (py -> pto -> cpp) @@ -315,15 +303,13 @@ jobs: env: CI_EVENT_NAME: ${{ github.event_name }} WORKFLOW_SOC_VERSION: ${{ github.event.inputs.soc_version || 'Ascend910' }} - PTOAS_BIN: ${{ env.PTO_INSTALL_DIR }}/bin/ptoas + PTOAS_BIN: ${{ env.PTOAS_VENV }}/bin/ptoas PTOBC_BIN: ${{ env.PTO_BUILD_DIR }}/tools/ptobc/ptobc PTO_BUILD_DIR: ${{ env.PTO_BUILD_DIR }} PYTHON_BIN: ${{ env.PTOAS_VENV }}/bin/python - PTO_INSTALL_DIR: ${{ env.PTO_INSTALL_DIR }} run: | set -euo pipefail - export PATH="${PTOAS_VENV}/bin:${PTO_INSTALL_DIR}/bin:${PATH}" - export LD_LIBRARY_PATH="${LLVM_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}" + export PATH="${PTOAS_VENV}/bin:${PATH}" export PTOAS_OUT_DIR="${PAYLOAD_DIR}/test/samples" if [[ "${CI_EVENT_NAME}" == "workflow_dispatch" || "${CI_EVENT_NAME}" == "schedule" ]]; then # Board-validation payloads must only contain the arch-matching diff --git a/.github/workflows/ci_sim.yml b/.github/workflows/ci_sim.yml index b04add1de8..ac07cccbee 100644 --- a/.github/workflows/ci_sim.yml +++ b/.github/workflows/ci_sim.yml @@ -111,7 +111,6 @@ jobs: env: LLVM_REPO: https://github.com/vpto-dev/llvm-project.git LLVM_REF: feature-vpto-llvm21 - PTO_INSTALL_DIR: ${{ github.workspace }}/install PTOAS_VENV: ${{ github.workspace }}/.work/ptoas-sim-venv VPTO_SIM_WORKSPACE: ${{ github.workspace }}/.work/vpto-sim-ci TILELANG_DSL_WORKSPACE: ${{ github.workspace }}/.work/tilelang-dsl-ci @@ -154,7 +153,7 @@ jobs: fi echo "ASCEND_HOME_PATH=${ASCEND_HOME_PATH_DETECTED}" >> "${GITHUB_ENV}" - echo "PTOAS_BIN=${GITHUB_WORKSPACE}/install/bin/ptoas" >> "${GITHUB_ENV}" + echo "PTOAS_BIN=${PTOAS_VENV}/bin/ptoas" >> "${GITHUB_ENV}" - name: Ensure runner dependencies shell: bash @@ -170,7 +169,7 @@ jobs: if [[ "${#missing_tools[@]}" -gt 0 ]]; then if command -v sudo >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1; then sudo apt-get update - sudo apt-get install -y python3 python3-pip git cmake ninja-build make + sudo apt-get install -y python3 python3-pip python3-venv git cmake ninja-build make else echo "ERROR: missing required tools on self-hosted runner: ${missing_tools[*]}" >&2 echo "ERROR: automatic installation requires sudo + apt-get" >&2 @@ -178,26 +177,14 @@ jobs: fi fi - python3 -m pip --version >/dev/null 2>&1 || { + if ! python3 -m ensurepip --version >/dev/null 2>&1; then if command -v sudo >/dev/null 2>&1 && command -v apt-get >/dev/null 2>&1; then sudo apt-get update - sudo apt-get install -y python3-pip + sudo apt-get install -y python3-pip python3-venv else - echo "ERROR: python3-pip is required on self-hosted runner" >&2 + echo "ERROR: python3-venv is required on self-hosted runner" >&2 exit 1 fi - } - - need_pip_install=0 - python3 -c "import numpy" >/dev/null 2>&1 || need_pip_install=1 - python3 -c "import scikit_build_core" >/dev/null 2>&1 || need_pip_install=1 - python3 -m pybind11 --cmakedir >/dev/null 2>&1 || need_pip_install=1 - python3 -m nanobind --cmake_dir >/dev/null 2>&1 || need_pip_install=1 - python3 -c "import ml_dtypes" >/dev/null 2>&1 || need_pip_install=1 - - if [[ "${need_pip_install}" -eq 1 ]]; then - python3 -m pip install --upgrade pip - python3 -m pip install 'scikit-build-core>=0.12.2,<2' 'pybind11<3' nanobind numpy ml-dtypes fi - name: Configure ccache @@ -230,7 +217,6 @@ jobs: run: | set -euo pipefail echo "PTO_DSL_ST_BUILD_DIR=${GITHUB_WORKSPACE}/build-ptodsl" >> "${GITHUB_ENV}" - echo "PTO_DSL_ST_INSTALL_DIR=${GITHUB_WORKSPACE}/install-ptodsl" >> "${GITHUB_ENV}" - name: Resolve LLVM cache key id: llvm-cache-key @@ -246,7 +232,7 @@ jobs: exit 1 fi echo "sha=${sha}" >> "${GITHUB_OUTPUT}" - echo "key=llvm-build-${sha}-assert-v1" >> "${GITHUB_OUTPUT}" + echo "key=llvm-build-${sha}-assert-v2" >> "${GITHUB_OUTPUT}" - name: Restore LLVM build cache id: llvm-cache @@ -262,8 +248,6 @@ jobs: set -euo pipefail rm -rf "${GITHUB_WORKSPACE}/build" rm -rf "${GITHUB_WORKSPACE}/build-ptodsl" - rm -rf "${PTO_INSTALL_DIR}" - rm -rf "${PTO_DSL_ST_INSTALL_DIR}" rm -rf "${PTOAS_VENV}" rm -rf "${VPTO_SIM_WORKSPACE}" rm -rf "${TILELANG_DSL_WORKSPACE}" @@ -272,6 +256,16 @@ jobs: rm -rf "${PTO_ISA_ROOT}" rm -rf "${GITHUB_WORKSPACE}/.work/camodel" + - name: Create PTOAS simulator environment + shell: bash + run: | + set -euo pipefail + python3 -m venv "${PTOAS_VENV}" + "${PTOAS_VENV}/bin/python" -m pip install --upgrade pip + "${PTOAS_VENV}/bin/pip" install \ + 'scikit-build-core>=0.12.2,<2' 'pybind11<3' \ + nanobind numpy ml-dtypes + - name: Prepare LLVM source shell: bash run: | @@ -309,10 +303,10 @@ jobs: -DBUILD_SHARED_LIBS=ON \ -DLLVM_ENABLE_ASSERTIONS=ON \ -DMLIR_ENABLE_BINDINGS_PYTHON=ON \ - -DPython3_EXECUTABLE=python3 \ - -DPython_EXECUTABLE=python3 \ - -Dpybind11_DIR="$(python3 -m pybind11 --cmakedir)" \ - -Dnanobind_DIR="$(python3 -m nanobind --cmake_dir)" \ + -DPython3_EXECUTABLE="${PTOAS_VENV}/bin/python" \ + -DPython_EXECUTABLE="${PTOAS_VENV}/bin/python" \ + -Dpybind11_DIR="$("${PTOAS_VENV}/bin/python" -m pybind11 --cmakedir)" \ + -Dnanobind_DIR="$("${PTOAS_VENV}/bin/python" -m nanobind --cmake_dir)" \ -DCMAKE_BUILD_TYPE=Release \ -DLLVM_TARGETS_TO_BUILD="host" @@ -326,17 +320,10 @@ jobs: path: ${{ env.LLVM_DIR }} key: ${{ steps.llvm-cache-key.outputs.key }} - - name: Install PTOAS editable in simulator venv + - name: Install PTOAS editable shell: bash run: | set -euo pipefail - rm -rf "${PTO_INSTALL_DIR}" - rm -rf "${PTOAS_VENV}" - python3 -m venv "${PTOAS_VENV}" - "${PTOAS_VENV}/bin/python" -m pip install --upgrade pip - "${PTOAS_VENV}/bin/pip" install \ - 'scikit-build-core>=0.12.2,<2' 'pybind11<3' \ - nanobind numpy ml-dtypes # Pin system compilers for the same reason as LLVM above. export CC=gcc export CXX=g++ @@ -344,7 +331,6 @@ jobs: "${PTOAS_VENV}/bin/python" -m pip install --editable . \ --no-build-isolation --no-deps \ --config-settings="build-dir=${GITHUB_WORKSPACE}/build" - cmake --install "${GITHUB_WORKSPACE}/build" --prefix "${PTO_INSTALL_DIR}" PATH="${PTOAS_VENV}/bin:${PATH}" \ PYTHON="${PTOAS_VENV}/bin/python" \ bash docker/test_wheel_imports.sh @@ -791,14 +777,13 @@ jobs: shell: bash run: | set -euo pipefail - rm -rf "${PTO_DSL_ST_BUILD_DIR}" "${PTO_DSL_ST_INSTALL_DIR}" + rm -rf "${PTO_DSL_ST_BUILD_DIR}" export CC=gcc export CXX=g++ LLVM_BUILD_DIR="${PTO_DSL_ST_LLVM_DIR}" \ "${PTO_DSL_ST_PYTHON_BIN}" -m pip install --editable . \ --no-build-isolation --no-deps \ --config-settings="build-dir=${PTO_DSL_ST_BUILD_DIR}" - cmake --install "${PTO_DSL_ST_BUILD_DIR}" --prefix "${PTO_DSL_ST_INSTALL_DIR}" - name: Probe PTODSL runtime Python shell: bash @@ -923,7 +908,6 @@ jobs: set -euo pipefail mkdir -p "${TILELANG_DSL_UT_WORKSPACE}" export PATH="${PTOAS_VENV}/bin:${PATH}" - export LD_LIBRARY_PATH="${LLVM_DIR}/lib:${PTO_INSTALL_DIR}/lib:${GITHUB_WORKSPACE}/build/lib:${LD_LIBRARY_PATH:-}" cd tilelang-dsl/python python3 -m unittest discover -s ../tests -p 'test_*.py' \ 2>&1 | tee "${TILELANG_DSL_UT_WORKSPACE}/unittest.log" diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index c0bd2b19d4..ba950c649b 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -8,6 +8,18 @@ include(AddMLIRPython) +# Do not carry toolchain-injected paths, such as a Conda compiler RPATH, into +# installed Python modules. Distribution builds keep only MLIR's relative +# package RPATHs; editable builds add their external link paths below. +set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH ON) + +# scikit-build-core editable installs use the external LLVM build directly. +# Keep this developer-only fallback local to the MLIR Python targets; wheel +# builds use package-relative RPATHs and let auditwheel/delocate collect LLVM. +if(SKBUILD_STATE STREQUAL "editable") + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) +endif() + # This directory materializes C++ sources exported by upstream MLIR. PTOAS # keeps -Werror enabled globally, but upstream sources are not part of the # project warning contract. Scope the exception to this directory; the diff --git a/tools/ptoas/CMakeLists.txt b/tools/ptoas/CMakeLists.txt index 0ec5afe766..c0fb306764 100644 --- a/tools/ptoas/CMakeLists.txt +++ b/tools/ptoas/CMakeLists.txt @@ -6,6 +6,18 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. +# Do not carry toolchain-injected paths, such as a Conda compiler RPATH, into +# installed Python modules. Distribution builds keep only MLIR's relative +# package RPATHs; editable builds add their external link paths below. +set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH ON) + +# scikit-build-core editable installs use the external LLVM build directly. +# Keep this developer-only fallback local to the PTOAS Python extension; wheel +# builds use package-relative RPATHs and let auditwheel/delocate collect LLVM. +if(SKBUILD_STATE STREQUAL "editable") + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) +endif() + set(PTOAS_RUNTIME_SOURCES ptoas.cpp driver.cpp From aa825b9637ab7a242229e74d06c20742ebde3283 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Mon, 27 Jul 2026 12:48:33 +0800 Subject: [PATCH 14/19] build: retain ccache in wheel environments --- .github/workflows/build_wheel.yml | 2 +- .github/workflows/build_wheel_mac.yml | 2 +- docker/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index c309932bc5..11ff6ee9ef 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -129,7 +129,7 @@ jobs: - name: Install system dependencies run: | - dnf install -y ninja-build cmake git gcc-c++ lld zip binutils patchelf chrpath + dnf install -y ninja-build cmake git ccache gcc-c++ lld zip binutils patchelf chrpath dnf clean all - name: Install Python dependencies diff --git a/.github/workflows/build_wheel_mac.yml b/.github/workflows/build_wheel_mac.yml index b3e96f8ff5..b047c1b280 100644 --- a/.github/workflows/build_wheel_mac.yml +++ b/.github/workflows/build_wheel_mac.yml @@ -129,7 +129,7 @@ jobs: - name: Install system dependencies run: | - brew install ninja + brew install ninja ccache - name: Install Python dependencies run: | diff --git a/docker/Dockerfile b/docker/Dockerfile index 0911fdb594..aac5865981 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -19,7 +19,7 @@ ENV PY_PATH="/opt/python/${PY_VER}" ENV PATH="${PY_PATH}/bin:${PATH}" # dependency -RUN dnf install -y ninja-build cmake git gcc-c++ lld zip binutils patchelf chrpath && dnf clean all +RUN dnf install -y ninja-build cmake git ccache gcc-c++ lld zip binutils patchelf chrpath && dnf clean all RUN pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' auditwheel COPY cmake/LinuxHardeningCache.cmake /tmp/LinuxHardeningCache.cmake From 54a2db92a37399d139d5d1fc8b6e77d5da8c4c5b Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Mon, 27 Jul 2026 20:59:28 +0800 Subject: [PATCH 15/19] build: isolate MLIR Python packaging --- .codex/skills/build-ptoas-wsl/SKILL.md | 6 +- .github/workflows/build_wheel.yml | 35 +- .github/workflows/build_wheel_mac.yml | 15 +- README.md | 10 +- README_en.md | 8 +- cmake/RelocatePTOASCompilerArchive.cmake.in | 190 +++++ docker/collect_ptoas_dist.sh | 255 ------- docker/collect_ptoas_dist_mac.sh | 378 ---------- docker/test_wheel_imports.sh | 20 +- docker/validate_wheel_payload.py | 33 + docs/build_with_installed_llvm.md | 2 +- ...oas-mlir-namespace-and-native-isolation.md | 692 ++++++++++++++++++ docs/designs/ptoas-python-launcher-layout.md | 29 +- lib/Bindings/Python/CMakeLists.txt | 17 +- lib/Bindings/Python/PTOModule.cpp | 2 +- ptodsl/CMakeLists.txt | 4 +- ptodsl/examples/softmax_lowlevel.py | 4 +- ptodsl/examples/tadd_lowlevel.py | 4 +- ptodsl/ptodsl/_allreduce.py | 4 +- ptodsl/ptodsl/_builtin_vector.py | 6 +- ptodsl/ptodsl/_context.py | 6 +- ptodsl/ptodsl/_control_flow.py | 4 +- ptodsl/ptodsl/_jit.py | 2 +- ptodsl/ptodsl/_ops.py | 6 +- ptodsl/ptodsl/_runtime/codegen.py | 2 +- ptodsl/ptodsl/_runtime/launch.py | 2 +- ptodsl/ptodsl/_runtime_scalar_ops.py | 4 +- ptodsl/ptodsl/_scalar_adaptation.py | 4 +- ptodsl/ptodsl/_source_loader.py | 2 +- ptodsl/ptodsl/_surface_types.py | 2 +- ptodsl/ptodsl/_surface_values.py | 8 +- ptodsl/ptodsl/_tile_template_tracing.py | 4 +- ptodsl/ptodsl/_tracing/artifacts.py | 4 +- ptodsl/ptodsl/_tracing/control_flow.py | 6 +- ptodsl/ptodsl/_tracing/module_builder.py | 4 +- ptodsl/ptodsl/_tracing/runtime.py | 4 +- ptodsl/ptodsl/_tracing/session.py | 6 +- ptodsl/ptodsl/_types.py | 14 +- ptodsl/ptodsl/_vmi_namespace.py | 4 +- ptodsl/ptodsl/pto.py | 2 +- ptodsl/ptodsl/scalar.py | 12 +- ptodsl/ptodsl/tilelib/_render_runtime.py | 4 +- ptodsl/ptodsl/tilelib/metadata.py | 2 +- ptodsl/ptodsl/tilelib/templates/a5/tcvt.py | 2 +- .../tests/support/docs_fragment_fixtures.py | 8 +- ptodsl/tests/test_ast_rewrite_example_ir.py | 2 +- ptodsl/tests/test_docs_as_test.py | 2 +- .../test_flash_attention_demo_compile.py | 2 +- ptodsl/tests/test_jit_compile.py | 2 +- ptodsl/tests/test_ptoas_frontend_verify.py | 2 +- ptodsl/tests/test_ptoas_tree_wrapper.py | 25 + ptodsl/tests/test_tileop.py | 2 +- ptodsl/tests/test_vector_cube_ops.py | 2 +- python/pto/dialects/pto.py | 8 +- scripts/sim_dsl.sh | 4 +- test/dsl/abs.py | 2 +- test/dsl/strict_vecscope.py | 2 +- test/dsl/template_abs.py | 2 +- test/python/compact_tile_buf_asm.py | 4 +- test/python/low_precision_types.py | 4 +- test/python/memory_consistency_bindings.py | 4 +- test/samples/Abs/abs.py | 6 +- test/samples/AddPtr/addptr.py | 6 +- test/samples/AddPtr/addptr_chain.py | 6 +- test/samples/AddPtr/addptr_dynamic.py | 6 +- test/samples/AddPtr/addptr_f16.py | 6 +- test/samples/Addc/addc.py | 6 +- test/samples/Adds/adds.py | 6 +- test/samples/Addsc/addsc.py | 6 +- test/samples/AllocTile/alloc_tile_addr.py | 6 +- test/samples/And/and.py | 6 +- test/samples/Ands/ands.py | 6 +- test/samples/AsyncComm/async_comm.py | 4 +- .../AsyncComm/tget_async_kernel_impl_like.py | 4 +- .../AsyncComm/tput_async_kernel_impl_like.py | 4 +- test/samples/Bf16/bf16_tile.py | 4 +- test/samples/Ci/ci.py | 6 +- test/samples/Cmp/cmp.py | 6 +- test/samples/Cmps/cmps.py | 6 +- test/samples/Colexpand/colexpand.py | 6 +- test/samples/Colexpandadd/colexpandadd.py | 6 +- test/samples/Colexpanddiv/colexpanddiv.py | 6 +- ...colexpanddiv_src1_vcol_mismatch_invalid.py | 6 +- .../Colexpandexpdif/colexpandexpdif.py | 6 +- .../colexpandexpdif_dtype_invalid.py | 6 +- test/samples/Colexpandmax/colexpandmax.py | 6 +- test/samples/Colexpandmin/colexpandmin.py | 6 +- test/samples/Colexpandmul/colexpandmul.py | 6 +- test/samples/Colexpandsub/colexpandsub.py | 6 +- .../colexpandsub_src0_layout_invalid.py | 6 +- test/samples/Colmax/colmax.py | 6 +- test/samples/Colmin/colmin.py | 6 +- test/samples/Colprod/colprod.py | 6 +- test/samples/Colsum/colsum.py | 6 +- test/samples/CommSync/comm_collective.py | 4 +- .../comm_collective_binding_variants.py | 4 +- test/samples/CommSync/comm_p2p.py | 4 +- .../CommSync/comm_p2p_binding_variants.py | 4 +- .../CommSync/tbroadcast_root_binding.py | 4 +- test/samples/CommSync/tgather_root_binding.py | 4 +- .../CommSync/tnotify_atomic_add_binding.py | 4 +- test/samples/CommSync/treduce_root_binding.py | 4 +- .../samples/CommSync/tscatter_root_binding.py | 4 +- test/samples/CommSync/twait_atomic_binding.py | 4 +- test/samples/Complex/cv_region.py | 4 +- test/samples/Complex/mix_kernel.py | 6 +- test/samples/Concat/concat.py | 6 +- test/samples/Cvt/cvt_f32_f16.py | 4 +- test/samples/Cvt/cvt_f32_f32.py | 6 +- test/samples/Cvt/tcvt.py | 4 +- test/samples/Dequant/dequant.py | 4 +- test/samples/Dequant/dequant_i8.py | 4 +- test/samples/Div/div.py | 6 +- test/samples/Divs/divs.py | 6 +- test/samples/Divs2/divs2.py | 6 +- .../DynamicTailMatmul/dynamic_tail_matmul.py | 4 +- test/samples/Exp/exp.py | 6 +- test/samples/Expands/expand.py | 6 +- test/samples/Extract/extract.py | 6 +- test/samples/Extract/extract_fp.py | 6 +- test/samples/Fillpad/fillpad.py | 6 +- test/samples/Fillpad/fillpad_expand.py | 6 +- .../samples/Fillpad/fillpad_expand_invalid.py | 6 +- .../fillpad_expand_pad_null_invalid.py | 6 +- test/samples/Fillpad/fillpad_inplace.py | 6 +- test/samples/Fmod/fmod.py | 6 +- test/samples/Fmods/fmods.py | 6 +- .../Fmods/tfmods_scalar_type_invalid.py | 6 +- test/samples/Gather/gather.py | 6 +- test/samples/Gather/gather_legacy.py | 6 +- test/samples/Gatherb/gatherb.py | 4 +- test/samples/Gemv/gemv.py | 6 +- test/samples/Gemv/gemvacc.py | 6 +- test/samples/Gemv/gemvbias.py | 6 +- test/samples/Gemvmx/gemvmx.py | 6 +- .../Layout/tensor_view_infer_layout_dn.py | 6 +- test/samples/Layout/tensor_view_layout_dn.py | 4 +- .../LayoutInference/layout_inference.py | 4 +- test/samples/Log/log.py | 6 +- test/samples/Lrelu/lrelu.py | 6 +- test/samples/MatMul/tmatmulk.py | 8 +- .../matmul_mx_low_precision.py | 4 +- .../Matmul_transpose/Matmul_transpose.py | 6 +- test/samples/Max/max.py | 6 +- test/samples/Maxs/maxs.py | 6 +- test/samples/Mgather/mgather.py | 6 +- test/samples/Min/min.py | 6 +- test/samples/Mins/mins.py | 6 +- test/samples/Movfp/movfp.py | 6 +- test/samples/Mrgsort/mrgsort.py | 6 +- test/samples/Mrgsort/mrgsort_a5.py | 6 +- test/samples/Mrgsort/mrgsort_format2.py | 8 +- test/samples/Mscatter/mscatter.py | 6 +- test/samples/Mul/mul.py | 6 +- test/samples/Muls/muls.py | 6 +- test/samples/Neg/neg.py | 6 +- test/samples/Not/not.py | 6 +- test/samples/Or/or.py | 6 +- test/samples/Ors/ors.py | 6 +- test/samples/Partadd/partadd.py | 6 +- test/samples/Partarg/partarg.py | 4 +- test/samples/Partition5D/partition5d.py | 4 +- test/samples/Partition5D/partition5d_a5.py | 4 +- test/samples/Partmax/partmax.py | 6 +- test/samples/Partmin/partmin.py | 6 +- test/samples/Partmul/partmul.py | 6 +- test/samples/Prelu/prelu.py | 6 +- test/samples/Print/print.py | 6 +- test/samples/Print/print_scalar.py | 6 +- test/samples/Quant/quant.py | 4 +- test/samples/Quant/quant_asym.py | 4 +- test/samples/Recip/recip.py | 6 +- test/samples/Relu/relu.py | 6 +- test/samples/Rem/rem.py | 6 +- test/samples/Rems/rems.py | 6 +- test/samples/Reshape/bitcast_dtype_alias.py | 6 +- test/samples/Reshape/bitcast_inplace_cvt.py | 6 +- .../Reshape/bitcast_same_dtype_invalid.py | 6 +- test/samples/Reshape/reshape.py | 6 +- test/samples/Rowexpand/rowexpand.py | 6 +- test/samples/Rowexpandadd/rowexpandadd.py | 6 +- .../rowexpandadd_src1_width_invalid.py | 6 +- test/samples/Rowexpanddiv/rowexpanddiv.py | 6 +- .../Rowexpandexpdif/rowexpandexpdif.py | 6 +- .../rowexpandexpdif_dtype_invalid.py | 6 +- test/samples/Rowexpandmax/rowexpandmax.py | 6 +- .../rowexpandmax_a5_tmp_invalid.py | 6 +- test/samples/Rowexpandmin/rowexpandmin.py | 6 +- test/samples/Rowexpandmul/rowexpandmul.py | 6 +- test/samples/Rowexpandsub/rowexpandsub.py | 6 +- test/samples/Rowmax/rowmax.py | 6 +- test/samples/Rowmin/rowmin.py | 6 +- test/samples/Rowprod/rowprod.py | 6 +- test/samples/Rowsum/rowsum.py | 6 +- test/samples/Rsqrt/rsqrt.py | 6 +- test/samples/ScalarPtr/scalar_ptr.py | 6 +- test/samples/Scatter/scatter.py | 4 +- test/samples/Sel/sel.py | 6 +- test/samples/Sels/sels.py | 6 +- test/samples/SetValidShape/set_validshape.py | 6 +- test/samples/Shl/shl.py | 6 +- test/samples/Shls/shls.py | 6 +- test/samples/Shr/shr.py | 6 +- test/samples/Shrs/shrs.py | 6 +- test/samples/Sort32/sort32.py | 6 +- test/samples/Sqrt/sqrt.py | 6 +- test/samples/Storefp/storefp.py | 6 +- test/samples/Storefp/storefp_invalid.py | 6 +- test/samples/Sub/sub.py | 6 +- test/samples/SubView/subview.py | 6 +- test/samples/SubView/subview_boxed_dynamic.py | 6 +- test/samples/SubView/subview_boxed_invalid.py | 6 +- test/samples/SubView/subview_tsubs.py | 6 +- test/samples/SubView/vadd_pto_pingpong.py | 6 +- test/samples/Subc/subc.py | 6 +- test/samples/Subs/subs.py | 6 +- test/samples/Subsc/subsc.py | 6 +- test/samples/Sync/sync.py | 6 +- test/samples/Sync/syncHigh.py | 6 +- test/samples/Sync/test_a5_buf_sync.py | 4 +- test/samples/Sync/test_inject_sync_if.py | 4 +- test/samples/Sync/test_inject_sync_if_else.py | 4 +- .../test_inject_sync_intra_pipe_barrier.py | 6 +- test/samples/Sync/test_inject_sync_loop.py | 6 +- .../Sync/test_inject_sync_loop_nest.py | 6 +- .../Sync/test_inject_sync_two_event_id.py | 4 +- test/samples/Sync/test_intercore_sync_a3.py | 4 +- .../Sync/test_intercore_sync_a3_dyn.py | 4 +- .../test_intercore_sync_a3_missing_setffts.py | 4 +- .../Sync/test_intercore_sync_a3_modes.py | 4 +- test/samples/Sync/test_intercore_sync_a5.py | 4 +- .../Sync/test_intercore_sync_a5_dyn.py | 4 +- .../Sync/test_intercore_sync_a5_functional.py | 4 +- .../Sync/test_intercore_sync_a5_ptoisa_vec.py | 4 +- .../Sync/test_mem_inject_sync_basic.py | 4 +- .../samples/Sync/test_set_wait_unified_api.py | 6 +- test/samples/Sync/tmatmulk_autosync.py | 6 +- test/samples/Sync/tmatmulk_autosync_a5.py | 6 +- test/samples/SyncAll/syncall_binding.py | 4 +- test/samples/TInsert/tinsert.py | 6 +- test/samples/TInsert/tinsert_fp.py | 6 +- test/samples/TPrefetch/tprefetch.py | 4 +- .../TPrefetchAsync/tprefetch_async_binding.py | 4 +- test/samples/TTri/ttri.py | 4 +- .../TileSetGetValue/tileSetGetValue.py | 6 +- .../tile_getval_mat_invalid.py | 6 +- test/samples/Tpow/tpow.py | 6 +- test/samples/Tpows/tpows.py | 6 +- test/samples/Trans/trans.py | 6 +- test/samples/Trap/trap.py | 4 +- test/samples/VectorAddition/vadd_pto_ir.py | 6 +- .../samples/VectorAddition/vadd_validshape.py | 6 +- .../VectorAddition/vadd_validshape_dynamic.py | 6 +- .../VectorAddition/vadd_validshape_hyper.py | 6 +- test/samples/Xor/xor.py | 6 +- test/samples/Xors/xors.py | 6 +- test/tilelib-st/README.md | 2 +- tilelang-dsl/CMakeLists.txt | 4 +- .../python/tilelang_dsl/env_config.py | 6 +- .../python/tilelang_dsl/lowering_backend.py | 12 +- .../python/tilelang_dsl/pybind_renderer.py | 18 +- .../tests/backend/test_e2e_pybind_backend.py | 2 +- tools/ptoas/CMakeLists.txt | 36 +- tools/ptoas/NativeModule.cpp | 2 +- tools/ptoas/ptoas_wrapper.py | 13 + 265 files changed, 1748 insertions(+), 1326 deletions(-) create mode 100644 cmake/RelocatePTOASCompilerArchive.cmake.in delete mode 100755 docker/collect_ptoas_dist.sh delete mode 100644 docker/collect_ptoas_dist_mac.sh create mode 100644 docs/designs/ptoas-mlir-namespace-and-native-isolation.md diff --git a/.codex/skills/build-ptoas-wsl/SKILL.md b/.codex/skills/build-ptoas-wsl/SKILL.md index dabd88045d..a35773f03c 100644 --- a/.codex/skills/build-ptoas-wsl/SKILL.md +++ b/.codex/skills/build-ptoas-wsl/SKILL.md @@ -160,8 +160,8 @@ Validate Python dialect loading: ```bash python3 - <<'PY' -from mlir.ir import Context, Module, Location -from mlir.dialects import pto +from ptoas.mlir.ir import Context, Module, Location +from ptoas.mlir.dialects import pto with Context() as ctx, Location.unknown(): pto.register_dialect(ctx, load=True) @@ -174,6 +174,6 @@ PY - `def_property family does not currently support keep_alive`: reinstall `pybind11==2.12.0`, clear the affected CMake cache if needed, and reconfigure. - CMake cannot find LLVM or MLIR: confirm `LLVM_DIR=$LLVM_BUILD_DIR/lib/cmake/llvm` and `MLIR_DIR=$LLVM_BUILD_DIR/lib/cmake/mlir` exist and were produced by the `llvmorg-19.1.7` build. -- Python cannot import `mlir.dialects.pto`: re-export `PYTHONPATH` with MLIR core first and PTO install second, and confirm `_pto.cpython-*.so` exists under MLIR's `_mlir_libs`. +- Python cannot import `ptoas.mlir.dialects.pto`: make sure the PTOAS build/install Python root is on `PYTHONPATH`, and confirm `_core.cpython-*.so` and `ptoas/mlir/_mlir_libs/_mlir*.so` exist in the same package tree. - Runtime linker errors for LLVM or PTO libraries: re-export `LD_LIBRARY_PATH=$LLVM_BUILD_DIR/lib:$PTO_INSTALL_DIR/lib:$LD_LIBRARY_PATH`. - Builds are very slow under `/mnt/c`: move the workspace into the WSL Linux filesystem, for example `$HOME/llvm-workspace`. diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index 11ff6ee9ef..a047da35d6 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -150,7 +150,6 @@ jobs: echo "LLVM_BUILD_DIR=/llvm-workspace/llvm-project/build-release" >> $GITHUB_ENV echo "PTO_SOURCE_DIR=$GITHUB_WORKSPACE" >> $GITHUB_ENV echo "PTO_BUILD_DIR=$GITHUB_WORKSPACE/build-release" >> $GITHUB_ENV - echo "PTO_INSTALL_DIR=$GITHUB_WORKSPACE/install-release" >> $GITHUB_ENV - name: Resolve LLVM source SHA id: llvm-source @@ -262,8 +261,13 @@ jobs: - name: Collect ptoas binary and dependencies if: matrix.python == '3.11' run: | - cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" - bash $PTO_SOURCE_DIR/docker/collect_ptoas_dist.sh $GITHUB_WORKSPACE/ptoas-dist + rm -rf "$GITHUB_WORKSPACE/ptoas-dist" + cmake --install "${PTO_BUILD_DIR}" \ + --prefix "$GITHUB_WORKSPACE/ptoas-dist" \ + --component PTOAS_Python + cmake --install "${PTO_BUILD_DIR}" \ + --prefix "$GITHUB_WORKSPACE/ptoas-dist" \ + --component PTOAS_CompilerArchive - name: Archive ptoas binary artifact if: matrix.python == '3.11' @@ -272,6 +276,31 @@ jobs: tar -czf "$GITHUB_WORKSPACE/ptoas-bin-${{ matrix.arch }}.tar.gz" \ -C "$GITHUB_WORKSPACE/ptoas-dist" . + - name: Smoke test archived ptoas binary artifact + if: matrix.python == '3.11' + run: | + TEST_DIR="$RUNNER_TEMP/ptoas-dist-smoke-${{ matrix.arch }}" + rm -rf "$TEST_DIR" + mkdir -p "$TEST_DIR/extracted" + tar -xzf "$GITHUB_WORKSPACE/ptoas-bin-${{ matrix.arch }}.tar.gz" \ + -C "$TEST_DIR/extracted" + + test -x "$TEST_DIR/extracted/bin/ptoas" + test -f "$TEST_DIR/extracted/ptoas/_cli.py" + test -f "$TEST_DIR/extracted/ptoas/mlir/ir.py" + test -f "$TEST_DIR/extracted/ptodsl/__init__.py" + test -f "$TEST_DIR/extracted/tilelang_dsl/__init__.py" + test -d "$TEST_DIR/extracted/share/ptoas/TileOps" + test "$(cat "$TEST_DIR/extracted/.ptoas-python-version")" = "3.11" + compgen -G "$TEST_DIR/extracted/ptoas/_core*.so" >/dev/null + + env -u PYTHONPATH -u DYLD_LIBRARY_PATH -u LD_LIBRARY_PATH \ + "$TEST_DIR/extracted/bin/ptoas" --version + env -u PYTHONPATH -u DYLD_LIBRARY_PATH -u LD_LIBRARY_PATH \ + "$TEST_DIR/extracted/bin/ptoas" \ + "$PTO_SOURCE_DIR/test/lit/pto/kernel_kind_vector_scf_while_emitc.pto" \ + >/dev/null + - name: Upload ptoas binary artifact if: matrix.python == '3.11' uses: actions/upload-artifact@v4 diff --git a/.github/workflows/build_wheel_mac.yml b/.github/workflows/build_wheel_mac.yml index b047c1b280..1158508314 100644 --- a/.github/workflows/build_wheel_mac.yml +++ b/.github/workflows/build_wheel_mac.yml @@ -149,7 +149,6 @@ jobs: echo "LLVM_BUILD_DIR=${RUNNER_TEMP}/llvm-workspace/llvm-project/build-release" >> $GITHUB_ENV echo "PTO_SOURCE_DIR=$GITHUB_WORKSPACE" >> $GITHUB_ENV echo "PTO_BUILD_DIR=$GITHUB_WORKSPACE/build-release" >> $GITHUB_ENV - echo "PTO_INSTALL_DIR=$GITHUB_WORKSPACE/install-release" >> $GITHUB_ENV - name: Resolve LLVM source SHA id: llvm-source @@ -338,8 +337,13 @@ jobs: - name: Collect ptoas binary and dependencies if: matrix.python == '3.11' run: | - cmake --install "${PTO_BUILD_DIR}" --prefix "${PTO_INSTALL_DIR}" - bash "$PTO_SOURCE_DIR/docker/collect_ptoas_dist_mac.sh" "$GITHUB_WORKSPACE/ptoas-dist" + rm -rf "$GITHUB_WORKSPACE/ptoas-dist" + cmake --install "${PTO_BUILD_DIR}" \ + --prefix "$GITHUB_WORKSPACE/ptoas-dist" \ + --component PTOAS_Python + cmake --install "${PTO_BUILD_DIR}" \ + --prefix "$GITHUB_WORKSPACE/ptoas-dist" \ + --component PTOAS_CompilerArchive - name: Archive ptoas binary artifact if: matrix.python == '3.11' @@ -358,6 +362,11 @@ jobs: test -x "$TEST_DIR/extracted/bin/ptoas" test -f "$TEST_DIR/extracted/ptoas/_cli.py" + test -f "$TEST_DIR/extracted/ptoas/mlir/ir.py" + test -f "$TEST_DIR/extracted/ptodsl/__init__.py" + test -f "$TEST_DIR/extracted/tilelang_dsl/__init__.py" + test -d "$TEST_DIR/extracted/share/ptoas/TileOps" + test "$(cat "$TEST_DIR/extracted/.ptoas-python-version")" = "3.11" compgen -G "$TEST_DIR/extracted/ptoas/_core*.so" >/dev/null env -u PYTHONPATH -u DYLD_LIBRARY_PATH -u LD_LIBRARY_PATH \ diff --git a/README.md b/README.md index e17ca864b3..64f3858ed5 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ pip install /path/to/ptoas*.whl ```python import ptodsl from ptodsl import pto, scalar -from mlir.dialects import pto as mlir_pto +from ptoas.mlir.dialects import pto as mlir_pto ``` > 说明: @@ -184,7 +184,7 @@ from mlir.dialects import pto as mlir_pto ## 4. 运行环境配置 (Runtime Environment) 如果你已经通过 `pip install .`、`pip install -e .` 或 `pip install ptoas*.whl` -完成安装,那么 `import ptodsl` / `from mlir.dialects import pto` / `ptoas` +完成安装,那么 `import ptodsl` / `from ptoas.mlir.dialects import pto` / `ptoas` 都不应再依赖手动设置 `PYTHONPATH`。 下面这组环境变量主要用于**直接消费 build/install tree** 的场景,例如: @@ -243,9 +243,9 @@ ptoas --version 在支持的 `ptoas` 安装环境中,PTO Dialect 与 PTODSL 都可以直接导入。 ```python -from mlir.ir import Context, Module, Location -# [关键] 从 mlir.dialects 导入 pto,这是 Out-of-tree 绑定的标准用法 -from mlir.dialects import pto +from ptoas.mlir.ir import Context, Module, Location +# PTOAS 自带的 MLIR Python API 位于 ptoas.mlir 命名空间。 +from ptoas.mlir.dialects import pto from ptodsl import pto as jit_pto, scalar with Context() as ctx, Location.unknown(): diff --git a/README_en.md b/README_en.md index 2dc0de52fe..f582003bb2 100644 --- a/README_en.md +++ b/README_en.md @@ -152,7 +152,7 @@ After installation, the following imports should work directly: ```python import ptodsl from ptodsl import pto, scalar -from mlir.dialects import pto as mlir_pto +from ptoas.mlir.dialects import pto as mlir_pto ``` > Notes: @@ -198,9 +198,9 @@ In a supported `ptoas` install environment, both the PTO Dialect and PTODSL can be imported directly. ```python -from mlir.ir import Context, Module, Location -# [Key] Import pto from mlir.dialects — the standard pattern for out-of-tree bindings -from mlir.dialects import pto +from ptoas.mlir.ir import Context, Module, Location +# PTOAS ships its MLIR Python API in the ptoas.mlir namespace. +from ptoas.mlir.dialects import pto from ptodsl import pto as jit_pto, scalar with Context() as ctx, Location.unknown(): diff --git a/cmake/RelocatePTOASCompilerArchive.cmake.in b/cmake/RelocatePTOASCompilerArchive.cmake.in new file mode 100644 index 0000000000..2acb48de7f --- /dev/null +++ b/cmake/RelocatePTOASCompilerArchive.cmake.in @@ -0,0 +1,190 @@ +# Copyright (c) 2026 Huawei Technologies Co., Ltd. +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of +# CANN Open Software License Agreement Version 2.0 (the "License"). +# Please refer to the License for details. You may not use this file except in compliance with the License. +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE in the root of the software repository for the full text of the License. + +# Relocate a staged PTOAS compiler archive. This script intentionally runs at +# install time: CMake inspects the binaries that are present in the explicit +# staging prefix, computes their runtime dependency closure, and copies only +# external dependencies into /lib. + +# A full developer `cmake --install` keeps the normal install-tree contract. +# Relocation is an explicit archive-staging operation selected with +# `--component PTOAS_CompilerArchive`. +if(NOT CMAKE_INSTALL_COMPONENT STREQUAL "PTOAS_CompilerArchive") + return() +endif() + +set(_ptoas_archive_root "${CMAKE_INSTALL_PREFIX}") +set(_ptoas_package_root "${_ptoas_archive_root}/ptoas") +set(_ptoas_mlir_lib_root "${_ptoas_package_root}/mlir/_mlir_libs") +set(_ptoas_external_lib_root "${_ptoas_archive_root}/lib") + +if(NOT EXISTS "${_ptoas_package_root}/_cli.py") + message(FATAL_ERROR + "PTOAS compiler archive is missing ptoas/_cli.py under ${_ptoas_archive_root}; " + "install component PTOAS_Python before PTOAS_CompilerArchive") +endif() + +set(_ptoas_known_native_files + "${_ptoas_package_root}/$" + "${_ptoas_mlir_lib_root}/$" +) +foreach(_ptoas_native IN LISTS _ptoas_known_native_files) + if(NOT EXISTS "${_ptoas_native}") + message(FATAL_ERROR + "PTOAS compiler archive is missing native entry point ${_ptoas_native}; " + "install component PTOAS_Python before PTOAS_CompilerArchive") + endif() +endforeach() + +# AddMLIRPython owns the concrete module target list. Treat its installed +# extension directory as the plugin boundary, as opposed to scanning the +# complete archive tree for arbitrary shared libraries. +file(GLOB _ptoas_generated_native_files LIST_DIRECTORIES FALSE + "${_ptoas_mlir_lib_root}/*.so" + "${_ptoas_mlir_lib_root}/*.so.*" + "${_ptoas_mlir_lib_root}/*.dylib") +set(_ptoas_archive_native_files + ${_ptoas_known_native_files} + ${_ptoas_generated_native_files}) +list(REMOVE_DUPLICATES _ptoas_archive_native_files) +if(NOT _ptoas_generated_native_files) + message(FATAL_ERROR + "PTOAS compiler archive contains no MLIR native modules under " + "${_ptoas_mlir_lib_root}; " + "install component PTOAS_Python before PTOAS_CompilerArchive") +endif() + +file(MAKE_DIRECTORY "${_ptoas_external_lib_root}") +set(_ptoas_dependency_search_dirs + "${_ptoas_mlir_lib_root}" + "${_ptoas_archive_root}/lib" + "@LLVM_BUILD_LIBRARY_DIR@") + +file(GET_RUNTIME_DEPENDENCIES + LIBRARIES ${_ptoas_archive_native_files} + DIRECTORIES ${_ptoas_dependency_search_dirs} + RESOLVED_DEPENDENCIES_VAR _ptoas_resolved_dependencies + UNRESOLVED_DEPENDENCIES_VAR _ptoas_unresolved_dependencies + CONFLICTING_DEPENDENCIES_PREFIX _ptoas_conflicting_dependencies + POST_EXCLUDE_REGEXES + "^/lib/.*" + "^/lib64/.*" + "^/usr/lib/.*" + "^/usr/lib64/.*" + "^/System/Library/.*") + +if(_ptoas_unresolved_dependencies) + list(JOIN _ptoas_unresolved_dependencies "\n " _ptoas_unresolved_text) + message(FATAL_ERROR + "Unresolved PTOAS compiler archive dependencies:\n ${_ptoas_unresolved_text}") +endif() + +# A basename collision is harmless only when every candidate has identical +# contents. Otherwise flattening the dependency closure into lib/ would make +# the selected ABI depend on search order. +foreach(_ptoas_conflicting_name IN LISTS + _ptoas_conflicting_dependencies_FILENAMES) + set(_ptoas_conflicting_paths_var + "_ptoas_conflicting_dependencies_${_ptoas_conflicting_name}") + set(_ptoas_conflicting_paths ${${_ptoas_conflicting_paths_var}}) + list(GET _ptoas_conflicting_paths 0 _ptoas_selected_dependency) + file(SHA256 "${_ptoas_selected_dependency}" _ptoas_selected_sha256) + set(_ptoas_conflict_is_identical TRUE) + foreach(_ptoas_conflicting_path IN LISTS _ptoas_conflicting_paths) + file(SHA256 "${_ptoas_conflicting_path}" _ptoas_conflicting_sha256) + if(NOT _ptoas_conflicting_sha256 STREQUAL _ptoas_selected_sha256) + set(_ptoas_conflict_is_identical FALSE) + break() + endif() + endforeach() + + if(NOT _ptoas_conflict_is_identical) + list(JOIN _ptoas_conflicting_paths "\n " _ptoas_conflicting_text) + message(FATAL_ERROR + "Conflicting PTOAS compiler archive dependency " + "${_ptoas_conflicting_name}:\n ${_ptoas_conflicting_text}") + endif() + list(APPEND _ptoas_resolved_dependencies "${_ptoas_selected_dependency}") +endforeach() +list(REMOVE_DUPLICATES _ptoas_resolved_dependencies) + +foreach(_ptoas_dependency IN LISTS _ptoas_resolved_dependencies) + file(REAL_PATH "${_ptoas_dependency}" _ptoas_dependency_real) + string(FIND "${_ptoas_dependency_real}" "${_ptoas_archive_root}/" _ptoas_is_staged) + if(_ptoas_is_staged EQUAL 0) + continue() + endif() + + get_filename_component(_ptoas_dependency_name "${_ptoas_dependency_real}" NAME) + if(_ptoas_dependency_name MATCHES "^libPTOASPythonCAPI") + continue() + endif() + file(INSTALL "${_ptoas_dependency}" + DESTINATION "${_ptoas_external_lib_root}" + TYPE SHARED_LIBRARY + FOLLOW_SYMLINK_CHAIN) +endforeach() + +if(APPLE) + find_program(_ptoas_delocate_path NAMES delocate-path REQUIRED) + execute_process( + COMMAND "${_ptoas_delocate_path}" + --dylibs-only + --lib-path "${_ptoas_external_lib_root}" + "${_ptoas_package_root}" + RESULT_VARIABLE _ptoas_delocate_result + COMMAND_ECHO STDOUT) + if(NOT _ptoas_delocate_result EQUAL 0) + message(FATAL_ERROR "delocate-path failed for PTOAS compiler archive") + endif() +elseif(UNIX) + find_program(_ptoas_patchelf NAMES patchelf REQUIRED) + + function(_ptoas_origin_relative_rpath _ptoas_output _ptoas_from _ptoas_to) + file(RELATIVE_PATH _ptoas_relative_path "${_ptoas_from}" "${_ptoas_to}") + if(_ptoas_relative_path STREQUAL "") + set(_ptoas_rpath "$ORIGIN") + else() + set(_ptoas_rpath "$ORIGIN/${_ptoas_relative_path}") + endif() + set(${_ptoas_output} "${_ptoas_rpath}" PARENT_SCOPE) + endfunction() + + foreach(_ptoas_native IN LISTS _ptoas_archive_native_files) + if(IS_SYMLINK "${_ptoas_native}") + continue() + endif() + get_filename_component(_ptoas_native_dir "${_ptoas_native}" DIRECTORY) + _ptoas_origin_relative_rpath( + _ptoas_mlir_lib_rpath "${_ptoas_native_dir}" "${_ptoas_mlir_lib_root}") + _ptoas_origin_relative_rpath( + _ptoas_external_lib_rpath "${_ptoas_native_dir}" "${_ptoas_external_lib_root}") + set(_ptoas_native_rpaths + "$ORIGIN" + "${_ptoas_mlir_lib_rpath}" + "${_ptoas_external_lib_rpath}") + list(REMOVE_DUPLICATES _ptoas_native_rpaths) + list(JOIN _ptoas_native_rpaths ":" _ptoas_native_rpath) + execute_process( + COMMAND "${_ptoas_patchelf}" --set-rpath "${_ptoas_native_rpath}" + "${_ptoas_native}" + COMMAND_ERROR_IS_FATAL ANY) + endforeach() + + file(GLOB _ptoas_external_libraries LIST_DIRECTORIES FALSE + "${_ptoas_external_lib_root}/*.so" + "${_ptoas_external_lib_root}/*.so.*") + foreach(_ptoas_library IN LISTS _ptoas_external_libraries) + if(IS_SYMLINK "${_ptoas_library}") + continue() + endif() + execute_process( + COMMAND "${_ptoas_patchelf}" --set-rpath "$ORIGIN" "${_ptoas_library}" + COMMAND_ERROR_IS_FATAL ANY) + endforeach() +endif() diff --git a/docker/collect_ptoas_dist.sh b/docker/collect_ptoas_dist.sh deleted file mode 100755 index d682f842bd..0000000000 --- a/docker/collect_ptoas_dist.sh +++ /dev/null @@ -1,255 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -# Collect ptoas binary and its dependencies into a self-contained distribution. -# -# Usage: ./collect_ptoas_dist.sh -# -# Required environment variables: -# LLVM_BUILD_DIR - Path to LLVM build directory -# PTO_INSTALL_DIR - Path to PTO install directory -# PTO_SOURCE_DIR - Path to PTO source directory -# -# Output structure: -# / -# bin/ptoas - Python console wrapper -# ptoas/ - CLI package and native extension -# lib/*.so* - Required shared library dependencies -# tilelang_dsl/ - TileLang DSL Python package -# -# This compiler-oriented binary artifact intentionally does not bundle the -# PTODSL Python package. PTODSL is provided only by the `ptoas` wheel. - -set -euo pipefail - -if [ $# -lt 1 ]; then - echo "Usage: $0 " >&2 - exit 1 -fi - -PTOAS_DIST_DIR="$1" - -# Validate required environment variables -for var in LLVM_BUILD_DIR PTO_INSTALL_DIR PTO_SOURCE_DIR; do - if [ -z "${!var}" ]; then - echo "Error: $var environment variable is not set" >&2 - exit 1 - fi -done - -export LD_LIBRARY_PATH="${LLVM_BUILD_DIR}/lib:${PTO_INSTALL_DIR}/lib:${LD_LIBRARY_PATH:-}" - -PTOAS_BIN="${PTO_INSTALL_DIR}/bin/ptoas" -PTOAS_PACKAGE_SRC_DIR="${PTO_INSTALL_DIR}/ptoas" -PTOAS_PACKAGE_DIST_DIR="${PTOAS_DIST_DIR}/ptoas" -PTOAS_DEPS_DIR="${PTOAS_DIST_DIR}/lib" -PTOAS_TILELANG_DSL_SRC_DIR="${PTO_INSTALL_DIR}/tilelang_dsl" -PTOAS_TILELANG_DSL_DIST_DIR="${PTOAS_DIST_DIR}/tilelang_dsl" - -if [ ! -f "$PTOAS_BIN" ]; then - echo "Error: installed ptoas wrapper not found at $PTOAS_BIN" >&2 - exit 1 -fi -if [ ! -d "$PTOAS_PACKAGE_SRC_DIR" ]; then - echo "Error: installed ptoas package not found at $PTOAS_PACKAGE_SRC_DIR" >&2 - exit 1 -fi -remove_rpath() { - local path="$1" - if ! has_rpath "$path"; then - return - fi - if ! can_scrub_rpath; then - echo "WARN: skipping RPATH/RUNPATH scrub for ${path}; install patchelf or chrpath to harden local dist artifacts" >&2 - return - fi - if command -v patchelf >/dev/null 2>&1; then - patchelf --remove-rpath "$path" - fi - if has_rpath "$path" && command -v chrpath >/dev/null 2>&1; then - chrpath -d "$path" - fi - if has_rpath "$path"; then - echo "Error: failed to scrub RPATH/RUNPATH from ${path}" >&2 - exit 1 - fi -} - -strip_symbols() { - local path="$1" - strip --strip-unneeded "$path" -} - -has_rpath() { - local path="$1" - if command -v patchelf >/dev/null 2>&1; then - local rpath_value - rpath_value="$(patchelf --print-rpath "$path" 2>/dev/null || true)" - [[ -n "$rpath_value" ]] - return - fi - readelf -d "$path" 2>/dev/null | grep -Eq '(RPATH|RUNPATH)' -} - -can_scrub_rpath() { - command -v patchelf >/dev/null 2>&1 || command -v chrpath >/dev/null 2>&1 -} - -assert_relro() { - local path="$1" - if ! readelf -l "$path" 2>/dev/null | grep -q 'GNU_RELRO'; then - echo "WARN: RELRO segment missing in ${path}" >&2 - return - fi - if ! readelf -d "$path" 2>/dev/null | grep -Eq '(BIND_NOW|FLAGS.*NOW|FLAGS_1.*NOW)'; then - echo "WARN: NOW binding missing in ${path}" >&2 - fi -} - -assert_no_symtab() { - local path="$1" - if readelf -S "$path" 2>/dev/null | grep -Eq '[[:space:]]\\.symtab[[:space:]]'; then - echo "Error: symbol table still present in ${path}" >&2 - exit 1 - fi -} - -assert_no_rpath() { - local path="$1" - if ! can_scrub_rpath; then - return - fi - if has_rpath "$path"; then - echo "Error: runtime search path still present in ${path}" >&2 - exit 1 - fi -} - -harden_elf() { - local path="$1" - remove_rpath "$path" - strip_symbols "$path" - assert_relro "$path" - assert_no_symtab "$path" - assert_no_rpath "$path" -} - -# Create output directories -mkdir -p \ - "${PTOAS_DIST_DIR}/bin" \ - "${PTOAS_DEPS_DIR}" -rm -rf "${PTOAS_PACKAGE_DIST_DIR}" -cp -R "${PTOAS_PACKAGE_SRC_DIR}" "${PTOAS_PACKAGE_DIST_DIR}" -cp "$PTOAS_BIN" "${PTOAS_DIST_DIR}/bin/ptoas" -chmod +x "${PTOAS_DIST_DIR}/bin/ptoas" - -PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}" -maxdepth 1 -type f -name '_core*.so' -print -quit)" -if [ -z "${PTOAS_NATIVE_MODULE}" ]; then - echo "Error: packaged ptoas._core extension not found" >&2 - exit 1 -fi - -# Collect non-system dependencies needed by the Python extension. -echo "Collecting shared library dependencies..." -linux_runtime_dep_paths() { - local path="$1" - ldd "$path" 2>/dev/null | awk ' - /=> \// { print $3 } - /^\// { print $1 } - ' -} - -should_bundle_linux_dep() { - local path="$1" - case "$path" in - /lib/*|/lib64/*|/usr/lib/*|/usr/lib64/*) - return 1 - ;; - esac - return 0 -} - -copy_so() { - local f="$1" - [[ -f "$f" ]] || return 0 - local name - name=$(basename "$f") - [[ -f "${PTOAS_DEPS_DIR}/${name}" ]] && return 0 - cp -L -n "$f" "${PTOAS_DEPS_DIR}/" 2>/dev/null || true - harden_elf "${PTOAS_DEPS_DIR}/${name}" - while read -r res; do - [[ -n "$res" ]] || continue - should_bundle_linux_dep "$res" || continue - copy_so "$res" - done < <(linux_runtime_dep_paths "$f") -} - -while read -r res; do - [[ -n "$res" ]] || continue - should_bundle_linux_dep "$res" || continue - copy_so "$res" -done < <(linux_runtime_dep_paths "${PTOAS_NATIVE_MODULE}") - -while read -r packaged; do - harden_elf "$packaged" -done < <(find "${PTOAS_DEPS_DIR}" -type f | sort) - -if ! command -v patchelf >/dev/null 2>&1; then - echo "Error: patchelf is required to make the ptoas archive relocatable" >&2 - exit 1 -fi -while read -r packaged; do - patchelf --set-rpath '$ORIGIN' "$packaged" -done < <(find "${PTOAS_DEPS_DIR}" -type f | sort) -harden_elf "${PTOAS_NATIVE_MODULE}" -patchelf --set-rpath '$ORIGIN/../lib' "${PTOAS_NATIVE_MODULE}" - -echo "Copying TileLang runtime resources..." -if [ ! -d "${PTOAS_TILELANG_DSL_SRC_DIR}" ]; then - echo "Error: tilelang_dsl package directory not found at ${PTOAS_TILELANG_DSL_SRC_DIR}" >&2 - exit 1 -fi -rm -rf "${PTOAS_TILELANG_DSL_DIST_DIR}" -cp -R "${PTOAS_TILELANG_DSL_SRC_DIR}" "${PTOAS_TILELANG_DSL_DIST_DIR}" - -echo "Smoke testing packaged ptoas dist..." -VERSION_OUTPUT="$(env -u PYTHONPATH -u DYLD_LIBRARY_PATH -u LD_LIBRARY_PATH \ - "${PTOAS_DIST_DIR}/bin/ptoas" --version | tr -d '\r')" -echo "$VERSION_OUTPUT" -EXPECTED_PTOAS_CLI_VERSION="${PTOAS_CLI_VERSION:-${PTOAS_VERSION:-}}" -if [ -n "${EXPECTED_PTOAS_CLI_VERSION}" ]; then - EXPECTED_VERSION_OUTPUT="ptoas ${EXPECTED_PTOAS_CLI_VERSION}" - if [ "${VERSION_OUTPUT}" != "${EXPECTED_VERSION_OUTPUT}" ]; then - echo "Error: expected '${EXPECTED_VERSION_OUTPUT}', got '${VERSION_OUTPUT}'" >&2 - exit 1 - fi -else - echo "$VERSION_OUTPUT" | grep -Eq '^ptoas [0-9]+\.[0-9]+$' -fi - -test -f "${PTOAS_PACKAGE_DIST_DIR}/_cli.py" -test -d "${PTOAS_PACKAGE_DIST_DIR}/_runtime/share/ptoas/TileOps" -test -f "${PTOAS_TILELANG_DSL_DIST_DIR}/__init__.py" -if [ -e "${PTOAS_DIST_DIR}/ptodsl" ]; then - echo "Error: compiler-oriented ptoas dist must not bundle PTODSL" >&2 - exit 1 -fi - -# Show collected files -echo "" -echo "=== ptoas distribution contents ===" -ls -la "${PTOAS_DIST_DIR}/" -ls -la "${PTOAS_DIST_DIR}/bin/" -ls -la "${PTOAS_PACKAGE_DIST_DIR}/" -ls -la "${PTOAS_TILELANG_DSL_DIST_DIR}" -SO_COUNT=$(find "${PTOAS_DEPS_DIR}" -name "*.so*" 2>/dev/null | wc -l) -echo "=== Collected .so dependencies (${SO_COUNT} files) ===" -du -sh "${PTOAS_DEPS_DIR}/" -echo "" -echo "Distribution created at: ${PTOAS_DIST_DIR}" diff --git a/docker/collect_ptoas_dist_mac.sh b/docker/collect_ptoas_dist_mac.sh deleted file mode 100644 index 6685930f5f..0000000000 --- a/docker/collect_ptoas_dist_mac.sh +++ /dev/null @@ -1,378 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -# Collect ptoas binary and macOS dylib dependencies into a self-contained distribution. -# -# Usage: ./collect_ptoas_dist_mac.sh -# -# Required environment variables: -# LLVM_BUILD_DIR - Path to LLVM build directory -# PTO_INSTALL_DIR - Path to PTO install directory -# PTO_SOURCE_DIR - Path to PTO source directory -# -# Output structure: -# / -# bin/ptoas - Python console wrapper -# ptoas/ - CLI package and native extension -# lib/*.dylib - Required shared library dependencies -# tilelang_dsl/ - TileLang DSL Python package -# -# This compiler-oriented binary artifact intentionally does not bundle the -# PTODSL Python package. PTODSL is provided only by the `ptoas` wheel. - -set -euo pipefail - -if [ $# -lt 1 ]; then - echo "Usage: $0 " >&2 - exit 1 -fi - -PTOAS_DIST_DIR="$1" - -# Validate required environment variables -for var in LLVM_BUILD_DIR PTO_INSTALL_DIR PTO_SOURCE_DIR; do - if [ -z "${!var:-}" ]; then - echo "Error: $var environment variable is not set" >&2 - exit 1 - fi -done - -PTOAS_BIN="${PTO_INSTALL_DIR}/bin/ptoas" -PTOAS_PACKAGE_SRC_DIR="${PTO_INSTALL_DIR}/ptoas" -PTOAS_PACKAGE_DIST_DIR="${PTOAS_DIST_DIR}/ptoas" -PTOAS_DEPS_DIR="${PTOAS_DIST_DIR}/lib" -PTOAS_TILELANG_DSL_SRC_DIR="${PTO_INSTALL_DIR}/tilelang_dsl" -PTOAS_TILELANG_DSL_DIST_DIR="${PTOAS_DIST_DIR}/tilelang_dsl" -UNRESOLVED_NON_SYSTEM_COUNT=0 - -if [ ! -f "$PTOAS_BIN" ]; then - echo "Error: installed ptoas wrapper not found at $PTOAS_BIN" >&2 - exit 1 -fi -if [ ! -d "$PTOAS_PACKAGE_SRC_DIR" ]; then - echo "Error: installed ptoas package not found at $PTOAS_PACKAGE_SRC_DIR" >&2 - exit 1 -fi -mkdir -p \ - "${PTOAS_DIST_DIR}/bin" \ - "${PTOAS_DEPS_DIR}" -rm -rf "${PTOAS_PACKAGE_DIST_DIR}" -cp -R "${PTOAS_PACKAGE_SRC_DIR}" "${PTOAS_PACKAGE_DIST_DIR}" -cp -fL "$PTOAS_BIN" "${PTOAS_DIST_DIR}/bin/ptoas" -chmod +x "${PTOAS_DIST_DIR}/bin/ptoas" - -PTOAS_NATIVE_MODULE="$(find "${PTOAS_PACKAGE_DIST_DIR}" -maxdepth 1 -type f -name '_core*.so' -print -quit)" -if [ -z "${PTOAS_NATIVE_MODULE}" ]; then - echo "Error: packaged ptoas._core extension not found" >&2 - exit 1 -fi - -# Resolve @rpath / @loader_path / @executable_path / absolute install names. -resolve_dep_path() { - local owner="$1" - local dep="$2" - local owner_dir - owner_dir="$(dirname "$owner")" - - # macOS GitHub runners use bash 3.2; avoid mapfile for compatibility. - local owner_rpaths=() - local rp_line - while IFS= read -r rp_line; do - [ -n "$rp_line" ] && owner_rpaths+=("$rp_line") - done < <( - otool -l "$owner" | awk ' - $1=="cmd" && $2=="LC_RPATH" {want=1; next} - want && $1=="path" {print $2; want=0} - ' - ) - - local dep_tail="$dep" - if [[ "$dep" == @rpath/* ]]; then - dep_tail="${dep#@rpath/}" - fi - - local candidates=() - if [[ "$dep" = /* ]]; then - candidates+=("$dep") - fi - if [[ "$dep" == @loader_path/* ]]; then - candidates+=("${owner_dir}/${dep#@loader_path/}") - fi - if [[ "$dep" == @executable_path/* ]]; then - candidates+=("${PTOAS_DIST_DIR}/bin/${dep#@executable_path/}") - fi - if [[ "$dep" == @rpath/* ]]; then - for rp in "${owner_rpaths[@]:-}"; do - case "$rp" in - @loader_path/*) rp="${owner_dir}/${rp#@loader_path/}" ;; - @executable_path/*) rp="${PTOAS_DIST_DIR}/bin/${rp#@executable_path/}" ;; - esac - candidates+=("${rp}/${dep_tail}") - done - candidates+=( - "${LLVM_BUILD_DIR}/lib/${dep_tail}" - "${PTO_INSTALL_DIR}/lib/${dep_tail}" - "${owner_dir}/${dep_tail}" - ) - fi - - local c - for c in "${candidates[@]}"; do - if [[ -f "$c" ]]; then - echo "$c" - return 0 - fi - done - return 1 -} - -collect_dylibs() { - local bin="$1" - while read -r dep; do - [ -n "$dep" ] || continue - local resolved - resolved="$(resolve_dep_path "$bin" "$dep" || true)" - if [ -z "$resolved" ]; then - case "$dep" in - /usr/lib/*|/System/Library/*) - # Expected on macOS: system libs are provided by the host. - ;; - *) - echo "WARN: unresolved non-system dep for $bin -> $dep" - UNRESOLVED_NON_SYSTEM_COUNT=$((UNRESOLVED_NON_SYSTEM_COUNT + 1)) - ;; - esac - continue - fi - - local base - base="$(basename "$resolved")" - if [ ! -f "${PTOAS_DEPS_DIR}/${base}" ]; then - cp -fL "$resolved" "${PTOAS_DEPS_DIR}/${base}" - install_name_tool -id "@loader_path/${base}" "${PTOAS_DEPS_DIR}/${base}" || true - collect_dylibs "${PTOAS_DEPS_DIR}/${base}" - fi - install_name_tool -change "$dep" "@loader_path/../lib/${base}" "$bin" || true - done < <(otool -L "$bin" | awk 'NR>1 {print $1}') -} - -rewrite_packaged_install_names() { - python3 - "${PTOAS_DIST_DIR}" "${PTOAS_DEPS_DIR}" <<'PY' -import os -import subprocess -import sys -from pathlib import Path - -dist_dir = Path(sys.argv[1]).resolve() -deps_dir = Path(sys.argv[2]).resolve() -bin_dir = (dist_dir / "bin").resolve() -package_dir = (dist_dir / "ptoas").resolve() -allowed_prefixes = ( - "@loader_path/", - "@rpath/", - "@executable_path/", - "/usr/lib/", - "/System/Library/", -) - - -def is_under(path: Path, root: Path) -> bool: - try: - path.relative_to(root) - return True - except ValueError: - return False - - -def packaged_dep_ref(owner: Path, dep_base: str) -> str: - if is_under(owner, bin_dir): - return f"@loader_path/../lib/{dep_base}" - if is_under(owner, package_dir): - return f"@loader_path/../lib/{dep_base}" - if is_under(owner, deps_dir): - return f"@loader_path/{dep_base}" - return f"@loader_path/{dep_base}" - - -def iter_targets(): - for root in (package_dir, deps_dir): - if not root.exists(): - continue - for base, _, files in os.walk(root): - for name in sorted(files): - if name.endswith(".dylib") or name.endswith(".so"): - yield Path(base, name).resolve() - - -def iter_deps(target: Path): - try: - output = subprocess.check_output( - ["otool", "-L", str(target)], - stderr=subprocess.STDOUT, - text=True, - ) - except subprocess.CalledProcessError as exc: - sys.stderr.write( - f"ERROR: failed to inspect install names for {target}: " - f"{exc.output.strip()}\n" - ) - raise SystemExit(exc.returncode or 1) - - for line in output.splitlines()[1:]: - dep = line.strip().split(" ", 1)[0] - if dep: - yield dep - - -for target in iter_targets(): - for dep in iter_deps(target): - if dep.startswith(allowed_prefixes): - continue - - dep_base = os.path.basename(dep) - if not (deps_dir / dep_base).is_file(): - continue - - replacement = packaged_dep_ref(target, dep_base) - if dep == replacement: - continue - - print(f"rewrite install name: {target} :: {dep} -> {replacement}") - try: - subprocess.check_call( - ["install_name_tool", "-change", dep, replacement, str(target)] - ) - except subprocess.CalledProcessError as exc: - sys.stderr.write( - f"ERROR: failed to rewrite install name for {target}: {dep} -> " - f"{replacement} (exit {exc.returncode})\n" - ) - raise SystemExit(exc.returncode or 1) -PY -} - -echo "Collecting dylib dependencies..." -collect_dylibs "${PTOAS_NATIVE_MODULE}" - -echo "Copying TileLang runtime resources..." -if [[ ! -d "${PTOAS_TILELANG_DSL_SRC_DIR}" ]]; then - echo "Error: tilelang_dsl package directory not found at ${PTOAS_TILELANG_DSL_SRC_DIR}" >&2 - exit 1 -fi -rm -rf "${PTOAS_TILELANG_DSL_DIST_DIR}" -cp -R "${PTOAS_TILELANG_DSL_SRC_DIR}" "${PTOAS_TILELANG_DSL_DIST_DIR}" -if [[ -e "${PTOAS_DIST_DIR}/ptodsl" ]]; then - echo "Error: compiler-oriented ptoas dist must not bundle PTODSL" >&2 - exit 1 -fi - -echo "Rewriting packaged install names..." -rewrite_packaged_install_names - -echo "Validating packaged dependency install names..." -if ! python3 - "${PTOAS_DIST_DIR}" <<'PY' -import os -import subprocess -import sys - -root = sys.argv[1] -allowed_prefixes = ( - "@loader_path/", - "@rpath/", - "@executable_path/", - "/usr/lib/", - "/System/Library/", -) - -bad = [] -for base, _, files in os.walk(root): - for name in files: - if not name.endswith(".dylib") and not name.endswith(".so"): - continue - path = os.path.join(base, name) - try: - output = subprocess.check_output( - ["otool", "-L", path], - stderr=subprocess.STDOUT, - text=True, - ) - except subprocess.CalledProcessError as exc: - print(f"ERROR: failed to inspect {path}: {exc.output.strip()}", - file=sys.stderr) - sys.exit(2) - - for line in output.splitlines()[1:]: - dep = line.strip().split(" ", 1)[0] - if dep.startswith(allowed_prefixes): - continue - bad.append((path, dep)) - -for path, dep in bad: - print(f"ERROR: non-portable dependency in {path} -> {dep}", file=sys.stderr) - -print(f"portable dependency scan checked {root} ({len(bad)} offending deps)") -sys.exit(1 if bad else 0) -PY -then - echo "Error: found non-portable dependency install names" >&2 - exit 1 -fi - -if ! command -v codesign >/dev/null 2>&1; then - echo "Error: codesign is required on macOS to sign packaged artifacts" >&2 - exit 1 -fi - -echo "Ad-hoc signing packaged binaries and dylibs..." -shopt -s nullglob -SIGN_TARGETS=("${PTOAS_NATIVE_MODULE}" "${PTOAS_DEPS_DIR}"/*.so "${PTOAS_DEPS_DIR}"/*.dylib) -for target in "${SIGN_TARGETS[@]}"; do - codesign --force --sign - --timestamp=none "$target" -done - -echo "Verifying code signatures..." -for target in "${SIGN_TARGETS[@]}"; do - codesign --verify --strict --verbose=2 "$target" -done -shopt -u nullglob - -echo "Smoke testing packaged ptoas dist..." -VERSION_OUTPUT="$(env -u PYTHONPATH -u DYLD_LIBRARY_PATH -u LD_LIBRARY_PATH \ - "${PTOAS_DIST_DIR}/bin/ptoas" --version | tr -d '\r')" -echo "$VERSION_OUTPUT" -EXPECTED_PTOAS_CLI_VERSION="${PTOAS_CLI_VERSION:-${PTOAS_VERSION:-}}" -if [ -n "${EXPECTED_PTOAS_CLI_VERSION}" ]; then - EXPECTED_VERSION_OUTPUT="ptoas ${EXPECTED_PTOAS_CLI_VERSION}" - if [ "${VERSION_OUTPUT}" != "${EXPECTED_VERSION_OUTPUT}" ]; then - echo "Error: expected '${EXPECTED_VERSION_OUTPUT}', got '${VERSION_OUTPUT}'" >&2 - exit 1 - fi -else - echo "$VERSION_OUTPUT" | grep -Eq '^ptoas [0-9]+\.[0-9]+$' -fi -test -f "${PTOAS_PACKAGE_DIST_DIR}/_cli.py" -test -d "${PTOAS_PACKAGE_DIST_DIR}/_runtime/share/ptoas/TileOps" -test -f "${PTOAS_TILELANG_DSL_DIST_DIR}/__init__.py" -env -u DYLD_LIBRARY_PATH -u LD_LIBRARY_PATH \ - "${PTOAS_DIST_DIR}/bin/ptoas" \ - "${PTO_SOURCE_DIR}/test/lit/pto/kernel_kind_vector_scf_while_emitc.pto" \ - >/dev/null - -echo "" -echo "=== ptoas distribution contents ===" -ls -la "${PTOAS_DIST_DIR}/" -ls -la "${PTOAS_DIST_DIR}/bin/" -ls -la "${PTOAS_PACKAGE_DIST_DIR}/" -ls -la "${PTOAS_TILELANG_DSL_DIST_DIR}" -DYLIB_COUNT=$(find "${PTOAS_DEPS_DIR}" -name "*.dylib" 2>/dev/null | wc -l) -echo "=== Collected .dylib dependencies (${DYLIB_COUNT} files) ===" -du -sh "${PTOAS_DEPS_DIR}/" -echo "=== Unresolved non-system deps: ${UNRESOLVED_NON_SYSTEM_COUNT} ===" -echo "" -echo "Distribution created at: ${PTOAS_DIST_DIR}" diff --git a/docker/test_wheel_imports.sh b/docker/test_wheel_imports.sh index df2a30487c..aff59bcc2a 100755 --- a/docker/test_wheel_imports.sh +++ b/docker/test_wheel_imports.sh @@ -12,8 +12,8 @@ # Usage: ./test_wheel_imports.sh # # This script tests that the installed wheel can import: -# - mlir.ir -# - mlir.dialects.pto +# - ptoas.mlir.ir +# - ptoas.mlir.dialects.pto # - ptodsl # - from ptodsl import pto, scalar # - ptoas CLI entry @@ -76,11 +76,21 @@ cd /tmp PTOAS_ENTRYPOINT="$(command -v ptoas)" PYTHON_ENTRYPOINT="$(command -v "${PYTHON_BIN}")" -echo "Testing mlir.ir import..." -"$PYTHON_BIN" -c "import mlir.ir; print('mlir.ir imported successfully')" +echo "Testing ptoas.mlir.ir import..." +"$PYTHON_BIN" -c "from ptoas.mlir import ir; print('ptoas.mlir.ir imported successfully')" echo "Testing pto dialect import..." -"$PYTHON_BIN" -c "from mlir.dialects import pto; print('pto dialect imported successfully')" +"$PYTHON_BIN" -c "from ptoas.mlir.dialects import pto; print('pto dialect imported successfully')" + +echo "Testing that PTOAS does not claim the top-level mlir namespace..." +"$PYTHON_BIN" - <<'PY' +try: + import mlir # noqa: F401 +except ImportError: + pass +else: + raise SystemExit("the ptoas wheel unexpectedly provides a top-level mlir package") +PY echo "Testing ptodsl import..." "$PYTHON_BIN" -c "import ptodsl; print(f'ptodsl imported successfully from {ptodsl.__file__}')" diff --git a/docker/validate_wheel_payload.py b/docker/validate_wheel_payload.py index 0ddcda8a3d..a96f677fa0 100644 --- a/docker/validate_wheel_payload.py +++ b/docker/validate_wheel_payload.py @@ -21,6 +21,9 @@ "ptoas/__init__.py", "ptoas/_cli.py", "ptoas/_runtime/share/ptoas/TileOps/__init__.py", + "ptoas/mlir/ir.py", + "ptoas/mlir/dialects/pto.py", + "ptoas/mlir/_mlir_libs/libPTOASPythonCAPI.so", } FORBIDDEN_FILES = { "ptoas/_runtime/bin/ptoas", @@ -31,6 +34,15 @@ f"ptoas/_core{suffix}" for suffix in importlib.machinery.EXTENSION_SUFFIXES } +MLIR_NATIVE_MODULE_PREFIX = "ptoas/mlir/_mlir_libs/" +MLIR_NATIVE_MODULE_PATHS = { + f"{MLIR_NATIVE_MODULE_PREFIX}_mlir{suffix}" + for suffix in importlib.machinery.EXTENSION_SUFFIXES +} +SITE_INITIALIZER_PATHS = { + f"{MLIR_NATIVE_MODULE_PREFIX}_site_initialize_0{suffix}" + for suffix in importlib.machinery.EXTENSION_SUFFIXES +} def _resolve_wheel(candidate: str) -> Path: @@ -93,6 +105,27 @@ def validate_wheel_payload(wheel: Path) -> None: f"found {native_modules}" ) + mlir_native_modules = sorted(MLIR_NATIVE_MODULE_PATHS & names) + if len(mlir_native_modules) != 1: + raise SystemExit( + "wheel must contain exactly one ptoas-owned MLIR native module, " + f"found {mlir_native_modules}" + ) + + site_initializers = sorted(SITE_INITIALIZER_PATHS & names) + if len(site_initializers) != 1: + raise SystemExit( + "wheel must contain exactly one PTOAS MLIR site initializer, " + f"found {site_initializers}" + ) + + top_level_mlir = sorted(name for name in names if name.startswith("mlir/")) + if top_level_mlir: + raise SystemExit( + "wheel must not install a top-level mlir package; " + f"found {top_level_mlir[:10]}" + ) + present_forbidden = sorted(FORBIDDEN_FILES & names) if present_forbidden: raise SystemExit( diff --git a/docs/build_with_installed_llvm.md b/docs/build_with_installed_llvm.md index 807485d898..06e751dfc4 100644 --- a/docs/build_with_installed_llvm.md +++ b/docs/build_with_installed_llvm.md @@ -111,7 +111,7 @@ cmake --install build - install 目录: - `$PTO_INSTALL_DIR/bin/ptoas` - `$PTO_INSTALL_DIR/ptoas/_core.cpython-*.so` - - `$PTO_INSTALL_DIR/mlir/dialects/pto.py` + - `$PTO_INSTALL_DIR/ptoas/mlir/dialects/pto.py` - `$PTO_INSTALL_DIR/share/ptoas/oplib/level3` ## 补充:运行环境 diff --git a/docs/designs/ptoas-mlir-namespace-and-native-isolation.md b/docs/designs/ptoas-mlir-namespace-and-native-isolation.md new file mode 100644 index 0000000000..40eecde609 --- /dev/null +++ b/docs/designs/ptoas-mlir-namespace-and-native-isolation.md @@ -0,0 +1,692 @@ +// Copyright (c) 2026 Huawei Technologies Co., Ltd. +// This program is free software, you can redistribute it and/or modify it under the terms and conditions of +// CANN Open Software License Agreement Version 2.0 (the "License"). +// Please refer to the License for details. You may not use this file except in compliance with the License. +// THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +// See LICENSE in the root of the software repository for the full text of the License. + +# PTOAS MLIR Python Namespace and Native Isolation Design + +## Status + +This document records the agreed migration direction and its constraints. The +design is **proposed and not yet implemented**. Until the migration lands, the +current public imports remain `mlir.ir` and `mlir.dialects.pto`. + +The intended public API is: + +```python +from ptoas.mlir import ir +from ptoas.mlir.ir import Context, Module +from ptoas.mlir.dialects import pto +``` + +The migration must remove the PTOAS-owned top-level `mlir` package rather than +installing a compatibility alias that would recreate the namespace collision. + +## Goals + +1. Place the complete PTOAS-owned MLIR Python runtime under `ptoas.mlir`. +2. Allow PTOAS and another self-contained MLIR distribution, such as IREE, + CIRCT, torch-mlir, or JAX, to coexist in one Python environment. +3. Give all PTOAS MLIR extensions one project-specific nanobind domain. +4. Keep one native MLIR runtime inside PTOAS so that `ptoas.mlir`, the PTO + dialect facade, PTODSL, and `ptoas._core` share object identity. +5. Use MLIR's exported CMake source graph and standard wheel repair tools + instead of copying package trees or implementing a custom loader. +6. Define and test the supported boundary between independently packaged MLIR + runtimes. +7. Keep the repaired wheel as the official Python distribution, while retaining + `ptoas-bin` as a CI and board-validation compatibility artifact. Generate + that artifact from a deterministic CMake install-tree staging directory; + do not make it a second Python package distribution. + +## Non-Goals + +- Do not make `ptoas.mlir.ir.Module` interchangeable with an IREE, CIRCT, + torch-mlir, JAX, or system-MLIR `Module`. +- Do not install or populate a top-level `mlir` compatibility package. +- Do not scan repositories, neighboring build trees, `PYTHONPATH`, or library + directories at Python import time. +- Do not preload LLVM/MLIR libraries with `RTLD_GLOBAL` or a custom bootstrap + loader. +- Do not switch the LLVM SDK from shared to static libraries as part of the + namespace migration. +- Do not modify LLVM/MLIR sources to implement the package layout. +- Do not make the compiler archive a second PyPI-style distribution with its + own metadata, Python dependency resolver, or import bootstrap. +- Do not scan the source tree or arbitrary build directories while assembling + the archive. Its contents must come from an explicit install prefix. +- Do not pretend that `auditwheel repair` or `delocate` is a generic tarball + relocation tool. They remain the standard repair tools for wheels; any + archive-native relocation must be a small, explicit packaging step. + +## Industry and Upstream References + +The design separates mechanisms with direct upstream/industry precedent from +the PTOAS-specific compatibility artifact required by the current board-test +workflow. + +### Directly Referenced Mechanisms + +- LLVM's standalone example uses `MLIR_PYTHON_PACKAGE_PREFIX`, + `add_mlir_python_common_capi_library`, and `add_mlir_python_modules` to embed + MLIR bindings in a downstream namespace. +- torch-mlir explicitly vendors MLIR in the `torch_mlir` namespace and defines + `MLIR_PYTHON_PACKAGE_PREFIX=torch_mlir.`. +- IREE defines `MLIR_PYTHON_PACKAGE_PREFIX=iree.compiler.`, installs its MLIR + tree below `iree/compiler`, and makes the Python bindings consume one + project-owned shared compiler implementation. Its compiler tools are found + relative to the installed Python package rather than by scanning build or + source trees. +- CIRCT defines `MLIR_PYTHON_PACKAGE_PREFIX=circt.`, installs below `circt`, and + uses a project-owned `CIRCTBindingsPythonCAPI` library. +- JAX packages its MLIR bindings below `jaxlib.mlir` with a private + `_mlir_libs` directory. +- Linux native wheels conventionally use `auditwheel repair`; auditwheel copies + external libraries, gives them content-derived names, rewrites `DT_NEEDED`, + and installs package-relative RPATH entries. +- macOS native wheels conventionally use `delocate`, which copies dependent + dylibs and rewrites install names and RPATH entries. +- CMake install components and CPack archive an explicit install graph into a + deterministic prefix. They are the standard boundary for a native install + tree, although they do not replace wheel-specific dependency repair. + +These references directly support the `ptoas.mlir` namespace, project-owned +common CAPI, project-specific nanobind domain, and repaired-wheel architecture. + +### Distribution and Archive Boundary + +There is no universal MLIR or Python packaging standard for publishing a +compiler-only tarball alongside a Python wheel. Comparable projects either +publish wheels only or maintain a project-specific compiler/binary package. +The standard Python distribution remains the repaired wheel; `auditwheel` and +`delocate` are intentionally wheel-oriented tools. + +PTOAS must currently retain a `ptoas-bin` archive because the PR board-test +monitor downloads the Linux artifact before running compiler cases. This is a +compatibility artifact, not a second public Python distribution. The archive +will be assembled from a dedicated CMake install-tree staging prefix, using +the same `ptoas` package layout and runtime contract as the wheel. CPack/TGZ or +an equivalent archive of that install prefix is the appropriate packaging +boundary; a script must not reconstruct a package by scanning the repository. + +The archive and wheel have different native packaging constraints. Wheel +repair can be delegated to `auditwheel`/`delocate`. A relocatable install-tree +archive may still need a narrowly scoped platform step to ensure that bundled +non-system libraries use relative RPATHs or install names. That step must not +also copy Python sources, invent a second package layout, or run a second +general-purpose dependency-discovery pipeline hidden inside the launcher. + +Relevant upstream sources: + +- `llvm-project/mlir/examples/standalone/python/CMakeLists.txt` +- `llvm-project/mlir/cmake/modules/AddMLIRPython.cmake` +- `llvm/torch-mlir/python/CMakeLists.txt` +- `iree-org/iree/compiler/bindings/python/CMakeLists.txt` +- `iree-org/iree/compiler/bindings/python/iree/compiler/tools/binaries.py` +- `llvm/circt/lib/Bindings/Python/CMakeLists.txt` +- `cmake/Help/module/CPack.rst` +- `pypa/auditwheel` +- `matthew-brett/delocate` + +## Target Package Layout + +```text +ptoas/ +├── __init__.py +├── _cli.py +├── _core..so +├── _runtime/ +└── mlir/ + ├── __init__.py + ├── ir.py + ├── passmanager.py + ├── dialects/ + │ ├── arith.py + │ ├── func.py + │ ├── llvm.py + │ ├── math.py + │ ├── memref.py + │ ├── pto.py + │ └── scf.py + └── _mlir_libs/ + ├── _mlir..so + ├── _site_initialize_0..so + └── libPTOASPythonCAPI.so +``` + +The corresponding native ownership graph is: + +```text +ptoas.mlir.ir + │ + ▼ +ptoas/mlir/_mlir_libs/_mlir.so + │ + ├──────────────────────┐ + ▼ ▼ +libPTOASPythonCAPI.so ◄── ptoas/_core.so + │ + ▼ +repaired, content-named LLVM/MLIR shared libraries +``` + +All PTOAS binding modules must resolve MLIR objects through the same +`PTOASPythonCAPI` and the same underlying LLVM/MLIR shared libraries. + +## Python Namespace Configuration + +Moving files under `ptoas/mlir` is not sufficient. Native MLIR bindings also +use the package prefix to locate Python classes and capsules. The binding +targets must therefore be compiled with: + +```cmake +add_compile_definitions( + "MLIR_PYTHON_PACKAGE_PREFIX=ptoas.mlir." +) +``` + +The definition must apply to the MLIR-generated extension targets and to +`PTOASPythonCore`. Since `_core` is built in a separate CMake directory, it may +need an explicit target-scoped compile definition in addition to the binding +directory definition. + +The staged and installed package roots should become: + +```cmake +set(PTOAS_MLIR_PYTHON_PACKAGE_DIR + "${CMAKE_BINARY_DIR}/python/ptoas/mlir") + +add_mlir_python_common_capi_library(PTOASPythonCAPI + INSTALL_DESTINATION "ptoas/mlir/_mlir_libs" + OUTPUT_DIRECTORY "${PTOAS_MLIR_PYTHON_PACKAGE_DIR}/_mlir_libs" + ... +) + +add_mlir_python_modules(PTOAS_Python + ROOT_PREFIX "${PTOAS_MLIR_PYTHON_PACKAGE_DIR}" + INSTALL_PREFIX "ptoas/mlir" + ... +) +``` + +The generated package remains owned by the `PTOAS_Python` CMake install +component. It should not be copied from an LLVM build tree or added as a second +`tool.scikit-build.wheel.packages` source tree. + +## Nanobind Domain Isolation + +MLIR's nanobind domain determines which extension modules share native Python +type registrations. All modules inside one PTOAS MLIR runtime must use one +domain, while other MLIR distributions must use different domains. + +Use: + +```cmake +set(MLIR_BINDINGS_PYTHON_NB_DOMAIN "ptoas_mlir") +``` + +### Current LLVM Fork Constraint + +The LLVM fork currently used by PTOAS has an older `AddMLIRPython.cmake` API. +Its `add_mlir_python_modules` function accepts `ROOT_PREFIX` and +`INSTALL_PREFIX`, but does not accept the newer per-call +`MLIR_BINDINGS_PYTHON_NB_DOMAIN` argument. It reads the CMake variable when it +creates nanobind extension targets. + +Therefore the current implementation must set the variable before calling +`add_mlir_python_modules`; passing an extra argument to that function is not a +valid implementation for the current SDK. When the LLVM fork adopts the newer +upstream API, this can be converted to a per-package argument without changing +the public layout. + +`ptoas._core` currently uses pybind11, so the nanobind domain does not directly +configure `_core`. Its interoperability with MLIR objects instead depends on +the package prefix, MLIR's adaptor/C API boundary, and the shared common CAPI. + +## Common CAPI and Runtime Identity + +`PTOASPythonCAPI` is already a project-owned common CAPI name and should remain +the single native binding runtime for PTOAS. The migration must preserve these +relationships: + +- `_mlir` links `PTOASPythonCAPI`. +- `_site_initialize_0` links the same common CAPI. +- `ptoas._core` links the same common CAPI. +- `ptoas._core` initializes the matching Python runtime with: + + ```cpp + py::module_::import("ptoas.mlir.ir"); + ``` + +- `ptoas.mlir.dialects.pto` imports `ptoas._core` for project-owned PTO types + and enums. +- No PTOAS component imports or links a second system `MLIRPythonCAPI`. + +`ptoas.__init__` should stay minimal and must not eagerly import `_core` or +`ptoas.mlir`, avoiding an import cycle between `_core`, `ir`, and the PTO +dialect facade. + +## Dynamic Library Isolation + +### Linux Repaired Wheels + +PTOAS currently builds its LLVM SDK with `BUILD_SHARED_LIBS=ON`. This produces +many `libLLVM*.so` and `libMLIR*.so` dependencies. The release wheel must +continue through `auditwheel repair`. + +Auditwheel provides the distribution isolation for those external libraries: + +1. Copy each non-system dependency into the wheel-owned `ptoas.libs` tree. +2. Rename it with a content-derived hash. +3. Rewrite its ELF SONAME. +4. Rewrite consumers' `DT_NEEDED` entries. +5. Install package-relative RPATH entries. + +PTOAS's repaired wheel already demonstrates this pattern with names such as: + +```text +ptoas.libs/libMLIRArithDialect-00278e1e.so.21.1 +ptoas.libs/libLLVMTransformUtils-2cda0d9b.so.21.1 +``` + +The project should not manually rename or enumerate all LLVM/MLIR libraries. +The internal common CAPI name is already project-specific; auditwheel owns the +external dependency names. + +### macOS Repaired Wheels + +The macOS wheel must continue through `delocate`. Delocate owns copying dylibs +and rewriting install names and RPATH entries. PTOAS should not add a parallel +`install_name_tool` implementation. + +### `_core` Package-Local RPATH + +After nesting MLIR under `ptoas`, `_core` and its common CAPI are laid out as: + +```text +ptoas/_core.so +ptoas/mlir/_mlir_libs/libPTOASPythonCAPI.so +``` + +The package-local install RPATH must therefore be: + +```text +Linux: $ORIGIN;$ORIGIN/mlir/_mlir_libs +macOS: @loader_path;@loader_path/mlir/_mlir_libs +``` + +The old `$ORIGIN/../mlir/_mlir_libs` path belongs to the current sibling +packages and must not survive the migration. + +For the common CAPI under `ptoas/mlir/_mlir_libs`, the +`RELATIVE_INSTALL_ROOT` value must be recomputed from the new location rather +than copied from the old configuration. From this location back to the Python +install prefix is normally three levels (`../../..`). The final value must be +verified from installed ELF/Mach-O metadata because auditwheel and delocate +will subsequently replace distribution-wheel dependency paths. + +### Editable and Build-Tree Installs + +Editable and direct build-tree installations do not pass through wheel repair. +They may use RPATH entries that refer to the selected developer LLVM build. +This is sufficient for a convenient PTOAS development environment, but it does +not guarantee same-process coexistence with an unrelated developer MLIR build. + +The supported isolation contract applies most strongly to repaired release +wheels. Editable multi-MLIR coexistence is best effort unless both projects +were intentionally built against one compatible runtime. + +### Compiler Compatibility Archive + +The `ptoas-bin` archive is compiler-oriented and includes PTODSL as an internal +compiler runtime dependency. PTOAS defaults to the PTODSL TileLib backend, so +excluding `ptodsl/` would make an extracted archive unable to compile `.pto` +input containing unexpanded TileOps with the normal CLI defaults. The archive +must therefore contain both PTODSL and the installed nested MLIR package: + +```text +ptodsl/ +ptoas/_core.so +ptoas/mlir/ +ptoas/mlir/_mlir_libs/_mlir.so +ptoas/mlir/_mlir_libs/libPTOASPythonCAPI.so +``` + +This does not make the archive a general PTODSL development distribution. +`ptodsl/` and `ptoas.mlir` are present so the compiler's default TileLib path +works without changing CLI semantics. The repaired wheel remains the supported +Python installation for authoring and importing PTODSL applications. + +The repaired wheel remains the canonical Python distribution. Wheel and +archive packaging share the same CMake target graph but use different install +contracts. The archive is produced from an explicit compiler-runtime install +component so that its contents are owned by CMake rather than reconstructed +from source paths: + +```text +configured CMake build + │ + ├── wheel install components + │ └── raw wheel + │ └── auditwheel / delocate + │ └── repaired Python wheel + │ + └── PTOAS_Python + compiler-runtime install components + └── archive staging prefix + └── native relocation, if required + └── tar/CPack board artifact +``` + +The staging prefix must contain only the compiler archive contract: + +```text +bin/ptoas +ptodsl/ +ptoas/ +ptoas/mlir/ +ptoas/_runtime/share/ptoas/TileOps/ +tilelang_dsl/ +lib/ # only if native dependencies are bundled +``` + +The archive exposes PTODSL only as part of the compiler runtime contract. It +does not include wheel metadata or claim to satisfy normal `pip` dependency +resolution. Board validation invokes the packaged compiler rather than using +the archive as an installable Python distribution. + +Archive assembly is limited to install-tree and relocation operations: + +- install `PTOAS_Python` and then `PTOAS_CompilerArchive` with an explicit, + shared staging prefix; +- preserve the package-relative `ptoas/`, `ptoas/mlir/`, and `ptodsl/` layout; +- place any bundled non-system native dependencies below the archive prefix + and use `$ORIGIN`/`@loader_path`-relative linkage; +- create the tarball from that prefix with CPack/TGZ or an equivalent simple + archive command; +- smoke test the extracted archive with a clean environment. + +The archive's `lib/` directory, when needed, is an install-tree convention and +is distinct from auditwheel's wheel-local `*.libs` sidecar. We must not copy a +wheel sidecar into an unrelated layout without also preserving the native +linkage that refers to it. + +Native dependency discovery for the archive should use CMake's install-time +`file(GET_RUNTIME_DEPENDENCIES)`, which is available within PTOAS's existing +CMake 3.20 minimum, rather than handwritten recursive `ldd` or `otool` +parsers. Package-owned files such as `PTOASPythonCAPI`, `_mlir`, and site +initializers remain under `ptoas/mlir/_mlir_libs` and must be excluded from the +external dependency copy into `lib/`. + +The archive relocation contract is: + +```text +Linux ptoas/_core.so: + $ORIGIN;$ORIGIN/mlir/_mlir_libs;$ORIGIN/../lib +Linux ptoas/mlir/_mlir_libs/*: + $ORIGIN;$ORIGIN/../../../lib +Linux lib/*.so*: + $ORIGIN + +macOS ptoas/_core.so: + @loader_path;@loader_path/mlir/_mlir_libs;@loader_path/../lib +macOS ptoas/mlir/_mlir_libs/*: + @loader_path;@loader_path/../../../lib +macOS lib/*.dylib: + @loader_path +``` + +Linux uses `patchelf` only to apply this staging-tree RPATH contract after +CMake resolves and copies dependencies. macOS uses `delocate-path` for the +equivalent directory relocation instead of maintaining a project-owned Mach-O +dependency parser. Neither platform searches for libraries at Python import +time. + +The current compatibility archive is built from the CPython 3.11 workflow and +contains CPython-ABI-specific extension modules. It therefore requires CPython +3.11 at runtime. The existing `ptoas-bin-` artifact names remain +unchanged for the external board-test monitor; the build and extracted-archive +tests must validate the interpreter version explicitly. Moving to abi3 or +publishing per-Python archive names is outside this migration. + +The single-runtime invariant is inherited from the shared CMake target graph: + +- exactly one package-owned `PTOASPythonCAPI` is retained; +- `_core`, `_mlir`, and site initializers link the same project-owned common + CAPI before the wheel and archive take their platform-specific packaging + paths; +- LLVM/MLIR dependencies in the archive use relative install-tree RPATHs or + install names and contain no build-tree absolute paths; +- any platform relocation helper is limited to the archive staging prefix and + is separately validated from the wheel repair path. + +The standalone archive is intended to launch a fresh compiler process. Unlike +the repaired wheel, it does not promise arbitrary same-process import +coexistence with another MLIR distribution. Its required invariant is narrower +but strict: one archive invocation loads one internally consistent PTOAS native +runtime built from the same CMake targets as the wheel and relocated only for +the archive's own install-tree layout. + +## Why Not Switch Directly to Static LLVM + +Changing only `BUILD_SHARED_LIBS=OFF` can make `_mlir.so` and `_core.so` +statically embed separate copies of MLIR. That would duplicate registries, +TypeIDs, command-line options, and native global state inside one process and +could break PTOAS's own cross-module object identity. + +A future single-DSO design must instead follow an IREE-style ownership model: + +```text +libPTOASCompiler.so +├── LLVM/MLIR implementation +├── PTO dialect and passes +├── compiler driver +└── exported C API + +_mlir.so ──► libPTOASCompiler.so +_core.so ──► libPTOASCompiler.so +``` + +That is a separate architectural change requiring a deliberate exported API +boundary and symbol-visibility policy. It is not a prerequisite for the +namespace migration because repaired wheels already isolate external shared +libraries with package-local, content-derived names. + +## Public API Migration + +Production imports, tests, samples, and documentation must move together: + +```python +# Old +from mlir import ir +from mlir.ir import Module +from mlir.dialects import pto + +# New +from ptoas.mlir import ir +from ptoas.mlir.ir import Module +from ptoas.mlir.dialects import pto +``` + +The affected surfaces include: + +- PTO dialect Python facade and generated source graph; +- PTODSL implementation and public MLIR object documentation; +- TileLang DSL pybind backend; +- PTOAS Python tests; +- sample programs; +- README installation and Python API examples; +- wheel payload validation and import smoke tests; +- native `mlir.ir` import strings. + +Because README and wheel tests currently promise top-level `mlir`, removing it +is a public API break and requires an explicit release note. A default alias is +not an acceptable compatibility mechanism because it defeats package +isolation. + +## Supported Coexistence Boundary + +| Scenario | Contract | +|---|---| +| Install PTOAS and another namespaced MLIR wheel in one environment | Supported target | +| Import both repaired wheels in one interpreter | Must be validated | +| Create independent contexts and modules in each runtime | Supported target | +| Pass a PTOAS `Module`, `Type`, or `Value` into another runtime | Unsupported | +| Exchange textual MLIR, bytecode, or files | Supported integration boundary | +| Mix editable builds backed by unrelated LLVM trees | Best effort, not guaranteed | + +No public function should imply that independently packaged MLIR native objects +are interchangeable. Cross-project integration must serialize the IR or use a +subprocess unless the projects deliberately share one compatible runtime. + +## Validation Plan + +### Package Contract + +- The wheel contains `ptoas/mlir/ir.py` and + `ptoas/mlir/dialects/pto.py`. +- The wheel does not contain a top-level `mlir/` tree. +- `ptoas._core` and exactly one PTOAS `_mlir` core extension are present. +- Importing PTOAS does not create `sys.modules["mlir"]`. + +### Functional Imports + +```python +from ptoas.mlir import ir +from ptoas.mlir.dialects import pto +import ptodsl +from ptodsl import pto as dsl_pto, scalar +``` + +The test must create a context and module, register the PTO dialect, compile a +minimal PTODSL kernel, and invoke the installed `ptoas` console script. + +### Runtime Identity + +- PTO types created through `ptoas._core` work with + `ptoas.mlir.ir.Context`. +- PTODSL returns `ptoas.mlir.ir.Module` objects. +- PTOAS binding modules all resolve the same `PTOASPythonCAPI`. +- Import order between `ptoas._core`, `ptoas.mlir.ir`, and + `ptoas.mlir.dialects.pto` is deterministic and cycle-free. + +### Linux Wheel Dependencies + +- `auditwheel show` reports an accepted manylinux policy. +- Repaired LLVM/MLIR dependencies have content-derived names. +- `readelf -d` contains no absolute LLVM build path. +- No non-system `libLLVM*` or `libMLIR*` dependency remains outside the wheel. + +### macOS Wheel Dependencies + +- `delocate-listdeps` reports no external developer LLVM path. +- `otool -L` contains only system or wheel-owned dylibs. +- No absolute LLVM build or install path remains. + +### Compiler Archive Dependencies + +- The archive contains `ptoas/mlir` and `ptodsl` so the default PTODSL TileLib + backend works without extra CLI options. +- The archive is produced by an explicit CMake compiler-runtime install + component, not by scanning the source tree or an arbitrary install tree. +- Package-relative paths are preserved and the archive contains no source, + build, or install-prefix absolute paths. +- Exactly one package-owned `PTOASPythonCAPI` exists. +- `_core`, `_mlir`, site initializers, and the common CAPI resolve through the + archive's own relative native paths. +- Any native dependency relocation is performed only on the staging prefix and + is not implemented by Python import-time path scanning. +- Runtime dependency discovery uses CMake + `file(GET_RUNTIME_DEPENDENCIES)` rather than recursive shell parsing. +- Package-owned MLIR extensions and `PTOASPythonCAPI` remain under + `ptoas/mlir/_mlir_libs`; only external native dependencies are copied to + the archive `lib/` directory. +- The archive reports a clear error unless it is launched with CPython 3.11. +- The extracted archive runs `ptoas --version` and compiles a representative + `.pto` input containing an unexpanded TileOp through the default PTODSL + backend with `PYTHONPATH`, `LD_LIBRARY_PATH`, and `DYLD_LIBRARY_PATH` unset. +- PR workflows continue to upload the artifact name consumed by the external + board-test monitor until that consumer is explicitly migrated. + +### Coexistence + +A packaging or release integration job should install one representative +namespaced MLIR distribution, preferably IREE, and test both import orders: + +```python +import ptoas.mlir.ir +import iree.compiler.ir +``` + +and: + +```python +import iree.compiler.ir +import ptoas.mlir.ir +``` + +Each runtime should create and verify its own context/module. The test must not +pass objects between runtimes. This heavier check belongs in wheel packaging or +release validation rather than every source-only PR job. + +### Repository Regression + +- Python binding and PTODSL tests; +- TileLang DSL backend tests; +- PTOAS lit tests; +- VMI lit and simulator regression where Python samples are involved; +- Linux and macOS wheel build, repair, clean-install, and CLI smoke tests. + +## Implementation Sequence + +1. Add `ptoas.mlir` package prefix and staging/install destinations. +2. Set the current LLVM fork's global nanobind domain to `ptoas_mlir`. +3. Keep and relocate the single `PTOASPythonCAPI`. +4. Update `_core` package import and package-local RPATH. +5. Add a dedicated compiler-runtime install component and explicit archive + staging prefix; remove source-tree and arbitrary-prefix discovery from the + collectors. +6. Include PTODSL in the compiler-runtime component so the default TileLib + backend remains functional. +7. Replace recursive native dependency parsing with install-time CMake + `file(GET_RUNTIME_DEPENDENCIES)`, then apply the documented Linux/macOS + staging-tree relocation contract. +8. Update the PTO dialect facade and all production Python imports. +9. Update samples, tests, README, workflow artifacts, and wheel/archive + contract validation without renaming the board-test artifact consumed by + the external monitor. +10. Remove top-level `mlir` from the wheel without a default alias. +11. Run build-tree, editable, lit, simulator, repaired-wheel, and extracted + standalone-archive regressions. +12. Validate dynamic dependencies and representative same-process wheel + coexistence. +13. Consider a monolithic `libPTOASCompiler` only as a later, separately + justified optimization for wheel size, startup time, or stronger symbol + isolation. + +## Decision Summary + +- Public namespace: `ptoas.mlir`. +- Public PTO dialect: `ptoas.mlir.dialects.pto`. +- Native compiler module: `ptoas._core`. +- MLIR Python package prefix: `ptoas.mlir.`. +- Nanobind domain: `ptoas_mlir`. +- Common native runtime: one `PTOASPythonCAPI`. +- Linux distribution isolation: `auditwheel repair`. +- macOS distribution isolation: `delocate`. +- Official Python distribution: repaired wheel with the `ptoas` console script. +- Board-validation artifact: compiler-only tarball from the CMake + compiler-runtime install component, preserving the nested `ptoas.mlir` + package layout, including PTODSL for the default TileLib backend, and using + relative native paths. +- Compiler archive Python ABI: CPython 3.11 until a separate abi3 or + per-Python archive design is adopted. +- Archive dependency discovery: CMake `file(GET_RUNTIME_DEPENDENCIES)`; + platform tools perform only staging-tree relocation. +- Board-test compatibility: retain the current `ptoas-bin` artifact contract + until the external monitor is migrated deliberately. +- Cross-runtime native objects: unsupported. +- Top-level `mlir` compatibility alias: not installed. +- Static or monolithic LLVM redesign: deferred to a separate proposal. diff --git a/docs/designs/ptoas-python-launcher-layout.md b/docs/designs/ptoas-python-launcher-layout.md index f85b9014e4..9d197029cd 100644 --- a/docs/designs/ptoas-python-launcher-layout.md +++ b/docs/designs/ptoas-python-launcher-layout.md @@ -14,6 +14,10 @@ This document records the internal launcher contract for the Python-backed `ptoas` command. The user-facing README should describe how to install and run PTOAS without exposing these implementation details. +The PTOAS-owned MLIR Python runtime lives under `ptoas.mlir`; its namespace and +native-library isolation requirements are recorded separately in +[`ptoas-mlir-namespace-and-native-isolation.md`](ptoas-mlir-namespace-and-native-isolation.md). + ## Entry Model The wheel launcher uses the standard Python console-script and native-extension @@ -28,7 +32,7 @@ both -> import ptoas._core -> ptoas._core.main(argv) `ptoas._core` is the single PTOAS-owned native extension. It provides the compiler entry point and the native PTO dialect bindings used by the public -`mlir.dialects.pto` facade. CMake and Python own the platform and ABI-specific +`ptoas.mlir.dialects.pto` facade. CMake and Python own the platform and ABI-specific filename. Launcher and packaging code refer to the import name and never construct `.so`, `.dylib`, or `.pyd` paths. @@ -109,15 +113,28 @@ bin/ptoas ptoas/_cli.py ptoas/_core..so ptoas/_runtime/share/ptoas/TileOps +ptoas/mlir/ +ptodsl/ lib/ tilelang_dsl/ ``` -The archive requires a Python interpreter compatible with the packaged -extension ABI. `bin/ptoas` adds the archive root to `sys.path`, then uses the -same `ptoas._cli -> ptoas._core` path as the install tree. Linux archives set -the extension runtime path to `$ORIGIN/../lib`; macOS archives rewrite the -extension's install names relative to its package directory. +The archive is assembled by installing `PTOAS_Python` and then +`PTOAS_CompilerArchive` into one staging prefix. The second component owns the +wrapper and compiler-time Python resources and performs relocation against the +already staged native payload. Packaging code does not scan source trees or +assemble Python packages from unrelated build directories. + +The current archive is built against CPython 3.11 and requires a CPython 3.11 +interpreter. `bin/ptoas` adds the archive root to `sys.path`, then uses the same +`ptoas._cli -> ptoas._core` path as the install tree. The packaged `ptodsl/` +tree supports the compiler's default PTODSL TileLib backend; it does not turn +the archive into a normal pip-installable PTODSL distribution. + +Linux archives use package-relative and archive-relative `$ORIGIN` RPATHs; +macOS archives use the equivalent `@loader_path` install names. Package-owned +MLIR extensions remain under `ptoas/mlir/_mlir_libs`, while only external +native dependencies are collected under the archive `lib/` directory. ## PTODSL and TileLib Runtime diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index ba950c649b..0c56fef22e 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -8,6 +8,13 @@ include(AddMLIRPython) +# Keep the complete PTOAS-owned MLIR Python runtime below the project namespace +# so it can coexist with independently packaged MLIR distributions. This is a +# package-prefix contract as well as a Python import path: MLIR's generated +# capsules and nanobind registration code use the same value. +add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=ptoas.mlir.") +set(MLIR_BINDINGS_PYTHON_NB_DOMAIN "ptoas_mlir") + # Do not carry toolchain-injected paths, such as a Conda compiler RPATH, into # installed Python modules. Distribution builds keep only MLIR's relative # package RPATHs; editable builds add their external link paths below. @@ -33,11 +40,11 @@ if(PTOAS_ENABLE_WERROR) endif() endif() -# Build the `mlir` Python package from MLIR's exported source declarations and +# Build the `ptoas.mlir` Python package from MLIR's exported source declarations and # add PTOAS's dialect to the same package. This is the composition mechanism # supported by AddMLIRPython and avoids copying or overlaying another build's # package tree. -set(PTOAS_MLIR_PYTHON_PACKAGE_DIR "${CMAKE_BINARY_DIR}/python/mlir") +set(PTOAS_MLIR_PYTHON_PACKAGE_DIR "${CMAKE_BINARY_DIR}/python/ptoas/mlir") declare_mlir_python_sources(PTOASPythonSources) @@ -104,9 +111,9 @@ set(PTOAS_MLIR_PYTHON_SOURCE_SETS # CAPI and contains both the PTO dialect implementation and compiler driver. add_mlir_python_common_capi_library(PTOASPythonCAPI INSTALL_COMPONENT PTOAS_Python - INSTALL_DESTINATION "mlir/_mlir_libs" + INSTALL_DESTINATION "ptoas/mlir/_mlir_libs" OUTPUT_DIRECTORY "${PTOAS_MLIR_PYTHON_PACKAGE_DIR}/_mlir_libs" - RELATIVE_INSTALL_ROOT "../../../.." + RELATIVE_INSTALL_ROOT "../../../" DECLARED_HEADERS MLIRPythonCAPI.HeaderSources DECLARED_SOURCES @@ -125,7 +132,7 @@ set_property(TARGET PTOASPythonCAPI PROPERTY LINKER_LANGUAGE CXX) add_mlir_python_modules(PTOAS_Python ROOT_PREFIX "${PTOAS_MLIR_PYTHON_PACKAGE_DIR}" - INSTALL_PREFIX mlir + INSTALL_PREFIX ptoas/mlir DECLARED_SOURCES ${PTOAS_MLIR_PYTHON_SOURCE_SETS} PTOASPythonSources diff --git a/lib/Bindings/Python/PTOModule.cpp b/lib/Bindings/Python/PTOModule.cpp index 8d6d061b29..b9abb1cc30 100644 --- a/lib/Bindings/Python/PTOModule.cpp +++ b/lib/Bindings/Python/PTOModule.cpp @@ -9,7 +9,7 @@ //===- DialectPTO.cpp -----------------------------------------------------===// // // Python bindings for the PTO dialect types in the project-owned ptoas._core -// extension. The public Python facade remains mlir.dialects.pto. +// extension. The public Python facade remains ptoas.mlir.dialects.pto. // //===----------------------------------------------------------------------===// diff --git a/ptodsl/CMakeLists.txt b/ptodsl/CMakeLists.txt index 4be1601179..c8d1e9ba25 100644 --- a/ptodsl/CMakeLists.txt +++ b/ptodsl/CMakeLists.txt @@ -29,7 +29,7 @@ add_dependencies(PTODSLPackage PTODSLPackageStage) install( DIRECTORY "${PTODSL_PACKAGE_SRC_DIR}" DESTINATION "." - COMPONENT PTOAS_Runtime + COMPONENT PTOAS_CompilerArchive PATTERN "__pycache__" EXCLUDE PATTERN "*.pyc" EXCLUDE ) @@ -37,7 +37,7 @@ install( install( DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/ptoas" DESTINATION "." - COMPONENT PTOAS_Runtime + COMPONENT PTOAS_CompilerArchive PATTERN "__pycache__" EXCLUDE PATTERN "*.pyc" EXCLUDE ) diff --git a/ptodsl/examples/softmax_lowlevel.py b/ptodsl/examples/softmax_lowlevel.py index b962551fab..4d673ca93d 100644 --- a/ptodsl/examples/softmax_lowlevel.py +++ b/ptodsl/examples/softmax_lowlevel.py @@ -14,7 +14,7 @@ using raw MLIR Python binding calls, with no additional abstraction layer. """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Attribute, Context, F32Type, @@ -28,7 +28,7 @@ Type, UnitAttr, ) -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.dialects import arith, func, pto, scf def build(): diff --git a/ptodsl/examples/tadd_lowlevel.py b/ptodsl/examples/tadd_lowlevel.py index 8dd98c77dc..fbae54c7b8 100644 --- a/ptodsl/examples/tadd_lowlevel.py +++ b/ptodsl/examples/tadd_lowlevel.py @@ -41,7 +41,7 @@ } """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Attribute, Context, F32Type, @@ -54,7 +54,7 @@ StringAttr, Type, ) -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.dialects import arith, func, pto, scf def build(): diff --git a/ptodsl/ptodsl/_allreduce.py b/ptodsl/ptodsl/_allreduce.py index 4d14b540c0..24080cb72d 100644 --- a/ptodsl/ptodsl/_allreduce.py +++ b/ptodsl/ptodsl/_allreduce.py @@ -28,8 +28,8 @@ from ._surface_values import unwrap_surface_value from ._types import _resolve, float16 as _f16_dtype, float32 as _f32_dtype, si32 as _si32_dtype, ui32 as _ui32_dtype -from mlir.dialects import pto as _pto -from mlir.ir import F16Type, F32Type, IntegerType +from ptoas.mlir.dialects import pto as _pto +from ptoas.mlir.ir import F16Type, F32Type, IntegerType # ── helpers ──────────────────────────────────────────────────────────────────── diff --git a/ptodsl/ptodsl/_builtin_vector.py b/ptodsl/ptodsl/_builtin_vector.py index 544b66470b..d1cfa5bac2 100644 --- a/ptodsl/ptodsl/_builtin_vector.py +++ b/ptodsl/ptodsl/_builtin_vector.py @@ -11,9 +11,9 @@ from ._surface_values import VecValue, unwrap_surface_value from ._types import _resolve, _validate_vec_size, vec_type -from mlir.dialects import arith -from mlir.dialects import llvm -from mlir.ir import IntegerType, VectorType +from ptoas.mlir.dialects import arith +from ptoas.mlir.dialects import llvm +from ptoas.mlir.ir import IntegerType, VectorType def Vec(dtype, size: int, *, init=None): diff --git a/ptodsl/ptodsl/_context.py b/ptodsl/ptodsl/_context.py index efdc47af59..a3f2fd7be4 100644 --- a/ptodsl/ptodsl/_context.py +++ b/ptodsl/ptodsl/_context.py @@ -8,14 +8,14 @@ """MLIR context construction for an installed or explicitly configured PTODSL.""" -from mlir.dialects import pto as _pto_dialect +from ptoas.mlir.dialects import pto as _pto_dialect try: - from mlir.dialects import llvm as _llvm_dialect + from ptoas.mlir.dialects import llvm as _llvm_dialect except Exception: # pragma: no cover - depends on the installed MLIR package. _llvm_dialect = None -from mlir.ir import Context +from ptoas.mlir.ir import Context def make_context() -> Context: diff --git a/ptodsl/ptodsl/_control_flow.py b/ptodsl/ptodsl/_control_flow.py index 77b2c9bdb1..f8dd0883cd 100644 --- a/ptodsl/ptodsl/_control_flow.py +++ b/ptodsl/ptodsl/_control_flow.py @@ -27,8 +27,8 @@ from ._tracing.active import current_session from ._surface_values import unwrap_surface_value, wrap_like_surface_value, wrap_surface_value -from mlir.dialects import pto as _pto, scf -from mlir.ir import InsertionPoint +from ptoas.mlir.dialects import pto as _pto, scf +from ptoas.mlir.ir import InsertionPoint # ── vecscope ────────────────────────────────────────────────────────────────── diff --git a/ptodsl/ptodsl/_jit.py b/ptodsl/ptodsl/_jit.py index 26fb8311e5..f90f7809ac 100644 --- a/ptodsl/ptodsl/_jit.py +++ b/ptodsl/ptodsl/_jit.py @@ -28,7 +28,7 @@ current_runtime, ) -from mlir.ir import InsertionPoint +from ptoas.mlir.ir import InsertionPoint _MODULE_ATTRS = ("pto.target_arch",) diff --git a/ptodsl/ptodsl/_ops.py b/ptodsl/ptodsl/_ops.py index 20a0b5af7f..e1a399db3c 100644 --- a/ptodsl/ptodsl/_ops.py +++ b/ptodsl/ptodsl/_ops.py @@ -72,8 +72,8 @@ vreg_type, ) -from mlir.dialects import arith, pto as _pto -from mlir.ir import ( +from ptoas.mlir.dialects import arith, pto as _pto +from ptoas.mlir.ir import ( Attribute, BF16Type, F16Type, @@ -234,7 +234,7 @@ def const(value: int, *, dtype=None): """ Emit an ``arith.constant``. - ``dtype`` is a ``_DType`` descriptor or a concrete ``mlir.ir.Type``. + ``dtype`` is a ``_DType`` descriptor or a concrete ``ptoas.mlir.ir.Type``. Defaults to ``index`` when omitted. """ from ._types import index as _idx_dtype diff --git a/ptodsl/ptodsl/_runtime/codegen.py b/ptodsl/ptodsl/_runtime/codegen.py index 768a11155b..f0fa1a4e83 100644 --- a/ptodsl/ptodsl/_runtime/codegen.py +++ b/ptodsl/ptodsl/_runtime/codegen.py @@ -10,7 +10,7 @@ from __future__ import annotations from .._context import make_context -from mlir.ir import BF16Type, F16Type, F32Type, IndexType, IntegerType +from ptoas.mlir.ir import BF16Type, F16Type, F32Type, IndexType, IntegerType from .._kernel_signature import DeviceParameterSpec, RuntimeScalarParameterSpec from .._types import _PtrDescriptor, _resolve diff --git a/ptodsl/ptodsl/_runtime/launch.py b/ptodsl/ptodsl/_runtime/launch.py index 5780fe1a93..d6e5c26402 100644 --- a/ptodsl/ptodsl/_runtime/launch.py +++ b/ptodsl/ptodsl/_runtime/launch.py @@ -16,7 +16,7 @@ from .._types import _resolve from .native_build import build_native_library -from mlir.ir import BF16Type, Context, F16Type, F32Type, IndexType, IntegerType +from ptoas.mlir.ir import BF16Type, Context, F16Type, F32Type, IndexType, IntegerType if TYPE_CHECKING: from .._kernel_compilation import CompiledKernelHandle diff --git a/ptodsl/ptodsl/_runtime_scalar_ops.py b/ptodsl/ptodsl/_runtime_scalar_ops.py index fa0acf0a7b..0fef5843a1 100644 --- a/ptodsl/ptodsl/_runtime_scalar_ops.py +++ b/ptodsl/ptodsl/_runtime_scalar_ops.py @@ -19,8 +19,8 @@ _strip_integer_signedness, ) -from mlir.dialects import arith, math -from mlir.ir import IndexType, IntegerType +from ptoas.mlir.dialects import arith, math +from ptoas.mlir.ir import IndexType, IntegerType _FLOAT_BINARY_OPS = { diff --git a/ptodsl/ptodsl/_scalar_adaptation.py b/ptodsl/ptodsl/_scalar_adaptation.py index faa1fdb8b4..4457c693db 100644 --- a/ptodsl/ptodsl/_scalar_adaptation.py +++ b/ptodsl/ptodsl/_scalar_adaptation.py @@ -17,8 +17,8 @@ _strip_integer_signedness, ) -from mlir.dialects import arith -from mlir.ir import BF16Type, F16Type, F32Type, FloatAttr, IndexType, IntegerType, VectorType +from ptoas.mlir.dialects import arith +from ptoas.mlir.ir import BF16Type, F16Type, F32Type, FloatAttr, IndexType, IntegerType, VectorType def classify_runtime_scalar_type(type_obj): diff --git a/ptodsl/ptodsl/_source_loader.py b/ptodsl/ptodsl/_source_loader.py index f4bac6f730..1603d0fc0f 100644 --- a/ptodsl/ptodsl/_source_loader.py +++ b/ptodsl/ptodsl/_source_loader.py @@ -20,7 +20,7 @@ jit_source_file_error, ) -from mlir.ir import Location, Module +from ptoas.mlir.ir import Location, Module @dataclass(frozen=True) diff --git a/ptodsl/ptodsl/_surface_types.py b/ptodsl/ptodsl/_surface_types.py index 9ec4d95142..0074c10e62 100644 --- a/ptodsl/ptodsl/_surface_types.py +++ b/ptodsl/ptodsl/_surface_types.py @@ -9,7 +9,7 @@ from enum import Enum -from mlir.dialects import pto as _pto +from ptoas.mlir.dialects import pto as _pto class _ConstExprHelper: diff --git a/ptodsl/ptodsl/_surface_values.py b/ptodsl/ptodsl/_surface_values.py index d541e776de..d8fa1fb0e3 100644 --- a/ptodsl/ptodsl/_surface_values.py +++ b/ptodsl/ptodsl/_surface_values.py @@ -22,10 +22,10 @@ from ._surface_types import PartitionTensorView, TensorView, Tile from ._types import _normalize_address_space, _resolve, ptr -from mlir.dialects import arith -from mlir.dialects import memref -from mlir.dialects import pto as _pto -from mlir.ir import IndexType, IntegerAttr, IntegerType, MemRefType, ShapedType, StridedLayoutAttr, Type, VectorType +from ptoas.mlir.dialects import arith +from ptoas.mlir.dialects import memref +from ptoas.mlir.dialects import pto as _pto +from ptoas.mlir.ir import IndexType, IntegerAttr, IntegerType, MemRefType, ShapedType, StridedLayoutAttr, Type, VectorType def _validate_surface_value_access(value): diff --git a/ptodsl/ptodsl/_tile_template_tracing.py b/ptodsl/ptodsl/_tile_template_tracing.py index 571239717d..ea10cf2582 100644 --- a/ptodsl/ptodsl/_tile_template_tracing.py +++ b/ptodsl/ptodsl/_tile_template_tracing.py @@ -58,8 +58,8 @@ vreg_type as _vreg_type, ) -from mlir.dialects import arith, pto as _pto, scf -from mlir.ir import InsertionPoint, IntegerType, Type +from ptoas.mlir.dialects import arith, pto as _pto, scf +from ptoas.mlir.ir import InsertionPoint, IntegerType, Type @dataclass(frozen=True) diff --git a/ptodsl/ptodsl/_tracing/artifacts.py b/ptodsl/ptodsl/_tracing/artifacts.py index 5dc51e3feb..975efe05b4 100644 --- a/ptodsl/ptodsl/_tracing/artifacts.py +++ b/ptodsl/ptodsl/_tracing/artifacts.py @@ -27,7 +27,7 @@ def __init__(self, py_name: str, *, module=None, module_factory=None, mlir_text: self._build_metadata = {} def build(self): - """Return the cached ``mlir.ir.Module``.""" + """Return the cached ``ptoas.mlir.ir.Module``.""" if self._cached_module is None: if self._module_factory is None: raise RuntimeError(f"{self._py_name} has no module factory") @@ -43,7 +43,7 @@ def build(self): return self._cached_module def mlir_module(self): - """Return the cached ``mlir.ir.Module``.""" + """Return the cached ``ptoas.mlir.ir.Module``.""" return self.build() def mlir_text(self) -> str: diff --git a/ptodsl/ptodsl/_tracing/control_flow.py b/ptodsl/ptodsl/_tracing/control_flow.py index 60a2c4ec84..f878e9198e 100644 --- a/ptodsl/ptodsl/_tracing/control_flow.py +++ b/ptodsl/ptodsl/_tracing/control_flow.py @@ -14,9 +14,9 @@ from .._runtime_index_ops import coerce_runtime_index from .._surface_values import unwrap_surface_value -from mlir.dialects import arith -from mlir.dialects import scf -from mlir.ir import InsertionPoint, IntegerType +from ptoas.mlir.dialects import arith +from ptoas.mlir.dialects import scf +from ptoas.mlir.ir import InsertionPoint, IntegerType @dataclass diff --git a/ptodsl/ptodsl/_tracing/module_builder.py b/ptodsl/ptodsl/_tracing/module_builder.py index e5fb99859a..9894ceb62e 100644 --- a/ptodsl/ptodsl/_tracing/module_builder.py +++ b/ptodsl/ptodsl/_tracing/module_builder.py @@ -12,8 +12,8 @@ from dataclasses import dataclass from enum import Enum -from mlir.dialects import func -from mlir.ir import Attribute, InsertionPoint, Module, Operation, StringAttr, UnitAttr +from ptoas.mlir.dialects import func +from ptoas.mlir.ir import Attribute, InsertionPoint, Module, Operation, StringAttr, UnitAttr class ModuleStyle(str, Enum): diff --git a/ptodsl/ptodsl/_tracing/runtime.py b/ptodsl/ptodsl/_tracing/runtime.py index 4a22c6b462..d9172d95e2 100644 --- a/ptodsl/ptodsl/_tracing/runtime.py +++ b/ptodsl/ptodsl/_tracing/runtime.py @@ -16,8 +16,8 @@ from .._context import make_context from .._types import _resolve -from mlir.dialects import func -from mlir.ir import InsertionPoint, Location +from ptoas.mlir.dialects import func +from ptoas.mlir.ir import InsertionPoint, Location class TracingRuntime: diff --git a/ptodsl/ptodsl/_tracing/session.py b/ptodsl/ptodsl/_tracing/session.py index 617fc05578..e5aa3a2ca0 100644 --- a/ptodsl/ptodsl/_tracing/session.py +++ b/ptodsl/ptodsl/_tracing/session.py @@ -36,9 +36,9 @@ from .._types import _strip_integer_signedness from .module_builder import create_container_child_module -from mlir.dialects import arith, func -from mlir.dialects import pto as _pto -from mlir.ir import ( +from ptoas.mlir.dialects import arith, func +from ptoas.mlir.dialects import pto as _pto +from ptoas.mlir.ir import ( Attribute, FlatSymbolRefAttr, IndexType, diff --git a/ptodsl/ptodsl/_types.py b/ptodsl/ptodsl/_types.py index a89e887bf7..10a885178a 100644 --- a/ptodsl/ptodsl/_types.py +++ b/ptodsl/ptodsl/_types.py @@ -9,7 +9,7 @@ Lazy MLIR type descriptors and eager type constructors. Type descriptors (``_DType`` subclasses) can be created *before* any MLIR -Context exists – they only resolve to concrete ``mlir.ir.Type`` objects when +Context exists – they only resolve to concrete ``ptoas.mlir.ir.Type`` objects when ``_resolve()`` is called inside an active context. This lets users write:: def softmax(arg0: pto.ptr(pto.float32, "GM"), ...): @@ -19,10 +19,10 @@ def softmax(arg0: pto.ptr(pto.float32, "GM"), ...): the actual type is materialised later by the ``@pto.jit`` decorator. """ -from mlir.dialects import pto as _pto -from mlir.dialects import arith -from mlir.dialects.builtin import UnrealizedConversionCastOp -from mlir.ir import ( +from ptoas.mlir.dialects import pto as _pto +from ptoas.mlir.dialects import arith +from ptoas.mlir.dialects.builtin import UnrealizedConversionCastOp +from ptoas.mlir.ir import ( BF16Type, F16Type, F32Type, @@ -216,10 +216,10 @@ def _validate_vec_size(size: int, *, context: str) -> int: def _resolve(dtype) -> Type: - """Coerce a ``_DType`` descriptor or a concrete ``mlir.ir.Type`` to a Type.""" + """Coerce a ``_DType`` descriptor or a concrete ``ptoas.mlir.ir.Type`` to a Type.""" if isinstance(dtype, _DType): return dtype.resolve() - return dtype # already an mlir.ir.Type + return dtype # already a ptoas.mlir.ir.Type def _classify_scalar_type(type_obj): diff --git a/ptodsl/ptodsl/_vmi_namespace.py b/ptodsl/ptodsl/_vmi_namespace.py index b22287b23c..aef05c8d82 100644 --- a/ptodsl/ptodsl/_vmi_namespace.py +++ b/ptodsl/ptodsl/_vmi_namespace.py @@ -11,8 +11,8 @@ from collections.abc import Sequence -from mlir.dialects import pto as _pto -from mlir.ir import BF16Type, F16Type, F32Type, Float8E4M3FNType, Float8E5M2Type, IntegerType, MemRefType +from ptoas.mlir.dialects import pto as _pto +from ptoas.mlir.ir import BF16Type, F16Type, F32Type, Float8E4M3FNType, Float8E5M2Type, IntegerType, MemRefType from ._scalar_coercion import coerce_scalar_to_type from ._surface_values import _coerce_index_value, _try_get_constant_index, unwrap_surface_value, wrap_surface_value diff --git a/ptodsl/ptodsl/pto.py b/ptodsl/ptodsl/pto.py index 4795c91221..58f82d3305 100644 --- a/ptodsl/ptodsl/pto.py +++ b/ptodsl/ptodsl/pto.py @@ -17,7 +17,7 @@ from ptodsl import pto All user-facing symbols live here. Low-level MLIR bindings are accessed -internally as ``_pto`` (``from mlir.dialects import pto as _pto``). +internally as ``_pto`` (``from ptoas.mlir.dialects import pto as _pto``). """ from ._diagnostics import unsupported_public_surface_error diff --git a/ptodsl/ptodsl/scalar.py b/ptodsl/ptodsl/scalar.py index 3e18343b8e..a646fe728f 100644 --- a/ptodsl/ptodsl/scalar.py +++ b/ptodsl/ptodsl/scalar.py @@ -9,7 +9,7 @@ Scalar arithmetic helpers – exposed as top-level ``scalar.*`` from the ``ptodsl`` package (for example ``from ptodsl import scalar``). -Arithmetic helpers operate on raw ``mlir.ir.Value`` objects and emit the +Arithmetic helpers operate on raw ``ptoas.mlir.ir.Value`` objects and emit the corresponding arith dialect operations at the active insertion point. Scalar memory helpers (`load` / `store`) also accept PTODSL surface-level address views such as `tile[row, col]` and `tile.as_ptr() + offset`. @@ -33,11 +33,11 @@ ) from ._types import _resolve -from mlir.dialects import arith -from mlir.dialects import llvm -from mlir.dialects import math -from mlir.ir import IndexType, IntegerType, MemRefType, Operation, VectorType -from mlir.dialects import pto as _pto +from ptoas.mlir.dialects import arith +from ptoas.mlir.dialects import llvm +from ptoas.mlir.dialects import math +from ptoas.mlir.ir import IndexType, IntegerType, MemRefType, Operation, VectorType +from ptoas.mlir.dialects import pto as _pto def muli(lhs, rhs): diff --git a/ptodsl/ptodsl/tilelib/_render_runtime.py b/ptodsl/ptodsl/tilelib/_render_runtime.py index b87dafe8ae..3aa6fed25b 100644 --- a/ptodsl/ptodsl/tilelib/_render_runtime.py +++ b/ptodsl/ptodsl/tilelib/_render_runtime.py @@ -36,8 +36,8 @@ from .._surface_values import wrap_surface_value from .._types import _DType, _resolve -from mlir.dialects import func -from mlir.ir import Attribute, InsertionPoint, Location, Module, StringAttr, UnitAttr +from ptoas.mlir.dialects import func +from ptoas.mlir.ir import Attribute, InsertionPoint, Location, Module, StringAttr, UnitAttr # ── tile handle handed to the template body ──────────────────────────────────────── diff --git a/ptodsl/ptodsl/tilelib/metadata.py b/ptodsl/ptodsl/tilelib/metadata.py index 9ebaef8877..94ed62903b 100644 --- a/ptodsl/ptodsl/tilelib/metadata.py +++ b/ptodsl/ptodsl/tilelib/metadata.py @@ -40,7 +40,7 @@ _resolve, ) -from mlir.ir import Type +from ptoas.mlir.ir import Type @dataclass(frozen=True) diff --git a/ptodsl/ptodsl/tilelib/templates/a5/tcvt.py b/ptodsl/ptodsl/tilelib/templates/a5/tcvt.py index 17f65cc02d..e54a360d79 100644 --- a/ptodsl/ptodsl/tilelib/templates/a5/tcvt.py +++ b/ptodsl/ptodsl/tilelib/templates/a5/tcvt.py @@ -10,7 +10,7 @@ from ptodsl import pto from ptodsl._surface_values import unwrap_surface_value, wrap_surface_value import ptodsl.tilelib as tilelib -from mlir.dialects import pto as _pto +from ptoas.mlir.dialects import pto as _pto def _rowwise(src_shape, src_valid_shape, dst_shape, dst_valid_shape, src_config, dst_config, **_): diff --git a/ptodsl/tests/support/docs_fragment_fixtures.py b/ptodsl/tests/support/docs_fragment_fixtures.py index 9aed2ff2ea..85ad735759 100644 --- a/ptodsl/tests/support/docs_fragment_fixtures.py +++ b/ptodsl/tests/support/docs_fragment_fixtures.py @@ -2111,8 +2111,8 @@ def pipe_communication_c2v_local_declaration_probe(): ), "pipe_communication.c2v_local_import": _fixture( f""" - from mlir.dialects import func - from mlir.ir import InsertionPoint + from ptoas.mlir.dialects import func + from ptoas.mlir.ir import InsertionPoint from ptodsl._tracing import current_session @@ -2135,8 +2135,8 @@ def pipe_communication_c2v_local_import_probe(): ), "pipe_communication.c2v_local_producer": _fixture( f""" - from mlir.dialects import func - from mlir.ir import InsertionPoint + from ptoas.mlir.dialects import func + from ptoas.mlir.ir import InsertionPoint from ptodsl._tracing import current_session diff --git a/ptodsl/tests/test_ast_rewrite_example_ir.py b/ptodsl/tests/test_ast_rewrite_example_ir.py index bc6d6242cc..b8e3de51b9 100644 --- a/ptodsl/tests/test_ast_rewrite_example_ir.py +++ b/ptodsl/tests/test_ast_rewrite_example_ir.py @@ -15,7 +15,7 @@ REPO_ROOT = Path(__file__).resolve().parents[2] from ptodsl import pto from ptodsl._context import make_context -from mlir.ir import Module +from ptoas.mlir.ir import Module def expect(condition: bool, message: str) -> None: diff --git a/ptodsl/tests/test_docs_as_test.py b/ptodsl/tests/test_docs_as_test.py index 7e03b8debe..5f3f70dcd6 100644 --- a/ptodsl/tests/test_docs_as_test.py +++ b/ptodsl/tests/test_docs_as_test.py @@ -26,7 +26,7 @@ from ptodsl._context import make_context from ptodsl._runtime.launch import LaunchHandle, _marshal_launch_args from ptodsl._runtime.toolchain import resolve_ptoas_binary -from mlir.ir import Module +from ptoas.mlir.ir import Module from support.docs_fragment_fixtures import FRAGMENT_FIXTURES, render_fragment_fixture FENCE_RE = re.compile(r"^```(?P[A-Za-z0-9_+-]*)\s*$") diff --git a/ptodsl/tests/test_flash_attention_demo_compile.py b/ptodsl/tests/test_flash_attention_demo_compile.py index 00bb6eadf1..d022103a8d 100644 --- a/ptodsl/tests/test_flash_attention_demo_compile.py +++ b/ptodsl/tests/test_flash_attention_demo_compile.py @@ -12,7 +12,7 @@ REPO_ROOT = Path(__file__).resolve().parents[2] from ptodsl._context import make_context -from mlir.ir import Module +from ptoas.mlir.ir import Module def expect(condition: bool, message: str) -> None: diff --git a/ptodsl/tests/test_jit_compile.py b/ptodsl/tests/test_jit_compile.py index 32987848a0..1d76730a68 100644 --- a/ptodsl/tests/test_jit_compile.py +++ b/ptodsl/tests/test_jit_compile.py @@ -30,7 +30,7 @@ from ptodsl._runtime.codegen import generate_launch_cpp from ptodsl._runtime.launch import _marshal_launch_args from ptodsl._tracing import current_session -from mlir.ir import InsertionPoint, Location, Module +from ptoas.mlir.ir import InsertionPoint, Location, Module def expect(condition: bool, message: str) -> None: diff --git a/ptodsl/tests/test_ptoas_frontend_verify.py b/ptodsl/tests/test_ptoas_frontend_verify.py index b3e80a4687..c8403171df 100644 --- a/ptodsl/tests/test_ptoas_frontend_verify.py +++ b/ptodsl/tests/test_ptoas_frontend_verify.py @@ -19,7 +19,7 @@ from ptodsl import scalar from ptodsl._context import make_context from ptodsl._runtime.toolchain import resolve_ptoas_binary -from mlir.ir import Module +from ptoas.mlir.ir import Module def expect(condition: bool, message: str) -> None: diff --git a/ptodsl/tests/test_ptoas_tree_wrapper.py b/ptodsl/tests/test_ptoas_tree_wrapper.py index 5bea72f01c..e289172a11 100644 --- a/ptodsl/tests/test_ptoas_tree_wrapper.py +++ b/ptodsl/tests/test_ptoas_tree_wrapper.py @@ -123,6 +123,31 @@ def test_wrapper_requires_cli_module(self): with self.assertRaisesRegex(SystemExit, "ptoas/_cli.py"): module._require_python_root(python_root, context="test") + def test_archive_wrapper_rejects_a_different_python_minor(self): + with tempfile.TemporaryDirectory() as temp_dir: + python_root = Path(temp_dir) / "archive" + wrapper = python_root / "bin" / "ptoas" + self._make_package(python_root) + wrapper.parent.mkdir(parents=True) + wrapper.write_text("", encoding="utf-8") + (python_root / ".ptoas-python-version").write_text( + "0.0\n", encoding="utf-8" + ) + + module = self._load_wrapper( + wrapper, + "test_ptoas_archive_python_version", + python_root_mode="wrapper-relative", + python_root=Path(".."), + ) + saved_argv = list(sys.argv) + try: + sys.argv = [str(wrapper)] + with self.assertRaisesRegex(SystemExit, "requires CPython 0.0"): + module.main() + finally: + sys.argv = saved_argv + if __name__ == "__main__": unittest.main() diff --git a/ptodsl/tests/test_tileop.py b/ptodsl/tests/test_tileop.py index 6b30cb88fc..1496439638 100644 --- a/ptodsl/tests/test_tileop.py +++ b/ptodsl/tests/test_tileop.py @@ -11,7 +11,7 @@ from ptodsl import pto from ptodsl._context import make_context -from mlir.ir import Module +from ptoas.mlir.ir import Module @pto.simt(max_threads=64, ast_rewrite=False) diff --git a/ptodsl/tests/test_vector_cube_ops.py b/ptodsl/tests/test_vector_cube_ops.py index 9bca1f9167..eecc8aae10 100644 --- a/ptodsl/tests/test_vector_cube_ops.py +++ b/ptodsl/tests/test_vector_cube_ops.py @@ -15,7 +15,7 @@ import ptodsl._pipe_namespace as _pipe_namespace from ptodsl._context import make_context from ptodsl import pto -from mlir.ir import F32Type +from ptoas.mlir.ir import F32Type def _identity(value): return value diff --git a/python/pto/dialects/pto.py b/python/pto/dialects/pto.py index f2038d060a..83709ba68a 100644 --- a/python/pto/dialects/pto.py +++ b/python/pto/dialects/pto.py @@ -9,7 +9,7 @@ import functools from typing import Optional -from mlir import ir as _ods_ir +from ptoas.mlir import ir as _ods_ir from . import _pto_ops_gen as _pto_ops_gen from ._ods_common import ( @@ -1138,9 +1138,9 @@ def _project_result(group, index, ty): def _load_standard_dialects(): try: - from mlir.dialects import arith as _mlir_arith # noqa: F401 - from mlir.dialects import func as _mlir_func # noqa: F401 - from mlir.dialects import scf as _mlir_scf # noqa: F401 + from ptoas.mlir.dialects import arith as _mlir_arith # noqa: F401 + from ptoas.mlir.dialects import func as _mlir_func # noqa: F401 + from ptoas.mlir.dialects import scf as _mlir_scf # noqa: F401 except ImportError as exc: raise RuntimeError("mlir standard dialect python bindings are required for vkernel parsing") from exc diff --git a/scripts/sim_dsl.sh b/scripts/sim_dsl.sh index 63dbf0b8ad..33d2cbec5e 100755 --- a/scripts/sim_dsl.sh +++ b/scripts/sim_dsl.sh @@ -129,7 +129,7 @@ print_msprof_log() { python_can_import_ptodsl() { local python_bin="$1" "${python_bin}" - <<'PY' >/dev/null 2>&1 -import mlir.ir # noqa: F401 +import ptoas.mlir.ir # noqa: F401 from ptodsl import pto # noqa: F401 PY } @@ -232,7 +232,7 @@ if [[ -n "${RESOLVED_PTOAS_BIN:-}" ]]; then export PTOAS_BIN="${RESOLVED_PTOAS_BIN}" fi if ! python_can_import_ptodsl "${RESOLVED_PYTHON_BIN}"; then - die "active Python environment cannot import ptodsl/mlir.ir; install the PTOAS wheel or use a preconfigured environment" + die "active Python environment cannot import ptodsl/ptoas.mlir.ir; install the PTOAS wheel or use a preconfigured environment" fi if ! command -v ptoas >/dev/null 2>&1; then die "ptoas is not available on PATH; install the PTOAS wheel or export PTOAS_BIN" diff --git a/test/dsl/abs.py b/test/dsl/abs.py index 1917a57250..807eca7d0c 100644 --- a/test/dsl/abs.py +++ b/test/dsl/abs.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -import mlir.dialects.pto as pto +import ptoas.mlir.dialects.pto as pto @pto.vkernel(target="a5", name="abs_kernel_2d") diff --git a/test/dsl/strict_vecscope.py b/test/dsl/strict_vecscope.py index 7badac2ae4..03bf99a801 100644 --- a/test/dsl/strict_vecscope.py +++ b/test/dsl/strict_vecscope.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -import mlir.dialects.pto as pto +import ptoas.mlir.dialects.pto as pto @pto.vkernel(target="a5", name="abs_strict_vecscope_kernel_2d") diff --git a/test/dsl/template_abs.py b/test/dsl/template_abs.py index dc674adee0..512ad54f08 100644 --- a/test/dsl/template_abs.py +++ b/test/dsl/template_abs.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -import mlir.dialects.pto as pto +import ptoas.mlir.dialects.pto as pto @pto.vkernel(target="a5", name="template_abs_kernel") diff --git a/test/python/compact_tile_buf_asm.py b/test/python/compact_tile_buf_asm.py index 8c07e945ce..cdf74879e7 100644 --- a/test/python/compact_tile_buf_asm.py +++ b/test/python/compact_tile_buf_asm.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 -from mlir.ir import Context, F32Type, MLIRError, Module -from mlir.dialects import pto +from ptoas.mlir.ir import Context, F32Type, MLIRError, Module +from ptoas.mlir.dialects import pto def expect_equal(actual: str, expected: str, label: str) -> None: diff --git a/test/python/low_precision_types.py b/test/python/low_precision_types.py index dde603f191..aac0e2d976 100644 --- a/test/python/low_precision_types.py +++ b/test/python/low_precision_types.py @@ -7,8 +7,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context -from mlir.dialects import pto +from ptoas.mlir.ir import Context +from ptoas.mlir.dialects import pto def assert_contains(text: str, needle: str) -> None: diff --git a/test/python/memory_consistency_bindings.py b/test/python/memory_consistency_bindings.py index e52d26bae5..a227332d3b 100644 --- a/test/python/memory_consistency_bindings.py +++ b/test/python/memory_consistency_bindings.py @@ -7,8 +7,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, InsertionPoint, Location, Module -from mlir.dialects import pto +from ptoas.mlir.ir import Context, InsertionPoint, Location, Module +from ptoas.mlir.dialects import pto def assert_contains(text: str, needle: str) -> None: diff --git a/test/samples/Abs/abs.py b/test/samples/Abs/abs.py index 5d01854e83..7e3a862254 100644 --- a/test/samples/Abs/abs.py +++ b/test/samples/Abs/abs.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/AddPtr/addptr.py b/test/samples/AddPtr/addptr.py index 603162e98e..2a5cddd3bc 100644 --- a/test/samples/AddPtr/addptr.py +++ b/test/samples/AddPtr/addptr.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/AddPtr/addptr_chain.py b/test/samples/AddPtr/addptr_chain.py index cc9a3da26d..7d460cbe8e 100644 --- a/test/samples/AddPtr/addptr_chain.py +++ b/test/samples/AddPtr/addptr_chain.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/AddPtr/addptr_dynamic.py b/test/samples/AddPtr/addptr_dynamic.py index ce25d91178..a6c81e5e55 100644 --- a/test/samples/AddPtr/addptr_dynamic.py +++ b/test/samples/AddPtr/addptr_dynamic.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/AddPtr/addptr_f16.py b/test/samples/AddPtr/addptr_f16.py index 16ef95e3bc..0db5337049 100644 --- a/test/samples/AddPtr/addptr_f16.py +++ b/test/samples/AddPtr/addptr_f16.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, IndexType def build(): diff --git a/test/samples/Addc/addc.py b/test/samples/Addc/addc.py index 460e194c07..89209b44d8 100644 --- a/test/samples/Addc/addc.py +++ b/test/samples/Addc/addc.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Adds/adds.py b/test/samples/Adds/adds.py index 1a2c02b070..0cb7e53081 100644 --- a/test/samples/Adds/adds.py +++ b/test/samples/Adds/adds.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Addsc/addsc.py b/test/samples/Addsc/addsc.py index 1d96ed7dff..a15e6cc3eb 100644 --- a/test/samples/Addsc/addsc.py +++ b/test/samples/Addsc/addsc.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/AllocTile/alloc_tile_addr.py b/test/samples/AllocTile/alloc_tile_addr.py index 6072a6098c..452b408e63 100644 --- a/test/samples/AllocTile/alloc_tile_addr.py +++ b/test/samples/AllocTile/alloc_tile_addr.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IntegerType, IntegerAttr, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IntegerType, IntegerAttr, IndexType def build(): diff --git a/test/samples/And/and.py b/test/samples/And/and.py index 0bb8cb7a03..b138cc5041 100644 --- a/test/samples/And/and.py +++ b/test/samples/And/and.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType def build(): diff --git a/test/samples/Ands/ands.py b/test/samples/Ands/ands.py index a34372db67..1bdb4ef328 100644 --- a/test/samples/Ands/ands.py +++ b/test/samples/Ands/ands.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType, IntegerAttr +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType, IntegerAttr def build(): diff --git a/test/samples/AsyncComm/async_comm.py b/test/samples/AsyncComm/async_comm.py index f8e4177f63..3efa0b39ce 100644 --- a/test/samples/AsyncComm/async_comm.py +++ b/test/samples/AsyncComm/async_comm.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, F32Type, IntegerType, IntegerAttr, IndexType, Operation, UnitAttr -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, F32Type, IntegerType, IntegerAttr, IndexType, Operation, UnitAttr +from ptoas.mlir.dialects import arith, func, pto, scf def _build_async_session(scratch, workspace, i32, ctx, sync_id=0): diff --git a/test/samples/AsyncComm/tget_async_kernel_impl_like.py b/test/samples/AsyncComm/tget_async_kernel_impl_like.py index 691f1cb160..ca93990421 100644 --- a/test/samples/AsyncComm/tget_async_kernel_impl_like.py +++ b/test/samples/AsyncComm/tget_async_kernel_impl_like.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, F32Type, @@ -19,7 +19,7 @@ Operation, Type, ) -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.dialects import arith, func, pto, scf def _build_async_session(scratch, workspace, i32, ctx, sync_id=0): diff --git a/test/samples/AsyncComm/tput_async_kernel_impl_like.py b/test/samples/AsyncComm/tput_async_kernel_impl_like.py index 63551fb208..73a3af2e67 100644 --- a/test/samples/AsyncComm/tput_async_kernel_impl_like.py +++ b/test/samples/AsyncComm/tput_async_kernel_impl_like.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, F32Type, @@ -19,7 +19,7 @@ Operation, Type, ) -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.dialects import arith, func, pto, scf def _build_async_session(scratch, workspace, i32, ctx, sync_id=0): diff --git a/test/samples/Bf16/bf16_tile.py b/test/samples/Bf16/bf16_tile.py index 54b08ece08..f08e6fd68a 100644 --- a/test/samples/Bf16/bf16_tile.py +++ b/test/samples/Bf16/bf16_tile.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, @@ -15,7 +15,7 @@ BF16Type, StringAttr, ) -from mlir.dialects import func, arith, pto, builtin +from ptoas.mlir.dialects import func, arith, pto, builtin def _idx_const(v: int): diff --git a/test/samples/Ci/ci.py b/test/samples/Ci/ci.py index d7d374930c..ad5d337231 100644 --- a/test/samples/Ci/ci.py +++ b/test/samples/Ci/ci.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType, IntegerAttr, BoolAttr +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType, IntegerAttr, BoolAttr def build(): diff --git a/test/samples/Cmp/cmp.py b/test/samples/Cmp/cmp.py index b71552638d..fbbada8478 100644 --- a/test/samples/Cmp/cmp.py +++ b/test/samples/Cmp/cmp.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/Cmps/cmps.py b/test/samples/Cmps/cmps.py index 17eae6b9be..2b8f0bb7ff 100644 --- a/test/samples/Cmps/cmps.py +++ b/test/samples/Cmps/cmps.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/Colexpand/colexpand.py b/test/samples/Colexpand/colexpand.py index 044dfcb225..e2f9deed8a 100644 --- a/test/samples/Colexpand/colexpand.py +++ b/test/samples/Colexpand/colexpand.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colexpandadd/colexpandadd.py b/test/samples/Colexpandadd/colexpandadd.py index 94df4271b2..5043948b7d 100644 --- a/test/samples/Colexpandadd/colexpandadd.py +++ b/test/samples/Colexpandadd/colexpandadd.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colexpanddiv/colexpanddiv.py b/test/samples/Colexpanddiv/colexpanddiv.py index b3e6679608..f6faf69413 100644 --- a/test/samples/Colexpanddiv/colexpanddiv.py +++ b/test/samples/Colexpanddiv/colexpanddiv.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colexpanddiv/colexpanddiv_src1_vcol_mismatch_invalid.py b/test/samples/Colexpanddiv/colexpanddiv_src1_vcol_mismatch_invalid.py index aa2e612c1c..ea67e95bf3 100644 --- a/test/samples/Colexpanddiv/colexpanddiv_src1_vcol_mismatch_invalid.py +++ b/test/samples/Colexpanddiv/colexpanddiv_src1_vcol_mismatch_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import F32Type +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import F32Type def build(): diff --git a/test/samples/Colexpandexpdif/colexpandexpdif.py b/test/samples/Colexpandexpdif/colexpandexpdif.py index 7ec49106fd..bb207c8ebc 100644 --- a/test/samples/Colexpandexpdif/colexpandexpdif.py +++ b/test/samples/Colexpandexpdif/colexpandexpdif.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colexpandexpdif/colexpandexpdif_dtype_invalid.py b/test/samples/Colexpandexpdif/colexpandexpdif_dtype_invalid.py index d507da8518..429a2f8b50 100644 --- a/test/samples/Colexpandexpdif/colexpandexpdif_dtype_invalid.py +++ b/test/samples/Colexpandexpdif/colexpandexpdif_dtype_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import IntegerType def build(): diff --git a/test/samples/Colexpandmax/colexpandmax.py b/test/samples/Colexpandmax/colexpandmax.py index f7bbf72c69..681661c8f0 100644 --- a/test/samples/Colexpandmax/colexpandmax.py +++ b/test/samples/Colexpandmax/colexpandmax.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colexpandmin/colexpandmin.py b/test/samples/Colexpandmin/colexpandmin.py index 8680dfc3b1..28b8deaf10 100644 --- a/test/samples/Colexpandmin/colexpandmin.py +++ b/test/samples/Colexpandmin/colexpandmin.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colexpandmul/colexpandmul.py b/test/samples/Colexpandmul/colexpandmul.py index e8a02938c3..3e748fe3ae 100644 --- a/test/samples/Colexpandmul/colexpandmul.py +++ b/test/samples/Colexpandmul/colexpandmul.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colexpandsub/colexpandsub.py b/test/samples/Colexpandsub/colexpandsub.py index dd1c3ef8ef..287bd35eab 100644 --- a/test/samples/Colexpandsub/colexpandsub.py +++ b/test/samples/Colexpandsub/colexpandsub.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colexpandsub/colexpandsub_src0_layout_invalid.py b/test/samples/Colexpandsub/colexpandsub_src0_layout_invalid.py index d811ca37f5..097a979265 100644 --- a/test/samples/Colexpandsub/colexpandsub_src0_layout_invalid.py +++ b/test/samples/Colexpandsub/colexpandsub_src0_layout_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import F32Type +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import F32Type def build(): diff --git a/test/samples/Colmax/colmax.py b/test/samples/Colmax/colmax.py index fba23dfe26..250188a5b7 100644 --- a/test/samples/Colmax/colmax.py +++ b/test/samples/Colmax/colmax.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colmin/colmin.py b/test/samples/Colmin/colmin.py index acdea6e5de..f98683bc4f 100644 --- a/test/samples/Colmin/colmin.py +++ b/test/samples/Colmin/colmin.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colprod/colprod.py b/test/samples/Colprod/colprod.py index 5d946c5043..9e40d974cf 100644 --- a/test/samples/Colprod/colprod.py +++ b/test/samples/Colprod/colprod.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Colsum/colsum.py b/test/samples/Colsum/colsum.py index d5fca8ca96..0c3c32d044 100644 --- a/test/samples/Colsum/colsum.py +++ b/test/samples/Colsum/colsum.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, BoolAttr +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, BoolAttr def build(): diff --git a/test/samples/CommSync/comm_collective.py b/test/samples/CommSync/comm_collective.py index d198c41df4..142bbf16bd 100644 --- a/test/samples/CommSync/comm_collective.py +++ b/test/samples/CommSync/comm_collective.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): with Context() as ctx: diff --git a/test/samples/CommSync/comm_collective_binding_variants.py b/test/samples/CommSync/comm_collective_binding_variants.py index 0c5ad90b77..f8350d6377 100644 --- a/test/samples/CommSync/comm_collective_binding_variants.py +++ b/test/samples/CommSync/comm_collective_binding_variants.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/CommSync/comm_p2p.py b/test/samples/CommSync/comm_p2p.py index a7325df7d2..e26a0f1f83 100644 --- a/test/samples/CommSync/comm_p2p.py +++ b/test/samples/CommSync/comm_p2p.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/CommSync/comm_p2p_binding_variants.py b/test/samples/CommSync/comm_p2p_binding_variants.py index 3df46d762b..a302ab2eb2 100644 --- a/test/samples/CommSync/comm_p2p_binding_variants.py +++ b/test/samples/CommSync/comm_p2p_binding_variants.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/CommSync/tbroadcast_root_binding.py b/test/samples/CommSync/tbroadcast_root_binding.py index 4ec5565004..b078b29463 100644 --- a/test/samples/CommSync/tbroadcast_root_binding.py +++ b/test/samples/CommSync/tbroadcast_root_binding.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto, scf def _make_part(ptr, tv_ty, pv_ty, c0, c1, count): diff --git a/test/samples/CommSync/tgather_root_binding.py b/test/samples/CommSync/tgather_root_binding.py index b5e75c8ed9..51aeb7a1e9 100644 --- a/test/samples/CommSync/tgather_root_binding.py +++ b/test/samples/CommSync/tgather_root_binding.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto, scf def _make_part(ptr, tv_ty, pv_ty, c0, c1, count): diff --git a/test/samples/CommSync/tnotify_atomic_add_binding.py b/test/samples/CommSync/tnotify_atomic_add_binding.py index bb93ab4193..c7d0655727 100644 --- a/test/samples/CommSync/tnotify_atomic_add_binding.py +++ b/test/samples/CommSync/tnotify_atomic_add_binding.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/CommSync/treduce_root_binding.py b/test/samples/CommSync/treduce_root_binding.py index 780b36e0c8..00571c3041 100644 --- a/test/samples/CommSync/treduce_root_binding.py +++ b/test/samples/CommSync/treduce_root_binding.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto, scf def _make_part(ptr, tv_ty, pv_ty, c0, c1, count): diff --git a/test/samples/CommSync/tscatter_root_binding.py b/test/samples/CommSync/tscatter_root_binding.py index bfd1b3d8bb..c9bdf71c5d 100644 --- a/test/samples/CommSync/tscatter_root_binding.py +++ b/test/samples/CommSync/tscatter_root_binding.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto, scf def _make_part(ptr, tv_ty, pv_ty, c0, c1, count): diff --git a/test/samples/CommSync/twait_atomic_binding.py b/test/samples/CommSync/twait_atomic_binding.py index 639e2a1e32..bed112f013 100644 --- a/test/samples/CommSync/twait_atomic_binding.py +++ b/test/samples/CommSync/twait_atomic_binding.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.ir import Context, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto, scf def build(): diff --git a/test/samples/Complex/cv_region.py b/test/samples/Complex/cv_region.py index 05d7ea37d0..b000ff7cef 100644 --- a/test/samples/Complex/cv_region.py +++ b/test/samples/Complex/cv_region.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, IndexType, F32Type, UnitAttr -from mlir.dialects import func, arith, pto +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, IndexType, F32Type, UnitAttr +from ptoas.mlir.dialects import func, arith, pto def build_sections_test(): with Context() as ctx: diff --git a/test/samples/Complex/mix_kernel.py b/test/samples/Complex/mix_kernel.py index a5ed3312ea..a7f4e8f6ba 100644 --- a/test/samples/Complex/mix_kernel.py +++ b/test/samples/Complex/mix_kernel.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, Attribute, IntegerType, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, Attribute, IntegerType, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(M=32, N=32, K=32, TM=32, TN=32, TK=32): diff --git a/test/samples/Concat/concat.py b/test/samples/Concat/concat.py index 4cb4c5264f..c740481b70 100644 --- a/test/samples/Concat/concat.py +++ b/test/samples/Concat/concat.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType def build(): diff --git a/test/samples/Cvt/cvt_f32_f16.py b/test/samples/Cvt/cvt_f32_f16.py index fe00d1547f..7f68e6ed4a 100644 --- a/test/samples/Cvt/cvt_f32_f16.py +++ b/test/samples/Cvt/cvt_f32_f16.py @@ -16,8 +16,8 @@ make_tensor_view -> partition_view -> alloc_tile -> tload -> tcvt -> tstore """ -from mlir.ir import Attribute, Context, F16Type, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Attribute, Context, F16Type, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/Cvt/cvt_f32_f32.py b/test/samples/Cvt/cvt_f32_f32.py index 2fa89a0df2..b8ebf0742d 100644 --- a/test/samples/Cvt/cvt_f32_f32.py +++ b/test/samples/Cvt/cvt_f32_f32.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, BoolAttr +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, BoolAttr def build(): diff --git a/test/samples/Cvt/tcvt.py b/test/samples/Cvt/tcvt.py index 2ab189faef..b8a2a66c1b 100644 --- a/test/samples/Cvt/tcvt.py +++ b/test/samples/Cvt/tcvt.py @@ -17,7 +17,7 @@ make_tensor_view -> partition_view -> alloc_tile -> tload -> tcvt -> tstore """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Attribute, Context, F32Type, @@ -28,7 +28,7 @@ Module, UnitAttr, ) -from mlir.dialects import arith, func, pto +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/Dequant/dequant.py b/test/samples/Dequant/dequant.py index 3829aed870..93bc8375dd 100644 --- a/test/samples/Dequant/dequant.py +++ b/test/samples/Dequant/dequant.py @@ -23,7 +23,7 @@ f32 parameter tiles: Cols*4 >= 32 means Cols >= 8. """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Attribute, Context, Location, @@ -34,7 +34,7 @@ IntegerType, UnitAttr, ) -from mlir.dialects import func, arith, pto +from ptoas.mlir.dialects import func, arith, pto # Tile shapes diff --git a/test/samples/Dequant/dequant_i8.py b/test/samples/Dequant/dequant_i8.py index a21672fdbf..134159dd90 100644 --- a/test/samples/Dequant/dequant_i8.py +++ b/test/samples/Dequant/dequant_i8.py @@ -23,7 +23,7 @@ f32 parameter tiles: Cols*4 >= 32 means Cols >= 8. """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Attribute, Context, Location, @@ -34,7 +34,7 @@ IntegerType, UnitAttr, ) -from mlir.dialects import func, arith, pto +from ptoas.mlir.dialects import func, arith, pto # Tile shapes diff --git a/test/samples/Div/div.py b/test/samples/Div/div.py index eddd50b339..d36196e52d 100644 --- a/test/samples/Div/div.py +++ b/test/samples/Div/div.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, IndexType, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, IndexType, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type def build(): diff --git a/test/samples/Divs/divs.py b/test/samples/Divs/divs.py index e37ce94435..c285efc195 100644 --- a/test/samples/Divs/divs.py +++ b/test/samples/Divs/divs.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Divs2/divs2.py b/test/samples/Divs2/divs2.py index 6d52e659dc..248e8aac71 100644 --- a/test/samples/Divs2/divs2.py +++ b/test/samples/Divs2/divs2.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/DynamicTailMatmul/dynamic_tail_matmul.py b/test/samples/DynamicTailMatmul/dynamic_tail_matmul.py index 762ac5b3ac..d86c136808 100644 --- a/test/samples/DynamicTailMatmul/dynamic_tail_matmul.py +++ b/test/samples/DynamicTailMatmul/dynamic_tail_matmul.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, IndexType, IntegerType, F16Type, F32Type, UnitAttr -from mlir.dialects import func, arith, pto +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, IndexType, IntegerType, F16Type, F32Type, UnitAttr +from ptoas.mlir.dialects import func, arith, pto def build(): diff --git a/test/samples/Exp/exp.py b/test/samples/Exp/exp.py index aeddc984e0..979acdacd6 100644 --- a/test/samples/Exp/exp.py +++ b/test/samples/Exp/exp.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Expands/expand.py b/test/samples/Expands/expand.py index 77c30d59b2..f5f7e55efa 100644 --- a/test/samples/Expands/expand.py +++ b/test/samples/Expands/expand.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Extract/extract.py b/test/samples/Extract/extract.py index 2618f43f72..d649fe44ed 100644 --- a/test/samples/Extract/extract.py +++ b/test/samples/Extract/extract.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, F32Type, IndexType def build(): diff --git a/test/samples/Extract/extract_fp.py b/test/samples/Extract/extract_fp.py index 085db33f01..594e40c971 100644 --- a/test/samples/Extract/extract_fp.py +++ b/test/samples/Extract/extract_fp.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/Fillpad/fillpad.py b/test/samples/Fillpad/fillpad.py index 07908652ae..e221c9accd 100644 --- a/test/samples/Fillpad/fillpad.py +++ b/test/samples/Fillpad/fillpad.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Fillpad/fillpad_expand.py b/test/samples/Fillpad/fillpad_expand.py index 5f06ab054a..1bfd10011e 100644 --- a/test/samples/Fillpad/fillpad_expand.py +++ b/test/samples/Fillpad/fillpad_expand.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, InsertionPoint, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, InsertionPoint, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Fillpad/fillpad_expand_invalid.py b/test/samples/Fillpad/fillpad_expand_invalid.py index 1cb14c144a..98fdf7206b 100644 --- a/test/samples/Fillpad/fillpad_expand_invalid.py +++ b/test/samples/Fillpad/fillpad_expand_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, InsertionPoint, Location, Module, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import F32Type +from ptoas.mlir.ir import Context, InsertionPoint, Location, Module, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import F32Type def build(): diff --git a/test/samples/Fillpad/fillpad_expand_pad_null_invalid.py b/test/samples/Fillpad/fillpad_expand_pad_null_invalid.py index 8926dc905a..a3f250b95f 100644 --- a/test/samples/Fillpad/fillpad_expand_pad_null_invalid.py +++ b/test/samples/Fillpad/fillpad_expand_pad_null_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, InsertionPoint, Location, Module, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import F32Type +from ptoas.mlir.ir import Context, InsertionPoint, Location, Module, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import F32Type def build(): diff --git a/test/samples/Fillpad/fillpad_inplace.py b/test/samples/Fillpad/fillpad_inplace.py index 25f16eddd7..b4159ef842 100644 --- a/test/samples/Fillpad/fillpad_inplace.py +++ b/test/samples/Fillpad/fillpad_inplace.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Fmod/fmod.py b/test/samples/Fmod/fmod.py index 87c58f33b7..32a1a79ff0 100644 --- a/test/samples/Fmod/fmod.py +++ b/test/samples/Fmod/fmod.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Fmods/fmods.py b/test/samples/Fmods/fmods.py index e852a67fe3..77c43e8193 100644 --- a/test/samples/Fmods/fmods.py +++ b/test/samples/Fmods/fmods.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Fmods/tfmods_scalar_type_invalid.py b/test/samples/Fmods/tfmods_scalar_type_invalid.py index f478435ae1..634ad763ae 100644 --- a/test/samples/Fmods/tfmods_scalar_type_invalid.py +++ b/test/samples/Fmods/tfmods_scalar_type_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IntegerType def build(): diff --git a/test/samples/Gather/gather.py b/test/samples/Gather/gather.py index bcb9c3dbf7..08ec15b6f8 100644 --- a/test/samples/Gather/gather.py +++ b/test/samples/Gather/gather.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto -from mlir.ir import IntegerType +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto +from ptoas.mlir.ir import IntegerType def build(): diff --git a/test/samples/Gather/gather_legacy.py b/test/samples/Gather/gather_legacy.py index eecfab05e0..dcf33bcdce 100644 --- a/test/samples/Gather/gather_legacy.py +++ b/test/samples/Gather/gather_legacy.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Gatherb/gatherb.py b/test/samples/Gatherb/gatherb.py index 4b1a0e435d..cf76034bbe 100644 --- a/test/samples/Gatherb/gatherb.py +++ b/test/samples/Gatherb/gatherb.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.dialects import arith, func, pto -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr def build(): diff --git a/test/samples/Gemv/gemv.py b/test/samples/Gemv/gemv.py index 416c2b0076..5870784948 100644 --- a/test/samples/Gemv/gemv.py +++ b/test/samples/Gemv/gemv.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, F32Type, IndexType def build(): diff --git a/test/samples/Gemv/gemvacc.py b/test/samples/Gemv/gemvacc.py index d70916cfeb..27c2b8c276 100644 --- a/test/samples/Gemv/gemvacc.py +++ b/test/samples/Gemv/gemvacc.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, F32Type, IndexType def build(): diff --git a/test/samples/Gemv/gemvbias.py b/test/samples/Gemv/gemvbias.py index 5beb088c7d..6ca847542e 100644 --- a/test/samples/Gemv/gemvbias.py +++ b/test/samples/Gemv/gemvbias.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, F32Type, IndexType def build(): diff --git a/test/samples/Gemvmx/gemvmx.py b/test/samples/Gemvmx/gemvmx.py index b667873a7b..c624a5d452 100644 --- a/test/samples/Gemvmx/gemvmx.py +++ b/test/samples/Gemvmx/gemvmx.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, StringAttr, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, F32Type, Float8E4M3FNType, Float8E5M2Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, StringAttr, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, F32Type, Float8E4M3FNType, Float8E5M2Type, IndexType def build(): diff --git a/test/samples/Layout/tensor_view_infer_layout_dn.py b/test/samples/Layout/tensor_view_infer_layout_dn.py index 05b29b8fd1..488cb3eb75 100644 --- a/test/samples/Layout/tensor_view_infer_layout_dn.py +++ b/test/samples/Layout/tensor_view_infer_layout_dn.py @@ -16,9 +16,9 @@ The expected emitted C++ should use `pto::Layout::DN` in GlobalTensor<>. """ -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Layout/tensor_view_layout_dn.py b/test/samples/Layout/tensor_view_layout_dn.py index 8d311920a4..984599cba1 100644 --- a/test/samples/Layout/tensor_view_layout_dn.py +++ b/test/samples/Layout/tensor_view_layout_dn.py @@ -15,8 +15,8 @@ - The generated C++ GlobalTensor uses pto::Layout::DN. """ -from mlir.ir import Context, Location, InsertionPoint, Module, IndexType -from mlir.dialects import arith, func, pto, builtin +from ptoas.mlir.ir import Context, Location, InsertionPoint, Module, IndexType +from ptoas.mlir.dialects import arith, func, pto, builtin def idx(val: int): diff --git a/test/samples/LayoutInference/layout_inference.py b/test/samples/LayoutInference/layout_inference.py index 8b72d15646..2944d3b969 100644 --- a/test/samples/LayoutInference/layout_inference.py +++ b/test/samples/LayoutInference/layout_inference.py @@ -20,7 +20,7 @@ on each make_tensor_view op. """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Context, InsertionPoint, Location, @@ -29,7 +29,7 @@ IndexType, UnitAttr, ) -from mlir.dialects import func, arith, pto +from ptoas.mlir.dialects import func, arith, pto from typing import Optional import sys diff --git a/test/samples/Log/log.py b/test/samples/Log/log.py index 0edf56293c..ac93b89b4d 100644 --- a/test/samples/Log/log.py +++ b/test/samples/Log/log.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Lrelu/lrelu.py b/test/samples/Lrelu/lrelu.py index 877a0a74ae..56e5736a99 100644 --- a/test/samples/Lrelu/lrelu.py +++ b/test/samples/Lrelu/lrelu.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/MatMul/tmatmulk.py b/test/samples/MatMul/tmatmulk.py index 1a75231e86..06bc905a4f 100644 --- a/test/samples/MatMul/tmatmulk.py +++ b/test/samples/MatMul/tmatmulk.py @@ -6,17 +6,17 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, InsertionPoint, IndexType, IntegerType, F16Type, F32Type, StringAttr ) -from mlir.dialects import func, arith, scf, pto, builtin -from mlir.dialects.pto import ( +from ptoas.mlir.dialects import func, arith, scf, pto, builtin +from ptoas.mlir.dialects.pto import ( TLOAD, TMOV_M2L, TMATMUL, TSTORE_ACC, EVENT_ID0 ) -from mlir.dialects.arith import CmpIPredicate +from ptoas.mlir.dialects.arith import CmpIPredicate def _idx_const(v: int): diff --git a/test/samples/MatmulMxLowPrecision/matmul_mx_low_precision.py b/test/samples/MatmulMxLowPrecision/matmul_mx_low_precision.py index 14a30dd803..3661b60692 100644 --- a/test/samples/MatmulMxLowPrecision/matmul_mx_low_precision.py +++ b/test/samples/MatmulMxLowPrecision/matmul_mx_low_precision.py @@ -7,7 +7,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( Attribute, Context, F16Type, @@ -20,7 +20,7 @@ StringAttr, UnitAttr, ) -from mlir.dialects import func, pto +from ptoas.mlir.dialects import func, pto def build(): diff --git a/test/samples/Matmul_transpose/Matmul_transpose.py b/test/samples/Matmul_transpose/Matmul_transpose.py index 46b2ea916c..9e1f8d9aa4 100644 --- a/test/samples/Matmul_transpose/Matmul_transpose.py +++ b/test/samples/Matmul_transpose/Matmul_transpose.py @@ -15,9 +15,9 @@ - pto-as/test/samples/MatMul/tmatmulk.py """ -from mlir.ir import Context, Location, InsertionPoint, IndexType, IntegerType, F32Type, StringAttr, UnitAttr -from mlir.dialects import func, arith, scf, pto, builtin -from mlir.dialects.pto import TLOAD, TMOV_M2L, TMATMUL, TSTORE_ACC, EVENT_ID0 +from ptoas.mlir.ir import Context, Location, InsertionPoint, IndexType, IntegerType, F32Type, StringAttr, UnitAttr +from ptoas.mlir.dialects import func, arith, scf, pto, builtin +from ptoas.mlir.dialects.pto import TLOAD, TMOV_M2L, TMATMUL, TSTORE_ACC, EVENT_ID0 def _idx_const(v: int): diff --git a/test/samples/Max/max.py b/test/samples/Max/max.py index f6c74c3c1d..a62b1c7107 100644 --- a/test/samples/Max/max.py +++ b/test/samples/Max/max.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Maxs/maxs.py b/test/samples/Maxs/maxs.py index a51b0b3139..cd0e85cb6c 100644 --- a/test/samples/Maxs/maxs.py +++ b/test/samples/Maxs/maxs.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Mgather/mgather.py b/test/samples/Mgather/mgather.py index 543d1211ae..9269e3072e 100644 --- a/test/samples/Mgather/mgather.py +++ b/test/samples/Mgather/mgather.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Attribute, Context, Location, Module, InsertionPoint, StringAttr, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IndexType, IntegerType +from ptoas.mlir.ir import Attribute, Context, Location, Module, InsertionPoint, StringAttr, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IndexType, IntegerType def build(): diff --git a/test/samples/Min/min.py b/test/samples/Min/min.py index 4b19f65e91..6ffe24fdb9 100644 --- a/test/samples/Min/min.py +++ b/test/samples/Min/min.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Mins/mins.py b/test/samples/Mins/mins.py index 86cfd556fa..928db3d38c 100644 --- a/test/samples/Mins/mins.py +++ b/test/samples/Mins/mins.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Movfp/movfp.py b/test/samples/Movfp/movfp.py index dda90fe81e..47e75e88ad 100644 --- a/test/samples/Movfp/movfp.py +++ b/test/samples/Movfp/movfp.py @@ -16,9 +16,9 @@ - src must be ACC tile; dst must be MAT tile. """ -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/Mrgsort/mrgsort.py b/test/samples/Mrgsort/mrgsort.py index 4d58443f0b..4c5b000911 100644 --- a/test/samples/Mrgsort/mrgsort.py +++ b/test/samples/Mrgsort/mrgsort.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/Mrgsort/mrgsort_a5.py b/test/samples/Mrgsort/mrgsort_a5.py index 40251dd2fb..b3d2ac9970 100644 --- a/test/samples/Mrgsort/mrgsort_a5.py +++ b/test/samples/Mrgsort/mrgsort_a5.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/Mrgsort/mrgsort_format2.py b/test/samples/Mrgsort/mrgsort_format2.py index 4179f6e3eb..6c43018901 100644 --- a/test/samples/Mrgsort/mrgsort_format2.py +++ b/test/samples/Mrgsort/mrgsort_format2.py @@ -15,11 +15,11 @@ - This testcase covers all three forms in a single function entry so it fits the remote validation flow. """ -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType -from mlir.ir import VectorType +from ptoas.mlir.ir import VectorType def build(): diff --git a/test/samples/Mscatter/mscatter.py b/test/samples/Mscatter/mscatter.py index d3dca96d53..a314705e92 100644 --- a/test/samples/Mscatter/mscatter.py +++ b/test/samples/Mscatter/mscatter.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, StringAttr, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, StringAttr, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IndexType, IntegerType def build(): diff --git a/test/samples/Mul/mul.py b/test/samples/Mul/mul.py index 3b1be61534..05f80fdea8 100644 --- a/test/samples/Mul/mul.py +++ b/test/samples/Mul/mul.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Muls/muls.py b/test/samples/Muls/muls.py index dd1573dace..fa72991760 100644 --- a/test/samples/Muls/muls.py +++ b/test/samples/Muls/muls.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Neg/neg.py b/test/samples/Neg/neg.py index 5cb5f8f10b..a64a264947 100644 --- a/test/samples/Neg/neg.py +++ b/test/samples/Neg/neg.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Not/not.py b/test/samples/Not/not.py index 400fcbcedb..369481fddc 100644 --- a/test/samples/Not/not.py +++ b/test/samples/Not/not.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType def build(): diff --git a/test/samples/Or/or.py b/test/samples/Or/or.py index e958119129..76a1676669 100644 --- a/test/samples/Or/or.py +++ b/test/samples/Or/or.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType def build(): diff --git a/test/samples/Ors/ors.py b/test/samples/Ors/ors.py index 3ed43d47fd..afa0e8f8a4 100644 --- a/test/samples/Ors/ors.py +++ b/test/samples/Ors/ors.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType, IntegerAttr +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType, IntegerAttr def build(): diff --git a/test/samples/Partadd/partadd.py b/test/samples/Partadd/partadd.py index 85cfe40adc..3a54a054af 100644 --- a/test/samples/Partadd/partadd.py +++ b/test/samples/Partadd/partadd.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Partarg/partarg.py b/test/samples/Partarg/partarg.py index 0c156e36a6..01b9459a91 100644 --- a/test/samples/Partarg/partarg.py +++ b/test/samples/Partarg/partarg.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.dialects import arith, func, pto -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr def build(): diff --git a/test/samples/Partition5D/partition5d.py b/test/samples/Partition5D/partition5d.py index 0e9d11c67e..25a684f34c 100644 --- a/test/samples/Partition5D/partition5d.py +++ b/test/samples/Partition5D/partition5d.py @@ -16,14 +16,14 @@ 4) tstore writes back to the destination tensor_view """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Context, Location, InsertionPoint, Module, IndexType, ) -from mlir.dialects import arith, func, pto, builtin +from ptoas.mlir.dialects import arith, func, pto, builtin def idx(val: int): diff --git a/test/samples/Partition5D/partition5d_a5.py b/test/samples/Partition5D/partition5d_a5.py index 91da2458e8..021693ee52 100644 --- a/test/samples/Partition5D/partition5d_a5.py +++ b/test/samples/Partition5D/partition5d_a5.py @@ -16,14 +16,14 @@ 4) tstore writes back to the destination tensor_view """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Context, Location, InsertionPoint, Module, IndexType, ) -from mlir.dialects import arith, func, pto, builtin +from ptoas.mlir.dialects import arith, func, pto, builtin def idx(val: int): diff --git a/test/samples/Partmax/partmax.py b/test/samples/Partmax/partmax.py index 9c91b5df56..b5a2a5e347 100644 --- a/test/samples/Partmax/partmax.py +++ b/test/samples/Partmax/partmax.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Partmin/partmin.py b/test/samples/Partmin/partmin.py index 32baa46d83..d4a6cd5a16 100644 --- a/test/samples/Partmin/partmin.py +++ b/test/samples/Partmin/partmin.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Partmul/partmul.py b/test/samples/Partmul/partmul.py index 0dcde4f4eb..d7dd68e626 100644 --- a/test/samples/Partmul/partmul.py +++ b/test/samples/Partmul/partmul.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Prelu/prelu.py b/test/samples/Prelu/prelu.py index e01f0fc94e..ec508cf027 100644 --- a/test/samples/Prelu/prelu.py +++ b/test/samples/Prelu/prelu.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/Print/print.py b/test/samples/Print/print.py index 33f2942391..5fd0562496 100644 --- a/test/samples/Print/print.py +++ b/test/samples/Print/print.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): with Context() as ctx: diff --git a/test/samples/Print/print_scalar.py b/test/samples/Print/print_scalar.py index 8478319114..58c3013879 100644 --- a/test/samples/Print/print_scalar.py +++ b/test/samples/Print/print_scalar.py @@ -7,9 +7,9 @@ # See LICENSE in the root of the software repository for the full text of the License. """Test pto.print: format is string attribute, scalar is operand. Generates PRINTF("format", scalar) in C++.""" -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import F32Type +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import F32Type def build(): diff --git a/test/samples/Quant/quant.py b/test/samples/Quant/quant.py index 7e802bbc6f..cdfa3d5952 100644 --- a/test/samples/Quant/quant.py +++ b/test/samples/Quant/quant.py @@ -17,7 +17,7 @@ (the NPU aligned-size). At 1 byte/element that means Cols >= 32. """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Attribute, Context, Location, @@ -28,7 +28,7 @@ IntegerType, UnitAttr, ) -from mlir.dialects import func, arith, pto +from ptoas.mlir.dialects import func, arith, pto # Tile shape used throughout the sample. diff --git a/test/samples/Quant/quant_asym.py b/test/samples/Quant/quant_asym.py index 67490c96e7..aab8e02ed2 100644 --- a/test/samples/Quant/quant_asym.py +++ b/test/samples/Quant/quant_asym.py @@ -18,7 +18,7 @@ (the NPU aligned-size). At 1 byte/element that means Cols >= 32. """ -from mlir.ir import ( +from ptoas.mlir.ir import ( Attribute, Context, Location, @@ -29,7 +29,7 @@ IntegerType, UnitAttr, ) -from mlir.dialects import func, arith, pto +from ptoas.mlir.dialects import func, arith, pto # Tile shape used throughout the sample. diff --git a/test/samples/Recip/recip.py b/test/samples/Recip/recip.py index 132295f5e2..410e8ab7f2 100644 --- a/test/samples/Recip/recip.py +++ b/test/samples/Recip/recip.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Relu/relu.py b/test/samples/Relu/relu.py index a4b6078f1f..073eb19393 100644 --- a/test/samples/Relu/relu.py +++ b/test/samples/Relu/relu.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rem/rem.py b/test/samples/Rem/rem.py index 7a8f50ef9d..245b16d73b 100644 --- a/test/samples/Rem/rem.py +++ b/test/samples/Rem/rem.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rems/rems.py b/test/samples/Rems/rems.py index 3f5b0cefd6..fd55edeba9 100644 --- a/test/samples/Rems/rems.py +++ b/test/samples/Rems/rems.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Reshape/bitcast_dtype_alias.py b/test/samples/Reshape/bitcast_dtype_alias.py index a107ecf1e2..ff2826d645 100644 --- a/test/samples/Reshape/bitcast_dtype_alias.py +++ b/test/samples/Reshape/bitcast_dtype_alias.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/Reshape/bitcast_inplace_cvt.py b/test/samples/Reshape/bitcast_inplace_cvt.py index 7ba321e293..0f504f7590 100644 --- a/test/samples/Reshape/bitcast_inplace_cvt.py +++ b/test/samples/Reshape/bitcast_inplace_cvt.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, F32Type, IndexType def build(): diff --git a/test/samples/Reshape/bitcast_same_dtype_invalid.py b/test/samples/Reshape/bitcast_same_dtype_invalid.py index 44f3bd3c46..ea0271ffd5 100644 --- a/test/samples/Reshape/bitcast_same_dtype_invalid.py +++ b/test/samples/Reshape/bitcast_same_dtype_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import F32Type +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import F32Type def build(): diff --git a/test/samples/Reshape/reshape.py b/test/samples/Reshape/reshape.py index 244b3a540d..ce265c0ccb 100644 --- a/test/samples/Reshape/reshape.py +++ b/test/samples/Reshape/reshape.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowexpand/rowexpand.py b/test/samples/Rowexpand/rowexpand.py index 6f0622cbec..54c62361dc 100644 --- a/test/samples/Rowexpand/rowexpand.py +++ b/test/samples/Rowexpand/rowexpand.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowexpandadd/rowexpandadd.py b/test/samples/Rowexpandadd/rowexpandadd.py index cf4faa7f16..74d8414337 100644 --- a/test/samples/Rowexpandadd/rowexpandadd.py +++ b/test/samples/Rowexpandadd/rowexpandadd.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowexpandadd/rowexpandadd_src1_width_invalid.py b/test/samples/Rowexpandadd/rowexpandadd_src1_width_invalid.py index a47feb3b80..19a68eeb5f 100644 --- a/test/samples/Rowexpandadd/rowexpandadd_src1_width_invalid.py +++ b/test/samples/Rowexpandadd/rowexpandadd_src1_width_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import F32Type +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import F32Type def build(): diff --git a/test/samples/Rowexpanddiv/rowexpanddiv.py b/test/samples/Rowexpanddiv/rowexpanddiv.py index aa6c2e46fe..cff800754f 100644 --- a/test/samples/Rowexpanddiv/rowexpanddiv.py +++ b/test/samples/Rowexpanddiv/rowexpanddiv.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowexpandexpdif/rowexpandexpdif.py b/test/samples/Rowexpandexpdif/rowexpandexpdif.py index 6955a0d411..ca0c22d032 100644 --- a/test/samples/Rowexpandexpdif/rowexpandexpdif.py +++ b/test/samples/Rowexpandexpdif/rowexpandexpdif.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowexpandexpdif/rowexpandexpdif_dtype_invalid.py b/test/samples/Rowexpandexpdif/rowexpandexpdif_dtype_invalid.py index 7027715436..772b2d5cf5 100644 --- a/test/samples/Rowexpandexpdif/rowexpandexpdif_dtype_invalid.py +++ b/test/samples/Rowexpandexpdif/rowexpandexpdif_dtype_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import IntegerType def build(): diff --git a/test/samples/Rowexpandmax/rowexpandmax.py b/test/samples/Rowexpandmax/rowexpandmax.py index 26b2d5d2dd..fc6e695974 100644 --- a/test/samples/Rowexpandmax/rowexpandmax.py +++ b/test/samples/Rowexpandmax/rowexpandmax.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowexpandmax/rowexpandmax_a5_tmp_invalid.py b/test/samples/Rowexpandmax/rowexpandmax_a5_tmp_invalid.py index 48d832a527..1c3ac39955 100644 --- a/test/samples/Rowexpandmax/rowexpandmax_a5_tmp_invalid.py +++ b/test/samples/Rowexpandmax/rowexpandmax_a5_tmp_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, StringAttr, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import F32Type, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, StringAttr, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import F32Type, IntegerType def build(): diff --git a/test/samples/Rowexpandmin/rowexpandmin.py b/test/samples/Rowexpandmin/rowexpandmin.py index b708716550..9ea8728d0a 100644 --- a/test/samples/Rowexpandmin/rowexpandmin.py +++ b/test/samples/Rowexpandmin/rowexpandmin.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowexpandmul/rowexpandmul.py b/test/samples/Rowexpandmul/rowexpandmul.py index e90dfce604..066eb3817e 100644 --- a/test/samples/Rowexpandmul/rowexpandmul.py +++ b/test/samples/Rowexpandmul/rowexpandmul.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowexpandsub/rowexpandsub.py b/test/samples/Rowexpandsub/rowexpandsub.py index 15768203c6..04a84f89a9 100644 --- a/test/samples/Rowexpandsub/rowexpandsub.py +++ b/test/samples/Rowexpandsub/rowexpandsub.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowmax/rowmax.py b/test/samples/Rowmax/rowmax.py index 8e7798d8ac..30819eca8a 100644 --- a/test/samples/Rowmax/rowmax.py +++ b/test/samples/Rowmax/rowmax.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowmin/rowmin.py b/test/samples/Rowmin/rowmin.py index 4c7c3fde81..a51efdf81c 100644 --- a/test/samples/Rowmin/rowmin.py +++ b/test/samples/Rowmin/rowmin.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowprod/rowprod.py b/test/samples/Rowprod/rowprod.py index 7246a7407a..15e7c55734 100644 --- a/test/samples/Rowprod/rowprod.py +++ b/test/samples/Rowprod/rowprod.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rowsum/rowsum.py b/test/samples/Rowsum/rowsum.py index 452fb36c32..d7c5842f82 100644 --- a/test/samples/Rowsum/rowsum.py +++ b/test/samples/Rowsum/rowsum.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Rsqrt/rsqrt.py b/test/samples/Rsqrt/rsqrt.py index a43331cc41..bc04f8a13d 100644 --- a/test/samples/Rsqrt/rsqrt.py +++ b/test/samples/Rsqrt/rsqrt.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/ScalarPtr/scalar_ptr.py b/test/samples/ScalarPtr/scalar_ptr.py index baec3bd58c..f4f5e20bff 100644 --- a/test/samples/ScalarPtr/scalar_ptr.py +++ b/test/samples/ScalarPtr/scalar_ptr.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Scatter/scatter.py b/test/samples/Scatter/scatter.py index 569f612c82..6ef873b06d 100644 --- a/test/samples/Scatter/scatter.py +++ b/test/samples/Scatter/scatter.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.dialects import arith, func, pto -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr def build(): diff --git a/test/samples/Sel/sel.py b/test/samples/Sel/sel.py index ffbd047026..f4ae49b5ac 100644 --- a/test/samples/Sel/sel.py +++ b/test/samples/Sel/sel.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/Sels/sels.py b/test/samples/Sels/sels.py index 40411f708a..1e10484e6b 100644 --- a/test/samples/Sels/sels.py +++ b/test/samples/Sels/sels.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, IntegerType, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, IntegerType, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): with Context() as ctx: diff --git a/test/samples/SetValidShape/set_validshape.py b/test/samples/SetValidShape/set_validshape.py index 93a9edb7ee..dc003b07d2 100644 --- a/test/samples/SetValidShape/set_validshape.py +++ b/test/samples/SetValidShape/set_validshape.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Shl/shl.py b/test/samples/Shl/shl.py index 2c65bdab16..3a45069f6f 100644 --- a/test/samples/Shl/shl.py +++ b/test/samples/Shl/shl.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType def build(): diff --git a/test/samples/Shls/shls.py b/test/samples/Shls/shls.py index 3359f4f47e..19886789e0 100644 --- a/test/samples/Shls/shls.py +++ b/test/samples/Shls/shls.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IndexType, IntegerType def build(): diff --git a/test/samples/Shr/shr.py b/test/samples/Shr/shr.py index ca500102dd..5040781517 100644 --- a/test/samples/Shr/shr.py +++ b/test/samples/Shr/shr.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType def build(): diff --git a/test/samples/Shrs/shrs.py b/test/samples/Shrs/shrs.py index a1640c0e08..448d4049c1 100644 --- a/test/samples/Shrs/shrs.py +++ b/test/samples/Shrs/shrs.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IndexType, IntegerType def build(): diff --git a/test/samples/Sort32/sort32.py b/test/samples/Sort32/sort32.py index 79c12c1c7d..d32567ea13 100644 --- a/test/samples/Sort32/sort32.py +++ b/test/samples/Sort32/sort32.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IntegerType, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IntegerType, IndexType def build(): diff --git a/test/samples/Sqrt/sqrt.py b/test/samples/Sqrt/sqrt.py index d2f34653ab..fc9cfaa525 100644 --- a/test/samples/Sqrt/sqrt.py +++ b/test/samples/Sqrt/sqrt.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Storefp/storefp.py b/test/samples/Storefp/storefp.py index 0d8edd5dcb..a37f689366 100644 --- a/test/samples/Storefp/storefp.py +++ b/test/samples/Storefp/storefp.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IntegerType, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IntegerType, IndexType def build(): with Context() as ctx: diff --git a/test/samples/Storefp/storefp_invalid.py b/test/samples/Storefp/storefp_invalid.py index 92906076ab..aeed23011e 100644 --- a/test/samples/Storefp/storefp_invalid.py +++ b/test/samples/Storefp/storefp_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, pto -from mlir.ir import F16Type, IntegerType, MemRefType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, pto +from ptoas.mlir.ir import F16Type, IntegerType, MemRefType def build(): diff --git a/test/samples/Sub/sub.py b/test/samples/Sub/sub.py index 4f199b1a16..375b9ded5c 100644 --- a/test/samples/Sub/sub.py +++ b/test/samples/Sub/sub.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/SubView/subview.py b/test/samples/SubView/subview.py index 7b33c74fa1..ecdc4cb940 100644 --- a/test/samples/SubView/subview.py +++ b/test/samples/SubView/subview.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/SubView/subview_boxed_dynamic.py b/test/samples/SubView/subview_boxed_dynamic.py index 57ce85d657..6a69817376 100644 --- a/test/samples/SubView/subview_boxed_dynamic.py +++ b/test/samples/SubView/subview_boxed_dynamic.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, IndexType def build(): diff --git a/test/samples/SubView/subview_boxed_invalid.py b/test/samples/SubView/subview_boxed_invalid.py index 6099705119..03a76ba229 100644 --- a/test/samples/SubView/subview_boxed_invalid.py +++ b/test/samples/SubView/subview_boxed_invalid.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, IndexType def build(): diff --git a/test/samples/SubView/subview_tsubs.py b/test/samples/SubView/subview_tsubs.py index 7081d0fb6f..60676aed00 100644 --- a/test/samples/SubView/subview_tsubs.py +++ b/test/samples/SubView/subview_tsubs.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/SubView/vadd_pto_pingpong.py b/test/samples/SubView/vadd_pto_pingpong.py index f6e106c26d..7153f50ebe 100644 --- a/test/samples/SubView/vadd_pto_pingpong.py +++ b/test/samples/SubView/vadd_pto_pingpong.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build_pingpong(): with Context() as ctx: diff --git a/test/samples/Subc/subc.py b/test/samples/Subc/subc.py index d220f4c378..f06057ded5 100644 --- a/test/samples/Subc/subc.py +++ b/test/samples/Subc/subc.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Subs/subs.py b/test/samples/Subs/subs.py index e0e60988ac..a59742a8ac 100644 --- a/test/samples/Subs/subs.py +++ b/test/samples/Subs/subs.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Subsc/subsc.py b/test/samples/Subsc/subsc.py index 510d913f63..f0005a1b0a 100644 --- a/test/samples/Subsc/subsc.py +++ b/test/samples/Subsc/subsc.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Sync/sync.py b/test/samples/Sync/sync.py index 5b404f618a..b7b72e09e4 100644 --- a/test/samples/Sync/sync.py +++ b/test/samples/Sync/sync.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Sync/syncHigh.py b/test/samples/Sync/syncHigh.py index 61e797e15b..ff4dd26e65 100755 --- a/test/samples/Sync/syncHigh.py +++ b/test/samples/Sync/syncHigh.py @@ -7,9 +7,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Sync/test_a5_buf_sync.py b/test/samples/Sync/test_a5_buf_sync.py index 62be895521..9a5676c370 100644 --- a/test/samples/Sync/test_a5_buf_sync.py +++ b/test/samples/Sync/test_a5_buf_sync.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, pto +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, pto def build(): diff --git a/test/samples/Sync/test_inject_sync_if.py b/test/samples/Sync/test_inject_sync_if.py index c0ffd0ea81..29478d54b6 100644 --- a/test/samples/Sync/test_inject_sync_if.py +++ b/test/samples/Sync/test_inject_sync_if.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, @@ -16,7 +16,7 @@ IndexType, IntegerType, ) -from mlir.dialects import func, arith, scf, pto +from ptoas.mlir.dialects import func, arith, scf, pto def _idx_const(v: int): diff --git a/test/samples/Sync/test_inject_sync_if_else.py b/test/samples/Sync/test_inject_sync_if_else.py index 4dc1d20d0c..c175f15ed0 100644 --- a/test/samples/Sync/test_inject_sync_if_else.py +++ b/test/samples/Sync/test_inject_sync_if_else.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, @@ -16,7 +16,7 @@ IndexType, IntegerType, ) -from mlir.dialects import func, arith, scf, pto +from ptoas.mlir.dialects import func, arith, scf, pto def _idx_const(v: int): diff --git a/test/samples/Sync/test_inject_sync_intra_pipe_barrier.py b/test/samples/Sync/test_inject_sync_intra_pipe_barrier.py index 0f63d00657..60059ae3ef 100644 --- a/test/samples/Sync/test_inject_sync_intra_pipe_barrier.py +++ b/test/samples/Sync/test_inject_sync_intra_pipe_barrier.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.ir import F16Type -from mlir.dialects import func, pto +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.ir import F16Type +from ptoas.mlir.dialects import func, pto def build(): diff --git a/test/samples/Sync/test_inject_sync_loop.py b/test/samples/Sync/test_inject_sync_loop.py index 3b12958241..e2221dea8c 100644 --- a/test/samples/Sync/test_inject_sync_loop.py +++ b/test/samples/Sync/test_inject_sync_loop.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, @@ -15,8 +15,8 @@ F16Type, IndexType, ) -from mlir.dialects import func, arith, scf, pto -from mlir.dialects.arith import CmpIPredicate +from ptoas.mlir.dialects import func, arith, scf, pto +from ptoas.mlir.dialects.arith import CmpIPredicate def _idx_const(v: int): diff --git a/test/samples/Sync/test_inject_sync_loop_nest.py b/test/samples/Sync/test_inject_sync_loop_nest.py index 3e25acc909..b561f0846f 100644 --- a/test/samples/Sync/test_inject_sync_loop_nest.py +++ b/test/samples/Sync/test_inject_sync_loop_nest.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, @@ -15,8 +15,8 @@ F16Type, IndexType, ) -from mlir.dialects import func, arith, scf, pto -from mlir.dialects.arith import CmpIPredicate +from ptoas.mlir.dialects import func, arith, scf, pto +from ptoas.mlir.dialects.arith import CmpIPredicate def _idx_const(v: int): diff --git a/test/samples/Sync/test_inject_sync_two_event_id.py b/test/samples/Sync/test_inject_sync_two_event_id.py index 0b42083c95..e277fe5d95 100644 --- a/test/samples/Sync/test_inject_sync_two_event_id.py +++ b/test/samples/Sync/test_inject_sync_two_event_id.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, @@ -15,7 +15,7 @@ F16Type, IndexType, ) -from mlir.dialects import func, arith, pto +from ptoas.mlir.dialects import func, arith, pto def _idx_const(v: int): diff --git a/test/samples/Sync/test_intercore_sync_a3.py b/test/samples/Sync/test_intercore_sync_a3.py index 5ce20add1d..59fb54d326 100644 --- a/test/samples/Sync/test_intercore_sync_a3.py +++ b/test/samples/Sync/test_intercore_sync_a3.py @@ -7,7 +7,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, F32Type, @@ -18,7 +18,7 @@ MemRefType, Module, ) -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.dialects import arith, func, pto, scf def build(): diff --git a/test/samples/Sync/test_intercore_sync_a3_dyn.py b/test/samples/Sync/test_intercore_sync_a3_dyn.py index 302554847b..375929788f 100644 --- a/test/samples/Sync/test_intercore_sync_a3_dyn.py +++ b/test/samples/Sync/test_intercore_sync_a3_dyn.py @@ -7,7 +7,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, F32Type, @@ -18,7 +18,7 @@ MemRefType, Module, ) -from mlir.dialects import arith, func, pto, scf +from ptoas.mlir.dialects import arith, func, pto, scf def build(): diff --git a/test/samples/Sync/test_intercore_sync_a3_missing_setffts.py b/test/samples/Sync/test_intercore_sync_a3_missing_setffts.py index 847e29c9a9..223b4b421c 100644 --- a/test/samples/Sync/test_intercore_sync_a3_missing_setffts.py +++ b/test/samples/Sync/test_intercore_sync_a3_missing_setffts.py @@ -7,8 +7,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, InsertionPoint, Location, Module, UnitAttr -from mlir.dialects import func, pto +from ptoas.mlir.ir import Context, InsertionPoint, Location, Module, UnitAttr +from ptoas.mlir.dialects import func, pto def build(): diff --git a/test/samples/Sync/test_intercore_sync_a3_modes.py b/test/samples/Sync/test_intercore_sync_a3_modes.py index ff7614b488..f3c9d4c5e3 100644 --- a/test/samples/Sync/test_intercore_sync_a3_modes.py +++ b/test/samples/Sync/test_intercore_sync_a3_modes.py @@ -7,8 +7,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, IndexType, InsertionPoint, IntegerType, Location, MemRefType, Module, UnitAttr -from mlir.dialects import func, pto +from ptoas.mlir.ir import Context, IndexType, InsertionPoint, IntegerType, Location, MemRefType, Module, UnitAttr +from ptoas.mlir.dialects import func, pto def build(): diff --git a/test/samples/Sync/test_intercore_sync_a5.py b/test/samples/Sync/test_intercore_sync_a5.py index c3f9607ed4..d7089fc697 100644 --- a/test/samples/Sync/test_intercore_sync_a5.py +++ b/test/samples/Sync/test_intercore_sync_a5.py @@ -7,7 +7,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, F32Type, @@ -16,7 +16,7 @@ Location, Module, ) -from mlir.dialects import arith, func, pto +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/Sync/test_intercore_sync_a5_dyn.py b/test/samples/Sync/test_intercore_sync_a5_dyn.py index cc7b9d7535..b53e759143 100644 --- a/test/samples/Sync/test_intercore_sync_a5_dyn.py +++ b/test/samples/Sync/test_intercore_sync_a5_dyn.py @@ -7,8 +7,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/Sync/test_intercore_sync_a5_functional.py b/test/samples/Sync/test_intercore_sync_a5_functional.py index 77d37495e5..4049393f51 100644 --- a/test/samples/Sync/test_intercore_sync_a5_functional.py +++ b/test/samples/Sync/test_intercore_sync_a5_functional.py @@ -7,8 +7,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/Sync/test_intercore_sync_a5_ptoisa_vec.py b/test/samples/Sync/test_intercore_sync_a5_ptoisa_vec.py index 68919478f1..04beb6fe3a 100644 --- a/test/samples/Sync/test_intercore_sync_a5_ptoisa_vec.py +++ b/test/samples/Sync/test_intercore_sync_a5_ptoisa_vec.py @@ -7,8 +7,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/Sync/test_mem_inject_sync_basic.py b/test/samples/Sync/test_mem_inject_sync_basic.py index 01d29aa6dc..878523918f 100644 --- a/test/samples/Sync/test_mem_inject_sync_basic.py +++ b/test/samples/Sync/test_mem_inject_sync_basic.py @@ -6,7 +6,7 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, @@ -16,7 +16,7 @@ IndexType, IntegerType, ) -from mlir.dialects import func, arith, scf, pto +from ptoas.mlir.dialects import func, arith, scf, pto def _idx_const(v: int): diff --git a/test/samples/Sync/test_set_wait_unified_api.py b/test/samples/Sync/test_set_wait_unified_api.py index 1f3172ded7..5df69762d9 100644 --- a/test/samples/Sync/test_set_wait_unified_api.py +++ b/test/samples/Sync/test_set_wait_unified_api.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import arith, func, pto -from mlir.ir import IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import arith, func, pto +from ptoas.mlir.ir import IndexType def build(): diff --git a/test/samples/Sync/tmatmulk_autosync.py b/test/samples/Sync/tmatmulk_autosync.py index d89717c1fb..6a2f3756dd 100644 --- a/test/samples/Sync/tmatmulk_autosync.py +++ b/test/samples/Sync/tmatmulk_autosync.py @@ -6,13 +6,13 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, InsertionPoint, IndexType, IntegerType, F16Type, F32Type, StringAttr ) -from mlir.dialects import func, arith, scf, pto, builtin -from mlir.dialects.arith import CmpIPredicate +from ptoas.mlir.dialects import func, arith, scf, pto, builtin +from ptoas.mlir.dialects.arith import CmpIPredicate def _idx_const(v: int): diff --git a/test/samples/Sync/tmatmulk_autosync_a5.py b/test/samples/Sync/tmatmulk_autosync_a5.py index e3f3b012c9..106ebc34a5 100644 --- a/test/samples/Sync/tmatmulk_autosync_a5.py +++ b/test/samples/Sync/tmatmulk_autosync_a5.py @@ -6,13 +6,13 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import ( +from ptoas.mlir.ir import ( UnitAttr, Context, Location, InsertionPoint, IndexType, IntegerType, F16Type, F32Type, StringAttr ) -from mlir.dialects import func, arith, scf, pto, builtin -from mlir.dialects.arith import CmpIPredicate +from ptoas.mlir.dialects import func, arith, scf, pto, builtin +from ptoas.mlir.dialects.arith import CmpIPredicate def _idx_const(v: int): diff --git a/test/samples/SyncAll/syncall_binding.py b/test/samples/SyncAll/syncall_binding.py index 1ac3e1472b..578093c131 100644 --- a/test/samples/SyncAll/syncall_binding.py +++ b/test/samples/SyncAll/syncall_binding.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Attribute, Context, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Attribute, Context, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def _mode(name): diff --git a/test/samples/TInsert/tinsert.py b/test/samples/TInsert/tinsert.py index 7180061e30..dbb367c0e4 100644 --- a/test/samples/TInsert/tinsert.py +++ b/test/samples/TInsert/tinsert.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F16Type, F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F16Type, F32Type, IndexType def build(): diff --git a/test/samples/TInsert/tinsert_fp.py b/test/samples/TInsert/tinsert_fp.py index dfc99bb116..470dbf7beb 100644 --- a/test/samples/TInsert/tinsert_fp.py +++ b/test/samples/TInsert/tinsert_fp.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType, IntegerType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType, IntegerType def build(): diff --git a/test/samples/TPrefetch/tprefetch.py b/test/samples/TPrefetch/tprefetch.py index f08919bdd0..9338203f02 100644 --- a/test/samples/TPrefetch/tprefetch.py +++ b/test/samples/TPrefetch/tprefetch.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, InsertionPoint, Location, Module, IndexType, F16Type, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, InsertionPoint, Location, Module, IndexType, F16Type, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/TPrefetchAsync/tprefetch_async_binding.py b/test/samples/TPrefetchAsync/tprefetch_async_binding.py index d28bcd212a..b21f50ff83 100644 --- a/test/samples/TPrefetchAsync/tprefetch_async_binding.py +++ b/test/samples/TPrefetchAsync/tprefetch_async_binding.py @@ -6,8 +6,8 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr -from mlir.dialects import arith, func, pto +from ptoas.mlir.ir import Context, F32Type, IndexType, InsertionPoint, IntegerType, Location, Module, UnitAttr +from ptoas.mlir.dialects import arith, func, pto def build(): diff --git a/test/samples/TTri/ttri.py b/test/samples/TTri/ttri.py index 7000b10645..401e288f17 100644 --- a/test/samples/TTri/ttri.py +++ b/test/samples/TTri/ttri.py @@ -12,8 +12,8 @@ stores them into a single output buffer as two consecutive 32x32 slices. """ -from mlir.ir import Context, Location, Module, InsertionPoint, IndexType, IntegerType, UnitAttr -from mlir.dialects import func, arith, pto +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, IndexType, IntegerType, UnitAttr +from ptoas.mlir.dialects import func, arith, pto def build(): diff --git a/test/samples/TileSetGetValue/tileSetGetValue.py b/test/samples/TileSetGetValue/tileSetGetValue.py index 46ee475e89..49d5529f24 100644 --- a/test/samples/TileSetGetValue/tileSetGetValue.py +++ b/test/samples/TileSetGetValue/tileSetGetValue.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/TileSetGetValue/tile_getval_mat_invalid.py b/test/samples/TileSetGetValue/tile_getval_mat_invalid.py index 18065bd6e3..917f2c2376 100644 --- a/test/samples/TileSetGetValue/tile_getval_mat_invalid.py +++ b/test/samples/TileSetGetValue/tile_getval_mat_invalid.py @@ -10,9 +10,9 @@ Test that TGetValOp rejects MAT tile_buf (Ascend hardware does not support reading from MAT tile_buf to scalar). Verification must fail. """ -from mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, MLIRError, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Tpow/tpow.py b/test/samples/Tpow/tpow.py index e58442d06b..a648654461 100644 --- a/test/samples/Tpow/tpow.py +++ b/test/samples/Tpow/tpow.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Tpows/tpows.py b/test/samples/Tpows/tpows.py index 1c4ad7acc1..8bcc8cc00a 100644 --- a/test/samples/Tpows/tpows.py +++ b/test/samples/Tpows/tpows.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Trans/trans.py b/test/samples/Trans/trans.py index a7b6b2e5b8..9b17b31b1e 100644 --- a/test/samples/Trans/trans.py +++ b/test/samples/Trans/trans.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/Trap/trap.py b/test/samples/Trap/trap.py index b4376af13a..005b559f1d 100644 --- a/test/samples/Trap/trap.py +++ b/test/samples/Trap/trap.py @@ -7,8 +7,8 @@ # See LICENSE in the root of the software repository for the full text of the License. """Test pto.trap: generates TRAP() in C++.""" -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, pto +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, pto def build(): diff --git a/test/samples/VectorAddition/vadd_pto_ir.py b/test/samples/VectorAddition/vadd_pto_ir.py index c06bd018f9..4e43773bd8 100644 --- a/test/samples/VectorAddition/vadd_pto_ir.py +++ b/test/samples/VectorAddition/vadd_pto_ir.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): diff --git a/test/samples/VectorAddition/vadd_validshape.py b/test/samples/VectorAddition/vadd_validshape.py index 269c7604a1..3239998bb2 100644 --- a/test/samples/VectorAddition/vadd_validshape.py +++ b/test/samples/VectorAddition/vadd_validshape.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, IntegerType, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, IntegerType, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): with Context() as ctx: diff --git a/test/samples/VectorAddition/vadd_validshape_dynamic.py b/test/samples/VectorAddition/vadd_validshape_dynamic.py index 639716c890..01e6818fe8 100644 --- a/test/samples/VectorAddition/vadd_validshape_dynamic.py +++ b/test/samples/VectorAddition/vadd_validshape_dynamic.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, IntegerType, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, IntegerType, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build(): with Context() as ctx: diff --git a/test/samples/VectorAddition/vadd_validshape_hyper.py b/test/samples/VectorAddition/vadd_validshape_hyper.py index 45b1415de6..5172f5192a 100644 --- a/test/samples/VectorAddition/vadd_validshape_hyper.py +++ b/test/samples/VectorAddition/vadd_validshape_hyper.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, IntegerType, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import F32Type, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, IntegerType, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import F32Type, IndexType def build_mixed_shape(): with Context() as ctx: diff --git a/test/samples/Xor/xor.py b/test/samples/Xor/xor.py index 0d25112001..86acc61a46 100644 --- a/test/samples/Xor/xor.py +++ b/test/samples/Xor/xor.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType def build(): diff --git a/test/samples/Xors/xors.py b/test/samples/Xors/xors.py index 02f2c8c8e6..3ef70a27ea 100644 --- a/test/samples/Xors/xors.py +++ b/test/samples/Xors/xors.py @@ -6,9 +6,9 @@ # INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. # See LICENSE in the root of the software repository for the full text of the License. -from mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr -from mlir.dialects import func, arith, pto -from mlir.ir import IntegerType, IndexType, IntegerAttr +from ptoas.mlir.ir import Context, Location, Module, InsertionPoint, UnitAttr +from ptoas.mlir.dialects import func, arith, pto +from ptoas.mlir.ir import IntegerType, IndexType, IntegerAttr def build(): diff --git a/test/tilelib-st/README.md b/test/tilelib-st/README.md index c9cc31e2ef..c896108ae7 100644 --- a/test/tilelib-st/README.md +++ b/test/tilelib-st/README.md @@ -294,7 +294,7 @@ build: ```bash "$PYTHON_BIN" - <<'PY' from ptodsl import pto # noqa: F401 -from mlir.dialects import pto as _pto # noqa: F401 +from ptoas.mlir.dialects import pto as _pto # noqa: F401 print("ptodsl imports ok") PY diff --git a/tilelang-dsl/CMakeLists.txt b/tilelang-dsl/CMakeLists.txt index db11784d6f..3c00670513 100644 --- a/tilelang-dsl/CMakeLists.txt +++ b/tilelang-dsl/CMakeLists.txt @@ -29,7 +29,7 @@ add_dependencies(TileLangDSLPackage TileLangDSLPackageStage) install( DIRECTORY "${TILELANG_DSL_PACKAGE_SRC_DIR}" DESTINATION "." - COMPONENT PTOAS_Runtime + COMPONENT PTOAS_CompilerArchive PATTERN "__pycache__" EXCLUDE PATTERN "*.pyc" EXCLUDE ) @@ -37,7 +37,7 @@ install( install( DIRECTORY "${CMAKE_SOURCE_DIR}/lib/TileOps" DESTINATION "share/ptoas" - COMPONENT PTOAS_Runtime + COMPONENT PTOAS_CompilerArchive PATTERN "__pycache__" EXCLUDE PATTERN "*.pyc" EXCLUDE ) diff --git a/tilelang-dsl/python/tilelang_dsl/env_config.py b/tilelang-dsl/python/tilelang_dsl/env_config.py index 47fdd9b7ef..a6967e869d 100644 --- a/tilelang-dsl/python/tilelang_dsl/env_config.py +++ b/tilelang-dsl/python/tilelang_dsl/env_config.py @@ -24,7 +24,7 @@ def check_mlir_bindings_available() -> bool: True if mlir.ir module can be imported, False otherwise. """ try: - from mlir import ir + from ptoas.mlir import ir return True except ImportError: return False @@ -37,7 +37,7 @@ def check_pto_dialect_available() -> bool: True if mlir.dialects.pto can be imported, False otherwise. """ try: - from mlir.dialects import pto + from ptoas.mlir.dialects import pto return True except ImportError: return False @@ -83,7 +83,7 @@ def print_environment_help() -> None: print(" export PYTHONPATH=$PTOAS_BUILD_DIR/python") print() print("After setup, verify with:") - print(" python3 -c 'from mlir import ir; print(\"MLIR bindings OK\")'") + print(" python3 -c 'from ptoas.mlir import ir; print(\"MLIR bindings OK\")'") print(" python3 -c 'from pto.dialects import pto; print(\"PTO dialect OK\")'") print() print("=" * 60) diff --git a/tilelang-dsl/python/tilelang_dsl/lowering_backend.py b/tilelang-dsl/python/tilelang_dsl/lowering_backend.py index 80bdb4e972..9d1c5cd406 100644 --- a/tilelang-dsl/python/tilelang_dsl/lowering_backend.py +++ b/tilelang-dsl/python/tilelang_dsl/lowering_backend.py @@ -24,7 +24,7 @@ if TYPE_CHECKING: from .semantic import SemanticKernel - from mlir import ir as _ods_ir + from ptoas.mlir import ir as _ods_ir @dataclass(frozen=True) @@ -70,10 +70,10 @@ def _parse_text_to_module( Registers all required dialects (func, arith, scf, pto) before parsing. """ - from mlir import ir as _ods_ir - from mlir.dialects import func as _func_dialect - from mlir.dialects import arith as _arith_dialect - from mlir.dialects import scf as _scf_dialect + from ptoas.mlir import ir as _ods_ir + from ptoas.mlir.dialects import func as _func_dialect + from ptoas.mlir.dialects import arith as _arith_dialect + from ptoas.mlir.dialects import scf as _scf_dialect from pto.dialects import pto as _pto_dialect ctx = context if context is not None else _ods_ir.Context() @@ -180,7 +180,7 @@ def _check_mlir_available(self) -> bool: return self._mlir_available try: - from mlir import ir + from ptoas.mlir import ir self._mlir_available = True except ImportError: self._mlir_available = False diff --git a/tilelang-dsl/python/tilelang_dsl/pybind_renderer.py b/tilelang-dsl/python/tilelang_dsl/pybind_renderer.py index a817cec884..b0962408af 100644 --- a/tilelang-dsl/python/tilelang_dsl/pybind_renderer.py +++ b/tilelang-dsl/python/tilelang_dsl/pybind_renderer.py @@ -14,9 +14,9 @@ Phase 2 implementation: core framework with basic stmt/expr rendering. Dependencies: - - mlir.ir: MLIR Python bindings assembled by the PTOAS build - - mlir.dialects.func, arith, scf: Standard MLIR dialects - - mlir.dialects.pto: PTO dialect bindings from PTOAS build + - ptoas.mlir.ir: MLIR Python bindings assembled by the PTOAS build + - ptoas.mlir.dialects.func, arith, scf: Standard MLIR dialects + - ptoas.mlir.dialects.pto: PTO dialect bindings from PTOAS build To use this module from a build tree, ensure PYTHONPATH includes: $PTOAS_BUILD_DIR/python @@ -31,7 +31,7 @@ from typing import Any, TYPE_CHECKING if TYPE_CHECKING: - from mlir import ir as _ods_ir + from ptoas.mlir import ir as _ods_ir # Lazy imports - only load when actually needed _mlir_ir: Any = None @@ -54,10 +54,10 @@ def _ensure_mlir_bindings() -> None: return # Already loaded try: - from mlir import ir as mlir_ir - from mlir.dialects import func as func_dialect - from mlir.dialects import arith as arith_dialect - from mlir.dialects import scf as scf_dialect + from ptoas.mlir import ir as mlir_ir + from ptoas.mlir.dialects import func as func_dialect + from ptoas.mlir.dialects import arith as arith_dialect + from ptoas.mlir.dialects import scf as scf_dialect _mlir_ir = mlir_ir _func_dialect = func_dialect @@ -72,7 +72,7 @@ def _ensure_mlir_bindings() -> None: ) from exc try: - from mlir.dialects import pto as pto_dialect + from ptoas.mlir.dialects import pto as pto_dialect _pto_dialect = pto_dialect except ImportError: # PTO dialect is optional for some operations diff --git a/tilelang-dsl/tests/backend/test_e2e_pybind_backend.py b/tilelang-dsl/tests/backend/test_e2e_pybind_backend.py index a3b6088b93..5ca6630957 100644 --- a/tilelang-dsl/tests/backend/test_e2e_pybind_backend.py +++ b/tilelang-dsl/tests/backend/test_e2e_pybind_backend.py @@ -46,7 +46,7 @@ def _check_pto_dialect_available(): """Check if PTO dialect bindings are available.""" try: - from mlir.dialects import pto + from ptoas.mlir.dialects import pto return True except ImportError: return False diff --git a/tools/ptoas/CMakeLists.txt b/tools/ptoas/CMakeLists.txt index c0fb306764..18652a8ce3 100644 --- a/tools/ptoas/CMakeLists.txt +++ b/tools/ptoas/CMakeLists.txt @@ -130,6 +130,9 @@ add_mlir_python_extension(PTOASPythonCore _core PTOCAPI PTOASPythonCAPI ) +target_compile_definitions(PTOASPythonCore PRIVATE + "MLIR_PYTHON_PACKAGE_PREFIX=ptoas.mlir." +) target_include_directories(PTOASPythonCore PRIVATE "${CMAKE_SOURCE_DIR}/lib/Bindings/Python" ) @@ -137,10 +140,10 @@ mlir_python_setup_extension_rpath(PTOASPythonCore) if(APPLE) set_property(TARGET PTOASPythonCore PROPERTY INSTALL_RPATH - "@loader_path;@loader_path/../mlir/_mlir_libs") + "@loader_path;@loader_path/mlir/_mlir_libs") elseif(UNIX) set_property(TARGET PTOASPythonCore PROPERTY INSTALL_RPATH - "$ORIGIN;$ORIGIN/../mlir/_mlir_libs") + "$ORIGIN;$ORIGIN/mlir/_mlir_libs") endif() declare_mlir_python_sources(PTOASRuntimePythonSources @@ -183,7 +186,34 @@ endif() install(PROGRAMS "${PTOAS_INSTALL_WRAPPER_BINARY}" DESTINATION bin RENAME ptoas - COMPONENT PTOAS_Runtime + COMPONENT PTOAS_CompilerArchive +) + +set(PTOAS_ARCHIVE_PYTHON_VERSION_FILE + "${CMAKE_CURRENT_BINARY_DIR}/.ptoas-python-version") +file(WRITE "${PTOAS_ARCHIVE_PYTHON_VERSION_FILE}" + "${Python3_VERSION_MAJOR}.${Python3_VERSION_MINOR}\n") +install(FILES "${PTOAS_ARCHIVE_PYTHON_VERSION_FILE}" + DESTINATION "." + COMPONENT PTOAS_CompilerArchive +) + +# The standalone compiler archive is staged by installing PTOAS_Python first +# and PTOAS_CompilerArchive second into the same prefix. Generate the deploy +# script so known native entry points come from CMake targets; the script scans +# only AddMLIRPython's generated extension directory for the remaining modules. +configure_file( + "${CMAKE_SOURCE_DIR}/cmake/RelocatePTOASCompilerArchive.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/RelocatePTOASCompilerArchive.cmake.in" + @ONLY +) +file(GENERATE + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/RelocatePTOASCompilerArchive.cmake" + INPUT "${CMAKE_CURRENT_BINARY_DIR}/RelocatePTOASCompilerArchive.cmake.in" +) +install(SCRIPT + "${CMAKE_CURRENT_BINARY_DIR}/RelocatePTOASCompilerArchive.cmake" + COMPONENT PTOAS_CompilerArchive ) install( diff --git a/tools/ptoas/NativeModule.cpp b/tools/ptoas/NativeModule.cpp index e0097e0641..5a474cbd27 100644 --- a/tools/ptoas/NativeModule.cpp +++ b/tools/ptoas/NativeModule.cpp @@ -35,7 +35,7 @@ int runPTOASFromPython(const std::vector &arguments) { PYBIND11_MODULE(_core, module) { module.doc() = "PTOAS compiler and PTO dialect native bindings"; - py::module_::import("mlir.ir"); + py::module_::import("ptoas.mlir.ir"); mlir::pto::python::populatePTODialectBindings(module); module.def("main", &runPTOASFromPython, py::arg("argv")); } diff --git a/tools/ptoas/ptoas_wrapper.py b/tools/ptoas/ptoas_wrapper.py index 3b1e96ad25..0328d9733f 100644 --- a/tools/ptoas/ptoas_wrapper.py +++ b/tools/ptoas/ptoas_wrapper.py @@ -17,6 +17,7 @@ _PYTHON_ROOT_MODE = "@PTOAS_WRAPPER_PYTHON_ROOT_MODE@" _PYTHON_ROOT = Path(r"@PTOAS_WRAPPER_PYTHON_ROOT@") +_ARCHIVE_PYTHON_REQUIREMENT_FILE = ".ptoas-python-version" def _resolve_wrapper_path(argv0: str | None = None) -> Path: @@ -59,6 +60,18 @@ def _add_configured_python_root(wrapper: Path) -> Path: def main() -> None: wrapper = _resolve_wrapper_path() + requirement_file = wrapper.parent.parent / _ARCHIVE_PYTHON_REQUIREMENT_FILE + if requirement_file.is_file(): + required_python_major_minor = requirement_file.read_text( + encoding="utf-8" + ).strip() + actual = f"{sys.version_info.major}.{sys.version_info.minor}" + if actual != required_python_major_minor: + raise SystemExit( + "this ptoas compiler archive requires CPython " + f"{required_python_major_minor}, but the active interpreter is " + f"{actual} ({sys.executable})" + ) _add_configured_python_root(wrapper) from ptoas import _cli From c7f49d6e593116768a41db474732e22124021869 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Mon, 27 Jul 2026 22:24:41 +0800 Subject: [PATCH 16/19] build: fix packaging gate regressions --- packaging/ptoas-vmi/pyproject.toml | 4 ++-- test/python/compact_tile_buf_asm.py | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packaging/ptoas-vmi/pyproject.toml b/packaging/ptoas-vmi/pyproject.toml index c5de369d66..185a135e66 100644 --- a/packaging/ptoas-vmi/pyproject.toml +++ b/packaging/ptoas-vmi/pyproject.toml @@ -55,5 +55,5 @@ PTOAS_RELEASE_VERSION_OVERRIDE = { env = "PTOAS_RELEASE_VERSION_OVERRIDE", defau [tool.scikit-build.metadata.version] provider = "scikit_build_core.metadata.regex" -input = "../../docs/release/VMI_VERSION" -regex = '^(?P[0-9]+\.[0-9]+\.[0-9]+)\s*$' +input = "../../CMakeLists.txt" +regex = 'set\s*\(\s*PTOAS_VMI_VERSION\s+"(?P[0-9]+\.[0-9]+\.[0-9]+)"\s*\)' diff --git a/test/python/compact_tile_buf_asm.py b/test/python/compact_tile_buf_asm.py index cdf74879e7..f73be451f5 100644 --- a/test/python/compact_tile_buf_asm.py +++ b/test/python/compact_tile_buf_asm.py @@ -1,4 +1,11 @@ #!/usr/bin/env python3 +# Copyright (c) 2026 Huawei Technologies Co., Ltd. +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of +# CANN Open Software License Agreement Version 2.0 (the "License"). +# Please refer to the License for details. You may not use this file except in compliance with the License. +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. +# See LICENSE in the root of the software repository for the full text of the License. from ptoas.mlir.ir import Context, F32Type, MLIRError, Module from ptoas.mlir.dialects import pto From 44709de1a61f0112fb181f06976f6b004b402599 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Mon, 27 Jul 2026 23:11:25 +0800 Subject: [PATCH 17/19] build: source VMI version from package metadata --- .github/scripts/compute_vmi_version.py | 73 --------- .github/scripts/update_vmi_version.py | 84 ----------- .github/workflows/build_wheel.yml | 75 +++------- .github/workflows/build_wheel_mac.yml | 32 ++-- CMakeLists.txt | 13 +- README.md | 4 +- README_en.md | 1 + lib/Bindings/Python/CMakeLists.txt | 35 ++++- packaging/ptoas-vmi/pyproject.toml | 12 +- test/python/test_release_version_scripts.py | 156 -------------------- 10 files changed, 85 insertions(+), 400 deletions(-) delete mode 100644 .github/scripts/compute_vmi_version.py delete mode 100644 .github/scripts/update_vmi_version.py delete mode 100644 test/python/test_release_version_scripts.py diff --git a/.github/scripts/compute_vmi_version.py b/.github/scripts/compute_vmi_version.py deleted file mode 100644 index 3d37f87217..0000000000 --- a/.github/scripts/compute_vmi_version.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import argparse -import pathlib -import re -import sys - - -def parse_args() -> argparse.Namespace: - parser = argparse.ArgumentParser( - description="Compute the VMI release version from the top-level CMakeLists.txt." - ) - parser.add_argument( - "--cmake-file", - default="CMakeLists.txt", - help="Path to the top-level CMakeLists.txt file.", - ) - parser.add_argument( - "--check-tag", - help="Optional release tag to validate, e.g. vmi-v0.1.0.", - ) - return parser.parse_args() - - -def read_version(cmake_file: pathlib.Path) -> str: - content = cmake_file.read_text(encoding="utf-8") - match = re.search( - r'set\s*\(\s*PTOAS_VMI_VERSION\s+"([0-9]+\.[0-9]+\.[0-9]+)"\s*\)', - content, - ) - if not match: - raise ValueError( - f'could not find \'set(PTOAS_VMI_VERSION "x.y.z")\' in {cmake_file}' - ) - return match.group(1) - - -def normalize_tag(tag: str) -> str: - normalized = tag.strip() - if normalized.startswith("vmi-"): - normalized = normalized[len("vmi-"):] - if normalized.startswith("v"): - normalized = normalized[1:] - return normalized - - -def main() -> int: - args = parse_args() - cmake_file = pathlib.Path(args.cmake_file) - version = read_version(cmake_file) - - if args.check_tag is not None: - normalized_tag = normalize_tag(args.check_tag) - if normalized_tag != version: - print( - f"release tag '{args.check_tag}' does not match computed version '{version}'", - file=sys.stderr, - ) - return 1 - - print(version) - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/.github/scripts/update_vmi_version.py b/.github/scripts/update_vmi_version.py deleted file mode 100644 index 8c029009d6..0000000000 --- a/.github/scripts/update_vmi_version.py +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import argparse -import pathlib -import re -import sys - - -VMI_VERSION_RE = re.compile( - r'(set\s*\(\s*PTOAS_VMI_VERSION\s+")([0-9]+\.[0-9]+\.[0-9]+)("\s*\))' -) -TAG_VERSION_RE = re.compile(r"^vmi-v([0-9]+)\.([0-9]+)\.([0-9]+)$") - - -def parse_args() -> argparse.Namespace: - parser = argparse.ArgumentParser( - description="Update the VMI version in the top-level CMakeLists.txt." - ) - parser.add_argument( - "--cmake-file", - default="CMakeLists.txt", - help="Path to the top-level CMakeLists.txt file.", - ) - parser.add_argument( - "--version", - required=True, - help="Released VMI version, for example vmi-v0.1.3.", - ) - parser.add_argument( - "--next", - action="store_true", - help="Advance the resolved version by one patch step.", - ) - return parser.parse_args() - - -def normalize_version(version: str) -> str: - match = TAG_VERSION_RE.fullmatch(version.strip()) - if not match: - raise ValueError(f"invalid VMI release tag '{version}'") - return ".".join(match.groups()) - - -def bump_version(version: str) -> str: - major, minor, patch = (int(part) for part in version.split(".")) - return f"{major}.{minor}.{patch + 1}" - - -def update_version(cmake_file: pathlib.Path, version: str) -> bool: - content = cmake_file.read_text(encoding="utf-8") - updated, count = VMI_VERSION_RE.subn( - lambda match: f"{match.group(1)}{version}{match.group(3)}", - content, - count=1, - ) - if count != 1: - raise ValueError( - f'could not find \'set(PTOAS_VMI_VERSION "x.y.z")\' in {cmake_file}' - ) - if updated == content: - return False - cmake_file.write_text(updated, encoding="utf-8") - return True - - -def main() -> int: - args = parse_args() - version = normalize_version(args.version) - if args.next: - version = bump_version(version) - update_version(pathlib.Path(args.cmake_file), version) - print(version) - return 0 - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/.github/workflows/build_wheel.yml b/.github/workflows/build_wheel.yml index a047da35d6..1ffafa50cc 100644 --- a/.github/workflows/build_wheel.yml +++ b/.github/workflows/build_wheel.yml @@ -75,25 +75,37 @@ jobs: echo "PY_PATH=/opt/python/$PY_VER" >> $GITHUB_ENV echo "/opt/python/$PY_VER/bin" >> $GITHUB_PATH - - name: Compute PTOAS CLI version + - name: Install system dependencies + run: | + dnf install -y ninja-build cmake git ccache gcc-c++ lld zip binutils patchelf chrpath + dnf clean all + + - name: Install Python dependencies run: | + # LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x + # (see pybind11 static_assert on def_property + keep_alive). + pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' auditwheel + + - name: Resolve PTOAS distribution version + run: | + VMI_PROJECT_METADATA="$(cd packaging/ptoas-vmi && python -m scikit_build_core.build project-table)" + VMI_PROJECT_VERSION="$(printf '%s\n' "${VMI_PROJECT_METADATA}" | python -c 'import json, sys; print(json.load(sys.stdin)["version"])')" if [ "${GITHUB_EVENT_NAME}" = "release" ]; then case "${GITHUB_REF_NAME}" in vmi-v*) - EXPECTED_RELEASE_VERSION="$(${PY_PATH}/bin/python .github/scripts/compute_vmi_version.py \ - --check-tag "${GITHUB_REF_NAME}")" + EXPECTED_RELEASE_VERSION="${VMI_PROJECT_VERSION}" PTOAS_VERSION="${GITHUB_REF_NAME#vmi-v}" PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}" PTOAS_PYTHON_PACKAGE_NAME="ptoas-vmi" ;; ptoas-v*) - EXPECTED_RELEASE_VERSION="$(${PY_PATH}/bin/python .github/scripts/compute_ptoas_version.py --mode release)" + EXPECTED_RELEASE_VERSION="$(python .github/scripts/compute_ptoas_version.py --mode release)" PTOAS_VERSION="${GITHUB_REF_NAME#ptoas-v}" PTOAS_CLI_VERSION="${PTOAS_VERSION}" PTOAS_PYTHON_PACKAGE_NAME="ptoas" ;; v*) - EXPECTED_RELEASE_VERSION="$(${PY_PATH}/bin/python .github/scripts/compute_ptoas_version.py --mode release)" + EXPECTED_RELEASE_VERSION="$(python .github/scripts/compute_ptoas_version.py --mode release)" PTOAS_VERSION="${GITHUB_REF_NAME#v}" PTOAS_CLI_VERSION="${PTOAS_VERSION}" PTOAS_PYTHON_PACKAGE_NAME="ptoas" @@ -104,19 +116,19 @@ jobs: ;; esac if [ "${PTOAS_VERSION}" != "${EXPECTED_RELEASE_VERSION}" ]; then - echo "release tag '${GITHUB_REF_NAME}' does not match computed version '${EXPECTED_RELEASE_VERSION}'" >&2 + echo "release tag '${GITHUB_REF_NAME}' does not match project version '${EXPECTED_RELEASE_VERSION}'" >&2 exit 1 fi elif [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ] && [ "${{ inputs.release_kind }}" = "vmi" ]; then - PTOAS_VERSION="$(${PY_PATH}/bin/python .github/scripts/compute_vmi_version.py)" + PTOAS_VERSION="${VMI_PROJECT_VERSION}" PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}" PTOAS_PYTHON_PACKAGE_NAME="ptoas-vmi" elif [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then - PTOAS_VERSION="$(${PY_PATH}/bin/python .github/scripts/compute_ptoas_version.py --mode release)" + PTOAS_VERSION="$(python .github/scripts/compute_ptoas_version.py --mode release)" PTOAS_CLI_VERSION="${PTOAS_VERSION}" PTOAS_PYTHON_PACKAGE_NAME="ptoas" else - PTOAS_VERSION="$(${PY_PATH}/bin/python .github/scripts/compute_ptoas_version.py --mode dev)" + PTOAS_VERSION="$(python .github/scripts/compute_ptoas_version.py --mode dev)" PTOAS_CLI_VERSION="${PTOAS_VERSION}" PTOAS_PYTHON_PACKAGE_NAME="ptoas" fi @@ -127,17 +139,6 @@ jobs: echo "Using PTOAS wheel version: ${PTOAS_VERSION}" echo "Using PTOAS Python package name: ${PTOAS_PYTHON_PACKAGE_NAME}" - - name: Install system dependencies - run: | - dnf install -y ninja-build cmake git ccache gcc-c++ lld zip binutils patchelf chrpath - dnf clean all - - - name: Install Python dependencies - run: | - # LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x - # (see pybind11 static_assert on def_property + keep_alive). - pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' auditwheel - - name: Validate PEP 517 project metadata run: | python -m scikit_build_core.build project-table @@ -225,7 +226,6 @@ jobs: fi rm -rf "${PTO_SOURCE_DIR}/build/wheel-dist" mkdir -p "${PTO_SOURCE_DIR}/build/wheel-dist" - PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_CLI_VERSION}" \ SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}" \ python -m pip wheel "${PTOAS_WHEEL_SOURCE_DIR}" \ --no-build-isolation --no-deps \ @@ -434,36 +434,3 @@ jobs: git add CMakeLists.txt git commit -m "chore(release): bump base version to v${{ steps.bump.outputs.next_base_version }}" git push origin HEAD:${{ github.event.repository.default_branch }} - - bump_vmi_version: - name: Bump VMI version after release - if: github.event_name == 'release' && github.event.action == 'released' && startsWith(github.ref_name, 'vmi-v') - needs: upload_release_assets - runs-on: ubuntu-latest - - steps: - - name: Checkout default branch - uses: actions/checkout@v4 - with: - ref: ${{ github.event.repository.default_branch }} - - - name: Update VMI version - id: bump - run: | - next_vmi_version="$(python3 .github/scripts/update_vmi_version.py \ - --version "${GITHUB_REF_NAME}" \ - --next)" - echo "next_vmi_version=${next_vmi_version}" >> "$GITHUB_OUTPUT" - - - name: Commit version bump - run: | - if git diff --quiet -- CMakeLists.txt; then - echo "CMakeLists.txt already matches the next VMI version." - exit 0 - fi - - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add CMakeLists.txt - git commit -m "chore(release): bump VMI version to v${{ steps.bump.outputs.next_vmi_version }}" - git push origin HEAD:${{ github.event.repository.default_branch }} diff --git a/.github/workflows/build_wheel_mac.yml b/.github/workflows/build_wheel_mac.yml index 1158508314..de79399e3f 100644 --- a/.github/workflows/build_wheel_mac.yml +++ b/.github/workflows/build_wheel_mac.yml @@ -75,13 +75,24 @@ jobs: run: | echo "PY_PATH=$(python -c 'import sys; print(sys.prefix)')" >> $GITHUB_ENV - - name: Compute PTOAS CLI version + - name: Install system dependencies + run: | + brew install ninja ccache + + - name: Install Python dependencies + run: | + # LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x + # (see pybind11 static_assert on def_property + keep_alive). + pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' delocate + + - name: Resolve PTOAS distribution version run: | + VMI_PROJECT_METADATA="$(cd packaging/ptoas-vmi && python -m scikit_build_core.build project-table)" + VMI_PROJECT_VERSION="$(printf '%s\n' "${VMI_PROJECT_METADATA}" | python -c 'import json, sys; print(json.load(sys.stdin)["version"])')" if [ "${GITHUB_EVENT_NAME}" = "release" ]; then case "${GITHUB_REF_NAME}" in vmi-v*) - EXPECTED_RELEASE_VERSION="$(python .github/scripts/compute_vmi_version.py \ - --check-tag "${GITHUB_REF_NAME}")" + EXPECTED_RELEASE_VERSION="${VMI_PROJECT_VERSION}" PTOAS_VERSION="${GITHUB_REF_NAME#vmi-v}" PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}" PTOAS_PYTHON_PACKAGE_NAME="ptoas-vmi" @@ -104,11 +115,11 @@ jobs: ;; esac if [ "${PTOAS_VERSION}" != "${EXPECTED_RELEASE_VERSION}" ]; then - echo "release tag '${GITHUB_REF_NAME}' does not match computed version '${EXPECTED_RELEASE_VERSION}'" >&2 + echo "release tag '${GITHUB_REF_NAME}' does not match project version '${EXPECTED_RELEASE_VERSION}'" >&2 exit 1 fi elif [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ] && [ "${{ inputs.release_kind }}" = "vmi" ]; then - PTOAS_VERSION="$(python .github/scripts/compute_vmi_version.py)" + PTOAS_VERSION="${VMI_PROJECT_VERSION}" PTOAS_CLI_VERSION="vmi ${PTOAS_VERSION}" PTOAS_PYTHON_PACKAGE_NAME="ptoas-vmi" elif [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then @@ -127,16 +138,6 @@ jobs: echo "Using PTOAS wheel version: ${PTOAS_VERSION}" echo "Using PTOAS Python package name: ${PTOAS_PYTHON_PACKAGE_NAME}" - - name: Install system dependencies - run: | - brew install ninja ccache - - - name: Install Python dependencies - run: | - # LLVM/MLIR Python bindings are not yet compatible with pybind11 3.x - # (see pybind11 static_assert on def_property + keep_alive). - pip install --no-cache-dir numpy 'pybind11<3' nanobind 'scikit-build-core>=0.12.2,<2' delocate - - name: Validate PEP 517 project metadata run: | python -m scikit_build_core.build project-table @@ -228,7 +229,6 @@ jobs: export _PYTHON_HOST_PLATFORM="$(python "$PTO_SOURCE_DIR/docker/get_macos_wheel_plat_name.py" "$TARGET_ARCH")" rm -rf "${PTO_SOURCE_DIR}/build/wheel-dist" mkdir -p "${PTO_SOURCE_DIR}/build/wheel-dist" - PTOAS_RELEASE_VERSION_OVERRIDE="${PTOAS_CLI_VERSION}" \ SKBUILD_BUILD_DIR="${PTO_BUILD_DIR}" \ python -m pip wheel "${PTOAS_WHEEL_SOURCE_DIR}" \ --no-build-isolation --no-deps \ diff --git a/CMakeLists.txt b/CMakeLists.txt index 46999b107a..58a3c082dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,6 @@ if((NOT DEFINED MLIR_DIR OR MLIR_DIR STREQUAL "") endif() project(ptoas VERSION 0.53) -set(PTOAS_VMI_VERSION "0.1.4") # Wheel builds carry the same Linux hardening policy as release CMake builds. # Including the cache settings here keeps the policy backend-independent. @@ -46,6 +45,11 @@ endif() set(PTOAS_RELEASE_VERSION_OVERRIDE "" CACHE STRING "Override the version printed by ptoas --version") +# scikit-build-core owns wheel metadata and supplies its resolved PEP 621 +# version here. The optional label distinguishes distributions that install the +# same CLI without making CMake a second source of package-version truth. +set(PTOAS_CLI_VERSION_LABEL "" + CACHE STRING "Optional label prepended to the packaged ptoas version") set(PTOAS_EXACT_GIT_TAG_VERSION "") if(EXISTS "${PROJECT_SOURCE_DIR}/.git") find_package(Git QUIET) @@ -68,6 +72,13 @@ set(PTOAS_CLI_VERSION "${PROJECT_VERSION}") if(PTOAS_EXACT_GIT_TAG_VERSION) set(PTOAS_CLI_VERSION "${PTOAS_EXACT_GIT_TAG_VERSION}") endif() +if(SKBUILD AND SKBUILD_PROJECT_VERSION_FULL) + set(PTOAS_CLI_VERSION "${SKBUILD_PROJECT_VERSION_FULL}") +endif() +if(PTOAS_CLI_VERSION_LABEL) + set(PTOAS_CLI_VERSION + "${PTOAS_CLI_VERSION_LABEL} ${PTOAS_CLI_VERSION}") +endif() if(PTOAS_RELEASE_VERSION_OVERRIDE) set(PTOAS_CLI_VERSION "${PTOAS_RELEASE_VERSION_OVERRIDE}") endif() diff --git a/README.md b/README.md index 64f3858ed5..e51767fea0 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,9 @@ from ptoas.mlir.dialects import pto as mlir_pto > - `ptoas-bin-*.tar.gz` 这类 compiler-only 二进制 tarball 只提供 CLI/toolchain, > **不是** PTODSL-capable Python distribution;仅解压 tarball 不能保证 > `import ptodsl` 可用。 -> - release tag 约定:`ptoas-vX.Y` 发布主工具链,`vmi-vA.B.C` 发布 VMI 文档/规范。 +> - release tag 约定:`ptoas-vX.Y` 发布主工具链,`vmi-vA.B.C` 发布 +> `ptoas-vmi` distribution。创建 VMI release tag 前,应通过发布 PR 将 +> `packaging/ptoas-vmi/pyproject.toml` 中的版本更新为相同的 `A.B.C`。 --- diff --git a/README_en.md b/README_en.md index f582003bb2..efde0e8c48 100644 --- a/README_en.md +++ b/README_en.md @@ -161,6 +161,7 @@ from ptoas.mlir.dialects import pto as mlir_pto > - The VMI release line keeps the `ptoas` CLI name; `ptoas --version` prints `ptoas vmi A.B.C`. > - The `ptoas` and `ptoas-vmi` release wheels are **mutually exclusive**. They both install the same top-level `ptoas` Python package and `ptoas` console script, so do **not** install them into the same Python environment. Mixing them will overwrite files, and uninstalling one can break the other. > - `ptoas-bin-*.tar.gz` compiler-only tarballs provide CLI/toolchain bits, not a PTODSL-capable Python distribution. +> - Release tags use `ptoas-vX.Y` for the main toolchain and `vmi-vA.B.C` for the `ptoas-vmi` distribution. Before creating a VMI release tag, update the version in `packaging/ptoas-vmi/pyproject.toml` to the matching `A.B.C` through the release PR. > - `--no-build-isolation` keeps pip from baking a temporary pybind11 path into `CMakeCache.txt`, which would break later `ninja` reconfigure runs after the temporary virtual environment is removed. If you previously ran `pip install -e .` without the flag and your build is now broken, fix the existing `CMakeCache.txt` with: diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index 0c56fef22e..6be7441b47 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -15,16 +15,15 @@ include(AddMLIRPython) add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=ptoas.mlir.") set(MLIR_BINDINGS_PYTHON_NB_DOMAIN "ptoas_mlir") -# Do not carry toolchain-injected paths, such as a Conda compiler RPATH, into -# installed Python modules. Distribution builds keep only MLIR's relative -# package RPATHs; editable builds add their external link paths below. -set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH ON) - # scikit-build-core editable installs use the external LLVM build directly. -# Keep this developer-only fallback local to the MLIR Python targets; wheel -# builds use package-relative RPATHs and let auditwheel/delocate collect LLVM. +# Wheel builds retain AddMLIRPython's package-relative RPATHs for +# auditwheel/delocate to repair. if(SKBUILD_STATE STREQUAL "editable") - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) + set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH OFF) +else() + # Do not carry toolchain-injected paths, such as a Conda compiler RPATH, + # into distribution modules. + set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH ON) endif() # This directory materializes C++ sources exported by upstream MLIR. PTOAS @@ -139,3 +138,23 @@ add_mlir_python_modules(PTOAS_Python COMMON_CAPI_LINK_LIBS PTOASPythonCAPI ) + +# AddMLIRPython deliberately resets each generated target's install RPATH to +# its package-relative layout. Append the external LLVM directory afterwards +# for editable installs, where those dependencies are not bundled into the +# Python environment. Discover the native targets by CMake type so additional +# generated MLIR extensions inherit the same contract automatically. +if(SKBUILD_STATE STREQUAL "editable") + get_filename_component(_ptoas_editable_llvm_library_dir + "${LLVM_BUILD_LIBRARY_DIR}" REALPATH) + get_property(_ptoas_python_directory_targets + DIRECTORY PROPERTY BUILDSYSTEM_TARGETS) + foreach(_ptoas_python_target IN LISTS _ptoas_python_directory_targets) + get_target_property(_ptoas_python_target_type + "${_ptoas_python_target}" TYPE) + if(_ptoas_python_target_type MATCHES "^(MODULE|SHARED)_LIBRARY$") + set_property(TARGET "${_ptoas_python_target}" APPEND PROPERTY + INSTALL_RPATH "${_ptoas_editable_llvm_library_dir}") + endif() + endforeach() +endif() diff --git a/packaging/ptoas-vmi/pyproject.toml b/packaging/ptoas-vmi/pyproject.toml index 185a135e66..d655e523ff 100644 --- a/packaging/ptoas-vmi/pyproject.toml +++ b/packaging/ptoas-vmi/pyproject.toml @@ -9,7 +9,9 @@ # The VMI distribution intentionally installs the same `ptoas` import package # and console script as the main distribution. The two wheels are mutually # exclusive; this separate static PEP 621 project supplies the distribution -# name required by package indexes without a custom build backend. +# name and version required by package indexes without a custom build backend. +# scikit-build-core forwards that version to CMake as +# `SKBUILD_PROJECT_VERSION_FULL`. [build-system] requires = ["scikit-build-core>=0.12.2,<2", "pybind11<3", "nanobind>=2.4"] @@ -17,7 +19,7 @@ build-backend = "scikit_build_core.build" [project] name = "ptoas-vmi" -dynamic = ["version"] +version = "0.1.4" description = "PTO Assembler & Optimizer with VMI support" requires-python = ">=3.10" license = "Apache-2.0" @@ -52,8 +54,4 @@ tilelang_dsl = "../../tilelang-dsl/python/tilelang_dsl" [tool.scikit-build.cmake.define] PTOAS_RELEASE_VERSION_OVERRIDE = { env = "PTOAS_RELEASE_VERSION_OVERRIDE", default = "" } - -[tool.scikit-build.metadata.version] -provider = "scikit_build_core.metadata.regex" -input = "../../CMakeLists.txt" -regex = 'set\s*\(\s*PTOAS_VMI_VERSION\s+"(?P[0-9]+\.[0-9]+\.[0-9]+)"\s*\)' +PTOAS_CLI_VERSION_LABEL = "vmi" diff --git a/test/python/test_release_version_scripts.py b/test/python/test_release_version_scripts.py deleted file mode 100644 index 235face241..0000000000 --- a/test/python/test_release_version_scripts.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2026 Huawei Technologies Co., Ltd. -# This program is free software, you can redistribute it and/or modify it under the terms and conditions of -# CANN Open Software License Agreement Version 2.0 (the "License"). -# Please refer to the License for details. You may not use this file except in compliance with the License. -# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, -# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. -# See LICENSE in the root of the software repository for the full text of the License. - -import subprocess -import sys -import tempfile -from pathlib import Path -import unittest - - -REPO_ROOT = Path(__file__).resolve().parents[2] - - -class ReleaseVersionScriptTests(unittest.TestCase): - def test_ptoas_version_script_accepts_plain_v_tag(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - cmake_file = temp_root / "CMakeLists.txt" - cmake_file.write_text("project(ptoas VERSION 0.51)\n", encoding="utf-8") - result = subprocess.run( - [ - sys.executable, - str(REPO_ROOT / ".github/scripts/compute_ptoas_version.py"), - "--cmake-file", - str(cmake_file), - "--check-tag", - "v0.51", - ], - check=True, - capture_output=True, - text=True, - ) - self.assertEqual(result.stdout.strip(), "0.51") - - def test_ptoas_version_script_accepts_ptoas_tag_prefix(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - cmake_file = temp_root / "CMakeLists.txt" - cmake_file.write_text("project(ptoas VERSION 0.51)\n", encoding="utf-8") - result = subprocess.run( - [ - sys.executable, - str(REPO_ROOT / ".github/scripts/compute_ptoas_version.py"), - "--cmake-file", - str(cmake_file), - "--check-tag", - "ptoas-v0.51", - ], - check=True, - capture_output=True, - text=True, - ) - self.assertEqual(result.stdout.strip(), "0.51") - - def test_vmi_version_script_accepts_vmi_tag_prefix(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - cmake_file = temp_root / "CMakeLists.txt" - cmake_file.write_text( - 'project(ptoas VERSION 0.51)\nset(PTOAS_VMI_VERSION "0.1.0")\n', - encoding="utf-8", - ) - result = subprocess.run( - [ - sys.executable, - str(REPO_ROOT / ".github/scripts/compute_vmi_version.py"), - "--cmake-file", - str(cmake_file), - "--check-tag", - "vmi-v0.1.0", - ], - check=True, - capture_output=True, - text=True, - ) - self.assertEqual(result.stdout.strip(), "0.1.0") - - def test_vmi_version_bump_updates_only_vmi_version(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - cmake_file = temp_root / "CMakeLists.txt" - cmake_file.write_text( - 'project(ptoas VERSION 0.51)\nset(PTOAS_VMI_VERSION "0.1.9")\n', - encoding="utf-8", - ) - result = subprocess.run( - [ - sys.executable, - str(REPO_ROOT / ".github/scripts/update_vmi_version.py"), - "--cmake-file", - str(cmake_file), - "--version", - "vmi-v0.1.9", - "--next", - ], - check=True, - capture_output=True, - text=True, - ) - self.assertEqual(result.stdout.strip(), "0.1.10") - self.assertEqual( - cmake_file.read_text(encoding="utf-8"), - 'project(ptoas VERSION 0.51)\nset(PTOAS_VMI_VERSION "0.1.10")\n', - ) - - def test_vmi_version_bump_rejects_ptoas_tag(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - cmake_file = temp_root / "CMakeLists.txt" - cmake_file.write_text( - 'project(ptoas VERSION 0.51)\nset(PTOAS_VMI_VERSION "0.1.0")\n', - encoding="utf-8", - ) - result = subprocess.run( - [ - sys.executable, - str(REPO_ROOT / ".github/scripts/update_vmi_version.py"), - "--cmake-file", - str(cmake_file), - "--version", - "v0.51", - "--next", - ], - capture_output=True, - text=True, - ) - self.assertNotEqual(result.returncode, 0) - - def test_ptoas_version_bump_rejects_vmi_tag(self): - with tempfile.TemporaryDirectory() as temp_dir: - temp_root = Path(temp_dir) - cmake_file = temp_root / "CMakeLists.txt" - cmake_file.write_text("project(ptoas VERSION 0.51)\n", encoding="utf-8") - result = subprocess.run( - [ - sys.executable, - str(REPO_ROOT / ".github/scripts/update_ptoas_base_version.py"), - "--cmake-file", - str(cmake_file), - "--version", - "vmi-v0.1.0", - ], - capture_output=True, - text=True, - ) - self.assertNotEqual(result.returncode, 0) - - -if __name__ == "__main__": - unittest.main() From a746241eaac676b043c0469235c10ac46dd8c608 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Mon, 27 Jul 2026 23:33:59 +0800 Subject: [PATCH 18/19] build: fix editable core LLVM rpath --- CMakeLists.txt | 15 +++++++++++++++ lib/Bindings/Python/CMakeLists.txt | 19 +++++-------------- tools/ptoas/CMakeLists.txt | 12 +++--------- 3 files changed, 23 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58a3c082dd..4c884667fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,6 +50,21 @@ set(PTOAS_RELEASE_VERSION_OVERRIDE "" # same CLI without making CMake a second source of package-version truth. set(PTOAS_CLI_VERSION_LABEL "" CACHE STRING "Optional label prepended to the packaged ptoas version") + +# Editable installs intentionally link against the developer's external LLVM +# build instead of bundling it. Apply that contract explicitly to every native +# Python target; generated and project-owned extensions live in different +# CMake directories and must use the same install RPATH policy. +function(ptoas_append_editable_llvm_rpath target_name) + if(NOT SKBUILD_STATE STREQUAL "editable") + return() + endif() + get_filename_component(_ptoas_editable_llvm_library_dir + "${LLVM_BUILD_LIBRARY_DIR}" REALPATH) + set_property(TARGET "${target_name}" APPEND PROPERTY + INSTALL_RPATH "${_ptoas_editable_llvm_library_dir}") +endfunction() + set(PTOAS_EXACT_GIT_TAG_VERSION "") if(EXISTS "${PROJECT_SOURCE_DIR}/.git") find_package(Git QUIET) diff --git a/lib/Bindings/Python/CMakeLists.txt b/lib/Bindings/Python/CMakeLists.txt index 6be7441b47..04ed2a183b 100644 --- a/lib/Bindings/Python/CMakeLists.txt +++ b/lib/Bindings/Python/CMakeLists.txt @@ -15,16 +15,10 @@ include(AddMLIRPython) add_compile_definitions("MLIR_PYTHON_PACKAGE_PREFIX=ptoas.mlir.") set(MLIR_BINDINGS_PYTHON_NB_DOMAIN "ptoas_mlir") -# scikit-build-core editable installs use the external LLVM build directly. -# Wheel builds retain AddMLIRPython's package-relative RPATHs for -# auditwheel/delocate to repair. -if(SKBUILD_STATE STREQUAL "editable") - set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH OFF) -else() - # Do not carry toolchain-injected paths, such as a Conda compiler RPATH, - # into distribution modules. - set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH ON) -endif() +# Do not carry toolchain-injected paths, such as a Conda compiler RPATH, into +# installed Python modules. Wheel builds retain AddMLIRPython's package-relative +# RPATHs for repair; editable builds append only the external LLVM directory. +set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH ON) # This directory materializes C++ sources exported by upstream MLIR. PTOAS # keeps -Werror enabled globally, but upstream sources are not part of the @@ -145,16 +139,13 @@ add_mlir_python_modules(PTOAS_Python # Python environment. Discover the native targets by CMake type so additional # generated MLIR extensions inherit the same contract automatically. if(SKBUILD_STATE STREQUAL "editable") - get_filename_component(_ptoas_editable_llvm_library_dir - "${LLVM_BUILD_LIBRARY_DIR}" REALPATH) get_property(_ptoas_python_directory_targets DIRECTORY PROPERTY BUILDSYSTEM_TARGETS) foreach(_ptoas_python_target IN LISTS _ptoas_python_directory_targets) get_target_property(_ptoas_python_target_type "${_ptoas_python_target}" TYPE) if(_ptoas_python_target_type MATCHES "^(MODULE|SHARED)_LIBRARY$") - set_property(TARGET "${_ptoas_python_target}" APPEND PROPERTY - INSTALL_RPATH "${_ptoas_editable_llvm_library_dir}") + ptoas_append_editable_llvm_rpath("${_ptoas_python_target}") endif() endforeach() endif() diff --git a/tools/ptoas/CMakeLists.txt b/tools/ptoas/CMakeLists.txt index 18652a8ce3..7a8575f854 100644 --- a/tools/ptoas/CMakeLists.txt +++ b/tools/ptoas/CMakeLists.txt @@ -7,17 +7,10 @@ # See LICENSE in the root of the software repository for the full text of the License. # Do not carry toolchain-injected paths, such as a Conda compiler RPATH, into -# installed Python modules. Distribution builds keep only MLIR's relative -# package RPATHs; editable builds add their external link paths below. +# installed Python modules. Distribution builds keep only package-relative +# RPATHs; editable builds add the external LLVM directory explicitly below. set(CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH ON) -# scikit-build-core editable installs use the external LLVM build directly. -# Keep this developer-only fallback local to the PTOAS Python extension; wheel -# builds use package-relative RPATHs and let auditwheel/delocate collect LLVM. -if(SKBUILD_STATE STREQUAL "editable") - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) -endif() - set(PTOAS_RUNTIME_SOURCES ptoas.cpp driver.cpp @@ -145,6 +138,7 @@ elseif(UNIX) set_property(TARGET PTOASPythonCore PROPERTY INSTALL_RPATH "$ORIGIN;$ORIGIN/mlir/_mlir_libs") endif() +ptoas_append_editable_llvm_rpath(PTOASPythonCore) declare_mlir_python_sources(PTOASRuntimePythonSources ROOT_DIR "${CMAKE_SOURCE_DIR}/ptodsl/ptoas" From fa9b6291195ff88b8c71101cb5b28522f20583e7 Mon Sep 17 00:00:00 2001 From: mouliangyu Date: Tue, 28 Jul 2026 00:36:56 +0800 Subject: [PATCH 19/19] ci: validate macOS common CAPI wheel payload --- docker/validate_wheel_payload.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docker/validate_wheel_payload.py b/docker/validate_wheel_payload.py index a96f677fa0..0b67082e39 100644 --- a/docker/validate_wheel_payload.py +++ b/docker/validate_wheel_payload.py @@ -23,7 +23,6 @@ "ptoas/_runtime/share/ptoas/TileOps/__init__.py", "ptoas/mlir/ir.py", "ptoas/mlir/dialects/pto.py", - "ptoas/mlir/_mlir_libs/libPTOASPythonCAPI.so", } FORBIDDEN_FILES = { "ptoas/_runtime/bin/ptoas", @@ -35,6 +34,10 @@ for suffix in importlib.machinery.EXTENSION_SUFFIXES } MLIR_NATIVE_MODULE_PREFIX = "ptoas/mlir/_mlir_libs/" +COMMON_CAPI_LIBRARY_PATHS = { + f"{MLIR_NATIVE_MODULE_PREFIX}libPTOASPythonCAPI{suffix}" + for suffix in (".so", ".dylib") +} MLIR_NATIVE_MODULE_PATHS = { f"{MLIR_NATIVE_MODULE_PREFIX}_mlir{suffix}" for suffix in importlib.machinery.EXTENSION_SUFFIXES @@ -112,6 +115,13 @@ def validate_wheel_payload(wheel: Path) -> None: f"found {mlir_native_modules}" ) + common_capi_libraries = sorted(COMMON_CAPI_LIBRARY_PATHS & names) + if len(common_capi_libraries) != 1: + raise SystemExit( + "wheel must contain exactly one PTOAS MLIR common CAPI library, " + f"found {common_capi_libraries}" + ) + site_initializers = sorted(SITE_INITIALIZER_PATHS & names) if len(site_initializers) != 1: raise SystemExit(