2017-03-28 44 views
2

提前道歉我确定是一个非常简单的问题,但我一直无法找到解决方案。我将一个非常简单的C++项目放在一起,但无法正确使用头文件。C++中头文件的问题:链接器命令失败

目录结构如下:

. 
├── mainGraph 
│   └── hnsw.cpp 
└── utils 
    ├── distances.cpp 
    └── distances.h 

的距离头文件(distances.h):

#ifndef DISTANCES 
#define DISTANCES 

#include <vector> 

enum class Metric { Cosine, Euclidean}; 

double distance(const std::vector<double>& A, const std::vector<double>& B, Metric metric); 
double similarity(const std::vector<double>& A, const std::vector<double>& B, Metric metric); 

#endif 

最后hnsw.cpp

#include "../utils/distances.h" 
#include <vector> 
#include <iostream> 

int main(){ 
    std::vector<double> A = {0.1, 0.5, 0.7, 1.1}; 
    std::vector<double> B = {0.5, 0.3, 0.8, 0.9}; 

    std::cout << distance(A, B, Metric::Cosine) << '\n'; 
} 

现在,当我真正尝试使用以下命令编译hnsw.cppg++ hnsw.cpp --std=c++11我得到以下错误:

Undefined symbols for architecture x86_64: 
    "distance(std::__1::vector<double, std::__1::allocator<double> > const&, std::__1::vector<double, std::__1::allocator<double> > const&, Metric)", referenced from: 
     _main in hnsw-ad0e05.o 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

如果我提出的主要入distances.cpp文件,然后一切工作顺利进行。为简洁起见,我不会发布整个文件,因为它很大,我相当确定它不相关。如果有任何关于理解这里的一般过程的资源,那也是非常有用的。

回答

3

如果你不想建立以后将个人目标文件,而是构建整个可执行文件一气呵成,你需要指定所有参与翻译在命令行上单位:

g++ -std=c++11 hnsw.cpp ../utils/distances.cpp 

输出文件将被称为a.out,除非您还使用-o标志覆盖该名称。

一般你会单独编译翻译单位和单独的步骤将它们链接:

g++ -std=c++11 mainGraph/hnsw.cpp -c -o mainGraph/hnsw.o 
g++ -std=c++11 utils/distances.cpp -c -o utils/distances.o 

g++ -std=c++11 mainGraph.hnsw.o utils/distances.o -o myprog 

,您也无法维持用手这些命令,但它们粘成一个Makefile文件,或某种等价构建系统。关键在于,您不需要重新编译仅仅因为您更改了某些部分源代码而未更改的翻译单元。

+0

这是非常有帮助的。事后看来,这似乎很明显,但事实并非如此。我得到的最后一个问题就是你的第二部分的订单。你有没有理由在距离之前编译hnsw?看起来反过来会更有意义,因为hnsw需要距离。 –

+0

@SlaterTyranus:两者不相关,可以按任何顺序编译,或者实际上可以并行编译(特别是如果你有多个核心的话)。这正是'make'会为你免费做的。 –

+0

@SlaterTyranus:要清楚的是,任何翻译单位在任何有意义的意义上都不“要求”另一方。只有链接需要*全部*的翻译单元。 (但是,两个翻译单元*都依赖*文件*距离.h,因此如果更改该文件,则需要重建两个TU。该文件构成两个TU的一部分。) –

2

当您运行g++ hnsw.cpp --std=c++11时,您告诉编译器编译hnsw.cpp并将输出链接到C++标准库以创建可执行文件。链接器无法找到distances的实现,因为它位于距离.pppp中。

您需要编译这两个文件并将它们链接在一起。有很多方法可以实现这一点,但最简单的是在调用gcc时指定两个源文件,如下所示:

g++ -std=c++11 hnsw.cpp ../utils/distances.cpp 
+0

谢谢你的回答!无赖,你失去了FGIW与305k代表的人的战斗:) –

相关问题