cancel
Showing results for 
Search instead for 
Did you mean: 

Best way to handle multiple definition errors (project structure or variable declaration)?

JayDev
Senior II

Hello!

I have a project I setup that I'm getting multiple definition issues with and I'm not 100% sure if it's because of they way I structured it or if it's because of the way I declared it.

Variable Declaration (since this will be easier to read and more straight forward):

I tried pasting the following code into my sensor1.h file:

const float mlx90393_lsb_lookup[8][4][2] =
 
{
 
 /* 5x gain */
 
 {{0.805, 1.468}, {1.610, 2.936}, {3.220, 5.872}, {6.440, 11.744}},
 
 /* 4x gain */
 
 {{0.644, 1.174}, {1.288, 2.349}, {2.576, 4.698}, {5.152, 9.395}},
 
 /* 3x gain */
 
 {{0.483, 0.881}, {0.966, 1.762}, {1.932, 3.523}, {3.864, 7.046}},
 
 /* 2.5x gain */
 
 {{0.403, 0.734}, {0.805, 1.468}, {1.610, 2.936}, {3.220, 5.872}},
 
 /* 2x gain */
 
 {{0.322, 0.587}, {0.644, 1.174}, {1.288, 2.349}, {2.576, 4.698}},
 
 /* 1.667x gain */
 
 {{0.268, 0.489}, {0.537, 0.979}, {1.073, 1.957}, {2.147, 3.915}},
 
 /* 1.333x gain */
 
 {{0.215, 0.391}, {0.429, 0.783}, {0.859, 1.566}, {1.717, 3.132}},
 
 /* 1x gain */
 
 {{0.161, 0.294}, {0.322, 0.587}, {0.644, 1.174}, {1.288, 2.349}}
 
};

The error I got was:

10:41:12 **** Incremental Build of configuration Debug for project Test_Project ****
 
make -j12 all 
 
arm-none-eabi-gcc "../Core/Src/sensor_main.c" -mcpu=cortex-m4 -std=gnu11 -g3 -DUSE_HAL_DRIVER -DDEBUG -DSTM32WB55xx -c -I../Drivers/CMSIS/Include -I../Core/Inc -I../Drivers/STM32WBxx_HAL_Driver/Inc -I../Drivers/STM32WBxx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32WBxx/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -MMD -MP -MF"Core/Src/ sensor_main.d" -MT"Core/Src/ sensor_main.o" --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -o "Core/Src/ sensor_main.o"
 
arm-none-eabi-gcc "../Core/Src/mlx90393.c" -mcpu=cortex-m4 -std=gnu11 -g3 -DUSE_HAL_DRIVER -DDEBUG -DSTM32WB55xx -c -I../Drivers/CMSIS/Include -I../Core/Inc -I../Drivers/STM32WBxx_HAL_Driver/Inc -I../Drivers/STM32WBxx_HAL_Driver/Inc/Legacy -I../Drivers/CMSIS/Device/ST/STM32WBxx/Include -O0 -ffunction-sections -fdata-sections -Wall -fstack-usage -MMD -MP -MF"Core/Src/mlx90393.d" -MT"Core/Src/mlx90393.o" --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -o "Core/Src/mlx90393.o"
 
arm-none-eabi-gcc -o "Test_Project.elf" @"objects.list"  -mcpu=cortex-m4 -T"C:\Users\ jay\STM32CubeIDE\workspace_1.3.0\Test_Project\STM32WB55RGVX_FLASH.ld" --specs=nosys.specs -Wl,-Map="Test_Project.map" -Wl,--gc-sections -static --specs=nano.specs -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Wl,--start-group -lc -lm -Wl,--end-group
 
Core/Src/mlx90393.o:C:/Users/jay/STM32CubeIDE/workspace_1.3.0/Test_Project/Debug/../Core/Inc/mlx90393.h:93: multiple definition of `mlx90393_lsb_lookup'
 
Core/Src/ sensor_main.o:C:/Users/ jay/STM32CubeIDE/workspace_1.3.0/Test_Project/Debug/../Core/Inc/mlx90393.h:93: first defined here
 
collect2.exe: error: ld returned 1 exit status
 
make: *** [makefile:44: Test_Project.elf] Error 1
 
"make -j12 all" terminated with exit code 2. Build might be incomplete.
 
 
 
10:41:14 Build Failed. 3 errors, 0 warnings. (took 1s.371ms)

I assume this is an issue with the way the project is structured (more detail below, but a lot more complicated). As a workaround, I can just declare the definition in the sensor1.c file but I wasn’t sure if that’s the best practice or if I need to change my file structure. Below is a detailed description of the issue.

Project Structure:

So, with the way STM32CubeIDE is setup, the peripheral initializations are done in main.c ( for example, static void MX_I2C1_Init(void) is initialized in main.c, along with all other IO initialization). The specific pin definitions are all in main.h.

I'm trying to structure my code so all our app specific code is OUTSIDE of main, so that means a lot of separate *.c and *.h files, one of each for each peripheral (ie mlx90393.c, mlx90393.h, etc).

Below is basically what the structure ends of looking like (as well as their includes)

main.h
 
#include “sensor_main.h�? //where it calls the main functionality
 
//Includes all peripheral location info
 
 
 
sensor_main.h
 
#include mlx90393.h // calls functions in mlx90393.h as well as other files
 
//Called from main.h, makes function calls to all peripherals
 
 
 
mlx90393
 
#include “main.h�? // needs peripheral info from main.h
 
// contains all sensor related functions

I think the core of the issue is that I have a sort of circular #include chain there, but I’m not entirely sure the best way to approach the issue. I could move the init commands from main.c, but that would mean it would stop syncing with the code generator (same with the peripherals from main.h, which I don’t want to do). 

Is there a recommended structure/way to reference these files from external code? Or should I just stick with the solution of variable declarations in the *.c file?

Thanks!

3 REPLIES 3

Put prototypes and externs in the .H, put the function bodies and initialized data in the .C

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
TDK
Guru

You should generally be using include guards or #pragma once to ensure an include file is only included once. If you have this, it eliminates the possibility of circular dependencies.

Unless a file is only included from a single compilation unit, I'd stick to having the definition in the .c files and the declaration in the .h.

If you feel a post has answered your question, please click "Accept as Solution".
prain
Senior III

Define mlx90393_lsb_lookup in your c file. Also use extern declaration of mlx90393_lsb_lookup in your h file. where you need to reference this variable, just include h file.