1import os 2import re 3import sys 4import tempfile 5import subprocess 6from urllib.request import urlopen 7from urllib.error import HTTPError, URLError 8 9ARTIFACTS_URL = "http://autobuild.buildroot.net/artefacts/" 10BASE_DIR = os.path.realpath(os.path.join(os.path.dirname(__file__), "../../..")) 11 12 13def log_file_path(builddir, stage, logtofile=True): 14 """Return path to log file""" 15 return "{}-{}.log".format(builddir, stage) if logtofile else None 16 17 18def open_log_file(builddir, stage, logtofile=True): 19 """ 20 Open a file for logging and return its handler. 21 If logtofile is True, returns sys.stdout. Otherwise opens a file 22 with a suitable name in the build directory. 23 """ 24 return open(log_file_path(builddir, stage, logtofile), 'a+') if logtofile else sys.stdout 25 26 27def basepath(relpath=""): 28 """Return the absolute path for a file or directory relative to the Buildroot top directory.""" 29 return os.path.join(BASE_DIR, relpath) 30 31 32def filepath(relpath): 33 return os.path.join(BASE_DIR, "support/testing", relpath) 34 35 36def download(dldir, filename): 37 finalpath = os.path.join(dldir, filename) 38 if os.path.exists(finalpath): 39 return finalpath 40 41 if not os.path.exists(dldir): 42 os.makedirs(dldir) 43 44 tmpfile = tempfile.mktemp(dir=dldir) 45 print("Downloading to {}".format(tmpfile)) 46 47 try: 48 url_fh = urlopen(os.path.join(ARTIFACTS_URL, filename)) 49 with open(tmpfile, "w+b") as tmpfile_fh: 50 tmpfile_fh.write(url_fh.read()) 51 except (HTTPError, URLError) as err: 52 os.unlink(tmpfile) 53 raise err 54 55 print("Renaming from {} to {}".format(tmpfile, finalpath)) 56 os.rename(tmpfile, finalpath) 57 return finalpath 58 59 60def run_cmd_on_host(builddir, cmd): 61 """Call subprocess.check_output and return the text output.""" 62 out = subprocess.check_output(cmd, 63 stderr=open(os.devnull, "w"), 64 cwd=builddir, 65 env={"LANG": "C"}, 66 universal_newlines=True) 67 return out 68 69 70def get_elf_arch_tag(builddir, prefix, fpath, tag): 71 """ 72 Runs the cross readelf on 'fpath', then extracts the value of tag 'tag'. 73 Example: 74 >>> get_elf_arch_tag('output', 'arm-none-linux-gnueabi-', 75 'bin/busybox', 'Tag_CPU_arch') 76 v5TEJ 77 >>> 78 """ 79 cmd = ["host/bin/{}-readelf".format(prefix), 80 "-A", os.path.join("target", fpath)] 81 out = run_cmd_on_host(builddir, cmd) 82 regexp = re.compile(r"^ {}: (.*)$".format(tag)) 83 for line in out.splitlines(): 84 m = regexp.match(line) 85 if not m: 86 continue 87 return m.group(1) 88 return None 89 90 91def get_file_arch(builddir, prefix, fpath): 92 return get_elf_arch_tag(builddir, prefix, fpath, "Tag_CPU_arch") 93 94 95def get_elf_prog_interpreter(builddir, prefix, fpath): 96 """ 97 Runs the cross readelf on 'fpath' to extract the program interpreter 98 name and returns it. 99 Example: 100 >>> get_elf_prog_interpreter('br-tests/TestExternalToolchainLinaroArm', 101 'arm-linux-gnueabihf', 102 'bin/busybox') 103 /lib/ld-linux-armhf.so.3 104 >>> 105 """ 106 cmd = ["host/bin/{}-readelf".format(prefix), 107 "-l", os.path.join("target", fpath)] 108 out = run_cmd_on_host(builddir, cmd) 109 regexp = re.compile(r"^ *\[Requesting program interpreter: (.*)\]$") 110 for line in out.splitlines(): 111 m = regexp.match(line) 112 if not m: 113 continue 114 return m.group(1) 115 return None 116 117 118def img_round_power2(img): 119 """ 120 Rounds up the size of an image file to the next power of 2 121 """ 122 sz = os.stat(img).st_size 123 pow2 = 1 124 while pow2 < sz: 125 pow2 = pow2 << 1 126 with open(img, 'ab') as f: 127 f.truncate(pow2) 128