cocoapods-binary-ht 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. checksums.yaml +7 -0
  2. data/lib/cocoapods-binary-cache.rb +2 -0
  3. data/lib/cocoapods-binary-ht/cache/all.rb +9 -0
  4. data/lib/cocoapods-binary-ht/cache/validation_result.rb +73 -0
  5. data/lib/cocoapods-binary-ht/cache/validator.rb +20 -0
  6. data/lib/cocoapods-binary-ht/cache/validator_accumulated.rb +4 -0
  7. data/lib/cocoapods-binary-ht/cache/validator_base.rb +112 -0
  8. data/lib/cocoapods-binary-ht/cache/validator_dependencies_graph.rb +25 -0
  9. data/lib/cocoapods-binary-ht/cache/validator_dev_pods.rb +30 -0
  10. data/lib/cocoapods-binary-ht/cache/validator_exclusion.rb +14 -0
  11. data/lib/cocoapods-binary-ht/cache/validator_non_dev_pods.rb +13 -0
  12. data/lib/cocoapods-binary-ht/cache/validator_with_podfile.rb +9 -0
  13. data/lib/cocoapods-binary-ht/dependencies_graph/dependencies_graph.rb +108 -0
  14. data/lib/cocoapods-binary-ht/dependencies_graph/graph_visualizer.rb +65 -0
  15. data/lib/cocoapods-binary-ht/diagnosis/base.rb +13 -0
  16. data/lib/cocoapods-binary-ht/diagnosis/diagnosis.rb +24 -0
  17. data/lib/cocoapods-binary-ht/diagnosis/integration.rb +23 -0
  18. data/lib/cocoapods-binary-ht/env.rb +32 -0
  19. data/lib/cocoapods-binary-ht/helper/benchmark_show.rb +11 -0
  20. data/lib/cocoapods-binary-ht/helper/checksum.rb +18 -0
  21. data/lib/cocoapods-binary-ht/helper/json.rb +37 -0
  22. data/lib/cocoapods-binary-ht/helper/lockfile.rb +90 -0
  23. data/lib/cocoapods-binary-ht/helper/path_utils.rb +8 -0
  24. data/lib/cocoapods-binary-ht/helper/podspec.rb +20 -0
  25. data/lib/cocoapods-binary-ht/hooks/post_install.rb +23 -0
  26. data/lib/cocoapods-binary-ht/hooks/pre_install.rb +121 -0
  27. data/lib/cocoapods-binary-ht/main.rb +21 -0
  28. data/lib/cocoapods-binary-ht/pod-binary/LICENSE.txt +22 -0
  29. data/lib/cocoapods-binary-ht/pod-binary/helper/build.rb +37 -0
  30. data/lib/cocoapods-binary-ht/pod-binary/helper/detected_prebuilt_pods/installer.rb +25 -0
  31. data/lib/cocoapods-binary-ht/pod-binary/helper/detected_prebuilt_pods/target_definition.rb +29 -0
  32. data/lib/cocoapods-binary-ht/pod-binary/helper/names.rb +27 -0
  33. data/lib/cocoapods-binary-ht/pod-binary/helper/podfile_options.rb +2 -0
  34. data/lib/cocoapods-binary-ht/pod-binary/helper/prebuild_sandbox.rb +71 -0
  35. data/lib/cocoapods-binary-ht/pod-binary/helper/sandbox.rb +9 -0
  36. data/lib/cocoapods-binary-ht/pod-binary/helper/target_checker.rb +42 -0
  37. data/lib/cocoapods-binary-ht/pod-binary/integration/alter_specs.rb +150 -0
  38. data/lib/cocoapods-binary-ht/pod-binary/integration/patch/embed_framework_script.rb +36 -0
  39. data/lib/cocoapods-binary-ht/pod-binary/integration/patch/resolve_dependencies.rb +20 -0
  40. data/lib/cocoapods-binary-ht/pod-binary/integration/patch/sandbox_analyzer_state.rb +29 -0
  41. data/lib/cocoapods-binary-ht/pod-binary/integration/patch/source_installation.rb +55 -0
  42. data/lib/cocoapods-binary-ht/pod-binary/integration/source_installer.rb +114 -0
  43. data/lib/cocoapods-binary-ht/pod-binary/integration/validation.rb +20 -0
  44. data/lib/cocoapods-binary-ht/pod-binary/integration.rb +11 -0
  45. data/lib/cocoapods-binary-ht/pod-binary/prebuild.rb +166 -0
  46. data/lib/cocoapods-binary-ht/pod-binary/prebuild_dsl.rb +10 -0
  47. data/lib/cocoapods-binary-ht/pod-binary/prebuild_hook.rb +10 -0
  48. data/lib/cocoapods-binary-ht/pod-rome/LICENSE.txt +22 -0
  49. data/lib/cocoapods-binary-ht/pod-rome/xcodebuild_command.rb +266 -0
  50. data/lib/cocoapods-binary-ht/pod-rome/xcodebuild_raw.rb +68 -0
  51. data/lib/cocoapods-binary-ht/prebuild_output/metadata.rb +63 -0
  52. data/lib/cocoapods-binary-ht/prebuild_output/output.rb +44 -0
  53. data/lib/cocoapods-binary-ht/state_store.rb +21 -0
  54. data/lib/cocoapods-binary-ht/ui.rb +9 -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,266 @@
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
+ @options[:simulator] = "iphoneos"
12
+ when :tvos
13
+ @options[:device] = "appletvos"
14
+ @options[:simulator] = "appletvsimulator"
15
+ when :watchos
16
+ @options[:device] = "watchos"
17
+ @options[:simulator] = "watchsimulator"
18
+ end
19
+ @build_args = make_up_build_args(options[:args] || {})
20
+ end
21
+
22
+ def run
23
+ sdks.each { |sdk| build_for_sdk(sdk) }
24
+
25
+ targets.each do |target|
26
+ if PodPrebuild.config.xcframework?
27
+ create_xcframework(target)
28
+ elsif sdks.count > 1
29
+ create_fat_framework(target)
30
+ else
31
+ collect_output(target, Dir[target_products_dir_of(target, sdks[0]) + "/*"])
32
+ end
33
+ end
34
+ end
35
+
36
+ private
37
+
38
+ def sdks
39
+ @sdks ||= begin
40
+ sdks_ = []
41
+ sdks_ << simulator if build_types.include?(:simulator)
42
+ sdks_ << device if build_types.include?(:device)
43
+ sdks_
44
+ end
45
+ end
46
+
47
+ def preferred_sdk
48
+ @preferred_sdk ||= sdks.include?(device) ? device : sdks[0]
49
+ end
50
+
51
+ def build_types
52
+ @build_types ||= begin
53
+ # TODO (thuyen): Add DSL options `build_for_types` to specify build types
54
+ types = [:simulator]
55
+ types << :device if device_build_enabled?
56
+ types
57
+ end
58
+ end
59
+
60
+ def make_up_build_args(args)
61
+ # Note: The build arguments explicitly passed from config_cocoapods_binary_cache
62
+ # should be preceded by the default arguments so that they could take higher priority
63
+ # when there are argument collisions in the xcodebuild command.
64
+ # For ex. `xcodebuild AN_ARG=1 AN_ARG=2` should use `AN_ARG=2` instead.
65
+ args_ = args.clone
66
+ args_[:default] ||= []
67
+ args_[:simulator] ||= []
68
+ args_[:device] ||= []
69
+ args_[:default].prepend("BITCODE_GENERATION_MODE=bitcode") if bitcode_enabled?
70
+ args_[:default].prepend("DEBUG_INFORMATION_FORMAT=dwarf") if disable_dsym?
71
+ # args_[:simulator].prepend("ARCHS=x86_64", "ONLY_ACTIVE_ARCH=NO") if simulator == "iphonesimulator"
72
+ # 我们的项目由于 SDK 的因素,只能在真机调试,因此调整此处编译架构。
73
+ # 这里判断模拟器条件是由于该插件默认支持模拟器,不想过多调整代码,因此保留了之前的流程。
74
+ # args_[:simulator].prepend("ARCHS=arm64") if simulator == "iphoneos"
75
+ args_[:simulator] += args_[:default]
76
+ # args_[:device].prepend("ONLY_ACTIVE_ARCH=NO")
77
+ # args_[:device] += args_[:default]
78
+ args_
79
+ end
80
+
81
+ def build_for_sdk(sdk)
82
+ PodPrebuild::XcodebuildCommand.xcodebuild(
83
+ sandbox: sandbox,
84
+ scheme: scheme,
85
+ targets: targets.map(&:label),
86
+ configuration: configuration,
87
+ sdk: sdk,
88
+ deployment_target: targets.map { |t| t.platform.deployment_target }.max.to_s,
89
+ log_path: log_path(sdk),
90
+ args: sdk == simulator ? @build_args[:simulator] : @build_args[:device]
91
+ )
92
+ end
93
+
94
+ def create_xcframework(target)
95
+ non_framework_paths = Dir[target_products_dir_of(target, preferred_sdk) + "/*"] \
96
+ - [framework_path_of(target, preferred_sdk)] \
97
+ - dsym_paths_of(target, preferred_sdk) \
98
+ - bcsymbolmap_paths_of(target, preferred_sdk)
99
+ collect_output(target, non_framework_paths)
100
+
101
+ output = "#{output_path(target)}/#{target.product_module_name}.xcframework"
102
+ FileUtils.rm_rf(output)
103
+
104
+ cmd = ["xcodebuild", "-create-xcframework", "-allow-internal-distribution"]
105
+
106
+ # for each sdk, the order of params must be -framework then -debug-symbols
107
+ # to prevent duplicated file error when copying dSYMs
108
+ sdks.each do |sdk|
109
+ cmd << "-framework" << framework_path_of(target, sdk).shellescape
110
+
111
+ unless disable_dsym?
112
+ dsyms = dsym_paths_of(target, sdk)
113
+ cmd += dsyms.map { |dsym| "-debug-symbols #{dsym.shellescape}" }
114
+ end
115
+
116
+ if bitcode_enabled?
117
+ bcsymbolmaps = bcsymbolmap_paths_of(target, sdk)
118
+ cmd += bcsymbolmaps.map { |bcsymbolmap| "-debug-symbols #{bcsymbolmap.shellescape}" }
119
+ end
120
+ end
121
+
122
+ cmd << "-output" << output
123
+
124
+ Pod::UI.puts "- Create xcframework: #{target}".magenta
125
+ Pod::UI.puts_indented "$ #{cmd.join(' ')}" unless PodPrebuild.config.silent_build?
126
+
127
+ `#{cmd.join(" ")}`
128
+ end
129
+
130
+ def create_fat_framework(target)
131
+ # When merging contents of `simulator` & `device`, prefer contents of `device` over `simulator`
132
+ # https://github.com/pandaleecn/cocoapods-binary-ht/issues/25
133
+ collect_output(target, Dir[target_products_dir_of(target, device) + "/*"])
134
+
135
+ merge_framework_binary(target)
136
+ merge_framework_dsym(target)
137
+ merge_swift_headers(target)
138
+ merge_swift_modules(target)
139
+ end
140
+
141
+ def merge_framework_binary(target)
142
+ merge_contents(target, "/#{target.product_module_name}", &method(:create_fat_binary))
143
+ end
144
+
145
+ def merge_framework_dsym(target)
146
+ merge_contents(
147
+ target,
148
+ ".dSYM/Contents/Resources/DWARF/#{target.product_module_name}",
149
+ &method(:create_fat_binary)
150
+ )
151
+ end
152
+
153
+ def merge_swift_headers(target)
154
+ merge_contents(target, "/Headers/#{target.product_module_name}-Swift.h") do |options|
155
+ merged_header = <<~HEREDOC
156
+ #if TARGET_OS_SIMULATOR // merged by cocoapods-binary
157
+ #{File.read(options[:simulator])}
158
+ #else // merged by cocoapods-binary
159
+ #{File.read(options[:device])}
160
+ #endif // merged by cocoapods-binary
161
+ HEREDOC
162
+ File.write(options[:output], merged_header.strip)
163
+ end
164
+ end
165
+
166
+ def merge_swift_modules(target)
167
+ merge_contents(target, "/Modules/#{target.product_module_name}.swiftmodule") do |options|
168
+ # Note: swiftmodules of `device` were copied beforehand,
169
+ # here, we only need to copy swiftmodules of `simulator`
170
+ FileUtils.cp_r(options[:simulator] + "/.", options[:output])
171
+ end
172
+ end
173
+
174
+ def merge_contents(target, path_suffix, &merger)
175
+ simulator_, device_, output_ = [
176
+ framework_path_of(target, simulator),
177
+ framework_path_of(target, device),
178
+ "#{output_path(target)}/#{target.product_module_name}.framework"
179
+ ].map { |p| p + path_suffix }
180
+ return unless File.exist?(simulator_) && File.exist?(device_)
181
+
182
+ merger.call(simulator: simulator_, device: device_, output: output_)
183
+ end
184
+
185
+ def create_fat_binary(options)
186
+ cmd = ["lipo", " -create"]
187
+ cmd << "-output" << options[:output]
188
+ cmd << options[:simulator].shellescape << options[:device].shellescape
189
+ `#{cmd.join(" ")}`
190
+ end
191
+
192
+ def collect_output(target, paths)
193
+ FileUtils.mkdir_p(output_path(target))
194
+ paths = [paths] unless paths.is_a?(Array)
195
+ paths.each do |path|
196
+ FileUtils.rm_rf(File.join(output_path(target), File.basename(path)))
197
+ FileUtils.cp_r(path, output_path(target))
198
+ end
199
+ end
200
+
201
+ def target_products_dir_of(target, sdk)
202
+ "#{build_dir}/#{configuration}-#{sdk}/#{target.name}"
203
+ end
204
+
205
+ def framework_path_of(target, sdk)
206
+ "#{target_products_dir_of(target, sdk)}/#{target.product_module_name}.framework"
207
+ end
208
+
209
+ def dsym_paths_of(target, sdk)
210
+ Dir["#{target_products_dir_of(target, sdk)}/*.dSYM"]
211
+ end
212
+
213
+ def bcsymbolmap_paths_of(target, sdk)
214
+ Dir["#{target_products_dir_of(target, sdk)}/*.bcsymbolmap"]
215
+ end
216
+
217
+ def sandbox
218
+ @options[:sandbox]
219
+ end
220
+
221
+ def build_dir
222
+ @options[:build_dir]
223
+ end
224
+
225
+ def output_path(target)
226
+ "#{@options[:output_path]}/#{target.label}"
227
+ end
228
+
229
+ def scheme
230
+ @options[:scheme]
231
+ end
232
+
233
+ def targets
234
+ @options[:targets]
235
+ end
236
+
237
+ def configuration
238
+ @options[:configuration]
239
+ end
240
+
241
+ def bitcode_enabled?
242
+ @options[:bitcode_enabled]
243
+ end
244
+
245
+ def device_build_enabled?
246
+ @options[:device_build_enabled]
247
+ end
248
+
249
+ def device
250
+ @options[:device] || "iphoneos"
251
+ end
252
+
253
+ def simulator
254
+ # @options[:simulator] || "iphonesimulator"
255
+ @options[:simulator] || "iphoneos"
256
+ end
257
+
258
+ def disable_dsym?
259
+ @options[:disable_dsym]
260
+ end
261
+
262
+ def log_path(sdk)
263
+ @options[:log_path].nil? ? nil : "#{@options[:log_path]}_#{sdk}"
264
+ end
265
+ end
266
+ end
@@ -0,0 +1,68 @@
1
+ require "fourflusher"
2
+
3
+ module PodPrebuild
4
+ class XcodebuildCommand
5
+ PLATFORM_OF_SDK = {
6
+ # "iphonesimulator" => "iOS",
7
+ "iphoneos" => "iOS",
8
+ "appletvsimulator" => "tvOS",
9
+ "watchsimulator" => "watchOS"
10
+ }.freeze
11
+
12
+ DESTINATION_OF_SDK = {
13
+ "iphoneos" => "\"generic/platform=iOS\"",
14
+ "iphonesimulator" => "\"generic/platform=iOS Simulator\""
15
+ }.freeze
16
+
17
+ def self.xcodebuild(options)
18
+ # sdk = options[:sdk] || "iphonesimulator"
19
+ sdk = options[:sdk] || "iphoneos"
20
+ targets = options[:targets] || [options[:target]]
21
+ platform = PLATFORM_OF_SDK[sdk]
22
+
23
+ cmd = ["xcodebuild"]
24
+ cmd << "-project" << options[:sandbox].project_path.realdirpath.shellescape
25
+ targets.each { |target| cmd << "-target" << target }
26
+ cmd << "-configuration" << options[:configuration].shellescape
27
+ cmd << "-sdk" << sdk
28
+ if DESTINATION_OF_SDK.key?(sdk)
29
+ cmd << "-destination" << DESTINATION_OF_SDK[sdk]
30
+ else
31
+ unless platform.nil?
32
+ cmd << Fourflusher::SimControl.new.destination(:oldest, platform, options[:deployment_target])
33
+ end
34
+ end
35
+ cmd += options[:args] if options[:args]
36
+ # cmd << "clean"
37
+ cmd << "build"
38
+ # cmd << "-UseModernBuildSystem=NO"
39
+
40
+ if options[:log_path].nil?
41
+ cmd << "2>&1"
42
+ else
43
+ FileUtils.mkdir_p(File.dirname(options[:log_path]))
44
+ cmd << "> #{options[:log_path].shellescape}"
45
+ end
46
+ cmd = cmd.join(" ")
47
+
48
+ Pod::UI.puts_indented "$ #{cmd}" unless PodPrebuild.config.silent_build?
49
+
50
+ log = `#{cmd}`
51
+ return if $?.exitstatus.zero? # rubocop:disable Style/SpecialGlobalVars
52
+
53
+ begin
54
+ require "xcpretty" # TODO (thuyen): Revise this dependency
55
+ # use xcpretty to print build log
56
+ # 64 represent command invalid. http://www.manpagez.com/man/3/sysexits/
57
+ printer = XCPretty::Printer.new({:formatter => XCPretty::Simple, :colorize => "auto"})
58
+ log.each_line do |line|
59
+ printer.pretty_print(line)
60
+ end
61
+ rescue
62
+ Pod::UI.puts log.red
63
+ ensure
64
+ raise "Fail to build targets: #{targets}"
65
+ end
66
+ end
67
+ end
68
+ 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 panda Holdings PTE LTE (panda), 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,5 @@
1
+ # Copyright 2019 panda Holdings PTE LTE (panda), 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-ht/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