Building armv7h packages on a x86 system
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.
Contents
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/
# 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
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
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
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
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
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
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.
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.