diff --git a/docs/html/cli/pip_install.rst b/docs/html/cli/pip_install.rst
index 6b4d3b1a2ba..6900499a763 100644
--- a/docs/html/cli/pip_install.rst
+++ b/docs/html/cli/pip_install.rst
@@ -490,18 +490,20 @@ You can install local projects by specifying the project path to pip:
py -m pip install path/to/SomeProject
-During regular installation, pip will copy the entire project directory to a
-temporary location and install from there. The exception is that pip will
-exclude .tox and .nox directories present in the top level of the project from
-being copied. This approach is the cause of several performance and correctness
-issues, so it is planned that pip 21.3 will change to install directly from the
-local project directory. Depending on the build backend used by the project,
-this may generate secondary build artifacts in the project directory, such as
-the ``.egg-info`` and ``build`` directories in the case of the setuptools
-backend.
-
-To opt in to the future behavior, specify the ``--use-feature=in-tree-build``
-option in pip's command line.
+.. note::
+
+ Depending on the build backend used by the project, this may generate
+ secondary build artifacts in the project directory, such as the
+ ``.egg-info`` and ``build`` directories in the case of the setuptools
+ backend.
+
+ Pip has a legacy behaviour that copies the entire project directory to a
+ temporary location and installs from there. This approach was the cause of
+ several performance and correctness issues, so it is now disabled by
+ default, and it is planned that pip 22.1 will remove it.
+
+ To opt in to the legacy behavior, specify the
+ ``--use-deprecated=out-of-tree-build`` option in pip's command line.
.. _`editable-installs`:
diff --git a/news/10495.removal.rst b/news/10495.removal.rst
new file mode 100644
index 00000000000..9b5d2256408
--- /dev/null
+++ b/news/10495.removal.rst
@@ -0,0 +1,3 @@
+In-tree builds are now the default. ``--use-feature=in-tree-build`` is now
+ignored. ``--use-deprecated=out-of-tree-build`` may be used temporarily to ease
+the transition.
diff --git a/src/pip/_internal/cli/cmdoptions.py b/src/pip/_internal/cli/cmdoptions.py
index b4f0f83c679..efe209adc9c 100644
--- a/src/pip/_internal/cli/cmdoptions.py
+++ b/src/pip/_internal/cli/cmdoptions.py
@@ -961,7 +961,7 @@ def check_list_path_option(options: Values) -> None:
metavar="feature",
action="append",
default=[],
- choices=["legacy-resolver"],
+ choices=["legacy-resolver", "out-of-tree-build"],
help=("Enable deprecated functionality, that will be removed in the future."),
)
diff --git a/src/pip/_internal/cli/req_command.py b/src/pip/_internal/cli/req_command.py
index 4129bf7e14c..c224bd276e2 100644
--- a/src/pip/_internal/cli/req_command.py
+++ b/src/pip/_internal/cli/req_command.py
@@ -34,6 +34,7 @@
from pip._internal.req.req_tracker import RequirementTracker
from pip._internal.resolution.base import BaseResolver
from pip._internal.self_outdated_check import pip_self_version_check
+from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.temp_dir import (
TempDirectory,
TempDirectoryTypeRegistry,
@@ -260,6 +261,20 @@ def make_requirement_preparer(
"fast-deps has no effect when used with the legacy resolver."
)
+ in_tree_build = "out-of-tree-build" not in options.deprecated_features_enabled
+ if "in-tree-build" in options.features_enabled:
+ deprecated(
+ reason="In-tree builds are now the default.",
+ replacement="to remove the --use-feature=in-tree-build flag",
+ gone_in="22.1",
+ )
+ if "out-of-tree-build" in options.deprecated_features_enabled:
+ deprecated(
+ reason="Out-of-tree builds are deprecated.",
+ replacement=None,
+ gone_in="22.1",
+ )
+
return RequirementPreparer(
build_dir=temp_build_dir_path,
src_dir=options.src_dir,
@@ -272,7 +287,7 @@ def make_requirement_preparer(
require_hashes=options.require_hashes,
use_user_site=use_user_site,
lazy_wheel=lazy_wheel,
- in_tree_build="in-tree-build" in options.features_enabled,
+ in_tree_build=in_tree_build,
)
@classmethod
diff --git a/src/pip/_internal/operations/prepare.py b/src/pip/_internal/operations/prepare.py
index 67ef9dd8313..ccf034eb5a0 100644
--- a/src/pip/_internal/operations/prepare.py
+++ b/src/pip/_internal/operations/prepare.py
@@ -35,7 +35,6 @@
from pip._internal.network.session import PipSession
from pip._internal.req.req_install import InstallRequirement
from pip._internal.req.req_tracker import RequirementTracker
-from pip._internal.utils.deprecation import deprecated
from pip._internal.utils.filesystem import copy2_fixed
from pip._internal.utils.hashes import Hashes, MissingHashes
from pip._internal.utils.logging import indent_log
@@ -197,19 +196,9 @@ def unpack_url(
#
# As further cleanup, _copy_source_tree and accompanying tests can
# be removed.
+ #
+ # TODO when use-deprecated=out-of-tree-build is removed
if link.is_existing_dir():
- deprecated(
- reason=(
- "pip copied the source tree into a temporary directory "
- "before building it. This is changing so that packages "
- "are built in-place "
- 'within the original source tree ("in-tree build").'
- ),
- replacement=None,
- gone_in="21.3",
- feature_flag="in-tree-build",
- issue=7555,
- )
if os.path.isdir(location):
rmtree(location)
_copy_source_tree(link.file_path, location)
diff --git a/tests/functional/test_install.py b/tests/functional/test_install.py
index 3af75cb5639..d6ec8a0a4fc 100644
--- a/tests/functional/test_install.py
+++ b/tests/functional/test_install.py
@@ -587,7 +587,7 @@ def test_install_from_local_directory_with_symlinks_to_directories(script, data)
Test installing from a local directory containing symlinks to directories.
"""
to_install = data.packages.joinpath("symlinks")
- result = script.pip("install", to_install)
+ result = script.pip("install", "--use-deprecated=out-of-tree-build", to_install)
pkg_folder = script.site_packages / "symlinks"
dist_info_folder = script.site_packages / "symlinks-0.1.dev0.dist-info"
result.did_create(pkg_folder)
@@ -597,10 +597,10 @@ def test_install_from_local_directory_with_symlinks_to_directories(script, data)
@pytest.mark.usefixtures("with_wheel")
def test_install_from_local_directory_with_in_tree_build(script, data):
"""
- Test installing from a local directory with --use-feature=in-tree-build.
+ Test installing from a local directory with default in tree build.
"""
to_install = data.packages.joinpath("FSPkg")
- args = ["install", "--use-feature=in-tree-build", to_install]
+ args = ["install", to_install]
in_tree_build_dir = to_install / "build"
assert not in_tree_build_dir.exists()