我将在此处更新标题和内容,以明确说明此特定问题是我在其他地方未明确回答的问题。关键概念是要理解,看起来像单个目标在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
。 (其中的注释表明我在运行时看到的内容。)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)没有像我想象的那样被执行;接受的答案已经澄清了这一点。
答案 0 :(得分:2)
制造的方式是,如果不提供参数,则将首先扫描Makefile
寻找“默认目标” 。默认目标只是它遇到的第一个目标(注意,它是第一个 target ,而不是 targets )。
根据您的情况,规则:
$(SUB_DIRS):
$(MAKE) -C $@
等效于:
src/zmachine src/cheap:
$(MAKE) -C $@
等同于:
src/zmachine:
$(MAKE) -C $@
src/cheap:
$(MAKE) -C $@
因此遇到的第一个目标是src/zmachine
,这是它的默认目标,也是要处理的目标。如user657267在评论中所述,解决此问题的方法是添加一个您将首先处理的目标,该目标将其他目标(您确实要构建)作为先决条件。