Skip to content

Commit 78f06e4

Browse files
committed
Migrate gitian-build.sh to python
1 parent 17943f7 commit 78f06e4

File tree

2 files changed

+201
-413
lines changed

2 files changed

+201
-413
lines changed

contrib/gitian-build.py

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
#!/usr/bin/env python3
2+
3+
import argparse
4+
import os
5+
import subprocess
6+
import sys
7+
8+
def setup():
9+
global args, workdir
10+
programs = ['ruby', 'git', 'apt-cacher-ng']
11+
if args.kvm:
12+
programs += ['python-vm-builder', 'qemu-kvm', 'qemu-utils']
13+
elif args.docker:
14+
programs += ['docker.io']
15+
else:
16+
programs += ['lxc', 'debootstrap']
17+
subprocess.check_call(['sudo', 'apt-get', 'install', '-qq'] + programs)
18+
if not os.path.isdir('gitian.sigs'):
19+
subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/gitian.sigs.git'])
20+
if not os.path.isdir('bitcoin-detached-sigs'):
21+
subprocess.check_call(['git', 'clone', 'https://github.com/bitcoin-core/bitcoin-detached-sigs.git'])
22+
if not os.path.isdir('gitian-builder'):
23+
subprocess.check_call(['git', 'clone', 'https://github.com/devrandom/gitian-builder.git'])
24+
os.chdir('gitian-builder')
25+
make_image_prog = ['bin/make-base-vm', '--suite', 'bionic', '--arch', 'amd64']
26+
if args.docker:
27+
make_image_prog += ['--docker']
28+
elif not args.kvm:
29+
make_image_prog += ['--lxc']
30+
subprocess.check_call(make_image_prog)
31+
os.chdir(workdir)
32+
33+
def build():
34+
global args, workdir
35+
36+
os.makedirs('bitcoin-binaries/' + args.version, exist_ok=True)
37+
print('\nBuilding Dependencies\n')
38+
os.chdir('gitian-builder')
39+
os.makedirs('inputs', exist_ok=True)
40+
41+
subprocess.check_call(['wget', '-N', '-P', 'inputs', 'http://downloads.sourceforge.net/project/osslsigncode/osslsigncode/osslsigncode-1.7.1.tar.gz'])
42+
subprocess.check_call(['wget', '-N', '-P', 'inputs', 'https://bitcoincore.org/cfields/osslsigncode-Backports-to-1.7.1.patch'])
43+
subprocess.check_call(['make', '-C', '../bitcoin/depends', 'download', 'SOURCES_PATH=' + os.getcwd() + '/cache/common'])
44+
45+
if args.linux:
46+
print('\nCompiling ' + args.version + ' Linux')
47+
subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-linux.yml'])
48+
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-linux', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-linux.yml'])
49+
subprocess.check_call('mv build/out/bitcoin-*.tar.gz build/out/src/bitcoin-*.tar.gz ../bitcoin-binaries/'+args.version, shell=True)
50+
51+
if args.windows:
52+
print('\nCompiling ' + args.version + ' Windows')
53+
subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-win.yml'])
54+
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-unsigned', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-win.yml'])
55+
subprocess.check_call('mv build/out/bitcoin-*-win-unsigned.tar.gz inputs/bitcoin-win-unsigned.tar.gz', shell=True)
56+
subprocess.check_call('mv build/out/bitcoin-*.zip build/out/bitcoin-*.exe ../bitcoin-binaries/'+args.version, shell=True)
57+
58+
if args.macos:
59+
print('\nCompiling ' + args.version + ' MacOS')
60+
subprocess.check_call(['bin/gbuild', '-j', args.jobs, '-m', args.memory, '--commit', 'bitcoin='+args.commit, '--url', 'bitcoin='+args.url, '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml'])
61+
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-unsigned', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml'])
62+
subprocess.check_call('mv build/out/bitcoin-*-osx-unsigned.tar.gz inputs/bitcoin-osx-unsigned.tar.gz', shell=True)
63+
subprocess.check_call('mv build/out/bitcoin-*.tar.gz build/out/bitcoin-*.dmg ../bitcoin-binaries/'+args.version, shell=True)
64+
65+
os.chdir(workdir)
66+
67+
if args.commit_files:
68+
print('\nCommitting '+args.version+' Unsigned Sigs\n')
69+
os.chdir('gitian.sigs')
70+
subprocess.check_call(['git', 'add', args.version+'-linux/'+args.signer])
71+
subprocess.check_call(['git', 'add', args.version+'-win-unsigned/'+args.signer])
72+
subprocess.check_call(['git', 'add', args.version+'-osx-unsigned/'+args.signer])
73+
subprocess.check_call(['git', 'commit', '-a', '-m', 'Add '+args.version+' unsigned sigs for '+args.signer])
74+
os.chdir(workdir)
75+
76+
def sign():
77+
global args, workdir
78+
os.chdir('gitian-builder')
79+
80+
if args.windows:
81+
print('\nSigning ' + args.version + ' Windows')
82+
subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml'])
83+
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-win-signed', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml'])
84+
subprocess.check_call('mv build/out/bitcoin-*win64-setup.exe ../bitcoin-binaries/'+args.version, shell=True)
85+
subprocess.check_call('mv build/out/bitcoin-*win32-setup.exe ../bitcoin-binaries/'+args.version, shell=True)
86+
87+
if args.macos:
88+
print('\nSigning ' + args.version + ' MacOS')
89+
subprocess.check_call(['bin/gbuild', '-i', '--commit', 'signature='+args.commit, '../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml'])
90+
subprocess.check_call(['bin/gsign', '-p', args.sign_prog, '--signer', args.signer, '--release', args.version+'-osx-signed', '--destination', '../gitian.sigs/', '../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml'])
91+
subprocess.check_call('mv build/out/bitcoin-osx-signed.dmg ../bitcoin-binaries/'+args.version+'/bitcoin-'+args.version+'-osx.dmg', shell=True)
92+
93+
os.chdir(workdir)
94+
95+
if args.commit_files:
96+
print('\nCommitting '+args.version+' Signed Sigs\n')
97+
os.chdir('gitian.sigs')
98+
subprocess.check_call(['git', 'add', args.version+'-win-signed/'+args.signer])
99+
subprocess.check_call(['git', 'add', args.version+'-osx-signed/'+args.signer])
100+
subprocess.check_call(['git', 'commit', '-a', '-m', 'Add '+args.version+' signed binary sigs for '+args.signer])
101+
os.chdir(workdir)
102+
103+
def verify():
104+
global args, workdir
105+
os.chdir('gitian-builder')
106+
107+
print('\nVerifying v'+args.version+' Linux\n')
108+
subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-linux', '../bitcoin/contrib/gitian-descriptors/gitian-linux.yml'])
109+
print('\nVerifying v'+args.version+' Windows\n')
110+
subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-unsigned', '../bitcoin/contrib/gitian-descriptors/gitian-win.yml'])
111+
print('\nVerifying v'+args.version+' MacOS\n')
112+
subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-unsigned', '../bitcoin/contrib/gitian-descriptors/gitian-osx.yml'])
113+
print('\nVerifying v'+args.version+' Signed Windows\n')
114+
subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-win-signed', '../bitcoin/contrib/gitian-descriptors/gitian-win-signer.yml'])
115+
print('\nVerifying v'+args.version+' Signed MacOS\n')
116+
subprocess.check_call(['bin/gverify', '-v', '-d', '../gitian.sigs/', '-r', args.version+'-osx-signed', '../bitcoin/contrib/gitian-descriptors/gitian-osx-signer.yml'])
117+
118+
os.chdir(workdir)
119+
120+
def main():
121+
global args, workdir
122+
123+
parser = argparse.ArgumentParser(usage='%(prog)s [options] signer version')
124+
parser.add_argument('-c', '--commit', action='store_true', dest='commit', help='Indicate that the version argument is for a commit or branch')
125+
parser.add_argument('-u', '--url', dest='url', default='https://github.com/bitcoin/bitcoin', help='Specify the URL of the repository. Default is %(default)s')
126+
parser.add_argument('-v', '--verify', action='store_true', dest='verify', help='Verify the Gitian build')
127+
parser.add_argument('-b', '--build', action='store_true', dest='build', help='Do a Gitian build')
128+
parser.add_argument('-s', '--sign', action='store_true', dest='sign', help='Make signed binaries for Windows and MacOS')
129+
parser.add_argument('-B', '--buildsign', action='store_true', dest='buildsign', help='Build both signed and unsigned binaries')
130+
parser.add_argument('-o', '--os', dest='os', default='lwm', help='Specify which Operating Systems the build is for. Default is %(default)s. l for Linux, w for Windows, m for MacOS')
131+
parser.add_argument('-j', '--jobs', dest='jobs', default='2', help='Number of processes to use. Default %(default)s')
132+
parser.add_argument('-m', '--memory', dest='memory', default='2000', help='Memory to allocate in MiB. Default %(default)s')
133+
parser.add_argument('-k', '--kvm', action='store_true', dest='kvm', help='Use KVM instead of LXC')
134+
parser.add_argument('-d', '--docker', action='store_true', dest='docker', help='Use Docker instead of LXC')
135+
parser.add_argument('-S', '--setup', action='store_true', dest='setup', help='Set up the Gitian building environment. Uses LXC. If you want to use KVM, use the --kvm option. Only works on Debian-based systems (Ubuntu, Debian)')
136+
parser.add_argument('-D', '--detach-sign', action='store_true', dest='detach_sign', help='Create the assert file for detached signing. Will not commit anything.')
137+
parser.add_argument('-n', '--no-commit', action='store_false', dest='commit_files', help='Do not commit anything to git')
138+
parser.add_argument('signer', help='GPG signer to sign each build assert file')
139+
parser.add_argument('version', help='Version number, commit, or branch to build. If building a commit or branch, the -c option must be specified')
140+
141+
args = parser.parse_args()
142+
workdir = os.getcwd()
143+
144+
args.linux = 'l' in args.os
145+
args.windows = 'w' in args.os
146+
args.macos = 'm' in args.os
147+
148+
if args.buildsign:
149+
args.build=True
150+
args.sign=True
151+
152+
if args.kvm and args.docker:
153+
raise Exception('Error: cannot have both kvm and docker')
154+
155+
args.sign_prog = 'true' if args.detach_sign else 'gpg --detach-sign'
156+
157+
# Set enviroment variable USE_LXC or USE_DOCKER, let gitian-builder know that we use lxc or docker
158+
if args.docker:
159+
os.environ['USE_DOCKER'] = '1'
160+
elif not args.kvm:
161+
os.environ['USE_LXC'] = '1'
162+
163+
# Disable for MacOS if no SDK found
164+
if args.macos and not os.path.isfile('gitian-builder/inputs/MacOSX10.11.sdk.tar.gz'):
165+
print('Cannot build for MacOS, SDK does not exist. Will build for other OSes')
166+
args.macos = False
167+
168+
script_name = os.path.basename(sys.argv[0])
169+
# Signer and version shouldn't be empty
170+
if args.signer == '':
171+
print(script_name+': Missing signer.')
172+
print('Try '+script_name+' --help for more information')
173+
exit(1)
174+
if args.version == '':
175+
print(script_name+': Missing version.')
176+
print('Try '+script_name+' --help for more information')
177+
exit(1)
178+
179+
# Add leading 'v' for tags
180+
args.commit = ('' if args.commit else 'v') + args.version
181+
print(args.commit)
182+
183+
if args.setup:
184+
setup()
185+
186+
os.chdir('bitcoin')
187+
subprocess.check_call(['git', 'fetch'])
188+
subprocess.check_call(['git', 'checkout', args.commit])
189+
os.chdir(workdir)
190+
191+
if args.build:
192+
build()
193+
194+
if args.sign:
195+
sign()
196+
197+
if args.verify:
198+
verify()
199+
200+
if __name__ == '__main__':
201+
main()

0 commit comments

Comments
 (0)