先看两篇博文,作为基础知识。如果对C/C++编译链接过程都了解的话,可以跳过不看。
一、编译不同目录下的多个文件
各个文件的布局如下:
head.h文件的代码:
#ifndef HEAD_H#define HEAD_Hint add(int a, int b);#endif /*HEAD_H*/
head.cpp文件的代码:
#include "head.h"int add(int a, int b){return a + b;}
main.cpp文件的代码(head.h头文件还没包含)
#include <iostream>using namespace std;int main(int argc, char *argv[]){cout<<add(3, 5)<<endl;return 0;}1)以相对路径的方式直接包含头文件
为了能够使用add函数,必须包含add所在的头文件。 最简单的方法是直接在main.cpp文件中,用相对路径包含head.h文件.即 #include”function/head.h”。完整代码为
#include <iostream>#include "function/head.h"using namespace std;int main(int argc, char *argv[]){cout<<add(3, 5)<<endl;return 0;}
此时,编译命令为 :$g++ main.cpp function/head.cpp -o main
这种用相对路径包含头文件的方式有很多弊端。当function目录改成其它名字,或者head.h文件放到其它目录了,这时都要对main.cpp文件进行修改,如果head.h头文件被很多其它文件包含的话,这个工作量就大多了。
2)用编译选项 –I(大写i)
其实,可以想一下,为什么iostream文件不在当前目录下,就可以直接使用呢?这是因为,编译器会在一些默认的目录下(/usr/include,/usr/inlucde/c++/4.4.3等目录)搜索头文件。所以,iostream头文件不用添加。但我们不能每写一个头文件就放到那里。
知道了原理,现在来用一下一个编译选项 –I(include的缩写)用来告诉编译器,还可以去哪里找头文件。
使用这个编译命令,$g++ main.cpp function/head.cpp -Ifunction -o main
此时main.cpp文件写成
#include <iostream>#include <head.h>using namespace std;int main(int argc, char *argv[]){cout<<add(3, 5)<<endl;return 0;}
可以看到head.h文件是用<>而不是””。想一下C语言书中,两者的区别。这说明,用-I选项,相当于说明了一条标准路径。
3)使用.o文件
此时,对于head.cpp文件,在编译命令中,还是要用到路径function/head.cpp。现在的想法是去掉这个。这时可以先根据head.cpp文件生成一个.o文件,然后就可以了去掉那个路径了。
先cd 到function目录。
输入命令:$g++ -c head.cpp -o head.o
生成一个head.o目标文件,
此时把生成的head.o文件复制到function的父目录,就是main.cpp所在的目录。
然后回到function的父目录,输入命令$g++ main.cpp head.o -Ifunction -o main
此时,直接使用head.o即可,无需head.cpp了。但头文件head.h还是要的。因为编译的时候要用到。链接的时候不用头文件。这个可以拆分成两条命令
$g++ -c main.cpp -Ifunction -o main.o
$g++ main.o head.o -o main
第一条是编译命令,后一条是链接命令。
二、静态库
虽然上面说到的先生成.o目标文件,但如果function目录下有多个.cpp文件。那么就要为每一个.cpp文件都生成一个.o文件,这个工作量是会比较大。此时可以用静态库。静态库是把多个目标文件打包成一个文件。Anarchive(or static library) is simply a collection of object filesstored as a single file(摘自《Advanced Linux Programming》)。
下面介绍静态库
此时,文件布局为:
head.h文件代码
#ifndef HEAD_H#define HEAD_Hint add(int a, int b);int sub(int a, int b);#endif /*HEAD_H*/
add.cpp文件代码
#include "head.h"int add(int a, int b){return a + b;}
sub.cpp文件代码
#include "head.h"int sub(int a, int b){return a – b;}
首先,生成.o目标文件。
cd进入function目录,输入命令$g++ -c sub.cpp add.cpp 这会分别为两个源文件目标文件,即生成sub.o和add.o文件。
然后,打包生成静态库,即.a文件。
输入命令$ar -cr libhead.a add.o sub.o
注意:
1) 命令中,.a文件要放到 .o文件的前面
2) .a文件的格式。要以lib作为前缀, .a作为后缀。
选项 c是代表create,创建.a文件。
r是代表replace,如果之前有创建过.a文件,现在为了提高性能而更改了add函数里面的代码,此时,就可以用r选项来代替之前.a文件里面的add.o
可以用命令$ar -t libhead.a 查看libhead.a文件里面包含了哪些目标文件。其执行结果自然为add.o sub.o
现在回过头来关注main.cpp文件。
呼唤你前往另一个地方,过上另一种生活。