fastlane-plugin-analyze_ios_linkmap 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2d7e26083cb69298f9af1dec82d0f015bb595454ee6bdcaeae84f121ff9a61c6
4
- data.tar.gz: 28119251fdc69243ba162aecbd19774589df4cac1ad32402235c8cf9dc96de97
3
+ metadata.gz: c3bdbca21db75b21aaf970b4116c66ce3bfb4bfda14b606c1eddcc08748b2396
4
+ data.tar.gz: 40fd82b671e199e38a1215be9a665e08a312440c502e83aacd30c654a3fba9e5
5
5
  SHA512:
6
- metadata.gz: f76607c8979fd32f427a7d2e6f35936cf68bf98f1acb5e94f1a7c985e9143356891f442eba0ccb512c3f16bb4dc72abf9b22545f7e2e5419d9e04dbbbb6cb87f
7
- data.tar.gz: 0a7888ee701c27db2f3643f5e2a2ee372ff212a3552561d8b8b39888fd5360fcd76e447ff2fff7b1ad5d554c2873835994eadd124b9079801e8683ee7ed39e6c
6
+ metadata.gz: 26ddfed8795e9b4416a4ea3fb03dc2eaa013c84ab2587537612b4b0b0edeb4b77685fc9edd361be4301edf345bb311d3448c7fd610a7d986982261cfc15270d3
7
+ data.tar.gz: 27b1cb171f8990d3a4b5f8068f26b67d3203e3a9dbefc76abd1463c53fc00b5d693fc5ddfcbbd8d52d44c28d7119121093c2bf3087bc48733bf4e6a4d61a16c8
data/README.md CHANGED
@@ -12,33 +12,72 @@ fastlane add_plugin analyze_ios_linkmap
12
12
 
13
13
  ## About analyze_ios_linkmap
14
14
 
15
- xx
16
-
17
15
  **Note to author:** Add a more detailed description about this plugin here. If your plugin contains multiple actions, make sure to mention them here.
18
16
 
19
17
  ## Example
20
18
 
21
19
  Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`.
22
20
 
21
+ ### Eg1: 默认解析一个 linkmap.txt
22
+
23
+ ```ruby
24
+ path = '/Users/xiongzenghui/Desktop/Demo-LinkMap-normal-arm64.txt'
25
+ Fastlane::Actions::AnalyzeIosLinkmapAction.run( file_path: path )
26
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_HASH]
27
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_JSON]
28
+ ```
29
+
30
+ ### Eg2: 显示所有的 object file
31
+
32
+ ```ruby
33
+ path = '/Users/xiongzenghui/Desktop/Demo-LinkMap-normal-arm64.txt'
34
+ Fastlane::Actions::AnalyzeIosLinkmapAction.run(
35
+ file_path: path,
36
+ all_objects: true
37
+ )
38
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_HASH]
39
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_JSON]
40
+ ```
41
+
42
+ ### Eg3: 显示所有的 symbol
43
+
23
44
  ```ruby
24
- lane :test do
25
- # eg1:
26
- analyze_ios_linkmap(
27
- filepath: '/Users/xiongzenghui/collect_rubygems/fastlane-plugins/fastlane-plugin-analyze_ios_linkmap/spec/demo-LinkMap.txt'
28
- )
29
- pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_HASH]
30
- pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_JSON]
31
-
32
- # eg2:
33
- analyze_ios_linkmap(
34
- filepath: '/Users/xiongzenghui/Desktop/osee2unifiedRelease-LinkMap-normal-arm64.txt',
35
- search_symbol: 'TDATEvo'
36
- )
37
- pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_SEARCH_SYMBOL]
38
- end
45
+ path = '/Users/xiongzenghui/Desktop/Demo-LinkMap-normal-arm64.txt'
46
+ Fastlane::Actions::AnalyzeIosLinkmapAction.run(
47
+ file_path: path,
48
+ all_objects: true,
49
+ all_symbols: true
50
+ )
51
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_HASH]
52
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_JSON]
53
+ ```
54
+
55
+ ### Eg4: 根据 podspec name 进行合并
39
56
 
57
+ ```ruby
58
+ path = '/Users/xiongzenghui/Desktop/Demo-LinkMap-normal-arm64.txt'
59
+ Fastlane::Actions::AnalyzeIosLinkmapAction.run(
60
+ file_path: path,
61
+ all_objects: false,
62
+ all_symbols: false,
63
+ merge_by_pod: true
64
+ )
65
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_HASH]
66
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_JSON]
67
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_MERGE_HASH]
68
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_MERGE_JSON]
40
69
  ```
41
70
 
71
+ ### Eg5: 搜索一个 symbol 所属的 library
72
+
73
+ ```ruby
74
+ path = '/Users/xiongzenghui/Desktop/Demo-LinkMap-normal-arm64.txt'
75
+ Fastlane::Actions::AnalyzeIosLinkmapAction.run(
76
+ file_path: path,
77
+ search_symbol: 'TDATEvo'
78
+ )
79
+ pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_SEARCH_SYMBOL]
80
+ ```
42
81
 
43
82
 
44
83
  ## Run tests for this plugin
@@ -1,62 +1,77 @@
1
1
  require 'fastlane/action'
2
- require_relative '../helper/analyze_ios_linkmap_helper'
2
+ require_relative '../helper/analyze_ios_linkmap_parser'
3
3
 
4
4
  module Fastlane
5
5
  module Actions
6
6
  module ShatedValues
7
- ANALYZE_IOS_LINKMAP_SEARCH_SYMBOL = :ANALYZE_IOS_LINKMAP_SEARCH_SYMBOL
8
- ANALYZE_IOS_LINKMAP_PARSED_HASH = :ANALYZE_IOS_LINKMAP_PARSED_HASH
9
- ANALYZE_IOS_LINKMAP_PARSED_JSON = :ANALYZE_IOS_LINKMAP_PARSED_JSON
7
+ ANALYZE_IOS_LINKMAP_SEARCH_SYMBOL = :ANALYZE_IOS_LINKMAP_SEARCH_SYMBOL
8
+ ANALYZE_IOS_LINKMAP_PARSED_HASH = :ANALYZE_IOS_LINKMAP_PARSED_HASH
9
+ ANALYZE_IOS_LINKMAP_PARSED_JSON = :ANALYZE_IOS_LINKMAP_PARSED_JSON
10
10
  ANALYZE_IOS_LINKMAP_PARSED_MERGE_HASH = :ANALYZE_IOS_LINKMAP_PARSED_MERGE_HASH
11
11
  ANALYZE_IOS_LINKMAP_PARSED_MERGE_JSON = :ANALYZE_IOS_LINKMAP_PARSED_MERGE_JSON
12
12
  end
13
13
 
14
14
  class AnalyzeIosLinkmapAction < Action
15
15
  def self.run(params)
16
- filepath = params[:filepath]
16
+ file_path = params[:file_path]
17
17
  search_symbol = params[:search_symbol]
18
- all_symbols = params[:all_symbols] || false
19
- merge_by_pod = params[:merge_by_pod] || false
18
+ all_objects = params[:all_objects] || false
19
+ all_symbols = params[:all_symbols] || false
20
+ merge_by_pod = params[:merge_by_pod] || false
20
21
 
21
- parser = Fastlane::Helper::LinkMap::Parser.new({
22
- filepath: filepath,
23
- all_symbols: all_symbols
24
- })
22
+ linkmap_parser = Fastlane::Helper::LinkMap::Parser.new(
23
+ if search_symbol
24
+ {
25
+ file_path: file_path,
26
+ all_objects: true,
27
+ all_symbols: true
28
+ }
29
+ else
30
+ {
31
+ file_path: file_path,
32
+ all_objects: all_objects,
33
+ all_symbols: all_symbols
34
+ }
35
+ end
36
+ )
37
+
38
+ # parse Linkmap.txt
39
+ Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_HASH] = linkmap_parser.pretty_hash
40
+ Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_JSON] = linkmap_parser.pretty_json
41
+
42
+ # merge Linkmap.txt parsed all symbols by library
43
+ if merge_by_pod
44
+ Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_MERGE_HASH] = linkmap_parser.pretty_merge_by_pod_hash
45
+ Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_MERGE_JSON] = linkmap_parser.pretty_merge_by_pod_json
46
+ end
25
47
 
48
+ # if search a symbol from Linkmap.txt
26
49
  if search_symbol
27
50
  Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_SEARCH_SYMBOL] = []
28
- parser.pretty_hash[:librarys].each do |lib|
29
- lib[:objects].each do |obj|
51
+ linkmap_parser.pretty_hash[:librarys].each do |lib|
52
+ lib[:object_files].each do |obj|
30
53
  obj[:symbols].each do |symol|
31
54
  next unless symol[:name].include?(search_symbol)
32
55
 
33
56
  Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_SEARCH_SYMBOL] << {
34
- library: lib[:library],
35
- object_file: obj[:object],
57
+ library: lib[:name],
58
+ object_file: obj[:file_name],
36
59
  symbol: symol[:name]
37
60
  }
38
61
  end
39
62
  end
40
63
  end
41
64
  end
42
-
43
- Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_HASH] = parser.pretty_hash
44
- Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_JSON] = parser.pretty_json
45
-
46
- if merge_by_pod
47
- Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_MERGE_HASH] = parser.pretty_merge_by_pod_hash
48
- Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_MERGE_JSON] = parser.pretty_merge_by_pod_json
49
- end
50
65
  end
51
66
 
52
67
  def self.available_options
53
68
  [
54
69
  FastlaneCore::ConfigItem.new(
55
- key: :filepath,
70
+ key: :file_path,
56
71
  description: "/your/path/to/linkmap.txt",
57
- verify_block: ->(value) {
58
- UI.user_error("❌ filepath not pass") unless value
59
- UI.user_error!("❌ filepath #{value} not exist") unless File.exist?(value)
72
+ verify_block: ->(value) {
73
+ UI.user_error("❌ file_path not pass") unless value
74
+ UI.user_error!("❌ file_path #{value} not exist") unless File.exist?(value)
60
75
  }
61
76
  ),
62
77
  FastlaneCore::ConfigItem.new(
@@ -66,35 +81,29 @@ module Fastlane
66
81
  ),
67
82
  FastlaneCore::ConfigItem.new(
68
83
  key: :all_symbols,
69
- description: "print all symbol size ???",
70
- optional: true
84
+ description: "print a object fille all symbols ???",
85
+ optional: true,
86
+ default_value: false,
87
+ is_string: false
88
+ ),
89
+ FastlaneCore::ConfigItem.new(
90
+ key: :all_objects,
91
+ description: "print a library all object files ???",
92
+ optional: true,
93
+ default_value: false,
94
+ is_string: false
71
95
  ),
72
96
  FastlaneCore::ConfigItem.new(
73
97
  key: :merge_by_pod,
74
98
  description: "merge linkmap parsed hash by pod name ???",
75
- optional: true
99
+ optional: true,
100
+ default_value: false,
101
+ is_string: false
76
102
  )
77
103
  ]
78
104
  end
79
105
 
80
106
  def self.example_code
81
- [
82
- 'analyze_ios_linkmap(filepath: "/path/to/linkmap.txt")
83
- pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_HASH]
84
- pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_JSON]',
85
- 'analyze_ios_linkmap(
86
- filepath: "/path/to/linkmap.txt",
87
- search_symbol: "TDATEvo"
88
- )
89
- pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_SEARCH_SYMBOL]'
90
- 'analyze_ios_linkmap(
91
- filepath: "/path/to/linkmap.txt",
92
- all_symbols: false,
93
- merge_by_pod: true
94
- )
95
- pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_MERGE_HASH]
96
- pp Fastlane::Actions.lane_context[Fastlane::Actions::ShatedValues::ANALYZE_IOS_LINKMAP_PARSED_MERGE_JSON]'
97
- ]
98
107
  end
99
108
 
100
109
  def self.return_value
@@ -0,0 +1,299 @@
1
+ require 'fastlane_core/ui/ui'
2
+
3
+ module Fastlane
4
+ UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
5
+ module Helper
6
+ module LinkMap
7
+ require 'pp'
8
+ require 'json'
9
+ require_relative 'linkmap_helper'
10
+
11
+ class Parser
12
+ attr_accessor(:object_map, :library_map, :section_map, :segment_map)
13
+
14
+ def initialize(options)
15
+ @file_path = options[:file_path]
16
+ @all_objects = options[:all_objects] || false
17
+ @all_symbols = options[:all_symbols] || false
18
+
19
+ unless @file_path
20
+ raise "❌ [Parser] file_path not pass"
21
+ end
22
+
23
+ unless File.exist?(@file_path)
24
+ raise "❌ [Parser] file at #{@file_path} not exist"
25
+ end
26
+
27
+ @object_map = {}
28
+ @library_map = {}
29
+ @section_map = {}
30
+ @segment_map = {}
31
+
32
+ parse
33
+ end
34
+
35
+ #
36
+ # 读取并解析 Linkmap.txt 文件的【每一行】内容
37
+ #
38
+ def parse
39
+ File.foreach(@file_path).with_index do |line, num|
40
+ # begin
41
+ unless line.valid_encoding?
42
+ line = line.encode("UTF-16", :invalid => :replace, :replace => "?").encode('UTF-8')
43
+ end
44
+
45
+ if line.start_with? "#"
46
+ if line.start_with? "# Object files:"
47
+ @subparser = :parse_object_files
48
+ elsif line.start_with? "# Sections:"
49
+ @subparser = :parse_sections
50
+ elsif line.start_with? "# Symbols:"
51
+ @subparser = :parse_symbols
52
+ elsif line.start_with? '# Dead Stripped Symbols:'
53
+ @subparser = :parse_dead_stripped_symbols
54
+ end
55
+ else
56
+ send(@subparser, line)
57
+ end
58
+ # rescue => e
59
+ # UI.error "Exception on LinkMap file line #{num}:"
60
+ # # UI.message line
61
+ # end
62
+ end
63
+ # puts "There are #{@section_map.values.map{|value| value[:residual_size]}.inject(:+)} Byte in some section can not be analyze"
64
+ end
65
+
66
+ def parse_object_files(line)
67
+ ObjectFile.new(line) do |of, type|
68
+ # 保存解析完成的 ObjectFile
69
+ @object_map[of.index] = of
70
+
71
+ # xx.o 没有 Library 的情况
72
+ next if OBJECT_FILE_TYPE_SYSTEM == type #=> 1) system 类型的 xx.o 不创建 Library
73
+ next unless of.library #=> 2) xx.o 没有归属的 library
74
+
75
+ # 创建/获取 xx.o 归属到的 library
76
+ library = @library_map[of.library]
77
+ library ||= Library.new({
78
+ name: of.library,
79
+ size: of.size,
80
+ object_files: Array.new,
81
+ dead_symbol_size: of.dead_symbol_size
82
+ })
83
+
84
+ # 只有【用户】类型的【xx.a】和【xx.framework】, 才可能是 CocoaPods 方式集成, 也才会有 podspec name
85
+ # podspec、subspec
86
+ ## - 1) 没有 subspec
87
+ # /path/to/Pods/BaiduMobAdSDK/BaiduMobAdSDK/BaiduMobAdSDK.framework ==> podspec name: BaiduMobAdSDK
88
+ ## - 2) 有 subspec
89
+ # /path/to/Pods/AlibcSDK/AlibcSDK/Frameworks/UTDID/UTDID.framework ==> podspec name: AlibcSDK, subspec name: UTDID
90
+ # /path/to/Pods/AlibcSDK/AlibcSDK/Frameworks/AliAuthSDK/AlibabaAuthExt.framework ==> podspec name: AlibcSDK, subspec name: AliAuthSDK
91
+ # /path/to/Pods/AlibcSDK/AlibcSDK/Frameworks/AliAuthSDK/AlibabaAuthSDK.framework ==> podspec name: AlibcSDK, subspec name: AliAuthSDK
92
+ #
93
+ # 结论
94
+ # - 1) /path/to/pods/<Podspec#name>/.../xx.framework 或 xx.a
95
+ # - 2) /path/to/pods/<Podspec#name>/.../<Subspec#name>/xx.framework 或 xx.a ==> <Subspec#name> 不好确定
96
+ #
97
+ if OBJECT_FILE_TYPE_USER_LIBRARY == type
98
+ if line.include?('/Pods/')
99
+ # [ 23] /path/to/App/Pods/AFNetworking/AFNetworking.framework/AFNetworking(AFAutoPurgingImageCache.o)
100
+ divstr = line.split('/Pods/').last #=> AFNetworking/AFNetworking.framework/AFNetworking(AFAutoPurgingImageCache.o)
101
+ podspec_name = divstr.split('/').first #=> AFNetworking
102
+ library.podspec_name = podspec_name
103
+ else
104
+ library.podspec_name = nil
105
+ end
106
+ end
107
+
108
+ # library【追加】位于 `# Object Files` 后面【xx.o 目标文件】的 下标值 [ n]
109
+ library.object_files << of.index
110
+
111
+ # 保存/更新 library
112
+ @library_map[of.library] = library
113
+ end
114
+ end
115
+
116
+ def parse_sections(line)
117
+ section = Section.new(line)
118
+ @section_map[section.key] = section
119
+ end
120
+
121
+ def parse_symbols(line)
122
+ symbol = Fastlane::Helper::LinkMap::Symbol.new(line)
123
+ return if symbol.invalid #=> line parse failed
124
+
125
+ object_file = @object_map[symbol.file]
126
+ return unless object_file #=> line can not found object file
127
+
128
+ # 累加1: 一个 ObjectFile 总大小 (包含 N个 Symbol)
129
+ object_file.add_symbol(symbol)
130
+
131
+ # 累加2: 一个 Library 总大小 (包含 N个 ObjectFile)
132
+ library = @library_map[object_file.library]
133
+ library.size += symbol.size if library
134
+
135
+ # 累加3: 一个 Segment 总大小 (包含 N个 Section)
136
+ ## 找到 当前被解析 symbol 所属的 section
137
+ section = @section_map.detect do |_, sec|
138
+ if sec
139
+ (sec.start_addr...sec.end_addr).include?(symbol.address)
140
+ else
141
+ false
142
+ end
143
+ end #=> [:"__TEXT:__text", #<FastlaneCore::Helper::LinkMap::Section:0x00007fd8e3787eb8 ...>]
144
+ ## 再把 当前被解析 symbol 符号总大小, 累加到
145
+ if section
146
+ key = section[0] #=> :"__TEXT:__text"
147
+ value = section[1] #=> #<FastlaneCore::Helper::LinkMap::Section:0x00007fd8e3787eb8 ...>
148
+
149
+ segment_name = value.to_segment #=> 解析出 section 所属的 segment name
150
+ segment = @segment_map[segment_name] #=> 尝试从 segment map 中, 查找是否有 缓存的 segment 对象
151
+
152
+ unless segment
153
+ segment = Segment.new({ name: segment_name, size: symbol.size, residual_size: symbol.size })
154
+ else
155
+ segment.size += symbol.size
156
+ segment.residual_size += symbol.size
157
+ end
158
+
159
+ @segment_map[segment_name] = segment
160
+ end
161
+ end
162
+
163
+ def parse_dead_stripped_symbols(line)
164
+ stripped_symbol = DeadStrippedSymbol.new(line)
165
+ return if stripped_symbol.invalid #=> line parse failed
166
+
167
+ object_file = @object_map[stripped_symbol.file]
168
+ return unless object_file #=> line can not found object file
169
+
170
+ # 累加 一个 ObjectFile 总大小 (包含 N个 Dead Stripped Symbol)
171
+ object_file.dead_symbol_size += stripped_symbol.size
172
+
173
+ # 累加 一个 Library 总大小 (包含 N个 ObjectFile)
174
+ library = @library_map[object_file.library]
175
+ return unless library
176
+ library.dead_symbol_size += stripped_symbol.size
177
+ end
178
+
179
+ def pretty_json
180
+ return @json_result if @json_result
181
+
182
+ @json_result = JSON.pretty_generate(pretty_hash)
183
+ @json_result
184
+ end
185
+
186
+ def pretty_hash
187
+ return @hash_result if @hash_result
188
+
189
+ # sort object_map[i].ObjectFile.symbols
190
+ @object_map.each do |_, object_file|
191
+ next unless object_file.symbols
192
+
193
+ object_file.symbols.sort! do |sym1, sym2|
194
+ sym2.size <=> sym1.size
195
+ end
196
+ end
197
+
198
+ # 计算 linkmap.txt 所有的 symbol 总大小
199
+ total_size = @library_map.values.map(&:size).inject(:+)
200
+ total_dead_size = @library_map.values.map(&:dead_symbol_size).inject(:+)
201
+
202
+ # sort library_map[i]
203
+ sorted_librarys = @library_map.values.sort do |a, b|
204
+ b.size <=> a.size
205
+ end
206
+
207
+ # fixed library_map[i].object_files[i]
208
+ fixed_librarys = sorted_librarys.map { |lib|
209
+ fixed_library = lib.to_hash(@all_objects)
210
+
211
+ if @all_objects
212
+ fixed_library[:object_files] = lib.object_files.map { |object_file_index|
213
+ # 修正 object file [1,2,3,...] ==> ["TXVodPlayerStatsCollection.o", "TXVodDownloadManager.o", "TXUGCVideoRecorder.o", ...]
214
+ object_file = object_map[object_file_index]
215
+
216
+ # fixed library_map[i].object_files[i].symbols 是否打印每一个 object file 下面 all symbol
217
+ if object_file
218
+ object_file.to_hash(@all_symbols)
219
+ else
220
+ nil
221
+ end
222
+ }.compact
223
+ end
224
+
225
+ fixed_library
226
+ }
227
+
228
+ @hash_result = {
229
+ count: fixed_librarys.count,
230
+ size: total_size,
231
+ format_total_size: Fastlane::Helper::LinkMap::FileHelper.format_size(total_size),
232
+ dead_size: total_dead_size,
233
+ format_dead_size: Fastlane::Helper::LinkMap::FileHelper.format_size(total_dead_size),
234
+ librarys: fixed_librarys
235
+ }
236
+ @hash_result
237
+ end
238
+
239
+ def pretty_merge_by_pod_json
240
+ return @merge_json_result if @merge_json_result
241
+ @merge_json_result = JSON.pretty_generate(pretty_merge_by_pod_hash)
242
+ @merge_json_result
243
+ end
244
+
245
+ def pretty_merge_by_pod_hash
246
+ return @merge_hash_result if @merge_hash_result
247
+
248
+ @merge_hash_result = {
249
+ count: pretty_hash[:count],
250
+ size: pretty_hash[:size],
251
+ format_size: pretty_hash[:format_size],
252
+ dead_size: pretty_hash[:dead_size],
253
+ format_dead_size: pretty_hash[:format_dead_size]
254
+ }
255
+
256
+ # 合并 subspec 下的 library
257
+ # AlibcSDK.podspec
258
+ # ------------------------------------------------------------------
259
+ # $ cd /path/to/App/Pods/AlibcSDK/AlibcSDK/Frameworks
260
+ # $ tree -d -L 3
261
+ # .
262
+ # ├── AliAuthSDK
263
+ # │   ├── AlibabaAuthExt.framework
264
+ # │   └── AlibabaAuthSDK.framework
265
+ # ├── AliLinkPartnerSDK
266
+ # │   └── AlibcLinkPartnerSDK.framework
267
+ # ├── AlibcTradeSDK
268
+ # │   ├── AlibcTradeBiz.framework
269
+ # │   └── AlibcTradeSDK.framework
270
+ # ├── BCUserTrack
271
+ # │   └── UTMini.framework
272
+ # ├── UTDID
273
+ # │   └── UTDID.framework
274
+ # ├── mtopSDK
275
+ # │   ├── MtopSDK.framework
276
+ # │   ├── mtopcoreopen.framework
277
+ # │   └── mtopext.framework
278
+ # └── securityGuard
279
+ # ├── SGAVMP.framework
280
+ # ├── SGMain.framework
281
+ # ├── SGMiddleTier.framework
282
+ # ├── SGSecurityBody.framework
283
+ # └── SecurityGuardSDK.framework
284
+ #
285
+ pod_hash = Hash.new
286
+ pretty_hash[:librarys].each_with_object(pod_hash) do |lib, hash|
287
+ apod_librarys = hash[lib[:podspec_name]]
288
+ apod_librarys ||= Array.new
289
+ apod_librarys << lib
290
+ hash[lib[:podspec_name]] = apod_librarys
291
+ end
292
+
293
+ @merge_hash_result[:pods] = pod_hash
294
+ @merge_hash_result
295
+ end
296
+ end
297
+ end
298
+ end
299
+ end