Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 1 | # Copyright 2021 The IREE Authors |
| 2 | # |
| 3 | # Licensed under the Apache License v2.0 with LLVM Exceptions. |
| 4 | # See https://llvm.org/LICENSE.txt for license information. |
| 5 | # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | |
Scott Todd | 57b9239 | 2023-08-10 20:13:49 -0700 | [diff] [blame] | 7 | # Build/install the iree-compiler python package. |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 8 | # Note that this includes a relatively large build of LLVM (~2400 C++ files) |
| 9 | # and can take a considerable amount of time, especially with defaults. |
| 10 | # To install: |
| 11 | # pip install . |
| 12 | # To build a wheel: |
| 13 | # pip wheel . |
| 14 | # |
| 15 | # It is recommended to build with Ninja and ccache. To do so, set environment |
| 16 | # variables by prefixing to above invocations: |
| 17 | # CMAKE_C_COMPILER_LAUNCHER=ccache CMAKE_CXX_COMPILER_LAUNCHER=ccache |
| 18 | # |
| 19 | # On CIs, it is often advantageous to re-use/control the CMake build directory. |
| 20 | # This can be set with the IREE_COMPILER_API_CMAKE_BUILD_DIR env var. |
| 21 | # |
| 22 | # Select CMake options are available from environment variables: |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 23 | # IREE_ENABLE_CPUINFO |
| 24 | |
| 25 | from gettext import install |
| 26 | import json |
| 27 | from multiprocessing.spawn import prepare |
| 28 | import os |
| 29 | import platform |
| 30 | import re |
| 31 | import shutil |
| 32 | import subprocess |
| 33 | import sys |
| 34 | import sysconfig |
| 35 | |
| 36 | from distutils.command.build import build as _build |
| 37 | from setuptools import find_namespace_packages, setup, Extension |
| 38 | from setuptools.command.build_ext import build_ext as _build_ext |
| 39 | from setuptools.command.build_py import build_py as _build_py |
| 40 | |
| 41 | |
| 42 | def check_pip_version(): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 43 | from packaging import version |
| 44 | |
| 45 | # Pip versions < 22.0.3 default to out of tree builds, which is quite |
| 46 | # incompatible with what we do (and has other issues). Pip >= 22.0.4 |
| 47 | # removed this option entirely and are only in-tree builds. Since the |
| 48 | # old behavior can silently produce unworking installations, we aggressively |
| 49 | # suppress it. |
| 50 | try: |
| 51 | import pip |
| 52 | except ModuleNotFoundError: |
| 53 | # If pip not installed, we are obviously not trying to package via pip. |
| 54 | pass |
| 55 | else: |
| 56 | if version.parse(pip.__version__) < version.parse("21.3"): |
| 57 | print("ERROR: pip version >= 21.3 required") |
| 58 | print("Upgrade: pip install pip --upgrade") |
| 59 | sys.exit(2) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 60 | |
| 61 | |
| 62 | check_pip_version() |
| 63 | |
| 64 | # This file can be run directly from the source tree or it can be CMake |
| 65 | # configured so it can run from the build tree with an already existing |
| 66 | # build tree. We detect the difference based on whether the following |
| 67 | # are expanded by CMake. |
| 68 | CONFIGURED_SOURCE_DIR = "@IREE_SOURCE_DIR@" |
| 69 | CONFIGURED_BINARY_DIR = "@IREE_BINARY_DIR@" |
| 70 | |
| 71 | IREE_SOURCE_DIR = None |
| 72 | IREE_BINARY_DIR = None |
| 73 | |
| 74 | # We must do the intermediate installation to a fixed location that agrees |
| 75 | # between what we pass to setup() and cmake. So hard-code it here. |
| 76 | # Note that setup() needs a relative path (to the setup.py file). |
Scott Todd | 31738a8 | 2023-08-08 18:00:38 -0700 | [diff] [blame] | 77 | # We keep the path short ('i' instead of 'install') for platforms like Windows |
| 78 | # that have file length limits. |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 79 | SETUPPY_DIR = os.path.realpath(os.path.dirname(__file__)) |
Scott Todd | 31738a8 | 2023-08-08 18:00:38 -0700 | [diff] [blame] | 80 | CMAKE_INSTALL_DIR_REL = os.path.join("build", "i") |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 81 | CMAKE_INSTALL_DIR_ABS = os.path.join(SETUPPY_DIR, CMAKE_INSTALL_DIR_REL) |
| 82 | |
| 83 | IS_CONFIGURED = CONFIGURED_SOURCE_DIR[0] != "@" |
| 84 | if IS_CONFIGURED: |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 85 | IREE_SOURCE_DIR = CONFIGURED_SOURCE_DIR |
| 86 | IREE_BINARY_DIR = CONFIGURED_BINARY_DIR |
| 87 | print( |
| 88 | f"Running setup.py from build tree: " |
| 89 | f"SOURCE_DIR = {IREE_SOURCE_DIR} " |
| 90 | f"BINARY_DIR = {IREE_BINARY_DIR}", |
| 91 | file=sys.stderr, |
| 92 | ) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 93 | else: |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 94 | IREE_SOURCE_DIR = os.path.join(SETUPPY_DIR, "..") |
| 95 | IREE_BINARY_DIR = os.getenv("IREE_COMPILER_API_CMAKE_BUILD_DIR") |
| 96 | if not IREE_BINARY_DIR: |
| 97 | # Note that setuptools always builds into a "build" directory that |
| 98 | # is a sibling of setup.py, so we just colonize a sub-directory of that |
| 99 | # by default. |
Scott Todd | 31738a8 | 2023-08-08 18:00:38 -0700 | [diff] [blame] | 100 | IREE_BINARY_DIR = os.path.join(SETUPPY_DIR, "build", "b") |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 101 | print( |
| 102 | f"Running setup.py from source tree: " |
| 103 | f"SOURCE_DIR = {IREE_SOURCE_DIR} " |
| 104 | f"BINARY_DIR = {IREE_BINARY_DIR}", |
| 105 | file=sys.stderr, |
| 106 | ) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 107 | |
| 108 | # Setup and get version information. |
| 109 | VERSION_INFO_FILE = os.path.join(IREE_SOURCE_DIR, "version_info.json") |
| 110 | |
| 111 | |
| 112 | def load_version_info(): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 113 | with open(VERSION_INFO_FILE, "rt") as f: |
| 114 | return json.load(f) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 115 | |
| 116 | |
| 117 | def find_git_versions(): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 118 | revisions = {} |
| 119 | try: |
| 120 | revisions["IREE"] = ( |
| 121 | subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=IREE_SOURCE_DIR) |
| 122 | .decode("utf-8") |
| 123 | .strip() |
| 124 | ) |
| 125 | except subprocess.SubprocessError as e: |
| 126 | print(f"ERROR: Could not get IREE revision: {e}", file=sys.stderr) |
| 127 | return revisions |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 128 | |
| 129 | |
| 130 | def find_git_submodule_revision(submodule_path): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 131 | try: |
| 132 | data = ( |
| 133 | subprocess.check_output( |
| 134 | ["git", "ls-tree", "HEAD", submodule_path], cwd=IREE_SOURCE_DIR |
| 135 | ) |
| 136 | .decode("utf-8") |
| 137 | .strip() |
| 138 | ) |
| 139 | columns = re.split("\\s+", data) |
| 140 | return columns[2] |
| 141 | except Exception as e: |
| 142 | print( |
| 143 | f"ERROR: Could not get submodule revision for {submodule_path}" f" ({e})", |
| 144 | file=sys.stderr, |
| 145 | ) |
| 146 | return "" |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 147 | |
| 148 | |
| 149 | try: |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 150 | version_info = load_version_info() |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 151 | except FileNotFoundError: |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 152 | print("version_info.json not found. Using defaults", file=sys.stderr) |
| 153 | version_info = {} |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 154 | git_versions = find_git_versions() |
| 155 | |
| 156 | PACKAGE_SUFFIX = version_info.get("package-suffix") or "" |
| 157 | PACKAGE_VERSION = version_info.get("package-version") |
| 158 | if not PACKAGE_VERSION: |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 159 | PACKAGE_VERSION = f"0.dev0+{git_versions.get('IREE') or '0'}" |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 160 | |
| 161 | |
Stella Laurenzo | 585d387 | 2023-04-20 20:54:11 -0700 | [diff] [blame] | 162 | def get_cmake_version_info_args(): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 163 | version_info_args = [ |
| 164 | f"-DIREE_RELEASE_VERSION:STRING={PACKAGE_VERSION}", |
| 165 | f"-DIREE_RELEASE_REVISION:STRING={git_versions.get('IREE') or '0'}", |
| 166 | ] |
| 167 | if version_info: |
| 168 | version_info_args.append("-DIREE_EMBEDDED_RELEASE_INFO=ON") |
| 169 | return version_info_args |
Stella Laurenzo | 585d387 | 2023-04-20 20:54:11 -0700 | [diff] [blame] | 170 | |
| 171 | |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 172 | def maybe_nuke_cmake_cache(): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 173 | # From run to run under pip, we can end up with different paths to ninja, |
| 174 | # which isn't great and will confuse cmake. Detect if the location of |
| 175 | # ninja changes and force a cache flush. |
| 176 | ninja_path = "" |
| 177 | try: |
| 178 | import ninja |
| 179 | except ModuleNotFoundError: |
| 180 | pass |
| 181 | else: |
| 182 | ninja_path = ninja.__file__ |
| 183 | expected_stamp_contents = f"{sys.executable}\n{ninja_path}" |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 184 | |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 185 | # In order to speed things up on CI and not rebuild everything, we nuke |
| 186 | # the CMakeCache.txt file if the path to the Python interpreter changed. |
| 187 | # Ideally, CMake would let us reconfigure this dynamically... but it does |
| 188 | # not (and gets very confused). |
| 189 | # We only do this because the compiler is so expensive to build and very |
| 190 | # little of it depends on the Python version. This is a hack. |
| 191 | PYTHON_STAMP_FILE = os.path.join(IREE_BINARY_DIR, "python_stamp.txt") |
| 192 | if os.path.exists(PYTHON_STAMP_FILE): |
| 193 | with open(PYTHON_STAMP_FILE, "rt") as f: |
| 194 | actual_stamp_contents = f.read() |
| 195 | if actual_stamp_contents == expected_stamp_contents: |
| 196 | # All good. |
| 197 | return |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 198 | |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 199 | # Mismatch or not found. Clean it. |
| 200 | cmake_cache_file = os.path.join(IREE_BINARY_DIR, "CMakeCache.txt") |
| 201 | if os.path.exists(cmake_cache_file): |
| 202 | print("Removing CMakeCache.txt because Python version changed", file=sys.stderr) |
| 203 | os.remove(cmake_cache_file) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 204 | |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 205 | # Also clean the install directory. This avoids version specific pileups |
| 206 | # of binaries that can occur with repeated builds against different |
| 207 | # Python versions. |
| 208 | if os.path.exists(CMAKE_INSTALL_DIR_ABS): |
| 209 | print( |
| 210 | f"Removing CMake install dir because Python version changed: " |
| 211 | f"{CMAKE_INSTALL_DIR_ABS}", |
| 212 | file=sys.stderr, |
| 213 | ) |
| 214 | shutil.rmtree(CMAKE_INSTALL_DIR_ABS) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 215 | |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 216 | # And write. |
| 217 | with open(PYTHON_STAMP_FILE, "wt") as f: |
| 218 | f.write(expected_stamp_contents) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 219 | |
| 220 | |
maxbartel | c7351e1 | 2024-09-12 11:30:26 +0200 | [diff] [blame] | 221 | def get_env_cmake_option(name: str, default_value: str = "OFF") -> str: |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 222 | svalue = os.getenv(name) |
| 223 | if not svalue: |
maxbartel | c7351e1 | 2024-09-12 11:30:26 +0200 | [diff] [blame] | 224 | svalue = default_value |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 225 | return f"-D{name}={svalue}" |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 226 | |
| 227 | |
| 228 | def add_env_cmake_setting(args, env_name: str, cmake_name=None) -> str: |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 229 | svalue = os.getenv(env_name) |
| 230 | if svalue is not None: |
| 231 | if not cmake_name: |
| 232 | cmake_name = env_name |
| 233 | args.append(f"-D{cmake_name}={svalue}") |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 234 | |
| 235 | |
| 236 | def prepare_installation(): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 237 | version_py_content = generate_version_py() |
| 238 | print(f"Generating version.py:\n{version_py_content}", file=sys.stderr) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 239 | |
Stella Laurenzo | c003beb | 2023-07-19 13:19:14 -0700 | [diff] [blame] | 240 | cfg = os.getenv("IREE_CMAKE_BUILD_TYPE", "Release") |
| 241 | strip_install = cfg == "Release" |
| 242 | |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 243 | if not IS_CONFIGURED: |
| 244 | # Build from source tree. |
| 245 | subprocess.check_call(["cmake", "--version"]) |
| 246 | os.makedirs(IREE_BINARY_DIR, exist_ok=True) |
| 247 | maybe_nuke_cmake_cache() |
| 248 | print(f"CMake build dir: {IREE_BINARY_DIR}", file=sys.stderr) |
| 249 | print(f"CMake install dir: {CMAKE_INSTALL_DIR_ABS}", file=sys.stderr) |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 250 | cmake_args = [ |
| 251 | "-GNinja", |
| 252 | "--log-level=VERBOSE", |
| 253 | "-DIREE_BUILD_PYTHON_BINDINGS=ON", |
Scott Todd | 57b9239 | 2023-08-10 20:13:49 -0700 | [diff] [blame] | 254 | "-DIREE_BUILD_SAMPLES=OFF", |
| 255 | "-DIREE_BUILD_TESTS=OFF", |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 256 | # Disable .so.0 style symlinking. Python wheels don't preserve links, |
| 257 | # so this ~doubles the binary size if not disabled (yikes!). |
| 258 | "-DCMAKE_PLATFORM_NO_VERSIONED_SONAME=ON", |
| 259 | "-DPython3_EXECUTABLE={}".format(sys.executable), |
| 260 | "-DCMAKE_BUILD_TYPE={}".format(cfg), |
Ben Vanik | eeda5ca | 2024-02-27 14:18:32 -0800 | [diff] [blame] | 261 | # TODO(scotttodd): include IREE_TARGET_BACKEND_WEBGPU_SPIRV here (and in env) |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 262 | get_env_cmake_option("IREE_ENABLE_CPUINFO", "ON"), |
maxbartel | f2bf602 | 2024-09-04 17:53:38 +0200 | [diff] [blame] | 263 | get_env_cmake_option("IREE_TARGET_BACKEND_ROCM", "OFF"), |
| 264 | get_env_cmake_option("IREE_TARGET_BACKEND_CUDA", "OFF"), |
Stanley Winata | ebdb098 | 2023-10-15 18:21:47 -0700 | [diff] [blame] | 265 | get_env_cmake_option("IREE_ENABLE_LLD", "OFF"), |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 266 | ] |
| 267 | cmake_args.extend(get_cmake_version_info_args()) |
| 268 | |
| 269 | # These usually flow through the environment, but we add them explicitly |
| 270 | # so that they show clearly in logs (getting them wrong can have bad |
| 271 | # outcomes). |
| 272 | add_env_cmake_setting(cmake_args, "CMAKE_OSX_ARCHITECTURES") |
| 273 | add_env_cmake_setting( |
| 274 | cmake_args, "MACOSX_DEPLOYMENT_TARGET", "CMAKE_OSX_DEPLOYMENT_TARGET" |
| 275 | ) |
| 276 | |
| 277 | # Only do a from-scratch configure if not already configured. |
| 278 | cmake_cache_file = os.path.join(IREE_BINARY_DIR, "CMakeCache.txt") |
| 279 | if not os.path.exists(cmake_cache_file): |
| 280 | print(f"Configuring with: {cmake_args}", file=sys.stderr) |
| 281 | subprocess.check_call( |
| 282 | ["cmake", IREE_SOURCE_DIR] + cmake_args, cwd=IREE_BINARY_DIR |
| 283 | ) |
| 284 | else: |
| 285 | print(f"Not re-configuring (already configured)", file=sys.stderr) |
| 286 | |
| 287 | # Build. |
Stella Laurenzo | c003beb | 2023-07-19 13:19:14 -0700 | [diff] [blame] | 288 | subprocess.check_call(["cmake", "--build", "."], cwd=IREE_BINARY_DIR) |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 289 | print("Build complete.", file=sys.stderr) |
| 290 | |
| 291 | # Perform installation on the entire compiler/ tree as this is guaranteed |
| 292 | # to have all of our installation targets. |
Stella Laurenzo | c003beb | 2023-07-19 13:19:14 -0700 | [diff] [blame] | 293 | install_subdirectory = os.path.join(IREE_BINARY_DIR) |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 294 | install_args = [ |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 295 | f"-DCMAKE_INSTALL_PREFIX={CMAKE_INSTALL_DIR_ABS}", |
| 296 | "-P", |
| 297 | os.path.join(install_subdirectory, "cmake_install.cmake"), |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 298 | ] |
Stella Laurenzo | c003beb | 2023-07-19 13:19:14 -0700 | [diff] [blame] | 299 | if strip_install: |
| 300 | install_args.append("-DCMAKE_INSTALL_DO_STRIP=ON") |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 301 | print(f"Installing with: {install_args}", file=sys.stderr) |
| 302 | subprocess.check_call(["cmake"] + install_args, cwd=install_subdirectory) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 303 | |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 304 | # Write version.py directly into install dir. |
| 305 | version_py_file = os.path.join( |
| 306 | CMAKE_INSTALL_DIR_ABS, |
| 307 | "python_packages", |
| 308 | "iree_compiler", |
| 309 | "iree", |
| 310 | "compiler", |
| 311 | "version.py", |
| 312 | ) |
| 313 | os.makedirs(os.path.dirname(version_py_file), exist_ok=True) |
| 314 | with open(version_py_file, "wt") as f: |
| 315 | f.write(version_py_content) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 316 | |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 317 | print(f"Installation prepared: {CMAKE_INSTALL_DIR_ABS}", file=sys.stderr) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 318 | |
| 319 | |
| 320 | class CMakeBuildPy(_build_py): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 321 | def run(self): |
| 322 | # It is critical that the target directory contain all built extensions, |
| 323 | # or else setuptools will helpfully compile an empty binary for us |
| 324 | # (this is the **worst** possible thing it could do). We just copy |
| 325 | # everything. What's another hundred megs between friends? |
| 326 | target_dir = os.path.abspath(self.build_lib) |
| 327 | print(f"Building in target dir: {target_dir}", file=sys.stderr) |
| 328 | os.makedirs(target_dir, exist_ok=True) |
| 329 | print("Copying install to target.", file=sys.stderr) |
| 330 | if os.path.exists(target_dir): |
| 331 | shutil.rmtree(target_dir) |
| 332 | shutil.copytree( |
| 333 | os.path.join(CMAKE_INSTALL_DIR_ABS, "python_packages", "iree_compiler"), |
| 334 | target_dir, |
| 335 | symlinks=False, |
| 336 | ) |
| 337 | print("Target populated.", file=sys.stderr) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 338 | |
| 339 | |
| 340 | class CustomBuild(_build): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 341 | def run(self): |
| 342 | self.run_command("build_py") |
| 343 | self.run_command("build_ext") |
| 344 | self.run_command("build_scripts") |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 345 | |
| 346 | |
| 347 | class CMakeExtension(Extension): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 348 | def __init__(self, name, sourcedir=""): |
| 349 | Extension.__init__(self, name, sources=[]) |
| 350 | self.sourcedir = os.path.abspath(sourcedir) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 351 | |
| 352 | |
| 353 | class NoopBuildExtension(_build_ext): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 354 | def __init__(self, *args, **kwargs): |
| 355 | assert False |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 356 | |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 357 | def build_extension(self, ext): |
| 358 | pass |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 359 | |
| 360 | |
| 361 | def generate_version_py(): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 362 | return f"""# Auto-generated version info. |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 363 | PACKAGE_SUFFIX = "{PACKAGE_SUFFIX}" |
| 364 | VERSION = "{PACKAGE_VERSION}" |
| 365 | REVISIONS = {json.dumps(git_versions)} |
| 366 | """ |
| 367 | |
| 368 | |
| 369 | def find_git_versions(): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 370 | revisions = {} |
| 371 | try: |
| 372 | revisions["IREE"] = ( |
| 373 | subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=IREE_SOURCE_DIR) |
| 374 | .decode("utf-8") |
| 375 | .strip() |
| 376 | ) |
| 377 | except subprocess.SubprocessError as e: |
| 378 | print(f"ERROR: Could not get IREE revision: {e}", file=sys.stderr) |
| 379 | revisions["LLVM_PROJECT"] = find_git_submodule_revision("third_party/llvm-project") |
| 380 | revisions["STABLEHLO"] = find_git_submodule_revision("third_party/stablehlo") |
| 381 | return revisions |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 382 | |
| 383 | |
| 384 | def find_git_submodule_revision(submodule_path): |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 385 | try: |
| 386 | data = ( |
| 387 | subprocess.check_output( |
| 388 | ["git", "ls-tree", "HEAD", submodule_path], cwd=IREE_SOURCE_DIR |
| 389 | ) |
| 390 | .decode("utf-8") |
| 391 | .strip() |
| 392 | ) |
| 393 | columns = re.split("\\s+", data) |
| 394 | return columns[2] |
| 395 | except Exception as e: |
| 396 | print( |
| 397 | f"ERROR: Could not get submodule revision for {submodule_path}" f" ({e})", |
| 398 | file=sys.stderr, |
| 399 | ) |
| 400 | return "" |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 401 | |
| 402 | |
| 403 | prepare_installation() |
| 404 | |
Jakub Kuderski | be24f02 | 2023-06-21 14:44:18 -0400 | [diff] [blame] | 405 | packages = find_namespace_packages( |
| 406 | where=os.path.join(CMAKE_INSTALL_DIR_ABS, "python_packages", "iree_compiler"), |
| 407 | include=[ |
| 408 | "iree.compiler", |
| 409 | "iree.compiler.*", |
| 410 | ], |
| 411 | ) |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 412 | print(f"Found compiler packages: {packages}") |
| 413 | |
Stella Laurenzo | c003beb | 2023-07-19 13:19:14 -0700 | [diff] [blame] | 414 | custom_package_suffix = os.getenv("IREE_COMPILER_CUSTOM_PACKAGE_SUFFIX", "") |
| 415 | custom_package_prefix = os.getenv("IREE_COMPILER_CUSTOM_PACKAGE_PREFIX", "") |
| 416 | |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 417 | setup( |
Stella Laurenzo | c003beb | 2023-07-19 13:19:14 -0700 | [diff] [blame] | 418 | name=f"{custom_package_prefix}iree-compiler{custom_package_suffix}{PACKAGE_SUFFIX}", |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 419 | version=f"{PACKAGE_VERSION}", |
| 420 | author="IREE Authors", |
Marius Brehler | 45132f5 | 2024-09-05 00:21:41 +0200 | [diff] [blame] | 421 | author_email="iree-technical-discussion@lists.lfaidata.foundation", |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 422 | description="IREE Compiler API", |
| 423 | long_description="", |
| 424 | license="Apache-2.0", |
| 425 | classifiers=[ |
| 426 | "Development Status :: 3 - Alpha", |
| 427 | "License :: OSI Approved :: Apache Software License", |
Scott Todd | fe9cb17 | 2022-12-08 09:17:52 -0800 | [diff] [blame] | 428 | "Programming Language :: Python :: 3", |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 429 | "Programming Language :: Python :: 3.9", |
Scott Todd | fe9cb17 | 2022-12-08 09:17:52 -0800 | [diff] [blame] | 430 | "Programming Language :: Python :: 3.10", |
powderluv | ed10551 | 2023-02-11 23:01:43 -0800 | [diff] [blame] | 431 | "Programming Language :: Python :: 3.11", |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 432 | ], |
| 433 | ext_modules=[ |
| 434 | CMakeExtension("iree.compiler._mlir_libs._mlir"), |
| 435 | CMakeExtension("iree.compiler._mlir_libs._ireeDialects"), |
Stella Laurenzo | 7ed278e | 2022-11-25 10:36:57 -0800 | [diff] [blame] | 436 | # TODO: MHLO has been broken for a while so disabling. If re-enabling, |
| 437 | # it also needs to be enabled on the build side. |
| 438 | # CMakeExtension("iree.compiler._mlir_libs._mlirHlo"), |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 439 | CMakeExtension("iree.compiler._mlir_libs._mlirLinalgPasses"), |
Dmitry Babokin | 360dc3e | 2024-05-01 11:42:25 -0700 | [diff] [blame] | 440 | CMakeExtension("iree.compiler._mlir_libs._mlirGPUPasses"), |
Stella Laurenzo | bf475bb | 2023-05-11 08:41:23 -0700 | [diff] [blame] | 441 | CMakeExtension("iree.compiler._mlir_libs._site_initialize_0"), |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 442 | ], |
| 443 | cmdclass={ |
| 444 | "build": CustomBuild, |
| 445 | "built_ext": NoopBuildExtension, |
| 446 | "build_py": CMakeBuildPy, |
| 447 | }, |
| 448 | zip_safe=False, |
| 449 | package_dir={ |
| 450 | # Note: Must be relative path, so we line this up with the absolute |
| 451 | # path built above. Note that this must exist prior to the call. |
| 452 | "": f"{CMAKE_INSTALL_DIR_REL}/python_packages/iree_compiler", |
| 453 | }, |
| 454 | packages=packages, |
| 455 | entry_points={ |
| 456 | "console_scripts": [ |
Scott Todd | 84d0789 | 2024-09-06 08:55:14 -0700 | [diff] [blame] | 457 | "iree-compile = iree.compiler.tools.scripts.iree_compile.__main__:main", |
Stella Laurenzo | 7b7ffeb | 2023-12-20 19:03:59 -0800 | [diff] [blame] | 458 | "iree-import-onnx = iree.compiler.tools.import_onnx.__main__:_cli_main", |
Stella Laurenzo | ecc49f6 | 2023-08-10 23:37:22 -0700 | [diff] [blame] | 459 | "iree-ir-tool = iree.compiler.tools.ir_tool.__main__:_cli_main", |
Stella Laurenzo | 1b12b5e | 2024-08-26 16:49:48 -0700 | [diff] [blame] | 460 | "iree-opt = iree.compiler.tools.scripts.iree_opt.__main__:main", |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 461 | ], |
| 462 | }, |
| 463 | install_requires=[ |
| 464 | "numpy", |
Lei Zhang | ac418d1 | 2024-06-20 19:24:08 -0700 | [diff] [blame] | 465 | "sympy", |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 466 | ], |
Stella Laurenzo | 7b7ffeb | 2023-12-20 19:03:59 -0800 | [diff] [blame] | 467 | extras_require={ |
| 468 | "onnx": [ |
Scott Todd | 29e70ab | 2024-05-28 12:48:55 -0700 | [diff] [blame] | 469 | "onnx>=1.16.0", |
Stella Laurenzo | 7b7ffeb | 2023-12-20 19:03:59 -0800 | [diff] [blame] | 470 | ], |
| 471 | }, |
Stella Laurenzo | 41a2ceb | 2022-04-29 12:49:36 -0700 | [diff] [blame] | 472 | ) |