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

installation_root[R]

@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.
podfile[R]

@return [Podfile] the podfile that should be integrated with the user

projects.
sandbox[R]

@return [Project] the pods project which contains the libraries to

integrate.

attr_reader :pods_project

targets[R]

@return [Array<AggregateTarget>] the targets represented in the Podfile.

Public Class Methods

new(podfile, sandbox, installation_root, targets) click to toggle source

Init a new UserProjectIntegrator

@param [Podfile] podfile @see podfile @param [Sandbox] sandbox @see sandbox @param [Pathname] installation_root @see installation_root @param [Array<AggregateTarget>] targets @see targets

# File lib/cocoapods/installer/user_project_integrator.rb, line 47
def initialize(podfile, sandbox, installation_root, targets)
  @podfile = podfile
  @sandbox = sandbox
  @installation_root = installation_root
  @targets = targets
end

Public Instance Methods

integrate!() click to toggle source

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 59
def integrate!
  create_workspace
  integrate_user_targets
  warn_about_xcconfig_overrides
  save_projects
end

Private Instance Methods

create_workspace() click to toggle source

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 81
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
integrate_user_targets() click to toggle source

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 112
def integrate_user_targets
  target_integrators = targets_to_integrate.sort_by(&:name).map do |target|
    TargetIntegrator.new(target)
  end

  Config.instance.with_changes(:silent => true) do
    deintegrator = Deintegrator.new
    all_project_targets = user_projects.flat_map(&:native_targets).uniq
    all_native_targets = targets_to_integrate.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
  end

  target_integrators.each(&:integrate!)
end
print_override_warning(aggregate_target, user_target, config, key) click to toggle source

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.
save_projects() click to toggle source

Save all user projects.

@return [void]

# File lib/cocoapods/installer/user_project_integrator.rb, line 134
def save_projects
  user_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
targets_to_integrate() click to toggle source
# File lib/cocoapods/installer/user_project_integrator.rb, line 216
def targets_to_integrate
  targets
end
user_project_paths() click to toggle source

@return [Array<Pathname>] the paths of all the user projects referenced

by the target definitions.

@note Empty target definitions are ignored.

# File lib/cocoapods/installer/user_project_integrator.rb, line 208
def user_project_paths
  targets.map(&:user_project_path).compact.uniq
end
user_projects() click to toggle source
# File lib/cocoapods/installer/user_project_integrator.rb, line 212
def user_projects
  targets.map(&:user_project).compact.uniq
end
warn_about_xcconfig_overrides() click to toggle source

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 159
def warn_about_xcconfig_overrides
  targets.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
workspace_path() click to toggle source

@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 186
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