Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Ardupilot
GitHub Repository: Ardupilot/ardupilot
Path: blob/master/Tools/scripts/build_script_base.py
9355 views
1
from __future__ import annotations
2
3
'''
4
Base class for ArduPilot build scripts providing common utilities
5
6
AP_FLAKE8_CLEAN
7
'''
8
9
import os
10
import pathlib
11
import string
12
import subprocess
13
import sys
14
import time
15
16
17
class BuildScriptBase:
18
"""Base class for build scripts with common utilities for running programs"""
19
20
def __init__(self):
21
self.tmpdir = None # Can be set by subclasses that need it
22
23
def run_program(self, prefix, cmd_list, show_output=True, env=None, show_output_on_error=True, show_command=None, cwd="."):
24
if show_command is None:
25
show_command = True
26
27
cmd = " ".join(cmd_list)
28
if cwd is None:
29
cwd = "."
30
command_debug = f"Running ({cmd}) in ({cwd})"
31
process_failure_content = command_debug + "\n"
32
if show_command:
33
self.progress(command_debug)
34
35
p = subprocess.Popen(
36
cmd_list,
37
stdin=None,
38
stdout=subprocess.PIPE,
39
close_fds=True,
40
stderr=subprocess.STDOUT,
41
cwd=cwd,
42
env=env)
43
output = ""
44
while True:
45
x = p.stdout.readline()
46
if len(x) == 0:
47
returncode = os.waitpid(p.pid, 0)
48
if returncode:
49
break
50
# select not available on Windows... probably...
51
time.sleep(0.1)
52
continue
53
x = bytearray(x)
54
x = filter(lambda x : chr(x) in string.printable, x)
55
x = "".join([chr(c) for c in x])
56
output += x
57
process_failure_content += x
58
x = x.rstrip()
59
some_output = "%s: %s" % (prefix, x)
60
if show_output:
61
print(some_output)
62
(_, status) = returncode
63
if status != 0:
64
if not show_output and show_output_on_error:
65
# we were told not to show output, but we just
66
# failed... so show output...
67
print(output)
68
self.progress("Process failed (%s)" %
69
str(returncode))
70
try:
71
path = pathlib.Path(self.tmpdir, f"process-failure-{int(time.time())}")
72
path.write_text(process_failure_content)
73
self.progress("Wrote process failure file (%s)" % path)
74
except Exception:
75
self.progress("Writing process failure file failed")
76
raise subprocess.CalledProcessError(
77
returncode, cmd_list)
78
return output
79
80
def find_current_git_branch_or_sha1(self):
81
try:
82
output = self.run_git(["symbolic-ref", "--short", "HEAD"])
83
output = output.strip()
84
return output
85
except subprocess.CalledProcessError:
86
pass
87
88
# probably in a detached-head state. Get a sha1 instead:
89
output = self.run_git(["rev-parse", "--short", "HEAD"])
90
output = output.strip()
91
return output
92
93
def find_git_branch_merge_base(self, branch, master_branch):
94
output = self.run_git(["merge-base", branch, master_branch])
95
output = output.strip()
96
return output
97
98
def run_git(self, args, show_output=True, source_dir=None):
99
'''run git with args git_args; returns git's output'''
100
cmd_list = ["git"]
101
cmd_list.extend(args)
102
return self.run_program("SCB-GIT", cmd_list, show_output=show_output, cwd=source_dir)
103
104
def run_waf(self, args, compiler=None, show_output=True, source_dir=None):
105
# try to modify the environment so we can consistent builds:
106
consistent_build_envs = {
107
"CHIBIOS_GIT_VERSION": "12345678",
108
"GIT_VERSION": "abcdef",
109
"GIT_VERSION_EXTENDED": "0123456789abcdef",
110
"GIT_VERSION_INT": "15",
111
}
112
for (n, v) in consistent_build_envs.items():
113
os.environ[n] = v
114
115
if os.path.exists("waf"):
116
waf = "./waf"
117
else:
118
waf = os.path.join(".", "modules", "waf", "waf-light")
119
cmd_list = [waf]
120
cmd_list.extend(args)
121
env = None
122
if compiler is not None:
123
# default to $HOME/arm-gcc, but allow for any path with AP_GCC_HOME environment variable
124
gcc_home = os.environ.get("AP_GCC_HOME", os.path.join(os.environ["HOME"], "arm-gcc"))
125
gcc_path = os.path.join(gcc_home, compiler, "bin")
126
if os.path.exists(gcc_path):
127
# setup PATH to point at the right compiler, and setup to use ccache
128
env = os.environ.copy()
129
env["PATH"] = gcc_path + ":" + env["PATH"]
130
env["CC"] = "ccache arm-none-eabi-gcc"
131
env["CXX"] = "ccache arm-none-eabi-g++"
132
else:
133
raise Exception("BB-WAF: Missing compiler %s" % gcc_path)
134
self.run_program("SCB-WAF", cmd_list, env=env, show_output=show_output, cwd=source_dir)
135
136
def progress(self, string):
137
'''pretty-print progress'''
138
print(f"{self.progress_prefix()}: {string}", file=sys.stderr)
139
140