Using #if compiler from now on instead of swift-tools-version annotation

To prevent the ever increasing number of Package@swift-x.y.swift files a library author must maintain may I suggest we halt the ascent of swift-tools-version at 5.0 and instead encourage use of #if compiler in the manifest files.

Lately I have been trying to support both Xcode 10.1 and Xcode 10.2 toolchains in my libraries, and the only way to do this is to duplicate the whole manifest to Package@swift-5.0.swift and change the top tools annotation from 4.2 to 5.0.

I almost didn't, but I want to use some Swift 5 features in my tests, which means I must have a Package@swift-5.0.swift file.

Since we now have a compiler directive that can determine tools-version, perhaps we can make a proposal to adjust the forward direction for this part of SwiftPM to something more maintainable?

With #if compiler I could then:

#if compiler(>=5)
package.swiftLangageVersions.append(.v5)
#endif
1 Like

The swift-tools-version annotation is used to determine the version of PackageDescription library that should be used to evaluate the manifest file. We need this information before the manifest can be evaluated. This feature allows SwiftPM to evolve the PackageDescription library without breaking the existing package ecosystem. For e.g., if you update your package's tools version, your clients on older tools version will continue to use the latest version of the older manifest until they update their tools. Also note that this feature is different from version-specific manifest file which determines which manifest to use for a particular (marketing) version of Swift. We never really had a feature that allows using newer manifest features without breaking compatibility for older clients.

I like the #if compiler idea but we would need a way for manifests to declare a list of compatible tools versions so older tools can figure out which PackageDescription version to use if they don't have the latest one. Maybe, something like:

// swift-tools-version: 4.2, 5.0
1 Like

I confess I don’t fully understand all the specifics, but it certainly seems to me that the manifest tools-version increases haven't had any breaking changes since Swift 3 -> 4, and provided that seems likely in the future, anything that would allow us to have one manifest rather than several would be great.

Mainly here I want to be able to add platforms and declare support for Swift 5 without duplicating the manifest files.

So your suggestion seems great to me. I'd happily draft the proposal.

Is it necessary to have a version 5 manifest to get swift 5 to run?
There is the ability to specify an arbitrary future version of swift in the swiftLanguageVersions array...

I find that I have to force the issue by specifying
swift test -Xswiftc -swift-version -Xswiftc 5
(awfulness)
... but I hope it's not just because I need yet another manifest.

I tried specifying .v5 in the 4.2 manifest but SwiftPM rejected it insisting I use a 5.0 tools version.

I know you used to be able to specify integer values, maybe that still works and would work here? I can try at some point. If so that would help with quite a bunch of my current issues.

The discussed feature would still have merit of course.

You need to use the untyped API for specifying versions not known to the current PackageDescription API.

swiftLanguageVersions: [.v4_2, .version("5")]

I just found that if your default is a tools-version-4 manifest, it probably won't work. Make your default specify tools-version 4.2, with the alternate for swift-4. Then my swift 5 toolchain built the package as swift 5, as expected, with just a swift test

The documentation doesn't do a good job on this.

Superb! This means I can have a single manifest for all 4.2+ packages I support that don't need platforms. Much thanks.

1 Like