My project uses CocoaPods and also custom xcconfig
files. Until now, this hasn't caused any problems: I've just had to #include
the CocoaPods-generated configuration at the end of my custom configuration.
However, I've run into a problem where a need to conditionally specify OTHER_LDFLAGS
based on the xcconfig
, but I can't figure out how to do this.
As a start, I've tried simply logging the OTHER_LDFLAGS
like this, but the flags aren't actually logged:
post_install do |installer_representation|
installer_representation.project.targets.each do |target|
target.build_configurations.each do |config|
name = target.name
puts "Target Found: #{name}"
flags = config.build_settings['OTHER_LDFLAGS']
puts "OTHER_LDFLAGS Found: #{flags}"
end
end
end
The output looks like this:
Target Found: Pods-ProjectName-DependencyName1
OTHER_LDFLAGS Found: # nothing here...?
Target Found: Pods-ProjectName-DependencyName2
OTHER_LDFLAGS Found: # again nothing...
# etc...
Target Found: Pods-ProjectName # Cool, this is the main target pod
OTHER_LDFLAGS Found: # ...
How can I actually modify OTHER_LDFLAGS
via the 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
end
end
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
end
end
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
end
end
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
end
end
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 configs
GCC_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)
I couldn't figure out a good way to modify the xcconfig
. I can view them and even change them in post install, but my changes don't get written to the pod xcconfig
.
This is what I use to modify the xcconfig file:
post_install do |installer|
installer.libraries.each do |lib|
if lib.name != "Pods-lib"
next
end
target = lib.library
target.xcconfigs.each do |key, value|
config_file_path = target.xcconfig_path(key)
File.open("config.tmp", "w") do |io|
io << File.read(config_file_path).gsub(/-l"c\+\+"/, '').gsub(/-l"icucore"/,'')
end
FileUtils.mv("config.tmp", config_file_path)
end
end
end
The way to modify the OTHER_LD_FLAGS
in the post install script directly is as follows. But since they don't get written to the xcconfig
file, I had to resort to the hacky solution above. If you can figure out how to get these changes written to the file, it would be awesome.
post_install do |installer|
libs_to_remove = ['c++', 'icucore']
installer.libraries.each do |lib|
if lib.name != "Pods-lib"
next
end
target = lib.library
target.xcconfigs.each do |key, value|
other_ld = value.other_linker_flags
libs = other_ld[:libraries]
libs.subtract(libs_to_remove)
value.other_linker_flags[:libraries] = libs
end
end
end
来源:https://stackoverflow.com/questions/30244675/how-can-i-modify-other-ldflags-via-cocoapods-post-install-hook