-
Notifications
You must be signed in to change notification settings - Fork 3
/
build.py
190 lines (142 loc) · 5.13 KB
/
build.py
1
2
3
4
5
6
7
8
9
10
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
import argparse
import sys
import os
import subprocess
import urllib.request
from collections import OrderedDict
'''
PyInstaller settings
'''
EXECUTABLE_NAME = 'UBCRGS'
ENTRY_POINT = 'start.py'
DATA_FILES = [
'qt_files/*',
'required_flare.txt'
]
HIDDEN_IMPORTS = [
'main_window.mplwidget',
]
SPLASH_IMAGE = 'qt_files/logo.png'
ICON_FILE = 'qt_files/icon.ico'
'''
Environment specific paths and constants
'''
LOCAL = os.path.dirname(os.path.abspath(__file__))
GLOBAL_PYTHON = sys.executable
VENV_BIN_DIR = os.path.join(LOCAL, {
'linux': 'venv/bin/',
'win32': 'venv/Scripts/',
'darwin': 'venv/bin/'
}[sys.platform])
EXECUTABLE_FILE_EXTENSION = {
'linux': '',
'win32': '.exe',
'darwin': ''
}[sys.platform]
VENV_PYTHON = os.path.join(VENV_BIN_DIR, {
'linux': 'python3',
'win32': 'python',
'darwin': 'python3'
}[sys.platform] + EXECUTABLE_FILE_EXTENSION)
VENV_PIP = os.path.join(VENV_BIN_DIR, 'pip' + EXECUTABLE_FILE_EXTENSION)
VENV_PYINSTALLER = os.path.join(VENV_BIN_DIR, 'pyinstaller' + EXECUTABLE_FILE_EXTENSION)
BUILD_OUTPUT = os.path.join(LOCAL, 'dist/', EXECUTABLE_NAME + EXECUTABLE_FILE_EXTENSION)
PYINSTALLER_SEPARATOR = {
'linux': ':',
'win32': ';',
'darwin': ':'
}[sys.platform]
GIT_HASH_FILE = os.path.join(LOCAL, '.git_hash')
EXTERNAL_DEPENDENCIES = {
'https://github.com/openrocket/openrocket/releases/download/release-15.03/OpenRocket-15.03.jar':
os.path.join(LOCAL, 'OpenRocket-15.03.jar'),
}
def _run(executable, args):
cmd = [executable] + args
cmd = ' '.join(cmd)
print(cmd)
sys.stdout.flush() # Otherwise the output gets mixed with the subprocess output
subprocess.run(cmd, cwd=LOCAL, check=True, shell=True)
def _is_venv():
return (hasattr(sys, 'real_prefix') or
(hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix))
def parent_dir(path):
path = os.path.dirname(path)
if len(path) == 0:
return '.'
else:
return path
def setup_step():
print("Creating venv...")
_run(GLOBAL_PYTHON, ['-m', 'venv', 'venv'])
print("Printing some venv debug info...")
_run(VENV_PYTHON, ['--version'])
_run(VENV_PYTHON, ['-c', '"import sys; print(sys.executable)"'])
print("Installing requirements in venv...")
_run(VENV_PIP, ['install', '-r', 'requirements.txt'])
print("Downloading external requirements...")
for url, file in EXTERNAL_DEPENDENCIES.items():
print(f"Downloading {url} to {file}")
urllib.request.urlretrieve(url, file)
def build_step():
git_hash = subprocess.check_output(["git", "rev-parse", "HEAD"], cwd=LOCAL).strip().decode("utf-8")
print(f"Using git hash: {git_hash}")
with open(GIT_HASH_FILE, 'w') as f:
f.write(git_hash)
DATA_FILES.append(os.path.relpath(GIT_HASH_FILE, start=LOCAL))
print("Running PyInstaller...")
hidden_imports = [f"--hidden-import={i}" for i in HIDDEN_IMPORTS]
data_files = [f"--add-data={i}{PYINSTALLER_SEPARATOR}{parent_dir(i)}" for i in DATA_FILES]
splash = f"--splash {SPLASH_IMAGE}" if sys.platform != 'darwin' else "" # Splash not currently supported on MacOS
_run(VENV_PYINSTALLER, ['--onefile',
ENTRY_POINT,
'--console',
'--name', EXECUTABLE_NAME,
'--icon', ICON_FILE,
splash,
] + hidden_imports + data_files)
os.remove(GIT_HASH_FILE)
def test_step():
print("Starting self-test...")
_run(BUILD_OUTPUT, ['--self-test'])
BUILD_STEPS = OrderedDict({
'setup': setup_step,
'build': build_step,
'test': test_step
})
def main(cmd_args):
"""
Validate input
"""
if cmd_args.only and cmd_args.skip:
raise Exception("Cannot use --skip and --only together")
if cmd_args.only or cmd_args.skip:
for step in cmd_args.only if cmd_args.only else cmd_args.skip:
if step not in BUILD_STEPS:
raise Exception(f"Invalid build step: {step}")
"""
Run build steps in order
"""
for step in BUILD_STEPS.keys():
if cmd_args.skip and step in cmd_args.skip:
print(f"Skipping build step: {step}")
continue
elif cmd_args.only and step not in cmd_args.only:
print(f"Skipping build step: {step}")
continue
else:
print(f"Starting build step: {step}")
BUILD_STEPS[step]()
print(f"Finished build step: {step}")
if __name__ == '__main__':
if not (sys.version_info[0] == 3 and sys.version_info[1] == 7):
raise Exception("Python version is not 3.7")
if _is_venv():
raise Exception("Running in a virtual environment")
parser = argparse.ArgumentParser()
parser.add_argument("-s", "--skip", nargs='+', type=str,
help="List of build steps to skip. Cannot be used in conjunction with --only")
parser.add_argument("-o", "--only", nargs='+', type=str,
help="List of build steps to run exclusively. Cannot be used in conjunction with --skip")
cmd_args = parser.parse_args()
main(cmd_args)