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 +4 -4
- data/README.md +56 -17
- data/lib/fastlane/plugin/analyze_ios_linkmap/actions/analyze_ios_linkmap_action.rb +56 -47
- data/lib/fastlane/plugin/analyze_ios_linkmap/helper/analyze_ios_linkmap_parser.rb +299 -0
- data/lib/fastlane/plugin/analyze_ios_linkmap/helper/linkmap_dead_stripped_symbol.rb +38 -0
- data/lib/fastlane/plugin/analyze_ios_linkmap/helper/linkmap_helper.rb +7 -0
- data/lib/fastlane/plugin/analyze_ios_linkmap/helper/linkmap_library.rb +55 -0
- data/lib/fastlane/plugin/analyze_ios_linkmap/helper/linkmap_object_file.rb +143 -0
- data/lib/fastlane/plugin/analyze_ios_linkmap/helper/linkmap_section.rb +71 -0
- data/lib/fastlane/plugin/analyze_ios_linkmap/helper/linkmap_segment.rb +31 -0
- data/lib/fastlane/plugin/analyze_ios_linkmap/helper/linkmap_symbol.rb +41 -0
- data/lib/fastlane/plugin/analyze_ios_linkmap/version.rb +1 -1
- metadata +11 -4
- data/lib/fastlane/plugin/analyze_ios_linkmap/helper/analyze_ios_linkmap_helper.rb +0 -493
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c3bdbca21db75b21aaf970b4116c66ce3bfb4bfda14b606c1eddcc08748b2396
|
4
|
+
data.tar.gz: 40fd82b671e199e38a1215be9a665e08a312440c502e83aacd30c654a3fba9e5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
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/
|
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
|
8
|
-
ANALYZE_IOS_LINKMAP_PARSED_HASH
|
9
|
-
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
|
-
|
16
|
+
file_path = params[:file_path]
|
17
17
|
search_symbol = params[:search_symbol]
|
18
|
-
|
19
|
-
|
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
|
-
|
22
|
-
|
23
|
-
|
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
|
-
|
29
|
-
lib[:
|
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[:
|
35
|
-
object_file: obj[:
|
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: :
|
70
|
+
key: :file_path,
|
56
71
|
description: "/your/path/to/linkmap.txt",
|
57
|
-
verify_block: ->(value) {
|
58
|
-
UI.user_error("❌
|
59
|
-
UI.user_error!("❌
|
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
|
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
|