diff --git a/.ci/aarch64_linux/aarch64_wheel_ci_build.py b/.ci/aarch64_linux/aarch64_wheel_ci_build.py index d7bbdebc677a..2c6b94a0dc23 100755 --- a/.ci/aarch64_linux/aarch64_wheel_ci_build.py +++ b/.ci/aarch64_linux/aarch64_wheel_ci_build.py @@ -250,7 +250,7 @@ def parse_arguments(): else: print("build pytorch without mkldnn backend") - os.system(f"cd /pytorch; {build_vars} python3 setup.py bdist_wheel") + os.system(f"cd /pytorch; {build_vars} python3 -m build --wheel --no-isolation") if enable_cuda: print("Updating Cuda Dependency") filename = os.listdir("/pytorch/dist/") diff --git a/.ci/aarch64_linux/build_aarch64_wheel.py b/.ci/aarch64_linux/build_aarch64_wheel.py index 7a4715d33006..36b85ebc422c 100755 --- a/.ci/aarch64_linux/build_aarch64_wheel.py +++ b/.ci/aarch64_linux/build_aarch64_wheel.py @@ -442,7 +442,7 @@ def build_torchvision( if host.using_docker(): build_vars += " CMAKE_SHARED_LINKER_FLAGS=-Wl,-z,max-page-size=0x10000" - host.run_cmd(f"cd vision && {build_vars} python3 setup.py bdist_wheel") + host.run_cmd(f"cd vision && {build_vars} python3 -m build --wheel --no-isolation") vision_wheel_name = host.list_dir("vision/dist")[0] embed_libgomp(host, use_conda, os.path.join("vision", "dist", vision_wheel_name)) @@ -497,7 +497,7 @@ def build_torchdata( if host.using_docker(): build_vars += " CMAKE_SHARED_LINKER_FLAGS=-Wl,-z,max-page-size=0x10000" - host.run_cmd(f"cd data && {build_vars} python3 setup.py bdist_wheel") + host.run_cmd(f"cd data && {build_vars} python3 -m build --wheel --no-isolation") wheel_name = host.list_dir("data/dist")[0] embed_libgomp(host, use_conda, os.path.join("data", "dist", wheel_name)) @@ -553,7 +553,7 @@ def build_torchtext( if host.using_docker(): build_vars += " CMAKE_SHARED_LINKER_FLAGS=-Wl,-z,max-page-size=0x10000" - host.run_cmd(f"cd text && {build_vars} python3 setup.py bdist_wheel") + host.run_cmd(f"cd text && {build_vars} python3 -m build --wheel --no-isolation") wheel_name = host.list_dir("text/dist")[0] embed_libgomp(host, use_conda, os.path.join("text", "dist", wheel_name)) @@ -614,7 +614,7 @@ def build_torchaudio( host.run_cmd( f"cd audio && export FFMPEG_ROOT=$(pwd)/third_party/ffmpeg && export USE_FFMPEG=1 \ && ./packaging/ffmpeg/build.sh \ - && {build_vars} python3 setup.py bdist_wheel" + && {build_vars} python3 -m build --wheel --no-isolation" ) wheel_name = host.list_dir("audio/dist")[0] @@ -726,7 +726,7 @@ def start_build( print("Building PyTorch wheel") build_opts = "" if pytorch_build_number is not None: - build_opts += f" --build-number {pytorch_build_number}" + build_opts += f" -C--build-option=--build-number={pytorch_build_number}" # Breakpad build fails on aarch64 build_vars = "USE_BREAKPAD=0 " if branch == "nightly": @@ -747,7 +747,8 @@ def start_build( print("build pytorch with mkldnn+acl backend") build_vars += " USE_MKLDNN=ON USE_MKLDNN_ACL=ON" host.run_cmd( - f"cd $HOME/pytorch && export ACL_ROOT_DIR=$HOME/ComputeLibrary && {build_vars} python3 setup.py bdist_wheel{build_opts}" + f"cd $HOME/pytorch && export ACL_ROOT_DIR=$HOME/ComputeLibrary && " + f"{build_vars} python3 -m build --wheel --no-isolation{build_opts}" ) print("Repair the wheel") pytorch_wheel_name = host.list_dir("pytorch/dist")[0] @@ -763,7 +764,7 @@ def start_build( else: print("build pytorch without mkldnn backend") host.run_cmd( - f"cd pytorch && {build_vars} python3 setup.py bdist_wheel{build_opts}" + f"cd pytorch && {build_vars} python3 -m build --wheel --no-isolation{build_opts}" ) print("Deleting build folder") diff --git a/.ci/docker/build.sh b/.ci/docker/build.sh index aabfbd5a4772..49470a055808 100755 --- a/.ci/docker/build.sh +++ b/.ci/docker/build.sh @@ -456,12 +456,3 @@ elif [ "$HAS_TRITON" = "yes" ]; then echo "expecting triton to not be installed, but it is" exit 1 fi - -# Sanity check cmake version. Executorch reinstalls cmake and I'm not sure if -# they support 4.0.0 yet, so exclude them from this check. -CMAKE_VERSION=$(drun cmake --version) -if [[ "$EXECUTORCH" != *yes* && "$CMAKE_VERSION" != *4.* ]]; then - echo "CMake version is not 4.0.0:" - drun cmake --version - exit 1 -fi diff --git a/.ci/docker/common/install_triton.sh b/.ci/docker/common/install_triton.sh index a965f0f743d4..695a373397ab 100755 --- a/.ci/docker/common/install_triton.sh +++ b/.ci/docker/common/install_triton.sh @@ -66,15 +66,15 @@ if [ -n "${UBUNTU_VERSION}" ] && [ -n "${GCC_VERSION}" ] && [[ "${GCC_VERSION}" # Triton needs at least gcc-9 to build apt-get install -y g++-9 - CXX=g++-9 conda_run python setup.py bdist_wheel + CXX=g++-9 conda_run python -m build --wheel --no-isolation elif [ -n "${UBUNTU_VERSION}" ] && [ -n "${CLANG_VERSION}" ]; then # Triton needs which surprisingly is not available with clang-9 toolchain add-apt-repository -y ppa:ubuntu-toolchain-r/test apt-get install -y g++-9 - CXX=g++-9 conda_run python setup.py bdist_wheel + CXX=g++-9 conda_run python -m build --wheel --no-isolation else - conda_run python setup.py bdist_wheel + conda_run python -m build --wheel --no-isolation fi # Copy the wheel to /opt for multi stage docker builds diff --git a/.ci/docker/requirements-ci.txt b/.ci/docker/requirements-ci.txt index d4bdd9b2a9cb..0f4a3fb9e47e 100644 --- a/.ci/docker/requirements-ci.txt +++ b/.ci/docker/requirements-ci.txt @@ -10,6 +10,11 @@ boto3==1.35.42 #Pinned versions: 1.19.12, 1.16.34 #test that import: +build +#Description: A simple, correct Python build frontend. +#Pinned versions: +#test that import: + click #Description: Command Line Interface Creation Kit #Pinned versions: @@ -381,7 +386,7 @@ dataclasses_json==0.6.7 #Pinned versions: 0.6.7 #test that import: -cmake==4.0.0 +cmake==3.31.6 #Description: required for building tlparse==0.3.30 diff --git a/.ci/manywheel/build_common.sh b/.ci/manywheel/build_common.sh index 4c268befb30e..b84268fd1289 100644 --- a/.ci/manywheel/build_common.sh +++ b/.ci/manywheel/build_common.sh @@ -142,7 +142,7 @@ time CMAKE_ARGS=${CMAKE_ARGS[@]} \ EXTRA_CAFFE2_CMAKE_FLAGS=${EXTRA_CAFFE2_CMAKE_FLAGS[@]} \ BUILD_LIBTORCH_CPU_WITH_DEBUG=$BUILD_DEBUG_INFO \ USE_NCCL=${USE_NCCL} USE_RCCL=${USE_RCCL} USE_KINETO=${USE_KINETO} \ - python setup.py bdist_wheel -d /tmp/$WHEELHOUSE_DIR + python -m build --wheel --no-isolation --outdir /tmp/$WHEELHOUSE_DIR echo "Finished setup.py bdist at $(date)" # Build libtorch packages diff --git a/.ci/pytorch/build.sh b/.ci/pytorch/build.sh index 65f97389324a..cd541bba6b25 100755 --- a/.ci/pytorch/build.sh +++ b/.ci/pytorch/build.sh @@ -261,13 +261,13 @@ else WERROR=1 python setup.py clean - WERROR=1 python setup.py bdist_wheel + WERROR=1 python -m build --wheel --no-isolation else python setup.py clean if [[ "$BUILD_ENVIRONMENT" == *xla* ]]; then source .ci/pytorch/install_cache_xla.sh fi - python setup.py bdist_wheel + python -m build --wheel --no-isolation fi pip_install_whl "$(echo dist/*.whl)" diff --git a/.ci/pytorch/macos-build.sh b/.ci/pytorch/macos-build.sh index d7447e7d4858..c01efda11ea6 100755 --- a/.ci/pytorch/macos-build.sh +++ b/.ci/pytorch/macos-build.sh @@ -36,11 +36,11 @@ fi print_cmake_info if [[ ${BUILD_ENVIRONMENT} == *"distributed"* ]]; then # Needed for inductor benchmarks, as lots of HF networks make `torch.distribtued` calls - USE_DISTRIBUTED=1 USE_OPENMP=1 WERROR=1 python setup.py bdist_wheel + USE_DISTRIBUTED=1 USE_OPENMP=1 WERROR=1 python -m build --wheel --no-isolation else # Explicitly set USE_DISTRIBUTED=0 to align with the default build config on mac. This also serves as the sole CI config that tests # that building with USE_DISTRIBUTED=0 works at all. See https://github.com/pytorch/pytorch/issues/86448 - USE_DISTRIBUTED=0 USE_OPENMP=1 MACOSX_DEPLOYMENT_TARGET=11.0 WERROR=1 BUILD_TEST=OFF USE_PYTORCH_METAL=1 python setup.py bdist_wheel --plat-name macosx_11_0_arm64 + USE_DISTRIBUTED=0 USE_OPENMP=1 MACOSX_DEPLOYMENT_TARGET=11.0 WERROR=1 BUILD_TEST=OFF USE_PYTORCH_METAL=1 python -m build --wheel --no-isolation -C--build-option=--plat-name=macosx_11_0_arm64 fi if which sccache > /dev/null; then print_sccache_stats diff --git a/.ci/pytorch/test.sh b/.ci/pytorch/test.sh index 724ba3792c1e..74fc47f421eb 100755 --- a/.ci/pytorch/test.sh +++ b/.ci/pytorch/test.sh @@ -1383,7 +1383,7 @@ EOF pip3 install -r requirements.txt # shellcheck source=./common-build.sh source "$(dirname "${BASH_SOURCE[0]}")/common-build.sh" - python setup.py bdist_wheel --bdist-dir="base_bdist_tmp" --dist-dir="base_dist" + python -m build --wheel --no-isolation -C--build-option=--bdist-dir="base_bdist_tmp" --outdir "base_dist" python -mpip install base_dist/*.whl echo "::endgroup::" diff --git a/.ci/pytorch/win-test-helpers/build_pytorch.bat b/.ci/pytorch/win-test-helpers/build_pytorch.bat index 7ceb425ce2d1..03db27847c1d 100644 --- a/.ci/pytorch/win-test-helpers/build_pytorch.bat +++ b/.ci/pytorch/win-test-helpers/build_pytorch.bat @@ -129,7 +129,7 @@ if "%USE_CUDA%"=="1" ( :: Print all existing environment variable for debugging set -python setup.py bdist_wheel +python -m build --wheel --no-isolation if errorlevel 1 goto fail if not errorlevel 0 goto fail sccache --show-stats diff --git a/.ci/pytorch/windows/arm64/build_pytorch.bat b/.ci/pytorch/windows/arm64/build_pytorch.bat index 3363a2d08846..b5c2ef65b84a 100644 --- a/.ci/pytorch/windows/arm64/build_pytorch.bat +++ b/.ci/pytorch/windows/arm64/build_pytorch.bat @@ -48,7 +48,7 @@ sccache --zero-stats sccache --show-stats :: Call PyTorch build script -python setup.py bdist_wheel -d "%PYTORCH_FINAL_PACKAGE_DIR%" +python -m build --wheel --no-isolation --outdir "%PYTORCH_FINAL_PACKAGE_DIR%" :: show sccache stats sccache --show-stats diff --git a/.ci/pytorch/windows/internal/setup.bat b/.ci/pytorch/windows/internal/setup.bat index 71056540464c..34a5140cb1ee 100644 --- a/.ci/pytorch/windows/internal/setup.bat +++ b/.ci/pytorch/windows/internal/setup.bat @@ -86,7 +86,7 @@ copy /Y "%LIBTORCH_PREFIX%-%PYTORCH_BUILD_VERSION%.zip" "%PYTORCH_FINAL_PACKAGE_ goto build_end :pytorch -%PYTHON_EXEC% setup.py bdist_wheel -d "%PYTORCH_FINAL_PACKAGE_DIR%" +%PYTHON_EXEC% -m build --wheel --no-isolation --outdir "%PYTORCH_FINAL_PACKAGE_DIR%" :build_end IF ERRORLEVEL 1 exit /b 1 diff --git a/.ci/wheel/build_wheel.sh b/.ci/wheel/build_wheel.sh index b90e6f38e911..0e6c7a3235ac 100755 --- a/.ci/wheel/build_wheel.sh +++ b/.ci/wheel/build_wheel.sh @@ -197,11 +197,11 @@ export USE_QNNPACK=OFF export BUILD_TEST=OFF pushd "$pytorch_rootdir" -echo "Calling setup.py bdist_wheel at $(date)" +echo "Calling -m build --wheel --no-isolation at $(date)" -python setup.py bdist_wheel -d "$whl_tmp_dir" +python -m build --wheel --no-isolation --outdir "$whl_tmp_dir" -echo "Finished setup.py bdist_wheel at $(date)" +echo "Finished -m build --wheel --no-isolation at $(date)" if [[ $package_type != 'libtorch' ]]; then echo "delocating wheel dependencies" diff --git a/.github/requirements/pip-requirements-macOS.txt b/.github/requirements/pip-requirements-macOS.txt index 224835188d87..85ae4e015d20 100644 --- a/.github/requirements/pip-requirements-macOS.txt +++ b/.github/requirements/pip-requirements-macOS.txt @@ -1,4 +1,5 @@ boto3==1.35.42 +build==1.2.2.post1 cmake==3.27.* expecttest==0.3.0 fbscribelogger==0.1.7 diff --git a/test/cpp_extensions/python_agnostic_extension/test/test_python_agnostic.py b/test/cpp_extensions/python_agnostic_extension/test/test_python_agnostic.py index a64ddc8e440e..f0597191ea9b 100644 --- a/test/cpp_extensions/python_agnostic_extension/test/test_python_agnostic.py +++ b/test/cpp_extensions/python_agnostic_extension/test/test_python_agnostic.py @@ -24,7 +24,7 @@ def setUpClass(cls): shutil.rmtree(cls.dist_dir) # Build the wheel - wheel_cmd = [sys.executable, "setup.py", "bdist_wheel"] + wheel_cmd = [sys.executable, "-m", "build", "--wheel", "--no-isolation"] return_code = shell(wheel_cmd, cwd=cls.extension_root, env=os.environ) if return_code != 0: raise RuntimeError("python_agnostic bdist_wheel failed to build") @@ -32,7 +32,7 @@ def setUpClass(cls): @onlyCUDA @unittest.skipIf(not IS_LINUX, "test requires linux tools ldd and nm") def test_extension_is_python_agnostic(self, device): - # For this test, run_test.py will call `python setup.py bdist_wheel` in the + # For this test, run_test.py will call `python -m build --wheel --no-isolation` in the # cpp_extensions/python_agnostic_extension folder, where the extension and # setup calls specify py_limited_api to `True`. To approximate that the # extension is indeed python agnostic, we test diff --git a/test/run_test.py b/test/run_test.py index 8a5861ba251f..051168cce47b 100755 --- a/test/run_test.py +++ b/test/run_test.py @@ -842,7 +842,7 @@ def _test_cpp_extensions_aot(test_directory, options, use_ninja): "--root", "./install", ] - wheel_cmd = [sys.executable, "setup.py", "bdist_wheel"] + wheel_cmd = [sys.executable, "-m", "build", "--wheel", "--no-isolation"] return_code = shell(install_cmd, cwd=cpp_extensions_test_dir, env=shell_env) if return_code != 0: return return_code diff --git a/tools/packaging/build_wheel.py b/tools/packaging/build_wheel.py index 10c4516a3280..dad2d8084967 100644 --- a/tools/packaging/build_wheel.py +++ b/tools/packaging/build_wheel.py @@ -20,7 +20,6 @@ logger.setLevel(logging.INFO) ROOT_PATH = Path(__file__).absolute().parent.parent.parent -SETUP_PY_PATH = ROOT_PATH / "setup.py" REQUIREMENTS_PATH = ROOT_PATH / "requirements.txt" PYPROJECT_TOML_PATH = ROOT_PATH / "pyproject.toml" @@ -143,18 +142,27 @@ class Builder: def __init__(self, interpreter: str) -> None: self.interpreter = interpreter - def setup_py(self, cmd_args: list[str]) -> bool: + def build_wheel(self, destination: str) -> bool: + logger.info("Running bdist_wheel -d %s", destination) return ( - run_cmd([self.interpreter, str(SETUP_PY_PATH), *cmd_args]).returncode == 0 + run_cmd( + [ + self.interpreter, + "-m", + "build", + "--wheel", + "--no-isolation", + "--outdir", + destination, + str(ROOT_PATH), + ] + ).returncode + == 0 ) - def bdist_wheel(self, destination: str) -> bool: - logger.info("Running bdist_wheel -d %s", destination) - return self.setup_py(["bdist_wheel", "-d", destination]) - def clean(self) -> bool: logger.info("Running clean") - return self.setup_py(["clean"]) + return run_cmd([self.interpreter, "setup.py", "clean"]).returncode == 0 def install_requirements(self) -> None: logger.info("Installing requirements") @@ -234,7 +242,7 @@ def main() -> None: start_time = time.time() - builder.bdist_wheel(args.destination) + builder.build_wheel(args.destination) end_time = time.time()