1*523fa7a6SAndroid Build Coastguard Worker# Copyright (c) Meta Platforms, Inc. and affiliates. 2*523fa7a6SAndroid Build Coastguard Worker# All rights reserved. 3*523fa7a6SAndroid Build Coastguard Worker# 4*523fa7a6SAndroid Build Coastguard Worker# This source code is licensed under the BSD-style license found in the 5*523fa7a6SAndroid Build Coastguard Worker# LICENSE file in the root directory of this source tree. 6*523fa7a6SAndroid Build Coastguard Worker 7*523fa7a6SAndroid Build Coastguard Worker 8*523fa7a6SAndroid Build Coastguard Workerimport glob 9*523fa7a6SAndroid Build Coastguard Workerimport os 10*523fa7a6SAndroid Build Coastguard Workerimport platform 11*523fa7a6SAndroid Build Coastguard Workerimport re 12*523fa7a6SAndroid Build Coastguard Workerimport shutil 13*523fa7a6SAndroid Build Coastguard Workerimport subprocess 14*523fa7a6SAndroid Build Coastguard Workerimport sys 15*523fa7a6SAndroid Build Coastguard Worker 16*523fa7a6SAndroid Build Coastguard Worker# Before doing anything, cd to the directory containing this script. 17*523fa7a6SAndroid Build Coastguard Workeros.chdir(os.path.dirname(os.path.abspath(__file__))) 18*523fa7a6SAndroid Build Coastguard Worker 19*523fa7a6SAndroid Build Coastguard Worker 20*523fa7a6SAndroid Build Coastguard Workerdef python_is_compatible(): 21*523fa7a6SAndroid Build Coastguard Worker # Scrape the version range from pyproject.toml, which should be in the current directory. 22*523fa7a6SAndroid Build Coastguard Worker version_specifier = None 23*523fa7a6SAndroid Build Coastguard Worker with open("pyproject.toml", "r") as file: 24*523fa7a6SAndroid Build Coastguard Worker for line in file: 25*523fa7a6SAndroid Build Coastguard Worker if line.startswith("requires-python"): 26*523fa7a6SAndroid Build Coastguard Worker match = re.search(r'"([^"]*)"', line) 27*523fa7a6SAndroid Build Coastguard Worker if match: 28*523fa7a6SAndroid Build Coastguard Worker version_specifier = match.group(1) 29*523fa7a6SAndroid Build Coastguard Worker break 30*523fa7a6SAndroid Build Coastguard Worker 31*523fa7a6SAndroid Build Coastguard Worker if not version_specifier: 32*523fa7a6SAndroid Build Coastguard Worker print( 33*523fa7a6SAndroid Build Coastguard Worker "WARNING: Skipping python version check: version range not found", 34*523fa7a6SAndroid Build Coastguard Worker file=sys.stderr, 35*523fa7a6SAndroid Build Coastguard Worker ) 36*523fa7a6SAndroid Build Coastguard Worker return False 37*523fa7a6SAndroid Build Coastguard Worker 38*523fa7a6SAndroid Build Coastguard Worker # Install the packaging module if necessary. 39*523fa7a6SAndroid Build Coastguard Worker try: 40*523fa7a6SAndroid Build Coastguard Worker import packaging 41*523fa7a6SAndroid Build Coastguard Worker except ImportError: 42*523fa7a6SAndroid Build Coastguard Worker subprocess.run( 43*523fa7a6SAndroid Build Coastguard Worker [sys.executable, "-m", "pip", "install", "packaging"], check=True 44*523fa7a6SAndroid Build Coastguard Worker ) 45*523fa7a6SAndroid Build Coastguard Worker # Compare the current python version to the range in version_specifier. Exits 46*523fa7a6SAndroid Build Coastguard Worker # with status 1 if the version is not compatible, or with status 0 if the 47*523fa7a6SAndroid Build Coastguard Worker # version is compatible or the logic itself fails. 48*523fa7a6SAndroid Build Coastguard Worker try: 49*523fa7a6SAndroid Build Coastguard Worker import packaging.specifiers 50*523fa7a6SAndroid Build Coastguard Worker import packaging.version 51*523fa7a6SAndroid Build Coastguard Worker 52*523fa7a6SAndroid Build Coastguard Worker python_version = packaging.version.parse(platform.python_version()) 53*523fa7a6SAndroid Build Coastguard Worker version_range = packaging.specifiers.SpecifierSet(version_specifier) 54*523fa7a6SAndroid Build Coastguard Worker if python_version not in version_range: 55*523fa7a6SAndroid Build Coastguard Worker print( 56*523fa7a6SAndroid Build Coastguard Worker f'ERROR: ExecuTorch does not support python version {python_version}: must satisfy "{version_specifier}"', 57*523fa7a6SAndroid Build Coastguard Worker file=sys.stderr, 58*523fa7a6SAndroid Build Coastguard Worker ) 59*523fa7a6SAndroid Build Coastguard Worker return False 60*523fa7a6SAndroid Build Coastguard Worker except Exception as e: 61*523fa7a6SAndroid Build Coastguard Worker print(f"WARNING: Skipping python version check: {e}", file=sys.stderr) 62*523fa7a6SAndroid Build Coastguard Worker return True 63*523fa7a6SAndroid Build Coastguard Worker 64*523fa7a6SAndroid Build Coastguard Worker 65*523fa7a6SAndroid Build Coastguard Workerif not python_is_compatible(): 66*523fa7a6SAndroid Build Coastguard Worker sys.exit(1) 67*523fa7a6SAndroid Build Coastguard Worker 68*523fa7a6SAndroid Build Coastguard Worker# Parse options. 69*523fa7a6SAndroid Build Coastguard WorkerEXECUTORCH_BUILD_PYBIND = "OFF" 70*523fa7a6SAndroid Build Coastguard WorkerCMAKE_ARGS = os.getenv("CMAKE_ARGS", "") 71*523fa7a6SAndroid Build Coastguard WorkerCMAKE_BUILD_ARGS = os.getenv("CMAKE_BUILD_ARGS", "") 72*523fa7a6SAndroid Build Coastguard WorkerUSE_PYTORCH_NIGHTLY = True 73*523fa7a6SAndroid Build Coastguard Worker 74*523fa7a6SAndroid Build Coastguard Workerfor arg in sys.argv[1:]: 75*523fa7a6SAndroid Build Coastguard Worker if arg == "--pybind": 76*523fa7a6SAndroid Build Coastguard Worker EXECUTORCH_BUILD_PYBIND = "ON" 77*523fa7a6SAndroid Build Coastguard Worker elif arg in ["coreml", "mps", "xnnpack"]: 78*523fa7a6SAndroid Build Coastguard Worker if EXECUTORCH_BUILD_PYBIND == "ON": 79*523fa7a6SAndroid Build Coastguard Worker arg_upper = arg.upper() 80*523fa7a6SAndroid Build Coastguard Worker CMAKE_ARGS += f" -DEXECUTORCH_BUILD_{arg_upper}=ON" 81*523fa7a6SAndroid Build Coastguard Worker else: 82*523fa7a6SAndroid Build Coastguard Worker print(f"Error: {arg} must follow --pybind") 83*523fa7a6SAndroid Build Coastguard Worker sys.exit(1) 84*523fa7a6SAndroid Build Coastguard Worker elif arg == "--clean": 85*523fa7a6SAndroid Build Coastguard Worker print("Cleaning build artifacts...") 86*523fa7a6SAndroid Build Coastguard Worker print("Cleaning pip-out/...") 87*523fa7a6SAndroid Build Coastguard Worker shutil.rmtree("pip-out/", ignore_errors=True) 88*523fa7a6SAndroid Build Coastguard Worker dirs = glob.glob("cmake-out*/") 89*523fa7a6SAndroid Build Coastguard Worker for d in dirs: 90*523fa7a6SAndroid Build Coastguard Worker print(f"Cleaning {d}...") 91*523fa7a6SAndroid Build Coastguard Worker shutil.rmtree(d, ignore_errors=True) 92*523fa7a6SAndroid Build Coastguard Worker print("Done cleaning build artifacts.") 93*523fa7a6SAndroid Build Coastguard Worker sys.exit(0) 94*523fa7a6SAndroid Build Coastguard Worker elif arg == "--use-pt-pinned-commit": 95*523fa7a6SAndroid Build Coastguard Worker # This option is used in CI to make sure that PyTorch build from the pinned commit 96*523fa7a6SAndroid Build Coastguard Worker # is used instead of nightly. CI jobs wouldn't be able to catch regression from the 97*523fa7a6SAndroid Build Coastguard Worker # latest PT commit otherwise 98*523fa7a6SAndroid Build Coastguard Worker USE_PYTORCH_NIGHTLY = False 99*523fa7a6SAndroid Build Coastguard Worker else: 100*523fa7a6SAndroid Build Coastguard Worker print(f"Error: Unknown option {arg}") 101*523fa7a6SAndroid Build Coastguard Worker sys.exit(1) 102*523fa7a6SAndroid Build Coastguard Worker 103*523fa7a6SAndroid Build Coastguard Worker# Use ClangCL on Windows. 104*523fa7a6SAndroid Build Coastguard Worker# ClangCL is an alias to Clang that configures it to work in an MSVC-compatible 105*523fa7a6SAndroid Build Coastguard Worker# mode. Using it on Windows to avoid compiler compatibility issues for MSVC. 106*523fa7a6SAndroid Build Coastguard Workerif os.name == "nt": 107*523fa7a6SAndroid Build Coastguard Worker CMAKE_ARGS += " -T ClangCL" 108*523fa7a6SAndroid Build Coastguard Worker 109*523fa7a6SAndroid Build Coastguard Worker# Since ExecuTorch often uses main-branch features of pytorch, only the nightly 110*523fa7a6SAndroid Build Coastguard Worker# pip versions will have the required features. 111*523fa7a6SAndroid Build Coastguard Worker# 112*523fa7a6SAndroid Build Coastguard Worker# NOTE: If a newly-fetched version of the executorch repo changes the value of 113*523fa7a6SAndroid Build Coastguard Worker# NIGHTLY_VERSION, you should re-run this script to install the necessary 114*523fa7a6SAndroid Build Coastguard Worker# package versions. 115*523fa7a6SAndroid Build Coastguard WorkerNIGHTLY_VERSION = "dev20241112" 116*523fa7a6SAndroid Build Coastguard Worker 117*523fa7a6SAndroid Build Coastguard Worker# The pip repository that hosts nightly torch packages. 118*523fa7a6SAndroid Build Coastguard WorkerTORCH_URL = "https://download.pytorch.org/whl/test/cpu" 119*523fa7a6SAndroid Build Coastguard Worker 120*523fa7a6SAndroid Build Coastguard Worker# pip packages needed by exir. 121*523fa7a6SAndroid Build Coastguard WorkerEXIR_REQUIREMENTS = [ 122*523fa7a6SAndroid Build Coastguard Worker # Setting USE_PYTORCH_NIGHTLY to false to test the pinned PyTorch commit. Note 123*523fa7a6SAndroid Build Coastguard Worker # that we don't need to set any version number there because they have already 124*523fa7a6SAndroid Build Coastguard Worker # been installed on CI before this step, so pip won't reinstall them 125*523fa7a6SAndroid Build Coastguard Worker f"torch==2.6.0.{NIGHTLY_VERSION}" if USE_PYTORCH_NIGHTLY else "torch", 126*523fa7a6SAndroid Build Coastguard Worker ( 127*523fa7a6SAndroid Build Coastguard Worker f"torchvision==0.20.0.{NIGHTLY_VERSION}" 128*523fa7a6SAndroid Build Coastguard Worker if USE_PYTORCH_NIGHTLY 129*523fa7a6SAndroid Build Coastguard Worker else "torchvision" 130*523fa7a6SAndroid Build Coastguard Worker ), # For testing. 131*523fa7a6SAndroid Build Coastguard Worker "typing-extensions", 132*523fa7a6SAndroid Build Coastguard Worker] 133*523fa7a6SAndroid Build Coastguard Worker 134*523fa7a6SAndroid Build Coastguard Worker# pip packages needed to run examples. 135*523fa7a6SAndroid Build Coastguard Worker# TODO: Make each example publish its own requirements.txt 136*523fa7a6SAndroid Build Coastguard WorkerEXAMPLES_REQUIREMENTS = [ 137*523fa7a6SAndroid Build Coastguard Worker "timm==1.0.7", 138*523fa7a6SAndroid Build Coastguard Worker f"torchaudio==2.5.0.{NIGHTLY_VERSION}" if USE_PYTORCH_NIGHTLY else "torchaudio", 139*523fa7a6SAndroid Build Coastguard Worker "torchsr==1.0.4", 140*523fa7a6SAndroid Build Coastguard Worker "transformers==4.46.1", 141*523fa7a6SAndroid Build Coastguard Worker] 142*523fa7a6SAndroid Build Coastguard Worker 143*523fa7a6SAndroid Build Coastguard Worker# pip packages needed for development. 144*523fa7a6SAndroid Build Coastguard WorkerDEVEL_REQUIREMENTS = [ 145*523fa7a6SAndroid Build Coastguard Worker "cmake", # For building binary targets. 146*523fa7a6SAndroid Build Coastguard Worker "pip>=23", # For building the pip package. 147*523fa7a6SAndroid Build Coastguard Worker "pyyaml", # Imported by the kernel codegen tools. 148*523fa7a6SAndroid Build Coastguard Worker "setuptools>=63", # For building the pip package. 149*523fa7a6SAndroid Build Coastguard Worker "tomli", # Imported by extract_sources.py when using python < 3.11. 150*523fa7a6SAndroid Build Coastguard Worker "wheel", # For building the pip package archive. 151*523fa7a6SAndroid Build Coastguard Worker "zstd", # Imported by resolve_buck.py. 152*523fa7a6SAndroid Build Coastguard Worker] 153*523fa7a6SAndroid Build Coastguard Worker 154*523fa7a6SAndroid Build Coastguard Worker# Assemble the list of requirements to actually install. 155*523fa7a6SAndroid Build Coastguard Worker# TODO: Add options for reducing the number of requirements. 156*523fa7a6SAndroid Build Coastguard WorkerREQUIREMENTS_TO_INSTALL = EXIR_REQUIREMENTS + DEVEL_REQUIREMENTS + EXAMPLES_REQUIREMENTS 157*523fa7a6SAndroid Build Coastguard Worker 158*523fa7a6SAndroid Build Coastguard Worker# Install the requirements. `--extra-index-url` tells pip to look for package 159*523fa7a6SAndroid Build Coastguard Worker# versions on the provided URL if they aren't available on the default URL. 160*523fa7a6SAndroid Build Coastguard Workersubprocess.run( 161*523fa7a6SAndroid Build Coastguard Worker [ 162*523fa7a6SAndroid Build Coastguard Worker sys.executable, 163*523fa7a6SAndroid Build Coastguard Worker "-m", 164*523fa7a6SAndroid Build Coastguard Worker "pip", 165*523fa7a6SAndroid Build Coastguard Worker "install", 166*523fa7a6SAndroid Build Coastguard Worker *REQUIREMENTS_TO_INSTALL, 167*523fa7a6SAndroid Build Coastguard Worker "--extra-index-url", 168*523fa7a6SAndroid Build Coastguard Worker TORCH_URL, 169*523fa7a6SAndroid Build Coastguard Worker ], 170*523fa7a6SAndroid Build Coastguard Worker check=True, 171*523fa7a6SAndroid Build Coastguard Worker) 172*523fa7a6SAndroid Build Coastguard Worker 173*523fa7a6SAndroid Build Coastguard Worker# 174*523fa7a6SAndroid Build Coastguard Worker# Install executorch pip package. This also makes `flatc` available on the path. 175*523fa7a6SAndroid Build Coastguard Worker# The --extra-index-url may be necessary if pyproject.toml has a dependency on a 176*523fa7a6SAndroid Build Coastguard Worker# pre-release or nightly version of a torch package. 177*523fa7a6SAndroid Build Coastguard Worker# 178*523fa7a6SAndroid Build Coastguard Worker 179*523fa7a6SAndroid Build Coastguard Worker# Set environment variables 180*523fa7a6SAndroid Build Coastguard Workeros.environ["EXECUTORCH_BUILD_PYBIND"] = EXECUTORCH_BUILD_PYBIND 181*523fa7a6SAndroid Build Coastguard Workeros.environ["CMAKE_ARGS"] = CMAKE_ARGS 182*523fa7a6SAndroid Build Coastguard Workeros.environ["CMAKE_BUILD_ARGS"] = CMAKE_BUILD_ARGS 183*523fa7a6SAndroid Build Coastguard Worker 184*523fa7a6SAndroid Build Coastguard Worker# Run the pip install command 185*523fa7a6SAndroid Build Coastguard Workersubprocess.run( 186*523fa7a6SAndroid Build Coastguard Worker [ 187*523fa7a6SAndroid Build Coastguard Worker sys.executable, 188*523fa7a6SAndroid Build Coastguard Worker "-m", 189*523fa7a6SAndroid Build Coastguard Worker "pip", 190*523fa7a6SAndroid Build Coastguard Worker "install", 191*523fa7a6SAndroid Build Coastguard Worker ".", 192*523fa7a6SAndroid Build Coastguard Worker "--no-build-isolation", 193*523fa7a6SAndroid Build Coastguard Worker "-v", 194*523fa7a6SAndroid Build Coastguard Worker "--extra-index-url", 195*523fa7a6SAndroid Build Coastguard Worker TORCH_URL, 196*523fa7a6SAndroid Build Coastguard Worker ], 197*523fa7a6SAndroid Build Coastguard Worker check=True, 198*523fa7a6SAndroid Build Coastguard Worker) 199