c - Automake、GNU make、检查和(忽略的)模式规则

标签 c makefile autotools check-framework

我有以下 Makefile.am,它应该创建 foo.hdbfoo.cdb来自 foo.h (通过 Python 脚本):

TESTS = check_foo

check_PROGRAMS = check_foo

check_foo_SOURCES = check_foo.c $(top_builddir)/src/isti.h \
    foo.cdb foo.h foo.hdb
check_foo_CFLAGS = @CHECK_CFLAGS@ $(all_includes) -I../../clib/src/
check_foo_LDADD = $(top_builddir)/src/libcorm.la @CHECK_LIBS@ -lsqlite3

%.hdb %.cdb: %.h
    PYTHONPATH=$(top_builddir)/cgen/src python $(top_builddir)/cgen/src/isti/cgen/run.py $<

clean-local:
    rm -f *.hdb *.cdb

然而,虽然make foo.hdbmake foo.cdb工作(调用 Python 代码并从 foo.hdb 生成 foo.cdbfoo.h 文件),make clean check (或两者分开)不(缺少 foo.hdb - 没有这样的文件) - 模式规则未被调用以生成 foo.hdb来自 foo.h .

换句话说:没有为 check_foo_SOURCES 中列出的文件调用模式规则

我怎样才能使这项工作?其余的 autotools 基础设施运行良好。通过查看 Makefile,我怀疑问题出在 autotools 如何扩展检查源。

这都是在 Linux 上用 Gnu make 完成的。这是 the Makefile .

[稍微更新以反射(reflect)来自 MadScientist 的帮助]。

稍后更新

下面的 Makefile(只是 make,不是 autotools)工作正常,所以这个问题似乎与 autotools 和检查支持有关。

all: check_foo

CFLAGS=-I../../clib/src
LDFLAGS=-L../../clib/src/.libs

check_foo: check_foo.c foo.h corm_foo.h corm_foo.c
    gcc $(CFLAGS) $(LDFLAGS) $^ -o $@ -lcorm -lsqlite3

corm_%.h corm_%.c: %.h
    PYTHONPATH=../../cgen/src python ../../cgen/src/isti/cgen/run.py $<

clean:
    rm -f corm_*.h corm_*.c
    rm -f *.o

(请注意,我已从 xxx.hdb 切换到 corm_xxx.h 等,以便文件扩展名保持正常)。

更多详情

因为好像和CHECK宏有关,所以这里是configure.ac:

AC_INIT([corm], [0.1], [a.cooke@isti.com])
AC_CONFIG_MACRO_DIR([m4])
PKG_CHECK_MODULES([CHECK], [check >= 0.9.4]) 
AM_INIT_AUTOMAKE([-Wall foreign -Werror])
AC_PROG_CC_C99
AM_PROG_CC_C_O
LT_INIT
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile clib/Makefile clib/src/Makefile clib/tests/Makefile clib/docs/Makefile cgen/Makefile cgen/docs/Makefile example/Makefile example/src/Makefile])
AC_CHECK_PROGS([DOXYGEN], [doxygen], AC_MSG_WARN([Doxygen not found - continuing without Doxygen support]))
AM_CONDITIONAL([HAVE_DOXYGEN], [test -n "$DOXYGEN"])
AM_COND_IF([HAVE_DOXYGEN], [AC_CONFIG_FILES([clib/docs/Doxyfile cgen/docs/Doxyfile])])

解决方案

好的,所以总结下面的各种事情,有两个重要的问题(一旦我有固定的文件扩展名 - 请参阅“普通”makefile 和 fceller 的回答),其中任何一个都足以使事情正常进行:

  1. (处理)头文件很复杂。由于自动依赖性,以编程方式生成的头文件会破坏事物。解决方案是使用 BUILT_SOURCES

  2. 但是(处理).c 文件并不复杂。因此将 corm_foo.c 放在 check_foo.c 前面会触发该文件的生成。由于这也会生成 corm_foo.h,因此一切正常(因为 check_foo.c 现在可以包含 corm_foo.h)。

此外,fceller 对 tidy makefile 有一些很好的一般观点,并解释了为什么“普通”makefile 有效。

最佳答案

线

%.cdb: %.hdb

什么都不做。检查 GNU make 手册,您会看到没有命令行的模式规则用于删除先前定义的具有相同模式的规则。由于没有先前的规则,这本质上是空操作。

如果您有一条命令通过一次规则调用创建两个输出文件,那么您需要将两种模式放在同一规则中,如下所示:

%.cdb %.hdb: %.h
        PYTHONPATH=$(top_builddir)/cgen/src python $(top_builddir)/cgen/src/isti/cgen/run.py $<

这将告诉 GNU make 两个目标都是从规则的一次调用中生成的。意识到!此语法仅对模式规则具有此行为。具有多个目标的显式规则会做一些完全不同的事情(足够令人困惑)。

至于make clean 行为,我不确定。 automake 生成的 makefile 太复杂了,我无法阅读它;它需要一些调试(运行它并跟踪发生的情况)。但是,我怀疑那里的规则设计不当,无法在同一次 make 调用中运行 clean 目标和构建目标。分别运行这两个命令,看看效果是否更好:

make clean
make check

关于c - Automake、GNU make、检查和(忽略的)模式规则,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14944070/

相关文章:

c - 将共享库链接到静态库

Qt 和 QMake 构建目录

c - 使用设备树引导主线 Linux 内核

C-Lomuto Quicksort Exe 不起作用

makefile - 在Windows上编译OpenSSL MinGw-make [1] : *** [Makefile:2800: crypto/dso/dso_win32.o] Error 1

c++ - 使用 Makefile 对 main 的多个定义

java - Gradle编译生成java文件

c++ - 在IR远程库中找不到IRremote.h header

c - main() 有时会在 x86 上使用 -fomit-frame-pointer 保留帧指针

ubuntu - 配置 : error: Package requirements(. ..) 未满足