From e1bd214d259ddbea1545fdeea0be207b7fe38891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Mon, 1 Jul 2019 12:15:09 +0200 Subject: [PATCH 01/13] Move brp-python-bytecompile from rpm, so we can easily adapt it --- brp-python-bytecompile | 112 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100755 brp-python-bytecompile diff --git a/brp-python-bytecompile b/brp-python-bytecompile new file mode 100755 index 0000000..c06bdfa --- /dev/null +++ b/brp-python-bytecompile @@ -0,0 +1,112 @@ +#!/bin/bash +errors_terminate=$2 +extra=$3 + +# If using normal root, avoid changing anything. +if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then + exit 0 +fi + +# Figure out how deep we need to descend. We could pick an insanely high +# number and hope it's enough, but somewhere, somebody's sure to run into it. +depth=`(find "$RPM_BUILD_ROOT" -type f -name "*.py" -print0 ; echo /) | \ + xargs -0 -n 1 dirname | sed 's,[^/],,g' | sort -u | tail -n 1 | wc -c` +if [ -z "$depth" -o "$depth" -le "1" ]; then + exit 0 +fi + +function python_bytecompile() +{ + local options=$1 + local python_binary=$2 + local exclude=$3 + local python_libdir=$4 + local depth=$5 + local real_libdir=$6 + +cat << EOF | $python_binary $options +import compileall, sys, os, re + +python_libdir = "$python_libdir" +depth = $depth +real_libdir = "$real_libdir" +build_root = "$RPM_BUILD_ROOT" +exclude = r"$exclude" + +class Filter: + def search(self, path): + ret = not os.path.realpath(path).startswith(build_root) + if exclude: + ret = ret or re.search(exclude, path) + return ret + +sys.exit(not compileall.compile_dir(python_libdir, depth, real_libdir, force=1, rx=Filter(), quiet=1)) +EOF +} + +# .pyc/.pyo files embed a "magic" value, identifying the ABI version of Python +# bytecode that they are for. +# +# The files below RPM_BUILD_ROOT could be targeting multiple versions of +# python (e.g. a single build that emits several subpackages e.g. a +# python26-foo subpackage, a python31-foo subpackage etc) +# +# Support this by assuming that below each /usr/lib/python$VERSION/, all +# .pyc/.pyo files are to be compiled for /usr/bin/python$VERSION. +# +# For example, below /usr/lib/python2.6/, we're targeting /usr/bin/python2.6 +# and below /usr/lib/python3.1/, we're targeting /usr/bin/python3.1 + +shopt -s nullglob +for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/usr/lib(64)?/python[0-9]\.[0-9]$"`; +do + python_binary=/usr/bin/$(basename $python_libdir) + real_libdir=${python_libdir/$RPM_BUILD_ROOT/} + echo "Bytecompiling .py files below $python_libdir using $python_binary" + + # Generate normal (.pyc) byte-compiled files. + python_bytecompile "" "$python_binary" "" "$python_libdir" "$depth" "$real_libdir" + if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then + # One or more of the files had a syntax error + exit 1 + fi + + # Generate optimized (.pyo) byte-compiled files. + python_bytecompile "-O" "$python_binary" "" "$python_libdir" "$depth" "$real_libdir" + if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then + # One or more of the files had a syntax error + exit 1 + fi +done + + +# Handle other locations in the filesystem using the default python implementation +# if extra is set to 0, don't do this +if [ 0$extra -eq 0 ]; then + exit 0 +fi + +# If we don't have a default python interpreter, we cannot proceed +default_python=${1:-/usr/bin/python} +if [ ! -x "$default_python" ]; then + exit 0 +fi + +# Figure out if there are files to be bytecompiled with the default_python at all +# this prevents unnecessary default_python invocation +find "$RPM_BUILD_ROOT" -type f -name "*.py" | grep -Ev "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" || exit 0 + +# Generate normal (.pyc) byte-compiled files. +python_bytecompile "" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/" +if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then + # One or more of the files had a syntax error + exit 1 +fi + +# Generate optimized (.pyo) byte-compiled files. +python_bytecompile "-O" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/" +if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then + # One or more of the files had a syntax error + exit 1 +fi +exit 0 From e64ffd7f264d4172edbefad79535d7c966f36306 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Sat, 20 Jul 2019 08:08:26 +0200 Subject: [PATCH 02/13] Use compileall2 Python module for byte-compilation in brp-python-bytecompile --- brp-python-bytecompile | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index c06bdfa..fee0048 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -15,6 +15,14 @@ if [ -z "$depth" -o "$depth" -le "1" ]; then exit 0 fi +# This function now implements Python byte-compilation in two different ways: +# Python >= 3.4 uses a new module compileall2 - https://github.com/fedora-python/compileall2 +# Python < 3.4 (inc. Python 2) uses compileall module from stdlib with some hacks +# When we drop support for Python 2, we'd be able to use all compileall2 features like: +# - -s and -p options to manipulate with a path baked into pyc files instead of $real_libdir +# - -o 0 -o 1 to produce multiple files in one run - each with a different optimization level - instead of $options +# - removed useless $depth - both compileall and compileall2 are limited by sys.getrecursionlimit() +# These changes will make this script much simpler function python_bytecompile() { local options=$1 @@ -24,6 +32,26 @@ function python_bytecompile() local depth=$5 local real_libdir=$6 + python_version=$($python_binary -c "import sys; sys.stdout.write('{0.major}{0.minor}'.format(sys.version_info))") + + # + # Python 3.4 and higher + # + if [ "$python_version" -ge 34 ]; then + + [ ! -z $exclude ] && exclude="-x '$exclude'" + # /usr/lib/rpm/redhat/ contains compileall2 Python module + # -q disables verbose output + # -f forces the process to overwrite existing compiled files + # -x excludes paths defined by regex + # -e excludes symbolic links pointing outside the build root + # -x and -e together implements the same functionality as the Filter class below + PYTHONPATH=/usr/lib/rpm/redhat/ $python_binary $options -m compileall2 -q -f $exclude -d $real_libdir -e $RPM_BUILD_ROOT $python_libdir + else +# +# Python 3.3 and lower (incl. Python 2) +# + cat << EOF | $python_binary $options import compileall, sys, os, re @@ -42,6 +70,8 @@ class Filter: sys.exit(not compileall.compile_dir(python_libdir, depth, real_libdir, force=1, rx=Filter(), quiet=1)) EOF + +fi } # .pyc/.pyo files embed a "magic" value, identifying the ABI version of Python From 8f6bc2fd6ca40fc74f67f914f4109ed54ee63c5b Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Tue, 5 Nov 2019 09:40:12 +0100 Subject: [PATCH 03/13] Fix brp-python-bytecompile with the new features from compileall2 Resolves: rhbz#1595265 The problem this change is intended to solve is with how `real_libdir` is calculated. Let's assume we want to recursively byte-compile all `*.py` files in `/builddir/build/BUILDROOT/python-scales-1.0.9-250.fc32.x86_64/usr/lib/python3.8`. Then, `real_libdir` is this path without `$RPM_BUILD_ROOT` with the filename at the end which displays in the error message like this: ``` Bytecompiling .py files below /builddir/build/BUILDROOT/python-scales-1.0.9-250.fc32.x86_64/usr/lib/python3.8 using /usr/bin/python3.8 *** Error compiling '/builddir/build/BUILDROOT/python-scales-1.0.9-250.fc32.x86_64/usr/lib/python3.8/site-packages/greplin/bar.py'... File "/usr/lib/python3.8/bar.py", line 1 import sin from math ^ SyntaxError: invalid syntax ``` `/usr/lib/python3.8/bar.py` is obviously wrong. One of the new features of the `compileall2` module (which will be available in stdlib in Python 3.9) is that the path byte-compiled to `*.pyc` files is calculated for each file. This means that by using `-s` and `-p` we can strip `$RPM_BUILD_ROOT` and prepend `/` for each file individually which will fix the problem. ``` Bytecompiling .py files below /builddir/build/BUILDROOT/python-scales-1.0.9-250.fc32.x86_64/usr/lib/python3.8 using /usr/bin/python3.8 *** Error compiling '/builddir/build/BUILDROOT/python-scales-1.0.9-250.fc32.x86_64/usr/lib/python3.8/site-packages/greplin/bar.py'... File "/usr/lib/python3.8/site-packages/greplin/bar.py", line 1 import sin from math ^ SyntaxError: invalid syntax ``` This change has an effect only for Python >= 3.4. --- brp-python-bytecompile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index fee0048..ede435b 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -29,8 +29,8 @@ function python_bytecompile() local python_binary=$2 local exclude=$3 local python_libdir=$4 - local depth=$5 - local real_libdir=$6 + local depth=$5 # Not used for Python >= 3.4 + local real_libdir=$6 # Not used for Python >= 3.4 python_version=$($python_binary -c "import sys; sys.stdout.write('{0.major}{0.minor}'.format(sys.version_info))") @@ -46,7 +46,9 @@ function python_bytecompile() # -x excludes paths defined by regex # -e excludes symbolic links pointing outside the build root # -x and -e together implements the same functionality as the Filter class below - PYTHONPATH=/usr/lib/rpm/redhat/ $python_binary $options -m compileall2 -q -f $exclude -d $real_libdir -e $RPM_BUILD_ROOT $python_libdir + # -s strips $RPM_BUILD_ROOT from the path + # -p prepends the leading slash to the path to make it absolute + PYTHONPATH=/usr/lib/rpm/redhat/ $python_binary $options -m compileall2 -q -f $exclude -s $RPM_BUILD_ROOT -p / -e $RPM_BUILD_ROOT $python_libdir else # # Python 3.3 and lower (incl. Python 2) From fa7d708e3c06e24ce7de8ea49d69be5a2615df9c Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Wed, 22 Jan 2020 13:09:31 +0100 Subject: [PATCH 04/13] Use `-B` flag for Python when using compileall2 to not write pyc files The Python compileall2 module in /usr/lib/rpm/redhat/ can be executed by various different Python interpreters. We don't want to write several different `*.pyc` files to this location - in most cases, that's not possible, but somebody might run this as root. --- brp-python-bytecompile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index ede435b..ed1563b 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -48,7 +48,7 @@ function python_bytecompile() # -x and -e together implements the same functionality as the Filter class below # -s strips $RPM_BUILD_ROOT from the path # -p prepends the leading slash to the path to make it absolute - PYTHONPATH=/usr/lib/rpm/redhat/ $python_binary $options -m compileall2 -q -f $exclude -s $RPM_BUILD_ROOT -p / -e $RPM_BUILD_ROOT $python_libdir + PYTHONPATH=/usr/lib/rpm/redhat/ $python_binary -B $options -m compileall2 -q -f $exclude -s $RPM_BUILD_ROOT -p / -e $RPM_BUILD_ROOT $python_libdir else # # Python 3.3 and lower (incl. Python 2) From 229fd899ac20d25a66efb9c09841d0b0c5ece7c9 Mon Sep 17 00:00:00 2001 From: Tomas Orsava Date: Mon, 27 Jan 2020 13:29:41 +0100 Subject: [PATCH 05/13] brp-python-bytecompile: Prepare for 2 digit minor versions (e.g. 3.10) --- brp-python-bytecompile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index ed1563b..4727feb 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -90,7 +90,7 @@ fi # and below /usr/lib/python3.1/, we're targeting /usr/bin/python3.1 shopt -s nullglob -for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/usr/lib(64)?/python[0-9]\.[0-9]$"`; +for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/usr/lib(64)?/python[0-9]\.[0-9]+$"`; do python_binary=/usr/bin/$(basename $python_libdir) real_libdir=${python_libdir/$RPM_BUILD_ROOT/} From f77cb3e9dd9b452b19582a5765178e3a3ae8c084 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Wed, 20 May 2020 15:06:16 +0200 Subject: [PATCH 06/13] No more automagic Python bytecompilation (phase 3) --- brp-python-bytecompile | 41 +++++++++-------------------------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index 4727feb..f8ca447 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -1,6 +1,15 @@ #!/bin/bash errors_terminate=$2 + +# Usage of %_python_bytecompile_extra is not allowed anymore +# See: https://fedoraproject.org/wiki/Changes/No_more_automagic_Python_bytecompilation_phase_3 +# Therefore $1 ($default_python) is not needed and is invoked with "" by default. +# $default_python stays in the arguments for backward compatibility and $extra for the following check: extra=$3 +if [ 0$extra -eq 1 ]; then + echo -e "%_python_bytecompile_extra is discontinued, use %py_byte_compile instead.\nSee: https://fedoraproject.org/wiki/Changes/No_more_automagic_Python_bytecompilation_phase_3" >/dev/stderr + exit 1 +fi # If using normal root, avoid changing anything. if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then @@ -110,35 +119,3 @@ do exit 1 fi done - - -# Handle other locations in the filesystem using the default python implementation -# if extra is set to 0, don't do this -if [ 0$extra -eq 0 ]; then - exit 0 -fi - -# If we don't have a default python interpreter, we cannot proceed -default_python=${1:-/usr/bin/python} -if [ ! -x "$default_python" ]; then - exit 0 -fi - -# Figure out if there are files to be bytecompiled with the default_python at all -# this prevents unnecessary default_python invocation -find "$RPM_BUILD_ROOT" -type f -name "*.py" | grep -Ev "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" || exit 0 - -# Generate normal (.pyc) byte-compiled files. -python_bytecompile "" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/" -if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then - # One or more of the files had a syntax error - exit 1 -fi - -# Generate optimized (.pyo) byte-compiled files. -python_bytecompile "-O" $default_python "/bin/|/sbin/|/usr/lib(64)?/python[0-9]\.[0-9]|/usr/share/doc" "$RPM_BUILD_ROOT" "$depth" "/" -if [ $? -ne 0 -a 0$errors_terminate -ne 0 ]; then - # One or more of the files had a syntax error - exit 1 -fi -exit 0 From 437166cca727048be145b329ba53383f20b816c8 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Wed, 20 May 2020 15:06:26 +0200 Subject: [PATCH 07/13] Remove trailing whitespace --- brp-python-bytecompile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index f8ca447..eabc39a 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -94,7 +94,7 @@ fi # # Support this by assuming that below each /usr/lib/python$VERSION/, all # .pyc/.pyo files are to be compiled for /usr/bin/python$VERSION. -# +# # For example, below /usr/lib/python2.6/, we're targeting /usr/bin/python2.6 # and below /usr/lib/python3.1/, we're targeting /usr/bin/python3.1 From 8e9c3d8bbecf840e7463c8790c085b7c90fc881e Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Fri, 5 Jun 2020 08:59:16 +0200 Subject: [PATCH 08/13] Use compileall from stdlib for Python >= 3.9 All enhancements from compileall2 are merged in Python 3.9. --- brp-python-bytecompile | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index eabc39a..c6afd1e 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -24,14 +24,15 @@ if [ -z "$depth" -o "$depth" -le "1" ]; then exit 0 fi -# This function now implements Python byte-compilation in two different ways: -# Python >= 3.4 uses a new module compileall2 - https://github.com/fedora-python/compileall2 +# This function now implements Python byte-compilation in three different ways: +# Python >= 3.4 and < 3.9 uses a new module compileall2 - https://github.com/fedora-python/compileall2 # Python < 3.4 (inc. Python 2) uses compileall module from stdlib with some hacks # When we drop support for Python 2, we'd be able to use all compileall2 features like: # - -s and -p options to manipulate with a path baked into pyc files instead of $real_libdir # - -o 0 -o 1 to produce multiple files in one run - each with a different optimization level - instead of $options # - removed useless $depth - both compileall and compileall2 are limited by sys.getrecursionlimit() # These changes will make this script much simpler +# In Python >= 3.9, compileall2 was merged back to standard library (compileall) so we can use it directly again. function python_bytecompile() { local options=$1 @@ -43,10 +44,25 @@ function python_bytecompile() python_version=$($python_binary -c "import sys; sys.stdout.write('{0.major}{0.minor}'.format(sys.version_info))") + # + # Python 3.9 and higher + # + if [ "$python_version" -ge 39 ]; then + + [ ! -z $exclude ] && exclude="-x '$exclude'" + # -q disables verbose output + # -f forces the process to overwrite existing compiled files + # -x excludes paths defined by regex + # -e excludes symbolic links pointing outside the build root + # -x and -e together implements the same functionality as the Filter class below + # -s strips $RPM_BUILD_ROOT from the path + # -p prepends the leading slash to the path to make it absolute + $python_binary -B $options -m compileall -q -f $exclude -s $RPM_BUILD_ROOT -p / -e $RPM_BUILD_ROOT $python_libdir + # # Python 3.4 and higher # - if [ "$python_version" -ge 34 ]; then + elif [ "$python_version" -ge 34 ]; then [ ! -z $exclude ] && exclude="-x '$exclude'" # /usr/lib/rpm/redhat/ contains compileall2 Python module From b983c2118b85a734eae7e5f163611b9c4e90301e Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Thu, 16 Jul 2020 10:30:55 +0200 Subject: [PATCH 09/13] New opt-in possibility to fix byte-compilation reproducibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new script brp-fix-pyc-reproducibility creates an opt-in way of how to fix problems with the reproducibility of byte-compiled Python files. The script uses marshalparser [0] which currently doesn't provide solutions for all issues but can fix at least problems with reference flags. For more info see this Bugzilla [1]. If you want to use this new feature, you need to define `%py_reproducible_pyc_path` to specify a path you want to fix `.pyc` files in (recursively) and build-require /usr/bin/marshalparser. if you forget to build-require the parser. The error message is: ``` + /usr/lib/rpm/redhat/brp-python-bytecompile '' 1 0 Bytecompiling .py files below /builddir/build/BUILDROOT/tldr-0.5-2.fc33.x86_64/usr/lib/python3.9 using /usr/bin/python3.9 + /usr/lib/rpm/redhat/brp-fix-pyc-reproducibility /builddir/build/BUILDROOT/tldr-0.5-2.fc33.x86_64 ERROR: If %py_reproducible_pyc_path is defined, you have to also BuildRequire: /usr/bin/marshalparser ! error: Bad exit status from /var/tmp/rpm-tmp.UUJr4v (%install) ``` A build fails if the parser is not able to parse any of the `.pyc` files. And finally, if a build is properly configured it produces fixed `.pyc` files. Currently, `.pyc` files in the tldr package contain a lot of unused reference flags: ``` $ dnf install -y tldr $ marshalparser --unused /usr/lib/python3.9/site-packages/__pycache__/tldr.cpython-39.pyc … long output … 190 - Flag_ref(byte=9610, type='TYPE_SHORT_ASCII_INTERNED', content=b'init', usages=0) 191 - Flag_ref(byte=9633, type='TYPE_SHORT_ASCII_INTERNED', content=b'source', usages=0) 192 - Flag_ref(byte=9651, type='TYPE_SHORT_ASCII_INTERNED', content=b'argv', usages=0) 193 - Flag_ref(byte=9657, type='TYPE_SHORT_ASCII_INTERNED', content=b'print_help', usages=0) 194 - Flag_ref(byte=9669, type='TYPE_SHORT_ASCII_INTERNED', content=b'stderr', usages=0) 195 - Flag_ref(byte=9682, type='TYPE_SHORT_ASCII_INTERNED', content=b'parse_args', usages=0) 196 - Flag_ref(byte=9737, type='TYPE_SHORT_ASCII_INTERNED', content=b'encode', usages=0) 197 - Flag_ref(byte=9782, type='TYPE_SHORT_ASCII_INTERNED', content=b'parser', usages=0) 198 - Flag_ref(byte=9790, type='TYPE_SHORT_ASCII_INTERNED', content=b'options', usages=0) 199 - Flag_ref(byte=9799, type='TYPE_SHORT_ASCII_INTERNED', content=b'rest', usages=0) 200 - Flag_ref(byte=9821, type='TYPE_SHORT_ASCII_INTERNED', content=b'result', usages=0) 202 - Flag_ref(byte=10022, type='TYPE_SHORT_ASCII_INTERNED', content=b'__main__', usages=0) 203 - Flag_ref(byte=10102, type='TYPE_SHORT_ASCII_INTERNED', content=b'argparse', usages=0) 204 - Flag_ref(byte=10433, type='TYPE_SHORT_ASCII_INTERNED', content=b'__name__', usages=0) 205 - Flag_ref(byte=10463, type='TYPE_SHORT_ASCII_INTERNED', content=b'', usages=0) ``` This new feature fixes them: ``` $ marshalparser --unused /usr/lib/python3.9/site-packages/__pycache__/tldr.cpython-39.pyc ``` [0] https://github.com/fedora-python/marshalparser [1] https://bugzilla.redhat.com/show_bug.cgi?id=1686078 --- brp-fix-pyc-reproducibility | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 brp-fix-pyc-reproducibility diff --git a/brp-fix-pyc-reproducibility b/brp-fix-pyc-reproducibility new file mode 100644 index 0000000..4118d97 --- /dev/null +++ b/brp-fix-pyc-reproducibility @@ -0,0 +1,18 @@ +#!/bin/bash -e + +# If using normal root, avoid changing anything. +if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then + exit 0 +fi + +# Defined as %py_reproducible_pyc_path macro and passed here as +# the first command-line argument +path_to_fix=$1 + +# First, check that the parser is available: +if [ ! -x /usr/bin/marshalparser ]; then + echo "ERROR: If %py_reproducible_pyc_path is defined, you have to also BuildRequire: /usr/bin/marshalparser !" + exit 1 +fi + +find "$path_to_fix" -type f -name "*.pyc" | xargs /usr/bin/marshalparser --fix --overwrite From 71c410dfa916461e5ded386b8585a028e72e3337 Mon Sep 17 00:00:00 2001 From: Lumir Balhar Date: Thu, 23 Jul 2020 08:09:55 +0200 Subject: [PATCH 10/13] Disable Python hash seed randomization in brp-python-bytecompile This change should help with byte-compilation reproducibility: https://bugzilla.redhat.com/show_bug.cgi?id=1686078 --- brp-python-bytecompile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index c6afd1e..fbbd02b 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -114,6 +114,10 @@ fi # For example, below /usr/lib/python2.6/, we're targeting /usr/bin/python2.6 # and below /usr/lib/python3.1/, we're targeting /usr/bin/python3.1 +# Disable Python hash seed randomization +# This should help with byte-compilation reproducibility: https://bugzilla.redhat.com/show_bug.cgi?id=1686078 +export PYTHONHASHSEED=0 + shopt -s nullglob for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/usr/lib(64)?/python[0-9]\.[0-9]+$"`; do From a27bc6cc242e90f5daeaf6ee344d29c7192f97a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Sun, 29 Nov 2020 17:44:37 +0100 Subject: [PATCH 11/13] BRP Python Bytecompile: Also detect Python files in /app/lib/pythonX.Y This is needed for flatpaks. Alternatively, we could pass %{_prefix} as an argument to this script, but that could make things a tad more complicated. This solution is less general, but more pragmatic. See https://lists.fedoraproject.org/archives/list/devel@lists.fedoraproject.org/thread/4FBBB3C5E63VDNGUJRLLW27LPZ74SEJH/ --- brp-python-bytecompile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index fbbd02b..012e8b5 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -119,7 +119,7 @@ fi export PYTHONHASHSEED=0 shopt -s nullglob -for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/usr/lib(64)?/python[0-9]\.[0-9]+$"`; +for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/(usr|app)/lib(64)?/python[0-9]\.[0-9]+$"`; do python_binary=/usr/bin/$(basename $python_libdir) real_libdir=${python_libdir/$RPM_BUILD_ROOT/} From 4805d44fa0dc4adfdc66b50cbdd5f57fd73ad8e6 Mon Sep 17 00:00:00 2001 From: Kalev Lember Date: Wed, 10 Mar 2021 17:09:14 +0100 Subject: [PATCH 12/13] BRP Python Bytecompile: Avoid hardcoding /usr/bin prefix for python Avoid using the full path and instead rely on PATH being correctly set up to find the executable. This fixes byte compilation for python2.7 when doing flatpak module builds where python2.7 can be in either /usr/bin or /app/bin, depending on how it's compiled. --- brp-python-bytecompile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index 012e8b5..ead7022 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -121,7 +121,7 @@ export PYTHONHASHSEED=0 shopt -s nullglob for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/(usr|app)/lib(64)?/python[0-9]\.[0-9]+$"`; do - python_binary=/usr/bin/$(basename $python_libdir) + python_binary=$(basename $python_libdir) real_libdir=${python_libdir/$RPM_BUILD_ROOT/} echo "Bytecompiling .py files below $python_libdir using $python_binary" From c487f82ef751f1277a59a80c0fc2cd4efea0b65b Mon Sep 17 00:00:00 2001 From: Ben Burton Date: Mon, 19 Apr 2021 21:02:49 +0200 Subject: [PATCH 13/13] Adapt macros and BRP scripts for %topdir with spaces Fixes https://bugzilla.redhat.com/show_bug.cgi?id=1947416 --- brp-python-bytecompile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/brp-python-bytecompile b/brp-python-bytecompile index ead7022..71f4d2d 100755 --- a/brp-python-bytecompile +++ b/brp-python-bytecompile @@ -38,7 +38,7 @@ function python_bytecompile() local options=$1 local python_binary=$2 local exclude=$3 - local python_libdir=$4 + local python_libdir="$4" local depth=$5 # Not used for Python >= 3.4 local real_libdir=$6 # Not used for Python >= 3.4 @@ -57,7 +57,7 @@ function python_bytecompile() # -x and -e together implements the same functionality as the Filter class below # -s strips $RPM_BUILD_ROOT from the path # -p prepends the leading slash to the path to make it absolute - $python_binary -B $options -m compileall -q -f $exclude -s $RPM_BUILD_ROOT -p / -e $RPM_BUILD_ROOT $python_libdir + $python_binary -B $options -m compileall -q -f $exclude -s "$RPM_BUILD_ROOT" -p / -e "$RPM_BUILD_ROOT" "$python_libdir" # # Python 3.4 and higher @@ -73,7 +73,7 @@ function python_bytecompile() # -x and -e together implements the same functionality as the Filter class below # -s strips $RPM_BUILD_ROOT from the path # -p prepends the leading slash to the path to make it absolute - PYTHONPATH=/usr/lib/rpm/redhat/ $python_binary -B $options -m compileall2 -q -f $exclude -s $RPM_BUILD_ROOT -p / -e $RPM_BUILD_ROOT $python_libdir + PYTHONPATH=/usr/lib/rpm/redhat/ $python_binary -B $options -m compileall2 -q -f $exclude -s "$RPM_BUILD_ROOT" -p / -e "$RPM_BUILD_ROOT" "$python_libdir" else # # Python 3.3 and lower (incl. Python 2) @@ -119,9 +119,9 @@ fi export PYTHONHASHSEED=0 shopt -s nullglob -for python_libdir in `find "$RPM_BUILD_ROOT" -type d|grep -E "/(usr|app)/lib(64)?/python[0-9]\.[0-9]+$"`; +find "$RPM_BUILD_ROOT" -type d -print0|grep -z -E "/(usr|app)/lib(64)?/python[0-9]\.[0-9]+$" | while read -d "" python_libdir; do - python_binary=$(basename $python_libdir) + python_binary=$(basename "$python_libdir") real_libdir=${python_libdir/$RPM_BUILD_ROOT/} echo "Bytecompiling .py files below $python_libdir using $python_binary"