Swift with Linux

It’s been more than five years since Swift declared itself open source and supported Linux in 2015. Although Swift grew rapidly in its first few years, it was not widely accepted by the Linux community. There are many reasons for this situation, including language stability problems, imperfect support for Linux, lack of attractive basic libraries and third-party libraries, and lack of hot projects.

In the past two years, these problems have improved significantly.

  • Starting with Swift5, the Swift team has announced that the ABI is stable. From there, Swift provides binary compatibility for applications, and with ABI stability as the foundation, Swift’s support for other platforms will be much faster and more powerful
  • In 2020, the Swift team released version 5.3. In addition to “significant quality improvements and performance enhancements,” one of the key features of Swift5.3 is official support for the Linux and Windows platforms. In fact, this is the first time that Swift’s release process has a release leader for each of the three different platforms. In the first sign of their commitment to bringing Swift to Linux, the Swift team has announced that a new version of Swift is available on a number of Linux distributions.
  • A number of excellent official and third-party cross-platform libraries have emerged. Apple alone has contributed a large number of Swift codes to the Swift community in recent years and has maintained a very high frequency of submissions.
  • Swift has achieved good results in server side and deep learning field.

Swift is ready for more Linux.

The reason for writing this article

The other day, when I wrote an introduction to Publish blog I – Getting Started, a great static website generator in Swift, someone asked me if I could use it on Linux, and I said no problem. But when you think about it, Publish supports Linux perfectly, but is it as easy for developers to develop and debug as it is on the MAC?

When using Vapor, I installed Swift on Ubuntu via Docker, but the code was debugged on a MAC. I’m also curious as to what the Swift development environment will look like on Linux in 2021.

The goal of this article is to build a production standard Swift development and debugging environment on Linux. Users will get a comprehensive development experience that supports code highlighting, auto-completion, defined jumps, breakpoint debugging, code landscaping, code static scanning, and configuration across operating system platforms.

To prepare

Because everyone uses a different Linux distribution, if necessary dependencies are missing during the installation process, install the required libraries as prompted.

This article describes how to do each step, along with the necessary explanations. Even if you are using a different Linux distribution, or a different editor, or even after a major upgrade to Swift or other tools, you can still build your environment using the following installation ideas.

The starting point for this article was built on an Ubuntu 20.04LTS (minimal installation) system with Visual Studio Code 1.53.0 installed. Select Swift Toolchain 5.3.3.

For Ubuntu 20.04, python2.7 and NPM need to be installed to do the rest of the following.

$sudo apt install libpython2.7 libpython2.7-dev libz3-4 NPMCopy the code

Swift Toolchain

Toolchain selection

Although you can download the Swift Toolchain source code and compile it yourself, the most recommended way is to install it using the official compiled download package. Swift.org provides Ubuntu 16.04, Ubuntu 18.04, Ubuntu 20.04, CentOS 7, CentOS 8, and Amazon Linux 2. Other distributions have their own official support, such as Fodor, Red Hat Enterprise Linux8, Raspbian OSi, etc

Swift has been officially supported on the Linux platform since version 5.3, so this article chose to install Swift 5.3.3 Release on Ubuntu 20.04.

The installation

Find the Swift Toolchain download address for your distribution on Swift.org

$cd ~
$wget https://swift.org/builds/swift-5.3.3-release/ubuntu2004/swift-5.3.3-RELEASE/swift-5.3.3-RELEASE-ubuntu20.04.tar.gz
Copy the code

Unzip the files

$tar- XZF swift - 5.3.3 - RELEASE - ubuntu20.04. Tar. GzCopy the code

The Swift toolchain will be unwrapped in the ~/ swift-5.3.3-release-Ubuntu20.04 directory. Move the directory to your preferred path, such as:

$sudoSwift - 5.3.3 - RELEASE - mv ubuntu20.04 / usr/share/swiftCopy the code

Keep in mind that the moved path, /usr/share/swift, will be used several times in the following configuration.

Add the swift bin path to the environment

$echo "export PATH=/usr/share/swift/usr/bin:$PATH" >> ~/.bash
$source .bash
Copy the code

At this point, Swift has been installed on your current system

$swift-- Version Swift Version 5.3.3 (swift-5.3.3-release) Target: x86_64-unknown-linux-gnuCopy the code

Run the first piece of code

Create hello. Swift with the content as

#! /usr/bin/env swift
print("My first swift code")
Copy the code
$cd ~
$swift hello.swift
My first swift code
Copy the code

Or the Swift code can be executed as a script

$chmod +755 hello.swift
$./hellow.swift
My first swift code
Copy the code

Create your first Swift project

Swift Package Manager (SPM) is apple’s tool for creating libraries and executables that use Swift. It is now part of the Swift Toolchain.

Create an executable program project

$cd ~
$mdkir MyProject
$cd MyProject
$swift package init --type executable
Creating executable package: MyProject
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/MyProject/main.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/MyProjectTests/
Creating Tests/MyProjectTests/MyProjectTests.swift
Creating Tests/MyProjectTests/XCTestManifests.swift
Copy the code

Compile and run the project

~/MyProject$swift run
[4/4] Linking MyProject
Hello, world!
Copy the code

This project will also be used in the following configuration. You can also open project files directly using vscode

~/MyProject$code .
Copy the code

Vscode already has built-in support for code highlighting for Swift.

SourceKit-LSP

What is the LSP

The whole process of LSP is Language Sever Protocol, which is a standardized Protocol proposed by Microsoft. It aims to unify the communication between development tools and Lanuguage Server. LSP provides a common set of functions for supported languages, including syntax highlighting, auto-completion, defining hops, and finding references. Apple has provided the CODE and support for LSP to the Swift community since 2018. Currently LSP has been integrated into the Swift toolchain.

The installation

Although LSP has been integrated into Swift ToolChain, we still need to install and configure the corresponding plug-in for vscode to use the Swift LSP function in vscode.

Since the Swift LSP plug-in is not placed in vscode’s plug-in market, we still need to download it from apple’s LSP Github site

$git clone https://github.com/apple/sourcekit-lsp.git
Copy the code

The downloaded file contains all the CODES for the LSP and the plug-in code. We just need to install the plug-in code.

$cd sourcekit-lsp/Editors/vscode/
$npm run createDevPackage 
Copy the code

The compiled plug-in is placed in the ~/sourcekit-lsp/Editors/vscode/out directory.

Configuration vscode

Install to vscode using a command line plug-in

$cd ~/sourcekit-lsp/Editors/vscode/out
$code --install-extension sourcekit-lsp-vscode-dev.vsix
Copy the code

Or select the plug-in in vscode to install

The configuration Settings

Since the LSP is integrated into the Swift Toolchain, when we install the Toolchain, it is already installed in the /usr/share/swift/usr/bin directory, which is also set in the environment PATH. Therefore, it is usually not necessary to specify the absolute PATH. Vscode can use the LSP function of Swift. If you download the new version of the LSP yourself, you can set the path in settings.json.

"sourcekit-lsp.serverPath": "/usr/share/swift/usr/bin/sourcekit-lsp"
Copy the code

Once installed, vscode can support auto-completion of code, define jumps, and more.

LLDB

What is a LLDB

The LLDB debugger is the debugger component of the LLVM project. It is built as a set of reusable components that make extensive use of existing libraries in LLVM, such as the Clang expression parser and the LLVM disassembler. Through LLDB, VSCode has the ability to debug Swift code.

The installation

Since Swift Toolchain is currently integrated with LLDB, we do not need to install it. We only need to install VSCode’s LLDB plug-in.

In vscode’s plug-in marketplace, install CodeLLDB

Specify the LLDB location in settings.json

"lldb.library": "/usr/share/swift/usr/lib/liblldb.so"
Copy the code

You can also do that in the Settings UI

Debugging configuration Files

To debug a project using LLDB in vscode, you need to create the debug configuration files launch.json and tasks.json for each project in the. Vscode directory of the project.

Json is the configuration file vsCode uses for debugging, such as specifying the debug locale, specifying the debug type, and so on. This is similar to target in XCode. In the Swift project, we typically set up two configurations, one for debugging the program and one for Unit testing.

$cd MyProject
$code .
Copy the code

The first time you click the run button on the left, vscode will prompt you to create the launch.json file, or you can manually create the file yourself in the.vscode directory.

launch.json

{
    "version": "0.2.0"."configurations": [{"type": "lldb"."request": "launch"."name": "Debug"."program": "${workspaceFolder}/.build/debug/MyProject"."args": []."cwd": "${workspaceFolder}"."preLaunchTask": "swift-build"
        },
        {
            "type": "lldb"."request": "launch"."name": "unit testing on Linux"."program": "./.build/debug/MyProjectPackageTests.xctest"."preLaunchTask": "swift-build-tests"}}]Copy the code
  • type

    The type of debugger used for this launch configuration, swift debugging needs to be set to LLDB

  • request

    The request type of this launch configuration, swift debugging needs to be set to launch,

  • name

    Display name in the debug start configuration drop – down list

  • program

    Location of executable files. Execution files compiled with Swift build (without the realase argument) are placed in the project directory ${workspaceFolder}/.build/debug/, usually with the project name (MyProject in this case); Swift build -c release The compiled execution file is placed under ${workspaceFolder}/.build/release/. The file name is project name (MyProject in this example). Unit testing of the executable file placed in the ${workspaceFolder} / build/debug/file name for the project name usually PackageTests. Xctest (in this case for MyProjectPackageTests. Xctest). Set this item according to the name and configuration of each project.

  • args

    Parameters passed to the program. For example, if your project supports MyProject name hello, then args is [“name”,”hello”]

  • cwd

    Current working directory, used to find dependencies and other files

  • preLaunchTask

    To start tasks before the debug session starts, each task needs to have a setting in tasks.json. For example, in this example, swift-build corresponds to the task of label:swift-build in tasks.json. For Swift projects, the most common thing to do before debugging is compile.

tasks.json

{
    "version": "2.0.0"."tasks": [{"label": "swift-build"."type": "shell"."command":"swift build"
        },
        {
            "label": "swift-build-tests"."type": "process"."command": "swift"."args": [
                "build"."--build-tests"]]}}Copy the code
  • lable

    Corresponds to preLaunchTask in launch.json

  • type

    Shell or Process, both of which are used in this example for better illustration.

  • command

    If type is process, commNad can only be the name of the executable file (without parameters) in which the command is to be executed. In this example, it is swift. If type is shell, you can directly write the parameters to be invoked in command, such as swift build

  • args

    If type is process, enter the parameters that need to be called here. In this case, swift-build-tests can also be written

"label": "swift-build-tests"."type": "shell"."command": "swift build --build-tests"
Copy the code

Json and tasks.json have many other options, please refer to the VSCode manual and SPM manual for more usage.

We are now ready to start debugging the Swift project

First debugging

$cd MyProject
$code .
Copy the code

Feel free to add something to main.swift, such as:

import Foundation
let a = 100
print("Hello, world!\(Int.random(in: 0.100))")
print("a:\(a)")
Copy the code

SwiftFormat

Why Foramt the code

Many projects have a fixed code style, and a uniform code specification not only helps with project iteration and maintenance, but also makes the code more aesthetically pleasing and readable. But not every programmer is able to master and use project style conventions. It’s nice to be able to do this with automated tools.

There are several Format projects in the Swift community, the most active currently being nicklockwood’s swiftformat and Apple’s swift-format. In this case, we chose to install Nicklockwood’s SwiftFormat. The installation methods are similar, SwiftFormat supports more rules than Swift-Foramt, and swiftFormat does not require the same strict binding with Swift versions.

Install the command-line tool

$cd ~
$git clone https://github.com/nicklockwood/SwiftFormat.git
$cd SwiftFormat
$swift build -c release
$sudo cp ~/SwiftFormat/.build/release/swiftformat /usr/local/bin
$swiftformat --version
0.47.11
Copy the code

Install the vscode plug-in

The VsCode plug-ins for SwiftFormat, Swift-Format and SwiftLint were developed by Valentin Kabel, who also manages and develops several other VSCode plug-ins for SwiftFormat, Swift-Format and SwiftLint. Has contributed to better use of swift in vscode.

Select the plugin for SwiftFormat in the plugin store (make sure you choose the wrong plugin).

Add it in settings.json

"swiftformat.path": "/usr/local/bin/swiftformat"."swiftformat.configSearchPaths": [
        "./swiftformat"."~/.swiftformat"
        ]
Copy the code

Swiftformat from swiftformat. ConfigSearchPaths set path to attempt to search for users to create your own configuration file (. Swiftformat), the configured above, if not, the current directory from the user to find the root directory. If neither, use the default configuration and rules.

Swiftformat currently contains over 50 Rules and is well documented, with a list of the latest Rules and demos available at rules.md. Note that VSCode currently does not respond correctly to –indent in the SwiftFormat custom configuration. You need to set indent separately in VSCode (I am currently using EditorConfig for VS Code to do unified Settings). In addition, if swift.options:[“–config”,”~/rules/.swiftformat”] specifies a rule file with a higher priority than the rule file in swiftformat.path.

SwiftLint

Make the code more canonical

Lint in computer science, Lint is the name of a utility program used to flag suspicious, unstructured sections of source code. It is a static program analysis tool, first applied to C language, developed on UNIX platform. It has since become a generic term for a tool used to mark questionable passages in source code in any computer programming language. One of the most widely used in the Swift community is SwiftLint, developed by Realm.

In fact, swiftFormat and Swift-Format both have the functionality of SwiftLint and use similar rules to SwiftLint in many places (both are based on Github’s Swift Style Guide), but each has slightly different features.

Swiftformat is more about automatic changes to code, while SwiftLint provides something that SwiftFormat doesn’t because it hooks Clang and Sourcekit directly. Real-time validation and prompting during the code entry phase (usually without using its AutoCorrect).

Install the command-line tool

$git clone https://github.com/realm/SwiftLint.git
$cd SwiftLint
$swift build -c release
$sudo cp ~/SwiftLint/.build/release/swiftlint /usr/local/bin
$swiftlint --version
0.42.0
Copy the code

Install the vscode plug-in

Install the SwiftLint plugin in the VSCode plugin marketplace

Add it in settings.json

"swiftlint.path": "/usr/local/bin/swiftlint"."swiftlint.toolchainPath": "/usr/share/swift/usr/bin"."swiftlint.configSearchPaths": [
        "./.swiftlint.yml"."~/.swiftlint.yml"
    ]
Copy the code

The setting of configSearchPath is similar to that of SwiftFormat. If you do not need to customize the configuration, skip this step.

Cross-platform Configuration

We have built a fairly complete Swift development environment on Ubuntu 20.04.

settings

If you use vsCode’s Setting synchronization as I did, Settings. Json will not work on other platforms (such as MAC).

In order to build a development environment for multiple platforms, we need to enable configured multi-platform support and set it separately for each platform.

Install the Platform-settins plug-in

Modify the Settings. The json

The current is:

{
    "sourcekit-lsp.serverPath": "/usr/share/swift/usr/bin/sourcekit-lsp"."lldb.library": "/usr/share/swift/usr/lib/liblldb.so"."swiftformat.path": "/usr/local/bin/swiftformat"."swiftformat.configSearchPaths": [
        "./swiftformat"."~/.swiftformat"]."swiftlint.path": "/usr/local/bin/swiftlint"."swiftlint.toolchainPath": "/usr/share/swift/usr/bin"."swiftlint.configSearchPaths": [
        "./.swiftlint.yml"."~/.swiftlint.yml"]}Copy the code

Is amended as:

{
    "platformSettings.autoLoad": true."platformSettings.platforms": {
        "linux": {"sourcekit-lsp.serverPath": "/usr/share/swift/usr/bin/sourcekit-lsp"."lldb.library": "/usr/share/swift/usr/lib/liblldb.so"."swiftformat.path": "/usr/local/bin/swiftformat"."swiftlint.path": "/usr/local/bin/swiftlint"."swiftlint.toolchainPath": "/usr/share/swift/usr/bin",},"mac": {"sourcekit-lsp.serverPath": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/sourcekit-lsp"."lldb.library": "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/LLDB"."swiftformat.path": "/usr/local/bin/swiftformat".// Homebrew also happens to be installed here
            "swiftlint.path": "/usr/local/bin/swiftlint".// Point to the actual path of the tool
            "swiftlint.toolchainPath": "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin",}},"swiftformat.configSearchPaths": [
        "./swiftformat"."~/.swiftformat"]."swiftlint.configSearchPaths": [
        "./.swiftlint.yml"."~/.swiftlint.yml"]}Copy the code

launch.json

On MAC, unit Testing is also called differently than on Linux, so you need to add a configuration in launch.json. Since the same preLauchchTask is used, tasks.json does not need to be changed.

       {
            "type": "lldb"."request": "launch"."name": "Debug tests on macOS"."program": "/Applications/Xcode.app/Contents/Developer/usr/bin/xctest".//For example /Applications/Xcode.app/Contents/Developer/usr/bin/xctest
            "args": [
                "${workspaceFolder}/.build/debug/MyProjectPackageTests.xctest"]."preLaunchTask": "swift-build-tests"
        },
Copy the code

On different platforms, select the corresponding target.

conclusion

I hope this article can help more people develop with Swift on Linux.

My personal blog, Swift Notepad, has more on Swift, SwiftUI, and CoreData.