Question

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.

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top