| version: 2.1 |
| |
| commands: |
| setup-toolchain: |
| parameters: |
| toolchain: |
| type: string |
| |
| steps: |
| - run: |
| name: Set toolchain url and key |
| command: | |
| toolchain_url=$(jq -r '."<< parameters.toolchain >>"' .github/actions/setup_toolchain/toolchain.json) |
| # only cache if not a github link |
| if [[ $toolchain_url != "https://github.com"* ]]; then |
| echo "<< parameters.toolchain >>-$toolchain_url" > toolchain_key |
| fi |
| echo "export toolchain_url=$toolchain_url" >> $BASH_ENV |
| |
| - restore_cache: |
| name: Restore Toolchain Cache |
| key: deps-{{ checksum "toolchain_key" }} |
| paths: |
| - ~/cache/<< parameters.toolchain >> |
| |
| - run: |
| name: Install Toolchain |
| command: | |
| # download if folder does not exist (not cached) |
| if [ ! -d ~/cache/<< parameters.toolchain >> ]; then |
| mkdir -p ~/cache/<< parameters.toolchain >> |
| if [[ << parameters.toolchain >> == rx-gcc ]]; then |
| wget --progress=dot:giga $toolchain_url -O toolchain.run |
| chmod +x toolchain.run |
| ./toolchain.run -p ~/cache/<< parameters.toolchain >>/gnurx -y |
| elif [[ << parameters.toolchain >> == ft9xx-gcc ]]; then |
| wget --progress=dot:giga $toolchain_url -O ~/cache/<< parameters.toolchain >>/ft9xxtoolchain.deb |
| elif [[ << parameters.toolchain >> == arm-iar ]]; then |
| wget --progress=dot:giga https://netstorage.iar.com/FileStore/STANDARD/001/003/926/iar-lmsc-tools_1.8_amd64.deb -O ~/cache/<< parameters.toolchain >>/iar-lmsc-tools.deb |
| wget --progress=dot:giga $toolchain_url -O ~/cache/<< parameters.toolchain >>/toolchain.deb |
| else |
| wget --progress=dot:giga $toolchain_url -O toolchain.tar.gz |
| tar -C ~/cache/<< parameters.toolchain >> -xaf toolchain.tar.gz |
| fi |
| fi |
| |
| # Add toolchain to PATH |
| if [[ << parameters.toolchain >> == arm-iar ]]; then |
| # Install IAR since we only cache deb file |
| sudo dpkg -i ~/cache/<< parameters.toolchain >>/iar-lmsc-tools.deb |
| sudo dpkg --ignore-depends=libusb-1.0-0 -i ~/cache/<< parameters.toolchain >>/toolchain.deb |
| echo "export PATH=$PATH:/opt/iar/cxarm/arm/bin" >> $BASH_ENV |
| elif [[ << parameters.toolchain >> == ft9xx-gcc ]]; then |
| sudo apt install -y ~/cache/<< parameters.toolchain >>/ft9xxtoolchain.deb |
| echo "export PATH=$PATH:/opt/ft32/bin" >> $BASH_ENV |
| else |
| echo "export PATH=$PATH:`echo ~/cache/<< parameters.toolchain >>/*/bin`" >> $BASH_ENV |
| fi |
| |
| - save_cache: |
| name: Save Toolchain Cache |
| key: deps-{{ checksum "toolchain_key" }} |
| paths: |
| - ~/cache/<< parameters.toolchain >> |
| |
| build: |
| parameters: |
| build-system: |
| type: string |
| toolchain: |
| type: string |
| family: |
| type: string |
| build-args: |
| type: string |
| default: "" |
| |
| steps: |
| - checkout |
| - run: |
| name: Get Dependencies |
| command: | |
| python tools/get_deps.py << parameters.family >> |
| |
| # Install ninja if cmake build system |
| if [ << parameters.build-system >> == "cmake" ]; then |
| NINJA_URL=https://github.com/ninja-build/ninja/releases/download/v1.12.1/ninja-linux.zip |
| wget $NINJA_URL -O ninja-linux.zip |
| unzip ninja-linux.zip -d ~/bin |
| fi |
| |
| # rx-gcc is 32-bit binary |
| if [[ << parameters.toolchain >> == rx-gcc ]]; then |
| sudo dpkg --add-architecture i386 |
| sudo apt update |
| sudo apt install libc6:i386 libstdc++6:i386 zlib1g:i386 |
| fi |
| |
| # Install Pico SDK |
| if [ << parameters.family >> == "rp2040" ]; then |
| git clone --depth 1 https://github.com/raspberrypi/pico-sdk.git ~/pico-sdk |
| echo "export PICO_SDK_PATH=~/pico-sdk" >> $BASH_ENV |
| fi |
| |
| - when: |
| condition: |
| not: |
| equal: [esp-idf, << parameters.toolchain >>] |
| steps: |
| - setup-toolchain: |
| toolchain: << parameters.toolchain >> |
| |
| - run: |
| name: Build |
| no_output_timeout: 20m |
| command: | |
| if [ << parameters.toolchain >> == esp-idf ]; then |
| docker run --rm -v $PWD:/project -w /project espressif/idf:v5.5.3 python tools/build.py << parameters.build-args >> --target all << parameters.family >> |
| else |
| # Toolchain option default is gcc |
| if [ << parameters.toolchain >> == arm-clang ]; then |
| TOOLCHAIN_OPTION="--toolchain clang" |
| elif [ << parameters.toolchain >> == arm-iar ]; then |
| TOOLCHAIN_OPTION="--toolchain iar" |
| iccarm --version |
| elif [ << parameters.toolchain >> == arm-gcc ]; then |
| TOOLCHAIN_OPTION="--toolchain gcc" |
| fi |
| |
| # circleci docker return $nproc as 36 core, limit parallel to 4 (resource-class = large) |
| # Required for IAR, also prevent crashed/killed by docker |
| BUILD_PY_ARGS="-s << parameters.build-system >> $TOOLCHAIN_OPTION -j 4 << parameters.build-args >> --target all" |
| if [ << parameters.build-system >> == "cmake" ]; then |
| BUILD_PY_ARGS="$BUILD_PY_ARGS --target tinyusb_metrics" |
| fi |
| python tools/build.py $BUILD_PY_ARGS << parameters.family >> |
| fi |
| |
| # Only collect and persist metrics for cmake builds (excluding esp-idf and --one-random) |
| - when: |
| condition: |
| and: |
| - equal: [ cmake, << parameters.build-system >> ] |
| - not: |
| equal: [ esp-idf, << parameters.toolchain >> ] |
| - not: |
| equal: [ arm-iar, << parameters.toolchain >> ] |
| steps: |
| - run: |
| name: Collect Metrics |
| command: | |
| # Create unique directory per toolchain to avoid workspace conflicts |
| METRICS_DIR="/tmp/metrics/<< parameters.toolchain >>" |
| mkdir -p "${METRICS_DIR}" |
| # Copy all metrics.json files |
| for f in cmake-build/cmake-build-*/metrics.json; do |
| if [ -f "$f" ]; then |
| BOARD_DIR=$(dirname "$f" | xargs basename) |
| cp "$f" "${METRICS_DIR}/${BOARD_DIR}.json" |
| fi |
| done |
| |
| - persist_to_workspace: |
| root: /tmp |
| paths: |
| - metrics/<< parameters.toolchain >> |
| |
| jobs: |
| # Build using docker |
| build: |
| parameters: |
| resource_class: |
| type: string |
| default: large |
| build-system: |
| type: string |
| toolchain: |
| type: string |
| family: |
| type: string |
| build-args: |
| type: string |
| default: "" |
| |
| docker: |
| - image: cimg/base:current |
| working_directory: ~/project/tinyusb |
| resource_class: << parameters.resource_class >> |
| |
| steps: |
| - build: |
| build-system: << parameters.build-system >> |
| toolchain: << parameters.toolchain >> |
| family: << parameters.family >> |
| build-args: << parameters.build-args >> |
| |
| # Build using VM |
| build-vm: |
| parameters: |
| resource_class: |
| type: string |
| default: large |
| build-system: |
| type: string |
| toolchain: |
| type: string |
| family: |
| type: string |
| build-args: |
| type: string |
| default: "" |
| |
| machine: |
| image: ubuntu-2404:current |
| working_directory: ~/project/tinyusb |
| resource_class: << parameters.resource_class >> |
| |
| steps: |
| - build: |
| build-system: << parameters.build-system >> |
| toolchain: << parameters.toolchain >> |
| family: << parameters.family >> |
| build-args: << parameters.build-args >> |
| |
| # Aggregate code metrics from all builds |
| code-metrics: |
| docker: |
| - image: cimg/python:3.12 |
| resource_class: large |
| steps: |
| - checkout |
| - attach_workspace: |
| at: /tmp |
| |
| - run: |
| name: Aggregate Code Metrics |
| command: | |
| python tools/get_deps.py |
| # Combine all metrics files from all toolchain subdirectories |
| ls -R /tmp/metrics |
| if ls /tmp/metrics/*/*.json 1> /dev/null 2>&1; then |
| python tools/metrics.py combine -j -m -f tinyusb/src /tmp/metrics/*/*.json |
| else |
| echo "No metrics files found" |
| exit 1 |
| fi |
| |
| - store_artifacts: |
| path: metrics.json |
| destination: metrics.json |
| |
| # Compare with base master metrics on PR branches |
| - when: |
| condition: |
| not: |
| equal: [ master, << pipeline.git.branch >> ] |
| steps: |
| - run: |
| name: Download Base Branch Metrics |
| command: | |
| # Download metrics.json artifact from the latest successful build on master branch |
| mkdir -p base-metrics |
| # Use CircleCI API to get the latest artifact |
| curl -s -L "https://dl.circleci.com/api/v2/project/gh/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/latest/artifacts?branch=master&filter=successful" \ |
| -H "Circle-Token: ${CIRCLE_TOKEN:-}" | \ |
| jq -r '.items[] | select(.path == "metrics.json") | .url' | \ |
| head -1 | xargs -I {} curl -s -L -o base-metrics/metrics.json {} || true |
| |
| - run: |
| name: Compare with Base Branch |
| command: | |
| if [ -f base-metrics/metrics.json ]; then |
| python tools/metrics.py compare -f tinyusb/src base-metrics/metrics.json metrics.json |
| cat metrics_compare.md |
| else |
| echo "No base metrics found, skipping comparison" |
| cp metrics.md metrics_compare.md |
| fi |
| |
| - store_artifacts: |
| path: metrics_compare.md |
| destination: metrics_compare.md |
| |
| workflows: |
| build: |
| jobs: |
| # The jobs below are populated dynamically by config.yml set-matrix job |
| # Example entries that will be generated: |
| # - build: |
| # matrix: |
| # alias: build-cmake-arm-gcc |
| # parameters: |
| # toolchain: [ 'arm-gcc' ] |
| # build-system: [ 'cmake' ] |
| # family: [ 'nrf' ] |
| # resource_class: ['large'] |
| # - code-metrics: |
| # requires: |
| # - build-cmake-arm-gcc |