GNU Make 包含其他 makefile 时的正确行为
GNU Make correct behaviour when including other makefiles
我在项目的根目录中有以下生成文件:
生成文件
# Board version
# Available: 3
PI ?= 3
# Kernel binaries
ifeq ($(PI), 3)
KERNEL_IMG := kernel8.img
else ifeq ($(PI), 2)
KERNEL_IMG := kernel7.img
else ifeq ($(PI), 1)
KERNEL_IMG := kernel.img
else
$(error Unsupported Raspberry Pi version)
endif
KERNEL_ELF := $(patsubst %.img,%.elf,$(KERNEL_IMG))
# Directories/paths
BUILD_DIR := build
# Toolchain
TOOLCHAIN ?= aarch64-elf
OBJCOPY := $(TOOLCHAIN)-objcopy
LD := $(TOOLCHAIN)-ld
CC := $(TOOLCHAIN)-gcc
# Misc
LINKER_SCRIPT := linker.ld
# Flags
LDFLAGS := -T $(LINKER_SCRIPT)
ASFLAGS :=
CFLAGS :=
# Source files
C_SRC := $(wildcard *.c)
ASM_SRC := $(wildcard *.S)
# Include
include pi/$(PI)/mod.mk
# Object files
OBJECTS := $(patsubst %,$(BUILD_DIR)/%.o,$(C_SRC))
OBJECTS += $(patsubst %,$(BUILD_DIR)/%.o,$(ASM_SRC))
# Targets
.PHONY: all builddirs clean
all: $(BUILD_DIR)/$(KERNEL_IMG)
$(BUILD_DIR)/$(KERNEL_IMG): $(BUILD_DIR)/$(KERNEL_ELF)
$(OBJCOPY) $< -O binary $@
$(BUILD_DIR)/$(KERNEL_ELF): $(LINKER_SCRIPT) $(OBJECTS)
$(LD) $(OBJECTS) $(LDFLAGS) -o $@
$(OBJECTS): | builddirs
builddirs: $(BUILD_DIR)/pi/$(PI)
$(BUILD_DIR)/pi/$(PI):
mkdir -p $@
$(BUILD_DIR)/%.S.o: %.S
$(CC) -c $< $(ASFLAGS) -o $@
$(BUILD_DIR)/%.c.o: %.c
$(CC) -c $< $(CFLAGS) -o $@
clean:
$(RM) -r $(BUILD_DIR)
它包括pi/3/mod.mk
C_SRC +=
ASM_SRC += pi/3/start.S
$(BUILD_DIR)/pi/3/start.S.o: pi/3/start.S pi/3/include/cpu/sysregs.h
$(CC) -c $< $(ASFLAGS) -o $@
现在的问题是:每当我 运行 'make' 在项目的根目录中时,'$(BUILD_DIR)/pi/3/start.S.o'规则调用,而不是 'all'。如果我将 'include pi/$(PI)/mod.mk' 移动到根 makefile 的最底部,并将 'pi/3/mod.mk' 中的 'C_SRC' 和 'ASM_SRC' 变量替换为 'OBJECTS += $(BUILD_DIR)/pi/3/start.S.o' 并调用 'make' ,这个规则甚至没有被调用,所以我得到一个 make doesn't know how to build start.S.o.
的错误
我哪里做错了,最好的处理方法是什么?
Make 的默认目标是 Makefile 中的第一个目标。在您的情况下,第一个目标是在包含的 Makefile 中定义的目标:$(BUILD_DIR)/pi/3/start.S.o
。在 Makefile 中调用 make all
或移动 all
规则,使其成为第一个规则,或者告诉 make 默认目标是 all
:
.DEFAULT_GOAL := all
(参见 GNU make manual)。
我在项目的根目录中有以下生成文件:
生成文件
# Board version
# Available: 3
PI ?= 3
# Kernel binaries
ifeq ($(PI), 3)
KERNEL_IMG := kernel8.img
else ifeq ($(PI), 2)
KERNEL_IMG := kernel7.img
else ifeq ($(PI), 1)
KERNEL_IMG := kernel.img
else
$(error Unsupported Raspberry Pi version)
endif
KERNEL_ELF := $(patsubst %.img,%.elf,$(KERNEL_IMG))
# Directories/paths
BUILD_DIR := build
# Toolchain
TOOLCHAIN ?= aarch64-elf
OBJCOPY := $(TOOLCHAIN)-objcopy
LD := $(TOOLCHAIN)-ld
CC := $(TOOLCHAIN)-gcc
# Misc
LINKER_SCRIPT := linker.ld
# Flags
LDFLAGS := -T $(LINKER_SCRIPT)
ASFLAGS :=
CFLAGS :=
# Source files
C_SRC := $(wildcard *.c)
ASM_SRC := $(wildcard *.S)
# Include
include pi/$(PI)/mod.mk
# Object files
OBJECTS := $(patsubst %,$(BUILD_DIR)/%.o,$(C_SRC))
OBJECTS += $(patsubst %,$(BUILD_DIR)/%.o,$(ASM_SRC))
# Targets
.PHONY: all builddirs clean
all: $(BUILD_DIR)/$(KERNEL_IMG)
$(BUILD_DIR)/$(KERNEL_IMG): $(BUILD_DIR)/$(KERNEL_ELF)
$(OBJCOPY) $< -O binary $@
$(BUILD_DIR)/$(KERNEL_ELF): $(LINKER_SCRIPT) $(OBJECTS)
$(LD) $(OBJECTS) $(LDFLAGS) -o $@
$(OBJECTS): | builddirs
builddirs: $(BUILD_DIR)/pi/$(PI)
$(BUILD_DIR)/pi/$(PI):
mkdir -p $@
$(BUILD_DIR)/%.S.o: %.S
$(CC) -c $< $(ASFLAGS) -o $@
$(BUILD_DIR)/%.c.o: %.c
$(CC) -c $< $(CFLAGS) -o $@
clean:
$(RM) -r $(BUILD_DIR)
它包括pi/3/mod.mk
C_SRC +=
ASM_SRC += pi/3/start.S
$(BUILD_DIR)/pi/3/start.S.o: pi/3/start.S pi/3/include/cpu/sysregs.h
$(CC) -c $< $(ASFLAGS) -o $@
现在的问题是:每当我 运行 'make' 在项目的根目录中时,'$(BUILD_DIR)/pi/3/start.S.o'规则调用,而不是 'all'。如果我将 'include pi/$(PI)/mod.mk' 移动到根 makefile 的最底部,并将 'pi/3/mod.mk' 中的 'C_SRC' 和 'ASM_SRC' 变量替换为 'OBJECTS += $(BUILD_DIR)/pi/3/start.S.o' 并调用 'make' ,这个规则甚至没有被调用,所以我得到一个 make doesn't know how to build start.S.o.
的错误我哪里做错了,最好的处理方法是什么?
Make 的默认目标是 Makefile 中的第一个目标。在您的情况下,第一个目标是在包含的 Makefile 中定义的目标:$(BUILD_DIR)/pi/3/start.S.o
。在 Makefile 中调用 make all
或移动 all
规则,使其成为第一个规则,或者告诉 make 默认目标是 all
:
.DEFAULT_GOAL := all
(参见 GNU make manual)。