clang makefile“ar:没有指定存档成员”

时间:2017-02-14 12:06:49

标签: c gcc makefile clang ar

我重构了一些C代码,我尝试将它编译为mac上的clang上的lib而不是linux上的gcc。

首先,如果我只是运行make命令,我在第一个文件编译时遇到错误:
+++ Compiling [sys_msg.c] clang: error: unsupported argument '-adhlns=../../src/sys_msg.lst' to option 'Wa,'

所以我删除了创建此错误的-Wa,-adhlns=$(<:.c=.lst)选项。

之后一切似乎都在编译,但是最后一个.a文件的汇编失败了,我不明白为什么。

这是我的输出:

+++ Creation of [../../hal/stub/obj]
+++ Dependencies of [hal.c]
+++ Dependencies of [target.c]
+++ Dependencies of [robus.c]
+++ Dependencies of [reception.c]
+++ Dependencies of [sys_msg.c]
+++ Compiling [sys_msg.c]
+++ Compiling [reception.c]
+++ Compiling [robus.c]
+++ Compiling [target.c]
+++ Compiling [hal.c]
ar -rv ../../hal/stub/libstub.a 
ar: no archive members specified
usage:  ar -d [-TLsv] archive file ...
    ar -m [-TLsv] archive file ...
    ar -m [-abiTLsv] position archive file ...
    ar -p [-TLsv] archive [file ...]
    ar -q [-cTLsv] archive file ...
    ar -r [-cuTLsv] archive file ...
    ar -r [-abciuTLsv] position archive file ...
    ar -t [-TLsv] archive [file ...]
    ar -x [-ouTLsv] archive [file ...]
make: *** [../../hal/stub/libstub.a] Error 1

这是我的makefile:

# make all = Make software and program
# make clean = Clean out built project files.
# make program = Download the hex file to the device, using avrdude.  Please
#                customize the avrdude settings below first!
# make docs = compile with doxygen the code documentation

# Maximum I2C speed (HZ)
SCLFREQ = 400000

#-------------------------------------------------------------------------------
# Tools
#-------------------------------------------------------------------------------

# Set DEBUG variable for once if not coming from command line
ifndef DEBUG
DEBUG = 0
endif

# Tool suffix when cross-compiling
CROSS_COMPILE ?=

# Compilation tools
CC = $(CROSS_COMPILE)gcc
AR = $(CROSS_COMPILE)ar
SIZE = $(CROSS_COMPILE)size
STRIP = $(CROSS_COMPILE)strip
OBJCOPY = $(CROSS_COMPILE)objcopy
OBJDUMP = $(CROSS_COMPILE)objdump
SIZE = $(CROSS_COMPILE)size
GDB = $(CROSS_COMPILE)gdb
NM = $(CROSS_COMPILE)nm

ROOT_PATH = ../..
HAL_PATH = $(ROOT_PATH)/hal/$(BOARD)
DOC_PATH = $(ROOT_PATH)/../extra/Docs

# Doxygen configuration file name
DOXYFILE = $(ROOT_PATH)/../extra/.Doxyfile

OBJ_PATH = $(HAL_PATH)/obj
OUTPUT_NAME = lib$(BOARD)
OUTPUT_FILE_PATH = $(HAL_PATH)/$(OUTPUT_NAME).a

#|---------------------------------------------------------------------------------------|
#| Source files                                                                          |
#|---------------------------------------------------------------------------------------|
include ../sources.mk

#|---------------------------------------------------------------------------------------|
#| Extract file names and path                                                           |
#|---------------------------------------------------------------------------------------|
PROJ_ASRCS   = $(filter %.s,$(foreach file,$(SOURCES),$(file)))
PROJ_ASRCS  += $(filter %.S,$(foreach file,$(SOURCES),$(file)))
PROJ_CSRCS   = $(filter %.c,$(foreach file,$(SOURCES),$(file)))
PROJ_CPPSRCS = $(filter %.cpp,$(foreach file,$(SOURCES),$(file)))

#|---------------------------------------------------------------------------------------|
#| Set important path variables                                                          |
#|---------------------------------------------------------------------------------------|
VPATH    = $(foreach path,$(sort $(foreach file,$(SOURCES),$(dir $(file)))),$(path) :)
INC_PATH = $(INCLUDES)
LIB_PATH = -L$(dir $(RESOURCES_LINKER))

#|---------------------------------------------------------------------------------------|
#| Options for compiler binaries                                                         |
#|---------------------------------------------------------------------------------------|

COMMON_FLAGS = \
-g -O$(OPT)                                                      \
-funsigned-char -fpack-struct -fshort-enums                      \
-Wall -Wstrict-prototypes                                        \
-DMCU=$(MCU)                                                     \
-DMAINCLOCK=$(MAINCLOCK)                                         \
-DSCLFREQ=$(SCLFREQ)                                             \
$(INCLUDES)


ifeq ($(CROSS_COMPILE),avr-)
    COMMON_FLAGS += -mmcu=$(MCU)
    ASFLAGS = -mmcu=$(MCU)
endif

CFLAGS += $(COMMON_FLAGS) -std=gnu99

CPPFLAGS = $(COMMON_FLAGS) -std=gnu++11 -fno-rtti -fno-exceptions

ASFLAGS += -Wa,-adhlns=$(<:.S=.lst),-gstabs -I. -x assembler-with-cpp

LDFLAGS = -Wl,-Map=$(BOARD).map,--cref

#|---------------------------------------------------------------------------------------|
#| Define targets                                                                        |
#|---------------------------------------------------------------------------------------|
#AOBJS += $(patsubst %.S,%.o,$(PROJ_ASRCS))
AOBJS = $(patsubst %.s,%.o,$(addprefix $(OBJ_PATH)/, $(notdir $(PROJ_ASRCS))))
COBJS = $(patsubst %.c,%.o,$(addprefix $(OBJ_PATH)/, $(notdir $(PROJ_CSRCS))))
CPPOBJS = $(patsubst %.cpp,%.o,$(addprefix $(OBJ_PATH)/, $(notdir $(PROJ_CPPSRCS))))

.PHONY: all clean print_info packaging

all: $(OUTPUT_FILE_PATH)

print_info:
    @echo DEFAULT_GOAL ---------------------------------------------------------------------------------
    @echo $(.DEFAULT_GOAL)
    @echo VPATH ---------------------------------------------------------------------------------
    @echo $(VPATH)
    @echo SOURCES -------------------------------------------------------------------------------
    @echo $(SOURCES)
#   @echo PROJ_ASRCS ----------------------------------------------------------------------------
#   @echo $(PROJ_ASRCS)
#   @echo AOBJS ---------------------------------------------------------------------------------
#   @echo $(AOBJS)
    @echo PROJ_CSRCS ----------------------------------------------------------------------------
    @echo $(PROJ_CSRCS)
    @echo COBJS ---------------------------------------------------------------------------------
    @echo $(COBJS)
    @echo PROJ_CPPSRCS --------------------------------------------------------------------------
    @echo $(PROJ_CPPSRCS)
    @echo CPPOBJS -------------------------------------------------------------------------------
    @echo $(CPPOBJS)
    @echo ---------------------------------------------------------------------------------------
    @echo $(CURDIR)
    @echo $(OUTPUT_FILE_PATH)
    @echo ---------------------------------------------------------------------------------------

$(OUTPUT_FILE_PATH): $(OBJ_PATH) ../rules.mk ../sources.mk $(HAL_PATH)/Makefile $(AOBJS) $(COBJS) $(CPPOBJS)
    $(AR) -rv $(OUTPUT_FILE_PATH) $(AOBJS)
    $(AR) -rv $(OUTPUT_FILE_PATH) $(COBJS)
    $(AR) -rv $(OUTPUT_FILE_PATH) $(CPPOBJS)
    $(NM) $(OUTPUT_FILE_PATH) > $(HAL_PATH)/$(OUTPUT_NAME)_symbols.txt

#|---------------------------------------------------------------------------------------|
#| Compile or assemble                                                                   |
#|---------------------------------------------------------------------------------------|
$(AOBJS): $(OBJ_PATH)/%.o: %.s
    @echo +++ Assembling [$(notdir $<)]
    @$(AS) $(AFLAGS) $< -o $@

$(AOBJS): $(OBJ_PATH)/%.o: %.S
    @echo +++ Assembling [$(notdir $<)]
    @$(AS) $(AFLAGS) $< -o $@

$(COBJS): $(OBJ_PATH)/%.o: %.c
    @echo +++ Compiling [$(notdir $<)]
    @$(CC) $(CFLAGS) -c $< -o $@

$(CPPOBJS): $(OBJ_PATH)/%.o: %.cpp
    @echo +++ Compiling [$(notdir $<)]
    @$(CC) $(CPPFLAGS) -c $< -o $@

#|---------------------------------------------------------------------------------------|
#| Output folder                                                                         |
#|---------------------------------------------------------------------------------------|
$(OBJ_PATH):
    @echo +++ Creation of [$@]
    @-mkdir $(OBJ_PATH)

#|---------------------------------------------------------------------------------------|
#| Cleanup                                                                               |
#|---------------------------------------------------------------------------------------|
clean:
    -rm -f $(OBJ_PATH)/* $(OBJ_PATH)/*.*
    -rmdir $(OBJ_PATH)
    -rm -f $(OUTPUT_FILE_PATH)
    -rm -f $(HAL_PATH)/$(OUTPUT_NAME)_symbols.txt
    -rm -rf $(DOC_PATH)

#|---------------------------------------------------------------------------------------|
#| Dependencies                                                                          |
#|---------------------------------------------------------------------------------------|
$(OBJ_PATH)/%.d: %.s $(OBJ_PATH)
    @echo +++ Dependencies of [$(notdir $<)]
    @$(CC) $(AFLAGS) -MM -c $< -MT $(basename $@).o -o $@

$(OBJ_PATH)/%.d: %.S $(OBJ_PATH)
    @echo +++ Dependencies of [$(notdir $<)]
    @$(CC) $(AFLAGS) -MM -c $< -MT $(basename $@).o -o $@

$(OBJ_PATH)/%.d: %.c $(OBJ_PATH)
    @echo +++ Dependencies of [$(notdir $<)]
    @$(CC) $(CFLAGS) -MM -c $< -MT $(basename $@).o -o $@

$(OBJ_PATH)/%.d: %.cpp $(OBJ_PATH)
    @echo +++ Dependencies of [$(notdir $<)]
    @$(CC) $(CPPFLAGS) -MM -c $< -MT $(basename $@).o -o $@

#|---------------------------------------------------------------------------------------|
#| Include dependencies, if existing                                                     |
#| Little trick to avoid dependencies build for some rules when useless                  |
#| CAUTION: this won't work as expected with 'make clean all'                            |
#|---------------------------------------------------------------------------------------|
DEP_EXCLUDE_RULES := clean print_info
ifeq (,$(findstring $(MAKECMDGOALS), $(DEP_EXCLUDE_RULES)))
-include $(AOBJS:%.o=%.d)
-include $(COBJS:%.o=%.d)
-include $(CPPOBJS:%.o=%.d)
endif


#|---------------------------------------------------------------------------------------|
#| Module packaging for Arduino IDE Board Manager                                        |
#|---------------------------------------------------------------------------------------|
packaging: $(OUTPUT_FILE_PATH)

docs:   ( cat $(DOXYFILE) ; echo "OUTPUT_DIRECTORY = $(DOC_PATH)" ; echo "INPUT = $(DOC_SOURCES)" ) | doxygen -
#   doxygen $(DOXYFILE)

%.d:

为什么clang会提请我这个?

感谢@MadScientist 我理解为什么我有这个错误,如果我在我的作品上打印出来的东西:

$make print_info 
DEFAULT_GOAL ---------------------------------------------------------------------------------
all
VPATH ---------------------------------------------------------------------------------
../../hal/stub/ : ../../src/ :
SOURCES -------------------------------------------------------------------------------
../../src/sys_msg.c ../../src/reception.c ../../src/robus.c ../../src/target.c ../../hal/stub/hal.c
PROJ_ASRCS ----------------------------------------------------------------------------

AOBJS ---------------------------------------------------------------------------------

PROJ_CSRCS ----------------------------------------------------------------------------
../../src/sys_msg.c ../../src/reception.c ../../src/robus.c ../../src/target.c ../../hal/stub/hal.c
COBJS ---------------------------------------------------------------------------------
../../hal/stub/obj/sys_msg.o ../../hal/stub/obj/reception.o ../../hal/stub/obj/robus.o ../../hal/stub/obj/target.o ../../hal/stub/obj/hal.o
PROJ_CPPSRCS --------------------------------------------------------------------------

CPPOBJS -------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
/Users/nico/Documents/pollen/Robus/robus/hal/stub
../../hal/stub/libstub.a
---------------------------------------------------------------------------------------

我的错误来自于makefile的这一部分:

PROJ_ASRCS   = $(filter %.s,$(foreach file,$(SOURCES),$(file)))
PROJ_ASRCS  += $(filter %.S,$(foreach file,$(SOURCES),$(file)))

我不想包含所有.o因为我做了多次编译,我只想列出所需的文件。

我的编译过程与ExperimentalCore-sam项目相同。

我该怎么做?

2 个答案:

答案 0 :(得分:1)

我只能假设变量AOBJS为空。回到它创建的位置,我只能假设这意味着.s变量中没有列出.SSOURCES个文件。

为什么不运行$(AR)的单个调用,只使用$^自动变量并过滤掉.o个文件,而不是$(AR)的三个不同调用命令?

$(AR) -rv $(OUTPUT_FILE_PATH) $(filter %.o,$^)

编辑要明确我建议您将输出目标规则更改为:

$(OUTPUT_FILE_PATH): $(OBJ_PATH) ../rules.mk ../sources.mk $(HAL_PATH)/Makefile $(AOBJS) $(COBJS) $(CPPOBJS)
        $(AR) -rv $(OUTPUT_FILE_PATH) $(filter %.o,$^)
        $(NM) $(OUTPUT_FILE_PATH) > $(HAL_PATH)/$(OUTPUT_NAME)_symbols.txt

或者,如果你想更正确地说:

$(OUTPUT_FILE_PATH): $(OBJ_PATH) ../rules.mk ../sources.mk $(HAL_PATH)/Makefile $(AOBJS) $(COBJS) $(CPPOBJS)
        $(AR) -rv $@ $(filter %.o,$^)
        $(NM) $@ > $(HAL_PATH)/$(OUTPUT_NAME)_symbols.txt

如上所述,我肯定会从先决条件列表中删除$(OBJ_PATH)

答案 1 :(得分:1)

我理解GCC和Clang之间的区别。

如果您运行ar命令而未指定存档成员,则使用GCC,他只是跳过该步骤。 Clang在这种情况下引发错误并停止构建。

要修补它,我只是检查我的列表是否为空:

$(OUTPUT_FILE_PATH): $(OBJ_PATH) ../rules.mk ../sources.mk $(HAL_PATH)/Makefile $(AOBJS) $(COBJS) $(CPPOBJS)
ifneq ($(strip $(AOBJS)),)
    $(AR) -rv $(OUTPUT_FILE_PATH) $(AOBJS)
endif
ifneq ($(strip $(COBJS)),)
    $(AR) -rv $(OUTPUT_FILE_PATH) $(COBJS)
endif
ifneq ($(strip $(CPPOBJS)),)
    $(AR) -rv $(OUTPUT_FILE_PATH) $(CPPOBJS)
endif