2017-02-14 58 views
0

我重构了一些C代码,我尝试将它编译为mac上的clang而不是linux上的gcc。铿锵makefile“ar:没有指定存档成员”

首先,如果我只是运行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 [email protected] 

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

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

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

#|---------------------------------------------------------------------------------------| 
#| Output folder                   | 
#|---------------------------------------------------------------------------------------| 
$(OBJ_PATH): 
    @echo +++ Creation of [[email protected]] 
    @-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 [email protected]).o -o [email protected] 

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

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

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

#|---------------------------------------------------------------------------------------| 
#| 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: 

为什么铛鼓舞了我呢?


感谢对@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 
--------------------------------------------------------------------------------------- 

我的错误来为我的生成文件的这一部分:

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

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

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

我该怎么做?

+0

您的循环'$(的foreach文件,$(源),$(文件))'没有做任何事情;你正在循环查看'SOURCES'中的每个单词,并且每个单词都将其展开为该单词......这是一种非常耗费资源的方式来恢复原始列表。除非你试图做一些非常棘手的双重评估事情。 – MadScientist

+0

是的,这是因为我用不同的文件版本编译不同的lib。我不想包含所有对象。我使用与此项目相同的构建系统:[ExperimentalCore-sam](https://github.com/aethaniel/ExperimentalCore-sam) –

+0

对不起,但我不理解您的评论或与我的相关内容。我只是说'$(foreach file,$(SOURCES),$(file))'不过是编写'$(SOURCES)'的非常低效的方式。你会得到相同的结果。您循环访问'$(SOURCES)'的值,并为列表中的每个元素获取相同的元素。 – MadScientist

回答

1

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

你为什么不跑的$(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 [email protected] $(filter %.o,$^) 
     $(NM) [email protected] > $(HAL_PATH)/$(OUTPUT_NAME)_symbols.txt 

与上面一样,我一定会从必备项列表中删除$(OBJ_PATH)

+0

我这样做是因为我不想在这个库中包含所有'.o',所以SOURCES列表中确实没有包含任何.s或.S。 –

+0

如果SOURCES列表中不包含任何'.s'或'.S'文件,那么'AOBJS'的值将是空的(因为我们发现:这就是导致原始问题的原因),所以'$( AOBJS)'在先决条件列表中将是空的,所以'$ ^'自动变量的值将不包含任何对象。我的改变给你以前的行为。 – MadScientist

1

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

使用GCC如果您运行的ar命令没有指定存档成员,他只是跳过这一步。 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 
+0

我真的不明白为什么你不想在下面使用我建议的解决方案。它更简单,更高效,因为你只调用一次'ar'而不是三次。 – MadScientist

+0

你的建议是更通用的建议,但在我的情况下,我必须选择我的档案成员。我每次都用不同的输入文件多次运行这个makefile。我不想在此存档中添加冲突的二进制文件。 –

+0

看到我上面的评论。你的makefile在任何情况下的行为都与我的行为相同。 – MadScientist