diff --git a/Docs/ProjectSpec.md b/Docs/ProjectSpec.md index 3f091bfd..17f6c5b3 100644 --- a/Docs/ProjectSpec.md +++ b/Docs/ProjectSpec.md @@ -133,6 +133,13 @@ Note that target names can also be changed by adding a `name` property to a targ - [ ] **indentWidth**: **Int** - If this is specified, the Xcode project will override the user's setting for indent width in number of spaces. - [ ] **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` + - `xcode16_3`: Xcode 16.3 + - `xcode16_0`: Xcode 16.0 + - `xcode15_3`: Xcode 15.3 + - `xcode15_0`: Xcode 15.0 + - `xcode14_0`: Xcode 14.0 + - [ ] **deploymentTarget**: **[[Platform](#platform): String]** - A project wide deployment target can be specified for each platform otherwise the default SDK version in Xcode will be used. This will be overridden by any custom build settings that set the deployment target eg `IPHONEOS_DEPLOYMENT_TARGET`. Target specific deployment targets can also be set with [Target](#target).deploymentTarget. - [ ] **disabledValidations**: **[String]** - A list of validations that can be disabled if they're too strict for your use case. By default this is set to an empty array. Currently these are the available options: - `missingConfigs`: Disable errors for configurations in yaml files that don't exist in the project itself. This can be useful if you include the same yaml file in different projects @@ -156,7 +163,7 @@ Note that target names can also be changed by adding a `name` property to a targ - [ ] **defaultSourceDirectoryType**: **String** - When a [Target source](#target-source) doesn't specify a type and is a directory, this is the type that will be used. If nothing is specified for either then `group` will be used. - `group` (default) - `folder` - - `syncedFolder` + - `syncedFolder`: Can be used starting from **projectFormat** `xcode16_0` ```yaml options: diff --git a/Sources/ProjectSpec/SpecOptions.swift b/Sources/ProjectSpec/SpecOptions.swift index c10c3469..07582d42 100644 --- a/Sources/ProjectSpec/SpecOptions.swift +++ b/Sources/ProjectSpec/SpecOptions.swift @@ -24,6 +24,7 @@ public struct SpecOptions: Equatable { public var tabWidth: UInt? public var indentWidth: UInt? public var xcodeVersion: String? + public var projectFormat: String? public var deploymentTarget: DeploymentTarget public var defaultConfig: String? public var transitivelyLinkDependencies: Bool @@ -88,6 +89,7 @@ public struct SpecOptions: Equatable { tabWidth: UInt? = nil, usesTabs: Bool? = nil, xcodeVersion: String? = nil, + projectFormat: String? = nil, deploymentTarget: DeploymentTarget = .init(), disabledValidations: [ValidationType] = [], defaultConfig: String? = nil, @@ -115,6 +117,7 @@ public struct SpecOptions: Equatable { self.indentWidth = indentWidth self.usesTabs = usesTabs self.xcodeVersion = xcodeVersion + self.projectFormat = projectFormat self.deploymentTarget = deploymentTarget self.disabledValidations = disabledValidations self.defaultConfig = defaultConfig @@ -148,6 +151,7 @@ extension SpecOptions: JSONObjectConvertible { developmentLanguage = jsonDictionary.json(atKeyPath: "developmentLanguage") usesTabs = jsonDictionary.json(atKeyPath: "usesTabs") xcodeVersion = jsonDictionary.json(atKeyPath: "xcodeVersion") + projectFormat = jsonDictionary.json(atKeyPath: "projectFormat") indentWidth = (jsonDictionary.json(atKeyPath: "indentWidth") as Int?).flatMap(UInt.init) tabWidth = (jsonDictionary.json(atKeyPath: "tabWidth") as Int?).flatMap(UInt.init) deploymentTarget = jsonDictionary.json(atKeyPath: "deploymentTarget") ?? DeploymentTarget() @@ -186,6 +190,7 @@ extension SpecOptions: JSONEncodable { "developmentLanguage": developmentLanguage, "usesTabs": usesTabs, "xcodeVersion": xcodeVersion, + "projectFormat": projectFormat, "indentWidth": indentWidth.flatMap { Int($0) }, "tabWidth": tabWidth.flatMap { Int($0) }, "defaultConfig": defaultConfig, diff --git a/Sources/XcodeGenKit/PBXProjGenerator.swift b/Sources/XcodeGenKit/PBXProjGenerator.swift index 0c3a99d7..48fc8810 100644 --- a/Sources/XcodeGenKit/PBXProjGenerator.swift +++ b/Sources/XcodeGenKit/PBXProjGenerator.swift @@ -102,7 +102,7 @@ public class PBXProjGenerator { name: project.name, buildConfigurationList: buildConfigList, compatibilityVersion: project.compatibilityVersion, - preferredProjectObjectVersion: Int(project.objectVersion), + preferredProjectObjectVersion: project.preferredProjectObjectVersion.map { Int($0) }, minimizedProjectReferenceProxies: project.minimizedProjectReferenceProxies, mainGroup: mainGroup, developmentRegion: developmentRegion diff --git a/Sources/XcodeGenKit/ProjectFormat.swift b/Sources/XcodeGenKit/ProjectFormat.swift new file mode 100644 index 00000000..0405518f --- /dev/null +++ b/Sources/XcodeGenKit/ProjectFormat.swift @@ -0,0 +1,37 @@ +public extension ProjectFormat { + static let `default`: ProjectFormat = .xcode16_0 +} + +public enum ProjectFormat: String { + case xcode16_3 + case xcode16_0 + case xcode15_3 + case xcode15_0 + case xcode14_0 + + public var objectVersion: UInt { + switch self { + case .xcode16_3: 90 + case .xcode16_0: 77 + case .xcode15_3: 63 + case .xcode15_0: 60 + case .xcode14_0: 56 + } + } + + public var preferredProjectObjectVersion: UInt? { + switch self { + case .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 .xcode15_3: "Xcode 15.3" + case .xcode15_0: "Xcode 15.0" + case .xcode14_0: "Xcode 14.0" + } + } +} diff --git a/Sources/XcodeGenKit/Version.swift b/Sources/XcodeGenKit/Version.swift index 7b7246e9..b5ba54d4 100644 --- a/Sources/XcodeGenKit/Version.swift +++ b/Sources/XcodeGenKit/Version.swift @@ -7,16 +7,24 @@ extension Project { XCodeVersion.parse(options.xcodeVersion ?? "14.3") } + public var projectFormat: ProjectFormat { + options.projectFormat.flatMap(ProjectFormat.init) ?? .default + } + var schemeVersion: String { "1.7" } - var compatibilityVersion: String { - "Xcode 14.0" + var compatibilityVersion: String? { + projectFormat.compatibilityVersion } var objectVersion: UInt { - 77 + projectFormat.objectVersion + } + + var preferredProjectObjectVersion: UInt? { + projectFormat.preferredProjectObjectVersion } var minimizedProjectReferenceProxies: Int { diff --git a/Tests/Fixtures/CarthageProject/Project.xcodeproj/project.pbxproj b/Tests/Fixtures/CarthageProject/Project.xcodeproj/project.pbxproj index 8b2ad988..79aeefb4 100644 --- a/Tests/Fixtures/CarthageProject/Project.xcodeproj/project.pbxproj +++ b/Tests/Fixtures/CarthageProject/Project.xcodeproj/project.pbxproj @@ -326,7 +326,6 @@ }; }; buildConfigurationList = D91E14E36EC0B415578456F2 /* Build configuration list for PBXProject "Project" */; - compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( diff --git a/Tests/Fixtures/SPM/SPM.xcodeproj/project.pbxproj b/Tests/Fixtures/SPM/SPM.xcodeproj/project.pbxproj index f9320a9d..aba46c9a 100644 --- a/Tests/Fixtures/SPM/SPM.xcodeproj/project.pbxproj +++ b/Tests/Fixtures/SPM/SPM.xcodeproj/project.pbxproj @@ -246,7 +246,6 @@ }; }; buildConfigurationList = 425866ADA259DB93FC4AF1E3 /* Build configuration list for PBXProject "SPM" */; - compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( diff --git a/Tests/Fixtures/TestProject/AnotherProject/AnotherProject.xcodeproj/project.pbxproj b/Tests/Fixtures/TestProject/AnotherProject/AnotherProject.xcodeproj/project.pbxproj index d86f4027..af01fcbe 100644 --- a/Tests/Fixtures/TestProject/AnotherProject/AnotherProject.xcodeproj/project.pbxproj +++ b/Tests/Fixtures/TestProject/AnotherProject/AnotherProject.xcodeproj/project.pbxproj @@ -124,7 +124,6 @@ }; }; buildConfigurationList = 3DFC1105373EDB6483D4BC5D /* Build configuration list for PBXProject "AnotherProject" */; - compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( diff --git a/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj b/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj index d49a058e..b3801b69 100644 --- a/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj +++ b/Tests/Fixtures/TestProject/Project.xcodeproj/project.pbxproj @@ -2484,7 +2484,6 @@ ); }; buildConfigurationList = D91E14E36EC0B415578456F2 /* Build configuration list for PBXProject "Project" */; - compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( diff --git a/Tests/Fixtures/scheme_test/TestProject.xcodeproj/project.pbxproj b/Tests/Fixtures/scheme_test/TestProject.xcodeproj/project.pbxproj index 5c0229f7..ddb2e470 100644 --- a/Tests/Fixtures/scheme_test/TestProject.xcodeproj/project.pbxproj +++ b/Tests/Fixtures/scheme_test/TestProject.xcodeproj/project.pbxproj @@ -76,7 +76,6 @@ }; }; buildConfigurationList = E903F6E8184E2A86CEC31778 /* Build configuration list for PBXProject "TestProject" */; - compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = (