はじめに
本記事は全5部構成のシリーズです。
- #1:概要・構成編
- #2:ビルド・単体テスト編
- #3(本記事):静的解析・カバレッジ編 ← いまここ
- #4:ハマりどころ編
- #5:GitLab経験者向けワークフロー構文解説
#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 | 関数がテストで呼び出された割合 |
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」からダウンロードして確認できます。
まとめ
本記事では以下を解説しました。
- cppcheckとgcc警告チェックによる静的解析の設定
- gcovr/lcovを使ったC0カバレッジ計測とHTMLレポート生成
- カバレッジレポートをArtifactsとして保存する仕組み
次回はCI構築中に実際にハマったポイントを解説します。

