install-buildtools 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #!/usr/bin/env python3
  2. # Buildtools and buildtools extended installer helper script
  3. #
  4. # Copyright (C) 2017-2020 Intel Corporation
  5. #
  6. # SPDX-License-Identifier: MIT
  7. #
  8. # NOTE: --with-extended-buildtools is on by default
  9. #
  10. # Example usage (extended buildtools from milestone):
  11. # (1) using --url and --filename
  12. # $ install-buildtools \
  13. # --url http://downloads.yoctoproject.org/releases/yocto/milestones/yocto-3.1_M2/buildtools \
  14. # --filename x86_64-buildtools-extended-nativesdk-standalone-3.0+snapshot-20200122.sh
  15. # (2) using --base-url, --release, --installer-version and --build-date
  16. # $ install-buildtools \
  17. # --base-url http://downloads.yoctoproject.org/releases/yocto \
  18. # --release yocto-3.1_M2 \
  19. # --installer-version 3.0+snapshot
  20. # --build-date 202000122
  21. #
  22. # Example usage (standard buildtools from release):
  23. # (3) using --url and --filename
  24. # $ install-buildtools --without-extended-buildtools \
  25. # --url http://downloads.yoctoproject.org/releases/yocto/yocto-3.0.2/buildtools \
  26. # --filename x86_64-buildtools-nativesdk-standalone-3.0.2.sh
  27. # (4) using --base-url, --release and --installer-version
  28. # $ install-buildtools --without-extended-buildtools \
  29. # --base-url http://downloads.yoctoproject.org/releases/yocto \
  30. # --release yocto-3.0.2 \
  31. # --installer-version 3.0.2
  32. #
  33. import argparse
  34. import logging
  35. import os
  36. import re
  37. import shutil
  38. import stat
  39. import subprocess
  40. import sys
  41. import tempfile
  42. from urllib.parse import quote
  43. scripts_path = os.path.dirname(os.path.realpath(__file__))
  44. lib_path = scripts_path + '/lib'
  45. sys.path = sys.path + [lib_path]
  46. import scriptutils
  47. import scriptpath
  48. # Figure out where is the bitbake/lib/bb since we need bb.utils.md5_file
  49. bitbakepath = scriptpath.add_bitbake_lib_path()
  50. if not bitbakepath:
  51. sys.stderr.write("Unable to find bitbake by searching parent directory "
  52. "of this script or PATH\n")
  53. sys.exit(1)
  54. PROGNAME = 'install-buildtools'
  55. logger = scriptutils.logger_create(PROGNAME, stream=sys.stdout)
  56. DEFAULT_INSTALL_DIR: str = os.path.join(os.path.split(scripts_path)[0],'buildtools')
  57. DEFAULT_BASE_URL: str = 'http://downloads.yoctoproject.org/releases/yocto'
  58. DEFAULT_RELEASE: str = 'yocto-3.1_M2'
  59. DEFAULT_INSTALLER_VERSION: str = '3.0+snapshot'
  60. DEFAULT_BUILDDATE: str = "20200122"
  61. def main():
  62. global DEFAULT_INSTALL_DIR
  63. global DEFAULT_BASE_URL
  64. global DEFAULT_RELEASE
  65. global DEFAULT_INSTALLER_VERSION
  66. global DEFAULT_BUILDDATE
  67. filename: str = ""
  68. release: str = ""
  69. buildtools_url: str = ""
  70. install_dir: str = ""
  71. parser = argparse.ArgumentParser(
  72. description="Buildtools installation helper",
  73. add_help=False)
  74. parser.add_argument('-u', '--url',
  75. help='URL from where to fetch buildtools SDK installer, not '
  76. 'including filename (optional)\n'
  77. 'Requires --filename.',
  78. action='store')
  79. parser.add_argument('-f', '--filename',
  80. help='filename for the buildtools SDK installer to be installed '
  81. '(optional)\nRequires --url',
  82. action='store')
  83. parser.add_argument('-d', '--directory',
  84. default=DEFAULT_INSTALL_DIR,
  85. help='directory where buildtools SDK will be installed (optional)',
  86. action='store')
  87. parser.add_argument('-r', '--release',
  88. default=DEFAULT_RELEASE,
  89. help='Yocto Project release string for SDK which will be '
  90. 'installed (optional)',
  91. action='store')
  92. parser.add_argument('-V', '--installer-version',
  93. default=DEFAULT_INSTALLER_VERSION,
  94. help='version string for the SDK to be installed (optional)',
  95. action='store')
  96. parser.add_argument('-b', '--base-url',
  97. default=DEFAULT_BASE_URL,
  98. help='base URL from which to fetch SDK (optional)', action='store')
  99. parser.add_argument('-t', '--build-date',
  100. default=DEFAULT_BUILDDATE,
  101. help='Build date of pre-release SDK (optional)', action='store')
  102. group = parser.add_mutually_exclusive_group()
  103. group.add_argument('--with-extended-buildtools', action='store_true',
  104. dest='with_extended_buildtools',
  105. default=True,
  106. help='enable extended buildtools tarball (on by default)')
  107. group.add_argument('--without-extended-buildtools', action='store_false',
  108. dest='with_extended_buildtools',
  109. help='disable extended buildtools (traditional buildtools tarball)')
  110. parser.add_argument('-c', '--check', help='enable md5 checksum checking',
  111. default=True,
  112. action='store_true')
  113. parser.add_argument('-D', '--debug', help='enable debug output',
  114. action='store_true')
  115. parser.add_argument('-q', '--quiet', help='print only errors',
  116. action='store_true')
  117. parser.add_argument('-h', '--help', action='help',
  118. default=argparse.SUPPRESS,
  119. help='show this help message and exit')
  120. args = parser.parse_args()
  121. if args.debug:
  122. logger.setLevel(logging.DEBUG)
  123. elif args.quiet:
  124. logger.setLevel(logging.ERROR)
  125. if args.url and args.filename:
  126. logger.debug("--url and --filename detected. Ignoring --base-url "
  127. "--release --installer-version arguments.")
  128. filename = args.filename
  129. buildtools_url = "%s/%s" % (args.url, filename)
  130. else:
  131. if args.base_url:
  132. base_url = args.base_url
  133. else:
  134. base_url = DEFAULT_BASE_URL
  135. if args.release:
  136. # check if this is a pre-release "milestone" SDK
  137. m = re.search(r"^(?P<distro>[a-zA-Z\-]+)(?P<version>[0-9.]+)(?P<milestone>_M[1-9])$",
  138. args.release)
  139. logger.debug("milestone regex: %s" % m)
  140. if m and m.group('milestone'):
  141. logger.debug("release[distro]: %s" % m.group('distro'))
  142. logger.debug("release[version]: %s" % m.group('version'))
  143. logger.debug("release[milestone]: %s" % m.group('milestone'))
  144. if not args.build_date:
  145. logger.error("Milestone installers require --build-date")
  146. else:
  147. if args.with_extended_buildtools:
  148. filename = "x86_64-buildtools-extended-nativesdk-standalone-%s-%s.sh" % (
  149. args.installer_version, args.build_date)
  150. else:
  151. filename = "x86_64-buildtools-nativesdk-standalone-%s-%s.sh" % (
  152. args.installer_version, args.build_date)
  153. safe_filename = quote(filename)
  154. buildtools_url = "%s/milestones/%s/buildtools/%s" % (base_url, args.release, safe_filename)
  155. # regular release SDK
  156. else:
  157. if args.with_extended_buildtools:
  158. filename = "x86_64-buildtools-extended-nativesdk-standalone-%s.sh" % args.installer_version
  159. else:
  160. filename = "x86_64-buildtools-nativesdk-standalone-%s.sh" % args.installer_version
  161. safe_filename = quote(filename)
  162. buildtools_url = "%s/%s/buildtools/%s" % (base_url, args.release, safe_filename)
  163. tmpsdk_dir = tempfile.mkdtemp()
  164. try:
  165. # Fetch installer
  166. logger.info("Fetching buildtools installer")
  167. tmpbuildtools = os.path.join(tmpsdk_dir, filename)
  168. ret = subprocess.call("wget -q -O %s %s" %
  169. (tmpbuildtools, buildtools_url), shell=True)
  170. if ret != 0:
  171. logger.error("Could not download file from %s" % buildtools_url)
  172. return ret
  173. # Verify checksum
  174. if args.check:
  175. import bb
  176. logger.info("Fetching buildtools installer checksum")
  177. check_url = "{}.md5sum".format(buildtools_url)
  178. checksum_filename = "%s.md5sum" % filename
  179. tmpbuildtools_checksum = os.path.join(tmpsdk_dir, checksum_filename)
  180. ret = subprocess.call("wget -q -O %s %s" %
  181. (tmpbuildtools_checksum, check_url), shell=True)
  182. if ret != 0:
  183. logger.error("Could not download file from %s" % check_url)
  184. return ret
  185. regex = re.compile(r"^(?P<md5sum>[0-9a-f]+)\s\s(?P<path>.*/)(?P<filename>.*)$")
  186. with open(tmpbuildtools_checksum, 'rb') as f:
  187. original = f.read()
  188. m = re.search(regex, original.decode("utf-8"))
  189. logger.debug("md5sum: %s" % m.group('md5sum'))
  190. logger.debug("path: %s" % m.group('path'))
  191. logger.debug("filename: %s" % m.group('filename'))
  192. if filename != m.group('filename'):
  193. logger.error("Filename does not match name in checksum")
  194. return 1
  195. md5sum = m.group('md5sum')
  196. md5value = bb.utils.md5_file(tmpbuildtools)
  197. if md5sum == md5value:
  198. logger.info("Checksum success")
  199. else:
  200. logger.error("Checksum %s expected. Actual checksum is %s." %
  201. (md5sum, md5value))
  202. # Make installer executable
  203. logger.info("Making installer executable")
  204. st = os.stat(tmpbuildtools)
  205. os.chmod(tmpbuildtools, st.st_mode | stat.S_IEXEC)
  206. logger.debug(os.stat(tmpbuildtools))
  207. if args.directory:
  208. install_dir = args.directory
  209. ret = subprocess.call("%s -d %s -y" %
  210. (tmpbuildtools, install_dir), shell=True)
  211. else:
  212. install_dir = "/opt/poky/%s" % args.installer_version
  213. ret = subprocess.call("%s -y" % tmpbuildtools, shell=True)
  214. if ret != 0:
  215. logger.error("Could not run buildtools installer")
  216. # Test installation
  217. logger.info("Testing installation")
  218. tool = ""
  219. m = re.search("extended", tmpbuildtools)
  220. logger.debug("extended regex: %s" % m)
  221. if args.with_extended_buildtools and not m:
  222. logger.info("Ignoring --with-extended-buildtools as filename "
  223. "does not contain 'extended'")
  224. if args.with_extended_buildtools and m:
  225. tool = 'gcc'
  226. else:
  227. tool = 'tar'
  228. logger.debug("install_dir: %s" % install_dir)
  229. proc = subprocess.run(". %s/environment-setup-x86_64-pokysdk-linux && which %s" %
  230. (install_dir, tool),
  231. shell=True, stdout=subprocess.PIPE)
  232. which_tool = proc.stdout.decode("utf-8")
  233. logger.debug("which %s: %s" % (tool, which_tool))
  234. ret = proc.returncode
  235. if not which_tool.startswith(install_dir):
  236. logger.error("Something went wrong: %s not found in %s" %
  237. (tool, install_dir))
  238. if ret != 0:
  239. logger.error("Something went wrong: installation failed")
  240. else:
  241. logger.info("Installation successful. Remember to source the "
  242. "environment setup script now and in any new session.")
  243. return ret
  244. finally:
  245. # cleanup tmp directory
  246. shutil.rmtree(tmpsdk_dir)
  247. if __name__ == '__main__':
  248. try:
  249. ret = main()
  250. except Exception:
  251. ret = 1
  252. import traceback
  253. traceback.print_exc()
  254. sys.exit(ret)