I'm receiving the undefined symbols error on XC8 for two struct arrays declared as externs in file io.h. Why is this happening?

    #ifndef _IO_H_
    #define _IO_H_

#include <pic16f872.h>
#include <string.h>
#include "../var.h"

#define DEBOUNCE_LOW        50000
#define DEBOUNCE_HIGH       50000
#define DEBOUNCE_HOLD       4000000

#define TOTAL_INPUTS        3

typedef struct {
   unsigned char press : 1;
    unsigned char hold  : 1;        
} Input;

typedef struct {
    unsigned int low;
    unsigned int high;  
    unsigned long hold;
} Debounce;

extern Input input[TOTAL_INPUTS];   //<== The variables declaration
extern Debounce debounce[TOTAL_INPUTS];  // <==

#define BT_UP           input[0]
#define BT_DOWN         input[1]

#define BT_UP_PIN       PORTCbits.RC1
#define BT_DOWN_PIN     PORTCbits.RC3

#define LED1            PORTBbits.RB1
#define LED2            PORTBbits.RB2

void setupIo( void );
void initIo( void );
void resetIo( char input );
void taskIo( void );
void readIo( void );
void writeIo( void );

#endif // _IO_H_

and the io.c:

  #include "io.h";

void initIo( void ){
    for( int in = 0; in < TOTAL_INPUTS; in++ ){        
        input[in].hold = false;
        input[in].press = false;
        resetIo( in );

void resetIo( unsigned char input){ debounce[input].low = DEBOUNCE_LOW; debounce[input].high = DEBOUNCE_HIGH; debounce[input].hold = DEBOUNCE_HOLD; }

void taskIo( void ){

if( !BT_UP_PIN ){  //botão up pressionado

    if( debounce[0].low > 0) debounce[0].low--;
    if( !debounce[0].low ){

        if( debounce[0].hold > 0 ) debounce[0].hold--;            
        if( !debounce[0].hold){                
            input[0].hold = true;
} else if( !debounce[0].low ){ // botão solto

    if( debounce[0].high > 0) debounce[0].high--;

    if( !debounce[0].high ){
        input[0].press = true;
        resetIo( 0 );            

if( !BT_DOWN_PIN ){  //botão up pressionado

    if( debounce[1].low > 0) debounce[1].low--;
    if( !debounce[1].low ){

        if( debounce[0].hold > 0 ) debounce[0].hold--;           
        if( !debounce[1].hold){                
            input[1].hold = true;
} else if( !debounce[1].low ){ // botão solto

    if( debounce[1].high > 0) debounce[1].high--;

    if( !debounce[1].high ){
        input[1].press = true;
        resetIo( 1 );            


compiler error:

    CLEAN SUCCESSFUL (total time: 125ms)
make -f nbproject/Makefile-default.mk SUBPROJECTS= .build-conf
make1: Entering directory 'C:/Users/User/Google Drive/Desenvolvimento/Projetos/Microchip/Fonte Chaveada/FonteChaveada.X'
make  -f nbproject/Makefile-default.mk dist/default/production/FonteChaveada.X.production.hex
make2: Entering directory 'C:/Users/User/Google Drive/Desenvolvimento/Projetos/Microchip/Fonte Chaveada/FonteChaveada.X'
"C:\Program Files (x86)\Microchip\xc8\v1.41\bin\xc8.exe" --pass1  --chip=16F872 -Q -G  --double=24 --float=24 --opt=+asm,+asmfile,-speed,+space,-debug,-local --addrqual=ignore --mode=free -P -N255 --warn=0 --asmlist -DXPRJ_default=default  --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,+osccal,-resetbits,-download,-stackcall,+clib   --output=-mcof,+elf:multilocs --stack=compiled:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -obuild/default/production/main.p1  main.c 
"C:\Program Files (x86)\Microchip\xc8\v1.41\bin\xc8.exe" --pass1  --chip=16F872 -Q -G  --double=24 --float=24 --opt=+asm,+asmfile,-speed,+space,-debug,-local --addrqual=ignore --mode=free -P -N255 --warn=0 --asmlist -DXPRJ_default=default  --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,+osccal,-resetbits,-download,-stackcall,+clib   --output=-mcof,+elf:multilocs --stack=compiled:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"    -obuild/default/production/drivers/io/io.p1  drivers/io/io.c 
hw_config.h:22: warning: (162) #warning: "Sistema configurado como DEBUG!"
"C:\Program Files (x86)\Microchip\xc8\v1.41\bin\xc8.exe"  --chip=16F872 -G -mdist/default/production/FonteChaveada.X.production.map  --double=24 --float=24 --opt=+asm,+asmfile,-speed,+space,-debug,-local --addrqual=ignore --mode=free -P -N255 --warn=0 --asmlist -DXPRJ_default=default  --summary=default,-psect,-class,+mem,-hex,-file --output=default,-inhx032 --runtime=default,+clear,+init,-keep,-no_startup,+osccal,-resetbits,-download,-stackcall,+clib --output=-mcof,+elf:multilocs --stack=compiled:auto:auto "--errformat=%f:%l: error: (%n) %s" "--warnformat=%f:%l: warning: (%n) %s" "--msgformat=%f:%l: advisory: (%n) %s"      --memorysummary dist/default/production/memoryfile.xml -odist/default/production/FonteChaveada.X.production.elf  build/default/production/main.p1 build/default/production/drivers/io/io.p1
Microchip MPLAB XC8 C Compiler (Free Mode) V1.41 Build date: Jan 24 2017 Part Support Version: 1.41 Copyright (C) 2017 Microchip Technology Inc. License type: Node Configuration

:: warning: (1273) Omniscient Code Generation not available in Free mode main.c:88: warning: (764) mismatched comparison :0: error: (500) undefined symbols: _debounce(dist/default/production\FonteChaveada.X.production.obj) _input(dist/default/production\FonteChaveada.X.production.obj) (908) exit status = 1 nbproject/Makefile-default.mk:141: recipe for target 'dist/default/production/FonteChaveada.X.production.hex' failed make2: Leaving directory 'C:/Users/User/Google Drive/Desenvolvimento/Projetos/Microchip/Fonte Chaveada/FonteChaveada.X' nbproject/Makefile-default.mk:84: recipe for target '.build-conf' failed make1: Leaving directory 'C:/Users/User/Google Drive/Desenvolvimento/Projetos/Microchip/Fonte Chaveada/FonteChaveada.X' nbproject/Makefile-impl.mk:39: recipe for target '.build-impl' failed make2: * [dist/default/production/FonteChaveada.X.production.hex] Error 1 make1: * [.build-conf] Error 2 make: *** [.build-impl] Error 2

BUILD FAILED (exit value 2, total time: 1s)

and my main.c file as well:

#include "hw_config.h";

/=====================================================================================\ ======= INTERRUPÇÔES ========= *=====================================================================================*/

void interrupt interruptFuction( void ){ if( INTCONbits.T0IF ){ INTCONbits.T0IF = 0;


if( PIR1bits.TMR2IF ){
    PIR1bits.TMR2IF = 0;



void main( void ){

int pwm = 0;


while( true ){
    LED1 = ~LED1;


    if( BT_UP.press ){  // input.press
        if( pwm < PWM_MAX ) pwm++;
        CCPR1L = (char) pwm;
        CCPR1H = pwm >> 8;
        LED2 = ~LED2;

    if( BT_DOWN.press ){
        if( pwm >= 1 ) pwm--;
        CCPR1L = (char) pwm;
        CCPR1H = pwm >> 8;
        LED2 = ~LED2;

} //end while

} //end main

void initHw( void ){

/=====================================================================================\ ======= SETUP SFFRs ========= *=====================================================================================/ ADCON0 = 0b00000000; // Desalibilita pull-ups ou ADC não lembro ADCON1 = 0b00000111; OPTION_REG = 0b10000011; INTCON = 0b10100000; //Habilita interrupções // T1CON = 0b10000000; //Habilita e configura Timer 1 PIE1 = 0b00000110; // Habilita CCPIE e TMR2IE inerrupts para PWM T2CON = 0b00000100; //Habilita e configura Timer 2 (1:1) PR2 = 5; / Para PWM é utilizável somente o preScaler (bits 1-0): * 00= 1:1; * 01=1:4; * 1x=1:16; */ CCP1CON = 0b00001111; //Habilita PWM
CCPR1H = 0b0000000; //Ciclo alto do Duty do PWM CCPR1L = 0b00000000; //Ciclo baixo do Duty do PWM

 *      Limpeza dos SFRs.
TMR0 = 0;
TMR2 = 0;

 *      Limpeza dos PORTS e LATS.
PORTA = 0;
PORTB = 0;
PORTC = 0;

 *      Configuração da direção dos pinos de I/O's.
//        76543210
TRISA = 0b11111111; //entrada
TRISB = 0b11111001; //saída
TRISC = 0b00001010; //saída


I've tried to mark de Xc8 Linker option buts its not enabled for this device.

Project Properties

enter image description here

  • 1
    \$\begingroup\$ Please fix the code formatting, otherwise some characters might be missing and we can't tell if it is relevant to your problem! \$\endgroup\$ Feb 3 '17 at 0:58
  • 1
    \$\begingroup\$ Seems the compiler cannot find the arrays debounce[] and input[]. Where are these defined? \$\endgroup\$ Feb 3 '17 at 1:30
  • \$\begingroup\$ Sorry about the formating, i'm trying to fix. the arrays are declareted in io.h as extern Structs arrays. So hw_config.h import the io.h and then my file main.c import the hw_config.h. \$\endgroup\$
    – Henrique
    Feb 3 '17 at 10:36
  • 2
    \$\begingroup\$ Declaring a var as extern tells the compiler "Hey, these variables exist somewhere, dont worry about where they are located". When its time for the linker to run, it sees this extern flag and says "Ok, which one of you has the actual variable so I can give it to the rest of the people who asked for it". If nobody has the actual instantiation, you get this error. \$\endgroup\$
    – gregb212
    Feb 3 '17 at 17:00

There's a difference between declaring a variable and defining it. You've declared that debounce[] and input[] exist somewhere else by using the extern keyword, but you've not actually defined them anywhere (at least that we can see from the code provided).

To simply fix the error, you can define the arrays in your io.c file. But as far as I can tell, debounce[] and input[] are not used anywhere else in your program, so there's no need to expose them in the header file (i.e. define them in the io.c file and remove the extern declarations from the io.h file).


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.