cocoapods-binary-cache 0.1.7 → 0.1.12

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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/lib/cocoapods-binary-cache/cache/validation_result.rb +4 -0
  3. data/lib/cocoapods-binary-cache/dependencies_graph/dependencies_graph.rb +20 -25
  4. data/lib/cocoapods-binary-cache/dependencies_graph/graph_visualizer.rb +29 -38
  5. data/lib/cocoapods-binary-cache/diagnosis/diagnosis.rb +9 -1
  6. data/lib/cocoapods-binary-cache/diagnosis/integration.rb +3 -1
  7. data/lib/cocoapods-binary-cache/helper/podspec.rb +4 -2
  8. data/lib/cocoapods-binary-cache/hooks/post_install.rb +2 -12
  9. data/lib/cocoapods-binary-cache/hooks/pre_install.rb +19 -36
  10. data/lib/cocoapods-binary-cache/main.rb +0 -1
  11. data/lib/cocoapods-binary-cache/pod-binary/helper/build.rb +27 -29
  12. data/lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/installer.rb +1 -1
  13. data/lib/cocoapods-binary-cache/pod-binary/helper/prebuild_sandbox.rb +14 -13
  14. data/lib/cocoapods-binary-cache/pod-binary/helper/target_checker.rb +7 -10
  15. data/lib/cocoapods-binary-cache/pod-binary/integration.rb +1 -2
  16. data/lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb +32 -15
  17. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/embed_framework_script.rb +1 -1
  18. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/resolve_dependencies.rb +0 -3
  19. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/sandbox_analyzer_state.rb +29 -0
  20. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb +25 -11
  21. data/lib/cocoapods-binary-cache/pod-binary/integration/source_installer.rb +30 -19
  22. data/lib/cocoapods-binary-cache/pod-binary/prebuild.rb +30 -108
  23. data/lib/cocoapods-binary-cache/pod-binary/prebuild_dsl.rb +0 -2
  24. data/lib/cocoapods-binary-cache/pod-binary/prebuild_hook.rb +0 -1
  25. data/lib/cocoapods-binary-cache/pod-rome/xcodebuild_command.rb +222 -146
  26. data/lib/cocoapods-binary-cache/pod-rome/xcodebuild_raw.rb +45 -32
  27. data/lib/cocoapods-binary-cache/prebuild_output/output.rb +6 -4
  28. data/lib/cocoapods-binary-cache/state_store.rb +16 -6
  29. data/lib/command/config.rb +42 -4
  30. data/lib/command/executor/base.rb +18 -1
  31. data/lib/command/executor/fetcher.rb +21 -3
  32. data/lib/command/executor/prebuilder.rb +9 -7
  33. data/lib/command/executor/pusher.rb +20 -4
  34. data/lib/command/executor/visualizer.rb +3 -2
  35. data/lib/command/prebuild.rb +6 -0
  36. metadata +17 -7
  37. data/lib/cocoapods-binary-cache/pod-binary/helper/feature_switches.rb +0 -52
  38. data/lib/cocoapods-binary-cache/pod-binary/helper/passer.rb +0 -25
  39. data/lib/cocoapods-binary-cache/pod-binary/integration/remove_target_files.rb +0 -29
  40. data/lib/cocoapods-binary-cache/pod-binary/tool/tool.rb +0 -12
  41. data/lib/cocoapods-binary-cache/scheme_editor.rb +0 -35
@@ -1,5 +1,3 @@
1
- require_relative "tool/tool"
2
-
3
1
  module Pod
4
2
  class Podfile
5
3
  module DSL
@@ -1,4 +1,3 @@
1
- require_relative "helper/passer"
2
1
  require_relative "helper/podfile_options"
3
2
  require_relative "helper/prebuild_sandbox"
4
3
 
@@ -1,176 +1,252 @@
1
1
  require_relative "xcodebuild_raw"
2
2
 
3
- class XcodebuildCommand
4
- def initialize(options)
5
- @options = options
6
- case options[:target].platform.name
7
- when :ios
8
- @options[:device] = "iphoneos"
9
- @options[:simulator] = "iphonesimulator"
10
- when :tvos
11
- @options[:device] = "appletvos"
12
- @options[:simulator] = "appletvsimulator"
13
- when :watchos
14
- @options[:device] = "watchos"
15
- @options[:simulator] = "watchsimulator"
16
- end
17
- @build_args = make_up_build_args(options[:args] || {})
18
- end
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
19
20
 
20
- def run
21
- build_for_sdk(simulator)
22
- if device_build_enabled?
23
- build_for_sdk(device)
24
- create_universal_framework
25
- merge_dsym unless disable_dsym?
26
- merge_swift_headers
27
- merge_swift_modules
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
28
33
  end
29
- collect_output(Dir[target_products_dir_of(simulator) + "/*"])
30
- end
31
34
 
32
- private
33
-
34
- def make_up_build_args(args)
35
- args_ = args.clone
36
- args_[:default] ||= []
37
- args_[:simulator] ||= []
38
- args_[:device] ||= []
39
- args_[:default] += ["BITCODE_GENERATION_MODE=bitcode"] if bitcode_enabled?
40
- args_[:default] += ["DEBUG_INFORMATION_FORMAT=dwarf"] if disable_dsym?
41
- args_[:simulator] += ["ARCHS=x86_64", "ONLY_ACTIVE_ARCH=NO"] if simulator == "iphonesimulator"
42
- args_[:simulator] += args_[:default]
43
- args_[:device] += args_[:default]
44
- args_
45
- end
35
+ private
46
36
 
47
- def build_for_sdk(sdk)
48
- framework_path = framework_path_of(sdk)
49
- if Dir.exist?(framework_path)
50
- Pod::UI.puts "Framework already exists at: #{framework_path}"
51
- return
52
- end
53
-
54
- succeeded, = xcodebuild(
55
- sandbox: sandbox,
56
- target: target.label,
57
- configuration: configuration,
58
- sdk: sdk,
59
- deployment_target: target.platform.deployment_target.to_s,
60
- args: sdk == simulator ? @build_args[:simulator] : @build_args[:device]
61
- )
62
- raise "Build framework failed: #{target.label}" unless succeeded
63
- end
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
64
45
 
65
- def create_universal_framework
66
- create_fat_binary(
67
- simulator: "#{framework_path_of(simulator)}/#{module_name}",
68
- device: "#{framework_path_of(device)}/#{module_name}"
69
- )
70
- end
46
+ def build_types
47
+ @build_types ||= begin
48
+ # TODO (thuyen): Add DSL options `build_for_types` to specify build types
49
+ types = [:simulator]
50
+ types << :device if device_build_enabled?
51
+ types
52
+ end
53
+ end
71
54
 
72
- def merge_dsym
73
- simulator_dsym = framework_path_of(simulator) + ".dSYM"
74
- device_dsym = framework_path_of(device) + ".dSYM"
75
- return unless File.exist?(simulator_dsym) && File.exist?(device_dsym)
55
+ def make_up_build_args(args)
56
+ # Note: The build arguments explicitly passed from config_cocoapods_binary_cache
57
+ # should be preceded by the default arguments so that they could take higher priority
58
+ # when there are argument collisions in the xcodebuild command.
59
+ # For ex. `xcodebuild AN_ARG=1 AN_ARG=2` should use `AN_ARG=2` instead.
60
+ args_ = args.clone
61
+ args_[:default] ||= []
62
+ args_[:simulator] ||= []
63
+ args_[:device] ||= []
64
+ args_[:default].prepend("BITCODE_GENERATION_MODE=bitcode") if bitcode_enabled?
65
+ args_[:default].prepend("DEBUG_INFORMATION_FORMAT=dwarf") if disable_dsym?
66
+ args_[:simulator].prepend("ARCHS=x86_64", "ONLY_ACTIVE_ARCH=NO") if simulator == "iphonesimulator"
67
+ args_[:simulator] += args_[:default]
68
+ args_[:device].prepend("ONLY_ACTIVE_ARCH=NO")
69
+ args_[:device] += args_[:default]
70
+ args_
71
+ end
76
72
 
77
- create_fat_binary(
78
- simulator: "#{simulator_dsym}/Contents/Resources/DWARF/#{module_name}",
79
- device: "#{device_dsym}/Contents/Resources/DWARF/#{module_name}"
80
- )
81
- collect_output(simulator_dsym)
82
- end
73
+ def build_for_sdk(sdk)
74
+ PodPrebuild::XcodebuildCommand.xcodebuild(
75
+ sandbox: sandbox,
76
+ scheme: scheme,
77
+ targets: targets.map(&:label),
78
+ configuration: configuration,
79
+ sdk: sdk,
80
+ deployment_target: targets.map { |t| t.platform.deployment_target }.max.to_s,
81
+ args: sdk == simulator ? @build_args[:simulator] : @build_args[:device]
82
+ )
83
+ end
83
84
 
84
- def create_fat_binary(options)
85
- cmd = ["lipo", " -create"]
86
- cmd << "-output" << options[:simulator]
87
- cmd << options[:simulator] << options[:device]
88
- Pod::UI.puts `#{cmd.join(" ")}`
89
- end
85
+ def create_xcframework(target)
86
+ non_framework_paths = Dir[target_products_dir_of(target, sdks[0]) + "/*"] \
87
+ - [framework_path_of(target, sdks[0])] \
88
+ - dsym_paths_of(target, sdks[0]) \
89
+ - bcsymbolmap_paths_of(target, sdks[0])
90
+ collect_output(target, non_framework_paths)
90
91
 
91
- def merge_swift_headers
92
- simulator_header_path = framework_path_of(simulator) + "/Headers/#{module_name}-Swift.h"
93
- device_header_path = framework_path_of(device) + "/Headers/#{module_name}-Swift.h"
94
- return unless File.exist?(simulator_header_path) && File.exist?(device_header_path)
95
-
96
- merged_header = <<~HEREDOC
97
- #if TARGET_OS_SIMULATOR // merged by cocoapods-binary
98
- #{File.read(simulator_header_path)}
99
- #else // merged by cocoapods-binary
100
- #{File.read(device_header_path)}
101
- #endif // merged by cocoapods-binary
102
- HEREDOC
103
- File.write(simulator_header_path, merged_header.strip)
104
- end
92
+ output = "#{output_path(target)}/#{target.product_module_name}.xcframework"
93
+ FileUtils.rm_rf(output)
105
94
 
106
- def merge_swift_modules
107
- simulator_swift_module_path = framework_path_of(simulator) + "/Modules/#{module_name}.swiftmodule"
108
- device_swift_module_path = framework_path_of(device) + "/Modules/#{module_name}.swiftmodule"
109
- return unless File.exist?(simulator_swift_module_path) && File.exist?(device_swift_module_path)
95
+ cmd = ["xcodebuild", "-create-xcframework", "-allow-internal-distribution"]
110
96
 
111
- FileUtils.cp_r(
112
- device_swift_module_path + "/.",
113
- simulator_swift_module_path
114
- )
115
- end
97
+ # for each sdk, the order of params must be -framework then -debug-symbols
98
+ # to prevent duplicated file error when copying dSYMs
99
+ sdks.each do |sdk|
100
+ cmd << "-framework" << framework_path_of(target, sdk)
101
+
102
+ unless disable_dsym?
103
+ dsyms = dsym_paths_of(target, sdk)
104
+ cmd += dsyms.map { |dsym| "-debug-symbols #{dsym}" }
105
+ end
106
+
107
+ if bitcode_enabled?
108
+ bcsymbolmaps = bcsymbolmap_paths_of(target, sdk)
109
+ cmd += bcsymbolmaps.map { |bcsymbolmap| "-debug-symbols #{bcsymbolmap}" }
110
+ end
111
+ end
112
+
113
+ cmd << "-output" << output
116
114
 
117
- def collect_output(paths)
118
- paths = [paths] unless paths.is_a?(Array)
119
- paths.each do |path|
120
- FileUtils.rm_rf(File.join(output_path, File.basename(path)))
121
- FileUtils.mv(path, output_path)
115
+ Pod::UI.puts "- Create xcframework: #{target}".magenta
116
+ Pod::UI.puts_indented "$ #{cmd.join(' ')}" unless PodPrebuild.config.silent_build?
117
+
118
+ `#{cmd.join(" ")}`
122
119
  end
123
- end
124
120
 
125
- def target_products_dir_of(sdk)
126
- "#{build_dir}/#{configuration}-#{sdk}/#{target.name}"
127
- end
121
+ def create_fat_framework(target)
122
+ # When merging contents of `simulator` & `device`, prefer contents of `device` over `simulator`
123
+ # https://github.com/grab/cocoapods-binary-cache/issues/25
124
+ collect_output(target, Dir[target_products_dir_of(target, device) + "/*"])
128
125
 
129
- def framework_path_of(sdk)
130
- "#{target_products_dir_of(sdk)}/#{module_name}.framework"
131
- end
126
+ merge_framework_binary(target)
127
+ merge_framework_dsym(target)
128
+ merge_swift_headers(target)
129
+ merge_swift_modules(target)
130
+ end
132
131
 
133
- def module_name
134
- target.product_module_name
135
- end
132
+ def merge_framework_binary(target)
133
+ merge_contents(target, "/#{target.product_module_name}", &method(:create_fat_binary))
134
+ end
136
135
 
137
- def sandbox
138
- @options[:sandbox]
139
- end
136
+ def merge_framework_dsym(target)
137
+ merge_contents(
138
+ target,
139
+ ".dSYM/Contents/Resources/DWARF/#{target.product_module_name}",
140
+ &method(:create_fat_binary)
141
+ )
142
+ end
140
143
 
141
- def build_dir
142
- @options[:build_dir]
143
- end
144
+ def merge_swift_headers(target)
145
+ merge_contents(target, "/Headers/#{target.product_module_name}-Swift.h") do |options|
146
+ merged_header = <<~HEREDOC
147
+ #if TARGET_OS_SIMULATOR // merged by cocoapods-binary
148
+ #{File.read(options[:simulator])}
149
+ #else // merged by cocoapods-binary
150
+ #{File.read(options[:device])}
151
+ #endif // merged by cocoapods-binary
152
+ HEREDOC
153
+ File.write(options[:output], merged_header.strip)
154
+ end
155
+ end
144
156
 
145
- def output_path
146
- @options[:output_path]
147
- end
157
+ def merge_swift_modules(target)
158
+ merge_contents(target, "/Modules/#{target.product_module_name}.swiftmodule") do |options|
159
+ # Note: swiftmodules of `device` were copied beforehand,
160
+ # here, we only need to copy swiftmodules of `simulator`
161
+ FileUtils.cp_r(options[:simulator] + "/.", options[:output])
162
+ end
163
+ end
148
164
 
149
- def target
150
- @options[:target]
151
- end
165
+ def merge_contents(target, path_suffix, &merger)
166
+ simulator_, device_, output_ = [
167
+ framework_path_of(target, simulator),
168
+ framework_path_of(target, device),
169
+ "#{output_path(target)}/#{target.product_module_name}.framework"
170
+ ].map { |p| p + path_suffix }
171
+ return unless File.exist?(simulator_) && File.exist?(device_)
152
172
 
153
- def configuration
154
- @options[:configuration]
155
- end
173
+ merger.call(simulator: simulator_, device: device_, output: output_)
174
+ end
156
175
 
157
- def bitcode_enabled?
158
- @options[:bitcode_enabled]
159
- end
176
+ def create_fat_binary(options)
177
+ cmd = ["lipo", " -create"]
178
+ cmd << "-output" << options[:output]
179
+ cmd << options[:simulator] << options[:device]
180
+ `#{cmd.join(" ")}`
181
+ end
160
182
 
161
- def device_build_enabled?
162
- @options[:device_build_enabled]
163
- end
183
+ def collect_output(target, paths)
184
+ FileUtils.mkdir_p(output_path(target))
185
+ paths = [paths] unless paths.is_a?(Array)
186
+ paths.each do |path|
187
+ FileUtils.rm_rf(File.join(output_path(target), File.basename(path)))
188
+ FileUtils.cp_r(path, output_path(target))
189
+ end
190
+ end
164
191
 
165
- def device
166
- @options[:device] || "iphoneos"
167
- end
192
+ def target_products_dir_of(target, sdk)
193
+ "#{build_dir}/#{configuration}-#{sdk}/#{target.name}"
194
+ end
168
195
 
169
- def simulator
170
- @options[:simulator] || "iphonesimulator"
171
- end
196
+ def framework_path_of(target, sdk)
197
+ "#{target_products_dir_of(target, sdk)}/#{target.product_module_name}.framework"
198
+ end
172
199
 
173
- def disable_dsym?
174
- @options[:disable_dsym]
200
+ def dsym_paths_of(target, sdk)
201
+ Dir["#{target_products_dir_of(target, sdk)}/*.dSYM"]
202
+ end
203
+
204
+ def bcsymbolmap_paths_of(target, sdk)
205
+ Dir["#{target_products_dir_of(target, sdk)}/*.bcsymbolmap"]
206
+ end
207
+
208
+ def sandbox
209
+ @options[:sandbox]
210
+ end
211
+
212
+ def build_dir
213
+ @options[:build_dir]
214
+ end
215
+
216
+ def output_path(target)
217
+ "#{@options[:output_path]}/#{target.label}"
218
+ end
219
+
220
+ def scheme
221
+ @options[:scheme]
222
+ end
223
+
224
+ def targets
225
+ @options[:targets]
226
+ end
227
+
228
+ def configuration
229
+ @options[:configuration]
230
+ end
231
+
232
+ def bitcode_enabled?
233
+ @options[:bitcode_enabled]
234
+ end
235
+
236
+ def device_build_enabled?
237
+ @options[:device_build_enabled]
238
+ end
239
+
240
+ def device
241
+ @options[:device] || "iphoneos"
242
+ end
243
+
244
+ def simulator
245
+ @options[:simulator] || "iphonesimulator"
246
+ end
247
+
248
+ def disable_dsym?
249
+ @options[:disable_dsym]
250
+ end
175
251
  end
176
252
  end
@@ -1,43 +1,56 @@
1
1
  require "fourflusher"
2
2
 
3
- PLATFORM_OF_SDK = {
4
- "iphonesimulator" => "iOS",
5
- "appletvsimulator" => "tvOS",
6
- "watchsimulator" => "watchOS"
7
- }.freeze
3
+ module PodPrebuild
4
+ class XcodebuildCommand
5
+ PLATFORM_OF_SDK = {
6
+ "iphonesimulator" => "iOS",
7
+ "appletvsimulator" => "tvOS",
8
+ "watchsimulator" => "watchOS"
9
+ }.freeze
8
10
 
9
- def xcodebuild(options)
10
- sdk = options[:sdk] || "iphonesimulator"
11
- platform = PLATFORM_OF_SDK[sdk]
11
+ DESTINATION_OF_SDK = {
12
+ "iphoneos" => "\"generic/platform=iOS\"",
13
+ "iphonesimulator" => "\"generic/platform=iOS Simulator\""
14
+ }.freeze
12
15
 
13
- cmd = ["xcodebuild"]
14
- cmd << "-project" << options[:sandbox].project_path.realdirpath
15
- cmd << "-scheme" << options[:target]
16
- cmd << "-configuration" << options[:configuration]
17
- cmd << "-sdk" << sdk
18
- cmd << Fourflusher::SimControl.new.destination(:oldest, platform, options[:deployment_target]) unless platform.nil?
19
- cmd += options[:args] if options[:args]
20
- cmd << "2>&1"
21
- cmd = cmd.join(" ")
16
+ def self.xcodebuild(options)
17
+ sdk = options[:sdk] || "iphonesimulator"
18
+ targets = options[:targets] || [options[:target]]
19
+ platform = PLATFORM_OF_SDK[sdk]
22
20
 
23
- puts "xcodebuild command: #{cmd}"
24
- log = `#{cmd}`
21
+ cmd = ["xcodebuild"]
22
+ cmd << "-project" << options[:sandbox].project_path.realdirpath.shellescape
23
+ targets.each { |target| cmd << "-target" << target }
24
+ cmd << "-configuration" << options[:configuration]
25
+ cmd << "-sdk" << sdk
26
+ if DESTINATION_OF_SDK.key?(sdk)
27
+ cmd << "-destination" << DESTINATION_OF_SDK[sdk]
28
+ else
29
+ cmd << Fourflusher::SimControl.new.destination(:oldest, platform, options[:deployment_target]) unless platform.nil?
30
+ end
31
+ cmd += options[:args] if options[:args]
32
+ cmd << "build"
33
+ cmd << "2>&1"
34
+ cmd = cmd.join(" ")
35
+
36
+ Pod::UI.puts_indented "$ #{cmd}" unless PodPrebuild.config.silent_build?
25
37
 
26
- succeeded = $?.exitstatus.zero?
27
- unless succeeded
28
- begin
29
- raise "Unexpected error" unless log.include?("** BUILD FAILED **")
38
+ log = `#{cmd}`
39
+ return if $?.exitstatus.zero? # rubocop:disable Style/SpecialGlobalVars
30
40
 
31
- require "xcpretty" # TODO (thuyen): Revise this dependency
32
- # use xcpretty to print build log
33
- # 64 represent command invalid. http://www.manpagez.com/man/3/sysexits/
34
- printer = XCPretty::Printer.new({:formatter => XCPretty::Simple, :colorize => "auto"})
35
- log.each_line do |line|
36
- printer.pretty_print(line)
41
+ begin
42
+ require "xcpretty" # TODO (thuyen): Revise this dependency
43
+ # use xcpretty to print build log
44
+ # 64 represent command invalid. http://www.manpagez.com/man/3/sysexits/
45
+ printer = XCPretty::Printer.new({:formatter => XCPretty::Simple, :colorize => "auto"})
46
+ log.each_line do |line|
47
+ printer.pretty_print(line)
48
+ end
49
+ rescue
50
+ Pod::UI.puts log.red
51
+ ensure
52
+ raise "Fail to build targets: #{targets}"
37
53
  end
38
- rescue
39
- puts log.red
40
54
  end
41
55
  end
42
- [succeeded, log]
43
56
  end