nupkgファイルを作成する C++native版②

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

前回の記事で、

tera1707.com

nupkgの作り方を知ったが、x64固定、Releaseビルド固定だった。
これを、nupkgが使われるときのx64/x86Debug/Releaseでそれぞれ切り替えるようにしたい。

やったこと

条件切り分けのための条件Condition.propsファイルとtargetsファイルに追記し、nuspecに、それぞれの出力ファイル(dll/lib)を追記する。

以下のようにする。

propsファイル

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <!-- Debug + x86 -->
  <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug' and '$(Platform)'=='Win32'">
    <ClCompile>
      <AdditionalIncludeDirectories>
        $(MSBuildThisFileDirectory)..\..\include;%(AdditionalIncludeDirectories)
      </AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <AdditionalLibraryDirectories>
        $(MSBuildThisFileDirectory)..\..\lib\native\x86\Debug;%(AdditionalLibraryDirectories)
      </AdditionalLibraryDirectories>
      <AdditionalDependencies>
        DllTest.lib;%(AdditionalDependencies)
      </AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>

  <!-- Release + x86 -->
  <ItemDefinitionGroup Condition="'$(Configuration)'=='Release' and '$(Platform)'=='Win32'">
    <ClCompile>
      <AdditionalIncludeDirectories>
        $(MSBuildThisFileDirectory)..\..\include;%(AdditionalIncludeDirectories)
      </AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <AdditionalLibraryDirectories>
        $(MSBuildThisFileDirectory)..\..\lib\native\x86\Release;%(AdditionalLibraryDirectories)
      </AdditionalLibraryDirectories>
      <AdditionalDependencies>
        DllTest.lib;%(AdditionalDependencies)
      </AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>

  <!-- Debug + x64 -->
  <ItemDefinitionGroup Condition="'$(Configuration)'=='Debug' and '$(Platform)'=='x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>
        $(MSBuildThisFileDirectory)..\..\include;%(AdditionalIncludeDirectories)
      </AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <AdditionalLibraryDirectories>
        $(MSBuildThisFileDirectory)..\..\lib\native\x64\Debug;%(AdditionalLibraryDirectories)
      </AdditionalLibraryDirectories>
      <AdditionalDependencies>
        DllTest.lib;%(AdditionalDependencies)
      </AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>

  <!-- Release + x64 -->
  <ItemDefinitionGroup Condition="'$(Configuration)'=='Release' and '$(Platform)'=='x64'">
    <ClCompile>
      <AdditionalIncludeDirectories>
        $(MSBuildThisFileDirectory)..\..\include;%(AdditionalIncludeDirectories)
      </AdditionalIncludeDirectories>
    </ClCompile>
    <Link>
      <AdditionalLibraryDirectories>
        $(MSBuildThisFileDirectory)..\..\lib\native\x64\Release;%(AdditionalLibraryDirectories)
      </AdditionalLibraryDirectories>
      <AdditionalDependencies>
        DllTest.lib;%(AdditionalDependencies)
      </AdditionalDependencies>
    </Link>
  </ItemDefinitionGroup>
</Project>

targetsファイル

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <!-- Debug + x86 -->
  <ItemGroup Condition="'$(Configuration)'=='Debug' and '$(Platform)'=='Win32'">
    <None Include="$(MSBuildThisFileDirectory)..\..\lib\native\x86\Debug\DllTest.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>

  <!-- Release + x86 -->
  <ItemGroup Condition="'$(Configuration)'=='Release' and '$(Platform)'=='Win32'">
    <None Include="$(MSBuildThisFileDirectory)..\..\lib\native\x86\Release\DllTest.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>

  <!-- Debug + x64 -->
  <ItemGroup Condition="'$(Configuration)'=='Debug' and '$(Platform)'=='x64'">
    <None Include="$(MSBuildThisFileDirectory)..\..\lib\native\x64\Debug\DllTest.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>

  <!-- Release + x64 -->
  <ItemGroup Condition="'$(Configuration)'=='Release' and '$(Platform)'=='x64'">
    <None Include="$(MSBuildThisFileDirectory)..\..\lib\native\x64\Release\DllTest.dll">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
  </ItemGroup>

</Project>

nuspecファイル

<?xml version="1.0"?>
<package>
  <metadata>
    <id>DllTest</id>
    <version>1.0.4</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\x86\Debug\*.dll" target="lib\native\x86\Debug" />
    <file src="lib\native\x86\Debug\*.lib" target="lib\native\x86\Debug" />
    <file src="lib\native\x86\Release\*.dll" target="lib\native\x86\Release" />
    <file src="lib\native\x86\Release\*.lib" target="lib\native\x86\Release" />
    <file src="lib\native\x64\Debug\*.dll" target="lib\native\x64\Debug" />
    <file src="lib\native\x64\Debug\*.lib" target="lib\native\x64\Debug" />
    <file src="lib\native\x64\Release\*.dll" target="lib\native\x64\Release" />
    <file src="lib\native\x64\Release\*.lib" target="lib\native\x64\Release" />
    <file src="build\native\*.props" target="build\native" />
    <file src="build\native\*.targets" target="build\native" />
  </files>
</package>

ビルド・nupkgフォルダに配置するためのバッチファイル

Debug/Release、x86/x64で、それぞれビルドを行い、nupkg\libフォルダのそれぞれのフォルダに成果物dllを格納するようにした。

※Azureなどのパイプラインを使ってビルドするときは、この辺の内容はyamlなどに書くのだと思う。

@echo off
chcp 932
setlocal

call "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\VsDevCmd.bat"

cd %~dp0

REM === 1. nuget.exe を同じ階層にダウンロード ===
set NUGET_URL=https://dist.nuget.org/win-x86-commandline/latest/nuget.exe
set NUGET_EXE=%~dp0nuget.exe
set DLLPJPATH=%~dp0DllTest\DllTest.vcxproj

if not exist "%NUGET_EXE%" (
    echo Downloading nuget.exe...
    powershell -Command "Invoke-WebRequest -Uri %NUGET_URL% -OutFile '%NUGET_EXE%'"
) else (
    echo nuget.exe already exists.
)


REM === ビルド実施後、必要成果物ファイルをnupkg フォルダにコピー ===
xcopy /Y /S /I  "%~dp0DllTest\DllTest.h" "%~dp0nupkg\include\"

MSBuild %DLLPJPATH% /t:clean;rebuild /p:Configuration=Release;Platform="x64"
xcopy /Y /S /I "%~dp0DllTest\x64\Release\*.dll" "%~dp0nupkg\lib\native\x64\Release\"
xcopy /Y /S /I "%~dp0DllTest\x64\Release\*.lib" "%~dp0nupkg\lib\native\x64\Release\"

MSBuild %DLLPJPATH% /t:clean;rebuild /p:Configuration=Release;Platform="Win32"
xcopy /Y /S /I "%~dp0DllTest\Release\*.dll" "%~dp0nupkg\lib\native\x86\Release\"
xcopy /Y /S /I "%~dp0DllTest\Release\*.lib" "%~dp0nupkg\lib\native\x86\Release\"

MSBuild %DLLPJPATH% /t:clean;rebuild /p:Configuration=Debug;Platform="x64"
xcopy /Y /S /I "%~dp0DllTest\x64\Debug\*.dll" "%~dp0nupkg\lib\native\x64\Debug\"
xcopy /Y /S /I "%~dp0DllTest\x64\Debug\*.lib" "%~dp0nupkg\lib\native\x64\Debug\"

MSBuild %DLLPJPATH% /t:clean;rebuild /p:Configuration=Debug;Platform="Win32"
xcopy /Y /S /I "%~dp0DllTest\Debug\*.dll" "%~dp0nupkg\lib\native\x86\Debug\"
xcopy /Y /S /I "%~dp0DllTest\Debug\*.lib" "%~dp0nupkg\lib\native\x86\Debug\"

REM === nupkg フォルダ内の DllTest.nuspec を使って nupkg を作成 ===
set NUSPEC=%~dp0nupkg\DllTest.nuspec

if exist "%NUSPEC%" (
    echo Packing NuGet package...
    "%NUGET_EXE%" pack "%NUSPEC%" -OutputDirectory "%~dp0nupkg"
    echo Done.
) else (
    echo ERROR: DllTest.nuspec not found in nupkg folder.
)

endlocal

echo nuget.exeの出すNU5128:は、nativeのみのライブラリなら無視してOK。

pause

参考

Common MSBuild project items
targetsファイル内の「None」などの項目の仕様

https://learn.microsoft.com/en-us/visualstudio/msbuild/common-msbuild-project-items?view=visualstudio

MSBuild items
Noneの中の「Include」などの項目の仕様

https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-items?view=vs-2022

Item definitions
x86/x64で切り替えるときに使う「Condition」の書き方

https://learn.microsoft.com/en-us/visualstudio/msbuild/item-definitions?view=vs-2022