Rcpp: не может открыть общий объектный файл - PullRequest
1 голос
/ 21 октября 2019

Я пытаюсь разработать пакет R, который использует Arrayfire , благодаря библиотеке Rcpp. Я начал писать пример кода (назовем его hello_world.cpp ), который выглядит следующим образом:

#include <arrayfire.h>

// [[Rcpp::export]]
bool test_array_fire(){
    af::randu(1, 4);    
    return true;
}

Затем я попытался скомпилировать его с помощью sourceCpp функции

Rcpp::sourceCpp('src/hello_world.cpp')

Моим первым сюрпризом стало то, что мне пришлось установить некоторые флаги вручную (sourceCpp, кажется, игнорирует конфигурацию Makevars при компиляции фрагмента кода C ++). Я сделал это с:

Sys.setenv("PKG_CXXFLAGS"="-std=c++11")
Sys.setenv("PKG_CPPFLAGS"="-I/opt/arrayfire/include/")
Sys.setenv("PKG_LIBS"="-L/opt/arrayfire/lib64/ -laf")

Тем не менее, код по-прежнему не компилируется должным образом. Каждое испытание заканчивается следующим выводом:

Error in 'dyn.load("/tmp/RtmpHaODIU/sourceCpp-x86_64-pc-linux-gnu-1.0.2/sourcecpp_689c5adb8d/sourceCpp_14.so")':
unable to load shared object '/tmp/RtmpHaODIU/sourceCpp-x86_64-pc-linux-gnu-1.0.2/sourcecpp_689c5adb8d/sourceCpp_14.so':
  libaf.so.3: cannot open shared object file: No such file or directory

К сожалению, я не смог найти решение своей проблемы (даже если некоторые вопросы переполнения стека поднимают проблемы, которые более или менее похожи на первый взгляд).

Как это исправить?

Ответы [ 2 ]

3 голосов
/ 21 октября 2019

Ошибка возникает очень поздно в процессе, когда R пытается загрузить файл общего объекта. Это означает, что компиляция и компоновка работали нормально с помощью заданных вами переменных среды. Но на последнем этапе компоновщик времени выполнения не знает, где находится libaf.so.3. Это конфигурация, обычно выполняемая на уровне ОС, например, в моей системе

ralf@barra:~$ /sbin/ldconfig -p | grep libaf
        libafopencl.so.3 (libc6,x86-64) => /lib/libafopencl.so.3
        libafopencl.so (libc6,x86-64) => /lib/libafopencl.so
        libafcpu.so.3 (libc6,x86-64) => /lib/libafcpu.so.3
        libafcpu.so (libc6,x86-64) => /lib/libafcpu.so
        libaf.so.3 (libc6,x86-64) => /lib/libaf.so.3
        libaf.so (libc6,x86-64) => /lib/libaf.so

. И если я попробую ваш пример, он без проблем будет работать с общим объектным файлом, который связан с libaf:

ralf@barra:~$ ldd /tmp/RtmpcjY9dN/sourceCpp-x86_64-pc-linux-gnu-1.0.2/sourcecpp_13d33790279c/sourceCpp_7.so | grep libaf
        libaf.so.3 => /lib/libaf.so.3 (0x00007f21037ed000)

Я ожидаю, что в вашем случае первая команда не даст результата, а вторая (скорректированная) команда приведет к ошибке «файл не найден» (?).

Существует несколько способов. Чтобы сообщить исполняющему компоновщику о местонахождении библиотеки:

  • Изменить /etc/ld.so.conf или (лучше) поместить файл в /etc.ld.so.conf.d/, ср http://arrayfire.org/docs/installing.htm#Linux.
  • УстановитьLD_LIBRARY_PATH.
  • Добавить -Wl,-rpath,/opt/arrayfire/lib64/ в PKG_LIBS
  • Установить ArrayFire в каталог, который компоновщик ищет по умолчанию. Это то, что я делаю, так как я компилирую из исходного кода и использую результирующие пакеты DEB .

Что касается Rcpp::sourceCpp, не относящегося к файлу Makevars: проблема в том, чтоФайл C ++, который вы пишете, не может быть использован напрямую. Вместо этого атрибуты Rcpp должны создавать дополнительные функции-оболочки, что делается во временном каталоге. Теперь можно в принципе скопировать файл Makevars в этот каталог. Однако обычно такие переменные устанавливаются с помощью атрибутов Rcpp::plugins и Rcpp::depends. Например, включение C ++ 11 выполняется с помощью // [[Rcpp::plugins(cpp11)]]. Что касается других переменных, вы можете написать свой собственный плагин или наш плагин, предоставленный моим RcppArrayFire .

Однако я предлагаю вам начать с пакета, если это ваша цель. Rcpp::sourceCpp отлично подходит для многих вещей, но взаимодействие с установленной системой библиотекой без помощи пакета R. не входит в их число.

2 голосов
/ 21 октября 2019

Несколько вещей, быстро:

  • когда вы используете sourceCpp() вы не используете пакет
  • случайное удаление переменной, используемой с пакетом, не помогает
  • там на самом деле есть пакет Ральфа, который, вероятно, прозвучит в
  • , и у нас есть запись об этом здесь, в Галерее Rcpp

Так что я бы, вероятно, начал с переделки / перестройки примеров из статьи Rcpp Gallery о RcppArrayFire .

...