Как я могу загрузить модули C++ и включить флаги компиляции как часть компиляции пакета Rcpp?

Я использую Rcpp, чтобы обернуть программу на C ++ в пакет R. Моей программе на C ++ требуется следующий заголовок:

      #include "htslib/sam.h"

Перед компиляцией я обычно загружаю в Ubuntu следующий модуль:

      HTSlib/1.11-GCC-9.3.0

Обычно я компилирую сценарий C ++ со следующими флагами в Ubuntu, используя GCC / 9.3.0:

      g++ scriptname.cpp -Ihtslib -Lhtslib -lhts

Поскольку я получаю доступ к программе из R через Rcpp, я не знаю, как загрузить модуль HTSlib. Когда я пытаюсь «очистить и перестроить» пакет, я получаю следующую ошибку:

      fatal error: htslib/sam.h: No such file or directory
    #include "htslib/sam.h"
                           ^
   compilation terminated.

У меня два вопроса:

  1. Как загрузить модули C ++ при сборке пакета R из исходного кода C ++?

  2. Как включить флаги компиляции при сборке пакета R из исходного кода C ++?

Я создал минимальный заголовочный файл, файл .R и исходный скрипт на C ++. Сценарий открывает файл BAM и выводит имена хромосом и позиции считываний. Эти файлы не представляют собой реальную программу, которую я хочу запустить (которая слишком длинна и сложна для включения сюда), но генерируют ту же ошибку, когда я пытаюсь создать пакет с помощью Rcpp.

Исходный файл C ++:

      #include "htslib/sam.h"
#include <string>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <Rcpp.h>
#include "HTSlibBasics.h

void OpenBam(std::string command_string){
    // Stores filename and converts to character string
    const char * char_command;
    char_command = command_string.c_str();
    
    // Opens bam file
    samFile *fp = sam_open(char_command, "r");
    
    // Opens bam header
    bam_hdr_t *h = sam_hdr_read(fp);
    
    // Initialize an alignment
    bam1_t *b = bam_init1();
    
    while(sam_read1(fp, h, b) >= 0) {
        if (b->core.tid < 0){
            continue;
        }else{
            std::cout << h->target_name[b->core.tid] << "\t" << b->core.pos << "\t" << bam_endpos(b) << std::endl;
       }
    }
    
    /*
    * Destroy the alignment and header which have been read into the C++ program
    * and close the sam file.
    */
    bam_destroy1(b);
    bam_hdr_destroy(h);
    sam_close(fp);
}

Заголовочный файл:

      #ifndef OPEN_BAM
#define OPEN_BAM

//' Documentation
//' @param command_string Documentation
// [[Rcpp::export]]
void OpenBam(std::string command_string);

#endif // OPEN_BAM

R файл:

      ## usethis namespace: start
#' @useDynLib HTSlibBasics, .registration = TRUE
## usethis namespace: end
NULL
## usethis namespace: start
#' @importFrom Rcpp sourceCpp
## usethis namespace: end
NULL
#' Documentation
#' @export
OpenBam <- function(command_string) {
  .Call(`_HTSlibBasics_OpenBam`, command_string)
}

Файл R находится в каталоге «R» пакета, а сценарий C ++ и заголовок - в каталоге «src».

1 ответ

Я понял: оказывается, ответ был довольно простым. Я вольно следил за виньеткой Дирка Эддельбюттеля (https://cloud.r-project.org/web/packages/Rcpp/vignettes/Rcpp-libraries.pdf), а также собрал целую кучу информации из Интернета.

В командной строке я перешел в каталог HTSlib в своей системе:

      cd /sw/eb/sw/HTSlib/1.11-GCC-9.3.0/

Затем я перешел в каталог с заголовочными файлами htslib и переместил их в каталог src / моего пакета R:

      cd include/htslib
cp *.h /home/annabelperry/R/HTSlibBasics/src/

Затем я перешел к своему исходному файлу C++ и изменил заголовок include "htslib/sam.h" к include "sam.h", так как моего файла sam.h больше не было в каталоге htslib.

Затем я перешел в каталог библиотек HTSlib и скопировал каждый из файлов в каталог за пределами моего пакета R. (Примечание: я попытался скопировать весь каталог и переместить его, но это привело к проблемам с доступом к редактированию).

      cd /sw/eb/sw/HTSlib/1.11-GCC-9.3.0/lib
cp libhts.a /home/annabelperry/R/lib/
cp libhts.so /home/annabelperry/R/lib/
cp libhts.so.1.11 /home/annabelperry/R/lib/
cp libhts.so.3 /home/annabelperry/R/lib/
cd pkgconfig
cp htslib.pc /home/annabelperry/R/lib/pkgconfig/

Затем я создал файл под названием Makevars в каталоге src / моего пакета R и ввел это:

      CXX_STD = CXX11
PKG_CXXFLAGS = -Ihtslib
PKG_LIBS = -L/home/annabelperry/R/lib -lhts -Wl,-rpath,/home/annabelperry/R/lib

В -L флаг компоновщика указывает каталог, в котором можно найти файлы библиотеки и -l Флаг компоновщика дает базовое имя файлов библиотеки.

Когда я попытался собрать пакет, я получил сообщение об ошибке libcrypto.so.10библиотека не может быть найдена. Я переместил эту библиотеку из исходного каталога, /usr/lib64, в /home/annabelperry/R/lib/ каталог с остальными файлами моей библиотеки.

Мне также пришлось удалить все std::cout вызовы из моего исходного кода, так как они несовместимы с Rcpp.

После этого я смог успешно собрать пакет.

Другие вопросы по тегам