Open7

C++20 で Siv3D v0.6.0 の開発をしたときのふりかえり

usagigausagiga

Abstract

C++20 で Siv3D v0.6.0 を利用した開発をしました。

自分はファイルシステムと画面描画を少し触っただけなのですけれど、Siv3D を用いた開発一般、ひいてはゲームプログラミングに関して学びを得ることができました。

このスクラップでは、自分の復習を目的として、この作業を通して得た知見についてまとめます。

Topics

このスクラップでは、主に以下のようなトピックを扱います。

  • C++20 の開発手法
  • Siv3D の開発手法
    • おすすめのリファレンス
  • 環境構築
    • フォーマッタの設定
      • clang-format
      • EditorConfig
    • IDE の設定
      • Visual Studio 2019
      • CLion Nova
      • Visual Studio Code for the Web (on GitHub Codespaces)
    • CI
      • フォーマッタを GitHub Actions で動かす
    • Git
      • .gitignore
      • Git LFS

TBU

それぞれについて Comparison や Best Practice なんかが書かれる予定です。

Disclaimer

このスクラップの内容は、usagiga 個人の推測が多分に含まれます

usagigausagiga

Siv3D v0.6.0 について

Siv3D とは

  • OSS のゲームエンジン
  • C++20 製
    • Boost や最新の標準ライブラリなど、モダンなもので構成されている
  • シンプル
    • Unity や UE などと異なり、小さく平易なエコシステム
  • マルチプラットフォーム
    • Windows / Mac / Linux / Web で動くらしい

現行の Siv3D との差分

自分が使っている Siv3D v0.6.0 は、現行である Siv3D v0.6.13 よりも古いものになります。
現行との違いはリリースノートを読めば差分がわかります。

https://siv3d.github.io/ja-jp/releases/

大きな差分としては以下の通りです:

  • Siv3D v0.6.0 は Siv3D August 2016 v2 とも呼ばれる
  • レポジトリやリファレンスの所在が異なる
  • 開発環境が異なる
    • Visual Studio 2015 / 2019
    • Windows 7 SP1 / 8.1 / 10
    • Windows 10 SDK 10.0.17763.0

リンク集

環境構築

IDE やライブラリの準備

まずはこれをやれば IDE やライブラリ群、テンプレートとなるソリューションやプロジェクトを作成できます。

ダウンロードとインストール · Siv3D/Reference-JP Wiki

.gitignore

公式ドキュメント にも記述がありますが、一応書いておきます。

# Siv3D
[Ee]ngine/
[Ee]xample/
[Ss]creenshot/
[Aa]ssets/
*.html
*.s3a

# その他、Visual Studio の自動生成ファイルなどを記述しておく
# gibo dump VisualStudio でばちっとやってしまうのがおすすめ

Git LFS

大きめのアセットを Git で利用するなら、Git LFS を使うとレポジトリ操作を高速に実行してくれます。

なお、GitHub では LFS について制約やクォータが存在するので、GitHub を利用する方はドキュメントを参照してください。

usagigausagiga

C++20 を使う

せっかく Siv3D 本体が C++20 で作られているので、ソースコードも C++20 で作ってみましょう。

VC++ コンパイラ(cl) の実行時引数に /std:c++latest を指定すればよいです。
これで、本記事作成時点では C++20 の機能が有効化されます。

/std (言語の標準バージョンの指定) | Microsoft Learn

手順

Visual Studio のプロジェクトのプロパティをよしなに操作し、「追加のオプション」内に引数を記述してやれば OK です。

visualstudio-project-properties-for-cpp20

usagigausagiga

ヘッダファイルをインクルードできるようにする

テンプレートのプロジェクトそのままだと、cl/I オプションが特に指定されていないので、プロジェクト内のヘッダファイルを #include <...> を使ってインクルードすることができません。したがって、#include "..." を使って相対パスでインクルードをすることになります。

#include ディレクティブ (C/C++) | Microsoft Learn

とはいえ、これだと使い勝手が悪いので、コンパイラの引数をいじっておきます。

今回は、プロジェクトルートディレクトリをベースとする相対パスで指定できるようにします。
以下のようなものを想定しています:

$ pwd
/mnt/c/Users/maris/source/repos/siv3d-file-open-multiplatform

$ tree .
.
├── LICENSE
├── README.md
├── siv3d-file-open-multiplatform
│   ├── Main.cpp
│   ├── Models
│   │   ├── Poetry.cpp
│   │   └── Poetry.hpp ... #include <Model/Poetry.hpp> で読み込む
│   └── siv3d-file-open-multiplatform.vcxproj
└── siv3d-file-open-multiplatform.sln

ディレクトリ構成に関しては各自よきように設定してください。

手順

Visual Studio についているプロジェクトのプロパティの GUI を開きます。
C/C++ -> 全般追加のインクルードディレクトリ というのがあるので、それを編集しましょう。

ここでは、${ProjectDir} というマクロを使って、プロジェクトのルートディレクトリを指定しておきます。

visualstudio-additional-include-dirs

usagigausagiga

フォーマッタなどの設定

フォーマッタとして、clang-format と EditorConfig を導入します。

フォーマッタを設定しておくと、ファイルごとの表記ゆれや文字コード・改行コードのブレが少なくなり、複数人での開発やエディタの違いをいい感じに吸収してくれて便利です。

なお、Visual Studio にもある程度フォーマットに関する設定はありますが、自分はエディタに強く依存した操作をするのをあまり好まないため、今回は IDE が clang-format / EditorConfig を使ってくれるように設定することにします。

clang-format を設定する

まず、C++に関連するファイルのフォーマッタである clang-format を設定します。

Visual Studio 2019 以降には clang-format (v5) が内蔵されており、既定で動いてくれています。
これは IDE 側でいくらか設定がなされたものになるので、別途コンフィグを書いて設定項目を上書きし、環境依存を減らしておくことにします。

<solutiondir>/.clang-format
BasedOnStyle: LLVM

---
Language: Cpp
DerivePointerAlignment: false
PointerAlignment: Left
FixNamespaceComments: false
NamespaceIndentation: All
BreakBeforeBraces: Allman

ここは各自お好みで変更してください。

補足: CLI での操作

WSL など、 Linux 実行環境がある場合は、以下のコマンドでソースコードのフォーマットを実行できます。

find . -regextype posix-extended -regex ".*\.(c|cpp|h|hpp)" | xargs -IX clang-format -i --verbose X

EditorConfig

次に、文字コード・改行コードや行末を整えてくれる EditorConfig を設定します。

Visual Studio では、IDE 内に類似の設定項目があり、よしなに設定されていますが、EditorConfig のコンフィグがある場合は EditorConfig の設定値を優先して読み込むような挙動をします。そういうわけで、自分でコンフィグを書いていきます。

<solutiondir>/.editorconfig
root = true

[*]
end_of_line = lf
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 4

[Makefile]
# Makefile のインデントは Tab のみ許容
indent_style = tab

[*.md]
# Markdown のリストではいくつかの実装でインデント幅が2でないと正しく動かない
indent_size = 2

[*.{c,cpp,h,hpp}]
# C++ のファイルでは clang-format がよしなにやってくれるので、
# 衝突するようなものは読みやすさのために明示的に無効としておく
# なお、衝突するコンフィグは clang-format のバージョンにより異なる
indent_style = unset
indent_size = unset

Windows Native 向けの Siv3D プロジェクトならこんなかんじでいいと思います。
お好みで変更してください。

ファイル保存時にフォーマットを自動実行する

ここまでの設定ではフォーマッタが動かないシチュエーションがあるので、ファイル保存時にフォーマットを自動実行するようにします。VSCode や IntelliJ のようなよくあるエディタの挙動ですね。

ここでは、拡張機能を導入して解決します。

Format on Save - Visual Studio Marketplace

導入するだけで、保存時に自動的にコードクリーンナップが実行されるようになります。
コードクリーンナップ内ではデフォルトでIDE内蔵フォーマッタが走り、IDE内蔵フォーマッタは clang-format と EditorConfig のコンフィグがある場合はそれらを走らせる、という挙動になっています。なお、実行順番は EditorConfig → clang-format になっており、コンフリクトした設定項目がある場合、後勝ちします。

フォーマットが通っているか検査する

フォーマットが通っていないファイルがレポジトリに混入しないことを保証しましょう。
よくあるのは CI でフォーマッタを回すか、Git Hooks で pre-commit Hook で蹴ってしまう(保証にはなっていないが)ことです。

今回は、GitHub Actions を使ってフォーマッタを回してみます。

clang-format を GitHub Actions 上で走らせる

ubuntu-latest ランナーには clang-format がデフォルトで入っている [1] ので、一瞬で実現できます。
今回は、 .clang-format ルールにそぐわないファイルがあった場合に Fail するワークフローを定義してみました。

.github/workflows/clang-format.yml
name: "clang-format"

on:
  push:
  pull_request:

jobs:
  check-format:
    name: "Run clang-format"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: "Run clang-format"
        run: find . -regextype posix-extended -regex ".*\.(c|cpp|h|hpp)" | xargs -IX clang-format --Werror --dry-run X

これで、CI 上で clang-format を走らせることができました。

clang-format.png

EditorConfig がうまく通っているかを GitHub Actions 上でチェックする

今回は Windows Native での開発が前提になるので、文字コード・改行コードのブレがないかもチェックしておきたいところです。そこで、先ほど設定した EditorConfig に活躍してもらうことにします。

実現方法について触れます。

まず、EditorConfig はエディタの拡張機能であり、公式の CLI ツールがありません。
そこで、editorconfig-checker という、各ファイルが EditorConfig のルールに従っているかをチェックする趣旨の CLI ツールを使います。

editorconfig-checker/editorconfig-checker: A tool to verify that your files are in harmony with your .editorconfig

まず、editorconfig-checker 自体のコンフィグを書いていきます。
特に重要なのが Exclude で、素のままだとあらゆるファイルに対してチェックを走らせてしまうので、フォーマッタが通っていなくてもよいファイルを例外としておきます。

.ecrc
{
  "Verbose": false,
  "IgnoreDefaults": false,
  "Exclude": [
    "^\\.ecrc$",
    "\\.sln$",
    "\\.vcxproj$",
    "\\.vcxproj\\.filters$",
    "Resource\\.rc$",
    "^<siv3d-project-dir>/Engine"
  ],
  "SpacesAfterTabs": false,
  "Disable": {
    "EndOfLine": false,
    "Indentation": false,
    "IndentSize": false,
    "InsertFinalNewline": false,
    "TrimTrailingWhitespace": false,
    "MaxLineLength": false
  }
}

次に、EditorConfig のルールに従わないファイルがあった場合に Fail するワークフローを定義していきます。
editorconfig-checker は公式の Action が存在するので、すぐに書くことができます。

.github/workflows/editorconfig.yml
name: "editorconfig-checker"

on:
  push:
  pull_request:

jobs:
  check-format:
    name: "Run editorconfig-checker"
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: editorconfig-checker/action-editorconfig-checker@main

      - name: "Run editorconfig-checker"
        run: editorconfig-checker

これで、EditorConfig がうまく通っているかを GitHub Actions 上でチェックすることができました。

脚注
  1. https://github.com/actions/runner-images#software-and-image-support ↩︎

usagigausagiga

CLion Nova をつかう

キーマップや操作感が JetBrains ライクなほうが好みだったので、CLion Nova を使うことにしました。

記事にもありますが、CLion Nova は ReSharper C++ / Rider のエンジンを流用した IDE で、AppCode 向けのレガシーな CLion を置き換えるために開発されています。

ここでは、若干トリッキーな使い方にはなりますが、CLion Nova で VS2019 の Windows Native App な設定を構築してみます。

Open Project Wizard

clion-open-project-wizard.png

プロジェクトを開くと、その時点で導入されている開発環境を選択するウィザードが開かれます。以下のような環境があります:

  • MinGW で CMake を使うもの(CLion Nova に Bundle されている)
  • Visual Studio の VC++ などを使うもの

ここでは、VC++ Compiler を使いたいので、Visual Studio 2019 の開発環境を設定しておきます。

フォーマッタ関連の設定

これらのプラグインを導入していてコンフィグも存在しているときは、CLion はすべての Code Style の設定を EditorConfig や clang-format のものでオーバーライドするという仕組みになっています。

なお、Visual Studio 2019 と違い、EditorConfig や clang-format の間で衝突する設定項目があった場合にも不穏な動作をせず、うまく競合を解決してフォーマットを実行してくれます。とてもモダンですね。

保存時の自動フォーマットは、Settings の中にある Actions on Save から設定可能です。

clion-actions-on-save.png

いろいろなものをトリガーすることができますが、ここでは Reformat と Import の最適化のみ実施することにします。

ビルド設定

CLion Nova は vcxproj を読んでくれないので、ビルドはイチから設定してやる必要があります。

デフォルトだと、CMake を前提としているので、CMakeLists や make を作ってあげることになります。

TBU

補完の設定

Siv3D のライブラリ群を補完してあげるように設定してあげます。

(たぶん↑をやってあげると、勝手に Siv3d.hpp にぶらさがってるやつが External Libraries に追加されて補完がきくようになるはず)

TBU

usagigausagiga

GitHub Codespaces をつかう

ふとしたときにコードを編集したくなったときのために、
メインマシンの開発環境とは別に、Codespaces (Visual Studio Code for the Web) を使えるようにしておきます。

Codespaces の設定をする

Codespaces は特にコンフィグを書かなくても動いてくれます。
しかし、毎度同じような環境を構築するのは面倒なので、コンフィグを書いておきましょう。

まず、Codespaces をプリセットの状態で作成し、内部の VSCode で C++ 向けの Dev Container を作っておきます。
そうすると、.devcontainer ディレクトリが切られ、 Dockerfiledevcontainer.json が自動的につくられると思いますので、それをベースに編集していきます。

手始めに、コンテナ作成と同時に VSCode に clang-format と EditorConfig が入っている拡張機能のインストールをやってもらうことにします。

.devcontainer/
{
  "name": "C++",
  "build": {
    "dockerfile": "Dockerfile"
  },
  "customizations": {
    "vscode": {
      "extensions": [
        "ms-vscode.cpptools",
        "EditorConfig.EditorConfig"
      ]
    }
  }
}

次に、VSCode で Format On Save が動くようにしておきます。

.vscode/settings.json
{
  "editor.formatOnSave": true
}

これで、他の投稿に書いたような Visual Studio / CLion Nova のようなフォーマッタが整いました。

Siv3D のライブラリを補完できるようにする

TBU

これが一番大事な気がするけれど、書ければよいというところを優先したので、そのうちじぶんのなかで需要がでてきたときにやります~