Building for ARM 32-bit embedded

Bonsaipanda jukka.korhonen at gmail.com
Fri Oct 11 21:02:04 UTC 2024


Hey guys, thought I'd throw some notes from testing out D for the 
first time. I'm a complete n00b when it comes to cross-platform 
buildchains and barely understand what crosslinking means and I 
thought I'd just create a small hello world test app and try to 
build it for amrhf to see if D would work for an app idea I have 
had for quite a while.

Now, for comparison, same hello world test app (when running 
Ubuntu 24.04) build using C is >>

```
arm-linux-gnueabihf-gcc test.c test_armhf
```
.. and out pops a 32-bit ARM executable.

So, in my head, I thought that there would be some kind of 
shorthand like this >>
```
ldc2 -armhf test.d
```
.. and that would give me a standalone executable, ready to be 
deployed on the ARM box and run.

The documentation says that you have to jump a bit through hoops 
to get LLVM working if you're not building on the platform that 
you're targeting, but the section in the documentation was almost 
incomprehensible to me - not that I'm stupid, I'm just not 
familiar with all that's required when linking stuff together, 
never done anything like that, never heard of any of these 
technologies before.

Apparently, if I want a static build (the target platform will 
not have anything available, optimal end-result is a standalone 
executable), I would need a pre-built armhf binary of the D 
runtime and Phobos, but I didn't understand why would I need 
those. When working with Vala, this was the thing that put me off 
- no matter how I would build the executable, on the embedded 
platform it would always nag about not finding all it's libraries 
and I couldn't figure out a way to make stuff static (there is a 
way, folks use it for embedded dev).

So I hopped on over to Raspberry Pi and made the test build 
there. Out pops a test.o which I have no idea what to do with. I 
know it's a 'shared object' but why would I want something like 
this. Testing out different build options I managed to get an 
executable out. Which then nags that it's in wrong format, it 
doesn't understand what to do, it wants to run for president 
etc., head scratching x 9000.

Diving into this forum, I found out that there's a problem with 
the linker - it connects stuff in the wrong order.

So the final build command, after ~5 hours of headscrathing (and 
trying ChatGPT to help out on understanding everything) is in the 
form of >>
```
ldc2 -mtriple=armv6-linux-gnueabihf -c test.d && 
arm-linux-gnueabihf-gcc test.o 
/usr/lib/arm-linux-gnueabihf/libphobos2-ldc.a 
/usr/lib/arm-linux-gnueabihf/libdruntime-ldc.a -lm -lz -o 
test_armhf
```
Yipe.

I mean, when you break it down, it's completely logical, but holy 
skagsack minion, that's verbose and I have a feeling I'm doing 
this completely wrong. Also, doing this on the Raspberry Pi is 
super cumbersome and slow.

And I don't mean this post to be any sort of rant, I'm just 
surprised on how the whole toolchain was so tricky to understand 
and set up. Was really hoping for the shorthand of sorts that 
would 'just work' on Ubuntu (or Windows), since LLVM itself is 
pretty agnostic about the platforms, or so I've understood.

The D language itself seems to fit perfectly for the stuff I had 
in mind, so I'm excited to dive deeper into it, but I have no 
idea if I'm able to build more complex code (like drawing 
directly into the framebuffer, some DSP stuff for ALSA).


More information about the digitalmars-d-ldc mailing list