Makefile - 在不同的目录中编译单个对象
Makefile - Compile Single Objects in different directory
我一直在梳理网络,但我想不出使它起作用的正确方法。只是尝试创建一个简单的 Makefile,它采用我的源代码并只构建更改的文件。我需要将所有 .o 文件放在同一个输出文件夹中。我目前一切正常,除了如果我更改一个文件,整个文件都会重建。例如,如果我更改 main.c,它也会编译 EOL.c。但是,如果没有任何变化,它表示无需执行任何操作。
NAME=Program
CC=arm-none-eabi-gcc
CFLAGS=-c -Wall -O0 -std=c99 \
-nostartfiles --specs=nano.specs \
-mthumb -fmessage-length=0 \
-fsigned-char -ffunction-sections \
-fdata-sections -mcpu=cortex-m0
BID?=_DEV
DEFINES= -DPROD -DBLD_ID=\"$(BID)\"
LDFLAGS= -nostartfiles
INCLUDES= -ISrc/App/Include -ISrc/Device/CMSIS/Include
SOURCES= Src/main.c Src/App/Source/Application.c Src/App/Source/EOL.c Src/Svc/Source/TimerManager.c
OBJECTS=$(OBJECTS1:.c=.o)
OBJECTS1=$(SOURCES:.S=.o)
OFILES1=$(notdir ${OBJECTS})
OFILES=$(addprefix $(OBJDIR)/,$(OFILES1))
OBJDIR=Output
.PHONY: all rebuild clean
all: $(OBJDIR) $(SOURCES) $(OBJDIR)/$(NAME).hex
%.hex: %.elf
arm-none-eabi-objcopy -O ihex $< $@
%elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(OFILES) -o $@
rebuild: clean all
.SECONDARY:
.c.o:
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $(OBJDIR)/$(notdir $@)
.S.o:
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $(OBJDIR)/$(notdir $@)
$(OBJDIR):
mkdir $(OBJDIR)
clean:
rm -f $(OBJDIR)/*.o $(OBJDIR)/*.elf $(OBJDIR)/*.hex $(OBJDIR)/*.bin
这个生成文件有几个问题。基本上,您有一些规则,其目标不是它们实际生成的文件,还有一个规则,其先决条件不是它实际需要的文件。
假设您已修改 Src/main.c
并尝试使用此规则重建 Output/Program.elf
:
%elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(OFILES) -o $@
先决条件($(OBJECTS)
)其实就是Src/main.o Src/App/Source/EOL.o
等等。这些文件不存在——它们从不存在——但是它们有一个规则:
.c.o:
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $(OBJDIR)/$(notdir $@)
Make 发现 Src/main.o
依赖于 Src/main.c
,因此必须重建,Output/Program.elf
也是如此。所以它调用了这条规则——它实际上构建了 Output/main.o
。但是 elf 规则要求 all 个(虚构的)目标文件,所以所有的源代码都必须重新编译——变成已经存在并且没有过时的目标文件,但是 Make没注意。
首先要做的是修复对象规则,但是有一个问题:虽然规则有缺陷,但它们的优点是帮助 Make 找到相应的源文件(在滥用它们之前),就像这样:
Src/App/Source/EOL.o: Src/App/Source/EOL.c
...
如何告诉Make去哪里找Output/EOL.o
对应的源文件呢?方法不止一种,但一个好方法是使用 vpath:
vpath %.c Src/App/Source
Output/EOL.o: EOL.c
...
我们所要做的就是创建一个源目录列表,将其传递给 vpath,并修改模式规则:
SRCDIRS := $(dir $(SOURCES))
vpath %.c $(SRCDIRS)
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $@
(.S.o
规则可以用同样的方法修复。)
然后修改 elf
规则以命名并使用其真正的先决条件:
%elf: $(OFILES)
$(CC) $(LDFLAGS) $^ -o $@
我一直在梳理网络,但我想不出使它起作用的正确方法。只是尝试创建一个简单的 Makefile,它采用我的源代码并只构建更改的文件。我需要将所有 .o 文件放在同一个输出文件夹中。我目前一切正常,除了如果我更改一个文件,整个文件都会重建。例如,如果我更改 main.c,它也会编译 EOL.c。但是,如果没有任何变化,它表示无需执行任何操作。
NAME=Program
CC=arm-none-eabi-gcc
CFLAGS=-c -Wall -O0 -std=c99 \
-nostartfiles --specs=nano.specs \
-mthumb -fmessage-length=0 \
-fsigned-char -ffunction-sections \
-fdata-sections -mcpu=cortex-m0
BID?=_DEV
DEFINES= -DPROD -DBLD_ID=\"$(BID)\"
LDFLAGS= -nostartfiles
INCLUDES= -ISrc/App/Include -ISrc/Device/CMSIS/Include
SOURCES= Src/main.c Src/App/Source/Application.c Src/App/Source/EOL.c Src/Svc/Source/TimerManager.c
OBJECTS=$(OBJECTS1:.c=.o)
OBJECTS1=$(SOURCES:.S=.o)
OFILES1=$(notdir ${OBJECTS})
OFILES=$(addprefix $(OBJDIR)/,$(OFILES1))
OBJDIR=Output
.PHONY: all rebuild clean
all: $(OBJDIR) $(SOURCES) $(OBJDIR)/$(NAME).hex
%.hex: %.elf
arm-none-eabi-objcopy -O ihex $< $@
%elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(OFILES) -o $@
rebuild: clean all
.SECONDARY:
.c.o:
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $(OBJDIR)/$(notdir $@)
.S.o:
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $(OBJDIR)/$(notdir $@)
$(OBJDIR):
mkdir $(OBJDIR)
clean:
rm -f $(OBJDIR)/*.o $(OBJDIR)/*.elf $(OBJDIR)/*.hex $(OBJDIR)/*.bin
这个生成文件有几个问题。基本上,您有一些规则,其目标不是它们实际生成的文件,还有一个规则,其先决条件不是它实际需要的文件。
假设您已修改 Src/main.c
并尝试使用此规则重建 Output/Program.elf
:
%elf: $(OBJECTS)
$(CC) $(LDFLAGS) $(OFILES) -o $@
先决条件($(OBJECTS)
)其实就是Src/main.o Src/App/Source/EOL.o
等等。这些文件不存在——它们从不存在——但是它们有一个规则:
.c.o:
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $(OBJDIR)/$(notdir $@)
Make 发现 Src/main.o
依赖于 Src/main.c
,因此必须重建,Output/Program.elf
也是如此。所以它调用了这条规则——它实际上构建了 Output/main.o
。但是 elf 规则要求 all 个(虚构的)目标文件,所以所有的源代码都必须重新编译——变成已经存在并且没有过时的目标文件,但是 Make没注意。
首先要做的是修复对象规则,但是有一个问题:虽然规则有缺陷,但它们的优点是帮助 Make 找到相应的源文件(在滥用它们之前),就像这样:
Src/App/Source/EOL.o: Src/App/Source/EOL.c
...
如何告诉Make去哪里找Output/EOL.o
对应的源文件呢?方法不止一种,但一个好方法是使用 vpath:
vpath %.c Src/App/Source
Output/EOL.o: EOL.c
...
我们所要做的就是创建一个源目录列表,将其传递给 vpath,并修改模式规则:
SRCDIRS := $(dir $(SOURCES))
vpath %.c $(SRCDIRS)
$(OBJDIR)/%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) $< -o $@
(.S.o
规则可以用同样的方法修复。)
然后修改 elf
规则以命名并使用其真正的先决条件:
%elf: $(OFILES)
$(CC) $(LDFLAGS) $^ -o $@