Commit 55a8c912 authored by Fabio Pelosin's avatar Fabio Pelosin

[TargetEnvironmentHeader] Refactor

parent cccca4ff
...@@ -28,12 +28,12 @@ module Pod ...@@ -28,12 +28,12 @@ module Pod
# @return [Hash{String => LocalPod}] the specifications installed for # @return [Hash{String => LocalPod}] the specifications installed for
# the target by build configuration name. # the target by build configuration name.
# #
attr_reader :specs_by_build_configuration attr_reader :specs_by_configuration
# @param [Array<LocalPod>] pods @see pods # @param [Array<Specification>] pods @see pods
# #
def initialize(specs_by_build_configuration) def initialize(specs_by_configuration)
@specs_by_build_configuration = specs_by_build_configuration @specs_by_configuration = specs_by_configuration
end end
# Generates and saves the file. # Generates and saves the file.
...@@ -43,51 +43,129 @@ module Pod ...@@ -43,51 +43,129 @@ module Pod
# #
# @return [void] # @return [void]
# #
def save_as(pathname) def generate
pathname.open('w') do |source| result = "\n#{notice}\n\n"
source.puts common_specs = common_specs(specs_by_configuration)
source.puts "// To check if a library is compiled with CocoaPods you" common_specs.each { |spec| result << spec_defines(spec) }
source.puts "// can use the `COCOAPODS` macro definition which is"
source.puts "// defined in the xcconfigs so it is available in" specs_by_config = specs_scoped_by_configuration(common_specs, specs_by_configuration)
source.puts "// headers also when they are imported in the client" specs_by_config.each do |config, specs|
source.puts "// project." result << "// #{config} build configuration\n"
source.puts result << "#ifdef #{config.gsub(' ', '_').upcase}\n\n"
source.puts specs.each { |spec| result << spec_defines(spec, 1) }
common_specs(specs_by_build_configuration).each do |spec| result << "#endif\n"
spec_name = safe_spec_name(spec.name)
source.puts "// #{spec.name}"
source.puts "#define COCOAPODS_POD_AVAILABLE_#{spec_name}"
if spec.version.semantic?
source.puts "#define COCOAPODS_VERSION_MAJOR_#{spec_name} #{spec.version.major}"
source.puts "#define COCOAPODS_VERSION_MINOR_#{spec_name} #{spec.version.minor}"
source.puts "#define COCOAPODS_VERSION_PATCH_#{spec_name} #{spec.version.patch}"
else
source.puts "// This library does not follow semantic-versioning,"
source.puts "// so we were not able to define version macros."
source.puts "// Please contact the author."
source.puts "// Version: #{spec.version}."
end
source.puts
end
end end
result
end end
#-----------------------------------------------------------------------# def save_as(path)
path.open('w') { |header| header.write(generate) }
end
private private
# !@group Private Helpers # !@group Private Helpers
#-----------------------------------------------------------------------#
# @return [Array<Specification>] The list of the specifications present
# in all build configurations sorted by name.
#
# @param [Hash{String => Array<Specification>}] specs_by_configuration
# The specs grouped by build configuration.
#
def common_specs(specs_by_configuration)
result = specs_by_configuration.values.flatten.uniq
specs_by_configuration.values.each do |configuration_specs|
result = result & configuration_specs
end
result.sort_by(&:name)
end
# @return [Hash{String => Array<Specification>}] The list of the
# specifications not present in all build configurations sorted
# by name and grouped by build configuration name.
#
# @param [Hash{String => Array<Specification>}] specs_by_configuration
# The specs grouped by build configuration.
#
def specs_scoped_by_configuration(common_specs, specs_by_configuration)
result = {}
specs_by_configuration.each do |configuration, all_specs|
specs = all_specs.sort_by(&:name) - common_specs
result[configuration] = specs unless specs.empty?
end
result
end
# @return The sanitized name of a specification to make it suitable to be
# used as part of an identifier of a define statement.
#
# @param [String] spec_name
# The name of the spec.
#
def safe_spec_name(spec_name) def safe_spec_name(spec_name)
spec_name.gsub(/[^\w]/,'_') spec_name.gsub(/[^\w]/,'_')
end end
def common_specs(specs_by_build_configuration) # @return [String]
result = specs_by_build_configuration.values.flatten.uniq #
specs_by_build_configuration.values.each do |build_configuration_specs| def notice
result = result & build_configuration_specs <<-DOC.strip_heredoc
// To check if a library is compiled with CocoaPods you
// can use the `COCOAPODS` macro definition which is
// defined in the xcconfigs so it is available in
// headers also when they are imported in the client
// project.
DOC
end
# @return [String]
#
def spec_defines(spec, indent_count = 0)
spec_name = safe_spec_name(spec.name)
result = "// #{spec.name}\n"
result << "#define COCOAPODS_POD_AVAILABLE_#{spec_name}\n"
if spec.version.semantic?
result << semantic_version_defines(spec)
else
result << non_semantic_version_notice(spec)
end end
result result << "\n"
indent(result, indent_count)
end
def indent(string, indent_count)
indent = ' ' * (indent_count * 2)
lines = string.lines.map { |line|
if line == "\n"
line
else
"#{indent}#{line}"
end
}
lines.join
end
# @return [String]
#
def semantic_version_defines(spec)
spec_name = safe_spec_name(spec.name)
<<-DOC.strip_heredoc
#define COCOAPODS_VERSION_MAJOR_#{spec_name} #{spec.version.major}
#define COCOAPODS_VERSION_MINOR_#{spec_name} #{spec.version.minor}
#define COCOAPODS_VERSION_PATCH_#{spec_name} #{spec.version.patch}
DOC
end
# @return [String]
#
def non_semantic_version_notice(spec)
<<-DOC.strip_heredoc
// This library does not follow semantic-versioning,
// so we were not able to define version macros.
// Please contact the author.
// Version: #{spec.version}.
DOC
end end
#-----------------------------------------------------------------------# #-----------------------------------------------------------------------#
......
...@@ -3,8 +3,8 @@ require File.expand_path('../../../spec_helper', __FILE__) ...@@ -3,8 +3,8 @@ require File.expand_path('../../../spec_helper', __FILE__)
describe Pod::Generator::TargetEnvironmentHeader do describe Pod::Generator::TargetEnvironmentHeader do
before do before do
specification = fixture_spec('banana-lib/BananaLib.podspec') spec = fixture_spec('banana-lib/BananaLib.podspec')
@gen = Pod::Generator::TargetEnvironmentHeader.new({'Debug' => [specification]}) @gen = Pod::Generator::TargetEnvironmentHeader.new({'Debug' => [spec]})
end end
it "generates a header files which include macro definitions for installed Pods" do it "generates a header files which include macro definitions for installed Pods" do
...@@ -32,5 +32,52 @@ describe Pod::Generator::TargetEnvironmentHeader do ...@@ -32,5 +32,52 @@ describe Pod::Generator::TargetEnvironmentHeader do
name = @gen.send(:safe_spec_name, 'AppleCoreAudioUtilityClasses@thehtb') name = @gen.send(:safe_spec_name, 'AppleCoreAudioUtilityClasses@thehtb')
name.should == 'AppleCoreAudioUtilityClasses_thehtb' name.should == 'AppleCoreAudioUtilityClasses_thehtb'
end end
it "includes conditional statements for specifications not present in all build configurations" do
spec = fixture_spec('banana-lib/BananaLib.podspec')
debug_spec = stub(:name => 'DebugPod', :version => Pod::Version.new('1.2.3'))
specs_by_configuration = {
'Debug' => [spec, debug_spec],
'Release' => [spec]
}
@gen = Pod::Generator::TargetEnvironmentHeader.new(specs_by_configuration)
@gen.generate.should == <<-EOS.strip_heredoc
// To check if a library is compiled with CocoaPods you
// can use the `COCOAPODS` macro definition which is
// defined in the xcconfigs so it is available in
// headers also when they are imported in the client
// project.
// BananaLib
#define COCOAPODS_POD_AVAILABLE_BananaLib
#define COCOAPODS_VERSION_MAJOR_BananaLib 1
#define COCOAPODS_VERSION_MINOR_BananaLib 0
#define COCOAPODS_VERSION_PATCH_BananaLib 0
// Debug build configuration
#ifdef DEBUG
// DebugPod
#define COCOAPODS_POD_AVAILABLE_DebugPod
#define COCOAPODS_VERSION_MAJOR_DebugPod 1
#define COCOAPODS_VERSION_MINOR_DebugPod 2
#define COCOAPODS_VERSION_PATCH_DebugPod 3
#endif
EOS
end
it "normalizes the name of the build configuration" do
spec = fixture_spec('banana-lib/BananaLib.podspec')
specs_by_configuration = {
'Debug' => [],
'build configuration copy' => [spec]
}
@gen = Pod::Generator::TargetEnvironmentHeader.new(specs_by_configuration)
@gen.generate.should.include 'BUILD_CONFIGURATION_COPY'
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