Skip to content

Commit

Permalink
Merge pull request #347 from CocoaPods/t-296
Browse files Browse the repository at this point in the history
Support for `header_dir` attr in subspecs.
  • Loading branch information
fabiopelosin committed Jun 25, 2012
2 parents d4bc737 + f4326c7 commit 16a324a
Show file tree
Hide file tree
Showing 10 changed files with 377 additions and 257 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ examples/Pods
examples/**/Pods examples/**/Pods
examples/RelativePathProject/RelativePathProject/RelativePathProject.xcodeproj examples/RelativePathProject/RelativePathProject/RelativePathProject.xcodeproj
spec/fixtures/banana-lib spec/fixtures/banana-lib
spec/fixtures/chameleon
spec/fixtures/integration/Headers/ spec/fixtures/integration/Headers/
/concatenated.* /concatenated.*
spec/fixtures/mercurial-repo/.hg/*cache spec/fixtures/mercurial-repo/.hg/*cache
Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ namespace :gem do
# Update the last version in CocoaPods-version.yml # Update the last version in CocoaPods-version.yml
specs_branch = '0.6' specs_branch = '0.6'


Dir.chdir ('../Specs') do Dir.chdir('../Specs') do
puts Dir.pwd puts Dir.pwd
sh "git checkout #{specs_branch}" sh "git checkout #{specs_branch}"
sh "git pull" sh "git pull"
Expand Down
2 changes: 1 addition & 1 deletion lib/cocoapods/command/spec.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ def process_xcode_build_output(output)
def file_patterns_errors def file_patterns_errors
messages = [] messages = []
messages << "The sources did not match any file" if !@spec.source_files.empty? && @pod.source_files.empty? messages << "The sources did not match any file" if !@spec.source_files.empty? && @pod.source_files.empty?
messages << "The resources did not match any file" if !@spec.resources.empty? && @pod.resources.empty? messages << "The resources did not match any file" if !@spec.resources.empty? && @pod.resource_files.empty?
messages << "The preserve_paths did not match any file" if !@spec.preserve_paths.empty? && @pod.preserve_paths.empty? messages << "The preserve_paths did not match any file" if !@spec.preserve_paths.empty? && @pod.preserve_paths.empty?
messages << "The exclude_header_search_paths did not match any file" if !@spec.exclude_header_search_paths.empty? && @pod.headers_excluded_from_search_paths.empty? messages << "The exclude_header_search_paths did not match any file" if !@spec.exclude_header_search_paths.empty? && @pod.headers_excluded_from_search_paths.empty?
messages messages
Expand Down
2 changes: 1 addition & 1 deletion lib/cocoapods/installer.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def project
pods.each do |pod| pods.each do |pod|
# Add all source files to the project grouped by pod # Add all source files to the project grouped by pod
group = @project.add_pod_group(pod.name) group = @project.add_pod_group(pod.name)
pod.source_files.each do |path| pod.relative_source_files.each do |path|
group.files.new('path' => path.to_s) group.files.new('path' => path.to_s)
end end
end end
Expand Down
4 changes: 2 additions & 2 deletions lib/cocoapods/installer/target_installer.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ def xcconfig
end end


def copy_resources_script_for(pods) def copy_resources_script_for(pods)
@copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.resources }.flatten) @copy_resources_script ||= Generator::CopyResourcesScript.new(pods.map { |p| p.relative_resource_files }.flatten)
end end


def bridge_support_generator_for(pods, sandbox) def bridge_support_generator_for(pods, sandbox)
Generator::BridgeSupport.new(pods.map do |pod| Generator::BridgeSupport.new(pods.map do |pod|
pod.header_files.map { |header| sandbox.root + header } pod.relative_header_files.map { |header| sandbox.root + header }
end.flatten) end.flatten)
end end


Expand Down
187 changes: 114 additions & 73 deletions lib/cocoapods/local_pod.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -13,10 +13,13 @@ module Pod
# safely cleaned by the pod. # safely cleaned by the pod.
# #
# @example # @example
#
# pod = LocalPod.new 'RestKit/Networking' # pod = LocalPod.new 'RestKit/Networking'
# pod.add_specification 'RestKit/UI' # pod.add_specification 'RestKit/UI'
# #
# @note
# Unless otherwise specified in the name of the method the {LocalPod}
# returns absolute paths.
#
class LocalPod class LocalPod


# @return [Specification] The specification that describes the pod. # @return [Specification] The specification that describes the pod.
Expand Down Expand Up @@ -140,6 +143,7 @@ def implode
# #
def clean def clean
clean_paths.each { |path| FileUtils.rm_rf(path) } clean_paths.each { |path| FileUtils.rm_rf(path) }
@cleaned = true
end end


# Finds the absolute paths, including hidden ones, of the files # Finds the absolute paths, including hidden ones, of the files
Expand All @@ -148,7 +152,7 @@ def clean
# @return [Array<Strings>] The paths that can be deleted. # @return [Array<Strings>] The paths that can be deleted.
# #
def clean_paths def clean_paths
cached_used_paths = used_paths.map{ |path| path.to_s } cached_used_paths = used_files
files = Dir.glob(root + "**/*", File::FNM_DOTMATCH) files = Dir.glob(root + "**/*", File::FNM_DOTMATCH)


files.reject! do |candidate| files.reject! do |candidate|
Expand All @@ -159,51 +163,77 @@ def clean_paths
files files
end end


# @return [Array<Pathname>] The relative path of the files used by the pod. # @return [Array<String>] The absolute path of the files used by the pod.
# #
def used_paths def used_files
files = [ source_files(false), files = [ source_files, resource_files, preserve_files, readme_file, license_file, prefix_header_file ]
resources(false),
preserve_paths,
readme_file,
license_file,
prefix_header_file ]
files.compact! files.compact!
files.flatten! files.flatten!
files.map!{ |path| path.to_s }
files files
end end


# @!group Files # @!group Files


# @param (see #source_files_by_spec)
#
# @return [Array<Pathname>] The paths of the source files. # @return [Array<Pathname>] The paths of the source files.
# #
def source_files(relative = true) def source_files
chained_expanded_paths(:source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => relative) source_files_by_spec.values.flatten
end end


# Finds the source files that every activated {Specification} requires. # @return [Array<Pathname>] The *relative* paths of the source files.
# #
# @param [Boolean] relative Whether the paths should be returned relative def relative_source_files
# to the sandbox. source_files.map{ |p| p.relative_path_from(@sandbox.root) }
end

# Finds the source files that every activated {Specification} requires.
# #
# @note If the same file is required by two specifications the one at the # @note If the same file is required by two specifications the one at the
# higher level in the inheritance chain wins. # higher level in the inheritance chain wins.
# #
# @return [Hash{Specification => Array<Pathname>}] The files grouped by
# {Specification}.
#
def source_files_by_spec
options = {:glob => '*.{h,m,mm,c,cpp}'}
paths_by_spec(:source_files, options)
end

# @return [Array<Pathname>] The paths of the header files. # @return [Array<Pathname>] The paths of the header files.
# #
def header_files def header_files
source_files.select { |f| f.extname == '.h' } header_files_by_spec.values.flatten
end

# @return [Array<Pathname>] The *relative* paths of the source files.
#
def relative_header_files
header_files.map{ |p| p.relative_path_from(@sandbox.root) }
end end


# @return [Hash{Specification => Array<Pathname>}] The paths of the header # @return [Hash{Specification => Array<Pathname>}] The paths of the header
# files grouped by {Specification}. # files grouped by {Specification}.
# #
def header_files_by_spec
result = {}
source_files_by_spec.each do |spec, paths|
headers = paths.select { |f| f.extname == '.h' }
result[spec] = headers unless headers.empty?
end
result
end

# @return [Array<Pathname>] The paths of the resources. # @return [Array<Pathname>] The paths of the resources.
# #
def resources(relative = true) def resource_files
chained_expanded_paths(:resources, :relative_to_sandbox => relative) paths_by_spec(:resources).values.flatten
end

# @return [Array<Pathname>] The *relative* paths of the resources.
#
def relative_resource_files
resource_files.map{ |p| p.relative_path_from(@sandbox.root) }
end end


# @return [Pathname] The absolute path of the prefix header file # @return [Pathname] The absolute path of the prefix header file
Expand All @@ -215,11 +245,15 @@ def prefix_header_file
# @return [Array<Pathname>] The absolute paths of the files of the pod # @return [Array<Pathname>] The absolute paths of the files of the pod
# that should be preserved. # that should be preserved.
# #
def preserve_paths def preserve_files
chained_expanded_paths(:preserve_paths) + expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ]) paths = paths_by_spec(:preserve_paths).values
paths += expanded_paths(%w[ *.podspec notice* NOTICE* CREDITS* ])
paths.compact!
paths.uniq!
paths
end end


# @return [Pathname] The automatically detected path of the README # @return [Pathname] The automatically detected absolute path of the README
# file. # file.
# #
def readme_file def readme_file
Expand Down Expand Up @@ -266,17 +300,25 @@ def xcconfig
# @return [Array<Pathname>] The path of all the public headers of the pod. # @return [Array<Pathname>] The path of all the public headers of the pod.
# #
def all_specs_public_header_files def all_specs_public_header_files
#TODO: merge with #221 if @cleaned
specs = top_specification.recursive_subspecs << top_specification raise Informative, "The pod is cleaned and cannot compute the all the "\
specs.map { |s| expanded_paths(s.source_files, :glob => '*.{h}') }.compact.flatten.select { |f| f.extname == '.h' }.uniq "header files as they might be deleted."
end

all_specs = [ top_specification ] + top_specification.subspecs
options = {:glob => '*.{h}'}
files = paths_by_spec(:source_files, options, all_specs).values.flatten!
headers = files.select { |f| f.extname == '.h' }
headers
end end


# @!group Target integration # @!group Target integration


# @return [void] Copies the pods headers to the sandbox. # @return [void] Copies the pods headers to the sandbox.
# #
def link_headers def link_headers
copy_header_mappings.each do |namespaced_path, files| @sandbox.add_header_search_path(headers_sandbox)
header_mappings.each do |namespaced_path, files|
@sandbox.add_header_files(namespaced_path, files) @sandbox.add_header_files(namespaced_path, files)
end end
end end
Expand All @@ -287,8 +329,9 @@ def link_headers
# @return [void] Adds the pods source files to a given target. # @return [void] Adds the pods source files to a given target.
# #
def add_to_target(target) def add_to_target(target)
sources_files_by_specification.each do | spec, files | source_files_by_spec.each do | spec, files |
files.each do |file| files.each do |file|
file = file.relative_path_from(@sandbox.root)
target.add_source_file(file, nil, spec.compiler_flags.strip) target.add_source_file(file, nil, spec.compiler_flags.strip)
end end
end end
Expand All @@ -306,7 +349,7 @@ def requires_arc?
# (the files the need to compiled) of the pod. # (the files the need to compiled) of the pod.
# #
def implementation_files def implementation_files
source_files.select { |f| f.extname != '.h' } relative_source_files.select { |f| f.extname != '.h' }
end end


# @return [Pathname] The path of the pod relative from the sandbox. # @return [Pathname] The path of the pod relative from the sandbox.
Expand All @@ -315,72 +358,74 @@ def relative_root
root.relative_path_from(@sandbox.root) root.relative_path_from(@sandbox.root)
end end


# @return Hash{Pathname => [Array<Pathname>]} A hash containing the headers
# folders as the keys and the the absolute paths of the header files
# as the values.
#
# @todo this is being overridden in the RestKit 0.9.4 spec, need to do # @todo this is being overridden in the RestKit 0.9.4 spec, need to do
# something with that, and this method also still exists in Specification. # something with that, and this method also still exists in Specification.
# #
# @todo This is not overridden anymore in specification refactor and the # @todo This is not overridden anymore in specification refactor and the
# code Pod::Specification#copy_header_mapping can be moved here. # code Pod::Specification#copy_header_mapping can be moved here.
def copy_header_mappings def header_mappings
search_path_headers = header_files - headers_excluded_from_search_paths mappings = {}
search_path_headers.inject({}) do |mappings, from| header_files_by_spec.each do |spec, paths|
from_without_prefix = from.relative_path_from(relative_root) paths = paths - headers_excluded_from_search_paths
to = top_specification.header_dir + top_specification.copy_header_mapping(from_without_prefix) paths.each do |from|
(mappings[to.dirname] ||= []) << from from_relative = from.relative_path_from(root)
mappings to = headers_sandbox + (spec.header_dir) + spec.copy_header_mapping(from_relative)
(mappings[to.dirname] ||= []) << from
end
end end
mappings
end end


# Finds the source files that every activate {Specification} requires. def headers_sandbox
# @headers_sandbox ||= Pathname.new(top_specification.name)
# @note The paths of the files are relative to the sandbox.
# @note If the same file is required by two specifications the one at the higher level in the inheritance chain wins.
#
# @return [Hash{Specification => Array<Pathname>}] The files grouped by {Specification}.
#
def sources_files_by_specification
files_by_spec = {}
processed_files = []
specifications.sort_by { |s| s.name.length }.each do |spec|
files = []
expanded_paths(spec.source_files, :glob => '*.{h,m,mm,c,cpp}', :relative_to_sandbox => true).each do | file |
files << file unless processed_files.include?(file)
end
files_by_spec[spec] = files
processed_files += files
end
files_by_spec
end end


# @todo merge with #221 # @return [<Pathname>] The relative path of the headers that should not be
# included in the linker search paths.
# #
def headers_excluded_from_search_paths def headers_excluded_from_search_paths
chained_expanded_paths(:exclude_header_search_paths, :glob => '*.h', :relative_to_sandbox => true) options = { :glob => '*.h' }
paths = paths_by_spec(:exclude_header_search_paths, options)
paths.values.compact.uniq
end end


# @!group Paths Patterns # @!group Paths Patterns


# Finds all the paths patterns of a each activated specifications and # The paths obtained by resolving the patterns of an attribute
# converts them to the actual paths present in the pod. # groupped by spec.
# #
# @return [Array<Pathname>] A list of the paths. # @param [Symbol] accessor The accessor to use to obtain the paths patterns.
# @param [Hash] options (see #expanded_paths)
# #
def chained_expanded_paths(accessor, options = {}) def paths_by_spec(accessor, options = {}, specs = nil)
specifications.map { |s| expanded_paths(s.send(accessor), options) }.compact.flatten.uniq specs ||= specifications
paths_by_spec = {}
processed_paths = []

specs = specs.sort_by { |s| s.name.length }
specs.each do |spec|
paths = expanded_paths(spec.send(accessor), options)
unless paths.empty?
paths_by_spec[spec] = paths - processed_paths
processed_paths += paths
end
end
paths_by_spec
end end


# The paths obtained by interpolating the patterns of a given attribute # Converts patterns of paths to the {Pathname} of the files present in the
# collected by spec. # pod.
#
# @todo implement case insensitive search
# #
# @param [String, FileList, Array<String, Pathname>] patterns # @param [String, FileList, Array<String, Pathname>] patterns
# The patterns to expand. # The patterns to expand.
# @param [Hash] options # @param [Hash] options
# The options to used for expanding the paths patterns. # The options to used for expanding the paths patterns.
# @option options [String] :glob # @option options [String] :glob
# The pattern to use for globing directories. # The pattern to use for globing directories.
# @option options [Boolean] :relative_to_sandbox
# Whether the paths should be returned relative to the sandbox.
# #
# @raise [Informative] If the pod does not exists. # @raise [Informative] If the pod does not exists.
# #
Expand All @@ -405,11 +450,7 @@ def expanded_paths(patterns, options = {})
end end


pattern.glob.map do |file| pattern.glob.map do |file|
if options[:relative_to_sandbox] file
file.relative_path_from(@sandbox.root)
else
file
end
end end
end.flatten end.flatten
end end
Expand Down
10 changes: 10 additions & 0 deletions lib/cocoapods/sandbox.rb
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ def header_search_paths
@header_search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" } @header_search_paths.uniq.map { |path| "${PODS_ROOT}/#{path}" }
end 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? headers_root.rmtree if headers_root.exist?
end end
Expand Down
Loading

0 comments on commit 16a324a

Please sign in to comment.