我试图使用samtools C API(https://github.com/samtools/samtools)编译(在Linux上,使用G ++)一个简单的main.cpp程序,该程序已下载到main.cpp文件的文件夹中。 我想有一个非常简单的makefile来编译main.cpp(并最终编译samtools代码)。但是,由于我对makefile的了解很少,所以我可能做错了。
这是我的makefile:
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无法打开共享对象文件”
任何帮助都倍受欢迎!预先感谢。
答案 0 :(得分:1)
这不是您的makefile本身的问题;您的makefile遇到一些问题,但是您遇到的问题是了解如何正确地与共享库链接。换句话说,如果您从Shell命令行运行相同的命令集,而不是使用makefile,则会遇到相同的问题。
您应该在链接命令行选项-L
中查找文档,并了解 link-time 和 run-time 库位置之间的区别。< / p>
-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
目录并且它们中仍然包含正确的共享库,这将很好地工作。显然,这是一个很大的限制,但是我们无法猜测您的最终要求是什么。