首页 > 解决方案 > 用于构建库的旧 Makefile 不再适用于 FreeBSD

问题描述

最近没怎么做C编程,最近重温了一个老项目,发现在FreeBSD下建库的老Makefile已经不行了。这是过去可以工作的 Makefile 的简化版本:

TEST    = Test
LIBTEST = lib$(TEST).a

CC      = cc

.PRECIOUS: $(LIBTEST)

all: $(LIBTEST)

LIBSRC  = test.c

# Do not automatically delete library source files
.SECONDARY: $(LIBSRC)

LIBOBJ  = $(LIBSRC:%.c=%.o)

$(LIBTEST): $(LIBTEST)($(LIBOBJ))
        $(AR) $(ARFLAGS) $@ $?
        rm -f $?

clean:
        @rm -f *.o $(LIBTEST)

这是一个简单的 C 程序:

/* test.c */
#include <stdio.h>

int
test(char const *text)
{
    printf("%s\n", text);
    return 1;
}

它看起来像 Makefile 指令依赖项:

$(LIBTEST): $(LIBTEST)($(LIBOBJ))

不再工作。结果是:

 ar -crD libTest.a
 rm -f

我一直在细读“人造”,但没有成功。

令我困惑的一件事是,'man make' 说“有关 make 和 makefile 的更详尽描述,请参阅 PMake - A Tutorial。”

这是准确的吗?我的印象是在最近的 FreeBSD 版本中 pmake 被 bsdmake 取代 - 这是我问题的根源吗?

注意:我对归结为“您可以使用 GNU make 做到这一点”的答案不感兴趣 - 这是 FreeBSD make 的问题。

标签: makefilefreebsdbmake

解决方案


$(LIBTEST): $(LIBTEST)($(LIBOBJ))

表明 (here ) 的先决条件$(LIBTEST)libTest.a该存档的$(LIBOBJ)(here test.o) 成员,我不确定make应该从中得出什么结论,但对我来说 (FreeBSD 11.0) 它提出了all(这实际上意味着libTest.a) 已经起来了迄今为止(另请参见标尺下方的示例)。将行更改为:

$(LIBTEST): $(LIBOBJ)

似乎是有道理的(除非我遗漏了什么,否则应该是您想要的),目标文件是库目标的先决条件,并且规则使用比目标($?)更新的所有先决条件更新库。

这让我又发表了一条评论。这rm似乎不仅不必要,而且实际上是有害的,因为这意味着test.o总是在调用时重新编译,make all并且库总是得到更新,即使没有源(test.c)更改,因为中间先决条件目标不存在(即过时)。


即使我解决所有问题并将其剥离Makefile到最低限度,我也会真正得到这种行为:

$ ls
Makefile        test.c
$ cat Makefile 
libTest.a: libTest.a(test.o)
        $(AR) $(ARFLAGS) $@ $?
$ make
`libTest.a' is up to date.
$ ls
Makefile        test.c

推荐阅读