#!/bin/bash #=============================================================================== # # build.sh # # Copyright (C) 2013-2025 by Digi International Inc. # All rights reserved. # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License version 2 as published by # the Free Software Foundation. # # # !Description: Yocto autobuild script from Jenkins. # # Parameters set by Jenkins: # DY_BUILD_RELEASE: Build for release mode # DY_BUILD_TCHAIN: Build toolchain for DEY images # DY_DISTRO: Distribution name (the default is 'dey') # DY_PLATFORMS: Platforms to build # DY_REVISION: Revision of the manifest repository (for 'repo init') # DY_RM_WORK: Remove the package working folders to save disk space. # DY_TARGET: Target image (the default is platform dependent) # DY_USE_MIRROR: Use internal Digi mirror to download packages # DY_CVE_REPORT: Generate Vigiles CVE report # DY_VIGILES_DIR: Path to Vigiles configuration files on the build server # DY_USE_CVE_LAYER: Apply meta-digi-security layer with CVE fixes # DY_MANIFEST: Use specific manifest file (none by default) # #=============================================================================== set -e MANIFEST_URL="ssh://git@stash.digi.com/dey/digi-yocto-sdk-manifest.git" DIGI_PREMIRROR_CFG=" # Use internal mirror SOURCE_MIRROR_URL = \"http://log-sln-jenkins.digi.com/yocto/downloads/\" INHERIT += \"own-mirrors\" BB_GENERATE_MIRROR_TARBALLS = \"1\" " RM_WORK_CFG=" INHERIT += \"rm_work\" # Exclude rm_work for some key packages (for debugging purposes) RM_WORK_EXCLUDE += \"dey-image-qt dey-image-webkit linux-dey qtbase u-boot-dey\" " VIGILES_CFG=" unset do_vigiles_check[noexec] VIGILES_KEY_FILE = \"${DY_VIGILES_DIR}/linuxlink_key.json\" VIGILES_DASHBOARD_CONFIG = \"##VIGILES_CONF_PATH##\" VIGILES_SUBFOLDER_NAME = \"${DY_REVISION}\" INHERIT += \"##VIGILES_BBCLASS##\" " SDCARD_FSTYPE=" IMAGE_FSTYPES:append:ccimx6 = \" wic.bmap wic.gz\" IMAGE_FSTYPES:append:ccimx8x = \" wic.bmap wic.gz\" IMAGE_FSTYPES:append:ccimx8m = \" wic.bmap wic.gz\" IMAGE_FSTYPES:append:ccimx9 = \" wic.bmap wic.gz\" " SOURCE_DATE_EPOCH="${SOURCE_DATE_EPOCH:-$(date +%s)}" BUILD_TIMESTAMP=" SOURCE_DATE_EPOCH = \"${SOURCE_DATE_EPOCH}\" REPRODUCIBLE_TIMESTAMP_ROOTFS = \"${SOURCE_DATE_EPOCH}\" " REPO="$(which repo)" error() { printf "%s" "${1}" exit 1 } # # Copy buildresults (images, licenses, packages) # # $1: destination directoy # copy_images() { # Copy individual packages only for 'release' builds, not for 'daily'. # For 'daily' builds just copy the firmware images (the buildserver # cannot afford such amount of disk space) if [ "${DY_BUILD_RELEASE}" = "true" ]; then cp -r tmp/deploy/* "${1}"/ else cp -r tmp/deploy/images "${1}"/ if [ "${DY_BUILD_TCHAIN}" = "true" ]; then if [ -d tmp/deploy/sdk ]; then cp -r tmp/deploy/sdk "${1}"/ fi fi fi # Images directory post-processing # - Jenkins artifact archiver does not copy symlinks, so remove them # beforehand to avoid ending up with several duplicates of the same # files. # - Remove 'README_-_DO_NOT_DELETE_FILES_IN_THIS_DIRECTORY.txt' files # - Create MD5SUMS file find "${1}" -type l -delete find "${1}" -type f -name 'README_-_DO_NOT_DELETE*' -delete find "${1}" -type f -not -name MD5SUMS -print0 | xargs -r -0 md5sum | sed -e "s,${1}/,,g" | sort -k2,2 > "${1}"/MD5SUMS } # # For a given image recipe print the SWU recipe (if it exists) # # $1: image recipe # swu_recipe_name() { if [ -n "$(find "${YOCTO_INST_DIR}"/sources/meta-digi -type f -name "${1}-swu.bb")" ]; then printf "%s-swu" "${1}" fi } # Sanity check (Jenkins environment) [ -z "${DY_REVISION}" ] && error "DY_REVISION not specified" [ -z "${DY_RM_WORK}" ] && error "DY_RM_WORK not specified" [ -z "${DY_USE_MIRROR}" ] && error "DY_USE_MIRROR not specified" [ -z "${WORKSPACE}" ] && error "WORKSPACE not specified" # Set default settings if Jenkins does not do it [ -z "${DY_DISTRO}" ] && DY_DISTRO="dey" [ -z "${DY_BUILD_RELEASE}" ] && [[ "${JOB_NAME}" =~ dey-.*-release ]] && DY_BUILD_RELEASE="true" # If DY_BUILD_TCHAIN is unset, set it for release jobs [ -z "${DY_BUILD_TCHAIN}" ] && [ "${DY_BUILD_RELEASE}" = "true" ] && DY_BUILD_TCHAIN="true" # If DY_MFG_IMAGE is unset, set it depending on the job name if [ -z "${DY_MFG_IMAGE}" ] && echo "${JOB_NAME}" | grep -qs 'dey.*mfg'; then DY_MFG_IMAGE="true" fi [ -z "${DY_CVE_REPORT}" ] && DY_CVE_REPORT="false" [ -z "${DY_USE_CVE_LAYER}" ] && DY_USE_CVE_LAYER="false" [ "${DY_CVE_REPORT}" = "true" ] && [ -z "${DY_VIGILES_DIR}" ] && error "DY_VIGILES_DIR not specified" [ "${DY_CVE_REPORT}" = "true" ] && [ -z "${DY_CODENAME}" ] && error "DY_CODENAME not specified" # Per-platform data while read -r _pl _tgt; do AVAILABLE_PLATFORMS="${AVAILABLE_PLATFORMS:+${AVAILABLE_PLATFORMS} }${_pl}" # shellcheck disable=SC2015 [ -n "${DY_TARGET}" ] && _tgt="${DY_TARGET}" || true # Dashes are not allowed in variables so let's substitute them on # the fly with underscores. eval "${_pl//-/_}_tgt=\"${_tgt//,/ }\"" done<<-_EOF_ ccimx8mm-dvk dey-image-qt,dey-image-webkit,dey-image-lvgl,dey-image-flutter ccimx8mn-dvk dey-image-qt,dey-image-webkit,dey-image-lvgl,dey-image-flutter ccimx8x-sbc-pro dey-image-qt,dey-image-webkit,dey-image-lvgl,dey-image-flutter ccimx8x-sbc-express dey-image-qt ccimx6qpsbc dey-image-qt,dey-image-webkit,dey-image-lvgl ccimx6sbc dey-image-qt,dey-image-webkit,dey-image-lvgl ccimx6ulsbc core-image-base,dey-image-qt,dey-image-lvgl ccimx6ulstarter core-image-base ccimx6ulsom dey-image-mft-module-min ccimx6ulrftest dey-image-mft-module-rf ccmp15-dvk dey-image-qt,dey-image-webkit,dey-image-lvgl,dey-image-flutter ccmp13-dvk core-image-base ccmp25-dvk dey-image-qt,dey-image-webkit,dey-image-lvgl,dey-image-flutter ccimx91-dvk core-image-base ccimx93-dvk dey-image-qt,dey-image-lvgl ccimx95-dvk dey-image-qt,dey-image-chromium,dey-image-lvgl,dey-image-flutter _EOF_ # Set default values if not provided by Jenkins DY_PLATFORMS="${DY_PLATFORMS:-${AVAILABLE_PLATFORMS}}" YOCTO_IMGS_DIR="${WORKSPACE}/images" YOCTO_INST_DIR="${WORKSPACE}/digi-yocto-sdk.$(echo "${DY_REVISION}" | tr '/' '_')" YOCTO_DOWNLOAD_DIR="${DY_DOWNLOADS:-${WORKSPACE}}/downloads" YOCTO_PROJ_DIR="${WORKSPACE}/projects" YOCTO_SSTATE_DIR="${DY_SSTATE:-${YOCTO_PROJ_DIR}/sstate-cache}" # If CPUS is unset, set it with the machine cpus if [ -z "${CPUS}" ]; then CPUS="$(grep -c processor /proc/cpuinfo)" fi [ "${CPUS}" -gt 1 ] && MAKE_JOBS="-j${CPUS}" printf "\n[INFO] Build Yocto \"%s\" for \"%s\" (cpus=%s)\n\n" "${DY_REVISION}" "${DY_PLATFORMS}" "${CPUS}" # Install/Update Digi's Yocto SDK if [ "${DY_BUILD_RELEASE}" = "true" ]; then # Start a build release environment from scratch rm -rf "${YOCTO_INST_DIR}" fi mkdir -p "${YOCTO_INST_DIR}" if pushd "${YOCTO_INST_DIR}"; then # Use git ls-remote to check the revision type if [ "${DY_REVISION}" != "master" ]; then if git ls-remote --tags --exit-code "${MANIFEST_URL}" "${DY_REVISION}"; then printf "[INFO] Using tag \"%s\"\n" "${DY_REVISION}" repo_revision="-b refs/tags/${DY_REVISION}" elif git ls-remote --heads --exit-code "${MANIFEST_URL}" "${DY_REVISION}"; then printf "[INFO] Using branch \"%s\"\n" "${DY_REVISION}" repo_revision="-b ${DY_REVISION}" else error "Revision \"${DY_REVISION}\" not found" fi fi # shellcheck disable=SC2086 yes "" 2>/dev/null | ${REPO} init --depth=1 --no-repo-verify -u ${MANIFEST_URL} ${repo_revision} ${DY_MANIFEST:+-m ${DY_MANIFEST}} ${REPO} --no-pager forall --ignore-missing -j4 -p -c 'git clean -fdx' # shellcheck disable=SC2016 ${REPO} --no-pager forall --ignore-missing -j4 -p -c 'git remote prune $(git remote)' || true # shellcheck disable=SC2086 time ${REPO} sync -d ${MAKE_JOBS} popd fi # Clean downloads directory if [ "${DY_RM_DOWNLOADS}" = "true" ]; then printf "\n[INFO] Removing the downloads folder.\n" rm -rf "${YOCTO_DOWNLOAD_DIR}" fi # Clean images and projects folders rm -rf "${YOCTO_IMGS_DIR}" "${YOCTO_PROJ_DIR}" # Create projects and build for platform in ${DY_PLATFORMS}; do # The variable _tgt got its dashes converted to # underscores, so we must convert also the ones in ${platform}. eval "platform_targets=\"\${${platform//-/_}_tgt}\"" _this_prj_dir="${YOCTO_PROJ_DIR}/${platform}" _this_img_dir="${YOCTO_IMGS_DIR}/${platform}" mkdir -p "${_this_img_dir}" "${_this_prj_dir}" if pushd "${_this_prj_dir}"; then # Configure and build the project in a sub-shell to avoid # mixing environments between different platform's projects ( export TEMPLATECONF="${TEMPLATECONF:+${TEMPLATECONF}/${platform}}" # shellcheck disable=SC1091,SC2086 MKP_PAGER="" . ${YOCTO_INST_DIR}/mkproject.sh -p "${platform}" ${DY_MACHINES_LAYER:+-m ${DY_MACHINES_LAYER}} <<< "y" # Set a common DL_DIR and SSTATE_DIR for all platforms sed -i -e "/^#DL_DIR ?=/cDL_DIR ?= \"${YOCTO_DOWNLOAD_DIR}\"" \ -e "/^#SSTATE_DIR ?=/cSSTATE_DIR ?= \"${YOCTO_SSTATE_DIR}\"" \ conf/local.conf # Set the DISTRO and remove 'meta-digi-dey' layer if distro is not DEY based sed -i -e "/^DISTRO ?=/cDISTRO ?= \"${DY_DISTRO}\"" conf/local.conf if ! echo "${DY_DISTRO}" | grep -qs "dey"; then sed -i -e '/meta-digi-dey/d' conf/bblayers.conf fi if [ "${DY_USE_MIRROR}" = "true" ]; then sed -i -e "s,^#DIGI_INTERNAL_GIT,DIGI_INTERNAL_GIT,g" conf/local.conf printf "%s" "${DIGI_PREMIRROR_CFG}" >> conf/local.conf fi if [ "${DY_RM_WORK}" = "true" ]; then printf "%s" "${RM_WORK_CFG}" >> conf/local.conf fi printf "%s" "${SDCARD_FSTYPE}" >> conf/local.conf # Append extra configuration macros if provided from build environment if [ -n "${DY_EXTRA_LOCAL_CONF}" ]; then printf "%s\n" "${DY_EXTRA_LOCAL_CONF}" >> conf/local.conf fi # Add build timestamp if [ -n "${BUILD_TIMESTAMP}" ]; then printf "%s" "${BUILD_TIMESTAMP}" >> conf/local.conf fi # Check if it is a manufacturing job and, if the mfg layer is not there, add it if [ "${DY_MFG_IMAGE}" = "true" ] && ! grep -qs "meta-digi-mfg" conf/bblayers.conf; then sed -i -e "/meta-digi-dey/a\ ${YOCTO_INST_DIR}/sources/meta-digi-mfg \\\\" conf/bblayers.conf fi # Apply CVE layer if needed (do so before potentially inheriting "digi_ccss" to avoid errors) [ "${DY_USE_CVE_LAYER}" = "true" ] && bitbake-layers add-layer "${YOCTO_INST_DIR}"/sources/meta-digi-security # If we want to generate a CVE report, update conf/local.conf if [ "${DY_CVE_REPORT}" = "true" ]; then # Build Vigiles config path using platform and patch status status="non-patched" bbclass="vigiles" [ "${DY_USE_CVE_LAYER}" = "true" ] && { status="patched"; bbclass="digi_ccss"; } VIGILES_CONF_PATH="${DY_VIGILES_DIR}/configs/${DY_CODENAME}/${platform}_${status}_config" # Return error if config file doesn't exist [ ! -f "${VIGILES_CONF_PATH}" ] && error "Cannot find Vigiles config file ${VIGILES_CONF_PATH}" printf "%s" "${VIGILES_CFG}" | sed -e "s,##VIGILES_CONF_PATH##,${VIGILES_CONF_PATH},g" -e "s,##VIGILES_BBCLASS##,${bbclass},g" >> conf/local.conf fi printf "\n[INFO] Show customized local.conf.\n" cat conf/local.conf for target in ${platform_targets:?}; do printf "\n[INFO] Building the %s target.\n" "${target}" # shellcheck disable=SC2046 time bitbake "${target}" $(swu_recipe_name "${target}") done # Build the toolchain for DEY images if [ "${DY_BUILD_TCHAIN}" = "true" ]; then printf "\n[INFO] Building the toolchain for %s.\n" "${platform}" time bitbake -c populate_sdk dey-toolchain fi ) copy_images "${_this_img_dir}" popd fi done