Spaces:
Runtime error
Runtime error
# Copyright (c) Facebook, Inc. and its affiliates. All rights reserved. | |
# | |
# This source code is licensed under the BSD license found in the | |
# LICENSE file in the root directory of this source tree. | |
import argparse | |
import os | |
import shutil | |
import subprocess | |
from dataclasses import dataclass | |
from pathlib import Path | |
from typing import List | |
THIS_PATH = Path(__file__).resolve() | |
SOURCE_ROOT_DIR = THIS_PATH.parents[1] | |
class Build: | |
""" | |
Represents one configuration of a build, i.e. | |
a set of versions of dependent libraries. | |
Members: | |
conda_always_copy: avoids hard linking which can behave weirdly. | |
conda_debug: get added information about package search | |
conda_dirty: see intermediate files after build | |
build_inside_tree: output in build/ not ../build | |
is_release: whether this is an official versioned release | |
""" | |
python_version: str | |
pytorch_version: str | |
pytorch_channel: str | |
cuda_version: str | |
cuda_dep_runtime: str | |
conda_always_copy: bool = True | |
conda_debug: bool = False | |
conda_dirty: bool = False | |
build_inside_tree: bool = False | |
def _set_env_for_build(self) -> None: | |
""" | |
NOTE: Variables set here won't be visible in `setup.py` | |
UNLESS they are also specified in meta.yaml | |
""" | |
assert ( | |
"BUILD_VERSION" in os.environ | |
), "BUILD_VERSION must be set as env variable" | |
tag = subprocess.check_output( | |
["git", "rev-parse", "--short", "HEAD"], text=True | |
).strip() | |
os.environ["GIT_TAG"] = tag | |
os.environ["PYTORCH_VERSION"] = self.pytorch_version | |
os.environ["CU_VERSION"] = self.cuda_version | |
os.environ["SOURCE_ROOT_DIR"] = str(SOURCE_ROOT_DIR) | |
# At build time, the same major/minor (otherwise we might get a CPU pytorch ...) | |
cuda_constraint_build = "=" + ".".join(self.cuda_version.split(".")[:2]) | |
pytorch_version_tuple = tuple( | |
int(v) for v in self.pytorch_version.split(".")[:2] | |
) | |
if pytorch_version_tuple < (1, 13): | |
os.environ[ | |
"CONDA_CUDA_CONSTRAINT_BUILD" | |
] = f"cudatoolkit{cuda_constraint_build}" | |
os.environ[ | |
"CONDA_CUDA_CONSTRAINT_RUN" | |
] = f"cudatoolkit{self.cuda_dep_runtime}" | |
else: | |
os.environ[ | |
"CONDA_CUDA_CONSTRAINT_BUILD" | |
] = f"pytorch-cuda{cuda_constraint_build}" | |
os.environ[ | |
"CONDA_CUDA_CONSTRAINT_RUN" | |
] = f"pytorch-cuda{self.cuda_dep_runtime}" | |
if self.conda_always_copy: | |
os.environ["CONDA_ALWAYS_COPY"] = "true" | |
def _get_build_args(self) -> List[str]: | |
args = [ | |
"conda", | |
"build", | |
"-c", | |
self.pytorch_channel, | |
"-c", | |
"nvidia", | |
"--python", | |
self.python_version, | |
"--no-anaconda-upload", | |
] | |
if self.conda_debug: | |
args += ["--debug"] | |
if self.conda_dirty: | |
args += ["--dirty"] | |
if not self.build_inside_tree: | |
args += ["--croot", "../build"] | |
return args + ["packaging/xformers"] | |
def do_build(self) -> None: | |
self._set_env_for_build() | |
args = self._get_build_args() | |
print(args) | |
subprocess.check_call(args) | |
def move_artifacts_to_store(self, store_pytorch_package: bool) -> None: | |
""" | |
Run after a build to move the built package, and, if using nightly, the | |
used PyTorch package, to a location where they will be recognized | |
as build artifacts. | |
""" | |
print("moving artifacts") | |
assert not self.build_inside_tree | |
artifacts = Path("packages") | |
artifacts.mkdir(exist_ok=True) | |
for filename in Path("../build/linux-64").resolve().glob("*.tar.bz2"): | |
print("moving", filename, "to", artifacts) | |
shutil.move(filename, artifacts) | |
if store_pytorch_package: | |
for filename in Path("/opt/conda/pkgs").glob("pytorch-[12].*.tar.bz2"): | |
print("moving", filename, "to", artifacts) | |
shutil.move(filename, artifacts) | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser(description="Build the conda package.") | |
parser.add_argument( | |
"--python", metavar="3.X", required=True, help="python version e.g. 3.10" | |
) | |
parser.add_argument( | |
"--cuda-dep-runtime", metavar="1X.Y", required=True, help="eg '>=11.7,<11.9" | |
) | |
parser.add_argument( | |
"--cuda", metavar="1X.Y", required=True, help="cuda version e.g. 11.3" | |
) | |
parser.add_argument( | |
"--pytorch", metavar="1.Y.Z", required=True, help="PyTorch version e.g. 1.11.0" | |
) | |
parser.add_argument( | |
"--build-inside-tree", | |
action="store_true", | |
help="Build in build/ instead of ../build/", | |
) | |
parser.add_argument( | |
"--store", | |
action="store_true", | |
help="position artifact to store", | |
) | |
parser.add_argument( | |
"--store-pytorch-package", | |
action="store_true", | |
help="position artifact to store", | |
) | |
parser.add_argument( | |
"--pytorch-channel", default="pytorch", help="Use 'pytorch-nightly' for nightly" | |
) | |
args = parser.parse_args() | |
pkg = Build( | |
pytorch_channel=args.pytorch_channel, | |
python_version=args.python, | |
pytorch_version=args.pytorch, | |
cuda_version=args.cuda, | |
build_inside_tree=args.build_inside_tree, | |
cuda_dep_runtime=args.cuda_dep_runtime, | |
) | |
pkg.do_build() | |
pkg.move_artifacts_to_store(store_pytorch_package=args.store_pytorch_package) | |
# python packaging/conda/build_conda.py --cuda 11.6 --python 3.10 --pytorch 1.12.1 | |
# python packaging/conda/build_conda.py --cuda 11.3 --python 3.9 --pytorch 1.12.1 # <= the dino one | |
# python packaging/conda/build_conda.py --cuda 11.6 --python 3.10 --pytorch 1.11.0 | |
# Note this does the build outside the root of the tree. | |
# TODO: | |
# - Make a local conda package cache available inside docker | |
# - do we need builds for both _GLIBCXX_USE_CXX11_ABI values? | |
# - how to prevent some cpu only builds of pytorch from being discovered? | |