はじめに
競プロ用のプロジェクトテンプレートを整備したので、dotnet newのカスタムテンプレート作成の備忘録です。
dotnet new のカスタムテンプレートとは
公式の情報はこちら
.NETのプロジェクトを作成する際、dotnetコマンドを利用してプロジェクトを生成します。
例えば、コンソールアプリケーションを作成する場合、
dotnet new console -n Sample
のようなコマンドを実行することで、Sampleという名称のプロジェクトが作成されます。
これは、dotnet newコマンドで、consoleというデフォルトテンプレートを使ってプロジェクトを生成するという意味になります。
このdotnet newコマンドに、プロジェクトやスクリプトをカスタムテンプレートとして登録しておくことで、プロジェクトやファイルの作成を使いまわすことができます。
既定のテンプレートとして、dotnet newコマンドに-l|--listオプションをつけて実行すると、現在インストールされているdotnet newコマンドで生成できるテンプレートを確認することができます。
dotnet new -l
作ってみる
テンプレートの基本として、テンプレート化したいプロジェクトのディレクトリ下に、.template.configのディレクトリを作成し、さらにその下に、template.jsonを作成します。
そして、template.jsonにプロパティを設定し、dotnet newコマンドを使ってインストールすることで、テンプレートを使うことができるようになります。
dotnet new -i path-to-template
競技プロ用のプロジェクトテンプレートでは、次の3つをテンプレートとして準備します。
- プロジェクト
- 解答用のクラス
- テスト用のクラス
プロジェクトのテンプレート
プロジェクトでは、解答用のクラスとテスト用クラスを配置するための骨組みとしてのプロジェクトを生成するようにします。
Template.Project/
|
|- Tasks/
| |
| |- Tasks.csproj
|
|- Tests/
| |
| |- Tester.cs
| |- Tests.csproj
|
|- Template.Project.sln
このプロジェクトをベースとして、Project/下に.template.config/ディレクトリを作成し、その下にtemplate.jsonを作成します。
Template.Project/
|
|- .template.config
| |
| |- template.json
...
template.jsonでは、次のメンバを記述します。
| メンバ | 説明 |
|---|---|
$schema |
template.jsonのスキーマ |
author |
テンプレートの作成者 |
classfication |
テンプレートの種類 |
tags |
テンプレートのタグ |
identity |
テンプレートの識別子 |
name |
テンプレートの名前 |
shortName |
dotnet new で指定する際の名前 (例: dotnet new cpproj) |
sourceName |
テンプレート使用時に置き換える文字列 (dotnet newコマンドに、-n|--nameオプションで名前を指定することで、指定された文字列を全てその名前に置換することができます) |
preferNameDirectory |
出力先ディレクトリがない場合テンプレートのディレクトリを作成するか (既定値: false) |
例えば、上記のプロジェクトでは次のようなjsonを記述します。
{
"$schema": "http://json.schemastore.org/template",
"author": "AconCavy",
"classifications": [
"C#",
"Console"
],
"tags": {
"language": "C#",
"type": "project"
},
"name": "Template Project",
"identity": "AconCavy.Template.Project",
"shortName": "cpproj",
"sourceName": "Template.Project",
"preferNameDirectory": true
}
sourceNameに設定した文字列は、テンプレート以下のすべての対象の文字列が置換されるため、dotnet new cpproj -n Sampleを実行した場合、Template.Project/ディレクトリ、Template.Project.slnがSample/ディレクトリ、Sample.slnに置換されて生成されます。ファイル内の文字列も置換されるため注意が必要です。
この状態で、dotnet new -i path-to-templateコマンドでインストールし、dotnet new cpproj -n Sampleを実行することで、上記のプロジェクトテンプレートをもとに以下のようなプロジェクトが生成されます。
Sample/
|
|- Tasks/
| |
| |- Tasks.csproj
|
|- Tests/
| |
| |- Tester.cs
| |- Tests.csproj
|
|- Sample.sln
コマンドの追加オプション
また、Task.csprojとTests.csprojのターゲットフレームワークをテンプレート生成時に指定できるようにするため、dotnet new cpprojコマンドにオプションを追加します。
まず、.template.config下にdotnetcli.host.jsonを追加します。
symbolInfoメンバに、longNameのオプションにframeworkを、shortNameにfをもったFrameworkというメンバを追加します。
追加することで、dotnet new cpprojにオプションとして、-f|--frameworkのオプションを付与することができるようになります。
{
"$schema": "http://json.schemastore.org/dotnetcli.host",
"symbolInfo": {
"Framework": {
"longName": "framework",
"shortName": "f"
}
}
}
次にtemplate.jsonにsymbolsというメンバを追加し、ここに先ほど定義したFrameworkメンバを追加します。
ここではオプションの振る舞いを定義します。
今回はターゲットフレームワークを.NET 5と.NET Core 3.1を選択肢として定義します。
datatypeをchoiceにして、choicesに選択肢を定義します。
csprojのTargetFrameworkに指定する文字列として、.NET 5の場合はnet5.0、.NET Core 3.1の場合はnetcoreapp3.1をchoiceに設定します。
replacesに置換する文字列を、defaultValueにオプションを指定しない場合の文字列を設定します。
{
...
"symbols": {
"Framework": {
"type": "parameter",
"description": "The target framework for the project.",
"datatype": "choice",
"choices": [
{
"choice": "net5.0",
"description": "Target net5.0"
},
{
"choice": "netcoreapp3.1",
"description": "Target netcoreapp3.1"
}
],
"replaces": "netcoreapp3.1",
"defaultValue": "netcoreapp3.1"
}
},
...
}
そして、Tasks.csprojとTests.csprojのTargetFrameworkにreplacesで設定した文字列を設定します。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
...
<TargetFramework>netcoreapp3.1</TargetFramework>
...
</PropertyGroup>
...
</Project>
この状態で、dotnet new cpproj -n Sample -f net5.0を実行することで、TargetFrameworkにnet5.0が設定されたプロジェクトを生成することができます。
解答用のクラスとテスト用のクラスのテンプレート
単一のファイルのみ生成するように、テンプレートを構築します。
Template.Solver/
|
|- .template.config/
| |
| |- template.json
|
|- Template.Solver.cs
Template.Tests/
|
|- .template.config/
| |
| |- template.json
|
|- Template.TestsTests.cs
プロジェクトのテンプレートの作り方と同様に、template.jsonを記述しますが、単一ファイルのみ生成させるため、preferNameDirectoryを削除、またはfalseにします。
解答用のsourceNameをTemplate.Solverに、テスト用のsourceNameをTemplate.Testsにすることで、dotnet newコマンドの-n|--nameオプションにSampleを指定すると、それぞれSample.csとSampleTests.csが生成されます。
プロジェクトのパッケージ化
テンプレートが3つ用意できましたが、テンプレートをインストールする際にはそれぞれ個別にインストールが必要となります。
そのため、3つのテンプレートまとめて、1つのnugetパッケージを生成します。
3つのディレクトリを一つのディレクトリにまとめ、そのディレクトリと同じ階層にcsprojファイルを生成します。
CPTemplate/
|
|- content/
| |
| |- Template.Project/
| |- Template.Solver/
| |- Template.Tests/
|
|- CPTemplate.csproj
ディレクトリを整理したら、CPTemplate.csprojを編集し、ビルド情報を定義します。
| メンバ | 説明 |
|---|---|
PackageType |
nugetパッケージタイプ |
PackageVersion |
パッケージのバージョン |
PackageId |
パッケージの識別子 |
Title |
パッケージの名称 |
Authors |
パッケージの作成者 |
Description |
パッケージの説明 |
PackageTags |
パッケージのタグ |
TargetFramework |
パッケージをビルドするためのターゲットフレームワーク |
PackageProjectUrl |
プロジェクトURL |
IncludeBuildOutput |
ビルド時に生成されるファイルをパッケージに含めるか |
ContentTargetFolders |
パッケージ化するプロジェクトのルートがcontentかcontentFiles以外の場合は設定する |
Content |
パッケージに含めるファイルや除くファイルを設定する |
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<PackageType>Template</PackageType>
<PackageVersion>1.0</PackageVersion>
<PackageId>AconCavy.Templates</PackageId>
<Title>Templates</Title>
<Authors>AconCavy</Authors>
<Description>sample template.</Description>
<PackageTags>dotnet-new;templates;competitive-programming</PackageTags>
<TargetFramework>netcoreapp3.1</TargetFramework>
<PackageProjectUrl>https://github.com/AconCavy/CompetitiveProgrammingTemplateCSharp</PackageProjectUrl>
<IncludeBuildOutput>false</IncludeBuildOutput>
<ContentTargetFolders>content</ContentTargetFolders>
</PropertyGroup>
<ItemGroup>
<Content Include="content/**/*" Exclude="content/**/bin/**;content/**/obj/**" />
<Compile Remove="**/*" />
</ItemGroup>
</Project>
また、それぞれのテンプレートのtemplate.jsonにgroupIdentityを追加します。
// Project
"groupIdentity": "AconCavy.Templates.Project"
// Solver
"groupIdentity": "AconCavy.Templates.Solver"
// Tests
"groupIdentity": "AconCavy.Templates.Tests"
dotnet packコマンドを実行することでnugetパッケージを生成することができます。
dotnet pack
実行後、bin/Debug/下に{PackageId}.{PackageVersion}.nupkgが生成されます。
CPTemplate/
|
|- bin/
| |
| |- Debug/
| | |
| | |- AconCavy.Templates.1.0.0.nupkg
...
このnupkgをdotnet newコマンドでインストールすることで、3つのテンプレートを1回でインストールすることができます。
dotnet new -i ./bin/Debug/AconCavy.Templates.1.0.0.nupkg
まとめ
dotnet newのカスタムテンプレートの作り方と、テンプレートのパッケージ化の手順をまとめました。
- テンプレートのルートに
.template.configディレクトリを作成し、内にtemplate.jsonを作成する。 - テンプレートが複数ある場合は1つのディレクトリにまとめ、
dotnet packコマンドでパッケージ化する。