__init__.py 4.3 KB

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