はじめに
dotNet Coreで作成したコントロールアプリをLinuxでも動くようにしたく、いろいろと参考にした記事のメモです。
WindowsからLinux環境で動作確認する
今回、Linuxでの動作を確認するためにDockerを利用しました。
アプリを自己完結型で発行する
Linuxで動作以前にdotNetの環境がない状態でアプリを実行しようとしても動作しないため、自己完結型で発行する必要がありました。
実行時にICUパッケージが見つからないとエラーが出る
Process terminated. Couldn't find a valid ICU package installed on the system. Set the configuration flag System.Globalization.Invariant to true if you want to run with no globalization support.
自己完結型で発行し、いざ実行してみると上記のようなエラーが出る。
調べてみるとICUパッケージがLinux環境にインストールされていない場合に出るエラーだそうで、ICUパッケージをLinux環境にインストールするか、国際化対応を行わないInvariant
モードにすることで解決できるとありました。
下記を参考にしてICUパッケージをLinux環境にインストールすることでも実行できるようになりましたが、環境を作るたびにやりたくないし、自分以外に渡すときも面倒になるので
https://github.com/dotnet/core/blob/main/Documentation/build-and-install-rhel6-prerequisites.md#icu
今回はInvariant
モードにする設定を行い、Linux環境で動作できるようにしました。
Invariantモードの設定
グローバリゼーション不変モード(.NET Core 2.0の新機能)を使用すると、グローバリゼーションデータおよびグローバリゼーション動作に対するアプリケーションの依存関係を削除できます。このモードはオプトイン機能であり、グローバリゼーション機能やグローバリゼーションの正確さよりも、依存関係と分散のサイズを減らすことに関心がある場合に、より柔軟性を提供します。(参考記事をGoogle翻訳しました)
ちょっと意味がわかりにくいですが、アプリに対する国際化対応のサポートを行わない設定とし、そもそもICUパッケージを使用しないようにすることで、ライブラリが見つかりませんというエラーを回避するものだと思います。インバリアントにすることの影響などは上記記事を参照ください。
実際に設定する際はプロジェクトファイル(.csproj)に以下を追加します。
<ItemGroup>
<RuntimeHostConfigurationOption Include="System.Globalization.Invariant" Value="true" />
</ItemGroup>
以下の[3.グローバリゼーション インバリアント モードを使用するかどうかを決定します。]を参考にしています。
インバリアントについては下記記事がわかりやすかったです。
補足
ICU(International Components for Unicode)とは
ICUは、ソフトウェアアプリケーションのUnicodeおよびグローバリゼーションサポートを提供する、成熟した、広く使用されているC / C ++およびJavaライブラリのセットです。ICUは広く移植可能であり、すべてのプラットフォームで、C / C ++とJavaソフトウェア間で同じ結果をアプリケーションに提供します。
調べた限りでは、国際化対応をサポートするライブラリというもので、日付/時刻など国ごとに違う書式(日本なら2021年3月11日、英語なら11 March,2011など)や文字列のどこで改行していいのか、アルファベットの大文字/小文字の対応付けみたいな言語に依存する情報なんかが入ってるライブラリでICUのほかにもWindowsであればNLS(National Language Support)が使われているそうです。