0

For a minimal reproducible example of this problem, please go to this link.

I'm working on a stm32 project that is initialized using stm32cubemx(Makefile) and I'm using vscode as ide.

Until now I had a single main.c file with main() function in it and everything was ok.

I have two separate boards in my project and I decided to create two source files (master.c and slave.c) with specific main() functions in them and deleted the main.c file. Also I added two targets (master and slave) to my Makefile (which is created by cubemx) so that I can choose which files to compile and flash to each board. The C_SOURCES variable was defined by cumbemx:

# C sources
C_SOURCES =  \
Src/gpio.c \
Src/crc.c \
Src/i2c.c \
Src/usart.c \
Src/stm32f1xx_it.c \
Src/stm32f1xx_hal_msp.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_crc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c \
Src/system_stm32f1xx.c \
Src/tim.c \
Src/fxos.c

I added MASTER_SOURCES variable and copied all the sources above plus master.c in it:

MASTER_SOURCES = \
Src/master.c \
Src/gpio.c \
Src/crc.c \
Src/i2c.c \
Src/usart.c \
Src/stm32f1xx_it.c \
Src/stm32f1xx_hal_msp.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_crc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c \
Src/system_stm32f1xx.c \
Src/tim.c \
Src/fxos.c
TARGET = my-initial-target
MASTER = master
SLAVE = slave

and down below I defined the targets for each board as follows:

all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).bin

master: $(BUILD_DIR)/$(MASTER).elf $(BUILD_DIR)/$(MASTER).hex $(BUILD_DIR)/$(MASTER).hex
slave: $(BUILD_DIR)/$(SLAVE).elf $(BUILD_DIR)/$(SLAVE).hex $(BUILD_DIR)/$(SLAVE).hex

and also defined MASTER_OBJ using auto-created OBJECTS variable as a sample:

OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))

MASTER_OBJ = $(addprefix $(BUILD_DIR)/,$(notdir $(MASTER_SOURCES:.c=.o))) 
vpath %.c $(sort $(dir $(MASTER_SOURCES)))

MASTER_OBJ += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))


$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR) 
    $(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@

$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
    $(AS) -c $(CFLAGS) $< -o $@

$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
    $(CC) $(OBJECTS) $(LDFLAGS) -o $@
    $(SZ) $@

$(BUILD_DIR)/$(MASTER).elf: $(MASTER_OBJ) Makefile
    $(CC) $(MASTER_OBJ) $(LDFLAGS) -o $@
    $(SZ) $@

$(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
    $(HEX) $< $@
    
$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR)
    $(BIN) $< $@    
    
$(BUILD_DIR):
    mkdir $@        

But after I run make master or in terminal, I get several multiple definition errors like this:

/usr/lib/gcc/arm-none-eabi/11.2.0/../../../../arm-none-eabi/bin/ld: build/master.elf: in function `_sbss':
/home/mehdi/coding/mag-dual-interface/Src/master.c:132: multiple definition of `drdyFlag'; /tmp/ccnS08MO.o:/home/mehdi/coding/mag-dual-interface/Src/master.c:132: first defined here

the drdyFlag variable is defined in the master.c file which has replaced the initial main.c. this error is repeated nearly for every function and variable declared and defined in master.c. If I add extern to function declarations (although I have not declared or defined them in any other source file), the above error for functions is resolved, but it has no effect in variables. All the header files have include guards and no .c files are included anywhere.

So can someone please tell me what am I doing wrong here?

mehdi
  • 167
  • 11
  • 2
    Please [edit] your question and explain what files the targets `all`, `master` and `slave` are supposed to generate. It is not a good idea to modify a generated `Makefile`. If you generate it again you will probably lose your changes. To debug your `Makefile`, I suggest to add some rule that prints the variables, e.g. `$(OBJECTS)`, `$(MASTER_OBJ)` etc. Did you notice the space in ```make: *** No rule to make target ` build/master.o'```...? What's the purpose of `\ ` in `MASTER_OBJ = $(OBJECTS) \ $(addprefix`...? – Bodo Apr 07 '22 at 11:48
  • You didn't mention it, but as part of your changes, did you happen to create that `Src/` directory in which your new files appear? Because no, the rule you present for `$(BUILD_DIR)/%.o` *will not* build objects from sources in a subdirectory of the working directory. – John Bollinger Apr 07 '22 at 15:49
  • @Bodo the target all is created by cubemx and generates the .elf, .bin and .hex files with the name of the project. the master and slave targets are added by me and are supposed to generate the same three files by their respective name. If I can get this edited makefile to work I can replace it in the next code generations. and about the \ my intention was to append the master.c to the default objects defined by cubemx. but I don't think it's right and honestly I don't know why I put it there. please read the edited question for the follow up. – mehdi Apr 07 '22 at 21:20
  • @JohnBollinger the Src/ directory was created by cubemx and all the .c files (e.g. usart.c, i2c.c, gpio.c and etc) are in it. I added the master.c and slave.c to the same directory. the $(BUILD_DIR)/%.o rule is also generated by cubemx and was working fine with the initial main.c file. – mehdi Apr 07 '22 at 21:23
  • @mehdi, the rule in question is correct for building sources from directory `Src/` only if `make` is run with `Src/` as its working directory. It is not out of the question that that happens -- for instance, if recursive `make` is being engaged -- but in that case there are too many missing pieces. We cannot answer the question authoritatively without a [mre]. – John Bollinger Apr 07 '22 at 21:51
  • @JohnBollinger I changed some lines in makefile and got new errors. would you please take a look? if it's not clear I will create a repex and post it. – mehdi Apr 07 '22 at 22:03
  • It looks like you are now linking some of the same `.o` files twice, but it's not clear to me why. – John Bollinger Apr 08 '22 at 02:03
  • @mehdi Please add requested information, clarification or explanation to your question instead of using comments for this purpose. Without seeing a complete (minimalized) `Makefile` and a list of the files it is impossible to know what `make` will do. Please always show the command that prints the error message. As I already suggested: Add rules that will show you the values of the variables, e.g. `help:` `echo MASTER_OBJ = $(MASTER_OBJ)` – Bodo Apr 08 '22 at 09:18
  • Please don't ask a long trail of subsequent questions in a single question. After you get an answer to the first question, if you have more questions then ask a new question. Remember asking SO is the **last** resort, not the _first_ resort: first try to solve it yourself. For linking problems _look carefully_ at the link line that make prints out. The problem is very likely there. Are there multiple copies of the same file? Is the `foo.c` and `foo.o` both in the link line? etc. If you really can't figure it out put the link line in your question not just the errors. – MadScientist Apr 08 '22 at 14:42
  • I added a minimal reproducible example in a new question. https://stackoverflow.com/q/71799906/9439683 – mehdi Apr 08 '22 at 15:51
  • Please keep everything together in the same question, @mehdi. If that makes the question too complicated then the question is too complicated. The solution then is to ask a simpler question, or perhaps multiple *separate and independent* questions. I'm now going to close this one as a dupe of the new one. – John Bollinger Apr 08 '22 at 21:58

0 Answers0