Back to Handy

Build Instructions

BUILD.md

0.9.48.0 KB
Original Source

Build Instructions

This guide covers how to set up the development environment and build Handy from source across different platforms.

Prerequisites

All Platforms

Platform-Specific Requirements

macOS

  • Xcode Command Line Tools
  • Install with: xcode-select --install
Intel Mac (x86_64)

Prebuilt ONNX Runtime binaries are not available for Intel Macs. Install ONNX Runtime via Homebrew and link dynamically:

bash
brew install onnxruntime
ORT_LIB_LOCATION=$(brew --prefix onnxruntime)/lib ORT_PREFER_DYNAMIC_LINK=1 bun run tauri dev

The same environment variables apply for production builds:

bash
ORT_LIB_LOCATION=$(brew --prefix onnxruntime)/lib ORT_PREFER_DYNAMIC_LINK=1 bun run tauri build

Windows

  • Microsoft C++ Build Tools: Visual Studio 2019/2022 with C++ development tools, or Visual Studio Build Tools 2019/2022

  • CMake (must be on PATH):

    powershell
    winget install Kitware.CMake
    
  • Vulkan SDK from LunarG — required to build the Vulkan GPU backend (vulkan-shaders-gen needs the SDK's headers and glslc):

    powershell
    winget install KhronosGroup.VulkanSDK
    

    Open a new terminal afterward so VULKAN_SDK is set.

[!NOTE] Windows' 260-character path limit used to break the native Vulkan build in most checkouts. Since transcribe-cpp 0.1.3 the build works around it automatically (it compiles through a short NTFS junction — no admin rights or setup needed), so a normal checkout just builds. If you still hit path-limit errors, see Windows build fails with path-limit errors in Troubleshooting.

Linux

  • Build essentials

  • ALSA development libraries

  • Install with:

    bash
    # Ubuntu/Debian
    sudo apt update
    sudo apt install build-essential libasound2-dev pkg-config libssl-dev libvulkan-dev vulkan-tools glslc spirv-headers glslang-tools libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev libgtk-layer-shell0 libgtk-layer-shell-dev patchelf cmake
    
    # Fedora/RHEL
    sudo dnf groupinstall "Development Tools"
    sudo dnf install alsa-lib-devel pkgconf openssl-devel vulkan-devel \
      spirv-headers-devel spirv-tools-devel glslang glslc \
      gtk3-devel webkit2gtk4.1-devel libappindicator-gtk3-devel librsvg2-devel \
      gtk-layer-shell gtk-layer-shell-devel \
      cmake
    
    # Arch Linux
    sudo pacman -S base-devel alsa-lib pkgconf openssl vulkan-devel \
      spirv-headers glslang shaderc \
      gtk3 webkit2gtk-4.1 libappindicator-gtk3 librsvg gtk-layer-shell \
      cmake
    

Setup Instructions

1. Clone the Repository

bash
git clone [email protected]:cjpais/Handy.git
cd Handy

2. Install Dependencies

bash
bun install

3. Start Dev Server

bash
bun tauri dev

4. Build for Production

bash
bun run tauri build

This compiles a release binary and generates platform-specific bundles (deb, rpm, AppImage on Linux; dmg on macOS; msi on Windows).

Linux Install (from source)

The raw binary (src-tauri/target/release/handy) cannot run standalone — it needs Tauri resource files (tray icons, sounds, VAD model) to be co-located at the expected path.

Install from the deb bundle (works on any Linux distro):

bash
cd /tmp
ar x /path/to/Handy/src-tauri/target/release/bundle/deb/Handy_*_amd64.deb data.tar.gz
tar xzf data.tar.gz
sudo cp usr/bin/handy /usr/bin/
sudo cp -a usr/lib/. /usr/lib/
sudo cp -r usr/share/icons/hicolor/* /usr/share/icons/hicolor/
sudo cp usr/share/applications/Handy.desktop /usr/share/applications/

The runtime libraries live in the app-private /usr/lib/Handy/ (on the binary's rpath), so no ldconfig step is needed.

After subsequent rebuilds, copy the binary and any refreshed runtime libraries:

bash
sudo cp src-tauri/target/release/handy /usr/bin/
sudo mkdir -p /usr/lib/Handy
sudo cp -a src-tauri/transcribe-libs/. /usr/lib/Handy/

Resources only need re-copying if they change upstream (new icons, sounds, models, etc.).

Troubleshooting

AppImage build fails on Arch / rolling-release distros

linuxdeploy bundles its own strip binary which is too old to process system libraries built with newer toolchains on rolling-release distros (Arch, CachyOS, Manjaro, EndeavourOS).

The error from Tauri:

Bundling Handy_*_amd64.AppImage
failed to bundle project `failed to run linuxdeploy`

Tauri swallows the real linuxdeploy error. To see it, run linuxdeploy manually:

bash
cd src-tauri/target/release/bundle/appimage
~/.cache/tauri/linuxdeploy-x86_64.AppImage --appimage-extract-and-run \
  --appdir Handy.AppDir --plugin gtk --output appimage

Workaround: The binary, deb, and rpm bundles all build fine — only the AppImage step fails. To skip it:

bash
bun run tauri build -- --bundles deb

Then install using the deb extraction method above.

Windows build fails with path-limit errors (MSB3491 / FTK1011 / MSB6003)

On Windows the native build can fail partway through transcribe-cpp-sys with any of these (all the same root cause):

error MSB3491: Could not write lines to file "...VCTargetsPath.tlog\VCTargetsPath.lastbuildstate".
Path: ... exceeds the OS max path limit. The fully qualified file name must be less than 260 characters.
FileTracker : error FTK1011: could not create the new file tracking log file:
...\vulkan-shaders-gen-build\...\cmTC_xxxxx.tlog\link.write.1.tlog.
The system cannot find the path specified.
error MSB6003: The specified task executable "CL.exe" could not be run.
System.IO.DirectoryNotFoundException: Could not find a part of the path ...

This is not a code or toolchain problem — it's Windows' legacy 260-character path limit (MAX_PATH), overflowed by the Vulkan shader generator's nested CMake build tree on top of Cargo's already-deep target\release\build\<crate>-<hash>\out\build\... directory.

Since transcribe-cpp 0.1.3 this is mitigated automatically: the native build compiles through a short NTFS junction under %LOCALAPPDATA%\tcs (created without admin rights), so a normal checkout builds with no setup. Enabling Windows long paths does not reliably help here — MSBuild's native FileTracker (tracker.exe) ignores the long-paths flag — which is why the junction, not the registry flag, is the fix.

If you still see the errors above, junction creation was likely blocked (filesystem or corporate policy) — the failing build's log then contains a transcribe-cpp-sys: could not create short build junction ... warning — or your checkout is deep enough to overflow even the shortened layout. Work around either case with a short Cargo target directory:

powershell
# Per-shell:
$env:CARGO_TARGET_DIR = "C:\h"

# Or persist it for all future terminals (note: redirects ALL your
# Rust projects' build output, not just Handy):
[Environment]::SetEnvironmentVariable('CARGO_TARGET_DIR', 'C:\h', 'User')

Artifacts then land in C:\h\release\... instead of the repo's src-tauri\target\. Open a new terminal if you persisted the variable — it is only picked up by freshly started processes. Then bun run tauri dev and bun run tauri build work normally.

Windows tauri build fails at bundling with program not found

If the build compiles all the way to Built application at: ...\handy.exe and then fails with:

Signing C:\...\handy.exe with a custom signing command
failed to bundle project `program not found`

that's the code-signing step: tauri.conf.json configures a custom signCommand (trusted-signing-cli, Azure Trusted Signing) that only exists in the release CI environment. Local development doesn't need it:

powershell
# Development (no bundling/signing at all):
bun run tauri dev

# Or compile a release binary without the installer/signing step:
bun run tauri build --no-bundle