Unverified Commit 8307a689 authored by Dimitris Koutsogiorgas's avatar Dimitris Koutsogiorgas Committed by GitHub

Merge pull request #7412 from dnkoutso/strict_header_search_paths

Add support for modular header search paths, include "legacy" support
parents 31b2b9cb 95d59b9d
......@@ -8,6 +8,10 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
##### Enhancements
* Add support for modular header search paths, include "legacy" support.
[Dimitris Koutsogiorgas](https://github.com/dnkoutso)
[#7412](https://github.com/CocoaPods/CocoaPods/pull/7412)
* Set direct and transitive dependency header search paths for pod targets
[Dimitris Koutsogiorgas](https://github.com/dnkoutso)
[#7116](https://github.com/CocoaPods/CocoaPods/pull/7116)
......
......@@ -7,7 +7,7 @@ GIT
GIT
remote: https://github.com/CocoaPods/Core.git
revision: 1f8ced657a224eabeba6958d130ee04058d91f60
revision: e0c6884b37ab6a44095a2bbdbfe9032627a90388
branch: master
specs:
cocoapods-core (1.4.0)
......
......@@ -163,11 +163,11 @@ module Pod
private
# Add build settings, which ensure that the pod targets can be imported
# from the integrating target by all sort of imports, which are:
# - `#import <…>`
# - `#import "…"`
# - `@import …;` / `import …`
# Add build settings, which ensure that the pod targets can be imported from the integrating target.
# For >= 1.5.0 we use modular (stricter) header search paths this means that the integrated target will only be
# able to import public headers using `<>` or `@import` notation, but never import any private headers.
#
# For < 1.5.0 legacy header search paths the same rules apply: It's the wild west.
#
def generate_settings_to_import_pod_targets
@xcconfig.merge! XCConfigHelper.search_paths_for_dependent_targets(target, pod_targets)
......@@ -176,7 +176,6 @@ module Pod
generator = AggregateXCConfig.new(search_paths_target, configuration_name)
@xcconfig.merge! XCConfigHelper.search_paths_for_dependent_targets(nil, search_paths_target.pod_targets)
@xcconfig.merge!(generator.settings_to_import_pod_targets)
# Propagate any HEADER_SEARCH_PATHS settings from the search paths.
XCConfigHelper.propagate_header_search_paths_from_search_paths(search_paths_target, @xcconfig)
end
......
......@@ -147,11 +147,15 @@ module Pod
pod_target.build_headers.add_search_path(headers_sandbox, pod_target.platform)
sandbox.public_headers.add_search_path(headers_sandbox, pod_target.platform)
# Private headers will always end up in Pods/Headers/Private/PodA/*.h
# This will allow for `""` imports to work.
header_mappings(headers_sandbox, file_accessor, file_accessor.headers).each do |namespaced_path, files|
pod_target.build_headers.add_files(namespaced_path, files.reject { |f| f.to_path =~ framework_exp })
end
header_mappings(headers_sandbox, file_accessor, file_accessor.public_headers).each do |namespaced_path, files|
# Public headers on the other hand will be added in Pods/Headers/Public/PodA/PodA/*.h
# The extra folder is intentional in order for `<>` imports to work.
header_mappings(headers_sandbox, file_accessor, file_accessor.public_headers, :public).each do |namespaced_path, files|
sandbox.public_headers.add_files(namespaced_path, files.reject { |f| f.to_path =~ framework_exp })
end
end
......@@ -295,6 +299,10 @@ module Pod
# The consumer file accessor for which the headers need to be
# linked.
#
# @param [Symbol] visibility_scope
# The visibility scope to produce header mappings for. If set to :public then the headers
# are nested an additional level deep. For example, 'Pods/Headers/Public/PodA/PodA'.
#
# @param [Array<Pathname>] headers
# The absolute paths of the headers which need to be mapped.
#
......@@ -302,17 +310,18 @@ module Pod
# headers folders as the keys and the absolute paths of the
# header files as the values.
#
def header_mappings(headers_sandbox, file_accessor, headers)
def header_mappings(headers_sandbox, file_accessor, headers, visibility_scope = :private)
consumer = file_accessor.spec_consumer
header_mappings_dir = consumer.header_mappings_dir
dir = headers_sandbox
dir += headers_sandbox if visibility_scope == :public
dir += consumer.header_dir if consumer.header_dir
mappings = {}
headers.each do |header|
sub_dir = dir
if consumer.header_mappings_dir
header_mappings_dir = file_accessor.path_list.root + consumer.header_mappings_dir
relative_path = header.relative_path_from(header_mappings_dir)
if header_mappings_dir
relative_path = header.relative_path_from(file_accessor.path_list.root + header_mappings_dir)
sub_dir += relative_path.dirname
end
mappings[sub_dir] ||= []
......
......@@ -57,7 +57,7 @@ module Pod
def initialize(root)
FileUtils.mkdir_p(root)
@root = Pathname.new(root).realpath
@public_headers = HeadersStore.new(self, 'Public')
@public_headers = HeadersStore.new(self, 'Public', :public)
@predownloaded_pods = []
@checkout_sources = {}
@development_pods = {}
......
......@@ -4,7 +4,7 @@ module Pod
# the header search paths.
#
class HeadersStore
SEARCH_PATHS_KEY = Struct.new(:platform_name, :target_name)
SEARCH_PATHS_KEY = Struct.new(:platform_name, :target_name, :use_modular_headers)
# @return [Pathname] the absolute path of this header directory.
#
......@@ -22,36 +22,48 @@ module Pod
# the relative path to the sandbox root and hence to the Pods
# project.
#
def initialize(sandbox, relative_path)
# @param [Symbol] visibility_scope
# the header visibility scope to use in this store. Can be `:private` or `:public`.
#
def initialize(sandbox, relative_path, visibility_scope)
@sandbox = sandbox
@relative_path = relative_path
@search_paths = []
@search_paths_cache = {}
@visibility_scope = visibility_scope
end
# @param [Platform] platform
# the platform for which the header search paths should be
# returned
# returned.
#
# @param [String] target_name
# the target for which the header search paths should be
# returned. This will return only header root scope e.g. `${PODS_ROOT}/Headers/Public`
# if the target name specified is `nil`.
# returned. Can be `nil` in which case all headers that match the platform
# will be returned.
#
# @param [Boolean] use_modular_headers
# whether the search paths generated should use modular (stricter) style.
#
# @return [Array<String>] All the search paths of the header directory in
# xcconfig format. The paths are specified relative to the pods
# root with the `${PODS_ROOT}` variable.
#
def search_paths(platform, target_name = nil)
key = SEARCH_PATHS_KEY.new(platform.name, target_name)
def search_paths(platform, target_name = nil, use_modular_headers = false)
key = SEARCH_PATHS_KEY.new(platform.name, target_name, use_modular_headers)
return @search_paths_cache[key] if @search_paths_cache.key?(key)
platform_search_paths = @search_paths.select do |entry|
search_paths = @search_paths.select do |entry|
matches_platform = entry[:platform] == platform.name
matches_target = target_name.nil? || (entry[:path].basename.to_s == target_name)
matches_platform && matches_target
end
headers_dir = root.relative_path_from(sandbox.root).dirname
@search_paths_cache[key] = ["${PODS_ROOT}/#{headers_dir}/#{@relative_path}"] + platform_search_paths.uniq.map { |entry| "${PODS_ROOT}/#{headers_dir}/#{entry[:path]}" }
@search_paths_cache[key] = search_paths.uniq.flat_map do |entry|
path = "${PODS_ROOT}/#{headers_dir}/#{entry[:path]}"
paths = [path]
paths.push("#{path}/#{entry[:path].basename}") if !use_modular_headers && @visibility_scope == :public
paths
end
end
# Removes the directory as it is regenerated from scratch during each
......
......@@ -54,7 +54,7 @@ module Pod
@target_definitions = target_definitions
@sandbox = sandbox
@scope_suffix = scope_suffix
@build_headers = Sandbox::HeadersStore.new(sandbox, 'Private')
@build_headers = Sandbox::HeadersStore.new(sandbox, 'Private', :private)
@file_accessors = []
@resource_bundle_targets = []
@test_resource_bundle_targets = []
......@@ -195,6 +195,20 @@ module Pod
end
end
# @return [Boolean] Whether the target defines a "module"
# (and thus will need a module map and umbrella header).
#
# @note Static library targets can temporarily opt in to this behavior by setting
# `DEFINES_MODULE = YES` in their specification's `pod_target_xcconfig`.
#
def defines_module?
return @defines_module if defined?(@defines_module)
return @defines_module = true if uses_swift? || requires_frameworks?
return @defines_module = true if target_definitions.any? { |td| td.build_pod_as_module?(pod_name) }
@defines_module = non_test_specs.any? { |s| s.consumer(platform).pod_target_xcconfig['DEFINES_MODULE'] == 'YES' }
end
# @return [Array<Hash{Symbol=>String}>] An array of hashes where each hash represents a single script phase.
#
def script_phases
......@@ -224,7 +238,7 @@ module Pod
#
attr_reader :test_specs
# @return [Array<Specification>] All of the non test specs within this target.
# @return [Array<Specification>] All of the specs within this target that are not test specs.
#
attr_reader :non_test_specs
......@@ -572,16 +586,33 @@ module Pod
#
def header_search_paths(include_test_dependent_targets = false)
header_search_paths = []
header_search_paths.concat(build_headers.search_paths(platform))
header_search_paths.concat(sandbox.public_headers.search_paths(platform, pod_name))
header_search_paths.concat(build_headers.search_paths(platform, nil, uses_modular_headers?))
header_search_paths.concat(sandbox.public_headers.search_paths(platform, pod_name, uses_modular_headers?))
dependent_targets = recursive_dependent_targets
dependent_targets += recursive_test_dependent_targets if include_test_dependent_targets
dependent_targets.each do |dependent_target|
header_search_paths.concat(sandbox.public_headers.search_paths(platform, dependent_target.pod_name))
header_search_paths.concat(sandbox.public_headers.search_paths(platform, dependent_target.pod_name, defines_module? && dependent_target.uses_modular_headers?(false)))
end
header_search_paths.uniq
end
protected
# Returns whether the pod target should use modular headers.
#
# @param [Boolean] only_if_defines_modules
# whether the use of modular headers should require the target to define a module
#
# @note This must return false when a pod has a `header_mappings_dir`,
# as that allows the spec to completely customize the header structure, and
# therefore it might not be expecting the module name to be prepended
# to imports at all.
#
def uses_modular_headers?(only_if_defines_modules = true)
return false if only_if_defines_modules && !defines_module?
spec_consumers.none?(&:header_mappings_dir)
end
private
# @param [TargetDefinition] target_definition
......
Subproject commit 4bb5eeef8cb713fc2e0abe51f79716d0edceb019
Subproject commit b21c05141a790ac307a0ff605d2015e58c173889
......@@ -279,6 +279,11 @@ describe_cli 'pod' do
'install --no-repo-update'
end
describe 'Integrates a Pod with a header mappings directory' do
behaves_like cli_spec 'install_header_mappings_dir',
'install --no-repo-update'
end
describe 'Integrates a Pod using non Objective-C source files' do
behaves_like cli_spec 'install_non_objective_c_files',
'install --no-repo-update'
......
......@@ -126,6 +126,10 @@ module Pod
#-----------------------------------------------------------------------#
describe 'with library' do
before do
config.sandbox.public_headers.stubs(:search_paths).returns(['${PODS_ROOT}/Headers/Public/BananaLib'])
end
def specs
[fixture_spec('banana-lib/BananaLib.podspec')]
end
......@@ -137,12 +141,12 @@ module Pod
end
it 'adds the sandbox public headers search paths to the xcconfig, with quotes, as header search paths' do
expected = "$(inherited) \"#{config.sandbox.public_headers.search_paths(Platform.ios).join('" "')}\""
expected = '$(inherited) "${PODS_ROOT}/Headers/Public/BananaLib"'
@xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == expected
end
it 'adds the sandbox public headers search paths to the xcconfig, with quotes, as system headers' do
expected = "$(inherited) -isystem \"#{config.sandbox.public_headers.search_paths(Platform.ios).join('" -isystem "')}\""
expected = '$(inherited) -isystem "${PODS_ROOT}/Headers/Public/BananaLib"'
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end
......@@ -185,6 +189,10 @@ module Pod
end
describe 'with a vendored-library pod' do
before do
config.sandbox.public_headers.stubs(:search_paths).returns(['${PODS_ROOT}/Headers/Public/monkey'])
end
def specs
[fixture_spec('monkey/monkey.podspec')]
end
......@@ -199,23 +207,26 @@ module Pod
it 'does not include framework header paths as local headers for pods that are linked statically' do
monkey_headers = '-iquote "${PODS_CONFIGURATION_BUILD_DIR}/monkey.framework/Headers"'
@xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_CFLAGS'].should.not.include monkey_headers
end
it 'includes the public header paths as system headers' do
expected = '$(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/OrangeFramework/OrangeFramework.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public"'
expected = '$(inherited) -iquote "${PODS_CONFIGURATION_BUILD_DIR}/OrangeFramework/OrangeFramework.framework/Headers" -isystem "${PODS_ROOT}/Headers/Public/monkey"'
@generator.stubs(:pod_targets).returns([@pod_targets.first, pod_target(fixture_spec('orange-framework/OrangeFramework.podspec'), @target_definition)])
@xcconfig = @generator.generate
@xcconfig.to_hash['OTHER_CFLAGS'].should == expected
end
it 'includes the public header paths as user headers' do
expected = '${PODS_ROOT}/Headers/Public'
expected = '${PODS_ROOT}/Headers/Public/monkey'
@xcconfig = @generator.generate
@xcconfig.to_hash['HEADER_SEARCH_PATHS'].should.include expected
end
it 'includes $(inherited) in the header search paths' do
expected = '$(inherited)'
@xcconfig = @generator.generate
@xcconfig.to_hash['HEADER_SEARCH_PATHS'].should.include expected
end
......
......@@ -11,6 +11,7 @@ module Pod
vspec = stub(:test_specification? => false)
consumer = stub(
"Spec Consumer (#{vspec} iOS)",
:pod_target_xcconfig => {},
:libraries => ['xml2'],
:frameworks => [],
......@@ -18,6 +19,7 @@ module Pod
:platform_name => :ios,
)
file_accessor = stub(
'File Accessor',
:spec => vspec,
:spec_consumer => consumer,
:vendored_static_frameworks => [config.sandbox.root + 'AAA/StaticFramework.framework'],
......@@ -26,6 +28,7 @@ module Pod
:vendored_dynamic_libraries => [config.sandbox.root + 'DDD/VendoredDyld.dyld'],
)
vendored_dep_target = stub(
'Vendored Dependent Target',
:name => 'BananaLib',
:pod_name => 'BananaLib',
:sandbox => config.sandbox,
......@@ -34,6 +37,7 @@ module Pod
:static_framework? => false,
:dependent_targets => [],
:file_accessors => [file_accessor],
:uses_modular_headers? => false,
)
@spec = fixture_spec('banana-lib/BananaLib.podspec')
......@@ -133,11 +137,8 @@ module Pod
@xcconfig.to_hash['PODS_TARGET_SRCROOT'].should == '${PODS_ROOT}/../../spec/fixtures/banana-lib'
end
it 'adds the library build headers and public headers search paths to the xcconfig, with quotes' do
private_headers = "\"#{@pod_target.build_headers.search_paths(Platform.new(:ios)).join('" "')}\""
public_headers = "\"#{config.sandbox.public_headers.search_paths(Platform.new(:ios)).join('" "')}\""
@xcconfig.to_hash['HEADER_SEARCH_PATHS'].should.include private_headers
@xcconfig.to_hash['HEADER_SEARCH_PATHS'].should.include public_headers
it 'does not add root public or private header search paths to the xcconfig' do
@xcconfig.to_hash['HEADER_SEARCH_PATHS'].should.be.empty
end
it 'adds the COCOAPODS macro definition' do
......@@ -269,8 +270,10 @@ module Pod
@coconut_pod_target.dependent_targets = [@banana_pod_target]
generator = PodXCConfig.new(@coconut_pod_target, true)
xcconfig = generator.generate
xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '"${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/CoconutLib"' \
' "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/BananaLib" "${PODS_ROOT}/Headers/Public/CoconutLib" "${PODS_ROOT}/Headers/Public/monkey"'
xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '"${PODS_ROOT}/Headers/Private/CoconutLib"' \
' "${PODS_ROOT}/Headers/Public/BananaLib" "${PODS_ROOT}/Headers/Public/BananaLib/BananaLib"' \
' "${PODS_ROOT}/Headers/Public/CoconutLib" "${PODS_ROOT}/Headers/Public/CoconutLib/CoconutLib"' \
' "${PODS_ROOT}/Headers/Public/monkey" "${PODS_ROOT}/Headers/Public/monkey/monkey"'
end
it 'adds correct header search paths for dependent and test targets for non test xcconfigs' do
......@@ -285,8 +288,9 @@ module Pod
# This is not an test xcconfig so it should exclude header search paths for the 'monkey' pod
generator = PodXCConfig.new(@coconut_pod_target, false)
xcconfig = generator.generate
xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '"${PODS_ROOT}/Headers/Private" "${PODS_ROOT}/Headers/Private/CoconutLib"' \
' "${PODS_ROOT}/Headers/Public" "${PODS_ROOT}/Headers/Public/BananaLib" "${PODS_ROOT}/Headers/Public/CoconutLib"'
xcconfig.to_hash['HEADER_SEARCH_PATHS'].should == '"${PODS_ROOT}/Headers/Private/CoconutLib"' \
' "${PODS_ROOT}/Headers/Public/BananaLib" "${PODS_ROOT}/Headers/Public/BananaLib/BananaLib"' \
' "${PODS_ROOT}/Headers/Public/CoconutLib" "${PODS_ROOT}/Headers/Public/CoconutLib/CoconutLib"'
end
it 'does not include other ld flags for test dependent targets if its not a test xcconfig' do
......
......@@ -84,7 +84,7 @@ module Pod
it 'links the public headers meant for the user' do
@installer.install!
headers_root = config.sandbox.public_headers.root
public_headers = [headers_root + 'BananaLib/Banana.h', headers_root + 'BananaLib/MoreBanana.h']
public_headers = [headers_root + 'BananaLib/BananaLib/Banana.h', headers_root + 'BananaLib/BananaLib/MoreBanana.h']
private_header = headers_root + 'BananaLib/BananaPrivate.h'
framework_header = headers_root + 'BananaLib/Bananalib/Bananalib.h'
framework_subdir_header = headers_root + 'BananaLib/Bananalib/SubDir/SubBananalib.h'
......@@ -106,7 +106,7 @@ module Pod
headers_root = config.sandbox.public_headers.root
banana_headers = [headers_root + 'BananaLib/Banana.h', headers_root + 'BananaLib/MoreBanana.h']
banana_headers.each { |banana_header| banana_header.should.not.exist }
monkey_header = headers_root + 'monkey/monkey.h'
monkey_header = headers_root + 'monkey/monkey/monkey.h'
monkey_header.should.exist
end
......@@ -206,22 +206,32 @@ module Pod
end
describe '#header_mappings' do
it 'returns the header mappings' do
it 'returns the correct public header mappings' do
headers_sandbox = Pathname.new('BananaLib')
headers = [Pathname.new('BananaLib/Banana.h')]
mappings = @installer.send(:header_mappings, headers_sandbox, @file_accessor, headers)
headers = [Pathname.new('Banana.h')]
mappings = @installer.send(:header_mappings, headers_sandbox, @file_accessor, headers, :public)
mappings.should == {
Pathname.new('BananaLib/BananaLib') => [Pathname.new('Banana.h')],
}
end
it 'takes into account the header dir specified in the spec for public headers' do
headers_sandbox = Pathname.new('BananaLib')
headers = [Pathname.new('Banana.h')]
@file_accessor.spec_consumer.stubs(:header_dir).returns('Sub_dir')
mappings = @installer.send(:header_mappings, headers_sandbox, @file_accessor, headers, :public)
mappings.should == {
headers_sandbox => headers,
Pathname.new('BananaLib/BananaLib/Sub_dir') => [Pathname.new('Banana.h')],
}
end
it 'takes into account the header dir specified in the spec' do
it 'takes into account the header dir specified in the spec for private headers' do
headers_sandbox = Pathname.new('BananaLib')
headers = [Pathname.new('BananaLib/Banana.h')]
headers = [Pathname.new('Banana.h')]
@file_accessor.spec_consumer.stubs(:header_dir).returns('Sub_dir')
mappings = @installer.send(:header_mappings, headers_sandbox, @file_accessor, headers)
mappings.should == {
(headers_sandbox + 'Sub_dir') => headers,
Pathname.new('BananaLib/Sub_dir') => [Pathname.new('Banana.h')],
}
end
......
......@@ -4,11 +4,12 @@ module Pod
describe Sandbox::HeadersStore do
before do
@sandbox = Pod::Sandbox.new(temporary_directory + 'Sandbox')
@header_dir = Sandbox::HeadersStore.new(@sandbox, 'Public')
@public_header_dir = Sandbox::HeadersStore.new(@sandbox, 'Public', :public)
@private_header_dir = Sandbox::HeadersStore.new(@sandbox, 'Private', :private)
end
it "returns it's headers root" do
@header_dir.root.should == temporary_directory + 'Sandbox/Headers/Public'
@public_header_dir.root.should == temporary_directory + 'Sandbox/Headers/Public'
end
it 'can add namespaced headers to its header path using symlinks and return the relative path' do
......@@ -21,7 +22,7 @@ module Pod
relative_header_paths.each do |path|
File.open(@sandbox.root + path, 'w') { |file| file.write('hello') }
end
symlink_paths = @header_dir.add_files(namespace_path, relative_header_paths)
symlink_paths = @public_header_dir.add_files(namespace_path, relative_header_paths)
symlink_paths.each do |path|
path.should.be.symlink
File.read(path).should == 'hello'
......@@ -39,35 +40,75 @@ module Pod
File.open(@sandbox.root + path, 'w') { |file| file.write('hello') }
end
fake_platform = mock(:name => 'fake_platform')
@header_dir.add_files(namespace_path, relative_header_paths)
@header_dir.search_paths(fake_platform).should.not.include('${PODS_ROOT}/Headers/Public/ExampleLib')
@public_header_dir.add_files(namespace_path, relative_header_paths)
@public_header_dir.search_paths(fake_platform).should.not.include('${PODS_ROOT}/Headers/Public/ExampleLib')
end
it 'always adds the Headers root to the header search paths' do
fake_platform = mock(:name => 'fake_platform')
@header_dir.search_paths(fake_platform).should.include('${PODS_ROOT}/Headers/Public')
end
describe 'non modular header search paths' do
it 'returns the correct public header search paths for the given platform' do
@public_header_dir.add_search_path('iOS Search Path', Platform.ios)
@public_header_dir.add_search_path('OS X Search Path', Platform.osx)
@public_header_dir.search_paths(Platform.ios).sort.should == [
'${PODS_ROOT}/Headers/Public/iOS Search Path',
'${PODS_ROOT}/Headers/Public/iOS Search Path/iOS Search Path',
]
end
it 'only exposes header search paths for the given platform' do
@header_dir.add_search_path('iOS Search Path', Platform.ios)
@header_dir.add_search_path('OS X Search Path', Platform.osx)
@header_dir.search_paths(Platform.ios).sort.should == [
'${PODS_ROOT}/Headers/Public',
'${PODS_ROOT}/Headers/Public/iOS Search Path',
]
it 'returns the correct public header search paths given platform and target' do
@public_header_dir.add_search_path('ios-target', Platform.ios)
@public_header_dir.add_search_path('osx-target', Platform.osx)
@public_header_dir.search_paths(Platform.ios, 'ios-target').sort.should == [
'${PODS_ROOT}/Headers/Public/ios-target',
'${PODS_ROOT}/Headers/Public/ios-target/ios-target',
]
@public_header_dir.search_paths(Platform.osx, 'osx-target').sort.should == [
'${PODS_ROOT}/Headers/Public/osx-target',
'${PODS_ROOT}/Headers/Public/osx-target/osx-target',
]
end
it 'returns the correct private header search paths given platform and target' do
@private_header_dir.add_search_path('ios-target', Platform.ios)
@private_header_dir.add_search_path('osx-target', Platform.osx)
@private_header_dir.search_paths(Platform.ios, 'ios-target', false).sort.should == [
'${PODS_ROOT}/Headers/Private/ios-target',
]
@private_header_dir.search_paths(Platform.osx, 'osx-target', false).sort.should == [
'${PODS_ROOT}/Headers/Private/osx-target',
]
end
end
it 'returns the correct header search paths given platform and target' do
@header_dir.add_search_path('ios-target', Platform.ios)
@header_dir.add_search_path('osx-target', Platform.osx)
@header_dir.search_paths(Platform.ios, 'ios-target').sort.should == [
'${PODS_ROOT}/Headers/Public',
'${PODS_ROOT}/Headers/Public/ios-target',
]
@header_dir.search_paths(Platform.osx, 'osx-target').sort.should == [
'${PODS_ROOT}/Headers/Public',
'${PODS_ROOT}/Headers/Public/osx-target',
]
describe 'modular header search paths' do
it 'returns the correct public header search paths for the given platform' do
@public_header_dir.add_search_path('iOS Search Path', Platform.ios)
@public_header_dir.add_search_path('OS X Search Path', Platform.osx)
@public_header_dir.search_paths(Platform.ios, nil, true).sort.should == [
'${PODS_ROOT}/Headers/Public/iOS Search Path',
]
end
it 'returns the correct public header search paths given platform and target' do
@public_header_dir.add_search_path('ios-target', Platform.ios)
@public_header_dir.add_search_path('osx-target', Platform.osx)
@public_header_dir.search_paths(Platform.ios, 'ios-target', true).sort.should == [
'${PODS_ROOT}/Headers/Public/ios-target',
]
@public_header_dir.search_paths(Platform.osx, 'osx-target', true).sort.should == [
'${PODS_ROOT}/Headers/Public/osx-target',
]
end
it 'returns the correct private header search paths given platform and target' do
@private_header_dir.add_search_path('ios-target', Platform.ios)
@private_header_dir.add_search_path('osx-target', Platform.osx)
@private_header_dir.search_paths(Platform.ios, 'ios-target', true).sort.should == [
'${PODS_ROOT}/Headers/Private/ios-target',
]
@private_header_dir.search_paths(Platform.osx, 'osx-target', true).sort.should == [
'${PODS_ROOT}/Headers/Private/osx-target',
]
end
end
end
end
......@@ -234,52 +234,113 @@ module Pod
@pod_target.prefix_header_path.to_s.should.include 'Pods/Target Support Files/BananaLib/BananaLib-prefix.pch'
end
it 'returns the correct header search paths' do
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
header_search_paths = @pod_target.header_search_paths
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private',
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public',
'${PODS_ROOT}/Headers/Public/BananaLib',
]
end
it 'returns the correct header search paths recursively for dependent targets' do
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('monkey', Platform.ios)
monkey_spec = fixture_spec('monkey/monkey.podspec')
monkey_pod_target = PodTarget.new([monkey_spec], [@target_definition], config.sandbox)
monkey_pod_target.stubs(:platform).returns(Platform.ios)
@pod_target.stubs(:dependent_targets).returns([monkey_pod_target])
header_search_paths = @pod_target.header_search_paths
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private',
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public',
'${PODS_ROOT}/Headers/Public/BananaLib',
'${PODS_ROOT}/Headers/Public/monkey',
]
end
it 'returns the correct header search paths recursively for dependent targets excluding platform' do
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('monkey', Platform.osx)
monkey_spec = fixture_spec('monkey/monkey.podspec')
monkey_pod_target = PodTarget.new([monkey_spec], [@target_definition], config.sandbox)
monkey_pod_target.stubs(:platform).returns(Platform.ios)
@pod_target.stubs(:dependent_targets).returns([monkey_pod_target])
header_search_paths = @pod_target.header_search_paths
# The monkey lib header search paths should not be present since they are only present in OSX.
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private',
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public',
'${PODS_ROOT}/Headers/Public/BananaLib',
]
describe 'non modular header search paths' do
it 'returns the correct search paths' do
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
header_search_paths = @pod_target.header_search_paths
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib/BananaLib',
]
end
it 'returns the correct header search paths recursively for dependent targets' do
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('monkey', Platform.ios)
monkey_spec = fixture_spec('monkey/monkey.podspec')
monkey_pod_target = PodTarget.new([monkey_spec], [@target_definition], config.sandbox)
monkey_pod_target.stubs(:platform).returns(Platform.ios)
@pod_target.stubs(:dependent_targets).returns([monkey_pod_target])
header_search_paths = @pod_target.header_search_paths
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib/BananaLib',
'${PODS_ROOT}/Headers/Public/monkey',
'${PODS_ROOT}/Headers/Public/monkey/monkey',
]
end
it 'returns the correct header search paths recursively for dependent targets excluding platform' do
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('monkey', Platform.osx)
monkey_spec = fixture_spec('monkey/monkey.podspec')
monkey_pod_target = PodTarget.new([monkey_spec], [@target_definition], config.sandbox)
monkey_pod_target.stubs(:platform).returns(Platform.ios)
@pod_target.stubs(:dependent_targets).returns([monkey_pod_target])
header_search_paths = @pod_target.header_search_paths
# The monkey lib header search paths should not be present since they are only present in OSX.
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib/BananaLib',
]
end
end
describe 'modular header search paths' do
before do
@pod_target.stubs(:defines_module?).returns(true)
end
it 'uses modular header search paths when specified in the podfile' do
@pod_target.unstub(:defines_module?)
@pod_target.target_definitions.first.stubs(:build_pod_as_module?).with('BananaLib').returns(true)
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
header_search_paths = @pod_target.header_search_paths
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib',
]
end
it 'returns the correct header search paths' do
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
header_search_paths = @pod_target.header_search_paths
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib',
]
end
it 'returns the correct header search paths recursively for dependent targets' do
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('monkey', Platform.ios)
monkey_spec = fixture_spec('monkey/monkey.podspec')
monkey_pod_target = PodTarget.new([monkey_spec], [@target_definition], config.sandbox)
monkey_pod_target.stubs(:platform).returns(Platform.ios)
@pod_target.stubs(:dependent_targets).returns([monkey_pod_target])
header_search_paths = @pod_target.header_search_paths
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib',
'${PODS_ROOT}/Headers/Public/monkey',
]
end
it 'returns the correct header search paths recursively for dependent targets excluding platform' do
@pod_target.build_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('BananaLib', Platform.ios)
@pod_target.sandbox.public_headers.add_search_path('monkey', Platform.osx)
monkey_spec = fixture_spec('monkey/monkey.podspec')
monkey_pod_target = PodTarget.new([monkey_spec], [@target_definition], config.sandbox)
monkey_pod_target.stubs(:platform).returns(Platform.ios)
@pod_target.stubs(:dependent_targets).returns([monkey_pod_target])
header_search_paths = @pod_target.header_search_paths
# The monkey lib header search paths should not be present since they are only present in OSX.
header_search_paths.sort.should == [
'${PODS_ROOT}/Headers/Private/BananaLib',
'${PODS_ROOT}/Headers/Public/BananaLib',
]
end
end
end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment