zabel 1.0.1 → 1.0.4
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/.gitignore +1 -0
- data/README.md +69 -21
- data/bin/zabel +14 -5
- data/lib/zabel.rb +130 -136
- data/lib/zabel/version.rb +2 -1
- 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: 7bbbbd6d01a9148ff002993ceebe5ed44aba4fd905cb1529689ca40406357aff
|
4
|
+
data.tar.gz: b0ef1fd3e75802bc1ab90f99f3c2910263e84c0fa4352536a7e7515a7e8515c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 842b4eade28085456376de660c8f353108d488caf3f26dcd6308476c2eab2a60cfa67e1c4f5a248cc9a7c4a29d574ecbaa41273d56dd3d323a05a8453698fd11
|
7
|
+
data.tar.gz: 28fdc857de4f92a8c6c806305e858bdd94c5fb2888bc86eaa7fb7f9a3b67ea311ef28bf132ffb4690ab5bea9449f62eb62c5a983fb5f0a9bc1988d38f343cf3b
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
Zabel, is a build cacher for Xcode, using Xcodeproj and MD5, to detect and cache products for targets. Designed for CI by now. Zabel is not Bazel.
|
2
|
+
|
3
|
+
WARNING: BE CAREFUL IN PRODUCTION ENVIRONMENT.
|
4
|
+
|
5
|
+
- [Feature](https://github.com/WeijunDeng/Zabel#feature)
|
6
|
+
- [Installation](https://github.com/WeijunDeng/Zabel#installation)
|
7
|
+
- [Usage](https://github.com/WeijunDeng/Zabel#usage)
|
8
|
+
- [Advanced usage](https://github.com/WeijunDeng/Zabel#advanced-usage)
|
9
|
+
- [Options](https://github.com/WeijunDeng/Zabel#options)
|
10
|
+
- [Changelog](https://github.com/WeijunDeng/Zabel#changelog)
|
11
|
+
- [Development](https://github.com/WeijunDeng/Zabel#development)
|
12
|
+
- [Test](https://github.com/WeijunDeng/Zabel#test)
|
13
|
+
- [Contributing](https://github.com/WeijunDeng/Zabel#contributing)
|
14
|
+
- [License](https://github.com/WeijunDeng/Zabel#license)
|
15
|
+
- [Code of Conduct](https://github.com/WeijunDeng/Zabel#code-of-conduct)
|
16
|
+
- [FAQ](https://github.com/WeijunDeng/Zabel#faq)
|
17
|
+
- [TODO](https://github.com/WeijunDeng/Zabel#todo)
|
4
18
|
|
5
19
|
## Feature
|
6
20
|
|
@@ -19,12 +33,17 @@ Zabel, is a build cacher for Xcode, using Xcodeproj and MD5, to detect and cache
|
|
19
33
|
- support dependent files and implicit dependent targets
|
20
34
|
- support xcodebuild build or archive
|
21
35
|
- support fastlane build or archive
|
36
|
+
- support legacy or new build system
|
22
37
|
|
23
38
|
## Installation
|
24
39
|
|
40
|
+
Please use Ruby 2.x.
|
41
|
+
|
25
42
|
Add this line to your application's Gemfile:
|
26
43
|
|
27
44
|
```ruby
|
45
|
+
source "https://rubygems.org"
|
46
|
+
|
28
47
|
gem 'zabel'
|
29
48
|
```
|
30
49
|
|
@@ -32,27 +51,57 @@ And then execute:
|
|
32
51
|
|
33
52
|
$ bundle
|
34
53
|
|
54
|
+
Or install in local path:
|
55
|
+
|
56
|
+
$ bundle install --path vendor/bundle
|
57
|
+
|
35
58
|
Or install it yourself as:
|
36
59
|
|
37
|
-
$ gem install zabel
|
60
|
+
$ [sudo] gem install zabel
|
38
61
|
|
39
62
|
## Usage
|
40
63
|
|
41
|
-
Simply add zabel before your xcodebuild/fastlane command. Please ensure that your command can work without zabel.
|
64
|
+
Simply add zabel before your xcodebuild/fastlane command. Please ensure that your command can work without zabel.
|
42
65
|
|
43
|
-
|
44
|
-
zabel xcodebuild/fastlane xxx
|
45
|
-
```
|
66
|
+
$ [bundle exec] zabel xcodebuild/fastlane ...
|
46
67
|
|
47
68
|
## Advanced usage
|
48
69
|
|
49
70
|
You can controll your cache keys, which can be more or less. Please ensure that your arguments are same in pre and post.
|
50
71
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
72
|
+
$ [bundle exec] zabel pre -configuration Debug ...
|
73
|
+
$ xcodebuild/fastlane ...
|
74
|
+
$ [bundle exec] zabel post -configuration Debug ...
|
75
|
+
|
76
|
+
Importantly, configuration argument must be set with zabel.
|
77
|
+
|
78
|
+
## Options
|
79
|
+
|
80
|
+
You can customize some options by yourself.
|
81
|
+
|
82
|
+
Zabel stores caches in `~/zabel` by default. You can change this path.
|
83
|
+
|
84
|
+
$ export ZABEL_CACHE_ROOT=xxx
|
85
|
+
|
86
|
+
Zabel uses LRU to clear unuse old caches, to keep max count with 10000 by default. You can change this number.
|
87
|
+
|
88
|
+
$ export ZABEL_CACHE_COUNT=12345
|
89
|
+
|
90
|
+
Zable caches targets which count of source files is greater than or equal 1 by default. You can set this value to 0 or more than 1 to achieve higher total speed.
|
91
|
+
|
92
|
+
$ export ZABEL_MIN_SOURCE_FILE_COUNT=10
|
93
|
+
|
94
|
+
Zabel detects module map dependecy by default. However, there are bugs of xcodebuild or swift-frontend, which emits unnecessary, incorrect and even cycle modulemap dependencies. Cycle dependency targets will be miss every time. To test by run "ruby test/one.rb test/todo/modulemap_file/Podfile". You can disable this feature.
|
95
|
+
|
96
|
+
$ export ZABEL_NOT_DETECT_MODULE_MAP_DEPENDENCY=YES
|
97
|
+
|
98
|
+
## Changelog
|
99
|
+
|
100
|
+
- 1.0.4 optimize spec checksums; optimize output log; use CACHE_VERSION; should not cache if dependency error
|
101
|
+
- 1.0.3 support bundle install
|
102
|
+
- 1.0.2 support legacy build system
|
103
|
+
- 1.0.1 support xcodebuild archive and fastlane
|
104
|
+
- 1.0.0
|
56
105
|
|
57
106
|
## Development
|
58
107
|
|
@@ -71,14 +120,6 @@ ruby test/one.rb test/case/simple/Podfile
|
|
71
120
|
ruby test/one.rb test/todo/modulemap_file/Podfile
|
72
121
|
```
|
73
122
|
|
74
|
-
## TODO
|
75
|
-
|
76
|
-
- support more projects and targets, not only Pods
|
77
|
-
- support and test more clang arguments
|
78
|
-
- support intermediate cache such as .o and .gcno
|
79
|
-
- try to support local development
|
80
|
-
- try to support remote cache server
|
81
|
-
|
82
123
|
## Contributing
|
83
124
|
|
84
125
|
Bug reports and pull requests are welcome on GitHub at https://github.com/WeijunDeng/Zabel. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
@@ -113,4 +154,11 @@ Q: What about dependencies ?
|
|
113
154
|
|
114
155
|
A: Simple dependent files (headers) and implicit dependent targets will be detected. If dependent files of a target change, this target will be recompiled. If dependent targets of a target miss cache, this target and dependent targets will be recompiled.
|
115
156
|
|
157
|
+
## TODO
|
158
|
+
|
159
|
+
- support more projects and targets, not only Pods
|
160
|
+
- support and test more clang arguments
|
161
|
+
- support intermediate cache such as .o and .gcno
|
162
|
+
- try to support local development
|
163
|
+
- try to support remote cache server
|
116
164
|
|
data/bin/zabel
CHANGED
@@ -19,13 +19,22 @@ elsif ARGV.include?("-configuration") or ARGV.include?("--configuration")
|
|
19
19
|
|
20
20
|
build_start_time = Time.now
|
21
21
|
exit 1 unless system(*ARGV)
|
22
|
-
puts "[ZABEL]
|
22
|
+
puts "[ZABEL/I] duration = #{(Time.now - build_start_time).to_i} s in stage build"
|
23
23
|
|
24
24
|
Zabel::zabel_post(ARGV)
|
25
25
|
|
26
|
-
puts "[ZABEL]
|
27
|
-
|
28
|
-
puts "
|
29
|
-
puts "
|
26
|
+
puts "[ZABEL/I] duration = #{(Time.now - total_start_time).to_i} s in stage all"
|
27
|
+
elsif ARGV.size == 0 or (ARGV.size == 1 and ARGV[0].include?("v"))
|
28
|
+
puts "ver: #{Zabel::VERSION}"
|
29
|
+
puts "exe: #{$0}"
|
30
30
|
puts "url: https://github.com/WeijunDeng/Zabel"
|
31
|
+
else
|
32
|
+
puts "Usage: "
|
33
|
+
puts "IMPORTANT: configuration must be set."
|
34
|
+
puts "For example:"
|
35
|
+
puts "zabel xcodebuild archive -workspace app.xcworkspace -scheme app -configuration Debug ..."
|
36
|
+
puts "zabel fastlane gym --workspace app.xcworkspace --scheme app --configuration Debug ..."
|
37
|
+
puts ""
|
38
|
+
puts "Advanced usage:"
|
39
|
+
puts "zabel pre -configuration Debug && xcodebuild/fastlane ... && zabel post -configuration Debug"
|
31
40
|
end
|
data/lib/zabel.rb
CHANGED
@@ -13,6 +13,7 @@ module Zabel
|
|
13
13
|
|
14
14
|
BUILD_KEY_SYMROOT = "SYMROOT"
|
15
15
|
BUILD_KEY_CONFIGURATION_BUILD_DIR = "CONFIGURATION_BUILD_DIR"
|
16
|
+
BUILD_KEY_TARGET_BUILD_DIR = "TARGET_BUILD_DIR"
|
16
17
|
BUILD_KEY_OBJROOT = "OBJROOT"
|
17
18
|
BUILD_KEY_TARGET_TEMP_DIR = "TARGET_TEMP_DIR"
|
18
19
|
BUILD_KEY_PODS_XCFRAMEWORKS_BUILD_DIR = "PODS_XCFRAMEWORKS_BUILD_DIR"
|
@@ -73,19 +74,6 @@ module Zabel
|
|
73
74
|
return 1
|
74
75
|
end
|
75
76
|
|
76
|
-
def self.zabel_should_extract_once
|
77
|
-
# By default, to achieve better compatibility, zabel extracts target cache ondemand,
|
78
|
-
# which means it depends on original dependencies of targets and it is in parallel.
|
79
|
-
# However, extracting once in a shell script build phase rather than multiple shell script build phases,
|
80
|
-
# is a little bit faster in some cases.
|
81
|
-
# You can enable this by set "export ZABEL_EXTRACT_ONCE=YES"
|
82
|
-
should_extract_once = ENV["ZABEL_EXTRACT_ONCE"]
|
83
|
-
if should_extract_once == "YES"
|
84
|
-
return true
|
85
|
-
end
|
86
|
-
return false
|
87
|
-
end
|
88
|
-
|
89
77
|
def self.zabel_get_projects
|
90
78
|
# TODO: to support more project, not only Pods
|
91
79
|
pods_project = Xcodeproj::Project.open("Pods/Pods.xcodeproj")
|
@@ -111,6 +99,7 @@ module Zabel
|
|
111
99
|
|
112
100
|
def self.zabel_can_cache_target(target)
|
113
101
|
if target.name.start_with? "Pods-"
|
102
|
+
puts "[ZABEL/I] skip #{target.name}"
|
114
103
|
return false
|
115
104
|
end
|
116
105
|
if target.class == Xcodeproj::Project::Object::PBXNativeTarget
|
@@ -119,7 +108,11 @@ module Zabel
|
|
119
108
|
target.product_type == "com.apple.product-type.library.static" or
|
120
109
|
target.product_type == "com.apple.product-type.framework"
|
121
110
|
return true
|
111
|
+
else
|
112
|
+
puts "[ZABEL/I] skip #{target.name} #{target.class} #{target.product_type}"
|
122
113
|
end
|
114
|
+
else
|
115
|
+
puts "[ZABEL/I] skip #{target.name} #{target.class}"
|
123
116
|
end
|
124
117
|
return false
|
125
118
|
end
|
@@ -137,7 +130,7 @@ module Zabel
|
|
137
130
|
file = file.gsub("\\ ", " ")
|
138
131
|
|
139
132
|
unless File.exist? file
|
140
|
-
puts "[ZABEL]
|
133
|
+
puts "[ZABEL/E] #{target.name} #{file} should exist in dependency file #{dependency_file}"
|
141
134
|
return []
|
142
135
|
end
|
143
136
|
|
@@ -206,11 +199,11 @@ module Zabel
|
|
206
199
|
file_time_hash[file] = File.mtime(file)
|
207
200
|
end
|
208
201
|
file_list = file_list.sort_by {|file| - file_time_hash[file].to_f}
|
209
|
-
puts "[ZABEL]
|
202
|
+
puts "[ZABEL/I] keep cache " + file_list.size.to_s + " " + Open3.capture3("du -sh #{zabel_get_cache_root}")[0].to_s
|
210
203
|
|
211
204
|
if file_list.size > 1
|
212
|
-
puts "[ZABEL]
|
213
|
-
puts "[ZABEL]
|
205
|
+
puts "[ZABEL/I] keep oldest " + file_time_hash[file_list.last].to_s + " " + file_list.last
|
206
|
+
puts "[ZABEL/I] keep newest " + file_time_hash[file_list.first].to_s + " " + file_list.first
|
214
207
|
end
|
215
208
|
|
216
209
|
if file_list.size > zabel_get_cache_count
|
@@ -254,7 +247,7 @@ module Zabel
|
|
254
247
|
project_configuration_content = project_configuration.pretty_print.to_yaml
|
255
248
|
project_xcconfig = ""
|
256
249
|
if project_configuration.base_configuration_reference
|
257
|
-
config_file_path = project_configuration.base_configuration_reference.real_path
|
250
|
+
config_file_path = project_configuration.base_configuration_reference.real_path.to_s
|
258
251
|
if File.exist? config_file_path
|
259
252
|
project_xcconfig = File.read(config_file_path).lines.reject{|line|line.include? "_SEARCH_PATHS"}.sort.join("")
|
260
253
|
end
|
@@ -263,8 +256,10 @@ module Zabel
|
|
263
256
|
target_configuration = target.build_configurations.detect { | config | config.name == configuration_name}
|
264
257
|
target_configuration_content = target_configuration.pretty_print.to_yaml
|
265
258
|
target_xcconfig = ""
|
259
|
+
target_spec_name = ""
|
266
260
|
if target_configuration.base_configuration_reference
|
267
|
-
config_file_path = target_configuration.base_configuration_reference.real_path
|
261
|
+
config_file_path = target_configuration.base_configuration_reference.real_path.to_s
|
262
|
+
target_spec_name = File.basename(File.dirname(config_file_path))
|
268
263
|
if File.exist? config_file_path
|
269
264
|
target_xcconfig = File.read(config_file_path).lines.reject{|line|line.include? "_SEARCH_PATHS"}.sort.join("")
|
270
265
|
end
|
@@ -301,22 +296,15 @@ module Zabel
|
|
301
296
|
|
302
297
|
source_md5_list = []
|
303
298
|
# zabel built-in verison, which will be changed for incompatibility in the future
|
304
|
-
source_md5_list.push "Zabel version : #{Zabel::
|
299
|
+
source_md5_list.push "Zabel cache version : #{Zabel::CACHE_VERSION}"
|
305
300
|
source_md5_list.push "ARGV : #{key_argv.to_s}"
|
306
301
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
if $zabel_podfile_spec_checksums.has_key? spec_name
|
314
|
-
source_md5_list.push "SPEC CHECKSUM : #{spec_name} #{$zabel_podfile_spec_checksums[spec_name]}"
|
315
|
-
has_found_checksum = true
|
316
|
-
end
|
317
|
-
end
|
318
|
-
unless has_found_checksum
|
319
|
-
puts "[ZABEL]<ERROR> #{target.name} SPEC CHECKSUM should be found"
|
302
|
+
# TODO: to get a explicit spec name from a target.
|
303
|
+
if target_spec_name.size > 0 and $zabel_podfile_spec_checksums.has_key? target_spec_name
|
304
|
+
source_md5_list.push "SPEC CHECKSUM : #{target_spec_name} #{$zabel_podfile_spec_checksums[target_spec_name]}"
|
305
|
+
has_found_checksum = true
|
306
|
+
else
|
307
|
+
puts "[ZABEL/E] #{target.name} #{target_spec_name} SPEC CHECKSUM should be found"
|
320
308
|
end
|
321
309
|
|
322
310
|
source_md5_list.push "Project : #{File.basename(project.path)}"
|
@@ -350,10 +338,6 @@ module Zabel
|
|
350
338
|
command = "rm -rf Pods/*.xcodeproj/*.#{FILE_NAME_TARGET_CONTEXT}"
|
351
339
|
puts command
|
352
340
|
raise unless system command
|
353
|
-
|
354
|
-
command = "rm -rf Pods/zabel.xcodeproj"
|
355
|
-
puts command
|
356
|
-
raise unless system command
|
357
341
|
end
|
358
342
|
|
359
343
|
def self.zabel_add_cache(target, target_context, message)
|
@@ -374,7 +358,7 @@ module Zabel
|
|
374
358
|
end
|
375
359
|
|
376
360
|
unless full_product_name and full_product_name.size > 0 and File.exist? "#{product_dir}/#{full_product_name}"
|
377
|
-
puts "[ZABEL]
|
361
|
+
puts "[ZABEL/E] #{target.name} #{product_dir}/#{full_product_name} should exist"
|
378
362
|
return false
|
379
363
|
end
|
380
364
|
|
@@ -387,12 +371,12 @@ module Zabel
|
|
387
371
|
|
388
372
|
puts command
|
389
373
|
unless system command
|
390
|
-
puts "[ZABEL]
|
374
|
+
puts "[ZABEL/E] #{command} should succeed"
|
391
375
|
return false
|
392
376
|
end
|
393
377
|
|
394
378
|
if File.exist? target_cache_dir
|
395
|
-
puts "[ZABEL]
|
379
|
+
puts "[ZABEL/E] #{target_cache_dir} should not exist"
|
396
380
|
raise unless system "rm -rf \"#{target_cache_dir}\""
|
397
381
|
return false
|
398
382
|
end
|
@@ -400,7 +384,7 @@ module Zabel
|
|
400
384
|
command = "mkdir -p \"#{target_cache_dir}\""
|
401
385
|
unless system command
|
402
386
|
puts command
|
403
|
-
puts "[ZABEL]
|
387
|
+
puts "[ZABEL/E] #{command} should succeed"
|
404
388
|
return false
|
405
389
|
end
|
406
390
|
|
@@ -410,11 +394,11 @@ module Zabel
|
|
410
394
|
puts command
|
411
395
|
unless system command
|
412
396
|
puts command
|
413
|
-
puts "[ZABEL]
|
397
|
+
puts "[ZABEL/E] #{command} should succeed"
|
414
398
|
return false
|
415
399
|
end
|
416
400
|
unless File.exist? cache_product_path
|
417
|
-
puts "[ZABEL]
|
401
|
+
puts "[ZABEL/E] #{cache_product_path} should exist after mv"
|
418
402
|
return false
|
419
403
|
end
|
420
404
|
|
@@ -430,6 +414,7 @@ module Zabel
|
|
430
414
|
target_context.delete(:target_status)
|
431
415
|
target_context.delete(:potential_hit_target_cache_dirs)
|
432
416
|
target_context.delete(:target_md5_content)
|
417
|
+
target_context.delete(:miss_dependency_list)
|
433
418
|
[BUILD_KEY_SYMROOT, BUILD_KEY_CONFIGURATION_BUILD_DIR, BUILD_KEY_OBJROOT, BUILD_KEY_TARGET_TEMP_DIR, BUILD_KEY_PODS_XCFRAMEWORKS_BUILD_DIR, BUILD_KEY_SRCROOT].each do | key |
|
434
419
|
target_context.delete(key)
|
435
420
|
end
|
@@ -450,7 +435,7 @@ module Zabel
|
|
450
435
|
configuration_name = argv[argv.index("--configuration") + 1]
|
451
436
|
end
|
452
437
|
unless configuration_name and configuration_name.size > 0
|
453
|
-
raise "[ZABEL]
|
438
|
+
raise "[ZABEL/E] -configuration or --configuration should be set"
|
454
439
|
end
|
455
440
|
|
456
441
|
start_time = Time.now
|
@@ -462,14 +447,17 @@ module Zabel
|
|
462
447
|
post_targets_context = {}
|
463
448
|
|
464
449
|
projects.each do | project |
|
450
|
+
project_configuration = project.build_configurations.detect { | config | config.name == configuration_name}
|
451
|
+
unless project_configuration
|
452
|
+
puts "[ZABEL/E] #{project.path} should have config #{configuration_name}"
|
453
|
+
next
|
454
|
+
end
|
465
455
|
project.native_targets.each do | target |
|
456
|
+
target_context_file = "#{project.path}/#{target.name}.#{FILE_NAME_TARGET_CONTEXT}"
|
457
|
+
unless File.exist? target_context_file
|
458
|
+
next
|
459
|
+
end
|
466
460
|
if zabel_can_cache_target(target)
|
467
|
-
|
468
|
-
target_context_file = "#{project.path}/#{target.name}.#{FILE_NAME_TARGET_CONTEXT}"
|
469
|
-
unless File.exist? target_context_file
|
470
|
-
next
|
471
|
-
end
|
472
|
-
|
473
461
|
target_context = YAML.load(File.read(target_context_file))
|
474
462
|
|
475
463
|
if target_context[:target_status] == STATUS_MISS
|
@@ -481,7 +469,7 @@ module Zabel
|
|
481
469
|
|
482
470
|
dependency_files = zabel_get_dependency_files(target, intermediate_dir, product_dir, xcframeworks_build_dir)
|
483
471
|
if source_files.size > 0 and dependency_files.size == 0 and target.product_type != "com.apple.product-type.bundle"
|
484
|
-
puts "[ZABEL]
|
472
|
+
puts "[ZABEL/E] #{target.name} should have dependent files"
|
485
473
|
next
|
486
474
|
end
|
487
475
|
target_context[:dependency_files] = dependency_files - source_files
|
@@ -489,7 +477,7 @@ module Zabel
|
|
489
477
|
target_context[:target_md5_content] = target_md5_content
|
490
478
|
target_md5 = Digest::MD5.hexdigest(target_md5_content)
|
491
479
|
unless target_context[:target_md5] == target_md5
|
492
|
-
puts "[ZABEL]
|
480
|
+
puts "[ZABEL/E] #{target.name} md5 should not be changed after build"
|
493
481
|
next
|
494
482
|
end
|
495
483
|
if target_context[BUILD_KEY_SRCROOT] and target_context[BUILD_KEY_SRCROOT].size > 0 and
|
@@ -497,19 +485,19 @@ module Zabel
|
|
497
485
|
if File.exist? Dir.pwd + "/" + zabel_get_content_without_pwd("#{target_context[BUILD_KEY_SRCROOT]}/#{target_context[BUILD_KEY_MODULEMAP_FILE]}")
|
498
486
|
target_context[BUILD_KEY_MODULEMAP_FILE] = zabel_get_content_without_pwd("#{target_context[BUILD_KEY_SRCROOT]}/#{target_context[BUILD_KEY_MODULEMAP_FILE]}")
|
499
487
|
else
|
500
|
-
puts "[ZABEL]
|
488
|
+
puts "[ZABEL/E] #{target.name} #{target_context[BUILD_KEY_MODULEMAP_FILE]} should be supported"
|
501
489
|
next
|
502
490
|
end
|
503
491
|
end
|
504
492
|
elsif target_context[:target_status] == STATUS_HIT
|
505
493
|
if target_context[BUILD_KEY_MODULEMAP_FILE] and target_context[BUILD_KEY_MODULEMAP_FILE].size > 0
|
506
494
|
if not File.exist? Dir.pwd + "/" + target_context[BUILD_KEY_MODULEMAP_FILE]
|
507
|
-
puts "[ZABEL]
|
495
|
+
puts "[ZABEL/E] #{target.name} #{target_context[BUILD_KEY_MODULEMAP_FILE]} should be supported"
|
508
496
|
next
|
509
497
|
end
|
510
498
|
end
|
511
499
|
else
|
512
|
-
puts "[ZABEL]
|
500
|
+
puts "[ZABEL/E] #{target.name} should be hit or miss"
|
513
501
|
next
|
514
502
|
end
|
515
503
|
|
@@ -567,9 +555,17 @@ module Zabel
|
|
567
555
|
|
568
556
|
target_context[:dependency_files] = target_context[:dependency_files] - implicit_dependencies
|
569
557
|
dependency_files_md5 = []
|
558
|
+
should_not_cache = false
|
570
559
|
target_context[:dependency_files].each do | file |
|
560
|
+
if file.start_with? target_context[BUILD_KEY_OBJROOT] + "/" or file.start_with? target_context[BUILD_KEY_SYMROOT] + "/"
|
561
|
+
puts "[ZABEL/W] #{target.name} #{file} dependecy should not include build path"
|
562
|
+
should_not_cache = true
|
563
|
+
break
|
564
|
+
end
|
571
565
|
dependency_files_md5.push [zabel_get_content_without_pwd(file), zabel_get_file_md5(file)]
|
572
566
|
end
|
567
|
+
next if should_not_cache
|
568
|
+
|
573
569
|
target_context[:dependency_files_md5] = dependency_files_md5.sort.uniq
|
574
570
|
|
575
571
|
dependency_targets_md5 = dependency_targets_set.to_a.map { | target | [target.name, post_targets_context[target][:target_md5]]}
|
@@ -590,13 +586,13 @@ module Zabel
|
|
590
586
|
|
591
587
|
zabel_keep
|
592
588
|
|
593
|
-
puts "[ZABEL]
|
589
|
+
puts "[ZABEL/I] total add #{add_count}"
|
594
590
|
|
595
|
-
puts "[ZABEL]
|
591
|
+
puts "[ZABEL/I] duration = #{(Time.now - start_time).to_i} s in stage post"
|
596
592
|
|
597
593
|
end
|
598
594
|
|
599
|
-
def self.zabel_get_potential_hit_target_cache_dirs(target, target_md5)
|
595
|
+
def self.zabel_get_potential_hit_target_cache_dirs(target, target_md5, miss_dependency_list)
|
600
596
|
dependency_start_time = Time.now
|
601
597
|
target_cache_dirs = Dir.glob(zabel_get_cache_root + "/" + target.name + "-" + target_md5 + "-*")
|
602
598
|
file_time_hash = {}
|
@@ -615,12 +611,12 @@ module Zabel
|
|
615
611
|
dependency_md5 = item[1]
|
616
612
|
|
617
613
|
unless File.exist? dependency_file
|
618
|
-
|
614
|
+
miss_dependency_list.push "[ZABEL/W] #{target.name} #{dependency_file} file should exist to be hit"
|
619
615
|
dependency_miss = true
|
620
616
|
break
|
621
617
|
end
|
622
618
|
unless zabel_get_file_md5(dependency_file) == dependency_md5
|
623
|
-
|
619
|
+
miss_dependency_list.push "[ZABEL/W] #{target.name} #{dependency_file} md5 #{zabel_get_file_md5(dependency_file)} should match #{dependency_md5} to be hit"
|
624
620
|
dependency_miss = true
|
625
621
|
break
|
626
622
|
end
|
@@ -629,14 +625,14 @@ module Zabel
|
|
629
625
|
if not target_context[:target_md5] == target_md5
|
630
626
|
command = "rm -rf \"#{target_cache_dir}\""
|
631
627
|
raise unless system command
|
632
|
-
puts "[ZABEL]
|
628
|
+
puts "[ZABEL/E] #{target.name} #{target_cache_dir} target md5 should match to be verified"
|
633
629
|
dependency_miss = false
|
634
630
|
next
|
635
631
|
end
|
636
632
|
if not target_context[:product_md5] == zabel_get_file_md5(target_cache_dir + "/" + FILE_NAME_PRODUCT)
|
637
633
|
command = "rm -rf \"#{target_cache_dir}\""
|
638
634
|
raise unless system command
|
639
|
-
puts "[ZABEL]
|
635
|
+
puts "[ZABEL/E] #{target.name} #{target_cache_dir} product md5 should match to be verified"
|
640
636
|
dependency_miss = false
|
641
637
|
next
|
642
638
|
end
|
@@ -653,23 +649,7 @@ module Zabel
|
|
653
649
|
return potential_hit_target_cache_dirs
|
654
650
|
end
|
655
651
|
|
656
|
-
|
657
|
-
# and this is faster, without searching deeply.
|
658
|
-
def self.zabel_fast_add_dependency(project, target_target, target, subproject_reference)
|
659
|
-
container_proxy = project.new(Xcodeproj::Project::PBXContainerItemProxy)
|
660
|
-
container_proxy.container_portal = subproject_reference.uuid
|
661
|
-
container_proxy.proxy_type = Xcodeproj::Constants::PROXY_TYPES[:native_target]
|
662
|
-
container_proxy.remote_global_id_string = target.uuid
|
663
|
-
container_proxy.remote_info = target.name
|
664
|
-
|
665
|
-
dependency = project.new(Xcodeproj::Project::PBXTargetDependency)
|
666
|
-
dependency.name = target.name
|
667
|
-
dependency.target_proxy = container_proxy
|
668
|
-
|
669
|
-
target_target.dependencies << dependency
|
670
|
-
end
|
671
|
-
|
672
|
-
def self.zabel_disable_build_and_inject_extract(project, target, inject_project, inject_target, inject_scripts, target_context)
|
652
|
+
def self.zabel_disable_build_and_inject_extract(project, target, target_context)
|
673
653
|
target_cache_dir = target_context[:hit_target_cache_dir]
|
674
654
|
|
675
655
|
# touch to update mtime
|
@@ -682,34 +662,24 @@ module Zabel
|
|
682
662
|
build_phase.class == Xcodeproj::Project::Object::PBXResourcesBuildPhase
|
683
663
|
}
|
684
664
|
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
subproject_reference = nil
|
689
|
-
project.main_group.files.each do | file |
|
690
|
-
if file.class == Xcodeproj::Project::Object::PBXFileReference and File.basename(file.path) == File.basename(inject_project.path)
|
691
|
-
subproject_reference = file
|
692
|
-
break
|
693
|
-
end
|
694
|
-
end
|
695
|
-
|
696
|
-
unless subproject_reference
|
697
|
-
subproject_reference = project.main_group.new_reference(inject_project.path, :group)
|
698
|
-
end
|
699
|
-
|
700
|
-
zabel_fast_add_dependency(project, target, inject_target, subproject_reference)
|
701
|
-
|
702
|
-
inject_scripts.push extract_script
|
703
|
-
else
|
704
|
-
inject_phase = target.new_shell_script_build_phase("zabel_extract_#{target.name}")
|
705
|
-
inject_phase.shell_script = extract_script
|
706
|
-
inject_phase.show_env_vars_in_log = '1'
|
665
|
+
zabel_exec = "\"#{$0}\""
|
666
|
+
if ENV["BUNDLE_BIN_PATH"] and ENV["BUNDLE_BIN_PATH"].size > 0 and ENV["BUNDLE_GEMFILE"] and ENV["BUNDLE_GEMFILE"].size > 0
|
667
|
+
zabel_exec = "cd \"#{File.dirname(ENV["BUNDLE_GEMFILE"])}\" && \"#{ENV["BUNDLE_BIN_PATH"]}\" exe zabel"
|
707
668
|
end
|
669
|
+
extract_script = "#{zabel_exec} #{STAGE_EXTRACT} \"#{target_cache_dir}\" \"#{target_context[:build_product_dir]}\" \"#{target_context[:build_intermediate_dir]}\""
|
670
|
+
|
671
|
+
inject_phase = target.new_shell_script_build_phase("zabel_extract_#{target.name}")
|
672
|
+
inject_phase.shell_script = extract_script
|
673
|
+
inject_phase.show_env_vars_in_log = '1'
|
708
674
|
end
|
709
675
|
|
710
676
|
def self.zabel_inject_printenv(project, target)
|
677
|
+
zabel_exec = "\"#{$0}\""
|
678
|
+
if ENV["BUNDLE_BIN_PATH"] and ENV["BUNDLE_BIN_PATH"].size > 0 and ENV["BUNDLE_GEMFILE"] and ENV["BUNDLE_GEMFILE"].size > 0
|
679
|
+
zabel_exec = "cd \"#{File.dirname(ENV["BUNDLE_GEMFILE"])}\" && \"#{ENV["BUNDLE_BIN_PATH"]}\" exe zabel"
|
680
|
+
end
|
711
681
|
inject_phase = target.new_shell_script_build_phase("zabel_printenv_#{target.name}")
|
712
|
-
inject_phase.shell_script = "#{
|
682
|
+
inject_phase.shell_script = "#{zabel_exec} #{STAGE_PRINTENV} #{target.name} \"#{project.path}\""
|
713
683
|
inject_phase.show_env_vars_in_log = '1'
|
714
684
|
end
|
715
685
|
|
@@ -723,7 +693,7 @@ module Zabel
|
|
723
693
|
configuration_name = argv[argv.index("--configuration") + 1]
|
724
694
|
end
|
725
695
|
unless configuration_name and configuration_name.size > 0
|
726
|
-
raise "[ZABEL]
|
696
|
+
raise "[ZABEL/E] -configuration or --configuration should be set"
|
727
697
|
end
|
728
698
|
|
729
699
|
start_time = Time.now
|
@@ -736,15 +706,6 @@ module Zabel
|
|
736
706
|
|
737
707
|
zabel_clean_temp_files
|
738
708
|
|
739
|
-
if zabel_should_extract_once
|
740
|
-
inject_project = Xcodeproj::Project.new("Pods/zabel.xcodeproj")
|
741
|
-
inject_target = inject_project.new_aggregate_target("zabel")
|
742
|
-
inject_phase = inject_target.new_shell_script_build_phase("zabel_extract")
|
743
|
-
inject_phase.show_env_vars_in_log = '1'
|
744
|
-
inject_project.save
|
745
|
-
inject_scripts = []
|
746
|
-
end
|
747
|
-
|
748
709
|
projects = zabel_get_projects
|
749
710
|
|
750
711
|
pre_targets_context = {}
|
@@ -755,19 +716,32 @@ module Zabel
|
|
755
716
|
iteration_count = 0
|
756
717
|
|
757
718
|
projects.each do | project |
|
719
|
+
project_configuration = project.build_configurations.detect { | config | config.name == configuration_name}
|
720
|
+
unless project_configuration
|
721
|
+
puts "[ZABEL/E] #{project.path} should have config #{configuration_name}"
|
722
|
+
next
|
723
|
+
end
|
758
724
|
project.native_targets.each do | target |
|
759
725
|
if zabel_can_cache_target(target)
|
760
726
|
source_files = zabel_get_target_source_files(target)
|
761
|
-
|
727
|
+
unless source_files.size >= zabel_get_min_source_file_count
|
728
|
+
puts "[ZABEL/I] skip #{target.name} #{source_files.size} >= #{zabel_get_min_source_file_count}"
|
729
|
+
next
|
730
|
+
end
|
762
731
|
target_md5_content = zabel_get_target_md5_content(project, target, configuration_name, argv, source_files)
|
763
732
|
target_md5 = Digest::MD5.hexdigest(target_md5_content)
|
764
|
-
|
733
|
+
miss_dependency_list = []
|
734
|
+
potential_hit_target_cache_dirs = zabel_get_potential_hit_target_cache_dirs(target, target_md5, miss_dependency_list)
|
765
735
|
|
766
736
|
target_context = {}
|
767
737
|
target_context[:target_md5] = target_md5
|
768
738
|
target_context[:potential_hit_target_cache_dirs] = potential_hit_target_cache_dirs
|
739
|
+
target_context[:miss_dependency_list] = miss_dependency_list
|
769
740
|
if potential_hit_target_cache_dirs.size == 0
|
770
|
-
|
741
|
+
if miss_dependency_list.size > 0
|
742
|
+
puts miss_dependency_list.uniq.join("\n")
|
743
|
+
end
|
744
|
+
puts "[ZABEL/I] miss #{target.name} #{target_md5} in iteration #{iteration_count}"
|
771
745
|
target_context[:target_status] = STATUS_MISS
|
772
746
|
miss_count = miss_count + 1
|
773
747
|
end
|
@@ -811,7 +785,7 @@ module Zabel
|
|
811
785
|
end
|
812
786
|
end
|
813
787
|
if hit_target_cache_dir
|
814
|
-
puts "[ZABEL]
|
788
|
+
puts "[ZABEL/I] hit #{target.name} #{target_context[:target_md5]} in iteration #{iteration_count} potential #{potential_hit_target_cache_dirs.size}"
|
815
789
|
target_context[:target_status] = STATUS_HIT
|
816
790
|
target_context[:hit_target_cache_dir] = hit_target_cache_dir
|
817
791
|
hit_count = hit_count + 1
|
@@ -831,11 +805,15 @@ module Zabel
|
|
831
805
|
target_context = pre_targets_context[target]
|
832
806
|
|
833
807
|
if target_context[:target_status] == STATUS_HIT
|
834
|
-
zabel_disable_build_and_inject_extract(project, target,
|
808
|
+
zabel_disable_build_and_inject_extract(project, target, target_context)
|
835
809
|
else
|
836
810
|
unless target_context[:target_status] == STATUS_MISS
|
837
811
|
target_context[:target_status] = STATUS_MISS
|
838
|
-
|
812
|
+
miss_dependency_list = target_context[:miss_dependency_list]
|
813
|
+
if miss_dependency_list.size > 0
|
814
|
+
puts miss_dependency_list.uniq.join("\n")
|
815
|
+
end
|
816
|
+
puts "[ZABEL/I] miss #{target.name} #{target_context[:target_md5]} in iteration #{iteration_count}"
|
839
817
|
miss_count = miss_count + 1
|
840
818
|
end
|
841
819
|
zabel_inject_printenv(project, target)
|
@@ -852,29 +830,50 @@ module Zabel
|
|
852
830
|
zabel_clean_backup_project(project)
|
853
831
|
end
|
854
832
|
end
|
855
|
-
|
856
|
-
if zabel_should_extract_once and inject_scripts.size > 0
|
857
|
-
inject_scripts = (["startTime_s=`date +%s`"] + inject_scripts + ["echo \"[ZABEL]<INFO> duration = $[ `date +%s` - $startTime_s ] s in stage #{STAGE_EXTRACT}\""]).flatten
|
858
|
-
inject_phase.shell_script = inject_scripts.join("\n")
|
859
|
-
inject_project.save
|
860
|
-
end
|
861
833
|
|
862
|
-
puts "[ZABEL]
|
834
|
+
puts "[ZABEL/I] total #{hit_count + miss_count} hit #{hit_count} miss #{miss_count} iteration #{iteration_count}"
|
863
835
|
|
864
|
-
puts "[ZABEL]
|
836
|
+
puts "[ZABEL/I] duration = #{(Time.now - start_time).to_i} s in stage pre"
|
865
837
|
end
|
866
838
|
|
867
839
|
def self.zabel_extract
|
840
|
+
puts "[ZABEL/D] #{Time.now.to_f.to_s}"
|
841
|
+
start_time = Time.now
|
842
|
+
|
868
843
|
target_cache_dir = ARGV[1]
|
869
|
-
product_path = ARGV[2]
|
870
844
|
|
871
845
|
cache_product_path = target_cache_dir + "/#{FILE_NAME_PRODUCT}"
|
872
846
|
|
873
847
|
start_time = Time.now
|
874
|
-
|
875
|
-
|
876
|
-
|
877
|
-
|
848
|
+
|
849
|
+
if ENV[BUILD_KEY_CONFIGURATION_BUILD_DIR] != ENV[BUILD_KEY_TARGET_BUILD_DIR]
|
850
|
+
command = "mkdir -p \"#{ENV[BUILD_KEY_CONFIGURATION_BUILD_DIR]}\" && cd \"#{File.dirname(ENV[BUILD_KEY_CONFIGURATION_BUILD_DIR])}/\" && tar -xf \"#{cache_product_path}\""
|
851
|
+
puts command
|
852
|
+
raise unless system command
|
853
|
+
|
854
|
+
command = "rm -rf \"#{ENV[BUILD_KEY_TARGET_BUILD_DIR]+"/"+ENV[BUILD_KEY_FULL_PRODUCT_NAME]}\""
|
855
|
+
puts command
|
856
|
+
raise unless system command
|
857
|
+
|
858
|
+
command = "mkdir -p \"#{File.dirname(ENV[BUILD_KEY_TARGET_BUILD_DIR]+"/"+ENV[BUILD_KEY_FULL_PRODUCT_NAME])}\""
|
859
|
+
puts command
|
860
|
+
raise unless system command
|
861
|
+
|
862
|
+
command = "mv \"#{ENV[BUILD_KEY_CONFIGURATION_BUILD_DIR]+"/"+ENV[BUILD_KEY_FULL_PRODUCT_NAME]}\" \"#{ENV[BUILD_KEY_TARGET_BUILD_DIR]+"/"+ENV[BUILD_KEY_FULL_PRODUCT_NAME]}\""
|
863
|
+
puts command
|
864
|
+
raise unless system command
|
865
|
+
|
866
|
+
command = "/bin/ln -sfh \"#{ENV[BUILD_KEY_TARGET_BUILD_DIR]+"/"+ENV[BUILD_KEY_FULL_PRODUCT_NAME]}\" \"#{ENV[BUILD_KEY_CONFIGURATION_BUILD_DIR]+"/"+ENV[BUILD_KEY_FULL_PRODUCT_NAME]}\""
|
867
|
+
puts command
|
868
|
+
raise unless system command
|
869
|
+
else
|
870
|
+
command = "mkdir -p \"#{ENV[BUILD_KEY_CONFIGURATION_BUILD_DIR]}\" && cd \"#{File.dirname(ENV[BUILD_KEY_CONFIGURATION_BUILD_DIR])}/\" && tar -xf \"#{cache_product_path}\""
|
871
|
+
puts command
|
872
|
+
raise unless system command
|
873
|
+
end
|
874
|
+
|
875
|
+
puts "[ZABEL/I] duration = #{(Time.now - start_time).to_i} s in stage extract"
|
876
|
+
puts "[ZABEL/D] #{Time.now.to_f.to_s}"
|
878
877
|
end
|
879
878
|
|
880
879
|
def self.zabel_printenv
|
@@ -893,11 +892,6 @@ module Zabel
|
|
893
892
|
end
|
894
893
|
|
895
894
|
def self.zabel_clean
|
896
|
-
if File.exist? "Pods/zabel.xcodeproj"
|
897
|
-
command = "rm -rf Pods/*.xcodeproj"
|
898
|
-
puts command
|
899
|
-
raise unless system command
|
900
|
-
end
|
901
895
|
zabel_clean_temp_files
|
902
896
|
end
|
903
897
|
|
data/lib/zabel/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: zabel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- dengweijun
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: xcodeproj
|