From eec4746a56d0b55e4d592253fee76531fb2bafb0 Mon Sep 17 00:00:00 2001 From: draco892 Date: Tue, 13 Oct 2026 11:01:40 +0200 Subject: [PATCH 1/2] build: automatically include craft-fonts in desktop packages Detect ../craft-fonts or use CRAFT_FONTS_DIR on macOS, Linux and Windows. Download the pinned release revision when the checkout is missing and require Chinese and Japanese fonts during the build. Document font setup and preserve skip-build behavior. --- docs/releasing.md | 10 ++++++++++ packaging/fonts.sh | 31 +++++++++++++++++++++++++++++++ packaging/linux/package.sh | 4 ++++ packaging/macos/package.sh | 4 ++++ packaging/windows/fonts.ps1 | 24 ++++++++++++++++++++++++ packaging/windows/package.ps1 | 4 ++++ 6 files changed, 77 insertions(+) create mode 100644 packaging/fonts.sh create mode 100644 packaging/windows/fonts.ps1 diff --git a/docs/releasing.md b/docs/releasing.md index feff91d87..44a1afaaa 100644 --- a/docs/releasing.md +++ b/docs/releasing.md @@ -64,6 +64,16 @@ whose glyph-coverage test checks the characters in available faces. `CRAFT_FONTS the native build fail if the pinned manifest lacks Noto Sans CJK SC Regular (`Hans`) or BIZ UDPGothic Regular; the web build requires BIZ UDPGothic Regular and packages Noto Sans CJK SC as a separate asset. +Local macOS, Linux and Windows packaging scripts automatically use the sibling `../craft-fonts` +checkout. If it is absent, they clone it at revision +`8dcdacd5153e64560d109541a47d806f26f048c0` (keep the pins in `packaging/fonts.sh` and +`packaging/windows/fonts.ps1` in sync with the release workflow). Existing checkouts are left untouched. +Set `CRAFT_FONTS_DIR` to use another +checkout; relative paths resolve from the workspace root. The script requires the Chinese and Japanese +UI faces and includes their OFL licences in the package. Download failures or incomplete checkouts +stop packaging with an error. `--skip-build` (`-SkipBuild` on Windows) packages existing binaries without downloading fonts or +changing what they embed; pass the same `CRAFT_FONTS_DIR` used to compile them so their licences ship. + ## Signing credentials All credentials are stored as secrets in the GitHub `release` environment. Signing is optional: diff --git a/packaging/fonts.sh b/packaging/fonts.sh new file mode 100644 index 000000000..61dc913f4 --- /dev/null +++ b/packaging/fonts.sh @@ -0,0 +1,31 @@ +# shellcheck shell=bash +# Font setup for local packaging; sourced after packaging/env.sh. +prepare_fonts() { + local font_dir="${CRAFT_FONTS_DIR:-$ROOT/../craft-fonts}" + # Relative overrides are documented relative to the workspace, regardless of the caller's cwd. + case "$font_dir" in + /*) ;; + *) font_dir="$ROOT/$font_dir" ;; + esac + + if [ -z "${CRAFT_FONTS_DIR:-}" ] && [ ! -e "$font_dir" ]; then + # Same revision as release.yml. Never update or reset an existing checkout. + local revision=8dcdacd5153e64560d109541a47d806f26f048c0 + echo "==> downloading craft-fonts ($revision) to $font_dir" + if ! git clone --no-checkout https://github.com/storytold/craft-fonts "$font_dir" || + ! git -C "$font_dir" checkout --detach "$revision"; then + echo "error: could not prepare craft-fonts; provide a complete checkout with CRAFT_FONTS_DIR" >&2 + return 1 + fi + fi + + if [ ! -f "$font_dir/fonts/manifest.txt" ]; then + echo "error: missing $font_dir/fonts/manifest.txt; set CRAFT_FONTS_DIR to a complete craft-fonts checkout" >&2 + return 1 + fi + CRAFT_FONTS_DIR="$(cd "$font_dir" && pwd)" || return 1 + export CRAFT_FONTS_DIR + # Fail the build if required faces are missing, rather than ship empty glyph boxes. + export CRAFT_FONTS_REQUIRED=1 + echo "==> embedding fonts from $CRAFT_FONTS_DIR" +} diff --git a/packaging/linux/package.sh b/packaging/linux/package.sh index b5e1d9457..383c20f07 100755 --- a/packaging/linux/package.sh +++ b/packaging/linux/package.sh @@ -8,6 +8,7 @@ # $DIST/lightcraft--linux-.tar.gz plain FHS-style tree (bin/, share/) # # Usage: packaging/linux/package.sh [--skip-build] [--formats "appimage deb rpm tar"] +# Fonts: use CRAFT_FONTS_DIR or ../craft-fonts; download the pinned checkout if absent. # # Needs: cargo; nfpm for deb/rpm (https://nfpm.goreleaser.com); appimagetool for the AppImage # (downloaded into $CARGO_TARGET_DIR if missing). Build on an old distro (CI: Ubuntu 22.04, @@ -45,6 +46,9 @@ BASENAME="lightcraft-$VERSION-linux-$ARCH" echo "==> LightCraft $VERSION for Linux $ARCH ($FORMATS)" if [ "$SKIP_BUILD" = 0 ]; then + # shellcheck source=../fonts.sh + . "$ROOT/packaging/fonts.sh" + prepare_fonts (cd "$ROOT" && cargo build --release --locked -p lightcraft -p lightcraft-cli --features lightcraft/heif,lightcraft-cli/heif \ ${CROSS_TARGET:+--target "$CROSS_TARGET"}) fi diff --git a/packaging/macos/package.sh b/packaging/macos/package.sh index b26aa96d6..f26237a4c 100755 --- a/packaging/macos/package.sh +++ b/packaging/macos/package.sh @@ -5,6 +5,7 @@ # $DIST/lightcraft-cli--macos-.zip the headless CLI # # Usage: packaging/macos/package.sh [--arch universal|aarch64|x86_64] [--skip-build] +# Fonts: use CRAFT_FONTS_DIR or ../craft-fonts; download the pinned checkout if absent. # # Signing (env): # MACOS_SIGN_IDENTITY codesign identity (name or SHA-1). Default "-" = ad-hoc (local testing; @@ -56,6 +57,9 @@ echo "==> LightCraft $VERSION for macOS ($ARCH), identity: $IDENTITY, notarize: # ---- build ------------------------------------------------------------------------------------- if [ "$SKIP_BUILD" = 0 ]; then + # shellcheck source=../fonts.sh + . "$ROOT/packaging/fonts.sh" + prepare_fonts args=() for t in "${TARGETS[@]}"; do args+=(--target "$t"); done (cd "$ROOT" && cargo build --release --locked -p lightcraft -p lightcraft-cli --features lightcraft/heif,lightcraft-cli/heif "${args[@]}") diff --git a/packaging/windows/fonts.ps1 b/packaging/windows/fonts.ps1 new file mode 100644 index 000000000..c927fbb7a --- /dev/null +++ b/packaging/windows/fonts.ps1 @@ -0,0 +1,24 @@ +# Font setup for local packaging; dot-sourced by package.ps1. +function Initialize-CraftFonts([string] $WorkspaceRoot) { + $fontDir = $env:CRAFT_FONTS_DIR + if (-not $fontDir) { $fontDir = Join-Path $WorkspaceRoot '../craft-fonts' } + if (-not [IO.Path]::IsPathRooted($fontDir)) { $fontDir = Join-Path $WorkspaceRoot $fontDir } + + if (-not $env:CRAFT_FONTS_DIR -and -not (Test-Path -LiteralPath $fontDir)) { + # Same revision as release.yml and packaging/fonts.sh. Existing checkouts stay untouched. + $revision = '8dcdacd5153e64560d109541a47d806f26f048c0' + Write-Output "==> downloading craft-fonts ($revision) to $fontDir" + & git clone --no-checkout https://github.com/storytold/craft-fonts $fontDir + if ($LASTEXITCODE -ne 0) { throw 'Could not download craft-fonts; provide a complete checkout with CRAFT_FONTS_DIR' } + & git -C $fontDir checkout --detach $revision + if ($LASTEXITCODE -ne 0) { throw 'Could not check out craft-fonts; provide a complete checkout with CRAFT_FONTS_DIR' } + } + + $manifest = Join-Path $fontDir 'fonts/manifest.txt' + if (-not (Test-Path -LiteralPath $manifest -PathType Leaf)) { + throw "Missing $manifest; set CRAFT_FONTS_DIR to a complete craft-fonts checkout" + } + $env:CRAFT_FONTS_DIR = (Resolve-Path -LiteralPath $fontDir).Path + $env:CRAFT_FONTS_REQUIRED = '1' + Write-Output "==> embedding fonts from $env:CRAFT_FONTS_DIR" +} diff --git a/packaging/windows/package.ps1 b/packaging/windows/package.ps1 index e2cd2a8e7..27e0f0a03 100644 --- a/packaging/windows/package.ps1 +++ b/packaging/windows/package.ps1 @@ -11,6 +11,8 @@ zip needs the Visual C++ redistributable. Signing is delegated to sign.ps1 (skipped with a warning when no signing secrets are set). + Fonts: uses CRAFT_FONTS_DIR or ../craft-fonts; downloads the pinned checkout if absent. + Needs: Rust (MSVC toolchain + the target), the Windows SDK (rc.exe, signtool.exe), and WiX v5: dotnet tool install --global wix --version 5.0.2 The WiX UI and Util extensions (installer dialogs, "Launch LightCraft" on Finish) are added to @@ -81,6 +83,8 @@ if (-not $env:LIGHTCRAFT_BUILD_DATE) { $env:LIGHTCRAFT_BUILD_DATE = (Get-Date).T Write-Output "LightCraft $Version for Windows $Arch ($Target)" if (-not $SkipBuild) { + . (Join-Path $PSScriptRoot 'fonts.ps1') + Initialize-CraftFonts $Root # Static CRT: no VC++ redistributable needed. Scoped to the target so host build scripts and # proc-macros are unaffected. $flagVar = 'CARGO_TARGET_' + ($Target.ToUpper() -replace '-', '_') + '_RUSTFLAGS' From bd0ca28bb0186ec8e74b53862763949fabbf71cb Mon Sep 17 00:00:00 2001 From: draco892 Date: Tue, 13 Oct 2026 12:00:04 +0200 Subject: [PATCH 2/2] build: fix host architecture detection in Windows PowerShell 5.1 Use Windows environment variables instead of RuntimeInformation to avoid a null value during the final CLI smoke test. Account for emulated shells using PROCESSOR_ARCHITEW6432. --- packaging/windows/package.ps1 | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packaging/windows/package.ps1 b/packaging/windows/package.ps1 index 27e0f0a03..24101e707 100644 --- a/packaging/windows/package.ps1 +++ b/packaging/windows/package.ps1 @@ -167,7 +167,15 @@ Compress-Archive -Path $Portable -DestinationPath $Zip # Smoke-test the CLI when this machine can run it. An ARM64 build made on an x64 runner can't run # here; .github/workflows/windows-arm64.yml installs and runs it on ARM64 instead. -$HostArch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant() +# Windows PowerShell 5.1 can expose OSArchitecture as null. Use Windows' environment +# variables instead; PROCESSOR_ARCHITEW6432 identifies the OS when the shell is emulated. +$nativeArchitecture = if ($env:PROCESSOR_ARCHITEW6432) { $env:PROCESSOR_ARCHITEW6432 } else { $env:PROCESSOR_ARCHITECTURE } +$HostArch = switch ($nativeArchitecture) { + 'AMD64' { 'x64' } + 'x86' { 'x86' } + 'ARM64' { 'arm64' } + default { 'unknown' } +} if ($Arch -ne 'arm64' -or $HostArch -eq 'arm64') { Invoke-Native 'lightcraft-cli --version' { & (Join-Path $Stage 'lightcraft-cli.exe') --version } } else {