f# – FS2024 Static linking error when PCL project use by TypeProvider – Stack Overflow
http://stackoverflow.com/questions/25175031/fs2024-static-linking-error-when-pcl-project-use-by-typeprovider
@AshtonKJ さんから解答を貰った、以下のところを、少しメモ書き
Once that is done, you will need to select either Profile78, or Profile259 (I would recommend 78, as the current Xamarin.Forms nuget package doesn’t support 259).
Portable Class Library を作るときに、対応するサブセットがあって、Xamarin.iOS/Android の場合に対応しているのが Profile78 です。Profile 自体は、対応する実行環境のセットがあって、Windows 8.1 やら Windows Phone やらの組み合わせでサブセットの番号が決まっています。対応自体は、C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\ の中にある、SupportedFrameworks フォルダの中身を見ればいいのですが、なかなか手間なので、対応表を作りました。
私の環境では、Xamarin.iOS/Android が入っているので、これの対応も入っています。プログラム自体は、https://gist.github.com/moonmile/91573c79fed65062a217 にあるので、自分の環境で作ってみてください。
プロファイルの中にある DLL は名前は同じですが、API の実装が異なるので、それぞれの環境にあったプロファイルの DLL を使わないといけません。ですから、プロファイルの中にある API の一覧がほしい…のですが、無いのかな? Leveraging existing code across .NET platforms – .NET Blog – Site Home – MSDN Blogs がその役割をしているような気もするけど。ちょっときちんと調べていない。
■Xamarin.Forms の Mobile Apps で PCL を作る
まず、Mobile Apps で Xamarin.Forms 用の PCL を作ると、これが「Profile78」になっています。
ソリューションエクスプローラーで、PCL の「参照設定」→「.NET」を選択した状態でプロパティウィンドウのパスを見ます。
ここに「Profile78」が書いてある。
プロジェクトのプロパティから「ライブラリ」→「ターゲット」を見ると、どのプラットフォームに対応するのかが出てきます。
Xamarin Studio だと、もうちょっと直接的にプロファイルが見れて、プロジェクトのオプションから「ビルド」→「一般」でプロファイルがわかる。
□Profile78 の場合
ここの Target Framework をちょいちょいと変えてやると対応するプロファイルの番号がかわります。Xamarin.Forms の場合は、Windows Phone Silverlight が入っているので「Profile78」になっていますが、Silverlight を外すと「Profile7」に変わります。
□Profile7 の場合
□Profile259
Profile259 ってのは、Windows Phone 8.1 を含んだ場合ですね。結構制限された環境であることが想像できます。
7 | 78 | 259 | 47 | |
.NET 4.5 | ○ | ○ | ○ | ○ |
SilverLight 5 | ○ | |||
Widnows Phone SL8 | ○ | ○ | ||
Windows 8 | ○ | ○ | ○ | ○ |
Windows 8.1 | ○ | ○ | ||
Windows Phone 8.1 | ○ | |||
Xamarin.Android | ○ | ○ | ○ | ○ |
Xamarin.iOS | ○ | ○ | ○ | ○ |
そんな訳で、Xamarin.iOS/Android に対応した PCL を作る場合には、Profile78 か Profile259 を作ればよいわけです。
■F# でポータブルライブラリを作るとどうなるのか?
C# では PCL を作るときやプロジェクトで対応する Profile を指定できるのですが、F# の場合はこれができません。何故できないのかは不思議です。まあ、歴史的経緯で FSharp.Core があちこちに散らばってしまっているためなのかな、と。さまざまな FSHarp.Core は、C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp\ にあります。
あと、ビルド時には C:\Program Files (x86)\Microsoft SDKs\F#\ を参照していたりします。.NETCore にある 3.78.3.1 とか 3.259.3.1 は、それぞれ Profile78 と Profile259 に対応したプロファイルです。これは、https://visualfsharp.codeplex.com/ からダウンロード&インストールするとできるフォルダです。
Visual F# Tools – Home
https://visualfsharp.codeplex.com/wikipage?title=Current%20Priorities
にある通り、「Put the finishing touches to Profile78 and 259」されます。
プロジェクトを作成するときも、新しいテンプレートが増えて、
- Portable Library(.NET 4.5 Widnows Store, Windows Phone 8 Silverlight)
→ Profile78 相当
- Portable Library(.NET 4.5 Widnows Store, Windows 8.1, Windows Phone 8 Silverlight)
→ Profile259 相当
になります。
試しに、「Portable Library(.NET 4.5 Widnows Store, Windows Phone 8 Silverlight)」のほうを作って、プロパティのパスを見ると、「C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\v4.5\Profile\Profile78」になっていて、プロジェクトのプロパティではターゲットが「F# 3.1 (FSharp.Core, 3.78.3.1)」になります。このマイナーバージョン部分が、プロファイル番号に相当するという混沌さです(苦笑)。
おそらく、FShap.Core を C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\ に突っ込んでしまうか、C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETPortable\ 以下、相当のフォルダを C:\Program Files (x86)\Reference Assemblies\Microsoft\FSharp\.NETPortable\ に作ってしまうほうが素直だと思うのですが…先行きどうなるか分かりません。対応するプロファイルが増えると混沌の度合いが増しそうです。実際、FSharp.Data が動的ロードする FSharp.Core に Profile78 を追加するときは、このマイナーバージョンを見る必要があってで、えらいことになりそうです。
ちなみに
- ポータブルライブラリ
→ Profile7 .NET 4.5 → FSharp.Core 3.3.1.0 - ポータブルライブラリ(レガシー)
→ Profile47 .NET 4.0 → FSharp.Core 2.3.5.1
になります。
Profile | FSharp.Core | .NET | |
Portable Library(.NET 4.5 Widnows Store, Windows Phone 8 Silverlight) | 78 | 3.78.3.1 | 4.5 |
Portable Library(.NET 4.5 Widnows Store, Windows 8.1, Windows Phone 8 Silverlight) | 259 | 3.259.3.1 | 4.5 |
ポータブルライブラリ – Portable Library | 7 | 3.3.1.0 | 4.5 |
ポータブルライブラリ(レガシー) – Portable Library Legacy | 47 | 2.3.5.1 | 4.0 |
ライブラリ – Library | Native | 4.3.1.0 | 4.5 |
■結論
というわけで、F# で Xamarin.iOS/Android 用のライブラリを作るときに、Profile7 しか選択肢がなかったけど、Profile78 か Profile259 が増えたよ、って話です。Xamarin.Forms を使う時は、Profile78 を使えば OK。
Xamarin.Forms 自体が Windows Phone 8.1 に対応していないので意味はありませんが、Profile259 にしておくことで、Windows Phone 8.1 から参照設定できるようになるので、ライブラリとして利用させることができます。F# のポータブルライブラリ=Profile47 相当が Window Phone 8.1 を含んでいなかったので、これで、Xamarin.iOS/Android, Windows Store 8.1, Windows Phone 8.1 の共通ライブラリが作れるようになった、ってことです。
~~~
FSharp.Core がややこしいことになっているのと、先の TypeProvider の謎の実行エラー(StringStream のコンストラクタがないエラー)も、ここに関わっているような気がするので、Profile 間で呼び出せる API を総ざらいしたほうがよさそうですね。ビルドは通るけど実行エラーになるのはマルチプラットフォーム開発の常なので、もうちょっと突っ込んで調べたほうが安全そうです。
ピンバック: F# Weekly #33, 2014 | Sergey Tihon's Blog