Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Makefile results in multiple definition errors

I have the following Makefile:

TARGET = main.elf
BUILD_DIR = build
SRC_DIR = src

CC = arm-none-eabi-gcc -std=gnu17
CXX = arm-none-eabi-g++ -std=c++17 
LINKER = arm-none-eabi-g++
OBJDUMP = arm-none-eabi-objdump
OBJCOPY = arm-none-eabi-objcopy

INCLUDES = -I./src/inc \
           -I./src/usys/inc

SRC_FILES_C =   $(SRC_DIR)/usys/startup.c \
                $(SRC_DIR)/usys/usys.c

SRC_FILES_CXX = $(SRC_DIR)/main.cpp

LINKER_FILE = $(SRC_DIR)/usys/flash.ld

CFLAGS = -Wall -Wextra -g3 -O0
CFLAGS += -c -mthumb -fdata-sections -ffunction-sections -DARM
CFLAGS += -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard --specs=nano.specs

LFLAGS = -mcpu=cortex-m33 --specs=nosys.specs --specs=nano.specs
LFLAGS += -T$(LINKER_FILE) -Wl,-Map="$(TARGET).map" -Wl,--gc-sections -static
LFLAGS += -mfpu=fpv5-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -lstdc++ -lsupc++ -Wl,--end-group

C_OBJS = ${subst $(SRC_DIR),$(BUILD_DIR),$(SRC_FILES_C:.c=.o)}
CXX_OBJS = ${subst $(SRC_DIR),$(BUILD_DIR),$(SRC_FILES_CXX:.cpp=.o)}

ALL_OBJS = $(CXX_OBJS) $(C_OBJS)

.PHONY: clean

all: $(TARGET)

# Compile
$(C_OBJS): $(SRC_FILES_C)
    $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@

$(CXX_OBJS): $(SRC_FILES_CXX)
    $(CXX) $(INCLUDES) $(CFLAGS) -c $< -o $@

# Link
$(TARGET): $(ALL_OBJS)
    $(CXX) $(LFLAGS) $(ALL_OBJS) -o $@

# Clean
clean:
    @rm -f $(ALL_OBJS) $(TARGET)

My source directly roughly looks like this:

├───build
│   └───usys
├───src
|   main.cpp
│   └───usys
|       startup.c
|       usys.c
│       └───inc
└───tools

When I compile my program, I get multiple definition errors when linking. Which makes sense, because during compilation, I see the following:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

arm-none-eabi-gcc -std=gnu17 -I./src/inc -I./src/usys/inc -Wall
-Wextra -g3 -O0 -c -mthumb -fdata-sections -ffunction-sections -DARM -mcpu=cortex-m33 -mfpu=fpv5-sp-d16 -mfloat-abi=hard –specs=nano.specs -c src/usys/startup.c -o build/usys/usys.o

How can I modify my Makefile so that it does what I want: take the list of $(SRC_FILES_C), and creates the objects in the output at $(C_OBJS)?

>Solution :

Here’s the problem:

$(C_OBJS): $(SRC_FILES_C)
    $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@

$(SRC_FILES_C) expands to a list of all the source files, and $< subsequently takes the first of these, which is src/usys/startup.c. This file is used as the input for each object file.

Instead, you’re looking for a pattern rule. A pattern rule is only applied if all prerequisites already exist or can be made (maked). Thanks to this, you can use pattern rules for both .c and .cpp files:

$(BUILD_DIR)/%.o : $(SRC_DIR)/%.c
    $(CC) $(INCLUDES) $(CFLAGS) -c $< -o $@

$(BUILD_DIR)/%.o : $(SRC_DIR)/%.cpp
    $(CXX) $(INCLUDES) $(CFLAGS) -c $< -o $@
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading