A bit less than a year ago, I tried to get my Dummy Counter to run on my PinePhone. My first attempt on Postmarket OS failed but eventually, I got it running on Manjaro. This year, even though I barely touched my PinePhone since then, I decided to give it a go. I guess the phone insurance shenanigans were a blessing in disguise even though they led to a fairly ranty podcast. Today is the day I make the Dummy Counter work on Postmarket OS. Let’s jump right into it!
For this, I went back from the same project and the same Makefile as last time. The first thing I do is update my project to use .NET 6.0. Then I run my local clean install command.
make cleanup publish-local
The app is there, just like last time.
And yet, when I click, nothing happens. I try a couple more times then realise there must be more going on. So I try to run my binary by force to see what output I get.
And I get this:
sudo: unable to execute /usr/local/bin/DummyCounter/DummyCounter: No such file or directory
This makes no sense to me, the file is there and if I run
ls against it, I can see the file is definitely there. So what gives? Time for some googling and I find something on StackOverflow. “No such file or directory” but it exists” is the “question”, I use quotation marks because it isn’t much of a question.
One of the answers mentions that this kind of error occurs for dynamically linked binaries when one of the dependencies is missing. I can see what I need by running the
ldd command so I do just that:
As it turns out there’s a bunch of missing stuff but it all seem dependent on that ld-linux-aarch64.so.1 library. For some reason this is already there in UBTouch and Manjaro but not Postmarket. Actually there is a reason, it’s that PostmarketOS is built on top of Alpine Linux which is tiny, like 10MB if memory serves well.
Now I’ve got a target,
lib/ld-linux-aarch64.so.1. If I can figure how to find it, I can make this work. Lucky for me, searching for that error led me to something very similar. The shortest, most efficient post I’ve seen. The title is “Error loading shared library ld-linux-x86-64.so.2: on Alpine Linux“.
The author’s solution is to install the musl which is an implementation of the standard C library. He does so by installing the
libc6-compat package on his x64 Linux machine. However, there is a pickle. The library needs to exist for arm64 devices which would be aarch64. So I search for that and wouldn’t you know it, it is there!
The next step for me is copying the author’s solution but adjusting it for the the arm64 architecture. First, I installed the library.
sudo apk add libc6-compat
Next, I create a symbolic link between the musl library and the missing library. Surprisingly, I didn’t need to create a symlink as he did since the
/lib/ld-linux-aarch64.so.1 library file already existed. Unfortunately, it still does not work. The library issue is gone but now I get these last lines still showing up:
Error relocating /usr/local/bin/DummyCounter/DummyCounter: __strdup: symbol not found Error relocating /usr/local/bin/DummyCounter/DummyCounter: __isnan: symbol not found Error relocating /usr/local/bin/DummyCounter/DummyCounter: __isnanf: symbol not found
This stumps as I am not a big Linux enthusiast to begin with so I have no idea what I’m looking at. Further word searching leads me to an article about how Alpine Linux is now using musl instead of glibc potentially explaining my issues so far. Why? Because it is very likely the C implementation I used through .NET Core when building my Dummy Counter is glibc. Most stuff I find seems to point towards rebuilding postmarketOS using glibc but that’s not happening. I’m barely dipping my fingers into Linux so I’m not ready to go that deep just yet.
Now I need to figure how to run a glibc program on postmarketOS which does not involve rebuilding postmarketOS with glibc. Turns out there is a page on the Alpine Linux wiki about just that. The first option is to install gcompat, the he GNU C Library Compatibility Layer for Adélie Linux. I don’t know Adélie but it probably is another distribution built atop Alpine so it’s good enough for me. I install it but no luck. Same error. I even rebooted the phone but still the same deadly trio of errors.
Surely, someone solved this before, I’m not that much of a precursor. With that in mind, I check issues from the gcompat repository and find something that rings a bell. An issue about strdup not being found. Seemingly the issue lies within the musl dynamic program loader
ldd does not execute the stub loader that forces the gcompat library to be preloaded. Therefore we need to force this by overriding the
LD_PRELOAD variable. Let’s give it a try:
pine64-pinephone:~$ LD_PRELOAD=/lib/libgcompat.so.0 ldd /usr/local/bin/DummyCounter/DummyCounter /lib/ld-linux-aarch64.so.1 (0xffffaad6a000) /lib/libgcompat.so.0 => /lib/libgcompat.so.0 (0xffffaa390000) libpthread.so.0 => /lib/ld-linux-aarch64.so.1 (0xffffaad6a000) libdl.so.2 => /lib/ld-linux-aarch64.so.1 (0xffffaad6a000) libz.so.1 => /lib/libz.so.1 (0xffffaa369000) librt.so.1 => /lib/ld-linux-aarch64.so.1 (0xffffaad6a000) libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0xffffaa344000) libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0xffffaa185000) libm.so.6 => /lib/ld-linux-aarch64.so.1 (0xffffaad6a000) libc.so.6 => /lib/ld-linux-aarch64.so.1 (0xffffaad6a000) ld-linux-aarch64.so.1 => /lib/ld-linux-aarch64.so.1 (0xffffaa170000) libucontext.so.1 => /lib/libucontext.so.1 (0xffffaa15e000) libobstack.so.1 => /usr/lib/libobstack.so.1 (0xffffaa14b000)
Now that we killed all the linking errors, let’s try to run the Dummy Counter one last time.
pine64-pinephone:~$ LD_PRELOAD=/lib/libgcompat.so.0 sudo /usr/local/bin/DummyCounter/DummyCounter Segmentation fault
Oh cool segfault, thanks for nothing. Looks like I will need some sort of container like Flatpak to run my app. Better luck next time. I hope you enjoyed the read and I will see you on the next one.