Hi there,
In an effort to get this project running on my Raspberry Pi 5, I discovered that there are no pre-compiled watchman releases for arm64.
To solve this, I was able to successfully compile from source. This is a very large compile, and I was not able to complete it on my Raspberry Pi 5. A Hetzner VPS with 16 Cores and 32GB luckily did the trick.
Hopefully this helps add support for arm64 in the main install script.
Below is the script I came up with to successfully compile on a fresh install of Ubuntu 22.04. It automatically takes care of everything, and spits out an installable .deb file.
For your convenience, A working pre-compiled package is here: https://tixo.net/proton-drive-sync/watchman_2025.12.29.00_arm64.deb
If you wish to compile yourself:
Compilation Script (For Ubuntu 22.04)
$ bash <(curl -fsSL https://tixo.net/proton-drive-sync/watchman_arm64.sh)
#!/bin/bash
# ==============================================================================
# Watchman Builder & Packager: Standalone Distribution
# ==============================================================================
# This script builds a portable Debian package for Facebook Watchman.
#
# Workflow:
# 1. Downloads the specific release tarball from GitHub.
# 2. Cleans the build environment to ensure dependency compatibility.
# 3. Compiles from source using standard build tools.
# 4. Identifies and bundles necessary shared libraries (Boost, Glog, etc.).
# 5. Patches binaries for RPATH isolation to prevent system conflicts.
# ==============================================================================
set -e
# ==============================================================================
# CONFIGURATION
# ==============================================================================
WATCHMAN_TAG="v2025.12.29.00"
RUST_CHANNEL="stable"
REQUIRED_SPACE_KB=14680064 # ~14GB
# ==============================================================================
# 0. Output Helpers
# ==============================================================================
GREEN='\033[0;32m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m'
log() { echo -e "${BLUE}[INFO]${NC} $1"; }
success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
error() { echo -e "${RED}[ERROR]${NC} $1"; }
# ==============================================================================
# 1. Pre-flight Checks & Cleanup
# ==============================================================================
log "Checking system resources..."
AVAILABLE_SPACE=$(df -k /tmp | awk 'NR==2 {print $4}')
if [ "$AVAILABLE_SPACE" -lt "$REQUIRED_SPACE_KB" ]; then
error "Insufficient disk space in /tmp. Required: 14GB."
exit 1
fi
# CRITICAL: Clean build cache to ensure fresh dependency resolution
log "Cleaning stale dependency caches in /tmp..."
sudo rm -rf /tmp/fbcode_builder_getdeps*
success "Dependency cache cleared."
# ==============================================================================
# 2. System Dependencies
# ==============================================================================
log "Installing build dependencies..."
sudo apt-get update
# patchelf is required for the RPATH isolation step
sudo apt-get install -y \
libbz2-dev liblzma-dev libzstd-dev libboost-all-dev \
libgoogle-glog-dev libgflags-dev libevent-dev \
libdouble-conversion-dev libssl-dev build-essential \
curl tar git libunwind-dev pipx patchelf
# ==============================================================================
# 3. Rust Environment Setup
# ==============================================================================
if [ -f "$HOME/.cargo/env" ]; then source "$HOME/.cargo/env"; fi
if command -v rustc &> /dev/null; then
log "Rust is already installed: $(rustc --version)"
else
log "Installing Rust..."
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain "$RUST_CHANNEL" --profile complete
source "$HOME/.cargo/env"
fi
# ==============================================================================
# 4. Python Tooling (Pex)
# ==============================================================================
export PATH="$PATH:$HOME/.local/bin"
if ! command -v pex &> /dev/null; then
log "Installing pex via pipx..."
pipx install pex
pipx ensurepath
else
log "Pex is already installed."
fi
# ==============================================================================
# 5. Source Code Retrieval
# ==============================================================================
WATCHMAN_DIR="watchman_build"
TARBALL_URL="https://github.com/facebook/watchman/archive/refs/tags/${WATCHMAN_TAG}.tar.gz"
if [ -d "$WATCHMAN_DIR" ]; then
log "Cleaning up old build directory..."
rm -rf "$WATCHMAN_DIR"
fi
mkdir -p "$WATCHMAN_DIR"
log "Downloading source release: $WATCHMAN_TAG"
log "URL: $TARBALL_URL"
# Download and extract, stripping the top-level directory (usually watchman-TAG)
curl -L "$TARBALL_URL" | tar -xz -C "$WATCHMAN_DIR" --strip-components=1
cd "$WATCHMAN_DIR"
# === Patch CMakeLists.txt ===
# We directly edit the build definition to force our version.
# We replace: set(WATCHMAN_VERSION_OVERRIDE "" ...
# With: set(WATCHMAN_VERSION_OVERRIDE "2025.12.29.00" ...
VERSION_NUM="${WATCHMAN_TAG#v}"
log "Patching CMakeLists.txt to force version: $VERSION_NUM"
sed -i "s/set(WATCHMAN_VERSION_OVERRIDE \"\"/set(WATCHMAN_VERSION_OVERRIDE \"$VERSION_NUM\"/" CMakeLists.txt
# Also patch the fallback just in case
sed -i "s/set(PACKAGE_VERSION \"0.0.0\")/set(PACKAGE_VERSION \"$VERSION_NUM\")/" CMakeLists.txt
# === FIX END ===
# ==============================================================================
# 6. Patching Build Scripts
# ==============================================================================
log "Patching build/fbcode_builder/getdeps.py..."
# Remove internal pip install command to avoid conflicts with system python
sed -i '/cmd_argss.append(\["pip", "install", "pex"\])/d' build/fbcode_builder/getdeps.py
# ==============================================================================
# 7. Build Execution
# ==============================================================================
log "Running install-system-packages.sh..."
./install-system-packages.sh
log "Running autogen.sh (This will take a while)..."
./autogen.sh
# ==============================================================================
# 8. Standalone Packaging Process
# ==============================================================================
log "Starting Standalone Packaging Process..."
# Set version
VERSION="${WATCHMAN_TAG#v}"
VERSION="${VERSION:-$(date +%Y.%m.%d.00)}"
PKG_NAME="watchman"
ARCH=$(dpkg --print-architecture)
DEB_FILENAME="${PKG_NAME}_${VERSION}_${ARCH}.deb"
WORK_DIR="deb_package"
# 1. Prepare Workspace
rm -rf "$WORK_DIR"
mkdir -p "$WORK_DIR/DEBIAN"
mkdir -p "$WORK_DIR/usr/local/bin"
mkdir -p "$WORK_DIR/usr/local/lib/watchman"
mkdir -p "$WORK_DIR/usr/local/var/run/watchman"
# 2. Copy Binaries
log "Copying compiled binaries..."
if [ -d "built/bin" ]; then
cp -r built/bin/* "$WORK_DIR/usr/local/bin/"
else
error "Build failed: built/bin missing."
exit 1
fi
# 3. Dependency Identification & Bundling
log "Analyzing and bundling non-system dependencies..."
# Filter function: Returns 0 (True) if we should bundle, 1 (False) if Core OS lib
should_bundle() {
local libname="$1"
# Exclude core OS libs: libc, libssl (openssl), libstdc++, libgcc, dynamic linker
if [[ "$libname" =~ libc\.so || "$libname" =~ libstdc\+\+ || "$libname" =~ libgcc_s || \
"$libname" =~ libm\.so || "$libname" =~ libpthread || "$libname" =~ libdl || \
"$libname" =~ ld-linux || "$libname" =~ libssl || "$libname" =~ libcrypto ]]; then
return 1 # False (Do not bundle)
fi
return 0 # True (Bundle)
}
# Identify dependencies via ldd
DEPENDENCIES=$(ldd built/bin/watchman | awk '{print $3}' | grep "^/")
# Include libraries built by Watchman itself (e.g. libfolly, libfizz)
for f in built/lib/*.so*; do
if [ -f "$f" ]; then cp "$f" "$WORK_DIR/usr/local/lib/watchman/"; fi
done
# Include necessary system libraries (e.g. libboost, libglog)
for dep_path in $DEPENDENCIES; do
lib_name=$(basename "$dep_path")
if should_bundle "$lib_name"; then
echo " [BUNDLE] $lib_name"
cp "$dep_path" "$WORK_DIR/usr/local/lib/watchman/"
else
echo " [SYSTEM] $lib_name (Skipping)"
fi
done
# 4. Portability Sanitization (RPATH & Absolute Paths)
log "Applying RPATH isolation and sanitizing absolute paths..."
patch_file() {
local file="$1"
local is_bin="$2"
# A. Strip absolute paths (ensure linkage uses relative names)
patchelf --print-needed "$file" | grep "/" | while read -r bad_dep; do
clean_dep=$(basename "$bad_dep")
patchelf --replace-needed "$bad_dep" "$clean_dep" "$file"
done
# B. Set RPATH to look in the bundled directory
if [ "$is_bin" -eq 1 ]; then
patchelf --set-rpath '$ORIGIN/../lib/watchman' "$file"
else
patchelf --set-rpath '$ORIGIN' "$file"
fi
}
# Patch Binaries
patch_file "$WORK_DIR/usr/local/bin/watchman" 1
patch_file "$WORK_DIR/usr/local/bin/watchmanctl" 1
# Patch Libraries
for lib in "$WORK_DIR/usr/local/lib/watchman"/*.so*; do
patch_file "$lib" 0
done
# 5. Create Control File
# Note: Depends on libssl3 (runtime) instead of libssl-dev (headers)
cat <<EOF > "$WORK_DIR/DEBIAN/control"
Package: $PKG_NAME
Version: $VERSION
Architecture: $ARCH
Maintainer: Admin <admin@localhost>
Depends: libc6, libstdc++6, libgcc-s1, libssl3
Section: utils
Priority: optional
Description: Watchman (Standalone)
Facebook's Watchman, compiled for Ubuntu 22.04.
This package is self-contained and includes private versions of
necessary libraries (Boost, Glog, Folly, etc.) to ensure
portability and prevent system conflicts.
EOF
# 6. Post-Install Script
cat <<EOF > "$WORK_DIR/DEBIAN/postinst"
#!/bin/sh
set -e
mkdir -p /usr/local/var/run/watchman
chmod 2777 /usr/local/var/run/watchman
exit 0
EOF
chmod 755 "$WORK_DIR/DEBIAN/postinst"
# 7. Build Package
log "Building .deb package..."
dpkg-deb --build "$WORK_DIR" "../$DEB_FILENAME"
rm -rf "$WORK_DIR"
echo ""
echo "----------------------------------------------------"
success "Standalone Package created: $(dirname $(pwd))/$DEB_FILENAME"
echo "----------------------------------------------------"
Hi there,
In an effort to get this project running on my Raspberry Pi 5, I discovered that there are no pre-compiled watchman releases for arm64.
To solve this, I was able to successfully compile from source. This is a very large compile, and I was not able to complete it on my Raspberry Pi 5. A Hetzner VPS with 16 Cores and 32GB luckily did the trick.
Hopefully this helps add support for arm64 in the main install script.
Below is the script I came up with to successfully compile on a fresh install of Ubuntu 22.04. It automatically takes care of everything, and spits out an installable .deb file.
For your convenience, A working pre-compiled package is here: https://tixo.net/proton-drive-sync/watchman_2025.12.29.00_arm64.deb
If you wish to compile yourself:
Compilation Script (For Ubuntu 22.04)