Swift давно перестал быть языком только для Apple-платформ. Официальный тулчейн собирается для Linux, поддерживает серверные фреймворки, Swift Package Manager и отладку через LLDB. Доступны и сам компилятор, и статическая линковка, и готовые контейнерные образы. Ниже — установка через Swiftly, структура пакета, сборка, тесты, минимальный сервис на Vapor и разбор различий между платформами, на которые натыкаются почти все новички.

Установка через Swiftly

Swiftly — официальный менеджер версий. Он скачивает тулчейн, прописывает переменные окружения и позволяет держать несколько версий одновременно, переключаясь между ними без конфликтов. Установка занимает пару минут и не требует прав root.

curl -O https://download.swift.org/swiftly/linux/swiftly-$(uname -m).tar.gz
tar zxf swiftly-$(uname -m).tar.gz
./swiftly init --quiet-shell-followup
. "${SWIFTLY_HOME_DIR:-$HOME/.local/share/swiftly}/env.sh" && hash -r

Последняя строка подхватывает окружение в текущей оболочке. Чтобы настройки сохранились после перезахода, инициализатор добавляет нужный фрагмент в профиль. Дальше проверяют список доступных релизов и ставят актуальный.

swiftly install latest
swiftly list
swift --version

Команда swiftly use выбирает активную версию, что удобно при проверке совместимости библиотек. Для серверов без интернета или с жёсткими требованиями к воспроизводимости используют официальный образ: он содержит компилятор и системные зависимости, а итоговый бинарник можно собрать статически.

docker run --rm -v "$PWD":/src -w /src swift:latest swift build -c release

Структура пакета

Пакет описывается файлом Package.swift. В нём указывают версию инструментов, зависимости и цели. Для исполняемого файла достаточно одной цели, но тестовую цель стоит добавить сразу.

// swift-tools-version: 6.0
import PackageDescription

let package = Package(
    name: "MyCLI",
    dependencies: [
        .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0")
    ],
    targets: [
        .executableTarget(name: "MyCLI", dependencies: [.product(name: "Vapor", package: "vapor")]),
        .testTarget(name: "MyCLITests", dependencies: ["MyCLI"])
    ]
)

Каталог Sources/MyCLI содержит точку входа, тесты кладут в Tests/MyCLITests. Разделение важно: без тестовой цели команда swift test молча завершится успехом, и это часто сбивает с толку в CI, где пустой прогон выглядит как зелёная сборка.

Сборка, запуск и тесты

Основные команды немногочисленны и предсказуемы. Флаг -c release включает оптимизацию, -v показывает реальные вызовы компилятора, а --parallel ускоряет тесты на многоядерной машине.

swift build
swift run MyCLI
swift test --parallel
swift package describe

Для диагностики зависимостей полезен swift package show-dependencies, для обновления — swift package update. Кэш пакетов и артефакты лежат в каталоге .build, поэтому его удаление равносильно чистой пересборке. Если сборка внезапно падает после смены тулчейна, начинать нужно именно с очистки кэша.

Минимальный сервис на Vapor

Vapor — самый распространённый серверный фреймворк для Swift. После добавления зависимости точка входа настраивает маршруты и запускает приложение. Асинхронный API стал основным, поэтому примеры из старых статей с app.run() уже не отражают актуальный стиль.

import Vapor

let app = try await Application.make(.detect())
app.get("health") { _ in "ok" }
try await app.execute()

Запуск выполняется командой swift run MyCLI serve --hostname 0.0.0.0 --port 8080. В контейнере обязательно слушать 0.0.0.0, иначе порт будет доступен только внутри сети контейнера. Режим задаётся через --env production, а хост и порт можно переопределить переменными окружения.

Особенности Linux

Главное отличие — Foundation. На Linux часть API вынесена в отдельные модули, поэтому импорт приходится делать условным. Кроме того, нет Apple-фреймворков, а работа с датами и локалью опирается на ICU.

  • CoreData, Combine и SwiftUI на Linux недоступны.
  • FoundationNetworking и FoundationXML импортируются через canImport.
  • Системные библиотеки ставятся пакетным менеджером дистрибутива.
  • Бинарник зависит от версии glibc целевой системы.

Последний пункт особенно важен при переносе сборки: бинарник, собранный на новом дистрибутиве, может не запуститься на сервере со старым glibc. Поэтому сборку в CI ведут в том же образе, что и эксплуатацию, либо используют статическую линковку.

#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

Для сборки нужны системные библиотеки: libcurl, libxml2, sqlite, zlib и компилятор C. Их ставят через пакетный менеджер дистрибутива. Если компоновка падает с сообщением о missing -lcurl, причина почти всегда в отсутствующем пакете разработки, а не в самом Swift. Второй частый случай — несовпадение версии glibc между сборочным образом и целевым сервером.

Отладка и профилирование

LLDB на Linux работает полноценно: точки останова, просмотр переменных, backtrace и пошаговое выполнение. Для символов сборку делают отладочной, а для анализа памяти подключают санитайзеры.

swift build -Xswiftc -g
lldb .build/debug/MyCLI
ldd .build/debug/MyCLI
swift build -Xswiftc -sanitize=address

Команда ldd показывает, какие разделяемые библиотеки потребует бинарник, и сразу выявляет забытые зависимости. Для профилирования CPU применяют perf: бинарник собирают с отладочными символами, снимают профиль и смотрят горячие функции. Санитайзеры замедляют работу, поэтому их включают только на стенде.

CI и контейнер

В CI достаточно образа Swift и трёх шагов: сборка, тесты, упаковка. Кэшировать имеет смысл каталог .build, иначе каждая сборка будет скачивать зависимости заново. Для финального образа используют multi-stage: компиляция в полном образе, копирование бинарника в минимальный базовый слой.

FROM swift:latest AS build
WORKDIR /src
COPY . .
RUN swift build -c release --static-swift-stdlib

FROM debian:stable-slim
COPY --from=build /src/.build/release/MyCLI /usr/local/bin/MyCLI
ENTRYPOINT ["/usr/local/bin/MyCLI"]

Флаг --static-swift-stdlib вкладывает стандартную библиотеку в бинарник, поэтому в финальном образе не нужны её разделяемые версии. Размер образа растёт, зато пропадает риск несовпадения версий. Перед публикацией полезно запустить полученный контейнер локально и проверить, что приложение стартует без доступа к сети сборки.

Итог

Swift на Linux — рабочая среда для серверных и консольных приложений, а не эксперимент. Swiftly снимает боль с версиями, Swift Package Manager закрывает сборку и зависимости, Vapor даёт HTTP-стек, а LLDB и санитайзеры — нормальную отладку. Главное — помнить про FoundationNetworking, системные библиотеки и совместимость glibc, и тогда различия с macOS перестают быть проблемой.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте