.NET プロジェクト SDK

.NET Core および .NET 5.0 以降のプロジェクトは、ソフトウェア開発キット (SDK) に関連付けられています。 各 "プロジェクト SDK" は、MSBuild ターゲットと、コードのコンパイル、パッキング、発行を行う関連する タスクのセットです。 プロジェクト SDK を参照するプロジェクトは、"SDK スタイルのプロジェクト" と呼ばれることもあります。

使用可能な SDK

次の SDK を利用できます。

ID 説明 リポジトリ
Microsoft.NET.Sdk .NET SDK https://github.com/dotnet/sdk
Microsoft.NET.Sdk.Web .NET Web SDK https://github.com/dotnet/sdk
Microsoft.NET.Sdk.BlazorWebAssembly .NET Blazor WebAssembly SDK
Microsoft.NET.Sdk.Razor .NET Razor SDK
Microsoft.NET.Sdk.Worker .NET Worker Service SDK
Microsoft.NET.Sdk.WindowsDesktop .NET デスクトップ SDK。これには Windows フォーム (WinForms) と Windows Presentation Foundation (WPF) が含まれています。* https://github.com/dotnet/winforms および https://github.com/dotnet/wpf

.NET SDK は、.NET の基本 SDK です。 その他の SDK からは .NET SDK が参照され、その他の SDK に関連付けられているプロジェクトでは、すべての .NET SDK プロパティが使用可能になります。 たとえば、Web SDK は、.NET SDK と Razor SDK の両方に依存しています。

NuGet を使用して配布できる独自の SDK を作成することもできます。

* .NET 5.0 以降、Windows フォームおよび Windows Presentation Foundation (WPF) プロジェクトでは、Microsoft.NET.Sdk.WindowsDesktop ではなく .NET SDK (Microsoft.NET.Sdk) を指定する必要があります。 これらのプロジェクトでは、TargetFrameworknet5.0-windows に、UseWPF または UseWindowsFormstrue に設定することで、Windows デスクトップ SDK が自動的にインポートされます。 プロジェクトで .NET 5.0 以降をターゲットとし、Microsoft.NET.Sdk.WindowsDesktop SDK を指定すると、ビルド警告 NETSDK1137 が表示されます。

プロジェクト ファイル

.NET プロジェクトは、MSBuild 形式に基づいています。 プロジェクト ファイルは、C# プロジェクトでは .csproj、F# プロジェクトでは .fsproj のような拡張子が付いていて、XML 形式です。 MSBuild プロジェクト ファイルのルート要素は、Project 要素です。 Project 要素には、使用する SDK (およびバージョン) を指定する省略可能な Sdk 属性があります。 .NET ツールを使用してコードをビルドするには、Sdk 属性を、「使用可能な SDK」の表にあるいずれかの ID に設定します。

<Project Sdk="Microsoft.NET.Sdk">
  ...
</Project>

NuGet から取得した SDK を指定するには、名前の末尾にバージョンを含めるか、global.json ファイルに名前とバージョンを指定します。

<Project Sdk="MSBuild.Sdk.Extras/2.0.54">
  ...
</Project>

SDK を指定する別の方法として、トップレベルの SDK 要素を使用する方法があります。

<Project>
  <Sdk Name="Microsoft.NET.Sdk" />
  ...
</Project>

これらの方法のいずれかで SDK を参照すると、.NET のプロジェクト ファイルが大幅に簡素化されます。 プロジェクトの評価中に、MSBuild によってプロジェクト ファイルの先頭に Sdk.props の暗黙的なインポートと、末尾に Sdk.targets の暗黙的なインポートが追加されます。

<Project>
  <!-- Implicit top import -->
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
  ...
  <!-- Implicit bottom import -->
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
</Project>

ヒント

Windows コンピューターでは、Sdk.props ファイルと Sdk.targets ファイルは %ProgramFiles%\dotnet\sdk\[バージョン]\Sdks\Microsoft.NET.Sdk\Sdk フォルダーにあります。

プロジェクト ファイルの前処理

MSBuild では、dotnet msbuild -preprocess コマンドを使用して、SDK とそのターゲットが取り込まれた後の完全に展開されたプロジェクトがどのようになるかを確認できます。 dotnet msbuild コマンドの preprocess スイッチによって、インポートされるファイル、そのソース、ビルドに対するそのコントリビューションが、実際にプロジェクトをビルドすることなく、表示されます。

プロジェクトにターゲット フレームワークが複数存在する場合は、1 つのフレームワークだけにコマンドの結果を集中させてください。そのためには、そのフレームワークを MSBuild プロパティとして指定します。 次に例を示します。

dotnet msbuild -property:TargetFramework=netcoreapp2.0 -preprocess:output.xml

既定で含まれるものと除外されるもの

Compile 項目埋め込みリソースNone 項目に既定で含まれるものと除外されるものが SDK で定義されています。 SDK 以外の .NET Framework プロジェクトとは異なり、既定値がほとんどの一般的なユース ケースに対応しているため、これらの項目をプロジェクト ファイルで指定する必要はありません。 この動作により、プロジェクト ファイルのサイズがより小さく、より簡単に理解できるようになり、必要に応じて手作業で編集できます。

次の表は、.NET SDK に組み込まれる、および除外される要素と glob の一覧を示します。

要素 含まれる glob 除外される glob glob の削除
Compile **/*.cs (または他の言語拡張機能) **/*.user; **/*.*proj; **/*.sln; **/*.vssscc N/A
EmbeddedResource **/*.resx **/*.user; **/*.*proj; **/*.sln; **/*.vssscc N/A
None **/* **/*.user; **/*.*proj; **/*.sln; **/*.vssscc **/*.cs; **/*.resx

注意

./bin フォルダーと ./obj フォルダーは、$(BaseOutputPath)$(BaseIntermediateOutputPath) の MSBuild プロパティによって表され、既定で glob から除外されます。 除外されるものは、DefaultItemExcludes プロパティによって表されます。

.NET デスクトップ SDK には、さらに多くの WPF に含まれるものと除外されるものが含まれています。 詳細については、「WPF に含まれるものと除外されるもの」を参照してください。

ビルド エラー

これらの項目をプロジェクト ファイルに明示的に定義すると、次のような "NETSDK1022" ビルド エラーが発生する可能性があります。

重複する 'Compile' 項目が含まれていました。 .NET SDK には、既定でプロジェクト ディレクトリの 'Compile' 項目が含まれています。 これらの項目をプロジェクト ファイルから削除するか、プロジェクト ファイルに明示的に含める場合は 'EnableDefaultCompileItems' プロパティを 'false' に設定することができます。

重複する 'EmbeddedResource' 項目が含まれていました。 .NET SDK には、既定でプロジェクト ディレクトリの 'EmbeddedResource' 項目が含まれています。 これらの項目をプロジェクト ファイルから削除するか、プロジェクト ファイルに明示的に含める場合は 'EnableDefaultEmbeddedResourceItems' プロパティを 'false' に設定することができます。

このエラーを解決するには、次のいずれかの操作を行います。

  • 前の表に列挙されている暗黙的な項目と一致する明示的な CompileEmbeddedResource、または None の項目を削除します。

  • 暗黙的なファイルの組み込みをすべて無効にするには、EnableDefaultItems プロパティfalse に設定します。

    <PropertyGroup>
      <EnableDefaultItems>false</EnableDefaultItems>
    </PropertyGroup>
    

    アプリで発行する一部のファイルを指定する必要がある場合は、そのために既知の MSBuild のしくみ (たとえば Content 要素) を引き続き使用できます。

  • CompileEmbeddedResource、または None glob のみを選択的に無効にするには、EnableDefaultCompileItemsEnableDefaultEmbeddedResourceItems、または EnableDefaultNoneItems のプロパティを false に設定します。

    <PropertyGroup>
      <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
      <EnableDefaultEmbeddedResourceItems>false</EnableDefaultEmbeddedResourceItems>
      <EnableDefaultNoneItems>false</EnableDefaultNoneItems>
    </PropertyGroup>
    

    Compile glob のみを無効にすると、Visual Studio のソリューション エクスプローラーに *.cs 項目がプロジェクトの一部として (None 項目として組み込まれて) 引き続き表示されます。 暗黙的な None glob を無効にするには、EnableDefaultNoneItemsfalse に設定します。

暗黙的なパッケージ参照

.NET Core 1.0 から 2.2 または .NET Standard 1.0 から 2.0 をターゲットとする場合、.NET SDK により、特定の メタパッケージ への暗黙的な参照が追加されます。 メタパッケージは、他のパッケージの依存関係のみで構成されるフレームワーク ベースのパッケージです。 メタパッケージは、プロジェクト ファイルの TargetFramework または TargetFrameworks プロパティで指定されたターゲット フレームワークに基づいて暗黙的に参照されます。

<PropertyGroup>
  <TargetFramework>netcoreapp2.1</TargetFramework>
</PropertyGroup>
<PropertyGroup>
  <TargetFrameworks>netcoreapp2.1;net462</TargetFrameworks>
</PropertyGroup>

必要に応じて、DisableImplicitFrameworkReferences プロパティを使用して暗黙的なパッケージ参照を無効にし、必要なフレームワークまたはパッケージのみに明示的な参照を追加することができます。

推奨事項:

  • .NET Framework、.NET Core 1.0 から 2.2、または .NET Standard 1.0 から 2.0 をターゲットとする場合は、プロジェクト ファイルの <PackageReference> アイテム経由で Microsoft.NETCore.App または NETStandard.Library メタパッケージを明示的に参照しないようにします。 .NET Core 1.0 から 2.2 および .NET Standard 1.0 から 2.0 のプロジェクトの場合、このようなメタパッケージは暗黙的に参照されます。 .NET Framework プロジェクトの場合、.NET Standard ベースの NuGet パッケージを使用する場合、何らかのバージョンの NETStandard.Library が必要であれば、NuGet はそのバージョンを自動的にインストールします。
  • .NET Core 1.0 から 2.2 をターゲットとする場合、特定バージョンのランタイムが必要であれば、メタパッケージを参照するのではなく、プロジェクト内で <RuntimeFrameworkVersion> プロパティを使用します (1.0.4 など)。 たとえば、自己完結の配置を使用している場合は、1.0.0 LTS ランタイムの特定のパッチ バージョンが必要になることがあります。
  • .NET Standard 1.0 から 2.0 をターゲットとする場合、特定バージョンの NETStandard.Library メタパッケージが必要であれば、<NetStandardImplicitPackageVersion> プロパティを使用し、必要なバージョンを設定できます。

ビルド イベント

SDK スタイルのプロジェクトでは、PreBuild または PostBuild という名前の MSBuild ターゲットを使用し、PreBuildBeforeTargets プロパティまたは AfterTargetsPostBuild プロパティを設定します。

<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="&quot;$(ProjectDir)PreBuildEvent.bat&quot; &quot;$(ProjectDir)..\&quot; &quot;$(ProjectDir)&quot; &quot;$(TargetDir)&quot;" />
</Target>

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
   <Exec Command="echo Output written to $(TargetDir)" />
</Target>

注意

  • MSBuild ターゲットには任意の名前を使用できます。 ただし、PreBuild および PostBuild ターゲットは Visual Studio IDE によって認識されるため、これらの名前を使用することにより、IDE でコマンドを編集できます。
  • $(ProjectDir) などのマクロが解決されないため、SDK スタイルのプロジェクトでは、プロパティ PreBuildEventPostBuildEvent は推奨されません。 たとえば、次のようなコードはサポートされません。
<PropertyGroup>
  <PreBuildEvent>"$(ProjectDir)PreBuildEvent.bat" "$(ProjectDir)..\" "$(ProjectDir)" "$(TargetDir)"</PreBuildEvent>
</PropertyGroup>

ビルドのカスタマイズ

ビルドをカスタマイズするには、さまざまな方法があります。 プロパティを引数として msbuild または dotnet コマンドに渡すことによって、プロパティをオーバーライドすることができます。 また、プロパティをプロジェクト ファイルに追加することや、Directory.Build.props ファイルに追加することができます。 .NET プロジェクトの便利なプロパティの一覧については、「.NET SDK プロジェクトの MSBuild リファレンス」をご覧ください。

カスタム ターゲット

.NET プロジェクトでは、プロジェクトで使用するカスタムの MSBuild ターゲットとプロパティをパッケージ化し、そのパッケージをプロジェクトで使用することができます。 この種の拡張機能を使用するのは、次の場合です。

  • ビルド処理を拡張する。
  • ビルド プロセスの成果物 (生成されたファイルなど) にアクセスする。
  • どのような構成でビルドが呼び出されるかを検査する。

カスタムのビルド ターゲットまたはプロパティを追加するには、プロジェクトの build フォルダーに <package_id>.targets または <package_id>.props の形式のファイル (たとえば Contoso.Utility.UsefulStuff.targets) を配置します。

次の XML は .csproj ファイルからのスニペットです。パッケージ化する対象を dotnet pack コマンドに指示しています。 <ItemGroup Label="dotnet pack instructions"> 要素で、パッケージ内の build フォルダーにターゲット ファイルを配置します。 <Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles"> 要素で、アセンブリと .json ファイルを build フォルダーに配置します。

<Project Sdk="Microsoft.NET.Sdk">

  ...
  <ItemGroup Label="dotnet pack instructions">
    <Content Include="build\*.targets">
      <Pack>true</Pack>
      <PackagePath>build\</PackagePath>
    </Content>
  </ItemGroup>
  <Target Name="CollectRuntimeOutputs" BeforeTargets="_GetPackageFiles">
    <!-- Collect these items inside a target that runs after build but before packaging. -->
    <ItemGroup>
      <Content Include="$(OutputPath)\*.dll;$(OutputPath)\*.json">
        <Pack>true</Pack>
        <PackagePath>build\</PackagePath>
      </Content>
    </ItemGroup>
  </Target>
  ...

</Project>

プロジェクトでカスタム ターゲットを使用するには、パッケージとそのバージョンを指す PackageReference 要素を追加します。 ツールとは異なり、カスタム ターゲットのパッケージは、それを使用するプロジェクトの依存関係クロージャに含まれます。

カスタム ターゲットの使用方法を構成できます。 それは MSBuild ターゲットであるため、指定されたターゲットに依存することや、別のターゲットの後に実行したり、dotnet msbuild -t:<target-name> コマンドを使用して手動で呼び出したりすることができます。 ただし、優れたユーザー エクスペリエンスを提供するために、プロジェクトごとのツールとカスタム ターゲットを組み合わせることができます。 このシナリオでは、必要なすべてのパラメーターをプロジェクトごとのツールで受け取り、受け取ったパラメーターを、ターゲットを実行する必要な dotnet msbuild の呼び出しに変換します。 このような相乗効果のサンプルは、dotnet-packer プロジェクトの「MVP Summit 2016 Hackathon samples」 (MVP Summit 2016 ハッカソンのサンプル) レポートで参照することができます。

関連項目