cocoapods 0.0.8 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +0 -4
- data/lib/cocoapods.rb +18 -15
- data/lib/cocoapods/bridge_support_generator.rb +25 -0
- data/lib/cocoapods/command/install.rb +2 -4
- data/lib/cocoapods/command/spec.rb +1 -1
- data/lib/cocoapods/config.rb +23 -1
- data/lib/cocoapods/downloader.rb +7 -1
- data/lib/cocoapods/executable.rb +2 -0
- data/lib/cocoapods/installer.rb +38 -34
- data/lib/cocoapods/podfile.rb +99 -0
- data/lib/cocoapods/resolver.rb +14 -1
- data/lib/cocoapods/specification.rb +98 -55
- data/lib/cocoapods/specification/set.rb +2 -1
- data/lib/cocoapods/xcode/copy_resources_script.rb +21 -0
- data/lib/cocoapods/xcode/project.rb +266 -111
- data/xcode-project-templates/cocoa-static-library/Pods-Prefix.pch +7 -0
- data/xcode-project-templates/cocoa-static-library/Pods.xcconfig +1 -0
- data/xcode-project-templates/cocoa-static-library/Pods.xcodeproj/project.pbxproj +236 -0
- data/xcode-project-templates/cocoa-static-library/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/xcode-project-templates/cocoa-static-library/PodsResources.sh +8 -0
- data/xcode-project-templates/cocoa-touch-static-library/Pods.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/xcode-project-templates/cocoa-touch-static-library/PodsResources.sh +8 -0
- metadata +17 -10
@@ -32,6 +32,7 @@ module Pod
|
|
32
32
|
"but already activated version `#{required_version}' " \
|
33
33
|
"by #{@required_by.join(', ')}."
|
34
34
|
end
|
35
|
+
@specification = nil
|
35
36
|
@required_by << specification
|
36
37
|
end
|
37
38
|
|
@@ -54,7 +55,7 @@ module Pod
|
|
54
55
|
end
|
55
56
|
|
56
57
|
def specification
|
57
|
-
Specification.
|
58
|
+
@specification ||= Specification.from_file(specification_path)
|
58
59
|
end
|
59
60
|
|
60
61
|
# Return the first version that matches the current dependency.
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Pod
|
2
|
+
module Xcode
|
3
|
+
class CopyResourcesScript
|
4
|
+
attr_reader :resources
|
5
|
+
|
6
|
+
# A list of files relative to the project pods root.
|
7
|
+
def initialize(resources)
|
8
|
+
@resources = resources
|
9
|
+
end
|
10
|
+
|
11
|
+
def create_in(root)
|
12
|
+
return if @resources.empty?
|
13
|
+
(root + 'PodsResources.sh').open('a') do |script|
|
14
|
+
@resources.each do |resource|
|
15
|
+
script.puts "install_resource '#{resource}'"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,8 +1,220 @@
|
|
1
1
|
framework 'Foundation'
|
2
|
+
require 'fileutils'
|
2
3
|
|
3
4
|
module Pod
|
4
5
|
module Xcode
|
5
6
|
class Project
|
7
|
+
class PBXObject
|
8
|
+
def self.attributes_accessor(*names)
|
9
|
+
names.each do |name|
|
10
|
+
name = name.to_s
|
11
|
+
define_method(name) { @attributes[name] }
|
12
|
+
define_method("#{name}=") { |value| @attributes[name] = value }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.isa
|
17
|
+
@isa ||= name.split('::').last
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :uuid, :attributes
|
21
|
+
attributes_accessor :isa, :name
|
22
|
+
|
23
|
+
def initialize(project, uuid, attributes)
|
24
|
+
@project, @uuid, @attributes = project, uuid || generate_uuid, attributes
|
25
|
+
self.isa ||= self.class.isa
|
26
|
+
end
|
27
|
+
|
28
|
+
def inspect
|
29
|
+
"#<#{isa} UUID: `#{uuid}', name: `#{name}'>"
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def generate_uuid
|
35
|
+
_uuid = CFUUIDCreate(nil)
|
36
|
+
uuid = CFUUIDCreateString(nil, _uuid)
|
37
|
+
CFRelease(_uuid)
|
38
|
+
CFMakeCollectable(uuid)
|
39
|
+
# Xcode's version is actually shorter, not worrying about collisions too much right now.
|
40
|
+
uuid.gsub('-', '')[0..23]
|
41
|
+
end
|
42
|
+
|
43
|
+
def list_by_class(uuids, klass, scoped = nil)
|
44
|
+
unless scoped
|
45
|
+
scoped = uuids.map { |uuid| @project.objects[uuid] }.select { |o| o.is_a?(klass) }
|
46
|
+
end
|
47
|
+
PBXObjectList.new(klass, @project, scoped) do |object|
|
48
|
+
# Add the uuid of a newly created object to the uuids list
|
49
|
+
uuids << object.uuid
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class PBXGroup < PBXObject
|
55
|
+
attributes_accessor :sourceTree, :children
|
56
|
+
|
57
|
+
def initialize(project, uuid, attributes)
|
58
|
+
super
|
59
|
+
self.sourceTree ||= '<group>'
|
60
|
+
self.children ||= []
|
61
|
+
end
|
62
|
+
|
63
|
+
def files
|
64
|
+
list_by_class(children, PBXFileReference)
|
65
|
+
end
|
66
|
+
|
67
|
+
def source_files
|
68
|
+
list_by_class(children, PBXFileReference, files.select { |file| !file.build_file.nil? })
|
69
|
+
end
|
70
|
+
|
71
|
+
def groups
|
72
|
+
list_by_class(children, PBXGroup)
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_source_file(path, copy_header_phase = nil, compiler_flags = nil)
|
76
|
+
file = files.new('path' => path.to_s)
|
77
|
+
build_file = file.build_file
|
78
|
+
if path.extname == '.h'
|
79
|
+
build_file.settings = { 'ATTRIBUTES' => ["Public"] }
|
80
|
+
# Working around a bug in Xcode 4.2 betas, remove this once the Xcode bug is fixed:
|
81
|
+
# https://github.com/alloy/cocoapods/issues/13
|
82
|
+
#phase = copy_header_phase || @project.headers_build_phases.first
|
83
|
+
phase = copy_header_phase || @project.copy_files_build_phases.first # TODO is this really needed?
|
84
|
+
phase.files << build_file
|
85
|
+
else
|
86
|
+
build_file.settings = { 'COMPILER_FLAGS' => compiler_flags } if compiler_flags
|
87
|
+
@project.source_build_phase.files << build_file
|
88
|
+
end
|
89
|
+
file
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class PBXFileReference < PBXObject
|
94
|
+
attributes_accessor :path, :sourceTree
|
95
|
+
|
96
|
+
def initialize(project, uuid, attributes)
|
97
|
+
is_new = uuid.nil?
|
98
|
+
super
|
99
|
+
self.name ||= pathname.basename.to_s
|
100
|
+
self.sourceTree ||= 'SOURCE_ROOT'
|
101
|
+
if is_new
|
102
|
+
@project.build_files.new.file = self
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def pathname
|
107
|
+
Pathname.new(path)
|
108
|
+
end
|
109
|
+
|
110
|
+
def build_file
|
111
|
+
@project.build_files.find { |o| o.fileRef == uuid }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
class PBXBuildFile < PBXObject
|
116
|
+
attributes_accessor :fileRef, :settings
|
117
|
+
|
118
|
+
# Takes a PBXFileReference instance and assigns its uuid to the fileRef attribute.
|
119
|
+
def file=(file)
|
120
|
+
self.fileRef = file.uuid
|
121
|
+
end
|
122
|
+
|
123
|
+
# Returns a PBXFileReference instance corresponding to the uuid in the fileRef attribute.
|
124
|
+
def file
|
125
|
+
project.objects[fileRef]
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
class PBXBuildPhase < PBXObject
|
130
|
+
attributes_accessor :files
|
131
|
+
alias_method :file_uuids, :files
|
132
|
+
alias_method :file_uuids=, :files=
|
133
|
+
|
134
|
+
def initialize(project, uuid, attributes)
|
135
|
+
super
|
136
|
+
self.file_uuids ||= []
|
137
|
+
end
|
138
|
+
|
139
|
+
def files
|
140
|
+
list_by_class(file_uuids, PBXBuildFile)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
class PBXSourcesBuildPhase < PBXBuildPhase; end
|
144
|
+
class PBXCopyFilesBuildPhase < PBXBuildPhase; end
|
145
|
+
|
146
|
+
class PBXNativeTarget < PBXObject
|
147
|
+
attributes_accessor :buildPhases
|
148
|
+
alias_method :build_phase_uuids, :buildPhases
|
149
|
+
alias_method :build_phase_uuids=, :buildPhases=
|
150
|
+
|
151
|
+
def buildPhases
|
152
|
+
list_by_class(build_phase_uuids, PBXBuildPhase)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Missing constants that begin with either `PBX' or `XC' are assumed to be
|
157
|
+
# valid classes in a Xcode project. A new PBXObject subclass is created
|
158
|
+
# for the constant and returned.
|
159
|
+
def self.const_missing(name)
|
160
|
+
if name =~ /^(PBX|XC)/
|
161
|
+
klass = Class.new(PBXObject)
|
162
|
+
const_set(name, klass)
|
163
|
+
klass
|
164
|
+
else
|
165
|
+
super
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
class PBXObjectList
|
170
|
+
include Enumerable
|
171
|
+
|
172
|
+
def initialize(represented_class, project, scoped, &new_object_callback)
|
173
|
+
@represented_class = represented_class
|
174
|
+
@project = project
|
175
|
+
@scoped_hash = scoped.is_a?(Array) ? scoped.inject({}) { |h, o| h[o.uuid] = o.attributes; h } : scoped
|
176
|
+
@callback = new_object_callback
|
177
|
+
end
|
178
|
+
|
179
|
+
def [](uuid)
|
180
|
+
if hash = @scoped_hash[uuid]
|
181
|
+
Project.const_get(hash['isa']).new(@project, uuid, hash)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def add(klass, hash = {})
|
186
|
+
object = klass.new(@project, nil, hash)
|
187
|
+
@project.objects_hash[object.uuid] = object.attributes
|
188
|
+
object
|
189
|
+
end
|
190
|
+
|
191
|
+
def new(hash = {})
|
192
|
+
object = add(@represented_class, hash)
|
193
|
+
@callback.call(object) if @callback
|
194
|
+
object
|
195
|
+
end
|
196
|
+
|
197
|
+
def <<(object)
|
198
|
+
@callback.call(object) if @callback
|
199
|
+
end
|
200
|
+
|
201
|
+
def each
|
202
|
+
@scoped_hash.keys.each do |uuid|
|
203
|
+
yield self[uuid]
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
def inspect
|
208
|
+
"<PBXObjectList: #{map(&:inspect)}>"
|
209
|
+
end
|
210
|
+
|
211
|
+
# Only makes sense on the list that has the full objects_hash as its scoped hash.
|
212
|
+
def select_by_class(klass)
|
213
|
+
scoped = @project.objects_hash.select { |_, attr| attr['isa'] == klass.isa }
|
214
|
+
PBXObjectList.new(klass, @project, scoped)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
6
218
|
include Pod::Config::Mixin
|
7
219
|
|
8
220
|
# TODO this is a workaround for an issue with MacRuby with compiled files
|
@@ -12,9 +224,15 @@ module Pod
|
|
12
224
|
file = $LOADED_FEATURES.find { |file| file =~ %r{cocoapods/xcode/project\.rbo?$} }
|
13
225
|
TEMPLATES_DIR = Pathname.new(File.expand_path('../../../../xcode-project-templates', file))
|
14
226
|
|
15
|
-
|
16
|
-
|
17
|
-
|
227
|
+
def self.static_library(platform)
|
228
|
+
case platform
|
229
|
+
when :osx
|
230
|
+
new TEMPLATES_DIR + 'cocoa-static-library'
|
231
|
+
when :ios
|
232
|
+
new TEMPLATES_DIR + 'cocoa-touch-static-library'
|
233
|
+
else
|
234
|
+
raise "No Xcode project template exists for the platform `#{platform.inspect}'"
|
235
|
+
end
|
18
236
|
end
|
19
237
|
|
20
238
|
def initialize(template_dir)
|
@@ -31,56 +249,58 @@ module Pod
|
|
31
249
|
@template
|
32
250
|
end
|
33
251
|
|
34
|
-
def
|
35
|
-
objects
|
36
|
-
|
37
|
-
|
252
|
+
def objects_hash
|
253
|
+
@template['objects']
|
254
|
+
end
|
255
|
+
|
256
|
+
def objects
|
257
|
+
@objects ||= PBXObjectList.new(PBXObject, self, objects_hash)
|
258
|
+
end
|
259
|
+
|
260
|
+
def groups
|
261
|
+
objects.select_by_class(PBXGroup)
|
262
|
+
end
|
263
|
+
|
264
|
+
# Shortcut access to the `Pods' PBXGroup.
|
265
|
+
def pods
|
266
|
+
groups.find { |g| g.name == 'Pods' }
|
267
|
+
end
|
268
|
+
|
269
|
+
# Adds a group as child to the `Pods' group.
|
270
|
+
def add_pod_group(name)
|
271
|
+
pods.groups.new('name' => name)
|
272
|
+
end
|
273
|
+
|
274
|
+
def files
|
275
|
+
objects.select_by_class(PBXFileReference)
|
38
276
|
end
|
39
277
|
|
40
|
-
def
|
41
|
-
|
278
|
+
def build_files
|
279
|
+
objects.select_by_class(PBXBuildFile)
|
280
|
+
end
|
281
|
+
|
282
|
+
def source_build_phase
|
283
|
+
objects.find { |o| o.is_a?(PBXSourcesBuildPhase) }
|
284
|
+
end
|
285
|
+
|
286
|
+
def copy_files_build_phases
|
287
|
+
objects.select_by_class(PBXCopyFilesBuildPhase)
|
288
|
+
end
|
289
|
+
|
290
|
+
def targets
|
291
|
+
objects.select_by_class(PBXNativeTarget)
|
42
292
|
end
|
43
293
|
|
44
294
|
IGNORE_GROUPS = ['Pods', 'Frameworks', 'Products', 'Supporting Files']
|
45
295
|
def source_files
|
46
296
|
source_files = {}
|
47
|
-
|
48
|
-
next if
|
49
|
-
source_files[
|
50
|
-
Pathname.new(objects[uuid]['path'])
|
51
|
-
end
|
297
|
+
groups.each do |group|
|
298
|
+
next if group.name.nil? || IGNORE_GROUPS.include?(group.name)
|
299
|
+
source_files[group.name] = group.source_files.map(&:pathname)
|
52
300
|
end
|
53
301
|
source_files
|
54
302
|
end
|
55
303
|
|
56
|
-
def add_source_file(file, group, phase_uuid = nil, compiler_flags = nil)
|
57
|
-
file_ref_uuid = add_file_reference(file, 'SOURCE_ROOT')
|
58
|
-
add_object_to_group(file_ref_uuid, group)
|
59
|
-
if file.extname == '.h'
|
60
|
-
build_file_uuid = add_build_file(file_ref_uuid, "settings" => { "ATTRIBUTES" => ["Public"] })
|
61
|
-
# Working around a bug in Xcode 4.2 betas, remove this once the Xcode bug is fixed:
|
62
|
-
# https://github.com/alloy/cocoapods/issues/13
|
63
|
-
#add_file_to_list('PBXHeadersBuildPhase', build_file_uuid)
|
64
|
-
add_file_to_list('PBXCopyFilesBuildPhase', build_file_uuid, phase_uuid)
|
65
|
-
else
|
66
|
-
extra = compiler_flags ? {"settings" => { "COMPILER_FLAGS" => compiler_flags }} : {}
|
67
|
-
build_file_uuid = add_build_file(file_ref_uuid, extra)
|
68
|
-
add_file_to_list('PBXSourcesBuildPhase', build_file_uuid)
|
69
|
-
end
|
70
|
-
file_ref_uuid
|
71
|
-
end
|
72
|
-
|
73
|
-
def add_group(name)
|
74
|
-
group_uuid = add_object({
|
75
|
-
"name" => name,
|
76
|
-
"isa" => "PBXGroup",
|
77
|
-
"sourceTree" => "<group>",
|
78
|
-
"children" => []
|
79
|
-
})
|
80
|
-
add_object_to_group(group_uuid, 'Pods')
|
81
|
-
group_uuid
|
82
|
-
end
|
83
|
-
|
84
304
|
def create_in(pods_root)
|
85
305
|
puts " * Copying contents of template directory `#{@template_dir}' to `#{pods_root}'" if config.verbose?
|
86
306
|
FileUtils.cp_r("#{@template_dir}/.", pods_root)
|
@@ -91,83 +311,18 @@ module Pod
|
|
91
311
|
|
92
312
|
# TODO add comments, or even constants, describing what these magic numbers are.
|
93
313
|
def add_copy_header_build_phase(name, path)
|
94
|
-
|
95
|
-
"isa" => "PBXCopyFilesBuildPhase",
|
314
|
+
phase = copy_files_build_phases.new({
|
96
315
|
"buildActionMask" => "2147483647",
|
97
316
|
"dstPath" => "$(PUBLIC_HEADERS_FOLDER_PATH)/#{path}",
|
98
317
|
"dstSubfolderSpec" => "16",
|
99
|
-
"files" => [],
|
100
318
|
"name" => "Copy #{name} Public Headers",
|
101
319
|
"runOnlyForDeploymentPostprocessing" => "0",
|
102
320
|
})
|
103
|
-
|
104
|
-
|
105
|
-
object['buildPhases'] << phase_uuid
|
106
|
-
phase_uuid
|
107
|
-
end
|
108
|
-
|
109
|
-
def objects_by_isa(isa)
|
110
|
-
objects.select { |_, object| object['isa'] == isa }
|
321
|
+
targets.first.buildPhases << phase
|
322
|
+
phase
|
111
323
|
end
|
112
324
|
|
113
|
-
|
114
|
-
|
115
|
-
def add_object(object)
|
116
|
-
uuid = generate_uuid
|
117
|
-
objects[uuid] = object
|
118
|
-
uuid
|
119
|
-
end
|
120
|
-
|
121
|
-
def add_file_reference(path, source_tree)
|
122
|
-
add_object({
|
123
|
-
"name" => path.basename.to_s,
|
124
|
-
"isa" => "PBXFileReference",
|
125
|
-
"sourceTree" => source_tree,
|
126
|
-
"path" => path.to_s,
|
127
|
-
})
|
128
|
-
end
|
129
|
-
|
130
|
-
def add_build_file(file_ref_uuid, extra = {})
|
131
|
-
add_object(extra.merge({
|
132
|
-
"isa" => "PBXBuildFile",
|
133
|
-
"fileRef" => file_ref_uuid
|
134
|
-
}))
|
135
|
-
end
|
136
|
-
|
137
|
-
# TODO refactor to create PBX object classes and make this take aither a uuid or a class instead of both.
|
138
|
-
def add_file_to_list(isa, build_file_uuid, phase_uuid = nil)
|
139
|
-
objects = objects_by_isa(isa)
|
140
|
-
_ = object = nil
|
141
|
-
if phase_uuid.nil?
|
142
|
-
_, object = objects.first
|
143
|
-
else
|
144
|
-
object = objects[phase_uuid]
|
145
|
-
end
|
146
|
-
object['files'] << build_file_uuid
|
147
|
-
end
|
148
|
-
|
149
|
-
def add_object_to_group(object_ref_uuid, name)
|
150
|
-
object_uuid, object = objects.find do |_, object|
|
151
|
-
object['isa'] == 'PBXGroup' && object['name'] == name
|
152
|
-
end
|
153
|
-
object['children'] << object_ref_uuid
|
154
|
-
end
|
155
|
-
|
156
|
-
def objects
|
157
|
-
@template['objects']
|
158
|
-
end
|
159
|
-
|
160
|
-
def generate_uuid
|
161
|
-
_uuid = CFUUIDCreate(nil)
|
162
|
-
uuid = CFUUIDCreateString(nil, _uuid)
|
163
|
-
CFRelease(_uuid)
|
164
|
-
CFMakeCollectable(uuid)
|
165
|
-
# Xcode's version is actually shorter, not worrying about collisions too much right now.
|
166
|
-
uuid.gsub('-', '')[0..23]
|
167
|
-
end
|
168
|
-
|
169
|
-
public
|
170
|
-
|
325
|
+
# A silly hack to pretty print the objects hash from MacRuby.
|
171
326
|
def pretty_print
|
172
327
|
puts `ruby -r pp -e 'pp(#{@template.inspect})'`
|
173
328
|
end
|