class Pod::Installer::UserProjectIntegrator
The {UserProjectIntegrator} integrates the libraries generated by TargetDefinitions of the {Podfile} with their correspondent user projects.
Constants
- IGNORED_KEYS
- INHERITED_FLAGS
Attributes
@return [Pathname] the path of the installation.
@todo This is only used to compute the workspace path in case that it
should be inferred by the project. If the workspace should be in the same dir of the project, this could be removed.
@return [Podfile] the podfile that should be integrated with the user
projects.
@return [Sandbox] The sandbox used for this installation.
@return [Array<AggregateTarget>] the targets represented in the Podfile
.
@return [Array<AggregateTarget>] the targets that require integration. This will always be equal or a smaller
subset of #targets.
@return [Boolean] whether to use input/output paths for build phase scripts
@return [Boolean] whether to use input/output paths for build phase scripts
Public Class Methods
Initialize a new instance
@param [Podfile] podfile @see podfile
@param [Sandbox] sandbox @see sandbox
@param [Pathname] installation_root
@see installation_root
@param [Array<AggregateTarget>] targets @see targets
@param [Array<AggregateTarget>] targets_to_integrate
@see targets_to_integrate
@param [Boolean] use_input_output_paths
@see use_input_output_paths
# File lib/cocoapods/installer/user_project_integrator.rb, line 56 def initialize(podfile, sandbox, installation_root, targets, targets_to_integrate, use_input_output_paths: true) @podfile = podfile @sandbox = sandbox @installation_root = installation_root @targets = targets @targets_to_integrate = targets_to_integrate @use_input_output_paths = use_input_output_paths end
Public Instance Methods
Integrates the user projects associated with the {TargetDefinitions} with the Pods project and its products.
@return [void]
# File lib/cocoapods/installer/user_project_integrator.rb, line 70 def integrate! create_workspace deintegrated_projects = deintegrate_removed_targets integrate_user_targets warn_about_xcconfig_overrides projects_to_save = (user_projects_to_integrate + deintegrated_projects).uniq save_projects(projects_to_save) end
Private Instance Methods
Creates and saved the workspace containing the Pods project and the user projects, if needed.
@note If the workspace already contains the projects it is not saved
to avoid Xcode from displaying the revert dialog: `Do you want to keep the Xcode version or revert to the version on disk?`
@return [void]
# File lib/cocoapods/installer/user_project_integrator.rb, line 94 def create_workspace all_projects = user_project_paths.sort.push(sandbox.project_path).uniq file_references = all_projects.map do |path| relative_path = path.relative_path_from(workspace_path.dirname).to_s Xcodeproj::Workspace::FileReference.new(relative_path, 'group') end if workspace_path.exist? workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path) new_file_references = file_references - workspace.file_references unless new_file_references.empty? new_file_references.each { |fr| workspace << fr } workspace.save_as(workspace_path) end else UI.notice "Please close any current Xcode sessions and use `#{workspace_path.basename}` for this project from now on." workspace = Xcodeproj::Workspace.new(*file_references) workspace.save_as(workspace_path) end end
Deintegrates the targets of the user projects that are no longer part of the installation.
@return [Array<Xcodeproj::PBXProject>] The list of projects that were deintegrated.
# File lib/cocoapods/installer/user_project_integrator.rb, line 120 def deintegrate_removed_targets Config.instance.with_changes(:silent => true) do deintegrator = Deintegrator.new all_project_targets = user_projects.flat_map(&:native_targets).uniq all_native_targets = targets.flat_map(&:user_targets).uniq targets_to_deintegrate = all_project_targets - all_native_targets targets_to_deintegrate.each do |target| deintegrator.deintegrate_target(target) end return targets_to_deintegrate.map(&:project).select(&:dirty?).uniq end end
Integrates the targets of the user projects with the libraries generated from the {Podfile}.
@note {TargetDefinition} without dependencies are skipped prevent
creating empty libraries for targets definitions which are only wrappers for others.
@return [void]
# File lib/cocoapods/installer/user_project_integrator.rb, line 142 def integrate_user_targets target_integrators = targets_to_integrate.sort_by(&:name).map do |target| TargetIntegrator.new(target, :use_input_output_paths => use_input_output_paths?) end target_integrators.each(&:integrate!) end
Prints a warning informing the user that a build configuration of the integrated target is overriding the CocoaPods build settings.
@param [Target::AggregateTarget] aggregate_target
The umbrella target.
@param [Xcodeproj::PBXNativeTarget] user_target
The native target.
@param [Xcodeproj::XCBuildConfiguration] config
The build configuration.
@param [String] key
The key of the overridden build setting.
# File lib/cocoapods/installer/user_project_integrator.rb, line 265 def print_override_warning(aggregate_target, user_target, config, key) actions = [ 'Use the `$(inherited)` flag, or', 'Remove the build settings from the target.', ] message = "The `#{user_target.name} [#{config.name}]` " \ "target overrides the `#{key}` build setting defined in " \ "`#{aggregate_target.xcconfig_relative_path(config.name)}'. " \ 'This can lead to problems with the CocoaPods installation' UI.warn(message, actions) end
Save all user projects.
@param [Array<Xcodeproj::PBXProject>] projects The projects to save.
@return [void]
# File lib/cocoapods/installer/user_project_integrator.rb, line 155 def save_projects(projects) projects.each do |project| if project.dirty? project.save else # There is a bug in Xcode where the process of deleting and # re-creating the xcconfig files used in the build # configuration cause building the user project to fail until # Xcode is relaunched. # # Touching/saving the project causes Xcode to reload these. # # https://github.com/CocoaPods/CocoaPods/issues/2665 FileUtils.touch(project.path + 'project.pbxproj') end end end
@return [Array<Pathname>] the paths of all the user projects from all targets regardless of whether they are
integrated or not.
@note Empty target definitions are ignored.
# File lib/cocoapods/installer/user_project_integrator.rb, line 246 def user_project_paths targets.map(&:user_project_path).compact.uniq end
@return [Array<Xcodeproj::Project>] the projects of all the targets regardless of whether they are integrated
or not.
@note Empty target definitions are ignored.
# File lib/cocoapods/installer/user_project_integrator.rb, line 237 def user_projects targets.map(&:user_project).compact.uniq end
@return [Array<Xcodeproj::Project>] the projects of all the targets that require integration.
@note Empty target definitions are ignored.
# File lib/cocoapods/installer/user_project_integrator.rb, line 228 def user_projects_to_integrate targets_to_integrate.map(&:user_project).compact.uniq end
Checks whether the settings of the CocoaPods generated xcconfig are overridden by the build configuration of a target and prints a warning to inform the user if needed.
# File lib/cocoapods/installer/user_project_integrator.rb, line 180 def warn_about_xcconfig_overrides targets_to_integrate.each do |aggregate_target| aggregate_target.user_targets.each do |user_target| user_target.build_configurations.each do |config| xcconfig = aggregate_target.xcconfigs[config.name] if xcconfig (xcconfig.to_hash.keys - IGNORED_KEYS).each do |key| target_values = config.build_settings[key] if target_values && !INHERITED_FLAGS.any? { |flag| target_values.include?(flag) } print_override_warning(aggregate_target, user_target, config, key) end end end end end end end
@return [Pathname] the path where the workspace containing the Pods
project and the user projects should be saved.
# File lib/cocoapods/installer/user_project_integrator.rb, line 207 def workspace_path if podfile.workspace_path declared_path = podfile.workspace_path path_with_ext = File.extname(declared_path) == '.xcworkspace' ? declared_path : "#{declared_path}.xcworkspace" podfile_dir = File.dirname(podfile.defined_in_file || '') absolute_path = File.expand_path(path_with_ext, podfile_dir) Pathname.new(absolute_path) elsif user_project_paths.count == 1 project = user_project_paths.first.basename('.xcodeproj') installation_root + "#{project}.xcworkspace" else raise Informative, 'Could not automatically select an Xcode ' \ "workspace. Specify one in your Podfile like so:\n\n" \ " workspace 'path/to/Workspace.xcworkspace'\n" end end