Skip to content

Add FreeBSD platform support #992

Add FreeBSD platform support

Add FreeBSD platform support #992

Workflow file for this run

name: Pull Request
permissions:
contents: read
on:
pull_request:
types: [opened, reopened, synchronize]
push:
branches: [main, 'release/*']
jobs:
soundness:
name: Soundness
uses: swiftlang/github-workflows/.github/workflows/soundness.yml@main
with:
license_header_check_enabled: false
license_header_check_project_name: "Swift.org"
api_breakage_check_enabled: false
docs_check_enabled: false
format_check_enabled: false
shell_check_enabled: false
unacceptable_language_check_enabled: true
freebsd-aarch64-tests:
name: Test / FreeBSD aarch64
runs-on: ubuntu-latest
if: ${{ github.repository == 'networkextension/swiftly' || github.repository == 'swiftlang/swiftly' }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Install cloudflared
run: |
curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared any main' | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt-get update && sudo apt-get install -y cloudflared
- name: Set up SSH key and known hosts
env:
FREEBSD_SSH_KEY: ${{ secrets.FREEBSD_SSH_KEY }}
FREEBSD_CF_HOSTNAME: ${{ secrets.FREEBSD_CF_HOSTNAME }}
run: |
mkdir -p "$HOME/.ssh"
printf '%s\n' "$FREEBSD_SSH_KEY" > "$HOME/.ssh/freebsd_ci_key"
chmod 600 "$HOME/.ssh/freebsd_ci_key"
printf '%s ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFqpy2Vs6oX1K5khxWW7INHC8a6meSaSvNDVXpCSv1Gj\n' \
"$FREEBSD_CF_HOSTNAME" >> "$HOME/.ssh/known_hosts"
chmod 600 "$HOME/.ssh/known_hosts"
printf 'Host freebsd-ci\n HostName %s\n User swift\n IdentityFile %s/.ssh/freebsd_ci_key\n ProxyCommand cloudflared access tcp --hostname %%h\n' \
"$FREEBSD_CF_HOSTNAME" "$HOME" > "$HOME/.ssh/config"
chmod 600 "$HOME/.ssh/config"
- name: Sync source to board
run: |
ssh -F "$HOME/.ssh/config" freebsd-ci 'mkdir -p /home/swift/ci/swiftly'
rsync -avz --delete \
--exclude='.build' --exclude='.git' \
-e "ssh -F $HOME/.ssh/config" \
. freebsd-ci:/home/swift/ci/swiftly/
- name: Build and Test on FreeBSD aarch64
run: |
ssh -F "$HOME/.ssh/config" freebsd-ci /bin/sh << 'ENDSSH'
set -e
. "$HOME/swift632-env.sh"
cd "$HOME/ci/swiftly"
swift package resolve 2>&1
# CNIOBoringSSL: FreeBSD sys/time.h guards gettimeofday behind __XSI_VISIBLE,
# which is 0 unless _XOPEN_SOURCE>=500. BoringSSL doesn't define it.
# Inject _XOPEN_SOURCE 600 + sys/time.h unconditionally at line 1.
# Also strip any prior v1 patch (2-line) before applying the new 5-line one.
SSL_LIB=$(find .build/checkouts -path "*/CNIOBoringSSL*/ssl/ssl_lib.cc" 2>/dev/null | head -1)
if [ -n "$SSL_LIB" ]; then
grep -qF 'FreeBSD-gettimeofday-xsi' "$SSL_LIB" || {
grep -q 'FreeBSD-gettimeofday' "$SSL_LIB" && sed -i '' '1,2d' "$SSL_LIB"
awk 'NR==1{print "/* FreeBSD-gettimeofday-xsi */\n#ifndef _XOPEN_SOURCE\n#define _XOPEN_SOURCE 600\n#endif\n#include <sys/time.h>"}1' "$SSL_LIB" > /tmp/_ssl.cc
mv /tmp/_ssl.cc "$SSL_LIB"
echo "Patched $SSL_LIB"
}
fi
# CNIOBoringSSL: getentropy in unistd.h is behind __BSD_VISIBLE on FreeBSD.
# Forward-declare it directly so no feature macros are needed.
GE=$(find .build/checkouts -path "*/CNIOBoringSSL*/crypto/rand/getentropy.cc" 2>/dev/null | head -1)
if [ -n "$GE" ]; then
grep -qF 'FreeBSD-getentropy-fix' "$GE" || {
awk 'NR==1{print "/* FreeBSD-getentropy-fix */\n#if defined(__FreeBSD__)\nextern \"C\" int getentropy(void*, __SIZE_TYPE__);\n#endif"}1' "$GE" > /tmp/_ge.cc
mv /tmp/_ge.cc "$GE"
echo "Patched $GE"
}
fi
# All NIO-style lock files: FreeBSD pthread types are opaque pointers like OpenBSD
find .build/checkouts \( -name "Locks.swift" -o -name "NIOLock.swift" \) 2>/dev/null | while read LOCKS; do
grep -qF "pthread" "$LOCKS" || continue
grep -qF "os(OpenBSD) || os(FreeBSD)" "$LOCKS" || \
sed -i '' 's/os(OpenBSD)/os(OpenBSD) || os(FreeBSD)/g' "$LOCKS"
grep -qF "pthread_rwlock_t?>" "$LOCKS" || \
sed -i '' 's/pthread_rwlock_t> =/pthread_rwlock_t?> =/' "$LOCKS"
grep -qF "LockPrimitive = pthread_mutex_t?" "$LOCKS" || \
sed -i '' 's/typealias LockPrimitive = pthread_mutex_t$/typealias LockPrimitive = pthread_mutex_t?/' "$LOCKS"
grep -qF "pthread_mutexattr_t(bitPattern:" "$LOCKS" || \
sed -i '' 's/var attr = pthread_mutexattr_t()/var attr: pthread_mutexattr_t? = pthread_mutexattr_t(bitPattern: 0)/' "$LOCKS"
echo "Patched $LOCKS"
done
# swift-log Logging.swift: Glibc.stdout/stderr non-optional on FreeBSD (unlike Linux)
LOGGING=$(find .build/checkouts -path "*/swift-log*/Logging.swift" 2>/dev/null | head -1)
if [ -n "$LOGGING" ]; then
grep -qF "Glibc.stdout!" "$LOGGING" && \
sed -i '' 's/Glibc\.stdout!/Glibc.stdout/g; s/Glibc\.stderr!/Glibc.stderr/g' "$LOGGING" && \
echo "Patched $LOGGING"
fi
# swift-subprocess Thread.swift: MutexType/ConditionType need optional on FreeBSD
SUBTHREAD=$(find .build/checkouts -path "*/swift-subprocess*/Thread.swift" 2>/dev/null | head -1)
if [ -n "$SUBTHREAD" ]; then
grep -qF "pthread_mutex_t?" "$SUBTHREAD" || {
awk '/^private typealias MutexType = pthread_mutex_t$/{
print "#if os(FreeBSD) || os(OpenBSD)\nprivate typealias MutexType = pthread_mutex_t?\nprivate typealias ConditionType = pthread_cond_t?\n#else\n" $0; next}
/^private typealias ConditionType = pthread_cond_t$/{print $0 "\n#endif"; next}1' \
"$SUBTHREAD" > /tmp/_th.swift
mv /tmp/_th.swift "$SUBTHREAD"
echo "Patched $SUBTHREAD"
}
fi
swift build 2>&1
swift test --filter SwiftlyTests 2>&1
ENDSSH
timeout-minutes: 60
macos-tests-selfhosted:
name: Test (Self Hosted) / macOS Tahoe ARM64
runs-on: [self-hosted, macos, tahoe, ARM64]
if: ${{ github.repository == 'swiftlang/swiftly' }}
strategy:
fail-fast: false
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Prepare the action
run: ./scripts/prep-gh-action.sh --install-swiftly
- name: Build and Test
run: swift test
timeout-minutes: 60
tests-selfhosted:
name: Test (Self Hosted) / ${{ matrix.container }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
container: ["ubuntu:22.04", "ubuntu:24.04", "redhat/ubi9", "debian:12", "fedora:39"]
container:
image: ${{ matrix.container }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Prepare the action
run: ./scripts/prep-gh-action.sh --install-swiftly
- name: Build and Test
# UBI 9 - See https://github.com/swiftlang/swift/issues/80908
# UBI 9 - See https://github.com/swiftlang/swift/issues/80909
run: bash -c 'if [[ "${{ matrix.container }}" == "redhat/ubi9" ]]; then swift build --build-tests; else swift test; fi'
# Verify new platforms without a released Swiftly build
tests-bootstrapped:
name: Test (Bootstrapped) / ${{ matrix.container }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
container: ["swiftlang/swift:nightly-6.3-fedora41"]
container:
image: ${{ matrix.container }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Prepare the action
run: ./scripts/prep-gh-action.sh
- name: Build and Test
run: swift test
releasebuildcheck:
name: Release Build Check / Linux
runs-on: ubuntu-latest
container:
image: "redhat/ubi9"
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Prepare the action
run: ./scripts/prep-gh-action.sh --install-swiftly
- name: Build Artifact
run: swift run build-swiftly-release --test --skip "999.0.0"
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: swiftly-release-x86_64
path: .build/release/swiftly-*.tar.gz
if-no-files-found: error
retention-days: 1
- name: Upload Tests
uses: actions/upload-artifact@v4
with:
name: test-swiftly-linux-x86_64
path: .build/debug/test-swiftly-linux-x86_64.tar.gz
if-no-files-found: error
retention-days: 1
releasebuildcheckmacos:
name: Release Build Check / macOS
runs-on: [self-hosted, macos, tahoe, ARM64]
if: ${{ github.repository == 'swiftlang/swiftly' }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Prepare the action
run: ./scripts/prep-gh-action.sh --install-swiftly
- name: Build Artifact
run: swift run build-swiftly-release --test --skip "999.0.0"
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: swiftly-release-darwin
path: .build/release/swiftly-*.pkg
if-no-files-found: error
retention-days: 1
- name: Upload Tests
uses: actions/upload-artifact@v4
with:
name: test-swiftly-macos
path: .build/release/test-swiftly-macos.tar.gz
if-no-files-found: error
retention-days: 1
releasetest:
name: Test Release / ${{matrix.shell.pkg}}
needs: releasebuildcheck
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
shell: [
{"pkg": "bash", "bin": "/bin/bash"},
{"pkg": "zsh", "bin": "/bin/zsh"},
{"pkg": "fish", "bin": "/bin/fish"}
]
container:
image: "ubuntu:24.04"
steps:
- name: Prepare System
run: apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install ca-certificates gpg tzdata ${{matrix.shell.pkg}} && chsh -s ${{matrix.shell.bin}}
- name: Download Release
uses: actions/download-artifact@v4
with:
name: swiftly-release-x86_64
- name: Download Tests
uses: actions/download-artifact@v4
with:
name: test-swiftly-linux-x86_64
- name: Extract and Run Workflow Tests
run: cp swiftly-*.tar.gz /root/swiftly.tar.gz && cp test-swiftly-*.tar.gz /root && cd /root && tar zxf test-swiftly-*.tar.gz && ./test-swiftly -y ./swiftly.tar.gz
release-custom-install-test:
name: Test Release - Custom Install Location
needs: releasebuildcheck
runs-on: ubuntu-latest
container:
image: "ubuntu:24.04"
steps:
- name: Prepare System
run: apt-get update && DEBIAN_FRONTEND=noninteractive TZ=Etc/UTC apt-get -y install ca-certificates gpg tzdata
- name: Download Release
uses: actions/download-artifact@v4
with:
name: swiftly-release-x86_64
- name: Download Tests
uses: actions/download-artifact@v4
with:
name: test-swiftly-linux-x86_64
- name: Extract and Run Workflow Tests
run: cp swiftly-*.tar.gz /root/swiftly.tar.gz && cp test-swiftly-*.tar.gz /root && cd /root && tar zxf test-swiftly-*.tar.gz && ./test-swiftly -y --custom-location ./swiftly.tar.gz
formatcheck:
name: Format Check
runs-on: ubuntu-latest
container:
image: ubuntu:22.04
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Prepare the action
run: ./scripts/prep-gh-action.sh --install-swiftly
- name: Check format
run: swift run swiftformat --lint --dryrun . || (echo "Please run 'swift run swiftformat .' to format the source code."; exit 1)
docscheck:
name: Documentation Check
runs-on: ubuntu-latest
container:
image: ubuntu:24.04
steps:
- name: Install git
run: apt-get update && apt-get -y install git
- name: Checkout repository
uses: actions/checkout@v4
- name: Prepare the action
run: ./scripts/prep-gh-action.sh --install-swiftly
- name: Generate Swiftly CLI Reference and Check for Differences
run: swift package plugin --allow-writing-to-package-directory generate-docs-reference && bash -c 'git config --global --add safe.directory $(pwd)' && git diff --exit-code Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md || (echo "The documentation hasn't been updated with the latest swiftly command-line reference. Please run 'swift package plugin generate-docs-reference' and commit/push the changes."; exit 1)
- name: Generate Documentation Set
run: swift package --allow-writing-to-directory .build/docs generate-documentation --target SwiftlyDocs --output-path .build/docs
- name: Upload Documentation Artifacts
uses: actions/upload-artifact@v4
with:
name: swiftly-docs
path: .build/docs/**
if-no-files-found: error
retention-days: 1