简体   繁体   English

使用Rtools和外部库/ DLL构建64位R软件包

[英]Build 64-bit R Package with Rtools and External Library / DLL

I'm building/installing an R package on Windows created with Rcpp skeleton. 我正在使用Rcpp骨架创建的Windows上构建/安装R包。 For a while I was just building a 32-bit version that links a 32-bit dll. 有一段时间我只是在构建一个链接32位dll的32位版本。 My Makevars file looked like this: 我的Makevars文件如下所示:

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

and I would run 我会跑

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

In a cmd prompt and all would be fine. 在cmd提示符下,一切都会好的。 Now I need the 64-bit version also. 现在,我还需要64位版本。 I made my Makevars look like this: 我使我的Makevars看起来像这样:

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

Where my 64 bit dll is named projectx64.dll. 我的64位dll命名为projectx64.dll。 The issue is when I run the command: 问题是当我运行命令时:

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

The build fails because during the 32-bit build process because the compiler tries to link the 64 bit dll. 生成失败,因为在32位生成过程中,因为编译器尝试链接64位dll。 What is a way around this to get it to sequentially link the dll's for the appropriate architecture? 有什么方法可以解决这个问题,以便为适当的体系结构顺序链接dll?

As a PS I've read the big red text that says "NO WINDOWS!" 作为PS,我阅读了红色的大文字,上面写着“没有窗户!” in the Rcpp manual but that is simply inaccurate and I don't see how my issue would be different on Linux. 在Rcpp手册中,但这只是不准确,我看不出我的问题在Linux上会有什么不同。

EDIT 编辑

Here is the output of the INSTALL command. 这是INSTALL命令的输出。 It predicatbly fails when 32-bit gcc is launched and tries to link in the 64-bit dll specficied in the Makevars. 启动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'

I took Dirk's advice and built two separate packages for each architecture. 我接受了Dirk的建议,并为每种体系结构构建了两个单独的软件包。 Makevars of course only links in the appropriate library for each build. 当然,Makevars仅在每个构建的相应库中链接。 The choice of architecture used when running the --no_multiarch flag is determined by whichever R version is set first in your PATH . 运行--no_multiarch标志时使用的体系结构选择取决于PATH首先设置的R版本。 The version can be seen by running R --version in a command prompt. 通过在命令提示符下运行R --version可以查看R --version Change your PATH for each build. 更改每个构建的PATH

I'll add that you have to add a manifest on Windows to get this to work. 我要补充一点,您必须在Windows上添加清单才能使它起作用。 Add this to a stdafx.h file in a Visual Studio Project: 将此添加到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

This is because there's a super cool bug in Window's LoadLibrary function (that has been present for years without fix) used by R to load DLLs that will try to call a 32bit Common Controls DLL in calling your 64-bit DLL causing the entire load to fail. 这是因为R用来加载DLL的Window的LoadLibrary函数(已经存在多年未修复)中存在一个非常酷的错误,该DLL会尝试在调用64位DLL时调用32位Common Controls DLL,从而导致整个加载失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM