Commit 2ab89bd5 authored by Eloy Duran's avatar Eloy Duran

Merge branch 'xcodeproj-gem'. Closes #24.

parents dba5cbfe da41a657
......@@ -13,3 +13,6 @@
[submodule "spec/fixtures/integration/sstoolkit"]
path = spec/fixtures/integration/sstoolkit
url = https://github.com/samsoffes/sstoolkit.git
[submodule "external/xcodeproj"]
path = external/xcodeproj
url = git@github.com:alloy/xcodeproj.git
#!/usr/bin/env macruby
if $0 == __FILE__
require 'rubygems'
gem 'activesupport', '~> 3.1.1'
$:.unshift File.expand_path('../../external/xcodeproj/lib', __FILE__)
$:.unshift File.expand_path('../../lib', __FILE__)
end
......
......@@ -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"
......
Subproject commit af5d347f9cf7768ea9433a321c3a7c7d898044e1
......@@ -12,26 +12,23 @@ module Pod
autoload :Executable, 'cocoapods/executable'
autoload :Installer, 'cocoapods/installer'
autoload :Podfile, 'cocoapods/podfile'
autoload :ProjectTemplate, 'cocoapods/project_template'
autoload :Resolver, 'cocoapods/resolver'
autoload :Source, 'cocoapods/source'
autoload :Spec, 'cocoapods/specification'
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
module Xcodeproj
autoload :Config, 'cocoapods/xcodeproj_ext'
autoload :Project, 'cocoapods/xcodeproj_ext'
autoload :Workspace, 'cocoapods/xcodeproj_ext'
end
class Pathname
def glob(pattern = '')
Dir.glob((self + pattern).to_s).map { |f| Pathname.new(f) }
end
end
......@@ -14,6 +14,36 @@ module Pod
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
......@@ -25,7 +55,7 @@ module Pod
end
def xcconfig
@xcconfig ||= Xcode::Config.new({
@xcconfig ||= Xcodeproj::Config.new({
# In a workspace this is where the static library headers should be found.
'USER_HEADER_SEARCH_PATHS' => '"$(BUILT_PRODUCTS_DIR)/Pods"',
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
......@@ -40,7 +70,7 @@ module Pod
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
......@@ -134,7 +164,7 @@ module Pod
def project
return @project if @project
@project = ProjectTemplate.for_platform(@podfile.platform)
@project = Xcodeproj::Project.for_platform(@podfile.platform)
# First we need to resolve dependencies across *all* targets, so that the
# same correct versions of pods are being used for all targets. This
# happens when we call `build_specifications'.
......@@ -191,7 +221,7 @@ module Pod
def configure_project(projpath)
root = File.dirname(projpath)
xcworkspace = File.join(root, File.basename(projpath, '.xcodeproj') + '.xcworkspace')
workspace = Xcode::Workspace.new_from_xcworkspace(xcworkspace)
workspace = Xcodeproj::Workspace.new_from_xcworkspace(xcworkspace)
pods_projpath = File.join(config.project_pods_root, 'Pods.xcodeproj')
root = Pathname.new(root).expand_path
[projpath, pods_projpath].each do |path|
......@@ -200,7 +230,7 @@ module Pod
end
workspace.save_as(xcworkspace)
app_project = Xcode::Project.new(projpath)
app_project = Xcodeproj::Project.new(projpath)
return if app_project.files.find { |file| file.path =~ /libPods\.a$/ }
configfile = app_project.files.new('path' => 'Pods/Pods.xcconfig')
......@@ -212,7 +242,7 @@ module Pod
libfile = app_project.files.new_static_library('Pods')
libfile.group = app_project.main_group.groups.find { |g| g.name == 'Frameworks' }
app_project.objects.select_by_class(Xcode::Project::PBXFrameworksBuildPhase).each do |build_phase|
app_project.objects.select_by_class(Xcodeproj::Project::PBXFrameworksBuildPhase).each do |build_phase|
build_phase.files << libfile.buildFiles.new
end
......
......@@ -22,7 +22,7 @@ module Pod
def initialize
@dependencies = []
@xcconfig = Xcode::Config.new
@xcconfig = Xcodeproj::Config.new
yield self if block_given?
end
......
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
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
This diff is collapsed.
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
require 'fileutils'
require 'xcodeproj'
module Xcodeproj
class 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
module Pod
module ProjectTemplate
def self.for_platform(platform)
project = Xcode::Project.new
project = Xcodeproj::Project.new
project.main_group << project.groups.new({ 'name' => 'Pods' })
framework = project.add_system_framework(platform == :ios ? 'Foundation' : 'Cocoa')
framework.group = project.groups.new({ 'name' => 'Frameworks' })
......@@ -12,15 +31,15 @@ module Pod
project.main_group << products
project.root_object.products = products
project.root_object.attributes['buildConfigurationList'] = project.objects.add(Xcode::Project::XCConfigurationList, {
project.root_object.attributes['buildConfigurationList'] = project.objects.add(Xcodeproj::Project::XCConfigurationList, {
'defaultConfigurationIsVisible' => '0',
'defaultConfigurationName' => 'Release',
'buildConfigurations' => [
project.objects.add(Xcode::Project::XCBuildConfiguration, {
project.objects.add(Xcodeproj::Project::XCBuildConfiguration, {
'name' => 'Debug',
'buildSettings' => build_settings(platform, :debug)
}),
project.objects.add(Xcode::Project::XCBuildConfiguration, {
project.objects.add(Xcodeproj::Project::XCBuildConfiguration, {
'name' => 'Release',
'buildSettings' => build_settings(platform, :release)
})
......@@ -38,7 +57,8 @@ module Pod
'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',
......
......@@ -207,7 +207,7 @@ if false
installer = SpecHelper::Installer.new(spec)
installer.install!
project = Pod::Xcode::Project.new(config.project_pods_root + 'Pods.xcodeproj')
project = Xcodeproj::Project.new(config.project_pods_root + 'Pods.xcodeproj')
project.source_files.should == installer.project.source_files
end
......@@ -264,10 +264,10 @@ if false
installer.configure_project(projpath)
xcworkspace = temporary_directory + 'ASIHTTPRequest.xcworkspace'
workspace = Pod::Xcode::Workspace.new_from_xcworkspace(xcworkspace)
workspace = Xcodeproj::Workspace.new_from_xcworkspace(xcworkspace)
workspace.projpaths.sort.should == ['ASIHTTPRequest.xcodeproj', 'Pods/Pods.xcodeproj']
project = Pod::Xcode::Project.new(projpath)
project = Xcodeproj::Project.new(projpath)
libPods = project.files.find { |f| f.name == 'libPods.a' }
project.targets.each do |target|
target.buildConfigurations.each do |config|
......
......@@ -4,8 +4,8 @@ require 'mac_bacon'
require 'pathname'
ROOT = Pathname.new(File.expand_path('../../', __FILE__))
gem 'activesupport', '~> 3.1.1'
$:.unshift((ROOT + 'lib').to_s)
$:.unshift File.expand_path('../../external/xcodeproj/lib', __FILE__)
$:.unshift (ROOT + 'lib').to_s
require 'cocoapods'
$:.unshift((ROOT + 'spec').to_s)
......
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
This diff is collapsed.
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
require File.expand_path('../../spec_helper', __FILE__)
describe 'Xcodeproj::Project' do
before do
@project = Xcodeproj::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
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