Skip to content

Commit

Permalink
Merge https://github.com/groue/CocoaPods into public_headers
Browse files Browse the repository at this point in the history
* https://github.com/groue/CocoaPods:
  [CocoaPods#221] robustness against nil file lists (such as public_header_files)
  [CocoaPods#221] code cleanup
  [CocoaPods#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.
  [CocoaPods#221] Pod::Sandbox#build_header_storage and Pod::Sandbox#public_header_storage
  [CocoaPods#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
  • Loading branch information
fabiopelosin committed Aug 6, 2012
2 parents 2471137 + be27569 commit d44e0fe
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 46 deletions.
14 changes: 13 additions & 1 deletion lib/cocoapods/command/spec.rb
Expand Up @@ -321,10 +321,11 @@ def source_valid?

def paths_starting_with_a_slash_errors
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)
# Some values are multiplaform
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|
# Skip FileList that would otherwise be resolved from the working directory resulting
# in a potentially very expensi operation
Expand Down Expand Up @@ -563,6 +564,17 @@ def spec_template(data)
#
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
# target bundle with a build phase script.
#
Expand Down
2 changes: 1 addition & 1 deletion lib/cocoapods/file_list.rb
Expand Up @@ -5,7 +5,7 @@
end

# 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
class FileList
Expand Down
7 changes: 5 additions & 2 deletions lib/cocoapods/installer/target_installer.rb
Expand Up @@ -73,21 +73,24 @@ def install!(pods, sandbox)
@target.add_source_files(source_file_descriptions)

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.create_files(target_support_files)

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)
end

def configure_build_configurations(xcconfig_file)
def configure_build_configurations(xcconfig_file, sandbox)
@target.build_configurations.each do |config|
config.base_configuration = xcconfig_file
config.build_settings['OTHER_LDFLAGS'] = ''
config.build_settings['GCC_PREFIX_HEADER'] = @target_definition.prefix_header_name
config.build_settings['PODS_ROOT'] = '${SRCROOT}'
config.build_settings['PODS_HEADER_SEARCH_PATHS'] = quoted(sandbox.build_headers.search_paths).join(" ")
end
end

Expand Down
31 changes: 30 additions & 1 deletion lib/cocoapods/local_pod.rb
Expand Up @@ -229,6 +229,16 @@ def header_files_by_spec
result
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.
#
def resource_files
Expand Down Expand Up @@ -323,8 +333,13 @@ def all_specs_public_header_files
#
def link_headers
@sandbox.add_header_search_path(headers_sandbox)

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

Expand Down Expand Up @@ -389,6 +404,20 @@ def header_mappings
mappings
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
@headers_sandbox ||= Pathname.new(top_specification.name)
end
Expand Down
86 changes: 51 additions & 35 deletions lib/cocoapods/sandbox.rb
Expand Up @@ -3,58 +3,31 @@
module Pod
class Sandbox
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)
@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 = {}

FileUtils.mkdir_p(@root)
end

def implode
root.rmtree
end

def headers_root
root + HEADERS_DIR
end

def project_path
root + "Pods.xcodeproj"
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
headers_root.rmtree if headers_root.exist?
build_headers.prepare_for_install
public_headers.prepare_for_install
end

def local_pod_for_spec(spec, platform)
Expand All @@ -79,4 +52,47 @@ def podspec_for_name(name)
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
2 changes: 2 additions & 0 deletions lib/cocoapods/specification.rb
Expand Up @@ -121,6 +121,7 @@ def initialize(specification, platform)
end

%w{ source_files=
public_header_files=
resource=
resources=
preserve_paths=
Expand Down Expand Up @@ -239,6 +240,7 @@ def available_platforms


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 :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)
Expand Down
1 change: 1 addition & 0 deletions spec/functional/command/spec_spec.rb
Expand Up @@ -34,6 +34,7 @@
spec.source.should == { :git => 'http://EXAMPLE/Bananas.git', :tag => '0.0.1' }
spec.description.should == 'A short description of Bananas.'
spec.source_files.should == ['Classes', 'Classes/**/*.{h,m}']
spec.public_header_files[:ios].should == []
end

it "correctly creates a podspec from github" do
Expand Down
2 changes: 1 addition & 1 deletion spec/unit/installer/target_installer_spec.rb
Expand Up @@ -51,7 +51,7 @@ def do_install!

it 'adds the sandbox header search paths to the xcconfig, with quotes' do
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

it 'does not add the -fobjc-arc to OTHER_LDFLAGS by default as Xcode 4.3.2 does not support it' do
Expand Down
33 changes: 33 additions & 0 deletions spec/unit/local_pod_spec.rb
Expand Up @@ -10,6 +10,28 @@
@pod = Pod::LocalPod.new(@spec, @sandbox, Pod::Platform.new(:ios))
copy_fixture_to_pod('banana-lib', @pod)
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
@pod.root.should == @sandbox.root + 'BananaLib'
Expand Down Expand Up @@ -94,10 +116,21 @@
@pod.platform.should == :ios
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
@pod.implode
lambda { @pod.source_files }.should.raise Pod::Informative
end

@spec.build_headers.search_paths.should == %w{
"$(PODS_ROOT)/Headers/AnotherRoot"
"$(PODS_ROOT)/Headers/AnotherRoot/ns"
}
end

describe "with installed source and multiple subspecs" do
Expand Down
10 changes: 5 additions & 5 deletions spec/unit/sandbox_spec.rb
Expand Up @@ -24,15 +24,15 @@
end

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

it "can add namespaced headers to it's header path using symlinks and return the relative path" do
FileUtils.mkdir_p(@sandbox.root + "ExampleLib/Headers")
namespace_path = Pathname.new("ExampleLib")
relative_header_path = Pathname.new("ExampleLib/Headers/MyHeader.h")
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
File.read(symlink_path).should == 'hello'
end
Expand All @@ -47,7 +47,7 @@
relative_header_paths.each do |path|
File.open(@sandbox.root + path, "w") { |file| file.write('hello') }
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|
path.should.be.symlink
File.read(path).should == "hello"
Expand All @@ -64,7 +64,7 @@
relative_header_paths.each do |path|
File.open(@sandbox.root + path, "w") { |file| file.write('hello') }
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")
end

Expand All @@ -74,7 +74,7 @@

it 'clears out its headers root when preparing for install' do
@sandbox.prepare_for_install
@sandbox.headers_root.should.not.exist
@sandbox.build_headers.root.should.not.exist
end

it "returns the path to a spec file in the root of the pod's dir" do
Expand Down

0 comments on commit d44e0fe

Please sign in to comment.