diff --git a/CHANGES/1591.packaging.rst b/CHANGES/1591.packaging.rst new file mode 100644 index 000000000..2cd0a3c28 --- /dev/null +++ b/CHANGES/1591.packaging.rst @@ -0,0 +1,14 @@ +Starting this version, when building the wheels is happening +in an automatically created temporary directory, the build +backend makes an effort to normalize the respective file +system path to a deterministic source checkout directory. + +-- by :user:`webknjaz` + +It does so by injecting the ``-ffile-prefix-map`` compiler +option into the ``CFLAGS`` environment variable as suggested +by known `reproducible build practices +`__. + +The effect is that downstreams will get more reproducible +build results. diff --git a/packaging/pep517_backend/_backend.py b/packaging/pep517_backend/_backend.py index b7181d414..e9e4fb731 100644 --- a/packaging/pep517_backend/_backend.py +++ b/packaging/pep517_backend/_backend.py @@ -261,7 +261,7 @@ def _exclude_dir_path( @contextmanager -def _in_temporary_directory(src_dir: Path) -> _c.Iterator[None]: +def _in_temporary_directory(src_dir: Path) -> _c.Iterator[Path]: with TemporaryDirectory(prefix='.tmp-yarl-pep517-') as tmp_dir: tmp_dir_path = Path(tmp_dir) root_tmp_dir_path = tmp_dir_path.parent @@ -276,7 +276,7 @@ def _in_temporary_directory(src_dir: Path) -> _c.Iterator[None]: symlinks=True, ) os.chdir(tmp_src_dir) - yield + yield tmp_src_dir @contextmanager @@ -356,12 +356,13 @@ def maybe_prebuild_c_extensions( stacklevel=999, ) + original_src_dir = Path.cwd().resolve() build_dir_ctx = ( nullcontext() if build_inplace - else _in_temporary_directory(src_dir=Path.cwd().resolve()) + else _in_temporary_directory(src_dir=original_src_dir) ) - with build_dir_ctx: + with build_dir_ctx as tmp_build_dir: config = _get_local_cython_config() cythonize_args = _make_cythonize_cli_args_from_config( @@ -371,6 +372,8 @@ def maybe_prebuild_c_extensions( with _patched_cython_env( config['env'], cython_line_tracing_requested=cython_line_tracing_requested, + original_source_directory=original_src_dir, + temporary_build_directory=tmp_build_dir, ): _cythonize_cli_cmd(cythonize_args) # type: ignore[no-untyped-call] with patched_distutils_cmd_install(): diff --git a/packaging/pep517_backend/_cython_configuration.py b/packaging/pep517_backend/_cython_configuration.py index 61b32367e..e4e53c363 100644 --- a/packaging/pep517_backend/_cython_configuration.py +++ b/packaging/pep517_backend/_cython_configuration.py @@ -184,6 +184,8 @@ def patched_env( env: dict[str, str], *, cython_line_tracing_requested: bool, + original_source_directory: Path | None = None, + temporary_build_directory: Path | None = None, ) -> _c.Iterator[None]: """Temporary set given env vars. @@ -224,6 +226,16 @@ def patched_env( '-DNDEBUG', # disable assertions ) ), + *( + # In-tree mode: + () + if temporary_build_directory is None + # Temporary build directory mode: + else ( + '-ffile-prefix-map=' + f'{temporary_build_directory!s}={original_source_directory!s}', + ) + ), # Finally, append the user-set env var, ensuring its top priority: orig_env.get('CFLAGS', ''), # Last thing, strip spaces caused by empty leading/trailing flags: