am243x: add PRU-EQEP example #74
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # SPDX-License-Identifier: BSD-3-Clause | |
| # Copyright (C) 2026 Texas Instruments Incorporated - http://www.ti.com/ | |
| # | |
| # CCS Build CI — imports and builds all CCS projectspecs for each device. | |
| # Complements the make-based CI (makefile.yml) by verifying that projectspecs | |
| # can be imported, product path variables resolve correctly, postBuildStep | |
| # scripts (hexpru header generation) run successfully, and R5F projects can | |
| # find the generated firmware headers. | |
| # | |
| # Triggered only on files that affect CCS import or project build | |
| # configuration; source-only changes are already covered by makefile.yml. | |
| name: CCS Build | |
| on: | |
| pull_request: | |
| paths: | |
| - '**/example.projectspec' | |
| - '.metadata/**' | |
| - '**/linker.cmd' | |
| - '**/example.syscfg' | |
| - '**/makefile_ccs_bootimage_gen' | |
| push: | |
| branches: [ main, master ] | |
| paths: | |
| - '**/example.projectspec' | |
| - '.metadata/**' | |
| - '**/linker.cmd' | |
| - '**/example.syscfg' | |
| - '**/makefile_ccs_bootimage_gen' | |
| workflow_dispatch: | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| jobs: | |
| install-toolchain: | |
| # Installs CCS and shared compiler tools once and caches them. | |
| # MCU+ SDKs are intentionally omitted — each ccs-build job installs | |
| # only the SDK it needs, keeping the shared cache small. | |
| name: Install shared toolchain | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Install OS dependencies | |
| run: | | |
| sudo tee -a /etc/apt/sources.list >/dev/null <<'EOF' | |
| deb http://security.ubuntu.com/ubuntu focal-security main universe | |
| EOF | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| libx11-6 libxext6 libxrender1 libxtst6 libxi6 libxt6 libxinerama1 \ | |
| libgtk2.0-0 libncurses5 libnss3 python3-pip \ | |
| unzip xz-utils wget ca-certificates xvfb | |
| pip3 install pyserial xmodem tqdm pyelftools construct | |
| - name: Restore toolchain cache | |
| id: cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: | | |
| ~/ti/ccs_20.3.1 | |
| ~/ti/ti-cgt-pru_2.3.3 | |
| ~/ti/ti-cgt-armllvm_4.0.3.LTS | |
| ~/ti/sysconfig_1.27.0 | |
| key: toolchain-ccs-${{ runner.os }}-v5-ccs20_3_1-sysconfig1_27_0-pru2_3_3-armclang4_0_3 | |
| - name: Install CCS, SYSCONFIG, TIARMCLANG and PRU CGT if missing | |
| if: success() && steps.cache.outputs.cache-hit != 'true' | |
| run: | | |
| set -e | |
| mkdir -p "$HOME/ti/downloads" | |
| cd "$HOME/ti" | |
| # Install CCS 20.3.1 | |
| if [ ! -d "$HOME/ti/ccs_20.3.1" ]; then | |
| cd "$HOME/ti/downloads" | |
| wget -q --retry-connrefused --waitretry=1 --tries=5 --timeout=30 \ | |
| https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-J1VdearkvK/20.3.1/CCS_20.3.1.00005_linux.zip | |
| cd "$HOME/ti" | |
| unzip -t "$HOME/ti/downloads/CCS_20.3.1.00005_linux.zip" > /dev/null | |
| unzip -q "$HOME/ti/downloads/CCS_20.3.1.00005_linux.zip" | |
| cd CCS_20.3.1.00005_linux | |
| ./ccs_setup_20.3.1.00005.run --mode unattended --enable-components PF_ARM_MPU,PF_SITARA_MCU --prefix "$HOME/ti/ccs_20.3.1" | |
| fi | |
| # Install SYSCONFIG 1.27.0 | |
| if [ ! -d "$HOME/ti/ccs_20.3.1/ccs/utils/sysconfig_1.27.0" ] && [ ! -d "$HOME/ti/sysconfig_1.27.0" ]; then | |
| cd "$HOME/ti/downloads" | |
| wget -q --retry-connrefused --waitretry=1 --tries=5 --timeout=30 \ | |
| https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-nsUM6f7Vvb/1.27.0.4565/sysconfig-1.27.0_4565-setup.run | |
| chmod +x sysconfig-1.27.0_4565-setup.run | |
| ./sysconfig-1.27.0_4565-setup.run --mode unattended --prefix "$HOME/ti/sysconfig_1.27.0" | |
| chmod -R +x "$HOME/ti/sysconfig_1.27.0" | |
| fi | |
| # Install ARM CLANG CGT 4.0.3 | |
| if [ ! -d "$HOME/ti/ccs_20.3.1/ccs/tools/compiler/ti-cgt-armllvm_4.0.3.LTS" ] && [ ! -d "$HOME/ti/ti-cgt-armllvm_4.0.3.LTS" ]; then | |
| cd "$HOME/ti/downloads" | |
| wget -q --retry-connrefused --waitretry=1 --tries=5 --timeout=30 \ | |
| https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-ayxs93eZNN/4.0.3.LTS/ti_cgt_armllvm_4.0.3.LTS_linux-x64_installer.bin | |
| chmod +x ti_cgt_armllvm_4.0.3.LTS_linux-x64_installer.bin | |
| ./ti_cgt_armllvm_4.0.3.LTS_linux-x64_installer.bin --mode unattended --prefix "$HOME/ti/" | |
| fi | |
| # Install PRU CGT 2.3.3 | |
| if [ ! -d "$HOME/ti/ccs_20.3.1/ccs/tools/compiler/ti-cgt-pru_2.3.3" ] && [ ! -d "$HOME/ti/ti-cgt-pru_2.3.3" ]; then | |
| cd "$HOME/ti/downloads" | |
| wget -q --retry-connrefused --waitretry=1 --tries=5 --timeout=30 \ | |
| https://dr-download.ti.com/software-development/ide-configuration-compiler-or-debugger/MD-FaNNGkDH7s/2.3.3/ti_cgt_pru_2.3.3_linux_installer_x86.bin | |
| chmod +x ti_cgt_pru_2.3.3_linux_installer_x86.bin | |
| ./ti_cgt_pru_2.3.3_linux_installer_x86.bin --mode unattended --prefix "$HOME/ti" | |
| fi | |
| test -x "$HOME/ti/ti-cgt-armllvm_4.0.3.LTS/bin/tiarmclang" && \ | |
| "$HOME/ti/ti-cgt-armllvm_4.0.3.LTS/bin/tiarmclang" --version || \ | |
| ls -l "$HOME/ti/ti-cgt-armllvm_4.0.3.LTS" | |
| # Remove large temporaries — do NOT cache installer files or extracted zip | |
| rm -rf "$HOME/ti/downloads" | |
| rm -rf "$HOME/ti/CCS_20.3.1.00005_linux" | |
| # Strip bundled compilers for architectures not used by OpenPRU. | |
| # rm -rf is silent if directory is absent (e.g. already excluded by | |
| # --enable-components), so this is safe regardless of install flags. | |
| rm -rf "$HOME/ti/ccs_20.3.1"/ccs/tools/compiler/ti-cgt-c2000_* | |
| rm -rf "$HOME/ti/ccs_20.3.1"/ccs/tools/compiler/ti-cgt-c29_* | |
| rm -rf "$HOME/ti/ccs_20.3.1"/ccs/tools/compiler/ti-cgt-c6000_* | |
| rm -rf "$HOME/ti/ccs_20.3.1"/ccs/tools/compiler/ti-cgt-c7000_* | |
| rm -rf "$HOME/ti/ccs_20.3.1"/ccs/tools/compiler/ti-cgt-msp430_* | |
| # Strip Theia web IDE — not used by ccs-server-cli.sh headless mode | |
| rm -rf "$HOME/ti/ccs_20.3.1/ccs/theia" | |
| # Strip cloud agent and uninstallers — not needed in CI | |
| rm -rf "$HOME/ti/ccs_20.3.1/ccs/ccs_base/cloudagent" | |
| rm -rf "$HOME/ti/ccs_20.3.1/ccs/uninstallers" | |
| echo "=== Toolchain sizes after cleanup ===" | |
| du -sh "$HOME/ti/ccs_20.3.1" "$HOME/ti/ti-cgt-pru_2.3.3" \ | |
| "$HOME/ti/ti-cgt-armllvm_4.0.3.LTS" "$HOME/ti/sysconfig_1.27.0" 2>/dev/null || true | |
| - name: Save toolchain cache | |
| if: success() && steps.cache.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: | | |
| ~/ti/ccs_20.3.1 | |
| ~/ti/ti-cgt-pru_2.3.3 | |
| ~/ti/ti-cgt-armllvm_4.0.3.LTS | |
| ~/ti/sysconfig_1.27.0 | |
| key: toolchain-ccs-${{ runner.os }}-v5-ccs20_3_1-sysconfig1_27_0-pru2_3_3-armclang4_0_3 | |
| ccs-build: | |
| name: CCS Build (${{ matrix.device }}) | |
| needs: [install-toolchain] | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - device: am243x | |
| mcu_plus_sdk: mcu_plus_sdk_am243x_12_00_00_26 | |
| sdk_installer: mcu_plus_sdk_am243x_12_00_00_26-linux-x64-installer.run | |
| sdk_url: https://dr-download.ti.com/software-development/software-development-kit-sdk/MD-ouHbHEm1PK/12.00.00.26/mcu_plus_sdk_am243x_12_00_00_26-linux-x64-installer.run | |
| - device: am261x | |
| mcu_plus_sdk: mcu_plus_sdk_am261x_26_00_00_06 | |
| sdk_installer: mcu_plus_sdk_am261x_26_00_00_06-linux-x64-installer.run | |
| sdk_url: https://dr-download.ti.com/software-development/software-development-kit-sdk/MD-h64OlWnQrg/26.00.00.06.STS/mcu_plus_sdk_am261x_26_00_00_06-linux-x64-installer.run | |
| - device: am263px | |
| mcu_plus_sdk: mcu_plus_sdk_am263px_26_00_00_06 | |
| sdk_installer: mcu_plus_sdk_am263px_26_00_00_06-linux-x64-installer.run | |
| sdk_url: https://dr-download.ti.com/software-development/software-development-kit-sdk/MD-JVtW1V4WfA/26.00.00.06.STS/mcu_plus_sdk_am263px_26_00_00_06-linux-x64-installer.run | |
| - device: am263x | |
| mcu_plus_sdk: mcu_plus_sdk_am263x_26_00_00_06 | |
| sdk_installer: mcu_plus_sdk_am263x_26_00_00_06-linux-x64-installer.run | |
| sdk_url: https://dr-download.ti.com/software-development/software-development-kit-sdk/MD-r5FY9rRaGv/26.00.00.06.STS/mcu_plus_sdk_am263x_26_00_00_06-linux-x64-installer.run | |
| - device: am64x | |
| mcu_plus_sdk: mcu_plus_sdk_am64x_12_00_00_27 | |
| sdk_installer: mcu_plus_sdk_am64x_12_00_00_27-linux-x64-installer.run | |
| sdk_url: https://dr-download.ti.com/software-development/software-development-kit-sdk/MD-SfkcjYAjGS/12.00.00.27/mcu_plus_sdk_am64x_12_00_00_27-linux-x64-installer.run | |
| - device: am62x | |
| mcu_plus_sdk: "" | |
| sdk_installer: "" | |
| sdk_url: "" | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Install OS dependencies | |
| run: | | |
| sudo tee -a /etc/apt/sources.list >/dev/null <<'EOF' | |
| deb http://security.ubuntu.com/ubuntu focal-security main universe | |
| EOF | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| libx11-6 libxext6 libxrender1 libxtst6 libxi6 libxt6 libxinerama1 \ | |
| libgtk2.0-0 libncurses5 libnss3 python3-pip \ | |
| unzip xz-utils wget ca-certificates xvfb | |
| pip3 install pyserial xmodem tqdm pyelftools construct | |
| - name: Restore toolchain cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: | | |
| ~/ti/ccs_20.3.1 | |
| ~/ti/ti-cgt-pru_2.3.3 | |
| ~/ti/ti-cgt-armllvm_4.0.3.LTS | |
| ~/ti/sysconfig_1.27.0 | |
| key: toolchain-ccs-${{ runner.os }}-v5-ccs20_3_1-sysconfig1_27_0-pru2_3_3-armclang4_0_3 | |
| fail-on-cache-miss: true | |
| - name: Install device MCU+ SDK | |
| if: matrix.mcu_plus_sdk != '' | |
| run: | | |
| set -e | |
| mkdir -p "$HOME/ti/downloads" | |
| cd "$HOME/ti/downloads" | |
| wget -q --retry-connrefused --waitretry=1 --tries=5 --timeout=30 \ | |
| "${{ matrix.sdk_url }}" | |
| chmod +x "${{ matrix.sdk_installer }}" | |
| "./${{ matrix.sdk_installer }}" --mode unattended --prefix "$HOME/ti/" | |
| - name: Generate imports.mak for CI | |
| # imports.mak is gitignored (developer-configured). CCS R5F post-build steps | |
| # invoke makefile_ccs_bootimage_gen, which unconditionally includes | |
| # $(OPEN_PRU_PATH)/imports.mak before any ifeq guard. Without this file the | |
| # include fails and CCS counts the project as having errors. | |
| # override CCS_IDE_MODE := cloud ensures the ifeq($(CCS_IDE_MODE),cloud) | |
| # guard in makefile_ccs_bootimage_gen skips boot-image generation even when | |
| # CCS headless passes CCS_IDE_MODE= (empty) on the command line. | |
| # Boot image generation is not needed for compilation CI. | |
| run: | | |
| cat > imports.mak << 'EOF' | |
| # Auto-generated by ccs_build.yml — do not edit. | |
| # Provides Linux utility variables for makefile_ccs_bootimage_gen. | |
| # override beats command-line CCS_IDE_MODE= so post-build is skipped. | |
| override CCS_IDE_MODE := cloud | |
| DEVICE_TYPE ?= GP | |
| ENC_ENABLED ?= no | |
| export MKDIR := mkdir -p | |
| export RMDIR := rm -rf | |
| export RM := rm -f | |
| export COPY := cp | |
| export MOVE := mv | |
| export CAT := cat | |
| export SED := sed | |
| export TOUCH := touch | |
| export PATHSEP := / | |
| export CHMOD := chmod | |
| CCS_NODE = $(CCS_PATH)/tools/node/node | |
| EOF | |
| - name: Patch metadata for SysConfig version | |
| # Temporarily encodes the SysConfig version into OpenPRU's package.tirex.json | |
| # and product.json so CCS selects the correct SysConfig version when | |
| # initializing the workspace. See test_ccs_import.sh for background. | |
| # No backup/restore needed — CI workspace is ephemeral. | |
| run: | | |
| SYSCFG_VERSION="1.27.0" | |
| OPENPRU_VERSION="1.${SYSCFG_VERSION}" | |
| sed -i "s/^ \"version\": \"[^\"]*\"/ \"version\": \"${OPENPRU_VERSION}\"/" \ | |
| .metadata/.tirex/package.tirex.json | |
| sed -i "/\"packageId\": \"sysconfig\"/s/\"version\": \"[^\"]*\"/\"version\": \"${SYSCFG_VERSION}\"/" \ | |
| .metadata/.tirex/package.tirex.json | |
| sed -i "s/\"minToolVersion\" : \"[^\"]*\"/\"minToolVersion\" : \"${SYSCFG_VERSION}\"/" \ | |
| .metadata/product.json | |
| - name: Start Xvfb | |
| run: | | |
| Xvfb :99 -screen 0 1024x768x24 & | |
| echo "DISPLAY=:99" >> $GITHUB_ENV | |
| - name: Initialize CCS workspace | |
| run: | | |
| set -eo pipefail | |
| DEVICE="${{ matrix.device }}" | |
| WORKSPACE="${HOME}/workspace_ccs_${DEVICE}" | |
| CCS_CLI="$HOME/ti/ccs_20.3.1/ccs/eclipse/ccs-server-cli.sh" | |
| PRODUCT_PATHS="${GITHUB_WORKSPACE};$HOME/ti/sysconfig_1.27.0" | |
| if [ -d "$HOME/ti/ccs_20.3.1/ccs/utils/sysconfig_1.27.0" ]; then | |
| PRODUCT_PATHS="${GITHUB_WORKSPACE};$HOME/ti/ccs_20.3.1/ccs/utils/sysconfig_1.27.0" | |
| fi | |
| if [ -n "${{ matrix.mcu_plus_sdk }}" ]; then | |
| PRODUCT_PATHS="${PRODUCT_PATHS};$HOME/ti/${{ matrix.mcu_plus_sdk }}" | |
| fi | |
| # PRU CGT: prefer the copy bundled inside CCS, fall back to standalone | |
| PRU_CGT_PATH="$HOME/ti/ccs_20.3.1/ccs/tools/compiler/ti-cgt-pru_2.3.3" | |
| [ -d "${PRU_CGT_PATH}" ] || PRU_CGT_PATH="$HOME/ti/ti-cgt-pru_2.3.3" | |
| mkdir -p "${WORKSPACE}" | |
| "${CCS_CLI}" -noSplash \ | |
| -workspace "${WORKSPACE}" \ | |
| -application com.ti.ccs.apps.initialize \ | |
| -ccs.productDiscoveryPath "${PRODUCT_PATHS}" \ | |
| -ccs.toolDiscoveryPath "${PRU_CGT_PATH}" \ | |
| 2>&1 | tee workspace_init.log | |
| INIT_EXIT="${PIPESTATUS[0]}" | |
| if [ "${INIT_EXIT}" -ne 0 ]; then | |
| echo "ERROR: CCS workspace initialization failed (exit=${INIT_EXIT})" | |
| exit 1 | |
| fi | |
| - name: Import all projectspecs | |
| run: | | |
| DEVICE="${{ matrix.device }}" | |
| WORKSPACE="${HOME}/workspace_ccs_${DEVICE}" | |
| CCS_CLI="$HOME/ti/ccs_20.3.1/ccs/eclipse/ccs-server-cli.sh" | |
| mapfile -t SPECS < <(find . -name "example.projectspec" | grep "/${DEVICE}-" | sort) | |
| echo "Found ${#SPECS[@]} projectspecs for ${DEVICE}" | |
| CMD=("${CCS_CLI}" -noSplash | |
| -workspace "${WORKSPACE}" | |
| -application com.ti.ccs.apps.importProject) | |
| for spec in "${SPECS[@]}"; do CMD+=(-ccs.location "${spec}"); done | |
| "${CMD[@]}" 2>&1 | tee import.log | |
| IMPORT_EXIT="${PIPESTATUS[0]}" | |
| # CCS may exit 0 even when individual imports fail; check log as well. | |
| ERRORS=$(grep -c '!ERROR:' import.log || true) | |
| if [ "${IMPORT_EXIT}" -ne 0 ] || [ "${ERRORS}" -gt 0 ]; then | |
| echo "ERROR: CCS import failed (exit=${IMPORT_EXIT}, errors=${ERRORS})" | |
| exit 1 | |
| fi | |
| - name: Build pass 1 — PRU firmware (ti-pru-cgt) | |
| # All PRU projects are built first so that hexpru postBuildStep headers | |
| # are written to the workspace before any R5F project tries to include them. | |
| run: | | |
| DEVICE="${{ matrix.device }}" | |
| WORKSPACE="${HOME}/workspace_ccs_${DEVICE}" | |
| CCS_CLI="$HOME/ti/ccs_20.3.1/ccs/eclipse/ccs-server-cli.sh" | |
| mapfile -t SPECS < <(find . -name "example.projectspec" | grep "/${DEVICE}-" | sort) | |
| mapfile -t PRU_SPECS < <(printf '%s\n' "${SPECS[@]}" | grep '/ti-pru-cgt/') | |
| if [ "${#PRU_SPECS[@]}" -gt 0 ]; then | |
| PRU_CMD=("${CCS_CLI}" -noSplash | |
| -workspace "${WORKSPACE}" | |
| -application com.ti.ccs.apps.buildProject | |
| -ccs.configuration Release | |
| -ccs.projects) | |
| for spec in "${PRU_SPECS[@]}"; do | |
| PRU_CMD+=("$(grep -oP '(?<=name = ")[^"]+' "${spec}" | head -1)") | |
| done | |
| "${PRU_CMD[@]}" 2>&1 | tee build_pru.log || true | |
| else | |
| echo "No ti-pru-cgt projects found for ${DEVICE}, skipping PRU build pass" | |
| fi | |
| - name: Build pass 2 — R5F/ARM (ti-arm-clang) | |
| run: | | |
| DEVICE="${{ matrix.device }}" | |
| WORKSPACE="${HOME}/workspace_ccs_${DEVICE}" | |
| CCS_CLI="$HOME/ti/ccs_20.3.1/ccs/eclipse/ccs-server-cli.sh" | |
| mapfile -t SPECS < <(find . -name "example.projectspec" | grep "/${DEVICE}-" | sort) | |
| mapfile -t R5F_SPECS < <(printf '%s\n' "${SPECS[@]}" | grep -v '/ti-pru-cgt/') | |
| if [ "${#R5F_SPECS[@]}" -gt 0 ]; then | |
| R5F_CMD=("${CCS_CLI}" -noSplash | |
| -workspace "${WORKSPACE}" | |
| -application com.ti.ccs.apps.buildProject | |
| -ccs.configuration Release | |
| -ccs.projects) | |
| for spec in "${R5F_SPECS[@]}"; do | |
| R5F_CMD+=("$(grep -oP '(?<=name = ")[^"]+' "${spec}" | head -1)") | |
| done | |
| "${R5F_CMD[@]}" 2>&1 | tee build_r5f.log || true | |
| else | |
| echo "No ti-arm-clang projects found for ${DEVICE}, skipping R5F build pass" | |
| fi | |
| - name: Check build results | |
| run: | | |
| DEVICE="${{ matrix.device }}" | |
| # Recompute expected project counts (same find as build steps). | |
| mapfile -t SPECS < <(find . -name "example.projectspec" | grep "/${DEVICE}-" | sort) | |
| mapfile -t PRU_SPECS < <(printf '%s\n' "${SPECS[@]}" | grep '/ti-pru-cgt/') | |
| mapfile -t R5F_SPECS < <(printf '%s\n' "${SPECS[@]}" | grep -v '/ti-pru-cgt/') | |
| declare -A EXPECTED_COUNT | |
| EXPECTED_COUNT[build_pru.log]="${#PRU_SPECS[@]}" | |
| EXPECTED_COUNT[build_r5f.log]="${#R5F_SPECS[@]}" | |
| TOTAL_ERRORS=0 | |
| BUILD_OK=true | |
| for logfile in build_pru.log build_r5f.log; do | |
| [ -f "${logfile}" ] || continue | |
| # Primary: parse "N out of M projects have errors" summary lines. | |
| E=$(grep -oP '\d+(?= out of \d+ projects have errors)' "${logfile}" | \ | |
| awk '{s+=$1} END{print s+0}') | |
| # Secondary: sum per-project error counts from "# Problem summary" | |
| # lines. Catches failures if the overall summary line is absent. | |
| P=$(grep '# Problem summary' "${logfile}" | \ | |
| grep -oP '\d+(?= errors)' | awk '{s+=$1} END{print s+0}') | |
| [ "${P}" -gt "${E}" ] && E="${P}" | |
| # Tertiary: catch Eclipse "project not open" race — these do not | |
| # always appear in the Problem summary count. | |
| NOT_OPEN=$(grep -c 'is not open' "${logfile}" || true) | |
| if [ "${NOT_OPEN}" -gt 0 ]; then | |
| echo "ERROR: ${NOT_OPEN} 'project not open' error(s) in ${logfile}:" | |
| grep 'is not open' "${logfile}" || true | |
| fi | |
| E=$((E + NOT_OPEN)) | |
| TOTAL_ERRORS=$((TOTAL_ERRORS + E)) | |
| if ! grep -q 'headless build complete' "${logfile}"; then | |
| echo "ERROR: no 'headless build complete' line in ${logfile}" | |
| BUILD_OK=false | |
| fi | |
| # Verify CCS built every project that was found on disk. | |
| EXPECTED="${EXPECTED_COUNT[${logfile}]}" | |
| BUILT=$(grep -oP '(?<=out of )\d+(?= projects have errors)' "${logfile}" | head -1) | |
| BUILT="${BUILT:-0}" | |
| if [ "${EXPECTED}" -gt 0 ] && [ "${BUILT}" -ne "${EXPECTED}" ]; then | |
| echo "ERROR: ${logfile}: expected ${EXPECTED} projects, CCS built ${BUILT}" | |
| BUILD_OK=false | |
| fi | |
| done | |
| if [ "${TOTAL_ERRORS}" -gt 0 ]; then | |
| echo "ERROR: ${TOTAL_ERRORS} build error(s) detected" | |
| BUILD_OK=false | |
| fi | |
| if [ "${BUILD_OK}" != "true" ]; then | |
| exit 1 | |
| fi | |
| echo "CCS build passed for ${{ matrix.device }}" | |
| - name: Upload logs | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ccs-logs-${{ matrix.device }} | |
| path: | | |
| workspace_init.log | |
| import.log | |
| build_pru.log | |
| build_r5f.log | |
| if-no-files-found: ignore |