如何编写基于通用规则的makefile

时间:2017-11-25 16:17:00

标签: makefile

我有以下文件夹结构

    --Makefile
    --source/
        --boot.s
        --kernel.c
        --linker.ld
    --build/

我使用以下Makefile编译我的源代码

###############################################################################
#
#   A makefile script for generation of raspberry pi kernel images.
#
###############################################################################

# The toolchain to use. arm-none-eabi works, but there does exist 
CC = arm-none-eabi-gcc
LD = arm-none-eabi-gcc

# The intermediate directory for compiled object files.
BUILD = build/

# The directory in which source files are stored.
SOURCE = source/

CFLAGS =    -march=armv8-a+crc \
            -mcpu=cortex-a53 \
            -mtune=cortex-a53 \
            -mfpu=crypto-neon-fp-armv8 \
            -mfloat-abi=hard \
            -ftree-vectorize \
            -funsafe-math-optimizations \
            -O2 -pipe -ffreestanding

LDFLAGS = -T $(SOURCE)linker.ld -ffreestanding -O2 -nostdlib


# The name of the output file to generate.
TARGET = kernel.img

.PHONY: all clean run

# Rule to make everything.
all: $(TARGET)

# Rule to remake everything. Does not include clean.
rebuild: clean all 

#Rule to invoke qemu
run:
    qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $(BUILD)kernel.elf

$(TARGET): kernel.elf
    arm-none-eabi-objcopy $(BUILD)kernel.elf -O binary $(BUILD)kernel.img

kernel.elf: boot.o kernel.o
    $(LD)   $(LDFLAGS) -o $(BUILD)kernel.elf $(BUILD)boot.o $(BUILD)kernel.o

boot.o: $(SOURCE)boot.s
    $(CC) $(CFLAGS) -c $(SOURCE)boot.s -o $(BUILD)boot.o

kernel.o: $(SOURCE)boot.s
    $(CC) $(CFLAGS) -c $(SOURCE)kernel.c -o $(BUILD)kernel.o

# Rule to clean files.
clean : 
    -rm -f $(BUILD)*
    -rm -f *.o
    -rm -f *.elf
    -rm -f *.img

如何编写基于模式的规则?我尝试了很多堆栈溢出答案,但无法使其工作。

首先我使用通配符列出了我的源代码,但无法编写正确的目标,因为源列表有[source / boot.s source / kernel.c],它会自动在源文件夹中创建目标文件。

我在保持资源和构建目录方面遇到了困难。任何帮助表示赞赏。

----------根据@MadScientist的完整解决方案-----------

###############################################################################
#
#   A makefile script for generation of raspberry pi kernel images.
#
###############################################################################

# The toolchain to use. arm-none-eabi works, but there does exist 
CC = arm-none-eabi-gcc
LD = arm-none-eabi-gcc

# The intermediate directory for compiled object files.
BUILD = build/

# The directory in which source files are stored.
SOURCE = source/

CFLAGS =    -march=armv8-a+crc \
            -mcpu=cortex-a53 \
            -mtune=cortex-a53 \
            -mfpu=crypto-neon-fp-armv8 \
            -mfloat-abi=hard \
            -ftree-vectorize \
            -funsafe-math-optimizations \
            -O2 -pipe -ffreestanding

LDFLAGS = -T $(SOURCE)linker.ld -ffreestanding -O2 -nostdlib

SOURCES := $(wildcard $(SOURCE)*.s) $(wildcard $(SOURCE)*.c)
OBJECTS := $(patsubst $(SOURCE)%,$(BUILD)%.o,$(basename $(SOURCES)))

# The name of the output file to generate.
TARGET = kernel.img

.PHONY: all clean run

# Rule to make everything.
all: $(BUILD)$(TARGET)

# Rule to remake everything. Does not include clean.
rebuild: clean all 

#Rule to invoke qemu
run:
    qemu-system-arm -m 256 -M raspi2 -serial stdio -kernel $(BUILD)kernel.elf

$(BUILD)%.o : $(SOURCE)%.s
    $(CC) $(CFLAGS) -c $< -o $@

$(BUILD)%.o : $(SOURCE)%.c
    $(CC) $(CFLAGS) -c $< -o $@

$(BUILD)$(TARGET): $(BUILD)kernel.elf
    arm-none-eabi-objcopy $< -O binary $@

$(BUILD)kernel.elf: $(OBJECTS)
    $(LD) $(LDFLAGS) -o $@ $^

# Rule to clean files.
clean : 
    -rm -f $(BUILD)*
    -rm -f *.o
    -rm -f *.elf
    -rm -f *.img

1 个答案:

答案 0 :(得分:1)

这是错误的:

boot.o: $(SOURCE)boot.s
        $(CC) $(CFLAGS) -c $(SOURCE)boot.s -o $(BUILD)boot.o

您告诉make您的配方将构建一个名为boot.o的文件,但它不会:它创建一个名为$(BUILD)boot.o的文件,这是完全不同的。与您构建kernel.imgkernel.elf的规则相同。

如果要编写模式规则,%只能匹配相同的部分。由于SOURCEBUILD不相同,因此它们与%部分不匹配。所以你必须写下这个:

$(BUILD)%.o : $(SOURCE)%.s
         $(CC) $(CFLAGS) -c $< -o $@

由于你正在构建$(BUILD)xxx.o,你必须将它作为先决条件,所以你必须写:

$(BUILD)$(TARGET): $(BUILD)kernel.elf
        arm-none-eabi-objcopy $< -O binary $@

$(BUILD)kernel.elf: $(BUILD)boot.o $(BUILD)kernel.o
        $(LD) $(LDFLAGS) -o $@ $^

ETA

如果你想通过通配符获取源文件,你必须替换目录,而不仅仅是后缀,如下所示:

SOURCES := $(wildcard $(SOURCE)*.s)
OBJECTS := $(patsubst $(SOURCE)%.s,$(BUILD)%.o,$(SOURCES))

如果你同时拥有汇编和C源文件(你的示例makefile中没有显示任何C源文件),你可以使用它:

SOURCES := $(wildcard $(SOURCE)*.s) $(wildcard $(SOURCE)*.c)
OBJECTS := $(patsubst $(SOURCE)%,$(BUILD)%.o,$(basename $(SOURCES)))