Develop 32bit Applications on 64bit Linux Machines

Overview

Nowadays almost all PC and servers are 64bit. Once in a while one may need to develop and run 32bit apps. In this post we will go through several methods for both x86_64 and ARM64 machines.

I can think of 4 ways of doing this:

  • Run a virtual machine, which in turn runs a 32bit OS. Not covered in this post.
  • Set up 32bit chroot environment. (Recommended)
  • Set up 32bit architecture with Debian multi-arch support (Recommended)
  • Use gcc multi-lib feature to build 32bit binaries.

X86_64/Ubuntu 20.04

Here we go through some detailed steps for those approaches on X86_64/Ubuntu 20.04. Instructions should apply to other Debian-based distributions and different versions as well.

GCC Multi-Lib Approach

Although this is the simplest approach, I don’t recommend it because the GCC support varies for different CPU architectures and the command line options also varies, making it hard to generalize and port existing software. I believe mult-arch is the future direction.

  • Install GCC multi-lib package
sudo apt install gcc-multilib
  • Compile with -m32 option
gcc -m32 hello.c -o hello
file hello
./hello

Multi-Arch Approach

  • Add 32bit as secondary architecture
sudo dpkg --add-architecture i386
  • Install dev tools and 32bit specific dev tools and libraries
sudo apt update
sudo apt install -y build-essential
sudo apt install -y crossbuild-essential-i386
sudo apt install -y libc6:i386
sudo apt install -y libstdc++6:i386
  • Develop 32bit apps with i686-linux-gnu- cross-compile prefix
i686-linux-gnu-gcc hello.c -o hello
file hello
./hello
  • Note for Ubuntu 18.04, crossbuild-essential-i386 meta-package does not exist. One needs to install below packages explicityly
sudo apt install -y dpkg-cross g++-i686-linux-gnu  gcc-i686-linux-gnu

Chroot Approach

For more detailed descriptions, please refer to http://logan.tw/posts/2018/02/24/manage-chroot-environments-with-schroot/

  • Install packages
sudo apt-get install schroot debootstrap
  • Install 32bit environment (e.g., Ubuntu 20.04) (note the last URL arg can be ommited)
sudo debootstrap --arch=i386 focal /var/chroot/focal32 http://archive.ubuntu.com/ubuntu
  • Edit /etc/schroot/schroot.conf file
[focal32]
description=Ubuntu 20.04 Focal Fossil 32bit
directory=/var/chroot/focal32
root-users=ubuntu,jsun
users=ubuntu,jsun
type=directory
personality=linux32
  • Create and enter 32bit chroot session
schroot -c focal32          ; enter as normal user
schroot -c focal32 -u root  ; enter as root user
  • From inside the session, one can install build-essential meta-package and develop 32bit apps as if inside a 32bit machine.
  • (Optional) One can even run 32bit graphic apps from inside the chroot environment.
export DISPLAY=:0.0

ARM64/Ubuntu18.04

ARM64 is also called aarch64. “ARM64” is rooted from Linux community and “aarch64” is official name from ARM. We will use those 2 terms inter-changeably.

Multi-Lib approach

GCC for aarch64 does not support multi-lib. So this option is not available.

Multi-Arch Approach

It is similar to i386 case, except that architecture is “armhf” and 32bit cross-compile prefix is “arm-linux-gunueabihf-“.

sudo dpkg --add-architecture armhf
sudo apt update
sudo apt install -y build-essential
sudo apt install -y crossbuild-essential-armhf
sudo apt install -y libc6:armhf
sudo apt install -y libstdc++6:armhf

arm-linux-gnueabihf-gcc hello.c -o hello
file hello
./hello

Chroot Approach

For chroot approach, it is similar to i386 case, with 2 exceptions:

  • The architecture name is “armhf” instead of “i386”
  • The repo URL is “http://ports.ubuntu.com/ubuntu-ports”, instead of “http://archive.ubuntu.com/ubuntu”

Note we can also set up the root filesystem from debian repos. Below is an example to set up debian sid for armhf 32bit architecture:

  • Install packages and bootstrap root filesystem
sudo apt-get install schroot debootstrap
sudo debootstrap --arch=armhf sid /var/chroot/sid-armhf http://ftp.debian.org/debian/
  • Modify and add to /etc/schroot/schroot.conf file
[sid32]
description=Debian Sid 32bit
directory=/var/chroot/sid-armhf
root-users=ubuntu
users=ubuntu
type=directory
personality=linux32
  • Create and enter sid32 session, “schroot -c sid32”

About MIPS64

  • Multilib works for MIPS64.
    • sudo apt install gcc-multilib g++-multilib
    • compile with -mabi=32 flags, i.e., “gcc -mabi=32 hello.c”
  • Multi-Arch does not work for MIPS64, at least from 32bit app development perspective
  • I have not tried chroot approach on MIPS64 yet. Let me know if you have had any success.

Last Words

  • In Ubuntu chroot environment, the initial apt repo source is limited to main. You may find many packages are missing. To fix this, edit /etc/apt/source.list
deb http://archive.ubuntu.com/ubuntu xenial main universe multiverse