cocoapods-tt 0.0.1

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.
Files changed (124) hide show
  1. checksums.yaml +7 -0
  2. data/lib/cocoapods-tt/command/native/install.rb +56 -0
  3. data/lib/cocoapods-tt/command/native/update.rb +157 -0
  4. data/lib/cocoapods-tt/command/tt/make.rb +92 -0
  5. data/lib/cocoapods-tt/command/tt.rb +115 -0
  6. data/lib/cocoapods-tt/command.rb +1 -0
  7. data/lib/cocoapods-tt/gem_version.rb +3 -0
  8. data/lib/cocoapods-tt/native/command.rb +185 -0
  9. data/lib/cocoapods-tt/native/config.rb +366 -0
  10. data/lib/cocoapods-tt/native/core_overrides.rb +1 -0
  11. data/lib/cocoapods-tt/native/downloader/cache.rb +322 -0
  12. data/lib/cocoapods-tt/native/downloader/request.rb +86 -0
  13. data/lib/cocoapods-tt/native/downloader/response.rb +16 -0
  14. data/lib/cocoapods-tt/native/downloader.rb +192 -0
  15. data/lib/cocoapods-tt/native/executable.rb +247 -0
  16. data/lib/cocoapods-tt/native/external_sources/abstract_external_source.rb +205 -0
  17. data/lib/cocoapods-tt/native/external_sources/downloader_source.rb +30 -0
  18. data/lib/cocoapods-tt/native/external_sources/path_source.rb +55 -0
  19. data/lib/cocoapods-tt/native/external_sources/podspec_source.rb +54 -0
  20. data/lib/cocoapods-tt/native/external_sources.rb +57 -0
  21. data/lib/cocoapods-tt/native/gem_version.rb +5 -0
  22. data/lib/cocoapods-tt/native/generator/acknowledgements/markdown.rb +44 -0
  23. data/lib/cocoapods-tt/native/generator/acknowledgements/plist.rb +94 -0
  24. data/lib/cocoapods-tt/native/generator/acknowledgements.rb +107 -0
  25. data/lib/cocoapods-tt/native/generator/app_target_helper.rb +363 -0
  26. data/lib/cocoapods-tt/native/generator/bridge_support.rb +22 -0
  27. data/lib/cocoapods-tt/native/generator/constant.rb +19 -0
  28. data/lib/cocoapods-tt/native/generator/copy_dsyms_script.rb +56 -0
  29. data/lib/cocoapods-tt/native/generator/copy_resources_script.rb +223 -0
  30. data/lib/cocoapods-tt/native/generator/copy_xcframework_script.rb +227 -0
  31. data/lib/cocoapods-tt/native/generator/dummy_source.rb +31 -0
  32. data/lib/cocoapods-tt/native/generator/embed_frameworks_script.rb +196 -0
  33. data/lib/cocoapods-tt/native/generator/file_list.rb +39 -0
  34. data/lib/cocoapods-tt/native/generator/header.rb +103 -0
  35. data/lib/cocoapods-tt/native/generator/info_plist_file.rb +128 -0
  36. data/lib/cocoapods-tt/native/generator/module_map.rb +99 -0
  37. data/lib/cocoapods-tt/native/generator/prefix_header.rb +60 -0
  38. data/lib/cocoapods-tt/native/generator/script_phase_constants.rb +100 -0
  39. data/lib/cocoapods-tt/native/generator/umbrella_header.rb +46 -0
  40. data/lib/cocoapods-tt/native/hooks_manager.rb +132 -0
  41. data/lib/cocoapods-tt/native/installer/analyzer/analysis_result.rb +87 -0
  42. data/lib/cocoapods-tt/native/installer/analyzer/locking_dependency_analyzer.rb +103 -0
  43. data/lib/cocoapods-tt/native/installer/analyzer/pod_variant.rb +87 -0
  44. data/lib/cocoapods-tt/native/installer/analyzer/pod_variant_set.rb +175 -0
  45. data/lib/cocoapods-tt/native/installer/analyzer/podfile_dependency_cache.rb +55 -0
  46. data/lib/cocoapods-tt/native/installer/analyzer/sandbox_analyzer.rb +268 -0
  47. data/lib/cocoapods-tt/native/installer/analyzer/specs_state.rb +108 -0
  48. data/lib/cocoapods-tt/native/installer/analyzer/target_inspection_result.rb +58 -0
  49. data/lib/cocoapods-tt/native/installer/analyzer/target_inspector.rb +258 -0
  50. data/lib/cocoapods-tt/native/installer/analyzer.rb +1204 -0
  51. data/lib/cocoapods-tt/native/installer/base_install_hooks_context.rb +135 -0
  52. data/lib/cocoapods-tt/native/installer/installation_options.rb +195 -0
  53. data/lib/cocoapods-tt/native/installer/pod_source_installer.rb +224 -0
  54. data/lib/cocoapods-tt/native/installer/pod_source_preparer.rb +77 -0
  55. data/lib/cocoapods-tt/native/installer/podfile_validator.rb +168 -0
  56. data/lib/cocoapods-tt/native/installer/post_install_hooks_context.rb +9 -0
  57. data/lib/cocoapods-tt/native/installer/post_integrate_hooks_context.rb +9 -0
  58. data/lib/cocoapods-tt/native/installer/pre_install_hooks_context.rb +51 -0
  59. data/lib/cocoapods-tt/native/installer/pre_integrate_hooks_context.rb +9 -0
  60. data/lib/cocoapods-tt/native/installer/project_cache/project_cache.rb +11 -0
  61. data/lib/cocoapods-tt/native/installer/project_cache/project_cache_analysis_result.rb +53 -0
  62. data/lib/cocoapods-tt/native/installer/project_cache/project_cache_analyzer.rb +200 -0
  63. data/lib/cocoapods-tt/native/installer/project_cache/project_cache_version.rb +43 -0
  64. data/lib/cocoapods-tt/native/installer/project_cache/project_installation_cache.rb +103 -0
  65. data/lib/cocoapods-tt/native/installer/project_cache/project_metadata_cache.rb +73 -0
  66. data/lib/cocoapods-tt/native/installer/project_cache/target_cache_key.rb +176 -0
  67. data/lib/cocoapods-tt/native/installer/project_cache/target_metadata.rb +74 -0
  68. data/lib/cocoapods-tt/native/installer/sandbox_dir_cleaner.rb +105 -0
  69. data/lib/cocoapods-tt/native/installer/sandbox_header_paths_installer.rb +45 -0
  70. data/lib/cocoapods-tt/native/installer/source_provider_hooks_context.rb +34 -0
  71. data/lib/cocoapods-tt/native/installer/target_uuid_generator.rb +34 -0
  72. data/lib/cocoapods-tt/native/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb +179 -0
  73. data/lib/cocoapods-tt/native/installer/user_project_integrator/target_integrator.rb +815 -0
  74. data/lib/cocoapods-tt/native/installer/user_project_integrator.rb +280 -0
  75. data/lib/cocoapods-tt/native/installer/xcode/multi_pods_project_generator.rb +82 -0
  76. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/aggregate_target_dependency_installer.rb +66 -0
  77. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/aggregate_target_installer.rb +192 -0
  78. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/app_host_installer.rb +154 -0
  79. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/file_references_installer.rb +329 -0
  80. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_dependency_installer.rb +195 -0
  81. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_installer.rb +1239 -0
  82. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pod_target_integrator.rb +312 -0
  83. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/pods_project_writer.rb +90 -0
  84. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/project_generator.rb +120 -0
  85. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installation_result.rb +140 -0
  86. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installer.rb +257 -0
  87. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator/target_installer_helper.rb +110 -0
  88. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator.rb +291 -0
  89. data/lib/cocoapods-tt/native/installer/xcode/pods_project_generator_result.rb +54 -0
  90. data/lib/cocoapods-tt/native/installer/xcode/single_pods_project_generator.rb +38 -0
  91. data/lib/cocoapods-tt/native/installer/xcode/target_validator.rb +170 -0
  92. data/lib/cocoapods-tt/native/installer/xcode.rb +11 -0
  93. data/lib/cocoapods-tt/native/installer.rb +1044 -0
  94. data/lib/cocoapods-tt/native/native_target_extension.rb +60 -0
  95. data/lib/cocoapods-tt/native/open-uri.rb +33 -0
  96. data/lib/cocoapods-tt/native/podfile.rb +13 -0
  97. data/lib/cocoapods-tt/native/project.rb +544 -0
  98. data/lib/cocoapods-tt/native/resolver/lazy_specification.rb +88 -0
  99. data/lib/cocoapods-tt/native/resolver/resolver_specification.rb +41 -0
  100. data/lib/cocoapods-tt/native/resolver.rb +600 -0
  101. data/lib/cocoapods-tt/native/sandbox/file_accessor.rb +532 -0
  102. data/lib/cocoapods-tt/native/sandbox/headers_store.rb +163 -0
  103. data/lib/cocoapods-tt/native/sandbox/path_list.rb +242 -0
  104. data/lib/cocoapods-tt/native/sandbox/pod_dir_cleaner.rb +71 -0
  105. data/lib/cocoapods-tt/native/sandbox/podspec_finder.rb +23 -0
  106. data/lib/cocoapods-tt/native/sandbox.rb +470 -0
  107. data/lib/cocoapods-tt/native/sources_manager.rb +221 -0
  108. data/lib/cocoapods-tt/native/target/aggregate_target.rb +558 -0
  109. data/lib/cocoapods-tt/native/target/build_settings.rb +1385 -0
  110. data/lib/cocoapods-tt/native/target/pod_target.rb +1168 -0
  111. data/lib/cocoapods-tt/native/target.rb +378 -0
  112. data/lib/cocoapods-tt/native/user_interface/error_report.rb +204 -0
  113. data/lib/cocoapods-tt/native/user_interface/inspector_reporter.rb +102 -0
  114. data/lib/cocoapods-tt/native/user_interface.rb +463 -0
  115. data/lib/cocoapods-tt/native/validator.rb +1170 -0
  116. data/lib/cocoapods-tt/native/version_metadata.rb +26 -0
  117. data/lib/cocoapods-tt/native/xcode/framework_paths.rb +54 -0
  118. data/lib/cocoapods-tt/native/xcode/linkage_analyzer.rb +22 -0
  119. data/lib/cocoapods-tt/native/xcode/xcframework/xcframework_slice.rb +138 -0
  120. data/lib/cocoapods-tt/native/xcode/xcframework.rb +99 -0
  121. data/lib/cocoapods-tt/native/xcode.rb +7 -0
  122. data/lib/cocoapods-tt.rb +1 -0
  123. data/lib/cocoapods_plugin.rb +17 -0
  124. metadata +193 -0
@@ -0,0 +1,280 @@
1
+ require 'xcodeproj/workspace'
2
+ require 'xcodeproj/project'
3
+
4
+ require 'active_support/core_ext/string/inflections'
5
+ require 'active_support/core_ext/array/conversions'
6
+
7
+ module Pod
8
+ class Installer
9
+ # The {UserProjectIntegrator} integrates the libraries generated by
10
+ # TargetDefinitions of the {Podfile} with their correspondent user
11
+ # projects.
12
+ #
13
+ class UserProjectIntegrator
14
+ autoload :TargetIntegrator, 'cocoapods/installer/user_project_integrator/target_integrator'
15
+
16
+ # @return [Podfile] the podfile that should be integrated with the user
17
+ # projects.
18
+ #
19
+ attr_reader :podfile
20
+
21
+ # @return [Sandbox] The sandbox used for this installation.
22
+ #
23
+ attr_reader :sandbox
24
+
25
+ # @return [Pathname] the path of the installation.
26
+ #
27
+ # @todo This is only used to compute the workspace path in case that it
28
+ # should be inferred by the project. If the workspace should be in
29
+ # the same dir of the project, this could be removed.
30
+ #
31
+ attr_reader :installation_root
32
+
33
+ # @return [Array<AggregateTarget>] the targets represented in the Podfile.
34
+ #
35
+ attr_reader :targets
36
+
37
+ # @return [Array<AggregateTarget>] the targets that require integration. This will always be equal or a smaller
38
+ # subset of #targets.
39
+ #
40
+ attr_reader :targets_to_integrate
41
+
42
+ # @return [Boolean] whether to use input/output paths for build phase scripts
43
+ #
44
+ attr_reader :use_input_output_paths
45
+ alias use_input_output_paths? use_input_output_paths
46
+
47
+ # Initialize a new instance
48
+ #
49
+ # @param [Podfile] podfile @see #podfile
50
+ # @param [Sandbox] sandbox @see #sandbox
51
+ # @param [Pathname] installation_root @see #installation_root
52
+ # @param [Array<AggregateTarget>] targets @see #targets
53
+ # @param [Array<AggregateTarget>] targets_to_integrate @see #targets_to_integrate
54
+ # @param [Boolean] use_input_output_paths @see #use_input_output_paths
55
+ #
56
+ def initialize(podfile, sandbox, installation_root, targets, targets_to_integrate, use_input_output_paths: true)
57
+ @podfile = podfile
58
+ @sandbox = sandbox
59
+ @installation_root = installation_root
60
+ @targets = targets
61
+ @targets_to_integrate = targets_to_integrate
62
+ @use_input_output_paths = use_input_output_paths
63
+ end
64
+
65
+ # Integrates the user projects associated with the {TargetDefinitions}
66
+ # with the Pods project and its products.
67
+ #
68
+ # @return [void]
69
+ #
70
+ def integrate!
71
+ create_workspace
72
+ deintegrated_projects = deintegrate_removed_targets
73
+ integrate_user_targets
74
+ warn_about_xcconfig_overrides
75
+ projects_to_save = (user_projects_to_integrate + deintegrated_projects).uniq
76
+ save_projects(projects_to_save)
77
+ end
78
+
79
+ #-----------------------------------------------------------------------#
80
+
81
+ private
82
+
83
+ # @!group Integration steps
84
+
85
+ # Creates and saved the workspace containing the Pods project and the
86
+ # user projects, if needed.
87
+ #
88
+ # @note If the workspace already contains the projects it is not saved
89
+ # to avoid Xcode from displaying the revert dialog: `Do you want to
90
+ # keep the Xcode version or revert to the version on disk?`
91
+ #
92
+ # @return [void]
93
+ #
94
+ def create_workspace
95
+ all_projects = user_project_paths.sort.push(sandbox.project_path).uniq
96
+ file_references = all_projects.map do |path|
97
+ relative_path = path.relative_path_from(workspace_path.dirname).to_s
98
+ Xcodeproj::Workspace::FileReference.new(relative_path, 'group')
99
+ end
100
+
101
+ if workspace_path.exist?
102
+ workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
103
+ new_file_references = file_references - workspace.file_references
104
+ unless new_file_references.empty?
105
+ new_file_references.each { |fr| workspace << fr }
106
+ workspace.save_as(workspace_path)
107
+ end
108
+
109
+ else
110
+ UI.notice "Please close any current Xcode sessions and use `#{workspace_path.basename}` for this project from now on."
111
+ workspace = Xcodeproj::Workspace.new(*file_references)
112
+ workspace.save_as(workspace_path)
113
+ end
114
+ end
115
+
116
+ # Deintegrates the targets of the user projects that are no longer part of the installation.
117
+ #
118
+ # @return [Array<Xcodeproj::PBXProject>] The list of projects that were deintegrated.
119
+ #
120
+ def deintegrate_removed_targets
121
+ Config.instance.with_changes(:silent => true) do
122
+ deintegrator = Deintegrator.new
123
+ all_project_targets = user_projects.flat_map(&:native_targets).uniq
124
+ all_native_targets = targets.flat_map(&:user_targets).uniq
125
+ targets_to_deintegrate = all_project_targets - all_native_targets
126
+ targets_to_deintegrate.each do |target|
127
+ deintegrator.deintegrate_target(target)
128
+ end
129
+ return targets_to_deintegrate.map(&:project).select(&:dirty?).uniq
130
+ end
131
+ end
132
+
133
+ # Integrates the targets of the user projects with the libraries
134
+ # generated from the {Podfile}.
135
+ #
136
+ # @note {TargetDefinition} without dependencies are skipped prevent
137
+ # creating empty libraries for targets definitions which are only
138
+ # wrappers for others.
139
+ #
140
+ # @return [void]
141
+ #
142
+ def integrate_user_targets
143
+ target_integrators = targets_to_integrate.sort_by(&:name).map do |target|
144
+ TargetIntegrator.new(target, :use_input_output_paths => use_input_output_paths?)
145
+ end
146
+ target_integrators.each(&:integrate!)
147
+ end
148
+
149
+ # Save all user projects.
150
+ #
151
+ # @param [Array<Xcodeproj::PBXProject>] projects The projects to save.
152
+ #
153
+ # @return [void]
154
+ #
155
+ def save_projects(projects)
156
+ projects.each do |project|
157
+ if project.dirty?
158
+ project.save
159
+ else
160
+ # There is a bug in Xcode where the process of deleting and
161
+ # re-creating the xcconfig files used in the build
162
+ # configuration cause building the user project to fail until
163
+ # Xcode is relaunched.
164
+ #
165
+ # Touching/saving the project causes Xcode to reload these.
166
+ #
167
+ # https://github.com/CocoaPods/CocoaPods/issues/2665
168
+ FileUtils.touch(project.path + 'project.pbxproj')
169
+ end
170
+ end
171
+ end
172
+
173
+ IGNORED_KEYS = %w(CODE_SIGN_IDENTITY).freeze
174
+ INHERITED_FLAGS = %w($(inherited) ${inherited}).freeze
175
+
176
+ # Checks whether the settings of the CocoaPods generated xcconfig are
177
+ # overridden by the build configuration of a target and prints a
178
+ # warning to inform the user if needed.
179
+ #
180
+ def warn_about_xcconfig_overrides
181
+ targets_to_integrate.each do |aggregate_target|
182
+ aggregate_target.user_targets.each do |user_target|
183
+ user_target.build_configurations.each do |config|
184
+ xcconfig = aggregate_target.xcconfigs[config.name]
185
+ if xcconfig
186
+ (xcconfig.to_hash.keys - IGNORED_KEYS).each do |key|
187
+ target_values = config.build_settings[key]
188
+ if target_values &&
189
+ !INHERITED_FLAGS.any? { |flag| target_values.include?(flag) }
190
+ print_override_warning(aggregate_target, user_target, config, key)
191
+ end
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
198
+
199
+ private
200
+
201
+ # @!group Private Helpers
202
+ #-----------------------------------------------------------------------#
203
+
204
+ # @return [Pathname] the path where the workspace containing the Pods
205
+ # project and the user projects should be saved.
206
+ #
207
+ def workspace_path
208
+ if podfile.workspace_path
209
+ declared_path = podfile.workspace_path
210
+ path_with_ext = File.extname(declared_path) == '.xcworkspace' ? declared_path : "#{declared_path}.xcworkspace"
211
+ podfile_dir = File.dirname(podfile.defined_in_file || '')
212
+ absolute_path = File.expand_path(path_with_ext, podfile_dir)
213
+ Pathname.new(absolute_path)
214
+ elsif user_project_paths.count == 1
215
+ project = user_project_paths.first.basename('.xcodeproj')
216
+ installation_root + "#{project}.xcworkspace"
217
+ else
218
+ raise Informative, 'Could not automatically select an Xcode ' \
219
+ "workspace. Specify one in your Podfile like so:\n\n" \
220
+ " workspace 'path/to/Workspace.xcworkspace'\n"
221
+ end
222
+ end
223
+
224
+ # @return [Array<Xcodeproj::Project>] the projects of all the targets that require integration.
225
+ #
226
+ # @note Empty target definitions are ignored.
227
+ #
228
+ def user_projects_to_integrate
229
+ targets_to_integrate.map(&:user_project).compact.uniq
230
+ end
231
+
232
+ # @return [Array<Xcodeproj::Project>] the projects of all the targets regardless of whether they are integrated
233
+ # or not.
234
+ #
235
+ # @note Empty target definitions are ignored.
236
+ #
237
+ def user_projects
238
+ targets.map(&:user_project).compact.uniq
239
+ end
240
+
241
+ # @return [Array<Pathname>] the paths of all the user projects from all targets regardless of whether they are
242
+ # integrated or not.
243
+ #
244
+ # @note Empty target definitions are ignored.
245
+ #
246
+ def user_project_paths
247
+ targets.map(&:user_project_path).compact.uniq
248
+ end
249
+
250
+ # Prints a warning informing the user that a build configuration of
251
+ # the integrated target is overriding the CocoaPods build settings.
252
+ #
253
+ # @param [Target::AggregateTarget] aggregate_target
254
+ # The umbrella target.
255
+ #
256
+ # @param [Xcodeproj::PBXNativeTarget] user_target
257
+ # The native target.
258
+ #
259
+ # @param [Xcodeproj::XCBuildConfiguration] config
260
+ # The build configuration.
261
+ #
262
+ # @param [String] key
263
+ # The key of the overridden build setting.
264
+ #
265
+ def print_override_warning(aggregate_target, user_target, config, key)
266
+ actions = [
267
+ 'Use the `$(inherited)` flag, or',
268
+ 'Remove the build settings from the target.',
269
+ ]
270
+ message = "The `#{user_target.name} [#{config.name}]` " \
271
+ "target overrides the `#{key}` build setting defined in " \
272
+ "`#{aggregate_target.xcconfig_relative_path(config.name)}'. " \
273
+ 'This can lead to problems with the CocoaPods installation'
274
+ UI.warn(message, actions)
275
+ end
276
+
277
+ #-----------------------------------------------------------------------#
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,82 @@
1
+ module Pod
2
+ class Installer
3
+ class Xcode
4
+ # The {MultiPodsProjectGenerator} handles generation of the 'Pods/Pods.xcodeproj' and Xcode projects
5
+ # for every {PodTarget}. All Pod Target projects are nested under the 'Pods.xcodeproj'.
6
+ #
7
+ class MultiPodsProjectGenerator < PodsProjectGenerator
8
+ # Generates `Pods/Pods.xcodeproj` and all pod target subprojects.
9
+ #
10
+ # @return [PodsProjectGeneratorResult]
11
+ #
12
+ def generate!
13
+ # Generate container Pods.xcodeproj.
14
+ container_project = create_container_project(aggregate_targets, sandbox.project_path)
15
+
16
+ project_paths_by_pod_targets = pod_targets.group_by do |pod_target|
17
+ sandbox.pod_target_project_path(pod_target.project_name)
18
+ end
19
+ projects_by_pod_targets = Hash[project_paths_by_pod_targets.map do |project_path, pod_targets|
20
+ project = create_pods_project(pod_targets, project_path, container_project)
21
+ [project, pod_targets]
22
+ end]
23
+
24
+ # Note: We must call `install_file_references` on all pod targets before installing them.
25
+ pod_target_installation_results = install_all_pod_targets(projects_by_pod_targets)
26
+ aggregate_target_installation_results = install_aggregate_targets_into_project(container_project, aggregate_targets)
27
+ target_installation_results = InstallationResults.new(pod_target_installation_results, aggregate_target_installation_results)
28
+
29
+ integrate_targets(target_installation_results.pod_target_installation_results)
30
+ wire_target_dependencies(target_installation_results)
31
+ PodsProjectGeneratorResult.new(container_project, projects_by_pod_targets, target_installation_results)
32
+ end
33
+
34
+ private
35
+
36
+ def create_container_project(aggregate_targets, path)
37
+ return unless aggregate_targets
38
+ platforms = aggregate_targets.map(&:platform)
39
+ ProjectGenerator.new(sandbox, path, [], build_configurations, platforms,
40
+ project_object_version, config.podfile_path).generate!
41
+ end
42
+
43
+ def create_pods_project(pod_targets, path, parent_project)
44
+ platforms = pod_targets.map(&:platform)
45
+ project = ProjectGenerator.new(sandbox, path, pod_targets, build_configurations, platforms,
46
+ project_object_version, false, :pod_target_subproject => true).generate!
47
+ # Instead of saving every subproject to disk, we can optimize this by creating a temporary folder
48
+ # the file reference can use so that we only have to call `save` once for all projects.
49
+ project.path.mkpath
50
+ if parent_project
51
+ pod_name = pod_name_from_grouping(pod_targets)
52
+ is_local = sandbox.local?(pod_name)
53
+ parent_project.add_pod_subproject(project, is_local)
54
+ end
55
+
56
+ install_file_references(project, pod_targets)
57
+ project
58
+ end
59
+
60
+ def install_all_pod_targets(projects_by_pod_targets)
61
+ UI.message '- Installing Pod Targets' do
62
+ projects_by_pod_targets.each_with_object({}) do |(project, pod_targets), target_installation_results|
63
+ target_installation_results.merge!(install_pod_targets(project, pod_targets))
64
+ end
65
+ end
66
+ end
67
+
68
+ def install_aggregate_targets_into_project(project, aggregate_targets)
69
+ return {} unless project
70
+ install_aggregate_targets(project, aggregate_targets)
71
+ end
72
+
73
+ def pod_name_from_grouping(pod_targets)
74
+ # The presumption here for multi pods project is that we group by `pod_name`, thus the grouping of `pod_targets`
75
+ # should share the same `pod_name`.
76
+ raise '[BUG] Expected at least 1 pod target' if pod_targets.empty?
77
+ pod_targets.first.pod_name
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,66 @@
1
+ module Pod
2
+ class Installer
3
+ class Xcode
4
+ # Wires up the dependencies for aggregate targets from the target installation results
5
+ #
6
+ class AggregateTargetDependencyInstaller
7
+ require 'cocoapods/native_target_extension.rb'
8
+
9
+ # @return [Hash{String => TargetInstallationResult}] The target installation results for pod targets.
10
+ #
11
+ attr_reader :pod_target_installation_results
12
+
13
+ # @return [Hash{String => TargetInstallationResult}] The target installation results for aggregate targets.
14
+ #
15
+ attr_reader :aggregate_target_installation_results
16
+
17
+ # @return [ProjectMetadataCache] The project metadata cache.
18
+ #
19
+ attr_reader :metadata_cache
20
+
21
+ # @return [Sandbox] The sandbox used for this installation.
22
+ #
23
+ attr_reader :sandbox
24
+
25
+ # Initialize a new instance.
26
+ #
27
+ # @param [Sandbox] sandbox @see #sandbox
28
+ # @param [Hash{String => TargetInstallationResult}] aggregate_target_installation_results @see #aggregate_target_installation_results
29
+ # @param [Hash{String => TargetInstallationResult}] pod_target_installation_results @see #pod_target_installation_results
30
+ # @param [ProjectMetadataCache] metadata_cache @see #metadata_cache
31
+ #
32
+ def initialize(sandbox, aggregate_target_installation_results, pod_target_installation_results, metadata_cache)
33
+ @sandbox = sandbox
34
+ @aggregate_target_installation_results = aggregate_target_installation_results
35
+ @pod_target_installation_results = pod_target_installation_results
36
+ @metadata_cache = metadata_cache
37
+ end
38
+
39
+ def install!
40
+ aggregate_target_installation_results.values.each do |aggregate_target_installation_result|
41
+ aggregate_target = aggregate_target_installation_result.target
42
+ aggregate_native_target = aggregate_target_installation_result.native_target
43
+ project = aggregate_native_target.project
44
+ # Wire up dependencies that are part of inherit search paths for this aggregate target.
45
+ aggregate_target.search_paths_aggregate_targets.each do |search_paths_target|
46
+ aggregate_native_target.add_dependency(aggregate_target_installation_results[search_paths_target.name].native_target)
47
+ end
48
+ # Wire up all pod target dependencies to aggregate target.
49
+ aggregate_target.pod_targets.each do |pod_target|
50
+ if pod_target_installation_result = pod_target_installation_results[pod_target.name]
51
+ pod_target_native_target = pod_target_installation_result.native_target
52
+ aggregate_native_target.add_dependency(pod_target_native_target)
53
+ else
54
+ # Hit the cache
55
+ is_local = sandbox.local?(pod_target.pod_name)
56
+ cached_dependency = metadata_cache.target_label_by_metadata[pod_target.label]
57
+ project.add_cached_pod_subproject(sandbox, cached_dependency, is_local)
58
+ Project.add_cached_dependency(sandbox, aggregate_native_target, cached_dependency)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,192 @@
1
+ module Pod
2
+ class Installer
3
+ class Xcode
4
+ class PodsProjectGenerator
5
+ # Creates the targets which aggregate the Pods libraries in the Pods
6
+ # project and the relative support files.
7
+ #
8
+ class AggregateTargetInstaller < TargetInstaller
9
+ # @return [AggregateTarget] @see TargetInstaller#target
10
+ #
11
+ attr_reader :target
12
+
13
+ # Creates the target in the Pods project and the relative support files.
14
+ #
15
+ # @return [TargetInstallationResult] the result of the installation of this target.
16
+ #
17
+ def install!
18
+ UI.message "- Installing target `#{target.name}` #{target.platform}" do
19
+ native_target = add_target
20
+ create_support_files_dir
21
+ create_support_files_group
22
+ create_xcconfig_file(native_target)
23
+ if target.build_as_framework?
24
+ create_info_plist_file(target.info_plist_path, native_target, target.version, target.platform)
25
+ create_module_map(native_target)
26
+ create_umbrella_header(native_target)
27
+ elsif target.uses_swift?
28
+ create_module_map(native_target)
29
+ create_umbrella_header(native_target)
30
+ end
31
+ # Because embedded targets live in their host target, CocoaPods
32
+ # copies all of the embedded target's pod_targets to its host
33
+ # targets. Having this script for the embedded target would
34
+ # cause an App Store rejection because frameworks cannot be
35
+ # embedded in embedded targets.
36
+ #
37
+ create_embed_frameworks_script if embed_frameworks_script_required?
38
+ create_bridge_support_file(native_target)
39
+ create_copy_resources_script if target.includes_resources?
40
+ create_acknowledgements
41
+ create_dummy_source(native_target)
42
+ clean_support_files_temp_dir
43
+ TargetInstallationResult.new(target, native_target)
44
+ end
45
+ end
46
+
47
+ #-----------------------------------------------------------------------#
48
+
49
+ private
50
+
51
+ # @return [TargetDefinition] the target definition of the library.
52
+ #
53
+ def target_definition
54
+ target.target_definition
55
+ end
56
+
57
+ # Ensure that vendored static frameworks and libraries are not linked
58
+ # twice to the aggregate target, which shares the xcconfig of the user
59
+ # target.
60
+ #
61
+ def custom_build_settings
62
+ settings = {
63
+ 'CODE_SIGN_IDENTITY[sdk=appletvos*]' => '',
64
+ 'CODE_SIGN_IDENTITY[sdk=iphoneos*]' => '',
65
+ 'CODE_SIGN_IDENTITY[sdk=watchos*]' => '',
66
+ 'MACH_O_TYPE' => 'staticlib',
67
+ 'OTHER_LDFLAGS' => '',
68
+ 'OTHER_LIBTOOLFLAGS' => '',
69
+ 'PODS_ROOT' => '$(SRCROOT)',
70
+ 'PRODUCT_BUNDLE_IDENTIFIER' => 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}',
71
+ 'SKIP_INSTALL' => 'YES',
72
+
73
+ # Needed to ensure that static libraries won't try to embed the swift stdlib,
74
+ # since there's no where to embed in for a static library.
75
+ # Not necessary for dynamic frameworks either, since the aggregate targets are never shipped
76
+ # on their own, and are always further embedded into an app target.
77
+ 'ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES' => 'NO',
78
+ }
79
+ super.merge(settings)
80
+ end
81
+
82
+ # @return [Boolean] whether this target requires an `Embed Frameworks` script phase
83
+ #
84
+ def embed_frameworks_script_required?
85
+ includes_dynamic_xcframeworks = target.xcframeworks_by_config.values.flatten.map(&:build_type).any?(&:dynamic_framework?)
86
+ (target.includes_frameworks? || includes_dynamic_xcframeworks) && !target.requires_host_target?
87
+ end
88
+
89
+ # Creates the group that holds the references to the support files
90
+ # generated by this installer.
91
+ #
92
+ # @return [void]
93
+ #
94
+ def create_support_files_group
95
+ parent = project.support_files_group
96
+ name = target.name
97
+ dir = target.support_files_dir
98
+ @support_files_group = parent.new_group(name, dir)
99
+ end
100
+
101
+ # Generates the contents of the xcconfig file and saves it to disk.
102
+ #
103
+ # @param [PBXNativeTarget] native_target
104
+ # the native target to link the module map file into.
105
+ #
106
+ # @return [void]
107
+ #
108
+ def create_xcconfig_file(native_target)
109
+ native_target.build_configurations.each do |configuration|
110
+ next unless target.user_build_configurations.key?(configuration.name)
111
+ path = target.xcconfig_path(configuration.name)
112
+ build_settings = target.build_settings(configuration.name)
113
+ update_changed_file(build_settings, path)
114
+ target.xcconfigs[configuration.name] = build_settings.xcconfig
115
+ xcconfig_file_ref = add_file_to_support_group(path)
116
+ configuration.base_configuration_reference = xcconfig_file_ref
117
+ end
118
+ end
119
+
120
+ # Generates the bridge support metadata if requested by the {Podfile}.
121
+ #
122
+ # @note The bridge support metadata is added to the resources of the
123
+ # target because it is needed for environments interpreted at
124
+ # runtime.
125
+ #
126
+ # @param [PBXNativeTarget] native_target
127
+ # the native target to add the bridge support file into.
128
+ #
129
+ # @return [void]
130
+ #
131
+ def create_bridge_support_file(native_target)
132
+ if target.podfile.generate_bridge_support?
133
+ path = target.bridge_support_path
134
+ headers = native_target.headers_build_phase.files.map { |bf| sandbox.root + bf.file_ref.path }
135
+ generator = Generator::BridgeSupport.new(headers)
136
+ update_changed_file(generator, path)
137
+ add_file_to_support_group(path)
138
+ end
139
+ end
140
+
141
+ # Creates a script that copies the resources to the bundle of the client
142
+ # target.
143
+ #
144
+ # @note The bridge support file needs to be created before the prefix
145
+ # header, otherwise it will not be added to the resources script.
146
+ #
147
+ # @return [void]
148
+ #
149
+ def create_copy_resources_script
150
+ path = target.copy_resources_script_path
151
+ generator = Generator::CopyResourcesScript.new(target.resource_paths_by_config, target.platform)
152
+ update_changed_file(generator, path)
153
+ add_file_to_support_group(path)
154
+ end
155
+
156
+ # Creates a script that embeds the frameworks to the bundle of the client
157
+ # target.
158
+ #
159
+ # @note We can't use Xcode default link libraries phase, because
160
+ # we need to ensure that we only copy the frameworks which are
161
+ # relevant for the current build configuration.
162
+ #
163
+ # @return [void]
164
+ #
165
+ def create_embed_frameworks_script
166
+ path = target.embed_frameworks_script_path
167
+ generator = Generator::EmbedFrameworksScript.new(target.framework_paths_by_config, target.xcframeworks_by_config)
168
+ update_changed_file(generator, path)
169
+ add_file_to_support_group(path)
170
+ end
171
+
172
+ # Generates the acknowledgement files (markdown and plist) for the target.
173
+ #
174
+ # @return [void]
175
+ #
176
+ def create_acknowledgements
177
+ basepath = target.acknowledgements_basepath
178
+ Generator::Acknowledgements.generators.each do |generator_class|
179
+ path = generator_class.path_from_basepath(basepath)
180
+ file_accessors = target.pod_targets.map(&:file_accessors).flatten
181
+ generator = generator_class.new(file_accessors)
182
+ update_changed_file(generator, path)
183
+ add_file_to_support_group(path)
184
+ end
185
+ end
186
+
187
+ #-----------------------------------------------------------------------#
188
+ end
189
+ end
190
+ end
191
+ end
192
+ end