This commit is contained in:
Alan Wang 2026-10-28 10:10:50 +08:00 committed by GitHub
commit 3f68c8bfcf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 157 additions and 0 deletions

48
.github/workflows/apple-silicon.yml vendored Normal file
View file

@ -0,0 +1,48 @@
name: Apple Silicon
on:
push:
paths:
- '.github/workflows/apple-silicon.yml'
- 'scripts/build-apple-silicon.sh'
- 'desktop/**'
- 'n-link-core/**'
- 'package.json'
- 'yarn.lock'
- 'postcss.config.js'
- 'LICENSE'
pull_request:
paths:
- '.github/workflows/apple-silicon.yml'
- 'scripts/build-apple-silicon.sh'
- 'desktop/**'
- 'n-link-core/**'
- 'package.json'
- 'yarn.lock'
- 'postcss.config.js'
- 'LICENSE'
workflow_dispatch:
permissions:
contents: read
jobs:
build:
runs-on: macos-15
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Install Rust toolchain
run: rustup toolchain install 1.77.2 --profile minimal
- name: Build native app and archive
run: ./scripts/build-apple-silicon.sh
- uses: actions/upload-artifact@v4
with:
name: n-link-macos-arm64
path: |
releases/N-Link_*_macOS_arm64.zip
releases/N-Link_*_macOS_arm64.zip.sha256
if-no-files-found: error

4
.gitignore vendored
View file

@ -23,3 +23,7 @@ pnpm-debug.log*
*.sw?
*.tns
# Local macOS release artifacts
/releases/
/desktop/dist/

View file

@ -2,6 +2,33 @@
Free, cross-platform, CX-II compatible computer linking program for the TI-Nspire
## Native Apple Silicon build
From the repository root, run:
```sh
rustup toolchain install 1.77.2 --profile minimal
./scripts/build-apple-silicon.sh
```
Requires Apple's Command Line Tools, Node.js/npm, Python 3, and Rust installed
through rustup. Node.js 22 is used in CI. The script selects Rust 1.77.2 for
this build to support the project's 2021 dependencies, and uses the existing Yarn and Cargo
lockfiles, skips the old Tauri CLI's Intel-only installer, builds the frontend,
and compiles the backend for `aarch64-apple-darwin`. `libusb` is linked statically;
the resulting app needs only macOS system libraries.
Outputs are `releases/N-Link.app`, `releases/N-Link_0.1.6_macOS_arm64.zip`, and
the ZIP's SHA-256 checksum. The app is ad-hoc signed for local use; it is not
Developer ID signed or notarized. Install it by copying `N-Link.app` to
`~/Applications` and opening it.
The deployment target is macOS 11.0; older macOS versions still need runtime
testing. `.github/workflows/apple-silicon.yml` builds on a native ARM64 runner,
checks the architecture and code signature, and uploads the release ZIP and
checksum as an Actions artifact. USB behavior needs testing on a physical Mac
with a connected calculator.
## Project setup
You'll need to install [Node.js](https://nodejs.org/en/download/package-manager),
[Yarn](https://classic.yarnpkg.com/en/docs/install/) (which may be included with your installation of Node.js), and

View file

@ -1,3 +1,4 @@
module.exports = {
publicPath: process.env.TAURI_BUILD ? './' : '/',
transpileDependencies: ['n-link-core']
}

77
scripts/build-apple-silicon.sh Executable file
View file

@ -0,0 +1,77 @@
#!/bin/bash
set -euo pipefail
cd "$(dirname "$0")/.."
if [[ "$(uname -s)" != Darwin || "$(uname -m)" != arm64 ]]; then
echo "Run this script natively on an Apple Silicon Mac." >&2
exit 1
fi
export PATH="$HOME/.cargo/bin:$PATH"
export MACOSX_DEPLOYMENT_TARGET=11.0
# Keep the legacy dependencies buildable without changing other build targets.
rust_toolchain=1.77.2
if ! rustup run "$rust_toolchain" rustc --version >/dev/null 2>&1; then
echo "Install the build toolchain with: rustup toolchain install $rust_toolchain --profile minimal" >&2
exit 1
fi
# Skip the legacy Tauri CLI's installer, which fetches an Intel executable.
npm exec --yes --package yarn@1.22.22 -- yarn install \
--frozen-lockfile --ignore-engines --ignore-scripts --non-interactive
(
cd desktop
TAURI_BUILD=true NODE_OPTIONS="${NODE_OPTIONS:-} --openssl-legacy-provider" \
node ../node_modules/@vue/cli-service/bin/vue-cli-service.js build
)
(
cd desktop/src-tauri
cargo +"$rust_toolchain" build --release --locked --target aarch64-apple-darwin
)
app="$PWD/releases/N-Link.app"
mkdir -p "$app/Contents/MacOS" "$app/Contents/Resources"
cp desktop/src-tauri/target/aarch64-apple-darwin/release/n-link "$app/Contents/MacOS/n-link"
cp desktop/src-tauri/icons/icon.icns "$app/Contents/Resources/icon.icns"
cp LICENSE "$app/Contents/Resources/LICENSE"
python3 - "$app/Contents/Info.plist" <<'PY'
import json
import os
import plistlib
import sys
with open('desktop/package.json') as f:
version = json.load(f)['version']
with open('desktop/src-tauri/tauri.conf.json') as f:
bundle = json.load(f)['tauri']['bundle']
with open(sys.argv[1], 'wb') as f:
plistlib.dump({
'CFBundleDevelopmentRegion': 'en',
'CFBundleDisplayName': 'N-Link',
'CFBundleExecutable': 'n-link',
'CFBundleIconFile': 'icon.icns',
'CFBundleIdentifier': bundle['identifier'],
'CFBundleInfoDictionaryVersion': '6.0',
'CFBundleName': 'N-Link',
'CFBundlePackageType': 'APPL',
'CFBundleShortVersionString': version,
'CFBundleVersion': version,
'LSApplicationCategoryType': 'public.app-category.utilities',
'LSMinimumSystemVersion': os.environ['MACOSX_DEPLOYMENT_TARGET'],
'NSHighResolutionCapable': True,
'NSHumanReadableCopyright': bundle['copyright'],
'NSPrincipalClass': 'NSApplication',
}, f)
PY
codesign --force --sign - --timestamp=none "$app"
codesign --verify --deep --strict "$app"
[[ "$(lipo -archs "$app/Contents/MacOS/n-link")" == arm64 ]]
"$app/Contents/MacOS/n-link" --version
version="$(node -p 'require("./desktop/package.json").version')"
archive="$PWD/releases/N-Link_${version}_macOS_arm64.zip"
ditto -c -k --sequesterRsrc --keepParent "$app" "$archive"
(
cd releases
shasum -a 256 "$(basename "$archive")" > "$(basename "$archive").sha256"
)
echo "Built: $app"
echo "Archive: $archive"