從年初開始在項(xiàng)目中引入flutter,用其實(shí)現(xiàn)了部分簡(jiǎn)單的頁面。
我們團(tuán)隊(duì)中Pod的使用和主流有些不一樣,Pods目錄是不寫入.gitignore的??阅签。
原因:
當(dāng)通過pod引入Flutter module
并執(zhí)行pod install
后,Pod Project中Flutter
相關(guān)的Targrt
配置里都會(huì)寫入Flutter.xcframework的絕對(duì)路徑蝎抽;
再加上我們git沒有忽略pod目錄政钟;
所以如果不同的電腦Flutter
安裝路徑不同,就會(huì)編譯報(bào)錯(cuò)樟结,找不到Flutter.xcframework
养交。
有比較簡(jiǎn)單的解決方案
- Pods文件夾不要上傳到git
或 - 確保各電腦的flutter安裝路徑統(tǒng)一,比如都是
Users/flutter/
狭吼,
由于我想了解下flutter的構(gòu)建方式层坠,因此決定通過編寫腳本的方式解決這個(gè)問題
通過分析,看到路徑的配置是在xxxxxx/flutter/packages/flutter_tools/bin/podhelper.rb
這個(gè)腳本中(省略了無關(guān)的代碼)
def flutter_additional_ios_build_settings(target)
...
artifacts_dir = File.join('..', '..', '..', '..', 'bin', 'cache', 'artifacts', 'engine')
debug_framework_dir = File.expand_path(File.join(artifacts_dir, 'ios', 'Flutter.xcframework'), __FILE__)
release_framework_dir = File.expand_path(File.join(artifacts_dir, 'ios-release', 'Flutter.xcframework'), __FILE__)
...
target.build_configurations.each do |build_configuration|
...
# Skip other updates if it's not a Flutter plugin (transitive dependency).
next unless target.dependencies.any? { |dependency| dependency.name == 'Flutter' }
...
# Profile can't be derived from the CocoaPods build configuration. Use release framework (for linking only).
configuration_engine_dir = build_configuration.type == :debug ? debug_framework_dir : release_framework_dir
Dir.new(configuration_engine_dir).each_child do |xcframework_file|
next if xcframework_file.start_with?('.') # Hidden file, possibly on external disk.
if xcframework_file.end_with?('-simulator') # ios-arm64_x86_64-simulator
build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]'] = "\"#{configuration_engine_dir}/#{xcframework_file}\" $(inherited)"
elsif xcframework_file.start_with?('ios-') # ios-arm64
build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]'] = "\"#{configuration_engine_dir}/#{xcframework_file}\" $(inherited)"
# else Info.plist or another platform.
end
end
...
end
end
如果能夠修改這里腳本寫入的路徑刁笙,比如debug_framework_dir = File.join("$(Flutter_Install_Path)", 'bin', 'cache', 'artifacts', 'engine', 'ios', 'Flutter.xcframework')
破花,然后只需要在xcconfig
中定義不同的Flutter_Install_Path
就可以解決問題了。
但是修改flutter中的腳本是比較危險(xiǎn)的操作疲吸,因此決定通過編寫腳本再次修改掉flutter寫入的Flutter.xcframework
路徑座每。
方案還是比較簡(jiǎn)單的,下面直接給出步驟:
-
在Podfile同級(jí)目錄創(chuàng)建一個(gè)文件
Flutter_Path.xcconfig
摘悴,寫入自己電腦上Flutter安裝路徑kv (這個(gè)文件需要寫入.gitignore)Flutter_Install_Path = /Users/dadadongl/flutter
-
修改Podfile中的腳本 (下面是修改前/后)
# 修改前 post_install do |installer| flutter_post_install(installer) if defined?(flutter_post_install) end
# 修改后 post_install do |installer| # 先執(zhí)行flutter正常的腳本 flutter_post_install(installer) if defined?(flutter_post_install) # 注入環(huán)境變量 & 修改flutter默認(rèn)寫入的framework search path # 遍歷Pod中的Targets installer.pods_project.targets.each do |target| # 修改flutter.xcframework的引用路徑配置 (后面這段腳本基本是基于flutter的腳本修改的峭梳,做到改動(dòng)最少) # 跳過沒有依賴'Flutter'的target next unless target.dependencies.any? { |dependency| dependency.name == 'Flutter' } # 構(gòu)造使用了環(huán)境變量$(Flutter_Install_Path)"的search path debug_framework_dir = File.join("$(Flutter_Install_Path)", 'bin', 'cache', 'artifacts', 'engine', 'ios', 'Flutter.xcframework') release_framework_dir = File.join("$(Flutter_Install_Path)", 'bin', 'cache', 'artifacts', 'engine', 'ios-release', 'Flutter.xcframework') # 解析自定義的xcconfig文件,為了拿到Flutter安裝路徑 xcconfig = Xcodeproj::Config.new("./Flutter_Path.xcconfig") flutter_DIR = xcconfig.attributes["Flutter_Install_Path"] # 拿到Flutter的安裝絕對(duì)路徑 full_debug_framework_dir = File.join(flutter_DIR, 'bin', 'cache', 'artifacts', 'engine', 'ios', 'Flutter.xcframework') full_release_framework_dir = File.join(flutter_DIR, 'bin', 'cache', 'artifacts', 'engine', 'ios-release', 'Flutter.xcframework') # 遍歷Target下的配置環(huán)境(Debug 蹂喻、Release) target.build_configurations.each do |build_configuration| # 追加自定義環(huán)境變量到 Pod 庫的 .xcconfig 文件葱椭,為了編譯時(shí)能夠識(shí)別$(Flutter_Install_Path) xcconfig_path = build_configuration.base_configuration_reference.real_path # 這里導(dǎo)入時(shí)相對(duì)pod.debug.xcconfig的路徑 File.write(xcconfig_path, "#include \"../../../Flutter_Path.xcconfig\"", mode: 'a') # 修改 FRAMEWORK_SEARCH_PATHS configuration_engine_dir = build_configuration.type == :debug ? debug_framework_dir : release_framework_dir full_configuration_engine_dir = build_configuration.type == :debug ? full_debug_framework_dir : full_release_framework_dir Dir.new(full_configuration_engine_dir).each_child do |xcframework_file| next if xcframework_file.start_with?('.') # Hidden file, possibly on external disk. if xcframework_file.end_with?('-simulator') # ios-arm64_x86_64-simulator build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS[sdk=iphonesimulator*]'] = "\"#{configuration_engine_dir}/#{xcframework_file}\" $(inherited)" elsif xcframework_file.start_with?('ios-') # ios-arm64 build_configuration.build_settings['FRAMEWORK_SEARCH_PATHS[sdk=iphoneos*]'] = "\"#{configuration_engine_dir}/#{xcframework_file}\" $(inherited)" # else Info.plist or another platform. end end end end end
重新執(zhí)行Pod install
通過上述步驟后,就會(huì)把Flutter_Install_Path = /Users/dadadongl/flutter
注入各Pod Target
口四,然后修改后的framework search path
就可以找到正確的路徑孵运,并成功編譯。