swiftlang / swift-package-manager

The Package Manager for the Swift Programming Language
Apache License 2.0
9.72k stars 1.34k forks source link

`swift-tools-version` behavior differs from SE-0209 #7869

Closed norio-nomura closed 1 month ago

norio-nomura commented 1 month ago

Is it reproducible with SwiftPM command-line tools: swift build, swift test, swift package etc?

Description

When building the release/6.0 branch of swift-syntax using Xcode 16 beta 5, the build process includes the -swift-version 6 flag. However, according to SE-0209, this should not be the case.

Referring to Example 4 in SE-0209:

Example 4:

// swift-tools-version:4.2

import PackageDescription

let package = Package(
    name: "HTTPClient",
    ...
    swiftLanguageVersions: [.v4, .version("5")]
)

The sources will be compiled with -swift-version 4.

In alignment with this example, the release/6.0 branch of swift-syntax, which has // swift-tools-version:5.7 in its Package.swift, should be built with the -swift-version 5 flag. However, this is not the case, and the build process uses -swift-version 6 instead.

While I personally believe the current behavior might be more correct, it still represents a deviation from the behavior specified in SE-0209, which could be problematic.

Expected behavior

No response

Actual behavior

swift-build --verbose outputs logs using "-swift-version 6"

Steps to reproduce

  1. git clone https://github.com/swiftlang/swift-syntax.git -b release/6.0
  2. cd swift-syntax
  3. swift build --verbose | grep -e "-swift-version 6"

Swift Package Manager version/commit hash

Swift Package Manager - Swift 6.0.0-dev

Swift & OS version (output of swift --version ; uname -a)

swift-driver version: 1.113 Apple Swift version 6.0 (swiftlang-6.0.0.7.6 clang-1600.0.24.1) Target: arm64-apple-macosx15.0 Darwin norio-nomura-MacBook-Pro.local 24.0.0 Darwin Kernel Version 24.0.0: Wed Jul 31 21:50:55 PDT 2024; root:xnu-11215.0.199.501.2~1/RELEASE_ARM64_T6020 arm64

bnbarham commented 1 month ago

There's three concepts here:

  1. Toolchain (or compiler) version
  2. Tools version specified by the manifest
  3. Supported language modes specified by swiftLanguageModes (which was swiftLanguageVersions)

The language mode used is the one closest to the current compiler version that's in the list of supported language modes. Note that the tools version specified by the manifest is mostly orthogonal in this case, other than being used to decide on a default if no language modes are specified.

In the given example, swift-syntax specifies both 5 and 6. Xcode 16 beta 5 contains a 6.0 compiler, thus language mode 6 is used. If instead a pre 6.0 compiler was used for the compilation, language mode 5 would be selected instead.

The final example in the SE is a little confusing, as the compiler and tools version isn't split and instead assumed to be the same. The actual design states:

The package manager will use standard version numbering rules to determine precedence of language versions. For e.g. 5 > 4.2.1 > 4.2 > 4. ... When building a package, we will always select the Swift language version that is most close to (but not exceeding) a valid language version of the Swift compiler in use.

If a package does not specify a Swift language version, the tools version of the manifest will be used to derive the value.

norio-nomura commented 1 month ago

Thank you for the clarification. 🙏🏻