xcconfig
Build configuration对应一个xcconfig文件,通过这个文件可以不打开xcode达到修改build configuration的目的。
1、语法
-
注释://可以添加注释
-
引入其他文件,使用#include来引入
-
变量:以_、大写或小写字母开头,可以包含下划线、数字、字母
-
赋值:通过”=“,将值付给变量
-
行:每行作为单独的一项,不以”;“为分割符
-
字符串,使用”或者‘
2、变量赋值
(1)覆盖
通过在 xcconfig 文件中重新分配该变量的值,可以覆盖在项目或目标级别上设置的构建设置变量。如下面设置,-ObjC 值将被新值 -framework Security 覆盖。
// 项目文件中设置的变量
OTHER_LDFLAGS = -ObjC
// lib.xcconfig
OTHER_LDFLAGS = -framework Security
(2)继承
可以使用$(inherited)使用已经存在的值,例如下面的设置,编译完成之后OTHER_LDFLAGS的值就是-ObjC -framework Security
// Variable set in the project file
OTHER_LDFLAGS = -ObjC
// lib.xcconfig
OTHER_LDFLAGS = $(inherited) -framework Security
关于变量赋值的优先级问题,可以参考Build Setting Inheritance.
3、条件变量
除了常规变量分配之外,如果满足一组条件,我们还可以给变量赋值。 例如,根据您正在构建的操作系统版本更改使用的链接器标志。 条件的值检查支持通配符*来进行求值。需要注意的是,条件赋值优先于其他赋值。 例如:
FOO = bar
FOO[sdk=macosx*] = buzz
如果target在iOS和mac上都可以运行,那么FOO的设置,在不同的机型上运行的值不同,如下
|-- FOO = bar
|-- Any Mac SDK = buzz
|-- Any iOS SDK = bar // this is going to inherit from the original assignment of FOO
注意:还可以多个条件组合结合来赋值,例如
FOO[sdk=macosx*][arch=i386] = bar // This only gets assigned if building against an OS X SDK
// and targeting 32bit Intel architecture
(1)SDK
sdk条件变量的分配基于$(SDKROOT)的值来操作
FOO[sdk=macosx10.8] = ... // 针对10.8 SDK ,设置的FOO的值
FOO[sdk=macosx10.9] = ... // For building against the 10.9 SDK
FOO[sdk=macosx10.10] = ... // For building against the 10.10 SDK
FOO[sdk=macosx*] = ... // For building against any Mac OS X SDK
(2)Arch
arch条件变量的设置基于$ (CURRENT_ARCH)来自于 $ (ARCH)
FOO[arch=i386] = ... // For building to target 32bit Intel
FOO[arch=x86_64] = ... // For building to target 64bit Intel
(3)config
configuration条件变量的设置基于$(configuration),还可以结合[SDK=*]或者[arch=*]来设置值,例如下面
ONLY_ACTIVE_ARCH[config=Debug] = YES
ONLY_ACTIVE_ARCH[config=Debug][sdk=*][arch=*] = YES //结合[SDK=*]或者[arch=*]来设置值
4、变量替代
给变量赋值可以直接使用值设置,也可以使用其他变量来赋值(一般用于比较复杂的条件变量),例如下面使用变量赋值的方式
HELLO = hello
WORLD = world
FOO = $(HELLO) ${WORLD} // The value of FOO is "hello world"
例如,有一个工程里面有一个app 的target和一个unit测试的target,你想做到在编译的时候改变target和unit target的版本号,可以创建两个单独的xcconfig,一个是taget的,一个是unit target的,另外也可以基于一个变量替换给变量赋值
CURRENT_PROJECT_VERSION_app = 15.3.9 // Application version number
CURRENT_PROJECT_VERSION_xctest = 1.0.0 // Unit Test version number
CURRENT_PROJECT_VERSION = $(CURRENT_PROJECT_VERSION_$(WRAPPER_EXTENSION))
Xcode 将通过首先解析 $(WRAPPER_EXTENSION)
的值来给CURRENT_PROJECT_VERSION分配值。对于构建应用程序,此变量的值将是 app,而对于单元测试,它将是 xctest。根据$(WRAPPER_EXTENSION)
的值,CURRENT_PROJECT_VERSION的值是对$(CURRENT_PROJECT_VERSION_app) 或 $(CURRENT_PROJECT_VERSION_xctest) 的变量引用,并将与其相关的相应值分配给 CURRENT_PROJECT_VERSION。如果 $(WRAPPER_EXTENSION) 设置为空时,由于没有对该值的声明,所以不会分配任何内容来覆盖 CURRENT_PROJECT_VERSION 的值。
注意:有一种方法可以解决无效字符名称的限制。如果在 Xcode 项目文件中编辑 project.pbxproj 文件并通过将名称括在双引号中向相关 XCBuildConfiguration 对象添加新值,则变量将注册为有效并显示在“用户定义”设置部分下Xcode 编辑器。虽然这些设置是可见的并且可用于替换项目或 xcconfig 文件中其他地方的值,但这是不支持的。使用包含无效字符的名称设置将无法正确导出以用于构建系统的其他部分。
5、Build Setting的继承
xcode将build Settings设置为不同的level,在构建的时候从build Settings中获取单个的解析值,每个构建设置变量的值都是从上一级继承而来。
继承顺序按照下面流程进行
- Platform defaults
- Project file
- xcconfig file for the Project file
- Target
- xcconfig file for the Target
值的设置按照下面的流程
- Platform defaults
- xcconfig for the Project file
- Project file
- xcconfig for the Target
- Target
例如,在project文件里面target里定义PRODUCT_NAME是MyApp,工程里面定义了一xcconfig,如下
//
// Config.xcconfig
//
PRODUCT_NAME = testing
PRODUCT_NAME_ORIGINAL = $(PRODUCT_NAME) // The value of `PRODUCT_NAME_ORIGINAL` would seem to be "testing"
// as assigned by the line before in the xcconfig file. The value
// is "MyApp", because the inheritance takes prescedence
// over assignment.
// ...
FOO_MyApp = MyAppsName
FOO_testing = MyAppsNewName
BAR = $(FOO_$(PRODUCT_NAME)) // This will also use the value "MyApp" for "PRODUCT_NAME",
// and resolve to be "$(FOO_MyApp)".
继承只在不同的level之间起作用,在同一级别执行的变量赋值将覆盖之前的赋值。 不能在 xcconfig 文件中使用 $(inherited) 从导入的 xcconfig 文件中获取为变量分配的值。 要使用该值,您必须使用单独的名称并在赋值中引用这些变量。