2017-02-14 16 views
0

Я реорганизую некоторый код C, и я пытаюсь скомпилировать его как lib на clang на mac вместо gcc на linux.clang 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 
--------------------------------------------------------------------------------------- 

Моя ошибка прийти к этой части моей Makefile:

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

Я не хочу включать все .o, потому что я делаю несколько компиляции, просто хочу перечислить необходимые файлы.

У меня такой же процесс компиляции, как у ExperimentalCore-sam проект.

Как я могу это сделать?

+0

Вашего цикла '$ (Еогеасп файл, $ (ИСТОЧНИКИ), $ (файл))' ничего не делает; вы говорите через каждое слово в «ИСТОЧНИКЕ», и каждый из них расширяет его до этого слова ... это очень ресурсоемкий способ вернуть исходный список. Если вы не пытаетесь сделать очень сложную двойную вещь. – MadScientist

+0

Да, это связано с тем, что я компилирую другую библиотеку с другой версией файлов. Я не хочу включать все объекты. Я использую ту же систему сборки, что и этот проект: [ExperimentalCore-sam] (https://github.com/aethaniel/ExperimentalCore-sam) –

+0

Извините, но я не понимаю ваш комментарий или что он имеет отношение к моему. Все, что я говорю, это то, что '$ (foreach file, $ (SOURCES), $ (файл)) - это не что иное, как очень неэффективный способ записи' $ (SOURCES) '. Вы получите те же результаты. Вы зацикливаете значение '$ (SOURCES)' и для каждого элемента в списке вы получаете тот же самый элемент. – MadScientist

ответ

1

Я могу только предположить, что переменная AOBJS пуста. После того, как он создан, я могу только предположить, что это означает, что нет .s или .S файлов, перечисленных в вашей переменной SOURCES.

Почему вы не запустить один вызов $(AR) и использовать только $^ автоматическую переменную и отфильтровать .o файлы, а не три различных инвокации команды $(AR)?

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

EDIT Чтобы быть ясно, что я предлагаю вам изменить ваш выход целевого правила к этому:

$(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

Я делаю это, потому что я не хочу включать в это lib все '.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

Смотрите мой комментарий выше. Ваш make-файл будет вести себя одинаково с моим во всех ситуациях. – MadScientist