A better Rust ATProto crate

at least some cross-compiling releases

Orual 98e6912d c6309d57

-6
Cargo.toml
··· 80 80 # Crypto curves and JOSE 81 81 p256 = "0.13" 82 82 jose-jwk = "0.1" 83 - 84 - 85 - [workspace.package.metadata.binstall] 86 - pkg-url = "https://github.com/rsform/jacquard/releases/download/v{ version }/{ name }_{ target }_v{ version }{ archive-suffix }" 87 - bin-dir = "{ name }_{ target }_v{ version }/{ bin }{ binary-ext }" 88 - pkg-fmt = "txz"
+6 -2
binaries/SHA256SUMS
··· 1 - 4c047bb41a4001d92451bd3c5223657143a27f3dee4d73583a12f08fccaebd7b jacquard-codegen_x86_64-unknown-linux-gnu.tar.xz 2 - af356cb142953a43bbc56b2b2c9fa4f38a41ed727634d70eeafc906da3a4ca8d lex-fetch_x86_64-unknown-linux-gnu.tar.xz 1 + 6e690739ec8d6349bd584ef743bdf34bbf61b531dbfc4922ba3db276fcb5f973 jacquard-codegen_aarch64-unknown-linux-gnu.tar.xz 2 + 8edd99321d52e85da26e31a551ee0476d7bc6653dfce2aaa41191119f41cba80 jacquard-codegen_x86_64-unknown-linux-gnu.tar.xz 3 + 831cd4cb95e6f944145907fc480625dc19044ee21a2cb794f4a387520a580c00 lex-fetch_aarch64-unknown-linux-gnu.tar.xz 4 + 4b6495f0cb60396f348a2afb24fed7bf5081f6f41970de0aa080ceb27960ebb7 lex-fetch_x86_64-unknown-linux-gnu.tar.xz 5 + 76d102081c02b9a33ea84433fea80665ff58e2297257ccb1a4ef235cfdf877ab jacquard-codegen_x86_64-pc-windows-gnu.zip 6 + 4405fd615292bfe8c28d9592fa451e0adeeada66573d020fde652b0d69877445 lex-fetch_x86_64-pc-windows-gnu.zip
binaries/jacquard-codegen_aarch64-unknown-linux-gnu.tar.xz

This is a binary file and will not be displayed.

binaries/jacquard-codegen_x86_64-pc-windows-gnu.zip

This is a binary file and will not be displayed.

binaries/jacquard-codegen_x86_64-unknown-linux-gnu.tar.xz

This is a binary file and will not be displayed.

binaries/lex-fetch_aarch64-unknown-linux-gnu.tar.xz

This is a binary file and will not be displayed.

binaries/lex-fetch_x86_64-pc-windows-gnu.zip

This is a binary file and will not be displayed.

binaries/lex-fetch_x86_64-unknown-linux-gnu.tar.xz

This is a binary file and will not be displayed.

+5 -1
crates/jacquard-lexicon/Cargo.toml
··· 54 54 55 55 [package.metadata.binstall] 56 56 pkg-url = "https://github.com/rsform/jacquard/releases/download/v{ version }/{ name }_{ target }_v{ version }{ archive-suffix }" 57 - bin-dir = "{ name }_{ target }_v{ version }/{ bin }{ binary-ext }" 57 + bin-dir = "{ name }_{ target }_v{ version }/bin/{ bin }{ binary-ext }" 58 58 pkg-fmt = "txz" 59 + 60 + [package.metadata.binstall.overrides.x86_64-pc-windows-gnu] 61 + pkg-fmt = "zip" 62 + bin-dir = "{ name }_{ target }_v{ version }/{ bin }{ binary-ext }"
+38 -1
flake.lock
··· 2 2 "nodes": { 3 3 "crane": { 4 4 "locked": { 5 + "lastModified": 1759893430, 6 + "narHash": "sha256-yAy4otLYm9iZ+NtQwTMEbqHwswSFUbhn7x826RR6djw=", 7 + "owner": "ipetkov", 8 + "repo": "crane", 9 + "rev": "1979a2524cb8c801520bd94c38bb3d5692419d93", 10 + "type": "github" 11 + }, 12 + "original": { 13 + "owner": "ipetkov", 14 + "repo": "crane", 15 + "type": "github" 16 + } 17 + }, 18 + "crane_2": { 19 + "locked": { 5 20 "lastModified": 1758758545, 6 21 "narHash": "sha256-NU5WaEdfwF6i8faJ2Yh+jcK9vVFrofLcwlD/mP65JrI=", 7 22 "owner": "ipetkov", ··· 69 84 }, 70 85 "root": { 71 86 "inputs": { 87 + "crane": "crane", 72 88 "flake-parts": "flake-parts", 73 89 "git-hooks": "git-hooks", 74 90 "nixpkgs": "nixpkgs", 75 91 "rust-flake": "rust-flake", 92 + "rust-overlay": "rust-overlay_2", 76 93 "systems": "systems" 77 94 } 78 95 }, 79 96 "rust-flake": { 80 97 "inputs": { 81 - "crane": "crane", 98 + "crane": "crane_2", 82 99 "nixpkgs": [ 83 100 "nixpkgs" 84 101 ], ··· 111 128 "owner": "oxalica", 112 129 "repo": "rust-overlay", 113 130 "rev": "5bfedf3fbbf5caf8e39f7fcd62238f54d82aa1e2", 131 + "type": "github" 132 + }, 133 + "original": { 134 + "owner": "oxalica", 135 + "repo": "rust-overlay", 136 + "type": "github" 137 + } 138 + }, 139 + "rust-overlay_2": { 140 + "inputs": { 141 + "nixpkgs": [ 142 + "nixpkgs" 143 + ] 144 + }, 145 + "locked": { 146 + "lastModified": 1760754684, 147 + "narHash": "sha256-B4+gmoRuvjZGKvDQtMjYkqyA89gZLjrXObZrXFrcKOk=", 148 + "owner": "oxalica", 149 + "repo": "rust-overlay", 150 + "rev": "16c233757f1b200936f1b39961c901733936c616", 114 151 "type": "github" 115 152 }, 116 153 "original": {
+5
flake.nix
··· 9 9 #process-compose-flake.url = "github:Platonic-Systems/process-compose-flake"; 10 10 #cargo-doc-live.url = "github:srid/cargo-doc-live"; 11 11 12 + # For cross-compilation 13 + crane.url = "github:ipetkov/crane"; 14 + rust-overlay.url = "github:oxalica/rust-overlay"; 15 + rust-overlay.inputs.nixpkgs.follows = "nixpkgs"; 16 + 12 17 git-hooks.url = "github:cachix/git-hooks.nix"; 13 18 git-hooks.flake = false; 14 19 };
+25 -15
nix/modules/cross.nix
··· 5 5 # Get the filtered source from rust-project 6 6 src = config.rust-project.src; 7 7 8 + # Import nixpkgs with rust-overlay for getting rust toolchains (not cross) 9 + pkgs-rust = import inputs.nixpkgs { 10 + inherit system; 11 + overlays = [(import inputs.rust-overlay)]; 12 + }; 13 + 8 14 # Helper to create a cross-compiled package 9 15 mkCrossPackage = { 10 16 crossSystem, 11 17 rustTarget, 12 18 extraArgs ? {} 13 19 }: let 14 - # Import nixpkgs with cross-compilation configured 20 + # Import nixpkgs with cross-compilation configured (no overlays) 15 21 pkgs-cross = import inputs.nixpkgs { 16 22 inherit crossSystem; 17 23 localSystem = system; 18 - overlays = [(import inputs.rust-overlay)]; 19 24 }; 20 25 21 - # Set up crane with rust-overlay toolchain for the target 22 - craneLib = (inputs.crane.mkLib pkgs-cross).overrideToolchain (p: 23 - p.rust-bin.stable.latest.default.override { 24 - targets = [rustTarget]; 25 - } 26 - ); 26 + # Get rust toolchain from host system with the cross target added 27 + rustToolchain = pkgs-rust.rust-bin.stable.latest.default.override { 28 + targets = [rustTarget]; 29 + }; 30 + 31 + # Set up crane with the rust toolchain 32 + craneLib = (inputs.crane.mkLib pkgs-cross).overrideToolchain rustToolchain; 27 33 28 34 # Common crane args 29 35 commonArgs = { ··· 101 107 rustTarget = "x86_64-pc-windows-gnu"; 102 108 }; 103 109 104 - jacquard-lexicon-aarch64-windows = mkCrossPackage { 105 - crossSystem = { 106 - config = "aarch64-w64-mingw32"; 107 - libc = "msvcrt"; 108 - }; 109 - rustTarget = "aarch64-pc-windows-gnullvm"; 110 - }; 110 + # TODO: aarch64-windows cross-compilation broken in nixpkgs 111 + # Issue: mingw-w64-pthreads build fails with missing winver.h header 112 + # The aarch64-w64-mingw32 toolchain setup in nixpkgs is incomplete 113 + # Workaround: build on actual Windows with MSVC or wait for nixpkgs fix 114 + # jacquard-lexicon-aarch64-windows = mkCrossPackage { 115 + # crossSystem = { 116 + # config = "aarch64-w64-mingw32"; 117 + # useLLVM = true; 118 + # }; 119 + # rustTarget = "aarch64-pc-windows-gnullvm"; 120 + # }; 111 121 }; 112 122 }; 113 123 }
+1
nix/modules/devshell.nix
··· 21 21 cargo-semver-checks 22 22 cargo-binstall 23 23 cargo-dist 24 + zip 24 25 ]; 25 26 }; 26 27 };
+91 -24
scripts/package-binaries.sh
··· 21 21 CURRENT_SYSTEM=$(nix eval --impure --expr 'builtins.currentSystem' --raw) 22 22 echo "Current system: $CURRENT_SYSTEM" 23 23 24 - # Map target triples to nix package names and friendly names 24 + # Map target triples to nix package names 25 25 declare -A TARGET_TO_PACKAGE=( 26 26 ["x86_64-unknown-linux-gnu"]="jacquard-lexicon-x86_64-linux" 27 27 ["aarch64-unknown-linux-gnu"]="jacquard-lexicon-aarch64-linux" ··· 35 35 TARGETS=() 36 36 case "$CURRENT_SYSTEM" in 37 37 x86_64-linux) 38 - # Linux can cross-compile to everything 38 + # Linux can cross-compile to other Linux archs and Windows x86_64 39 + # macOS requires remote builders or actual macOS hardware 40 + # aarch64-windows: nixpkgs mingw-w64-pthreads broken for aarch64 (missing winver.h) 39 41 TARGETS=( 40 42 "x86_64-unknown-linux-gnu" 41 43 "aarch64-unknown-linux-gnu" 42 - "x86_64-apple-darwin" 43 - "aarch64-apple-darwin" 44 44 "x86_64-pc-windows-gnu" 45 - "aarch64-pc-windows-gnullvm" 45 + # "aarch64-pc-windows-gnullvm" # TODO: nixpkgs cross-compile broken 46 46 ) 47 - echo "Building from x86_64-linux: All targets (Linux, macOS, Windows for x86_64 and aarch64)" 47 + echo "Building from x86_64-linux: Linux (x86_64, aarch64) + Windows (x86_64)" 48 + echo "Note: macOS cross-compilation requires remote builders or macOS hardware" 49 + echo "Note: aarch64-windows cross-compilation broken in nixpkgs (mingw-w64-pthreads build fails)" 48 50 ;; 49 51 aarch64-linux) 50 - # Linux can cross-compile to everything 52 + # Linux can cross-compile to other Linux archs and Windows x86_64 53 + # macOS requires remote builders or actual macOS hardware 54 + # aarch64-windows: nixpkgs mingw-w64-pthreads broken for aarch64 (missing winver.h) 51 55 TARGETS=( 52 56 "aarch64-unknown-linux-gnu" 53 57 "x86_64-unknown-linux-gnu" 54 - "x86_64-apple-darwin" 55 - "aarch64-apple-darwin" 56 58 "x86_64-pc-windows-gnu" 57 - "aarch64-pc-windows-gnullvm" 59 + # "aarch64-pc-windows-gnullvm" # TODO: nixpkgs cross-compile broken 58 60 ) 59 - echo "Building from aarch64-linux: All targets (Linux, macOS, Windows for x86_64 and aarch64)" 61 + echo "Building from aarch64-linux: Linux (aarch64, x86_64) + Windows (x86_64)" 62 + echo "Note: macOS cross-compilation requires remote builders or macOS hardware" 63 + echo "Note: aarch64-windows cross-compilation broken in nixpkgs (mingw-w64-pthreads build fails)" 60 64 ;; 61 65 x86_64-darwin) 62 66 # macOS cross-compilation is limited ··· 64 68 "x86_64-apple-darwin" 65 69 ) 66 70 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 71 ;; 69 72 aarch64-darwin) 70 73 # macOS aarch64 can build both macOS targets via rosetta ··· 73 76 "x86_64-apple-darwin" 74 77 ) 75 78 echo "Building from aarch64-darwin: macOS targets (aarch64 + x86_64 via rosetta)" 76 - echo "Note: Cross to Linux/Windows needs more setup" 77 79 ;; 78 80 *) 79 81 echo "Error: Unknown system: $CURRENT_SYSTEM" ··· 109 111 return 1 110 112 fi 111 113 114 + # Package each binary separately 115 + for BINARY in lex-fetch jacquard-codegen; do 116 + echo " Packaging binary: $BINARY" 117 + package_binary "$TARGET" "$BINARY" 118 + done 119 + 120 + # Cleanup 121 + rm -f "$PROJECT_ROOT/result-${TARGET}" 122 + cd "$PROJECT_ROOT" 123 + } 124 + 125 + # Helper function to package a single binary 126 + package_binary() { 127 + local TARGET=$1 128 + local BINARY=$2 129 + 130 + # Determine binary extension 131 + local BINARY_EXT="" 132 + if [[ "$TARGET" == *"windows"* ]]; then 133 + BINARY_EXT=".exe" 134 + fi 135 + 136 + # Check if binary exists 137 + if [[ ! -f "result-${TARGET}/bin/${BINARY}${BINARY_EXT}" ]]; then 138 + echo " Warning: ${BINARY}${BINARY_EXT} not found, skipping" 139 + return 0 140 + fi 141 + 112 142 # Names for versioned and unversioned archives 113 - local VERSIONED_NAME="jacquard-lexicon_${TARGET}_v${VERSION}" 114 - local UNVERSIONED_NAME="jacquard-lexicon_${TARGET}" 143 + local VERSIONED_NAME="${BINARY}_${TARGET}_v${VERSION}" 144 + local UNVERSIONED_NAME="${BINARY}_${TARGET}" 115 145 116 146 # Create staging directory 117 147 local STAGE_DIR="/tmp/${VERSIONED_NAME}" ··· 120 150 121 151 # Detect if this is a Windows target 122 152 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 153 + # Windows: binary, README, LICENSE, example config (for lex-fetch only) 154 + cp "result-${TARGET}/bin/${BINARY}.exe" "$STAGE_DIR/" 126 155 cp LICENSE "$STAGE_DIR/" 127 156 cp README.md "$STAGE_DIR/" 128 157 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 158 + # Only include example config for lex-fetch 159 + if [[ "$BINARY" == "lex-fetch" ]]; then 160 + mkdir -p "$STAGE_DIR/examples" 161 + cp crates/jacquard-lexicon/lexicons.kdl.example "$STAGE_DIR/examples/" 2>/dev/null || true 162 + fi 132 163 else 133 - # Unix (Linux/macOS): full structure with man pages and completions 134 - cp -r "result-${TARGET}"/* "$STAGE_DIR/" 164 + # Unix (Linux/macOS): binary, man page, completions, README, LICENSE 165 + mkdir -p "$STAGE_DIR/bin" 166 + cp "result-${TARGET}/bin/${BINARY}" "$STAGE_DIR/bin/" 167 + 135 168 cp LICENSE "$STAGE_DIR/" 136 169 cp README.md "$STAGE_DIR/" 170 + 171 + # Copy man page if it exists 172 + if [[ -f "result-${TARGET}/share/man/man1/${BINARY}.1.gz" ]]; then 173 + mkdir -p "$STAGE_DIR/share/man/man1" 174 + cp "result-${TARGET}/share/man/man1/${BINARY}.1.gz" "$STAGE_DIR/share/man/man1/" 175 + fi 176 + 177 + # Copy completions if they exist 178 + for shell_dir in bash fish zsh; do 179 + local comp_dir="result-${TARGET}/share/$shell_dir/site-functions" 180 + if [[ "$shell_dir" == "bash" ]]; then 181 + comp_dir="result-${TARGET}/share/bash-completion/completions" 182 + elif [[ "$shell_dir" == "fish" ]]; then 183 + comp_dir="result-${TARGET}/share/fish/vendor_completions.d" 184 + fi 185 + 186 + if [[ -d "$comp_dir" ]]; then 187 + for comp in "$comp_dir"/*; do 188 + local comp_name=$(basename "$comp") 189 + # Only copy completions for this specific binary 190 + if [[ "$comp_name" == "${BINARY}"* ]] || [[ "$comp_name" == "_${BINARY}" ]]; then 191 + mkdir -p "$STAGE_DIR/share/$(dirname "${comp#result-${TARGET}/share/}")" 192 + cp "$comp" "$STAGE_DIR/share/$(dirname "${comp#result-${TARGET}/share/}")/" 193 + fi 194 + done 195 + fi 196 + done 197 + 198 + # Only include example config for lex-fetch 199 + if [[ "$BINARY" == "lex-fetch" ]]; then 200 + mkdir -p "$STAGE_DIR/share/doc/jacquard-lexicon" 201 + cp crates/jacquard-lexicon/lexicons.kdl.example "$STAGE_DIR/share/doc/jacquard-lexicon/" 2>/dev/null || true 202 + fi 137 203 fi 138 204 139 205 # Create versioned archive (for releases) ··· 164 230 165 231 # Cleanup 166 232 rm -rf "$UNVERSIONED_NAME" 167 - rm -f "$PROJECT_ROOT/result-${TARGET}" 233 + 234 + # Return to project root 168 235 cd "$PROJECT_ROOT" 169 236 } 170 237