Best way to support multiple swiftsyntax versions

I was writing a utility package for one of my projects for the swift standard library, but got a major version conflict for swift-syntax (603 & 602) with one of my dependencies. As SwiftPM doesn't support multiple versions of the same dependency (yet?), I came up with this workaround in my package manifest:

// MARK: - SwiftSyntax dependency

// This can be considered a workaround for the lack of multiple major versions of a package,
// with swift-syntax being one of the most common examples of major version conflicts.
// 
// https://www.pointfree.co/blog/posts/116-being-a-good-citizen-in-the-land-of-swiftsyntax
// https://forums.swift.org/t/multiple-major-versions-of-a-package-in-swiftpm-opening-the-discussion/86317
// https://github.com/orgs/swiftlang/projects/32/views/1

let swiftSyntaxCustomVersionEnvKey = "SWIFT_STDLIB_UTILS_SWIFTSYNTAX_VERSION"
let swiftSyntaxPath = "https://github.com/swiftlang/swift-syntax.git"
let swiftSyntaxDependency: Package.Dependency
if let customVersionString = environment[swiftSyntaxCustomVersionEnvKey] {

  // Make sure the version specified is valid
  let customVersion: Version
  if let majorVersion = Int(customVersionString) {
    customVersion = Version(majorVersion, 0, 0)
  } else if let version = Version(customVersionString) {
    customVersion = version
  } else {
    fatalError("\(swiftSyntaxCustomVersionEnvKey) contains invalid version")
  }
    
  // Make sure the version is supported
  guard (600...603).contains(customVersion.major) else {
    fatalError("\(swiftSyntaxCustomVersionEnvKey) has unsupported version \(customVersion)")
  }

  swiftSyntaxDependency = .package(url: swiftSyntaxPath, from: customVersion)
} else {
  swiftSyntaxDependency = .package(url: swiftSyntaxPath, "600.0.0"..<"604.0.0")
}

I have already made some basic changes using the module versions (i.e. canImport(603)). Is there any other important considerations I am missing or a better way to support multiple SwiftSyntax versions?

What is the issue that you’re seeing that’s solved by your workaround? I would have expected you to be able to handle all cases with this dependency declaration that you already have.

.package(url: swiftSyntaxPath, "600.0.0"..<"604.0.0")
1 Like

I think what I meant to ask was how many major versions should I support nowadays? I would have liked to just use from: 603.0.0 but I can’t do that due to my dependencies

I would cover the same range as your package's supported Swift versions. You can try higher if there are breaking changes to support, or when Apple is running the beta that wants the next version, or lower, if you know the lower version works correctly with your higher Swift version code.

This is another thing SPM should really fix. Different macros should be able to use different versions of swift-syntax, especially if there are prebuilts for the various versions.

2 Likes