diff --git a/Sources/ProjectSpec/Scheme.swift b/Sources/ProjectSpec/Scheme.swift index 6e58be0c..bb773db5 100644 --- a/Sources/ProjectSpec/Scheme.swift +++ b/Sources/ProjectSpec/Scheme.swift @@ -112,6 +112,7 @@ public struct Scheme: Equatable { public static let parallelizableDefault = false public let name: String + public var externalProject: String? public var randomExecutionOrder: Bool public var parallelizable: Bool public var skippedTests: [String] @@ -220,11 +221,13 @@ public struct Scheme: Equatable { public struct BuildTarget: Equatable { public var target: String + public var externalProject: String? public var buildTypes: [BuildType] - public init(target: String, buildTypes: [BuildType] = BuildType.all) { + public init(target: String, externalProject: String? = nil, buildTypes: [BuildType] = BuildType.all) { self.target = target self.buildTypes = buildTypes + self.externalProject = externalProject } } } @@ -335,6 +338,7 @@ extension Scheme.Test.TestTarget: JSONObjectConvertible { public init(jsonDictionary: JSONDictionary) throws { name = try jsonDictionary.json(atKeyPath: "name") + externalProject = jsonDictionary.json(atKeyPath: "externalProject") randomExecutionOrder = jsonDictionary.json(atKeyPath: "randomExecutionOrder") ?? Scheme.Test.TestTarget.randomExecutionOrderDefault parallelizable = jsonDictionary.json(atKeyPath: "parallelizable") ?? Scheme.Test.TestTarget.parallelizableDefault skippedTests = jsonDictionary.json(atKeyPath: "skippedTests") ?? [] @@ -357,6 +361,9 @@ extension Scheme.Test.TestTarget: JSONEncodable { if parallelizable != Scheme.Test.TestTarget.parallelizableDefault { dict["parallelizable"] = parallelizable } + if let externalProject = externalProject { + dict["externalProject"] = externalProject + } return dict } diff --git a/Sources/XcodeGenKit/SchemeGenerator.swift b/Sources/XcodeGenKit/SchemeGenerator.swift index 5324aa0c..3c9dc8e9 100644 --- a/Sources/XcodeGenKit/SchemeGenerator.swift +++ b/Sources/XcodeGenKit/SchemeGenerator.swift @@ -75,18 +75,24 @@ public class SchemeGenerator { public func generateScheme(_ scheme: Scheme) throws -> XCScheme { - func getBuildEntry( - _ buildTarget: Scheme.BuildTarget, - from project: (pbxProj: PBXProj, name: String) - ) -> XCScheme.BuildAction.Entry { + func getBuildEntry(_ buildTarget: Scheme.BuildTarget) throws -> XCScheme.BuildAction.Entry { + let pbxProj: PBXProj + let projectFilename: String + if let externalProject = buildTarget.externalProject { + pbxProj = try XcodeProj(pathString: externalProject).pbxproj + projectFilename = externalProject + } else { + pbxProj = self.pbxProj + projectFilename = "\(self.project.name).xcodeproj" + } - guard let pbxTarget = project.pbxProj.targets(named: buildTarget.target).first else { + guard let pbxTarget = pbxProj.targets(named: buildTarget.target).first else { fatalError("Unable to find target named \"\(buildTarget.target)\" in \"PBXProj.targets\"") } let buildableName = pbxTarget.productNameWithExtension() ?? pbxTarget.name let buildableReference = XCScheme.BuildableReference( - referencedContainer: "container:\(project.name).xcodeproj", + referencedContainer: "container:\(projectFilename)", blueprint: pbxTarget, buildableName: buildableName, blueprintName: buildTarget.target @@ -96,13 +102,12 @@ public class SchemeGenerator { let testTargets = scheme.test?.targets ?? [] let testBuildTargets = testTargets.map { - Scheme.BuildTarget(target: $0.name, buildTypes: BuildType.testOnly) + Scheme.BuildTarget(target: $0.name, externalProject: $0.externalProject, buildTypes: BuildType.testOnly) } - let testBuildTargetEntries = testBuildTargets.map { getBuildEntry($0, from: (pbxProj, project.name)) } + let testBuildTargetEntries = try testBuildTargets.map(getBuildEntry) - let buildActionEntries: [XCScheme.BuildAction.Entry] = scheme.build.targets - .map { getBuildEntry($0, from: (pbxProj, project.name)) } + let buildActionEntries: [XCScheme.BuildAction.Entry] = try scheme.build.targets.map(getBuildEntry) func getExecutionAction(_ action: Scheme.ExecutionAction) -> XCScheme.ExecutionAction { // ExecutionActions can require the use of build settings. Xcode allows the settings to come from a build or test target.