Commit 397eaa9a authored by Fabio Pelosin's avatar Fabio Pelosin

Merge branch 'dedicated-targets' of https://github.com/jasl8r/CocoaPods into…

Merge branch 'dedicated-targets' of https://github.com/jasl8r/CocoaPods into jasl8r-dedicated-targets

* 'dedicated-targets' of https://github.com/jasl8r/CocoaPods:
  Support xcconfig files per Podfile target
  Add specs to libraries for non-integrated targets
  Only add a single Manifest.lock phase when dealing with multiple specs
  Identify copy build phase by spec name
  Add per-spec static library targets
parents 71ab8a7e 717dc518
...@@ -44,7 +44,7 @@ module Pod ...@@ -44,7 +44,7 @@ module Pod
autoload :ExternalSources, 'cocoapods/external_sources' autoload :ExternalSources, 'cocoapods/external_sources'
autoload :Installer, 'cocoapods/installer' autoload :Installer, 'cocoapods/installer'
autoload :SourcesManager, 'cocoapods/sources_manager' autoload :SourcesManager, 'cocoapods/sources_manager'
autoload :Library, 'cocoapods/library' autoload :Target, 'cocoapods/target'
autoload :Project, 'cocoapods/project' autoload :Project, 'cocoapods/project'
autoload :Resolver, 'cocoapods/resolver' autoload :Resolver, 'cocoapods/resolver'
autoload :Sandbox, 'cocoapods/sandbox' autoload :Sandbox, 'cocoapods/sandbox'
......
...@@ -6,6 +6,10 @@ module Pod ...@@ -6,6 +6,10 @@ module Pod
# #
class XCConfig class XCConfig
# @return [Target] the library or target represented by this xcconfig.
#
attr_reader :library
# @return [Sandbox] the sandbox where the Pods project is installed. # @return [Sandbox] the sandbox where the Pods project is installed.
# #
attr_reader :sandbox attr_reader :sandbox
...@@ -20,12 +24,13 @@ module Pod ...@@ -20,12 +24,13 @@ module Pod
# #
attr_reader :relative_pods_root attr_reader :relative_pods_root
# @param [Sandbox] sandbox @see sandbox # @param [Target] library @see library
# @param [Array<LocalPod>] pods @see pods # @param [Array<Specification::Consumer>] spec_consumers @see spec_consumers
# @param [String] relative_pods_root @see relative_pods_root # @param [String] relative_pods_root @see relative_pods_root
# #
def initialize(sandbox, spec_consumers, relative_pods_root) def initialize(library, spec_consumers, relative_pods_root)
@sandbox = sandbox @library = library
@sandbox = library.sandbox
@spec_consumers = spec_consumers @spec_consumers = spec_consumers
@relative_pods_root = relative_pods_root @relative_pods_root = relative_pods_root
end end
...@@ -50,14 +55,17 @@ module Pod ...@@ -50,14 +55,17 @@ module Pod
ld_flags << ' -fobjc-arc' ld_flags << ' -fobjc-arc'
end end
public_headers = [library.public_headers.search_paths,
library.libraries.map { |lib| lib.public_headers.search_paths }].flatten
@xcconfig = Xcodeproj::Config.new({ @xcconfig = Xcodeproj::Config.new({
'ALWAYS_SEARCH_USER_PATHS' => 'YES', 'ALWAYS_SEARCH_USER_PATHS' => 'YES',
'OTHER_LDFLAGS' => ld_flags, 'OTHER_LDFLAGS' => ld_flags,
'HEADER_SEARCH_PATHS' => '${PODS_HEADERS_SEARCH_PATHS}', 'HEADER_SEARCH_PATHS' => '${PODS_HEADERS_SEARCH_PATHS}',
'PODS_ROOT' => relative_pods_root, 'PODS_ROOT' => relative_pods_root,
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_PUBLIC_HEADERS_SEARCH_PATHS}', 'PODS_HEADERS_SEARCH_PATHS' => '${PODS_PUBLIC_HEADERS_SEARCH_PATHS}',
'PODS_BUILD_HEADERS_SEARCH_PATHS' => quote(sandbox.build_headers.search_paths), 'PODS_BUILD_HEADERS_SEARCH_PATHS' => quote(library.build_headers.search_paths),
'PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quote(sandbox.public_headers.search_paths), 'PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quote(public_headers),
'GCC_PREPROCESSOR_DEFINITIONS' => 'COCOAPODS=1' 'GCC_PREPROCESSOR_DEFINITIONS' => 'COCOAPODS=1'
}) })
...@@ -77,7 +85,8 @@ module Pod ...@@ -77,7 +85,8 @@ module Pod
# #
def self.pods_project_settings def self.pods_project_settings
{ 'PODS_ROOT' => '${SRCROOT}', { 'PODS_ROOT' => '${SRCROOT}',
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_BUILD_HEADERS_SEARCH_PATHS}' } 'PODS_HEADERS_SEARCH_PATHS' => '${PODS_BUILD_HEADERS_SEARCH_PATHS} ${PODS_PUBLIC_HEADERS_SEARCH_PATHS}',
'USE_HEADERMAP' => 'NO' }
end end
# Generates and saves the xcconfig to the given path. # Generates and saves the xcconfig to the given path.
......
...@@ -60,7 +60,7 @@ module Pod ...@@ -60,7 +60,7 @@ module Pod
def specs_by_lib def specs_by_lib
result = {} result = {}
installer.libraries.each do |lib| installer.libraries.each do |lib|
result[installer.library_rep(lib)] = lib.specs result[installer.library_rep(lib)] = [lib.spec]
end end
result result
end end
...@@ -71,7 +71,7 @@ module Pod ...@@ -71,7 +71,7 @@ module Pod
def pods_by_lib def pods_by_lib
result = {} result = {}
installer.libraries.each do |lib| installer.libraries.each do |lib|
pod_names = lib.specs.map { |spec| spec.root.name }.uniq pod_names = [lib.spec.root.name]
pod_reps = pods.select { |rep| pod_names.include?(rep.name) } pod_reps = pods.select { |rep| pod_names.include?(rep.name) }
result[lib.target_definition] = pod_reps result[lib.target_definition] = pod_reps
end end
......
...@@ -108,7 +108,7 @@ module Pod ...@@ -108,7 +108,7 @@ module Pod
UI.section "Generating Pods project" do UI.section "Generating Pods project" do
prepare_pods_project prepare_pods_project
install_file_references install_file_references
install_targets install_libraries
run_post_install_hooks run_post_install_hooks
write_pod_project write_pod_project
write_lockfiles write_lockfiles
...@@ -134,10 +134,10 @@ module Pod ...@@ -134,10 +134,10 @@ module Pod
# #
attr_reader :names_of_pods_to_install attr_reader :names_of_pods_to_install
# @return [Array<Library>] The libraries generated by the installation # @return [Array<Target>] The Podfile targets containing library
# process. # dependencies.
# #
attr_reader :libraries attr_reader :targets
# @return [Array<Specification>] The specifications that where installed. # @return [Array<Specification>] The specifications that where installed.
# #
...@@ -165,7 +165,7 @@ module Pod ...@@ -165,7 +165,7 @@ module Pod
analyzer = Analyzer.new(sandbox, podfile, lockfile) analyzer = Analyzer.new(sandbox, podfile, lockfile)
analyzer.update_mode = update_mode analyzer.update_mode = update_mode
@analysis_result = analyzer.analyze @analysis_result = analyzer.analyze
@libraries = analyzer.result.libraries @targets = analyzer.result.targets
end end
# Prepares the Pods folder in order to be compatible with the most recent # Prepares the Pods folder in order to be compatible with the most recent
...@@ -186,8 +186,12 @@ module Pod ...@@ -186,8 +186,12 @@ module Pod
# @todo [#247] Clean the headers of only the pods to install. # @todo [#247] Clean the headers of only the pods to install.
# #
def clean_sandbox def clean_sandbox
sandbox.build_headers.implode! targets.each do |target|
sandbox.public_headers.implode! target.libraries.each do |library|
library.build_headers.implode!
library.public_headers.implode!
end
end
unless sandbox_state.deleted.empty? unless sandbox_state.deleted.empty?
title_options = { :verbose_prefix => "-> ".red } title_options = { :verbose_prefix => "-> ".red }
...@@ -203,11 +207,11 @@ module Pod ...@@ -203,11 +207,11 @@ module Pod
# created by the Pod source installer as well. # created by the Pod source installer as well.
# #
def create_file_accessors def create_file_accessors
libraries.each do |library| targets.each do |target|
library.specs.each do |spec| target.libraries.each do |library|
pod_root = sandbox.pod_dir(spec.root.name) pod_root = sandbox.pod_dir(library.spec.root.name)
path_list = Sandbox::PathList.new(pod_root) path_list = Sandbox::PathList.new(pod_root)
file_accessor = Sandbox::FileAccessor.new(path_list, spec.consumer(library.platform)) file_accessor = Sandbox::FileAccessor.new(path_list, library.spec.consumer(library.platform))
library.file_accessors ||= [] library.file_accessors ||= []
library.file_accessors << file_accessor library.file_accessors << file_accessor
end end
...@@ -243,11 +247,9 @@ module Pod ...@@ -243,11 +247,9 @@ module Pod
def install_source_of_pod(pod_name) def install_source_of_pod(pod_name)
specs_by_platform = {} specs_by_platform = {}
libraries.each do |library| libraries.each do |library|
specs = library.specs.select { |spec| spec.root.name == pod_name } if library.spec.root.name == pod_name
unless specs.empty?
specs_by_platform[library.platform] ||= [] specs_by_platform[library.platform] ||= []
specs_by_platform[library.platform].concat(specs) specs_by_platform[library.platform] << library.spec
end end
end end
...@@ -286,7 +288,7 @@ module Pod ...@@ -286,7 +288,7 @@ module Pod
@pods_project.add_podfile(config.podfile_path) @pods_project.add_podfile(config.podfile_path)
end end
sandbox.project = @pods_project sandbox.project = @pods_project
platforms = libraries.map(&:platform) platforms = targets.map(&:platform)
osx_deployment_target = platforms.select { |p| p.name == :osx }.map(&:deployment_target).min osx_deployment_target = platforms.select { |p| p.name == :osx }.map(&:deployment_target).min
ios_deployment_target = platforms.select { |p| p.name == :ios }.map(&:deployment_target).min ios_deployment_target = platforms.select { |p| p.name == :ios }.map(&:deployment_target).min
@pods_project.build_configurations.each do |build_configuration| @pods_project.build_configurations.each do |build_configuration|
...@@ -307,15 +309,14 @@ module Pod ...@@ -307,15 +309,14 @@ module Pod
installer.install! installer.install!
end end
# Installs the targets of the Pods projects and generates their support # Installs the library targets of the Pods projects and generates their
# files. # support files.
# #
# @return [void] # @return [void]
# #
def install_targets def install_libraries
UI.message"- Installing targets" do UI.message"- Installing libraries" do
libraries.sort_by(&:name).each do |library| libraries.sort_by(&:name).each do |library|
next if library.target_definition.empty?
target_installer = TargetInstaller.new(sandbox, library) target_installer = TargetInstaller.new(sandbox, library)
target_installer.install! target_installer.install!
end end
...@@ -368,7 +369,7 @@ module Pod ...@@ -368,7 +369,7 @@ module Pod
def integrate_user_project def integrate_user_project
UI.section "Integrating client #{'project'.pluralize(libraries.map(&:user_project_path).uniq.count) }" do UI.section "Integrating client #{'project'.pluralize(libraries.map(&:user_project_path).uniq.count) }" do
installation_root = config.installation_root installation_root = config.installation_root
integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, libraries) integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, targets)
integrator.integrate! integrator.integrate!
end end
end end
...@@ -545,7 +546,14 @@ module Pod ...@@ -545,7 +546,14 @@ module Pod
# @return [Array<Library>] The library. # @return [Array<Library>] The library.
# #
def libraries_using_spec(spec) def libraries_using_spec(spec)
libraries.select { |lib| lib.specs.include?(spec) } libraries.select { |lib| lib.spec == spec }
end
# @return [Array<Library>] The libraries generated by the installation
# process.
#
def libraries
targets.map(&:libraries).flatten
end end
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
......
...@@ -51,10 +51,11 @@ module Pod ...@@ -51,10 +51,11 @@ module Pod
@result.podfile_state = generate_podfile_state @result.podfile_state = generate_podfile_state
@locked_dependencies = generate_version_locking_dependencies @locked_dependencies = generate_version_locking_dependencies
@result.libraries = generated_libraries compute_target_platforms
fetch_external_sources if allow_fetches fetch_external_sources if allow_fetches
@result.specs_by_target = resolve_dependencies @result.specs_by_target = resolve_dependencies
@result.specifications = generate_specifications @result.specifications = generate_specifications
@result.targets = generate_targets
@result.sandbox_state = generate_sandbox_state @result.sandbox_state = generate_sandbox_state
@result @result
end end
...@@ -158,44 +159,59 @@ module Pod ...@@ -158,44 +159,59 @@ module Pod
# Creates the models that represent the libraries generated by CocoaPods. # Creates the models that represent the libraries generated by CocoaPods.
# #
# @note The libraries are generated before the resolution process
# because it might be necessary to infer the platform from the
# user targets, which in turns requires to identify the user
# project.
#
# @note The specification of the libraries are added in the
# {#resolve_dependencies} step.
#
# @return [Array<Libraries>] the generated libraries. # @return [Array<Libraries>] the generated libraries.
# #
def generated_libraries def generate_targets
libraries = [] targets = []
podfile.target_definition_list.each do |target_definition| result.specs_by_target.each do |target_definition, specs|
lib = Library.new(target_definition) libs_by_name = {}
target = Target.new(target_definition, sandbox)
targets << target
specs.each do |spec|
lib_target = Podfile::TargetDefinition.from_hash(target_definition.to_hash, target_definition.parent)
if target_definition.name == 'Pods'
lib_target.name = spec.name.gsub('/', '-')
else
lib_target.name = "#{target_definition.name}-#{spec.name.gsub('/', '-')}"
end
lib = Target.new(lib_target, sandbox)
libs_by_name[spec.name] = lib
lib.support_files_root = sandbox.library_support_files_dir(lib.name) lib.support_files_root = sandbox.library_support_files_dir(lib.name)
lib.platform = target_definition.platform
lib.spec = spec
target.support_files_root = sandbox.library_support_files_dir(target.name)
target.platform = target_definition.platform
if config.integrate_targets? if config.integrate_targets?
project_path = compute_user_project_path(target_definition) project_path = compute_user_project_path(target_definition)
user_project = Xcodeproj::Project.new(project_path) user_project = Xcodeproj::Project.new(project_path)
targets = compute_user_project_targets(target_definition, user_project) native_targets = compute_user_project_targets(target_definition, user_project)
lib.user_project_path = project_path lib.user_project_path = project_path
lib.client_root = project_path.dirname lib.client_root = project_path.dirname
lib.user_target_uuids = targets.map(&:uuid) lib.user_build_configurations = compute_user_build_configurations(target_definition, native_targets)
lib.user_build_configurations = compute_user_build_configurations(target_definition, targets)
lib.platform = compute_platform_for_target_definition(target_definition, targets) target.user_project_path = project_path
target.client_root = project_path.dirname
target.user_target_uuids = native_targets.map(&:uuid)
target.user_build_configurations = compute_user_build_configurations(target_definition, native_targets)
else else
unless target_definition.platform
raise Informative, "It is necessary to specify the platform in the Podfile if not integrating."
end
lib.client_root = config.installation_root lib.client_root = config.installation_root
lib.user_target_uuids = [] lib.user_target_uuids = []
lib.user_build_configurations = {} lib.user_build_configurations = {}
lib.platform = target_definition.platform
end end
libraries << lib target.libraries << lib
end end
libraries
target.libraries.each do |library|
library.libraries = library.spec.dependencies(library.platform).map { |dep| libs_by_name[dep.name] }
end
end
targets
end end
# Generates dependencies that require the specific version of the Pods # Generates dependencies that require the specific version of the Pods
...@@ -263,8 +279,6 @@ module Pod ...@@ -263,8 +279,6 @@ module Pod
# Converts the Podfile in a list of specifications grouped by target. # Converts the Podfile in a list of specifications grouped by target.
# #
# @note In this step the specs are added to the libraries.
#
# @note As some dependencies might have external sources the resolver # @note As some dependencies might have external sources the resolver
# is aware of the {Sandbox} and interacts with it to download the # is aware of the {Sandbox} and interacts with it to download the
# podspecs of the external sources. This is necessary because the # podspecs of the external sources. This is necessary because the
...@@ -284,17 +298,10 @@ module Pod ...@@ -284,17 +298,10 @@ module Pod
# #
def resolve_dependencies def resolve_dependencies
specs_by_target = nil specs_by_target = nil
UI.section "Resolving dependencies of #{UI.path podfile.defined_in_file}" do UI.section "Resolving dependencies of #{UI.path podfile.defined_in_file}" do
resolver = Resolver.new(sandbox, podfile, locked_dependencies) resolver = Resolver.new(sandbox, podfile, locked_dependencies)
specs_by_target = resolver.resolve specs_by_target = resolver.resolve
end end
specs_by_target.each do |target_definition, specs|
lib = result.libraries.find { |l| l.target_definition == target_definition}
lib.specs = specs
end
specs_by_target specs_by_target
end end
...@@ -449,6 +456,29 @@ module Pod ...@@ -449,6 +456,29 @@ module Pod
Platform.new(name, deployment_target) Platform.new(name, deployment_target)
end end
# Precompute the platforms for each target_definition in the Podfile
#
# @note The platforms are computed and added to each target_definition
# because it might be necessary to infer the platform from the
# user targets.
#
# @return [void]
#
def compute_target_platforms
podfile.target_definition_list.each do |target_definition|
if config.integrate_targets?
project_path = compute_user_project_path(target_definition)
user_project = Xcodeproj::Project.new(project_path)
targets = compute_user_project_targets(target_definition, user_project)
platform = compute_platform_for_target_definition(target_definition, targets)
else
unless target_definition.platform
raise Informative, "It is necessary to specify the platform in the Podfile if not integrating."
end
end
end
end
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
class AnalysisResult class AnalysisResult
...@@ -472,10 +502,10 @@ module Pod ...@@ -472,10 +502,10 @@ module Pod
# #
attr_accessor :sandbox_state attr_accessor :sandbox_state
# @return [Array<Library>] the libraries generated by the target # @return [Array<Target>] The Podfile targets containing library
# definitions. # dependencies.
# #
attr_accessor :libraries attr_accessor :targets
end end
......
...@@ -107,18 +107,19 @@ module Pod ...@@ -107,18 +107,19 @@ module Pod
# #
def link_headers def link_headers
UI.message "- Linking headers" do UI.message "- Linking headers" do
libraries.each do |library|
file_accessors.each do |file_accessor| library.file_accessors.each do |file_accessor|
headers_sandbox = Pathname.new(file_accessor.spec.root.name) headers_sandbox = Pathname.new(file_accessor.spec.root.name)
sandbox.build_headers.add_search_path(headers_sandbox) library.build_headers.add_search_path(headers_sandbox)
sandbox.public_headers.add_search_path(headers_sandbox) library.public_headers.add_search_path(headers_sandbox)
header_mappings(headers_sandbox, file_accessor, file_accessor.headers).each do |namespaced_path, files| header_mappings(headers_sandbox, file_accessor, file_accessor.headers).each do |namespaced_path, files|
sandbox.build_headers.add_files(namespaced_path, files) library.build_headers.add_files(namespaced_path, files)
end end
header_mappings(headers_sandbox, file_accessor, file_accessor.public_headers).each do |namespaced_path, files| header_mappings(headers_sandbox, file_accessor, file_accessor.public_headers).each do |namespaced_path, files|
sandbox.public_headers.add_files(namespaced_path, files) library.public_headers.add_files(namespaced_path, files)
end
end end
end end
end end
......
...@@ -140,7 +140,7 @@ module Pod ...@@ -140,7 +140,7 @@ module Pod
def create_xcconfig_file def create_xcconfig_file
path = library.xcconfig_path path = library.xcconfig_path
UI.message "- Generating xcconfig file at #{UI.path(path)}" do UI.message "- Generating xcconfig file at #{UI.path(path)}" do
gen = Generator::XCConfig.new(sandbox, spec_consumers, library.relative_pods_root) gen = Generator::XCConfig.new(library, spec_consumers, library.relative_pods_root)
gen.set_arc_compatibility_flag = target_definition.podfile.set_arc_compatibility_flag? gen.set_arc_compatibility_flag = target_definition.podfile.set_arc_compatibility_flag?
gen.save_as(path) gen.save_as(path)
library.xcconfig = gen.xcconfig library.xcconfig = gen.xcconfig
...@@ -161,7 +161,7 @@ module Pod ...@@ -161,7 +161,7 @@ module Pod
def create_target_environment_header def create_target_environment_header
path = library.target_environment_header_path path = library.target_environment_header_path
UI.message "- Generating target environment header at #{UI.path(path)}" do UI.message "- Generating target environment header at #{UI.path(path)}" do
generator = Generator::TargetEnvironmentHeader.new(library.specs) generator = Generator::TargetEnvironmentHeader.new([library.spec])
generator.save_as(path) generator.save_as(path)
add_file_to_support_group(path) add_file_to_support_group(path)
end end
......
...@@ -35,9 +35,9 @@ module Pod ...@@ -35,9 +35,9 @@ module Pod
# #
attr_reader :installation_root attr_reader :installation_root
# @return [Library] the libraries generated by the installer. # @return [Array<Target>] the targets represented in the Podfile.
# #
attr_reader :libraries attr_reader :targets
# @param [Podfile] podfile @see #podfile # @param [Podfile] podfile @see #podfile
# @param [Sandbox] sandbox @see #sandbox # @param [Sandbox] sandbox @see #sandbox
...@@ -46,11 +46,11 @@ module Pod ...@@ -46,11 +46,11 @@ module Pod
# #
# @todo Too many initialization arguments # @todo Too many initialization arguments
# #
def initialize(podfile, sandbox, installation_root, libraries) def initialize(podfile, sandbox, installation_root, targets)
@podfile = podfile @podfile = podfile
@sandbox = sandbox @sandbox = sandbox
@installation_root = installation_root @installation_root = installation_root
@libraries = libraries @targets = targets
end end
# Integrates the user projects associated with the {TargetDefinitions} # Integrates the user projects associated with the {TargetDefinitions}
...@@ -110,8 +110,8 @@ module Pod ...@@ -110,8 +110,8 @@ module Pod
# @return [void] # @return [void]
# #
def integrate_user_targets def integrate_user_targets
libraries_to_integrate.sort_by(&:name).each do |lib| targets_to_integrate.sort_by(&:name).each do |target|
TargetIntegrator.new(lib).integrate! TargetIntegrator.new(target).integrate!
end end
end end
...@@ -163,14 +163,14 @@ module Pod ...@@ -163,14 +163,14 @@ module Pod
# @note Empty target definitions are ignored. # @note Empty target definitions are ignored.
# #
def user_project_paths def user_project_paths
libraries.map do |lib| targets.map do |target|
lib.user_project_path target.user_project_path
end.compact.uniq end.compact.uniq
end end
def libraries_to_integrate def targets_to_integrate
libraries.reject { |lib| lib.target_definition.empty? } targets.reject { |target| target.target_definition.empty? }
end end
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
......
...@@ -9,14 +9,14 @@ module Pod ...@@ -9,14 +9,14 @@ module Pod
# #
class TargetIntegrator class TargetIntegrator
# @return [Library] the library that should be integrated. # @return [Target] the target that should be integrated.
# #
attr_reader :library attr_reader :target
# @param [Library] library @see #target_definition # @param [Target] target @see #target_definition
# #
def initialize(library) def initialize(target)
@library = library @target = target
end end
# Integrates the user project targets. Only the targets that do **not** # Integrates the user project targets. Only the targets that do **not**
...@@ -26,8 +26,8 @@ module Pod ...@@ -26,8 +26,8 @@ module Pod
# @return [void] # @return [void]
# #
def integrate! def integrate!
return if targets.empty?
UI.section(integration_message) do UI.section(integration_message) do
create_xcconfig_file
add_xcconfig_base_configuration add_xcconfig_base_configuration
add_pods_library add_pods_library
add_copy_resources_script_phase add_copy_resources_script_phase
...@@ -36,40 +36,17 @@ module Pod ...@@ -36,40 +36,17 @@ module Pod
end end
end end
# @return [Array<PBXNativeTarget>] the list of targets that the Pods # @return [Array<PBXNativeTarget>] the user targets for integration.
# lib that need to be integrated.
# #
# @note A target is considered integrated if it already references def native_targets
# @native_targets ||= target.user_target_uuids.map { |uuid| user_project.objects_by_uuid[uuid] }
def targets
unless @targets
target_uuids = library.user_target_uuids
targets = target_uuids.map do |uuid|
target = user_project.objects_by_uuid[uuid]
unless target
raise Informative, "[Bug] Unable to find the target with " \
"the `#{uuid}` UUID for the `#{library}` library"
end
target
end
non_integrated = targets.reject do |target|
target.frameworks_build_phase.files.any? do |build_file|
file_ref = build_file.file_ref
file_ref &&
file_ref.isa == 'PBXFileReference' &&
file_ref.display_name == library.product_name
end
end
@targets = non_integrated
end
@targets
end end
# Read the project from the disk to ensure that it is up to date as # Read the project from the disk to ensure that it is up to date as
# other TargetIntegrators might have modified it. # other TargetIntegrators might have modified it.
# #
def user_project def user_project
@user_project ||= Xcodeproj::Project.new(library.user_project_path) @user_project ||= Xcodeproj::Project.new(target.user_project_path)
end end
# @return [String] a string representation suitable for debugging. # @return [String] a string representation suitable for debugging.
...@@ -84,6 +61,29 @@ module Pod ...@@ -84,6 +61,29 @@ module Pod
private private
# @return [Specification::Consumer] the consumer for the specifications.
#
def spec_consumers
@spec_consumers ||= target.libraries.map(&:file_accessors).flatten.map(&:spec_consumer)
end
# Generates the contents of the xcconfig file and saves it to disk.
#
# @note The `ALWAYS_SEARCH_USER_PATHS` flag is enabled to support
# libraries like `EmbedReader`.
#
# @return [void]
#
def create_xcconfig_file
path = target.xcconfig_path
UI.message "- Generating xcconfig file at #{UI.path(path)}" do
gen = Generator::XCConfig.new(target, spec_consumers, target.relative_pods_root)
gen.set_arc_compatibility_flag = target.target_definition.podfile.set_arc_compatibility_flag?
gen.save_as(path)
target.xcconfig = gen.xcconfig
end
end
# Adds the `xcconfig` configurations files generated for the current # Adds the `xcconfig` configurations files generated for the current
# {TargetDefinition} to the build configurations of the targets that # {TargetDefinition} to the build configurations of the targets that
# should be integrated. # should be integrated.
...@@ -98,10 +98,11 @@ module Pod ...@@ -98,10 +98,11 @@ module Pod
# @return [void] # @return [void]
# #
def add_xcconfig_base_configuration def add_xcconfig_base_configuration
xcconfig = user_project.new_file(library.xcconfig_relative_path) xcconfig = user_project.files.select { |f| f.path == target.xcconfig_relative_path }.first ||
targets.each do |target| user_project.new_file(target.xcconfig_relative_path)
check_overridden_build_settings(library.xcconfig, target) native_targets.each do |native_target|
target.build_configurations.each do |config| check_overridden_build_settings(target.xcconfig, native_target)
native_target.build_configurations.each do |config|
config.base_configuration_reference = xcconfig config.base_configuration_reference = xcconfig
end end
end end
...@@ -114,9 +115,14 @@ module Pod ...@@ -114,9 +115,14 @@ module Pod
# #
def add_pods_library def add_pods_library
frameworks = user_project.frameworks_group frameworks = user_project.frameworks_group
pods_library = frameworks.new_static_library(library.label) native_targets.each do |native_target|
targets.each do |target| target.libraries.each do |library|
target.frameworks_build_phase.add_file_reference(pods_library) lib = frameworks.files.select { |f| f.path == library.product_name }.first ||
frameworks.new_static_library(library.name)
unless native_target.frameworks_build_phase.files_references.include?(lib)
native_target.frameworks_build_phase.add_file_reference(lib)
end
end
end end
end end
...@@ -127,12 +133,16 @@ module Pod ...@@ -127,12 +133,16 @@ module Pod
# @return [void] # @return [void]
# #
def add_copy_resources_script_phase def add_copy_resources_script_phase
targets.each do |target| native_targets.each do |native_target|
phase = target.new_shell_script_build_phase('Copy Pods Resources') target.libraries.each do |library|
phase_name = "Copy Pods Resources (#{library.name})"
next if native_target.shell_script_build_phases.select { |bp| bp.name == phase_name }.first
phase = native_target.new_shell_script_build_phase(phase_name)
path = library.copy_resources_script_relative_path path = library.copy_resources_script_relative_path
phase.shell_script = %{"#{path}"\n} phase.shell_script = %{"#{path}"\n}
end end
end end
end
# Adds a shell script build phase responsible for checking if the Pods # Adds a shell script build phase responsible for checking if the Pods
# locked in the Pods/Manifest.lock file are in sync with the Pods defined # locked in the Pods/Manifest.lock file are in sync with the Pods defined
...@@ -144,10 +154,12 @@ module Pod ...@@ -144,10 +154,12 @@ module Pod
# @return [void] # @return [void]
# #
def add_check_manifest_lock_script_phase def add_check_manifest_lock_script_phase
targets.each do |target| phase_name = 'Check Pods Manifest.lock'
phase = target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase) native_targets.each do |native_target|
target.build_phases.unshift(phase) next if native_target.shell_script_build_phases.any? { |phase| phase.name == phase_name }
phase.name = 'Check Pods Manifest.lock' phase = native_target.project.new(Xcodeproj::Project::Object::PBXShellScriptBuildPhase)
native_target.build_phases.unshift(phase)
phase.name = phase_name
phase.shell_script = <<-EOS.strip_heredoc phase.shell_script = <<-EOS.strip_heredoc
diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null diff "${PODS_ROOT}/../Podfile.lock" "${PODS_ROOT}/Manifest.lock" > /dev/null
if [[ $? != 0 ]] ; then if [[ $? != 0 ]] ; then
...@@ -165,7 +177,7 @@ module Pod ...@@ -165,7 +177,7 @@ module Pod
# @return [void] # @return [void]
# #
def save_user_project def save_user_project
user_project.save_as(library.user_project_path) user_project.save_as(target.user_project_path)
end end
#---------------------------------------------------------------------# #---------------------------------------------------------------------#
...@@ -179,11 +191,11 @@ module Pod ...@@ -179,11 +191,11 @@ module Pod
# #
# @return [void] # @return [void]
# #
def check_overridden_build_settings(xcconfig, target) def check_overridden_build_settings(xcconfig, native_target)
return unless xcconfig return unless xcconfig
configs_by_overridden_key = {} configs_by_overridden_key = {}
target.build_configurations.each do |config| native_target.build_configurations.each do |config|
xcconfig.attributes.keys.each do |key| xcconfig.attributes.keys.each do |key|
target_value = config.build_settings[key] target_value = config.build_settings[key]
...@@ -194,13 +206,13 @@ module Pod ...@@ -194,13 +206,13 @@ module Pod
end end
configs_by_overridden_key.each do |key, config_names| configs_by_overridden_key.each do |key, config_names|
name = "#{target.name} [#{config_names.join(' - ')}]" name = "#{native_target.name} [#{config_names.join(' - ')}]"
actions = [ actions = [
"Use the `$(inherited)` flag, or", "Use the `$(inherited)` flag, or",
"Remove the build settings from the target." "Remove the build settings from the target."
] ]
UI.warn("The target `#{name}` overrides the `#{key}` build " \ UI.warn("The target `#{name}` overrides the `#{key}` build " \
"setting defined in `#{library.xcconfig_relative_path}'.", "setting defined in `#{target.xcconfig_relative_path}'.",
actions) actions)
end end
end end
...@@ -210,10 +222,10 @@ module Pod ...@@ -210,10 +222,10 @@ module Pod
# integration. # integration.
# #
def integration_message def integration_message
"Integrating `#{library.product_name}` into " \ "Integrating #{'library'.pluralize(target.libraries.size)} " \
"#{'target'.pluralize(targets.size)} " \ "`#{target.libraries.map(&:name).to_sentence}` " \
"`#{targets.map(&:name).to_sentence}` " \ "into target #{target.name} " \
"of project #{UI.path library.user_project_path}." "of project #{UI.path target.user_project_path}."
end end
#---------------------------------------------------------------------# #---------------------------------------------------------------------#
......
module Pod module Pod
# Model class which describes a Pods library. # Model class which describes a Pods target.
# #
# The Library class stores and provides the information necessary for # The Target class stores and provides the information necessary for
# working with a library in the Pods project and in the user projects # working with a target in the Podfile and it's dependent libraries.
# through the installation process. # This class is used to represent both the targets and their libraries.
# #
class Library class Target
# @return [PBXNativeTarget] the target definition of the Podfile that # @return [PBXNativeTarget] the target definition of the Podfile that
# generated this library. # generated this target.
# #
attr_reader :target_definition attr_reader :target_definition
# @return [Sandbox] The sandbox where the Pods should be installed.
#
attr_reader :sandbox
# @return [HeadersStore] the header directory for the library.
#
attr_reader :build_headers
# @return [HeadersStore] the public header directory for the library.
#
attr_reader :public_headers
# @param [TargetDefinition] target_definition @see target_definition # @param [TargetDefinition] target_definition @see target_definition
# @param [PBXNativeTarget] target @see target # @param [Sandbox] sandbox @see sandbox
# #
def initialize(target_definition) def initialize(target_definition, sandbox)
@target_definition = target_definition @target_definition = target_definition
@sandbox = sandbox
@build_headers = Sandbox::HeadersStore.new(sandbox, "BuildHeaders/#{target_definition.name}")
@public_headers = Sandbox::HeadersStore.new(sandbox, "Headers/#{target_definition.name}")
@libraries = []
end end
# @return [String] the label for the library. # @return [String] the label for the library.
...@@ -29,13 +45,13 @@ module Pod ...@@ -29,13 +45,13 @@ module Pod
# @return [String] the name of the library. # @return [String] the name of the library.
# #
def name def name
target_definition.label.to_s label
end end
# @return [String] the name of the library. # @return [String] the name of the library.
# #
def product_name def product_name
"lib#{target_definition.label}.a" "lib#{label}.a"
end end
# @return [String] A string suitable for debugging. # @return [String] A string suitable for debugging.
...@@ -99,15 +115,19 @@ module Pod ...@@ -99,15 +115,19 @@ module Pod
# #
attr_accessor :xcconfig attr_accessor :xcconfig
# @return [Array<Specification>] the specifications of this library. # @return [Specification] the specification for this library.
# #
attr_accessor :specs attr_accessor :spec
# @return [Array<Sandbox::FileAccessor>] the file accessors for the # @return [Array<Sandbox::FileAccessor>] the file accessors for the
# specifications of this library. # specifications of this library.
# #
attr_accessor :file_accessors attr_accessor :file_accessors
# @return [Array<Target>] the dependencies for this target (or library).
#
attr_accessor :libraries
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# @!group Support files # @!group Support files
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment