How to conditionally compile a version of Swift (1.2 vs 2.0) in the same source file?

I have a Swift demo project that comes with my map. I want to make sure that the Swift code in the demo successfully compiles with both Xcode 6 (Swift 1.2) and Xcode 7 (Swift 2.0) without user intervention .

Since there is only marginal preprocessor support in Swift , how can I determine at compile time which version of Swift or Xcode is used to compile the code?

Now here is the important detail:

  • It should work automatically!
    • Open a project in Xcode 6 -> compiles Swift 1.2 code.
    • Open project in Xcode 7 -> compiles Swift 2.0.

There are no build settings or other tools that require the user to specify, anyway, which version of Swift / Xcode it uses.

I keep thinking: this is such a trivial task, how could this be impossible with Swift?

As a framework developer, this infuriates me, since the successful compilation of the Swift project now completely depends on the user version of Xcode, and I cannot ask them to “upgrade to Xcode 6.4” and at a later point ask them to “upgrade to Xcode 7.1 again”. This is madness!

An alternative would, of course, be to have separate demo projects managing different code bases, one for each version of Swift. And hoping that the user will find out which project will work with its version of Xcode. Not a real alternative.

Another alternative that simply does not use any Swift 2.0 enhancement, unfortunately, is not possible either. There is syntax, classes, and methods that will not work in a particular version of Swift, if only because the compiler becomes more picky in newer versions of Xcode.

+5
source share
2 answers

You can accomplish this using some advanced Xcode settings, in particular:

  • XCODE_VERSION_MAJOR : XCODE_VERSION_MAJOR main version of Xcode as a string, for example "0700".
  • EXCLUDED_SOURCE_FILE_NAMES : source file EXCLUDED_SOURCE_FILE_NAMES template for default exception.
  • INCLUDED_SOURCE_FILE_NAMES : INCLUDED_SOURCE_FILE_NAMES template for source files to include.

I would not recommend doing this at all , as this will make it difficult for most Xcode users to understand your project, but if you absolutely want to get it working, you can use this technique.

The way you do this is as follows:

  • For any source files that should be versions, name them something like "Thing-Versioned-0600.swift" and "Thing-Versioned-0700.swift". Make sure both files are in the source build phase.

  • Use the excluded mechanism to prevent any version of the files by default by adding the build setting at the project level: EXCLUDED_SOURCE_FILE_NAMES = *-Versioned-*.swift .

  • Use the included mechanism only to add back to files that correspond to the current main version of Xcode by adding another build parameter at the project level: INCLUDED_SOURCE_FILE_NAMES = *-Versioned-$(XCODE_VERSION_MAJOR).swift .

+4
source

Having two versions of the code inside your project will not work, as the code will not compile. There is no compiler directive for conditional compilation based on version.

There is one workaround that could work (not tested it)

First create 3 files named version_current.swift, version_1_2.swift and version_2.swift. Make sure that only version_current.swift is part of your build goal.

Then create a new script build phase and place it right above the “compile” phase. In this script, you copy the contents of version 1_2 or 2 on top of the current one.

My scripting skills are not so good, so I cannot help you with this. You can get the version with the code, for example:

 $ xcrun swift -version 

And then just execute the copy statement.

But then this will only work for the default version of Xcode on your system. If you want to use a different version, you also need to change the default version.

0
source

All Articles