-
Notifications
You must be signed in to change notification settings - Fork 71
feat: upgrade linux-tools-mac to latest toolsets #168
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
65ab03b
feat: upgrade linux-tools-mac to latest toolsets of gnu-tar, lzip, ma…
mmaietta 9664c6c
boop
mmaietta 8aca613
add binutils' `gar` and `ar`
mmaietta 69100a4
change name to linux-tools-mac for better understandability
mmaietta c876d76
whoops
mmaietta 23741fd
fix build
mmaietta d4595fe
fix arm64 build
mmaietta f154406
stripppppp before install_name_tool
mmaietta 0f383cb
retry
mmaietta d448efe
tmp save
mmaietta fd60b71
xcode 16+ vs xcode 26.5 differences
mmaietta c7e56e5
Merge branch 'master' into linux-tools-v1
mmaietta 77f2463
use macos-26 runners for latest xcode
mmaietta 6278eb4
Merge commit 'c7e56e5f0949ad9bed30a668d876de0397be5330' into linux-to…
mmaietta fcaf128
address PR comments
mmaietta File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| --- | ||
| "linux-tools-mac": major | ||
| --- | ||
|
|
||
| feat: upgrade linux-tools-mac to latest toolsets of gnu-tar, lzip, makedepend, glib, libgsf, libtool, pcre, gettext, binutils | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| name: Build macOS linux-tools-mac bundle | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| workflow_call: | ||
|
|
||
| jobs: | ||
| mac: | ||
| runs-on: ${{ matrix.runner }} | ||
| timeout-minutes: 30 | ||
| strategy: | ||
| fail-fast: false | ||
| matrix: | ||
| runner: [macos-26-intel, macos-26] | ||
| steps: | ||
| - name: Checkout repository | ||
| uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 | ||
|
|
||
| - name: Build | ||
| run: | | ||
| bash ./packages/linux-tools-mac/build.sh | ||
|
|
||
| - name: Upload linux-tools-mac artifact | ||
| uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 | ||
| with: | ||
| name: linux-tools-mac-${{ matrix.runner }} | ||
| path: ./packages/linux-tools-mac/out/**/*.tar.gz | ||
| if-no-files-found: error | ||
| retention-days: 1 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,323 @@ | ||
| #!/usr/bin/env bash | ||
| set -euo pipefail | ||
|
|
||
| if [[ "$(uname -s)" != "Darwin" ]]; then | ||
| echo "❌ Must be run on macOS" | ||
| exit 1 | ||
| fi | ||
|
|
||
| XCODE_VER="$(xcodebuild -version 2>/dev/null | awk '/^Xcode /{print $2}')" | ||
| XCODE_MAJOR="${XCODE_VER%%.*}" | ||
| if [[ -z "$XCODE_MAJOR" || "$XCODE_MAJOR" -lt 26 ]]; then | ||
| echo "❌ Xcode 26+ required (found: ${XCODE_VER:-none})" | ||
| echo " install_name_tool in Xcode < 26 rejects Homebrew ld_prime binaries." | ||
| echo " Use a macos-26 runner." | ||
| exit 1 | ||
| fi | ||
|
|
||
| ### ================================ | ||
| ### ARGS | ||
| ### ================================ | ||
| ARCH="" | ||
| OUTPUT_DIR="" | ||
| ROOT="" | ||
|
|
||
| while [[ $# -gt 0 ]]; do | ||
| case "$1" in | ||
| --arch) ARCH="$2"; shift 2 ;; | ||
| --output-dir) OUTPUT_DIR="$2"; shift 2 ;; | ||
| --root) ROOT="$2"; shift 2 ;; | ||
| *) echo "Unknown argument: $1"; exit 1 ;; | ||
| esac | ||
| done | ||
|
|
||
| ROOT="${ROOT:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}" | ||
| OUTPUT_DIR="${OUTPUT_DIR:-${ROOT}/out/linux-tools-mac}" | ||
| ARCH="${ARCH:-$(uname -m)}" | ||
|
|
||
| if [[ "$ARCH" != "arm64" && "$ARCH" != "x86_64" ]]; then | ||
| echo "❌ Unsupported ARCH: $ARCH" | ||
| exit 1 | ||
| fi | ||
|
|
||
| ### ================================ | ||
| ### CONFIG | ||
| ### ================================ | ||
| TMP_DIR="/tmp/linux-tools-mac-build-${ARCH}" | ||
|
mmaietta marked this conversation as resolved.
|
||
| BUNDLE_DIR="${TMP_DIR}/linux-tools-mac" | ||
| BIN_DIR="${BUNDLE_DIR}/bin" | ||
| LIB_DIR="${BUNDLE_DIR}/lib" | ||
|
|
||
| cleanup() { rm -rf "$TMP_DIR"; } | ||
| trap cleanup EXIT INT TERM | ||
|
|
||
| # Binaries to collect per formula — "formula:bin1 bin2 bin3" entries | ||
| FORMULA_BINS=( | ||
| "gnu-tar:gtar" | ||
| "lzip:lzip" | ||
| "makedepend:makedepend" | ||
| "glib:gapplication gdbus gdbus-codegen gio gio-querymodules glib-compile-resources glib-compile-schemas glib-genmarshal glib-gettextize glib-mkenums gobject-query gresource gsettings gtester gtester-report" | ||
| "libgsf:gsf gsf-office-thumbnailer gsf-vba-dump" | ||
| "libtool:glibtool glibtoolize" | ||
| "pcre:pcre-config pcregrep pcretest" | ||
| "gettext:autopoint envsubst gettext gettext.sh gettextize msgattrib msgcat msgcmp msgcomm msgconv msgen msgexec msgfilter msgfmt msggrep msginit msgmerge msgunfmt msguniq ngettext recode-sr-latin xgettext" | ||
| "binutils:gar ar" | ||
| ) | ||
|
|
||
| echo "🛠️ linux-tools-mac macOS bundle" | ||
| echo " Arch: $ARCH" | ||
| echo " Xcode: $XCODE_VER" | ||
| echo " Output: $OUTPUT_DIR" | ||
|
|
||
| ### ================================ | ||
| ### CLEAN | ||
| ### ================================ | ||
| rm -rf "$TMP_DIR" | ||
| mkdir -p "$BIN_DIR" "$LIB_DIR" | ||
|
|
||
| ### ================================ | ||
| ### INSTALL DEPENDENCIES | ||
| ### ================================ | ||
| echo "" | ||
| echo "📦 Installing brew formulas..." | ||
| brew install gnu-tar lzip makedepend glib libgsf libtool pcre gettext binutils | ||
|
|
||
| ### ================================ | ||
| ### COPY BINARIES | ||
| ### ================================ | ||
| echo "" | ||
| echo "📋 Copying binaries..." | ||
|
|
||
| for entry in "${FORMULA_BINS[@]}"; do | ||
| formula="${entry%%:*}" | ||
| bins="${entry#*:}" | ||
| prefix="$(brew --prefix "$formula" 2>/dev/null || true)" | ||
| if [[ -z "$prefix" ]]; then | ||
| echo " ⚠️ Could not find prefix for $formula, skipping" | ||
| continue | ||
| fi | ||
| for bin in $bins; do | ||
| src="$prefix/bin/$bin" | ||
| if [[ -f "$src" || -L "$src" ]]; then | ||
| echo " ➕ $formula/$bin" | ||
| cp -L "$src" "$BIN_DIR/$bin" | ||
| chmod u+w,a+x "$BIN_DIR/$bin" | ||
| else | ||
| echo " ⏭️ $formula/$bin not found, skipping" | ||
| fi | ||
| done | ||
| done | ||
|
|
||
| ### ================================ | ||
| ### COPY LICENSE FILES | ||
| ### ================================ | ||
| echo "" | ||
| echo "📄 Copying license files..." | ||
| mkdir -p "$BUNDLE_DIR/LICENSES" | ||
|
|
||
|
mmaietta marked this conversation as resolved.
|
||
| for entry in "${FORMULA_BINS[@]}"; do | ||
| formula="${entry%%:*}" | ||
| license_prefix="$(brew --prefix "$formula" 2>/dev/null || true)" | ||
| if [[ -z "$license_prefix" ]]; then | ||
| echo " ⚠️ Could not find prefix for $formula, skipping licenses" | ||
| continue | ||
| fi | ||
|
|
||
| license_dir="$BUNDLE_DIR/LICENSES/$formula" | ||
| mkdir -p "$license_dir" | ||
|
|
||
| found=0 | ||
| for name in COPYING LICENSE LICENCE COPYING.LIB AUTHORS; do | ||
| src="$license_prefix/$name" | ||
| if [[ -f "$src" ]]; then | ||
| cp "$src" "$license_dir/$name" | ||
| echo " 📄 $formula/$name" | ||
|
mmaietta marked this conversation as resolved.
|
||
| found=1 | ||
| fi | ||
| done | ||
| if [[ "$found" -eq 0 ]]; then | ||
| echo " ⚠️ No license file found for $formula in $license_prefix" | ||
| fi | ||
| done | ||
|
|
||
| ### ================================ | ||
| ### COLLECT DYLIB DEPENDENCIES | ||
| ### ================================ | ||
| echo "" | ||
| echo "📚 Collecting dylib dependencies..." | ||
|
|
||
| should_skip_lib() { | ||
| local dep="$1" | ||
| [[ "$dep" == /usr/lib/* ]] && return 0 | ||
| [[ "$dep" == /System/* ]] && return 0 | ||
| [[ "$dep" == @* ]] && return 0 | ||
| return 1 | ||
| } | ||
|
|
||
| is_macho() { | ||
| file -b "$1" 2>/dev/null | grep -q '^Mach-O' | ||
| } | ||
|
|
||
| collect_deps() { | ||
| local binary="$1" | ||
| is_macho "$binary" || return 0 | ||
| otool -L "$binary" 2>/dev/null | awk 'NR>1 {print $1}' | while read -r dep; do | ||
| should_skip_lib "$dep" && continue | ||
| [[ ! -f "$dep" ]] && continue | ||
|
mmaietta marked this conversation as resolved.
|
||
|
|
||
| local dep_name | ||
| dep_name="$(basename "$dep")" | ||
| local dest="$LIB_DIR/$dep_name" | ||
|
|
||
| if [[ ! -f "$dest" ]]; then | ||
| echo " 📥 $dep_name" | ||
| cp -L "$dep" "$dest" | ||
| chmod u+w "$dest" | ||
| # Recurse into this library's own deps | ||
| collect_deps "$dest" | ||
| fi | ||
| done | ||
| } | ||
|
|
||
| find "$BIN_DIR" -type f | while read -r bin; do | ||
| collect_deps "$bin" | ||
| done | ||
|
|
||
| # Also collect deps of libs (they may have deps we missed) | ||
| find "$LIB_DIR" -name "*.dylib" -type f | while read -r lib; do | ||
| collect_deps "$lib" | ||
| done | ||
|
|
||
| ### ================================ | ||
| ### PATCH DYLIB REFERENCES | ||
| ### ================================ | ||
| echo "" | ||
| echo "🔧 Patching dylib references..." | ||
|
|
||
| patch_binary() { | ||
| local binary="$1" | ||
| local is_lib="${2:-false}" | ||
|
|
||
| is_macho "$binary" || return 0 | ||
|
|
||
| # Set install name for dylibs | ||
| if [[ "$is_lib" == "true" ]]; then | ||
| local lib_name | ||
| lib_name="$(basename "$binary")" | ||
| install_name_tool -id "@loader_path/$lib_name" "$binary" 2>/dev/null || true | ||
| fi | ||
|
|
||
| # Patch all absolute non-system dep references | ||
| otool -L "$binary" 2>/dev/null | awk 'NR>1 {print $1}' | while read -r dep; do | ||
| should_skip_lib "$dep" && continue | ||
|
|
||
|
mmaietta marked this conversation as resolved.
|
||
| local dep_name | ||
| dep_name="$(basename "$dep")" | ||
| local dest="$LIB_DIR/$dep_name" | ||
|
|
||
| if [[ -f "$dest" ]]; then | ||
| local new_path | ||
| if [[ "$is_lib" == "true" ]]; then | ||
| new_path="@loader_path/$dep_name" | ||
| else | ||
| new_path="@loader_path/../lib/$dep_name" | ||
| fi | ||
| local it_err | ||
| it_err="$(install_name_tool -change "$dep" "$new_path" "$binary" 2>&1)" \ | ||
| || echo " ⚠️ patch failed [$(basename "$binary")] $dep: $it_err" | ||
| fi | ||
| done | ||
| } | ||
|
|
||
| find "$BIN_DIR" -type f | while read -r bin; do | ||
| echo " 🔁 bin/$(basename "$bin")" | ||
| patch_binary "$bin" "false" | ||
| done | ||
|
|
||
| find "$LIB_DIR" -name "*.dylib" -type f | while read -r lib; do | ||
| echo " 🔁 lib/$(basename "$lib")" | ||
| patch_binary "$lib" "true" | ||
| done | ||
|
|
||
| ### ================================ | ||
| ### STRIP SYMBOLS | ||
| ### ================================ | ||
| echo "" | ||
| echo "✂️ Stripping symbols..." | ||
| find "$BUNDLE_DIR" -type f | while read -r f; do | ||
| strip -x "$f" 2>/dev/null || true | ||
| done | ||
|
|
||
| ### ================================ | ||
| ### AD-HOC CODESIGN | ||
| ### ================================ | ||
| echo "" | ||
| echo "🔏 Code signing..." | ||
|
|
||
| # Sign libs first (executables may load them) | ||
| find "$LIB_DIR" -name "*.dylib" -type f | while read -r lib; do | ||
| codesign --force --sign - "$lib" 2>/dev/null || true | ||
| done | ||
|
|
||
| find "$BIN_DIR" -type f | while read -r bin; do | ||
| codesign --force --sign - "$bin" 2>/dev/null || true | ||
| done | ||
|
|
||
| ### ================================ | ||
| ### VERSION.txt | ||
| ### ================================ | ||
| echo "" | ||
| echo "📝 Writing VERSION.txt..." | ||
| { | ||
| echo "platform: darwin" | ||
| echo "arch: $ARCH" | ||
| echo "created_at: $(date -u +"%Y-%m-%dT%H:%M:%SZ")" | ||
| echo "" | ||
| for formula in gnu-tar lzip makedepend glib libgsf libtool pcre gettext binutils; do | ||
| ver="$(brew info --json "$formula" 2>/dev/null | python3 -c "import sys,json; d=json.load(sys.stdin); print(d[0]['versions']['stable'])" 2>/dev/null || echo "unknown")" | ||
| echo "$formula: $ver" | ||
| done | ||
| } > "$BUNDLE_DIR/VERSION.txt" | ||
|
|
||
| ### ================================ | ||
| ### ARCHIVE | ||
| ### ================================ | ||
| echo "" | ||
| echo "📦 Creating archive..." | ||
| mkdir -p "$OUTPUT_DIR" | ||
|
|
||
| ARCHIVE_ARCH="$ARCH" | ||
| ARCHIVE_NAME="linux-tools-mac-darwin-${ARCHIVE_ARCH}.tar.gz" | ||
| ARCHIVE_PATH="$OUTPUT_DIR/$ARCHIVE_NAME" | ||
|
|
||
| tar -czf "$ARCHIVE_PATH" -C "$TMP_DIR" linux-tools-mac | ||
| shasum -a 256 "$ARCHIVE_PATH" > "${ARCHIVE_PATH}.sha256" | ||
|
|
||
| rm -rf "$TMP_DIR" | ||
|
|
||
| ### ================================ | ||
| ### TEST | ||
| ### ================================ | ||
| echo "" | ||
| echo "🧪 Running tests..." | ||
|
|
||
| VERIFY_DIR="/tmp/linux-tools-mac-verify-$$" | ||
| mkdir -p "$VERIFY_DIR" | ||
| tar -xzf "$ARCHIVE_PATH" -C "$VERIFY_DIR" | ||
|
|
||
| bash "$ROOT/assets/test.sh" --bundle-dir "$VERIFY_DIR/linux-tools-mac" | ||
|
|
||
| rm -rf "$VERIFY_DIR" | ||
|
|
||
| ### ================================ | ||
| ### DONE | ||
| ### ================================ | ||
| SIZE="$(du -sh "$ARCHIVE_PATH" | cut -f1)" | ||
| echo "" | ||
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | ||
| echo "✅ DONE" | ||
| echo "• Arch: $ARCH" | ||
| echo "• Archive: $ARCHIVE_NAME" | ||
| echo "• Size: $SIZE" | ||
| echo "• Path: $ARCHIVE_PATH" | ||
| echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━" | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.