cocoapods-binary-cache-next 0.1.15

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.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/lib/cocoapods-binary-cache/cache/all.rb +9 -0
  3. data/lib/cocoapods-binary-cache/cache/validation_result.rb +73 -0
  4. data/lib/cocoapods-binary-cache/cache/validator.rb +20 -0
  5. data/lib/cocoapods-binary-cache/cache/validator_accumulated.rb +4 -0
  6. data/lib/cocoapods-binary-cache/cache/validator_base.rb +112 -0
  7. data/lib/cocoapods-binary-cache/cache/validator_dependencies_graph.rb +25 -0
  8. data/lib/cocoapods-binary-cache/cache/validator_dev_pods.rb +30 -0
  9. data/lib/cocoapods-binary-cache/cache/validator_exclusion.rb +14 -0
  10. data/lib/cocoapods-binary-cache/cache/validator_non_dev_pods.rb +13 -0
  11. data/lib/cocoapods-binary-cache/cache/validator_with_podfile.rb +9 -0
  12. data/lib/cocoapods-binary-cache/dependencies_graph/dependencies_graph.rb +108 -0
  13. data/lib/cocoapods-binary-cache/dependencies_graph/graph_visualizer.rb +65 -0
  14. data/lib/cocoapods-binary-cache/diagnosis/base.rb +13 -0
  15. data/lib/cocoapods-binary-cache/diagnosis/diagnosis.rb +24 -0
  16. data/lib/cocoapods-binary-cache/diagnosis/integration.rb +23 -0
  17. data/lib/cocoapods-binary-cache/env.rb +32 -0
  18. data/lib/cocoapods-binary-cache/helper/benchmark_show.rb +11 -0
  19. data/lib/cocoapods-binary-cache/helper/checksum.rb +18 -0
  20. data/lib/cocoapods-binary-cache/helper/json.rb +37 -0
  21. data/lib/cocoapods-binary-cache/helper/lockfile.rb +90 -0
  22. data/lib/cocoapods-binary-cache/helper/path_utils.rb +8 -0
  23. data/lib/cocoapods-binary-cache/helper/podspec.rb +20 -0
  24. data/lib/cocoapods-binary-cache/hooks/post_install.rb +23 -0
  25. data/lib/cocoapods-binary-cache/hooks/pre_install.rb +121 -0
  26. data/lib/cocoapods-binary-cache/main.rb +21 -0
  27. data/lib/cocoapods-binary-cache/pod-binary/LICENSE.txt +22 -0
  28. data/lib/cocoapods-binary-cache/pod-binary/helper/build.rb +37 -0
  29. data/lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/installer.rb +25 -0
  30. data/lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/target_definition.rb +29 -0
  31. data/lib/cocoapods-binary-cache/pod-binary/helper/names.rb +27 -0
  32. data/lib/cocoapods-binary-cache/pod-binary/helper/podfile_options.rb +2 -0
  33. data/lib/cocoapods-binary-cache/pod-binary/helper/prebuild_sandbox.rb +71 -0
  34. data/lib/cocoapods-binary-cache/pod-binary/helper/sandbox.rb +9 -0
  35. data/lib/cocoapods-binary-cache/pod-binary/helper/target_checker.rb +42 -0
  36. data/lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb +150 -0
  37. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/embed_framework_script.rb +36 -0
  38. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/resolve_dependencies.rb +20 -0
  39. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/sandbox_analyzer_state.rb +29 -0
  40. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb +55 -0
  41. data/lib/cocoapods-binary-cache/pod-binary/integration/source_installer.rb +114 -0
  42. data/lib/cocoapods-binary-cache/pod-binary/integration/validation.rb +20 -0
  43. data/lib/cocoapods-binary-cache/pod-binary/integration.rb +11 -0
  44. data/lib/cocoapods-binary-cache/pod-binary/prebuild.rb +166 -0
  45. data/lib/cocoapods-binary-cache/pod-binary/prebuild_dsl.rb +10 -0
  46. data/lib/cocoapods-binary-cache/pod-binary/prebuild_hook.rb +10 -0
  47. data/lib/cocoapods-binary-cache/pod-rome/LICENSE.txt +22 -0
  48. data/lib/cocoapods-binary-cache/pod-rome/xcodebuild_command.rb +261 -0
  49. data/lib/cocoapods-binary-cache/pod-rome/xcodebuild_raw.rb +64 -0
  50. data/lib/cocoapods-binary-cache/prebuild_output/metadata.rb +63 -0
  51. data/lib/cocoapods-binary-cache/prebuild_output/output.rb +44 -0
  52. data/lib/cocoapods-binary-cache/state_store.rb +21 -0
  53. data/lib/cocoapods-binary-cache/ui.rb +9 -0
  54. data/lib/cocoapods-binary-cache.rb +2 -0
  55. data/lib/cocoapods_plugin.rb +5 -0
  56. data/lib/command/binary.rb +37 -0
  57. data/lib/command/config.rb +215 -0
  58. data/lib/command/executor/base.rb +37 -0
  59. data/lib/command/executor/fetcher.rb +67 -0
  60. data/lib/command/executor/prebuilder.rb +61 -0
  61. data/lib/command/executor/pusher.rb +35 -0
  62. data/lib/command/executor/visualizer.rb +23 -0
  63. data/lib/command/fetch.rb +22 -0
  64. data/lib/command/helper/zip.rb +20 -0
  65. data/lib/command/prebuild.rb +47 -0
  66. data/lib/command/push.rb +22 -0
  67. data/lib/command/visualize.rb +34 -0
  68. metadata +209 -0
@@ -0,0 +1,261 @@
1
+ require_relative "xcodebuild_raw"
2
+
3
+ module PodPrebuild
4
+ class XcodebuildCommand # rubocop:disable Metrics/ClassLength
5
+ def initialize(options)
6
+ @options = options
7
+ case options[:targets][0].platform.name
8
+ when :ios
9
+ @options[:device] = "iphoneos"
10
+ @options[:simulator] = "iphonesimulator"
11
+ when :tvos
12
+ @options[:device] = "appletvos"
13
+ @options[:simulator] = "appletvsimulator"
14
+ when :watchos
15
+ @options[:device] = "watchos"
16
+ @options[:simulator] = "watchsimulator"
17
+ end
18
+ @build_args = make_up_build_args(options[:args] || {})
19
+ end
20
+
21
+ def run
22
+ sdks.each { |sdk| build_for_sdk(sdk) }
23
+
24
+ targets.each do |target|
25
+ if PodPrebuild.config.xcframework?
26
+ create_xcframework(target)
27
+ elsif sdks.count > 1
28
+ create_fat_framework(target)
29
+ else
30
+ collect_output(target, Dir[target_products_dir_of(target, sdks[0]) + "/*"])
31
+ end
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def sdks
38
+ @sdks ||= begin
39
+ sdks_ = []
40
+ sdks_ << simulator if build_types.include?(:simulator)
41
+ sdks_ << device if build_types.include?(:device)
42
+ sdks_
43
+ end
44
+ end
45
+
46
+ def preferred_sdk
47
+ @preferred_sdk ||= sdks.include?(device) ? device : sdks[0]
48
+ end
49
+
50
+ def build_types
51
+ @build_types ||= begin
52
+ # TODO (thuyen): Add DSL options `build_for_types` to specify build types
53
+ types = [:simulator]
54
+ types << :device if device_build_enabled?
55
+ types
56
+ end
57
+ end
58
+
59
+ def make_up_build_args(args)
60
+ # Note: The build arguments explicitly passed from config_cocoapods_binary_cache
61
+ # should be preceded by the default arguments so that they could take higher priority
62
+ # when there are argument collisions in the xcodebuild command.
63
+ # For ex. `xcodebuild AN_ARG=1 AN_ARG=2` should use `AN_ARG=2` instead.
64
+ args_ = args.clone
65
+ args_[:default] ||= []
66
+ args_[:simulator] ||= []
67
+ args_[:device] ||= []
68
+ args_[:default].prepend("BITCODE_GENERATION_MODE=bitcode") if bitcode_enabled?
69
+ args_[:default].prepend("DEBUG_INFORMATION_FORMAT=dwarf") if disable_dsym?
70
+ args_[:simulator].prepend("ARCHS=x86_64", "ONLY_ACTIVE_ARCH=NO") if simulator == "iphonesimulator"
71
+ args_[:simulator] += args_[:default]
72
+ args_[:device].prepend("ONLY_ACTIVE_ARCH=NO")
73
+ args_[:device] += args_[:default]
74
+ args_
75
+ end
76
+
77
+ def build_for_sdk(sdk)
78
+ PodPrebuild::XcodebuildCommand.xcodebuild(
79
+ sandbox: sandbox,
80
+ scheme: scheme,
81
+ targets: targets.map(&:label),
82
+ configuration: configuration,
83
+ sdk: sdk,
84
+ deployment_target: targets.map { |t| t.platform.deployment_target }.max.to_s,
85
+ log_path: log_path(sdk),
86
+ args: sdk == simulator ? @build_args[:simulator] : @build_args[:device]
87
+ )
88
+ end
89
+
90
+ def create_xcframework(target)
91
+ non_framework_paths = Dir[target_products_dir_of(target, preferred_sdk) + "/*"] \
92
+ - [framework_path_of(target, preferred_sdk)] \
93
+ - dsym_paths_of(target, preferred_sdk) \
94
+ - bcsymbolmap_paths_of(target, preferred_sdk)
95
+ collect_output(target, non_framework_paths)
96
+
97
+ output = "#{output_path(target)}/#{target.product_module_name}.xcframework"
98
+ FileUtils.rm_rf(output)
99
+
100
+ cmd = ["xcodebuild", "-create-xcframework", "-allow-internal-distribution"]
101
+
102
+ # for each sdk, the order of params must be -framework then -debug-symbols
103
+ # to prevent duplicated file error when copying dSYMs
104
+ sdks.each do |sdk|
105
+ cmd << "-framework" << framework_path_of(target, sdk).shellescape
106
+
107
+ unless disable_dsym?
108
+ dsyms = dsym_paths_of(target, sdk)
109
+ cmd += dsyms.map { |dsym| "-debug-symbols #{dsym.shellescape}" }
110
+ end
111
+
112
+ if bitcode_enabled?
113
+ bcsymbolmaps = bcsymbolmap_paths_of(target, sdk)
114
+ cmd += bcsymbolmaps.map { |bcsymbolmap| "-debug-symbols #{bcsymbolmap.shellescape}" }
115
+ end
116
+ end
117
+
118
+ cmd << "-output" << output
119
+
120
+ Pod::UI.puts "- Create xcframework: #{target}".magenta
121
+ Pod::UI.puts_indented "$ #{cmd.join(' ')}" unless PodPrebuild.config.silent_build?
122
+
123
+ `#{cmd.join(" ")}`
124
+ end
125
+
126
+ def create_fat_framework(target)
127
+ # When merging contents of `simulator` & `device`, prefer contents of `device` over `simulator`
128
+ # https://github.com/grab/cocoapods-binary-cache/issues/25
129
+ collect_output(target, Dir[target_products_dir_of(target, device) + "/*"])
130
+
131
+ merge_framework_binary(target)
132
+ merge_framework_dsym(target)
133
+ merge_swift_headers(target)
134
+ merge_swift_modules(target)
135
+ end
136
+
137
+ def merge_framework_binary(target)
138
+ merge_contents(target, "/#{target.product_module_name}", &method(:create_fat_binary))
139
+ end
140
+
141
+ def merge_framework_dsym(target)
142
+ merge_contents(
143
+ target,
144
+ ".dSYM/Contents/Resources/DWARF/#{target.product_module_name}",
145
+ &method(:create_fat_binary)
146
+ )
147
+ end
148
+
149
+ def merge_swift_headers(target)
150
+ merge_contents(target, "/Headers/#{target.product_module_name}-Swift.h") do |options|
151
+ merged_header = <<~HEREDOC
152
+ #if TARGET_OS_SIMULATOR // merged by cocoapods-binary
153
+ #{File.read(options[:simulator])}
154
+ #else // merged by cocoapods-binary
155
+ #{File.read(options[:device])}
156
+ #endif // merged by cocoapods-binary
157
+ HEREDOC
158
+ File.write(options[:output], merged_header.strip)
159
+ end
160
+ end
161
+
162
+ def merge_swift_modules(target)
163
+ merge_contents(target, "/Modules/#{target.product_module_name}.swiftmodule") do |options|
164
+ # Note: swiftmodules of `device` were copied beforehand,
165
+ # here, we only need to copy swiftmodules of `simulator`
166
+ FileUtils.cp_r(options[:simulator] + "/.", options[:output])
167
+ end
168
+ end
169
+
170
+ def merge_contents(target, path_suffix, &merger)
171
+ simulator_, device_, output_ = [
172
+ framework_path_of(target, simulator),
173
+ framework_path_of(target, device),
174
+ "#{output_path(target)}/#{target.product_module_name}.framework"
175
+ ].map { |p| p + path_suffix }
176
+ return unless File.exist?(simulator_) && File.exist?(device_)
177
+
178
+ merger.call(simulator: simulator_, device: device_, output: output_)
179
+ end
180
+
181
+ def create_fat_binary(options)
182
+ cmd = ["lipo", " -create"]
183
+ cmd << "-output" << options[:output]
184
+ cmd << options[:simulator].shellescape << options[:device].shellescape
185
+ `#{cmd.join(" ")}`
186
+ end
187
+
188
+ def collect_output(target, paths)
189
+ FileUtils.mkdir_p(output_path(target))
190
+ paths = [paths] unless paths.is_a?(Array)
191
+ paths.each do |path|
192
+ FileUtils.rm_rf(File.join(output_path(target), File.basename(path)))
193
+ FileUtils.cp_r(path, output_path(target))
194
+ end
195
+ end
196
+
197
+ def target_products_dir_of(target, sdk)
198
+ "#{build_dir}/#{configuration}-#{sdk}/#{target.name}"
199
+ end
200
+
201
+ def framework_path_of(target, sdk)
202
+ "#{target_products_dir_of(target, sdk)}/#{target.product_module_name}.framework"
203
+ end
204
+
205
+ def dsym_paths_of(target, sdk)
206
+ Dir["#{target_products_dir_of(target, sdk)}/*.dSYM"]
207
+ end
208
+
209
+ def bcsymbolmap_paths_of(target, sdk)
210
+ Dir["#{target_products_dir_of(target, sdk)}/*.bcsymbolmap"]
211
+ end
212
+
213
+ def sandbox
214
+ @options[:sandbox]
215
+ end
216
+
217
+ def build_dir
218
+ @options[:build_dir]
219
+ end
220
+
221
+ def output_path(target)
222
+ "#{@options[:output_path]}/#{target.label}"
223
+ end
224
+
225
+ def scheme
226
+ @options[:scheme]
227
+ end
228
+
229
+ def targets
230
+ @options[:targets]
231
+ end
232
+
233
+ def configuration
234
+ @options[:configuration]
235
+ end
236
+
237
+ def bitcode_enabled?
238
+ @options[:bitcode_enabled]
239
+ end
240
+
241
+ def device_build_enabled?
242
+ @options[:device_build_enabled]
243
+ end
244
+
245
+ def device
246
+ @options[:device] || "iphoneos"
247
+ end
248
+
249
+ def simulator
250
+ @options[:simulator] || "iphonesimulator"
251
+ end
252
+
253
+ def disable_dsym?
254
+ @options[:disable_dsym]
255
+ end
256
+
257
+ def log_path(sdk)
258
+ @options[:log_path].nil? ? nil : "#{@options[:log_path]}_#{sdk}"
259
+ end
260
+ end
261
+ end
@@ -0,0 +1,64 @@
1
+ require "fourflusher"
2
+
3
+ module PodPrebuild
4
+ class XcodebuildCommand
5
+ PLATFORM_OF_SDK = {
6
+ "iphonesimulator" => "iOS",
7
+ "appletvsimulator" => "tvOS",
8
+ "watchsimulator" => "watchOS"
9
+ }.freeze
10
+
11
+ DESTINATION_OF_SDK = {
12
+ "iphoneos" => "\"generic/platform=iOS\"",
13
+ "iphonesimulator" => "\"generic/platform=iOS Simulator\""
14
+ }.freeze
15
+
16
+ def self.xcodebuild(options)
17
+ sdk = options[:sdk] || "iphonesimulator"
18
+ targets = options[:targets] || [options[:target]]
19
+ platform = PLATFORM_OF_SDK[sdk]
20
+
21
+ cmd = ["xcodebuild"]
22
+ cmd << "-project" << options[:sandbox].project_path.realdirpath.shellescape
23
+ targets.each { |target| cmd << "-target" << target }
24
+ cmd << "-configuration" << options[:configuration].shellescape
25
+ cmd << "-sdk" << sdk
26
+ if DESTINATION_OF_SDK.key?(sdk)
27
+ cmd << "-destination" << DESTINATION_OF_SDK[sdk]
28
+ else
29
+ unless platform.nil?
30
+ cmd << Fourflusher::SimControl.new.destination(:oldest, platform, options[:deployment_target])
31
+ end
32
+ end
33
+ cmd += options[:args] if options[:args]
34
+ cmd << "build"
35
+
36
+ if options[:log_path].nil?
37
+ cmd << "2>&1"
38
+ else
39
+ FileUtils.mkdir_p(File.dirname(options[:log_path]))
40
+ cmd << "> #{options[:log_path].shellescape}"
41
+ end
42
+ cmd = cmd.join(" ")
43
+
44
+ Pod::UI.puts_indented "$ #{cmd}" unless PodPrebuild.config.silent_build?
45
+
46
+ log = `#{cmd}`
47
+ return if $?.exitstatus.zero? # rubocop:disable Style/SpecialGlobalVars
48
+
49
+ begin
50
+ require "xcpretty" # TODO (thuyen): Revise this dependency
51
+ # use xcpretty to print build log
52
+ # 64 represent command invalid. http://www.manpagez.com/man/3/sysexits/
53
+ printer = XCPretty::Printer.new({:formatter => XCPretty::Simple, :colorize => "auto"})
54
+ log.each_line do |line|
55
+ printer.pretty_print(line)
56
+ end
57
+ rescue
58
+ Pod::UI.puts log.red
59
+ ensure
60
+ raise "Fail to build targets: #{targets}"
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,63 @@
1
+ module PodPrebuild
2
+ class Metadata < JSONFile
3
+ def self.in_dir(dir)
4
+ PodPrebuild::Metadata.new(dir + "metadata.json")
5
+ end
6
+
7
+ def resources
8
+ @data["resources"] || []
9
+ end
10
+
11
+ def resources=(value)
12
+ @data["resources"] = value
13
+ end
14
+
15
+ def framework_name
16
+ @data["framework_name"]
17
+ end
18
+
19
+ def framework_name=(value)
20
+ @data["framework_name"] = value
21
+ end
22
+
23
+ def static_framework?
24
+ @data["static_framework"] || false
25
+ end
26
+
27
+ def static_framework=(value)
28
+ @data["static_framework"] = value
29
+ end
30
+
31
+ def resource_bundles
32
+ @data["resource_bundles"] || []
33
+ end
34
+
35
+ def resource_bundles=(value)
36
+ @data["resource_bundles"] = value
37
+ end
38
+
39
+ def build_settings
40
+ @data["build_settings"] || {}
41
+ end
42
+
43
+ def build_settings=(value)
44
+ @data["build_settings"] = value
45
+ end
46
+
47
+ def source_hash
48
+ @data["source_hash"] || {}
49
+ end
50
+
51
+ def source_hash=(value)
52
+ @data["source_hash"] = value
53
+ end
54
+
55
+ def project_root
56
+ @data["project_root"]
57
+ end
58
+
59
+ def project_root=(value)
60
+ @data["project_root"] = value
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,44 @@
1
+ # Copyright 2019 Grabtaxi Holdings PTE LTE (GRAB), All rights reserved.
2
+ # Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
3
+
4
+ module PodPrebuild
5
+ class Output
6
+ def initialize(prebuild_sandbox)
7
+ @sandbox = prebuild_sandbox
8
+ end
9
+
10
+ def prebuild_delta_path
11
+ @prebuild_delta_path ||= PodPrebuild.config.prebuild_delta_path
12
+ end
13
+
14
+ def delta_dir
15
+ @delta_dir ||= File.dirname(prebuild_delta_path)
16
+ end
17
+
18
+ def clean_delta_file
19
+ Pod::UI.message "Clean delta file: #{prebuild_delta_path}"
20
+ FileUtils.rm_rf(prebuild_delta_path)
21
+ end
22
+
23
+ def create_dir_if_needed(dir)
24
+ FileUtils.mkdir_p dir unless File.directory?(dir)
25
+ end
26
+
27
+ def write_delta_file(options)
28
+ updated = options[:updated]
29
+ deleted = options[:deleted]
30
+
31
+ if updated.empty? && deleted.empty?
32
+ Pod::UI.puts "No changes in prebuild"
33
+ return
34
+ end
35
+
36
+ Pod::UI.message "Write prebuild changes to: #{prebuild_delta_path}"
37
+ create_dir_if_needed(delta_dir)
38
+ changes = PodPrebuild::JSONFile.new(prebuild_delta_path)
39
+ changes["updated"] = updated
40
+ changes["deleted"] = deleted
41
+ changes.save!
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,21 @@
1
+ module PodPrebuild
2
+ def self.state
3
+ @state ||= State.new
4
+ end
5
+
6
+ class State
7
+ def initialize
8
+ @store = {
9
+ :cache_validation => CacheValidationResult.new
10
+ }
11
+ end
12
+
13
+ def update(data)
14
+ @store.merge!(data)
15
+ end
16
+
17
+ def cache_validation
18
+ @store[:cache_validation]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,9 @@
1
+ module Pod
2
+ module UI
3
+ class << self
4
+ def step(message)
5
+ section("❯❯❯ Step: #{message}".magenta) { yield if block_given? }
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ # Copyright 2019 Grabtaxi Holdings PTE LTE (GRAB), All rights reserved.
2
+ # Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
@@ -0,0 +1,5 @@
1
+ # Copyright 2019 Grabtaxi Holdings PTE LTE (GRAB), All rights reserved.
2
+ # Use of this source code is governed by an MIT-style license that can be found in the LICENSE file
3
+
4
+ require "cocoapods-binary-cache/main"
5
+ require "command/binary"
@@ -0,0 +1,37 @@
1
+ require "fileutils"
2
+ require_relative "config"
3
+ require_relative "fetch"
4
+ require_relative "prebuild"
5
+ require_relative "push"
6
+ require_relative "visualize"
7
+
8
+ module Pod
9
+ class Command
10
+ class Binary < Command
11
+ self.abstract_command = true
12
+ def self.options
13
+ [
14
+ ["--repo", "Cache repo (in accordance with `cache_repo` in `config_cocoapods_binary_cache`)"]
15
+ ]
16
+ end
17
+
18
+ def initialize(argv)
19
+ super
20
+ load_podfile
21
+ update_cli_config(:repo => argv.option("repo"))
22
+ end
23
+
24
+ def prebuild_config
25
+ @prebuild_config ||= PodPrebuild.config
26
+ end
27
+
28
+ def load_podfile
29
+ Pod::Config.instance.podfile
30
+ end
31
+
32
+ def update_cli_config(options)
33
+ PodPrebuild.config.cli_config.merge!(options)
34
+ end
35
+ end
36
+ end
37
+ end