R-devel-win.exe 是 R 的实验性安装程序,用于下载 CRAN 包的实验性二进制版本。它将 UTF-8 设置为 Windows 上的当前默认编码(Windows 10 2019 年 11 月版或更新版本)。支持 92% 的 CRAN 包。旨在演示此选项,以支持 Windows 上 R 中的 Unicode 字符,而非用于生产用途。
要使用此版本的 R,请启动 cmd.exe
,运行 chcp 65001
(以设置 UTF-8 代码页),转到 属性/字体/字体
并选择 NSimFun
(一种具有此示例所需字形的字体),转到 C:\Program Files\R\R-devel\bin
(演示的默认安装目录),运行 R
。
检查 C 库编码(codepage
)和系统编码(system.codepage
)是否都为 65001,即 UTF-8。
> l10n_info()
$MBCS
[1] TRUE
$`UTF-8`
[1] TRUE
$`Latin-1`
[1] FALSE
$codepage
[1] 65001
$system.codepage
[1] 65001
尝试绘制标题为日语的直方图
hist(mtcars[,"mpg"], xlab="マイル/ガロン", ylab="車の数")
在 R 的标准版本上,这仅适用于运行在支持日语的区域设置中的 Windows。在其他 Windows 系统上,甚至无法将日语字符(“Miles/Gallon”和“Number of Cars”)粘贴到 RTerm 窗口中。使用此演示版本的 R,它应该可以在任何 Windows 10(2019 年 11 月版或更新版本,最后一次测试为 2020 年 4 月版)上运行。
我们可以对外部包执行相同的操作。运行
install.packages("ggplot2")
将从 https://www.r-project.org.cn/nosvn/winutf8/demo 中的预设演示二进制存储库安装 ggplot2
。使用它,我们可以运行
library(ggplot2)
ggplot(mtcars,aes(x=mpg)) + geom_histogram(binwidth=5) + xlab('マイル/ガロン') + ylab('車の数')
可以在我的 5 月份 的上一篇文章中找到更多使用示例。当时,仅支持基本包和推荐包。
背景
Windows 10(2019 年 11 月版及更新版本)允许应用程序在与 C 库(需要是 UCRT)和操作系统进行交互时使用 UTF-8 作为其本机编码。此新的 Windows 功能在 Unix 系统中已存在多年,它最终允许 Windows 上的 R 可靠地处理所有 Unicode 字符。
在 Windows 上已可靠地处理所有 Unicode 字符的应用程序以前使用专有的 Windows API 和宽字符字符串,这需要实现和维护大量 Windows 特定代码。R 并未完全采用该途径,RGui 除外,特别是与文件系统/操作系统进行交互的 Windows 特定代码(在某些情况下,Windows 中也出于字符编码之外的原因需要这样做)。如今,Windows 甚至无法使用一个宽字符对所有 Unicode 字符进行编码(宽字符为 16 位,使用 UTF16-LE,因此需要两个宽字符来表示某些 Unicode 字符),因此,支持 Unicode 的旧 Windows 方式似乎没有任何技术优势。相反,通过 UTF-8 的新方式将最终允许逐步淘汰 R 中的一些 Windows 特定代码。
要在 Windows 上使用 UTF-8 作为本机编码,只需要对 R 进行微小的更改,但我们需要重新构建 R 和软件包以使用 UCRT 作为 C 运行时。为此,我们需要一个新的 Windows 工具链,并且我们需要使用新工具链重新构建所有代码。不再能够以目标文件或静态库的形式重新使用使用以前工具链构建的二进制代码。不幸的是,在 Windows 上构建 R 软件包时的一种常见做法是从外部来源下载预构建的静态库,而当这些库使用 MSVCRT 构建时,这种做法不再可行。从原则上讲,这在 Windows 上无论如何都是一种不好的做法,此类代码应使用相同的编译器工具链进行编译。只能假设 DLL 之间存在不同 C 运行时之间的兼容性,即使这样也有其局限性,例如对当前本机编码的解释。
演示
已使用 GCC 9 和 MXE(在 Linux 上交叉编译)构建了一个新的实验性编译器工具链和一些 R 和软件包库。它可以作为 gcc9_ucrt2.txz, 733M 下载。
此部分的工作需要更新一些 MXE 构建配置以使用较新的软件,使用 UCRT 构建,使用较新的 GCC 构建,等等。此外,这需要修补一些外部软件才能在 MXE(一个交叉编译环境)中构建或使用 MXE 构建。还需要更多外部库来支持所有 CRAN 软件包。完成此项工作以构建具有基本和推荐软件包的 R 大约花费了 5 天时间,再花费大约 5 天时间来添加更多库,以便支持 92% 的 CRAN 软件包(注意:许多 CRAN 软件包没有任何本机代码)。
R 已修补,允许在 Windows 上使用 UTF-8 作为本机编码,这很简单(在其他操作系统上受支持),并且已经是 R-devel 的一部分。然后修补演示构建以通过融合清单设置 UTF-8(必须在构建时为可执行文件执行此操作),仅构建 64 位二进制文件/安装程序,以及一些较小的更改。可作为 r_gcc9_ucrt2_2.diff 获得。
已修补 50 多个 CRAN 软件包以使用新工具链进行构建。几乎所有修补程序都只是在安装时删除了外部二进制代码的下载,并将其替换为链接到与实验工具链一起构建的静态库。请注意,许多软件包正在下载即使在 Rtools4 中也仍然可用的代码。此外,一些软件包正在下载外部软件的源代码并构建它,即使它包含在 Rtools4 中也是如此。
修补软件包以构建和构建所有软件包的二进制版本大约花费了 5 天时间。剩余的软件包需要工具链中更多一些库。修补程序可 在此处 获得(如果考虑用于生产工具链,显然必须重新审视并清理它们)。
此外,通过 R CMD check
对软件包进行了测试。输出可用于 CRAN 软件包和这些 CRAN 软件包所需的几个 BIOC 软件包。在使用的快照中,CRAN 和所需的 BIOC 软件包(15793 个)中,约有 92% 构建并通过了其测试,状态为 OK/NOTE(14656 个 CRAN 和 59 个 BIOC 软件包)。所有创建的二进制软件包都可以使用,即使是那些未通过测试的软件包也是如此。
最后,花了一些时间撰写了有关此内容的各种文本,请参见下面的参考,因此总共在此演示上花费了大约 20 天时间。
测试
如果有人在这个版本中发现了与编码相关的问题,即使用 UTF-8 作为本机编码应该可以工作但实际上不行的问题,我们非常欢迎您报告该问题。R 的某些部分可能暗藏了 Windows 上的本机编码永远不会是多字节(要么是单字节,要么是双字节)的假设,这种情况必须得到修复。通过运行 R CMD check
发现此类问题的可能性很小,因为测试/示例不包含非常规字符。
结论
基于此经验,我相信切换到 UCRT 已经可行,而且我预计构建一个完整的工具链只需要几个月的时间。我认为这是在 Windows 上可靠地支持 Unicode 字符(本机编码中无法表示)的唯一现实方法。
在添加和修复各种“捷径”(在某些情况下避免转换为本机编码)方面投入更多精力只会使代码变得复杂,引入更多错误,而且无法完全解决问题。
重写所有 R 和 R 包以使用旧的专有 Windows 方式来支持 Unicode(宽字符、专有 Windows API 而不是标准 C 库),我认为这是不可能的,这需要付出更多数量级的努力,而且几乎没有人愿意这样做。这需要 R 内部专家的参与(例如重写解析器或连接代码),而且要么会复制大量代码,要么会在 Unix 系统上造成低效,这两种情况似乎都是不可接受的。可能必须替换或扩展一些使用的外部库。
构建新的 UCRT 工具链和库不需要任何 R 或其内部的特殊知识。构建 UCRT 的外部软件补丁(例如,当回馈给 MXE 或类似系统时,目前看来对此类效果的良好补丁非常受欢迎)可以被其他项目重复使用,与 R 完全无关。最后,无论如何,从 MSVCRT 切换到 UCRT 可能在某个时间点是必要的。
参考文献
https://developer.r-project.org/WindowsBuilds/winutf8/winutf8.html。有关在 Windows 上构建 R 以及如何创建此演示的详细文本。
https://www.r-project.org.cn/nosvn/winutf8/gcc9_ucrt2.txz, 733M。基于 GCC 9/UCRT 的实验性工具链,其中包含大多数 CRAN 包的库,仅限 64 位。使用 https://www.r-project.org.cn/nosvn/winutf8/mxe_gcc9_ucrt2.tgz 中提供的 MXE 修改版构建。
https://www.r-project.org.cn/nosvn/winutf8/demo。二进制 CRAN 包和必需的 BIOC 包的存储库,包括补丁及其检查结果。使用实验性工具链构建。仅限 64 位。
https://www.r-project.org.cn/nosvn/winutf8/R-devel-win.exe。R 安装程序,使用 R-devel 78739 的实验工具链构建,并使用 https://www.r-project.org.cn/nosvn/winutf8/r_gcc9_ucrt2_2.diff 修补。仅限 64 位。