cocoapods在podfile中如何修改build phase

問題

升級Xcode12之后,單測的target (ReadInJoyTests) 出現(xiàn)了報錯:

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
            
            # 執(zhí)行刪除
            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執(zhí)行順序

  1. 終端執(zhí)行命令pod install
  2. 運行podfile 中的 ruby method
  3. 執(zhí)行hook pre_install
  4. 執(zhí)行 pod install 的行為,但此時修改內(nèi)容還在內(nèi)存的 installer 中,還未寫入磁盤
  5. 執(zhí)行hook post_install ,同上還是未寫入磁盤
  6. 將installer修改部分寫入磁盤

如果在 post_install 中執(zhí)行 delete_rij_tests_output_file_lists ,那因為 post_install 內(nèi)pod的修改還沒寫入磁盤,delete_rij_tests_output_file_lists 的修改,會被 post_install 之后pod寫入磁盤而覆蓋掉。導(dǎo)致刪除失敗。

調(diào)試發(fā)現(xiàn),如果在第3步之前, output file paths 內(nèi)容存在,則在post_install 中執(zhí)行刪除,就不會發(fā)生覆蓋寫入時重新生成 output file paths 。

也就是說可以在第3步之前,先通過腳本寫入 path,欺騙cocoapods,path存在,這次 install 就不要生成path 做添加動作。然后在post_install 中執(zhí)行刪除邏輯,這樣就解決了問題。

寫入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 認為已經(jīng)有了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
          
          #執(zhí)行刪除
          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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容