1、 What is “makefile” :
make命令执行时,需要一个makefile文件,用来告诉make命令需要怎么样的编译和链接程序
makefile其实就是make命令的配置文件
2、 makefile的规则
格式:
target : prerequisites
command
白话 : 用 command 将 prerequisites 生成 target
[注]
target : 要生成的目标文件,可以是 object file,也可以是执行文件,还可以是一个 Label(标签)
prerequisites : 依赖哪些文件,要生成target 所需要的文件
command : 需要执行的命令(任意shell命令)
另外书写的格式,target左靠齐,command前是 ‘Tab’,不能是4个空格!
举个栗子:
hello.c 的 makefile : 生成可执行文件
hello : hello.c
gcc hello.c -o hello
执行make命令即可生成可执行文件
注意事项:
3、 通过例子来读懂&使用makefile
Ex1:
#1
hello : hello.o test.o
gcc -o hello hello.o tset.o
#2
hello.o : hello.c test.h
gcc -c hello.c
#3
test.o : test.c test.h
gcc -c test.c
#4
clean :
rm hello hello.o test.o
“#1”: 目标是生成hello可执行文件,依赖文件有hello.o , test.o ,但是当前没有hello.o ,test.o文件,hello.o, test.o是下面生成的,所以执行”#2,#3”,生成”#1”所需的依赖文件
“#2”: 通过gcc -c , hello.c -> hello.o
“#3”: 通过gcc -c , test.c -> test.o
最后”#1”的依赖文件生成,最终#1生成hello可执行文件
拓展:通过gcc命令实现上述makefile 功能
s1 : gcc -c test.c -o test.o
s2: gcc -c hello.c -o hello.o
s3 :gcc -o hello hello.o test.o
当然对应的头文件,库的目录地址通过 -I
, -L
参数选项来解决,不做阐述
EX2:引入变量
有没有发现EX1中 hello.o test.o出现多次,我们可以引入变量来简化makefie的编写
#1
objects = hello.o test.o
#2
hello : $(objects)
gcc -o hello $(objects)
#3
hello.o : hello.c test.h
gcc -c hello.c
#4
test.o : test.c test.h
gcc -c test.c
#5
clean :
rm hello $(objects)
引入变量 objects , 简化编写
Ex3: 自动推演
#1
objects = hello.o test.o
#2
hello : $(objects)
gcc -o hello $(objects)
#3 自动推演,这是makefile的规则 !!!
hello.o : test.h
#4
clean :
rm hello $(objects)
利用makefile 自动推演的规则
Ex4: 自动变量
#1
objects = hello.o test.o
#2
hello : $(objects)
gcc -o hello $(objects)
#3 !!!采用自动变量
%.o : %.c
gcc -c $< -o $@
#4 定义伪目标
.PHONY : clean
clean :
rm hello $(objects)
整理自动变量的含义:
(1) : 冒号表示依赖的意思 例如 A : B 即A依赖B
(2) $<
第一个依赖文件,形如上面的B
(3) $@
目标文件
(4) $^
所有的依赖文件
“#3” : 这里的自动变量$<
表示所有的.c文件,$@
表示所有的.o文件;
#3语句的功能是将当前目录下的所有.c文件编译汇编成 .o文件(即.o文件都是依赖与相应的.c文件的)
[注] “#3”是当前目录,思考补充:编译选项,头文件路径,链接库目录分别在哪添加?
A1:编译选项(如-g…):在-c那一行后面加
A2:头文件路径:也在 -c 那一行加入
A3:链接库: 是在 -o 那一行添加
Ex5 :含有 编译选项 & 头文件 & 库
#1
target=hello
#2
objects = hello.o test.o
#3
flags = -g #编译选项
header_path = -I. #头文件路径
lib_path = -L. #lib库路径
libs = -lpthread #库名 libpthread.so
#4
hello : $(objects)
gcc -o $(target) $(objects) $(lib_path) $(libs)
#5
%.o : %.c
gcc -c $(flags) $(header_path) $< -o $@
#6
.PHONY : clean
clean :
rm $(target) $(objects)
Ex6: 动态库
target = libtest.so
object = test.o
hello: $(object)
gcc -o $(target) $(object) -fPIC -shared #链接时添加后面两个参数
%.o : %.c
gcc -c fPIC $< -o $@ #生成库,添加FPIC参数选项
.PHONY : clean
clean :
rm $(target) $(object)
补充:动态库的搜索路径
找不到相应的动态库,两种方法解决:
(1)LD_LIBRARY_PATH
LD_LIBRARY_PATH
export LD_LIBRARY_PATH = /data/xxx/lib : $LD_LIBRARY_PATH
找动态库,先去系统路径下找(PATH),找不到,再去LD_LIBRARY_PATH路径下找
(2) /ect/ld.so.conf (推荐方案)
手动配置一个配置文件,在动态库目录下,本例在lib下
例:
[root@zzz lib] # cat /etc/ld.so.conf
include ld.so.conf.d/*.conf
设置方法