Commit 01fc9441 authored by Jeremy Slater's avatar Jeremy Slater

Split targets and supporting classes into single purpose classes

Target class converted to PodTarget and SpecTarget representing Pod 
integration targets and podspec targets.
TargetInstaller converted to PodTargetInstaller and 
SpecTargetInstaller to handle variations in installing Pod targets 
and spec targets.
XCConfig generator converted to PodXCConfig, PublicSpecXCCconfig and 
PrivateSpecXCConfig classes to handle generating the different 
xcconfig files.
Requires Xcodeproj file changes to support namespaced xcconfig files.
parent b9dfaa9d
......@@ -44,7 +44,8 @@ module Pod
autoload :ExternalSources, 'cocoapods/external_sources'
autoload :Installer, 'cocoapods/installer'
autoload :SourcesManager, 'cocoapods/sources_manager'
autoload :Target, 'cocoapods/target'
autoload :PodTarget, 'cocoapods/target'
autoload :SpecTarget, 'cocoapods/target'
autoload :Project, 'cocoapods/project'
autoload :Resolver, 'cocoapods/resolver'
autoload :Sandbox, 'cocoapods/sandbox'
......@@ -60,7 +61,9 @@ module Pod
autoload :Plist, 'cocoapods/generator/acknowledgements/plist'
autoload :PrefixHeader, 'cocoapods/generator/prefix_header'
autoload :TargetEnvironmentHeader, 'cocoapods/generator/target_environment_header'
autoload :XCConfig, 'cocoapods/generator/xcconfig'
autoload :PodXCConfig, 'cocoapods/generator/xcconfig'
autoload :PublicSpecXCConfig, 'cocoapods/generator/xcconfig'
autoload :PrivateSpecXCConfig, 'cocoapods/generator/xcconfig'
end
module Hooks
......
......@@ -5,105 +5,20 @@ module Pod
# for each Pod and for each Pod target definition. The aggregates the
# configurations of the Pods and define target specific settings.
#
class XCConfig
class AbstractXCConfig
# @return [Target] the library or target represented by this xcconfig.
#
attr_reader :library
# @return [Sandbox] the sandbox where the Pods project is installed.
#
attr_reader :sandbox
# @return [Array<Specification::Consumer>] the consumers for the
# specifications of the library which needs the xcconfig.
#
attr_reader :spec_consumers
# @return [String] the relative path of the Pods root respect the user
# project that should be integrated by this library.
#
attr_reader :relative_pods_root
# @param [Target] library @see library
# @param [Array<Specification::Consumer>] spec_consumers @see spec_consumers
# @param [String] relative_pods_root @see relative_pods_root
#
def initialize(library, spec_consumers, relative_pods_root)
def initialize(library)
@library = library
@sandbox = library.sandbox
@spec_consumers = spec_consumers
@relative_pods_root = relative_pods_root
end
# @return [Bool] whether the Podfile specifies to add the `-fobjc-arc`
# flag for compatibility.
#
attr_accessor :set_arc_compatibility_flag
#-----------------------------------------------------------------------#
# Generates the xcconfig for the library.
#
# @note The xcconfig file for a spec derived target includes namespaced
# configuration values, the private build headers and headermap
# disabled. The xcconfig file for the Pods integration target
# then includes the spec xcconfig and incorporates the namespaced
# configuration values like preprocessor overrides or frameworks
# to link with.
#
# @return [Xcodeproj::Config]
#
def generate
ld_flags = '-ObjC'
if set_arc_compatibility_flag && spec_consumers.any? { |consumer| consumer.requires_arc }
ld_flags << ' -fobjc-arc'
end
if library.spec
config = {
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
'OTHER_LDFLAGS' => ld_flags,
'PODS_ROOT' => '${SRCROOT}',
'HEADER_SEARCH_PATHS' => quote(library.build_headers.search_paths) + ' ' + quote(sandbox.public_headers.search_paths),
'GCC_PREPROCESSOR_DEFINITIONS' => 'COCOAPODS=1',
# 'USE_HEADERMAP' => 'NO'
}
consumer_xcconfig(library.consumer).to_hash.each do |k, v|
prefixed_key = library.xcconfig_prefix + k
config[k] = "#{config[k]} ${#{prefixed_key}}"
config[prefixed_key] = v
end
else
config = {
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
'OTHER_LDFLAGS' => ld_flags,
'HEADER_SEARCH_PATHS' => '${PODS_HEADERS_SEARCH_PATHS}',
'PODS_ROOT' => relative_pods_root,
'PODS_HEADERS_SEARCH_PATHS' => '${PODS_PUBLIC_HEADERS_SEARCH_PATHS}',
'PODS_BUILD_HEADERS_SEARCH_PATHS' => '',
'PODS_PUBLIC_HEADERS_SEARCH_PATHS' => quote(sandbox.public_headers.search_paths),
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
}
library.libraries.each do |lib|
consumer_xcconfig(lib.consumer).to_hash.each do |k, v|
prefixed_key = lib.xcconfig_prefix + k
config[k] = "#{config[k]} ${#{prefixed_key}}"
end
end
end
@xcconfig = Xcodeproj::Config.new(config)
@xcconfig.includes = library.libraries.map(&:name) unless library.spec
@xcconfig
end
# @return [Xcodeproj::Config] The generated xcconfig.
#
attr_reader :xcconfig
# Generates and saves the xcconfig to the given path.
#
# @param [Pathname] path
......@@ -112,7 +27,7 @@ module Pod
# @return [void]
#
def save_as(path)
path.open('w') { |file| file.write(generate) }
generate.save_as(path)
end
#-----------------------------------------------------------------------#
......@@ -121,19 +36,6 @@ module Pod
private
# @return [String] the default linker flags. `-ObjC` is always included
# while `-fobjc-arc` is included only if requested in the
# Podfile.
#
def default_ld_flags
flags = %w[ -ObjC ]
requires_arc = pods.any? { |pod| pod.requires_arc? }
if requires_arc && set_arc_compatibility_flag
flags << '-fobjc-arc'
end
flags.join(" ")
end
# Converts an array of strings to a single string where the each string
# is surrounded by double quotes and separated by a space. Used to
# represent strings in a xcconfig file.
......@@ -159,8 +61,7 @@ module Pod
# @return [Xcodeproj::Config]
#
def consumer_xcconfig(consumer)
xcconfig = Xcodeproj::Config.new()
xcconfig.merge!(consumer.xcconfig)
xcconfig = Xcodeproj::Config.new(consumer.xcconfig)
xcconfig.libraries.merge(consumer.libraries)
xcconfig.frameworks.merge(consumer.frameworks)
xcconfig.weak_frameworks.merge(consumer.weak_frameworks)
......@@ -206,6 +107,122 @@ module Pod
#-----------------------------------------------------------------------#
end
#-------------------------------------------------------------------------#
class PodXCConfig < AbstractXCConfig
# Generates the xcconfig for the Pod integration target.
#
# @note The xcconfig file for a Pods integration target includes the
# namespaced xcconfig files for each spec target dependency.
# Each namespaced configuration value is merged into the Pod
# xcconfig file.
#
# @return [Xcodeproj::Config]
#
def generate
ld_flags = '-ObjC'
if library.target_definition.podfile.set_arc_compatibility_flag?
ld_flags << ' -fobjc-arc'
end
config = {
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
'OTHER_LDFLAGS' => ld_flags,
'HEADER_SEARCH_PATHS' => quote(sandbox.public_headers.search_paths),
'PODS_ROOT' => library.relative_pods_root,
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
}
library.libraries.each do |lib|
consumer_xcconfig(lib.consumer).to_hash.each do |k, v|
prefixed_key = lib.xcconfig_prefix + k
config[k] = "#{config[k]} ${#{prefixed_key}}"
end
end
xcconfig = Xcodeproj::Config.new(config)
xcconfig.includes = library.libraries.map(&:name)
xcconfig
end
end
#-------------------------------------------------------------------------#
class PublicSpecXCConfig < AbstractXCConfig
# Generates and saves the xcconfig to the given path.
#
# @param [Pathname] path
# the path where the prefix header should be stored.
#
# @note The public xcconfig file for a spec target is completely
# namespaced to prevent configuration value collision with other
# spec configurations.
#
# @return [void]
#
def save_as(path)
generate.save_as(path, library.xcconfig_prefix)
end
# Generates the xcconfig for the library.
#
# @note The xcconfig file for a public spec target includes the
# standard podspec defined values including libraries,
# frameworks, weak frameworks and xcconfig overrides.
#
# @return [Xcodeproj::Config]
#
def generate
consumer_xcconfig(library.consumer)
end
end
#-------------------------------------------------------------------------#
class PrivateSpecXCConfig < AbstractXCConfig
# Generates the xcconfig for the library.
#
# @note The private xcconfig file for a spec target includes the public
# namespaced xcconfig file and merges the configuration values
# with the default private configuration values.
#
# @return [Xcodeproj::Config]
#
def generate
ld_flags = '-ObjC'
if library.consumer.requires_arc?
ld_flags << ' -fobjc-arc'
end
config = {
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
'OTHER_LDFLAGS' => ld_flags,
'PODS_ROOT' => '${SRCROOT}',
'HEADER_SEARCH_PATHS' => quote(library.build_headers.search_paths) + ' ' + quote(sandbox.public_headers.search_paths),
'GCC_PREPROCESSOR_DEFINITIONS' => 'COCOAPODS=1',
# 'USE_HEADERMAP' => 'NO'
}
consumer_xcconfig(library.consumer).to_hash.each do |k, v|
prefixed_key = library.xcconfig_prefix + k
config[k] = "#{config[k]} ${#{prefixed_key}}"
end
xcconfig = Xcodeproj::Config.new(config)
xcconfig.includes = [library.name]
xcconfig
end
end
#-------------------------------------------------------------------------#
end
end
......@@ -31,7 +31,8 @@ module Pod
autoload :Analyzer, 'cocoapods/installer/analyzer'
autoload :FileReferencesInstaller, 'cocoapods/installer/file_references_installer'
autoload :PodSourceInstaller, 'cocoapods/installer/pod_source_installer'
autoload :TargetInstaller, 'cocoapods/installer/target_installer'
autoload :PodTargetInstaller, 'cocoapods/installer/target_installer'
autoload :SpecTargetInstaller, 'cocoapods/installer/target_installer'
autoload :UserProjectIntegrator, 'cocoapods/installer/user_project_integrator'
include Config::Mixin
......@@ -135,7 +136,7 @@ module Pod
#
attr_reader :names_of_pods_to_install
# @return [Array<Target>] The Podfile targets containing library
# @return [Array<PodTarget>] The Podfile targets containing library
# dependencies.
#
attr_reader :targets
......@@ -315,7 +316,13 @@ module Pod
UI.message"- Installing libraries" do
libraries.sort_by(&:name).each do |library|
next if library.target_definition.empty?
target_installer = TargetInstaller.new(sandbox, library)
target_installer = SpecTargetInstaller.new(sandbox, library)
target_installer.install!
end
targets.sort_by(&:name).each do |target|
next if target.target_definition.empty?
target_installer = PodTargetInstaller.new(sandbox, target)
target_installer.install!
end
end
......@@ -381,7 +388,7 @@ module Pod
# information in the lockfile.
#
def integrate_user_project
UI.section "Integrating client #{'project'.pluralize(libraries.map(&:user_project_path).uniq.count) }" do
UI.section "Integrating client #{'project'.pluralize(targets.map(&:user_project_path).uniq.count) }" do
installation_root = config.installation_root
integrator = UserProjectIntegrator.new(podfile, sandbox, installation_root, targets)
integrator.integrate!
......@@ -567,7 +574,7 @@ module Pod
# process.
#
def libraries
targets + targets.map(&:libraries).flatten
targets.map(&:libraries).flatten
end
#-------------------------------------------------------------------------#
......
......@@ -164,12 +164,9 @@ module Pod
def generate_targets
targets = []
result.specs_by_target.each do |target_definition, specs|
target = Target.new(target_definition, sandbox)
target = PodTarget.new(target_definition, sandbox)
targets << target
target.support_files_root = sandbox.library_support_files_dir(target.name)
target.platform = target_definition.platform
if config.integrate_targets?
project_path = compute_user_project_path(target_definition)
user_project = Xcodeproj::Project.new(project_path)
......@@ -186,22 +183,9 @@ module Pod
end
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)
lib.spec = spec
lib.support_files_root = target.support_files_root
lib.platform = target.platform
lib.user_project_path = target.user_project_path
lib.client_root = target.client_root
lib.user_build_configurations = target.user_build_configurations
target.libraries << lib
spec_target = SpecTarget.new(spec, target_definition, sandbox)
spec_target.user_build_configurations = target.user_build_configurations
target.libraries << spec_target
end
end
targets
......
This diff is collapsed.
......@@ -6,7 +6,7 @@ module Pod
# working with a target in the Podfile and it's dependent libraries.
# This class is used to represent both the targets and their libraries.
#
class Target
class AbstractTarget
# @return [PBXNativeTarget] the target definition of the Podfile that
# generated this target.
......@@ -17,27 +17,6 @@ module Pod
#
attr_reader :sandbox
# @return [HeadersStore] the header directory for the library.
#
attr_reader :build_headers
# @param [TargetDefinition] target_definition @see target_definition
# @param [Sandbox] sandbox @see sandbox
#
def initialize(target_definition, sandbox)
@target_definition = target_definition
@sandbox = sandbox
@build_headers = Sandbox::HeadersStore.new(sandbox, "BuildHeaders")
@libraries = []
@file_accessors = []
end
# @return [String] the label for the library.
#
def label
target_definition.label.to_s
end
# @return [String] the name of the library.
#
def name
......@@ -66,33 +45,11 @@ module Pod
# @!group Information storage
# @return [Pathname] the folder where to store the support files of this
# library.
#
attr_accessor :support_files_root
# @return [Pathname] the folder where the client is stored used for
# computing the relative paths. If integrating it should be the
# folder where the user project is stored, otherwise it should
# be the installation root.
#
attr_accessor :client_root
# @return [Pathname] the path of the user project that this library will
# integrate as identified by the analyzer.
#
# @note The project instance is not stored to prevent editing different
# instances.
#
attr_accessor :user_project_path
# @return [String] the list of the UUIDs of the user targets that will be
# integrated by this library as identified by the analizer.
#
# @note The target instances are not stored to prevent editing different
# instances.
# @return [Platform] the platform for this library.
#
attr_accessor :user_target_uuids
def platform
@platform ||= target_definition.platform
end
# @return [Hash{String=>Symbol}] A hash representing the user build
# configurations where each key corresponds to the name of a
......@@ -100,57 +57,34 @@ module Pod
#
attr_accessor :user_build_configurations
# @return [Platform] the platform for this library.
#
attr_accessor :platform
# @return [PBXNativeTarget] the target generated in the Pods project for
# this library.
#
attr_accessor :target
# @return [Xcodeproj::Config] the configuration file of the library
#
# @note The configuration is generated by the {TargetInstaller} and
# used by {UserProjectIntegrator} to check for any overridden
# values.
#
attr_accessor :xcconfig
# @return [Specification] the specification for this library.
#
attr_accessor :spec
# @return [Array<Sandbox::FileAccessor>] the file accessors for the
# specifications of this library.
#
attr_accessor :file_accessors
# @return [Array<Target>] the dependencies for this target (or library).
#
attr_accessor :libraries
#-------------------------------------------------------------------------#
# @!group Support files
# @return [Pathname] the folder where to store the support files of this
# library.
#
def support_files_root
@sandbox.library_support_files_dir(name)
end
# @return [Pathname] the absolute path of the xcconfig file.
#
def xcconfig_path
support_files_root + "#{label}.xcconfig"
end
# @return [Pathname] the absolute path of the copy resources script.
# @return [Pathname] the absolute path of the private xcconfig file.
#
def copy_resources_script_path
support_files_root + "#{label}-resources.sh"
def xcconfig_private_path
support_files_root + "#{label}-Private.xcconfig"
end
# @return [Pathname] the absolute path of the header file which contains
# the information about the installed pods.
#
def target_environment_header_path
support_files_root + "#{label}-environment.h"
support_files_root + "#{target_definition.label.to_s}-environment.h"
end
# @return [Pathname] the absolute path of the prefix header file.
......@@ -165,6 +99,61 @@ module Pod
support_files_root + "#{label}.bridgesupport"
end
# @return [Pathname] the path of the dummy source generated by CocoaPods
#
def dummy_source_path
support_files_root + "#{label}-dummy.m"
end
end
#---------------------------------------------------------------------------#
class PodTarget < AbstractTarget
# @param [TargetDefinition] target_definition @see target_definition
# @param [Sandbox] sandbox @see sandbox
#
def initialize(target_definition, sandbox)
@target_definition = target_definition
@sandbox = sandbox
@libraries = []
@file_accessors = []
end
# @return [String] the label for the library.
#
def label
target_definition.label.to_s
end
# @return [Pathname] the folder where the client is stored used for
# computing the relative paths. If integrating it should be the
# folder where the user project is stored, otherwise it should
# be the installation root.
#
attr_accessor :client_root
# @return [Pathname] the path of the user project that this library will
# integrate as identified by the analyzer.
#
# @note The project instance is not stored to prevent editing different
# instances.
#
attr_accessor :user_project_path
# @return [String] the list of the UUIDs of the user targets that will be
# integrated by this library as identified by the analizer.
#
# @note The target instances are not stored to prevent editing different
# instances.
#
attr_accessor :user_target_uuids
# @return [Array<SpecTarget>] the dependencies for this target (or library).
#
attr_accessor :libraries
# @return [Pathname] the absolute path of acknowledgements file.
#
# @note The acknowledgements generators add the extension according to
......@@ -174,14 +163,12 @@ module Pod
support_files_root + "#{label}-acknowledgements"
end
# @return [Pathname] the path of the dummy source generated by CocoaPods
# @return [Pathname] the absolute path of the copy resources script.
#
def dummy_source_path
support_files_root + "#{label}-dummy.m"
def copy_resources_script_path
support_files_root + "#{label}-resources.sh"
end
#--------------------------------------#
# @return [String] The xcconfig path of the root from the `$(SRCROOT)`
# variable of the user's project.
#
......@@ -203,12 +190,6 @@ module Pod
"${SRCROOT}/#{relative_to_srcroot(copy_resources_script_path)}"
end
# @return [Specification::Consumer] the specification consumer for the
# library.
#
def consumer
spec.consumer(platform)
end
#-------------------------------------------------------------------------#
# @!group Private Helpers
......@@ -226,5 +207,59 @@ module Pod
def relative_to_srcroot(path)
path.relative_path_from(client_root).to_s
end
end
#---------------------------------------------------------------------------#
class SpecTarget < AbstractTarget
# @return [Specification] the spec for the target.
#
attr_reader :spec
# @return [HeadersStore] the header directory for the library.
#
attr_reader :build_headers
# @param [Specification] spec @see spec
# @param [TargetDefinition] target_definition @see target_definition
# @param [Sandbox] sandbox @see sandbox
#
def initialize(spec, target_definition, sandbox)
@spec = spec
@target_definition = target_definition
@sandbox = sandbox
@build_headers = Sandbox::HeadersStore.new(sandbox, "BuildHeaders")
@file_accessors = []
end
# @return [String] the label for the library.
#
def label
"#{target_definition.label.to_s}-#{spec.name.gsub('/', '-')}"
end
# @return [Specification] the specification for this library.
#
attr_accessor :spec
# @return [Array<Sandbox::FileAccessor>] the file accessors for the
# specifications of this library.
#
attr_accessor :file_accessors
#--------------------------------------#
# @return [Specification::Consumer] the specification consumer for the
# library.
#
def consumer
spec.consumer(platform)
end
end
#---------------------------------------------------------------------------#
end
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