Class: Xcode::Project

Inherits:
Object
  • Object
show all
Defined in:
lib/xcode/project.rb,
lib/xcode/builder/scheme_builder.rb

Overview

The project is the representation of an Xcode Project folder, the ‘*.xcodeproj`, folder that contains a number of workspace files and project files like `project.pbxproj`.

The Project represents encapsulates the an actual Resource that is ProjectReference and other objects.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, sdk = nil) ⇒ Project

Initialized with a specific path and sdk.

This initialization is not often used. Instead projects are generated through the Xcode#project method.

Parameters:

  • path (String)

    of the project to open.

  • sdk (String) (defaults to: nil)

    the sdk value of the project. This will default to ‘iphoneos`.

See Also:



55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/xcode/project.rb', line 55

def initialize(path, sdk=nil)
  @sdk = sdk || "iphoneos"  # FIXME: should support OSX/simulator too
  @path = File.expand_path path
  @schemes = nil
  @groups = []
  @name = File.basename(@path).gsub(/\.xcodeproj/,'')

  # Parse the Xcode project file and create the registry

  @registry = parse_pbxproj
  raise "Unable to parse project at #{@path}" if @registry.nil?
  @project = Xcode::Resource.new @registry.root, @registry
end

Instance Attribute Details

#nameString (readonly)

Returns the name of the project; This value is deteremined from the first part of the Xcode project folder name (e.g. “TestProject.xcodeproj” name is “TestProject”).

Returns:

  • (String)

    the name of the project; This value is deteremined from the first part of the Xcode project folder name (e.g. “TestProject.xcodeproj” name is “TestProject”)



21
22
23
# File 'lib/xcode/project.rb', line 21

def name
  @name
end

#pathString (readonly)

Returns the expanded file path for the project. This is expanded from the file path specified during initialization.

Returns:

  • (String)

    the expanded file path for the project. This is expanded from the file path specified during initialization.



29
30
31
# File 'lib/xcode/project.rb', line 29

def path
  @path
end

#projectProjectReference (readonly)

Returns the project object that is contained in the project file that contains additional information.

Returns:

  • (ProjectReference)

    the project object that is contained in the project file that contains additional information



41
42
43
# File 'lib/xcode/project.rb', line 41

def project
  @project
end

#registryRegistry (readonly)

Returns the data that is parsed from the project.pbxproj, it is in most part a Hash with additional methods included to provide core functionality.

Returns:

  • (Registry)

    the data that is parsed from the project.pbxproj, it is in most part a Hash with additional methods included to provide core functionality.



37
38
39
# File 'lib/xcode/project.rb', line 37

def registry
  @registry
end

#schemesArray<Xcode::Scheme> (readonly)

Returns available schemes for the project.

Returns:



32
33
34
# File 'lib/xcode/project.rb', line 32

def schemes
  @schemes
end

#sdkString (readonly)

Returns the sdks for the project. This is specified during the project initialization. If none are provided this currently defaults to “iphoneos”.

Returns:

  • (String)

    the sdks for the project. This is specified during the project initialization. If none are provided this currently defaults to “iphoneos”



25
26
27
# File 'lib/xcode/project.rb', line 25

def sdk
  @sdk
end

Instance Method Details

#archive_versionFixnum

Returns the project’s archive version.

Returns:

  • (Fixnum)

    the project’s archive version



88
89
90
# File 'lib/xcode/project.rb', line 88

def archive_version
  @registry.archive_version
end

#create_target(name, type = :native) {|target| ... } ⇒ Target

Creates a new target within the Xcode project. This will by default not generate all the additional build phases, configurations, and files that create a project.

Available targts:

  • native

  • aggregate

Parameters:

  • name (String)

    the name to provide to the target. This will also be the value that other defaults will be based on.

  • type (String, Symbol) (defaults to: :native)

    the type of build target to create.

Yields:

Returns:

  • (Target)

    the target created.



290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
# File 'lib/xcode/project.rb', line 290

def create_target(name,type=:native)

  target = @registry.add_object Target.send(type)
  @project.properties['targets'] << target.identifier

  target.name = name

  build_configuration_list = @registry.add_object(ConfigurationList.configration_list)
  target.build_configuration_list = build_configuration_list.identifier

  target.project = self

  yield target if block_given?

  target.save!
end

#describeObject

Prints to STDOUT a description of this project’s targets, configuration and schemes.



334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/xcode/project.rb', line 334

def describe
  puts "Project #{name} contains"
  targets.each do |t|
    puts " + target:#{t.name}"
    t.configs.each do |c|
      puts "    + config:#{c.name}"
    end
  end
  schemes.each do |s|
    puts " + scheme #{s.name}"
    puts "    + Launch action => target:#{s.launch.target.name}, config:#{s.launch.name}" unless s.launch.nil?
    puts "    + Test action   => target:#{s.test.target.name}, config:#{s.test.name}" unless s.test.nil?
  end
end

#file(name_with_path) ⇒ FileReference

Return the file that matches the specified path. This will traverse the project’s groups and find the file at the end of the path.

Parameters:

  • name_with_path (String)

    the path to the file

Returns:

  • (FileReference)

    the file that matches the name, nil if no file matches the path.



156
157
158
159
# File 'lib/xcode/project.rb', line 156

def file(name_with_path)
  path, name = File.split(name_with_path)
  group(path).file(name).first
end

#frameworks_groupGroup

Most Xcode projects have a Frameworks gorup where all the imported frameworks are shown. This will generate an exception if there is no Frameworks group.

Returns:

  • (Group)

    the ‘Frameworks’ group of the projet.



178
179
180
181
182
# File 'lib/xcode/project.rb', line 178

def frameworks_group
  current_group = groups.group('Frameworks').first
  current_group.instance_eval(&block) if block_given? and current_group
  current_group
end

#global_config(name) ⇒ Configuration

Returns the project level configuration with the given name; raise an exception if no configuration exists with that name.

Parameters:

  • name (String, Symbol)

    of the configuration for the project

Returns:

  • (Configuration)

    the project level configuration with the given name; raise an exception if no configuration exists with that name.



105
106
107
# File 'lib/xcode/project.rb', line 105

def global_config(name)
  @project.config(name)
end

#global_configsArray<Configuration>

Returns a list of configurations global to the project.

Returns:



95
96
97
# File 'lib/xcode/project.rb', line 95

def global_configs
  @project.configs
end

#group(name, options = {}, &block) ⇒ Group

Note:

this will attempt to find the paths specified, if it fails to find them it will create one and then continue traversing.

Note:

this path functionality current is only exercised from the project level all groups will treat the path division ‘/` as simply a character.

Returns the group specified. If any part of the group does not exist along the path the group is created. Also paths can be specified to make the traversing of the groups easier.

Examples:

Traverse a path through the various sub-groups.


project.group('Vendor/MyCode/Support Files')
# is equivalent to ...
project.group('Vendor').first.group('MyCode').first.group('Supporting Files')

Parameters:

  • name (String)

    the group name to find/create

Returns:

  • (Group)

    the group with the specified name.



145
146
147
# File 'lib/xcode/project.rb', line 145

def group(name,options = {},&block)
  @project.group(name,options,&block)
end

#groupsGroup

TODO:

this really could use a better name then groups as it is the main group but it should likely be something like main_group, root or something else that conveys that this is the project root for files, and such.

Returns the main group of the project where all the files reside.

Returns:

  • (Group)

    the main group, the heart of the action of the file explorer for the Xcode project. From here all other groups and items may be found.



120
121
122
# File 'lib/xcode/project.rb', line 120

def groups
  @project.main_group
end

#object_versionFixnum

Returns the project’s object version.

Returns:

  • (Fixnum)

    the project’s object version



81
82
83
# File 'lib/xcode/project.rb', line 81

def object_version
  @registry.object_version
end

#products_groupGroup

Most Xcode projects have a products group where products are placed. This will generate an exception if there is no products group.

Returns:

  • (Group)

    the ‘Products’ group of the project.



166
167
168
169
170
# File 'lib/xcode/project.rb', line 166

def products_group
  current_group = groups.group('Products').first
  current_group.instance_eval(&block) if block_given? and current_group
  current_group
end

#remove_target(name) ⇒ Target

Note:

this will remove the first target that matches the specified name.

Note:

this will remove only the project entry at the moment and not the the files that may be associated with the target. All build phases, build files, and configurations will automatically be cleaned up when Xcode is opened.

Remove a target from the Xcode project.

Parameters:

  • name (String)

    the name of the target to remove from the Xcode project.

Returns:

  • (Target)

    the target that has been removed.



322
323
324
325
326
327
328
329
# File 'lib/xcode/project.rb', line 322

def remove_target(name)
  found_target = targets.find {|target| target.name == name }
  if found_target
    @project.properties['targets'].delete found_target.identifier
    @registry.remove_object found_target.identifier
  end
  found_target
end

#save(path) ⇒ Object

Note:

currently this does not support saving the workspaces associated with the project to their new location.

Saves the current project at the specified path.

Parameters:

  • path (String)

    the path to save the project



217
218
219
220
221
222
223
224
225
226
227
# File 'lib/xcode/project.rb', line 217

def save(path)

  Dir.mkdir(path) unless File.exists?(path)
  project_filepath = "#{path}/project.pbxproj"

  # @toodo Save the workspace when the project is saved
  # FileUtils.cp_r "#{path}/project.xcworkspace", "#{path}/project.xcworkspace"

  Xcode::PLUTILProjectParser.save "#{path}/project.pbxproj", to_xcplist

end

#save!Object

Save the current project at the current path that it exists.



205
206
207
# File 'lib/xcode/project.rb', line 205

def save!
  save @path
end

#scheme(name) {|scheme| ... } ⇒ Scheme

Note:

if two schemes match names, the first matching scheme is returned.

Return the scheme with the specified name. Raises an error if no schemes match the specified name.

Parameters:

  • name (String)

    of the specific scheme

Yields:

Returns:

  • (Scheme)

    the specific scheme that matches the name specified



238
239
240
241
242
243
# File 'lib/xcode/project.rb', line 238

def scheme(name)
  scheme = schemes.select {|t| t.name == name.to_s}.first
  raise "No such scheme #{name}, available schemes are #{schemes.map {|t| t.name}.join(', ')}" if scheme.nil?
  yield scheme if block_given?
  scheme
end

#target(name) {|target| ... } ⇒ Target

Note:

if two targets match names, the first matching target is returned.

Return the target with the specified name. Raises an error if no targets match the specified name.

Parameters:

  • name (String)

    of the specific target

Yields:

Returns:

  • (Target)

    the specific target that matches the name specified



267
268
269
270
271
272
# File 'lib/xcode/project.rb', line 267

def target(name)
  target = targets.select {|t| t.name == name.to_s}.first
  raise "No such target #{name}, available targets are #{targets.map {|t| t.name}.join(', ')}" if target.nil?
  yield target if block_given?
  target
end

#targetsArray<Target>

All the targets specified within the project.

Returns:

  • (Array<Target>)

    an array of all the available targets for the specific project.



251
252
253
254
255
256
# File 'lib/xcode/project.rb', line 251

def targets
  @project.targets.map do |target|
    target.project = self
    target
  end
end

#to_xcodebuild_optionObject



10
11
12
# File 'lib/xcode/builder/scheme_builder.rb', line 10

def to_xcodebuild_option
  "-project \"#{self.path}\""
end

#to_xcplistString

This will convert the current project file into a supported Xcode Plist format. This format is not json or a traditional plist so several core Ruby objects gained the #to_xcplist method to save it properly.

Specifically this will add the necessary file header information and the surrounding mustache braces around the xcode plist format of the registry.

Returns:

  • (String)

    Xcode Plist format of the project.



193
194
195
196
197
198
199
200
# File 'lib/xcode/project.rb', line 193

def to_xcplist

  # @note The Hash#to_xcplist, which the Registry will save out as xcode,
  #   saves a semi-colon at the end which needs to be removed to ensure
  #   the project file can be opened.

  %{// !$*UTF8*$!"\n#{@registry.to_xcplist.gsub(/\};\s*\z/,'}')}}
end