让我先声明我几乎是一个编程新手,在 C 或 GNU 环境中都没有受过良好的训练。另外,我真的无法提供可重现的示例,因为我没有编写此代码,我只是在尝试构建它。我已经自学足以编译一些程序,给定一个良好的预先存在的makefile,并多次使用Rtools为Windows编译R。
我一直在尝试使用 GCC 4.8.4 为 Windows(7 64 位)编译 R(Rtools 仍然存在于 4.6.3 预发行版中,并且 4.9 中的链接时间优化已经复活了一些 旧 错误),并且可以这样做问题。在其中一个文件(准确地说是/src/extra/trio/compat.c)中包含 stdio.h 和 and 的sprintf
定义vsprintf
。因此,构建崩溃并出现以下错误:
In file included from compat.c:3:0:
F:/MinGW64/x86_64-w64-mingw32/include/stdio.h:553:5: note: previous
definition of 'snprintf' was here
int snprintf (char * __restrict__ __stream, size_t __n, const char *
__restrict__ __format, ...)
^
compat.c:75:5: error: redefinition of 'vsnprintf'
int vsnprintf(char *buffer, size_t bufferSize, const char *format,
va_list args)
^
In file included from compat.c:3:0:
F:/MinGW64/x86_64-w64-mingw32/include/stdio.h:543:7: note: previous
definition of 'vsnprintf' was here
int vsnprintf (char * __restrict__ __stream, size_t __n, const char
* __restrict__ __format, va_list __local_argv)
^
../../gnuwin32/MkRules:218: recipe for target 'compat.o' failed
make[4]: *** [compat.o] Error 1
Makefile:120: recipe for target 'rlibs' failed
make[3]: *** [rlibs] Error 1
Makefile:179: recipe for target '../../bin/x64/R.dll' failed
make[2]: *** [../../bin/x64/R.dll] Error 2
Makefile:104: recipe for target 'rbuild' failed
make[1]: *** [rbuild] Error 2
Makefile:14: recipe for target 'all' failed
make: *** [all] Error 2
compat.c 中的行是 65–79 中的行:
int snprintf(char *buffer, size_t max, const char *format, ...)
{
int res;
va_list(ap);
va_start(ap, format);
res = trio_vsnprintf(buffer, max, format, ap);
va_end(ap);
return res;
}
int vsnprintf(char *buffer, size_t bufferSize, const char *format, va_list args)
{
return trio_vsnprintf(buffer, bufferSize, format, args);
}
如果我删除这些行,构建完成,但是 R 输出具有三位十进制科学记数法指数而不是两位数(例如“3.11e-004”而不是“3.11e-04”),这会导致各种检查崩溃。我被告知这是标准的 Windows 方法,所以我删除本地 R 版本几乎肯定会导致这个问题。
我的问题是,有什么方法可以继续将 stdio.h 包含在 compat.c 文件中,但在 compat.c 中将snpritf
其vsnprintf
重新定义为本地文件?
谢谢你。
失败的尝试 1
我尝试添加直接#undef
声明以及
#ifdef snprintf
#undef snprintf
#endif
vsnprintf
以及compat.c 中的对应 for ,但都不起作用。由于“重新定义”,我得到相同的构建错误崩溃停止。
失败的尝试 2
将 compat.c 中的代码更改为:
#ifdef snprintf
#undef snprintf
int snprintf(char *buffer, size_t max, const char *format, ...)
{
int res;
va_list(ap);
va_start(ap, format);
res = trio_vsnprintf(buffer, max, format, ap);
va_end(ap);
return res;
}
#endif
允许程序编译,但它有相同的符号错误,这意味着它在功能上等同于删除这些行。
根据评论请求更新
- 安装一些 Mingw-64 的味道并将 \bin 放在 PATH 的头部
- 安装 MSYS2:基本安装,然后添加 tar、make、zlib、zip、unzip 和 rsync,并将其 bin 作为路径中的第二个
- Untar R-3.1.2.tar.gz (两次,第一次使用 MSYS2 的 tar 1.28 返回 simlink 错误。使用 Rtolls 的已修补的 tar 1.2.1 不会返回错误)
- 将 Tcl 和 bitmapdll 子目录从 R64 (Rtools) 复制到适当的位置
- 修改 MkRules.dist 以强制执行 64 位、Windows 64 平台、HTML 帮助以及 Cairo、Inno 和 qpdf 的正确目录,并将其保存为 MkRules.local。对于这些测试,我没有使用基于 OpenBLAS 的 Rblas,除了增加
-pipe
速度之外,没有对 EOPTS 进行任何特定于处理器的调用 - 跑
make all
我已经使用 Rtools 中的二进制文件构建了很多次 R,包括使用 OpenBLAS(愚弄 R 认为它是 ATLAS)。我注意到但不明白的是,stdio.h
在 GCC 4.7(以及 4.6)和 4.8 及后续版本之间发生了变化。包含错误中抛出的行号的新版本snprintf
直接定义vsnprintf
。4.6.3 的版本没有。我复制了以下部分:
来自 GCC 4.6.3 第 494-514 行的 stdio.h:
#if !defined (__USE_MINGW_ANSI_STDIO) || __USE_MINGW_ANSI_STDIO == 0
/* this is here to deal with software defining
* vsnprintf as _vsnprintf, eg. libxml2. */
#pragma push_macro("snprintf")
#pragma push_macro("vsnprintf")
# undef snprintf
# undef vsnprintf
int __cdecl vsnprintf(char * __restrict__ d,size_t n,const char * __restrict__ format,va_list arg)
__MINGW_ATTRIB_DEPRECATED_MSVC2005 __MINGW_ATTRIB_DEPRECATED_SEC_WARN;
#ifndef __NO_ISOCEXT
int __cdecl snprintf(char * __restrict__ s, size_t n, const char * __restrict__ format, ...);
#ifndef __CRT__NO_INLINE
__CRT_INLINE int __cdecl vsnprintf(char * __restrict__ d,size_t n,const char * __restrict__ format,va_list arg)
{
return _vsnprintf (d, n, format, arg);
}
#endif /* !__CRT__NO_INLINE */
#endif /* !__NO_ISOCEXT */
#pragma pop_macro ("vsnprintf")
#pragma pop_macro ("snprintf")
#endif
来自 GCC 4.9.2 的 stdio.h(与 4.8.4 中的相同)第 531-565 行:
#if !defined (__USE_MINGW_ANSI_STDIO) || __USE_MINGW_ANSI_STDIO == 0
/* this is here to deal with software defining
* vsnprintf as _vsnprintf, eg. libxml2. */
#pragma push_macro("snprintf")
#pragma push_macro("vsnprintf")
# undef snprintf
# undef vsnprintf
int __cdecl __ms_vsnprintf(char * __restrict__ d,size_t n,const char * __restrict__ format,va_list arg)
__MINGW_ATTRIB_DEPRECATED_MSVC2005 __MINGW_ATTRIB_DEPRECATED_SEC_WARN;
__mingw_ovr
__MINGW_ATTRIB_NONNULL(3)
int vsnprintf (char * __restrict__ __stream, size_t __n, const char * __restrict__ __format, va_list __local_argv)
{
return __ms_vsnprintf (__stream, __n, __format, __local_argv);
}
int __cdecl __ms_snprintf(char * __restrict__ s, size_t n, const char * __restrict__ format, ...);
#ifndef __NO_ISOCEXT
__mingw_ovr
__MINGW_ATTRIB_NONNULL(3)
int snprintf (char * __restrict__ __stream, size_t __n, const char * __restrict__ __format, ...)
{
register int __retval;
__builtin_va_list __local_argv; __builtin_va_start( __local_argv, __format );
__retval = __ms_vsnprintf (__stream, __n, __format, __local_argv);
__builtin_va_end( __local_argv );
return __retval;
}
#endif /* !__NO_ISOCEXT */
#pragma pop_macro ("vsnprintf")
#pragma pop_macro ("snprintf")
#endif