简体   繁体   中英

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

I'm building/installing an R package on Windows created with Rcpp skeleton. For a while I was just building a 32-bit version that links a 32-bit dll. My Makevars file looked like this:

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. Now I need the 64-bit version also. I made my Makevars look like this:

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. 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. What is a way around this to get it to sequentially link the dll's for the appropriate architecture?

As a PS I've read the big red text that says "NO WINDOWS!" in the Rcpp manual but that is simply inaccurate and I don't see how my issue would be different on Linux.

EDIT

Here is the output of the INSTALL command. It predicatbly fails when 32-bit gcc is launched and tries to link in the 64-bit dll specficied in the Makevars.

*** 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. Makevars of course only links in the appropriate library for each build. The choice of architecture used when running the --no_multiarch flag is determined by whichever R version is set first in your PATH . The version can be seen by running R --version in a command prompt. Change your PATH for each build.

I'll add that you have to add a manifest on Windows to get this to work. Add this to a stdafx.h file in a Visual Studio Project:

#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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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