Make Custom Debug Build Configurations Play Nicely With CocoaPods
To test the Word Counter during development, I have long used a special build target. But that doesn’t scale well if all I want is change a preprocessor macro to switch from file-based to in memory storage, for example.
I’ve never played around with build configurations in Xcode. They work well with Schemes, though, and setting up a build configuration and a scheme is much less overhead than maintaining a custom target.
From the project view, it’s easy to duplicate the existing debug build configuration.
I’ve done this twice for the Word Counter: once for an in memory store, once using test data. In the second case, the clock always points to the same time and the app uses different files. This way I don’t destroy my personal records and have nice presets to make screenshots.
To be able to build and run the project using the new configuration, add a scheme.
From the scheme editor, duplicate the existing scheme for running the app and change its name. I added a “In Memory” suffix to have it read nicely in the list of schemes.
Change the used build configuration from the “Run” setting to the new configuration. You may also want to change the used configuration for testing, but I didn’t, since the tests stay the same.
Now we have to tame CocoaPods.
Configure CocoaPods
You will probably get a warning with pod install
:
[!] CocoaPods did not set the base configuration of your project because your project already has a custom config set. …
In my case, there were a dozen of these.
They continued like this:
In order for CocoaPods integration to work at all, please either set the base configurations of the target
InteractionTests
toPods/Target Support Files/Pods/Pods.debug in memory.xcconfig
or include thePods/Target Support Files/Pods/Pods.debug in memory.xcconfig
in your build configuration.
You see that the InteractionTests
target under the “Debug In Memory” configuration is expected to use a different .xcconfig
. Although CocoaPods created some new of these, I wasn’t able to pick them in Xcode.
To solve the problem, I performed these steps:
- Tell CocoaPods that the new configurations are descendants from the “Debug” configuration. I added
xcodeproj 'WordCounter', 'Debug In Memory' => :debug, 'Debug Test Data' => :debug
to my Podfile at root level. - Then I reset all newly created configurations. Instead of the
Pods.debug
configuration of some targets, I set all target configurations to “None”. - Run
pod install
to make CocoaPods attach its.xcconfig
files in the appropriate slots – those I’ve just cleared.
Now I get different warnings: the test targets of the new configurations use the wrong .xcconfig
files. Instead of Pods-InteractionTests.debug.xcconfig
, it is set to Pods.debug.xcconfig
.
Turns out this is because my 18-months-old podfile had global pods defined.
Modern CocoaPods File (2018 Edition)
The original file, severely outdated:
platform :osx, '10.9'
use_frameworks!
xcodeproj 'WordCounter', 'Debug In Memory' => :debug, 'Debug Test Data' => :debug
link_with ['WordCounter', 'CedarSpecs', 'InteractionTests']
pod 'CocoaLumberjack'
pod 'LaunchAtLoginController', :git => "https://github.com/jashephe/LaunchAtLoginController.git"
pod 'CorePlot', :git => 'https://github.com/core-plot/core-plot.git'
target "CedarSpecs", :exclusive => true do
pod 'Cedar'
end
target "InteractionTests", :exclusive => true do
pod 'OCHamcrest', '~> 4.2'
pod 'OCMockito', '~> 2.0' #OCHamcrest 4 support
end
For historical reasons, here’s the 2015 iteration:
platform :osx, '10.9'
use_frameworks!
xcodeproj 'WordCounter', 'Debug In Memory' => :debug, 'Debug Test Data' => :debug
def shared_pods
pod 'CocoaLumberjack'
pod 'LaunchAtLoginController', :git => "https://github.com/jashephe/LaunchAtLoginController.git"
pod 'CorePlot', :git => 'https://github.com/core-plot/core-plot.git'
end
target "WordCounter" do
shared_pods
end
target "CedarSpecs" do
shared_pods
pod 'Cedar'
end
target "InteractionTests" do
shared_pods
pod 'OCHamcrest', '~> 4.2'
pod 'OCMockito', '~> 2.0' #OCHamcrest 4 support
end
Seems to solve the exclusivity problem from before just fine. (Whatever that was. I don’t remember anymore.)
No warnings left for me now and everything builds fine.
And here’s the 2018 Podfile, getting rid of shared_pods
and replacing it with the new abstract_target
as a way to inherit dependencies:
platform :osx, '10.10'
use_frameworks!
project 'WordCounter', 'Debug' => :debug, 'Debug In Memory' => :debug, 'Debug Test Data' => :debug, 'Release Final' => :release
abstract_target "shared_pods" do
pod 'CocoaLumberjack', '3.4.2'
pod 'LaunchAtLoginController', :git => "https://github.com/jashephe/LaunchAtLoginController.git"
pod 'CorePlot', :git => 'https://github.com/core-plot/core-plot.git'
target "WordCounter" do
# Only shared pods
end
target "CedarSpecs" do
pod 'Cedar'
end
target "InteractionTests" do
pod 'OCHamcrest', '~> 7.1.1'
pod 'OCMockito', '~> 5.1.1'
end
target "UnitTests" do
# TODO: might be better off getting rid of the dependency one day
end
end
If that doesn’t seem to work, delete the Pods folder from your project: mine contained stale and missing files. After deleting it, pod install
added fresh files just fine.