Commit 09c6bdb0 authored by Ben Asher's avatar Ben Asher

v0 of special handling for embedded targets

parent 03ab3a34
...@@ -4,7 +4,7 @@ module Pod ...@@ -4,7 +4,7 @@ module Pod
# Generates the xcconfigs for the aggregate targets. # Generates the xcconfigs for the aggregate targets.
# #
class AggregateXCConfig class AggregateXCConfig
# @return [Target] the target represented by this xcconfig. # @return [AggregateTarget] the target represented by this xcconfig.
# #
attr_reader :target attr_reader :target
...@@ -61,7 +61,14 @@ module Pod ...@@ -61,7 +61,14 @@ module Pod
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ', 'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
'LIBRARY_SEARCH_PATHS' => '$(inherited) ', 'LIBRARY_SEARCH_PATHS' => '$(inherited) ',
} }
if pod_targets.any?(&:uses_swift?) # Because app extensions live in their host app, CocoaPods
# copies all of the app extension's pod_targets to the host
# app. Therefore, this check will properly require the Swift
# libs in the host app, if the app extension has any pod targets
# that use swift. Setting this for the app extension target would
# cause an App Store rejection because frameworks cannot be embedded
# in app extensions.
if !target.requires_host_target? && pod_targets.any?(&:uses_swift?)
config['EMBEDDED_CONTENT_CONTAINS_SWIFT'] = 'YES' config['EMBEDDED_CONTENT_CONTAINS_SWIFT'] = 'YES'
end end
@xcconfig = Xcodeproj::Config.new(config) @xcconfig = Xcodeproj::Config.new(config)
......
...@@ -226,6 +226,57 @@ module Pod ...@@ -226,6 +226,57 @@ module Pod
private private
# Copies the pod_targets of any of the app extension aggregate targets into
# their potential host aggregate target, if that potential host aggregate target's
# user_target hosts any of the app extension aggregate targets' user_targets
#
# @param [AggregateTarget] aggregate_target the aggregate target whose user_target
# might host one or more of the app extension aggregate targets' user_targets
#
# @param [Array<AggregateTarget>] extension_aggregate_targets the aggregate targets
# representing the app extension targets to be integrated
#
def copy_extension_pod_targets_to_host(aggregate_target, extension_aggregate_targets)
return if aggregate_target.requires_host_target?
# Get the uuids of the aggregate_target's user_target's extension targets if any
extension_uuids = aggregate_target.user_project.extensions_for_native_target(aggregate_target.user_targets[0]).map(&:uuid)
return if extension_uuids.empty?
extension_aggregate_targets.each do |extension_target|
next unless extension_uuids.include? extension_target.user_targets[0].uuid
raise "#{aggregate_target.name} must use_frameworks! because it is hosting an extension." unless aggregate_target.requires_frameworks?
pod_target_names = aggregate_target.pod_targets.map(&:name)
# This extension target is hosted by the aggregate target's user_target; copy over the non-duplicate pod_targets
aggregate_target.pod_targets = aggregate_target.pod_targets + extension_target.pod_targets.select do |pod_target|
!pod_target_names.include? pod_target.name
end
end
end
# Raises an error if there are extension targets in the Podfile, but
# their host targets have not been declared in the Podfile
#
# @param [Array<AggregateTarget>] aggregate_targets the generated
# aggregate targets
#
# @param [Array<AggregateTarget>] extension_aggregate_targets the aggregate targets
# representing the app extension targets to be integrated
#
def verify_host_targets_in_podfile(aggregate_targets, extension_aggregate_targets)
aggregate_target_uuids = Set.new aggregate_targets.map(&:user_targets).flatten.map(&:uuid)
extension_targets_missing_hosts = []
extension_aggregate_targets.each do |target|
host_uuids = target.user_targets.map do |user_target|
target.user_project.host_targets_for_extension_target(user_target).map(&:uuid)
end.flatten
extension_targets_missing_hosts << target unless host_uuids.any? do |uuid|
aggregate_target_uuids.include? uuid
end
end
unless extension_targets_missing_hosts.empty?
raise ArgumentError, "Unable to find host target for #{extension_targets_missing_hosts.map(&:name).join(', ')}. Please add the extension's host targets to the Podfile."
end
end
# Creates the models that represent the targets generated by CocoaPods. # Creates the models that represent the targets generated by CocoaPods.
# #
# @return [Array<AggregateTarget>] # @return [Array<AggregateTarget>]
...@@ -236,6 +287,14 @@ module Pod ...@@ -236,6 +287,14 @@ module Pod
aggregate_targets = specs_by_target.keys.map do |target_definition| aggregate_targets = specs_by_target.keys.map do |target_definition|
generate_target(target_definition, pod_targets) generate_target(target_definition, pod_targets)
end end
if installation_options.integrate_targets?
# Copy extension target pods that cannot have their pods embedded as frameworks to their host targets
extension_targets = aggregate_targets.select(&:requires_host_target?).select(&:requires_frameworks?)
verify_host_targets_in_podfile(aggregate_targets, extension_targets)
aggregate_targets.each do |target|
copy_extension_pod_targets_to_host(target, extension_targets)
end
end
aggregate_targets.each do |target| aggregate_targets.each do |target|
target.search_paths_aggregate_targets = aggregate_targets.select do |aggregate_target| target.search_paths_aggregate_targets = aggregate_targets.select do |aggregate_target|
target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition) target.target_definition.targets_to_inherit_search_paths.include?(aggregate_target.target_definition)
...@@ -277,6 +336,7 @@ module Pod ...@@ -277,6 +336,7 @@ module Pod
target.pod_targets = pod_targets.select do |pod_target| target.pod_targets = pod_targets.select do |pod_target|
pod_target.target_definitions.include?(target_definition) pod_target.target_definitions.include?(target_definition)
end end
target target
end end
......
...@@ -20,7 +20,10 @@ module Pod ...@@ -20,7 +20,10 @@ module Pod
# @return [Array<Symbol>] the symbol types, which require that the pod # @return [Array<Symbol>] the symbol types, which require that the pod
# frameworks are embedded in the output directory / product bundle. # frameworks are embedded in the output directory / product bundle.
# #
EMBED_FRAMEWORK_TARGET_TYPES = [:application, :unit_test_bundle, :ui_test_bundle, :app_extension, :watch_extension, :watch2_extension].freeze # @note This does not include :app_extension or :watch_extension because
# these types must have their frameworks embedded in their host targets
#
EMBED_FRAMEWORK_TARGET_TYPES = [:application, :unit_test_bundle, :ui_test_bundle, :watch2_extension].freeze
# @return [String] the name of the embed frameworks phase # @return [String] the name of the embed frameworks phase
# #
...@@ -54,6 +57,7 @@ module Pod ...@@ -54,6 +57,7 @@ module Pod
add_pods_library add_pods_library
add_embed_frameworks_script_phase add_embed_frameworks_script_phase
remove_embed_frameworks_script_phase_from_app_extensions
add_copy_resources_script_phase add_copy_resources_script_phase
add_check_manifest_lock_script_phase add_check_manifest_lock_script_phase
end end
...@@ -110,6 +114,21 @@ module Pod ...@@ -110,6 +114,21 @@ module Pod
end end
end end
# Removes the embed frameworks build phase from app extension targets
#
# @note Older versions of CocoaPods would add this build phase to app
# extension targets. They should be removed on upgrade because app
# extension targets will have their frameworks embedded in their host
# apps.
#
def remove_embed_frameworks_script_phase_from_app_extensions
native_targets.each do |native_target|
if AggregateTarget::EMBED_FRAMEWORKS_IN_HOST_TARGET_TYPES.include? native_target.symbol_type
remove_embed_frameworks_script_phase(native_target)
end
end
end
def add_embed_frameworks_script_phase_to_target(native_target) def add_embed_frameworks_script_phase_to_target(native_target)
phase = create_or_update_build_phase(native_target, EMBED_FRAMEWORK_PHASE_NAME) phase = create_or_update_build_phase(native_target, EMBED_FRAMEWORK_PHASE_NAME)
script_path = target.embed_frameworks_script_relative_path script_path = target.embed_frameworks_script_relative_path
...@@ -121,7 +140,7 @@ module Pod ...@@ -121,7 +140,7 @@ module Pod
# @param [PBXNativeTarget] native_target # @param [PBXNativeTarget] native_target
# #
def remove_embed_frameworks_script_phase(native_target) def remove_embed_frameworks_script_phase(native_target)
embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name == EMBED_FRAMEWORK_PHASE_NAME } embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name && bp.name.end_with?(EMBED_FRAMEWORK_PHASE_NAME) }
return unless embed_build_phase.present? return unless embed_build_phase.present?
native_target.build_phases.delete(embed_build_phase) native_target.build_phases.delete(embed_build_phase)
end end
......
...@@ -21,7 +21,13 @@ module Pod ...@@ -21,7 +21,13 @@ module Pod
create_module_map create_module_map
create_umbrella_header create_umbrella_header
end end
create_embed_frameworks_script # Because embedded targets live in their host target, CocoaPods
# copies all of the embedded target's pod_targets to its host
# targets. Having this script for the embedded target would
# cause an App Store rejection because frameworks cannot be
# embedded in embedded targets.
#
create_embed_frameworks_script unless target.requires_host_target?
create_bridge_support_file create_bridge_support_file
create_copy_resources_script create_copy_resources_script
create_acknowledgements create_acknowledgements
......
...@@ -7,6 +7,9 @@ module Pod ...@@ -7,6 +7,9 @@ module Pod
# generated this target. # generated this target.
attr_reader :target_definition attr_reader :target_definition
# Product types where the product's frameworks must be embedded in a host target
EMBED_FRAMEWORKS_IN_HOST_TARGET_TYPES = [:app_extension, :watch_extension].freeze
# Initialize a new instance # Initialize a new instance
# #
# @param [TargetDefinition] target_definition @see target_definition # @param [TargetDefinition] target_definition @see target_definition
...@@ -23,6 +26,21 @@ module Pod ...@@ -23,6 +26,21 @@ module Pod
@xcconfigs = {} @xcconfigs = {}
end end
# @return True if the user_target's pods are
# for an extension and must be embedded in a host,
# target, otherwise false.
#
def requires_host_target?
# If we don't have a user_project, then we can't
# glean any info about how this target is going to
# be integrated, so return false since we can't know
# for sure that this target refers to an extension
# target that would require a host target
return false if user_project.nil?
raise ArgumentError, "Expected single user_target for #{name}" unless user_targets.count == 1
EMBED_FRAMEWORKS_IN_HOST_TARGET_TYPES.include? user_targets[0].symbol_type
end
# @return [String] the label for the target. # @return [String] the label for the target.
# #
def label def label
......
Subproject commit 409958a75378ff70582af2fbabb1441c551ed1c7 Subproject commit 4c7f2413a2cf1a8175c544555d000bfb6511e943
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
135286D11D0B010C007FC288 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135286D01D0B010C007FC288 /* AppDelegate.swift */; };
135286D31D0B010C007FC288 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135286D21D0B010C007FC288 /* ViewController.swift */; };
135286D61D0B010C007FC288 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 135286D41D0B010C007FC288 /* Main.storyboard */; };
135286D81D0B010C007FC288 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 135286D71D0B010C007FC288 /* Assets.xcassets */; };
135286DB1D0B010C007FC288 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 135286D91D0B010C007FC288 /* LaunchScreen.storyboard */; };
135286E91D0B015D007FC288 /* NotificationCenter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 135286E81D0B015D007FC288 /* NotificationCenter.framework */; };
135286EC1D0B015D007FC288 /* TodayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 135286EB1D0B015D007FC288 /* TodayViewController.swift */; };
135286EF1D0B015D007FC288 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 135286ED1D0B015D007FC288 /* MainInterface.storyboard */; };
135286F31D0B015D007FC288 /* Today Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 135286E61D0B015D007FC288 /* Today Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
135286F11D0B015D007FC288 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 135286C51D0B010C007FC288 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 135286E51D0B015D007FC288;
remoteInfo = "Today Extension";
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
135286F71D0B015E007FC288 /* Embed App Extensions */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 13;
files = (
135286F31D0B015D007FC288 /* Today Extension.appex in Embed App Extensions */,
);
name = "Embed App Extensions";
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
135286CD1D0B010C007FC288 /* Sample Extensions Project.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Sample Extensions Project.app"; sourceTree = BUILT_PRODUCTS_DIR; };
135286D01D0B010C007FC288 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
135286D21D0B010C007FC288 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
135286D51D0B010C007FC288 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
135286D71D0B010C007FC288 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
135286DA1D0B010C007FC288 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
135286DC1D0B010C007FC288 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
135286E61D0B015D007FC288 /* Today Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Today Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; };
135286E81D0B015D007FC288 /* NotificationCenter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NotificationCenter.framework; path = System/Library/Frameworks/NotificationCenter.framework; sourceTree = SDKROOT; };
135286EB1D0B015D007FC288 /* TodayViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TodayViewController.swift; sourceTree = "<group>"; };
135286EE1D0B015D007FC288 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = "<group>"; };
135286F01D0B015D007FC288 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
135286CA1D0B010C007FC288 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
135286E31D0B015D007FC288 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
135286E91D0B015D007FC288 /* NotificationCenter.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
135286C41D0B010C007FC288 = {
isa = PBXGroup;
children = (
135286CF1D0B010C007FC288 /* Sample Extensions Project */,
135286EA1D0B015D007FC288 /* Today Extension */,
135286E71D0B015D007FC288 /* Frameworks */,
135286CE1D0B010C007FC288 /* Products */,
);
sourceTree = "<group>";
};
135286CE1D0B010C007FC288 /* Products */ = {
isa = PBXGroup;
children = (
135286CD1D0B010C007FC288 /* Sample Extensions Project.app */,
135286E61D0B015D007FC288 /* Today Extension.appex */,
);
name = Products;
sourceTree = "<group>";
};
135286CF1D0B010C007FC288 /* Sample Extensions Project */ = {
isa = PBXGroup;
children = (
135286D01D0B010C007FC288 /* AppDelegate.swift */,
135286D21D0B010C007FC288 /* ViewController.swift */,
135286D41D0B010C007FC288 /* Main.storyboard */,
135286D71D0B010C007FC288 /* Assets.xcassets */,
135286D91D0B010C007FC288 /* LaunchScreen.storyboard */,
135286DC1D0B010C007FC288 /* Info.plist */,
);
path = "Sample Extensions Project";
sourceTree = "<group>";
};
135286E71D0B015D007FC288 /* Frameworks */ = {
isa = PBXGroup;
children = (
135286E81D0B015D007FC288 /* NotificationCenter.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
135286EA1D0B015D007FC288 /* Today Extension */ = {
isa = PBXGroup;
children = (
135286EB1D0B015D007FC288 /* TodayViewController.swift */,
135286ED1D0B015D007FC288 /* MainInterface.storyboard */,
135286F01D0B015D007FC288 /* Info.plist */,
);
path = "Today Extension";
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
135286CC1D0B010C007FC288 /* Sample Extensions Project */ = {
isa = PBXNativeTarget;
buildConfigurationList = 135286DF1D0B010C007FC288 /* Build configuration list for PBXNativeTarget "Sample Extensions Project" */;
buildPhases = (
135286C91D0B010C007FC288 /* Sources */,
135286CA1D0B010C007FC288 /* Frameworks */,
135286CB1D0B010C007FC288 /* Resources */,
135286F71D0B015E007FC288 /* Embed App Extensions */,
);
buildRules = (
);
dependencies = (
135286F21D0B015D007FC288 /* PBXTargetDependency */,
);
name = "Sample Extensions Project";
productName = "Sample Extensions Project";
productReference = 135286CD1D0B010C007FC288 /* Sample Extensions Project.app */;
productType = "com.apple.product-type.application";
};
135286E51D0B015D007FC288 /* Today Extension */ = {
isa = PBXNativeTarget;
buildConfigurationList = 135286F41D0B015E007FC288 /* Build configuration list for PBXNativeTarget "Today Extension" */;
buildPhases = (
135286E21D0B015D007FC288 /* Sources */,
135286E31D0B015D007FC288 /* Frameworks */,
135286E41D0B015D007FC288 /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = "Today Extension";
productName = "Today Extension";
productReference = 135286E61D0B015D007FC288 /* Today Extension.appex */;
productType = "com.apple.product-type.app-extension";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
135286C51D0B010C007FC288 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0730;
LastUpgradeCheck = 0730;
ORGANIZATIONNAME = CocoaPods;
TargetAttributes = {
135286CC1D0B010C007FC288 = {
CreatedOnToolsVersion = 7.3.1;
};
135286E51D0B015D007FC288 = {
CreatedOnToolsVersion = 7.3.1;
};
};
};
buildConfigurationList = 135286C81D0B010C007FC288 /* Build configuration list for PBXProject "Sample Extensions Project" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 135286C41D0B010C007FC288;
productRefGroup = 135286CE1D0B010C007FC288 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
135286CC1D0B010C007FC288 /* Sample Extensions Project */,
135286E51D0B015D007FC288 /* Today Extension */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
135286CB1D0B010C007FC288 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
135286DB1D0B010C007FC288 /* LaunchScreen.storyboard in Resources */,
135286D81D0B010C007FC288 /* Assets.xcassets in Resources */,
135286D61D0B010C007FC288 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
135286E41D0B015D007FC288 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
135286EF1D0B015D007FC288 /* MainInterface.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
135286C91D0B010C007FC288 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
135286D31D0B010C007FC288 /* ViewController.swift in Sources */,
135286D11D0B010C007FC288 /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
135286E21D0B015D007FC288 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
135286EC1D0B015D007FC288 /* TodayViewController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
135286F21D0B015D007FC288 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 135286E51D0B015D007FC288 /* Today Extension */;
targetProxy = 135286F11D0B015D007FC288 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
135286D41D0B010C007FC288 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
135286D51D0B010C007FC288 /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
135286D91D0B010C007FC288 /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
135286DA1D0B010C007FC288 /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
135286ED1D0B015D007FC288 /* MainInterface.storyboard */ = {
isa = PBXVariantGroup;
children = (
135286EE1D0B015D007FC288 /* Base */,
);
name = MainInterface.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
135286DD1D0B010C007FC288 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
135286DE1D0B010C007FC288 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
135286E01D0B010C007FC288 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = "Sample Extensions Project/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "cocoapods.Sample-Extensions-Project";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
135286E11D0B010C007FC288 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
EMBEDDED_CONTENT_CONTAINS_SWIFT = YES;
INFOPLIST_FILE = "Sample Extensions Project/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "cocoapods.Sample-Extensions-Project";
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
135286F51D0B015E007FC288 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = "Today Extension/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "cocoapods.Sample-Extensions-Project.Today-Extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Debug;
};
135286F61D0B015E007FC288 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
INFOPLIST_FILE = "Today Extension/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "cocoapods.Sample-Extensions-Project.Today-Extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
135286C81D0B010C007FC288 /* Build configuration list for PBXProject "Sample Extensions Project" */ = {
isa = XCConfigurationList;
buildConfigurations = (
135286DD1D0B010C007FC288 /* Debug */,
135286DE1D0B010C007FC288 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
135286DF1D0B010C007FC288 /* Build configuration list for PBXNativeTarget "Sample Extensions Project" */ = {
isa = XCConfigurationList;
buildConfigurations = (
135286E01D0B010C007FC288 /* Debug */,
135286E11D0B010C007FC288 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
135286F41D0B015E007FC288 /* Build configuration list for PBXNativeTarget "Today Extension" */ = {
isa = XCConfigurationList;
buildConfigurations = (
135286F51D0B015E007FC288 /* Debug */,
135286F61D0B015E007FC288 /* Release */,
);
defaultConfigurationIsVisible = 0;
};
/* End XCConfigurationList section */
};
rootObject = 135286C51D0B010C007FC288 /* Project object */;
}
//
// AppDelegate.swift
// Sample Extensions Project
//
// Created by Benjamin Asher on 6/10/16.
// Copyright © 2016 CocoaPods. All rights reserved.
//
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8150" systemVersion="15A204g" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8122"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Llm-lL-Icb"/>
<viewControllerLayoutGuide type="bottom" id="xb3-aO-Qok"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" initialViewController="BYZ-38-t0r">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="y3c-jy-aDJ"/>
<viewControllerLayoutGuide type="bottom" id="wfy-db-euE"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
</scene>
</scenes>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
//
// ViewController.swift
// Sample Extensions Project
//
// Created by Benjamin Asher on 6/10/16.
// Copyright © 2016 CocoaPods. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6211" systemVersion="14A298i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="M4Y-Lb-cyx">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6204"/>
</dependencies>
<scenes>
<!--Today View Controller-->
<scene sceneID="cwh-vc-ff4">
<objects>
<viewController id="M4Y-Lb-cyx" customClass="TodayViewController" customModuleProvider="target" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="Ft6-oW-KC0"/>
<viewControllerLayoutGuide type="bottom" id="FKl-LY-JtV"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" simulatedAppContext="notificationCenter" id="S3S-Oj-5AN">
<rect key="frame" x="0.0" y="0.0" width="320" height="37"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="top" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Hello World" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" preferredMaxLayoutWidth="280" translatesAutoresizingMaskIntoConstraints="NO" id="GcN-lo-r42">
<rect key="frame" x="20" y="8" width="280" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="lightTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="FKl-LY-JtV" firstAttribute="top" secondItem="GcN-lo-r42" secondAttribute="bottom" constant="20" symbolic="YES" id="0Q0-KW-PJ6"/>
<constraint firstItem="GcN-lo-r42" firstAttribute="leading" secondItem="S3S-Oj-5AN" secondAttribute="leading" constant="20" symbolic="YES" id="6Vq-gs-PHe"/>
<constraint firstAttribute="trailing" secondItem="GcN-lo-r42" secondAttribute="trailing" constant="20" symbolic="YES" id="L8K-9R-egU"/>
<constraint firstItem="GcN-lo-r42" firstAttribute="top" secondItem="Ft6-oW-KC0" secondAttribute="bottom" constant="20" symbolic="YES" id="mYS-Cv-VNx"/>
</constraints>
</view>
<extendedEdge key="edgesForExtendedLayout"/>
<nil key="simulatedStatusBarMetrics"/>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<size key="freeformSize" width="320" height="37"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="vXp-U4-Rya" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="516" y="285"/>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
<string>Today Extension</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSExtension</key>
<dict>
<key>NSExtensionMainStoryboard</key>
<string>MainInterface</string>
<key>NSExtensionPointIdentifier</key>
<string>com.apple.widget-extension</string>
</dict>
</dict>
</plist>
//
// TodayViewController.swift
// Today Extension
//
// Created by Benjamin Asher on 6/10/16.
// Copyright © 2016 CocoaPods. All rights reserved.
//
import UIKit
import NotificationCenter
class TodayViewController: UIViewController, NCWidgetProviding {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view from its nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResult.Failed
// If there's no update required, use NCUpdateResult.NoData
// If there's an update, use NCUpdateResult.NewData
completionHandler(NCUpdateResult.NewData)
}
}
...@@ -250,6 +250,12 @@ module Pod ...@@ -250,6 +250,12 @@ module Pod
@generator.send(:pod_targets).each { |pt| pt.stubs(:uses_swift?).returns(false) } @generator.send(:pod_targets).each { |pt| pt.stubs(:uses_swift?).returns(false) }
@generator.generate.to_hash['EMBEDDED_CONTENT_CONTAINS_SWIFT'].should.be.nil @generator.generate.to_hash['EMBEDDED_CONTENT_CONTAINS_SWIFT'].should.be.nil
end end
it 'does not set EMBEDDED_CONTENT_CONTAINS_SWIFT when there is swift, but the target is an extension' do
@target.stubs(:requires_host_target?).returns(true)
@generator.send(:pod_targets).first.stubs(:uses_swift?).returns(true)
@generator.generate.to_hash['EMBEDDED_CONTENT_CONTAINS_SWIFT'].should.be.nil
end
end end
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
......
...@@ -671,6 +671,66 @@ module Pod ...@@ -671,6 +671,66 @@ module Pod
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
describe 'extension targets' do
before do
SpecHelper.create_sample_app_copy_from_fixture('Sample Extensions Project')
@podfile = Pod::Podfile.new do
source SpecHelper.test_repo_url
platform :ios, '6.0'
project 'Sample Extensions Project/Sample Extensions Project'
target 'Sample Extensions Project' do
pod 'JSONKit', '1.4'
end
target 'Today Extension' do
pod 'monkey'
end
end
end
it 'copies extension pod targets to host target, when use_frameworks!' do
@podfile.use_frameworks!
analyzer = Pod::Installer::Analyzer.new(config.sandbox, @podfile)
result = analyzer.analyze
result.targets.flat_map { |at| at.pod_targets.map { |pt| "#{at.name}/#{pt.name}" } }.sort.should == [
'Pods-Sample Extensions Project/JSONKit',
'Pods-Sample Extensions Project/monkey',
'Pods-Today Extension/monkey',
].sort
end
it 'does not copy extension pod targets to host target, when not use_frameworks!' do
analyzer = Pod::Installer::Analyzer.new(config.sandbox, @podfile)
result = analyzer.analyze
result.targets.flat_map { |at| at.pod_targets.map { |pt| "#{at.name}/#{pt.name}" } }.sort.should == [
'Pods-Sample Extensions Project/JSONKit',
'Pods-Today Extension/monkey',
].sort
end
it 'raises exception when unable' do
podfile = Pod::Podfile.new do
source SpecHelper.test_repo_url
use_frameworks!
platform :ios, '6.0'
project 'Sample Extensions Project/Sample Extensions Project'
target 'Today Extension' do
pod 'monkey'
end
end
analyzer = Pod::Installer::Analyzer.new(config.sandbox, podfile)
should.raise ArgumentError do
analyzer.analyze
end.message.should.equal "Unable to find host target for Pods-Today Extension. Please add the extension's host targets to the Podfile."
end
end
#-------------------------------------------------------------------------#
describe 'Private helpers' do describe 'Private helpers' do
describe '#sources' do describe '#sources' do
describe 'when there are no explicit sources' do describe 'when there are no explicit sources' do
......
...@@ -147,22 +147,22 @@ module Pod ...@@ -147,22 +147,22 @@ module Pod
phase.nil?.should == true phase.nil?.should == true
end end
it 'adds an embed frameworks build phase if the target to integrate is an app extension' do it 'does not add an embed frameworks build phase if the target to integrate is an app extension' do
@pod_bundle.stubs(:requires_frameworks? => true) @pod_bundle.stubs(:requires_frameworks? => true)
target = @target_integrator.send(:native_targets).first target = @target_integrator.send(:native_targets).first
target.stubs(:symbol_type).returns(:app_extension) target.stubs(:symbol_type).returns(:app_extension)
@target_integrator.integrate! @target_integrator.integrate!
phase = target.shell_script_build_phases.find { |bp| bp.name == @embed_framework_phase_name } phase = target.shell_script_build_phases.find { |bp| bp.name == @embed_framework_phase_name }
phase.nil?.should == false phase.nil?.should == true
end end
it 'adds an embed frameworks build phase if the target to integrate is a watch extension' do it 'does not add an embed frameworks build phase if the target to integrate is a watch extension' do
@pod_bundle.stubs(:requires_frameworks? => true) @pod_bundle.stubs(:requires_frameworks? => true)
target = @target_integrator.send(:native_targets).first target = @target_integrator.send(:native_targets).first
target.stubs(:symbol_type).returns(:watch_extension) target.stubs(:symbol_type).returns(:watch_extension)
@target_integrator.integrate! @target_integrator.integrate!
phase = target.shell_script_build_phases.find { |bp| bp.name == @embed_framework_phase_name } phase = target.shell_script_build_phases.find { |bp| bp.name == @embed_framework_phase_name }
phase.nil?.should == false phase.nil?.should == true
end end
it 'adds an embed frameworks build phase if the target to integrate is a watchOS 2 extension' do it 'adds an embed frameworks build phase if the target to integrate is a watchOS 2 extension' do
......
...@@ -226,6 +226,25 @@ module Pod ...@@ -226,6 +226,25 @@ module Pod
dummy = support_files_dir + 'Pods-SampleProject-dummy.m' dummy = support_files_dir + 'Pods-SampleProject-dummy.m'
dummy.read.should.include?('@interface PodsDummy_Pods') dummy.read.should.include?('@interface PodsDummy_Pods')
end end
it 'creates an embed frameworks script, if the target does not require a host target' do
@pod_target.stubs(:requires_frameworks? => true)
@target.stubs(:requires_frameworks? => true)
@installer.install!
support_files_dir = config.sandbox.target_support_files_dir('Pods-SampleProject')
script = support_files_dir + 'Pods-SampleProject-frameworks.sh'
File.exist?(script).should == true
end
it 'does not create an embed frameworks script, if the target requires a host target' do
@pod_target.stubs(:requires_frameworks? => true)
@target.stubs(:requires_frameworks? => true)
@target.stubs(:requires_host_target? => true)
@installer.install!
support_files_dir = config.sandbox.target_support_files_dir('Pods-SampleProject')
script = support_files_dir + 'Pods-SampleProject-frameworks.sh'
File.exist?(script).should == false
end
end end
end end
end end
......
...@@ -193,6 +193,50 @@ module Pod ...@@ -193,6 +193,50 @@ module Pod
@target.requires_frameworks?.should == false @target.requires_frameworks?.should == false
end end
end end
describe 'Target might require a host target' do
before do
target_definition = Podfile::TargetDefinition.new('Pods', nil)
target_definition.abstract = false
@target = AggregateTarget.new(target_definition, config.sandbox)
project_path = SpecHelper.fixture('SampleProject/SampleProject.xcodeproj')
@target.user_project = Xcodeproj::Project.open(project_path)
@target.user_target_uuids = ['A346496C14F9BE9A0080D870']
end
it 'requires a host target for app extension targets' do
@target.user_targets.first.stubs(:symbol_type).returns(:app_extension)
@target.requires_host_target?.should == true
end
it 'requires a host target for watch extension targets' do
@target.user_targets.first.stubs(:symbol_type).returns(:watch_extension)
@target.requires_host_target?.should == true
end
it 'does not require a host target for watch 2 extension targets' do
@target.user_targets.first.stubs(:symbol_type).returns(:watch2_extension)
@target.requires_host_target?.should == false
end
it 'does not require a host target for application targets' do
@target.user_targets.first.stubs(:symbol_type).returns(:application)
@target.requires_host_target?.should == false
end
it 'does not require a host target, if there is no user project (manual integration)' do
@target.user_project = nil
@target.user_target_uuids = []
@target.requires_host_target?.should == false
end
it 'raises an exception if more than one user_target is found' do
@target.user_target_uuids += @target.user_target_uuids
should.raise ArgumentError do
@target.requires_host_target?
end.message.should.equal 'Expected single user_target for Pods'
end
end
end end
describe 'With frameworks' do describe 'With frameworks' do
......
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