Skip to content

Commit 84d6374

Browse files
committed
Add workflow for Linux static SDK build
1 parent bc2db71 commit 84d6374

File tree

2 files changed

+353
-0
lines changed

2 files changed

+353
-0
lines changed
Lines changed: 316 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,316 @@
1+
#!/bin/bash
2+
##===----------------------------------------------------------------------===##
3+
##
4+
## This source file is part of the Swift.org open source project
5+
##
6+
## Copyright (c) 2025 Apple Inc. and the Swift project authors
7+
## Licensed under Apache License v2.0 with Runtime Library Exception
8+
##
9+
## See https://swift.org/LICENSE.txt for license information
10+
## See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
11+
##
12+
##===----------------------------------------------------------------------===##
13+
14+
set -euo pipefail
15+
16+
log() { printf -- "** %s\n" "$*" >&2; }
17+
error() { printf -- "** ERROR: %s\n" "$*" >&2; }
18+
fatal() { error "$@"; exit 1; }
19+
20+
# Detect OS from /etc/os-release
21+
detect_os_info() {
22+
if [[ ! -f /etc/os-release ]]; then
23+
fatal "Cannot detect OS: /etc/os-release not found"
24+
fi
25+
26+
local os_id
27+
os_id=$(grep '^ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"' | tr '[:upper:]' '[:lower:]')
28+
local version_id
29+
version_id=$(grep '^VERSION_ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"')
30+
31+
if [[ -z "$os_id" || -z "$version_id" ]]; then
32+
fatal "Could not parse OS information from /etc/os-release"
33+
fi
34+
35+
# Create both formats
36+
local os_name
37+
os_name="${os_id}$(echo "$version_id" | tr -d '.')"
38+
local os_dotted="${os_id}${version_id}"
39+
40+
log "Detected OS from /etc/os-release: $os_name (dotted: $os_dotted)"
41+
42+
echo "$os_name|$os_dotted"
43+
}
44+
45+
OS_INFO=$(detect_os_info)
46+
OS_NAME=$(echo "$OS_INFO" | cut -d'|' -f1)
47+
OS_DOTTED_VERSION=$(echo "$OS_INFO" | cut -d'|' -f2)
48+
49+
log "Using OS: $OS_NAME"
50+
log "Dotted version of OS for filenames: $OS_DOTTED_VERSION"
51+
52+
# Detect architecture to adjust platform name if needed
53+
ARCH=$(uname -m)
54+
ARCH_SUFFIX=""
55+
if [[ "$ARCH" == "aarch64" ]]; then
56+
ARCH_SUFFIX="-aarch64"
57+
log "Detected aarch64 architecture, using suffix: $ARCH_SUFFIX"
58+
else
59+
log "Detected $ARCH architecture, using no suffix"
60+
fi
61+
62+
# Install curl if not already installed
63+
check_and_install_tools() {
64+
if ! which curl >/dev/null 2>&1; then
65+
log "Installing required tools: curl"
66+
apt -q update && apt -yq install curl
67+
fi
68+
}
69+
70+
SWIFT_WEBROOT="https://download.swift.org/swift-6.2-branch"
71+
PLATFORM_NAME="${OS_NAME}${ARCH_SUFFIX}"
72+
PLATFORM_WEBROOT="${SWIFT_WEBROOT}/${PLATFORM_NAME}"
73+
STATIC_SDK_WEBROOT="${SWIFT_WEBROOT}/static-sdk"
74+
75+
# Directory for extracted toolchain (if needed to match the static SDK)
76+
TOOLCHAIN_DIR="${HOME}/.swift-toolchains"
77+
78+
# Get current Swift version from /.swift_tag
79+
get_current_swift_version() {
80+
# Check /.swift_tag file
81+
if [[ -f "/.swift_tag" ]]; then
82+
local swift_tag
83+
swift_tag=$(tr -d '\n' < /.swift_tag | tr -d ' ')
84+
if [[ -n "$swift_tag" ]]; then
85+
log "Found Swift tag in /.swift_tag: $swift_tag"
86+
echo "$swift_tag"
87+
return 0
88+
fi
89+
fi
90+
91+
log "No Swift tag found in /.swift_tag"
92+
echo "none"
93+
}
94+
95+
parse_yaml_value() {
96+
local key="$1"
97+
local content="$2"
98+
echo "$content" | grep "^${key}:" | sed "s/^${key}:[[:space:]]*//"
99+
}
100+
101+
download_and_verify() {
102+
local url="$1"
103+
local sig_url="$2"
104+
local output_file="$3"
105+
local temp_sig="${output_file}.sig"
106+
107+
log "Downloading ${url##*/}"
108+
curl -fsSL "$url" -o "$output_file"
109+
110+
log "Downloading signature"
111+
curl -fsSL "$sig_url" -o "$temp_sig"
112+
113+
log "Setting up GPG for verification"
114+
local gnupghome
115+
gnupghome="$(mktemp -d)"
116+
export GNUPGHOME="$gnupghome"
117+
curl -fSsL https://swift.org/keys/all-keys.asc | zcat -f | gpg --import - >/dev/null 2>&1
118+
119+
log "Verifying signature"
120+
if gpg --batch --verify "$temp_sig" "$output_file" >/dev/null 2>&1; then
121+
log "✅ Signature verification successful"
122+
else
123+
fatal "Signature verification failed"
124+
fi
125+
126+
rm -rf "$GNUPGHOME" "$temp_sig"
127+
}
128+
129+
# Uses the static SDK snapshot name to find the correct toolchain snapshot
130+
# E.g. takes "swift-6.2-DEVELOPMENT-SNAPSHOT-2025-07-22-a" as input
131+
download_and_extract_toolchain() {
132+
local dir_name="$1"
133+
134+
log "Downloading Swift toolchain: $dir_name"
135+
136+
# "swift-6.2-DEVELOPMENT-SNAPSHOT-2025-07-22-a-ubuntu22.04.tar.gz"
137+
# "swift-6.2-DEVELOPMENT-SNAPSHOT-2025-07-22-a-ubuntu22.04.tar.gz.sig"
138+
local toolchain_filename="${dir_name}-${OS_DOTTED_VERSION}${ARCH_SUFFIX}.tar.gz"
139+
local toolchain_sig_filename="${toolchain_filename}.sig"
140+
141+
local toolchain_url="${PLATFORM_WEBROOT}/${dir_name}/${toolchain_filename}"
142+
local toolchain_sig_url="${PLATFORM_WEBROOT}/${dir_name}/${toolchain_sig_filename}"
143+
144+
# Check if toolchain is available
145+
local http_code
146+
http_code=$(curl -sSL --head -w "%{http_code}" -o /dev/null "$toolchain_url")
147+
if [[ "$http_code" == "404" ]]; then
148+
log "❌ Toolchain not found: ${toolchain_url##*/}"
149+
log "Exiting workflow..."
150+
# Don't fail the workflow if we can't find the right toolchain
151+
exit 0
152+
fi
153+
154+
# Create toolchain directory
155+
mkdir -p "$TOOLCHAIN_DIR"
156+
local toolchain_path="${TOOLCHAIN_DIR}/${dir_name}"
157+
158+
# Check if toolchain already exists
159+
if [[ -d "$toolchain_path" && -f "${toolchain_path}/usr/bin/swift" ]]; then
160+
log "Toolchain already exists at: $toolchain_path"
161+
echo "$toolchain_path/usr/bin/swift"
162+
return 0
163+
fi
164+
165+
# Create temporary directory
166+
local temp_dir
167+
temp_dir=$(mktemp -d)
168+
local toolchain_file="${temp_dir}/swift_toolchain.tar.gz"
169+
170+
# Download and verify toolchain
171+
download_and_verify "$toolchain_url" "$toolchain_sig_url" "$toolchain_file"
172+
173+
log "Extracting toolchain to: $toolchain_path"
174+
mkdir -p "$toolchain_path"
175+
tar -xzf "$toolchain_file" --directory "$toolchain_path" --strip-components=1
176+
177+
# Clean up
178+
rm -rf "$temp_dir"
179+
180+
local swift_executable="${toolchain_path}/usr/bin/swift"
181+
if [[ -f "$swift_executable" ]]; then
182+
log "✅ Swift toolchain extracted successfully"
183+
echo "$swift_executable"
184+
else
185+
fatal "Swift executable not found at expected path: $swift_executable"
186+
fi
187+
}
188+
189+
install_static_sdk() {
190+
local sdk_info="$1"
191+
local swift_executable="$2"
192+
local download_name
193+
download_name=$(parse_yaml_value "download" "$sdk_info")
194+
local dir_name
195+
dir_name=$(parse_yaml_value "dir" "$sdk_info")
196+
local checksum
197+
checksum=$(parse_yaml_value "checksum" "$sdk_info")
198+
199+
# Check if the static SDK is already installed
200+
if "$swift_executable" sdk list 2>/dev/null | grep -q "^$dir_name"; then
201+
log "✅ Static SDK $dir_name is already installed, skipping installation"
202+
return 0
203+
fi
204+
205+
log "Installing Swift Static SDK: $dir_name"
206+
207+
local sdk_url="${STATIC_SDK_WEBROOT}/${dir_name}/${download_name}"
208+
209+
log "Running: ${swift_executable} sdk install ${sdk_url} --checksum $checksum"
210+
211+
if "$swift_executable" sdk install "$sdk_url" --checksum "$checksum"; then
212+
log "✅ Static SDK installed successfully"
213+
else
214+
fatal "Failed to install static SDK"
215+
fi
216+
}
217+
218+
get_static_sdk_name() {
219+
local sdk_info="$1"
220+
local download_name
221+
download_name=$(parse_yaml_value "download" "$sdk_info")
222+
# Note: we want to keep the "_static-linux-0.0.1"
223+
echo "${download_name%.artifactbundle.tar.gz}"
224+
}
225+
226+
run_swift_static_sdk_build() {
227+
local swift_executable="$1"
228+
local sdk_name="$2"
229+
230+
log "Running Swift build with static SDK"
231+
log "Command: $swift_executable build --swift-sdk $sdk_name"
232+
233+
if "$swift_executable" build --swift-sdk "$sdk_name"; then
234+
log "✅ Swift build with static SDK completed successfully"
235+
else
236+
fatal "Swift build with static SDK failed"
237+
fi
238+
}
239+
240+
main() {
241+
log "Starting Swift 6.2 Static SDK and Toolchain setup for $OS_NAME"
242+
log "Platform URL: $PLATFORM_WEBROOT"
243+
244+
check_and_install_tools
245+
246+
local current_swift_version
247+
current_swift_version=$(get_current_swift_version)
248+
log "Current Swift version: $current_swift_version"
249+
250+
log "Fetching latest 6.2 static SDK information"
251+
local sdk_info
252+
if ! sdk_info=$(curl -fsSL "${STATIC_SDK_WEBROOT}/latest-build.yml"); then
253+
fatal "Failed to fetch static SDK information"
254+
fi
255+
256+
local sdk_dir
257+
sdk_dir=$(parse_yaml_value "dir" "$sdk_info")
258+
local sdk_checksum
259+
sdk_checksum=$(parse_yaml_value "checksum" "$sdk_info")
260+
261+
log "Latest static SDK: $sdk_dir"
262+
log "Static SDK checksum: ${sdk_checksum:0:16}..."
263+
264+
local swift_executable=""
265+
local sdk_name=""
266+
267+
# Check if current Swift version matches the static SDK version
268+
if [[ "$current_swift_version" == "$sdk_dir" ]]; then
269+
log "✅ Current Swift version matches latest static SDK version"
270+
log "Using system Swift and installing static SDK"
271+
272+
swift_executable="swift"
273+
install_static_sdk "$sdk_info" "$swift_executable"
274+
sdk_name=$(get_static_sdk_name "$sdk_info")
275+
276+
else
277+
# Either no Swift or version mismatch, so download matching toolchain
278+
if [[ "$current_swift_version" == "none" ]]; then
279+
log "No Swift installation detected"
280+
else
281+
log "Current Swift version ($current_swift_version) does not match latest static SDK ($sdk_dir)"
282+
fi
283+
284+
log "Downloading matching toolchain and installing static SDK"
285+
286+
# Download the toolchain that matches the static SDK snapshot name
287+
swift_executable=$(download_and_extract_toolchain "$sdk_dir")
288+
install_static_sdk "$sdk_info" "$swift_executable"
289+
sdk_name=$(get_static_sdk_name "$sdk_info")
290+
fi
291+
292+
# Uncomment to save paths to files for other scripting
293+
# echo "$swift_executable" > swift_executable_path.txt
294+
# echo "$sdk_name" > static_sdk_name.txt
295+
296+
# log "Paths saved to:"
297+
# log " swift_executable_path.txt"
298+
# log " static_sdk_name.txt"
299+
300+
# Run Swift build with static SDK
301+
log ""
302+
run_swift_static_sdk_build "$swift_executable" "$sdk_name"
303+
304+
# Success
305+
log ""
306+
log "✅ Setup and build completed successfully!"
307+
log ""
308+
log "Swift executable path: $swift_executable"
309+
log "Static SDK name: $sdk_name"
310+
log ""
311+
log "To run manually:"
312+
log " $swift_executable build --swift-sdk $sdk_name"
313+
314+
}
315+
316+
main "$@"

.github/workflows/swift_package_test.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ on:
8787
type: boolean
8888
description: "Boolean to enable linux testing. Defaults to true"
8989
default: true
90+
enable_linux_static_sdk_build:
91+
type: boolean
92+
description: "Boolean to enable building with the Linux static SDK. Defaults to false"
93+
default: false
9094
enable_macos_checks:
9195
type: boolean
9296
description: "Boolean to enable macOS testing. Defaults to false"
@@ -175,6 +179,39 @@ jobs:
175179
- name: Build / Test
176180
run: ${{ inputs.linux_build_command }} ${{ (contains(matrix.swift_version, 'nightly') && inputs.swift_nightly_flags) || inputs.swift_flags }}
177181

182+
linux-static-sdk-build:
183+
name: Linux Static SDK Build (nightly-6.2 - ${{ matrix.os_version }})
184+
if: ${{ inputs.enable_linux_static_sdk_build }}
185+
runs-on: ubuntu-latest
186+
strategy:
187+
fail-fast: false
188+
matrix:
189+
os_version: ${{ fromJson(inputs.linux_os_versions) }}
190+
container:
191+
image: swiftlang/swift:nightly-6.2-${{ matrix.os_version }}
192+
steps:
193+
- name: Swift version
194+
run: swift --version
195+
- name: Checkout repository
196+
uses: actions/checkout@v4
197+
- name: Provide token
198+
if: ${{ inputs.needs_token }}
199+
run: |
200+
echo "GITHUB_TOKEN=${{ secrets.GITHUB_TOKEN }}" >> $GITHUB_ENV
201+
- name: Set environment variables
202+
if: ${{ inputs.linux_env_vars }}
203+
run: |
204+
for i in "${{ inputs.linux_env_vars }}"
205+
do
206+
printf "%s\n" $i >> $GITHUB_ENV
207+
done
208+
- name: Pre-build
209+
run: ${{ inputs.linux_pre_build_command }}
210+
- name: Install static SDK and build
211+
run: |
212+
which curl || (apt -q update && apt -yq install curl)
213+
curl -s --retry 3 https://raw.githubusercontent.com/swiftlang/github-workflows/refs/heads/main/.github/workflows/scripts/install-and-build-with-6.2-static-sdk.sh | bash
214+
178215
windows-build:
179216
name: Windows (${{ matrix.swift_version }} - windows-2022)
180217
if: ${{ inputs.enable_windows_checks }}

0 commit comments

Comments
 (0)