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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### Added
- Added support for Swift package `traits` on remote and local package references, so generated projects preserve the configured trait selections #1629 @philprime
- Added scheme build architecture overrides #1642 @arhxam

### Changed
- Targets in the generated project now follow the declaration order from the source spec (Xcode sidebar, `xcodebuild -list` output). Previously they were always sorted alphabetically. Applies to both YAML and JSON specs. Declaration order is now also preserved for targets whose `platform`/`name` come from a target template and for targets whose key is a `${VARIABLE}`. #1619 @mirkokg
Expand Down
2 changes: 2 additions & 0 deletions Docs/ProjectSpec.md
Original file line number Diff line number Diff line change
Expand Up @@ -1019,6 +1019,7 @@ Schemes allows for more control than the convenience [Target Scheme](#target-sch
- [ ] **runPostActionsOnFailure**: **Bool** - Flag to determine if Xcode should run post scripts despite failure build. By default this is `false` if not set.
- `true`: Run post scripts even if build is failed
- `false`: Only run post scripts if build success
- [ ] **buildArchitectures**: **String** - Overrides the architectures built for all targets in the scheme. Supported values are `matchRunDestination`, `universal`, and `useTargetSettings`. By default this is `useTargetSettings` if not set.


```yaml
Expand All @@ -1027,6 +1028,7 @@ targets:
FooLib/FooTarget: [test, run]
parallelizeBuild: true
buildImplicitDependencies: true
buildArchitectures: matchRunDestination
```

### Common Build Action options
Expand Down
35 changes: 34 additions & 1 deletion Sources/ProjectSpec/Scheme.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import PathKit
import XcodeProj

public typealias BuildType = XCScheme.BuildAction.Entry.BuildFor
public typealias BuildArchitectures = XCScheme.BuildAction.Architectures

public struct Scheme: Equatable {

Expand Down Expand Up @@ -101,28 +102,32 @@ public struct Scheme: Equatable {
public static let parallelizeBuildDefault = true
public static let buildImplicitDependenciesDefault = true
public static let runPostActionsOnFailureDefault = false
public static let buildArchitecturesDefault = BuildArchitectures.useTargetSettings

public var targets: [BuildTarget]
public var parallelizeBuild: Bool
public var buildImplicitDependencies: Bool
public var preActions: [ExecutionAction]
public var postActions: [ExecutionAction]
public var runPostActionsOnFailure: Bool
public var buildArchitectures: BuildArchitectures

public init(
targets: [BuildTarget],
parallelizeBuild: Bool = parallelizeBuildDefault,
buildImplicitDependencies: Bool = buildImplicitDependenciesDefault,
preActions: [ExecutionAction] = [],
postActions: [ExecutionAction] = [],
runPostActionsOnFailure: Bool = false
runPostActionsOnFailure: Bool = runPostActionsOnFailureDefault,
buildArchitectures: BuildArchitectures = buildArchitecturesDefault
) {
self.targets = targets
self.parallelizeBuild = parallelizeBuild
self.buildImplicitDependencies = buildImplicitDependencies
self.preActions = preActions
self.postActions = postActions
self.runPostActionsOnFailure = runPostActionsOnFailure
self.buildArchitectures = buildArchitectures
}
}

Expand Down Expand Up @@ -946,6 +951,7 @@ extension Scheme.Build: JSONObjectConvertible {
parallelizeBuild = jsonDictionary.json(atKeyPath: "parallelizeBuild") ?? Scheme.Build.parallelizeBuildDefault
buildImplicitDependencies = jsonDictionary.json(atKeyPath: "buildImplicitDependencies") ?? Scheme.Build.buildImplicitDependenciesDefault
runPostActionsOnFailure = jsonDictionary.json(atKeyPath: "runPostActionsOnFailure") ?? Scheme.Build.runPostActionsOnFailureDefault
buildArchitectures = jsonDictionary.json(atKeyPath: "buildArchitectures") ?? Scheme.Build.buildArchitecturesDefault
}
}

Expand All @@ -968,6 +974,9 @@ extension Scheme.Build: JSONEncodable {
if runPostActionsOnFailure != Scheme.Build.runPostActionsOnFailureDefault {
dict["runPostActionsOnFailure"] = runPostActionsOnFailure
}
if buildArchitectures != Scheme.Build.buildArchitecturesDefault {
dict["buildArchitectures"] = buildArchitectures.toJSONValue()
}

return dict
}
Expand Down Expand Up @@ -1005,6 +1014,30 @@ extension BuildType: JSONEncodable {
}
}

extension BuildArchitectures: JSONUtilities.JSONPrimitiveConvertible {

public typealias JSONType = String

public static func from(jsonValue: String) -> BuildArchitectures? {
switch jsonValue {
case "matchRunDestination": return .matchRunDestination
case "universal": return .universal
case "useTargetSettings": return .useTargetSettings
default: return nil
}
}
}

extension BuildArchitectures: JSONEncodable {
public func toJSONValue() -> Any {
switch self {
case .matchRunDestination: return "matchRunDestination"
case .universal: return "universal"
case .useTargetSettings: return "useTargetSettings"
}
}
}

extension XCScheme.EnvironmentVariable: JSONUtilities.JSONObjectConvertible {
public static let enabledDefault = true

Expand Down
3 changes: 2 additions & 1 deletion Sources/XcodeGenKit/SchemeGenerator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ public class SchemeGenerator {
postActions: scheme.build.postActions.map(getExecutionAction),
parallelizeBuild: scheme.build.parallelizeBuild,
buildImplicitDependencies: scheme.build.buildImplicitDependencies,
runPostActionsOnFailure: scheme.build.runPostActionsOnFailure
runPostActionsOnFailure: scheme.build.runPostActionsOnFailure,
buildArchitectures: scheme.build.buildArchitectures
)

let testables: [XCScheme.TestableReference] = zip(testTargets, testBuildTargetEntries).map { testTarget, testBuildEntries in
Expand Down
20 changes: 20 additions & 0 deletions Tests/ProjectSpecTests/SpecLoadingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,7 @@ class SpecLoadingTests: XCTestCase {
"parallelizeBuild": false,
"buildImplicitDependencies": false,
"runPostActionsOnFailure": true,
"buildArchitectures": "matchRunDestination",
"targets": [
"Target1": "all",
"Target2": "testing",
Expand Down Expand Up @@ -1100,6 +1101,7 @@ class SpecLoadingTests: XCTestCase {
try expect(scheme.build.parallelizeBuild) == false
try expect(scheme.build.buildImplicitDependencies) == false
try expect(scheme.build.runPostActionsOnFailure) == true
try expect(scheme.build.buildArchitectures) == .matchRunDestination

let expectedRun = Scheme.Run(
config: "debug",
Expand Down Expand Up @@ -1137,6 +1139,24 @@ class SpecLoadingTests: XCTestCase {
try expect(scheme.management) == expectedManagement
}

$0.it("encodes scheme build architecture overrides") {
let architectureOptions: [(BuildArchitectures, String)] = [
(.matchRunDestination, "matchRunDestination"),
(.universal, "universal"),
]

for (option, expected) in architectureOptions {
let build = Scheme.Build(targets: [], buildArchitectures: option)
let dictionary = try unwrap(build.toJSONValue() as? [String: Any])

try expect(dictionary["buildArchitectures"] as? String) == expected
}

let defaultBuild = Scheme.Build(targets: [])
let defaultDictionary = try unwrap(defaultBuild.toJSONValue() as? [String: Any])
try expect(defaultDictionary["buildArchitectures"]).to.beNil()
}

$0.it("parses alternate test schemes") {
let schemeDictionary: [String: Any] = [
"build": [
Expand Down
22 changes: 22 additions & 0 deletions Tests/XcodeGenKitTests/SchemeGeneratorTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,28 @@ class SchemeGeneratorTests: XCTestCase {
try expect(xcscheme.testAction?.testables[1].locationScenarioReference?.identifier) == "New York, NY, USA"
}

$0.it("generates scheme build architecture overrides") {
let architectureOptions: [(String, XCScheme.BuildAction.Architectures)] = [
("matchRunDestination", .matchRunDestination),
("universal", .universal),
("useTargetSettings", .useTargetSettings),
]

for (option, expected) in architectureOptions {
let scheme = try Scheme(name: "MyScheme", jsonDictionary: [
"build": [
"targets": [app.name: "all"],
"buildArchitectures": option,
],
])
let project = Project(name: "test", targets: [app, framework], schemes: [scheme])
let xcodeProject = try project.generateXcodeProject()
let xcscheme = try unwrap(xcodeProject.sharedData?.schemes.first)

try expect(xcscheme.buildAction?.buildArchitectures) == expected
}
}

let frameworkTarget = Scheme.BuildTarget(target: .local(framework.name), buildTypes: [.archiving])
$0.it("generates a scheme with the first runnable selected") {
let scheme = Scheme(
Expand Down