Skip to content
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e4efbeb
DRAFT: Swiftly proxies
cmcgee1024 Aug 10, 2024
3b5c404
Add a swiftly install workflow where the version comes from the .swif…
cmcgee1024 Aug 10, 2024
956256f
update design to make auto-installation an error instead
cmcgee1024 Aug 20, 2024
375df29
provide a mechanism to find the currently in-use toolchain physical l…
cmcgee1024 Aug 20, 2024
ed68a9e
add more details about the selector prefix, and methods to escape
cmcgee1024 Aug 21, 2024
c745f4c
Restructure the PR to move the selector syntax from the proxies to a …
cmcgee1024 Aug 29, 2024
560236d
Implement proxy mechanism with dynamic toolchain selection
cmcgee1024 Sep 4, 2024
ae29e88
Merge branch 'main' of github.com:cmcgee1024/swiftly into proxies-design
cmcgee1024 Sep 5, 2024
ce0d27a
Rewrite the select toolchain function with a type for the selection r…
cmcgee1024 Sep 5, 2024
66dd459
Update the documentation
cmcgee1024 Sep 5, 2024
2df7357
Create a swiftly run command
cmcgee1024 Sep 6, 2024
8976bba
Fix empty command case with a single ++++
cmcgee1024 Sep 7, 2024
3caab66
Write run command and proxy tests
cmcgee1024 Sep 9, 2024
31f4327
Regenerate the cli reference documentation
cmcgee1024 Sep 9, 2024
16caf80
Fix design document discrepancies and add install proxy argument tests
cmcgee1024 Sep 9, 2024
b2aa165
Update the list command to decorate default, and in-use toolchains
cmcgee1024 Sep 10, 2024
7504dd3
Update list tests to check for in use and default labels
cmcgee1024 Sep 10, 2024
0e7b661
Make the version argument optional in the install subcommand
cmcgee1024 Sep 11, 2024
43d620a
Fix case of empty bin directory when checking for overwrite
cmcgee1024 Sep 12, 2024
2e3c59d
Remove +install selector option from swift run in favour of regular `…
cmcgee1024 Sep 20, 2024
9dd640c
Import GPG keys on every install to get new signing keys from swift.org
cmcgee1024 Sep 17, 2024
5e615ea
Make recommended documentation changes.
cmcgee1024 Oct 18, 2024
10a0856
Merge branch 'main' of github.com:cmcgee1024/swiftly into proxies-design
cmcgee1024 Oct 18, 2024
6d6050e
Provide a better error message on swiftly install with no version
cmcgee1024 Oct 19, 2024
6989796
Update README, and add documentation for the new run subcommand
cmcgee1024 Oct 20, 2024
52d081f
Prompt before updating the `.swift-version` file.
cmcgee1024 Oct 23, 2024
2f6d701
Merge branch 'main' of github.com:cmcgee1024/swiftly into proxies-design
cmcgee1024 Oct 23, 2024
cb0e923
Create proxies on toolchain installation, creating only the necessary…
cmcgee1024 Nov 5, 2024
bb36de0
Fix the design document
cmcgee1024 Nov 5, 2024
7269128
Merge branch 'main' of github.com:cmcgee1024/swiftly into proxies-design
cmcgee1024 Nov 8, 2024
35cb5c5
Merge branch 'main' of github.com:cmcgee1024/swiftly into proxies-design
cmcgee1024 Nov 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 79 additions & 21 deletions DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,28 @@ This document contains the high level design of swiftly. Not all features have b

## Index

- [Swiftly's purpose](#swiftlys-purpose)
- [Installation of swiftly](#installation-of-switly)
- [Linux](#linux)
- [Installation of swiftly](#installation-of-swiftly)
- [Installation of a Swift toolchain](#installation-of-a-swift-toolchain)
- [macOS](#macos)
- [Installation of swiftly](#installation-of-swiftly-1)
- [Installation of a Swift toolchain](#installation-of-a-swift-toolchain-1)
- [Interface](#interface)
- [Toolchain names and versions](#toolchain-names-and-versions)
- [Commands](#commands)
- [Toolchain selection](#toolchain-selection)
- [Detailed design](#detailed-design)
- [Implementation sketch - Core](#implementation-sketch---core)
- [Implementation sketch - Ubuntu 20.04](#implementation-sketch---ubuntu-2004)
- [Implementation sketch - macOS](#implementation-sketch---macos)
- [`config.json` schema](#configjson-schema)

## Swiftly's purpose

Swiftly helps you to easily install different Swift toolchains locally on your account. It also provides a single path where you can run the tools in the currently selected toolchain. Toolchain selection is [configurable](#toolchain-selection) using different mechanisms.

Note that swiftly is *not* a virtual toolchain in itself since there are cases where it cannot behave as a self-contained Swift toolchain. For example, there can be external dependencies on specific files, such as headers or libraries. There are far too many files that change between toolchain versions to be managed by swiftly. Also, for long-lived processes, there is no way to gracefully restart them without help from the client.

## Installation of swiftly

The installation of swiftly is divided into two phases: delivery and initialization. Delivery of the swiftly binary can be accomplished using different methods:
Expand Down Expand Up @@ -60,7 +67,7 @@ A simple setup for managing the toolchains could look like this:

The toolchains (i.e. the contents of a given Swift download tarball) would be contained in the toolchains directory, each named according to the major/minor/patch version. `config.json` would contain any required metadata (e.g. the latest Swift version, which toolchain is selected, etc.). If pulling in Foundation to use `JSONEncoder`/`JSONDecoder` (or some other JSON tool) would be a problem, we could also use something simpler.

The `~/.local/bin` directory would include symlinks pointing to the `bin` directory of the "active" toolchain, if any.
The `~/.local/bin` directory would include symlinks pointing to swiftly itself. When the proxies binaries are executed swiftly proxies them to the requested toolchain, or the default.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we ought to be using ~/.swiftly/bin for this. Swiftly doesn't own that directory and while it's fine to install the swiftly command itself there (assuming it's being installed per-user rather than system-wide), I think it's very bad form installing "proxies" in there.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've changed this to put the proxies and swiftly itself into its own managed directory by default, which is ~/.local/share/swiftly/bin. This matches what we do on macOS, except there we use a more typical macOS location ~/Library/Application Support/swiftly/bin.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

~/.local/bin was originally chosen according to the XDG Base Directories specification, which is something of a standard for directories like this. While swiftly doesn't own ~/.local/bin, it is the designated place to drop per-user executables according to that spec. Why would it be bad form to put our symlinks there?

https://specifications.freedesktop.org/basedir-spec/latest/
https://wiki.archlinux.org/title/XDG_Base_Directory

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The concern is that the user might have swift toolchain, and other items (clang, lld, lldb, etc.) existing in the ~/.local/bin directory and swiftly will attempt to manage those.

Copy link

@al45tair al45tair Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are really two reasons for this; the first is that, as @cmcgee1024 says, you might actually have Swift installed in ~/.local/bin, in which case the proxies would then overwrite your Swift executables, which would be wrong. The second is that when using tools like swiftly, there are situations where you want to bypass the proxies, and it's easiest to do that if they're in a separate bin directory all of their own (since whether you're using the proxies or not is dependent on whether that bin directory appears in your PATH).

There is precedent here; pyenv, rbenv et al also put their shims (which we seem to be calling proxies) into a separate bin directory for the same reasons.

Copy link

@al45tair al45tair Nov 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I've changed this to put the proxies and swiftly itself into its own managed directory by default

I think swiftly itself belongs in ~/.local/bin or /usr/local/bin or wherever the user installed it. It's just the proxies that should live elsewhere IMO. // @cmcgee1024

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@al45tair swiftly is aware of two locations at the moment. There is the swiftly home dir, where its configuration lives, and the swiftly bin dir where all of the binaries that it manages live. I'm hesitant to add another location to the list.

In the Linux case ~/.local/bin doesn't tend to be on the user's path, so swiftly finds itself adding it as part of augmenting the user's profile, being mindful of collisions with other packages that might attempt to do the same, or even the user themselves. There's no similar common CLT bin directory at a user level for macOS, so the swiftly bin directory is ~/Application Support/swiftly/bin as the default. There's a far less likelihood of a path collision where something else that adds swiftly's managed bin directory. I think it makes sense to keep all of the binaries that swiftly manages (potentially itself too), separate from a shared binary location on all platforms as the default. The user can customize the paths if they want in the installer to change this, but then they are taking on more responsibility for the possibility of collisions.

Swiftly itself can be installed by a system package manager where it will probably be installed in one of the usual locations like /usr/bin or /usr/local/bin. The latter is where swiftly is installed using the macOS pkg file. The package manager manages these paths and the user's profile likely includes them in their path without extra handling by swiftly. In this case the swiftly bin directory is just the proxies that swiftly manages since it can't manage its own binary.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong objection to that, I suppose, but it does mean that you can't use swiftly without having the proxies in your path if you've let swiftly install itself. At least, unless you make a symlink from ~/.local/bin or similar.


This is all very similar to how rustup does things, but I figure there's no need to reinvent the wheel here.

Expand All @@ -78,7 +85,7 @@ The contents of `~/Library/Application Support/swiftly` would look like this:
– env
```

Instead of downloading tarballs containing the toolchains and storing them directly in `~/.local/share/swiftly/toolchains`, we instead install Swift toolchains to `~/Library/Developer/Toolchains` via the `.pkg` files provided for download at swift.org. To select a toolchain for use, we update the symlinks at `~/Library/Application Support/swiftly/bin` to point to the desired toolchain in `~/Library/Developer/Toolchains`. In the env file, we’ll contain a line that looks like `export PATH="$HOME/Library/Application Support/swiftly:$PATH"`, so the version of swift being used will automatically always be from the active toolchain. `config.json` will contain version information about the selected toolchain as well as its actual location on disk.
Instead of downloading tarballs containing the toolchains and storing them directly in `~/.local/share/swiftly/toolchains`, we instead install Swift toolchains to `~/Library/Developer/Toolchains` via the `.pkg` files provided for download at swift.org. In the env file, we’ll add a line that looks like `export PATH="$HOME/Library/Application Support/swiftly:$PATH"`, so that swiftly can proxy toolchain commands to the requested toolchain, or default. `config.json` will contain version information about the selected toolchain as well as its actual location on disk.

This scheme works for ensuring the version of Swift used on the command line can be controlled, but it doesn’t affect the active toolchain used by Xcode, which uses its own mechanisms for that. Xcode, if it is installed, can find the toolchains installed by swiftly.

Expand Down Expand Up @@ -138,6 +145,14 @@ Installing a specific snapshot from a swift version development branch

`swiftly install 5.5-snapshot-2022-1-28`

##### Installing the version from the `.swift-version` file

A package could have a ".swift-version" file that specifies the recommended toolchain version. A swiftly install with no version will search for a version file and install that version.

`swiftly install`

If no ".swift-version" file can be found then the installation fails indicating that it couldn't fine the file.

#### uninstall

Uninstalling versions of Swift should be in a similar form to install. Uninstalling a toolchain that is currently “in use” (see the “use” command section below) will cause swiftly to use the latest Swift release toolchain that is installed. If none are, the latest snapshot will be used. If no snapshots are installed either, then a message will be printed indicating that all Swift versions are uninstalled.
Expand Down Expand Up @@ -178,7 +193,7 @@ To list all the versions of swift installed on your system

#### use

“Using” a toolchain sets it as the active toolchain, meaning it will be the one found via $PATH and invoked via `swift` commands executed in the shell. Only a single toolchain can be used at a given time. Using a toolchain doesn’t uninstall anything; it only updates symlinks so that the requested toolchain can be found by the shell.
“Using” a toolchain sets it as the default toolchain, meaning it will be the default one that is used when running toolchain commands from the shell. Only a single toolchain can be the default at a given time and location. Using a toolchain doesn’t uninstall anything; it only updates the configuration.

To use the toolchain associated with the most up-to-date Swift version, the “latest” version can be specified:

Expand Down Expand Up @@ -208,6 +223,10 @@ To use the latest installed main snapshot, leave off the date:

`swiftly use main-snapshot`

The use subcommand also supports `.swift-version` files. If a ".swift-version" file is present in the current working directory, or an ancestory directory, then swiftly will update that file with the new version to use. This can be a useful feature for a team to share and align on toolchain versions with git. As a special case, if swiftly could not find a version file, but it could find a Package.swift file it will create a new version file for you in the package and set that to the requested toolchain version.

Note: The `.swift-version` file mechanisms can be overridden using the `--global-default` flag so that your swiftly installation's default toolchain can be set explicitly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rather the default is the other way. ie use edits global settings and you can change local settings with a --local flag.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that there are advantage of having this local as the default. It encourages the sharing of the toolchain revision that the team is working with through discovery of this feature of swiftly. Also, this helps to tie into one of the values of using swiftly itself, which is how easily and flexibly you can switch toolchains.

In terms of precedence, git defaults to local over global for its configuration.

I'm curious what you think are the pitfalls of this approach.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I realised as I was writing this, there is previous art that defaults to local. It is more a preference on my behalf and how I'd use swiftly

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pyenv and rbenv call this command local, global or shell depending on whether you're setting the Python/Ruby version for a directory, globally on the machine (for your user), or just in the current shell. The shell setting overrides the local setting, which overrides the global setting.


#### update

Update replaces a given toolchain with a later version of that toolchain. For a stable release, this means updating to a later patch version. For snapshots, this means updating to the most recently available snapshot.
Expand Down Expand Up @@ -266,6 +285,58 @@ This command checks to see if there are new versions of `swiftly` itself and upg

`swiftly self-update`

### Toolchain selection

Swiftly will create a set of symbolic links in its SWIFTLY_BIN_DIR during installation that point to the swiftly binary itself for each of the common toolchain commands, such as swift, swiftc, clang, etc. This mechanism will allows swiftly to proxy those command invocations to a selected toolchain at the time of invocation. A toolchain can be selected in these ways in order of precedence:

* The presence of a .swift-version file in the current working directory, or ancestor directory, with the required toolchain version
* The swiftly default (in-use) toolchain set in the swftly config.json by `swiftly install` or `swiftly use` commands

If swiftly cannot find an installed toolchain that matches the selection then it fails with an error and instructions how to use `swiftly install` to satisfy the selection next time.

#### Resolve selected toolchain

For cases where the physical toolchain must be located, such as references specific header files, or shared libraries that are not proxied by swiftly there is a method to resolve the currently selected toolchain to its physical location using `swiftly use`.

```
swiftly use --print-location
```

This command will provide the full path to the directory where the selected toolchain is installed to standard output if such a toolchain exists. An external tool can directly navigate to the resources that it requires. For external tools that manage long-lived processes from the toolchain, such as the language server, and lldb, this command can be used in a poll to detect cases where the processes should be restarted.

#### Run with a selected toolchain

There are cases where you might want to run an arbitrary command using a selected toolchain. An example could be that you want to build something with CMake.

```
# CMake
swiftly run cmake -G ninja
swiftly run ninja build

# Autoconf
swiftly run ./configure
swiftly run make
```

Swiftly adjusts certain environment variables, such as prefixing the PATH to the selected toolchain directory, and setting the CC and CXX variables to the locations of clang and clang++ in those toolchains so that the build tools use them. If you want to explicitly specify a toolchain for the command you can do that with a selector notation like this:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I don't think manipulating PATH is a good idea. Swiftly should have its proxy bin directory added to the path when it is installed, but should refrain from messing with PATH thereafter. Similarly for CC and CXX.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed the setting of CC and CXX variables, opting instead to have the user provide those if they need them, copied verbatim along with the rest of their environment. The only environment changes is to the PATH prepending the current toolchain, and leaving the rest of it untouched as the user had set previously.

Overriding the proxies in this case has the benefit of keeping this as a workaround for proxy performance issues. Also, this approach has pyenv as a precedent, which is documented to be doing the exact same thing. https://github.com/pyenv/pyenv/blob/master/COMMANDS.md#pyenv-exec


```
swiftly run swift build +5.10.1 # Runs swift build with the 5.10.1 toolchain
```

A few notes about the '+' prefix. First, if a literal '+' prefix should be sent directly to the tool as an argument then it is escaped by doubling it with '++'. An argument with only '++' is ignored entirely, and any additional arguments are sent directly to the command without any further inspection of their prefixes. This is analogous to the special '--' token that certain argument parsers accept so that they don't interpret anything following that token as command flags or options.

If the selected toolchain is not installed then swiftly will exit with a message indicating that you need to run `swiftly install x.y.z` to install it.

```
# Use the latest main snapshot toolchain and run 'swift build' to build the package with it.
swiftly run swift build +main-snapshot

# Generate makefiles with the latest released Swift toolchain
swiftly run +latest cmake -G "Unix Makefile"
swiftly run +latest make
```

## Detailed Design

Swiftly itself will be a SPM project consisting of several executable products, one per supported platform, and all of these will share the core module that handles argument parsing, printing help information, and dispatching commands. Each platform’s executable will be built to statically link the stdlib so that they can be run without having installed Swift first.
Expand Down Expand Up @@ -457,15 +528,7 @@ https://download.swift.org/swift-5.5.1-release/ubuntu1604/swift-5.5.1-RELEASE/sw
$ tar -xf <URL> --directory ~/.local/share/swiftly/toolchains
```

It also updates `config.json` to include this toolchain as the latest for the provided version. If installing a new patch release toolchain, the now-outdated one can be deleted (e.g. `5.5.0` can be deleted when `5.5.1` is installed).

Finally, the use implementation executes the following to update the link:

```
$ ln -s ~/.local/share/swiftly/toolchains/<toolchain>/usr/bin/swift ~/.local/bin/swift
```

It also updates `config.json` to include this version as the currently selected one.
It also updates `config.json` to include this toolchain as the latest for the provided version. If installing a new patch release toolchain, the now-outdated one can be deleted (e.g. `5.5.0` can be deleted when `5.5.1` is installed). The `config.json` is updated to include this version as the currently selected (default) one.

### Implementation Sketch - macOS

Expand All @@ -481,18 +544,13 @@ https://download.swift.org/swift-<version>-RELEASE/xcode/swift-<version>-RELEASE

`config.json` is then updated to include this toolchain as the latest for the provided version.

Finally, the use implementation executes the following to update the link:

```
$ ln -s ~/Library/Developer/Toolchains/<toolchain name> ~/.swiftly/active-toolchain
```

It also updates `config.json` to include this version as the currently selected one.
It also updates `config.json` to include this version as the currently selected (default) one.

### `config.json` Schema

```
{
"version": "<version of swiftly that created/updated this config.json file>",
"platform": {
"namePretty": <OS name pretty printed>,
"fullName": <OS name used in toolchain file name>,
Expand Down
1 change: 1 addition & 0 deletions Documentation/SwiftlyDocs.docc/SwiftlyDocs.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Install and manage your Swift programming language toolchains.
### HOWTOS

- <doc:install-toolchains>
- <doc:use-toolchains>
- <doc:uninstall-toolchains>
- <doc:update-toolchain>
- <doc:automated-install>
Expand Down
23 changes: 20 additions & 3 deletions Documentation/SwiftlyDocs.docc/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,11 @@ $ swift --version

Swift version 5.8.1 (swift-5.8.1-RELEASE)
Target: x86_64-unknown-linux-gnu

$ swift build # Build with the latest (5.8.1) toolchain
```

Or, you can install (and use) a swift release:
You can install (and use) another release toolchain:

```
$ swiftly install --use 5.7
Expand All @@ -38,12 +40,27 @@ $ swift --version

Swift version 5.7.2 (swift-5.7.2-RELEASE)
Target: x86_64-unknown-linux-gnu

$ swift build # Build with the 5.7.2 toolchain
```

There's also an option to install the latest snapshot release and get access to the latest features:
Quickly test your package with the latest nightly snapshot to prepare for the next release:

```
$ swiftly install main-snapshot
$ swiftly run swift test +main-snapshot # Run "swift test" with the main-snapshot toolchain
$ swift build # Continue to build with my usual toolchain
```

> Note: This last example just installed the toolchain. You can run "swiftly use" to switch to it and other installed toolchahins when you're ready.
Uninstall this toolchain after you're finished with it:

```
$ swiftly uninstall main-snapshot
```

# See Also:

- [Install Toolchains](install-toolchains)
- [Using Toolchains](use-toolchains)
- [Uninstall Toolchains](uninstall-toolchains)
- [Swiftly CLI Reference](swiftly-cli-reference)
87 changes: 81 additions & 6 deletions Documentation/SwiftlyDocs.docc/swiftly-cli-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ swiftly [--version] [--help]
Install a new toolchain.

```
swiftly install <version> [--use] [--verify] [--post-install-file=<post-install-file>] [--version] [--help]
swiftly install [<version>] [--use] [--verify|no-verify] [--post-install-file=<post-install-file>] [--version] [--help]
```

**version:**
Expand Down Expand Up @@ -53,13 +53,17 @@ Likewise, the latest snapshot associated with a given development branch can be
$ swiftly install 5.7-snapshot
$ swiftly install main-snapshot

Install whatever toolchain is currently selected, such as the the one in the .swift-version file:

$ swiftly install


**--use:**

*Mark the newly installed toolchain as in-use.*


**--verify:**
**--verify|no-verify:**

*Verify the toolchain's PGP signature before proceeding with installation.*

Expand Down Expand Up @@ -131,12 +135,27 @@ Note that listing available snapshots before the latest release (major and minor

## use

Set the active toolchain. If no toolchain is provided, print the currently in-use toolchain, if any.
Set the in-use toolchain. If no toolchain is provided, print the currently in-use toolchain, if any.

```
swiftly use [<toolchain>] [--version] [--help]
swiftly use [--print-location] [--global-default] [--assume-yes] [<toolchain>] [--version] [--help]
```

**--print-location:**

*Print the location of the in-use toolchain. This is valid only when there is no toolchain argument.*


**--global-default:**

*Use the global default, ignoring any .swift-version files.*


**--assume-yes:**

*Disable confirmation prompts by assuming 'yes'*


**toolchain:**

*The toolchain to use.*
Expand Down Expand Up @@ -285,7 +304,7 @@ The installed snapshots for a given devlopment branch can be listed by specifyin
Update an installed toolchain to a newer version.

```
swiftly update [<toolchain>] [--assume-yes] [--verify] [--post-install-file=<post-install-file>] [--version] [--help]
swiftly update [<toolchain>] [--assume-yes] [--verify|no-verify] [--post-install-file=<post-install-file>] [--version] [--help]
```

**toolchain:**
Expand Down Expand Up @@ -331,7 +350,7 @@ A specific snapshot toolchain can be updated by including the date:
*Disable confirmation prompts by assuming 'yes'*


**--verify:**
**--verify|no-verify:**

*Verify the toolchain's PGP signature before proceeding with installation.*

Expand Down Expand Up @@ -416,3 +435,59 @@ swiftly self-update [--version] [--help]



## run

Run a command while proxying to the selected toolchain commands.

```
swiftly run <command>... [--version] [--help]
```

**command:**

*Run a command while proxying to the selected toolchain commands.*


Run a command with a selected toolchain. The toolchain commands become the default in the system path.

You can run one of the usual toolchain commands directly:

$ swiftly run swift build

Or you can run another program (or script) that runs one or more toolchain commands:

$ swiftly run make # Builds targets using clang/swiftc
$ swiftly run ./build-things.sh # Script invokes 'swift build' to create certain product binaries

Toolchain selection is determined by swift version files `.swift-version`, with a default global as the fallback. See the `swiftly use` command for more details.

You can also override the selection mechanisms temporarily for the duration of the command using a special syntax. An argument prefixed with a '+' will be treated as the selector.

$ swiftly run swift build +latest
$ swiftly run swift build +5.10.1

The first command builds the swift package with the latest toolchain and the second selects the 5.10.1 toolchain. Note that if these aren't installed then run will fail with an error message. You can pre-install the toolchain using `swiftly install <toolchain>` to ensure success.

If the command that you are running needs the arguments with the '+' prefixes then you can escape it by doubling the '++'.

$ swiftly run ./myscript.sh ++abcde

The script will receive the argument as '+abcde'. If there are multiple arguments with the '+' prefix that should be escaped you can disable the selection using a '++' argument, which turns off any selector argument processing for subsequent arguments. This is anologous to the '--' that turns off flag and option processing for subsequent arguments in many argument parsers.

$ swiftly run ./myscript.sh ++ +abcde +xyz

The script will receive the argument '+abcde' followed by '+xyz'.


**--version:**

*Show the version.*


**--help:**

*Show help information.*




Loading