cocoapods-binary-cache 0.1.8 → 0.1.13

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: 939a85addd611d4a4bcd2b9ce1eeb7e036d58a937a14bdd4f772a6c8170e4394
4
- data.tar.gz: 0372d8f94f6e486259669f4db5431585a08645c1a23ad363258581fc5f679eff
3
+ metadata.gz: 732c3a4179deba8a6f1ffe95e9035c12d80989a1b3edb0581a5d569f1b9ef542
4
+ data.tar.gz: c72c2d4333f1525d2078896374b2fbe239891dc404ca35dadffc2f22fc4b8aff
5
5
  SHA512:
6
- metadata.gz: aa2bbc570dc6a1f462a85286578b8dc41a7ce189df2017177d083a70df9ac0d026c8ca8dea310eee2ae5b517b3418004045b8bcc782aa0440f755d8bab1dd0d4
7
- data.tar.gz: c98e55ae66d034897db4969bf9c12b0386a69a5139bc78ada10298875c5a9487d499852bb77195ffca42f11b0d2ab97fad940348da90d21296f6f0d6952b64af
6
+ metadata.gz: 9ff71c26afc711721ce4360999a94b03a36fcd49f51ead77583c5ef4b07e86c7c841effcfdc023a4968d26d19d33f66ed9ea0891ce046584e9c4bd50e6afa375
7
+ data.tar.gz: 1c28065aefc4539864e5645d9d01c5b660c03a9df40ca72a05a07be80cba28c28906e11802ff4fcb676057628e4eb4f39a8eee72ec920a04d4acfc336589a9d2
@@ -1,7 +1,6 @@
1
1
  module Pod
2
2
  class Specification
3
3
  def empty_source_files?
4
-
5
4
  unless subspecs.empty?
6
5
  # return early if there are some files in subpec(s) but process the spec itself
7
6
  return false unless subspecs.all?(&:empty_source_files?)
@@ -5,7 +5,6 @@ module PodPrebuild
5
5
  end
6
6
 
7
7
  def run
8
- edit_scheme_for_code_coverage if PodPrebuild::Env.prebuild_stage?
9
8
  diagnose if PodPrebuild::Env.integration_stage?
10
9
  end
11
10
 
@@ -20,15 +19,5 @@ module PodPrebuild
20
19
  ).run
21
20
  end
22
21
  end
23
-
24
- def edit_scheme_for_code_coverage
25
- return unless PodPrebuild.config.dev_pods_enabled?
26
- return unless @installer_context.sandbox.instance_of?(Pod::PrebuildSandbox)
27
-
28
- # Modify pods scheme to support code coverage
29
- # If we don't prebuild dev pod -> no need to care about this in Pod project
30
- # because we setup in the main project (ex. DriverCI scheme)
31
- SchemeEditor.edit_to_support_code_coverage(@installer_context.sandbox)
32
- end
33
22
  end
34
23
  end
@@ -2,13 +2,14 @@ module PodPrebuild
2
2
  class PreInstallHook
3
3
  include ObjectSpace
4
4
 
5
- attr_reader :installer_context, :podfile, :prebuild_sandbox, :cache_validation
5
+ attr_reader :installer_context, :podfile, :prebuild_sandbox, :standard_sandbox, :cache_validation
6
6
 
7
7
  def initialize(installer_context)
8
8
  @installer_context = installer_context
9
9
  @podfile = installer_context.podfile
10
10
  @pod_install_options = {}
11
11
  @prebuild_sandbox = nil
12
+ @standard_sandbox = installer_context.sandbox
12
13
  @cache_validation = nil
13
14
  end
14
15
 
@@ -24,6 +25,7 @@ module PodPrebuild
24
25
  prebuild! if PodPrebuild.config.prebuild_job?
25
26
 
26
27
  PodPrebuild::Env.next_stage!
28
+ prepare_for_integration
27
29
  log_section "🤖 Resume pod installation"
28
30
  require_relative "../pod-binary/integration"
29
31
  end
@@ -51,7 +53,6 @@ module PodPrebuild
51
53
  end
52
54
 
53
55
  def create_prebuild_sandbox
54
- standard_sandbox = installer_context.sandbox
55
56
  @prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sandbox)
56
57
  Pod::UI.message "Create prebuild sandbox at #{@prebuild_sandbox.root}"
57
58
  end
@@ -102,6 +103,15 @@ module PodPrebuild
102
103
  end
103
104
  end
104
105
 
106
+ def prepare_for_integration
107
+ # Remove local podspec of external sources so that it downloads sources correctly.
108
+ # Otherwise, with incremental pod installation, CocoaPods downloads the sources
109
+ # based on the `s.source` declaration in the podspecs which are sometimes incorrect.
110
+ PodPrebuild.config.prebuilt_pod_names.each do |name|
111
+ @standard_sandbox.remove_local_podspec(name) if @standard_sandbox.checkout_sources.key?(name)
112
+ end
113
+ end
114
+
105
115
  def log_section(message)
106
116
  Pod::UI.puts "-----------------------------------------"
107
117
  Pod::UI.puts message
@@ -18,5 +18,4 @@ require_relative "pod-binary/prebuild_hook"
18
18
  require_relative "pod-binary/prebuild"
19
19
  require_relative "prebuild_output/metadata"
20
20
  require_relative "prebuild_output/output"
21
- require_relative "scheme_editor"
22
21
  require_relative "diagnosis/diagnosis"
@@ -1,40 +1,37 @@
1
1
  require_relative "../../pod-rome/xcodebuild_raw"
2
2
  require_relative "../../pod-rome/xcodebuild_command"
3
3
 
4
- module Pod
5
- class Prebuild
6
- def self.build(options)
7
- target = options[:target]
8
- return if target.nil?
4
+ module PodPrebuild
5
+ def self.build(options)
6
+ targets = options[:targets] || []
7
+ return if targets.empty?
9
8
 
10
- Pod::UI.puts "Building target: #{target}...".magenta
11
- options[:sandbox] = Pod::Sandbox.new(Pathname(options[:sandbox])) unless options[:sandbox].is_a?(Pod::Sandbox)
12
- options[:build_dir] = build_dir(options[:sandbox].root)
9
+ options[:sandbox] = Pod::Sandbox.new(Pathname(options[:sandbox])) unless options[:sandbox].is_a?(Pod::Sandbox)
10
+ options[:build_dir] = build_dir(options[:sandbox].root)
13
11
 
14
- case target.platform.name
15
- when :ios, :tvos, :watchos
16
- XcodebuildCommand.new(options).run
17
- when :osx
18
- xcodebuild(
19
- sandbox: options[:sandbox],
20
- target: target.label,
21
- configuration: options[:configuration],
22
- sdk: "macosx",
23
- args: options[:args]
24
- )
25
- else
26
- raise "Unsupported platform for '#{target.name}': '#{target.platform.name}'"
27
- end
28
- raise "The build directory was not found in the expected location" unless options[:build_dir].directory?
12
+ case targets[0].platform.name
13
+ when :ios, :tvos, :watchos
14
+ PodPrebuild::XcodebuildCommand.new(options).run
15
+ when :osx
16
+ xcodebuild(
17
+ sandbox: options[:sandbox],
18
+ targets: targets,
19
+ configuration: options[:configuration],
20
+ sdk: "macosx",
21
+ args: options[:args]
22
+ )
23
+ else
24
+ raise "Unsupported platform for '#{targets[0].name}': '#{targets[0].platform.name}'"
29
25
  end
26
+ raise "The build directory was not found in the expected location" unless options[:build_dir].directory?
27
+ end
30
28
 
31
- def self.remove_build_dir(sandbox_root)
32
- path = build_dir(sandbox_root)
33
- path.rmtree if path.exist?
34
- end
29
+ def self.remove_build_dir(sandbox_root)
30
+ path = build_dir(sandbox_root)
31
+ path.rmtree if path.exist?
32
+ end
35
33
 
36
- def self.build_dir(sandbox_root)
37
- sandbox_root.parent + "build"
38
- end
34
+ def self.build_dir(sandbox_root)
35
+ sandbox_root.parent + "build"
39
36
  end
40
37
  end
@@ -4,26 +4,43 @@ module Pod
4
4
  cache = []
5
5
  analysis_result.specifications
6
6
  .select { |spec| should_integrate_prebuilt_pod?(spec.root.name) }
7
- .each { |spec| alter_spec(spec, cache) }
7
+ .group_by(&:root)
8
+ .each do |_, specs|
9
+ first_subspec_or_self = specs.find(&:subspec?) || specs[0]
10
+ specs.each do |spec|
11
+ alterations = {
12
+ :source_files => true,
13
+ :resources => true,
14
+ :license => true,
15
+ :vendored_framework => spec == first_subspec_or_self
16
+ }
17
+ alter_spec(spec, alterations, cache)
18
+ end
19
+ end
8
20
  end
9
21
 
10
- def alter_spec(spec, cache)
22
+ private
23
+
24
+ def alter_spec(spec, alterations, cache)
11
25
  targets = Pod.fast_get_targets_for_pod_name(spec.root.name, pod_targets, cache)
12
- targets.each do |target|
13
- # Use the prebuild framworks as vendered frameworks.
14
- # The framework_file_path rule is decided in `install_for_prebuild`,
15
- # as to compitable with older version and be less wordy.
16
- framework_file_path = target.framework_name
17
- framework_file_path = target.name + "/" + framework_file_path if targets.count > 1
18
- framework_file_path = PodPrebuild.config.prebuilt_path(path: framework_file_path)
19
- add_vendered_framework(spec, target.platform.name.to_s, framework_file_path)
26
+ platforms = targets.map { |target| target.platform.name.to_s }.uniq
27
+
28
+ if alterations[:vendored_framework]
29
+ targets.each do |target|
30
+ # Use the prebuilt frameworks as vendered frameworks.
31
+ # The framework_file_path rule is decided in `install_for_prebuild`,
32
+ # as to compitable with older version and be less wordy.
33
+ framework_file_path = target.framework_name
34
+ framework_file_path = target.name + "/" + framework_file_path if targets.count > 1
35
+ framework_file_path = PodPrebuild.config.prebuilt_path(path: framework_file_path)
36
+ add_vendered_framework(spec, target.platform.name.to_s, framework_file_path)
37
+ end
20
38
  end
21
39
 
22
- platforms = targets.map { |target| target.platform.name.to_s }.uniq
23
- empty_source_files(spec, platforms)
24
- tweak_resources_for_xib(spec, platforms)
25
- tweak_resources_for_resource_bundles(spec, platforms)
26
- empty_liscence(spec) # to avoid the warning of missing license
40
+ empty_source_files(spec, platforms) if alterations[:source_files]
41
+ tweak_resources_for_xib(spec, platforms) if alterations[:resources]
42
+ tweak_resources_for_resource_bundles(spec, platforms) if alterations[:resources]
43
+ empty_liscence(spec) if alterations[:license]
27
44
  end
28
45
 
29
46
  def tweak_resources_for_xib(spec, platforms)
@@ -17,7 +17,7 @@ module Pod
17
17
  # If the path isn't an absolute path, we add a realtive prefix.
18
18
  old_read_link=`which readlink`
19
19
  readlink () {
20
- path=`$old_read_link $1`;
20
+ path=`$old_read_link "$1"`;
21
21
  if [ $(echo "$path" | cut -c 1-1) = '/' ]; then
22
22
  echo $path;
23
23
  else
@@ -3,17 +3,31 @@ require_relative "../source_installer"
3
3
  module Pod
4
4
  class Installer
5
5
  # Override the download step to skip download and prepare file in target folder
6
- define_method(:install_source_of_pod) do |pod_name|
7
- pod_installer = create_pod_installer(pod_name)
8
- # Injected code
9
- # ------------------------------------------
10
- if should_integrate_prebuilt_pod?(pod_name)
11
- pod_installer.install_for_prebuild!(sandbox)
6
+ alias original_create_pod_installer create_pod_installer
7
+ def create_pod_installer(name)
8
+ if should_integrate_prebuilt_pod?(name)
9
+ create_prebuilt_source_installer(name)
12
10
  else
13
- pod_installer.install!
11
+ create_normal_source_installer(name)
14
12
  end
15
- # ------------------------------------------
16
- @installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
13
+ end
14
+
15
+ private
16
+
17
+ def create_normal_source_installer(name)
18
+ original_create_pod_installer(name)
19
+ end
20
+
21
+ def create_prebuilt_source_installer(name)
22
+ source_installer = PodSourceInstaller.new(sandbox, podfile, specs_for_pod(name))
23
+ pod_installer = PrebuiltSourceInstaller.new(
24
+ sandbox,
25
+ podfile,
26
+ specs_for_pod(name),
27
+ source_installer: source_installer
28
+ )
29
+ pod_installers << pod_installer
30
+ pod_installer
17
31
  end
18
32
 
19
33
  def should_integrate_prebuilt_pod?(name)
@@ -1,21 +1,27 @@
1
- # NOTE:
2
- # This file will only be loaded on normal pod install step
3
- # so there's no need to check is_prebuild_stage
4
-
5
- # Provide a special "download" process for prebuilded pods.
6
- #
7
- # As the frameworks is already exsited in local folder. We
8
- # just create a symlink to the original target folder.
9
- #
10
1
  module Pod
11
2
  class Installer
12
- class PodSourceInstaller
13
- def install_for_prebuild!(standard_sanbox)
14
- return if !PodPrebuild.config.dev_pods_enabled? && standard_sanbox.local?(name)
3
+ class PrebuiltSourceInstaller < PodSourceInstaller
4
+ def initialize(*args, **kwargs)
5
+ @source_installer = kwargs.delete(:source_installer)
6
+ super(*args, **kwargs)
7
+ end
8
+
9
+ def prebuild_sandbox
10
+ @prebuild_sandbox ||= Pod::PrebuildSandbox.from_standard_sandbox(sandbox)
11
+ end
12
+
13
+ def install!
14
+ @source_installer.install!
15
+ install_prebuilt_framework!
16
+ end
17
+
18
+ private
19
+
20
+ def install_prebuilt_framework!
21
+ return if !PodPrebuild.config.dev_pods_enabled? && sandbox.local?(name)
15
22
 
16
23
  # make a symlink to target folder
17
24
  # TODO (bang): Unify to 1 sandbox to optimize and avoid inconsistency
18
- prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sanbox)
19
25
  # if spec used in multiple platforms, it may return multiple paths
20
26
  target_names = prebuild_sandbox.existed_target_names_for_pod_name(name)
21
27
  target_names.each do |name|
@@ -24,7 +30,7 @@ module Pod
24
30
  # If have only one platform, just place int the root folder of this pod.
25
31
  # If have multiple paths, we use a sperated folder to store different
26
32
  # platform frameworks. e.g. AFNetworking/AFNetworking-iOS/AFNetworking.framework
27
- target_folder = standard_sanbox.pod_dir(self.name)
33
+ target_folder = sandbox.pod_dir(self.name)
28
34
  target_folder += real_file_folder.basename if target_names.count > 1
29
35
  target_folder += PodPrebuild.config.prebuilt_path
30
36
  target_folder.rmtree if target_folder.exist?
@@ -33,8 +39,10 @@ module Pod
33
39
  walk(real_file_folder) do |child|
34
40
  source = child
35
41
  # only make symlink to file and `.framework` folder
36
- if child.directory? && [".framework", ".dSYM"].include?(child.extname)
37
- mirror_with_symlink(source, real_file_folder, target_folder) if child.extname == ".framework"
42
+ if child.directory? && [".framework", ".xcframework", ".dSYM"].include?(child.extname)
43
+ if [".framework", ".xcframework"].include?(child.extname)
44
+ mirror_with_symlink(source, real_file_folder, target_folder)
45
+ end
38
46
  # Ignore dsym here to avoid cocoapods from adding install_dsym to buildphase-script
39
47
  # That can cause duplicated output files error in Xcode 11 (warning in Xcode 10)
40
48
  # We need more setup to support local debuging with prebuilt dSYM
@@ -52,10 +60,15 @@ module Pod
52
60
  next unless metadata.static_framework?
53
61
 
54
62
  metadata.resources.each do |path|
55
- target_file_path = path
63
+ target_file_path = Pathname(path)
56
64
  .sub("${PODS_ROOT}", sandbox.root.to_path)
57
65
  .sub("${PODS_CONFIGURATION_BUILD_DIR}", sandbox.root.to_path)
66
+ next if target_file_path.exist?
67
+
58
68
  real_file_path = real_file_folder + metadata.framework_name + File.basename(path)
69
+
70
+ # TODO (thuyen): Fix https://github.com/grab/cocoapods-binary-cache/issues/45
71
+
59
72
  case File.extname(path)
60
73
  when ".xib"
61
74
  # https://github.com/grab/cocoapods-binary-cache/issues/7
@@ -73,8 +86,6 @@ module Pod
73
86
  end
74
87
  end
75
88
 
76
- private
77
-
78
89
  def walk(path, &action)
79
90
  return unless path.exist?
80
91
 
@@ -1,7 +1,6 @@
1
1
  require "fileutils"
2
2
  require_relative "../prebuild_output/output"
3
3
  require_relative "../helper/lockfile"
4
- require_relative "../helper/prebuild_order"
5
4
  require_relative "helper/target_checker"
6
5
  require_relative "helper/build"
7
6
 
@@ -15,6 +14,13 @@ module Pod
15
14
  @lockfile_wrapper = lockfile && PodPrebuild::Lockfile.new(lockfile)
16
15
  end
17
16
 
17
+ def installation_options
18
+ # Skip integrating user targets for prebuild Pods project.
19
+ @installation_options ||= Pod::Installer::InstallationOptions.new(
20
+ super.to_h.merge(:integrate_targets => false)
21
+ )
22
+ end
23
+
18
24
  def run_code_gen!(targets)
19
25
  return if PodPrebuild.config.prebuild_code_gen.nil?
20
26
 
@@ -38,27 +44,27 @@ module Pod
38
44
  def prebuild_frameworks!
39
45
  existed_framework_folder = sandbox.generate_framework_path
40
46
  sandbox_path = sandbox.root
47
+ targets = targets_to_prebuild
48
+ Pod::UI.puts "Prebuild frameworks (total #{targets.count}): #{targets.map(&:name)}".magenta
41
49
 
42
- targets = PodPrebuild::BuildOrder.order_targets(targets_to_prebuild)
43
- Pod::UI.puts "Prebuild frameworks (total #{targets.count}): #{targets.map(&:name)}"
44
- Pod::Prebuild.remove_build_dir(sandbox_path)
45
50
  run_code_gen!(targets)
51
+
52
+ PodPrebuild.remove_build_dir(sandbox_path)
53
+ PodPrebuild.build(
54
+ sandbox: sandbox_path,
55
+ targets: targets,
56
+ configuration: PodPrebuild.config.prebuild_config,
57
+ output_path: sandbox.generate_framework_path,
58
+ bitcode_enabled: PodPrebuild.config.bitcode_enabled?,
59
+ device_build_enabled: PodPrebuild.config.device_build_enabled?,
60
+ disable_dsym: PodPrebuild.config.disable_dsym?,
61
+ args: PodPrebuild.config.build_args
62
+ )
63
+ PodPrebuild.remove_build_dir(sandbox_path)
64
+
46
65
  targets.each do |target|
47
- output_path = sandbox.framework_folder_path_for_target_name(target.name)
48
- output_path.mkpath unless output_path.exist?
49
- Pod::Prebuild.build(
50
- sandbox: sandbox_path,
51
- target: target,
52
- configuration: PodPrebuild.config.prebuild_config,
53
- output_path: output_path,
54
- bitcode_enabled: PodPrebuild.config.bitcode_enabled?,
55
- device_build_enabled: PodPrebuild.config.device_build_enabled?,
56
- disable_dsym: PodPrebuild.config.disable_dsym?,
57
- args: PodPrebuild.config.build_args
58
- )
59
- collect_metadata(target, output_path)
66
+ collect_metadata(target, sandbox.framework_folder_path_for_target_name(target.name))
60
67
  end
61
- Pod::Prebuild.remove_build_dir(sandbox_path)
62
68
 
63
69
  # copy vendored libraries and frameworks
64
70
  targets.each do |target|
@@ -1,192 +1,252 @@
1
1
  require_relative "xcodebuild_raw"
2
2
 
3
- class XcodebuildCommand # rubocop:disable Metrics/ClassLength
4
- def initialize(options)
5
- @options = options
6
- case options[:target].platform.name
7
- when :ios
8
- @options[:device] = "iphoneos"
9
- @options[:simulator] = "iphonesimulator"
10
- when :tvos
11
- @options[:device] = "appletvos"
12
- @options[:simulator] = "appletvsimulator"
13
- when :watchos
14
- @options[:device] = "watchos"
15
- @options[:simulator] = "watchsimulator"
16
- end
17
- @build_args = make_up_build_args(options[:args] || {})
18
- end
3
+ module PodPrebuild
4
+ class XcodebuildCommand # rubocop:disable Metrics/ClassLength
5
+ def initialize(options)
6
+ @options = options
7
+ case options[:targets][0].platform.name
8
+ when :ios
9
+ @options[:device] = "iphoneos"
10
+ @options[:simulator] = "iphonesimulator"
11
+ when :tvos
12
+ @options[:device] = "appletvos"
13
+ @options[:simulator] = "appletvsimulator"
14
+ when :watchos
15
+ @options[:device] = "watchos"
16
+ @options[:simulator] = "watchsimulator"
17
+ end
18
+ @build_args = make_up_build_args(options[:args] || {})
19
+ end
19
20
 
20
- def run
21
- build_for_sdk(simulator) if build_types.include?(:simulator)
22
- build_for_sdk(device) if build_types.include?(:device)
21
+ def run
22
+ sdks.each { |sdk| build_for_sdk(sdk) }
23
+
24
+ targets.each do |target|
25
+ if PodPrebuild.config.xcframework?
26
+ create_xcframework(target)
27
+ elsif sdks.count > 1
28
+ create_fat_framework(target)
29
+ else
30
+ collect_output(target, Dir[target_products_dir_of(target, sdks[0]) + "/*"])
31
+ end
32
+ end
33
+ end
23
34
 
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) + "/*"])
33
- create_universal_framework
35
+ private
36
+
37
+ def sdks
38
+ @sdks ||= begin
39
+ sdks_ = []
40
+ sdks_ << simulator if build_types.include?(:simulator)
41
+ sdks_ << device if build_types.include?(:device)
42
+ sdks_
43
+ end
34
44
  end
35
- end
36
45
 
37
- private
46
+ def build_types
47
+ @build_types ||= begin
48
+ # TODO (thuyen): Add DSL options `build_for_types` to specify build types
49
+ types = [:simulator]
50
+ types << :device if device_build_enabled?
51
+ types
52
+ end
53
+ end
38
54
 
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
55
+ def make_up_build_args(args)
56
+ # Note: The build arguments explicitly passed from config_cocoapods_binary_cache
57
+ # should be preceded by the default arguments so that they could take higher priority
58
+ # when there are argument collisions in the xcodebuild command.
59
+ # For ex. `xcodebuild AN_ARG=1 AN_ARG=2` should use `AN_ARG=2` instead.
60
+ args_ = args.clone
61
+ args_[:default] ||= []
62
+ args_[:simulator] ||= []
63
+ args_[:device] ||= []
64
+ args_[:default].prepend("BITCODE_GENERATION_MODE=bitcode") if bitcode_enabled?
65
+ args_[:default].prepend("DEBUG_INFORMATION_FORMAT=dwarf") if disable_dsym?
66
+ args_[:simulator].prepend("ARCHS=x86_64", "ONLY_ACTIVE_ARCH=NO") if simulator == "iphonesimulator"
67
+ args_[:simulator] += args_[:default]
68
+ args_[:device].prepend("ONLY_ACTIVE_ARCH=NO")
69
+ args_[:device] += args_[:default]
70
+ args_
45
71
  end
46
- end
47
72
 
48
- def make_up_build_args(args)
49
- args_ = args.clone
50
- args_[:default] ||= []
51
- args_[:simulator] ||= []
52
- args_[:device] ||= []
53
- args_[:default] += ["BITCODE_GENERATION_MODE=bitcode"] if bitcode_enabled?
54
- args_[:default] += ["DEBUG_INFORMATION_FORMAT=dwarf"] if disable_dsym?
55
- args_[:simulator] += ["ARCHS=x86_64", "ONLY_ACTIVE_ARCH=NO"] if simulator == "iphonesimulator"
56
- args_[:simulator] += args_[:default]
57
- args_[:device] += args_[:default]
58
- args_
59
- end
73
+ def build_for_sdk(sdk)
74
+ PodPrebuild::XcodebuildCommand.xcodebuild(
75
+ sandbox: sandbox,
76
+ scheme: scheme,
77
+ targets: targets.map(&:label),
78
+ configuration: configuration,
79
+ sdk: sdk,
80
+ deployment_target: targets.map { |t| t.platform.deployment_target }.max.to_s,
81
+ args: sdk == simulator ? @build_args[:simulator] : @build_args[:device]
82
+ )
83
+ end
60
84
 
61
- def build_for_sdk(sdk)
62
- framework_path = framework_path_of(sdk)
63
- if Dir.exist?(framework_path)
64
- Pod::UI.puts_indented "--> Framework already exists at: #{framework_path}"
65
- return
66
- end
67
-
68
- succeeded, = xcodebuild(
69
- sandbox: sandbox,
70
- target: target.label,
71
- configuration: configuration,
72
- sdk: sdk,
73
- deployment_target: target.platform.deployment_target.to_s,
74
- args: sdk == simulator ? @build_args[:simulator] : @build_args[:device]
75
- )
76
- raise "Build framework failed: #{target.label}" unless succeeded
77
- end
85
+ def create_xcframework(target)
86
+ non_framework_paths = Dir[target_products_dir_of(target, sdks[0]) + "/*"] \
87
+ - [framework_path_of(target, sdks[0])] \
88
+ - dsym_paths_of(target, sdks[0]) \
89
+ - bcsymbolmap_paths_of(target, sdks[0])
90
+ collect_output(target, non_framework_paths)
78
91
 
79
- def create_universal_framework
80
- merge_framework_binary
81
- merge_framework_dsym
82
- merge_swift_headers
83
- merge_swift_modules
84
- end
92
+ output = "#{output_path(target)}/#{target.product_module_name}.xcframework"
93
+ FileUtils.rm_rf(output)
85
94
 
86
- def merge_framework_binary
87
- merge_contents("/#{module_name}", &method(:create_fat_binary))
88
- end
95
+ cmd = ["xcodebuild", "-create-xcframework", "-allow-internal-distribution"]
89
96
 
90
- def merge_framework_dsym
91
- merge_contents(".dSYM/Contents/Resources/DWARF/#{module_name}", &method(:create_fat_binary))
92
- end
97
+ # for each sdk, the order of params must be -framework then -debug-symbols
98
+ # to prevent duplicated file error when copying dSYMs
99
+ sdks.each do |sdk|
100
+ cmd << "-framework" << framework_path_of(target, sdk)
101
+
102
+ unless disable_dsym?
103
+ dsyms = dsym_paths_of(target, sdk)
104
+ cmd += dsyms.map { |dsym| "-debug-symbols #{dsym}" }
105
+ end
106
+
107
+ if bitcode_enabled?
108
+ bcsymbolmaps = bcsymbolmap_paths_of(target, sdk)
109
+ cmd += bcsymbolmaps.map { |bcsymbolmap| "-debug-symbols #{bcsymbolmap}" }
110
+ end
111
+ end
93
112
 
94
- def merge_swift_headers
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)
113
+ cmd << "-output" << output
114
+
115
+ Pod::UI.puts "- Create xcframework: #{target}".magenta
116
+ Pod::UI.puts_indented "$ #{cmd.join(' ')}" unless PodPrebuild.config.silent_build?
117
+
118
+ `#{cmd.join(" ")}`
104
119
  end
105
- end
106
120
 
107
- def merge_swift_modules
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])
121
+ def create_fat_framework(target)
122
+ # When merging contents of `simulator` & `device`, prefer contents of `device` over `simulator`
123
+ # https://github.com/grab/cocoapods-binary-cache/issues/25
124
+ collect_output(target, Dir[target_products_dir_of(target, device) + "/*"])
125
+
126
+ merge_framework_binary(target)
127
+ merge_framework_dsym(target)
128
+ merge_swift_headers(target)
129
+ merge_swift_modules(target)
112
130
  end
113
- end
114
131
 
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_)
132
+ def merge_framework_binary(target)
133
+ merge_contents(target, "/#{target.product_module_name}", &method(:create_fat_binary))
134
+ end
122
135
 
123
- merger.call(simulator: simulator_, device: device_, output: output_)
124
- end
136
+ def merge_framework_dsym(target)
137
+ merge_contents(
138
+ target,
139
+ ".dSYM/Contents/Resources/DWARF/#{target.product_module_name}",
140
+ &method(:create_fat_binary)
141
+ )
142
+ end
125
143
 
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(" ")}`
131
- end
144
+ def merge_swift_headers(target)
145
+ merge_contents(target, "/Headers/#{target.product_module_name}-Swift.h") do |options|
146
+ merged_header = <<~HEREDOC
147
+ #if TARGET_OS_SIMULATOR // merged by cocoapods-binary
148
+ #{File.read(options[:simulator])}
149
+ #else // merged by cocoapods-binary
150
+ #{File.read(options[:device])}
151
+ #endif // merged by cocoapods-binary
152
+ HEREDOC
153
+ File.write(options[:output], merged_header.strip)
154
+ end
155
+ end
132
156
 
133
- def collect_output(paths)
134
- paths = [paths] unless paths.is_a?(Array)
135
- paths.each do |path|
136
- FileUtils.rm_rf(File.join(output_path, File.basename(path)))
137
- FileUtils.cp_r(path, output_path)
157
+ def merge_swift_modules(target)
158
+ merge_contents(target, "/Modules/#{target.product_module_name}.swiftmodule") do |options|
159
+ # Note: swiftmodules of `device` were copied beforehand,
160
+ # here, we only need to copy swiftmodules of `simulator`
161
+ FileUtils.cp_r(options[:simulator] + "/.", options[:output])
162
+ end
138
163
  end
139
- end
140
164
 
141
- def target_products_dir_of(sdk)
142
- "#{build_dir}/#{configuration}-#{sdk}/#{target.name}"
143
- end
165
+ def merge_contents(target, path_suffix, &merger)
166
+ simulator_, device_, output_ = [
167
+ framework_path_of(target, simulator),
168
+ framework_path_of(target, device),
169
+ "#{output_path(target)}/#{target.product_module_name}.framework"
170
+ ].map { |p| p + path_suffix }
171
+ return unless File.exist?(simulator_) && File.exist?(device_)
144
172
 
145
- def framework_path_of(sdk)
146
- "#{target_products_dir_of(sdk)}/#{module_name}.framework"
147
- end
173
+ merger.call(simulator: simulator_, device: device_, output: output_)
174
+ end
148
175
 
149
- def module_name
150
- target.product_module_name
151
- end
176
+ def create_fat_binary(options)
177
+ cmd = ["lipo", " -create"]
178
+ cmd << "-output" << options[:output]
179
+ cmd << options[:simulator] << options[:device]
180
+ `#{cmd.join(" ")}`
181
+ end
152
182
 
153
- def sandbox
154
- @options[:sandbox]
155
- end
183
+ def collect_output(target, paths)
184
+ FileUtils.mkdir_p(output_path(target))
185
+ paths = [paths] unless paths.is_a?(Array)
186
+ paths.each do |path|
187
+ FileUtils.rm_rf(File.join(output_path(target), File.basename(path)))
188
+ FileUtils.cp_r(path, output_path(target))
189
+ end
190
+ end
156
191
 
157
- def build_dir
158
- @options[:build_dir]
159
- end
192
+ def target_products_dir_of(target, sdk)
193
+ "#{build_dir}/#{configuration}-#{sdk}/#{target.name}"
194
+ end
160
195
 
161
- def output_path
162
- @options[:output_path]
163
- end
196
+ def framework_path_of(target, sdk)
197
+ "#{target_products_dir_of(target, sdk)}/#{target.product_module_name}.framework"
198
+ end
164
199
 
165
- def target
166
- @options[:target]
167
- end
200
+ def dsym_paths_of(target, sdk)
201
+ Dir["#{target_products_dir_of(target, sdk)}/*.dSYM"]
202
+ end
168
203
 
169
- def configuration
170
- @options[:configuration]
171
- end
204
+ def bcsymbolmap_paths_of(target, sdk)
205
+ Dir["#{target_products_dir_of(target, sdk)}/*.bcsymbolmap"]
206
+ end
172
207
 
173
- def bitcode_enabled?
174
- @options[:bitcode_enabled]
175
- end
208
+ def sandbox
209
+ @options[:sandbox]
210
+ end
176
211
 
177
- def device_build_enabled?
178
- @options[:device_build_enabled]
179
- end
212
+ def build_dir
213
+ @options[:build_dir]
214
+ end
180
215
 
181
- def device
182
- @options[:device] || "iphoneos"
183
- end
216
+ def output_path(target)
217
+ "#{@options[:output_path]}/#{target.label}"
218
+ end
184
219
 
185
- def simulator
186
- @options[:simulator] || "iphonesimulator"
187
- end
220
+ def scheme
221
+ @options[:scheme]
222
+ end
223
+
224
+ def targets
225
+ @options[:targets]
226
+ end
227
+
228
+ def configuration
229
+ @options[:configuration]
230
+ end
231
+
232
+ def bitcode_enabled?
233
+ @options[:bitcode_enabled]
234
+ end
235
+
236
+ def device_build_enabled?
237
+ @options[:device_build_enabled]
238
+ end
239
+
240
+ def device
241
+ @options[:device] || "iphoneos"
242
+ end
243
+
244
+ def simulator
245
+ @options[:simulator] || "iphonesimulator"
246
+ end
188
247
 
189
- def disable_dsym?
190
- @options[:disable_dsym]
248
+ def disable_dsym?
249
+ @options[:disable_dsym]
250
+ end
191
251
  end
192
252
  end