Manual byte compilation
When byte compiling a .py file, python embeds a magic number in the byte compiled files that correspond to the runtime. Files in %{python?_sitelib}
and %{python?_sitearch}
must correspond to the runtime for which they were built. For instance, a pure python module compiled for the 3.4 runtime needs to be below %{_usr}/lib/python3.4/site-packages
The brp-python-bytecompile
script tries to figure this out for you. The script determines which interpreter to use when byte compiling the module by following these steps:
- what directory is the module installed in? If it's
/usr/lib{,64}/pythonX.Y
, thenpythonX.Y
is used to byte compile the module. IfpythonX.Y
is not installed, then an error is returned and the rpm build process will exit on an error so remember toBuildRequire
the proper python package. - by default the script interpreter defined in
%{__python}
is used to compile the modules outside of those directories. This defaults to/usr/bin/python
(that's Python 2.7 on Fedora). This only happens for backwards compatibility reasons.
If you have *.py
files outside of the /usr/lib(64)?/pythonX.Y/
directories, you MUST disable their automatic compilation. If you require those files to be byte compiled (e.g. it's an importable Python module) you can then compile them explicitly using the %py_byte_compile
macro.
Example for package that has both Python versions:
# Disable automatic compilation of Python files in extra directories %global _python_bytecompile_extra 0 # Buildrequire both python2 and python3 BuildRequires: python2-devel python3-devel %install # Installs a python2 private module into %{buildroot}%{_datadir}/mypackage/foo # and installs a python3 private module into %{buildroot}%{_datadir}/mypackage/bar make install DESTDIR=%{buildroot} # Manually invoke the python byte compile macro for each path that needs byte # compilation. %py_byte_compile %{__python2} %{buildroot}%{_datadir}/mypackage/foo %py_byte_compile %{__python3} %{buildroot}%{_datadir}/mypackage/bar
Note that this does not disable the compilation of files in /usr/lib(64)?/pythonX.Y/
.
The %py_byte_compile
macro takes two arguments. The first is the python interpreter to use for byte compiling. The second is a file or directory to byte compile. If the second argument is a directory, the macro will recursively byte compile any *.py file in the directory.
Manual byte compilation for Fedora 28 or earlier (including EPEL)
The script interpreter defined in %{__python}
is used to compile the modules outside of /usr/lib(64)?/pythonX.Y/
directories. This defaults to /usr/bin/python
(that's Python 2.7 on Fedora). If you need to compile the modules for python3, set it to /usr/bin/python3
instead:
%global __python %{__python3}
Doing this is useful when you have a python3 application that's installing a private module into its own directory. For instance, if the foobar application installs a module for use only by the command line application in %{_datadir}/foobar
. Since these files are not in one of the python3 library paths (ie. /usr/lib/python3.1
) you have to override %{__python}
to tell brp-python-bytecompile
to use the python3 interpreter for byte compiling.
These settings are enough to properly byte compile any package that builds python modules in %{python?_sitelib}
or %{python?_sitearch}
or builds for only a single python interpreter. However, if the application you're packaging needs to build with both python2 and python3 and install into a private module directory (perhaps because it provides one utility written in python2 and a second utility written in python3) then you need to do this manually. Here's a sample spec file snippet that shows what to do:
# Turn off the brp-python-bytecompile script %undefine __brp_python_bytecompile # Buildrequire both python2 and python3 BuildRequires: python2-devel python3-devel [...] %install # Installs a python2 private module into %{buildroot}%{_datadir}/mypackage/foo # and installs a python3 private module into %{buildroot}%{_datadir}/mypackage/bar make install DESTDIR=%{buildroot} # Manually invoke the python byte compile macro for each path that needs byte # compilation. %py_byte_compile %{__python2} %{buildroot}%{_datadir}/mypackage/foo %py_byte_compile %{__python3} %{buildroot}%{_datadir}/mypackage/bar
Note that this does disable the compilation of files in /usr/lib(64)?/pythonX.Y/
.
In Fedora 27 or earlier, use %global __os_install_post %(echo '%{__os_install_post}' | sed -e 's!/usr/lib[^[:space:]]*/brp-python-bytecompilespace:.*$!!g')
instead of the %undefine
line above.