GNU make:使用生成的头文件生成自动依赖项 [英] GNU make: Generating automatic dependencies with generated header files

查看:154
本文介绍了GNU make:使用生成的头文件生成自动依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我遵循了高级自动依赖项生成论文-

Makefile :

SRCS := main.c foo.c

main: main.o foo.o

%.o: %.c
    $(CC) -MMD -MG -MT '$@ $*.d' -c $< -o $@
    cp $*.d $*.tmp
    sed -e 's;#.*;;' -e 's;^[^:]*: *;;' -e 's; *\\$$;;' \
        -e '/^$$/d' -e 's;$$; :;' < $*.tmp >> $*.d
    rm $*.tmp

clean::
    -rm *.o *.d main

-include $(SRCS:.c=.d)

main.c :

#include "foo.h"

int main(int argc, char** argv) {
  foo() ;
  return 0 ;
}

foo.h :

#ifndef __FOO_H__
#define __FOO_H__

void foo() ;

#endif

-和它的魅力一样.

但是当foo.h成为生成文件时-

But when foo.h becomes a generated file --

Makefile:

...

HDRS := foo.h

$(HDRS):
    mk_header.sh $*

clean::
    -rm $(HDRS)
...

mk_header.sh:

mk_header.sh:

#!/bin/bash
UP=$(tr "[:lower:]" "[:upper:]" <<< $1)

cat <<EOF > $1.h
#ifndef __${UP}_H__
#define __${UP}_H__

void $1() ;

#endif
EOF

我第一次运行make时,尚未生成main.d,因此foo.h未被视为先决条件,因此也没有生成:

The 1st time I run make, main.d is not yet generated, and thus foo.h is not considered a prerequisite, and thus isn't been generated:

$ ls
foo.c  main.c  Makefile  mk_header.sh*

$ make
cc -MMD -MG -MT 'main.o main.d' -c main.c -o main.o
cp main.d main.tmp
sed -e 's;#.*;;' -e 's;^[^:]*: *;;' -e 's; *\\$;;' \
    -e '/^$/d' -e 's;$; :;' < main.tmp >> main.d
rm main.tmp
cc -MMD -MG -MT 'foo.o foo.d' -c foo.c -o foo.o
cp foo.d foo.tmp
sed -e 's;#.*;;' -e 's;^[^:]*: *;;' -e 's; *\\$;;' \
    -e '/^$/d' -e 's;$; :;' < foo.tmp >> foo.d
rm foo.tmp
cc   main.o foo.o   -o main

$ ls
foo.c  foo.d  foo.o  
main*  main.c  main.d  main.o  
Makefile  mk_header.sh*

仅在make的第二次调用中生成foo.h,结果另一个构建级联.

Only in the 2nd invocation of make, the foo.h is generated, and as a result another build cascades.

$ make
./mk_header.sh foo
cc -MMD -MG -MT 'main.o main.d' -c main.c -o main.o
cp main.d main.tmp
sed -e 's;#.*;;' -e 's;^[^:]*: *;;' -e 's; *\\$;;' \
    -e '/^$/d' -e 's;$; :;' < main.tmp >> main.d
rm main.tmp
cc   main.o foo.o   -o main

$ ls
foo.c  foo.d  foo.h  foo.o  
main*  main.c  main.d  main.o  
Makefile  mk_header.sh*

并且只有在这之后,make才意识到:

And only after that make realizes that:

$ make
make: `main' is up to date.


所以我的问题是:是否有一种方法可以扩展上述论文建议的方法,以允许生成头文件,而又不会消除不必重新评估整个make所带来的性能提升.包含*.d片段时的树?


So my question is: Is there a way to extend the recipe suggested by the paper above, to allow for generated header files, without the elimination of the performance gain realized by not having to re-evaluate the entire make tree when including the *.d fragments?

推荐答案

问题在于,必须在所有标头生成完成后 后执行*.d Makefile-fragments生成.这样说来,就可以使用make依赖项来强制正确的顺序:

The problem is that the *.d Makefile-fragments generation must be performed after all the header generation is complete. Putting it this way, one can use the make dependencies to force the right order:

SRCS := main.c foo.c
HDRS := foo.h

main: main.o foo.o

%.o: %.c | generated_headers
    $(CC) -MMD -MG -MT '$@ $*.d' -c $< -o $@
    cp $*.d $*.tmp
    sed -e 's;#.*;;' -e 's;^[^:]*: *;;' -e 's; *\\$$;;' \
        -e '/^$$/d' -e 's;$$; :;' < $*.tmp >> $*.d
    rm $*.tmp

-include $(SRCS:.c=.d)

$(HDRS):
    mk_header.sh $*

generated_headers: $(HDRS)

clean:
    -rm $(HDRS) *.o *.d main

.PHONY: clean generated_headers

注释:

  1. 我使用了仅订购依赖项.

此解决方案具有相当的可扩展性:每个生成标头规则仅是generated_headers .PHONY目标的先决条件.假设正确编写了标头生成规则,则在正确生成标头生成规则之后,满足generated_headers目标应该是空操作.

This solution is fairly scalable: Each generate-header rule, needs only to be a prerequisite of the generated_headers .PHONY target. Assuming that the header generation rule is written properly, once it has been generated correctly, satisfying the generated_headers target should be a no-op.

即使该对象不需要任何已生成的标头,也无法编译单个对象,而无需先生成 all 项目的已生成标头.从技术上讲,这听起来不错,但是您的开发人员会抱怨.

One can't compile a single object, even if that object does not require any generated headers, without generating all the generated headers of the project first. While this is technically sound, your developers will complain.

因此,您应该考虑使用FAST_AND_LOOSE标志,这将关闭此功能:

So you should think about having a FAST_AND_LOOSE flag, that will turn this feature off:

%.o: %.c | $(if $(FAST_AND_LOOSE),,generated_headers)
    ...

因此开发人员可以发布:

Thus a developer may issue:

make FAST_AND_LOOSE=1 main.o

这篇关于GNU make:使用生成的头文件生成自动依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆