【问题标题】:Build 64-bit R Package with Rtools and External Library / DLL使用 Rtools 和外部库/DLL 构建 64 位 R 包
【发布时间】:2017-01-03 22:09:27
【问题描述】:

我正在使用 Rcpp 框架创建的 Windows 上构建/安装 R 包。有一段时间我只是在构建一个链接 32 位 dll 的 32 位版本。我的 Makevars 文件如下所示:

PKG_CPPFLAGS = -I"D:/projects/source/my_project"
PKG_LIBS = -L"D:/projects/source/my_project/Release" -lproject

我会跑

R CMD build Package
R CMD INSTALL --no-multiarch --no-test-load --build Package_1.0.tar.gz

在 cmd 提示符下,一切都会好起来的。现在我也需要 64 位版本。我让我的 Makevars 看起来像这样:

PKG_CPPFLAGS = -I"D:/projects/source/my_project"
PKG_LIBS = -L"D:/projects/source/my_project/Release" -lproject -lprojectx64

我的 64 位 dll 被命名为 projectx64.dll。问题是当我运行命令时:

R CMD INSTALL --build Package_1.0.tar.gz

构建失败是因为在 32 位构建过程中,因为编译器尝试链接 64 位 dll。有什么方法可以让它按顺序链接相应架构的 dll?

作为 P.S.我读过大红色的文字,上面写着“NO WINDOWS!”在 Rcpp 手册中,但这根本不准确,我看不出我的问题在 Linux 上会有什么不同。

编辑

这是 INSTALL 命令的输出。当 32 位 gcc 启动并尝试链接到 Makevars 中指定的 64 位 dll 时,它可能会失败。

*** arch - i386
c:/Rtools/mingw_32/bin/g++  -I"C:/R/R-3.3.1/include" -DNDEBUG -    I"D:/projects/source/my_project"   -I"C:/Users/rk/Documents/R/win-library/3.3/Rcpp/include" -I"d:/Compiler/gcc-4.9.3/local330/include"     -O2 -Wall  -mtune=core2 -c RcppExports.cpp -o RcppExports.o
c:/Rtools/mingw_32/bin/g++  -I"C:/R/R-3.3.1/include" -DNDEBUG -I"D:/projects/source/my_project"   -I"C:/Users/rk/Documents/R/win-library/3.3/Rcpp/include" -I"d:/Compiler/gcc-4.9.3/local330/include"     -O2 -Wall  -mtune=core2 -c cstyle.cpp -o cstyle.o
c:/Rtools/mingw_32/bin/g++ -shared -s -static-libgcc -o Package.dll tmp.def RcppExports.o cstyle.o -LD:/projects/source/my_project/Release -lproject -lprojectx64 -Ld:/Compiler/gcc-4.9.3/local330/lib/i386 -Ld:/Compiler/gcc-4.9.3/local330/lib -LC:/R/R-3.3.1/bin/i386 -lR
D:/projects/source/my_project/Release/projectx64.dll: file not recognized: File format not recognized
collect2.exe: error: ld returned 1 exit status
no DLL was created
ERROR: compilation failed for package 'Package'
* removing 'C:/Users/rk/Documents/R/win-library/3.3/Package'
* restoring previous 'C:/Users/rk/Documents/R/win-library/3.3/Package'

【问题讨论】:

  • 我想你误会了。默认情况下,Windows 上的 each 版本是 32 64 位。试试win-builder
  • 另外,这个:"D:/projects/source/my_project" 并不理想,因为它是绝对路径而不是相对路径,因此包会绑定到您的机器上。
  • R CMD 检查失败并显示相同的消息。我知道它默认使用这两种架构,但是如何链接正确架构的库文件呢?运行 R CMD INSTALL 为 32 位构建启动 32 位 gcc,并在尝试链接 64 位库时失败(显然)。
  • 包含外部库很难。我对lproject 一无所知,但FWIW 我也曾尝试在Rcpp 中包含一个C 库,并且只能在32 位Windows 上编译。作为指导,您应该查看包含外部库的其他一些 Rcpp 包的 Makevars。
  • 和/或仅在一个子架构上构建您的包。这与 Rcpp per se 无关,而是关于在 Windows 上构建(更高级的)包。这也有记录。

标签: r rcpp


【解决方案1】:

我听取了 Dirk 的建议,为每个架构构建了两个单独的包。 Makevars 当然只链接每个构建的相应库中。运行--no_multiarch 标志时使用的架构选择取决于PATH 中首先设置的R 版本。在命令提示符下运行R --version 可以查看版本。为每个构建更改您的PATH

我要补充一点,您必须在 Windows 上添加清单才能使其正常工作。将此添加到 Visual Studio 项目中的 stdafx.h 文件中:

#if defined _M_IX86
  #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_IA64
  #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='ia64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#elif defined _M_X64
  #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
#else
  #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
#endif

这是因为 R 使用 Window 的 LoadLibrary 函数来加载 DLL 时存在一个超级酷的错误(该错误已存在多年但未修复),它会在调用 64 位 DLL 时尝试调用 32 位通用控件 DLL,从而导致整个加载失败。

【讨论】:

  • 说“我听取了 Dirk 的建议,为每个架构构建了两个单独的包。”误解,甚至歪曲我所说的。
  • 这是一个src/Makefile.win(来自我是合著者的一个项目),它在处理外部库时可以适当地检测 32 位和 64 位。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-06-02
  • 2010-12-09
  • 2018-02-05
  • 2015-01-07
  • 1970-01-01
  • 2013-06-08
  • 2018-11-29
相关资源
最近更新 更多