xcodeproj 0.9.0 → 0.10.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.
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