【发布时间】: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