cocoapods-binary-cache 0.1.5 → 0.1.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7896d5bccb5c1b995271da31a02a9374ff4abc833e081bff2b38fe2401dfa2da
4
- data.tar.gz: ca520b237ddf0377a1e1ca03f90e5f4afa79f576241662ae22c3a9fc86e158c5
3
+ metadata.gz: afe99f8a6986c687fb8033d369ffd7db7ac4543782070d386de8ca20d7e303f5
4
+ data.tar.gz: 8424f90961d5bd08d827ce427f576869b059172b1a07a89e9ff85b012299f0d7
5
5
  SHA512:
6
- metadata.gz: 3a7a9a3decaa6a14b80c80b77e69576a9b77ccbb3b4a5760c23c6e02b7ebc809a1e326ccf19030d6a1e091cdaa21a2a0d14c141d87457e7fdba7742c04adcf37
7
- data.tar.gz: 4b6c9a841f4b98d41b1ad1ed36aaab65e7c7b59cd4ee30b1b13b0f695b264a0ef1222007adf305cab0be216d175f41d471a61368f641653592a31b5e23ecff1f
6
+ metadata.gz: '09b307361741d28ea6d3343061e9baff47d9eb477ce6c31771b2d0ac3893389e34f48b9cd8b41a9337e22225bf6accbbf402445549d07d733575e19602a33b34'
7
+ data.tar.gz: d8c33dd9aac8606cb853d6dd3d4cf20cabec06f17974ae7248ff632bb6e34e43a5e3be98357bc975ef9229a9418cfdc463d5b8093e829babde8ab642c157249b
@@ -5,7 +5,7 @@ module PodPrebuild
5
5
  PodPrebuild::PodfileChangesCacheValidator.new(options),
6
6
  PodPrebuild::NonDevPodsCacheValidator.new(options)
7
7
  ]
8
- @validators << PodPrebuild::DevPodsCacheValidator.new(options) if Pod::Podfile::DSL.dev_pods_enabled
8
+ @validators << PodPrebuild::DevPodsCacheValidator.new(options) if Pod::Podfile::DSL.dev_pods_enabled?
9
9
  @validators << PodPrebuild::DependenciesGraphCacheValidator.new(options)
10
10
  @validators << PodPrebuild::ExclusionCacheValidator.new(options)
11
11
  end
@@ -1,11 +1,16 @@
1
1
  module PodPrebuild
2
2
  class DependenciesGraphCacheValidator < AccumulatedCacheValidator
3
+ def initialize(options)
4
+ super(options)
5
+ @ignored_pods = options[:ignored_pods] || Set.new
6
+ end
7
+
3
8
  def validate(accumulated)
4
9
  return accumulated if library_evolution_supported? || @pod_lockfile.nil?
5
10
 
6
11
  dependencies_graph = DependenciesGraph.new(@pod_lockfile.lockfile)
7
- clients = dependencies_graph.get_clients(accumulated.missed.to_a)
8
- unless Pod::Podfile::DSL.dev_pods_enabled
12
+ clients = dependencies_graph.get_clients(accumulated.discard(@ignored_pods).missed.to_a)
13
+ unless Pod::Podfile::DSL.dev_pods_enabled?
9
14
  clients = clients.reject { |client| @pod_lockfile.dev_pods.keys.include?(client) }
10
15
  end
11
16
 
@@ -4,9 +4,15 @@
4
4
  require "digest/md5"
5
5
 
6
6
  class FolderChecksum
7
- def self.checksum(dir)
8
- files = Dir["#{dir}/**/*"].reject { |f| File.directory?(f) }
9
- content = files.map { |f| File.read(f) }.join
10
- Digest::MD5.hexdigest(content).to_s
7
+ def self.git_checksum(dir)
8
+ checksum_of_files(`git ls-files #{dir}`.split("\n"))
9
+ rescue => e
10
+ Pod::UI.warn "Cannot get checksum of tracked files under #{dir}: #{e}"
11
+ checksum_of_files(Dir["#{dir}/**/*"].reject { |f| File.directory?(f) })
12
+ end
13
+
14
+ def self.checksum_of_files(files)
15
+ checksums = files.sort.map { |f| Digest::MD5.hexdigest(File.read(f)) }
16
+ Digest::MD5.hexdigest(checksums.join)
11
17
  end
12
18
  end
@@ -68,7 +68,7 @@ module PodPrebuild
68
68
  # Generate a map between a dev_pod and it source hash
69
69
  def dev_pod_hashes_map
70
70
  @dev_pod_hashes_map ||=
71
- dev_pod_sources.map { |name, attribs| [name, FolderChecksum.checksum(attribs[:path])] }.to_h
71
+ dev_pod_sources.map { |name, attribs| [name, FolderChecksum.git_checksum(attribs[:path])] }.to_h
72
72
  end
73
73
 
74
74
  # Parse an item under `PODS` section of a Lockfile
@@ -22,7 +22,7 @@ module PodPrebuild
22
22
  end
23
23
 
24
24
  def edit_scheme_for_code_coverage
25
- return unless Pod::Podfile::DSL.dev_pods_enabled && @installer_context.sandbox.instance_of?(Pod::PrebuildSandbox)
25
+ return unless Pod::Podfile::DSL.dev_pods_enabled? && @installer_context.sandbox.instance_of?(Pod::PrebuildSandbox)
26
26
 
27
27
  # Modify pods scheme to support code coverage
28
28
  # If we don't prebuild dev pod -> no need to care about this in Pod project
@@ -0,0 +1,39 @@
1
+ require_relative "../../pod-rome/xcodebuild_raw"
2
+ require_relative "../../pod-rome/xcodebuild_command"
3
+
4
+ module Pod
5
+ class Prebuild
6
+ def self.build(options)
7
+ target = options[:target]
8
+ return if target.nil?
9
+
10
+ options[:sandbox] = Pod::Sandbox.new(Pathname(options[:sandbox])) unless options[:sandbox].is_a?(Pod::Sandbox)
11
+ options[:build_dir] = build_dir(options[:sandbox].root)
12
+
13
+ case target.platform.name
14
+ when :ios, :tvos, :watchos
15
+ XcodebuildCommand.new(options).run
16
+ when :osx
17
+ xcodebuild(
18
+ sandbox: options[:sandbox],
19
+ target: target.label,
20
+ configuration: options[:configuration],
21
+ sdk: "macosx",
22
+ args: options[:args]
23
+ )
24
+ else
25
+ raise "Unsupported platform for '#{target.name}': '#{target.platform.name}'"
26
+ end
27
+ raise "The build directory was not found in the expected location" unless options[:build_dir].directory?
28
+ end
29
+
30
+ def self.remove_build_dir(sandbox_root)
31
+ path = build_dir(sandbox_root)
32
+ path.rmtree if path.exist?
33
+ end
34
+
35
+ def self.build_dir(sandbox_root)
36
+ sandbox_root.parent + "build"
37
+ end
38
+ end
39
+ end
@@ -4,19 +4,12 @@ module Pod
4
4
  def detect_prebuilt_pod(name, requirements)
5
5
  @explicit_prebuilt_pod_names ||= []
6
6
  options = requirements.last || {}
7
- if Pod::Podfile::DSL.prebuild_all?
8
- @explicit_prebuilt_pod_names << Specification.root_name(name)
9
- elsif options.is_a?(Hash) && options[:binary]
10
- @explicit_prebuilt_pod_names << Specification.root_name(name)
11
- end
7
+ @explicit_prebuilt_pod_names << Specification.root_name(name) if options.is_a?(Hash) && options[:binary]
12
8
  options.delete(:binary) if options.is_a?(Hash)
13
9
  requirements.pop if options.empty?
14
10
  end
15
11
 
16
- # Returns the names of pod targets explicitly declared as prebuilt in Podfile
17
- # using `:binary => true`.
18
- # In case `prebuild_all` is ON via `config_cocoapods_binary_cache`, returns the
19
- # name of all pod targets
12
+ # Returns the names of pod targets explicitly declared as prebuilt in Podfile using `:binary => true`.
20
13
  def explicit_prebuilt_pod_names
21
14
  names = @explicit_prebuilt_pod_names || []
22
15
  names += parent.explicit_prebuilt_pod_names if !parent.nil? && parent.is_a?(TargetDefinition)
@@ -17,13 +17,14 @@ module Pod
17
17
  end
18
18
 
19
19
  def should_integrate_prebuilt_pod?(name)
20
- if Pod::Podfile::DSL.prebuild_job?
20
+ if Pod::Podfile::DSL.prebuild_job? && Pod::Podfile::DSL.targets_to_prebuild_from_cli.empty?
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
24
  PodPrebuild::StateStore.cache_validation.include?(name)
25
25
  else
26
- PodPrebuild::StateStore.cache_validation.hit?(name)
26
+ prebuilt = PodPrebuild::StateStore.cache_validation.hit + Pod::Podfile::DSL.targets_to_prebuild_from_cli
27
+ prebuilt.include?(name)
27
28
  end
28
29
  end
29
30
  end
@@ -11,7 +11,7 @@ module Pod
11
11
  class Installer
12
12
  class PodSourceInstaller
13
13
  def install_for_prebuild!(standard_sanbox)
14
- return if !Podfile::DSL.dev_pods_enabled && standard_sanbox.local?(name)
14
+ return if !Podfile::DSL.dev_pods_enabled? && standard_sanbox.local?(name)
15
15
 
16
16
  # make a symlink to target folder
17
17
  # TODO (bang): Unify to 1 sandbox to optimize and avoid inconsistency
@@ -1,17 +1,18 @@
1
1
  require "fileutils"
2
- require_relative "../pod-rome/build_framework"
3
2
  require_relative "../prebuild_output/output"
3
+ require_relative "../helper/lockfile"
4
4
  require_relative "helper/passer"
5
5
  require_relative "helper/target_checker"
6
- require_relative "../helper/lockfile"
6
+ require_relative "helper/build"
7
7
 
8
- # patch prebuild ability
9
8
  module Pod
10
9
  class PrebuildInstaller < Installer
10
+ attr_reader :lockfile_wrapper
11
+
11
12
  def initialize(options)
12
13
  super(options[:sandbox], options[:podfile], options[:lockfile])
13
14
  @cache_validation = options[:cache_validation]
14
- @lockfile_wrapper = PodPrebuild::Lockfile.new(lockfile)
15
+ @lockfile_wrapper = lockfile && PodPrebuild::Lockfile.new(lockfile)
15
16
  end
16
17
 
17
18
  private
@@ -43,30 +44,25 @@ module Pod
43
44
 
44
45
  def should_not_prebuild_vendor_pod(name)
45
46
  return true if blacklisted?(name)
46
- return false if Pod::Podfile::DSL.prebuild_all_vendor_pods
47
+ return false if Pod::Podfile::DSL.prebuild_all_pods?
47
48
  end
48
49
 
49
- public
50
+ def run_code_gen!(targets)
51
+ return if Pod::Podfile::DSL.prebuild_code_gen.nil?
50
52
 
51
- def prebuild_output
52
- @prebuild_output ||= PodPrebuild::Output.new(sandbox)
53
+ Pod::UI.title("Running code generation...") do
54
+ Pod::Podfile::DSL.prebuild_code_gen.call(self, targets)
55
+ end
53
56
  end
54
57
 
55
- # Build the needed framework files
56
- def prebuild_frameworks!
57
- UI.puts "Start prebuild_frameworks"
58
-
59
- # build options
60
- sandbox_path = sandbox.root
58
+ def targets_to_prebuild
61
59
  existed_framework_folder = sandbox.generate_framework_path
62
- bitcode_enabled = Pod::Podfile::DSL.bitcode_enabled
63
- targets = []
64
-
65
- if Pod::Podfile::DSL.prebuild_all_vendor_pods
66
- UI.puts "Rebuild all vendor frameworks"
67
- targets = pod_targets
68
- elsif !local_manifest.nil?
69
- UI.puts "Update some frameworks"
60
+ targets = pod_targets
61
+
62
+ targets_from_cli = Pod::Podfile::DSL.targets_to_prebuild_from_cli
63
+ if !targets_from_cli.empty?
64
+ targets = targets.select { |target| targets_from_cli.include?(target.name) }
65
+ elsif !Pod::Podfile::DSL.prebuild_all_pods? && !local_manifest.nil?
70
66
  changes = prebuild_pods_changes
71
67
  added = changes.added
72
68
  changed = changes.changed
@@ -93,39 +89,46 @@ module Pod
93
89
  # add the dendencies
94
90
  dependency_targets = targets.map(&:recursive_dependent_targets).flatten.uniq || []
95
91
  targets = (targets + dependency_targets).uniq
96
- else
97
- UI.puts "Rebuild all frameworks"
98
- targets = pod_targets
99
92
  end
100
93
 
101
- unless Pod::Podfile::DSL.prebuild_all_vendor_pods
94
+ unless Pod::Podfile::DSL.prebuild_all_pods?
102
95
  targets = targets.select { |pod_target| cache_missed?(pod_target.name) }
103
96
  end
104
97
  targets = targets.reject { |pod_target| should_not_prebuild_vendor_pod(pod_target.name) }
105
- targets = targets.reject { |pod_target| sandbox.local?(pod_target.pod_name) } unless Podfile::DSL.dev_pods_enabled
98
+ unless Podfile::DSL.dev_pods_enabled?
99
+ targets = targets.reject { |pod_target| sandbox.local?(pod_target.pod_name) }
100
+ end
101
+ targets
102
+ end
106
103
 
107
- # build!
108
- Pod::UI.puts "Prebuild frameworks (total #{targets.count})"
109
- Pod::UI.puts targets.map(&:name)
104
+ public
105
+
106
+ def prebuild_output
107
+ @prebuild_output ||= PodPrebuild::Output.new(sandbox)
108
+ end
110
109
 
110
+ # Build the needed framework files
111
+ def prebuild_frameworks!
112
+ UI.puts "Start prebuild_frameworks"
113
+ existed_framework_folder = sandbox.generate_framework_path
114
+ sandbox_path = sandbox.root
115
+ targets = targets_to_prebuild
116
+
117
+ Pod::UI.puts "Prebuild frameworks (total #{targets.count}): #{targets.map(&:name)}"
111
118
  Pod::Prebuild.remove_build_dir(sandbox_path)
119
+ run_code_gen!(targets)
112
120
  targets.each do |target|
113
- unless target.should_build?
114
- Pod::UI.puts "Skip prebuilding #{target.label} because of no source files".yellow
115
- next
116
- end
117
-
118
121
  output_path = sandbox.framework_folder_path_for_target_name(target.name)
119
122
  output_path.mkpath unless output_path.exist?
120
123
  Pod::Prebuild.build(
121
- sandbox_root_path: sandbox_path,
124
+ sandbox: sandbox_path,
122
125
  target: target,
123
126
  configuration: Pod::Podfile::DSL.prebuild_config,
124
127
  output_path: output_path,
125
- bitcode_enabled: bitcode_enabled,
126
- device_build_enabled: Pod::Podfile::DSL.device_build_enabled,
127
- custom_build_options: Pod::Podfile::DSL.custom_device_build_options,
128
- custom_build_options_simulator: Pod::Podfile::DSL.custom_simulator_build_options
128
+ bitcode_enabled: Pod::Podfile::DSL.bitcode_enabled?,
129
+ device_build_enabled: Pod::Podfile::DSL.device_build_enabled?,
130
+ disable_dsym: Pod::Podfile::DSL.disable_dsym?,
131
+ args: Pod::Podfile::DSL.build_args
129
132
  )
130
133
  collect_metadata(target, output_path)
131
134
  end
@@ -175,7 +178,7 @@ module Pod
175
178
  path.rmtree if path.exist?
176
179
  end
177
180
 
178
- if Podfile::DSL.dont_remove_source_code
181
+ if Podfile::DSL.dont_remove_source_code?
179
182
  # just remove the tmp files
180
183
  path = sandbox.root + "Manifest.lock.tmp"
181
184
  path.rmtree if path.exist?
@@ -214,8 +217,7 @@ module Pod
214
217
  .build_configurations
215
218
  .detect { |config| config.name == Pod::Podfile::DSL.prebuild_config }
216
219
  .build_settings
217
- hash = @lockfile_wrapper.dev_pod_hash(target.name)
218
- metadata.source_hash = hash unless hash.nil?
220
+ metadata.source_hash = @lockfile_wrapper && @lockfile_wrapper.dev_pod_hash(target.name)
219
221
 
220
222
  # Store root path for code-coverage support later
221
223
  # TODO: update driver code-coverage logic to use path stored here
@@ -3,68 +3,71 @@ require_relative "tool/tool"
3
3
  module Pod
4
4
  class Podfile
5
5
  module DSL
6
+ @binary_cache_config = {}
7
+ @binary_cache_cli_config = {}
6
8
  def config_cocoapods_binary_cache(options)
7
- apply_config = lambda do |config|
8
- DSL.send("#{config}=", options[config]) unless options[config].nil?
9
+ Pod::Podfile::DSL.binary_cache_config = options
10
+ end
11
+
12
+ class << self
13
+ attr_accessor :binary_cache_config
14
+ attr_accessor :binary_cache_cli_config
15
+
16
+ def prebuild_config
17
+ @binary_cache_config[:prebuild_config] || "Debug"
9
18
  end
10
19
 
11
- apply_config.call(:prebuild_config)
12
- apply_config.call(:prebuild_all) # TODO (thuyen): Revise this option
13
- apply_config.call(:prebuild_all_vendor_pods)
14
- apply_config.call(:excluded_pods)
15
- apply_config.call(:dev_pods_enabled)
16
- apply_config.call(:bitcode_enabled)
17
- apply_config.call(:device_build_enabled)
18
- apply_config.call(:dont_remove_source_code)
19
- apply_config.call(:custom_device_build_options)
20
- apply_config.call(:custom_simulator_build_options)
21
- apply_config.call(:save_cache_validation_to)
22
- apply_config.call(:validate_prebuilt_settings)
23
- end
20
+ def prebuild_job?
21
+ @binary_cache_cli_config[:prebuild_job] || @binary_cache_config[:prebuild_job]
22
+ end
24
23
 
25
- @prebuild_config = "Debug"
26
- @prebuild_job = false
27
- @prebuild_all = false
28
- @prebuild_all_vendor_pods = false
29
- @excluded_pods = Set.new
30
- @dev_pods_enabled = false
31
- @bitcode_enabled = false
32
- @device_build_enabled = false
33
- @dont_remove_source_code = false
34
- @custom_device_build_options = []
35
- @custom_simulator_build_options = []
36
- @save_cache_validation_to = nil
37
- # A proc to validate the provided build settings (per target) with the build settings of the prebuilt frameworks
38
- # For example, in Podfile:
39
- # -----------------------------------------------
40
- # validate_prebuilt_settings do |target|
41
- # settings = {}
42
- # settings["MACH_O_TYPE"] == "staticlib"
43
- # settings["SWIFT_VERSION"] == swift_version_of(target)
44
- # settings
45
- # end
46
- # -----------------------------------------------
47
- @validate_prebuilt_settings = nil
24
+ def prebuild_all_pods?
25
+ @binary_cache_cli_config[:prebuild_all_pods] || @binary_cache_config[:prebuild_all_pods]
26
+ end
48
27
 
49
- class << self
50
- attr_accessor :prebuild_config
51
- attr_accessor :prebuild_job
52
- attr_accessor :prebuild_all
53
- attr_accessor :prebuild_all_vendor_pods
54
- attr_accessor :excluded_pods
55
- attr_accessor :dev_pods_enabled
56
- attr_accessor :bitcode_enabled
57
- attr_accessor :device_build_enabled
58
- attr_accessor :dont_remove_source_code
59
- attr_accessor :custom_device_build_options
60
- attr_accessor :custom_simulator_build_options
61
- attr_accessor :save_cache_validation_to
62
- attr_accessor :validate_prebuilt_settings
63
-
64
- alias prebuild_job? prebuild_job
65
- alias prebuild_all? prebuild_all
66
- alias prebuild_all_vendor_pods? prebuild_all_vendor_pods
67
- alias dev_pods_enabled? dev_pods_enabled
28
+ def excluded_pods
29
+ @binary_cache_config[:excluded_pods] || Set.new
30
+ end
31
+
32
+ def dev_pods_enabled?
33
+ @binary_cache_config[:dev_pods_enabled]
34
+ end
35
+
36
+ def bitcode_enabled?
37
+ @binary_cache_config[:bitcode_enabled]
38
+ end
39
+
40
+ def device_build_enabled?
41
+ @binary_cache_config[:device_build_enabled]
42
+ end
43
+
44
+ def disable_dsym?
45
+ @binary_cache_config[:disable_dsym]
46
+ end
47
+
48
+ def dont_remove_source_code?
49
+ @binary_cache_config[:dont_remove_source_code]
50
+ end
51
+
52
+ def build_args
53
+ @binary_cache_config[:build_args]
54
+ end
55
+
56
+ def save_cache_validation_to
57
+ @binary_cache_config[:save_cache_validation_to]
58
+ end
59
+
60
+ def validate_prebuilt_settings
61
+ @binary_cache_config[:validate_prebuilt_settings]
62
+ end
63
+
64
+ def prebuild_code_gen
65
+ @binary_cache_config[:prebuild_code_gen]
66
+ end
67
+
68
+ def targets_to_prebuild_from_cli
69
+ @binary_cache_cli_config[:prebuild_targets] || []
70
+ end
68
71
  end
69
72
  end
70
73
  end
@@ -0,0 +1,176 @@
1
+ require_relative "xcodebuild_raw"
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
19
+
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
28
+ end
29
+ collect_output(Dir[target_products_dir_of(simulator) + "/*"])
30
+ end
31
+
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
46
+
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
64
+
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
71
+
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)
82
+ end
83
+
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
90
+
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
105
+
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)
110
+
111
+ FileUtils.cp_r(
112
+ device_swift_module_path + "/.",
113
+ simulator_swift_module_path
114
+ )
115
+ end
116
+
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)
122
+ end
123
+ end
124
+
125
+ def target_products_dir_of(sdk)
126
+ "#{build_dir}/#{configuration}-#{sdk}/#{target.name}"
127
+ end
128
+
129
+ def framework_path_of(sdk)
130
+ "#{target_products_dir_of(sdk)}/#{module_name}.framework"
131
+ end
132
+
133
+ def module_name
134
+ target.product_module_name
135
+ end
136
+
137
+ def sandbox
138
+ @options[:sandbox]
139
+ end
140
+
141
+ def build_dir
142
+ @options[:build_dir]
143
+ end
144
+
145
+ def output_path
146
+ @options[:output_path]
147
+ end
148
+
149
+ def target
150
+ @options[:target]
151
+ end
152
+
153
+ def configuration
154
+ @options[:configuration]
155
+ end
156
+
157
+ def bitcode_enabled?
158
+ @options[:bitcode_enabled]
159
+ end
160
+
161
+ def device_build_enabled?
162
+ @options[:device_build_enabled]
163
+ end
164
+
165
+ def device
166
+ @options[:device] || "iphoneos"
167
+ end
168
+
169
+ def simulator
170
+ @options[:simulator] || "iphonesimulator"
171
+ end
172
+
173
+ def disable_dsym?
174
+ @options[:disable_dsym]
175
+ end
176
+ end
@@ -0,0 +1,43 @@
1
+ require "fourflusher"
2
+
3
+ PLATFORM_OF_SDK = {
4
+ "iphonesimulator" => "iOS",
5
+ "appletvsimulator" => "tvOS",
6
+ "watchsimulator" => "watchOS"
7
+ }.freeze
8
+
9
+ def xcodebuild(options)
10
+ sdk = options[:sdk] || "iphonesimulator"
11
+ platform = PLATFORM_OF_SDK[sdk]
12
+
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(" ")
22
+
23
+ puts "xcodebuild command: #{cmd}"
24
+ log = `#{cmd}`
25
+
26
+ succeeded = $?.exitstatus.zero?
27
+ unless succeeded
28
+ begin
29
+ raise "Unexpected error" unless log.include?("** BUILD FAILED **")
30
+
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)
37
+ end
38
+ rescue
39
+ puts log.red
40
+ end
41
+ end
42
+ [succeeded, log]
43
+ end
@@ -8,12 +8,16 @@ module Pod
8
8
  self.arguments = [CLAide::Argument.new("CACHE-BRANCH", false)]
9
9
  def self.options
10
10
  [
11
- ["--push", "Push cache to repo upon completion"]
11
+ ["--push", "Push cache to repo upon completion"],
12
+ ["--all", "Prebuild all binary pods regardless of cache validation"],
13
+ ["--targets", "Targets to prebuild. Use comma (,) to specify a list of targets"]
12
14
  ]
13
15
  end
14
16
 
15
17
  def initialize(argv)
16
18
  super
19
+ @prebuild_all_pods = argv.flag?("all")
20
+ @prebuild_targets = argv.option("targets", "").split(",")
17
21
  @prebuilder = PodPrebuild::CachePrebuilder.new(
18
22
  config: prebuild_config,
19
23
  cache_branch: argv.shift_argument || "master",
@@ -22,7 +26,9 @@ module Pod
22
26
  end
23
27
 
24
28
  def run
25
- Pod::Podfile::DSL.prebuild_job = true
29
+ Pod::Podfile::DSL.binary_cache_cli_config[:prebuild_job] = true
30
+ Pod::Podfile::DSL.binary_cache_cli_config[:prebuild_all_pods] = @prebuild_all_pods
31
+ Pod::Podfile::DSL.binary_cache_cli_config[:prebuild_targets] = @prebuild_targets unless @prebuild_all_pods
26
32
  @prebuilder.run
27
33
  end
28
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-binary-cache
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.5
4
+ version: 0.1.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bang Nguyen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-04 00:00:00.000000000 Z
11
+ date: 2020-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cocoapods
@@ -129,6 +129,7 @@ files:
129
129
  - lib/cocoapods-binary-cache/hooks/pre_install.rb
130
130
  - lib/cocoapods-binary-cache/main.rb
131
131
  - lib/cocoapods-binary-cache/pod-binary/LICENSE.txt
132
+ - lib/cocoapods-binary-cache/pod-binary/helper/build.rb
132
133
  - lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/installer.rb
133
134
  - lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/target_definition.rb
134
135
  - lib/cocoapods-binary-cache/pod-binary/helper/feature_switches.rb
@@ -150,7 +151,8 @@ files:
150
151
  - lib/cocoapods-binary-cache/pod-binary/prebuild_hook.rb
151
152
  - lib/cocoapods-binary-cache/pod-binary/tool/tool.rb
152
153
  - lib/cocoapods-binary-cache/pod-rome/LICENSE.txt
153
- - lib/cocoapods-binary-cache/pod-rome/build_framework.rb
154
+ - lib/cocoapods-binary-cache/pod-rome/xcodebuild_command.rb
155
+ - lib/cocoapods-binary-cache/pod-rome/xcodebuild_raw.rb
154
156
  - lib/cocoapods-binary-cache/prebuild_output/metadata.rb
155
157
  - lib/cocoapods-binary-cache/prebuild_output/output.rb
156
158
  - lib/cocoapods-binary-cache/scheme_editor.rb
@@ -188,7 +190,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
188
190
  - !ruby/object:Gem::Version
189
191
  version: '0'
190
192
  requirements: []
191
- rubygems_version: 3.0.8
193
+ rubygems_version: 3.0.3
192
194
  signing_key:
193
195
  specification_version: 4
194
196
  summary: Reduce build time by building pod frameworks and cache to remote storage,
@@ -1,248 +0,0 @@
1
- require 'fourflusher'
2
- require 'xcpretty' # TODO (thuyen): Revise this dependency
3
-
4
- module FileUtils
5
- def self.mvpath(src, dst, **options)
6
- FileUtils.rm_rf(File.join(dst, File.basename(src)))
7
- FileUtils.mv(src, dst, **options)
8
- end
9
- end
10
-
11
- PLATFORMS = { 'iphonesimulator' => 'iOS',
12
- 'appletvsimulator' => 'tvOS',
13
- 'watchsimulator' => 'watchOS' }
14
-
15
- # Build specific target to framework file
16
- # @param [PodTarget] target
17
- # a specific pod target
18
- #
19
- def build_for_iosish_platform(sandbox,
20
- build_dir,
21
- output_path,
22
- target,
23
- configuration,
24
- device,
25
- simulator,
26
- bitcode_enabled,
27
- custom_build_options = [], # Array<String>
28
- custom_build_options_simulator = [], # Array<String>
29
- enable_device_build = false
30
- )
31
-
32
- deployment_target = target.platform.deployment_target.to_s
33
-
34
- target_label = target.label # name with platform if it's used in multiple platforms
35
- Pod::UI.puts "Prebuilding #{target_label}..."
36
-
37
- other_options = []
38
- # bitcode enabled
39
- other_options += ['BITCODE_GENERATION_MODE=bitcode'] if bitcode_enabled
40
- # make less arch to iphone simulator for faster build
41
- custom_build_options_simulator += ['ARCHS=x86_64', 'ONLY_ACTIVE_ARCH=NO'] if simulator == 'iphonesimulator'
42
-
43
- # paths
44
- target_name = target.name # equals target.label, like "AFNeworking-iOS" when AFNetworking is used in multiple platforms.
45
- module_name = target.product_module_name
46
- device_framework_path = "#{build_dir}/#{configuration}-#{device}/#{target_name}/#{module_name}.framework"
47
- simulator_framework_path = "#{build_dir}/#{configuration}-#{simulator}/#{target_name}/#{module_name}.framework"
48
- simulator_target_products_path = "#{build_dir}/#{configuration}-#{simulator}/#{target_name}"
49
-
50
- if !Dir.exist?(simulator_framework_path)
51
- is_succeed, = xcodebuild(
52
- sandbox,
53
- target_label,
54
- configuration,
55
- simulator,
56
- deployment_target,
57
- other_options + custom_build_options_simulator
58
- )
59
- raise "Build simulator framework failed: #{target_label}" unless is_succeed
60
- else
61
- puts "Simulator framework already exist at: #{simulator_framework_path}"
62
- end
63
-
64
- unless enable_device_build
65
- FileUtils.cp_r Dir["#{simulator_target_products_path}/*"], output_path
66
- return
67
- end
68
-
69
- if !Dir.exist?(device_framework_path)
70
- is_succeed, = xcodebuild(
71
- sandbox,
72
- target_label,
73
- configuration,
74
- device,
75
- deployment_target,
76
- other_options + custom_build_options
77
- )
78
- raise "Build device framework failed: #{target_label}" unless is_succeed
79
- else
80
- puts "Device framework already exist at: #{device_framework_path}"
81
- end
82
-
83
- device_binary = device_framework_path + "/#{module_name}"
84
- simulator_binary = simulator_framework_path + "/#{module_name}"
85
- return unless File.file?(device_binary) && File.file?(simulator_binary)
86
-
87
- # the device_lib path is the final output file path
88
- # combine the binaries
89
- tmp_lipoed_binary_path = "#{build_dir}/#{target_name}"
90
- lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_binary} #{simulator_binary}`
91
- puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
92
- FileUtils.mvpath tmp_lipoed_binary_path, device_binary
93
-
94
- # collect the swiftmodule file for various archs.
95
- device_swiftmodule_path = device_framework_path + "/Modules/#{module_name}.swiftmodule"
96
- simulator_swiftmodule_path = simulator_framework_path + "/Modules/#{module_name}.swiftmodule"
97
- if File.exist?(device_swiftmodule_path)
98
- FileUtils.cp_r simulator_swiftmodule_path + "/.", device_swiftmodule_path
99
- end
100
-
101
- # combine the generated swift headers
102
- # (In xcode 10.2, the generated swift headers vary for each archs)
103
- # https://github.com/leavez/cocoapods-binary/issues/58
104
- simulator_generated_swift_header_path = simulator_framework_path + "/Headers/#{module_name}-Swift.h"
105
- device_generated_swift_header_path = device_framework_path + "/Headers/#{module_name}-Swift.h"
106
- if File.exist? simulator_generated_swift_header_path
107
- device_header = File.read(device_generated_swift_header_path)
108
- simulator_header = File.read(simulator_generated_swift_header_path)
109
- # https://github.com/Carthage/Carthage/issues/2718#issuecomment-473870461
110
- combined_header_content = %Q{
111
- #if TARGET_OS_SIMULATOR // merged by cocoapods-binary
112
-
113
- #{simulator_header}
114
-
115
- #else // merged by cocoapods-binary
116
-
117
- #{device_header}
118
-
119
- #endif // merged by cocoapods-binary
120
- }
121
- File.write(device_generated_swift_header_path, combined_header_content.strip)
122
- end
123
-
124
- # handle the dSYM files
125
- device_dsym = "#{device_framework_path}.dSYM"
126
- if File.exist? device_dsym
127
- # lipo the simulator dsym
128
- simulator_dsym = "#{simulator_framework_path}.dSYM"
129
- if File.exist? simulator_dsym
130
- tmp_lipoed_binary_path = "#{output_path}/#{module_name}.draft"
131
- lipo_log = `lipo -create -output #{tmp_lipoed_binary_path} #{device_dsym}/Contents/Resources/DWARF/#{module_name} #{simulator_dsym}/Contents/Resources/DWARF/#{module_name}`
132
- puts lipo_log unless File.exist?(tmp_lipoed_binary_path)
133
- FileUtils.mvpath tmp_lipoed_binary_path, "#{device_framework_path}.dSYM/Contents/Resources/DWARF/#{module_name}"
134
- end
135
- FileUtils.mvpath device_dsym, output_path
136
- end
137
-
138
- # output
139
- output_path.mkpath unless output_path.exist?
140
- FileUtils.mvpath device_framework_path, output_path
141
- end
142
-
143
- def xcodebuild(sandbox, target, configuration, sdk='macosx', deployment_target=nil, other_options=[])
144
- args = %W(-project #{sandbox.project_path.realdirpath} -scheme #{target} -configuration #{configuration} -sdk #{sdk} )
145
- platform = PLATFORMS[sdk]
146
- args += Fourflusher::SimControl.new.destination(:oldest, platform, deployment_target) unless platform.nil?
147
- args += other_options
148
-
149
- args_str = args.join(" ")
150
- cmd = "xcodebuild #{args_str} 2>&1"
151
- puts "xcodebuild command: #{cmd}"
152
- log = `#{cmd}`
153
-
154
- exit_code = $?.exitstatus # Process::Status
155
- is_succeed = (exit_code == 0)
156
-
157
- if !is_succeed
158
- begin
159
- if log.include?('** BUILD FAILED **')
160
- # use xcpretty to print build log
161
- # 64 represent command invalid. http://www.manpagez.com/man/3/sysexits/
162
- printer = XCPretty::Printer.new({:formatter => XCPretty::Simple, :colorize => 'auto'})
163
- log.each_line do |line|
164
- printer.pretty_print(line)
165
- end
166
- else
167
- raise "shouldn't be handle by xcpretty"
168
- end
169
- rescue
170
- puts log.red
171
- end
172
- end
173
- [is_succeed, log]
174
- end
175
-
176
- module Pod
177
- class Prebuild
178
- def self.build(options)
179
- sandbox_root_path = options[:sandbox_root_path]
180
- target = options[:target]
181
- configuration = options[:configuration]
182
- output_path = options[:output_path]
183
- bitcode_enabled = options[:bitcode_enabled] || false
184
- device_build_enabled = options[:device_build_enabled] || false
185
- custom_build_options = options[:custom_build_options] || []
186
- custom_build_options_simulator = options[:custom_build_options_simulator] || []
187
-
188
- return if target.nil?
189
-
190
- sandbox_root = Pathname(sandbox_root_path)
191
- sandbox = Pod::Sandbox.new(sandbox_root)
192
- build_dir = self.build_dir(sandbox_root)
193
-
194
- # -- build the framework
195
- case target.platform.name
196
- when :ios
197
- build_for_iosish_platform(
198
- sandbox,
199
- build_dir,
200
- output_path,
201
- target,
202
- configuration,
203
- "iphoneos",
204
- "iphonesimulator",
205
- bitcode_enabled,
206
- custom_build_options,
207
- custom_build_options_simulator,
208
- device_build_enabled
209
- )
210
- when :osx
211
- xcodebuild(
212
- sandbox,
213
- target.label,
214
- configuration,
215
- "macosx",
216
- nil,
217
- custom_build_options
218
- )
219
- # when :tvos then build_for_iosish_platform(sandbox, build_dir, target, 'appletvos', 'appletvsimulator')
220
- when :watchos
221
- build_for_iosish_platform(
222
- sandbox,
223
- build_dir,
224
- output_path,
225
- target,
226
- configuration,
227
- "watchos",
228
- "watchsimulator",
229
- true,
230
- custom_build_options,
231
- custom_build_options_simulator,
232
- device_build_enabled
233
- )
234
- else raise "Unsupported platform for '#{target.name}': '#{target.platform.name}'" end
235
-
236
- raise Pod::Informative, "The build directory was not found in the expected location" unless build_dir.directory?
237
- end
238
-
239
- def self.remove_build_dir(sandbox_root)
240
- path = build_dir(sandbox_root)
241
- path.rmtree if path.exist?
242
- end
243
-
244
- def self.build_dir(sandbox_root)
245
- sandbox_root.parent + "build"
246
- end
247
- end
248
- end