Linux下多个文件的C++工程编写、编译要点

时间:2022-05-18 09:15:00

编译流程:


假定有三个文件:

main.cpp:

#include <iostream>
#include "include/func1.hpp"

int main(){
	cout<<"this is main"<<endl;
	func1();
	return 0;
}

func1.hpp:
void func1();

func1.cpp:
#include <iostream>
void func1(){
	cout<<"this is func1"<<endl;
}

假定目录结构为:
./makefile
./func1.cpp
./include/func1.hpp

./main.cpp


其中func1.hpp仅给出了函数定义,
实现位于func1.cpp中。


自底向上地看,
1.预处理+编译:
g++ -c main.cpp -o main.o
#对main.cpp 进行预处理+编译,但不链接(选项-c),生成中间文件main.o(选项-o)

g++ -c func1.cpp -o func1.o
#同理


2.链接
g++ main.o func1.o -o program
#由main.o func1.o链接生成可执行文件program(选项-o似乎是指定输出文件名)


备注:
#如果只有一个main.cpp 作为源文件,g++ main.cpp可以直接预处理+编译+链接生成可执行文件a.out。
#g++ -E main.cpp -o main.ii可以只进行预处理,预处理生成的文件由-o指定,这里是main.ii。
#在上述的项目结构中,main.cpp中需要include位于./include的func1.hpp。这时,正确的写法是:
#include "./include/func1.hpp"
而不是
#include <./include/func1.hpp> (提示找不到文件)
这可能是因为,用<>括起来的一般都是系统的某些库,比如#include <iostream>,这样的include可能是要到特 殊的目录下去寻找相关文件的,所以用户自己的文件这样引用就可能出现“找不到”的情况。


#注意到上述项目中func1的定义和实现是分开的。那么,其定义和实现是在预处理-编译-链接的哪个阶段才整合在一起的呢?在预处理阶段,include 的内容会被整合到一个文件里。最初,func1.cpp中有#include "./include/func1.hpp"的语句。然而注意到,去掉这个语句之后,按上述操作仍能得到正确的program。因此推测,上述项目中func1的定义和实现直到编译阶段都还是分开的。分别编译后,定义位于main.o(因为main.o include 了func1.hpp), 而实现位于func1.o,两者直到链接完成后才整合到program中。也就是说,直到链接完成之后,main函数才能正确地“调用”func1。


上述项目的makefile如下:
all: program


program: main.o func1.o
        g++ main.o func1.o -o program


main.o: main.cpp
        g++ -c main.cpp -o  main.o


func1.o: func1.cpp
        g++ -c func1.cpp -o func1.o


clean: 
        rm *.o




如果项目中有定义和实现分开的情况,可以参考以下规则:
1.在写代码阶段,注意:
#调用函数的地方一定要正确地include被调用函数的定义(hpp),而并不需要关心其实现(cpp)在哪里。
2.在编译阶段,注意:
#每个.cpp生成一个对应的.o;
#所有的.o链接生成可执行文件。


如果项目结构变为:
./makefile
./src/func1.cpp
./src/main.cpp
./include/func1.hpp
保持main.cpp中为#include "include/func1.hpp";
makefile修改为:
all: program


program: main.o func1.o
        g++ main.o func1.o -o program


main.o: src/main.cpp
        g++ -c src/main.cpp -o  main.o


func1.o: src/func1.cpp
        g++ -c src/func1.cpp -o func1.o


clean: 
        rm *.o


执行make,发现提示找不到include/func1.hpp。
原先以为,遇到#include "xxx"的写法,预处理器寻找include文件的默认目录是makefile所在的目录,现在看来不是,推测应该是包含该#include语句的cpp所在的目录。查资料获知,可以通过增加如下指令选项来添加包含目录:
g++ -I. -c src/func1.cpp -o func1.o
这就是把makefile所在的目录添加到了预处理器的包含目录中,这样预处理器就会在.目录下寻找include/func1.hpp。


正确的makefile如下:
all: program


program: main.o func1.o
g++ main.o func1.o -o program


main.o: src/main.cpp
g++ -I. -c src/main.cpp -o  main.o


func1.o: src/func1.cpp
g++ -I. -c src/func1.cpp -o func1.o


clean: 
rm *.o


如果在编译时需要的包含文件存放在多个目录下,可以使用多个-I来指定各个目录:
g++ -I./include1 -I./include2 -c xxx.cpp -o xxx.o