diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d4c66cc..f0ee536 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -7,11 +7,11 @@ on: jobs: build: - runs-on: macos-13 + runs-on: macos-latest steps: - uses: actions/checkout@v3 - name: 🔨 Build run: | - sudo xcode-select -s /Applications/Xcode_14.2.app/ + sudo xcode-select -s /Applications/Xcode_15.4.app/ swift build \ No newline at end of file diff --git a/.swiftlint.yml b/.swiftlint.yml index 5d6a87b..6b98756 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -1,14 +1,25 @@ excluded: - - .build/ - .swiftpm/ - .vscode/ - - PBXProjParser/.build/ # https://github.com/realm/SwiftLint/issues/2329 doesn't support recursive globs yet - - GenIRLogging/.build/ + - "**/.build/*" + - .build/ - TestAssets/ + - PIF/.build/ + - '**/Package.swift' + - Package.swift + - PIF/Sources/pif-parser/pif-parser.swift disabled_rules: - todo + - nesting line_length: warning: 200 ignores_comments: true + +missing_docs: + warning: + - public + +opt_in_rules: + - missing_docs diff --git a/PBXProjParser/Package.resolved b/PBXProjParser/Package.resolved deleted file mode 100644 index 40da984..0000000 --- a/PBXProjParser/Package.resolved +++ /dev/null @@ -1,14 +0,0 @@ -{ - "pins" : [ - { - "identity" : "swift-log", - "kind" : "remoteSourceControl", - "location" : "https://github.com/apple/swift-log.git", - "state" : { - "revision" : "32e8d724467f8fe623624570367e3d50c5638e46", - "version" : "1.5.2" - } - } - ], - "version" : 2 -} diff --git a/PBXProjParser/Package.swift b/PBXProjParser/Package.swift deleted file mode 100644 index 4e57d05..0000000 --- a/PBXProjParser/Package.swift +++ /dev/null @@ -1,38 +0,0 @@ -// swift-tools-version: 5.7 -// The swift-tools-version declares the minimum version of Swift required to build this package. - -import PackageDescription - -let package = Package( - name: "PBXProjParser", - products: [ - // Products define the executables and libraries a package produces, and make them visible to other packages. - .library( - name: "PBXProjParser", - targets: ["PBXProjParser"]) - ], - dependencies: [ - // Dependencies declare other packages that this package depends on. - // .package(url: /* package url */, from: "1.0.0"), - .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0") - ], - targets: [ - // Targets are the basic building blocks of a package. A target can define a module or a test suite. - // Targets can depend on other targets in this package, and on products in packages this package depends on. - .target( - name: "PBXProjParser", - dependencies: [ - .product(name: "Logging", package: "swift-log") - ]), - .testTarget( - name: "PBXProjParserTests", - dependencies: ["PBXProjParser"]), - .executableTarget( - name: "projparser", - dependencies: [ - .product(name: "Logging", package: "swift-log"), - "PBXProjParser" - ] - ) - ] -) diff --git a/PBXProjParser/README.md b/PBXProjParser/README.md deleted file mode 100644 index aea5328..0000000 --- a/PBXProjParser/README.md +++ /dev/null @@ -1,12 +0,0 @@ -# PBXProjParser - -As the name alludes to, this package handles parsing a pbxproj via xcodeproj or xcworkspace folders. - -It also contains some helper functions and structures to wrap an API around a pretty terrible file format, as well as an executable target for testing locally. - -## Note - -A _lot_ of the parsing is hidden behind a compiler flag for a couple reasons: - -- This is a largely undocumented format, and what little documentation is out there is often either slightly wrong or outdated. -- Only a handful of information is required for `Gen IR` so to speed things up/have less decoding issues we don't parse most of the files although the structures exist to do so diff --git a/PBXProjParser/Sources/PBXProjParser/Extensions/DecodingExtensions.swift b/PBXProjParser/Sources/PBXProjParser/Extensions/DecodingExtensions.swift deleted file mode 100644 index a9ed543..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Extensions/DecodingExtensions.swift +++ /dev/null @@ -1,102 +0,0 @@ -// -// DecodingExtensions.swift -// -// -// Created by Thomas Hedderwick on 03/02/2023. -// - -import Foundation - -// https://gist.github.com/mikebuss/17142624da4baf9cdcc337861e256533 - -struct PlistCodingKeys: CodingKey { - var stringValue: String - - init(stringValue: String) { - self.stringValue = stringValue - } - - var intValue: Int? - - init?(intValue: Int) { - self.init(stringValue: "\(intValue)") - self.intValue = intValue - } -} - -extension KeyedDecodingContainer { - func decode(_ type: [String: Any].Type, forKey key: K) throws -> [String: Any] { - let container = try self.nestedContainer(keyedBy: PlistCodingKeys.self, forKey: key) - return try container.decode(type) - } - - func decodeIfPresent(_ type: [String: Any].Type, forKey key: K) throws -> [String: Any]? { - return try? self.nestedContainer(keyedBy: PlistCodingKeys.self, forKey: key).decode(type) - } - - func decode(_ type: [Any].Type, forKey key: K) throws -> [Any] { - var container = try self.nestedUnkeyedContainer(forKey: key) - return try container.decode(type) - } - - func decodeIfPresent(_ type: [Any].Type, forKey key: K) throws -> [Any]? { - guard var container = try? self.nestedUnkeyedContainer(forKey: key) else { - return nil - } - - return try? container.decode(type) - } - - func decode(_ type: [String: Any].Type) throws -> [String: Any] { - var dictionary = [String: Any]() - - for key in allKeys { - if let boolValue = try? decode(Bool.self, forKey: key) { - dictionary[key.stringValue] = boolValue - } else if let stringValue = try? decode(String.self, forKey: key) { - dictionary[key.stringValue] = stringValue - } else if let intValue = try? decode(Int.self, forKey: key) { - dictionary[key.stringValue] = intValue - } else if let doubleValue = try? decode(Double.self, forKey: key) { - dictionary[key.stringValue] = doubleValue - } else if let nestedDictionary = try? decode([String: Any].self, forKey: key) { - dictionary[key.stringValue] = nestedDictionary - } else if let nestedArray = try? decode([Any].self, forKey: key) { - dictionary[key.stringValue] = nestedArray - } - } - return dictionary - } -} - -extension UnkeyedDecodingContainer { - mutating func decode(_ type: [Any].Type) throws -> [Any] { - var array: [Any] = [] - - while isAtEnd == false { - let value: String? = try decode(String?.self) - if value == nil { - continue - } - if let value = try? decode(Bool.self) { - array.append(value) - } else if let value = try? decode(Int.self) { - array.append(value) - } else if let value = try? decode(Double.self) { - array.append(value) - } else if let value = try? decode(String.self) { - array.append(value) - } else if let nestedDictionary = try? decode([String: Any].self) { - array.append(nestedDictionary) - } else if let nestedArray = try? decode([Any].self) { - array.append(nestedArray) - } - } - return array - } - - mutating func decode(_ type: [String: Any].Type) throws -> [String: Any] { - let nestedContainer = try self.nestedContainer(keyedBy: PlistCodingKeys.self) - return try nestedContainer.decode(type) - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXBuildFile.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXBuildFile.swift deleted file mode 100644 index 25bc290..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXBuildFile.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// PBXBuildFile.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class PBXBuildFile: PBXObject { - public let productRef: String? - public let fileRef: String? - - #if FULL_PBX_PARSING - public let platformFilter: String? - public let platformFilters: [String]? - public let settings: [String: Any]? - #endif - - private enum CodingKeys: String, CodingKey { - case productRef - case fileRef - - #if FULL_PBX_PARSING - case platformFilter - case platformFilters - case settings - #endif - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - productRef = try container.decodeIfPresent(String.self, forKey: .productRef) - fileRef = try container.decodeIfPresent(String.self, forKey: .fileRef) - - #if FULL_PBX_PARSING - platformFilter = try container.decodeIfPresent(String.self, forKey: .platformFilter) - platformFilters = try container.decodeIfPresent([String].self, forKey: .platformFilters) - settings = try container.decodeIfPresent([String: Any].self, forKey: .settings) - #endif - - try super.init(from: decoder) - } -} - -public class PBXBuildRule: PBXObject {} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXBuildPhase.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXBuildPhase.swift deleted file mode 100644 index cbc5d70..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXBuildPhase.swift +++ /dev/null @@ -1,99 +0,0 @@ -// -// PBXBuildPhase.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class PBXBuildPhase: PBXObject { - public let files: [String] -#if FULL_PBX_PARSING - public let alwaysOutOfDate: String? - public let buildActionMask: UInt32 - public let runOnlyForDeploymentPostprocessing: Int -#endif - - private enum CodingKeys: String, CodingKey { - case files - #if FULL_PBX_PARSING - case alwaysOutOfDate - case buildActionMask - case runOnlyForDeploymentPostprocessing - #endif - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - #if FULL_PBX_PARSING - alwaysOutOfDate = try container.decodeIfPresent(String.self, forKey: .alwaysOutOfDate) - - let mask = try container.decode(String.self, forKey: .buildActionMask) - buildActionMask = UInt32(mask) ?? 0 - - let flag = try container.decode(String.self, forKey: .runOnlyForDeploymentPostprocessing) - runOnlyForDeploymentPostprocessing = Int(flag) ?? 0 - #endif - - files = try container.decodeIfPresent([String].self, forKey: .files) ?? [] - - try super.init(from: decoder) - } -} - -public class PBXCopyFilesBuildPhase: PBXBuildPhase { -#if FULL_PBX_PARSING - let dstPath: String - let dstSubfolderSpec: String - - private enum CodingKeys: String, CodingKey { - case dstPath - case dstSubfolderSpec - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - dstPath = try container.decode(String.self, forKey: .dstPath) - dstSubfolderSpec = try container.decode(String.self, forKey: .dstSubfolderSpec) - - try super.init(from: decoder) - } -#endif -} - -public class PBXShellScriptBuildPhase: PBXBuildPhase { -#if FULL_PBX_PARSING - let inputPaths: [String]? - let outputPaths: [String]? - let shellPath: String - let shellScript: String - - private enum CodingKeys: String, CodingKey { - case inputPaths - case outputPaths - case shellPath - case shellScript - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - inputPaths = try container.decodeIfPresent([String].self, forKey: .inputPaths) - outputPaths = try container.decodeIfPresent([String].self, forKey: .outputPaths) - shellPath = try container.decode(String.self, forKey: .shellPath) - shellScript = try container.decode(String.self, forKey: .shellScript) - - try super.init(from: decoder) - } -#endif -} - -public class PBXFrameworksBuildPhase: PBXBuildPhase {} -public class PBXHeadersBuildPhase: PBXBuildPhase {} -public class PBXResourcesBuildPhase: PBXBuildPhase {} -public class PBXSourcesBuildPhase: PBXBuildPhase {} -public class PBXAppleScriptBuildPhase: PBXBuildPhase {} -public class PBXRezBuildPhase: PBXBuildPhase {} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXContainerItemProxy.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXContainerItemProxy.swift deleted file mode 100644 index 079eb04..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXContainerItemProxy.swift +++ /dev/null @@ -1,41 +0,0 @@ -// -// PBXContainerItemProxy.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class PBXContainerItemProxy: PBXObject { - #if FULL_PBX_PARSING - public let containerPortal: String - public let proxyType: String - public let remoteInfo: String - #endif - public let remoteGlobalIDString: String - - private enum CodingKeys: String, CodingKey { - #if FULL_PBX_PARSING - case containerPortal - case proxyType - case remoteInfo - #endif - case remoteGlobalIDString - - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - #if FULL_PBX_PARSING - containerPortal = try container.decode(String.self, forKey: .containerPortal) - proxyType = try container.decode(String.self, forKey: .proxyType) - remoteInfo = try container.decode(String.self, forKey: .remoteInfo) - #endif - - remoteGlobalIDString = try container.decode(String.self, forKey: .remoteGlobalIDString) - - try super.init(from: decoder) - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXFileReference.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXFileReference.swift deleted file mode 100644 index 9dea7fd..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXFileReference.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// PBXFileReference.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class PBXFileReference: PBXObject { - #if FULL_PBX_PARSING - public let fileEncoding: String? - public let includeInIndex: String? - public let lastKnownFileType: String? - public let name: String? - public let sourceTree: String - #endif - public let explicitFileType: String? - public let path: String - - private enum CodingKeys: String, CodingKey { - #if FULL_PBX_PARSING - case fileEncoding - case includeInIndex - case lastKnownFileType - case name - case sourceTree - #endif - case explicitFileType - case path - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - explicitFileType = try container.decodeIfPresent(String.self, forKey: .explicitFileType) - path = try container.decode(String.self, forKey: .path) - - #if FULL_PBX_PARSING - fileEncoding = try container.decodeIfPresent(String.self, forKey: .fileEncoding) - includeInIndex = try container.decodeIfPresent(String.self, forKey: .includeInIndex) - lastKnownFileType = try container.decodeIfPresent(String.self, forKey: .lastKnownFileType) - name = try container.decodeIfPresent(String.self, forKey: .name) - sourceTree = try container.decode(String.self, forKey: .sourceTree) - #endif - - try super.init(from: decoder) - } -} - -public class PBXReferenceProxy: PBXObject {} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXGroup.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXGroup.swift deleted file mode 100644 index 14f2f33..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXGroup.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// PBXGroup.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class PBXGroup: PBXObject { -#if FULL_PBX_PARSING - public let children: [String] - public let name: String? - public let sourceTree: String - - private enum CodingKeys: String, CodingKey { - case children - case name - case sourceTree - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - children = try container.decode([String].self, forKey: .children) - name = try container.decodeIfPresent(String.self, forKey: .name) - sourceTree = try container.decode(String.self, forKey: .sourceTree) - - try super.init(from: decoder) - } -#endif -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXObject.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXObject.swift deleted file mode 100644 index 4dbd1f2..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXObject.swift +++ /dev/null @@ -1,110 +0,0 @@ -// -// File.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -/// Base class for all PBX objects -public class PBXObject: Decodable { - /// Objects class name - public let isa: ObjectType - // / The 'UUID-like' reference key found at the start of an object declaration - public var reference: String! - - public enum ObjectType: String, Decodable, CaseIterable { - case buildFile = "PBXBuildFile" - case appleScriptBuildPhase = "PBXAppleScriptBuildPhase" - case copyFilesBuildPhase = "PBXCopyFilesBuildPhase" - case frameworksBuildPhase = "PBXFrameworksBuildPhase" - case headersBuildPhase = "PBXHeadersBuildPhase" - case resourcesBuildPhase = "PBXResourcesBuildPhase" - case shellScriptBuildPhase = "PBXShellScriptBuildPhase" - case sourcesBuildPhase = "PBXSourcesBuildPhase" - case containerItemProxy = "PBXContainerItemProxy" - case fileReference = "PBXFileReference" - case group = "PBXGroup" - case variantGroup = "PBXVariantGroup" - case aggregateTarget = "PBXAggregateTarget" - case legacyTarget = "PBXLegacyTarget" - case nativeTarget = "PBXNativeTarget" - case project = "PBXProject" - case targetDependency = "PBXTargetDependency" - case buildConfiguration = "XCBuildConfiguration" - case configurationList = "XCConfigurationList" - case swiftPackageProductDependency = "XCSwiftPackageProductDependency" - case localSwiftPackageReference = "XCLocalSwiftPackageReference" - case remoteSwiftPackageReference = "XCRemoteSwiftPackageReference" - case referenceProxy = "PBXReferenceProxy" - case versionGroup = "XCVersionGroup" - case buildRule = "PBXBuildRule" - case rezBuildPhase = "PBXRezBuildPhase" - - // swiftlint:disable cyclomatic_complexity - public func getType() -> PBXObject.Type { - switch self { - case .buildFile: return PBXBuildFile.self - case .appleScriptBuildPhase: return PBXAppleScriptBuildPhase.self - case .copyFilesBuildPhase: return PBXCopyFilesBuildPhase.self - case .frameworksBuildPhase: return PBXFrameworksBuildPhase.self - case .headersBuildPhase: return PBXHeadersBuildPhase.self - case .resourcesBuildPhase: return PBXResourcesBuildPhase.self - case .shellScriptBuildPhase: return PBXShellScriptBuildPhase.self - case .sourcesBuildPhase: return PBXSourcesBuildPhase.self - case .containerItemProxy: return PBXContainerItemProxy.self - case .fileReference: return PBXFileReference.self - case .group: return PBXGroup.self - case .variantGroup: return PBXVariantGroup.self - case .aggregateTarget: return PBXAggregateTarget.self - case .legacyTarget: return PBXLegacyTarget.self - case .nativeTarget: return PBXNativeTarget.self - case .project: return PBXProject.self - case .targetDependency: return PBXTargetDependency.self - case .buildConfiguration: return XCBuildConfiguration.self - case .configurationList: return XCConfigurationList.self - case .swiftPackageProductDependency: return XCSwiftPackageProductDependency.self - case .remoteSwiftPackageReference: return XCRemoteSwiftPackageReference.self - case .localSwiftPackageReference: return XCLocalSwiftPackageReference.self - case .referenceProxy: return PBXReferenceProxy.self - case .versionGroup: return XCVersionGroup.self - case .buildRule: return PBXBuildRule.self - case .rezBuildPhase: return PBXRezBuildPhase.self - } - // swiftlint:enable cyclomatic_complexity - } -} - -} - -/// Single case enum that decodes and holds a reference to an underlying `PBXObject` subclass -enum Object: Decodable { - /// The wrapped object - case object(PBXObject) - - private enum CodingKeys: String, CodingKey { - case isa - } - - init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - let isa = try container.decode(PBXObject.ObjectType.self, forKey: .isa) - let singleContainer = try decoder.singleValueContainer() - - self = .object(try singleContainer.decode(isa.getType())) - } - - func unwrap() -> PBXObject { - if case .object(let object) = self { - return object - } - - fatalError( - """ - Failed to unwrap the underlying PBXObject, this should only happen if someone adds a case to `Object` and \ - didn't handle it. - """ - ) - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXProj.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXProj.swift deleted file mode 100644 index 05c4033..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXProj.swift +++ /dev/null @@ -1,111 +0,0 @@ -// -// pbxproj.swift -// -// -// Created by Thomas Hedderwick on 27/01/2023. -// - -import Foundation - -/* - Note: This is based _largely_ on prior art. Thanks to: - http://www.monobjc.net/xcode-project-file-format.html - Cocoapods - - Some of the references here are reverse engineered from the `XCBuild.framework` from Xcode: - /Applications/Xcode.app/Contents/SharedFrameworks/XCBuild.framework/Versions/A/PlugIns/XCBBuildService.bundle/Contents/Frameworks/XCBProjectModel.framework/Versions/A/XCBProjectModel - */ - -// NOTE! Big thanks to http://www.monobjc.net/xcode-project-file-format.html for the file format reference - a lot of the layout here is based on that work - -/// Represents a pbxproj file -public class PBXProj: Decodable { - /// Version of the pbxproj - let archiveVersion: String - /// ??? - let classes: [String: String] - /// Version of the `objects` - let objectVersion: String - /// Mapping of UUID to their corresponding object - let objects: [String: Object] - /// UUID of the root object (probably a PBXProject - let rootObject: String - - enum Error: Swift.Error { - case projectNotFound(String) - } - - /// Decodes a `pbxproj` object from the contents of `path` - /// - Parameter path: path to `project.pbxproj` to parse - /// - Returns: a deserialized pbxproj structure - static func contentsOf(_ path: URL) throws -> PBXProj { - let data: Data - - do { - data = try Data(contentsOf: path) - } catch { - logger.error("Failed to get contents of path: \(path), please check that this path exists and is readable.") - throw error - } - - let decoder = PropertyListDecoder() - - do { - let project = try decoder.decode(Self.self, from: data) - project.fixup() - return project - } catch { - logger.error( - "Failed to decode the pbxproj for path: \(path). Please report this as an error with the pbxproj!" - ) - throw error - } - } - - /// Fixes `Object`s by unwrapping them and assigning the UUID key that represents them to the reference field - private func fixup() { - objects.forEach { (key, object) in - object.unwrap().reference = key - } - } -} - -/// Helper functions for operating on the project structure -public extension PBXProj { - /// Returns the object for a given key as the given type - /// - Parameters: - /// - key: the reference key for the object - /// - type: the type the object should be cast to - /// - Returns: the object, if the reference exists and the type conversion succeeded. Otherwise, nil. - func object(forKey key: String, as type: T.Type = T.self) -> T? { - objects[key]?.unwrap() as? T - } - - /// Returns all the objects of a given type in the project structure - /// - Parameter objectType: the type of objects to find - /// - Parameter type: the type to cast the object to - /// - Returns: an array of all the typed objects found in the project structure - func objects(of objectType: PBXObject.ObjectType, as type: T.Type) -> [T] { - objects - .map { $1.unwrap() } - .filter { $0.isa == objectType } - .compactMap { $0 as? T } - } - - func project() throws -> PBXProject { - guard let project: PBXProject = object(forKey: rootObject) else { - throw Error.projectNotFound( - "The root object of the pbxproj doesn't exist, or isn't castable to PBXProject... this shouldn't happen" - ) - } - - return project - } - - /// Returns a list of objects for a given list of references - /// - Parameter references: a list of references to lookup - /// - Returns: a list of objects that matches a reference in the references list - func objects(for references: [String]) -> [T] { - references.compactMap { object(forKey: $0) } - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXProject.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXProject.swift deleted file mode 100644 index 45c50ca..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXProject.swift +++ /dev/null @@ -1,64 +0,0 @@ -// -// PBXProject.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class PBXProject: PBXObject { - #if FULL_PBX_PARSING - public let attributes: [String: Any] - public let buildConfigurationList: String - public let compatibilityVersion: String - public let developmentRegion: String - public let hasScannedForEncodings: String - public let knownRegions: [String] - public let mainGroup: String - public let productRefGroup: String - public let projectDirPath: String - public let projectReferences: [[String: String]]? - public let projectRoot: String - #endif - public let packageReferences: [String] - public let targets: [String] /// Hold references to targets via their identifiers - - private enum CodingKeys: String, CodingKey { - case attributes - case buildConfigurationList - case compatibilityVersion - case developmentRegion - case hasScannedForEncodings - case knownRegions - case mainGroup - case productRefGroup - case projectDirPath - case projectReferences - case packageReferences - case projectRoot - case targets - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) -#if FULL_PBX_PARSING - // We currently don't decode this as it's painful and we don't need it - attributes = [:] - buildConfigurationList = try container.decode(String.self, forKey: .buildConfigurationList) - compatibilityVersion = try container.decode(String.self, forKey: .compatibilityVersion) - developmentRegion = try container.decode(String.self, forKey: .developmentRegion) - hasScannedForEncodings = try container.decode(String.self, forKey: .hasScannedForEncodings) - knownRegions = try container.decode([String].self, forKey: .knownRegions) - mainGroup = try container.decode(String.self, forKey: .mainGroup) - productRefGroup = try container.decode(String.self, forKey: .productRefGroup) - projectDirPath = try container.decode(String.self, forKey: .projectDirPath) - projectReferences = try container.decodeIfPresent([[String: String]].self, forKey: .projectReferences) - projectRoot = try container.decode(String.self, forKey: .projectRoot) -#endif - packageReferences = try container.decodeIfPresent([String].self, forKey: .packageReferences) ?? [] - targets = try container.decode([String].self, forKey: .targets) - - try super.init(from: decoder) - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXTarget.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXTarget.swift deleted file mode 100644 index 26b458c..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXTarget.swift +++ /dev/null @@ -1,170 +0,0 @@ -// -// PBXTarget.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class PBXTarget: PBXObject { - #if FULL_PBX_PARSING - public let buildConfigurationList: String - public let comments: String? - #endif - public let productName: String? - public let name: String - public let dependencies: [String] - - private enum CodingKeys: String, CodingKey { - #if FULL_PBX_PARSING - case buildConfigurationList - case comments - #endif - case productName - case name - case dependencies - - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - #if FULL_PBX_PARSING - buildConfigurationList = try container.decode(String.self, forKey: .buildConfigurationList) - comments = try container.decodeIfPresent(String.self, forKey: .comments) - #endif - productName = try container.decodeIfPresent(String.self, forKey: .productName) - name = try container.decode(String.self, forKey: .name) - dependencies = try container.decode([String].self, forKey: .dependencies) - - try super.init(from: decoder) - } -} - -public class PBXAggregateTarget: PBXTarget { - public let buildPhases: [String] - - private enum CodingKeys: String, CodingKey { - case buildPhases - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - buildPhases = try container.decode([String].self, forKey: .buildPhases) - - try super.init(from: decoder) - } -} - -public class PBXLegacyTarget: PBXTarget {} - -public class PBXNativeTarget: PBXTarget { - #if FULL_PBX_PARSING - public let productInstallPath: String? - #endif - public let buildPhases: [String] - public let productType: String? - public let productReference: String? - public let packageProductDependencies: [String] - - private(set) var targetDependencies: [String: TargetDependency] = [:] - - public enum TargetDependency { - case native(PBXNativeTarget) - case package(XCSwiftPackageProductDependency) - case externalProjectFramework(String) - - public var name: String { - switch self { - case .native(let target): - return target.name - case .package(let package): - return package.productName - case .externalProjectFramework(let filename): - return (filename as NSString).deletingPathExtension - } - } - } - - private enum CodingKeys: String, CodingKey { - #if FULL_PBX_PARSING - case productInstallPath - #endif - case buildPhases - case productType - case productReference - case packageProductDependencies - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - #if FULL_PBX_PARSING - productInstallPath = try container.decodeIfPresent(String.self, forKey: .productInstallPath) - #endif - buildPhases = try container.decodeIfPresent([String].self, forKey: .buildPhases) ?? [] - productType = try container.decodeIfPresent(String.self, forKey: .productType) - productReference = try container.decodeIfPresent(String.self, forKey: .productReference) - packageProductDependencies = try container.decodeIfPresent([String].self, forKey: .packageProductDependencies) ?? [] - - try super.init(from: decoder) - } - - func add(dependency: TargetDependency) { - targetDependencies[dependency.name] = dependency - } -} - -extension PBXNativeTarget: Hashable { - public func hash(into hasher: inout Hasher) { - hasher.combine(isa) - hasher.combine(reference) - hasher.combine(productName) - hasher.combine(name) - } -} - -extension PBXNativeTarget: Equatable { - public static func == (lhs: PBXNativeTarget, rhs: PBXNativeTarget) -> Bool { - // This should be enough as references _should_ be unique to the object - lhs.reference == rhs.reference - } -} - -extension PBXNativeTarget: CustomStringConvertible { - public var description: String { - #if FULL_PBX_PARSING - """ - - """ - #else - """ - - """ - #endif - } -} - -public class PBXTargetDependency: PBXObject { - public let target: String? - public let targetProxy: String? - - private enum CodingKeys: String, CodingKey { - case target - case targetProxy - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - target = try container.decodeIfPresent(String.self, forKey: .target) - targetProxy = try container.decodeIfPresent(String.self, forKey: .targetProxy) - - try super.init(from: decoder) - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/PBXVariantGroup.swift b/PBXProjParser/Sources/PBXProjParser/Models/PBXVariantGroup.swift deleted file mode 100644 index d086ea1..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/PBXVariantGroup.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// PBXVariantGroup.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class PBXVariantGroup: PBXObject { - #if FULL_PBX_PARSING - public let children: [String] - public let name: String - public let sourceTree: String - - private enum CodingKeys: String, CodingKey { - case children - case name - case sourceTree - } - #endif - - required init(from decoder: Decoder) throws { - #if FULL_PBX_PARSING - let container = try decoder.container(keyedBy: CodingKeys.self) - - children = try container.decode([String].self, forKey: .children) - name = try container.decode(String.self, forKey: .name) - sourceTree = try container.decode(String.self, forKey: .sourceTree) - #endif - - try super.init(from: decoder) - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/XCBuildConfiguration.swift b/PBXProjParser/Sources/PBXProjParser/Models/XCBuildConfiguration.swift deleted file mode 100644 index b93d554..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/XCBuildConfiguration.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// XCBuildConfiguration.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class XCBuildConfiguration: PBXObject { - #if FULL_PBX_PARSING - public var baseConfigurationReference: String? - public var buildSettings: [String: Any] - public var name: String - - private enum CodingKeys: String, CodingKey { - case baseConfigurationReference - case buildSettings - case name - } - #endif - - required init(from decoder: Decoder) throws { - #if FULL_PBX_PARSING - let container = try decoder.container(keyedBy: CodingKeys.self) - - baseConfigurationReference = try container.decodeIfPresent(String.self, forKey: .baseConfigurationReference) - buildSettings = try container.decode([String: Any].self, forKey: .buildSettings) - name = try container.decode(String.self, forKey: .name) - #endif - - try super.init(from: decoder) - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/XCConfigurationList.swift b/PBXProjParser/Sources/PBXProjParser/Models/XCConfigurationList.swift deleted file mode 100644 index 4e12a1f..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/XCConfigurationList.swift +++ /dev/null @@ -1,34 +0,0 @@ -// -// XCConfigurationList.swift -// -// -// Created by Thomas Hedderwick on 31/01/2023. -// - -import Foundation - -public class XCConfigurationList: PBXObject { - #if FULL_PBX_PARSING - public let buildConfigurations: [String] - public let defaultConfigurationIsVisible: String - public let defaultConfigurationName: String - - private enum CodingKeys: String, CodingKey { - case buildConfigurations - case defaultConfigurationIsVisible - case defaultConfigurationName - } - #endif - - required init(from decoder: Decoder) throws { - #if FULL_PBX_PARSING - let container = try decoder.container(keyedBy: CodingKeys.self) - - buildConfigurations = try container.decode([String].self, forKey: .buildConfigurations) - defaultConfigurationIsVisible = try container.decode(String.self, forKey: .defaultConfigurationIsVisible) - defaultConfigurationName = try container.decode(String.self, forKey: .defaultConfigurationName) - #endif - - try super.init(from: decoder) - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Models/XCSwiftPackageProductDependency.swift b/PBXProjParser/Sources/PBXProjParser/Models/XCSwiftPackageProductDependency.swift deleted file mode 100644 index 9274529..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Models/XCSwiftPackageProductDependency.swift +++ /dev/null @@ -1,48 +0,0 @@ -// -// XCSwiftPackageProductDependency.swift -// -// -// Created by Thomas Hedderwick on 15/02/2023. -// - -import Foundation - -public class XCSwiftPackageProductDependency: PBXObject { - public let package: String? - public let productName: String - - private enum CodingKeys: CodingKey { - case package - case productName - } - - required init(from decoder: Decoder) throws { - let container = try decoder.container(keyedBy: CodingKeys.self) - - package = try container.decodeIfPresent(String.self, forKey: .package) - productName = try container.decode(String.self, forKey: .productName) - - try super.init(from: decoder) - } -} - -extension XCSwiftPackageProductDependency: Hashable { - public func hash(into hasher: inout Hasher) { - hasher.combine(isa) - hasher.combine(reference) - hasher.combine(package) - hasher.combine(productName) - } -} - -extension XCSwiftPackageProductDependency: Equatable { - public static func == (lhs: XCSwiftPackageProductDependency, rhs: XCSwiftPackageProductDependency) -> Bool { - lhs.reference == rhs.reference && - lhs.package == rhs.package && - lhs.productName == rhs.productName - } -} - -public class XCRemoteSwiftPackageReference: PBXObject {} -public class XCLocalSwiftPackageReference: PBXObject {} -public class XCVersionGroup: PBXObject {} diff --git a/PBXProjParser/Sources/PBXProjParser/ProjectParser.swift b/PBXProjParser/Sources/PBXProjParser/ProjectParser.swift deleted file mode 100644 index 8e4fbc6..0000000 --- a/PBXProjParser/Sources/PBXProjParser/ProjectParser.swift +++ /dev/null @@ -1,121 +0,0 @@ -import Foundation -import Logging - -var logger: Logger = .init(label: "com.veracode.PBXProjParser") - -/// An Xcode project parser (note: not an Xcode Project parser!) -public struct ProjectParser { - /// Path to the xcodeproj or xcworkspace bundle - let path: URL - - /// The type of project - let type: ProjectType - - /// All the native targets for the project - public var targets: [PBXNativeTarget] { - switch type { - case .project(let project): - return project.targets - case .workspace(let workspace): - return workspace.targets - } - } - - /// All the packages for the project - public var packages: [XCSwiftPackageProductDependency] { - switch type { - case .project(let project): - return project.packages - case .workspace(let workspace): - return workspace.packages - } - } - - /// Type of project this parser is working on - enum ProjectType { - /// A single Xcode Project - case project(XcodeProject) - /// An Xcode Workspace, which is a collection of Xcode Projects with some metadata - case workspace(XcodeWorkspace) - } - - public enum Error: Swift.Error { - case invalidPath(String) - } - - public init(path: URL, logLevel level: Logger.Level) throws { - self.path = path - logger.logLevel = level - - switch path.pathExtension { - case "xcodeproj": - let project = try XcodeProject(path: path) - type = .project(project) - case "xcworkspace": - let workspace = try XcodeWorkspace(path: path) - type = .workspace(workspace) - default: - throw Error.invalidPath("Path should be a xcodeproj or xcworkspace, got: \(path.lastPathComponent)") - } - } - - /// Returns a list of dependencies for a given target - /// - Parameter target: the target to get dependencies for - /// - Returns: an array of dependency references - public func dependencies(for target: String) -> [String] { - guard let project = project(for: target) else { - logger.error("Couldn't find project for target: \(target)") - return [] - } - - guard let target = project.target(for: target) else { - // SPMs don't list their dependencies in the pbxproj, skip warning about them - if project.package(for: target) == nil { - // TODO: once SPM dependencies work better, move this back to error level warning - logger.debug( - """ - Failed to find a target: \(target) in project: \(project.path). \ - Possible targets: \(project.targets.map { ($0.name, $0.productName ?? "nil")}). \ - Possible Packages: \(project.packages.map { $0.productName}) - """ - ) - } - - return [] - } - - return target.targetDependencies - .values - .map { dependency in - switch dependency { - case .native(let target): - if let path = project.path(for: target) { - return path - } - - fallthrough - default: - return dependency.name - } - } - } - - /// Gets a project for a given target - /// - Parameter target: the target to search for - /// - Returns: a `XcodeProject` that holds the target, if one was found - private func project(for target: String) -> XcodeProject? { - switch type { - case .project(let project): - return project - case .workspace(let workspace): - return workspace.targetsToProject[target] - } - } - - /// Gets the project model for a given target - /// - Parameter target: the target to search for - /// - Returns: a `PBXProj` that represents the pbxproj this target is a part of, if one was found - public func model(for target: String) -> PBXProj? { - project(for: target)?.model - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Workspace/Reference.swift b/PBXProjParser/Sources/PBXProjParser/Workspace/Reference.swift deleted file mode 100644 index a205cdf..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Workspace/Reference.swift +++ /dev/null @@ -1,86 +0,0 @@ -// -// Reference.swift -// -// -// Created by Thomas Hedderwick on 18/10/2023. -// -import Foundation - -protocol Reference { - var location: Location { get } - static var elementName: String { get } -} - -enum Location { - // TODO: Find where we can get a definitive list of these. Xcode must have them somewhere? - case container(String) - case group(String) - - enum Error: Swift.Error { - case invalidLocation(String) - } - - init(_ location: String) throws { - let split = location - .split(separator: ":", maxSplits: 1, omittingEmptySubsequences: false) - .map(String.init) - - guard - let key = split.first, - let value = split.last - else { throw Error.invalidLocation("Couldn't extract key/value pair from split: \(split)") } - - switch key { - case "container": self = .container(value) - case "group": self = .group(value) - default: throw Error.invalidLocation("Key didn't match a supported location key: \(key)") - } - } - - var path: String { - switch self { - case .container(let path): return path - case .group(let path): return path - } - } -} - -class Group: Reference { - static let elementName: String = "Group" - - let location: Location - let name: String? - var references: [Reference] = [] - - init(location: String, name: String?) throws { - self.location = try .init(location) - self.name = name - } -} - -struct FileRef: Reference { - static let elementName: String = "FileRef" - - let location: Location - let enclosingGroup: Group? - - init(location: String, enclosingGroup: Group? = nil) throws { - self.location = try .init(location) - self.enclosingGroup = enclosingGroup - } - - var path: String { - guard - let enclosingGroup - else { return location.path } - - switch enclosingGroup.location { - case let .group(path), let .container(path): - if path.last == "/" { - return path + location.path - } - - return path + "/" + location.path - } - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/Workspace/WorkspaceParser.swift b/PBXProjParser/Sources/PBXProjParser/Workspace/WorkspaceParser.swift deleted file mode 100644 index 4bca3fe..0000000 --- a/PBXProjParser/Sources/PBXProjParser/Workspace/WorkspaceParser.swift +++ /dev/null @@ -1,88 +0,0 @@ -// -// WorkspaceParser.swift -// -// -// Created by Thomas Hedderwick on 18/10/2023. -// - -import Foundation - -struct Workspace { - private(set) var fileReferences: [FileRef] = [] - private(set) var groupReferences: [Group] = [] -} - -struct WorkspaceParser { - static func parse(_ path: URL) throws -> Workspace { - // Parse the `contents.xcworkspacedata` (XML) file and get the list of projects - let contentsPath = path.appendingPathComponent("contents.xcworkspacedata") - - let data = try Data(contentsOf: contentsPath) - let delegate = WorkspaceDataParserDelegate() - let parser = XMLParser(data: data) - parser.delegate = delegate - parser.parse() - - return .init( - fileReferences: delegate.fileReferences, - groupReferences: delegate.groupReferences - ) - } -} - -private class WorkspaceDataParserDelegate: NSObject, XMLParserDelegate { - private(set) var fileReferences: [FileRef] = [] - private(set) var groupReferences: [Group] = [] - - static let supportedElements = [Group.elementName, FileRef.elementName] - - private var groupPath: [Group] = [] - - func parser( - _ parser: XMLParser, - didStartElement elementName: String, - namespaceURI: String?, - qualifiedName qName: String?, - attributes attributeDict: [String: String] = [:] - ) { - guard Self.supportedElements.contains(elementName) else { - logger.debug("Skipping parsing of unsupported element: \(elementName)") - return - } - - guard - let location = attributeDict["location"] - else { - logger.debug("Location attribute for element \(elementName) is nil, this shouldn't be the case: \(attributeDict)") - return - } - - do { - switch elementName { - case Group.elementName: - let group = try Group(location: location, name: attributeDict["name"]) - groupPath.append(group) - groupReferences.append(group) - case FileRef.elementName: - let file = try FileRef(location: location, enclosingGroup: groupPath.last) - fileReferences.append(file) - groupPath.last?.references.append(file) - // Ignore any element that doesn't match the search space - default: - break - } - } catch { - logger.debug("Parsing element: \(elementName) failed. Reason: \(error)") - } - } - - func parser( - _ parser: XMLParser, - didEndElement elementName: String, - namespaceURI: String?, - qualifiedName qName: String? - ) { - guard elementName == Group.elementName else { return } - groupPath.removeLast() - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/XcodeProject.swift b/PBXProjParser/Sources/PBXProjParser/XcodeProject.swift deleted file mode 100644 index 90e9a77..0000000 --- a/PBXProjParser/Sources/PBXProjParser/XcodeProject.swift +++ /dev/null @@ -1,231 +0,0 @@ -// -// XcodeProject.swift -// -// -// Created by Thomas Hedderwick on 27/01/2023. -// - -import Foundation - -/// Represents an xcodeproj bundle -public struct XcodeProject { - /// Path to the Workspace - public let path: URL - - /// The underlying pbxproj model - public let model: PBXProj - - /// The 'project' object for the pbxproj - let project: PBXProject - - /// All the native targets in this project - let targets: [PBXNativeTarget] - - /// All the swift packages in this project - let packages: [XCSwiftPackageProductDependency] - - enum Error: Swift.Error { - case invalidPBXProj(String) - } - - public init(path: URL) throws { - self.path = path - model = try PBXProj.contentsOf(path.appendingPathComponent("project.pbxproj")) - project = try model.project() - - targets = model.objects(for: project.targets) - .filter { - // Cocoapods likes to insert resource bundles as native targets. On iOS resource bundles - // cannot contain executables, therefore we should ignore them - IR will never be generated for them. - $0.productType != "com.apple.product-type.bundle" - } - - packages = model.objects(of: .swiftPackageProductDependency, as: XCSwiftPackageProductDependency.self) - - // get all the direct dependencies - targets.forEach { determineDirectDependencies($0) } - - targets.forEach { target in - logger.debug("target: \(target.name). Dependencies: \(target.targetDependencies.map { $0.1.name })") - } - - packages.forEach { package in - logger.debug("package: \(package.productName)") - } - } - - /// Gets the native target for a given name - /// - Parameter name: the target name or product name to lookup - /// - Returns: the native target corresponding to the name provided - func target(for name: String) -> PBXNativeTarget? { - if let target = targets.filter({ $0.name == name }).first { - return target - } else if let target = targets.filter({ $0.productName == name }).first { - return target - } - - return nil - } - - /// Gets the package dependency object for a given name - /// - Parameter name: the product name to lookup - /// - Returns: the swift package product dependency object corresponding to the name provided - func package(for key: String) -> XCSwiftPackageProductDependency? { - packages.filter({ $0.productName == key }).first - } - - /// Determines the target & swift package dependencies for a target - /// - Parameter target: the target to get direct dependencies for - private func determineDirectDependencies(_ target: PBXNativeTarget) { - // Calculate the native target dependencies - target.dependencies - .compactMap { model.object(forKey: $0, as: PBXTargetDependency.self) } - .compactMap { dependency in - if let target = dependency.target { - return target - } - - guard - let targetProxy = dependency.targetProxy, - let proxy = model.object(forKey: targetProxy, as: PBXContainerItemProxy.self) - else { - return nil - } - - return proxy.remoteGlobalIDString - } - .compactMap { model.object(forKey: $0, as: PBXNativeTarget.self) } - .forEach { target.add(dependency: .native($0)) } - - // Calculate the swift package dependencies - target.packageProductDependencies - .compactMap { model.object(forKey: $0, as: XCSwiftPackageProductDependency.self) } - .forEach { target.add(dependency: .package($0)) } - - // Calculate dependencies from "Embed Frameworks" copy files build phase - let embeddedFrameworks = determineEmbeddedFrameworksDependencies(target, with: model) - - // Calculate the dependencies from "Link Binary with Library" build phase - let linkLibraries = determineBuildPhaseFrameworkDependencies(target, with: model) - - let buildFiles = embeddedFrameworks + linkLibraries - - // Now, we have two potential targets - file & package dependencies. - // File dependencies will likely have a reference in another Xcode Project. We might not have seen said project yet, so we need to offload discovery until after we've parsed all projects... - // Package dependencies will be a swift package - those we can handle easily :) - - // ONE: package dependencies - they are the easiest - buildFiles - .compactMap { $0.productRef } - .compactMap { model.object(forKey: $0, as: XCSwiftPackageProductDependency.self) } - .forEach { target.add(dependency: .package($0)) } - - // TWO: Resolve dependencies to... a thing that refers to something in the other project - let fileReferences = buildFiles - .compactMap { $0.fileRef } - .compactMap { model.object(forKey: $0, as: PBXFileReference.self) } - - fileReferences - .filter { $0.explicitFileType == "wrapper.framework" } - .compactMap { $0.path } // TODO: do we want to last path component the path here? Need to figure out matching... - .filter { !$0.contains("System/Library/Frameworks/")} // System frameworks will contain this path - .forEach { target.add(dependency: .externalProjectFramework($0)) } - } - - /// Determines transitive dependencies by looping through direct dependencies and finding the items they depend on - /// - Parameter target: the target to find transitive dependencies for - private func determineTransitiveDependencies(_ target: PBXNativeTarget) { - logger.debug("Target: \(target.name). Deps: \(target.targetDependencies.map { $0.0 })") - - var targetDependencies = target.targetDependencies.map { $0.1 } - var seen = Set() - var count = 50 // recursion guard - - while !targetDependencies.isEmpty, count != 0 { - let dependency = targetDependencies.removeFirst() - count -= 1 - - if seen.contains(dependency.name) { - continue - } - - seen.insert(dependency.name) - - switch dependency { - case .native(let nativeTarget): - logger.debug("Adding native dependency: \(dependency.name), deps: \(nativeTarget.targetDependencies.map { $0.0 })") - targetDependencies.append(contentsOf: nativeTarget.targetDependencies.map { $0.1 }) - nativeTarget.targetDependencies.forEach { target.add(dependency: $0.1) } - case .package: - // Packages don't have a transitive dependency field like native targets do, so we can't find dependency of a dependency from the project file - logger.debug("Adding package dependency: \(dependency.name)") - target.add(dependency: dependency) - case .externalProjectFramework: - // Can't move IR dependencies for prebuilt frameworks - continue - } - } - - logger.debug("--- FINAL ---") - logger.debug("Target: \(target.name), deps: \(target.targetDependencies.map { $0.0 })") - } - - /// Gets the 'path' (normally the name of the target's product) for a given target - /// - Parameters: - /// - target: the target to get the path for - /// - removeExtension: should the file extension be removed from the returned path - /// - Returns: the path, if one was found - func path(for target: PBXNativeTarget, removeExtension: Bool = false) -> String? { - guard let productReference = target.productReference else { - logger.debug("Failed to get product reference for target: \(target). Possibly a SPM Package description?") - return nil - } - - guard let reference = model.object(forKey: productReference, as: PBXFileReference.self) else { - logger.error("Failed to get object for target productReference: \(productReference)") - return nil - } - - var path = ((reference.path as NSString).lastPathComponent as String) - - if removeExtension, let index = path.firstIndex(of: ".") { - path = String(path[path.startIndex.. [PBXBuildFile] { - // Find the 'Link Binary with Libraries' build phase - let buildPhase = target.buildPhases - .compactMap { model.object(forKey: $0, as: PBXFrameworksBuildPhase.self) } - .first - - guard let buildPhase else { - logger.debug("No PBXFrameworkBuild phase for target: \(target) found, continuing.") - return [] - } - - return buildPhase - .files - .compactMap { model.object(forKey: $0, as: PBXBuildFile.self) } -} - -private func determineEmbeddedFrameworksDependencies(_ target: PBXNativeTarget, with model: PBXProj) -> [PBXBuildFile] { - // Find the "Embed Frameworks" build phase (copy files build phase) - let buildPhases = target - .buildPhases - .compactMap { model.object(forKey: $0, as: PBXCopyFilesBuildPhase.self) } - - return buildPhases - .flatMap { $0.files } - .compactMap { model.object(forKey: $0, as: PBXBuildFile.self) } - .filter { file in - guard let ref = file.fileRef else { return false } - guard let object = model.object(forKey: ref, as: PBXFileReference.self) else { return false } - guard object.explicitFileType == "wrapper.framework" else { return false } - - return true - } -} diff --git a/PBXProjParser/Sources/PBXProjParser/XcodeWorkspace.swift b/PBXProjParser/Sources/PBXProjParser/XcodeWorkspace.swift deleted file mode 100644 index 608dfea..0000000 --- a/PBXProjParser/Sources/PBXProjParser/XcodeWorkspace.swift +++ /dev/null @@ -1,61 +0,0 @@ -// -// XcodeWorkspace.swift -// -// -// Created by Thomas Hedderwick on 27/01/2023. -// - -import Foundation - -/// Represents an xcworkspace - which is a set of xcodeproj bundles -class XcodeWorkspace { - /// Path to the Workspace - let path: URL - /// Path to the various underlying xcodeproj bundles - private(set) var projectPaths: [URL] - /// List of projects this workspace references - let projects: [XcodeProject] - - /// A mapping of targets to the projects that define them - let targetsToProject: [String: XcodeProject] - - init(path: URL) throws { - self.path = path - - // Parse the `contents.xcworkspacedata` (XML) file and get the list of projects - let workspace = try WorkspaceParser.parse(path) - let paths = workspace - .fileReferences - .map { $0.path } - .filter { $0.hasSuffix("xcodeproj") } - - let baseFolder = path.deletingLastPathComponent() - projectPaths = paths - .map { baseFolder.appendingPathComponent($0, isDirectory: true) } - - projects = try projectPaths.map(XcodeProject.init(path:)) - - targetsToProject = projects.reduce(into: [String: XcodeProject](), { partialResult, project in - project.targets.forEach { (target) in - partialResult[target.name] = project - if let productName = target.productName, productName != target.name { - partialResult[productName] = project - } - } - - project.packages.forEach { (target) in - partialResult[target.productName] = project - } - }) - } - - /// All native targets in the workspace - var targets: [PBXNativeTarget] { - projects.flatMap { $0.targets } - } - - /// All packages in the workspace - var packages: [XCSwiftPackageProductDependency] { - projects.flatMap { $0.packages } - } -} diff --git a/PBXProjParser/Sources/projparser/projparser.swift b/PBXProjParser/Sources/projparser/projparser.swift deleted file mode 100644 index ff2cb85..0000000 --- a/PBXProjParser/Sources/projparser/projparser.swift +++ /dev/null @@ -1,22 +0,0 @@ -// -// projparser.swift -// -// -// Created by Thomas Hedderwick on 24/02/2023. -// - -import Foundation -import PBXProjParser - -@main -struct ProjParser { - static func main() throws { - guard CommandLine.arguments.count == 2 else { - print("USAGE: \(CommandLine.arguments.first!) [project path]") - return - } - - let projectPath = URL(fileURLWithPath: CommandLine.arguments[1]) - _ = try ProjectParser(path: projectPath, logLevel: .debug) - } -} diff --git a/PBXProjParser/Tests/PBXProjParserTests/PBXProjParserTests.swift b/PBXProjParser/Tests/PBXProjParserTests/PBXProjParserTests.swift deleted file mode 100644 index 3d9d527..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/PBXProjParserTests.swift +++ /dev/null @@ -1,47 +0,0 @@ -import XCTest -@testable import PBXProjParser - -final class PBXProjParserTests: XCTestCase { - func testDoubleTargetsHaveValidTargets() throws { - let path = URL(fileURLWithPath: - "Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcworkspace" - ) - - let parser = try ProjectParser(path: path, logLevel: .debug) - - let targets = parser.targets - let targetNames = targets.map { $0.name } - - let knownNames = ["DoubleTargetTest", "MyBundle", "Pods-DoubleTargetTest"] - - XCTAssert(targetNames.count == knownNames.count, "The list of targets doesn't match the size of allowed names") - - for name in targetNames { - XCTAssert(knownNames.contains(name), "\(name) wasn't in knownNames: \(knownNames)") - } - } - - func testDoubleTargetsHaveValidDependencies() throws { - let path = URL(fileURLWithPath: - "Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcworkspace" - ) - - let parser = try ProjectParser(path: path, logLevel: .debug) - let dependencies = parser.targets.reduce(into: [String: [String]]()) { partialResult, target in - partialResult[target.name] = parser.dependencies(for: target.name) - } - - let knownDependencies = [ - // TODO: This should probably handle Cocoapods doing their stupid embedding thing without listing it as a dependency... - "DoubleTargetTest": [], - // TODO: should we also disregard Cocoapods doing their stupid bundle as a native target even though it isn't - "MyBundle": ["MyBundle.bundle"], - "Pods-DoubleTargetTest": ["MyBundle.framework", "MyBundle.bundle"] - ] - - XCTAssert( - dependencies == knownDependencies, - "Dependencies: \(dependencies) doesn't equal known dependencies: \(knownDependencies)" - ) - } -} diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/xcshareddata/xcschemes/DoubleTargetTest.xcscheme b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/xcshareddata/xcschemes/DoubleTargetTest.xcscheme deleted file mode 100644 index 9c2834b..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/xcshareddata/xcschemes/DoubleTargetTest.xcscheme +++ /dev/null @@ -1,78 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcworkspace/contents.xcworkspacedata b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index a81118b..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Local Podspecs/MyBundle.podspec.json b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Local Podspecs/MyBundle.podspec.json deleted file mode 100644 index 0e86514..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Local Podspecs/MyBundle.podspec.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "MyBundle", - "version": "0.1.0", - "summary": "A short description of MyBundle.", - "description": "TODO: Add long description of the pod here.", - "homepage": "https://github.com/thedderwick/MyBundle", - "license": { - "type": "MIT", - "file": "LICENSE" - }, - "authors": { - "thedderwick": "thedderwick@veracode.com" - }, - "source": { - "git": "https://github.com/thedderwick/MyBundle.git", - "tag": "0.1.0" - }, - "platforms": { - "ios": "10.0" - }, - "source_files": "MyBundle/Classes/**/*", - "resource_bundles": { - "MyBundle": [ - "MyBundle/Assets/*.png" - ] - } -} diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Manifest.lock b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Manifest.lock deleted file mode 100644 index 71ccc8f..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Manifest.lock +++ /dev/null @@ -1,16 +0,0 @@ -PODS: - - MyBundle (0.1.0) - -DEPENDENCIES: - - MyBundle (from `/Users/thedderwick/dev/ios_tests/double_target_test/DoubleTargetTest/MyBundle`) - -EXTERNAL SOURCES: - MyBundle: - :path: "/Users/thedderwick/dev/ios_tests/double_target_test/DoubleTargetTest/MyBundle" - -SPEC CHECKSUMS: - MyBundle: e1f22e3445c35cc16854bc29f5159058eb370c1a - -PODFILE CHECKSUM: c56d07086d026876301d9d46d35896e3a7be8a1b - -COCOAPODS: 1.11.3 diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Pods.xcodeproj/project.pbxproj b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Pods.xcodeproj/project.pbxproj deleted file mode 100644 index 02766b2..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Pods.xcodeproj/project.pbxproj +++ /dev/null @@ -1,734 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - 0505D039F580D8C1C4DA3135641F7BD3 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; - 33DD7B8459A3A39525345E644BEEF41A /* Pods-DoubleTargetTest-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F65DA5A28E59EDF453B5AAA1A8D8949E /* Pods-DoubleTargetTest-dummy.m */; }; - 44651C95EE6FC2391DD4F3A167F41A44 /* MyBundle-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B24F4C49C16832C3D1AF6AED1995658 /* MyBundle-dummy.m */; }; - 674BA68B5EAA5F9008004BF3F5C02EC5 /* MyBundle-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F3E212D006779EE067440F2CB7785A4B /* MyBundle-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - A67798D7C4577858327517567612E2CD /* Pods-DoubleTargetTest-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A0B870A89DF602D8AAEA39600D8FDFDB /* Pods-DoubleTargetTest-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E25F7D067CF0E1D9B934CEECF2384CB4 /* ReplaceMe.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7F486712B4AA55E662E1657576D8133B /* ReplaceMe.swift */; }; - EE3C3BE914FAF168E38D719BEC2768D8 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */; }; - FC2645FD54DC4BE00237174806868D1D /* MyBundle.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D93F17E53BD7D266CAF6F17003C375A8 /* MyBundle.bundle */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 34E01361C037C7F47C9C4A6FD583961C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 5E26517DF39E585BCF742D88F142F59B; - remoteInfo = "MyBundle-MyBundle"; - }; - A6F9652FCB6D63EEE2F28D6506461B50 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = BFDFE7DC352907FC980B868725387E98 /* Project object */; - proxyType = 1; - remoteGlobalIDString = D44D2D0674B19633F70576544F03D1F6; - remoteInfo = MyBundle; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 05D2F3E34E29E2AEEABAF781437B56B1 /* MyBundle.podspec */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; path = MyBundle.podspec; sourceTree = ""; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 224DC3273E1C05AE11AF83EA85B8FD36 /* ResourceBundle-MyBundle-MyBundle-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "ResourceBundle-MyBundle-MyBundle-Info.plist"; sourceTree = ""; }; - 2B24F4C49C16832C3D1AF6AED1995658 /* MyBundle-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "MyBundle-dummy.m"; sourceTree = ""; }; - 57786B8140E731F1F6FF148B154D46B9 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; - 5FBA60238FECB2540F038F4AB9345480 /* Pods-DoubleTargetTest.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DoubleTargetTest.release.xcconfig"; sourceTree = ""; }; - 6A70FA6E6FCA926AAA416C9CB244CEDE /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; - 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS14.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; - 736A5947EB69EC1CF1800C6EE8A9A4D8 /* MyBundle-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "MyBundle-Info.plist"; sourceTree = ""; }; - 7F486712B4AA55E662E1657576D8133B /* ReplaceMe.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ReplaceMe.swift; path = MyBundle/Classes/ReplaceMe.swift; sourceTree = ""; }; - 80BF02E1C33CF6CD2922D48629338A1B /* MyBundle-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MyBundle-prefix.pch"; sourceTree = ""; }; - 8138D938080D00037C41432BBDEF69FB /* Pods_DoubleTargetTest.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DoubleTargetTest.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; indentWidth = 2; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; tabWidth = 2; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - A0B870A89DF602D8AAEA39600D8FDFDB /* Pods-DoubleTargetTest-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-DoubleTargetTest-umbrella.h"; sourceTree = ""; }; - C10B3C1ABAD75C99CAE60E63E4C5C226 /* MyBundle.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MyBundle.debug.xcconfig; sourceTree = ""; }; - C72825197160F688488EC69B39E06FDC /* MyBundle.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = MyBundle.modulemap; sourceTree = ""; }; - CA43AB7A1931E11A8E1FA62FC3D322F8 /* Pods-DoubleTargetTest.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-DoubleTargetTest.debug.xcconfig"; sourceTree = ""; }; - D65C2A1ACEDD3BF60470333B525BD1DC /* Pods-DoubleTargetTest-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-DoubleTargetTest-acknowledgements.markdown"; sourceTree = ""; }; - D93F17E53BD7D266CAF6F17003C375A8 /* MyBundle.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MyBundle.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - D989667258FDEA181A33B4DCADEBFEF1 /* Pods-DoubleTargetTest-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-DoubleTargetTest-acknowledgements.plist"; sourceTree = ""; }; - DC48A4403E54985F3959D0D6E0045204 /* Pods-DoubleTargetTest.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.module; path = "Pods-DoubleTargetTest.modulemap"; sourceTree = ""; }; - E511354FF29F23818915A2B3632C07CC /* Pods-DoubleTargetTest-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-DoubleTargetTest-Info.plist"; sourceTree = ""; }; - E8E0EC7D175B97912F7CBD8BFDF2B45E /* MyBundle.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = MyBundle.release.xcconfig; sourceTree = ""; }; - ED7431F391879458DE73243628EBC744 /* Pods-DoubleTargetTest-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-DoubleTargetTest-frameworks.sh"; sourceTree = ""; }; - F3E212D006779EE067440F2CB7785A4B /* MyBundle-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "MyBundle-umbrella.h"; sourceTree = ""; }; - F65DA5A28E59EDF453B5AAA1A8D8949E /* Pods-DoubleTargetTest-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-DoubleTargetTest-dummy.m"; sourceTree = ""; }; - FF65CA6FF03DFFFE7F7FFCF321A2EF48 /* MyBundle.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MyBundle.framework; sourceTree = BUILT_PRODUCTS_DIR; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 2A12A09328EBBF7ECA09B932C9A7C0E8 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C5E0F87B0CA6C796BA0B765746BF2AFB /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 0505D039F580D8C1C4DA3135641F7BD3 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EABB4E9BB1FC17E80981BA9096434936 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - EE3C3BE914FAF168E38D719BEC2768D8 /* Foundation.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 07FF93065E54DBA0271C6409D3DB7967 /* Targets Support Files */ = { - isa = PBXGroup; - children = ( - 1D5473B0E8035066E3E94EEDE7E5A8AE /* Pods-DoubleTargetTest */, - ); - name = "Targets Support Files"; - sourceTree = ""; - }; - 1D5473B0E8035066E3E94EEDE7E5A8AE /* Pods-DoubleTargetTest */ = { - isa = PBXGroup; - children = ( - DC48A4403E54985F3959D0D6E0045204 /* Pods-DoubleTargetTest.modulemap */, - D65C2A1ACEDD3BF60470333B525BD1DC /* Pods-DoubleTargetTest-acknowledgements.markdown */, - D989667258FDEA181A33B4DCADEBFEF1 /* Pods-DoubleTargetTest-acknowledgements.plist */, - F65DA5A28E59EDF453B5AAA1A8D8949E /* Pods-DoubleTargetTest-dummy.m */, - ED7431F391879458DE73243628EBC744 /* Pods-DoubleTargetTest-frameworks.sh */, - E511354FF29F23818915A2B3632C07CC /* Pods-DoubleTargetTest-Info.plist */, - A0B870A89DF602D8AAEA39600D8FDFDB /* Pods-DoubleTargetTest-umbrella.h */, - CA43AB7A1931E11A8E1FA62FC3D322F8 /* Pods-DoubleTargetTest.debug.xcconfig */, - 5FBA60238FECB2540F038F4AB9345480 /* Pods-DoubleTargetTest.release.xcconfig */, - ); - name = "Pods-DoubleTargetTest"; - path = "Target Support Files/Pods-DoubleTargetTest"; - sourceTree = ""; - }; - 20FDC45F1DD3EF707467BF569B570407 /* Pod */ = { - isa = PBXGroup; - children = ( - 6A70FA6E6FCA926AAA416C9CB244CEDE /* LICENSE */, - 05D2F3E34E29E2AEEABAF781437B56B1 /* MyBundle.podspec */, - 57786B8140E731F1F6FF148B154D46B9 /* README.md */, - ); - name = Pod; - sourceTree = ""; - }; - 2DA60530B2F5B4007868F26C4A31DCB8 /* Support Files */ = { - isa = PBXGroup; - children = ( - C72825197160F688488EC69B39E06FDC /* MyBundle.modulemap */, - 2B24F4C49C16832C3D1AF6AED1995658 /* MyBundle-dummy.m */, - 736A5947EB69EC1CF1800C6EE8A9A4D8 /* MyBundle-Info.plist */, - 80BF02E1C33CF6CD2922D48629338A1B /* MyBundle-prefix.pch */, - F3E212D006779EE067440F2CB7785A4B /* MyBundle-umbrella.h */, - C10B3C1ABAD75C99CAE60E63E4C5C226 /* MyBundle.debug.xcconfig */, - E8E0EC7D175B97912F7CBD8BFDF2B45E /* MyBundle.release.xcconfig */, - 224DC3273E1C05AE11AF83EA85B8FD36 /* ResourceBundle-MyBundle-MyBundle-Info.plist */, - ); - name = "Support Files"; - path = "../Pods/Target Support Files/MyBundle"; - sourceTree = ""; - }; - 530F2AFE538911ABCDFFFAD240B6C43F /* Development Pods */ = { - isa = PBXGroup; - children = ( - 779A4C1FC7F0153F4E499ED3B1262F9D /* MyBundle */, - ); - name = "Development Pods"; - sourceTree = ""; - }; - 578452D2E740E91742655AC8F1636D1F /* iOS */ = { - isa = PBXGroup; - children = ( - 73010CC983E3809BECEE5348DA1BB8C6 /* Foundation.framework */, - ); - name = iOS; - sourceTree = ""; - }; - 779A4C1FC7F0153F4E499ED3B1262F9D /* MyBundle */ = { - isa = PBXGroup; - children = ( - 7F486712B4AA55E662E1657576D8133B /* ReplaceMe.swift */, - 20FDC45F1DD3EF707467BF569B570407 /* Pod */, - 2DA60530B2F5B4007868F26C4A31DCB8 /* Support Files */, - ); - name = MyBundle; - path = /Users/thedderwick/dev/ios_tests/double_target_test/DoubleTargetTest/MyBundle; - sourceTree = ""; - }; - 8820BDE64C1284039B9392B149BBF3F1 /* Products */ = { - isa = PBXGroup; - children = ( - FF65CA6FF03DFFFE7F7FFCF321A2EF48 /* MyBundle.framework */, - D93F17E53BD7D266CAF6F17003C375A8 /* MyBundle.bundle */, - 8138D938080D00037C41432BBDEF69FB /* Pods_DoubleTargetTest.framework */, - ); - name = Products; - sourceTree = ""; - }; - CF1408CF629C7361332E53B88F7BD30C = { - isa = PBXGroup; - children = ( - 9D940727FF8FB9C785EB98E56350EF41 /* Podfile */, - 530F2AFE538911ABCDFFFAD240B6C43F /* Development Pods */, - D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */, - 8820BDE64C1284039B9392B149BBF3F1 /* Products */, - 07FF93065E54DBA0271C6409D3DB7967 /* Targets Support Files */, - ); - sourceTree = ""; - }; - D210D550F4EA176C3123ED886F8F87F5 /* Frameworks */ = { - isa = PBXGroup; - children = ( - 578452D2E740E91742655AC8F1636D1F /* iOS */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - DFDB214017CAB64FA5759DEEE88C6482 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 674BA68B5EAA5F9008004BF3F5C02EC5 /* MyBundle-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - EF90799616133DD7D69BDFBBA5CEA166 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - A67798D7C4577858327517567612E2CD /* Pods-DoubleTargetTest-umbrella.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 2C5F8EFB5430A4211A0B84AAF4F13F9C /* Pods-DoubleTargetTest */ = { - isa = PBXNativeTarget; - buildConfigurationList = 4BA9A3509482DBEAB6E2815BA49CFF38 /* Build configuration list for PBXNativeTarget "Pods-DoubleTargetTest" */; - buildPhases = ( - EF90799616133DD7D69BDFBBA5CEA166 /* Headers */, - B3CB7EA40906C61E205292A9A351D3CB /* Sources */, - EABB4E9BB1FC17E80981BA9096434936 /* Frameworks */, - 87E5F63D5CCB13C8680E20FD9006DE94 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 72A1629C1F4E73D2E84B18F70BC27E45 /* PBXTargetDependency */, - ); - name = "Pods-DoubleTargetTest"; - productName = Pods_DoubleTargetTest; - productReference = 8138D938080D00037C41432BBDEF69FB /* Pods_DoubleTargetTest.framework */; - productType = "com.apple.product-type.framework"; - }; - 5E26517DF39E585BCF742D88F142F59B /* MyBundle-MyBundle */ = { - isa = PBXNativeTarget; - buildConfigurationList = 653128552AEA47E651B38399510A6921 /* Build configuration list for PBXNativeTarget "MyBundle-MyBundle" */; - buildPhases = ( - 8E15891098856B42AEF03BBCF6C6CF8B /* Sources */, - 2A12A09328EBBF7ECA09B932C9A7C0E8 /* Frameworks */, - 51CCDFF654B64A04999C81E4263E6D99 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "MyBundle-MyBundle"; - productName = MyBundle; - productReference = D93F17E53BD7D266CAF6F17003C375A8 /* MyBundle.bundle */; - productType = "com.apple.product-type.bundle"; - }; - D44D2D0674B19633F70576544F03D1F6 /* MyBundle */ = { - isa = PBXNativeTarget; - buildConfigurationList = 2F9F1F2725B9CBC6E4E1D2BC535F21BB /* Build configuration list for PBXNativeTarget "MyBundle" */; - buildPhases = ( - DFDB214017CAB64FA5759DEEE88C6482 /* Headers */, - C44C0BBB4071B406F57E947248DC4312 /* Sources */, - C5E0F87B0CA6C796BA0B765746BF2AFB /* Frameworks */, - 4CB90525191925AD5A3E2E39B45FECCD /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - C624302602CF69389AEA79A23EA0372D /* PBXTargetDependency */, - ); - name = MyBundle; - productName = MyBundle; - productReference = FF65CA6FF03DFFFE7F7FFCF321A2EF48 /* MyBundle.framework */; - productType = "com.apple.product-type.framework"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - BFDFE7DC352907FC980B868725387E98 /* Project object */ = { - isa = PBXProject; - attributes = { - LastSwiftUpdateCheck = 1300; - LastUpgradeCheck = 1300; - }; - buildConfigurationList = 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */; - compatibilityVersion = "Xcode 14.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - Base, - en, - ); - mainGroup = CF1408CF629C7361332E53B88F7BD30C; - productRefGroup = 8820BDE64C1284039B9392B149BBF3F1 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - D44D2D0674B19633F70576544F03D1F6 /* MyBundle */, - 5E26517DF39E585BCF742D88F142F59B /* MyBundle-MyBundle */, - 2C5F8EFB5430A4211A0B84AAF4F13F9C /* Pods-DoubleTargetTest */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 4CB90525191925AD5A3E2E39B45FECCD /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - FC2645FD54DC4BE00237174806868D1D /* MyBundle.bundle in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 51CCDFF654B64A04999C81E4263E6D99 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 87E5F63D5CCB13C8680E20FD9006DE94 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 8E15891098856B42AEF03BBCF6C6CF8B /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - B3CB7EA40906C61E205292A9A351D3CB /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 33DD7B8459A3A39525345E644BEEF41A /* Pods-DoubleTargetTest-dummy.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - C44C0BBB4071B406F57E947248DC4312 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 44651C95EE6FC2391DD4F3A167F41A44 /* MyBundle-dummy.m in Sources */, - E25F7D067CF0E1D9B934CEECF2384CB4 /* ReplaceMe.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 72A1629C1F4E73D2E84B18F70BC27E45 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = MyBundle; - target = D44D2D0674B19633F70576544F03D1F6 /* MyBundle */; - targetProxy = A6F9652FCB6D63EEE2F28D6506461B50 /* PBXContainerItemProxy */; - }; - C624302602CF69389AEA79A23EA0372D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = "MyBundle-MyBundle"; - target = 5E26517DF39E585BCF742D88F142F59B /* MyBundle-MyBundle */; - targetProxy = 34E01361C037C7F47C9C4A6FD583961C /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin XCBuildConfiguration section */ - 20B1B8D2F3D27105B0D81D14421C20CA /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C10B3C1ABAD75C99CAE60E63E4C5C226 /* MyBundle.debug.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MyBundle"; - DEVELOPMENT_TEAM = ""; - IBSC_MODULE = MyBundle; - INFOPLIST_FILE = "Target Support Files/MyBundle/ResourceBundle-MyBundle-MyBundle-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - PRODUCT_NAME = MyBundle; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; - 446BA1B9A1F1F2F95D04E5F82EB1B0F4 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_DEBUG=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; - MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; - MTL_FAST_MATH = YES; - ONLY_ACTIVE_ARCH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; - 5D47E2EFAC6FAC81A782D9BFD8736F53 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_ENABLE_OBJC_WEAK = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_DOCUMENTATION_COMMENTS = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREPROCESSOR_DEFINITIONS = ( - "POD_CONFIGURATION_RELEASE=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; - MTL_ENABLE_DEBUG_INFO = NO; - MTL_FAST_MATH = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; - STRIP_INSTALLED_PRODUCT = NO; - SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; - SWIFT_VERSION = 5.0; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Release; - }; - 962BDC6723AD0C2121208533EE1026E7 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = CA43AB7A1931E11A8E1FA62FC3D322F8 /* Pods-DoubleTargetTest.debug.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - 9C1B3E43E825EB8D4540CCEEDD20FEFC /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 5FBA60238FECB2540F038F4AB9345480 /* Pods-DoubleTargetTest.release.xcconfig */; - buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO; - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.modulemap"; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - AF63CE00DDA4FBC37E5031858C625514 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E8E0EC7D175B97912F7CBD8BFDF2B45E /* MyBundle.release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - CODE_SIGN_STYLE = Manual; - CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/MyBundle"; - DEVELOPMENT_TEAM = ""; - IBSC_MODULE = MyBundle; - INFOPLIST_FILE = "Target Support Files/MyBundle/ResourceBundle-MyBundle-MyBundle-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - PRODUCT_NAME = MyBundle; - PROVISIONING_PROFILE_SPECIFIER = ""; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - TARGETED_DEVICE_FAMILY = "1,2"; - WRAPPER_EXTENSION = bundle; - }; - name = Release; - }; - B8B137A9E60B7D7D73FFD3D06FC029D7 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = E8E0EC7D175B97912F7CBD8BFDF2B45E /* MyBundle.release.xcconfig */; - buildSettings = { - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/MyBundle/MyBundle-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/MyBundle/MyBundle-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MODULEMAP_FILE = "Target Support Files/MyBundle/MyBundle.modulemap"; - PRODUCT_MODULE_NAME = MyBundle; - PRODUCT_NAME = MyBundle; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - E1E03382DD524E8939F7CC62A62FDE3A /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = C10B3C1ABAD75C99CAE60E63E4C5C226 /* MyBundle.debug.xcconfig */; - buildSettings = { - CLANG_ENABLE_OBJC_WEAK = NO; - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - GCC_PREFIX_HEADER = "Target Support Files/MyBundle/MyBundle-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/MyBundle/MyBundle-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 10.0; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/Frameworks", - "@loader_path/Frameworks", - ); - MODULEMAP_FILE = "Target Support Files/MyBundle/MyBundle.modulemap"; - PRODUCT_MODULE_NAME = MyBundle; - PRODUCT_NAME = MyBundle; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; - SWIFT_VERSION = 5.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 2F9F1F2725B9CBC6E4E1D2BC535F21BB /* Build configuration list for PBXNativeTarget "MyBundle" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E1E03382DD524E8939F7CC62A62FDE3A /* Debug */, - B8B137A9E60B7D7D73FFD3D06FC029D7 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4821239608C13582E20E6DA73FD5F1F9 /* Build configuration list for PBXProject "Pods" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 446BA1B9A1F1F2F95D04E5F82EB1B0F4 /* Debug */, - 5D47E2EFAC6FAC81A782D9BFD8736F53 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 4BA9A3509482DBEAB6E2815BA49CFF38 /* Build configuration list for PBXNativeTarget "Pods-DoubleTargetTest" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 962BDC6723AD0C2121208533EE1026E7 /* Debug */, - 9C1B3E43E825EB8D4540CCEEDD20FEFC /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 653128552AEA47E651B38399510A6921 /* Build configuration list for PBXNativeTarget "MyBundle-MyBundle" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 20B1B8D2F3D27105B0D81D14421C20CA /* Debug */, - AF63CE00DDA4FBC37E5031858C625514 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = BFDFE7DC352907FC980B868725387E98 /* Project object */; -} diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-Info.plist b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-Info.plist deleted file mode 100644 index 161a9d3..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 0.1.0 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-dummy.m b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-dummy.m deleted file mode 100644 index e24399a..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_MyBundle : NSObject -@end -@implementation PodsDummy_MyBundle -@end diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-prefix.pch b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-prefix.pch deleted file mode 100644 index beb2a24..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-prefix.pch +++ /dev/null @@ -1,12 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-umbrella.h b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-umbrella.h deleted file mode 100644 index f846ef6..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle-umbrella.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - - -FOUNDATION_EXPORT double MyBundleVersionNumber; -FOUNDATION_EXPORT const unsigned char MyBundleVersionString[]; - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle.debug.xcconfig b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle.debug.xcconfig deleted file mode 100644 index 8a95b1f..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle.debug.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MyBundle -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/../MyBundle -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle.modulemap b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle.modulemap deleted file mode 100644 index 23d5f54..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module MyBundle { - umbrella header "MyBundle-umbrella.h" - - export * - module * { export * } -} diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle.release.xcconfig b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle.release.xcconfig deleted file mode 100644 index 8a95b1f..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/MyBundle.release.xcconfig +++ /dev/null @@ -1,13 +0,0 @@ -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/MyBundle -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_ROOT = ${SRCROOT} -PODS_TARGET_SRCROOT = ${PODS_ROOT}/../MyBundle -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} -SKIP_INSTALL = YES -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/ResourceBundle-MyBundle-MyBundle-Info.plist b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/ResourceBundle-MyBundle-MyBundle-Info.plist deleted file mode 100644 index 99a40ff..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/MyBundle/ResourceBundle-MyBundle-MyBundle-Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - BNDL - CFBundleShortVersionString - 0.1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - NSPrincipalClass - - - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-Info.plist b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-Info.plist deleted file mode 100644 index 2243fe6..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-Info.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - ${EXECUTABLE_NAME} - CFBundleIdentifier - ${PRODUCT_BUNDLE_IDENTIFIER} - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - ${PRODUCT_NAME} - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0.0 - CFBundleSignature - ???? - CFBundleVersion - ${CURRENT_PROJECT_VERSION} - NSPrincipalClass - - - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-acknowledgements.markdown b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-acknowledgements.markdown deleted file mode 100644 index 8bb471a..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-acknowledgements.markdown +++ /dev/null @@ -1,26 +0,0 @@ -# Acknowledgements -This application makes use of the following third party libraries: - -## MyBundle - -Copyright (c) 2023 thedderwick - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - -Generated by CocoaPods - https://cocoapods.org diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-acknowledgements.plist b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-acknowledgements.plist deleted file mode 100644 index 711f6ee..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-acknowledgements.plist +++ /dev/null @@ -1,58 +0,0 @@ - - - - - PreferenceSpecifiers - - - FooterText - This application makes use of the following third party libraries: - Title - Acknowledgements - Type - PSGroupSpecifier - - - FooterText - Copyright (c) 2023 thedderwick <thedderwick@veracode.com> - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - - License - MIT - Title - MyBundle - Type - PSGroupSpecifier - - - FooterText - Generated by CocoaPods - https://cocoapods.org - Title - - Type - PSGroupSpecifier - - - StringsTable - Acknowledgements - Title - Acknowledgements - - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-dummy.m b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-dummy.m deleted file mode 100644 index beca502..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-dummy.m +++ /dev/null @@ -1,5 +0,0 @@ -#import -@interface PodsDummy_Pods_DoubleTargetTest : NSObject -@end -@implementation PodsDummy_Pods_DoubleTargetTest -@end diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Debug-input-files.xcfilelist b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Debug-input-files.xcfilelist deleted file mode 100644 index cd39096..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Debug-input-files.xcfilelist +++ /dev/null @@ -1,2 +0,0 @@ -${PODS_ROOT}/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks.sh -${BUILT_PRODUCTS_DIR}/MyBundle/MyBundle.framework \ No newline at end of file diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Debug-output-files.xcfilelist b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Debug-output-files.xcfilelist deleted file mode 100644 index 07517cb..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Debug-output-files.xcfilelist +++ /dev/null @@ -1 +0,0 @@ -${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MyBundle.framework \ No newline at end of file diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Release-input-files.xcfilelist b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Release-input-files.xcfilelist deleted file mode 100644 index cd39096..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Release-input-files.xcfilelist +++ /dev/null @@ -1,2 +0,0 @@ -${PODS_ROOT}/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks.sh -${BUILT_PRODUCTS_DIR}/MyBundle/MyBundle.framework \ No newline at end of file diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Release-output-files.xcfilelist b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Release-output-files.xcfilelist deleted file mode 100644 index 07517cb..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-Release-output-files.xcfilelist +++ /dev/null @@ -1 +0,0 @@ -${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MyBundle.framework \ No newline at end of file diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks.sh b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks.sh deleted file mode 100755 index 8fe186b..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks.sh +++ /dev/null @@ -1,186 +0,0 @@ -#!/bin/sh -set -e -set -u -set -o pipefail - -function on_error { - echo "$(realpath -mq "${0}"):$1: error: Unexpected failure" -} -trap 'on_error $LINENO' ERR - -if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then - # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy - # frameworks to, so exit 0 (signalling the script phase was successful). - exit 0 -fi - -echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" -mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - -COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" -SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" -BCSYMBOLMAP_DIR="BCSymbolMaps" - - -# This protects against multiple targets copying the same framework dependency at the same time. The solution -# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html -RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") - -# Copies and strips a vendored framework -install_framework() -{ - if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then - local source="${BUILT_PRODUCTS_DIR}/$1" - elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then - local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" - elif [ -r "$1" ]; then - local source="$1" - fi - - local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - - if [ -L "${source}" ]; then - echo "Symlinked..." - source="$(readlink "${source}")" - fi - - if [ -d "${source}/${BCSYMBOLMAP_DIR}" ]; then - # Locate and install any .bcsymbolmaps if present, and remove them from the .framework before the framework is copied - find "${source}/${BCSYMBOLMAP_DIR}" -name "*.bcsymbolmap"|while read f; do - echo "Installing $f" - install_bcsymbolmap "$f" "$destination" - rm "$f" - done - rmdir "${source}/${BCSYMBOLMAP_DIR}" - fi - - # Use filter instead of exclude so missing patterns don't throw errors. - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" - - local basename - basename="$(basename -s .framework "$1")" - binary="${destination}/${basename}.framework/${basename}" - - if ! [ -r "$binary" ]; then - binary="${destination}/${basename}" - elif [ -L "${binary}" ]; then - echo "Destination binary is symlinked..." - dirname="$(dirname "${binary}")" - binary="${dirname}/$(readlink "${binary}")" - fi - - # Strip invalid architectures so "fat" simulator / device frameworks work on device - if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then - strip_invalid_archs "$binary" - fi - - # Resign the code if required by the build settings to avoid unstable apps - code_sign_if_enabled "${destination}/$(basename "$1")" - - # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. - if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then - local swift_runtime_libs - swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u) - for lib in $swift_runtime_libs; do - echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" - rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" - code_sign_if_enabled "${destination}/${lib}" - done - fi -} -# Copies and strips a vendored dSYM -install_dsym() { - local source="$1" - warn_missing_arch=${2:-true} - if [ -r "$source" ]; then - # Copy the dSYM into the targets temp dir. - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" - - local basename - basename="$(basename -s .dSYM "$source")" - binary_name="$(ls "$source/Contents/Resources/DWARF")" - binary="${DERIVED_FILES_DIR}/${basename}.dSYM/Contents/Resources/DWARF/${binary_name}" - - # Strip invalid architectures from the dSYM. - if [[ "$(file "$binary")" == *"Mach-O "*"dSYM companion"* ]]; then - strip_invalid_archs "$binary" "$warn_missing_arch" - fi - if [[ $STRIP_BINARY_RETVAL == 0 ]]; then - # Move the stripped file into its final destination. - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --links --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.dSYM" "${DWARF_DSYM_FOLDER_PATH}" - else - # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. - mkdir -p "${DWARF_DSYM_FOLDER_PATH}" - touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.dSYM" - fi - fi -} - -# Used as a return value for each invocation of `strip_invalid_archs` function. -STRIP_BINARY_RETVAL=0 - -# Strip invalid architectures -strip_invalid_archs() { - binary="$1" - warn_missing_arch=${2:-true} - # Get architectures for current target binary - binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" - # Intersect them with the architectures we are building for - intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" - # If there are no archs supported by this binary then warn the user - if [[ -z "$intersected_archs" ]]; then - if [[ "$warn_missing_arch" == "true" ]]; then - echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." - fi - STRIP_BINARY_RETVAL=1 - return - fi - stripped="" - for arch in $binary_archs; do - if ! [[ "${ARCHS}" == *"$arch"* ]]; then - # Strip non-valid architectures in-place - lipo -remove "$arch" -output "$binary" "$binary" - stripped="$stripped $arch" - fi - done - if [[ "$stripped" ]]; then - echo "Stripped $binary of architectures:$stripped" - fi - STRIP_BINARY_RETVAL=0 -} - -# Copies the bcsymbolmap files of a vendored framework -install_bcsymbolmap() { - local bcsymbolmap_path="$1" - local destination="${BUILT_PRODUCTS_DIR}" - echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}"" - rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${bcsymbolmap_path}" "${destination}" -} - -# Signs a framework with the provided identity -code_sign_if_enabled() { - if [ -n "${EXPANDED_CODE_SIGN_IDENTITY:-}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then - # Use the current code_sign_identity - echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" - local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" - - if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then - code_sign_cmd="$code_sign_cmd &" - fi - echo "$code_sign_cmd" - eval "$code_sign_cmd" - fi -} - -if [[ "$CONFIGURATION" == "Debug" ]]; then - install_framework "${BUILT_PRODUCTS_DIR}/MyBundle/MyBundle.framework" -fi -if [[ "$CONFIGURATION" == "Release" ]]; then - install_framework "${BUILT_PRODUCTS_DIR}/MyBundle/MyBundle.framework" -fi -if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then - wait -fi diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-umbrella.h b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-umbrella.h deleted file mode 100644 index 570ba23..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-umbrella.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifdef __OBJC__ -#import -#else -#ifndef FOUNDATION_EXPORT -#if defined(__cplusplus) -#define FOUNDATION_EXPORT extern "C" -#else -#define FOUNDATION_EXPORT extern -#endif -#endif -#endif - - -FOUNDATION_EXPORT double Pods_DoubleTargetTestVersionNumber; -FOUNDATION_EXPORT const unsigned char Pods_DoubleTargetTestVersionString[]; - diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.debug.xcconfig b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.debug.xcconfig deleted file mode 100644 index c9bfcc2..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.debug.xcconfig +++ /dev/null @@ -1,15 +0,0 @@ -ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MyBundle" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MyBundle/MyBundle.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -OTHER_LDFLAGS = $(inherited) -framework "MyBundle" -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_PODFILE_DIR_PATH = ${SRCROOT}/. -PODS_ROOT = ${SRCROOT}/Pods -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.modulemap b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.modulemap deleted file mode 100644 index 0fe645c..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.modulemap +++ /dev/null @@ -1,6 +0,0 @@ -framework module Pods_DoubleTargetTest { - umbrella header "Pods-DoubleTargetTest-umbrella.h" - - export * - module * { export * } -} diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.release.xcconfig b/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.release.xcconfig deleted file mode 100644 index c9bfcc2..0000000 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/Pods/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.release.xcconfig +++ /dev/null @@ -1,15 +0,0 @@ -ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES -CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO -FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MyBundle" -GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 -HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/MyBundle/MyBundle.framework/Headers" -LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' -LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift -OTHER_LDFLAGS = $(inherited) -framework "MyBundle" -OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -PODS_BUILD_DIR = ${BUILD_DIR} -PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) -PODS_PODFILE_DIR_PATH = ${SRCROOT}/. -PODS_ROOT = ${SRCROOT}/Pods -PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates -USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES diff --git a/PBXProjParser/.gitignore b/PIF/.gitignore similarity index 72% rename from PBXProjParser/.gitignore rename to PIF/.gitignore index 3b29812..0023a53 100644 --- a/PBXProjParser/.gitignore +++ b/PIF/.gitignore @@ -1,9 +1,8 @@ .DS_Store /.build /Packages -/*.xcodeproj xcuserdata/ DerivedData/ -.swiftpm/config/registries.json +.swiftpm/configuration/registries.json .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata .netrc diff --git a/PIF/NOTICE.txt b/PIF/NOTICE.txt new file mode 100644 index 0000000..26b34a9 --- /dev/null +++ b/PIF/NOTICE.txt @@ -0,0 +1,11 @@ + + PIF Support + =========== + +This product contains a derivation of Swift Package Manager's XCBuildSupport library, specifically `PIF.swift` + + * LICENSE (Apache License 2.0): + * https://raw.githubusercontent.com/apple/swift-package-manager/main/LICENSE.txt + * HOMEPAGE: + * https://github.com/apple/swift-package-manager/ + * https://swift.org diff --git a/PIF/Package.resolved b/PIF/Package.resolved new file mode 100644 index 0000000..d0d296f --- /dev/null +++ b/PIF/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "12c22d4bea7efd3c5084cc3bac01b276e5f01c1011991fc15f93790ff260cb4b", + "pins" : [ + { + "identity" : "swift-log", + "kind" : "remoteSourceControl", + "location" : "https://github.com/apple/swift-log.git", + "state" : { + "revision" : "e97a6fcb1ab07462881ac165fdbb37f067e205d5", + "version" : "1.5.4" + } + } + ], + "version" : 3 +} diff --git a/PIF/Package.swift b/PIF/Package.swift new file mode 100644 index 0000000..ff4790d --- /dev/null +++ b/PIF/Package.swift @@ -0,0 +1,39 @@ +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "PIF", + platforms: [.macOS(.v12)], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "PIFSupport", + targets: ["PIFSupport"] + ) + ], + dependencies: [ + .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0") + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "PIFSupport", + dependencies: [ + .product(name: "Logging", package: "swift-log") + ] + ), + .testTarget( + name: "PIFSupportTests", + dependencies: ["PIFSupport"] + ), + .executableTarget( + name: "pif-parser", + dependencies: [ + "PIFSupport" + ] + ) + ] +) diff --git a/PIF/Sources/PIFSupport/PIF.swift b/PIF/Sources/PIFSupport/PIF.swift new file mode 100644 index 0000000..48d8145 --- /dev/null +++ b/PIF/Sources/PIFSupport/PIF.swift @@ -0,0 +1,901 @@ +// ===----------------------------------------------------------------------=== // +// +// This source file contains derivative work from the Swift Open Source Project +// +// Copyright (c) 2014-2020 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See http://swift.org/LICENSE.txt for license information +// See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors +// +// ===----------------------------------------------------------------------=== // + +/* Changes: Thomas Hedderwick: + - adjust structures to allow for only decoding Xcode's PIF files found in DerivedData + - adjust types to remove external dependencies on SPM +*/ + +// swiftlint:disable file_length type_body_length +import Foundation + +/// The Project Interchange Format (PIF) is a structured representation of the +/// project model created by clients (Xcode/SwiftPM) to send to XCBuild. +/// +/// The PIF is a representation of the project model describing the static +/// objects which contribute to building products from the project, independent +/// of "how" the user has chosen to build those products in any particular +/// build. This information can be cached by XCBuild between builds (even +/// between builds which use different schemes or configurations), and can be +/// incrementally updated by clients when something changes. +public enum PIF { + /// This is used as part of the signature for the high-level PIF objects, to ensure that changes to the PIF schema + /// are represented by the objects which do not use a content-based signature scheme (workspaces and projects, + /// currently). + static let schemaVersion = 11 + + /// The file extension for files in the PIF cache + static let cacheFileExtension = "-json" + + /// The type used for identifying PIF objects. + public typealias GUID = String + + public enum Error: Swift.Error { + case decodingError(String) + case userInfoError(String) + case dataReadingFailure(String) + } + + /// The top-level PIF object. + public struct TopLevelObject: Decodable { + public let workspace: PIF.Workspace + + public init(workspace: PIF.Workspace) { + self.workspace = workspace + } + } + + public class TypedObject: Decodable { + class var type: String { + fatalError("\(self) missing implementation") + } + + let type: String? + + fileprivate init() { + type = Swift.type(of: self).type + } + + private enum CodingKeys: CodingKey { + case type + } + + required public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + type = try container.decode(String.self, forKey: .type) + } + } + + public final class Workspace: Decodable { + public let guid: GUID + public let name: String + public let path: URL + public let projects: [Project] + + private enum CodingKeys: CodingKey { + case guid, name, path, projects + } + + public required init(from decoder: Decoder) throws { + guard let cachePath = decoder.userInfo[.pifCachePath] as? URL else { + throw Error.userInfoError("decoder's userInfo doesn't container required key .cachePath, or that value isn't a URL") + } + + let container = try decoder.container(keyedBy: CodingKeys.self) + + guid = try container.decode(GUID.self, forKey: .guid) + name = try container.decode(String.self, forKey: .name) + path = try container.decode(URL.self, forKey: .path) + + let projectPaths = try container.decode([String].self, forKey: .projects) + .map { + cachePath + .appendingPathComponent("project") + .appendingPathComponent("\($0)\(PIF.cacheFileExtension)") + } + + let projectContents = try projectPaths + .map { + do { + return try Data(contentsOf: $0) + } catch { + throw Error.dataReadingFailure(error.localizedDescription) + } + } + + projects = try projectContents + .map { + try PIFDecoder(cache: cachePath).decode(PIF.Project.self, from: $0) + } + } + } + + /// A PIF project, consisting of a tree of groups and file references, a list of targets, and some additional + /// information. + public final class Project: Decodable { + public let guid: GUID + public let projectName: String? + public let path: URL + public let projectDirectory: URL + public let developmentRegion: String? + public let buildConfigurations: [BuildConfiguration] + public let targets: [BaseTarget] + public let groupTree: Group + + private enum CodingKeys: CodingKey { + case guid, projectName, projectIsPackage, path, projectDirectory, developmentRegion, defaultConfigurationName, buildConfigurations, targets, groupTree + } + + public required init(from decoder: Decoder) throws { + guard let cachePath = decoder.userInfo[.pifCachePath] as? URL else { + throw Error.userInfoError("decoder's userInfo doesn't container required key .cachePath, or that value isn't a URL") + } + let container = try decoder.container(keyedBy: CodingKeys.self) + + guid = try container.decode(GUID.self, forKey: .guid) + projectName = try container.decodeIfPresent(String.self, forKey: .projectName) + path = try container.decode(URL.self, forKey: .path) + projectDirectory = try container.decode(URL.self, forKey: .projectDirectory) + developmentRegion = try container.decodeIfPresent(String.self, forKey: .developmentRegion) + buildConfigurations = try container.decode([BuildConfiguration].self, forKey: .buildConfigurations) + + let targetContents = try container.decode([String].self, forKey: .targets) + .map { + cachePath + .appendingPathComponent("target") + .appendingPathComponent("\($0)\(PIF.cacheFileExtension)") + } + .map { + do { + return try Data(contentsOf: $0) + } catch { + throw Error.dataReadingFailure(error.localizedDescription) + } + } + + targets = try targetContents + .map { targetData -> BaseTarget in + let pifDecoder = PIFDecoder(cache: cachePath) + let untypedTarget = try pifDecoder.decode(PIF.TypedObject.self, from: targetData) + switch untypedTarget.type { + case "aggregate": + return try pifDecoder.decode(PIF.AggregateTarget.self, from: targetData) + case "standard", "packageProduct": + return try pifDecoder.decode(PIF.Target.self, from: targetData) + default: + throw Error.decodingError("Target type unknown: \(untypedTarget)") + } + } + + self.groupTree = try container.decode(Group.self, forKey: .groupTree) + } + } + + /// Abstract base class for all items in the group hierarchy. + public class Reference: TypedObject { + /// Determines the base path for a reference's relative path. + public enum SourceTree: String, Decodable { + /// Indicates that the path is relative to the source root (i.e. the "project directory"). + case sourceRoot = "SOURCE_ROOT" + + /// Indicates that the path is relative to the path of the parent group. + case group = "" + + /// Indicates that the path is relative to the effective build directory (which varies depending on active + /// scheme, active run destination, or even an overridden build setting. + case builtProductsDir = "BUILT_PRODUCTS_DIR" + + /// Indicates that the path is an absolute path. + case absolute = "" + + /// Indicates that the path is relative to the SDKROOT + case sdkRoot = "SDKROOT" + + /// Indicates that the path is relative to the DEVELOPER_DIR (normally in the Xcode.app bundle) + case developerDir = "DEVELOPER_DIR" + } + + public let guid: GUID + + /// Relative path of the reference. It is usually a literal, but may in fact contain build settings. + public let path: String + + /// Determines the base path for the reference's relative path. + public let sourceTree: SourceTree + + /// Name of the reference, if different from the last path component (if not set, the last path component will + /// be used as the name). + public let name: String? + + private enum CodingKeys: CodingKey { + case guid, sourceTree, path, name, type + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + guid = try container.decode(String.self, forKey: .guid) + sourceTree = try container.decode(SourceTree.self, forKey: .sourceTree) + path = try container.decode(String.self, forKey: .path) + name = try container.decodeIfPresent(String.self, forKey: .name) + + try super.init(from: decoder) + } + } + + /// A reference to a file system entity (a file, folder, etc). + public final class FileReference: Reference { + override class var type: String { "file" } + + public var fileType: String + + private enum CodingKeys: CodingKey { + case fileType + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + fileType = try container.decode(String.self, forKey: .fileType) + + try super.init(from: decoder) + } + } + + /// A group that can contain References (FileReferences and other Groups). The resolved path of a group is used as + /// the base path for any child references whose source tree type is GroupRelative. + public final class VariantGroup: Group { + override class var type: String { "variantGroup" } + + private enum CodingKeys: CodingKey { + case children, type + } + + public required init(from decoder: Decoder) throws { + try super.init(from: decoder) + } + } + + public final class VersionGroup: Group { + override class var type: String { "versionGroup" } + + private enum CodingKeys: CodingKey { + case children, type + } + + public required init(from decoder: Decoder) throws { + try super.init(from: decoder) + } + } + + /// A group that can contain References (FileReferences and other Groups). The resolved path of a group is used as + /// the base path for any child references whose source tree type is GroupRelative. + public class Group: Reference { + override class var type: String { "group" } + + public let children: [Reference] + + private enum CodingKeys: CodingKey { + case children, type + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let untypedChildren = try container.decodeIfPresent([TypedObject].self, forKey: .children) ?? [] + if !untypedChildren.isEmpty { + var childrenContainer = try container.nestedUnkeyedContainer(forKey: .children) + + children = try untypedChildren.compactMap { child in + switch child.type { + case Group.type: + return try childrenContainer.decode(Group.self) + case VariantGroup.type: + return try childrenContainer.decode(VariantGroup.self) + case VersionGroup.type: + return try childrenContainer.decode(VersionGroup.self) + case FileReference.type: + return try childrenContainer.decode(FileReference.self) + default: + logger.debug("unknown reference type: \(child.type ?? "")") + return nil + } + } + } else { + children = [] + } + + try super.init(from: decoder) + } + } + + /// Represents a dependency on another target (identified by its PIF GUID). + public struct TargetDependency: Decodable { + /// Identifier of depended-upon target. + public let targetGUID: String + + /// The platform filters for this target dependency. + public let platformFilters: [PlatformFilter] + + private enum CodingKeys: CodingKey { + case guid, platformFilters + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + targetGUID = try container.decode(String.self, forKey: .guid) + platformFilters = try container.decodeIfPresent([PlatformFilter].self, forKey: .platformFilters) ?? [] + } + } + + public class BaseTarget: TypedObject { + class override var type: String { "target" } + + public let guid: GUID + public let name: String + public let buildConfigurations: [BuildConfiguration] + public let buildPhases: [BuildPhase] + public let dependencies: [TargetDependency] + public let impartedBuildProperties: ImpartedBuildProperties? + + fileprivate init( + guid: GUID, + name: String, + buildConfigurations: [BuildConfiguration], + buildPhases: [BuildPhase], + dependencies: [TargetDependency], + impartedBuildSettings: PIF.BuildSettings? + ) { + self.guid = guid + self.name = name + self.buildConfigurations = buildConfigurations + self.buildPhases = buildPhases + self.dependencies = dependencies + self.impartedBuildProperties = ImpartedBuildProperties(buildSettings: impartedBuildSettings ?? .init()) + super.init() + } + + public required init(from decoder: Decoder) throws { + throw Error.decodingError("init(from:) has not been implemented") + } + } + + public final class AggregateTarget: BaseTarget { + private enum CodingKeys: CodingKey { + case type, guid, name, buildConfigurations, buildPhases, dependencies, impartedBuildProperties + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let guid = try container.decode(GUID.self, forKey: .guid) + let name = try container.decode(String.self, forKey: .name) + let buildConfigurations = try container.decode([BuildConfiguration].self, forKey: .buildConfigurations) + + let untypedBuildPhases = try container.decode([TypedObject].self, forKey: .buildPhases) + var buildPhasesContainer = try container.nestedUnkeyedContainer(forKey: .buildPhases) + + let buildPhases: [BuildPhase] = try untypedBuildPhases.compactMap { + guard let type = $0.type else { + throw Error.decodingError("Expected type in build phase \($0)") + } + return try BuildPhase.decode(container: &buildPhasesContainer, type: type) + } + + let dependencies = try container.decode([TargetDependency].self, forKey: .dependencies) + let impartedBuildProperties = try container.decodeIfPresent(BuildSettings.self, forKey: .impartedBuildProperties) + + super.init( + guid: guid, + name: name, + buildConfigurations: buildConfigurations, + buildPhases: buildPhases, + dependencies: dependencies, + impartedBuildSettings: impartedBuildProperties + ) + } + } + + /// An Xcode target, representing a single entity to build. + public final class Target: BaseTarget { + public enum ProductType: String, Decodable { + case appExtension = "com.apple.product-type.app-extension" + case appExtensionMessages = "com.apple.product-type.app-extension.messages" + case stickerPackExtension = "com.apple.product-type.app-extension.messages-sticker-pack" + case application = "com.apple.product-type.application" + case applicationMessages = "com.apple.product-type.application.messages" + case appClip = "com.apple.product-type.application.on-demand-install-capable" + case bundle = "com.apple.product-type.bundle" + case externalTest = "com.apple.product-type.bundle.external-test" + case ocUnitTest = "com.apple.product-type.bundle.ocunit-test" + case uiTesting = "com.apple.product-type.bundle.ui-testing" + case unitTest = "com.apple.product-type.bundle.unit-test" + case extensionKitExtension = "com.apple.product-type.extensionkit-extension" + case framework = "com.apple.product-type.framework" + case staticFramework = "com.apple.product-type.framework.static" + case instrumentsPackage = "com.apple.product-type.instruments-package" + case kernelExtension = "com.apple.product-type.kernel-extension" + case ioKitKernelExtension = "com.apple.product-type.kernel-extension.iokit" + case dynamicLibrary = "com.apple.product-type.library.dynamic" + case staticLibrary = "com.apple.product-type.library.static" + case objectFile = "com.apple.product-type.objfile" + case pluginKitPlugin = "com.apple.product-type.pluginkit-plugin" + case packageProduct = "packageProduct" + case systemExtension = "com.apple.product-type.system-extension" + case tool = "com.apple.product-type.tool" + case hostBuild = "com.apple.product-type.tool.host-build" + case xpcService = "com.apple.product-type.xpc-service" + } + + public let productName: String + public let productType: ProductType + + private enum CodingKeys: CodingKey { + case guid, name, dependencies, buildConfigurations, type, frameworksBuildPhase, productTypeIdentifier, productReference, buildRules, buildPhases, impartedBuildProperties + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + let guid = try container.decode(GUID.self, forKey: .guid) + let name = try container.decode(String.self, forKey: .name) + let buildConfigurations = try container.decode([BuildConfiguration].self, forKey: .buildConfigurations) + let dependencies = try container.decode([TargetDependency].self, forKey: .dependencies) + let type = try container.decode(String.self, forKey: .type) + + let buildPhases: [BuildPhase] + let impartedBuildProperties: ImpartedBuildProperties + + if type == "packageProduct" { + self.productType = .packageProduct + self.productName = "" + let fwkBuildPhase = try container.decodeIfPresent(FrameworksBuildPhase.self, forKey: .frameworksBuildPhase) + buildPhases = fwkBuildPhase.map { [$0] } ?? [] + impartedBuildProperties = ImpartedBuildProperties(buildSettings: BuildSettings()) + } else if type == "standard" { + self.productType = try container.decode(ProductType.self, forKey: .productTypeIdentifier) + + let productReference = try container.decode([String: String].self, forKey: .productReference) + self.productName = productReference["name"]! + + let untypedBuildPhases = try container.decodeIfPresent([TypedObject].self, forKey: .buildPhases) ?? [] + var buildPhasesContainer = try container.nestedUnkeyedContainer(forKey: .buildPhases) + + buildPhases = try untypedBuildPhases.compactMap { + guard let type = $0.type else { + throw Error.decodingError("Expected type in build phase \($0)") + } + return try BuildPhase.decode(container: &buildPhasesContainer, type: type) + } + + impartedBuildProperties = try container.decodeIfPresent(ImpartedBuildProperties.self, forKey: .impartedBuildProperties) ?? .init(buildSettings: .init()) + } else { + throw Error.decodingError("Unhandled target type \(type)") + } + + super.init( + guid: guid, + name: name, + buildConfigurations: buildConfigurations, + buildPhases: buildPhases, + dependencies: dependencies, + impartedBuildSettings: impartedBuildProperties.buildSettings + ) + } + } + + /// Abstract base class for all build phases in a target. + public class BuildPhase: TypedObject { + static func decode(container: inout UnkeyedDecodingContainer, type: String) throws -> BuildPhase? { + switch type { + case HeadersBuildPhase.type: + return try container.decode(HeadersBuildPhase.self) + case SourcesBuildPhase.type: + return try container.decode(SourcesBuildPhase.self) + case FrameworksBuildPhase.type: + return try container.decode(FrameworksBuildPhase.self) + case ResourcesBuildPhase.type: + return try container.decode(ResourcesBuildPhase.self) + default: + logger.debug("unknown build phase: \(type)") + return nil + // TODO: we should probably handle these: + /* + case copyFiles = "com.apple.buildphase.copy-files" + case shellScript = "com.apple.buildphase.shell-script" + case sources = "com.apple.buildphase.sources"*/ + // throw Error.decodingError("unknown build phase \(type)") + } + } + + public let guid: GUID + public let buildFiles: [BuildFile] + + private enum CodingKeys: CodingKey { + case guid, buildFiles + } + + public required init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + guid = try container.decode(GUID.self, forKey: .guid) + buildFiles = try container.decode([BuildFile].self, forKey: .buildFiles) + + try super.init(from: decoder) + } + } + + /// A "headers" build phase, i.e. one that copies headers into a directory of the product, after suitable + /// processing. + public final class HeadersBuildPhase: BuildPhase { + override class var type: String { "com.apple.buildphase.headers" } + } + + /// A "sources" build phase, i.e. one that compiles sources and provides them to be linked into the executable code + /// of the product. + public final class SourcesBuildPhase: BuildPhase { + override class var type: String { "com.apple.buildphase.sources" } + } + + /// A "frameworks" build phase, i.e. one that links compiled code and libraries into the executable of the product. + public final class FrameworksBuildPhase: BuildPhase { + override class var type: String { "com.apple.buildphase.frameworks" } + } + + public final class ResourcesBuildPhase: BuildPhase { + override class var type: String { "com.apple.buildphase.resources" } + } + + /// A build file, representing the membership of either a file or target product reference in a build phase. + public struct BuildFile: Decodable { + public enum Reference { + case file(guid: PIF.GUID) + case target(guid: PIF.GUID) + } + + public enum HeaderVisibility: String, Decodable { + case `public` = "public" + case `private` = "private" + } + + public let guid: GUID + public let reference: Reference + public let headerVisibility: HeaderVisibility? + public let platformFilters: [PlatformFilter] + + private enum CodingKeys: CodingKey { + case guid, platformFilters, fileReference, targetReference, headerVisibility + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + guid = try container.decode(GUID.self, forKey: .guid) + platformFilters = try container.decodeIfPresent([PlatformFilter].self, forKey: .platformFilters) ?? [] + headerVisibility = try container.decodeIfPresent(HeaderVisibility.self, forKey: .headerVisibility) ?? nil + + if container.allKeys.contains(.fileReference) { + reference = try .file(guid: container.decode(GUID.self, forKey: .fileReference)) + } else if container.allKeys.contains(.targetReference) { + reference = .target(guid: try container.decode(GUID.self, forKey: .targetReference)) + } else { + throw Error.decodingError("Expected \(CodingKeys.fileReference) or \(CodingKeys.targetReference) in the keys") + } + } + } + + /// Represents a generic platform filter. + public struct PlatformFilter: Decodable, Equatable { + /// The name of the platform (`LC_BUILD_VERSION`). + /// + /// Example: macos, ios, watchos, tvos. + public let platform: String + + /// The name of the environment (`LC_BUILD_VERSION`) + /// + /// Example: simulator, maccatalyst. + public let environment: String? + } + + /// A build configuration, which is a named collection of build settings. + public struct BuildConfiguration: Decodable { + public let guid: GUID + public let name: String + public let buildSettings: BuildSettings + public let impartedBuildProperties: ImpartedBuildProperties + + private enum CodingKeys: CodingKey { + case guid, name, buildSettings, impartedBuildProperties + } + + public init(from decoder: any Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + guid = try container.decode(GUID.self, forKey: .guid) + name = try container.decode(String.self, forKey: .name) + buildSettings = try container.decode(BuildSettings.self, forKey: .buildSettings) + impartedBuildProperties = try container.decodeIfPresent(ImpartedBuildProperties.self, forKey: .impartedBuildProperties) ?? .init(buildSettings: .init()) + } + } + + public struct ImpartedBuildProperties: Decodable { + public let buildSettings: BuildSettings + } + + // swiftlint:disable identifier_name inclusive_language + /// A set of build settings, which is represented as a struct of optional build settings. This is not optimally + /// efficient, but it is great for code completion and type-checking. + public struct BuildSettings: Decodable { + public enum SingleValueSetting: String, Decodable { + case APPLICATION_EXTENSION_API_ONLY + case BUILT_PRODUCTS_DIR + case CLANG_CXX_LANGUAGE_STANDARD + case CLANG_ENABLE_MODULES + case CLANG_ENABLE_OBJC_ARC + case CODE_SIGNING_REQUIRED + case CODE_SIGN_IDENTITY + case COMBINE_HIDPI_IMAGES + case COPY_PHASE_STRIP + case DEBUG_INFORMATION_FORMAT + case DEFINES_MODULE + case DRIVERKIT_DEPLOYMENT_TARGET + case DYLIB_INSTALL_NAME_BASE + case EMBEDDED_CONTENT_CONTAINS_SWIFT + case ENABLE_NS_ASSERTIONS + case ENABLE_TESTABILITY + case ENABLE_TESTING_SEARCH_PATHS + case ENTITLEMENTS_REQUIRED + case EXECUTABLE_NAME + case GENERATE_INFOPLIST_FILE + case GCC_C_LANGUAGE_STANDARD + case GCC_OPTIMIZATION_LEVEL + case GENERATE_MASTER_OBJECT_FILE + case INFOPLIST_FILE + case IPHONEOS_DEPLOYMENT_TARGET + case KEEP_PRIVATE_EXTERNS + case CLANG_COVERAGE_MAPPING_LINKER_ARGS + case MACH_O_TYPE + case MACOSX_DEPLOYMENT_TARGET + case MODULEMAP_FILE + case MODULEMAP_FILE_CONTENTS + case MODULEMAP_PATH + case MODULE_CACHE_DIR + case ONLY_ACTIVE_ARCH + case PACKAGE_RESOURCE_BUNDLE_NAME + case PACKAGE_RESOURCE_TARGET_KIND + case PRODUCT_BUNDLE_IDENTIFIER + case PRODUCT_MODULE_NAME + case PRODUCT_NAME + case PROJECT_NAME + case SDKROOT + case SDK_VARIANT + case SKIP_INSTALL + case INSTALL_PATH + case SUPPORTS_MACCATALYST + case SWIFT_SERIALIZE_DEBUGGING_OPTIONS + case SWIFT_FORCE_STATIC_LINK_STDLIB + case SWIFT_FORCE_DYNAMIC_LINK_STDLIB + case SWIFT_INSTALL_OBJC_HEADER + case SWIFT_OBJC_INTERFACE_HEADER_NAME + case SWIFT_OBJC_INTERFACE_HEADER_DIR + case SWIFT_OPTIMIZATION_LEVEL + case SWIFT_VERSION + case TARGET_NAME + case TARGET_BUILD_DIR + case TVOS_DEPLOYMENT_TARGET + case USE_HEADERMAP + case USES_SWIFTPM_UNSAFE_FLAGS + case WATCHOS_DEPLOYMENT_TARGET + case XROS_DEPLOYMENT_TARGET + case MARKETING_VERSION + case CURRENT_PROJECT_VERSION + case SWIFT_EMIT_MODULE_INTERFACE + case GENERATE_RESOURCE_ACCESSORS + } + + public enum MultipleValueSetting: String, Decodable { + case EMBED_PACKAGE_RESOURCE_BUNDLE_NAMES + case FRAMEWORK_SEARCH_PATHS + case GCC_PREPROCESSOR_DEFINITIONS + case HEADER_SEARCH_PATHS + case LD_RUNPATH_SEARCH_PATHS + case LIBRARY_SEARCH_PATHS + case OTHER_CFLAGS + case OTHER_CPLUSPLUSFLAGS + case OTHER_LDFLAGS + case OTHER_LDRFLAGS + case OTHER_SWIFT_FLAGS + case PRELINK_FLAGS + case SPECIALIZATION_SDK_OPTIONS + case SUPPORTED_PLATFORMS + case SWIFT_ACTIVE_COMPILATION_CONDITIONS + case SWIFT_MODULE_ALIASES + } + // swiftlint:enable identifier_name inclusive_language + + public enum Platform: String, CaseIterable, Decodable { + case macOS = "macos" + case macCatalyst = "maccatalyst" + case iOS = "ios" + case tvOS = "tvos" + case watchOS = "watchos" + case driverKit = "driverkit" + case linux + } + + public private(set) var platformSpecificSingleValueSettings = [Platform: [SingleValueSetting: String]]() + public private(set) var platformSpecificMultipleValueSettings = [Platform: [MultipleValueSetting: [String]]]() + public private(set) var singleValueSettings: [SingleValueSetting: String] = [:] + public private(set) var multipleValueSettings: [MultipleValueSetting: [String]] = [:] + + public subscript(_ setting: SingleValueSetting) -> String? { + get { singleValueSettings[setting] } + set { singleValueSettings[setting] = newValue } + } + + public subscript(_ setting: SingleValueSetting, for platform: Platform) -> String? { + get { platformSpecificSingleValueSettings[platform]?[setting] } + set { platformSpecificSingleValueSettings[platform, default: [:]][setting] = newValue } + } + + public subscript(_ setting: SingleValueSetting, default defaultValue: @autoclosure () -> String) -> String { + get { singleValueSettings[setting, default: defaultValue()] } + set { singleValueSettings[setting] = newValue } + } + + public subscript(_ setting: MultipleValueSetting) -> [String]? { + get { multipleValueSettings[setting] } + set { multipleValueSettings[setting] = newValue } + } + + public subscript(_ setting: MultipleValueSetting, for platform: Platform) -> [String]? { + get { platformSpecificMultipleValueSettings[platform]?[setting] } + set { platformSpecificMultipleValueSettings[platform, default: [:]][setting] = newValue } + } + + public subscript( + _ setting: MultipleValueSetting, + default defaultValue: @autoclosure () -> [String] + ) -> [String] { + get { multipleValueSettings[setting, default: defaultValue()] } + set { multipleValueSettings[setting] = newValue } + } + + public subscript( + _ setting: MultipleValueSetting, + for platform: Platform, + default defaultValue: @autoclosure () -> [String] + ) -> [String] { + get { platformSpecificMultipleValueSettings[platform, default: [:]][setting, default: defaultValue()] } + set { platformSpecificMultipleValueSettings[platform, default: [:]][setting] = newValue } + } + + public init() {} + + private enum CodingKeys: CodingKey { + case platformSpecificSingleValueSettings, platformSpecificMultipleValueSettings, singleValueSettings, multipleValueSettings + } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + platformSpecificSingleValueSettings = try container.decodeIfPresent([Platform: [SingleValueSetting: String]].self, forKey: .platformSpecificSingleValueSettings) ?? .init() + platformSpecificMultipleValueSettings = try container.decodeIfPresent([Platform: [MultipleValueSetting: [String]]].self, forKey: .platformSpecificMultipleValueSettings) ?? .init() + singleValueSettings = try container.decodeIfPresent([SingleValueSetting: String].self, forKey: .singleValueSettings) ?? [:] + multipleValueSettings = try container.decodeIfPresent([MultipleValueSetting: [String]] .self, forKey: .multipleValueSettings) ?? [:] + } + } +} + +/// Represents a filetype recognized by the Xcode build system. +public struct XCBuildFileType: CaseIterable { + public static let xcdatamodeld: XCBuildFileType = XCBuildFileType( + fileType: "xcdatamodeld", + fileTypeIdentifier: "wrapper.xcdatamodeld" + ) + + public static let xcdatamodel: XCBuildFileType = XCBuildFileType( + fileType: "xcdatamodel", + fileTypeIdentifier: "wrapper.xcdatamodel" + ) + + public static let xcmappingmodel: XCBuildFileType = XCBuildFileType( + fileType: "xcmappingmodel", + fileTypeIdentifier: "wrapper.xcmappingmodel" + ) + + public static let allCases: [XCBuildFileType] = [ + .xcdatamodeld, + .xcdatamodel, + .xcmappingmodel + ] + + public let fileTypes: Set + public let fileTypeIdentifier: String + + private init(fileTypes: Set, fileTypeIdentifier: String) { + self.fileTypes = fileTypes + self.fileTypeIdentifier = fileTypeIdentifier + } + + private init(fileType: String, fileTypeIdentifier: String) { + self.init(fileTypes: [fileType], fileTypeIdentifier: fileTypeIdentifier) + } +} + +extension PIF.FileReference { + // fileprivate static func fileTypeIdentifier(forPath path: String) -> String { + // let pathExtension: String? + // if let path = try? URL(validating: path) { + // pathExtension = path.extension + // } else if let path = try? RelativePath(validating: path) { + // pathExtension = path.extension + // } else { + // pathExtension = nil + // } + + // switch pathExtension { + // case "a": + // return "archive.ar" + // case "s", "S": + // return "sourcecode.asm" + // case "c": + // return "sourcecode.c.c" + // case "cl": + // return "sourcecode.opencl" + // case "cpp", "cp", "cxx", "cc", "c++", "C", "tcc": + // return "sourcecode.cpp.cpp" + // case "d": + // return "sourcecode.dtrace" + // case "defs", "mig": + // return "sourcecode.mig" + // case "m": + // return "sourcecode.c.objc" + // case "mm", "M": + // return "sourcecode.cpp.objcpp" + // case "metal": + // return "sourcecode.metal" + // case "l", "lm", "lmm", "lpp", "lp", "lxx": + // return "sourcecode.lex" + // case "swift": + // return "sourcecode.swift" + // case "y", "ym", "ymm", "ypp", "yp", "yxx": + // return "sourcecode.yacc" + + // case "xcassets": + // return "folder.assetcatalog" + // case "xcstrings": + // return "text.json.xcstrings" + // case "storyboard": + // return "file.storyboard" + // case "xib": + // return "file.xib" + + // case "xcframework": + // return "wrapper.xcframework" + + // default: + // return pathExtension.flatMap({ pathExtension in + // XCBuildFileType.allCases.first(where: ({ $0.fileTypes.contains(pathExtension) })) + // })?.fileTypeIdentifier ?? "file" + // } + // } +} + +private struct UntypedTarget: Decodable { + struct TargetContents: Decodable { + let type: String + } + let contents: TargetContents +} +// swiftlint:enable file_length type_body_length diff --git a/PIF/Sources/PIFSupport/PIFSupport.swift b/PIF/Sources/PIFSupport/PIFSupport.swift new file mode 100644 index 0000000..7ca3b8e --- /dev/null +++ b/PIF/Sources/PIFSupport/PIFSupport.swift @@ -0,0 +1,70 @@ +import Foundation +import Logging + +/// Global logger for the module +var logger: Logger! + +/// PIFCacheParser is responsible for discovering the files in a PIF Cache and decoding them. +public class PIFCacheParser { + /// The path to the PIF Cache (in Xcode's DerivedData this is often under Build/Intermediates.noindex/XCBuildData/PIFCache) + private let cachePath: URL + /// The most recent workspace in the cache + public let workspace: PIF.Workspace + + public enum Error: Swift.Error { + /// A PIF Workspace was not found in the cache + case workspaceNotFound + } + + /// Creates an instance initialized with the cache data at the given path. + public init(cachePath: URL, logger log: Logger) throws { + logger = log + self.cachePath = cachePath + + let data = try Data(contentsOf: try Self.workspacePath(in: cachePath)) + workspace = try PIF.PIFDecoder(cache: cachePath).decode(PIF.Workspace.self, from: data) + } + + /// Finds the most recent workspace in the cache + /// - Throws: a `workspaceNotFound` error when a workspace is not found + /// - Returns: the path to the most recent workspace file + private static func workspacePath(in cachePath: URL) throws -> URL { + let workspaces = try FileManager.default.contentsOfDirectory( + at: cachePath.appendingPathComponent("workspace"), + includingPropertiesForKeys: nil + ) + .filter { $0.lastPathComponent.starts(with: "WORKSPACE@") } + .map { + ( + workspace: $0, + modificationDate: (try? FileManager.default.attributesOfItem(atPath: $0.path)[.modificationDate] as? Date) ?? Date() + ) + } + + if workspaces.isEmpty { + throw Error.workspaceNotFound + } else if workspaces.count == 1, let workspace = workspaces.first?.workspace { + return workspace + } + + // If multiple workspaces exist, it's because the something in the project changed between builds. Sort workspaces by the most recent. + return workspaces + .sorted(using: KeyPathComparator(\.modificationDate)) + .first! + .workspace + } +} + +extension PIF { + class PIFDecoder: JSONDecoder { + internal init(cache path: URL) { + super.init() + + userInfo[.pifCachePath] = path + } + } +} + +extension CodingUserInfoKey { + static let pifCachePath: CodingUserInfoKey = CodingUserInfoKey(rawValue: "PIFCachePath")! +} diff --git a/PIF/Sources/pif-parser/pif-parser.swift b/PIF/Sources/pif-parser/pif-parser.swift new file mode 100644 index 0000000..b7b0c8b --- /dev/null +++ b/PIF/Sources/pif-parser/pif-parser.swift @@ -0,0 +1,28 @@ +// +// pif-parser.swift +// +// +// Created by Thomas Hedderwick on 03/05/2024. +// + +import Foundation +import PIFSupport +import Logging + +@main +struct PIFCacheParser { + static func main() throws { + guard CommandLine.arguments.count == 2 else { + print("USAGE: \(CommandLine.arguments.first!) [PIFCache path]") + return + } + + let cachePath = URL(fileURLWithPath: CommandLine.arguments[1]) + let parser = try PIFSupport.PIFCacheParser(cachePath: cachePath, logger: .init(label: "com.veracode.pif-parser")) + let workspace = parser.workspace + + print("workspace: \(workspace.guid):") + print("projects: \(workspace.projects.map { $0.guid }.joined(separator: "\n"))\n") + print("targets: \(workspace.projects.flatMap { $0.targets }.map { $0.guid }.joined(separator: "\n"))") + } +} diff --git a/PIF/Tests/PIFTests/PIFTests.swift b/PIF/Tests/PIFTests/PIFTests.swift new file mode 100644 index 0000000..000a103 --- /dev/null +++ b/PIF/Tests/PIFTests/PIFTests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import PIF + +final class PIFTests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +} diff --git a/Package.swift b/Package.swift index 566f581..43e6f30 100644 --- a/Package.swift +++ b/Package.swift @@ -8,23 +8,43 @@ let package = Package( platforms: [ .macOS(.v12) ], + products: [ + .library(name: "DependencyGraph", targets: ["DependencyGraph"]), + .library(name: "LogHandlers", targets: ["LogHandlers"]), + .executable(name: "gen-ir", targets: ["gen-ir"]) + ], dependencies: [ // Dependencies declare other packages that this package depends on. // .package(url: /* package url */, from: "1.0.0"), .package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.0.0"), .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0"), .package(url: "https://github.com/apple/swift-docc-plugin", from: "1.0.0"), - .package(path: "PBXProjParser") + .package(path: "PIF") ], targets: [ // Targets are the basic building blocks of a package. A target can define a module or a test suite. // Targets can depend on other targets in this package, and on products in packages this package depends on. + .target( + name: "LogHandlers", + dependencies: [ + .product(name: "Logging", package: "swift-log") + ] + ), + .target( + name: "DependencyGraph", + dependencies: [ + .product(name: "Logging", package: "swift-log"), + .target(name: "LogHandlers") + ] + ), .executableTarget( name: "gen-ir", dependencies: [ .product(name: "ArgumentParser", package: "swift-argument-parser"), .product(name: "Logging", package: "swift-log"), - .product(name: "PBXProjParser", package: "PBXProjParser") + .product(name: "PIFSupport", package: "PIF"), + .target(name: "DependencyGraph"), + .target(name: "LogHandlers") ], path: "Sources/GenIR" ), diff --git a/Sources/DependencyGraph/DependencyGraph.swift b/Sources/DependencyGraph/DependencyGraph.swift new file mode 100644 index 0000000..25296fd --- /dev/null +++ b/Sources/DependencyGraph/DependencyGraph.swift @@ -0,0 +1,106 @@ +// +// DependencyGraph.swift +// +// +// Created by Thomas Hedderwick on 28/08/2023. +// + +import Foundation +import LogHandlers + +/// A directed graph that maps dependencies between values (nodes) via edges (directions between nodes) +public class DependencyGraph { + /// All the nodes in the graph + private(set) public var nodes = [String: Node]() + + /// Adds a node for the associated value to the graph + /// - Parameter value: the value associated with the node + /// - Returns: the node for the associated value. If the node already existed it is returned + func addNode(for value: Value) -> Node { + if let node = findNode(for: value) { + return node + } + + let node = Node(value) + nodes[value.valueName] = node + return node + } + + /// Finds the node associated with a value + /// - Parameter value: the value to look for + /// - Returns: the node for which the value is associated, if found + public func findNode(for value: Value) -> Node? { + nodes[value.valueName] + } + + /// Returns the dependency 'chain' for the value associated with a node in the graph using a depth-first search + /// - Parameter value: the associated value for a node to start the search with + /// - Returns: the chain of nodes, starting with the 'bottom' of the dependency subgraph + public func chain(for value: Value) -> [Node] { + guard let node = findNode(for: value) else { + logger.debug("Couldn't find node for value: \(value.valueName)") + return [] + } + + return depthFirstSearch(startingAt: node) + } + + /// Perform a depth-first search starting at the provided node + /// - Parameter node: the node whose children to search through + /// - Returns: an array of nodes ordered by a depth-first search approach + private func depthFirstSearch(startingAt node: Node) -> [Node] { + logger.debug("----\nSearching for: \(node.value.valueName)") + var visited = Set() + var chain = [Node]() + + /// Visits node dependencies and adds them to the chain from the bottom up + /// - Parameter node: the node to search through + func depthFirst(node: Node) { + logger.debug("inserting node: \(node.value.valueName)") + visited.insert(node) + + for edge in node.edges where edge.relationship == .dependency { + if visited.insert(edge.to).inserted { + logger.debug("edge to: \(edge.to)") + depthFirst(node: edge.to) + } else { + logger.debug("edge already in visited: \(visited)") + } + } + + logger.debug("appending to chain: \(node.value.valueName)") + chain.append(node) + } + + depthFirst(node: node) + return chain + } + + /// Writes a 'dot' graph file to disk + /// - Parameter path: the path to write the graph to + public func toDot(_ path: String) throws { + var contents = "digraph DependencyGraph {\n" + + for node in nodes.values { + for edge in node.edges.filter({ $0.relationship == .dependency }) { + contents.append("\"\(node.valueName)\" -> \"\(edge.to.valueName)\"\n") + } + } + + contents.append("}") + try contents.write(toFile: path, atomically: true, encoding: .utf8) + } +} + +extension DependencyGraph: CustomStringConvertible { + public var description: String { + var description = "" + + nodes + .forEach { + description += "[\($0)]" + } + + return description + } +} diff --git a/Sources/DependencyGraph/DependencyGraphBuilder.swift b/Sources/DependencyGraph/DependencyGraphBuilder.swift new file mode 100644 index 0000000..74ee422 --- /dev/null +++ b/Sources/DependencyGraph/DependencyGraphBuilder.swift @@ -0,0 +1,64 @@ +// +// DependencyGraphBuilder.swift +// +// +// Created by Thomas Hedderwick on 28/08/2023. +// + +import LogHandlers + +/// A type that provides dependency relationships between values +public protocol DependencyProviding { + /// A type that represents the value of a node + associatedtype Value: NodeValue + + /// Returns the direct dependencies for a given value + /// - Parameter value: the value to get dependencies for + /// - Returns: a list of dependencies + func dependencies(for value: Value) -> [Value] +} + +/// A builder for the DependencyGraph - you should _always_ use this class to build out the `DependencyGraph` +public class DependencyGraphBuilder where Value == Provider.Value { + /// The graph the builder will operate on + public typealias Graph = DependencyGraph + + /// The dependency provider + private let provider: Provider + + /// The built graph + public let graph = Graph() + + /// Inits the Graph Builder + /// - Parameters: + /// - provider: the dependency provider for the values + /// - values: the values to add to the graph + public init(provider: Provider, values: [Value]) { + self.provider = provider + values.forEach { add(value: $0) } + } + + /// Adds a value (and it's dependencies) to the graph + /// - Parameters: + /// - value: the value to add + @discardableResult + private func add(value: Value) -> Graph.Node { + if let existingNode = graph.findNode(for: value) { + return existingNode + } + + logger.debug("Adding value: \(value.valueName) to graph") + + let dependencies = provider.dependencies(for: value) + let node = graph.addNode(for: value) + + for dependency in dependencies { + let dependencyNode = add(value: dependency) + + node.add(edge: .init(to: dependencyNode, from: node, relationship: .dependency)) + dependencyNode.add(edge: .init(to: node, from: dependencyNode, relationship: .depender)) + } + + return node + } +} diff --git a/Sources/DependencyGraph/Edge.swift b/Sources/DependencyGraph/Edge.swift new file mode 100644 index 0000000..595f57d --- /dev/null +++ b/Sources/DependencyGraph/Edge.swift @@ -0,0 +1,59 @@ +// +// Edge.swift +// +// +// Created by Thomas Hedderwick on 28/08/2023. +// + +// swiftlint:disable identifier_name +/// An edge describes the relationship between two Nodes in a graph + +extension DependencyGraph { + /// An edge represents the connection between two nodes in the graph + public class Edge { + /// The source node + public let to: DependencyGraph.Node + /// The destination node + public let from: DependencyGraph.Node + /// The relationship between the two nodes + public let relationship: Relationship + + /// Description of the relationships between two nodes + public enum Relationship { + /// From depends on To + case dependency + /// From is a depender of To + case depender + } + + /// Initializes an edge between two nodes + /// - Parameters: + /// - to: the node this edge is pointing to + /// - from: the node this edge is pointing from + /// - relationship: the type of relationship this edge represents + init(to: DependencyGraph.Node, from: DependencyGraph.Node, relationship: Relationship) { + self.to = to + self.from = from + self.relationship = relationship + } + } +} + +extension DependencyGraph.Edge: Equatable { + public static func == (_ lhs: DependencyGraph.Edge, rhs: DependencyGraph.Edge) -> Bool { + lhs.to == rhs.to && lhs.from == rhs.from && lhs.relationship == rhs.relationship + } +} + +extension DependencyGraph.Edge: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(to) + hasher.combine(from) + hasher.combine(relationship) + } +} + +extension DependencyGraph.Edge: CustomStringConvertible { + public var description: String { "[Edge from \(from) to \(to) relationship: \(relationship)]"} +} +// swiftlint:enable identifier_name diff --git a/Sources/DependencyGraph/Node.swift b/Sources/DependencyGraph/Node.swift new file mode 100644 index 0000000..45f8456 --- /dev/null +++ b/Sources/DependencyGraph/Node.swift @@ -0,0 +1,70 @@ +// +// Node.swift +// +// +// Created by Thomas Hedderwick on 28/08/2023. +// + +import Foundation + +public protocol NodeValue: Hashable { + /// The name of this node, this should be unique + var valueName: String { get } +} + +extension DependencyGraph { + /// A node holds an associated value and edges to other nodes in the graph + public class Node { + /// The edges from and to this node + private(set) public var edges = [DependencyGraph.Edge]() + + /// The associated value of this node + public let value: Value + + /// The name of this node + public var valueName: String { + value.valueName + } + + /// Initializes a node with an associated value + /// - Parameter value: the value to associate with this node + init(_ value: Value) { + self.value = value + } + + /// Adds an edge to this node + /// - Parameter edge: the edge to add + func add(edge: DependencyGraph.Edge) { + if edges.filter({ $0.to.valueName == edge.to.valueName }).count == 0 { + edges.append(edge) + } + } + } +} + +extension DependencyGraph.Node: Equatable { + public static func == (_ lhs: DependencyGraph.Node, rhs: DependencyGraph.Node) -> Bool { + lhs.value == rhs.value && lhs.edges == rhs.edges + } +} + +extension DependencyGraph.Node: CustomStringConvertible { + public var description: String { + var description = "" + + if !edges.isEmpty { + description += "[Node: \(value.valueName), edges: \(edges.filter({ $0.relationship == .dependency }).map { $0.to.value.valueName})] " + } else { + description += "[Node: \(value.valueName)] " + } + + return description + } +} + +extension DependencyGraph.Node: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(valueName) + hasher.combine(value) + } +} diff --git a/Sources/GenIR/BuildCacheManipulator.swift b/Sources/GenIR/BuildCacheManipulator.swift index b9a2e7a..e8f8489 100644 --- a/Sources/GenIR/BuildCacheManipulator.swift +++ b/Sources/GenIR/BuildCacheManipulator.swift @@ -1,4 +1,5 @@ import Foundation +import LogHandlers /// Manipulates the build cache, if and when needed, to fix up potential invalidations struct BuildCacheManipulator { @@ -8,6 +9,7 @@ struct BuildCacheManipulator { /// Build settings used as part of the build private let buildSettings: [String: String] + /// Run without doing any cache manipulation private let dryRun: Bool /// Should we run the SKIP_INSTALL hack? @@ -21,6 +23,12 @@ struct BuildCacheManipulator { case tooManyDirectories(String) } + /// Creates an instance of the cache manipulator + /// - Parameters: + /// - buildCachePath: the build cache to operate on + /// - buildSettings: the project build settings + /// - archive: the path to the xcarchive produced as part of the build + /// - dryRun: should be a dry run? init(buildCachePath: URL, buildSettings: [String: String], archive: URL, dryRun: Bool) throws { self.buildCachePath = buildCachePath self.buildSettings = buildSettings @@ -35,9 +43,13 @@ struct BuildCacheManipulator { } } + /// Start the build cache manipulator func manipulate() throws { + guard !dryRun else { return } + if shouldDeploySkipInstallHack { let intermediatesPath = buildCachePath + .appendingPathComponent("Build") .appendingPathComponent("Intermediates.noindex") .appendingPathComponent("ArchiveIntermediates") @@ -67,7 +79,7 @@ struct BuildCacheManipulator { .appendingPathComponent("BuildProductsPath") guard - let archivePath = Self.findConfigurationDirectory(intermediatesBuildPath) + let archivePath = findConfigurationDirectory(intermediatesBuildPath) else { throw Error.directoryNotFound( "Couldn't find or determine a build configuration directory (expected inside of: \(intermediatesBuildPath))" @@ -78,17 +90,19 @@ struct BuildCacheManipulator { } } - // This is a hack. Turn away now. - // - // When archiving frameworks with the SKIP_INSTALL=NO setting, frameworks will be evicted (see below) from the build cache. - // This means when we rerun commands to generate IR, the frameworks no longer exist on disk, and we fail with linker errors. - // - // This is how the build cache is (roughly) laid out: - // - // * Build/Intermediates.noindex/ArchiveIntermediates//BuildProductsPath/- - // * this contains a set of symlinks to elsewhere in the build cache. These links remain in place, but the items they point to are removed - // - // The idea here is simple, attempt to update the symlinks so they point to valid framework product. + /// This is a hack. Turn away now. + /// + /// When archiving frameworks with the SKIP_INSTALL=NO setting, frameworks will be evicted (see below) from the build cache. + /// This means when we rerun commands to generate IR, the frameworks no longer exist on disk, and we fail with linker errors. + /// + /// This is how the build cache is (roughly) laid out: + /// + /// * Build/Intermediates.noindex/ArchiveIntermediates//BuildProductsPath/- + /// * this contains a set of symlinks to elsewhere in the build cache. These links remain in place, but the items they point to are removed + /// + /// The idea here is simple, attempt to update the symlinks so they point to valid framework product. + /// + /// - Parameter archiveBuildProductsPath: build products path (see description) private func skipInstallHack(_ archiveBuildProductsPath: URL) throws { let symlinksToUpdate = FileManager.default.filteredContents(of: archiveBuildProductsPath) { $0.lastPathComponent.hasSuffix("framework") @@ -117,10 +131,11 @@ struct BuildCacheManipulator { } } + /// TODO: This could be more sensible and get the build configuration from the log and match that to a configuration in the PIF Cache /// Tries to find the xcode build configuration directory path inside the given path /// - Parameter path: the path to search - /// - Returns: - private static func findConfigurationDirectory(_ path: URL) -> URL? { + /// - Returns: the path to the build configuration directory, if found + private func findConfigurationDirectory(_ path: URL) -> URL? { let folders = (try? FileManager.default.directories(at: path, recursive: false)) ?? [] guard folders.count != 0 else { diff --git a/Sources/GenIR/CompilerCommandRunner.swift b/Sources/GenIR/CompilerCommandRunner.swift index bec6c29..6e25247 100644 --- a/Sources/GenIR/CompilerCommandRunner.swift +++ b/Sources/GenIR/CompilerCommandRunner.swift @@ -6,8 +6,7 @@ // import Foundation -import Logging -import PBXProjParser +import LogHandlers /// A model of the contents of an output file map json typealias OutputFileMap = [String: [String: String]] @@ -18,23 +17,28 @@ typealias OutputFileMap = [String: [String: String]] /// /// > clang will emit LLVM BC to the current working directory in a named file. In this case, the runner will move the files from temporary storage to the output location struct CompilerCommandRunner { + enum Error: Swift.Error { + /// Command runner failed to parse the command for the required information + case failedToParse(String) + } + /// The directory to place the LLVM BC output private let output: URL + /// The cache manipulator, required to do fix ups on the build cache in very specific circumstances private let buildCacheManipulator: BuildCacheManipulator + /// Manager used to access the file system private let fileManager = FileManager.default - enum Error: Swift.Error { - /// Command runner failed to parse the command for the required information - case failedToParse(String) - } - + /// Run without running the commands private let dryRun: Bool - /// Initializes a runner + /// Initializes the runner /// - Parameters: /// - output: The location to place the resulting LLVM IR + /// - buildCacheManipulator: the cache manipulator to perform fixups with + /// - dryRun: should run in dry run mode? init(output: URL, buildCacheManipulator: BuildCacheManipulator, dryRun: Bool) { self.output = output self.dryRun = dryRun @@ -42,28 +46,29 @@ struct CompilerCommandRunner { } /// Starts the runner - func run(targets: Targets) throws { + /// - Parameter targets: the targets holding the commands to run + func run(targets: [Target], commands: [String: [CompilerCommand]]) throws { // Quick, do a hack! try buildCacheManipulator.manipulate() - let tempDirectory = try fileManager.temporaryDirectory(named: "gen-ir-\(UUID().uuidString)") - defer { try? fileManager.removeItem(at: tempDirectory) } - logger.debug("Using temp directory as working directory: \(tempDirectory.filePath)") - - let totalCommands = targets.totalCommandCount + let totalCommands = commands + .map { $0.value.count } + .reduce(0, +) logger.info("Total commands to run: \(totalCommands)") var totalModulesRun = 0 - for target in targets { + for target in targets.filter({ $0.isBuildable }) { + guard let targetCommands = commands[target.name] else { + continue + } + logger.info("Operating on target: \(target.name). Total modules processed: \(totalModulesRun)") - totalModulesRun += try run(commands: target.commands, for: target.nameForOutput, at: tempDirectory) + totalModulesRun += try run(commands: targetCommands, for: target.productName, at: output) } - try fileManager.moveItemReplacingExisting(from: tempDirectory, to: output) - - let uniqueModules = try fileManager.files(at: output, withSuffix: ".bc").count + let uniqueModules = Set(try fileManager.files(at: output, withSuffix: ".bc")).count logger.info("Finished compiling all targets. Unique modules: \(uniqueModules)") } @@ -163,7 +168,7 @@ struct CompilerCommandRunner { /// Parses, and corrects, the executable name and arguments for a given command. /// - Parameter command: The command to parse and correct /// - Returns: A tuple of executable name and an array of arguments - private func parse(command: CompilerCommand) throws -> (String, [String]) { + private func parse(command: CompilerCommand) throws -> (executable: String, arguments: [String]) { let fixed = fixup(command: command.command) let (executable, arguments) = try split(command: fixed) let fixedArguments = fixup(arguments: arguments, for: command.compiler) diff --git a/Sources/GenIR/Dependency Graph/DependencyGraph.swift b/Sources/GenIR/Dependency Graph/DependencyGraph.swift deleted file mode 100644 index b2d4098..0000000 --- a/Sources/GenIR/Dependency Graph/DependencyGraph.swift +++ /dev/null @@ -1,103 +0,0 @@ -// -// DependencyGraph.swift -// -// -// Created by Thomas Hedderwick on 28/08/2023. -// - -import Foundation - -/// A directed graph that maps dependencies between targets (nodes) via edges (directions between nodes) -class DependencyGraph { - /// All the nodes in the graph - private(set) var nodes: [Node] = [] - - /// Adds a target to the graph - /// - Parameter target: the target to add - /// - Returns: the node added, iff a node for this target didn't already exist in the graph - func addNode(target: Target) -> Node? { - if findNode(for: target) != nil { - return nil - } - - let node = Node(target) - nodes.append(node) - return node - } - - /// Finds a target's node in the graph - /// - Parameter target: the target to look for - /// - Returns: the node for the given target, if found - func findNode(for target: Target) -> Node? { - nodes.first(where: { $0.target == target }) - } - - /// Builds a dependency 'chain' for a target using a depth-first search - /// - Parameter target: the target to get a chain for - /// - Returns: the chain of nodes, starting - func chain(for target: Target) -> [Node] { - guard let targetNode = findNode(for: target) else { - logger.debug("Couldn't find node for target: \(target.name)") - return [] - } - - return depthFirstSearch(startingAt: targetNode) - } - - func toDot(_ path: String) throws { - var contents = "digraph DependencyGraph {\n" - - for node in nodes { - for edge in node.edges.filter({ $0.relationship == .dependency }) { - contents.append("\(node.name.replacingOccurrences(of: "-", with: "_")) -> \(edge.to.name.replacingOccurrences(of: "-", with: "_"))\n") - } - } - - contents.append("}") - try contents.write(toFile: path, atomically: true, encoding: .utf8) - } - - /// Perform a depth-first search starting at the provided node - /// - Parameter node: the node whose children to search through - /// - Returns: an array of nodes ordered by a depth-first search approach - private func depthFirstSearch(startingAt node: Node) -> [Node] { - logger.debug("----\nSearching for: \(node.target.name)") - var visited = Set() - var chain = [Node]() - - func depthFirst(node: Node) { - logger.debug("inserting node: \(node.target.name)") - visited.insert(node) - logger.debug("visited: \(visited)") - - for edge in node.edges { - logger.debug("edge to: \(edge.to)") - if visited.insert(edge.to).inserted { - logger.debug("inserted, recursing") - depthFirst(node: edge.to) - } else { - logger.debug("edge already in visited: \(visited)") - } - } - - logger.debug("appending to chain: \(node.target.name)") - chain.append(node) - } - - depthFirst(node: node) - return chain - } -} - -extension DependencyGraph: CustomStringConvertible { - var description: String { - var description = "" - - nodes - .forEach { - description += "[\($0)]" - } - - return description - } -} diff --git a/Sources/GenIR/Dependency Graph/DependencyGraphBuilder.swift b/Sources/GenIR/Dependency Graph/DependencyGraphBuilder.swift deleted file mode 100644 index e2985d0..0000000 --- a/Sources/GenIR/Dependency Graph/DependencyGraphBuilder.swift +++ /dev/null @@ -1,56 +0,0 @@ -// -// DependencyGraphBuilder.swift -// -// -// Created by Thomas Hedderwick on 28/08/2023. -// - -class DependencyGraphBuilder { - /// Builds a dependency graph for the given collection of targets - /// - Parameter targets: the targets to build a graph for - /// - Returns: the dependency graph - static func build(targets: Targets) -> DependencyGraph { - let graph = DependencyGraph() - - targets.forEach { - add(target: $0, in: targets, to: graph) - } - - return graph - } - - /// Adds a target (and it's dependencies) to the graph - /// - Parameters: - /// - graph: the graph to add a target to - /// - target: the target to add - /// - targets: the targets containing the target and it's dependencies - static func add(target: Target, in targets: Targets, to graph: DependencyGraph) { - logger.debug("Adding target: \(target.name) to graph") - - guard let node = graph.addNode(target: target) else { - logger.debug("Already inserted node: \(target.name). Skipping.") - return - } - - let dependencies = targets.calculateDependencies(for: target) - - for dependency in dependencies { - guard let dependencyTarget = targets.target(for: dependency) else { - logger.debug("Couldn't lookup dependency in targets: \(dependency)") - continue - } - - add(target: dependencyTarget, in: targets, to: graph) - - guard let dependencyNode = graph.findNode(for: dependencyTarget) else { - logger.debug("Couldn't find node for target (\(dependencyTarget.name)) even though it was just inserted?") - continue - } - - // We add both an edge from and to the node and dependency - this way we can do bidirectional - // searches for a given node and see what it's dependencies are and who depends on it - node.add(edge: .init(to: dependencyNode, from: node, relationship: .dependency)) - dependencyNode.add(edge: .init(to: node, from: dependencyNode, relationship: .depender)) - } - } -} diff --git a/Sources/GenIR/Dependency Graph/Edge.swift b/Sources/GenIR/Dependency Graph/Edge.swift deleted file mode 100644 index 4e62019..0000000 --- a/Sources/GenIR/Dependency Graph/Edge.swift +++ /dev/null @@ -1,42 +0,0 @@ -// -// Edge.swift -// -// -// Created by Thomas Hedderwick on 28/08/2023. -// - -// swiftlint:disable identifier_name -/// An edge describes the relationship between two Nodes in a graph -class Edge { - /// The source node - let to: Node - /// The destination node - let from: Node - /// The relationship between the two nodes - let relationship: Relationship - - /// Description of the relationships between two nodes - enum Relationship { - /// From depends on To - case dependency - /// From is a depender of To - case depender - } - - init(to: Node, from: Node, relationship: Relationship) { - self.to = to - self.from = from - self.relationship = relationship - } -} - -extension Edge: Equatable { - static func == (_ lhs: Edge, rhs: Edge) -> Bool { - lhs.to == rhs.to && lhs.from == rhs.from && lhs.relationship == rhs.relationship - } -} - -extension Edge: CustomStringConvertible { - var description: String { "[Edge from \(from) to \(to) relationship: \(relationship)]"} -} -// swiftlint:enable identifier_name diff --git a/Sources/GenIR/Dependency Graph/Node.swift b/Sources/GenIR/Dependency Graph/Node.swift deleted file mode 100644 index dd9a8c1..0000000 --- a/Sources/GenIR/Dependency Graph/Node.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// Node.swift -// -// -// Created by Thomas Hedderwick on 28/08/2023. -// - -import Foundation - -class Node { - /// The edges from and to this node - private(set) var edges = [Edge]() - /// The target this node represents - let target: Target - /// The name of this node, mostly used for debugging and printing - let name: String - - init(_ target: Target) { - self.target = target - self.name = target.name - } - - /// Adds an edge to this node - /// - Parameter edge: the edge to add - func add(edge: Edge) { - if edges.filter({ $0.to.name == edge.to.name }).count == 0 { - edges.append(edge) - } - } -} - -extension Node: Equatable { - static func == (_ lhs: Node, rhs: Node) -> Bool { - lhs.target == rhs.target && lhs.edges == rhs.edges - } -} - -extension Node: CustomStringConvertible { - var description: String { - var description = "" - - if !edges.isEmpty { - description += "[Node: \(target.name), edges: \(edges.filter({ $0.relationship == .dependency }).map { $0.to.target.name})] " - } else { - description += "[Node: \(target.name)] " - } - - return description - } -} - -extension Node: Hashable { - func hash(into hasher: inout Hasher) { - hasher.combine(name) - hasher.combine(target) - } -} diff --git a/Sources/GenIR/Extensions/FileManager+Extension.swift b/Sources/GenIR/Extensions/FileManager+Extension.swift index 76a544c..b85b6b4 100644 --- a/Sources/GenIR/Extensions/FileManager+Extension.swift +++ b/Sources/GenIR/Extensions/FileManager+Extension.swift @@ -102,27 +102,6 @@ extension FileManager { try moveItem(at: source, to: destination) } - /// Copies an item, merging with the existing path. Replacement of existing paths is performed if specified. - /// - Parameters: - /// - source: the item to copy - /// - destination: the destination of the copy - /// - replacing: should existing items be replaced? - func copyItemMerging(at source: URL, to destination: URL, replacing: Bool = false) throws { - let sourceFiles = try contentsOfDirectory(at: source, includingPropertiesForKeys: nil) - - for sourceFile in sourceFiles { - let path = destination.appendingPathComponent(sourceFile.lastPathComponent) - - if replacing && fileExists(atPath: path.filePath) { - try removeItem(at: path) - } - - let destinationFile = uniqueFilename(directory: destination, filename: sourceFile.lastPathComponent) - - try copyItem(at: sourceFile, to: destinationFile) - } - } - /// Generates a unique filename for a file at the given directory. This attempts to emulates finders style of appending a 'version' number at the end of the filename /// - Parameters: /// - directory: the directory the file would exist in diff --git a/Sources/GenIR/Extensions/Process+Extension.swift b/Sources/GenIR/Extensions/Process+Extension.swift index a5df895..c1d2c8e 100644 --- a/Sources/GenIR/Extensions/Process+Extension.swift +++ b/Sources/GenIR/Extensions/Process+Extension.swift @@ -8,7 +8,7 @@ import Foundation extension Process { - /// Presents the result of a Process + /// Represents the result of a Process struct ReturnValue { /// The stdout output of the process, if there was any let stdout: String? @@ -17,17 +17,22 @@ extension Process { /// The return code of the process let code: Int32 + /// Initializes a ReturnValue + /// - Parameters: + /// - stdout: the standard output + /// - stderr: the standard error + /// - code: the exit code init(stdout: String?, stderr: String?, code: Int32) { - if let stdout, stdout.isEmpty { - self.stdout = nil + self.stdout = if let stdout, stdout.isEmpty { + nil } else { - self.stdout = stdout + stdout } - if let stderr, stderr.isEmpty { - self.stderr = nil + self.stderr = if let stderr, stderr.isEmpty { + nil } else { - self.stderr = stderr + stderr } self.code = code @@ -54,7 +59,16 @@ extension Process { let process = Process() - let executable = command.replacingOccurrences(of: "\\", with: "") + let executable: String + let args: [String] + + if command.starts(with: ".") || command.starts(with: "/") { + executable = command.replacingOccurrences(of: "\\", with: "") + args = arguments + } else { + executable = "/usr/bin/env" + args = [command] + arguments + } if #available(macOS 10.13, *) { process.executableURL = executable.fileURL @@ -62,7 +76,7 @@ extension Process { process.launchPath = executable } - process.arguments = arguments.map { $0.replacingOccurrences(of: "\\", with: "") } + process.arguments = args.map { $0.replacingOccurrences(of: "\\", with: "") } process.standardOutput = stdoutPipe process.standardError = stderrPipe process.standardInput = FileHandle.nullDevice diff --git a/Sources/GenIR/Extensions/String+Extension.swift b/Sources/GenIR/Extensions/String+Extension.swift index ca6e499..4f6df5b 100644 --- a/Sources/GenIR/Extensions/String+Extension.swift +++ b/Sources/GenIR/Extensions/String+Extension.swift @@ -61,16 +61,6 @@ extension String { return results } - - func deletingPathExtension() -> String { - if let index = self.firstIndexWithEscapes(of: ".") { - var newSelf = self - newSelf.removeSubrange(index.. \ log.txt - $ \(programName) log.txt output_folder/ --project-path MyProject.xcodeproj + $ \(programName) log.txt x.xcarchive/ Example with pipe: $ xcodebuild clean && xcodebuild build -project MyProject.xcodeproj -configuration Debug -scheme MyScheme 2>&1 \ - | \(programName) - output_folder/ --project-path MyProject.xcodeproj + | \(programName) - x.xcarchive/ """, version: "v\(Versions.version)" ) @@ -45,8 +44,8 @@ struct IREmitterCommand: ParsableCommand { var xcarchivePath: URL /// Path to xcodeproj or xcworkspace file - @Option(help: "Path to your Xcode Project or Workspace file") - var projectPath: URL! + @Option(help: "DEPRECATED: This Option is deprecated and will go away in a future version.") + var projectPath: URL? /// Enables enhanced debug logging @Flag(help: "Enables debug level logging") @@ -63,17 +62,13 @@ struct IREmitterCommand: ParsableCommand { var dumpDependencyGraph = false mutating func validate() throws { + // This will run before run() so set this here if debug { logger.logLevel = .debug } - // Version 0.2.x and below didn't require a project. Attempt to default this value if we can - if projectPath == nil { - projectPath = try findProjectPath() - } - - if !FileManager.default.fileExists(atPath: projectPath.filePath) { - throw ValidationError("Project doesn't exist at path: \(projectPath.filePath)") + if projectPath != nil { + logger.warning("--project-path has been deprecated and will go away in a future version. Please remove it from your invocation.") } // Version 0.2.x and below allowed the output folder to be any arbitrary folder. @@ -94,7 +89,6 @@ struct IREmitterCommand: ParsableCommand { mutating func run() throws { try run( - project: projectPath, log: logPath, archive: xcarchivePath, level: logger.logLevel, @@ -104,19 +98,39 @@ struct IREmitterCommand: ParsableCommand { } mutating func run( - project: URL, log: String, archive: URL, level: Logger.Level, dryRun: Bool, dumpDependencyGraph: Bool ) throws { + logger.logLevel = level let output = archive.appendingPathComponent("IR") - let project = try ProjectParser(path: project, logLevel: level) - var targets = Targets(for: project) let log = try logParser(for: log) - try log.parse(&targets) + try log.parse() + + // Find and parse the PIF cache + let pifCache = try PIFCache(buildCache: log.buildCachePath) + let targets = pifCache.targets.map { Target(from: $0) } + + let builder = DependencyGraphBuilder( + provider: .init(targets: targets, cache: pifCache), + values: targets + ) + let graph = builder.graph + + if dumpDependencyGraph { + do { + try graph.toDot(output + .deletingLastPathComponent() + .appendingPathComponent("graph.dot") + .filePath + ) + } catch { + logger.error("toDot error: \(error)") + } + } let buildCacheManipulator = try BuildCacheManipulator( buildCachePath: log.buildCachePath, @@ -125,20 +139,24 @@ struct IREmitterCommand: ParsableCommand { dryRun: dryRun ) + let tempDirectory = try FileManager.default.temporaryDirectory(named: "gen-ir-\(UUID().uuidString)") + defer { try? FileManager.default.removeItem(at: tempDirectory) } + logger.info("Using temp directory as working directory: \(tempDirectory)") + let runner = CompilerCommandRunner( - output: output, + output: tempDirectory, buildCacheManipulator: buildCacheManipulator, dryRun: dryRun ) - try runner.run(targets: targets) + try runner.run(targets: targets, commands: log.targetCommands) let postprocessor = try OutputPostprocessor( archive: archive, - output: output, - targets: targets, - dumpGraph: dumpDependencyGraph + build: tempDirectory, + graph: graph ) - try postprocessor.process(targets: &targets) + + try postprocessor.process() } /// Gets an `XcodeLogParser` for a path @@ -159,8 +177,6 @@ struct IREmitterCommand: ParsableCommand { /// Reads stdin until an EOF is found /// - Returns: An array of Strings representing stdin split by lines private func readStdin() throws -> [String] { - logger.info("Collating input via pipe") - var results = [String]() while let line = readLine() { @@ -178,40 +194,10 @@ struct IREmitterCommand: ParsableCommand { print("\n\n") } - logger.info("Finished reading from pipe") - return results } } -extension IREmitterCommand { - /// Attempt to automatically determine the Xcode workspace or project path - /// - Returns: the path to the first xcworkspace or xcodeproj found in the current directory - private func findProjectPath() throws -> URL { - let cwd = FileManager.default.currentDirectoryPath.fileURL - // First, xcworkspace, then xcodeproj - let xcworkspace = try FileManager.default.directories(at: cwd, recursive: false) - .filter { $0.pathExtension == "xcworkspace" } - - if xcworkspace.count == 1 { - return xcworkspace[0] - } - - let xcodeproj = try FileManager.default.directories(at: cwd, recursive: false) - .filter { $0.pathExtension == "xcodeproj" } - - if xcodeproj.count == 1 { - return xcodeproj[0] - } - - throw ValidationError( - """ - Couldn't automatically determine path to xcodeproj or xcworkspace. Please use --project-path to provide it. - """ - ) - } -} - extension URL: ExpressibleByArgument { public init?(argument: String) { self = argument.fileURL.absoluteURL diff --git a/Sources/GenIR/OutputPostprocessor.swift b/Sources/GenIR/OutputPostprocessor.swift index 643f8c2..790c840 100644 --- a/Sources/GenIR/OutputPostprocessor.swift +++ b/Sources/GenIR/OutputPostprocessor.swift @@ -6,127 +6,106 @@ // import Foundation -import PBXProjParser - -private typealias SizeAndCreation = (Int, Date) +import DependencyGraph +import LogHandlers /// The `OutputPostprocessor` is responsible for trying to match the IR output of the `CompilerCommandRunner` with the products in the `xcarchive`. /// The `CompilerCommandRunner` will output IR with it's product name, but doesn't take into account the linking of products into each other. /// The `OutputPostprocessor` attempts to remedy this by using the `ProjectParser` to detect dependencies between products AND /// parsing the `xcarchive` to determine if something was statically linked, and if so, copies the IR for that product into the linker's IR folder. class OutputPostprocessor { - /// The to the output IR folders that will be processed - let output: URL - /// The archive path, this should be the parent path of `output` let archive: URL /// Mapping of dynamic dependencies (inside the xcarchive) to their paths on disk - private let dynamicDependencyToPath: [String: URL] + private lazy var dynamicDependencyToPath: [String: URL] = { + dynamicDependencies(in: archive) + }() - private let graph: DependencyGraph + /// A dependency graph containing the targets in the output archive + private let graph: DependencyGraph - private var seenConflictingFiles: [URL: [SizeAndCreation]] = [:] + /// The targets in this archive + private let targets: [Target] - private let manager: FileManager = .default + /// Path to the folder containing build artifacts + private let build: URL - init(archive: URL, output: URL, targets: Targets, dumpGraph: Bool) throws { - self.output = output - self.archive = archive + /// The manager to use for file system access + private let manager: FileManager = .default - dynamicDependencyToPath = dynamicDependencies(in: self.archive) + /// Cache of all files that have been copied to the IR output folder. + /// This maps a destination to a set of source URLs. This is used to determine if a file has already + /// been copied without having to waste cycles comparing file contents. If multiple source files + /// map to the same destination, then they will be given unique file names when copied to the IR folder. + private var copiedFiles: [URL: Set] = [:] - graph = DependencyGraphBuilder.build(targets: targets) - if dumpGraph { - do { - try graph.toDot(output.appendingPathComponent("graph.dot").filePath) - } catch { - logger.error("toDot error: \(error)") - } - } + /// Initializes the postprocessor + init(archive: URL, build: URL, graph: DependencyGraph) throws { + self.archive = archive + self.build = build + self.graph = graph + self.targets = graph.nodes.map { $0.value.value } } /// Starts the OutputPostprocessor - /// - Parameter targets: the targets to operate on - func process(targets: inout Targets) throws { - try manager.directories(at: output, recursive: false) - .forEach { path in - let product = path.lastPathComponent.deletingPathExtension() - - guard let target = targets.target(for: product) else { - logger.error("Failed to look up target for product: \(product)") - return - } + func process() throws { + let nodes = targets.compactMap { graph.findNode(for: $0) } + let output = archive.appendingPathComponent("IR") + + try manager.createDirectory(at: output, withIntermediateDirectories: false) - target.irFolderPath = path + for node in nodes { + let dependers = node.edges.filter { $0.relationship == .depender } + + guard dynamicDependencyToPath[node.value.productName] != nil || (dependers.count == 0 && !node.value.isSwiftPackage) else { + continue } - // TODO: remove 'static' deps so we don't duplicate them in the submission? - _ = try manager.directories(at: output, recursive: false) - .flatMap { path in - let product = path.lastPathComponent.deletingPathExtension() + let irDirectory = output.appendingPathComponent(node.value.productName) + let buildDirectory = build.appendingPathComponent(node.value.productName) - guard let target = targets.target(for: product) else { - logger.error("Failed to look up target for product: \(product)") - return Set() - } + logger.debug("Copying \(node.value.guid) with name \(node.value.productName)") - return try process(target: target) + // If there is a build directory for this target then copy the artifacts over to the IR + // folder. Otherwise we will create an empty directory and that will contain the artifacts + // of the dependency chain. + if manager.directoryExists(at: buildDirectory) { + try manager.copyItem(at: buildDirectory, to: irDirectory) + } else { + try manager.createDirectory(at: irDirectory, withIntermediateDirectories: false) } + + // Copy over this target's static dependencies + var processed: Set = [] + try copyDependencies(for: node.value, to: irDirectory, processed: &processed) + } } - /// Processes an individual target - /// - Parameters: - /// - target: the target to process - /// - path: the output path - /// - Returns: - private func process( - target: Target - ) throws -> Set { - let chain = graph.chain(for: target) - - logger.debug("Chain for target: \(target.nameForOutput):\n") - chain.forEach { logger.debug("\($0)") } - - // We want to process the chain, visiting each node _shallowly_ and copy it's dependencies into it's parent - var processed = Set() - - for node in chain { - logger.debug("Processing Node: \(node.name)") - // Ensure node is not a dynamic dependency - guard dynamicDependencyToPath[node.target.nameForOutput] == nil else { continue } - - // Only care about moving dependencies into dependers - check this node's edges to dependent relationships - let dependers = node.edges - .filter { $0.relationship == .depender } - .map { $0.to } - - // Move node's IR into depender's IR folder - guard let nodeFolderPath = node.target.irFolderPath else { - logger.debug("IR folder for node: \(node) is nil") - continue - } + private func copyDependencies(for target: Target, to irDirectory: URL, processed: inout Set) throws { + guard processed.insert(target).inserted else { + return + } - for depender in dependers { - guard let dependerFolderPath = depender.target.irFolderPath else { - logger.debug("IR folder for depender node \(depender) is nil") - continue - } + for node in graph.chain(for: target) { + logger.debug("Processing Node: \(node.valueName)") + + // Do not copy dynamic dependencies + guard dynamicDependencyToPath[node.value.productName] == nil else { continue } - // Move the dependency IR (the node) to the depender (the thing depending on this node) + try copyDependencies(for: node.value, to: irDirectory, processed: &processed) + + let buildDirectory = build.appendingPathComponent(node.value.productName) + if manager.directoryExists(at: buildDirectory) { do { - try copyContentsOfDirectoryMergingDifferingFiles(at: nodeFolderPath, to: dependerFolderPath) + try copyContentsOfDirectoryMergingDifferingFiles(at: buildDirectory, to: irDirectory) } catch { logger.debug("Copy error: \(error)") } - processed.insert(nodeFolderPath) } } - - return processed } - // TODO: Write tests for this. /// Copies the contents of a directory from source to destination, merging files that share the same name but differ in attributes /// - Parameters: /// - source: the source directory to copy the contents of @@ -134,121 +113,76 @@ class OutputPostprocessor { func copyContentsOfDirectoryMergingDifferingFiles(at source: URL, to destination: URL) throws { let files = try manager.contentsOfDirectory(at: source, includingPropertiesForKeys: nil) - // Get two arrays of file paths of the source and destination file where: - // 1) destination already exists - // 2) destination doesn't already exist - typealias SourceAndDestination = (source: URL, destination: URL) - let (existing, nonexisting) = files + let sourceAndDestinations = files .map { ( source: source.appendingPathComponent($0.lastPathComponent), destination: destination.appendingPathComponent($0.lastPathComponent) ) } - .reduce(into: (existing: [SourceAndDestination](), nonexisting: [SourceAndDestination]())) { (partialResult, sourceAndDestination) in - if manager.fileExists(atPath: sourceAndDestination.destination.filePath) { - partialResult.existing.append(sourceAndDestination) - } else { - partialResult.nonexisting.append(sourceAndDestination) - } - } - - // Nonexisting files are easy - just move them - try nonexisting - .forEach { (source, destination) in - try manager.copyItem(at: source, to: destination) - } - - // Existing files require some additional checks and renaming - try existing - .forEach { - try copyFileUniquingConflictingFiles(source: $0.source, destination: $0.destination) - } - } - /// Copies a file, uniquing the path if it conflicts, _if_ the files they conflict with aren't the same size - /// - Parameters: - /// - source: source file path - /// - destination: destination file path - private func copyFileUniquingConflictingFiles(source: URL, destination: URL) throws { - let destinationAttributes = try manager.attributesOfItem(atPath: destination.filePath) - let sourceAttributes = try manager.attributesOfItem(atPath: source.filePath) - - guard - let destinationSize = destinationAttributes[.size] as? Int, - let sourceSize = sourceAttributes[.size] as? Int, - let destinationCreatedDate = destinationAttributes[.creationDate] as? Date, - let sourceCreatedDate = sourceAttributes[.creationDate] as? Date - else { - logger.debug("Failed to get attributes for source: \(source) & destination: \(destination)") - return - } + for (source, destination) in sourceAndDestinations where copiedFiles[destination, default: []].insert(source).inserted { + // Avoid overwriting existing files with the same name. + let uniqueDestinationURL = manager.uniqueFilename(directory: destination.deletingLastPathComponent(), filename: source.lastPathComponent) - let uniqueDestinationURL = manager.uniqueFilename(directory: destination.deletingLastPathComponent(), filename: source.lastPathComponent) - - if seenConflictingFiles[source] == nil { - seenConflictingFiles[source] = [(sourceSize, sourceCreatedDate)] + logger.debug("Copying source \(source) to destination: \(uniqueDestinationURL)") + try manager.copyItem(at: source, to: uniqueDestinationURL) } + } - for (size, date) in seenConflictingFiles[source]! where size == destinationSize && date == destinationCreatedDate { - return + /// Returns a map of dynamic objects in the provided path + /// - Parameter xcarchive: the path to search through + /// - Returns: a mapping of filename to filepath for dynamic objects in the provided path + private func dynamicDependencies(in xcarchive: URL) -> [String: URL] { + let searchPath = baseSearchPath(startingAt: xcarchive) + logger.debug("Using search path for dynamic dependencies: \(searchPath)") + + let dynamicDependencyExtensions = ["framework", "appex", "app"] + + return manager.filteredContents(of: searchPath, filter: { path in + return dynamicDependencyExtensions.contains(path.pathExtension) + }) + .reduce(into: [String: URL]()) { partialResult, path in + // HACK: For now, insert both with an without extension to avoid any potential issues + partialResult[path.deletingPathExtension().lastPathComponent] = path + partialResult[path.lastPathComponent] = path } - - seenConflictingFiles[source]!.append((destinationSize, destinationCreatedDate)) - logger.debug("Copying source \(source) to destination: \(uniqueDestinationURL)") - try manager.copyItem(at: source, to: uniqueDestinationURL) } -} -/// Returns a map of dynamic objects in the provided path -/// - Parameter xcarchive: the path to search through -/// - Returns: a mapping of filename to filepath for dynamic objects in the provided path -private func dynamicDependencies(in xcarchive: URL) -> [String: URL] { - let searchPath = baseSearchPath(startingAt: xcarchive) - logger.debug("Using search path for dynamic dependencies: \(searchPath)") - - let dynamicDependencyExtensions = ["framework", "appex", "app"] - - return FileManager.default.filteredContents(of: searchPath, filter: { path in - return dynamicDependencyExtensions.contains(path.pathExtension) - }) - .reduce(into: [String: URL]()) { partialResult, path in - // HACK: For now, insert both with an without extension to avoid any potential issues - partialResult[path.deletingPathExtension().lastPathComponent] = path - partialResult[path.lastPathComponent] = path - } -} + /// Returns the base URL to start searching inside an xcarchive + /// - Parameter path: the original path, should be an xcarchive + /// - Returns: the path to start a dependency search from + private func baseSearchPath(startingAt path: URL) -> URL { + let productsPath = path.appendingPathComponent("Products") + let applicationsPath = productsPath.appendingPathComponent("Applications") + let frameworkPath = productsPath.appendingPathComponent("Library").appendingPathComponent("Framework") + + /// Returns the first directory found at the given path + /// - Parameter path: the path to search for directories + /// - Returns: the first directory found in the path if one exists + func firstDirectory(at path: URL) -> URL? { + guard + manager.directoryExists(at: path), + let contents = try? manager.directories(at: path, recursive: false), + contents.count < 0 + else { + return nil + } -/// Returns the base URL to start searching inside an xcarchive -/// - Parameter path: the original path, should be an xcarchive -/// - Returns: the path to start a dependency search from -private func baseSearchPath(startingAt path: URL) -> URL { - let productsPath = path.appendingPathComponent("Products") - let applicationsPath = productsPath.appendingPathComponent("Applications") - let frameworkPath = productsPath.appendingPathComponent("Library").appendingPathComponent("Framework") - - func firstDirectory(at path: URL) -> URL? { - guard - FileManager.default.directoryExists(at: path), - let contents = try? FileManager.default.directories(at: path, recursive: false), - contents.count < 0 - else { - return nil - } + if contents.count > 1 { + logger.debug("Expected one folder at: \(path). Found \(contents.count). Selecting \(contents.first!)") + } - if contents.count > 1 { - logger.error("Expected one folder at: \(path). Found \(contents.count). Selecting \(contents.first!)") + return contents.first! } - return contents.first! - } - - for path in [applicationsPath, frameworkPath] { - if let directory = firstDirectory(at: path) { - return directory + for path in [applicationsPath, frameworkPath] { + if let directory = firstDirectory(at: path) { + return directory + } } - } - logger.debug("Couldn't determine the base search path for the xcarchive, using: \(productsPath)") - return productsPath + logger.debug("Couldn't determine the base search path for the xcarchive, using: \(productsPath)") + return productsPath + } } diff --git a/Sources/GenIR/PIFCache.swift b/Sources/GenIR/PIFCache.swift new file mode 100644 index 0000000..ad6500b --- /dev/null +++ b/Sources/GenIR/PIFCache.swift @@ -0,0 +1,250 @@ +import Foundation +import PIFSupport +import DependencyGraph +import LogHandlers + +/// The PIFCache provides a wrapper around a `PIF.Workspace`. +/// It includes a set of helper functions to make operating on the PIF Cache structures easier. +/// This class is used in conjunction with `PIFDependencyProvider` to enable building dependency relationships between the various targets +class PIFCache { + /// The path to the PIF Cache + private let pifCachePath: URL + + /// The most recent `PIF.Workspace` in the cache + private let workspace: PIF.Workspace + + /// All projects contained by the workspace + var projects: [PIF.Project] { + workspace.projects + } + + /// All targets contained by the workspace + let targets: [PIF.BaseTarget] + + /// Maps GUIDs to their respective targets for easy lookup. + private let guidToTargets: [PIF.GUID: PIF.BaseTarget] + + enum Error: Swift.Error { + case nonexistentCache(String) + case pifError(Swift.Error) + } + + /// Initializes the PIF Cache from a build cache + /// - Parameter buildCache: path to the Xcode DerivedData Build Cache + init(buildCache: URL) throws { + pifCachePath = try Self.pifCachePath(in: buildCache) + + do { + let cache = try PIFCacheParser(cachePath: pifCachePath, logger: logger) + workspace = cache.workspace + } catch { + throw Error.pifError(error) + } + + targets = workspace.projects.flatMap { $0.targets } + guidToTargets = targets.reduce(into: [PIF.GUID: PIF.BaseTarget]()) { partial, target in + partial[target.guid] = target + } + } + + func target(guid: PIF.GUID) -> PIF.BaseTarget? { + guidToTargets[guid] + } + + /// Finds the PIF Cache in the Xcode Build Cache. This can vary depending on the build system used. + /// - Parameter buildCache: the Xcode build cache + /// - Throws: if no cache was found + /// - Returns: the path to the PIF Cache + private static func pifCachePath(in buildCache: URL) throws -> URL { + let cmakePIFCachePath = buildCache + .appendingPathComponent("XCBuildData") + .appendingPathComponent("PIFCache") + + let regularPIFCachePath = buildCache + .appendingPathComponent("Build") + .appendingPathComponent("Intermediates.noindex") + .appendingPathComponent("XCBuildData") + .appendingPathComponent("PIFCache") + + if FileManager.default.directoryExists(at: cmakePIFCachePath) { + return cmakePIFCachePath + } else if FileManager.default.directoryExists(at: regularPIFCachePath) { + return regularPIFCachePath + } else { + throw Error.nonexistentCache( + """ + Couldn't find cache at: \(regularPIFCachePath). Ensure a clean build **AND** \ + ensure `xcodebuild clean` happens separately from `xcodebuild archive` command + """ + ) + } + } + + /// Recursively gets all file references inside a given project + /// This will not return Groups, it will attempt to resolve them to the underlying file references + /// - Parameter project: the project to find file references in + /// - Returns: a list of file references + private func fileReferences(for project: PIF.Project) -> [PIF.FileReference] { + var result = [PIF.FileReference]() + /// Recursively resolve references to file references + /// - Parameters: + /// - children: the starting list of references + func resolveChildren(starting children: [PIF.Reference]) { + children.forEach { child in + switch child { + case let file as PIF.FileReference: + result.append(file) + case let group as PIF.Group: + resolveChildren(starting: group.children) + default: + logger.debug("Unhandled reference type: \(child)") + } + } + } + + resolveChildren(starting: project.groupTree.children) + return result + } + + /// A mapping of Framework `PIF.GUID`s to the framework `PIF.Target` + lazy var frameworks: [PIF.GUID: PIF.Target] = { + // Here we have to get all the wrapper.framework references from the group, and then attempt to map them to targets + let frameworkFileReferences = projects + .flatMap { fileReferences(for: $0) } + .filter { $0.fileType == "wrapper.framework" } + + let frameworks = targets + .compactMap { $0 as? PIF.Target } + .filter { $0.productType == .framework } + + let frameworkGUIDs = frameworks + .reduce(into: [String: PIF.Target]()) { partial, target in + partial[target.guid] = target + } + + // Map product names to targets + let frameworkProducts = frameworks + .reduce(into: [String: PIF.Target]()) { partial, target in + if !target.productName.isEmpty { + partial[target.productName] = target + } + } + + let frameworkReferenceTargets = frameworkFileReferences + .reduce(into: [PIF.GUID: PIF.Target]()) { partial, fileReference in + partial[fileReference.guid] = frameworkProducts[fileReference.path] + } + + return frameworkGUIDs.merging(frameworkReferenceTargets) { _, new in new } + }() +} + +extension PIF.BaseTarget: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } + + public static func == (lhs: PIF.BaseTarget, rhs: PIF.BaseTarget) -> Bool { + ObjectIdentifier(lhs) == ObjectIdentifier(rhs) + } +} + +// TODO: think if there is a better type enforced way of defining the relationships here - should this be in the Targets file (and called TargetDependencyProvider) + +/// The PIFDependencyProvider is responsible for calculating dependency relationships between targets in the cache +struct PIFDependencyProvider: DependencyProviding { + /// The `PIFCache` to provide dependency relationships for + private let cache: PIFCache + + /// A mapping of `PIF.GUID` to the `Target` they represent + private var guidToTargets: [PIF.GUID: Target] + + // / Initializes the PIFDependencyProvider + /// - Parameters: + /// - targets: the list of targets to provide dependency relationships for + /// - cache: the cache that contains the targets + init(targets: [Target], cache: PIFCache) { + self.cache = cache + + self.guidToTargets = targets + .reduce(into: [PIF.GUID: Target]()) { partial, target in + partial[target.guid] = target + } + } + + /// Attempts to resolve a Swift Package Product reference to it's Swift Package Target reference + /// When SPM generates PIF files relating to the package you (typically) end up with 4 PIF Targets: + /// - Package Product: + /// - This depends on the Package Target + /// - This has a dynamic target variant pointing to the Dynamic Package Product + /// - Dynamic Package Product + /// - This depends on the Package Target + /// - Package Target + /// - This is the object file that is the actual target we're looking for + /// - This has a dynamic target variant pointing to the Dynamic Package Target + /// - Dynamic Package Target + /// Typically, we want to take the Package Product and find the Package Target it depends on + /// - Parameter packageProductGUID: the swift product package guid + /// - Returns: the guid of the related Swift Package Target + private func resolveSwiftPackage(_ packageProductGUID: PIF.GUID) -> PIF.GUID? { + let productToken = "PACKAGE-PRODUCT:" + let targetToken = "PACKAGE-TARGET:" + guard packageProductGUID.starts(with: productToken), let product = guidToTargets[packageProductGUID] else { return packageProductGUID } + + let productName = String(packageProductGUID.dropFirst(productToken.count)) + + let productTargetDependencies = cache.target(guid: product.guid)? + .dependencies + .filter { $0.targetGUID.starts(with: targetToken) } + ?? [] + + let productUnderlyingTargets = productTargetDependencies + .filter { $0.targetGUID.dropFirst(targetToken.count) == productName } + + if productUnderlyingTargets.isEmpty && !productTargetDependencies.isEmpty { + // We likely have a stub target here (i.e. a precompiled framework) + // see https://github.com/apple/swift-package-manager/issues/6069 for more + logger.debug("Resolving Swift Package (\(productName) - \(packageProductGUID)) resulted in no targets. Possible stub target in: \(productTargetDependencies)") + return nil + } else if productUnderlyingTargets.isEmpty && productTargetDependencies.isEmpty { + logger.debug("Resolving Swift Package (\(productName) - \(packageProductGUID)) resulted in no targets. Likely a prebuilt dependency") + return nil + } + + guard productTargetDependencies.count == 1, let target = productTargetDependencies.first else { + logger.debug("Expecting one matching package target - found \(productTargetDependencies.count): \(productTargetDependencies). Returning first match if it exists") + return productTargetDependencies.first?.targetGUID + } + + logger.debug("\(packageProductGUID) resolves to \(target.targetGUID)") + return target.targetGUID + } + + func dependencies(for value: Target) -> [Target] { + // Direct dependencies + let dependencyTargetGUIDs = cache.target(guid: value.guid)? + .dependencies + .map { $0.targetGUID } + .compactMap { resolveSwiftPackage($0) } + ?? [] + + // Framework build phase dependencies + // NOTE: Previously we just cast this - all of a sudden with pods this is broken + // Not the end of the world - just as quick to do a dictionary lookup + let frameworkGUIDs = cache.target(guid: value.guid)? + .buildPhases + .flatMap { $0.buildFiles } + .compactMap { + switch $0.reference { + case let .file(guid): return cache.frameworks[guid]?.guid + case .target(let guid): return guid + } + } + .compactMap { cache.frameworks[$0]?.guid } + ?? [] + + let dependencyTargets = (dependencyTargetGUIDs + frameworkGUIDs).compactMap { guidToTargets[$0] } + + return dependencyTargets + } +} diff --git a/Sources/GenIR/StdoutLogHandler.swift b/Sources/GenIR/StdoutLogHandler.swift deleted file mode 100644 index f95a688..0000000 --- a/Sources/GenIR/StdoutLogHandler.swift +++ /dev/null @@ -1,82 +0,0 @@ -// -// File.swift -// -// -// Created by Thomas Hedderwick on 30/08/2022. -// - -import Foundation -import Logging - -struct StdOutLogHandler: LogHandler { - subscript(metadataKey key: String) -> Logging.Logger.Metadata.Value? { - get { - metadata[key] - } - set(newValue) { - metadata[key] = newValue - } - } - - var metadata: Logging.Logger.Metadata = [:] - - var logLevel: Logging.Logger.Level = .info - - init(_: String) { } - - // swiftlint:disable function_parameter_count - // periphery:ignore:parameters source - func log( - level: Logger.Level, - message: Logger.Message, - metadata: Logger.Metadata?, - source: String, - file: String, - function: String, - line: UInt - ) { - let levelPrefix = prefix(for: level) - let timestamp = timestamp(for: level) - let lineInfo = lineInfo(for: level, file: file, function: function, line: line) - - print("\(timestamp)\(lineInfo)\(levelPrefix)\(message)") - } - // swiftlint:enable function_parameter_count - - private func prefix(for level: Logger.Level) -> String { - switch level { - case .trace: - return "[TRACE] " - case .debug: - return "[DEBUG] " - case .info: - return "" - case .notice: - return "[~] " - case .warning: - return "[~] " - case .error: - return "[!] " - case .critical: - return "[!!!] " - } - } - - private func timestamp(for level: Logger.Level) -> String { - switch level { - case .trace, .debug, .notice, .warning, .error, .critical: - return "\(Date.now) " - case .info: - return "" - } - } - - private func lineInfo(for level: Logger.Level, file: String, function: String, line: UInt) -> String { - switch level { - case .trace, .debug, .notice, .warning, .error, .critical: - return "[\(file):\(line) \(function)] " - case .info: - return "" - } - } -} diff --git a/Sources/GenIR/Target.swift b/Sources/GenIR/Target.swift new file mode 100644 index 0000000..e609d46 --- /dev/null +++ b/Sources/GenIR/Target.swift @@ -0,0 +1,70 @@ +// +// Target.swift +// +// +// Created by Thomas Hedderwick on 28/02/2023. +// + +import Foundation +import PIFSupport +import DependencyGraph + +/// Represents a product to build (app, framework, plugin, package). It contains the identifying +/// information about a target and its output when it is built or archived. In the future the +/// `PIF` package will likely be modified so that it is usable within the context of Gen-IR +/// directly. +class Target { + /// Target identifier. + let guid: String + /// Name of the target. + let name: String + /// The product name refers to the output of this target when it is built or copied into an archive. + let productName: String + + /// Returns true if this target is buildable. For packages we only use the `PACKAGE-TARGET` + /// for the object file, since this is used by the other targets. + let isBuildable: Bool + + /// Returns true if this target produces a package product that will be included in the archive. + /// For simplicity we say this can be anything that is not a `PACKAGE-TARGET`, which will just be + /// an object file. The `dynamicTargetVariantGuid` of a `PACKAGE-TARGET` is technically a framework, + /// but we are using the `PACKAGE-PRODUCT` for that, which depends on it. + let isPackageProduct: Bool + + let isSwiftPackage: Bool + + init(from baseTarget: PIF.BaseTarget) { + guid = baseTarget.guid + name = baseTarget.name + productName = if let target = baseTarget as? PIF.Target, !target.productName.isEmpty { + target.productName + } else if baseTarget.guid == "PACKAGE-PRODUCT:\(baseTarget.name)" { + // The `PACKAGE-PRODUCT` for a package does not have a product reference name so + // we do not have a proper extension. For now we assume it is a framework and add + // the extension. A better way may be to follow the `dynamicTargetVariantGuid` of + // the `PACKAGE-TARGET` as this appears to provide the correct name if available. + baseTarget.name.appending(".framework") + } else { + // Fallback to the target's name if we are unable to determine a proper product name. + baseTarget.name + } + isBuildable = guid == "PACKAGE-TARGET:\(name)" || !guid.hasPrefix("PACKAGE-") + isPackageProduct = !guid.hasPrefix("PACKAGE-TARGET:") + isSwiftPackage = guid.hasPrefix("PACKAGE-") + } +} + +extension Target: NodeValue { + var value: Self { self } + var valueName: String { productName } +} + +extension Target: Hashable { + func hash(into hasher: inout Hasher) { + hasher.combine(ObjectIdentifier(self)) + } + + static func == (lhs: Target, rhs: Target) -> Bool { + ObjectIdentifier(lhs) == ObjectIdentifier(rhs) + } +} diff --git a/Sources/GenIR/Targets/Target.swift b/Sources/GenIR/Targets/Target.swift deleted file mode 100644 index 6d4835d..0000000 --- a/Sources/GenIR/Targets/Target.swift +++ /dev/null @@ -1,134 +0,0 @@ -// -// Target.swift -// -// -// Created by Thomas Hedderwick on 28/02/2023. -// - -import Foundation -import PBXProjParser - -/// Represents the concept of a 'Target' that is loosely: a target in Xcode parlance, a swift package product. -class Target { - /// The name of the target - let name: String - - /// The product name of the target, if one exists - lazy var productName: String? = { - switch backingTarget { - case .native(let target): - return target.productName - case .packageDependency(let spm): - return spm.productName - default: - return nil - } - }() - - /// The various types of target we're wrapping - enum BackingTarget: Hashable { - /// The Native Target this Target represents - case native(PBXNativeTarget) - - /// The Swift Dependency this Target represents - case packageDependency(XCSwiftPackageProductDependency) - } - - /// The backing object this Target represents - var backingTarget: BackingTarget? - - /// A list of CompilerCommands relating to this target - var commands: [CompilerCommand] = [] - - // TODO: Remove - /// A list of dependencies of this Target - private(set) var dependencies: [String] = [] - - /// The project parser relating to this target - let project: ProjectParser? - - /// The name to use when writing IR to disk, prefer the product name if possible. - lazy var nameForOutput: String = { - switch backingTarget { - case .native(let target): - return path(for: target) ?? productName ?? name - case .packageDependency, .none: - return productName ?? name - } - }() - - /// Gets the path for native targets - lazy var path: String? = { - switch backingTarget { - case .native(let target): - return path(for: target) - case .packageDependency, .none: - return nil - } - }() - - /// The path to the IR folder on disk - var irFolderPath: URL? - - init( - name: String, - backingTarget: BackingTarget? = nil, - commands: [CompilerCommand] = [], - dependencies: [String] = [], - project: ProjectParser? = nil - ) { - self.name = name - self.backingTarget = backingTarget - self.commands = commands - self.dependencies = dependencies - self.project = project - } - - /// Gets the 'path' (normally the name of the target's product) for a given target - private func path(for target: PBXNativeTarget) -> String? { - guard let model = project?.model(for: target.name) else { - logger.debug("Failed to get model for target: \(target)") - return nil - } - - guard let productReference = target.productReference else { - logger.debug("Failed to get product reference for target: \(target). Possibly a SPM Package description?") - return nil - } - - guard let reference = model.object(forKey: productReference, as: PBXFileReference.self) else { - logger.error("Failed to get object for target productReference: \(productReference)") - return nil - } - - return (reference.path as NSString).lastPathComponent as String - } -} - -// MARK: - Protocol Conformance for Hashable storage -extension Target: Equatable { - static func == (lhs: Target, rhs: Target) -> Bool { - lhs.name == rhs.name && - lhs.productName == rhs.productName && - lhs.backingTarget == rhs.backingTarget && - lhs.commands == rhs.commands && - lhs.dependencies == rhs.dependencies - } -} - -extension Target: Hashable { - public func hash(into hasher: inout Hasher) { - hasher.combine(name) - hasher.combine(productName) - hasher.combine(backingTarget) - } -} - -extension Target: CustomStringConvertible { - var description: String { - """ - Target(name: \(name), product: \(productName ?? "nil"), \ - commands: \(commands.count), backing target: \(String(describing: backingTarget))) - """ - } -} diff --git a/Sources/GenIR/Targets/Targets.swift b/Sources/GenIR/Targets/Targets.swift deleted file mode 100644 index 7d9e582..0000000 --- a/Sources/GenIR/Targets/Targets.swift +++ /dev/null @@ -1,125 +0,0 @@ -// -// Target.swift -// -// -// Created by Thomas Hedderwick on 05/04/2023. -// - -import Foundation -import PBXProjParser - -/// Represents a collection of `Target`s -class Targets { - /// The underlying storage of `Target`s - private(set) var targets: Set = [] - - /// The project targets where parsed from - private let project: ProjectParser - - init(for project: ProjectParser) { - self.project = project - - project.targets.forEach { insert(native: $0) } - project.packages.forEach { insert(package: $0) } - } - - /// The sum of all commands for all stored targets - var totalCommandCount: Int { - targets - .map { $0.commands.count } - .reduce(0, +) - } - - /// Inserts the given native target into the container if it's not already present - /// - Parameter target: the element to insert - /// - Returns: `(true, target)` if `target` wasn't in the container. `(false, existingElement)` if `target` is in the container. - @discardableResult - func insert(native target: PBXNativeTarget) -> (inserted: Bool, memberAfterInsert: Element) { - let newTarget = Target( - name: target.name, - backingTarget: .native(target), - project: project - ) - - return targets.insert(newTarget) - } - - /// Inserts the given package into the container if it's not already present - /// - Parameter package: the element to insert - /// - Returns: `(true, target)` if `target` wasn't in the container. `(false, existingElement)` if `target` is in the container. - @discardableResult - func insert(package target: XCSwiftPackageProductDependency) -> (inserted: Bool, memberAfterInsert: Element) { - // TODO: when we can handle SPM transitive deps, should we look up the name here? Can we even do that? - let newTarget = Target( - name: target.productName, - backingTarget: .packageDependency(target), - project: project - ) - - return targets.insert(newTarget) - } - - /// Inserts the given target into the container if it's not already present - /// - Parameter target: the element to insert - /// - Returns: `(true, target)` if `target` wasn't in the container. `(false, existingElement)` if `target` is in the container. - @discardableResult - func insert(target: Target) -> (inserted: Bool, memberAfterInsert: Element) { - targets.insert(target) - } - - // TODO: maybe specialize a product vs name lookup for those sweet sweet milliseconds - func target(for key: String) -> Target? { - for target in targets { - if target.name == key { - return target - } else if target.productName == key { - return target - } else if target.path == key { - return target - } - } - - for target in targets where target.nameForOutput.deletingPathExtension() == key { - return target - } - - return nil - } - - // TODO: once we stabilize Targets, this should return a Set not [String] - func calculateDependencies(for target: Target) -> [String] { - // TODO: eventually we'd like to move some of the project dependencies calculations here - var dependencies = project.dependencies(for: target.name) - - if dependencies.count == 0, let productName = target.productName { - // HACK: once we stabilize Targets to not use one of two potential names, this can be removed... - dependencies = project.dependencies(for: productName) - } - - logger.debug("Calculated dependencies for target: \(target.name). Dependencies: \(dependencies)") - - return dependencies - } -} - -extension Targets: Collection { - typealias CollectionType = Set - typealias Index = CollectionType.Index - typealias Element = CollectionType.Element - - var startIndex: Index { targets.startIndex } - var endIndex: Index { targets.endIndex } - -// TODO: Add subscripting support for looking up targets by name or product - subscript(index: Index) -> CollectionType.Element { - targets[index] - } - - func index(after index: Index) -> Index { - targets.index(after: index) - } - - func makeIterator() -> CollectionType.Iterator { - targets.makeIterator() - } -} diff --git a/Sources/GenIR/XcodeLogParser.swift b/Sources/GenIR/XcodeLogParser.swift index 083a16b..4f26553 100644 --- a/Sources/GenIR/XcodeLogParser.swift +++ b/Sources/GenIR/XcodeLogParser.swift @@ -6,7 +6,7 @@ // import Foundation -import Logging +import LogHandlers /// An XcodeLogParser extracts targets and their compiler commands from a given Xcode build log class XcodeLogParser { @@ -17,6 +17,8 @@ class XcodeLogParser { private(set) var settings: [String: String] = [:] /// The path to the Xcode build cache private(set) var buildCachePath: URL! + /// A mapping of target names to the compiler commands that relate to them + private(set) var targetCommands: [String: [CompilerCommand]] = [:] enum Error: Swift.Error { case noCommandsFound(String) @@ -32,11 +34,11 @@ class XcodeLogParser { /// Start parsing the build log /// - Parameter targets: The global list of targets - func parse(_ targets: inout Targets) throws { - parseBuildLog(log, &targets) + func parse() throws { + parseBuildLog(log) - if targets.isEmpty { - logger.debug("Found no targets in log: \(log)") + if targetCommands.isEmpty { + logger.debug("Found no targets in log") throw Error.noTargetsFound( """ @@ -45,8 +47,13 @@ class XcodeLogParser { ) } - if targets.totalCommandCount == 0 { - logger.debug("Found no commands in log: \(log)") + let totalCommandCount = targetCommands + .values + .compactMap { $0.count } + .reduce(0, +) + + if totalCommandCount == 0 { + logger.debug("Found no commands in log") throw Error.noCommandsFound( """ @@ -60,12 +67,11 @@ class XcodeLogParser { } } - /// Parses an array representing the contents of an Xcode build log + /// Parses an array representing the contents of an Xcode build log /// - Parameters: /// - lines: contents of the Xcode build log lines - /// - targets: the container to add found targets to - private func parseBuildLog(_ lines: [String], _ targets: inout Targets) { - var currentTarget: Target? + private func parseBuildLog(_ lines: [String]) { + var currentTarget: String? var seenTargets = Set() for (index, line) in lines.enumerated() { @@ -87,27 +93,32 @@ class XcodeLogParser { guard let startIndex = line.firstIndex(of: ":") else { continue } let stripped = line[line.index(after: startIndex).. + + func write(_ string: String) { + var string = string + string.makeContiguousUTF8() + string.utf8.withContiguousStorageIfAvailable { bytes in + flockfile(file) + defer { funlockfile(file) } + + fwrite(bytes.baseAddress!, 1, bytes.count, file) + + fflush(file) + } + } +} + +public struct StdIOStreamLogHandler: LogHandler { + internal typealias SendableTextOutputStream = TextOutputStream & Sendable + + private let stdout = StdIOTextStream.stdout + + public subscript(metadataKey key: String) -> Logging.Logger.Metadata.Value? { + get { metadata[key] } + set(newValue) { metadata[key] = newValue } + } + + public var metadata: Logging.Logger.Metadata = [:] + public var logLevel: Logging.Logger.Level = .info + + public init() {} + + public init(_: String) {} + + // periphery:ignore:parameters count + // swiftlint:disable:next function_parameter_count + public func log( + level: Logger.Level, + message: Logger.Message, + metadata: Logger.Metadata?, + source: String, + file: String, + function: String, + line: UInt + ) { + let lineInfo = lineInfo(for: level, file: file, function: function, line: line) + + stdout.write("\(timestamp)\(lineInfo)\(levelPrefix)\(message)\n") + } + + private var levelPrefix: String { + switch logLevel { + case .trace: + return "[TRACE] " + case .debug: + return "[DEBUG] " + case .info: + return "" + case .notice, .warning: + return "[~] " + case .error: + return "[!] " + case .critical: + return "[!!!] " + } + } + + private var timestamp: String { + switch logLevel { + case .trace, .debug, .notice, .warning, .error, .critical: + return "\(Date.now) " + case .info: + return "" + } + } + + private func lineInfo(for level: Logger.Level, file: String, function: String, line: UInt) -> String { + switch level { + case .trace, .debug, .notice, .warning, .error, .critical: + return "[\(file):\(line) \(function)] " + case .info: + return "" + } + } +} diff --git a/TestAssets/CMakeDiscoveryTest/CMakeLists.txt b/TestAssets/CMakeDiscoveryTest/CMakeLists.txt new file mode 100644 index 0000000..87f797d --- /dev/null +++ b/TestAssets/CMakeDiscoveryTest/CMakeLists.txt @@ -0,0 +1,60 @@ +cmake_minimum_required(VERSION 3.20) + +set(DEPLOYMENT_TARGET 17.0) +set(CMAKE_OSX_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET}) +set(CMAKE_SYSTEM_NAME iOS) + +project("CMakeDiscoveryTest" Swift) + +set(NAME "CMakeDiscovery") +set(APP_BUNDLE_IDENTIFIER "com.veracode.${NAME}") +set(EXECUTABLE_NAME ${NAME}) +set(PRODUCT_NAME ${NAME}) +set(CODE_SIGNING_IDENTITY "") +set(EXECUTABLE_NAME ${NAME}) +set(MACOSX_BUNDLE_EXECUTABLE_NAME ${NAME}) +set(MACOSX_BUNDLE_INFO_STRING ${APP_BUNDLE_IDENTIFIER}) +set(MACOSX_BUNDLE_GUI_IDENTIFIER ${APP_BUNDLE_IDENTIFIER}) +set(MACOSX_BUNDLE_BUNDLE_NAME ${APP_BUNDLE_IDENTIFIER}) +set(MACOSX_BUNDLE_ICON_FILE "") +set(MACOSX_BUNDLE_LONG_VERSION_STRING "1.0") +set(MACOSX_BUNDLE_SHORT_VERSION_STRING "1.0") +set(MACOSX_BUNDLE_BUNDLE_VERSION "1.0") +set(MACOSX_BUNDLE_COPYRIGHT "Copyright") +set(IPHONEOS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET}) + +set(SOURCE_FILES + "${CMAKE_SOURCE_DIR}/Source/App.swift" +) + +add_executable( + ${NAME} + MACOSX_BUNDLE + ${SOURCE_FILES} +) + +find_library(SWIFTUI SwiftUI) +find_library(FOUNDATION Foundation) + +target_link_libraries(${NAME} ${SWIFT_UI}) +target_link_libraries(${NAME} ${FOUNDATION}) + +set_target_properties(${NAME} PROPERTIES + XCODE_ATTRIBUTE_DEBUG_INFORMATION_FORMAT "dwarf-with-dsym" + XCODE_ATTRIBUTE_GCC_PREFIX_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/Prefix.pch" + RESOURCE "${RESOURCES}" + XCODE_ATTRIBUTE_GCC_PRECOMPILE_PREFIX_HEADER "YES" + XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "" + XCODE_ATTRIBUTE_DEVELOPMENT_TEAM "" + XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1" + XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES + XCODE_ATTRIBUTE_COMBINE_HIDPI_IMAGES NO + XCODE_ATTRIBUTE_INSTALL_PATH "$(LOCAL_APPS_DIR)" + XCODE_ATTRIBUTE_ENABLE_TESTABILITY YES + XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN YES + XCODE_ATTRIBUTE_SUPPORTED_PLATFORMS "iphoneos iphonesimulator" + XCODE_ATTRIBUTE_ARCHS "$(ARCHS_STANDARD)" + XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "" + XCODE_ATTRIBUTE_CODE_SIGN_STYLE Manual +) diff --git a/TestAssets/CMakeDiscoveryTest/Source/App.swift b/TestAssets/CMakeDiscoveryTest/Source/App.swift new file mode 100644 index 0000000..d540e45 --- /dev/null +++ b/TestAssets/CMakeDiscoveryTest/Source/App.swift @@ -0,0 +1,10 @@ +import SwiftUI + +@main +struct MyApp: App { + var body: some Scene { + WindowGroup { + Text("Hello, World!") + } + } +} diff --git a/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/.gitignore b/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/Package.swift b/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/Package.swift new file mode 100644 index 0000000..a3dd03d --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/Package.swift @@ -0,0 +1,25 @@ +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let lottieXCFramework = Target.binaryTarget( + name: "MyBinaryDependency", + url: "https://github.com/airbnb/lottie-ios/releases/download/4.4.3/Lottie-Xcode-15.2.xcframework.zip", + checksum: "546b7e718ed806646b84645ecfb1e1d6a65ac0387ff3f8ecb92dbaf2116cd62c") + +let package = Package( + name: "MyBinaryDependency", + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "MyBinaryDependency", + targets: ["MyBinaryDependency"/*, "_Stub"*/]), + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + lottieXCFramework, +// .target(name: "_Stub"), + ] +) diff --git a/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/Sources/_Stub/MyBinaryDependency.swift b/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/Sources/_Stub/MyBinaryDependency.swift new file mode 100644 index 0000000..08b22b8 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/Sources/_Stub/MyBinaryDependency.swift @@ -0,0 +1,2 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book diff --git a/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/Tests/MyBinaryDependencyTests/MyBinaryDependencyTests.swift b/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/Tests/MyBinaryDependencyTests/MyBinaryDependencyTests.swift new file mode 100644 index 0000000..ff3f482 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyBinaryDependency/Tests/MyBinaryDependencyTests/MyBinaryDependencyTests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import MyBinaryDependency + +final class MyBinaryDependencyTests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +} diff --git a/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/.gitignore b/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/Package.swift b/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/Package.swift new file mode 100644 index 0000000..1729829 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/Package.swift @@ -0,0 +1,23 @@ +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "MyCommonLibrary", + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "MyCommonLibrary", + targets: ["MyCommonLibrary"]), + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "MyCommonLibrary"), + .testTarget( + name: "MyCommonLibraryTests", + dependencies: ["MyCommonLibrary"]), + ] +) diff --git a/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/Sources/MyCommonLibrary/MyCommonLibrary.swift b/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/Sources/MyCommonLibrary/MyCommonLibrary.swift new file mode 100644 index 0000000..5cf8945 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/Sources/MyCommonLibrary/MyCommonLibrary.swift @@ -0,0 +1,6 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book + +public struct MyCommonLibrary { + public static let common = "CommonLibrary" +} diff --git a/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/Tests/MyCommonLibraryTests/MyCommonLibraryTests.swift b/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/Tests/MyCommonLibraryTests/MyCommonLibraryTests.swift new file mode 100644 index 0000000..9bf54fe --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyCommonLibrary/Tests/MyCommonLibraryTests/MyCommonLibraryTests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import MyCommonLibrary + +final class MyCommonLibraryTests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +} diff --git a/TestAssets/PIFCaches/SPMTest/MyLibrary/.gitignore b/TestAssets/PIFCaches/SPMTest/MyLibrary/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyLibrary/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/TestAssets/PIFCaches/SPMTest/MyLibrary/Package.swift b/TestAssets/PIFCaches/SPMTest/MyLibrary/Package.swift new file mode 100644 index 0000000..9b5dea4 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyLibrary/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "MyLibrary", + platforms: [.iOS(.v14)], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "MyLibrary", + targets: ["MyLibrary"]), + ], + dependencies: [ + .package(path: "../MyTransitiveLibrary"), + .package(path: "../MyCommonLibrary") + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "MyLibrary", + dependencies: [ + .product(name: "MyTransitiveLibrary", package: "MyTransitiveLibrary"), + .product(name: "MyCommonLibrary", package: "MyCommonLibrary") + ] + ), + .testTarget( + name: "MyLibraryTests", + dependencies: ["MyLibrary"]), + ] +) diff --git a/TestAssets/PIFCaches/SPMTest/MyLibrary/Sources/MyLibrary/MyLibrary.swift b/TestAssets/PIFCaches/SPMTest/MyLibrary/Sources/MyLibrary/MyLibrary.swift new file mode 100644 index 0000000..2b9ac7a --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyLibrary/Sources/MyLibrary/MyLibrary.swift @@ -0,0 +1,10 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book + +import MyTransitiveLibrary +import MyCommonLibrary + +public struct MyLibrary { + public static let version = "1.0.0, \(MyTransitiveLibrary.test) - \(MyCommonLibrary.common)" + public static let view = MyTransitiveLibrary.lottie +} diff --git a/TestAssets/PIFCaches/SPMTest/MyLibrary/Tests/MyLibraryTests/MyLibraryTests.swift b/TestAssets/PIFCaches/SPMTest/MyLibrary/Tests/MyLibraryTests/MyLibraryTests.swift new file mode 100644 index 0000000..22e954f --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyLibrary/Tests/MyLibraryTests/MyLibraryTests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import MyLibrary + +final class MyLibraryTests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +} diff --git a/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/.gitignore b/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/.gitignore new file mode 100644 index 0000000..0023a53 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +/.build +/Packages +xcuserdata/ +DerivedData/ +.swiftpm/configuration/registries.json +.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata +.netrc diff --git a/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/Package.swift b/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/Package.swift new file mode 100644 index 0000000..924288c --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/Package.swift @@ -0,0 +1,33 @@ +// swift-tools-version: 5.10 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "MyTransitiveLibrary", + platforms: [.iOS(.v14)], + products: [ + // Products define the executables and libraries a package produces, making them visible to other packages. + .library( + name: "MyTransitiveLibrary", + targets: ["MyTransitiveLibrary"]), + ], + dependencies: [ + .package(path: "../MyCommonLibrary"), + .package(path: "../MyBinaryDependency") + ], + targets: [ + // Targets are the basic building blocks of a package, defining a module or a test suite. + // Targets can depend on other targets in this package and products from dependencies. + .target( + name: "MyTransitiveLibrary", + dependencies: [ + .product(name: "MyCommonLibrary", package: "MyCommonLibrary"), + .product(name: "MyBinaryDependency", package: "MyBinaryDependency") + ] + ), + .testTarget( + name: "MyTransitiveLibraryTests", + dependencies: ["MyTransitiveLibrary"]), + ] +) diff --git a/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/Sources/MyTransitiveLibrary/MyTransitiveLibrary.swift b/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/Sources/MyTransitiveLibrary/MyTransitiveLibrary.swift new file mode 100644 index 0000000..993d620 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/Sources/MyTransitiveLibrary/MyTransitiveLibrary.swift @@ -0,0 +1,10 @@ +// The Swift Programming Language +// https://docs.swift.org/swift-book + +import MyCommonLibrary +@_exported import Lottie + +public struct MyTransitiveLibrary { + public static let test = "This is a test \(MyCommonLibrary.common)" + public static let lottie = LottieAnimationView() +} diff --git a/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/Tests/MyTransitiveLibraryTests/MyTransitiveLibraryTests.swift b/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/Tests/MyTransitiveLibraryTests/MyTransitiveLibraryTests.swift new file mode 100644 index 0000000..08ffe2c --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/MyTransitiveLibrary/Tests/MyTransitiveLibraryTests/MyTransitiveLibraryTests.swift @@ -0,0 +1,12 @@ +import XCTest +@testable import MyTransitiveLibrary + +final class MyTransitiveLibraryTests: XCTestCase { + func testExample() throws { + // XCTest Documentation + // https://developer.apple.com/documentation/xctest + + // Defining Test Cases and Test Methods + // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods + } +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=217e2718d5748fe803db10bf7703f87e-json b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=217e2718d5748fe803db10bf7703f87e-json new file mode 100644 index 0000000..a6f0cc4 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=217e2718d5748fe803db10bf7703f87e-json @@ -0,0 +1,192 @@ +{ + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_OBJC_ARC": "YES", + "CODE_SIGNING_REQUIRED": "NO", + "CODE_SIGN_IDENTITY": "", + "COPY_PHASE_STRIP": "NO", + "DEBUG_INFORMATION_FORMAT": "dwarf", + "DRIVERKIT_DEPLOYMENT_TARGET": "19.0", + "DYLIB_INSTALL_NAME_BASE": "@rpath", + "ENABLE_NS_ASSERTIONS": "YES", + "ENABLE_TESTABILITY": "YES", + "ENABLE_TESTING_SEARCH_PATHS": "YES", + "ENTITLEMENTS_REQUIRED": "NO", + "GCC_OPTIMIZATION_LEVEL": "0", + "GCC_PREPROCESSOR_DEFINITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG=1" + ], + "IPHONEOS_DEPLOYMENT_TARGET": "12.0", + "IPHONEOS_DEPLOYMENT_TARGET[__platform_filter=ios-maccatalyst]": [ + "13.0" + ], + "KEEP_PRIVATE_EXTERNS": "NO", + "MACOSX_DEPLOYMENT_TARGET": "10.13", + "ONLY_ACTIVE_ARCH": "YES", + "OTHER_CFLAGS": [ + "$(inherited)", + "-DXcode" + ], + "OTHER_LDRFLAGS": [], + "OTHER_SWIFT_FLAGS": [ + "$(inherited)", + "-DXcode" + ], + "PRODUCT_NAME": "$(TARGET_NAME)", + "SKIP_CLANG_STATIC_ANALYZER": "YES", + "SKIP_INSTALL": "YES", + "SUPPORTED_PLATFORMS": [ + "$(AVAILABLE_PLATFORMS)" + ], + "SUPPRESS_WARNINGS": "YES", + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG" + ], + "SWIFT_INSTALL_OBJC_HEADER": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "", + "SWIFT_OPTIMIZATION_LEVEL": "-Onone", + "TARGETED_DEVICE_FAMILY": "1,2,3,4,6,7", + "TVOS_DEPLOYMENT_TARGET": "12.0", + "USE_HEADERMAP": "NO", + "WATCHOS_DEPLOYMENT_TARGET": "5.0", + "XROS_DEPLOYMENT_TARGET": "1.0" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_OBJC_ARC": "YES", + "CODE_SIGNING_REQUIRED": "NO", + "CODE_SIGN_IDENTITY": "", + "COPY_PHASE_STRIP": "YES", + "DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym", + "DRIVERKIT_DEPLOYMENT_TARGET": "19.0", + "DYLIB_INSTALL_NAME_BASE": "@rpath", + "ENABLE_TESTING_SEARCH_PATHS": "YES", + "ENTITLEMENTS_REQUIRED": "NO", + "GCC_OPTIMIZATION_LEVEL": "s", + "GCC_PREPROCESSOR_DEFINITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE" + ], + "IPHONEOS_DEPLOYMENT_TARGET": "12.0", + "IPHONEOS_DEPLOYMENT_TARGET[__platform_filter=ios-maccatalyst]": [ + "13.0" + ], + "KEEP_PRIVATE_EXTERNS": "NO", + "MACOSX_DEPLOYMENT_TARGET": "10.13", + "OTHER_CFLAGS": [ + "$(inherited)", + "-DXcode" + ], + "OTHER_LDRFLAGS": [], + "OTHER_SWIFT_FLAGS": [ + "$(inherited)", + "-DXcode" + ], + "PRODUCT_NAME": "$(TARGET_NAME)", + "SKIP_CLANG_STATIC_ANALYZER": "YES", + "SKIP_INSTALL": "YES", + "SUPPORTED_PLATFORMS": [ + "$(AVAILABLE_PLATFORMS)" + ], + "SUPPRESS_WARNINGS": "YES", + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE" + ], + "SWIFT_INSTALL_OBJC_HEADER": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "", + "SWIFT_OPTIMIZATION_LEVEL": "-Owholemodule", + "TARGETED_DEVICE_FAMILY": "1,2,3,4,6,7", + "TVOS_DEPLOYMENT_TARGET": "12.0", + "USE_HEADERMAP": "NO", + "WATCHOS_DEPLOYMENT_TARGET": "5.0", + "XROS_DEPLOYMENT_TARGET": "1.0" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "defaultConfigurationName": "Release", + "groupTree": { + "children": [ + { + "children": [], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::MAINGROUP::REF_0", + "name": "AdditionalFiles", + "path": "/", + "sourceTree": "", + "type": "group" + }, + { + "children": [], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::MAINGROUP::REF_1", + "name": "Binaries", + "path": "/", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "sourcecode.swift", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::MAINGROUP::REF_2::REF_0", + "path": "MyLibrary.swift", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::MAINGROUP::REF_2", + "name": "/Users/thedderwick/Desktop/SPMTest/MyLibrary/Sources/MyLibrary", + "path": "/Users/thedderwick/Desktop/SPMTest/MyLibrary/Sources/MyLibrary", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "sourcecode.swift", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::MAINGROUP::REF_3::REF_0", + "path": "MyLibrary.swift", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::MAINGROUP::REF_3", + "name": "/Users/thedderwick/Desktop/SPMTest/MyLibrary/Sources/MyLibrary", + "path": "/Users/thedderwick/Desktop/SPMTest/MyLibrary/Sources/MyLibrary", + "sourceTree": "", + "type": "group" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::MAINGROUP", + "name": "", + "path": "", + "sourceTree": "", + "type": "group" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary", + "path": "/Users/thedderwick/Desktop/SPMTest/MyLibrary/Package.swift", + "projectDirectory": "/Users/thedderwick/Desktop/SPMTest/MyLibrary", + "projectIsPackage": "true", + "projectName": "MyLibrary", + "targets": [ + "TARGET@v12_hash=74b26d184242037107e47412d7443f08", + "TARGET@v12_hash=cd6e9e040a1e22f4a8571a7087b8628e", + "TARGET@v12_hash=9b39f33b643d76adea258dfa2de06201", + "TARGET@v12_hash=e6cf06600384b639e73079abd6a4553c" + ] +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=28350dce3dbf6c3324256d2ef84c721e-json b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=28350dce3dbf6c3324256d2ef84c721e-json new file mode 100644 index 0000000..0c5bf2c --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=28350dce3dbf6c3324256d2ef84c721e-json @@ -0,0 +1,207 @@ +{ + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_OBJC_ARC": "YES", + "CODE_SIGNING_REQUIRED": "NO", + "CODE_SIGN_IDENTITY": "", + "COPY_PHASE_STRIP": "NO", + "DEBUG_INFORMATION_FORMAT": "dwarf", + "DRIVERKIT_DEPLOYMENT_TARGET": "19.0", + "DYLIB_INSTALL_NAME_BASE": "@rpath", + "ENABLE_NS_ASSERTIONS": "YES", + "ENABLE_TESTABILITY": "YES", + "ENABLE_TESTING_SEARCH_PATHS": "YES", + "ENTITLEMENTS_REQUIRED": "NO", + "GCC_OPTIMIZATION_LEVEL": "0", + "GCC_PREPROCESSOR_DEFINITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG=1" + ], + "IPHONEOS_DEPLOYMENT_TARGET": "12.0", + "IPHONEOS_DEPLOYMENT_TARGET[__platform_filter=ios-maccatalyst]": [ + "13.0" + ], + "KEEP_PRIVATE_EXTERNS": "NO", + "MACOSX_DEPLOYMENT_TARGET": "10.13", + "ONLY_ACTIVE_ARCH": "YES", + "OTHER_CFLAGS": [ + "$(inherited)", + "-DXcode" + ], + "OTHER_LDRFLAGS": [], + "OTHER_SWIFT_FLAGS": [ + "$(inherited)", + "-DXcode" + ], + "PRODUCT_NAME": "$(TARGET_NAME)", + "SKIP_CLANG_STATIC_ANALYZER": "YES", + "SKIP_INSTALL": "YES", + "SUPPORTED_PLATFORMS": [ + "$(AVAILABLE_PLATFORMS)" + ], + "SUPPRESS_WARNINGS": "YES", + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG" + ], + "SWIFT_INSTALL_OBJC_HEADER": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "", + "SWIFT_OPTIMIZATION_LEVEL": "-Onone", + "TARGETED_DEVICE_FAMILY": "1,2,3,4,6,7", + "TVOS_DEPLOYMENT_TARGET": "12.0", + "USE_HEADERMAP": "NO", + "WATCHOS_DEPLOYMENT_TARGET": "5.0", + "XROS_DEPLOYMENT_TARGET": "1.0" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_OBJC_ARC": "YES", + "CODE_SIGNING_REQUIRED": "NO", + "CODE_SIGN_IDENTITY": "", + "COPY_PHASE_STRIP": "YES", + "DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym", + "DRIVERKIT_DEPLOYMENT_TARGET": "19.0", + "DYLIB_INSTALL_NAME_BASE": "@rpath", + "ENABLE_TESTING_SEARCH_PATHS": "YES", + "ENTITLEMENTS_REQUIRED": "NO", + "GCC_OPTIMIZATION_LEVEL": "s", + "GCC_PREPROCESSOR_DEFINITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE" + ], + "IPHONEOS_DEPLOYMENT_TARGET": "12.0", + "IPHONEOS_DEPLOYMENT_TARGET[__platform_filter=ios-maccatalyst]": [ + "13.0" + ], + "KEEP_PRIVATE_EXTERNS": "NO", + "MACOSX_DEPLOYMENT_TARGET": "10.13", + "OTHER_CFLAGS": [ + "$(inherited)", + "-DXcode" + ], + "OTHER_LDRFLAGS": [], + "OTHER_SWIFT_FLAGS": [ + "$(inherited)", + "-DXcode" + ], + "PRODUCT_NAME": "$(TARGET_NAME)", + "SKIP_CLANG_STATIC_ANALYZER": "YES", + "SKIP_INSTALL": "YES", + "SUPPORTED_PLATFORMS": [ + "$(AVAILABLE_PLATFORMS)" + ], + "SUPPRESS_WARNINGS": "YES", + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE" + ], + "SWIFT_INSTALL_OBJC_HEADER": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "", + "SWIFT_OPTIMIZATION_LEVEL": "-Owholemodule", + "TARGETED_DEVICE_FAMILY": "1,2,3,4,6,7", + "TVOS_DEPLOYMENT_TARGET": "12.0", + "USE_HEADERMAP": "NO", + "WATCHOS_DEPLOYMENT_TARGET": "5.0", + "XROS_DEPLOYMENT_TARGET": "1.0" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "defaultConfigurationName": "Release", + "groupTree": { + "children": [ + { + "children": [], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_0", + "name": "AdditionalFiles", + "path": "/", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "wrapper.xcframework", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_1::REF_0", + "path": "/Users/thedderwick/Library/Developer/Xcode/DerivedData/SPMTest-akjbvrfwkrsolpeqhugesmlhclvn/SourcePackages/artifacts/mybinarydependency/MyBinaryDependency/Lottie.xcframework", + "sourceTree": "", + "type": "file" + }, + { + "fileType": "wrapper.xcframework", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_1::REF_1", + "path": "/Users/thedderwick/Library/Developer/Xcode/DerivedData/SPMTest-akjbvrfwkrsolpeqhugesmlhclvn/SourcePackages/artifacts/mybinarydependency/MyBinaryDependency/Lottie.xcframework", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_1", + "name": "Binaries", + "path": "/", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "sourcecode.swift", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_2::REF_0", + "path": "MyBinaryDependency.swift", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_2", + "name": "/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency/Sources/_Stub", + "path": "/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency/Sources/_Stub", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "sourcecode.swift", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_3::REF_0", + "path": "MyBinaryDependency.swift", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_3", + "name": "/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency/Sources/_Stub", + "path": "/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency/Sources/_Stub", + "sourceTree": "", + "type": "group" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP", + "name": "", + "path": "", + "sourceTree": "", + "type": "group" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency", + "path": "/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency/Package.swift", + "projectDirectory": "/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency", + "projectIsPackage": "true", + "projectName": "MyBinaryDependency", + "targets": [ + "TARGET@v12_hash=da546fca3b585ddf35a5a7d6d76bf04c", + "TARGET@v12_hash=322b71ca67a33085a0152ac83f23a35f", + "TARGET@v12_hash=5c5fac44a4728a01cbe089b857eb0636", + "TARGET@v12_hash=8de09bc5397dcfbae930a9e8ab952e62" + ] +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=60e18114455190230d62ad086fd6a1d5-json b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=60e18114455190230d62ad086fd6a1d5-json new file mode 100644 index 0000000..8458f70 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=60e18114455190230d62ad086fd6a1d5-json @@ -0,0 +1,221 @@ +{ + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_OBJC_ARC": "YES", + "CODE_SIGNING_REQUIRED": "NO", + "CODE_SIGN_IDENTITY": "", + "COPY_PHASE_STRIP": "NO", + "DEBUG_INFORMATION_FORMAT": "dwarf", + "DRIVERKIT_DEPLOYMENT_TARGET": "19.0", + "DYLIB_INSTALL_NAME_BASE": "@rpath", + "ENABLE_NS_ASSERTIONS": "YES", + "ENABLE_TESTABILITY": "YES", + "ENABLE_TESTING_SEARCH_PATHS": "YES", + "ENTITLEMENTS_REQUIRED": "NO", + "GCC_OPTIMIZATION_LEVEL": "0", + "GCC_PREPROCESSOR_DEFINITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG=1" + ], + "IPHONEOS_DEPLOYMENT_TARGET": "12.0", + "IPHONEOS_DEPLOYMENT_TARGET[__platform_filter=ios-maccatalyst]": [ + "13.0" + ], + "KEEP_PRIVATE_EXTERNS": "NO", + "MACOSX_DEPLOYMENT_TARGET": "10.13", + "ONLY_ACTIVE_ARCH": "YES", + "OTHER_CFLAGS": [ + "$(inherited)", + "-DXcode" + ], + "OTHER_LDRFLAGS": [], + "OTHER_SWIFT_FLAGS": [ + "$(inherited)", + "-DXcode" + ], + "PRODUCT_NAME": "$(TARGET_NAME)", + "SKIP_CLANG_STATIC_ANALYZER": "YES", + "SKIP_INSTALL": "YES", + "SUPPORTED_PLATFORMS": [ + "$(AVAILABLE_PLATFORMS)" + ], + "SUPPRESS_WARNINGS": "YES", + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG" + ], + "SWIFT_INSTALL_OBJC_HEADER": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "", + "SWIFT_OPTIMIZATION_LEVEL": "-Onone", + "TARGETED_DEVICE_FAMILY": "1,2,3,4,6,7", + "TVOS_DEPLOYMENT_TARGET": "12.0", + "USE_HEADERMAP": "NO", + "WATCHOS_DEPLOYMENT_TARGET": "5.0", + "XROS_DEPLOYMENT_TARGET": "1.0" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_OBJC_ARC": "YES", + "CODE_SIGNING_REQUIRED": "NO", + "CODE_SIGN_IDENTITY": "", + "COPY_PHASE_STRIP": "YES", + "DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym", + "DRIVERKIT_DEPLOYMENT_TARGET": "19.0", + "DYLIB_INSTALL_NAME_BASE": "@rpath", + "ENABLE_TESTING_SEARCH_PATHS": "YES", + "ENTITLEMENTS_REQUIRED": "NO", + "GCC_OPTIMIZATION_LEVEL": "s", + "GCC_PREPROCESSOR_DEFINITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE" + ], + "IPHONEOS_DEPLOYMENT_TARGET": "12.0", + "IPHONEOS_DEPLOYMENT_TARGET[__platform_filter=ios-maccatalyst]": [ + "13.0" + ], + "KEEP_PRIVATE_EXTERNS": "NO", + "MACOSX_DEPLOYMENT_TARGET": "10.13", + "OTHER_CFLAGS": [ + "$(inherited)", + "-DXcode" + ], + "OTHER_LDRFLAGS": [], + "OTHER_SWIFT_FLAGS": [ + "$(inherited)", + "-DXcode" + ], + "PRODUCT_NAME": "$(TARGET_NAME)", + "SKIP_CLANG_STATIC_ANALYZER": "YES", + "SKIP_INSTALL": "YES", + "SUPPORTED_PLATFORMS": [ + "$(AVAILABLE_PLATFORMS)" + ], + "SUPPRESS_WARNINGS": "YES", + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE" + ], + "SWIFT_INSTALL_OBJC_HEADER": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "", + "SWIFT_OPTIMIZATION_LEVEL": "-Owholemodule", + "TARGETED_DEVICE_FAMILY": "1,2,3,4,6,7", + "TVOS_DEPLOYMENT_TARGET": "12.0", + "USE_HEADERMAP": "NO", + "WATCHOS_DEPLOYMENT_TARGET": "5.0", + "XROS_DEPLOYMENT_TARGET": "1.0" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "defaultConfigurationName": "Release", + "groupTree": { + "children": [ + { + "children": [], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_0", + "name": "AdditionalFiles", + "path": "/", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "wrapper.xcframework", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_1::REF_0", + "path": "/Users/thedderwick/Library/Developer/Xcode/DerivedData/SPMTest-akjbvrfwkrsolpeqhugesmlhclvn/SourcePackages/artifacts/mybinarydependency/MyBinaryDependency/Lottie.xcframework", + "sourceTree": "", + "type": "file" + }, + { + "fileType": "wrapper.xcframework", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_1::REF_1", + "path": "/Users/thedderwick/Library/Developer/Xcode/DerivedData/SPMTest-akjbvrfwkrsolpeqhugesmlhclvn/SourcePackages/artifacts/mybinarydependency/MyBinaryDependency/Lottie.xcframework", + "sourceTree": "", + "type": "file" + }, + { + "fileType": "wrapper.xcframework", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_1::REF_2", + "path": "/Users/thedderwick/Library/Developer/Xcode/DerivedData/SPMTest-akjbvrfwkrsolpeqhugesmlhclvn/SourcePackages/artifacts/mybinarydependency/MyBinaryDependency/Lottie.xcframework", + "sourceTree": "", + "type": "file" + }, + { + "fileType": "wrapper.xcframework", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_1::REF_3", + "path": "/Users/thedderwick/Library/Developer/Xcode/DerivedData/SPMTest-akjbvrfwkrsolpeqhugesmlhclvn/SourcePackages/artifacts/mybinarydependency/MyBinaryDependency/Lottie.xcframework", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_1", + "name": "Binaries", + "path": "/", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "sourcecode.swift", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_2::REF_0", + "path": "MyTransitiveLibrary.swift", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_2", + "name": "/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary/Sources/MyTransitiveLibrary", + "path": "/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary/Sources/MyTransitiveLibrary", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "sourcecode.swift", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_3::REF_0", + "path": "MyTransitiveLibrary.swift", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_3", + "name": "/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary/Sources/MyTransitiveLibrary", + "path": "/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary/Sources/MyTransitiveLibrary", + "sourceTree": "", + "type": "group" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP", + "name": "", + "path": "", + "sourceTree": "", + "type": "group" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary", + "path": "/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary/Package.swift", + "projectDirectory": "/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary", + "projectIsPackage": "true", + "projectName": "MyTransitiveLibrary", + "targets": [ + "TARGET@v12_hash=fb7de2da6bb6f870c73ba0c83581f638", + "TARGET@v12_hash=85e5507488bfe17e9e4e18b38ecf6a38", + "TARGET@v12_hash=f6b1fc5ff8b0c87e4d17a05b612118a8", + "TARGET@v12_hash=ec86d6a4683c2028c68c9a06f9947bf3" + ] +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=d061ee81d8927d5b63443e777e83938a-json b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=d061ee81d8927d5b63443e777e83938a-json new file mode 100644 index 0000000..8aedf87 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PACKAGE@v12_hash=d061ee81d8927d5b63443e777e83938a-json @@ -0,0 +1,192 @@ +{ + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_OBJC_ARC": "YES", + "CODE_SIGNING_REQUIRED": "NO", + "CODE_SIGN_IDENTITY": "", + "COPY_PHASE_STRIP": "NO", + "DEBUG_INFORMATION_FORMAT": "dwarf", + "DRIVERKIT_DEPLOYMENT_TARGET": "19.0", + "DYLIB_INSTALL_NAME_BASE": "@rpath", + "ENABLE_NS_ASSERTIONS": "YES", + "ENABLE_TESTABILITY": "YES", + "ENABLE_TESTING_SEARCH_PATHS": "YES", + "ENTITLEMENTS_REQUIRED": "NO", + "GCC_OPTIMIZATION_LEVEL": "0", + "GCC_PREPROCESSOR_DEFINITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG=1" + ], + "IPHONEOS_DEPLOYMENT_TARGET": "12.0", + "IPHONEOS_DEPLOYMENT_TARGET[__platform_filter=ios-maccatalyst]": [ + "13.0" + ], + "KEEP_PRIVATE_EXTERNS": "NO", + "MACOSX_DEPLOYMENT_TARGET": "10.13", + "ONLY_ACTIVE_ARCH": "YES", + "OTHER_CFLAGS": [ + "$(inherited)", + "-DXcode" + ], + "OTHER_LDRFLAGS": [], + "OTHER_SWIFT_FLAGS": [ + "$(inherited)", + "-DXcode" + ], + "PRODUCT_NAME": "$(TARGET_NAME)", + "SKIP_CLANG_STATIC_ANALYZER": "YES", + "SKIP_INSTALL": "YES", + "SUPPORTED_PLATFORMS": [ + "$(AVAILABLE_PLATFORMS)" + ], + "SUPPRESS_WARNINGS": "YES", + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE", + "DEBUG" + ], + "SWIFT_INSTALL_OBJC_HEADER": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "", + "SWIFT_OPTIMIZATION_LEVEL": "-Onone", + "TARGETED_DEVICE_FAMILY": "1,2,3,4,6,7", + "TVOS_DEPLOYMENT_TARGET": "12.0", + "USE_HEADERMAP": "NO", + "WATCHOS_DEPLOYMENT_TARGET": "5.0", + "XROS_DEPLOYMENT_TARGET": "1.0" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_OBJC_ARC": "YES", + "CODE_SIGNING_REQUIRED": "NO", + "CODE_SIGN_IDENTITY": "", + "COPY_PHASE_STRIP": "YES", + "DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym", + "DRIVERKIT_DEPLOYMENT_TARGET": "19.0", + "DYLIB_INSTALL_NAME_BASE": "@rpath", + "ENABLE_TESTING_SEARCH_PATHS": "YES", + "ENTITLEMENTS_REQUIRED": "NO", + "GCC_OPTIMIZATION_LEVEL": "s", + "GCC_PREPROCESSOR_DEFINITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE" + ], + "IPHONEOS_DEPLOYMENT_TARGET": "12.0", + "IPHONEOS_DEPLOYMENT_TARGET[__platform_filter=ios-maccatalyst]": [ + "13.0" + ], + "KEEP_PRIVATE_EXTERNS": "NO", + "MACOSX_DEPLOYMENT_TARGET": "10.13", + "OTHER_CFLAGS": [ + "$(inherited)", + "-DXcode" + ], + "OTHER_LDRFLAGS": [], + "OTHER_SWIFT_FLAGS": [ + "$(inherited)", + "-DXcode" + ], + "PRODUCT_NAME": "$(TARGET_NAME)", + "SKIP_CLANG_STATIC_ANALYZER": "YES", + "SKIP_INSTALL": "YES", + "SUPPORTED_PLATFORMS": [ + "$(AVAILABLE_PLATFORMS)" + ], + "SUPPRESS_WARNINGS": "YES", + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": [ + "$(inherited)", + "SWIFT_PACKAGE" + ], + "SWIFT_INSTALL_OBJC_HEADER": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "", + "SWIFT_OPTIMIZATION_LEVEL": "-Owholemodule", + "TARGETED_DEVICE_FAMILY": "1,2,3,4,6,7", + "TVOS_DEPLOYMENT_TARGET": "12.0", + "USE_HEADERMAP": "NO", + "WATCHOS_DEPLOYMENT_TARGET": "5.0", + "XROS_DEPLOYMENT_TARGET": "1.0" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "defaultConfigurationName": "Release", + "groupTree": { + "children": [ + { + "children": [], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::MAINGROUP::REF_0", + "name": "AdditionalFiles", + "path": "/", + "sourceTree": "", + "type": "group" + }, + { + "children": [], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::MAINGROUP::REF_1", + "name": "Binaries", + "path": "/", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "sourcecode.swift", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::MAINGROUP::REF_2::REF_0", + "path": "MyCommonLibrary.swift", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::MAINGROUP::REF_2", + "name": "/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary/Sources/MyCommonLibrary", + "path": "/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary/Sources/MyCommonLibrary", + "sourceTree": "", + "type": "group" + }, + { + "children": [ + { + "fileType": "sourcecode.swift", + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::MAINGROUP::REF_3::REF_0", + "path": "MyCommonLibrary.swift", + "sourceTree": "", + "type": "file" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::MAINGROUP::REF_3", + "name": "/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary/Sources/MyCommonLibrary", + "path": "/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary/Sources/MyCommonLibrary", + "sourceTree": "", + "type": "group" + } + ], + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::MAINGROUP", + "name": "", + "path": "", + "sourceTree": "", + "type": "group" + }, + "guid": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary", + "path": "/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary/Package.swift", + "projectDirectory": "/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary", + "projectIsPackage": "true", + "projectName": "MyCommonLibrary", + "targets": [ + "TARGET@v12_hash=7fe91a1e2b8f90031d23796421a46a09", + "TARGET@v12_hash=c5eeab26a0e301a2419ee7e6d1254b52", + "TARGET@v12_hash=27eb3a98abb5101fe49563a2824e9794", + "TARGET@v12_hash=e0ad90d36af3737ec5215a32f000294d" + ] +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/project/PROJECT@v11_mod=1716537774.576404_hash=0f958f39499d9f0b6b454948d2be549bplugins=1OJSG6M1FOV3XYQCBH7Z29RZ0FPR9XDE1-json b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PROJECT@v11_mod=1716537774.576404_hash=0f958f39499d9f0b6b454948d2be549bplugins=1OJSG6M1FOV3XYQCBH7Z29RZ0FPR9XDE1-json new file mode 100644 index 0000000..6ce343f --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/project/PROJECT@v11_mod=1716537774.576404_hash=0f958f39499d9f0b6b454948d2be549bplugins=1OJSG6M1FOV3XYQCBH7Z29RZ0FPR9XDE1-json @@ -0,0 +1,192 @@ +{ + "appPreferencesBuildSettings": {}, + "buildConfigurations": [ + { + "buildSettings": { + "ALWAYS_SEARCH_USER_PATHS": "NO", + "ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS": "YES", + "CLANG_ANALYZER_NONNULL": "YES", + "CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION": "YES_AGGRESSIVE", + "CLANG_CXX_LANGUAGE_STANDARD": "gnu++20", + "CLANG_ENABLE_MODULES": "YES", + "CLANG_ENABLE_OBJC_ARC": "YES", + "CLANG_ENABLE_OBJC_WEAK": "YES", + "CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING": "YES", + "CLANG_WARN_BOOL_CONVERSION": "YES", + "CLANG_WARN_COMMA": "YES", + "CLANG_WARN_CONSTANT_CONVERSION": "YES", + "CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS": "YES", + "CLANG_WARN_DIRECT_OBJC_ISA_USAGE": "YES_ERROR", + "CLANG_WARN_DOCUMENTATION_COMMENTS": "YES", + "CLANG_WARN_EMPTY_BODY": "YES", + "CLANG_WARN_ENUM_CONVERSION": "YES", + "CLANG_WARN_INFINITE_RECURSION": "YES", + "CLANG_WARN_INT_CONVERSION": "YES", + "CLANG_WARN_NON_LITERAL_NULL_CONVERSION": "YES", + "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF": "YES", + "CLANG_WARN_OBJC_LITERAL_CONVERSION": "YES", + "CLANG_WARN_OBJC_ROOT_CLASS": "YES_ERROR", + "CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER": "YES", + "CLANG_WARN_RANGE_LOOP_ANALYSIS": "YES", + "CLANG_WARN_STRICT_PROTOTYPES": "YES", + "CLANG_WARN_SUSPICIOUS_MOVE": "YES", + "CLANG_WARN_UNGUARDED_AVAILABILITY": "YES_AGGRESSIVE", + "CLANG_WARN_UNREACHABLE_CODE": "YES", + "CLANG_WARN__DUPLICATE_METHOD_MATCH": "YES", + "COPY_PHASE_STRIP": "NO", + "DEBUG_INFORMATION_FORMAT": "dwarf", + "ENABLE_STRICT_OBJC_MSGSEND": "YES", + "ENABLE_TESTABILITY": "YES", + "ENABLE_USER_SCRIPT_SANDBOXING": "YES", + "GCC_C_LANGUAGE_STANDARD": "gnu17", + "GCC_DYNAMIC_NO_PIC": "NO", + "GCC_NO_COMMON_BLOCKS": "YES", + "GCC_OPTIMIZATION_LEVEL": "0", + "GCC_PREPROCESSOR_DEFINITIONS": "DEBUG=1 $(inherited)", + "GCC_WARN_64_TO_32_BIT_CONVERSION": "YES", + "GCC_WARN_ABOUT_RETURN_TYPE": "YES_ERROR", + "GCC_WARN_UNDECLARED_SELECTOR": "YES", + "GCC_WARN_UNINITIALIZED_AUTOS": "YES_AGGRESSIVE", + "GCC_WARN_UNUSED_FUNCTION": "YES", + "GCC_WARN_UNUSED_VARIABLE": "YES", + "IPHONEOS_DEPLOYMENT_TARGET": "17.4", + "LOCALIZATION_PREFERS_STRING_CATALOGS": "YES", + "MTL_ENABLE_DEBUG_INFO": "INCLUDE_SOURCE", + "MTL_FAST_MATH": "YES", + "ONLY_ACTIVE_ARCH": "YES", + "SDKROOT": "iphoneos", + "SWIFT_ACTIVE_COMPILATION_CONDITIONS": "DEBUG $(inherited)", + "SWIFT_OPTIMIZATION_LEVEL": "-Onone" + }, + "guid": "0f958f39499d9f0b6b454948d2be549b42f5c53a127a9a1a044740c8d5a00ed1", + "name": "Debug" + }, + { + "buildSettings": { + "ALWAYS_SEARCH_USER_PATHS": "NO", + "ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS": "YES", + "CLANG_ANALYZER_NONNULL": "YES", + "CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION": "YES_AGGRESSIVE", + "CLANG_CXX_LANGUAGE_STANDARD": "gnu++20", + "CLANG_ENABLE_MODULES": "YES", + "CLANG_ENABLE_OBJC_ARC": "YES", + "CLANG_ENABLE_OBJC_WEAK": "YES", + "CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING": "YES", + "CLANG_WARN_BOOL_CONVERSION": "YES", + "CLANG_WARN_COMMA": "YES", + "CLANG_WARN_CONSTANT_CONVERSION": "YES", + "CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS": "YES", + "CLANG_WARN_DIRECT_OBJC_ISA_USAGE": "YES_ERROR", + "CLANG_WARN_DOCUMENTATION_COMMENTS": "YES", + "CLANG_WARN_EMPTY_BODY": "YES", + "CLANG_WARN_ENUM_CONVERSION": "YES", + "CLANG_WARN_INFINITE_RECURSION": "YES", + "CLANG_WARN_INT_CONVERSION": "YES", + "CLANG_WARN_NON_LITERAL_NULL_CONVERSION": "YES", + "CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF": "YES", + "CLANG_WARN_OBJC_LITERAL_CONVERSION": "YES", + "CLANG_WARN_OBJC_ROOT_CLASS": "YES_ERROR", + "CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER": "YES", + "CLANG_WARN_RANGE_LOOP_ANALYSIS": "YES", + "CLANG_WARN_STRICT_PROTOTYPES": "YES", + "CLANG_WARN_SUSPICIOUS_MOVE": "YES", + "CLANG_WARN_UNGUARDED_AVAILABILITY": "YES_AGGRESSIVE", + "CLANG_WARN_UNREACHABLE_CODE": "YES", + "CLANG_WARN__DUPLICATE_METHOD_MATCH": "YES", + "COPY_PHASE_STRIP": "NO", + "DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym", + "ENABLE_NS_ASSERTIONS": "NO", + "ENABLE_STRICT_OBJC_MSGSEND": "YES", + "ENABLE_USER_SCRIPT_SANDBOXING": "YES", + "GCC_C_LANGUAGE_STANDARD": "gnu17", + "GCC_NO_COMMON_BLOCKS": "YES", + "GCC_WARN_64_TO_32_BIT_CONVERSION": "YES", + "GCC_WARN_ABOUT_RETURN_TYPE": "YES_ERROR", + "GCC_WARN_UNDECLARED_SELECTOR": "YES", + "GCC_WARN_UNINITIALIZED_AUTOS": "YES_AGGRESSIVE", + "GCC_WARN_UNUSED_FUNCTION": "YES", + "GCC_WARN_UNUSED_VARIABLE": "YES", + "IPHONEOS_DEPLOYMENT_TARGET": "17.4", + "LOCALIZATION_PREFERS_STRING_CATALOGS": "YES", + "MTL_ENABLE_DEBUG_INFO": "NO", + "MTL_FAST_MATH": "YES", + "SDKROOT": "iphoneos", + "SWIFT_COMPILATION_MODE": "wholemodule", + "VALIDATE_PRODUCT": "YES" + }, + "guid": "0f958f39499d9f0b6b454948d2be549bfc0d140c3c428c4be4300c4ad84f502b", + "name": "Release" + } + ], + "classPrefix": "", + "defaultConfigurationName": "Release", + "developmentRegion": "en", + "groupTree": { + "children": [ + { + "children": [ + { + "fileType": "sourcecode.swift", + "guid": "0f958f39499d9f0b6b454948d2be549bfecf073ab7da34165ac491b2cb2608da", + "path": "SPMTestApp.swift", + "sourceTree": "", + "type": "file" + }, + { + "fileType": "sourcecode.swift", + "guid": "0f958f39499d9f0b6b454948d2be549bb774bcb839cea612c4808e51e76f1d8a", + "path": "ContentView.swift", + "sourceTree": "", + "type": "file" + }, + { + "fileType": "folder.assetcatalog", + "guid": "0f958f39499d9f0b6b454948d2be549b63f219360fcbccc1f13e995b6d2c55bd", + "path": "Assets.xcassets", + "sourceTree": "", + "type": "file" + }, + { + "children": [ + { + "fileType": "folder.assetcatalog", + "guid": "0f958f39499d9f0b6b454948d2be549be0988c6a6200faa66fc4e43736a838c5", + "path": "Preview Assets.xcassets", + "sourceTree": "", + "type": "file" + } + ], + "guid": "0f958f39499d9f0b6b454948d2be549b2f11424f01062300b0bebb6c9130131b", + "name": "Preview Content", + "path": "Preview Content", + "sourceTree": "", + "type": "group" + } + ], + "guid": "0f958f39499d9f0b6b454948d2be549b435ba3b373201685aef000e70e51db4d", + "name": "SPMTest", + "path": "SPMTest", + "sourceTree": "", + "type": "group" + }, + { + "guid": "0f958f39499d9f0b6b454948d2be549befe9d7653bff13bf45841ede70f783cd", + "name": "Products", + "path": "", + "sourceTree": "", + "type": "group" + } + ], + "guid": "0f958f39499d9f0b6b454948d2be549b33bedd8701761212ef2c3a2c378a8e0b", + "name": "SPMTest", + "path": "", + "sourceTree": "", + "type": "group" + }, + "guid": "0f958f39499d9f0b6b454948d2be549b", + "path": "/Users/thedderwick/Desktop/SPMTest/SPMTest.xcodeproj", + "projectDirectory": "/Users/thedderwick/Desktop/SPMTest", + "targets": [ + "TARGET@v11_hash=d5012c60a72570c6ac682d8666f0e4a1" + ] +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v11_hash=d5012c60a72570c6ac682d8666f0e4a1-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v11_hash=d5012c60a72570c6ac682d8666f0e4a1-json new file mode 100644 index 0000000..4cc5168 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v11_hash=d5012c60a72570c6ac682d8666f0e4a1-json @@ -0,0 +1,137 @@ +{ + "buildConfigurations": [ + { + "buildSettings": { + "ASSETCATALOG_COMPILER_APPICON_NAME": "AppIcon", + "ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME": "AccentColor", + "CODE_SIGN_IDENTITY": "", + "CODE_SIGN_STYLE": "Manual", + "CURRENT_PROJECT_VERSION": "1", + "DEVELOPMENT_ASSET_PATHS": "\"SPMTest/Preview Content\"", + "DEVELOPMENT_TEAM": "", + "ENABLE_PREVIEWS": "YES", + "GENERATE_INFOPLIST_FILE": "YES", + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation": "YES", + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents": "YES", + "INFOPLIST_KEY_UILaunchScreen_Generation": "YES", + "INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad": "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight", + "INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone": "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight", + "LD_RUNPATH_SEARCH_PATHS": "$(inherited) @executable_path/Frameworks", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "com.veracode.SPMTest", + "PRODUCT_NAME": "$(TARGET_NAME)", + "PROVISIONING_PROFILE_SPECIFIER": "", + "SWIFT_EMIT_LOC_STRINGS": "YES", + "SWIFT_VERSION": "5.0", + "TARGETED_DEVICE_FAMILY": "1,2" + }, + "guid": "0f958f39499d9f0b6b454948d2be549b4cca86b4d9d5847565233659a29761c4", + "name": "Debug" + }, + { + "buildSettings": { + "ASSETCATALOG_COMPILER_APPICON_NAME": "AppIcon", + "ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME": "AccentColor", + "CODE_SIGN_IDENTITY": "", + "CODE_SIGN_STYLE": "Manual", + "CURRENT_PROJECT_VERSION": "1", + "DEVELOPMENT_ASSET_PATHS": "\"SPMTest/Preview Content\"", + "DEVELOPMENT_TEAM": "", + "ENABLE_PREVIEWS": "YES", + "GENERATE_INFOPLIST_FILE": "YES", + "INFOPLIST_KEY_UIApplicationSceneManifest_Generation": "YES", + "INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents": "YES", + "INFOPLIST_KEY_UILaunchScreen_Generation": "YES", + "INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad": "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight", + "INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone": "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight", + "LD_RUNPATH_SEARCH_PATHS": "$(inherited) @executable_path/Frameworks", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "com.veracode.SPMTest", + "PRODUCT_NAME": "$(TARGET_NAME)", + "PROVISIONING_PROFILE_SPECIFIER": "", + "SWIFT_EMIT_LOC_STRINGS": "YES", + "SWIFT_VERSION": "5.0", + "TARGETED_DEVICE_FAMILY": "1,2" + }, + "guid": "0f958f39499d9f0b6b454948d2be549bb821c619cfb8b2e724c5328e54f54e17", + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "fileReference": "0f958f39499d9f0b6b454948d2be549bb774bcb839cea612c4808e51e76f1d8a", + "guid": "0f958f39499d9f0b6b454948d2be549b7a45127807cf63f6589a4a0de9d1e716" + }, + { + "fileReference": "0f958f39499d9f0b6b454948d2be549bfecf073ab7da34165ac491b2cb2608da", + "guid": "0f958f39499d9f0b6b454948d2be549bd0950f9139cbf08f13714ef301b71636" + } + ], + "guid": "0f958f39499d9f0b6b454948d2be549b1112b312486e6592252467de83ac12fa", + "type": "com.apple.buildphase.sources" + }, + { + "buildFiles": [ + { + "guid": "0f958f39499d9f0b6b454948d2be549bae8c757dc1f71dc80677176e88f57513", + "targetReference": "PACKAGE-PRODUCT:MyLibrary" + }, + { + "guid": "0f958f39499d9f0b6b454948d2be549b1990e4c3872d798fb604b5b6dde1e9d7", + "targetReference": "PACKAGE-PRODUCT:MyCommonLibrary" + } + ], + "guid": "0f958f39499d9f0b6b454948d2be549bc68ad644ebd05301e2324acbeb00d9ce", + "type": "com.apple.buildphase.frameworks" + }, + { + "buildFiles": [ + { + "fileReference": "0f958f39499d9f0b6b454948d2be549be0988c6a6200faa66fc4e43736a838c5", + "guid": "0f958f39499d9f0b6b454948d2be549b2bdba7efbecb87014e782e630cad919b" + }, + { + "fileReference": "0f958f39499d9f0b6b454948d2be549b63f219360fcbccc1f13e995b6d2c55bd", + "guid": "0f958f39499d9f0b6b454948d2be549b011725fb4c17cd464e9eeb9cd6e70496" + } + ], + "guid": "0f958f39499d9f0b6b454948d2be549b42f6470020217a2716154a23e1ad07ff", + "type": "com.apple.buildphase.resources" + } + ], + "buildRules": [], + "dependencies": [ + { + "guid": "PACKAGE-PRODUCT:MyLibrary", + "name": "MyLibrary" + }, + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "name": "MyCommonLibrary" + } + ], + "guid": "0f958f39499d9f0b6b454948d2be549be609cf86f8e7120d04a2edc980fbcfa8", + "name": "SPMTest", + "predominantSourceCodeLanguage": "Xcode.SourceCodeLanguage.Swift", + "productReference": { + "guid": "0f958f39499d9f0b6b454948d2be549b6201de4660da2a235e2bcde1105d0dfd", + "name": "SPMTest.app", + "type": "product" + }, + "productTypeIdentifier": "com.apple.product-type.application", + "provisioningSourceData": [ + { + "bundleIdentifierFromInfoPlist": "$(PRODUCT_BUNDLE_IDENTIFIER)", + "configurationName": "Debug", + "provisioningStyle": 1 + }, + { + "bundleIdentifierFromInfoPlist": "$(PRODUCT_BUNDLE_IDENTIFIER)", + "configurationName": "Release", + "provisioningStyle": 1 + } + ], + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=27eb3a98abb5101fe49563a2824e9794-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=27eb3a98abb5101fe49563a2824e9794-json new file mode 100644 index 0000000..d0beab8 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=27eb3a98abb5101fe49563a2824e9794-json @@ -0,0 +1,128 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_COVERAGE_MAPPING_LINKER_ARGS": "NO", + "CLANG_ENABLE_MODULES": "YES", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyCommonLibrary.o", + "GENERATE_MASTER_OBJECT_FILE": "NO", + "MACH_O_TYPE": "mh_object", + "MODULEMAP_FILE_CONTENTS": "module MyCommonLibrary {\nheader \"MyCommonLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyCommonLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyCommonLibrary", + "PRODUCT_MODULE_NAME": "MyCommonLibrary", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "STRIP_INSTALLED_PRODUCT": "NO", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyCommonLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mycommonlibrary", + "SWIFT_VERSION": "5", + "TAPI_DYLIB_INSTALL_NAME": "MyCommonLibrary", + "TARGET_NAME": "MyCommonLibrary" + }, + "guid": "PACKAGE-TARGET:MyCommonLibrary::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "LD_RUNPATH_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyCommonLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_COVERAGE_MAPPING_LINKER_ARGS": "NO", + "CLANG_ENABLE_MODULES": "YES", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyCommonLibrary.o", + "GENERATE_MASTER_OBJECT_FILE": "NO", + "MACH_O_TYPE": "mh_object", + "MODULEMAP_FILE_CONTENTS": "module MyCommonLibrary {\nheader \"MyCommonLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyCommonLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyCommonLibrary", + "PRODUCT_MODULE_NAME": "MyCommonLibrary", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "STRIP_INSTALLED_PRODUCT": "NO", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyCommonLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mycommonlibrary", + "SWIFT_VERSION": "5", + "TAPI_DYLIB_INSTALL_NAME": "MyCommonLibrary", + "TARGET_NAME": "MyCommonLibrary" + }, + "guid": "PACKAGE-TARGET:MyCommonLibrary::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyCommonLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "codeSignOnCopy": "false", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::MAINGROUP::REF_2::REF_0", + "guid": "PACKAGE-TARGET:MyCommonLibrary::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "false" + } + ], + "guid": "PACKAGE-TARGET:MyCommonLibrary::BUILDPHASE_0", + "type": "com.apple.buildphase.sources" + } + ], + "buildRules": [], + "dependencies": [], + "dynamicTargetVariantGuid": "PACKAGE-TARGET:MyCommonLibrary--138526C95691DCED-dynamic", + "guid": "PACKAGE-TARGET:MyCommonLibrary", + "name": "MyCommonLibrary", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-TARGET:MyCommonLibrary", + "name": "MyCommonLibrary.o", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.objfile", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=322b71ca67a33085a0152ac83f23a35f-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=322b71ca67a33085a0152ac83f23a35f-json new file mode 100644 index 0000000..bfc0190 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=322b71ca67a33085a0152ac83f23a35f-json @@ -0,0 +1,92 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "EXECUTABLE_NAME": "MyBinaryDependency_-5B0EB316CCB8BC4_PackageProduct", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "MyBinaryDependency", + "PRODUCT_MODULE_NAME": "MyBinaryDependency", + "PRODUCT_NAME": "MyBinaryDependency_-5B0EB316CCB8BC4_PackageProduct", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SWIFT_PACKAGE_NAME": "mybinarydependency", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyBinaryDependency product", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyBinaryDependency--5B0EB316CCB8BC4-dynamic::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "EXECUTABLE_NAME": "MyBinaryDependency_-5B0EB316CCB8BC4_PackageProduct", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "MyBinaryDependency", + "PRODUCT_MODULE_NAME": "MyBinaryDependency", + "PRODUCT_NAME": "MyBinaryDependency_-5B0EB316CCB8BC4_PackageProduct", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SWIFT_PACKAGE_NAME": "mybinarydependency", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyBinaryDependency product", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyBinaryDependency--5B0EB316CCB8BC4-dynamic::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "codeSignOnCopy": "true", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_1::REF_1", + "guid": "PACKAGE-PRODUCT:MyBinaryDependency--5B0EB316CCB8BC4-dynamic::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "true" + }, + { + "guid": "PACKAGE-PRODUCT:MyBinaryDependency--5B0EB316CCB8BC4-dynamic::BUILDPHASE_0::1", + "platformFilters": [], + "targetReference": "PACKAGE-TARGET:_Stub" + } + ], + "guid": "PACKAGE-PRODUCT:MyBinaryDependency--5B0EB316CCB8BC4-dynamic::BUILDPHASE_0", + "type": "com.apple.buildphase.frameworks" + }, + { + "buildFiles": [], + "guid": "PACKAGE-PRODUCT:MyBinaryDependency--5B0EB316CCB8BC4-dynamic::BUILDPHASE_1", + "type": "com.apple.buildphase.sources" + } + ], + "buildRules": [], + "dependencies": [ + { + "guid": "PACKAGE-TARGET:_Stub", + "platformFilters": [] + } + ], + "guid": "PACKAGE-PRODUCT:MyBinaryDependency--5B0EB316CCB8BC4-dynamic", + "name": "MyBinaryDependency", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-PRODUCT:MyBinaryDependency--5B0EB316CCB8BC4-dynamic", + "name": "MyBinaryDependency_-5B0EB316CCB8BC4_PackageProduct.framework", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.framework", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=5c5fac44a4728a01cbe089b857eb0636-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=5c5fac44a4728a01cbe089b857eb0636-json new file mode 100644 index 0000000..bf7f212 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=5c5fac44a4728a01cbe089b857eb0636-json @@ -0,0 +1,128 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_COVERAGE_MAPPING_LINKER_ARGS": "NO", + "CLANG_ENABLE_MODULES": "YES", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "_Stub.o", + "GENERATE_MASTER_OBJECT_FILE": "NO", + "MACH_O_TYPE": "mh_object", + "MODULEMAP_FILE_CONTENTS": "module _Stub {\nheader \"_Stub-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/_Stub.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "_Stub", + "PRODUCT_MODULE_NAME": "_Stub", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "STRIP_INSTALLED_PRODUCT": "NO", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "_Stub-Swift.h", + "SWIFT_PACKAGE_NAME": "mybinarydependency", + "SWIFT_VERSION": "5", + "TAPI_DYLIB_INSTALL_NAME": "_Stub", + "TARGET_NAME": "_Stub" + }, + "guid": "PACKAGE-TARGET:_Stub::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "LD_RUNPATH_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/_Stub.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_COVERAGE_MAPPING_LINKER_ARGS": "NO", + "CLANG_ENABLE_MODULES": "YES", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "_Stub.o", + "GENERATE_MASTER_OBJECT_FILE": "NO", + "MACH_O_TYPE": "mh_object", + "MODULEMAP_FILE_CONTENTS": "module _Stub {\nheader \"_Stub-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/_Stub.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "_Stub", + "PRODUCT_MODULE_NAME": "_Stub", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "STRIP_INSTALLED_PRODUCT": "NO", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "_Stub-Swift.h", + "SWIFT_PACKAGE_NAME": "mybinarydependency", + "SWIFT_VERSION": "5", + "TAPI_DYLIB_INSTALL_NAME": "_Stub", + "TARGET_NAME": "_Stub" + }, + "guid": "PACKAGE-TARGET:_Stub::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/_Stub.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "codeSignOnCopy": "false", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_2::REF_0", + "guid": "PACKAGE-TARGET:_Stub::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "false" + } + ], + "guid": "PACKAGE-TARGET:_Stub::BUILDPHASE_0", + "type": "com.apple.buildphase.sources" + } + ], + "buildRules": [], + "dependencies": [], + "dynamicTargetVariantGuid": "PACKAGE-TARGET:_Stub-F15A07A8D42-dynamic", + "guid": "PACKAGE-TARGET:_Stub", + "name": "_Stub", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-TARGET:_Stub", + "name": "_Stub.o", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.objfile", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=74b26d184242037107e47412d7443f08-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=74b26d184242037107e47412d7443f08-json new file mode 100644 index 0000000..a3b683f --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=74b26d184242037107e47412d7443f08-json @@ -0,0 +1,68 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyLibrary::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyLibrary::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "dependencies": [ + { + "guid": "PACKAGE-TARGET:MyLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "platformFilters": [] + } + ], + "dynamicTargetVariantGuid": "PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic", + "frameworksBuildPhase": { + "buildFiles": [ + { + "guid": "PACKAGE-PRODUCT:MyLibrary::BUILDPHASE_0::0", + "platformFilters": [], + "targetReference": "PACKAGE-TARGET:MyLibrary" + }, + { + "guid": "PACKAGE-PRODUCT:MyLibrary::BUILDPHASE_0::1", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyTransitiveLibrary" + }, + { + "guid": "PACKAGE-PRODUCT:MyLibrary::BUILDPHASE_0::2", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyCommonLibrary" + } + ], + "guid": "PACKAGE-PRODUCT:MyLibrary::BUILDPHASE_0", + "type": "com.apple.buildphase.frameworks" + }, + "guid": "PACKAGE-PRODUCT:MyLibrary", + "name": "MyLibrary", + "type": "packageProduct" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=7fe91a1e2b8f90031d23796421a46a09-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=7fe91a1e2b8f90031d23796421a46a09-json new file mode 100644 index 0000000..c869509 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=7fe91a1e2b8f90031d23796421a46a09-json @@ -0,0 +1,50 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyCommonLibrary::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyCommonLibrary::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "dependencies": [ + { + "guid": "PACKAGE-TARGET:MyCommonLibrary", + "platformFilters": [] + } + ], + "dynamicTargetVariantGuid": "PACKAGE-PRODUCT:MyCommonLibrary--138526C95691DCED-dynamic", + "frameworksBuildPhase": { + "buildFiles": [ + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary::BUILDPHASE_0::0", + "platformFilters": [], + "targetReference": "PACKAGE-TARGET:MyCommonLibrary" + } + ], + "guid": "PACKAGE-PRODUCT:MyCommonLibrary::BUILDPHASE_0", + "type": "com.apple.buildphase.frameworks" + }, + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "name": "MyCommonLibrary", + "type": "packageProduct" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=85e5507488bfe17e9e4e18b38ecf6a38-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=85e5507488bfe17e9e4e18b38ecf6a38-json new file mode 100644 index 0000000..c28cc3c --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=85e5507488bfe17e9e4e18b38ecf6a38-json @@ -0,0 +1,110 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "EXECUTABLE_NAME": "MyTransitiveLibrary_29D6C569F63C2FD7_PackageProduct", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "MyTransitiveLibrary", + "PRODUCT_MODULE_NAME": "MyTransitiveLibrary", + "PRODUCT_NAME": "MyTransitiveLibrary_29D6C569F63C2FD7_PackageProduct", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SWIFT_PACKAGE_NAME": "mytransitivelibrary", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyTransitiveLibrary product", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "EXECUTABLE_NAME": "MyTransitiveLibrary_29D6C569F63C2FD7_PackageProduct", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "MyTransitiveLibrary", + "PRODUCT_MODULE_NAME": "MyTransitiveLibrary", + "PRODUCT_NAME": "MyTransitiveLibrary_29D6C569F63C2FD7_PackageProduct", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SWIFT_PACKAGE_NAME": "mytransitivelibrary", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyTransitiveLibrary product", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_0::0", + "platformFilters": [], + "targetReference": "PACKAGE-TARGET:MyTransitiveLibrary" + }, + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_0::1", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyCommonLibrary" + }, + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_0::2", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyBinaryDependency" + }, + { + "codeSignOnCopy": "true", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_1::REF_1", + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_0::3", + "platformFilters": [], + "removeHeadersOnCopy": "true" + } + ], + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_0", + "type": "com.apple.buildphase.frameworks" + }, + { + "buildFiles": [], + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_1", + "type": "com.apple.buildphase.sources" + } + ], + "buildRules": [], + "dependencies": [ + { + "guid": "PACKAGE-TARGET:MyTransitiveLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyBinaryDependency", + "platformFilters": [] + } + ], + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic", + "name": "MyTransitiveLibrary", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic", + "name": "MyTransitiveLibrary_29D6C569F63C2FD7_PackageProduct.framework", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.framework", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=8de09bc5397dcfbae930a9e8ab952e62-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=8de09bc5397dcfbae930a9e8ab952e62-json new file mode 100644 index 0000000..34f0e82 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=8de09bc5397dcfbae930a9e8ab952e62-json @@ -0,0 +1,125 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "_Stub", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "MODULEMAP_FILE_CONTENTS": "module _Stub {\nheader \"_Stub-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/_Stub.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "_Stub", + "PRODUCT_MODULE_NAME": "_Stub", + "PRODUCT_NAME": "_Stub", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "_Stub-Swift.h", + "SWIFT_PACKAGE_NAME": "mybinarydependency", + "SWIFT_VERSION": "5", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "_Stub" + }, + "guid": "PACKAGE-TARGET:_Stub-F15A07A8D42-dynamic::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "LD_RUNPATH_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/_Stub.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "_Stub", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "MODULEMAP_FILE_CONTENTS": "module _Stub {\nheader \"_Stub-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/_Stub.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "_Stub", + "PRODUCT_MODULE_NAME": "_Stub", + "PRODUCT_NAME": "_Stub", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "_Stub-Swift.h", + "SWIFT_PACKAGE_NAME": "mybinarydependency", + "SWIFT_VERSION": "5", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "_Stub" + }, + "guid": "PACKAGE-TARGET:_Stub-F15A07A8D42-dynamic::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/_Stub.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "codeSignOnCopy": "false", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_3::REF_0", + "guid": "PACKAGE-TARGET:_Stub-F15A07A8D42-dynamic::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "false" + } + ], + "guid": "PACKAGE-TARGET:_Stub-F15A07A8D42-dynamic::BUILDPHASE_0", + "type": "com.apple.buildphase.sources" + } + ], + "buildRules": [], + "dependencies": [], + "guid": "PACKAGE-TARGET:_Stub-F15A07A8D42-dynamic", + "name": "_Stub", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-TARGET:_Stub-F15A07A8D42-dynamic", + "name": "_Stub.framework", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.framework", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=9b39f33b643d76adea258dfa2de06201-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=9b39f33b643d76adea258dfa2de06201-json new file mode 100644 index 0000000..93fdf4d --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=9b39f33b643d76adea258dfa2de06201-json @@ -0,0 +1,137 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_COVERAGE_MAPPING_LINKER_ARGS": "NO", + "CLANG_ENABLE_MODULES": "YES", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyLibrary.o", + "GENERATE_MASTER_OBJECT_FILE": "NO", + "MACH_O_TYPE": "mh_object", + "MODULEMAP_FILE_CONTENTS": "module MyLibrary {\nheader \"MyLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyLibrary", + "PRODUCT_MODULE_NAME": "MyLibrary", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "STRIP_INSTALLED_PRODUCT": "NO", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mylibrary", + "SWIFT_VERSION": "5", + "TAPI_DYLIB_INSTALL_NAME": "MyLibrary", + "TARGET_NAME": "MyLibrary" + }, + "guid": "PACKAGE-TARGET:MyLibrary::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "LD_RUNPATH_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_COVERAGE_MAPPING_LINKER_ARGS": "NO", + "CLANG_ENABLE_MODULES": "YES", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyLibrary.o", + "GENERATE_MASTER_OBJECT_FILE": "NO", + "MACH_O_TYPE": "mh_object", + "MODULEMAP_FILE_CONTENTS": "module MyLibrary {\nheader \"MyLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyLibrary", + "PRODUCT_MODULE_NAME": "MyLibrary", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "STRIP_INSTALLED_PRODUCT": "NO", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mylibrary", + "SWIFT_VERSION": "5", + "TAPI_DYLIB_INSTALL_NAME": "MyLibrary", + "TARGET_NAME": "MyLibrary" + }, + "guid": "PACKAGE-TARGET:MyLibrary::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "codeSignOnCopy": "false", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::MAINGROUP::REF_2::REF_0", + "guid": "PACKAGE-TARGET:MyLibrary::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "false" + } + ], + "guid": "PACKAGE-TARGET:MyLibrary::BUILDPHASE_0", + "type": "com.apple.buildphase.sources" + } + ], + "buildRules": [], + "dependencies": [ + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "platformFilters": [] + } + ], + "dynamicTargetVariantGuid": "PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic", + "guid": "PACKAGE-TARGET:MyLibrary", + "name": "MyLibrary", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-TARGET:MyLibrary", + "name": "MyLibrary.o", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.objfile", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=c5eeab26a0e301a2419ee7e6d1254b52-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=c5eeab26a0e301a2419ee7e6d1254b52-json new file mode 100644 index 0000000..d7daddd --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=c5eeab26a0e301a2419ee7e6d1254b52-json @@ -0,0 +1,85 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "EXECUTABLE_NAME": "MyCommonLibrary_-138526C95691DCED_PackageProduct", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "MyCommonLibrary", + "PRODUCT_MODULE_NAME": "MyCommonLibrary", + "PRODUCT_NAME": "MyCommonLibrary_-138526C95691DCED_PackageProduct", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SWIFT_PACKAGE_NAME": "mycommonlibrary", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyCommonLibrary product", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyCommonLibrary--138526C95691DCED-dynamic::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "EXECUTABLE_NAME": "MyCommonLibrary_-138526C95691DCED_PackageProduct", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "MyCommonLibrary", + "PRODUCT_MODULE_NAME": "MyCommonLibrary", + "PRODUCT_NAME": "MyCommonLibrary_-138526C95691DCED_PackageProduct", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SWIFT_PACKAGE_NAME": "mycommonlibrary", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyCommonLibrary product", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyCommonLibrary--138526C95691DCED-dynamic::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary--138526C95691DCED-dynamic::BUILDPHASE_0::0", + "platformFilters": [], + "targetReference": "PACKAGE-TARGET:MyCommonLibrary" + } + ], + "guid": "PACKAGE-PRODUCT:MyCommonLibrary--138526C95691DCED-dynamic::BUILDPHASE_0", + "type": "com.apple.buildphase.frameworks" + }, + { + "buildFiles": [], + "guid": "PACKAGE-PRODUCT:MyCommonLibrary--138526C95691DCED-dynamic::BUILDPHASE_1", + "type": "com.apple.buildphase.sources" + } + ], + "buildRules": [], + "dependencies": [ + { + "guid": "PACKAGE-TARGET:MyCommonLibrary", + "platformFilters": [] + } + ], + "guid": "PACKAGE-PRODUCT:MyCommonLibrary--138526C95691DCED-dynamic", + "name": "MyCommonLibrary", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-PRODUCT:MyCommonLibrary--138526C95691DCED-dynamic", + "name": "MyCommonLibrary_-138526C95691DCED_PackageProduct.framework", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.framework", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=cd6e9e040a1e22f4a8571a7087b8628e-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=cd6e9e040a1e22f4a8571a7087b8628e-json new file mode 100644 index 0000000..2b5a912 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=cd6e9e040a1e22f4a8571a7087b8628e-json @@ -0,0 +1,103 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "EXECUTABLE_NAME": "MyLibrary_-71ED4B7C0CDEC55C_PackageProduct", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "MyLibrary", + "PRODUCT_MODULE_NAME": "MyLibrary", + "PRODUCT_NAME": "MyLibrary_-71ED4B7C0CDEC55C_PackageProduct", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SWIFT_PACKAGE_NAME": "mylibrary", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyLibrary product", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "EXECUTABLE_NAME": "MyLibrary_-71ED4B7C0CDEC55C_PackageProduct", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "PRODUCT_BUNDLE_IDENTIFIER": "MyLibrary", + "PRODUCT_MODULE_NAME": "MyLibrary", + "PRODUCT_NAME": "MyLibrary_-71ED4B7C0CDEC55C_PackageProduct", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SWIFT_PACKAGE_NAME": "mylibrary", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyLibrary product", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "guid": "PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_0::0", + "platformFilters": [], + "targetReference": "PACKAGE-TARGET:MyLibrary" + }, + { + "guid": "PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_0::1", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyTransitiveLibrary" + }, + { + "guid": "PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_0::2", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyCommonLibrary" + } + ], + "guid": "PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_0", + "type": "com.apple.buildphase.frameworks" + }, + { + "buildFiles": [], + "guid": "PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_1", + "type": "com.apple.buildphase.sources" + } + ], + "buildRules": [], + "dependencies": [ + { + "guid": "PACKAGE-TARGET:MyLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "platformFilters": [] + } + ], + "guid": "PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic", + "name": "MyLibrary", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-PRODUCT:MyLibrary--71ED4B7C0CDEC55C-dynamic", + "name": "MyLibrary_-71ED4B7C0CDEC55C_PackageProduct.framework", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.framework", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=da546fca3b585ddf35a5a7d6d76bf04c-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=da546fca3b585ddf35a5a7d6d76bf04c-json new file mode 100644 index 0000000..8401536 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=da546fca3b585ddf35a5a7d6d76bf04c-json @@ -0,0 +1,57 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyBinaryDependency::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyBinaryDependency::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "dependencies": [ + { + "guid": "PACKAGE-TARGET:_Stub", + "platformFilters": [] + } + ], + "dynamicTargetVariantGuid": "PACKAGE-PRODUCT:MyBinaryDependency--5B0EB316CCB8BC4-dynamic", + "frameworksBuildPhase": { + "buildFiles": [ + { + "codeSignOnCopy": "true", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyBinaryDependency::MAINGROUP::REF_1::REF_0", + "guid": "PACKAGE-PRODUCT:MyBinaryDependency::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "true" + }, + { + "guid": "PACKAGE-PRODUCT:MyBinaryDependency::BUILDPHASE_0::1", + "platformFilters": [], + "targetReference": "PACKAGE-TARGET:_Stub" + } + ], + "guid": "PACKAGE-PRODUCT:MyBinaryDependency::BUILDPHASE_0", + "type": "com.apple.buildphase.frameworks" + }, + "guid": "PACKAGE-PRODUCT:MyBinaryDependency", + "name": "MyBinaryDependency", + "type": "packageProduct" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=e0ad90d36af3737ec5215a32f000294d-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=e0ad90d36af3737ec5215a32f000294d-json new file mode 100644 index 0000000..4b1f821 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=e0ad90d36af3737ec5215a32f000294d-json @@ -0,0 +1,125 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyCommonLibrary", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "MODULEMAP_FILE_CONTENTS": "module MyCommonLibrary {\nheader \"MyCommonLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyCommonLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyCommonLibrary", + "PRODUCT_MODULE_NAME": "MyCommonLibrary", + "PRODUCT_NAME": "MyCommonLibrary", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyCommonLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mycommonlibrary", + "SWIFT_VERSION": "5", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyCommonLibrary" + }, + "guid": "PACKAGE-TARGET:MyCommonLibrary--138526C95691DCED-dynamic::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "LD_RUNPATH_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyCommonLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyCommonLibrary", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "MODULEMAP_FILE_CONTENTS": "module MyCommonLibrary {\nheader \"MyCommonLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyCommonLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyCommonLibrary", + "PRODUCT_MODULE_NAME": "MyCommonLibrary", + "PRODUCT_NAME": "MyCommonLibrary", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyCommonLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mycommonlibrary", + "SWIFT_VERSION": "5", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyCommonLibrary" + }, + "guid": "PACKAGE-TARGET:MyCommonLibrary--138526C95691DCED-dynamic::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyCommonLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "codeSignOnCopy": "false", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyCommonLibrary::MAINGROUP::REF_3::REF_0", + "guid": "PACKAGE-TARGET:MyCommonLibrary--138526C95691DCED-dynamic::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "false" + } + ], + "guid": "PACKAGE-TARGET:MyCommonLibrary--138526C95691DCED-dynamic::BUILDPHASE_0", + "type": "com.apple.buildphase.sources" + } + ], + "buildRules": [], + "dependencies": [], + "guid": "PACKAGE-TARGET:MyCommonLibrary--138526C95691DCED-dynamic", + "name": "MyCommonLibrary", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-TARGET:MyCommonLibrary--138526C95691DCED-dynamic", + "name": "MyCommonLibrary.framework", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.framework", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=e6cf06600384b639e73079abd6a4553c-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=e6cf06600384b639e73079abd6a4553c-json new file mode 100644 index 0000000..b254780 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=e6cf06600384b639e73079abd6a4553c-json @@ -0,0 +1,150 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyLibrary", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "MODULEMAP_FILE_CONTENTS": "module MyLibrary {\nheader \"MyLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyLibrary", + "PRODUCT_MODULE_NAME": "MyLibrary", + "PRODUCT_NAME": "MyLibrary", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mylibrary", + "SWIFT_VERSION": "5", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyLibrary" + }, + "guid": "PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "LD_RUNPATH_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyLibrary", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "MODULEMAP_FILE_CONTENTS": "module MyLibrary {\nheader \"MyLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyLibrary", + "PRODUCT_MODULE_NAME": "MyLibrary", + "PRODUCT_NAME": "MyLibrary", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mylibrary", + "SWIFT_VERSION": "5", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyLibrary" + }, + "guid": "PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "codeSignOnCopy": "false", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyLibrary::MAINGROUP::REF_3::REF_0", + "guid": "PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "false" + } + ], + "guid": "PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_0", + "type": "com.apple.buildphase.sources" + }, + { + "buildFiles": [ + { + "guid": "PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_1::0", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyTransitiveLibrary" + }, + { + "guid": "PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_1::1", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyCommonLibrary" + } + ], + "guid": "PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic::BUILDPHASE_1", + "type": "com.apple.buildphase.frameworks" + } + ], + "buildRules": [], + "dependencies": [ + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "platformFilters": [] + } + ], + "guid": "PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic", + "name": "MyLibrary", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-TARGET:MyLibrary--71ED4B7C0CDEC55C-dynamic", + "name": "MyLibrary.framework", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.framework", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=ec86d6a4683c2028c68c9a06f9947bf3-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=ec86d6a4683c2028c68c9a06f9947bf3-json new file mode 100644 index 0000000..9eaaa2e --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=ec86d6a4683c2028c68c9a06f9947bf3-json @@ -0,0 +1,157 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyTransitiveLibrary", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "MODULEMAP_FILE_CONTENTS": "module MyTransitiveLibrary {\nheader \"MyTransitiveLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyTransitiveLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyTransitiveLibrary", + "PRODUCT_MODULE_NAME": "MyTransitiveLibrary", + "PRODUCT_NAME": "MyTransitiveLibrary", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyTransitiveLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mytransitivelibrary", + "SWIFT_VERSION": "5", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyTransitiveLibrary" + }, + "guid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "LD_RUNPATH_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyTransitiveLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_ENABLE_MODULES": "YES", + "CURRENT_PROJECT_VERSION": "1", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyTransitiveLibrary", + "GENERATE_INFOPLIST_FILE": "YES", + "MARKETING_VERSION": "1.0", + "MODULEMAP_FILE_CONTENTS": "module MyTransitiveLibrary {\nheader \"MyTransitiveLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyTransitiveLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyTransitiveLibrary", + "PRODUCT_MODULE_NAME": "MyTransitiveLibrary", + "PRODUCT_NAME": "MyTransitiveLibrary", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyTransitiveLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mytransitivelibrary", + "SWIFT_VERSION": "5", + "TARGET_BUILD_DIR": "$(TARGET_BUILD_DIR)/PackageFrameworks", + "TARGET_NAME": "MyTransitiveLibrary" + }, + "guid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyTransitiveLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "codeSignOnCopy": "false", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_3::REF_0", + "guid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "false" + } + ], + "guid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_0", + "type": "com.apple.buildphase.sources" + }, + { + "buildFiles": [ + { + "guid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_1::0", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyCommonLibrary" + }, + { + "guid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_1::1", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyBinaryDependency" + }, + { + "codeSignOnCopy": "true", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_1::REF_3", + "guid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_1::2", + "platformFilters": [], + "removeHeadersOnCopy": "true" + } + ], + "guid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic::BUILDPHASE_1", + "type": "com.apple.buildphase.frameworks" + } + ], + "buildRules": [], + "dependencies": [ + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyBinaryDependency", + "platformFilters": [] + } + ], + "guid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic", + "name": "MyTransitiveLibrary", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic", + "name": "MyTransitiveLibrary.framework", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.framework", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=f6b1fc5ff8b0c87e4d17a05b612118a8-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=f6b1fc5ff8b0c87e4d17a05b612118a8-json new file mode 100644 index 0000000..c3a4089 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=f6b1fc5ff8b0c87e4d17a05b612118a8-json @@ -0,0 +1,150 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "CLANG_COVERAGE_MAPPING_LINKER_ARGS": "NO", + "CLANG_ENABLE_MODULES": "YES", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyTransitiveLibrary.o", + "GENERATE_MASTER_OBJECT_FILE": "NO", + "MACH_O_TYPE": "mh_object", + "MODULEMAP_FILE_CONTENTS": "module MyTransitiveLibrary {\nheader \"MyTransitiveLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyTransitiveLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyTransitiveLibrary", + "PRODUCT_MODULE_NAME": "MyTransitiveLibrary", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "STRIP_INSTALLED_PRODUCT": "NO", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyTransitiveLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mytransitivelibrary", + "SWIFT_VERSION": "5", + "TAPI_DYLIB_INSTALL_NAME": "MyTransitiveLibrary", + "TARGET_NAME": "MyTransitiveLibrary" + }, + "guid": "PACKAGE-TARGET:MyTransitiveLibrary::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "LD_RUNPATH_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyTransitiveLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Debug" + }, + { + "buildSettings": { + "CLANG_COVERAGE_MAPPING_LINKER_ARGS": "NO", + "CLANG_ENABLE_MODULES": "YES", + "DEFINES_MODULE": "YES", + "EXECUTABLE_NAME": "MyTransitiveLibrary.o", + "GENERATE_MASTER_OBJECT_FILE": "NO", + "MACH_O_TYPE": "mh_object", + "MODULEMAP_FILE_CONTENTS": "module MyTransitiveLibrary {\nheader \"MyTransitiveLibrary-Swift.h\"\nexport *\n}", + "MODULEMAP_PATH": "$(GENERATED_MODULEMAP_DIR)/MyTransitiveLibrary.modulemap", + "PACKAGE_RESOURCE_TARGET_KIND": "regular", + "PRODUCT_BUNDLE_IDENTIFIER": "MyTransitiveLibrary", + "PRODUCT_MODULE_NAME": "MyTransitiveLibrary", + "PRODUCT_NAME": "$(TARGET_NAME)", + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "STRIP_INSTALLED_PRODUCT": "NO", + "SUPPORTS_TEXT_BASED_API": "NO", + "SWIFT_ENABLE_BARE_SLASH_REGEX": "NO", + "SWIFT_OBJC_INTERFACE_HEADER_DIR": "$(GENERATED_MODULEMAP_DIR)", + "SWIFT_OBJC_INTERFACE_HEADER_NAME": "MyTransitiveLibrary-Swift.h", + "SWIFT_PACKAGE_NAME": "mytransitivelibrary", + "SWIFT_VERSION": "5", + "TAPI_DYLIB_INSTALL_NAME": "MyTransitiveLibrary", + "TARGET_NAME": "MyTransitiveLibrary" + }, + "guid": "PACKAGE-TARGET:MyTransitiveLibrary::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": { + "FRAMEWORK_SEARCH_PATHS": [ + "$(BUILT_PRODUCTS_DIR)/PackageFrameworks", + "$(inherited)" + ], + "OTHER_CFLAGS": [ + "-fmodule-map-file=$(GENERATED_MODULEMAP_DIR)/MyTransitiveLibrary.modulemap", + "$(inherited)" + ], + "OTHER_LDFLAGS": [ + "-Wl,-no_warn_duplicate_libraries", + "$(inherited)" + ], + "OTHER_LDRFLAGS": [] + } + }, + "name": "Release" + } + ], + "buildPhases": [ + { + "buildFiles": [ + { + "codeSignOnCopy": "false", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_2::REF_0", + "guid": "PACKAGE-TARGET:MyTransitiveLibrary::BUILDPHASE_0::0", + "platformFilters": [], + "removeHeadersOnCopy": "false" + } + ], + "guid": "PACKAGE-TARGET:MyTransitiveLibrary::BUILDPHASE_0", + "type": "com.apple.buildphase.sources" + }, + { + "buildFiles": [ + { + "codeSignOnCopy": "false", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_1::REF_2", + "guid": "PACKAGE-TARGET:MyTransitiveLibrary::BUILDPHASE_1::0", + "platformFilters": [], + "removeHeadersOnCopy": "false" + } + ], + "guid": "PACKAGE-TARGET:MyTransitiveLibrary::BUILDPHASE_1", + "type": "com.apple.buildphase.resources" + } + ], + "buildRules": [], + "dependencies": [ + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyBinaryDependency", + "platformFilters": [] + } + ], + "dynamicTargetVariantGuid": "PACKAGE-TARGET:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic", + "guid": "PACKAGE-TARGET:MyTransitiveLibrary", + "name": "MyTransitiveLibrary", + "productReference": { + "guid": "PRODUCTREF-PACKAGE-TARGET:MyTransitiveLibrary", + "name": "MyTransitiveLibrary.o", + "type": "file" + }, + "productTypeIdentifier": "com.apple.product-type.objfile", + "type": "standard" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=fb7de2da6bb6f870c73ba0c83581f638-json b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=fb7de2da6bb6f870c73ba0c83581f638-json new file mode 100644 index 0000000..0f6cb43 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/target/TARGET@v12_hash=fb7de2da6bb6f870c73ba0c83581f638-json @@ -0,0 +1,75 @@ +{ + "approvedByUser": "true", + "buildConfigurations": [ + { + "buildSettings": { + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary::BUILDCONFIG_0", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Debug" + }, + { + "buildSettings": { + "SDKROOT": "auto", + "SDK_VARIANT": "auto", + "USES_SWIFTPM_UNSAFE_FLAGS": "NO" + }, + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary::BUILDCONFIG_1", + "impartedBuildProperties": { + "buildSettings": {} + }, + "name": "Release" + } + ], + "dependencies": [ + { + "guid": "PACKAGE-TARGET:MyTransitiveLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyCommonLibrary", + "platformFilters": [] + }, + { + "guid": "PACKAGE-PRODUCT:MyBinaryDependency", + "platformFilters": [] + } + ], + "dynamicTargetVariantGuid": "PACKAGE-PRODUCT:MyTransitiveLibrary-29D6C569F63C2FD7-dynamic", + "frameworksBuildPhase": { + "buildFiles": [ + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary::BUILDPHASE_0::0", + "platformFilters": [], + "targetReference": "PACKAGE-TARGET:MyTransitiveLibrary" + }, + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary::BUILDPHASE_0::1", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyCommonLibrary" + }, + { + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary::BUILDPHASE_0::2", + "platformFilters": [], + "targetReference": "PACKAGE-PRODUCT:MyBinaryDependency" + }, + { + "codeSignOnCopy": "true", + "fileReference": "PACKAGE:/Users/thedderwick/Desktop/SPMTest/MyTransitiveLibrary::MAINGROUP::REF_1::REF_0", + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary::BUILDPHASE_0::3", + "platformFilters": [], + "removeHeadersOnCopy": "true" + } + ], + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary::BUILDPHASE_0", + "type": "com.apple.buildphase.frameworks" + }, + "guid": "PACKAGE-PRODUCT:MyTransitiveLibrary", + "name": "MyTransitiveLibrary", + "type": "packageProduct" +} diff --git a/TestAssets/PIFCaches/SPMTest/PIFCache/workspace/WORKSPACE@v11_hash=e6e1ff1ce1d8441dff7731e4f843ec43_subobjects=f62a50b6ced3d59774fc6ba5a392ffaa-json b/TestAssets/PIFCaches/SPMTest/PIFCache/workspace/WORKSPACE@v11_hash=e6e1ff1ce1d8441dff7731e4f843ec43_subobjects=f62a50b6ced3d59774fc6ba5a392ffaa-json new file mode 100644 index 0000000..1a2d122 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/PIFCache/workspace/WORKSPACE@v11_hash=e6e1ff1ce1d8441dff7731e4f843ec43_subobjects=f62a50b6ced3d59774fc6ba5a392ffaa-json @@ -0,0 +1,12 @@ +{ + "guid": "1548de4dda862e04fcc1cb773900f3bf", + "name": "SPMTest", + "path": "/Users/thedderwick/Desktop/SPMTest/SPMTest.xcodeproj/project.xcworkspace", + "projects": [ + "PROJECT@v11_mod=1716537774.576404_hash=0f958f39499d9f0b6b454948d2be549bplugins=1OJSG6M1FOV3XYQCBH7Z29RZ0FPR9XDE1", + "PACKAGE@v12_hash=28350dce3dbf6c3324256d2ef84c721e", + "PACKAGE@v12_hash=d061ee81d8927d5b63443e777e83938a", + "PACKAGE@v12_hash=217e2718d5748fe803db10bf7703f87e", + "PACKAGE@v12_hash=60e18114455190230d62ad086fd6a1d5" + ] +} diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/project.pbxproj b/TestAssets/PIFCaches/SPMTest/SPMTest.xcodeproj/project.pbxproj similarity index 52% rename from PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/project.pbxproj rename to TestAssets/PIFCaches/SPMTest/SPMTest.xcodeproj/project.pbxproj index ccd69a9..3044785 100644 --- a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/project.pbxproj +++ b/TestAssets/PIFCaches/SPMTest/SPMTest.xcodeproj/project.pbxproj @@ -3,90 +3,70 @@ archiveVersion = 1; classes = { }; - objectVersion = 56; + objectVersion = 60; objects = { /* Begin PBXBuildFile section */ - 35460152C27D425AD341441A /* Pods_DoubleTargetTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 85C8A3B68F9E974DC6038BFF /* Pods_DoubleTargetTest.framework */; }; - CE25174229C9C2C100A2E14B /* DoubleTargetTestApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE25174129C9C2C100A2E14B /* DoubleTargetTestApp.swift */; }; - CE25174429C9C2C100A2E14B /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE25174329C9C2C100A2E14B /* ContentView.swift */; }; - CE25174629C9C2C200A2E14B /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE25174529C9C2C200A2E14B /* Assets.xcassets */; }; - CE25174929C9C2C200A2E14B /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CE25174829C9C2C200A2E14B /* Preview Assets.xcassets */; }; + CEE341292C007A7E00BBA9C3 /* SPMTestApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE341282C007A7E00BBA9C3 /* SPMTestApp.swift */; }; + CEE3412B2C007A7E00BBA9C3 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CEE3412A2C007A7E00BBA9C3 /* ContentView.swift */; }; + CEE3412D2C007A7F00BBA9C3 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CEE3412C2C007A7F00BBA9C3 /* Assets.xcassets */; }; + CEE341302C007A7F00BBA9C3 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = CEE3412F2C007A7F00BBA9C3 /* Preview Assets.xcassets */; }; + CEE341382C007CA900BBA9C3 /* MyLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = CEE341372C007CA900BBA9C3 /* MyLibrary */; }; + CEE3413B2C00812D00BBA9C3 /* MyCommonLibrary in Frameworks */ = {isa = PBXBuildFile; productRef = CEE3413A2C00812D00BBA9C3 /* MyCommonLibrary */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - 815B8E932FA5793B81A510EC /* Pods-DoubleTargetTest.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DoubleTargetTest.release.xcconfig"; path = "Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.release.xcconfig"; sourceTree = ""; }; - 85C8A3B68F9E974DC6038BFF /* Pods_DoubleTargetTest.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_DoubleTargetTest.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - BC9AAD5FA65122E6FCDEC90E /* Pods-DoubleTargetTest.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-DoubleTargetTest.debug.xcconfig"; path = "Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest.debug.xcconfig"; sourceTree = ""; }; - CE25173E29C9C2C100A2E14B /* DoubleTargetTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DoubleTargetTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; - CE25174129C9C2C100A2E14B /* DoubleTargetTestApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoubleTargetTestApp.swift; sourceTree = ""; }; - CE25174329C9C2C100A2E14B /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; - CE25174529C9C2C200A2E14B /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - CE25174829C9C2C200A2E14B /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + CEE341252C007A7E00BBA9C3 /* SPMTest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SPMTest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + CEE341282C007A7E00BBA9C3 /* SPMTestApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPMTestApp.swift; sourceTree = ""; }; + CEE3412A2C007A7E00BBA9C3 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + CEE3412C2C007A7F00BBA9C3 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + CEE3412F2C007A7F00BBA9C3 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - CE25173B29C9C2C100A2E14B /* Frameworks */ = { + CEE341222C007A7E00BBA9C3 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 35460152C27D425AD341441A /* Pods_DoubleTargetTest.framework in Frameworks */, + CEE341382C007CA900BBA9C3 /* MyLibrary in Frameworks */, + CEE3413B2C00812D00BBA9C3 /* MyCommonLibrary in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 01D7ED154039FF16EE28AD13 /* Pods */ = { + CEE3411C2C007A7E00BBA9C3 = { isa = PBXGroup; children = ( - BC9AAD5FA65122E6FCDEC90E /* Pods-DoubleTargetTest.debug.xcconfig */, - 815B8E932FA5793B81A510EC /* Pods-DoubleTargetTest.release.xcconfig */, + CEE341272C007A7E00BBA9C3 /* SPMTest */, + CEE341262C007A7E00BBA9C3 /* Products */, ); - path = Pods; sourceTree = ""; }; - 04DE6891E5415C30C89A0396 /* Frameworks */ = { + CEE341262C007A7E00BBA9C3 /* Products */ = { isa = PBXGroup; children = ( - 85C8A3B68F9E974DC6038BFF /* Pods_DoubleTargetTest.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - CE25173529C9C2C100A2E14B = { - isa = PBXGroup; - children = ( - CE25174029C9C2C100A2E14B /* DoubleTargetTest */, - CE25173F29C9C2C100A2E14B /* Products */, - 01D7ED154039FF16EE28AD13 /* Pods */, - 04DE6891E5415C30C89A0396 /* Frameworks */, - ); - sourceTree = ""; - }; - CE25173F29C9C2C100A2E14B /* Products */ = { - isa = PBXGroup; - children = ( - CE25173E29C9C2C100A2E14B /* DoubleTargetTest.app */, + CEE341252C007A7E00BBA9C3 /* SPMTest.app */, ); name = Products; sourceTree = ""; }; - CE25174029C9C2C100A2E14B /* DoubleTargetTest */ = { + CEE341272C007A7E00BBA9C3 /* SPMTest */ = { isa = PBXGroup; children = ( - CE25174129C9C2C100A2E14B /* DoubleTargetTestApp.swift */, - CE25174329C9C2C100A2E14B /* ContentView.swift */, - CE25174529C9C2C200A2E14B /* Assets.xcassets */, - CE25174729C9C2C200A2E14B /* Preview Content */, + CEE341282C007A7E00BBA9C3 /* SPMTestApp.swift */, + CEE3412A2C007A7E00BBA9C3 /* ContentView.swift */, + CEE3412C2C007A7F00BBA9C3 /* Assets.xcassets */, + CEE3412E2C007A7F00BBA9C3 /* Preview Content */, ); - path = DoubleTargetTest; + path = SPMTest; sourceTree = ""; }; - CE25174729C9C2C200A2E14B /* Preview Content */ = { + CEE3412E2C007A7F00BBA9C3 /* Preview Content */ = { isa = PBXGroup; children = ( - CE25174829C9C2C200A2E14B /* Preview Assets.xcassets */, + CEE3412F2C007A7F00BBA9C3 /* Preview Assets.xcassets */, ); path = "Preview Content"; sourceTree = ""; @@ -94,41 +74,43 @@ /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - CE25173D29C9C2C100A2E14B /* DoubleTargetTest */ = { + CEE341242C007A7E00BBA9C3 /* SPMTest */ = { isa = PBXNativeTarget; - buildConfigurationList = CE25174C29C9C2C200A2E14B /* Build configuration list for PBXNativeTarget "DoubleTargetTest" */; + buildConfigurationList = CEE341332C007A7F00BBA9C3 /* Build configuration list for PBXNativeTarget "SPMTest" */; buildPhases = ( - 60C22A37CD715212D57E629D /* [CP] Check Pods Manifest.lock */, - CE25173A29C9C2C100A2E14B /* Sources */, - CE25173B29C9C2C100A2E14B /* Frameworks */, - CE25173C29C9C2C100A2E14B /* Resources */, - 16B418F3FB824614A4DADAF1 /* [CP] Embed Pods Frameworks */, + CEE341212C007A7E00BBA9C3 /* Sources */, + CEE341222C007A7E00BBA9C3 /* Frameworks */, + CEE341232C007A7E00BBA9C3 /* Resources */, ); buildRules = ( ); dependencies = ( ); - name = DoubleTargetTest; - productName = DoubleTargetTest; - productReference = CE25173E29C9C2C100A2E14B /* DoubleTargetTest.app */; + name = SPMTest; + packageProductDependencies = ( + CEE341372C007CA900BBA9C3 /* MyLibrary */, + CEE3413A2C00812D00BBA9C3 /* MyCommonLibrary */, + ); + productName = SPMTest; + productReference = CEE341252C007A7E00BBA9C3 /* SPMTest.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - CE25173629C9C2C100A2E14B /* Project object */ = { + CEE3411D2C007A7E00BBA9C3 /* Project object */ = { isa = PBXProject; attributes = { BuildIndependentTargetsInParallel = 1; - LastSwiftUpdateCheck = 1420; - LastUpgradeCheck = 1420; + LastSwiftUpdateCheck = 1530; + LastUpgradeCheck = 1530; TargetAttributes = { - CE25173D29C9C2C100A2E14B = { - CreatedOnToolsVersion = 14.2; + CEE341242C007A7E00BBA9C3 = { + CreatedOnToolsVersion = 15.3; }; }; }; - buildConfigurationList = CE25173929C9C2C100A2E14B /* Build configuration list for PBXProject "DoubleTargetTest" */; + buildConfigurationList = CEE341202C007A7E00BBA9C3 /* Build configuration list for PBXProject "SPMTest" */; compatibilityVersion = "Xcode 14.0"; developmentRegion = en; hasScannedForEncodings = 0; @@ -136,87 +118,50 @@ en, Base, ); - mainGroup = CE25173529C9C2C100A2E14B; - productRefGroup = CE25173F29C9C2C100A2E14B /* Products */; + mainGroup = CEE3411C2C007A7E00BBA9C3; + packageReferences = ( + CEE341362C007CA900BBA9C3 /* XCLocalSwiftPackageReference "MyLibrary" */, + CEE341392C00812D00BBA9C3 /* XCLocalSwiftPackageReference "MyCommonLibrary" */, + ); + productRefGroup = CEE341262C007A7E00BBA9C3 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - CE25173D29C9C2C100A2E14B /* DoubleTargetTest */, + CEE341242C007A7E00BBA9C3 /* SPMTest */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - CE25173C29C9C2C100A2E14B /* Resources */ = { + CEE341232C007A7E00BBA9C3 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - CE25174929C9C2C200A2E14B /* Preview Assets.xcassets in Resources */, - CE25174629C9C2C200A2E14B /* Assets.xcassets in Resources */, + CEE341302C007A7F00BBA9C3 /* Preview Assets.xcassets in Resources */, + CEE3412D2C007A7F00BBA9C3 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ -/* Begin PBXShellScriptBuildPhase section */ - 16B418F3FB824614A4DADAF1 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-DoubleTargetTest/Pods-DoubleTargetTest-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; - 60C22A37CD715212D57E629D /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-DoubleTargetTest-checkManifestLockResult.txt", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - /* Begin PBXSourcesBuildPhase section */ - CE25173A29C9C2C100A2E14B /* Sources */ = { + CEE341212C007A7E00BBA9C3 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - CE25174429C9C2C100A2E14B /* ContentView.swift in Sources */, - CE25174229C9C2C100A2E14B /* DoubleTargetTestApp.swift in Sources */, + CEE3412B2C007A7E00BBA9C3 /* ContentView.swift in Sources */, + CEE341292C007A7E00BBA9C3 /* SPMTestApp.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ - CE25174A29C9C2C200A2E14B /* Debug */ = { + CEE341312C007A7F00BBA9C3 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -249,7 +194,8 @@ DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -263,20 +209,22 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; - CE25174B29C9C2C200A2E14B /* Release */ = { + CEE341322C007A7F00BBA9C3 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -309,7 +257,8 @@ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu11; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -317,27 +266,26 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 16.2; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; - SWIFT_OPTIMIZATION_LEVEL = "-O"; VALIDATE_PRODUCT = YES; }; name = Release; }; - CE25174D29C9C2C200A2E14B /* Debug */ = { + CEE341342C007A7F00BBA9C3 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BC9AAD5FA65122E6FCDEC90E /* Pods-DoubleTargetTest.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"DoubleTargetTest/Preview Content\""; - DEVELOPMENT_TEAM = M2QJQZX6EU; + DEVELOPMENT_ASSET_PATHS = "\"SPMTest/Preview Content\""; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -350,7 +298,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.veracode.DoubleTargetTest; + PRODUCT_BUNDLE_IDENTIFIER = com.veracode.SPMTest; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; @@ -359,17 +307,16 @@ }; name = Debug; }; - CE25174E29C9C2C200A2E14B /* Release */ = { + CEE341352C007A7F00BBA9C3 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 815B8E932FA5793B81A510EC /* Pods-DoubleTargetTest.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_IDENTITY = "Apple Development"; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_ASSET_PATHS = "\"DoubleTargetTest/Preview Content\""; - DEVELOPMENT_TEAM = M2QJQZX6EU; + DEVELOPMENT_ASSET_PATHS = "\"SPMTest/Preview Content\""; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -382,7 +329,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.veracode.DoubleTargetTest; + PRODUCT_BUNDLE_IDENTIFIER = com.veracode.SPMTest; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; @@ -394,25 +341,47 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - CE25173929C9C2C100A2E14B /* Build configuration list for PBXProject "DoubleTargetTest" */ = { + CEE341202C007A7E00BBA9C3 /* Build configuration list for PBXProject "SPMTest" */ = { isa = XCConfigurationList; buildConfigurations = ( - CE25174A29C9C2C200A2E14B /* Debug */, - CE25174B29C9C2C200A2E14B /* Release */, + CEE341312C007A7F00BBA9C3 /* Debug */, + CEE341322C007A7F00BBA9C3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - CE25174C29C9C2C200A2E14B /* Build configuration list for PBXNativeTarget "DoubleTargetTest" */ = { + CEE341332C007A7F00BBA9C3 /* Build configuration list for PBXNativeTarget "SPMTest" */ = { isa = XCConfigurationList; buildConfigurations = ( - CE25174D29C9C2C200A2E14B /* Debug */, - CE25174E29C9C2C200A2E14B /* Release */, + CEE341342C007A7F00BBA9C3 /* Debug */, + CEE341352C007A7F00BBA9C3 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + CEE341362C007CA900BBA9C3 /* XCLocalSwiftPackageReference "MyLibrary" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = MyLibrary; + }; + CEE341392C00812D00BBA9C3 /* XCLocalSwiftPackageReference "MyCommonLibrary" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = MyCommonLibrary; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + CEE341372C007CA900BBA9C3 /* MyLibrary */ = { + isa = XCSwiftPackageProductDependency; + productName = MyLibrary; + }; + CEE3413A2C00812D00BBA9C3 /* MyCommonLibrary */ = { + isa = XCSwiftPackageProductDependency; + productName = MyCommonLibrary; + }; +/* End XCSwiftPackageProductDependency section */ }; - rootObject = CE25173629C9C2C100A2E14B /* Project object */; + rootObject = CEE3411D2C007A7E00BBA9C3 /* Project object */; } diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/TestAssets/PIFCaches/SPMTest/SPMTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata similarity index 100% rename from PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata rename to TestAssets/PIFCaches/SPMTest/SPMTest.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/TestAssets/PIFCaches/SPMTest/SPMTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist similarity index 100% rename from PBXProjParser/Tests/PBXProjParserTests/TestAssets/Projects/DoubleTargetTest/DoubleTargetTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist rename to TestAssets/PIFCaches/SPMTest/SPMTest.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist diff --git a/TestAssets/PIFCaches/SPMTest/SPMTest/Assets.xcassets/AccentColor.colorset/Contents.json b/TestAssets/PIFCaches/SPMTest/SPMTest/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/SPMTest/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TestAssets/PIFCaches/SPMTest/SPMTest/Assets.xcassets/AppIcon.appiconset/Contents.json b/TestAssets/PIFCaches/SPMTest/SPMTest/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/SPMTest/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TestAssets/PIFCaches/SPMTest/SPMTest/Assets.xcassets/Contents.json b/TestAssets/PIFCaches/SPMTest/SPMTest/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/SPMTest/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TestAssets/PIFCaches/SPMTest/SPMTest/ContentView.swift b/TestAssets/PIFCaches/SPMTest/SPMTest/ContentView.swift new file mode 100644 index 0000000..2e83bfa --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/SPMTest/ContentView.swift @@ -0,0 +1,26 @@ +// +// ContentView.swift +// SPMTest +// +// Created by Thomas Hedderwick on 24/05/2024. +// + +import SwiftUI +import MyLibrary + +struct ContentView: View { + var body: some View { + VStack { + Image(systemName: "globe") + .imageScale(.large) + .foregroundStyle(.tint) + Text("VERSION: \(MyLibrary.version)") + Text("view: \(MyLibrary.view)") + } + .padding() + } +} + +#Preview { + ContentView() +} diff --git a/TestAssets/PIFCaches/SPMTest/SPMTest/Preview Content/Preview Assets.xcassets/Contents.json b/TestAssets/PIFCaches/SPMTest/SPMTest/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/SPMTest/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/TestAssets/PIFCaches/SPMTest/SPMTest/SPMTestApp.swift b/TestAssets/PIFCaches/SPMTest/SPMTest/SPMTestApp.swift new file mode 100644 index 0000000..716f46c --- /dev/null +++ b/TestAssets/PIFCaches/SPMTest/SPMTest/SPMTestApp.swift @@ -0,0 +1,17 @@ +// +// SPMTestApp.swift +// SPMTest +// +// Created by Thomas Hedderwick on 24/05/2024. +// + +import SwiftUI + +@main +struct SPMTestApp: App { + var body: some Scene { + WindowGroup { + ContentView() + } + } +} diff --git a/TestAssets/WorkspaceContainerTest/App/App.xcodeproj/project.pbxproj b/TestAssets/WorkspaceContainerTest/App/App.xcodeproj/project.pbxproj index 8e3249d..879dacb 100644 --- a/TestAssets/WorkspaceContainerTest/App/App.xcodeproj/project.pbxproj +++ b/TestAssets/WorkspaceContainerTest/App/App.xcodeproj/project.pbxproj @@ -215,6 +215,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; @@ -275,6 +276,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; @@ -302,9 +304,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"App/Preview Content\""; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -319,6 +323,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.test.App; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; @@ -330,9 +335,11 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = "\"App/Preview Content\""; + DEVELOPMENT_TEAM = ""; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; @@ -347,6 +354,7 @@ MARKETING_VERSION = 1.0; PRODUCT_BUNDLE_IDENTIFIER = com.test.App; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; diff --git a/TestAssets/WorkspaceContainerTest/Modules/FrameworkA/FrameworkA.xcodeproj/project.pbxproj b/TestAssets/WorkspaceContainerTest/Modules/FrameworkA/FrameworkA.xcodeproj/project.pbxproj index 3bfedf6..b3429ba 100644 --- a/TestAssets/WorkspaceContainerTest/Modules/FrameworkA/FrameworkA.xcodeproj/project.pbxproj +++ b/TestAssets/WorkspaceContainerTest/Modules/FrameworkA/FrameworkA.xcodeproj/project.pbxproj @@ -172,6 +172,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; @@ -235,6 +236,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -264,9 +266,11 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -284,6 +288,7 @@ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++20"; PRODUCT_BUNDLE_IDENTIFIER = com.test.FrameworkA; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -296,9 +301,11 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -316,6 +323,7 @@ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++20"; PRODUCT_BUNDLE_IDENTIFIER = com.test.FrameworkA; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; diff --git a/TestAssets/WorkspaceContainerTest/Modules/FrameworkB/FrameworkB.xcodeproj/project.pbxproj b/TestAssets/WorkspaceContainerTest/Modules/FrameworkB/FrameworkB.xcodeproj/project.pbxproj index 2c9c860..b51d48a 100644 --- a/TestAssets/WorkspaceContainerTest/Modules/FrameworkB/FrameworkB.xcodeproj/project.pbxproj +++ b/TestAssets/WorkspaceContainerTest/Modules/FrameworkB/FrameworkB.xcodeproj/project.pbxproj @@ -208,6 +208,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; @@ -271,6 +272,7 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -300,9 +302,11 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -320,6 +324,7 @@ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++20"; PRODUCT_BUNDLE_IDENTIFIER = com.test.FrameworkB; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -332,9 +337,11 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; - CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; + CODE_SIGN_STYLE = Manual; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -352,6 +359,7 @@ MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++20"; PRODUCT_BUNDLE_IDENTIFIER = com.test.FrameworkB; PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + PROVISIONING_PROFILE_SPECIFIER = ""; SKIP_INSTALL = YES; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_VERSION = 5.0; diff --git a/Tests/GenIRTests/CMakeDiscoveryTests.swift b/Tests/GenIRTests/CMakeDiscoveryTests.swift new file mode 100644 index 0000000..9120d61 --- /dev/null +++ b/Tests/GenIRTests/CMakeDiscoveryTests.swift @@ -0,0 +1,54 @@ +import XCTest +@testable import gen_ir + +final class CMakeDiscoveryTests: XCTestCase { + let testPath: URL = { + TestContext.testAssetPath + .appendingPathComponent("CMakeDiscoveryTest") + .appendingPathComponent(".build") + .appendingPathComponent("CMakeDiscoveryTest.xcodeproj") + }() + + private lazy var buildPath: URL = { + TestContext.testAssetPath + .appendingPathComponent("CMakeDiscoveryTest") + .appendingPathComponent(".build") + }() + + let scheme = "CMakeDiscovery" + + private func generate() throws { + if !FileManager.default.fileExists(atPath: buildPath.path) { + try FileManager.default.createDirectory(at: buildPath, withIntermediateDirectories: true) + } + + _ = try Process.runShell( + "cmake", + arguments: [ + "-GXcode", + TestContext.testAssetPath.appendingPathComponent("CMakeDiscoveryTest").path + ], + runInDirectory: buildPath + ) + + // If this isn't set - xcodebuild will refuse to clean the project (thanks Apple!) + _ = try Process.runShell( + "xattr", + arguments: [ + "-w", + "com.apple.xcode.CreatedByBuildSystem", + "true", + buildPath.appendingPathComponent("build").path + ] + ) + } + + func testCMakeDiscovery() throws { + try generate() + let context = TestContext() + try context.build(test: testPath, scheme: scheme) + + let cache = context.pifCache + XCTAssertEqual(cache.targets.filter { $0.name == "CMakeDiscovery" }.count, 1) + } +} diff --git a/Tests/GenIRTests/DependencyGraphTests.swift b/Tests/GenIRTests/DependencyGraphTests.swift index 300b933..d0d4ef2 100644 --- a/Tests/GenIRTests/DependencyGraphTests.swift +++ b/Tests/GenIRTests/DependencyGraphTests.swift @@ -1,47 +1,41 @@ import XCTest @testable import gen_ir -import PBXProjParser +@testable import DependencyGraph final class DependencyGraphTests: XCTestCase { - static private var testPath: URL = { + let testPath: URL = { TestContext.testAssetPath .appendingPathComponent("WorkspaceTest") .appendingPathComponent("Workspace.xcworkspace") }() - - static private var scheme = "App" + let scheme = "App" func testChains() throws { // Test Setup - let context = try TestContext() - let process = try context.build(test: Self.testPath, scheme: Self.scheme) + let context = TestContext() + let process = try context.build(test: testPath, scheme: scheme) XCTAssertEqual(process.code, 0, "Build returned non-zero exit code") - let project = try ProjectParser(path: Self.testPath, logLevel: .debug) - var targets = Targets(for: project) - - let buildLog = try String(contentsOf: context.buildLog).components(separatedBy: .newlines) - let logParser = XcodeLogParser(log: buildLog) + let targets = context.targets + let graph = context.graph - try logParser.parse(&targets) - - let graph = DependencyGraphBuilder.build(targets: targets) - let appTarget = try XCTUnwrap(targets.target(for: "App"), "Failed to get App target from targets") + let appTarget = try XCTUnwrap(targets.first(where: { $0.name == "App"}), "Failed to get App target from targets") let app = try XCTUnwrap(graph.findNode(for: appTarget), "Failed to find App node in graph") // App should have two nodes - Framework & Common XCTAssertTrue(app.edges.count == 2, "App's edges is not equal to 2") - _ = try XCTUnwrap(app.edges.first(where: { $0.to.name == "Framework" }), "Failed to get Framework edge from App") - let commonEdge = try XCTUnwrap(app.edges.first(where: { $0.to.name == "Common" }), "Failed to get Common edge from App") + _ = try XCTUnwrap(app.edges.first(where: { $0.to.valueName == "Framework.framework" }), "Failed to get Framework edge from App") + let commonEdge = try XCTUnwrap(app.edges.first(where: { $0.to.valueName == "Common.framework" }), "Failed to get Common edge from App") - let frameworkTarget = try XCTUnwrap(targets.target(for: "Framework"), "Failed to get Framework from targets") + let frameworkTarget = try XCTUnwrap(targets.first(where: { $0.name == "Framework"}), "Failed to get Framework from targets") let framework = try XCTUnwrap(graph.findNode(for: frameworkTarget), "Failed to find Framework node in graph") // Framework should have two dependency edges - Common & SFSafeSymbols and one depender edge - App XCTAssertTrue(framework.edges.count == 3, "Framework's edges is not equal to 3") - let symbolsEdge = try XCTUnwrap(framework.edges.first(where: { $0.to.name == "SFSafeSymbols" }), "Failed to get SFSafeSymbols edge from Framework") - let frameworkCommonEdge = try XCTUnwrap(framework.edges.first(where: { $0.to.name == "Common" }), "Failed to get SFSafeSymbols edge from Framework") - let frameworkAppEdge = try XCTUnwrap(framework.edges.first(where: { $0.to.name == "App" }), "Failed to get App edge from Framework") + let symbolsEdge = try XCTUnwrap(framework.edges.first(where: { $0.to.valueName == "SFSafeSymbols.o" }), "Failed to get SFSafeSymbols edge from Framework") + let frameworkCommonEdge = try XCTUnwrap(framework.edges.first(where: { $0.to.valueName == "Common.framework" }), "Failed to get SFSafeSymbols edge from Framework") + let frameworkAppEdge = try XCTUnwrap(framework.edges.first(where: { $0.to.valueName == "App.app" }), "Failed to get App edge from Framework") + XCTAssertNotEqual(commonEdge, frameworkCommonEdge, "App's Common edge is equal to Framework's Common edge - they should have different from values") XCTAssertEqual(symbolsEdge.relationship, .dependency) XCTAssertEqual(frameworkCommonEdge.relationship, .dependency) diff --git a/Tests/GenIRTests/MultipleAppTests.swift b/Tests/GenIRTests/MultipleAppTests.swift index 5d946c3..90b0042 100644 --- a/Tests/GenIRTests/MultipleAppTests.swift +++ b/Tests/GenIRTests/MultipleAppTests.swift @@ -1,30 +1,24 @@ import XCTest @testable import gen_ir -import PBXProjParser final class MultipleAppTests: XCTestCase { - static private var testPath: URL = { + let testPath: URL = { TestContext.testAssetPath .appendingPathComponent("MultipleApp") .appendingPathComponent("MultipleApp.xcodeproj") }() + let scheme = "MultipleApp" func testExpectedTargetLookup() throws { - let context = try TestContext() - let result = try context.build(test: Self.testPath, scheme: "MultipleApp") - XCTAssertEqual(result.code, 0, "Build returned non-zero exit code") + let context = TestContext() + try context.build(test: testPath, scheme: "MultipleApp") - let project: ProjectParser = try ProjectParser(path: Self.testPath, logLevel: .debug) - var targets = Targets(for: project) + let targets = context.targets - let logContents = try String(contentsOf: context.buildLog).components(separatedBy: .newlines) - let log = XcodeLogParser(log: logContents) - try log.parse(&targets) + let app = try XCTUnwrap(targets.first(where: { $0.name == "MultipleApp" })) + let copy = try XCTUnwrap(targets.first(where: { $0.name == "MultipleApp Copy" })) - let app = try XCTUnwrap(targets.target(for: "MultipleApp")) - let copy = try XCTUnwrap(targets.target(for: "MultipleApp Copy")) - - XCTAssertEqual(app.commands.count, 3) - XCTAssertEqual(copy.commands.count, 3) + XCTAssertEqual(context.logParser.targetCommands[app.name]?.count, 3) + XCTAssertEqual(context.logParser.targetCommands[copy.name]?.count, 3) } } diff --git a/Tests/GenIRTests/OutputPostprocessorFileMoverTests.swift b/Tests/GenIRTests/OutputPostprocessorFileMoverTests.swift index b4ca4e8..00497e3 100644 --- a/Tests/GenIRTests/OutputPostprocessorFileMoverTests.swift +++ b/Tests/GenIRTests/OutputPostprocessorFileMoverTests.swift @@ -1,22 +1,20 @@ import XCTest @testable import gen_ir -import PBXProjParser final class OutputPostprocessorFileMoverTests: XCTestCase { - static private var testPath: URL = { + let testPath: URL = { TestContext.testAssetPath .appendingPathComponent("OutputPostprocessorFileMoverTests") .appendingPathComponent("OutputPostprocessorFileMoverTests.xcodeproj") }() + let scheme = "OutputPostprocessorFileMoverTests" func testFileMoving() throws { - let context = try TestContext() - let result = try context.build(test: Self.testPath, scheme: "OutputPostprocessorFileMoverTests") - XCTAssertEqual(result.code, 0, "Build returned non-zero exit code") + let context = TestContext() + try context.build(test: testPath, scheme: scheme) var runner = IREmitterCommand() try runner.run( - project: Self.testPath, log: context.buildLog.filePath, archive: context.archive, level: .debug, @@ -25,13 +23,11 @@ final class OutputPostprocessorFileMoverTests: XCTestCase { ) // Check the output path for unique Image files - print("archivePAth: \(context.archive)") let appIRPath = context.archive .appendingPathComponent("IR") .appendingPathComponent("OutputPostprocessorFileMoverTests.app") let files = try FileManager.default.contentsOfDirectory(at: appIRPath, includingPropertiesForKeys: nil) let imageFilesCount = files.filter { $0.lastPathComponent.starts(with: "Image") }.count - print("imageFilesCount: \(imageFilesCount)") // Only expecting two - one of the dependencies is dynamic and won't be moved. XCTAssertEqual(imageFilesCount, 2, "2 Image*.bc files expected, \(imageFilesCount) were found.") diff --git a/Tests/GenIRTests/PIFCacheTests.swift b/Tests/GenIRTests/PIFCacheTests.swift new file mode 100644 index 0000000..47bdcea --- /dev/null +++ b/Tests/GenIRTests/PIFCacheTests.swift @@ -0,0 +1,35 @@ +import XCTest +@testable import gen_ir +import PIFSupport + +final class PIFCacheTests: XCTestCase { + let testPath: URL = { + TestContext.testAssetPath + .appendingPathComponent("PIFCaches") + .appendingPathComponent("SPMTest") + .appendingPathComponent("SPMTest.xcodeproj") + }() + let scheme = "SPMTest" + var cachePath: URL { + testPath + .deletingLastPathComponent() + .appendingPathComponent("PIFCache") + } + + func testSPMTestChain() throws { + let context = TestContext() + try context.build(test: testPath, scheme: scheme) + let graph = context.graph + + let appTarget = try XCTUnwrap(context.targets.first(where: { $0.productName == "SPMTest.app" })) + let node = try XCTUnwrap(graph.findNode(for: appTarget)) + + XCTAssertEqual(node.edges.count, 2) + let chain = graph.chain(for: appTarget) + let nameSet = Set(chain.map { $0.value.name }) + + let expectedNameSet = Set(["SPMTest", "MyLibrary", "MyCommonLibrary", "MyTransitiveLibrary"]) + let nameDifference = nameSet.symmetricDifference(expectedNameSet) + XCTAssertTrue(nameDifference.isEmpty, "Difference found in name set (\(nameSet)) and expected name set: \(expectedNameSet) - difference: \(nameDifference)") + } +} diff --git a/Tests/GenIRTests/TestContext.swift b/Tests/GenIRTests/TestContext.swift index 661ebfb..401fa92 100644 --- a/Tests/GenIRTests/TestContext.swift +++ b/Tests/GenIRTests/TestContext.swift @@ -1,21 +1,31 @@ import Foundation @testable import gen_ir +import DependencyGraph +import XCTest +/// TestContext is a grouping of convenance functions and a context to ease the burden of testing Gen IR class TestContext { enum Error: Swift.Error { case commandFailed(Process.ReturnValue) case invalidArgument(String) } - static let baseTestingPath: URL = { + /// The base folder path of the Gen IR project + static let baseProjectPath: URL = { // HACK: use the #file magic to get a path to the test case... Maybe there's a better way to do this? URL(fileURLWithPath: #file.replacingOccurrences(of: "Tests/GenIRTests/TestContext.swift", with: "")) }() + /// Path to the TestAssets folder static let testAssetPath: URL = { - baseTestingPath.appendingPathComponent("TestAssets") + baseProjectPath.appendingPathComponent("TestAssets") }() + /// Run xcodebuild's clean action + /// - Parameters: + /// - path: the path of the project to clean + /// - scheme: the name of the scheme to clean (required for workspaces) + /// - Returns: func clean(test path: URL, scheme: String) throws -> Process.ReturnValue { var arguments = ["clean"] @@ -36,7 +46,13 @@ class TestContext { ) } - func build( + /// Run xcodebuild's archive action + /// - Parameters: + /// - path: the path of the project to build + /// - scheme: the name of the scheme to build + /// - additionalArguments: any additional arguments to passthrough to xcodebuild + /// - Returns: the result of running the action. + @discardableResult func build( test path: URL, scheme: String, additionalArguments: [String] = [] @@ -74,18 +90,66 @@ class TestContext { throw Error.commandFailed(process) } else if let stdout = process.stdout { try stdout.write(to: buildLog, atomically: true, encoding: .utf8) + buildLogContents = stdout.components(separatedBy: .newlines) } + built = true + return process } + /// Path to the xcarchive (once built) let archive: URL + /// Path to the build log (once built) let buildLog: URL + /// Path to the temporary working directory for this context let temporaryDirectory: URL + /// Has the project been built? + private(set) var built = false + /// Contents of the built build log + private(set) var buildLogContents = [String]() - init() throws { - temporaryDirectory = try FileManager.default.temporaryDirectory(named: "gen-ir-tests-\(UUID().uuidString)") + /// Initializes the test context + init() { + // swiftlint:disable force_try + temporaryDirectory = try! FileManager.default.temporaryDirectory(named: "gen-ir-tests-\(UUID().uuidString)") archive = temporaryDirectory.appendingPathComponent("x.xcarchive") buildLog = temporaryDirectory.appendingPathComponent("build.log") } + + deinit { + try! FileManager.default.removeItem(at: temporaryDirectory) + // swiftlint:enable force_try + } + + /// Generate the log parser for this context + lazy var logParser: XcodeLogParser = { + XCTAssertTrue(built, "Requests a log parser without building the project") + let parser = XcodeLogParser(log: buildLogContents) + do { + try parser.parse() + } catch { + fatalError("XcodeLogParser error: \(error)") + } + return parser + }() + + /// Generate the PIF Cache for this context + lazy var pifCache: PIFCache = { + do { + return try PIFCache(buildCache: logParser.buildCachePath) + } catch { + fatalError("PIFCache init failed with error: \(error)") + } + }() + + /// Generate the Targets for this context + lazy var targets: [Target] = { + pifCache.targets.map { Target(from: $0) } + }() + + /// Generate the dependency graph for this context + lazy var graph: DependencyGraph = { + DependencyGraphBuilder(provider: PIFDependencyProvider(targets: targets, cache: pifCache), values: targets).graph + }() } diff --git a/Tests/GenIRTests/UmbrellaTests.swift b/Tests/GenIRTests/UmbrellaTests.swift index 167b05f..2b86381 100644 --- a/Tests/GenIRTests/UmbrellaTests.swift +++ b/Tests/GenIRTests/UmbrellaTests.swift @@ -1,36 +1,31 @@ import XCTest @testable import gen_ir -import PBXProjParser final class UmbrellaTests: XCTestCase { - static private var testPath: URL = { + let testPath: URL = { TestContext.testAssetPath .appendingPathComponent("Umbrella") .appendingPathComponent("Umbrella.xcworkspace") }() - static private var scheme = "Umbrella" + let scheme = "Umbrella" - static private let targetsToFiles = [ - "Common.framework": ["Common_vers.bc", "Common-dummy.bc", "OrgModel.bc"].sorted(), - "Networking.framework": ["Networking_vers.bc", "Networking-dummy.bc", "Networking.bc"].sorted(), - "Pods_Umbrella.framework": ["Pods_Umbrella_vers.bc", "Pods-Umbrella-dummy.bc"].sorted(), + let targetsToFiles = [ + "Common.framework": ["Common-dummy.bc", "Common_vers.bc", "OrgModel.bc"].sorted(), + "Networking.framework": ["Networking-dummy.bc", "Networking.bc", "Networking_vers.bc"].sorted(), + "Pods_Umbrella.framework": ["Pods-Umbrella-dummy.bc", "Pods_Umbrella_vers.bc"], "Umbrella.framework": ["GetOrg.bc", "Umbrella_vers.bc"].sorted() ] func testUmbrellaTargets() throws { - let context = try TestContext() - let process = try context.build(test: Self.testPath, scheme: Self.scheme) - XCTAssertEqual(process.code, 0, "Build returned non-zero exit code") - - let projectParser = try ProjectParser(path: Self.testPath, logLevel: .info) - let targets = Targets(for: projectParser) + let context = TestContext() + try context.build(test: testPath, scheme: scheme) + let targets = context.targets XCTAssertEqual(targets.count, 4, "Expected 4 targets, got \(targets.count)") let expectedTargetNames = ["Umbrella", "Common", "Networking", "Pods-Umbrella"].sorted() let actualTargetNames = targets.map { $0.name }.sorted() - XCTAssertEqual( actualTargetNames, expectedTargetNames, "Expected target names: \(expectedTargetNames), got: \(actualTargetNames)" @@ -38,16 +33,13 @@ final class UmbrellaTests: XCTestCase { } func testSkipInstallNo() throws { - let context = try TestContext() - defer { try? FileManager.default.removeItem(at: context.temporaryDirectory) } - let result = try context.build(test: Self.testPath, scheme: Self.scheme, additionalArguments: ["SKIP_INSTALL=NO"]) - XCTAssertEqual(result.code, 0, "Build returned non-zero exit code") + let context = TestContext() + try context.build(test: testPath, scheme: scheme, additionalArguments: ["SKIP_INSTALL=NO"]) let output = context.archive.appendingPathComponent("IR") var genIR = gen_ir.IREmitterCommand() try genIR.run( - project: Self.testPath, log: context.buildLog.filePath, archive: context.archive, level: .debug, @@ -58,28 +50,25 @@ final class UmbrellaTests: XCTestCase { let directories = try FileManager.default.directories(at: output, recursive: false) let targets = directories.map { $0.lastPathComponent } - XCTAssertEqual(targets.sorted(), Self.targetsToFiles.keys.sorted(), "Targets list doesn't match the known targets") + XCTAssertEqual(targets.sorted(), targetsToFiles.keys.sorted(), "Targets list doesn't match the known targets") for directory in directories { let contents = try FileManager.default.files(at: directory, withSuffix: "bc") .map { $0.lastPathComponent } .sorted() - XCTAssertEqual(contents, Self.targetsToFiles[directory.lastPathComponent]) + XCTAssertEqual(contents, targetsToFiles[directory.lastPathComponent]) } } func testCustomDerivedDataAndSkipInstallNo() throws { - let context = try TestContext() - defer { try? FileManager.default.removeItem(at: context.temporaryDirectory) } - let result = try context.build(test: Self.testPath, scheme: Self.scheme, additionalArguments: ["SKIP_INSTALL=NO", "-derivedDataPath", "_build"]) - XCTAssertEqual(result.code, 0, "Build returned non-zero exit code") + let context = TestContext() + try context.build(test: testPath, scheme: scheme, additionalArguments: ["SKIP_INSTALL=NO", "-derivedDataPath", "_build"]) let output = context.archive.appendingPathComponent("IR") var genIR = gen_ir.IREmitterCommand() try genIR.run( - project: Self.testPath, log: context.buildLog.filePath, archive: context.archive, level: .debug, @@ -90,14 +79,14 @@ final class UmbrellaTests: XCTestCase { let directories = try FileManager.default.directories(at: output, recursive: false) let targets = directories.map { $0.lastPathComponent } - XCTAssertEqual(targets.sorted(), Self.targetsToFiles.keys.sorted(), "Targets list doesn't match the known targets") + XCTAssertEqual(targets.sorted(), targetsToFiles.keys.sorted(), "Targets list doesn't match the known targets") for directory in directories { let contents = try FileManager.default.files(at: directory, withSuffix: "bc") .map { $0.lastPathComponent } .sorted() - XCTAssertEqual(contents, Self.targetsToFiles[directory.lastPathComponent]) + XCTAssertEqual(contents, targetsToFiles[directory.lastPathComponent]) } } } diff --git a/Tests/GenIRTests/WorkspaceContainerTests.swift b/Tests/GenIRTests/WorkspaceContainerTests.swift index e910bf5..8e1275e 100644 --- a/Tests/GenIRTests/WorkspaceContainerTests.swift +++ b/Tests/GenIRTests/WorkspaceContainerTests.swift @@ -1,17 +1,18 @@ import XCTest @testable import gen_ir -import PBXProjParser final class WorkspaceContainerTests: XCTestCase { - static private var testPath: URL = { + let testPath: URL = { TestContext.testAssetPath .appendingPathComponent("WorkspaceContainerTest") .appendingPathComponent("WorkspaceContainerTest.xcworkspace") }() + let scheme = "App" func testWeirdGroupTagLocationParsing() throws { - let parser = try ProjectParser(path: Self.testPath, logLevel: .debug) - let targets = parser.targets + let context = TestContext() + try context.build(test: testPath, scheme: scheme) + let targets = context.targets XCTAssert(targets.count == 3) XCTAssertNotNil(targets.first(where: { $0.name == "App" })) diff --git a/Tests/GenIRTests/WorkspaceTests.swift b/Tests/GenIRTests/WorkspaceTests.swift index 7c2851a..d9f56d3 100644 --- a/Tests/GenIRTests/WorkspaceTests.swift +++ b/Tests/GenIRTests/WorkspaceTests.swift @@ -1,19 +1,18 @@ import XCTest @testable import gen_ir -import PBXProjParser final class WorkspaceTests: XCTestCase { - static private var testPath: URL = { + let testPath: URL = { TestContext.testAssetPath .appendingPathComponent("WorkspaceTest") .appendingPathComponent("Workspace.xcworkspace") }() - static private var scheme = "App" + let scheme = "App" static let appIRFiles: Set = ["AppApp.bc", "ContentView.bc", "GeneratedAssetSymbols.bc"] - static let commonIRFiles: Set = ["Common_vers.bc", "Model.bc"] - static let frameworkIRFiles: Set = ["Framework_vers.bc", "Framework.bc"] + static let commonIRFiles: Set = ["Model.bc", "Common_vers.bc"] + static let frameworkIRFiles: Set = ["Framework.bc", "Framework_vers.bc"] static let sfSafeSymbolsIRFiles: Set = [ "NSImageExtension.bc", "SFSymbol+1.0.bc", @@ -50,14 +49,12 @@ final class WorkspaceTests: XCTestCase { ] func testWorkspace() throws { - let context = try TestContext() - let process = try context.build(test: Self.testPath, scheme: Self.scheme) - XCTAssertEqual(process.code, 0, "Build returned non-zero exit code") + let context = TestContext() + try context.build(test: testPath, scheme: scheme) var genIR = gen_ir.IREmitterCommand() try genIR.run( - project: Self.testPath, log: context.buildLog.filePath, archive: context.archive, level: .debug, @@ -65,41 +62,18 @@ final class WorkspaceTests: XCTestCase { dumpDependencyGraph: false ) - // Check dependencies made it to the right place + // Check dependencies made it to the right place. All dependencies should be statically + // linked and appear under the .app directory. let appIRPath = context.archive.appending(path: "IR/App.app/") - let commonIRPath = context.archive.appending(path: "IR/Common.framework/") - let frameworkIRPath = context.archive.appending(path: "IR/Framework.framework/") - let sfSafeSymbolsIRPath = context.archive.appending(path: "IR/SFSafeSymbols/") - let appIRPathContents = try FileManager.default.contentsOfDirectory(at: appIRPath, includingPropertiesForKeys: nil) - .reduce(into: Set(), { $0.insert($1.lastPathComponent) }) - let commonIRPathContents = try FileManager.default.contentsOfDirectory(at: commonIRPath, includingPropertiesForKeys: nil) - .reduce(into: Set(), { $0.insert($1.lastPathComponent) }) - let frameworkIRPathContents = try FileManager.default.contentsOfDirectory(at: frameworkIRPath, includingPropertiesForKeys: nil) - .reduce(into: Set(), { $0.insert($1.lastPathComponent) }) - let sfSafeSymbolsIRPathContents = try FileManager.default.contentsOfDirectory(at: sfSafeSymbolsIRPath, includingPropertiesForKeys: nil) - .reduce(into: Set(), { $0.insert($1.lastPathComponent) }) - - let expectedAppIRFiles = Self.appIRFiles + let expectedIRFiles = Self.appIRFiles .union(Self.commonIRFiles) .union(Self.frameworkIRFiles) .union(Self.sfSafeSymbolsIRFiles) - .reduce(into: Set(), { $0.insert($1) }) - let expectedFrameworkIRFiles = Self.frameworkIRFiles - .union(Self.commonIRFiles) - .union(Self.sfSafeSymbolsIRFiles) - .reduce(into: Set(), { $0.insert($1) }) - - let expectedCommonIRFiles = Self.commonIRFiles - .reduce(into: Set(), { $0.insert($1) }) - - let expectedSFSafeSymbolsIRFiles = Self.sfSafeSymbolsIRFiles - .reduce(into: Set(), { $0.insert($1) }) + let appIRPathContents = try FileManager.default.contentsOfDirectory(at: appIRPath, includingPropertiesForKeys: nil) + .reduce(into: Set(), { $0.insert($1.lastPathComponent) }) - XCTAssertEqual(expectedAppIRFiles, appIRPathContents, "App IR expected contents didn't equal actual") - XCTAssertEqual(expectedFrameworkIRFiles, frameworkIRPathContents, "Framework IR expected contents didn't equal actual") - XCTAssertEqual(expectedCommonIRFiles, commonIRPathContents, "Common IR expected contents didn't equal actual") - XCTAssertEqual(expectedSFSafeSymbolsIRFiles, sfSafeSymbolsIRPathContents, "SFSafeSymbols IR expected contents didn't equal actual") + XCTAssertEqual(expectedIRFiles, appIRPathContents, "App IR expected contents didn't equal actual: \(expectedIRFiles.symmetricDifference(appIRPathContents))") } } diff --git a/Tests/GenIRTests/gen_irTests.swift b/Tests/GenIRTests/gen_irTests.swift index ffdfd9f..fcfc920 100644 --- a/Tests/GenIRTests/gen_irTests.swift +++ b/Tests/GenIRTests/gen_irTests.swift @@ -1,15 +1,16 @@ import XCTest @testable import gen_ir -import PBXProjParser final class GenIRTests: XCTestCase { func testManyTargetTestTargets() throws { - let projectPath = TestContext.baseTestingPath + let context = TestContext() + let projectPath = TestContext.baseProjectPath .appendingPathComponent("TestAssets") .appendingPathComponent("ManyTargetTest") .appendingPathComponent("ManyTargetTest.xcodeproj") - let project = try ProjectParser(path: projectPath, logLevel: logger.logLevel) - let targets = Targets(for: project) + + try context.build(test: projectPath, scheme: "ManyTargetTest") + let targets = context.targets XCTAssert(targets.count == 3, "Targets count expected to be 3, was \(targets.count)")