<artificial>: undefined reference

Hello,

I’m a more or less unexperienced user regarding C/C++ and new to PIO (with VS Code, Win 10).
In my current project I wanted to reuse some libs, which I successfuly used years ago in a (mainly) non-Arduino environment. What I can’t manage to track down is the cause of this linker error:
<artificial>:(.text.startup+0x100): undefined reference to `lcd_init(unsigned char)’

My platformio.ini is:

[env:Mission Cyrus III]

platform = atmelavr
board = ATmega328P
framework = arduino

lib_ldf_mode = chain+
lib_deps = 
    libRK_utilities
    libRK_I2C-master
    libRK_PCF8574
    libRK_LCD_I2C
    Encoder
    libRK_RC5-IR-Remote
;;build_flags = 
;;    -v -v

The library sources are installed in the global storage. When building the project, I get

> Executing task: C:\Users\LeftBrain\.platformio\penv\Scripts\platformio.exe run <

Processing Mission Cyrus III (platform: atmelavr; board: ATmega328P; framework: arduino)

Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/atmelavr/ATmega328P.html
PLATFORM: Atmel AVR 2.0.0 > ATmega328P/PA
HARDWARE: ATMEGA328P 16MHz, 2KB RAM, 31.50KB Flash
PACKAGES:
 - framework-arduino-avr-minicore 2.0.3
 - toolchain-atmelavr 1.50400.190710 (5.4.0)      
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain+, Compatibility ~ soft
Found 14 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <libRK_utilities> 0.0.1-alpha #3ac5d22
|-- <libRK_I2C-master> 0.0.1-alpha #c759d58        
|-- <libRK_PCF8574> 0.0.1-alpha #149afb6
|   |-- <libRK_I2C-master> 0.0.1-alpha #c759d58    
|-- <libRK_LCD_I2C> 0.0.1-alpha #fee99e6
|   |-- <libRK_PCF8574> 0.0.1-alpha #149afb6       
|   |   |-- <libRK_I2C-master> 0.0.1-alpha #c759d58
|-- <Encoder> #4c4ec3a
|-- <libRK_RC5-IR-Remote> 0.0.1-alpha #e43375b     
Building in release mode
Compiling .pio\build\Mission Cyrus III\src\main.cpp.o
Compiling .pio\build\Mission Cyrus III\lib28d\libRK_utilities\libRK_utilities.c.o
Compiling .pio\build\Mission Cyrus III\lib195\libRK_I2C-master\libRK_I2C-master.c.o
Compiling .pio\build\Mission Cyrus III\lib55f\libRK_PCF8574\libRK_PCF8574.c.o
Archiving .pio\build\Mission Cyrus III\lib195\libRK_I2C-master.a
Archiving .pio\build\Mission Cyrus III\lib55f\libRK_PCF8574.a
Archiving .pio\build\Mission Cyrus III\lib28d\libRK_utilities.a
Compiling .pio\build\Mission Cyrus III\libc51\libRK_LCD_I2C\libRK_LCD_I2C.c.o
Compiling .pio\build\Mission Cyrus III\lib1cc\Encoder\Encoder.cpp.o
Compiling .pio\build\Mission Cyrus III\lib7bf\libRK_RC5-IR-Remote\libRK_RC5-IR-Remote.cpp.o
Archiving .pio\build\Mission Cyrus III\libFrameworkArduinoVariant.a
Compiling .pio\build\Mission Cyrus III\FrameworkArduino\CDC.cpp.o
Archiving .pio\build\Mission Cyrus III\libc51\libRK_LCD_I2C.a
Archiving .pio\build\Mission Cyrus III\lib1cc\libEncoder.a
Archiving .pio\build\Mission Cyrus III\lib7bf\libRK_RC5-IR-Remote.a
Compiling .pio\build\Mission Cyrus III\FrameworkArduino\HardwareSerial.cpp.o
[...more FrameworkArduino stuff here...]
Compiling .pio\build\Mission Cyrus III\FrameworkArduino\wiring_shift.c.o
Archiving .pio\build\Mission Cyrus III\libFrameworkArduino.a
Linking .pio\build\Mission Cyrus III\firmware.elf
C:\Users\LEFTBR~1\AppData\Local\Temp\ccezMMdQ.ltrans0.ltrans.o: In function `main':
<artificial>:(.text.startup+0x100): undefined reference to `lcd_init(unsigned char)'
<artificial>:(.text.startup+0x10e): undefined reference to `lcd_home()'
[...some more of these...]
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\Mission Cyrus III\firmware.elf] Error 1

The dependency graph looks fine, the function declarations/definitions in question are in libRK_LCD_I2C.h / libRK_LCD_I2C.c like:

In libRK_LCD_I2C.h:

#include <inttypes.h>
#include <stdbool.h>
#include <avr/pgmspace.h>

extern bool lcd_init( uint8_t dispAttr);

extern void lcd_home( void);

In libRK_LCD_I2C.c:

#include "libRK_PCF8574.h"                      // this lib contains all the I2C stuff

bool lcd_init( uint8_t dispAttr)
{
    [...]
}

void lcd_home( void)
{
    [...]
}

An objdump on the lib archive file yields:

libRK_LCD_I2C.c.o:     file format elf32-avr

SYMBOL TABLE:
00000000 l    df *ABS*                          00000000 libRK_LCD_I2C.c
[...]
00000000 l    d  .gnu.lto_lcd_home.e5da2ecd     00000000 .gnu.lto_lcd_home.e5da2ecd
00000000 l    d  .gnu.lto_lcd_init.e5da2ecd     00000000 .gnu.lto_lcd_init.e5da2ecd

Well, here I’m stuck :-o
Any idea what’s going wrong?

Btw.: even with

build_flags =
-v -v

in platformio.ini I do not see the call to ld.exe in the terminal log. Is there a possibility to force PIO to “echo” the complete linker command? Or… am I just too stupid to find it??

Appreciate your help :wink: :slight_smile:
Ralph

And you’re calling the functions implemented in this file from a cpp file? Then you just have a name mangling problem. See Standard C++.

Just modify your libRK_LCD_I2C.h to

#include <inttypes.h>
#include <stdbool.h>
#include <avr/pgmspace.h>

#ifndef LIBRK_LCD_I2C_H
#define LIBRK_LCD_I2C_H

#ifdef __cplusplus
extern "C" {
#endif

extern bool lcd_init( uint8_t dispAttr);

extern void lcd_home( void);

#ifdef __cplusplus
}
#endif

#endif /* LIBRK_LCD_I2C_H */

I also added standard include guards because it’s kinda unclean code without it (double-declarations…)

Thank you very much for the words of a wizard :))

What about the linker call in the terminal log?

The -v has to be applied to the pio run command. Otherwise you’re passing it to the compiler.

Just click on the readily-made task “Verbose Build” as opposed to “Build”, as documented.