cocoapods-spm 0.0.1 → 0.0.2.rc7194768598

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: 88926a40ad19c2ccc3b9ceccefe301a6f939ec7460c719b914a13eba5c1d3739
4
- data.tar.gz: 190363f1092af74595af470f7bdc617e8ffaca00314894b136298a9c31e9d979
3
+ metadata.gz: 023cb57cc496da534db60773efea73bdcdc40a869a7edeee06e52c16344dbe98
4
+ data.tar.gz: 5cc2ca8ee116d74324e187a1a3150386f74e01a9994f5d4a05278fc55820986f
5
5
  SHA512:
6
- metadata.gz: '06209d7e15bdbccf151db058e53dc27dfb9179d75ed76c6341518f5f56f02d62629ae2f0a369cdace8e719725a040aee2a24d626b709f280c15b18277f2ca636'
7
- data.tar.gz: c40d20e4560c12625ac7a4a52c6bbcee54407582039ac59f829f75978c29581379f24514e489fa6f393ef8872a131ce7608969b193927cabca7dfc2f06a0db35
6
+ metadata.gz: c3ee693e680264039630ac55ea94d477bab5a5e8e264b3af1f9d696b40d2d232a4e006495746d1b2722b633acabee97b937be065d1e4eb465554b41cdff33d90
7
+ data.tar.gz: 87e655ba9232d80f6277bfef1cf234876fd8a164dcac3e2a2be1298f313b2528ed267ff5697cc40c21039c5672df2659f19b914b448cc47947486f9179006aa8
@@ -0,0 +1,31 @@
1
+ require "cocoapods-spm/macro/fetcher"
2
+
3
+ module Pod
4
+ class Command
5
+ class Spm < Command
6
+ class Fetch < Spm
7
+ self.summary = "Fetch macros"
8
+ def self.options
9
+ [
10
+ ["--all", "Prebuild all macros"],
11
+ ["--macros=foo", "Macros to prebuild, separated by comma (,)"],
12
+ ].concat(super)
13
+ end
14
+
15
+ def initialize(argv)
16
+ super
17
+ update_cli_config(
18
+ all: argv.flag?("all"),
19
+ macros: argv.option("macros", "").split(",")
20
+ )
21
+ end
22
+
23
+ def run
24
+ spm_config.macros.each do |name|
25
+ SPM::MacroFetcher.new(name: name, can_cache: true).run
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,35 @@
1
+ require "cocoapods-spm/macro/prebuilder"
2
+
3
+ module Pod
4
+ class Command
5
+ class Spm < Command
6
+ class Prebuild < Spm
7
+ self.summary = "Prebuild macros"
8
+ def self.options
9
+ [
10
+ ["--all", "Prebuild all macros"],
11
+ ["--macros=foo", "Macros to prebuild, separated by comma (,)"],
12
+ ["--config=foo", "Config (debug/release) to prebuild macros"],
13
+ ].concat(super)
14
+ end
15
+
16
+ def initialize(argv)
17
+ super
18
+ update_cli_config(
19
+ all: argv.flag?("all"),
20
+ macros: argv.option("macros", "").split(","),
21
+ config: argv.option("config"),
22
+ dont_prebuild_macros: false,
23
+ dont_prebuild_macros_if_exist: false
24
+ )
25
+ end
26
+
27
+ def run
28
+ spm_config.macros.each do |name|
29
+ SPM::MacroPrebuilder.new(name: name).run
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,17 @@
1
+ require "cocoapods-spm/command/prebuild"
2
+ require "cocoapods-spm/command/fetch"
3
+
4
+ module Pod
5
+ class Command
6
+ class Spm < Command
7
+ include SPM::Config::Mixin
8
+
9
+ self.summary = "Working with SPM"
10
+ self.abstract_command = true
11
+
12
+ def update_cli_config(options)
13
+ spm_config.cli_config.merge!(options)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,15 +1,65 @@
1
1
  module Pod
2
2
  module SPM
3
3
  class Config
4
- attr_accessor :dsl_config
4
+ module Mixin
5
+ def spm_config
6
+ Config.instance
7
+ end
8
+
9
+ def macro_pods
10
+ Pod::Config.instance.podfile.macro_pods
11
+ end
12
+ end
13
+
14
+ attr_accessor :dsl_config, :cli_config
5
15
 
6
16
  def initialize
7
- @dsl_config = {}
17
+ @dsl_config = {
18
+ :dont_prebuild_macros => false,
19
+ :dont_prebuild_macros_if_exist => true
20
+ }
21
+ @cli_config = {}
8
22
  end
9
23
 
10
24
  def self.instance
11
25
  @instance ||= Config.new
12
26
  end
27
+
28
+ def merged_config
29
+ @dsl_config.merge(@cli_config)
30
+ end
31
+
32
+ def dont_prebuild_macros?
33
+ merged_config[:dont_prebuild_macros]
34
+ end
35
+
36
+ def dont_prebuild_macros_if_exist?
37
+ merged_config[:dont_prebuild_macros_if_exist]
38
+ end
39
+
40
+ def macro_config
41
+ merged_config[:config] || merged_config[:default_macro_config] || "debug"
42
+ end
43
+
44
+ def all_macros
45
+ @all_macros ||= Pod::Config.instance.podfile.macro_pods.keys
46
+ end
47
+
48
+ def macros
49
+ merged_config[:all] ? all_macros : (merged_config[:macros] || [])
50
+ end
51
+
52
+ def macro_root_dir
53
+ @macro_root_dir ||= Pathname(".spm.pods")
54
+ end
55
+
56
+ def macro_downloaded_root_dir
57
+ macro_root_dir / ".downloaded"
58
+ end
59
+
60
+ def macro_downloaded_sandbox
61
+ @macro_downloaded_sandbox ||= Sandbox.new(macro_downloaded_root_dir)
62
+ end
13
63
  end
14
64
  end
15
65
  end
@@ -0,0 +1,55 @@
1
+ require "cocoapods-spm/config"
2
+
3
+ module Pod
4
+ class Podfile
5
+ module DSL
6
+ alias origin_pod pod
7
+ def config_cocoapods_spm(options)
8
+ SPM::Config.instance.dsl_config = options
9
+ end
10
+
11
+ def macro_pods
12
+ @macro_pods ||= {}
13
+ end
14
+
15
+ def pod(name = nil, *requirements)
16
+ macro = requirements[0].delete(:macro) if requirements.first.is_a?(Hash)
17
+ macro ||= {}
18
+ unless macro.empty?
19
+ requirements[0][:path] = prepare_macro_pod_dir(name, macro)
20
+ macro_pods[name] = macro
21
+ end
22
+ origin_pod(name, *requirements)
23
+ end
24
+
25
+ def spm_pkg(name, options)
26
+ current_target_definition.store_spm_pkg(name, options)
27
+ end
28
+
29
+ private
30
+
31
+ def prepare_macro_pod_dir(name, requirement)
32
+ link = requirement[:git]
33
+ podspec_content = <<~HEREDOC
34
+ Pod::Spec.new do |s|
35
+ s.name = "#{name}"
36
+ s.version = "0.0.1"
37
+ s.summary = "#{name}"
38
+ s.description = "#{name}"
39
+ s.homepage = "#{link}"
40
+ s.license = "MIT"
41
+ s.authors = "dummy@gmail.com"
42
+ s.source = #{requirement}
43
+ s.source_files = "Sources/**/*"
44
+ end
45
+ HEREDOC
46
+
47
+ path = Pathname(".spm.pods/#{name}")
48
+ (path / ".prebuilt").mkpath
49
+ (path / "Sources").mkpath
50
+ (path / "#{name}.podspec").write(podspec_content)
51
+ path
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,26 @@
1
+ require "cocoapods-spm/config"
2
+ require "cocoapods-spm/def/spm_dependency"
3
+
4
+ module Pod
5
+ class Specification
6
+ def spm_dependencies
7
+ @spm_dependencies ||= []
8
+ end
9
+
10
+ def spm_dependency(name, options = {})
11
+ spm_dependencies << SPM::Dependency.new(name, options)
12
+ end
13
+
14
+ def with
15
+ spec = Pod::Spec.new(
16
+ parent,
17
+ name,
18
+ test_specification,
19
+ app_specification: app_specification
20
+ )
21
+ spec.attributes_hash = attributes_hash.dup
22
+ yield spec if block_given?
23
+ spec
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ module Pod
2
+ module SPM
3
+ class Dependency
4
+ attr_reader :name, :product
5
+ attr_accessor :pkg
6
+
7
+ def initialize(name, options = {}, product: nil, pkg: nil)
8
+ cmps = name.split("/")
9
+ raise "Invalid dependency `#{name}`" if cmps.count > 2
10
+
11
+ @name = cmps.first
12
+ @product = product || cmps.last
13
+ @options = options
14
+ @pkg = pkg
15
+ end
16
+
17
+ def inspect
18
+ "#<#{self.class} name=#{name} product=#{product} pkg=#{pkg}>"
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,65 @@
1
+ require "cocoapods-spm/def/xcodeproj"
2
+ require "cocoapods-spm/def/spm_dependency"
3
+
4
+ module Pod
5
+ module SPM
6
+ class Package
7
+ attr_reader :name, :requirement, :url, :relative_path
8
+
9
+ def initialize(name, options = {})
10
+ @name = name
11
+ @options = options
12
+ @requirement = requirement_from(options)
13
+ @url = options[:url]
14
+ @relative_path = options[:relative_path]
15
+ end
16
+
17
+ def inspect
18
+ "#<#{self.class} name=#{name}>"
19
+ end
20
+
21
+ def local?
22
+ @relative_path != nil
23
+ end
24
+
25
+ def to_dependencies
26
+ if (products = @options[:products])
27
+ products.map { |product| Dependency.new(@name, product: product, pkg: self) }
28
+ else
29
+ [Dependency.new(@name, pkg: self)]
30
+ end
31
+ end
32
+
33
+ def create_pkg_ref(project)
34
+ cls = local? ? Object::XCLocalSwiftPackageReference : Object::XCRemoteSwiftPackageReference
35
+ ref = project.new(cls)
36
+ ref.name = name
37
+ if local?
38
+ ref.relative_path = relative_path
39
+ else
40
+ ref.repositoryURL = url
41
+ ref.requirement = requirement
42
+ end
43
+ ref
44
+ end
45
+
46
+ private
47
+
48
+ def requirement_from(options)
49
+ if options[:requirement]
50
+ options[:requirement]
51
+ elsif (version = options.delete(:version))
52
+ { :kind => "exactVersion", :version => version }
53
+ elsif (branch = options.delete(:branch))
54
+ { :kind => "branch", :branch => branch }
55
+ elsif (revision = options.delete(:commit))
56
+ { :kind => "revision", :revision => revision }
57
+ elsif options[:relative_path]
58
+ nil
59
+ else
60
+ raise "Missing requirement for SPM package: #{name}"
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,15 @@
1
+ require "cocoapods-spm/def/spm_package"
2
+
3
+ module Pod
4
+ class Podfile
5
+ class TargetDefinition
6
+ def store_spm_pkg(name, options)
7
+ spm_pkgs << SPM::Package.new(name, options)
8
+ end
9
+
10
+ def spm_pkgs
11
+ @spm_pkgs ||= []
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,31 @@
1
+ require "xcodeproj"
2
+
3
+ module Pod
4
+ module SPM
5
+ module Object
6
+ module PackageReferenceMixin
7
+ attr_accessor :name
8
+
9
+ def create_pkg_product_dependency_ref(product)
10
+ ref = project.new(BaseObject::XCSwiftPackageProductDependency)
11
+ ref.package = self
12
+ ref.product_name = product
13
+ ref
14
+ end
15
+ end
16
+
17
+ BaseObject = Xcodeproj::Project::Object
18
+
19
+ class XCRemoteSwiftPackageReference < BaseObject::XCRemoteSwiftPackageReference
20
+ include PackageReferenceMixin
21
+ end
22
+
23
+ class XCLocalSwiftPackageReference < BaseObject::XCLocalSwiftPackageReference
24
+ include PackageReferenceMixin
25
+ end
26
+
27
+ class XCSwiftPackageProductDependency < BaseObject::XCSwiftPackageProductDependency
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,83 @@
1
+ require "cocoapods-spm/config"
2
+ require "cocoapods-spm/def/podfile"
3
+ require "cocoapods-spm/def/spec"
4
+
5
+ module Pod
6
+ module SPM
7
+ class Hook
8
+ include Config::Mixin
9
+
10
+ def initialize(context, options = {})
11
+ @context = context
12
+ @options = options
13
+ @spm_analyzer = options[:spm_analyzer]
14
+ @analysis_result = options[:analysis_result]
15
+ end
16
+
17
+ def sandbox
18
+ @context.sandbox
19
+ end
20
+
21
+ def pods_project
22
+ @context.pods_project
23
+ end
24
+
25
+ def pod_targets
26
+ @analysis_result.pod_targets
27
+ end
28
+
29
+ def aggregate_targets
30
+ @analysis_result.targets
31
+ end
32
+
33
+ def user_build_configurations
34
+ @user_build_configurations ||= (pod_targets + aggregate_targets)[0].user_build_configurations
35
+ end
36
+
37
+ def config
38
+ Config.instance
39
+ end
40
+
41
+ def run; end
42
+
43
+ def self.run_hooks(phase, context, options)
44
+ Dir["#{__dir__}/#{phase}/*.rb"].sort.each do |f|
45
+ require f
46
+ id = File.basename(f, ".*")
47
+ cls_name = "Pod::SPM::Hook::#{id.camelize}"
48
+ UI.message "Running hook: #{cls_name}"
49
+ cls_name.constantize.new(context, options).run
50
+ end
51
+ end
52
+
53
+ def perform_settings_update(
54
+ update_targets: nil,
55
+ update_pod_targets: nil,
56
+ update_aggregate_targets: nil
57
+ )
58
+ proc = lambda do |update, target, setting, config|
59
+ return if update.nil?
60
+
61
+ hash = update.call(target, setting, config)
62
+ setting.xcconfig.merge!(hash)
63
+ setting.generate.merge!(hash)
64
+ end
65
+
66
+ pod_targets.each do |target|
67
+ target.build_settings.each do |config, setting|
68
+ proc.call(update_targets, target, setting, config)
69
+ proc.call(update_pod_targets, target, setting, config)
70
+ end
71
+ end
72
+
73
+ aggregate_targets.each do |target|
74
+ target.user_build_configurations.each_key do |config|
75
+ setting = target.build_settings(config)
76
+ proc.call(update_targets, target, setting, config)
77
+ proc.call(update_aggregate_targets, target, setting, config)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,50 @@
1
+ require "cocoapods-spm/hooks/base"
2
+ require "cocoapods-spm/installer/analyzer"
3
+
4
+ module Pod
5
+ module SPM
6
+ class Hook
7
+ class AddSpmPkgs < Hook
8
+ def run
9
+ return unless @spm_analyzer.spm_pkgs
10
+
11
+ add_spm_pkg_refs_to_project
12
+ add_spm_products_to_targets
13
+ pods_project.save
14
+ end
15
+
16
+ private
17
+
18
+ def spm_pkg_refs
19
+ @spm_pkg_refs ||= {}
20
+ end
21
+
22
+ def add_spm_pkg_refs_to_project
23
+ @spm_pkg_refs = @spm_analyzer.spm_pkgs.to_h do |pkg|
24
+ pkg_ref = pkg.create_pkg_ref(pods_project)
25
+ pods_project.root_object.package_references << pkg_ref
26
+ [pkg.name, pkg_ref]
27
+ end
28
+ end
29
+
30
+ def spm_pkgs_by_target
31
+ @spm_pkgs_by_target ||= {}
32
+ end
33
+
34
+ def add_spm_products_to_targets
35
+ pods_project.targets.each do |target|
36
+ @spm_analyzer.spm_dependencies_by_target[target.name].to_a.each do |dep|
37
+ pkg_ref = spm_pkg_refs[dep.pkg.name]
38
+ product_ref = pkg_ref.create_pkg_product_dependency_ref(dep.product)
39
+ target.package_product_dependencies << product_ref
40
+ end
41
+ end
42
+ end
43
+
44
+ def podfile
45
+ Pod::Config.instance.podfile
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,71 @@
1
+ require "cocoapods-spm/hooks/base"
2
+ require "cocoapods-spm/metadata"
3
+
4
+ module Pod
5
+ module SPM
6
+ class Hook
7
+ class UpdateSettings < Hook
8
+ def run
9
+ update_other_swift_flags
10
+ update_swift_include_paths
11
+ update_linker_flags
12
+ end
13
+
14
+ private
15
+
16
+ def other_swift_flags_by_config
17
+ @other_swift_flags_by_config ||= begin
18
+ hash = user_build_configurations.keys.to_h do |config|
19
+ flags = macro_pods.keys.map do |name|
20
+ metadata = Metadata.for_pod(name)
21
+ impl_module_name = metadata.macro_impl_name
22
+ plugin_executable_path =
23
+ "${PODS_ROOT}/../.spm.pods/#{name}/.prebuilt/#{config.to_s.downcase}/" \
24
+ "#{impl_module_name}##{impl_module_name}"
25
+ "-load-plugin-executable \"#{plugin_executable_path}\""
26
+ end.join(" ")
27
+ [config, flags]
28
+ end
29
+ user_build_configurations.each { |config, symbol| hash[symbol] = hash[config] }
30
+ hash
31
+ end
32
+ end
33
+
34
+ def update_other_swift_flags
35
+ return unless spm_config.macros
36
+
37
+ # For prebuilt macros
38
+ perform_settings_update(
39
+ update_targets: lambda do |_, _, config|
40
+ { "OTHER_SWIFT_FLAGS" => other_swift_flags_by_config[config] }
41
+ end
42
+ )
43
+ end
44
+
45
+ def update_linker_flags
46
+ return unless @spm_analyzer.spm_pkgs
47
+
48
+ # For packages to work in the main target
49
+ perform_settings_update(
50
+ update_aggregate_targets: lambda do |target, _, _|
51
+ spm_deps = @spm_analyzer.spm_dependencies_by_target[target.to_s].to_a
52
+ flags = spm_deps.map { |d| "-l\"#{d.product}.o\"" }
53
+ { "OTHER_LDFLAGS" => flags }
54
+ end
55
+ )
56
+ end
57
+
58
+ def update_swift_include_paths
59
+ return unless @spm_analyzer.spm_pkgs
60
+
61
+ # For macro packages
62
+ perform_settings_update(
63
+ update_targets: lambda do |_, _, _|
64
+ { "SWIFT_INCLUDE_PATHS" => "${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}" }
65
+ end
66
+ )
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,66 @@
1
+ module Pod
2
+ class Installer
3
+ class SPMAnalyzer
4
+ attr_reader :spm_pkgs, :spm_dependencies_by_target
5
+
6
+ def initialize(podfile, umbrella_targets)
7
+ @podfile = podfile
8
+ @umbrella_targets = umbrella_targets
9
+ @spm_pkgs = []
10
+ @spm_dependencies_by_target = {}
11
+ end
12
+
13
+ def analyze
14
+ analyze_spm_pkgs
15
+ analyze_spm_dependencies_by_target
16
+ end
17
+
18
+ private
19
+
20
+ def analyze_spm_pkgs
21
+ @spm_pkgs = @podfile.target_definition_list.flat_map(&:spm_pkgs).uniq
22
+ end
23
+
24
+ def analyze_spm_dependencies_by_target
25
+ analyze_dependencies_for_targets
26
+ analyze_dependencies_for_umbrella_targets
27
+ @spm_dependencies_by_target.values.flatten.each { |d| d.pkg = spm_pkg_for(d.name) }
28
+ end
29
+
30
+ def analyze_dependencies_for_targets
31
+ specs = @umbrella_targets.flat_map(&:specs).uniq
32
+ specs.each do |spec|
33
+ @spm_dependencies_by_target[spec.name] = spec.spm_dependencies
34
+ end
35
+ end
36
+
37
+ def analyze_dependencies_for_umbrella_targets
38
+ @umbrella_targets.each do |target|
39
+ spm_dependencies = target.specs.flat_map(&:spm_dependencies)
40
+ @spm_dependencies_by_target[target.to_s] = merge_spm_dependencies(spm_dependencies)
41
+ end
42
+
43
+ common_spm_pkgs = @podfile.root_target_definitions.flat_map(&:spm_pkgs)
44
+ @podfile.target_definition_list.reject(&:abstract?).each do |target|
45
+ existing = @spm_dependencies_by_target[target.label].to_a
46
+ spm_dependencies = (common_spm_pkgs + target.spm_pkgs).flat_map(&:to_dependencies)
47
+ @spm_dependencies_by_target[target.label] = merge_spm_dependencies(existing + spm_dependencies)
48
+ end
49
+ end
50
+
51
+ def merge_spm_dependencies(deps)
52
+ deps_by_name = Hash.new { |h, k| h[k] = [] }
53
+ deps.each { |d| deps_by_name[d.name] << d }
54
+ deps_by_name.each do |name, ds|
55
+ deps_by_name[name] = ds.uniq { |d| [d.name, d.product] }
56
+ end
57
+ deps_by_name.values.flatten
58
+ end
59
+
60
+ def spm_pkg_for(name)
61
+ @_spm_pkgs_by_name ||= @spm_pkgs.to_h { |pkg| [pkg.name, pkg] }
62
+ @_spm_pkgs_by_name[name]
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,51 @@
1
+ module Pod
2
+ module SPM
3
+ class MacroFetcher
4
+ include Config::Mixin
5
+
6
+ attr_reader :name
7
+
8
+ def initialize(options = {})
9
+ @name = options[:name]
10
+ @specs_by_platform = options[:specs_by_platform]
11
+ @can_cache = options[:can_cache]
12
+ @podfile = Pod::Config.instance.podfile
13
+ end
14
+
15
+ def run
16
+ download_macro_source
17
+ macro_dir = spm_config.macro_root_dir / name
18
+ macro_downloaded_dir = spm_config.macro_downloaded_root_dir / name
19
+ FileUtils.copy_entry(
20
+ macro_downloaded_dir / "Sources" / name,
21
+ macro_dir / "Sources" / name
22
+ )
23
+ end
24
+
25
+ def download_macro_source
26
+ @specs_by_platform ||= @podfile.root_target_definitions.to_h do |definition|
27
+ spec = Pod::Spec.from_file(spm_config.macro_root_dir / name / "#{name}.podspec")
28
+ [definition.platform, [spec]]
29
+ end
30
+
31
+ # When `can_cache` is true, PodSourceDownloader only keeps the contents
32
+ # according to its `source_files` declared in the podspec.
33
+ # However, we wish to keep all contents (including Package.swift...).
34
+ # --> We alter the spec when downloading the source.
35
+ altered_specs_by_platform = @specs_by_platform.to_h do |platform, specs|
36
+ altered_specs = specs.map do |spec|
37
+ spec.with { |s| s.source_files = "**/*" }
38
+ end
39
+ [platform, altered_specs]
40
+ end
41
+ downloader = Pod::Installer::PodSourceDownloader.new(
42
+ spm_config.macro_downloaded_sandbox,
43
+ @podfile,
44
+ altered_specs_by_platform,
45
+ can_cache: @can_cache
46
+ )
47
+ downloader.download!
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,35 @@
1
+ require "cocoapods-spm/def/spec"
2
+ require "cocoapods-spm/macro/fetcher"
3
+ require "cocoapods-spm/macro/prebuilder"
4
+
5
+ module Pod
6
+ class Installer
7
+ class MacroPodInstaller < PodSourceInstaller
8
+ include SPM::Config::Mixin
9
+
10
+ def install!
11
+ install_macro_pod!
12
+ super
13
+ end
14
+
15
+ private
16
+
17
+ def fetcher
18
+ @fetcher ||= SPM::MacroFetcher.new(
19
+ name: name,
20
+ specs_by_platform: specs_by_platform,
21
+ can_cache: can_cache?
22
+ )
23
+ end
24
+
25
+ def prebuilder
26
+ @prebuilder ||= SPM::MacroPrebuilder.new(name: name)
27
+ end
28
+
29
+ def install_macro_pod!
30
+ fetcher.run
31
+ prebuilder.run
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,64 @@
1
+ require "cocoapods-spm/metadata"
2
+
3
+ module Pod
4
+ module SPM
5
+ class MacroPrebuilder
6
+ include Config::Mixin
7
+
8
+ attr_reader :name
9
+
10
+ def initialize(options = {})
11
+ @name = options[:name]
12
+ end
13
+
14
+ def run
15
+ generate_metadata
16
+ prebuild_macro_impl
17
+ end
18
+
19
+ def macro_downloaded_dir
20
+ spm_config.macro_downloaded_root_dir / name
21
+ end
22
+
23
+ def macro_dir
24
+ @macro_dir ||= spm_config.macro_root_dir / name
25
+ end
26
+
27
+ def macro_prebuilt_dir
28
+ macro_dir / ".prebuilt"
29
+ end
30
+
31
+ def metadata_path
32
+ macro_dir / "metadata.json"
33
+ end
34
+
35
+ def generate_metadata
36
+ raise "Package.swift not exist in #{macro_downloaded_dir}" \
37
+ unless (macro_downloaded_dir / "Package.swift").exist?
38
+
39
+ cmd =
40
+ "cd #{macro_downloaded_dir} " \
41
+ "&& swift package dump-package " \
42
+ "> #{metadata_path.relative_path_from(macro_downloaded_dir)}"
43
+ `#{cmd}`
44
+ @metadata = Metadata.from_file(metadata_path)
45
+ end
46
+
47
+ def prebuild_macro_impl
48
+ return if spm_config.dont_prebuild_macros?
49
+
50
+ config = spm_config.macro_config
51
+ impl_module_name = @metadata.macro_impl_name
52
+ return if spm_config.dont_prebuild_macros_if_exist? && (macro_prebuilt_dir / config / impl_module_name).exist?
53
+
54
+ UI.puts "Building macro implementation: #{impl_module_name} (#{config})...".green
55
+ `cd #{macro_downloaded_dir} && swift build -c #{config}`
56
+ (macro_prebuilt_dir / config).mkpath
57
+ FileUtils.copy_entry(
58
+ macro_downloaded_dir / ".build" / config / impl_module_name,
59
+ macro_prebuilt_dir / config / impl_module_name
60
+ )
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,78 +1,5 @@
1
- require "cocoapods-spm/config"
2
- require "cocoapods-spm/dsl"
3
- require "cocoapods-spm/specification"
4
-
5
- module Pod
6
- module SPM
7
- class Hook
8
- def initialize(context)
9
- @context = context
10
- end
11
-
12
- def sandbox
13
- @context.sandbox
14
- end
15
-
16
- def pods_project
17
- @context.pods_project
18
- end
19
-
20
- def config
21
- Config.instance
22
- end
23
-
24
- def all_specs
25
- @all_specs ||= @context.umbrella_targets.flat_map(&:specs).uniq
26
- end
27
-
28
- def run
29
- all_specs.each do |spec|
30
- if spec.spm_dependencies
31
- target = pods_project.targets.find { |t| t.name == spec.name }
32
- add_spm_dependencies(target, spec.spm_dependencies)
33
- end
34
- end
35
- update_import_paths
36
- pods_project.save
37
- end
38
-
39
- private
40
-
41
- def add_spm_dependencies(target, dependencies)
42
- dependencies.each do |data|
43
- pkg = pkg_from_data(data)
44
- data[:products].each do |product|
45
- ref = pods_project.new(Xcodeproj::Project::Object::XCSwiftPackageProductDependency)
46
- ref.package = pkg
47
- ref.product_name = product
48
- target.package_product_dependencies << ref
49
- end
50
- pods_project.root_object.package_references << pkg
51
- end
52
- end
53
-
54
- def update_import_paths
55
- # Workaround: Currently, update the swift import paths of the base/Pods project
56
- # to make it effective across all pod targets
57
- pods_project.build_configurations.each do |config|
58
- to_add = '${SYMROOT}/${CONFIGURATION}${EFFECTIVE_PLATFORM_NAME}'
59
- import_paths = config.build_settings['SWIFT_INCLUDE_PATHS'] || ['$(inherited)']
60
- import_paths << to_add unless import_paths.include?(to_add)
61
- config.build_settings['SWIFT_INCLUDE_PATHS'] = import_paths
62
- end
63
- end
64
-
65
- def pkg_from_data(data)
66
- if data[:requirement]
67
- pkg = pods_project.new(Xcodeproj::Project::Object::XCRemoteSwiftPackageReference)
68
- pkg.repositoryURL = data[:url]
69
- pkg.requirement = data[:requirement]
70
- else
71
- pkg = pods_project.new(Xcodeproj::Project::Object::XCLocalSwiftPackageReference)
72
- pkg.relative_path = data[:relative_path]
73
- end
74
- pkg
75
- end
76
- end
77
- end
78
- end
1
+ require "cocoapods-spm/def/target_definition"
2
+ require "cocoapods-spm/def/podfile"
3
+ require "cocoapods-spm/def/spec"
4
+ require "cocoapods-spm/patch/installer"
5
+ require "cocoapods-spm/command/spm"
@@ -0,0 +1,33 @@
1
+ require "json"
2
+
3
+ module Pod
4
+ module SPM
5
+ class Metadata
6
+ attr_reader :raw
7
+
8
+ def initialize(raw)
9
+ @raw = raw
10
+ end
11
+
12
+ def self.from_file(path)
13
+ new(JSON.parse(File.read(path)))
14
+ end
15
+
16
+ def self.for_pod(name)
17
+ from_file(Config.instance.macro_root_dir / name / "metadata.json")
18
+ end
19
+
20
+ def targets
21
+ raw["targets"]
22
+ end
23
+
24
+ def targets_of_type(type)
25
+ targets.select { |t| t["type"] == type }
26
+ end
27
+
28
+ def macro_impl_name
29
+ targets_of_type("macro").first&.fetch("name")
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,63 @@
1
+ require "cocoapods-spm/installer/analyzer"
2
+ require "cocoapods-spm/macro/pod_installer"
3
+ require "cocoapods-spm/hooks/base"
4
+
5
+ module Pod
6
+ class Installer
7
+ include SPM::Config::Mixin
8
+
9
+ alias origin_resolve_dependencies resolve_dependencies
10
+ def resolve_dependencies
11
+ origin_resolve_dependencies
12
+ resolve_spm_dependencies
13
+ end
14
+
15
+ alias origin_create_pod_installer create_pod_installer
16
+ def create_pod_installer(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
+ alias origin_integrate integrate
32
+ def integrate
33
+ run_spm_pre_integrate_hooks
34
+ origin_integrate
35
+ run_spm_post_integrate_hooks
36
+ end
37
+
38
+ private
39
+
40
+ def hook_options
41
+ {
42
+ :spm_analyzer => @spm_analyzer,
43
+ :analysis_result => @analysis_result
44
+ }
45
+ end
46
+
47
+ def run_spm_pre_integrate_hooks
48
+ context = PreIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
49
+ SPM::Hook.run_hooks(:pre_integrate, context, hook_options)
50
+ end
51
+
52
+ def run_spm_post_integrate_hooks
53
+ context = PostIntegrateHooksContext.generate(sandbox, pods_project, pod_target_subprojects, aggregate_targets)
54
+ SPM::Hook.run_hooks(:post_integrate, context, hook_options)
55
+ end
56
+
57
+ def resolve_spm_dependencies
58
+ # TODO: convert aggregate_targets to umbrella_targets?
59
+ @spm_analyzer ||= Pod::Installer::SPMAnalyzer.new(podfile, aggregate_targets)
60
+ @spm_analyzer.analyze
61
+ end
62
+ end
63
+ end
@@ -1,5 +1 @@
1
1
  require "cocoapods-spm/main"
2
-
3
- Pod::HooksManager.register("cocoapods-spm", :post_install) do |context|
4
- Pod::SPM::Hook.new(context).run
5
- end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-spm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2.rc7194768598
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thuyen Trinh
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-28 00:00:00.000000000 Z
11
+ date: 2023-12-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -60,16 +60,32 @@ extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
62
  - lib/cocoapods-spm.rb
63
+ - lib/cocoapods-spm/command/fetch.rb
64
+ - lib/cocoapods-spm/command/prebuild.rb
65
+ - lib/cocoapods-spm/command/spm.rb
63
66
  - lib/cocoapods-spm/config.rb
64
- - lib/cocoapods-spm/dsl.rb
67
+ - lib/cocoapods-spm/def/podfile.rb
68
+ - lib/cocoapods-spm/def/spec.rb
69
+ - lib/cocoapods-spm/def/spm_dependency.rb
70
+ - lib/cocoapods-spm/def/spm_package.rb
71
+ - lib/cocoapods-spm/def/target_definition.rb
72
+ - lib/cocoapods-spm/def/xcodeproj.rb
73
+ - lib/cocoapods-spm/hooks/base.rb
74
+ - lib/cocoapods-spm/hooks/post_integrate/add_spm_pkgs.rb
75
+ - lib/cocoapods-spm/hooks/pre_integrate/update_settings.rb
76
+ - lib/cocoapods-spm/installer/analyzer.rb
77
+ - lib/cocoapods-spm/macro/fetcher.rb
78
+ - lib/cocoapods-spm/macro/pod_installer.rb
79
+ - lib/cocoapods-spm/macro/prebuilder.rb
65
80
  - lib/cocoapods-spm/main.rb
66
- - lib/cocoapods-spm/specification.rb
81
+ - lib/cocoapods-spm/metadata.rb
82
+ - lib/cocoapods-spm/patch/installer.rb
67
83
  - lib/cocoapods_plugin.rb
68
84
  homepage: https://github.com/trinhngocthuyen/cocoapods-spm
69
85
  licenses:
70
86
  - MIT
71
87
  metadata: {}
72
- post_install_message:
88
+ post_install_message:
73
89
  rdoc_options: []
74
90
  require_paths:
75
91
  - lib
@@ -80,12 +96,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
96
  version: '0'
81
97
  required_rubygems_version: !ruby/object:Gem::Requirement
82
98
  requirements:
83
- - - ">="
99
+ - - ">"
84
100
  - !ruby/object:Gem::Version
85
- version: '0'
101
+ version: 1.3.1
86
102
  requirements: []
87
- rubygems_version: 3.2.3
88
- signing_key:
103
+ rubygems_version: 3.1.6
104
+ signing_key:
89
105
  specification_version: 4
90
106
  summary: CocoaPods plugin to add SPM dependencies to CocoaPods targets
91
107
  test_files: []
@@ -1,11 +0,0 @@
1
- require "cocoapods-spm/config"
2
-
3
- module Pod
4
- class Podfile
5
- module DSL
6
- def config_xcconfig_hooks(options)
7
- Pod::SPM::Config.instance.dsl_config = options
8
- end
9
- end
10
- end
11
- end
@@ -1,10 +0,0 @@
1
- module Pod
2
- class Specification
3
- attr_reader :spm_dependencies
4
-
5
- def spm_dependency(options)
6
- @spm_dependencies ||= []
7
- @spm_dependencies << options
8
- end
9
- end
10
- end