I've been wondering how to correctly build clang/LLVM for the AVR target architecture. Unfortunately documentation is very scarce (or outdated or I didn't find it) and while I've been able to build clang/LLVM for AVR I'm still falling short of compiling an actual binary for the MCU. Here are the steps I've undertaken so far:
git clone https://github.com/llvm/llvm-project
cd llvm-project
mkdir build && cd build
cmake -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS="clang;libcxx;libcxxabi" -DLLVM_TARGETS_TO_BUILD="AVR" -DCMAKE_BUILD_TYPE=Release ../llvm
make -j8
sudo make install
Next I created a pretty empty main.cpp and tried to compile that:
#include <stdint.h>
int main()
{
for(;;) { }
return 0;
}
Here's the result of attempting the compilation ...
$ clang++ --target=avr -mmcu=atmega328p -c main.cpp -o main.o -v
clang version 11.0.0 (https://github.com/llvm/llvm-project 177dd63c8d742250dac6ea365e7c30f0fbab3257)
Target: avr
Thread model: posix
InstalledDir: /usr/local/bin
Found candidate GCC installation: /usr/lib/gcc/avr/5.4.0
Selected GCC installation: /usr/lib/gcc/avr/5.4.0
(in-process)
"/usr/local/bin/clang-11" -cc1 -triple avr -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -target-cpu atmega328p -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /usr/local/lib/clang/11.0.0 -fdeprecated-macro -fdebug-compilation-dir /home/alex/tmp/clang-avr -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o main.o -x c++ main.cpp
clang -cc1 version 11.0.0 based upon LLVM 11.0.0git default target x86_64-unknown-linux-gnu
#include "..." search starts here:
#include <...> search starts here:
/usr/local/include
/usr/local/lib/clang/11.0.0/include
/usr/include
End of search list.
In file included from main.cpp:1:
In file included from /usr/local/lib/clang/11.0.0/include/stdint.h:52:
/usr/include/stdint.h:26:10: fatal error: 'bits/libc-header-start.h' file not found
#include <bits/libc-header-start.h>
^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
Looking for that file I can find it in the system
$ find /usr -iname libc-header-start.h
/usr/include/x86_64-linux-gnu/bits/libc-header-start.h
But adding it to the clang call via -isystem or -I does not help either.
$ clang --target=avr -mmcu=atmega328p -c main.cpp -o main.o -v -I/usr/include/x86_64-linux-gnu
clang version 11.0.0 (https://github.com/llvm/llvm-project 177dd63c8d742250dac6ea365e7c30f0fbab3257)
Target: avr
Thread model: posix
InstalledDir: /usr/local/bin
(in-process)
"/usr/local/bin/clang-11" -cc1 -triple avr -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name main.cpp -mrelocation-model static -mthread-model posix -mframe-pointer=all -fmath-errno -fno-rounding-math -masm-verbose -mconstructor aliases -target-cpu atmega328p -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -v -resource-dir /usr/local/lib/clang/11.0.0 -I /usr/include/x86_64-linux-gnu -fdeprecated-macro -fdebug-compilation-dir /home/alex/tmp/clang-avr -ferror-limit 19 -fmessage-length 0 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fcxx-exceptions -fexceptions -fdiagnostics-show-option -fcolor-diagnostics -faddrsig -o main.o -x c++ main.cpp
clang -cc1 version 11.0.0 based upon LLVM 11.0.0git default target x86_64-unknown-linux-gnu
#include "..." search starts here:
#include <...> search starts here:
/usr/include/x86_64-linux-gnu
/usr/local/include
/usr/local/lib/clang/11.0.0/include
/usr/include
End of search list.
In file included from main.cpp:1:
In file included from /usr/local/lib/clang/11.0.0/include/stdint.h:52:
In file included from /usr/include/stdint.h:26:
In file included from /usr/include/x86_64-linux-gnu/bits/libc-header-start.h:33:
In file included from /usr/include/features.h:448:
/usr/include/x86_64-linux-gnu/gnu/stubs.h:7:11: fatal error: 'gnu/stubs-32.h' file not found
# include <gnu/stubs-32.h>
^~~~~~~~~~~~~~~~
1 error generated.
Thinking that maybe the old version (5.4.0) of avr-gcc might be a problem I've built a 9.2.0 version from sources
$ avr-gcc -v
Using built-in specs.
Reading specs from /opt/avr/avr-gcc/lib/gcc/avr/9.2.0/device-specs/specs-avr2
COLLECT_GCC=avr-gcc
COLLECT_LTO_WRAPPER=/opt/avr/avr-gcc/libexec/gcc/avr/9.2.0/lto-wrapper
Target: avr
Configured with: ../configure --prefix=/opt/avr/avr-gcc --target=avr --enable-languages=c,c++ --disable-nls --disable-libssp --disable-libada --with-dwarf2 --disable-shared --enable-static --enable-mingw-wildcard
Thread model: single
gcc version 9.2.0 (GCC)
But this didn't change anything, except that when running clang without file arguments it does indicate that there is no avr-gcc in the system (although there is, but probably not spliced in there where the clang/LLVM build process expects it).
$ clang --target=avr -mmcu=atmega328p
clang-11: warning: no avr-gcc installation can be found on the system, cannot link standard libraries [-Wavr-rtlib-linking-quirks]
clang-11: warning: standard library not linked and so no interrupt vector table or compiler runtime routines will be linked [-Wavr-rtlib-linking-quirks]
clang-11: error: no input files
I'd greatly appreciate any input helping to solve these problems or a pointer to working documentation.
With kind regards, Alex
_______________________________________________
LLVM Developers mailing list
llvm...@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
The first thing to try is adding the --gcc-toolchain argument to clang to point to the root of the avr gcc toolchain (I think in your case this will be /opt/avr/avr-gcc ). This should help the driver pick up the right include paths for AVR.
Try that see how you get on.
Sam
--
Sam Elliott
Software Developer - LLVM and OpenTitan
lowRISC CIC
Getting back to the compilation: when I run clang with both both -nostdlibinc (which makes it necessary to point clang to the header file location via -isystem /opt/avr/avr-libc/avr/include) and --gcc-toolchain I can compile the minimum example code.
clang++ --target=avr -nostdlibinc -isystem /opt/avr/avr-libc/avr/include --gcc-toolchain=/opt/avr/avr-gcc -mmcu=atmega328p -c main.cpp -o main.o
However, when I'm running a compilation on a more complicated embedded programm I get a lot of troubling warnings, e.g.
warning: unknown attribute '__progmem__' ignored [-Wunknown-attributes]
(which are troubling me, because if all those string constants are put in RAM instead of Flash the RAM will be pretty soon empty ;) ).
But those warnings aside I run ultimately into problems when getting to the linking step where it appears there are trouble providing implementations for avr-gcc built-in functions which I believe are located within the avr-gcc MCU specific libraries
/opt/avr/avr-libc/avr/include/util/delay.h:187: undefined reference to `__builtin_avr_delay_cycles(unsigned long)'
as well as troubles which seem to be originating from my C++ usage within the firmware
undefined reference to `vtable for __cxxabiv1::__class_type_info'
Kind regards, Alex
________________________________________
Von: Sam Elliott [sell...@lowrisc.org]
Gesendet: Mittwoch, 25. März 2020 13:17
An: Alexander Entinger
Cc: llvm...@lists.llvm.org
Betreff: Re: [llvm-dev] Build Clang/LLVM for AVR
In file included from main.cpp:1:
In file included from /usr/local/lib/clang/11.0.0/include/stdint.h:52:
/usr/include/stdint.h:26:10: fatal error: 'bits/libc-header-start.h' file not found
#include <bits/libc-header-start.h>
^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
I've created a minimum source file and build instructions which exhibit the same behaviour I see at my larger firmware project. The example involves dynamic polymorphism and builtin AVR specific functions.
#include <stdlib.h>
#include <util/delay.h>
void * operator new(size_t size) { return malloc(size); }
void operator delete(void * ptr) { free(ptr); }
__extension__ typedef int __guard __attribute__((mode (__DI__)));
extern "C" int __cxa_guard_acquire (__guard * g) { return !*(char *)(g); }
extern "C" void __cxa_guard_release (__guard * g) { *(char *)g = 1; }
extern "C" void __cxa_guard_abort (__guard * g) { }
extern "C" void __cxa_pure_virtual (void ) { }
class DelayBase
{
public:
virtual ~DelayBase() { }
virtual void delay(unsigned int const ms) = 0;
};
class Delay : public DelayBase
{
public:
virtual ~Delay() { }
virtual void delay(unsigned int const ms) override { for(unsigned int i = 0; i < ms; i++) { _delay_ms(1); } }
};
int main()
{
Delay delay;
for(;;)
{
delay.delay(10);
}
return 0;
}
Compilation is done via
$ clang++ --target=avr -nostdlibinc -isystem /opt/avr/avr-libc/avr/include --gcc-toolchain=/opt/avr/avr-gcc -mmcu=atmega328p -DF_CPU=16000000UL -O1 -c main.cpp -o main.o
and linking via
$ avr-ld main.o -o main.bin --relax --gc-sections -L/usr/lib/avr/lib/avr5 -L/usr/lib/avr/lib/avr5 -L/opt/avr/avr-gcc/lib/gcc/avr/9.2.0/avr5 -l:crtatmega328p.o -lgcc -lm -lc -latmega328p -mavr5
which results in the following error message:
avr-ld: main.o: in function `Delay::delay(unsigned int)':
main.cpp:(.progmem.data+0xa8): undefined reference to `__builtin_avr_delay_cycles(unsigned long)'
avr-ld: main.o:(.rodata._ZTI9DelayBase[_ZTI9DelayBase]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
avr-ld: main.o:(.rodata._ZTI5Delay[_ZTI5Delay]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
Any insight into the cause of this problem would be greatly appreciated ;)
Kind regards, Alex
________________________________________
Von: llvm-dev [llvm-dev...@lists.llvm.org]" im Auftrag von "Alexander Entinger via llvm-dev [llvm...@lists.llvm.org]
Gesendet: Mittwoch, 25. März 2020 14:51
An: Sam Elliott
1. You are using C++ runtime, so you'd need to link C++ runtime
library (e.g. libc++abi / libsupc++, etc)
2. You need to link some library that provides implementation of AVR
builtins (like __builtin_avr_delay_cycles). Note that avr-gcc
implements __builtin_avr_delay_cycles as a compiler builtin function
and expands it during the codegen.
Patches are welcome ;)
On Thu, Mar 26, 2020 at 8:42 AM Alexander Entinger via llvm-dev
--
With best regards, Anton Korobeynikov
Department of Statistical Modelling, Saint Petersburg State University
Regarding 1) I'm wondering from where to obtain such a library? Certainly it does not come with avr-gcc which is the reason I'm looking at clang/LLVM in the first place. Unfortunately to the best of my knowledge it was also not produced during the compilation of the cross-compiler, since both libc++.a and libc++abi.a are for i386:x86-64 architecture (objdump -f *.a).
Regarding 2) I believe I might be able to provide a patch for this, once I've learned a bit more about the internal works of LLVM ;)
Kind regards, Alex
________________________________________
Von: Anton Korobeynikov [an...@korobeynikov.info]
Gesendet: Donnerstag, 26. März 2020 09:09
An: Alexander Entinger
Cc: Sam Elliott; llvm...@lists.llvm.org