Spec-Zone.ru › Swift

Начало работы со статическим SDK для Linux

Хорошо известно, что Swift можно использовать для разработки программного обеспечения для платформ Apple, таких как macOS или iOS, но Swift также поддерживается и на других платформах, включая Linux и Windows.

Разработка для Linux особенно интересна, потому что исторически программы на Swift для Linux нуждались в установке копии Swift-런타임 и всех его зависимостей на целевой системе. Кроме того, программа, созданная для конкретного дистрибутива, или даже для конкретной основной версии конкретного дистрибутива, необязательно будет работать на любом другом дистрибутиве, а в некоторых случаях даже на другой основной версии того же дистрибутива.

Статическое SDK для Linux Swift решает обе эти проблемы, позволяя создавать вашу программу как полностью статически связанный исполняемый файл без каких-либо внешних зависимостей (даже без библиотеки C), что означает, что он будет работать на любом дистрибутиве Linux, поскольку единственное, от чего он зависит, это интерфейс системных вызовов Linux.

Кроме того, статическое SDK для Linux можно использовать с любой платформы, поддерживаемой компилятором и менеджером пакетов Swift; это означает, что вы можете разрабатывать и тестировать свою программу на macOS, прежде чем создавать и развертывать ее на сервере на базе Linux, работающем локально или где-то в облаке.

Статическое против динамического связывания

Связывание — это процесс объединения различных частей компьютерной программы и соединения всех ссылок между ними. При статическом связывании, как правило, эти части представляют собой объектные файлы или статические библиотеки (которые на самом деле просто являются коллекциями объектных файлов).

При динамическом связывании эти части представляют собой исполняемые файлы и динамические библиотеки (также известные как dylibs, shared objects или DLL).

Существует две ключевые различия между динамическим и статическим связыванием:

  • Время, когда происходит связывание. Статическое связывание происходит во время построения вашей программы; динамическое связывание происходит во время выполнения.

  • Факт, что статическая библиотека (или архив) на самом деле является коллекцией отдельных объектных файлов, в то время как динамическая библиотека — монолитна.

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

На практике вещи могут быть сложнее — статический компоновщик может фактически работать на основе отдельных разделов или атомов из ваших объектных файлов, поэтому он может быть способен отбрасывать отдельные функции или фрагменты данных, а не только целые объекты.

Преимущества и недостатки статического связывания

Преимущества статического связывания:

  • Нет накладных расходов во время выполнения.

  • Включается только код из библиотек, который фактически нужен.

  • Нет необходимости в отдельных установленных динамических библиотеках.

  • Нет проблем с версиями во время выполнения.

Недостатки статического связывания:

  • Программы не могут совместно использовать код (более высокое общее использование памяти).

  • Нет возможности обновления зависимостей без перекомпиляции программы.

  • Более крупные исполняемые файлы (хотя это может быть компенсировано тем, что не нужно устанавливать отдельные динамические библиотеки).

В частности, в Linux также можно использовать статическое связывание, чтобы полностью устранить зависимости от системных библиотек, поставляемых дистрибутивом, в результате чего получаются исполняемые файлы, которые работают на любом дистрибутиве и могут быть установлены путем простого копирования.

Установка SDK

Прежде чем начать, важно отметить:

  • Вам необходимо установить инструмент разработки Open Source со страницы swift.org.

  • Вы не можете использовать инструмент разработки, поставляемый с Xcode, для создания программ, использующих данное SDK.

  • Если вы используете macOS, вам также необходимо убедиться, что вы используете компилятор Swift из этого набора инструментов, выполнив инструкции здесь.

  • Набор инструментов должен соответствовать версии статического SDK для Linux, которую вы устанавливаете. Статическое SDK для Linux содержит соответствующую версию Swift в своём имени файла, чтобы помочь определить правильную версию SDK.

  • При установке SDK Swift из удалённых URL-адресов, вы должны передать параметр --checksum с соответствующей контрольной суммой, предоставленной автором SDK Swift.

После этого установка статического SDK для Linux очень проста; введите в командной строке

$swift sdk install <URL-or-filename-here> [--checksum <checksum-for-archive-URL>]

указав URL-адрес (и соответствующую контрольную сумму) или имя файла, в котором можно найти SDK.

Например, предположим, что вы установили набор инструментов swift-6.0-DEVELOPMENT-SNAPSHOT-2024-07-02-a, вам нужно будет ввести

$swift sdk install https://download.swift.org/swift-6.0-branch/static-sdk/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-07-02-a/swift-6.0-DEVELOPMENT-SNAPSHOT-2024-07-02-a_static-linux-0.0.1.artifactbundle.tar.gz --checksum 42a361e1a240e97e4bb3a388f2f947409011dcd3d3f20b396c28999e9736df36

чтобы установить соответствующий статический SDK для Linux.

Swift загрузит и установит SDK на вашу систему. Вы можете получить список установленных SDK с помощью

$swift sdk list

и также можно удалить их с помощью

$swift sdk remove <name-of-SDK>

Ваша первая статически связанная программа для Linux

Сначала создайте каталог для хранения кода:

$mkdir hello
$cd hello

Далее, попросите Swift создать для вас новый пакет программы:

$swift package init --type executable

Вы можете скомпилировать и запустить это локально:

$swift build
Building for debugging...
[8/8] Applying hello
Build complete! (15.29s)
$.build/debug/hello
Hello, world!

Но при установке статического SDK для Linux вы также можете скомпилировать двоичные файлы для машин x86-64 и ARM64:

$swift build --swift-sdk x86_64-swift-linux-musl
Building for debugging...
[8/8] Linking hello
Build complete! (2.04s)
$file .build/x86_64-swift-linux-musl/debug/hello
.build/x86_64-swift-linux-musl/debug/hello: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped
$swift build --swift-sdk aarch64-swift-linux-musl
Building for debugging...
[8/8] Linking hello
Build complete! (2.00s)
$file .build/aarch64-swift-linux-musl/debug/hello
.build/aarch64-swift-linux-musl/debug/hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, with debug_info, not stripped

Эти файлы можно скопировать на соответствующую систему на базе Linux и выполнить:

$scp .build/x86_64-swift-linux-musl/debug/hello linux:~/hello
$ssh linux ~/hello
Hello, world!

А как насчёт зависимостей пакетов?

Пакеты Swift, которые используют Foundation или Swift NIO, должны просто работать. Однако, если вы попытаетесь использовать пакет, который использует библиотеку C, вам, возможно, придётся немного поработать. Такие пакеты часто содержат файлы с кодом, подобным следующему:

#if os(macOS) || os(iOS)
import Darwin
#elseif os(Linux)
import Glibc
#elseif os(Windows)
import ucrt
#else
#error(Unknown platform)
#endif

Статическое SDK для Linux не использует Glibc; вместо этого оно основано на альтернативной библиотеке C для Linux под названием Musl. Мы выбрали такой подход по двум причинам:

  1. Musl отлично поддерживает статическое связывание.

  2. Musl имеет лицензию permissive, что упрощает распространение исполняемых файлов, статически связанных с ним.

Если вы используете такую зависимость, вам необходимо будет изменить её, чтобы импортировать модуль Musl вместо модуля Glibc:

#if os(macOS) || os(iOS)
import Darwin
#elseif canImport(Glibc)
import Glibc
#elseif canImport(Musl)
import Musl
#elseif os(Windows)
import ucrt
#else
#error(Unknown platform)
#endif

Иногда могут быть различия в способе импорта типов библиотек C между Musl и Glibc; это иногда происходит, если кто-то добавил аннотации nullability или где тип указателя использует forward-объявленный struct, для которого никогда не предоставляется фактическое определение. Обычно проблема будет очевидна — аргумент или результат функции будет Optional в одном случае и не-Optional в другом, или тип указателя будет импортирован как OpaquePointer вместо UnsafePointer<FOO>.

Если вам необходимо внести такие изменения, вы можете сделать локальную копию зависимостей пакета редактируемой, выполнив

$swift package edit SomePackage

а затем отредактировать файлы в каталоге Packages, который появляется в каталоге исходных кодов вашей программы. Вы можете рассмотреть возможность отправки PR с любыми исправлениями, которые у вас могут быть.

Автор

Alastair Houghton Аластер Хаутон
Аластер Хаутон работает над Swift и Objective-C-런타임 в Apple.

Автор Аластер Хаутон Аластер Хаутон работает над Swift и Objective-C-런타임 в Apple.

Аластер Хаутон

The Swift Programming Language, Copyright © 2014-2025 Apple Inc.
Swift and the Swift logo are trademarks of Apple Inc.

Documentation for Swift 6.0.3


https://www.swift.org/documentation/articles/static-linux-getting-started.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API