cocoapods 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -3
- data/lib/cocoapods.rb +1 -1
- data/lib/cocoapods/command/spec.rb +1 -1
- data/lib/cocoapods/installer.rb +30 -6
- data/lib/cocoapods/source.rb +2 -2
- data/lib/cocoapods/specification.rb +71 -3
- data/lib/cocoapods/specification/set.rb +4 -1
- data/lib/cocoapods/xcode/project.rb +60 -19
- data/xcode-project-templates/cocoa-touch-static-library/Pods.xcodeproj/project.pbxproj +14 -0
- metadata +3 -3
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# CocoaPods
|
2
2
|
|
3
|
-
CocoaPods is an Objective-C library package manager. It tries to take
|
4
|
-
hard work of maintaining your dependencies
|
3
|
+
CocoaPods is an Objective-C library dependency/package manager. It tries to take
|
4
|
+
away all hard work of maintaining your dependencies.
|
5
5
|
|
6
6
|
Its goal is to create a more centralized overview of open-source libraries and
|
7
|
-
unify the way in which we deal with them, like RubyGems
|
7
|
+
unify the way in which we deal with them, like [RubyGems](http://rubygems.org)
|
8
8
|
does for the Ruby community.
|
9
9
|
|
10
10
|
CocoaPods will:
|
data/lib/cocoapods.rb
CHANGED
@@ -42,7 +42,7 @@ module Pod
|
|
42
42
|
s.description = 'An optional longer description of #{@name}.'
|
43
43
|
|
44
44
|
# A list of file patterns. If the pattern is a directory then the path will
|
45
|
-
# automatically have '*.{h,m,mm,c,cpp' appended.
|
45
|
+
# automatically have '*.{h,m,mm,c,cpp}' appended.
|
46
46
|
s.source_files = 'Classes', 'Classes/**/*.{h,m}'
|
47
47
|
|
48
48
|
s.xcconfig = { 'OTHER_LDFLAGS' => '-framework SomeRequiredFramework' }
|
data/lib/cocoapods/installer.rb
CHANGED
@@ -17,14 +17,15 @@ module Pod
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def source_files
|
20
|
-
source_files =
|
20
|
+
source_files = {}
|
21
21
|
build_specification_sets.each do |set|
|
22
22
|
spec = set.specification
|
23
|
+
source_files[spec.name] = []
|
23
24
|
spec.source_files.each do |pattern|
|
24
25
|
pattern = spec.pod_destroot + pattern
|
25
26
|
pattern = pattern + '*.{h,m,mm,c,cpp}' if pattern.directory?
|
26
27
|
pattern.glob.each do |file|
|
27
|
-
source_files << file.relative_path_from(config.project_pods_root)
|
28
|
+
source_files[spec.name] << file.relative_path_from(config.project_pods_root)
|
28
29
|
end
|
29
30
|
end
|
30
31
|
end
|
@@ -35,7 +36,7 @@ module Pod
|
|
35
36
|
@xcconfig ||= Xcode::Config.new({
|
36
37
|
# In a workspace this is where the static library headers should be found
|
37
38
|
# We could also make this recursive, but let's let the user decide on that.
|
38
|
-
'USER_HEADER_SEARCH_PATHS' => '$(BUILT_PRODUCTS_DIR)/Pods',
|
39
|
+
'USER_HEADER_SEARCH_PATHS' => '"$(BUILT_PRODUCTS_DIR)/Pods"',
|
39
40
|
# search the user headers
|
40
41
|
'ALWAYS_SEARCH_USER_PATHS' => 'YES',
|
41
42
|
})
|
@@ -46,17 +47,40 @@ module Pod
|
|
46
47
|
end
|
47
48
|
|
48
49
|
def generate_project
|
49
|
-
|
50
|
+
puts "==> Generating Xcode project and xcconfig" unless config.silent?
|
51
|
+
user_header_search_paths = []
|
50
52
|
build_specification_sets.each do |set|
|
51
|
-
|
53
|
+
spec = set.specification
|
54
|
+
xcconfig.merge!(spec.xcconfig)
|
55
|
+
xcodeproj.add_group(spec.name)
|
56
|
+
|
57
|
+
# Only add implementation files to the compile phase
|
58
|
+
spec.implementation_files.each do |file|
|
59
|
+
xcodeproj.add_source_file(file, spec.name)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Add header files to a `copy header build phase` for each destination
|
63
|
+
# directory in the pod's header directory.
|
64
|
+
set.specification.copy_header_mappings.each do |header_dir, files|
|
65
|
+
copy_phase_uuid = xcodeproj.add_copy_header_build_phase(spec.name, header_dir)
|
66
|
+
files.each do |file|
|
67
|
+
xcodeproj.add_source_file(file, spec.name, copy_phase_uuid)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Collect all header search paths
|
72
|
+
user_header_search_paths.concat(spec.user_header_search_paths)
|
52
73
|
end
|
74
|
+
xcconfig.merge!('USER_HEADER_SEARCH_PATHS' => user_header_search_paths.sort.uniq.join(" "))
|
53
75
|
end
|
54
76
|
|
55
77
|
# TODO we need a spec that tests that all dependencies are first downloaded/installed
|
56
78
|
# before #generate_project is called!
|
57
79
|
def install!
|
58
80
|
puts "Installing dependencies of: #{@specification.defined_in_file}" unless config.silent?
|
59
|
-
build_specification_sets.each
|
81
|
+
build_specification_sets.each do |set|
|
82
|
+
set.specification.install!
|
83
|
+
end
|
60
84
|
generate_project
|
61
85
|
xcodeproj.create_in(config.project_pods_root)
|
62
86
|
xcconfig.create_in(config.project_pods_root)
|
data/lib/cocoapods/source.rb
CHANGED
@@ -20,8 +20,8 @@ module Pod
|
|
20
20
|
result = all.map { |s| s.search_by_name(query, full_text_search) }.flatten
|
21
21
|
if result.empty?
|
22
22
|
extra = ", summary, or description" if full_text_search
|
23
|
-
raise(Informative, "Unable to find a pod
|
24
|
-
"#{extra}
|
23
|
+
raise(Informative, "Unable to find a pod with name" \
|
24
|
+
"#{extra} matching `#{query}'")
|
25
25
|
end
|
26
26
|
result
|
27
27
|
end
|
@@ -1,5 +1,9 @@
|
|
1
1
|
module Pod
|
2
|
-
|
2
|
+
def self._eval_podspec(path)
|
3
|
+
eval(path.read, nil, path.to_s)
|
4
|
+
end
|
5
|
+
|
6
|
+
class Specification
|
3
7
|
autoload :Set, 'cocoapods/specification/set'
|
4
8
|
|
5
9
|
def self.from_podfile(path)
|
@@ -12,7 +16,7 @@ module Pod
|
|
12
16
|
end
|
13
17
|
|
14
18
|
def self.from_podspec(path)
|
15
|
-
spec =
|
19
|
+
spec = Pod._eval_podspec(path)
|
16
20
|
spec.defined_in_file = path
|
17
21
|
spec
|
18
22
|
end
|
@@ -95,6 +99,13 @@ module Pod
|
|
95
99
|
end
|
96
100
|
alias_method :library=, :libraries=
|
97
101
|
|
102
|
+
def header_dir=(dir)
|
103
|
+
@header_dir = Pathname.new(dir)
|
104
|
+
end
|
105
|
+
def header_dir
|
106
|
+
@header_dir || pod_destroot_name
|
107
|
+
end
|
108
|
+
|
98
109
|
# Not attributes
|
99
110
|
|
100
111
|
include Config::Mixin
|
@@ -125,7 +136,13 @@ module Pod
|
|
125
136
|
if part_of_other_pod?
|
126
137
|
part_of_specification.pod_destroot
|
127
138
|
else
|
128
|
-
config.project_pods_root +
|
139
|
+
config.project_pods_root + @name
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def pod_destroot_name
|
144
|
+
if root = pod_destroot
|
145
|
+
root.basename
|
129
146
|
end
|
130
147
|
end
|
131
148
|
|
@@ -137,6 +154,57 @@ module Pod
|
|
137
154
|
@name.nil? && @version.nil?
|
138
155
|
end
|
139
156
|
|
157
|
+
# Returns all source files of this pod including header files.
|
158
|
+
def expanded_source_files
|
159
|
+
files = []
|
160
|
+
source_files.each do |pattern|
|
161
|
+
pattern = pod_destroot + pattern
|
162
|
+
pattern = pattern + '*.{h,m,mm,c,cpp}' if pattern.directory?
|
163
|
+
pattern.glob.each do |file|
|
164
|
+
files << file.relative_path_from(config.project_pods_root)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
files
|
168
|
+
end
|
169
|
+
|
170
|
+
def implementation_files
|
171
|
+
expanded_source_files.select { |f| f.extname != '.h' }
|
172
|
+
end
|
173
|
+
|
174
|
+
# Returns only the header files of this pod.
|
175
|
+
def header_files
|
176
|
+
expanded_source_files.select { |f| f.extname == '.h' }
|
177
|
+
end
|
178
|
+
|
179
|
+
# This method takes a header path and returns the location it should have
|
180
|
+
# in the pod's header dir.
|
181
|
+
#
|
182
|
+
# By default all headers are copied to the pod's header dir without any
|
183
|
+
# namespacing. You can, however, override this method in the podspec, or
|
184
|
+
# copy_header_mappings for full control.
|
185
|
+
def copy_header_mapping(from)
|
186
|
+
from.basename
|
187
|
+
end
|
188
|
+
|
189
|
+
# See copy_header_mapping.
|
190
|
+
def copy_header_mappings
|
191
|
+
header_files.inject({}) do |mappings, from|
|
192
|
+
from_without_prefix = from.relative_path_from(pod_destroot_name)
|
193
|
+
to = header_dir + copy_header_mapping(from_without_prefix)
|
194
|
+
(mappings[to.dirname] ||= []) << from
|
195
|
+
mappings
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
# Returns a list of search paths where the pod's headers can be found. This
|
200
|
+
# includes the pod's header dir root and any other directories that might
|
201
|
+
# have been added by overriding the copy_header_mapping/copy_header_mappings
|
202
|
+
# methods.
|
203
|
+
def user_header_search_paths
|
204
|
+
dirs = [header_dir] + copy_header_mappings.keys
|
205
|
+
dirs.map { |dir| %{"$(BUILT_PRODUCTS_DIR)/Pods/#{dir}"} }
|
206
|
+
end
|
207
|
+
|
140
208
|
def to_s
|
141
209
|
if from_podfile?
|
142
210
|
"podfile at `#{@defined_in_file}'"
|
@@ -75,7 +75,10 @@ module Pod
|
|
75
75
|
# Returns Pod::Version instances, for each version directory, sorted from
|
76
76
|
# highest version to lowest.
|
77
77
|
def versions
|
78
|
-
@pod_dir.children.map
|
78
|
+
@pod_dir.children.map do |v|
|
79
|
+
basename = v.basename.to_s
|
80
|
+
Version.new(basename) if v.directory? && basename[0,1] != '.'
|
81
|
+
end.compact.sort.reverse
|
79
82
|
end
|
80
83
|
end
|
81
84
|
end
|
@@ -41,21 +41,27 @@ module Pod
|
|
41
41
|
find_objects(conditions).first
|
42
42
|
end
|
43
43
|
|
44
|
+
IGNORE_GROUPS = ['Pods', 'Frameworks', 'Products', 'Supporting Files']
|
44
45
|
def source_files
|
45
|
-
|
46
|
-
find_objects(
|
47
|
-
if
|
48
|
-
|
49
|
-
|
50
|
-
|
46
|
+
source_files = {}
|
47
|
+
find_objects('isa' => 'PBXGroup').each do |_, object|
|
48
|
+
next if object['name'].nil? || IGNORE_GROUPS.include?(object['name'])
|
49
|
+
source_files[object['name']] = object['children'].map do |uuid|
|
50
|
+
Pathname.new(objects[uuid]['path'])
|
51
|
+
end
|
52
|
+
end
|
53
|
+
source_files
|
51
54
|
end
|
52
55
|
|
53
|
-
def add_source_file(file, compiler_flags = nil)
|
56
|
+
def add_source_file(file, group, phase_uuid = nil, compiler_flags = nil)
|
54
57
|
file_ref_uuid = add_file_reference(file, 'SOURCE_ROOT')
|
55
|
-
|
58
|
+
add_object_to_group(file_ref_uuid, group)
|
56
59
|
if file.extname == '.h'
|
57
60
|
build_file_uuid = add_build_file(file_ref_uuid, "settings" => { "ATTRIBUTES" => ["Public"] })
|
58
|
-
|
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)
|
59
65
|
else
|
60
66
|
extra = compiler_flags ? {"settings" => { "COMPILER_FLAGS" => compiler_flags }} : {}
|
61
67
|
build_file_uuid = add_build_file(file_ref_uuid, extra)
|
@@ -63,6 +69,17 @@ module Pod
|
|
63
69
|
end
|
64
70
|
file_ref_uuid
|
65
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
|
66
83
|
|
67
84
|
def create_in(pods_root)
|
68
85
|
puts " * Copying contents of template directory `#{@template_dir}' to `#{pods_root}'" if config.verbose?
|
@@ -72,6 +89,27 @@ module Pod
|
|
72
89
|
@template.writeToFile(pbxproj.to_s, atomically:true)
|
73
90
|
end
|
74
91
|
|
92
|
+
# TODO add comments, or even constants, describing what these magic numbers are.
|
93
|
+
def add_copy_header_build_phase(name, path)
|
94
|
+
phase_uuid = add_object({
|
95
|
+
"isa" => "PBXCopyFilesBuildPhase",
|
96
|
+
"buildActionMask" => "2147483647",
|
97
|
+
"dstPath" => "$(PUBLIC_HEADERS_FOLDER_PATH)/#{path}",
|
98
|
+
"dstSubfolderSpec" => "16",
|
99
|
+
"files" => [],
|
100
|
+
"name" => "Copy #{name} Public Headers",
|
101
|
+
"runOnlyForDeploymentPostprocessing" => "0",
|
102
|
+
})
|
103
|
+
|
104
|
+
object_uuid, object = objects_by_isa('PBXNativeTarget').first
|
105
|
+
object['buildPhases'] << phase_uuid
|
106
|
+
phase_uuid
|
107
|
+
end
|
108
|
+
|
109
|
+
def objects_by_isa(isa)
|
110
|
+
objects.select { |_, object| object['isa'] == isa }
|
111
|
+
end
|
112
|
+
|
75
113
|
private
|
76
114
|
|
77
115
|
def add_object(object)
|
@@ -88,34 +126,37 @@ module Pod
|
|
88
126
|
"path" => path.to_s,
|
89
127
|
})
|
90
128
|
end
|
91
|
-
|
129
|
+
|
92
130
|
def add_build_file(file_ref_uuid, extra = {})
|
93
131
|
add_object(extra.merge({
|
94
132
|
"isa" => "PBXBuildFile",
|
95
133
|
"fileRef" => file_ref_uuid
|
96
134
|
}))
|
97
135
|
end
|
98
|
-
|
99
|
-
|
100
|
-
|
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
|
101
146
|
object['files'] << build_file_uuid
|
102
147
|
end
|
103
148
|
|
104
|
-
def
|
149
|
+
def add_object_to_group(object_ref_uuid, name)
|
105
150
|
object_uuid, object = objects.find do |_, object|
|
106
151
|
object['isa'] == 'PBXGroup' && object['name'] == name
|
107
152
|
end
|
108
|
-
object['children'] <<
|
153
|
+
object['children'] << object_ref_uuid
|
109
154
|
end
|
110
155
|
|
111
156
|
def objects
|
112
157
|
@template['objects']
|
113
158
|
end
|
114
159
|
|
115
|
-
def objects_by_isa(isa)
|
116
|
-
objects.select { |_, object| object['isa'] == isa }
|
117
|
-
end
|
118
|
-
|
119
160
|
def generate_uuid
|
120
161
|
_uuid = CFUUIDCreate(nil)
|
121
162
|
uuid = CFUUIDCreateString(nil, _uuid)
|
@@ -10,6 +10,19 @@
|
|
10
10
|
515B0FB9141D52E0001DC3E6 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 515B0FB8141D52E0001DC3E6 /* Foundation.framework */; };
|
11
11
|
/* End PBXBuildFile section */
|
12
12
|
|
13
|
+
/* Begin PBXCopyFilesBuildPhase section */
|
14
|
+
82A8B61C142F7EC7006897C9 /* Copy Public Headers */ = {
|
15
|
+
isa = PBXCopyFilesBuildPhase;
|
16
|
+
buildActionMask = 2147483647;
|
17
|
+
dstPath = "$(PUBLIC_HEADERS_FOLDER_PATH)";
|
18
|
+
dstSubfolderSpec = 16;
|
19
|
+
files = (
|
20
|
+
);
|
21
|
+
name = "Copy Public Headers";
|
22
|
+
runOnlyForDeploymentPostprocessing = 0;
|
23
|
+
};
|
24
|
+
/* End PBXCopyFilesBuildPhase section */
|
25
|
+
|
13
26
|
/* Begin PBXFileReference section */
|
14
27
|
515160D0141EC5D100EBB823 /* Pods.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Pods.xcconfig; sourceTree = "<group>"; };
|
15
28
|
515B0FB5141D52E0001DC3E6 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
@@ -92,6 +105,7 @@
|
|
92
105
|
515B0FB1141D52E0001DC3E6 /* Sources */,
|
93
106
|
515B0FB2141D52E0001DC3E6 /* Frameworks */,
|
94
107
|
515B0FB3141D52E0001DC3E6 /* Headers */,
|
108
|
+
82A8B61C142F7EC7006897C9 /* Copy Public Headers */,
|
95
109
|
);
|
96
110
|
buildRules = (
|
97
111
|
);
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 7
|
9
|
+
version: 0.0.7
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Eloy Duran
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-09-17 00:00:00
|
17
|
+
date: 2011-09-17 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|