cocoapods-binary-cache 0.1.8 → 0.1.13

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: 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