【问题标题】:How to execute shell commands in Automake/Makefile.am?如何在 Automake/Makefile.am 中执行 shell 命令?
【发布时间】:2019-01-22 07:32:11
【问题描述】:

使用 Automake 编译可执行文件后,我希望可执行文件输出编译日期、使用的编译器和 git repo 版本/日期。但是,我似乎无法从 Makefile.am 运行 shell 命令。当我尝试时,会收到以下警告:

sample/C++/Makefile.am:1: 警告: date +%D: non-POSIX variable name

sample/C++/Makefile.am:1:(可能是 GNU make 扩展)

sample/C++/Makefile.am:2: 警告: git --no-pager show --date=short --format="%ad" --name-only | {先读_;回声 $first ; }: 非 POSIX 变量名

sample/C++/Makefile.am:2:(可能是 GNU make 扩展)

sample/C++/Makefile.am:3: 警告: git --no-pager describe --tags --always --dirty: 非 POSIX 变量名

sample/C++/Makefile.am:3:(可能是 GNU make 扩展)

如果除了运行 configure.ac 中的命令之外还有更好的方法(因为这违背了编译时间的目的),请告诉我。

【问题讨论】:

    标签: makefile gnu autotools autoconf automake


    【解决方案1】:

    POSIX make 和许多特定的 make 实现没有提供在配方之外运行 shell 命令的机制。 GNU make 和也许其他人确实将其作为扩展提供,但 Autotools 的目标之一是支持尽可能广泛的构建环境,因此依赖特定实现提供的扩展与 Autotools 习惯用法相反。

    在不依赖扩展的情况下解决问题的一种方法是让您的源代码#include 成为在构建时动态生成的标头。例如,Makefile.am 部分可能如下所示:

    bin_PROGRAMS = hello
    
    hello_SOURCES = \
      hello.cpp \
      build_details.h
    
    BUILT_SOURCES = \
      build_details.h
    
    CLEANFILES = \
      build_details.h
    
    build_details.h:
        echo "#define BUILDDATE \"`date +%D`\"" >$@
        echo "#define COMPILER \"$(CXX)\"" >>$@
    

    因为它被列在BUILT_SOURCES 中,所以目标build_details.h 将被提前构建。因为构建它的规则没有先决条件,它总是被认为是过时的,所以它会被重建,从而得到新鲜的细节。当然,这也意味着每次运行 make 时都会重新构建依赖它的所有源,但如果您正在跟踪此类构建信息,也许这实际上就是您想要的。

    另一方面,如果您愿意依赖 GNU make 扩展,那么它们提供了一种将变量设置为 shell 命令输出的方法。在这种情况下,你可能会做更多这样的事情:

    bin_PROGRAMS = hello
    
    builddate := $(shell date +%D)
    CXXFLAGS = -DBUILDDATE='"$(builddate)"' -DCOMPILER='"$(CXX)"'
    
    hello_SOURCES = \
      hello.cpp
    

    注意双引号:内部双引号需要是正在定义的宏的替换文本的一部分,因此当它们出现在编译器命令行上时,需要保护它们免受 shell 的影响。

    它的优点是它更短,并且如果hello.cpp 没有更改,它不会导致hello 被重建。但它只适用于支持所使用的 GNU 扩展的make。此外,这不会导致任何对象过时,因此它可能会留下陈旧的构建信息被记录在二进制文件中的可能性,因为保存它的对象不在某些给定的make 上重建的对象中执行。

    当然,尽管我已经解决了所提出的问题,但值得注意的是,其中一些与直接存在于 C 和 C++ 语言中的特性重复。具体来说,__DATE____TIME__ 宏被自动定义为扩展到编译的日期和时间。它们不能让您控制格式,但这可能是一个值得权衡的选择。

    【讨论】:

    • 还可以生成build_details.c 文件为BUILT_SOURCES,这将避免在仅更改构建信息时编译其他代码的开销。此外,您可以将伪造的邮票文件添加到 BUILD_SOURCES 并让配方生成一个新文件 build_details.c.new 并且仅将 *.new 复制到 build_details.c 如果后者实际上不同或不存在。这避免了不必要的重新编译,例如git 信息没有改变。
    猜你喜欢
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 2015-01-03
    • 1970-01-01
    • 2014-06-12
    • 2015-09-26
    • 2010-12-25
    • 2011-08-23
    相关资源
    最近更新 更多