- Added upx package to Dockerfile.alpine build dependencies - Added optimize_binary() function to compile-components.sh - Automatically strips debug symbols from all Zero-OS binaries - Applies UPX compression with --best --lzma for maximum size reduction - Optimizes binaries in both initramfs and output directories - Shows size reduction stats (original → stripped → compressed) - Graceful fallback if UPX fails, keeping stripped version This significantly reduces initramfs size by compressing zinit, rfs, and mycelium binaries.
250 lines
8.0 KiB
Bash
Executable File
250 lines
8.0 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e
|
|
|
|
# Detect if running in container or locally
|
|
if [ -d "/build" ]; then
|
|
# Running in Docker container
|
|
ALPINE_ROOT="/build/initramfs"
|
|
OUTPUT_DIR="/build/output"
|
|
WORKSPACE_ROOT="/build"
|
|
else
|
|
# Running locally
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
WORKSPACE_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
ALPINE_ROOT="$WORKSPACE_ROOT/initramfs"
|
|
OUTPUT_DIR="$WORKSPACE_ROOT/output"
|
|
fi
|
|
|
|
echo "[+] Compiling Zero-OS components individually..."
|
|
|
|
# Check if components exist
|
|
if [ ! -d "$WORKSPACE_ROOT/components" ]; then
|
|
echo "Error: Components directory not found."
|
|
exit 1
|
|
fi
|
|
|
|
echo " Components found:"
|
|
ls -1 "$WORKSPACE_ROOT/components/" | sed 's/^/ - /'
|
|
echo ""
|
|
|
|
# Function to build a single component
|
|
build_component() {
|
|
local component="$1"
|
|
local component_dir="$WORKSPACE_ROOT/components/$component"
|
|
|
|
echo " Building $component..."
|
|
|
|
if [ ! -d "$component_dir" ]; then
|
|
echo " ✗ Component directory not found: $component_dir"
|
|
return 1
|
|
fi
|
|
|
|
if [ ! -f "$component_dir/Cargo.toml" ]; then
|
|
echo " ✗ Cargo.toml not found in: $component_dir"
|
|
return 1
|
|
fi
|
|
|
|
cd "$component_dir"
|
|
|
|
# Source cargo environment
|
|
. ~/.cargo/env
|
|
|
|
# Handle special case for myceliumd (requires subdirectory build)
|
|
if [ "$component" = "mycelium" ]; then
|
|
echo " Building myceliumd from mycelium/myceliumd subdirectory..."
|
|
cd "$component_dir/myceliumd"
|
|
if [ ! -f "Cargo.toml" ]; then
|
|
echo " ✗ myceliumd/Cargo.toml not found"
|
|
return 1
|
|
fi
|
|
|
|
# Set OpenSSL environment variables for musl cross-compilation
|
|
export OPENSSL_STATIC=1
|
|
export OPENSSL_DIR=/usr
|
|
|
|
echo " Running: cargo build --release --target x86_64-unknown-linux-musl"
|
|
CARGO_TARGET_DIR="$WORKSPACE_ROOT/target" cargo build --release --target x86_64-unknown-linux-musl || {
|
|
echo " ⚠ myceliumd build failed (OpenSSL cross-compilation issue)"
|
|
echo " This is a known issue with OpenSSL and musl cross-compilation"
|
|
return 1
|
|
}
|
|
elif [ "$component" = "rfs" ]; then
|
|
# Build RFS with required features
|
|
echo " Removing "
|
|
echo " Running: cargo build --release --target x86_64-unknown-linux-musl --features build-binary"
|
|
CARGO_TARGET_DIR="$WORKSPACE_ROOT/target" cargo build --release --target x86_64-unknown-linux-musl --features build-binary
|
|
else
|
|
# Build component with musl target for static linking
|
|
echo " Running: cargo build --release --target x86_64-unknown-linux-musl"
|
|
CARGO_TARGET_DIR="$WORKSPACE_ROOT/target" cargo build --release --target x86_64-unknown-linux-musl
|
|
fi
|
|
|
|
echo " ✓ $component build completed"
|
|
return 0
|
|
}
|
|
|
|
# Function to optimize binaries (strip + upx)
|
|
optimize_binary() {
|
|
local binary_path="$1"
|
|
local binary_name=$(basename "$binary_path")
|
|
|
|
if [ ! -f "$binary_path" ]; then
|
|
echo " ⚠ Binary not found for optimization: $binary_path"
|
|
return 1
|
|
fi
|
|
|
|
local original_size=$(stat -c%s "$binary_path")
|
|
|
|
# Strip debug symbols and unnecessary sections
|
|
echo " Stripping $binary_name..."
|
|
strip --strip-all "$binary_path" 2>/dev/null || {
|
|
echo " ⚠ Failed to strip $binary_name"
|
|
}
|
|
|
|
local stripped_size=$(stat -c%s "$binary_path")
|
|
|
|
# Compress with UPX (with fallback if UPX fails)
|
|
echo " Compressing $binary_name with UPX..."
|
|
if upx --best --lzma "$binary_path" 2>/dev/null; then
|
|
local final_size=$(stat -c%s "$binary_path")
|
|
echo " ✓ $binary_name optimized: $original_size → $stripped_size → $final_size bytes"
|
|
else
|
|
echo " ⚠ UPX compression failed for $binary_name, keeping stripped version"
|
|
echo " ✓ $binary_name stripped: $original_size → $stripped_size bytes"
|
|
fi
|
|
}
|
|
|
|
# Function to install workspace binaries
|
|
install_component_binaries() {
|
|
local target_dir="$WORKSPACE_ROOT/target/x86_64-unknown-linux-musl/release"
|
|
|
|
echo " Installing component binaries..."
|
|
echo " Target directory: $target_dir"
|
|
|
|
# Debug: Show what was built
|
|
echo " Built binaries:"
|
|
ls -la "$target_dir" 2>/dev/null | grep -E '^-.*x.*' | awk '{print " " $9 " (" $5 " bytes)"}' || echo " No binaries found"
|
|
|
|
# Create output and alpine root directories
|
|
mkdir -p "$OUTPUT_DIR"
|
|
mkdir -p "$ALPINE_ROOT/sbin"
|
|
mkdir -p "$ALPINE_ROOT/usr/bin"
|
|
|
|
# Install specific binaries
|
|
local installed=0
|
|
|
|
# Install zinit
|
|
if [ -f "$target_dir/zinit" ]; then
|
|
cp "$target_dir/zinit" "$ALPINE_ROOT/sbin/"
|
|
cp "$target_dir/zinit" "$OUTPUT_DIR/"
|
|
chmod +x "$ALPINE_ROOT/sbin/zinit"
|
|
|
|
# Optimize binaries
|
|
optimize_binary "$ALPINE_ROOT/sbin/zinit"
|
|
optimize_binary "$OUTPUT_DIR/zinit"
|
|
|
|
echo " ✓ zinit -> /sbin/zinit (optimized)"
|
|
installed=$((installed + 1))
|
|
else
|
|
echo " ✗ zinit binary not found"
|
|
fi
|
|
|
|
# Install rfs (check for different possible names)
|
|
local rfs_binary=""
|
|
for name in "rfs" "rfs-server" "rfs-bin" "fl-server"; do
|
|
if [ -f "$target_dir/$name" ]; then
|
|
rfs_binary="$name"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -n "$rfs_binary" ]; then
|
|
cp "$target_dir/$rfs_binary" "$ALPINE_ROOT/usr/bin/rfs"
|
|
cp "$target_dir/$rfs_binary" "$OUTPUT_DIR/rfs"
|
|
chmod +x "$ALPINE_ROOT/usr/bin/rfs"
|
|
|
|
# Optimize binaries
|
|
optimize_binary "$ALPINE_ROOT/usr/bin/rfs"
|
|
optimize_binary "$OUTPUT_DIR/rfs"
|
|
|
|
echo " ✓ $rfs_binary -> /usr/bin/rfs (optimized)"
|
|
installed=$((installed + 1))
|
|
else
|
|
echo " ✗ rfs binary not found (checked: rfs, rfs-server, rfs-bin)"
|
|
fi
|
|
|
|
# Install mycelium (check for different possible names)
|
|
local mycelium_binary=""
|
|
for name in "mycelium" "myceliumd" "mycelium-cli"; do
|
|
if [ -f "$target_dir/$name" ]; then
|
|
mycelium_binary="$name"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -n "$mycelium_binary" ]; then
|
|
cp "$target_dir/$mycelium_binary" "$ALPINE_ROOT/usr/bin/mycelium"
|
|
cp "$target_dir/$mycelium_binary" "$OUTPUT_DIR/mycelium"
|
|
chmod +x "$ALPINE_ROOT/usr/bin/mycelium"
|
|
|
|
# Optimize binaries
|
|
optimize_binary "$ALPINE_ROOT/usr/bin/mycelium"
|
|
optimize_binary "$OUTPUT_DIR/mycelium"
|
|
|
|
echo " ✓ $mycelium_binary -> /usr/bin/mycelium (optimized)"
|
|
installed=$((installed + 1))
|
|
else
|
|
echo " ✗ mycelium binary not found (checked: mycelium, myceliumd, mycelium-cli)"
|
|
fi
|
|
|
|
echo " Installed $installed out of 3 expected binaries"
|
|
return 0
|
|
}
|
|
|
|
# Ensure Alpine root directory exists
|
|
if [ ! -d "$ALPINE_ROOT" ]; then
|
|
echo " Creating Alpine initramfs root at $ALPINE_ROOT"
|
|
mkdir -p "$ALPINE_ROOT"
|
|
fi
|
|
|
|
# Build each component individually
|
|
failed_components=()
|
|
|
|
for component in zinit mycelium rfs; do
|
|
if build_component "$component"; then
|
|
echo " ✓ $component build completed"
|
|
else
|
|
echo " ✗ $component build failed"
|
|
failed_components+=("$component")
|
|
fi
|
|
done
|
|
|
|
# Report build results
|
|
if [ ${#failed_components[@]} -eq 0 ]; then
|
|
echo " ✓ All components built successfully"
|
|
else
|
|
echo " ✗ Failed to build: ${failed_components[*]}"
|
|
echo " Note: Continuing with available binaries..."
|
|
fi
|
|
|
|
# Install binaries
|
|
install_component_binaries
|
|
|
|
echo ""
|
|
echo "[+] Zero-OS component compilation completed"
|
|
|
|
# Show installed binaries info
|
|
echo ""
|
|
echo "[+] Compiled Zero-OS components in Alpine root:"
|
|
for binary in "/sbin/zinit" "/usr/bin/rfs" "/usr/bin/mycelium"; do
|
|
if [ -x "$ALPINE_ROOT$binary" ]; then
|
|
size=$(stat -c%s "$ALPINE_ROOT$binary" 2>/dev/null || echo "unknown")
|
|
echo " $binary (${size} bytes)"
|
|
else
|
|
echo " $binary (NOT BUILT)"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "[+] Compiled binaries also saved to: $OUTPUT_DIR"
|
|
echo "[+] Zero-OS Rust component compilation complete!" |