加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

makefile – 关于GNU make依赖文件* .d

发布时间:2020-12-16 10:03:42 所属栏目:百科 来源:网络整理
导读:在程序的makefile中,必须编写定义每个目标文件的依赖关系的规则.考虑目标文件fileA.o.很明显,这个目标文件依赖于源文件fileA.c.但它也将取决于此源文件包含的所有头文件.因此,应将以下规则添加到makefile中: # This rule states that fileA.o depends on fi
在程序的makefile中,必须编写定义每个目标文件的依赖关系的规则.考虑目标文件fileA.o.很明显,这个目标文件依赖于源文件fileA.c.但它也将取决于此源文件包含的所有头文件.因此,应将以下规则添加到makefile中:

# This rule states that fileA.o depends on fileA.c (obviously),but also
    # on the header files fileA.h,fileB.h and fileC.h
    fileA.o: fileA.c fileA.h fileB.h fileC.h

请注意,该规则没有配方.可以添加一个配方,但严格来说没有必要,因为GNU make可以依赖隐式规则(带配方)将* .c文件编译成* .o文件.

无论如何,手动编写这样的规则是一项地狱般的任务.想象一下使makefile规则与源代码中的#include语句保持同步的工作.

GNU make手册在第4.14章“自动生成先决条件”中描述了一种自动执行此过程的方法.该过程从为每个源文件生成* .d文件开始.我引用:

For each source file name.c there is a makefile name.d which lists what files the object file name.o depends on.

手册进行:

Here is the pattern rule to generate a file of prerequisites (i.e,a makefile) called name.d from a C source file called name.c :

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

遗憾的是,该手册没有详细解释这条规则是如何实际运作的.是的,它提供了所需的name.d文件,但为什么呢?该规则非常混淆..

在查看此规则时,我感觉它的配方只能在Linux上顺利运行.我对吗?有没有办法让这个配方在Windows上正确运行?

任何帮助是极大的赞赏 :-)

解决方法

退出所有错误

@set -e;

删除现有的dep文件($@ = target =%.d)

rm -f $@;

让编译器生成dep文件并输出到后缀为pid的临时文件($< = first prerequisite =%.c,$$$$ - > $$ – > pid)

$(CC) -M $(CPPFLAGS) $< > $@.$$$$;

捕获匹配$* .o($* = match stem =%)的目标,将其替换为目标后跟依赖项文件本身,输出到dep文件

sed 's,g' < $@.$$$$> $@; 

删除temp dep

rm -f $@.$$$$

让我们插入foo,CC = gcc和CPPFLAGS =”来看看make完成扩展后会发生什么:

foo.d: foo.c
    @set -e; rm -f foo.d; 
     gcc -M foo.c > foo.d.$$; 
     sed 's,(foo).o[ :]*,1.o foo.d :,g' < foo.d.$$> foo.d; 
     rm -f foo.d.$$

shell本身会将$$扩展为pid,而dep文件中的最终规则将类似于

foo.o foo.d : foo.c foo.h someheader.h

请注意,这是一种非常过时的生成依赖关系的方法,如果您正在使用GCC或clang,则可以将generate them作为编译本身的一部分使用CPPFLAGS = -MMD -MP.

假设您有一个名为foo的程序:

objs := foo.o bar.o
deps := $(objs:.o=.d)

vpath %.c $(dir $(MAKEFILE_LIST))

CPPFLAGS += -MMD -MP

foo: $(objs)

.PHONY: clean
clean: ; $(RM) foo $(objs) $(deps)

-include $(deps)

这就是你所需要的,内置规则将完成其余的工作.显然,如果您希望将对象文件放在不同的文件夹中,或者您希望在源树之外构建,那么事情会更复杂一些.

vpath指令允许您在不同的目录中运行make并在那里创建文件,例如make -f path / to / source / Makefile.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读