333 lines
7.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# C/C++の開発環境
- [C/C++の開発環境](#ccの開発環境)
- [Linter](#linter)
- [導入方法](#導入方法)
- [Dockerを活用する](#dockerを活用する)
- [Linterの使い方](#linterの使い方)
- [clang-tidy の使い方(C++向け)](#clang-tidy-の使い方c向け)
- [ccppcheck の使い方C / C++ 両対応)](#ccppcheck-の使い方c--c-両対応)
- [テスト](#テスト)
- [テスト環境を構築する](#テスト環境を構築する)
- [Doc(ドキュメンテーション)](#docドキュメンテーション)
- [環境構築](#環境構築)
- [Dockerを活用する](#dockerを活用する-1)
- [doxygen 使い方](#doxygen-使い方)
- [CI / CDによる実行](#ci--cdによる実行)
- [Doxyfileの設定](#doxyfileの設定)
- [Docコメントの書き方](#docコメントの書き方)
## Linter
ライブラリの候補
* **clang-tidy**
* 精度はかなり高い
* C++向け(Cはカバー範囲が狭い)
* **cppcheck**
* C/C++ 両方対応・軽量
* 導入が簡単にできる
### 導入方法
**Macの場合**
```sh
brew install cppcheck llvm
# パスの追加が必要
export PATH="/opt/homebrew/opt/llvm/bin:$PATH"
clang-tidy --version
cppcheck --version
```
* llvm: clang-tidy は llvm に含まれています
**Linux(Ubuntu)の場合**
```sh
sudo apt install cppcheck clang-tidy
clang-tidy --version
cppcheck --version
```
#### Dockerを活用する
[Dockerfileはこちら](../Dockerfile.devtools)
Dockerイメージをビルドする
```sh
docker build -f Dockerfile.devtools -t c-dev-tools .
```
```sh
# docker run --rm -v "$(pwd)":/work -w /work c-dev-tools <コマンド>
```
### Linterの使い方
#### clang-tidy の使い方(C++向け)
**単一ファイルをチェックする例**
```sh
clang-tidy src/cpp/hello.cpp -- -Iinclude -std=c++17
# Docker
docker run --rm -v "$(pwd)":/work -w /work clang-tidy src/cpp/hello.cpp -- -Iinclude -std=c++17
```
* `--`以降がコンパイラフラグ(g++に渡すものと同じ)
* -Iinclude : ヘッダファイルのパス
* -std=c++17 : 使用している C++ のバージョン
**チェック内容を絞る使い方**
```sh
clang-tidy src/cpp/hello.cpp \
-checks='modernize-*,bugprone-*,readability-*' \
-- -Iinclude -std=c++17
```
よく使うチェックカテゴリ:
* bugprone-* : バグにつながるコード
* modernize-* : モダンC++スタイルへの改善提案
* readability-* : 可読性の改善
**プロジェクト全体**
CMake + compile_commands.jsonがある場合に以下の内容でできます
(clang-tidy は「コンパイル情報」がないと正しく解析できない)
compile_commands.jsonについては別途解説します。
```sh
mkdir -p build
cd build
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
# プロジェクト全体に対して実行
run-clang-tidy -p build
```
#### ccppcheck の使い方C / C++ 両対応)
cppcheckはコンパイル不要で実行できる静的解析ツールです。
CでもC++でも同じコマンドで使えます。
**基本的な使い方**
```sh
cppcheck src/
# Docker
docker run --rm -v "$(pwd)":/work -w /work c-dev-tools cppcheck src/
```
**チェックレベルを広げる(おすすめ)**
```sh
cppcheck --enable=warning,style,performance,portability src/
# Docker
docker run --rm -v "$(pwd)":/work -w /work c-dev-tools \
cppcheck --enable=warning,style,performance,portability src/
```
* warning : 危険なコードやバグの可能性
* style : コーディングスタイル上の問題
* performance : 非効率なコード
* portability : 環境依存のコード
## テスト
テストフレームワークの選定
* **C**
* Unity:
* 最軽量・C専用
* C言語の組込み開発でもよく使われる
* シングルヘッダに近い軽量テストツール
* doctest / googletest の C版のような位置付け
* CMocka: Unity より“しっかりしたテスト”をしたいときに最適
* Criterion: C言語でも“近代的なテスト開発”をしたい場合に良い
* **C++**
* GoogleTest:
* C++テストで最も使われる
* 機能が豊富モック、パラメトリック、DeathTestなど
* Catch2: シンプルで読みやすいテストを作りたい人向け
* doctest: 個人開発や高速実行が必要なプロジェクトに最適
### テスト環境を構築する
* Unity(C言語の軽量テストフレームワーク)はパッケージとして提供されていません。https://github.com/ThrowTheSwitch/Unityから必要なファイルをダウンロードして使う
```sh
# unity.c,unity.h,unity_internals.h
git clone https://github.com/ThrowTheSwitch/Unity /opt/unity
```
* Alpine(musl libc)ではGTestのABIが合わず、gtest が正常にビルドできないケースが多い
* doctestとCatch2は普通にビルドで使えます
[Dockerfileはこちら](../Dockerfile.testtools)
テスト用のDockerイメージをビルドする
```sh
docker build -f Dockerfile.testtools -t c-test-tools .
```
## Doc(ドキュメンテーション)
C / C++ の自動ドキュメンテーションをしたい場合、
Doxygen(Graphviz)が圧倒的スタンダードで、最もおすすめです。
* C / C++ / Java / Python などメジャー言語に対応
* コメントを解析して HTML / PDF / Markdown などへ出力
* 関数・構造体・クラスの関係図UML・依存グラフを自動生成
* C++ テンプレートや名前空間にも対応
* Graphvizを入れれば図が自動で描かれる
### 環境構築
**Macの場合**
```sh
brew install doxygen graphviz
```
**Linux(Ubuntu)の場合**
```sh
sudo apt install doxygen graphviz
```
#### Dockerを活用する
[Dockerfileはこちら](../Dockerfile.devtools)
Dockerイメージをビルドする
```sh
docker build -f Dockerfile.devtools -t c-dev-tools .
```
Linuxでコマンドを実行する
```sh
mkdir -p docs
# docker run --rm -v "$(pwd)":/work -w /work/docs c-dev-tools <コマンド>
# 初期化コマンド
docker run --rm -v "$(pwd)":/work -w /work/docs c-dev-tools doxygen -g
# ドキュメントを生成する
docker run --rm -v "$(pwd)":/work -w /work/docs c-dev-tools doxygen Doxyfile
```
### doxygen 使い方
**設定ファイルを生成**
```sh
doxygen -g
```
Doxyfileが作成される
**ドキュメント生成**
```sh
doxygen Doxyfile
```
* html/ に HTML ドキュメント
* latex/ に PDF 用のファイルが出力される(必要なら make)
### CI / CDによる実行
**Git Actionsで生成の場合**
```yaml
- name: Generate Doxygen docs
run: doxygen docs/Doxyfile
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./docs/html
```
### Doxyfileの設定
`docs/Doxyfile`を設定する
* `PROJECT_NAME`を実際のプロジェクト名に変更する
```sh
# ドキュメント化したいディレクトリ
INPUT = ../src ../include
# INPUT 内を再帰的に探索
RECURSIVE = YES
# C向け出力最適化
OPTIMIZE_OUTPUT_FOR_C = YES
# 全シンボル抽出
EXTRACT_ALL = YES
```
図形の設定(クラス図などの生成)
```sh
# クラス図の生成を有効にする
HAVE_DOT = YES
CLASS_DIAGRAMS = YES
# コールグラフと呼び出しグラフを有効にする
CALL_GRAPH = YES
CALLER_GRAPH = YES
# グラフとダイアグラムのサポートを有効にする
DOT_GRAPH = YES
DOT_CLEANUP = YES
# 詳細なクラス図を生成する
UML_LOOK = YES
```
### Docコメントの書き方
C言語の場合
```c
/**
* @brief 二数の最大値を返す関数
* @param a 整数
* @param b 整数
* @return 最大値
*/
int max(int a, int b);
```
C++言語の場合
```c
/**
* @class User
* @brief ユーザー情報を扱うクラス
*/
class User {
public:
/**
* @brief コンストラクタ
*/
User(std::string name, int age);
/**
* @brief 名前を取得する
*/
std::string getName() const;
```