MSBuild のカスタムタスクをNuGet パッケージ化してC++ プロジェクトに組み込む - 見切り発車

見切り発車

とりあえずかきとめたい

MSBuild のカスタムタスクをNuGet パッケージ化してC++ プロジェクトに組み込む

MSBuild のカスタムタスクをC++ のvcxproj に組み込む方法として、以前の記事ではImport Project を手動で記述するというのを紹介しました。

C++ をclang で解析するときに情報をvcxproj から取得する方法

その後、NuGet パッケージとして組み込む方法についても確認し、そちらの方がシンプルでよさそうなので以下で紹介します。

NuGet パッケージの組み込み形式について

NuGet パッケージの組み込み形式には、PackageReference 形式とpackages.config 形式の2つがあります。

PackageReference 形式はプロジェクトファイルの中にパッケージの情報を含める方法です。これはVisual Studio 2017 バージョン 15.7 以降から利用可能になったpackages.config 形式よりも新しい形式です。

packages.config から PackageReference への移行

上記のリンク先にも書いてある通り、見た目がシンプルになったり、グローバルパッケージフォルダーが利用されることでパッケージ管理のパフォーマンスが向上するなどの利点がありますが、C++ のプロジェクトでは利用できません。

packages.config 形式はNuGet パッケージの情報をvcxproj ファイルとは別のファイルで管理し、パッケージの内容はソリューションごとに用意されたpackages フォルダにダウンロードして展開されます。また、NuGet パッケージごとのプロパティなどの定義が含まれるprops ファイル、targets ファイルなどがある場合はvcxproj にImport 要素を含めておく必要があります。しかしC++ プロジェクトでは現在のところpackages.config 形式を利用するしかありません。

vcxproj へのNuGet パッケージのインストール

チュートリアルに従って作成したカスタムタスクのNuGet パッケージをvcxproj に組み込むのは、Visual Studio IDE のNuGet パッケージマネージャーを利用すれば簡単に実行できます。

チュートリアル: コード生成用のカスタム タスクを作成する

NuGet パッケージマネージャーからカスタムタスクのNuGet パッケージを選択してインストールを実行すると、ソリューションのpackages フォルダへの展開、packages.config の作成・更新、必要に応じてvcxproj へのImport 要素の追加も行われます。

NuGet パッケージマネージャー

packages.config

props ファイルのImport

targets ファイルのImport

パッケージソースの設定

NuGet パッケージをパッケージマネージャーのリストから選択するためには、パッケージソースとして設定されている場所にnupkg ファイルを置いておきます。ローカルファイルシステムにおいてあるnupkg ファイルを利用したい場合、Visual Studio のメニューで「ツール」->「NuGet パッケージマネージャー」->「パッケージマネージャー設定」からウィンドウを開き、NuGet パッケージマネージャーの「パッケージソース」で登録しておくこともできますが、ソリューションファイルと同じ階層にnuget.config ファイルを置いてプロジェクト固有のパスを指定することもできます。

NuGet パッケージマネージャーのパッケージソースの設定

<configuration>
  <packageRestore>
    <add key="enabled" value="true" />
    <add key="automatic" value="true" />
  </packageRestore>
  <packageSources>
    <add key="local" value="../MyCustomTask/bin/Debug" />
  </packageSources>
</configuration>

NuGet パッケージのインストール手段の注意点

NuGet パッケージはパッケージマネージャーからインストールするほか、nuget.exe clidotnet cli などのコマンドラインツールからインストールすることもできますが、NuGet パッケージマネージャー以外のコマンドラインツールを利用した場合はvcxproj からprops ファイル、targets ファイルを参照するためのImport 要素は追加されません。これについては別途情報をまとめます。

まとめ

開発したカスタムタスクを配布する場合、NuGet パッケージを利用したほうが利便性が高そうですが、vcxproj で利用する場合には新しくて便利なPackageReference 形式は利用できないことも分かりました。また、これまで古いほうのpackages.config 形式の知識しかなかったのですがPackageReference 形式になるとdll やprops, targets ファイルがソリューション、プロジェクトのフォルダに展開されずに戸惑い、いろいろと調べて情報をアップデートするいい機会になりました。