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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2cd88f4c2670ce0ca90f7f0d797f04b55a469bfc469c8b37362c06776f85ba6e
4
- data.tar.gz: 984fb36533b3d9f66cbed561f1d70caa1799844345966ba07809afbcc6a52345
3
+ metadata.gz: f21262cc4824565c6d34162cb6e20312ddfa2d0ff3331c7b58fac561f2432e2f
4
+ data.tar.gz: 72fdfa72cca275404202ddbffcf6805fa22598b1897a379b49a77586a328cb52
5
5
  SHA512:
6
- metadata.gz: b9a7d8cd37b494c7cab267b360af65690b9a05639b91ad13d101fe9d16b8658d8fd84c60f4b3c7b575810d39fe8c6db80e650596b389ced553df3df5e1d70f19
7
- data.tar.gz: 1734bb0083d74411e3ac6e7bcbb5ace9d38100c2284f92e697cb6ef6d17a40909e149087a6a65e8e1785cd2a8e11e2f83c2dabf58d143d167b35e0fb4f976e7f
6
+ metadata.gz: 523fe6d21ea621a6c3035a59c950beea558cfbaaac1dcba17ba23ee999103e195845413bbf62a400baa8d3aff031d11a7980b4e2fe5d5e315fce370726be890d
7
+ data.tar.gz: 2229639a9d3ef51e44aa73ec7b3347fc049421da8ed4430e40d03ac984671ea78ebb594cb027afca83b184c25c052642a7319212980f7607ebb795583c6f12b4
@@ -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 dependant
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.4.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).podfiles_by_spec.each do |spec, podfile|
68
- Generate::Installer.new(configuration, spec, podfile).install!
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.insert(-2, env)
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 dependant 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.',
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 :share_schemes_for_development_pods, BOOLEAN, 'true', 'Whether installation should share schemes for development pods', nil, nil, coerce_to_bool
189
- option :warn_for_multiple_pod_sources, BOOLEAN, 'false', 'Whether installation should warn when a pod is found in multiple sources', nil, nil, coerce_to_bool
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 [String] name the name of the pod
309
+ # @param [Array<Specification>] specs The specs to get a directory name for.
293
310
  #
294
- def gen_dir_for_pod(name)
295
- gen_directory.join(name)
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
- def self.podspecs_from_paths(paths)
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 + '*.podspec{.json,}')
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 :spec
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, spec, podfile)
22
+ def initialize(configuration, specs, podfile)
35
23
  @configuration = configuration
36
- @spec = spec
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 #{spec.name} in #{UI.path install_directory}" do
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, lockfile: configuration.lockfile, sandbox: nil, sandbox_root: install_directory, podfile_path: podfile.defined_in_file, silent: !configuration.pod_config.verbose?, verbose: false, lockfile_path: nil) do
67
- installer = InstallerNoValidatePodfile.new(configuration.pod_config.sandbox, podfile, configuration.lockfile)
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
- perform_post_install_steps(open_app_project, installer)
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("#{spec.name}.xcodeproj")
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: true)
108
-
109
- spec.available_platforms.map do |platform|
110
- consumer = spec.consumer(platform)
111
- target_name = "App-#{Platform.string_name(consumer.platform_name)}"
112
- native_app_target = Pod::Generator::AppTargetHelper.add_app_target(app_project, consumer.platform_name, deployment_target(consumer), target_name)
113
- # Temporarily set Swift version to pass validator checks for pods which do not specify Swift version.
114
- # It will then be re-set again within #perform_post_install_steps.
115
- Pod::Generator::AppTargetHelper.add_swift_version(native_app_target, Pod::Validator::DEFAULT_SWIFT_VERSION)
116
- native_app_target
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
- .tap do
119
- app_project.recreate_user_schemes do |scheme, target|
120
- installation_result = installation_result_from_target(target)
121
- next unless installation_result
122
- installation_result.test_native_targets.each do |test_native_target|
123
- scheme.add_test_target(test_native_target)
124
- end
125
- end
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
- .each do |target|
128
- Xcodeproj::XCScheme.share_scheme(app_project.path, target.name)
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
- pod_target = installer.pod_targets.find { |pt| pt.platform.name == native_app_target.platform_name && pt.pod_name == spec.name }
148
- raise "unable to find a pod target for #{native_app_target} / #{spec}" unless pod_target
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
- Pod::Generator::AppTargetHelper.add_app_project_import(app_project, native_app_target, pod_target, pod_target.platform.name, pod_target.requires_frameworks?, native_app_target.name)
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(installer, app_project, native_app_target)
221
+ make_ios_app_launchable(app_project, native_app_target)
187
222
  end
188
223
 
189
- Pod::Generator::AppTargetHelper.add_swift_version(native_app_target, pod_target.swift_version) unless pod_target.swift_version.blank?
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
- # Share the pods xcscheme only if it exists. For pre-built vendored pods there is no xcscheme generated.
195
- if installer.respond_to?(:generated_projects) # CocoaPods 1.7.0
196
- installer.generated_projects.each do |project|
197
- Xcodeproj::XCScheme.share_scheme(project.path, pod_target.label) if File.exist?(project.path + pod_target.label)
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
- if installer.respond_to?(:target_installation_results) # CocoaPods >= 1.6
226
- installer
227
- .target_installation_results
228
- .pod_target_installation_results
229
- .values
230
- .flatten(1)
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
- app_project.path.sub_ext('.xcworkspace').join('xcshareddata').tap(&:mkpath).join('WorkspaceSettings.xcsettings')
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'] = 'container:Pods.xcodeproj'
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(installer, app_project, native_app_target)
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 = installer.sandbox.root.join('App', platform_name).tap(&:mkpath)
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/#{platform_name}/Info.plist"
366
+ bc.build_settings['INFOPLIST_FILE'] = "${SRCROOT}/App-#{platform_name}/Info.plist"
331
367
  end
332
368
 
333
- group = app_project.main_group.find_subpath("App-#{platform_name}", true)
334
- group.new_file(info_plist_path)
335
- native_app_target.resources_build_phase.add_file_reference group.new_file(launch_storyboard)
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 #{spec.name}"
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, Podfile>]
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 podfiles_by_spec
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, podfile_for_spec(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] spec
28
+ # @param [Array<Specification>] specs
29
29
  #
30
- def podfile_for_spec(spec)
30
+ def podfile_for_specs(specs)
31
31
  generator = self
32
- dir = configuration.gen_dir_for_pod(spec.name)
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 "#{spec.name}.xcodeproj"
36
- workspace "#{spec.name}.xcworkspace"
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.configuration.podfile_plugins.each do |name, options|
43
+ generator.podfile_plugins.each do |name, options|
43
44
  plugin(*[name, options].compact)
44
45
  end
45
46
 
46
- use_frameworks!(generator.configuration.use_frameworks?)
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('Podfile.yaml')
58
+ self.defined_in_file = dir.join('CocoaPods.podfile.yaml')
58
59
 
59
- test_specs = spec.recursive_subspecs.select(&:test_specification?)
60
- app_specs = if spec.respond_to?(:app_specification?)
61
- spec.recursive_subspecs.select(&:app_specification?)
62
- else
63
- []
64
- end
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 = [spec.name]
72
- .concat(test_specs.map(&:name))
73
- .concat(test_specs.flat_map { |ts| ts.dependencies.flat_map(&:name) })
74
- .concat(app_specs.map(&:name))
75
- .concat(app_specs.flat_map { |as| as.dependencies.flat_map(&:name) })
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 == spec.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
- # `pod` declaration for the local pod.
94
- spec.available_platforms.map(&:string_name).sort.each do |platform_name|
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
- # This is the pod declaration for the local pod,
116
- # it will be inherited by the concrete target definitions below
117
- pod_options = generator.dependency_compilation_kwargs(spec.name)
118
- pod_options[:path] = spec.defined_in_file.relative_path_from(dir).to_s
119
- { testspecs: test_specs, appspecs: app_specs }.each do |key, specs|
120
- pod_options[key] = specs.map { |s| s.name.sub(%r{^#{Regexp.escape spec.root.name}/}, '') }.sort unless specs.empty?
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
- pod spec.name, **pod_options
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
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- if Pod::VERSION >= '1.5.0'
3
+ if Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.5.0')
4
4
  require 'cocoapods/command/gen'
5
5
  else
6
6
  Pod::UI.warn 'cocoapods-generate requires CocoaPods >= 1.5.0'
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.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: 2019-04-09 00:00:00.000000000 Z
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.1
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: []