Skip to content

Commit feb512a

Browse files
committed
Support for additional scheme options regarding memory management options
1 parent 29bcb92 commit feb512a

10 files changed

Lines changed: 253 additions & 1 deletion

File tree

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import Foundation
2+
import JSONUtilities
3+
4+
public struct AdditionalOptions: Equatable, Hashable {
5+
public var mallocScribble: Bool
6+
public var mallocGuardEdges: Bool
7+
public var guardMalloc: Bool
8+
public var zombieObjects: Bool
9+
10+
public init(mallocScribble: Bool,
11+
mallocGuardEdges: Bool,
12+
guardMalloc: Bool,
13+
zombieObjects: Bool) {
14+
self.mallocScribble = mallocScribble
15+
self.mallocGuardEdges = mallocGuardEdges
16+
self.guardMalloc = guardMalloc
17+
self.zombieObjects = zombieObjects
18+
}
19+
}
20+
21+
extension AdditionalOptions: JSONObjectConvertible {
22+
public init(jsonDictionary: JSONDictionary) throws {
23+
mallocScribble = jsonDictionary.json(atKeyPath: "mallocScribble") ?? false
24+
mallocGuardEdges = jsonDictionary.json(atKeyPath: "mallocGuardEdges") ?? false
25+
guardMalloc = jsonDictionary.json(atKeyPath: "guardMalloc") ?? false
26+
zombieObjects = jsonDictionary.json(atKeyPath: "zombieObjects") ?? false
27+
}
28+
}
29+
30+
extension AdditionalOptions: JSONEncodable {
31+
public func toJSONValue() -> Any {
32+
[
33+
"mallocScribble": mallocScribble,
34+
"mallocGuardEdges": mallocGuardEdges,
35+
"guardMalloc": guardMalloc,
36+
"zombieObjects": zombieObjects,
37+
]
38+
}
39+
}

Sources/ProjectSpec/Scheme.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ public struct Scheme: Equatable {
111111
public var environmentVariables: [XCScheme.EnvironmentVariable]
112112
public var disableMainThreadChecker: Bool
113113
public var stopOnEveryMainThreadCheckerIssue: Bool
114+
public var additionalOptions: AdditionalOptions?
114115
public var language: String?
115116
public var region: String?
116117
public var askForAppToLaunch: Bool?
@@ -131,6 +132,7 @@ public struct Scheme: Equatable {
131132
environmentVariables: [XCScheme.EnvironmentVariable] = [],
132133
disableMainThreadChecker: Bool = disableMainThreadCheckerDefault,
133134
stopOnEveryMainThreadCheckerIssue: Bool = stopOnEveryMainThreadCheckerIssueDefault,
135+
additionalOptions: AdditionalOptions? = nil,
134136
language: String? = nil,
135137
region: String? = nil,
136138
askForAppToLaunch: Bool? = nil,
@@ -148,6 +150,7 @@ public struct Scheme: Equatable {
148150
self.environmentVariables = environmentVariables
149151
self.disableMainThreadChecker = disableMainThreadChecker
150152
self.stopOnEveryMainThreadCheckerIssue = stopOnEveryMainThreadCheckerIssue
153+
self.additionalOptions = additionalOptions
151154
self.language = language
152155
self.region = region
153156
self.askForAppToLaunch = askForAppToLaunch
@@ -171,6 +174,8 @@ public struct Scheme: Equatable {
171174
public var gatherCoverageData: Bool
172175
public var coverageTargets: [TestableTargetReference]
173176
public var disableMainThreadChecker: Bool
177+
public var additionalOptions: AdditionalOptions?
178+
174179
public var commandLineArguments: [String: Bool]
175180
public var targets: [TestTarget]
176181
public var preActions: [ExecutionAction]
@@ -236,6 +241,7 @@ public struct Scheme: Equatable {
236241
gatherCoverageData: Bool = gatherCoverageDataDefault,
237242
coverageTargets: [TestableTargetReference] = [],
238243
disableMainThreadChecker: Bool = disableMainThreadCheckerDefault,
244+
additionalOptions: AdditionalOptions? = nil,
239245
randomExecutionOrder: Bool = false,
240246
parallelizable: Bool = false,
241247
commandLineArguments: [String: Bool] = [:],
@@ -255,6 +261,7 @@ public struct Scheme: Equatable {
255261
self.gatherCoverageData = gatherCoverageData
256262
self.coverageTargets = coverageTargets
257263
self.disableMainThreadChecker = disableMainThreadChecker
264+
self.additionalOptions = additionalOptions
258265
self.commandLineArguments = commandLineArguments
259266
self.targets = targets
260267
self.preActions = preActions
@@ -410,6 +417,7 @@ extension Scheme.Run: JSONObjectConvertible {
410417
environmentVariables = try XCScheme.EnvironmentVariable.parseAll(jsonDictionary: jsonDictionary)
411418
disableMainThreadChecker = jsonDictionary.json(atKeyPath: "disableMainThreadChecker") ?? Scheme.Run.disableMainThreadCheckerDefault
412419
stopOnEveryMainThreadCheckerIssue = jsonDictionary.json(atKeyPath: "stopOnEveryMainThreadCheckerIssue") ?? Scheme.Run.stopOnEveryMainThreadCheckerIssueDefault
420+
additionalOptions = jsonDictionary.json(atKeyPath: "additionalOptions")
413421
language = jsonDictionary.json(atKeyPath: "language")
414422
region = jsonDictionary.json(atKeyPath: "region")
415423
debugEnabled = jsonDictionary.json(atKeyPath: "debugEnabled") ?? Scheme.Run.debugEnabledDefault
@@ -505,6 +513,7 @@ extension Scheme.Test: JSONObjectConvertible {
505513
}
506514

507515
disableMainThreadChecker = jsonDictionary.json(atKeyPath: "disableMainThreadChecker") ?? Scheme.Test.disableMainThreadCheckerDefault
516+
additionalOptions = jsonDictionary.json(atKeyPath: "additionalOptions")
508517
commandLineArguments = jsonDictionary.json(atKeyPath: "commandLineArguments") ?? [:]
509518
if let targets = jsonDictionary["targets"] as? [Any] {
510519
self.targets = try targets.compactMap { target in

Sources/ProjectSpec/TargetScheme.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ public struct TargetScheme: Equatable {
1717
public var region: String?
1818
public var disableMainThreadChecker: Bool
1919
public var stopOnEveryMainThreadCheckerIssue: Bool
20+
public var additionalOptions: AdditionalOptions?
2021
public var buildImplicitDependencies: Bool
2122
public var commandLineArguments: [String: Bool]
2223
public var environmentVariables: [XCScheme.EnvironmentVariable]
@@ -35,6 +36,7 @@ public struct TargetScheme: Equatable {
3536
region: String? = nil,
3637
disableMainThreadChecker: Bool = disableMainThreadCheckerDefault,
3738
stopOnEveryMainThreadCheckerIssue: Bool = stopOnEveryMainThreadCheckerIssueDefault,
39+
additionalOptions: AdditionalOptions? = nil,
3840
buildImplicitDependencies: Bool = buildImplicitDependenciesDefault,
3941
commandLineArguments: [String: Bool] = [:],
4042
environmentVariables: [XCScheme.EnvironmentVariable] = [],
@@ -51,6 +53,7 @@ public struct TargetScheme: Equatable {
5153
self.region = region
5254
self.disableMainThreadChecker = disableMainThreadChecker
5355
self.stopOnEveryMainThreadCheckerIssue = stopOnEveryMainThreadCheckerIssue
56+
self.additionalOptions = additionalOptions
5457
self.buildImplicitDependencies = buildImplicitDependencies
5558
self.commandLineArguments = commandLineArguments
5659
self.environmentVariables = environmentVariables
@@ -100,6 +103,7 @@ extension TargetScheme: JSONObjectConvertible {
100103
region = jsonDictionary.json(atKeyPath: "region")
101104
disableMainThreadChecker = jsonDictionary.json(atKeyPath: "disableMainThreadChecker") ?? TargetScheme.disableMainThreadCheckerDefault
102105
stopOnEveryMainThreadCheckerIssue = jsonDictionary.json(atKeyPath: "stopOnEveryMainThreadCheckerIssue") ?? TargetScheme.stopOnEveryMainThreadCheckerIssueDefault
106+
additionalOptions = jsonDictionary.json(atKeyPath: "additionalOptions")
103107
buildImplicitDependencies = jsonDictionary.json(atKeyPath: "buildImplicitDependencies") ?? TargetScheme.buildImplicitDependenciesDefault
104108
commandLineArguments = jsonDictionary.json(atKeyPath: "commandLineArguments") ?? [:]
105109
environmentVariables = try XCScheme.EnvironmentVariable.parseAll(jsonDictionary: jsonDictionary)
@@ -136,6 +140,10 @@ extension TargetScheme: JSONEncodable {
136140
if stopOnEveryMainThreadCheckerIssue != TargetScheme.stopOnEveryMainThreadCheckerIssueDefault {
137141
dict["stopOnEveryMainThreadCheckerIssue"] = stopOnEveryMainThreadCheckerIssue
138142
}
143+
144+
if let additionalOptions = additionalOptions {
145+
dict["additionalOptions"] = additionalOptions.toJSONValue()
146+
}
139147

140148
if buildImplicitDependencies != TargetScheme.buildImplicitDependenciesDefault {
141149
dict["buildImplicitDependencies"] = buildImplicitDependencies

Sources/XcodeGenKit/SchemeGenerator.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,24 @@ public class SchemeGenerator {
249249
let testPlans = scheme.test?.testPlans.enumerated().map { index, testPlan in
250250
XCScheme.TestPlanReference(reference: "container:\(testPlan.path)", default: defaultTestPlanIndex == index)
251251
} ?? []
252-
252+
253+
func getAdditionalOptions(_ options: AdditionalOptions) -> [XCScheme.AdditionalOption] {
254+
var additionalOptions: [XCScheme.AdditionalOption] = []
255+
if options.mallocScribble {
256+
additionalOptions.append(XCScheme.AdditionalOption(key: "MallocScribble", value: "", isEnabled: true))
257+
}
258+
if options.mallocGuardEdges {
259+
additionalOptions.append(XCScheme.AdditionalOption(key: "MallocGuardEdges", value: "", isEnabled: true))
260+
}
261+
if options.guardMalloc {
262+
additionalOptions.append(XCScheme.AdditionalOption(key: "DYLD_INSERT_LIBRARIES", value: "/usr/lib/libgmalloc.dylib", isEnabled: true))
263+
}
264+
if options.zombieObjects {
265+
additionalOptions.append(XCScheme.AdditionalOption(key: "NSZombieEnabled", value: "YES", isEnabled: true))
266+
}
267+
return additionalOptions
268+
}
269+
253270
let testAction = XCScheme.TestAction(
254271
buildConfiguration: scheme.test?.config ?? defaultDebugConfig.name,
255272
macroExpansion: buildableReference,
@@ -264,6 +281,7 @@ public class SchemeGenerator {
264281
codeCoverageTargets: coverageBuildableTargets,
265282
onlyGenerateCoverageForSpecifiedTargets: !coverageBuildableTargets.isEmpty,
266283
disableMainThreadChecker: scheme.test?.disableMainThreadChecker ?? Scheme.Test.disableMainThreadCheckerDefault,
284+
additionalOptions: scheme.test?.additionalOptions.map(getAdditionalOptions) ?? [],
267285
commandlineArguments: testCommandLineArgs,
268286
environmentVariables: testVariables,
269287
language: scheme.test?.language,
@@ -310,6 +328,7 @@ public class SchemeGenerator {
310328
locationScenarioReference: locationScenarioReference,
311329
disableMainThreadChecker: scheme.run?.disableMainThreadChecker ?? Scheme.Run.disableMainThreadCheckerDefault,
312330
stopOnEveryMainThreadCheckerIssue: scheme.run?.stopOnEveryMainThreadCheckerIssue ?? Scheme.Run.stopOnEveryMainThreadCheckerIssueDefault,
331+
additionalOptions: scheme.run?.additionalOptions.map(getAdditionalOptions) ?? [],
313332
commandlineArguments: launchCommandLineArgs,
314333
environmentVariables: launchVariables,
315334
language: scheme.run?.language,
@@ -433,6 +452,7 @@ extension Scheme {
433452
environmentVariables: targetScheme.environmentVariables,
434453
disableMainThreadChecker: targetScheme.disableMainThreadChecker,
435454
stopOnEveryMainThreadCheckerIssue: targetScheme.stopOnEveryMainThreadCheckerIssue,
455+
additionalOptions: targetScheme.additionalOptions,
436456
language: targetScheme.language,
437457
region: targetScheme.region,
438458
storeKitConfiguration: targetScheme.storeKitConfiguration
@@ -442,6 +462,7 @@ extension Scheme {
442462
gatherCoverageData: targetScheme.gatherCoverageData,
443463
coverageTargets: targetScheme.coverageTargets,
444464
disableMainThreadChecker: targetScheme.disableMainThreadChecker,
465+
additionalOptions: targetScheme.additionalOptions,
445466
commandLineArguments: targetScheme.commandLineArguments,
446467
targets: targetScheme.testTargets,
447468
environmentVariables: targetScheme.environmentVariables,

Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_iOS Production.xcscheme

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,28 @@
8181
ReferencedContainer = "container:Project.xcodeproj">
8282
</BuildableReference>
8383
</CodeCoverageTargets>
84+
<AdditionalOptions>
85+
<AdditionalOption
86+
isEnabled = "YES"
87+
key = "MallocScribble"
88+
value = "">
89+
</AdditionalOption>
90+
<AdditionalOption
91+
isEnabled = "YES"
92+
key = "MallocGuardEdges"
93+
value = "">
94+
</AdditionalOption>
95+
<AdditionalOption
96+
isEnabled = "YES"
97+
key = "DYLD_INSERT_LIBRARIES"
98+
value = "/usr/lib/libgmalloc.dylib">
99+
</AdditionalOption>
100+
<AdditionalOption
101+
isEnabled = "YES"
102+
key = "NSZombieEnabled"
103+
value = "YES">
104+
</AdditionalOption>
105+
</AdditionalOptions>
84106
</TestAction>
85107
<LaunchAction
86108
buildConfiguration = "Production Debug"
@@ -117,6 +139,28 @@
117139
<StoreKitConfigurationFileReference
118140
identifier = "../../App_iOS/Configuration.storekit">
119141
</StoreKitConfigurationFileReference>
142+
<AdditionalOptions>
143+
<AdditionalOption
144+
isEnabled = "YES"
145+
key = "MallocScribble"
146+
value = "">
147+
</AdditionalOption>
148+
<AdditionalOption
149+
isEnabled = "YES"
150+
key = "MallocGuardEdges"
151+
value = "">
152+
</AdditionalOption>
153+
<AdditionalOption
154+
isEnabled = "YES"
155+
key = "DYLD_INSERT_LIBRARIES"
156+
value = "/usr/lib/libgmalloc.dylib">
157+
</AdditionalOption>
158+
<AdditionalOption
159+
isEnabled = "YES"
160+
key = "NSZombieEnabled"
161+
value = "YES">
162+
</AdditionalOption>
163+
</AdditionalOptions>
120164
</LaunchAction>
121165
<ProfileAction
122166
buildConfiguration = "Production Release"

Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_iOS Staging.xcscheme

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,28 @@
8181
ReferencedContainer = "container:Project.xcodeproj">
8282
</BuildableReference>
8383
</CodeCoverageTargets>
84+
<AdditionalOptions>
85+
<AdditionalOption
86+
isEnabled = "YES"
87+
key = "MallocScribble"
88+
value = "">
89+
</AdditionalOption>
90+
<AdditionalOption
91+
isEnabled = "YES"
92+
key = "MallocGuardEdges"
93+
value = "">
94+
</AdditionalOption>
95+
<AdditionalOption
96+
isEnabled = "YES"
97+
key = "DYLD_INSERT_LIBRARIES"
98+
value = "/usr/lib/libgmalloc.dylib">
99+
</AdditionalOption>
100+
<AdditionalOption
101+
isEnabled = "YES"
102+
key = "NSZombieEnabled"
103+
value = "YES">
104+
</AdditionalOption>
105+
</AdditionalOptions>
84106
</TestAction>
85107
<LaunchAction
86108
buildConfiguration = "Staging Debug"
@@ -117,6 +139,28 @@
117139
<StoreKitConfigurationFileReference
118140
identifier = "../../App_iOS/Configuration.storekit">
119141
</StoreKitConfigurationFileReference>
142+
<AdditionalOptions>
143+
<AdditionalOption
144+
isEnabled = "YES"
145+
key = "MallocScribble"
146+
value = "">
147+
</AdditionalOption>
148+
<AdditionalOption
149+
isEnabled = "YES"
150+
key = "MallocGuardEdges"
151+
value = "">
152+
</AdditionalOption>
153+
<AdditionalOption
154+
isEnabled = "YES"
155+
key = "DYLD_INSERT_LIBRARIES"
156+
value = "/usr/lib/libgmalloc.dylib">
157+
</AdditionalOption>
158+
<AdditionalOption
159+
isEnabled = "YES"
160+
key = "NSZombieEnabled"
161+
value = "YES">
162+
</AdditionalOption>
163+
</AdditionalOptions>
120164
</LaunchAction>
121165
<ProfileAction
122166
buildConfiguration = "Staging Release"

Tests/Fixtures/TestProject/Project.xcodeproj/xcshareddata/xcschemes/App_iOS Test.xcscheme

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,28 @@
8181
ReferencedContainer = "container:Project.xcodeproj">
8282
</BuildableReference>
8383
</CodeCoverageTargets>
84+
<AdditionalOptions>
85+
<AdditionalOption
86+
isEnabled = "YES"
87+
key = "MallocScribble"
88+
value = "">
89+
</AdditionalOption>
90+
<AdditionalOption
91+
isEnabled = "YES"
92+
key = "MallocGuardEdges"
93+
value = "">
94+
</AdditionalOption>
95+
<AdditionalOption
96+
isEnabled = "YES"
97+
key = "DYLD_INSERT_LIBRARIES"
98+
value = "/usr/lib/libgmalloc.dylib">
99+
</AdditionalOption>
100+
<AdditionalOption
101+
isEnabled = "YES"
102+
key = "NSZombieEnabled"
103+
value = "YES">
104+
</AdditionalOption>
105+
</AdditionalOptions>
84106
</TestAction>
85107
<LaunchAction
86108
buildConfiguration = "Test Debug"
@@ -117,6 +139,28 @@
117139
<StoreKitConfigurationFileReference
118140
identifier = "../../App_iOS/Configuration.storekit">
119141
</StoreKitConfigurationFileReference>
142+
<AdditionalOptions>
143+
<AdditionalOption
144+
isEnabled = "YES"
145+
key = "MallocScribble"
146+
value = "">
147+
</AdditionalOption>
148+
<AdditionalOption
149+
isEnabled = "YES"
150+
key = "MallocGuardEdges"
151+
value = "">
152+
</AdditionalOption>
153+
<AdditionalOption
154+
isEnabled = "YES"
155+
key = "DYLD_INSERT_LIBRARIES"
156+
value = "/usr/lib/libgmalloc.dylib">
157+
</AdditionalOption>
158+
<AdditionalOption
159+
isEnabled = "YES"
160+
key = "NSZombieEnabled"
161+
value = "YES">
162+
</AdditionalOption>
163+
</AdditionalOptions>
120164
</LaunchAction>
121165
<ProfileAction
122166
buildConfiguration = "Test Release"

Tests/Fixtures/TestProject/project.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ targets:
156156
- App_iOS
157157
disableMainThreadChecker: true
158158
stopOnEveryMainThreadCheckerIssue: true
159+
additionalOptions:
160+
mallocScribble: true
161+
mallocGuardEdges: true
162+
guardMalloc: true
163+
zombieObjects: true
159164
configVariants:
160165
- Test
161166
- Staging

0 commit comments

Comments
 (0)