компиляция исходных файлов * .C и * .S из одного каталога 'make' - PullRequest
0 голосов
/ 27 февраля 2019

Я работал с проектом, который компилирует только исходные тексты на Си, но я обнаружил, что мне тоже нужен какой-то ассемблер, я не хочу вставлять ассемблерный код в C-файл, поскольку GCC может неправильно его интерпретировать.

Мой предшественник создал make-файл для проекта (извините, он довольно длинный):

# Compiler and options
CC          := sparc-rtems-gcc

# The application software binary
TARGET      := icu_asw

# Source and build directories
SRCDIR      := src
BUILDDIR    := obj
TARGETDIR   := bin
HDSWROOT    := ../../hdsw
BSWTOOLS    := ../../bsw/sw/tools
SRCEXT      := c
DEPEXT      := d
OBJEXT      := o
MRAMEXT     := img.elf

# Flags, libraries and includes
CFLAGS      := -std=gnu99 -Wall -Wextra -g
LIBDRV      := $(HDSWROOT)/lib/libdrv.a 
INCFLAGS    := -I$(HDSWROOT)/include -I$(HDSWROOT)/osal/rtems

# Debug flags
DEBUGFLAGS = -DLOGERROR=1 -DLOGWARN=1 -DLOGDEBUG=1 -DLOGINFO=1 -DMAKECHECKS=1
NODEBUGFLAGS = -DLOGERROR=1 -DLOGWARN=0 -DLOGDEBUG=0 -DLOGINFO=0 -DMAKECHECKS=1

#-----------------------------------------------------------------------
# Build instructions
#-----------------------------------------------------------------------
SOURCES     := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT))
OBJECTS     := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)))

# Default make
all: $(TARGET)

# Remake
remake: cleaner all

# Clean only objects
clean:
    @$(RM) -rf $(BUILDDIR)

# Full clean (objects and binaries)
cleaner: clean
    @$(RM) -rf $(TARGETDIR)

# Pull in dependency info for *existing* .o files
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))

# Link (uses an order-only prerequisite for the directories so that they
# don't affect the use of the $^)
$(TARGET): $(OBJECTS) | directories
    $(CC) -o $(TARGETDIR)/$(TARGET) $^ $(LIBDRV)

# Make the build and target directories
directories:
    @mkdir -p $(TARGETDIR)
    @mkdir -p $(BUILDDIR)

# Compile
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
    @mkdir -p $(dir $@)
    $(CC) $(CFLAGS) $(INCFLAGS) $(NODEBUGFLAGS) -c -o $@ $<
    @$(CC) $(CFLAGS) $(INCDEP) -MM $(SRCDIR)/$*.$(SRCEXT) > $(BUILDDIR)/$*.$(DEPEXT)
    @cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
    @sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
    @sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
    @rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp

# Non-File Targets
.PHONY: all remake clean cleaner

Я также хочу собрать и скомпилировать два файла .S, поэтому я отредактировал следующую строку

SOURCES     := $(shell find $(SRCDIR) -type f -name *.$(SRCEXT) -or -name *.$(ASMEXT))

Чтобы добавить файлы .S, я отредактировал ОБЪЕКТЫ, включив в них также источники ASM ("* .S")

OBJECTS     := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES:.$(SRCEXT)=.$(OBJEXT)),$(SOURCES:.$(ASMEXT)=.$(OBJEXT)))

Но при перекомпиляции с "make all"Я получаю:

$ make all
make: *** No rule to make target `obj/asi_access.S', needed by `icu_asw'.  Stop.

Не думаю, что кто-то может определить, где я иду не так?Я думаю, что я не правильно добавил в строку ОБЪЕКТЫ!

Спасибо

1 Ответ

0 голосов
/ 27 февраля 2019

Выражение $(var:.ext1=.ext2) не фильтрует по .ext1, т.е.

$(SOURCES:.$(SRCEXT)=.$(OBJEXT)) $(SOURCES:.$(ASMEXT)=.$(OBJEXT))

дает для списка источников тестов следующий результат

a.o b.o c.S a.c b.c c.o

Т.е. вы продублировали свои файлы и у вас есть исходные файлы в определении OBJECTS.

Следующий подход будет правильным:

OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%, \
             $(patsubst %.$(SRCEXT),%.$(OBJEXT), \
               $(patsubst %.$(ASMEXT),%.$(OBJEXT),$(SOURCES)) \
             ) \
           )

ОБНОВЛЕНИЕ: вам следует рассмотреть возможность использования 2 отдельных списков объектов, чтобы вы могли применять к ним различные правила, например

SOURCES_C   := $(filter %.$(SRCEXT),$(SOURCES))
OBJECTS_C   := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES_C:%.$(SRCEXT)=%.$(OBJEXT)))
SOURCES_ASM := $(filter %.$(ASMEXT),$(SOURCES))
OBJECTS_ASM := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(SOURCES_ASM:%.$(ASMEXT)=%.$(OBJEXT)))

$(OBJECTS_C): $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SRCEXT)
    .... C compiler recipe ....

$(OBJECTS_ASM): $(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(ASMEXT)
    .... assembler recipe ....

$(TARGET): $(OBJECTS_C) $(OBJECTS_ASM) | directories
...