diff --git a/Sources/CSwiftScan/include/swiftscan_header.h b/Sources/CSwiftScan/include/swiftscan_header.h index d17b40b4c..bb3a67f62 100644 --- a/Sources/CSwiftScan/include/swiftscan_header.h +++ b/Sources/CSwiftScan/include/swiftscan_header.h @@ -155,6 +155,8 @@ typedef struct { (*swiftscan_swift_binary_detail_get_is_framework)(swiftscan_module_details_t); swiftscan_string_ref_t (*swiftscan_swift_binary_detail_get_module_cache_key)(swiftscan_module_details_t); + swiftscan_string_set_t * + (*swiftscan_swift_binary_detail_get_header_dependency_module_dependencies)(swiftscan_module_details_t); //=== Swift Placeholder Module Details query APIs -------------------------===// swiftscan_string_ref_t diff --git a/Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift b/Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift index f7b457573..e7b4cc736 100644 --- a/Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift +++ b/Sources/SwiftDriver/ExplicitModuleBuilds/ExplicitDependencyBuildPlanner.swift @@ -253,8 +253,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT inputs: inout [TypedVirtualPath], commandLine: inout [Job.ArgTemplate]) throws { // Prohibit the frontend from implicitly building textual modules into binary modules. - var swiftDependencyArtifacts: [SwiftModuleArtifactInfo] = [] - var clangDependencyArtifacts: [ClangModuleArtifactInfo] = [] + var swiftDependencyArtifacts: Set = [] + var clangDependencyArtifacts: Set = [] try addModuleDependencies(of: moduleId, clangDependencyArtifacts: &clangDependencyArtifacts, swiftDependencyArtifacts: &swiftDependencyArtifacts) @@ -276,8 +276,6 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT inputs.append(TypedVirtualPath(file: headerDep.path, type: .pch)) } } - - // Clang module dependencies are specified on the command line explicitly for moduleArtifactInfo in clangDependencyArtifacts { let clangModulePath = TypedVirtualPath(file: moduleArtifactInfo.clangModulePath.path, @@ -311,8 +309,9 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT private mutating func addModuleDependency(of moduleId: ModuleDependencyId, dependencyId: ModuleDependencyId, - clangDependencyArtifacts: inout [ClangModuleArtifactInfo], - swiftDependencyArtifacts: inout [SwiftModuleArtifactInfo] + clangDependencyArtifacts: inout Set, + swiftDependencyArtifacts: inout Set, + bridgingHeaderDeps: Set? = nil ) throws { switch dependencyId { case .swift: @@ -325,7 +324,7 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT isFramework = swiftModuleDetails.isFramework ?? false // Accumulate the required information about this dependency // TODO: add .swiftdoc and .swiftsourceinfo for this module. - swiftDependencyArtifacts.append( + swiftDependencyArtifacts.insert( SwiftModuleArtifactInfo(name: dependencyId.moduleName, modulePath: TextualVirtualPath(path: swiftModulePath.fileHandle), isFramework: isFramework, @@ -335,11 +334,12 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT let dependencyClangModuleDetails = try dependencyGraph.clangModuleDetails(of: dependencyId) // Accumulate the required information about this dependency - clangDependencyArtifacts.append( + clangDependencyArtifacts.insert( ClangModuleArtifactInfo(name: dependencyId.moduleName, modulePath: TextualVirtualPath(path: dependencyInfo.modulePath.path), moduleMapPath: dependencyClangModuleDetails.moduleMapPath, - moduleCacheKey: dependencyClangModuleDetails.moduleCacheKey)) + moduleCacheKey: dependencyClangModuleDetails.moduleCacheKey, + isBridgingHeaderDependency: bridgingHeaderDeps?.contains(dependencyId) ?? true)) case .swiftPrebuiltExternal: let prebuiltModuleDetails = try dependencyGraph.swiftPrebuiltDetails(of: dependencyId) let compiledModulePath = prebuiltModuleDetails.compiledModulePath @@ -348,7 +348,7 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT .init(file: compiledModulePath.path, type: .swiftModule) // Accumulate the required information about this dependency // TODO: add .swiftdoc and .swiftsourceinfo for this module. - swiftDependencyArtifacts.append( + swiftDependencyArtifacts.insert( SwiftModuleArtifactInfo(name: dependencyId.moduleName, modulePath: TextualVirtualPath(path: swiftModulePath.fileHandle), headerDependencies: prebuiltModuleDetails.headerDependencyPaths, @@ -359,11 +359,37 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT } } + /// Collect the Set of all Clang module dependencies which are dependencies of either + /// the `moduleId` bridging header or dependencies of bridging headers + /// of any prebuilt binary Swift modules in the dependency graph. + private func collectHeaderModuleDeps(of moduleId: ModuleDependencyId) throws -> Set? { + var bridgingHeaderDeps: Set? = nil + guard let moduleDependencies = reachabilityMap[moduleId] else { + fatalError("Expected reachability information for the module: \(moduleId.moduleName).") + } + if let dependencySourceBridingHeaderDeps = + try dependencyGraph.moduleInfo(of: moduleId).bridgingHeaderModuleDependencies { + bridgingHeaderDeps = Set(dependencySourceBridingHeaderDeps) + } else { + bridgingHeaderDeps = Set() + } + // Collect all binary Swift module dependnecies' header input module dependencies + for dependencyId in moduleDependencies { + if case .swiftPrebuiltExternal(_) = dependencyId { + let prebuiltDependencyDetails = try dependencyGraph.swiftPrebuiltDetails(of: dependencyId) + for headerDependency in prebuiltDependencyDetails.headerDependencyModuleDependencies ?? [] { + bridgingHeaderDeps!.insert(headerDependency) + } + } + } + return bridgingHeaderDeps + } + /// Add a specific module dependency as an input and a corresponding command /// line flag. private mutating func addModuleDependencies(of moduleId: ModuleDependencyId, - clangDependencyArtifacts: inout [ClangModuleArtifactInfo], - swiftDependencyArtifacts: inout [SwiftModuleArtifactInfo] + clangDependencyArtifacts: inout Set, + swiftDependencyArtifacts: inout Set ) throws { guard let moduleDependencies = reachabilityMap[moduleId] else { fatalError("Expected reachability information for the module: \(moduleId.moduleName).") @@ -371,7 +397,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT for dependencyId in moduleDependencies { try addModuleDependency(of: moduleId, dependencyId: dependencyId, clangDependencyArtifacts: &clangDependencyArtifacts, - swiftDependencyArtifacts: &swiftDependencyArtifacts) + swiftDependencyArtifacts: &swiftDependencyArtifacts, + bridgingHeaderDeps: try collectHeaderModuleDeps(of: moduleId)) } } @@ -430,8 +457,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT public mutating func resolveBridgingHeaderDependencies(inputs: inout [TypedVirtualPath], commandLine: inout [Job.ArgTemplate]) throws { let mainModuleId: ModuleDependencyId = .swift(dependencyGraph.mainModuleName) - var swiftDependencyArtifacts: [SwiftModuleArtifactInfo] = [] - var clangDependencyArtifacts: [ClangModuleArtifactInfo] = [] + var swiftDependencyArtifacts: Set = [] + var clangDependencyArtifacts: Set = [] let mainModuleDetails = try dependencyGraph.swiftModuleDetails(of: mainModuleId) var addedDependencies: Set = [] @@ -491,8 +518,8 @@ public typealias ExternalTargetModuleDetailsMap = [ModuleDependencyId: ExternalT /// Serialize the output file artifacts for a given module in JSON format. private func serializeModuleDependencies(for moduleId: ModuleDependencyId, - swiftDependencyArtifacts: [SwiftModuleArtifactInfo], - clangDependencyArtifacts: [ClangModuleArtifactInfo] + swiftDependencyArtifacts: Set, + clangDependencyArtifacts: Set ) throws -> Data { // The module dependency map in CAS needs to be stable. // Sort the dependencies by name. diff --git a/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/CommonDependencyOperations.swift b/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/CommonDependencyOperations.swift index a4c742a07..eaad3543d 100644 --- a/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/CommonDependencyOperations.swift +++ b/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/CommonDependencyOperations.swift @@ -252,22 +252,22 @@ extension InterModuleDependencyGraph { internal extension InterModuleDependencyGraph { func explainDependency(dependencyModuleName: String) throws -> [[ModuleDependencyId]]? { guard modules.contains(where: { $0.key.moduleName == dependencyModuleName }) else { return nil } - var results = [[ModuleDependencyId]]() + var results = Set<[ModuleDependencyId]>() try findAllPaths(source: .swift(mainModuleName), to: dependencyModuleName, pathSoFar: [.swift(mainModuleName)], results: &results) - return Array(results) + return results.sorted(by: { $0.count < $1.count }) } private func findAllPaths(source: ModuleDependencyId, to moduleName: String, pathSoFar: [ModuleDependencyId], - results: inout [[ModuleDependencyId]]) throws { + results: inout Set<[ModuleDependencyId]>) throws { let sourceInfo = try moduleInfo(of: source) // If the source is our target, we are done - guard source.moduleName != moduleName else { + if source.moduleName == moduleName { // If the source is a target Swift module, also check if it // depends on a corresponding Clang module with the same name. // If it does, add it to the path as well. @@ -276,8 +276,7 @@ internal extension InterModuleDependencyGraph { dependencies.contains(.clang(moduleName)) { completePath.append(.clang(moduleName)) } - results.append(completePath) - return + results.insert(completePath) } var allDependencies = sourceInfo.directDependencies ?? [] diff --git a/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/InterModuleDependencyGraph.swift b/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/InterModuleDependencyGraph.swift index 47374b247..e45b6c765 100644 --- a/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/InterModuleDependencyGraph.swift +++ b/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/InterModuleDependencyGraph.swift @@ -164,24 +164,14 @@ public struct SwiftPrebuiltExternalModuleDetails: Codable, Hashable { /// The paths to the binary module's header dependencies public var headerDependencyPaths: [TextualVirtualPath]? + /// Clang module dependencies of the textual header input + public var headerDependencyModuleDependencies: [ModuleDependencyId]? + /// A flag to indicate whether or not this module is a framework. public var isFramework: Bool? /// The module cache key of the pre-built module. public var moduleCacheKey: String? - - public init(compiledModulePath: TextualVirtualPath, - moduleDocPath: TextualVirtualPath? = nil, - moduleSourceInfoPath: TextualVirtualPath? = nil, - headerDependencies: [TextualVirtualPath]? = nil, - isFramework: Bool, moduleCacheKey: String? = nil) throws { - self.compiledModulePath = compiledModulePath - self.moduleDocPath = moduleDocPath - self.moduleSourceInfoPath = moduleSourceInfoPath - self.headerDependencyPaths = headerDependencies - self.isFramework = isFramework - self.moduleCacheKey = moduleCacheKey - } } /// Details specific to Clang modules. @@ -201,18 +191,6 @@ public struct ClangModuleDetails: Codable, Hashable { /// The module cache key of the output module. public var moduleCacheKey: String? - - public init(moduleMapPath: TextualVirtualPath, - contextHash: String, - commandLine: [String], - capturedPCMArgs: Set<[String]>?, - moduleCacheKey: String? = nil) { - self.moduleMapPath = moduleMapPath - self.contextHash = contextHash - self.commandLine = commandLine - self.capturedPCMArgs = capturedPCMArgs - self.moduleCacheKey = moduleCacheKey - } } public struct ModuleInfo: Codable, Hashable { @@ -302,6 +280,19 @@ extension ModuleInfo.Details: Codable { } } +extension ModuleInfo { + var bridgingHeaderModuleDependencies: [ModuleDependencyId]? { + switch details { + case .swift(let swiftDetails): + return swiftDetails.bridgingHeaderDependencies + case .swiftPrebuiltExternal(let swiftPrebuiltDetails): + return swiftPrebuiltDetails.headerDependencyModuleDependencies + default: + return nil + } + } +} + /// Describes the complete set of dependencies for a Swift module, including /// all of the Swift and C modules and source files it depends on. public struct InterModuleDependencyGraph: Codable { diff --git a/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/InterModuleDependencyOracle.swift b/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/InterModuleDependencyOracle.swift index 27590f9ea..c54bc30a0 100644 --- a/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/InterModuleDependencyOracle.swift +++ b/Sources/SwiftDriver/ExplicitModuleBuilds/InterModuleDependencies/InterModuleDependencyOracle.swift @@ -132,6 +132,13 @@ public class InterModuleDependencyOracle { return swiftScan.hasBinarySwiftModuleIsFramework } + @_spi(Testing) public func supportsBinaryModuleHeaderModuleDependencies() throws -> Bool { + guard let swiftScan = swiftScanLibInstance else { + fatalError("Attempting to query supported scanner API with no scanner instance.") + } + return swiftScan.hasBinarySwiftModuleHeaderModuleDependencies + } + @_spi(Testing) public func supportsScannerDiagnostics() throws -> Bool { guard let swiftScan = swiftScanLibInstance else { fatalError("Attempting to query supported scanner API with no scanner instance.") diff --git a/Sources/SwiftDriver/ExplicitModuleBuilds/SerializableModuleArtifacts.swift b/Sources/SwiftDriver/ExplicitModuleBuilds/SerializableModuleArtifacts.swift index 5f6e51faa..1049ab802 100644 --- a/Sources/SwiftDriver/ExplicitModuleBuilds/SerializableModuleArtifacts.swift +++ b/Sources/SwiftDriver/ExplicitModuleBuilds/SerializableModuleArtifacts.swift @@ -15,7 +15,7 @@ /// - Swift Module Path /// - Swift Doc Path /// - Swift Source Info Path -@_spi(Testing) public struct SwiftModuleArtifactInfo: Codable { +@_spi(Testing) public struct SwiftModuleArtifactInfo: Codable, Hashable { /// The module's name public let moduleName: String /// The path for the module's .swiftmodule file @@ -48,7 +48,7 @@ /// - Clang Module (name) /// - Clang Module (PCM) Path /// - Clang Module Map Path -@_spi(Testing) public struct ClangModuleArtifactInfo: Codable { +@_spi(Testing) public struct ClangModuleArtifactInfo: Codable, Hashable { /// The module's name public let moduleName: String /// The path for the module's .pcm file @@ -57,24 +57,28 @@ public let clangModuleMapPath: TextualVirtualPath /// A flag to indicate whether this module is a framework public let isFramework: Bool + /// A flag to indicate whether this module is a dependency + /// of the main module's bridging header + public let isBridgingHeaderDependency: Bool /// The cache key for the module. public let clangModuleCacheKey: String? init(name: String, modulePath: TextualVirtualPath, moduleMapPath: TextualVirtualPath, - moduleCacheKey: String? = nil) { + moduleCacheKey: String? = nil, isBridgingHeaderDependency: Bool = true) { self.moduleName = name self.clangModulePath = modulePath self.clangModuleMapPath = moduleMapPath self.isFramework = false + self.isBridgingHeaderDependency = isBridgingHeaderDependency self.clangModuleCacheKey = moduleCacheKey } } -enum ModuleDependencyArtifactInfo: Codable { +@_spi(Testing) public enum ModuleDependencyArtifactInfo: Codable { case clang(ClangModuleArtifactInfo) case swift(SwiftModuleArtifactInfo) - func encode(to encoder: Encoder) throws { + @_spi(Testing) public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() switch self { case .swift(let swiftInfo): @@ -83,6 +87,17 @@ enum ModuleDependencyArtifactInfo: Codable { try container.encode(clangInfo) } } + + @_spi(Testing) public init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + do { + let thing = try container.decode(SwiftModuleArtifactInfo.self) + self = .swift(thing) + } catch { + let thing = try container.decode(ClangModuleArtifactInfo.self) + self = .clang(thing) + } + } } /// Describes a given module's batch dependency scanning input info diff --git a/Sources/SwiftDriver/SwiftScan/DependencyGraphBuilder.swift b/Sources/SwiftDriver/SwiftScan/DependencyGraphBuilder.swift index 542fb5fbc..44cf74f18 100644 --- a/Sources/SwiftDriver/SwiftScan/DependencyGraphBuilder.swift +++ b/Sources/SwiftDriver/SwiftScan/DependencyGraphBuilder.swift @@ -249,15 +249,22 @@ private extension SwiftScan { } else { isFramework = false } + + let headerDependencyModuleDependencies: [ModuleDependencyId]? = + hasBinarySwiftModuleHeaderModuleDependencies ? + try getOptionalStringArrayDetail(from: moduleDetailsRef, + using: api.swiftscan_swift_binary_detail_get_header_dependency_module_dependencies)?.map { .clang($0) } : nil + let moduleCacheKey = supportsCaching ? try getOptionalStringDetail(from: moduleDetailsRef, using: api.swiftscan_swift_binary_detail_get_module_cache_key) : nil - return try SwiftPrebuiltExternalModuleDetails(compiledModulePath: compiledModulePath, - moduleDocPath: moduleDocPath, - moduleSourceInfoPath: moduleSourceInfoPath, - headerDependencies: headerDependencies, - isFramework: isFramework, - moduleCacheKey: moduleCacheKey) + return SwiftPrebuiltExternalModuleDetails(compiledModulePath: compiledModulePath, + moduleDocPath: moduleDocPath, + moduleSourceInfoPath: moduleSourceInfoPath, + headerDependencyPaths: headerDependencies, + headerDependencyModuleDependencies: headerDependencyModuleDependencies, + isFramework: isFramework, + moduleCacheKey: moduleCacheKey) } /// Construct a `SwiftPlaceholderModuleDetails` from a `swiftscan_module_details_t` reference diff --git a/Sources/SwiftDriver/SwiftScan/SwiftScan.swift b/Sources/SwiftDriver/SwiftScan/SwiftScan.swift index b319a50d4..8b23ecdd3 100644 --- a/Sources/SwiftDriver/SwiftScan/SwiftScan.swift +++ b/Sources/SwiftDriver/SwiftScan/SwiftScan.swift @@ -268,6 +268,10 @@ internal extension swiftscan_diagnostic_severity_t { api.swiftscan_swift_binary_detail_get_is_framework != nil } + @_spi(Testing) public var hasBinarySwiftModuleHeaderModuleDependencies : Bool { + api.swiftscan_swift_binary_detail_get_header_dependency_module_dependencies != nil + } + @_spi(Testing) public var canLoadStoreScannerCache : Bool { api.swiftscan_scanner_cache_load != nil && api.swiftscan_scanner_cache_serialize != nil && @@ -534,6 +538,11 @@ private extension swiftscan_functions_t { self.swiftscan_swift_binary_detail_get_is_framework = try loadOptional("swiftscan_swift_binary_detail_get_is_framework") + // Clang module dependencies of header input of binary module dependencies + self.swiftscan_swift_binary_detail_get_header_dependency_module_dependencies = + try loadOptional("swiftscan_swift_binary_detail_get_header_dependency_module_dependencies") + + // Bridging PCH build command-line self.swiftscan_swift_textual_detail_get_bridging_pch_command_line = try loadOptional("swiftscan_swift_textual_detail_get_bridging_pch_command_line") diff --git a/Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift b/Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift index 73e0719d3..18b9c4a15 100644 --- a/Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift +++ b/Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift @@ -87,8 +87,6 @@ private func checkExplicitModuleBuildJobDependencies(job: Job, XCTAssertTrue(job.inputs.contains(clangDependencyModulePath)) XCTAssertTrue(job.commandLine.contains( .flag(String("-fmodule-file=\(dependencyId.moduleName)=\(clangDependencyModulePathString)")))) - XCTAssertTrue(job.commandLine.contains( - .flag(String("-fmodule-map-file=\(clangDependencyDetails.moduleMapPath.path.description)")))) } for dependencyId in moduleInfo.directDependencies! { @@ -276,6 +274,76 @@ final class ExplicitModuleBuildTests: XCTestCase { path.extension! == FileType.swiftModule.rawValue } + /// Test generation of explicit module build jobs for dependency modules when the driver + /// is invoked with -explicit-module-build + func testBridgingHeaderDeps() throws { + try withTemporaryDirectory { path in + let main = path.appending(component: "testExplicitModuleBuildJobs.swift") + try localFileSystem.writeFileContents(main, bytes: + """ + import C;\ + import E;\ + import G; + """ + ) + let cHeadersPath: AbsolutePath = + try testInputsPath.appending(component: "ExplicitModuleBuilds") + .appending(component: "CHeaders") + let bridgingHeaderpath: AbsolutePath = + cHeadersPath.appending(component: "Bridging.h") + let swiftModuleInterfacesPath: AbsolutePath = + try testInputsPath.appending(component: "ExplicitModuleBuilds") + .appending(component: "Swift") + let sdkArgumentsForTesting = (try? Driver.sdkArgumentsForTesting()) ?? [] + var driver = try Driver(args: ["swiftc", + "-target", "x86_64-apple-macosx11.0", + "-I", cHeadersPath.nativePathString(escaped: true), + "-I", swiftModuleInterfacesPath.nativePathString(escaped: true), + "-explicit-module-build", + "-import-objc-header", bridgingHeaderpath.nativePathString(escaped: true), + main.nativePathString(escaped: true)] + sdkArgumentsForTesting) + let jobs = try driver.planBuild() + let compileJob = try XCTUnwrap(jobs.first(where: { $0.kind == .compile })) + + // Load the dependency JSON and verify this dependency was encoded correctly + let explicitDepsFlag = + SwiftDriver.Job.ArgTemplate.flag(String("-explicit-swift-module-map-file")) + XCTAssert(compileJob.commandLine.contains(explicitDepsFlag)) + let jsonDepsPathIndex = compileJob.commandLine.firstIndex(of: explicitDepsFlag) + let jsonDepsPathArg = compileJob.commandLine[jsonDepsPathIndex! + 1] + guard case .path(let jsonDepsPath) = jsonDepsPathArg else { + XCTFail("No JSON dependency file path found.") + return + } + guard case let .temporaryWithKnownContents(_, contents) = jsonDepsPath else { + XCTFail("Unexpected path type") + return + } + let jsonDepsDecoded = try JSONDecoder().decode(Array.self, from: contents) + + // Ensure that "F" is specified as a bridging dependency + XCTAssertTrue(jsonDepsDecoded.contains { artifactInfo in + if case .clang(let details) = artifactInfo { + return details.moduleName == "F" && details.isBridgingHeaderDependency == true + } else { + return false + } + }) + + // If the scanner supports the feature, ensure that "C" is reported as *not* a bridging + // header dependency + if try driver.interModuleDependencyOracle.supportsBinaryModuleHeaderModuleDependencies() { + XCTAssertTrue(jsonDepsDecoded.contains { artifactInfo in + if case .clang(let details) = artifactInfo { + return details.moduleName == "C" && details.isBridgingHeaderDependency == false + } else { + return false + } + }) + } + } + } + /// Test generation of explicit module build jobs for dependency modules when the driver /// is invoked with -explicit-module-build func testExplicitModuleBuildJobs() throws { @@ -541,7 +609,7 @@ final class ExplicitModuleBuildTests: XCTestCase { let swiftModuleInterfacesPath: AbsolutePath = try testInputsPath.appending(component: "ExplicitModuleBuilds") - .appending(component: "Swift") + .appending(component: "Swift") let cHeadersPath: AbsolutePath = try testInputsPath.appending(component: "ExplicitModuleBuilds") .appending(component: "CHeaders") @@ -1923,6 +1991,7 @@ final class ExplicitModuleBuildTests: XCTestCase { print(diag.behavior) print(diag.message) } + XCTAssertEqual(driver.diagnosticEngine.diagnostics.filter { $0.behavior == .note}.count, 2) XCTAssertTrue(driver.diagnosticEngine.diagnostics.contains { $0.behavior == .note && $0.message.text == "[testTraceDependency] -> [A] -> [A](ObjC)"}) XCTAssertTrue(driver.diagnosticEngine.diagnostics.contains { $0.behavior == .note &&