Reputation: 3817
xcode one has the ability to set a default build configuration to use for xcodebuild. E.g. Release or Debug
Yet when I try this on my project, it looks as it is not used as it said it should
$ echo $DEVELOPER_DIR
/Applications/Xcode6.0.1.app/Contents/Developer
$ xcodebuild -list
Information about project "CocoaPodsExample":
Targets:
CocoaPodsExample
CocoaPodsExampleTests
Build Configurations:
Debug
Release
If no build configuration is specified and -scheme is not passed then "Release" is used.
Schemes:
CocoaPodsExample
Given a Debug default configuration:
$ git grep defaultConfigurationName
CocoaPodsExample.xcodeproj/project.pbxproj: defaultConfigurationName = Debug;
CocoaPodsExample.xcodeproj/project.pbxproj: defaultConfigurationName = Debug;
CocoaPodsExample.xcodeproj/project.pbxproj: defaultConfigurationName = Debug;
Pods/Pods.xcodeproj/project.pbxproj: defaultConfigurationName = Debug;
Pods/Pods.xcodeproj/project.pbxproj: defaultConfigurationName = Debug;
Pods/Pods.xcodeproj/project.pbxproj: defaultConfigurationName = Debug;
specifying DEFAULT configuration uses Debug (EXPECTED)
$ xcodebuild -scheme CocoaPodsExample -workspace CocoaPodsExample.xcworkspace -configuration DEFAULT build | grep "CONFIGURATION"
=== BUILD TARGET Pods-AFNetworking OF PROJECT Pods WITH THE DEFAULT CONFIGURATION (Debug) ===
=== BUILD TARGET Pods OF PROJECT Pods WITH THE DEFAULT CONFIGURATION (Debug) ===
=== BUILD TARGET CocoaPodsExample OF PROJECT CocoaPodsExample WITH THE DEFAULT CONFIGURATION (Debug) ===
=== BUILD TARGET CocoaPodsExampleTests OF PROJECT CocoaPodsExample WITH THE DEFAULT CONFIGURATION (Debug) ===
and not specifying the configuration uses Debug (EXPECTED)
$ DEVELOPER_DIR=/Applications/Xcode6.0.1.app/Contents/Developer xcodebuild -scheme CocoaPodsExample -workspace CocoaPodsExample.xcworkspace build | grep "CONFIGURATION"
=== BUILD TARGET Pods-AFNetworking OF PROJECT Pods WITH CONFIGURATION Debug ===
=== BUILD TARGET Pods OF PROJECT Pods WITH CONFIGURATION Debug ===
=== BUILD TARGET CocoaPodsExample OF PROJECT CocoaPodsExample WITH CONFIGURATION Debug ===
=== BUILD TARGET CocoaPodsExampleTests OF PROJECT CocoaPodsExample WITH CONFIGURATION Debug ===
Given Release as default configuration
$ git grep defaultConfigurationName
CocoaPodsExample.xcodeproj/project.pbxproj: defaultConfigurationName = Release;
CocoaPodsExample.xcodeproj/project.pbxproj: defaultConfigurationName = Release;
CocoaPodsExample.xcodeproj/project.pbxproj: defaultConfigurationName = Release;
Pods/Pods.xcodeproj/project.pbxproj: defaultConfigurationName = Release;
Pods/Pods.xcodeproj/project.pbxproj: defaultConfigurationName = Release;
Pods/Pods.xcodeproj/project.pbxproj: defaultConfigurationName = Release;
specifying DEFAULT configuration uses Release (EXPECTED)
$ xcodebuild -scheme CocoaPodsExample -workspace CocoaPodsExample.xcworkspace -configuration DEFAULT build | grep "CONFIGURATION"
=== BUILD TARGET Pods-AFNetworking OF PROJECT Pods WITH THE DEFAULT CONFIGURATION (Release) ===
=== BUILD TARGET Pods OF PROJECT Pods WITH THE DEFAULT CONFIGURATION (Release) ===
=== BUILD TARGET CocoaPodsExample OF PROJECT CocoaPodsExample WITH THE DEFAULT CONFIGURATION (Release) ===
=== BUILD TARGET CocoaPodsExampleTests OF PROJECT CocoaPodsExample WITH THE DEFAULT CONFIGURATION (Release) ===
and not specifying the configuration uses Debug (UNEXPECTED)
$ xcodebuild -scheme CocoaPodsExample -workspace CocoaPodsExample.xcworkspace build | grep "CONFIGURATION"
=== BUILD TARGET Pods-AFNetworking OF PROJECT Pods WITH CONFIGURATION Debug ===
=== BUILD TARGET Pods OF PROJECT Pods WITH CONFIGURATION Debug ===
=== BUILD TARGET CocoaPodsExample OF PROJECT CocoaPodsExample WITH CONFIGURATION Debug ===
=== BUILD TARGET CocoaPodsExampleTests OF PROJECT CocoaPodsExample WITH CONFIGURATION Debug ===
It's as if:
I don't even know if this is a bug or expected behavior.
Upvotes: 4
Views: 3099
Reputation: 8458
This was something that was tripping up my own Continuous Integration scripts as well and caused me to be very specific in xcodebuild
commands when it came to determining which of my configurations to run. It wasn't until several months later I dug into the behavior to determine what was actually going on.
TL;DR version: The behavior you are observing is functioning correctly given the commands you are firing off to xcodebuild
.
...now for the 'why'
As it turns out, the defaultConfigurationName
value is a setting that was added to pre-Xcode 4 projects as a means to describe which of potentially many build configurations should be leveraged by command-line builds when a configuration hadn't been specified...exactly as its name suggests and entirely consistent with the expectation you've expressed in your question.
There is some nuance in that history -- specifically, why is Xcode 4 important? Xcode 4 was the first version of the developer toolchain that introduced the concept of "Schemes" as a manner of defining different ways in which an application would be built. Per Apple's definition (emphasis added):
An Xcode scheme defines a collection of targets to build, a configuration to use when building, and a collection of tests to execute.
Peering into the .xcscheme
file associated with a project we see a bunch of configuration data consistent with the settings we see exposed in the Scheme editor of the modern Xcode interface. There is one section in the root of /Scheme for each of the six items that appear in the left side bar of the scheme editor accessible by selecting "Edit Scheme" from the scheme picker next to the Stop button:
BuildAction
maps to "Build"TestAction
maps to "Test"LaunchAction
maps to "Run"ProfileAction
maps to "Profile"AnalyzeAction
maps to "Analyze"ArchiveAction
maps to "Archive"Within all but the "Build" item in Xcode we find a "Build Configuration" drop down list. The value of this item is reflected in the .xcscheme
file under the respective action's setting for buildConfiguration
. Take note of the build configuration defined for what the "Run" action (via the Xcode Scheme Editor Interface) or the "LaunchAction" in the .xcscheme
file. I'd hazard a guess that the CocoaPodsExample
scheme has Debug
set as the Build Configuration for the Run / LaunchAction.
In your original question, your xcodebuild
commands indicate that you are using a Workspace to organize your project. Per documentation for xcodebuild
:
To build an Xcode workspace, you must pass both the -workspace and -scheme options to define the build. The parameters of the scheme will control which targets are built and how they are built, although you may pass other options to xcodebuild to override some param- eters of the scheme.
...because you use a Workspace you are compelled to provide a -scheme
parameter and therefore are leveraging the buildConfiguration
value that is found under the "Run" item in the Xcode Scheme Editor, equivalently located in the "LaunchAction:buildConfiguration" setting in the Scheme's .xcscheme
file. Whatever build configuration is defined in this scheme takes precedence over not setting -configuration
in the xcodebuild
command itself.
So why does defaultBuildConfiguration
still exist?
There are still legacy projects and even some development teams that have not adopted workspaces in their Xcode projects. Were you to create a brand new test project, not incorporate it in a Workspace, and run xcodebuild build | grep "CONFIGURATION"
from the folder that contains the .xcodeproj
you'd see the defaultBuildConfiguration
get picked up.
I created a Single View iOS Application named "Demo" and did nothing else to the blank project. The default project creates a scheme named "Demo" that has the Run Build Configuration set to Debug
while the defaultConfigurationName
defaults to Release
(NOTE: There are user-specific paths in some of these commands -- If you are going to run them yourself, do be sure to update paths accordingly!):
$ xmllint --xpath //Scheme/LaunchAction/@buildConfiguration Demo.xcodeproj/xcuserdata/bmusial.xcuserdatad/xcschemes/Demo.xcscheme
buildConfiguration="Debug"
$ grep defaultConfigurationName Demo.xcodeproj/project.pbxproj
defaultConfigurationName = Release;
defaultConfigurationName = Release;
defaultConfigurationName = Release;
$ xcodebuild build | grep "CONFIGURATION"
=== BUILD TARGET Demo OF PROJECT Demo WITH THE DEFAULT CONFIGURATION (Release) ===
The output of the BUILD TARGET
has changed slightly: It now reads: DEFAULT CONFIGURATION (Release)
instead of CONFIGURATION Release
. The inclusion of DEFAULT
and the parenthesis around the actual configuration are the only indications that xcodebuild
has fallen back to the value from defaultConfigurationName
. Incidentally, these same indicators are present in the output from your Workspace command equivalents.
As this is a Scheme-enabled project we can use -scheme
to pull the scheme-configured build configuration, or we can explicitly override the configuration to use by setting -configuration
:
$ xcodebuild -scheme Demo build | grep "CONFIGURATION"
=== BUILD TARGET Demo OF PROJECT Demo WITH CONFIGURATION Debug ===
=== BUILD TARGET DemoTests OF PROJECT Demo WITH CONFIGURATION Debug ===
$ xcodebuild -configuration Debug build | grep "CONFIGURATION"
=== BUILD TARGET Demo OF PROJECT Demo WITH CONFIGURATION Debug ===
The output of these commands goes back to the normal WITH CONFIGURATION
style and the configuration not wrapped by parenthesis.
Hopefully this gives you a lens into what is going on with your own projects and you can adjust your command-line scripts accordingly. Once I sorted this out, I was able to be less specific in my CI scripts so that as the project evolved there was less off a need to update the build scripts in parallel with project configuration changes. Naturally, depending on the nature of your own project and the frequency with which build configuration may or may not change, you may want to defer to being very prescriptive in your xcodebuild commands...that is, compel a specific configuration via -configuration
. If you run into any followup questions, I'm all ears!
Upvotes: 3