1*4882a593Smuzhiyun 2*4882a593SmuzhiyunIMAGE_CLASSES ??= "" 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun# rootfs bootstrap install 5*4882a593Smuzhiyun# warning - image-container resets this 6*4882a593SmuzhiyunROOTFS_BOOTSTRAP_INSTALL = "run-postinsts" 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun# Handle inherits of any of the image classes we need 9*4882a593SmuzhiyunIMGCLASSES = "rootfs_${IMAGE_PKGTYPE} image_types ${IMAGE_CLASSES}" 10*4882a593Smuzhiyun# Only Linux SDKs support populate_sdk_ext, fall back to populate_sdk_base 11*4882a593Smuzhiyun# in the non-Linux SDK_OS case, such as mingw32 12*4882a593SmuzhiyunIMGCLASSES += "${@['populate_sdk_base', 'populate_sdk_ext']['linux' in d.getVar("SDK_OS")]}" 13*4882a593SmuzhiyunIMGCLASSES += "${@bb.utils.contains_any('IMAGE_FSTYPES', 'live iso hddimg', 'image-live', '', d)}" 14*4882a593SmuzhiyunIMGCLASSES += "${@bb.utils.contains('IMAGE_FSTYPES', 'container', 'image-container', '', d)}" 15*4882a593SmuzhiyunIMGCLASSES += "image_types_wic" 16*4882a593SmuzhiyunIMGCLASSES += "rootfs-postcommands" 17*4882a593SmuzhiyunIMGCLASSES += "image-postinst-intercepts" 18*4882a593SmuzhiyunIMGCLASSES += "overlayfs-etc" 19*4882a593Smuzhiyuninherit ${IMGCLASSES} 20*4882a593Smuzhiyun 21*4882a593SmuzhiyunTOOLCHAIN_TARGET_TASK += "${PACKAGE_INSTALL}" 22*4882a593SmuzhiyunTOOLCHAIN_TARGET_TASK_ATTEMPTONLY += "${PACKAGE_INSTALL_ATTEMPTONLY}" 23*4882a593SmuzhiyunPOPULATE_SDK_POST_TARGET_COMMAND += "rootfs_sysroot_relativelinks; " 24*4882a593Smuzhiyun 25*4882a593SmuzhiyunLICENSE ?= "MIT" 26*4882a593SmuzhiyunPACKAGES = "" 27*4882a593SmuzhiyunDEPENDS += "${@' '.join(["%s-qemuwrapper-cross" % m for m in d.getVar("MULTILIB_VARIANTS").split()])} qemuwrapper-cross depmodwrapper-cross cross-localedef-native" 28*4882a593SmuzhiyunRDEPENDS += "${PACKAGE_INSTALL} ${LINGUAS_INSTALL} ${IMAGE_INSTALL_DEBUGFS}" 29*4882a593SmuzhiyunRRECOMMENDS += "${PACKAGE_INSTALL_ATTEMPTONLY}" 30*4882a593SmuzhiyunPATH:prepend = "${@":".join(all_multilib_tune_values(d, 'STAGING_BINDIR_CROSS').split())}:" 31*4882a593Smuzhiyun 32*4882a593SmuzhiyunINHIBIT_DEFAULT_DEPS = "1" 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun# IMAGE_FEATURES may contain any available package group 35*4882a593SmuzhiyunIMAGE_FEATURES ?= "" 36*4882a593SmuzhiyunIMAGE_FEATURES[type] = "list" 37*4882a593SmuzhiyunIMAGE_FEATURES[validitems] += "debug-tweaks read-only-rootfs read-only-rootfs-delayed-postinsts stateless-rootfs empty-root-password allow-empty-password allow-root-login post-install-logging overlayfs-etc" 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun# Generate companion debugfs? 40*4882a593SmuzhiyunIMAGE_GEN_DEBUGFS ?= "0" 41*4882a593Smuzhiyun 42*4882a593Smuzhiyun# These packages will be installed as additional into debug rootfs 43*4882a593SmuzhiyunIMAGE_INSTALL_DEBUGFS ?= "" 44*4882a593Smuzhiyun 45*4882a593Smuzhiyun# These packages will be removed from a read-only rootfs after all other 46*4882a593Smuzhiyun# packages have been installed 47*4882a593SmuzhiyunROOTFS_RO_UNNEEDED ??= "update-rc.d base-passwd shadow ${VIRTUAL-RUNTIME_update-alternatives} ${ROOTFS_BOOTSTRAP_INSTALL}" 48*4882a593Smuzhiyun 49*4882a593Smuzhiyun# packages to install from features 50*4882a593SmuzhiyunFEATURE_INSTALL = "${@' '.join(oe.packagegroup.required_packages(oe.data.typed_value('IMAGE_FEATURES', d), d))}" 51*4882a593SmuzhiyunFEATURE_INSTALL[vardepvalue] = "${FEATURE_INSTALL}" 52*4882a593SmuzhiyunFEATURE_INSTALL_OPTIONAL = "${@' '.join(oe.packagegroup.optional_packages(oe.data.typed_value('IMAGE_FEATURES', d), d))}" 53*4882a593SmuzhiyunFEATURE_INSTALL_OPTIONAL[vardepvalue] = "${FEATURE_INSTALL_OPTIONAL}" 54*4882a593Smuzhiyun 55*4882a593Smuzhiyun# Define some very basic feature package groups 56*4882a593SmuzhiyunFEATURE_PACKAGES_package-management = "${ROOTFS_PKGMANAGE}" 57*4882a593SmuzhiyunSPLASH ?= "${@bb.utils.contains("MACHINE_FEATURES", "screen", "psplash", "", d)}" 58*4882a593SmuzhiyunFEATURE_PACKAGES_splash = "${SPLASH}" 59*4882a593Smuzhiyun 60*4882a593SmuzhiyunIMAGE_INSTALL_COMPLEMENTARY = '${@complementary_globs("IMAGE_FEATURES", d)}' 61*4882a593Smuzhiyun 62*4882a593Smuzhiyundef check_image_features(d): 63*4882a593Smuzhiyun valid_features = (d.getVarFlag('IMAGE_FEATURES', 'validitems') or "").split() 64*4882a593Smuzhiyun valid_features += d.getVarFlags('COMPLEMENTARY_GLOB').keys() 65*4882a593Smuzhiyun for var in d: 66*4882a593Smuzhiyun if var.startswith("FEATURE_PACKAGES_"): 67*4882a593Smuzhiyun valid_features.append(var[17:]) 68*4882a593Smuzhiyun valid_features.sort() 69*4882a593Smuzhiyun 70*4882a593Smuzhiyun features = set(oe.data.typed_value('IMAGE_FEATURES', d)) 71*4882a593Smuzhiyun for feature in features: 72*4882a593Smuzhiyun if feature not in valid_features: 73*4882a593Smuzhiyun if bb.utils.contains('EXTRA_IMAGE_FEATURES', feature, True, False, d): 74*4882a593Smuzhiyun raise bb.parse.SkipRecipe("'%s' in IMAGE_FEATURES (added via EXTRA_IMAGE_FEATURES) is not a valid image feature. Valid features: %s" % (feature, ' '.join(valid_features))) 75*4882a593Smuzhiyun else: 76*4882a593Smuzhiyun raise bb.parse.SkipRecipe("'%s' in IMAGE_FEATURES is not a valid image feature. Valid features: %s" % (feature, ' '.join(valid_features))) 77*4882a593Smuzhiyun 78*4882a593SmuzhiyunIMAGE_INSTALL ?= "" 79*4882a593SmuzhiyunIMAGE_INSTALL[type] = "list" 80*4882a593Smuzhiyunexport PACKAGE_INSTALL ?= "${IMAGE_INSTALL} ${ROOTFS_BOOTSTRAP_INSTALL} ${FEATURE_INSTALL}" 81*4882a593SmuzhiyunPACKAGE_INSTALL_ATTEMPTONLY ?= "${FEATURE_INSTALL_OPTIONAL}" 82*4882a593Smuzhiyun 83*4882a593SmuzhiyunIMGDEPLOYDIR = "${WORKDIR}/deploy-${PN}-image-complete" 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun# Images are generally built explicitly, do not need to be part of world. 86*4882a593SmuzhiyunEXCLUDE_FROM_WORLD = "1" 87*4882a593Smuzhiyun 88*4882a593SmuzhiyunUSE_DEVFS ?= "1" 89*4882a593SmuzhiyunUSE_DEPMOD ?= "1" 90*4882a593Smuzhiyun 91*4882a593SmuzhiyunPID = "${@os.getpid()}" 92*4882a593Smuzhiyun 93*4882a593SmuzhiyunPACKAGE_ARCH = "${MACHINE_ARCH}" 94*4882a593Smuzhiyun 95*4882a593SmuzhiyunLDCONFIGDEPEND ?= "ldconfig-native:do_populate_sysroot" 96*4882a593SmuzhiyunLDCONFIGDEPEND:libc-musl = "" 97*4882a593Smuzhiyun 98*4882a593Smuzhiyun# This is needed to have depmod data in PKGDATA_DIR, 99*4882a593Smuzhiyun# but if you're building small initramfs image 100*4882a593Smuzhiyun# e.g. to include it in your kernel, you probably 101*4882a593Smuzhiyun# don't want this dependency, which is causing dependency loop 102*4882a593SmuzhiyunKERNELDEPMODDEPEND ?= "virtual/kernel:do_packagedata" 103*4882a593Smuzhiyun 104*4882a593Smuzhiyundo_rootfs[depends] += " \ 105*4882a593Smuzhiyun makedevs-native:do_populate_sysroot virtual/fakeroot-native:do_populate_sysroot ${LDCONFIGDEPEND} \ 106*4882a593Smuzhiyun virtual/update-alternatives-native:do_populate_sysroot update-rc.d-native:do_populate_sysroot \ 107*4882a593Smuzhiyun ${KERNELDEPMODDEPEND} \ 108*4882a593Smuzhiyun" 109*4882a593Smuzhiyundo_rootfs[recrdeptask] += "do_packagedata" 110*4882a593Smuzhiyun 111*4882a593Smuzhiyundef rootfs_command_variables(d): 112*4882a593Smuzhiyun return ['ROOTFS_POSTPROCESS_COMMAND','ROOTFS_PREPROCESS_COMMAND','ROOTFS_POSTINSTALL_COMMAND','ROOTFS_POSTUNINSTALL_COMMAND','OPKG_PREPROCESS_COMMANDS','OPKG_POSTPROCESS_COMMANDS','IMAGE_POSTPROCESS_COMMAND', 113*4882a593Smuzhiyun 'IMAGE_PREPROCESS_COMMAND','RPM_PREPROCESS_COMMANDS','RPM_POSTPROCESS_COMMANDS','DEB_PREPROCESS_COMMANDS','DEB_POSTPROCESS_COMMANDS'] 114*4882a593Smuzhiyun 115*4882a593Smuzhiyunpython () { 116*4882a593Smuzhiyun variables = rootfs_command_variables(d) 117*4882a593Smuzhiyun for var in variables: 118*4882a593Smuzhiyun if d.getVar(var, False): 119*4882a593Smuzhiyun d.setVarFlag(var, 'func', '1') 120*4882a593Smuzhiyun} 121*4882a593Smuzhiyun 122*4882a593Smuzhiyundef rootfs_variables(d): 123*4882a593Smuzhiyun from oe.rootfs import variable_depends 124*4882a593Smuzhiyun variables = ['IMAGE_DEVICE_TABLE','IMAGE_DEVICE_TABLES','BUILD_IMAGES_FROM_FEEDS','IMAGE_TYPES_MASKED','IMAGE_ROOTFS_ALIGNMENT','IMAGE_OVERHEAD_FACTOR','IMAGE_ROOTFS_SIZE','IMAGE_ROOTFS_EXTRA_SPACE', 125*4882a593Smuzhiyun 'IMAGE_ROOTFS_MAXSIZE','IMAGE_NAME','IMAGE_LINK_NAME','IMAGE_MANIFEST','DEPLOY_DIR_IMAGE','IMAGE_FSTYPES','IMAGE_INSTALL_COMPLEMENTARY','IMAGE_LINGUAS', 'IMAGE_LINGUAS_COMPLEMENTARY', 'IMAGE_LOCALES_ARCHIVE', 126*4882a593Smuzhiyun 'MULTILIBRE_ALLOW_REP','MULTILIB_TEMP_ROOTFS','MULTILIB_VARIANTS','MULTILIBS','ALL_MULTILIB_PACKAGE_ARCHS','MULTILIB_GLOBAL_VARIANTS','BAD_RECOMMENDATIONS','NO_RECOMMENDATIONS', 127*4882a593Smuzhiyun 'PACKAGE_ARCHS','PACKAGE_CLASSES','TARGET_VENDOR','TARGET_ARCH','TARGET_OS','OVERRIDES','BBEXTENDVARIANT','FEED_DEPLOYDIR_BASE_URI','INTERCEPT_DIR','USE_DEVFS', 128*4882a593Smuzhiyun 'CONVERSIONTYPES', 'IMAGE_GEN_DEBUGFS', 'ROOTFS_RO_UNNEEDED', 'IMGDEPLOYDIR', 'PACKAGE_EXCLUDE_COMPLEMENTARY', 'REPRODUCIBLE_TIMESTAMP_ROOTFS', 'IMAGE_INSTALL_DEBUGFS'] 129*4882a593Smuzhiyun variables.extend(rootfs_command_variables(d)) 130*4882a593Smuzhiyun variables.extend(variable_depends(d)) 131*4882a593Smuzhiyun return " ".join(variables) 132*4882a593Smuzhiyun 133*4882a593Smuzhiyundo_rootfs[vardeps] += "${@rootfs_variables(d)}" 134*4882a593Smuzhiyun 135*4882a593Smuzhiyun# This is needed to have kernel image in DEPLOY_DIR. 136*4882a593Smuzhiyun# This follows many common usecases and user expectations. 137*4882a593Smuzhiyun# But if you are building an image which doesn't need the kernel image at all, 138*4882a593Smuzhiyun# you can unset this variable manually. 139*4882a593SmuzhiyunKERNEL_DEPLOY_DEPEND ?= "virtual/kernel:do_deploy" 140*4882a593Smuzhiyundo_build[depends] += "${KERNEL_DEPLOY_DEPEND}" 141*4882a593Smuzhiyun 142*4882a593Smuzhiyun 143*4882a593Smuzhiyunpython () { 144*4882a593Smuzhiyun def extraimage_getdepends(task): 145*4882a593Smuzhiyun deps = "" 146*4882a593Smuzhiyun for dep in (d.getVar('EXTRA_IMAGEDEPENDS') or "").split(): 147*4882a593Smuzhiyun if ":" in dep: 148*4882a593Smuzhiyun deps += " %s " % (dep) 149*4882a593Smuzhiyun else: 150*4882a593Smuzhiyun deps += " %s:%s" % (dep, task) 151*4882a593Smuzhiyun return deps 152*4882a593Smuzhiyun 153*4882a593Smuzhiyun d.appendVarFlag('do_image_complete', 'depends', extraimage_getdepends('do_populate_sysroot')) 154*4882a593Smuzhiyun 155*4882a593Smuzhiyun deps = " " + imagetypes_getdepends(d) 156*4882a593Smuzhiyun d.appendVarFlag('do_rootfs', 'depends', deps) 157*4882a593Smuzhiyun 158*4882a593Smuzhiyun #process IMAGE_FEATURES, we must do this before runtime_mapping_rename 159*4882a593Smuzhiyun #Check for replaces image features 160*4882a593Smuzhiyun features = set(oe.data.typed_value('IMAGE_FEATURES', d)) 161*4882a593Smuzhiyun remain_features = features.copy() 162*4882a593Smuzhiyun for feature in features: 163*4882a593Smuzhiyun replaces = set((d.getVar("IMAGE_FEATURES_REPLACES_%s" % feature) or "").split()) 164*4882a593Smuzhiyun remain_features -= replaces 165*4882a593Smuzhiyun 166*4882a593Smuzhiyun #Check for conflict image features 167*4882a593Smuzhiyun for feature in remain_features: 168*4882a593Smuzhiyun conflicts = set((d.getVar("IMAGE_FEATURES_CONFLICTS_%s" % feature) or "").split()) 169*4882a593Smuzhiyun temp = conflicts & remain_features 170*4882a593Smuzhiyun if temp: 171*4882a593Smuzhiyun bb.fatal("%s contains conflicting IMAGE_FEATURES %s %s" % (d.getVar('PN'), feature, ' '.join(list(temp)))) 172*4882a593Smuzhiyun 173*4882a593Smuzhiyun d.setVar('IMAGE_FEATURES', ' '.join(sorted(list(remain_features)))) 174*4882a593Smuzhiyun 175*4882a593Smuzhiyun check_image_features(d) 176*4882a593Smuzhiyun} 177*4882a593Smuzhiyun 178*4882a593SmuzhiyunIMAGE_POSTPROCESS_COMMAND ?= "" 179*4882a593Smuzhiyun 180*4882a593SmuzhiyunIMAGE_LINGUAS ??= "" 181*4882a593Smuzhiyun 182*4882a593SmuzhiyunLINGUAS_INSTALL ?= "${@" ".join(map(lambda s: "locale-base-%s" % s, d.getVar('IMAGE_LINGUAS').split()))}" 183*4882a593Smuzhiyun 184*4882a593Smuzhiyun# per default create a locale archive 185*4882a593SmuzhiyunIMAGE_LOCALES_ARCHIVE ?= '1' 186*4882a593Smuzhiyun 187*4882a593Smuzhiyun# Prefer image, but use the fallback files for lookups if the image ones 188*4882a593Smuzhiyun# aren't yet available. 189*4882a593SmuzhiyunPSEUDO_PASSWD = "${IMAGE_ROOTFS}:${STAGING_DIR_NATIVE}" 190*4882a593Smuzhiyun 191*4882a593SmuzhiyunPSEUDO_IGNORE_PATHS .= ",${WORKDIR}/intercept_scripts,${WORKDIR}/oe-rootfs-repo,${WORKDIR}/sstate-build-image_complete" 192*4882a593Smuzhiyun 193*4882a593SmuzhiyunPACKAGE_EXCLUDE ??= "" 194*4882a593SmuzhiyunPACKAGE_EXCLUDE[type] = "list" 195*4882a593Smuzhiyun 196*4882a593Smuzhiyunfakeroot python do_rootfs () { 197*4882a593Smuzhiyun from oe.rootfs import create_rootfs 198*4882a593Smuzhiyun from oe.manifest import create_manifest 199*4882a593Smuzhiyun import logging 200*4882a593Smuzhiyun 201*4882a593Smuzhiyun logger = d.getVar('BB_TASK_LOGGER', False) 202*4882a593Smuzhiyun if logger: 203*4882a593Smuzhiyun logcatcher = bb.utils.LogCatcher() 204*4882a593Smuzhiyun logger.addHandler(logcatcher) 205*4882a593Smuzhiyun else: 206*4882a593Smuzhiyun logcatcher = None 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun # NOTE: if you add, remove or significantly refactor the stages of this 209*4882a593Smuzhiyun # process then you should recalculate the weightings here. This is quite 210*4882a593Smuzhiyun # easy to do - just change the MultiStageProgressReporter line temporarily 211*4882a593Smuzhiyun # to pass debug=True as the last parameter and you'll get a printout of 212*4882a593Smuzhiyun # the weightings as well as a map to the lines where next_stage() was 213*4882a593Smuzhiyun # called. Of course this isn't critical, but it helps to keep the progress 214*4882a593Smuzhiyun # reporting accurate. 215*4882a593Smuzhiyun stage_weights = [1, 203, 354, 186, 65, 4228, 1, 353, 49, 330, 382, 23, 1] 216*4882a593Smuzhiyun progress_reporter = bb.progress.MultiStageProgressReporter(d, stage_weights) 217*4882a593Smuzhiyun progress_reporter.next_stage() 218*4882a593Smuzhiyun 219*4882a593Smuzhiyun # Handle package exclusions 220*4882a593Smuzhiyun excl_pkgs = d.getVar("PACKAGE_EXCLUDE").split() 221*4882a593Smuzhiyun inst_pkgs = d.getVar("PACKAGE_INSTALL").split() 222*4882a593Smuzhiyun inst_attempt_pkgs = d.getVar("PACKAGE_INSTALL_ATTEMPTONLY").split() 223*4882a593Smuzhiyun 224*4882a593Smuzhiyun d.setVar('PACKAGE_INSTALL_ORIG', ' '.join(inst_pkgs)) 225*4882a593Smuzhiyun d.setVar('PACKAGE_INSTALL_ATTEMPTONLY', ' '.join(inst_attempt_pkgs)) 226*4882a593Smuzhiyun 227*4882a593Smuzhiyun for pkg in excl_pkgs: 228*4882a593Smuzhiyun if pkg in inst_pkgs: 229*4882a593Smuzhiyun bb.warn("Package %s, set to be excluded, is in %s PACKAGE_INSTALL (%s). It will be removed from the list." % (pkg, d.getVar('PN'), inst_pkgs)) 230*4882a593Smuzhiyun inst_pkgs.remove(pkg) 231*4882a593Smuzhiyun 232*4882a593Smuzhiyun if pkg in inst_attempt_pkgs: 233*4882a593Smuzhiyun bb.warn("Package %s, set to be excluded, is in %s PACKAGE_INSTALL_ATTEMPTONLY (%s). It will be removed from the list." % (pkg, d.getVar('PN'), inst_pkgs)) 234*4882a593Smuzhiyun inst_attempt_pkgs.remove(pkg) 235*4882a593Smuzhiyun 236*4882a593Smuzhiyun d.setVar("PACKAGE_INSTALL", ' '.join(inst_pkgs)) 237*4882a593Smuzhiyun d.setVar("PACKAGE_INSTALL_ATTEMPTONLY", ' '.join(inst_attempt_pkgs)) 238*4882a593Smuzhiyun 239*4882a593Smuzhiyun # Ensure we handle package name remapping 240*4882a593Smuzhiyun # We have to delay the runtime_mapping_rename until just before rootfs runs 241*4882a593Smuzhiyun # otherwise, the multilib renaming could step in and squash any fixups that 242*4882a593Smuzhiyun # may have occurred. 243*4882a593Smuzhiyun pn = d.getVar('PN') 244*4882a593Smuzhiyun runtime_mapping_rename("PACKAGE_INSTALL", pn, d) 245*4882a593Smuzhiyun runtime_mapping_rename("PACKAGE_INSTALL_ATTEMPTONLY", pn, d) 246*4882a593Smuzhiyun runtime_mapping_rename("BAD_RECOMMENDATIONS", pn, d) 247*4882a593Smuzhiyun 248*4882a593Smuzhiyun # Generate the initial manifest 249*4882a593Smuzhiyun create_manifest(d) 250*4882a593Smuzhiyun 251*4882a593Smuzhiyun progress_reporter.next_stage() 252*4882a593Smuzhiyun 253*4882a593Smuzhiyun # generate rootfs 254*4882a593Smuzhiyun d.setVarFlag('REPRODUCIBLE_TIMESTAMP_ROOTFS', 'export', '1') 255*4882a593Smuzhiyun create_rootfs(d, progress_reporter=progress_reporter, logcatcher=logcatcher) 256*4882a593Smuzhiyun 257*4882a593Smuzhiyun progress_reporter.finish() 258*4882a593Smuzhiyun} 259*4882a593Smuzhiyundo_rootfs[dirs] = "${TOPDIR}" 260*4882a593Smuzhiyundo_rootfs[cleandirs] += "${IMAGE_ROOTFS} ${IMGDEPLOYDIR} ${S}" 261*4882a593Smuzhiyundo_rootfs[file-checksums] += "${POSTINST_INTERCEPT_CHECKSUMS}" 262*4882a593Smuzhiyunaddtask rootfs after do_prepare_recipe_sysroot 263*4882a593Smuzhiyun 264*4882a593Smuzhiyunfakeroot python do_image () { 265*4882a593Smuzhiyun from oe.utils import execute_pre_post_process 266*4882a593Smuzhiyun 267*4882a593Smuzhiyun d.setVarFlag('REPRODUCIBLE_TIMESTAMP_ROOTFS', 'export', '1') 268*4882a593Smuzhiyun pre_process_cmds = d.getVar("IMAGE_PREPROCESS_COMMAND") 269*4882a593Smuzhiyun 270*4882a593Smuzhiyun execute_pre_post_process(d, pre_process_cmds) 271*4882a593Smuzhiyun} 272*4882a593Smuzhiyundo_image[dirs] = "${TOPDIR}" 273*4882a593Smuzhiyunaddtask do_image after do_rootfs 274*4882a593Smuzhiyun 275*4882a593Smuzhiyunfakeroot python do_image_complete () { 276*4882a593Smuzhiyun from oe.utils import execute_pre_post_process 277*4882a593Smuzhiyun 278*4882a593Smuzhiyun post_process_cmds = d.getVar("IMAGE_POSTPROCESS_COMMAND") 279*4882a593Smuzhiyun 280*4882a593Smuzhiyun execute_pre_post_process(d, post_process_cmds) 281*4882a593Smuzhiyun} 282*4882a593Smuzhiyundo_image_complete[dirs] = "${TOPDIR}" 283*4882a593SmuzhiyunSSTATETASKS += "do_image_complete" 284*4882a593SmuzhiyunSSTATE_SKIP_CREATION:task-image-complete = '1' 285*4882a593Smuzhiyundo_image_complete[sstate-inputdirs] = "${IMGDEPLOYDIR}" 286*4882a593Smuzhiyundo_image_complete[sstate-outputdirs] = "${DEPLOY_DIR_IMAGE}" 287*4882a593Smuzhiyundo_image_complete[stamp-extra-info] = "${MACHINE_ARCH}" 288*4882a593Smuzhiyunaddtask do_image_complete after do_image before do_build 289*4882a593Smuzhiyunpython do_image_complete_setscene () { 290*4882a593Smuzhiyun sstate_setscene(d) 291*4882a593Smuzhiyun} 292*4882a593Smuzhiyunaddtask do_image_complete_setscene 293*4882a593Smuzhiyun 294*4882a593Smuzhiyun# Add image-level QA/sanity checks to IMAGE_QA_COMMANDS 295*4882a593Smuzhiyun# 296*4882a593Smuzhiyun# IMAGE_QA_COMMANDS += " \ 297*4882a593Smuzhiyun# image_check_everything_ok \ 298*4882a593Smuzhiyun# " 299*4882a593Smuzhiyun# This task runs all functions in IMAGE_QA_COMMANDS after the rootfs 300*4882a593Smuzhiyun# construction has completed in order to validate the resulting image. 301*4882a593Smuzhiyun# 302*4882a593Smuzhiyun# The functions should use ${IMAGE_ROOTFS} to find the unpacked rootfs 303*4882a593Smuzhiyun# directory, which if QA passes will be the basis for the images. 304*4882a593Smuzhiyunfakeroot python do_image_qa () { 305*4882a593Smuzhiyun from oe.utils import ImageQAFailed 306*4882a593Smuzhiyun 307*4882a593Smuzhiyun qa_cmds = (d.getVar('IMAGE_QA_COMMANDS') or '').split() 308*4882a593Smuzhiyun qamsg = "" 309*4882a593Smuzhiyun 310*4882a593Smuzhiyun for cmd in qa_cmds: 311*4882a593Smuzhiyun try: 312*4882a593Smuzhiyun bb.build.exec_func(cmd, d) 313*4882a593Smuzhiyun except oe.utils.ImageQAFailed as e: 314*4882a593Smuzhiyun qamsg = qamsg + '\tImage QA function %s failed: %s\n' % (e.name, e.description) 315*4882a593Smuzhiyun except Exception as e: 316*4882a593Smuzhiyun qamsg = qamsg + '\tImage QA function %s failed: %s\n' % (cmd, e) 317*4882a593Smuzhiyun 318*4882a593Smuzhiyun if qamsg: 319*4882a593Smuzhiyun imgname = d.getVar('IMAGE_NAME') 320*4882a593Smuzhiyun bb.fatal("QA errors found whilst validating image: %s\n%s" % (imgname, qamsg)) 321*4882a593Smuzhiyun} 322*4882a593Smuzhiyunaddtask do_image_qa after do_rootfs before do_image 323*4882a593Smuzhiyun 324*4882a593SmuzhiyunSSTATETASKS += "do_image_qa" 325*4882a593SmuzhiyunSSTATE_SKIP_CREATION:task-image-qa = '1' 326*4882a593Smuzhiyundo_image_qa[sstate-inputdirs] = "" 327*4882a593Smuzhiyundo_image_qa[sstate-outputdirs] = "" 328*4882a593Smuzhiyunpython do_image_qa_setscene () { 329*4882a593Smuzhiyun sstate_setscene(d) 330*4882a593Smuzhiyun} 331*4882a593Smuzhiyunaddtask do_image_qa_setscene 332*4882a593Smuzhiyun 333*4882a593Smuzhiyundef setup_debugfs_variables(d): 334*4882a593Smuzhiyun d.appendVar('IMAGE_ROOTFS', '-dbg') 335*4882a593Smuzhiyun if d.getVar('IMAGE_LINK_NAME'): 336*4882a593Smuzhiyun d.appendVar('IMAGE_LINK_NAME', '-dbg') 337*4882a593Smuzhiyun d.appendVar('IMAGE_NAME','-dbg') 338*4882a593Smuzhiyun d.setVar('IMAGE_BUILDING_DEBUGFS', 'true') 339*4882a593Smuzhiyun debugfs_image_fstypes = d.getVar('IMAGE_FSTYPES_DEBUGFS') 340*4882a593Smuzhiyun if debugfs_image_fstypes: 341*4882a593Smuzhiyun d.setVar('IMAGE_FSTYPES', debugfs_image_fstypes) 342*4882a593Smuzhiyun 343*4882a593Smuzhiyunpython setup_debugfs () { 344*4882a593Smuzhiyun setup_debugfs_variables(d) 345*4882a593Smuzhiyun} 346*4882a593Smuzhiyun 347*4882a593Smuzhiyunpython () { 348*4882a593Smuzhiyun vardeps = set() 349*4882a593Smuzhiyun # We allow CONVERSIONTYPES to have duplicates. That avoids breaking 350*4882a593Smuzhiyun # derived distros when OE-core or some other layer independently adds 351*4882a593Smuzhiyun # the same type. There is still only one command for each type, but 352*4882a593Smuzhiyun # presumably the commands will do the same when the type is the same, 353*4882a593Smuzhiyun # even when added in different places. 354*4882a593Smuzhiyun # 355*4882a593Smuzhiyun # Without de-duplication, gen_conversion_cmds() below 356*4882a593Smuzhiyun # would create the same compression command multiple times. 357*4882a593Smuzhiyun ctypes = set(d.getVar('CONVERSIONTYPES').split()) 358*4882a593Smuzhiyun old_overrides = d.getVar('OVERRIDES', False) 359*4882a593Smuzhiyun 360*4882a593Smuzhiyun def _image_base_type(type): 361*4882a593Smuzhiyun basetype = type 362*4882a593Smuzhiyun for ctype in ctypes: 363*4882a593Smuzhiyun if type.endswith("." + ctype): 364*4882a593Smuzhiyun basetype = type[:-len("." + ctype)] 365*4882a593Smuzhiyun break 366*4882a593Smuzhiyun 367*4882a593Smuzhiyun if basetype != type: 368*4882a593Smuzhiyun # New base type itself might be generated by a conversion command. 369*4882a593Smuzhiyun basetype = _image_base_type(basetype) 370*4882a593Smuzhiyun 371*4882a593Smuzhiyun return basetype 372*4882a593Smuzhiyun 373*4882a593Smuzhiyun basetypes = {} 374*4882a593Smuzhiyun alltypes = d.getVar('IMAGE_FSTYPES').split() 375*4882a593Smuzhiyun typedeps = {} 376*4882a593Smuzhiyun 377*4882a593Smuzhiyun if d.getVar('IMAGE_GEN_DEBUGFS') == "1": 378*4882a593Smuzhiyun debugfs_fstypes = d.getVar('IMAGE_FSTYPES_DEBUGFS').split() 379*4882a593Smuzhiyun for t in debugfs_fstypes: 380*4882a593Smuzhiyun alltypes.append("debugfs_" + t) 381*4882a593Smuzhiyun 382*4882a593Smuzhiyun def _add_type(t): 383*4882a593Smuzhiyun baset = _image_base_type(t) 384*4882a593Smuzhiyun input_t = t 385*4882a593Smuzhiyun if baset not in basetypes: 386*4882a593Smuzhiyun basetypes[baset]= [] 387*4882a593Smuzhiyun if t not in basetypes[baset]: 388*4882a593Smuzhiyun basetypes[baset].append(t) 389*4882a593Smuzhiyun debug = "" 390*4882a593Smuzhiyun if t.startswith("debugfs_"): 391*4882a593Smuzhiyun t = t[8:] 392*4882a593Smuzhiyun debug = "debugfs_" 393*4882a593Smuzhiyun deps = (d.getVar('IMAGE_TYPEDEP:' + t) or "").split() 394*4882a593Smuzhiyun vardeps.add('IMAGE_TYPEDEP:' + t) 395*4882a593Smuzhiyun if baset not in typedeps: 396*4882a593Smuzhiyun typedeps[baset] = set() 397*4882a593Smuzhiyun deps = [debug + dep for dep in deps] 398*4882a593Smuzhiyun for dep in deps: 399*4882a593Smuzhiyun if dep not in alltypes: 400*4882a593Smuzhiyun alltypes.append(dep) 401*4882a593Smuzhiyun _add_type(dep) 402*4882a593Smuzhiyun basedep = _image_base_type(dep) 403*4882a593Smuzhiyun typedeps[baset].add(basedep) 404*4882a593Smuzhiyun 405*4882a593Smuzhiyun if baset != input_t: 406*4882a593Smuzhiyun _add_type(baset) 407*4882a593Smuzhiyun 408*4882a593Smuzhiyun for t in alltypes[:]: 409*4882a593Smuzhiyun _add_type(t) 410*4882a593Smuzhiyun 411*4882a593Smuzhiyun d.appendVarFlag('do_image', 'vardeps', ' '.join(vardeps)) 412*4882a593Smuzhiyun 413*4882a593Smuzhiyun maskedtypes = (d.getVar('IMAGE_TYPES_MASKED') or "").split() 414*4882a593Smuzhiyun maskedtypes = [dbg + t for t in maskedtypes for dbg in ("", "debugfs_")] 415*4882a593Smuzhiyun 416*4882a593Smuzhiyun for t in basetypes: 417*4882a593Smuzhiyun vardeps = set() 418*4882a593Smuzhiyun cmds = [] 419*4882a593Smuzhiyun subimages = [] 420*4882a593Smuzhiyun realt = t 421*4882a593Smuzhiyun 422*4882a593Smuzhiyun if t in maskedtypes: 423*4882a593Smuzhiyun continue 424*4882a593Smuzhiyun 425*4882a593Smuzhiyun localdata = bb.data.createCopy(d) 426*4882a593Smuzhiyun debug = "" 427*4882a593Smuzhiyun if t.startswith("debugfs_"): 428*4882a593Smuzhiyun setup_debugfs_variables(localdata) 429*4882a593Smuzhiyun debug = "setup_debugfs " 430*4882a593Smuzhiyun realt = t[8:] 431*4882a593Smuzhiyun localdata.setVar('OVERRIDES', '%s:%s' % (realt, old_overrides)) 432*4882a593Smuzhiyun localdata.setVar('type', realt) 433*4882a593Smuzhiyun # Delete DATETIME so we don't expand any references to it now 434*4882a593Smuzhiyun # This means the task's hash can be stable rather than having hardcoded 435*4882a593Smuzhiyun # date/time values. It will get expanded at execution time. 436*4882a593Smuzhiyun # Similarly TMPDIR since otherwise we see QA stamp comparision problems 437*4882a593Smuzhiyun # Expand PV else it can trigger get_srcrev which can fail due to these variables being unset 438*4882a593Smuzhiyun localdata.setVar('PV', d.getVar('PV')) 439*4882a593Smuzhiyun localdata.delVar('DATETIME') 440*4882a593Smuzhiyun localdata.delVar('DATE') 441*4882a593Smuzhiyun localdata.delVar('TMPDIR') 442*4882a593Smuzhiyun localdata.delVar('IMAGE_VERSION_SUFFIX') 443*4882a593Smuzhiyun vardepsexclude = (d.getVarFlag('IMAGE_CMD:' + realt, 'vardepsexclude') or '').split() 444*4882a593Smuzhiyun for dep in vardepsexclude: 445*4882a593Smuzhiyun localdata.delVar(dep) 446*4882a593Smuzhiyun 447*4882a593Smuzhiyun image_cmd = localdata.getVar("IMAGE_CMD") 448*4882a593Smuzhiyun vardeps.add('IMAGE_CMD:' + realt) 449*4882a593Smuzhiyun if image_cmd: 450*4882a593Smuzhiyun cmds.append("\t" + image_cmd) 451*4882a593Smuzhiyun else: 452*4882a593Smuzhiyun bb.fatal("No IMAGE_CMD defined for IMAGE_FSTYPES entry '%s' - possibly invalid type name or missing support class" % t) 453*4882a593Smuzhiyun cmds.append(localdata.expand("\tcd ${IMGDEPLOYDIR}")) 454*4882a593Smuzhiyun 455*4882a593Smuzhiyun # Since a copy of IMAGE_CMD:xxx will be inlined within do_image_xxx, 456*4882a593Smuzhiyun # prevent a redundant copy of IMAGE_CMD:xxx being emitted as a function. 457*4882a593Smuzhiyun d.delVarFlag('IMAGE_CMD:' + realt, 'func') 458*4882a593Smuzhiyun 459*4882a593Smuzhiyun rm_tmp_images = set() 460*4882a593Smuzhiyun def gen_conversion_cmds(bt): 461*4882a593Smuzhiyun for ctype in sorted(ctypes): 462*4882a593Smuzhiyun if bt.endswith("." + ctype): 463*4882a593Smuzhiyun type = bt[0:-len(ctype) - 1] 464*4882a593Smuzhiyun if type.startswith("debugfs_"): 465*4882a593Smuzhiyun type = type[8:] 466*4882a593Smuzhiyun # Create input image first. 467*4882a593Smuzhiyun gen_conversion_cmds(type) 468*4882a593Smuzhiyun localdata.setVar('type', type) 469*4882a593Smuzhiyun cmd = "\t" + localdata.getVar("CONVERSION_CMD:" + ctype) 470*4882a593Smuzhiyun if cmd not in cmds: 471*4882a593Smuzhiyun cmds.append(cmd) 472*4882a593Smuzhiyun vardeps.add('CONVERSION_CMD:' + ctype) 473*4882a593Smuzhiyun subimage = type + "." + ctype 474*4882a593Smuzhiyun if subimage not in subimages: 475*4882a593Smuzhiyun subimages.append(subimage) 476*4882a593Smuzhiyun if type not in alltypes: 477*4882a593Smuzhiyun rm_tmp_images.add(localdata.expand("${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.${type}")) 478*4882a593Smuzhiyun 479*4882a593Smuzhiyun for bt in basetypes[t]: 480*4882a593Smuzhiyun gen_conversion_cmds(bt) 481*4882a593Smuzhiyun 482*4882a593Smuzhiyun localdata.setVar('type', realt) 483*4882a593Smuzhiyun if t not in alltypes: 484*4882a593Smuzhiyun rm_tmp_images.add(localdata.expand("${IMAGE_NAME}${IMAGE_NAME_SUFFIX}.${type}")) 485*4882a593Smuzhiyun else: 486*4882a593Smuzhiyun subimages.append(realt) 487*4882a593Smuzhiyun 488*4882a593Smuzhiyun # Clean up after applying all conversion commands. Some of them might 489*4882a593Smuzhiyun # use the same input, therefore we cannot delete sooner without applying 490*4882a593Smuzhiyun # some complex dependency analysis. 491*4882a593Smuzhiyun for image in sorted(rm_tmp_images): 492*4882a593Smuzhiyun cmds.append("\trm " + image) 493*4882a593Smuzhiyun 494*4882a593Smuzhiyun after = 'do_image' 495*4882a593Smuzhiyun for dep in typedeps[t]: 496*4882a593Smuzhiyun after += ' do_image_%s' % dep.replace("-", "_").replace(".", "_") 497*4882a593Smuzhiyun 498*4882a593Smuzhiyun task = "do_image_%s" % t.replace("-", "_").replace(".", "_") 499*4882a593Smuzhiyun 500*4882a593Smuzhiyun d.setVar(task, '\n'.join(cmds)) 501*4882a593Smuzhiyun d.setVarFlag(task, 'func', '1') 502*4882a593Smuzhiyun d.setVarFlag(task, 'fakeroot', '1') 503*4882a593Smuzhiyun 504*4882a593Smuzhiyun d.appendVarFlag(task, 'prefuncs', ' ' + debug + ' set_image_size') 505*4882a593Smuzhiyun d.prependVarFlag(task, 'postfuncs', 'create_symlinks ') 506*4882a593Smuzhiyun d.appendVarFlag(task, 'subimages', ' ' + ' '.join(subimages)) 507*4882a593Smuzhiyun d.appendVarFlag(task, 'vardeps', ' ' + ' '.join(vardeps)) 508*4882a593Smuzhiyun d.appendVarFlag(task, 'vardepsexclude', ' DATETIME DATE ' + ' '.join(vardepsexclude)) 509*4882a593Smuzhiyun 510*4882a593Smuzhiyun bb.debug(2, "Adding task %s before %s, after %s" % (task, 'do_image_complete', after)) 511*4882a593Smuzhiyun bb.build.addtask(task, 'do_image_complete', after, d) 512*4882a593Smuzhiyun} 513*4882a593Smuzhiyun 514*4882a593Smuzhiyun# 515*4882a593Smuzhiyun# Compute the rootfs size 516*4882a593Smuzhiyun# 517*4882a593Smuzhiyundef get_rootfs_size(d): 518*4882a593Smuzhiyun import subprocess, oe.utils 519*4882a593Smuzhiyun 520*4882a593Smuzhiyun rootfs_alignment = int(d.getVar('IMAGE_ROOTFS_ALIGNMENT')) 521*4882a593Smuzhiyun overhead_factor = float(d.getVar('IMAGE_OVERHEAD_FACTOR')) 522*4882a593Smuzhiyun rootfs_req_size = int(d.getVar('IMAGE_ROOTFS_SIZE')) 523*4882a593Smuzhiyun rootfs_extra_space = eval(d.getVar('IMAGE_ROOTFS_EXTRA_SPACE')) 524*4882a593Smuzhiyun rootfs_maxsize = d.getVar('IMAGE_ROOTFS_MAXSIZE') 525*4882a593Smuzhiyun image_fstypes = d.getVar('IMAGE_FSTYPES') or '' 526*4882a593Smuzhiyun initramfs_fstypes = d.getVar('INITRAMFS_FSTYPES') or '' 527*4882a593Smuzhiyun initramfs_maxsize = d.getVar('INITRAMFS_MAXSIZE') 528*4882a593Smuzhiyun 529*4882a593Smuzhiyun size_kb = oe.utils.directory_size(d.getVar("IMAGE_ROOTFS")) / 1024 530*4882a593Smuzhiyun 531*4882a593Smuzhiyun base_size = size_kb * overhead_factor 532*4882a593Smuzhiyun bb.debug(1, '%f = %d * %f' % (base_size, size_kb, overhead_factor)) 533*4882a593Smuzhiyun base_size2 = max(base_size, rootfs_req_size) + rootfs_extra_space 534*4882a593Smuzhiyun bb.debug(1, '%f = max(%f, %d)[%f] + %d' % (base_size2, base_size, rootfs_req_size, max(base_size, rootfs_req_size), rootfs_extra_space)) 535*4882a593Smuzhiyun 536*4882a593Smuzhiyun base_size = base_size2 537*4882a593Smuzhiyun if base_size != int(base_size): 538*4882a593Smuzhiyun base_size = int(base_size + 1) 539*4882a593Smuzhiyun else: 540*4882a593Smuzhiyun base_size = int(base_size) 541*4882a593Smuzhiyun bb.debug(1, '%f = int(%f)' % (base_size, base_size2)) 542*4882a593Smuzhiyun 543*4882a593Smuzhiyun base_size_saved = base_size 544*4882a593Smuzhiyun base_size += rootfs_alignment - 1 545*4882a593Smuzhiyun base_size -= base_size % rootfs_alignment 546*4882a593Smuzhiyun bb.debug(1, '%d = aligned(%d)' % (base_size, base_size_saved)) 547*4882a593Smuzhiyun 548*4882a593Smuzhiyun # Do not check image size of the debugfs image. This is not supposed 549*4882a593Smuzhiyun # to be deployed, etc. so it doesn't make sense to limit the size 550*4882a593Smuzhiyun # of the debug. 551*4882a593Smuzhiyun if (d.getVar('IMAGE_BUILDING_DEBUGFS') or "") == "true": 552*4882a593Smuzhiyun bb.debug(1, 'returning debugfs size %d' % (base_size)) 553*4882a593Smuzhiyun return base_size 554*4882a593Smuzhiyun 555*4882a593Smuzhiyun # Check the rootfs size against IMAGE_ROOTFS_MAXSIZE (if set) 556*4882a593Smuzhiyun if rootfs_maxsize: 557*4882a593Smuzhiyun rootfs_maxsize_int = int(rootfs_maxsize) 558*4882a593Smuzhiyun if base_size > rootfs_maxsize_int: 559*4882a593Smuzhiyun bb.fatal("The rootfs size %d(K) exceeds IMAGE_ROOTFS_MAXSIZE: %d(K)" % \ 560*4882a593Smuzhiyun (base_size, rootfs_maxsize_int)) 561*4882a593Smuzhiyun 562*4882a593Smuzhiyun # Check the initramfs size against INITRAMFS_MAXSIZE (if set) 563*4882a593Smuzhiyun if image_fstypes == initramfs_fstypes != '' and initramfs_maxsize: 564*4882a593Smuzhiyun initramfs_maxsize_int = int(initramfs_maxsize) 565*4882a593Smuzhiyun if base_size > initramfs_maxsize_int: 566*4882a593Smuzhiyun bb.error("The initramfs size %d(K) exceeds INITRAMFS_MAXSIZE: %d(K)" % \ 567*4882a593Smuzhiyun (base_size, initramfs_maxsize_int)) 568*4882a593Smuzhiyun bb.error("You can set INITRAMFS_MAXSIZE a larger value. Usually, it should") 569*4882a593Smuzhiyun bb.fatal("be less than 1/2 of ram size, or you may fail to boot it.\n") 570*4882a593Smuzhiyun 571*4882a593Smuzhiyun bb.debug(1, 'returning %d' % (base_size)) 572*4882a593Smuzhiyun return base_size 573*4882a593Smuzhiyun 574*4882a593Smuzhiyunpython set_image_size () { 575*4882a593Smuzhiyun rootfs_size = get_rootfs_size(d) 576*4882a593Smuzhiyun d.setVar('ROOTFS_SIZE', str(rootfs_size)) 577*4882a593Smuzhiyun d.setVarFlag('ROOTFS_SIZE', 'export', '1') 578*4882a593Smuzhiyun} 579*4882a593Smuzhiyun 580*4882a593Smuzhiyun# 581*4882a593Smuzhiyun# Create symlinks to the newly created image 582*4882a593Smuzhiyun# 583*4882a593Smuzhiyunpython create_symlinks() { 584*4882a593Smuzhiyun 585*4882a593Smuzhiyun deploy_dir = d.getVar('IMGDEPLOYDIR') 586*4882a593Smuzhiyun img_name = d.getVar('IMAGE_NAME') 587*4882a593Smuzhiyun link_name = d.getVar('IMAGE_LINK_NAME') 588*4882a593Smuzhiyun manifest_name = d.getVar('IMAGE_MANIFEST') 589*4882a593Smuzhiyun taskname = d.getVar("BB_CURRENTTASK") 590*4882a593Smuzhiyun subimages = (d.getVarFlag("do_" + taskname, 'subimages', False) or "").split() 591*4882a593Smuzhiyun imgsuffix = d.getVarFlag("do_" + taskname, 'imgsuffix') or d.expand("${IMAGE_NAME_SUFFIX}.") 592*4882a593Smuzhiyun 593*4882a593Smuzhiyun if not link_name: 594*4882a593Smuzhiyun return 595*4882a593Smuzhiyun for type in subimages: 596*4882a593Smuzhiyun dst = os.path.join(deploy_dir, link_name + "." + type) 597*4882a593Smuzhiyun src = img_name + imgsuffix + type 598*4882a593Smuzhiyun if os.path.exists(os.path.join(deploy_dir, src)): 599*4882a593Smuzhiyun bb.note("Creating symlink: %s -> %s" % (dst, src)) 600*4882a593Smuzhiyun if os.path.islink(dst): 601*4882a593Smuzhiyun os.remove(dst) 602*4882a593Smuzhiyun os.symlink(src, dst) 603*4882a593Smuzhiyun else: 604*4882a593Smuzhiyun bb.note("Skipping symlink, source does not exist: %s -> %s" % (dst, src)) 605*4882a593Smuzhiyun} 606*4882a593Smuzhiyun 607*4882a593SmuzhiyunMULTILIBRE_ALLOW_REP =. "${base_bindir}|${base_sbindir}|${bindir}|${sbindir}|${libexecdir}|${sysconfdir}|${nonarch_base_libdir}/udev|/lib/modules/[^/]*/modules.*|" 608*4882a593SmuzhiyunMULTILIB_CHECK_FILE = "${WORKDIR}/multilib_check.py" 609*4882a593SmuzhiyunMULTILIB_TEMP_ROOTFS = "${WORKDIR}/multilib" 610*4882a593Smuzhiyun 611*4882a593Smuzhiyundo_fetch[noexec] = "1" 612*4882a593Smuzhiyundo_unpack[noexec] = "1" 613*4882a593Smuzhiyundo_patch[noexec] = "1" 614*4882a593Smuzhiyundo_configure[noexec] = "1" 615*4882a593Smuzhiyundo_compile[noexec] = "1" 616*4882a593Smuzhiyundo_install[noexec] = "1" 617*4882a593Smuzhiyundeltask do_populate_lic 618*4882a593Smuzhiyundeltask do_populate_sysroot 619*4882a593Smuzhiyundo_package[noexec] = "1" 620*4882a593Smuzhiyundeltask do_package_qa 621*4882a593Smuzhiyundeltask do_packagedata 622*4882a593Smuzhiyundeltask do_package_write_ipk 623*4882a593Smuzhiyundeltask do_package_write_deb 624*4882a593Smuzhiyundeltask do_package_write_rpm 625*4882a593Smuzhiyun 626*4882a593Smuzhiyun# Prepare the root links to point to the /usr counterparts. 627*4882a593Smuzhiyuncreate_merged_usr_symlinks() { 628*4882a593Smuzhiyun root="$1" 629*4882a593Smuzhiyun install -d $root${base_bindir} $root${base_sbindir} $root${base_libdir} 630*4882a593Smuzhiyun ln -rs $root${base_bindir} $root/bin 631*4882a593Smuzhiyun ln -rs $root${base_sbindir} $root/sbin 632*4882a593Smuzhiyun ln -rs $root${base_libdir} $root/${baselib} 633*4882a593Smuzhiyun 634*4882a593Smuzhiyun if [ "${nonarch_base_libdir}" != "${base_libdir}" ]; then 635*4882a593Smuzhiyun install -d $root${nonarch_base_libdir} 636*4882a593Smuzhiyun ln -rs $root${nonarch_base_libdir} $root/lib 637*4882a593Smuzhiyun fi 638*4882a593Smuzhiyun 639*4882a593Smuzhiyun # create base links for multilibs 640*4882a593Smuzhiyun multi_libdirs="${@d.getVar('MULTILIB_VARIANTS')}" 641*4882a593Smuzhiyun for d in $multi_libdirs; do 642*4882a593Smuzhiyun install -d $root${exec_prefix}/$d 643*4882a593Smuzhiyun ln -rs $root${exec_prefix}/$d $root/$d 644*4882a593Smuzhiyun done 645*4882a593Smuzhiyun} 646*4882a593Smuzhiyun 647*4882a593Smuzhiyuncreate_merged_usr_symlinks_rootfs() { 648*4882a593Smuzhiyun create_merged_usr_symlinks ${IMAGE_ROOTFS} 649*4882a593Smuzhiyun} 650*4882a593Smuzhiyun 651*4882a593Smuzhiyuncreate_merged_usr_symlinks_sdk() { 652*4882a593Smuzhiyun create_merged_usr_symlinks ${SDK_OUTPUT}${SDKTARGETSYSROOT} 653*4882a593Smuzhiyun} 654*4882a593Smuzhiyun 655*4882a593SmuzhiyunROOTFS_PREPROCESS_COMMAND += "${@bb.utils.contains('DISTRO_FEATURES', 'usrmerge', 'create_merged_usr_symlinks_rootfs; ', '',d)}" 656*4882a593SmuzhiyunPOPULATE_SDK_PRE_TARGET_COMMAND += "${@bb.utils.contains('DISTRO_FEATURES', 'usrmerge', 'create_merged_usr_symlinks_sdk; ', '',d)}" 657*4882a593Smuzhiyun 658*4882a593Smuzhiyunreproducible_final_image_task () { 659*4882a593Smuzhiyun if [ "$REPRODUCIBLE_TIMESTAMP_ROOTFS" = "" ]; then 660*4882a593Smuzhiyun REPRODUCIBLE_TIMESTAMP_ROOTFS=`git -C "${COREBASE}" log -1 --pretty=%ct 2>/dev/null` || true 661*4882a593Smuzhiyun if [ "$REPRODUCIBLE_TIMESTAMP_ROOTFS" = "" ]; then 662*4882a593Smuzhiyun REPRODUCIBLE_TIMESTAMP_ROOTFS=`stat -c%Y ${@bb.utils.which(d.getVar("BBPATH"), "conf/bitbake.conf")}` 663*4882a593Smuzhiyun fi 664*4882a593Smuzhiyun fi 665*4882a593Smuzhiyun # Set mtime of all files to a reproducible value 666*4882a593Smuzhiyun bbnote "reproducible_final_image_task: mtime set to $REPRODUCIBLE_TIMESTAMP_ROOTFS" 667*4882a593Smuzhiyun find ${IMAGE_ROOTFS} -print0 | xargs -0 touch -h --date=@$REPRODUCIBLE_TIMESTAMP_ROOTFS 668*4882a593Smuzhiyun} 669*4882a593Smuzhiyun 670*4882a593Smuzhiyunsystemd_preset_all () { 671*4882a593Smuzhiyun if [ -e ${IMAGE_ROOTFS}${root_prefix}/lib/systemd/systemd ]; then 672*4882a593Smuzhiyun systemctl --root="${IMAGE_ROOTFS}" --preset-mode=enable-only preset-all 673*4882a593Smuzhiyun fi 674*4882a593Smuzhiyun} 675*4882a593Smuzhiyun 676*4882a593SmuzhiyunIMAGE_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; " 677*4882a593Smuzhiyun 678*4882a593SmuzhiyunCVE_PRODUCT = "" 679