First version that only builds obfs4proxy for Android and Linux

\ No newline at end of file
#!/usr/bin/env python3
from glob import glob
import os
from shutil import move, rmtree
from subprocess import check_call
from utils import get_build_versions, ex, get_sha256, fail, zip_file
NDK_DIR = 'android-ndk'
REPO_DIR = 'obfs4'
SOURCE = 'obfs4/obfs4proxy/*'
def main():
# Get the latest versions for building
versions = get_build_versions(None)
# Setup Android NDK
# Clone or reset the git repository
# Install dependencies (of git HEAD)
ex(['go', 'get', '-d', versions['obfs4']['got-get']])
# Build for various Android versions
# Build for 64-bit Linux
def setup_android_ndk(versions):
if os.path.isdir(NDK_DIR):
# check that we are using the correct NDK
from configparser import ConfigParser
config = ConfigParser()
with open(os.path.join(NDK_DIR, ''), 'rt') as f:
config.read_string('[default]\n' + str(
revision = config.get('default', 'Pkg.Revision')
if revision != versions['ndk']['revision']:
print("Existing Android NDK has unexpected revision (%s). Deleting..." % revision)
if not os.path.isdir(NDK_DIR):
# download Android NDK
print("Downloading Android NDK...")
check_call(['wget', '-c', '--no-verbose', versions['ndk']['url'], '-O', ''])
# check sha256 hash on downloaded file
is_hash = get_sha256('')
if is_hash != versions['ndk']['sha256']:
fail("Android NDK checksum does not match, should be %s" % is_hash)
# install the NDK
print("Unpacking Android NDK...")
ndk_dir_tmp = NDK_DIR + '-tmp'
check_call(['unzip', '-q', '', '-d', ndk_dir_tmp])
content = os.listdir(ndk_dir_tmp)
if len(content) == 1 and content[0].startswith('android-ndk-r'):
move(os.path.join(ndk_dir_tmp, content[0]), NDK_DIR)
fail("Could not extract NDK: %s" % str(content))
os.putenv('ANDROID_NDK_HOME', os.path.abspath(NDK_DIR))
def prepare_repo(versions):
if os.path.isdir(REPO_DIR):
# get latest commits and tags from remote
check_call(['git', 'fetch', 'origin'], cwd=REPO_DIR)
# clone repo
url = versions['obfs4']['url']
check_call(['git', 'clone', url, REPO_DIR])
# checkout tag
check_call(['git', 'checkout', '-f', versions['obfs4']['tag']], cwd=REPO_DIR)
# undo all changes
check_call(['git', 'reset', '--hard'], cwd=REPO_DIR)
# clean all untracked files and directories (-d) from repo
check_call(['git', 'clean', '-dffx'], cwd=REPO_DIR)
def build_android():
env = os.environ.copy()
env['GOARCH'] = "arm"
env['GOARM'] = "7"
build_android_arch(env, "arm-linux-androideabi", ndk_arch="arm", pie=False)
env = os.environ.copy()
env['GOARCH'] = "arm"
env['GOARM'] = "7"
build_android_arch(env, "arm-linux-androideabi", ndk_arch="arm", pie=True)
env = os.environ.copy()
env['GOARCH'] = "386"
build_android_arch(env, "i686-linux-android", ndk_arch="x86", pie=False)
env = os.environ.copy()
env['GOARCH'] = "386"
build_android_arch(env, "i686-linux-android", ndk_arch="x86", pie=True)
def build_android_arch(env, tool, ndk_arch, pie):
toolchain = os.path.join("toolchain", ndk_arch)
if not os.path.isdir(toolchain):
toolchain_maker = os.path.join(NDK_DIR, "build", "tools", "")
ex([toolchain_maker, "--arch=%s" % ndk_arch, "--install-dir=%s" % toolchain])
env['CC'] = "%s/bin/%s-clang" % (os.path.abspath(toolchain), tool)
env['CGO_ENABLED'] = "1"
env['GOOS'] = "android"
build_mode = "pie" if pie else "exe"
ex(['go', 'build', '-buildmode=%s' % build_mode, '-o', 'obfs4proxy'] + glob(SOURCE), env=env)
ex(['%s/bin/%s-strip' % (toolchain, tool), '-D', 'obfs4proxy'])
pie_suffix = '_pie' if pie else ''
zip_file('obfs4proxy', '' % (ndk_arch, pie_suffix))
def build_linux():
ex(['go', 'build', '-o', 'obfs4proxy'] + glob(SOURCE))
ex(['strip', '-D', 'obfs4proxy'])
zip_file('obfs4proxy', '')
def get_source_files():
files = []
for file_name in glob(SOURCE):
return files
if __name__ == "__main__":
import hashlib
import json
import sys
from collections import OrderedDict
from subprocess import check_call
REPO_DIR = 'tor-android'
def get_version():
if len(sys.argv) > 2:
fail("Usage: %s [version tag]" % sys.argv[0])
return sys.argv[1] if len(sys.argv) > 1 else None
def get_build_versions(tag):
# load versions and their dependencies
with open('versions.json', 'r') as f:
versions = json.load(f, object_pairs_hook=OrderedDict)
if tag is None:
# take top-most version
tag = next(iter(versions))
return versions[tag]
def ex(args, env=None):
print("+ %s" % " ".join(args))
check_call(args, env=env)
def fail(msg=""):
sys.stderr.write("Error: %s\n" % msg)
def get_sha256(filename, block_size=65536):
sha256 = hashlib.sha256()
with open(filename, 'rb') as f:
for block in iter(lambda:, b''):
return sha256.hexdigest()
def zip_file(file_name, zip_name):
ex(['touch', '--no-dereference', '-t', '197001010000.00', file_name])
ex(['zip', '-X', zip_name, file_name])
"0.0.7": {
"obfs4": {
"url": "",
"got-get": "",
"tag": "obfs4proxy-0.0.7"
"ndk": {
"url": "",
"revision": "18.0.5002713",
"sha256": "c413dd014edc37f822d0dc88fabc05b64232d07d5c6e9345224e47073fdf140b"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment