所以我跟着
Advanced Auto-Dependency Generation纸 –
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
– 它的作用就像一个魅力.
Makefile文件:
... HDRS := foo.h $(HDRS): mk_header.sh $* clean:: -rm $(HDRS) ...
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不被认为是先决条件,因此没有被生成:
$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,从而产生另一个构建级联.
$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 make: `main' is up to date.
所以我的问题是:是否有办法扩展上面提到的食谱,以允许生成的头文件,而不会通过在包含*时不必重新评估整个make树而实现的性能增益. d片段?
解决方法
问题是在完成所有的头生成之后,必须执行* .d Makefile-fragments生成.以这种方式,可以使用make依赖来强制正确的顺序:
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
笔记:
>我用了order-only dependency.
>该解决方案是相当可扩展的:每个生成头规则只需要作为generate_headers.PHONY目标的先决条件.假设标题生成规则被正确写入,一旦生成正确,满足generate_headers的目标应该是无效的.
>无法编译单个对象,即使该对象不需要任何生成的头,也不会首先生成项目的所有生成的头文件.虽然这在技术上是合理的,但您的开发人员将抱怨.
所以你应该考虑有一个FAST_AND_LOOSE标志,这将关闭此功能:
%.o: %.c | $(if $(FAST_AND_LOOSE),generated_headers) ...
因此,开发人员可能会发布:
make FAST_AND_LOOSE=1 main.o