I am building an avr-libc static library like this:
avr-gcc -O2 -I. -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -g -ggdb -ffunction-sections -fdata-sections -Wl,--gc-sections -mrelax -std=gnu99 -c font.c unifont.c libtft.c
and then:
avr-ar rcs libtft.a libtft.o font.o unifont.o
Including the library in a project, and building it like this:
avr-gcc -mmcu=atmega328p -DF_CPU=8000000UL -O2 -I. -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -Wall -Wstrict-prototypes -g -ggdb -ffunction-sections -fdata-sections -Wl,--gc-sections -mrelax -std=gnu99 rfm.c tft.c sdc.c avrrfm.c librfm95.a libtft.a libsdc.a --output avrrfm.elf
fails with:
/usr/lib/gcc/avr/14.2.0/../../../avr/bin/ld: libtft.a(libtft.o): in function `tftWriteSpace':
/home/dode/dev/libtft/libtft.c:284:(.text.tftWriteSpace+0x44): undefined reference to `__mulhi3'
libtft.c:284 is:
bytes_t bytes = width * height / 8;
By including -mmcu=atmega328p
when building the library, the issue is solved, so I guess that when building the library without specifying the target MCU, a multiplication function that works for all MCU types is picked.
Then, when building the project and specifying the MCU, another (optimized?) function is used, and the one used in the library is undefined.
Is it possible at all to build a target MCU independent static library?
Is it possible at all to build a target MCU independent static library?
No. You'll need multilib granularity at least.
Multilib options are: -mmcu=
, -msp8
, -mshort-calls
, -mdouble=
and -mlong-double=
where availability depends on configure options and the compiler version, and not all combinations are possible. Showing all multilib variants, here with avr-gcc v15 that has bee configured with --with-long-double=64
:
$ avr-gcc -print-multi-lib
.;
avr25;@mmcu=avr25
avr3;@mmcu=avr3
avr31;@mmcu=avr31
avr35;@mmcu=avr35
avr4;@mmcu=avr4
...
avrxmega3/short-calls/double64;@mmcu=avrxmega3@mshort-calls@mdouble=64
avrxmega4/double64;@mmcu=avrxmega4@mdouble=64
avrxmega5/double64;@mmcu=avrxmega5@mdouble=64
avrxmega6/double64;@mmcu=avrxmega6@mdouble=64
avrxmega7/double64;@mmcu=avrxmega7@mdouble=64
avrtiny/double64;@mmcu=avrtiny@mdouble=64
Left of ;
are the multilib variants' paths like used on disk. Right of ;
are the options that lead to that multilib variant (replace @
with -
(a blank and a dash)).
You can of course generate only a selection of these when you don't need all variants. In order to map options to a multilib path:
$ avr-gcc -mmcu=atmega328p -print-multi-directory
avr5
which is very useful in Makefile or build scripts, for example when you have to select a multilib path. That is: You build multilib variants according to subdirs and options as of -print-multi-lib
and then select the path according to -print-multi-directory
. This is exactly what avr-gcc does when it has to select a multilib variant of libgcc.a
, libc.a
or libm.a
, see for example the output of avr-gcc -v ...
when linking.
In the case where the library contains device specific stuff like SFR addresses and the like, you may have to switch to device granularity.