Newer
Older
import json
from collections import OrderedDict
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
BUILD_DIR = 'tor-build'
TOR_CONFIGURE_FLAGS = [
'--disable-asciidoc',
'--disable-systemd',
'--disable-tool-name-check',
'--disable-module-relay',
'--disable-module-dirauth',
'--disable-unittests',
'--disable-asciidoc',
'--disable-manpage',
'--disable-html-manual',
]
XZ_CONFIGURE_FLAGS = [
'--enable-static',
'--disable-doc',
'--disable-lzma-links',
'--disable-lzmadec',
'--disable-lzmainfo',
'--disable-scripts',
'--disable-shared',
'--disable-xz',
'--disable-xzdec',
]
OPENSSL_CONFIGURE_FLAGS = [
'no-unit-test',
'no-asm',
'no-comp',
'no-dtls',
'no-err',
'no-psk',
'no-srp',
'no-weak-ssl-ciphers',
'no-camellia',
'no-idea',
'no-md2',
'no-md4',
'no-rc2',
'no-rc4',
'no-rc5',
'no-rmd160',
'no-whirlpool',
'no-ui-console',
]
REPRODUCIBLE_GCC_CFLAGS = '-fno-guess-branch-probability -frandom-seed="0"'
return os.path.abspath(os.path.join('output', platform))
def setup(platform):
# get Tor version from command or show usage information
version = get_version()
# get Tor version and versions of its dependencies
versions = get_build_versions(version)
print("Building Tor %s" % versions['tor']['commit'])
output_dir = get_output_dir(platform)
if os.path.isdir(output_dir):
rmtree(output_dir)
os.makedirs(output_dir)
# clone and checkout repos based on tor-versions.json
prepare_repos(versions)
jar_name = create_sources_jar(versions, platform, BUILD_DIR)
def prepare_repos(versions):
prepare_repo(os.path.join(BUILD_DIR, "tor"), versions['tor']['url'], versions['tor']['commit'])
prepare_repo(os.path.join(BUILD_DIR, "libevent"), versions['libevent']['url'], versions['libevent']['commit'])
prepare_repo(os.path.join(BUILD_DIR, "openssl"), versions['openssl']['url'], versions['openssl']['commit'])
prepare_repo(os.path.join(BUILD_DIR, "xz"), versions['xz']['url'], versions['xz']['commit'])
prepare_repo(os.path.join(BUILD_DIR, "zlib"), versions['zlib']['url'], versions['zlib']['commit'])
prepare_repo(os.path.join(BUILD_DIR, "zstd"), versions['zstd']['url'], versions['zstd']['commit'])
def prepare_repo(path, url, version):
if os.path.isdir(path):
check_call(['git', 'fetch', '--recurse-submodules=yes', 'origin'], cwd=path)
# checkout given version
check_call(['git', 'checkout', '-f', version], cwd=path)
# initialize and/or update submodules
# (after checkout, because submodules can point to non-existent commits on master)
check_call(['git', 'submodule', 'update', '--init', '--recursive', '-f'], cwd=path)
check_call(['git', 'reset', '--hard'], cwd=path)
check_call(['git', 'submodule', 'foreach', 'git', 'reset', '--hard'], cwd=path)
# clean all untracked files and directories (-d) from repo
check_call(['git', 'clean', '-dffx'], cwd=path)
check_call(['git', 'submodule', 'foreach', 'git', 'clean', '-dffx'], cwd=path)
def get_version():
if len(sys.argv) > 2:
fail("Usage: %s [Tor version tag]" % sys.argv[0])
return sys.argv[1] if len(sys.argv) > 1 else None
def get_build_versions(tag):
# load Tor versions and their dependencies
with open('tor-versions.json', 'r') as f:
versions = json.load(f, object_pairs_hook=OrderedDict)
if tag is None:
# take top-most Tor version
tag = next(iter(versions))
return versions[tag]
def fail(msg=""):
sys.stderr.write("Error: %s\n" % msg)
sys.exit(1)
def get_sha256(filename, block_size=65536):
sha256 = hashlib.sha256()
with open(filename, 'rb') as f:
for block in iter(lambda: f.read(block_size), b''):
sha256.update(block)
return sha256.hexdigest()
def get_version_tag(versions):
return versions['tag']
version = get_version_tag(versions)
file = 'tor-%s.jar' % get_file_suffix(versions, platform)
return os.path.join(get_output_dir(platform), file)
file = 'tor-%s-sources.jar' % get_file_suffix(versions, platform)
return os.path.join(get_output_dir(platform), file)
file = 'tor-%s.pom' % get_file_suffix(versions, platform)
return os.path.join(get_output_dir(platform), file)
def pack(versions, file_list, platform):
# make file times deterministic before zipping
for filename in file_list:
reset_time(filename, versions)
zip_name = get_final_file_name(versions, platform)
# use platform_dir as the root of the zip paths
platform_dir = get_output_dir(platform)
relative_file_list = [os.path.relpath(filename, start=platform_dir) for filename in file_list]
check_call(['zip', '--no-dir-entries', '-X', zip_name] + relative_file_list, cwd=platform_dir)
return zip_name
def reset_time(filename, versions):
check_call(['touch', '--no-dereference', '-t', versions['timestamp'], filename])
def create_sources_jar(versions, platform, build_dir):
output_dir = get_output_dir(platform)
for root, dir_names, filenames in os.walk(build_dir):
for f in filenames:
if '/.git' in root:
continue
jar_files.append(os.path.join(root, f))
for file in jar_files:
reset_time(file, versions)
jar_name = get_sources_file_name(versions, platform)
jar_path = os.path.abspath(jar_name)
rel_paths = [os.path.relpath(f, build_dir) for f in sorted(jar_files)]
# create jar archive with first files
jar_step = 5000
check_call(['jar', 'cf', jar_path] + rel_paths[0:jar_step], cwd=build_dir)
# add subsequent files in steps, because the command line can't handle all at once
for i in range(jar_step, len(rel_paths), jar_step):
check_call(['jar', 'uf', jar_path] + rel_paths[i:i + jar_step], cwd=build_dir)
return jar_name
def create_pom_file(versions, platform):
version = get_version_tag(versions)
pom_name = get_pom_file_name(versions, platform)
template = 'template-%s.pom' % platform
with open(template, 'rt') as infile:
with open(pom_name, 'wt') as outfile:
for line in infile:
outfile.write(line.replace('VERSION', version))
return pom_name