Building armv7h packages on a x86 system

Gnu06-mascot-logo+parabola-logo 050ppi.png
This article or section needs expansion.
Please help expand this article so the intended scope is covered in sufficient detail. (Discuss)

How to build armv7h packages on a x86 system. This article focuses on configuration of package building tools on a x86_64 or i686 system.

Configuration files

Start taking a copy of pacman.conf and editing it:

# mkdir /mnt/custom-folder
# cp /etc/pacman.conf /mnt/custom-folder

You must set the architecture to armv7h (the default is auto) in the "general options" section in /etc/pacman.conf. Then, you should disable/remove all respositories other than [libre], [core], [extra] and [community].

pacman.conf
[options]
Architecture = armv7h

Create chroot

You need create the armv7h chroot with

# mkdir /mnt/chroot-armv7h

Make sure the pacman keyring has been initialized

# pacman-key --init

Import, trust and install the archlinuxarm keyring. When possible, Parabola leverages free packages that originally came from Arch ARM.

# pacman -U https://www.parabola.nu/packages/core/any/archlinuxarm-keyring/download/
# pacman-key --lsign-key builder@archlinuxarm.org
# pacman -U https://www.parabola.nu/packages/core/any/archlinuxarm-keyring/download/
Note: If this doesn't work, use any other available package mirror with each package. Update with the most recent package version, for example:
# pacman -U https://repo.parabola.nu/core/os/armv7h/archlinuxarm-keyring-20140119-1-any.pkg.tar.xz
# pacman-key --lsign-key builder@archlinuxarm.org
# pacman -U https://repo.parabola.nu/core/os/armv7h/archlinuxarm-keyring-20140119-1-any.pkg.tar.xz

Install pacstrap if you haven't already and install the base group packages with it

# pacman -S arch-install-scripts
# pacstrap -c -d -C /mnt/custom-folder/pacman.conf /mnt/chroot-armv7h base
Note: Errors about exec() calls might be benign. Proceed to see whether you can chroot into the new system

PRoot (alternative way 1)

PRoot is a user-space implementation of chroot, mount --bind, and binfmt_misc. This means that users don't need any privileges or setup to do things like using an arbitrary directory as the new root filesystem, making files accessible somewhere else in the filesystem hierarchy, or executing programs built for another CPU architecture transparently through QEMU user-mode. Also, developers can use PRoot as a generic GNU/Linux process instrumentation engine thanks to its extension mechanism, see CARE for an example. Technically PRoot relies on ptrace, an unprivileged system-call available in every Linux kernel.

To install, you run:

# pacman -S proot

QEMU

QEMU (short for Quick Emulator) is a free software hosted hypervisor that performs hardware virtualization (not to be confused with hardware-assisted virtualization)

We need it (qemu-arm) to build ARMv7 packages from a x86 machine into chroot, so you run:

# pacman -S qemu-arch-extra

Prepare and enter to the chroot

 # mount -o rbind /dev /mnt/chroot-armv7h/dev
 # mount -o bind /sys /mnt/chroot-armv7h/sys
 # mount -o bind /tmp /mnt/chroot-armv7h/tmp
 # mount -t proc none /mnt/chroot-armv7h/proc
 # rm /mnt/chroot-armv7h/etc/resolv.conf
 # cp -a /etc/resolv.conf /mnt/chroot-armv7h/etc
 # cd /mnt
 # proot -0 -q /usr/bin/qemu-arm -r /mnt/chroot-armv7h

QEMU Static (alternative way 2)

To be able to chroot into a target file system without proot, the qemu emulator for the target CPU needs to be accessible from inside the chroot jail. For this to work, you need first to install the qemu-arch-extra-static package:

 # pacman -S qemu-arch-extra-static
Note: You cannot use the dynamically linked qemu because the host libraries will not be accessible from inside the chroot.

First, install binfmt-qemu-static, enable and start the systemd service, systemd-binfmt.service.

 # pacman -S binfmt-qemu-static
 # systemctl enable systemd-binfmt.service
 # systemctl start systemd-binfmt.service

Next, copy the emulator for the target architecture to the path registered by binfmt-support. You need to do the following:

 # cp -a /usr/bin/qemu-arm-static /mnt/chroot-armv7h/usr/bin

Prepare and enter to the chroot

 # mount -o rbind /dev /mnt/chroot-armv7h/dev
 # mount -o bind /sys /mnt/chroot-armv7h/sys
 # mount -o bind /tmp /mnt/chroot-armv7h/tmp
 # mount -t proc none /mnt/chroot-armv7h/proc
 # rm /mnt/chroot-armv7h/etc/resolv.conf
 # cp -a /etc/resolv.conf /mnt/chroot-armv7h/etc
 # mkdir /mnt/chroot-armv7h/rootfs
 # mount -o bind / /mnt/chroot-armv7h/rootfs
 # chroot /mnt/chroot-armv7h /bin/bash
 # mount -o bind /rootfs/mnt/chroot-armv7h /

Configuring chroot

pacman.conf

Make sure signature verification is enabled and the correct architecture is set in /etc/pacman.conf:

pacman.conf
SigLevel    = Required DatabaseOptional

[options]
Architecture = armv7h

With that configuration you have to initialize the pacman keyring to be able to install signed packages:

# pacman-key --init
# pacman-key --populate archlinux
# pacman-key --populate archlinuxarm
# pacman-key --populate parabola
Note: This step can take quite a while, be patient. (see Pacman-Key)

Install development packages

Before continuing, ensure the base-devel group is installed. Packages belonging to this group are not required to be listed as dependencies in PKGBUILD files. Install the "base-devel" group by issuing (as root):

# pacman -S base-devel
Note: Before complaining about missing (make) dependencies, remember that the base group is assumed to be installed on all Parabola systems. The group "base-devel" is assumed to be installed when building with makepkg.
Note: Consult the #Pacman_and_certificates troubleshooting section if you run into certificate issues.

Generating locales

Before a locale can be enabled on the system, it has to be generated. The current generated/available locales can be viewed with:

$ locale -a

The locales that can be generated are listed in the /etc/locale.gen file: their names are defined using the format [language][_TERRITORY][.CODESET][@modifier]. To generate a locale, first uncomment the corresponding line in the file (or comment to remove); when doing this, also consider localizations needed by other users on the system and specific variables. For example, for American-English uncomment en_US.UTF-8 UTF-8. When done, save the file and generate the uncommented locale(s) by executing:

# locale-gen
Note: locale-gen also runs with every update of glibc.

Makepkg configuration

Packager information

Each package is tagged with metadata identifying amongst others also the packager. By default, user-compiled packages are marked with Unknown Packager. If multiple users will be compiling packages on a system, or you are otherwise distributing your packages to other users, it is convenient to provide real contact. This can be done by setting the PACKAGER variable in makepkg.conf.

To check this on an installed package:

# pacman -Qi package
[...]
Packager       : John Doe <john@doe.com>
[...]

MAKEFLAGS

The MAKEFLAGS option in makepkg.conf can be used to specify additional options for make. Users with multi-core/multi-processor systems can specify the number of jobs to run simultaneously to speed up compilation. This can be accomplished with the use of nproc to determine the number of available processors, e.g. MAKEFLAGS="-j$(nproc)". Some PKGBUILDs specifically override this with -j1, because of race conditions in certain versions or simply because it is not supported in the first place.

See man make for a complete list of available options.

Add a user

Finally, add a normal user (eg. username)

# useradd -m username
Note: It will be needed to build packages with makepkg command

Build package

Just put your folder package with the PKGBUILD and patches, enter into it and type just makepkg

 # su username
 $ cd your-package
 $ makepkg -L

It's recommended that you consult makepkg's options, they may be very useful to frequent package builders.

Signature checking

If a signature file in the form of .sig is part of the PKGBUILD source array, makepkg validates the authenticity of source files. For example, the signature pkgname-pkgver.tar.gz.sig is used to check the integrity of the file pkgname-pkgver.tar.gz with the gpg program.

If desired, signatures by other developers can be manually added to the GPG keyring. See GnuPG article for details. To temporarily disable signature checking, call the makepkg command with the --skippgpcheck option.

Note: The signature checking implemented in makepkg does not use pacman's keyring, relying on the user's keyring and the validpgpkeys() array instead. [1]

To show the current list of GPG keys, use the gpg command:

$ gpg --list-keys

If the pubring.gpg file does not exist, it will be created for you immediately.

The GPG keys are expected to be stored in the user's ~/.gnupg/pubring.gpg file. In case it does not contain the given signature, makepkg will abort the installation:

$ makepkg -L
[...]
==> Verifying source file signatures with gpg...
pkgname-pkgver.tar.gz ... FAILED (unknown public key 1234567890)
==> ERROR: One or more PGP signatures could not be verified!

Make sure that a keyserver is configured in gpg.conf, for example:

~/.gnupg/gpg.conf
keyserver hkp://keys.gnupg.net

To import the key from the server, use:

$ gpg --recv-keys 1234567890

Or to automate:

~/.gnupg/gpg.conf
keyserver-options auto-key-retrieve

Missing dependencies

If there are missing dependencies, just go back to root and install them, eg.

 $ exit
 # pacman -S --asdeps $pkgname
 # su username
 $ cd your-package
 $ makepkg -L

Troubleshooting

Pacman and certificates

If you have issues to install packages like:

 error: failed retrieving file 'bc-1.06.95-1.1-armv7h.pkg.tar.xz' from repo.parabola.nu : error setting certificate verify locations:
   CAfile: /etc/ssl/certs/ca-certificates.crt
   CApath: none
 warning: failed to retrieve some files
 error: failed to commit transaction (download library error)
 Errors occurred, no packages were upgraded.

Try copying the needed files from your real machine:

 # sudo cp -a /etc/ssl/certs/ca-certificates.crt /mnt/chroot-armv7h/etc/ssl/certs/
 # sudo cp -a /etc/ca-certificates/extracted/tls-ca-bundle.pem /mnt/chroot-armv7h/etc/ca-certificates/extracted/

That or switch to an HTTP (not HTTPS) mirror in /etc/pacman.d/mirrorlist.