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>
This commit is contained in:
@@ -1,2 +1,11 @@
|
|||||||
[target.x86_64-pc-windows-msvc]
|
[target.x86_64-pc-windows-msvc]
|
||||||
rustflags = ["-C", "target-feature=+crt-static", "-C", "link-args=/SUBSYSTEM:CONSOLE,6.01"]
|
rustflags = ["-C", "target-feature=+crt-static", "-C", "link-args=/SUBSYSTEM:CONSOLE,6.01"]
|
||||||
|
|
||||||
|
# macOS cross-compilation with osxcross
|
||||||
|
[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"
|
||||||
|
|||||||
@@ -19,13 +19,9 @@ tokio = { version = "1", features = ["full"] }
|
|||||||
# System information (cross-platform metrics)
|
# System information (cross-platform metrics)
|
||||||
sysinfo = "0.31"
|
sysinfo = "0.31"
|
||||||
|
|
||||||
# WebSocket client (native-tls for Windows 7/2008R2 compatibility)
|
# WebSocket - futures utilities
|
||||||
tokio-tungstenite = { version = "0.24", features = ["native-tls"] }
|
|
||||||
futures-util = "0.3"
|
futures-util = "0.3"
|
||||||
|
|
||||||
# HTTP client (fallback/registration) - native-tls for Windows 7/2008R2 compatibility
|
|
||||||
reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] }
|
|
||||||
|
|
||||||
# Serialization
|
# Serialization
|
||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
@@ -66,6 +62,19 @@ local-ip-address = "0.6"
|
|||||||
# Async file operations
|
# Async file operations
|
||||||
tokio-util = "0.7"
|
tokio-util = "0.7"
|
||||||
|
|
||||||
|
# Platform-specific TLS dependencies
|
||||||
|
[target.'cfg(not(target_os = "macos"))'.dependencies]
|
||||||
|
# WebSocket client - native-tls for Windows/Linux (Windows 7 compatibility)
|
||||||
|
tokio-tungstenite = { version = "0.24", features = ["native-tls"] }
|
||||||
|
# HTTP client - native-tls for Windows 7/2008R2 compatibility
|
||||||
|
reqwest = { version = "0.12", default-features = false, features = ["json", "native-tls"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
|
# WebSocket client - rustls for macOS (easier cross-compilation)
|
||||||
|
tokio-tungstenite = { version = "0.24", features = ["rustls-tls-native-roots"] }
|
||||||
|
# HTTP client - rustls for macOS
|
||||||
|
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls-native-roots", "blocking"] }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
# Windows service support (optional, only for native-service feature)
|
# Windows service support (optional, only for native-service feature)
|
||||||
windows-service = { version = "0.7", optional = true }
|
windows-service = { version = "0.7", optional = true }
|
||||||
|
|||||||
256
projects/msp-tools/guru-rmm/agent/MACOS_BUILD.md
Normal file
256
projects/msp-tools/guru-rmm/agent/MACOS_BUILD.md
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
# 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)
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[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:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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:
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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:
|
||||||
|
```bash
|
||||||
|
./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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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)
|
||||||
70
projects/msp-tools/guru-rmm/agent/build-macos.sh
Executable file
70
projects/msp-tools/guru-rmm/agent/build-macos.sh
Executable file
@@ -0,0 +1,70 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Build script for GuruRMM agent - macOS only
|
||||||
|
# Supports: macOS (Intel & Apple Silicon)
|
||||||
|
|
||||||
|
echo "=== GuruRMM Agent macOS Build ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Add osxcross to PATH
|
||||||
|
export PATH="/opt/osxcross/target/bin:$PATH"
|
||||||
|
|
||||||
|
# Source cargo environment
|
||||||
|
source ~/.cargo/env
|
||||||
|
|
||||||
|
# Set up cross-compilation environment variables for macOS
|
||||||
|
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
|
||||||
|
|
||||||
|
# Output directory
|
||||||
|
OUTPUT_DIR="$(dirname "$0")/dist"
|
||||||
|
|
||||||
|
# Create output directory
|
||||||
|
mkdir -p "$OUTPUT_DIR"
|
||||||
|
|
||||||
|
# Get version from Cargo.toml
|
||||||
|
VERSION=$(grep '^version' Cargo.toml | head -1 | cut -d'"' -f2)
|
||||||
|
echo "Building GuruRMM Agent v$VERSION for macOS"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Function to build for a target
|
||||||
|
build_target() {
|
||||||
|
local target=$1
|
||||||
|
local name=$2
|
||||||
|
local ext=$3
|
||||||
|
|
||||||
|
echo "[INFO] Building for $name ($target)..."
|
||||||
|
cargo build --release --target $target
|
||||||
|
|
||||||
|
local binary_name="gururmm-agent$ext"
|
||||||
|
local output_name="gururmm-agent-$name-v$VERSION$ext"
|
||||||
|
|
||||||
|
cp "target/$target/release/$binary_name" "$OUTPUT_DIR/$output_name"
|
||||||
|
|
||||||
|
# Create SHA256 checksum
|
||||||
|
cd "$OUTPUT_DIR"
|
||||||
|
sha256sum "$output_name" > "$output_name.sha256"
|
||||||
|
cd - > /dev/null
|
||||||
|
|
||||||
|
# Get file size
|
||||||
|
local size=$(du -h "$OUTPUT_DIR/$output_name" | cut -f1)
|
||||||
|
echo "[SUCCESS] Built $output_name ($size)"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Build for macOS platforms
|
||||||
|
echo "=== Building for macOS (Intel) ==="
|
||||||
|
build_target "x86_64-apple-darwin" "macos-amd64" ""
|
||||||
|
|
||||||
|
echo "=== Building for macOS (Apple Silicon) ==="
|
||||||
|
build_target "aarch64-apple-darwin" "macos-arm64" ""
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Build Complete ==="
|
||||||
|
echo ""
|
||||||
|
echo "Artifacts in: $OUTPUT_DIR"
|
||||||
|
ls -lh "$OUTPUT_DIR"
|
||||||
|
|
||||||
Reference in New Issue
Block a user