I'm having some trouble compiling and linking a library that's written in assembler with my program code which is in C++. In my case it's for an AVR microcontroller using the avr-gcc suite, but I imagine this problem would apply to GCC generally.
I can get .o files built from the C++ source and assembly, but linking them gives the error:
> avr-gcc -mmcu=attiny84 -lm -o obj\AvrTest.elf obj\Main.o obj\i2cmaster.o
obj\Main.o: In function `main':
Main.cpp:(.text+0x0): undefined reference to `i2c_init()'
Here's the uber-simple Main.cpp
code:
#include "i2cmaster.h"
void main() {
i2c_init();
while ( true ) {
}
}
i2cmaster.h
defines the function prototype like this:
extern void i2c_init(void);
And in the assembler file, i2cmaster.S
, that function is:
.global i2c_init
.func i2c_init
i2c_init:
cbi SDA_DDR,SDA ;release SDA
cbi SCL_DDR,SCL ;release SCL
cbi SDA_OUT,SDA
cbi SCL_OUT,SCL
ret
.endfunc
The linking would seem like a no-brainer - but I get that reference error. I noticed the assembler code generated for Main.cpp
comes out like this:
.global main
.type main, @function
main:
rcall _Z8i2c_initv
.L2:
rjmp .L2
.size main, .-main
I suspect the problem is that i2c_init
is becoming _Z8i2c_initv
through some name mangling process I don't understand, and that _Z8i2c_initv
can no longer be matched with the non-mangled i2c_init
symbol in the i2cmaster.o
object file.
Does anyone understand the mangling process, and how to suppress it during compilation/assembly so that these modules can talk to each other? Or anything else I might be doing wrong?