I've developed an iOS project that is a class library dealing with different servers. Only one server is needed per application in which the library is used. The server type is configurable through a preprocessor definition at compile time.
In the podspec of my library, I defined various subspecs for each server like this:
s.name = "ServerLib"
[...]
s.subspec 'ServerA' do |a|
a.source_files = 'Classes/A/**/*.{h,m}'
a.xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) ServerA=1" }
end
s.subspec 'ServerB' do |b|
b.source_files = 'Classes/B/**/*.{h,m}'
b.xcconfig = { "GCC_PREPROCESSOR_DEFINITIONS" => "$(inherited) ServerB=1" }
end
My application is a multi-customer app with one target per customer. Each customer uses a specific server from the library project. So, my Podfile looks like this:
platform :ios, '5.0'
pod 'MyCore'
pod '3rdPartyLib'
target :'Customer1', :exclusive => true do
pod 'ServerLib/ServerA'
end
target :'Customer2', :exclusive => true do
pod 'ServerLib/ServerB'
end
What the pod install
script does, is merging ALL flags defined in the subspecs into one value in every pod-customerN.xcconfig file
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) 3RD_PARTY_FLAGS $(inherited) ServerA=1 $(inherited) ServerB=1
Any suggestions how to circumvent this wrong(?) behavior of Cocoapods? As far as I understand the documentation, subspec properties should inherit only from its parent specs not same-level subspecs.
Found a workaround, maybe not that elegant:
Since pod install
merges all compiler flags into one, I had to remove the GCC_PREPROCESSOR_DEFINITIONS
from the library's podspec
file. But without this definition, my library does not build.
In Xcode this can be fixed easily by adding the definition to each library's target. But when I use my library in an application, the Pods project is generated out of the Podspec which doesn't include the required flag.
The solution is to use the post_install
hook in the application's Podfile to manipulate the generated xcconfig of the Pods project.
post_install do |installer|
file_names = ['./Pods/Pods-ServerA.xcconfig',
'./Pods/Pods-ServerB.xcconfig']
# rename existing pre-processor definitions
file_names.each do |file_name|
text = File.read(file_name)
File.open(file_name, 'w') { |f| f.puts text.gsub(/GCC_PREPROCESSOR_DEFINITIONS/, "GCC_PREPROCESSOR_DEFINITIONS_SHARED")}
end
# merge existing and required definition for ServerA
File.open('./Pods/Pods-ServerA.xcconfig', 'a') { |f|
f.puts "\nGCC_PREPROCESSOR_DEFINITIONS=$(GCC_PREPROCESSOR_DEFINITIONS_SHARED) ServerA=1"
}
# merge existing and required definition for ServerB
File.open('./Pods/Pods-ServerB.xcconfig', 'b') { |f|
f.puts "\nGCC_PREPROCESSOR_DEFINITIONS=$(GCC_PREPROCESSOR_DEFINITIONS_SHARED) ServerB=1"
}
end
The code is a bit verbose since I'm not familiar with Ruby but it works. It should be easily possible to automate this renaming-append process as long as variable and library follow a naming scheme.