Define provisional %pyproject_build_lib

This commit is contained in:
Miro Hrončok 2021-12-08 11:07:48 +01:00
parent c80fe03b9b
commit 55905e4681
7 changed files with 176 additions and 1 deletions

View File

@ -303,6 +303,71 @@ These arguments are still required:
Multiple subpackages are generated when multiple names are provided.
PROVISIONAL: Importing just-built (extension) modules in %build
---------------------------------------------------------------
Sometimes, it is desired to be able to import the *just-built* extension modules
in the `%build` section, e.g. to build the documentation with Sphinx.
%build
%pyproject_wheel
... build the docs here ...
With pure Python packages, it might be possible to set `PYTHONPATH=${PWD}` or `PYTHONPATH=${PWD}/src`.
However, it is a bit more complicated with extension modules.
The location of just-built modules might differ depending on Python version, architecture, pip version.
Hence, the macro `%{pyproject_build_lib}` exists to be used like this:
%build
%pyproject_wheel
PYTHONPATH=%{pyproject_build_lib} ... build the docs here ...
This macro is currently **provisional** and the behavior might change.
The `%{pyproject_build_lib}` macro expands to an Shell `$(...)` expression and does not work when put into single quotes (`'`).
Depending on the pip version, the expanded value will differ:
### New pip 21.3+ with in-tree-build (Fedora 36+)
Always use the macro from the same directory where you called `%pyproject_wheel` from.
The value will expand to something like:
* `/builddir/build/BUILD/%{name}-%{version}/build/lib.linux-x86_64-3.10` for wheels with extension modules
* `/builddir/build/BUILD/%{name}-%{version}/build/lib` for pure Python wheels
If multiple wheels were built from the same directory,
some pure Python and some with extension modules,
the expanded value will be combined with `:`:
* `/builddir/build/BUILD/%{name}-%{version}/build/lib.linux-x86_64-3.10:/builddir/build/BUILD/%{name}-%{version}/build/lib`
If multiple wheels were built from different directories,
the value will differ depending on the current directory.
### Older pip with out-of-tree-build (Fedora 34, 35, and EL 9)
The value will expand to something like:
* `/builddir/build/BUILD/%{name}-%{version}/.pyproject-builddir/pip-req-build-xxxxxxxx/build/lib.linux-x86_64-3.10` for wheels with extension modules
* `/builddir/build/BUILD/%{name}-%{version}/.pyproject-builddir/pip-req-build-xxxxxxxx/build/lib` for pure Python wheels
Note that the exact value is **not stable** between builds
(the `xxxxxxxx` part is randomly generated,
neither you should consider the `.pyproject-builddir` directory to remain stable).
If multiple wheels are built,
the expanded value will always be combined with `:` regardless of the current directory, e.g.:
* `/builddir/build/BUILD/%{name}-%{version}/.pyproject-builddir/pip-req-build-xxxxxxxx/build/lib.linux-x86_64-3.10:/builddir/build/BUILD/%{name}-%{version}/.pyproject-builddir/pip-req-build-yyyyyyyy/build/lib.linux-x86_64-3.10:/builddir/build/BUILD/%{name}-%{version}/.pyproject-builddir/pip-req-build-zzzzzzzz/build/lib`
**Note:** If you manage to build some wheels with in-tree-build and some with out-of-tree-build option,
the expanded value will contain all relevant directories.
Limitations
-----------

View File

@ -28,6 +28,25 @@ CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}" LDFLAGS="${LDFLAGS:-${RPM_LD_FLAGS}}" TMPDI
}
%pyproject_build_lib %{expand:\\\
$(
pyproject_build_lib=()
if [ -d build/lib.%{python3_platform}-%{python3_version} ]; then
pyproject_build_lib+=( "${PWD}/build/lib.%{python3_platform}-%{python3_version}" )
fi
if [ -d build/lib ]; then
pyproject_build_lib+=( "${PWD}/build/lib" )
fi
for directory in $(find "%{_pyproject_builddir}" -type d -wholename "%{_pyproject_builddir}/pip-req-build-*/build/lib.%{python3_platform}-%{python3_version}" 2>/dev/null); do
pyproject_build_lib+=( "${directory}" )
done
for directory in $(find "%{_pyproject_builddir}" -type d -wholename "%{_pyproject_builddir}/pip-req-build-*/build/lib" 2>/dev/null); do
pyproject_build_lib+=( "${directory}" )
done
echo $(IFS=:; echo "${pyproject_build_lib[*]}")
)}
%pyproject_install() %{expand:\\\
specifier=$(ls %{_pyproject_wheeldir}/*.whl | xargs basename --multiple | sed -E 's/([^-]+)-([^-]+)-.+\\\.whl/\\\1==\\\2/')
TMPDIR="%{_pyproject_builddir}" %{__python3} -m pip install --root %{buildroot} --no-deps --disable-pip-version-check --progress-bar off --verbose --ignore-installed --no-warn-script-location --no-index --no-cache-dir --find-links %{_pyproject_wheeldir} $specifier

View File

@ -6,7 +6,7 @@ License: MIT
# Keep the version at zero and increment only release
Version: 0
Release: 50%{?dist}
Release: 51%{?dist}
# Macro files
Source001: macros.pyproject
@ -54,6 +54,7 @@ Requires: python-srpm-macros
Requires: python3-rpm-macros
# We use the following tools outside of coreutils
Requires: /usr/bin/find
Requires: /usr/bin/sed
%description
@ -115,6 +116,9 @@ export HOSTNAME="rpmbuild" # to speedup tox in network-less mock, see rhbz#1856
%license LICENSE
%changelog
* Wed Dec 08 2021 Miro Hrončok <mhroncok@redhat.com> - 0-51
- Define provisional %%pyproject_build_lib
* Mon Nov 1 2021 Gordon Messmer <gordon.messmer@gmail.com> - 0-50
- Improve handling of > operator, preventing post-release from satisfying most rpm requirements
- Improve handling of < operator, preventing pre-release from satisfying rpm requirement

67
tests/double-install.spec Normal file
View File

@ -0,0 +1,67 @@
Name: double-install
Version: 0
Release: 0%{?dist}
Summary: Install 2 wheels
License: BSD and MIT
%global markupsafe_version 2.0.1
%global tldr_version 0.4.4
Source1: https://github.com/pallets/markupsafe/archive/%{markupsafe_version}/MarkupSafe-%{markupsafe_version}.tar.gz
Source2: %{pypi_source tldr %{tldr_version}}
BuildRequires: gcc
BuildRequires: python3-devel
%description
This package tests that we can build and install 2 wheels at once.
One of them is "noarch" and one has an extension module.
%prep
%setup -Tc
tar xf %{SOURCE1}
tar xf %{SOURCE2}
%generate_buildrequires
cd markupsafe-%{markupsafe_version}
%pyproject_buildrequires
cd ../tldr-%{tldr_version}
%pyproject_buildrequires
cd ..
%build
cd markupsafe-%{markupsafe_version}
%pyproject_wheel
cd ../tldr-%{tldr_version}
%pyproject_wheel
cd ..
%install
# This should install both the wheels:
%pyproject_install
#pyproject_save_files is not possible with 2 dist-infos
%check
# Internal check for the value of %%{pyproject_build_lib}
%if 0%{?fedora} >= 36 || 0%{?rhel} >= 10
cd markupsafe-%{markupsafe_version}
test "%{pyproject_build_lib}" == "%{_builddir}/%{buildsubdir}/markupsafe-%{markupsafe_version}/build/lib.%{python3_platform}-%{python3_version}"
cd ../tldr-%{tldr_version}
test "%{pyproject_build_lib}" == "%{_builddir}/%{buildsubdir}/tldr-%{tldr_version}/build/lib"
cd ..
%else
for dir in . markupsafe-%{markupsafe_version} tldr-%{tldr_version}; do
(cd $dir && test "%{pyproject_build_lib}" == "$(echo %{_pyproject_builddir}/pip-req-build-*/build/lib.%{python3_platform}-%{python3_version}):$(echo %{_pyproject_builddir}/pip-req-build-*/build/lib)")
done
%endif
%files
%{_bindir}/tldr*
%pycached %{python3_sitelib}/tldr.py
%{python3_sitelib}/tldr-%{tldr_version}.dist-info/
%{python3_sitearch}/MarkupSafe-%{markupsafe_version}.dist-info/
%{python3_sitearch}/markupsafe/

View File

@ -42,6 +42,9 @@ Summary: %{summary}
%build
%pyproject_wheel
# Internal check that we can import the built extension modules from %%{pyproject_build_lib}
! %{python3} -c 'import _ldap'
PYTHONPATH=%{pyproject_build_lib} %{python3} -c 'import _ldap'
%install
@ -73,6 +76,13 @@ test -f %{buildroot}%{python3_sitearch}/_ldap.cpython-*.so
! grep -E '/site-packages/__pycache__$' %{pyproject_files}
! grep -E '/site-packages/__pycache__/$' %{pyproject_files}
# Internal check for the value of %%{pyproject_build_lib} in an archful package
%if 0%{?fedora} >= 36 || 0%{?rhel} >= 10
test "%{pyproject_build_lib}" == "%{_builddir}/%{buildsubdir}/build/lib.%{python3_platform}-%{python3_version}"
%else
test "%{pyproject_build_lib}" == "$(echo %{_pyproject_builddir}/pip-req-build-*/build/lib.%{python3_platform}-%{python3_version})"
%endif
%files -n python3-ldap -f %{pyproject_files}
%license LICENCE

View File

@ -76,6 +76,9 @@
- markupsafe:
dir: .
run: ./mocktest.sh python-markupsafe
- double_install:
dir: .
run: ./mocktest.sh double-install
- fake_requirements:
dir: .
run: ./mocktest.sh fake-requirements

View File

@ -41,6 +41,13 @@ head -n1 %{buildroot}%{_bindir}/%{name}.py | grep -E '#!\s*%{python3}\s+%{py3_sh
# Internal check for our macros: tests that direct_url.json file wasn't created
test ! -e %{buildroot}%{python3_sitelib}/*.dist-info/direct_url.json
# Internal check for the value of %%{pyproject_build_lib} in a noarch package
%if 0%{?fedora} >= 36 || 0%{?rhel} >= 10
test "%{pyproject_build_lib}" == "${PWD}/build/lib"
%else
test "%{pyproject_build_lib}" == "$(echo %{_pyproject_builddir}/pip-req-build-*/build/lib)"
%endif
%files -f %pyproject_files
%license LICENSE
%doc README.md