Skip to content
Merged
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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ jobs:
with:
swift-version: ${{ matrix.swift }}
windows-toolchain-variant: noasserts
windows-minimal: true
- name: Check the +NoAsserts toolchain was selected, and compile
env:
VERSION: ${{ steps.setup.outputs.version }}
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ see [How verification works](#how-verification-works)). It never runs a pre-exis
| `swift-sdks` | no | | Cross-compilation Swift SDKs to install after the toolchain: `static-linux`, `wasm`, `android` (comma or space separated). |
| `use-preinstalled` | no | `false` | **Unverified opt-in.** If `swift` on `PATH` already reports exactly `swift-version`, run and use it instead of installing. By default no pre-existing binary is ever executed. |
| `windows-toolchain-variant` | no | `asserts` | Windows only. `asserts` keeps the installer's default `+Asserts` toolchain; `noasserts` installs the `+NoAsserts` one instead. Use `noasserts` on win-arm64, where the `+Asserts` `swift-package.exe` fails to start ([swiftlang/swift#92379](https://github.com/swiftlang/swift/issues/92379)). |
| `cache` | no | `true` | Cache the downloaded Linux toolchain archive and its `.sig` with `actions/cache`. The archive is re-verified with GPG on every run and extracted into a clean per-version directory; `false` reuses nothing on disk. |
| `windows-minimal` | no | `false` | Windows only. `true` leaves out what a CI build does not use: the debugger (`OptionsInstallDBG`), its embedded Python (`OptionsInstallPy`) and the Android platform (`OptionsInstallAndroidPlatform`). The IDE feature stays: without it `swift.exe` fails to start (`ERROR_SXS_CANT_GEN_ACTCTX`). |
| `cache` | no | `true` | Cache the downloaded Linux toolchain archive and its `.sig` with `actions/cache`. The archive is re-verified with GPG on every run and extracted into a clean per-version directory; `false` reuses nothing on disk. The macOS `.pkg` and the Windows installer are not cached: restoring them from the Actions cache measured slower than downloading them from swift.org. |

## Outputs

Expand Down Expand Up @@ -60,7 +61,7 @@ A cache entry that fails verification fails the job instead of being re-download
`RUNNER_TEMP` is private to one runner instance and emptied for every job on GitHub-hosted runners, so earlier or
concurrent jobs cannot plant or wipe the toolchain. Self-hosted runners must not share `RUNNER_TEMP` between
concurrently running jobs, and must run jobs of different trust levels on separate runner instances. Missing build prerequisites (`libcurl4-openssl-dev`,
`libxml2-dev`, the GCC dev packages, ...) are installed with `apt-get` only if absent.
`libxml2-dev`, the GCC dev packages, ...) are installed with `apt-get` only if absent - from the package lists the runner image ships, refreshed only if that fails, and, apart from `curl` and `gnupg2`, in the background while the archive is fetched, verified and extracted. The archive is extracted with `pigz` when the runner has it.

macOS: the package is installed into the user domain (`~/Library/Developer/Toolchains`), falling back to
`sudo installer -target /`. `TOOLCHAINS` is exported with the toolchain's bundle identifier and its
Expand Down
12 changes: 11 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,19 @@ inputs:
(https://github.com/swiftlang/swift/issues/92379); the +NoAsserts one does not.
required: false
default: "asserts"
windows-minimal:
description: >-
Windows only: leave out what a CI build does not use - the debugger, its embedded Python and the
Android platform. Shortens the install; default false installs everything the installer
installs by default.
required: false
default: "false"
cache:
description: >-
Cache the downloaded Linux toolchain archive and its signature with actions/cache. The archive is
re-verified with GPG on every run; with false nothing on disk is ever reused.
re-verified with GPG on every run; with false nothing on disk is ever reused. The macOS .pkg and
the Windows installer are not cached: restoring them from the Actions cache measured slower than
downloading them from swift.org.
required: false
default: "true"
outputs:
Expand Down Expand Up @@ -111,6 +120,7 @@ runs:
env:
SWIFT_VERSION: ${{ inputs.swift-version }}
WINDOWS_TOOLCHAIN_VARIANT: ${{ inputs.windows-toolchain-variant }}
WINDOWS_MINIMAL: ${{ inputs.windows-minimal }}
run: '& "$env:GITHUB_ACTION_PATH/install-windows.ps1"'

- name: Report Swift version
Expand Down
43 changes: 38 additions & 5 deletions install-linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,37 @@ for pkg in curl gnupg2 binutils git libcurl4-openssl-dev libedit2 libsqlite3-0 l
libncurses-dev pkg-config tzdata uuid-dev zlib1g-dev "libgcc-${gcc_ver}-dev" "libstdc++-${gcc_ver}-dev"; do
dpkg -s "$pkg" > /dev/null 2>&1 || missing+=("$pkg")
done
if [ "${#missing[@]}" -gt 0 ]; then
echo "Installing missing packages: ${missing[*]}"
"${sudo_cmd[@]}" apt-get update -qq
"${sudo_cmd[@]}" env DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends "${missing[@]}"
# The package lists a runner image ships are tried first, and refreshed only when that fails: the
# refresh is most of what installing a couple of packages costs.
apt_install() {
"${sudo_cmd[@]}" env DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends "$@" \
|| { "${sudo_cmd[@]}" apt-get update -qq \
&& "${sudo_cmd[@]}" env DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends "$@"; }
}

# curl and gnupg2 download and verify the toolchain, so they have to be there first. Everything else
# is needed only to run it, and is installed in the background while the archive is fetched,
# verified and extracted, then waited for at the end.
needed_now=()
later=()
for pkg in "${missing[@]}"; do
case "$pkg" in curl | gnupg2) needed_now+=("$pkg") ;; *) later+=("$pkg") ;; esac
done
if [ "${#needed_now[@]}" -gt 0 ]; then
echo "Installing missing packages: ${needed_now[*]}"
apt_install "${needed_now[@]}"
fi

scratch="$(mktemp -d "${RUNNER_TEMP:-/tmp}/setup-swift.XXXXXX")"
trap 'rm -r -f "$scratch"' EXIT

apt_pid=""
if [ "${#later[@]}" -gt 0 ]; then
echo "Installing missing packages in the background: ${later[*]}"
apt_install "${later[@]}" > "$scratch/apt.log" 2>&1 &
apt_pid=$!
fi

download() { # url dest
curl --fail --silent --show-error --location --retry 5 --retry-delay 5 --retry-all-errors \
--connect-timeout 30 --output "$2" "$1" \
Expand Down Expand Up @@ -107,9 +129,20 @@ assert_no_symlinks "$dest"
rm -r -f -- "$dest"
mkdir "$dest"
assert_no_symlinks "$dest"
tar -xzf "$snap/$file" -C "$dest" --strip-components=1 --no-same-owner
# pigz where the runner has it: inflation stays single-threaded, but pigz reads, writes and
# checksums on threads of its own.
if command -v pigz > /dev/null; then
tar -I pigz -xf "$snap/$file" -C "$dest" --strip-components=1 --no-same-owner
else
tar -xzf "$snap/$file" -C "$dest" --strip-components=1 --no-same-owner
fi
rm -r -f -- "$snap"
[ -x "$dest/usr/bin/swift" ] || { echo "::error::$dest/usr/bin/swift is missing after extraction"; exit 1; }
if [ -n "$apt_pid" ] && ! wait "$apt_pid"; then
cat "$scratch/apt.log"
echo "::error::Installing the packages the toolchain needs failed: ${later[*]}"
exit 1
fi
if [ -n "${GITHUB_PATH:-}" ]; then echo "$dest/usr/bin" >> "$GITHUB_PATH"; fi
if [ -n "${GITHUB_OUTPUT:-}" ]; then echo "source=$source" >> "$GITHUB_OUTPUT"; fi
echo "Installed Swift toolchain at $dest"
10 changes: 10 additions & 0 deletions install-windows.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@ switch ($variant) {
}
default { Write-Host "::error::windows-toolchain-variant must be asserts or noasserts, got '$variant'"; exit 1 }
}
# windows-minimal: the installer features a CI build does not use - the debugger, its Python and the
# Android platform, a second SDK. Not the IDE feature: without it swift.exe fails to start with
# ERROR_SXS_CANT_GEN_ACTCTX (14001), measured on 6.4.1 with each feature left out on its own.
switch ($env:WINDOWS_MINIMAL) {
{ $_ -in @('', 'false') } { }
'true' {
$installerOptions += @('OptionsInstallDBG=0', 'OptionsInstallPy=0', 'OptionsInstallAndroidPlatform=0')
}
default { Write-Host "::error::windows-minimal must be true or false, got '$env:WINDOWS_MINIMAL'"; exit 1 }
}
# Publisher the installer must be signed by, see README.md. swift.org's Windows installers are signed
# with an Apple Inc. certificate whose OU (an Apple internal group id) is deliberately not pinned.
$ExpectedSubject = '^CN=Apple Inc\., (OU=[^,]+, )?O=Apple Inc\., L=Cupertino, S=California, C=US$'
Expand Down
Loading