cocoapods-project-gen 0.1.0 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +62 -23
- data/bin/xcframework +11 -0
- data/lib/cocoapods-project-gen/command/command.rb +25 -0
- data/lib/cocoapods-project-gen/command/gen.rb +120 -0
- data/lib/cocoapods-project-gen/gem_version.rb +1 -1
- data/lib/cocoapods-project-gen/gen/build/headers_store.rb +104 -0
- data/lib/cocoapods-project-gen/gen/build/xcode_build.rb +47 -0
- data/lib/cocoapods-project-gen/gen/constants.rb +71 -0
- data/lib/cocoapods-project-gen/gen/pod/pod_copy_cleaner.rb +50 -0
- data/lib/cocoapods-project-gen/gen/pod/project_gen_helper.rb +341 -0
- data/lib/cocoapods-project-gen/gen/pod/swift_module_helper.rb +134 -0
- data/lib/cocoapods-project-gen/gen/product/product_helper.rb +93 -0
- data/lib/cocoapods-project-gen/gen/product.rb +165 -0
- data/lib/cocoapods-project-gen/gen/project_builder.rb +144 -0
- data/lib/cocoapods-project-gen/gen/project_gen.rb +179 -128
- data/lib/cocoapods-project-gen/gen/results.rb +143 -0
- data/lib/cocoapods-project-gen/gen/utils.rb +35 -0
- data/lib/cocoapods-project-gen/gen/xcframework_gen.rb +44 -0
- data/lib/cocoapods-project-gen.rb +14 -7
- metadata +21 -6
- data/lib/cocoapods-project-gen/gen/swift_module_helper.rb +0 -52
@@ -0,0 +1,165 @@
|
|
1
|
+
module ProjectGen
|
2
|
+
require 'cocoapods-project-gen/gen/product/product_helper'
|
3
|
+
require 'cocoapods-project-gen/gen/build/xcode_build'
|
4
|
+
class Products
|
5
|
+
attr_reader :products
|
6
|
+
|
7
|
+
def initialize(spec, products)
|
8
|
+
@products = products
|
9
|
+
@spec = spec
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_pod_targets_file_accessors_paths
|
13
|
+
products.each(&:add_pod_target_file_accessors_paths)
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_bin_products
|
17
|
+
FileUtils.rm_rf(product_path) if product_path.exist?
|
18
|
+
build_xcframework
|
19
|
+
add_pod_targets_file_accessors_paths
|
20
|
+
end
|
21
|
+
|
22
|
+
# Performs platform specific analysis. It requires to download the source
|
23
|
+
# at each iteration
|
24
|
+
#
|
25
|
+
# @note Xcode warnings are treated as notes because the spec maintainer
|
26
|
+
# might not be the author of the library
|
27
|
+
# @return [void]
|
28
|
+
def build_xcframework
|
29
|
+
xc_args = @products.flat_map(&:create_bin_product_args!)
|
30
|
+
error = XcodeBuild.create_xcframework?(xc_args, xcframework_product_path)
|
31
|
+
print_pod_xcframework_infos unless error
|
32
|
+
end
|
33
|
+
|
34
|
+
def xcframework_product_path
|
35
|
+
@products[0].xcframework_product_path
|
36
|
+
end
|
37
|
+
|
38
|
+
def product_path
|
39
|
+
@products[0].product_path
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
# Prints the list of specs & pod cache dirs for a single pod name.
|
44
|
+
#
|
45
|
+
# This output is valid YAML so it can be parsed with 3rd party tools
|
46
|
+
#
|
47
|
+
def print_pod_xcframework_infos
|
48
|
+
product = @products[0]
|
49
|
+
Results.puts("#{product.xcframework_name}:".green)
|
50
|
+
Results.puts(" - Version: #{product.version}".green)
|
51
|
+
Results.puts(" Type: #{product.product_type}".green)
|
52
|
+
Results.puts(" path: #{product_path}".green)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
class Product
|
57
|
+
include ProductHelper
|
58
|
+
|
59
|
+
attr_reader :target, :product_root
|
60
|
+
|
61
|
+
def initialize(target, product_root, root, archive_paths)
|
62
|
+
@target = GenTarget.new(target)
|
63
|
+
@archive_paths = archive_paths
|
64
|
+
@product_root = product_root
|
65
|
+
@root = root
|
66
|
+
end
|
67
|
+
|
68
|
+
def create_bin_product_args!
|
69
|
+
@archive_paths.flat_map do |path|
|
70
|
+
headers_dir = path.dirname.join(pod_name).join('Headers')
|
71
|
+
args = %W[-archive #{path}]
|
72
|
+
args + if build_as_framework?
|
73
|
+
%W[-framework #{product_name}]
|
74
|
+
else
|
75
|
+
h_a = %W[-headers #{headers_dir}] if headers_dir.exist? && headers_dir.children.count.nonzero?
|
76
|
+
%W[-library #{static_library_name}] + (h_a || [])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_pod_target_file_accessors_paths
|
82
|
+
add_vendored_frameworks
|
83
|
+
add_vendored_libraries
|
84
|
+
add_resources
|
85
|
+
add_other_files
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
# Removes the source files of the Pods to the Pods project.
|
91
|
+
#
|
92
|
+
# @note The source files are grouped by Pod and in turn by subspec
|
93
|
+
# (recursively).
|
94
|
+
#
|
95
|
+
# @return [void]
|
96
|
+
#
|
97
|
+
def remove_source_files_references
|
98
|
+
Pod::UI.message '- Removing source files' do
|
99
|
+
extensions = Pod::Sandbox::FileAccessor::SOURCE_FILE_EXTENSIONS
|
100
|
+
source_files = file_accessors.flat_map { |file_accessor| file_accessor.send(:source_files) }
|
101
|
+
source_files.each do |f|
|
102
|
+
next unless extensions.include?(f.extname)
|
103
|
+
|
104
|
+
relative_path = f.relative_path_from(pod_dir)
|
105
|
+
full_source_path = @product_path.join(relative_path)
|
106
|
+
FileUtils.rm_rf(full_source_path)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Adds the bundled frameworks to the Pods project
|
112
|
+
#
|
113
|
+
# @return [void]
|
114
|
+
#
|
115
|
+
def add_vendored_frameworks
|
116
|
+
Pod::UI.message '- Adding frameworks' do
|
117
|
+
add_file_accessors_paths_to_products_group(:vendored_frameworks)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Adds the bundled libraries to the Pods project
|
122
|
+
#
|
123
|
+
# @return [void]
|
124
|
+
#
|
125
|
+
def add_vendored_libraries
|
126
|
+
Pod::UI.message '- Adding libraries' do
|
127
|
+
add_file_accessors_paths_to_products_group(:vendored_libraries)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Adds the resources of the Pods to the Pods project.
|
132
|
+
#
|
133
|
+
# @note The source files are grouped by Pod and in turn by subspec
|
134
|
+
# (recursively) in the resources group.
|
135
|
+
#
|
136
|
+
# @return [void]
|
137
|
+
#
|
138
|
+
def add_resources
|
139
|
+
Pod::UI.message '- Adding resources' do
|
140
|
+
add_file_accessors_paths_to_products_group(:resources)
|
141
|
+
add_file_accessors_paths_to_products_group(:resource_bundle_files)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def add_other_files
|
146
|
+
Pod::UI.message '- Adding other files' do
|
147
|
+
add_file_accessors_paths_to_products_group(:license)
|
148
|
+
add_file_accessors_paths_to_products_group(:readme)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def add_file_accessors_paths_to_products_group(file_accessor_key)
|
153
|
+
fs = file_accessors.flat_map { |file_accessor| file_accessor.send(file_accessor_key) }
|
154
|
+
fs.each do |f|
|
155
|
+
relative_path = f.relative_path_from(pod_dir)
|
156
|
+
full_source_path = product_path.join(relative_path)
|
157
|
+
next if full_source_path.exist?
|
158
|
+
|
159
|
+
full_source_dir = product_path.join(relative_path.parent)
|
160
|
+
FileUtils.mkdir_p(full_source_dir) unless full_source_dir.exist?
|
161
|
+
FileUtils.cp_r(%W[#{f}], full_source_dir)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'cocoapods'
|
2
|
+
|
3
|
+
module ProjectGen
|
4
|
+
class BuildManager
|
5
|
+
require 'cocoapods-project-gen/gen/build/xcode_build'
|
6
|
+
require 'cocoapods-project-gen/gen/product'
|
7
|
+
require 'cocoapods-project-gen/gen/build/headers_store'
|
8
|
+
|
9
|
+
attr_reader :root
|
10
|
+
|
11
|
+
def initialize(app_root, root = nil, no_clean: true, fail_fast: true)
|
12
|
+
@root = root.nil? ? app_root : root
|
13
|
+
@app_root = app_root
|
14
|
+
@no_clean = no_clean
|
15
|
+
@fail_fast = fail_fast
|
16
|
+
end
|
17
|
+
|
18
|
+
def product_dir
|
19
|
+
Pathname.new(root.parent).join('./project_gen_products').expand_path
|
20
|
+
end
|
21
|
+
|
22
|
+
def archives_dir
|
23
|
+
Pathname.new(root.parent).join('./project_gen_archives').expand_path
|
24
|
+
end
|
25
|
+
|
26
|
+
# Integrates the user projects associated with the {TargetDefinitions}
|
27
|
+
# with the Pods project and its products.
|
28
|
+
#
|
29
|
+
# @return [void]
|
30
|
+
#
|
31
|
+
def create_xcframework_products!(platforms, pod_targets, configuration = nil, build_library_for_distribution: false)
|
32
|
+
ts = pod_targets.values.flatten
|
33
|
+
Results.puts '-> Start Archiving...'.green
|
34
|
+
platform_archive_paths = Hash[platforms.map do |platform|
|
35
|
+
archive_paths = compute_archive_paths(platform, ts, configuration, build_library_for_distribution)
|
36
|
+
[platform.name, archive_paths]
|
37
|
+
end]
|
38
|
+
return if platform_archive_paths.values.flatten.empty?
|
39
|
+
|
40
|
+
output = Hash[pod_targets.map do |key, targets|
|
41
|
+
products = targets.map do |target|
|
42
|
+
Product.new(target, product_dir, root.parent, platform_archive_paths[target.platform.name])
|
43
|
+
end
|
44
|
+
ps = Products.new(key, products)
|
45
|
+
ps.create_bin_products
|
46
|
+
ps.add_pod_targets_file_accessors_paths
|
47
|
+
[key, ps.product_path]
|
48
|
+
end]
|
49
|
+
unless @no_clean
|
50
|
+
FileUtils.rm_rf(@app_root)
|
51
|
+
FileUtils.rm_rf(archives_dir)
|
52
|
+
end
|
53
|
+
output
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def compute_archive_paths(platform, pod_targets, configuration, build_library_for_distribution)
|
59
|
+
sdks = Constants.sdks(platform.name)
|
60
|
+
archive_paths_by_platform(sdks, platform, pod_targets, configuration, build_library_for_distribution)
|
61
|
+
end
|
62
|
+
|
63
|
+
def archive_paths_by_platform(sdks, platform, pod_targets, configuration, build_library_for_distribution)
|
64
|
+
sdks.map do |sdk|
|
65
|
+
args = if build_library_for_distribution
|
66
|
+
%w[BUILD_LIBRARY_FOR_DISTRIBUTION=YES]
|
67
|
+
else
|
68
|
+
[]
|
69
|
+
end
|
70
|
+
args += %W[-destination generic/platform=#{Constants::SDK_DESTINATION[sdk]}]
|
71
|
+
args += %W[-configuration #{configuration}] unless configuration.nil?
|
72
|
+
args += %W[-sdk #{sdk}]
|
73
|
+
pod_project_path = File.expand_path('./Pods/Pods.xcodeproj', @app_root)
|
74
|
+
archive_root = archives_dir.join(sdk.to_s)
|
75
|
+
archive_path = archive_root.join('Pods-App.xcarchive')
|
76
|
+
error = XcodeBuild.archive?(args, pod_project_path, "Pods-App-#{platform.string_name}", archive_path)
|
77
|
+
break if @fail_fast && error
|
78
|
+
next if error
|
79
|
+
|
80
|
+
print_pod_archive_infos(sdk, archive_path)
|
81
|
+
library_targets = pod_targets.select(&:build_as_library?)
|
82
|
+
library_targets.each do |target|
|
83
|
+
rename_library_product_name(target, archive_path)
|
84
|
+
archive_headers_path = archive_root.join(target.pod_name)
|
85
|
+
link_headers(target, archive_headers_path)
|
86
|
+
end
|
87
|
+
archive_path
|
88
|
+
end.compact
|
89
|
+
end
|
90
|
+
|
91
|
+
def rename_library_product_name(target, archive_path)
|
92
|
+
return unless target.build_as_library?
|
93
|
+
|
94
|
+
full_archive_path = archive_path.join('Products/usr/local/lib')
|
95
|
+
full_product_path = full_archive_path.join(target.static_library_name)
|
96
|
+
scope_suffix = target.scope_suffix
|
97
|
+
return unless full_product_path.exist? && scope_suffix && target.label.end_with?(scope_suffix)
|
98
|
+
|
99
|
+
label = Utils.remove_target_scope_suffix(target.label, scope_suffix)
|
100
|
+
new_full_archive_path = full_archive_path.join("lib#{label}.a")
|
101
|
+
File.rename(full_product_path, new_full_archive_path)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Creates the link to the headers of the Pod in the sandbox.
|
105
|
+
#
|
106
|
+
# @return [void]
|
107
|
+
#
|
108
|
+
def link_headers(target, product_path)
|
109
|
+
Pod::UI.message '- Linking headers' do
|
110
|
+
# When integrating Pod as frameworks, built Pods are built into
|
111
|
+
# frameworks, whose headers are included inside the built
|
112
|
+
# framework. Those headers do not need to be linked from the
|
113
|
+
# sandbox.
|
114
|
+
next if target.build_as_framework? && target.should_build?
|
115
|
+
|
116
|
+
sandbox = Pod::Sandbox.new(product_path)
|
117
|
+
build_headers = ProjectGen::HeadersStore.new(sandbox, '', :public)
|
118
|
+
pod_target_header_mappings = target.header_mappings_by_file_accessor.values
|
119
|
+
public_header_mappings = target.public_header_mappings_by_file_accessor.values
|
120
|
+
headers = pod_target_header_mappings + public_header_mappings
|
121
|
+
headers.uniq.each do |header_mappings|
|
122
|
+
header_mappings.each do |namespaced_path, files|
|
123
|
+
hs = build_headers.add_files('', files)
|
124
|
+
build_headers.add_files(namespaced_path, hs, ln: true)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
root_name = Pod::Specification.root_name(target.pod_name)
|
128
|
+
pod_dir = target.sandbox.sources_root.join(root_name)
|
129
|
+
module_headers = pod_dir.join(Constants::COPY_LIBRARY_SWIFT_HEADERS)
|
130
|
+
module_paths = build_headers.add_files(root_name, module_headers.children) if module_headers.exist?
|
131
|
+
module_paths
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
# Prints the list of specs & pod cache dirs for a single pod name.
|
136
|
+
#
|
137
|
+
# This output is valid YAML so it can be parsed with 3rd party tools
|
138
|
+
#
|
139
|
+
def print_pod_archive_infos(sdk, archive_path)
|
140
|
+
Results.puts(" - Archive: #{sdk}")
|
141
|
+
Results.puts(" path: #{archive_path}")
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -1,10 +1,93 @@
|
|
1
|
-
require 'cocoapods/validator'
|
2
|
-
require 'cocoapods-project-gen/gen/swift_module_helper'
|
3
1
|
require 'fileutils'
|
4
2
|
|
5
3
|
module ProjectGen
|
6
|
-
|
4
|
+
autoload :PodDirCopyCleaner, 'cocoapods-project-gen/gen/pod/pod_copy_cleaner'
|
5
|
+
|
6
|
+
class ProjectGenerator
|
7
|
+
require 'cocoapods-project-gen/gen/pod/swift_module_helper'
|
8
|
+
require 'cocoapods-project-gen/gen/pod/project_gen_helper'
|
9
|
+
|
7
10
|
include ProjectGen::SwiftModule
|
11
|
+
include ProjectGen::Helper
|
12
|
+
include Pod::Config::Mixin
|
13
|
+
|
14
|
+
# !@group results
|
15
|
+
|
16
|
+
attr_reader :results
|
17
|
+
#-------------------------------------------------------------------------#
|
18
|
+
|
19
|
+
# @!group Configuration
|
20
|
+
|
21
|
+
# When multiple dependencies with different sources, use latest.
|
22
|
+
#
|
23
|
+
attr_accessor :use_latest
|
24
|
+
|
25
|
+
# @return [String] The SWIFT_VERSION that should be used to validate the pod. This is set by passing the
|
26
|
+
# `--swift-version` parameter during validation.
|
27
|
+
#
|
28
|
+
attr_accessor :swift_version
|
29
|
+
# @return [Boolean] whether the linter should not clean up temporary files
|
30
|
+
# for inspection.
|
31
|
+
#
|
32
|
+
attr_accessor :no_clean
|
33
|
+
|
34
|
+
# @return [Boolean] whether the linter should fail as soon as the first build
|
35
|
+
# variant causes an error. Helpful for i.e. multi-platforms specs,
|
36
|
+
# specs with subspecs.
|
37
|
+
#
|
38
|
+
attr_accessor :fail_fast
|
39
|
+
|
40
|
+
# @return [Boolean] whether the validation should be performed against the root of
|
41
|
+
# the podspec instead to its original source.
|
42
|
+
#
|
43
|
+
#
|
44
|
+
attr_accessor :local
|
45
|
+
alias local? local
|
46
|
+
|
47
|
+
# @return [Boolean] Whether the validator should fail on warnings, or only on errors.
|
48
|
+
#
|
49
|
+
attr_accessor :allow_warnings
|
50
|
+
|
51
|
+
# @return [String] name of the subspec to check, if nil all subspecs are checked.
|
52
|
+
#
|
53
|
+
attr_accessor :only_subspecs
|
54
|
+
|
55
|
+
# @return [Boolean] Whether frameworks should be used for the installation.
|
56
|
+
#
|
57
|
+
attr_accessor :use_frameworks
|
58
|
+
|
59
|
+
# @return [Boolean] Whether modular headers should be used for the installation.
|
60
|
+
#
|
61
|
+
attr_accessor :use_modular_headers
|
62
|
+
|
63
|
+
# @return [Boolean] Whether static frameworks should be used for the installation.
|
64
|
+
#
|
65
|
+
attr_accessor :use_static_frameworks
|
66
|
+
|
67
|
+
# @return [String] A glob for podspecs to be used during building of
|
68
|
+
# the local Podfile via :path.
|
69
|
+
#
|
70
|
+
attr_accessor :include_podspecs
|
71
|
+
|
72
|
+
# @return [String] A glob for podspecs to be used during building of
|
73
|
+
# the local Podfile via :podspec.
|
74
|
+
#
|
75
|
+
attr_accessor :external_podspecs
|
76
|
+
|
77
|
+
# !@group Helpers
|
78
|
+
|
79
|
+
# @return [Array<String>] an array of source URLs used to create the
|
80
|
+
# {Podfile} used in the linting process
|
81
|
+
#
|
82
|
+
attr_reader :source_urls
|
83
|
+
|
84
|
+
# @return configuration
|
85
|
+
#
|
86
|
+
attr_accessor :configuration
|
87
|
+
|
88
|
+
#-------------------------------------------------------------------------#
|
89
|
+
# @return [Boolean]
|
90
|
+
#
|
8
91
|
|
9
92
|
# Initialize a new instance
|
10
93
|
#
|
@@ -26,168 +109,136 @@ module ProjectGen
|
|
26
109
|
#
|
27
110
|
# @param [Boolean] Whether modular headers should be used for the installation.
|
28
111
|
#
|
29
|
-
def self.new_from_local(podspecs, source_urls, platforms = [], product_type = :framework, configuration = :release, swift_version = nil, use_modular_headers: false)
|
30
|
-
generator = new(
|
31
|
-
generator.local =
|
32
|
-
generator.no_subspecs
|
33
|
-
generator.
|
112
|
+
def self.new_from_local(podspecs = [], source_urls = [Pod::TrunkSource::TRUNK_REPO_URL], platforms = [], product_type = :framework, configuration = :release, swift_version = nil, use_modular_headers: false)
|
113
|
+
generator = new(source_urls, platforms)
|
114
|
+
generator.local = true
|
115
|
+
generator.no_subspecs = true
|
116
|
+
generator.only_subspecs = nil
|
34
117
|
generator.no_clean = false
|
35
118
|
generator.allow_warnings = true
|
36
119
|
generator.use_frameworks = product_type == :dynamic_framework
|
37
120
|
generator.use_static_frameworks = product_type == :framework
|
38
|
-
generator.
|
39
|
-
generator.external_podspecs = podspecs.drop(1)
|
121
|
+
generator.include_podspecs = podspecs
|
40
122
|
generator.configuration = configuration
|
41
|
-
generator.skip_tests = true
|
42
123
|
generator.use_modular_headers = use_modular_headers
|
43
|
-
generator.swift_version = swift_version
|
124
|
+
generator.swift_version = swift_version
|
44
125
|
generator
|
45
126
|
end
|
46
127
|
|
128
|
+
# Initialize a new instance
|
129
|
+
#
|
130
|
+
# @param [Array<String>] source_urls
|
131
|
+
# the Source URLs to use in creating a {Podfile}.
|
132
|
+
#
|
133
|
+
# @param [Array<String>] platforms
|
134
|
+
# the platforms to lint.
|
135
|
+
#
|
136
|
+
def initialize(source_urls, platforms = [])
|
137
|
+
@source_urls = source_urls.map { |url| config.sources_manager.source_with_name_or_url(url) }.map(&:url)
|
138
|
+
@platforms = platforms.map do |platform|
|
139
|
+
result = case platform.to_s.downcase
|
140
|
+
# Platform doesn't recognize 'macos' as being the same as 'osx' when initializing
|
141
|
+
when 'macos' then Pod::Platform.macos
|
142
|
+
else Pod::Platform.new(platform, nil)
|
143
|
+
end
|
144
|
+
unless Constants.valid_platform?(result)
|
145
|
+
raise Informative, "Unrecognized platform `#{platform}`. Valid platforms: #{VALID_PLATFORMS.join(', ')}"
|
146
|
+
end
|
147
|
+
|
148
|
+
result
|
149
|
+
end
|
150
|
+
@allow_warnings = true
|
151
|
+
@use_frameworks = true
|
152
|
+
@use_latest = true
|
153
|
+
end
|
154
|
+
|
47
155
|
# Create app project
|
48
|
-
#
|
156
|
+
#
|
49
157
|
# @param [String, Pathname] dir the temporary directory used by the Gen.
|
50
158
|
#
|
51
|
-
# @param [block<
|
52
|
-
#
|
53
|
-
def generate!(
|
54
|
-
|
55
|
-
@results =
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
159
|
+
# @param [block<platforms, pod_targets, valid>] &block the block to execute inside the lock.
|
160
|
+
#
|
161
|
+
def generate!(work_dir, &block)
|
162
|
+
@project_gen_dir = Pathname(work_dir)
|
163
|
+
@results = Results.new
|
164
|
+
unless config.silent?
|
165
|
+
podspecs.each do |spec|
|
166
|
+
subspecs = determine_subspecs[spec]
|
167
|
+
if subspecs && !subspecs.empty?
|
168
|
+
subspecs.each { |s| Results.puts " -> #{s}\r\n" }
|
169
|
+
else
|
170
|
+
Results.puts " -> #{spec.name}\r\n"
|
171
|
+
end
|
172
|
+
end
|
62
173
|
end
|
63
|
-
@validation_dir = dir
|
64
|
-
Pod::UI.print " -> #{a_spec ? a_spec.name : file.basename}\r" unless config.silent?
|
65
174
|
$stdout.flush
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
175
|
+
perform_linting
|
176
|
+
platforms, pod_targets, valid = install
|
177
|
+
@results.print_results
|
178
|
+
block.call(platforms, pod_targets, @clean, @fail_fast) if !block.nil? && valid
|
70
179
|
end
|
71
180
|
|
72
|
-
|
73
|
-
|
181
|
+
# @return [Pathname] the temporary directory used by the linter.
|
182
|
+
#
|
183
|
+
def project_gen_dir
|
184
|
+
@project_gen_dir ||= Pathname(Dir.mktmpdir(['cocoapods-project-gen-', "-#{spec.name}"]))
|
74
185
|
end
|
75
186
|
|
76
187
|
private
|
77
188
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
85
|
-
platforms = send(:platforms_to_lint, spec)
|
86
|
-
valid = platforms.send(fail_fast ? :all? : :each) do |platform|
|
87
|
-
Pod::UI.message "\n\n#{spec} - Analyzing on #{platform} platform.".green.reversed
|
88
|
-
@consumer = spec.consumer(platform)
|
89
|
-
c_method = %i[setup_validation_environment create_app_project handle_local_pod
|
90
|
-
check_file_patterns install_pod validate_swift_version
|
91
|
-
add_app_project_import validate_vendored_dynamic_frameworks]
|
189
|
+
def install
|
190
|
+
podspec = podspecs.find(&:non_library_specification?)
|
191
|
+
if podspec
|
192
|
+
error('spec', "Validating a non library spec (`#{podspec.name}`) is not supported.")
|
193
|
+
[determine_platforms, specs_for_pods, false]
|
194
|
+
else
|
92
195
|
begin
|
93
|
-
|
196
|
+
setup_gen_environment
|
197
|
+
create_app_project
|
198
|
+
download_or_copy_pod
|
199
|
+
install_pod
|
200
|
+
validate_swift_version
|
201
|
+
add_app_project_import
|
202
|
+
validate_vendored_dynamic_frameworks
|
94
203
|
valid = validated?
|
204
|
+
results.note('Project gen', 'finish!') if valid
|
205
|
+
[determine_platforms, specs_for_pods, valid]
|
206
|
+
rescue StandardError => e
|
207
|
+
message = e.to_s
|
208
|
+
message << "\n" << e.backtrace.join("\n") << "\n" if config.verbose?
|
209
|
+
error('unknown', "Encountered an unknown error (#{message}) during validation.")
|
210
|
+
[determine_platforms, specs_for_pods, false]
|
95
211
|
end
|
96
|
-
block.call(platform, pod_targets, valid) unless block&.nil?
|
97
|
-
return false if fail_fast && !valid
|
98
|
-
|
99
|
-
generate_subspec(spec, dir, &block) unless @no_subspecs
|
100
|
-
rescue StandardError => e
|
101
|
-
message = e.to_s
|
102
|
-
raise Pod::Informative, "Encountered an unknown error\n\n#{message})\n\n#{e.backtrace * "\n"}"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
def generate_subspec(spec, dir, &block)
|
107
|
-
spec.subspecs.reject(&:non_library_specification?).send(fail_fast ? :all? : :each) do |subspec|
|
108
|
-
@subspec_name = subspec.name
|
109
|
-
install(subspec, dir, &block)
|
110
212
|
end
|
111
213
|
end
|
112
214
|
|
113
|
-
def
|
114
|
-
sandbox = Pod::Sandbox.new(@
|
115
|
-
|
116
|
-
ts.supported_on_platform?(consumer.platform_name)
|
117
|
-
end.map(&:name)
|
118
|
-
podfile = podfile_from_spec(consumer.platform_name, deployment_target, use_frameworks, test_spec_names,
|
119
|
-
use_modular_headers, use_static_frameworks)
|
120
|
-
|
215
|
+
def download_or_copy_pod
|
216
|
+
sandbox = Pod::Sandbox.new(@project_gen_dir + 'Pods')
|
217
|
+
podfile = podfile_from_spec(use_frameworks, use_modular_headers, use_static_frameworks)
|
121
218
|
@installer = Pod::Installer.new(sandbox, podfile)
|
122
219
|
@installer.use_default_plugins = false
|
123
|
-
@installer.has_dependencies = !
|
124
|
-
%i[prepare resolve_dependencies
|
220
|
+
@installer.has_dependencies = podspecs.any? { |podspec| !podspec.all_dependencies.empty? }
|
221
|
+
%i[prepare resolve_dependencies install_pod_sources run_podfile_pre_install_hooks clean_pod_sources
|
222
|
+
write_lockfiles].each do |m|
|
125
223
|
case m
|
126
224
|
when :clean_pod_sources
|
127
|
-
copy_and_clean(sandbox)
|
128
|
-
|
225
|
+
ProjectGen::PodDirCopyCleaner.new(include_specifications).copy_and_clean(config.sandbox_root, sandbox)
|
226
|
+
include_specifications.each { |s| sandbox.development_pods.delete(s.name) }
|
129
227
|
@installer.send(m)
|
130
228
|
else
|
131
229
|
@installer.send(m)
|
132
230
|
next unless m == :resolve_dependencies
|
133
231
|
|
134
|
-
|
232
|
+
# local --> source in local
|
233
|
+
# no-local --> source from cdn
|
234
|
+
# external_podspecs --> source in cdn
|
235
|
+
# include_podspecs --> source in local
|
236
|
+
include_specifications.each do |spec|
|
237
|
+
sandbox.store_local_path(spec.name, spec.defined_in_file, Utils.absolute?(spec.defined_in_file))
|
238
|
+
end
|
135
239
|
end
|
136
240
|
end
|
137
|
-
|
138
|
-
add_swift_library_compatibility_header(library_targets)
|
139
|
-
@file_accessor = pod_targets.flat_map(&:file_accessors).find do |fa|
|
140
|
-
fa.spec.name == consumer.spec.name
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
def podspecs
|
145
|
-
ps = [file]
|
146
|
-
ps += external_podspecs.map { |pa| Pathname.new(pa) } if external_podspecs
|
147
|
-
ps += include_podspecs.map { |pa| Pathname.new(pa) } if include_podspecs
|
148
|
-
ps.uniq.map { |path| Pod::Specification.from_file(path) }
|
149
|
-
end
|
150
|
-
|
151
|
-
# @return [Bool]
|
152
|
-
#
|
153
|
-
def absolute?(path)
|
154
|
-
Pathname(path).absolute? || path.to_s.start_with?('~')
|
155
|
-
end
|
156
|
-
|
157
|
-
def group_subspecs_by_platform(spec)
|
158
|
-
specs_by_platform = {}
|
159
|
-
[spec, *spec.recursive_subspecs].each do |ss|
|
160
|
-
ss.available_platforms.each do |platform|
|
161
|
-
specs_by_platform[platform] ||= []
|
162
|
-
specs_by_platform[platform] << ss
|
163
|
-
end
|
164
|
-
end
|
165
|
-
specs_by_platform
|
166
|
-
end
|
167
|
-
|
168
|
-
def copy(source, destination, specs_by_platform)
|
169
|
-
path_list = Pod::Sandbox::PathList.new(source)
|
170
|
-
file_accessors = specs_by_platform.flat_map do |platform, specs|
|
171
|
-
specs.flat_map { |spec| Pod::Sandbox::FileAccessor.new(path_list, spec.consumer(platform)) }
|
172
|
-
end
|
173
|
-
used_files = Pod::Sandbox::FileAccessor.all_files(file_accessors)
|
174
|
-
used_files.each do |path|
|
175
|
-
path = Pathname(path)
|
176
|
-
n_path = destination.join(path.relative_path_from(source))
|
177
|
-
n_path.dirname.mkpath
|
178
|
-
FileUtils.cp_r(path, n_path.dirname)
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
def copy_and_clean(sandbox)
|
183
|
-
podspecs.each do |spec|
|
184
|
-
destination = config.sandbox_root + spec.name
|
185
|
-
source = sandbox.pod_dir(spec.name)
|
186
|
-
specs_by_platform = group_subspecs_by_platform(spec)
|
187
|
-
destination.parent.mkpath
|
188
|
-
FileUtils.rm_rf(destination)
|
189
|
-
copy(source, destination, specs_by_platform)
|
190
|
-
end
|
241
|
+
add_swift_library_compatibility_header(@installer.pod_targets)
|
191
242
|
end
|
192
243
|
end
|
193
244
|
end
|