xcodeproj 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 529ed72e9f63e78ad2b0ca1a550ff4316ef1606f
4
- data.tar.gz: 43bfe6819ebde4b4e6d1a1f4ce8bd49891663254
3
+ metadata.gz: 17c13e04abd44c7e6dceedf68acf67a1d8ba2f37
4
+ data.tar.gz: 44fdf17f6e7ea9ca3a9f08dece0112eacffe746c
5
5
  SHA512:
6
- metadata.gz: 16a8b646d24a0cf360732816343f08daa455271e8909ae6c2ccc7b1fe9f05f4f4750544ea9af40798969e8aa4f7de30efc7ec53adc42f928fdc71897b3e75e25
7
- data.tar.gz: ba101e58ee80931f8991c64f23b0a001bfb59ec27f6decd7c22e22b625f15b65da3aa1c0ec032ef336db39b92e7ef23a483d2853492418c049663f5d1ed61698
6
+ metadata.gz: a6cd8393ddfa58f805c14e0e2dface2ae60d24bd4774b78f81faa6c40f228ec2b3d9fd7eb24b6b6ebf05027227db84c1e9c5cc8b52b07235e0ad955b004f35c1
7
+ data.tar.gz: 979709a8376c2e40be97fcba4d554a0e53277a173a99fe56cf70380c54d240c783c248a6b275cb4ccff589c4e02cf66dc93f722acc136228345debb7960eef8a
@@ -24,6 +24,14 @@ checking_for "-std=c99 option to compiler" do
24
24
  $CFLAGS += " -std=c99" if try_compile '', '-std=c99'
25
25
  end
26
26
 
27
+ # From `man ld`:
28
+ #
29
+ # -Z Do not search the standard directories when searching for libraries and frameworks.
30
+ #
31
+ # This is typically used when you want compilation against Xcode SDK as opposed to the frameworks installed
32
+ # in the running system, which is our use case.
33
+ $LDFLAGS.gsub!(/\s-Z\s/,' ')
34
+
27
35
  unless have_framework('CoreFoundation')
28
36
  if have_library('CoreFoundation')
29
37
  # this is needed for opencflite, assume it's on linux
data/lib/xcodeproj.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  module Xcodeproj
2
- VERSION = '0.9.0' unless defined? Xcodeproj::VERSION
3
2
 
4
3
  class PlainInformative < StandardError
5
4
  end
@@ -10,13 +9,14 @@ module Xcodeproj
10
9
  end
11
10
  end
12
11
 
12
+ require 'xcodeproj/user_interface'
13
+
13
14
  autoload :Command, 'xcodeproj/command'
14
15
  autoload :Config, 'xcodeproj/config'
15
16
  autoload :Constants, 'xcodeproj/constants'
16
17
  autoload :Differ, 'xcodeproj/differ'
17
18
  autoload :Helper, 'xcodeproj/helper'
18
19
  autoload :Project, 'xcodeproj/project'
19
- autoload :UI, 'xcodeproj/user_interface'
20
20
  autoload :Workspace, 'xcodeproj/workspace'
21
21
  autoload :XCScheme, 'xcodeproj/scheme'
22
22
  autoload :XcodebuildHelper, 'xcodeproj/xcodebuild_helper'
@@ -150,9 +150,9 @@ module Xcodeproj
150
150
  flags = @attributes['OTHER_LDFLAGS']
151
151
  return unless flags
152
152
 
153
- frameworks = flags.scan(/-framework\s+([^\s]+)/).map { |m| m[0] }
154
- weak_frameworks = flags.scan(/-weak_framework\s+([^\s]+)/).map { |m| m[0] }
155
- libraries = flags.scan(/-l ?([^\s]+)/).map { |m| m[0] }
153
+ frameworks = flags.scan(/(?:\A|\s)-framework\s+([^\s]+)/).map { |m| m[0] }
154
+ weak_frameworks = flags.scan(/(?:\A|\s)-weak_framework\s+([^\s]+)/).map { |m| m[0] }
155
+ libraries = flags.scan(/(?:\A|\s)-l ?([^\s]+)/).map { |m| m[0] }
156
156
  @frameworks.merge frameworks
157
157
  @weak_frameworks.merge weak_frameworks
158
158
  @libraries.merge libraries
@@ -159,7 +159,7 @@ module Xcodeproj
159
159
  }.freeze,
160
160
  :debug => {
161
161
  # TODO: enable after Xcode 4
162
- # 'ONLY_ACTIVE_ARCH' => 'YES',
162
+ # 'ONLY_ACTIVE_ARCH' => 'YES',
163
163
  }.freeze,
164
164
  }.freeze
165
165
 
@@ -0,0 +1,6 @@
1
+ module Xcodeproj
2
+ # The version of the xcodeproj gem.
3
+ #
4
+ VERSION = '0.10.0' unless defined? Xcodeproj::VERSION
5
+ end
6
+
@@ -3,6 +3,7 @@ require 'pathname'
3
3
  require 'xcodeproj/xcodeproj_ext'
4
4
  require 'xcodeproj/project/object'
5
5
  require 'xcodeproj/project/project_helper'
6
+ require 'xcodeproj/project/xcproj_helper'
6
7
 
7
8
  module Xcodeproj
8
9
 
@@ -41,31 +42,34 @@ module Xcodeproj
41
42
 
42
43
  include Object
43
44
 
44
- # @return [String] the archive version.
45
+ # @return [Pathname] the path of the project.
45
46
  #
46
- attr_reader :archive_version
47
+ attr_reader :path
47
48
 
48
- # @return [Hash] an dictionary whose purpose is unknown.
49
+ # @param [Pathname, String] path @see path
50
+ # @param [Bool] skip_initialization
51
+ # Wether the project should be initialized from scratch.
49
52
  #
50
- attr_reader :classes
51
-
52
- # @return [String] the objects version.
53
- #
54
- attr_reader :object_version
55
-
56
- # @return [Hash{String => AbstractObject}] A hash containing all the
57
- # objects of the project by UUID.
53
+ # @example Creating a project
54
+ # Project.new("path/to/Project.xcodeproj")
58
55
  #
59
- attr_reader :objects_by_uuid
60
-
61
- # @return [PBXProject] the root object of the project.
62
- #
63
- attr_reader :root_object
56
+ def initialize(path, skip_initialization = false)
57
+ @path = Pathname.new(path)
58
+ @objects_by_uuid = {}
59
+ @generated_uuids = []
60
+ @available_uuids = []
61
+ unless skip_initialization
62
+ initialize_from_scratch
63
+ end
64
+ unless skip_initialization.is_a?(TrueClass) || skip_initialization.is_a?(FalseClass)
65
+ raise ArgumentError, "[Xcodeproj] Initialization parameter expected to " \
66
+ "be a boolean #{skip_initialization}"
67
+ end
68
+ end
64
69
 
65
- # Creates a new Project instance or initializes one with the data of an
66
- # existing Xcode document.
70
+ # Opens the project at the given path.
67
71
  #
68
- # @param [Pathname, String] xcodeproj
72
+ # @param [Pathname, String] path
69
73
  # The path to the Xcode project document (xcodeproj).
70
74
  #
71
75
  # @raise If the project versions are more recent than the ones know to
@@ -77,57 +81,37 @@ module Xcodeproj
77
81
  # malformed.
78
82
  #
79
83
  # @example Opening a project
80
- # Project.new("path/to/Project.xcodeproj")
84
+ # Project.open("path/to/Project.xcodeproj")
81
85
  #
82
- def initialize(xcodeproj = nil)
83
- @objects_by_uuid = {}
84
- @generated_uuids = []
85
- @available_uuids = []
86
-
87
- if xcodeproj
88
- file = File.join(xcodeproj, 'project.pbxproj')
89
- plist = Xcodeproj.read_plist(file.to_s)
86
+ def self.open(path)
87
+ unless Pathname.new(path).exist?
88
+ raise "[Xcodeproj] Unable to open `#{path}` because it doesn't exist."
89
+ end
90
+ project = new(path, true)
91
+ project.send(:initialize_from_file)
92
+ project
93
+ end
90
94
 
91
- @archive_version = plist['archiveVersion']
92
- @object_version = plist['objectVersion']
93
- @classes = plist['classes']
95
+ # @return [String] the archive version.
96
+ #
97
+ attr_reader :archive_version
94
98
 
95
- root_object_uuid = plist['rootObject']
96
- @root_object = new_from_plist(root_object_uuid, plist['objects'], self)
99
+ # @return [Hash] an dictionary whose purpose is unknown.
100
+ #
101
+ attr_reader :classes
97
102
 
98
- if (@archive_version.to_i > Constants::LAST_KNOWN_ARCHIVE_VERSION || @object_version.to_i > Constants::LAST_KNOWN_OBJECT_VERSION)
99
- raise '[Xcodeproj] Unknown archive or object version.'
100
- end
103
+ # @return [String] the objects version.
104
+ #
105
+ attr_reader :object_version
101
106
 
102
- unless @root_object
103
- raise "[Xcodeproj] Unable to find a root object in #{file}."
104
- end
105
- else
106
- @archive_version = Constants::LAST_KNOWN_ARCHIVE_VERSION.to_s
107
- @object_version = Constants::LAST_KNOWN_OBJECT_VERSION.to_s
108
- @classes = {}
109
-
110
- root_object = new(PBXProject)
111
- root_object.main_group = new(PBXGroup)
112
- root_object.product_ref_group = root_object.main_group.new_group('Products')
113
-
114
- config_list = new(XCConfigurationList)
115
- config_list.default_configuration_name = 'Release'
116
- config_list.default_configuration_is_visible = '0'
117
- root_object.build_configuration_list = config_list
118
-
119
- %w| Release Debug |.each do |name|
120
- build_configuration = new(XCBuildConfiguration)
121
- build_configuration.name = name
122
- build_configuration.build_settings = Constants::PROJECT_DEFAULT_BUILD_SETTINGS[name.downcase.to_sym].dup
123
- config_list.build_configurations << build_configuration
124
- end
107
+ # @return [Hash{String => AbstractObject}] A hash containing all the
108
+ # objects of the project by UUID.
109
+ #
110
+ attr_reader :objects_by_uuid
125
111
 
126
- @root_object = root_object
127
- root_object.add_referrer(self)
128
- new_group('Frameworks')
129
- end
130
- end
112
+ # @return [PBXProject] the root object of the project.
113
+ #
114
+ attr_reader :root_object
131
115
 
132
116
  # Compares the project to another one, or to a plist representation.
133
117
  #
@@ -140,16 +124,75 @@ module Xcodeproj
140
124
  end
141
125
 
142
126
  def to_s
143
- "Project with root object UUID: #{root_object.uuid}"
127
+ "#<#{self.class}> path:`#{path}` UUID:`#{root_object.uuid}`"
144
128
  end
145
129
 
146
130
  alias :inspect :to_s
147
131
 
132
+ # @return [Bool] Whether the xcproj conversion should be disabled.
133
+ #
134
+ attr_accessor :disable_xcproj
135
+
136
+
137
+ public
138
+
139
+ # @!group Initialization
148
140
  #-------------------------------------------------------------------------#
149
141
 
142
+ # Initializes the instance from scratch.
143
+ #
144
+ def initialize_from_scratch
145
+ @archive_version = Constants::LAST_KNOWN_ARCHIVE_VERSION.to_s
146
+ @object_version = Constants::LAST_KNOWN_OBJECT_VERSION.to_s
147
+ @classes = {}
148
+
149
+ root_object.remove_referrer(self) if root_object
150
+ @root_object = new(PBXProject)
151
+ root_object.add_referrer(self)
152
+
153
+ root_object.main_group = new(PBXGroup)
154
+ root_object.product_ref_group = root_object.main_group.new_group('Products')
155
+
156
+ config_list = new(XCConfigurationList)
157
+ root_object.build_configuration_list = config_list
158
+ config_list.default_configuration_name = 'Release'
159
+ config_list.default_configuration_is_visible = '0'
160
+ add_build_configuration('Debug', :debug)
161
+ add_build_configuration('Release', :release)
162
+
163
+ new_group('Frameworks')
164
+ end
165
+
166
+ # Initializes the instance with the project stored in the `path` attribute.
167
+ #
168
+ def initialize_from_file
169
+ pbxproj_path = path + 'project.pbxproj'
170
+ plist = Xcodeproj.read_plist(pbxproj_path.to_s)
171
+ root_object_uuid = plist['rootObject']
172
+ root_object.remove_referrer(self) if root_object
173
+ @root_object = new_from_plist(root_object_uuid, plist['objects'], self)
174
+ @archive_version = plist['archiveVersion']
175
+ @object_version = plist['objectVersion']
176
+ @classes = plist['classes']
177
+
178
+ unless root_object
179
+ raise "[Xcodeproj] Unable to find a root object in #{pbxproj_path}."
180
+ end
181
+
182
+ if (archive_version.to_i > Constants::LAST_KNOWN_ARCHIVE_VERSION)
183
+ raise '[Xcodeproj] Unknown archive version.'
184
+ end
185
+
186
+ if (object_version.to_i > Constants::LAST_KNOWN_OBJECT_VERSION)
187
+ raise '[Xcodeproj] Unknown object version.'
188
+ end
189
+ end
190
+
191
+
150
192
  public
151
193
 
152
194
  # @!group Plist serialization
195
+ #-------------------------------------------------------------------------#
153
196
 
154
197
  # Creates a new object from the given UUID and `objects` hash (of a plist).
155
198
  #
@@ -232,27 +275,32 @@ module Xcodeproj
232
275
  {
233
276
  'File References' => root_object.main_group.pretty_print.values.first,
234
277
  'Targets' => root_object.targets.map(&:pretty_print),
235
- 'Build Configurations' => build_configurations.map(&:pretty_print)
278
+ 'Build Configurations' => build_configurations.sort_by(&:name).map(&:pretty_print)
236
279
  }
237
280
  end
238
281
 
239
- # Serializes the internal data as a property list and stores it on disk at
240
- # the given path (`xcodeproj` file).
282
+ # Serializes the project in the xcodeproj format using the path provided
283
+ # during initialization or the given path (`xcodeproj` file). If a path is
284
+ # provided file references depending on the root of the project are not
285
+ # updated automatically, thus clients are responsible to perform any needed
286
+ # modification before saving.
241
287
  #
242
- # @example Saving a project
243
- # project.save_as("path/to/Project.xcodeproj") #=> true
288
+ # @param [String, Pathname] path
289
+ # The optional path where the project should be saved.
244
290
  #
245
- # @param [String, Pathname] projpath
246
- # The path where the data should be stored.
291
+ # @example Saving a project
292
+ # project.save
293
+ # project.save
247
294
  #
248
- # @return [Boolean] Whether or not saving was successful.
295
+ # @return [void]
249
296
  #
250
- def save_as(projpath)
251
- projpath = projpath.to_s
252
- FileUtils.mkdir_p(projpath)
253
- file = File.join(projpath, 'project.pbxproj')
297
+ def save(save_path = nil)
298
+ save_path ||= path
299
+ FileUtils.mkdir_p(save_path)
300
+ file = File.join(save_path, 'project.pbxproj')
254
301
  Xcodeproj.write_plist(to_hash, file)
255
302
  fix_encoding(file)
303
+ XCProjHelper.touch(save_path) unless disable_xcproj
256
304
  end
257
305
 
258
306
  # Simple workaround to escape characters which are outside of ASCII
@@ -298,12 +346,16 @@ module Xcodeproj
298
346
  # attributes, for this reason it is better to use the convenience methods
299
347
  # offered by the {AbstractObject} subclasses or by this class.
300
348
  #
301
- # @param [Class] klass
302
- # The concrete subclass of AbstractObject for new object.
349
+ # @param [Class, String] klass
350
+ # The concrete subclass of AbstractObject for new object or its
351
+ # ISA.
303
352
  #
304
353
  # @return [AbstractObject] the new object.
305
354
  #
306
355
  def new(klass)
356
+ if klass.is_a?(String)
357
+ klass = Object.const_get(klass)
358
+ end
307
359
  object = klass.new(self, generate_uuid)
308
360
  object.initialize_defaults
309
361
  object
@@ -467,14 +519,14 @@ module Xcodeproj
467
519
 
468
520
  # @!group Helpers for generating objects
469
521
 
470
- # Creates a new file reference at the given subpath of the main group.
522
+ # Creates a new file reference in the main group.
471
523
  #
472
524
  # @param @see PBXGroup#new_file
473
525
  #
474
526
  # @return [PBXFileReference] the new file.
475
527
  #
476
- def new_file(path, sub_group_path = nil)
477
- main_group.new_file(path, sub_group_path)
528
+ def new_file(path, source_tree = :group)
529
+ main_group.new_file(path, source_tree)
478
530
  end
479
531
 
480
532
  # Creates a new group at the given subpath of the main group.
@@ -483,14 +535,12 @@ module Xcodeproj
483
535
  #
484
536
  # @return [PBXGroup] the new group.
485
537
  #
486
- def new_group(name, path = nil)
487
- main_group.new_group(name, path)
538
+ def new_group(name, path = nil, source_tree = :group)
539
+ main_group.new_group(name, path, source_tree)
488
540
  end
489
541
 
490
- # Adds a file reference for a system framework to the project.
491
- #
492
- # The file reference can then be added to the build files of a
493
- # {PBXFrameworksBuildPhase}.
542
+ # Adds a file reference for a system framework to the project if needed and
543
+ # adds it to the {PBXFrameworksBuildPhase} of the given target.
494
544
  #
495
545
  # @example Adding QuartzCore
496
546
  #
@@ -504,12 +554,12 @@ module Xcodeproj
504
554
  # The name of a framework.
505
555
  #
506
556
  # @param [PBXNativeTarget] target
507
- # The target for which to add the framework.
557
+ # The target to which to add the framework.
508
558
  #
509
559
  # @note This method adds a reference to the highest know SDK for the
510
560
  # given platform.
511
561
  #
512
- # @return [PBXFileReference] The generated file reference.
562
+ # @return [PBXFileReference] The file reference of the framework.
513
563
  #
514
564
  def add_system_framework(name, target)
515
565
  ProjectHelper.add_system_framework(self, name, target)
@@ -564,6 +614,29 @@ module Xcodeproj
564
614
  ProjectHelper.new_resources_bundle(self, name, platform, product_group)
565
615
  end
566
616
 
617
+ # Adds a new build configuration to the project and populates its with
618
+ # default settings according to the provided type.
619
+ #
620
+ # @param [String] name
621
+ # The name of the build configuration.
622
+ #
623
+ # @param [Symbol] type
624
+ # The type of the build configuration used to populate the build
625
+ # settings, must be :debug or :release.
626
+ #
627
+ # @return [XCBuildConfiguration] The new build configuration.
628
+ #
629
+ def add_build_configuration(name, type)
630
+ build_configuration_list = root_object.build_configuration_list
631
+ unless build_configuration_list[name]
632
+ build_configuration = new(XCBuildConfiguration)
633
+ build_configuration.name = name
634
+ build_configuration.build_settings = Constants::PROJECT_DEFAULT_BUILD_SETTINGS[type].dup
635
+ build_configuration_list.build_configurations << build_configuration
636
+ build_configuration
637
+ end
638
+ end
639
+
567
640
  #-------------------------------------------------------------------------#
568
641
  # Get list of shared schemes in project
569
642
  #
@@ -99,8 +99,19 @@ module Xcodeproj
99
99
  # @return [void]
100
100
  #
101
101
  def remove_from_project
102
- @project.objects_by_uuid.delete(uuid)
103
- @referrers.each { |referrer| referrer.remove_reference(self) }
102
+ project.objects_by_uuid.delete(uuid)
103
+ referrers.each { |referrer| referrer.remove_reference(self) }
104
+
105
+ to_one_attributes.each do |attrb|
106
+ object = attrb.get_value(self)
107
+ object.remove_referrer(self) if object
108
+ end
109
+
110
+ to_many_attributes.each do |attrb|
111
+ list = attrb.get_value(self)
112
+ list.clear
113
+ end
114
+
104
115
  raise "[Xcodeproj] BUG: #{self} should have no referrers instead the following objects are still referencing it #{referrers}" unless referrers.count == 0
105
116
  end
106
117
 
@@ -391,8 +402,10 @@ module Xcodeproj
391
402
  end
392
403
 
393
404
  def inspect
394
- name_part = " name=#{self.name}" if respond_to?(:name)
395
- "<#{self.class}#{name_part} UUID=#{uuid}>"
405
+ optional = ''
406
+ optional << " name=`#{self.name}`" if respond_to?(:name) && self.name
407
+ optional << " path=`#{self.path}`" if respond_to?(:path) && self.path
408
+ "<#{self.isa}#{optional} UUID=`#{uuid}`>"
396
409
  end
397
410
  end
398
411
  end