cocoapods-binary-cache 0.1.5 → 0.1.6

Sign up to get free protection for your applications and to get access to all the features.
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