cocoapods-binary-cache 0.1.7 → 0.1.8

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 (36) 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 +5 -2
  8. data/lib/cocoapods-binary-cache/helper/prebuild_order.rb +12 -0
  9. data/lib/cocoapods-binary-cache/hooks/post_install.rb +4 -3
  10. data/lib/cocoapods-binary-cache/hooks/pre_install.rb +7 -34
  11. data/lib/cocoapods-binary-cache/pod-binary/helper/build.rb +1 -0
  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/patch/embed_framework_script.rb +1 -1
  17. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/resolve_dependencies.rb +0 -3
  18. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/sandbox_analyzer_state.rb +29 -0
  19. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb +2 -2
  20. data/lib/cocoapods-binary-cache/pod-binary/prebuild.rb +16 -93
  21. data/lib/cocoapods-binary-cache/pod-binary/prebuild_dsl.rb +0 -2
  22. data/lib/cocoapods-binary-cache/pod-binary/prebuild_hook.rb +0 -1
  23. data/lib/cocoapods-binary-cache/pod-rome/xcodebuild_command.rb +64 -48
  24. data/lib/cocoapods-binary-cache/pod-rome/xcodebuild_raw.rb +3 -3
  25. data/lib/cocoapods-binary-cache/prebuild_output/output.rb +6 -4
  26. data/lib/cocoapods-binary-cache/scheme_editor.rb +16 -15
  27. data/lib/cocoapods-binary-cache/state_store.rb +16 -6
  28. data/lib/command/config.rb +25 -3
  29. data/lib/command/executor/base.rb +7 -0
  30. data/lib/command/executor/prebuilder.rb +1 -1
  31. data/lib/command/executor/visualizer.rb +3 -2
  32. metadata +4 -6
  33. data/lib/cocoapods-binary-cache/pod-binary/helper/feature_switches.rb +0 -52
  34. data/lib/cocoapods-binary-cache/pod-binary/helper/passer.rb +0 -25
  35. data/lib/cocoapods-binary-cache/pod-binary/integration/remove_target_files.rb +0 -29
  36. data/lib/cocoapods-binary-cache/pod-binary/tool/tool.rb +0 -12
@@ -1,16 +1,15 @@
1
1
  module Pod
2
2
  class Prebuild
3
-
4
3
  # Check the targets, for the current limitation of the plugin
5
4
  #
6
5
  # @param [Array<PodTarget>] prebuilt_targets
7
6
  def self.check_one_pod_should_have_only_one_target(prebuilt_targets)
8
- targets_have_different_platforms = prebuilt_targets.select { |t| t.pod_name != t.name }
7
+ targets_have_different_platforms = prebuilt_targets.reject { |t| t.pod_name == t.name }
8
+ return unless targets_have_different_platforms.empty?
9
9
 
10
- if targets_have_different_platforms.count > 0
11
- names = targets_have_different_platforms.map(&:pod_name)
12
- raw_names = targets_have_different_platforms.map(&:name)
13
- message = "Oops, you came across a limitation of cocoapods-binary.
10
+ names = targets_have_different_platforms.map(&:pod_name)
11
+ raw_names = targets_have_different_platforms.map(&:name)
12
+ message = "Oops, you came across a limitation of cocoapods-binary.
14
13
 
15
14
  The plugin requires that one pod should have ONLY ONE target in the 'Pod.xcodeproj'. There are mainly 2 situations \
16
15
  causing this problem:
@@ -36,10 +35,8 @@ causing this problem:
36
35
  end
37
36
  ```
38
37
 
39
- Related pods: #{names}, target names: #{raw_names}
40
- "
41
- raise Informative, message
42
- end
38
+ Related pods: #{names}, target names: #{raw_names}"
39
+ raise Informative, message
43
40
  end
44
41
  end
45
42
  end
@@ -1,11 +1,10 @@
1
1
  require_relative "helper/podfile_options"
2
2
  require_relative "helper/prebuild_sandbox"
3
- require_relative "helper/passer"
4
3
  require_relative "helper/names"
5
4
  require_relative "helper/target_checker"
6
5
  require_relative "integration/alter_specs"
7
- require_relative "integration/remove_target_files"
8
6
  require_relative "integration/validation"
9
7
  require_relative "integration/patch/embed_framework_script"
8
+ require_relative "integration/patch/sandbox_analyzer_state"
10
9
  require_relative "integration/patch/resolve_dependencies"
11
10
  require_relative "integration/patch/source_installation"
@@ -9,7 +9,7 @@ module Pod
9
9
  class EmbedFrameworksScript
10
10
  old_method = instance_method(:script)
11
11
  define_method(:script) do
12
- script = old_method.bind(self).()
12
+ script = old_method.bind(self).call
13
13
  patch = <<-SH.strip_heredoc
14
14
  #!/bin/sh
15
15
  # ---- this is added by cocoapods-binary ---
@@ -7,9 +7,6 @@ module Pod
7
7
  # Modify specification to use only the prebuild framework after analyzing
8
8
  original_resolve_dependencies = instance_method(:resolve_dependencies)
9
9
  define_method(:resolve_dependencies) do
10
- # Remove the old target files. Otherwise, it will not notice file changes.
11
- # This call is to make sure subsequent pod installations function properly
12
- remove_target_files_if_needed
13
10
  original_resolve_dependencies.bind(self).call
14
11
 
15
12
  # check the pods
@@ -0,0 +1,29 @@
1
+ module Pod
2
+ class Installer
3
+ class Analyzer
4
+ class SandboxAnalyzer
5
+ original_analyze = instance_method(:analyze)
6
+ define_method(:analyze) do
7
+ state = original_analyze.bind(self).call
8
+ state = alter_state(state)
9
+ state
10
+ end
11
+
12
+ private
13
+
14
+ def alter_state(state)
15
+ return state if PodPrebuild.config.tracked_prebuilt_pod_names.empty?
16
+
17
+ prebuilt = PodPrebuild.config.tracked_prebuilt_pod_names
18
+ Pod::UI.message "Alter sandbox state: treat prebuilt frameworks as added: #{prebuilt.to_a}"
19
+ SpecsState.new(
20
+ :added => (state.added + prebuilt).uniq,
21
+ :changed => state.changed - prebuilt,
22
+ :removed => state.deleted - prebuilt,
23
+ :unchanged => state.unchanged - prebuilt
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -21,9 +21,9 @@ module Pod
21
21
  # In a prebuild job, at the integration stage, all prebuilt frameworks should be
22
22
  # ready for integration regardless of whether there was any cache miss or not.
23
23
  # Those that are missed were prebuilt in the prebuild stage.
24
- PodPrebuild::StateStore.cache_validation.include?(name)
24
+ PodPrebuild.state.cache_validation.include?(name)
25
25
  else
26
- prebuilt = PodPrebuild::StateStore.cache_validation.hit + PodPrebuild.config.targets_to_prebuild_from_cli
26
+ prebuilt = PodPrebuild.state.cache_validation.hit + PodPrebuild.config.targets_to_prebuild_from_cli
27
27
  prebuilt.include?(name)
28
28
  end
29
29
  end
@@ -1,12 +1,12 @@
1
1
  require "fileutils"
2
2
  require_relative "../prebuild_output/output"
3
3
  require_relative "../helper/lockfile"
4
- require_relative "helper/passer"
4
+ require_relative "../helper/prebuild_order"
5
5
  require_relative "helper/target_checker"
6
6
  require_relative "helper/build"
7
7
 
8
8
  module Pod
9
- class PrebuildInstaller < Installer
9
+ class PrebuildInstaller < Installer # rubocop:disable Metrics/ClassLength
10
10
  attr_reader :lockfile_wrapper
11
11
 
12
12
  def initialize(options)
@@ -15,38 +15,6 @@ module Pod
15
15
  @lockfile_wrapper = lockfile && PodPrebuild::Lockfile.new(lockfile)
16
16
  end
17
17
 
18
- private
19
-
20
- def local_manifest
21
- @local_manifest ||= sandbox.manifest
22
- end
23
-
24
- # @return [Analyzer::SpecsState]
25
- def prebuild_pods_changes
26
- return nil if local_manifest.nil?
27
-
28
- if @prebuild_pods_changes.nil?
29
- changes = local_manifest.detect_changes_with_podfile(podfile)
30
- @prebuild_pods_changes = Analyzer::SpecsState.new(changes)
31
- # save the chagnes info for later stage
32
- Pod::Prebuild::Passer.prebuild_pods_changes = @prebuild_pods_changes
33
- end
34
- @prebuild_pods_changes
35
- end
36
-
37
- def blacklisted?(name)
38
- PodPrebuild::StateStore.excluded_pods.include?(name)
39
- end
40
-
41
- def cache_missed?(name)
42
- @cache_validation.missed?(name)
43
- end
44
-
45
- def should_not_prebuild_vendor_pod(name)
46
- return true if blacklisted?(name)
47
- return false if PodPrebuild.config.prebuild_all_pods?
48
- end
49
-
50
18
  def run_code_gen!(targets)
51
19
  return if PodPrebuild.config.prebuild_code_gen.nil?
52
20
 
@@ -55,65 +23,23 @@ module Pod
55
23
  end
56
24
  end
57
25
 
58
- def targets_to_prebuild
59
- existed_framework_folder = sandbox.generate_framework_path
60
- targets = pod_targets
61
-
62
- targets_from_cli = PodPrebuild.config.targets_to_prebuild_from_cli
63
- if !targets_from_cli.empty?
64
- targets = targets.select { |target| targets_from_cli.include?(target.name) }
65
- elsif !PodPrebuild.config.prebuild_all_pods? && !local_manifest.nil?
66
- changes = prebuild_pods_changes
67
- added = changes.added
68
- changed = changes.changed
69
- unchanged = changes.unchanged
70
-
71
- existed_framework_folder.mkdir unless existed_framework_folder.exist?
72
- exsited_framework_pod_names = sandbox.exsited_framework_pod_names
73
-
74
- # additions
75
- missing = unchanged.reject { |pod_name| exsited_framework_pod_names.include?(pod_name) }
76
-
77
- root_names_to_update = (added + changed + missing)
78
- root_names_to_update += PodPrebuild::StateStore.cache_validation.missed
79
-
80
- # transform names to targets
81
- cache = []
82
- targets = root_names_to_update.map do |pod_name|
83
- tars = Pod.fast_get_targets_for_pod_name(pod_name, pod_targets, cache) || []
84
- raise "There's no target named (#{pod_name}) in Pod.xcodeproj" if tars.empty?
85
-
86
- tars
87
- end.flatten
88
-
89
- # add the dendencies
90
- dependency_targets = targets.map(&:recursive_dependent_targets).flatten.uniq || []
91
- targets = (targets + dependency_targets).uniq
92
- end
93
-
94
- unless PodPrebuild.config.prebuild_all_pods?
95
- targets = targets.select { |pod_target| cache_missed?(pod_target.name) }
96
- end
97
- targets = targets.reject { |pod_target| should_not_prebuild_vendor_pod(pod_target.name) }
98
- unless PodPrebuild.config.dev_pods_enabled?
99
- targets = targets.reject { |pod_target| sandbox.local?(pod_target.pod_name) }
100
- end
101
- targets
102
- end
103
-
104
- public
105
-
106
26
  def prebuild_output
107
27
  @prebuild_output ||= PodPrebuild::Output.new(sandbox)
108
28
  end
109
29
 
110
- # Build the needed framework files
30
+ def targets_to_prebuild
31
+ to_build = PodPrebuild.config.targets_to_prebuild_from_cli
32
+ if to_build.empty?
33
+ to_build = PodPrebuild.config.prebuild_all_pods? ? @cache_validation.all : @cache_validation.missed
34
+ end
35
+ pod_targets.select { |target| to_build.include?(target.name) }
36
+ end
37
+
111
38
  def prebuild_frameworks!
112
- UI.puts "Start prebuild_frameworks"
113
39
  existed_framework_folder = sandbox.generate_framework_path
114
40
  sandbox_path = sandbox.root
115
- targets = targets_to_prebuild
116
41
 
42
+ targets = PodPrebuild::BuildOrder.order_targets(targets_to_prebuild)
117
43
  Pod::UI.puts "Prebuild frameworks (total #{targets.count}): #{targets.map(&:name)}"
118
44
  Pod::Prebuild.remove_build_dir(sandbox_path)
119
45
  run_code_gen!(targets)
@@ -142,7 +68,6 @@ module Pod
142
68
  # If target shouldn't build, we copy all the original files
143
69
  # This is for target with only .a and .h files
144
70
  unless target.should_build?
145
- Prebuild::Passer.target_names_to_skip_integration_framework << target.name
146
71
  FileUtils.cp_r(root_path, target_folder, :remove_destination => true)
147
72
  next
148
73
  end
@@ -173,7 +98,7 @@ module Pod
173
98
  all_needed_names.include? name
174
99
  end
175
100
  useless_target_names.each do |name|
176
- UI.puts "Remove: #{name}"
101
+ Pod::UI.message "Remove: #{name}"
177
102
  path = sandbox.framework_folder_path_for_target_name(name)
178
103
  path.rmtree if path.exist?
179
104
  end
@@ -189,12 +114,10 @@ module Pod
189
114
  to_delete_files.each { |file| file.rmtree if file.exist? }
190
115
  end
191
116
 
192
- updated_target_names = targets.map { |target| target.label.to_s }
193
- deleted_target_names = useless_target_names
194
- Pod::UI.puts "Targets to prebuild: #{updated_target_names}"
195
- Pod::UI.puts "Targets to cleanup: #{deleted_target_names}"
196
-
197
- prebuild_output.write_delta_file(updated_target_names, deleted_target_names)
117
+ prebuild_output.write_delta_file(
118
+ updated: targets.map { |target| target.label.to_s },
119
+ deleted: useless_target_names
120
+ )
198
121
  end
199
122
 
200
123
  def clean_delta_file
@@ -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,6 +1,6 @@
1
1
  require_relative "xcodebuild_raw"
2
2
 
3
- class XcodebuildCommand
3
+ class XcodebuildCommand # rubocop:disable Metrics/ClassLength
4
4
  def initialize(options)
5
5
  @options = options
6
6
  case options[:target].platform.name
@@ -18,19 +18,33 @@ class XcodebuildCommand
18
18
  end
19
19
 
20
20
  def run
21
- build_for_sdk(simulator)
22
- if device_build_enabled?
23
- build_for_sdk(device)
21
+ build_for_sdk(simulator) if build_types.include?(:simulator)
22
+ build_for_sdk(device) if build_types.include?(:device)
23
+
24
+ case build_types
25
+ when [:simulator]
26
+ collect_output(Dir[target_products_dir_of(simulator) + "/*"])
27
+ when [:device]
28
+ collect_output(Dir[target_products_dir_of(device) + "/*"])
29
+ else
30
+ # When merging contents of `simulator` & `device`, prefer contents of `device` over `simulator`
31
+ # https://github.com/grab/cocoapods-binary-cache/issues/25
32
+ collect_output(Dir[target_products_dir_of(device) + "/*"])
24
33
  create_universal_framework
25
- merge_dsym unless disable_dsym?
26
- merge_swift_headers
27
- merge_swift_modules
28
34
  end
29
- collect_output(Dir[target_products_dir_of(simulator) + "/*"])
30
35
  end
31
36
 
32
37
  private
33
38
 
39
+ def build_types
40
+ @build_types ||= begin
41
+ # TODO (thuyen): Add DSL options `build_for_types` to specify build types
42
+ types = [:simulator]
43
+ types << :device if device_build_enabled?
44
+ types
45
+ end
46
+ end
47
+
34
48
  def make_up_build_args(args)
35
49
  args_ = args.clone
36
50
  args_[:default] ||= []
@@ -47,7 +61,7 @@ class XcodebuildCommand
47
61
  def build_for_sdk(sdk)
48
62
  framework_path = framework_path_of(sdk)
49
63
  if Dir.exist?(framework_path)
50
- Pod::UI.puts "Framework already exists at: #{framework_path}"
64
+ Pod::UI.puts_indented "--> Framework already exists at: #{framework_path}"
51
65
  return
52
66
  end
53
67
 
@@ -63,62 +77,64 @@ class XcodebuildCommand
63
77
  end
64
78
 
65
79
  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
- )
80
+ merge_framework_binary
81
+ merge_framework_dsym
82
+ merge_swift_headers
83
+ merge_swift_modules
70
84
  end
71
85
 
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)
76
-
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)
86
+ def merge_framework_binary
87
+ merge_contents("/#{module_name}", &method(:create_fat_binary))
82
88
  end
83
89
 
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(" ")}`
90
+ def merge_framework_dsym
91
+ merge_contents(".dSYM/Contents/Resources/DWARF/#{module_name}", &method(:create_fat_binary))
89
92
  end
90
93
 
91
94
  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)
95
+ merge_contents("/Headers/#{module_name}-Swift.h") do |options|
96
+ merged_header = <<~HEREDOC
97
+ #if TARGET_OS_SIMULATOR // merged by cocoapods-binary
98
+ #{File.read(options[:simulator])}
99
+ #else // merged by cocoapods-binary
100
+ #{File.read(options[:device])}
101
+ #endif // merged by cocoapods-binary
102
+ HEREDOC
103
+ File.write(options[:output], merged_header.strip)
104
+ end
104
105
  end
105
106
 
106
107
  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)
108
+ merge_contents("/Modules/#{module_name}.swiftmodule") do |options|
109
+ # Note: swiftmodules of `device` were copied beforehand,
110
+ # here, we only need to copy swiftmodules of `simulator`
111
+ FileUtils.cp_r(options[:simulator] + "/.", options[:output])
112
+ end
113
+ end
110
114
 
111
- FileUtils.cp_r(
112
- device_swift_module_path + "/.",
113
- simulator_swift_module_path
114
- )
115
+ def merge_contents(path_suffix, &merger)
116
+ simulator_, device_, output_ = [
117
+ framework_path_of(simulator),
118
+ framework_path_of(device),
119
+ "#{output_path}/#{module_name}.framework"
120
+ ].map { |p| p + path_suffix }
121
+ return unless File.exist?(simulator_) && File.exist?(device_)
122
+
123
+ merger.call(simulator: simulator_, device: device_, output: output_)
124
+ end
125
+
126
+ def create_fat_binary(options)
127
+ cmd = ["lipo", " -create"]
128
+ cmd << "-output" << options[:output]
129
+ cmd << options[:simulator] << options[:device]
130
+ Pod::UI.puts `#{cmd.join(" ")}`
115
131
  end
116
132
 
117
133
  def collect_output(paths)
118
134
  paths = [paths] unless paths.is_a?(Array)
119
135
  paths.each do |path|
120
136
  FileUtils.rm_rf(File.join(output_path, File.basename(path)))
121
- FileUtils.mv(path, output_path)
137
+ FileUtils.cp_r(path, output_path)
122
138
  end
123
139
  end
124
140
 
@@ -20,10 +20,10 @@ def xcodebuild(options)
20
20
  cmd << "2>&1"
21
21
  cmd = cmd.join(" ")
22
22
 
23
- puts "xcodebuild command: #{cmd}"
23
+ Pod::UI.puts_indented "$ #{cmd}"
24
24
  log = `#{cmd}`
25
25
 
26
- succeeded = $?.exitstatus.zero?
26
+ succeeded = $?.exitstatus.zero? # rubocop:disable Style/SpecialGlobalVars
27
27
  unless succeeded
28
28
  begin
29
29
  raise "Unexpected error" unless log.include?("** BUILD FAILED **")
@@ -36,7 +36,7 @@ def xcodebuild(options)
36
36
  printer.pretty_print(line)
37
37
  end
38
38
  rescue
39
- puts log.red
39
+ Pod::UI.puts log.red
40
40
  end
41
41
  end
42
42
  [succeeded, log]