Makefile - Компилировать отдельные объекты в другой каталог - PullRequest
0 голосов
/ 19 марта 2019

Я расчесываю паутину и не могу найти правильный способ заставить это работать.Просто пытаюсь создать простой 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

1 Ответ

1 голос
/ 20 марта 2019

Есть несколько проблем с этим make-файлом. По сути, у вас есть правила, целью которых не являются файлы, которые они на самом деле производят, и правило, предварительными условиями которого не являются файлы, которые ему действительно нужны.

Предположим, вы изменили 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. Но правило эльфов требует всех (мнимых) объектных файлов, поэтому все источники должны быть перекомпилированы - в объектные файлы, которые уже существуют и не устарели, но которые 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 $@
...