From 15e98287bbb0c2fdeb2c7f0985a56c8e27fe6c73 Mon Sep 17 00:00:00 2001 From: Raymond Riter Date: Mon, 14 Sep 2026 13:18:04 -0400 Subject: [PATCH 1/2] Add xcode26_3 project format (objectVersion 100) Adds a `xcode26_3` case to `ProjectFormat`, selectable via the `projectFormat` spec option, which generates projects in the Xcode 26.3 format: `objectVersion = 100` and `preferredProjectObjectVersion = 100`, with no `compatibilityVersion` (matching the existing Xcode 16.x formats). The default format is unchanged. Resolves #1620 Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 1 + Docs/ProjectSpec.md | 1 + Sources/XcodeGenKit/ProjectFormat.swift | 6 +++-- .../PBXProjGeneratorTests.swift | 24 +++++++++++++++++++ 4 files changed, 30 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45ff4ff8..522431b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added - Added `buildArchitectures` to scheme build options and target schemes, to control Xcode's "Override Architectures" scheme setting #1642 @arhxam - Added FAQ documentation on how to add an Xcode capability, such as In-App Purchase #1644 @Hokila +- Added `xcode26_3` `projectFormat` option for the Xcode 26.3 project format (`objectVersion = 100`) #XXXX @Raymondriter ### 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 diff --git a/Docs/ProjectSpec.md b/Docs/ProjectSpec.md index 9fc2f918..23d46fb5 100644 --- a/Docs/ProjectSpec.md +++ b/Docs/ProjectSpec.md @@ -134,6 +134,7 @@ Note that target names can also be changed by adding a `name` property to a targ - [ ] **tabWidth**: **Int** - If this is specified, the Xcode project will override the user's setting for indent width in number of spaces. - [ ] **xcodeVersion**: **String** - The version of Xcode. This defaults to the latest version periodically. You can specify it in the format `0910` or `9.1` - [ ] **projectFormat**: **String** - The version of Xcode project. By default this is set to `xcode16_0` + - `xcode26_3`: Xcode 26.3 - `xcode16_3`: Xcode 16.3 - `xcode16_0`: Xcode 16.0 - `xcode15_3`: Xcode 15.3 diff --git a/Sources/XcodeGenKit/ProjectFormat.swift b/Sources/XcodeGenKit/ProjectFormat.swift index 0405518f..cb792448 100644 --- a/Sources/XcodeGenKit/ProjectFormat.swift +++ b/Sources/XcodeGenKit/ProjectFormat.swift @@ -3,6 +3,7 @@ public extension ProjectFormat { } public enum ProjectFormat: String { + case xcode26_3 case xcode16_3 case xcode16_0 case xcode15_3 @@ -11,6 +12,7 @@ public enum ProjectFormat: String { public var objectVersion: UInt { switch self { + case .xcode26_3: 100 case .xcode16_3: 90 case .xcode16_0: 77 case .xcode15_3: 63 @@ -21,14 +23,14 @@ public enum ProjectFormat: String { public var preferredProjectObjectVersion: UInt? { switch self { - case .xcode16_3, .xcode16_0: objectVersion + case .xcode26_3, .xcode16_3, .xcode16_0: objectVersion case .xcode15_3, .xcode15_0, .xcode14_0: nil } } public var compatibilityVersion: String? { switch self { - case .xcode16_3, .xcode16_0: nil + case .xcode26_3, .xcode16_3, .xcode16_0: nil case .xcode15_3: "Xcode 15.3" case .xcode15_0: "Xcode 15.0" case .xcode14_0: "Xcode 14.0" diff --git a/Tests/XcodeGenKitTests/PBXProjGeneratorTests.swift b/Tests/XcodeGenKitTests/PBXProjGeneratorTests.swift index a94404a0..8b2ac35e 100644 --- a/Tests/XcodeGenKitTests/PBXProjGeneratorTests.swift +++ b/Tests/XcodeGenKitTests/PBXProjGeneratorTests.swift @@ -507,6 +507,30 @@ class PBXProjGeneratorTests: XCTestCase { } } + func testDefaultProjectFormat() throws { + let project = Project(name: "Test") + + let pbxProj = try PBXProjGenerator(project: project).generate() + let pbxProject = try XCTUnwrap(pbxProj.rootObject) + + XCTAssertEqual(project.projectFormat, .xcode16_0) + XCTAssertEqual(pbxProj.objectVersion, 77) + XCTAssertEqual(pbxProject.preferredProjectObjectVersion, 77) + XCTAssertNil(pbxProject.compatibilityVersion) + } + + func testXcode26_3ProjectFormat() throws { + let project = Project(name: "Test", options: SpecOptions(projectFormat: "xcode26_3")) + + let pbxProj = try PBXProjGenerator(project: project).generate() + let pbxProject = try XCTUnwrap(pbxProj.rootObject) + + XCTAssertEqual(project.projectFormat, .xcode26_3) + XCTAssertEqual(pbxProj.objectVersion, 100) + XCTAssertEqual(pbxProject.preferredProjectObjectVersion, 100) + XCTAssertNil(pbxProject.compatibilityVersion) + } + func testProductsGroupIsSet() throws { let target = Target(name: "TestApp", type: .application, platform: .iOS) let project = Project(name: "Test", targets: [target]) From 4bf3fd9ff1952eb6b3368617eaa3413c86805a4b Mon Sep 17 00:00:00 2001 From: Raymond Riter Date: Mon, 14 Sep 2026 17:15:06 -0400 Subject: [PATCH 2/2] Add PR number to CHANGELOG entry Co-Authored-By: Claude Opus 5 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 522431b3..a1850e7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ ### Added - Added `buildArchitectures` to scheme build options and target schemes, to control Xcode's "Override Architectures" scheme setting #1642 @arhxam - Added FAQ documentation on how to add an Xcode capability, such as In-App Purchase #1644 @Hokila -- Added `xcode26_3` `projectFormat` option for the Xcode 26.3 project format (`objectVersion = 100`) #XXXX @Raymondriter +- Added `xcode26_3` `projectFormat` option for the Xcode 26.3 project format (`objectVersion = 100`) #1648 @Raymondriter ### 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