Linux on Mac via UTM

Apple Silicon, UTM, and working with multiarch.

Linux on Mac via UTM

I am a big fan of Windows Subsystem for Linux and it is one of many reasons why I can't quit Windows. But Windows laptops have terrible battery life... it is not even close when compared to the MacBook Pro assigned to me from work. All is not lost; it is possible to have Linux running side-by-side without having to pay expensive license fee for virtualization software. Here are my notes, perhaps you'll find them useful.

Software to Download

Get UTM from here: https://mac.getutm.app/. If you want, you can buy the App Store version for $10 and you get automatic updates in return.

Download UTM images from here: https://mac.getutm.app/gallery/. It is possible to set up a new VM instance from CD image, but this is a faster way to get it done. A recent Ubuntu image is about 3.6GB in download size. Default image RAM size is 4GB and you want to increase that to make it more useful.

Run x86 Binaries on ARM

From time to time you may come across utilities that do not have ARM equivalent. But if you are running Ubuntu Linux then multiple CPU architectures are supported. For example, to run x86-64 executable, you can tell Linux you want packages from a different architecture:

sudo apt install qemu-user-static binfmt-support
sudo dpkg --add-architecture amd64
sudo vi /etc/apt/sources.list.d/amd64.list

Then add the sources in amd64.list

deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-updates main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse
deb [arch=amd64] http://archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse

Once you do that, you can refresh your software list and install x86 ld.so, which is something you need to execute everything in Linux:

sudo apt update
sudo apt install lib6:amd64

The syntax :amd64 allow you to specify the binary architecture you want, and is often the solution to solve incompatibilities. For example, I tried to run a compiler executable and it complained about missing libzstd.so object; the solution is:

sudo apt install libzstd-dev:amd64

Everything your executable depends on, there is a version from Ubuntu you can install to fulfill the dependency.

In Conclusion

Once these packages are installed, you can run x86 executable binaries directly and they'll just work; I was able to compile code with a proprietary SDK that only shipped with x86 toolchain. The performance is generally great, except when heavy disk I/O is involved; that used to take 38 seconds to build on a beefy workstation is now taking 15 minutes from scratch. But you obviously can't lug the workstation around, and remote access may not be possible, especially if the device under test and build machine are at different physical locations and you want to attach gdb.

References