From 779397ec8d2761dbe1a95069bb11f8c0fbd07233 Mon Sep 17 00:00:00 2001 From: Yonas Kolb Date: Tue, 24 Oct 2017 21:30:06 +0200 Subject: [PATCH] move basePath into ProjectSpec --- Sources/ProjectSpec/ProjectSpec.swift | 9 ++++--- Sources/XcodeGen/main.swift | 2 +- Sources/XcodeGenKit/PBXProjGenerator.swift | 26 +++++++++---------- Sources/XcodeGenKit/ProjectGenerator.swift | 8 +++--- Sources/XcodeGenKit/SpecLoader.swift | 2 +- Sources/XcodeGenKit/SpecValidation.swift | 12 ++++----- Tests/XcodeGenKitTests/FixtureTests.swift | 4 +-- .../ProjectGeneratorTests.swift | 20 +++++++------- Tests/XcodeGenKitTests/SpecLoadingTests.swift | 8 +++--- 9 files changed, 45 insertions(+), 46 deletions(-) diff --git a/Sources/ProjectSpec/ProjectSpec.swift b/Sources/ProjectSpec/ProjectSpec.swift index 544782e4..7789f9fe 100644 --- a/Sources/ProjectSpec/ProjectSpec.swift +++ b/Sources/ProjectSpec/ProjectSpec.swift @@ -14,6 +14,7 @@ import Yams public struct ProjectSpec { + public var basePath: Path public var name: String public var targets: [Target] public var settings: Settings @@ -56,7 +57,8 @@ public struct ProjectSpec { } } - public init(name: String, configs: [Config] = [], targets: [Target] = [], settings: Settings = .empty, settingGroups: [String: Settings] = [:], schemes: [Scheme] = [], options: Options = Options(), fileGroups: [String] = [], configFiles: [String: String] = [:], attributes: [String: Any] = [:]) { + public init(basePath: Path, name: String, configs: [Config] = [], targets: [Target] = [], settings: Settings = .empty, settingGroups: [String: Settings] = [:], schemes: [Scheme] = [], options: Options = Options(), fileGroups: [String] = [], configFiles: [String: String] = [:], attributes: [String: Any] = [:]) { + self.basePath = basePath self.name = name self.targets = targets self.configs = configs @@ -124,9 +126,10 @@ extension ProjectSpec.Options: Equatable { } } -extension ProjectSpec: JSONObjectConvertible { +extension ProjectSpec { - public init(jsonDictionary: JSONDictionary) throws { + public init(basePath: Path, jsonDictionary: JSONDictionary) throws { + self.basePath = basePath let jsonDictionary = try ProjectSpec.filterJSON(jsonDictionary: jsonDictionary) name = try jsonDictionary.json(atKeyPath: "name") settings = jsonDictionary.json(atKeyPath: "settings") ?? .empty diff --git a/Sources/XcodeGen/main.swift b/Sources/XcodeGen/main.swift index 4934dcfc..46875360 100644 --- a/Sources/XcodeGen/main.swift +++ b/Sources/XcodeGen/main.swift @@ -33,7 +33,7 @@ func generate(spec: String, project: String) { } do { - let projectGenerator = ProjectGenerator(spec: spec, path: specPath.parent()) + let projectGenerator = ProjectGenerator(spec: spec) let project = try projectGenerator.generateProject() print("⚙️ Generated project") diff --git a/Sources/XcodeGenKit/PBXProjGenerator.swift b/Sources/XcodeGenKit/PBXProjGenerator.swift index 18e1f6ab..98b24305 100644 --- a/Sources/XcodeGenKit/PBXProjGenerator.swift +++ b/Sources/XcodeGenKit/PBXProjGenerator.swift @@ -17,7 +17,6 @@ import ProjectSpec public class PBXProjGenerator { let spec: ProjectSpec - let basePath: Path let currentXcodeVersion: String var fileReferencesByPath: [Path: String] = [:] @@ -38,10 +37,9 @@ public class PBXProjGenerator { return spec.options.carthageBuildPath ?? "Carthage/Build" } - public init(spec: ProjectSpec, path: Path, currentXcodeVersion: String) { + public init(spec: ProjectSpec, currentXcodeVersion: String) { self.currentXcodeVersion = currentXcodeVersion self.spec = spec - basePath = path } public func generateUUID(_ element: T.Type, _ id: String) -> String { @@ -67,14 +65,14 @@ public class PBXProjGenerator { project = PBXProj(archiveVersion: 1, objectVersion: 46, rootObject: generateUUID(PBXProject.self, spec.name)) for group in spec.fileGroups { - _ = try getGroups(path: basePath + group) + _ = try getGroups(path: spec.basePath + group) } let buildConfigs: [XCBuildConfiguration] = spec.configs.map { config in let buildSettings = spec.getProjectBuildSettings(config: config) var baseConfigurationReference: String? if let configPath = spec.configFiles[config.name] { - baseConfigurationReference = getFileReference(path: basePath + configPath, inPath: basePath) + baseConfigurationReference = getFileReference(path: spec.basePath + configPath, inPath: spec.basePath) } return XCBuildConfiguration(reference: generateUUID(XCBuildConfiguration.self, config.name), name: config.name, baseConfigurationReference: baseConfigurationReference, buildSettings: buildSettings) } @@ -159,7 +157,7 @@ public class PBXProjGenerator { let carthageDependencies = getAllCarthageDependencies(target: target) - let sourcePaths = target.sources.map { basePath + $0 } + let sourcePaths = target.sources.map { spec.basePath + $0 } var sourceFiles: [SourceFile] = [] for source in sourcePaths { @@ -177,13 +175,13 @@ public class PBXProjGenerator { // automatically set INFOPLIST_FILE path if let plistPath = infoPlists.first, - !spec.targetHasBuildSetting("INFOPLIST_FILE", basePath: basePath, target: target, config: config) { - buildSettings["INFOPLIST_FILE"] = plistPath.byRemovingBase(path: basePath) + !spec.targetHasBuildSetting("INFOPLIST_FILE", basePath: spec.basePath, target: target, config: config) { + buildSettings["INFOPLIST_FILE"] = plistPath.byRemovingBase(path: spec.basePath) } // automatically calculate bundle id if let bundleIdPrefix = spec.options.bundleIdPrefix, - !spec.targetHasBuildSetting("PRODUCT_BUNDLE_IDENTIFIER", basePath: basePath, target: target, config: config) { + !spec.targetHasBuildSetting("PRODUCT_BUNDLE_IDENTIFIER", basePath: spec.basePath, target: target, config: config) { let characterSet = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-.")).inverted let escapedTargetName = target.name.replacingOccurrences(of: "_", with: "-").components(separatedBy: characterSet).joined(separator: "") buildSettings["PRODUCT_BUNDLE_IDENTIFIER"] = bundleIdPrefix + "." + escapedTargetName @@ -191,7 +189,7 @@ public class PBXProjGenerator { // automatically set test target name if target.type == .uiTestBundle, - !spec.targetHasBuildSetting("TEST_TARGET_NAME", basePath: basePath, target: target, config: config) { + !spec.targetHasBuildSetting("TEST_TARGET_NAME", basePath: spec.basePath, target: target, config: config) { for dependency in target.dependencies { if dependency.type == .target, let dependencyTarget = spec.getTarget(dependency.reference), @@ -219,7 +217,7 @@ public class PBXProjGenerator { var baseConfigurationReference: String? if let configPath = target.configFiles[config.name] { - baseConfigurationReference = getFileReference(path: basePath + configPath, inPath: basePath) + baseConfigurationReference = getFileReference(path: spec.basePath + configPath, inPath: spec.basePath) } return XCBuildConfiguration(reference: generateUUID(XCBuildConfiguration.self, config.name + target.name), name: config.name, baseConfigurationReference: baseConfigurationReference, buildSettings: buildSettings) } @@ -277,7 +275,7 @@ public class PBXProjGenerator { case .framework: - let fileReference = getFileReference(path: Path(dependency.reference), inPath: basePath) + let fileReference = getFileReference(path: Path(dependency.reference), inPath: spec.basePath) let buildFile = PBXBuildFile(reference: generateUUID(PBXBuildFile.self, fileReference + target.name), fileRef: fileReference) addObject(buildFile) @@ -330,7 +328,7 @@ public class PBXProjGenerator { var shellScript: String switch buildScript.script { case let .path(path): - shellScript = try (basePath + path).read() + shellScript = try (spec.basePath + path).read() case let .script(script): shellScript = script } @@ -583,7 +581,7 @@ public class PBXProjGenerator { } } - let groupPath: String = depth == 0 ? path.byRemovingBase(path: basePath).string : path.lastComponent + let groupPath: String = depth == 0 ? path.byRemovingBase(path: spec.basePath).string : path.lastComponent let group: PBXGroup if let cachedGroup = groupsByPath[path] { group = cachedGroup diff --git a/Sources/XcodeGenKit/ProjectGenerator.swift b/Sources/XcodeGenKit/ProjectGenerator.swift index cd804ec5..1670e7a8 100644 --- a/Sources/XcodeGenKit/ProjectGenerator.swift +++ b/Sources/XcodeGenKit/ProjectGenerator.swift @@ -16,12 +16,10 @@ import ProjectSpec public class ProjectGenerator { var spec: ProjectSpec - var path: Path let currentXcodeVersion = "0900" - public init(spec: ProjectSpec, path: Path) { + public init(spec: ProjectSpec) { self.spec = spec - self.path = path } var defaultDebugConfig: Config { @@ -33,8 +31,8 @@ public class ProjectGenerator { } public func generateProject() throws -> XcodeProj { - try spec.validate(path: path) - let pbxProjGenerator = PBXProjGenerator(spec: spec, path: path, currentXcodeVersion: currentXcodeVersion) + try spec.validate() + let pbxProjGenerator = PBXProjGenerator(spec: spec, currentXcodeVersion: currentXcodeVersion) let pbxProject = try pbxProjGenerator.generate() let workspace = try generateWorkspace() let sharedData = try generateSharedData(pbxProject: pbxProject) diff --git a/Sources/XcodeGenKit/SpecLoader.swift b/Sources/XcodeGenKit/SpecLoader.swift index cee23066..51f10c29 100644 --- a/Sources/XcodeGenKit/SpecLoader.swift +++ b/Sources/XcodeGenKit/SpecLoader.swift @@ -16,7 +16,7 @@ public struct SpecLoader { public static func loadSpec(path: Path) throws -> ProjectSpec { let dictionary = try loadDictionary(path: path) - return try ProjectSpec(jsonDictionary: dictionary) + return try ProjectSpec(basePath: path.parent(), jsonDictionary: dictionary) } private static func loadDictionary(path: Path) throws -> JSONDictionary { diff --git a/Sources/XcodeGenKit/SpecValidation.swift b/Sources/XcodeGenKit/SpecValidation.swift index e27375b3..454e5837 100644 --- a/Sources/XcodeGenKit/SpecValidation.swift +++ b/Sources/XcodeGenKit/SpecValidation.swift @@ -11,7 +11,7 @@ import PathKit extension ProjectSpec { - public mutating func validate(path: Path) throws { + public mutating func validate() throws { if configs.isEmpty { configs = [Config(name: "Debug", type: .debug), Config(name: "Release", type: .release)] @@ -32,13 +32,13 @@ extension ProjectSpec { } for fileGroup in fileGroups { - if !(path + fileGroup).exists { + if !(basePath + fileGroup).exists { errors.append(.invalidFileGroup(fileGroup)) } } for (config, configFile) in configFiles { - if !(path + configFile).exists { + if !(basePath + configFile).exists { errors.append(.invalidConfigFile(configFile: configFile, config: config)) } } @@ -55,7 +55,7 @@ extension ProjectSpec { } for (config, configFile) in target.configFiles { - if !(path + configFile).exists { + if !(basePath + configFile).exists { errors.append(.invalidTargetConfigFile(configFile: configFile, config: config, target: target.name)) } } @@ -67,7 +67,7 @@ extension ProjectSpec { } for source in target.sources { - let sourcePath = path + source + let sourcePath = basePath + source if !sourcePath.exists { errors.append(.missingTargetSource(target: target.name, source: sourcePath.string)) } @@ -94,7 +94,7 @@ extension ProjectSpec { let scripts = target.prebuildScripts + target.postbuildScripts for script in scripts { if case let .path(pathString) = script.script { - let scriptPath = path + pathString + let scriptPath = basePath + pathString if !scriptPath.exists { errors.append(.invalidBuildScriptPath(target: target.name, path: pathString)) } diff --git a/Tests/XcodeGenKitTests/FixtureTests.swift b/Tests/XcodeGenKitTests/FixtureTests.swift index 8fad8542..fe808cbc 100644 --- a/Tests/XcodeGenKitTests/FixtureTests.swift +++ b/Tests/XcodeGenKitTests/FixtureTests.swift @@ -7,8 +7,8 @@ import ProjectSpec let fixturePath = Path(#file).parent().parent().parent() + "Fixtures" func generate(specPath: Path, projectPath: Path) throws -> XcodeProj { - let spec = try ProjectSpec(path: specPath) - let generator = ProjectGenerator(spec: spec, path: specPath.parent()) + let spec = try SpecLoader.loadSpec(path: specPath) + let generator = ProjectGenerator(spec: spec) let project = try generator.generateProject() let oldProject = try XcodeProj(path: projectPath) try project.write(path: projectPath, override: true) diff --git a/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift b/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift index 26268719..4238033b 100644 --- a/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift +++ b/Tests/XcodeGenKitTests/ProjectGeneratorTests.swift @@ -7,7 +7,7 @@ import ProjectSpec func projectGeneratorTests() { func getProject(_ spec: ProjectSpec) throws -> XcodeProj { - let generator = ProjectGenerator(spec: spec, path: Path("")) + let generator = ProjectGenerator(spec: spec) return try generator.generateProject() } @@ -31,7 +31,7 @@ func projectGeneratorTests() { $0.it("generates bundle id") { var options = ProjectSpec.Options() options.bundleIdPrefix = "com.test" - let spec = ProjectSpec(name: "test", targets: [framework], options: options) + let spec = ProjectSpec(basePath: "", name: "test", targets: [framework], options: options) let project = try getProject(spec) guard let target = project.pbxproj.nativeTargets.first, let buildConfigs = project.pbxproj.configurationLists.getReference(target.buildConfigurationList), @@ -45,7 +45,7 @@ func projectGeneratorTests() { $0.it("clears setting presets") { var options = ProjectSpec.Options() options.settingPresets = .none - let spec = ProjectSpec(name: "test", targets: [framework], options: options) + let spec = ProjectSpec(basePath: "", name: "test", targets: [framework], options: options) let project = try getProject(spec) let allSettings = project.pbxproj.buildConfigurations.reduce([:]) { $0.merged($1.buildSettings)}.keys.sorted() try expect(allSettings) == ["SETTING_2"] @@ -56,7 +56,7 @@ func projectGeneratorTests() { $0.describe("Config") { $0.it("generates config defaults") { - let spec = ProjectSpec(name: "test") + let spec = ProjectSpec(basePath: "", name: "test") let project = try getProject(spec) let configs = project.pbxproj.buildConfigurations try expect(configs.count) == 2 @@ -65,7 +65,7 @@ func projectGeneratorTests() { } $0.it("generates configs") { - let spec = ProjectSpec(name: "test", configs: [Config(name: "config1"), Config(name: "config2")]) + let spec = ProjectSpec(basePath: "", name: "test", configs: [Config(name: "config1"), Config(name: "config2")]) let project = try getProject(spec) let configs = project.pbxproj.buildConfigurations try expect(configs.count) == 2 @@ -74,7 +74,7 @@ func projectGeneratorTests() { } $0.it("clears config settings when missing type") { - let spec = ProjectSpec(name: "test", configs: [Config(name: "config")]) + let spec = ProjectSpec(basePath: "", name: "test", configs: [Config(name: "config")]) let project = try getProject(spec) guard let config = project.pbxproj.buildConfigurations.first else { throw failure("configuration not found") @@ -83,7 +83,7 @@ func projectGeneratorTests() { } $0.it("merges settings") { - let spec = try ProjectSpec(path: fixturePath + "settings_test.yml") + let spec = try SpecLoader.loadSpec(path: fixturePath + "settings_test.yml") guard let config = spec.getConfig("config1") else { throw failure("Couldn't find config1") } let debugProjectSettings = spec.getProjectBuildSettings(config: config) @@ -113,7 +113,7 @@ func projectGeneratorTests() { $0.describe("Targets") { - let spec = ProjectSpec(name: "test", targets: targets) + let spec = ProjectSpec(basePath: "", name: "test", targets: targets) $0.it("generates targets") { let pbxProject = try getPbxProj(spec) @@ -164,7 +164,7 @@ func projectGeneratorTests() { let buildTarget = Scheme.BuildTarget(target: application.name) $0.it("generates scheme") { let scheme = Scheme(name: "MyScheme", build: Scheme.Build(targets: [buildTarget])) - let spec = ProjectSpec(name: "test", targets: [application, framework], schemes: [scheme]) + let spec = ProjectSpec(basePath: "", name: "test", targets: [application, framework], schemes: [scheme]) let project = try getProject(spec) guard let target = project.pbxproj.nativeTargets.first(where: { $0.name == application.name }) else { throw failure("Target not found") } guard let xcscheme = project.sharedData?.schemes.first else { throw failure("Scheme not found") } @@ -203,7 +203,7 @@ func projectGeneratorTests() { Config(name: "Production Release", type: .release), ] - let spec = ProjectSpec(name: "test", configs: configs, targets: [target, framework]) + let spec = ProjectSpec(basePath: "", name: "test", configs: configs, targets: [target, framework]) let project = try getProject(spec) try expect(project.sharedData?.schemes.count) == 2 diff --git a/Tests/XcodeGenKitTests/SpecLoadingTests.swift b/Tests/XcodeGenKitTests/SpecLoadingTests.swift index d7319601..60279410 100644 --- a/Tests/XcodeGenKitTests/SpecLoadingTests.swift +++ b/Tests/XcodeGenKitTests/SpecLoadingTests.swift @@ -12,7 +12,7 @@ func specLoadingTests() { for (key, value) in spec { specDictionary[key] = value } - return try ProjectSpec(jsonDictionary: specDictionary) + return try ProjectSpec(basePath: "", jsonDictionary: specDictionary) } func expectProjectSpecError(_ spec: [String: Any], _ expectedError: ProjectSpecError) throws { @@ -82,7 +82,7 @@ func specLoadingTests() { try expect(target.dependencies[2]) == Dependency(type: .framework, reference: "path") } - $0.it("parsed cross platform targets") { + $0.it("parses cross platform targets") { let targetDictionary: [String: Any] = [ "platform": ["iOS", "tvOS"], "type": "framework", @@ -128,7 +128,7 @@ func specLoadingTests() { } $0.it("parses settings") { - let spec = try ProjectSpec(path: fixturePath + "settings_test.yml") + let spec = try SpecLoader.loadSpec(path: fixturePath + "settings_test.yml") let buildSettings: BuildSettings = ["SETTING": "value"] let configSettings: [String: Settings] = ["config1": Settings(buildSettings: ["SETTING1": "value"])] let groups = ["preset1"] @@ -176,7 +176,7 @@ func specLoadingTests() { var options = ProjectSpec.Options() options.carthageBuildPath = "../Carthage/Build" options.bundleIdPrefix = "com.test" - let expected = ProjectSpec(name: "test", options: options) + let expected = ProjectSpec(basePath: "", name: "test", options: options) let parsedSpec = try getProjectSpec(["options": ["carthageBuildPath": "../Carthage/Build", "bundleIdPrefix": "com.test"]]) try expect(parsedSpec) == expected }