Как связать с уже скомпилированными внешними общими библиотеками в RCPP, используя Makevars? - PullRequest
2 голосов
/ 04 июля 2019

Я посмотрел несколько мест, но не смог найти простой пример для моей проблемы.

Мне нужно иметь возможность использовать несколько файлов .so, которые у меня есть (вместе с файлами .h).

Простой пример:

У меня есть следующие файлы: ах, a.cpp функция jeden - это моя библиотека R, accessor.cpp, которая предоставляет R функцию dwa извнешняя библиотека libdwa.so.У меня есть заголовочный файл dwa.h и эта библиотека libdwa.so.

Я могу управлять сборкой двоичного пакета (и все работает нормально) только и только тогда, когда я помещаю библиотечный файл libdwa.so в каталог '/ usr / lib '(я использую Debian).Но это не совместимое решение.

Где я должен поместить файлы библиотеки "dwa" (dwa.h и libdwa.so) и какие флаги добавить в файл Makevars, чтобы получить переносимое решение?

РЕЗЮМЕ ДОБАВЛЕНО

Я суммирую свои результаты здесь.Я полагаю, что некоторые чрезвычайно простые примеры полезны при запуске.

  1. 2 внешние библиотеки, помещенные в inst :

    /inst/include/dwa.h
    /inst/include/trzy.h
    /inst/jeden/libdwa.so
    /inst/jeden/libtrzy.so
    
  2. Настройка Файл / Настройка имеет форму (test6 - это имя пакета):

    #!/bin/bash
    rpath=$(${R_HOME}/bin/Rscript -e 'cat(file.path(.libPaths()[1], "test6", "jeden"))') #'
    sed -e"s|@rpath@|"${rpath}"|" src/Makevars.in > src/Makevars
    
    exit 0
    
  3. Файл /src/Makevars.in имеет вид:

    CXX_STD = CXX11
    
    PKG_CPPFLAGS = -I../inst/include/ -I.
    PKG_LIBS     = -ldwa -ltrzy -L../inst/jeden -Wl,-rpath,@rpath@
    
  4. / src / accessor.cpp предоставляет функции библиотек R:

    #include <Rcpp.h>
    #include "../inst/include/dwa.h"
    #include "../inst/include/trzy.h"
    
    // [[Rcpp::export]]
    Rcpp::String r_dwa() {
      Rcpp::String res = dwa();.
      return res;
    }
    
    // [[Rcpp::export]]
    Rcpp::String r_trzy() {
      Rcpp::String res = trzy();.
      return res;
    }
    
  5. Библиотека Pure R также существует / / src / hello_world.cpp_:

    #include <Rcpp.h>
    using namespace Rcpp;
    
    // [[Rcpp::export]]
    String hello_world() {
      String hw = "Hello World";
      return hw ;
    }
    
  6. Окончательно / NAMESPACE файл:

    useDynLib("test6", .registration=TRUE)
    
    import("Rcpp")
    importFrom("utils", "object.size", "packageVersion")
    exportPattern("^[[:alpha:]]+")
    

Сборка исходных и двоичных пакетов прошла успешно, но только исходных один полезен в качестве двоичный файл имеет путь к библиотекам, написанным жестко.

1 Ответ

6 голосов
/ 04 июля 2019

Предположим, у вас есть структура каталогов, подобная

/opt/dwa/include/dwa.h
/opt/dwa/lib/libdwa.so

. В этом случае вы можете использовать src/Makevars:

PKG_CPPFLAGS = -I/opt/dwa/include
PKG_LIBS = -L/opt/dwa/lib -ldwa -Wl,-rpath,/opt/dwa/lib

Конечно, это все еще не переносимо, так какпуть к библиотеке и заголовочным файлам жестко запрограммирован.Чтобы обойти это, можно использовать файл шаблона, например, src/Makevars.in

PKG_CPPFLAGS = @DWA_INC@
PKG_LIBS = @DWA_LIB@

и написать сценарий configure, который проверяет среду и создает src/Makevars на основе результатов.Существуют разные стратегии написания configure скриптов.Я обычно использую autoconf, например, в RcppArrayFire или dqmagic .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...