美文网首页
cocoapods在podfile中如何修改build phas

cocoapods在podfile中如何修改build phas

作者: yofer张耀琦 | 来源:发表于2020-09-25 18:29 被阅读0次

    问题

    升级Xcode12之后,单测的target (ReadInJoyTests) 出现了报错:

    error: Cycle inside ReadInJoyTests; building could produce unreliable results.
    Cycle details:
    → Target 'ReadInJoyTests': CodeSign /Users/yoferzhang/Library/Developer/Xcode/DerivedData/QQMSFContact-gpvqexdcrtvrsdczqfqownxrezqo/Build/Products/Debug-iphonesimulator/QQ.app/EarlGrey.framework
    ○ That command depends on command in Target 'ReadInJoyTests': script phase “[CP] Copy Pods Resources”
    ○ Target 'ReadInJoyTests': CodeSign /Users/yoferzhang/Library/Developer/Xcode/DerivedData/QQMSFContact-gpvqexdcrtvrsdczqfqownxrezqo/Build/Products/Debug-iphonesimulator/QQ.app/EarlGrey.framework
    

    解决方案,是要删除 ReadInJoyTests target 中 build phase 的 [CP] Copy Pods Resources 的 Output file lists

    手动删除

    image

    手动清空后,pod install 后还是会生成。

    脚本删除

    考虑是否可以通过脚本删除。

    删除方法

    脚本删除可以分为以下几步:

    1. 获取主工程的xcodeproj
    2. 找到target ReadInJoyTests target
    3. 找到build phase [CP] Copy Pods Resources
    4. 保存project

    删除的代码

    require 'xcodeproj'
    
    def delete_rij_tests_output_file_lists
        puts "===================> Start delete ReadInJoyTests Target [CP] Copy Pods Resources output file lists"
    
        project_path = './QQMSFContact.xcodeproj'
        project = Xcodeproj::Project.open(project_path)
        project.targets.each do |target|
            if target.name == "ReadInJoyTests"
                puts "===================> Find ReadInJoyTests Target"
                build_phase = target.build_phases.find { |bp| bp.display_name == '[CP] Copy Pods Resources' }
    
                puts "===================> Before delete, Output file lists:"
                puts build_phase.output_file_list_paths
                
                # 执行删除
                while build_phase.output_file_list_paths.length > 0
                    build_phase.output_file_list_paths.pop()
                end
            end
        end
    
        # 保存工程文件
        project.save
        puts "===================> Finish delete ReadInJoyTests Target [CP] Copy Pods Resources output file lists"
    end
    

    删除时机

    首先来看一下cocoapods的hook执行顺序

    1. 终端执行命令pod install
    2. 运行podfile 中的 ruby method
    3. 执行hook pre_install
    4. 执行 pod install 的行为,但此时修改内容还在内存的 installer 中,还未写入磁盘
    5. 执行hook post_install ,同上还是未写入磁盘
    6. 将installer修改部分写入磁盘

    如果在 post_install 中执行 delete_rij_tests_output_file_lists ,那因为 post_install 内pod的修改还没写入磁盘,delete_rij_tests_output_file_lists 的修改,会被 post_install 之后pod写入磁盘而覆盖掉。导致删除失败。

    调试发现,如果在第3步之前, output file paths 内容存在,则在post_install 中执行删除,就不会发生覆盖写入时重新生成 output file paths

    也就是说可以在第3步之前,先通过脚本写入 path,欺骗cocoapods,path存在,这次 install 就不要生成path 做添加动作。然后在post_install 中执行删除逻辑,这样就解决了问题。

    写入path的代码为:

    def add_rij_tests_temp_output_file_list
        project_path = './QQMSFContact.xcodeproj'
        project = Xcodeproj::Project.open(project_path)
        project.targets.each do |target|
            if target.name == "ReadInJoyTests"
                puts "===================> Find ReadInJoyTests Target"
                build_phase = target.build_phases.find { |bp| bp.display_name == '[CP] Copy Pods Resources' }
    
                puts "===================> Before add, temp output file lists:"
                puts build_phase.output_file_list_paths
                
                list_path = '${PODS_ROOT}/Target Support Files/Pods-ReadInJoyTests/Pods-ReadInJoyTests-resources-${CONFIGURATION}-output-files.xcfilelist'
                # 添加路径
                if build_phase.output_file_list_paths.include?(list_path) == false
                    build_phase.output_file_list_paths.push(list_path)
                end
            end
        end
    
        # 保存工程文件
        project.save
    end
    

    最后修改完成的podfile 为

    # 省略上述两个method定义
    post_install do |installer|
        # 省略...
      
      # 删除 ReadInJoyTests Target [CP] Copy Pods Resources output file lists
      delete_rij_tests_output_file_lists
    end
    
    # pod install之前添加一次,让 pod 认为已经有了path,pod install过程中就不会再新增了
    add_rij_tests_temp_output_file_list
    

    完整流程

    最后来看完整的流程

    1. 临时添加output file path,让cocoapods认为本次 install 无需做添加path的动作。
    2. install 生成工程修改(不会添加path)
    3. post_install 中再删除 output file path
    4. pod将install 写入磁盘。

    See Also

    最后提供一个不用 xcodeproj 工具的删除方法

    post_install do |installer|
    
      installer.aggregate_targets.each do |target|
        if target.name == "Pods-ReadInJoyTests"
          puts "==========> Find Pods-ReadInJoyTests:"
          project = target.user_project
          puts project
          project.targets.each do |sub_target|
            if sub_target.name =="ReadInJoyTests"
              puts "==========> Find ReadInJoyTests Target"
              build_phase = sub_target.build_ phases. find { |bp| bp.display_name == '[CP] Copy Pods Resources' }
              puts "==========> Before delete, Output file lists:"
              puts build_phase.output_file_list_paths
              
              #执行刪除
              build_phase.output_file_list_paths.pop( )
              puts"==========> After delete, Output file lists:"
              puts build_phase.output_file_list_paths
            end
          end
          project. save
        end
      end
    end
    

    相关文章

      网友评论

          本文标题:cocoapods在podfile中如何修改build phas

          本文链接:https://www.haomeiwen.com/subject/jfofuktx.html