I refactor some C code and I try to compile it as a lib on clang on mac instead of gcc on linux.
First of all if I just run make command I got an error at the first file compile:
+++ Compiling [sys_msg.c]
clang: error: unsupported argument '-adhlns=../../src/sys_msg.lst' to option 'Wa,'
So I remove the -Wa,-adhlns=$(<:.c=.lst) option that create this error.
After that everything seems to compile but the assembly of the last .a file fail, and I don't understand why.
Here is my make output :
+++ 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
Here is my 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:
Why clang raise me this?
Thank's to @MadScientist I understand why I have this error, if I print things on my make I got :
$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
---------------------------------------------------------------------------------------
My mistake come for the for this part of my makefile :
PROJ_ASRCS = $(filter %.s,$(foreach file,$(SOURCES),$(file)))
PROJ_ASRCS += $(filter %.S,$(foreach file,$(SOURCES),$(file)))
I don't want to include all .o because I do multiple compilation, I just want to list the needed files.
I have the same compilation process than ExperimentalCore-sam project.
How can I do that?
I can only assume that the variable AOBJS is empty. Following back along where it's created, I can only assume that means that there are no .s or .S files listed in your SOURCES variable.
Why don't you run a single invocation of $(AR) and just use the $^ automatic variable and filter out .o files, rather than three different invocations of the $(AR) command?
$(AR) -rv $(OUTPUT_FILE_PATH) $(filter %.o,$^)
EDIT To be clear I'm suggesting you change your output target rule to this:
$(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
Or, if you wanted to be more idiomatically correct:
$(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
As above I'd definitely remove $(OBJ_PATH) from the prerequisites list.
I understand the difference between GCC and Clang.
With GCC if you run an ar command with no archive members specified, he just skip the step.
Clang raise an error in this case and stop the build.
To patch it I just check if my list is empty or not :
$(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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With