Get Swift language version programmatically

Is there any way to get the Swift language version programmatically? Something similar to what the REPL prints as “Swift version”:

$ swift -version
Apple Swift version 4.1 (swiftlang-902.0.41 clang-902.0.31)
Target: x86_64-apple-darwin17.5.0

Background: I can install multiple Xcode apps in parallel, switch between language versions (e.g. 4.1 vs 3.3) in the build settings, and also switch between additional toolchains downloaded from https://swift.org/download/#releases.

Therefore – solely for information purposes! – something like

print(SWIFT_VERSION_STRING) // 4.1

would be convenient to see what I am currently working with. I am aware that there is a conditional compilation check

#if swift(>=4.2)
print("Swift 4.2")
#elseif swift(>=4.1)
print("Swift 4.1")
#elseif swift(>=4.0)
...
#endif

but that is quite a lot of code for such a simple purpose, and also needs to be updated for new Swift versions.

There is a SWIFT_VERSION_STRING in Version.cpp,
but I cannot see how this (or something similar) is exposed to Swift.

1 Like

Such a thing doesn’t really make sense in compiled languages. Maybe getting the runtime version if the Swift runtime is ever vended by OSs. But beyond that compilation is the only time the “version” of swift comes into play.

Of course it makes sense.

let (major, minor, patch) = /* the version of Swift being used to compile this code */
print("\(major).\(minor).\(patch)")

That is a perfectly sensible program.

Whether or not it is generally useful enough to warrant inclusion is a separate matter, but it definitely makes *sense*.

Hm, okay I guess that’s a sort of “sense”.

But I don’t see how it would be helpful beyond printing out what version of the compiler a particular something was compiled under, since it would effectively be a compile-time constant. Although I could see some bizarro world where library versioning is expressed in this kind of manner whenever or if ever that comes about.

Having a pound-literal #languageVersion that produces a named tuple is totally reasonable, just like #file.

I’ve found it to be a useful debugging feature. In C++ I often use __GNUC__, __cplusplus, etc. when trying to figure out what compiler/C++ version I’m actually using. Plus, I can think about some sort of runtime check that dynamically loads the “right” version of a method based on the Swift version…

This is a feature that kind of makes sense to me in a world after ABI stability has been reached, and therefore your code could be compiled under Swift N and then interact with the runtime of Swift M, for N!=M

1 Like

Yes, I could totally see that as being useful if the runtime is built in a way that new features can be added in a way that maintains the ABI, but some features are not available on older versions. Like more robust reflection capabilities.

But that would probably be expressed as a runtime if @swift query rather than a static version check.

Indeed.

That is exactly what I was thinking of. Just as a confirmation in my test program, when playing around with different Xcode apps/build settings/toolchains, to see what Swift version I am currently compiling with.

Indeed, a pound-literal might be more appropriate.

Apparently such a variable does not exist yet. Perhaps the discussion should be continued in https://forums.swift.org/c/evolution/pitches ?

2 Likes

This would require a SE proposal. I’m happy to implement #swiftVersion :)

2 Likes

I see a few usage models. Today one can approximately use the Swift language version — e.g., #if swift(>=4.0) — to conditionally build different blocks of code depending on what compiler you are using. Examples can be found in the swift test suite. It's indirect, however, as a given compiler can support different language compatibility modes. However, every bump in compiler version is accompanied by a bump in the language compatibility version for each of the language modes the compiler supports, so it is possible to write code that detects a specific compiler.

However, this is complicated and error prone if one wants to detect for a specific compiler release versus a supported language mode — which are two different concerns.

The immediate question I have is what would this be used for, and is it the use case that motivated this thread. We already have the ability to conditionally write code based on language version, which is more powerful than just producing a tuple. My interpretation is the desire here is to be able to conditionally compile blocks of code based on a check for the compiler version.

No, that is not what I was thinking of. The only purpose of such a version string would be informational.

For example: I downloaded and installed the latest development snapshot and selected it in the Xcode Toolchains preferences (where it is called “Swift Development Snapshot”). There is no indication which Swift language versions this snapshot implements. I have to call

$ /Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2018-04-09-a.xctoolchain/usr/bin/swift -version
Apple Swift version 4.2-dev (LLVM 49e6f88643, Clang cf4f73cfc1, Swift 53be298f1f)
Target: x86_64-apple-darwin17.5.0

to see that this is a development version of Swift 4.2.

That’s why I think that some mechanism producing the current version information would be convenient: To see/verify what Swift language I am currently compiling with (in particular when switching between toolchains or switching between Xcode apps).

Thanks for all the feedback so far. I have posted a follow-up on Evolution/Pitches: Get Swift version information programmatically.

Looks like the link here is to the current post, not an evolution post.

The link looks correct to me. The current post is Get Swift language version programmatically. The follow-up evolution post is Get Swift version information programmatically.