tcmode-external-oe-sdk.inc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. require conf/distro/include/tcmode-external.inc
  2. # OE-built toolchains default to this, so don't pass it explicitly
  3. TARGET_LDFLAGS_BUILD_ID = ""
  4. # OE-built toolchains assume en_US is utf8
  5. EXTERNAL_TOOLCHAIN_FEATURES_DEFAULT ??= "locale-utf8-is-default"
  6. TCMODEOVERRIDES .= ":tcmode-external-oe-sdk"
  7. EXTERNAL_TARGET_SYS ?= "${TARGET_SYS}"
  8. EXTERNAL_SDK_SYS ?= "${SDK_SYS}"
  9. EXTERNAL_TOOLCHAIN_BIN = "${EXTERNAL_TOOLCHAIN}/sysroots/${EXTERNAL_SDK_SYS}/usr/bin/${EXTERNAL_TARGET_SYS}"
  10. EXTERNAL_MULTIMACH_TARGET_SYS ?= "${MULTIMACH_TARGET_SYS}"
  11. EXTERNAL_TOOLCHAIN_SYSROOT = "${EXTERNAL_TOOLCHAIN}/sysroots/${EXTERNAL_MULTIMACH_TARGET_SYS}"
  12. EXTERNAL_CC = "${EXTERNAL_TARGET_SYS}-gcc --sysroot=${EXTERNAL_TOOLCHAIN_SYSROOT}"
  13. EXTERNAL_TOOLCHAIN_FEATURES:append = " locale-utf8-is-default"
  14. EXTERNAL_SETUP_SCRIPT_VARS ?= ""
  15. # Our headers are already multilib
  16. oe_multilib_header:pn-glibc-external = ":"
  17. EXTERNAL_TOOLCHAINS ??= "${EXTERNAL_TOOLCHAIN}"
  18. python extract_env_setup_metadata() {
  19. from pathlib import Path
  20. paths = [Path(p) for p in d.getVar('EXTERNAL_TOOLCHAINS').split()]
  21. paths = [p for p in paths if p.is_absolute() and p.is_dir()]
  22. if paths:
  23. setup_external_vars(paths, d, d)
  24. localdata = bb.data.createCopy(d)
  25. variants = d.getVar('MULTILIB_VARIANTS') or ''
  26. for item in variants.split():
  27. # Load overrides from 'd' to avoid having to reset the value...
  28. overrides = d.getVar('OVERRIDES', False) + ':virtclass-multilib-' + item
  29. localdata.setVar('OVERRIDES', overrides)
  30. localdata.setVar('MLPREFIX', item + '-')
  31. setup_external_vars(paths, localdata, d)
  32. }
  33. extract_env_setup_metadata[eventmask] = "bb.event.ConfigParsed"
  34. addhandler extract_env_setup_metadata
  35. def setup_external_vars(paths, localdata, d):
  36. from pathlib import Path
  37. setup, env = get_setup_script_env(paths, localdata)
  38. mlprefix = localdata.getVar('MLPREFIX')
  39. if mlprefix:
  40. suffix = '_virtclass-multilib-' + mlprefix[:-1]
  41. else:
  42. suffix = ''
  43. d.setVar('EXTERNAL_TOOLCHAIN' + suffix, str(setup.parent))
  44. for var in localdata.getVar('EXTERNAL_SETUP_SCRIPT_VARS').split():
  45. d.setVar('EXTERNAL_' + var + suffix, env.get(var) or '')
  46. target_sys = env.get('TARGET_PREFIX')[:-1]
  47. native_sysroot = Path(env.get('OECORE_NATIVE_SYSROOT'))
  48. if str(native_sysroot).startswith('$scriptdir/'):
  49. native_sysroot = setup.parent / native_sysroot.relative_to('$scriptdir')
  50. target_sysroot = Path(env.get('SDKTARGETSYSROOT'))
  51. if str(target_sysroot).startswith('$scriptdir/'):
  52. target_sysroot = setup.parent / target_sysroot.relative_to('$scriptdir')
  53. d.setVar('EXTERNAL_TARGET_SYS' + suffix, str(target_sys))
  54. d.setVar('EXTERNAL_TOOLCHAIN_BIN' + suffix, str(native_sysroot / 'usr' / 'bin' / target_sys))
  55. d.setVar('EXTERNAL_TOOLCHAIN_SYSROOT' + suffix, str(target_sysroot))
  56. # These are treated as prefixes to items in PACKAGE_ARCHS at this time.
  57. #
  58. # An armv7-a sysroot will run fine with armv7ve machines, as the latter just
  59. # have virtualization extensions. We need to handle this sort of thing
  60. # directly in this case, as for some reason the armv7-a tunes aren't listed in
  61. # the armv7ve PACKAGE_ARCHS.
  62. EXTERNAL_TOOLCHAIN_ARCH_COMPAT[armv7ve] += "armv7a"
  63. def select_appropriate_setup_script(d, paths):
  64. from itertools import chain
  65. from pathlib import Path
  66. candidates = []
  67. tune_pkgarch = d.getVar('TUNE_PKGARCH')
  68. arch_setups = list(chain.from_iterable(Path(path).glob('environment-setup-' + tune_pkgarch + '-*') for path in paths))
  69. if arch_setups:
  70. # Exact match, skip processing
  71. for setup in arch_setups:
  72. setup_env = parse_setup_script(setup)
  73. candidates.append((setup, setup_env))
  74. return candidates
  75. target_arch = d.getVar('TARGET_ARCH')
  76. target_os = d.getVar('TARGET_OS')
  77. baselib = d.getVar('baselib')
  78. package_archs = d.getVar('PACKAGE_ARCHS').split()
  79. arch_compat = d.getVarFlags('EXTERNAL_TOOLCHAIN_ARCH_COMPAT')
  80. setups = chain.from_iterable(Path(path).glob('environment-setup-*') for path in paths)
  81. for setup in setups:
  82. setup_env = parse_setup_script(setup)
  83. if target_arch != setup_get(setup_env, 'OECORE_TARGET_ARCH'):
  84. bb.debug(1, "tcmode-external-oe-sdk: TARGET_ARCH `{}` doesn't match `{}` in `{}`".format(target_arch, setup_get(setup_env, 'OECORE_TARGET_ARCH'), setup))
  85. continue
  86. if target_os != setup_get(setup_env, 'OECORE_TARGET_OS'):
  87. bb.debug(1, "tcmode-external-oe-sdk: TARGET_OS `{}` doesn't match `{}` in `{}`".format(target_os, setup_get(setup_env, 'OECORE_TARGET_OS'), setup))
  88. continue
  89. if baselib != setup_get(setup_env, 'OECORE_BASELIB'):
  90. bb.debug(1, "tcmode-external-oe-sdk: BASELIB `{}` doesn't match `{}` in `{}`".format(baselib, setup_get(setup_env, 'OECORE_BASELIB'), setup))
  91. continue
  92. setup_tune_pkgarch = setup_env.get('TUNE_PKGARCH')
  93. if setup_tune_pkgarch:
  94. if setup_tune_pkgarch not in package_archs:
  95. compatible = False
  96. for from_arch, compat_archs in arch_compat.items():
  97. for compat_arch in compat_archs.split():
  98. adjusted_archs = [a.replace(from_arch, compat_arch) for a in package_archs]
  99. if setup_tune_pkgarch in adjusted_archs:
  100. compatible = True
  101. if not compatible:
  102. bb.debug(1, "tcmode-external-oe-sdk: skipping incompatible {}: TUNE_PKGARCH `{}` not found in PACKAGE_ARCHS `{}`".format(setup, setup_tune_pkgarch, package_archs))
  103. continue
  104. candidates.append((setup, setup_env))
  105. return candidates
  106. def get_setup_script_env(paths, d):
  107. from pathlib import Path
  108. setup = d.getVar('EXTERNAL_TOOLCHAIN_SETUP_SCRIPT')
  109. if setup:
  110. setup = Path(setup)
  111. env = parse_setup_script(setup)
  112. else:
  113. candidates = select_appropriate_setup_script(d, paths)
  114. if not candidates:
  115. setup = None
  116. elif len(candidates) > 1:
  117. bb.fatal("tcmode-external-oe-sdk: multiple candidate setup scripts found, please specify with EXTERNAL_TOOLCHAIN_SETUP_SCRIPT: {}".format(" ".join(str(p) for p, e in candidates)))
  118. else:
  119. setup, env = candidates[0]
  120. bb.debug(1, "tcmode-external-oe-sdk: selected setup script {}".format(setup))
  121. if not setup:
  122. bb.fatal("tcmode-external-oe-sdk: no compatible toolchain for tuning `{}` found in TOOLCHAIN_PATHS ({})".format(d.getVar("TUNE_PKGARCH"), ", ".join(str(p) for p in paths)))
  123. return setup, env
  124. def setup_get(setup, field):
  125. if not field in setup:
  126. bb.fatal("tcmode-external-oe-sdk: no variable `{}` found in `{}`".format(field, setup))
  127. return setup[field]
  128. def parse_setup_script(setup):
  129. import shlex
  130. import subprocess
  131. with open(setup, 'r') as f:
  132. value = f.read()
  133. values = {}
  134. for line in value.splitlines():
  135. if line.split():
  136. split = shlex.split(line)
  137. if len(split) == 2 and split[0] == 'export':
  138. split = split[1:]
  139. if len(split) == 1:
  140. try:
  141. k, v = split[0].split('=', 1)
  142. except ValueError:
  143. continue
  144. else:
  145. values[k] = v
  146. return values