xref: /aosp_15_r20/external/executorch/install_requirements.py (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
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