Files
claudetools/projects/msp-tools/guru-rmm/agent/MACOS_BUILD.md
azcomputerguru 53cadd0f97 Add macOS cross-compilation support for GuruRMM agent
Enables building macOS agents (Intel and Apple Silicon) on Linux server
without requiring Mac hardware. Successfully tested on M3 MacBook Air.

Changes:
- Configure rustls for macOS builds (easier cross-compilation)
- Keep native-tls for Windows/Linux (Windows 7 compatibility)
- Add osxcross linker configuration for both architectures
- Create build-macos.sh script for automated builds
- Document complete setup in MACOS_BUILD.md

Technical Details:
- Build server: 172.16.3.30 (Ubuntu 22.04)
- Toolchain: osxcross 1.5 with macOS SDK 14.5
- Targets: x86_64-apple-darwin, aarch64-apple-darwin
- Binary sizes: ~3.5M (Intel), ~3.1M (ARM64)
- Build time: ~90 seconds per target

Tested: Successfully connected to wss://rmm-api.azcomputerguru.com/ws
Agent ID: 6177bcac-e046-4166-ac76-a6db68a363ab

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-04-02 20:03:35 -07:00

6.9 KiB

macOS Cross-Compilation Setup

Overview

GuruRMM agent can now be built for macOS (Intel and Apple Silicon) directly on the Linux build server (172.16.3.30) without requiring a Mac for compilation.

Architecture

  • Build Server: Ubuntu 22.04 LTS (172.16.3.30)
  • Toolchain: osxcross with macOS SDK 14.5
  • Targets:
    • x86_64-apple-darwin (Intel Macs)
    • aarch64-apple-darwin (Apple Silicon Macs)
  • TLS Stack: rustls (pure Rust, no native dependencies)

Key Changes

1. Cargo.toml Modifications

The agent now uses conditional dependencies for TLS:

  • Windows/Linux: native-tls (for Windows 7 compatibility)
  • macOS: rustls-tls-native-roots (for easier cross-compilation)
[target.'cfg(not(target_os = "macos"))'.dependencies]
tokio-tungstenite = { version = "0.24", features = ["native-tls"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] }

[target.'cfg(target_os = "macos")'.dependencies]
tokio-tungstenite = { version = "0.24", features = ["rustls-tls-native-roots"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-native-roots", "blocking"] }

2. Cargo Configuration (.cargo/config.toml)

Linker configuration for macOS targets:

[target.x86_64-apple-darwin]
linker = "/opt/osxcross/target/bin/x86_64-apple-darwin23.5-clang"
ar = "/opt/osxcross/target/bin/x86_64-apple-darwin23.5-ar"

[target.aarch64-apple-darwin]
linker = "/opt/osxcross/target/bin/aarch64-apple-darwin23.5-clang"
ar = "/opt/osxcross/target/bin/aarch64-apple-darwin23.5-ar"

Build Server Setup

Installed Components

  1. osxcross: /opt/osxcross/

    • macOS SDK 14.5 (darwin23.5)
    • Clang/LLVM cross-compilers
    • Binutils for macOS
  2. Rust Toolchain:

    • rustc 1.94.1
    • Targets: x86_64-apple-darwin, aarch64-apple-darwin
  3. Build Dependencies:

    • clang-14
    • cmake 3.22.1
    • libxml2-dev
    • uuid-dev

Environment Variables

For cross-compilation, the following must be set:

export PATH="/opt/osxcross/target/bin:$PATH"
export CC_x86_64_apple_darwin=x86_64-apple-darwin23.5-clang
export AR_x86_64_apple_darwin=x86_64-apple-darwin23.5-ar
export CC_aarch64_apple_darwin=aarch64-apple-darwin23.5-clang
export AR_aarch64_apple_darwin=aarch64-apple-darwin23.5-ar

Building for macOS

Using the Build Script

The simplest method is to use the provided build script:

cd ~/gururmm/agent
./build-macos.sh

This will:

  • Build for both Intel (x86_64) and Apple Silicon (arm64)
  • Create binaries in dist/ directory
  • Generate SHA256 checksums
  • Name binaries: gururmm-agent-macos-{amd64|arm64}-v{version}

Manual Build

For individual targets:

# Source environment
source ~/.cargo/env
export PATH="/opt/osxcross/target/bin:$PATH"

# Intel Macs
export CC_x86_64_apple_darwin=x86_64-apple-darwin23.5-clang
export AR_x86_64_apple_darwin=x86_64-apple-darwin23.5-ar
cargo build --release --target x86_64-apple-darwin

# Apple Silicon Macs
export CC_aarch64_apple_darwin=aarch64-apple-darwin23.5-clang
export AR_aarch64_apple_darwin=aarch64-apple-darwin23.5-ar
cargo build --release --target aarch64-apple-darwin

Build Output

Binary Sizes

  • Intel (x86_64): ~3.5 MB
  • Apple Silicon (arm64): ~3.1 MB

Build Times (on 172.16.3.30)

  • Clean build: ~1 minute 30 seconds per target
  • Incremental build: ~20-30 seconds per target

Output Directory Structure

dist/
├── gururmm-agent-macos-amd64-v0.6.0
├── gururmm-agent-macos-amd64-v0.6.0.sha256
├── gururmm-agent-macos-arm64-v0.6.0
└── gururmm-agent-macos-arm64-v0.6.0.sha256

Deployment

Installation on macOS

Intel Macs:

curl -fsSL http://172.16.3.30/downloads/gururmm-agent-macos-amd64 -o /tmp/gururmm-agent
chmod +x /tmp/gururmm-agent
sudo /tmp/gururmm-agent install --server-url wss://rmm-api.azcomputerguru.com/ws --api-key SITE-CODE

Apple Silicon Macs:

curl -fsSL http://172.16.3.30/downloads/gururmm-agent-macos-arm64 -o /tmp/gururmm-agent
chmod +x /tmp/gururmm-agent
sudo /tmp/gururmm-agent install --server-url wss://rmm-api.azcomputerguru.com/ws --api-key SITE-CODE

macOS Service Configuration

The agent installs as a launchd service:

  • Plist: /Library/LaunchDaemons/com.gururmm.agent.plist
  • Binary: /usr/local/bin/gururmm-agent
  • Config: /etc/gururmm/agent.toml

Troubleshooting

Build Failures

  1. "ring" crate compilation errors:

    • Ensure CC_* and AR_* environment variables are set
    • Verify osxcross binaries are in PATH
  2. Linker errors:

    • Check .cargo/config.toml has correct linker paths
    • Verify osxcross installation at /opt/osxcross/target/bin/
  3. "native-tls" errors on macOS:

    • Ensure Cargo.toml uses rustls-tls-native-roots for macOS targets
    • Conditional dependencies must be properly configured

Testing Binaries

To verify a macOS binary was built correctly:

# On build server
file target/x86_64-apple-darwin/release/gururmm-agent
# Output: Mach-O 64-bit executable x86_64

file target/aarch64-apple-darwin/release/gururmm-agent
# Output: Mach-O 64-bit executable arm64

On an actual Mac, the binary should run without errors:

./gururmm-agent --version
# Output: gururmm-agent 0.6.0

Maintenance

Updating osxcross

To update to a newer macOS SDK:

  1. Download SDK from https://github.com/joseluisq/macosx-sdks/releases
  2. Place in /opt/osxcross/tarballs/
  3. Run /opt/osxcross/build.sh
  4. Update linker paths in .cargo/config.toml if SDK version changes

Updating Rust Targets

rustup target add x86_64-apple-darwin
rustup target add aarch64-apple-darwin

Security Notes

  • macOS SDK usage is in a legal gray area; osxcross requires accepting Xcode license terms
  • Binaries built with osxcross are functionally identical to native macOS builds
  • TLS implementation (rustls) is audited and widely used in production Rust applications
  • No code signing is performed; users will need to approve binary on first run

CI/CD Integration

The build script can be integrated into automated builds:

# Example: Build on git push
cd ~/gururmm/agent
git pull
./build-macos.sh
# Copy to deployment directory
cp dist/gururmm-agent-macos-* /var/www/gururmm/downloads/

Performance

Cross-compiled binaries perform identically to native builds:

  • No runtime overhead from cross-compilation
  • Full optimization with opt-level = "z" and LTO
  • Binary stripping reduces size without affecting performance

Future Enhancements

  • Code signing for macOS binaries (requires Apple Developer account)
  • Notarization for Gatekeeper compatibility
  • Universal binary (combined Intel + ARM)
  • Automated CI/CD pipeline with GitHub Actions (macOS runners)

Last Updated: 2026-04-03 Build Server: 172.16.3.30 (Ubuntu 22.04) osxcross Version: 1.5 SDK Version: macOS 14.5 (darwin23.5)