JamitLabs / Accio

A dependency manager driven by SwiftPM that works for iOS/tvOS/watchOS/macOS projects.
MIT License
664 stars 32 forks source link

Fix cache mixed up with different swift versions #62

Closed fredpi closed 5 years ago

fredpi commented 5 years ago

Fixes #61.

With this implementation, there is a differentiation between versions like "Swift 5.0" and "Swift 5.0.1". Previously, those have been treated equally. I'm indecisive how to handle this – what do you think?

Also, with module stability coming, we should allow a Swift 6.0 project to access cached Swift 5.1 builds, right?

Jeehut commented 5 years ago

Regarding the first point, I agree that differentiating Swift 5.0 from 5.0.1 is a good idea. Regarding backwards compatibility, see my comment in #64.

fredpi commented 5 years ago

Regarding global state of the Swift version:

The reason is that the Swift version really doesn't change during the entire process of running Accio commands

While a change of the Swift version during runtime isn't that likely, it will have severe consequences if it happens. And scenarios, where it may happen, exist: e. g., when a new Xcode Beta release is published, the user, who set their command line tools to use this new version, may trigger accio install. Because the new Xcode release includes a new Swift version, many frameworks may not be in the cache already. So, the process takes a while, the user grabs a coffee, returns to their Mac and sets the command line tools to use the previous Xcode version again, while Accio is still running.

Now, when the Swift version has been cached, as you proposed, that's fine: Although the Swift version changed during the process of building, Accio will still store the build products in the proper place. We could therefore opt to do this caching. Still I think, it's semantically better to pass it around, as it may differ from build to build (which is currently not handled, but I suggest to do so, see next paragraph).

However, some frameworks might have been built with the Swift version that was set during the process, so not all frameworks belong to the same caching folder. In such a case, the Swift version should be determined right before each build and then stored in the build product model. We could opt for such a solution, but it would of course cause even more swift --version calls.

Given that having a framework built with Swift version x in the global cache for Swift Version y, where x != y, definitely has severe consequences for multiple users accessing this shared cache, and requires manual cleanup, I think we should be pretty precise about this. Maybe, one could infer the Swift Version from the .framework quite easily, so that a swift --version check isn't required each time?

Also, as the user himself will most likely not be able to use their frameworks built by Accio, when they changed the Swift version in the process of running Accio, we could also just stop Accio at all when a Swift version change is detected and drop a corresponding error message instead of performing the caching per Swift version.

Jeehut commented 5 years ago

IMHO the Swift version shouldn't change at all during the processing of one command. That would only cause confusion and make reproducing and fixing errors a nightmare. So, I'm definitely for returning with an error if the Swift version really ever changes during a command. I didn't think of that before, I was just referring to the thread of the command itself, not the commands we additionally run in console. But it's true that people might change Swift versions during a command.

fredpi commented 5 years ago

@Dschee Fine – I will...

fredpi commented 5 years ago

@Dschee This is what I found out:

• Getting the Swift version via the swift --version command takes ~ 0.1 s for me • It's possible to look for the Swift Header file (~Headers/...-Swift.h) in a framework and look up the Swift version there (it's included in a comment). This takes ~ 0.001 s on my machine, but doesn't work for some frameworks like RxAtomic where this file is missing for some reason...

Now, I implemented Swift version monitoring using the performant per-framework checking mechanism, having the swift --version command as a fallback. I'm wondering whether there is a better way to get the Swift version a framework was built with, also ensuring proper compatibility with frameworks like RxAtomic.