cocoapods-generate 1.4.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.md +9 -0
- data/README.md +15 -1
- data/VERSION +1 -1
- data/lib/cocoapods/command/gen.rb +6 -4
- data/lib/cocoapods/generate/configuration.rb +46 -12
- data/lib/cocoapods/generate/installer.rb +145 -76
- data/lib/cocoapods/generate/podfile_generator.rb +123 -36
- data/lib/cocoapods_plugin.rb +1 -1
- metadata +23 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f21262cc4824565c6d34162cb6e20312ddfa2d0ff3331c7b58fac561f2432e2f
|
4
|
+
data.tar.gz: 72fdfa72cca275404202ddbffcf6805fa22598b1897a379b49a77586a328cb52
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 523fe6d21ea621a6c3035a59c950beea558cfbaaac1dcba17ba23ee999103e195845413bbf62a400baa8d3aff031d11a7980b4e2fe5d5e315fce370726be890d
|
7
|
+
data.tar.gz: 2229639a9d3ef51e44aa73ec7b3347fc049421da8ed4430e40d03ac984671ea78ebb594cb027afca83b184c25c052642a7319212980f7607ebb795583c6f12b4
|
data/LICENSE.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2019
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
6
|
+
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
8
|
+
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -47,6 +47,7 @@ Usage:
|
|
47
47
|
|
48
48
|
Options:
|
49
49
|
|
50
|
+
--allow-root Allows CocoaPods to run as root
|
50
51
|
--silent Show nothing
|
51
52
|
--verbose Show more debugging information
|
52
53
|
--no-ansi Show output without ANSI codes
|
@@ -62,6 +63,8 @@ Options:
|
|
62
63
|
be used
|
63
64
|
--use-libraries Whether to use libraries instead of
|
64
65
|
frameworks
|
66
|
+
--generate-multiple-pod-projects Whether to generate multiple Xcode projects
|
67
|
+
--incremental-installation Whether to use incremental installation
|
65
68
|
--gen-directory=PATH Path to generate workspaces in
|
66
69
|
--auto-open Whether to automatically open the generated
|
67
70
|
workspaces
|
@@ -69,17 +72,26 @@ Options:
|
|
69
72
|
before generating
|
70
73
|
--app-host-source-dir=DIR A directory containing sources to use for
|
71
74
|
the app host
|
72
|
-
--sources=SOURCE1,SOURCE2 The sources from which to pull
|
75
|
+
--sources=SOURCE1,SOURCE2 The sources from which to pull dependent
|
73
76
|
pods (defaults to all repos in the podfile
|
74
77
|
if using the podfile, else all available
|
75
78
|
repos). Can be a repo name or URL. Multiple
|
76
79
|
sources must be comma-delimited.
|
80
|
+
--local-sources=SOURCE1,SOURCE2 Paths from which to find local podspecs for
|
81
|
+
transitive dependencies. Multiple
|
82
|
+
local-sources must be comma-delimited.
|
83
|
+
--platforms=ios,macos Limit to specific platforms. Default is all
|
84
|
+
platforms supported by the podspec.
|
85
|
+
Multiple platforms must be comma-delimited.
|
77
86
|
--repo-update Force running `pod repo update` before
|
78
87
|
install
|
79
88
|
--use-default-plugins Whether installation should activate
|
80
89
|
default plugins
|
81
90
|
--deterministic-uuids Whether installation should use
|
82
91
|
deterministic UUIDs for pods projects
|
92
|
+
--disable-input-output-paths Whether to disable the input & output paths
|
93
|
+
of the CocoaPods script phases (Copy
|
94
|
+
Frameworks & Copy Resources)
|
83
95
|
--share-schemes-for-development-pods Whether installation should share schemes
|
84
96
|
for development pods
|
85
97
|
--warn-for-multiple-pod-sources Whether installation should warn when a pod
|
@@ -89,6 +101,8 @@ Options:
|
|
89
101
|
modules, as if `use_modular_headers!` were
|
90
102
|
specified. Will error if both this option
|
91
103
|
and a podfile are specified
|
104
|
+
--single-workspace Whether to produce a single workspace for
|
105
|
+
all podspecs specified.
|
92
106
|
```
|
93
107
|
<!-- end cli usage -->
|
94
108
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
2.1.0
|
@@ -64,8 +64,8 @@ module Pod
|
|
64
64
|
# even if there are multiple podspecs
|
65
65
|
update_sources if configuration.repo_update?
|
66
66
|
|
67
|
-
Generate::PodfileGenerator.new(configuration).
|
68
|
-
Generate::Installer.new(configuration,
|
67
|
+
Generate::PodfileGenerator.new(configuration).podfiles_by_specs.each do |specs, podfile|
|
68
|
+
Generate::Installer.new(configuration, specs, podfile).install!
|
69
69
|
end
|
70
70
|
|
71
71
|
remove_warnings(UI.warnings)
|
@@ -86,10 +86,12 @@ module Pod
|
|
86
86
|
path = dir + '.gen_config.yml'
|
87
87
|
next unless path.file?
|
88
88
|
Pod::Generate::Configuration.from_file(path)
|
89
|
-
end
|
89
|
+
end.compact
|
90
|
+
|
91
|
+
options.delete(:podspec_paths) if options[:podspec_paths].empty? && config_hashes.any? { |h| h.include?(:podspec_paths) }
|
90
92
|
|
91
93
|
env = Generate::Configuration.from_env(ENV)
|
92
|
-
config_hashes
|
94
|
+
config_hashes = [env] + config_hashes
|
93
95
|
config_hashes << options
|
94
96
|
|
95
97
|
configuration = config_hashes.compact.each_with_object({}) { |e, h| h.merge!(e) }
|
@@ -169,7 +169,7 @@ module Pod
|
|
169
169
|
->(paths) { ('paths do not exist' unless paths.all? { |p| p.is_a?(URI) || p.exist? }) },
|
170
170
|
->(paths) { paths && paths.map { |path| path.to_s =~ %r{https?://} ? URI(path) : Pathname(path).expand_path } }
|
171
171
|
option :podspecs, ArrayOf.new(Pod::Specification),
|
172
|
-
'self.class.podspecs_from_paths(podspec_paths)',
|
172
|
+
'self.class.podspecs_from_paths(podspec_paths, gen_directory)',
|
173
173
|
nil,
|
174
174
|
nil,
|
175
175
|
->(specs) { 'no podspecs found' if specs.empty? },
|
@@ -178,16 +178,33 @@ module Pod
|
|
178
178
|
# installer options
|
179
179
|
option :sources, ArrayOf.new(String),
|
180
180
|
'if use_podfile && podfile then ::Pod::Installer::Analyzer.new(:sandbox, podfile).sources.map(&:url) else pod_config.sources_manager.all.map(&:url) end',
|
181
|
-
'The sources from which to pull
|
181
|
+
'The sources from which to pull dependent pods (defaults to all repos in the podfile if using the podfile, else all available repos). Can be a repo name or URL. Multiple sources must be comma-delimited.',
|
182
182
|
'SOURCE1,SOURCE2',
|
183
183
|
->(_) { nil },
|
184
184
|
->(sources) { Array(sources).flat_map { |s| s.split(',') } }
|
185
|
+
option :local_sources, ArrayOf.new(String),
|
186
|
+
[],
|
187
|
+
'Paths from which to find local podspecs for transitive dependencies. Multiple local-sources must be comma-delimited.',
|
188
|
+
'SOURCE1,SOURCE2',
|
189
|
+
->(_) { nil },
|
190
|
+
->(local_sources) { Array(local_sources).flat_map { |s| s.split(',') } }
|
191
|
+
option :platforms, ArrayOf.new(String),
|
192
|
+
nil,
|
193
|
+
'Limit to specific platforms. Default is all platforms supported by the podspec. Multiple platforms must be comma-delimited.',
|
194
|
+
'ios,macos',
|
195
|
+
lambda { |platforms|
|
196
|
+
valid_platforms = Platform.all.map { |p| p.string_name.downcase }
|
197
|
+
valid_platforms unless (platforms - valid_platforms).empty?
|
198
|
+
}, # validates platforms is a subset of Platform.all
|
199
|
+
->(platforms) { Array(platforms).flat_map { |s| s.split(',') } }
|
185
200
|
option :repo_update, BOOLEAN, 'false', 'Force running `pod repo update` before install', nil, nil, coerce_to_bool
|
186
201
|
option :use_default_plugins, BOOLEAN, 'false', 'Whether installation should activate default plugins', nil, nil, coerce_to_bool
|
187
|
-
option :deterministic_uuids, BOOLEAN, 'false', 'Whether installation should use deterministic UUIDs for pods projects', nil, nil, coerce_to_bool
|
188
|
-
option :
|
189
|
-
option :
|
202
|
+
option :deterministic_uuids, BOOLEAN, '(use_podfile && podfile) ? podfile.installation_options.deterministic_uuids : false', 'Whether installation should use deterministic UUIDs for pods projects', nil, nil, coerce_to_bool
|
203
|
+
option :disable_input_output_paths, BOOLEAN, '(use_podfile && podfile) ? podfile.installation_options.disable_input_output_paths : false', 'Whether to disable the input & output paths of the CocoaPods script phases (Copy Frameworks & Copy Resources)', nil, nil, coerce_to_bool
|
204
|
+
option :share_schemes_for_development_pods, [TrueClass, FalseClass, Array], '(use_podfile && podfile) ? podfile.installation_options.share_schemes_for_development_pods : true', 'Whether installation should share schemes for development pods', nil, nil
|
205
|
+
option :warn_for_multiple_pod_sources, BOOLEAN, '(use_podfile && podfile) ? podfile.installation_options.warn_for_multiple_pod_sources : false', 'Whether installation should warn when a pod is found in multiple sources', nil, nil, coerce_to_bool
|
190
206
|
option :use_modular_headers, BOOLEAN, 'false', 'Whether the target should be generated as a clang module, treating dependencies as modules, as if `use_modular_headers!` were specified. Will error if both this option and a podfile are specified', nil, nil, coerce_to_bool
|
207
|
+
option :single_workspace, BOOLEAN, 'false', 'Whether to produce a single workspace for all podspecs specified.', nil, nil, coerce_to_bool
|
191
208
|
|
192
209
|
options.freeze
|
193
210
|
options.each do |o|
|
@@ -287,12 +304,13 @@ module Pod
|
|
287
304
|
end << ' }'
|
288
305
|
end
|
289
306
|
|
290
|
-
# @return [Pathname] the directory for installation of the generated workspace
|
307
|
+
# @return [Pathname] the directory for installation of the generated workspace.
|
291
308
|
#
|
292
|
-
# @param [
|
309
|
+
# @param [Array<Specification>] specs The specs to get a directory name for.
|
293
310
|
#
|
294
|
-
def
|
295
|
-
|
311
|
+
def gen_dir_for_specs(specs)
|
312
|
+
basename = specs.count == 1 ? specs.first.name : 'Workspace'
|
313
|
+
gen_directory.join(basename)
|
296
314
|
end
|
297
315
|
|
298
316
|
# @return [Boolean] whether gen should install with dynamic frameworks
|
@@ -301,13 +319,29 @@ module Pod
|
|
301
319
|
!use_libraries?
|
302
320
|
end
|
303
321
|
|
322
|
+
# @return [String] The project name to use for generating this workspace.
|
323
|
+
#
|
324
|
+
# @param [Array<Specification>] specs
|
325
|
+
# the specifications to generate project name for.
|
326
|
+
#
|
327
|
+
def project_name_for_specs(specs)
|
328
|
+
project_name = specs.count == 1 ? +specs.first.name.dup : +'Workspace'
|
329
|
+
# When using multiple Xcode project the project name will collide with the actual .xcodeproj meant for the pod
|
330
|
+
# that we are generating the workspace for.
|
331
|
+
project_name << 'Sample' if generate_multiple_pod_projects? && specs.count == 1
|
332
|
+
project_name
|
333
|
+
end
|
334
|
+
|
304
335
|
# @return [Array<Specification>] the podspecs found at the given paths.
|
305
336
|
# This method will download specs from URLs and traverse a directory's children.
|
306
337
|
#
|
307
338
|
# @param [Array<Pathname,URI>] paths
|
308
339
|
# the paths to search for podspecs
|
309
340
|
#
|
310
|
-
|
341
|
+
# @param [Pathname] gen_directory
|
342
|
+
# the directory that the gen installation would occur into.
|
343
|
+
#
|
344
|
+
def self.podspecs_from_paths(paths, gen_directory)
|
311
345
|
paths = [Pathname('.')] if paths.empty?
|
312
346
|
paths.flat_map do |path|
|
313
347
|
if path.is_a?(URI)
|
@@ -323,9 +357,9 @@ module Pod
|
|
323
357
|
$ERROR_INFO
|
324
358
|
end
|
325
359
|
elsif path.directory?
|
326
|
-
glob = Pathname.glob(path + '
|
360
|
+
glob = Pathname.glob(path.expand_path + '**/*.podspec{.json,}').select { |f| f.relative_path_from(gen_directory).to_s.start_with?('..') }
|
327
361
|
next StandardError.new "no specs found in #{UI.path path}" if glob.empty?
|
328
|
-
glob.map { |f| Pod::Specification.from_file(f) }
|
362
|
+
glob.map { |f| Pod::Specification.from_file(f) }.sort_by(&:name)
|
329
363
|
else
|
330
364
|
Pod::Specification.from_file(path)
|
331
365
|
end
|
@@ -4,36 +4,24 @@ module Pod
|
|
4
4
|
# given a configuration and a generated podfile.
|
5
5
|
#
|
6
6
|
class Installer
|
7
|
-
# A subclass of the CocoaPods installer that vends analyzer classes
|
8
|
-
# that skip validating podfiles
|
9
|
-
#
|
10
|
-
class InstallerNoValidatePodfile < ::Pod::Installer
|
11
|
-
def create_analyzer(*)
|
12
|
-
super.tap do |analyzer|
|
13
|
-
def analyzer.validate_podfile!; end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
private_constant :InstallerNoValidatePodfile
|
18
|
-
|
19
7
|
# @return [Configuration]
|
20
8
|
# the configuration to use when installing
|
21
9
|
#
|
22
10
|
attr_reader :configuration
|
23
11
|
|
24
|
-
# @return [Specification]
|
12
|
+
# @return [Array<Specification>]
|
25
13
|
# the spec whose workspace is being created
|
26
14
|
#
|
27
|
-
attr_reader :
|
15
|
+
attr_reader :specs
|
28
16
|
|
29
17
|
# @return [Podfile]
|
30
18
|
# the podfile to install
|
31
19
|
#
|
32
20
|
attr_reader :podfile
|
33
21
|
|
34
|
-
def initialize(configuration,
|
22
|
+
def initialize(configuration, specs, podfile)
|
35
23
|
@configuration = configuration
|
36
|
-
@
|
24
|
+
@specs = specs
|
37
25
|
@podfile = podfile
|
38
26
|
end
|
39
27
|
|
@@ -49,7 +37,7 @@ module Pod
|
|
49
37
|
# @return [void]
|
50
38
|
#
|
51
39
|
def install!
|
52
|
-
UI.title "Generating
|
40
|
+
UI.title "Generating workspace in #{UI.path install_directory}" do
|
53
41
|
clean! if configuration.clean?
|
54
42
|
install_directory.mkpath
|
55
43
|
|
@@ -63,15 +51,25 @@ module Pod
|
|
63
51
|
|
64
52
|
installer = nil
|
65
53
|
UI.section 'Installing...' do
|
66
|
-
configuration.pod_config.with_changes(installation_root: install_directory, podfile: podfile,
|
67
|
-
|
54
|
+
configuration.pod_config.with_changes(installation_root: install_directory, podfile: podfile,
|
55
|
+
lockfile: configuration.lockfile, sandbox: nil,
|
56
|
+
sandbox_root: install_directory + 'Pods',
|
57
|
+
podfile_path: podfile.defined_in_file,
|
58
|
+
silent: !configuration.pod_config.verbose?, verbose: false,
|
59
|
+
lockfile_path: nil) do
|
60
|
+
installer = ::Pod::Installer.new(configuration.pod_config.sandbox, podfile, configuration.lockfile)
|
68
61
|
installer.use_default_plugins = configuration.use_default_plugins
|
69
62
|
installer.install!
|
70
63
|
end
|
71
64
|
end
|
72
65
|
|
73
66
|
UI.section 'Performing post-installation steps' do
|
74
|
-
|
67
|
+
should_perform_post_install = if installer.respond_to?(:generated_aggregate_targets) # CocoaPods 1.7.0
|
68
|
+
!installer.generated_aggregate_targets.empty?
|
69
|
+
else
|
70
|
+
true
|
71
|
+
end
|
72
|
+
perform_post_install_steps(open_app_project, installer) if should_perform_post_install
|
75
73
|
end
|
76
74
|
|
77
75
|
print_post_install_message
|
@@ -91,7 +89,7 @@ module Pod
|
|
91
89
|
end
|
92
90
|
|
93
91
|
def open_app_project(recreate: false)
|
94
|
-
app_project_path = install_directory.join("#{
|
92
|
+
app_project_path = install_directory.join("#{configuration.project_name_for_specs(specs)}.xcodeproj")
|
95
93
|
if !recreate && app_project_path.exist?
|
96
94
|
Xcodeproj::Project.open(app_project_path)
|
97
95
|
else
|
@@ -104,31 +102,47 @@ module Pod
|
|
104
102
|
# @return [Xcodeproj::Project]
|
105
103
|
#
|
106
104
|
def create_app_project
|
107
|
-
app_project = open_app_project(recreate:
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
105
|
+
app_project = open_app_project(recreate: !configuration.incremental_installation?)
|
106
|
+
|
107
|
+
platforms_by_spec = Hash[specs.map do |spec|
|
108
|
+
platforms = spec.available_platforms.flatten.reject do |platform|
|
109
|
+
!configuration.platforms.nil? && !configuration.platforms.include?(platform.string_name.downcase)
|
110
|
+
end
|
111
|
+
[spec, platforms]
|
112
|
+
end]
|
113
|
+
|
114
|
+
if platforms_by_spec.values.all?(&:empty?)
|
115
|
+
Pod::Command::Gen.help! Pod::StandardError.new "No available platforms for podspecs #{specs.map(&:name).to_sentence} match requested platforms: #{configuration.platforms}"
|
117
116
|
end
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
117
|
+
|
118
|
+
platforms_by_spec
|
119
|
+
.flat_map do |spec, platforms|
|
120
|
+
platforms.map do |platform|
|
121
|
+
consumer = spec.consumer(platform)
|
122
|
+
target_name = "App-#{Platform.string_name(consumer.platform_name)}"
|
123
|
+
next if app_project.targets.map(&:name).include? target_name
|
124
|
+
native_app_target = Pod::Generator::AppTargetHelper.add_app_target(app_project, consumer.platform_name,
|
125
|
+
deployment_target(consumer), target_name)
|
126
|
+
# Temporarily set Swift version to pass validator checks for pods which do not specify Swift version.
|
127
|
+
# It will then be re-set again within #perform_post_install_steps.
|
128
|
+
Pod::Generator::AppTargetHelper.add_swift_version(native_app_target, Pod::Validator::DEFAULT_SWIFT_VERSION)
|
129
|
+
native_app_target
|
126
130
|
end
|
127
|
-
|
128
|
-
|
131
|
+
end
|
132
|
+
.compact.uniq.tap do
|
133
|
+
app_project.recreate_user_schemes do |scheme, target|
|
134
|
+
installation_result = installation_result_from_target(target)
|
135
|
+
next unless installation_result
|
136
|
+
installation_result.test_native_targets.each do |test_native_target|
|
137
|
+
scheme.add_test_target(test_native_target)
|
138
|
+
end
|
129
139
|
end
|
130
|
-
|
140
|
+
end
|
141
|
+
.each do |target|
|
142
|
+
Xcodeproj::XCScheme.share_scheme(app_project.path.to_s, target.name) if target
|
143
|
+
end
|
131
144
|
app_project.save
|
145
|
+
app_project
|
132
146
|
end
|
133
147
|
|
134
148
|
def deployment_target(consumer)
|
@@ -144,8 +158,13 @@ module Pod
|
|
144
158
|
app_project.native_targets.each do |native_app_target|
|
145
159
|
remove_script_phase_from_target(native_app_target, 'Check Pods Manifest.lock')
|
146
160
|
|
147
|
-
|
148
|
-
|
161
|
+
spec_names = specs.map(&:name)
|
162
|
+
pod_targets = installer.pod_targets.select do |pt|
|
163
|
+
pt.platform.name == native_app_target.platform_name && spec_names.include?(pt.pod_name)
|
164
|
+
end
|
165
|
+
|
166
|
+
native_app_target.source_build_phase.clear
|
167
|
+
native_app_target.resources_build_phase.clear
|
149
168
|
|
150
169
|
if (app_host_source_dir = configuration.app_host_source_dir)
|
151
170
|
relative_app_host_source_dir = app_host_source_dir.relative_path_from(installer.sandbox.root)
|
@@ -164,16 +183,32 @@ module Pod
|
|
164
183
|
end
|
165
184
|
|
166
185
|
next
|
186
|
+
elsif file.to_s.end_with?('-Bridging-Header.h')
|
187
|
+
native_app_target.build_configurations.each do |bc|
|
188
|
+
if (old_bridging_header = bc.build_settings['SWIFT_OBJC_BRIDGING_HEADER'])
|
189
|
+
raise Informative, "Conflicting Swift ObjC bridging headers specified, got #{old_bridging_header} and #{relative_path}. Only one `-Bridging-Header.h` file may be specified in the app host source dir."
|
190
|
+
end
|
191
|
+
|
192
|
+
bc.build_settings['SWIFT_OBJC_BRIDGING_HEADER'] = relative_path.to_s
|
193
|
+
end
|
167
194
|
end
|
168
195
|
|
169
196
|
group = groups[relative_path.dirname]
|
170
197
|
source_file_ref = group.new_file(file.basename)
|
171
198
|
native_app_target.add_file_references([source_file_ref])
|
172
199
|
end
|
173
|
-
elsif Pod::Generator::AppTargetHelper.method(:add_app_project_import).arity == -5 # CocoaPods >= 1.6
|
174
|
-
Pod::Generator::AppTargetHelper.add_app_project_import(app_project, native_app_target, pod_target, pod_target.platform.name, native_app_target.name)
|
175
200
|
else
|
176
|
-
|
201
|
+
platform_name = Platform.string_name(native_app_target.platform_name)
|
202
|
+
group = group_for_platform_name(app_project, platform_name)
|
203
|
+
main_file_ref = group.files.find { |f| f.display_name == 'main.m' }
|
204
|
+
if main_file_ref.nil?
|
205
|
+
source_file = create_main_source_file(app_project, pod_targets, native_app_target.name)
|
206
|
+
group = app_project[group.name] || app_project.new_group(group.name, group.name)
|
207
|
+
source_file_ref = group.new_file(source_file)
|
208
|
+
native_app_target.add_file_references([source_file_ref])
|
209
|
+
else
|
210
|
+
native_app_target.add_file_references([main_file_ref])
|
211
|
+
end
|
177
212
|
end
|
178
213
|
|
179
214
|
# Set `PRODUCT_BUNDLE_IDENTIFIER`
|
@@ -183,21 +218,25 @@ module Pod
|
|
183
218
|
|
184
219
|
case native_app_target.platform_name
|
185
220
|
when :ios
|
186
|
-
make_ios_app_launchable(
|
221
|
+
make_ios_app_launchable(app_project, native_app_target)
|
187
222
|
end
|
188
223
|
|
189
|
-
Pod::
|
224
|
+
swift_version = pod_targets.map { |pt| Pod::Version.new(pt.swift_version) }.max.to_s
|
225
|
+
|
226
|
+
Pod::Generator::AppTargetHelper.add_swift_version(native_app_target, swift_version) unless swift_version.blank?
|
190
227
|
if installer.pod_targets.any? { |pt| pt.spec_consumers.any? { |c| c.frameworks.include?('XCTest') } }
|
191
228
|
Pod::Generator::AppTargetHelper.add_xctest_search_paths(native_app_target)
|
192
229
|
end
|
193
230
|
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
231
|
+
pod_targets.each do |pod_target|
|
232
|
+
result = installer.target_installation_results.pod_target_installation_results[pod_target.name]
|
233
|
+
share_scheme(result.native_target.project, pod_target.label)
|
234
|
+
pod_target.test_specs.each do |test_spec|
|
235
|
+
share_scheme(result.native_target.project, pod_target.test_target_label(test_spec))
|
236
|
+
end
|
237
|
+
pod_target.app_specs.each do |app_spec|
|
238
|
+
share_scheme(result.native_target.project, pod_target.app_target_label(app_spec))
|
198
239
|
end
|
199
|
-
elsif File.exist?(installer.pods_project.path + pod_target.label)
|
200
|
-
Xcodeproj::XCScheme.share_scheme(installer.pods_project.path, pod_target.label)
|
201
240
|
end
|
202
241
|
|
203
242
|
add_test_spec_schemes_to_app_scheme(installer, app_project)
|
@@ -221,25 +260,22 @@ module Pod
|
|
221
260
|
end
|
222
261
|
|
223
262
|
def add_test_spec_schemes_to_app_scheme(installer, app_project)
|
263
|
+
spec_root_names = Set.new(specs.map { |s| s.root.name })
|
264
|
+
|
224
265
|
test_native_targets =
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
.select { |installation_result| installation_result.target.pod_name == spec.root.name }
|
232
|
-
else
|
233
|
-
installer
|
234
|
-
.pod_targets
|
235
|
-
.select { |pod_target| pod_target.pod_name == spec.root.name }
|
236
|
-
end
|
266
|
+
installer
|
267
|
+
.target_installation_results
|
268
|
+
.pod_target_installation_results
|
269
|
+
.values
|
270
|
+
.flatten(1)
|
271
|
+
.select { |installation_result| spec_root_names.include?(installation_result.target.pod_name) }
|
237
272
|
.flat_map(&:test_native_targets)
|
238
273
|
.group_by(&:platform_name)
|
239
274
|
|
275
|
+
workspace_path = install_directory + (configuration.project_name_for_specs(specs) + '.xcworkspace')
|
240
276
|
Xcodeproj::Plist.write_to_path(
|
241
277
|
{ 'IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded' => false },
|
242
|
-
|
278
|
+
workspace_path.join('xcshareddata').tap(&:mkpath).join('WorkspaceSettings.xcsettings')
|
243
279
|
)
|
244
280
|
|
245
281
|
test_native_targets.each do |platform_name, test_targets|
|
@@ -255,7 +291,7 @@ module Pod
|
|
255
291
|
|
256
292
|
testable = Xcodeproj::XCScheme::TestAction::TestableReference.new(target)
|
257
293
|
testable.buildable_references.each do |buildable|
|
258
|
-
buildable.xml_element.attributes['ReferencedContainer'] =
|
294
|
+
buildable.xml_element.attributes['ReferencedContainer'] = "container:Pods/#{File.basename(target.project.path)}"
|
259
295
|
end
|
260
296
|
test_action.add_testable(testable)
|
261
297
|
end
|
@@ -264,9 +300,9 @@ module Pod
|
|
264
300
|
end
|
265
301
|
end
|
266
302
|
|
267
|
-
def make_ios_app_launchable(
|
303
|
+
def make_ios_app_launchable(app_project, native_app_target)
|
268
304
|
platform_name = Platform.string_name(native_app_target.platform_name)
|
269
|
-
generated_source_dir =
|
305
|
+
generated_source_dir = install_directory.join("App-#{platform_name}").tap(&:mkpath)
|
270
306
|
|
271
307
|
# Add `LaunchScreen.storyboard`
|
272
308
|
launch_storyboard = generated_source_dir.join('LaunchScreen.storyboard')
|
@@ -327,12 +363,17 @@ module Pod
|
|
327
363
|
Xcodeproj::Plist.write_to_path(info_plist_contents, info_plist_path)
|
328
364
|
|
329
365
|
native_app_target.build_configurations.each do |bc|
|
330
|
-
bc.build_settings['INFOPLIST_FILE'] = "${SRCROOT}/App
|
366
|
+
bc.build_settings['INFOPLIST_FILE'] = "${SRCROOT}/App-#{platform_name}/Info.plist"
|
331
367
|
end
|
332
368
|
|
333
|
-
group = app_project
|
334
|
-
group.new_file(info_plist_path)
|
335
|
-
|
369
|
+
group = group_for_platform_name(app_project, platform_name)
|
370
|
+
group.files.find { |f| f.display_name == 'Info.plist' } || group.new_file(info_plist_path)
|
371
|
+
launch_storyboard_file_ref = group.files.find { |f| f.display_name == 'LaunchScreen.storyboard' } || group.new_file(launch_storyboard)
|
372
|
+
native_app_target.resources_build_phase.add_file_reference(launch_storyboard_file_ref)
|
373
|
+
end
|
374
|
+
|
375
|
+
def group_for_platform_name(project, platform_name, should_create = true)
|
376
|
+
project.main_group.find_subpath("App-#{platform_name}", should_create)
|
336
377
|
end
|
337
378
|
|
338
379
|
def print_post_install_message
|
@@ -343,9 +384,37 @@ module Pod
|
|
343
384
|
Executable.execute_command 'open', [workspace_path]
|
344
385
|
end
|
345
386
|
else
|
346
|
-
UI.info "Open #{UI.path workspace_path} to work on
|
387
|
+
UI.info "Open #{UI.path workspace_path} to work on it!"
|
347
388
|
end
|
348
389
|
end
|
390
|
+
|
391
|
+
def share_scheme(project, scheme_name)
|
392
|
+
scheme = Xcodeproj::XCScheme.user_data_dir(project.path) + "#{scheme_name}.xcscheme"
|
393
|
+
return unless File.exist?(scheme)
|
394
|
+
Xcodeproj::XCScheme.share_scheme(project.path, scheme_name)
|
395
|
+
end
|
396
|
+
|
397
|
+
def create_main_source_file(project, pod_targets, name)
|
398
|
+
source_file = project.path.dirname.+("#{name}/main.m")
|
399
|
+
source_file.parent.mkpath
|
400
|
+
|
401
|
+
import_statements = pod_targets.map do |pod_target|
|
402
|
+
if pod_target.should_build? && pod_target.defines_module?
|
403
|
+
"@import #{pod_target.product_module_name};"
|
404
|
+
else
|
405
|
+
header_name = "#{pod_target.product_module_name}/#{pod_target.product_module_name}.h"
|
406
|
+
"#import <#{header_name}>" if pod_target.sandbox.public_headers.root.+(header_name).file?
|
407
|
+
end
|
408
|
+
end.compact
|
409
|
+
|
410
|
+
source_file.open('w') do |f|
|
411
|
+
f << import_statements.join("\n")
|
412
|
+
f << "\n" unless import_statements.empty?
|
413
|
+
f << "int main() {}\n"
|
414
|
+
end
|
415
|
+
|
416
|
+
source_file
|
417
|
+
end
|
349
418
|
end
|
350
419
|
end
|
351
420
|
end
|
@@ -14,36 +14,37 @@ module Pod
|
|
14
14
|
@configuration = configuration
|
15
15
|
end
|
16
16
|
|
17
|
-
# @return [Hash<Specification
|
18
|
-
# a hash of specifications to generated podfiles
|
17
|
+
# @return [Hash<Array<Specification>, Podfile>] the podfiles keyed by the specs that are part of each.
|
19
18
|
#
|
20
|
-
def
|
19
|
+
def podfiles_by_specs
|
20
|
+
return { configuration.podspecs => podfile_for_specs(configuration.podspecs) } if configuration.single_workspace?
|
21
21
|
Hash[configuration.podspecs.map do |spec|
|
22
|
-
[spec,
|
22
|
+
[[spec], podfile_for_specs([spec])]
|
23
23
|
end]
|
24
24
|
end
|
25
25
|
|
26
26
|
# @return [Podfile] a podfile suitable for installing the given spec
|
27
27
|
#
|
28
|
-
# @param [Specification]
|
28
|
+
# @param [Array<Specification>] specs
|
29
29
|
#
|
30
|
-
def
|
30
|
+
def podfile_for_specs(specs)
|
31
31
|
generator = self
|
32
|
-
dir = configuration.
|
32
|
+
dir = configuration.gen_dir_for_specs(specs)
|
33
|
+
project_name = configuration.project_name_for_specs(specs)
|
33
34
|
|
34
35
|
Pod::Podfile.new do
|
35
|
-
project "#{
|
36
|
-
workspace "#{
|
36
|
+
project "#{project_name}.xcodeproj"
|
37
|
+
workspace "#{project_name}.xcworkspace"
|
37
38
|
|
38
39
|
plugin 'cocoapods-generate'
|
39
40
|
|
40
41
|
install! 'cocoapods', generator.installation_options
|
41
42
|
|
42
|
-
generator.
|
43
|
+
generator.podfile_plugins.each do |name, options|
|
43
44
|
plugin(*[name, options].compact)
|
44
45
|
end
|
45
46
|
|
46
|
-
use_frameworks!(generator.
|
47
|
+
use_frameworks!(generator.use_frameworks_value)
|
47
48
|
|
48
49
|
if (supported_swift_versions = generator.supported_swift_versions)
|
49
50
|
supports_swift_versions(supported_swift_versions)
|
@@ -54,26 +55,34 @@ module Pod
|
|
54
55
|
source(source_url)
|
55
56
|
end
|
56
57
|
|
57
|
-
self.defined_in_file = dir.join('
|
58
|
+
self.defined_in_file = dir.join('CocoaPods.podfile.yaml')
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
60
|
+
test_specs_by_spec = Hash[specs.map do |spec|
|
61
|
+
[spec, spec.recursive_subspecs.select(&:test_specification?)]
|
62
|
+
end]
|
63
|
+
app_specs_by_spec = Hash[specs.map do |spec|
|
64
|
+
app_specs = if spec.respond_to?(:app_specification?)
|
65
|
+
spec.recursive_subspecs.select(&:app_specification?)
|
66
|
+
else
|
67
|
+
[]
|
68
|
+
end
|
69
|
+
[spec, app_specs]
|
70
|
+
end]
|
65
71
|
|
66
72
|
# Stick all of the transitive dependencies in an abstract target.
|
67
73
|
# This allows us to force CocoaPods to use the versions / sources / external sources
|
68
74
|
# that we want.
|
69
|
-
# By using an abstract target,
|
70
75
|
abstract_target 'Transitive Dependencies' do
|
71
|
-
pods_for_transitive_dependencies =
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
+
pods_for_transitive_dependencies = specs.flat_map do |spec|
|
77
|
+
[spec.name]
|
78
|
+
.concat(test_specs_by_spec.keys.map(&:name))
|
79
|
+
.concat(test_specs_by_spec.values.flatten.flat_map { |ts| ts.dependencies.flat_map(&:name) })
|
80
|
+
.concat(app_specs_by_spec.keys.map(&:name))
|
81
|
+
.concat(app_specs_by_spec.values.flatten.flat_map { |as| as.dependencies.flat_map(&:name) })
|
82
|
+
end
|
83
|
+
pods_for_transitive_dependencies.uniq!
|
76
84
|
|
85
|
+
spec_names = specs.map { |s| s.root.name }
|
77
86
|
dependencies = generator
|
78
87
|
.transitive_dependencies_by_pod
|
79
88
|
.values_at(*pods_for_transitive_dependencies)
|
@@ -81,7 +90,7 @@ module Pod
|
|
81
90
|
.flatten(1)
|
82
91
|
.uniq
|
83
92
|
.sort_by(&:name)
|
84
|
-
.reject { |d| d.root_name
|
93
|
+
.reject { |d| spec_names.include?(d.root_name) }
|
85
94
|
|
86
95
|
dependencies.each do |dependency|
|
87
96
|
pod_args = generator.pod_args_for_dependency(self, dependency)
|
@@ -89,9 +98,12 @@ module Pod
|
|
89
98
|
end
|
90
99
|
end
|
91
100
|
|
92
|
-
# Add platform-specific concrete targets that inherit the
|
93
|
-
|
94
|
-
|
101
|
+
# Add platform-specific concrete targets that inherit the `pod` declaration for the local pod.
|
102
|
+
spec_platform_names = specs.flat_map { |s| s.available_platforms.map(&:string_name) }.uniq.each.reject do |platform_name|
|
103
|
+
!generator.configuration.platforms.nil? && !generator.configuration.platforms.include?(platform_name.downcase)
|
104
|
+
end
|
105
|
+
|
106
|
+
spec_platform_names.sort.each do |platform_name|
|
95
107
|
target "App-#{platform_name}" do
|
96
108
|
current_target_definition.swift_version = generator.swift_version if generator.swift_version
|
97
109
|
end
|
@@ -112,18 +124,61 @@ module Pod
|
|
112
124
|
inhibit_all_warnings! if generator.inhibit_all_warnings?
|
113
125
|
use_modular_headers! if generator.use_modular_headers?
|
114
126
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
127
|
+
specs.each do |spec|
|
128
|
+
# This is the pod declaration for the local pod,
|
129
|
+
# it will be inherited by the concrete target definitions below
|
130
|
+
pod_options = generator.dependency_compilation_kwargs(spec.name)
|
131
|
+
|
132
|
+
path = spec.defined_in_file.relative_path_from(dir).to_s
|
133
|
+
pod_options[:path] = path
|
134
|
+
{ testspecs: test_specs_by_spec[spec], appspecs: app_specs_by_spec[spec] }.each do |key, subspecs|
|
135
|
+
pod_options[key] = subspecs.map { |s| s.name.sub(%r{^#{Regexp.escape spec.root.name}/}, '') }.sort unless subspecs.blank?
|
136
|
+
end
|
137
|
+
pod spec.name, **pod_options
|
121
138
|
end
|
122
139
|
|
123
|
-
|
140
|
+
# Implement local-sources option to set up dependencies to podspecs in the local filesystem.
|
141
|
+
next if generator.configuration.local_sources.empty?
|
142
|
+
specs.each do |spec|
|
143
|
+
generator.transitive_local_dependencies(spec, generator.configuration.local_sources).sort_by(&:first).each do |dependency, podspec_file|
|
144
|
+
pod_options = generator.dependency_compilation_kwargs(dependency.name)
|
145
|
+
pod_options[:path] = if podspec_file[0] == '/' # absolute path
|
146
|
+
podspec_file
|
147
|
+
else
|
148
|
+
'../../' + podspec_file
|
149
|
+
end
|
150
|
+
pod dependency.name, **pod_options
|
151
|
+
end
|
152
|
+
end
|
124
153
|
end
|
125
154
|
end
|
126
155
|
|
156
|
+
def transitive_local_dependencies(spec, paths, found_podspecs: {}, include_non_library_subspecs: true)
|
157
|
+
if include_non_library_subspecs
|
158
|
+
non_library_specs = spec.recursive_subspecs.select do |ss|
|
159
|
+
ss.test_specification? || (ss.respond_to?(:app_specification?) && ss.app_specification?)
|
160
|
+
end
|
161
|
+
non_library_specs.each do |subspec|
|
162
|
+
transitive_local_dependencies(subspec, paths, found_podspecs: found_podspecs, include_non_library_subspecs: false)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
spec.dependencies.each do |dependency|
|
166
|
+
next if found_podspecs.key?(dependency)
|
167
|
+
found_podspec_file = nil
|
168
|
+
name = dependency.name.split('/')[0]
|
169
|
+
paths.each do |path|
|
170
|
+
podspec_file = File.join(path, name + '.podspec')
|
171
|
+
next unless File.file?(podspec_file)
|
172
|
+
found_podspec_file = podspec_file
|
173
|
+
break
|
174
|
+
end
|
175
|
+
next unless found_podspec_file
|
176
|
+
found_podspecs[dependency] = found_podspec_file.sub(%r{\A\./}, '')
|
177
|
+
transitive_local_dependencies(Pod::Specification.from_file(found_podspec_file), paths, found_podspecs: found_podspecs)
|
178
|
+
end
|
179
|
+
found_podspecs
|
180
|
+
end
|
181
|
+
|
127
182
|
# @return [Boolean]
|
128
183
|
# whether all warnings should be inhibited
|
129
184
|
#
|
@@ -151,6 +206,27 @@ module Pod
|
|
151
206
|
end
|
152
207
|
end
|
153
208
|
|
209
|
+
# @return [Boolean, Hash]
|
210
|
+
# the value to use for `use_frameworks!` DSL directive
|
211
|
+
#
|
212
|
+
def use_frameworks_value
|
213
|
+
return configuration.use_frameworks? unless configuration.use_podfile?
|
214
|
+
use_framework_values = target_definition_list.map do |target_definition|
|
215
|
+
if target_definition.respond_to?(:build_type) # CocoaPods >= 1.9
|
216
|
+
build_type = target_definition.build_type
|
217
|
+
if build_type.static_library?
|
218
|
+
false
|
219
|
+
else
|
220
|
+
{ linkage: build_type == BuildType.dynamic_framework ? :dynamic : :static }
|
221
|
+
end
|
222
|
+
else
|
223
|
+
target_definition.uses_frameworks?
|
224
|
+
end
|
225
|
+
end.uniq
|
226
|
+
raise Informative, 'Multiple use_frameworks! values detected in user Podfile.' unless use_framework_values.count == 1
|
227
|
+
use_framework_values.first
|
228
|
+
end
|
229
|
+
|
154
230
|
# @return [Hash]
|
155
231
|
# a hash with "compilation"-related dependency options for the `pod` DSL method
|
156
232
|
#
|
@@ -261,7 +337,7 @@ module Pod
|
|
261
337
|
def installation_options
|
262
338
|
installation_options = {
|
263
339
|
deterministic_uuids: configuration.deterministic_uuids?,
|
264
|
-
share_schemes_for_development_pods: configuration.share_schemes_for_development_pods
|
340
|
+
share_schemes_for_development_pods: configuration.share_schemes_for_development_pods,
|
265
341
|
warn_for_multiple_pod_sources: configuration.warn_for_multiple_pod_sources?
|
266
342
|
}
|
267
343
|
|
@@ -273,9 +349,19 @@ module Pod
|
|
273
349
|
installation_options[:incremental_installation] = configuration.incremental_installation?
|
274
350
|
end
|
275
351
|
|
352
|
+
if Pod::Installer::InstallationOptions.all_options.include?('disable_input_output_paths')
|
353
|
+
installation_options[:disable_input_output_paths] = configuration.disable_input_output_paths
|
354
|
+
end
|
355
|
+
|
276
356
|
installation_options
|
277
357
|
end
|
278
358
|
|
359
|
+
def podfile_plugins
|
360
|
+
configuration.podfile_plugins.merge('cocoapods-disable-podfile-validations' => { 'no_abstract_only_pods' => true }) do |_key, old_value, new_value|
|
361
|
+
old_value.merge(new_value)
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
279
365
|
private
|
280
366
|
|
281
367
|
# @return [Array<Podfile::TargetDefinition>]
|
@@ -309,6 +395,7 @@ module Pod
|
|
309
395
|
#
|
310
396
|
def modular_headers?(pod_name)
|
311
397
|
return true if configuration.use_modular_headers?
|
398
|
+
return false unless configuration.use_podfile?
|
312
399
|
target_definitions_for_pod(pod_name).all? do |target_definition|
|
313
400
|
target_definition.build_pod_as_module?(pod_name)
|
314
401
|
end
|
data/lib/cocoapods_plugin.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cocoapods-generate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Giddins
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: cocoapods-disable-podfile-validations
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.1
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -59,6 +73,7 @@ extensions: []
|
|
59
73
|
extra_rdoc_files: []
|
60
74
|
files:
|
61
75
|
- CODE_OF_CONDUCT.md
|
76
|
+
- LICENSE.md
|
62
77
|
- README.md
|
63
78
|
- VERSION
|
64
79
|
- lib/cocoapods/command/gen.rb
|
@@ -68,9 +83,10 @@ files:
|
|
68
83
|
- lib/cocoapods/generate/podfile_generator.rb
|
69
84
|
- lib/cocoapods_plugin.rb
|
70
85
|
homepage: https://github.com/square/cocoapods-generate
|
71
|
-
licenses:
|
86
|
+
licenses:
|
87
|
+
- MIT
|
72
88
|
metadata: {}
|
73
|
-
post_install_message:
|
89
|
+
post_install_message:
|
74
90
|
rdoc_options: []
|
75
91
|
require_paths:
|
76
92
|
- lib
|
@@ -85,8 +101,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
85
101
|
- !ruby/object:Gem::Version
|
86
102
|
version: '0'
|
87
103
|
requirements: []
|
88
|
-
rubygems_version: 3.0.
|
89
|
-
signing_key:
|
104
|
+
rubygems_version: 3.0.3
|
105
|
+
signing_key:
|
90
106
|
specification_version: 4
|
91
107
|
summary: Generates Xcode workspaces from a podspec.
|
92
108
|
test_files: []
|