cocoapods 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. data/CHANGELOG.md +129 -0
  2. data/README.md +58 -54
  3. data/bin/pod +1 -0
  4. data/lib/cocoapods.rb +7 -10
  5. data/lib/cocoapods/bridge_support_generator.rb +3 -5
  6. data/lib/cocoapods/command.rb +1 -1
  7. data/lib/cocoapods/command/repo.rb +22 -12
  8. data/lib/cocoapods/command/setup.rb +14 -3
  9. data/lib/cocoapods/command/spec.rb +8 -7
  10. data/lib/cocoapods/config.rb +2 -2
  11. data/lib/cocoapods/dependency.rb +65 -3
  12. data/lib/cocoapods/downloader.rb +7 -2
  13. data/lib/cocoapods/installer.rb +244 -99
  14. data/lib/cocoapods/podfile.rb +145 -10
  15. data/lib/cocoapods/resolver.rb +10 -6
  16. data/lib/cocoapods/specification.rb +13 -12
  17. data/lib/cocoapods/specification/set.rb +34 -0
  18. data/lib/cocoapods/xcodeproj_ext.rb +99 -0
  19. metadata +32 -35
  20. data/lib/cocoapods/project_template.rb +0 -35
  21. data/lib/cocoapods/xcode/config.rb +0 -33
  22. data/lib/cocoapods/xcode/copy_resources_script.rb +0 -21
  23. data/lib/cocoapods/xcode/project.rb +0 -356
  24. data/lib/cocoapods/xcode/workspace.rb +0 -56
  25. data/xcode-project-templates/cocoa-static-library/Pods-Prefix.pch +0 -7
  26. data/xcode-project-templates/cocoa-static-library/Pods.xcconfig +0 -1
  27. data/xcode-project-templates/cocoa-static-library/Pods.xcodeproj/project.pbxproj +0 -236
  28. data/xcode-project-templates/cocoa-static-library/PodsResources.sh +0 -8
  29. data/xcode-project-templates/cocoa-touch-static-library/Pods-Prefix.pch +0 -7
  30. data/xcode-project-templates/cocoa-touch-static-library/Pods.xcconfig +0 -1
  31. data/xcode-project-templates/cocoa-touch-static-library/Pods.xcodeproj/project.pbxproj +0 -248
  32. data/xcode-project-templates/cocoa-touch-static-library/PodsResources.sh +0 -8
@@ -1,5 +1,23 @@
1
1
  module Pod
2
2
  class Podfile
3
+ class TargetDefinition
4
+ attr_reader :name, :parent, :target_dependencies
5
+
6
+ def initialize(name, parent = nil)
7
+ @name, @parent, @target_dependencies = name, parent, []
8
+ end
9
+
10
+ def lib_name
11
+ name == :default ? "Pods" : "Pods-#{name}"
12
+ end
13
+
14
+ # Returns *all* dependencies of this target, not only the target specific
15
+ # ones in `target_dependencies`.
16
+ def dependencies
17
+ @target_dependencies + (@parent ? @parent.dependencies : [])
18
+ end
19
+ end
20
+
3
21
  def self.from_file(path)
4
22
  podfile = Podfile.new do
5
23
  eval(path.read, nil, path.to_s)
@@ -9,8 +27,10 @@ module Pod
9
27
  podfile
10
28
  end
11
29
 
30
+ include Config::Mixin
31
+
12
32
  def initialize(&block)
13
- @dependencies = []
33
+ @target_definitions = { :default => (@target_definition = TargetDefinition.new(:default)) }
14
34
  instance_eval(&block)
15
35
  end
16
36
 
@@ -57,12 +77,68 @@ module Pod
57
77
  #
58
78
  # * http://semver.org
59
79
  # * http://docs.rubygems.org/read/chapter/7
60
- def dependency(name, *version_requirements)
61
- @dependencies << Dependency.new(name, *version_requirements)
80
+ #
81
+ #
82
+ # ## Dependency on a library, outside those available in a spec repo.
83
+ #
84
+ # ### From a podspec in the root of a library repo.
85
+ #
86
+ # Sometimes you may want to use the bleeding edge version of a Pod. Or a
87
+ # specific revision. If this is the case, you can specify that with your
88
+ # dependency declaration.
89
+ #
90
+ #
91
+ # To use the `master` branch of the repo:
92
+ #
93
+ # dependency 'TTTFormatterKit', :git => 'https://github.com/gowalla/AFNetworking.git'
94
+ #
95
+ #
96
+ # Or specify a commit:
97
+ #
98
+ # dependency 'TTTFormatterKit', :git => 'https://github.com/gowalla/AFNetworking.git', :commit => '082f8319af'
99
+ #
100
+ #
101
+ # It is important to note, though, that this means that the version will
102
+ # have to satisfy any other dependencies on the Pod by other Pods.
103
+ #
104
+ #
105
+ # The `podspec` file is expected to be in the root of the repo, if this
106
+ # library does not have a `podspec` file in its repo yet, you will have to
107
+ # use one of the approaches outlined in the sections below.
108
+ #
109
+ #
110
+ # ### From a podspec outside a spec repo, for a library without podspec.
111
+ #
112
+ # If a podspec is available from another source outside of the library’s
113
+ # repo. Consider, for instance, a podpsec available via HTTP:
114
+ #
115
+ # dependency 'JSONKit', :podspec => 'https://raw.github.com/gist/1346394/1d26570f68ca27377a27430c65841a0880395d72/JSONKit.podspec'
116
+ #
117
+ #
118
+ # ### For a library without any available podspec
119
+ #
120
+ # Finally, if no man alive has created a podspec, for the library you want
121
+ # to use, yet, you will have to specify the library yourself.
122
+ #
123
+ #
124
+ # When you omit arguments and pass a block to `dependency`, an instance of
125
+ # Pod::Specification is yielded to the block. This is the same class which
126
+ # is normally used to specify a Pod.
127
+ #
128
+ # dependency do |spec|
129
+ # spec.name = 'JSONKit'
130
+ # spec.version = '1.4'
131
+ # spec.source = { :git => 'https://github.com/johnezang/JSONKit.git', :tag => 'v1.4' }
132
+ # spec.source_files = 'JSONKit.*'
133
+ # end
134
+ #
135
+ #
136
+ # For more info on the definition of a Pod::Specification see:
137
+ # https://github.com/CocoaPods/CocoaPods/wiki/A-pod-specification
138
+ def dependency(*name_and_version_requirements, &block)
139
+ @target_definition.target_dependencies << Dependency.new(*name_and_version_requirements, &block)
62
140
  end
63
141
 
64
- attr_reader :dependencies
65
-
66
142
  # Specifies that a BridgeSupport metadata should be generated from the
67
143
  # headers of all installed Pods.
68
144
  #
@@ -72,27 +148,86 @@ module Pod
72
148
  @generate_bridge_support = true
73
149
  end
74
150
 
75
- # This is to be compatible with a Specification for use in the Installer and
76
- # Resolver.
151
+ # Defines a new static library target and scopes dependencies defined from
152
+ # the given block. The target will by default include the dependencies
153
+ # defined outside of the block, unless the `:exclusive => true` option is
154
+ # given.
155
+ #
156
+ # Consider the following Podfile:
157
+ #
158
+ # dependency 'ASIHTTPRequest'
159
+ #
160
+ # target :debug do
161
+ # dependency 'SSZipArchive'
162
+ # end
163
+ #
164
+ # target :test, :exclusive => true do
165
+ # dependency 'JSONKit'
166
+ # end
167
+ #
168
+ # This Podfile defines three targets. The first one is the `:default` target,
169
+ # which produces the `libPods.a` file. The second and third are the `:debug`
170
+ # and `:test` ones, which produce the `libPods-debug.a` and `libPods-test.a`
171
+ # files.
172
+ #
173
+ # The `:default` target has only one dependency (ASIHTTPRequest), whereas the
174
+ # `:debug` target has two (ASIHTTPRequest, SSZipArchive). The `:test` target,
175
+ # however, is an exclusive target which means it will only have one
176
+ # dependency (JSONKit).
177
+ def target(name, options = {})
178
+ parent = @target_definition
179
+ @target_definitions[name] = @target_definition = TargetDefinition.new(name, options[:exclusive] ? nil : parent)
180
+ yield
181
+ ensure
182
+ @target_definition = parent
183
+ end
184
+
185
+ # This hook allows you to make any last changes to the generated Xcode project
186
+ # before it is written to disk, or any other tasks you might want to perform.
187
+ #
188
+ # For instance, say you'd want to customize the `OTHER_LDFLAGS` of all targets:
189
+ #
190
+ # post_install do |installer|
191
+ # installer.project.targets.each do |target|
192
+ # target.buildConfigurations.each do |config|
193
+ # config.buildSettings['GCC_ENABLE_OBJC_GC'] = 'supported'
194
+ # end
195
+ # end
196
+ # end
197
+ def post_install(&block)
198
+ @post_install_callback = block
199
+ end
200
+
201
+
202
+ # Not attributes
77
203
 
78
204
  def podfile?
79
205
  true
80
206
  end
81
207
 
82
208
  attr_accessor :defined_in_file
209
+ attr_reader :target_definitions
210
+
211
+ def dependencies
212
+ @target_definitions.values.map(&:target_dependencies).flatten
213
+ end
214
+
215
+ def dependency_by_name(name)
216
+ dependencies.find { |d| d.name == name }
217
+ end
83
218
 
84
219
  def generate_bridge_support?
85
220
  @generate_bridge_support
86
221
  end
87
222
 
88
- def dependency_by_name(name)
89
- @dependencies.find { |d| d.name == name }
223
+ def post_install!(installer)
224
+ @post_install_callback.call(installer) if @post_install_callback
90
225
  end
91
226
 
92
227
  def validate!
93
228
  lines = []
94
229
  lines << "* the `platform` attribute should be either `:osx` or `:ios`" unless [:osx, :ios].include?(@platform)
95
- lines << "* no dependencies were specified, which is, well, kinda pointless" if @dependencies.empty?
230
+ lines << "* no dependencies were specified, which is, well, kinda pointless" if dependencies.empty?
96
231
  raise(Informative, (["The Podfile at `#{@defined_in_file}' is invalid:"] + lines).join("\n")) unless lines.empty?
97
232
  end
98
233
  end
@@ -1,17 +1,17 @@
1
1
  module Pod
2
2
  class Resolver
3
- def initialize(specification)
4
- @specification = specification
3
+ def initialize(specification, dependencies = nil)
4
+ @specification, @dependencies = specification, dependencies || specification.dependencies
5
5
  end
6
6
 
7
7
  def resolve
8
8
  @sets = []
9
- find_dependency_sets(@specification)
9
+ find_dependency_sets(@specification, @dependencies)
10
10
  @sets
11
11
  end
12
12
 
13
- def find_dependency_sets(specification)
14
- specification.dependencies.each do |dependency|
13
+ def find_dependency_sets(specification, dependencies = nil)
14
+ (dependencies || specification.dependencies).each do |dependency|
15
15
  set = find_dependency_set(dependency)
16
16
  set.required_by(specification)
17
17
  unless @sets.include?(set)
@@ -23,7 +23,11 @@ module Pod
23
23
  end
24
24
 
25
25
  def find_dependency_set(dependency)
26
- Source.search(dependency)
26
+ if external_spec = dependency.specification
27
+ Specification::Set::External.new(external_spec)
28
+ else
29
+ Source.search(dependency)
30
+ end
27
31
  end
28
32
 
29
33
  def validate_platform!(set)
@@ -10,6 +10,9 @@ module Pod
10
10
 
11
11
  # The file is expected to define and return a Pods::Specification.
12
12
  def self.from_file(path)
13
+ unless path.exist?
14
+ raise Informative, "No podspec exists at path `#{path}'."
15
+ end
13
16
  spec = Pod._eval_podspec(path)
14
17
  spec.defined_in_file = path
15
18
  spec
@@ -19,7 +22,7 @@ module Pod
19
22
 
20
23
  def initialize
21
24
  @dependencies = []
22
- @xcconfig = Xcode::Config.new
25
+ @xcconfig = Xcodeproj::Config.new
23
26
  yield self if block_given?
24
27
  end
25
28
 
@@ -29,6 +32,7 @@ module Pod
29
32
  attr_accessor :homepage
30
33
  attr_accessor :description
31
34
  attr_accessor :source
35
+ attr_accessor :license
32
36
 
33
37
  attr_reader :version
34
38
  def version=(version)
@@ -241,7 +245,7 @@ module Pod
241
245
  end
242
246
 
243
247
  def to_s
244
- "`#{name}' version `#{version}'"
248
+ "#{name} (#{version})"
245
249
  end
246
250
 
247
251
  def inspect
@@ -272,8 +276,6 @@ module Pod
272
276
 
273
277
  # Install and download hooks
274
278
 
275
- # Places the activated specification in the project's pods directory.
276
- #
277
279
  # Override this if you need to perform work before or after activating the
278
280
  # pod. Eg:
279
281
  #
@@ -284,12 +286,10 @@ module Pod
284
286
  # # post-install
285
287
  # end
286
288
  # end
289
+ #
290
+ # TODO Do we really need this now that we don’t install the podspec files anymore?
287
291
  def install!
288
292
  puts "==> Installing: #{self}" unless config.silent?
289
- config.project_pods_root.mkpath
290
- require 'fileutils'
291
- FileUtils.cp(defined_in_file, config.project_pods_root)
292
-
293
293
  # In case this spec is part of another pod's source, we need to dowload
294
294
  # the other pod's source.
295
295
  (part_of_specification || self).download_if_necessary!
@@ -325,17 +325,18 @@ module Pod
325
325
 
326
326
  # This is a convenience method which gets called after all pods have been
327
327
  # downloaded, installed, and the Xcode project and related files have been
328
- # generated. Override this to, for instance, add to the prefix header:
328
+ # generated. (It receives the Pod::Installer::Target instance for the current
329
+ # target.) Override this to, for instance, add to the prefix header:
329
330
  #
330
331
  # Pod::Spec.new do |s|
331
- # def s.post_install
332
- # prefix_header = config.project_pods_root + 'Pods-Prefix.pch'
332
+ # def s.post_install(target)
333
+ # prefix_header = config.project_pods_root + target.prefix_header_filename
333
334
  # prefix_header.open('a') do |file|
334
335
  # file.puts(%{#ifdef __OBJC__\n#import "SSToolkitDefines.h"\n#endif})
335
336
  # end
336
337
  # end
337
338
  # end
338
- def post_install
339
+ def post_install(target)
339
340
  end
340
341
 
341
342
  end
@@ -81,6 +81,40 @@ module Pod
81
81
  Version.new(basename) if v.directory? && basename[0,1] != '.'
82
82
  end.compact.sort.reverse
83
83
  end
84
+
85
+ class External < Set
86
+ def initialize(specification)
87
+ @specification = specification
88
+ @required_by = []
89
+ end
90
+
91
+ def name
92
+ @specification.name
93
+ end
94
+
95
+ def required_by(specification)
96
+ before = @specification
97
+ super(specification)
98
+ ensure
99
+ @specification = before
100
+ end
101
+
102
+ def only_part_of_other_pod?
103
+ false
104
+ end
105
+
106
+ def specification_path
107
+ raise "specification_path"
108
+ end
109
+
110
+ def specification
111
+ @specification
112
+ end
113
+
114
+ def versions
115
+ [@specification.version]
116
+ end
117
+ end
84
118
  end
85
119
  end
86
120
  end
@@ -0,0 +1,99 @@
1
+ require 'xcodeproj'
2
+
3
+ module Xcodeproj
4
+ class Project
5
+ # Shortcut access to the `Pods' PBXGroup.
6
+ def pods
7
+ groups.find { |g| g.name == 'Pods' } || groups.new({ 'name' => 'Pods' })
8
+ end
9
+
10
+ # Adds a group as child to the `Pods' group.
11
+ def add_pod_group(name)
12
+ pods.groups.new('name' => name)
13
+ end
14
+
15
+ class PBXCopyFilesBuildPhase
16
+ def self.new_pod_dir(project, pod_name, path)
17
+ new(project, nil, {
18
+ "dstPath" => "$(PRODUCT_NAME)/#{path}",
19
+ "name" => "Copy #{pod_name} Public Headers",
20
+ })
21
+ end
22
+ end
23
+
24
+ def self.for_platform(platform)
25
+ project = Xcodeproj::Project.new
26
+ project.main_group << project.groups.new({ 'name' => 'Pods' })
27
+ framework = project.add_system_framework(platform == :ios ? 'Foundation' : 'Cocoa')
28
+ framework.group = project.groups.new({ 'name' => 'Frameworks' })
29
+ project.main_group << framework.group
30
+ products = project.groups.new({ 'name' => 'Products' })
31
+ project.main_group << products
32
+ project.root_object.products = products
33
+
34
+ project.root_object.attributes['buildConfigurationList'] = project.objects.add(Xcodeproj::Project::XCConfigurationList, {
35
+ 'defaultConfigurationIsVisible' => '0',
36
+ 'defaultConfigurationName' => 'Release',
37
+ 'buildConfigurations' => [
38
+ project.objects.add(Xcodeproj::Project::XCBuildConfiguration, {
39
+ 'name' => 'Debug',
40
+ 'buildSettings' => build_settings(platform, :debug)
41
+ }),
42
+ project.objects.add(Xcodeproj::Project::XCBuildConfiguration, {
43
+ 'name' => 'Release',
44
+ 'buildSettings' => build_settings(platform, :release)
45
+ })
46
+ ].map(&:uuid)
47
+ }).uuid
48
+ project
49
+ end
50
+
51
+ private
52
+
53
+ COMMON_BUILD_SETTINGS = {
54
+ :all => {
55
+ 'ALWAYS_SEARCH_USER_PATHS' => 'NO',
56
+ 'GCC_C_LANGUAGE_STANDARD' => 'gnu99',
57
+ 'INSTALL_PATH' => "$(BUILT_PRODUCTS_DIR)",
58
+ 'GCC_WARN_ABOUT_MISSING_PROTOTYPES' => 'YES',
59
+ 'GCC_WARN_ABOUT_RETURN_TYPE' => 'YES',
60
+ 'GCC_WARN_UNUSED_VARIABLE' => 'YES',
61
+ 'OTHER_LDFLAGS' => ''
62
+ },
63
+ :debug => {
64
+ 'GCC_DYNAMIC_NO_PIC' => 'NO',
65
+ 'GCC_PREPROCESSOR_DEFINITIONS' => ["DEBUG=1", "$(inherited)"],
66
+ 'GCC_SYMBOLS_PRIVATE_EXTERN' => 'NO',
67
+ 'GCC_OPTIMIZATION_LEVEL' => '0'
68
+ },
69
+ :ios => {
70
+ 'ARCHS' => "$(ARCHS_STANDARD_32_BIT)",
71
+ 'GCC_VERSION' => 'com.apple.compilers.llvmgcc42',
72
+ 'IPHONEOS_DEPLOYMENT_TARGET' => '4.3',
73
+ 'PUBLIC_HEADERS_FOLDER_PATH' => "$(TARGET_NAME)",
74
+ 'SDKROOT' => 'iphoneos'
75
+ },
76
+ :osx => {
77
+ 'ARCHS' => "$(ARCHS_STANDARD_64_BIT)",
78
+ 'GCC_ENABLE_OBJC_EXCEPTIONS' => 'YES',
79
+ 'GCC_WARN_64_TO_32_BIT_CONVERSION' => 'YES',
80
+ 'GCC_VERSION' => 'com.apple.compilers.llvm.clang.1_0',
81
+ 'MACOSX_DEPLOYMENT_TARGET' => '10.7',
82
+ 'SDKROOT' => 'macosx'
83
+ }
84
+ }
85
+
86
+ def self.build_settings(platform, scheme)
87
+ settings = COMMON_BUILD_SETTINGS[:all].merge(COMMON_BUILD_SETTINGS[platform])
88
+ settings['COPY_PHASE_STRIP'] = scheme == :debug ? 'NO' : 'YES'
89
+ if scheme == :debug
90
+ settings.merge!(COMMON_BUILD_SETTINGS[:debug])
91
+ settings['ONLY_ACTIVE_ARCH'] = 'YES' if platform == :osx
92
+ else
93
+ settings['VALIDATE_PRODUCT'] = 'YES' if platform == :ios
94
+ settings['DEBUG_INFORMATION_FORMAT'] = "dwarf-with-dsym" if platform == :osx
95
+ end
96
+ settings
97
+ end
98
+ end
99
+ end