@@ -789,6 +789,92 @@ final class ExplicitModuleBuildTests: XCTestCase {
789789 }
790790 }
791791
792+ func testBinaryFrameworkDependencyScan( ) throws {
793+ try withTemporaryDirectory { path in
794+ let ( stdLibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning ( )
795+ let moduleCachePath = path. appending ( component: " ModuleCache " )
796+
797+ // Setup module to be used as dependency
798+ try localFileSystem. createDirectory ( moduleCachePath)
799+ let frameworksPath = path. appending ( component: " Frameworks " )
800+ let frameworkModuleDir = frameworksPath. appending ( component: " Foo.framework " )
801+ . appending ( component: " Modules " )
802+ . appending ( component: " Foo.swiftmodule " )
803+ let frameworkModulePath =
804+ frameworkModuleDir. appending ( component: hostTriple. archName + " .swiftmodule " )
805+ try localFileSystem. createDirectory ( frameworkModuleDir, recursive: true )
806+ let fooSourcePath = path. appending ( component: " Foo.swift " )
807+ try localFileSystem. writeFileContents ( fooSourcePath) {
808+ $0 <<< " public func foo() {} "
809+ }
810+
811+ // Setup our main test module
812+ let mainSourcePath = path. appending ( component: " Foo.swift " )
813+ try localFileSystem. writeFileContents ( mainSourcePath) {
814+ $0 <<< " import Foo "
815+ }
816+
817+ // 1. Build Foo module
818+ let sdkArgumentsForTesting = ( try ? Driver . sdkArgumentsForTesting ( ) ) ?? [ ]
819+ var driverFoo = try Driver ( args: [ " swiftc " ,
820+ " -module-cache-path " , moduleCachePath. nativePathString ( escaped: true ) ,
821+ " -module-name " , " Foo " ,
822+ " -emit-module " ,
823+ " -emit-module-path " ,
824+ frameworkModulePath. nativePathString ( escaped: true ) ,
825+ " -working-directory " ,
826+ path. nativePathString ( escaped: true ) ,
827+ fooSourcePath. nativePathString ( escaped: true ) ] + sdkArgumentsForTesting,
828+ env: ProcessEnv . vars)
829+ let jobs = try driverFoo. planBuild ( )
830+ try driverFoo. run ( jobs: jobs)
831+ XCTAssertFalse ( driverFoo. diagnosticEngine. hasErrors)
832+
833+ // 2. Run a dependency scan to find the just-built module
834+ let dependencyOracle = InterModuleDependencyOracle ( )
835+ let scanLibPath = try Driver . getScanLibPath ( of: toolchain,
836+ hostTriple: hostTriple,
837+ env: ProcessEnv . vars)
838+ guard try dependencyOracle
839+ . verifyOrCreateScannerInstance ( fileSystem: localFileSystem,
840+ swiftScanLibPath: scanLibPath) else {
841+ XCTFail ( " Dependency scanner library not found " )
842+ return
843+ }
844+ guard try dependencyOracle. supportsBinaryFrameworkDependencies ( ) else {
845+ throw XCTSkip ( " libSwiftScan does not support framework binary dependency reporting. " )
846+ }
847+
848+ var driver = try Driver ( args: [ " swiftc " ,
849+ " -I " , stdLibPath. nativePathString ( escaped: true ) ,
850+ " -I " , shimsPath. nativePathString ( escaped: true ) ,
851+ " -F " , frameworksPath. nativePathString ( escaped: true ) ,
852+ " -import-objc-header " ,
853+ " -explicit-module-build " ,
854+ " -module-name " , " main " ,
855+ " -working-directory " , path. nativePathString ( escaped: true ) ,
856+ mainSourcePath. nativePathString ( escaped: true ) ] + sdkArgumentsForTesting,
857+ env: ProcessEnv . vars)
858+ let resolver = try ArgsResolver ( fileSystem: localFileSystem)
859+ var scannerCommand = try driver. dependencyScannerInvocationCommand ( ) . 1 . map { try resolver. resolve ( $0) }
860+ if scannerCommand. first == " -frontend " {
861+ scannerCommand. removeFirst ( )
862+ }
863+ let dependencyGraph =
864+ try ! dependencyOracle. getDependencies ( workingDirectory: path,
865+ commandLine: scannerCommand)
866+
867+ let fooDependencyInfo = try XCTUnwrap ( dependencyGraph. modules [ . swiftPrebuiltExternal( " Foo " ) ] )
868+ guard case . swiftPrebuiltExternal( let fooDetails) = fooDependencyInfo. details else {
869+ XCTFail ( " Foo dependency module does not have Swift details field " )
870+ return
871+ }
872+
873+ // Ensure the dependency has been reported as a framework
874+ XCTAssertTrue ( fooDetails. isFramework)
875+ }
876+ }
877+
792878 func getStdlibShimsPaths( _ driver: Driver ) throws -> ( AbsolutePath , AbsolutePath ) {
793879 let toolchainRootPath : AbsolutePath = try driver. toolchain. getToolPath ( . swiftCompiler)
794880 . parentDirectory // bin
0 commit comments