所以我关注了Advanced Auto-Dependency Generation纸 -
生成文件:
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)
主文件:
#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
成为生成的文件——生成文件:
...
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
make: `main' is up to date.
所以我的问题是:有没有一种方法可以扩展上面论文中建议的配方,以允许生成头文件,而不会消除由于在包含
*.d
时不必重新评估整个 make 树而实现的性能提升。碎片?
最佳答案
问题在于*.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
备注:
generated_headers
的先决条件。 .PHONY
目标。假设header生成规则写得正确,一旦生成正确,满足generated_headers
目标应该是一个空操作。 所以你应该考虑拥有一个
FAST_AND_LOOSE
标志,这将关闭此功能:%.o: %.c | $(if $(FAST_AND_LOOSE),,generated_headers)
...
因此,开发人员可能会发出:
make FAST_AND_LOOSE=1 main.o
关于makefile - GNU 制作 : Generating automatic dependencies with generated header files,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5229561/