#!/bin/bash # SPDX-License-Identifier: GPL-2.0-or-later # Copyright (C) 2009-2016 Stephan Raue (stephan@openelec.tv) # Copyright (C) 2016-present Team LibreELEC (https://libreelec.tv) unset _CACHE_PACKAGE_LOCAL _CACHE_PACKAGE_GLOBAL _DEBUG_DEPENDS_LIST _DEBUG_PACKAGE_LIST . config/options "" . config/multithread . config/show_config ${SCRIPTS}/checkdeps # Setup both toolchain cmake configs to avoid potentially racy behaviour later. # Use a fork for host to isolate any variable modifications. (setup_toolchain host) setup_toolchain target show_config function do_mkimage() { # Variables used in mkimage script must be passed env \ ROOT="${ROOT}" \ SCRIPTS="${SCRIPTS}" \ TOOLCHAIN="${TOOLCHAIN}" \ PROJECT_DIR="${PROJECT_DIR}" \ PROJECT="${PROJECT}" \ DEVICE="${DEVICE}" \ DISTRO="${DISTRO}" \ DISTRO_HOME_URL="${DISTRO_HOME_URL}" \ TARGET_IMG="${TARGET_IMG}" \ BUILD_NAME="${IMAGE_NAME}" \ IMAGE_NAME="${1:-${IMAGE_NAME}}" \ BOOTLOADER="${BOOTLOADER}" \ KERNEL_NAME="${KERNEL_NAME}" \ TARGET_KERNEL_ARCH="${TARGET_KERNEL_ARCH}" \ RELEASE_DIR="${RELEASE_DIR}" \ UUID_SYSTEM="${UUID_SYSTEM}" \ UUID_STORAGE="${UUID_STORAGE}" \ UUID_ROOT="${UUID_ROOT}" \ DISTRO_BOOTLABEL="${DISTRO_BOOTLABEL}" \ DISTRO_ROOTLABEL="${DISTRO_ROOTLABEL}" \ DISTRO_DISKLABEL="${DISTRO_DISKLABEL}" \ UBOOT_SYSTEM="${UBOOT_SYSTEM}" \ EXTRA_CMDLINE="${EXTRA_CMDLINE}" \ SYSTEM_SIZE="${SYSTEM_SIZE}" \ SYSTEM_PART_START="${SYSTEM_PART_START}" \ BOOT_SIZE="${BOOT_SIZE}" \ ROOT_SIZE="${ROOT_SIZE}" \ ROOTFS_TYPE="${ROOTFS_TYPE}" \ STORAGE_SIZE="${STORAGE_SIZE:-32}" \ OVA_SIZE="${OVA_SIZE}" \ SUBDEVICE="${SUBDEVICE}" \ ${SCRIPTS}/mkimage } if [ -n "${CUSTOM_GIT_HASH}" ]; then GIT_HASH="${CUSTOM_GIT_HASH}" else GIT_HASH=$(git rev-parse HEAD) fi if [ "${DISTRO_VERSION}" = "devel" ]; then GIT_ABBREV=${GIT_HASH:0:7} DEVEL_VERSION=${DISTRO_VERSION} case "${BUILD_PERIODIC}" in nightly) DISTRO_VERSION=nightly-$(date +%Y%m%d)-${GIT_ABBREV} ;; daily) DISTRO_VERSION=daily-$(date +%Y%j)-${GIT_ABBREV} ;; weekly) DISTRO_VERSION=weekly-$(date +%G%V)-${GIT_ABBREV} ;; monthly) DISTRO_VERSION=monthly-$(date +%Y%m)-${GIT_ABBREV} ;; *) DISTRO_VERSION=devel-$(date +%Y%m%d%H%M%S)-${GIT_ABBREV} ;; esac fi DISTRO_VERSION=$(date +%Y%m%d) # Get origin url, fix git:// and git@github.com: urls if necessary ORIGIN_URL="$(git remote -v | awk '$1 == "origin" { print $2 }' | head -1 | sed -e 's#\.git$##' -e 's#^git:#https:#' -e 's#^git@github\.com:#https://github.com/#' -e 's#://.*@#://#')" eval "$(base64 -d <<< aWYgWyAiJHtPRkZJQ0lBTH0iID0gInllcyIgXTsgdGhlbgogIGV4cG9ydCBPU19CVUlMRD0ib2ZmaWNpYWwiCmVsaWYgWyAiJHtOSUdIVExZfSIgPSAieWVzIiBdOyB0aGVuCiAgZXhwb3J0IE9TX0JVSUxEPSJuaWdodGx5IgplbHNlCiAgZXhwb3J0IE9TX0JVSUxEPSJjb21tdW5pdHkiCmZp)" if [ -n "${CUSTOM_VERSION}" ]; then DISTRO_VERSION="${CUSTOM_VERSION}" fi DISTRO_ARCH="${DEVICE_NAME:-${DEVICE:-${PROJECT}}}.${TARGET_ARCH}" TARGET_VERSION="${DISTRO_ARCH}-${DISTRO_VERSION}" if [ -n "${CUSTOM_IMAGE_NAME}" ]; then IMAGE_NAME="${CUSTOM_IMAGE_NAME}" else if [ "${DEVEL_VERSION}" = "devel" ]; then IMAGE_NAME="${DISTRONAME}-${DISTRO_ARCH}-${OS_VERSION}" else IMAGE_NAME="${DISTRONAME}-${TARGET_VERSION}" fi if [ -n "${UBOOT_SYSTEM}" ] && [ "${UBOOT_SYSTEM}" != "${DEVICE:-${PROJECT}}" ]; then IMAGE_NAME="${IMAGE_NAME}-${UBOOT_SYSTEM}" fi fi if [ -n "${IMAGE_SUFFIX}" ]; then IMAGE_NAME="${IMAGE_NAME}-${IMAGE_SUFFIX}" fi echo "${IMAGE_NAME}" >${BUILD}/BUILD_FILENAME # Setup fakeroot rm -rf ${FAKEROOT_SCRIPT} # remove ${FAKEROOT_SCRIPT} if it exist touch ${FAKEROOT_SCRIPT} # create an empty ${FAKEROOT_SCRIPT} chmod +x ${FAKEROOT_SCRIPT} # make ${FAKEROOT_SCRIPT} executable echo "chown -R 0:0 ${INSTALL}" >>${FAKEROOT_SCRIPT} # Clean old install dirs rm -rf ${BUILD}/qa_checks/general rm -rf ${INSTALL} rm -rf ${STAMPS_INSTALL} mkdir -p ${INSTALL} # Create base layout of read-only file system for directory in etc dev proc run sys tmp usr var flash storage; do mkdir -p ${INSTALL}/${directory} done # Build image contents MTADDONBUILD=no start_multithread_build image || die "Parallel build failure - see log for details. Time of failure: $(date)" echo echo "Successful build, creating image..." >&2 # Create legacy sym links ln -sfn /var/media ${INSTALL}/media ln -sfn /usr/lib ${INSTALL}/lib ln -sfn /usr/bin ${INSTALL}/bin ln -sfn /usr/sbin ${INSTALL}/sbin if [ "${TARGET_ARCH}" = "x86_64" ]; then ln -sfn /usr/lib ${INSTALL}/lib64 ln -sfn /usr/lib ${INSTALL}/usr/lib64 fi echo "${TARGET_VERSION}" >${INSTALL}/etc/release # Create /etc/os-release cat <${INSTALL}/etc/os-release OS_NAME="${DISTRONAME}" OS_VERSION="${OS_VERSION}" OS_BUILD="${OS_BUILD}" GIT_ORGANIZATION="${GIT_ORGANIZATION}" GIT_REPO="${GIT_REPO}" HOME_URL="${HOME_URL}" BUILD_ID="${GIT_HASH}" BUILD_BRANCH="$(git branch --show-current)" BUILD_DATE="${BUILD_DATE}" HW_DEVICE="${DEVICE}" HW_ARCH="${ARCH}" EOF if [ -n "${HW_CPU}" ] then cat <>${INSTALL}/etc/os-release HW_CPU="${HW_CPU}" EOF fi [ -n "${DEVICE}" ] && echo "DISTRO_DEVICE=\"${DEVICE}\"" >>${INSTALL}/etc/os-release [ -n "${BUILDER_NAME}" ] && echo "BUILDER_NAME=\"${BUILDER_NAME}\"" >>${INSTALL}/etc/os-release [ -n "${BUILDER_VERSION}" ] && echo "BUILDER_VERSION=\"${BUILDER_VERSION}\"" >>${INSTALL}/etc/os-release # Copy PROJECT related files to filesystem if [ -d "${PROJECT_DIR}/${PROJECT}/filesystem" ]; then cp -PR --remove-destination ${PROJECT_DIR}/${PROJECT}/filesystem/* ${INSTALL} # Install project specific systemd services for service in ${PROJECT_DIR}/${PROJECT}/filesystem/usr/lib/systemd/system/*.service; do if [ -f "${service}" ]; then enable_service ${service##*/} fi done fi # Copy DEVICE related files to filesystem if [ -n "${DEVICE}" -a -d "${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/filesystem" ]; then cp -PR --remove-destination ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/filesystem/* ${INSTALL} # Install device specific systemd services for service in ${PROJECT_DIR}/${PROJECT}/devices/${DEVICE}/filesystem/usr/lib/systemd/system/*.service; do if [ -f "${service}" ]; then enable_service ${service##*/} fi done fi # Replace placeholders with values in install script to eMMC if [ -f ${INSTALL}/usr/bin/install2emmc ]; then sed -e "s%@SYSTEM_SIZE@%${SYSTEM_SIZE}%g" \ -i ${INSTALL}/usr/bin/install2emmc sed -e "s%@DISTRONAME@%${DISTRONAME}%g" \ -i ${INSTALL}/usr/bin/install2emmc fi # Run depmod for base overlay modules MODVER=$(basename $(ls -d ${INSTALL}/usr/lib/kernel-overlays/base/lib/modules/*)) find ${INSTALL}/usr/lib/kernel-overlays/base/lib/modules/${MODVER}/ -name *.ko | sed -e "s,${INSTALL}/usr/lib/kernel-overlays/base/lib/modules/${MODVER}/,," \ >${INSTALL}/usr/lib/kernel-overlays/base/lib/modules/${MODVER}/modules.order ${TOOLCHAIN}/bin/depmod -b ${INSTALL}/usr/lib/kernel-overlays/base -a -e -F "$(get_install_dir linux)/.image/System.map" ${MODVER} 2>&1 # Strip kernel modules for MOD in $(find ${INSTALL}/usr/lib/kernel-overlays/ -type f -name *.ko); do ${TARGET_KERNEL_PREFIX}strip --strip-debug ${MOD} done # Symlink overlayed modules to /usr/lib/modules ln -sT /run/kernel-overlays/modules ${INSTALL}/usr/lib/modules # Symlink overlayed firmware to /usr/lib/firmware ln -sT /run/kernel-overlays/firmware ${INSTALL}/usr/lib/firmware # Make target dir mkdir -p ${TARGET_IMG} rm -rf ${TARGET_IMG}/${IMAGE_NAME}.kernel # Copy kernel to target dir cp -PR $(get_install_dir linux)/.image/${KERNEL_TARGET} ${TARGET_IMG}/${IMAGE_NAME}.kernel chmod 0644 ${TARGET_IMG}/${IMAGE_NAME}.kernel if [ "${ROOTFS_TYPE}" = "ext4" ]; then # Create ext4 rootfs image inside fakeroot (preserves ownership/permissions) echo "rm -rf \"${TARGET_IMG}/${IMAGE_NAME}.system\"" >>${FAKEROOT_SCRIPT} echo "dd if=/dev/zero of=\"${TARGET_IMG}/${IMAGE_NAME}.system\" bs=1M count=${ROOT_SIZE}" >>${FAKEROOT_SCRIPT} echo "${TOOLCHAIN}/sbin/mke2fs -F -q -t ext4 -T ext4 -O ^orphan_file -m 1 \"${TARGET_IMG}/${IMAGE_NAME}.system\"" >>${FAKEROOT_SCRIPT} echo "${TOOLCHAIN}/bin/populatefs -U -d \"${BUILD}/image/system\" \"${TARGET_IMG}/${IMAGE_NAME}.system\"" >>${FAKEROOT_SCRIPT} # Run fakeroot ${TOOLCHAIN}/bin/fakeroot -- ${FAKEROOT_SCRIPT} rm -rf ${FAKEROOT_SCRIPT} # Verify ext4 image e2fsck -n "${TARGET_IMG}/${IMAGE_NAME}.system" >"${BUILD}/.work/e2fsck.log" 2>&1 || true # Set permissions chmod 0644 ${TARGET_IMG}/${IMAGE_NAME}.system else # Set mksquashfs options for each compression method if [ -z "${SQUASHFS_COMPRESSION_OPTION}" ]; then if [ "${SQUASHFS_COMPRESSION:-gzip}" = "gzip" ]; then SQUASHFS_COMPRESSION_OPTION="-Xcompression-level 9 -b 262144" elif [ "${SQUASHFS_COMPRESSION}" = "lzo" ]; then SQUASHFS_COMPRESSION_OPTION="-Xcompression-level 9 -b 524288" elif [ "${SQUASHFS_COMPRESSION}" = "zstd" ]; then SQUASHFS_COMPRESSION_OPTION="-Xcompression-level 19 -b 1048576" fi fi # Create squashfs file, default to gzip if no compression configured echo "rm -rf \"${TARGET_IMG}/${IMAGE_NAME}.system\"" >>${FAKEROOT_SCRIPT} echo "${TOOLCHAIN}/bin/mksquashfs \"${BUILD}/image/system\" \"${TARGET_IMG}/${IMAGE_NAME}.system\" -noappend -comp ${SQUASHFS_COMPRESSION:-gzip} ${SQUASHFS_COMPRESSION_OPTION}" >>${FAKEROOT_SCRIPT} # Run fakeroot ${TOOLCHAIN}/bin/fakeroot -- ${FAKEROOT_SCRIPT} rm -rf ${FAKEROOT_SCRIPT} # Set permissions chmod 0644 ${TARGET_IMG}/${IMAGE_NAME}.system fi if [ "${1}" = "release" -o "${1}" = "mkimage" -o "${1}" = "noobs" ]; then RELEASE_DIR="target/${IMAGE_NAME}" # Cleanup rm -rf ${RELEASE_DIR} # Create release dir mkdir -p ${RELEASE_DIR} # Remove any previously created release images rm -rf ${TARGET_IMG}/${IMAGE_NAME}.img.gz if [ -n "${BOOTLOADER}" ]; then BOOTLOADER_DIR="$(get_pkg_directory "${BOOTLOADER}")" if [ -d ${BOOTLOADER_DIR}/files ]; then cp -R ${BOOTLOADER_DIR}/files/* ${RELEASE_DIR} fi if find_file_path bootloader/release ${BOOTLOADER_DIR}/release; then echo "Running ${FOUND_PATH}" . ${FOUND_PATH} fi fi cp ${ROOT}/README* ${RELEASE_DIR} echo "${TARGET_VERSION}" >${RELEASE_DIR}/RELEASE if [ ! "${MEDIACENTER}" = "no" ]; then echo "Kodi commit: $(get_pkg_version ${MEDIACENTER})" >>${RELEASE_DIR}/RELEASE fi mkdir -p ${RELEASE_DIR}/licenses cp ${ROOT}/licenses/* ${RELEASE_DIR}/licenses mkdir -p ${RELEASE_DIR}/target cp ${TARGET_IMG}/${IMAGE_NAME}.system ${RELEASE_DIR}/target/SYSTEM cp ${TARGET_IMG}/${IMAGE_NAME}.kernel ${RELEASE_DIR}/target/KERNEL # Create md5sum's ( cd ${RELEASE_DIR} md5sum -t target/SYSTEM >target/SYSTEM.md5 md5sum -t target/KERNEL >target/KERNEL.md5 ) # Create target directory mkdir -p ${TARGET_IMG} # Remove any previously created release tarballs rm -rf ${TARGET_IMG}/${IMAGE_NAME}.tar # Create release tarball tar cf ${TARGET_IMG}/${IMAGE_NAME}.tar -C target ${IMAGE_NAME} # Create sha256 checksum of tarball ( cd ${TARGET_IMG} sha256sum ${IMAGE_NAME}.tar >${IMAGE_NAME}.tar.sha256 ) # Create image files if requested if [[ ("${1}" = "noobs" || "${1}" = "mkimage") && -n "${BOOTLOADER}" ]]; then UUID_SYSTEM="$(date '+%d%m')-$(date '+%M%S')" UUID_STORAGE="$(uuidgen)" UUID_ROOT="$(uuidgen)" if [ -n "${SUBDEVICES}" ]; then for SUBDEVICE in ${SUBDEVICES}; do do_mkimage "${IMAGE_NAME}" done else do_mkimage fi fi # Cleanup release dir rm -rf ${RELEASE_DIR} if [ "${1}" = "noobs" ]; then echo "Creating \"${1}\" release tarball..." RELEASE_DIR="${TARGET_IMG}/${IMAGE_NAME}-${1}" # eg. Distro_RPi, Distro_RPi2 etc. NOOBS_DISTRO="${DISTRONAME}_${DEVICE:-${PROJECT}}" # Create release dir mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO} if [ -f ${DISTRO_DIR}/${DISTRO}/${DISTRONAME}_40x40.png ]; then cp -PR ${DISTRO_DIR}/${DISTRO}/${DISTRONAME}_40x40.png ${RELEASE_DIR}/${NOOBS_DISTRO}/${NOOBS_DISTRO}.png else cp -PR ${DISTRO_DIR}/${DISTRO}/${DISTRONAME}.png ${RELEASE_DIR}/${NOOBS_DISTRO}/${NOOBS_DISTRO}.png fi cp -PR ${ROOT}/config/noobs/os.json ${RELEASE_DIR}/${NOOBS_DISTRO} cp -PR ${ROOT}/config/noobs/partition_setup.sh ${RELEASE_DIR}/${NOOBS_DISTRO} cp -PR ${ROOT}/config/noobs/partitions.json ${RELEASE_DIR}/${NOOBS_DISTRO} if [ -d ${DISTRO_DIR}/${DISTRO}/noobs/marketing ]; then tar cf ${RELEASE_DIR}/${NOOBS_DISTRO}/marketing.tar -C ${DISTRO_DIR}/${DISTRO}/noobs/marketing . else tar cf ${RELEASE_DIR}/${NOOBS_DISTRO}/marketing.tar -C ${ROOT}/config/noobs/marketing . fi cp ${ROOT}/README* ${RELEASE_DIR}/${NOOBS_DISTRO} cp ${ROOT}/CHANGELOG ${RELEASE_DIR}/${NOOBS_DISTRO}/release_notes.txt if [ -n "${NOOBS_HEX}" ]; then sed -e "s%@NOOBS_HEX@%${NOOBS_HEX}%g" \ -i ${RELEASE_DIR}/${NOOBS_DISTRO}/os.json else sed -e "/@NOOBS_HEX@/d" \ -i ${RELEASE_DIR}/${NOOBS_DISTRO}/os.json fi sed -e "s%@DISTRONAME@%${DISTRONAME}%g" \ -e "s%@PROJECT@%${DEVICE:-${PROJECT}}%g" \ -e "s%@DISTRO_VERSION@%${DISTRO_VERSION}%g" \ -e "s%@RELEASE_DATE@%$(date +%F)%g" \ -e "s%@KERNEL_VERSION@%$(kernel_version)%g" \ -e "s%@DESCRIPTION@%${DESCRIPTION}%g" \ -e "s%@ROOT_PASSWORD@%${ROOT_PASSWORD}%g" \ -e "s%@NOOBS_SUPPORTED_MODELS@%${NOOBS_SUPPORTED_MODELS}%g" \ -i ${RELEASE_DIR}/${NOOBS_DISTRO}/os.json sed -e "s%@DISTRONAME@%${DISTRONAME}%g" \ -e "s%@PROJECT@%${DEVICE:-${PROJECT}}%g" \ -e "s%@SYSTEM_SIZE@%${SYSTEM_SIZE}%g" \ -i ${RELEASE_DIR}/${NOOBS_DISTRO}/partitions.json sed -e "s%@EXTRA_CMDLINE@%${EXTRA_CMDLINE}%g" \ -i ${RELEASE_DIR}/${NOOBS_DISTRO}/partition_setup.sh # Create System dir mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO}/System # Copy Bootloader cp -PR ${INSTALL}/usr/share/bootloader/config.txt ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ for distro in "${INSTALL}/usr/share/bootloader/distroconfig"*.txt; do if [ -f "${distro}" ]; then cp -PR "${distro}" ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ fi done cp -PR ${INSTALL}/usr/share/bootloader/LICENCE* ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ for f in bootcode.bin fixup.dat start.elf; do if [ -f "${INSTALL}/usr/share/bootloader/$f" ]; then cp -PR "${INSTALL}/usr/share/bootloader/$f" "${RELEASE_DIR}/${NOOBS_DISTRO}/System/" fi done # Copy system files cp ${TARGET_IMG}/${IMAGE_NAME}.system ${RELEASE_DIR}/${NOOBS_DISTRO}/System/SYSTEM cp ${TARGET_IMG}/${IMAGE_NAME}.kernel ${RELEASE_DIR}/${NOOBS_DISTRO}/System/kernel.img for dtb in ${INSTALL}/usr/share/bootloader/*.dtb; do if [ -f ${dtb} ]; then cp -PR ${dtb} ${RELEASE_DIR}/${NOOBS_DISTRO}/System fi done for overlay in ${INSTALL}/usr/share/bootloader/overlays/*; do if [ -f ${overlay} ]; then mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO}/System/overlays cp -PR ${overlay} ${RELEASE_DIR}/${NOOBS_DISTRO}/System/overlays fi done # Create md5sum's ( cd ${RELEASE_DIR}/${NOOBS_DISTRO}/System md5sum -t SYSTEM >SYSTEM.md5 md5sum -t kernel.img >kernel.img.md5 ) # Copy additional files mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO}/System/licenses cp ${ROOT}/licenses/* ${RELEASE_DIR}/${NOOBS_DISTRO}/System/licenses # Create Storage dir mkdir -p ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage # Remove any previously created release tarball rm -rf ${RELEASE_DIR}/${NOOBS_DISTRO}/System.tar.xz rm -rf ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage.tar.xz # Create filesystem tarballs ${TOOLCHAIN}/bin/fakeroot tar cJf ${RELEASE_DIR}/${NOOBS_DISTRO}/System.tar.xz -C ${RELEASE_DIR}/${NOOBS_DISTRO}/System/ . ${TOOLCHAIN}/bin/fakeroot tar cJf ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage.tar.xz -C ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage/ . # Remove filesystem dirs rm -rf ${RELEASE_DIR}/${NOOBS_DISTRO}/System rm -rf ${RELEASE_DIR}/${NOOBS_DISTRO}/Storage # Remove any previously created release tarball rm -rf ${TARGET_IMG}/${IMAGE_NAME}-${1}.tar # Create release tarball tar cf ${TARGET_IMG}/${IMAGE_NAME}-${1}.tar -C ${TARGET_IMG} ${IMAGE_NAME}-${1} # Create sha256 checksum of tarball ( cd ${TARGET_IMG} sha256sum ${IMAGE_NAME}-${1}.tar >${IMAGE_NAME}-${1}.tar.sha256 ) fi if [ -d ${RELEASE_DIR} ]; then # Cleanup release dir rm -rf ${RELEASE_DIR} fi fi if [ -n "$(ls -1 ${BUILD}/qa_checks/ 2>/dev/null)" ]; then log_qa_check "qa_issues" "QA issues present, please fix!\n$(find ${BUILD}/qa_checks/* -type f ! -name qa_issues)\n" fi rm -f ${TARGET_IMG}/*.kernel rm -f ${TARGET_IMG}/*.system