mirror of
https://github.com/veeso/termscp.git
synced 2026-09-27 06:21:22 -07:00
ci(release): build Linux artifacts as static musl binaries (#447)
Build Linux release artifacts as statically linked musl binaries for x86_64 and aarch64, update packaging and updater handling, and document the reduced runtime requirements. Keep release version preparation locked without refreshing dependencies or committing Cargo.lock. Closes #440
This commit is contained in:
@@ -21,6 +21,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
version: ${{ inputs.version }}
|
version: ${{ inputs.version }}
|
||||||
|
prepared_ref: ${{ steps.prepared-ref.outputs.ref }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
@@ -44,7 +45,7 @@ jobs:
|
|||||||
git config user.email "christian.visintin@veeso.dev"
|
git config user.email "christian.visintin@veeso.dev"
|
||||||
|
|
||||||
- name: Install git-cliff
|
- name: Install git-cliff
|
||||||
uses: taiki-e/install-action@37f7c5781271959fb65b6b35224e28652ff2b63d # v2.87.0
|
uses: taiki-e/install-action@e67fa11c4b9316fa714ddf0abed07a0c3143b95b # v2.87.4
|
||||||
with:
|
with:
|
||||||
tool: git-cliff
|
tool: git-cliff
|
||||||
|
|
||||||
@@ -66,6 +67,9 @@ jobs:
|
|||||||
VERSION: ${{ inputs.version }}
|
VERSION: ${{ inputs.version }}
|
||||||
run: git-cliff --unreleased --tag "v$VERSION" --strip header -o RELEASE_NOTES.md
|
run: git-cliff --unreleased --tag "v$VERSION" --strip header -o RELEASE_NOTES.md
|
||||||
|
|
||||||
|
- name: Verify Cargo.lock is unchanged
|
||||||
|
run: git diff --exit-code -- Cargo.lock
|
||||||
|
|
||||||
- name: Upload release notes
|
- name: Upload release notes
|
||||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||||
with:
|
with:
|
||||||
@@ -84,10 +88,22 @@ jobs:
|
|||||||
VERSION: ${{ inputs.version }}
|
VERSION: ${{ inputs.version }}
|
||||||
run: |
|
run: |
|
||||||
rm -f RELEASE_NOTES.md
|
rm -f RELEASE_NOTES.md
|
||||||
git add -A
|
git add -A -- . ':!Cargo.lock'
|
||||||
|
git diff --cached --exit-code -- Cargo.lock
|
||||||
git commit -m "chore: release v$VERSION"
|
git commit -m "chore: release v$VERSION"
|
||||||
git push origin HEAD:main
|
git push origin HEAD:main
|
||||||
|
|
||||||
|
- name: Export prepared ref
|
||||||
|
id: prepared-ref
|
||||||
|
env:
|
||||||
|
DRY_RUN: ${{ inputs.dry_run }}
|
||||||
|
run: |
|
||||||
|
if [ "$DRY_RUN" = "true" ]; then
|
||||||
|
echo "ref=$GITHUB_SHA" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "ref=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
build:
|
build:
|
||||||
needs: prepare
|
needs: prepare
|
||||||
name: build-${{ matrix.target }}
|
name: build-${{ matrix.target }}
|
||||||
@@ -95,14 +111,12 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- target: x86_64-unknown-linux-gnu
|
- target: x86_64-unknown-linux-musl
|
||||||
os: ubuntu-latest
|
os: ubuntu-24.04
|
||||||
kind: linux
|
kind: linux
|
||||||
deb_suffix: amd64
|
- target: aarch64-unknown-linux-musl
|
||||||
- target: aarch64-unknown-linux-gnu
|
|
||||||
os: ubuntu-24.04-arm
|
os: ubuntu-24.04-arm
|
||||||
kind: linux
|
kind: linux
|
||||||
deb_suffix: arm64
|
|
||||||
- target: aarch64-apple-darwin
|
- target: aarch64-apple-darwin
|
||||||
os: macos-latest
|
os: macos-latest
|
||||||
kind: macos
|
kind: macos
|
||||||
@@ -125,58 +139,44 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
ref: ${{ inputs.dry_run && github.sha || 'main' }}
|
ref: ${{ needs.prepare.outputs.prepared_ref }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
|
- name: Prepare release version
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
dist/release/bump_version.sh "$VERSION" "$(date +%F)"
|
||||||
|
cargo update --package termscp --precise "$VERSION"
|
||||||
|
cargo metadata --locked --no-deps --format-version 1 > /dev/null
|
||||||
- name: Install just
|
- name: Install just
|
||||||
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
- name: Install Rust target
|
- name: Install Rust target
|
||||||
if: matrix.kind != 'windows'
|
if: matrix.kind == 'macos'
|
||||||
run: rustup target add "$TARGET"
|
run: rustup target add "$TARGET"
|
||||||
- name: Install Rust target
|
- name: Install Rust target
|
||||||
if: matrix.kind == 'windows'
|
if: matrix.kind == 'windows'
|
||||||
run: rustup target add "$env:TARGET"
|
run: rustup target add "$env:TARGET"
|
||||||
|
|
||||||
# ---- Linux: native per-arch build (x86_64 on ubuntu-latest, aarch64 on ubuntu-24.04-arm) ----
|
# ---- Linux: static musl build in a pinned Alpine container ----
|
||||||
- name: Install dependencies (Linux)
|
- name: Install cargo-deb (Linux)
|
||||||
if: matrix.kind == 'linux'
|
if: matrix.kind == 'linux'
|
||||||
run: |
|
run: cargo install cargo-deb --locked
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y \
|
|
||||||
make \
|
|
||||||
libgit2-dev \
|
|
||||||
build-essential \
|
|
||||||
pkg-config \
|
|
||||||
libbsd-dev \
|
|
||||||
libcap-dev \
|
|
||||||
libcups2-dev \
|
|
||||||
libgnutls28-dev \
|
|
||||||
libicu-dev \
|
|
||||||
libjansson-dev \
|
|
||||||
libkeyutils-dev \
|
|
||||||
libldap2-dev \
|
|
||||||
zlib1g-dev \
|
|
||||||
libpam0g-dev \
|
|
||||||
libacl1-dev \
|
|
||||||
libarchive-dev \
|
|
||||||
flex \
|
|
||||||
bison \
|
|
||||||
libntirpc-dev \
|
|
||||||
libtracker-sparql-3.0-dev \
|
|
||||||
libglib2.0-dev \
|
|
||||||
libdbus-1-dev \
|
|
||||||
libsasl2-dev \
|
|
||||||
libunistring-dev \
|
|
||||||
cpanminus
|
|
||||||
sudo cpanm Parse::Yapp::Driver
|
|
||||||
cargo install cargo-deb
|
|
||||||
- name: Build (Linux)
|
- name: Build (Linux)
|
||||||
if: matrix.kind == 'linux'
|
if: matrix.kind == 'linux'
|
||||||
run: just build_release "$TARGET" "--features smb-vendored"
|
run: just build_musl "$TARGET"
|
||||||
- name: Build deb (Linux)
|
- name: Build deb (Linux)
|
||||||
if: matrix.kind == 'linux'
|
if: matrix.kind == 'linux'
|
||||||
run: just package_deb "$TARGET"
|
run: cargo deb --locked --no-build --target "$TARGET" --features smb-vendored
|
||||||
|
- name: Verify deb declares no runtime dependencies (Linux)
|
||||||
|
if: matrix.kind == 'linux'
|
||||||
|
run: |
|
||||||
|
deb=$(ls target/"$TARGET"/debian/*.deb)
|
||||||
|
depends=$(dpkg-deb -f "$deb" Depends)
|
||||||
|
if [ -n "$depends" ]; then
|
||||||
|
echo "static deb must have no Depends, got: $depends" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# ---- macOS ----
|
# ---- macOS ----
|
||||||
- name: Install deps (macOS)
|
- name: Install deps (macOS)
|
||||||
@@ -229,7 +229,7 @@ jobs:
|
|||||||
if-no-files-found: error
|
if-no-files-found: error
|
||||||
|
|
||||||
publish-homebrew:
|
publish-homebrew:
|
||||||
needs: [prepare, build]
|
needs: [prepare, build, release]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
VERSION: ${{ needs.prepare.outputs.version }}
|
VERSION: ${{ needs.prepare.outputs.version }}
|
||||||
@@ -255,8 +255,8 @@ jobs:
|
|||||||
cd "$GITHUB_WORKSPACE"
|
cd "$GITHUB_WORKSPACE"
|
||||||
SHA_MAC_ARM=$(cat dl/aarch64-apple-darwin.sha256)
|
SHA_MAC_ARM=$(cat dl/aarch64-apple-darwin.sha256)
|
||||||
SHA_MAC_X64=$(cat dl/x86_64-apple-darwin.sha256)
|
SHA_MAC_X64=$(cat dl/x86_64-apple-darwin.sha256)
|
||||||
SHA_LIN_ARM=$(cat dl/aarch64-unknown-linux-gnu.sha256)
|
SHA_LIN_ARM=$(cat dl/aarch64-unknown-linux-musl.sha256)
|
||||||
SHA_LIN_X64=$(cat dl/x86_64-unknown-linux-gnu.sha256)
|
SHA_LIN_X64=$(cat dl/x86_64-unknown-linux-musl.sha256)
|
||||||
BASE="https://github.com/veeso/termscp/releases/latest/download"
|
BASE="https://github.com/veeso/termscp/releases/latest/download"
|
||||||
cat > tap/Formula/termscp.rb <<EOF
|
cat > tap/Formula/termscp.rb <<EOF
|
||||||
class Termscp < Formula
|
class Termscp < Formula
|
||||||
@@ -293,14 +293,12 @@ jobs:
|
|||||||
end
|
end
|
||||||
|
|
||||||
on_linux do
|
on_linux do
|
||||||
depends_on "dbus"
|
|
||||||
|
|
||||||
on_arm do
|
on_arm do
|
||||||
url "$BASE/termscp-v$VERSION-aarch64-unknown-linux-gnu.tar.gz"
|
url "$BASE/termscp-v$VERSION-aarch64-unknown-linux-musl.tar.gz"
|
||||||
sha256 "$SHA_LIN_ARM"
|
sha256 "$SHA_LIN_ARM"
|
||||||
end
|
end
|
||||||
on_intel do
|
on_intel do
|
||||||
url "$BASE/termscp-v$VERSION-x86_64-unknown-linux-gnu.tar.gz"
|
url "$BASE/termscp-v$VERSION-x86_64-unknown-linux-musl.tar.gz"
|
||||||
sha256 "$SHA_LIN_X64"
|
sha256 "$SHA_LIN_X64"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -336,9 +334,15 @@ jobs:
|
|||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.RELEASE_PAT }}
|
token: ${{ secrets.RELEASE_PAT }}
|
||||||
ref: ${{ inputs.dry_run && github.sha || 'main' }}
|
ref: ${{ needs.prepare.outputs.prepared_ref }}
|
||||||
persist-credentials: true
|
persist-credentials: true
|
||||||
|
|
||||||
|
- name: Prepare release version
|
||||||
|
run: |
|
||||||
|
dist/release/bump_version.sh "$VERSION" "$(date +%F)"
|
||||||
|
cargo update --package termscp --precise "$VERSION"
|
||||||
|
cargo metadata --locked --no-deps --format-version 1 > /dev/null
|
||||||
|
|
||||||
- name: Download build artifacts
|
- name: Download build artifacts
|
||||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||||
with:
|
with:
|
||||||
@@ -399,10 +403,15 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
|
||||||
with:
|
with:
|
||||||
ref: main
|
ref: ${{ needs.prepare.outputs.prepared_ref }}
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
fetch-tags: true
|
fetch-tags: true
|
||||||
|
- name: Prepare release version
|
||||||
|
run: |
|
||||||
|
dist/release/bump_version.sh "$VERSION" "$(date +%F)"
|
||||||
|
cargo update --package termscp --precise "$VERSION"
|
||||||
|
cargo metadata --locked --no-deps --format-version 1 > /dev/null
|
||||||
- name: Install just
|
- name: Install just
|
||||||
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
uses: extractions/setup-just@53165ef7e734c5c07cb06b3c8e7b647c5aa16db3 # v4
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ termscp = { path = "/usr/bin/termscp" }
|
|||||||
[package.metadata.deb]
|
[package.metadata.deb]
|
||||||
maintainer = "Christian Visintin <christian.visintin@veeso.dev>"
|
maintainer = "Christian Visintin <christian.visintin@veeso.dev>"
|
||||||
copyright = "2025, Christian Visintin <christian.visintin@veeso.dev>"
|
copyright = "2025, Christian Visintin <christian.visintin@veeso.dev>"
|
||||||
|
depends = ""
|
||||||
extended-description-file = "docs/misc/README.deb.txt"
|
extended-description-file = "docs/misc/README.deb.txt"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
|||||||
@@ -117,6 +117,12 @@ For more information or other platforms, please visit [termscp.rs](https://terms
|
|||||||
|
|
||||||
### Requirements ❗
|
### Requirements ❗
|
||||||
|
|
||||||
|
The official Linux binaries and `.deb` packages are statically linked against
|
||||||
|
musl and have **no runtime requirements**: they run on any distribution and
|
||||||
|
any glibc version.
|
||||||
|
|
||||||
|
These are only required to build termscp from source:
|
||||||
|
|
||||||
- **Linux** users:
|
- **Linux** users:
|
||||||
- libdbus-1
|
- libdbus-1
|
||||||
- pkg-config
|
- pkg-config
|
||||||
|
|||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# Builds a static musl termscp release binary for the given target triple
|
||||||
|
# inside a pinned Alpine container.
|
||||||
|
#
|
||||||
|
# Usage: dist/release/build_musl.sh <target-triple>
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
IMAGE="rust:1.98-alpine3.22"
|
||||||
|
|
||||||
|
TARGET="${1:-}"
|
||||||
|
if [ -z "$TARGET" ]; then
|
||||||
|
echo "usage: $0 <target-triple>" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
case "$TARGET" in
|
||||||
|
x86_64-unknown-linux-musl) PLATFORM="linux/amd64" ;;
|
||||||
|
aarch64-unknown-linux-musl) PLATFORM="linux/arm64" ;;
|
||||||
|
*)
|
||||||
|
echo "unsupported target: $TARGET" >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
WORKSPACE="$(CDPATH='' cd -- "$(dirname -- "$0")/../.." && pwd)"
|
||||||
|
|
||||||
|
# The container appends a [patch.crates-io] section to Cargo.toml and updates
|
||||||
|
# Cargo.lock; keep byte-exact copies so the workspace is clean afterwards.
|
||||||
|
BACKUP_DIR="$(mktemp -d)"
|
||||||
|
cp -p "$WORKSPACE/Cargo.toml" "$BACKUP_DIR/Cargo.toml"
|
||||||
|
cp -p "$WORKSPACE/Cargo.lock" "$BACKUP_DIR/Cargo.lock"
|
||||||
|
|
||||||
|
restore_manifests() {
|
||||||
|
cp -p "$BACKUP_DIR/Cargo.toml" "$WORKSPACE/Cargo.toml"
|
||||||
|
cp -p "$BACKUP_DIR/Cargo.lock" "$WORKSPACE/Cargo.lock"
|
||||||
|
rm -rf "$BACKUP_DIR"
|
||||||
|
}
|
||||||
|
trap restore_manifests EXIT
|
||||||
|
|
||||||
|
HOST_UID="$(id -u)"
|
||||||
|
HOST_GID="$(id -g)"
|
||||||
|
export TARGET HOST_UID HOST_GID
|
||||||
|
|
||||||
|
docker run --rm \
|
||||||
|
--platform "$PLATFORM" \
|
||||||
|
--env TARGET \
|
||||||
|
--env HOST_UID \
|
||||||
|
--env HOST_GID \
|
||||||
|
--volume "$WORKSPACE:/work" \
|
||||||
|
--workdir /work \
|
||||||
|
"$IMAGE" \
|
||||||
|
sh /work/dist/release/build_musl_container.sh
|
||||||
+143
@@ -0,0 +1,143 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# Builds a static musl termscp binary. Runs INSIDE the Alpine container
|
||||||
|
# started by dist/release/build_musl.sh; /work is the mounted workspace.
|
||||||
|
#
|
||||||
|
# Required environment: TARGET, HOST_UID, HOST_GID.
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
NETTLE_VERSION="3.10.1"
|
||||||
|
GNUTLS_VERSION="3.8.13"
|
||||||
|
PAVAO_SRC_VERSION="4.24.6"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
chown -R "$HOST_UID:$HOST_GID" /work
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
apk add --no-cache \
|
||||||
|
bison \
|
||||||
|
binutils \
|
||||||
|
build-base \
|
||||||
|
file \
|
||||||
|
flex \
|
||||||
|
git \
|
||||||
|
gnutls-dev \
|
||||||
|
libgit2-dev \
|
||||||
|
libgit2-static \
|
||||||
|
libunistring-dev \
|
||||||
|
libunistring-static \
|
||||||
|
linux-headers \
|
||||||
|
openssl-dev \
|
||||||
|
openssl-libs-static \
|
||||||
|
perl \
|
||||||
|
perl-parse-yapp \
|
||||||
|
pkgconf \
|
||||||
|
python3 \
|
||||||
|
wget \
|
||||||
|
xz \
|
||||||
|
zlib-dev \
|
||||||
|
zlib-static
|
||||||
|
|
||||||
|
rustup target add "$TARGET"
|
||||||
|
cargo fetch --locked
|
||||||
|
|
||||||
|
NATIVE_CFLAGS="-O2 -fPIC"
|
||||||
|
if [ "$TARGET" = "aarch64-unknown-linux-musl" ]; then
|
||||||
|
NATIVE_CFLAGS="$NATIVE_CFLAGS -mno-outline-atomics"
|
||||||
|
fi
|
||||||
|
export CFLAGS="$NATIVE_CFLAGS"
|
||||||
|
|
||||||
|
# -- static nettle (GnuTLS crypto backend); mini-gmp avoids a GMP dependency
|
||||||
|
mkdir -p /tmp/native
|
||||||
|
wget -q "https://ftp.gnu.org/gnu/nettle/nettle-$NETTLE_VERSION.tar.gz" \
|
||||||
|
-O /tmp/native/nettle.tar.gz
|
||||||
|
tar -xzf /tmp/native/nettle.tar.gz -C /tmp/native
|
||||||
|
cd "/tmp/native/nettle-$NETTLE_VERSION"
|
||||||
|
./configure \
|
||||||
|
--prefix=/tmp/native/nettle \
|
||||||
|
--disable-shared \
|
||||||
|
--enable-static \
|
||||||
|
--disable-documentation \
|
||||||
|
--enable-mini-gmp
|
||||||
|
make -j"$(getconf _NPROCESSORS_ONLN)"
|
||||||
|
make install
|
||||||
|
|
||||||
|
# -- static GnuTLS; every optional backend is disabled so nothing links
|
||||||
|
# against a shared library
|
||||||
|
wget -q "https://www.gnupg.org/ftp/gcrypt/gnutls/v3.8/gnutls-$GNUTLS_VERSION.tar.xz" \
|
||||||
|
-O /tmp/native/gnutls.tar.xz
|
||||||
|
tar -xf /tmp/native/gnutls.tar.xz -C /tmp/native
|
||||||
|
cd "/tmp/native/gnutls-$GNUTLS_VERSION"
|
||||||
|
PKG_CONFIG_PATH=/tmp/native/nettle/lib/pkgconfig \
|
||||||
|
./configure \
|
||||||
|
--prefix=/tmp/native/gnutls \
|
||||||
|
--disable-shared \
|
||||||
|
--enable-static \
|
||||||
|
--disable-doc \
|
||||||
|
--disable-tests \
|
||||||
|
--disable-nls \
|
||||||
|
--disable-hardware-acceleration \
|
||||||
|
--with-nettle-mini \
|
||||||
|
--with-included-libtasn1 \
|
||||||
|
--with-included-unistring \
|
||||||
|
--without-idn \
|
||||||
|
--without-p11-kit \
|
||||||
|
--without-brotli \
|
||||||
|
--without-zstd \
|
||||||
|
--without-zlib
|
||||||
|
make -j"$(getconf _NPROCESSORS_ONLN)"
|
||||||
|
make install
|
||||||
|
|
||||||
|
# -- flatten gnutls.pc: pkg-config must hand the linker the static archives
|
||||||
|
# directly, with no Requires.private chain to resolve
|
||||||
|
mkdir -p /tmp/native/pkgconfig
|
||||||
|
sed \
|
||||||
|
-e "s#^Libs:.*#Libs: -L/tmp/native/gnutls/lib -lgnutls -latomic -L/tmp/native/nettle/lib -lhogweed -lnettle#" \
|
||||||
|
-e "/^Requires.private:/d" \
|
||||||
|
-e "s#^Cflags:.*#Cflags: -I/tmp/native/gnutls/include -I/tmp/native/nettle/include#" \
|
||||||
|
/tmp/native/gnutls/lib/pkgconfig/gnutls.pc \
|
||||||
|
> /tmp/native/pkgconfig/gnutls.pc
|
||||||
|
|
||||||
|
# -- pavao-src: Samba's replacement library omits two sources that musl needs
|
||||||
|
cd /work
|
||||||
|
PAVAO_SRC=$(find "${CARGO_HOME:-/usr/local/cargo}/registry/src" \
|
||||||
|
-type d -name "pavao-src-$PAVAO_SRC_VERSION" -print -quit)
|
||||||
|
test -n "$PAVAO_SRC"
|
||||||
|
cp -R "$PAVAO_SRC" /tmp/pavao-src
|
||||||
|
perl -0pi -e "s#( \\\"lib/replace/replace\\.c\\\",\\n)#\$1 \\\"lib/replace/closefrom.c\\\",\\n \\\"lib/replace/strptime.c\\\",\\n#" \
|
||||||
|
/tmp/pavao-src/src/lib.rs
|
||||||
|
|
||||||
|
cat >> Cargo.toml <<EOF
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
pavao-src = { path = "/tmp/pavao-src" }
|
||||||
|
EOF
|
||||||
|
cargo update -p "pavao-src@$PAVAO_SRC_VERSION"
|
||||||
|
|
||||||
|
export PKG_CONFIG_ALL_STATIC=1
|
||||||
|
export PKG_CONFIG_PATH=/tmp/native/pkgconfig:/tmp/native/nettle/lib/pkgconfig:/usr/lib/pkgconfig
|
||||||
|
export RUSTFLAGS="-C target-feature=+crt-static -C link-arg=-static"
|
||||||
|
cargo build --locked --release --target "$TARGET" --features smb-vendored
|
||||||
|
|
||||||
|
# -- prove the binary is static: no interpreter, no shared libraries
|
||||||
|
file "target/$TARGET/release/termscp"
|
||||||
|
if readelf -l "target/$TARGET/release/termscp" > /tmp/program-headers.txt; then
|
||||||
|
cat /tmp/program-headers.txt
|
||||||
|
else
|
||||||
|
status=$?
|
||||||
|
cat /tmp/program-headers.txt
|
||||||
|
exit "$status"
|
||||||
|
fi
|
||||||
|
if readelf -d "target/$TARGET/release/termscp" > /tmp/dynamic-section.txt; then
|
||||||
|
cat /tmp/dynamic-section.txt
|
||||||
|
else
|
||||||
|
status=$?
|
||||||
|
cat /tmp/dynamic-section.txt
|
||||||
|
exit "$status"
|
||||||
|
fi
|
||||||
|
if grep -q INTERP /tmp/program-headers.txt; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if grep -q NEEDED /tmp/dynamic-section.txt; then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -44,9 +44,28 @@ Install termscp from the official repositories:
|
|||||||
pacman -S termscp
|
pacman -S termscp
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Official binaries
|
||||||
|
|
||||||
|
Official release binaries are published for these targets:
|
||||||
|
|
||||||
|
- GNU/Linux:
|
||||||
|
- `x86_64-unknown-linux-musl`
|
||||||
|
- `aarch64-unknown-linux-musl`
|
||||||
|
- macOS:
|
||||||
|
- `x86_64-apple-darwin`
|
||||||
|
- `aarch64-apple-darwin`
|
||||||
|
- Windows:
|
||||||
|
- `x86_64-pc-windows-msvc`
|
||||||
|
- `aarch64-pc-windows-msvc`
|
||||||
|
|
||||||
|
The Linux binaries, and the `.deb` package built from them, are statically
|
||||||
|
linked against musl. They have no runtime dependencies: they run on any Linux
|
||||||
|
distribution and any glibc version, with no system packages to install.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
The following system dependencies are required to run termscp.
|
The official binaries do not require these dependencies. They are needed only
|
||||||
|
to build termscp from source, for example with `cargo install termscp`:
|
||||||
|
|
||||||
- Linux users:
|
- Linux users:
|
||||||
- libdbus-1
|
- libdbus-1
|
||||||
|
|||||||
@@ -117,6 +117,10 @@ pacman -S termscp
|
|||||||
|
|
||||||
### 依赖 ❗
|
### 依赖 ❗
|
||||||
|
|
||||||
|
官方 Linux 二进制文件和 `.deb` 包静态链接了 musl,**没有任何运行时依赖**:可在任意发行版、任意 glibc 版本上运行。
|
||||||
|
|
||||||
|
以下依赖仅在从源码构建 termscp 时需要:
|
||||||
|
|
||||||
- **Linux** 用户:
|
- **Linux** 用户:
|
||||||
- libdbus-1
|
- libdbus-1
|
||||||
- pkg-config
|
- pkg-config
|
||||||
|
|||||||
@@ -42,9 +42,25 @@ pkgin install termscp
|
|||||||
pacman -S termscp
|
pacman -S termscp
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 官方二进制文件
|
||||||
|
|
||||||
|
官方发布的二进制文件支持以下目标:
|
||||||
|
|
||||||
|
- GNU/Linux:
|
||||||
|
- `x86_64-unknown-linux-musl`
|
||||||
|
- `aarch64-unknown-linux-musl`
|
||||||
|
- macOS:
|
||||||
|
- `x86_64-apple-darwin`
|
||||||
|
- `aarch64-apple-darwin`
|
||||||
|
- Windows:
|
||||||
|
- `x86_64-pc-windows-msvc`
|
||||||
|
- `aarch64-pc-windows-msvc`
|
||||||
|
|
||||||
|
Linux 二进制文件以及由其构建的 `.deb` 包都静态链接了 musl。它们没有任何运行时依赖:可在任意 Linux 发行版、任意 glibc 版本上运行,无需安装任何系统软件包。
|
||||||
|
|
||||||
## 系统要求
|
## 系统要求
|
||||||
|
|
||||||
运行 termscp 需要以下系统依赖。
|
官方二进制文件不需要以下依赖。它们仅在从源码构建 termscp 时才需要,例如使用 `cargo install termscp`:
|
||||||
|
|
||||||
- Linux 用户:
|
- Linux 用户:
|
||||||
- libdbus-1
|
- libdbus-1
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ build_crates_release:
|
|||||||
build_release target features="":
|
build_release target features="":
|
||||||
cargo build --locked --release --target {{ target }} {{ features }}
|
cargo build --locked --release --target {{ target }} {{ features }}
|
||||||
|
|
||||||
|
# Build a static musl Linux release binary in a pinned Alpine container
|
||||||
|
[group('build')]
|
||||||
|
build_musl target:
|
||||||
|
dist/release/build_musl.sh {{ target }}
|
||||||
|
|
||||||
# Package an already-built Linux release as a Debian package
|
# Package an already-built Linux release as a Debian package
|
||||||
[group('build')]
|
[group('build')]
|
||||||
package_deb target:
|
package_deb target:
|
||||||
|
|||||||
@@ -35,7 +35,9 @@ setup_githooks:
|
|||||||
[group('code_check')]
|
[group('code_check')]
|
||||||
check_install_scripts:
|
check_install_scripts:
|
||||||
sh -n install.sh
|
sh -n install.sh
|
||||||
shellcheck install.sh
|
sh -n dist/release/build_musl.sh
|
||||||
|
sh -n dist/release/build_musl_container.sh
|
||||||
|
shellcheck install.sh dist/release/build_musl.sh dist/release/build_musl_container.sh
|
||||||
@if command -v pwsh >/dev/null 2>&1; then \
|
@if command -v pwsh >/dev/null 2>&1; then \
|
||||||
pwsh -NoProfile -Command '$t = $null; $e = $null; $null = [System.Management.Automation.Language.Parser]::ParseFile("install.ps1", [ref]$t, [ref]$e); if ($e) { $e; exit 1 }'; \
|
pwsh -NoProfile -Command '$t = $null; $e = $null; $null = [System.Management.Automation.Language.Parser]::ParseFile("install.ps1", [ref]$t, [ref]$e); if ($e) { $e; exit 1 }'; \
|
||||||
else \
|
else \
|
||||||
|
|||||||
@@ -72,9 +72,12 @@ const methods = [
|
|||||||
Update anytime with <span class="text-green">termscp --update</span>.
|
Update anytime with <span class="text-green">termscp --update</span>.
|
||||||
</p>
|
</p>
|
||||||
<p class="mt-2 text-sm text-overlay">
|
<p class="mt-2 text-sm text-overlay">
|
||||||
Linux build deps: <span class="text-text">libdbus-1</span>, <span
|
Official Linux binaries and .deb packages are statically linked against <span
|
||||||
|
class="text-text">musl</span
|
||||||
|
>: no runtime dependencies, any distribution, any glibc version. Building
|
||||||
|
from source still needs <span class="text-text">libdbus-1</span>, <span
|
||||||
class="text-text">pkg-config</span
|
class="text-text">pkg-config</span
|
||||||
>, <span class="text-text">libsmbclient</span>. More details in the <a
|
> and <span class="text-text">libsmbclient</span>. More details in the <a
|
||||||
href={DOCS_URL}
|
href={DOCS_URL}
|
||||||
class="text-blue hover:underline">docs</a
|
class="text-blue hover:underline">docs</a
|
||||||
>.
|
>.
|
||||||
|
|||||||
@@ -50,6 +50,20 @@ impl Update {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Maps a build target triple onto the target triple used to name the
|
||||||
|
/// official release assets.
|
||||||
|
///
|
||||||
|
/// Official Linux binaries are statically linked against musl, so a
|
||||||
|
/// termscp built against glibc (for example via `cargo install`) must
|
||||||
|
/// still download the `-musl` asset.
|
||||||
|
fn map_release_target(target: &str) -> String {
|
||||||
|
if target.contains("-linux-") {
|
||||||
|
target.replace("-gnu", "-musl")
|
||||||
|
} else {
|
||||||
|
target.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Installs the latest available release using the configured update options.
|
/// Installs the latest available release using the configured update options.
|
||||||
pub fn upgrade(self) -> Result<UpdateStatus, UpdateError> {
|
pub fn upgrade(self) -> Result<UpdateStatus, UpdateError> {
|
||||||
info!("Updating termscp...");
|
info!("Updating termscp...");
|
||||||
@@ -58,6 +72,7 @@ impl Update {
|
|||||||
.repo_owner("veeso")
|
.repo_owner("veeso")
|
||||||
.repo_name("termscp")
|
.repo_name("termscp")
|
||||||
.bin_name("termscp")
|
.bin_name("termscp")
|
||||||
|
.target(&Self::map_release_target(self_update::get_target()))
|
||||||
.current_version(cargo_crate_version!())
|
.current_version(cargo_crate_version!())
|
||||||
.no_confirm(!self.ask_confirm)
|
.no_confirm(!self.ask_confirm)
|
||||||
.show_download_progress(self.progress)
|
.show_download_progress(self.progress)
|
||||||
@@ -180,6 +195,38 @@ mod test {
|
|||||||
assert_eq!(upd.progress, true);
|
assert_eq!(upd.progress, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_map_linux_release_target_to_musl() {
|
||||||
|
assert_eq!(
|
||||||
|
Update::map_release_target("x86_64-unknown-linux-gnu"),
|
||||||
|
"x86_64-unknown-linux-musl".to_string()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Update::map_release_target("aarch64-unknown-linux-gnu"),
|
||||||
|
"aarch64-unknown-linux-musl".to_string()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_leave_non_gnu_linux_release_target_unchanged() {
|
||||||
|
assert_eq!(
|
||||||
|
Update::map_release_target("x86_64-unknown-linux-musl"),
|
||||||
|
"x86_64-unknown-linux-musl".to_string()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn should_leave_other_platform_release_targets_unchanged() {
|
||||||
|
assert_eq!(
|
||||||
|
Update::map_release_target("aarch64-apple-darwin"),
|
||||||
|
"aarch64-apple-darwin".to_string()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Update::map_release_target("x86_64-pc-windows-msvc"),
|
||||||
|
"x86_64-pc-windows-msvc".to_string()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(
|
#[cfg(all(
|
||||||
not(all(
|
not(all(
|
||||||
|
|||||||
Reference in New Issue
Block a user