sbbuild 1.0.0 → 1.1.1
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/bin/sbuild +3 -3
- data/lib/sbuild/version.rb +1 -1
- data/lib/sbuild.rb +512 -487
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8cc91664ba4a0000dddfa6c03bbe269ec17ef4ba9c0243e6f63dd877f299c96e
|
4
|
+
data.tar.gz: 22bef0b81b5f58a4367b170e6d45837ffd3d2465f1dae5ec7b5bec654e52a30b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fa85219ee8b940161d4c66b1bda122176b67b101f912bd4745016a36fc0f9d85c7d698c79c5f7ab6ecd55a0874c11ced5f45a706278070265a8febb2aa86935c
|
7
|
+
data.tar.gz: '086dcb2c7c9a60d7dbab74d7c193f7095cc4957d1b3d316d7a87330ea0fdd6366cd46e91adb0156f2353220f2d57bcca592b4b56263ee52214150748d51bc18d'
|
data/bin/sbuild
CHANGED
@@ -7,15 +7,15 @@ manager = CacheManager.new
|
|
7
7
|
if ARGV[0] == "begin"
|
8
8
|
manager.project_task_begin(ARGV)
|
9
9
|
elsif ARGV[0] == "finish"
|
10
|
-
manager.project_task_end
|
10
|
+
manager.project_task_end(ARGV)
|
11
11
|
elsif ARGV[0] == "cache"
|
12
12
|
manager.add_cache_flag
|
13
13
|
elsif ARGV[0] == "copy"
|
14
14
|
manager.copy_cache
|
15
15
|
elsif ARGV[0] == "target_env"
|
16
16
|
manager.set_target_env
|
17
|
-
elsif ARGV[0] == "
|
18
|
-
manager.
|
17
|
+
elsif ARGV[0] == "main_project_env"
|
18
|
+
manager.set_main_project_env
|
19
19
|
else
|
20
20
|
puts "<ERROR> please input prama such as (begin, finish, inject, copy) "
|
21
21
|
end
|
data/lib/sbuild/version.rb
CHANGED
data/lib/sbuild.rb
CHANGED
@@ -5,6 +5,7 @@ require 'xcodeproj'
|
|
5
5
|
require 'pathname'
|
6
6
|
require "find"
|
7
7
|
require 'set'
|
8
|
+
require 'git'
|
8
9
|
|
9
10
|
#配置
|
10
11
|
|
@@ -17,6 +18,7 @@ CACHE_STATUS_HIT = "hit"
|
|
17
18
|
FILE_NAME_PRODUCT = "product.tar"
|
18
19
|
FILE_NAME_CONTEXT = "context.yml"
|
19
20
|
FILE_NAME_TARGET_CONTEXT = "target_context.yml"
|
21
|
+
FILE_NAME_MAIN_PROJECT_CONTEXT = "project_info.yml"
|
20
22
|
|
21
23
|
#Xcode编译相关常量
|
22
24
|
FULL_PRODUCT_NAME = "FULL_PRODUCT_NAME"
|
@@ -38,344 +40,350 @@ $exclude_target = []
|
|
38
40
|
|
39
41
|
class CacheManager
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
-
|
43
|
+
def get_branch_cache_folder
|
44
|
+
return Dir.home + "/sbBuild" +"/#{$project_build_branch.gsub("/", ".")}"
|
45
|
+
end
|
44
46
|
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
def get_main_project_info_path
|
48
|
+
return Dir.home + "/sbBuild/" + "#{FILE_NAME_MAIN_PROJECT_CONTEXT}"
|
49
|
+
end
|
48
50
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
def is_private_target(target)
|
54
|
-
if target.name.start_with? "AK" or target.name.start_with? "EUR" or target.name.start_with? "A4K"
|
55
|
-
return true
|
56
|
-
else
|
57
|
-
return false
|
58
|
-
end
|
59
|
-
end
|
51
|
+
def get_cache_root_path
|
52
|
+
return Dir.home + "/sbBuild"
|
53
|
+
end
|
60
54
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
55
|
+
def get_default_cache_folder
|
56
|
+
return Dir.home + "/sbBuild/master"
|
57
|
+
end
|
58
|
+
|
59
|
+
def is_private_target(target)
|
60
|
+
if target.name.start_with? "AK" or target.name.start_with? "EUR" or target.name.start_with? "A4K"
|
61
|
+
return true
|
62
|
+
else
|
63
|
+
return false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def get_content_without_pwd(content)
|
68
|
+
content = content.gsub("#{Dir.pwd}/", "").gsub(/#{Dir.pwd}(\W|$)/, '\1')
|
69
|
+
return content
|
70
|
+
end
|
75
71
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
72
|
+
def get_file_md5(file)
|
73
|
+
if $file_md5_hash.has_key? file
|
74
|
+
return $file_md5_hash[file]
|
75
|
+
end
|
76
|
+
md5 = Digest::MD5.hexdigest(File.read(file))
|
77
|
+
$file_md5_hash[file] = md5
|
78
|
+
return md5
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def get_projects(project_path)
|
83
|
+
pods_project_path = "Pods/Pods.xcodeproj"
|
84
|
+
if project_path.length > 0
|
85
|
+
pods_project_path = project_path + "/Pods/Pods.xcodeproj"
|
86
|
+
end
|
87
|
+
pods_project = Xcodeproj::Project.open(pods_project_path)
|
88
|
+
super_project_paths = get_super_project(pods_project)
|
89
|
+
super_projects = []
|
90
|
+
super_project_paths.each do | path |
|
91
|
+
next if path.end_with? pods_project_path
|
92
|
+
project = Xcodeproj::Project.open(path)
|
93
|
+
super_projects.push project
|
94
|
+
end
|
95
|
+
return (super_projects + [pods_project])
|
91
96
|
end
|
92
|
-
return (super_projects + [pods_project])
|
93
|
-
end
|
94
97
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
98
|
+
def get_super_project(project)
|
99
|
+
wrapper_projects = project.files.select{|file|file.last_known_file_type=="wrapper.pb-project"}
|
100
|
+
wrapper_project_paths = []
|
101
|
+
wrapper_projects.each do | wrapper_project_file |
|
102
|
+
wrapper_project_file_path = wrapper_project_file.real_path.to_s
|
103
|
+
wrapper_project_paths.push wrapper_project_file_path
|
104
|
+
end
|
105
|
+
return wrapper_project_paths.uniq
|
106
|
+
end
|
104
107
|
|
108
|
+
|
109
|
+
def backup_project(project)
|
110
|
+
command = "cp \"#{project.path}/project.pbxproj\" \"#{project.path}/ysTest_backup.pbxproj\""
|
111
|
+
raise unless system command
|
112
|
+
end
|
113
|
+
|
114
|
+
def clean_temp_files
|
115
|
+
|
116
|
+
command = "rm -rf Pods/*.xcodeproj/*.#{FILE_NAME_TARGET_CONTEXT}"
|
117
|
+
raise unless system command
|
118
|
+
end
|
105
119
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
|
125
|
-
def can_cache_target(target)
|
126
|
-
if target.product_type == "com.apple.product-type.bundle" or
|
127
|
-
target.product_type == "com.apple.product-type.library.static" or
|
128
|
-
target.product_type == "com.apple.product-type.framework"
|
129
|
-
return true
|
130
|
-
end
|
131
|
-
return false
|
132
|
-
end
|
120
|
+
def restore_project(project)
|
121
|
+
if File.exist? "#{project.path}/ysTest_backup.pbxproj"
|
122
|
+
command = "mv \"#{project.path}/ysTest_backup.pbxproj\" \"#{project.path}/project.pbxproj\""
|
123
|
+
raise unless system command
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
|
128
|
+
def can_cache_target(target)
|
129
|
+
if target.product_type == "com.apple.product-type.bundle" or
|
130
|
+
target.product_type == "com.apple.product-type.library.static" or
|
131
|
+
target.product_type == "com.apple.product-type.framework"
|
132
|
+
return true
|
133
|
+
end
|
134
|
+
return false
|
135
|
+
end
|
133
136
|
|
134
137
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
138
|
+
def get_target_source_files(target)
|
139
|
+
files = []
|
140
|
+
#获取所有可执行文件(.m .swift .cpp .mm)
|
141
|
+
target.source_build_phase.files.each do | file |
|
142
|
+
file_path = file.file_ref.real_path.to_s
|
143
|
+
files.push file_path
|
144
|
+
end
|
142
145
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
def generate_target_all_infomation(project, target, source_files)
|
171
|
-
if $podfile_spec_checksums == nil and File.exist? "#{project.path}/Podfile.lock"
|
172
|
-
podfile_lock = YAML.load(File.read("#{project.path}/Podfile.lock"))
|
173
|
-
$podfile_spec_checksums = podfile_lock["SPEC CHECKSUMS"]
|
174
|
-
end
|
175
|
-
|
176
|
-
project_configuration = project.build_configurations.detect { | config | config.name == $target_build_configuration}
|
177
|
-
project_configuration_content = project_configuration.pretty_print.to_yaml
|
178
|
-
|
179
|
-
project_xcconfig = ""
|
180
|
-
if project_configuration.base_configuration_reference
|
181
|
-
config_file_path = project_configuration.base_configuration_reference.real_path
|
182
|
-
if File.exist? config_file_path
|
183
|
-
project_xcconfig = File.read(config_file_path).lines.reject{|line|line.include? "_SEARCH_PATHS"}.sort.join("")
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
target_configuration = target.build_configurations.detect { | config | config.name == $target_build_configuration}
|
188
|
-
target_configuration_content = target_configuration.pretty_print.to_yaml
|
189
|
-
|
190
|
-
target_xcconfig = ""
|
191
|
-
if target_configuration.base_configuration_reference
|
192
|
-
config_file_path = target_configuration.base_configuration_reference.real_path
|
193
|
-
if File.exist? config_file_path
|
194
|
-
target_xcconfig = File.read(config_file_path).lines.reject{|line|line.include? "_SEARCH_PATHS"}.sort.join("")
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
|
199
|
-
files_configuration = []
|
200
|
-
build_phases = []
|
201
|
-
build_phases.push target.source_build_phase if target.methods.include? :source_build_phase
|
202
|
-
build_phases.push target.resources_build_phase if target.methods.include? :resources_build_phase
|
203
|
-
build_phases.each do | build_phase |
|
204
|
-
target.source_build_phase.files_references.each do | files_reference |
|
205
|
-
if files_reference.class == Xcodeproj::Project::Object::PBXVariantGroup
|
206
|
-
files_reference.files.each do |file_ref_in_group|
|
207
|
-
file_ref_in_group.build_files.each do |build_file|
|
208
|
-
if build_file.settings and build_file.settings.class == Hash
|
209
|
-
first_configuration.push File.basename(build_file.file_ref.real_path.to_s) + "\n" + build_file.settings.to_yaml
|
210
|
-
end
|
211
|
-
end
|
212
|
-
end
|
213
|
-
else
|
214
|
-
files_reference.build_files.each do |build_file|
|
215
|
-
if build_file.settings and build_file.settings.class == Hash
|
216
|
-
files_configuration.push File.basename(build_file.file_ref.real_path.to_s) + "\n" + build_file.settings.to_yaml
|
217
|
-
end
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
files_configuration = files_configuration.sort.uniq.join("\n")
|
222
|
-
|
223
|
-
|
224
|
-
source_md5_list = []
|
225
|
-
has_found_checksum = false
|
226
|
-
split_parts = target.name.split("-")
|
227
|
-
split_parts.each_with_index do | part, index |
|
228
|
-
spec_name = split_parts[0..index].join("-")
|
229
|
-
if $podfile_spec_checksums.has_key? spec_name
|
230
|
-
source_md5_list.push "SPEC CHECKSUM : #{spec_name} #{$podfile_spec_checksums[spec_name]}"
|
231
|
-
has_found_checksum = true
|
232
|
-
end
|
233
|
-
end
|
234
|
-
|
235
|
-
if has_found_checksum
|
236
|
-
if target.name.start_with? "AK" or target.name.start_with? "EUR"
|
237
|
-
|
238
|
-
source_md5_list.push "Project : #{File.basename(project.path)}"
|
239
|
-
source_md5_list.push "Project configuration : "
|
240
|
-
source_md5_list.push project_configuration_content.strip
|
241
|
-
source_md5_list.push "Project xcconfig : "
|
242
|
-
source_md5_list.push project_xcconfig.strip
|
146
|
+
#获取所有头文件(.h)
|
147
|
+
target.headers_build_phase.files.each do | file |
|
148
|
+
file_path = file.file_ref.real_path.to_s
|
149
|
+
files.push file_path
|
150
|
+
end
|
151
|
+
#获取所有资源文件(.png,.strings .json .html)
|
152
|
+
target.resources_build_phase.files.each do | file |
|
153
|
+
file_path = file.file_ref.real_path.to_s
|
154
|
+
files.push file_path
|
155
|
+
end
|
156
|
+
expand_files = []
|
157
|
+
files.uniq.each do | file |
|
158
|
+
next unless File.exist? file
|
159
|
+
if File.file? file
|
160
|
+
expand_files.push file
|
161
|
+
else
|
162
|
+
Find.find(file).each do | file_in_dir |
|
163
|
+
if File.file? file_in_dir
|
164
|
+
expand_files.push file_in_dir
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
return expand_files.uniq
|
170
|
+
end
|
243
171
|
|
244
|
-
source_md5_list.push "Target : #{target.name}, #{target.product_type}"
|
245
|
-
source_md5_list.push "Target configuration : "
|
246
|
-
source_md5_list.push target_configuration_content.strip
|
247
|
-
source_md5_list.push "Target xcconfig : "
|
248
|
-
source_md5_list.push target_xcconfig.strip
|
249
|
-
source_md5_list.push "Files settings : "
|
250
|
-
source_md5_list.push files_configuration.strip
|
251
172
|
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
173
|
+
def generate_target_all_infomation(main_path, project, target, source_files)
|
174
|
+
podfile_lock_path = "Podfile.lock"
|
175
|
+
if main_path.length > 0
|
176
|
+
podfile_lock_path = main_path + "/Podfile.lock"
|
177
|
+
end
|
178
|
+
if $podfile_spec_checksums == nil and File.exist? podfile_lock_path
|
179
|
+
podfile_lock = YAML.load(File.read(podfile_lock_path))
|
180
|
+
$podfile_spec_checksums = podfile_lock["SPEC CHECKSUMS"]
|
181
|
+
end
|
182
|
+
|
183
|
+
project_configuration = project.build_configurations.detect { | config | config.name == $target_build_configuration}
|
184
|
+
project_configuration_content = project_configuration.pretty_print.to_yaml
|
185
|
+
|
186
|
+
project_xcconfig = ""
|
187
|
+
if project_configuration.base_configuration_reference
|
188
|
+
config_file_path = project_configuration.base_configuration_reference.real_path
|
189
|
+
if File.exist? config_file_path
|
190
|
+
project_xcconfig = File.read(config_file_path).lines.reject{|line|line.include? "_SEARCH_PATHS"}.sort.join("")
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
target_configuration = target.build_configurations.detect { | config | config.name == $target_build_configuration}
|
195
|
+
target_configuration_content = target_configuration.pretty_print.to_yaml
|
196
|
+
|
197
|
+
target_xcconfig = ""
|
198
|
+
if target_configuration.base_configuration_reference
|
199
|
+
config_file_path = target_configuration.base_configuration_reference.real_path
|
200
|
+
if File.exist? config_file_path
|
201
|
+
target_xcconfig = File.read(config_file_path).lines.reject{|line|line.include? "_SEARCH_PATHS"}.sort.join("")
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
files_configuration = []
|
207
|
+
build_phases = []
|
208
|
+
build_phases.push target.source_build_phase if target.methods.include? :source_build_phase
|
209
|
+
build_phases.push target.resources_build_phase if target.methods.include? :resources_build_phase
|
210
|
+
build_phases.each do | build_phase |
|
211
|
+
target.source_build_phase.files_references.each do | files_reference |
|
212
|
+
if files_reference.class == Xcodeproj::Project::Object::PBXVariantGroup
|
213
|
+
files_reference.files.each do |file_ref_in_group|
|
214
|
+
file_ref_in_group.build_files.each do |build_file|
|
215
|
+
if build_file.settings and build_file.settings.class == Hash
|
216
|
+
first_configuration.push File.basename(build_file.file_ref.real_path.to_s) + "\n" + build_file.settings.to_yaml
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
else
|
221
|
+
files_reference.build_files.each do |build_file|
|
222
|
+
if build_file.settings and build_file.settings.class == Hash
|
223
|
+
files_configuration.push File.basename(build_file.file_ref.real_path.to_s) + "\n" + build_file.settings.to_yaml
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
files_configuration = files_configuration.sort.uniq.join("\n")
|
230
|
+
|
231
|
+
|
232
|
+
source_md5_list = []
|
233
|
+
has_found_checksum = false
|
234
|
+
split_parts = target.name.split("-")
|
235
|
+
split_parts.each_with_index do | part, index |
|
236
|
+
spec_name = split_parts[0..index].join("-")
|
237
|
+
if $podfile_spec_checksums.has_key? spec_name
|
238
|
+
source_md5_list.push "SPEC CHECKSUM : #{spec_name} #{$podfile_spec_checksums[spec_name]}"
|
239
|
+
has_found_checksum = true
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
if has_found_checksum
|
244
|
+
if target.name.start_with? "AK" or target.name.start_with? "EUR"
|
245
|
+
|
246
|
+
source_md5_list.push "Project : #{File.basename(project.path)}"
|
247
|
+
source_md5_list.push "Project configuration : "
|
248
|
+
source_md5_list.push project_configuration_content.strip
|
249
|
+
source_md5_list.push "Project xcconfig : "
|
250
|
+
source_md5_list.push project_xcconfig.strip
|
251
|
+
|
252
|
+
source_md5_list.push "Target : #{target.name}, #{target.product_type}"
|
253
|
+
source_md5_list.push "Target configuration : "
|
254
|
+
source_md5_list.push target_configuration_content.strip
|
255
|
+
source_md5_list.push "Target xcconfig : "
|
256
|
+
source_md5_list.push target_xcconfig.strip
|
257
|
+
source_md5_list.push "Files settings : "
|
258
|
+
source_md5_list.push files_configuration.strip
|
259
|
+
|
260
|
+
source_md5_list.push "Files MD5 : "
|
261
|
+
source_files.uniq.sort.each do | file |
|
262
|
+
path = file
|
263
|
+
if target.name == "AKULocalizedStrings" or target.name == "EURLocalizedStrings"
|
264
|
+
if file.include? ".swift"
|
265
|
+
source_md5_list.push path + " : " + get_file_md5(path)
|
266
|
+
end
|
267
|
+
else
|
268
|
+
source_md5_list.push path + " : " + get_file_md5(path)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
else
|
272
|
+
source_md5_list.push "Target configuration: #{$target_build_configuration}"
|
273
|
+
end
|
266
274
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
end
|
275
|
+
source_md5_content = source_md5_list.join("\n")
|
276
|
+
return source_md5_content
|
277
|
+
end
|
278
|
+
end
|
272
279
|
|
273
280
|
|
274
281
|
|
275
|
-
|
282
|
+
def get_target_cache(target, target_md5)
|
276
283
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
284
|
+
dependency_start_time = Time.now
|
285
|
+
|
286
|
+
if is_private_target(target)
|
287
|
+
target_cache_dirs = Dir.glob(get_branch_cache_folder + "/" + target.name + "-" + target_md5 + "-*")
|
288
|
+
else
|
289
|
+
target_cache_dirs = Dir.glob(get_default_cache_folder + "/" + target.name + "-" + target_md5 + "-*")
|
290
|
+
end
|
291
|
+
|
292
|
+
hit_results = []
|
293
|
+
|
294
|
+
target_cache_dirs.each do |target_cache_dir|
|
295
|
+
unless File.exist? target_cache_dir + "/" + FILE_NAME_PRODUCT
|
296
|
+
puts "<ERROR> #{target.name} target cache dir missed files: #{target_cache_dir}"
|
297
|
+
next
|
298
|
+
end
|
299
|
+
unless File.exist? target_cache_dir + "/" + FILE_NAME_CONTEXT
|
300
|
+
puts "<ERROR> #{target.name} target cache dir missed files: #{target_cache_dir}"
|
301
|
+
next
|
302
|
+
end
|
303
|
+
|
304
|
+
target_context = YAML.load(File.read(target_cache_dir + "/" + FILE_NAME_CONTEXT))
|
305
|
+
|
306
|
+
if target_context[:target_md5] != target_md5 or target_context[:product_md5] != get_file_md5(target_cache_dir + "/" + FILE_NAME_PRODUCT)
|
307
|
+
command = "rm -rf \"#{target_cache_dir}\""
|
308
|
+
raise unless system command
|
309
|
+
puts "<ERROR> #{target.name} target md5 does not match: #{target_cache_dir}"
|
310
|
+
end
|
311
|
+
|
312
|
+
hit_results.push target_cache_dir
|
306
313
|
|
307
|
-
|
314
|
+
end
|
308
315
|
|
309
|
-
|
316
|
+
return hit_results
|
310
317
|
|
311
|
-
|
318
|
+
end
|
312
319
|
|
313
|
-
|
314
|
-
|
315
|
-
|
320
|
+
def set_main_project_env
|
321
|
+
main_project_name = ARGV[1]
|
322
|
+
main_project_path = ARGV[2]
|
316
323
|
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
324
|
+
target_context = {}
|
325
|
+
if File.exist? get_main_project_info_path
|
326
|
+
target_context = YAML.load(File.read(get_main_project_info_path))
|
327
|
+
else
|
328
|
+
Dir.mkdir(get_cache_root_path)
|
329
|
+
end
|
330
|
+
target_context[main_project_name] = main_project_path
|
331
|
+
File.write(get_main_project_info_path, target_context.to_yaml)
|
332
|
+
end
|
322
333
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
branch_name = ARGV[3]
|
334
|
+
def set_target_env
|
335
|
+
target_name = ARGV[1]
|
336
|
+
project_path = ARGV[2]
|
327
337
|
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
338
|
+
target_context = {}
|
339
|
+
[SYMROOT, OBJROOT, SRCROOT, CONFIGURATION_BUILD_DIR, TARGET_BUILD_DIR, TARGET_TEMP_DIR, FULL_PRODUCT_NAME].sort.each do | key |
|
340
|
+
if ENV[key]
|
341
|
+
target_context[key] = ENV[key]
|
342
|
+
end
|
333
343
|
end
|
344
|
+
target_context[:target_status] = CACHE_STATUS_READY
|
345
|
+
File.write("#{project_path}/#{target_name}.#{FILE_NAME_TARGET_CONTEXT}", target_context.to_yaml)
|
334
346
|
end
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
inject_phase.show_env_vars_in_log = '1'
|
359
|
-
end
|
360
|
-
|
347
|
+
|
348
|
+
def add_cache_flag
|
349
|
+
target_name = ARGV[1]
|
350
|
+
project_path = ARGV[2]
|
351
|
+
if File.exist? "#{project_path}/#{target_name}.#{FILE_NAME_TARGET_CONTEXT}"
|
352
|
+
target_context = YAML.load(File.read("#{project_path}/#{target_name}.#{FILE_NAME_TARGET_CONTEXT}"))
|
353
|
+
[SYMROOT, OBJROOT, SRCROOT, CONFIGURATION_BUILD_DIR, TARGET_BUILD_DIR, TARGET_TEMP_DIR, FULL_PRODUCT_NAME].sort.each do | key |
|
354
|
+
if ENV[key]
|
355
|
+
target_context[key] = ENV[key]
|
356
|
+
end
|
357
|
+
end
|
358
|
+
target_context[:target_status] = CACHE_STATUS_READY
|
359
|
+
File.write("#{project_path}/#{target_name}.#{FILE_NAME_TARGET_CONTEXT}", target_context.to_yaml)
|
360
|
+
end
|
361
|
+
end
|
362
|
+
|
363
|
+
def inject_cache_action(project, target)
|
364
|
+
command_exec = "\"#{$0}\""
|
365
|
+
inject_phase = target.new_shell_script_build_phase("sb_cache_#{target.name}")
|
366
|
+
inject_phase.shell_script = "#{command_exec} #{"cache"} #{target.name} \"#{project.path}\""
|
367
|
+
inject_phase.show_env_vars_in_log = '1'
|
368
|
+
end
|
369
|
+
|
361
370
|
def inject_copy_action(project, target, target_context)
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
371
|
+
target_cache_dir = target_context[:hit_target_cache_dir]
|
372
|
+
|
373
|
+
target.build_phases.delete_if { | build_phase |
|
374
|
+
build_phase.class == Xcodeproj::Project::Object::PBXHeadersBuildPhase or
|
375
|
+
build_phase.class == Xcodeproj::Project::Object::PBXSourcesBuildPhase or
|
376
|
+
build_phase.class == Xcodeproj::Project::Object::PBXResourcesBuildPhase
|
377
|
+
}
|
378
|
+
|
379
|
+
command_exec = "\"#{$0}\""
|
380
|
+
inject_phase = target.new_shell_script_build_phase("sb_copy_#{target.name}")
|
381
|
+
inject_phase.shell_script = "#{command_exec} #{"copy"} \"#{target_cache_dir}\""
|
382
|
+
inject_phase.show_env_vars_in_log = '1'
|
383
|
+
end
|
375
384
|
|
376
385
|
def copy_cache
|
377
386
|
|
378
|
-
puts "<INFO> #{Time.now.to_f.to_s}"
|
379
387
|
start_time = Time.now
|
380
388
|
target_cache_dir = ARGV[1]
|
381
389
|
cache_product_path = target_cache_dir + "/#{FILE_NAME_PRODUCT}"
|
@@ -406,213 +414,230 @@ class CacheManager
|
|
406
414
|
end
|
407
415
|
|
408
416
|
puts "<INFO> duration = #{((Time.now - start_time)*1000).to_i} ms in copy cache action"
|
409
|
-
|
417
|
+
|
410
418
|
end
|
411
419
|
|
412
420
|
|
413
|
-
|
414
|
-
|
415
|
-
target_md5 = target_info[:target_md5]
|
416
|
-
product_dir = target_info[CONFIGURATION_BUILD_DIR]
|
417
|
-
full_product_name = target_info[FULL_PRODUCT_NAME]
|
418
|
-
$project_build_branch = target_info[:branch_name]
|
421
|
+
def add_cache(target, target_info)
|
419
422
|
|
423
|
+
target_md5 = target_info[:target_md5]
|
424
|
+
product_dir = target_info[CONFIGURATION_BUILD_DIR]
|
425
|
+
full_product_name = target_info[FULL_PRODUCT_NAME]
|
420
426
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
427
|
+
unless product_dir.length > 0 and full_product_name.length > 0
|
428
|
+
[SYMROOT, OBJROOT, SRCROOT, CONFIGURATION_BUILD_DIR, TARGET_BUILD_DIR, TARGET_TEMP_DIR, FULL_PRODUCT_NAME].sort.each do | key |
|
429
|
+
if CONFIGURATION_BUILD_DIR and ENV[CONFIGURATION_BUILD_DIR]
|
430
|
+
product_dir = ENV[CONFIGURATION_BUILD_DIR]
|
431
|
+
end
|
426
432
|
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
433
|
+
if FULL_PRODUCT_NAME and ENV[FULL_PRODUCT_NAME]
|
434
|
+
full_product_name = ENV[FULL_PRODUCT_NAME]
|
435
|
+
end
|
436
|
+
end
|
437
|
+
end
|
438
|
+
|
439
|
+
Dir.glob("#{product_dir}/**/*.modulemap").each do | modulemap |
|
440
|
+
modulemap_content = File.read(modulemap)
|
441
|
+
if modulemap_content.include? File.dirname(modulemap) + "/"
|
442
|
+
modulemap_content = modulemap_content.gsub(File.dirname(modulemap) + "/", "")
|
443
|
+
File.write(modulemap, modulemap_content)
|
444
|
+
end
|
445
|
+
end
|
440
446
|
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
447
|
+
unless full_product_name and full_product_name.size > 0 and File.exist? "#{product_dir}/#{full_product_name}"
|
448
|
+
puts "<ERROR> #{target.name} #{product_dir}/#{full_product_name} should exist"
|
449
|
+
return false
|
450
|
+
end
|
451
|
+
|
452
|
+
zip_start_time = Time.now
|
453
|
+
|
454
|
+
command = "cd \"#{File.dirname(product_dir)}\" && tar -L -c -f #{target.name}.#{FILE_NAME_PRODUCT} #{File.basename(product_dir)}/#{full_product_name}"
|
455
|
+
if target.product_type == "com.apple.product-type.library.static"
|
456
|
+
command = "cd \"#{File.dirname(product_dir)}\" && tar --exclude=*.bundle --exclude=*.framework -L -c -f #{target.name}.#{FILE_NAME_PRODUCT} #{File.basename(product_dir)}"
|
457
|
+
end
|
458
|
+
|
459
|
+
unless system command
|
460
|
+
puts "<INFO> #{command} should succeed"
|
461
|
+
return false
|
462
|
+
end
|
457
463
|
|
458
464
|
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
465
|
+
if is_private_target(target)
|
466
|
+
already_target_cache_dirs = Dir.glob(get_branch_cache_folder + "/" + target.name + "-" + target_md5 + "-*")
|
467
|
+
else
|
468
|
+
already_target_cache_dirs = Dir.glob(get_default_cache_folder + "/" + target.name + "-" + target_md5 + "-*")
|
469
|
+
end
|
464
470
|
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
471
|
+
already_target_cache_dirs.each do |path|
|
472
|
+
if File.exist? path
|
473
|
+
raise unless system "rm -rf \"#{path}\""
|
474
|
+
end
|
475
|
+
end
|
470
476
|
|
471
477
|
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
478
|
+
if is_private_target(target)
|
479
|
+
target_cache_dir = get_branch_cache_folder + "/" + target.name + "-" + target_md5 + "-" + (Time.now.to_f * 1000).to_i.to_s
|
480
|
+
else
|
481
|
+
target_cache_dir = get_default_cache_folder + "/" + target.name + "-" + target_md5 + "-" + (Time.now.to_f * 1000).to_i.to_s
|
482
|
+
end
|
477
483
|
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
484
|
+
if File.exist? target_cache_dir
|
485
|
+
puts "<INFO> #{target_cache_dir} should not exist"
|
486
|
+
raise unless system "rm -rf \"#{target_cache_dir}\""
|
487
|
+
return false
|
488
|
+
end
|
489
|
+
|
490
|
+
command = "mkdir -p \"#{target_cache_dir}\""
|
491
|
+
unless system command
|
492
|
+
puts "<INFO> #{command} should succeed"
|
493
|
+
return false
|
494
|
+
end
|
495
|
+
|
496
|
+
cache_product_path = target_cache_dir + "/#{FILE_NAME_PRODUCT}"
|
497
|
+
command = "mv \"#{File.dirname(product_dir)}/#{target.name}.#{FILE_NAME_PRODUCT}\" \"#{cache_product_path}\""
|
498
|
+
unless system command
|
499
|
+
puts "<INFO> #{command} should succeed"
|
500
|
+
return false
|
501
|
+
end
|
502
|
+
unless File.exist? cache_product_path
|
503
|
+
puts "<INFO> #{cache_product_path} should exist after mv"
|
504
|
+
return false
|
505
|
+
end
|
506
|
+
|
507
|
+
target_info[:product_md5] = get_file_md5(cache_product_path)
|
508
|
+
target_info[:build_product_dir] = target_info[CONFIGURATION_BUILD_DIR].gsub(target_info[SYMROOT] + "/", "")
|
509
|
+
target_info[:build_intermediate_dir] = target_info[TARGET_TEMP_DIR].gsub(target_info[OBJROOT] + "/", "")
|
504
510
|
|
505
|
-
|
506
|
-
|
507
|
-
|
511
|
+
target_info.delete(:target_status)
|
512
|
+
target_info.delete(:hit_target_cache_dir)
|
513
|
+
target_info.delete(:target_md5_content)
|
508
514
|
|
509
|
-
|
510
|
-
|
511
|
-
|
515
|
+
File.write(target_cache_dir + "/" + FILE_NAME_CONTEXT, target_info.to_yaml)
|
516
|
+
|
517
|
+
return true
|
512
518
|
|
513
|
-
|
519
|
+
end
|
514
520
|
|
515
521
|
|
516
|
-
|
522
|
+
def project_task_begin(argv)
|
517
523
|
|
518
|
-
|
519
|
-
total_count = 0
|
520
|
-
hit_count = 0
|
521
|
-
miss_count = 0
|
522
|
-
error_count = 0
|
523
|
-
hit_target_md5_cache_set = Set.new
|
524
|
-
miss_target_cache_set = Set.new
|
525
|
-
|
526
|
-
pre_targets_info = {}
|
527
|
-
|
528
|
-
projects.each do |project|
|
529
|
-
# restore_project(project)
|
530
|
-
backup_project(project)
|
531
|
-
end
|
524
|
+
system "pod install"
|
532
525
|
|
533
|
-
|
534
|
-
|
535
|
-
# projects = get_projects
|
536
|
-
|
537
|
-
projects.each do |project|
|
538
|
-
project.native_targets.each do |target|
|
539
|
-
if can_cache_target(target)
|
540
|
-
total_count = total_count + 1
|
541
|
-
source_files = get_target_source_files(target)
|
542
|
-
target_md5_content = generate_target_all_infomation(project, target, source_files)
|
543
|
-
unless target_md5_content
|
544
|
-
puts "<ERROR> target md5 content can not generate: #{target.name}"
|
545
|
-
error_count = error_count + 1
|
546
|
-
next
|
547
|
-
end
|
548
|
-
|
549
|
-
target_md5 = Digest::MD5.hexdigest(target_md5_content)
|
550
|
-
hit_target_cache_dirs = get_target_cache(target, target_md5)
|
551
|
-
target_info = {}
|
552
|
-
|
553
|
-
if hit_target_cache_dirs.count == 0
|
554
|
-
puts "<INFO> #{target.name} #{target_md5} does not hit any cache"
|
555
|
-
target_info[:target_status] = CACHE_STATUS_MISS
|
556
|
-
inject_cache_action(project, target)
|
557
|
-
miss_count = miss_count + 1
|
558
|
-
else
|
559
|
-
target_info[:hit_target_cache_dir] = hit_target_cache_dirs
|
560
|
-
hit_target_md5_cache_set.add "#{target.name}-#{target_md5}"
|
561
|
-
|
562
|
-
if hit_target_cache_dirs.count > 0
|
563
|
-
puts "<INFO> #{target.name} #{target_md5} hit cache"
|
564
|
-
hit_count = hit_count + 1
|
565
|
-
target_really_hit_dir = hit_target_cache_dirs[0]
|
566
|
-
hit_target_info = YAML.load(File.read(target_really_hit_dir + "/" + FILE_NAME_CONTEXT))
|
567
|
-
target_info = target_info.merge!(hit_target_info)
|
568
|
-
target_info[:target_status] = CACHE_STATUS_HIT
|
569
|
-
target_info[:hit_target_cache_dir] = target_really_hit_dir
|
570
|
-
inject_copy_action(project, target, target_info)
|
571
|
-
end
|
572
|
-
end
|
573
|
-
File.write("#{project.path}/#{target.name}.#{FILE_NAME_TARGET_CONTEXT}", target_info.to_yaml)
|
574
|
-
end
|
575
|
-
end
|
576
|
-
project.save
|
577
|
-
end
|
578
|
-
puts "<INFO> total count: #{total_count}, hit count: #{hit_count}, miss_count: #{miss_count}, error_count: #{error_count}"
|
579
|
-
end
|
580
|
-
|
581
|
-
|
582
|
-
def project_task_end
|
583
|
-
|
584
|
-
projects = get_projects
|
585
|
-
post_targets_context = {}
|
586
|
-
total_add_count = 0
|
587
|
-
|
588
|
-
projects.each do |project|
|
589
|
-
project.native_targets.each do | target |
|
590
|
-
target_context_file = "#{project.path}/#{target.name}.#{FILE_NAME_TARGET_CONTEXT}"
|
591
|
-
if can_cache_target(target)
|
592
|
-
if File.exist? target_context_file
|
593
|
-
post_targets_context = YAML.load(File.read(target_context_file))
|
594
|
-
end
|
595
|
-
next unless post_targets_context[:target_status] != CACHE_STATUS_HIT
|
526
|
+
g = Git.open("./")
|
527
|
+
$project_build_branch = g.current_branch
|
596
528
|
|
597
|
-
|
598
|
-
|
599
|
-
|
529
|
+
projects = get_projects("")
|
530
|
+
total_count = 0
|
531
|
+
hit_count = 0
|
532
|
+
miss_count = 0
|
533
|
+
error_count = 0
|
534
|
+
hit_target_md5_cache_set = Set.new
|
535
|
+
miss_target_cache_set = Set.new
|
600
536
|
|
601
|
-
|
537
|
+
pre_targets_info = {}
|
602
538
|
|
603
|
-
|
539
|
+
projects.each do |project|
|
540
|
+
backup_project(project)
|
541
|
+
end
|
604
542
|
|
605
|
-
|
606
|
-
|
607
|
-
|
543
|
+
clean_temp_files
|
544
|
+
|
545
|
+
projects.each do |project|
|
546
|
+
project.native_targets.each do |target|
|
608
547
|
target.build_phases.delete_if { |phase|
|
609
|
-
phase.class == Xcodeproj::Project::Object::PBXShellScriptBuildPhase and phase.name.include? "
|
548
|
+
phase.class == Xcodeproj::Project::Object::PBXShellScriptBuildPhase and phase.name.include? "sb_inject"
|
610
549
|
}
|
550
|
+
if can_cache_target(target)
|
551
|
+
total_count = total_count + 1
|
552
|
+
source_files = get_target_source_files(target)
|
553
|
+
target_md5_content = generate_target_all_infomation("", project, target, source_files)
|
554
|
+
unless target_md5_content
|
555
|
+
puts "<ERROR> target md5 content can not generate: #{target.name}"
|
556
|
+
error_count = error_count + 1
|
557
|
+
next
|
558
|
+
end
|
559
|
+
|
560
|
+
target_md5 = Digest::MD5.hexdigest(target_md5_content)
|
561
|
+
hit_target_cache_dirs = get_target_cache(target, target_md5)
|
562
|
+
target_info = {}
|
563
|
+
|
564
|
+
if hit_target_cache_dirs.count == 0
|
565
|
+
puts "<INFO> #{target.name} #{target_md5} does not hit any cache"
|
566
|
+
target_info[:target_status] = CACHE_STATUS_MISS
|
567
|
+
inject_cache_action(project, target)
|
568
|
+
miss_count = miss_count + 1
|
569
|
+
else
|
570
|
+
target_info[:hit_target_cache_dir] = hit_target_cache_dirs
|
571
|
+
hit_target_md5_cache_set.add "#{target.name}-#{target_md5}"
|
572
|
+
|
573
|
+
if hit_target_cache_dirs.count > 0
|
574
|
+
puts "<INFO> #{target.name} #{target_md5} hit cache"
|
575
|
+
hit_count = hit_count + 1
|
576
|
+
target_really_hit_dir = hit_target_cache_dirs[0]
|
577
|
+
hit_target_info = YAML.load(File.read(target_really_hit_dir + "/" + FILE_NAME_CONTEXT))
|
578
|
+
target_info = target_info.merge!(hit_target_info)
|
579
|
+
target_info[:target_status] = CACHE_STATUS_HIT
|
580
|
+
target_info[:hit_target_cache_dir] = target_really_hit_dir
|
581
|
+
inject_copy_action(project, target, target_info)
|
582
|
+
end
|
583
|
+
end
|
584
|
+
File.write("#{project.path}/#{target.name}.#{FILE_NAME_TARGET_CONTEXT}", target_info.to_yaml)
|
585
|
+
end
|
586
|
+
end
|
587
|
+
project.save
|
588
|
+
end
|
589
|
+
puts "<INFO> total count: #{total_count}, hit count: #{hit_count}, miss_count: #{miss_count}, error_count: #{error_count}"
|
590
|
+
end
|
591
|
+
|
592
|
+
|
593
|
+
def project_task_end(argv)
|
594
|
+
project_name = argv[1]
|
595
|
+
project_path = ""
|
596
|
+
project_path_key = "SBUILD_#{project_name}_PATH"
|
597
|
+
project_path = ENV[project_path_key]
|
598
|
+
if project_path == nil or project_path.length == 0
|
599
|
+
if File.exist? get_main_project_info_path
|
600
|
+
project_info = YAML.load(File.read(get_main_project_info_path))
|
601
|
+
project_path = project_info[project_name]
|
611
602
|
end
|
612
|
-
end
|
613
603
|
end
|
614
|
-
|
604
|
+
raise unless project_path.length > 0
|
605
|
+
|
606
|
+
g = Git.open(project_path)
|
607
|
+
$project_build_branch = g.current_branch
|
608
|
+
|
609
|
+
projects = get_projects(project_path)
|
610
|
+
post_targets_context = {}
|
611
|
+
total_add_count = 0
|
612
|
+
|
613
|
+
projects.each do |project|
|
614
|
+
project.native_targets.each do | target |
|
615
|
+
target_context_file = "#{project.path}/#{target.name}.#{FILE_NAME_TARGET_CONTEXT}"
|
616
|
+
if can_cache_target(target)
|
617
|
+
if File.exist? target_context_file
|
618
|
+
post_targets_context = YAML.load(File.read(target_context_file))
|
619
|
+
end
|
620
|
+
next unless post_targets_context[:target_status] != CACHE_STATUS_HIT
|
621
|
+
|
622
|
+
source_files = get_target_source_files(target)
|
623
|
+
target_md5_content = generate_target_all_infomation(project_path, project, target, source_files)
|
624
|
+
next unless target_md5_content && target_md5_content.length > 0
|
625
|
+
|
626
|
+
cur_target_md5 = Digest::MD5.hexdigest(target_md5_content)
|
627
|
+
|
628
|
+
post_targets_context[:target_md5] = cur_target_md5
|
629
|
+
|
630
|
+
if add_cache(target, post_targets_context)
|
631
|
+
puts "<INFO> #{target} is being added to cache dir"
|
632
|
+
total_add_count = total_add_count + 1
|
633
|
+
target.build_phases.delete_if { |phase|
|
634
|
+
phase.class == Xcodeproj::Project::Object::PBXShellScriptBuildPhase and phase.name.include? "sb_"
|
635
|
+
}
|
636
|
+
end
|
637
|
+
end
|
638
|
+
end
|
639
|
+
restore_project(project)
|
640
|
+
end
|
641
|
+
puts "<INFO> total add cache count: #{total_add_count}"
|
615
642
|
end
|
616
|
-
puts "<INFO> total add cache count: #{total_add_count}"
|
617
|
-
end
|
618
643
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sbbuild
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yusheng
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: xcodeproj
|