diff options
Diffstat (limited to 'meta/classes-recipe/image.bbclass')
-rw-r--r-- | meta/classes-recipe/image.bbclass | 120 |
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 | ||
31 | LICENSE ?= "MIT" | 31 | LICENSE ?= "MIT" |
32 | PACKAGES = "" | 32 | PACKAGES = "" |
33 | DEPENDS += "${@' '.join(["%s-qemuwrapper-cross" % m for m in d.getVar("MULTILIB_VARIANTS").split()])} qemuwrapper-cross depmodwrapper-cross cross-localedef-native" | 33 | DEPENDS += "depmodwrapper-cross cross-localedef-native" |
34 | RDEPENDS += "${PACKAGE_INSTALL} ${LINGUAS_INSTALL} ${IMAGE_INSTALL_DEBUGFS}" | 34 | RDEPENDS += "${PACKAGE_INSTALL} ${LINGUAS_INSTALL} ${IMAGE_INSTALL_DEBUGFS}" |
35 | RRECOMMENDS += "${PACKAGE_INSTALL_ATTEMPTONLY}" | 35 | RRECOMMENDS += "${PACKAGE_INSTALL_ATTEMPTONLY}" |
36 | PATH:prepend = "${@":".join(all_multilib_tune_values(d, 'STAGING_BINDIR_CROSS').split())}:" | 36 | PATH: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 |
41 | IMAGE_FEATURES ?= "" | 41 | IMAGE_FEATURES ?= "" |
42 | IMAGE_FEATURES[type] = "list" | 42 | IMAGE_FEATURES[type] = "list" |
43 | IMAGE_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" | 43 | IMAGE_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? |
46 | IMAGE_GEN_DEBUGFS ?= "0" | 46 | IMAGE_GEN_DEBUGFS ?= "0" |
@@ -88,6 +88,11 @@ PACKAGE_INSTALL_ATTEMPTONLY ?= "${FEATURE_INSTALL_OPTIONAL}" | |||
88 | 88 | ||
89 | IMGDEPLOYDIR = "${WORKDIR}/deploy-${PN}-image-complete" | 89 | IMGDEPLOYDIR = "${WORKDIR}/deploy-${PN}-image-complete" |
90 | 90 | ||
91 | IMGMANIFESTDIR = "${WORKDIR}/image-task-manifest" | ||
92 | |||
93 | IMAGE_OUTPUT_MANIFEST_DIR = "${WORKDIR}/deploy-image-output-manifest" | ||
94 | IMAGE_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. |
92 | EXCLUDE_FROM_WORLD = "1" | 97 | EXCLUDE_FROM_WORLD = "1" |
93 | 98 | ||
@@ -194,8 +199,6 @@ IMAGE_LOCALES_ARCHIVE ?= '1' | |||
194 | # aren't yet available. | 199 | # aren't yet available. |
195 | PSEUDO_PASSWD = "${IMAGE_ROOTFS}:${STAGING_DIR_NATIVE}" | 200 | PSEUDO_PASSWD = "${IMAGE_ROOTFS}:${STAGING_DIR_NATIVE}" |
196 | 201 | ||
197 | PSEUDO_IGNORE_PATHS .= ",${WORKDIR}/intercept_scripts,${WORKDIR}/oe-rootfs-repo,${WORKDIR}/sstate-build-image_complete" | ||
198 | |||
199 | PACKAGE_EXCLUDE ??= "" | 202 | PACKAGE_EXCLUDE ??= "" |
200 | PACKAGE_EXCLUDE[type] = "list" | 203 | PACKAGE_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 | } |
279 | do_image[dirs] = "${TOPDIR}" | 282 | do_image[dirs] = "${TOPDIR}" |
283 | do_image[cleandirs] += "${IMGMANIFESTDIR}" | ||
280 | addtask do_image after do_rootfs | 284 | addtask do_image after do_rootfs |
281 | 285 | ||
282 | fakeroot python do_image_complete () { | 286 | fakeroot 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 | } |
289 | do_image_complete[dirs] = "${TOPDIR}" | 306 | do_image_complete[dirs] = "${TOPDIR}" |
290 | SSTATETASKS += "do_image_complete" | 307 | SSTATETASKS += "do_image_complete" |
@@ -292,6 +309,8 @@ SSTATE_SKIP_CREATION:task-image-complete = '1' | |||
292 | do_image_complete[sstate-inputdirs] = "${IMGDEPLOYDIR}" | 309 | do_image_complete[sstate-inputdirs] = "${IMGDEPLOYDIR}" |
293 | do_image_complete[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" | 310 | do_image_complete[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" |
294 | do_image_complete[stamp-extra-info] = "${MACHINE_ARCH}" | 311 | do_image_complete[stamp-extra-info] = "${MACHINE_ARCH}" |
312 | do_image_complete[sstate-plaindirs] += "${IMAGE_OUTPUT_MANIFEST_DIR}" | ||
313 | do_image_complete[dirs] += "${IMAGE_OUTPUT_MANIFEST_DIR}" | ||
295 | addtask do_image_complete after do_image before do_build | 314 | addtask do_image_complete after do_image before do_build |
296 | python do_image_complete_setscene () { | 315 | python 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. | ||
311 | fakeroot python do_image_qa () { | 334 | fakeroot 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 | } |
329 | addtask do_image_qa after do_rootfs before do_image | 342 | addtask 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 | ||
628 | python 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 | |||
613 | MULTILIBRE_ALLOW_REP += "${base_bindir} ${base_sbindir} ${bindir} ${sbindir} ${libexecdir} ${sysconfdir} ${nonarch_base_libdir}/udev /lib/modules/[^/]*/modules.*" | 663 | MULTILIBRE_ALLOW_REP += "${base_bindir} ${base_sbindir} ${bindir} ${sbindir} ${libexecdir} ${sysconfdir} ${nonarch_base_libdir}/udev /lib/modules/[^/]*/modules.*" |
614 | MULTILIB_CHECK_FILE = "${WORKDIR}/multilib_check.py" | 664 | MULTILIB_CHECK_FILE = "${WORKDIR}/multilib_check.py" |
615 | MULTILIB_TEMP_ROOTFS = "${WORKDIR}/multilib" | 665 | MULTILIB_TEMP_ROOTFS = "${WORKDIR}/multilib" |
616 | 666 | ||
667 | PSEUDO_INCLUDE_PATHS .= ",${MULTILIB_TEMP_ROOTFS}" | ||
668 | |||
617 | do_fetch[noexec] = "1" | 669 | do_fetch[noexec] = "1" |
618 | do_unpack[noexec] = "1" | 670 | do_unpack[noexec] = "1" |
619 | do_patch[noexec] = "1" | 671 | do_patch[noexec] = "1" |
@@ -629,37 +681,11 @@ deltask do_package_write_ipk | |||
629 | deltask do_package_write_deb | 681 | deltask do_package_write_deb |
630 | deltask do_package_write_rpm | 682 | deltask do_package_write_rpm |
631 | 683 | ||
632 | # Prepare the root links to point to the /usr counterparts. | ||
633 | create_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 | |||
653 | create_merged_usr_symlinks_rootfs() { | 684 | create_merged_usr_symlinks_rootfs() { |
654 | create_merged_usr_symlinks ${IMAGE_ROOTFS} | 685 | create_merged_usr_symlinks ${IMAGE_ROOTFS} |
655 | } | 686 | } |
656 | 687 | ||
657 | create_merged_usr_symlinks_sdk() { | ||
658 | create_merged_usr_symlinks ${SDK_OUTPUT}${SDKTARGETSYSROOT} | ||
659 | } | ||
660 | |||
661 | ROOTFS_PREPROCESS_COMMAND += "${@bb.utils.contains('DISTRO_FEATURES', 'usrmerge', 'create_merged_usr_symlinks_rootfs', '',d)}" | 688 | ROOTFS_PREPROCESS_COMMAND += "${@bb.utils.contains('DISTRO_FEATURES', 'usrmerge', 'create_merged_usr_symlinks_rootfs', '',d)}" |
662 | POPULATE_SDK_PRE_TARGET_COMMAND += "${@bb.utils.contains('DISTRO_FEATURES', 'usrmerge', 'create_merged_usr_symlinks_sdk', '',d)}" | ||
663 | 689 | ||
664 | reproducible_final_image_task () { | 690 | reproducible_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 | ||
676 | systemd_preset_all () { | 702 | IMAGE_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 | |||
682 | IMAGE_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 | ||
684 | CVE_PRODUCT = "" | 704 | CVE_PRODUCT = "" |