【问题标题】:Linux make fails on first run, succeeds on second runLinux make 第一次运行失败,第二次运行成功
【发布时间】:2020-03-28 09:45:31
【问题描述】:

当我运行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 返回-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) 部分?

【问题讨论】:

    标签: c linux makefile cc


    【解决方案1】:

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

    你想在这里改用$^

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

    【讨论】:

    • 好答案。但是,我没有看到任何令人信服的理由在这里切换到 shell 脚本。我有很多非常小的 makefile,它们可能是一个简单的 shell 脚本,但以后可能会变得越来越复杂。
    • 解决了这个问题,谢谢!第二次运行是否有效,因为第一次运行更改了 csvparser.c 和 nxjson.c 上的时间戳?
    • 我认为这个 makefile 不会改变源文件的时间戳。这通常是一个非常糟糕的主意:源文件时间戳只能在进行更新时由用户更改。最有可能发生的情况是第一个构建由于缺少文件而无法编译(尽管您没有在此处显示),因此目标 ../project42 由于错误而被删除。然后你重新运行 make,现在 all 文件比(不存在的)目标新,所以 $? 扩展到所有文件。
    猜你喜欢
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 2015-12-01
    • 2011-09-02
    • 1970-01-01
    • 2020-08-22
    • 1970-01-01
    相关资源
    最近更新 更多