Make 中的通配符模式匹配

Wildcard Pattern Matching in Make

这是我的项目结构。

| - src
     | - boot
           | - table.s
           | - boot.s
     | - machine
           | - revb
                | - memmap
                | - vars.s
     | - os
     | - utils
           | - ...lots here

我按文件夹对功能进行分组,并且有一个专门用于机器特定代码、link 脚本等的文件夹。

我在使用 make 时遇到的问题是我似乎无法使模式匹配工作。

The below runs and builds the .o files.

#This gets repetative as every file needs to have a recipe by itself.
$(TARGET_DIR)/hash.o : $(SRC_DIR)/utils/hash.s machine
    @echo "compiling $<"
    $(CC) $(CFLAGS) $< -o $@
    @echo "assembly dump $@"
    $(DUMP) -D $@ > $@.list

The below does NOT work. It doesn't run any of the commands.

#if this works that would be perfect every folder/file will be a recipe!
$(TARGET_DIR)/%.o : $(SRC_DIR)/%.s machine
    @echo "compiling $<"
    $(CC) $(CFLAGS) $< -o $@
    @echo "assembly dump $@"
    $(DUMP) -D $@ > $@.list

根本没有运行任何东西,出于某种原因,似乎没有文件与该模式匹配。

I have also tried this.

# if this works, it would be a bit annoying as this is per feature recipe/target.
$(TARGET_DIR)/%.o : $(SRC_DIR)/boot/%.s machine
    @echo "compiling $<"
    $(CC) $(CFLAGS) $< -o $@
    @echo "assembly dump $@"
    $(DUMP) -D $@ > $@.list

编辑 完整的 makefile 供参考

CFLAGS = -march=rv32i -mabi=ilp32
CC = riscv32-unknown-linux-gnu-as
LINKER = riscv32-unknown-linux-gnu-ld
DUMP = riscv32-unknown-linux-gnu-objdump
COPY = riscv32-unknown-linux-gnu-objcopy
SRC_DIR = src
TARGET_DIR = target
MACHINE_FILES_DIR = machine
TARGET_MACHINE = revb


# vizoros : $(TARGET_DIR)/%.o
#   $(LINKER) $(TARGET_DIR)/boot.o $(TARGET_DIR)/table.o $(TARGET_DIR)/os.o $(TARGET_DIR)/hash.o -T $(TARGET_DIR)/memmap -o $(TARGET_DIR)/$@.elf
#   $(DUMP) -D $(TARGET_DIR)/$@.elf > $(TARGET_DIR)/$@.list


$(TARGET_DIR)/%.o : $(SRC_DIR)/boot/%.s machine
    @echo "compiling $<"
    $(CC) $(CFLAGS) $< -o $@
    @echo "assembly dump $@"
    $(DUMP) -D $@ > $@.list

machine: folders
    cp -r $(SRC_DIR)/$(MACHINE_FILES_DIR)/$(TARGET_MACHINE)/. $(TARGET_DIR)

folders:
    mkdir -p $(TARGET_DIR)

.phony: clean
clean:
    rm -rf $(TARGET_DIR)

与您的其他问题一样,您对 make 的功能期望过高。 Make 是一个非常简单的工具。它不会在您的目录中四处寻找可以构建的文件。它只会构建你要求它构建的东西。它不会根据启发式推断匹配文件:它只会匹配精确的字符串。

Make 始终有效向后:它从您要求它构建的最终目标开始,并找到可以构建该目标的规则。然后它查看最终目标的每个先决条件,并找到可以构建每个先决条件的规则。然后它查看这些先决条件中的每一个先决条件的任何先决条件,等等。一旦构建(或找到源文件)目标的所有先决条件,它就会构建该目标,然后返回直到最终构建最终目标你要的。

在上面的 makefile 中,您已经注释掉了您想要构建的 "final target" (vizoros),因此 make 当然不会构建它。

我只是给你一个 makefile 来解决你的问题...如果你想了解它的作用,请查阅 GNU make 手册。注意我还没有真正尝试过这个,我只是在这里写的。另请注意,我省略了整个 machine 内容,因为我不明白它应该做什么,而且您并没有真正定义它。

CFLAGS = -march=rv32i -mabi=ilp32
CC = riscv32-unknown-linux-gnu-as
LINKER = riscv32-unknown-linux-gnu-ld
DUMP = riscv32-unknown-linux-gnu-objdump
COPY = riscv32-unknown-linux-gnu-objcopy
SRC_DIR = src
TARGET_DIR = target
MACHINE_FILES_DIR = machine
TARGET_MACHINE = revb

# Find all .s files under SRC_DIR

SRCS := $(shell find $(SRC_DIR) -name \*.s)

# Use VPATH with a list of directories to be searched for

VPATH := $(sort $(dir $(SRCS)))

# Convert all .s files into .o files directly under TARGET_DIR
# First strip off the directory, then convert

OBJS := $(patsubst %.s,$(TARGET_DIR)/%.o,$(notdir $(SRCS)))

# Define the final target and provide all the object files as prerequisites

$(TARGET_DIR)/vizoros.elf : $(OBJS)
        mkdir -p $(@D)
        $(LINKER) $^ -T $(TARGET_DIR)/memmap -o $@
        $(DUMP) -D $@ > $(@:.elf=.list)

# Define a pattern rule to build an object file in TARGET_DIR
# The source file will be searched for via VPATH

$(TARGET_DIR)/%.o : %.s
        mkdir -p $(@D)
        @echo "compiling $<"
        $(CC) $(CFLAGS) -c $< -o $@
        @echo "assembly dump $@"
        $(DUMP) -D $@ > $@.list

# It must be .PHONY, not .phony: make, like all POSIX tools, is
# case-sensitive

.PHONY: clean
clean:
        rm -rf $(TARGET_DIR)

参考文献:

另请注意,您的编译命令有误;您缺少 -c 选项,该选项告诉编译器生成目标文件而不是最终的可执行文件。