Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

clang makefile "ar: no archive members specified"

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?

like image 858
Nicolas Rabault Avatar asked Dec 07 '25 11:12

Nicolas Rabault


2 Answers

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.

like image 122
MadScientist Avatar answered Dec 10 '25 01:12

MadScientist


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
like image 40
Nicolas Rabault Avatar answered Dec 10 '25 01:12

Nicolas Rabault