タイトル長いけどわかったので書きます。
概要
- NuGet v2 / v3 の違い
- UAP10.0 の NuGet package ロード順
- NuGet packgage の作成
- まとめ
1. NuGet v2 / v3 の違い
まず、NuGet package をローカルでテストするわけですけど、まずこの違いに引っ掛かった。v2 時代はソリューション フォルダー直下に packages
っていうフォルダーが作られてそこに package が一時保存されるわけですが、v3 時代は %UserProfile%\.nuget\packages\
にインストールされる。
自分は勘違いしていたのですが、csproj
の有無で packages
がどこのものを参照するのか変わるのかと思っていたのですが、実は project.json
に依存するようです。このあたりテスト中は注意が必要ですね。
2. UAP10.0 の NuGet package ロード順
UAP10.0 つまり UWP に関しては v3 の挙動をするので、ロード順はめちゃくちゃっぽくて、通常今までのやり方に即していると win81
と uap10.0
の両方の targets ファイルを読み込んでしまうようです。これにより、両方の winmd
と dll
が通ったり、VCLibs
が Version = 12 のモノを読み込んでしまってえらいことになります。
そこでハイブリッド型では win81 側の targets に win81
から読んでも問題ないような細工を施して uap10.0
から問題ないようロードできるようにします。
3. NuGet packgage の作成
3.1 ファイル構成
新時代基準の構成に伴い win81
や wpa81
の構成も見直しています。
※ フォルダー下の一部は同一構成なので省略しています
+ build | + native | | + XYZ.targets | | | + win81 | + wpa81 | + uap10.0 | | + lib | + win81 | | + XYZ.winmd | | | + wpa81 | + uap10.0 | + runtimes + win81-x86 | + native | + XYZ.dll | + win81-x64 + win81-ARM + wpa81-x86 + wpa81-ARM + win10-x86 + win10-x64 + win10-ARM
3.2 native な targets 実装
割とシンプルです。このケースは一ファイルに全部記述する感じになります。
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <Mntone-Platform Condition="'$(Platform)' == 'Win32'">x86</Mntone-Platform> <Mntone-Platform Condition="'$(Platform)' != 'Win32'">$(Platform)</Mntone-Platform> </PropertyGroup> <PropertyGroup Condition="'$(PlatformToolset)'=='v120'" Label="win81"> <Mntone-FrameworkFolder>win81</Mntone-FrameworkFolder> </PropertyGroup> <PropertyGroup Condition="'$(PlatformToolset)'=='v120_wp81'" Label="wpa81"> <Mntone-FrameworkFolder>wpa81</Mntone-FrameworkFolder> </PropertyGroup> <PropertyGroup Condition="'$(PlatformToolset)'=='v140'" Label="uwp"> <Mntone-FrameworkFolder>uap10.0</Mntone-FrameworkFolder> <Mntone-RuntimeFolder>win10</Mntone-RuntimeFolder> </PropertyGroup> <PropertyGroup Condition="'$(Mntone-RuntimeFolder)'==''" Label="uwp"> <Mntone-RuntimeFolder>$(Mntone-FrameworkFolder)</Mntone-RuntimeFolder> </PropertyGroup> <Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences"> <ItemGroup> <Reference Include="$(MSBuildThisFileDirectory)..\..\lib\$(Mntone-FrameworkFolder)\Mntone.WinRtLibrary.winmd"> <Implementation>Mntone.WinRtLibrary.dll</Implementation> </Reference> <ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)..\..\runtimes\$(Mntone-RuntimeFolder)-$(Mntone-Platform)\native\Mntone.WinRtLibrary.dll" /> </ItemGroup> </Target> </Project>
3.3 win81 な targets 実装
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Target Name="CheckAnyCPU" Condition="'$(Platform)' != 'x64' AND '$(Platform)' != 'x86' AND '$(Platform)' != 'ARM'" BeforeTargets="BeforeBuild"> <Error Text="Mntone WinRT Library does not support the $(Platform) target platform." /> </Target> <Target Name="CheckJS" Condition=" '$(MSBuildProjectExtension)' == '.jsproj' " BeforeTargets="BeforeBuild"> <Error Text="Mntone WinRT Library does not support the JavaScript target project." /> </Target> <Target Name="InjectReference" BeforeTargets="ResolveAssemblyReferences"> <ItemGroup Condition="'$(TargetPlatformIdentifier)' != 'UAP'"> <Reference Include="$(MSBuildThisFileDirectory)..\..\lib\win81\Mntone.WinRtLibrary.winmd"> <Implementation>Mntone.WinRtLibrary.dll</Implementation> </Reference> <ReferenceCopyLocalPaths Include="$(MSBuildThisFileDirectory)..\..\runtimes\win81-$(Platform)\native\Mntone.WinRtLibrary.dll" /> </ItemGroup> </Target> <ItemGroup Condition="'$(TargetPlatformIdentifier)' != 'UAP'"> <SDKReference Include="Microsoft.VCLibs, Version=12.0"> <Name>Microsoft Visual C++ 2013 Runtime Package for Windows</Name> </SDKReference> </ItemGroup> </Project>
ここで特殊なのは Condition="'$(TargetPlatformIdentifier)' != 'UAP'"
という条件を加えていることです。これで UWP における win81\.targets
が読み込まれてコンパイルがうまくいかない問題を回避します。
3.4 その他
3.3 の UAP 判別条件を外したものを適応すればおkです。
4. まとめ
C++/CX を使った Windows Runtime component を書く人はかなり少ないと思います。ですが、C++/CX を使ってやりたいことは多々あるはずですが、この類のブログ記事ってのはあまり存在しないわけで。
.NET だけなら構成がもっとシンプルで targets ファイルですら不要なものもあるわけです。
今回は csproj, vbproj, vcxproj の Windows ストア アプリ、Windows Phone ストア アプリ (Appx-based)、UWP のハイブリッド NuGet package を作るというお話でした。C++/CX を使ってカスタムコントロールを作るとかそういうのにはこのパッケージ作成方法は欠かせないので、頭の片隅に入れておいてもいいと思います。
以上です。