如何通过CocoaPods安装后挂钩修改OTHER_LDFLAGS?

时间:2015-05-14 18:29:39

标签: ios ruby cocoapods

我的项目使用CocoaPods和自定义xcconfig文件。到目前为止,这还没有引起任何问题:我在自定义配置结束时只需要#include CocoaPods生成的配置。

但是,我遇到了需要根据OTHER_LDFLAGS有条件地指定xcconfig的问题,但我无法弄清楚如何执行此操作。

首先,我尝试过像这样简单地记录OTHER_LDFLAGS,但标志实际上并未记录:

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

输出如下:

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: # ...

如何通过CocoaPods安装后挂钩实际修改OTHER_LDFLAGS

8 个答案:

答案 0 :(得分:28)

我偶然发现了同样的问题。首先,我尝试用明显的方法修改OTHER_LDFLAGS

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

但它没有用。相关的xcconfig没有得到改变。最终我找到了一个运行良好的解决方法 - 首先阅读post_intall钩子中的相关xcconfig文件内容,修改它并将其写回:

<强> 1.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

编辑:对 v1.0 的改进。不要直接对xcconfig String内容进行操作,而是将xccconfig读入build_configuration Hash,修改哈希值,然后将其刷新到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

答案 1 :(得分:10)

基于上面的答案以及cocoapodsxcodeproj的官方rubydocs,我提出了这个解决方案,它纯粹基于上述宝石提供的API:

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

这成功地将链接器标志-l"AFNetworking"添加到任何聚合目标的任何xcconfig文件中(&#39; Pod -...&#39;)。

在Xcode8.3.3和Xcode9 Beta 4上使用cocoapods 1.2.0和1.3.0进行测试。

答案 2 :(得分:3)

这是v1.0的用例: 我偶然发现了这个帖子,因为我们有多个应用程序都有单独的xcconfigs并共享常见的xcconfig文件。一旦我们添加了应用程序扩展作为目标,并且无法再共享活动配置的项目级继承(如调试),则使用pod开始崩溃。 Sooooo使用上面的v1.0你可以重命名pod级元素,比如OTHER_LDFLAGS到PODS_OTHER_LDFLAGS,然后安全#include它们到你的xcconfigs(不用踩其他值)将它们与常见的,app,target设置合并ala:

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

所以,在我的pods文件中,我们在循环中有一个像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 }

和在目标级别设置的胶水xcconfig 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"

将各种app / config / common / pod设置拉入,merge.xcconfig将所有内容拉到一起,如下所示:

//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)

答案 3 :(得分:1)

如果您需要修改LDFLAGS并将一个框架移至末尾,那么此脚本将为您提供帮助。如果您拥有同一框架的两个版本,并且您主要想使用特定的实现,那么这会有所帮助。 (由于having FFMPEG twice in my app,我需要解决此问题,这是MobileVLCKit的一部分。)经过CocoaPods 1.9和1.10的测试。

post_install do |installer|
    installer.pods_project.targets.each do |target|
        if target.name == "Pods-MYPROJECT"
            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
                vlc_flag = ' -framework "MobileVLCKit"'
                build_settings['OTHER_LDFLAGS'].gsub!(vlc_flag, "")
                build_settings['OTHER_LDFLAGS'].gsub!("\n", "")
                build_settings['OTHER_LDFLAGS'] += vlc_flag + "\n"

                # write build_settings dictionary to xcconfig
                File.open(xcconfig_path, "w") do |file|
                  build_settings.each do |key,value|
                    file.write(key + " = " + value)
                  end
                end
            end
        end
    end
end

答案 4 :(得分:0)

我正在运行pod版本1.8.4,但以上所有内容均不适用于我,因此请在此处发布以防万一。

下面的脚本基于@mrvincenzo的答案,但是我必须做一些更改以使其起作用,这将成功地将-ObjC标志附加到OTHER_LDFLAGS上,请记住,这将保留现有列表并仅在其上附加标志

post_install do |installer|
  installer.pods_project.targets.each do |target|
    #replace `Pod-target-lib` with your target library
    if target.name == "Pod-target-lib"
      puts "Updating #{target.name} OTHER_LDFLAGS"
      xcconfig_path = ""
      target.build_configurations.each do |config|
        new_xcconfig_path = config.base_configuration_reference.real_path
        if new_xcconfig_path != xcconfig_path
          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'] = "-ObjC #{build_settings['OTHER_LDFLAGS']}"

          # clear current file content
          File.open(xcconfig_path, "w") {|file| file.puts ""}

          # 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
end

答案 5 :(得分:0)

如果您需要修改一些现有标志,则此示例可能对您有用:

post_install do |installer|
    installer.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
            xcconfig_path = config.base_configuration_reference.real_path
            xcconfig = File.read(xcconfig_path)
            xcconfig_mod = xcconfig.gsub(/-framework "YourFramework"/, "-weak_framework \"YourFramework\"")
            File.open(xcconfig_path, "w") { |file| file << xcconfig_mod }
        end
    end
end

答案 6 :(得分:0)

此解决方案基于@ sven-driemecker的解决方案, 但由于使用了更多的纯可可足API,因此效果略好。 它不会简单地追加字符串,而是将其添加到set中以保持数据一致。

在当前示例中,我修改了聚合目标,例如<a>,以排除某些静态库无法链接,因为它们已经被依赖项之一链接了。

Pods-MYPROJECT

答案 7 :(得分:-1)

我无法找到修改xcconfig的好方法。我可以查看它们甚至在安装后更改它们,但我的更改不会写入pod xcconfig

这是我用来修改xcconfig文件的内容:

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

直接在安装后脚本中修改OTHER_LD_FLAGS的方法如下。但由于它们没有写入xcconfig文件,我不得不求助于上面的hacky解决方案。如果你能弄清楚如何将这些更改写入文件,那就太棒了。

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