Commit d44e0feb authored by Fabio Pelosin's avatar Fabio Pelosin

Merge https://github.com/groue/CocoaPods into public_headers

* https://github.com/groue/CocoaPods:
  [#221] robustness against nil file lists (such as public_header_files)
  [#221] code cleanup
  [#221] HEADER_SEARCH_PATHS value comes from the new variable PODS_HEADER_SEARCH_PATHS. PODS_HEADER_SEARCH_PATHS is set to public headers search paths in Pods.xcconfig, and to build headers search paths in Pods.xcodeproj.
  [#221] Pod::Sandbox#build_header_storage and Pod::Sandbox#public_header_storage
  [#221] Pod::Spec#public_header_files accepted and validated by `pod spec lint`

Conflicts:
	lib/cocoapods/command/spec.rb
	lib/cocoapods/installer/target_installer.rb
	lib/cocoapods/local_pod.rb
	lib/cocoapods/sandbox.rb
	lib/cocoapods/specification.rb
	spec/functional/command/spec_spec.rb
	spec/unit/local_pod_spec.rb
parents 24711376 be275692
...@@ -321,10 +321,11 @@ module Pod ...@@ -321,10 +321,11 @@ module Pod
def paths_starting_with_a_slash_errors def paths_starting_with_a_slash_errors
messages = [] messages = []
%w[source_files resources clean_paths].each do |accessor| %w[source_files public_header_files resources clean_paths].each do |accessor|
patterns = spec.send(accessor.to_sym) patterns = spec.send(accessor.to_sym)
# Some values are multiplaform # Some values are multiplaform
patterns = patterns.is_a?(Hash) ? patterns.values.flatten(1) : patterns patterns = patterns.is_a?(Hash) ? patterns.values.flatten(1) : patterns
patterns = patterns.compact # some patterns may be nil (public_header_files, for instance)
patterns.each do |pattern| patterns.each do |pattern|
# Skip FileList that would otherwise be resolved from the working directory resulting # Skip FileList that would otherwise be resolved from the working directory resulting
# in a potentially very expensi operation # in a potentially very expensi operation
...@@ -563,6 +564,17 @@ Pod::Spec.new do |s| ...@@ -563,6 +564,17 @@ Pod::Spec.new do |s|
# #
s.source_files = 'Classes', 'Classes/**/*.{h,m}' s.source_files = 'Classes', 'Classes/**/*.{h,m}'
# A list of file patterns which select the header files that should be
# made available to the application. If the pattern is a directory then the
# path will automatically have '*.h' appended.
#
# Also allows the use of the FileList class like `source_files does.
#
# If you do not explicitely set the list of public header files,
# all headers of source_files will be made public.
#
# s.public_header_files = 'Classes/**/*.h'
# A list of resources included with the Pod. These are copied into the # A list of resources included with the Pod. These are copied into the
# target bundle with a build phase script. # target bundle with a build phase script.
# #
......
...@@ -5,7 +5,7 @@ else ...@@ -5,7 +5,7 @@ else
end end
# This makes Rake::FileList usable with the Specification attributes # This makes Rake::FileList usable with the Specification attributes
# source_files, clean_paths, and resources. # source_files, public_header_files, clean_paths, and resources.
module Rake module Rake
class FileList class FileList
......
...@@ -73,21 +73,24 @@ module Pod ...@@ -73,21 +73,24 @@ module Pod
@target.add_source_files(source_file_descriptions) @target.add_source_files(source_file_descriptions)
xcconfig.merge!('HEADER_SEARCH_PATHS' => quoted(sandbox.header_search_paths).join(" ")) xcconfig.merge!('HEADER_SEARCH_PATHS' => quoted(sandbox.header_search_paths).join(" "))
# Indirect HEADER_SEARCH_PATHS, so that configure_build_configurations can override it
xcconfig.merge!('PODS_HEADER_SEARCH_PATHS' => quoted(sandbox.public_headers.search_paths).join(" "))
support_files_group = @project.group("Targets Support Files").create_group(@target_definition.label) support_files_group = @project.group("Targets Support Files").create_group(@target_definition.label)
support_files_group.create_files(target_support_files) support_files_group.create_files(target_support_files)
xcconfig_file = support_files_group.files.where(:path => @target_definition.xcconfig_name) xcconfig_file = support_files_group.files.where(:path => @target_definition.xcconfig_name)
configure_build_configurations(xcconfig_file) configure_build_configurations(xcconfig_file, sandbox)
create_files(pods, sandbox) create_files(pods, sandbox)
end end
def configure_build_configurations(xcconfig_file) def configure_build_configurations(xcconfig_file, sandbox)
@target.build_configurations.each do |config| @target.build_configurations.each do |config|
config.base_configuration = xcconfig_file config.base_configuration = xcconfig_file
config.build_settings['OTHER_LDFLAGS'] = '' config.build_settings['OTHER_LDFLAGS'] = ''
config.build_settings['GCC_PREFIX_HEADER'] = @target_definition.prefix_header_name config.build_settings['GCC_PREFIX_HEADER'] = @target_definition.prefix_header_name
config.build_settings['PODS_ROOT'] = '${SRCROOT}' config.build_settings['PODS_ROOT'] = '${SRCROOT}'
config.build_settings['PODS_HEADER_SEARCH_PATHS'] = quoted(sandbox.build_headers.search_paths).join(" ")
end end
end end
......
...@@ -229,6 +229,16 @@ module Pod ...@@ -229,6 +229,16 @@ module Pod
result result
end end
# TODO: complete, fix and comment
def public_header_files_by_specs
if specification.public_header_files.empty?
header_files_by_spec
else
options = {:glob => '*.h'}
paths_by_spec(:source_files, options)
end
end
# @return [Array<Pathname>] The paths of the resources. # @return [Array<Pathname>] The paths of the resources.
# #
def resource_files def resource_files
...@@ -323,8 +333,13 @@ module Pod ...@@ -323,8 +333,13 @@ module Pod
# #
def link_headers def link_headers
@sandbox.add_header_search_path(headers_sandbox) @sandbox.add_header_search_path(headers_sandbox)
header_mappings.each do |namespaced_path, files| header_mappings.each do |namespaced_path, files|
@sandbox.add_header_files(namespaced_path, files) @sandbox.build_header_storage.add_files(namespaced_path, files)
end
public_header_mappings.each do |namespaced_path, files|
@sandbox.public_header_storage.add_files(namespaced_path, files)
end end
end end
...@@ -389,6 +404,20 @@ module Pod ...@@ -389,6 +404,20 @@ module Pod
mappings mappings
end end
# TODO: complete, fix and comment
def public_header_mappings
mappings = {}
public_header_files_by_specs.each do |spec, paths|
paths = paths - headers_excluded_from_search_paths
paths.each do |from|
from_relative = from.relative_path_from(root)
to = headers_sandbox + (spec.header_dir) + spec.copy_header_mapping(from_relative)
(mappings[to.dirname] ||= []) << from
end
end
mappings
end
def headers_sandbox def headers_sandbox
@headers_sandbox ||= Pathname.new(top_specification.name) @headers_sandbox ||= Pathname.new(top_specification.name)
end end
......
...@@ -3,14 +3,17 @@ require 'fileutils' ...@@ -3,14 +3,17 @@ require 'fileutils'
module Pod module Pod
class Sandbox class Sandbox
attr_reader :root attr_reader :root
attr_reader :build_headers
attr_reader :public_headers
HEADERS_DIR = "Headers" BUILD_HEADERS_DIR = "BuildHeaders"
PUBLIC_HEADERS_DIR = "Headers"
def initialize(path) def initialize(path)
@root = Pathname.new(path) @root = Pathname.new(path)
@header_search_paths = [HEADERS_DIR] @build_headers = HeadersDirectory.new(self, BUILD_HEADERS_DIR)
@public_headers = HeadersDirectory.new(self, PUBLIC_HEADERS_DIR)
@cached_local_pods = {} @cached_local_pods = {}
FileUtils.mkdir_p(@root) FileUtils.mkdir_p(@root)
end end
...@@ -18,43 +21,13 @@ module Pod ...@@ -18,43 +21,13 @@ module Pod
root.rmtree root.rmtree
end end
def headers_root
root + HEADERS_DIR
end
def project_path def project_path
root + "Pods.xcodeproj" root + "Pods.xcodeproj"
end end
def add_header_file(namespace_path, relative_header_path)
namespaced_header_path = headers_root + namespace_path
namespaced_header_path.mkpath unless File.exist?(namespaced_header_path)
source = (root + relative_header_path).relative_path_from(namespaced_header_path)
Dir.chdir(namespaced_header_path) { FileUtils.ln_sf(source, relative_header_path.basename)}
@header_search_paths << namespaced_header_path.relative_path_from(root)
namespaced_header_path + relative_header_path.basename
end
def add_header_files(namespace_path, relative_header_paths)
relative_header_paths.map { |path| add_header_file(namespace_path, path) }
end
def header_search_paths
@header_search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
end
# Adds an header search path to the sandbox.
#
# @param path [Pathname] The path tho add.
#
# @return [void]
#
def add_header_search_path(path)
@header_search_paths << Pathname.new(HEADERS_DIR) + path
end
def prepare_for_install def prepare_for_install
headers_root.rmtree if headers_root.exist? build_headers.prepare_for_install
public_headers.prepare_for_install
end end
def local_pod_for_spec(spec, platform) def local_pod_for_spec(spec, platform)
...@@ -79,4 +52,47 @@ module Pod ...@@ -79,4 +52,47 @@ module Pod
end end
end end
end end
class HeadersDirectory
def initialize(sandbox, base_dir)
@sandbox = sandbox
@base_dir = base_dir
@search_paths = [base_dir]
end
def root
@sandbox.root + @base_dir
end
def add_file(namespace_path, relative_header_path)
namespaced_header_path = root + namespace_path
namespaced_header_path.mkpath unless File.exist?(namespaced_header_path)
source = (@sandbox.root + relative_header_path).relative_path_from(namespaced_header_path)
Dir.chdir(namespaced_header_path) { FileUtils.ln_sf(source, relative_header_path.basename)}
@search_paths << namespaced_header_path.relative_path_from(@sandbox.root)
namespaced_header_path + relative_header_path.basename
end
def add_files(namespace_path, relative_header_paths)
relative_header_paths.map { |path| add_file(namespace_path, path) }
end
def search_paths
@search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
end
# Adds an header search path to the sandbox.
#
# @param path [Pathname] The path tho add.
#
# @return [void]
#
def add_header_search_path(path)
@header_search_paths << Pathname.new(HEADERS_DIR) + path
end
def prepare_for_install
root.rmtree if root.exist?
end
end
end end
...@@ -121,6 +121,7 @@ module Pod ...@@ -121,6 +121,7 @@ module Pod
end end
%w{ source_files= %w{ source_files=
public_header_files=
resource= resource=
resources= resources=
preserve_paths= preserve_paths=
...@@ -239,6 +240,7 @@ module Pod ...@@ -239,6 +240,7 @@ module Pod
pltf_chained_attr_accessor :source_files, lambda {|value, current| pattern_list(value) } pltf_chained_attr_accessor :source_files, lambda {|value, current| pattern_list(value) }
pltf_chained_attr_accessor :public_header_files, lambda {|value, current| pattern_list(value) }
pltf_chained_attr_accessor :resources, lambda {|value, current| pattern_list(value) } pltf_chained_attr_accessor :resources, lambda {|value, current| pattern_list(value) }
pltf_chained_attr_accessor :preserve_paths, lambda {|value, current| pattern_list(value) } # Paths that should not be cleaned pltf_chained_attr_accessor :preserve_paths, lambda {|value, current| pattern_list(value) } # Paths that should not be cleaned
pltf_chained_attr_accessor :exclude_header_search_paths, lambda {|value, current| pattern_list(value) } # Headers to be excluded from being added to search paths (RestKit) pltf_chained_attr_accessor :exclude_header_search_paths, lambda {|value, current| pattern_list(value) } # Headers to be excluded from being added to search paths (RestKit)
......
...@@ -34,6 +34,7 @@ describe "Pod::Command::Spec#create" do ...@@ -34,6 +34,7 @@ describe "Pod::Command::Spec#create" do
spec.source.should == { :git => 'http://EXAMPLE/Bananas.git', :tag => '0.0.1' } spec.source.should == { :git => 'http://EXAMPLE/Bananas.git', :tag => '0.0.1' }
spec.description.should == 'A short description of Bananas.' spec.description.should == 'A short description of Bananas.'
spec.source_files.should == ['Classes', 'Classes/**/*.{h,m}'] spec.source_files.should == ['Classes', 'Classes/**/*.{h,m}']
spec.public_header_files[:ios].should == []
end end
it "correctly creates a podspec from github" do it "correctly creates a podspec from github" do
......
...@@ -51,7 +51,7 @@ describe Pod::Installer::TargetInstaller do ...@@ -51,7 +51,7 @@ describe Pod::Installer::TargetInstaller do
it 'adds the sandbox header search paths to the xcconfig, with quotes' do it 'adds the sandbox header search paths to the xcconfig, with quotes' do
do_install! do_install!
@installer.xcconfig.to_hash['HEADER_SEARCH_PATHS'].should.include("\"#{@sandbox.header_search_paths.join('" "')}\"") @installer.xcconfig.to_hash['HEADER_SEARCH_PATHS'].should.include("\"#{@sandbox.build_headers.search_paths.join('" "')}\"")
end end
it 'does not add the -fobjc-arc to OTHER_LDFLAGS by default as Xcode 4.3.2 does not support it' do it 'does not add the -fobjc-arc to OTHER_LDFLAGS by default as Xcode 4.3.2 does not support it' do
......
...@@ -10,6 +10,28 @@ describe Pod::LocalPod do ...@@ -10,6 +10,28 @@ describe Pod::LocalPod do
@pod = Pod::LocalPod.new(@spec, @sandbox, Pod::Platform.new(:ios)) @pod = Pod::LocalPod.new(@spec, @sandbox, Pod::Platform.new(:ios))
copy_fixture_to_pod('banana-lib', @pod) copy_fixture_to_pod('banana-lib', @pod)
end end
end
it "can link it's headers into the sandbox" do
@pod.link_headers
expected_header_path = @sandbox.build_headers.root + "BananaLib/Banana.h"
expected_header_path.should.be.symlink
File.read(expected_header_path).should == (@sandbox.root + @pod.header_files[0]).read
end
it "can add it's source files to an Xcode project target" do
target = mock('target')
target.expects(:add_source_file).with(Pathname.new("BananaLib/Classes/Banana.m"), anything, anything)
@pod.add_to_target(target)
end
it "can add it's source files to a target with any specially configured compiler flags" do
@pod.specification.compiler_flags = '-d some_flag'
target = mock('target')
target.expects(:add_source_file).with(anything, anything, "-d some_flag")
@pod.add_to_target(target)
end
end
it 'returns the Pod root directory path' do it 'returns the Pod root directory path' do
@pod.root.should == @sandbox.root + 'BananaLib' @pod.root.should == @sandbox.root + 'BananaLib'
...@@ -94,10 +116,21 @@ describe Pod::LocalPod do ...@@ -94,10 +116,21 @@ describe Pod::LocalPod do
@pod.platform.should == :ios @pod.platform.should == :ios
end end
@spec.build_headers.search_paths.should == %w{
"$(PODS_ROOT)/Headers/SSZipArchive"
"$(PODS_ROOT)/Headers/SSZipArchive/ns"
}
end
it "raises if the files are accessed before creating the pod dir" do it "raises if the files are accessed before creating the pod dir" do
@pod.implode @pod.implode
lambda { @pod.source_files }.should.raise Pod::Informative lambda { @pod.source_files }.should.raise Pod::Informative
end end
@spec.build_headers.search_paths.should == %w{
"$(PODS_ROOT)/Headers/AnotherRoot"
"$(PODS_ROOT)/Headers/AnotherRoot/ns"
}
end end
describe "with installed source and multiple subspecs" do describe "with installed source and multiple subspecs" do
......
...@@ -24,7 +24,7 @@ describe Pod::Sandbox do ...@@ -24,7 +24,7 @@ describe Pod::Sandbox do
end end
it "returns it's headers root" do it "returns it's headers root" do
@sandbox.headers_root.should == Pathname.new(File.join(TMP_POD_ROOT, "Headers")) @sandbox.build_headers.root.should == Pathname.new(File.join(TMP_POD_ROOT, "Headers"))
end end
it "can add namespaced headers to it's header path using symlinks and return the relative path" do it "can add namespaced headers to it's header path using symlinks and return the relative path" do
...@@ -32,7 +32,7 @@ describe Pod::Sandbox do ...@@ -32,7 +32,7 @@ describe Pod::Sandbox do
namespace_path = Pathname.new("ExampleLib") namespace_path = Pathname.new("ExampleLib")
relative_header_path = Pathname.new("ExampleLib/Headers/MyHeader.h") relative_header_path = Pathname.new("ExampleLib/Headers/MyHeader.h")
File.open(@sandbox.root + relative_header_path, "w") { |file| file.write('hello') } File.open(@sandbox.root + relative_header_path, "w") { |file| file.write('hello') }
symlink_path = @sandbox.add_header_file(namespace_path, relative_header_path) symlink_path = @sandbox.build_headers.add_file(namespace_path, relative_header_path)
symlink_path.should.be.symlink symlink_path.should.be.symlink
File.read(symlink_path).should == 'hello' File.read(symlink_path).should == 'hello'
end end
...@@ -47,7 +47,7 @@ describe Pod::Sandbox do ...@@ -47,7 +47,7 @@ describe Pod::Sandbox do
relative_header_paths.each do |path| relative_header_paths.each do |path|
File.open(@sandbox.root + path, "w") { |file| file.write('hello') } File.open(@sandbox.root + path, "w") { |file| file.write('hello') }
end end
symlink_paths = @sandbox.add_header_files(namespace_path, relative_header_paths) symlink_paths = @sandbox.build_headers.add_files(namespace_path, relative_header_paths)
symlink_paths.each do |path| symlink_paths.each do |path|
path.should.be.symlink path.should.be.symlink
File.read(path).should == "hello" File.read(path).should == "hello"
...@@ -64,7 +64,7 @@ describe Pod::Sandbox do ...@@ -64,7 +64,7 @@ describe Pod::Sandbox do
relative_header_paths.each do |path| relative_header_paths.each do |path|
File.open(@sandbox.root + path, "w") { |file| file.write('hello') } File.open(@sandbox.root + path, "w") { |file| file.write('hello') }
end end
@sandbox.add_header_files(namespace_path, relative_header_paths) @sandbox.build_headers.add_files(namespace_path, relative_header_paths)
@sandbox.header_search_paths.should.include("${PODS_ROOT}/Headers/ExampleLib") @sandbox.header_search_paths.should.include("${PODS_ROOT}/Headers/ExampleLib")
end end
...@@ -74,7 +74,7 @@ describe Pod::Sandbox do ...@@ -74,7 +74,7 @@ describe Pod::Sandbox do
it 'clears out its headers root when preparing for install' do it 'clears out its headers root when preparing for install' do
@sandbox.prepare_for_install @sandbox.prepare_for_install
@sandbox.headers_root.should.not.exist @sandbox.build_headers.root.should.not.exist
end end
it "returns the path to a spec file in the root of the pod's dir" do it "returns the path to a spec file in the root of the pod's dir" 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