cocoapods-spm2 0.1.10

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 (53) hide show
  1. checksums.yaml +7 -0
  2. data/lib/cocoapods-spm/command/clean.rb +31 -0
  3. data/lib/cocoapods-spm/command/macro/deprecated.rb +35 -0
  4. data/lib/cocoapods-spm/command/macro/fetch.rb +33 -0
  5. data/lib/cocoapods-spm/command/macro/prebuild.rb +37 -0
  6. data/lib/cocoapods-spm/command/macro.rb +14 -0
  7. data/lib/cocoapods-spm/command/spm.rb +17 -0
  8. data/lib/cocoapods-spm/compatibility/all.rb +1 -0
  9. data/lib/cocoapods-spm/compatibility/rb26.rb +14 -0
  10. data/lib/cocoapods-spm/config/pod.rb +11 -0
  11. data/lib/cocoapods-spm/config/project.rb +32 -0
  12. data/lib/cocoapods-spm/config/spm.rb +111 -0
  13. data/lib/cocoapods-spm/config.rb +15 -0
  14. data/lib/cocoapods-spm/def/installer.rb +7 -0
  15. data/lib/cocoapods-spm/def/podfile.rb +80 -0
  16. data/lib/cocoapods-spm/def/spec.rb +26 -0
  17. data/lib/cocoapods-spm/def/spm_dependency.rb +24 -0
  18. data/lib/cocoapods-spm/def/spm_package.rb +106 -0
  19. data/lib/cocoapods-spm/def/target_definition.rb +15 -0
  20. data/lib/cocoapods-spm/def/xcodeproj.rb +38 -0
  21. data/lib/cocoapods-spm/executables.rb +9 -0
  22. data/lib/cocoapods-spm/helpers/io.rb +14 -0
  23. data/lib/cocoapods-spm/helpers/patch.rb +14 -0
  24. data/lib/cocoapods-spm/hooks/base.rb +99 -0
  25. data/lib/cocoapods-spm/hooks/helpers/update_script.rb +61 -0
  26. data/lib/cocoapods-spm/hooks/post_integrate/1.add_spm_pkgs.rb +31 -0
  27. data/lib/cocoapods-spm/hooks/post_integrate/5.update_settings.rb +88 -0
  28. data/lib/cocoapods-spm/hooks/post_integrate/6.update_embed_frameworks_script.rb +32 -0
  29. data/lib/cocoapods-spm/hooks/post_integrate/7.update_copy_resources_script.rb +33 -0
  30. data/lib/cocoapods-spm/macro/config.rb +27 -0
  31. data/lib/cocoapods-spm/macro/fetcher.rb +86 -0
  32. data/lib/cocoapods-spm/macro/metadata.rb +17 -0
  33. data/lib/cocoapods-spm/macro/pod_installer.rb +35 -0
  34. data/lib/cocoapods-spm/macro/prebuilder.rb +50 -0
  35. data/lib/cocoapods-spm/main.rb +13 -0
  36. data/lib/cocoapods-spm/patch/aggregate_target.rb +25 -0
  37. data/lib/cocoapods-spm/patch/installer.rb +75 -0
  38. data/lib/cocoapods-spm/resolver/recursive_target_resolver.rb +39 -0
  39. data/lib/cocoapods-spm/resolver/result.rb +73 -0
  40. data/lib/cocoapods-spm/resolver/target_dep_resolver.rb +64 -0
  41. data/lib/cocoapods-spm/resolver/umbrella_package.rb +72 -0
  42. data/lib/cocoapods-spm/resolver/validator.rb +32 -0
  43. data/lib/cocoapods-spm/resolver.rb +43 -0
  44. data/lib/cocoapods-spm/swift/package/base.rb +54 -0
  45. data/lib/cocoapods-spm/swift/package/dependency.rb +27 -0
  46. data/lib/cocoapods-spm/swift/package/description.rb +76 -0
  47. data/lib/cocoapods-spm/swift/package/product.rb +17 -0
  48. data/lib/cocoapods-spm/swift/package/project_packages.rb +59 -0
  49. data/lib/cocoapods-spm/swift/package/resources.rb +17 -0
  50. data/lib/cocoapods-spm/swift/package/target.rb +171 -0
  51. data/lib/cocoapods-spm.rb +1 -0
  52. data/lib/cocoapods_plugin.rb +1 -0
  53. metadata +108 -0
@@ -0,0 +1,75 @@
1
+ require "cocoapods-spm/helpers/patch"
2
+ require "cocoapods-spm/resolver"
3
+ require "cocoapods-spm/macro/pod_installer"
4
+ require "cocoapods-spm/hooks/base"
5
+
6
+ module Pod
7
+ class Installer
8
+ include Mixin::PatchingBehavior
9
+ include SPM::Config::Mixin
10
+
11
+ patch_method :resolve_dependencies do
12
+ origin_resolve_dependencies
13
+ resolve_spm_dependencies
14
+ end
15
+
16
+ patch_method :create_pod_installer do |pod_name|
17
+ if macro_pods.include?(pod_name)
18
+ macro_pod_installer = MacroPodInstaller.new(
19
+ sandbox,
20
+ podfile,
21
+ specs_for_pod(pod_name),
22
+ can_cache: installation_options.clean?
23
+ )
24
+ pod_installers << macro_pod_installer
25
+ macro_pod_installer
26
+ else
27
+ origin_create_pod_installer(pod_name)
28
+ end
29
+ end
30
+
31
+ patch_method :integrate do
32
+ run_spm_pre_integrate_hooks
33
+ origin_integrate
34
+ run_spm_post_integrate_hooks
35
+ end
36
+
37
+ patch_method :sandbox_state do
38
+ state = origin_sandbox_state
39
+ # NOTE: For macro pods, we force-trigger their source installers even in incremental installations.
40
+ # This is done by altering the `sandbox_state` & marking them as `added`
41
+ spm_config.all_macros.each do |name|
42
+ %i[unchanged changed deleted].each { |key| state.send(key).delete(name) }
43
+ state.added << (name)
44
+ end
45
+ state
46
+ end
47
+
48
+ private
49
+
50
+ def hook_options
51
+ {
52
+ :spm_resolver => @spm_resolver,
53
+ :analysis_result => @analysis_result,
54
+ }
55
+ end
56
+
57
+ def run_spm_pre_integrate_hooks
58
+ context = PreIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
59
+ SPM::Hook.run_hooks(:pre_integrate, context, hook_options)
60
+ end
61
+
62
+ def run_spm_post_integrate_hooks
63
+ context = PostIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
64
+ SPM::Hook.run_hooks(:post_integrate, context, hook_options)
65
+ end
66
+
67
+ def resolve_spm_dependencies
68
+ UI.section "Resolving SPM dependencies" do
69
+ @spm_resolver ||= SPM::Resolver.new(podfile, aggregate_targets)
70
+ @spm_resolver.resolve
71
+ podfile.spm_resolver = @spm_resolver
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,39 @@
1
+ module Pod
2
+ module SPM
3
+ class Resolver
4
+ class RecursiveTargetResolver
5
+ require "cocoapods-spm/swift/package/project_packages"
6
+
7
+ include Config::Mixin
8
+
9
+ def initialize(podfile, result)
10
+ @podfile = podfile
11
+ @result = result
12
+ end
13
+
14
+ def resolve
15
+ resolve_recursive_targets
16
+ end
17
+
18
+ private
19
+
20
+ def project_pkgs
21
+ @result.project_pkgs ||= Swift::ProjectPackages.new(
22
+ src_dir: spm_config.pkg_checkouts_dir,
23
+ write_json_to_dir: spm_config.pkg_metadata_dir
24
+ )
25
+ end
26
+
27
+ def resolve_recursive_targets
28
+ @result.spm_dependencies_by_target.values.flatten.uniq(&:product).each do |dep|
29
+ next if dep.pkg.try(:use_default_xcode_linking?)
30
+
31
+ @podfile.platforms.each do |platform|
32
+ project_pkgs.resolve_recursive_targets_of(dep.pkg.name, dep.product, platform: platform)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,73 @@
1
+ module Pod
2
+ module SPM
3
+ class Resolver
4
+ class Result
5
+ include Config::Mixin
6
+
7
+ ATTRS = {
8
+ :spm_pkgs => [],
9
+ :spm_dependencies_by_target => {},
10
+ :project_pkgs => nil,
11
+ }.freeze
12
+
13
+ class WritableResult < Result
14
+ ATTRS.each_key { |x| attr_accessor x }
15
+
16
+ def to_read_only
17
+ Result.new(ATTRS.to_h { |x| [x, instance_variable_get("@#{x}")] })
18
+ end
19
+ end
20
+
21
+ ATTRS.each_key { |x| attr_reader x }
22
+
23
+ def initialize(options = {})
24
+ ATTRS.each do |k, v|
25
+ instance_variable_set("@#{k}", options[k] || v)
26
+ end
27
+ end
28
+
29
+ def spm_pkgs_for(target)
30
+ spm_dependencies_for(target).map(&:pkg).uniq(&:name)
31
+ end
32
+
33
+ def spm_dependencies_for(target)
34
+ filtered_dependencies = @spm_dependencies_by_target[spec_name_of(target)]&.reject do |dep|
35
+ dep.pkg&.should_exclude_from_target?(target.name)
36
+ end
37
+ filtered_dependencies.to_a
38
+ end
39
+
40
+ def spm_targets_for(target, exclude_default_xcode_linking: true)
41
+ targets = spm_dependencies_for(target).flat_map do |d|
42
+ project_pkgs.resolve_recursive_targets_of(d.pkg.name, d.product, platform: target.platform.name)
43
+ end.uniq(&:name)
44
+ return targets.reject(&:use_default_xcode_linking?) if exclude_default_xcode_linking
45
+
46
+ targets
47
+ end
48
+
49
+ def linker_flags_for(target)
50
+ (
51
+ spm_targets_for(target).flat_map(&:linker_flags) +
52
+ spm_pkgs_for(target).flat_map(&:linker_flags)
53
+ ).uniq
54
+ end
55
+
56
+ private
57
+
58
+ def spec_name_of(target)
59
+ # In case of multi-platforms, the target name might contains the platform (ex. Logger-iOS, Logger-macOS)
60
+ # We need to strip the platform suffix out
61
+ return target.name if @spm_dependencies_by_target.key?(target.name)
62
+ return target.root_spec.name if target.is_a?(Pod::PodTarget)
63
+ return target.name if target.is_a?(Pod::AggregateTarget)
64
+
65
+ cmps = target.name.split("-")
66
+ return cmps[...-1].join("-") if ["iOS", "macOS", "watchOS", "tvOS"].include?(cmps[-1])
67
+
68
+ target.name
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,64 @@
1
+ module Pod
2
+ module SPM
3
+ class Resolver
4
+ class TargetDependencyResolver
5
+ def initialize(podfile, aggregate_targets, result)
6
+ @podfile = podfile
7
+ @aggregate_targets = aggregate_targets
8
+ @result = result
9
+ end
10
+
11
+ def resolve
12
+ resolve_spm_pkgs
13
+ resolve_spm_dependencies_by_target
14
+ end
15
+
16
+ private
17
+
18
+ def resolve_spm_pkgs
19
+ @result.spm_pkgs = @podfile.target_definition_list.flat_map(&:spm_pkgs).uniq(&:name)
20
+ end
21
+
22
+ def resolve_spm_dependencies_by_target
23
+ resolve_dependencies_for_targets
24
+ resolve_dependencies_for_aggregate_targets
25
+ @result.spm_dependencies_by_target.values.flatten.each { |d| d.pkg = spm_pkg_for(d.name) }
26
+ end
27
+
28
+ def resolve_dependencies_for_targets
29
+ specs = @aggregate_targets.flat_map(&:specs).uniq
30
+ specs.each do |spec|
31
+ @result.spm_dependencies_by_target[spec.name] = spec.spm_dependencies
32
+ end
33
+ end
34
+
35
+ def resolve_dependencies_for_aggregate_targets
36
+ @aggregate_targets.each do |target|
37
+ spm_dependencies = target.specs.flat_map(&:spm_dependencies)
38
+ @result.spm_dependencies_by_target[target.to_s] = merge_spm_dependencies(spm_dependencies)
39
+ end
40
+
41
+ @podfile.spm_pkgs_by_aggregate_target.each do |target, pkgs|
42
+ existing = @result.spm_dependencies_by_target[target].to_a
43
+ spm_dependencies = pkgs.flat_map(&:to_dependencies)
44
+ @result.spm_dependencies_by_target[target] = merge_spm_dependencies(existing + spm_dependencies)
45
+ end
46
+ end
47
+
48
+ def merge_spm_dependencies(deps)
49
+ deps_by_name = Hash.new { |h, k| h[k] = [] }
50
+ deps.each { |d| deps_by_name[d.name] << d }
51
+ deps_by_name.each do |name, ds|
52
+ deps_by_name[name] = ds.uniq { |d| [d.name, d.product] }
53
+ end
54
+ deps_by_name.values.flatten
55
+ end
56
+
57
+ def spm_pkg_for(name)
58
+ @_spm_pkgs_by_name ||= @result.spm_pkgs.to_h { |pkg| [pkg.name, pkg] }
59
+ @_spm_pkgs_by_name[name]
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,72 @@
1
+ module Pod
2
+ module SPM
3
+ class UmbrellaPackage
4
+ include Config::Mixin
5
+
6
+ def initialize(podfile)
7
+ @podfile = podfile
8
+ @spm_pkgs = @podfile.target_definition_list.flat_map(&:spm_pkgs).uniq(&:name)
9
+ end
10
+
11
+ def prepare
12
+ generate_pkg_swift
13
+ swift_pkg_resolve
14
+ create_symlinks_to_local_pkgs
15
+ self
16
+ end
17
+
18
+ private
19
+
20
+ def generate_pkg_swift
21
+ swift_tools_version = "5.7"
22
+ dependencies = @spm_pkgs.map do |pkg|
23
+ # https://developer.apple.com/documentation/packagedescription/package/dependency
24
+ next ".package(path: \"#{pkg.absolute_path}\")" if pkg.local?
25
+
26
+ tail = case pkg.requirement[:kind]
27
+ when "exactVersion"
28
+ "exact: \"#{pkg.requirement[:version]}\""
29
+ when "branch"
30
+ "branch: \"#{pkg.requirement[:branch]}\""
31
+ when "revision"
32
+ "revision: \"#{pkg.requirement[:revision]}\""
33
+ else
34
+ # TODO: Handle this
35
+ "todo: \"handle this\""
36
+ end
37
+ ".package(url: \"#{pkg.url}\", #{tail})"
38
+ end
39
+
40
+ package_content = <<~HEREDOC
41
+ // swift-tools-version:#{swift_tools_version}
42
+ import PackageDescription
43
+
44
+ let package = Package(
45
+ name: "_umbrella_",
46
+ dependencies: [
47
+ #{dependencies.join(",\n ")}
48
+ ]
49
+ )
50
+ HEREDOC
51
+ (spm_config.pkg_umbrella_dir / "Package.swift").write(package_content)
52
+ end
53
+
54
+ def swift_pkg_resolve
55
+ Dir.chdir(spm_config.pkg_umbrella_dir) { `swift package resolve` }
56
+ end
57
+
58
+ def create_symlinks_to_local_pkgs
59
+ local_spm_pkgs = @spm_pkgs.select(&:local?)
60
+ symlinks = local_spm_pkgs.to_h { |p| [p.slug, p.absolute_path] }
61
+ local_spm_pkgs.each do |pkg|
62
+ pkg_desc = Swift::PackageDescription.from_dir(pkg.absolute_path)
63
+ pkg_desc.dependencies.select(&:local?).each { |d| symlinks[d.slug] = d.path }
64
+ end
65
+
66
+ symlinks.each do |slug, src_dir|
67
+ IOUtils.symlink(src_dir, spm_config.pkg_checkouts_dir / slug)
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,32 @@
1
+ module Pod
2
+ module SPM
3
+ class Validator
4
+ def initialize(aggregate_targets, result)
5
+ @aggregate_targets = aggregate_targets
6
+ @spm_pkgs = result.spm_pkgs
7
+ @spm_dependencies_by_target = result.spm_dependencies_by_target
8
+ end
9
+
10
+ def validate!
11
+ verify_no_missing_pkgs
12
+ end
13
+
14
+ private
15
+
16
+ def dependents_of_pkg(name)
17
+ @specs ||= @aggregate_targets.flat_map(&:specs).uniq
18
+ @specs.select { |s| s.spm_dependencies.any? { |d| d.name == name } }.map(&:name)
19
+ end
20
+
21
+ def verify_no_missing_pkgs
22
+ missing_pkgs = @spm_dependencies_by_target.values.flatten.select { |d| d.pkg.nil? }.map(&:name).uniq
23
+ return if missing_pkgs.empty?
24
+
25
+ messages = ["The following packages were not declared in Podfile:"]
26
+ messages += missing_pkgs.map { |pkg| " • #{pkg}: used by #{dependents_of_pkg(pkg).join(', ')}" }
27
+ messages << "Use the `spm_pkg` method to declare those packages in Podfile."
28
+ raise Informative, messages.join("\n")
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,43 @@
1
+ require "cocoapods-spm/resolver/validator"
2
+ require "cocoapods-spm/resolver/umbrella_package"
3
+
4
+ module Pod
5
+ module SPM
6
+ class Resolver
7
+ require "cocoapods-spm/resolver/result"
8
+ require "cocoapods-spm/resolver/target_dep_resolver"
9
+ require "cocoapods-spm/resolver/recursive_target_resolver"
10
+
11
+ def initialize(podfile, aggregate_targets)
12
+ @_result = Result::WritableResult.new
13
+ @podfile = podfile
14
+ @aggregate_targets = aggregate_targets
15
+ @umbrella_pkg = nil
16
+ @resolvers = [
17
+ TargetDependencyResolver.new(podfile, aggregate_targets, @_result),
18
+ RecursiveTargetResolver.new(podfile, @_result),
19
+ ]
20
+ end
21
+
22
+ def resolve
23
+ generate_umbrella_pkg
24
+ @resolvers.each(&:resolve)
25
+ validate!
26
+ end
27
+
28
+ def result
29
+ @result ||= @_result.to_read_only
30
+ end
31
+
32
+ private
33
+
34
+ def generate_umbrella_pkg
35
+ @umbrella_pkg = Pod::SPM::UmbrellaPackage.new(@podfile).prepare
36
+ end
37
+
38
+ def validate!
39
+ Validator.new(@aggregate_targets, result).validate!
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,54 @@
1
+ require "json"
2
+
3
+ module Pod
4
+ module Swift
5
+ class PackageDescriptionBaseObject
6
+ attr_reader :raw, :parent
7
+
8
+ def initialize(raw, parent: nil)
9
+ @raw = raw
10
+ @parent = parent
11
+ end
12
+
13
+ def root
14
+ @root ||= begin
15
+ node = self
16
+ node = node.parent until node.parent.nil?
17
+ node
18
+ end
19
+ end
20
+
21
+ def pkg_name
22
+ root.name
23
+ end
24
+
25
+ def self.from_s(str)
26
+ new(JSON.parse(str))
27
+ end
28
+
29
+ def self.from_file(path)
30
+ from_s(File.read(path))
31
+ end
32
+
33
+ def inspect
34
+ "#<#{self.class} #{name}>"
35
+ end
36
+
37
+ alias to_s inspect
38
+
39
+ def [](key)
40
+ raw[key]
41
+ end
42
+
43
+ def name
44
+ raw["name"]
45
+ end
46
+
47
+ def dup_with_attrs(options = {})
48
+ copy = dup
49
+ options.each { |key, value| copy.instance_variable_set("@#{key}", value) }
50
+ copy
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,27 @@
1
+ require "cocoapods-spm/swift/package/base"
2
+
3
+ module Pod
4
+ module Swift
5
+ class PackageDescription
6
+ class Dependency < PackageDescriptionBaseObject
7
+ def local?
8
+ raw.key?("fileSystem")
9
+ end
10
+
11
+ def slug
12
+ hash["identity"]
13
+ end
14
+
15
+ def path
16
+ hash["path"]
17
+ end
18
+
19
+ private
20
+
21
+ def hash
22
+ raw.values.flatten[0] || {}
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,76 @@
1
+ require "cocoapods-spm/swift/package/base"
2
+
3
+ module Pod
4
+ module Swift
5
+ class PackageDescription < PackageDescriptionBaseObject
6
+ include SPM::Config::Mixin
7
+ autoload :Dependency, "cocoapods-spm/swift/package/dependency"
8
+ autoload :Target, "cocoapods-spm/swift/package/target"
9
+ autoload :Product, "cocoapods-spm/swift/package/product"
10
+
11
+ def self.from_dir(dir)
12
+ raw = `swift package dump-package --package-path #{dir.shellescape}`
13
+ from_s(raw)
14
+ end
15
+
16
+ def src_dir
17
+ @src_dir ||= begin
18
+ path = raw.fetch("packageKind", {}).fetch("root", [])[0]
19
+ Pathname.new(path) unless path.nil?
20
+ end
21
+ end
22
+
23
+ def checkouts_dir
24
+ src_dir.parent
25
+ end
26
+
27
+ def artifacts_dir
28
+ spm_config.pkg_artifacts_dir / slug
29
+ end
30
+
31
+ def slug
32
+ src_dir.nil? ? name : src_dir.basename.to_s
33
+ end
34
+
35
+ def dependencies
36
+ @dependencies ||= convert_field("dependencies", Dependency)
37
+ end
38
+
39
+ def targets
40
+ @targets ||= convert_field("targets", Target)
41
+ end
42
+
43
+ def products
44
+ @products ||= convert_field("products", Product)
45
+ end
46
+
47
+ def targets_of_product(name)
48
+ matched_products = products.select { |p| p.name == name }
49
+ dynamic = matched_products.any?(&:dynamic?)
50
+ matched_products
51
+ .flat_map do |p|
52
+ targets.select { |t| p.target_names.include?(t.name) }.map do |t|
53
+ t.dup_with_attrs(dynamic: dynamic, product_name: name)
54
+ end
55
+ end
56
+ end
57
+
58
+ def macro_impl_name
59
+ targets.find(&:macro?)&.name
60
+ end
61
+
62
+ def use_default_xcode_linking?
63
+ return @use_default_xcode_linking unless @use_default_xcode_linking.nil?
64
+
65
+ pkg = pod_config.podfile.spm_pkgs.find { |t| t.name == name }
66
+ @use_default_xcode_linking = pkg&.use_default_xcode_linking?
67
+ end
68
+
69
+ private
70
+
71
+ def convert_field(name, type)
72
+ raw.fetch(name, []).flat_map { |h| type.new(h, parent: self) }
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,17 @@
1
+ require "cocoapods-spm/swift/package/base"
2
+
3
+ module Pod
4
+ module Swift
5
+ class PackageDescription
6
+ class Product < PackageDescriptionBaseObject
7
+ def dynamic?
8
+ @dynamic ||= raw.fetch("type", {}).fetch("library", []).include?("dynamic")
9
+ end
10
+
11
+ def target_names
12
+ raw["targets"]
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,59 @@
1
+ require "cocoapods-spm/swift/package/description"
2
+
3
+ module Pod
4
+ module Swift
5
+ class ProjectPackages
6
+ def initialize(options = {})
7
+ @src_dir = options[:src_dir]
8
+ raise Informative, "src_dir must not be nil" if @src_dir.nil?
9
+
10
+ @json_dir = options[:write_json_to_dir]
11
+ @pkg_desc_cache = {}
12
+ load
13
+ end
14
+
15
+ def resolve_recursive_targets_of(pkg_name, product_name, platform: nil)
16
+ @recursive_targets_cache ||= {}
17
+ @recursive_targets_cache[platform] ||= {}
18
+ return @recursive_targets_cache[platform][product_name] if @recursive_targets_cache[platform].key(product_name)
19
+
20
+ res = []
21
+ to_visit = pkg_desc_of(pkg_name).targets_of_product(product_name)
22
+ until to_visit.empty?
23
+ target = to_visit.pop
24
+ res << target
25
+ # Exclude macros as they wont be linked to the project's binary
26
+ # https://github.com/trinhngocthuyen/cocoapods-spm/issues/107
27
+ to_visit += target.resolve_dependencies(@pkg_desc_cache, platform: platform).reject(&:macro?)
28
+ end
29
+ @recursive_targets_cache[platform][product_name] = res.uniq(&:name)
30
+ end
31
+
32
+ def pkg_desc_of(name)
33
+ return @pkg_desc_cache[name] if @pkg_desc_cache.key?(name)
34
+
35
+ raise Informative, "Package description of `#{name}` does not exist!"
36
+ end
37
+
38
+ private
39
+
40
+ def load
41
+ @src_dir.glob("*").each do |dir|
42
+ next if dir.glob("Package*.swift").empty?
43
+
44
+ pkg_desc = PackageDescription.from_dir(dir)
45
+ name = pkg_desc.name
46
+ slug = dir.basename.to_s
47
+ @pkg_desc_cache[name] = pkg_desc
48
+ @pkg_desc_cache[slug] = pkg_desc
49
+ next if @json_dir.nil?
50
+
51
+ json_path = @json_dir / "#{name}.json"
52
+ slug_json_path = @json_dir / "#{slug}.json"
53
+ json_path.write(pkg_desc.raw.to_json)
54
+ IOUtils.symlink(json_path, slug_json_path) unless name == slug
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,17 @@
1
+ require "cocoapods-spm/swift/package/base"
2
+
3
+ module Pod
4
+ module Swift
5
+ class PackageDescription
6
+ class Resources < PackageDescriptionBaseObject
7
+ def name
8
+ "#{pkg_name}_#{parent.name}"
9
+ end
10
+
11
+ def built_resource_path
12
+ "${PODS_CONFIGURATION_BUILD_DIR}/#{name}.bundle"
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end