-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Finish SE‐0226 (Ignore Unused Products) #2749
The head ref may contain hidden characters: "se\u20100226"
Conversation
😱😱😱 |
This is a wonderful contribution, Jeremy! |
Actually, I just realized this was completely broken already in Swift 5.2. The 5.2 release included the first half of the SE‐0226 work, and that meant that such an implicit dependency was being skipped during resolution. With no product to point at either, a legacy system package was impossible to reference from a manifest with tools version 5.2. However, you could still get at it indirectly if you inserted a proxy package in between that had a 5.1 tools version or earlier. Since the test was grandfathered in and its client’s manifest was super old, this is how the test continued to pass without anyone noticing the breakage. Were there any bugs reported for Swift 5.2 complaining that it didn’t work? Or had everyone dealt with the deprecation warnings (since 4.2) by then so that no one was using system packages anymore? I ask because an alternative to the fix I’ve implemented here would be to just use the opportunity to turn the deprecation into an obsoletion and forego the extra complexity. 5.2 already effectively obsoleted it anyway, even if by accident. Let me know which route you’d rather take. |
First things first: amazing work! This was a big task and it’s great to know that SE-0226 will be completed very soon 😊 To answer the different points:
But it’s true that perhaps we ought to design a way of depending on executable dependency products.
|
I included a brief explanation in the fix‐me directly in source.
This is why I think a new manifest entry for “tools needed during development, but not needed for any target” could be useful. It would remove the need to hook them up to some arbitrary target just to avoid these two inconveniences. But I think that can be done as a separate evolution proposal later on. |
Thanks for the details.
Perhaps it could be designed with the external build script functionality.
… On 15 May 2020, at 00:25, Jeremy David Giesbrecht ***@***.***> wrote:
Why do you say that solution has some minor drawbacks?
I included a brief explanation in the fix‐me directly in source <https://github.com/apple/swift-package-manager/blob/4f434c0f5405e45033c36bcfb389c798ac0dd004/Sources/PackageGraph/PackageGraphRoot.swift#L108-L119>.
It means swift run foo, swift run bar and swift build all have potentially different dependency graphs (because the executables might need extra packages). If you go back and forth, it may have to re‐resolve each time. Your pins could jump back and forth.
Workaround: You can unify the dependency set by creating an otherwise empty internal target which explicitly depends on the executables you care about. Or you can add them as explicit dependencies of your tests or some other existing internal target.
If that executable is the only thing you are using from that dependency, then you will have to live with a warning about the dependency being unused.
Workaround: Explicitly attach it to something, just like for 1.
This is why I think a new manifest entry for “tools needed during development, but not needed for any product” could be useful. It would remove the need to hook them up to some arbitrary target just to avoid these two inconveniences. But I think that can be done as a separate evolution proposal later on.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub <#2749 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AACPPDY7XKP7VVUVAY7HVGDRRRVXBANCNFSM4NAJAOGQ>.
|
Firstly, as others have said, thanks a ton for all the work you've put into this! This is huge progress. I agree completely with the comments about the quirks resulting from the ad hoc product dependencies created by mentioning otherwise unreferenced products on the command line. In particular, there should absolutely be follow-on evolution proposals to deal with build-time products as well as examples — both would benefit from being able to be specifically annotated as such in the manifest, especially since build-time artifacts also have to be built differently (in particular, for the host platform). I agree with @hartbit that the tradeoff made here is the right one for now. One question: in the code the explicit product is an optional; would it make sense to make it an array from the start, or do you feel that that would just exacerbate the problem? (I don't actually know whether it's possible to build multiple products at once from the command line, but it seems logical to do). |
I used Looking closer now, while tagging on of external products also happens to work with SwiftPM doesn’t currently provide a way to build multiple specific products from the command line. A CLI for something like I envision all of these Tying a hypothetical So I guess my opinion is still weakly in favour of |
@swift-ci please smoke test |
I’m pleasantly surprised that no merge conflicts accumulated in the last two weeks. 😄 The Linux failure looks unrelated to me; it was in llbuild before even touching SwiftPM. Let me know if I need to do something about it. The macOS job was simply cancelled before it got anywhere. (Presumably due to this.) |
@swift-ci please smoke test |
While drafting the comment below, I received a notification of #2769, which makes me think the CI error has nothing to do with this PR. (I have still included the draft below in case any of the information in it turns out to be useful.) I think I’m going to need help figuring out why only 3 out of 4 jobs passed. 🤔
(My Linux machine does not have sufficient space to build the entire toolchain locally. I can run the self‐hosted tests, but they aren’t the problem.) |
As you saw in #2769, this failure doesn't seem to be related to your change at all, sorry about that. Once the test suite is green again, we can re-run tests for this PR. |
Is CI the only thing holding this PR back? |
@swift-ci smoke test |
For those of you who've done some code review on this one (@abertelrud @neonichu @aciidb0mb3r @hartbit), do you feel you've done a thorough review and think this is ready to take? This is a big set of changes with risk, but also a very important contribution. I'd like to take this once we've got confidence in the changes. |
Does that mean the test crashed, or that Jenkins’ monitoring crashed? |
For reviewers, an interesting real‐world use case that would be affected by the executable handling (1 above) just popped up in the forums. |
Thanks a lot for the detailed reasoning here. I agree that supporting multiple opens up a whole bunch of issues that would only complicate this PR. |
That's an interesting case. But such packages (where there are conflicting dependencies used in disjoint sets of targets) would still have problems with commands that operate on the whole package, such as |
@swift-ci please smoke test |
Thanks so much for your PR, @SDGGiesbrecht, this is awesome. Sorry that it took a while to get merged. |
Seeing an issue with https://github.com/vapor/database-kit:
I think we also missed that the |
Yes, your observation is likely correct. Looking closer. |
Presumably just incrementing this? I’ll try it. |
This works for fixing the package I mentioned: neonichu@ffef731 There's probably a much better fix, though. It also seems as if we have some tests that are incorrect, because they are assuming that the product filter is applied even pre 5.2 -- but maybe I am missing something. |
Yes, it seems to be more complicated, but I’m still working on sorting it out. It affects |
Okay, it was confusing me because TSC is swallowing the real error, and it needs repairing.
Since this looks like the first time the pins schema has changed, you’ll need to decide how such updates should work. If the pins should not autoupdate, then the error message simply needs improvement.
If the pins should autoupdate, then the workspace needs to catch the version mismatch and reset the pins file to a clean state before continuing.
Some of the tests will also need minor adjustment to correspond to expected behaviour. It’s late where I am, so I’m done for the day. If there is a hurry, feel free to go ahead and implement either solution without waiting for me. Otherwise I’ll check for your answer tomorrow. |
There's no rush, thanks for looking into this! I think we would want to auto update, but ideally in an way that carries the exact resolved versions forward, but we can do that as an incremental change to having updating at all. |
I'm not sure I understand your fix to |
I think we can actually avoid changing the resolved file format entirely, will make a PR soon. |
The loading method first loads raw JSON, checks the version, and throws the That method is wrapped inside a do‐catch block which catches any error and wraps it into the I assume that outer method was only intended to catch and wrap the miscellaneous errors, but the way it’s structured, it also wraps the My fix suggestion was to forward the
Great. If that works, it is a much better solution. |
We are seeing some issues with the full implementation of target-based dependency resolution done in swiftlang#2749 and need to temporarily disable it to unblock affected projects. The changes are still available behind a compile-time define `ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION` and the tests have been modified accordingly to work in both cases (some tests are skipped by default for now and only enabled when enabling target-based dependency resolution). I haven't yet distilled the issues into test cases, but once I have I'll start a branch of re-enabling this again.
We are seeing some issues with the full implementation of target-based dependency resolution done in #2749 and need to temporarily disable it to unblock affected projects. The changes are still available behind a compile-time define `ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION` and the tests have been modified accordingly to work in both cases (some tests are skipped by default for now and only enabled when enabling target-based dependency resolution). I haven't yet distilled the issues into test cases, but once I have I'll start a branch of re-enabling this again.
…y resolution As discussed in the original PR swiftlang#2749, we no longer support building arbitrary targets using `--target`, but this test was relying on it. We removed a similar test from the unit tests and should do the same with this one.
We are seeing some issues with the full implementation of target-based dependency resolution done in swiftlang#2749 and need to temporarily disable it to unblock affected projects. The changes are still available behind a compile-time define `ENABLE_TARGET_BASED_DEPENDENCY_RESOLUTION` and the tests have been modified accordingly to work in both cases (some tests are skipped by default for now and only enabled when enabling target-based dependency resolution). I haven't yet distilled the issues into test cases, but once I have I'll start a branch of re-enabling this again.
motivation: target based dependencies implementation of unused products never materialized. we need to revisit this topic, but until then we would like to simplify the codebase by removing the partial implementation changes: * undo changes from Finish SE‐0226 (Ignore Unused Products) swiftlang#2749 * adjust call-sites and test which were added or modified after Finish SE‐0226 (Ignore Unused Products) swiftlang#2749 was merged
This pull request should complete the implementation of SE‐0226: Package Manager Target Based Dependency Resolution. @hartbit already taught the resolver to only care about products in #2424. This takes that work further so that the resolver only cares about products that are actually used.
This pull request is sizeable, so I’ll elaborate the main points here.
The changes broadly fall into four groups:
The manifest is now able to compute the downward‐facing products required for any upward‐facing product set. This is mostly housed in
PackageModel/Manifest.swift
, and boils down to turning @hartbit’sallRequiredDependencies
intodependenciesRequired(for:)
, along with the input typeProductFilter
.The resolver now operates on abstract nodes. See
DependencyResolutionNode
for the nitty‐gritty details. Essentially, it resolves individual products instead of whole packages. The new node type has simply been slotted in to replace thePackageReference
s that were in use before. None of @kiliankoe’s Pubgrub decision making processes has been changed in any way. The diagnostics have also been left alone except for the inclusion of the specific product alongside the package name where relevant.Dozens of new method parameters and instance properties have been added to various types and methods in order to pass the new information along from where it originates to where it is needed. Unfortunately, this affects a whole swath of things across the
PackageModel
,PackageLoading
,PackageGraph
,Workspace
,Commands
andSPMTestSupport
modules, but all of these changes are straightforward.Many tests required fixing. Most of them merely needed to provide the new parameters required in order to satisfy the new API. Several were expecting failures that were no longer reachable, and needed dependencies to be made explicit so that the resolver would even enter the code branch in question. All but three are straightforward. (See below.)
While I was working through the tests, three things came up which need a closer look. They are tests that expected behaviour at least partially at odds with SE‐0226.
The test suite expected unreachable executable products to be available.
swift run dependency‐executable
is apparently supposed to work, even if no dependency is declared on that product. I can see how that could be useful, and it wouldn’t surprise me if users are taking advantage of it in their workflows. But SE‐0226 says this:So including such executables would undermine one of the motivating use cases for SE‐0226. As such, what I have implemented right now does not resolve such executables by default.
However, as a compromise to maintain backwards compatibility, I have channeled the argument provided to any
swift run
invocation through to the resolver, so that if you explicitly ask to run an executable of an immediate dependency, you will still be able to. Since it has some minor drawbacks, I consider this an interim solution. This implementation will suffice for now, but a separate evolution proposal should probably be made to design something better if we want to continue supporting this long‐term. See the Fix‐Me in the initializer forPackageGraphRoot
for more details.The test suite expected unreachable targets to be available to a
swift build --target dependency‐target
invocation. Since there is no infrastructure in the resolver to handle targets, there is no easy way to locate or load such a target. Since it seems backwards to SE‐0226 and has no practical use I can think of, I simply removed the test.The test suite expected legacy system packages to work without an explicit target dependency declaration. Such packages have been triggering a deprecation warning since Swift 4.2. Continuing to support them implicitly is problematic, because there is no way to know if that’s what a package is until after fetching and loading it, so it would defeat the whole of SE‐0226.
As a compromise to maintain as much backwards compatibility as possible, I have taught the manifest loader to internally convert such a package into a modern‐style one with a system target and product, which inherit the package’s name and details. This allows the current toolchain to still use such dependencies by referencing the synthesized product. However, if the client package wants to support both old and new toolchains at once (such as 5.1 and 5.4), it will have to make use of
#if compiler
, because the old toolchain will be unable to locate the declared product, whereas the new toolchain will not resolve an undeclared product.