[llvm-dev] Build Clang/LLVM for AVR
Anton Korobeynikov via llvm-dev
llvm-dev at lists.llvm.org
Thu Mar 26 01:09:12 PDT 2020
Two issues here:
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
<llvm-dev at lists.llvm.org> wrote:
>
> Good Morning,
>
> 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-bounces at lists.llvm.org]" im Auftrag von "Alexander Entinger via llvm-dev [llvm-dev at lists.llvm.org]
> Gesendet: Mittwoch, 25. März 2020 14:51
> An: Sam Elliott
> Cc: llvm-dev at lists.llvm.org
> Betreff: Re: [llvm-dev] Build Clang/LLVM for AVR
>
> Thank you for both of your input. Yes, I try to cross-compile for AVR, the simple ATMEGA328P used in every Arduino Uno. My main motivation being that I hope to be able to use a couple of STL containers, <functional> and <type_traits> on the MCU. Not sure though if this can be reached by going via the clang route.
>
> 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 [selliott at lowrisc.org]
> Gesendet: Mittwoch, 25. März 2020 13:17
> An: Alexander Entinger
> Cc: llvm-dev at lists.llvm.org
> Betreff: Re: [llvm-dev] Build Clang/LLVM for AVR
>
> It looks like you’re cross-compiling for an embedded target, so you need to be careful about how you treat headers (like libc’s), as the x86 ones will not be compatible with the AVR ones. The clang driver can manage this for you, if you give it enough information:
>
> 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
>
> > On 25 Mar 2020, at 12:01 pm, Alexander Entinger via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> >
> > Hi everyone,
> >
> > 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-dev at lists.llvm.org
> > https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
> --
> Sam Elliott
> Software Developer - LLVM and OpenTitan
> lowRISC CIC
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
--
With best regards, Anton Korobeynikov
Department of Statistical Modelling, Saint Petersburg State University
More information about the llvm-dev
mailing list