微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

makefile – GNU make:使用生成的头文件生成自动依赖关系

所以我跟着 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

– 它的作用就像一个魅力.

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

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

原文地址:https://www.jb51.cc/c/113832.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐