前提・実現したいことSVNのプロジェクトをMac(ver 10.13.4)にクローンしなければならなくて、Sourcetreeを使ってクローンしようと試みています。ローカルにデータは少し入った様なのですが、(いくつかのファイルで止まってしまっている様です、、)しかし、ずっとエラ. I'm trying to use husky precommit with sourcetree. The precommit command is run but i get the following error: Does anybody know what's wrong? OS: macOS Mojave 10.14 Node: 10.13 $ which node: /usr/local/bin/node npm: 6.4.1 $ whick npm: /usr/local/bin/npm. STEP 3: Restart SourceTree and clone remote repo using URL. Restarting SourceTree is needed so that SourceTree picks the new key. STEP 4: Copy the SSH URL provided by GitLab. STEP 5: Paste the SSH URL into the Source URL field of SourceTree. These steps were successfully performed on Mac OS 10.13.2 using SourceTree 2.7.1. How to setup python environment on macOS. On this page I describe how to setup python environment on macOS Catalina (10.13). When I upgrade to a next major version of macOS it's almost always some problems appear - some tools stop working, eapecially if you use your system for software development.
tl;dr
(see table)Sourcetree 3.2.1 should be supported on macOS 10.13 and is available from the download archives page. If for some reason you're not able to access all the versions.
Test | Result |
---|---|
Link the library project into the project’s Assets folder, without remote git repo? | Doesn’t work: For submodules we need a remote-origin |
Link the library project into the project’s Assets folder with remotes repo? | Doesn’t work: Unity doesn’t like a complete sub-project in the Assets folder. |
Maybe git-subtree does the trick? | Doesn’t work: Subtree is more or less an import and not a link. |
Use the new Unity PackageManager features? | Doesn’t work: Complicated and doesn’t work with older Unity versions |
Use a submodule and a symbolic link? | It works! |
Submodules can be a great tool for sharing library code and I like to make use of them when working with Unity. In this article I share my notes on my experiments around git submodules in Unity projects.
The development model I have in mind looks like this: I like to have on or more product project sharing one or more library project and want to able to commit, push and pull in each of them. Also I want to have reproducible connections between the project and the library code. So if I check out an old commit of a product it shall checkout the matching library project commit as well. All this without Unity plugins or the need of none-git work before or after the code change. No Unity packaging. No extra steps when committing.
To use this model one has to solve one issue: Unity (in it’s current state) forces the game creator to put all source-codes and assets into one folder named:
Assets
. As I had several ways in mind how I could solve this I took the liberty to write down my approaches and share them here.I’m using Unity 2017.4.11f1, macos 10.13.6 and Sourcetree 3.0.0.
Approach
The test case is made of one product project and one library project. Both are complete Unity projects. In this approach I like to see if I can simply link the library project as a sub-folder into the
Assets
folder of the product project.Being lazy I try this without using a remote git-repo.
The initial structure looks like this:
First I want each project to be in it’s own repository. Then I like to inject lib1 as a submodule into proj1:
The result should look something like this:
Setup
To set this up we first create the project structure. Then we need to create the repositories in each folder. I use Sourcetree for this.
For each folder:
- Create a repo
- Create a .gitignore
- Commit (master branch)
Now we have two repos with one commit in each.
The next step is to link lib1 into the main project. For that I do in Sourcetree this:
- Open proj1
- Right-Click on submodules -> Add Submodule
- Source Path: Navigate to the root folder of lib1
- Set local relative path (in proj1):
Asssets/lib1
- Say “okay”
- Two modified files appear in proj1 (they are already staged)
- We need to commit the changes
Basically that’s it. Now the library project is part of proj1.
Be careful: If you create a submodule in Sourcetree it automatically stages the files for you. You only have to commit them. Never unstage the initial submodule files. I incidentally unstaged them and created an incompatible state and I had to setup everything again.
Testing
Let’s see how this setup works and do some tests.
- Use case: modify a file in lib1 (the lib project itself not in the submodule)
- Edit lib1_file.txt
- The change is visible in lib1
- I commit the change in lib1
- Let’s see if we can get that into proj1/lib1
- proj1/lib1 shows one pull request.
- Pulling brings the change into proj1!
- Use case: modify a file in proj1/lib1
- Edit lib1_file.txt
- The change is visible in proj1 (submodule changed)
- The change is also visible in proj1/lib1, in the submodule.
- I can commit the change in proj1/lib1, in the submodule.
- However, I can’t push.
- Reading the error message it’s because the origin is a bare repository. Bare Repository. Welp. I don’t really get it, but what I get that it is related to the fact that I don’t use a remote origin.
Result
- I got exactly the desired structure.
- I can make changes in the lib1 project.
- I can read all changes in proj1/lib1
- I cannot write changes from proj1/lib1 to lib1 (commit: yes, pull: no)
- For submodules we need an remote-origin
Approach
Create proj1, lib1 and create a remote repository for both of them. Then basically check if we get around the issue of Test 1.
Setup
Generate the following structure:
- We create both as local repositories
- We create the counter parts on a remote git
- We combine the projects by setting up the remote repository
- Now we add lib1 to proj1, however this time the remote repo
- We commit the changed module files. DON’T UNSTAGE HERE ;)
- We commit the changes to the remote as well
That’s it. Now let’s test.
Testing
- Use case 1: modify a file in lib1 (the lib project itself not in the submodule)
- changed lib1_file.txt in lib1 folder
- comitted the change
- pushed the change
- proj1/lib1 does not show the change. Which is what we want.
- opening the project proj1/lib1 shows that we can pull a change
- this changed the proje1/lib1 submodule. This makes sense as our pull changed the commit-pointer we have in proj1.
- we commit and push that submodule too
- Now we have the modified file in the origin as well
- Use case 2: modify a file in proj1/lib1
- changed lib1_file.txt in proj1/lib1 folder
- The change becomes visible in proj1 lib1 submodule. 3 little dots.
- We open proj1/lib1. It shows the modified content
- We commit the changes
- We push it to the origin.
- This time it works!
- Going back to proj1/lib1 we see the submodule has changed
- We commit that and we are done in proj1.
- If we check in lib1 we can see the modification in the origin.
- Use case 3: Test in unity
- Open proj1 in Unity
- Unity says: You are trying to import an asset which contains a global game manager. This is not allowed.
Results
- Git submodule setup works.
- We can have two repositories, link them together and work in both of them.
- We can modify content in the library and also in the project.
- Both can fetch from each other.
- This supports a structure where we can have one or more projects share some nice generic libraries that we use a lot and update from time to time.
- Unity doesn’t like a complete sub-project in the Assets folder.
- The UnityPackageManager or ProjectSettings cause this to fail. If we had a setup which would ignore those it would work.
Approach
Using submodules we can import an entire library project into another project. However, our library folder is packed with the entire Unity project. In Test 2 I found out Unity doesn’t like that at all.
My next thought was: “maybe we can create a submodule-link that points only to a subfolder of the library”. But from what I read it seems we can’t use a subfolder in git-submodules.
There is another option in git called Subtrees. Maybe they can help? In this test I will check if it is possible to use a linked subtree to only the get
Assets
content of lib1 into proj1 and still being able to update content for both.Setup
The result should look like this:
- We create a new parent project: proj1
- We set it up as a local git repo
- We do the initial commit
- We add the remote lib1 as subtree: rightclick on submodule -> Add/Link Subtree
- We select the lib1 remote project with the Asset path:https://
.git/Assets - Squash commit? https://stackoverflow.com/a/35704829. Not now.
Testing
- Doesn’t work? I can’t find any content in the subtree folder
- While reading into this. I realized it’s the wrong tool.
Results
- Bad approach. Subtree’s isn’t the right tool here:
- Subtree is more or less an import and not a link. (details.)
- Too bad :(
Approach
Consider Unity Package manager.
Result
- Hm… reading into all this I’m not really motivated to follow that approach.
- Also I need a solution that works in older Unity versions too (some clients have this requirement).
Approach
In this test I like to follow the approach from prime31. I setup the submodule in proj1. However, I don’t put it into the
Assets
folder. Instead we use a folder next to Assets
. Then we link the content of that directory as a symbolic link into the Assets
folder.Setup
We create two Unity projects.
Then we link the entire lib1 project into a subdirectory and link the content of lib1. Like this:
- Create two Unity projects
- Create the local git repositories
- For lib1 we create and push it to an remote-origin
- We create a submodule folder in proj1
- We initialize lib1 as submodule in proj1/submodules
- Now we link the folder of lib1 assets using:
Testing
- Creating link succeeded
- The structure looks as expected
- Using
pwd
inproj1/Assets/lib1
looks alright - Open proj1 in Unity works without issues
- Sourcetree shows
proj1/Assets/Lib1
as a new folder. Which is fine - Committing
proj1/Assets/Lib1
works without issue - Now let’s edit a file in lib1, commit and push it
- Let’s see if we can pull the change in
proj/lib1
- Open
proj1/lib1
in Sourcetree shows that we can pull something - Pull
proj1/lib1
- Checking Sourcetree it works perfectly!
- Checking Unity it works perfectly!
- In Sourcetree I see the changed submodule-link
- In Unity I see the updated file
- Now let’s check if we can modify a file in
proj1/Assets/Lib1
- In Sourcetree it shows modified submodule content. Perfect!
- Open
proj1/lib1
in Sourcetree shows the modified file. Let’s commit that
Result
- It just works
Final words
Using symbolic links we have fully working solution: Git-submodules in Unity with only a little headache. We can work on one or more library from multiple projects.
The only downside is a little extra work every time we add or remove a submodule to update the symbolic link. This introduces some problems when it comes to automatic building. Also it requires us to consider platforms. On Win32 this won’t work with the same commands. Using git-hooks this maybe can be automated.
In the end it’s an practmatic approach and I like it. Thanks prime31 :)
Starting with Xcode 4 and through at least Xcode 6, the internals of the Xcode project have beenconsistent. The only evolution has been to add new object types to the xcodeproj file.
There are two objects - the workspace (.xcworkspace) and the project (.xcodeproject). As ofXcode 4, the workspace can now be a visible separate object.
An Xcode workspace always exists, and may be external to an .xcodeproj, or embedded within one. Wewill defer talking about embedded .xcworkspace directories for a bit.
Xcode workspaces are directories with the .xcworkspace extensionthat the Mac OS X desktop presents as packages.In the package directory, the important file is contents.xcworkspacedata. A workspace is just a list ofcontained projects; there is no other metadata.
The simplest possible .xcworkspace has an on-disk structure like this:
and the
contents.xcworkspacedata
file, containing the actual workspace data, looks like this:Sourcetree Macos 10.13.6
This workspace has nothing in it, but Xcode will open it up. Of course, once you open it up, Xcodewill likely generate other metadata like an
xcshareddata/
directory containing source controlinformation, and an xcuserdata/
directory with user interface settings (window positions andso on). That metadata isn’t used for building, so we’ll ignore it here.A better example is from cppget, which has an Xcode workspace (albeit currently generated withPremake and not hand-made). The current directory structure for this package is as follows:
This is the contents of the workspace file,
cppget.xcworkspace/contents.xcworkspacedata
:The document root object is
<Workspace>
. The root object has a version
attribute(always observed to be 1.0, indicating that the workspace file format hasn’t been changing),and then an array of child nodes of type <FileRef>
and/or <Group>
.Each FileRef
node has a single attribute, which is the location of the contained item.The value of the attribute is a string with either a “self:” prefix or a “group:” prefix (theself prefix is used when the .xcworkspace is embedded, see below). In thecase of the “group” prefix, this auto-creates a group containing just this item in the workspace.Groups can contain Groups or FileRefs, but FileRefs are just leaf nodes.In the example above, the source code structure looks like this:
explaining the relative paths (getting to
vendor
from project
requires ./vendor
).I say “item” because you can put anything in an .xcworkspace. Normally, you put projects intothe workspace, but you can also put individual files, or directories. These will only be used forbrowsing and search; to build, you need an .xcodeproj.
There is no idea of “main” project file. In this case, there is a main project file (cppget.xcodeproj)that builds an executable, and then 6 additional projects that build libraries (each in the form of aC/C++ package). When you open this workspace in Xcode, it in turn reads information from each projectreferenced in the workspace file. All the data displayed in the GUI comes from each .xcodeproj,the workspace itself contains no metadata.
There are other files in a typical .xcworkspace bundle. Usually, these are user-specific files thathold settings. We’ll defer covering those to some other time, as none of them alter the meaningof the project files themselves.
Adding a project to a workspace
Because a workspace just collects paths to projects, adding a project to a workspace isvery simple - just add a FileEntry node pointing to the project.
From C++, we would:
- read the XML with our preferred XML parser
- look to see if there is already a FileRef referring to our project
- if yes, done
- if not, add a new node
Note that we have no “update” ability; either we find the exact path to our new project alreadyin the workspace, or we add it. This means you need to take some care to have canonical paths.
The node we are adding follows the form
e.g. the only data is the value for the
location
attribute, and the attribute value is prefixedwith either group:
or self:
.So, for example, assuming you were using RapidXML,your code might look like this. I have parsed the workspace into a data structure that haspulled FileRefs out into a vector for easy manipulation, but then the XML itself has to bemanipulated to add a new FileRef.
Perhaps a different XML library would have cleaner syntax. It’s a tradeoff.
Like the workspace, an Xcode project is a bundle containing one or more files. The most importantand only required file is the
project.pbxproj
file.The simplest possible project looks like this
The
project.pbxproj
file is an Xcode-specific file format using the text plist format, which camefrom NeXt and is now only used by legacy programs - and Xcode. Or so the internet claims.Also interestingly, Xcode by default is reading and writing the ASCIIplist format, but can also read the XML plist format. But everyone seems to be creating the textversion, so we’ll stick with that (because the XML plist format is pretty hard to read).For a bigger example, let’s look at the .xcodeproj from cppget:
As with .xcworkspace directories, Xcode puts configuration data inside the project directory, whichwe will ignore, because it doesn’t bear directly on workspaces and projects at the build level.
The root of an Xcode project file is a dictionary. Looking at
cppget.xcodeproj/project.pbxproj
,we see this:archiveVersion
has always been 1. And classes
is usually empty (always?).objectVersion
indicates the project format::- 39: something really old, when the project files were called .xcode
- 42: Xcode 2.4
- 44: Xcode 3.0
- 45: Xcode 3.1 compatible
- 46: Xcode 3.2 compatible
- 47: Xcode 6.3 compatible
The most important key is
rootObject
, which tells us which object represents the project. The entireproject file is a tree, with rootObject
at the top. The value of rootObject is an Xcode objectidentifier that is an index into the objects
dictionary, which is a PBXProject object.Xcode object identifiers
Objects have a 12-byte or 24-byte identifier, written as 24 or 48 hexadecimal characters; we’ll callthem GUIDs here, although this does not imply similarity to other things people call GUIDs. ObjectGUIDs need to be unique inside a project file, and also need to be unique among the set of projectfiles that are opened at the same time in Xcode. This means an effort should be taken to make themunique across all projects. I don’t know how true that needs to be, because most UUIDs are only usedlocally to the project that they are found in.
There’s an interesting competing need that Premake satisfies but the Xcode algorithm does not, and thatis that if you regenerate a project, it would be nice to have the same GUIDs, so that diffs are minimized(e.g. when checking in to source control).
Premake uses a simple algorithm that is completely deterministic and relies on “paths” being unique.Each element that gets a GUID has a sequence of strings that creates a virtual path, and this path ishashed with a variant of the DJB algorithm. For example, creating a target ID uses the path[projectname, configname, “target”]; this whole thing is turned into a string and hashed to get aUUID. Since this is deterministic, regenerating the project will create the same UUID. The assumptionis that things that are named the same are the same thing. See uses of
xcode.newid
inpremake/premake-xcode,and refer topremake-core/src/host/string_hash.cfor the low-level C code.Xcode uses the algorithm linked here: PBXProj Identifiers. This basically creates a memorized per-user structure that used with current time each time anew identifer is created. This code was apparently reverse-engineered from DevToolsCore.framework.This is safer, but requires some extra work if you want to minimize change on project regeneration.
Xcode objects
All objects in the
objects
directory have an isa
that indicates the type of object. As of Xcode 3.2,there are the following object kinds- PBXAppleScriptBuildPhase
- PBXBuildFile
- PBXContainerItemProxy
- PBXCopyFilesBuildPhase
- PBXFileReference
- PBXFrameworksBuildPhase
- PBXHeadersBuildPhase
- PBXGroup
- PBXNativeTarget
- PBXProject
- PBXReferenceProxy
- PBXResourcesBuildPhase
- PBXShellScriptBuildPhase
- PBXSourcesBuildPhase
- PBXTargetDependency
- PBXVariantGroup
- XCBuildConfiguration
- XCConfigurationList
PBXProject
The root object points to an instance of PBXProject. Typically, there is just one in an .xcodeprojfile. The one for cppget looks like this:
Thoma bravo sophos. The
buildConfigurationList
key points to a XCConfigurationList object, which is an arrayof XCBuildConfiguration objects. Many projects have a Debug and Release configuration, butthere are no mandatory configurations; projects can declare ones specific to their needs.See below: there are two sets of config, one for projects, and the other for targets. Thisis distinguished in the Xcode GUI but can be a subtle difference, since many settings areshared.The
mainGroup
key points to a PBXGroup object, which is the list of files that are builtfor this project. As seen below, this is a list of individual items as well as other groups.A group is just a decorative container, but Xcode will use standard names for some groupslike Products and Frameworks and Projects. Every file that contributes to the build willbe traced from mainGroup
.The
targets
key points to a list of targets that this project creates. These are:- PBXNativeTarget: a build target that makes a binary (library or executable)
- PBXAggregateTarget: a build target that aggregates several others
- PBXLegacyTarget: (not supported any more?)
PBXGroup
A PBXGroup object is a list of zero or more:
- PBXFileReference: a group can contain a reference to a file; this can be a source file, a framework, a build artifact (like a binary), or even another project.
- PBXReferenceProxy: a group can contain a reference to something from outside the project; this is usually an object built by a dependent project.
- PBXGroup: a group can contain another group, and this shows up as a sub-folder in the UI.
As an example:
This group has the name Products, has its source tree as the group itself, and then has zero or more children.Typically groups are not empty.
PBXFilereference
All physical items are identified by PBXFileReference objects.
A
sourceTree
entry is the location where this object can be found. Typically, this is <group>
, meaningthat the location is inside the group containing this PBXFileReference (or the project itself). Sometimesthe sourceTree
will be a variable like BUILT_PRODUCTS_DIR
, which is either defined in the project itselfor externally (say as a default by Xcode).The majority of entries will be source code, with a
lastKnownFileType
indicating the file type that Xcodebelieves the file has. This is a hierarchy, so all source code tags start with sourcecode.
; C++ filesbegin with sourcecode.cpp.
, and so on. So a C++ source file would be sourcecode.cpp.cpp
, and a Cheader file would be sourcecode.c.h
.Tincta. Some entries will indicate built objects, like an executable. These have an
explicitFileType
entry with avalue such as compiled.mach-o.executable
.Some entries will indicate external items. These have a
lastKnowFileType
of 'wrapper.pb-project'
, and a path
pointing at the project itself, located relative to sourceTree
. In this case a sourceTree
of SOURCE_ROOT
indicates a variable set in Xcode pointing to the workspace or project.Some entries indicate Mac OS X frameworks, either installed by the system (like LDAP.framework), or customto the project. In this case,
lastKnownFileType
is wrapper.framework
and path
points to the path forthe framework relative to sourceTree
. In the example below, the source tree is SDKROOT
, which ispredefined by Xcode to point to the system SDKs.PBXNativeTarget
A PBXNativeTarget objects describes how to build a native target. This is the various build phases,the output name
In this example, this is an executable binary, as indicated by
productReference
pointingto a PBXFileReference that is a compiled.mach-o.executable
, but also by productType
being “command line tool”, com.apple.product-type.tool
. Mordhau g2a.Note that a PBXNativeTarget has its own XCConfigurationList; these are named the sameas the project configurations, but contain target-specific information. See below forthe cascade order for config.
For example, the debug configuration has this as its target config:
PBXBuildPhase
There are at least these 7 kinds of build phases
- PBXAppleScriptBuildPhase: run an AppleScript
- PBXCopyFilesBuildPhase: copy files
- PBXFrameworksBuildPhase: link frameworks
- PBXHeadersBuildPhase: build precompiled headers
- PBXResourcesBuildPhase: build resources
- PBXShellScriptBuildPhase: run an sh shell script
- PBXSourcesBuildPhase: build sources
Of these, the most interesting to us is PBXSourcesBuildPhase.
PBXSourcesBuildPhase
Without a PBXSourcesBuildPhase, an Xcode project is just an expensive container.
This is just a list of PBXBuildFile entries, with a note as to whether this is donein all builds or just for deployment post-processing (e.g. a PBXCopyFilesBuildPhasewould typically have this set).
PBXBuildFile
This is the heart of building something in Xcode. There are several distinct kinds offile builds.
First is source code. This just points to a PBXFileReference object that contains theinformation actually needed to build it. The indirection is no doubt useful to Apple,since the file entry is also used in a PBXGroup for display purposes.For convenience, we show the PBXBuildFile entry and its associated PBXFileReference entry.
Not everything is a source code file. We also link static libraries built from elsewhere.Note in this case that the reference is to a PBXReferenceProxy, indicating that thisfile is from a dependent project, which is itself pointed to by a PBXContainerItemProxy,which finally ends up at a PBXFileReference.
I don’t know what
remoteGlobalIDString
is, I can’t find that GUID in any project inmy hierarchy. Premake just assigns a value to it based on the hash of the path name (itsidea of the hierarchy to this point).Frameworks are semi-magic libraries with versioning and header files used with thelibraries. For the build phase, this is linking a framework, so it just ends up directlyat the PBXFileReference, no indirection needed.
XCConfigurationList
An XCConfigurationList object is just a list of XCBuildConfiguration objects.
The
defaultConfigurationName
key indicates which configuration, by name, is the one topick as the default when a project is opened for the first time.The
defaultConfigurationIsVisible
key, if set to non-zero, shows the default configurationinformation in the UI.Sourcetree App Download
XCBuildConfiguration
An XCBuildConfiguration object contains the settings that describe the configuration. At itsminimum, a build configuration looks like this:
This is an example where a name needs to be unique, because, for example, the UI will look upa configuration by name and not by UUID. Although, it must be doing some disambiguation,because in a typical project there are two distinct XCConfigurationList objects, one forthe project object, and one for the PBXNativeTarget object.
Any settings not specified here come from Xcode defaults. There is a cascade for configuration.Inheritance is performed in the following order (lowest to highest precedence):
- platform defaults
- project
- xcconfig file for project
- target
- xcconfig file for target
Value assignment is performed in the following order (lowest to highest precedence):
- platform defaults
- xcconfig for project file
- project
- xcconfig for target
- target
The distinction is due to handling of inheritance. TBD: explain.
It is possible to just have an .xcodeproj visible to the desktop, and have a .xcworkspace directoryinside the .xcodeproj directory. In this case, the workspace is always called
project.xcworkspace
and is at the root directory of the project. This is what you get if you use the Xcode wizard tocreate a new project first, instead of creating a workspace and adding projects to it.The simplest possible arrangement is to have the following:
where
project.xcworkspace/contents.xcworkspacedata
look like this:The
self
tag points to the top level of the one.xcodeproj
directory. The project.pbxproj
isas detailed above.Write a DTD for
contents.xcworkspacedata
files. And maybe a grammar; are DTDs comprehensiveenough that they can serve as prescriptive grammars? Looks like not really. Or maybe an XML Schema?Compile a list of more Xcode versions matched up againts
objectVersion
. What was before objectVersion 45?A few Xcode projects to test a xcworkspace parser against:
A few Xcode projects to test a xcodeproj parser against:
There is no formal documentation. Others have done their share of reverse engineering the project format,for their needs. Premake and CMake generate project files, CocoaPods is a package manager for Mac OS/iOSdevelopers, and so on. Here is a collection of what other people have written.
A dive into Xcode projects and workspaces.
Xcode Project File Format.
A series of articles on the Xcode project format:
- Xcode project files (bsxtools) - points to Github repo danwr/bsxtools
OpenOffice.org XML File Format 1.0. An example of a complex XML file format.
A number of projects that can manipulate Xcode projects
- XCoder. A no-longer-maintained Ruby project to manipulate Xcodeprojects. Lots of comments in the source, though.
- Xcodeproj. This is the library used by CocoaPods tocreate static libraries from scratch for iOS and OSX. Github is https://github.com/CocoaPods/Xcodeproj
- node-xcode. Includes a PEG grammar.
- kronenthaler/mod-pbxproj. Python.
- appsquickly/XcodeEditor.
CocoaPods. This is a package manager for Swift and Objective-C projects. Sourcecode is on Github at CocoaPods/CocoaPods.
Old-Style ASCII Property Lists. Except this doesn’t seem to match observed project.pbxprojfiles.
Xcode Build Settings Reference.