Я пытаюсь скомпилировать (в Linux, используя G ++) простую программу main.cpp, используя samtools C API (https://github.com/samtools/samtools), который я скачал в папке моего файла main.cpp.
Я хотел бы иметь очень простой make-файл, компилирующий main.cpp (и в конечном итоге компилирующий код samtools). Однако, поскольку у меня очень мало знаний о make-файлах, я, вероятно, что-то делаю не так.
Вот мой make-файл:
SAMTOOLS=./samtools/
HTSLIB=${SAMTOOLS}htslib-1.9/
all: samtools htslib BAMCoverage
samtools:
${MAKE} -C ${SAMTOOLS}
htslib:
${MAKE} -C ${HTSLIB}
BAMCoverage: main.cpp
g++ -I./ -I${SAMTOOLS} -I${HTSLIB} -g -O2 -Wall ./main.cpp -o ./BAMCoverage -lz -L${SAMTOOLS} -L${HTSLIB} -lbam -lhts
И вот мой главный cpp:
#include "samtools/sam.h"
#include <string>
#include <iostream>
using namespace std;
int main (int argc, char *argv[]) {
string bam_file_path ("myfile.bam");
bamFile bam_file = bam_open (bam_file_path.c_str (), "rb");
if (bam_file == 0) {
cerr << "Failed to open BAM file " << bam_file_path << endl;
return 1;
}
bam_close (bam_file);
return 0;
}
Он компилируется без предупреждения, когда я запускаю «make», но во время выполнения он сообщает мне: «ошибка при загрузке общих библиотек: libhts.so.2 не может открыть файл общих объектов»
Любая помощь приветствуется! Заранее спасибо.
Это не проблема с вашим make-файлом как таковым; у вашего make-файла есть некоторые проблемы, но проблема, с которой вы сталкиваетесь, заключается в понимании того, как правильно связываться с общими библиотеками. Другими словами, если вы запустите тот же набор команд из командной строки оболочки, вместо использования make-файла, у вас возникнет та же проблема.
Вы должны искать документацию по вашей опции командной строки ссылки -L
и прочитайте о разнице между ссылка времени а также время выполнения места расположения библиотеки
-lfoo
опция сообщит компоновщику ссылку в библиотеку с именем foo
, -Lsome/dir
опция скажет компоновщику найти эту библиотеку foo
в каталоге some_dir
,
Если компоновщик находит статическую библиотеку libfoo.a
тогда любые части этой библиотеки, необходимые для связи вашей программы, будут включены непосредственно в вашу программу. Это делает вашу программу больше, но это означает, что в время выполнения ничего кроме вашей программы не нужно искать.
Если компоновщик находит общую библиотеку (также называемую динамической библиотекой) libfoo.so
тогда компоновщик просто помещает ссылку на имя библиотеки libfoo.so в вашу программу (конечно, детали сложнее, чем это, но это общая идея). Это делает вашу программу меньше но это означает, что во время выполнения нужна не только ваша программа, но и общая библиотека, иначе ваша программа не может быть запущена.
Это называется связывание во время выполнения и программа, используемая для разрешения всех этих общих ссылок при запуске вашей программы, называется компоновщик во время выполнения. По очень веским причинам ссылка, которую компоновщик во время компиляции помещает в вашу программу, просто перечисляет название библиотеки, а не полный путь к библиотеке. Это означает, что компоновщик времени выполнения должен знать, где искать общую библиотеку.
Компоновщик во время выполнения просматривает различные места, о которых можно узнать, прочитав его документацию; например, в GNU / Linux временный компоновщик называется ld.so
так что вы можете читать документы с man ld.so
,
Это сложная тема, и лучший способ сделать это зависит от ваших потребностей и потребностей.
Если вы просто хотите жестко прописать путь для поиска во время компиляции / компоновки, вы можете добавить -Rsome/dir
вариант для вашей линии связи, по одному для каждого -L
вариант, вот так:
BAMCoverage: main.cpp
g++ -I./ -I${SAMTOOLS} -I${HTSLIB} -g -O2 -Wall ./main.cpp -o ./BAMCoverage -lz -L${SAMTOOLS} -L${HTSLIB} -R${SAMTOOLS} -R${HTSLIB} -lbam -lhts
Это будет хорошо работать, пока SAMTOOLS
а также HTSLIB
каталоги существуют и до сих пор содержат правильные общие библиотеки в них. Очевидно, что это большое ограничение, но мы не можем догадаться, каковы ваши конечные требования.
Других решений пока нет …