Commit 0c9f2480 authored by Samuel E. Giddins's avatar Samuel E. Giddins

Merge pull request #3832 from CocoaPods/seg-dynamic

Better vendored framework support
parents 5f9e19c1 7430a599
......@@ -41,6 +41,11 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
[Samuel Giddins](https://github.com/segiddins)
[#4059](https://github.com/CocoaPods/CocoaPods/issues/4059)
* Include the `-ObjC` linker flag when static `vendored_frameworks` are present.
[Samuel Giddins](https://github.com/segiddins)
[#3870](https://github.com/CocoaPods/CocoaPods/issues/3870)
[#3992](https://github.com/CocoaPods/CocoaPods/issues/3992)
##### Enhancements
* Collapse the namespaced public and private pod xcconfig into one single
......@@ -78,6 +83,10 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
[Core#190](https://github.com/CocoaPods/Core/issues/190)
[#2682](https://github.com/CocoaPods/CocoaPods/issues/2682)
* Add support for dynamic `vendored_frameworks` and `vendored_libraries`.
[Samuel Giddins](https://github.com/segiddins)
[#1993](https://github.com/CocoaPods/CocoaPods/issues/1993)
## 0.38.2 (2015-07-25)
......
GIT
remote: https://github.com/CocoaPods/CLAide.git
revision: 675dd608cd5b3f8b62a4f34da48aff5d0b75d41f
revision: 4e7b02d849c3e82dff7c1cdacf33df45516acaf3
branch: master
specs:
claide (0.9.1)
GIT
remote: https://github.com/CocoaPods/Core.git
revision: fd41ee938a5687a39711b0f3d1f9e76dd506dd5d
revision: ca6db91dd318f121e5b2008d55f52c62a86d4016
branch: master
specs:
cocoapods-core (0.38.2)
......@@ -24,7 +24,7 @@ GIT
GIT
remote: https://github.com/CocoaPods/Xcodeproj.git
revision: 186cd802eb8b3b929fbf8bf70b66b6ae52dda72e
revision: 47b067acc2554977c9dca6fd38588cc26d449b71
branch: master
specs:
xcodeproj (0.26.3)
......@@ -92,7 +92,7 @@ PATH
GEM
remote: https://rubygems.org/
specs:
activesupport (4.2.3)
activesupport (4.2.4)
i18n (~> 0.7)
json (~> 1.7, >= 1.7.7)
minitest (~> 5.1)
......@@ -132,7 +132,7 @@ GEM
rb-kqueue (>= 0.2)
metaclass (0.0.4)
method_source (0.8.2)
minitest (5.7.0)
minitest (5.8.0)
mocha (1.1.0)
metaclass (~> 0.0.1)
mocha-on-bacon (0.2.2)
......
......@@ -123,7 +123,7 @@ module Pod
['--no-clean', 'Lint leaves the build directory intact for inspection'],
['--fail-fast', 'Lint stops on the first failing platform or subspec'],
['--use-libraries', 'Lint uses static libraries to install the spec'],
['--sources=https://github.com/artsy/Specs,master', 'The sources from which to pull dependant pods ' \
['--sources=https://github.com/artsy/Specs,master', 'The sources from which to pull dependent pods ' \
'(defaults to https://github.com/CocoaPods/Specs.git). ' \
'Multiple sources must be comma-delimited.'],
['--private', 'Lint skips checks that apply only to public specs'],
......
......@@ -23,7 +23,7 @@ module Pod
[
['--allow-warnings', 'Allows pushing even if there are warnings'],
['--use-libraries', 'Linter uses static libraries to install the spec'],
['--sources=https://github.com/artsy/Specs,master', 'The sources from which to pull dependant pods ' \
['--sources=https://github.com/artsy/Specs,master', 'The sources from which to pull dependent pods ' \
'(defaults to all available repos). ' \
'Multiple sources must be comma-delimited.'],
['--local-only', 'Does not perform the step of pushing REPO to its remote'],
......
......@@ -23,7 +23,7 @@ module Pod
['--no-clean', 'Lint leaves the build directory intact for inspection'],
['--fail-fast', 'Lint stops on the first failing platform or subspec'],
['--use-libraries', 'Lint uses static libraries to install the spec'],
['--sources=https://github.com/artsy/Specs,master', 'The sources from which to pull dependant pods ' \
['--sources=https://github.com/artsy/Specs,master', 'The sources from which to pull dependent pods ' \
'(defaults to https://github.com/CocoaPods/Specs.git). ' \
'Multiple sources must be comma-delimited.'],
['--private', 'Lint skips checks that apply only to public specs'],
......
......@@ -45,14 +45,10 @@ module Pod
#
# @return [String] the output of the command (STDOUT and STDERR).
#
# @todo Find a way to display the live output of the commands.
#
def self.execute_command(executable, command, raise_on_failure)
def self.execute_command(executable, command, raise_on_failure = true)
bin = which(executable)
raise Informative, "Unable to locate the executable `#{executable}`" unless bin
require 'shellwords'
command = command.map(&:to_s)
full_command = "#{bin} #{command.join(' ')}"
......@@ -64,7 +60,8 @@ module Pod
end
status = popen3(bin, command, stdout, stderr)
output = stdout.join + stderr.join
stdout, stderr = stdout.join, stderr.join
output = stdout + stderr
unless status.success?
if raise_on_failure
raise Informative, "#{full_command}\n\n#{output}"
......@@ -72,6 +69,7 @@ module Pod
UI.message("[!] Failed: #{full_command}".red)
end
end
output
end
......@@ -95,6 +93,38 @@ module Pod
nil
end
# Runs the given command, capturing the desired output.
#
# @param [String] bin
# The binary to use.
#
# @param [Array<#to_s>] command
# The command to send to the binary.
#
# @param [Symbol] capture
# Whether it should raise if the command fails.
#
# @raise If the executable could not be located.
#
# @return [(String, Process::Status)]
# The desired captured output from the command, and the status from
# running the command.
#
def self.capture_command(executable, command, capture: :merge)
bin = which(executable)
raise Informative, "Unable to locate the executable `#{executable}`" unless bin
require 'open3'
command = command.map(&:to_s)
case capture
when :merge then Open3.capture2e(bin, *command)
when :both then Open3.capture3(bin, *command)
when :out then Open3.capture2(bin, *command)
when :err then Open3.capture3(bin, *command).drop(1)
when :none then Open3.capture2(bin, *command).last
end
end
private
def self.popen3(bin, command, stdout, stderr)
......
......@@ -34,7 +34,7 @@ module Pod
# @return [String] The contents of the embed frameworks script.
#
def script
script = <<-eos.strip_heredoc
script = <<-SH.strip_heredoc
#!/bin/sh
set -e
......@@ -47,8 +47,10 @@ module Pod
{
if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then
local source="${BUILT_PRODUCTS_DIR}/$1"
else
elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then
local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")"
elif [ -r "$1" ]; then
local source="$1"
fi
local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
......@@ -62,14 +64,24 @@ module Pod
echo "rsync -av --filter \\"- CVS/\\" --filter \\"- .svn/\\" --filter \\"- .git/\\" --filter \\"- .hg/\\" --filter \\"- Headers\\" --filter \\"- PrivateHeaders\\" --filter \\"- Modules\\" \\"${source}\\" \\"${destination}\\""
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}"
local basename
basename="$(basename -s .framework "$1")"
binary="${destination}/${basename}.framework/${basename}"
if ! [ -r "$binary" ]; then
binary="${destination}/${basename}"
fi
# Strip invalid architectures so "fat" simulator / device frameworks work on device
if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then
strip_invalid_archs "$binary"
fi
# Resign the code if required by the build settings to avoid unstable apps
code_sign_if_enabled "${destination}/$(basename "$1")"
# Embed linked Swift runtime libraries
local basename
basename="$(basename "$1" | sed -E s/\\\\..+// && exit ${PIPESTATUS[0]})"
local swift_runtime_libs
swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/${basename}.framework/${basename}" | grep --color=never @rpath/libswift | sed -E s/@rpath\\\\/\\(.+dylib\\).*/\\\\1/g | uniq -u && exit ${PIPESTATUS[0]})
swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\\\/\\(.+dylib\\).*/\\\\1/g | uniq -u && exit ${PIPESTATUS[0]})
for lib in $swift_runtime_libs; do
echo "rsync -auv \\"${SWIFT_STDLIB_PATH}/${lib}\\" \\"${destination}\\""
rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
......@@ -87,15 +99,33 @@ module Pod
fi
}
eos
script += "\n" unless frameworks_by_config.values.all?(&:empty?)
# Strip invalid architectures
strip_invalid_archs() {
binary="$1"
# Get architectures for current file
archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)"
stripped=""
for arch in $archs; do
if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then
# Strip non-valid architectures in-place
lipo -remove "$arch" -output "$binary" "$binary" || exit 1
stripped="$stripped $arch"
fi
done
if [[ "$stripped" ]]; then
echo "Stripped $binary of architectures:$stripped"
fi
}
SH
script << "\n" unless frameworks_by_config.values.all?(&:empty?)
frameworks_by_config.each do |config, frameworks|
unless frameworks.empty?
script += %(if [[ "$CONFIGURATION" == "#{config}" ]]; then\n)
script << %(if [[ "$CONFIGURATION" == "#{config}" ]]; then\n)
frameworks.each do |framework|
script += " install_framework '#{framework}'\n"
script << %( install_framework "#{framework}"\n)
end
script += "fi\n"
script << "fi\n"
end
end
script
......
......@@ -53,11 +53,12 @@ module Pod
#
def generate
includes_static_libs = !target.requires_frameworks?
includes_static_libs ||= pod_targets.flat_map(&:file_accessors).any? { |fa| !fa.vendored_libraries.empty? }
includes_static_libs ||= pod_targets.flat_map(&:file_accessors).any? { |fa| !fa.vendored_static_artifacts.empty? }
config = {
'OTHER_LDFLAGS' => '$(inherited) ' + XCConfigHelper.default_ld_flags(target, includes_static_libs),
'PODS_ROOT' => target.relative_pods_root,
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ',
}
@xcconfig = Xcodeproj::Config.new(config)
......@@ -112,7 +113,7 @@ module Pod
build_settings['OTHER_CFLAGS'] += ' ' + XCConfigHelper.quote(library_header_search_paths, '-isystem')
end
if pod_targets.any? { |t| t.should_build? && t.scoped? }
build_settings['FRAMEWORK_SEARCH_PATHS'] = '$(inherited) "$PODS_FRAMEWORK_BUILD_PATH"'
build_settings['FRAMEWORK_SEARCH_PATHS'] = '"$PODS_FRAMEWORK_BUILD_PATH"'
end
@xcconfig.merge!(build_settings)
else
......
......@@ -43,6 +43,7 @@ module Pod
target_search_paths = target.build_headers.search_paths(target.platform)
sandbox_search_paths = target.sandbox.public_headers.search_paths(target.platform)
search_paths = target_search_paths.concat(sandbox_search_paths).uniq
framework_search_paths = target.dependent_targets.flat_map(&:file_accessors).flat_map(&:vendored_frameworks).map { |fw| '${PODS_ROOT}/' << fw.dirname.relative_path_from(target.sandbox.root).to_s }
config = {
'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target),
......@@ -50,9 +51,12 @@ module Pod
'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(search_paths),
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
'SKIP_INSTALL' => 'YES',
'FRAMEWORK_SEARCH_PATHS' => '$(inherited) ' << XCConfigHelper.quote(framework_search_paths)
# 'USE_HEADERMAP' => 'NO'
}
@xcconfig = Xcodeproj::Config.new(config)
if target.requires_frameworks? && target.scoped?
# Only quote the FRAMEWORK_SEARCH_PATHS entry, because it’s a setting that takes multiple values.
# In addition, quoting CONFIGURATION_BUILD_DIR would make it be interpreted as a relative path.
......@@ -61,10 +65,9 @@ module Pod
'FRAMEWORK_SEARCH_PATHS' => '"$PODS_FRAMEWORK_BUILD_PATH"',
'CONFIGURATION_BUILD_DIR' => '$PODS_FRAMEWORK_BUILD_PATH',
}
config.merge!(build_settings)
@xcconfig.merge!(build_settings)
end
@xcconfig = Xcodeproj::Config.new(config)
XCConfigHelper.add_settings_for_file_accessors_of_target(target, @xcconfig)
target.file_accessors.each do |file_accessor|
@xcconfig.merge!(file_accessor.spec_consumer.pod_target_xcconfig)
......
......@@ -417,11 +417,7 @@ module Pod
dependencies = pod_targets.select(&:should_build?).flat_map(&:dependencies)
dependended_upon_targets = pod_targets.select { |t| dependencies.include?(t.pod_name) && !t.should_build? }
static_libs = dependended_upon_targets.flat_map(&:file_accessors).flat_map do |fa|
static_frameworks = fa.vendored_frameworks.reject { |fw| `file #{fw + fw.basename('.framework')} 2>&1` =~ /dynamically linked/ }
fa.vendored_libraries + static_frameworks
end
static_libs = dependended_upon_targets.flat_map(&:file_accessors).flat_map(&:vendored_static_artifacts)
unless static_libs.empty?
raise Informative, "The '#{aggregate_target.label}' target has " \
"transitive dependencies that include static binaries: (#{static_libs.to_sentence})"
......
......@@ -306,6 +306,7 @@ module Pod
# transitive dependencies can't be deduplicated.
pod_targets.flat_map do |target|
dependent_targets = transitive_dependencies_for_pod_target(target, pod_targets)
target.dependent_targets = dependent_targets
if dependent_targets.any?(&:scoped?)
target.scoped
else
......
......@@ -18,8 +18,8 @@ module Pod
create_info_plist_file
create_module_map
create_umbrella_header
create_embed_frameworks_script
end
create_embed_frameworks_script
create_bridge_support_file
create_copy_resources_script
create_acknowledgements
......@@ -145,10 +145,12 @@ module Pod
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) && pod_target.should_build?
pod_target.include_in_build_config?(target_definition, config)
end
frameworks_by_config[config] = relevant_pod_targets.map do |pod_target|
"#{target_definition.label}/#{pod_target.product_name}"
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 << "#{target_definition.label}/#{pod_target.product_name}" if pod_target.should_build? && pod_target.requires_frameworks?
frameworks
end
end
generator = Generator::EmbedFrameworksScript.new(frameworks_by_config)
......
......@@ -43,10 +43,10 @@ module Pod
XCConfigIntegrator.integrate(target, native_targets),
update_to_cocoapods_0_34,
update_to_cocoapods_0_37_1,
remove_embed_frameworks_script_phases,
update_to_cocoapods_0_39,
unless native_targets_to_integrate.empty?
add_pods_library
add_embed_frameworks_script_phase if target.requires_frameworks?
add_embed_frameworks_script_phase
add_copy_resources_script_phase
add_check_manifest_lock_script_phase
true
......@@ -112,11 +112,30 @@ module Pod
# @todo This can be removed for CocoaPods 1.0
#
def update_to_cocoapods_0_37_1
(native_targets - native_targets_to_embed_in).any? do |native_target|
targets_to_embed = native_targets.select do |target|
EMBED_FRAMEWORK_TARGET_TYPES.include?(target.symbol_type)
end
(native_targets - targets_to_embed).any? do |native_target|
remove_embed_frameworks_script_phase(native_target)
end
end
# Adds the embed frameworks script when integrating as a static library.
#
# @return [Bool] whether any changes to the project were made.
#
# @todo This can be removed for CocoaPods 1.0
#
def update_to_cocoapods_0_39
requires_update = native_targets_to_embed_in.any? do |target|
!target.shell_script_build_phases.find { |bp| bp.name == 'Embed Pods Frameworks' }
end
if requires_update
add_embed_frameworks_script_phase
true
end
end
# Adds spec product reference to the frameworks build phase of the
# {TargetDefinition} integration libraries. Adds a file reference to
# the frameworks group of the project and adds it to the frameworks
......@@ -166,19 +185,6 @@ module Pod
end
end
# Delete 'Embed Pods Frameworks' Build Phases, if they exist
# and are not needed anymore due to not integrating the
# dependencies by frameworks.
#
# @return [Bool] whether any changes to the project were made.
#
def remove_embed_frameworks_script_phases
return false if target.requires_frameworks?
native_targets.any? do |native_target|
remove_embed_frameworks_script_phase(native_target)
end
end
# Delete a 'Embed Pods Frameworks' Copy Files Build Phase if present
#
# @param [PBXNativeTarget] native_target
......
......@@ -152,6 +152,22 @@ module Pod
paths_for_attribute(:vendored_frameworks, true)
end
# @return [Array<Pathname>] The paths of the dynamic framework bundles
# that come shipped with the Pod.
#
def vendored_dynamic_frameworks
vendored_frameworks.select do |framework|
dynamic_binary?(framework + framework.basename('.*'))
end
end
# @return [Array<Pathname>] The paths of the static (fake) framework
# bundles that come shipped with the Pod.
#
def vendored_static_frameworks
vendored_frameworks - vendored_dynamic_frameworks
end
# @param [Pathname] framework
# The vendored framework to search into.
# @return [Pathname] The path of the header directory of the
......@@ -187,6 +203,36 @@ module Pod
paths_for_attribute(:vendored_libraries)
end
# @return [Array<Pathname>] The paths of the dynamic libraries
# that come shipped with the Pod.
#
def vendored_dynamic_libraries
vendored_libraries.select do |library|
dynamic_binary?(library)
end
end
# @return [Array<Pathname>] The paths of the static libraries
# that come shipped with the Pod.
#
def vendored_static_libraries
vendored_libraries - vendored_dynamic_libraries
end
# @return [Array<Pathname>] The paths of the dynamic binary artifacts
# that come shipped with the Pod.
#
def vendored_dynamic_artifacts
vendored_dynamic_libraries + vendored_dynamic_frameworks
end
# @return [Array<Pathname>] The paths of the static binary artifacts
# that come shipped with the Pod.
#
def vendored_static_artifacts
vendored_static_libraries + vendored_static_frameworks
end
# @return [Hash{String => Array<Pathname>}] A hash that describes the
# resource bundles of the Pod. The keys represent the name of
# the bundle while the values the path of the resources.
......@@ -315,6 +361,17 @@ module Pod
result.flatten.compact.uniq
end
# @param [Pathname] binary
# The file to be checked for being a dynamic Mach-O binary.
#
# @return [Boolean] Whether `binary` can be dynamically linked.
#
def dynamic_binary?(binary)
return unless binary.file?
output, status = Executable.capture_command('file', [binary], :capture => :out)
status.success? && output =~ /dynamically linked/
end
#-----------------------------------------------------------------------#
end
end
......
......@@ -33,6 +33,11 @@ module Pod
attr_reader :scoped
alias_method :scoped?, :scoped
# @return [Array<PodTarget>] the targets that this target has a dependency
# upon.
#
attr_accessor :dependent_targets
# @param [Array<Specification>] @spec #see spec
# @param [Array<TargetDefinition>] target_definitions @see target_definitions
# @param [Sandbox] sandbox @see sandbox
......@@ -49,6 +54,7 @@ module Pod
@build_headers = Sandbox::HeadersStore.new(sandbox, 'Private')
@file_accessors = []
@resource_bundle_targets = []
@dependent_targets = []
end
# @return [Array<PodTarget>] a scoped copy for each target definition.
......@@ -60,6 +66,7 @@ module Pod
target.user_build_configurations = user_build_configurations
target.native_target = native_target
target.archs = archs
target.dependent_targets = dependent_targets.map(&:scoped)
end
end
end
......
......@@ -382,8 +382,8 @@ module Pod
deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name)
unless file_accessor.nil?
dynamic_frameworks = file_accessor.vendored_frameworks.select { |fw| `file #{fw + fw.basename('.framework')} 2>&1` =~ /dynamically linked/ }
dynamic_libraries = file_accessor.vendored_libraries.select { |lib| `file #{lib} 2>&1` =~ /dynamically linked/ }
dynamic_frameworks = file_accessor.vendored_dynamic_frameworks
dynamic_libraries = file_accessor.vendored_dynamic_libraries
if (dynamic_frameworks.count > 0 || dynamic_libraries.count > 0) && consumer.platform_name == :ios &&
(deployment_target.nil? || Version.new(deployment_target).major < 8)
error('dynamic', 'Dynamic frameworks and libraries are only supported on iOS 8.0 and onwards.')
......
Subproject commit c3a5c5887ee81a34d548accc3e84aea3d071a5b2
Subproject commit 748ad0dac4f5660eba1d191efa89e0fc8d791b0e
......@@ -47,6 +47,8 @@ require 'bundler/setup'
require 'pretty_bacon'
require 'colored'
require 'clintegracon'
require 'fileutils'
require 'integration/file_tree'
require 'integration/xcodeproj_project_yaml'
require 'tmpdir'
......@@ -69,6 +71,12 @@ CLIntegracon.configure do |c|
end
end
c.transform_produced '**/*.framework' do |path|
tree = FileTree.to_tree(path)
FileUtils.rm_rf path
File.open(path, 'w') { |f| f << tree }
end
# Register special handling for YAML files
paths = [/Podfile\.lock/, /Manifest\.lock$/, /xcodeproj\.yaml$/]
c.has_special_handling_for(*paths) do |path|
......@@ -115,16 +123,28 @@ describe_cli 'pod' do
s.replace_path ROOT.to_s, 'ROOT'
s.replace_path `which git`.chomp, 'GIT_BIN'
s.replace_path `which hg`.chomp, 'HG_BIN' if has_mercurial
s.replace_path `which bash`.chomp, 'BASH_BIN'
s.replace_path `which curl`.chomp, 'CURL_BIN'
s.replace_user_path 'Library/Caches/CocoaPods', 'CACHES_DIR'
s.replace_pattern /#{Dir.tmpdir}\/[\w-]+/i, 'TMPDIR'
s.replace_pattern /#{Dir.tmpdir}\/[\w-]+/io, 'TMPDIR'
s.replace_pattern /\d{4}-\d\d-\d\d \d\d:\d\d:\d\d [-+]\d{4}/, '<#DATE#>'
s.replace_pattern /\(Took \d+.\d+ seconds\)/, '(Took <#DURATION#> seconds)'
s.replace_path %r{
`[^`]*? # The opening backtick on a plugin path
([[[:alnum:]]_+-]+?) # The plugin name
(- ([[:xdigit:]]+ | #{Gem::Version::VERSION_PATTERN}))? # The version or SHA
/lib/cocoapods_plugin.rb # The actual plugin file that gets loaded
}ix, '`\1/lib/cocoapods_plugin.rb'
}iox, '`\1/lib/cocoapods_plugin.rb'
# rubocop:disable Style/RegexpLiteral
s.replace_pattern %r{
^(\s* \$ \s (CURL_BIN | #{`which curl`.strip}) .* \n)
^\s* % \s* Total .* \n
^\s* Dload \s* Upload .* \n
(^\s* [[:cntrl:]] .* \n)+
}iox, "\\1\n"
# rubocop:enable Style/RegexpLiteral
end
describe 'Pod install' do
......@@ -226,6 +246,13 @@ describe_cli 'pod' do
'install --no-repo-update'
end
describe 'Integrates a Pod using a dynamic vendored framework' do
# We have to disable verbose mode by adding --no-verbose here,
# otherwise curl output is included in execution output.
behaves_like cli_spec 'install_vendored_dynamic_framework',
'install --no-repo-update --no-verbose'
end
# @todo add tests for all the hooks API
#
describe 'Runs the Podfile callbacks' do
......
require 'pathname'
module FileTree
def to_tree(path, depth = 0)
path = Pathname(path)
indentation = ' ' * depth * 2
tree = indentation << path.to_path << "\n"
path.children.each do |child|
tree << to_tree(child, depth + 1)
end if path.directory?
tree
end
module_function :to_tree
end
......@@ -8,17 +8,17 @@ module Pod
'Release' => %w(CrashlyticsFramework.framework),
}
generator = Pod::Generator::EmbedFrameworksScript.new(frameworks)
generator.send(:script).should.include <<-eos.strip_heredoc
generator.send(:script).should.include <<-SH.strip_heredoc
if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework 'Pods/Loopback.framework'
install_framework 'Reveal.framework'
install_framework "Pods/Loopback.framework"
install_framework "Reveal.framework"
fi
eos
generator.send(:script).should.include <<-eos.strip_heredoc
SH
generator.send(:script).should.include <<-SH.strip_heredoc
if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework 'CrashlyticsFramework.framework'
install_framework "CrashlyticsFramework.framework"
fi
eos
SH
end
end
end
......@@ -158,7 +158,7 @@ module Pod
end
it 'does not add the framework build path to the xcconfig' do
@xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.be.nil?
@xcconfig.to_hash['FRAMEWORK_SEARCH_PATHS'].should.be.nil
end
it 'configures the project to load all members that implement Objective-c classes or categories' do
......
......@@ -47,6 +47,7 @@ module Pod
'Pods-acknowledgements.markdown',
'Pods-acknowledgements.plist',
'Pods-dummy.m',
'Pods-frameworks.sh',
'Pods-resources.sh',
'Pods.appstore.xcconfig',
'Pods.debug.xcconfig',
......
......@@ -108,11 +108,11 @@ module Pod
phase.nil?.should == false
end
it 'does not add an embed frameworks build phase by default' do
it 'adds an embed frameworks build phase by default' do
@target_integrator.integrate!
target = @target_integrator.send(:native_targets).first
phase = target.shell_script_build_phases.find { |bp| bp.name == 'Embed Pods Frameworks' }
phase.nil?.should == true
phase.nil?.should == false
end
it 'does not add an embed frameworks build phase if the target to integrate is a framework' do
......@@ -151,25 +151,24 @@ module Pod
phase.nil?.should == false
end
it 'removes existing embed frameworks build phases from integrated framework targets' do
it 'does not remove existing embed frameworks build phases from integrated framework targets' do
@pod_bundle.stubs(:requires_frameworks? => true)
@target_integrator.integrate!
@pod_bundle.stubs(:requires_frameworks? => false)
target = @target_integrator.send(:native_targets).first
target.stubs(:symbol_type).returns(:framework)
@target_integrator.integrate!
phase = target.shell_script_build_phases.find { |bp| bp.name == 'Embed Pods Frameworks' }
phase.nil?.should == true
phase.should.not.be.nil
end
it 'removes existing embed frameworks build phases if frameworks are not used anymore' do
it 'does not remove existing embed frameworks build phases if frameworks are not used anymore' do
@pod_bundle.stubs(:requires_frameworks? => true)
@target_integrator.integrate!
@pod_bundle.stubs(:requires_frameworks? => false)
@target_integrator.integrate!
target = @target_integrator.send(:native_targets).first
phase = target.shell_script_build_phases.find { |bp| bp.name == 'Embed Pods Frameworks' }
phase.nil?.should == true
phase.nil?.should == false
end
end
......
......@@ -386,6 +386,7 @@ module Pod
end
@installer.stubs(:podfile).returns(podfile)
@installer.stubs(:lockfile).returns(nil)
Downloader::Git.any_instance.expects(:download).once
Downloader::Git.any_instance.expects(:download_head).once
Downloader::Git.any_instance.stubs(:checkout_options).returns({})
@installer.prepare
......
......@@ -251,7 +251,7 @@ module Pod
UI.warnings = ''
set_up_test_repo_for_update
Dir.chdir(test_repo_path) do
`git remote set-url origin https://example.com`
`git remote set-url origin file:///dev/null`
end
SourcesManager.update(test_repo_path.basename.to_s, true)
UI.warnings.should.include('not able to update the `master` repo')
......
......@@ -490,6 +490,13 @@ module Pod
end
it 'validates a podspec with dependencies' do
podspec = stub_podspec(/.*name.*/, '"name": "SBJson",').gsub(/.*version.*/, '"version": "3.2",')
file = write_podspec(podspec, 'SBJson.podspec.json')
spec = Specification.from_file(file)
set = mock
set.stubs(:all_specifications).returns([spec])
Source::Aggregate.any_instance.stubs(:search).with(Dependency.new('SBJson', '~> 3.2')).returns(set)
podspec = stub_podspec(/.*name.*/, '"name": "ZKit",')
podspec.gsub!(/.*requires_arc.*/, '"dependencies": { "SBJson": [ "~> 3.2" ] }, "requires_arc": false')
file = write_podspec(podspec, 'ZKit.podspec.json')
......
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