chore(examples): kebab-case naming, remove loose host demo and index #71
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
| name: CI | |
| on: | |
| push: | |
| branches: [ main ] | |
| pull_request: | |
| branches: [ main ] | |
| jobs: | |
| # ============================================================ | |
| # Desktop: full test suites (compile + run) | |
| # ============================================================ | |
| test-gcc: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Build and test (gcc, C99 strict) | |
| run: make CC=gcc test | |
| test-clang: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Build and test (clang, C99 strict) | |
| run: make CC=clang test | |
| test-macos: | |
| runs-on: macos-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Build and test (Apple clang) | |
| run: make test | |
| test-windows: | |
| runs-on: windows-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Build and test (MSVC) | |
| shell: cmd | |
| run: | | |
| call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat" | |
| cl /std:c11 /W4 /I src /Fe:test_msg.exe test\test_midi2_msg.c | |
| test_msg.exe | |
| cl /std:c11 /W4 /I src /Fe:test_proc.exe test\test_midi2_proc.c src\midi2_proc.c | |
| test_proc.exe | |
| cl /std:c11 /W4 /I src /Fe:test_ci.exe test\test_midi2_ci.c src\midi2_proc.c src\midi2_ci.c | |
| test_ci.exe | |
| cl /std:c11 /W4 /I src /Fe:test_conv.exe test\test_midi2_conv.c src\midi2_conv.c | |
| test_conv.exe | |
| cl /std:c11 /W4 /I src /Fe:test_dispatch.exe test\test_midi2_dispatch.c src\midi2_dispatch.c | |
| test_dispatch.exe | |
| cl /std:c11 /W4 /I src /Fe:test_ci_msg.exe test\test_midi2_ci_msg.c | |
| test_ci_msg.exe | |
| cl /std:c11 /W4 /I src /Fe:test_ci_dispatch.exe test\test_midi2_ci_dispatch.c src\midi2_ci_dispatch.c | |
| test_ci_dispatch.exe | |
| # ============================================================ | |
| # Embedded: cross-compilation (syntax + type check, no link) | |
| # ============================================================ | |
| build-arm-cortex-m: | |
| name: ARM Cortex-M (arm-none-eabi-gcc) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install ARM toolchain | |
| run: sudo apt-get update && sudo apt-get install -y gcc-arm-none-eabi | |
| - name: Compile all modules for Cortex-M | |
| run: | | |
| for f in src/*.c; do | |
| echo " CC $f" | |
| arm-none-eabi-gcc -std=c99 -Wall -Wextra -Wpedantic -I src \ | |
| -mcpu=cortex-m4 -mthumb -c "$f" -o /dev/null | |
| done | |
| echo "ARM Cortex-M4: OK" | |
| build-arm-cortex-a: | |
| name: ARM Cortex-A (aarch64-linux-gnu-gcc) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install AArch64 toolchain | |
| run: sudo apt-get update && sudo apt-get install -y gcc-aarch64-linux-gnu | |
| - name: Compile all modules for AArch64 | |
| run: | | |
| for f in src/*.c; do | |
| echo " CC $f" | |
| aarch64-linux-gnu-gcc -std=c99 -Wall -Wextra -Wpedantic -I src \ | |
| -c "$f" -o /dev/null | |
| done | |
| echo "AArch64 (Cortex-A / RPi / Daisy): OK" | |
| build-riscv: | |
| name: RISC-V (riscv64-linux-gnu-gcc) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install RISC-V toolchain | |
| run: sudo apt-get update && sudo apt-get install -y gcc-riscv64-linux-gnu | |
| - name: Compile all modules for RISC-V | |
| run: | | |
| for f in src/*.c; do | |
| echo " CC $f" | |
| riscv64-linux-gnu-gcc -std=c99 -Wall -Wextra -Wpedantic -I src \ | |
| -c "$f" -o /dev/null | |
| done | |
| echo "RISC-V 64: OK" | |
| build-esp32-idf: | |
| name: ESP32 (ESP-IDF component check) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Compile with Xtensa GCC (via xtensa-esp-elf docker) | |
| run: | | |
| # Verify C99 strict compilation with a cross-compiler proxy | |
| # ESP-IDF uses xtensa-esp-elf-gcc, but for CI we verify with | |
| # standard gcc in C99 mode as ESP-IDF component compatibility | |
| for f in src/*.c; do | |
| echo " CC $f" | |
| gcc -std=c99 -Wall -Wextra -Wpedantic -I src \ | |
| -DESP_PLATFORM -c "$f" -o /dev/null | |
| done | |
| echo "ESP32 (component check): OK" | |
| build-avr: | |
| name: AVR (avr-gcc) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install AVR toolchain | |
| run: sudo apt-get update && sudo apt-get install -y gcc-avr avr-libc | |
| - name: Compile header-only modules for AVR | |
| run: | | |
| # AVR has no stdint-compatible bool, test header-only modules | |
| avr-gcc -std=c99 -Wall -Wextra -I src -mmcu=atmega328p \ | |
| -c -x c - -o /dev/null <<'AVRTEST' | |
| #include "midi2_msg.h" | |
| #include "midi2_ci_msg.h" | |
| uint32_t test(void) { | |
| uint32_t w[2]; | |
| midi2_msg_note_on(w, 0, 0, 60, 0xC000, 0, 0); | |
| return w[0]; | |
| } | |
| AVRTEST | |
| echo "AVR ATmega328P (header-only): OK" | |
| build-cxx-header: | |
| name: C++ header compile (g++ c++17 / c++20) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Regenerate amalgam and fail on drift | |
| run: | | |
| # The amalgam is C++-compiled below. Regenerate it from src/ and fail | |
| # if the committed dist/ is stale, so a contributor who forgot to | |
| # re-amalgamate cannot ship a src/ change the C++ job never saw. | |
| ./tools/amalgamate.sh | |
| git diff --exit-code dist/ \ | |
| || (echo "dist/ is stale: run tools/amalgamate.sh and commit" && exit 1) | |
| - name: Compile public headers as C++ | |
| run: | | |
| # midi2.h is included directly by C++ consumers (midi2cpp, | |
| # libDaisy, Teensy wrappers). Guards against C-only constructs | |
| # such as designated array initializers that g++ rejects. The | |
| # modular arm includes every header a wrapper pulls in, so a | |
| # C++-hostile construct in any of them fails here, not downstream. | |
| printf '#define MIDI2_IMPLEMENTATION\n#include "midi2.h"\nint main(void) { return (int)midi2_msg_word_count(0x4); }\n' > cxx_amalgam.cpp | |
| printf '#include "midi2_msg.h"\n#include "midi2_conv.h"\n#include "midi2_proc.h"\nint main(void) { return (int)midi2_msg_word_count(0x4); }\n' > cxx_modular.cpp | |
| for std in c++17 c++20; do | |
| echo " amalgam $std" | |
| g++ -std=$std -Wall -Wextra -I dist cxx_amalgam.cpp -o /dev/null | |
| echo " modular $std" | |
| g++ -std=$std -Wall -Wextra -I src cxx_modular.cpp -o /dev/null | |
| done | |
| echo "C++ header compile: OK" | |
| # ============================================================ | |
| # Additional desktop architectures | |
| # ============================================================ | |
| test-gcc-32bit: | |
| name: Linux x86 32-bit (gcc -m32) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Install 32-bit libraries | |
| run: sudo apt-get update && sudo apt-get install -y gcc-multilib | |
| - name: Build and test (gcc 32-bit) | |
| run: make CC="gcc -m32" test | |
| test-gcc-sanitizers: | |
| name: Linux (gcc + ASan + UBSan) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Build and test with sanitizers | |
| run: make CC="gcc -fsanitize=address,undefined -fno-omit-frame-pointer" test | |
| # ============================================================ | |
| # CMake build matrix: configure -> build -> install -> downstream | |
| # find_package(midi2) consumer compiled and run from the installed | |
| # prefix. The synthetic consumer lives at tests/cmake-consumer/ so | |
| # the same files are exercised across Linux / macOS / Windows. | |
| # ============================================================ | |
| cmake-build: | |
| name: CMake build + install + find_package (${{ matrix.os }}) | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: [ubuntu-latest, macos-latest, windows-latest] | |
| steps: | |
| - uses: actions/checkout@v5 | |
| # CMAKE_BUILD_TYPE is needed by single-config generators (Make, | |
| # Ninja on Linux/macOS) so the exported midi2-config-<cfg>.cmake | |
| # carries IMPORTED_LOCATION_<CONFIG>. Multi-config generators | |
| # (Visual Studio) ignore CMAKE_BUILD_TYPE and respect --config. | |
| - name: Configure | |
| run: cmake -S . -B build-cmake -DCMAKE_BUILD_TYPE=Release | |
| - name: Build | |
| run: cmake --build build-cmake --parallel --config Release | |
| - name: Install | |
| run: cmake --install build-cmake --prefix ${{ runner.temp }}/midi2-install --config Release | |
| - name: Configure downstream consumer | |
| run: > | |
| cmake -S tests/cmake-consumer -B build-consumer | |
| -DCMAKE_PREFIX_PATH=${{ runner.temp }}/midi2-install | |
| -DCMAKE_BUILD_TYPE=Release | |
| - name: Build downstream consumer | |
| run: cmake --build build-consumer --parallel --config Release | |
| - name: Run downstream consumer (Unix) | |
| if: runner.os != 'Windows' | |
| run: ./build-consumer/midi2_consumer | |
| - name: Run downstream consumer (Windows) | |
| if: runner.os == 'Windows' | |
| run: build-consumer\Release\midi2_consumer.exe | |
| # ============================================================ | |
| # FetchContent path: synthetic project pulls midi2 from the local | |
| # checkout via FetchContent_Declare and links midi2::midi2 without | |
| # any install step. Documents-as-CI: the README's snippet has to | |
| # actually work. | |
| # ============================================================ | |
| cmake-fetchcontent: | |
| name: CMake FetchContent (downstream pulls midi2 by source) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Stage parent project | |
| run: | | |
| mkdir -p ${{ runner.temp }}/parent | |
| cat > ${{ runner.temp }}/parent/CMakeLists.txt <<'PARENT_CMAKE' | |
| cmake_minimum_required(VERSION 3.14) | |
| project(parent LANGUAGES C) | |
| include(FetchContent) | |
| FetchContent_Declare(midi2 SOURCE_DIR ${MIDI2_LOCAL_PATH}) | |
| FetchContent_MakeAvailable(midi2) | |
| add_executable(parent_consumer main.c) | |
| target_link_libraries(parent_consumer PRIVATE midi2::midi2) | |
| PARENT_CMAKE | |
| cp tests/cmake-consumer/main.c ${{ runner.temp }}/parent/main.c | |
| - name: Configure + build + run | |
| run: | | |
| cmake -S ${{ runner.temp }}/parent -B ${{ runner.temp }}/parent-build \ | |
| -DMIDI2_LOCAL_PATH=${{ github.workspace }} | |
| cmake --build ${{ runner.temp }}/parent-build --parallel | |
| ${{ runner.temp }}/parent-build/parent_consumer | |
| # ============================================================ | |
| # CMake build with ASan + UBSan parity to the Makefile sanitizer | |
| # job. Catches sanitizer-detectable regressions in the amalgam | |
| # build path that the Makefile build (which compiles the modular | |
| # src/*.c) might miss. | |
| # ============================================================ | |
| cmake-build-sanitizers: | |
| name: CMake (gcc + ASan + UBSan) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Configure with sanitizers | |
| run: > | |
| cmake -S . -B build-cmake-asan | |
| -DCMAKE_C_FLAGS="-fsanitize=address,undefined -fno-sanitize-recover=all -O1 -g" | |
| -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined" | |
| - name: Build | |
| run: cmake --build build-cmake-asan --parallel | |
| - name: Install | |
| run: cmake --install build-cmake-asan --prefix ${{ runner.temp }}/midi2-install | |
| - name: Configure + build + run downstream consumer with sanitizers | |
| run: | | |
| cmake -S tests/cmake-consumer -B build-consumer-asan \ | |
| -DCMAKE_PREFIX_PATH=${{ runner.temp }}/midi2-install \ | |
| -DCMAKE_C_FLAGS="-fsanitize=address,undefined -fno-sanitize-recover=all -O1 -g" \ | |
| -DCMAKE_EXE_LINKER_FLAGS="-fsanitize=address,undefined" | |
| cmake --build build-consumer-asan --parallel | |
| ./build-consumer-asan/midi2_consumer | |
| # ============================================================ | |
| # Zephyr (west module): builds the smoke consumer at | |
| # tests/zephyr-consumer/ on native_sim/native/64. Confirms the | |
| # zephyr/ module manifest keeps wiring midi2 sources into a Zephyr | |
| # application and that dispatch fires end-to-end under Zephyr's | |
| # kernel. native_sim uses host gcc -- no Zephyr SDK toolchain | |
| # bundle needed. | |
| # ============================================================ | |
| build-zephyr: | |
| name: Zephyr (native_sim/native/64) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| path: midi2 | |
| - name: Install west and host build tools | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends ninja-build device-tree-compiler | |
| python3 -m pip install --user west pyelftools jsonschema PyYAML packaging \ | |
| anytree colorama docutils intelhex | |
| echo "${HOME}/.local/bin" >> "$GITHUB_PATH" | |
| - name: Cache Zephyr workspace | |
| id: cache-zephyr | |
| uses: actions/cache@v4 | |
| with: | |
| path: zephyrproject | |
| key: zephyrproject-v4.4.0-${{ runner.os }} | |
| - name: Initialize Zephyr workspace (cache miss) | |
| if: steps.cache-zephyr.outputs.cache-hit != 'true' | |
| run: | | |
| west init --mr v4.4.0 zephyrproject | |
| cd zephyrproject | |
| west update --narrow -o=--depth=1 | |
| - name: Install Zephyr Python requirements | |
| run: | | |
| python3 -m pip install --user -r zephyrproject/zephyr/scripts/requirements-base.txt | |
| - name: Install Zephyr SDK minimal | |
| run: | | |
| cd "$HOME" | |
| wget -q https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v1.0.1/zephyr-sdk-1.0.1_linux-x86_64_minimal.tar.xz | |
| tar xf zephyr-sdk-1.0.1_linux-x86_64_minimal.tar.xz | |
| echo "ZEPHYR_SDK_INSTALL_DIR=$HOME/zephyr-sdk-1.0.1" >> "$GITHUB_ENV" | |
| - name: Configure smoke consumer | |
| env: | |
| ZEPHYR_BASE: ${{ github.workspace }}/zephyrproject/zephyr | |
| run: | | |
| cd midi2/tests/zephyr-consumer | |
| cmake -B build -GNinja \ | |
| -DBOARD=native_sim/native/64 \ | |
| -DZEPHYR_EXTRA_MODULES="$GITHUB_WORKSPACE/midi2" | |
| - name: Build smoke consumer | |
| run: cmake --build midi2/tests/zephyr-consumer/build | |
| - name: Run smoke, assert PASS | |
| run: | | |
| OUTPUT=$(timeout 5 midi2/tests/zephyr-consumer/build/zephyr/zephyr.exe 2>&1 || true) | |
| echo "$OUTPUT" | |
| echo "$OUTPUT" | grep -q "midi2 Zephyr smoke: PASS" |