Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linker: Undefined Reference for const C structs which are located in static lib

Tags:

c

I've following problem:

Header File "can_settings.h":

#ifndef CAN_SETTINGS_H_
#define CAN_SETTINGS_H_

#ifdef __cplusplus
extern "C" {
#endif

#include "can.h"

extern const CAN_InitTypeDef can_initstruct;

extern const CAN_FilterInitTypeDef can_filter_acceptall;
extern CAN_FilterInitTypeDef can_filter_1;
extern CAN_FilterInitTypeDef can_filter_2;


#ifdef __cplusplus
}
#endif

#endif

Source File "can_settings.c":

#include "can_settings.h"

const CAN_InitTypeDef can_initstruct = {
#ifdef SYSCLK_FREQ_72MHz
    // APB1_freq = 36 MHz
    /* .CAN_Prescaler = */ 24,
    /* .CAN_Mode = */ CAN_Mode_Normal,
    /* .CAN_SJW = */ CAN_SJW_1tq,
    /* .CAN_BS1 = */ CAN_BS1_8tq,
    /* .CAN_BS2 = */ CAN_BS2_3tq,
#elif defined SYSCLK_FREQ_24MHz
    // APB1_freq = 24 MHz
    /* .CAN_Prescaler = */ 16,
    /* .CAN_Mode = */ CAN_Mode_Normal,
    /* .CAN_SJW = */ CAN_SJW_1tq,
    /* .CAN_BS1 = */ CAN_BS1_8tq,
    /* .CAN_BS2 = */ CAN_BS2_3tq,
#endif
    /* .CAN_TTCM = */ DISABLE,
    /* .CAN_ABOM = */ DISABLE,
    /* .CAN_AWUM = */ DISABLE,
    /* .CAN_NART = */ DISABLE,
    /* .CAN_RFLM = */ DISABLE,
    /* .CAN_TXFP = */ ENABLE,
};

const CAN_FilterInitTypeDef can_filter_acceptall = {
    /* .CAN_FilterIdHigh = */ 0x0000,
    /* .CAN_FilterIdLow = */ 0x0000,
    /* .CAN_FilterMaskIdHigh = */ 0x0000,
    /* .CAN_FilterMaskIdLow = */ 0x0000,
    /* .CAN_FilterFIFOAssignment = */ 0,
    /* .CAN_FilterNumber = */ 0,
    /* .CAN_FilterMode = */ CAN_FilterMode_IdMask,
    /* .CAN_FilterScale = */ CAN_FilterScale_32bit,
    /* .CAN_FilterActivation = */ ENABLE
};

const CAN_FilterInitTypeDef can_filter_1 = {
        /* .CAN_FilterIdHigh = */ 0x0000,
        /* .CAN_FilterIdLow = */ CAN_ID_EXT,
        /* .CAN_FilterMaskIdHigh = */ 0x14FC << 3,
        /* .CAN_FilterMaskIdLow = */ CAN_ID_EXT,
        /* .CAN_FilterFIFOAssignment = */ 0,
        /* .CAN_FilterNumber = */ 0,
        /* .CAN_FilterMode = */ CAN_FilterMode_IdMask,
        /* .CAN_FilterScale = */ CAN_FilterScale_32bit,
        /* .CAN_FilterActivation = */ ENABLE
};

const CAN_FilterInitTypeDef can_filter_2 = {
        /* .CAN_FilterIdHigh = */ 0x0000,
        /* .CAN_FilterIdLow = */ CAN_ID_EXT,
        /* .CAN_FilterMaskIdHigh = */ 0x1400 << 3,
        /* .CAN_FilterMaskIdLow = */ CAN_ID_EXT,
        /* .CAN_FilterFIFOAssignment = */ 0,
        /* .CAN_FilterNumber = */ 1,
        /* .CAN_FilterMode = */ CAN_FilterMode_IdMask,
        /* .CAN_FilterScale = */ CAN_FilterScale_32bit,
        /* .CAN_FilterActivation = */ ENABLE
};

The linker returns undefined reference to 'can_initstruct' can_filter_acceptall' 'can_filter_1' 'can_filter_2'... The files can_settings.{c, h} are built as a static library and are used in my main application(only C) and in my CAN low level driver (C++). All static libraries are built before my low level drivers and main application have been built. With objdump I dumped the static CAN settings library and all the above structs are listed in the .rodata section as it should be. What I'm doing wrong...?

like image 275
arge Avatar asked Dec 03 '25 01:12

arge


1 Answers

If you're using GCC, be sure that you specify the libraries in the correct order. See Why does the order in which libraries are linked sometimes cause errors in GCC? for a detailed description.

However, if you don't want to bother with the library sequence, simply specify the sequence twice instead of just one time. Applied on the accepted answer of the above question, this would mean:

gcc prog.o libA.a libB.a libA.a libB.a -o prog.x

As an alternative, use the -Wl,--start-group ... -Wl,--end-group flags of GCC (GCC: what are the --start-group and --end-group command line options?).

like image 91
eckes Avatar answered Dec 05 '25 15:12

eckes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!