使用 Rtools 和外部库/DLL 构建 64 位 R 包
Build 64-bit R Package with Rtools and External Library / DLL
我是 building/installing Windows 上使用 Rcpp 骨架创建的 R 包。有一段时间我只是在构建一个 link 是一个 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 位构建过程中,因为编译器试图 link 64 位 dll。有什么方法可以让它按顺序 link 相应架构的 dll?
作为 P.S。我已经阅读了 Rcpp 手册中写着 "NO WINDOWS!" 的大红色文本,但这根本不准确,我看不出我的问题在 Linux.
上会有什么不同
编辑
这是安装命令的输出。当启动 32 位 gcc 并尝试在 Makevars 中指定的 64 位 dll 中 link 时,它可能会失败。
*** 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'
我采纳了 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
这是因为 Window 的 LoadLibrary 函数(已存在多年未修复)中存在一个非常酷的错误,R 用于加载 DLL,该 DLL 将尝试调用 32 位通用控件 DLL调用您的 64 位 DLL 导致整个加载失败。
我是 building/installing Windows 上使用 Rcpp 骨架创建的 R 包。有一段时间我只是在构建一个 link 是一个 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 位构建过程中,因为编译器试图 link 64 位 dll。有什么方法可以让它按顺序 link 相应架构的 dll?
作为 P.S。我已经阅读了 Rcpp 手册中写着 "NO WINDOWS!" 的大红色文本,但这根本不准确,我看不出我的问题在 Linux.
上会有什么不同编辑
这是安装命令的输出。当启动 32 位 gcc 并尝试在 Makevars 中指定的 64 位 dll 中 link 时,它可能会失败。
*** 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'
我采纳了 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
这是因为 Window 的 LoadLibrary 函数(已存在多年未修复)中存在一个非常酷的错误,R 用于加载 DLL,该 DLL 将尝试调用 32 位通用控件 DLL调用您的 64 位 DLL 导致整个加载失败。