5-Minute Read

Cross Compile to PinePhone Part Two

Click Here for Part one

Click Here for Part three

So on part one, we managed to compile kalk with emulator, and generated ArchLinux package to install on our PinePhone. However, emulator is slow, and compiling with emulator isn’t cross compile. Today, we’ll be using real cross compiler to build kalk package.

Setup the Toolchain and SDK

To be able to cross compile, we need cross compiler and target platform’s libraries. On ArchLinux, there is aarch64-linux-gnu-gcc. But it’s sysroot option is bugged so we won’t use the cross compiler from pacman this time. Instead, we’ll grab the toolchain from ArchLinux arm. The link is here. Since PinePhone is armv8, download the armv8 pre-built crosstool-ng toolchain. To keep everything nice and tidy, we store the toolchain in dedicated directory. I’m using ~/Develop/CrossCompile.

tar -xzvf x-tools8.tar.xz
mv x-tools8/aarch64-unknown-linux-gnu ~/Develop/CrossCompile

For a compiler, it needs program’s dynamically linked libraries and library headers to do its job. And we certainly won’t want our cross compiler to use our host system’s libraries. In fact, it can’t. That’s where sysroot comes to play. Sysroot is path for compiler and linker to find the things mentioned above. It defaults to /usr. But since we’re cross compiling, it have to be changed to a directory that contains all the libraries our project depends on, and in target platform’s format. That is, aarch64. Normally, on iOS and Android developing, it’s called SDK. Usually shipped with XCode or Android Studio, with one SDK for one system version. But for PinePhone, we don’t have one. So we would build one from scratch, it’s not that complicate.

Remember I said it needs to contain all our project’s dependencies? This may sound like a headache, manually find all our projects dependencies and dependencies' dependencies? Nay, we don’t do that here. As a lazy programmer, we could just ‘steal’ other people’s work! And the work in question is… Manjaro PinePhone plasma mobile dev image! So we need to extract the system part from ISO. The procedure has been detailed in part one, I won’t repeat it here. You should place the extracted rootfs in ~/Develop/CrossCompile, named as pinephone-manjaro-rootfs. Because I did so :P

Ideally we can just use the extracted rootfs as our sysroot. But as a KDE project, we use extra-cmake-modules. While in theory all programs used in building should come from host system, but we don’t have extra-cmake-modules package in x86_64 format that can produce correct aarch64 results. Even if we have, we still need cross compile version of moc qmake rcc uic qdbuscpp2xml qdbusxml2cpp desktop2json . Which don’t exist. We can’t use the above mentioned program on our host system either, because we can’t guarantee it can produce correct results for aarch64. But we won’t let that stop us, emulator is always available. So go back to part one, install qemu-user-static(bin) from aur. With emulator in hand, we can chroot into the rootfs, because the extra-cmake-modules isn’t installed by default on manjaro image. Follow the directions from part one, but only install extra-cmake-modules. That’s all we need.

Setup cmake toolchain file

Cmake provide --toolchain option to make cross compiling easier. It demands a cmake file contains information about toolchain. We’ll write one with the name pinephone_toolchain.cmake

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)

set(CMAKE_SYSROOT /home/hany/Develop/CrossCompile/pinephone-manjaro-rootfs)

set(tools /home/hany/Develop/CrossCompile/aarch64-unknown-linux-gnu)
set(CMAKE_C_COMPILER ${tools}/bin/aarch64-unknown-linux-gnu-gcc)
set(CMAKE_CXX_COMPILER ${tools}/bin/aarch64-unknown-linux-gnu-g++)

set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

For a detailed explaination of every options, cmake documentation is the place to go.

With everything ready, we can begen compile. The build directory is aloneside the source directory, not in the source directory.

cmake -G Ninja --toolchain ../kalk/pinephone_toolchain.cmake ../kalk

And you will get slapped by cmake errors. Scroll up a bit you’ll find cmake is complaining about something qemu-aarch64-static: Could not open '/lib/ld-linux-aarch64.so.1': No such file or directory. The reason behind this is extra-cmake-modules is calling our sysroot’s qmake, and that qmake want ld-linux-aarch64.so.1 in /lib. Of course we can copy this shared library from sysroot to our /lib, but why pollute your system while you can tell qemu to find this object file in sysroot? Qemu provides environment variable to do this, it’s QEMU_LD_PREFIX. Neat!

export QEMU_LD_PREFIX=/home/hany/Develop/CrossCompile/pinephone-manjaro-rootfs
cmake -G Ninja --toolchain ../kalk/pinephone_toolchain.cmake ../kalk
ninja

Setup PKGBUILD To Generate package

You should now be able to cross compile kalk, but what we want is a pacman package. So go back to part one and create PKGBUILD file, but in host system this time. Actually, you should’ve exit chroot and umount by now. No need to add new user, you’re not root, right? We need to change build section, the result file should like this:

# Maintainer: Gustavo Castro < gustawho [ at ] gmail [ dot ] com >

pkgname=kalk
pkgver=69.69
pkgrel=1
pkgdesc="Kalk is a powerful cross-platfrom calculator application built with the Kirigami framework"
arch=(x86_64 i686 arm armv6h armv7h aarch64)
url="https://invent.kde.org/plasma-mobile/kalk"
license=('GPL3')
depends=('ki18n' 'kconfig' 'kcoreaddons' 'knotifications' 'kirigami2' 'kunitconversion'
         'kdbusaddons' 'plasma-framework' 'gmp' 'mpfr' 'qt5-feedback')
makedepends=('qt5-tools' 'qt5-svg' 'extra-cmake-modules')

package() {
  DESTDIR="${pkgdir}" cmake --install build --config Release
}

Due to limitations of makepkg, you should create src/build in the PKGBUILD file directory and build the project there use the afore mentioned method. This way we only let makepkg packages for us. This is cross compiling by hand, it’s fine for small projects. But as Plasma Mobile has dozens of projects, I think automate scripts are better. And SDKs ready to use. But it’s enough for today, stay tuned for part three!

Recent Posts

Categories

About

A young developer who loves Linux.