窓を作っては壊していた人のブログ

この謎のブログタイトルの由来を知るものはもういないだろう

XamarinなどのPCLプロジェクトにSystem.Reactiveを導入しようとすると失敗することへの対策

はじめに

今日Twitter

System.Reactive を PCL に追加するとエラーになる

といった内容のツイートを見かけました. 自分は過去に普通に導入できていたので何が違うんだろうなぁということで少し検証してみました.

検証環境

  • macOSX
  • PCL 4.5 - Profile 111 (Visual Studio for MacでPCLのプロジェクトを作ると作られるデフォルトのやつです)
  • System.Reactive 3.1.1 (現時点でのStable)

検証

とりあえず実際にSystem.Reactiveを導入してみましょう. するとインストールに失敗するはずです.まあ何かに失敗したらログを見ればいい解決手段が載っているはずですね. ということで少し眺めてみると

Could not install package 'System.Runtime.InteropServices.RuntimeInformation 4.0.0'. You are trying to install this package into a project that targets '.NETPortable,Version=v4.5,Profile=Profile111', but the package does not contain any assembly references or content files that are compatible with that framework. For more information, contact the package author.

みたいなエラーが出ていると思います.これがSystem.Reactiveが導入できなかった根本原因と考えても良さそうです.

それであれば System.Runtime.InteropServices.RuntimeInformation 4.0.0 ではない,もうすこし上のバージョンではどうかと考えるのが基本的な考え方です. 実際にNuGetのサイトをアクセスしてみると

www.nuget.org

Stableで4.3.0が出ています.

依存ライブラリを比較してみるとバージョンアップの他,今回PCLのプロジェクトに影響しそうな部分で

Microsoft.NETCore.Platformsのバージョンが.NETCore 5.0の部分では1.1.0に上がり,.NETStandard 1.1の部分では削除されています.

ここが非常に匂いますよね?

GitHubのIssueを探してみると

Microsoft.NETCore.Platforms doesn't install on packages.config based projects · Issue #8952 · dotnet/corefx · GitHub

こんなものも見つかったりします. これが本当の原因であるかは(自分の知識が足りないので)わかりませんが,確かにMicrosoft.NETCore.Platforms 1.0.2でも導入に際してエラーが起こったのでこれであると断定してもいいでしょう.

ということで根本的な原因がわかりました.

あとは解決手段としてその問題が解消されている System.Runtime.InteropServices.RuntimeInformation 4.3.0 をまずはじめに導入します. System.Reactiveのインストールで失敗をしたSystem.Runtime.InteropServices.RuntimeInformationが入ってしまえばこっちのもんです,どうでしょう,入りましたよね?

問題の一つが解消されたのでSystem.Reactiveを導入してみましょう. 問題なく導入されたと思います.

まとめ

System.ReactiveをPCLのプロジェクトに導入する際はSystem.Runtime.InteropServices.RuntimeInformation 4.3.0 をまずはじめに導入すればよいでしょう.

またNuGetを使用してライブラリを導入する際はぜひともエラーログを見てみみてください. そうすると解決手段が結構簡単に見つかったりします. 最近ではXamarin.Android.SupportPackage関連でも同様の問題を抱えている人がいましたが,それはエラーログのAndroid71に対してのパッケージはないよー的なことが書かれていたので,TargetPlatformをAndroid80にすればいいだけだな,という風に容易に察しがつきました.

よくわからなかったら適当にバージョン上げてみるのもいいのかもしれませんw

おきもち

今回の問題が起きたのはXamarin StudioからVisual Studio for Macとかに変わってMonoのバージョンが4.8から5系に変わったり,もしくはインストールされている.NET Core SDKのバージョンが上がったことによって起こった問題ではないかなぁともちょっと想像しています.

Mono4.8から5系ではビルドシステムのフローが変わった気がしますし,.NET Core関係でも1.0.1-preとかのときと最近ではまずパッケージ管理の方法が変わったりしましたし,そういうものが積み重なって今回みたいなケースが出たんじゃないかなぁ...違うかなぁ...

ということで昔の環境を持っているという人は是非試してみて欲しい案件ではありますねw