diff --git a/CHANGELOG.md b/CHANGELOG.md index f48867138..faacbce96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change Log +## Next Version + +### Added +- Added `buildArchitectures` to scheme build options and target schemes, to control Xcode's "Override Architectures" scheme setting #1642 @arhxam + +### Changed +- Generated schemes now default to `buildArchitectures: matchRunDestination` ("Match Run Destination"), matching Xcode's default for new schemes. Previously schemes used each target's architecture settings. Set `buildArchitectures: useTargetSettings` to keep the previous behaviour #1642 @yonaskolb + ## 2.46.0 ### Added diff --git a/Docs/ProjectSpec.md b/Docs/ProjectSpec.md index d8c427804..9fc2f9182 100644 --- a/Docs/ProjectSpec.md +++ b/Docs/ProjectSpec.md @@ -893,6 +893,7 @@ This is a convenience used to automatically generate schemes for a target based - [ ] **stopOnEveryMainThreadCheckerIssue**: **Bool** - a boolean that indicates if this scheme should stop at every Main Thread Checker issue. This defaults to false - [ ] **disableThreadPerformanceChecker**: **Bool** - a boolean that indicates if this scheme should disable the Thread Performance Checker. This defaults to false - [ ] **buildImplicitDependencies**: **Bool** - Flag to determine if Xcode should build implicit dependencies of this scheme. By default this is `true` if not set. +- [ ] **buildArchitectures**: **String** - Overrides the architectures built for all targets in the scheme. Supported values are `matchRunDestination`, `universal`, and `useTargetSettings`. By default this is `matchRunDestination` if not set. See [Build](#build) for details. - [ ] **language**: **String** - a String that indicates the language used for running and testing. This defaults to nil - [ ] **region**: **String** - a String that indicates the region used for running and testing. This defaults to nil - [ ] **commandLineArguments**: **[String:Bool]** - a dictionary from the argument name (`String`) to if it is enabled (`Bool`). These arguments will be added to the Test, Profile and Run scheme actions @@ -1019,6 +1020,10 @@ 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. This is the "Override Architectures" build option in Xcode's scheme editor. By default this is `matchRunDestination` if not set, which matches Xcode's default for new schemes. + - `matchRunDestination`: Only build the architecture of the run destination ("Match Run Destination") + - `universal`: Build all standard architectures ("Universal") + - `useTargetSettings`: Use the architecture build settings of each target, such as `ONLY_ACTIVE_ARCH` ("Use Target Settings") ```yaml @@ -1027,6 +1032,7 @@ targets: FooLib/FooTarget: [test, run] parallelizeBuild: true buildImplicitDependencies: true +buildArchitectures: matchRunDestination ``` ### Common Build Action options diff --git a/Sources/ProjectSpec/Scheme.swift b/Sources/ProjectSpec/Scheme.swift index a19951fe8..8ec56bc56 100644 --- a/Sources/ProjectSpec/Scheme.swift +++ b/Sources/ProjectSpec/Scheme.swift @@ -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 { @@ -101,6 +102,7 @@ public struct Scheme: Equatable { public static let parallelizeBuildDefault = true public static let buildImplicitDependenciesDefault = true public static let runPostActionsOnFailureDefault = false + public static let buildArchitecturesDefault = BuildArchitectures.matchRunDestination public var targets: [BuildTarget] public var parallelizeBuild: Bool @@ -108,6 +110,7 @@ public struct Scheme: Equatable { public var preActions: [ExecutionAction] public var postActions: [ExecutionAction] public var runPostActionsOnFailure: Bool + public var buildArchitectures: BuildArchitectures public init( targets: [BuildTarget], @@ -115,7 +118,8 @@ public struct Scheme: Equatable { buildImplicitDependencies: Bool = buildImplicitDependenciesDefault, preActions: [ExecutionAction] = [], postActions: [ExecutionAction] = [], - runPostActionsOnFailure: Bool = false + runPostActionsOnFailure: Bool = runPostActionsOnFailureDefault, + buildArchitectures: BuildArchitectures = buildArchitecturesDefault ) { self.targets = targets self.parallelizeBuild = parallelizeBuild @@ -123,6 +127,7 @@ public struct Scheme: Equatable { self.preActions = preActions self.postActions = postActions self.runPostActionsOnFailure = runPostActionsOnFailure + self.buildArchitectures = buildArchitectures } } @@ -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 } } @@ -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 } @@ -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 diff --git a/Sources/ProjectSpec/TargetScheme.swift b/Sources/ProjectSpec/TargetScheme.swift index 967417b55..27fdd76cf 100644 --- a/Sources/ProjectSpec/TargetScheme.swift +++ b/Sources/ProjectSpec/TargetScheme.swift @@ -8,6 +8,7 @@ public struct TargetScheme: Equatable { public static let stopOnEveryMainThreadCheckerIssueDefault = false public static let disableThreadPerformanceCheckerDefault = false public static let buildImplicitDependenciesDefault = true + public static let buildArchitecturesDefault = Scheme.Build.buildArchitecturesDefault public var testTargets: [Scheme.Test.TestTarget] public var configVariants: [String] @@ -20,6 +21,7 @@ public struct TargetScheme: Equatable { public var stopOnEveryMainThreadCheckerIssue: Bool public var disableThreadPerformanceChecker: Bool public var buildImplicitDependencies: Bool + public var buildArchitectures: BuildArchitectures public var commandLineArguments: [String: Bool] public var environmentVariables: [XCScheme.EnvironmentVariable] public var preActions: [Scheme.ExecutionAction] @@ -40,6 +42,7 @@ public struct TargetScheme: Equatable { stopOnEveryMainThreadCheckerIssue: Bool = stopOnEveryMainThreadCheckerIssueDefault, disableThreadPerformanceChecker: Bool = disableThreadPerformanceCheckerDefault, buildImplicitDependencies: Bool = buildImplicitDependenciesDefault, + buildArchitectures: BuildArchitectures = buildArchitecturesDefault, commandLineArguments: [String: Bool] = [:], environmentVariables: [XCScheme.EnvironmentVariable] = [], preActions: [Scheme.ExecutionAction] = [], @@ -58,6 +61,7 @@ public struct TargetScheme: Equatable { self.stopOnEveryMainThreadCheckerIssue = stopOnEveryMainThreadCheckerIssue self.disableThreadPerformanceChecker = disableThreadPerformanceChecker self.buildImplicitDependencies = buildImplicitDependencies + self.buildArchitectures = buildArchitectures self.commandLineArguments = commandLineArguments self.environmentVariables = environmentVariables self.preActions = preActions @@ -110,6 +114,7 @@ extension TargetScheme: JSONObjectConvertible { stopOnEveryMainThreadCheckerIssue = jsonDictionary.json(atKeyPath: "stopOnEveryMainThreadCheckerIssue") ?? TargetScheme.stopOnEveryMainThreadCheckerIssueDefault disableThreadPerformanceChecker = jsonDictionary.json(atKeyPath: "disableThreadPerformanceChecker") ?? TargetScheme.disableThreadPerformanceCheckerDefault buildImplicitDependencies = jsonDictionary.json(atKeyPath: "buildImplicitDependencies") ?? TargetScheme.buildImplicitDependenciesDefault + buildArchitectures = jsonDictionary.json(atKeyPath: "buildArchitectures") ?? TargetScheme.buildArchitecturesDefault commandLineArguments = jsonDictionary.json(atKeyPath: "commandLineArguments") ?? [:] environmentVariables = try XCScheme.EnvironmentVariable.parseAll(jsonDictionary: jsonDictionary) preActions = jsonDictionary.json(atKeyPath: "preActions") ?? [] @@ -155,6 +160,10 @@ extension TargetScheme: JSONEncodable { dict["buildImplicitDependencies"] = buildImplicitDependencies } + if buildArchitectures != TargetScheme.buildArchitecturesDefault { + dict["buildArchitectures"] = buildArchitectures.toJSONValue() + } + if let language = language { dict["language"] = language } diff --git a/Sources/XcodeGenKit/SchemeGenerator.swift b/Sources/XcodeGenKit/SchemeGenerator.swift index bb5205c28..423bf8e8d 100644 --- a/Sources/XcodeGenKit/SchemeGenerator.swift +++ b/Sources/XcodeGenKit/SchemeGenerator.swift @@ -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 @@ -488,7 +489,8 @@ extension Scheme { targets: Scheme.buildTargets(for: target, project: project), buildImplicitDependencies: targetScheme.buildImplicitDependencies, preActions: targetScheme.preActions, - postActions: targetScheme.postActions + postActions: targetScheme.postActions, + buildArchitectures: targetScheme.buildArchitectures ), run: .init( config: debugConfig, diff --git a/Tests/Fixtures/SPM/SPM.xcodeproj/xcshareddata/xcschemes/App.xcscheme b/Tests/Fixtures/SPM/SPM.xcodeproj/xcshareddata/xcschemes/App.xcscheme index 298045bf8..2649ac5ba 100644 --- a/Tests/Fixtures/SPM/SPM.xcodeproj/xcshareddata/xcschemes/App.xcscheme +++ b/Tests/Fixtures/SPM/SPM.xcodeproj/xcshareddata/xcschemes/App.xcscheme @@ -5,6 +5,7 @@