Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@ git-fetch-with-cli = true

[target.'cfg(target_family = "wasm")']
rustflags = ["--cfg=web_sys_unstable_apis"]

[target.x86_64-unknown-linux-musl]
linker = "musl-gcc"

[target.aarch64-unknown-linux-musl]
linker = "musl-gcc"
13 changes: 2 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -501,19 +501,10 @@ jobs:
shell: bash
run: |
sudo apt-get install -y curl sshpass xz-utils
MUSL_CROSS_TAG="20250929"
MUSL_CROSS_TARGET="x86_64-unknown-linux-musl"
MUSL_CROSS_SHA256="6534870abd7dc327fd2e14cc53972d0552b21f47db5769505534f788537e3544"
MUSL_CROSS_ARCHIVE="$MUSL_CROSS_TARGET.tar.xz"
curl -fsSLO "https://github.com/cross-tools/musl-cross/releases/download/$MUSL_CROSS_TAG/$MUSL_CROSS_ARCHIVE"
echo "$MUSL_CROSS_SHA256 $MUSL_CROSS_ARCHIVE" | sha256sum -c -
sudo mkdir -p /opt/x-tools
sudo tar -xf "$MUSL_CROSS_ARCHIVE" -C /opt/x-tools
MUSL_CROSS_BIN="/opt/x-tools/$MUSL_CROSS_TARGET/bin"
source script/linux/configure_musl_toolchain "$MUSL_CROSS_TARGET"
MUSL_CROSS_BIN="$(dirname "$WARP_MUSL_CC")"
echo "$MUSL_CROSS_BIN" >> "$GITHUB_PATH"
export PATH="$MUSL_CROSS_BIN:$PATH"
command -v "$MUSL_CROSS_TARGET-gcc"
command -v "$MUSL_CROSS_TARGET-g++"
rustup target add x86_64-unknown-linux-musl

- name: Deploy remote server binary to test VM
Expand Down
12 changes: 6 additions & 6 deletions .github/workflows/create_release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -707,9 +707,9 @@ jobs:
config_file: ${{ env.CONFIG_FILE }}
channel: ${{ inputs.channel }}

- uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
with:
credentials_json: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
# - uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
# with:
# credentials_json: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}

- name: Load PGP signing key and passphrase
run: |
Expand Down Expand Up @@ -975,9 +975,9 @@ jobs:
config_file: ${{ env.CONFIG_FILE }}
channel: ${{ inputs.channel }}

- uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
with:
credentials_json: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
# - uses: google-github-actions/auth@7c6bc770dae815cd3e89ee6cdf493a5fab2cc093 # v3.0.0
# with:
# credentials_json: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}

# Namespace's User Bundled Cache persists target/ between jobs on the same profile, which can
# leave stale packages from a previous channel's build in the linux bundle output dir.
Expand Down
16 changes: 4 additions & 12 deletions script/deploy_remote_server
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,8 @@ case "$PROFILE_MODE" in
;;
esac

# Check for musl-cross linker
if ! command -v x86_64-linux-musl-gcc &>/dev/null; then
echo "Error: x86_64-linux-musl-gcc not found." >&2
echo "Install it with: brew install filosottile/musl-cross/musl-cross" >&2
exit 1
fi
TARGET="x86_64-unknown-linux-musl"
source "$SCRIPT_DIR/linux/configure_musl_toolchain" "$TARGET"

# Check for musl target
if ! rustup target list --installed 2>/dev/null | grep -q x86_64-unknown-linux-musl; then
Expand All @@ -91,9 +87,7 @@ if ! rustup target list --installed 2>/dev/null | grep -q x86_64-unknown-linux-m
exit 1
fi

# Determine build parameters
TARGET="x86_64-unknown-linux-musl"

# Select the requested Cargo build profile.
case "$PROFILE_MODE" in
dev-remote)
CARGO_PROFILE="dev-remote"
Expand Down Expand Up @@ -135,9 +129,7 @@ echo " Binary: $WARP_BIN -> $BINARY_NAME"
echo " Features: $FEATURES"
echo ""

# Build with linker and rustflags overrides to avoid macOS-specific flags
# from .cargo/config.toml
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER=x86_64-linux-musl-gcc \
# Override the target rustflags to avoid macOS-specific flags from .cargo/config.toml.
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS="-C symbol-mangling-version=v0" \
cargo build \
-p warp \
Expand Down
63 changes: 2 additions & 61 deletions script/deploy_remote_server_to_test_vm
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
# Integration channel's `check_binary` looks.
#
# Prerequisites (same as script/deploy_remote_server):
# Linux: install an x86_64 musl cross toolchain that includes gcc and g++
# (CI uses cross-tools/musl-cross) and sudo apt-get install sshpass
# On Linux, install curl, sha256sum, tar, and sshpass.
# rustup target add x86_64-unknown-linux-musl
# gcloud CLI authenticated for the warp-ssh-integration-testing project
#
Expand Down Expand Up @@ -47,59 +46,6 @@ REMOTE_HOST="ssh-remote-server-testing"
REMOTE_PORT="22"
PROXY_COMMAND="gcloud compute start-iap-tunnel ssh-remote-server-testing ${REMOTE_PORT} --listen-on-stdin --project=warp-ssh-integration-testing --zone=us-east4-b"

# ── Helpers ───────────────────────────────────────────────────────

install_musl_help() {
case "$(uname -s)" in
Linux)
echo "Install a musl cross toolchain that includes gcc and g++." >&2
;;
*)
echo "Install an x86_64 musl C compiler for $TARGET." >&2
;;
esac
}

detect_musl_linker() {
if command -v x86_64-linux-musl-gcc &>/dev/null; then
echo "x86_64-linux-musl-gcc"
return
fi
if command -v x86_64-unknown-linux-musl-gcc &>/dev/null; then
echo "x86_64-unknown-linux-musl-gcc"
return
fi

if command -v musl-gcc &>/dev/null; then
echo "musl-gcc"
return
fi

echo "Error: no musl linker found." >&2
install_musl_help
exit 1
}
detect_musl_cxx() {
local linker_cxx="${MUSL_LINKER%gcc}g++"
if [[ "$linker_cxx" != "$MUSL_LINKER" ]] && command -v "$linker_cxx" &>/dev/null; then
echo "$linker_cxx"
return
fi

if command -v x86_64-linux-musl-g++ &>/dev/null; then
echo "x86_64-linux-musl-g++"
return
fi

if command -v x86_64-unknown-linux-musl-g++ &>/dev/null; then
echo "x86_64-unknown-linux-musl-g++"
return
fi

echo "Error: no musl C++ compiler found." >&2
install_musl_help
exit 1
}

app_version() {
if [[ -n "${GIT_RELEASE_TAG:-}" ]]; then
Expand All @@ -112,9 +58,7 @@ app_version() {
}

# ── Preflight checks ──────────────────────────────────────────────

MUSL_LINKER="$(detect_musl_linker)"
MUSL_CXX="$(detect_musl_cxx)"
source "$SCRIPT_DIR/linux/configure_musl_toolchain" "$TARGET"

if ! rustup target list --installed 2>/dev/null | grep -q "$TARGET"; then
echo "Error: $TARGET target not installed." >&2
Expand All @@ -136,10 +80,7 @@ LOCAL_BUNDLE_TARBALL="$OUTPUT_DIR/remote-server-integration-bundle.tar.gz"

echo "==> Building Integration-channel Oz CLI for $TARGET (profile=$CARGO_PROFILE)"

CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_LINKER="$MUSL_LINKER" \
CARGO_TARGET_X86_64_UNKNOWN_LINUX_MUSL_RUSTFLAGS="-C symbol-mangling-version=v0" \
CC_x86_64_unknown_linux_musl="$MUSL_LINKER" \
CXX_x86_64_unknown_linux_musl="$MUSL_CXX" \
cargo build \
-p warp \
--bin "$WARP_BIN" \
Expand Down
25 changes: 19 additions & 6 deletions script/linux/bundle
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
set -e

WORKSPACE_ROOT_DIR="$(pwd)"
CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$WORKSPACE_ROOT_DIR/target}"
DIST_DIR="$CARGO_TARGET_DIR/dist"

cleanup() {
# Delete the directory that was used as a staging area during the bundling
Expand Down Expand Up @@ -122,6 +120,18 @@ done
# set positional arguments in their proper place
eval set -- "$PARAMS"

# Statically compile the CLI and warpctrl artifacts so they can run on older Linux distros.
if [[ "$ARTIFACT" == "cli" || "$ARTIFACT" == "warpctrl" ]]; then
TARGET_TRIPLE="${BUILD_ARCH}-unknown-linux-musl"
source "$WORKSPACE_ROOT_DIR/script/linux/configure_musl_toolchain" "$TARGET_TRIPLE"
# Make sure we have the rust musl target available.
rustup target add "$TARGET_TRIPLE"
fi
CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$WORKSPACE_ROOT_DIR/target}"
CARGO_TARGET_OUTPUT_ROOT="$CARGO_TARGET_DIR${TARGET_TRIPLE:+/$TARGET_TRIPLE}"

DIST_DIR="$CARGO_TARGET_OUTPUT_ROOT/dist"

if [[ $DEBUG = true ]]; then
CARGO_PROFILE="dev"
elif [[ $RELEASE_CHANNEL = "local" || $RELEASE_CHANNEL = "dev" ]]; then
Expand All @@ -142,9 +152,9 @@ else
fi

if [[ "$CARGO_PROFILE" == "dev" ]]; then
CARGO_TARGET_OUTPUT_DIR="$CARGO_TARGET_DIR/debug"
CARGO_TARGET_OUTPUT_DIR="$CARGO_TARGET_OUTPUT_ROOT/debug"
else
CARGO_TARGET_OUTPUT_DIR="$CARGO_TARGET_DIR/$CARGO_PROFILE"
CARGO_TARGET_OUTPUT_DIR="$CARGO_TARGET_OUTPUT_ROOT/$CARGO_PROFILE"
fi
# NOTE: if you change this path, update the "Clean stale bundle output"
# steps in .github/workflows/create_release.yml so they continue to wipe
Expand Down Expand Up @@ -233,14 +243,17 @@ export APPIMAGE_NAME="$APP_NAME-$BUILD_ARCH.AppImage"
# then exit. We use this script to invoke `cargo check` to ensure that we are
# using the same feature flags and profile that we would be using in production.
if [[ "$CHECK_ONLY" == "true" ]]; then
cargo check -p warp --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --features "$FEATURES"
cargo check -p warp --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --features "$FEATURES" ${TARGET_TRIPLE:+--target $TARGET_TRIPLE}
exit 0
fi

# Build the binary.
if [[ "$BUILD" == "true" ]]; then
echo "Building and bundling Warp for channel $RELEASE_CHANNEL and bundle id $BUNDLE_ID"
cargo build -p warp --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --features "$FEATURES"
cargo build -p warp --profile "$CARGO_PROFILE" --bin "$WARP_BIN" --features "$FEATURES" ${TARGET_TRIPLE:+--target $TARGET_TRIPLE}

exit 0

echo "Making debug copy of '$EXECUTABLE_PATH' at '$DEBUG_EXECUTABLE_PATH'"
cp "$EXECUTABLE_PATH" "$DEBUG_EXECUTABLE_PATH"

Expand Down
142 changes: 142 additions & 0 deletions script/linux/configure_musl_toolchain
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#!/usr/bin/env bash
#
# This script configures a complete musl C and C++ toolchain for a Rust target.
# Source this script so it can update the caller's environment.

configure_musl_toolchain() {
local target="${1:-$(uname -m)-unknown-linux-musl}"
local musl_cross_tag="20250929"
local musl_cross_sha256

case "$target" in
aarch64-unknown-linux-musl)
musl_cross_sha256="28a1d26f14f8ddc3aed31f20705fe696777400eb5952d90470a7e6e2dd1175bb"
;;
x86_64-unknown-linux-musl)
musl_cross_sha256="6534870abd7dc327fd2e14cc53972d0552b21f47db5769505534f788537e3544"
;;
*)
echo "Error: unsupported musl target '$target'." >&2
return 1
;;
esac

local compiler_prefix
local musl_cc=""
local musl_cxx=""
for compiler_prefix in "$target" "${target/unknown-/}"; do
if command -v "$compiler_prefix-gcc" &>/dev/null \
&& command -v "$compiler_prefix-g++" &>/dev/null; then
musl_cc="$(command -v "$compiler_prefix-gcc")"
musl_cxx="$(command -v "$compiler_prefix-g++")"
break
fi
done

if [[ -z "$musl_cc" && "$target" == "$(uname -m)-unknown-linux-musl" ]] \
&& command -v musl-gcc &>/dev/null \
&& command -v musl-g++ &>/dev/null; then
musl_cc="$(command -v musl-gcc)"
musl_cxx="$(command -v musl-g++)"
fi

local musl_cross_root="${WARP_MUSL_CROSS_ROOT:-/tmp/warp-musl-cross}"
local install_root="$musl_cross_root/$musl_cross_tag"
local toolchain_dir="$install_root/$target"
local toolchain_bin="$toolchain_dir/bin"

if [[ -z "$musl_cc" && -x "$toolchain_bin/$target-gcc" && -x "$toolchain_bin/$target-g++" ]]; then
case ":$PATH:" in
*":$toolchain_bin:"*) ;;
*) export PATH="$toolchain_bin:$PATH" ;;
esac
musl_cc="$(command -v "$target-gcc")"
musl_cxx="$(command -v "$target-g++")"
fi

if [[ -z "$musl_cc" ]]; then
if [[ "$(uname -s)" != "Linux" ]]; then
echo "Error: no complete C and C++ toolchain for '$target' was found on PATH." >&2
echo "Automatic musl-cross installation is only supported on Linux." >&2
return 1
fi

local required_command
for required_command in curl sha256sum tar; do
if ! command -v "$required_command" &>/dev/null; then
echo "Error: '$required_command' is required to install the musl toolchain." >&2
return 1
fi
done

local archive_name="$target.tar.xz"
local archive_url="https://github.com/cross-tools/musl-cross/releases/download/$musl_cross_tag/$archive_name"
if ! (
download_dir=""
cleanup_download() {
if [[ -n "$download_dir" && -d "$download_dir" ]]; then
chmod -R u+w "$download_dir" 2>/dev/null || true
rm -rf "$download_dir"
fi
}
trap cleanup_download EXIT

mkdir -p "$musl_cross_root" || exit 1
download_dir="$(mktemp -d "$musl_cross_root/.download-$target.XXXXXX")" || exit 1

echo "Downloading the $target C and C++ toolchain to $toolchain_dir"
curl -fsSL --retry 3 "$archive_url" -o "$download_dir/$archive_name" || exit 1
printf '%s %s\n' "$musl_cross_sha256" "$download_dir/$archive_name" | sha256sum -c - || exit 1
tar -xf "$download_dir/$archive_name" -C "$download_dir" || exit 1
if [[ ! -x "$download_dir/$target/bin/$target-gcc" \
|| ! -x "$download_dir/$target/bin/$target-g++" ]]; then
echo "Error: the downloaded archive does not contain the expected C and C++ compilers." >&2
exit 1
fi

chmod u+w "$download_dir/$target" || exit 1
mkdir -p "$install_root" || exit 1
if [[ -x "$toolchain_bin/$target-gcc" && -x "$toolchain_bin/$target-g++" ]]; then
exit 0
fi
if [[ -e "$toolchain_dir" ]]; then
chmod -R u+w "$toolchain_dir" || exit 1
rm -rf "$toolchain_dir" || exit 1
fi
mv "$download_dir/$target" "$toolchain_dir" || exit 1
); then
return 1
fi

case ":$PATH:" in
*":$toolchain_bin:"*) ;;
*) export PATH="$toolchain_bin:$PATH" ;;
esac
musl_cc="$(command -v "$target-gcc")"
musl_cxx="$(command -v "$target-g++")"
fi

local target_env="${target//-/_}"
local cargo_target_env
cargo_target_env="$(printf '%s' "$target" | tr '[:lower:]-' '[:upper:]_')"

export "CC_$target_env=$musl_cc"
export "CXX_$target_env=$musl_cxx"
export "CARGO_TARGET_${cargo_target_env}_LINKER=$musl_cc"
export WARP_MUSL_TARGET="$target"
export WARP_MUSL_CC="$musl_cc"
export WARP_MUSL_CXX="$musl_cxx"

echo "Configured the $target toolchain with $musl_cc and $musl_cxx"
}

if [[ -n "${BASH_VERSION:-}" && "${BASH_SOURCE[0]}" == "$0" ]]; then
echo "Error: source this script so it can configure the caller's environment." >&2
exit 1
fi
if [[ -n "${ZSH_VERSION:-}" && "${ZSH_EVAL_CONTEXT:-}" != *:file ]]; then
echo "Error: source this script so it can configure the caller's environment." >&2
exit 1
fi

configure_musl_toolchain "$@"
2 changes: 2 additions & 0 deletions script/linux/install_build_deps
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ if [[ "$(source /etc/os-release; echo $ID $ID_LIKE)" = *"debian"* ]]; then
libclang-dev
# Required by script/presubmit's clang-format check on C/C++/Obj-C sources.
clang-format
# Required to build statically-linked binaries for Linux.
musl-tools
)
warp_sudo apt-get install -y "${PACKAGES[@]}"

Expand Down
Loading
Loading