Search code examples
cheader-filesmplabxc8

Symbol "file@variable" defined more than once


IDE: MPLAB X v2.15

CC: XC8 v1.32

Target device: PIC18f45k20

I have a header file reg.h, which contains a variable

static const int aaasdf = 3;

That header has proper include guards at the beginning:

#ifndef PRJ_REG_H
#define PRJ_REG_H

And at the end:

#endif

If I have that same variable on any other header file, it compiles fine, but when that variable is in this particular file, it gives me error: (845) symbol "reg@aaasdf" defined more than once

But if I comment that variable, it doesn't exist anymore, and it complains because I need it in some .c file.

The strange name is just for testing, to be sure that there isn't any other variable with the same name.

What else can I do to debug this?

EDIT:

It does it for any static const variable, (I'll test tomorrow for only static, const or extern const), that I create in that file, but there are also enums, and static inline functions, and none of them gives me the repeated symbol error.

EDIT:

I think it's the compiler that is broken:

I removed everything from the header and also the source files. Now main is an infinite loop, and all is like that.

The headers are empty but for the variable triggering the error.

No header of mine includes any other header of mine.

What triggers the error: Any header that is included in many source files, and contains a static const variable of any type. What I mean by many is that if I include the header only in its source file and another file, it doesn't trigger the error, but if it is included in 2 source files that aren't its source file, it triggers the error.

EDIT:

As requested, here is a MCV example of what I want (not the compile error):

// reg.h

enum    Reg_OSCCON_IRCF_Values {
    REG_OSCCON_IRCF_FREQ_31_KHZ = 0x0u,
    REG_OSCCON_IRCF_FREQ_250_KHZ    = 0x1u,
    REG_OSCCON_IRCF_FREQ_500_KHZ    = 0x2u,
    REG_OSCCON_IRCF_FREQ_1_MHZ  = 0x3u,
    REG_OSCCON_IRCF_FREQ_2_MHZ  = 0x4u,
    REG_OSCCON_IRCF_FREQ_4_MHZ  = 0x5u,
    REG_OSCCON_IRCF_FREQ_8_MHZ  = 0x6u,
    REG_OSCCON_IRCF_FREQ_16_MHZ = 0x7u
};
#define REG_OSCCON_IRCF_FREQ        ((const uint32_t [8]){      \
                           31000u,      \
                          250000u,      \
                          500000u,      \
                         1000000u,      \
                         2000000u,      \
                         4000000u,      \
                         8000000u,      \
                        16000000u       \
                    })

static inline   void reg_field_set(volatile uint8_t *reg,
                uint8_t mask, uint8_t posn, uint8_t val)
{

    *reg    = (*reg & ~mask) | ((val << posn) & mask);
}

static inline   void reg_OSCCON_IRCF_set(uint8_t val)
{

    reg_field_set(&OSCCON, _OSCCON_IRCF_MASK, _OSCCON_IRCF_POSN, val);
}

// pwm.c

#include "reg.h"
extern uint32_t sys_freq;

int foo(/**/)
{
    static const uint32_t   freq_min =
        REG_OSCCON_IRCF_FREQ[REG_OSCCON_IRCF_FREQ_16_MHZ] /
        (UINT8_MAX * 4 *
        REG_T2CON_T2CKPS_PRESCALER[REG_T2CON_T2CKPS_PRESCALER_1]);

    reg_OSCCON_IRCF_set(REG_OSCCON_IRCF_FREQ_16_MHZ);
    sys_freq    = REG_OSCCON_IRCF_FREQ[REG_OSCCON_IRCF_FREQ_16_MHZ];
    // ...
}

Option 1: As showed above, using a macro that expands to a const compound array literal, where I can access any of its elements (either at compile time or at run time). Need C99, which I don't have. EDIT: const compound literals may or may not be constant expressions (Initialize static variable with element of const compound literal), and therefore may or may not be valid as initializers for static variables.

Option 2: Changing the macro to a static const array. Pros: don't need C99. Cons: Can NOT initialize a static variable. The compiler seems broken and doesn't allow me to do that.

Option 3: Magic numbers. Pros: Don't need C99. Can initialize a static variable. Cons: Magic numbers.

Option 4: A lot of macros (for each of the arrays, because it's not only this one!). Pros: Don't need C99. Cons: Polluting global namespace.


Solution

  • Definitely the XC8 compiler is broken.

    Today similar errors appeared when using static inline functions. I've googled about it, and it seems the compiler isn't very good with that kind of code.