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>
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
-
osxcross:
/opt/osxcross/- macOS SDK 14.5 (darwin23.5)
- Clang/LLVM cross-compilers
- Binutils for macOS
-
Rust Toolchain:
- rustc 1.94.1
- Targets:
x86_64-apple-darwin,aarch64-apple-darwin
-
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
-
"ring" crate compilation errors:
- Ensure
CC_*andAR_*environment variables are set - Verify osxcross binaries are in PATH
- Ensure
-
Linker errors:
- Check
.cargo/config.tomlhas correct linker paths - Verify osxcross installation at
/opt/osxcross/target/bin/
- Check
-
"native-tls" errors on macOS:
- Ensure Cargo.toml uses
rustls-tls-native-rootsfor macOS targets - Conditional dependencies must be properly configured
- Ensure Cargo.toml uses
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:
- Download SDK from https://github.com/joseluisq/macosx-sdks/releases
- Place in
/opt/osxcross/tarballs/ - Run
/opt/osxcross/build.sh - Update linker paths in
.cargo/config.tomlif 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)