cocoapods-binary-cache 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +7 -0
  2. data/lib/cocoapods-binary-cache.rb +4 -0
  3. data/lib/cocoapods-binary-cache/cache/all.rb +9 -0
  4. data/lib/cocoapods-binary-cache/cache/validation_result.rb +69 -0
  5. data/lib/cocoapods-binary-cache/cache/validator.rb +21 -0
  6. data/lib/cocoapods-binary-cache/cache/validator_accumulated.rb +4 -0
  7. data/lib/cocoapods-binary-cache/cache/validator_base.rb +92 -0
  8. data/lib/cocoapods-binary-cache/cache/validator_dependencies_graph.rb +20 -0
  9. data/lib/cocoapods-binary-cache/cache/validator_dev_pods.rb +22 -0
  10. data/lib/cocoapods-binary-cache/cache/validator_exclusion.rb +14 -0
  11. data/lib/cocoapods-binary-cache/cache/validator_non_dev_pods.rb +13 -0
  12. data/lib/cocoapods-binary-cache/cache/validator_with_podfile.rb +9 -0
  13. data/lib/cocoapods-binary-cache/dependencies_graph/dependencies_graph.rb +95 -0
  14. data/lib/cocoapods-binary-cache/dependencies_graph/graph_visualizer.rb +74 -0
  15. data/lib/cocoapods-binary-cache/gem_version.rb +6 -0
  16. data/lib/cocoapods-binary-cache/helper/benchmark_show.rb +11 -0
  17. data/lib/cocoapods-binary-cache/helper/checksum.rb +12 -0
  18. data/lib/cocoapods-binary-cache/helper/json.rb +37 -0
  19. data/lib/cocoapods-binary-cache/helper/lockfile.rb +67 -0
  20. data/lib/cocoapods-binary-cache/helper/path_utils.rb +8 -0
  21. data/lib/cocoapods-binary-cache/helper/podspec.rb +17 -0
  22. data/lib/cocoapods-binary-cache/hooks/post_install.rb +16 -0
  23. data/lib/cocoapods-binary-cache/hooks/pre_install.rb +141 -0
  24. data/lib/cocoapods-binary-cache/main.rb +21 -0
  25. data/lib/cocoapods-binary-cache/pod-binary/LICENSE.txt +22 -0
  26. data/lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/installer.rb +25 -0
  27. data/lib/cocoapods-binary-cache/pod-binary/helper/detected_prebuilt_pods/target_definition.rb +36 -0
  28. data/lib/cocoapods-binary-cache/pod-binary/helper/feature_switches.rb +90 -0
  29. data/lib/cocoapods-binary-cache/pod-binary/helper/names.rb +36 -0
  30. data/lib/cocoapods-binary-cache/pod-binary/helper/passer.rb +25 -0
  31. data/lib/cocoapods-binary-cache/pod-binary/helper/podfile_options.rb +2 -0
  32. data/lib/cocoapods-binary-cache/pod-binary/helper/prebuild_sandbox.rb +71 -0
  33. data/lib/cocoapods-binary-cache/pod-binary/helper/target_checker.rb +45 -0
  34. data/lib/cocoapods-binary-cache/pod-binary/integration.rb +12 -0
  35. data/lib/cocoapods-binary-cache/pod-binary/integration/alter_specs.rb +93 -0
  36. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/embed_framework_script.rb +36 -0
  37. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/resolve_dependencies.rb +23 -0
  38. data/lib/cocoapods-binary-cache/pod-binary/integration/patch/source_installation.rb +28 -0
  39. data/lib/cocoapods-binary-cache/pod-binary/integration/remove_target_files.rb +29 -0
  40. data/lib/cocoapods-binary-cache/pod-binary/integration/source_installer.rb +111 -0
  41. data/lib/cocoapods-binary-cache/pod-binary/integration/validation.rb +20 -0
  42. data/lib/cocoapods-binary-cache/pod-binary/prebuild.rb +224 -0
  43. data/lib/cocoapods-binary-cache/pod-binary/prebuild_dsl.rb +69 -0
  44. data/lib/cocoapods-binary-cache/pod-binary/prebuild_hook.rb +11 -0
  45. data/lib/cocoapods-binary-cache/pod-binary/tool/tool.rb +12 -0
  46. data/lib/cocoapods-binary-cache/pod-rome/LICENSE.txt +22 -0
  47. data/lib/cocoapods-binary-cache/pod-rome/build_framework.rb +247 -0
  48. data/lib/cocoapods-binary-cache/prebuild_cache.rb +49 -0
  49. data/lib/cocoapods-binary-cache/prebuild_output/metadata.rb +47 -0
  50. data/lib/cocoapods-binary-cache/prebuild_output/output.rb +71 -0
  51. data/lib/cocoapods-binary-cache/scheme_editor.rb +35 -0
  52. data/lib/cocoapods-binary-cache/state_store.rb +11 -0
  53. data/lib/cocoapods-binary-cache/ui.rb +9 -0
  54. data/lib/cocoapods_plugin.rb +5 -0
  55. data/lib/command/binary.rb +18 -0
  56. data/lib/command/config.rb +31 -0
  57. data/lib/command/executor/base.rb +20 -0
  58. data/lib/command/executor/fetcher.rb +44 -0
  59. data/lib/command/executor/prebuilder.rb +58 -0
  60. data/lib/command/executor/pusher.rb +19 -0
  61. data/lib/command/executor/visualizer.rb +20 -0
  62. data/lib/command/fetch.rb +23 -0
  63. data/lib/command/helper/zip.rb +20 -0
  64. data/lib/command/prebuild.rb +29 -0
  65. data/lib/command/visualize.rb +30 -0
  66. metadata +193 -0
@@ -0,0 +1,36 @@
1
+ # ABOUT NAMES
2
+ #
3
+ # There are many kinds of name in cocoapods. Two main names are widely used in this plugin.
4
+ # - root_spec.name (spec.root_name, targe.pod_name):
5
+ # aka "pod_name"
6
+ # the name we use in podfile. the concept.
7
+ #
8
+ # - target.name:
9
+ # aka "target_name"
10
+ # the name of the final target in xcode project. the final real thing.
11
+ #
12
+ # One pod may have multiple targets in xcode project, due to one pod can be used in mutiple
13
+ # platform simultaneously. So one `root_spec.name` may have multiple coresponding `target.name`s.
14
+ # Therefore, map a spec to/from targets is a little complecated. It's one to many.
15
+ #
16
+
17
+ # Tool to transform Pod_name to target efficiently
18
+ module Pod
19
+ def self.fast_get_targets_for_pod_name(pod_name, targets, cache)
20
+ pod_name = pod_name.split("/")[0] # Look for parent spec instead of subspecs
21
+ pod_name_to_targets_hash = nil
22
+ if cache.empty?
23
+ pod_name_to_targets_hash = targets.reduce({}) do |sum, target|
24
+ array = sum[target.pod_name] || []
25
+ array << target
26
+ sum[target.pod_name] = array
27
+ sum
28
+ end
29
+ cache << pod_name_to_targets_hash
30
+ else
31
+ pod_name_to_targets_hash = cache.first
32
+ end
33
+
34
+ pod_name_to_targets_hash[pod_name] || []
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ require_relative "../tool/tool"
2
+
3
+ module Pod
4
+ class Prebuild
5
+ # Pass the data between the 2 steps
6
+ #
7
+ # At step 2, the normal pod install, it needs some info of the
8
+ # prebuilt step. So we store it here.
9
+ #
10
+ class Passer
11
+ # indicate the add/remove/update of prebuit pods
12
+ # @return [Analyzer::SpecsState]
13
+ #
14
+ class_attr_accessor :prebuild_pods_changes
15
+
16
+ # Some pod won't be build in prebuild stage even if it have `binary=>true`.
17
+ # The targets of this pods have `oshould_build? == true`.
18
+ # We should skip integration (patch spec) for this pods
19
+ #
20
+ # @return [Array<String>]
21
+ class_attr_accessor :target_names_to_skip_integration_framework
22
+ self.target_names_to_skip_integration_framework = []
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,2 @@
1
+ require_relative "detected_prebuilt_pods/target_definition"
2
+ require_relative "detected_prebuilt_pods/installer"
@@ -0,0 +1,71 @@
1
+ require_relative "names"
2
+
3
+ module Pod
4
+ class PrebuildSandbox < Sandbox
5
+
6
+ # [String] standard_sandbox_path
7
+ def self.from_standard_sanbox_path(path)
8
+ prebuild_sandbox_path = Pathname.new(path).realpath + "_Prebuild"
9
+ self.new(prebuild_sandbox_path)
10
+ end
11
+
12
+ def self.from_standard_sandbox(sandbox)
13
+ self.from_standard_sanbox_path(sandbox.root)
14
+ end
15
+
16
+ def standard_sanbox_path
17
+ self.root.parent
18
+ end
19
+
20
+ def generate_framework_path
21
+ self.root + "GeneratedFrameworks"
22
+ end
23
+
24
+ # @param name [String] pass the target.name (may containing platform suffix)
25
+ # @return [Pathname] the folder containing the framework file.
26
+ def framework_folder_path_for_target_name(name)
27
+ self.generate_framework_path + name
28
+ end
29
+
30
+ def exsited_framework_target_names
31
+ exsited_framework_name_pairs.map { |pair| pair[0] }.uniq
32
+ end
33
+
34
+ def exsited_framework_pod_names
35
+ exsited_framework_name_pairs.map { |pair| pair[1] }.uniq
36
+ end
37
+
38
+ def existed_target_names_for_pod_name(pod_name)
39
+ exsited_framework_name_pairs.select { |pair| pair[1] == pod_name }.map { |pair| pair[0] }
40
+ end
41
+
42
+ def save_pod_name_for_target(target)
43
+ folder = framework_folder_path_for_target_name(target.name)
44
+ return unless folder.exist?
45
+ flag_file_path = folder + "#{target.pod_name}.pod_name"
46
+ File.write(flag_file_path.to_s, "")
47
+ end
48
+
49
+ private
50
+
51
+ def pod_name_for_target_folder(target_folder_path)
52
+ name = Pathname.new(target_folder_path).children.find do |child|
53
+ child.to_s.end_with? ".pod_name"
54
+ end
55
+ name = name.basename(".pod_name").to_s unless name.nil?
56
+ name ||= Pathname.new(target_folder_path).basename.to_s # for compatibility with older version
57
+ end
58
+
59
+ # Array<[target_name, pod_name]>
60
+ def exsited_framework_name_pairs
61
+ return [] unless generate_framework_path.exist?
62
+ generate_framework_path.children().map do |framework_path|
63
+ if framework_path.directory? && (not framework_path.children.empty?)
64
+ [framework_path.basename.to_s, pod_name_for_target_folder(framework_path)]
65
+ else
66
+ nil
67
+ end
68
+ end.reject(&:nil?).uniq
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,45 @@
1
+ module Pod
2
+ class Prebuild
3
+
4
+ # Check the targets, for the current limitation of the plugin
5
+ #
6
+ # @param [Array<PodTarget>] prebuilt_targets
7
+ def self.check_one_pod_should_have_only_one_target(prebuilt_targets)
8
+ targets_have_different_platforms = prebuilt_targets.select { |t| t.pod_name != t.name }
9
+
10
+ if targets_have_different_platforms.count > 0
11
+ names = targets_have_different_platforms.map(&:pod_name)
12
+ raw_names = targets_have_different_platforms.map(&:name)
13
+ message = "Oops, you came across a limitation of cocoapods-binary.
14
+
15
+ The plugin requires that one pod should have ONLY ONE target in the 'Pod.xcodeproj'. There are mainly 2 situations \
16
+ causing this problem:
17
+
18
+ 1. One pod integrates in 2 or more different platforms' targets. e.g.
19
+ ```
20
+ target 'iphoneApp' do
21
+ pod 'A', :binary => true
22
+ end
23
+ target 'watchApp' do
24
+ pod 'A'
25
+ end
26
+ ```
27
+
28
+ 2. Use different subspecs in multiple targets. e.g.
29
+ ```
30
+ target 'iphoneApp' do
31
+ pod 'A/core'
32
+ pod 'A/network'
33
+ end
34
+ target 'iphoneAppTest' do
35
+ pod 'A/core'
36
+ end
37
+ ```
38
+
39
+ Related pods: #{names}, target names: #{raw_names}
40
+ "
41
+ raise Informative, message
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,12 @@
1
+ require_relative "helper/podfile_options"
2
+ require_relative "helper/prebuild_sandbox"
3
+ require_relative "helper/passer"
4
+ require_relative "helper/names"
5
+ require_relative "helper/target_checker"
6
+ require_relative "integration/alter_specs"
7
+ require_relative "integration/remove_target_files"
8
+ require_relative "integration/source_installer"
9
+ require_relative "integration/validation"
10
+ require_relative "integration/patch/embed_framework_script"
11
+ require_relative "integration/patch/resolve_dependencies"
12
+ require_relative "integration/patch/source_installation"
@@ -0,0 +1,93 @@
1
+ module Pod
2
+ class Installer
3
+ def alter_specs_for_prebuilt_pods
4
+ cache = []
5
+ analysis_result.specifications
6
+ .select { |spec| should_integrate_prebuilt_pod?(spec.root.name) }
7
+ .each { |spec| alter_spec(spec, cache) }
8
+ end
9
+
10
+ def alter_spec(spec, cache)
11
+ 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
+ add_vendered_framework(spec, target.platform.name.to_s, framework_file_path)
19
+ end
20
+
21
+ platforms = targets.map { |target| target.platform.name.to_s }.uniq
22
+ empty_source_files(spec, platforms)
23
+ tweak_resources_for_xib(spec, platforms)
24
+ tweak_resources_for_resource_bundles(spec, platforms)
25
+ empty_liscence(spec) # to avoid the warning of missing license
26
+ end
27
+
28
+ def tweak_resources_for_xib(spec, platforms)
29
+ # This is a workaround for prebuilt static framework that has `*.xib` files in the resources
30
+ # (declared by `spec.resources = ...`)
31
+ # ---------------------------------------------------------------
32
+ # In the prebuild stage, a XIB file is compiled as a NIB file in the framework.
33
+ # In the integration stage, this file is added to the script `Pods-<Target>-resources.sh`:
34
+ # - If it's a XIB, it's installed to the target bundle by `ibtool`
35
+ # - If it's a NIB, it's copied directly to the target bundle
36
+ # Since the one embedded in the prebuilt framework is a NIB (already compiled)
37
+ # --> We need to alter the spec so that this file will be copied to the target bundle
38
+ change_xib_to_nib = ->(path) { path.sub(".xib", ".nib") }
39
+ update_resources = lambda do |resources|
40
+ if resources.is_a?(String)
41
+ change_xib_to_nib.call(resources)
42
+ elsif resources.is_a?(Array)
43
+ resources.map { |item| change_xib_to_nib.call(item) }
44
+ end
45
+ end
46
+ spec.attributes_hash["resources"] = update_resources.call(spec.attributes_hash["resources"])
47
+ platforms.each do |platform|
48
+ next if spec.attributes_hash[platform].nil?
49
+
50
+ platform_resources = spec.attributes_hash[platform]["resources"]
51
+ spec.attributes_hash[platform]["resources"] = update_resources.call(platform_resources)
52
+ end
53
+ end
54
+
55
+ def tweak_resources_for_resource_bundles(spec, platforms)
56
+ add_resource_bundles_to_resources = lambda do |attributes|
57
+ return if attributes.nil?
58
+
59
+ resource_bundles = attributes["resource_bundles"] || {}
60
+ resource_bundle_names = resource_bundles.keys
61
+ attributes["resource_bundles"] = nil
62
+ attributes["resources"] ||= []
63
+ attributes["resources"] = [attributes["resources"]] if attributes["resources"].is_a?(String)
64
+ attributes["resources"] += resource_bundle_names.map { |n| n + ".bundle" }
65
+ end
66
+
67
+ add_resource_bundles_to_resources.call(spec.attributes_hash)
68
+ platforms.each do |platform|
69
+ add_resource_bundles_to_resources.call(spec.attributes_hash[platform])
70
+ end
71
+ end
72
+
73
+ def add_vendered_framework(spec, platform, added_framework_file_path)
74
+ spec.attributes_hash[platform] = {} if spec.attributes_hash[platform].nil?
75
+ vendored_frameworks = spec.attributes_hash[platform]["vendored_frameworks"] || []
76
+ vendored_frameworks = [vendored_frameworks] if vendored_frameworks.is_a?(String)
77
+ vendored_frameworks += [added_framework_file_path]
78
+ spec.attributes_hash[platform]["vendored_frameworks"] = vendored_frameworks
79
+ end
80
+
81
+ def empty_source_files(spec, platforms)
82
+ spec.attributes_hash["source_files"] = []
83
+ platforms.each do |platform|
84
+ spec.attributes_hash[platform]["source_files"] = [] unless spec.attributes_hash[platform].nil?
85
+ end
86
+ end
87
+
88
+ def empty_liscence(spec)
89
+ spec.attributes_hash["license"] = {}
90
+ spec.root.attributes_hash["license"] = {}
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,36 @@
1
+ # A fix in embeded frameworks script.
2
+ #
3
+ # The framework file in pod target folder is a symblink. The EmbedFrameworksScript use `readlink`
4
+ # to read the read path. As the symlink is a relative symlink, readlink cannot handle it well. So
5
+ # we override the `readlink` to a fixed version.
6
+ #
7
+ module Pod
8
+ module Generator
9
+ class EmbedFrameworksScript
10
+ old_method = instance_method(:script)
11
+ define_method(:script) do
12
+ script = old_method.bind(self).()
13
+ patch = <<-SH.strip_heredoc
14
+ #!/bin/sh
15
+ # ---- this is added by cocoapods-binary ---
16
+ # Readlink cannot handle relative symlink well, so we override it to a new one
17
+ # If the path isn't an absolute path, we add a realtive prefix.
18
+ old_read_link=`which readlink`
19
+ readlink () {
20
+ path=`$old_read_link $1`;
21
+ if [ $(echo "$path" | cut -c 1-1) = '/' ]; then
22
+ echo $path;
23
+ else
24
+ echo "`dirname $1`/$path";
25
+ fi
26
+ }
27
+ # ---
28
+ SH
29
+
30
+ # patch the rsync for copy dSYM symlink
31
+ script = script.gsub "rsync --delete", "rsync --copy-links --delete"
32
+ patch + script
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,23 @@
1
+ # Let cocoapods use the prebuild framework files in install process.
2
+ #
3
+ # the code only effect the second pod install process.
4
+ #
5
+ module Pod
6
+ class Installer
7
+ # Modify specification to use only the prebuild framework after analyzing
8
+ original_resolve_dependencies = instance_method(:resolve_dependencies)
9
+ define_method(:resolve_dependencies) do
10
+ # Remove the old target files. Otherwise, it will not notice file changes.
11
+ # This call is to make sure subsequent pod installations function properly
12
+ remove_target_files_if_needed
13
+ original_resolve_dependencies.bind(self).call
14
+
15
+ # check the pods
16
+ # Although we have did it in prebuild stage, it's not sufficient.
17
+ # Same pod may appear in another target in form of source code.
18
+ # Prebuild.check_one_pod_should_have_only_one_target(prebuilt_pod_targets)
19
+ validate_every_pod_only_have_one_form
20
+ alter_specs_for_prebuilt_pods
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,28 @@
1
+ module Pod
2
+ class Installer
3
+ # Override the download step to skip download and prepare file in target folder
4
+ define_method(:install_source_of_pod) do |pod_name|
5
+ pod_installer = create_pod_installer(pod_name)
6
+ # Injected code
7
+ # ------------------------------------------
8
+ if should_integrate_prebuilt_pod?(pod_name)
9
+ pod_installer.install_for_prebuild!(sandbox)
10
+ else
11
+ pod_installer.install!
12
+ end
13
+ # ------------------------------------------
14
+ @installed_specs.concat(pod_installer.specs_by_platform.values.flatten.uniq)
15
+ end
16
+
17
+ def should_integrate_prebuilt_pod?(name)
18
+ if Pod::Podfile::DSL.prebuild_job?
19
+ # In a prebuild job, at the integration stage, all prebuilt frameworks should be
20
+ # ready for integration regardless of whether there was any cache miss or not.
21
+ # Those that are missed were prebuilt in the prebuild stage.
22
+ PodPrebuild::StateStore.cache_validation.include?(name)
23
+ else
24
+ PodPrebuild::StateStore.cache_validation.hit?(name)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,29 @@
1
+ module Pod
2
+ class Installer
3
+ # Remove the old target files if prebuild frameworks changed
4
+ def remove_target_files_if_needed
5
+ changes = Pod::Prebuild::Passer.prebuild_pods_changes
6
+ updated_names = []
7
+ if changes.nil?
8
+ updated_names = PrebuildSandbox.from_standard_sandbox(sandbox).exsited_framework_pod_names
9
+ else
10
+ added = changes.added
11
+ changed = changes.changed
12
+ deleted = changes.deleted
13
+ updated_names = added + changed + deleted
14
+ end
15
+
16
+ updated_names.each do |name|
17
+ root_name = Specification.root_name(name)
18
+ next if !Pod::Podfile::DSL.dev_pods_enabled && sandbox.local?(root_name)
19
+
20
+ UI.puts "Delete cached files: #{root_name}"
21
+ target_path = sandbox.pod_dir(root_name)
22
+ target_path.rmtree if target_path.exist?
23
+
24
+ support_path = sandbox.target_support_files_dir(root_name)
25
+ support_path.rmtree if support_path.exist?
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,111 @@
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
+ module Pod
11
+ class Installer
12
+ class PodSourceInstaller
13
+ def install_for_prebuild!(standard_sanbox)
14
+ return if !Podfile::DSL.dev_pods_enabled && standard_sanbox.local?(name)
15
+
16
+ # make a symlink to target folder
17
+ prebuild_sandbox = Pod::PrebuildSandbox.from_standard_sandbox(standard_sanbox)
18
+ # if spec used in multiple platforms, it may return multiple paths
19
+ target_names = prebuild_sandbox.existed_target_names_for_pod_name(self.name)
20
+
21
+ def walk(path, &action)
22
+ return unless path.exist?
23
+ path.children.each do |child|
24
+ result = action.call(child, &action)
25
+ if child.directory?
26
+ walk(child, &action) if result
27
+ end
28
+ end
29
+ end
30
+
31
+ def make_link(source, target)
32
+ source = Pathname.new(source)
33
+ target = Pathname.new(target)
34
+ target.parent.mkpath unless target.parent.exist?
35
+ relative_source = source.relative_path_from(target.parent)
36
+ FileUtils.ln_sf(relative_source, target)
37
+ end
38
+
39
+ def mirror_with_symlink(source, basefolder, target_folder)
40
+ target = target_folder + source.relative_path_from(basefolder)
41
+ make_link(source, target)
42
+ end
43
+
44
+ target_names.each do |name|
45
+
46
+ # symbol link copy all substructure
47
+ real_file_folder = prebuild_sandbox.framework_folder_path_for_target_name(name)
48
+
49
+ # If have only one platform, just place int the root folder of this pod.
50
+ # If have multiple paths, we use a sperated folder to store different
51
+ # platform frameworks. e.g. AFNetworking/AFNetworking-iOS/AFNetworking.framework
52
+
53
+ target_folder = standard_sanbox.pod_dir(self.name)
54
+ if target_names.count > 1
55
+ target_folder += real_file_folder.basename
56
+ end
57
+
58
+ if !standard_sanbox.local?(name)
59
+ target_folder.rmtree if target_folder.exist?
60
+ target_folder.mkpath
61
+ else
62
+ system "find #{target_folder} -type l -delete" # Only clean up symlink, keep source code for local pod
63
+ end
64
+
65
+ walk(real_file_folder) do |child|
66
+ source = child
67
+ # only make symlink to file and `.framework` folder
68
+ if child.directory? and [".framework", ".dSYM"].include? child.extname
69
+ if child.extname == ".framework"
70
+ mirror_with_symlink(source, real_file_folder, target_folder)
71
+ else
72
+ # Ignore dsym here to avoid cocoapods from adding install_dsym to buildphase-script
73
+ # That can cause duplicated output files error in Xcode 11 (warning in Xcode 10)
74
+ # We need more setup to support local debuging with prebuilt dSYM
75
+ end
76
+ next false # return false means don't go deeper
77
+ elsif child.file?
78
+ mirror_with_symlink(source, real_file_folder, target_folder)
79
+ next true
80
+ else
81
+ next true
82
+ end
83
+ end
84
+
85
+ # symbol link copy resource for static framework
86
+ metadata = PodPrebuild::Metadata.in_dir(real_file_folder)
87
+ next unless metadata.static_framework?
88
+
89
+ metadata.resources.each do |path|
90
+ target_file_path = path.sub("${PODS_ROOT}", sandbox.root.to_path)
91
+ .sub("${PODS_CONFIGURATION_BUILD_DIR}", sandbox.root.to_path)
92
+ real_file_path = real_file_folder + metadata.framework_name + File.basename(path)
93
+ case File.extname(path)
94
+ when ".xib"
95
+ # https://github.com/grab/cocoapods-binary-cache/issues/7
96
+ # When ".xib" files are compiled in a framework, it becomes ".nib" files
97
+ # --> We need to correct the path extension
98
+ real_file_path = real_file_path.sub_ext(".nib")
99
+ target_file_path = target_file_path.sub(".xib", ".nib")
100
+ when ".bundle"
101
+ next if metadata.resource_bundles.include?(File.basename(path))
102
+
103
+ real_file_path = real_file_folder + File.basename(path) unless real_file_path.exist?
104
+ end
105
+ make_link(real_file_path, target_file_path)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end