【问题标题】:Makefile: need to run `make` twice to relink objects fileMakefile:需要运行 `make` 两次来重新链接对象文件
【发布时间】:2021-09-25 17:13:21
【问题描述】:

这是我的 Makefile 的相关部分。

...
LIBS = gc ft

vpath %.a $(LIBS:%=lib%)

all:
    $(MAKE) $(NAME)

$(NAME): $(LIBS:%=lib%.a) $(OBJS) | libs
    $(CC) $(CFLAGS) $(OBJS) -o $(NAME) $(LDFLAGS)

-include $(DEPENDENCIES)
$(OBJS_DIR)/%.o: %.c $(OBJS_DIR)/debug$(DEBUG) | $(OBJS_DIR)
    $(CC) $(CFLAGS)  $(INCLUDES_DIR:%=-I %) -c $< -o $@

$(OBJS_DIR):
    $(MKDIR) $@

libs: $(LIBS:%=lib%.a)
    $(foreach LIB, ${LIBS}, ${MAKE} -C lib${LIB} ;)

lib%.a:
    $(MAKE) -C $(@:%.a=%)
...

我的问题是,每当我触摸其中一个库中的文件时,都要重新编译该库,但我必须再次运行 make 以使其重新链接目标文件。
我做错了什么?
提前致谢。

---编辑---
所以现在我的 Makefile 看起来像这样。

...
all: $(NAME)

$(NAME): $(OBJS) libft/libft.a libgc/libgc.a
    $(CC) $(CFLAGS) $(OBJS) -o $(NAME) $(LDFLAGS)

-include $(DEPENDENCIES)
$(OBJS_DIR)/%.o: %.c $(OBJS_DIR)/debug$(DEBUG) | $(OBJS_DIR)
    $(CC) $(CFLAGS)  $(INCLUDES_DIR:%=-I %) -c $< -o $@

$(OBJS_DIR):
    $(MKDIR) $@

libft/libft.a:
    $(MAKE) -C libft

libgc/libgc.a:
    $(MAKE) -C libgc
    ...

它不再重新链接,但如果更改我的库源中的某些文件,它也不会重新编译。

【问题讨论】:

  • 现在$(DEPENDENCIES) 看起来如何?

标签: c makefile linker .a multiple-makefiles


【解决方案1】:

您不能使用 vpath 来查找生成的文件。它只能用于定位源文件(始终存在)。详情请见http://make.mad-scientist.net/papers/how-not-to-use-vpath/

您需要使用生成的库的真实路径作为先决条件,以便在 make 检查其修改时间时知道它们已更改。

预计到达时间

您正在使用递归 make 模型进行构建。这意味着这个 makefile 不知道您的库是否已过时:这里您没有列出它们的任何先决条件,因此就 make 而言它们是否存在,它们是最新的。

相反,您已将有关库是否为最新的知识转移到子目录 makefile 中。这意味着为了知道它们是否是最新的,您必须运行该子制作以便它可以检查。这意味着您总是想运行子制作,它只会在库过时时更新它们。一个简单的方法是使用a FORCE target:

libft/libft.a: FORCE
        $(MAKE) -C libft

libgc/libgc.a: FORCE
        $(MAKE) -C libgc

FORCE:;

【讨论】:

  • 非常感谢,我不知道。不幸的是,这并不能解决我的问题。如果我只是将我的库的名称放在先决条件中,makefile 就会重新链接。 $(NAME): libft.a libgc.a $(OBJS) | libs 如果我输入完整路径,编译就会失败。 $(NAME): libft/libft.a libgc/libgc.a $(OBJS) | libsmake[2]: *** libft/libft: No such file or directory. Stop.make[1]: *** [Makefile:97: libft/libft.a] Error 2make: *** [Makefile:75: all] Error 2
  • 当然。我想我不清楚您是否必须使用完整路径名并修复您的 makefile 以使用这些完整路径作为运行 sub-make 命令的目标。显然你不能只使用没有目录的库名,因为这些不存在,所以 make 无法比较时间戳。
  • 是的,我想通了。正如您所说,如果我不指定它,请不要猜测我的库在哪里。但不幸的是,修复某些东西会破坏其他东西。我刚刚编辑了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多