0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【C言語×GitHub Actions CI#3】組込みC言語プロジェクトにCIを導入する:静的解析・カバレッジ編

0
Posted at

はじめに

本記事は全5部構成のシリーズです。

#2ではビルドとGoogleTestによる単体テストを解説しました。
本記事ではその中から「静的解析」と「カバレッジ計測」のステップを掘り下げて解説します。

サンプルコードはこちらです。
https://github.com/YusukeHarada/c-sample


静的コード解析(cppcheck)

cppcheckとは

cppcheckはC/C++向けの静的解析ツールです。コンパイルエラーにはならないが潜在的に問題となるコードを検出できます。組み込み開発でも広く使われています。

makefileの設定

check:
    @echo "Running cppcheck..."
    cppcheck --enable=all --suppress=missingIncludeSystem --error-exitcode=1 $(SRC) main.h
    @echo "Checking with strict compiler warnings..."
    $(CC) -Wall -Wextra -Werror -c $(SRC) -o /tmp/check.o
    @echo "Static analysis completed successfully!"

主なオプションの意味は以下のとおりです。

オプション 内容
--enable=all すべてのチェックを有効化
--suppress=missingIncludeSystem システムヘッダの未検出警告を抑制
--error-exitcode=1 警告検出時に非ゼロで終了(CI失敗扱いにする)

--error-exitcode=1 はCIと連携する上で特に重要です。これがないとcppcheckが警告を出しても make check が成功扱いになってしまいます。

また gcc -Wall -Wextra -Werror による警告チェックも合わせて実行しています。-Werror で警告をエラー扱いにすることで、コンパイラレベルの品質チェックも自動化できます。

GitHub Actionsでの解析ステップ

- name: Static code analysis with cppcheck
  run: |
    cppcheck --enable=all --suppress=missingIncludeSystem --error-exitcode=1 main.c main.h

- name: Build check with strict warnings
  run: |
    gcc -Wall -Wextra -Werror -c main.c -o /tmp/main_check.o

カバレッジ計測(gcovr / lcov)

カバレッジ計測の仕組み

gccには --coverage フラグを使ったカバレッジ計測機能が組み込まれています。コンパイル時にこのフラグを付けてビルドし、テストを実行すると .gcda / .gcno ファイルが生成されます。これをgcovrやlcovで集計・可視化する流れです。

コンパイル(--coverageフラグ付き)
    ↓
テスト実行(.gcda / .gcno が生成される)
    ↓
gcovr でコンソール出力(C0カバレッジ確認)
    ↓
lcov + genhtml でHTMLレポート生成

makefileの設定

カバレッジフラグの定義です。

COVERAGE_FLAGS = --coverage -fprofile-arcs -ftest-coverage

コンソール出力用の coverage ターゲットです。

coverage: CXXFLAGS += $(COVERAGE_FLAGS)
coverage: CFLAGS += $(COVERAGE_FLAGS)
coverage: clean
    @mkdir -p $(OUT_DIR)
    @echo "Building with coverage instrumentation..."
    $(CC) $(CFLAGS) -DTESTING -c $(SRC) -o $(OUT_DIR)/main_obj.o
    $(CXX) $(CXXFLAGS) -c $(TEST_SRC) -o $(OUT_DIR)/main_test.o
    $(CXX) $(CXXFLAGS) -o $(OUT_DIR)/$(TEST_TARGET) \
        $(OUT_DIR)/main_obj.o $(OUT_DIR)/main_test.o $(GTEST_FLAGS)
    @echo "Running tests with coverage..."
    ./$(OUT_DIR)/$(TEST_TARGET)
    @echo "Generating coverage report..."
    @mkdir -p $(OUT_DIR)/coverage
    gcov $(SRC) -o $(OUT_DIR)/ 2>/dev/null || true
    @echo ""
    @echo "C0 (Line) Coverage Report:"
    @echo "================================"
    @gcovr --filter=$(SRC) --print-summary 2>/dev/null || \
        (echo "Note: gcovr not installed." && \
        cat $(SRC:.c=.c.gcov) 2>/dev/null || \
        echo "No coverage data available")

main.c$(CC)(gcc)でコンパイルしている点が重要です。C++コンパイラでコンパイルするとカバレッジデータが正しく収集されません(詳しくは第4部)。

HTMLレポート生成用の coverage-html ターゲットです。

coverage-html: coverage
    @echo "Generating HTML coverage report..."
    @mkdir -p $(OUT_DIR)/coverage
    lcov --directory $(OUT_DIR) --capture \
        --output-file $(OUT_DIR)/coverage/coverage.info \
        --ignore-errors mismatch
    lcov --remove $(OUT_DIR)/coverage/coverage.info \
        '/usr/include/*' '/usr/local/*' '*/test_main.cc' \
        --output-file $(OUT_DIR)/coverage/coverage_filtered.info \
        --ignore-errors mismatch,unused
    genhtml $(OUT_DIR)/coverage/coverage_filtered.info \
        --output-directory $(OUT_DIR)/coverage/html \
        --ignore-errors mismatch
    @echo "HTML report generated at: $(OUT_DIR)/coverage/html/index.html"

--ignore-errors mismatch,unused を付けている理由については第4部で詳しく解説します。

コンソール出力例

C0 (Line) Coverage Report:
================================
Lines executed:100.00% of 8

HTMLレポートの見方

make coverage-html を実行すると out/coverage/html/index.html にHTMLレポートが生成されます。ブラウザで開くと各ソースファイルの行ごとの実行状況を確認できます。

メトリクス 説明
Line Coverage (C0) ソースコード行がテストで実行された割合
Branch Coverage (C1) if文などの分岐がテストで実行された割合
Function Coverage 関数がテストで呼び出された割合

スクリーンショット 2026-04-22 20.57.21.png

GitHub ActionsでのカバレッジステップとArtifacts保存

- name: Run coverage measurement
  run: make coverage
  continue-on-error: true

- name: Generate HTML coverage report
  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

continue-on-error: true を付けているのは、カバレッジが取れない場合でもビルドやテストの結果は確認できるようにするためです。

HTMLレポートはArtifactsとして保存されます。Actions実行結果のページ下部の「Artifacts」からダウンロードして確認できます。

スクリーンショット 2026-04-22 20.58.08.png


まとめ

本記事では以下を解説しました。

  • cppcheckとgcc警告チェックによる静的解析の設定
  • gcovr/lcovを使ったC0カバレッジ計測とHTMLレポート生成
  • カバレッジレポートをArtifactsとして保存する仕組み

次回はCI構築中に実際にハマったポイントを解説します。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?