summaryrefslogtreecommitdiffstats
path: root/meta/classes-recipe/image.bbclass
diff options
context:
space:
mode:
Diffstat (limited to 'meta/classes-recipe/image.bbclass')
-rw-r--r--meta/classes-recipe/image.bbclass120
1 files changed, 70 insertions, 50 deletions
diff --git a/meta/classes-recipe/image.bbclass b/meta/classes-recipe/image.bbclass
index 28be6c6362..24a19fce1a 100644
--- a/meta/classes-recipe/image.bbclass
+++ b/meta/classes-recipe/image.bbclass
@@ -30,7 +30,7 @@ POPULATE_SDK_POST_TARGET_COMMAND += "rootfs_sysroot_relativelinks"
30 30
31LICENSE ?= "MIT" 31LICENSE ?= "MIT"
32PACKAGES = "" 32PACKAGES = ""
33DEPENDS += "${@' '.join(["%s-qemuwrapper-cross" % m for m in d.getVar("MULTILIB_VARIANTS").split()])} qemuwrapper-cross depmodwrapper-cross cross-localedef-native" 33DEPENDS += "depmodwrapper-cross cross-localedef-native"
34RDEPENDS += "${PACKAGE_INSTALL} ${LINGUAS_INSTALL} ${IMAGE_INSTALL_DEBUGFS}" 34RDEPENDS += "${PACKAGE_INSTALL} ${LINGUAS_INSTALL} ${IMAGE_INSTALL_DEBUGFS}"
35RRECOMMENDS += "${PACKAGE_INSTALL_ATTEMPTONLY}" 35RRECOMMENDS += "${PACKAGE_INSTALL_ATTEMPTONLY}"
36PATH:prepend = "${@":".join(all_multilib_tune_values(d, 'STAGING_BINDIR_CROSS').split())}:" 36PATH:prepend = "${@":".join(all_multilib_tune_values(d, 'STAGING_BINDIR_CROSS').split())}:"
@@ -40,7 +40,7 @@ INHIBIT_DEFAULT_DEPS = "1"
40# IMAGE_FEATURES may contain any available package group 40# IMAGE_FEATURES may contain any available package group
41IMAGE_FEATURES ?= "" 41IMAGE_FEATURES ?= ""
42IMAGE_FEATURES[type] = "list" 42IMAGE_FEATURES[type] = "list"
43IMAGE_FEATURES[validitems] += "debug-tweaks read-only-rootfs read-only-rootfs-delayed-postinsts stateless-rootfs empty-root-password allow-empty-password allow-root-login serial-autologin-root post-install-logging overlayfs-etc" 43IMAGE_FEATURES[validitems] += "read-only-rootfs read-only-rootfs-delayed-postinsts stateless-rootfs empty-root-password allow-empty-password allow-root-login serial-autologin-root post-install-logging overlayfs-etc"
44 44
45# Generate companion debugfs? 45# Generate companion debugfs?
46IMAGE_GEN_DEBUGFS ?= "0" 46IMAGE_GEN_DEBUGFS ?= "0"
@@ -88,6 +88,11 @@ PACKAGE_INSTALL_ATTEMPTONLY ?= "${FEATURE_INSTALL_OPTIONAL}"
88 88
89IMGDEPLOYDIR = "${WORKDIR}/deploy-${PN}-image-complete" 89IMGDEPLOYDIR = "${WORKDIR}/deploy-${PN}-image-complete"
90 90
91IMGMANIFESTDIR = "${WORKDIR}/image-task-manifest"
92
93IMAGE_OUTPUT_MANIFEST_DIR = "${WORKDIR}/deploy-image-output-manifest"
94IMAGE_OUTPUT_MANIFEST = "${IMAGE_OUTPUT_MANIFEST_DIR}/manifest.json"
95
91# Images are generally built explicitly, do not need to be part of world. 96# Images are generally built explicitly, do not need to be part of world.
92EXCLUDE_FROM_WORLD = "1" 97EXCLUDE_FROM_WORLD = "1"
93 98
@@ -194,8 +199,6 @@ IMAGE_LOCALES_ARCHIVE ?= '1'
194# aren't yet available. 199# aren't yet available.
195PSEUDO_PASSWD = "${IMAGE_ROOTFS}:${STAGING_DIR_NATIVE}" 200PSEUDO_PASSWD = "${IMAGE_ROOTFS}:${STAGING_DIR_NATIVE}"
196 201
197PSEUDO_IGNORE_PATHS .= ",${WORKDIR}/intercept_scripts,${WORKDIR}/oe-rootfs-repo,${WORKDIR}/sstate-build-image_complete"
198
199PACKAGE_EXCLUDE ??= "" 202PACKAGE_EXCLUDE ??= ""
200PACKAGE_EXCLUDE[type] = "list" 203PACKAGE_EXCLUDE[type] = "list"
201 204
@@ -277,14 +280,28 @@ fakeroot python do_image () {
277 execute_pre_post_process(d, pre_process_cmds) 280 execute_pre_post_process(d, pre_process_cmds)
278} 281}
279do_image[dirs] = "${TOPDIR}" 282do_image[dirs] = "${TOPDIR}"
283do_image[cleandirs] += "${IMGMANIFESTDIR}"
280addtask do_image after do_rootfs 284addtask do_image after do_rootfs
281 285
282fakeroot python do_image_complete () { 286fakeroot python do_image_complete () {
283 from oe.utils import execute_pre_post_process 287 from oe.utils import execute_pre_post_process
288 from pathlib import Path
289 import json
284 290
285 post_process_cmds = d.getVar("IMAGE_POSTPROCESS_COMMAND") 291 post_process_cmds = d.getVar("IMAGE_POSTPROCESS_COMMAND")
286 292
287 execute_pre_post_process(d, post_process_cmds) 293 execute_pre_post_process(d, post_process_cmds)
294
295 image_manifest_dir = Path(d.getVar('IMGMANIFESTDIR'))
296
297 data = []
298
299 for manifest_path in image_manifest_dir.glob("*.json"):
300 with manifest_path.open("r") as f:
301 data.extend(json.load(f))
302
303 with open(d.getVar("IMAGE_OUTPUT_MANIFEST"), "w") as f:
304 json.dump(data, f)
288} 305}
289do_image_complete[dirs] = "${TOPDIR}" 306do_image_complete[dirs] = "${TOPDIR}"
290SSTATETASKS += "do_image_complete" 307SSTATETASKS += "do_image_complete"
@@ -292,6 +309,8 @@ SSTATE_SKIP_CREATION:task-image-complete = '1'
292do_image_complete[sstate-inputdirs] = "${IMGDEPLOYDIR}" 309do_image_complete[sstate-inputdirs] = "${IMGDEPLOYDIR}"
293do_image_complete[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" 310do_image_complete[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}"
294do_image_complete[stamp-extra-info] = "${MACHINE_ARCH}" 311do_image_complete[stamp-extra-info] = "${MACHINE_ARCH}"
312do_image_complete[sstate-plaindirs] += "${IMAGE_OUTPUT_MANIFEST_DIR}"
313do_image_complete[dirs] += "${IMAGE_OUTPUT_MANIFEST_DIR}"
295addtask do_image_complete after do_image before do_build 314addtask do_image_complete after do_image before do_build
296python do_image_complete_setscene () { 315python do_image_complete_setscene () {
297 sstate_setscene(d) 316 sstate_setscene(d)
@@ -303,28 +322,22 @@ addtask do_image_complete_setscene
303# IMAGE_QA_COMMANDS += " \ 322# IMAGE_QA_COMMANDS += " \
304# image_check_everything_ok \ 323# image_check_everything_ok \
305# " 324# "
325#
306# This task runs all functions in IMAGE_QA_COMMANDS after the rootfs 326# This task runs all functions in IMAGE_QA_COMMANDS after the rootfs
307# construction has completed in order to validate the resulting image. 327# construction has completed in order to validate the resulting image.
308# 328#
309# The functions should use ${IMAGE_ROOTFS} to find the unpacked rootfs 329# The functions should use ${IMAGE_ROOTFS} to find the unpacked rootfs
310# directory, which if QA passes will be the basis for the images. 330# directory, which if QA passes will be the basis for the images.
331#
332# The functions are expected to call oe.qa.handle_error() to report any
333# problems.
311fakeroot python do_image_qa () { 334fakeroot python do_image_qa () {
312 from oe.utils import ImageQAFailed
313
314 qa_cmds = (d.getVar('IMAGE_QA_COMMANDS') or '').split() 335 qa_cmds = (d.getVar('IMAGE_QA_COMMANDS') or '').split()
315 qamsg = ""
316 336
317 for cmd in qa_cmds: 337 for cmd in qa_cmds:
318 try: 338 bb.build.exec_func(cmd, d)
319 bb.build.exec_func(cmd, d) 339
320 except oe.utils.ImageQAFailed as e: 340 oe.qa.exit_if_errors(d)
321 qamsg = qamsg + '\tImage QA function %s failed: %s\n' % (e.name, e.description)
322 except Exception as e:
323 qamsg = qamsg + '\tImage QA function %s failed: %s\n' % (cmd, e)
324
325 if qamsg:
326 imgname = d.getVar('IMAGE_NAME')
327 bb.fatal("QA errors found whilst validating image: %s\n%s" % (imgname, qamsg))
328} 341}
329addtask do_image_qa after do_rootfs before do_image 342addtask do_image_qa after do_rootfs before do_image
330 343
@@ -507,12 +520,14 @@ python () {
507 d.setVar(task, '\n'.join(cmds)) 520 d.setVar(task, '\n'.join(cmds))
508 d.setVarFlag(task, 'func', '1') 521 d.setVarFlag(task, 'func', '1')
509 d.setVarFlag(task, 'fakeroot', '1') 522 d.setVarFlag(task, 'fakeroot', '1')
523 d.setVarFlag(task, 'imagetype', t)
510 524
511 d.appendVarFlag(task, 'prefuncs', ' ' + debug + ' set_image_size') 525 d.appendVarFlag(task, 'prefuncs', ' ' + debug + ' set_image_size')
512 d.prependVarFlag(task, 'postfuncs', 'create_symlinks ') 526 d.prependVarFlag(task, 'postfuncs', 'create_symlinks ')
513 d.appendVarFlag(task, 'subimages', ' ' + ' '.join(subimages)) 527 d.appendVarFlag(task, 'subimages', ' ' + ' '.join(subimages))
514 d.appendVarFlag(task, 'vardeps', ' ' + ' '.join(vardeps)) 528 d.appendVarFlag(task, 'vardeps', ' ' + ' '.join(vardeps))
515 d.appendVarFlag(task, 'vardepsexclude', ' DATETIME DATE ' + ' '.join(vardepsexclude)) 529 d.appendVarFlag(task, 'vardepsexclude', ' DATETIME DATE ' + ' '.join(vardepsexclude))
530 d.appendVarFlag(task, 'postfuncs', ' write_image_output_manifest')
516 531
517 bb.debug(2, "Adding task %s before %s, after %s" % (task, 'do_image_complete', after)) 532 bb.debug(2, "Adding task %s before %s, after %s" % (task, 'do_image_complete', after))
518 bb.build.addtask(task, 'do_image_complete', after, d) 533 bb.build.addtask(task, 'do_image_complete', after, d)
@@ -610,10 +625,47 @@ python create_symlinks() {
610 bb.note("Skipping symlink, source does not exist: %s -> %s" % (dst, src)) 625 bb.note("Skipping symlink, source does not exist: %s -> %s" % (dst, src))
611} 626}
612 627
628python write_image_output_manifest() {
629 import json
630 from pathlib import Path
631
632 taskname = d.getVar("BB_CURRENTTASK")
633 image_deploy_dir = Path(d.getVar('IMGDEPLOYDIR'))
634 image_manifest_dir = Path(d.getVar('IMGMANIFESTDIR'))
635 manifest_path = image_manifest_dir / ("do_" + d.getVar("BB_CURRENTTASK") + ".json")
636
637 image_name = d.getVar("IMAGE_NAME")
638 image_basename = d.getVar("IMAGE_BASENAME")
639 machine = d.getVar("MACHINE")
640
641 subimages = (d.getVarFlag("do_" + taskname, 'subimages', False) or "").split()
642 imagetype = d.getVarFlag("do_" + taskname, 'imagetype', False)
643
644 data = {
645 "taskname": taskname,
646 "imagetype": imagetype,
647 "images": []
648 }
649
650 for type in subimages:
651 image_filename = image_name + "." + type
652 image_path = image_deploy_dir / image_filename
653 if not image_path.exists():
654 continue
655 data["images"].append({
656 "filename": image_filename,
657 })
658
659 with manifest_path.open("w") as f:
660 json.dump([data], f)
661}
662
613MULTILIBRE_ALLOW_REP += "${base_bindir} ${base_sbindir} ${bindir} ${sbindir} ${libexecdir} ${sysconfdir} ${nonarch_base_libdir}/udev /lib/modules/[^/]*/modules.*" 663MULTILIBRE_ALLOW_REP += "${base_bindir} ${base_sbindir} ${bindir} ${sbindir} ${libexecdir} ${sysconfdir} ${nonarch_base_libdir}/udev /lib/modules/[^/]*/modules.*"
614MULTILIB_CHECK_FILE = "${WORKDIR}/multilib_check.py" 664MULTILIB_CHECK_FILE = "${WORKDIR}/multilib_check.py"
615MULTILIB_TEMP_ROOTFS = "${WORKDIR}/multilib" 665MULTILIB_TEMP_ROOTFS = "${WORKDIR}/multilib"
616 666
667PSEUDO_INCLUDE_PATHS .= ",${MULTILIB_TEMP_ROOTFS}"
668
617do_fetch[noexec] = "1" 669do_fetch[noexec] = "1"
618do_unpack[noexec] = "1" 670do_unpack[noexec] = "1"
619do_patch[noexec] = "1" 671do_patch[noexec] = "1"
@@ -629,37 +681,11 @@ deltask do_package_write_ipk
629deltask do_package_write_deb 681deltask do_package_write_deb
630deltask do_package_write_rpm 682deltask do_package_write_rpm
631 683
632# Prepare the root links to point to the /usr counterparts.
633create_merged_usr_symlinks() {
634 root="$1"
635 install -d $root${base_bindir} $root${base_sbindir} $root${base_libdir}
636 ln -rs $root${base_bindir} $root/bin
637 ln -rs $root${base_sbindir} $root/sbin
638 ln -rs $root${base_libdir} $root/${baselib}
639
640 if [ "${nonarch_base_libdir}" != "${base_libdir}" ]; then
641 install -d $root${nonarch_base_libdir}
642 ln -rs $root${nonarch_base_libdir} $root/lib
643 fi
644
645 # create base links for multilibs
646 multi_libdirs="${@d.getVar('MULTILIB_VARIANTS')}"
647 for d in $multi_libdirs; do
648 install -d $root${exec_prefix}/$d
649 ln -rs $root${exec_prefix}/$d $root/$d
650 done
651}
652
653create_merged_usr_symlinks_rootfs() { 684create_merged_usr_symlinks_rootfs() {
654 create_merged_usr_symlinks ${IMAGE_ROOTFS} 685 create_merged_usr_symlinks ${IMAGE_ROOTFS}
655} 686}
656 687
657create_merged_usr_symlinks_sdk() {
658 create_merged_usr_symlinks ${SDK_OUTPUT}${SDKTARGETSYSROOT}
659}
660
661ROOTFS_PREPROCESS_COMMAND += "${@bb.utils.contains('DISTRO_FEATURES', 'usrmerge', 'create_merged_usr_symlinks_rootfs', '',d)}" 688ROOTFS_PREPROCESS_COMMAND += "${@bb.utils.contains('DISTRO_FEATURES', 'usrmerge', 'create_merged_usr_symlinks_rootfs', '',d)}"
662POPULATE_SDK_PRE_TARGET_COMMAND += "${@bb.utils.contains('DISTRO_FEATURES', 'usrmerge', 'create_merged_usr_symlinks_sdk', '',d)}"
663 689
664reproducible_final_image_task () { 690reproducible_final_image_task () {
665 if [ "$REPRODUCIBLE_TIMESTAMP_ROOTFS" = "" ]; then 691 if [ "$REPRODUCIBLE_TIMESTAMP_ROOTFS" = "" ]; then
@@ -673,12 +699,6 @@ reproducible_final_image_task () {
673 find ${IMAGE_ROOTFS} -print0 | xargs -0 touch -h --date=@$REPRODUCIBLE_TIMESTAMP_ROOTFS 699 find ${IMAGE_ROOTFS} -print0 | xargs -0 touch -h --date=@$REPRODUCIBLE_TIMESTAMP_ROOTFS
674} 700}
675 701
676systemd_preset_all () { 702IMAGE_PREPROCESS_COMMAND:append = " reproducible_final_image_task "
677 if [ -e ${IMAGE_ROOTFS}${root_prefix}/lib/systemd/systemd ]; then
678 systemctl --root="${IMAGE_ROOTFS}" --preset-mode=enable-only preset-all
679 fi
680}
681
682IMAGE_PREPROCESS_COMMAND:append = " ${@ 'systemd_preset_all' if bb.utils.contains('DISTRO_FEATURES', 'systemd', True, False, d) and not bb.utils.contains('IMAGE_FEATURES', 'stateless-rootfs', True, False, d) else ''} reproducible_final_image_task "
683 703
684CVE_PRODUCT = "" 704CVE_PRODUCT = ""