From 4e35dc6b02e0c4177d6cfa3f9fadadf5df51edf2 Mon Sep 17 00:00:00 2001 From: Yonas Kolb Date: Wed, 26 Jul 2017 19:58:34 +0200 Subject: [PATCH] remove Spec.configVariants and move to Target.generateSchemes --- Sources/XcodeGenKit/ProjectGenerator.swift | 84 +++++++++---------- Sources/XcodeGenKit/Spec/Spec.swift | 7 +- Sources/XcodeGenKit/Spec/Target.swift | 8 +- .../ProjectGeneratorTests.swift | 34 +++----- 4 files changed, 58 insertions(+), 75 deletions(-) diff --git a/Sources/XcodeGenKit/ProjectGenerator.swift b/Sources/XcodeGenKit/ProjectGenerator.swift index b19b9e64..6324953f 100644 --- a/Sources/XcodeGenKit/ProjectGenerator.swift +++ b/Sources/XcodeGenKit/ProjectGenerator.swift @@ -34,38 +34,38 @@ public class ProjectGenerator { func validate() throws { - let defaultConfigs = [Config(name: "Debug", type: .debug), Config(name: "Release", type: .release)] - - if !spec.configVariants.isEmpty { - spec.configs = defaultConfigs.reduce([]) { all, config in - all + spec.configVariants.map { variant in - let name = "\(variant) \(config.name)" - return Config(name: name, type: config.type, buildSettingGroups: config.buildSettingGroups, buildSettings: config.buildSettings) - } - } - } else if spec.configs.isEmpty { - spec.configs = defaultConfigs + if spec.configs.isEmpty { + spec.configs = [Config(name: "Debug", type: .debug), Config(name: "Release", type: .release)] } var errors: [SpecValidationError.Error] = [] for target in spec.targets { for dependency in target.dependencies { - if case .target(let target) = dependency, spec.getTarget(target) == nil { - errors.append(.invalidTargetDependency(target)) + if case .target(let targetName) = dependency, spec.getTarget(targetName) == nil { + errors.append(.invalidTargetDependency(target: target.name, dependency: targetName)) } } if let buildSettings = target.buildSettings { for config in buildSettings.configSettings.keys { if spec.getConfig(config) == nil { - errors.append(.invalidBuildSettingConfig(config)) + errors.append(.invalidBuildSettingConfig(config: config)) } } } for source in target.sources { let sourcePath = path + source if !sourcePath.exists { - errors.append(.missingTargetSource(sourcePath.string)) + errors.append(.missingTargetSource(target: target.name, source: sourcePath.string)) + } + } + + for generatedScheme in target.generateSchemes { + if !spec.configs.contains(where: { $0.name.contains(generatedScheme) && $0.type == .debug }) { + errors.append(.invalidTargetGeneratedSchema(target: target.name, scheme: generatedScheme, configType: .debug)) + } + if !spec.configs.contains(where: { $0.name.contains(generatedScheme) && $0.type == .release }) { + errors.append(.invalidTargetGeneratedSchema(target: target.name, scheme: generatedScheme, configType: .release)) } } } @@ -73,23 +73,23 @@ public class ProjectGenerator { for scheme in spec.schemes { for buildTarget in scheme.build.targets { if spec.getTarget(buildTarget.target) == nil { - errors.append(.invalidSchemeTarget(buildTarget.target)) + errors.append(.invalidSchemeTarget(scheme: scheme.name, target: buildTarget.target)) } } if let buildAction = scheme.run, spec.getConfig(buildAction.config) == nil { - errors.append(.invalidSchemeConfig(buildAction.config)) + errors.append(.invalidSchemeConfig(scheme: scheme.name, config: buildAction.config)) } if let buildAction = scheme.test, spec.getConfig(buildAction.config) == nil { - errors.append(.invalidSchemeConfig(buildAction.config)) + errors.append(.invalidSchemeConfig(scheme: scheme.name, config: buildAction.config)) } if let buildAction = scheme.profile, spec.getConfig(buildAction.config) == nil { - errors.append(.invalidSchemeConfig(buildAction.config)) + errors.append(.invalidSchemeConfig(scheme: scheme.name, config: buildAction.config)) } if let buildAction = scheme.analyze, spec.getConfig(buildAction.config) == nil { - errors.append(.invalidSchemeConfig(buildAction.config)) + errors.append(.invalidSchemeConfig(scheme: scheme.name, config: buildAction.config)) } if let buildAction = scheme.archive, spec.getConfig(buildAction.config) == nil { - errors.append(.invalidSchemeConfig(buildAction.config)) + errors.append(.invalidSchemeConfig(scheme: scheme.name, config: buildAction.config)) } } @@ -161,17 +161,15 @@ public class ProjectGenerator { } for target in spec.targets { - if target.generateSchemes { - for variant in spec.configVariants { - let schemeName = "\(target.name) \(variant)" + for generatedScheme in target.generateSchemes { + let schemeName = "\(target.name) \(generatedScheme)" - let debugConfig = spec.configs.first { $0.type == .debug && $0.name.contains(variant) }! - let releaseConfig = spec.configs.first { $0.type == .release && $0.name.contains(variant) }! + let debugConfig = spec.configs.first { $0.type == .debug && $0.name.contains(generatedScheme) }! + let releaseConfig = spec.configs.first { $0.type == .release && $0.name.contains(generatedScheme) }! - let specScheme = Scheme(name: schemeName, targets: [Scheme.BuildTarget(target: target.name)], debugConfig: debugConfig.name, releaseConfig: releaseConfig.name) - let scheme = try generateScheme(specScheme, pbxProject: pbxProject) - xcschemes.append(scheme) - } + let specScheme = Scheme(name: schemeName, targets: [Scheme.BuildTarget(target: target.name)], debugConfig: debugConfig.name, releaseConfig: releaseConfig.name) + let scheme = try generateScheme(specScheme, pbxProject: pbxProject) + xcschemes.append(scheme) } } @@ -184,19 +182,21 @@ public struct SpecValidationError: Error, CustomStringConvertible { public var errors: [Error] public enum Error: CustomStringConvertible { - case invalidTargetDependency(String) - case invalidSchemeTarget(String) - case invalidSchemeConfig(String) - case invalidBuildSettingConfig(String) - case missingTargetSource(String) + case invalidTargetDependency(target: String, dependency: String) + case invalidSchemeTarget(scheme: String, target: String) + case invalidSchemeConfig(scheme: String, config: String) + case invalidBuildSettingConfig(config: String) + case missingTargetSource(target: String, source: String) + case invalidTargetGeneratedSchema(target: String, scheme: String, configType: ConfigType) public var description: String { switch self { - case let .invalidTargetDependency(dependency): return "Target has invalid dependency: \(dependency)" - case let .invalidSchemeTarget(target): return "Scheme has invalid build target: \(target)" - case let .invalidSchemeConfig(config): return "Scheme has invalid build configuration: \(config)" - case let .invalidBuildSettingConfig(config): return "Build setting has invalid build configuration: \(config)" - case let .missingTargetSource(source): return "Target has a missing source directory: \(source)" + case let .invalidTargetDependency(target, dependency): return "Target \(target.quoted) has invalid dependency: \(dependency.quoted)" + case let .invalidSchemeTarget(scheme, target): return "Scheme \(scheme.quoted) has invalid build target \(target.quoted)" + case let .invalidSchemeConfig(scheme, config): return "Scheme \(scheme.quoted) has invalid build configuration \(config.quoted)" + case let .invalidBuildSettingConfig(config): return "Build setting has invalid build configuration \(config.quoted)" + case let .missingTargetSource(target, source): return "Target \(target.quoted) has a missing source directory \(source.quoted)" + case let .invalidTargetGeneratedSchema(target, scheme, configType): return "Target \(target.quoted) has an invalid schema generation name which requires a config that has a \(configType.rawValue.quoted) type and contains the name \(scheme.quoted)" } } } @@ -206,8 +206,8 @@ public struct SpecValidationError: Error, CustomStringConvertible { if errors.count == 1 { title = "Spec validation error: " } else { - title = "\(errors.count) Spec validations errors:\n" + title = "\(errors.count) Spec validations errors:\n\t- " } - return "\(title)" + errors.map { $0.description }.joined(separator: "\n") + return "\(title)" + errors.map { $0.description }.joined(separator: "\n\t- ") } } diff --git a/Sources/XcodeGenKit/Spec/Spec.swift b/Sources/XcodeGenKit/Spec/Spec.swift index a9e28e7e..a3c7a40b 100644 --- a/Sources/XcodeGenKit/Spec/Spec.swift +++ b/Sources/XcodeGenKit/Spec/Spec.swift @@ -19,13 +19,11 @@ public struct Spec { public var settingGroups: [BuildSettingGroup] public var configs: [Config] public var schemes: [Scheme] - public var configVariants: [String] - - public init(name: String, targets: [Target] = [], configs: [Config] = [], configVariants: [String] = [], settingGroups: [BuildSettingGroup] = [], schemes: [Scheme] = []) { + + public init(name: String, configs: [Config] = [], targets: [Target] = [], settingGroups: [BuildSettingGroup] = [], schemes: [Scheme] = []) { self.name = name self.targets = targets self.configs = configs - self.configVariants = configVariants self.settingGroups = settingGroups self.schemes = schemes } @@ -63,6 +61,5 @@ extension Spec { targets = try jsonDictionary.json(atKeyPath: "targets", invalidItemBehaviour: .fail) } schemes = try jsonDictionary.json(atKeyPath: "schemes") - configVariants = jsonDictionary.json(atKeyPath: "configVariants") ?? [] } } diff --git a/Sources/XcodeGenKit/Spec/Target.swift b/Sources/XcodeGenKit/Spec/Target.swift index 02a7a9c3..45ae4641 100644 --- a/Sources/XcodeGenKit/Spec/Target.swift +++ b/Sources/XcodeGenKit/Spec/Target.swift @@ -21,7 +21,7 @@ public struct Target { public var prebuildScripts: [String] public var postbuildScripts: [String] public var configs: [String: String] - public var generateSchemes: Bool + public var generateSchemes: [String] public var filename: String { var name = self.name @@ -31,7 +31,7 @@ public struct Target { return name } - public init(name: String, type: PBXProductType, platform: Platform, buildSettings: TargetBuildSettings?, configs: [String: String] = [:], sources: [String] = [], sourceExludes: [String] = [], dependencies: [Dependency] = [], prebuildScripts: [String] = [], postbuildScripts: [String] = [], generateSchemes: Bool = false) { + public init(name: String, type: PBXProductType, platform: Platform, buildSettings: TargetBuildSettings?, configs: [String: String] = [:], sources: [String] = [], sourceExludes: [String] = [], dependencies: [Dependency] = [], prebuildScripts: [String] = [], postbuildScripts: [String] = [], generateSchemes: [String] = []) { self.name = name self.type = type self.platform = platform @@ -42,7 +42,7 @@ public struct Target { self.dependencies = dependencies self.prebuildScripts = prebuildScripts self.postbuildScripts = postbuildScripts - self.generateSchemes = false + self.generateSchemes = generateSchemes } } @@ -77,7 +77,7 @@ extension Target: JSONObjectConvertible { } prebuildScripts = jsonDictionary.json(atKeyPath: "prebuildScripts") ?? [] postbuildScripts = jsonDictionary.json(atKeyPath: "postbuildScripts") ?? [] - generateSchemes = jsonDictionary.json(atKeyPath: "generateSchemes") ?? false + generateSchemes = jsonDictionary.json(atKeyPath: "generateSchemes") ?? [] } } diff --git a/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift b/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift index ace69218..b339386b 100644 --- a/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift +++ b/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift @@ -42,30 +42,8 @@ func projectGeneratorTests() { try expect(configs).contains(name: "config1") try expect(configs).contains(name: "config2") } - - $0.it("generates config variants") { - let spec = Spec(name: "test", configVariants: ["Test", "Production"]) - let project = try getProject(spec) - let configs = project.pbxproj.objects.buildConfigurations - try expect(configs.count) == 4 - try expect(configs).contains(name: "Test Debug") - try expect(configs).contains(name: "Test Release") - try expect(configs).contains(name: "Production Debug") - try expect(configs).contains(name: "Production Release") - } - - $0.it("use config variants instead of configs") { - let spec = Spec(name: "test", configs: [Config(name: "Other"), Config(name: "Other2")], configVariants: ["Test", "Production"]) - let project = try getProject(spec) - let configs = project.pbxproj.objects.buildConfigurations - try expect(configs).contains(name: "Test Debug") - try expect(configs).contains(name: "Test Release") - try expect(configs).contains(name: "Production Debug") - try expect(configs).contains(name: "Production Release") - } } - $0.describe("Targets") { let spec = Spec(name: "test", targets: [application, framework]) @@ -120,9 +98,17 @@ func projectGeneratorTests() { } $0.it("generates target schemes from config variant") { + let configVariants = ["Test", "Production"] var target = application - target.generateSchemes = true - let spec = Spec(name: "test", targets: [target, framework], configVariants: ["Test", "Production"]) + target.generateSchemes = configVariants + let configs: [Config] = [ + Config(name: "Test Debug", type: .debug), + Config(name: "Production Debug", type: .debug), + Config(name: "Test Release", type: .release), + Config(name: "Production Release", type: .release), + ] + + let spec = Spec(name: "test", configs: configs, targets: [target, framework]) let project = try getProject(spec) try expect(project.sharedData?.schemes.count) == 2