external.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. import os.path
  2. import re
  3. import shlex
  4. import subprocess
  5. import oe.path
  6. import bb
  7. def run(d, cmd, *args):
  8. topdir = d.getVar('TOPDIR')
  9. toolchain_path = d.getVar('EXTERNAL_TOOLCHAIN')
  10. if toolchain_path:
  11. target_prefix = d.getVar('EXTERNAL_TARGET_SYS') + '-'
  12. if not cmd.startswith(target_prefix):
  13. cmd = target_prefix + cmd
  14. toolchain_bin = d.getVar('EXTERNAL_TOOLCHAIN_BIN')
  15. path = os.path.join(toolchain_bin, cmd)
  16. args = shlex.split(path) + list(args)
  17. bb.debug(1, 'oe.external.run({})'.format(repr(args)))
  18. try:
  19. output, _ = bb.process.run(args, cwd=topdir, stderr=subprocess.STDOUT)
  20. except bb.process.CmdError as exc:
  21. bb.debug(1, 'oe.external.run: {} failed: {}'.format(subprocess.list2cmdline(args), exc))
  22. else:
  23. return output
  24. return 'UNKNOWN'
  25. def parse_mirrors(mirrors_string):
  26. mirrors, invalid = [], []
  27. for entry in mirrors_string.replace('\\n', '\n').split('\n'):
  28. entry = entry.strip()
  29. if not entry:
  30. continue
  31. try:
  32. pathname, subst = entry.strip().split('|', 1)
  33. except ValueError:
  34. invalid.append(entry)
  35. mirrors.append(('^' + re.escape(pathname), subst))
  36. return mirrors, invalid
  37. def get_file_search_metadata(d):
  38. '''Given the metadata, return the mirrors and sysroots to operate against.'''
  39. premirrors, invalid = parse_mirrors(d.getVar('FILES_PREMIRRORS'))
  40. for invalid_entry in invalid:
  41. bb.warn('Invalid FILES_MIRRORS entry: {0}'.format(invalid_entry))
  42. mirrors, invalid = parse_mirrors(d.getVar('FILES_MIRRORS'))
  43. for invalid_entry in invalid:
  44. bb.warn('Invalid FILES_MIRRORS entry: {0}'.format(invalid_entry))
  45. source_paths = [os.path.realpath(p)
  46. for p in d.getVar('EXTERNAL_INSTALL_SOURCE_PATHS').split()]
  47. return source_paths, mirrors, premirrors
  48. def gather_pkg_files(d):
  49. '''Given the metadata, return all the files we want to copy to ${D} for
  50. this recipe.'''
  51. import itertools
  52. files = []
  53. for pkg in d.getVar('PACKAGES').split():
  54. files = itertools.chain(files, (d.getVar('EXTERNAL_FILES_{}'.format(pkg)) or d.getVar('FILES:{}'.format(pkg)) or '').split())
  55. files = itertools.chain(files, d.getVar('EXTERNAL_EXTRA_FILES').split())
  56. return files
  57. def copy_from_sysroots(pathnames, sysroots, mirrors, premirrors, installdest):
  58. '''Copy the specified files from the specified sysroots, also checking the
  59. specified mirror patterns as alternate paths, to the specified destination.'''
  60. expanded_pathnames = expand_paths(pathnames, mirrors, premirrors)
  61. searched_paths = search_sysroots(expanded_pathnames, sysroots)
  62. for path, files in searched_paths:
  63. if not files:
  64. bb.debug(1, 'oe.external: failed to find `{}`'.format(path))
  65. else:
  66. destdir = oe.path.join(installdest, os.path.dirname(path))
  67. bb.utils.mkdirhier(destdir)
  68. subprocess.check_call(['cp', '-PR', '--preserve=mode,timestamps', '--no-preserve=ownership'] + list(files) + [destdir + '/'])
  69. bb.note('Copied `{}` to `{}/`'.format(', '.join(files), destdir))
  70. def expand_paths(pathnames, mirrors, premirrors):
  71. '''Apply search/replace to paths to get alternate search paths.
  72. Returns a generator with tuples of (pathname, expanded_paths).'''
  73. import re
  74. for pathname in pathnames:
  75. expanded_paths = []
  76. for search, replace in premirrors:
  77. try:
  78. new_pathname = re.sub(search, replace, pathname, count=1)
  79. except re.error as exc:
  80. bb.warn("Invalid pattern for `%s`" % search)
  81. continue
  82. if new_pathname != pathname:
  83. expanded_paths.append(new_pathname)
  84. expanded_paths.append(pathname)
  85. for search, replace in mirrors:
  86. try:
  87. new_pathname = re.sub(search, replace, pathname, count=1)
  88. except re.error as exc:
  89. bb.warn("Invalid pattern for `%s`" % search)
  90. continue
  91. if new_pathname != pathname:
  92. expanded_paths.append(new_pathname)
  93. yield pathname, expanded_paths
  94. def search_sysroots(path_entries, sysroots):
  95. '''Search the supplied sysroots for the supplied paths, checking supplied
  96. alternate paths. Expects entries in the format (pathname, all_paths).
  97. Returns a generator with tuples of (pathname, found_paths).'''
  98. import glob
  99. import itertools
  100. for path, pathnames in path_entries:
  101. for sysroot, pathname in ((s, p) for s in sysroots
  102. for p in pathnames):
  103. check_path = sysroot + os.sep + pathname
  104. found_paths = glob.glob(check_path)
  105. if found_paths:
  106. yield path, found_paths
  107. break
  108. else:
  109. yield path, None
  110. def find_sysroot_files(paths, d):
  111. sysroots, mirrors, premirrors = get_file_search_metadata(d)
  112. expanded = expand_paths(paths, mirrors, premirrors)
  113. search_results = list(search_sysroots(expanded, sysroots))
  114. return [v for k, v in search_results]