如何让Wine/Linux中超越函数精度与Windows保持一致?
一、搞定native ucrtbase子进程重定向崩溃的问题
1. 先验证终端环境的推测
你怀疑是程序误判终端输出颜色导致崩溃,可以先通过模拟交互式终端来验证:
- 强制设置终端环境变量,让程序认为自己在交互式终端里:
或者用WINEDLLOVERRIDES="ucrtbase=n,b" TERM=xterm-256color wine <my program> > output.log 2>&1script命令模拟完整终端环境,即使重定向IO也能骗过程序:WINEDLLOVERRIDES="ucrtbase=n,b" script -q -c 'wine <my program>' output.log
2. 直接禁用程序的颜色输出
如果程序支持命令行参数关闭颜色(比如--no-color),直接加参数运行就行。要是没有这类参数,试试用环境变量强制禁用:
WINEDLLOVERRIDES="ucrtbase=n,b" NO_COLOR=1 wine <my program> > output.log 2>&1
或者设置TERM=dumb,让程序觉得终端不支持任何颜色输出。
3. 调试定位崩溃根源
要是上面的方法都没用,用Wine的调试工具抓崩溃日志:
WINEDLLOVERRIDES="ucrtbase=n,b" WINEDEBUG=+relay,+seh wine <my program> > debug.log 2>&1
查看debug.log里的SEH异常调用栈,找到崩溃的具体函数,确认是不是终端输出相关的代码出问题,再针对性修复(比如给程序打个小补丁,或者调整Wine的终端模拟逻辑)。
二、重编译Wine内置ucrtbase.dll匹配VS2019精度
Wine的源码完全公开,ucrtbase.dll的实现就在Wine源码树的dlls/ucrtbase/目录下,你可以替换里面的超越函数实现来对齐VS2019的精度:
1. 拉取Wine源码
克隆官方仓库(建议用和你当前Wine版本一致的分支,避免兼容性坑):
git clone https://gitlab.winehq.org/wine/wine.git cd wine
2. 替换超越函数实现
VS2019用的UCRT(通用C运行时)数学函数,微软已经开源了部分代码。你可以提取其中的sin、cos、exp、log等超越函数实现,替换Wine的ucrtbase/math/目录下对应的文件。
要是不想用微软的代码,也可以自己调整Wine现有实现的计算逻辑,确保输出结果和VS2019完全一致(重点是对齐精度和舍入规则)。
3. 编译自定义ucrtbase.dll
配置编译选项,指定只编译ucrtbase模块(比全编译快很多):
./configure --prefix=/usr/local/wine-custom make -j$(nproc) dlls/ucrtbase/ucrtbase.dll.so
编译完成后,要么把生成的ucrtbase.dll.so替换掉系统中Wine的原文件(记得备份),要么用WINEDLLPATH指定自定义库路径:
WINEDLLPATH=/path/to/custom-wine/dlls/ucrtbase wine <my program>
4. 验证精度
运行程序测试超越函数的输出结果,和VS2019下的结果对比,确保精度完全一致。
内容的提问来源于stack exchange,提问作者Emanuele

