はじめに
組み込みソフトウェア開発では、C言語プロジェクトへのCI導入は「やりたいけど設定が面倒」と後回しになりがちです。
今回、GitHub Actionsを使ってC言語プロジェクトのCI環境をゼロから構築してみました。
自動化した内容は以下の4つです。
- ビルド(make)
- 単体テスト(GoogleTest)
- 静的コード解析(cppcheck)
- カバレッジ計測(gcovr / lcov)
また、構築にあたってGitHub Copilotも活用しました。設定ファイルや定型コードの生成に役立った点や、ハマりどころについては#4でまとめています。
サンプルコードはこちらで公開しています。
https://github.com/YusukeHarada/c-sample
本記事は全5部構成のシリーズです。
- #1(本記事):概要・構成編 ← いまここ
- #2:ビルド・単体テスト編
- #3:静的解析・カバレッジ編
- #4:ハマりどころ編
- #5:GitLab経験者向けワークフロー構文解説
作ったものの全体像
リポジトリ構成
c-sample/
├── main.c # プログラム本体(add / multiply / run_program)
├── main.h # ヘッダファイル(extern "C" ガード付き)
├── test_main.cc # GoogleTestによる単体テスト(C++)
├── makefile # ビルド・テスト・解析・カバレッジをまとめて管理
└── .github/
└── workflows/
└── ci.yml # GitHub Actions ワークフロー定義
プログラム本体は add と multiply という2つの関数と、それらを呼び出す run_program で構成されたシンプルなサンプルです。CI環境の構築方法を示すことが目的なので、コード自体はシンプルに保っています。
CIで自動化している内容
| ステップ | ツール | 内容 |
|---|---|---|
| ビルド | gcc / make | メインプログラムのビルド確認 |
| 単体テスト | GoogleTest | 関数レベルのテスト実行 |
| 静的解析 | cppcheck | コード品質チェック |
| 警告チェック | gcc (-Wall -Wextra -Werror) | 厳密なコンパイル確認 |
| カバレッジ計測 | gcovr / lcov | C0カバレッジ計測・HTMLレポート生成 |
GitHub Actionsワークフローの概要
.github/workflows/ci.yml の全体像です。
name: CI Build
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential pkg-config libgtest-dev cppcheck gcovr lcov
- name: Build with make
run: make
- name: Run unit tests
id: test
run: make test
- name: Static code analysis with cppcheck
id: cppcheck
run: cppcheck --enable=all --suppress=missingIncludeSystem --error-exitcode=1 main.c main.h
- name: Build check with strict warnings
id: build_check
run: gcc -Wall -Wextra -Werror -c main.c -o /tmp/main_check.o
- name: Run coverage measurement
id: coverage
run: make coverage
continue-on-error: true
- name: Generate HTML coverage report
id: coverage_html
run: make coverage-html
continue-on-error: true
- name: Check coverage directory
run: ls -la out/ || echo "out directory does not exist"
continue-on-error: true
- name: Upload coverage reports
uses: actions/upload-artifact@v4
if: always() && hashFiles('out/coverage/**') != ''
with:
name: coverage-report
path: out/coverage/
if-no-files-found: warn
- name: Final status check
if: always()
run: |
if [[ "${{ steps.test.outcome }}" == "success" && "${{ steps.cppcheck.outcome }}" == "success" && "${{ steps.build_check.outcome }}" == "success" ]]; then
echo "🎉 All CI checks passed successfully!"
echo "✅ Build: OK"
echo "✅ Tests: OK"
echo "✅ Static Analysis: OK"
echo "✅ Warnings Check: OK"
echo "✅ Coverage: Generated (check artifacts)"
exit 0
else
echo "❌ Some CI checks failed!"
echo "Build: ${{ steps.test.outcome == 'success' && '✅ OK' || '❌ FAILED' }}"
echo "Tests: ${{ steps.cppcheck.outcome == 'success' && '✅ OK' || '❌ FAILED' }}"
echo "Static Analysis: ${{ steps.build_check.outcome == 'success' && '✅ OK' || '❌ FAILED' }}"
echo "Warnings Check: ${{ steps.coverage.outcome == 'success' && '✅ OK' || '⚠️ SKIPPED' }}"
echo "Coverage: ${{ steps.coverage_html.outcome == 'success' && '✅ OK' || '⚠️ SKIPPED' }}"
exit 1
fi
- name: Clean up
if: always()
run: make clean
トリガー条件
main ブランチへのpushおよびpull requestをトリガーとしています。
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
依存ライブラリのインストール
必要なツールをまとめて1ステップでインストールしています。
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install -y build-essential pkg-config libgtest-dev cppcheck gcovr lcov
CI結果のサマリー表示(Final status check)
各ステップに id を付与し、最終ステップで全体の成否をまとめて表示するようにしています。
- name: Final status check
if: always()
run: |
if [[ "${{ steps.test.outcome }}" == "success" && ... ]]; then
echo "🎉 All CI checks passed successfully!"
echo "✅ Build: OK"
echo "✅ Tests: OK"
...
else
echo "❌ Some CI checks failed!"
...
exit 1
fi
成功時・失敗時の表示イメージはこのようになります。
成功時:
🎉 All CI checks passed successfully!
✅ Build: OK
✅ Tests: OK
✅ Static Analysis: OK
✅ Warnings Check: OK
✅ Coverage: Generated (check artifacts)
失敗時:
❌ Some CI checks failed!
ビルドやテストが通ってもカバレッジが取れなかった場合は ⚠️ SKIPPED として扱い、CIを失敗扱いにしない設計にしています(カバレッジステップには continue-on-error: true を指定)。
まとめ
本記事では、CI環境の全体像とワークフローの概要を紹介しました。
次回以降で各ステップの詳細を解説していきます。

