C/C++ で作成された外部の DLL を C# から扱うためのラッパーを作成して NuGet パッケージとして公開しようとしていたのですが、その外部 DLL 自体も NuGet パッケージに含める方法について調べてみました。
環境
- Visual Studio 2017
- .NET Core 2.2
方法
ググってみるとまさにそのものが書いてある以下のページが見つかりました。
しかし、これだけではいろいろはまったので、追記・補足しておきます。
PackagePath について
出力先となる PackagePath
のディレクトリ名には lib
を指定する必要があるようです。
指定しなかった場合、以下の警告が表示されました。
warning NU5100: The assembly 'foo.dll' is not inside the 'lib' folder and hence it won't be added as a reference when the package is installed into a project. Move it into the 'lib' folder if it needs to be referenced.
さらに、lib
だけだと以下のエラーが表示されました。
warning NU5103: The folder 'lib/foo.dll' under 'lib' is not recognized as a valid framework name or a supported culture identifier. Rename it to a valid framework name or culture identifier.
lib
の下にはフレームワーク名またはカルチャー名のディレクトリを指定する必要があるみたいです。
<ItemGroup>
<Content Include="foo.dll" Pack="true" PackagePath="lib\netstandard2.0" />
</ItemGroup>
また、 このフレームワーク名またはカルチャー名以下の階層が、作成した DLL と同じ階層に作られるようです。
例えば、作成した DLL が sample.dll
だとして、外部の DLL を以下のように設定してパッケージに含めた場合、
<ItemGroup>
<Content Include="foo\x64\foo.dll" Pack="true" PackagePath="lib\netstandard2.0\foo\x64" />
<Content Include="foo\x86\foo.dll" Pack="true" PackagePath="lib\netstandard2.0\foo\x86" />
</ItemGroup>
NuGet パッケージインストール後の配置は以下のようになります。
- sample.dll
- foo\x64\foo.dll
- foo\x86\foo.dll
外部 DLL を出力ディレクトリにコピー
外部 DLL を出力ディレクトリにコピーするには、Visual Studio で該当の DLL を右クリックし、出力ディレクトリにコピー
の項目を 新しい場合はコピーする
(または 常にコピーする
) に設定しておく必要があります。
手動で .csproj
ファイルを修正する場合は以下を追加します。
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
publish 時に出力先ディレクトリに外部 DLL がコピーされない
この外部 DLL を含んだ NuGet パッケージを使っているアプリケーションにおいて、dotnet publish
コマンドを実行しても外部 DLL が出力先の publish
ディレクトリにコピーされませんでした。
publish
時に出力ディレクトリに外部 DLL をコピーするためには、まずライブラリ側(NuGet パッケージにするほう)の .csproj
ファイルに以下を追加します。
<PackageCopyToOutput>true</PackageCopyToOutput>
しかし、これを PackagePath
で lib
を指定している箇所に指定しても上手くいきませんでした。
PackagePath
を指定しなかった場合、該当のファイルはコンテンツとして追加されるようなので、そこに PackageCopyToOutput
を設定すると上手くいきました。
具体的には以下のような感じです。
<Content Include="foo\x64\foo.dll" Pack="true">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
<Content Include="foo\x86\foo.dll" Pack="true">
<PackageCopyToOutput>true</PackageCopyToOutput>
</Content>
これが一番はまりました。
最終的に作成した設定
上記を踏まえ、最終的に .csproj
ファイルの設定は以下のようになりました。
<ItemGroup>
<Content Include="foo\x64\foo.dll" Pack="true" PackagePath="lib\netstandard2.0\foo\x64" />
<Content Include="foo\x86\foo.dll" Pack="true" PackagePath="lib\netstandard2.0\foo\x86" />
<Content Include="foo\x64\foo.dll" Pack="true">
<PackageCopyToOutput>true</PackageCopyToOutput>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="foo\x86\foo.dll" Pack="true">
<PackageCopyToOutput>true</PackageCopyToOutput>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
参考 URL
- https://blog.okazuki.jp/entry/2019/09/28/145646
- https://docs.microsoft.com/ja-jp/nuget/reference/msbuild-targets
- https://docs.microsoft.com/ja-jp/nuget/consume-packages/package-references-in-project-files
- https://stackoverflow.com/questions/42862739/how-to-copy-files-to-output-directory-from-a-referenced-nuget-package-in-net-co
- https://docs.microsoft.com/ja-jp/nuget/reference/nuspec