swiftly icon indicating copy to clipboard operation
swiftly copied to clipboard

Swiftly installed with Homebrew freezes VS Code Swift plugin

Open SimplyDanny opened this issue 1 month ago • 2 comments

Swiftly installed with Homebrew doesn't link its binary into SWIFTLY_BIN_DIR. If we just call swiftly from the command line, it refers to $(brew --prefix)/bin/swiftly which is actually a symlink to $(brew --prefix)/Cellar/swiftly/1.1.0/bin/swiftly.

The check validateLinked(ctx), which is called first in almost all Swiftly commands, is happy if swiftly is either a symlink or exists in SWIFTLY_BIN_DIR. So just calling swiftly from the command-line is usually fine.

However, the combination of Swiftly (1.1.0) and the Swift extension for VS Code is currently problematic, in that VS Code is more or less blocked. Basic interactions don't work anymore, because it's busy with "Activating Swift for Visual Studio Code ...". The reason is an endless loop caused by the following circumstances:

Internally, the extension first checks where swift is and finds it at SWIFTLY_BIN_DIR/swift. It then resolves this symbolic link directly to the final real path $(brew --prefix)/Cellar/swiftly/1.1.0/bin/swiftly. Since this is not a symlink, validateLinked(ctx) requires it to effectively live in SWIFTLY_BIN_DIR. This is clearly not the case.

The result is the message "Swiftly is currently unlinked ..." being reported. The VS Code extension interprets it as a path and tries to traverse all its parents which never comes to an end (since this is not a path at all).

I was about to fix this, but got unsure on what the right fix would actually be. I think, it's something Swiftly needs to handle correctly. The question is how to recognize when it's okay that swiftly does not live in SWIFTLY_BIN_DIR. Only excluding symlinks is obviously not enough. Should absolute paths starting with brew --prefix be accepted as well? Absolute paths in general? Why is it so important to run validateLinked(ctx) every time in the first place?

SimplyDanny avatar Nov 03 '25 21:11 SimplyDanny

Should absolute paths starting with brew --prefix be accepted as well? Absolute paths in general? Why is it so important to run validateLinked(ctx) every time in the first place?

Thanks for verifying in other formats such as the home-brew formula. I'll try and answer some of these.

The validate linked check is there to support the new link/unlink subcommands that remove/add the symlinks to the toolchain commands so that the system versions of the tools can be activated/deactivated. When swiftly is unlinked it may not be obvious to the user that they are now running with the system managed toolchain commands, so this was attempting to remind them where possible.

The validateLinked ultimately calls findSwiftlyBin, which should take into consideration how the swiftly executable was invoked to find what swiftly is the correct one in this context. I think that it would handle the case of an absolute path /some/path/to/swiftly as well as swiftly being run from the PATH where it inspects each path in order to see if that's where swiftly is being run. It's this path that the proxies should be linked, otherwise the validation check fails.

The message that is emitted should really go to stderr, and not stdout though so that tools like VSCode don't try to interpret them as real output. I expect that this fix is needed on the swiftly side to stop the infinite looping.

It is strange that this message is being printed within the VSCode environment, and not at the command-prompt. Perhaps there's a different PATH environment that leads to a different swiftly location.

cmcgee1024 avatar Nov 07 '25 16:11 cmcgee1024

It is strange that this message is being printed within the VSCode environment, and not at the command-prompt. Perhaps there's a different PATH environment that leads to a different swiftly location.

The VS Code extension uses an absolute path (all symlinks resolved). The isLinked check fails, because https://github.com/swiftlang/swiftly/blob/b804e6da2f7cfe32cb364ac929bbfd194bc2d9a8/Sources/Swiftly/Unlink.swift#L96 never becomes true, as links in SWIFTLTY_BIN_DIR all link to yet another symlink inside of the Homebrew installation at $(brew --prefix)/bin/swiftly. So they would never match the absolute path.

From the command-prompt, we just call swiftly which effectively is $(brew --prefix)/bin/swiftly and so the check works. If we called the absolute path ourselves, we'd see the same warning as in the VS Code environment.

By streaming the warning to stderr (as you did) it should at least not block VS Code any longer. To avoid the warning completely, https://github.com/swiftlang/swiftly/blob/b804e6da2f7cfe32cb364ac929bbfd194bc2d9a8/Sources/Swiftly/Unlink.swift#L96 should perform another jump if potentialProxyPath is yet another link. It could even do so as long as linkTarget is a link which doesn't match proxyTo.

SimplyDanny avatar Nov 08 '25 11:11 SimplyDanny