【问题标题】:Multiple Targets Not Being Executed By MakefileMakefile 不执行多个目标
【发布时间】:2019-06-13 13:33:55
【问题描述】:

我在这里更新了标题和内容,以表明这个特定问题是在问一些我在其他地方没有明确回答的问题。关键概念是理解在 Makefile 中看似单个目标执行多项操作的内容实际上是多个目标各自执行一项操作。

我还将删除一些无关的材料,因为它们最终无关紧要。

原创内容

我的问题是我有一个 Makefile(显然)没有正确调用我的子目录 Makefile 之一。我有一个这样的项目结构:

quendor
  src
    cheap
      cheap_init.c
      Makefile

    zmachine
      main.c
      Makefile

  Makefile  

项目根目录中的 Makefile 将引用各个目录中的 Makefile。这是核心 Makefile:

CC ?= gcc

CFLAGS += -Wall -std=c99
CFLAGS += -D_POSIX_C_SOURCE=200809L
CFLAGS += -O2 -fomit-frame-pointer

RANLIB ?= $(shell which ranlib)
AR ?= $(shell which ar)

export CC
export AR
export CFLAGS
export RANLIB

SRC_DIR = src

ZMACHINE_DIR = $(SRC_DIR)/zmachine
ZMACHINE_LIB = $(ZMACHINE_DIR)/quendor_zmachine.a

CHEAP_DIR = $(SRC_DIR)/cheap
CHEAP_LIB = $(CHEAP_DIR)/quendor_cheap.a

SUB_DIRS = $(ZMACHINE_DIR) $(CHEAP_DIR)

SUB_CLEAN = $(SUB_DIRS:%=%-clean)

$(SUB_DIRS):
    @echo $(SUB_DIRS)   # src/zmachine src/cheap
    @echo "DIR:"
    @echo $@            # src/zmachine
    $(MAKE) -C $@

$(SUB_CLEAN):
    -$(MAKE) -C $(@:%-clean=%) clean

clean: $(SUB_CLEAN)

help:
    @echo "Quendor"

.PHONY: $(SUB_DIRS) $(SUB_CLEAN) clean help

对我来说一个关键问题是上面的这一点:

$(SUB_DIRS):
    @echo $(SUB_DIRS)   # src/zmachine src/cheap
    @echo "DIR:"
    @echo $@            # src/zmachine
    $(MAKE) -C $@

我将echo 语句放入只是为了显示正在发生的事情。注意$SUB_DIRS 正确显示了两个目录,但是当Makefile 运行时它只显示src/zmachine。 (那里的 cmets 表示我在运行时看到的内容。)Makefile(显然)不处理 src/cheap

Makefile 运行的完整输出如下(前三行是我的 echo 语句):

src/zmachine src/cheap
DIR:
src/zmachine
/Applications/Xcode.app/Contents/Developer/usr/bin/make -C src/zmachine
cc -Wall -std=c99 -D_POSIX_C_SOURCE=200809L -O2 -fomit-frame-pointer -fPIC -fpic -o main.o -c main.c
ar rc quendor_zmachine.a main.o
/usr/bin/ranlib quendor_zmachine.a
** Done with Quendor Z-Machine.

一开始我唯一能想到的是,也许在运行src/zmachine 中的子makefile 之后,Make 过程要么出错,要么认为它已经完成。但我原以为 $(SUB_DIRS) 部分应该遍历这两个目录。

所以我有点不知道如何继续。

额外说明:我所说的“我会想到”部分是我不正确的地方。 $(SUB_DIRS) 没有像我想象的那样被执行;接受的答案已经澄清了这一点。

【问题讨论】:

  • $(SUB_DIRS):上方添加all: $(SUB_DIRS),如果命令行中没有指定,make只会处理它在makefile中遇到的第一个目标。
  • 有趣。我会尝试。但是,为什么要处理一个子目录呢?就我而言,我想这意味着 $(SUB_DIRS): 正在作为第一个目标进行处理。但这不会仍然迫使它​​通过两个目录,而不仅仅是一个?显然不是,但我想我不知道为什么。
  • 确实有效。同样,不清楚为什么会出现这种情况。我有目标,找到的第一个目标是我的$(SUB_DIRS): 但显然这还不足以迭代。因此,对于新加入 Make 的人来说,我不确定第一直觉会是考虑要求一个默认目标。我不确定这是否可以证明这是重复的。
  • 我建议使用非递归方法来编写makefiles 并使用github.com/igagis/prorab 来轻松做到这一点

标签: makefile


【解决方案1】:

make 的工作方式是,如果您不提供参数,它将首先扫描Makefile 寻找“默认目标”。默认目标只是它遇到的第一个目标(注意它是第一个target,而不是targets)。

在你的情况下,规则:

$(SUB_DIRS):
    $(MAKE) -C $@

相当于:

src/zmachine src/cheap:
    $(MAKE) -C $@

相当于:

src/zmachine:
    $(MAKE) -C $@
src/cheap:
    $(MAKE) -C $@

所以 make 遇到的第一个目标是src/zmachine,这是它的默认目标,也是被处理的目标。解决此问题的方法是,正如 user657267 在 cmets 中所说,添加一个您知道将首先处理的目标,该目标将以其他目标(您真正想要构建的目标)作为其先决条件。

【讨论】:

  • 完美。与目标相反,对第一个目标的澄清正是我所缺少的部分。谢谢!
猜你喜欢
  • 2011-03-17
  • 2019-01-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多