【问题标题】:Makefile - Compile Single Objects in different directoryMakefile - 在不同目录中编译单个对象
【发布时间】:2019-03-19 13:44:58
【问题描述】:

我一直在梳理网络,但我无法找到正确的方法来让它发挥作用。只是试图创建一个简单的 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

【问题讨论】:

  • 我没有看到“cmake”标签与问题的关系。 CMake 不是 Make。

标签: gcc makefile gnu-make


【解决方案1】:

这个 makefile 有几个问题。基本上,您的规则的目标不是它们实际生成的文件,还有一条规则的先决条件不是它实际需要的文件。

假设您修改了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 规则要求所有(虚构的)目标文件,因此必须将所有源代码重新编译成已经存在且没有过期但 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 $@

【讨论】:

    猜你喜欢
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多