Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 73;
objectVersion = 77;
objects = {

/* Begin PBXCopyFilesBuildPhase section */
Expand All @@ -23,7 +23,7 @@
/* End PBXFileReference section */

/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
6CF05BA32C53F97F00EF267F /* PBXFileSystemSynchronizedBuildFileExceptionSet */ = {
6CF05BA32C53F97F00EF267F /* Exceptions for "SynchronizedRootGroups" folder in "SynchronizedRootGroups" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
Exception/Exception.swift,
Expand All @@ -33,7 +33,7 @@
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */

/* Begin PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */
F841A9D12D63B00A00059ED6 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */ = {
F841A9D12D63B00A00059ED6 /* Exceptions for "SynchronizedRootGroups" folder in "Copy Files" phase from "SynchronizedRootGroups" target */ = {
isa = PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet;
attributesByRelativePath = {
XPCService.xpc = (
Expand All @@ -48,7 +48,15 @@
/* End PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet section */

/* Begin PBXFileSystemSynchronizedRootGroup section */
6CF05B9D2C53F64800EF267F /* SynchronizedRootGroups */ = {isa = PBXFileSystemSynchronizedRootGroup; exceptions = (6CF05BA32C53F97F00EF267F /* PBXFileSystemSynchronizedBuildFileExceptionSet */, F841A9D12D63B00A00059ED6 /* PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet */, ); explicitFileTypes = {}; explicitFolders = (); path = SynchronizedRootGroups; sourceTree = "<group>"; };
6CF05B9D2C53F64800EF267F /* SynchronizedRootGroups */ = {
isa = PBXFileSystemSynchronizedRootGroup;
exceptions = (
6CF05BA32C53F97F00EF267F /* Exceptions for "SynchronizedRootGroups" folder in "SynchronizedRootGroups" target */,
F841A9D12D63B00A00059ED6 /* Exceptions for "SynchronizedRootGroups" folder in "Copy Files" phase from "SynchronizedRootGroups" target */,
);
path = SynchronizedRootGroups;
sourceTree = "<group>";
};
/* End PBXFileSystemSynchronizedRootGroup section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -138,7 +146,7 @@
Base,
);
mainGroup = 6CF05B822C53F5F200EF267F;
preferredProjectObjectVersion = 60;
preferredProjectObjectVersion = 77;
productRefGroup = 6CF05B8D2C53F5F200EF267F /* Products */;
projectDirPath = "";
projectRoot = "";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleIdentifier</key>
<string>com.example.XPCService</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>XPCService</string>
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>XPCService</key>
<dict>
<key>ServiceType</key>
<string>Application</string>
</dict>
</dict>
</plist>
49 changes: 24 additions & 25 deletions Fixtures/iOS/Project.xcodeproj/xcshareddata/xcschemes/iOS.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,6 @@
</ActionContent>
</ExecutionAction>
</PostActions>
<TestPlans>
<TestPlanReference
default = "YES"
reference = "container:iOS.xctestplan">
</TestPlanReference>
</TestPlans>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
Expand All @@ -96,19 +90,6 @@
ReferencedContainer = "container:Project.xcodeproj">
</BuildableReference>
</MacroExpansion>
<Testables>
<TestableReference
skipped = "NO"
useTestSelectionWhitelist = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "23766C251EAA3484007A9026"
BuildableName = "iOSTests.xctest"
BlueprintName = "iOSTests"
ReferencedContainer = "container:Project.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
<CommandLineArguments>
<CommandLineArgument
argument = "MyTestArgument"
Expand All @@ -122,6 +103,24 @@
isEnabled = "NO">
</EnvironmentVariable>
</EnvironmentVariables>
<TestPlans>
<TestPlanReference
reference = "container:iOS.xctestplan"
default = "YES">
</TestPlanReference>
</TestPlans>
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "23766C251EAA3484007A9026"
BuildableName = "iOSTests.xctest"
BlueprintName = "iOSTests"
ReferencedContainer = "container:Project.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand All @@ -131,9 +130,9 @@
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
customLaunchCommand = "custom command"
debugServiceExtension = "internal"
allowLocationSimulation = "YES"
customLaunchCommand = "custom command">
allowLocationSimulation = "YES">
<PreActions>
<ExecutionAction
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
Expand Down Expand Up @@ -180,10 +179,6 @@
ReferencedContainer = "container:Project.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<LocationScenarioReference
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
referenceType = "1">
</LocationScenarioReference>
<CommandLineArguments>
<CommandLineArgument
argument = "MyLaunchArgument"
Expand All @@ -197,6 +192,10 @@
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
<LocationScenarioReference
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
referenceType = "1">
</LocationScenarioReference>
<StoreKitConfigurationFileReference
identifier = "../../Configuration.storekit">
</StoreKitConfigurationFileReference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Release"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO"
useTestSelectionWhitelist = "NO">
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "23766C251EAA3484007A9026"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
Expand Down
5 changes: 5 additions & 0 deletions Sources/XcodeProj/Extensions/AEXML+XcodeFormat.swift
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ let attributesOrder: [String: [String]] = [
"customWorkingDirectory",
"ignoresPersistentStateOnLaunch",
"debugDocumentVersioning",
"customLaunchCommand",
"debugServiceExtension",
"enableGPUFrameCaptureMode",
"enableGPUValidationMode",
Expand Down Expand Up @@ -90,6 +91,10 @@ let attributesOrder: [String: [String]] = [
"parallelizable",
"testExecutionOrdering",
],
"TestPlanReference": [
"reference",
"default",
],
"BreakpointContent": [
"shouldBeEnabled",
"ignoreCount",
Expand Down
23 changes: 23 additions & 0 deletions Sources/XcodeProj/Objects/BuildPhase/PBXBuildPhase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,29 @@ public extension PBXBuildPhase {
buildPhase
}

/// Returns the target this build phase belongs to, if any.
///
/// - Returns: the owning target, or nil if not found.
func target() -> PBXTarget? {
guard let projectObjects = try? objects() else { return nil }
let allTargets: [PBXTarget] = Array(projectObjects.nativeTargets.values)
+ Array(projectObjects.legacyTargets.values)
+ Array(projectObjects.aggregateTargets.values)
return allTargets.first { $0.buildPhaseReferences.map(\.value).contains(reference.value) }
}

/// Human-readable display name, used in descriptive comment strings.
///
/// - Returns: display name matching Xcode's comment format.
func displayName() -> String? {
if let phase = self as? PBXCopyFilesBuildPhase {
return phase.name ?? "Copy Files"
} else if let phase = self as? PBXShellScriptBuildPhase {
return phase.name ?? "Run Script"
}
return name()
}

/// Build phase name.
///
/// - Returns: build phase name.
Expand Down
20 changes: 10 additions & 10 deletions Sources/XcodeProj/Objects/Files/PBXFileElement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,16 @@ public class PBXFileElement: PBXContainerItem, PlistSerializable {
guard let rhs = object as? PBXFileElement else { return false }
return isEqual(to: rhs)
}

// This method is needed to recursively set the parent to all elements.
// This allows us to more quickly find the full path to the elements.
func assignParentToChildren() {
guard let group = self as? PBXGroup else { return }
for child in group.children {
child.parent = self
child.assignParentToChildren()
}
}
}

// MARK: - Helpers
Expand Down Expand Up @@ -206,14 +216,4 @@ public extension PBXFileElement {
.first(where: { $0.name == "Base" }) else { return nil }
return baseReference.path
}

// This method is needed to recursively set the parent to all elements.
// This allows us to more quickly find the full path to the elements.
func assignParentToChildren() {
guard let group = self as? PBXGroup else { return }
for child in group.children {
child.parent = self
child.assignParentToChildren()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public class PBXFileSystemSynchronizedBuildFileExceptionSet: PBXFileSystemSynchr

// MARK: - PlistSerializable

override var plistComment: String {
let folder = synchronizedRootGroup?.fileName() ?? ""
return "Exceptions for \"\(folder)\" folder in \"\(target.name)\" target"
}

func plistKeyAndValue(proj _: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) {
var dictionary: [CommentedString: PlistValue] = [:]
dictionary["isa"] = .string(CommentedString(PBXFileSystemSynchronizedBuildFileExceptionSet.isa))
Expand Down Expand Up @@ -124,6 +129,6 @@ public class PBXFileSystemSynchronizedBuildFileExceptionSet: PBXFileSystemSynchr
}))
}
dictionary["target"] = .string(CommentedString(target.reference.value, comment: target.name))
return (key: CommentedString(reference, comment: "PBXFileSystemSynchronizedBuildFileExceptionSet"), value: .dictionary(dictionary))
return (key: CommentedString(reference, comment: plistComment), value: .dictionary(dictionary))
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import Foundation

/// Common class for exception sets, such as `PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet` and `PBXFileSystemSynchronizedBuildFileExceptionSet`
public class PBXFileSystemSynchronizedExceptionSet: PBXObject {}
public class PBXFileSystemSynchronizedExceptionSet: PBXObject {
/// The synchronized root group this exception set belongs to.
public internal(set) weak var synchronizedRootGroup: PBXFileSystemSynchronizedRootGroup?

/// The comment string used when this object is referenced in a plist.
var plistComment: String { type(of: self).isa }
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ public class PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet: PBX

// MARK: - PlistSerializable

override var plistComment: String {
guard let group = synchronizedRootGroup else { return type(of: self).isa }
let folder = group.fileName() ?? ""
let phase = buildPhase.displayName() ?? ""
let target = buildPhase.target()?.name ?? ""
return "Exceptions for \"\(folder)\" folder in \"\(phase)\" phase from \"\(target)\" target"
}

func plistKeyAndValue(proj _: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) {
var dictionary: [CommentedString: PlistValue] = [:]
dictionary["isa"] = .string(CommentedString(type(of: self).isa))
Expand All @@ -78,6 +86,6 @@ public class PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet: PBX
}))
}
dictionary["buildPhase"] = .string(CommentedString(buildPhase.reference.value, comment: buildPhase.name() ?? "CopyFiles"))
return (key: CommentedString(reference, comment: "PBXFileSystemSynchronizedGroupBuildPhaseMembershipExceptionSet"), value: .dictionary(dictionary))
return (key: CommentedString(reference, comment: plistComment), value: .dictionary(dictionary))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,24 +83,30 @@ public class PBXFileSystemSynchronizedRootGroup: PBXFileElement {

// MARK: - PlistSerializable

override var multiline: Bool { (exceptions?.count ?? 0) < 2 }
override func assignParentToChildren() {
super.assignParentToChildren()
exceptions?.forEach { $0.synchronizedRootGroup = self }
}

override func plistKeyAndValue(proj: PBXProj, reference: String) throws -> (key: CommentedString, value: PlistValue) {
var dictionary: [CommentedString: PlistValue] = try super.plistKeyAndValue(proj: proj, reference: reference).value.dictionary ?? [:]
dictionary["isa"] = .string(CommentedString(type(of: self).isa))
if let exceptions, !exceptions.isEmpty {
dictionary["exceptions"] = .array(exceptions.map { exception in
.string(CommentedString(exception.reference.value, comment: type(of: exception).isa))
.string(CommentedString(exception.reference.value, comment: exception.plistComment))
})
}
if let explicitFileTypes {
if let explicitFileTypes, !explicitFileTypes.isEmpty {
dictionary["explicitFileTypes"] = .dictionary(Dictionary(uniqueKeysWithValues: explicitFileTypes.map { relativePath, fileType in
(CommentedString(relativePath), .string(CommentedString(fileType)))
}))
}
if let explicitFolders {
if let explicitFolders, !explicitFolders.isEmpty {
dictionary["explicitFolders"] = .array(explicitFolders.map { .string(CommentedString($0)) })
}
if name == path {
dictionary["name"] = nil
}
return (key: CommentedString(reference,
comment: name ?? path),
value: .dictionary(dictionary))
Expand Down
1 change: 1 addition & 0 deletions Sources/XcodeProj/Project/Xcode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ public enum Xcode {
"xcsynspec": "text.plist.xcsynspec",
"xctarget": "wrapper.pb-target",
"xctest": "wrapper.cfbundle",
"xctestplan": "text",
"xctxtmacro": "text.plist.xctxtmacro",
"xcworkspace": "wrapper.workspace",
"xhtml": "text.xml",
Expand Down
Loading
Loading