How to set Swift version 5 (for recent dev snapshots) in Xcode build settings?

I've tried dev snapshots 2018-12-06 and 2018-12-07 (master), and both use Swift 5 by default from the command line (swiftc). But when using them from within Xcode 10.1 (10B61) (in a command line project), the option for Swift 5 is missing:

Am I missing something obvious?

I tried setting SWIFT_VERSION to 5 in the project.pbxproj file manually:

		B4AC0A56216ADAF500CDC919 /* Debug */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = 88S3B6XZEL;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5;
			};
			name = Debug;
		};
		B4AC0A57216ADAF500CDC919 /* Release */ = {
			isa = XCBuildConfiguration;
			buildSettings = {
				CODE_SIGN_STYLE = Automatic;
				DEVELOPMENT_TEAM = 88S3B6XZEL;
				PRODUCT_NAME = "$(TARGET_NAME)";
				SWIFT_VERSION = 5;
			};
			name = Release;
		};

but this only resulted in Xcode giving me this Build System info:

error: SWIFT_VERSION '5' is unsupported, supported versions are: 3.0, 4.0, 4.2.

I don't know if:

  1. This limit is hard-coded in Xcode 10.1 itself, without any workaround.

    In this case, I guess the Swift 5 snapshots are only available for SPM packages... We could open a radar so that Xcode eventually becomes able to run latest snapshots.

  2. If the snapshot does a bad job at telling Xcode the supported values for SWIFT_VERSION, and we should wait for a fixed snapshot.

    In this case, we should tell on http://bugs.swift.org

  3. if the snapshot ignores the SWIFT_VERSION and uses Swift 5 by default.

    I don't think this one is true, because I could not play with SE-0228 in a playground today, as if it wasn't implemented at all. Maybe the Swift 5 compiler was still stuck in the Swift 4 mode, I can't really tell.

The recent snapshots does not ignore the SWIFT_VERSION, and it seems impossible to get them to use Swift 5 from within Xcode.

As noted above, they do however use Swift 5 by default when using their swiftc from the command line. But I'd like to be able to use Swift 5 from within Xcode too.

I thought of two ways to get around this limitation but they don't work because of build system issues:

  • Adding -swift-version 5 in OTHER_SWIFT_FLAG doesn't work because these flags are added before the build system adds the evaluated value of SWIFT_VERSION.
  • Overriding SWIFT_VERSION using an xcconfig doesn't work because the build system validates the value against the hardcoded list.

The list of values in SWIFT_VERSION is effectively hardcoded so you don't see the language version 5 in the list. It is still possible to set a custom value using an xcconfig file (see my previous post). The radar could be for providing an easy way to configuring arbitrary values for SWIFT_VERSION or for reading the list of supported language versions from the compiler in use. /cc @NeoNacho

Thank you, @Aciid.

This reveals an opportunity for improvement in the release process of snapshots. I don't know who is the DRI (directly responsible individual) of the integration of snapshots in Xcode, but I would like this person to know about this thread promptly. CC @tkremenek.

The number of developers who try snapshots should raise, if only for their feedback. For one @Jens who tells about his difficulties, how many silently move on to something else?

2 Likes

Would you mind going through step by step exactly how you got this to work?

I've added a file SetSwift5Hack.xcconfig:

SWIFT_VERSION = 5

And set it to be used on both Debug and Release, both project and target level, but it does not have any effect on eg this program:

func test() {
    #if swift(>=3.0)
    print(">=3.0")
    #endif

    #if swift(>=4.0)
    print(">=4.0")
    #endif

    #if swift(>=4.2)
    print(">=4.2")
    #endif

    #if swift(>=5)
    print(">=5")
    #endif
}
test()

which will always print

>=3.0
>=4.0
>=4.2

(if 4.2 is what the Swift Language Version of my target is set to, leaving it unspecified is not supported by Xcode) no matter what value I set for SWIFT_VERSION in the xcconfig file (tried "5", 5.0, 4, etc).

Adding an intentional syntax error like an exclamation mark before SWIFT_VERSION will have Xcode complain about it so at least it doesn't completely ignore the file. Any ideas?

(Note that the above test program does print >=5 if I use the swiftc (of a recent dev snapshot) from the command line.)

Did you remove the existing entry from the build settings editor? Go to your target's build setting editor, select the SWIFT_VERSION row and press delete key (do the same for project level setting in case it is also explicitly set). You can check the build logs to confirm which version was used. Expand the "Compile Swift sources files" and look for the -swift-version argument in the command-line.

Hmm, doing that (for both the target and the project) will show "Swift 5 (unsupported)" in the combo box (which seems a bit promising, sort of). But when I try to compile Xcode will complain:

error: SWIFT_VERSION '5' is unsupported, supported versions are: 3.0, 4.0, 4.2. (in target 'Blabla')

Setting SWIFT_VERSION in my xcconfig file to 4 and 4.2 will work and set the version accordingly (I can verify it by the output of the above test program). Commenting out the SWIFT_VERSION line will result in Xcode telling me:

error: Value for SWIFT_VERSION cannot be empty. (in target 'Blabla')

That means you're still using an older version of compiler. Are you sure you selected the dev toolchain? You can check in logs which compiler is being used.

I have the same dev snapshot toolchain selected in Xcode as I have working with Swift 5 from the cmd line:

AFAICS the log ends with the above before it has had any chance of saying anything about which compiler it uses.

Ok, it looks the build system always validates the value of SWIFT_VERSION against the hardcoded list so there is no way make it work with the latest version of Xcode. I'll go ahead and file some radars. We definitely need some solution here :/

1 Like

Thank you!

Just out of curiosity, what environment are people using for eg trying out Swift 5?

I get the feeling I'm the only one trying to use Xcode for this, and everyone else is using some much better setup, how else to explain the fact that this thread seems to be the only place on the internet that talks about this problem?

Or is almost no one trying out Swift 5 (on larger projects, with code completion, etc)?

Are there really a lot of changes that you get only in the 5.0 mode? IIRC there were less changes this time. You can still use the Swift 5 snapshots in Swift 4.0 and 4.2 modes.

I’m expecting a lot of bug fixes in Swift 5.

Most of the time you will see the fixes across all language versions unless it is going to present a source compatibility issue.

Well, here's the most recent example that I know of where the behavior is different between Swift 5 and 4.2 (at least in recent snapshots), repeated here for clarity:

func hmm(_ fn:  (Int, Int)  -> Int) { print("two ints") }
func hmm(_ fn: ((Int, Int)) -> Int) { print("pair") }

func test() {
  let twoIntsFn: (Int, Int) -> Int = { $0 + $1 }
  let pairFn: ((Int, Int)) -> Int =  { $0.0 + $0.1 }

  hmm(twoIntsFn) // error with both Swift 5 and Swift 4.2
  hmm(pairFn) // OK with Swift 5, error in Swift 4.2
}
test()

All I was trying to say was that I'm a bit surprised at how uncommon an activity it seems to be to try out recent snapshots and switch between an upcoming Swift version and the current one, at least from within Xcode.

You can still try out the Swift 5 snapshots with the older language modes, and this is still extremely valuable for us because it can catch regressions.

Here is a hack that works for trying out the snapshots in Swift 5 mode:

  1. Edit the file /Applications/Xcode.app/Contents/PlugIns/Xcode3Core.ideplugin/Contents/SharedSupport/Developer/Library/Xcode/Plug-ins/XCLanguageSupport.xcplugin/Contents/Resources/Swift.xcspec

  2. Search for SupportedLanguageVersions and add 5.0 as a valid value.

11 Likes