Как добавить значения в переменные xcconfig?
Я использую файлы Xcode и .xcconfig. Я пытаюсь добавить некоторые значения в определениях препроцессора, но я просто не могу заставить его работать.
Я попробовал следующее (как и многие варианты этого), но пока не повезло:
GCC_PREPROCESSOR_DEFINITIONS = '$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE'
Символ NEW_VALUE
просто не добавляется к определениям препроцессора.
Кто-нибудь успел добавить новые значения в переменные в файлах xcconfig?
Ответы
Ответ 1
По причинам, изложенным в других ответах на этот вопрос, вы не можете легко наследовать ценности.
Я рекомендую определить ваши настройки в каскаде. Предположим, что APP - это ваш префикс проекта и упрощает определение только нескольких CFLAGS:
platform.xcconfig:
APP_PLATFORM_CFLAGS = -DMAS=1
project.xcconfig:
#include "platform.xcconfig"
APP_PROJECT_CFLAGS = -DBETA=1
целевой one.xcconfig:
#include "project.xcconfig"
APP_TARGET_CFLAGS = -DSUPER_COOL=1
#include "merge.xcconfig"
целевой two.xcconfig:
#include "project.xcconfig"
APP_TARGET_CFLAGS = -DULTRA_COOL=1
#include "merge.xcconfig"
merge.xcconfig:
OTHER_CFLAGS = $(inherited) $(APP_PLATFORM_CFLAGS) $(APP_PROJECT_CFLAGS) $(APP_TARGET_CFLAGS)
Затем вы будете основывать каждую конфигурацию вашей цели на target-xxx.xcconfig
. Реальный проект будет использовать более сложные настройки, используя конфигурационный файл для проекта и другой для цели, но вы получите эту идею.
Кроме того, помните, что $(inherited)
относится к уровню выше в иерархии, а не ранее. Например, он наследуется от уровня проекта на целевом уровне. Не уверен, что это относится и к Xcode 4.
Это упрощение GTM, идите туда, чтобы узнать больше.
Ответ 2
В соответствии с Системным руководством по построению Xcode:
Когда блок конфигурации содержит более одного определения для конкретная настройка сборки, Xcode использует последнее определение в блоке. Держать в виду, что файлы конфигурации не иметь доступа к настройке сборки определения, сделанные в конфигурации файлы, которые они включают. Это ты не может изменить определение, сделанное в включенный файл конфигурации; вы может только заменить его.
Итак, я думаю, это означает, что невозможно добавить значения к данной переменной.
Ответ 3
Это работает:
xcodebuild GCC_PREPROCESSOR_DEFINITIONS='$(value) NEW_VALUE'
Ответ 4
Существует другой вопрос с ответом, который может помочь в этой конкретной проблеме. Он описывает технику, в которой каждый слой составляет подмножество определений, а затем объединяет их все вместе на xcconfig на уровне листа.
Ответ 5
Я думаю, что я наткнулся на немного лучший подход, пытаясь интегрировать файлы xcconfig Cocoapods в свои собственные. Мне нравится указывать в моих проектах следующее:
GCC_PREPROCESSOR_DEFINITIONS = CONFIGURATION_$(CONFIGURATION)
К сожалению, это противоречит определениям, которые поставляются с Pods.xcconfig. Как сказано в другом месте, $(унаследованный) работает не так, как ожидалось. Что делает следующая работа
GCC_PREPROCESSOR_DEFINITIONS[config=*] = CONFIGURATION_$(CONFIGURATION) $(inherited)
UPDATE:
Если вам нужно переопределить параметр для конкретной конфигурации, тогда у вас возникнет соблазн написать что-то вроде
GCC_PREPROCESSOR_DEFINITIONS[config=*] = CONFIGURATION_$(CONFIGURATION) $(inherited)
GCC_PREPROCESSOR_DEFINITIONS[config=Debug] = DEBUG=1 CONFIGURATION_$(CONFIGURATION) $(inherited)
К сожалению, это не сработает, но добавление второго объявления в файл, загружаемый только конфигурацией Debug, будет правильно отменять настройку.
Ответ 6
Как указано в других ответах, до Xcode 10 файлы xcconfig не могли просто наследовать и расширять значения друг друга. Но,
Начиная с Xcode 10, xcconfig теперь работает так, как можно было бы ожидать: $(inherited)
фактически расширяется до ранее определенного значения переменной.
Если файл .xcconfig содержит несколько назначений одного и того же параметра сборки, более поздние назначения, использующие $(inherited)
или $(<setting_name>)
будут наследоваться от более ранних назначений в .xcconfig. Унаследованная система сборки приводила к тому, что каждое использование $(inherited)
или $(<setting_name>)
пропускало любые другие значения, определенные в .xcconfig. Чтобы определить, влияет ли это улучшение на ваш .xcconfig, запустив defaults write com.apple.dt.XCBuild EnableCompatibilityWarningsForXCBuildTransition -bool YES
в терминале, и Xcode выдаст предупреждение об этой ситуации.
(Примечания к выпуску Xcode 10 beta 1)
Так, например, даны два простых файла .xcconfig:
// Generic.xcconfig
OTHER_SWIFT_FLAGS = $(inherited) -DMY_GENERIC_FLAG
// Debug.xcconfig
#include "Generic.xcconfig"
OTHER_SWIFT_FLAGS = $(inherited) -DMY_DEBUG_FLAG
Предполагая, что ваш проект использует Debug.xcconfig для своей конфигурации Debug, вы получите ожидаемое значение -DMY_GENERIC_FLAG -DMY_DEBUG_FLAG
для OTHER_SWIFT_FLAGS
.
(вместо просто -DMY_DEBUG_FLAG
в Xcode 9 и более ранних выпусках)
Новое поведение довольно простое: $(inherited)
просто заменяется на ранее определенное значение переменной, если оно есть.
Так что в предыдущем примере, если мы #include
оператор #include
, мы получим следующий файл xcconfig:
// Merged xcconfig files after resolving #include
OTHER_SWIFT_FLAGS = -DMY_GENERIC_FLAG
OTHER_SWIFT_FLAGS = $(inherited) -DMY_DEBUG_FLAG
- В первой строке значение
OTHER_SWIFT_FLAGS
равно -DMY_GENERIC_FLAG
($(inherited)
расширяется до нуля, потому что это первое определение OTHER_SWIFT_FLAGS
мы сталкиваемся 1). - Во второй строке
OTHER_SWIFT_FLAGS
если перезаписано, и его значение теперь -DMY_GENERIC_FLAG -DMY_DEBUG_FLAG
(его предыдущее значение + вновь добавленный флаг).
На более сложной установке xcconfig все может выглядеть так:
// First.xcconfig
OTHER_SWIFT_FLAGS = $(inherited) -DMY_FIRST_FLAG
// Second.xcconfig
OTHER_SWIFT_FLAGS = $(inherited) -DMY_SECOND_FLAG
// Last.xcconfig
#include "Generic.xcconfig"
OTHER_SWIFT_FLAGS = $(inherited) -DMY_LAST_FLAG
// Merge.xcconfig
#include "First.xcconfig"
#include "Second.xcconfig"
OTHER_SWIFT_FLAGS = $(inherited) -DMY_INTERMEDIATE_FLAG
#include "Last.xcconfig"
Предположим, на этот раз мы используем Merge.xcconfig в нашей конфигурации.
Разрешенное значение для OTHER_SWIFT_FLAGS
будет тогда -DMY_FIRST_FLAG -DMY_SECOND_FLAG -DMY_INTERMEDIATE_FLAG -DMY_LAST_FLAG
.
Поначалу это может показаться удивительным, но на самом деле это имеет смысл: после разрешения #include
мы получим следующий xcconfig:
OTHER_SWIFT_FLAGS = $(inherited) -DMY_FIRST_FLAG
OTHER_SWIFT_FLAGS = $(inherited) -DMY_SECOND_FLAG
OTHER_SWIFT_FLAGS = $(inherited) -DMY_INTERMEDIATE_FLAG
OTHER_SWIFT_FLAGS = $(inherited) -DMY_LAST_FLAG
Окончательное разрешенное значение - это значение, определенное в последней строке, которое равно -DMY_LAST_FLAG
плюс значение, унаследованное от предыдущей строки -DMY_INTERMEDIATE_FLAG
т.д. И т.д.
Обратите внимание, что, естественно, если вы забудете $(inherited)
в одном из определений, вы разорвете цепочку наследования и получите значения только из нижних определений, до определения без $(inherited)
.
1 Можно ожидать, что файл xcconfig унаследует предыдущие значения, определенные на уровне проекта, но, похоже, это не так
📡 Начиная с Xcode 10 beta 1, кажется, что редактор настроек сборки неправильно разрешает правильное значение для переменных, определенных в файлах xcconfig, и отображает значения, как если бы они были разрешены со старым поведением до Xcode 10. Я подал rdar://40873121 относительно этого (https://openradar.appspot.com/radar?id=4925869923500032).
Ответ 7
Это работает для меня в Xcode 2.4.1:
GCC_PREPROCESSOR_DEFINITIONS = "$(GCC_PREPROCESSOR_DEFINITIONS) NEW_VALUE"
Вам нужно иногда разрешать несколько секунд между редактированием файла конфигурации и изменением в целевой информации о сборке.
Ответ 8
Вы хотите использовать заполнитель $(унаследованный) для представления значения, унаследованного от более низких уровней, например
GCC_PREPROCESSOR_DEFINITIONS = "$(inherited) NEW_VALUE"