tcmode-external-oe-sdk.inc 7.0 KB

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