システム概要
ジェネレータアーキテクチャ
generate.ts - エントリーポイント
ジェネレータのメインファイルです。コマンドライン引数を解析し、プロジェクト生成を制御します。
// コマンドライン引数の解析
const args = parseArgs(Deno.args, {
boolean: ["help", "with-git"],
string: ["name", "author", "version", "output"],
default: {
name: "MyApp",
author: "Your Name",
version: "1.0.0",
},
});
// プロジェクト設定の構築
const config: ProjectConfig = {
name: projectName,
nameLower: toSnakeCase(projectName),
nameUpper: nameLower.toUpperCase(),
author: args.author,
version: args.version,
outputDir: args.output || projectName.toLowerCase(),
withGit: args["with-git"],
};
templates.ts - テンプレート生成
各ファイルのテンプレートを生成する関数群です。プロジェクト設定に基づいて動的にコンテンツを生成します。
// CMakeLists.txt の生成例
export function generateCMakeLists(config: ProjectConfig): string {
return `cmake_minimum_required(VERSION 3.15)
project(${config.name} VERSION ${config.version} LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
...
`;
}
Deno URL実行の仕組み
Denoは deno run <url> でリモートのTypeScriptを直接実行できます。
これにより、ユーザーはツールをインストールせずにジェネレータを使用できます。
URL指定で実行
deno run https://...generate.ts
自動ダウンロード
Denoがスクリプトと依存関係をダウンロード
ローカル実行
ローカルファイルシステムにプロジェクト生成
ビルドシステムアーキテクチャ
build.ts - ビルドスクリプト
Denoとdaxを使用したクロスプラットフォームビルドスクリプトです。
import $ from "jsr:@david/dax@0.42.0";
// CMake設定
async function configure(): Promise<void> {
await $`mkdir -p build`;
await setupFileAPI("build");
await $`cmake -B build -DCMAKE_BUILD_TYPE=${args.config}`;
}
// ビルド実行
async function build(): Promise<BuildArtifact[]> {
await $`cmake --build build --config ${args.config}`;
const artifacts = await parseFileAPI("build");
return artifacts;
}
dax の特徴
-
クロスプラットフォーム
-
$`mkdir -p`がWindowsでも動作 - テンプレートリテラル - 変数の安全な埋め込み
- エラーハンドリング - コマンド失敗時の自動例外スロー
- パイプ・リダイレクト - シェルライクな操作が可能
CMake File API連携
CMake File API v1 を使用して、ビルド成果物の情報をプログラマティックに取得します。 これにより、ハードコードされたパスに依存せず、プラットフォームやジェネレータに応じた 正しいパスを自動検出できます。
仕組み
1. Query作成
build/.cmake/api/v1/query/codemodel-v2 に空ファイルを作成
2. CMake実行
CMake設定時にQueryを検出し、Replyを生成
3. Reply解析
build/.cmake/api/v1/reply/ のJSONファイルをパース
Reply構造
// cmake-types.ts より
interface FileAPIIndex {
cmake: { version: {...} };
objects: Array<{ kind: string; jsonFile: string; }>;
reply: {
[key: string]: { kind: string; jsonFile: string; };
};
}
interface CodeModelV2 {
paths: { source: string; build: string; };
configurations: Array<{
name: string;
targets: Array<{ name: string; jsonFile: string; }>;
}>;
}
interface TargetInfo {
name: string;
type: "EXECUTABLE" | "STATIC_LIBRARY" | "SHARED_LIBRARY";
artifacts?: Array<{ path: string; }>;
}
利点
- Visual Studio / Unix Makefiles / Ninja など、どのジェネレータでも動作
- Debug / Release などのビルドタイプを自動認識
- 生成されたすべてのターゲット(実行ファイル、ライブラリ)を自動検出
C++プロジェクト構造
ターゲット構成
静的ライブラリ: [project]_core
add_library(myapp_core STATIC
src/core/core.cpp
src/core/core.h
)
内部リンク用の静的ライブラリ。バイナリに直接リンクされます。
共有ライブラリ: [project]_utils
add_library(myapp_utils SHARED
src/utils/utils.cpp
src/utils/utils.h
)
target_compile_definitions(myapp_utils
PRIVATE MYAPP_UTILS_EXPORTS)
動的リンクライブラリ。Windows DLLエクスポートマクロを含みます。
実行ファイル: [project]
add_executable(myapp src/main.cpp)
target_link_libraries(myapp PRIVATE
myapp_core
myapp_utils
)
両方のライブラリを使用するメインアプリケーション。
Windows DLLエクスポート
Windows環境では、共有ライブラリのシンボルを適切にエクスポート/インポートする必要があります:
// utils.h
#ifdef _WIN32
#ifdef MYAPP_UTILS_EXPORTS
#define MYAPP_UTILS_API __declspec(dllexport)
#else
#define MYAPP_UTILS_API __declspec(dllimport)
#endif
#else
#define MYAPP_UTILS_API
#endif
MYAPP_UTILS_API void myFunction();
依存関係
| パッケージ | バージョン | 用途 |
|---|---|---|
| @david/dax | 0.42.0 | クロスプラットフォームシェルコマンド実行 |
| @std/cli | 1.0.6 | コマンドライン引数解析 |
| @std/path | 1.0.8 | パス操作 |
| @std/fs | 1.0.8 | ファイルシステム操作 |
すべての依存関係は JSR (JavaScript Registry) から取得されます。 Denoは実行時に自動的にダウンロード・キャッシュします。
セキュリティモデル
Denoはデフォルトでセキュアです。ジェネレータは必要最小限の権限のみを要求します:
| 権限 | フラグ | 用途 |
|---|---|---|
| ファイル読み取り | --allow-read |
既存ディレクトリの確認 |
| ファイル書き込み | --allow-write |
プロジェクトファイルの生成 |
| コマンド実行 | --allow-run |
git init の実行(オプション) |
build.ts は --allow-all を使用します。
これはCMakeやコンパイラの実行に必要な権限を包括的に付与するためです。