Как условно скомпилировать версию Swift (1.2 vs 2.0) в одном и том же исходном файле?

У меня есть демонстрационный проект Swift, который поставляется вместе с моей картой. Я хочу убедиться, что код Swift в демо успешно компилируется как с Xcode 6 (Swift 1.2), так и с Xcode 7 (Swift 2.0) без вмешательства пользователя.

Так как там только маргинальная поддержка препроцессора в Swift, как я могу определить во время компиляции, какая версия Swift или Xcode используется для компиляции кода?

Теперь вот важная деталь:

  • Он должен работать автоматически!
    • Откройте проект в Xcode 6 → компилирует код Swift 1.2.
    • Открыть проект в Xcode 7 → скомпилирует Swift 2.0.

Нет настроек сборки или других средств, которые требуют от пользователя указать, так или иначе, какую версию Swift/Xcode она использует.

Я продолжаю думать: это такая тривиальная задача, как это могло быть невозможно с Свифт?

Как разработчик фреймворка, это приводит меня в бешенство, поскольку успешная компиляция проекта Swift теперь полностью зависит от пользовательской версии Xcode, и я не могу попросить их "обновить до Xcode 6.4" и в более поздней точке попросив их снова "обновить до Xcode 7.1". Это безумие!

Альтернативой было бы, конечно, иметь отдельные демо-проекты, управляющие разными базами кода, по одному для каждой версии Swift. И надеясь, что пользователь узнает, какой проект будет работать с ее версией Xcode. Не настоящая альтернатива.

Другим альтернативом, просто не использующим какого-либо улучшения Swift 2.0, к сожалению, тоже не возможно. Существует синтаксис, классы и методы, которые не будут работать в той или иной версии Swift, если только из-за того, что компилятор становится более придирчивым в новых версиях Xcode.

+5
источник поделиться
2 ответа

Вы можете выполнить это, используя некоторые расширенные настройки Xcode, в частности:

  • XCODE_VERSION_MAJOR: Кодирует основную версию Xcode как строку, например "0700".
  • EXCLUDED_SOURCE_FILE_NAMES: шаблон "fnmatch" исходных файлов для исключения по умолчанию.
  • INCLUDED_SOURCE_FILE_NAMES: шаблон "fnmatch" для исходных файлов, которые нужно включить.

Я бы вообще не рекомендовал делать это, так как это затруднит понимание вашего проекта для большинства пользователей Xcode, но если вы абсолютно хотите заставить его работать, вы можете использовать эту технику.

Способ, которым вы выполняете это, выглядит следующим образом:

  • Для любых исходных файлов, которые должны быть версиями, назовите их что-то вроде "Thing-Versioned-0600.swift" и "Thing-Versioned-0700.swift". Убедитесь, что оба файла находятся в фазе сборки источников.

  • Использовать исключенный механизм для предотвращения любых версий файлов по умолчанию, добавив настройку сборки на уровне проекта: EXCLUDED_SOURCE_FILE_NAMES = *-Versioned-*.swift.

  • Используйте включенный механизм только для добавления обратно в файлы, соответствующие текущей основной версии Xcode, добавив еще один параметр сборки на уровне проекта: INCLUDED_SOURCE_FILE_NAMES = *-Versioned-$(XCODE_VERSION_MAJOR).swift.

+4
источник

Наличие двух версий кода внутри вашего проекта не будет работать, поскольку код не будет компилироваться. Нет директивы компилятора для условной компиляции на основе версии.

Существует одно обходное решение, которое могло бы работать (не проверял его)

Сначала создайте 3 файла с именем version_current.swift, version_1_2.swift и version_2.swift. Убедитесь, что только версия_current.swift является частью вашей цели сборки.

Затем создайте новую фазу сборки script и поместите ее прямо над фазой "компиляции". В этом script вы скопируете содержимое версии 1_2 или 2 поверх текущего.

Мои навыки написания сценариев не так хороши, поэтому я не могу помочь вам в этом. Вы можете получить версию с кодом, например:

$ xcrun swift -version

А затем просто выполните оператор копирования.

Но тогда это будет работать только для версии Xcode по умолчанию в вашей системе. Если вы хотите использовать другую версию, вам также необходимо изменить версию по умолчанию.

0
источник

Посмотрите другие вопросы по меткам или Задайте вопрос