もくじ
https://tera1707.com/entry/2022/02/06/144447
やりたいこと
C++のdllをnupkgにして、C++のexeのコードから使いたい。
実験コード
今回実験で作成したコードは下記。
やったこと
やったこと概要
- 指定のフォルダ構成を作成し、
- その中にpropsファイルとtargetsファイルを作成し、配置する
- specファイルを作成し、配置する
nuget.exe pack <nuspecファイル>コマンドで、nupkgを固める
ということをする。
登場人物
フォルダ構成
下記のような構成のフォルダを作成する。
※「DllTest」というライブラリ名だとする。
DllTest.nuspec include\DllTest.h lib\native\DllTest.dll lib\native\DllTest.lib build\native\DllTest.props build\native\DllTest.targets
※.hやdll、libは、必要な数だけ、includeフォルダ、libフォルダに配置する。
今回実験で作成したコードだと、以下のフォルダがそれ。
プロジェクトの中に、そういう階層構造のフォルダを作成した。
https://github.com/tera1707/CppDllTemplate/tree/main/nupkg
ライブラリ名.props
.props ファイルは、
「プロジェクトが参照されたときに適用される初期設定」を追加するファイル。
主に インクルードパスやライブラリパスの追加など、コンパイル前に必要な環境を整える。
C++のライブラリの場合はbuild\native\フォルダに配置する。
→初期設定を注入してくれるファイル。
今回の実験の例
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemDefinitionGroup> <ClCompile> <!-- include フォルダを自動追加 --> <AdditionalIncludeDirectories> $(MSBuildThisFileDirectory)..\..\include;%(AdditionalIncludeDirectories) </AdditionalIncludeDirectories> </ClCompile> <Link> <!-- lib フォルダをライブラリ検索パスに追加 --> <AdditionalLibraryDirectories> $(MSBuildThisFileDirectory)..\..\lib\native;%(AdditionalLibraryDirectories) </AdditionalLibraryDirectories> <!-- 必要な .lib を追加 --> <AdditionalDependencies> DllTest.lib;%(AdditionalDependencies) </AdditionalDependencies> </Link> </ItemDefinitionGroup> </Project>
- パッケージを使う側のプロジェクトの設定(vcxproj)に対して、
- パッケージの中にある.hファイルを置いてある場所を「追加のインクルードフォルダ」に登録して、
- パッケージの中にあるlibファイルが置いてある場所を「追加のlib参照先フォルダ」に登録して、
- なんのlibを見るか、
の設定をしている。
ライブラリ名.targets
- .targets ファイルは、
「ビルドの過程で適用される処理や動作」を追加するファイル。
主に DLL のコピーや追加ビルド手順など、ビルド後に必要なアクションを実行する。
C++のライブラリの場合は、propsと同じくbuild\native\フォルダに配置する。
→ビルド動作を注入するファイル。
今回の実験の例
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> <None Include="$(MSBuildThisFileDirectory)..\..\lib\native\DllTest.dll"> <Link>DllTest.dll</Link> <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> </None> </ItemGroup> </Project>
パッケージの中にあるdllファイルを、出力先フォルダにコピーしますよ、という設定。
nuspecファイル
nupkgの情報が詰まったファイル。
「このパッケージはどういうもので、どんなファイルを含んでいて、どう使われるべきか」を宣言するファイル。
- パッケージのメタ情報(ID、バージョン、作者、説明など)
- 含めるファイルの一覧(DLL、LIB、ヘッダ、props/targets など)
- 依存関係の定義(他のパッケージに依存する場合) ※今回の実験では←はやってない
上のフォルダ構成に、propsとtargetsを配置して、nuspecを書いてフォルダ構成の一番topに置き、
そのnuspecをnuget.exe packコマンドに食わすと、nupkgができる。
今回の実験の例
<?xml version="1.0"?> <package> <metadata> <id>DllTest</id> <version>1.0.2</version> <authors>MyName</authors> <owners>MyOrg</owners> <requireLicenseAcceptance>false</requireLicenseAcceptance> <description>C++ DLL library package Test</description> </metadata> <files> <file src="include\*.h" target="include" /> <file src="lib\native\*.dll" target="lib\native" /> <file src="lib\native\*.lib" target="lib\native" /> <file src="build\native\*.props" target="build\native" /> <file src="build\native\*.targets" target="build\native" /> </files> </package>
★注意★
nuspecで指定するパッケージのID(上のnuspecでいうところの「<id>DllTest</id>」の部分)に付けるIDと、.propsファイル名、.targetsファイル名は同じでないといけない。
この記事ではやってないのだが、nuget.exe push で、nugetホストにuploadするときに、はじかれたりしたことがある。
地味に注意。
今回の実験コード 参考情報
今回、ソリューションのtopフォルダに、「nupkg」というフォルダを作成し、 その中身を上の「フォルダ構成」に沿うような形にした。
.props、.targetsファイルは、build\native\フォルダの中に置き、gitにも登録するのだが、
lib\native\の中に置く/dllや.libは、DllTestのプロジェクトをビルドしたときの「ビルド後イベント」で、
出力されたdllやlibを、そのフォルダにコピーするようにした。
参考までに、ビルド後イベントに下記のようなコピーのためのバッチを入れている。
xcopy /Y /S /I "$(OutDir)*.dll" "$(SolutionDir)nupkg\lib\native" xcopy /Y /S /I "$(OutDir)*.lib" "$(SolutionDir)nupkg\lib\native" xcopy /Y /S /I "$(ProjectDir)DllTest.h" "$(SolutionDir)nupkg\include"
→このパッケージを利用する側がコードを書く際/ビルドする際に必要になる.hファイルとlibファイル、動くときに必要になるdllファイルを、nupkgのフォルダにコピーしている。
その他 参考情報
今回、x64でのみ動けばよかったので、「フォルダ構成」の中に、x64フォルダなどは出てこなくてよかった。 ただそれをわけたいとき(x64/x86で分けたいとき、Debug/Releaseでわけたいとき)には、またやり方があるっぽい。 (WindowsのCopilotが、そういうやり方がありますよ、試してみますか?と聞かれたが、今回はやらなかった)
下の「参考」のdocにもその内容が書かれているようなので、そこを見るか、copilotに聞くとよいかもしれない。
参考
フォルダ構成をどうすればいいか?
nuspecファイルの書き方
targetsファイル、propsファイルの書き方
https://learn.microsoft.com/ja-jp/nuget/concepts/msbuild-props-and-targets