makefile : 读懂 & 使用 makefile

1、 What is “makefile” :
make命令执行时,需要一个makefile文件,用来告诉make命令需要怎么样的编译和链接程序
makefile其实就是make命令的配置文件

2、 makefile的规则
格式:
target : prerequisites
  command

  
白话 : 用 commandprerequisites 生成 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命令即可生成可执行文件

注意事项:

  1. target从文件的行首开始
  2. command前面只允许且必须有一个tab符,而不能有其他的任何字符
  3. makefile中的注释以字符 “#”开始

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

设置方法

  • 在/ect/ld.so.conf.d/下创建一个自己的配置文件,如:mytest.conf
  • 在mytest.conf中添加 : /data/zzz/lib/lib
  • ldconfig     //使文件生效
Make命令   在make命令后不仅可以出现宏定义,还可以跟其他命令行参数,这些参数指定了需要编译的目标文件。其标准形式为:   target1 [target2 …]:[:][dependent1 …][;commands][#…]   [(tab) commands][#…]   方括号中间的部分表示可选项。Targets和dependents当中可以包含字符、数字、句点和"/"符号。除了引用,commands中不能含有"#",也不允许换行。   在通常的情况下命令行参数中只含有一个冒号":",此时command序列通常和makefile文件中某些定义文件间依赖关系的描述行有关。如果与目标相关连的那些描述行指定了相关的command序列,那么就执行这些相关的command命令,即使在分号和(tab)后面的aommand字段甚至有可能是NULL。如果那些与目标相关连的行没有指定command,那么将调用系统默认的目标文件生成规则。   如果命令行参数中含有两个冒号"::",则此时的command序列也许会和makefile中所有描述文件依赖关系的行有关。此时将执行那些与目标相关连的描述行所指向的相关命令。同时还将执行build-in规则。   如果在执行command命令时返回了一个非"0"的出错信号,例如makefile文件中出现了错误的目标文件名或者出现了以连字符打头的命令字符串,make操作一般会就此终止,但如果make后带有"-i"参数,则make将忽略此类出错信号。   Make命本身可带有四种参数:标志、宏定义、描述文件名和目标文件名。其标准形式为:   Make [flags] [macro definitions] [targets]   Unix系统下标志位flags选项及其含义为:   -f file  指定file文件为描述文件,如果file参数为"-"符,那么描述文件指向标准输入。如果没有"-f"参数,则系统将默认当前目录下名为makefile或者名为Makefile的文件为描述文件。在linux中, GNU make 工具在当前工作目录中按照GNUmakefilemakefileMakefile的顺序搜索 makefile文件。   -i   忽略命令执行返回的出错信息。   -s   沉默模式,在执行之前不输出相应的命令行信息。   -r   禁止使用build-in规则。   -n   非执行模式,输出所有执行命令,但并不执行。   -t   更新目标文件。   -q   make操作将根据目标文件是否已经更新返回"0"或非"0"的状态信息。   -p   输出所有宏定义和目标文件描述。   -d   Debug模式,输出有关文件和检测时间的详细信息。   linux下make标志位的常用选项与Unix系统中稍有不同,下面我们只列出了不同部分:   -c dir   在读取 makefile 之前改变到指定的目录dir。   -I dir   当包含其他 makefile文件时,利用该选项指定搜索目录。   -h   help文挡,显示所有的make选项。   -w   在处理 makefile 之前和之后,都显示工作目录。   通过命令行参数中的target ,可指定make要编译的目标,并且允许同时定义编译多个目标,操作时按照从左向右的顺序依次编译target选项中指定的目标文件。如果命令行中没有指定目标,则系统默认target指向描述文件中第一个目标文件。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值