System requirements
Building a Day app requires Rust and the SDK or development libraries for each target.
The requirements below are grouped by development host and target platform. day doctor can
check the installed tools and report what is missing.
Check with day doctor
day doctor checks your development host for installed toolchains and reports missing
requirements with setup guidance. The sections below describe the tools needed by each target.
day doctor # every toolkit buildable on this host
day doctor --toolkit android # focus one toolkit, with full setup instructions
Bare day doctor treats a missing toolkit as a warning and exits 0, because you only need the
toolkits you build for. Naming a toolkit with --toolkit turns its misses into errors and prints
that toolkit’s setup text. For a full check, day doctor verify scaffolds a throwaway app and builds
(and packs) it for each target; see CLI & projects.
For build errors or device connection problems, see Troubleshooting.
Every host
| What | Version | Where |
|---|---|---|
| Rust | 1.89 or newer | rustup.rs |
The day CLI | from the Day Git repository | Getting started |
| Git | any | git-scm.com |
Install Rust through rustup, not Homebrew or a distro package. Cross-compiled targets (iOS,
Android, HarmonyOS, and the web) need rustup’s per-target standard library, which a system rustc
does not carry. day build adds the one a target needs the first time it builds for it
(rustup target add …, said on the terminal as it happens), so the rustup target add lines
in the sections below are for doing that ahead of time, on a machine that will be offline or in
a CI image. rustup update stable keeps you current.
Everything else depends on which targets you build.
Which targets build on which host
| Target | macOS | Linux | Windows |
|---|---|---|---|
macos-appkit | ✅ | — | — |
ios-uikit | ✅ | — | — |
windows-winui | — | — | ✅ |
windows-xaml (deprecated) | — | — | ✅ |
linux-gtk / windows-gtk / macos-gtk | ✅ | ✅ | ✅ |
linux-qt / windows-qt / macos-qt | ✅ | ✅ | ✅ |
android-mdc | ✅ | ✅ | ✅ |
harmony-arkui | ✅ | ✅ | ✅ |
web-dom | ✅ | ✅ | ✅ |
Apple’s toolkits build only on macOS, and WinUI and XAML only on Windows, because they compile
against SDKs that exist only on the host OS. GTK and Qt are portable, so a macOS or Windows machine can build and
run them for development even though you ship linux-gtk and linux-qt.
macOS
macOS and iOS app builds require Xcode 27 or newer. Your macOS version must support
that Xcode release; check
Apple’s minimum requirements if you are on an older
release. Continuous integration builds on the current macos-latest runner (Apple silicon).
The GTK, Qt, Android, and web targets need Apple’s command-line development tools on macOS:
xcode-select --install
Full Xcode 27 or newer (App Store) is required for
macos-appkit and ios-uikit, whose builds run through xcodebuild. Point the command-line tools at it once
installed:
sudo xcode-select -s /Applications/Xcode.app
rustup target add aarch64-apple-ios-sim
Day derives build/day/xcode/macos/DayApp.xcodeproj unless an app supplies its own
platform/macos/DayApp.xcodeproj. macos-appkit builds through
xcodebuild, so it needs full Xcode 27 or newer too. (An app that predates the scaffold adopts it with
day project add-target macos-appkit.)
Both hosts use the JSON5 project.xcproj format introduced in Xcode 27.
day doctor --toolkit appkit --toolkit uikit checks the selected installation.
Homebrew provides the rest:
brew install gtk4 libadwaita librsvg pkg-config # macos-gtk
brew install qt pkg-config # macos-qt
brew install openjdk@21 # android-mdc
brew install qemu # the HarmonyOS emulator
Swift is needed only when a dependency embeds SwiftUI (SwiftUI embedding); Xcode and the command-line tools both provide it.
Windows
windows-winui builds on Windows 10 or 11. It renders WinUI 3 from the Windows App SDK 2.5.1;
see the Windows platform page for the details.
For windows-winui, install the
Visual Studio 2022 C++ Build Tools (MSVC plus the
Windows 10/11 SDK) and the MSVC Rust toolchain:
rustup default stable-msvc
Development builds (day build, day launch) also need the Windows App Runtime 2.5.1 or
newer, from Microsoft’s Windows App SDK
downloads; an app started
without it offers that page. The Windows App SDK packages themselves need no install: the build
downloads them on first use (about 270 MB) into %LOCALAPPDATA%\day\winappsdk. Set
DAY_WINAPPSDK to an already laid-out copy on an offline machine, or DAY_WINAPPSDK_CACHE to move
the cache. day doctor --toolkit winui checks the toolchain and the runtime.
A packed app is self-contained: the runtime travels inside the .msix and the installer, so your
users install nothing extra. The deprecated windows-xaml target needs the same Build Tools and
toolchain but no Windows App Runtime, since it uses the XAML that ships in Windows.
For windows-qt and windows-gtk, install MSYS2 and build with a GNU
Rust toolchain, because MSVC cannot link MSYS2’s import libraries, and the C++ shims are built
from pkg-config’s flags, which an online-installer Qt does not ship:
# Qt: run in the MINGW64 shell
pacman -S mingw-w64-x86_64-qt6-base mingw-w64-x86_64-qt6-svg
# GTK: run in the UCRT64 shell
pacman -S mingw-w64-ucrt-x86_64-gtk4 mingw-w64-ucrt-x86_64-libadwaita mingw-w64-ucrt-x86_64-librsvg
rustup toolchain install stable-x86_64-pc-windows-gnu
On ARM64 hosts, use the CLANGARM64 environment’s mingw-w64-clang-aarch64- packages and the
stable-aarch64-pc-windows-gnullvm toolchain. Build with MSYS2’s bin on PATH and
RUSTUP_TOOLCHAIN set to the GNU toolchain; the
Windows page walks through it.
Linux
Day’s minimums are library versions: GTK 4.10 with libadwaita 1.5, and Qt 6. Any distribution whose repositories carry those development packages works. Continuous integration builds on Ubuntu 24.04.
Native vector rendering also requires librsvg 2.52+ development files for GTK and
Qt SVG development files for Qt. day doctor checks these build dependencies.
# Debian / Ubuntu
sudo apt install libgtk-4-dev libadwaita-1-dev librsvg2-dev pkg-config # linux-gtk
sudo apt install qt6-base-dev qt6-svg-dev pkg-config # linux-qt
sudo apt install qemu-system-x86 qemu-system-gui unzip # harmony-arkui (emulator)
The GTK minimums are hard requirements. Day builds stack navigation on AdwNavigationView, and
its file and alert dialogs on GtkFileDialog and GtkAlertDialog; none of those exist in earlier
releases. Debian 12 ships GTK 4.8 and cannot build linux-gtk; run -p linux-qt there, which needs only Qt 6, or build against a newer runtime. day doctor reports the
installed versions against these minimums, so run it first; a version miss otherwise surfaces as a
build failure inside gdk4-sys.
Fedora, Arch, and openSUSE ship the same libraries under different package names; check GTK’s installation page and Qt’s for the equivalents.
Day finds both toolkits through pkg-config, so it is required.
Optional: web views
The web view piece needs one extra development package on the Linux desktop toolkits. Without it the piece compiles out and renders a placeholder; the rest of the app is unaffected.
| Toolkit | Package | Engine |
|---|---|---|
| GTK | libwebkitgtk-6.0-dev (Debian/Ubuntu), mingw-w64-x86_64-webkitgtk6 (MSYS2) | WebKitGTK 6 |
| Qt | qt6-webengine-dev (Debian/Ubuntu) | Qt WebEngine |
Two toolkit combinations have no web view package. Homebrew’s webkitgtk vends the GTK 3
API and has no bottle, so macos-gtk builds without a web view. MSYS2 ships no Qt 6 WebEngine, so
windows-qt does too.
Optional: media playback
The media piece plays through GStreamer on the
Linux GTK target (GtkVideo). The build needs nothing extra, but playback needs GTK’s
GStreamer module and a decoder for each format. Without a decoder the player stays a blank black
rectangle rather than showing an error.
# Debian / Ubuntu
sudo apt install libgtk-4-media-gstreamer gstreamer1.0-plugins-good gstreamer1.0-libav
gstreamer1.0-plugins-good reads MP4 and streams over HTTPS (qtdemux, souphttpsrc), and
gstreamer1.0-libav decodes H.264 video and AAC audio, which is what most MP4 files carry;
Ubuntu’s desktop install does not include it. To check a particular file or URL, run
gst-discoverer-1.0 <url>: any “Missing plugins” it lists is what the player lacks.
Optional: sound effects
day-part-sound plays through libpulse on the Linux desktop toolkits,
which reaches both PulseAudio and PipeWire. The build needs nothing extra. At run time the part
loads libpulse-simple.so.0, which a desktop install already has. A minimal container or CI
image may need it installed; without it the app runs and stays silent.
sudo apt install libpulse0 # Debian / Ubuntu
sudo dnf install pulseaudio-libs # Fedora
Optional: packaging tools
These are needed only to produce an installable artifact with day pack. Packaging &
distribution covers the formats themselves.
| Target | Tool | Install |
|---|---|---|
linux-gtk, linux-qt | flatpak-builder | flatpak.org, plus the Flathub remote |
linux-gtk, linux-qt | linuxdeploy and its GTK or Qt plugin | linuxdeploy releases |
windows-winui, windows-xaml | makeappx, signtool | the Windows 10/11 SDK (installed with the Build Tools) |
windows-winui, windows-xaml | makensis | NSIS, or choco install nsis |
Without the linuxdeploy GTK or Qt plugin an AppImage still builds, but it will only run on a
machine that already has the toolkit installed.
Android
Android cross-compiles the app to a JNI shared library and runs it inside a Gradle app, so it needs the Android SDK, an NDK, and a JDK regardless of which host you are on.
- Install the Android SDK, using
Android Studio, or the standalone
command-line tools. Day finds it at the platform default
(
~/Library/Android/sdkon macOS,%LOCALAPPDATA%\Android\Sdkon Windows,~/Android/Sdkon Linux). If you moved it in Android Studio’s settings, Day reads the new location from there. SetANDROID_HOMEto override either. - Install an NDK. Android Studio’s SDK Manager does not install one by default: open
Settings ▸ Languages & Frameworks ▸ Android SDK ▸ SDK Tools and check NDK (Side by side).
Without Studio, run
sdkmanager --install "ndk;<version>". Studio does not putsdkmanageronPATH: it lives at<sdk>/cmdline-tools/latest/bin/sdkmanageronce the Android SDK Command-line Tools package (also under SDK Tools) is installed. Day uses the newest NDK under<sdk>/ndkunlessANDROID_NDK_HOMEsays otherwise. - You need a JDK, version 17 or newer. If Android Studio is installed, you already have one:
when
JAVA_HOMEis unset, Day builds with Studio’s bundled JDK, the one Studio runs Gradle with. That also sidesteps a systemjavanewer than Gradle supports. Day finds Studio in its standard install locations (the macOS app bundle, the Windows installer’s directory, and on Linux the Snap,/opt/android-studio,~/android-studio, JetBrains Toolbox or Flathub). SetANDROID_STUDIO_HOMEfor anywhere else. Without Studio, install a JDK (brew install openjdk@21, or Adoptium) and setJAVA_HOMEif thejavaon yourPATHis older than 17.
day doctor shows what it found for each of these, including which Android Studio it is using.
4. Add the Rust target and cargo-ndk:
rustup target add aarch64-linux-android # arm64 device or emulator
rustup target add x86_64-linux-android # x86_64 emulator
cargo install cargo-ndk
To open, build, or run the app from Android Studio, use Android Studio 2026.1.4 (Quail 4) or
newer. Day’s Gradle plugin builds with the Android Gradle Plugin 9.4, and Android Studio syncs
only the AGP versions it supports. day build and day launch run Gradle themselves, so they work
with any Android Studio release.
Setting up an emulator
Create an AVD in Android Studio’s Device Manager, or with avdmanager create avd, then start
it:
emulator -avd <name>
adb devices # confirm it is listed as `device`
Day can list existing AVDs with day devices list -t android-mdc and start one with
day devices boot -t android-mdc AVD_NAME --wait. An AVD stays listed after its system image is
removed, so day devices boot checks the image first and names the package to reinstall. See
Android troubleshooting if it is not detected. Match the emulator’s ABI to an installed Rust target; an x86_64 system image needs
x86_64-linux-android. Set ANDROID_SERIAL when more than one device or emulator is attached, so
day launch and day drive act on the one you mean.
A booted emulator is needed only to run an app.
iOS
ios-uikit builds on a macOS host with full Xcode 27 or newer, as covered above. Xcode installs one iOS
simulator runtime; add others from Xcode’s settings under Platforms (or Components, depending
on your Xcode version); Apple documents the flow in
Installing additional simulator runtimes.
xcrun simctl list devices # what exists, and what is booted
xcrun simctl boot "iPhone 16 Pro" # or open Simulator.app
day launch -t ios-uikit installs into a booted simulator, so boot one first. Apps ship to a
physical device through Xcode’s normal signing setup.
HarmonyOS
HarmonyOS has two halves with different tool needs, which is why a partial install is common. The HarmonyOS platform page has the detail.
-
The Rust cross-compile runs through
cargo-ohos, which finds the OpenHarmony SDK’snativecomponent (the NDK) and sets up the cross-compiler for cargo. Install it, download the SDK, and add the targets:cargo install --locked cargo-ohos # or: cargo binstall cargo-ohos cargo ohos init sdk --api 18 # the public SDK, no account needed rustup target add aarch64-unknown-linux-ohos x86_64-unknown-linux-ohosAn SDK you already have works too: point
OHOS_SDK_NATIVEat itsnativedirectory. -
Packaging the
.hapneedshvigorandohpm, which are not part of the public SDK. They ship with the OpenHarmony command-line-tools, bundled with DevEco Studio or downloadable on their own without an account. Put theirbin/directory onPATH. hvigor builds against the SDK named byOHOS_BASE_SDK_HOME, which must use the versioned layout<dir>/<api>/…. The download above already has it:cargo ohos init sdkprints the SDK’s path, and its<version>/<host>directory is the value. -
Signing runs Day’s
sign-hap.mjsundernode, sonodemust be onPATHtoo.
hdc, which installs and launches the app, sits in the SDK’s toolchains/ directory, beside
native/; Day finds it there or on PATH.
On Linux
The Linux command-line-tools bundle carries everything above: hvigor, ohpm, a bundled node, and
an API 18 OpenHarmony SDK (native, ets, toolchains with hdc and the signing material)
whose tools run natively on a Linux x86_64 host. So one download covers the whole build, with no
separate SDK. It needs about 2.1 GB to download and 6.5 GB unpacked:
mkdir -p ~/ohos-clt && cd ~/ohos-clt
curl -fSLO https://repo.huaweicloud.com/harmonyos/ohpm/5.1.0/commandline-tools-linux-x64-5.1.0.840.zip
unzip -q commandline-tools-linux-x64-5.1.0.840.zip && rm commandline-tools-linux-x64-5.1.0.840.zip
# hvigor wants a versioned SDK layout; link the bundled SDK in as API 18.
mkdir -p ~/ohos/sdk
ln -sfn ~/ohos-clt/command-line-tools/sdk/default/openharmony ~/ohos/sdk/18
Then add these to your shell profile:
export OHOS_CLT=$HOME/ohos-clt/command-line-tools
export OHOS_SDK_NATIVE=$OHOS_CLT/sdk/default/openharmony/native
export OHOS_BASE_SDK_HOME=$HOME/ohos/sdk
export PATH=$OHOS_CLT/bin:$OHOS_CLT/tool/node/bin:$OHOS_CLT/sdk/default/openharmony/toolchains:$PATH
The bundle’s bin/hvigorw and bin/ohpm run as-is on Linux, using the bundle’s own node, and
tool/node/bin puts that node on PATH for signing, so no separate node install is needed. The
node wrapper scripts in the HarmonyOS notes are only for macOS. day doctor --toolkit harmonyos should now pass every check.
On macOS
Use the same Linux command-line-tools bundle for hvigor and ohpm, which are pure JavaScript,
through the node wrappers in the HarmonyOS notes. The bundle’s SDK
tools are Linux binaries, though, so hvigor fails with spawn ENOEXEC. Take the SDK from
cargo ohos init sdk --api 18 instead: it is the macOS public SDK in the layout hvigor wants, so
cargo ohos finds its NDK by itself, hdc sits in its toolchains/, and OHOS_BASE_SDK_HOME is
the <version>/darwin directory the download prints.
Setting up the Oniro emulator
Day runs the Oniro OpenHarmony emulator directly under QEMU, from a
public image download. You need qemu-system-x86_64 (on Linux your distribution’s, with its
display modules: sudo apt install qemu-system-x86 qemu-system-gui; on macOS brew install qemu)
and about 7 GB of disk: a 1.4 GB zip that unpacks to 5.5 GB of images. The
zip holds an images/ directory, so unpacking it in ~/ohos/emulator lands the images at the
default location:
mkdir -p ~/ohos/emulator && cd ~/ohos/emulator
curl -fSLO https://github.com/eclipse-oniro4openharmony/device_board_oniro/releases/download/v6.1/oniro_emulator.zip
unzip -q oniro_emulator.zip && rm oniro_emulator.zip # → ~/ohos/emulator/images
day devices boot -t harmony-arkui # --headless for no window
The image comes from the
device_board_oniro releases
(v6.1, OpenHarmony 6.1, is what Day’s CI runs). Set DAY_OHOS_EMULATOR if you keep the images
anywhere other than ~/ohos/emulator/images.
To test on OpenHarmony 7.0, use the x86_64_virt phone package from
harmony-contrib/ohos-qemu instead
(0.7 GB download, 4.7 GB unpacked). day devices boot recognizes its layout by its extra
sys_prod.img and chip_prod.img, so every day command works against either image:
mkdir -p ~/ohos/ohos-qemu && cd ~/ohos/ohos-qemu
curl -fSLO https://github.com/harmony-contrib/ohos-qemu/releases/download/v20260919/openharmony-qemu-x86_64-x86_64_virt-phone.tar.gz
tar xzf openharmony-qemu-x86_64-x86_64_virt-phone.tar.gz
export DAY_OHOS_EMULATOR=~/ohos/ohos-qemu/openharmony-qemu-x86_64-x86_64_virt-phone/images
day devices boot -t harmony-arkui --headless
Apps built for API 18 install and run on 7.0 unchanged. Boot prints which OpenHarmony came up. Boot returns once the guest has finished starting, and QEMU keeps
running in the background; day launch -t harmony-arkui then installs and starts the app on it.
On an x86_64 Linux host, the emulator runs KVM-accelerated when you can open /dev/kvm. That
normally means membership in the kvm group:
sudo usermod -aG kvm $USER # then log out and back in
Without it, Day falls back to TCG software emulation, and boot takes several minutes. The
emulator gets six vCPUs, or as many as the host has cores when that is fewer; set
DAY_OHOS_SMP to override. On macOS the emulator always runs under TCG.
On Linux the emulator window is QEMU’s SDL display, as the Oniro image’s own run.sh opens it, at
the panel --device names (a 360×720 phone unless you say otherwise). That needs your
distribution’s QEMU with its display modules (sudo apt install qemu-system-x86 qemu-system-gui); Homebrew’s QEMU has no SDL display, and day refuses it for a windowed boot. A
panel larger than your screen comes up at the size the window manager allows; --headless keeps
the requested panel. To watch a headless emulator, take screenshots with
hdc shell uitest screenCap -p /data/local/tmp/s.png and hdc file recv /data/local/tmp/s.png.
The x86_64 emulator image carries an arm64-only ArkWeb engine, so the web view piece does not render there. It works on a physical device.
Web
web-dom needs only the wasm target, which the first day build -t web-dom adds; to add it
yourself:
rustup target add wasm32-unknown-unknown
day build -t web-dom writes a self-contained static site, and day launch -t web-dom serves it
and opens a browser.
What your apps require
These are the minimums your users need, which the scaffold sets and you can change in your
project’s platform configuration — up to whatever your code needs, or down as far as the
platform’s own tooling still allows. The iOS value is day-uikit’s own floor: the toolkit guards
the UIKit calls that arrived after iOS 15, and a piece that needs a newer OS declares that
platform floor, which day build applies to the build. They are unrelated to what your
development machine needs.
| Target | Minimum |
|---|---|
macos-appkit | macOS 13 |
ios-uikit | iOS 15 |
android-mdc | API level 24 (Android 7.0), compiled against API 37 |
harmony-arkui | API level 18 |
windows-winui | Windows 10 version 1809 (Windows 11 recommended); packed apps carry the Windows App SDK runtime |
windows-xaml (deprecated) | Windows 10 or 11 |
linux-gtk / linux-qt | GTK 4.10 with libadwaita 1.5 / Qt 6 |
web-dom | a current browser, served as static files |
Check your toolchain
Run day doctor --toolkit <toolkit> before building. It checks the SDK and tool versions for
that backend. The target registry
lists which hosts can build each target.