Packaging & Distribution

14.1 Build from source (all platforms)

Use this checklist when you want to compile and share binaries with an alpha tester.

Prerequisites: Set up your development environment first (see §2 Development Environment Setup).

  1. Install Rust (rustup) and ensure the active toolchain uses edition 2021 (or later for edition 2024 support).

  2. Set up dependencies (choose one method from §2):

    • Docker (recommended):

      docker-compose -f docker-compose.dev.yml build  # Build image if needed
      docker-compose -f docker-compose.dev.yml run --rm dev cargo build --release
    • System packages: Follow platform-specific instructions in §2.2

    • Conda: conda activate orbitron-dev and set environment variables (see §2.3)

  3. Build binaries (examples for Docker; adjust paths for other environments):

    # Build all binaries at once
    cargo build --release --workspace
    
    # Or build individually:
    cargo build --release -p orbitron-ui-shell
    cargo build --release -p orbitron-cli --bin orbitron
    cargo build --release -p orbitron-tui --bin orbitron-tui
  4. Artifacts land in target/release/:

    • GUI: target/release/orbitron-viewer (or orbitron-ui-shell)
    • CLI: target/release/orbitron
    • TUI: target/release/orbitron-tui

Note: - Docker users: Environment variables are automatically set (see §2.1). HDF5 1.12.3 is pre-installed and compatible with hdf5-sys 0.8.1. - System packages/Conda users: Ensure HDF5_DIR and related environment variables are set (see §2.2 or §2.3). Verify HDF5 version compatibility with hdf5-sys 0.8.1 (requires HDF5 1.10.x - 1.12.x).

14.2 macOS desktop bundle

Run this after the build-from-source checklist to produce a signed .app (and optional .dmg).

  1. Install the bundler tooling once:

    cargo install cargo-bundle
  2. Ensure the GUI crate exposes a binary target (ui/shell/src/bin/orbitron-viewer.rs) that launches start_ui.

  3. Confirm bundle metadata in ui/shell/Cargo.toml under [package.metadata.bundle].

  4. Get your signing identity:

    security find-identity -v -p codesigning
  5. Build the .app (and optional .dmg):

    # Ensure HDF5_DIR is set (see §2.2 for system packages or §2.3 for conda)
    cargo bundle --release -p orbitron-ui-shell --bin orbitron-viewer
    
    cargo bundle --release -p orbitron-ui-shell --bin orbitron-viewer --format dmg

    Output lands in target/release/bundle/osx/.

  6. Sign, notarize, and staple (recommended sequence). Use the bundle name reported by cargo bundle (typically orbitron-ui-shell.app unless you override it in [package.metadata.bundle]):

    # ensure Resources exists (can be empty)
    mkdir -p target/release/bundle/osx/orbitron-ui-shell.app/Contents/Resources
    
    # sign the app bundle
    codesign --force --deep --options runtime --timestamp \
      --sign "Developer ID Application: YOUR NAME (TEAMID)" \
      target/release/bundle/osx/orbitron-ui-shell.app
    
    # verify signature
    codesign --verify --deep --strict --verbose=2 \
      target/release/bundle/osx/orbitron-ui-shell.app
    
    # create a zip for notarization
    ditto -c -k --keepParent \
      target/release/bundle/osx/orbitron-ui-shell.app \
      orbitron-ui-shell.zip
    
    # submit for notarization (use a keychain profile)
    xcrun notarytool submit orbitron-ui-shell.zip \
      --keychain-profile "notary-orbitron" \
      --wait
    
    # staple the notarization ticket
    xcrun stapler staple target/release/bundle/osx/orbitron-ui-shell.app
    
    # verify Gatekeeper acceptance
    spctl -a -vv target/release/bundle/osx/orbitron-ui-shell.app

    If you see source=Unnotarized Developer ID, the app is signed correctly but has not been notarized/stapled yet. Ensure the notarytool submit ... --wait and stapler staple steps succeed, then re-run spctl. You can also check ticket state with:

    xcrun stapler validate target/release/bundle/osx/orbitron-ui-shell.app

    For a single-command local workflow, use:

    scripts/macos-notarize-app.sh \
      --identity "Developer ID Application: YOUR NAME (TEAMID)" \
      --profile "notary-orbitron" \
      --app target/release/bundle/osx/orbitron-ui-shell.app
  7. Bundle runtime dylibs if the app fails to launch (common with HDF5/OpenSSL):

    APP=target/release/bundle/osx/orbitron-ui-shell.app
    # Set LIBDIR to your HDF5 installation (system packages: $(brew --prefix hdf5)/lib, conda: $CONDA_PREFIX/lib)
    LIBDIR="${HDF5_DIR:-$(brew --prefix hdf5)}/lib"
    FW="$APP/Contents/Frameworks"
    
    mkdir -p "$FW"
    cp "$LIBDIR"/libhdf5*.dylib "$FW/"
    cp "$LIBDIR"/libcrypto.3.dylib "$FW/"
    cp "$LIBDIR"/libssl.3.dylib "$FW/"
    cp "$LIBDIR"/libcurl.4.dylib "$FW/"
    cp "$LIBDIR"/libnghttp2.14.dylib "$FW/"
    cp "$LIBDIR"/libssh2.1.dylib "$FW/"
    cp "$LIBDIR"/libsz.2.dylib "$FW/"
    cp "$LIBDIR"/libz.1.dylib "$FW/"
    cp "$LIBDIR"/libgssapi_krb5.2.2.dylib "$FW/"
    cp "$LIBDIR"/libkrb5.3.3.dylib "$FW/"
    cp "$LIBDIR"/libk5crypto.3.1.dylib "$FW/"
    cp "$LIBDIR"/libcom_err.3.0.dylib "$FW/"
    cp "$LIBDIR"/libkrb5support.1.1.dylib "$FW/"
    
    install_name_tool -add_rpath "@executable_path/../Frameworks" \
      "$APP/Contents/MacOS/orbitron-viewer"
    
    codesign --force --deep --options runtime --timestamp \
      --sign "Developer ID Application: YOUR NAME (TEAMID)" \
      "$APP"

    If another dylib is missing, run otool -L on the failing library, copy the exact versioned dylib from LIBDIR into Contents/Frameworks, then re-sign.

  8. Create the keychain profile once:

    xcrun notarytool store-credentials "notary-orbitron" \
      --apple-id "you@example.com" \
      --team-id "TEAMID" \
      --password "APP_SPECIFIC_PASSWORD"

14.3 Windows installer

  • Install WiX tooling and the Cargo helper:

    cargo install cargo-wix
  • Generate an initial installer manifest (runs once to scaffold wix/main.wxs):

    cargo wix init --bin orbitron-viewer --output wix
  • Build the .msi:

    cargo wix --nocapture --release --bin orbitron-viewer

    The resulting installer lands in target/wix/. Sign with signtool.exe before shipping.

14.4 Linux packages

  • Deb:

    cargo install cargo-deb
    cargo deb --package orbitron-ui-shell --no-build
  • RPM (optional):

    cargo install cargo-rpm
    cargo rpm build --release

    Update Cargo.toml metadata (maintainer, license, post-install scripts) as required by the distribution.

14.5 Precompiled archive binaries

  • Build the desired targets with cargo build --release --target <triple>.

  • Package the artifacts alongside README, LICENSE, and sample config:

    tar czf orbitron-viewer-${VERSION}-${TARGET}.tar.gz \
        -C target/${TARGET}/release orbitron-viewer orbitron-cli README.md LICENSE

    Use .zip archives on Windows for ease of extraction.

  • Publish checksum files (e.g., shasum -a 256 <file>).

Automate the above via CI (GitHub Actions/Gitea runners) using a matrix over macos-latest, windows-latest, and ubuntu-latest. Reuse the same pipelines to upload artifacts to the chosen release host.

14.6 Python Wheels

Python wheels provide the Orbitron API for use in Jupyter notebooks and Python scripts.

Build Script

./scripts/build-python-wheels.sh [OPTIONS]

Options: - --skip-widget - Skip Jupyter widget frontend build - --release - Build with optimizations (default) - --debug - Build without optimizations (faster builds, slower runtime)

Output

dist/python-wheels/
├── orbitron-0.2.0-cp38-abi3-manylinux_2_34_x86_64.whl  # Linux
├── orbitron-0.2.0-cp38-abi3-macosx_11_0_arm64.whl      # macOS Apple Silicon
├── orbitron-0.2.0-cp38-abi3-win_amd64.whl              # Windows
└── README.txt  # Installation instructions
# abi3: one wheel per platform runs on CPython 3.8+. Intel macOS isn't built.

Manual Build

cd extensions/python-bridge

# Build wheel
maturin build --release --features python

# Output in target/wheels/
ls -lh ../../target/wheels/

Platform-Specific Builds

macOS Universal Binary (Intel + Apple Silicon):

maturin build --release --features python --universal2

Linux (manylinux):

# Requires Docker for manylinux compliance
maturin build --release --features python --manylinux 2_34

Windows:

# Build on Windows machine or CI
maturin build --release --features python

Testing Python Wheels

./scripts/test-python-wheel.sh [path/to/wheel.whl]

# Or test latest wheel
./scripts/test-python-wheel.sh

Tests performed: 1. Create clean virtual environment 2. Install wheel 3. Run 6 smoke tests: - Import orbitron module - Create Orbitron instance - Load molecule - Measure distance - Serialize to bytes - Access properties

Troubleshooting Python Wheels

Error: “maturin not found”

pip install maturin

Error: “Could not find HDF5 headers”

# Ensure conda environment is active
conda activate orbitron-dev

# Verify HDF5
conda list | grep hdf5

Error: “Rust compiler version mismatch”

# Project uses Rust 1.92.0 (pinned in rust-toolchain.toml)
rustup show  # Should show 1.92.0

# If wrong version
rustup update
cd /path/to/orbitron  # Let rust-toolchain.toml activate

Wheel platform mismatch:

# Build universal binary for macOS
maturin build --release --features python --universal2

# Check wheel platform tag
ls target/wheels/  # Should show macosx_*_universal2.whl

14.7 WASM Web Viewer

The WASM web viewer provides an interactive 3D molecular viewer for embedding in websites.

Prerequisites

# Install trunk (WASM bundler)
cargo install trunk

# Add WASM target
rustup target add wasm32-unknown-unknown

# Verify
trunk --version  # Should be 0.17+

Build Script

./scripts/build-wasm-viewer.sh

This script: 1. Builds WASM binary using trunk 2. Creates ZIP bundle with all assets 3. Calls standalone HTML builder (see §14.8) 4. Creates README.txt with usage instructions

Output

dist/wasm-viewer/
├── orbitron-viewer-web-v0.2.0.zip  # ZIP bundle (~2-3 MB)
│   └── Contains:
│       ├── index.html
│       ├── orbitron-viewer-wasm_bg.wasm  # WebGPU viewer binary
│       ├── orbitron-viewer-wasm.js       # JavaScript glue code
│       └── README.txt
├── orbitron-viewer-standalone-v0.2.0.html  # Self-contained HTML (~5 MB)
└── README.txt  # Deployment instructions

Manual Build

cd viewer/wasm

# Build with trunk
trunk build --release

# Output in dist/ subdirectory
ls -lh dist/

Customization

Edit viewer/wasm/Trunk.toml to customize: - Output directory - Asset paths - Build hooks - Optimization level

Testing WASM Viewer

ZIP Bundle:

# Extract and serve
cd dist/wasm-viewer
unzip orbitron-viewer-web-v0.2.0.zip
cd orbitron-viewer-web

# Create test molecule
orbitron convert ../../../../io/pipelines/tests/fixtures/xyz/benzene.xyz molecule.bin

# Serve locally
python3 -m http.server 8000

# Open in browser
open http://localhost:8000/index.html?scene=molecule.bin

Manual checks: - [ ] Viewer loads without errors (check browser console) - [ ] Molecule renders correctly - [ ] Rotation, zoom, pan controls work - [ ] Selection works (click atoms) - [ ] No console errors or warnings

Troubleshooting WASM Viewer

Error: “trunk not found”

cargo install trunk
rustup target add wasm32-unknown-unknown

Error: “wasm32-unknown-unknown not installed”

rustup target add wasm32-unknown-unknown

Blank viewer in browser: - Check browser console (F12) for errors - Verify WebGPU support: Run navigator.gpu in console (should not be null) - Check CORS: Serve via HTTP server, not file:// protocol

Large .wasm file size: - Ensure using --release flag (optimized build) - Check Cargo.toml for optimization settings - Expected size: ~2-3 MB for release build

14.8 Standalone HTML Viewer

The standalone HTML embeds the WASM binary as base64 for use in PowerPoint and presentations.

Prerequisites

# macOS/Linux
brew install coreutils  # Provides base64

# Or verify system base64
base64 --version
which base64

Build Script

./scripts/build-wasm-standalone.sh

This script: 1. Builds WASM viewer (if not already built) 2. Reads .wasm binary and converts to base64 3. Embeds base64 into self-contained HTML file 4. Outputs ~5 MB HTML file (WASM ~2 MB → base64 ~3 MB)

Output

dist/wasm-viewer/
└── orbitron-viewer-standalone-v0.2.0.html  # ~5 MB self-contained file

Manual Build

# Ensure WASM viewer is built first
cd viewer/wasm
trunk build --release

# Base64 encode WASM binary
WASM_BASE64=$(base64 -i dist/orbitron-viewer-wasm_bg.wasm)

# Embed in HTML (requires template editing)
# See scripts/build-wasm-standalone.sh for complete implementation

Testing Standalone HTML

cd dist/wasm-viewer

# Create test molecule
orbitron convert ../../../io/pipelines/tests/fixtures/xyz/benzene.xyz molecule.bin

# Open in browser (requires local web server for CORS)
python3 -m http.server 8000 &
open http://localhost:8000/orbitron-viewer-standalone-v0.2.0.html?scene=molecule.bin

PowerPoint test: 1. Open PowerPoint 2. Insert → Object → Browse → Select standalone HTML 3. Resize frame 4. Enter slideshow mode (F5) 5. Verify viewer is interactive

Troubleshooting Standalone HTML

Error: “base64 command not found”

# macOS
brew install coreutils

# Linux
apt-get install coreutils  # or yum install coreutils

# Verify
which base64

Standalone HTML won’t open in PowerPoint: - Security settings: Enable “Trust access to VBA project” in PowerPoint Options - File path length: Move to shorter path (e.g., C:\slides\) - Alternative: Upload to web server and link via URL

File too large (>10 MB): - Expected size: ~5 MB - If larger: Check WASM binary size (~2 MB expected) - Optimization: Ensure trunk used --release flag

14.9 Complete Release Build

To build all distributions at once:

#!/bin/bash
# Complete release build script

set -e  # Exit on error

echo "Building Orbitron v0.2.0 distributions..."

# 1. Clean previous builds
rm -rf dist/
mkdir -p dist

# 2. Build Python wheels
echo "Building Python wheels..."
./scripts/build-python-wheels.sh --skip-widget

# 3. Build WASM viewers
echo "Building WASM viewers..."
./scripts/build-wasm-viewer.sh

# 4. Create release archive
echo "Creating release archive..."
cd dist
tar -czf orbitron-v0.2.0-distributions.tar.gz python-wheels/ wasm-viewer/
cd ..

echo "Build complete!"
echo "Distributions:"
tree -L 2 dist/

14.10 Distribution Sizes

Expected sizes for v0.2.0:

Distribution Size Notes
Python wheel 5-15 MB Varies by platform
WASM ZIP bundle 2-3 MB Compressed
Standalone HTML ~5 MB Includes embedded WASM as base64
Complete tarball 25-50 MB All distributions

14.11 Build Times

Approximate build times on 2020 MacBook Pro (M1):

Task Time Notes
Python wheel (release) 3-5 min First build; incremental ~30s
WASM viewer (release) 2-4 min First build; incremental ~20s
Standalone HTML 10-30s Depends on base64 encoding speed
Complete release 5-10 min All distributions

14.12 Release Checklist

Before releasing distributions, verify:

See RELEASE_CHECKLIST.md for complete pre-release verification.