fastlane-plugin-analyze_ios_linkmap 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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