【问题标题】:compiling *.C and *.S sources from same directory 'make'从同一目录“make”编译 *.C 和 *.S 源
【发布时间】:2019-02-27 17:18:24
【问题描述】:

我一直在处理一个只编译 C 源代码的项目,但我发现我也需要一些汇编程序,我不愿将 asm 代码内联到 C 文件中,因为 GCC 可能无法正确解释它。

我的前任为该项目创建了 makefile(抱歉,它相当长):

# 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 文件,我编辑了 OBJECTS 以包含 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.

我不认为有人能发现我哪里出错了?我想我没有正确添加到 OBJECTS 行!

谢谢

【问题讨论】:

    标签: makefile gnu-make


    【解决方案1】:

    表达式$(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
    

    【讨论】:

    • 嗯,现在我得到了:make: *** 没有规则来制作目标 obj/asi_access.', needed by icu_asw'。停止。
    • 我建议将$(info OBJECTS '$(OBJECTS)') 添加到makefile 中,这样您就可以看到实际的变量内容是什么。这比在黑暗中猜测可能出了什么问题要容易...您可能在 patsubst 中有一个变量名拼写错误,即 asi_access.S 被替换为 asi_access.
    • 啊,好吧,所以似乎每个文件扩展名都丢失了。对象'obj/asi_access。 obj/copy_nocache。 ....等编辑:刚刚看到您的更新,因此将进一步探索。谢谢!
    • 哦,抱歉,我输入的是 $(OBJECT) 而不是 $(OBJEXT) :-/ 我会更新我的答案
    • 感谢 Stefan,我正在走得更远,但我想现在我还必须编辑: -include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT)) 用于 OBJECTS_C 和 OBJECTS_ASM。我可以在同一条线上吗?谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-05-21
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-19
    • 1970-01-01
    相关资源
    最近更新 更多