makefile自动生成依赖性

举报
yd_221104950 发表于 2020/12/02 23:10:57 2020/12/02
【摘要】 在Makefile文件中,我们的依赖关系中可能会包含一系列的头文件,当工程比较大时,我们必须搞清楚哪些.c文件包含了哪些头文件,在加入或删除这些头文件时,都要修改Makefile文件。这样的修改很麻烦,而且很容易修改错。 为了避免上面这种繁重又容易出错的工作,我们可以使用C/C++编译器自动寻找源文件中包含的头文件,并生成一个依赖关系 ,命令如下: gcc -MM ...

在Makefile文件中,我们的依赖关系中可能会包含一系列的头文件,当工程比较大时,我们必须搞清楚哪些.c文件包含了哪些头文件,在加入或删除这些头文件时,都要修改Makefile文件。这样的修改很麻烦,而且很容易修改错。

为了避免上面这种繁重又容易出错的工作,我们可以使用C/C++编译器自动寻找源文件中包含的头文件,并生成一个依赖关系 ,命令如下:

gcc -MM main.c 

  
 
  • 1

gcc -M main.c 

  
 
  • 1

使用"-MM"与"-M"生成的依赖关系的区别:
在使用 GNU 的 C/C++ 编译器(如gcc),使用 -M 参数会把一些标准库的头文件也包含进来,使用-MM参数则不会把标准库的头文件包含进来,示例如下。

  • “-MM”:
~/Desktop/testm$ gcc -MM main.c -o main
~/Desktop/testm$ cat main
main.o: main.c defs.h

  
 
  • 1
  • 2
  • 3
  • “-M”:
~/Desktop/testm$ gcc -M main.c -o main
~/Desktop/testm$ cat main
main.o: main.c /usr/include/stdc-predef.h /usr/include/stdio.h \
 /usr/include/x86_64-linux-gnu/bits/libc-header-start.h \
 /usr/include/features.h /usr/include/x86_64-linux-gnu/sys/cdefs.h \
 /usr/include/x86_64-linux-gnu/bits/wordsize.h \
 /usr/include/x86_64-linux-gnu/bits/long-double.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs.h \
 /usr/include/x86_64-linux-gnu/gnu/stubs-64.h \
 /usr/lib/gcc/x86_64-linux-gnu/7/include/stddef.h \
 /usr/include/x86_64-linux-gnu/bits/types.h \
 /usr/include/x86_64-linux-gnu/bits/typesizes.h \
 /usr/include/x86_64-linux-gnu/bits/types/__FILE.h \
 /usr/include/x86_64-linux-gnu/bits/types/FILE.h \
 /usr/include/x86_64-linux-gnu/bits/libio.h \
 /usr/include/x86_64-linux-gnu/bits/_G_config.h \
 /usr/include/x86_64-linux-gnu/bits/types/__mbstate_t.h \
 /usr/lib/gcc/x86_64-linux-gnu/7/include/stdarg.h \
 /usr/include/x86_64-linux-gnu/bits/stdio_lim.h \
 /usr/include/x86_64-linux-gnu/bits/sys_errlist.h defs.h


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

接下来要考虑如下将编译器这个功能与makefile联系在一起。 如何让我们的makefile文件也可以根据源文件来重新生成依赖关系呢?GNU组织建议把编译器为每一个源文件自动生成的依赖关系放到一个文件中,为每一个.c文件,都生成一个.d的makefile文件。那么.d文件中就存放了对应的.c文件的依赖关系。

我们可以写出.c文件与.d文件的依赖关系,并让make自动更新或生成.d文件,并将其包含在我们的主makefile文件中。这样,我们就可以自动化地生成每个文件的依赖关系了,如:
Makefile:

CC = gcc
SRCS := $(wildcard *.c)
-include $(SRCS:.c=.d)

%.d:%.c @echo "Creating $@ ..." @set -e; rm -f $@; \ $(CC) -MM $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

命令解释:

  • SRCS := $(wildcard *.c) :代表当前目录下所有的.c文件。
  • %.d:%.c:所有的 .d 文件依赖于 .c 文件,是<target-pattern>: <prereq-patterns>的静态模式。
  • set -e:指定发生错误后立即退出执行。
  • rm -f $@:删除所有的目标(即.d 文件)。
  • :意为一个随机编号。
  • $(CC) -MM $< > $@.
    : 为每个依赖文件 $< ,生成依赖关系文件,并保存到[%.d].xxxx随机文件(形如“name.d.12345”)中,$@ 表示模式 %.d 文件。 单独的“>”符号表示将前面的输出重定向到某个地方,如文件。
  • sed 命令做了一个替换操作,再将结果写入没有四位随机数的.d文件中。单独的“<”符号表示后面的内容重定向到前面。
  • 最后一行是删除临时文件。
  • 因为 include 是按次序来载入文件,最先载入的 .d 文件中的目标会成为默认目标。所以你会发现在下面的执行结果中有“gcc -c -o hello.o hello.c”这一个编译。

上面的执行结果:

~/Desktop/testm$ ls
def  hello.c  hello.o  main.c  Makefile  test.c
~/Desktop/testm$ cat Makefile
CC = gcc
SRCS := $(wildcard *.c)
-include $(SRCS:.c=.d)

%.d:%.c
	@echo "Creating $@ ..."
	@set -e; rm -f $@; \
	$(CC) -MM $< > $@.$$$$; \
	sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \
	rm -f $@.$$$$
~/Desktop/testm$ make
Creating test.d ...
Creating main.d ...
Creating hello.d ...
gcc -c -o hello.o hello.c
~/Desktop/testm$ ls
def  hello.c  hello.d  hello.o  main.c  main.d  Makefile  test.c  test.d
~/Desktop/testm$ cat main.d
main.o main.d : main.c def/defs.h

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

谢谢阅读!

文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_40763897/article/details/103233266

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。