When run_cmd_on_host() runs a command that fails, we only get an
exception with no details to debug what happened. Let's improve that
by catching the exception, and printing the command output. This
requires redirecting stderr to stdout (instead of /dev/null) and
asking to get the output in text format.
Signed-off-by: Thomas Petazzoni <thomas.petazzoni@bootlin.com>
Signed-off-by: Julien Olivain <ju.o@free.fr>
(cherry picked from commit 01dc13adfb)
Signed-off-by: Thomas Perale <thomas.perale@mind.be>
137 lines
4.0 KiB
Python
137 lines
4.0 KiB
Python
import os
|
|
import re
|
|
import sys
|
|
import tempfile
|
|
import subprocess
|
|
from urllib.request import urlopen
|
|
from urllib.error import HTTPError, URLError
|
|
|
|
ARTIFACTS_URL = "http://autobuild.buildroot.net/artefacts/"
|
|
BASE_DIR = os.path.realpath(os.path.join(os.path.dirname(__file__), "../../.."))
|
|
|
|
|
|
def log_file_path(builddir, stage, logtofile=True):
|
|
"""Return path to log file"""
|
|
return "{}-{}.log".format(builddir, stage) if logtofile else None
|
|
|
|
|
|
def open_log_file(builddir, stage, logtofile=True):
|
|
"""
|
|
Open a file for logging and return its handler.
|
|
If logtofile is True, returns sys.stdout. Otherwise opens a file
|
|
with a suitable name in the build directory.
|
|
"""
|
|
return open(log_file_path(builddir, stage, logtofile), 'a+') if logtofile else sys.stdout
|
|
|
|
|
|
def basepath(relpath=""):
|
|
"""Return the absolute path for a file or directory relative to the Buildroot top directory."""
|
|
return os.path.join(BASE_DIR, relpath)
|
|
|
|
|
|
def filepath(relpath):
|
|
return os.path.join(BASE_DIR, "support/testing", relpath)
|
|
|
|
|
|
def download(dldir, filename):
|
|
finalpath = os.path.join(dldir, filename)
|
|
if os.path.exists(finalpath):
|
|
return finalpath
|
|
|
|
if not os.path.exists(dldir):
|
|
os.makedirs(dldir)
|
|
|
|
tmpfile = tempfile.mktemp(dir=dldir)
|
|
print("Downloading to {}".format(tmpfile))
|
|
|
|
try:
|
|
url_fh = urlopen(os.path.join(ARTIFACTS_URL, filename))
|
|
with open(tmpfile, "w+b") as tmpfile_fh:
|
|
tmpfile_fh.write(url_fh.read())
|
|
except (HTTPError, URLError) as err:
|
|
os.unlink(tmpfile)
|
|
raise err
|
|
|
|
print("Renaming from {} to {}".format(tmpfile, finalpath))
|
|
os.rename(tmpfile, finalpath)
|
|
return finalpath
|
|
|
|
|
|
def run_cmd_on_host(builddir, cmd):
|
|
"""Call subprocess.check_output and return the text output."""
|
|
try:
|
|
out = subprocess.check_output(cmd,
|
|
cwd=builddir,
|
|
env={"LANG": "C"},
|
|
stderr=subprocess.STDOUT,
|
|
text=True,
|
|
universal_newlines=True)
|
|
except subprocess.CalledProcessError as e:
|
|
print(f"Command failed with return code {e.returncode}")
|
|
print("=== STDOUT/STDERR ===")
|
|
print(e.output)
|
|
print("=====================")
|
|
raise
|
|
|
|
return out
|
|
|
|
|
|
def get_elf_arch_tag(builddir, prefix, fpath, tag):
|
|
"""
|
|
Runs the cross readelf on 'fpath', then extracts the value of tag 'tag'.
|
|
Example:
|
|
>>> get_elf_arch_tag('output', 'arm-none-linux-gnueabi-',
|
|
'bin/busybox', 'Tag_CPU_arch')
|
|
v5TEJ
|
|
>>>
|
|
"""
|
|
cmd = ["host/bin/{}-readelf".format(prefix),
|
|
"-A", os.path.join("target", fpath)]
|
|
out = run_cmd_on_host(builddir, cmd)
|
|
regexp = re.compile(r"^ {}: (.*)$".format(tag))
|
|
for line in out.splitlines():
|
|
m = regexp.match(line)
|
|
if not m:
|
|
continue
|
|
return m.group(1)
|
|
return None
|
|
|
|
|
|
def get_file_arch(builddir, prefix, fpath):
|
|
return get_elf_arch_tag(builddir, prefix, fpath, "Tag_CPU_arch")
|
|
|
|
|
|
def get_elf_prog_interpreter(builddir, prefix, fpath):
|
|
"""
|
|
Runs the cross readelf on 'fpath' to extract the program interpreter
|
|
name and returns it.
|
|
Example:
|
|
>>> get_elf_prog_interpreter('br-tests/TestExternalToolchainLinaroArm',
|
|
'arm-linux-gnueabihf',
|
|
'bin/busybox')
|
|
/lib/ld-linux-armhf.so.3
|
|
>>>
|
|
"""
|
|
cmd = ["host/bin/{}-readelf".format(prefix),
|
|
"-l", os.path.join("target", fpath)]
|
|
out = run_cmd_on_host(builddir, cmd)
|
|
regexp = re.compile(r"^ *\[Requesting program interpreter: (.*)\]$")
|
|
for line in out.splitlines():
|
|
m = regexp.match(line)
|
|
if not m:
|
|
continue
|
|
return m.group(1)
|
|
return None
|
|
|
|
|
|
def img_round_power2(img):
|
|
"""
|
|
Rounds up the size of an image file to the next power of 2
|
|
"""
|
|
sz = os.stat(img).st_size
|
|
pow2 = 1
|
|
while pow2 < sz:
|
|
pow2 = pow2 << 1
|
|
with open(img, 'ab') as f:
|
|
f.truncate(pow2)
|