アズタケの開発日誌

備忘録を兼ねて作ってしまいました。さて、今回は何日坊主になるか・・・

CoreRTで外部ライブラリを使用する際に詰まった件

(新年)初投稿です。
相当期間が開いてしまいましたが…

.NetNativeがどこまで使用できるかをリサートしている時に、外部ライブラリの参照で詰まったのでメモ程度に書き残しておきます。
昔のバージョンのdotnet cliではそのまま --native をつけることによりネイティブでビルド出来ていたようですが、今は分離されているようです。
github.com

この記事ではVisual Studio 2017をビルドツールとして使用しています。
また、CoreRTをクローンしてきてCドライブ直下に展開しています(書きやすくするため)

まずは結論から。
CoreRTのビルドがReleaseだろうが、アプリケーションのビルドがReleaseだろうが、外部ライブラリはDebugである必要があるみたい。おそらく方法はあると思うのでわかり次第記事にします

どうやらReleaseビルドでかつ、awaitを外部ライブラリで使用しているとこの問題が起きる模様。サンプル作成しました
github.com

PS C:\corert> .\build.cmd vs2017

このようにvs2017をつけることによりVisual Studio 2017 RCを使用してデバッグビルドでビルドさせることを*1明示しています。尚この記載が無く、Visual Studio 2015がインストールされていない場合はビルドが行われません。
ビルドが終わるまで結構時間がかかるので待ちましょう。日本語環境だとUnicodeの関係でテストに失敗するのが現れますが気にしない方針で行きます。

まずはここのテンプレートを見ながらcsprojを生成していじってみます。
安易な考えで

<Project ToolsVersion="15.0">
  <Import Project="$(MSBuildSDKsPath)\Microsoft.NET.Sdk\Sdk\Sdk.props" />
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
  	<PackageReference Include="<社内ライブラリ>.Context">
      <Version>0.1.0-alpha-000022</Version>
      <PrivateAssets>All</PrivateAssets>
    </PackageReference>
  </ItemGroup>
  <Import Project="$(MSBuildSDKsPath)\Microsoft.NET.Sdk\Sdk\Sdk.targets" />
  <Import Project="$(IlcPath)\Microsoft.NETCore.Native.targets" />
</Project>

のようにして、Program.csでテストコードでも書いてビルドを行ってみます。
ここで行うビルドは、Visual Studio についてる開発者コマンドプロンプトを使いましょう。x64でビルドしたらx64の開発者コマンドプロンプトを使用してください。

C:\Users\azuta\Downloads\dtnt\corerttest>dotnet restore /p:IlcPath=C:\corert\bin\Product\Windows_NT.x64.Debug\packaging\publish1
dotnet build /t:LinkNative /p:IlcPath=C:\corert\bin\Product\Windows_NT.x64.Debug\packaging\publish1

これでビルドは通るはずです(執筆時点)

Microsoft (R) Build Engine version 15.1.545.13942
Copyright (C) Microsoft Corporation. All rights reserved.

  corerttest -> C:\Users\azuta\Downloads\dtnt\corerttest\bin\x64\Debug\netcoreapp1.1\corerttest.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:24.11

結果の表示で.dllとなっているのは気にせず、そのまま bin\x64\Debug\netcoreapp1.1\native\ を見てみるとexeとpdbだけの2つが存在します。

試しにこのまま実行しようとしてみると例外が発生しました。

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly '<社内ライブラリ>.Context'. The system cannot find the file specified.
File name: '<社内ライブラリ>.Context'
   at corerttest!<BaseAddress>+0x2e291806
   at corerttest!<BaseAddress>+0x2e29010f
   at corerttest!<BaseAddress>+0x2e27216a
   at corerttest!<BaseAddress>+0x2e271cce
   at corerttest!<BaseAddress>+0x2e261064
--------------------------------------------------
Debug Assertion Violation

Message: FailFast

Expression: 'ASSERT_UNCONDITIONALLY'

File: C:\corert\src\Native\Runtime\EHHelpers.cpp, Line: 498
--------------------------------------------------

どうやらこのライブラリに存在するメソッドを呼ぼうとしている時に、このライブラリファイルが無いというエラーが発生している模様。PackageReferenceを指定しているのになぜ発生しているのかと気になって調べた所、イッシューに上がってました
どうやらIlcReferenceも一緒に書いてライブラリを指定してやる必要があるんだそうな。
そこで.nugetディレクトリ内にあるdllファイルを指定して再度restore、ビルド*2を行ってみた。

--------------------------------------------------
Debug Assertion Violation

Message: Hardware exception raised inside the runtime.

Expression: 'ASSERT_UNCONDITIONALLY'

File: C:\corert\src\Native\Runtime\EHHelpers.cpp, Line: 486
--------------------------------------------------

( ^ω^)・・・
意味不明なので調べてみたが、特にそれっぽい記事は無い。
仕方がないので試行錯誤してみた所、外部ライブラリが「Release」でビルドされていることに関係しているようだ。
外部ライブラリをDebugに変えてビルドしなおし、参照すると正しく動作する。

てっきりCoreRT側がReleaseビルドでないことが問題かと思い、

PS C:\corert> .\build.cmd vs2017 Release

のようにしてReleaseビルドでビルドして、再度アプリケーションのビルドを行っても変わらず*3
現在はローカルでビルドしたDebugビルドを使用していますが、出来ればnugetから取得したReleaseビルドのライブラリを使用したい所。
P.S. Releaseビルドでかつ、外部ライブラリ内でawaitを使用していると そこでエラー落ちしているようです。

また何か分かったら続きの記事書こうと思います。

*1:勿論インストーラC++選択してないとビルド出来ません

*2:ビルドされている感が無い(妙に早い)とかだったらbinとかobjとか消してみてください

*3:アプリケーション側も -c Release をつけてビルドを行うと、Debug Assertion Violationも出ず、「動作を停止しました」だけが表示されるようになります。