This commit is contained in:
Jonathan Crooke 2024-06-04 10:59:09 +03:00 committed by GitHub
commit 2d14bd7e8f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 63 additions and 28 deletions

View File

@ -8,7 +8,7 @@ public typealias BuildType = XCScheme.BuildAction.Entry.BuildFor
public struct Scheme: Equatable {
public var name: String
public var build: Build
public var build: Build!
public var run: Run?
public var archive: Archive?
public var analyze: Analyze?
@ -18,7 +18,7 @@ public struct Scheme: Equatable {
public init(
name: String,
build: Build,
build: Build? = nil,
run: Run? = nil,
test: Test? = nil,
profile: Profile? = nil,
@ -791,7 +791,7 @@ extension Scheme: NamedJSONDictionaryConvertible {
public init(name: String, jsonDictionary: JSONDictionary) throws {
self.name = name
build = try jsonDictionary.json(atKeyPath: "build")
build = jsonDictionary.json(atKeyPath: "build")
run = jsonDictionary.json(atKeyPath: "run")
test = jsonDictionary.json(atKeyPath: "test")
analyze = jsonDictionary.json(atKeyPath: "analyze")
@ -804,7 +804,7 @@ extension Scheme: NamedJSONDictionaryConvertible {
extension Scheme: JSONEncodable {
public func toJSONValue() -> Any {
[
"build": build.toJSONValue(),
"build": build?.toJSONValue(),
"run": run?.toJSONValue(),
"test": test?.toJSONValue(),
"analyze": analyze?.toJSONValue(),

View File

@ -218,9 +218,11 @@ extension Project {
}
for scheme in schemes {
errors.append(
contentsOf: scheme.build.targets.compactMap { validationError(for: $0.target, in: scheme, action: "build") }
)
if let action = scheme.build {
errors.append(contentsOf: action.targets.compactMap {
validationError(for: $0.target, in: scheme, action: "build")
})
}
if let action = scheme.run, let config = action.config, getConfig(config) == nil {
errors.append(.invalidSchemeConfig(scheme: scheme.name, config: config))
}

View File

@ -199,7 +199,7 @@ public class SchemeGenerator {
let testBuildTargetEntries = try testBuildTargets.map(getBuildEntry)
let buildActionEntries: [XCScheme.BuildAction.Entry] = try scheme.build.targets.map(getBuildEntry)
let buildActionEntries: [XCScheme.BuildAction.Entry] = try scheme.build?.targets.map(getBuildEntry) ?? []
func getExecutionAction(_ action: Scheme.ExecutionAction) -> XCScheme.ExecutionAction {
// ExecutionActions can require the use of build settings. Xcode allows the settings to come from a build or test target.
@ -220,27 +220,42 @@ public class SchemeGenerator {
if let targetName = scheme.run?.executable {
schemeTarget = project.getTarget(targetName)
} else {
guard let firstTarget = scheme.build.targets.first else {
throw SchemeGenerationError.missingBuildTargets(scheme.name)
}
let name = scheme.build.targets.first { $0.buildTypes.contains(.running) }?.target.name ?? firstTarget.target.name
} else if
let targets = scheme.build?.targets,
let firstTarget = targets.first
{
let name = targets.first { $0.buildTypes.contains(.running) }?.target.name ?? firstTarget.target.name
schemeTarget = target ?? project.getTarget(name)
} else {
schemeTarget = nil
}
let shouldExecuteOnLaunch = schemeTarget?.shouldExecuteOnLaunch == true
let buildableReference: XCScheme.BuildableReference?
let buildAction: XCScheme.BuildAction?
let runnables: (launch: XCScheme.Runnable, profile: XCScheme.BuildableProductRunnable)?
let buildableReference = buildActionEntries.first(where: { $0.buildableReference.blueprintName == schemeTarget?.name })?.buildableReference ?? buildActionEntries.first!.buildableReference
let runnables = makeProductRunnables(for: schemeTarget, buildableReference: buildableReference)
if let buildableReferenceCandidate = buildActionEntries.first(where: { $0.buildableReference.blueprintName == schemeTarget?.name })?.buildableReference ?? buildActionEntries.first?.buildableReference
{
runnables = makeProductRunnables(for: schemeTarget, buildableReference: buildableReferenceCandidate)
buildableReference = buildableReferenceCandidate
buildAction = scheme.build.flatMap { build in
XCScheme.BuildAction(
buildActionEntries: buildActionEntries,
preActions: build.preActions.map(getExecutionAction),
postActions: build.postActions.map(getExecutionAction),
parallelizeBuild: build.parallelizeBuild,
buildImplicitDependencies: build.buildImplicitDependencies,
runPostActionsOnFailure: build.runPostActionsOnFailure
)
}
} else {
buildableReference = nil
buildAction = nil
runnables = nil
}
let buildAction = XCScheme.BuildAction(
buildActionEntries: buildActionEntries,
preActions: scheme.build.preActions.map(getExecutionAction),
postActions: scheme.build.postActions.map(getExecutionAction),
parallelizeBuild: scheme.build.parallelizeBuild,
buildImplicitDependencies: scheme.build.buildImplicitDependencies,
runPostActionsOnFailure: scheme.build.runPostActionsOnFailure
)
let testables: [XCScheme.TestableReference] = zip(testTargets, testBuildTargetEntries).map { testTarget, testBuildEntries in
@ -335,7 +350,7 @@ public class SchemeGenerator {
}
let launchAction = XCScheme.LaunchAction(
runnable: shouldExecuteOnLaunch ? runnables.launch : nil,
runnable: shouldExecuteOnLaunch ? runnables?.launch : nil,
buildConfiguration: scheme.run?.config ?? defaultDebugConfig.name,
preActions: scheme.run?.preActions.map(getExecutionAction) ?? [],
postActions: scheme.run?.postActions.map(getExecutionAction) ?? [],
@ -360,7 +375,7 @@ public class SchemeGenerator {
)
let profileAction = XCScheme.ProfileAction(
buildableProductRunnable: shouldExecuteOnLaunch ? runnables.profile : nil,
buildableProductRunnable: shouldExecuteOnLaunch ? runnables?.profile : nil,
buildConfiguration: scheme.profile?.config ?? defaultReleaseConfig.name,
preActions: scheme.profile?.preActions.map(getExecutionAction) ?? [],
postActions: scheme.profile?.postActions.map(getExecutionAction) ?? [],
@ -442,7 +457,6 @@ enum SchemeGenerationError: Error, CustomStringConvertible {
case missingTarget(TargetReference, projectPath: String)
case missingPackage(String)
case missingProject(String)
case missingBuildTargets(String)
var description: String {
switch self {
@ -450,8 +464,6 @@ enum SchemeGenerationError: Error, CustomStringConvertible {
return "Unable to find target named \"\(target)\" in \"\(projectPath)\""
case .missingProject(let project):
return "Unable to find project reference named \"\(project)\" in project.yml"
case .missingBuildTargets(let name):
return "Unable to find at least one build target in scheme \"\(name)\""
case .missingPackage(let package):
return "Unable to find swift package named \"\(package)\" in project.yml"
}

View File

@ -0,0 +1,12 @@
name: TestOnly
targets:
Target:
type: application
platform: iOS
sources:
- Target
schemes:
TestOnly:
test:
targets:
- Target

View File

@ -75,6 +75,15 @@ class SpecLoadingTests: XCTestCase {
]
}
$0.it("accepts schemes that have no build phase") {
let path = fixturePath + "test_only.yml"
let project = try loadSpec(path: path)
try expect(project.name) == "TestOnly"
try expect(project.schemes.count) == 1
try expect(project.schemes.first?.build).to.beNil()
try expect(project.schemes.first?.test?.targets.first?.name) == "Target"
}
$0.it("expands directories") {
let path = fixturePath + "paths_test.yml"
let project = try loadSpec(path: path)