Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/mjmsmith/pbxplorer
Ruby classes for parsing and editing Xcode project (.pbxproj) files, includes interactive help mode
https://github.com/mjmsmith/pbxplorer
pbxproj xcode
Last synced: 5 days ago
JSON representation
Ruby classes for parsing and editing Xcode project (.pbxproj) files, includes interactive help mode
- Host: GitHub
- URL: https://github.com/mjmsmith/pbxplorer
- Owner: mjmsmith
- Created: 2012-11-27T15:32:50.000Z (about 12 years ago)
- Default Branch: master
- Last Pushed: 2017-10-24T06:00:42.000Z (about 7 years ago)
- Last Synced: 2025-01-02T22:07:57.715Z (12 days ago)
- Topics: pbxproj, xcode
- Language: Ruby
- Size: 36.1 KB
- Stars: 93
- Watchers: 5
- Forks: 10
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# pbxplorer
pbxplorer is a set of Ruby classes for parsing, editing, and saving Xcode project (.pbxproj) files. It can also be used to explore the contents of a project using the interactive Ruby shell.
### Dependencies
pbxplorer has no Ruby dependencies outside of the standard library. It uses the OS X **plutil** command to parse the project file.
### Overview
An Xcode project (.pbxproj) file is essentially a hash of objects keyed by UUID. The objects are hashes of properties keyed by name. The associated values can be strings, arrays, or hashes.
Each object hash contains an "isa" property that identifies its type. pbxplorer loads a project file hash and replaces each generic object hash with a specific subclass based on its type.
### Class Hierarchy
PBXObject and PBXBuildPhase are abstract superclasses. All other subclasses of PBXObject correspond to object hashes in the project, based on their "isa" property.
```
PBXObject
PBXBuildFile
PBXBuildPhase
PBXFrameworksBuildPhase
PBXResourcesBuildPhase
PBXShellScriptBuildPhase
PBXSourcesBuildPhase
PBXFileReference
PBXGroup
PBXVariantGroup
PBXProject
PBXNativeTarget
XCBuildConfiguration
XCConfigurationList
XCProjectFile
```
### Reference HierarchyIn the project file, objects are referenced from other objects by UUID. pbxplorer includes convenience methods to return the objects themselves rather than the UUIDs. Below are the method names and object types returned.
```
PBXProject
build_configuration_list: XCConfigurationList
main_group: PBXGroup
targets: [PBXNativeTarget]
XCConfigurationList
build_configurations: [XCBuildConfiguration]
PBXGroup
children: [PBXGroup|PBXFileReference]
subgroups: [PBXGroup]
file_refs: [PBXFileReference]
variant_groups: [PBXVariantGroup]PBXNativeTarget
build_configuration_list: XCBuildConfigurationList
build_phases: [PBXBuildPhase]
product_file_ref: PBXFileReferencePBXBuildPhase
build_files: [PBXBuildFile]PBXBuildFile
file_ref: PBXFileReference
```### Interactive Use
To get started:
```ruby
$ irb
>> require 'pbxplorer'
=> true
>> XCProjectFile.help
project_file = XCProjectFile.new '/path/to/project.pbxproj'
=> XCProjectFile
```The help displays a suggested statement followed by the type of the assigned result. Enter the statement in the shell, editing as necessary:
```ruby
>> project_file = XCProjectFile.new 'project.pbxproj'
=> {
rootObject = "4D0B81831657473000DEF560"
objects = < 63 objects >
}
```This`XCProjectFile`instance contains a reference to the root object (a`PBXProject`instance), and the collection of all objects.
Get help from the **project_file** object:
```ruby
>> project_file.help
project = project_file.project
=> PBXProject
```Enter the statement:
```ruby
>> project = project_file.project
=> 4D0B81831657473000DEF560 = {
attributes = {"CLASSPREFIX"=>"Example", "LastUpgradeCheck"=>"0450", "ORGANIZATIONNAME"=>"Example"}
projectRoot = ""
hasScannedForEncodings = "0"
mainGroup = "4D0B81811657473000DEF560"
buildConfigurationList = "4D0B81861657473000DEF560"
compatibilityVersion = "Xcode 3.2"
productRefGroup = "4D0B818D1657473000DEF560"
projectDirPath = ""
knownRegions = ["en"]
targets = ["4D0B818B1657473000DEF560", "4D0B81AC1657473100DEF560"]
developmentRegion = "English"
isa = "PBXProject"
}
```This`PBXProject`instance contains an array of references to targets (`PBXNativeTarget`instances).
Get help from the **project** object:
```ruby
>> project.help
target = project.targets.first
=> PBXNativeTarget
list = project.build_configuration_list
=> XCConfigurationList
group = project.main_group
=> PBXGroup
```This time the help suggests three objects we can retrieve next; the first`PBXNativeTarget`instance, the sole`XCConfigurationList`instance, and the main`PBXGroup`instance.
Enter the target statement:
```ruby
>> target = project.targets.first
=> 4D0B818B1657473000DEF560 = {
productName = "Example"
productReference = "4D0B818C1657473000DEF560"
name = "Example"
dependencies = []
buildConfigurationList = "4D0B81BF1657473100DEF560"
productType = "com.apple.product-type.application"
buildPhases = ["4D0B81881657473000DEF560", "4D0B81891657473000DEF560", "4D0B818A1657473000DEF560"]
isa = "PBXNativeTarget"
buildRules = []
}
```You can continue exploring the object graph in this manner, down to `PBXFileReference`objects, which contain no references to other objects.
### Example: removing a source file
```ruby
file_ref = project_file.objects_of_class(PBXFileReference, { "path" => "ExampleTests.m" }).first
build_phases = project_file.objects_of_class PBXBuildPhase
build_files = project_file.objects_of_class PBXBuildFile, { "fileRef" => file_ref.uuid }
build_file_uuids = build_files.map { |obj| obj.uuid }
groups = project_file.objects_of_class PBXGroupbuild_phases.each { |phase| phase["files"] -= build_file_uuids }
build_files.each { |obj| project_file.remove_object obj }
groups.each { |group| group["children"].delete file_ref }
project_file.remove_object file_refproject_file.save
```### Example: adding a source file
```ruby
file_ref = project_file.new_object PBXFileReference, { "path" => "Example.c", "sourceTree" => "", "lastKnownFileType" => "sourcecode.c.c" }
build_file = project_file.new_object PBXBuildFile, { "fileRef" => file_ref.uuid }build_phases = project_file.objects_of_class PBXSourcesBuildPhase
build_phases.each { |phase| phase["files"] << build_file.uuid }project_file.save
```## LICENSE
MIT license.