组织对递归Makefile的依赖

时间:2015-11-24 11:05:09

标签: makefile gnu-make

我有两个Makefile,一个用于我的应用程序,另一个用于其依赖库。该库与应用程序链接在一起。库的Makefile是使用一些第三方包含文件编写的,因此无法进行太多更改(特别是,我无法摆脱递归make 用法)。

我想要实现的是自动库(重新)构建作为应用链接规则的先决条件。

我尝试使用特殊的戳记文件执行此操作:粗略地说,库Makefile会在重建发生时更新戳记文件,并且应用程序Makefile使用< em> stamp 文件作为先决条件。

所以我的 app Makefile 看起来像是:

.PHONY: rebuild_libfoo
rebuild_libfoo:
    +make -C path/to/libfoo STAMPDIR=out out/libfoo.stamp
all: rebuild_libfoo
out/libfoo.stamp: rebuild_libfoo
app: out/libfoo.stamp <... additional prerequisites ...>
    <... recipe with linker execution ...>
all: app

libfoo Makefile 如下所示:

$(STAMPDIR)/libfoo.stamp: installation/libs/path/libfoo.a
    touch $(STAMPDIR)/libfoo.stamp
installation/libs/path/libfoo.a: <... additional prerequisites ...>
    <... recipe with ar execution ...>
all: installation/libs/path/libfoo.a

所以这个解决方案的优点在于,无论什么时候,我都能做到#34;在app目录中,只要发生更改,就会重建库。

但也存在一个大问题:应用链接规则未自动执行 。因此,即使库重建发生,应用程序也会与旧库版本保持链接。但是,如果我运行&#34; make all&#34;在app目录中第二次,然后应用程序与新版本链接 - 这显然是一个非常容易出错的行为。

据我所知,那是因为make在执行任何配方之前读取所有时间戳,所以&#34; rebuild_libfoo&#34;规则,尽管触摸了戳文件,但对应用链接规则没有直接影响。

这有什么解决方法吗?也许,任何方式强制重新读取文件时间戳?

1 个答案:

答案 0 :(得分:0)

图书馆需要成为目标的先决条件。用最简单的形式

app: out/libfoo.stamp <... additional prerequisites ...> path/to/libfoo/libfoo.a
        <... recipe with linker execution ...>

我正在使用GNU Make 3.81。我已将示例缩减为以下文件:

app.c
Makefile
path/to/libfoo/Makefile
path/to/libfoo/libsrc.c

Library Makefile:

CC = gcc
all: libfoo.a
libfoo.a:   libsrc.o
    $(AR) -r $@ $?

.PHONY: clean
clean:
    rm -f libsrc.o libfoo.a

应用程序Makefile

.DEFAULT_GOAL = all
LD = gcc

.PHONY: rebuild_libfoo
rebuild_libfoo:
    +make -C path/to/libfoo $(MAKECMDGOALS)

all: rebuild_libfoo app

app: app.o path/to/libfoo/libfoo.a

.PHONY: clean
clean:
    +make -C path/to/libfoo $(MAKECMDGOALS)
    rm -f app app.o

在应用程序目录中发出make,我有

make -C path/to/libfoo 
make[1]: Entering directory `/home/digitemp/make/path/to/libfoo'
gcc    -c -o libsrc.o libsrc.c
ar -r libfoo.a libsrc.o
ar: creating libfoo.a
make[1]: Leaving directory `/home/digitemp/make/path/to/libfoo'
cc    -c -o app.o app.c
cc   app.o path/to/libfoo/libfoo.a   -o app

第二次发出make命令,导致无编译等(如预期的那样)。然后输入命令touch path/to/libfoo/libsrc.c后跟make会产生以下结果:

make -C path/to/libfoo 
make[1]: Entering directory `/home/digitemp/make/path/to/libfoo'
gcc    -c -o libsrc.o libsrc.c
ar -r libfoo.a libsrc.o
make[1]: Leaving directory `/home/digitemp/make/path/to/libfoo'
cc   app.o path/to/libfoo/libfoo.a   -o app

正如预期的那样,编译库对象文件并链接应用程序。