cocoapods-project-gen 0.1.0 → 0.2.3
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.
- 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
|