Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Switch to xcodeproj gem

  • Loading branch information...
commit be78f0dce888edf6b065ce48d74211a09133622a 1 parent 87e1a0b
@nolanw nolanw authored
View
3  cocoapods.gemspec
@@ -31,8 +31,7 @@ Gem::Specification.new do |s|
" $ sudo macgem install rubygems-compile\n" \
" $ sudo macgem compile cocoapods\n\n"
- s.add_runtime_dependency 'activesupport', '~> 3.1.1'
- s.add_runtime_dependency 'i18n', '~> 0.6.0' # only needed for ActiveSupport :-/
+ s.add_runtime_dependency 'xcodeproj', '~> 0.0.1'
## Make sure you can build the gem on older versions of RubyGems too:
s.rubygems_version = "1.6.2"
View
32 lib/cocoapods.rb
@@ -1,3 +1,6 @@
+require 'rubygems'
+require 'xcodeproj'
+
module Pod
VERSION = '0.2.0'
@@ -19,13 +22,6 @@ class Informative < StandardError
autoload :Specification, 'cocoapods/specification'
autoload :Version, 'cocoapods/version'
- module Xcode
- autoload :Config, 'cocoapods/xcode/config'
- autoload :CopyResourcesScript, 'cocoapods/xcode/copy_resources_script'
- autoload :Project, 'cocoapods/xcode/project'
- autoload :Workspace, 'cocoapods/xcode/workspace'
- end
-
autoload :Pathname, 'pathname'
end
@@ -35,3 +31,25 @@ def glob(pattern = '')
end
end
+# Sorry to dump these here...
+
+class Xcode::Project
+ # Shortcut access to the `Pods' PBXGroup.
+ def pods
+ groups.find { |g| g.name == 'Pods' } || groups.new({ 'name' => 'Pods' })
+ end
+
+ # Adds a group as child to the `Pods' group.
+ def add_pod_group(name)
+ pods.groups.new('name' => name)
+ end
+
+ class PBXCopyFilesBuildPhase
+ def self.new_pod_dir(project, pod_name, path)
+ new(project, nil, {
+ "dstPath" => "$(PUBLIC_HEADERS_FOLDER_PATH)/#{path}",
+ "name" => "Copy #{pod_name} Public Headers",
+ })
+ end
+ end
+end
View
32 lib/cocoapods/installer.rb
@@ -14,6 +14,36 @@ def build_specifications
end
end
+ class CopyResourcesScript
+ CONTENT = <<EOS
+#!/bin/sh
+
+install_resource()
+{
+ echo "cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
+ cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}
+}
+EOS
+
+ attr_reader :resources
+
+ # A list of files relative to the project pods root.
+ def initialize(resources)
+ @resources = resources
+ end
+
+ def save_as(pathname)
+ pathname.open('w') do |script|
+ script.puts CONTENT
+ @resources.each do |resource|
+ script.puts "install_resource '#{resource}'"
+ end
+ end
+ # TODO use File api
+ system("chmod +x '#{pathname}'")
+ end
+ end
+
class Target
include Config::Mixin
include Shared
@@ -40,7 +70,7 @@ def xcconfig_filename
end
def copy_resources_script
- @copy_resources_script ||= Xcode::CopyResourcesScript.new(build_specifications.map do |spec|
+ @copy_resources_script ||= CopyResourcesScript.new(build_specifications.map do |spec|
spec.expanded_resources
end.flatten)
end
View
3  lib/cocoapods/project_template.rb
@@ -38,7 +38,8 @@ def self.for_platform(platform)
'INSTALL_PATH' => "$(BUILT_PRODUCTS_DIR)",
'GCC_WARN_ABOUT_MISSING_PROTOTYPES' => 'YES',
'GCC_WARN_ABOUT_RETURN_TYPE' => 'YES',
- 'GCC_WARN_UNUSED_VARIABLE' => 'YES'
+ 'GCC_WARN_UNUSED_VARIABLE' => 'YES',
+ 'OTHER_LDFLAGS' => ''
},
:debug => {
'GCC_DYNAMIC_NO_PIC' => 'NO',
View
33 lib/cocoapods/xcode/config.rb
@@ -1,33 +0,0 @@
-module Pod
- module Xcode
- class Config
- def initialize(xcconfig = {})
- @attributes = {}
- merge!(xcconfig)
- end
-
- def to_hash
- @attributes
- end
-
- def merge!(xcconfig)
- xcconfig.to_hash.each do |key, value|
- if existing_value = @attributes[key]
- @attributes[key] = "#{existing_value} #{value}"
- else
- @attributes[key] = value
- end
- end
- end
- alias_method :<<, :merge!
-
- def to_s
- @attributes.map { |key, value| "#{key} = #{value}" }.join("\n")
- end
-
- def save_as(pathname)
- pathname.open('w') { |file| file << to_s }
- end
- end
- end
-end
View
33 lib/cocoapods/xcode/copy_resources_script.rb
@@ -1,33 +0,0 @@
-module Pod
- module Xcode
- class CopyResourcesScript
- CONTENT = <<EOS
-#!/bin/sh
-
-install_resource()
-{
- echo "cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
- cp -R ${SRCROOT}/Pods/$1 ${CONFIGURATION_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}
-}
-EOS
-
- attr_reader :resources
-
- # A list of files relative to the project pods root.
- def initialize(resources)
- @resources = resources
- end
-
- def save_as(pathname)
- pathname.open('w') do |script|
- script.puts CONTENT
- @resources.each do |resource|
- script.puts "install_resource '#{resource}'"
- end
- end
- # TODO use File api
- system("chmod +x '#{pathname}'")
- end
- end
- end
-end
View
683 lib/cocoapods/xcode/project.rb
@@ -1,683 +0,0 @@
-framework 'Foundation'
-require 'fileutils'
-
-require 'active_support/inflector'
-require 'active_support/core_ext/string/inflections'
-
-module Pod
- module Xcode
- class Project
- class PBXObject
- class AssociationReflection
- def initialize(name, options)
- @name, @options = name.to_s, options
- end
-
- attr_reader :name, :options
-
- def klass
- @options[:class] ||= begin
- name = "PBX#{@name.classify}"
- name = "XC#{@name.classify}" unless Project.const_defined?(name)
- Project.const_get(name)
- end
- end
-
- def inverse
- klass.reflection(@options[:inverse_of])
- end
-
- def inverse?
- !!@options[:inverse_of]
- end
-
- def singular_name
- @options[:singular_name] || @name.singularize
- end
-
- def singular_getter
- singular_name
- end
-
- def singular_setter
- "#{singular_name}="
- end
-
- def plural_name
- @name.pluralize
- end
-
- def plural_getter
- plural_name
- end
-
- def plural_setter
- "#{plural_name}="
- end
-
- def uuid_attribute
- @options[:uuid] || @name
- end
-
- def uuid_method_name
- (@options[:uuid] || @options[:uuids] || "#{singular_name}Reference").to_s.singularize
- end
-
- def uuid_getter
- uuid_method_name
- end
-
- def uuid_setter
- "#{uuid_method_name}="
- end
-
- def uuids_method_name
- uuid_method_name.pluralize
- end
-
- def uuids_getter
- uuids_method_name
- end
-
- def uuids_setter
- "#{uuids_method_name}="
- end
- end
-
- def self.reflections
- @reflections ||= []
- end
-
- def self.create_reflection(name, options)
- (reflections << AssociationReflection.new(name, options)).last
- end
-
- def self.reflection(name)
- reflections.find { |r| r.name.to_s == name.to_s }
- end
-
- def self.attribute(attribute_name, accessor_name = nil)
- attribute_name = attribute_name.to_s
- name = (accessor_name || attribute_name).to_s
- define_method(name) { @attributes[attribute_name] }
- define_method("#{name}=") { |value| @attributes[attribute_name] = value }
- end
-
- def self.attributes(*names)
- names.each { |name| attribute(name) }
- end
-
- def self.has_many(plural_attr_name, options = {}, &block)
- reflection = create_reflection(plural_attr_name, options)
- if reflection.inverse?
- define_method(reflection.name) do
- scoped = @project.objects.select_by_class(reflection.klass).select do |object|
- object.send(reflection.inverse.uuid_getter) == self.uuid
- end
- PBXObjectList.new(reflection.klass, @project, scoped) do |object|
- object.send(reflection.inverse.uuid_setter, self.uuid)
- end
- end
- else
- attribute(reflection.name, reflection.uuids_getter)
- define_method(reflection.name) do
- uuids = send(reflection.uuids_getter)
- if block
- # Evaluate the block, which was specified at the class level, in
- # the instance’s context.
- list_by_class(uuids, reflection.klass) do |object|
- instance_exec(object, &block)
- end
- else
- list_by_class(uuids, reflection.klass)
- end
- end
- define_method(reflection.plural_setter) do |objects|
- send(reflection.uuids_setter, objects.map(&:uuid))
- end
- end
- end
-
- def self.has_one(singular_attr_name, options = {})
- reflection = create_reflection(singular_attr_name, options)
- if reflection.inverse?
- define_method(reflection.name) do
- # Loop over all objects of the class and find the one that includes
- # this object in the specified uuid list.
- @project.objects.select_by_class(reflection.klass).find do |object|
- object.send(reflection.inverse.uuids_getter).include?(self.uuid)
- end
- end
- define_method(reflection.singular_setter) do |object|
- # Remove this object from the uuid list of the target
- # that this object was associated to.
- if previous = send(reflection.name)
- previous.send(reflection.inverse.uuids_getter).delete(self.uuid)
- end
- # Now assign this object to the new object
- object.send(reflection.inverse.uuids_getter) << self.uuid if object
- end
- else
- attribute(reflection.uuid_attribute, reflection.uuid_getter)
- define_method(reflection.name) do
- @project.objects[send(reflection.uuid_getter)]
- end
- define_method(reflection.singular_setter) do |object|
- send(reflection.uuid_setter, object.uuid)
- end
- end
- end
-
- def self.isa
- @isa ||= name.split('::').last
- end
-
- attr_reader :uuid, :attributes
- attributes :isa, :name
-
- def initialize(project, uuid, attributes)
- @project, @attributes = project, attributes
- unless uuid
- # Add new objects to the main hash with a unique UUID
- begin; uuid = generate_uuid; end while @project.objects_hash.has_key?(uuid)
- @project.objects_hash[uuid] = @attributes
- end
- @uuid = uuid
- self.isa ||= self.class.isa
- end
-
- def ==(other)
- other.is_a?(PBXObject) && self.uuid == other.uuid
- end
-
- def inspect
- "#<#{isa} UUID: `#{uuid}', name: `#{name}'>"
- end
-
- private
-
- def generate_uuid
- _uuid = CFUUIDCreate(nil)
- uuid = CFUUIDCreateString(nil, _uuid)
- CFRelease(_uuid)
- CFMakeCollectable(uuid)
- # Xcode's version is actually shorter, not worrying about collisions too much right now.
- uuid.gsub('-', '')[0..23]
- end
-
- def list_by_class(uuids, klass, scoped = nil, &block)
- unless scoped
- scoped = uuids.map { |uuid| @project.objects[uuid] }.select { |o| o.is_a?(klass) }
- end
- if block
- PBXObjectList.new(klass, @project, scoped, &block)
- else
- PBXObjectList.new(klass, @project, scoped) do |object|
- # Add the uuid of a newly created object to the uuids list
- uuids << object.uuid
- end
- end
- end
- end
-
- # Missing constants that begin with either `PBX' or `XC' are assumed to be
- # valid classes in a Xcode project. A new PBXObject subclass is created
- # for the constant and returned.
- def self.const_missing(name)
- if name =~ /^(PBX|XC)/
- klass = Class.new(PBXObject)
- const_set(name, klass)
- klass
- else
- super
- end
- end
-
- class PBXFileReference < PBXObject
- attributes :path, :sourceTree, :explicitFileType, :lastKnownFileType, :includeInIndex
- has_many :buildFiles, :inverse_of => :file
- has_one :group, :inverse_of => :children
-
- def self.new_static_library(project, productName)
- new(project, nil, {
- "path" => "lib#{productName}.a",
- "includeInIndex" => "0", # no idea what this is
- "sourceTree" => "BUILT_PRODUCTS_DIR",
- })
- end
-
- def initialize(project, uuid, attributes)
- is_new = uuid.nil?
- super
- self.path = path if path # sets default name
- self.sourceTree ||= 'SOURCE_ROOT'
- if is_new
- @project.main_group.children << self
- end
- set_default_file_type!
- end
-
- alias_method :_path=, :path=
- def path=(path)
- self._path = path
- self.name ||= pathname.basename.to_s
- path
- end
-
- def pathname
- Pathname.new(path)
- end
-
- def set_default_file_type!
- return if explicitFileType || lastKnownFileType
- case path
- when /\.a$/
- self.explicitFileType = 'archive.ar'
- when /\.framework$/
- self.lastKnownFileType = 'wrapper.framework'
- when /\.xcconfig$/
- self.lastKnownFileType = 'text.xcconfig'
- end
- end
- end
-
- class PBXGroup < PBXObject
- attributes :sourceTree
-
- has_many :children, :class => PBXFileReference do |object|
- if object.is_a?(Pod::Xcode::Project::PBXFileReference)
- # Associating the file to this group through the inverse
- # association will also remove it from the group it was in.
- object.group = self
- else
- # TODO What objects can actually be in a group and don't they
- # all need the above treatment.
- childReferences << object.uuid
- end
- end
-
- def initialize(*)
- super
- self.sourceTree ||= '<group>'
- self.childReferences ||= []
- end
-
- def files
- list_by_class(childReferences, Pod::Xcode::Project::PBXFileReference) do |file|
- file.group = self
- end
- end
-
- def source_files
- files = self.files.reject { |file| file.buildFiles.empty? }
- list_by_class(childReferences, Pod::Xcode::Project::PBXFileReference, files) do |file|
- file.group = self
- end
- end
-
- def groups
- list_by_class(childReferences, Pod::Xcode::Project::PBXGroup)
- end
-
- def <<(child)
- children << child
- end
- end
-
- class PBXBuildFile < PBXObject
- attributes :settings
- has_one :file, :uuid => :fileRef
- end
-
- class PBXBuildPhase < PBXObject
- # TODO rename this to buildFiles and add a files :through => :buildFiles shortcut
- has_many :files, :class => PBXBuildFile
-
- attributes :buildActionMask, :runOnlyForDeploymentPostprocessing
-
- def initialize(*)
- super
- self.fileReferences ||= []
- # These are always the same, no idea what they are.
- self.buildActionMask ||= "2147483647"
- self.runOnlyForDeploymentPostprocessing ||= "0"
- end
- end
-
- class PBXCopyFilesBuildPhase < PBXBuildPhase
- attributes :dstPath, :dstSubfolderSpec
-
- def self.new_pod_dir(project, pod_name, path)
- new(project, nil, {
- "dstPath" => "$(PRODUCT_NAME)/#{path}",
- "name" => "Copy #{pod_name} Public Headers",
- })
- end
-
- def initialize(*)
- super
- self.dstSubfolderSpec ||= "16"
- end
- end
-
- class PBXSourcesBuildPhase < PBXBuildPhase; end
- class PBXFrameworksBuildPhase < PBXBuildPhase; end
- class PBXShellScriptBuildPhase < PBXBuildPhase
- attribute :shellScript
- end
-
- class PBXNativeTarget < PBXObject
- STATIC_LIBRARY = 'com.apple.product-type.library.static'
-
- attributes :productName, :productType
-
- has_many :buildPhases
- has_many :dependencies # TODO :class => ?
- has_many :buildRules # TODO :class => ?
- has_one :buildConfigurationList
- has_one :product, :uuid => :productReference
-
- def self.new_static_library(project, productName)
- # TODO should probably switch the uuid and attributes argument
- target = new(project, nil, 'productType' => STATIC_LIBRARY, 'productName' => productName)
- target.product = project.files.new_static_library(productName)
- target.buildPhases.add(PBXSourcesBuildPhase)
-
- buildPhase = target.buildPhases.add(PBXFrameworksBuildPhase)
- project.groups.find { |g| g.name == 'Frameworks' }.files.each do |framework|
- buildPhase.files << framework.buildFiles.new
- end
-
- target.buildPhases.add(PBXCopyFilesBuildPhase, 'dstPath' => '$(PRODUCT_NAME)')
- target
- end
-
- # You need to specify a product. For a static library you can use
- # PBXFileReference.new_static_library.
- def initialize(project, *)
- super
- self.name ||= productName
- self.buildRuleReferences ||= []
- self.dependencyReferences ||= []
- self.buildPhaseReferences ||= []
-
- unless buildConfigurationList
- self.buildConfigurationList = project.objects.add(XCConfigurationList)
- # TODO or should this happen in buildConfigurationList?
- buildConfigurationList.buildConfigurations.new('name' => 'Debug')
- buildConfigurationList.buildConfigurations.new('name' => 'Release')
- end
- end
-
- alias_method :_product=, :product=
- def product=(product)
- self._product = product
- product.group = @project.products
- end
-
- def buildConfigurations
- buildConfigurationList.buildConfigurations
- end
-
- def source_build_phases
- buildPhases.select_by_class(PBXSourcesBuildPhase)
- end
-
- def copy_files_build_phases
- buildPhases.select_by_class(PBXCopyFilesBuildPhase)
- end
-
- def frameworks_build_phases
- buildPhases.select_by_class(PBXFrameworksBuildPhase)
- end
-
- # Finds an existing file reference or creates a new one.
- def add_source_file(path, copy_header_phase = nil, compiler_flags = nil)
- file = @project.files.find { |file| file.path == path.to_s } || @project.files.new('path' => path.to_s)
- buildFile = file.buildFiles.new
- if path.extname == '.h'
- buildFile.settings = { 'ATTRIBUTES' => ["Public"] }
- # Working around a bug in Xcode 4.2 betas, remove this once the Xcode bug is fixed:
- # https://github.com/alloy/cocoapods/issues/13
- #phase = copy_header_phase || headers_build_phases.first
- phase = copy_header_phase || copy_files_build_phases.first
- phase.files << buildFile
- else
- buildFile.settings = { 'COMPILER_FLAGS' => compiler_flags } if compiler_flags
- source_build_phases.first.files << buildFile
- end
- file
- end
- end
-
- class XCBuildConfiguration < PBXObject
- attribute :buildSettings
- has_one :baseConfiguration, :uuid => :baseConfigurationReference
-
- def initialize(*)
- super
- # TODO These are from an iOS static library, need to check if it works for any product type
- self.buildSettings = {
- 'DSTROOT' => '/tmp/Pods.dst',
- 'GCC_PRECOMPILE_PREFIX_HEADER' => 'YES',
- 'GCC_VERSION' => 'com.apple.compilers.llvm.clang.1_0',
- # The OTHER_LDFLAGS option *has* to be overriden so that it does not
- # use those from the xcconfig (for CocoaPods specifically).
- 'OTHER_LDFLAGS' => '',
- 'PRODUCT_NAME' => '$(TARGET_NAME)',
- 'SKIP_INSTALL' => 'YES',
- }.merge(buildSettings || {})
- end
- end
-
- class XCConfigurationList < PBXObject
- has_many :buildConfigurations
-
- def initialize(*)
- super
- self.buildConfigurationReferences ||= []
- end
- end
-
- class PBXProject < PBXObject
- has_many :targets, :class => PBXNativeTarget
- has_one :products, :singular_name => :products, :uuid => :productRefGroup, :class => PBXGroup
- end
-
- class PBXObjectList
- include Enumerable
-
- def initialize(represented_class, project, scoped, &new_object_callback)
- @represented_class = represented_class
- @project = project
- @scoped_hash = scoped.is_a?(Array) ? scoped.inject({}) { |h, o| h[o.uuid] = o.attributes; h } : scoped
- @callback = new_object_callback
- end
-
- def empty?
- @scoped_hash.empty?
- end
-
- def [](uuid)
- if hash = @scoped_hash[uuid]
- Project.const_get(hash['isa']).new(@project, uuid, hash)
- end
- end
-
- def add(klass, hash = {})
- object = klass.new(@project, nil, hash)
- @callback.call(object) if @callback
- object
- end
-
- def new(hash = {})
- add(@represented_class, hash)
- end
-
- def <<(object)
- @callback.call(object) if @callback
- end
-
- def each
- @scoped_hash.keys.each do |uuid|
- yield self[uuid]
- end
- end
-
- def ==(other)
- self.to_a == other.to_a
- end
-
- def first
- to_a.first
- end
-
- def last
- to_a.last
- end
-
- def inspect
- "<PBXObjectList: #{map(&:inspect)}>"
- end
-
- # Only makes sense on lists that contain mixed classes.
- def select_by_class(klass)
- scoped = @scoped_hash.select { |_, attr| attr['isa'] == klass.isa }
- PBXObjectList.new(klass, @project, scoped) do |object|
- # Objects added to the subselection should still use the same
- # callback as this list.
- self << object
- end
- end
-
- def method_missing(name, *args, &block)
- if @represented_class.respond_to?(name)
- object = @represented_class.send(name, @project, *args)
- # The callbacks are only for PBXObject instances instantiated
- # from the class method that we forwarded the message to.
- @callback.call(object) if object.is_a?(PBXObject)
- object
- else
- super
- end
- end
- end
-
- def initialize(xcodeproj = nil)
- if xcodeproj
- file = File.join(xcodeproj, 'project.pbxproj')
- @plist = NSMutableDictionary.dictionaryWithContentsOfFile(file.to_s)
- else
- @plist = {
- 'archiveVersion' => '1',
- 'classes' => {},
- 'objectVersion' => '46',
- 'objects' => {}
- }
- self.root_object = objects.add(Xcode::Project::PBXProject, {
- 'attributes' => { 'LastUpgradeCheck' => '0420' },
- 'compatibilityVersion' => 'Xcode 3.2',
- 'developmentRegion' => 'English',
- 'hasScannedForEncodings' => '0',
- 'knownRegions' => ['en'],
- 'mainGroup' => groups.new.uuid,
- 'projectDirPath' => '',
- 'projectRoot' => '',
- 'targets' => []
- })
- end
- end
-
- def to_hash
- @plist
- end
-
- def objects_hash
- @plist['objects']
- end
-
- def objects
- @objects ||= PBXObjectList.new(PBXObject, self, objects_hash)
- end
-
- def root_object
- objects[@plist['rootObject']]
- end
-
- def root_object=(object)
- @plist['rootObject'] = object.uuid
- end
-
- def groups
- objects.select_by_class(PBXGroup)
- end
-
- def main_group
- objects[root_object.attributes['mainGroup']]
- end
-
- # Shortcut access to the `Pods' PBXGroup.
- def pods
- groups.find { |g| g.name == 'Pods' }
- end
-
- # Adds a group as child to the `Pods' group.
- def add_pod_group(name)
- pods.groups.new('name' => name)
- end
-
- def files
- objects.select_by_class(PBXFileReference)
- end
-
- def add_system_framework(name)
- files.new({
- 'name' => "#{name}.framework",
- 'path' => "System/Library/Frameworks/#{name}.framework",
- 'sourceTree' => 'SDKROOT'
- })
- end
-
- def add_shell_script_build_phase(name, script_path)
- objects.add(Xcode::Project::PBXShellScriptBuildPhase, {
- 'name' => name,
- 'files' => [],
- 'inputPaths' => [],
- 'outputPaths' => [],
- 'shellPath' => '/bin/sh',
- 'shellScript' => script_path
- })
- end
-
- def build_files
- objects.select_by_class(PBXBuildFile)
- end
-
- def targets
- # Better to check the project object for targets to ensure they are
- # actually there so the project will work
- root_object.targets
- end
-
- def products
- root_object.products
- end
-
- IGNORE_GROUPS = ['Pods', 'Frameworks', 'Products', 'Supporting Files']
- def source_files
- source_files = {}
- groups.each do |group|
- next if group.name.nil? || IGNORE_GROUPS.include?(group.name)
- source_files[group.name] = group.source_files.map(&:pathname)
- end
- source_files
- end
-
- def save_as(projpath)
- projpath = projpath.to_s
- FileUtils.mkdir_p(projpath)
- @plist.writeToFile(File.join(projpath, 'project.pbxproj'), atomically:true)
- end
- end
- end
-end
View
56 lib/cocoapods/xcode/workspace.rb
@@ -1,56 +0,0 @@
-framework 'Foundation'
-require 'fileutils'
-
-module Pod
- module Xcode
- class Workspace
- def initialize(*projpaths)
- @projpaths = projpaths
- end
-
- def self.new_from_xcworkspace(path)
- begin
- from_s(File.read(File.join(path, 'contents.xcworkspacedata')))
- rescue Errno::ENOENT
- new
- end
- end
-
- def self.from_s(xml)
- doc = NSXMLDocument.alloc.initWithXMLString(xml, options:0, error:nil)
- projpaths = doc.nodesForXPath("/Workspace/FileRef", error:nil).map do |node|
- node.attributeForName("location").stringValue.sub(/^group:/, '')
- end
- new(*projpaths)
- end
-
- attr_reader :projpaths
-
- def <<(projpath)
- @projpaths << projpath
- end
-
- def include?(projpath)
- @projpaths.include?(projpath)
- end
-
- TEMPLATE = %q[<?xml version="1.0" encoding="UTF-8"?><Workspace version="1.0"></Workspace>]
- def to_s
- doc = NSXMLDocument.alloc.initWithXMLString(TEMPLATE, options:0, error:nil)
- @projpaths.each do |projpath|
- el = NSXMLNode.elementWithName("FileRef")
- el.addAttribute(NSXMLNode.attributeWithName("location", stringValue:"group:#{projpath}"))
- doc.rootElement.addChild(el)
- end
- NSString.alloc.initWithData(doc.XMLData, encoding:NSUTF8StringEncoding)
- end
-
- def save_as(path)
- FileUtils.mkdir_p(path)
- File.open(File.join(path, 'contents.xcworkspacedata'), 'w') do |out|
- out << to_s
- end
- end
- end
- end
-end
View
34 spec/unit/xcode/config_spec.rb
@@ -1,34 +0,0 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-
-describe "Pod::Xcode::Config" do
- extend SpecHelper::TemporaryDirectory
-
- before do
- @config = Pod::Xcode::Config.new('OTHER_LD_FLAGS' => '-framework Foundation')
- end
-
- it "merges another config hash in place" do
- @config.merge!('HEADER_SEARCH_PATHS' => '/some/path')
- @config.to_hash.should == {
- 'OTHER_LD_FLAGS' => '-framework Foundation',
- 'HEADER_SEARCH_PATHS' => '/some/path'
- }
- end
-
- it "appends a value for the same key when merging" do
- @config.merge!('OTHER_LD_FLAGS' => '-l xml2.2.7.3')
- @config.to_hash.should == {
- 'OTHER_LD_FLAGS' => '-framework Foundation -l xml2.2.7.3'
- }
- end
-
- it "creates the config file" do
- @config.merge!('HEADER_SEARCH_PATHS' => '/some/path')
- @config.merge!('OTHER_LD_FLAGS' => '-l xml2.2.7.3')
- @config.save_as(temporary_directory + 'Pods.xcconfig')
- (temporary_directory + 'Pods.xcconfig').read.split("\n").sort.should == [
- "OTHER_LD_FLAGS = -framework Foundation -l xml2.2.7.3",
- "HEADER_SEARCH_PATHS = /some/path"
- ].sort
- end
-end
View
347 spec/unit/xcode/project_spec.rb
@@ -1,347 +0,0 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-
-describe "Pod::Xcode::Project" do
- extend SpecHelper::TemporaryDirectory
-
- before do
- @project = Pod::ProjectTemplate.for_platform(:ios)
- end
-
- def find_objects(conditions)
- @project.objects_hash.select do |_, object|
- object.objectsForKeys(conditions.keys, notFoundMarker:Object.new) == conditions.values
- end
- end
-
- def find_object(conditions)
- find_objects(conditions).first
- end
-
- before do
- @target = @project.targets.new_static_library('Pods')
- end
-
- it "returns the objects hash" do
- @project.objects_hash.should == @project.to_hash['objects']
- end
-
- describe "PBXObject" do
- before do
- @object = Pod::Xcode::Project::PBXObject.new(@project, nil, 'name' => 'AnObject')
- end
-
- it "merges the class name into the attributes" do
- @object.isa.should == 'PBXObject'
- @object.attributes['isa'].should == 'PBXObject'
- end
-
- it "takes a name" do
- @object.name.should == 'AnObject'
- @object.name = 'AnotherObject'
- @object.name.should == 'AnotherObject'
- end
-
- it "generates a uuid" do
- @object.uuid.should.be.instance_of String
- @object.uuid.size.should == 24
- @object.uuid.should == @object.uuid
- end
-
- it "adds the object to the objects hash" do
- @project.objects_hash[@object.uuid].should == @object.attributes
- end
- end
-
- describe "a PBXFileReference" do
- it "sets a default file type" do
- framework, library, xcconfig = %w[framework a xcconfig].map { |n| @project.files.new('path' => "Rockin.#{n}") }
- framework.lastKnownFileType.should == 'wrapper.framework'
- framework.explicitFileType.should == nil
- library.lastKnownFileType.should == nil
- library.explicitFileType.should == 'archive.ar'
- xcconfig.lastKnownFileType.should == 'text.xcconfig'
- xcconfig.explicitFileType.should == nil
- end
-
- it "doesn't set a file type when overridden" do
- fakework = @project.files.new('path' => 'Sup.framework', 'lastKnownFileType' => 'fish')
- fakework.lastKnownFileType.should == 'fish'
- makework = @project.files.new('path' => 'n2m.framework', 'explicitFileType' => 'tree')
- makework.lastKnownFileType.should == nil
- end
-
- before do
- @file = @project.files.new('path' => 'some/file.m')
- end
-
- it "is automatically added to the main group" do
- @file.group.should == @project.main_group
- end
-
- it "is removed from the original group when added to another group" do
- @project.pods.children << @file
- @file.group.should == @project.pods
- @project.main_group.children.should.not.include @file
- end
- end
-
- describe "a new PBXBuildPhase" do
- before do
- @phase = @project.objects.add(Pod::Xcode::Project::PBXBuildPhase)
- end
-
- it "has an empty list of files" do
- @phase.files.to_a.should == []
- end
-
- it "always returns the same buildActionMask (no idea what it is)" do
- @phase.buildActionMask.should == "2147483647"
- end
-
- it "always returns zero for runOnlyForDeploymentPostprocessing (no idea what it is)" do
- @phase.runOnlyForDeploymentPostprocessing.should == "0"
- end
- end
-
- describe "a new PBXCopyFilesBuildPhase" do
- before do
- @phase = @project.objects.add(Pod::Xcode::Project::PBXCopyFilesBuildPhase, 'dstPath' => 'some/path')
- end
-
- it "is a PBXBuildPhase" do
- @phase.should.be.kind_of Pod::Xcode::Project::PBXBuildPhase
- end
-
- it "returns the dstPath" do
- @phase.dstPath.should == 'some/path'
- end
-
- it "returns the dstSubfolderSpec (no idea what it is yet, but it's not always the same)" do
- @phase.dstSubfolderSpec.should == "16"
- end
- end
-
- describe "a new PBXSourcesBuildPhase" do
- before do
- @phase = @project.objects.add(Pod::Xcode::Project::PBXSourcesBuildPhase)
- end
-
- it "is a PBXBuildPhase" do
- @phase.should.be.kind_of Pod::Xcode::Project::PBXBuildPhase
- end
- end
-
- describe "a new PBXFrameworksBuildPhase" do
- before do
- @phase = @project.objects.add(Pod::Xcode::Project::PBXFrameworksBuildPhase)
- end
-
- it "is a PBXBuildPhase" do
- @phase.should.be.kind_of Pod::Xcode::Project::PBXBuildPhase
- end
- end
-
- describe "a new XCBuildConfiguration" do
- before do
- @configuration = @project.objects.add(Pod::Xcode::Project::XCBuildConfiguration)
- end
-
- it "returns the xcconfig that this configuration is based on (baseConfigurationReference)" do
- xcconfig = @project.objects.new
- @configuration.baseConfiguration = xcconfig
- @configuration.baseConfigurationReference.should == xcconfig.uuid
- end
- end
-
- describe "a new XCConfigurationList" do
- before do
- @list = @project.objects.add(Pod::Xcode::Project::XCConfigurationList)
- end
-
- it "returns the configurations" do
- configuration = @project.objects.add(Pod::Xcode::Project::XCBuildConfiguration)
- @list.buildConfigurations.to_a.should == []
- @list.buildConfigurations = [configuration]
- @list.buildConfigurationReferences.should == [configuration.uuid]
- end
- end
-
- describe "a new PBXNativeTarget" do
- it "returns the product name, which is the name of the binary (minus prefix/suffix)" do
- @target.name.should == "Pods"
- @target.productName.should == "Pods"
- end
-
- it "returns the product" do
- product = @target.product
- product.uuid.should == @target.productReference
- product.should.be.instance_of Pod::Xcode::Project::PBXFileReference
- product.path.should == "libPods.a"
- product.name.should == "libPods.a"
- product.group.name.should == "Products"
- product.sourceTree.should == "BUILT_PRODUCTS_DIR"
- product.explicitFileType.should == "archive.ar"
- product.includeInIndex.should == "0"
- end
-
- it "returns that product type is a static library" do
- @target.productType.should == "com.apple.product-type.library.static"
- end
-
- it "returns the buildConfigurationList" do
- list = @target.buildConfigurationList
- list.should.be.instance_of Pod::Xcode::Project::XCConfigurationList
- list.buildConfigurations.each do |configuration|
- configuration.buildSettings.should == {
- 'DSTROOT' => '/tmp/Pods.dst',
- 'GCC_PRECOMPILE_PREFIX_HEADER' => 'YES',
- # TODO do we need a default?
- #'GCC_PREFIX_HEADER' => 'Pods-Prefix.pch',
- 'OTHER_LDFLAGS' => '',
- 'GCC_VERSION' => 'com.apple.compilers.llvm.clang.1_0',
- 'PRODUCT_NAME' => '$(TARGET_NAME)',
- 'SKIP_INSTALL' => 'YES',
- }
- end
- end
-
- it "returns an empty list of dependencies and buildRules (not sure yet which classes those are yet)" do
- @target.dependencies.to_a.should == []
- @target.buildRules.to_a.should == []
- end
-
- describe "concerning its build phases" do
- extend SpecHelper::TemporaryDirectory
-
- it "returns an empty sources build phase" do
- phase = @target.buildPhases.select_by_class(Pod::Xcode::Project::PBXSourcesBuildPhase).first
- phase.files.to_a.should == []
- end
-
- it "returns a libraries/frameworks build phase, which by default only contains `Foundation.framework'" do
- phase = @target.buildPhases.select_by_class(Pod::Xcode::Project::PBXFrameworksBuildPhase).first
- phase.files.map { |buildFile| buildFile.file.name }.should == ['Foundation.framework']
- end
-
- it "returns an empty 'copy headers' phase" do
- phase = @target.buildPhases.select_by_class(Pod::Xcode::Project::PBXCopyFilesBuildPhase).first
- phase.dstPath.should == "$(PUBLIC_HEADERS_FOLDER_PATH)"
- phase.files.to_a.should == []
- end
- end
- end
-
- it "returns the objects as PBXObject instances" do
- @project.objects.each do |object|
- @project.objects_hash[object.uuid].should == object.attributes
- end
- end
-
- it "adds any type of new PBXObject to the objects hash" do
- object = @project.objects.add(Pod::Xcode::Project::PBXObject, 'name' => 'An Object')
- object.name.should == 'An Object'
- @project.objects_hash[object.uuid].should == object.attributes
- end
-
- it "adds a new PBXObject, of the configured type, to the objects hash" do
- group = @project.groups.new('name' => 'A new group')
- group.isa.should == 'PBXGroup'
- group.name.should == 'A new group'
- @project.objects_hash[group.uuid].should == group.attributes
- end
-
- it "adds a new PBXFileReference to the objects hash" do
- file = @project.files.new('path' => '/some/file.m')
- file.isa.should == 'PBXFileReference'
- file.name.should == 'file.m'
- file.path.should == '/some/file.m'
- file.sourceTree.should == 'SOURCE_ROOT'
- @project.objects_hash[file.uuid].should == file.attributes
- end
-
- it "adds a new PBXBuildFile to the objects hash when a new PBXFileReference is created" do
- file = @project.files.new('name' => '/some/source/file.h')
- build_file = file.buildFiles.new
- build_file.file = file
- build_file.fileRef.should == file.uuid
- build_file.isa.should == 'PBXBuildFile'
- @project.objects_hash[build_file.uuid].should == build_file.attributes
- end
-
- it "adds a group to the `Pods' group" do
- group = @project.add_pod_group('JSONKit')
- @project.pods.childReferences.should.include group.uuid
- find_object({
- 'isa' => 'PBXGroup',
- 'name' => 'JSONKit',
- 'sourceTree' => '<group>',
- 'children' => []
- }).should.not == nil
- end
-
- it "adds an `m' or `c' file to the `sources build' phase list" do
- %w{ m mm c cpp }.each do |ext|
- path = Pathname.new("path/to/file.#{ext}")
- file = @target.add_source_file(path)
- # ensure that it was added to all objects
- file = @project.objects[file.uuid]
-
- phase = @target.buildPhases.find { |phase| phase.is_a?(Pod::Xcode::Project::PBXSourcesBuildPhase) }
- phase.files.map { |buildFile| buildFile.file }.should.include file
-
- phase = @target.buildPhases.find { |phase| phase.is_a?(Pod::Xcode::Project::PBXCopyFilesBuildPhase) }
- phase.files.map { |buildFile| buildFile.file }.should.not.include file
- end
- end
-
- it "adds custom compiler flags to the PBXBuildFile object if specified" do
- build_file_uuids = []
- %w{ m mm c cpp }.each do |ext|
- path = Pathname.new("path/to/file.#{ext}")
- file = @project.targets.first.add_source_file(path, nil, '-fno-obj-arc')
- find_object({
- 'isa' => 'PBXBuildFile',
- 'fileRef' => file.uuid,
- 'settings' => {'COMPILER_FLAGS' => '-fno-obj-arc' }
- }).should.not == nil
- end
- end
-
- it "creates a copy build header phase which will copy headers to a specified path" do
- phase = @project.targets.first.copy_files_build_phases.new_pod_dir("SomePod", "Path/To/Source")
- find_object({
- 'isa' => 'PBXCopyFilesBuildPhase',
- 'dstPath' => '$(PUBLIC_HEADERS_FOLDER_PATH)/Path/To/Source',
- 'name' => 'Copy SomePod Public Headers'
- }).should.not == nil
- @project.targets.first.buildPhases.should.include phase
- end
-
- # TODO add test for the optional copy_header_phase
- #it "adds a `h' file as a build file and adds it to the `headers build' phase list" do
- it "adds a `h' file as a build file and adds it to the `copy header files' build phase list" do
- path = Pathname.new("path/to/file.h")
- file = @target.add_source_file(path)
- # ensure that it was added to all objects
- file = @project.objects[file.uuid]
-
- phase = @target.buildPhases.find { |phase| phase.is_a?(Pod::Xcode::Project::PBXSourcesBuildPhase) }
- phase.files.map { |buildFile| buildFile.file }.should.not.include file
-
- phase = @target.buildPhases.find { |phase| phase.is_a?(Pod::Xcode::Project::PBXCopyFilesBuildPhase) }
- phase.files.map { |buildFile| buildFile.file }.should.include file
- end
-
- it "saves the template with the adjusted project" do
- @project.save_as(File.join(temporary_directory, 'Pods.xcodeproj'))
- project_file = (temporary_directory + 'Pods.xcodeproj/project.pbxproj')
- NSDictionary.dictionaryWithContentsOfFile(project_file.to_s).should == @project.to_hash
- end
-
- it "returns all source files" do
- group = @project.groups.new('name' => 'SomeGroup')
- files = [Pathname.new('/some/file.h'), Pathname.new('/some/file.m')]
- files.each { |file| group << @target.add_source_file(file) }
- group.source_files.map(&:pathname).sort.should == files.sort
- end
-end
View
26 spec/unit/xcode/workspace_spec.rb
@@ -1,26 +0,0 @@
-require File.expand_path('../../../spec_helper', __FILE__)
-
-describe "Pod::Xcode::Workspace" do
- before do
- @workspace = Pod::Xcode::Workspace.new('Pods/Pods.xcodeproj', 'App.xcodeproj')
- end
-
- it "accepts new projects" do
- @workspace << 'Framework.xcodeproj'
- @workspace.projpaths.should.include 'Framework.xcodeproj'
- end
-
- before do
- @doc = NSXMLDocument.alloc.initWithXMLString(@workspace.to_s, options:0, error:nil)
- end
-
- it "is the right xml workspace version" do
- @doc.rootElement.attributeForName("version").stringValue.should == "1.0"
- end
-
- it "refers to the projects in xml" do
- @doc.nodesForXPath("/Workspace/FileRef", error:nil).map do |node|
- node.attributeForName("location").stringValue.sub(/^group:/, '')
- end.sort.should == ['App.xcodeproj', 'Pods/Pods.xcodeproj']
- end
-end
View
35 spec/unit/xcode_spec.rb
@@ -0,0 +1,35 @@
+require File.expand_path('../../spec_helper', __FILE__)
+
+describe 'Xcode::Project' do
+ before do
+ @project = Xcode::Project.new
+ end
+
+ def find_object(conditions)
+ @project.objects_hash.select do |_, object|
+ object.objectsForKeys(conditions.keys, notFoundMarker:Object.new) == conditions.values
+ end.first
+ end
+
+ it "adds a group to the `Pods' group" do
+ group = @project.add_pod_group('JSONKit')
+ @project.pods.childReferences.should.include group.uuid
+ find_object({
+ 'isa' => 'PBXGroup',
+ 'name' => 'JSONKit',
+ 'sourceTree' => '<group>',
+ 'children' => []
+ }).should.not == nil
+ end
+
+ it "creates a copy build header phase which will copy headers to a specified path" do
+ @project.targets.new
+ phase = @project.targets.first.copy_files_build_phases.new_pod_dir("SomePod", "Path/To/Source")
+ find_object({
+ 'isa' => 'PBXCopyFilesBuildPhase',
+ 'dstPath' => '$(PUBLIC_HEADERS_FOLDER_PATH)/Path/To/Source',
+ 'name' => 'Copy SomePod Public Headers'
+ }).should.not == nil
+ @project.targets.first.buildPhases.should.include phase
+ end
+end
Please sign in to comment.
Something went wrong with that request. Please try again.