diff --git a/Sources/ProjectSpec/ProjectSpec.swift b/Sources/ProjectSpec/ProjectSpec.swift index 6d329a72..1d06a811 100644 --- a/Sources/ProjectSpec/ProjectSpec.swift +++ b/Sources/ProjectSpec/ProjectSpec.swift @@ -32,6 +32,7 @@ public struct ProjectSpec { public var indentWidth: UInt? public var xcodeVersion: String? public var deploymentTarget: DeploymentTarget + public var defaultConfigurationName: String? public enum SettingPresets: String { case all @@ -66,7 +67,8 @@ public struct ProjectSpec { usesTabs: Bool? = nil, xcodeVersion: String? = nil, deploymentTarget: DeploymentTarget = .init(), - disabledValidations: [ValidationType] = [] + disabledValidations: [ValidationType] = [], + defaultConfigurationName: String? = nil ) { self.carthageBuildPath = carthageBuildPath self.carthageExecutablePath = carthageExecutablePath @@ -80,6 +82,7 @@ public struct ProjectSpec { self.xcodeVersion = xcodeVersion self.deploymentTarget = deploymentTarget self.disabledValidations = disabledValidations + self.defaultConfigurationName = defaultConfigurationName } public static func == (lhs: ProjectSpec.Options, rhs: ProjectSpec.Options) -> Bool { @@ -217,5 +220,6 @@ extension ProjectSpec.Options: JSONObjectConvertible { tabWidth = (jsonDictionary.json(atKeyPath: "tabWidth") as Int?).flatMap(UInt.init) deploymentTarget = jsonDictionary.json(atKeyPath: "deploymentTarget") ?? DeploymentTarget() disabledValidations = jsonDictionary.json(atKeyPath: "disabledValidations") ?? [] + defaultConfigurationName = jsonDictionary.json(atKeyPath: "defaultConfigurationName") } } diff --git a/Sources/ProjectSpec/SpecValidation.swift b/Sources/ProjectSpec/SpecValidation.swift index 70110b53..22628c0e 100644 --- a/Sources/ProjectSpec/SpecValidation.swift +++ b/Sources/ProjectSpec/SpecValidation.swift @@ -47,6 +47,12 @@ extension ProjectSpec { } } + if let configName = options.defaultConfigurationName { + if !configs.contains(where: { $0.name == configName }) { + errors.append(.missingDefaultConfigurationName(configName: configName)) + } + } + for settings in settingGroups.values { errors += validateSettings(settings) } diff --git a/Sources/ProjectSpec/SpecValidationError.swift b/Sources/ProjectSpec/SpecValidationError.swift index 117c8644..32bab93f 100644 --- a/Sources/ProjectSpec/SpecValidationError.swift +++ b/Sources/ProjectSpec/SpecValidationError.swift @@ -19,6 +19,7 @@ public struct SpecValidationError: Error, CustomStringConvertible { case invalidFileGroup(String) case invalidConfigFileConfig(String) case missingConfigForTargetScheme(target: String, configType: ConfigType) + case missingDefaultConfigurationName(configName: String) public var description: String { switch self { @@ -50,6 +51,8 @@ public struct SpecValidationError: Error, CustomStringConvertible { return "Config file has invalid config \(config.quoted)" case let .missingConfigForTargetScheme(target, configType): return "Target \(target.quoted) is missing a config of type \(configType.rawValue) to generate its scheme" + case let .missingDefaultConfigurationName(name): + return "Default configuration \(name) doesn't exist" } } } diff --git a/Sources/XcodeGenKit/PBXProjGenerator.swift b/Sources/XcodeGenKit/PBXProjGenerator.swift index 78c1333f..e0f0b28f 100644 --- a/Sources/XcodeGenKit/PBXProjGenerator.swift +++ b/Sources/XcodeGenKit/PBXProjGenerator.swift @@ -70,11 +70,12 @@ public class PBXProjGenerator { ) } + let configName = spec.options.defaultConfigurationName ?? buildConfigs.first?.object.name ?? "" let buildConfigList = createObject( id: spec.name, XCConfigurationList( buildConfigurations: buildConfigs.map { $0.reference }, - defaultConfigurationName: buildConfigs.first?.object.name ?? "" + defaultConfigurationName: configName ) ) diff --git a/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift b/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift index a8c5a435..36757c52 100644 --- a/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift +++ b/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift @@ -96,6 +96,20 @@ func projectGeneratorTests() { try expect(XCodeVersion.parse(version)) == expected } } + + $0.it("uses the default configuration name") { + let options = ProjectSpec.Options(defaultConfigurationName: "Bconfig") + let spec = ProjectSpec(basePath: "", name: "test", configs: [Config(name: "Aconfig"), Config(name: "Bconfig")], targets: [framework], options: options) + let pbxProject = try getPbxProj(spec) + + guard let projectConfigListReference = pbxProject.objects.projects.values.first?.buildConfigurationList, + let defaultConfigurationName = pbxProject.objects.configurationLists[projectConfigListReference]?.defaultConfigurationName + else { + throw failure("Default configuration name not found") + } + + try expect(defaultConfigurationName) == "Bconfig" + } } $0.describe("Config") { diff --git a/Tests/XcodeGenKitTests/ProjectSpecTests.swift b/Tests/XcodeGenKitTests/ProjectSpecTests.swift index fcac1c02..7bed6d88 100644 --- a/Tests/XcodeGenKitTests/ProjectSpecTests.swift +++ b/Tests/XcodeGenKitTests/ProjectSpecTests.swift @@ -167,6 +167,12 @@ func projectSpecTests() { )] try spec.validate() } + + $0.it("validates missing default configurations") { + var spec = baseSpec + spec.options = ProjectSpec.Options(defaultConfigurationName: "foo") + try expectValidationError(spec, .missingDefaultConfigurationName(configName: "foo")) + } } } }