G++ при попытке скомпилировать С++ 11 с Rcpp - программирование
Подтвердить что ты не робот

G++ при попытке скомпилировать С++ 11 с Rcpp

SPEC SPEC:

  • ОС - Mac OS X 10.6.8 (Snow Leopard)
  • g++ - Macports gcc 4.8.1_2 + universal
  • R - 2.15.3
  • Rcpp - 0.10.3

Я продолжаю получать ошибку, когда пытаюсь скомпилировать функции, которые используют С++ 11 в R (через Rcpp) - по какой-то причине g++ не распознает параметр -std=c++11.

Этот пример взят из файлов справки Rcpp (он не содержит ничего, что характерно для С++ 11, но может показать, что моя проблема). Если я попробую запустить:

require( Rcpp )
Sys.setenv( "PKG_CXXFLAGS"="-std=c++11" )
cppFunction(plugins=c("cpp11"), '
int useCpp11() {
    int x = 10;
    return x;
}')

Я получаю:

cc1plus: error: unrecognized command line option "-std=c++11"
make: *** [file61239328ae6.o] Error 1
g++ -arch x86_64 -I/Library/Frameworks/R.framework/Resources/include -I/Library/Frameworks/R.framework/Resources/include/x86_64 -DNDEBUG  -I/usr/local/include  -I"/Library/Frameworks/R.framework/Versions/2.15/Resources/library/Rcpp/include"   -std=c++11  -fPIC  -g -O2  -c file61239328ae6.cpp -o file61239328ae6.o 
Error in sourceCpp(code = code, env = env, rebuild = rebuild, showOutput = showOutput,  : 
  Error 1 occurred building shared library.

В то же время я могу скомпилировать эту функцию непосредственно из bash - если этот код находится в файле useCpp11.cpp, то это выполняется без каких-либо жалоб:

g++ useCpp11.cpp -std=c++11

Конечно, я делаю что-то неправильно, но я не могу понять, что это такое. gcc 4.8 устанавливается как компилятор по умолчанию в bash, Rcpp работает без ошибок в прошлом. Я подозреваю, что я не говорю R, какую версию g++ использовать - может ли это так?

4b9b3361

Ответ 1

Kevin Ushley абсолютно прав - самый простой способ убедиться, что правильный компилятор используется в файле Makevars. В моем случае я добавил:

CXX = g++-4.8.1
PKG_CXXFLAGS = -std=c++11

Это то, чего мне не хватало - и все это сработало потом. Это работает, если вы компилируете свой пакет.

Ответ 2

Быстрые:

  • вы отстаете от Rcpp, который находится в выпущенной версии 0.10.4

  • версия, которую вы используете (0.10.3), имеет плагин для С++ 11

  • есть вся статья в галерее Rcpp, которая подробно описывает это.

Поэтому позвольте мне процитировать из С++ 11 в галерее Rcpp:

R> library(Rcpp)
R> sourceCpp("/tmp/cpp11.cpp")
R> useAuto()
[1] 42
R> 

где код в /tmp/cpp11.cpp выглядит следующим образом:

#include <Rcpp.h>

// Enable C++11 via this plugin (Rcpp 0.10.3 or later)
// [[Rcpp::plugins("cpp11")]]

// [[Rcpp::export]]
int useAuto() {
    auto val = 42;      // val will be of type int
    return val;
}

Если это не работает для вас, ваша система не настроена правильно. Другими словами, это не вопрос для тега Rcpp, а скорее для того, "как мне настроить свой путь для вызова версии g++, я думаю, что я должен вызывать".

Ответ 3

Если вы не хотите исправлять свой путь, вы можете установить переменную среды PKG_CXXFLAGS непосредственно перед компиляцией.

     export PKG_CXXFLAGS='`Rscript -e "Rcpp:::CxxFlags()"` -std=c++11'

Например:

В R

#generate the bare Rcpp package as usual
library(Rcpp)
Rcpp.package.skeleton("Foo",
                      example_code=FALSE,
                      attributes=TRUE,
                      cpp_files=c("./Foo_R_wrapper.cpp", "./Foo.h", "/Foo.cpp")
                     )    

и в Bash

#tell the compiler to use C++11
export PKG_CXXFLAGS='`Rscript -e "Rcpp:::CxxFlags()"` -std=c++11'

#compile as usual
cd ./Foo/;
R -e 'Rcpp::compileAttributes(".",verbose=TRUE)';
cd ..;

R CMD build Foo;
#ensure that there are no bugs
R CMD check Foo;

где Foo_R_wrapper.cpp обертывает С++-функцию FooBar, определенную и реализованную в Foo.h и Foo.cpp соответственно.

Foo_R_wrapper.cpp может содержать следующее:

#include <Rcpp.h>                                   

#include "Foo.h"                                    

// [[Rcpp::export]]                                 
SEXP FooBar(SEXP baa)
{                                                   
    Rcpp::NumericVector baa_vec(baa)
    //Do something from Foo.h (to baa_vec?)
    ...
    //etc
    return baa_vec;
}