Linux基础(五) makefile

makefile的规则
规则的三要素


本文主要介绍makefile的编写。

1 一个简单的makefile示例

创建一个makefile文件,并添加如下内容

app:main.c add.c sub.c mul.c
	gcc main.c add.c sub.c mul.c -o app 

当前文件夹中的问价

add.c  head.h  main.c  makefile  mul.c  sub.c

这种编译方式,每次改动一个文件都要整体重新编译,效率太低。通过.o来编译打包,再次编译时,可以实现只编译改动部分。

2 根据.o来编译

app:main.o add.o sub.o mul.o
        gcc main.o add.o sub.o mul.o -o app 
main.o:main.c
        gcc -c main.c
add.o:add.c
        gcc -c add.c
mul.o:mul.c
        gcc -c mul.c
sub.o:sub.c
        gcc -c sub.c

这里的执行顺序是,首先执行第一行,发现.o文件不存在时,再执行如下命令先编译生成.o文件

main.o:main.c
        gcc -c main.c

其它.o以此类推。到最后再执行如下这行命令

gcc main.o add.o sub.o mul.o -o app 

执行make

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# make
gcc -c add.c 
gcc -c sub.c 
gcc -c mul.c 
gcc main.o add.o sub.o mul.o -o app

下面验证下只修改一个文件会不会全部重新编译

1 先看下所有.o文件最后修改的时间

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# ls -l *.o
-rw-r--r-- 1 root root 1240 Jan 27 12:52 add.o
-rw-r--r-- 1 root root 2032 Jan 27 12:51 main.o
-rw-r--r-- 1 root root 1232 Jan 27 12:52 mul.o
-rw-r--r-- 1 root root 1232 Jan 27 12:52 sub.o

2 修改add.c文件,然后重新编译

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# make
gcc -c add.c 
gcc main.o add.o sub.o mul.o -o app

可以看到只是重新编译了.c文件
看生成.o文件的时间也可以验证。

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# ls -l *.o
-rw-r--r-- 1 root root 1240 Jan 27 13:15 add.o
-rw-r--r-- 1 root root 2032 Jan 27 12:51 main.o
-rw-r--r-- 1 root root 1232 Jan 27 12:52 mul.o
-rw-r--r-- 1 root root 1232 Jan 27 12:52 sub.o

3 提取makefile中的变量

首先看下之前的makefile

app:main.o add.o sub.o mul.o
        gcc main.o add.o sub.o mul.o -o app
main.o:main.c
        gcc -c main.c
add.o:add.c
        gcc -c add.c
mul.o:mul.c
        gcc -c mul.c
sub.o:sub.c
        gcc -c sub.c

再来看提取变量后的makefile

obj=main.o add.o sub.o mul.o
target=app
$(target):$(obj)
	gcc $(obj) -o $(target) 
%.o:%.c
	gcc -c $< -o $@

下面解释下替换过程

1 首先将要编译的.o文件提取为变量

obj=main.o add.o sub.o mul.o

2 将打包的包名app提取为target变量

target=app

3 把之前的表达式用变量来表示

app:main.o add.o sub.o mul.o ---> $(target):$(obj)
gcc main.o add.o sub.o mul.o -o app ---> gcc $(obj) -o $(target)

4 %.o:%.c — 含义

main.o add.o sub.o mul.o
每次查找main.o时,将会用main.o来匹配%.o
也就是说当查找main.o时,%.o:%.c就会匹配main.o:main.c
main.o:main.c  ---> %.o:%.c 

5 $ < ---- $@ — $^ — 含义

makefile中的自动变量
$<: 规则中的第一个依赖
$@: 规则中的目标
$^: 规则中的所有依赖
只能在规则的命令中使用
 gcc -c main.c --- gcc -c $< -o $@

6 拓展:makefile中自己维护的变量

CC == gcc
CPPFLAGS == -I
CFLAGS -Wall -g -c
LDFLAGS -L -l

把gcc替换为CC

:4,6s/gcc/$(CC) 
obj=main.o add.o sub.o mul.o
target=app
$(target):$(obj)
	$(CC) $(obj) -o $(target) 
%.o:%.c
	$(CC) -c $< -o $@

4 makefile中的函数

获取当前文件下的所有.c文件

src=$(wildcard ./*.c)

pathsubst是匹配替换函数,会把所有的.c替换成.o。
.c的来源是根据src获取的。

ojb=$(patsubst ./%.c, ./%.o, $(src))
root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# cat makefile 
target=app
src=$(wildcard ./*.c)
obj=$(patsubst ./%.c, ./%.o, $(src))
$(target):$(obj)
	$(CC) $(obj) -o $(target) 
%.o:%.c
	$(CC) -c $< -o $@

5 删除.o

每次重新编译都会提示app已经是最新的

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# make
make: 'app' is up to date.

可以在makefile中添加如下命令,使每次编译都把对应的.o和app程序删除。

clean:
    rm $(obj) $(target) 

整体makefile

target=app
src=$(wildcard ./*.c)
obj=$(patsubst ./%.c, ./%.o, $(src))
$(target):$(obj)
        $(CC) $(obj) -o $(target) 
%.o:%.c
        $(CC) -c $< -o $@
clean:
        rm $(obj) $(target)

make之前先执行make clean命令。此时.o和app都被删除了。

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# ls
add.c  add.o  app  head.h  main.c  main.o  makefile  mul.c  mul.o  sub.c  sub.o
root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# make clean
rm  ./mul.o  ./add.o  ./main.o  ./sub.o app 
root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# ls
add.c  head.h  main.c  makefile  mul.c  sub.c

删除完成后,在执行make clean,会提示文件找不到

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# make clean
rm  ./mul.o  ./main.o  ./add.o  ./sub.o app 
rm: cannot remove './mul.o': No such file or directory
rm: cannot remove './main.o': No such file or directory
rm: cannot remove './add.o': No such file or directory
rm: cannot remove './sub.o': No such file or directory
rm: cannot remove 'app': No such file or directory
makefile:9: recipe for target 'clean' failed
make: *** [clean] Error 1

添加-f,强制删除

clean:
	rm $(obj) $(target) -f 

此时再执行make clean 就不会提示找不到了

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# make clean
rm  ./mul.o  ./main.o  ./add.o  ./sub.o app -f 

但是如果当前文件有一个clean文件,执行make clean会遇到冲突

root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# touch clean
root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# ls
add.c  clean  head.h  main.c  makefile  mul.c  sub.c
root@iZ2ze9ftqv2b7zbety6qd8Z:~/learn_makeFile# make clean
make: 'clean' is up to date.

此时可以加一个伪目标.PHONY:clean,就不会有此问题

.PHONY:clean
clean:
	rm $(obj) $(target) -f 

6 命令执行失败时继续向下执行

当一条命令执行失败时,可以添加“ - ”,使命令继续向下执行
例如在clean命令中添加一个新建文件的命令

clean:
	mkdir /test
	rm $(obj) $(target) -f 

执行make clean后,会提示执行失败

james@iZ2ze9ftqv2b7zbety6qd8Z:/root/learn_makeFile$ make clean
mkdir /test
mkdir: cannot create directory ‘/test’: Permission denied
makefile:10: recipe for target 'clean' failed
make: *** [clean] Error 1

此时添加“ - ”,使命令执行失败后,继续向下执行

james@iZ2ze9ftqv2b7zbety6qd8Z:/root/learn_makeFile$ make clean
mkdir /test
mkdir: cannot create directory ‘/test’: Permission denied
makefile:10: recipe for target 'clean' failed
make: [clean] Error 1 (ignored)
rm  ./mul.o  ./main.o  ./add.o  ./sub.o app -f 
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Windows 10中,如果使用CMake进行编译,通常不会直接生成Makefile文件。相反,CMake会根据你的操作系统和编译器自动选择生成相应的构建文件,例如Visual Studio的解决方案文件或者Makefile文件。 然而,如果你想使用Makefile文件进行编译,你可以在CMake执行时指定生成Makefile文件的方式。根据引用的解答,你可以使用以下命令来生成Makefile文件: ``` cmake . -G "Unix Makefiles" ``` 这意味着你需要在CMakeLists.txt所在的目录中运行上述命令,并且在生成Makefile文件后,可以使用make命令进行后续的编译操作。 引用中介绍了如何在Windows上像Linux一样使用Makefile文件进行编译的详细过程。它提供了一种在Windows上搭建类似Linux开发环境的方法,并通过Makefile文件自动化编译。此方法可能更适合对Makefile文件有兴趣或者想要了解更多基础知识的开发者。 总结来说,如果你想在Windows 10中使用Makefile文件进行编译,可以通过在CMake执行时指定生成Makefile文件的方式来实现。另外,你还可以参考引用中介绍的方法来搭建类似Linux开发环境,并使用Makefile文件进行自动化编译。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [WIN10下cmake和make的介绍和部分错误描述记录](https://blog.csdn.net/weixin_44279924/article/details/124549600)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [怎么在Windows下使用Makefile文件](https://blog.csdn.net/m0_74282605/article/details/128132452)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值