Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SE-0301] Package Editor Commands Implementation #3034

Closed
wants to merge 1 commit into from

Conversation

owenv
Copy link
Contributor

@owenv owenv commented Nov 8, 2020

This PR:

  • Updates the SPMPackageEditor library so it compiles against ToT SwiftSyntax
  • Removes spm-manifest-tool, instead conditionally compiling package editor functionality into the Commands module
  • Refactors the library a bit to fix some bugs and make it more extensible
  • adds support for adding products

Possible future directions (not in this PR):

  • deleting products/targets/dependencies
  • a swift package upgrade command that could update requirement specs
  • Use the PackageSyntax infra to emit manifest-related diagnostics with source locations

@owenv
Copy link
Contributor Author

owenv commented Nov 8, 2020

@swift-ci please smoke test

@owenv owenv force-pushed the package-editor-modernization branch from 34877c5 to 60d418a Compare November 8, 2020 03:23
@owenv
Copy link
Contributor Author

owenv commented Nov 8, 2020

@swift-ci please smoke test

@owenv
Copy link
Contributor Author

owenv commented Nov 8, 2020

Hmm, I'm seeing this failure when the library tries to load a manifest:
invalidManifestFormat("/var/folders/_8/79jmzf2142z2xydc_01btlx00000gn/T/TemporaryFile.Br55su.swift:2:8: error: no such module \'PackageDescription\'\nimport PackageDescription\n ^", diagnosticFile: nil)

Other than that, everything seems to work as expected on CI

Edit: I think I managed to fix it by passing a UserToolchain into PackageEditor instead of trying to create one manually

@owenv owenv force-pushed the package-editor-modernization branch from 60d418a to 5b26311 Compare November 8, 2020 05:42
@owenv
Copy link
Contributor Author

owenv commented Nov 8, 2020

@swift-ci please smoke test

@owenv
Copy link
Contributor Author

owenv commented Nov 8, 2020

Looks like the newly reenabled tests ran and passed in the most recent run (but don't run in the self-hosted CI, as expected)

@abertelrud
Copy link
Contributor

Thanks for updating these! Right, passing in a toolchain seems like the right approach, as long as this is within SwiftPM. It would make sense to me for this to be in a separate package, except that (I believe) the intent was to make this functionality part of the core SwiftPM commands.

Copy link
Contributor

@abertelrud abertelrud left a comment

Choose a reason for hiding this comment

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

Looks good to me but I am not familiar with code, so I'd want @aciidb0mb3r to weigh in also.

@owenv
Copy link
Contributor Author

owenv commented Nov 15, 2020

I ended up finding a couple more bugs, so I merged the changes from #3035 into this PR to consolidate the package editing changes

@owenv owenv force-pushed the package-editor-modernization branch from 81ff1f7 to 569ad0d Compare November 15, 2020 19:35
@owenv
Copy link
Contributor Author

owenv commented Nov 15, 2020

@swift-ci please smoke test

1 similar comment
@owenv
Copy link
Contributor Author

owenv commented Nov 18, 2020

@swift-ci please smoke test

@owenv owenv force-pushed the package-editor-modernization branch from 7262b4c to 5182496 Compare November 19, 2020 05:10
@owenv
Copy link
Contributor Author

owenv commented Nov 19, 2020

@swift-ci please smoke test

Package.swift Outdated
// Because SwiftSyntax is closely tied to the compiler, only attempt to build
// the package editor library if we're in a build-script environment and can
// assume we're using a just-built compiler and SwiftSyntax library.
if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] != nil {
Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps we should have some additional control over whether to require swift-syntax and a matching compiler. SWIFTCI_USE_LOCAL_DEPS is the same environment variable that controls whether to fetch the other dependencies or expect to find them, and it would be good to have independent control over whether to try to build the package editor.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

👍 I updated this to use SPM_ENABLE_PACKAGE_EDITOR instead, and the bootstrap script passes that for the stage 2 build. We now also define ENABLE_PACKAGE_EDITOR when building the Commands module, and I'm conditionally compiling the new subcommands there instead of breaking them out into a separate executable swift-package would need to forward to. This setup should keep the build relatively simple as long as we're ok not supporting this functionality in stage 1 CMake builds, which IMO is fine (and then we don't need to setup CMake for SwiftSyntax either).

@owenv
Copy link
Contributor Author

owenv commented Nov 20, 2020

@swift-ci please smoke test

@owenv owenv changed the title Update SPMPackageEditor library to work with current toolchains [PackageEditor] Mechanical editing functionality for package manifests Nov 21, 2020
@owenv
Copy link
Contributor Author

owenv commented Nov 24, 2020

@swift-ci please smoke test

@owenv
Copy link
Contributor Author

owenv commented Nov 27, 2020

@swift-ci please test

@owenv
Copy link
Contributor Author

owenv commented Nov 27, 2020

@swift-ci please build toolchain macOS

@owenv
Copy link
Contributor Author

owenv commented Nov 27, 2020

@swift-ci please build toolchain

@owenv
Copy link
Contributor Author

owenv commented Nov 27, 2020

All of the functionality in this PR should be complete now, but the scope of the changes got a little out of hand 😭. I'm going to work on finishing the SE proposal and then I'll see if there's a good way to break this down into pieces that are easier to review.

@abertelrud
Copy link
Contributor

Thanks a lot for your additional investigations here!

AFAICT this won't work currently because Xcode toolchains only include lib_InternalSwiftSyntaxParser.dylib and not libSwiftSyntax.dylib. Do you know if the preset used to build Xcode toolchains is derived from one of the ones in build_presets.ini, or is that configured outside the open source project?

I don't actually know at all how that works — @shahmishal would probably know, but I don't know how much information is.

As far as including libSwiftSyntax.dylib in the Xcode toolchain, that might be something to explore, since there's a precedent for that with llbuild. But my impression was that it's lib_InternalSwiftSyntaxParser.dylib that needs to match the compiler, and that SwiftSyntax could generally be built from source, although I'm sure there are problems if they are too far apart.

I suppose it's no different than relying on an llbuild that's in the Xcode toolchain, in that its API sometimes changes too.

I guess my main concern with only building the mechanical editing support when SwiftSyntax is present is that it's very easy to break it.

It's an interesting idea to use executables but I agree that it's probably not the way to go in the long run here. I will look into what can be done to have a libSwiftSyntax.dylib in the toolchain.

@owenv
Copy link
Contributor Author

owenv commented Jun 12, 2021

@swift-ci please smoke test

@owenv
Copy link
Contributor Author

owenv commented Jun 12, 2021

@swift-ci please smoke test macos

@owenv
Copy link
Contributor Author

owenv commented Jun 12, 2021

the macOS self-hosted bot has an unrelated failure, but everything else appears to be passing.

@abertelrud The latest push reworks the build again, I'd be interested in hearing your thoughts on the approach - now PackageSyntax is always built if the compiler version is >=5.5. This works around the parser library ABI break between 5.4 and 5.5 that was previously causing issues when developing locally. Also, a local checkout of SwiftSyntax is no longer required unless SWIFTCI_USE_LOCAL_DEPS is set. Now:

  • When building locally with a 5.4 or earlier compiler, PackageSyntax is skipped
  • When building locally with a 5.5 or later compiler (this requires Xcode 13 beta since Xcode ignores custom toolchains when compiling a manifest):
    • If the parser library in the toolchain is compatible, PackageSyntax will compile and pass tests
    • If the parser library in the toolchain is incompatible, PackageSyntax will still compile and link, but its tests will fail
  • When bootstrapping in CI, PackageSyntax will compile as part of the second-stage build and pass tests
  • When building a toolchain, SwiftSyntax will be statically linked, and will dynamically link against the lib_InternalSwiftSyntaxParser installed in the toolchain. This increases binary size a bit, but it should work with Xcode's layout.

@owenv
Copy link
Contributor Author

owenv commented Jun 14, 2021

@swift-ci please smoke test macOS

// should compile with any 5.5 compiler, it will only be functional when built
// with a toolchain that has a compatible parser library.
if ProcessInfo.processInfo.environment["SWIFTCI_USE_LOCAL_DEPS"] == nil {
package.dependencies += [.package(url: "https://github.com/apple/swift-syntax.git", .branch(relatedDependenciesBranch))]
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be pinned to a particular release of SwiftSyntax rather than the branch? The toolchain build will use the branch, but it will presumably also set SWIFTCI_USE_LOCAL_DEPS.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think we should use the branch here - it ensures we only ever need to support one version of the SwiftSyntax API, which changes pretty often

Copy link
Contributor

Choose a reason for hiding this comment

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

But if it changes often, doesn't that mean that changes to the branch could suddenly break SwiftPM? i.e. would it not make sense to specify a semantic version and then when necessary update SwiftPM to use the newer version at the same time as adopting any necessary changes, in a single PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe SwiftSyntax CI builds SwiftPM so I think we'd at least catch breaking changes pre-merge. The main problem I'm running into is that SwiftPM always needs to build against top-of-tree SwiftSyntax for the feature to work in nightly toolchains. We could also support a specific tag for local development, but it wouldn't be guaranteed to compile 100% of the time

@abertelrud
Copy link
Contributor

the macOS self-hosted bot has an unrelated failure, but everything else appears to be passing.

@abertelrud The latest push reworks the build again, I'd be interested in hearing your thoughts on the approach - now PackageSyntax is always built if the compiler version is >=5.5. This works around the parser library ABI break between 5.4 and 5.5 that was previously causing issues when developing locally. Also, a local checkout of SwiftSyntax is no longer required unless SWIFTCI_USE_LOCAL_DEPS is set. Now:

  • When building locally with a 5.4 or earlier compiler, PackageSyntax is skipped

  • When building locally with a 5.5 or later compiler (this requires Xcode 13 beta since Xcode ignores custom toolchains when compiling a manifest):

    • If the parser library in the toolchain is compatible, PackageSyntax will compile and pass tests
    • If the parser library in the toolchain is incompatible, PackageSyntax will still compile and link, but its tests will fail
  • When bootstrapping in CI, PackageSyntax will compile as part of the second-stage build and pass tests

  • When building a toolchain, SwiftSyntax will be statically linked, and will dynamically link against the lib_InternalSwiftSyntaxParser installed in the toolchain. This increases binary size a bit, but it should work with Xcode's layout.

Thanks a lot, @owenv! Especially for taking into account the changes that will be needed to work with Xcode; that's what seems to me to be the trickiest aspect here.

Skipping PackageSyntax with Swift 5.4 makes sense to me, though hopefully we won't have to do that moving forward. Do you think we'll be in that situation whenever there are changes in the parser library (in other words, are ABI breaks like the one you mentioned a regular thing?).

Statically linking SwiftSyntax also makes sense — I think it would still be a good separate improvement for SwiftPM to allow binary targets to contain whatever libraries are needed, but that can be a future improvement.

@owenv
Copy link
Contributor Author

owenv commented Jun 15, 2021

Skipping PackageSyntax with Swift 5.4 makes sense to me, though hopefully we won't have to do that moving forward. Do you think we'll be in that situation whenever there are changes in the parser library (in other words, are ABI breaks like the one you mentioned a regular thing?).

@abertelrud If there's another break, it'll probably require a similar workaround. However, the parser library rarely has breaking changes even if it doesn't guarantee stability. The one in 5.5 is the first one since SwiftSyntax was open-sourced a couple years back.

@abertelrud
Copy link
Contributor

(Reengaging here, so we can try to get towards landing this — that you for your patience @owenv!)

If the parser library in the toolchain is incompatible, PackageSyntax will still compile and link, but its tests will fail

This is just referring to the tests for PackageSyntax itself, right, which don't normally run as part of building SwiftPM? Or would this also affect SwiftPM's own tests?

@owenv
Copy link
Contributor Author

owenv commented Jun 22, 2021

If the parser library in the toolchain is incompatible, PackageSyntax will still compile and link, but its tests will fail
This is just referring to the tests for PackageSyntax itself, right, which don't normally run as part of building SwiftPM? Or would this also affect SwiftPM's own tests?

This will affect the SwiftPM tests, but only when building with an incompatible swift >= 5.5. I may be able to add a public SwiftSyntax API so that we can skip these tests in that scenario.

Unfortunately, I'm running into another problem with the local development now. Building with the SwiftPM CLI works fine, but Xcode 13 must be linking differently because swift-package crashes on launch with Library not loaded: @rpath/lib_InternalSwiftSyntaxParser.dylib. I haven't figured out what changed from Xcode 12 yet but I'll see if I can reduce it and report a bug.

@abertelrud
Copy link
Contributor

If the parser library in the toolchain is incompatible, PackageSyntax will still compile and link, but its tests will fail
This is just referring to the tests for PackageSyntax itself, right, which don't normally run as part of building SwiftPM? Or would this also affect SwiftPM's own tests?

This will affect the SwiftPM tests, but only when building with an incompatible swift >= 5.5. I may be able to add a public SwiftSyntax API so that we can skip these tests in that scenario.

Unfortunately, I'm running into another problem with the local development now. Building with the SwiftPM CLI works fine, but Xcode 13 must be linking differently because swift-package crashes on launch with Library not loaded: @rpath/lib_InternalSwiftSyntaxParser.dylib. I haven't figured out what changed from Xcode 12 yet but I'll see if I can reduce it and report a bug.

Thank you — if you add the JIRA here I can take a look as well. I am not aware of any changes, but also I haven't worked with SwiftSyntax before.

I am keen to help get this landed — it's just the ergonomics and robustness of working with this new dependency that need to be worked out.

@owenv
Copy link
Contributor Author

owenv commented Jun 26, 2021

It turns out that the problem I'm running into is that the SwiftPM 5.5 CLI includes /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx as an rpath but Xcode 13 doesn't when building packages, so lib_InternalSwiftSyntaxParser.dylib can't be loaded at runtime. I think it might have been an intentional change but I'm not really sure how to work around it.

@abertelrud
Copy link
Contributor

It turns out that the problem I'm running into is that the SwiftPM 5.5 CLI includes /Applications/Xcode-beta.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx as an rpath but Xcode 13 doesn't when building packages, so lib_InternalSwiftSyntaxParser.dylib can't be loaded at runtime. I think it might have been an intentional change but I'm not really sure how to work around it.

Thanks @owenv that's news to me — I will look into what that's all about and see if I can come up with something (I know this PR has taken forever to land — apologies for that, there many things going on).

@abertelrud
Copy link
Contributor

I've been looking into this and I'm not sure that the change to no longer include that rpath was intentional. I'm looking to see what the options are for either a workaround or a fix.

This commit adds a new module, PackageSyntax, which supports making mechanical
edits to Package.swift manifests. It also exposes a CLI interface for this functionality

[PackageSyntax] Adapt to changes in identity and package plugin APIs

[PackageSyntax] Don;t include name argument in package dependency descriptions on 5.5+

[PackageSyntax] Improve tools version coverage of PackageEditor end to end tests

[PackageSyntax] Adapt to more identity API changes

[PackageSyntax] Use new branch and revision convenience methods on 5.5+

[PackageSyntax] Run the bootstrap script without PackageSyntax if SwiftSyntax isn't checked out or --skip-package-syntax is passed

Revert "[PackageSyntax] Run the bootstrap script without PackageSyntax if SwiftSyntax isn't checked out or --skip-package-syntax is passed"

This reverts commit 6f0a920.
@owenv owenv force-pushed the package-editor-modernization branch from 0464ef6 to 234303e Compare July 25, 2021 17:44
@owenv
Copy link
Contributor Author

owenv commented Jul 25, 2021

@swift-ci smoke test

@owenv
Copy link
Contributor Author

owenv commented Jul 31, 2021

I've decided to move this over to https://github.com/owenv/swift-package-editor as a standalone package since maintaining it out-of-tree for so long just ended up being too much work. I'm willing to transfer ownership of that repo if there's still interest in including this feature in the toolchain - otherwise I think I'll just ship a separate installer. Thanks everyone for your help with this! Sorry things didn't work out as expected

@owenv owenv closed this Jul 31, 2021
abertelrud added a commit to abertelrud/swift-package-manager that referenced this pull request Aug 16, 2021
… it. The way in which this is done is based on apple#3034 but it's possible we'll need to tweak it.  It's not great to only get the dependency in 5.5 or later but there might not be much to do about that if the compiler ABI changed.
abertelrud added a commit to abertelrud/swift-package-manager that referenced this pull request Aug 16, 2021
… need it. The way in which this is done is based on apple#3034 but it's possible we'll need to tweak it.  It's not great to only get the dependency in 5.5 or later but there might not be much to do about that if the compiler ABI changed.
abertelrud added a commit to abertelrud/swift-package-manager that referenced this pull request Aug 18, 2021
… need it. The way in which this is done is based on apple#3034 but it's possible we'll need to tweak it.  It's not great to only get the dependency in 5.5 or later but there might not be much to do about that if the compiler ABI changed.
abertelrud added a commit to abertelrud/swift-package-manager that referenced this pull request Sep 6, 2021
… need it. The way in which this is done is based on apple#3034 but it's possible we'll need to tweak it.  It's not great to only get the dependency in 5.5 or later but there might not be much to do about that if the compiler ABI changed.
@MaxDesiatov
Copy link
Member

Since the proposal has been accepted, is that separate repository a preferred implementation of it? I wonder if proposal status should be updated if there are no immediate plans to bring that feature into the toolchain.

@neonichu
Copy link
Member

We have #5802

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants