Commit 7646e92b authored by Daniel Tomlinson's avatar Daniel Tomlinson

Move Pods project generation to an Xcode namespace

* Fix Dangerfile Rubocop violations

* Update CHANGELOG.md

* Update docs

* Don't use Type = Type::Type in tests
parent 2782866f
......@@ -4,9 +4,6 @@ inherit_from:
#- CocoaPods ------------------------------------------------------------------
ParameterLists:
CountKeywordArgs: false
AllCops:
Include:
- Dangerfile
......
......@@ -14,6 +14,9 @@ Documentation:
#- CocoaPods -----------------------------------------------------------------#
ParameterLists:
CountKeywordArgs: false
# We adopted raise instead of fail.
SignalException:
EnforcedStyle: only_raise
......
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2016-03-03 16:16:26 -0600 using RuboCop version 0.37.2.
# on 2016-06-09 08:12:30 -0500 using RuboCop version 0.37.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 4
# Offense count: 7
# Cop supports --auto-correct.
# Configuration parameters: AlignWith, SupportedStyles, AutoCorrect.
# SupportedStyles: keyword, variable, start_of_line
......@@ -22,21 +22,38 @@ Lint/IneffectiveAccessModifier:
- 'lib/cocoapods/installer/analyzer/locking_dependency_analyzer.rb'
- 'lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect.
Lint/LiteralInInterpolation:
Exclude:
- 'Dangerfile'
# Offense count: 1
Lint/NonLocalExitFromIterator:
Exclude:
- 'spec/unit/installer_spec.rb'
# Offense count: 1
Lint/UnreachableCode:
Exclude:
- 'Dangerfile'
# Offense count: 40
Lint/UselessAccessModifier:
Enabled: false
# Offense count: 1853
# Offense count: 2035
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes.
# URISchemes: http, https
Metrics/LineLength:
Max: 279
# Offense count: 1
# Configuration parameters: CountKeywordArgs.
ParameterLists:
Max: 6
# Offense count: 5
# Cop supports --auto-correct.
Performance/Casecmp:
......@@ -55,20 +72,12 @@ Performance/RedundantBlockCall:
- 'lib/cocoapods/installer/analyzer/pod_variant_set.rb'
- 'spec/unit/validator_spec.rb'
# Offense count: 2
# Cop supports --auto-correct.
Performance/RedundantMatch:
Exclude:
- 'spec/**/*'
- 'lib/cocoapods/command/lib.rb'
- 'lib/cocoapods/external_sources/podspec_source.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: MaxKeyValuePairs.
Performance/RedundantMerge:
Exclude:
- 'lib/cocoapods/installer/target_installer.rb'
- 'lib/cocoapods/installer/xcode/pods_project_generator/target_installer.rb'
# Offense count: 1
# Cop supports --auto-correct.
......@@ -76,7 +85,7 @@ Performance/StringReplacement:
Exclude:
- 'spec/functional/command/spec_spec.rb'
# Offense count: 23
# Offense count: 22
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles.
# SupportedStyles: prefer_alias, prefer_alias_method
......@@ -106,12 +115,11 @@ Style/AlignParameters:
Exclude:
- 'lib/cocoapods/project.rb'
# Offense count: 7
# Offense count: 6
# Cop supports --auto-correct.
# Configuration parameters: SingleLineConditionsOnly.
Style/ConditionalAssignment:
Exclude:
- 'lib/cocoapods/command/init.rb'
- 'lib/cocoapods/command/repo/push.rb'
- 'lib/cocoapods/external_sources/abstract_external_source.rb'
- 'lib/cocoapods/sandbox/file_accessor.rb'
......@@ -137,32 +145,30 @@ Style/IfInsideElse:
Style/IndentArray:
EnforcedStyle: consistent
# Offense count: 27
# Offense count: 24
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
# SupportedStyles: aligned, indented
Style/MultilineMethodCallIndentation:
Enabled: false
# Offense count: 1
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
# SupportedStyles: aligned, indented
Style/MultilineOperationIndentation:
Enabled: false
# Offense count: 16
# Offense count: 12
# Cop supports --auto-correct.
Style/MutableConstant:
Exclude:
- 'bin/sandbox-pod'
- 'lib/cocoapods/command/inter_process_communication.rb'
- 'lib/cocoapods/command/lib.rb'
- 'lib/cocoapods/config.rb'
- 'lib/cocoapods/generator/copy_resources_script.rb'
- 'lib/cocoapods/installer.rb'
- 'lib/cocoapods/installer/target_installer/pod_target_installer.rb'
- 'lib/cocoapods/installer/user_project_integrator/target_integrator/xcconfig_integrator.rb'
- 'lib/cocoapods/installer/xcode/pods_project_generator/pod_target_installer.rb'
- 'lib/cocoapods/project.rb'
- 'spec/unit/installer/user_project_integrator/target_integrator/xcconfig_integrator_spec.rb'
......@@ -173,16 +179,8 @@ Style/NestedParenthesizedCalls:
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: AllowSafeAssignment.
Style/ParenthesesAroundCondition:
Exclude:
- 'lib/cocoapods/command/inter_process_communication.rb'
# Offense count: 2
# Cop supports --auto-correct.
Style/RedundantParentheses:
Exclude:
- 'lib/cocoapods/sources_manager.rb'
- 'spec/unit/sandbox_spec.rb'
# Offense count: 2
......@@ -191,15 +189,14 @@ Style/RedundantSelf:
Exclude:
- 'lib/cocoapods/command.rb'
# Offense count: 16
# Offense count: 13
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SupportedStyles, AllowInnerSlashes.
# SupportedStyles: slashes, percent_r, mixed
Style/RegexpLiteral:
Exclude:
- 'lib/cocoapods/installer/file_references_installer.rb'
- 'lib/cocoapods/installer/xcode/pods_project_generator/file_references_installer.rb'
- 'lib/cocoapods/sandbox/path_list.rb'
- 'lib/cocoapods/sources_manager.rb'
- 'lib/cocoapods/validator.rb'
- 'spec/integration.rb'
- 'spec/unit/external_sources/path_source_spec.rb'
......@@ -228,10 +225,8 @@ Style/UnneededInterpolation:
- 'lib/cocoapods/validator.rb'
- 'spec/spec_helper/temporary_repos.rb'
# Offense count: 4
# Offense count: 2
Style/ZeroLengthPredicate:
Exclude:
- 'lib/cocoapods/command/init.rb'
- 'lib/cocoapods/command/project.rb'
- 'lib/cocoapods/installer/podfile_validator.rb'
- 'lib/cocoapods/sources_manager.rb'
......@@ -8,6 +8,10 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
##### Enhancements
* Move Pods Project generation to an `Xcode` Namespace.
[Daniel Tomlinson](https://github.com/dantoml)
[#5480](https://github.com/CocoaPods/CocoaPods/pull/5480)
* Add the ability to inhibit swift warnings.
[Peter Ryszkiewicz](https://github.com/pRizz)
[#5414](https://github.com/CocoaPods/CocoaPods/pull/5414)
......
......@@ -11,13 +11,13 @@ end
# Ensure a clean commits history
if commits.any? { |c| c.message =~ /^Merge branch '#{branch_for_merge}'/ }
fail("Please rebase to get rid of the merge commits in this PR")
fail('Please rebase to get rid of the merge commits in this PR')
end
# Request a CHANGELOG entry, and give an example
has_app_changes = !modified_files.grep(/lib/).empty?
if !modified_files.include?("CHANGELOG.md") && has_app_changes
fail("Please include a CHANGELOG entry to credit yourself! \nYou can find it at [CHANGELOG.md](https://github.com/CocoaPods/CocoaPods/blob/master/CHANGELOG.md).", sticky: false)
if !modified_files.include?('CHANGELOG.md') && has_app_changes
fail('Please include a CHANGELOG entry to credit yourself! \nYou can find it at [CHANGELOG.md](https://github.com/CocoaPods/CocoaPods/blob/master/CHANGELOG.md).', :sticky => false)
markdown <<-MARKDOWN
Here's an example of your CHANGELOG entry:
......
This diff is collapsed.
This diff is collapsed.
module Pod
class Installer
# Controller class responsible of creating and configuring the static
# library target in Pods project. It also creates the support file needed
# by the target.
#
class TargetInstaller
# @return [Sandbox] sandbox the sandbox where the support files should
# be generated.
#
attr_reader :sandbox
# @return [Target] The library whose target needs to be generated.
#
attr_reader :target
# @param [Project] project @see project
# @param [Target] target @see target
#
def initialize(sandbox, target)
@sandbox = sandbox
@target = target
end
private
#-----------------------------------------------------------------------#
# @!group Installation steps
# Adds the target for the library to the Pods project with the
# appropriate build configurations.
#
# @note The `PODS_HEADERS_SEARCH_PATHS` overrides the xcconfig.
#
# @return [void]
#
def add_target
product_type = target.product_type
name = target.label
platform = target.platform.name
language = target.uses_swift? ? :swift : :objc
@native_target = project.new_target(product_type, name, platform, deployment_target, nil, language)
product_name = target.product_name
product = @native_target.product_reference
product.name = product_name
target.user_build_configurations.each do |bc_name, type|
@native_target.add_build_configuration(bc_name, type)
end
@native_target.build_configurations.each do |configuration|
configuration.build_settings.merge!(custom_build_settings)
end
target.native_target = @native_target
end
# @return [String] The deployment target.
#
def deployment_target
target.platform.deployment_target.to_s
end
# Returns the customized build settings which are overridden in the build
# settings of the user target.
#
# @return [Hash{String => String}]
#
def custom_build_settings
settings = {}
unless target.archs.empty?
settings['ARCHS'] = target.archs
end
if target.requires_frameworks?
settings['PRODUCT_NAME'] = target.product_module_name
else
settings.merge!('OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '')
end
settings
end
# Creates the directory where to store the support files of the target.
#
def create_support_files_dir
target.support_files_dir.mkdir
end
# Creates the Info.plist file which sets public framework attributes
#
# @return [void]
#
def create_info_plist_file
path = target.info_plist_path
UI.message "- Generating Info.plist file at #{UI.path(path)}" do
generator = Generator::InfoPlistFile.new(target)
generator.save_as(path)
add_file_to_support_group(path)
native_target.build_configurations.each do |c|
relative_path = path.relative_path_from(sandbox.root)
c.build_settings['INFOPLIST_FILE'] = relative_path.to_s
end
end
end
# Creates the module map file which ensures that the umbrella header is
# recognized with a customized path
#
# @yield_param [Generator::ModuleMap]
# yielded once to configure the private headers
#
# @return [void]
#
def create_module_map
path = target.module_map_path
UI.message "- Generating module map file at #{UI.path(path)}" do
generator = Generator::ModuleMap.new(target)
yield generator if block_given?
generator.save_as(path)
add_file_to_support_group(path)
native_target.build_configurations.each do |c|
relative_path = path.relative_path_from(sandbox.root)
c.build_settings['MODULEMAP_FILE'] = relative_path.to_s
end
end
end
# Generates a header which ensures that all header files are exported
# in the module map
#
# @yield_param [Generator::UmbrellaHeader]
# yielded once to configure the imports
#
def create_umbrella_header
path = target.umbrella_header_path
UI.message "- Generating umbrella header at #{UI.path(path)}" do
generator = Generator::UmbrellaHeader.new(target)
yield generator if block_given?
generator.save_as(path)
# Add the file to the support group and the native target,
# so it will been added to the header build phase
file_ref = add_file_to_support_group(path)
native_target.add_file_references([file_ref])
# Make the umbrella header public
build_file = native_target.headers_build_phase.build_file(file_ref)
build_file.settings ||= {}
build_file.settings['ATTRIBUTES'] = ['Public']
end
end
# Generates a dummy source file for each target so libraries that contain
# only categories build.
#
# @return [void]
#
def create_dummy_source
path = target.dummy_source_path
generator = Generator::DummySource.new(target.label)
generator.save_as(path)
file_reference = add_file_to_support_group(path)
native_target.source_build_phase.add_file_reference(file_reference)
end
# @return [PBXNativeTarget] the target generated by the installation
# process.
#
# @note Generated by the {#add_target} step.
#
attr_reader :native_target
private
#-----------------------------------------------------------------------#
# @!group Private helpers.
# @return [Project] the Pods project of the sandbox.
#
def project
sandbox.project
end
# @return [PBXGroup] the group where the file references to the support
# files should be stored.
#
attr_reader :support_files_group
# Adds a reference to the given file in the support group of this target.
#
# @param [Pathname] path
# The path of the file to which the reference should be added.
#
# @return [PBXFileReference] the file reference of the added file.
#
def add_file_to_support_group(path)
support_files_group.new_file(path)
end
#-----------------------------------------------------------------------#
end
end
end
module Pod
class Installer
# Creates the targets which aggregate the Pods libraries in the Pods
# project and the relative support files.
#
class AggregateTargetInstaller < TargetInstaller
# Creates the target in the Pods project and the relative support files.
#
# @return [void]
#
def install!
UI.message "- Installing target `#{target.name}` #{target.platform}" do
add_target
create_support_files_dir
create_support_files_group
create_xcconfig_file
if target.requires_frameworks?
create_info_plist_file
create_module_map
create_umbrella_header
end
create_embed_frameworks_script
create_bridge_support_file
create_copy_resources_script
create_acknowledgements
create_dummy_source
end
end
#-----------------------------------------------------------------------#
private
# @return [TargetDefinition] the target definition of the library.
#
def target_definition
target.target_definition
end
# Ensure that vendored static frameworks and libraries are not linked
# twice to the aggregate target, which shares the xcconfig of the user
# target.
#
def custom_build_settings
settings = {
'MACH_O_TYPE' => 'staticlib',
'OTHER_LDFLAGS' => '',
'OTHER_LIBTOOLFLAGS' => '',
'PODS_ROOT' => '$(SRCROOT)',
'PRODUCT_BUNDLE_IDENTIFIER' => 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}',
'SKIP_INSTALL' => 'YES',
}
super.merge(settings)
end
# Creates the group that holds the references to the support files
# generated by this installer.
#
# @return [void]
#
def create_support_files_group
parent = project.support_files_group
name = target.name
dir = target.support_files_dir
@support_files_group = parent.new_group(name, dir)
end
# Generates the contents of the xcconfig file and saves it to disk.
#
# @return [void]
#
def create_xcconfig_file
native_target.build_configurations.each do |configuration|
path = target.xcconfig_path(configuration.name)
gen = Generator::XCConfig::AggregateXCConfig.new(target, configuration.name)
gen.save_as(path)
target.xcconfigs[configuration.name] = gen.xcconfig
xcconfig_file_ref = add_file_to_support_group(path)
configuration.base_configuration_reference = xcconfig_file_ref
end
end
# Generates the bridge support metadata if requested by the {Podfile}.
#
# @note The bridge support metadata is added to the resources of the
# target because it is needed for environments interpreted at
# runtime.
#
# @return [void]
#
def create_bridge_support_file
if target.podfile.generate_bridge_support?
path = target.bridge_support_path
headers = native_target.headers_build_phase.files.map { |bf| sandbox.root + bf.file_ref.path }
generator = Generator::BridgeSupport.new(headers)
generator.save_as(path)
add_file_to_support_group(path)
@bridge_support_file = path.relative_path_from(sandbox.root)
end
end
# Uniqued Resources grouped by config
#
# @return [Hash{ Symbol => Array<Pathname> }]
#
def resources_by_config
library_targets = target.pod_targets.reject do |pod_target|
pod_target.should_build? && pod_target.requires_frameworks?
end
target.user_build_configurations.keys.each_with_object({}) do |config, resources_by_config|
resources_by_config[config] = library_targets.flat_map do |library_target|
next [] unless library_target.include_in_build_config?(target_definition, config)
resource_paths = library_target.file_accessors.flat_map do |accessor|
accessor.resources.flat_map { |res| res.relative_path_from(project.path.dirname) }
end
resource_bundles = library_target.file_accessors.flat_map do |accessor|
accessor.resource_bundles.keys.map { |name| "#{library_target.configuration_build_dir}/#{name.shellescape}.bundle" }
end
(resource_paths + resource_bundles + [bridge_support_file].compact).uniq
end
end
end
# Creates a script that copies the resources to the bundle of the client
# target.
#
# @note The bridge support file needs to be created before the prefix
# header, otherwise it will not be added to the resources script.
#
# @return [void]
#
def create_copy_resources_script
path = target.copy_resources_script_path
generator = Generator::CopyResourcesScript.new(resources_by_config, target.platform)
generator.save_as(path)
add_file_to_support_group(path)
end
# Creates a script that embeds the frameworks to the bundle of the client
# target.
#
# @note We can't use Xcode default copy bundle resource phase, because
# we need to ensure that we only copy the resources, which are
# relevant for the current build configuration.
#
# @return [void]
#
def create_embed_frameworks_script
path = target.embed_frameworks_script_path
frameworks_by_config = {}
target.user_build_configurations.keys.each do |config|
relevant_pod_targets = target.pod_targets.select do |pod_target|
pod_target.include_in_build_config?(target_definition, config)
end
frameworks_by_config[config] = relevant_pod_targets.flat_map do |pod_target|
frameworks = pod_target.file_accessors.flat_map(&:vendored_dynamic_artifacts).map { |fw| "${PODS_ROOT}/#{fw.relative_path_from(sandbox.root)}" }
frameworks << pod_target.build_product_path('$BUILT_PRODUCTS_DIR') if pod_target.should_build? && pod_target.requires_frameworks?
frameworks
end
end
generator = Generator::EmbedFrameworksScript.new(frameworks_by_config)
generator.save_as(path)
add_file_to_support_group(path)
end
# Generates the acknowledgement files (markdown and plist) for the target.
#
# @return [void]
#
def create_acknowledgements
basepath = target.acknowledgements_basepath
Generator::Acknowledgements.generators.each do |generator_class|
path = generator_class.path_from_basepath(basepath)
file_accessors = target.pod_targets.map(&:file_accessors).flatten
generator = generator_class.new(file_accessors)
generator.save_as(path)
add_file_to_support_group(path)
end
end
# @return [Pathname] the path of the bridge support file relative to the
# sandbox.
#
# @return [Nil] if no bridge support file was generated.
#
attr_reader :bridge_support_file
#-----------------------------------------------------------------------#
end
end
end
module Pod
class Installer
class Xcode
autoload :PodsProjectGenerator, 'cocoapods/installer/xcode/pods_project_generator'
end
end
end
This diff is collapsed.
module Pod
class Installer
class Xcode
class PodsProjectGenerator
# Creates the targets which aggregate the Pods libraries in the Pods
# project and the relative support files.
#
class AggregateTargetInstaller < TargetInstaller
# Creates the target in the Pods project and the relative support files.
#
# @return [void]
#
def install!
UI.message "- Installing target `#{target.name}` #{target.platform}" do
add_target
create_support_files_dir
create_support_files_group
create_xcconfig_file
if target.requires_frameworks?
create_info_plist_file
create_module_map
create_umbrella_header
end
create_embed_frameworks_script
create_bridge_support_file
create_copy_resources_script
create_acknowledgements
create_dummy_source
end
end
#-----------------------------------------------------------------------#
private
# @return [TargetDefinition] the target definition of the library.
#
def target_definition
target.target_definition
end
# Ensure that vendored static frameworks and libraries are not linked
# twice to the aggregate target, which shares the xcconfig of the user
# target.
#
def custom_build_settings
settings = {
'MACH_O_TYPE' => 'staticlib',
'OTHER_LDFLAGS' => '',
'OTHER_LIBTOOLFLAGS' => '',
'PODS_ROOT' => '$(SRCROOT)',
'PRODUCT_BUNDLE_IDENTIFIER' => 'org.cocoapods.${PRODUCT_NAME:rfc1034identifier}',
'SKIP_INSTALL' => 'YES',
}
super.merge(settings)
end
# Creates the group that holds the references to the support files
# generated by this installer.
#
# @return [void]
#
def create_support_files_group
parent = project.support_files_group
name = target.name
dir = target.support_files_dir
@support_files_group = parent.new_group(name, dir)
end
# Generates the contents of the xcconfig file and saves it to disk.
#
# @return [void]
#
def create_xcconfig_file
native_target.build_configurations.each do |configuration|
path = target.xcconfig_path(configuration.name)
gen = Generator::XCConfig::AggregateXCConfig.new(target, configuration.name)
gen.save_as(path)
target.xcconfigs[configuration.name] = gen.xcconfig
xcconfig_file_ref = add_file_to_support_group(path)
configuration.base_configuration_reference = xcconfig_file_ref
end
end
# Generates the bridge support metadata if requested by the {Podfile}.
#
# @note The bridge support metadata is added to the resources of the
# target because it is needed for environments interpreted at
# runtime.
#
# @return [void]
#
def create_bridge_support_file
if target.podfile.generate_bridge_support?
path = target.bridge_support_path
headers = native_target.headers_build_phase.files.map { |bf| sandbox.root + bf.file_ref.path }
generator = Generator::BridgeSupport.new(headers)
generator.save_as(path)
add_file_to_support_group(path)
@bridge_support_file = path.relative_path_from(sandbox.root)
end
end
# Uniqued Resources grouped by config
#
# @return [Hash{ Symbol => Array<Pathname> }]
#
def resources_by_config
library_targets = target.pod_targets.reject do |pod_target|
pod_target.should_build? && pod_target.requires_frameworks?
end
target.user_build_configurations.keys.each_with_object({}) do |config, resources_by_config|
resources_by_config[config] = library_targets.flat_map do |library_target|
next [] unless library_target.include_in_build_config?(target_definition, config)
resource_paths = library_target.file_accessors.flat_map do |accessor|
accessor.resources.flat_map { |res| res.relative_path_from(project.path.dirname) }
end
resource_bundles = library_target.file_accessors.flat_map do |accessor|
accessor.resource_bundles.keys.map { |name| "#{library_target.configuration_build_dir}/#{name.shellescape}.bundle" }
end
(resource_paths + resource_bundles + [bridge_support_file].compact).uniq
end
end
end
# Creates a script that copies the resources to the bundle of the client
# target.
#
# @note The bridge support file needs to be created before the prefix
# header, otherwise it will not be added to the resources script.
#
# @return [void]
#
def create_copy_resources_script
path = target.copy_resources_script_path
generator = Generator::CopyResourcesScript.new(resources_by_config, target.platform)
generator.save_as(path)
add_file_to_support_group(path)
end
# Creates a script that embeds the frameworks to the bundle of the client
# target.
#
# @note We can't use Xcode default copy bundle resource phase, because
# we need to ensure that we only copy the resources, which are
# relevant for the current build configuration.
#
# @return [void]
#
def create_embed_frameworks_script
path = target.embed_frameworks_script_path
frameworks_by_config = {}
target.user_build_configurations.keys.each do |config|
relevant_pod_targets = target.pod_targets.select do |pod_target|
pod_target.include_in_build_config?(target_definition, config)
end
frameworks_by_config[config] = relevant_pod_targets.flat_map do |pod_target|
frameworks = pod_target.file_accessors.flat_map(&:vendored_dynamic_artifacts).map { |fw| "${PODS_ROOT}/#{fw.relative_path_from(sandbox.root)}" }
frameworks << pod_target.build_product_path('$BUILT_PRODUCTS_DIR') if pod_target.should_build? && pod_target.requires_frameworks?
frameworks
end
end
generator = Generator::EmbedFrameworksScript.new(frameworks_by_config)
generator.save_as(path)
add_file_to_support_group(path)
end
# Generates the acknowledgement files (markdown and plist) for the target.
#
# @return [void]
#
def create_acknowledgements
basepath = target.acknowledgements_basepath
Generator::Acknowledgements.generators.each do |generator_class|
path = generator_class.path_from_basepath(basepath)
file_accessors = target.pod_targets.map(&:file_accessors).flatten
generator = generator_class.new(file_accessors)
generator.save_as(path)
add_file_to_support_group(path)
end
end
# @return [Pathname] the path of the bridge support file relative to the
# sandbox.
#
# @return [Nil] if no bridge support file was generated.
#
attr_reader :bridge_support_file
#-----------------------------------------------------------------------#
end
end
end
end
end
module Pod
class Installer
class Xcode
class PodsProjectGenerator
# Controller class responsible of creating and configuring the static
# library target in Pods project. It also creates the support file needed
# by the target.
#
class TargetInstaller
# @return [Sandbox] sandbox the sandbox where the support files should
# be generated.
#
attr_reader :sandbox
# @return [Target] The library whose target needs to be generated.
#
attr_reader :target
# @param [Project] project @see project
# @param [Target] target @see target
#
def initialize(sandbox, target)
@sandbox = sandbox
@target = target
end
private
#-----------------------------------------------------------------------#
# @!group Installation steps
# Adds the target for the library to the Pods project with the
# appropriate build configurations.
#
# @note The `PODS_HEADERS_SEARCH_PATHS` overrides the xcconfig.
#
# @return [void]
#
def add_target
product_type = target.product_type
name = target.label
platform = target.platform.name
language = target.uses_swift? ? :swift : :objc
@native_target = project.new_target(product_type, name, platform, deployment_target, nil, language)
product_name = target.product_name
product = @native_target.product_reference
product.name = product_name
target.user_build_configurations.each do |bc_name, type|
@native_target.add_build_configuration(bc_name, type)
end
@native_target.build_configurations.each do |configuration|
configuration.build_settings.merge!(custom_build_settings)
end
target.native_target = @native_target
end
# @return [String] The deployment target.
#
def deployment_target
target.platform.deployment_target.to_s
end
# Returns the customized build settings which are overridden in the build
# settings of the user target.
#
# @return [Hash{String => String}]
#
def custom_build_settings
settings = {}
unless target.archs.empty?
settings['ARCHS'] = target.archs
end
if target.requires_frameworks?
settings['PRODUCT_NAME'] = target.product_module_name
else
settings.merge!('OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '')
end
settings
end
# Creates the directory where to store the support files of the target.
#
def create_support_files_dir
target.support_files_dir.mkdir
end
# Creates the Info.plist file which sets public framework attributes
#
# @return [void]
#
def create_info_plist_file
path = target.info_plist_path
UI.message "- Generating Info.plist file at #{UI.path(path)}" do
generator = Generator::InfoPlistFile.new(target)
generator.save_as(path)
add_file_to_support_group(path)
native_target.build_configurations.each do |c|
relative_path = path.relative_path_from(sandbox.root)
c.build_settings['INFOPLIST_FILE'] = relative_path.to_s
end
end
end
# Creates the module map file which ensures that the umbrella header is
# recognized with a customized path
#
# @yield_param [Generator::ModuleMap]
# yielded once to configure the private headers
#
# @return [void]
#
def create_module_map
path = target.module_map_path
UI.message "- Generating module map file at #{UI.path(path)}" do
generator = Generator::ModuleMap.new(target)
yield generator if block_given?
generator.save_as(path)
add_file_to_support_group(path)
native_target.build_configurations.each do |c|
relative_path = path.relative_path_from(sandbox.root)
c.build_settings['MODULEMAP_FILE'] = relative_path.to_s
end
end
end
# Generates a header which ensures that all header files are exported
# in the module map
#
# @yield_param [Generator::UmbrellaHeader]
# yielded once to configure the imports
#
def create_umbrella_header
path = target.umbrella_header_path
UI.message "- Generating umbrella header at #{UI.path(path)}" do
generator = Generator::UmbrellaHeader.new(target)
yield generator if block_given?
generator.save_as(path)
# Add the file to the support group and the native target,
# so it will been added to the header build phase
file_ref = add_file_to_support_group(path)
native_target.add_file_references([file_ref])
# Make the umbrella header public
build_file = native_target.headers_build_phase.build_file(file_ref)
build_file.settings ||= {}
build_file.settings['ATTRIBUTES'] = ['Public']
end
end
# Generates a dummy source file for each target so libraries that contain
# only categories build.
#
# @return [void]
#
def create_dummy_source
path = target.dummy_source_path
generator = Generator::DummySource.new(target.label)
generator.save_as(path)
file_reference = add_file_to_support_group(path)
native_target.source_build_phase.add_file_reference(file_reference)
end
# @return [PBXNativeTarget] the target generated by the installation
# process.
#
# @note Generated by the {#add_target} step.
#
attr_reader :native_target
private
#-----------------------------------------------------------------------#
# @!group Private helpers.
# @return [Project] the Pods project of the sandbox.
#
def project
sandbox.project
end
# @return [PBXGroup] the group where the file references to the support
# files should be stored.
#
attr_reader :support_files_group
# Adds a reference to the given file in the support group of this target.
#
# @param [Pathname] path
# The path of the file to which the reference should be added.
#
# @return [PBXFileReference] the file reference of the added file.
#
def add_file_to_support_group(path)
support_files_group.new_file(path)
end
#-----------------------------------------------------------------------#
end
end
end
end
end
This diff is collapsed.
require File.expand_path('../../../spec_helper', __FILE__)
module Pod
describe Installer::TargetInstaller do
before do
@podfile = Podfile.new do
platform :ios
project 'SampleProject/SampleProject'
target 'SampleProject'
end
@target_definition = @podfile.target_definitions['SampleProject']
@project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project
path_list = Sandbox::PathList.new(fixture('banana-lib'))
@spec = fixture_spec('banana-lib/BananaLib.podspec')
file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios))
@project.add_pod_group('BananaLib', fixture('banana-lib'))
group = @project.group_for_spec('BananaLib')
file_accessor.source_files.each do |file|
@project.add_file_reference(file, group)
end
@pod_target = PodTarget.new([@spec], [@target_definition], config.sandbox)
@pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug }
@pod_target.file_accessors = [file_accessor]
@installer = Installer::TargetInstaller.new(config.sandbox, @pod_target)
end
it 'adds the architectures to the custom build configurations of the user target' do
@pod_target.archs = '$(ARCHS_STANDARD_64_BIT)'
@installer.send(:add_target)
@installer.send(:native_target).resolved_build_setting('ARCHS').should == {
'Release' => '$(ARCHS_STANDARD_64_BIT)',
'Debug' => '$(ARCHS_STANDARD_64_BIT)',
'AppStore' => '$(ARCHS_STANDARD_64_BIT)',
'Test' => '$(ARCHS_STANDARD_64_BIT)',
}
end
it 'always clears the OTHER_LDFLAGS and OTHER_LIBTOOLFLAGS, because these lib targets do not ever need any' do
@installer.send(:add_target)
@installer.send(:native_target).resolved_build_setting('OTHER_LDFLAGS').values.uniq.should == ['']
@installer.send(:native_target).resolved_build_setting('OTHER_LIBTOOLFLAGS').values.uniq.should == ['']
end
it 'adds Swift-specific build settings to the build settings' do
@pod_target.stubs(:requires_frameworks?).returns(true)
@pod_target.stubs(:uses_swift?).returns(true)
@installer.send(:add_target)
@installer.send(:native_target).resolved_build_setting('SWIFT_OPTIMIZATION_LEVEL').should == {
'Release' => nil,
'Debug' => '-Onone',
'Test' => nil,
'AppStore' => nil,
}
end
end
end
require File.expand_path('../../../../../spec_helper', __FILE__)
module Pod
class Installer
class Xcode
class PodsProjectGenerator
describe TargetInstaller do
before do
@podfile = Podfile.new do
platform :ios
project 'SampleProject/SampleProject'
target 'SampleProject'
end
@target_definition = @podfile.target_definitions['SampleProject']
@project = Project.new(config.sandbox.project_path)
config.sandbox.project = @project
path_list = Sandbox::PathList.new(fixture('banana-lib'))
@spec = fixture_spec('banana-lib/BananaLib.podspec')
file_accessor = Sandbox::FileAccessor.new(path_list, @spec.consumer(:ios))
@project.add_pod_group('BananaLib', fixture('banana-lib'))
group = @project.group_for_spec('BananaLib')
file_accessor.source_files.each do |file|
@project.add_file_reference(file, group)
end
@pod_target = PodTarget.new([@spec], [@target_definition], config.sandbox)
@pod_target.stubs(:platform).returns(Platform.new(:ios, '6.0'))
@pod_target.user_build_configurations = { 'Debug' => :debug, 'Release' => :release, 'AppStore' => :release, 'Test' => :debug }
@pod_target.file_accessors = [file_accessor]
@installer = TargetInstaller.new(config.sandbox, @pod_target)
end
it 'adds the architectures to the custom build configurations of the user target' do
@pod_target.archs = '$(ARCHS_STANDARD_64_BIT)'
@installer.send(:add_target)
@installer.send(:native_target).resolved_build_setting('ARCHS').should == {
'Release' => '$(ARCHS_STANDARD_64_BIT)',
'Debug' => '$(ARCHS_STANDARD_64_BIT)',
'AppStore' => '$(ARCHS_STANDARD_64_BIT)',
'Test' => '$(ARCHS_STANDARD_64_BIT)',
}
end
it 'always clears the OTHER_LDFLAGS and OTHER_LIBTOOLFLAGS, because these lib targets do not ever need any' do
@installer.send(:add_target)
@installer.send(:native_target).resolved_build_setting('OTHER_LDFLAGS').values.uniq.should == ['']
@installer.send(:native_target).resolved_build_setting('OTHER_LIBTOOLFLAGS').values.uniq.should == ['']
end
it 'adds Swift-specific build settings to the build settings' do
@pod_target.stubs(:requires_frameworks?).returns(true)
@pod_target.stubs(:uses_swift?).returns(true)
@installer.send(:add_target)
@installer.send(:native_target).resolved_build_setting('SWIFT_OPTIMIZATION_LEVEL').should == {
'Release' => nil,
'Debug' => '-Onone',
'Test' => nil,
'AppStore' => nil,
}
end
end
end
end
end
end
This diff is collapsed.
This diff is collapsed.
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