Define all graph methods in the traverser protocol and provide an implementation for the value graph traverser
This commit is contained in:
parent
bb5c419bae
commit
47bbc00f52
|
@ -94,6 +94,10 @@ class CacheGraphMutator: CacheGraphMutating {
|
|||
return
|
||||
}
|
||||
|
||||
// Transitive bundles
|
||||
// get all the transitive bundles
|
||||
// declare them as direct dependencies.
|
||||
|
||||
// If the target cannot be replaced with its associated .(xc)framework we return
|
||||
guard !sources.contains(targetDependency.target.name), let precompiledFrameworkPath = precompiledFrameworkPath(target: targetDependency,
|
||||
precompiledFrameworks: precompiledFrameworks,
|
||||
|
|
|
@ -353,7 +353,7 @@ public class Graph: Encodable, Equatable {
|
|||
/// - Parameters:
|
||||
/// - path: Path to the directory where the project that defines the target is located.
|
||||
/// - name: Name of the target.
|
||||
public func embeddableFrameworks(path: AbsolutePath, name: String) throws -> [GraphDependencyReference] {
|
||||
public func embeddableFrameworks(path: AbsolutePath, name: String) -> [GraphDependencyReference] {
|
||||
guard let targetNode = findTargetNode(path: path, name: name),
|
||||
canEmbedProducts(targetNode: targetNode)
|
||||
else {
|
||||
|
@ -382,7 +382,7 @@ public class Graph: Encodable, Equatable {
|
|||
// Exclude any products embed in unit test host apps
|
||||
if targetNode.target.product == .unitTests {
|
||||
if let hostApp = hostApplication(for: targetNode) {
|
||||
references.subtract(try embeddableFrameworks(path: hostApp.path, name: hostApp.name))
|
||||
references.subtract(embeddableFrameworks(path: hostApp.path, name: hostApp.name))
|
||||
} else {
|
||||
references = []
|
||||
}
|
||||
|
@ -417,8 +417,8 @@ public class Graph: Encodable, Equatable {
|
|||
try self.linkableDependencies(path: project.path, name: $0.name)
|
||||
}
|
||||
|
||||
let embeddableDependencies = try project.targets.flatMap {
|
||||
try self.embeddableFrameworks(path: project.path, name: $0.name)
|
||||
let embeddableDependencies = project.targets.flatMap {
|
||||
self.embeddableFrameworks(path: project.path, name: $0.name)
|
||||
}
|
||||
|
||||
let copyProductDependencies = project.targets.flatMap {
|
||||
|
@ -446,7 +446,7 @@ public class Graph: Encodable, Equatable {
|
|||
.filter { validProducts.contains($0.target.product) }
|
||||
}
|
||||
|
||||
public func appClipsDependency(path: AbsolutePath, name: String) -> TargetNode? {
|
||||
public func appClipDependencies(path: AbsolutePath, name: String) -> TargetNode? {
|
||||
guard let targetNode = findTargetNode(path: path, name: name) else {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ public enum GraphDependencyReference: Equatable, Comparable, Hashable {
|
|||
)
|
||||
case library(
|
||||
path: AbsolutePath,
|
||||
binaryPath: AbsolutePath,
|
||||
linking: BinaryLinking,
|
||||
architectures: [BinaryArchitecture],
|
||||
product: Product
|
||||
|
@ -40,7 +39,6 @@ public enum GraphDependencyReference: Equatable, Comparable, Hashable {
|
|||
product: frameworkNode.product)
|
||||
} else if let libraryNode = precompiledNode as? LibraryNode {
|
||||
self = .library(path: libraryNode.path,
|
||||
binaryPath: libraryNode.binaryPath,
|
||||
linking: libraryNode.linking,
|
||||
architectures: libraryNode.architectures,
|
||||
product: libraryNode.product)
|
||||
|
@ -56,7 +54,7 @@ public enum GraphDependencyReference: Equatable, Comparable, Hashable {
|
|||
|
||||
public func hash(into hasher: inout Hasher) {
|
||||
switch self {
|
||||
case let .library(path, _, _, _, _):
|
||||
case let .library(path, _, _, _):
|
||||
hasher.combine(path)
|
||||
case let .framework(path, _, _, _, _, _, _, _):
|
||||
hasher.combine(path)
|
||||
|
@ -78,7 +76,7 @@ public enum GraphDependencyReference: Equatable, Comparable, Hashable {
|
|||
switch self {
|
||||
case let .framework(path, _, _, _, _, _, _, _):
|
||||
return path
|
||||
case let .library(path, _, _, _, _):
|
||||
case let .library(path, _, _, _):
|
||||
return path
|
||||
case let .xcframework(path, _, _, _):
|
||||
return path
|
||||
|
@ -93,7 +91,7 @@ public enum GraphDependencyReference: Equatable, Comparable, Hashable {
|
|||
return lhsPath < rhsPath
|
||||
case let (.xcframework(lhsPath, _, _, _), .xcframework(rhsPath, _, _, _)):
|
||||
return lhsPath < rhsPath
|
||||
case let (.library(lhsPath, _, _, _, _), .library(rhsPath, _, _, _, _)):
|
||||
case let (.library(lhsPath, _, _, _), .library(rhsPath, _, _, _)):
|
||||
return lhsPath < rhsPath
|
||||
case let (.product(lhsTarget, lhsProductName), .product(rhsTarget, rhsProductName)):
|
||||
if lhsTarget == rhsTarget {
|
||||
|
|
|
@ -3,39 +3,92 @@ import TSCBasic
|
|||
|
||||
public final class GraphTraverser: GraphTraversing {
|
||||
private let graph: Graph
|
||||
public var name: String { graph.name }
|
||||
public var hasPackages: Bool { !graph.packages.isEmpty }
|
||||
public var path: AbsolutePath { graph.entryPath }
|
||||
public var workspace: Workspace { graph.workspace }
|
||||
public var projects: [AbsolutePath: Project]
|
||||
|
||||
public init(graph: Graph) {
|
||||
self.graph = graph
|
||||
projects = Dictionary(uniqueKeysWithValues: graph.projects.map { ($0.path, $0) })
|
||||
}
|
||||
|
||||
public func target(path: AbsolutePath, name: String) -> Target? {
|
||||
graph.target(path: path, name: name).map(\.target)
|
||||
public func target(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
graph.target(path: path, name: name).map {
|
||||
ValueGraphTarget(path: $0.path, target: $0.target, project: $0.project)
|
||||
}
|
||||
}
|
||||
|
||||
public func targets(at path: AbsolutePath) -> [Target] {
|
||||
graph.targets(at: path).map(\.target)
|
||||
public func targets(at path: AbsolutePath) -> Set<ValueGraphTarget> {
|
||||
Set(graph.targets(at: path).map {
|
||||
ValueGraphTarget(path: $0.path, target: $0.target, project: $0.project)
|
||||
})
|
||||
}
|
||||
|
||||
public func directTargetDependencies(path: AbsolutePath, name: String) -> [Target] {
|
||||
graph.targetDependencies(path: path, name: name).map(\.target)
|
||||
public func directTargetDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
Set(graph.targetDependencies(path: path, name: name).map {
|
||||
ValueGraphTarget(path: $0.path, target: $0.target, project: $0.project)
|
||||
})
|
||||
}
|
||||
|
||||
public func appExtensionDependencies(path: AbsolutePath, name: String) -> [Target] {
|
||||
graph.appExtensionDependencies(path: path, name: name).map(\.target)
|
||||
public func appExtensionDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
Set(graph.appExtensionDependencies(path: path, name: name).map {
|
||||
ValueGraphTarget(path: $0.path, target: $0.target, project: $0.project)
|
||||
})
|
||||
}
|
||||
|
||||
public func resourceBundleDependencies(path: AbsolutePath, name: String) -> [Target] {
|
||||
graph.resourceBundleDependencies(path: path, name: name).map(\.target)
|
||||
public func resourceBundleDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
Set(graph.resourceBundleDependencies(path: path, name: name).map {
|
||||
ValueGraphTarget(path: $0.path, target: $0.target, project: $0.project)
|
||||
})
|
||||
}
|
||||
|
||||
public func testTargetsDependingOn(path: AbsolutePath, name: String) -> [Target] {
|
||||
graph.testTargetsDependingOn(path: path, name: name).map(\.target)
|
||||
public func testTargetsDependingOn(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
Set(graph.testTargetsDependingOn(path: path, name: name).map {
|
||||
ValueGraphTarget(path: $0.path, target: $0.target, project: $0.project)
|
||||
})
|
||||
}
|
||||
|
||||
public func directStaticDependencies(path: AbsolutePath, name: String) -> [GraphDependencyReference] {
|
||||
graph.staticDependencies(path: path, name: name)
|
||||
public func directStaticDependencies(path: AbsolutePath, name: String) -> Set<GraphDependencyReference> {
|
||||
Set(graph.staticDependencies(path: path, name: name))
|
||||
}
|
||||
|
||||
public func appClipsDependency(path: AbsolutePath, name: String) -> Target? {
|
||||
graph.appClipsDependency(path: path, name: name).map(\.target)
|
||||
public func appClipDependencies(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
graph.appClipDependencies(path: path, name: name).map { ValueGraphTarget(path: $0.path, target: $0.target, project: $0.project) }
|
||||
}
|
||||
|
||||
public func embeddableFrameworks(path: AbsolutePath, name: String) -> Set<GraphDependencyReference> {
|
||||
Set(graph.embeddableFrameworks(path: path, name: name))
|
||||
}
|
||||
|
||||
public func linkableDependencies(path: AbsolutePath, name: String) throws -> Set<GraphDependencyReference> {
|
||||
try Set(graph.linkableDependencies(path: path, name: name))
|
||||
}
|
||||
|
||||
public func copyProductDependencies(path: AbsolutePath, name: String) -> Set<GraphDependencyReference> {
|
||||
guard let target = graph.target(path: path, name: name) else { return Set() }
|
||||
return Set(graph.copyProductDependencies(path: path, target: target.target))
|
||||
}
|
||||
|
||||
public func librariesPublicHeadersFolders(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
Set(graph.librariesPublicHeadersFolders(path: path, name: name))
|
||||
}
|
||||
|
||||
public func librariesSearchPaths(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
Set(graph.librariesSearchPaths(path: path, name: name))
|
||||
}
|
||||
|
||||
public func librariesSwiftIncludePaths(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
Set(graph.librariesSwiftIncludePaths(path: path, name: name))
|
||||
}
|
||||
|
||||
public func runPathSearchPaths(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
Set(graph.runPathSearchPaths(path: path, name: name))
|
||||
}
|
||||
|
||||
public func hostTargetFor(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
graph.hostTargetNodeFor(path: path, name: name)
|
||||
.map { ValueGraphTarget(path: $0.path, target: $0.target, project: $0.project) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,49 +2,114 @@ import Foundation
|
|||
import TSCBasic
|
||||
|
||||
public protocol GraphTraversing {
|
||||
/// Graph name
|
||||
var name: String { get }
|
||||
|
||||
/// Returns true if the project has package dependencies.
|
||||
var hasPackages: Bool { get }
|
||||
|
||||
/// The path to the directory from where the graph has been loaded.
|
||||
var path: AbsolutePath { get }
|
||||
|
||||
/// Returns the graph's workspace.
|
||||
var workspace: Workspace { get }
|
||||
|
||||
/// Returns the graph projects.
|
||||
var projects: [AbsolutePath: Project] { get }
|
||||
|
||||
/// It returns the target with the given name in the project that is defined in the given directory path.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the definition of the project with the target is defined.
|
||||
/// - name: Name of the target.
|
||||
func target(path: AbsolutePath, name: String) -> Target?
|
||||
func target(path: AbsolutePath, name: String) -> ValueGraphTarget?
|
||||
|
||||
/// It returns the targets of the project defined in the directory at the given path.
|
||||
/// - Parameter path: Path to the directory that contains the definition of the project.
|
||||
func targets(at path: AbsolutePath) -> [Target]
|
||||
func targets(at path: AbsolutePath) -> Set<ValueGraphTarget>
|
||||
|
||||
/// Given a project directory and target name, it returns all its direct target dependencies.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project.
|
||||
/// - name: Target name.
|
||||
func directTargetDependencies(path: AbsolutePath, name: String) -> [Target]
|
||||
func directTargetDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget>
|
||||
|
||||
/// Given a project directory and a target name, it returns all the dependencies that are extensions.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project.
|
||||
/// - name: Target name.
|
||||
func appExtensionDependencies(path: AbsolutePath, name: String) -> [Target]
|
||||
func appExtensionDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget>
|
||||
|
||||
/// Returns the transitive resource bundle dependencies for the given target.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory where the project that defines the target is located.
|
||||
/// - name: Name of the target.
|
||||
func resourceBundleDependencies(path: AbsolutePath, name: String) -> [Target]
|
||||
func resourceBundleDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget>
|
||||
|
||||
/// Returns the list of test targets that depend on the one with the given name at the given path.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project definition.
|
||||
/// - name: Name of the target whose dependant test targets will be returned.
|
||||
func testTargetsDependingOn(path: AbsolutePath, name: String) -> [Target]
|
||||
func testTargetsDependingOn(path: AbsolutePath, name: String) -> Set<ValueGraphTarget>
|
||||
|
||||
/// Returns all non-transitive target static dependencies for the given target.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory where the project that defines the target is located.
|
||||
/// - name: Name of the target.
|
||||
func directStaticDependencies(path: AbsolutePath, name: String) -> [GraphDependencyReference]
|
||||
func directStaticDependencies(path: AbsolutePath, name: String) -> Set<GraphDependencyReference>
|
||||
|
||||
/// Given a project directory and a target name, it returns an appClips dependency.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project.
|
||||
/// - name: Target name.
|
||||
func appClipsDependency(path: AbsolutePath, name: String) -> Target?
|
||||
func appClipDependencies(path: AbsolutePath, name: String) -> ValueGraphTarget?
|
||||
|
||||
/// Given a project directory and a target name, it returns the list of dependencies that need to be embedded into the target product.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project.
|
||||
/// - name: Target name.
|
||||
func embeddableFrameworks(path: AbsolutePath, name: String) -> Set<GraphDependencyReference>
|
||||
|
||||
/// Given a project directory and a target name, it returns the list of dependencies that need to be linked from the target.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project.
|
||||
/// - name: Target name.
|
||||
func linkableDependencies(path: AbsolutePath, name: String) throws -> Set<GraphDependencyReference>
|
||||
|
||||
/// Given a project directory and a target name, it returns a list of dependencies that need to be included in a copy files build phase
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project.
|
||||
/// - name: Target name
|
||||
func copyProductDependencies(path: AbsolutePath, name: String) -> Set<GraphDependencyReference>
|
||||
|
||||
/// Given a project directory and a target name, it returns the list of header folders that should be exposed to the target.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project.
|
||||
/// - name: Target name
|
||||
func librariesPublicHeadersFolders(path: AbsolutePath, name: String) -> Set<AbsolutePath>
|
||||
|
||||
/// Given a project directory and a target name, it returns the list of library folders that should be exposed to the target.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project.
|
||||
/// - name: Target name.
|
||||
func librariesSearchPaths(path: AbsolutePath, name: String) -> Set<AbsolutePath>
|
||||
|
||||
/// Given a project directory and a target name, it returns the list of foldres with Swift modules that should be expoed to the target.
|
||||
/// - Parameters:
|
||||
/// - path: Path to the directory that contains the project.
|
||||
/// - name: Target name.
|
||||
func librariesSwiftIncludePaths(path: AbsolutePath, name: String) -> Set<AbsolutePath>
|
||||
|
||||
/// Returns all runpath search paths of the given target
|
||||
/// Currently applied only to test targets with no host application
|
||||
/// - Parameters:
|
||||
/// - path; Path to the directory where the project that defines the target
|
||||
/// - name: Name of the target
|
||||
func runPathSearchPaths(path: AbsolutePath, name: String) -> Set<AbsolutePath>
|
||||
|
||||
/// It returns the host target for the given target.
|
||||
/// - Parameters:
|
||||
/// - path; Path to the directory where the project that defines the target
|
||||
/// - name: Name of the target
|
||||
func hostTargetFor(path: AbsolutePath, name: String) -> ValueGraphTarget?
|
||||
}
|
||||
|
|
|
@ -174,6 +174,10 @@ public enum Product: String, CustomStringConvertible, CaseIterable, Encodable {
|
|||
[.framework, .staticFramework].contains(self)
|
||||
}
|
||||
|
||||
public var isDynamic: Bool {
|
||||
[.framework, .dynamicLibrary].contains(self)
|
||||
}
|
||||
|
||||
public var xcodeValue: PBXProductType {
|
||||
switch self {
|
||||
case .app:
|
||||
|
|
|
@ -9,6 +9,9 @@ public struct ValueGraph: Equatable {
|
|||
/// The path where the graph has been loaded from.
|
||||
public let path: AbsolutePath
|
||||
|
||||
/// Graph's workspace.
|
||||
public let workspace: Workspace
|
||||
|
||||
/// A dictionary where the keys are the paths to the directories where the projects are defined,
|
||||
/// and the values are the projects defined in the directories.
|
||||
public let projects: [AbsolutePath: Project]
|
||||
|
@ -26,6 +29,7 @@ public struct ValueGraph: Equatable {
|
|||
|
||||
public init(name: String,
|
||||
path: AbsolutePath,
|
||||
workspace: Workspace,
|
||||
projects: [AbsolutePath: Project],
|
||||
packages: [AbsolutePath: [String: Package]],
|
||||
targets: [AbsolutePath: [String: Target]],
|
||||
|
@ -33,6 +37,7 @@ public struct ValueGraph: Equatable {
|
|||
{
|
||||
self.name = name
|
||||
self.path = path
|
||||
self.workspace = workspace
|
||||
self.projects = projects
|
||||
self.packages = packages
|
||||
self.targets = targets
|
||||
|
@ -42,6 +47,7 @@ public struct ValueGraph: Equatable {
|
|||
public init(graph: Graph) {
|
||||
name = graph.name
|
||||
path = graph.entryPath
|
||||
workspace = graph.workspace
|
||||
projects = graph.projects.reduce(into: [AbsolutePath: Project]()) { $0[$1.path] = $1 }
|
||||
packages = graph.packages.reduce(into: [AbsolutePath: [String: Package]]()) { acc, package in
|
||||
var packages = acc[package.path, default: [:]]
|
||||
|
@ -88,10 +94,12 @@ public struct ValueGraph: Equatable {
|
|||
return .target(name: node.name, path: node.path)
|
||||
case let node as FrameworkNode:
|
||||
return .framework(path: node.path,
|
||||
binaryPath: node.binaryPath,
|
||||
dsymPath: node.dsymPath,
|
||||
bcsymbolmapPaths: node.bcsymbolmapPaths,
|
||||
linking: node.linking,
|
||||
architectures: node.architectures)
|
||||
architectures: node.architectures,
|
||||
isCarthage: node.isCarthage)
|
||||
case let node as XCFrameworkNode:
|
||||
return .xcframework(path: node.path,
|
||||
infoPlist: node.infoPlist,
|
||||
|
|
|
@ -13,10 +13,12 @@ public enum ValueGraphDependency: Hashable {
|
|||
/// A dependency that represents a pre-compiled framework.
|
||||
case framework(
|
||||
path: AbsolutePath,
|
||||
binaryPath: AbsolutePath,
|
||||
dsymPath: AbsolutePath?,
|
||||
bcsymbolmapPaths: [AbsolutePath],
|
||||
linking: BinaryLinking,
|
||||
architectures: [BinaryArchitecture]
|
||||
architectures: [BinaryArchitecture],
|
||||
isCarthage: Bool
|
||||
)
|
||||
|
||||
/// A dependency that represents a pre-compiled library.
|
||||
|
@ -45,7 +47,7 @@ public enum ValueGraphDependency: Hashable {
|
|||
case let .xcframework(path, _, _, _):
|
||||
hasher.combine("xcframework")
|
||||
hasher.combine(path)
|
||||
case let .framework(path, _, _, _, _):
|
||||
case let .framework(path, _, _, _, _, _, _):
|
||||
hasher.combine("framework")
|
||||
hasher.combine(path)
|
||||
case let .library(path, _, _, _, _):
|
||||
|
@ -70,4 +72,28 @@ public enum ValueGraphDependency: Hashable {
|
|||
hasher.combine(path)
|
||||
}
|
||||
}
|
||||
|
||||
public var isTarget: Bool {
|
||||
switch self {
|
||||
case .xcframework: return false
|
||||
case .framework: return false
|
||||
case .library: return false
|
||||
case .packageProduct: return false
|
||||
case .target: return true
|
||||
case .sdk: return false
|
||||
case .cocoapods: return false
|
||||
}
|
||||
}
|
||||
|
||||
public var isPrecompiled: Bool {
|
||||
switch self {
|
||||
case .xcframework: return true
|
||||
case .framework: return true
|
||||
case .library: return true
|
||||
case .packageProduct: return false
|
||||
case .target: return false
|
||||
case .sdk: return false
|
||||
case .cocoapods: return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
import Foundation
|
||||
import TSCBasic
|
||||
|
||||
public struct ValueGraphTarget: Equatable, Hashable, Comparable, CustomDebugStringConvertible, CustomStringConvertible {
|
||||
/// Path to the directory that contains the project where the target is defined.
|
||||
public let path: AbsolutePath
|
||||
|
||||
/// Target representation.
|
||||
public let target: Target
|
||||
|
||||
/// Project that contains the target.
|
||||
public let project: Project
|
||||
|
||||
public static func < (lhs: ValueGraphTarget, rhs: ValueGraphTarget) -> Bool {
|
||||
(lhs.path, lhs.target) < (rhs.path, rhs.target)
|
||||
}
|
||||
|
||||
// MARK: - CustomDebugStringConvertible/CustomStringConvertible
|
||||
|
||||
public var debugDescription: String {
|
||||
description
|
||||
}
|
||||
|
||||
public var description: String {
|
||||
"Target '\(target.name)' at path '\(project.path)'"
|
||||
}
|
||||
}
|
|
@ -3,41 +3,51 @@ import TSCBasic
|
|||
import TuistSupport
|
||||
|
||||
public class ValueGraphTraverser: GraphTraversing {
|
||||
public var name: String { graph.name }
|
||||
public var hasPackages: Bool { !graph.packages.flatMap(\.value).isEmpty }
|
||||
public var path: AbsolutePath { graph.path }
|
||||
public var workspace: Workspace { graph.workspace }
|
||||
public var projects: [AbsolutePath: Project] { graph.projects }
|
||||
|
||||
private let graph: ValueGraph
|
||||
|
||||
public required init(graph: ValueGraph) {
|
||||
self.graph = graph
|
||||
}
|
||||
|
||||
public func target(path: AbsolutePath, name: String) -> Target? {
|
||||
graph.targets[path]?[name]
|
||||
public func target(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
guard let project = graph.projects[path], let target = graph.targets[path]?[name] else { return nil }
|
||||
return ValueGraphTarget(path: path, target: target, project: project)
|
||||
}
|
||||
|
||||
public func targets(at path: AbsolutePath) -> [Target] {
|
||||
public func targets(at path: AbsolutePath) -> Set<ValueGraphTarget> {
|
||||
guard let project = graph.projects[path] else { return Set() }
|
||||
guard let targets = graph.targets[path] else { return [] }
|
||||
return Array(targets.values).sorted()
|
||||
return Set(targets.values.map { ValueGraphTarget(path: path, target: $0, project: project) })
|
||||
}
|
||||
|
||||
public func directTargetDependencies(path: AbsolutePath, name: String) -> [Target] {
|
||||
public func directTargetDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
guard let dependencies = graph.dependencies[.target(name: name, path: path)] else { return [] }
|
||||
return dependencies.flatMap { (dependency) -> [Target] in
|
||||
guard let project = graph.projects[path] else { return Set() }
|
||||
|
||||
return Set(dependencies.flatMap { (dependency) -> [ValueGraphTarget] in
|
||||
guard case let ValueGraphDependency.target(dependencyName, dependencyPath) = dependency else { return [] }
|
||||
guard let projectDependencies = graph.targets[dependencyPath], let dependencyTarget = projectDependencies[dependencyName] else { return []
|
||||
}
|
||||
return [dependencyTarget]
|
||||
}.sorted()
|
||||
return [ValueGraphTarget(path: path, target: dependencyTarget, project: project)]
|
||||
})
|
||||
}
|
||||
|
||||
public func resourceBundleDependencies(path: AbsolutePath, name: String) -> [Target] {
|
||||
public func resourceBundleDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
guard let target = graph.targets[path]?[name] else { return [] }
|
||||
guard target.supportsResources else { return [] }
|
||||
|
||||
let canHostResources: (ValueGraphDependency) -> Bool = {
|
||||
self.target(from: $0)?.supportsResources == true
|
||||
self.target(from: $0)?.target.supportsResources == true
|
||||
}
|
||||
|
||||
let isBundle: (ValueGraphDependency) -> Bool = {
|
||||
self.target(from: $0)?.product == .bundle
|
||||
self.target(from: $0)?.target.product == .bundle
|
||||
}
|
||||
|
||||
let bundles = filterDependencies(from: .target(name: name, path: path),
|
||||
|
@ -45,39 +55,42 @@ public class ValueGraphTraverser: GraphTraversing {
|
|||
skip: canHostResources)
|
||||
let bundleTargets = bundles.compactMap(target(from:))
|
||||
|
||||
return bundleTargets.sorted()
|
||||
return Set(bundleTargets)
|
||||
}
|
||||
|
||||
public func testTargetsDependingOn(path: AbsolutePath, name: String) -> [Target] {
|
||||
graph.targets[path]?.values
|
||||
public func testTargetsDependingOn(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
guard let project = graph.projects[path] else { return Set() }
|
||||
|
||||
return Set(graph.targets[path]?.values
|
||||
.filter { $0.product.testsBundle }
|
||||
.filter { graph.dependencies[.target(name: $0.name, path: path)]?.contains(.target(name: name, path: path)) == true }
|
||||
.sorted() ?? []
|
||||
.map { ValueGraphTarget(path: path, target: $0, project: project) } ?? [])
|
||||
}
|
||||
|
||||
public func target(from dependency: ValueGraphDependency) -> Target? {
|
||||
public func target(from dependency: ValueGraphDependency) -> ValueGraphTarget? {
|
||||
guard case let ValueGraphDependency.target(name, path) = dependency else {
|
||||
return nil
|
||||
}
|
||||
return graph.targets[path]?[name]
|
||||
guard let target = graph.targets[path]?[name] else { return nil }
|
||||
guard let project = graph.projects[path] else { return nil }
|
||||
return ValueGraphTarget(path: path, target: target, project: project)
|
||||
}
|
||||
|
||||
public func appExtensionDependencies(path: AbsolutePath, name: String) -> [Target] {
|
||||
public func appExtensionDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
let validProducts: [Product] = [
|
||||
.appExtension, .stickerPackExtension, .watch2Extension, .messagesExtension,
|
||||
]
|
||||
return directTargetDependencies(path: path, name: name)
|
||||
.filter { validProducts.contains($0.product) }
|
||||
.sorted()
|
||||
return Set(directTargetDependencies(path: path, name: name)
|
||||
.filter { validProducts.contains($0.target.product) })
|
||||
}
|
||||
|
||||
public func appClipsDependency(path: AbsolutePath, name: String) -> Target? {
|
||||
public func appClipDependencies(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
directTargetDependencies(path: path, name: name)
|
||||
.first { $0.product == .appClip }
|
||||
.first { $0.target.product == .appClip }
|
||||
}
|
||||
|
||||
public func directStaticDependencies(path: AbsolutePath, name: String) -> [GraphDependencyReference] {
|
||||
graph.dependencies[.target(name: name, path: path)]?
|
||||
public func directStaticDependencies(path: AbsolutePath, name: String) -> Set<GraphDependencyReference> {
|
||||
Set(graph.dependencies[.target(name: name, path: path)]?
|
||||
.compactMap { (dependency: ValueGraphDependency) -> (path: AbsolutePath, name: String)? in
|
||||
guard case let ValueGraphDependency.target(name, path) = dependency else {
|
||||
return nil
|
||||
|
@ -86,8 +99,7 @@ public class ValueGraphTraverser: GraphTraversing {
|
|||
}
|
||||
.compactMap { graph.targets[$0.path]?[$0.name] }
|
||||
.filter { $0.product.isStatic }
|
||||
.map { .product(target: $0.name, productName: $0.productNameWithExtension) }
|
||||
.sorted() ?? []
|
||||
.map { .product(target: $0.name, productName: $0.productNameWithExtension) } ?? [])
|
||||
}
|
||||
|
||||
/// It traverses the depdency graph and returns all the dependencies.
|
||||
|
@ -105,15 +117,213 @@ public class ValueGraphTraverser: GraphTraversing {
|
|||
return references
|
||||
}
|
||||
|
||||
public func embeddableFrameworks(path: AbsolutePath, name: String) -> Set<GraphDependencyReference> {
|
||||
guard let target = self.target(path: path, name: name), canEmbedProducts(target: target.target) else { return Set() }
|
||||
|
||||
var references: Set<GraphDependencyReference> = Set([])
|
||||
|
||||
/// Precompiled frameworks
|
||||
let precompiledFrameworks = filterDependencies(from: .target(name: name, path: path),
|
||||
test: isDependencyPrecompiledDynamicAndLinkable,
|
||||
skip: canDependencyEmbedProducts)
|
||||
.lazy
|
||||
.compactMap(dependencyReference)
|
||||
references.formUnion(precompiledFrameworks)
|
||||
|
||||
/// Other targets' frameworks.
|
||||
let otherTargetFrameworks = filterDependencies(from: .target(name: name, path: path),
|
||||
test: isDependencyDynamicTarget,
|
||||
skip: canDependencyEmbedProducts)
|
||||
.lazy
|
||||
.compactMap(dependencyReference)
|
||||
references.formUnion(otherTargetFrameworks)
|
||||
|
||||
// Exclude any products embed in unit test host apps
|
||||
if target.target.product == .unitTests {
|
||||
if let hostApp = hostApplication(path: path, name: name) {
|
||||
references.subtract(embeddableFrameworks(path: hostApp.path, name: hostApp.target.name))
|
||||
} else {
|
||||
references = Set()
|
||||
}
|
||||
}
|
||||
|
||||
return references
|
||||
}
|
||||
|
||||
public func linkableDependencies(path: AbsolutePath, name: String) throws -> Set<GraphDependencyReference> {
|
||||
guard let target = self.target(path: path, name: name) else { return Set() }
|
||||
|
||||
var references = Set<GraphDependencyReference>()
|
||||
|
||||
// System libraries and frameworks
|
||||
if target.target.canLinkStaticProducts() {
|
||||
let transitiveSystemLibraries = transitiveStaticTargets(from: .target(name: name, path: path))
|
||||
.flatMap { (dependency) -> [GraphDependencyReference] in
|
||||
let dependencies = self.graph.dependencies[dependency, default: []]
|
||||
return dependencies.compactMap { dependencyDependency -> GraphDependencyReference? in
|
||||
guard case let ValueGraphDependency.sdk(_, path, status, source) = dependencyDependency else { return nil }
|
||||
return .sdk(path: path, status: status, source: source)
|
||||
}
|
||||
}
|
||||
references.formUnion(transitiveSystemLibraries)
|
||||
}
|
||||
|
||||
// AppClip dependencies
|
||||
if target.target.isAppClip {
|
||||
let path = try SDKNode.appClip(status: .required).path
|
||||
references.formUnion([GraphDependencyReference.sdk(path: path,
|
||||
status: .required,
|
||||
source: .system)])
|
||||
}
|
||||
|
||||
// Direct system libraries and frameworks
|
||||
let directSystemLibrariesAndFrameworks = graph.dependencies[.target(name: name, path: path), default: []]
|
||||
.compactMap { dependency -> GraphDependencyReference? in
|
||||
guard case let ValueGraphDependency.sdk(_, path, status, source) = dependency else { return nil }
|
||||
return .sdk(path: path, status: status, source: source)
|
||||
}
|
||||
references.formUnion(directSystemLibrariesAndFrameworks)
|
||||
|
||||
// Precompiled libraries and frameworks
|
||||
let precompiledLibrariesAndFrameworks = graph.dependencies[.target(name: name, path: path), default: []]
|
||||
.lazy
|
||||
.filter(\.isPrecompiled)
|
||||
.compactMap(dependencyReference)
|
||||
references.formUnion(precompiledLibrariesAndFrameworks)
|
||||
|
||||
// Static libraries and frameworks / Static libraries' dynamic libraries
|
||||
if target.target.canLinkStaticProducts() {
|
||||
var transitiveStaticTargets = self.transitiveStaticTargets(from: .target(name: name, path: path))
|
||||
|
||||
// Exclude any static products linked in a host application
|
||||
if target.target.product == .unitTests {
|
||||
if let hostApp = hostApplication(path: path, name: name) {
|
||||
transitiveStaticTargets.subtract(self.transitiveStaticTargets(from: .target(name: hostApp.target.name, path: hostApp.project.path)))
|
||||
}
|
||||
}
|
||||
|
||||
let transitiveStaticTargetReferences = transitiveStaticTargets.compactMap(dependencyReference)
|
||||
|
||||
let staticDependenciesDynamicLibrariesAndFrameworks = transitiveStaticTargets.flatMap { (dependency) -> [GraphDependencyReference] in
|
||||
self.graph.dependencies[dependency, default: []]
|
||||
.lazy
|
||||
.filter(\.isTarget)
|
||||
.filter(isDependencyDynamicTarget)
|
||||
.compactMap(dependencyReference)
|
||||
}
|
||||
|
||||
references.formUnion(transitiveStaticTargetReferences + staticDependenciesDynamicLibrariesAndFrameworks)
|
||||
}
|
||||
|
||||
// Link dynamic libraries and frameworks
|
||||
let dynamicLibrariesAndFrameworks = graph.dependencies[.target(name: name, path: path), default: []]
|
||||
.filter(or(isDependencyDynamicLibrary, isDependencyFramework))
|
||||
.compactMap(dependencyReference)
|
||||
references.formUnion(dynamicLibrariesAndFrameworks)
|
||||
|
||||
return references
|
||||
}
|
||||
|
||||
public func copyProductDependencies(path: AbsolutePath, name: String) -> Set<GraphDependencyReference> {
|
||||
guard let target = self.target(path: path, name: name) else { return Set() }
|
||||
|
||||
var dependencies = Set<GraphDependencyReference>()
|
||||
|
||||
if target.target.product.isStatic {
|
||||
dependencies.formUnion(directStaticDependencies(path: path, name: name))
|
||||
}
|
||||
|
||||
dependencies.formUnion(resourceBundleDependencies(path: path, name: name).map(targetProductReference))
|
||||
|
||||
return Set(dependencies)
|
||||
}
|
||||
|
||||
public func librariesPublicHeadersFolders(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
let dependencies = graph.dependencies[.target(name: name, path: path), default: []]
|
||||
let libraryPublicHeaders = dependencies.compactMap { dependency -> AbsolutePath? in
|
||||
guard case let ValueGraphDependency.library(_, publicHeaders, _, _, _) = dependency else { return nil }
|
||||
return publicHeaders
|
||||
}
|
||||
return Set(libraryPublicHeaders)
|
||||
}
|
||||
|
||||
public func librariesSearchPaths(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
let dependencies = graph.dependencies[.target(name: name, path: path), default: []]
|
||||
let libraryPaths = dependencies.compactMap { dependency -> AbsolutePath? in
|
||||
guard case let ValueGraphDependency.library(path, _, _, _, _) = dependency else { return nil }
|
||||
return path
|
||||
}
|
||||
return Set(libraryPaths.compactMap { $0.removingLastComponent() })
|
||||
}
|
||||
|
||||
public func librariesSwiftIncludePaths(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
let dependencies = graph.dependencies[.target(name: name, path: path), default: []]
|
||||
let librarySwiftModuleMapPaths = dependencies.compactMap { dependency -> AbsolutePath? in
|
||||
guard case let ValueGraphDependency.library(_, _, _, _, swiftModuleMapPath) = dependency else { return nil }
|
||||
return swiftModuleMapPath
|
||||
}
|
||||
return Set(librarySwiftModuleMapPaths.compactMap { $0.removingLastComponent() })
|
||||
}
|
||||
|
||||
public func runPathSearchPaths(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
guard let target = target(path: path, name: name),
|
||||
canEmbedProducts(target: target.target),
|
||||
target.target.product == .unitTests,
|
||||
hostApplication(path: path, name: name) == nil
|
||||
else {
|
||||
return Set()
|
||||
}
|
||||
|
||||
var references: Set<AbsolutePath> = Set([])
|
||||
|
||||
let from = ValueGraphDependency.target(name: name, path: path)
|
||||
let precompiledFramewoksPaths = filterDependencies(from: from,
|
||||
test: isDependencyPrecompiledDynamicAndLinkable,
|
||||
skip: canDependencyEmbedProducts)
|
||||
.lazy
|
||||
.compactMap { (dependency: ValueGraphDependency) -> AbsolutePath? in
|
||||
switch dependency {
|
||||
case let .xcframework(path, _, _, _): return path
|
||||
case let .framework(path, _, _, _, _, _, _): return path
|
||||
case .library: return nil
|
||||
case .packageProduct: return nil
|
||||
case .target: return nil
|
||||
case .sdk: return nil
|
||||
case .cocoapods: return nil
|
||||
}
|
||||
}
|
||||
.map(\.parentDirectory)
|
||||
|
||||
references.formUnion(precompiledFramewoksPaths)
|
||||
return references
|
||||
}
|
||||
|
||||
public func hostTargetFor(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
guard let targets = graph.targets[path] else { return nil }
|
||||
guard let project = graph.projects[path] else { return nil }
|
||||
|
||||
return targets.values.compactMap { (target) -> ValueGraphTarget? in
|
||||
let dependencies = self.graph.dependencies[.target(name: target.name, path: path), default: Set()]
|
||||
let dependsOnTarget = dependencies.contains(where: { dependency in
|
||||
guard case let ValueGraphDependency.target(_name, _path) = dependency else { return false }
|
||||
return _name == name && _path == path
|
||||
})
|
||||
let valueGraphTarget = ValueGraphTarget(path: path, target: target, project: project)
|
||||
return dependsOnTarget ? valueGraphTarget : nil
|
||||
}.first
|
||||
}
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
/// The method collects the dependencies that are selected by the provided test closure.
|
||||
/// The skip closure allows skipping the traversing of a specific dependendency branch.
|
||||
/// - Parameters:
|
||||
/// - from: Dependency from which the traverse is done.
|
||||
/// - test: If the closure returns true, the dependency is included.
|
||||
/// - skip: If the closure returns false, the traversing logic doesn't traverse the dependencies from that dependency.
|
||||
public func filterDependencies(from rootDependency: ValueGraphDependency,
|
||||
test: (ValueGraphDependency) -> Bool = { _ in true },
|
||||
skip: (ValueGraphDependency) -> Bool = { _ in false }) -> Set<ValueGraphDependency>
|
||||
func filterDependencies(from rootDependency: ValueGraphDependency,
|
||||
test: (ValueGraphDependency) -> Bool = { _ in true },
|
||||
skip: (ValueGraphDependency) -> Bool = { _ in false }) -> Set<ValueGraphDependency>
|
||||
{
|
||||
var stack = Stack<ValueGraphDependency>()
|
||||
|
||||
|
@ -150,4 +360,144 @@ public class ValueGraphTraverser: GraphTraversing {
|
|||
|
||||
return references
|
||||
}
|
||||
|
||||
func transitiveStaticTargets(from dependency: ValueGraphDependency) -> Set<ValueGraphDependency> {
|
||||
filterDependencies(from: dependency,
|
||||
test: isDependencyStaticTarget,
|
||||
skip: canDependencyLinkStaticProducts)
|
||||
}
|
||||
|
||||
func targetProductReference(target: ValueGraphTarget) -> GraphDependencyReference {
|
||||
.product(target: target.target.name, productName: target.target.productNameWithExtension)
|
||||
}
|
||||
|
||||
func isDependencyPrecompiledLibrary(dependency: ValueGraphDependency) -> Bool {
|
||||
switch dependency {
|
||||
case .xcframework: return true
|
||||
case .framework: return true
|
||||
case .library: return true
|
||||
case .packageProduct: return false
|
||||
case .target: return false
|
||||
case .sdk: return false
|
||||
case .cocoapods: return false
|
||||
}
|
||||
}
|
||||
|
||||
func isDependencyPrecompiledFramework(dependency: ValueGraphDependency) -> Bool {
|
||||
switch dependency {
|
||||
case .xcframework: return true
|
||||
case .framework: return true
|
||||
case .library: return false
|
||||
case .packageProduct: return false
|
||||
case .target: return false
|
||||
case .sdk: return false
|
||||
case .cocoapods: return false
|
||||
}
|
||||
}
|
||||
|
||||
func isDependencyStaticTarget(dependency: ValueGraphDependency) -> Bool {
|
||||
guard case let ValueGraphDependency.target(name, path) = dependency,
|
||||
let target = self.target(path: path, name: name) else { return false }
|
||||
return target.target.product.isStatic
|
||||
}
|
||||
|
||||
func isDependencyDynamicLibrary(dependency: ValueGraphDependency) -> Bool {
|
||||
guard case let ValueGraphDependency.target(name, path) = dependency,
|
||||
let target = self.target(path: path, name: name) else { return false }
|
||||
return target.target.product == .dynamicLibrary
|
||||
}
|
||||
|
||||
func isDependencyFramework(dependency: ValueGraphDependency) -> Bool {
|
||||
guard case let ValueGraphDependency.target(name, path) = dependency,
|
||||
let target = self.target(path: path, name: name) else { return false }
|
||||
return target.target.product == .framework
|
||||
}
|
||||
|
||||
func isDependencyDynamicTarget(dependency: ValueGraphDependency) -> Bool {
|
||||
switch dependency {
|
||||
case .xcframework: return false
|
||||
case .framework: return false
|
||||
case .library: return false
|
||||
case .packageProduct: return false
|
||||
case let .target(name, path):
|
||||
guard let target = self.target(path: path, name: name) else { return false }
|
||||
return target.target.product.isDynamic
|
||||
case .sdk: return false
|
||||
case .cocoapods: return false
|
||||
}
|
||||
}
|
||||
|
||||
func isDependencyPrecompiledDynamicAndLinkable(dependency: ValueGraphDependency) -> Bool {
|
||||
switch dependency {
|
||||
case let .xcframework(_, _, _, linking): return linking == .dynamic
|
||||
case let .framework(_, _, _, _, linking, _, _): return linking == .dynamic
|
||||
case .library: return false
|
||||
case .packageProduct: return false
|
||||
case .target: return false
|
||||
case .sdk: return false
|
||||
case .cocoapods: return false
|
||||
}
|
||||
}
|
||||
|
||||
func canDependencyEmbedProducts(dependency: ValueGraphDependency) -> Bool {
|
||||
guard case let ValueGraphDependency.target(name, path) = dependency,
|
||||
let target = self.target(path: path, name: name) else { return false }
|
||||
return canEmbedProducts(target: target.target)
|
||||
}
|
||||
|
||||
func canDependencyLinkStaticProducts(dependency: ValueGraphDependency) -> Bool {
|
||||
guard case let ValueGraphDependency.target(name, path) = dependency,
|
||||
let target = self.target(path: path, name: name) else { return false }
|
||||
return target.target.canLinkStaticProducts()
|
||||
}
|
||||
|
||||
func hostApplication(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
directTargetDependencies(path: path, name: name)
|
||||
.first(where: { $0.target.product == .app })
|
||||
}
|
||||
|
||||
func canEmbedProducts(target: Target) -> Bool {
|
||||
let validProducts: [Product] = [
|
||||
.app,
|
||||
.unitTests,
|
||||
.uiTests,
|
||||
.watch2Extension,
|
||||
]
|
||||
return validProducts.contains(target.product)
|
||||
}
|
||||
|
||||
func dependencyReference(dependency: ValueGraphDependency) -> GraphDependencyReference? {
|
||||
switch dependency {
|
||||
case .cocoapods:
|
||||
return nil
|
||||
case let .framework(path, binaryPath, dsymPath, bcsymbolmapPaths, linking, architectures, isCarthage):
|
||||
return .framework(path: path,
|
||||
binaryPath: binaryPath,
|
||||
isCarthage: isCarthage,
|
||||
dsymPath: dsymPath,
|
||||
bcsymbolmapPaths: bcsymbolmapPaths,
|
||||
linking: linking,
|
||||
architectures: architectures,
|
||||
product: (linking == .static) ? .staticFramework : .framework)
|
||||
case let .library(path, _, linking, architectures, _):
|
||||
return .library(path: path,
|
||||
linking: linking,
|
||||
architectures: architectures,
|
||||
product: (linking == .static) ? .staticLibrary : .dynamicLibrary)
|
||||
case .packageProduct:
|
||||
return nil
|
||||
case let .sdk(_, path, status, source):
|
||||
return .sdk(path: path,
|
||||
status: status,
|
||||
source: source)
|
||||
case let .target(name, path):
|
||||
guard let target = self.target(path: path, name: name) else { return nil }
|
||||
return .product(target: target.target.name, productName: target.target.productNameWithExtension)
|
||||
case let .xcframework(path, infoPlist, primaryBinaryPath, _):
|
||||
return .xcframework(path: path,
|
||||
infoPlist: infoPlist,
|
||||
primaryBinaryPath: primaryBinaryPath,
|
||||
binaryPath: primaryBinaryPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,8 @@ public extension GraphDependencyReference {
|
|||
path: AbsolutePath = "/frameworks/tuist.xcframework",
|
||||
infoPlist: XCFrameworkInfoPlist = .test(),
|
||||
primaryBinaryPath: AbsolutePath = "/frameworks/tuist.xcframework/ios-arm64/tuist",
|
||||
binaryPath: AbsolutePath = "/frameworks/tuist.xcframework/ios-arm64/tuist"
|
||||
binaryPath: AbsolutePath = "/frameworks/tuist.xcframework/ios-arm64/tuist",
|
||||
linking _: BinaryLinking = .dynamic
|
||||
) -> GraphDependencyReference {
|
||||
GraphDependencyReference.xcframework(path: path,
|
||||
infoPlist: infoPlist,
|
||||
|
@ -36,13 +37,11 @@ public extension GraphDependencyReference {
|
|||
}
|
||||
|
||||
static func testLibrary(path: AbsolutePath = "/libraries/library.a",
|
||||
binaryPath: AbsolutePath = "/libraries/library.a",
|
||||
linking: BinaryLinking = .static,
|
||||
architectures: [BinaryArchitecture] = [BinaryArchitecture.arm64],
|
||||
product: Product = .staticLibrary) -> GraphDependencyReference
|
||||
{
|
||||
GraphDependencyReference.library(path: path,
|
||||
binaryPath: binaryPath,
|
||||
linking: linking,
|
||||
architectures: architectures,
|
||||
product: product)
|
||||
|
|
|
@ -3,13 +3,63 @@ import TSCBasic
|
|||
@testable import TuistCore
|
||||
|
||||
final class MockGraphTraverser: GraphTraversing {
|
||||
var invokedNameGetter = false
|
||||
var invokedNameGetterCount = 0
|
||||
var stubbedName: String! = ""
|
||||
|
||||
var name: String {
|
||||
invokedNameGetter = true
|
||||
invokedNameGetterCount += 1
|
||||
return stubbedName
|
||||
}
|
||||
|
||||
var invokedHasPackagesGetter = false
|
||||
var invokedHasPackagesGetterCount = 0
|
||||
var stubbedHasPackages: Bool! = false
|
||||
|
||||
var hasPackages: Bool {
|
||||
invokedHasPackagesGetter = true
|
||||
invokedHasPackagesGetterCount += 1
|
||||
return stubbedHasPackages
|
||||
}
|
||||
|
||||
var invokedPathGetter = false
|
||||
var invokedPathGetterCount = 0
|
||||
var stubbedPath: AbsolutePath!
|
||||
|
||||
var path: AbsolutePath {
|
||||
invokedPathGetter = true
|
||||
invokedPathGetterCount += 1
|
||||
return stubbedPath
|
||||
}
|
||||
|
||||
var invokedWorkspaceGetter = false
|
||||
var invokedWorkspaceGetterCount = 0
|
||||
var stubbedWorkspace: Workspace!
|
||||
|
||||
var workspace: Workspace {
|
||||
invokedWorkspaceGetter = true
|
||||
invokedWorkspaceGetterCount += 1
|
||||
return stubbedWorkspace
|
||||
}
|
||||
|
||||
var invokedProjectsGetter = false
|
||||
var invokedProjectsGetterCount = 0
|
||||
var stubbedProjects: [AbsolutePath: Project]! = [:]
|
||||
|
||||
var projects: [AbsolutePath: Project] {
|
||||
invokedProjectsGetter = true
|
||||
invokedProjectsGetterCount += 1
|
||||
return stubbedProjects
|
||||
}
|
||||
|
||||
var invokedTarget = false
|
||||
var invokedTargetCount = 0
|
||||
var invokedTargetParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedTargetParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedTargetResult: Target!
|
||||
var stubbedTargetResult: ValueGraphTarget!
|
||||
|
||||
func target(path: AbsolutePath, name: String) -> Target? {
|
||||
func target(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
invokedTarget = true
|
||||
invokedTargetCount += 1
|
||||
invokedTargetParameters = (path, name)
|
||||
|
@ -21,9 +71,9 @@ final class MockGraphTraverser: GraphTraversing {
|
|||
var invokedTargetsCount = 0
|
||||
var invokedTargetsParameters: (path: AbsolutePath, Void)?
|
||||
var invokedTargetsParametersList = [(path: AbsolutePath, Void)]()
|
||||
var stubbedTargetsResult: [Target]! = []
|
||||
var stubbedTargetsResult: Set<ValueGraphTarget>! = []
|
||||
|
||||
func targets(at path: AbsolutePath) -> [Target] {
|
||||
func targets(at path: AbsolutePath) -> Set<ValueGraphTarget> {
|
||||
invokedTargets = true
|
||||
invokedTargetsCount += 1
|
||||
invokedTargetsParameters = (path, ())
|
||||
|
@ -35,9 +85,9 @@ final class MockGraphTraverser: GraphTraversing {
|
|||
var invokedDirectTargetDependenciesCount = 0
|
||||
var invokedDirectTargetDependenciesParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedDirectTargetDependenciesParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedDirectTargetDependenciesResult: [Target]! = []
|
||||
var stubbedDirectTargetDependenciesResult: Set<ValueGraphTarget>! = []
|
||||
|
||||
func directTargetDependencies(path: AbsolutePath, name: String) -> [Target] {
|
||||
func directTargetDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
invokedDirectTargetDependencies = true
|
||||
invokedDirectTargetDependenciesCount += 1
|
||||
invokedDirectTargetDependenciesParameters = (path, name)
|
||||
|
@ -49,9 +99,9 @@ final class MockGraphTraverser: GraphTraversing {
|
|||
var invokedAppExtensionDependenciesCount = 0
|
||||
var invokedAppExtensionDependenciesParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedAppExtensionDependenciesParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedAppExtensionDependenciesResult: [Target]! = []
|
||||
var stubbedAppExtensionDependenciesResult: Set<ValueGraphTarget>! = []
|
||||
|
||||
func appExtensionDependencies(path: AbsolutePath, name: String) -> [Target] {
|
||||
func appExtensionDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
invokedAppExtensionDependencies = true
|
||||
invokedAppExtensionDependenciesCount += 1
|
||||
invokedAppExtensionDependenciesParameters = (path, name)
|
||||
|
@ -63,9 +113,9 @@ final class MockGraphTraverser: GraphTraversing {
|
|||
var invokedResourceBundleDependenciesCount = 0
|
||||
var invokedResourceBundleDependenciesParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedResourceBundleDependenciesParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedResourceBundleDependenciesResult: [Target]! = []
|
||||
var stubbedResourceBundleDependenciesResult: Set<ValueGraphTarget>! = []
|
||||
|
||||
func resourceBundleDependencies(path: AbsolutePath, name: String) -> [Target] {
|
||||
func resourceBundleDependencies(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
invokedResourceBundleDependencies = true
|
||||
invokedResourceBundleDependenciesCount += 1
|
||||
invokedResourceBundleDependenciesParameters = (path, name)
|
||||
|
@ -77,9 +127,9 @@ final class MockGraphTraverser: GraphTraversing {
|
|||
var invokedTestTargetsDependingOnCount = 0
|
||||
var invokedTestTargetsDependingOnParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedTestTargetsDependingOnParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedTestTargetsDependingOnResult: [Target]! = []
|
||||
var stubbedTestTargetsDependingOnResult: Set<ValueGraphTarget>! = []
|
||||
|
||||
func testTargetsDependingOn(path: AbsolutePath, name: String) -> [Target] {
|
||||
func testTargetsDependingOn(path: AbsolutePath, name: String) -> Set<ValueGraphTarget> {
|
||||
invokedTestTargetsDependingOn = true
|
||||
invokedTestTargetsDependingOnCount += 1
|
||||
invokedTestTargetsDependingOnParameters = (path, name)
|
||||
|
@ -91,9 +141,9 @@ final class MockGraphTraverser: GraphTraversing {
|
|||
var invokedDirectStaticDependenciesCount = 0
|
||||
var invokedDirectStaticDependenciesParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedDirectStaticDependenciesParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedDirectStaticDependenciesResult: [GraphDependencyReference]! = []
|
||||
var stubbedDirectStaticDependenciesResult: Set<GraphDependencyReference>! = []
|
||||
|
||||
func directStaticDependencies(path: AbsolutePath, name: String) -> [GraphDependencyReference] {
|
||||
func directStaticDependencies(path: AbsolutePath, name: String) -> Set<GraphDependencyReference> {
|
||||
invokedDirectStaticDependencies = true
|
||||
invokedDirectStaticDependenciesCount += 1
|
||||
invokedDirectStaticDependenciesParameters = (path, name)
|
||||
|
@ -101,7 +151,133 @@ final class MockGraphTraverser: GraphTraversing {
|
|||
return stubbedDirectStaticDependenciesResult
|
||||
}
|
||||
|
||||
func appClipsDependency(path _: AbsolutePath, name _: String) -> Target? {
|
||||
nil
|
||||
var invokedAppClipDependencies = false
|
||||
var invokedAppClipDependenciesCount = 0
|
||||
var invokedAppClipDependenciesParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedAppClipDependenciesParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedAppClipDependenciesResult: ValueGraphTarget!
|
||||
|
||||
func appClipDependencies(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
invokedAppClipDependencies = true
|
||||
invokedAppClipDependenciesCount += 1
|
||||
invokedAppClipDependenciesParameters = (path, name)
|
||||
invokedAppClipDependenciesParametersList.append((path, name))
|
||||
return stubbedAppClipDependenciesResult
|
||||
}
|
||||
|
||||
var invokedEmbeddableFrameworks = false
|
||||
var invokedEmbeddableFrameworksCount = 0
|
||||
var invokedEmbeddableFrameworksParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedEmbeddableFrameworksParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedEmbeddableFrameworksResult: Set<GraphDependencyReference>! = []
|
||||
|
||||
func embeddableFrameworks(path: AbsolutePath, name: String) -> Set<GraphDependencyReference> {
|
||||
invokedEmbeddableFrameworks = true
|
||||
invokedEmbeddableFrameworksCount += 1
|
||||
invokedEmbeddableFrameworksParameters = (path, name)
|
||||
invokedEmbeddableFrameworksParametersList.append((path, name))
|
||||
return stubbedEmbeddableFrameworksResult
|
||||
}
|
||||
|
||||
var invokedLinkableDependencies = false
|
||||
var invokedLinkableDependenciesCount = 0
|
||||
var invokedLinkableDependenciesParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedLinkableDependenciesParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedLinkableDependenciesError: Error?
|
||||
var stubbedLinkableDependenciesResult: Set<GraphDependencyReference>! = []
|
||||
|
||||
func linkableDependencies(path: AbsolutePath, name: String) throws -> Set<GraphDependencyReference> {
|
||||
invokedLinkableDependencies = true
|
||||
invokedLinkableDependenciesCount += 1
|
||||
invokedLinkableDependenciesParameters = (path, name)
|
||||
invokedLinkableDependenciesParametersList.append((path, name))
|
||||
if let error = stubbedLinkableDependenciesError {
|
||||
throw error
|
||||
}
|
||||
return stubbedLinkableDependenciesResult
|
||||
}
|
||||
|
||||
var invokedCopyProductDependencies = false
|
||||
var invokedCopyProductDependenciesCount = 0
|
||||
var invokedCopyProductDependenciesParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedCopyProductDependenciesParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedCopyProductDependenciesResult: Set<GraphDependencyReference>! = []
|
||||
|
||||
func copyProductDependencies(path: AbsolutePath, name: String) -> Set<GraphDependencyReference> {
|
||||
invokedCopyProductDependencies = true
|
||||
invokedCopyProductDependenciesCount += 1
|
||||
invokedCopyProductDependenciesParameters = (path, name)
|
||||
invokedCopyProductDependenciesParametersList.append((path, name))
|
||||
return stubbedCopyProductDependenciesResult
|
||||
}
|
||||
|
||||
var invokedLibrariesPublicHeadersFolders = false
|
||||
var invokedLibrariesPublicHeadersFoldersCount = 0
|
||||
var invokedLibrariesPublicHeadersFoldersParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedLibrariesPublicHeadersFoldersParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedLibrariesPublicHeadersFoldersResult: Set<AbsolutePath>! = []
|
||||
|
||||
func librariesPublicHeadersFolders(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
invokedLibrariesPublicHeadersFolders = true
|
||||
invokedLibrariesPublicHeadersFoldersCount += 1
|
||||
invokedLibrariesPublicHeadersFoldersParameters = (path, name)
|
||||
invokedLibrariesPublicHeadersFoldersParametersList.append((path, name))
|
||||
return stubbedLibrariesPublicHeadersFoldersResult
|
||||
}
|
||||
|
||||
var invokedLibrariesSearchPaths = false
|
||||
var invokedLibrariesSearchPathsCount = 0
|
||||
var invokedLibrariesSearchPathsParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedLibrariesSearchPathsParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedLibrariesSearchPathsResult: Set<AbsolutePath>! = []
|
||||
|
||||
func librariesSearchPaths(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
invokedLibrariesSearchPaths = true
|
||||
invokedLibrariesSearchPathsCount += 1
|
||||
invokedLibrariesSearchPathsParameters = (path, name)
|
||||
invokedLibrariesSearchPathsParametersList.append((path, name))
|
||||
return stubbedLibrariesSearchPathsResult
|
||||
}
|
||||
|
||||
var invokedLibrariesSwiftIncludePaths = false
|
||||
var invokedLibrariesSwiftIncludePathsCount = 0
|
||||
var invokedLibrariesSwiftIncludePathsParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedLibrariesSwiftIncludePathsParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedLibrariesSwiftIncludePathsResult: Set<AbsolutePath>! = []
|
||||
|
||||
func librariesSwiftIncludePaths(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
invokedLibrariesSwiftIncludePaths = true
|
||||
invokedLibrariesSwiftIncludePathsCount += 1
|
||||
invokedLibrariesSwiftIncludePathsParameters = (path, name)
|
||||
invokedLibrariesSwiftIncludePathsParametersList.append((path, name))
|
||||
return stubbedLibrariesSwiftIncludePathsResult
|
||||
}
|
||||
|
||||
var invokedRunPathSearchPaths = false
|
||||
var invokedRunPathSearchPathsCount = 0
|
||||
var invokedRunPathSearchPathsParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedRunPathSearchPathsParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedRunPathSearchPathsResult: Set<AbsolutePath>! = []
|
||||
|
||||
func runPathSearchPaths(path: AbsolutePath, name: String) -> Set<AbsolutePath> {
|
||||
invokedRunPathSearchPaths = true
|
||||
invokedRunPathSearchPathsCount += 1
|
||||
invokedRunPathSearchPathsParameters = (path, name)
|
||||
invokedRunPathSearchPathsParametersList.append((path, name))
|
||||
return stubbedRunPathSearchPathsResult
|
||||
}
|
||||
|
||||
var invokedHostTargetFor = false
|
||||
var invokedHostTargetForCount = 0
|
||||
var invokedHostTargetForParameters: (path: AbsolutePath, name: String)?
|
||||
var invokedHostTargetForParametersList = [(path: AbsolutePath, name: String)]()
|
||||
var stubbedHostTargetForResult: ValueGraphTarget!
|
||||
|
||||
func hostTargetFor(path: AbsolutePath, name: String) -> ValueGraphTarget? {
|
||||
invokedHostTargetFor = true
|
||||
invokedHostTargetForCount += 1
|
||||
invokedHostTargetForParameters = (path, name)
|
||||
invokedHostTargetForParametersList.append((path, name))
|
||||
return stubbedHostTargetForResult
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@ import TuistCore
|
|||
|
||||
public extension ValueGraph {
|
||||
static func test(name: String = "graph",
|
||||
path: AbsolutePath,
|
||||
path: AbsolutePath = .root,
|
||||
workspace: Workspace = .test(),
|
||||
projects: [AbsolutePath: Project] = [:],
|
||||
packages: [AbsolutePath: [String: Package]] = [:],
|
||||
targets: [AbsolutePath: [String: Target]] = [:],
|
||||
|
@ -12,6 +13,7 @@ public extension ValueGraph {
|
|||
{
|
||||
ValueGraph(name: name,
|
||||
path: path,
|
||||
workspace: workspace,
|
||||
projects: projects,
|
||||
packages: packages,
|
||||
targets: targets,
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
import Foundation
|
||||
import TSCBasic
|
||||
|
||||
@testable import TuistCore
|
||||
|
||||
public extension ValueGraphDependency {
|
||||
static func testCocoapods(path: AbsolutePath = .root) -> ValueGraphDependency {
|
||||
ValueGraphDependency.cocoapods(path: path)
|
||||
}
|
||||
|
||||
static func testFramework(path: AbsolutePath = AbsolutePath.root.appending(component: "Test.framework"),
|
||||
binaryPath: AbsolutePath = AbsolutePath.root.appending(RelativePath("Test.framework/Test")),
|
||||
dsymPath: AbsolutePath? = nil,
|
||||
bcsymbolmapPaths: [AbsolutePath] = [],
|
||||
linking: BinaryLinking = .dynamic,
|
||||
architectures: [BinaryArchitecture] = [.armv7],
|
||||
isCarthage: Bool = false) -> ValueGraphDependency
|
||||
{
|
||||
ValueGraphDependency.framework(path: path,
|
||||
binaryPath: binaryPath,
|
||||
dsymPath: dsymPath,
|
||||
bcsymbolmapPaths: bcsymbolmapPaths,
|
||||
linking: linking,
|
||||
architectures: architectures,
|
||||
isCarthage: isCarthage)
|
||||
}
|
||||
|
||||
static func testXCFramework(path: AbsolutePath = AbsolutePath.root.appending(RelativePath("Test.xcframework")),
|
||||
infoPlist: XCFrameworkInfoPlist = .test(),
|
||||
primaryBinaryPath: AbsolutePath = AbsolutePath.root.appending(RelativePath("Test.xcframework/Test")),
|
||||
linking: BinaryLinking = .dynamic) -> ValueGraphDependency
|
||||
{
|
||||
.xcframework(path: path,
|
||||
infoPlist: infoPlist,
|
||||
primaryBinaryPath: primaryBinaryPath,
|
||||
linking: linking)
|
||||
}
|
||||
|
||||
static func testTarget(name: String = "Test",
|
||||
path: AbsolutePath = .root) -> ValueGraphDependency
|
||||
{
|
||||
.target(name: name,
|
||||
path: path)
|
||||
}
|
||||
|
||||
static func testSDK(name: String = "XCTest",
|
||||
path: AbsolutePath = AbsolutePath.root.appending(RelativePath("XCTest.framework")),
|
||||
status: SDKStatus = .required,
|
||||
source: SDKSource = .system) -> ValueGraphDependency
|
||||
{
|
||||
.sdk(name: name,
|
||||
path: path,
|
||||
status: status,
|
||||
source: source)
|
||||
}
|
||||
|
||||
static func testLibrary(path: AbsolutePath = AbsolutePath.root.appending(RelativePath("libTuist.a")),
|
||||
publicHeaders: AbsolutePath = AbsolutePath.root.appending(RelativePath("headers")),
|
||||
linking: BinaryLinking = .dynamic,
|
||||
architectures: [BinaryArchitecture] = [.armv7],
|
||||
swiftModuleMap: AbsolutePath? = nil) -> ValueGraphDependency
|
||||
{
|
||||
.library(path: path,
|
||||
publicHeaders: publicHeaders,
|
||||
linking: linking,
|
||||
architectures: architectures,
|
||||
swiftModuleMap: swiftModuleMap)
|
||||
}
|
||||
|
||||
static func testPackageProduct(path: AbsolutePath = .root,
|
||||
product: String = "Tuist") -> ValueGraphDependency
|
||||
{
|
||||
.packageProduct(path: path,
|
||||
product: product)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
import Foundation
|
||||
import TSCBasic
|
||||
|
||||
@testable import TuistCore
|
||||
|
||||
public extension ValueGraphTarget {
|
||||
static func test(path: AbsolutePath = .root,
|
||||
target: Target = .test(),
|
||||
project: Project = .test()) -> ValueGraphTarget
|
||||
{
|
||||
ValueGraphTarget(path: path,
|
||||
target: target,
|
||||
project: project)
|
||||
}
|
||||
}
|
|
@ -325,8 +325,10 @@ final class BuildPhaseGenerator: BuildPhaseGenerating {
|
|||
pbxproj: PBXProj,
|
||||
resourcesBuildPhase: PBXResourcesBuildPhase)
|
||||
{
|
||||
let bundles = graphTraverser.resourceBundleDependencies(path: path, name: target.name)
|
||||
let refs = bundles.compactMap { fileElements.product(target: $0.name) }
|
||||
let bundles = graphTraverser
|
||||
.resourceBundleDependencies(path: path, name: target.name)
|
||||
.sorted()
|
||||
let refs = bundles.compactMap { fileElements.product(target: $0.target.name) }
|
||||
|
||||
refs.forEach {
|
||||
let pbxBuildFile = PBXBuildFile(file: $0)
|
||||
|
@ -342,14 +344,14 @@ final class BuildPhaseGenerator: BuildPhaseGenerating {
|
|||
fileElements: ProjectFileElements,
|
||||
pbxproj: PBXProj) throws
|
||||
{
|
||||
let appExtensions = graphTraverser.appExtensionDependencies(path: path, name: target.name)
|
||||
let appExtensions = graphTraverser.appExtensionDependencies(path: path, name: target.name).sorted()
|
||||
guard !appExtensions.isEmpty else { return }
|
||||
|
||||
let appExtensionsBuildPhase = PBXCopyFilesBuildPhase(dstSubfolderSpec: .plugins, name: "Embed App Extensions")
|
||||
pbxproj.add(object: appExtensionsBuildPhase)
|
||||
pbxTarget.buildPhases.append(appExtensionsBuildPhase)
|
||||
|
||||
let refs = appExtensions.compactMap { fileElements.product(target: $0.name) }
|
||||
let refs = appExtensions.compactMap { fileElements.product(target: $0.target.name) }
|
||||
|
||||
refs.forEach {
|
||||
let pbxBuildFile = PBXBuildFile(file: $0, settings: ["ATTRIBUTES": ["RemoveHeadersOnCopy"]])
|
||||
|
@ -366,7 +368,7 @@ final class BuildPhaseGenerator: BuildPhaseGenerating {
|
|||
pbxproj: PBXProj) throws
|
||||
{
|
||||
let targetDependencies = graphTraverser.directTargetDependencies(path: path, name: target.name)
|
||||
let watchApps = targetDependencies.filter { $0.product == .watch2App }
|
||||
let watchApps = targetDependencies.filter { $0.target.product == .watch2App }
|
||||
guard !watchApps.isEmpty else { return }
|
||||
|
||||
let embedWatchAppBuildPhase = PBXCopyFilesBuildPhase(dstPath: "$(CONTENTS_FOLDER_PATH)/Watch",
|
||||
|
@ -375,7 +377,7 @@ final class BuildPhaseGenerator: BuildPhaseGenerating {
|
|||
pbxproj.add(object: embedWatchAppBuildPhase)
|
||||
pbxTarget.buildPhases.append(embedWatchAppBuildPhase)
|
||||
|
||||
let refs = watchApps.compactMap { fileElements.product(target: $0.name) }
|
||||
let refs = watchApps.compactMap { fileElements.product(target: $0.target.name) }
|
||||
|
||||
refs.forEach {
|
||||
let pbxBuildFile = PBXBuildFile(file: $0, settings: ["ATTRIBUTES": ["RemoveHeadersOnCopy"]])
|
||||
|
@ -395,7 +397,7 @@ final class BuildPhaseGenerator: BuildPhaseGenerating {
|
|||
return
|
||||
}
|
||||
|
||||
guard let appClips = graphTraverser.appClipsDependency(path: path, name: target.name) else {
|
||||
guard let appClips = graphTraverser.appClipDependencies(path: path, name: target.name) else {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -405,7 +407,7 @@ final class BuildPhaseGenerator: BuildPhaseGenerating {
|
|||
pbxproj.add(object: embedAppClipsBuildPhase)
|
||||
pbxTarget.buildPhases.append(embedAppClipsBuildPhase)
|
||||
|
||||
let refs = fileElements.product(target: appClips.name)
|
||||
let refs = fileElements.product(target: appClips.target.name)
|
||||
|
||||
let pbxBuildFile = PBXBuildFile(file: refs, settings: ["ATTRIBUTES": ["RemoveHeadersOnCopy"]])
|
||||
pbxproj.add(object: pbxBuildFile)
|
||||
|
|
|
@ -225,22 +225,22 @@ final class ConfigGenerator: ConfigGenerating {
|
|||
}
|
||||
|
||||
let targetDependencies = graphTraverser.directTargetDependencies(path: projectPath, name: target.name)
|
||||
let appDependency = targetDependencies.first { $0.product.canHostTests() }
|
||||
let appDependency = targetDependencies.first { $0.target.product.canHostTests() }
|
||||
|
||||
guard let app = appDependency else {
|
||||
return [:]
|
||||
}
|
||||
|
||||
var settings: SettingsDictionary = [:]
|
||||
settings["TEST_TARGET_NAME"] = .string("\(app.name)")
|
||||
settings["TEST_TARGET_NAME"] = .string("\(app.target.name)")
|
||||
if target.product == .unitTests {
|
||||
var testHostPath = "$(BUILT_PRODUCTS_DIR)/\(app.productNameWithExtension)"
|
||||
var testHostPath = "$(BUILT_PRODUCTS_DIR)/\(app.target.productNameWithExtension)"
|
||||
|
||||
if target.platform == .macOS {
|
||||
testHostPath += "/Contents/MacOS"
|
||||
}
|
||||
|
||||
settings["TEST_HOST"] = .string("\(testHostPath)/\(app.productName)")
|
||||
settings["TEST_HOST"] = .string("\(testHostPath)/\(app.target.productName)")
|
||||
settings["BUNDLE_LOADER"] = "$(TEST_HOST)"
|
||||
}
|
||||
|
||||
|
@ -287,12 +287,12 @@ final class ConfigGenerator: ConfigGenerating {
|
|||
}
|
||||
|
||||
let targetDependencies = graphTraverser.directTargetDependencies(path: projectPath, name: target.name)
|
||||
guard let watchExtension = targetDependencies.first(where: { $0.product == .watch2Extension }) else {
|
||||
guard let watchExtension = targetDependencies.first(where: { $0.target.product == .watch2Extension }) else {
|
||||
return [:]
|
||||
}
|
||||
|
||||
return [
|
||||
"IBSC_MODULE": .string(watchExtension.productName),
|
||||
"IBSC_MODULE": .string(watchExtension.target.productName),
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -338,7 +338,7 @@ final class LinkGenerator: LinkGenerating {
|
|||
switch dependency {
|
||||
case let .framework(path, _, _, _, _, _, _, _):
|
||||
try addBuildFile(path)
|
||||
case let .library(path, _, _, _, _):
|
||||
case let .library(path, _, _, _):
|
||||
try addBuildFile(path)
|
||||
case let .xcframework(path, _, _, _):
|
||||
try addBuildFile(path)
|
||||
|
|
|
@ -198,7 +198,7 @@ class ProjectFileElements {
|
|||
try generatePrecompiled(path)
|
||||
case let .framework(path, _, _, _, _, _, _, _):
|
||||
try generatePrecompiled(path)
|
||||
case let .library(path, _, _, _, _):
|
||||
case let .library(path, _, _, _):
|
||||
try generatePrecompiled(path)
|
||||
case let .sdk(sdkNodePath, _, _):
|
||||
generateSDKFileElement(sdkNodePath: sdkNodePath,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,28 @@
|
|||
import Foundation
|
||||
import TSCBasic
|
||||
import XCTest
|
||||
|
||||
@testable import TuistCore
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class ValueGraphDependencyTests: TuistUnitTestCase {
|
||||
func test_isTarget() {
|
||||
XCTAssertFalse(ValueGraphDependency.testXCFramework().isTarget)
|
||||
XCTAssertFalse(ValueGraphDependency.testFramework().isTarget)
|
||||
XCTAssertFalse(ValueGraphDependency.testLibrary().isTarget)
|
||||
XCTAssertFalse(ValueGraphDependency.testPackageProduct().isTarget)
|
||||
XCTAssertTrue(ValueGraphDependency.testTarget().isTarget)
|
||||
XCTAssertFalse(ValueGraphDependency.testSDK().isTarget)
|
||||
XCTAssertFalse(ValueGraphDependency.testCocoapods().isTarget)
|
||||
}
|
||||
|
||||
func test_isPrecompiled() {
|
||||
XCTAssertTrue(ValueGraphDependency.testXCFramework().isPrecompiled)
|
||||
XCTAssertTrue(ValueGraphDependency.testFramework().isPrecompiled)
|
||||
XCTAssertTrue(ValueGraphDependency.testLibrary().isPrecompiled)
|
||||
XCTAssertFalse(ValueGraphDependency.testPackageProduct().isPrecompiled)
|
||||
XCTAssertFalse(ValueGraphDependency.testTarget().isPrecompiled)
|
||||
XCTAssertFalse(ValueGraphDependency.testSDK().isPrecompiled)
|
||||
XCTAssertFalse(ValueGraphDependency.testCocoapods().isPrecompiled)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
import Foundation
|
||||
import TSCBasic
|
||||
import XCTest
|
||||
|
||||
@testable import TuistCore
|
||||
@testable import TuistCoreTesting
|
||||
@testable import TuistSupportTesting
|
||||
|
||||
final class ValueGraphTargetTests: TuistUnitTestCase {
|
||||
func test_comparable() {
|
||||
XCTAssertTrue(ValueGraphTarget.test(target: Target.test(name: "a")) < ValueGraphTarget.test(target: Target.test(name: "b")))
|
||||
XCTAssertFalse(ValueGraphTarget.test(target: Target.test(name: "b")) < ValueGraphTarget.test(target: Target.test(name: "a")))
|
||||
XCTAssertTrue(ValueGraphTarget.test(path: "/a", target: Target.test(name: "a")) < ValueGraphTarget.test(path: "/b", target: Target.test(name: "a")))
|
||||
XCTAssertFalse(ValueGraphTarget.test(path: "/b", target: Target.test(name: "a")) < ValueGraphTarget.test(path: "/a", target: Target.test(name: "a")))
|
||||
}
|
||||
}
|
|
@ -106,32 +106,40 @@ final class ValueGraphTests: TuistUnitTestCase {
|
|||
XCTAssertEqual(valueGraph.dependencies[.target(name: aTarget.name, path: aNode.path)]?
|
||||
.contains(.sdk(name: xctestNode.name, path: xctestNode.path, status: xctestNode.status, source: xctestNode.source)), true)
|
||||
// Then: A -> BFramework
|
||||
XCTAssertEqual(valueGraph.dependencies[.target(name: aTarget.name, path: aNode.path)]?
|
||||
.contains(.framework(path: bFrameworkNode.path,
|
||||
XCTAssertEqual(valueGraph.dependencies[.target(name: aTarget.name, path: aNode.path), default: []]
|
||||
.contains(.framework(path: bFrameworkPath,
|
||||
binaryPath: bFrameworkNode.binaryPath,
|
||||
dsymPath: bFrameworkNode.dsymPath,
|
||||
bcsymbolmapPaths: bFrameworkNode.bcsymbolmapPaths,
|
||||
linking: bFrameworkNode.linking,
|
||||
architectures: bFrameworkNode.architectures)), true)
|
||||
architectures: bFrameworkNode.architectures,
|
||||
isCarthage: bFrameworkNode.isCarthage)), true)
|
||||
// Then: A -> Package
|
||||
XCTAssertEqual(valueGraph.dependencies[.target(name: aTarget.name, path: aNode.path)]?
|
||||
.contains(.packageProduct(path: packageProduct.path, product: packageProduct.product)), true)
|
||||
// Then: BFramework -> AFramework
|
||||
XCTAssertEqual(valueGraph.dependencies[.framework(path: bFrameworkNode.path,
|
||||
binaryPath: bFrameworkNode.binaryPath,
|
||||
dsymPath: bFrameworkNode.dsymPath,
|
||||
bcsymbolmapPaths: bFrameworkNode.bcsymbolmapPaths,
|
||||
linking: bFrameworkNode.linking,
|
||||
architectures: bFrameworkNode.architectures)]?
|
||||
architectures: bFrameworkNode.architectures,
|
||||
isCarthage: bFrameworkNode.isCarthage), default: []]
|
||||
.contains(.framework(path: aFrameworkNode.path,
|
||||
binaryPath: aFrameworkNode.binaryPath,
|
||||
dsymPath: aFrameworkNode.dsymPath,
|
||||
bcsymbolmapPaths: aFrameworkNode.bcsymbolmapPaths,
|
||||
linking: aFrameworkNode.linking,
|
||||
architectures: aFrameworkNode.architectures)), true)
|
||||
architectures: aFrameworkNode.architectures,
|
||||
isCarthage: aFrameworkNode.isCarthage)), true)
|
||||
// then: AFramework
|
||||
XCTAssertNotNil(valueGraph.dependencies[.framework(path: aFrameworkNode.path,
|
||||
binaryPath: aFrameworkNode.binaryPath,
|
||||
dsymPath: aFrameworkNode.dsymPath,
|
||||
bcsymbolmapPaths: aFrameworkNode.bcsymbolmapPaths,
|
||||
linking: aFrameworkNode.linking,
|
||||
architectures: aFrameworkNode.architectures)])
|
||||
architectures: aFrameworkNode.architectures,
|
||||
isCarthage: aFrameworkNode.isCarthage)])
|
||||
|
||||
// Then: XCTest
|
||||
XCTAssertNotNil(valueGraph.dependencies[.sdk(name: xctestNode.name, path: xctestNode.path, status: xctestNode.status, source: xctestNode.source)])
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue