Linux make 在第一个 运行 上失败,在第二个 运行 上成功

Linux make fails on first run, succeeds on second run

当我 运行 make 时,第一个 运行 总是失败并显示 Error 1,但第二个 运行 按预期编译。

第一个 运行 产生这个命令:

cc -g -I../../../../include -I../../../../include/sdk/ctree.ctdb/multithreaded/static -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -ldl -o ../project42 ../project42.c -L../../../../lib/ctree.ctdb/multithreaded/static -lmtclient -lpthread -ldl -lm -lglib-2.0

第二个 运行 生成此命令(注意包含 csvparser.c 和 nxjson.c):

cc -g -I../../../../include -I../../../../include/sdk/ctree.ctdb/multithreaded/static -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include -ldl -o ../project42 ../csvparser.c ../nxjson.c ../project42.c -L../../../../lib/ctree.ctdb/multithreaded/static -lmtclient -lpthread -ldl -lm -lglib-2.0

Makefile 如下所示:

ACEBASEDIR=../../../..
APIDIR=ctree.ctdb/multithreaded/static
GLIBINC=$(shell pkg-config --cflags glib-2.0 | xargs)
INCDIRS=-I$(ACEBASEDIR)/include -I$(ACEBASEDIR)/include/sdk/$(APIDIR) $(GLIBINC)
CFLAGS=-g $(INCDIRS) -ldl -o $@
LIBDIRS=-L$(ACEBASEDIR)/lib/$(APIDIR)
SYSLIBS=-lpthread -ldl -lm -lglib-2.0
SRCDIR=..
OUTDIR=..
$(OUTDIR)/project42: $(SRCDIR)/csvparser.c $(SRCDIR)/nxjson.c $(SRCDIR)/project42.c
    cc $(CFLAGS) $? $(LIBDIRS) -lmtclient $(SYSLIBS)
clean:
    rm -f $(OUTDIR)/project42

当我展开命令时,我得到这个:

cc -g -I../../../../include -I../../../../include/sdk/ctree.ctdb/multithreaded/static $(shell pkg-config --cflags glib-2.0 | xargs) -ldl -o $@ $? -L../../../../lib/ctree.ctdb/multithreaded/static -lmtclient -lpthread -ldl -lm -lglib-2.0

运行 pkg-config --cflags glib-2.0 | xargs returns -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include.

对我来说,问题似乎出在 $? 变量 kindly described here 上。在第一个 运行 上,它似乎只解析为 ../project42.c 而不是 ../csvparser.c ../nxjson.c ../project42.c.

我怀疑我有一些东西出了问题,并且在第一个 运行 期间被缓存,但只有在需要它之后。

第一次编译时,我需要在 Makefile 中更改什么?我需要先移动 -L (LIBDIRS) 部分吗?

不要使用 $?。这会扩展到比目标 更新 的文件列表。您不能仅从更改的文件构建可执行文件:您必须从 所有 个文件构建它。

您想在这里使用 $^

真的,给定这个 makefile,使用 make 毫无意义;它总是每次都运行相同的东西,除非根本没有对任何源文件进行任何更改。您所拥有的仅比 shell 脚本好一点。