ねののお庭。

かりかりもふもふ。

.NET Coreにおけるローカルなnugetパッケージの使い方とその参照の持ち方。

.NET Core におけるローカルでのnugetパッケージの使い方。

パッケージ、作っておくと何かと楽ですよね。dllの直接参照なんて嫌です。 nuget.orgにアップロードしておくとなんも考えないでいいのですが、まぁpublicな場所にupできない場合って結構あると思います。

じゃぁローカルのパッケージに作ったパッケージどうやって使うのというとそれはstack overflow に書いてあるとおり、

nuget add ../whatever/lib/MyPackage.1.0.0.nupkg -Source ./packages

dotnet add package MyPackage -s ./packages

の一連のコマンドを実行すればとりあえずパケージを参照することはできるようになります。

コマンドの解説。

コマンドが何をやっているか、雑に書いておきます。 まずはじめにclasslibなどの.csprojなどがあるところで

dotnet pack -c Release ./

とかでpackします。 すると

./bin/Release/MyPackage.nuget

./bin以下に.nugetファイルが出来上がります。(こいつは実際のところただのzipで、unzipするとdllとか必要な情報が入ったものが出てきます。) でこいつを直接dotnet add packageとかで参照しようとしてもそれはできません。ここらへんはパッケージをよしなに参照してもらうために

nuget add ../whatever/lib/MyPackage.1.0.0.nupkg -Source ./packages

などとして、packagesディレクトリ内に参照する際のディレクトリ形式を整備してもらったり、必要なファイルを生成してもらったりします。 このディレクトリを参照するべく、参照したい側のプロジェクトで

dotnet add package MyPackage -s ./packages

とするとめでたくパッケージが使えるようになるわけです。

本題(参照とかがどうなってるのか)

ようやく本題です。

dotnet add package MyPackage -s ./packages

というコマンドを売ったときどういうふうに参照されるようになっているのかが気になるポイントです(私は気になった). このコマンドを叩くと、csprojには以下のようにPackageReferenceが追加されます。

<ItemGroup>
    <PackageReference Include="MyPackage" Version="1.0.0" />
</ItemGroup>

このPackageReference、別に先程addしたパッケージの直接の参照を持っていなさそうです。直接参照しているなら、なんらかの形でパッケージのパスを書き込まれていそうなものです。が、実際に書き込まれたのは名前とバージョン情報だけです。

試しに、雑に先程packしたプロジェクトに関数を追加し、もう一度pack,nuget addしてみて、dotnet add packageした側のプロジェクトでclasslib側に追加した関数を呼んでみると、そんな関数ないぞ!とコンパイラさんに怒られます。 やはり直接参照はしていなさそうです。 コンソールアプリだと、.csprojとMainのあるProgram.csしかありませんし、そこに対した情報がないことはわかったので、そこでちゃんとdotnet add packageがちゃんとできて、ビルドが通った場合のbin以下を覗いてみます。

するとPackTest.runtimeconfig.dev.jsonに

{
  "runtimeOptions": {
    "additionalProbingPaths": [
      "/Users/neno/.dotnet/store/|arch|/|tfm|",
      "/Users/neno/.nuget/packages",
      "/usr/local/share/dotnet/sdk/NuGetFallbackFolder"
    ]
  }
}

とか書いてるものがあります(環境はMac,nenoは私のユーザ名)。"additionalProbingPaths"。 完全に名前がそれっぽいですね。 参照先はここっぽい。"/Users/neno/.nuget/packages"を覗いてみると、先程packしたMyPackage.nugetが存在することがなんと確認できます。パッケージを追加したとき、どうやらここを参照していそうです。 しかし、いつの間に.nuget/以下に配置されたのでしょうか。。。

それは

dotnet add package MyPackage -s ./packages

でパッケージを追加したタイミングで、.nuget/以下に配置され、そこから参照するようになるようです。

まとめ

dotnet add package MyPackage -s ./packages すると、しれっと.nuget/配下にパッケージが配置されて、そこから参照されるようになるらしい。決してプロジェクトがあるディレクトリにコピーとかされたりしないし、パスで直接パッケージの参照を持ったりしない。

追記(2021/01/14)

ちなみに一番最初にnugetコマンドを叩いていますが、dotnetコマンドだけで完結することもできます。

まず最初に、nugetパッケージが置かれる場所(source)の設定を追加します。 (最後に追加したものを消す方法も紹介します。) どうやら相対パスはダメで、絶対パスじゃないといけないっぽい。

dotnet nuget add source C:\somewhere -n local_source

-nではsourceの名前の設定をしてます。省略してもいいですが、日本語の環境だとパッケージ ソース 1とかいう日本語だしスペースあるし、という嫌な名前を付けられるので設定したほうが良いです。この名前は他のコマンドでsourceを指定する際に使います。 このタイミングで

dotnet nuget list source

とかすると、nuget.orgのほかに追加したsourceが登録されていることがわかります。

そして、次にdotnet packで作成したパッケージをsourceに登録します。

 dotnet nuget push ../somewhere/MyPackage.1.0.0.nupkg -s local_source

で、使う際には

dotnet add package MyPackage -s local_source

とかすると、参照してくれます。 dotnet add packageした時点でsourceにあったものが$HOME/.nuget/packagesにコピー/配置される挙動は同じです。 -s local_sourceといのは無くてもsourceが有効の場合は問題なく参照してくれますが、明示的な方が気持ちよいでしょう。

ちなみに追加したソースがいらなくなった場合は

dotnet nuget remove source local_source

とかするとちゃんと消えてくれます。また、登録はそのままに、無効にしたいだけの場合は

dotnet nuget disable source local_source

で出来ます。