Tomacco

Docs Linux & hardware

Linux distributions and hardware#

Tomacco is developed and tested on one Arch Linux (Omarchy) workstation with an AMD graphics card. This page says what has run elsewhere, what tomaccoctl doctor reports about the computer it runs on, and what is known about other kinds of hosts. Anything not listed as run here has not been tried.

On this page (10)

What ran where#

For 1.2.1, in clean containers on 2026-11-01:

ImageInstallertomaccoctl doctor and capabilitiesJDK from the distributionAndroid starter build
debian:12Installed the portable packageRanopenjdk-17-jdk-headless (17.0.21)Succeeded, APK built
debian:13Installed the portable packageRanopenjdk-21-jdk-headless (21.0.13)Succeeded, APK built
ubuntu:24.04Installed the portable packageRanopenjdk-21-jdk-headless (21.0.12.1)Succeeded, APK built
fedora:44Installed the portable packageRanjava-25-openjdk-devel (25.0.4.1)Succeeded, APK built
opensuse/tumbleweedInstalled the portable packageRanjava-21-openjdk-devel (21.0.13)Succeeded, APK built

How it ran:

Earlier, tools/build_portable.py verify ran the portable desktop offscreen and on Xvfb in Debian 12, Ubuntu 22.04, Ubuntu 24.04 and Fedora 44 containers; see Getting started. No real desktop of these distributions has been tried.

What doctor says about the computer#

tomaccoctl doctor has a host entry:

KeyWhat it holds
distributionid, name, version, family (arch, debian, fedora, suse, nixos or other), immutable (steamos, ostree, nixos, read-only-usr or null) and container (toolbox, distrobox, podman, docker or null)
kvmstatus, a message and the commands that fix it on this system; also copied into doctor's kvm
emulator_gpuThe graphics cards and drivers found, the session (wayland, x11 or none), whether the emulator's window can open (window), the recommended renderer with its reason, and notes
resourcesMemory, processors and free space in the home directory, the smaller emulator settings a small computer gets, and whether the virtual iPhone fits
installThe command that installs a JDK here, and where Gradle 9 comes from

next_steps and tomaccoctl setup use it: the JDK step names this distribution's package instead of Arch's, and a KVM step with these commands appears while /dev/kvm is not usable.

The verdicts are tested with made-up machines in native/host.rs. On the development host (Omarchy, Intel and AMD graphics, Wayland with XWayland) doctor reported KVM ready and the auto renderer. A static build of this code ran doctor in debian:12, ubuntu:24.04, fedora:44 and opensuse/tumbleweed containers and in the SteamOS-like and nixos/nix containers described below: each named its distribution and JDK package (the nixos/nix image has no /etc/os-release, so it got the general advice), not_in_container for KVM, and swiftshader, since no /dev/dri was passed in. In debian:12 with /dev/kvm passed in and limited to its group, kvm.status was not_in_group, then log_in_again after usermod in the same session, then ready in a new login.

KVM#

The Android emulator needs /dev/kvm to run at a usable speed. kvm.status says why it is not usable:

statusMeaningCommands it gives
ready/dev/kvm opens. In a virtual machine (virtual_machine true) the emulator runs on nested virtualization, slower.None
module_not_loadedThe processor has VT-x or AMD-V but there is no /dev/kvm.sudo modprobe kvm_intel or kvm_amd
virtualization_offThe processor does not report VT-x or AMD-V.Turn it on in the firmware settings
nested_virtualization_offA virtual machine whose processor offers no VT-x or AMD-V.libvirt host-passthrough, VirtualBox --nested-hw-virt on, Hyper-V ExposeVirtualizationExtensions
not_in_containerA Docker or Podman container started without the device.docker run --device /dev/kvm ...
not_in_group/dev/kvm belongs to a group you are not in.sudo usermod -aG kvm USER, then log in again; per system, below
log_in_againYou were added to the group after this session started.Log out and in, or newgrp kvm for one terminal
no_group_access/dev/kvm is owned by root only.A udev rule giving the kvm group access, then the group

For not_in_group, on Fedora's ostree systems (Silverblue, Kinoite, Bazzite) the kvm group is only in /usr/lib/group, where usermod cannot change it, so the commands first copy its line into /etc/group. On NixOS they name users.users.USER.extraGroups in configuration.nix and nixos-rebuild switch. On SteamOS they say to set a password with passwd first, which sudo needs. None of these commands was run on those systems.

The emulator's window and renderer#

The Android emulator's own Qt has only the X11 (xcb) platform plugin; emulator 37.2.12 ships libqxcbAndroidEmu.so and no Wayland plugin. On the development host it aborted with "Could not find the Qt platform plugin wayland" when QT_QPA_PLATFORM was wayland, and aborted when neither DISPLAY nor WAYLAND_DISPLAY was set. Now:

The renderer: an AVD keeps the emulator's auto mode unless you chose one. auto lets the emulator test the host's OpenGL and fall back to software rendering by itself. Where doctor finds no hardware graphics driver (no card under /sys/class/drm, only a virtual machine's display adapter, or no render node in /dev/dri without NVIDIA's driver), a start with gpu configured passes -gpu swiftshader, and the start's result has gpu with source host and the reason. The modes emulator 37.2.12 lists are auto, host, software, lavapipe, swiftshader and swangle; older guides' swiftshader_indirect is not among them.

To choose yourself, pass gpu to android.avd_start for one start, or save it with android.avd_configure; a saved choice is kept and never replaced by the host's. Only the AMD development host has run the emulator; NVIDIA, Intel-only and virtual machine graphics have not.

Small computers#

HostNew emulators get
Less than 6 GiB of memory1536 MB of memory
6 to 10 GiB of memory2048 MB of memory
At most 4 processorsHalf of them, at least one

android.avd_profile, which android.avd_create runs, lowers the emulator's memory and processors to these and lists what it changed in adapted_to_host. Values set with android.avd_configure are kept. doctor's resources.emulator.notes say so, and also warn under 4 GiB of memory and with less than 16 GiB free in the home directory: the SDK download is about 5 GB, and an emulator's data partition may grow to 10 GB.

ios.virtual.start is refused with ios_virtual_host_too_small on a host that is not x86_64 or has less than 12 GiB of memory: the guest takes 8 GiB and its translated code up to 2 GiB more. ios.virtual.host_check gives the full picture.

Immutable and atomic systems#

Fedora Silverblue, Kinoite and Bazzite#

There is no pacman, so the installer takes the portable package and installs it into ~/.local, as on any other distribution. It needs python3 and openssl on the host; whether a given image has them was not checked. Development tools belong in a toolbox or distrobox container, and doctor's JDK advice says so: toolbox create, toolbox enter, then sudo dnf install java-25-openjdk-devel on Fedora 44. The container shares your home directory, so ~/.local/bin/tomaccoctl is there inside it too, beside the JDK. The fedora:44 result above is what such a container would do; a real toolbox has not been tried, and neither has the emulator from inside one.

NixOS#

Tomacco's programs, like the Android SDK's own (the emulator, and aapt2, which Gradle downloads), are linked for the standard loader /lib64/ld-linux-x86-64.so.2, which NixOS does not have. In a nixos/nix container, which has no such loader either, the 1.2.1 installer completed, but tomaccoctl could not start: "cannot execute: required file not found". A change to the installer, not yet on tomacco.dev, makes it stop before downloading and say why. NixOS's programs.nix-ld.enable, or running Tomacco in a distrobox container of another distribution, may work around it; neither has been tried. doctor gives NixOS-style commands for the JDK (nix-shell -p jdk21) and the kvm group.

SteamOS and the Steam Deck#

SteamOS is based on Arch and has pacman, but its root file system is read-only. The 1.2.1 installer takes it for Arch and asks to install Qt and FFmpeg with sudo pacman, which cannot work there. Without a terminal to ask in, it stops. Until the installer on tomacco.dev changes, install the portable package:

curl -fsSL https://tomacco.dev/install.sh | bash -s -- --portable

In an Arch container with SteamOS's /etc/os-release and a read-only root, the 1.2.1 installer stopped at the pacman step and --portable installed into the home directory. With the installer change that is not yet on tomacco.dev, it installed there without the flag: it notices SteamOS, or any read-only / or /usr, and takes the portable package. tomaccoctl --version and doctor ran afterwards. This was not run on a Steam Deck: its desktop libraries, /dev/kvm and graphics are unchecked. A JDK has to go into the home directory too: unpack one, such as Eclipse Temurin 21, and name it with settings.configure java_home. doctor says the same. The installer prints the line that puts ~/.local/bin on PATH when it is missing.

Containers#

The container image is the supported way to run tomaccoctl in Docker. Inside any container, doctor reports the container, and a missing /dev/kvm as not_in_container with the --device /dev/kvm flag.

View this page as Markdown on GitHub