1、需求:
一个大的项目通常还会将程序的.c和.h文件放在项目的不同文件夹内,那么在编译的时候,编译器默认不会在这些不同文件夹中搜索头文件,编译器默认在当前目录下搜索头文件
为了解决这个问题,需要在编译的时候告诉它,头文件在哪例如:
-I./submodule # 指定头文件在本目录下的submodule文件夹下
在调用库函数的时候如调用#include <stdio.h> 和#include <pthread>库的时候需要指定pthread的位置
这是因为stdio.h标准库被安装在操作系统提供的目录里,编译器会自动寻找这些头文件,而pthread,位于不同的位置,所以需要给编译器指定位置,以让编译器能找到这个库
-L/path/to/libs -lpthread # 指定动态库位置
一个庞大的项目每个模块可以由当前模块下的Makefile控制,而这些Makefile又可以由一个共同的父Makefile控制编译整个项目的时候直接调用父Makefile即可
2、试例:
在这个小项目内需要生成一个test可执行文件其中.c文件和.h文件都在不通的文件夹内,用Makefile控制项目编译
朴素版代码:
# Makefile
test: main.o module.o # 可执行文件test依赖main.o与module.o文件
gcc main.o module.o -o test -I ./submodule -I ./ # 生成可执行文件,并指定需要用到的头文件位置(-I后跟头文件路径)
#编译器编译的时会根据上述路径去便利
main.o: main.c
gcc -c main.c -o main.o -I ./sumodule -I ./
module.o: ./submodule/module.c
gcc -c ./submodule/module.c -o module.o -I ./ # module.c在其他文件夹所以也要指定位置
clean:
rm -f *.o test # 伪目标,删除当前文件夹下全部.o文件和名为test的文件
优雅代码:
# Makefile
VPATH = ./submodule # 路径
TAR = test # 目标文件
INC = -I./submodule -I ./ # 指定头文件位置
OBJ = main.o module.o # 依赖
$(TAR) : $(OBJ)
gcc *.o -o $@ $(INC) # 用所有.o文件去编译得到目标文件
%.o : %.c
gcc -c $< -o $@ $(INC) # 用任意.c文件编译得到.o文件$<代表当前规则第一个依赖文件即.o依赖文件.c文件,$@指的所有目标文件
clean:
rm -f *.o $(TAR) # -f是强制删除