populate_sdk_ext.bbclass 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. # Extensible SDK
  2. inherit populate_sdk_base
  3. # NOTE: normally you cannot use task overrides for this kind of thing - this
  4. # only works because of get_sdk_ext_rdepends()
  5. TOOLCHAIN_HOST_TASK_task-populate-sdk-ext = " \
  6. meta-environment-extsdk-${MACHINE} \
  7. "
  8. TOOLCHAIN_TARGET_TASK_task-populate-sdk-ext = ""
  9. SDK_RDEPENDS_append_task-populate-sdk-ext = " ${SDK_TARGETS}"
  10. SDK_RELOCATE_AFTER_INSTALL_task-populate-sdk-ext = "0"
  11. SDK_EXT = ""
  12. SDK_EXT_task-populate-sdk-ext = "-ext"
  13. SDK_LOCAL_CONF_WHITELIST ?= ""
  14. SDK_LOCAL_CONF_BLACKLIST ?= "CONF_VERSION BB_NUMBER_THREADS PARALLEL_MAKE PRSERV_HOST"
  15. SDK_INHERIT_BLACKLIST ?= "buildhistory icecc"
  16. SDK_UPDATE_URL ?= ""
  17. SDK_TARGETS ?= "${PN}"
  18. OE_INIT_ENV_SCRIPT ?= "oe-init-build-env"
  19. # The files from COREBASE that you want preserved in the COREBASE copied
  20. # into the sdk. This allows someone to have their own setup scripts in
  21. # COREBASE be preserved as well as untracked files.
  22. COREBASE_FILES ?= " \
  23. oe-init-build-env \
  24. oe-init-build-env-memres \
  25. scripts \
  26. LICENSE \
  27. .templateconf \
  28. "
  29. SDK_DIR_task-populate-sdk-ext = "${WORKDIR}/sdk-ext"
  30. B_task-populate-sdk-ext = "${SDK_DIR}"
  31. TOOLCHAIN_OUTPUTNAME_task-populate-sdk-ext = "${SDK_NAME}-toolchain-ext-${SDK_VERSION}"
  32. SDK_TITLE_task-populate-sdk-ext = "${@d.getVar('DISTRO_NAME', True) or d.getVar('DISTRO', True)} Extensible SDK"
  33. python copy_buildsystem () {
  34. import re
  35. import oe.copy_buildsystem
  36. oe_init_env_script = d.getVar('OE_INIT_ENV_SCRIPT', True)
  37. conf_bbpath = ''
  38. conf_initpath = ''
  39. core_meta_subdir = ''
  40. # Copy in all metadata layers + bitbake (as repositories)
  41. buildsystem = oe.copy_buildsystem.BuildSystem('extensible SDK', d)
  42. baseoutpath = d.getVar('SDK_OUTPUT', True) + '/' + d.getVar('SDKPATH', True)
  43. layers_copied = buildsystem.copy_bitbake_and_layers(baseoutpath + '/layers')
  44. sdkbblayers = []
  45. corebase = os.path.basename(d.getVar('COREBASE', True))
  46. for layer in layers_copied:
  47. if corebase == os.path.basename(layer):
  48. conf_bbpath = os.path.join('layers', layer, 'bitbake')
  49. else:
  50. sdkbblayers.append(layer)
  51. for path in os.listdir(baseoutpath + '/layers'):
  52. relpath = os.path.join('layers', path, oe_init_env_script)
  53. if os.path.exists(os.path.join(baseoutpath, relpath)):
  54. conf_initpath = relpath
  55. relpath = os.path.join('layers', path, 'scripts', 'devtool')
  56. if os.path.exists(os.path.join(baseoutpath, relpath)):
  57. scriptrelpath = os.path.dirname(relpath)
  58. relpath = os.path.join('layers', path, 'meta')
  59. if os.path.exists(os.path.join(baseoutpath, relpath, 'lib', 'oe')):
  60. core_meta_subdir = relpath
  61. d.setVar('oe_init_build_env_path', conf_initpath)
  62. d.setVar('scriptrelpath', scriptrelpath)
  63. # Write out config file for devtool
  64. import ConfigParser
  65. config = ConfigParser.SafeConfigParser()
  66. config.add_section('General')
  67. config.set('General', 'bitbake_subdir', conf_bbpath)
  68. config.set('General', 'init_path', conf_initpath)
  69. config.set('General', 'core_meta_subdir', core_meta_subdir)
  70. config.add_section('SDK')
  71. config.set('SDK', 'sdk_targets', d.getVar('SDK_TARGETS', True))
  72. updateurl = d.getVar('SDK_UPDATE_URL', True)
  73. if updateurl:
  74. config.set('SDK', 'updateserver', updateurl)
  75. bb.utils.mkdirhier(os.path.join(baseoutpath, 'conf'))
  76. with open(os.path.join(baseoutpath, 'conf', 'devtool.conf'), 'w') as f:
  77. config.write(f)
  78. # Create a layer for new recipes / appends
  79. bbpath = d.getVar('BBPATH', True)
  80. bb.process.run(['devtool', '--bbpath', bbpath, '--basepath', baseoutpath, 'create-workspace', '--create-only', os.path.join(baseoutpath, 'workspace')])
  81. # Create bblayers.conf
  82. bb.utils.mkdirhier(baseoutpath + '/conf')
  83. with open(baseoutpath + '/conf/bblayers.conf', 'w') as f:
  84. f.write('# WARNING: this configuration has been automatically generated and in\n')
  85. f.write('# most cases should not be edited. If you need more flexibility than\n')
  86. f.write('# this configuration provides, it is strongly suggested that you set\n')
  87. f.write('# up a proper instance of the full build system and use that instead.\n\n')
  88. f.write('LCONF_VERSION = "%s"\n\n' % d.getVar('LCONF_VERSION', False))
  89. f.write('BBPATH = "$' + '{TOPDIR}"\n')
  90. f.write('SDKBASEMETAPATH = "$' + '{TOPDIR}"\n')
  91. f.write('BBLAYERS := " \\\n')
  92. for layerrelpath in sdkbblayers:
  93. f.write(' $' + '{SDKBASEMETAPATH}/layers/%s \\\n' % layerrelpath)
  94. f.write(' $' + '{SDKBASEMETAPATH}/workspace \\\n')
  95. f.write(' "\n')
  96. # Create local.conf
  97. local_conf_whitelist = (d.getVar('SDK_LOCAL_CONF_WHITELIST', True) or '').split()
  98. local_conf_blacklist = (d.getVar('SDK_LOCAL_CONF_BLACKLIST', True) or '').split()
  99. def handle_var(varname, origvalue, op, newlines):
  100. if varname in local_conf_blacklist or (origvalue.strip().startswith('/') and not varname in local_conf_whitelist):
  101. newlines.append('# Removed original setting of %s\n' % varname)
  102. return None, op, 0, True
  103. else:
  104. return origvalue, op, 0, True
  105. varlist = ['[^#=+ ]*']
  106. builddir = d.getVar('TOPDIR', True)
  107. with open(builddir + '/conf/local.conf', 'r') as f:
  108. oldlines = f.readlines()
  109. (updated, newlines) = bb.utils.edit_metadata(oldlines, varlist, handle_var)
  110. with open(baseoutpath + '/conf/local.conf', 'w') as f:
  111. f.write('# WARNING: this configuration has been automatically generated and in\n')
  112. f.write('# most cases should not be edited. If you need more flexibility than\n')
  113. f.write('# this configuration provides, it is strongly suggested that you set\n')
  114. f.write('# up a proper instance of the full build system and use that instead.\n\n')
  115. for line in newlines:
  116. if line.strip() and not line.startswith('#'):
  117. f.write(line)
  118. # Write a newline just in case there's none at the end of the original
  119. f.write('\n')
  120. f.write('INHERIT += "%s"\n\n' % 'uninative')
  121. f.write('CONF_VERSION = "%s"\n\n' % d.getVar('CONF_VERSION', False))
  122. # Some classes are not suitable for SDK, remove them from INHERIT
  123. f.write('INHERIT_remove = "%s"\n' % d.getVar('SDK_INHERIT_BLACKLIST', False))
  124. # Bypass the default connectivity check if any
  125. f.write('CONNECTIVITY_CHECK_URIS = ""\n\n')
  126. # Ensure locked sstate cache objects are re-used without error
  127. f.write('SIGGEN_LOCKEDSIGS_CHECK_LEVEL = "none"\n\n')
  128. # Hide the config information from bitbake output (since it's fixed within the SDK)
  129. f.write('BUILDCFG_HEADER = ""\n')
  130. # If you define a sdk_extraconf() function then it can contain additional config
  131. extraconf = (d.getVar('sdk_extraconf', True) or '').strip()
  132. if extraconf:
  133. # Strip off any leading / trailing spaces
  134. for line in extraconf.splitlines():
  135. f.write(line.strip() + '\n')
  136. f.write('require conf/locked-sigs.inc\n')
  137. if os.path.exists(builddir + '/conf/auto.conf'):
  138. with open(builddir + '/conf/auto.conf', 'r') as f:
  139. oldlines = f.readlines()
  140. (updated, newlines) = bb.utils.edit_metadata(oldlines, varlist, handle_var)
  141. with open(baseoutpath + '/conf/auto.conf', 'w') as f:
  142. f.write('# WARNING: this configuration has been automatically generated and in\n')
  143. f.write('# most cases should not be edited. If you need more flexibility than\n')
  144. f.write('# this configuration provides, it is strongly suggested that you set\n')
  145. f.write('# up a proper instance of the full build system and use that instead.\n\n')
  146. for line in newlines:
  147. if line.strip() and not line.startswith('#'):
  148. f.write(line)
  149. sigfile = d.getVar('WORKDIR', True) + '/locked-sigs.inc'
  150. oe.copy_buildsystem.generate_locked_sigs(sigfile, d)
  151. # Filter the locked signatures file to just the sstate tasks we are interested in
  152. excluded_targets = d.getVar('SDK_TARGETS', True)
  153. lockedsigs_pruned = baseoutpath + '/conf/locked-sigs.inc'
  154. oe.copy_buildsystem.prune_lockedsigs([],
  155. excluded_targets.split(),
  156. sigfile,
  157. lockedsigs_pruned)
  158. sstate_out = baseoutpath + '/sstate-cache'
  159. bb.utils.remove(sstate_out, True)
  160. # uninative.bbclass sets NATIVELSBSTRING to 'universal'
  161. fixedlsbstring = 'universal'
  162. oe.copy_buildsystem.create_locked_sstate_cache(lockedsigs_pruned,
  163. d.getVar('SSTATE_DIR', True),
  164. sstate_out, d,
  165. fixedlsbstring)
  166. # We don't need sstate do_package files
  167. for root, dirs, files in os.walk(sstate_out):
  168. for name in files:
  169. if name.endswith("_package.tgz"):
  170. f = os.path.join(root, name)
  171. os.remove(f)
  172. }
  173. def extsdk_get_buildtools_filename(d):
  174. return '*-buildtools-nativesdk-standalone-*.sh'
  175. install_tools() {
  176. install -d ${SDK_OUTPUT}/${SDKPATHNATIVE}${bindir_nativesdk}
  177. lnr ${SDK_OUTPUT}/${SDKPATH}/${scriptrelpath}/devtool ${SDK_OUTPUT}/${SDKPATHNATIVE}${bindir_nativesdk}/devtool
  178. lnr ${SDK_OUTPUT}/${SDKPATH}/${scriptrelpath}/recipetool ${SDK_OUTPUT}/${SDKPATHNATIVE}${bindir_nativesdk}/recipetool
  179. touch ${SDK_OUTPUT}/${SDKPATH}/.devtoolbase
  180. # find latest buildtools-tarball and install it
  181. buildtools_path=`ls -t1 ${SDK_DEPLOY}/${@extsdk_get_buildtools_filename(d)} | head -n1`
  182. install $buildtools_path ${SDK_OUTPUT}/${SDKPATH}
  183. install ${SDK_DEPLOY}/${BUILD_ARCH}-nativesdk-libc.tar.bz2 ${SDK_OUTPUT}/${SDKPATH}
  184. install -m 0644 ${COREBASE}/meta/files/ext-sdk-prepare.py ${SDK_OUTPUT}/${SDKPATH}
  185. }
  186. # Since bitbake won't run as root it doesn't make sense to try and install
  187. # the extensible sdk as root.
  188. sdk_ext_preinst() {
  189. if [ "`id -u`" = "0" ]; then
  190. echo "ERROR: The extensible sdk cannot be installed as root."
  191. exit 1
  192. fi
  193. SDK_EXTENSIBLE="1"
  194. }
  195. SDK_PRE_INSTALL_COMMAND_task-populate-sdk-ext = "${sdk_ext_preinst}"
  196. # FIXME this preparation should be done as part of the SDK construction
  197. sdk_ext_postinst() {
  198. printf "\nExtracting buildtools...\n"
  199. cd $target_sdk_dir
  200. printf "buildtools\ny" | ./*buildtools-nativesdk-standalone* > /dev/null || ( printf 'ERROR: buildtools installation failed\n' ; exit 1 )
  201. # Make sure when the user sets up the environment, they also get
  202. # the buildtools-tarball tools in their path.
  203. env_setup_script="$target_sdk_dir/environment-setup-${REAL_MULTIMACH_TARGET_SYS}"
  204. echo ". $target_sdk_dir/buildtools/environment-setup*" >> $env_setup_script
  205. # Allow bitbake environment setup to be ran as part of this sdk.
  206. echo "export OE_SKIP_SDK_CHECK=1" >> $env_setup_script
  207. # A bit of another hack, but we need this in the path only for devtool
  208. # so put it at the end of $PATH.
  209. echo "export PATH=\$PATH:$target_sdk_dir/sysroots/${SDK_SYS}/${bindir_nativesdk}" >> $env_setup_script
  210. echo "printf 'SDK environment now set up; additionally you may now run devtool to perform development tasks.\nRun devtool --help for further details.\n'" >> $env_setup_script
  211. # Warn if trying to use external bitbake and the ext SDK together
  212. echo "(which bitbake > /dev/null 2>&1 && echo 'WARNING: attempting to use the extensible SDK in an environment set up to run bitbake - this may lead to unexpected results. Please source this script in a new shell session instead.') || true" >> $env_setup_script
  213. # For now this is where uninative.bbclass expects the tarball
  214. mv *-nativesdk-libc.tar.* $target_sdk_dir/`dirname ${oe_init_build_env_path}`
  215. if [ "$prepare_buildsystem" != "no" ]; then
  216. printf "Preparing build system...\n"
  217. # dash which is /bin/sh on Ubuntu will not preserve the
  218. # current working directory when first ran, nor will it set $1 when
  219. # sourcing a script. That is why this has to look so ugly.
  220. LOGFILE="$target_sdk_dir/preparing_build_system.log"
  221. sh -c ". buildtools/environment-setup* > $LOGFILE && cd $target_sdk_dir/`dirname ${oe_init_build_env_path}` && set $target_sdk_dir && . $target_sdk_dir/${oe_init_build_env_path} $target_sdk_dir >> $LOGFILE && python $target_sdk_dir/ext-sdk-prepare.py '${SDK_TARGETS}' >> $LOGFILE 2>&1" || { echo "ERROR: SDK preparation failed: see $LOGFILE"; echo "printf 'ERROR: this SDK was not fully installed and needs reinstalling\n'" >> $env_setup_script ; exit 1 ; }
  222. fi
  223. echo done
  224. }
  225. SDK_POST_INSTALL_COMMAND_task-populate-sdk-ext = "${sdk_ext_postinst}"
  226. SDK_POSTPROCESS_COMMAND_prepend_task-populate-sdk-ext = "copy_buildsystem; install_tools; "
  227. fakeroot python do_populate_sdk_ext() {
  228. # FIXME hopefully we can remove this restriction at some point, but uninative
  229. # currently forces this upon us
  230. if d.getVar('SDK_ARCH', True) != d.getVar('BUILD_ARCH', True):
  231. bb.fatal('The extensible SDK can currently only be built for the same architecture as the machine being built on - SDK_ARCH is set to %s (likely via setting SDKMACHINE) which is different from the architecture of the build machine (%s). Unable to continue.' % (d.getVar('SDK_ARCH', True), d.getVar('BUILD_ARCH', True)))
  232. bb.build.exec_func("do_populate_sdk", d)
  233. }
  234. def get_sdk_ext_rdepends(d):
  235. localdata = d.createCopy()
  236. localdata.appendVar('OVERRIDES', ':task-populate-sdk-ext')
  237. bb.data.update_data(localdata)
  238. return localdata.getVarFlag('do_populate_sdk', 'rdepends', True)
  239. do_populate_sdk_ext[dirs] = "${@d.getVarFlag('do_populate_sdk', 'dirs', False)}"
  240. do_populate_sdk_ext[depends] += "${@d.getVarFlag('do_populate_sdk', 'depends', False)}"
  241. do_populate_sdk_ext[rdepends] = "${@get_sdk_ext_rdepends(d)}"
  242. do_populate_sdk_ext[recrdeptask] += "${@d.getVarFlag('do_populate_sdk', 'recrdeptask', False)}"
  243. do_populate_sdk_ext[depends] += "buildtools-tarball:do_populate_sdk uninative-tarball:do_populate_sdk"
  244. do_populate_sdk_ext[rdepends] += "${@' '.join([x + ':do_build' for x in d.getVar('SDK_TARGETS', True).split()])}"
  245. do_populate_sdk_ext[recrdeptask] += "do_populate_lic do_package_qa do_populate_sysroot do_deploy"
  246. # Make sure codes change in copy_buildsystem can result in rebuilt
  247. do_populate_sdk_ext[vardeps] += "copy_buildsystem"
  248. addtask populate_sdk_ext