diff options
author | Juro Bystricky <juro.bystricky@intel.com> | 2017-08-09 10:48:31 -0700 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2017-08-16 00:03:15 +0100 |
commit | 6fd0e23dbd47bee2cd6debc4c8234375aa0e0e27 (patch) | |
tree | d62b195e81b0d70bd5d334060fa9a9c6084fad0a | |
parent | 591db9fbd3f67145a6389c6011381221b604f16f (diff) | |
download | poky-6fd0e23dbd47bee2cd6debc4c8234375aa0e0e27.tar.gz |
python3: improve reproducibility
The compiled .pyc files contain time stamp corresponding to the compile time.
This prevents binary reproducibility. This patch allows to achieve binary
reproducibility by overriding the build time stamp by the value
exported via SOURCE_DATE_EPOCH.
Patch by Bernhard M. Wiedemann.
[YOCTO#11241]
(From OE-Core rev: 2175aec10a764bfc925a3fb447547982d0ae662f)
Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
3 files changed, 99 insertions, 0 deletions
diff --git a/meta/recipes-devtools/python/python3-native_3.5.3.bb b/meta/recipes-devtools/python/python3-native_3.5.3.bb index 250697fbbc..3467d29d4e 100644 --- a/meta/recipes-devtools/python/python3-native_3.5.3.bb +++ b/meta/recipes-devtools/python/python3-native_3.5.3.bb | |||
@@ -24,6 +24,7 @@ ${DISTRO_SRC_URI} \ | |||
24 | file://sysconfig.py-add-_PYTHON_PROJECT_SRC.patch \ | 24 | file://sysconfig.py-add-_PYTHON_PROJECT_SRC.patch \ |
25 | file://setup.py-check-cross_compiling-when-get-FLAGS.patch \ | 25 | file://setup.py-check-cross_compiling-when-get-FLAGS.patch \ |
26 | file://0001-Do-not-use-the-shell-version-of-python-config-that-w.patch \ | 26 | file://0001-Do-not-use-the-shell-version-of-python-config-that-w.patch \ |
27 | file://support_SOURCE_DATE_EPOCH_in_py_compile.patch \ | ||
27 | " | 28 | " |
28 | 29 | ||
29 | SRC_URI[md5sum] = "57d1f8bfbabf4f2500273fb0706e6f21" | 30 | SRC_URI[md5sum] = "57d1f8bfbabf4f2500273fb0706e6f21" |
diff --git a/meta/recipes-devtools/python/python3/support_SOURCE_DATE_EPOCH_in_py_compile.patch b/meta/recipes-devtools/python/python3/support_SOURCE_DATE_EPOCH_in_py_compile.patch new file mode 100644 index 0000000000..32ecab9fec --- /dev/null +++ b/meta/recipes-devtools/python/python3/support_SOURCE_DATE_EPOCH_in_py_compile.patch | |||
@@ -0,0 +1,97 @@ | |||
1 | The compiled .pyc files contain time stamp corresponding to the compile time. | ||
2 | This prevents binary reproducibility. This patch allows to achieve binary | ||
3 | reproducibility by overriding the build time stamp by the value | ||
4 | exported via SOURCE_DATE_EPOCH. | ||
5 | |||
6 | Upstream-Status: Backport | ||
7 | |||
8 | Signed-off-by: Juro Bystricky <juro.bystricky@intel.com> | ||
9 | |||
10 | |||
11 | From aeab488630fdb1b56a8d0b0c13fa88706b2afe9b Mon Sep 17 00:00:00 2001 | ||
12 | From: "Bernhard M. Wiedemann" <bwiedemann@suse.de> | ||
13 | Date: Sat, 25 Feb 2017 06:42:28 +0100 | ||
14 | Subject: [PATCH] bpo-29708: support SOURCE_DATE_EPOCH env var in py_compile | ||
15 | |||
16 | to allow for reproducible builds of python packages | ||
17 | |||
18 | See https://reproducible-builds.org/ for why this is good | ||
19 | and https://reproducible-builds.org/specs/source-date-epoch/ | ||
20 | for the definition of this variable. | ||
21 | |||
22 | Background: | ||
23 | In some distributions like openSUSE, binary rpms contain precompiled .pyc files. | ||
24 | |||
25 | And packages like amqp or twisted dynamically generate .py files at build time | ||
26 | so those have the current time and that timestamp gets embedded | ||
27 | into the .pyc file header. | ||
28 | When we then adapt file timestamps in rpms to be constant, | ||
29 | the timestamp in the .pyc header will no more match | ||
30 | the .py timestamp in the filesystem. | ||
31 | The software will still work, but it will not use the .pyc file as it should. | ||
32 | --- | ||
33 | Doc/library/py_compile.rst | 4 ++++ | ||
34 | Lib/py_compile.py | 4 ++++ | ||
35 | Lib/test/test_py_compile.py | 19 +++++++++++++++++++ | ||
36 | 3 files changed, 27 insertions(+) | ||
37 | |||
38 | diff --git a/Doc/library/py_compile.rst b/Doc/library/py_compile.rst | ||
39 | index 0af8fb1..841f3e8 100644 | ||
40 | --- a/Doc/library/py_compile.rst | ||
41 | +++ b/Doc/library/py_compile.rst | ||
42 | @@ -53,6 +53,10 @@ byte-code cache files in the directory containing the source code. | ||
43 | :func:`compile` function. The default of ``-1`` selects the optimization | ||
44 | level of the current interpreter. | ||
45 | |||
46 | + If the SOURCE_DATE_EPOCH environment variable is set, the .py file mtime | ||
47 | + and timestamp entry in .pyc file header, will be limited to this value. | ||
48 | + See https://reproducible-builds.org/specs/source-date-epoch/ for more info. | ||
49 | + | ||
50 | .. versionchanged:: 3.2 | ||
51 | Changed default value of *cfile* to be :PEP:`3147`-compliant. Previous | ||
52 | default was *file* + ``'c'`` (``'o'`` if optimization was enabled). | ||
53 | diff --git a/Lib/py_compile.py b/Lib/py_compile.py | ||
54 | index 11c5b50..62dcdc7 100644 | ||
55 | --- a/Lib/py_compile.py | ||
56 | +++ b/Lib/py_compile.py | ||
57 | @@ -137,6 +137,10 @@ def compile(file, cfile=None, dfile=None, doraise=False, optimize=-1): | ||
58 | except FileExistsError: | ||
59 | pass | ||
60 | source_stats = loader.path_stats(file) | ||
61 | + sde = os.environ.get('SOURCE_DATE_EPOCH') | ||
62 | + if sde and source_stats['mtime'] > int(sde): | ||
63 | + source_stats['mtime'] = int(sde) | ||
64 | + os.utime(file, (source_stats['mtime'], source_stats['mtime'])) | ||
65 | bytecode = importlib._bootstrap_external._code_to_bytecode( | ||
66 | code, source_stats['mtime'], source_stats['size']) | ||
67 | mode = importlib._bootstrap_external._calc_mode(file) | ||
68 | diff --git a/Lib/test/test_py_compile.py b/Lib/test/test_py_compile.py | ||
69 | index 4a6caa5..3d09963 100644 | ||
70 | --- a/Lib/test/test_py_compile.py | ||
71 | +++ b/Lib/test/test_py_compile.py | ||
72 | @@ -98,6 +98,25 @@ def test_bad_coding(self): | ||
73 | self.assertFalse(os.path.exists( | ||
74 | importlib.util.cache_from_source(bad_coding))) | ||
75 | |||
76 | + def test_source_date_epoch(self): | ||
77 | + testtime = 123456789 | ||
78 | + orig_sde = os.getenv("SOURCE_DATE_EPOCH") | ||
79 | + os.environ["SOURCE_DATE_EPOCH"] = str(testtime) | ||
80 | + py_compile.compile(self.source_path, self.pyc_path) | ||
81 | + if orig_sde: | ||
82 | + os.environ["SOURCE_DATE_EPOCH"] = orig_sde | ||
83 | + else: | ||
84 | + del os.environ["SOURCE_DATE_EPOCH"] | ||
85 | + self.assertTrue(os.path.exists(self.pyc_path)) | ||
86 | + self.assertFalse(os.path.exists(self.cache_path)) | ||
87 | + statinfo = os.stat(self.source_path) | ||
88 | + self.assertEqual(statinfo.st_mtime, testtime) | ||
89 | + f = open(self.pyc_path, "rb") | ||
90 | + f.read(4) | ||
91 | + timebytes = f.read(4) # read timestamp from pyc header | ||
92 | + f.close() | ||
93 | + self.assertEqual(timebytes, (testtime).to_bytes(4, 'little')) | ||
94 | + | ||
95 | @unittest.skipIf(sys.flags.optimize > 0, 'test does not work with -O') | ||
96 | def test_double_dot_no_clobber(self): | ||
97 | # http://bugs.python.org/issue22966 | ||
diff --git a/meta/recipes-devtools/python/python3_3.5.3.bb b/meta/recipes-devtools/python/python3_3.5.3.bb index b67aec9fc0..13df12fe56 100644 --- a/meta/recipes-devtools/python/python3_3.5.3.bb +++ b/meta/recipes-devtools/python/python3_3.5.3.bb | |||
@@ -16,6 +16,7 @@ file://130-readline-setup.patch \ | |||
16 | file://150-fix-setupterm.patch \ | 16 | file://150-fix-setupterm.patch \ |
17 | file://0001-h2py-Fix-issue-13032-where-it-fails-with-UnicodeDeco.patch \ | 17 | file://0001-h2py-Fix-issue-13032-where-it-fails-with-UnicodeDeco.patch \ |
18 | file://tweak-MULTIARCH-for-powerpc-linux-gnuspe.patch \ | 18 | file://tweak-MULTIARCH-for-powerpc-linux-gnuspe.patch \ |
19 | file://support_SOURCE_DATE_EPOCH_in_py_compile.patch \ | ||
19 | ${DISTRO_SRC_URI} \ | 20 | ${DISTRO_SRC_URI} \ |
20 | " | 21 | " |
21 | 22 | ||