How can I modify OTHER_LDFLAGS via CocoaPods post-install hook? How can I modify OTHER_LDFLAGS via CocoaPods post-install hook? ruby ruby

How can I modify OTHER_LDFLAGS via CocoaPods post-install hook?


I stumbled across the same problem. First I tried to modify OTHER_LDFLAGS with the obvious:

post_install do |installer|    installer.pods_project.targets.each do |target|        if target.name == "Pods-SomeTarget"            puts "Updating #{target.name} OTHER_LDFLAGS"            target.build_configurations.each do |config|                config.build_settings['OTHER_LDFLAGS'] ||= ['$(inherited)']                config.build_settings['OTHER_LDFLAGS'] << '-l"AFNetworking"'            end        end    endend

but it didn't work. The relevant xcconfig didn't get the change. Eventually I found a workaround that works well - first read the relevant xcconfig file content in the post_intall hook, modify it and write it back:

v1.0

post_install do |installer|    installer.pods_project.targets.each do |target|        if target.name == "Pods-SomeTarget"            puts "Updating #{target.name} OTHER_LDFLAGS"            target.build_configurations.each do |config|                xcconfig_path = config.base_configuration_reference.real_path                xcconfig = File.read(xcconfig_path)                new_xcconfig = xcconfig.sub('OTHER_LDFLAGS = $(inherited)', 'OTHER_LDFLAGS = $(inherited) -l"AFNetworking"')                File.open(xcconfig_path, "w") { |file| file << new_xcconfig }            end        end    endend

EDIT: Improvement over the v1.0. Instead of operating on xcconfig String content directly, read xccconfig into a build_configuration Hash, modify the hash and then flush it to xcconfig.

v1.5

post_install do |installer|    installer.pods_project.targets.each do |target|        if target.name == "Pods-SomeTarget"            puts "Updating #{target.name} OTHER_LDFLAGS"            target.build_configurations.each do |config|                xcconfig_path = config.base_configuration_reference.real_path                # read from xcconfig to build_settings dictionary                build_settings = Hash[*File.read(xcconfig_path).lines.map{|x| x.split(/\s*=\s*/, 2)}.flatten]                # modify OTHER_LDFLAGS                build_settings['OTHER_LDFLAGS'] << '-l"AFNetworking"'                # write build_settings dictionary to xcconfig                build_settings.each do |key,value|                  File.open(xcconfig_path, "a") {|file| file.puts key = value}                end            end        end    endend


Based on the answers above and the official rubydocs of cocoapods and xcodeproj, I came up with this solution, which is purely based on the APIs provided by the mentioned gems:

post_install do |installer|    installer.aggregate_targets.each do |aggregate_target|        aggregate_target.xcconfigs.each do |config_name, config_file|            config_file.attributes['OTHER_LDFLAGS'] << '-l"AFNetworking"'            xcconfig_path = aggregate_target.xcconfig_path(config_name)            config_file.save_as(xcconfig_path)        end    endend

This successfully adds the linker flag -l"AFNetworking" to any xcconfig file of any aggregate target ('Pod-...').

Tested with cocoapods 1.2.0 and 1.3.0 on Xcode8.3.3 and Xcode9 Beta 4.


Here's a use case for v1.0:I stumbled across this thread because we have multiple apps that all have individual xcconfigs and share common xcconfig files. Using pods started to fall apart once we added an app extension as a target and could no longer share the project level inheritance for the active config(like debug). Sooooo using v1.0 from above you can re-name the pod level elements, like OTHER_LDFLAGS to PODS_OTHER_LDFLAGS and then safely #include them into your xcconfigs (without stomping other values) merge them with common, app, target settings ala:

OTHER_LDFLAGS = $(inherited) $(PODS_OTHER_LDFLAGS) $(COMMON_OTHER_LDFLAGS)

So, in my pods file we have a section like this inside a loop like v1.0:

    puts "Updating #{target.name} adapting settings like OTHER_LDFLAGS for merging at target level"    xcconfig_path = config.base_configuration_reference.real_path    xcconfig = File.read(xcconfig_path)    xcconfig = xcconfig.sub('OTHER_LDFLAGS = $(inherited)', 'PODS_OTHER_LDFLAGS = ')    xcconfig = xcconfig.sub('OTHER_CFLAGS = $(inherited)', 'PODS_OTHER_CFLAGS = ')    xcconfig = xcconfig.sub('GCC_PREPROCESSOR_DEFINITIONS = $(inherited)', 'PODS_GCC_PREPROCESSOR_DEFINITIONS = ')    xcconfig = xcconfig.sub('HEADER_SEARCH_PATHS = $(inherited)', 'PODS_HEADER_SEARCH_PATHS = ')    xcconfig = xcconfig.sub('LIBRARY_SEARCH_PATHS = $(inherited)', 'PODS_LIBRARY_SEARCH_PATHS = ')    File.open(xcconfig_path, "w") { |file| file << xcconfig }

and a glue xcconfig that is set at the target level ala:

#include "../../Pods/Target Support Files/Pods-Fusion/Pods-Fusion.release.xcconfig"#include "../../shared/main/config/release.xcconfig"#include "../../shared/main/config/allTargetsCommon.xcconfig"#include "Fusion.xcconfig"#include "../../shared/main/config/merge.xcconfig"

where the various app/config/common/pod settings are pulled in and merge.xcconfig pulls everything together like this:

//merge up the pods, common base target and target configsGCC_PREPROCESSOR_DEFINITIONS = $(inherited) $(PODS_GCC_PREPROCESSOR_DEFINITIONS) $(TARGET_GCC_PREPROCESSOR_DEFINITIONS) $(APP_GCC_PREPROCESSOR_DEFINITIONS)HEADER_SEARCH_PATHS = $(inherited) $(PODS_HEADER_SEARCH_PATHS)OTHER_CFLAGS = $(inherited) $(PODS_OTHER_CFLAGS) $(TARGET_OTHER_CFLAGS)OTHER_LDFLAGS = $(inherited) $(PODS_OTHER_LDFLAGS) $(COMMON_OTHER_LDFLAGS)