A better Rust ATProto crate
at c6309d5719b6c455c8ca73da35b2e69a2b3e2216 202 lines 7.2 kB view raw
1#!/usr/bin/env bash 2set -euo pipefail 3 4# Script to package jacquard-lexicon binaries for distribution using Nix cross-compilation 5# Creates tar.xz archives with binaries, man pages, completions, README, LICENSE, and config 6# 7# Generates two versions: 8# - Unversioned archives in binaries/ (tracked in git, overwritten each build) 9# - Versioned archives in binaries/releases/ (gitignored, for GitHub releases) 10 11# Determine project root (script is in scripts/ subdirectory) 12SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 13PROJECT_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)" 14cd "$PROJECT_ROOT" 15 16# Parse version from workspace Cargo.toml 17VERSION=$(grep '^version = ' Cargo.toml | head -1 | sed 's/version = "\(.*\)"/\1/') 18echo "Packaging version: $VERSION" 19 20# Detect current system 21CURRENT_SYSTEM=$(nix eval --impure --expr 'builtins.currentSystem' --raw) 22echo "Current system: $CURRENT_SYSTEM" 23 24# Map target triples to nix package names and friendly names 25declare -A TARGET_TO_PACKAGE=( 26 ["x86_64-unknown-linux-gnu"]="jacquard-lexicon-x86_64-linux" 27 ["aarch64-unknown-linux-gnu"]="jacquard-lexicon-aarch64-linux" 28 ["x86_64-apple-darwin"]="jacquard-lexicon-x86_64-darwin" 29 ["aarch64-apple-darwin"]="jacquard-lexicon-aarch64-darwin" 30 ["x86_64-pc-windows-gnu"]="jacquard-lexicon-x86_64-windows" 31 ["aarch64-pc-windows-gnullvm"]="jacquard-lexicon-aarch64-windows" 32) 33 34# Determine which targets we can build from the current system 35TARGETS=() 36case "$CURRENT_SYSTEM" in 37 x86_64-linux) 38 # Linux can cross-compile to everything 39 TARGETS=( 40 "x86_64-unknown-linux-gnu" 41 "aarch64-unknown-linux-gnu" 42 "x86_64-apple-darwin" 43 "aarch64-apple-darwin" 44 "x86_64-pc-windows-gnu" 45 "aarch64-pc-windows-gnullvm" 46 ) 47 echo "Building from x86_64-linux: All targets (Linux, macOS, Windows for x86_64 and aarch64)" 48 ;; 49 aarch64-linux) 50 # Linux can cross-compile to everything 51 TARGETS=( 52 "aarch64-unknown-linux-gnu" 53 "x86_64-unknown-linux-gnu" 54 "x86_64-apple-darwin" 55 "aarch64-apple-darwin" 56 "x86_64-pc-windows-gnu" 57 "aarch64-pc-windows-gnullvm" 58 ) 59 echo "Building from aarch64-linux: All targets (Linux, macOS, Windows for x86_64 and aarch64)" 60 ;; 61 x86_64-darwin) 62 # macOS cross-compilation is limited 63 TARGETS=( 64 "x86_64-apple-darwin" 65 ) 66 echo "Building from x86_64-darwin: x86_64-darwin only" 67 echo "Note: Cross to aarch64-darwin needs rosetta, cross to Linux/Windows needs more setup" 68 ;; 69 aarch64-darwin) 70 # macOS aarch64 can build both macOS targets via rosetta 71 TARGETS=( 72 "aarch64-apple-darwin" 73 "x86_64-apple-darwin" 74 ) 75 echo "Building from aarch64-darwin: macOS targets (aarch64 + x86_64 via rosetta)" 76 echo "Note: Cross to Linux/Windows needs more setup" 77 ;; 78 *) 79 echo "Error: Unknown system: $CURRENT_SYSTEM" 80 echo "This script supports: x86_64-linux, aarch64-linux, x86_64-darwin, aarch64-darwin" 81 exit 1 82 ;; 83esac 84 85echo "" 86echo "Will build for: ${TARGETS[*]}" 87echo "" 88 89# Output directories 90OUTPUT_DIR="binaries" 91RELEASES_DIR="binaries/releases" 92mkdir -p "$OUTPUT_DIR" 93mkdir -p "$RELEASES_DIR" 94 95# Helper function to package for a target 96package_target() { 97 local TARGET=$1 98 local PACKAGE_NAME="${TARGET_TO_PACKAGE[$TARGET]}" 99 100 echo "" 101 echo "======================================" 102 echo "Building for $TARGET" 103 echo "======================================" 104 105 # Build with nix using cross-compilation package 106 echo "Running: nix build .#${PACKAGE_NAME}" 107 if ! nix build ".#${PACKAGE_NAME}" -o "result-${TARGET}"; then 108 echo "Error: nix build failed for $TARGET" 109 return 1 110 fi 111 112 # Names for versioned and unversioned archives 113 local VERSIONED_NAME="jacquard-lexicon_${TARGET}_v${VERSION}" 114 local UNVERSIONED_NAME="jacquard-lexicon_${TARGET}" 115 116 # Create staging directory 117 local STAGE_DIR="/tmp/${VERSIONED_NAME}" 118 rm -rf "$STAGE_DIR" 119 mkdir -p "$STAGE_DIR" 120 121 # Detect if this is a Windows target 122 if [[ "$TARGET" == *"windows"* ]]; then 123 # Windows: just binaries, README, LICENSE, example config 124 mkdir -p "$STAGE_DIR/bin" 125 cp "result-${TARGET}"/bin/*.exe "$STAGE_DIR/bin/" 2>/dev/null || true 126 cp LICENSE "$STAGE_DIR/" 127 cp README.md "$STAGE_DIR/" 128 129 # Copy example config to a more Windows-friendly location 130 mkdir -p "$STAGE_DIR/examples" 131 cp crates/jacquard-lexicon/lexicons.kdl.example "$STAGE_DIR/examples/" 2>/dev/null || true 132 else 133 # Unix (Linux/macOS): full structure with man pages and completions 134 cp -r "result-${TARGET}"/* "$STAGE_DIR/" 135 cp LICENSE "$STAGE_DIR/" 136 cp README.md "$STAGE_DIR/" 137 fi 138 139 # Create versioned archive (for releases) 140 cd /tmp 141 142 # Use .zip for Windows, .tar.xz for Unix 143 if [[ "$TARGET" == *"windows"* ]]; then 144 zip -r "${VERSIONED_NAME}.zip" "$VERSIONED_NAME" 145 mv "${VERSIONED_NAME}.zip" "$PROJECT_ROOT/$RELEASES_DIR/" 146 echo " Created: ${RELEASES_DIR}/${VERSIONED_NAME}.zip" 147 148 # Rename and create unversioned archive 149 mv "$VERSIONED_NAME" "$UNVERSIONED_NAME" 150 zip -r "${UNVERSIONED_NAME}.zip" "$UNVERSIONED_NAME" 151 mv "${UNVERSIONED_NAME}.zip" "$PROJECT_ROOT/$OUTPUT_DIR/" 152 echo " Created: ${OUTPUT_DIR}/${UNVERSIONED_NAME}.zip" 153 else 154 tar -cJf "${VERSIONED_NAME}.tar.xz" "$VERSIONED_NAME" 155 mv "${VERSIONED_NAME}.tar.xz" "$PROJECT_ROOT/$RELEASES_DIR/" 156 echo " Created: ${RELEASES_DIR}/${VERSIONED_NAME}.tar.xz" 157 158 # Rename and create unversioned archive 159 mv "$VERSIONED_NAME" "$UNVERSIONED_NAME" 160 tar -cJf "${UNVERSIONED_NAME}.tar.xz" "$UNVERSIONED_NAME" 161 mv "${UNVERSIONED_NAME}.tar.xz" "$PROJECT_ROOT/$OUTPUT_DIR/" 162 echo " Created: ${OUTPUT_DIR}/${UNVERSIONED_NAME}.tar.xz" 163 fi 164 165 # Cleanup 166 rm -rf "$UNVERSIONED_NAME" 167 rm -f "$PROJECT_ROOT/result-${TARGET}" 168 cd "$PROJECT_ROOT" 169} 170 171# Build for all targets 172for target in "${TARGETS[@]}"; do 173 package_target "$target" || echo "Warning: build failed for $target, continuing..." 174done 175 176# Print summary 177echo "" 178echo "Packaging complete!" 179echo "" 180echo "Tracked archives (binaries/):" 181ls -lh "$OUTPUT_DIR"/*.tar.xz 2>/dev/null || true 182ls -lh "$OUTPUT_DIR"/*.zip 2>/dev/null || true 183echo "" 184echo "Release archives (binaries/releases/):" 185ls -lh "$RELEASES_DIR"/*.tar.xz 2>/dev/null || true 186ls -lh "$RELEASES_DIR"/*.zip 2>/dev/null || true 187 188# Generate checksums for tracked archives 189echo "" 190echo "Generating checksums for tracked archives..." 191cd "$OUTPUT_DIR" 192sha256sum *.tar.xz *.zip 2>/dev/null > SHA256SUMS || true 193echo "Checksums written to ${OUTPUT_DIR}/SHA256SUMS" 194cat SHA256SUMS 195 196# Generate checksums for release archives 197echo "" 198echo "Generating checksums for release archives..." 199cd "$PROJECT_ROOT/$RELEASES_DIR" 200sha256sum *.tar.xz *.zip 2>/dev/null > SHA256SUMS || true 201echo "Checksums written to ${RELEASES_DIR}/SHA256SUMS" 202cat SHA256SUMS