Closed rgrr closed 3 months ago
If one checks the generated obj file, then it seems, that clang release invents the symbol stdout out of the blue.
gcc undefined symbols in printf.c.obj:
00000000 *UND* 00000000 putchar
00000000 *UND* 00000000 __aeabi_dcmpun
00000000 *UND* 00000000 __aeabi_dcmpgt
00000000 *UND* 00000000 __aeabi_dcmplt
00000000 *UND* 00000000 __aeabi_i2d
00000000 *UND* 00000000 __aeabi_dmul
00000000 *UND* 00000000 __aeabi_dadd
00000000 *UND* 00000000 __aeabi_dsub
00000000 *UND* 00000000 __aeabi_d2iz
00000000 *UND* 00000000 __aeabi_ddiv
00000000 *UND* 00000000 __aeabi_dcmpge
00000000 *UND* 00000000 __aeabi_uidivmod
00000000 *UND* 00000000 __aeabi_idivmod
00000000 *UND* 00000000 __aeabi_uidiv
00000000 *UND* 00000000 __aeabi_idiv
00000000 *UND* 00000000 __aeabi_d2uiz
00000000 *UND* 00000000 __aeabi_ui2d
00000000 *UND* 00000000 __aeabi_uldivmod
clang:
00000000 *UND* 00000000 fputc
00000000 *UND* 00000000 stdout
00000000 *UND* 00000000 __aeabi_dcmpun
00000000 *UND* 00000000 __aeabi_dcmplt
00000000 *UND* 00000000 __aeabi_dcmpgt
00000000 *UND* 00000000 __aeabi_dsub
00000000 *UND* 00000000 __aeabi_memset4
00000000 *UND* 00000000 __aeabi_d2iz
00000000 *UND* 00000000 __aeabi_i2d
00000000 *UND* 00000000 __aeabi_dmul
00000000 *UND* 00000000 __aeabi_d2uiz
00000000 *UND* 00000000 __aeabi_ui2d
00000000 *UND* 00000000 __aeabi_dcmple
00000000 *UND* 00000000 __aeabi_dcmpeq
00000000 *UND* 00000000 __aeabi_idiv
00000000 *UND* 00000000 __aeabi_idivmod
00000000 *UND* 00000000 __aeabi_memset
00000000 *UND* 00000000 __aeabi_dadd
00000000 *UND* 00000000 __aeabi_ddiv
00000000 *UND* 00000000 __aeabi_dcmpge
00000000 *UND* 00000000 __aeabi_uidivmod
Wondering if this actually is an issue of picolib or compiler-rt?
Yeah, from the release notes for 1.5.1
Experimental support is provided for compiling with Clang. As an example, you can build with the LLVM Embedded Toolchain for Arm, noting however that currently only version 14.0.0 works, as later versions use picolib rather than newlib.
Thanks Graham for pointing me to the release notes...
Tried clang 14.0.0 as suggested and almost everything works out of the box (except some minor glitches with static_assert()).
Anything I can do to help making the SDK work with picolib and later clangs?
Yeah, i didn't have any time to look at it in detail, but the area of integration with the C-library and the somewhat wide distribution of such points within the SDK, suggests to me that we should factor that adapter layer out into a single library perhaps, and allow plugging that (or via #ifdef) (edit: note this was true even before LLVM 15.0.0 / picolib)
But even short of that, just prototyping something that works with picolib, even if it isn't abstracted out
I did some tests with clang 16.0.0 (on Windows) and a c++ project. After some small changes and resolving undefined symbols everything just works:
pico_arm_clang.cmake
: removed --sysroot
The --sysroot path wasn't correct for clang-16 but the option also seems unnecessary. Everything builds just fine without it.
(I think --target=armv6m-none-eabi
sets everything up)
undefined stdout
Simply added to source file: std::FILE* const stdout = nullptr;
. I assume this is good enough and it's not actually used (in my code anyway). printf
, for instance, seems to work without issue.
undefined extern "C" void __cxxabiv1::__cxa_pure_virtual();
Implemented in source file: calls panic()
undefined __heap_start
Added __heap_start = .;
to memmap_default.ld before __end__
undefined __heap_end
Added __heap_end = .;
to memmap_default.ld before __scratch_x_start__
undefined __atomic_load_[1/2/4]
and __atomic_store_[1/2/4]
gcc provides implementations for these while clang does not. I can provide (c++) implementations.
I still have 4 linker warnings all similar to:
ld.lld: warning: section type mismatch for .ram_vector_table
>>> .../pico_runtime/runtime.c.obj:(.ram_vector_table): SHT_PROGBITS
>>> output section .ram_vector_table: SHT_NOBITS
The others are for .heap
, .stack
and .stack1
. Not sure what to do with them.
@quertv these were tests on top of 1.5.1?
@kilograham yes they were with release-16.0.0 from LLVM Embedded Toolchain for Arm.
I can almost confirm what @geurtv wrote. My path was a little bit easier, because (my guess) my program is "C".
cmake invocation:
export PICO_TOOLCHAIN_PATH=~/bin/llvm-arm-none-eabi/bin
cmake -B $(BUILD_DIR) -G Ninja -DCMAKE_BUILD_TYPE=Release -DPICO_BOARD=$(PICO_BOARD) \
$(CMAKE_FLAGS) -DPICO_COMPILER=pico_arm_clang
Things I had to fix:
--sysroot
pointed to the correct location, so no changes required to pico_arm_clang.cmake
stdout
: I had to add FILE *const stdout = NULL;
because "C"That was it. Compiles and executes now fine with debug/release.
I compiled with a homebrewed version of the LLVM Embedded Toolchain which resembles more or less version 17 before they removed the *.cfg files.
@rgrr I assume you don't use heap allocations, so no malloc()
and free()
? Otherwise I would expect it to complain about __heap_start
and __heap_end
as well.
Also, just checked, on gcc uint32_t
is unsigned long
and on clang it's unsigned int
, hence the printf
warnings. BTW, the portable way to printf
uint32_t
is to use PRIu32
(from inttypes.h), so for instance:
void print_values(uint32_t value1, int32_t value2)
{
printf("value1=%" PRIu32", value2=%" PRIi32"\n", value1, value2);
}
@rgrr I assume you don't use heap allocations, so no
malloc()
andfree()
? Otherwise I would expect it to complain about__heap_start
and__heap_end
as well.Also, just checked, on gcc
uint32_t
isunsigned long
and on clang it'sunsigned int
, hence theprintf
warnings. BTW, the portable way toprintf
uint32_t
is to usePRIu32
(from inttypes.h), so for instance:void print_values(uint32_t value1, int32_t value2) { printf("value1=%" PRIu32", value2=%" PRIi32"\n", value1, value2); }
yup, but it tends to be a bit annoying/unreadable, so we/I tend to cast values to (int) instead.
note, GCC's behavior in this regard is very strange; Clang's makes more sense
1. clang throws some errors about static asserts without messages. Added those messages 3. clang does not know the "optimize" attribute which is used somewhere in a library. Added "-Wno-unknown-attributes"
Were these in pico-sdk/pico-examples; they should have all been fixed.
:
Were these in pico-sdk/pico-examples; they should have all been fixed.
Don't worry... it was somewhere in my daplink library copy. The only warning concerning RP2040 came from FreeRTOS which complains about warning: unused function 'prvGetAllEventGroupBits'
in port.c
@rgrr I assume you don't use heap allocations, so no
malloc()
andfree()
? Otherwise I would expect it to complain about__heap_start
and__heap_end
as well.
Yes, you are right. My actual application does no malloc()/free(). Only (pseudo) dynamic things are done in FreeRTOS and lwIP.
Also, just checked, on gcc
uint32_t
isunsigned long
and on clang it'sunsigned int
, hence theprintf
warnings. BTW, the portable way toprintf
uint32_t
is to usePRIu32
(from inttypes.h), so for instance:
Gosh, that's really unfortunate.
void print_values(uint32_t value1, int32_t value2) { printf("value1=%" PRIu32", value2=%" PRIi32"\n", value1, value2); }
Oh, that's new to me. I agree with Graham, that this is rather annoying and normally I change the parameters via casting as well.
Correction: libc++
and libc++abi
aren't linked by default. If both are added then __cxa_pure_virtual
isn't undefined anymore.
Note also that just like gcc clang doesn't know about multi-core, so to guarantee "atomic" initialization of statics in functions custom implementations for __cxa_guard_acquire
and __cxa_guard_release
might need to be provided. Pretty sure this is true for gcc as well. I guess this all mostly applies to c++ only. For instance, it's unclear to me what happens when the next function is called for the first time from both cores at (about) the same time:
auto& f()
{
static std::string s{"Hallo?"};
return s;
}
Hi,
I noticed the discussion about picolibc
vs newlib
above, so I want to point put that the LLVM embedded toolchain for Arm added experimental set of multilib variants based on newlib
4.1.0, see the dev drop.
If this proves useful, newlib
set of libraries will be included into every release, keeping picolibc
the default.
Please report any feedback back to the LLVM embedded toolchain for Arm project.
Hi,
I noticed the discussion about
picolibc
vsnewlib
above, so I want to point put that the LLVM embedded toolchain for Arm added experimental set of multilib variants based onnewlib
4.1.0, see the dev drop.If this proves useful,
newlib
set of libraries will be included into every release, keepingpicolibc
the default.Please report any feedback back to the LLVM embedded toolchain for Arm project.
excellent, thanks
fixed in SDK 2.0.0
Hello,
this is perhaps related to #196...
Currently I'm trying to compile my project with clang (main branch of llvm, embedded toolchain).
-DCMAKE_BUILD_TYPE=Debug
works, best: the generated image works.But... compiling with
-DCMAKE_BUILD_TYPE=Release
produces a linker error:Needless to say, that this works with gcc.
Invocation of the gcc build (works)
Invocation of the clang build (produces above error)
Any ideas on this?