最近没怎么搞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”但没有成功。
令我困惑的一件事是“man make”说“有关 make 和 makefile 的更详尽描述,请参阅 PMake - 教程。”
这个准确吗?我的印象是 pmake 在最近版本的 FreeBSD 中被 bsdmake 取代了——这是我问题的根源吗?
注意:我对归结为“您可以使用 GNU make 做到这一点”的答案不感兴趣 - 这是 FreeBSD make 的问题。
$(LIBTEST): $(LIBTEST)($(LIBOBJ))
表明
$(LIBTEST)
(此处为libTest.a
)的先决条件是该档案的$(LIBOBJ)
(此处为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