pytorch
/
setup.py
1408 строк · 48.5 Кб
1# Welcome to the PyTorch setup.py.
2#
3# Environment variables you are probably interested in:
4#
5# DEBUG
6# build with -O0 and -g (debug symbols)
7#
8# REL_WITH_DEB_INFO
9# build with optimizations and -g (debug symbols)
10#
11# USE_CUSTOM_DEBINFO="path/to/file1.cpp;path/to/file2.cpp"
12# build with debug info only for specified files
13#
14# MAX_JOBS
15# maximum number of compile jobs we should use to compile your code
16#
17# USE_CUDA=0
18# disables CUDA build
19#
20# CFLAGS
21# flags to apply to both C and C++ files to be compiled (a quirk of setup.py
22# which we have faithfully adhered to in our build system is that CFLAGS
23# also applies to C++ files (unless CXXFLAGS is set), in contrast to the
24# default behavior of autogoo and cmake build systems.)
25#
26# CC
27# the C/C++ compiler to use
28#
29# Environment variables for feature toggles:
30#
31# DEBUG_CUDA=1
32# if used in conjunction with DEBUG or REL_WITH_DEB_INFO, will also
33# build CUDA kernels with -lineinfo --source-in-ptx. Note that
34# on CUDA 12 this may cause nvcc to OOM, so this is disabled by default.
35
36# USE_CUDNN=0
37# disables the cuDNN build
38#
39# USE_CUSPARSELT=0
40# disables the cuSPARSELt build
41#
42# USE_FBGEMM=0
43# disables the FBGEMM build
44#
45# USE_KINETO=0
46# disables usage of libkineto library for profiling
47#
48# USE_NUMPY=0
49# disables the NumPy build
50#
51# BUILD_TEST=0
52# disables the test build
53#
54# USE_MKLDNN=0
55# disables use of MKLDNN
56#
57# USE_MKLDNN_ACL
58# enables use of Compute Library backend for MKLDNN on Arm;
59# USE_MKLDNN must be explicitly enabled.
60#
61# MKLDNN_CPU_RUNTIME
62# MKL-DNN threading mode: TBB or OMP (default)
63#
64# USE_STATIC_MKL
65# Prefer to link with MKL statically - Unix only
66# USE_ITT=0
67# disable use of Intel(R) VTune Profiler's ITT functionality
68#
69# USE_NNPACK=0
70# disables NNPACK build
71#
72# USE_QNNPACK=0
73# disables QNNPACK build (quantized 8-bit operators)
74#
75# USE_DISTRIBUTED=0
76# disables distributed (c10d, gloo, mpi, etc.) build
77#
78# USE_TENSORPIPE=0
79# disables distributed Tensorpipe backend build
80#
81# USE_GLOO=0
82# disables distributed gloo backend build
83#
84# USE_MPI=0
85# disables distributed MPI backend build
86#
87# USE_SYSTEM_NCCL=0
88# disables use of system-wide nccl (we will use our submoduled
89# copy in third_party/nccl)
90#
91# BUILD_CAFFE2_OPS=0
92# disable Caffe2 operators build
93#
94# BUILD_CAFFE2=0
95# disable Caffe2 build
96#
97# USE_IBVERBS
98# toggle features related to distributed support
99#
100# USE_OPENCV
101# enables use of OpenCV for additional operators
102#
103# USE_OPENMP=0
104# disables use of OpenMP for parallelization
105#
106# USE_FFMPEG
107# enables use of ffmpeg for additional operators
108#
109# USE_FLASH_ATTENTION=0
110# disables building flash attention for scaled dot product attention
111#
112# USE_MEM_EFF_ATTENTION=0
113# disables building memory efficient attention for scaled dot product attention
114#
115# USE_LEVELDB
116# enables use of LevelDB for storage
117#
118# USE_LMDB
119# enables use of LMDB for storage
120#
121# BUILD_BINARY
122# enables the additional binaries/ build
123#
124# ATEN_AVX512_256=TRUE
125# ATen AVX2 kernels can use 32 ymm registers, instead of the default 16.
126# This option can be used if AVX512 doesn't perform well on a machine.
127# The FBGEMM library also uses AVX512_256 kernels on Xeon D processors,
128# but it also has some (optimized) assembly code.
129#
130# PYTORCH_BUILD_VERSION
131# PYTORCH_BUILD_NUMBER
132# specify the version of PyTorch, rather than the hard-coded version
133# in this file; used when we're building binaries for distribution
134#
135# TORCH_CUDA_ARCH_LIST
136# specify which CUDA architectures to build for.
137# ie `TORCH_CUDA_ARCH_LIST="6.0;7.0"`
138# These are not CUDA versions, instead, they specify what
139# classes of NVIDIA hardware we should generate PTX for.
140#
141# PYTORCH_ROCM_ARCH
142# specify which AMD GPU targets to build for.
143# ie `PYTORCH_ROCM_ARCH="gfx900;gfx906"`
144#
145# ONNX_NAMESPACE
146# specify a namespace for ONNX built here rather than the hard-coded
147# one in this file; needed to build with other frameworks that share ONNX.
148#
149# BLAS
150# BLAS to be used by Caffe2. Can be MKL, Eigen, ATLAS, FlexiBLAS, or OpenBLAS. If set
151# then the build will fail if the requested BLAS is not found, otherwise
152# the BLAS will be chosen based on what is found on your system.
153#
154# MKL_THREADING
155# MKL threading mode: SEQ, TBB or OMP (default)
156#
157# USE_REDIS
158# Whether to use Redis for distributed workflows (Linux only)
159#
160# USE_ZSTD
161# Enables use of ZSTD, if the libraries are found
162#
163# USE_ROCM_KERNEL_ASSERT=1
164# Enable kernel assert in ROCm platform
165#
166# Environment variables we respect (these environment variables are
167# conventional and are often understood/set by other software.)
168#
169# CUDA_HOME (Linux/OS X)
170# CUDA_PATH (Windows)
171# specify where CUDA is installed; usually /usr/local/cuda or
172# /usr/local/cuda-x.y
173# CUDAHOSTCXX
174# specify a different compiler than the system one to use as the CUDA
175# host compiler for nvcc.
176#
177# CUDA_NVCC_EXECUTABLE
178# Specify a NVCC to use. This is used in our CI to point to a cached nvcc
179#
180# CUDNN_LIB_DIR
181# CUDNN_INCLUDE_DIR
182# CUDNN_LIBRARY
183# specify where cuDNN is installed
184#
185# MIOPEN_LIB_DIR
186# MIOPEN_INCLUDE_DIR
187# MIOPEN_LIBRARY
188# specify where MIOpen is installed
189#
190# NCCL_ROOT
191# NCCL_LIB_DIR
192# NCCL_INCLUDE_DIR
193# specify where nccl is installed
194#
195# NVTOOLSEXT_PATH (Windows only)
196# specify where nvtoolsext is installed
197#
198# ACL_ROOT_DIR
199# specify where Compute Library is installed
200#
201# LIBRARY_PATH
202# LD_LIBRARY_PATH
203# we will search for libraries in these paths
204#
205# ATEN_THREADING
206# ATen parallel backend to use for intra- and inter-op parallelism
207# possible values:
208# OMP - use OpenMP for intra-op and native backend for inter-op tasks
209# NATIVE - use native thread pool for both intra- and inter-op tasks
210# TBB - using TBB for intra- and native thread pool for inter-op parallelism
211#
212# USE_TBB
213# enable TBB support
214#
215# USE_SYSTEM_TBB
216# Use system-provided Intel TBB.
217#
218# USE_SYSTEM_LIBS (work in progress)
219# Use system-provided libraries to satisfy the build dependencies.
220# When turned on, the following cmake variables will be toggled as well:
221# USE_SYSTEM_CPUINFO=ON USE_SYSTEM_SLEEF=ON BUILD_CUSTOM_PROTOBUF=OFF
222#
223# USE_MIMALLOC
224# Static link mimalloc into C10, and use mimalloc in alloc_cpu & alloc_free.
225# By default, It is only enabled on Windows.
226
227import sys228
229if sys.platform == "win32" and sys.maxsize.bit_length() == 31:230print(231"32-bit Windows Python runtime is not supported. Please switch to 64-bit Python."232)233sys.exit(-1)234
235import platform236
237python_min_version = (3, 8, 0)238python_min_version_str = ".".join(map(str, python_min_version))239if sys.version_info < python_min_version:240print(241f"You are using Python {platform.python_version()}. Python >={python_min_version_str} is required."242)243sys.exit(-1)244
245import filecmp246import glob247import importlib248import json249import os250import shutil251import subprocess252import sysconfig253import time254from collections import defaultdict255
256import setuptools.command.build_ext257import setuptools.command.install258import setuptools.command.sdist259from setuptools import Extension, find_packages, setup260from setuptools.dist import Distribution261
262from tools.build_pytorch_libs import build_caffe2263from tools.generate_torch_version import get_torch_version264from tools.setup_helpers.cmake import CMake265from tools.setup_helpers.env import build_type, IS_DARWIN, IS_LINUX, IS_WINDOWS266
267################################################################################
268# Parameters parsed from environment
269################################################################################
270
271VERBOSE_SCRIPT = True272RUN_BUILD_DEPS = True273# see if the user passed a quiet flag to setup.py arguments and respect
274# that in our parts of the build
275EMIT_BUILD_WARNING = False276RERUN_CMAKE = False277CMAKE_ONLY = False278filtered_args = []279for i, arg in enumerate(sys.argv):280if arg == "--cmake":281RERUN_CMAKE = True282continue283if arg == "--cmake-only":284# Stop once cmake terminates. Leave users a chance to adjust build285# options.286CMAKE_ONLY = True287continue288if arg == "rebuild" or arg == "build":289arg = "build" # rebuild is gone, make it build290EMIT_BUILD_WARNING = True291if arg == "--":292filtered_args += sys.argv[i:]293break294if arg == "-q" or arg == "--quiet":295VERBOSE_SCRIPT = False296if arg in ["clean", "egg_info", "sdist"]:297RUN_BUILD_DEPS = False298filtered_args.append(arg)299sys.argv = filtered_args300
301if VERBOSE_SCRIPT:302
303def report(*args):304print(*args)305
306else:307
308def report(*args):309pass310
311# Make distutils respect --quiet too312setuptools.distutils.log.warn = report313
314# Constant known variables used throughout this file
315cwd = os.path.dirname(os.path.abspath(__file__))316lib_path = os.path.join(cwd, "torch", "lib")317third_party_path = os.path.join(cwd, "third_party")318caffe2_build_dir = os.path.join(cwd, "build")319
320# CMAKE: full path to python library
321if IS_WINDOWS:322cmake_python_library = "{}/libs/python{}.lib".format(323sysconfig.get_config_var("prefix"), sysconfig.get_config_var("VERSION")324)325# Fix virtualenv builds326if not os.path.exists(cmake_python_library):327cmake_python_library = "{}/libs/python{}.lib".format(328sys.base_prefix, sysconfig.get_config_var("VERSION")329)330else:331cmake_python_library = "{}/{}".format(332sysconfig.get_config_var("LIBDIR"), sysconfig.get_config_var("INSTSONAME")333)334cmake_python_include_dir = sysconfig.get_path("include")335
336
337################################################################################
338# Version, create_version_file, and package_name
339################################################################################
340package_name = os.getenv("TORCH_PACKAGE_NAME", "torch")341package_type = os.getenv("PACKAGE_TYPE", "wheel")342version = get_torch_version()343report(f"Building wheel {package_name}-{version}")344
345cmake = CMake()346
347
348def get_submodule_folders():349git_modules_path = os.path.join(cwd, ".gitmodules")350default_modules_path = [351os.path.join(third_party_path, name)352for name in [353"gloo",354"cpuinfo",355"tbb",356"onnx",357"foxi",358"QNNPACK",359"fbgemm",360"cutlass",361]362]363if not os.path.exists(git_modules_path):364return default_modules_path365with open(git_modules_path) as f:366return [367os.path.join(cwd, line.split("=", 1)[1].strip())368for line in f369if line.strip().startswith("path")370]371
372
373def check_submodules():374def check_for_files(folder, files):375if not any(os.path.exists(os.path.join(folder, f)) for f in files):376report("Could not find any of {} in {}".format(", ".join(files), folder))377report("Did you run 'git submodule update --init --recursive'?")378sys.exit(1)379
380def not_exists_or_empty(folder):381return not os.path.exists(folder) or (382os.path.isdir(folder) and len(os.listdir(folder)) == 0383)384
385if bool(os.getenv("USE_SYSTEM_LIBS", False)):386return387folders = get_submodule_folders()388# If none of the submodule folders exists, try to initialize them389if all(not_exists_or_empty(folder) for folder in folders):390try:391print(" --- Trying to initialize submodules")392start = time.time()393subprocess.check_call(394["git", "submodule", "update", "--init", "--recursive"], cwd=cwd395)396end = time.time()397print(f" --- Submodule initialization took {end - start:.2f} sec")398except Exception:399print(" --- Submodule initalization failed")400print("Please run:\n\tgit submodule update --init --recursive")401sys.exit(1)402for folder in folders:403check_for_files(404folder,405[406"CMakeLists.txt",407"Makefile",408"setup.py",409"LICENSE",410"LICENSE.md",411"LICENSE.txt",412],413)414check_for_files(415os.path.join(third_party_path, "fbgemm", "third_party", "asmjit"),416["CMakeLists.txt"],417)418check_for_files(419os.path.join(third_party_path, "onnx", "third_party", "benchmark"),420["CMakeLists.txt"],421)422
423
424# Windows has very bad support for symbolic links.
425# Instead of using symlinks, we're going to copy files over
426def mirror_files_into_torchgen():427# (new_path, orig_path)428# Directories are OK and are recursively mirrored.429paths = [430(431"torchgen/packaged/ATen/native/native_functions.yaml",432"aten/src/ATen/native/native_functions.yaml",433),434("torchgen/packaged/ATen/native/tags.yaml", "aten/src/ATen/native/tags.yaml"),435("torchgen/packaged/ATen/templates", "aten/src/ATen/templates"),436("torchgen/packaged/autograd", "tools/autograd"),437("torchgen/packaged/autograd/templates", "tools/autograd/templates"),438]439for new_path, orig_path in paths:440# Create the dirs involved in new_path if they don't exist441if not os.path.exists(new_path):442os.makedirs(os.path.dirname(new_path), exist_ok=True)443
444# Copy the files from the orig location to the new location445if os.path.isfile(orig_path):446shutil.copyfile(orig_path, new_path)447continue448if os.path.isdir(orig_path):449if os.path.exists(new_path):450# copytree fails if the tree exists already, so remove it.451shutil.rmtree(new_path)452shutil.copytree(orig_path, new_path)453continue454raise RuntimeError("Check the file paths in `mirror_files_into_torchgen()`")455
456
457# all the work we need to do _before_ setup runs
458def build_deps():459report("-- Building version " + version)460
461check_submodules()462check_pydep("yaml", "pyyaml")463
464build_caffe2(465version=version,466cmake_python_library=cmake_python_library,467build_python=True,468rerun_cmake=RERUN_CMAKE,469cmake_only=CMAKE_ONLY,470cmake=cmake,471)472
473if CMAKE_ONLY:474report(475'Finished running cmake. Run "ccmake build" or '476'"cmake-gui build" to adjust build options and '477'"python setup.py install" to build.'478)479sys.exit()480
481# Use copies instead of symbolic files.482# Windows has very poor support for them.483sym_files = [484"tools/shared/_utils_internal.py",485"torch/utils/benchmark/utils/valgrind_wrapper/callgrind.h",486"torch/utils/benchmark/utils/valgrind_wrapper/valgrind.h",487]488orig_files = [489"torch/_utils_internal.py",490"third_party/valgrind-headers/callgrind.h",491"third_party/valgrind-headers/valgrind.h",492]493for sym_file, orig_file in zip(sym_files, orig_files):494same = False495if os.path.exists(sym_file):496if filecmp.cmp(sym_file, orig_file):497same = True498else:499os.remove(sym_file)500if not same:501shutil.copyfile(orig_file, sym_file)502
503
504################################################################################
505# Building dependent libraries
506################################################################################
507
508missing_pydep = """509Missing build dependency: Unable to `import {importname}`.
510Please install it via `conda install {module}` or `pip install {module}`
511""".strip()512
513
514def check_pydep(importname, module):515try:516importlib.import_module(importname)517except ImportError as e:518raise RuntimeError(519missing_pydep.format(importname=importname, module=module)520) from e521
522
523class build_ext(setuptools.command.build_ext.build_ext):524def _embed_libomp(self):525# Copy libiomp5.dylib/libomp.dylib inside the wheel package on MacOS526lib_dir = os.path.join(self.build_lib, "torch", "lib")527libtorch_cpu_path = os.path.join(lib_dir, "libtorch_cpu.dylib")528if not os.path.exists(libtorch_cpu_path):529return530# Parse libtorch_cpu load commands531otool_cmds = (532subprocess.check_output(["otool", "-l", libtorch_cpu_path])533.decode("utf-8")534.split("\n")535)536rpaths, libs = [], []537for idx, line in enumerate(otool_cmds):538if line.strip() == "cmd LC_LOAD_DYLIB":539lib_name = otool_cmds[idx + 2].strip()540assert lib_name.startswith("name ")541libs.append(lib_name.split(" ", 1)[1].rsplit("(", 1)[0][:-1])542
543if line.strip() == "cmd LC_RPATH":544rpath = otool_cmds[idx + 2].strip()545assert rpath.startswith("path ")546rpaths.append(rpath.split(" ", 1)[1].rsplit("(", 1)[0][:-1])547
548omp_lib_name = (549"libomp.dylib" if os.uname().machine == "arm64" else "libiomp5.dylib"550)551if os.path.join("@rpath", omp_lib_name) not in libs:552return553
554# Copy libomp/libiomp5 from rpath locations555for rpath in rpaths:556source_lib = os.path.join(rpath, omp_lib_name)557if not os.path.exists(source_lib):558continue559target_lib = os.path.join(self.build_lib, "torch", "lib", omp_lib_name)560self.copy_file(source_lib, target_lib)561break562
563# Copy omp.h from OpenMP_C_FLAGS and copy it into include folder564omp_cflags = get_cmake_cache_vars()["OpenMP_C_FLAGS"]565if not omp_cflags:566return567for include_dir in [f[2:] for f in omp_cflags.split(" ") if f.startswith("-I")]:568omp_h = os.path.join(include_dir, "omp.h")569if not os.path.exists(omp_h):570continue571target_omp_h = os.path.join(self.build_lib, "torch", "include", "omp.h")572self.copy_file(omp_h, target_omp_h)573break574
575def run(self):576# Report build options. This is run after the build completes so # `CMakeCache.txt` exists and we can get an577# accurate report on what is used and what is not.578cmake_cache_vars = defaultdict(lambda: False, cmake.get_cmake_cache_variables())579if cmake_cache_vars["USE_NUMPY"]:580report("-- Building with NumPy bindings")581else:582report("-- NumPy not found")583if cmake_cache_vars["USE_CUDNN"]:584report(585"-- Detected cuDNN at "586+ cmake_cache_vars["CUDNN_LIBRARY"]587+ ", "588+ cmake_cache_vars["CUDNN_INCLUDE_DIR"]589)590else:591report("-- Not using cuDNN")592if cmake_cache_vars["USE_CUDA"]:593report("-- Detected CUDA at " + cmake_cache_vars["CUDA_TOOLKIT_ROOT_DIR"])594else:595report("-- Not using CUDA")596if cmake_cache_vars["USE_XPU"]:597report("-- Detected XPU runtime at " + cmake_cache_vars["SYCL_LIBRARY_DIR"])598else:599report("-- Not using XPU")600if cmake_cache_vars["USE_MKLDNN"]:601report("-- Using MKLDNN")602if cmake_cache_vars["USE_MKLDNN_ACL"]:603report("-- Using Compute Library for the Arm architecture with MKLDNN")604else:605report(606"-- Not using Compute Library for the Arm architecture with MKLDNN"607)608if cmake_cache_vars["USE_MKLDNN_CBLAS"]:609report("-- Using CBLAS in MKLDNN")610else:611report("-- Not using CBLAS in MKLDNN")612else:613report("-- Not using MKLDNN")614if cmake_cache_vars["USE_NCCL"] and cmake_cache_vars["USE_SYSTEM_NCCL"]:615report(616"-- Using system provided NCCL library at {}, {}".format(617cmake_cache_vars["NCCL_LIBRARIES"],618cmake_cache_vars["NCCL_INCLUDE_DIRS"],619)620)621elif cmake_cache_vars["USE_NCCL"]:622report("-- Building NCCL library")623else:624report("-- Not using NCCL")625if cmake_cache_vars["USE_DISTRIBUTED"]:626if IS_WINDOWS:627report("-- Building without distributed package")628else:629report("-- Building with distributed package: ")630report(631" -- USE_TENSORPIPE={}".format(cmake_cache_vars["USE_TENSORPIPE"])632)633report(" -- USE_GLOO={}".format(cmake_cache_vars["USE_GLOO"]))634report(" -- USE_MPI={}".format(cmake_cache_vars["USE_OPENMPI"]))635else:636report("-- Building without distributed package")637if cmake_cache_vars["STATIC_DISPATCH_BACKEND"]:638report(639"-- Using static dispatch with backend {}".format(640cmake_cache_vars["STATIC_DISPATCH_BACKEND"]641)642)643if cmake_cache_vars["USE_LIGHTWEIGHT_DISPATCH"]:644report("-- Using lightweight dispatch")645if cmake_cache_vars["BUILD_EXECUTORCH"]:646report("-- Building Executorch")647
648if cmake_cache_vars["USE_ITT"]:649report("-- Using ITT")650else:651report("-- Not using ITT")652
653# Do not use clang to compile extensions if `-fstack-clash-protection` is defined654# in system CFLAGS655c_flags = str(os.getenv("CFLAGS", ""))656if (657IS_LINUX
658and "-fstack-clash-protection" in c_flags659and "clang" in os.environ.get("CC", "")660):661os.environ["CC"] = str(os.environ["CC"])662
663# It's an old-style class in Python 2.7...664setuptools.command.build_ext.build_ext.run(self)665
666if IS_DARWIN and package_type != "conda":667self._embed_libomp()668
669# Copy the essential export library to compile C++ extensions.670if IS_WINDOWS:671build_temp = self.build_temp672
673ext_filename = self.get_ext_filename("_C")674lib_filename = ".".join(ext_filename.split(".")[:-1]) + ".lib"675
676export_lib = os.path.join(677build_temp, "torch", "csrc", lib_filename678).replace("\\", "/")679
680build_lib = self.build_lib681
682target_lib = os.path.join(build_lib, "torch", "lib", "_C.lib").replace(683"\\", "/"684)685
686# Create "torch/lib" directory if not exists.687# (It is not created yet in "develop" mode.)688target_dir = os.path.dirname(target_lib)689if not os.path.exists(target_dir):690os.makedirs(target_dir)691
692self.copy_file(export_lib, target_lib)693
694def build_extensions(self):695self.create_compile_commands()696# The caffe2 extensions are created in697# tmp_install/lib/pythonM.m/site-packages/caffe2/python/698# and need to be copied to build/lib.linux.... , which will be a699# platform dependent build folder created by the "build" command of700# setuptools. Only the contents of this folder are installed in the701# "install" command by default.702# We only make this copy for Caffe2's pybind extensions703caffe2_pybind_exts = [704"caffe2.python.caffe2_pybind11_state",705"caffe2.python.caffe2_pybind11_state_gpu",706"caffe2.python.caffe2_pybind11_state_hip",707]708i = 0709while i < len(self.extensions):710ext = self.extensions[i]711if ext.name not in caffe2_pybind_exts:712i += 1713continue714fullname = self.get_ext_fullname(ext.name)715filename = self.get_ext_filename(fullname)716report(f"\nCopying extension {ext.name}")717
718relative_site_packages = (719sysconfig.get_path("purelib")720.replace(sysconfig.get_path("data"), "")721.lstrip(os.path.sep)722)723src = os.path.join("torch", relative_site_packages, filename)724if not os.path.exists(src):725report(f"{src} does not exist")726del self.extensions[i]727else:728dst = os.path.join(os.path.realpath(self.build_lib), filename)729report(f"Copying {ext.name} from {src} to {dst}")730dst_dir = os.path.dirname(dst)731if not os.path.exists(dst_dir):732os.makedirs(dst_dir)733self.copy_file(src, dst)734i += 1735
736# Copy functorch extension737for i, ext in enumerate(self.extensions):738if ext.name != "functorch._C":739continue740fullname = self.get_ext_fullname(ext.name)741filename = self.get_ext_filename(fullname)742fileext = os.path.splitext(filename)[1]743src = os.path.join(os.path.dirname(filename), "functorch" + fileext)744dst = os.path.join(os.path.realpath(self.build_lib), filename)745if os.path.exists(src):746report(f"Copying {ext.name} from {src} to {dst}")747dst_dir = os.path.dirname(dst)748if not os.path.exists(dst_dir):749os.makedirs(dst_dir)750self.copy_file(src, dst)751
752setuptools.command.build_ext.build_ext.build_extensions(self)753
754def get_outputs(self):755outputs = setuptools.command.build_ext.build_ext.get_outputs(self)756outputs.append(os.path.join(self.build_lib, "caffe2"))757report(f"setup.py::get_outputs returning {outputs}")758return outputs759
760def create_compile_commands(self):761def load(filename):762with open(filename) as f:763return json.load(f)764
765ninja_files = glob.glob("build/*compile_commands.json")766cmake_files = glob.glob("torch/lib/build/*/compile_commands.json")767all_commands = [entry for f in ninja_files + cmake_files for entry in load(f)]768
769# cquery does not like c++ compiles that start with gcc.770# It forgets to include the c++ header directories.771# We can work around this by replacing the gcc calls that python772# setup.py generates with g++ calls instead773for command in all_commands:774if command["command"].startswith("gcc "):775command["command"] = "g++ " + command["command"][4:]776
777new_contents = json.dumps(all_commands, indent=2)778contents = ""779if os.path.exists("compile_commands.json"):780with open("compile_commands.json") as f:781contents = f.read()782if contents != new_contents:783with open("compile_commands.json", "w") as f:784f.write(new_contents)785
786
787class concat_license_files:788"""Merge LICENSE and LICENSES_BUNDLED.txt as a context manager789
790LICENSE is the main PyTorch license, LICENSES_BUNDLED.txt is auto-generated
791from all the licenses found in ./third_party/. We concatenate them so there
792is a single license file in the sdist and wheels with all of the necessary
793licensing info.
794"""
795
796def __init__(self, include_files=False):797self.f1 = "LICENSE"798self.f2 = "third_party/LICENSES_BUNDLED.txt"799self.include_files = include_files800
801def __enter__(self):802"""Concatenate files"""803
804old_path = sys.path805sys.path.append(third_party_path)806try:807from build_bundled import create_bundled808finally:809sys.path = old_path810
811with open(self.f1) as f1:812self.bsd_text = f1.read()813
814with open(self.f1, "a") as f1:815f1.write("\n\n")816create_bundled(817os.path.relpath(third_party_path), f1, include_files=self.include_files818)819
820def __exit__(self, exception_type, exception_value, traceback):821"""Restore content of f1"""822with open(self.f1, "w") as f:823f.write(self.bsd_text)824
825
826try:827from wheel.bdist_wheel import bdist_wheel828except ImportError:829# This is useful when wheel is not installed and bdist_wheel is not830# specified on the command line. If it _is_ specified, parsing the command831# line will fail before wheel_concatenate is needed832wheel_concatenate = None833else:834# Need to create the proper LICENSE.txt for the wheel835class wheel_concatenate(bdist_wheel):836"""check submodules on sdist to prevent incomplete tarballs"""837
838def run(self):839with concat_license_files(include_files=True):840super().run()841
842
843class install(setuptools.command.install.install):844def run(self):845super().run()846
847
848class clean(setuptools.Command):849user_options = []850
851def initialize_options(self):852pass853
854def finalize_options(self):855pass856
857def run(self):858import glob859import re860
861with open(".gitignore") as f:862ignores = f.read()863pat = re.compile(r"^#( BEGIN NOT-CLEAN-FILES )?")864for wildcard in filter(None, ignores.split("\n")):865match = pat.match(wildcard)866if match:867if match.group(1):868# Marker is found and stop reading .gitignore.869break870# Ignore lines which begin with '#'.871else:872# Don't remove absolute paths from the system873wildcard = wildcard.lstrip("./")874
875for filename in glob.glob(wildcard):876try:877os.remove(filename)878except OSError:879shutil.rmtree(filename, ignore_errors=True)880
881
882class sdist(setuptools.command.sdist.sdist):883def run(self):884with concat_license_files():885super().run()886
887
888def get_cmake_cache_vars():889try:890return defaultdict(lambda: False, cmake.get_cmake_cache_variables())891except FileNotFoundError:892# CMakeCache.txt does not exist. Probably running "python setup.py clean" over a clean directory.893return defaultdict(lambda: False)894
895
896def configure_extension_build():897r"""Configures extension build options according to system environment and user's choice.898
899Returns:
900The input to parameters ext_modules, cmdclass, packages, and entry_points as required in setuptools.setup.
901"""
902
903cmake_cache_vars = get_cmake_cache_vars()904
905################################################################################906# Configure compile flags907################################################################################908
909library_dirs = []910extra_install_requires = []911
912if IS_WINDOWS:913# /NODEFAULTLIB makes sure we only link to DLL runtime914# and matches the flags set for protobuf and ONNX915extra_link_args = ["/NODEFAULTLIB:LIBCMT.LIB"]916# /MD links against DLL runtime917# and matches the flags set for protobuf and ONNX918# /EHsc is about standard C++ exception handling919extra_compile_args = ["/MD", "/FS", "/EHsc"]920else:921extra_link_args = []922extra_compile_args = [923"-Wall",924"-Wextra",925"-Wno-strict-overflow",926"-Wno-unused-parameter",927"-Wno-missing-field-initializers",928"-Wno-unknown-pragmas",929# Python 2.6 requires -fno-strict-aliasing, see930# http://legacy.python.org/dev/peps/pep-3123/931# We also depend on it in our code (even Python 3).932"-fno-strict-aliasing",933]934
935library_dirs.append(lib_path)936
937main_compile_args = []938main_libraries = ["torch_python"]939main_link_args = []940main_sources = ["torch/csrc/stub.c"]941
942if cmake_cache_vars["USE_CUDA"]:943library_dirs.append(os.path.dirname(cmake_cache_vars["CUDA_CUDA_LIB"]))944
945if build_type.is_debug():946if IS_WINDOWS:947extra_compile_args.append("/Z7")948extra_link_args.append("/DEBUG:FULL")949else:950extra_compile_args += ["-O0", "-g"]951extra_link_args += ["-O0", "-g"]952
953if build_type.is_rel_with_deb_info():954if IS_WINDOWS:955extra_compile_args.append("/Z7")956extra_link_args.append("/DEBUG:FULL")957else:958extra_compile_args += ["-g"]959extra_link_args += ["-g"]960
961# pypi cuda package that requires installation of cuda runtime, cudnn and cublas962# should be included in all wheels uploaded to pypi963pytorch_extra_install_requirements = os.getenv(964"PYTORCH_EXTRA_INSTALL_REQUIREMENTS", ""965)966if pytorch_extra_install_requirements:967report(968f"pytorch_extra_install_requirements: {pytorch_extra_install_requirements}"969)970extra_install_requires += pytorch_extra_install_requirements.split("|")971
972# Cross-compile for M1973if IS_DARWIN:974macos_target_arch = os.getenv("CMAKE_OSX_ARCHITECTURES", "")975if macos_target_arch in ["arm64", "x86_64"]:976macos_sysroot_path = os.getenv("CMAKE_OSX_SYSROOT")977if macos_sysroot_path is None:978macos_sysroot_path = (979subprocess.check_output(980["xcrun", "--show-sdk-path", "--sdk", "macosx"]981)982.decode("utf-8")983.strip()984)985extra_compile_args += [986"-arch",987macos_target_arch,988"-isysroot",989macos_sysroot_path,990]991extra_link_args += ["-arch", macos_target_arch]992
993def make_relative_rpath_args(path):994if IS_DARWIN:995return ["-Wl,-rpath,@loader_path/" + path]996elif IS_WINDOWS:997return []998else:999return ["-Wl,-rpath,$ORIGIN/" + path]1000
1001################################################################################1002# Declare extensions and package1003################################################################################1004
1005extensions = []1006excludes = ["tools", "tools.*"]1007if not cmake_cache_vars["BUILD_CAFFE2"]:1008excludes.extend(["caffe2", "caffe2.*"])1009if not cmake_cache_vars["BUILD_FUNCTORCH"]:1010excludes.extend(["functorch", "functorch.*"])1011packages = find_packages(exclude=excludes)1012C = Extension(1013"torch._C",1014libraries=main_libraries,1015sources=main_sources,1016language="c",1017extra_compile_args=main_compile_args + extra_compile_args,1018include_dirs=[],1019library_dirs=library_dirs,1020extra_link_args=extra_link_args1021+ main_link_args1022+ make_relative_rpath_args("lib"),1023)1024extensions.append(C)1025
1026# These extensions are built by cmake and copied manually in build_extensions()1027# inside the build_ext implementation1028if cmake_cache_vars["BUILD_CAFFE2"]:1029extensions.append(1030Extension(name="caffe2.python.caffe2_pybind11_state", sources=[]),1031)1032if cmake_cache_vars["USE_CUDA"]:1033extensions.append(1034Extension(name="caffe2.python.caffe2_pybind11_state_gpu", sources=[]),1035)1036if cmake_cache_vars["USE_ROCM"]:1037extensions.append(1038Extension(name="caffe2.python.caffe2_pybind11_state_hip", sources=[]),1039)1040if cmake_cache_vars["BUILD_FUNCTORCH"]:1041extensions.append(1042Extension(name="functorch._C", sources=[]),1043)1044
1045cmdclass = {1046"bdist_wheel": wheel_concatenate,1047"build_ext": build_ext,1048"clean": clean,1049"install": install,1050"sdist": sdist,1051}1052
1053entry_points = {1054"console_scripts": [1055"convert-caffe2-to-onnx = caffe2.python.onnx.bin.conversion:caffe2_to_onnx",1056"convert-onnx-to-caffe2 = caffe2.python.onnx.bin.conversion:onnx_to_caffe2",1057"torchrun = torch.distributed.run:main",1058],1059"torchrun.logs_specs": [1060"default = torch.distributed.elastic.multiprocessing:DefaultLogsSpecs",1061],1062}1063
1064return extensions, cmdclass, packages, entry_points, extra_install_requires1065
1066
1067# post run, warnings, printed at the end to make them more visible
1068build_update_message = """1069It is no longer necessary to use the 'build' or 'rebuild' targets
1070
1071To install:
1072$ python setup.py install
1073To develop locally:
1074$ python setup.py develop
1075To force cmake to re-generate native build files (off by default):
1076$ python setup.py develop --cmake
1077"""
1078
1079
1080def print_box(msg):1081lines = msg.split("\n")1082size = max(len(l) + 1 for l in lines)1083print("-" * (size + 2))1084for l in lines:1085print("|{}{}|".format(l, " " * (size - len(l))))1086print("-" * (size + 2))1087
1088
1089def main():1090# the list of runtime dependencies required by this built package1091install_requires = [1092"filelock",1093"typing-extensions>=4.8.0",1094"sympy",1095"networkx",1096"jinja2",1097"fsspec",1098]1099if IS_WINDOWS:1100install_requires.append("mkl>=2021.1.1,<=2021.4.0")1101
1102# Parse the command line and check the arguments before we proceed with1103# building deps and setup. We need to set values so `--help` works.1104dist = Distribution()1105dist.script_name = os.path.basename(sys.argv[0])1106dist.script_args = sys.argv[1:]1107try:1108dist.parse_command_line()1109except setuptools.distutils.errors.DistutilsArgError as e:1110print(e)1111sys.exit(1)1112
1113mirror_files_into_torchgen()1114if RUN_BUILD_DEPS:1115build_deps()1116
1117(1118extensions,1119cmdclass,1120packages,1121entry_points,1122extra_install_requires,1123) = configure_extension_build()1124
1125install_requires += extra_install_requires1126
1127extras_require = {1128"optree": ["optree>=0.9.1"],1129"opt-einsum": ["opt-einsum>=3.3"],1130}1131
1132# Read in README.md for our long_description1133with open(os.path.join(cwd, "README.md"), encoding="utf-8") as f:1134long_description = f.read()1135
1136version_range_max = max(sys.version_info[1], 12) + 11137torch_package_data = [1138"py.typed",1139"bin/*",1140"test/*",1141"*.pyi",1142"_C/*.pyi",1143"cuda/*.pyi",1144"fx/*.pyi",1145"optim/*.pyi",1146"autograd/*.pyi",1147"nn/*.pyi",1148"nn/modules/*.pyi",1149"nn/parallel/*.pyi",1150"utils/data/*.pyi",1151"utils/data/datapipes/*.pyi",1152"lib/*.so*",1153"lib/*.dylib*",1154"lib/*.dll",1155"lib/*.lib",1156"lib/*.pdb",1157"lib/torch_shm_manager",1158"lib/*.h",1159"include/*.h",1160"include/ATen/*.h",1161"include/ATen/cpu/*.h",1162"include/ATen/cpu/vec/vec256/*.h",1163"include/ATen/cpu/vec/vec256/vsx/*.h",1164"include/ATen/cpu/vec/vec256/zarch/*.h",1165"include/ATen/cpu/vec/vec512/*.h",1166"include/ATen/cpu/vec/*.h",1167"include/ATen/core/*.h",1168"include/ATen/cuda/*.cuh",1169"include/ATen/cuda/*.h",1170"include/ATen/cuda/detail/*.cuh",1171"include/ATen/cuda/detail/*.h",1172"include/ATen/cuda/tunable/*.h",1173"include/ATen/cudnn/*.h",1174"include/ATen/functorch/*.h",1175"include/ATen/ops/*.h",1176"include/ATen/hip/*.cuh",1177"include/ATen/hip/*.h",1178"include/ATen/hip/detail/*.cuh",1179"include/ATen/hip/detail/*.h",1180"include/ATen/hip/impl/*.h",1181"include/ATen/hip/tunable/*.h",1182"include/ATen/mps/*.h",1183"include/ATen/miopen/*.h",1184"include/ATen/detail/*.h",1185"include/ATen/native/*.h",1186"include/ATen/native/cpu/*.h",1187"include/ATen/native/cuda/*.h",1188"include/ATen/native/cuda/*.cuh",1189"include/ATen/native/hip/*.h",1190"include/ATen/native/hip/*.cuh",1191"include/ATen/native/mps/*.h",1192"include/ATen/native/nested/*.h",1193"include/ATen/native/quantized/*.h",1194"include/ATen/native/quantized/cpu/*.h",1195"include/ATen/native/sparse/*.h",1196"include/ATen/native/utils/*.h",1197"include/ATen/quantized/*.h",1198"include/ATen/xpu/*.h",1199"include/ATen/xpu/detail/*.h",1200"include/caffe2/serialize/*.h",1201"include/c10/*.h",1202"include/c10/macros/*.h",1203"include/c10/core/*.h",1204"include/ATen/core/boxing/*.h",1205"include/ATen/core/boxing/impl/*.h",1206"include/ATen/core/dispatch/*.h",1207"include/ATen/core/op_registration/*.h",1208"include/c10/core/impl/*.h",1209"include/c10/util/*.h",1210"include/c10/cuda/*.h",1211"include/c10/cuda/impl/*.h",1212"include/c10/hip/*.h",1213"include/c10/hip/impl/*.h",1214"include/c10/xpu/*.h",1215"include/c10/xpu/impl/*.h",1216"include/torch/*.h",1217"include/torch/csrc/*.h",1218"include/torch/csrc/api/include/torch/*.h",1219"include/torch/csrc/api/include/torch/data/*.h",1220"include/torch/csrc/api/include/torch/data/dataloader/*.h",1221"include/torch/csrc/api/include/torch/data/datasets/*.h",1222"include/torch/csrc/api/include/torch/data/detail/*.h",1223"include/torch/csrc/api/include/torch/data/samplers/*.h",1224"include/torch/csrc/api/include/torch/data/transforms/*.h",1225"include/torch/csrc/api/include/torch/detail/*.h",1226"include/torch/csrc/api/include/torch/detail/ordered_dict.h",1227"include/torch/csrc/api/include/torch/nn/*.h",1228"include/torch/csrc/api/include/torch/nn/functional/*.h",1229"include/torch/csrc/api/include/torch/nn/options/*.h",1230"include/torch/csrc/api/include/torch/nn/modules/*.h",1231"include/torch/csrc/api/include/torch/nn/modules/container/*.h",1232"include/torch/csrc/api/include/torch/nn/parallel/*.h",1233"include/torch/csrc/api/include/torch/nn/utils/*.h",1234"include/torch/csrc/api/include/torch/optim/*.h",1235"include/torch/csrc/api/include/torch/optim/schedulers/*.h",1236"include/torch/csrc/api/include/torch/serialize/*.h",1237"include/torch/csrc/autograd/*.h",1238"include/torch/csrc/autograd/functions/*.h",1239"include/torch/csrc/autograd/generated/*.h",1240"include/torch/csrc/autograd/utils/*.h",1241"include/torch/csrc/cuda/*.h",1242"include/torch/csrc/distributed/c10d/*.h",1243"include/torch/csrc/distributed/c10d/*.hpp",1244"include/torch/csrc/distributed/rpc/*.h",1245"include/torch/csrc/distributed/autograd/context/*.h",1246"include/torch/csrc/distributed/autograd/functions/*.h",1247"include/torch/csrc/distributed/autograd/rpc_messages/*.h",1248"include/torch/csrc/dynamo/*.h",1249"include/torch/csrc/inductor/*.h",1250"include/torch/csrc/inductor/aoti_runner/*.h",1251"include/torch/csrc/inductor/aoti_runtime/*.h",1252"include/torch/csrc/inductor/aoti_torch/*.h",1253"include/torch/csrc/inductor/aoti_torch/c/*.h",1254"include/torch/csrc/jit/*.h",1255"include/torch/csrc/jit/backends/*.h",1256"include/torch/csrc/jit/generated/*.h",1257"include/torch/csrc/jit/passes/*.h",1258"include/torch/csrc/jit/passes/quantization/*.h",1259"include/torch/csrc/jit/passes/utils/*.h",1260"include/torch/csrc/jit/runtime/*.h",1261"include/torch/csrc/jit/ir/*.h",1262"include/torch/csrc/jit/frontend/*.h",1263"include/torch/csrc/jit/api/*.h",1264"include/torch/csrc/jit/serialization/*.h",1265"include/torch/csrc/jit/python/*.h",1266"include/torch/csrc/jit/mobile/*.h",1267"include/torch/csrc/jit/testing/*.h",1268"include/torch/csrc/jit/tensorexpr/*.h",1269"include/torch/csrc/jit/tensorexpr/operators/*.h",1270"include/torch/csrc/jit/codegen/cuda/*.h",1271"include/torch/csrc/onnx/*.h",1272"include/torch/csrc/profiler/*.h",1273"include/torch/csrc/profiler/orchestration/*.h",1274"include/torch/csrc/profiler/stubs/*.h",1275"include/torch/csrc/profiler/unwind/*.h",1276"include/torch/csrc/utils/*.h",1277"include/torch/csrc/tensor/*.h",1278"include/torch/csrc/lazy/backend/*.h",1279"include/torch/csrc/lazy/core/*.h",1280"include/torch/csrc/lazy/core/internal_ops/*.h",1281"include/torch/csrc/lazy/core/ops/*.h",1282"include/torch/csrc/lazy/python/python_util.h",1283"include/torch/csrc/lazy/ts_backend/*.h",1284"include/torch/csrc/xpu/*.h",1285"include/pybind11/*.h",1286"include/pybind11/detail/*.h",1287"include/pybind11/eigen/*.h",1288"include/TH/*.h*",1289"include/TH/generic/*.h*",1290"include/THC/*.cuh",1291"include/THC/*.h*",1292"include/THC/generic/*.h",1293"include/THH/*.cuh",1294"include/THH/*.h*",1295"include/THH/generic/*.h",1296"include/sleef.h",1297"_inductor/codegen/*.h",1298"_inductor/codegen/aoti_runtime/*.cpp",1299"_export/serde/*.yaml",1300"share/cmake/ATen/*.cmake",1301"share/cmake/Caffe2/*.cmake",1302"share/cmake/Caffe2/public/*.cmake",1303"share/cmake/Caffe2/Modules_CUDA_fix/*.cmake",1304"share/cmake/Caffe2/Modules_CUDA_fix/upstream/*.cmake",1305"share/cmake/Caffe2/Modules_CUDA_fix/upstream/FindCUDA/*.cmake",1306"share/cmake/Gloo/*.cmake",1307"share/cmake/Tensorpipe/*.cmake",1308"share/cmake/Torch/*.cmake",1309"utils/benchmark/utils/*.cpp",1310"utils/benchmark/utils/valgrind_wrapper/*.cpp",1311"utils/benchmark/utils/valgrind_wrapper/*.h",1312"utils/model_dump/skeleton.html",1313"utils/model_dump/code.js",1314"utils/model_dump/*.mjs",1315]1316
1317if get_cmake_cache_vars()["BUILD_CAFFE2"]:1318torch_package_data.extend(1319[1320"include/caffe2/**/*.h",1321"include/caffe2/utils/*.h",1322"include/caffe2/utils/**/*.h",1323]1324)1325if get_cmake_cache_vars()["USE_TENSORPIPE"]:1326torch_package_data.extend(1327[1328"include/tensorpipe/*.h",1329"include/tensorpipe/channel/*.h",1330"include/tensorpipe/channel/basic/*.h",1331"include/tensorpipe/channel/cma/*.h",1332"include/tensorpipe/channel/mpt/*.h",1333"include/tensorpipe/channel/xth/*.h",1334"include/tensorpipe/common/*.h",1335"include/tensorpipe/core/*.h",1336"include/tensorpipe/transport/*.h",1337"include/tensorpipe/transport/ibv/*.h",1338"include/tensorpipe/transport/shm/*.h",1339"include/tensorpipe/transport/uv/*.h",1340]1341)1342torchgen_package_data = [1343# Recursive glob doesn't work in setup.py,1344# https://github.com/pypa/setuptools/issues/18061345# To make this robust we should replace it with some code that1346# returns a list of everything under packaged/1347"packaged/ATen/*",1348"packaged/ATen/native/*",1349"packaged/ATen/templates/*",1350"packaged/autograd/*",1351"packaged/autograd/templates/*",1352]1353setup(1354name=package_name,1355version=version,1356description=(1357"Tensors and Dynamic neural networks in "1358"Python with strong GPU acceleration"1359),1360long_description=long_description,1361long_description_content_type="text/markdown",1362ext_modules=extensions,1363cmdclass=cmdclass,1364packages=packages,1365entry_points=entry_points,1366install_requires=install_requires,1367extras_require=extras_require,1368package_data={1369"torch": torch_package_data,1370"torchgen": torchgen_package_data,1371"caffe2": [1372"python/serialized_test/data/operator_test/*.zip",1373],1374},1375url="https://pytorch.org/",1376download_url="https://github.com/pytorch/pytorch/tags",1377author="PyTorch Team",1378author_email="packages@pytorch.org",1379python_requires=f">={python_min_version_str}",1380# PyPI package information.1381classifiers=[1382"Development Status :: 5 - Production/Stable",1383"Intended Audience :: Developers",1384"Intended Audience :: Education",1385"Intended Audience :: Science/Research",1386"License :: OSI Approved :: BSD License",1387"Topic :: Scientific/Engineering",1388"Topic :: Scientific/Engineering :: Mathematics",1389"Topic :: Scientific/Engineering :: Artificial Intelligence",1390"Topic :: Software Development",1391"Topic :: Software Development :: Libraries",1392"Topic :: Software Development :: Libraries :: Python Modules",1393"Programming Language :: C++",1394"Programming Language :: Python :: 3",1395]1396+ [1397f"Programming Language :: Python :: 3.{i}"1398for i in range(python_min_version[1], version_range_max)1399],1400license="BSD-3",1401keywords="pytorch, machine learning",1402)1403if EMIT_BUILD_WARNING:1404print_box(build_update_message)1405
1406
1407if __name__ == "__main__":1408main()1409