メインコンテンツまでスキップ

Extend Codegen CLI - テンプレートとデバッグ

Last updated on April 7, 2026

注釈:本資料はAI技術を用いて翻訳されています。

概要

このガイドでは、Extend Codegen CLI が OpenAPI 2.0 仕様から SDK コードを生成する方法について詳しく説明します。テンプレートエンジン、カスタムフィルター、デバッグツールを理解することで、問題のトラブルシューティングやコード生成プロセスのカスタマイズに役立てることができます。

この情報は、すべての SDK テンプレートパック(Unreal、Unity、Go など)に適用されます。これらはすべて AccelByte 固有の拡張を持つ同じ Jinja2 テンプレートエンジンを使用しています。

コード生成のワークフロー

Extend Codegen CLI の核心は、シンプルなテンプレートベースのコードジェネレーターです。2 つの入力を受け取り、1 つの出力を生成します。

Makefile が複数の生成を調整する方法

テンプレートパックで make all を実行すると、実際には異なるテンプレートと出力の組み合わせで Extend Codegen CLI を複数回呼び出しています。

# Unreal Makefile が行う処理の簡略例:

# 生成 1: モデルクラス
docker run ... renderc config.yaml \
--input spec/guild.json \
--template templates/operations-models.j2 \
--output Models/GuildModels.h

# 生成 2: クライアント API 宣言
docker run ... renderc config.yaml \
--input spec/guild.json \
--template templates/Client-operations-decl.j2 \
--output Api/GuildApi.h

# 生成 3: クライアント API 実装
docker run ... renderc config.yaml \
--input spec/guild.json \
--template templates/Client-operations-def.j2 \
--output Api/GuildApi.cpp

# ... ファイルタイプごとに続く

make ターゲットの基本:

  • 同じ入力 1: OpenAPI 仕様ファイル(例: guild.json
  • 異なる入力 2: 特定のテンプレートファイル(例: モデル用の operations-models.j2、ヘッダー用の Client-operations-decl.j2
  • 異なる出力: 適切なディレクトリの適切な名前のターゲットファイル
テンプレートパックの探索

SDK のコード生成がどのように機能するかを理解するには:

  1. accelbyte-unreal-sdk-template-pack.zip をダウンロードして展開する
  2. Makefile を開く — 各ターゲットがどのテンプレート、入力、出力ファイルを使用するかを示す
  3. templates/sdk_customization/ のテンプレートファイルを調べて Jinja2 構文を確認する
  4. テンプレートと生成された .h および .cpp ファイルを比較して変換を確認する

この実践的な探索が生成プロセスを理解する最良の方法です。

Jinja2 テンプレートエンジン

コード生成には、強力な Python テンプレート言語である Jinja2 を使用しています。

基本的なテンプレート構文

{# コメント - 出力には含まれない #}

{{ variable }} {# 変数の値を出力 #}

{% for item in items %} {# リストをループ #}
Process {{ item }}
{% endfor %}

{% if condition %} {# 条件ロジック #}
Do something
{% elif other_condition %}
Do something else
{% else %}
Default action
{% endif %}

{% set my_var = "value" %} {# 変数を設定 #}

{% import 'module.j2' as module %} {# 別テンプレートからマクロをインポート #}

{% macro func_name(params) %} {# 再利用可能なテンプレート関数を定義 #}
Macro content
{% endmacro %}

SDK テンプレートの例

Unreal SDK テンプレート(Client-operations-decl.j2)の実際の例:

{% import 'common/services.j2' as services -%}
{% set w_class_name = service.file_stem | to_pascal %}
{% set model_prefix = "FAccelByte" + service.file_stem | to_pascal %}

class ACCELBYTEUE4SDKCUSTOMIZATION_API {{ w_class_name }} : public Core::FApiBase
{
public:
{% for operation in operations %}
/**
* @brief {{ operation.summary }}.
*/
{% if operation.responses[0].field %}
{% set response_type = operation.responses[0].field | field_unreal_type(model_prefix) %}
THandler<{{ response_type }}> const& OnSuccess,
{% endif %}
{% endfor %}
};

これにより次のような C++ コードが生成されます:

class ACCELBYTEUE4SDKCUSTOMIZATION_API Guild : public Core::FApiBase
{
public:
/**
* @brief Create a new guild.
*/
THandler<FAccelByteGuildModelsCreateGuildResponse> const& OnSuccess,
};

カスタム Jinja2 フィルター

Extend Codegen CLI はコード生成のための豊富なカスタムフィルターを提供しています。これらのフィルターは OpenAPI 仕様のデータを言語固有のコードに変換します。

フィルターはいくつかのカテゴリに分類されます。

ケース変換フィルター

異なる命名規則(PascalCase、camelCase、snake_case、kebab-case など)の間で変換します。言語固有の命名規則に従ったコードを生成するために不可欠です。

使用例:

{% set class_name = service.file_stem | to_pascal %}
class {{ class_name }} {
// "guild_service" を "GuildService" に変換
}

一般的なフィルター: to_pascalto_camelto_snaketo_kebabto_sentenceto_title

言語固有の型フィルター

OpenAPI の型をターゲット言語の型に変換します。各 SDK(Unreal、Unity、Go など)は独自の型変換フィルターセットを持っています。

Unreal C++ フィルター:

  • 型変換: field_unreal_typeunreal_classunreal_enum_value
  • フォーマット: unreal_varunreal_enum_namefield_unreal_param
  • 検証: field_unreal_is_list_type

C#(Unity)フィルター:

  • 型変換: field_csharp_typecsharp_classcsharp_enum_value
  • フォーマット: csharp_propcsharp_varcsharp_enum_name
  • ジェネリック処理: csharp_generic_names

Go フィルター:

  • 型変換: field_go_typego_structgo_var

例:

{% for field in model.properties %}
{{ field | field_unreal_type("FAccelByte") }} {{ field.name | to_pascal }};
// 生成: FString GuildName;
{% endfor %}

文字列操作フィルター

コード生成のための文字列変換と操作:

  • 追加/削除: prefixsuffixaffixremoveprefixremovesuffix
  • 解析: splitstripsubstr
  • フォーマット: inquotes

正規表現フィルター

パターンマッチングとテキスト抽出:

  • 検索: regex_searchregex_findall
  • フィルター: alnumonlyalphaonlydigitonlynumericonly

ファイルとコンテンツのフィルター

テンプレートに外部コンテンツを含める:

  • filecontents - ファイルの内容全体を読み込む
  • filesnippet - ファイルから特定の行を抽出する

ユーティリティフィルター

汎用の変換フィルター:

  • コレクション: flattenmerge
  • 条件分岐: onlyifternaryboolean
  • 型処理: typenameto_csv

例生成フィルター

ドキュメントとテスト用のサンプルデータを作成:

  • create_example - OpenAPI スキーマに基づいてサンプル値を生成
  • create_example_json - JSON の例を生成
  • create_example_wsm - WebSocket メッセージの例を生成
ヒント

テンプレートパックのバージョンで利用可能なフィルターの完全なリストを確認するには、次のセクションで説明する --inspect verbose フラグを使用してください。

カスタムテンプレートを使ったデバッグと探索

コード生成を理解する最も強力な方法の一つは、独自のシンプルなテンプレートを作成し、利用可能なデータとフィルターを試してみることです。

テスト用の前提条件

テンプレートのレンダリングをテストしてデバッグするには、テンプレートパックから 3 つのものが必要です。

  1. config.yaml - テンプレートパックの設定(すべてのテンプレートパックに含まれています)
  2. OpenAPI 仕様 - API を記述する guild.json(または類似の)ファイル
  3. テンプレートファイル - 既存の .j2 ファイルまたは独自のカスタムテストテンプレート

テストテンプレートの作成

利用可能なデータを探索するための最小限のテンプレートを作成できます。test-template.j2 というファイルを作成します。

{# 利用可能なデータを探索するシンプルなテンプレート #}

サービス情報:
File Stem: {{ service.file_stem }}
Base Path: {{ service.base_path }}

操作数: {{ operations | length }}

最初の操作(存在する場合):
{% if operations %}
{% set op = operations[0] %}
Summary: {{ op.summary }}
Method: {{ op.method }}
Path: {{ op.path }}
{% endif %}

{# フィルターのテスト #}
フィルターのテスト:
to_pascal: {{ "hello_world" | to_pascal }}
to_camel: {{ "HelloWorld" | to_camel }}
to_snake: {{ "HelloWorld" | to_snake }}

テストテンプレートの実行

# 展開した accelbyte-unreal-sdk-template-pack/ ディレクトリ内から
docker run --rm \
-v "$(pwd)":"$(pwd)" \
-w "$(pwd)" \
accelbyte/extend-codegen-cli:0.0.28 renderc \
config.yaml \
--input /path/to/my-unreal-project/spec/guild.json \
--template test-template.j2

これにより、レンダリングされたテンプレートが標準出力に出力され、以下を確認できます。

  • 利用可能なデータ構造
  • 各オブジェクトが持つプロパティ
  • フィルターが値をどのように変換するか

詳細探索のための --inspect verbose

--inspect verbose フラグにより、完全なテンプレート環境が明らかになります。

# accelbyte-unreal-sdk-template-pack/ 内から
docker run --rm \
-v "$(pwd)":"$(pwd)" \
-w "$(pwd)" \
accelbyte/extend-codegen-cli:0.0.28 renderc \
config.yaml \
--input /path/to/my-unreal-project/spec/guild.json \
--template test-template.j2 \
--inspect verbose

--inspect verbose が表示する内容:

  1. 入力プロセッサー情報 - OpenAPI 仕様がどのように解析されるか
  2. 利用可能なフィルター - すべての Jinja2 フィルター(200 以上)と関数シグネチャの完全なリスト
  3. グローバル関数 - rangedictlipsum などの組み込み関数
  4. テスト関数 - is oddis definedis divisibleby などの条件
  5. テンプレートローダーパス - テンプレートが検索される場所
実践的なデバッグワークフロー
  1. シンプルに始める: 変数名を出力するだけの最小限のテンプレートを作成する
  2. データ構造を検査する: {{ variable }} を使用して各オブジェクトの内容を確認する
  3. フィルターをテストする: サンプルデータでさまざまなフィルターを試して出力を確認する
  4. 既存のテンプレートと比較する: テンプレートパックのテンプレートを参照して実際の使用例を確認する
  5. 検査出力を保存する: --inspect verbose > filters.txt を実行して後で参照できるようにする

探索用テンプレートの例:

{# デバッグテンプレート - 利用可能なすべてのデータを確認 #}
Service: {{ service }}
Operations: {{ operations }}
Models: {{ models }}

反復的なテンプレート開発

推奨アプローチ:

  1. テンプレートパックを展開してそのディレクトリに移動する
  2. 既存のテンプレートをコピーして出発点にする(例: operations-models.j2
  3. シンプルなテストケースを作成する - 1 つまたは 2 つのエンドポイントを持つ最小限の OpenAPI 仕様
  4. 変更してテストする - 小さな変更を加えてすぐに再実行する
  5. --inspect verbose を使用する - 特定のフィルターを見つけたり利用可能性を確認したりする必要があるとき

一般的なデバッグシナリオ

適切なフィルターを見つける:

# 検査出力を保存して検索する
docker run ... --inspect verbose > inspect.txt
grep "unreal" inspect.txt # Unreal 固有のフィルターを見つける
grep "to_" inspect.txt # ケース変換フィルターを見つける

フィルターの動作をテストする:

{# テストテンプレートを作成 #}
Original: guild_service
to_pascal: {{ "guild_service" | to_pascal }}
to_camel: {{ "guild_service" | to_camel }}
to_snake: {{ "GuildService" | to_snake }}

データ構造を理解する:

{# どのプロパティが存在するかを探索 #}
{% for operation in operations %}
Operation {{ loop.index }}:
Path: {{ operation.path }}
Method: {{ operation.method }}
Summary: {{ operation.summary }}
Parameters: {{ operation.parameters | length }}
{% endfor %}

設定ファイル(config.yaml

各テンプレートパックの config.yaml ファイルはレンダリングプロセスを設定します。

input_processor: 'accelbyte_codegen.ext.openapi2.legacy.OA2LegacyProcessor'
template_processor: 'textf'
renderer: 'accelbyte_codegen.ext.openapi2.legacy.OA2LegacyRenderer'
extension:
- '*jinja' # 標準 Jinja2 拡張機能
- 'accelbyte_codegen.ext.openapi2.legacy.OA2LegacyExtension' # カスタムフィルター
loader:
- './templates' # テンプレート検索パス
output: 'stdout'

主要なフィールド:

  • input_processor: OpenAPI 2.0 の解析を処理
  • renderer: 解析されたデータにテンプレートを適用
  • extension: カスタムフィルターと関数をロード
  • loader: テンプレートを検索するディレクトリ

一般的なデバッグシナリオ

生成されたコードの型が間違っている

問題: OpenAPI の integerint ではなく string を生成する。

デバッグ手順:

  1. OpenAPI 仕様を確認: フィールドが "type": "integer" として正しく定義されているか確認する
  2. --inspect verbose を使用して、ターゲット言語の正しい型変換フィルターを見つける
  3. テンプレートファイルを調べて、どのフィルターが適用されているかを確認する
  4. フィルターが正しいパラメーターで呼ばれているか確認する

名前空間が欠けているか間違っている

問題: 生成されたコードの名前空間またはパッケージ名が間違っている。

デバッグ手順:

  1. OpenAPI 仕様の basePath が正しいか確認する
  2. OpenAPI の info.title フィールドを確認する
  3. --inspect verbose を使用して名前空間関連のフィルターを検索する
  4. テンプレートが名前空間/パッケージ名をどのように構築するかを調べる

カスタムフィルターが機能しない

問題: テンプレートがフィルターを使用しているが、出力が間違っているか欠けている。

デバッグ手順:

  1. --inspect verbose を実行して、フィルターがテンプレートパックのバージョンに存在するか確認する
  2. テンプレートのフィルター名のスペルを確認する
  3. 入力データの型がフィルターが期待するものと一致しているか確認する(フィルターは文字列とオブジェクトで異なる動作をする場合がある)
  4. 最小限のテンプレートでテストして問題を切り分ける

テンプレートが見つからないエラー

問題: コード生成が "template not found" エラーで失敗する。

デバッグ手順:

  1. --inspect verbose を実行してテンプレートローダーパスを確認する
  2. テンプレートファイルが期待される場所に存在するか確認する
  3. テンプレートのファイル名またはパスのタイプミスを確認する
  4. Docker ボリュームマウントにテンプレートディレクトリが含まれているか確認する

テンプレートのカスタマイズ(上級)

テンプレートパックはそのまま使用できるように設計されていますが、特定のニーズに合わせてカスタマイズできます。

注意

テンプレートのカスタマイズにより、新しいテンプレートパックのバージョンへのアップグレードが困難になる場合があります。変更内容を丁寧にドキュメント化してください。

カスタマイズの手順

  1. テンプレートパックを展開する:

    unzip accelbyte-unreal-sdk-template-pack.zip
    cd accelbyte-unreal-sdk-template-pack/
  2. 変更するテンプレートを見つける:

    テンプレートは templates/sdk_customization/ にあります。

    • operations-decl.j2 - API クラスの宣言
    • operations-def.j2 - API クラスの実装
    • operations-models.j2 - モデル定義
  3. 変更を加える:

    上記のフィルターを使用して Jinja2 テンプレートファイルを編集します。

  4. 変更をテストする:

    make コマンドを実行して生成された出力を確認します。

  5. カスタマイズをドキュメント化する:

    将来の参照のために変更内容と理由を記録しておきます。

カスタマイズの例

すべての生成された API クラスにカスタムコメントを追加する:

{# operations-decl.j2 内 #}
class {{ w_class_name }} : public Core::FApiBase
{
// カスタムコメント: AccelByte Extend Codegen CLI によって生成
// OpenAPI ファイル: {{ service.file_stem }}.json
// 生成日時: {{ "now" | strftime("%Y-%m-%d") }}
public:
{% for operation in operations %}
...
{% endfor %}
};

追加リソース

まとめ

Extend Codegen CLI のテンプレートシステムを理解することで、以下が可能になります。

  • --inspect verbose を使用してコード生成の問題を効果的にデバッグする
  • Jinja2 テンプレートを通じて OpenAPI 仕様が生成されたコードにどのようにマッピングされるかを理解する
  • ターゲット言語とユースケースに適切なフィルターを使用する
  • 特定の要件に応じてテンプレートをカスタマイズする

Jinja2 の柔軟性と AccelByte の豊富なカスタムフィルターの組み合わせにより、単一の OpenAPI 仕様から複数のプログラミング言語と SDK をターゲットにできる強力なコード生成システムが実現します。