Skip to content

Commit 463aa55

Browse files
authored
Merge pull request #2390 from obfusk/reproducible-builds
reproducible builds
2 parents aadcfc4 + eafc5a9 commit 463aa55

File tree

4 files changed

+53
-6
lines changed

4 files changed

+53
-6
lines changed

pythonforandroid/archs.py

+6
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,12 @@ def get_env(self, with_flags_in_cc=True):
234234

235235
env['PATH'] = environ['PATH']
236236

237+
# for reproducible builds
238+
if 'SOURCE_DATE_EPOCH' in environ:
239+
for k in 'LC_ALL TZ SOURCE_DATE_EPOCH PYTHONHASHSEED BUILD_DATE BUILD_TIME'.split():
240+
if k in environ:
241+
env[k] = environ[k]
242+
237243
return env
238244

239245

pythonforandroid/bootstraps/common/build/build.py

+25-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#!/usr/bin/env python3
22

3+
from gzip import GzipFile
4+
import hashlib
35
import json
46
from os.path import (
57
dirname, join, isfile, realpath,
68
relpath, split, exists, basename
79
)
8-
from os import listdir, makedirs, remove
10+
from os import environ, listdir, makedirs, remove
911
import os
1012
import shlex
1113
import shutil
@@ -161,16 +163,25 @@ def select(fn):
161163
return False
162164
return not is_blacklist(fn)
163165

166+
def clean(tinfo):
167+
"""cleaning function (for reproducible builds)"""
168+
tinfo.uid = tinfo.gid = 0
169+
tinfo.uname = tinfo.gname = ''
170+
tinfo.mtime = 0
171+
return tinfo
172+
164173
# get the files and relpath file of all the directory we asked for
165174
files = []
166175
for sd in source_dirs:
167176
sd = realpath(sd)
168177
compile_dir(sd, optimize_python=optimize_python)
169178
files += [(x, relpath(realpath(x), sd)) for x in listfiles(sd)
170179
if select(x)]
180+
files.sort() # deterministic
171181

172182
# create tar.gz of thoses files
173-
tf = tarfile.open(tfn, 'w:gz', format=tarfile.USTAR_FORMAT)
183+
gf = GzipFile(tfn, 'wb', mtime=0) # deterministic
184+
tf = tarfile.open(None, 'w', gf, format=tarfile.USTAR_FORMAT)
174185
dirs = []
175186
for fn, afn in files:
176187
dn = dirname(afn)
@@ -189,8 +200,9 @@ def select(fn):
189200
tf.addfile(tinfo)
190201

191202
# put the file
192-
tf.add(fn, afn)
203+
tf.add(fn, afn, filter=clean)
193204
tf.close()
205+
gf.close()
194206

195207

196208
def compile_dir(dfn, optimize_python=True):
@@ -521,9 +533,18 @@ def make_package(args):
521533
versioned_name=versioned_name)
522534

523535
# String resources:
536+
timestamp = time.time()
537+
if 'SOURCE_DATE_EPOCH' in environ:
538+
# for reproducible builds
539+
timestamp = int(environ['SOURCE_DATE_EPOCH'])
540+
private_version = "{} {} {}".format(
541+
args.version,
542+
args.numeric_version,
543+
timestamp
544+
)
524545
render_args = {
525546
"args": args,
526-
"private_version": str(time.time())
547+
"private_version": hashlib.sha1(private_version.encode()).hexdigest()
527548
}
528549
if get_bootstrap_name() == "sdl2":
529550
render_args["url_scheme"] = url_scheme

pythonforandroid/recipes/python3/__init__.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import subprocess
44

55
from multiprocessing import cpu_count
6-
from os import environ
6+
from os import environ, utime
77
from os.path import dirname, exists, join
88
from pathlib import Path
99
from shutil import copy2
@@ -62,6 +62,7 @@ class Python3Recipe(TargetPythonRecipe):
6262

6363
patches = [
6464
'patches/pyconfig_detection.patch',
65+
'patches/reproducible-buildinfo.diff',
6566

6667
# Python 3.7.1
6768
('patches/py3.7.1_fix-ctypes-util-find-library.patch', version_starts_with("3.7")),
@@ -387,8 +388,14 @@ def create_python_bundle(self, dirn, arch):
387388
with current_directory(join(self.get_build_dir(arch.arch), 'Lib')):
388389
stdlib_filens = list(walk_valid_filens(
389390
'.', self.stdlib_dir_blacklist, self.stdlib_filen_blacklist))
391+
if 'SOURCE_DATE_EPOCH' in environ:
392+
# for reproducible builds
393+
stdlib_filens.sort()
394+
timestamp = int(environ['SOURCE_DATE_EPOCH'])
395+
for filen in stdlib_filens:
396+
utime(filen, (timestamp, timestamp))
390397
info("Zip {} files into the bundle".format(len(stdlib_filens)))
391-
shprint(sh.zip, stdlib_zip, *stdlib_filens)
398+
shprint(sh.zip, '-X', stdlib_zip, *stdlib_filens)
392399

393400
# copy the site-packages into place
394401
ensure_dir(join(dirn, 'site-packages'))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# DP: Build getbuildinfo.o with DATE/TIME values when defined
2+
3+
--- a/Makefile.pre.in
4+
+++ b/Makefile.pre.in
5+
@@ -785,6 +785,8 @@ Modules/getbuildinfo.o: $(PARSER_OBJS) \
6+
-DGITVERSION="\"`LC_ALL=C $(GITVERSION)`\"" \
7+
-DGITTAG="\"`LC_ALL=C $(GITTAG)`\"" \
8+
-DGITBRANCH="\"`LC_ALL=C $(GITBRANCH)`\"" \
9+
+ $(if $(BUILD_DATE),-DDATE='"$(BUILD_DATE)"') \
10+
+ $(if $(BUILD_TIME),-DTIME='"$(BUILD_TIME)"') \
11+
-o $@ $(srcdir)/Modules/getbuildinfo.c
12+
13+
Modules/getpath.o: $(srcdir)/Modules/getpath.c Makefile

0 commit comments

Comments
 (0)