Custom Files Multiple Definitions Issue

I added bms_module.c file modues folder and included in CMakeLists. Corresponding bms_events.c and bms_events.h files are placed in events folder. The project working well.

Then I added more files  bms.c and bms.h, serial.c and serial.h. The dependency graph is as :

bms_module.c -> bms.c and serial.c

bms.c-> serial.c

The some variables and functions declared in bms.h and serial.h are required in bms_module.c, while some variables and functions of serial.h are required in bms.c. I tried various methods to place these four files of (bms.c, bms.h, serial.c, serial.h) and declare in CMakeLists accordingly. I facing the issue of multiple definitions, as below.

1. What is rule to place files in zephyr ? 

2. Why including .h file only in multiple files causes multiple definitions error while theoretically declaration in C can be as many times but definition only in one file. I following this rule, even then the error occurs.

3. If the variables of a .h file are used in multiple .c files, how zephyr handles that ? Zephyr creates .obj file for each .c file. So, multiple definitions appear  in  ore than one .obj file ? How to handle this situation ?

c:/firmware/firmware/toolchain/opt/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: app/libapp.a(bms_module.c.obj):C:\firmware\firmware\firmware\src\modules\bms\bms.h:36: multiple definition of `max_mv_cell'; app/libapp.a(bms.c.obj):C:\firmware\firmware\firmware\src\modules\bms\bms.h:36: first defined here
c:/firmware/firmware/toolchain/opt/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: app/libapp.a(bms_module.c.obj):C:\firmware\firmware\firmware\src\modules\bms\bms.h:34: multiple definition of `current_msg'; app/libapp.a(bms.c.obj):C:\firmware\firmware\firmware\src\modules\bms\bms.h:34: first defined here
c:/firmware/firmware/toolchain/opt/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: app/libapp.a(bms_module.c.obj):C:\firmware\firmware\firmware\src\modules\bms\bms.h:33: multiple definition of `soc_msg'; app/libapp.a(bms.c.obj):C:\firmware\firmware\firmware\src\modules\bms\bms.h:33: first defined here
c:/firmware/firmware/toolchain/opt/bin/../lib/gcc/arm-none-eabi/9.2.1/../../../../arm-none-eabi/bin/ld.exe: app/libapp.a(bms_module.c.obj):C:\firmware\firmware\firmware\src\modules\bms\bms.h:32: multiple definition of `packv_msg'; app/libapp.a(bms.c.obj):C:\firmware\firmware\firmware\src\modules\bms\bms.h:32: first defined here

              

  • Hi Gulzar

    1. What is rule to place files in zephyr ? 

    Zephyr uses the GCC compiler under the hood, so there are no particular rules to file placement, compilation, linkage and so on other than those imposed by the GCC compiler. 

    As long as you configure the CMakeLists.txt file correctly you can place files wherever you want. 

    2. Why including .h file only in multiple files causes multiple definitions error while theoretically declaration in C can be as many times but definition only in one file. I following this rule, even then the error occurs.

    3. If the variables of a .h file are used in multiple .c files, how zephyr handles that ? Zephyr creates .obj file for each .c file. So, multiple definitions appear  in  ore than one .obj file ? How to handle this situation ?

    In order to share a variable between multiple files you need to use the extern keyword. 

    In one header file you need to declare the variable like this:

    extern int shared_variable;

    Then in a single C file you need to define the variable in the normal way:

    int shared_variable = 0;

    And then this variable can also be accessed from any C file that includes the header file, where the extern definition can be found. 

    If you still can't make it work maybe you can share the files with me, and I will have a look at them?

    Best regards
    Torbjørn

  • I need to access following variables in other files declared in one .h file ? I tried by copy and paste all this and extern before these. But, warning {useless variable space ....} is shown for some. There is one static const struct also to be globally accessible.  It shows multiple storage classes error for static device ... see the attached image.

    uint8_t bms_double_buffer[2][CONFIG_BMS_UART_BUF_SIZE];
    uint8_t *bms_buf_next = bms_double_buffer[1];
    
    K_SEM_DEFINE(bms_tx_done, 1, 1);
    K_SEM_DEFINE(bms_rx_disabled, 0, 1);
    
    static const struct device *bms_uart;
    
    struct bms_msg_queue_item {
    	uint8_t bytes[CONFIG_BMS_UART_BUF_SIZE];
    	uint8_t length;
    };
    
    struct bms_msg_queue_item bms_incoming_message;
    
    // UART TX fifo
    RING_BUF_DECLARE(bms_tx_fifo, CONFIG_BMS_UART_TX_BUF_SIZE);
    
    // UART RX message queue
    K_MSGQ_DEFINE(bms_rx_msgq, sizeof(struct bms_msg_queue_item), CONFIG_BMS_UART_RX_MSG_QUEUE_SIZE, 2);

Related