Skip to content

Commit 783a19e

Browse files
yonaskolbclaude
andauthored
Add Xcode 27.0 project format, validate projectFormat and default xcodeVersion to 16.0 (#1658)
* Add Xcode 27.0 project format, validate projectFormat and default xcodeVersion to 16.0 - Add `xcode27_0` `ProjectFormat` (objectVersion 110, preferredProjectObjectVersion 110, no compatibilityVersion) - Move `ProjectFormat` into ProjectSpec (with a typealias in XcodeGenKit) so spec validation can report unknown `projectFormat` values - Default `xcodeVersion` to 16.0 and regenerate fixtures Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Add PR number to CHANGELOG entries Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 35f7e52 commit 783a19e

32 files changed

Lines changed: 112 additions & 65 deletions

‎CHANGELOG.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
- Added `buildArchitectures` to scheme build options and target schemes, to control Xcode's "Override Architectures" scheme setting #1642 @arhxam
77
- Added FAQ documentation on how to add an Xcode capability, such as In-App Purchase #1644 @Hokila
88
- Added `xcode26_3` `projectFormat` option for the Xcode 26.3 project format (`objectVersion = 100`) #1648 @Raymondriter
9+
- Added `xcode27_0` `projectFormat` option for the Xcode 27.0 project format (`objectVersion = 110`) #1658 @yonaskolb
910

1011
### Changed
1112
- 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
13+
- The default `xcodeVersion` is now `16.0` (previously `14.3`), which sets `LastUpgradeCheck` in generated projects and `LastUpgradeVersion` in generated schemes. Set `options.xcodeVersion` to keep the previous value #1658 @yonaskolb
14+
- An unknown `options.projectFormat` value is now a spec validation error listing the valid values, instead of silently falling back to the default format #1658 @yonaskolb
1215

1316
### Fixed
1417
- Fix `syncedFolder` source paths being relative to the spec directory instead of the project directory when they differ, which caused Xcode to treat the synced folder as empty #1636 @Ckitakishi

‎Docs/ProjectSpec.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,9 @@ Note that target names can also be changed by adding a `name` property to a targ
132132
- [ ] **usesTabs**: **Bool** - If this is specified, the Xcode project will override the user's setting determining whether or not tabs or spaces should be used in the project.
133133
- [ ] **indentWidth**: **Int** - If this is specified, the Xcode project will override the user's setting for indent width in number of spaces.
134134
- [ ] **tabWidth**: **Int** - If this is specified, the Xcode project will override the user's setting for indent width in number of spaces.
135-
- [ ] **xcodeVersion**: **String** - The version of Xcode. This defaults to the latest version periodically. You can specify it in the format `0910` or `9.1`
136-
- [ ] **projectFormat**: **String** - The version of Xcode project. By default this is set to `xcode16_0`
135+
- [ ] **xcodeVersion**: **String** - The version of Xcode. This is used for `LastUpgradeCheck` in the project and `LastUpgradeVersion` in schemes. This defaults to `16.0`, and the default is updated periodically. You can specify it in the format `0910` or `9.1`
136+
- [ ] **projectFormat**: **String** - The version of Xcode project. By default this is set to `xcode16_0`. Must be one of:
137+
- `xcode27_0`: Xcode 27.0
137138
- `xcode26_3`: Xcode 26.3
138139
- `xcode16_3`: Xcode 16.3
139140
- `xcode16_0`: Xcode 16.0
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
public extension ProjectFormat {
2+
static let `default`: ProjectFormat = .xcode16_0
3+
}
4+
5+
public enum ProjectFormat: String, CaseIterable {
6+
case xcode27_0
7+
case xcode26_3
8+
case xcode16_3
9+
case xcode16_0
10+
case xcode15_3
11+
case xcode15_0
12+
case xcode14_0
13+
14+
public var objectVersion: UInt {
15+
switch self {
16+
case .xcode27_0: 110
17+
case .xcode26_3: 100
18+
case .xcode16_3: 90
19+
case .xcode16_0: 77
20+
case .xcode15_3: 63
21+
case .xcode15_0: 60
22+
case .xcode14_0: 56
23+
}
24+
}
25+
26+
public var preferredProjectObjectVersion: UInt? {
27+
switch self {
28+
case .xcode27_0, .xcode26_3, .xcode16_3, .xcode16_0: objectVersion
29+
case .xcode15_3, .xcode15_0, .xcode14_0: nil
30+
}
31+
}
32+
33+
public var compatibilityVersion: String? {
34+
switch self {
35+
case .xcode27_0, .xcode26_3, .xcode16_3, .xcode16_0: nil
36+
case .xcode15_3: "Xcode 15.3"
37+
case .xcode15_0: "Xcode 15.0"
38+
case .xcode14_0: "Xcode 14.0"
39+
}
40+
}
41+
}

‎Sources/ProjectSpec/SpecValidation.swift‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ extension Project {
7171
}
7272
}
7373

74+
if let projectFormat = options.projectFormat, ProjectFormat(rawValue: projectFormat) == nil {
75+
errors.append(.invalidProjectFormat(projectFormat))
76+
}
77+
7478
if let configName = options.defaultConfig {
7579
if !configs.contains(where: { $0.name == configName }) {
7680
errors.append(.missingDefaultConfig(configName: configName))

‎Sources/ProjectSpec/SpecValidationError.swift‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public struct SpecValidationError: Error, CustomStringConvertible {
4343
case duplicateDependencies(target: String, dependencyReference: String)
4444
case invalidPluginPackageReference(plugin: String, package: String)
4545
case emptySourcePath(target: String)
46+
case invalidProjectFormat(String)
4647

4748
public var description: String {
4849
switch self {
@@ -112,6 +113,9 @@ public struct SpecValidationError: Error, CustomStringConvertible {
112113
return "Plugin \(plugin) has invalid package reference \(package)"
113114
case let .emptySourcePath(target):
114115
return "Target \(target.quoted) has an empty source path entry"
116+
case let .invalidProjectFormat(projectFormat):
117+
let validValues = ProjectFormat.allCases.map(\.rawValue).joined(separator: ", ")
118+
return "Invalid projectFormat \(projectFormat.quoted). Valid values are: \(validValues)"
115119
}
116120
}
117121
}
Lines changed: 4 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,5 @@
1-
public extension ProjectFormat {
2-
static let `default`: ProjectFormat = .xcode16_0
3-
}
1+
import ProjectSpec
42

5-
public enum ProjectFormat: String {
6-
case xcode26_3
7-
case xcode16_3
8-
case xcode16_0
9-
case xcode15_3
10-
case xcode15_0
11-
case xcode14_0
12-
13-
public var objectVersion: UInt {
14-
switch self {
15-
case .xcode26_3: 100
16-
case .xcode16_3: 90
17-
case .xcode16_0: 77
18-
case .xcode15_3: 63
19-
case .xcode15_0: 60
20-
case .xcode14_0: 56
21-
}
22-
}
23-
24-
public var preferredProjectObjectVersion: UInt? {
25-
switch self {
26-
case .xcode26_3, .xcode16_3, .xcode16_0: objectVersion
27-
case .xcode15_3, .xcode15_0, .xcode14_0: nil
28-
}
29-
}
30-
31-
public var compatibilityVersion: String? {
32-
switch self {
33-
case .xcode26_3, .xcode16_3, .xcode16_0: nil
34-
case .xcode15_3: "Xcode 15.3"
35-
case .xcode15_0: "Xcode 15.0"
36-
case .xcode14_0: "Xcode 14.0"
37-
}
38-
}
39-
}
3+
/// `ProjectFormat` is defined in `ProjectSpec` so that spec validation can check `options.projectFormat`.
4+
/// This alias keeps `XcodeGenKit.ProjectFormat` available to existing clients.
5+
public typealias ProjectFormat = ProjectSpec.ProjectFormat

‎Sources/XcodeGenKit/Version.swift‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import ProjectSpec
44
extension Project {
55

66
public var xcodeVersion: String {
7-
XCodeVersion.parse(options.xcodeVersion ?? "14.3")
7+
XCodeVersion.parse(options.xcodeVersion ?? "16.0")
88
}
99

1010
public var projectFormat: ProjectFormat {

‎Tests/Fixtures/CarthageProject/Project.xcodeproj/project.pbxproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@
321321
isa = PBXProject;
322322
attributes = {
323323
BuildIndependentTargetsInParallel = YES;
324-
LastUpgradeCheck = 1430;
324+
LastUpgradeCheck = 1600;
325325
TargetAttributes = {
326326
};
327327
};

‎Tests/Fixtures/SPM/SPM.xcodeproj/project.pbxproj‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@
241241
isa = PBXProject;
242242
attributes = {
243243
BuildIndependentTargetsInParallel = YES;
244-
LastUpgradeCheck = 1430;
244+
LastUpgradeCheck = 1600;
245245
TargetAttributes = {
246246
};
247247
};

‎Tests/Fixtures/SPM/SPM.xcodeproj/xcshareddata/xcschemes/App.xcscheme‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<Scheme
3-
LastUpgradeVersion = "1430"
3+
LastUpgradeVersion = "1600"
44
version = "1.7">
55
<BuildAction
66
parallelizeBuildables = "YES"

0 commit comments

Comments
 (0)