R 4.2でWindowsもUTF-8になることとその他細かい話

この記事はR Advent Calendar 2021 19日目の記事です。

R 4.2では、WindowsでもUTF-8がデフォルトの文字コードになります。まだリリースは半年くらい先ですが、いったん情報をまとめておきます。 詳細が気になる方は、こちらの公式のブログ記事もあわせてご参照ください。

対象のWindowsは?

細かい話は↑のブログ記事に書かれていますが、古いWindowsを使っているとR 4.2がインストールできない可能性があります。 ざっくり言うと、

という感じらしいです(Windows Server については詳しくないので省略)。

ちなみに、私も勘違いしていたのですが、これは「WindowsがデフォルトロケールUTF-8にできるようになった」というのとは別の話で、 OSのロケールUTF-8以外であっても関係なくUTF-8版のRになります。 現に私も、デフォルトロケールは変更しないままのWindows 10でR-develを使っています。

UCRTって?

UCRT (Universal C RunTime)は、Windows 10以降に入っているCのライブラリです。UNIX系で言うとglibcに当たるもののようです。 以前のCライブラリ(MSVCRT)ではUTF-8の扱いに難がありましたが(例: setlocaleUTF-8を選べない)、URCTではそのあたりも改善されています。 R 4.2以降では、Windows版のRはUCRTでビルドされます。このため、UCRTが入っていない古いWindowsでは使えない、というわけです。

なにか対応する必要がある?

ユーザーが対応する必要があることはほとんどないです。

もしRtoolsをインストールしているなら、ツールチェーンが変わるということでRtoolsもセットアップしなおす必要があるので覚えておきましょう もちろんこれは、R 4.2が正式にリリースされた後の話なので、今は特に何もしなくて大丈夫です。

古いWindowsを使っている方は、R 4.2をインストールできない可能性があるのでこれを機にLinuxへの乗り換えを検討しましょうUCRTについて調べて備えましょう(丸投げ)。

余力があれば、今回のUTF-8化はかなりでかい変更なので、今のうちから試して変な挙動がないかチェックしましょう。 開発版のRのデイリービルドはもうUTF-8対応版になっています(ちなみに、RStudioもデイリービルド版を使う必要があります)。 なぜ自分でチェックしといた方がいいかというと、R自体の開発者にもパッケージ開発者にも「Windowsで非欧米系の言語圏」という人が少なくて、 開発者の誤解や見落としがある可能性があるからです。実際、R 4.0.4の時には、日本語など非ASCII文字がうまく表示できない問題がリリースされてから発覚する、という事件がありました。 変な挙動を見かけたらr-wakalangの#moji_codeチャンネルあたりに通報お願いします。

さて、ここから先は細かい話をしていきます。 一般のRユーザーであればこれ以降は特に読む必要はないです。

なにか対応する必要がある?(パッケージ開発者編)

ツールチェーンが変わるということで、C/C++コードを含むパッケージの開発者は対応が必要になるかもしれません。 UCRTに特有の設定が必要であれば、

  • src/Makevars.ucrt
  • configure.ucrt
  • cleanup.ucrt

を配置すると、それぞれ.winのファイル(src/Makevars.winなど)よりこちらが優先して使われるようになります。

依存ライブラリ

C/C++のパッケージは、別のC++のライブラリに依存していることがあります。例えば、sfパッケージはGEOSやPROJなどに依存しています。 Windowsの場合、これらをあらかじめインストールしておくのは大変なので、あらかじめコンパイルしたstatic libraryをダウンロードする、 という方式をとっているパッケージが数多くあります(参考:匿名バイナリ配布集団rwinlib)。特にtidyverse・r-lib周辺。

しかし、現行のRtoolsでビルドしたバイナリは互換性がないので、新しいRtoolsでビルドしなおす必要があります。 そして、上述のMakevars.ucrtあたりで変数を定義したりして、R 4.1とはダウンロードされるバイナリを分けます。 具体例はr-libの適当なパッケージを眺めてみてください(例:svgliteパッケージはCRTという変数でダウンロードするバイナリを区別している → Makevars.ucrtMakevars.win)。

ちなみに、R coreやCRANメンテナはこのやり方をあまり快く思っておらず、今後どうなるかについては火種がくすぶっているようです。 興味ある方はここで鍔迫り合いが見れます。いろいろつらい気持ちになる。。

冒頭のブログ記事にもあるように、現在は、R-develでエラーになるパッケージは、Tomas Kalibera氏によるパッチを適用した状態でビルドされています。

To help package authors with testing and fixing their packages, “ucrt3” R-devel builds automatically apply patches created by Tomas Kalibera to some packages at installation time (patches for over 100 CRAN packages and several Bioconductor packages have been created).

個人的には、これはやりすぎではないかと感じます。 いかにオープンソース、いかに善意といえども、作者の許可を得ずにソースコードを改変し、配布するというのは...。 とはいえ、それくらいゴリゴリ進めないとこんな壮大な変更はリリースできなそう、という現実もわかるので何も言えません。

ちなみに、パッチの内容はこんな感じで、rwinlibを外す方向(include Makevars.winしていればrwinlibからバイナリがダウンロードされる)で進んでいます。

diff -Nru orig/sf/src/Makevars.ucrt patched/sf/src/Makevars.ucrt
--- orig/sf/src/Makevars.ucrt 2021-07-23 15:13:28.000000000 +0200
+++ patched/sf/src/Makevars.ucrt  2021-08-05 11:09:14.744656300 +0200
@@ -1,2 +1,19 @@
-CRT=-ucrt
-include Makevars.win
+
+PKG_CPPFLAGS =\
+   -DHAVE_PROJ_H
+
+PKG_LIBS =  \
+-lgeos_c -lgeos -lgdal -lxml2 -lopenjp2 -lnetcdf -lmysqlclient -ljson-c -lgta -lfreexl -lexpat -lssl -lpsapi -lgif -lmfhdf -lhdf5_hl -lcrypto -lportablexdr -ldf -lhdf5 -lpng16 -lpng -lpcre -lcurl -lrtmp -lssl -lssh2 -lidn2 -lunistring -liconv -lgcrypt -lcrypto -lgpg-error -lws2_32 -ltiff -llzma -ljpeg -lz -lcfitsio -lzstd -lwebpdecoder -lwebp -lsbml-static -lgeotiff -lproj -lsqlite3 -lbz2 -lcrypt32 -lwldap32 -lsecur32
+
+all: clean winlibs
+
+winlibs:
+   cp -r $(R_TOOLS_SOFT)/share/gdal ../inst/
+   cp -r $(R_TOOLS_SOFT)/share/proj ../inst/
+
+CXX_STD = CXX11
+
+clean:
+   rm -f $(SHLIB) $(OBJECTS)
+
+.PHONY: all winlibs clean

「え、でもWindowsだと依存ライブラリをあらかじめインストールしておくのは大変とか言ったのは?」、と思ったそこのあなた。鋭いです。 新Rtoolsでは、CRANのパッケージをビルドするのに必要な主要なライブラリはあらかじめ用意する、という方針になっているようです。 ただ、そうなるとRtoolsが重くなるので(3GB!)どう配布するのか、新たなパッケージを追加したいときや既存のパッケージを更新したくなった時はどうするのか、 といった議論はまだ進行中というステータスらしいです。

The distribution of the libraries for packages in a single chunk (or two, the “base” and “full” version) is subject to an ongoing debate, with differing opinions. Should distribution in smaller chunks (sets of libraries, or even individual libraries) become necessary, it should be using a package manager external to R packages and be integrated with the toolchain bundle/Rtools, allowing automated re-build and change together with the compiler toolchain.

rwinlibがそもそも必要なくなる、ということ自体はいいことだとは思うので、よい方向に転がってほしいです。

その他

32-bit版Windowsが消える

これまでWindowsのRでは、64 bit版・32 bit版の両方でパッケージが提供されていました。 このため、開発者は、32 bitでしか発生しないエラーなどにも対応する必要があり、とりわけ非Windowsユーザーの開発者には重荷になっていました。 しかし、R 4.2以降は32-bit版は提供されなくなります。

CRAN checkではひとつ前のバージョンまでチェックされるので、順当にいけば32 bit対応から逃れられるのはさらに1年先ということになりますが、DESCRIPTION

Depends:
    R (>= 4.2)

と書けばたぶん32 bit版に別れを告げられることでしょう。おすすめです。

Solarisが消える

前掲のブログ記事ではあくまで「Windowsでの32 bit版の提供が終了」と書かれているだけなので関係あるのかわかりませんが、 32 bit版Windowsとともに長らく開発者の頭痛の種だったSolarisもサポート外になるようです。めでたい。

まとめ

備えよう。