Skip to content

Revert "[Dependency Scanning] Move computation of the path for libSwiftScan to the toolchain" #1260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jan 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions Sources/SwiftDriver/Driver/Driver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -650,11 +650,11 @@ public struct Driver {
outputFileMap: outputFileMap)

self.supportedFrontendFlags =
try Self.computeSupportedCompilerArgs(of: self.toolchain,
parsedOptions: &self.parsedOptions,
diagnosticsEngine: diagnosticEngine,
fileSystem: fileSystem,
executor: executor)
try Self.computeSupportedCompilerArgs(of: self.toolchain, hostTriple: self.hostTriple,
parsedOptions: &self.parsedOptions,
diagnosticsEngine: diagnosticEngine,
fileSystem: fileSystem, executor: executor,
env: env)
let supportedFrontendFlagsLocal = self.supportedFrontendFlags
self.savedUnknownDriverFlagsForSwiftFrontend = try self.parsedOptions.saveUnknownFlags {
Driver.isOptionFound($0, allOpts: supportedFrontendFlagsLocal)
Expand Down
24 changes: 0 additions & 24 deletions Sources/SwiftDriver/Driver/WindowsExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,3 @@ internal func executableName(_ name: String) -> String {
return name
#endif
}

@_spi(Testing) public func sharedLibraryName(_ name: String) -> String {
#if canImport(Darwin)
let ext = ".dylib"
#elseif os(Windows)
let ext = ".dll"
#else
let ext = ".so"
#endif
return name + ext
}

// FIXME: This can be subtly wrong, we should rather
// try to get the client to provide this info or move to a better
// path convention for where we keep compiler support libraries
internal var compilerHostSupportLibraryOSComponent : String {
#if canImport(Darwin)
return "macosx"
#elseif os(Windows)
return "windows"
#else
return "linux"
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ public extension Driver {
// attempt to fallback to using `swift-frontend -scan-dependencies` invocations for dependency
// scanning.
var fallbackToFrontend = parsedOptions.hasArgument(.driverScanDependenciesNonLib)
let scanLibPath = try toolchain.lookupSwiftScanLib()
let scanLibPath = try Self.getScanLibPath(of: toolchain, hostTriple: hostTriple, env: env)
if try interModuleDependencyOracle
.verifyOrCreateScannerInstance(fileSystem: fileSystem,
swiftScanLibPath: scanLibPath) == false {
Expand Down Expand Up @@ -490,9 +490,46 @@ public extension Driver {
useResponseFiles: useResponseFiles)
return args
}
}

@_spi(Testing) public extension Driver {
static func getScanLibPath(of toolchain: Toolchain, hostTriple: Triple,
env: [String: String]) throws -> AbsolutePath {
if hostTriple.isWindows {
// no matter if we are in a build tree or an installed tree, the layout is
// always: `bin/_InternalSwiftScan.dll`
return try getRootPath(of: toolchain, env: env)
.appending(component: "bin")
.appending(component: "_InternalSwiftScan.dll")
}

let sharedLibExt: String
if hostTriple.isMacOSX {
sharedLibExt = ".dylib"
} else {
sharedLibExt = ".so"
}
let libScanner = "lib_InternalSwiftScan\(sharedLibExt)"
// We first look into position in toolchain
let libPath
= try getRootPath(of: toolchain, env: env).appending(component: "lib")
.appending(component: "swift")
.appending(component: hostTriple.osNameUnversioned)
.appending(component: libScanner)
if localFileSystem.exists(libPath) {
return libPath
}
// In case we are using a compiler from the build dir, we should also try
// this path.
return try getRootPath(of: toolchain, env: env).appending(component: "lib")
.appending(component: libScanner)
}

static func getRootPath(of toolchain: Toolchain, env: [String: String])
throws -> AbsolutePath {
if let overrideString = env["SWIFT_DRIVER_SWIFT_SCAN_TOOLCHAIN_PATH"] {
return try AbsolutePath(validating: overrideString)
}
return try toolchain.getToolPath(.swiftCompiler)
.parentDirectory // bin
.parentDirectory // toolchain root
Expand Down
17 changes: 10 additions & 7 deletions Sources/SwiftDriver/Jobs/EmitSupportedFeaturesJob.swift
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,14 @@ extension Toolchain {
}

extension Driver {

static func computeSupportedCompilerArgs(of toolchain: Toolchain,
static func computeSupportedCompilerArgs(of toolchain: Toolchain, hostTriple: Triple,
parsedOptions: inout ParsedOptions,
diagnosticsEngine: DiagnosticsEngine,
fileSystem: FileSystem,
executor: DriverExecutor)
executor: DriverExecutor, env: [String: String])
throws -> Set<String> {
if let supportedArgs =
try querySupportedCompilerArgsInProcess(of: toolchain, fileSystem: fileSystem) {
if let supportedArgs = try querySupportedCompilerArgsInProcess(of: toolchain, hostTriple: hostTriple,
fileSystem: fileSystem, env: env) {
return supportedArgs
}

Expand All @@ -85,9 +84,13 @@ extension Driver {
}

static func querySupportedCompilerArgsInProcess(of toolchain: Toolchain,
fileSystem: FileSystem)
hostTriple: Triple,
fileSystem: FileSystem,
env: [String: String])
throws -> Set<String>? {
let swiftScanLibPath = try toolchain.lookupSwiftScanLib()
let swiftScanLibPath = try Self.getScanLibPath(of: toolchain,
hostTriple: hostTriple,
env: env)
if fileSystem.exists(swiftScanLibPath) {
let libSwiftScanInstance = try SwiftScan(dylib: swiftScanLibPath)
if libSwiftScanInstance.canQuerySupportedArguments() {
Expand Down
12 changes: 8 additions & 4 deletions Sources/SwiftDriver/SwiftScan/SwiftScan.swift
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,14 @@ internal final class SwiftScan {
@_spi(Testing) public extension Driver {
func querySupportedArgumentsForTest() throws -> Set<String>? {
// If a capable libSwiftScan is found, manually ensure we can get the supported arguments
let scanLibPath = try toolchain.lookupSwiftScanLib()
let libSwiftScanInstance = try SwiftScan(dylib: scanLibPath)
if libSwiftScanInstance.canQuerySupportedArguments() {
return try libSwiftScanInstance.querySupportedArguments()
let scanLibPath = try Self.getScanLibPath(of: toolchain,
hostTriple: hostTriple,
env: env)
if fileSystem.exists(scanLibPath) {
let libSwiftScanInstance = try SwiftScan(dylib: scanLibPath)
if libSwiftScanInstance.canQuerySupportedArguments() {
return try libSwiftScanInstance.querySupportedArguments()
}
}
return nil
}
Expand Down
40 changes: 0 additions & 40 deletions Sources/SwiftDriver/Toolchains/Toolchain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -245,46 +245,6 @@ extension Toolchain {
}
}

/// Looks for the executable in the `SWIFT_DRIVER_SWIFTSCAN_LIB` environment variable, if found nothing,
/// looks in the `lib` relative to the compiler executable.
/// TODO: If the driver needs to lookup other shared libraries, this is simple to generalize
@_spi(Testing) public func lookupSwiftScanLib() throws -> AbsolutePath {
#if os(Windows)
// no matter if we are in a build tree or an installed tree, the layout is
// always: `bin/_InternalSwiftScan.dll`
return try toolchain.getToolPath(.swiftCompiler)
.parentDirectory // bin
.appending(component: "_InternalSwiftScan.dll")
#else
let libraryName = sharedLibraryName("lib_InternalSwiftScan")
if let overrideString = env["SWIFT_DRIVER_SWIFTSCAN_LIB"],
let path = try? AbsolutePath(validating: overrideString) {
return path
} else {
let compilerPath = try getToolPath(.swiftCompiler)
let toolchainRootPath = compilerPath.parentDirectory // bin
.parentDirectory // toolchain root

let searchPaths = [toolchainRootPath.appending(component: "lib")
.appending(component: "swift")
.appending(component: compilerHostSupportLibraryOSComponent),
toolchainRootPath.appending(component: "lib")
.appending(component: "swift")
.appending(component: "host"),
// In case we are using a compiler from the build dir, we should also try
// this path.
toolchainRootPath.appending(component: "lib")]
for libraryPath in searchPaths.map({ $0.appending(component: libraryName) }) {
if fileSystem.isFile(libraryPath) {
return libraryPath
}
}
}

throw ToolchainError.unableToFind(tool: libraryName)
#endif
}

private func xcrunFind(executable: String) throws -> AbsolutePath {
let xcrun = "xcrun"
guard lookupExecutablePath(filename: xcrun, searchPaths: searchPaths) != nil else {
Expand Down
38 changes: 26 additions & 12 deletions Tests/SwiftDriverTests/ExplicitModuleBuildTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,7 @@ final class ExplicitModuleBuildTests: XCTestCase {
}

func testModuleAliasingWithImportPrescan() throws {
let (_, _, toolchain, _) = try getDriverArtifactsForScanning()
let (_, _, toolchain, hostTriple) = try getDriverArtifactsForScanning()

let dummyDriver = try Driver(args: ["swiftc", "-module-name", "dummyDriverCheck", "test.swift"])
guard dummyDriver.isFrontendArgSupported(.moduleAlias) else {
Expand All @@ -658,7 +658,9 @@ final class ExplicitModuleBuildTests: XCTestCase {
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
// queries.
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try toolchain.lookupSwiftScanLib()
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
hostTriple: hostTriple,
env: ProcessEnv.vars)
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
Expand Down Expand Up @@ -838,7 +840,9 @@ final class ExplicitModuleBuildTests: XCTestCase {

// 2. Run a dependency scan to find the just-built module
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try toolchain.lookupSwiftScanLib()
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
hostTriple: hostTriple,
env: ProcessEnv.vars)
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
Expand Down Expand Up @@ -935,12 +939,14 @@ final class ExplicitModuleBuildTests: XCTestCase {

/// Test the libSwiftScan dependency scanning (import-prescan).
func testDependencyImportPrescan() throws {
let (stdLibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
let (stdLibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()

// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
// queries.
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try toolchain.lookupSwiftScanLib()
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
hostTriple: hostTriple,
env: ProcessEnv.vars)
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
Expand Down Expand Up @@ -1014,12 +1020,14 @@ final class ExplicitModuleBuildTests: XCTestCase {
}

func testDependencyScanningFailure() throws {
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
let (stdlibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()

// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
// queries.
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try toolchain.lookupSwiftScanLib()
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
hostTriple: hostTriple,
env: ProcessEnv.vars)
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
Expand Down Expand Up @@ -1090,7 +1098,9 @@ final class ExplicitModuleBuildTests: XCTestCase {
// The dependency oracle wraps an instance of libSwiftScan and ensures thread safety across
// queries.
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try toolchain.lookupSwiftScanLib()
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
hostTriple: hostTriple,
env: ProcessEnv.vars)
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
Expand Down Expand Up @@ -1283,9 +1293,11 @@ final class ExplicitModuleBuildTests: XCTestCase {
}

func testDependencyGraphDotSerialization() throws {
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
let (stdlibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
let dependencyOracle = InterModuleDependencyOracle()
let scanLibPath = try toolchain.lookupSwiftScanLib()
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
hostTriple: hostTriple,
env: ProcessEnv.vars)
guard try dependencyOracle
.verifyOrCreateScannerInstance(fileSystem: localFileSystem,
swiftScanLibPath: scanLibPath) else {
Expand Down Expand Up @@ -1346,7 +1358,7 @@ final class ExplicitModuleBuildTests: XCTestCase {

/// Test the libSwiftScan dependency scanning.
func testDependencyScanReuseCache() throws {
let (stdlibPath, shimsPath, toolchain, _) = try getDriverArtifactsForScanning()
let (stdlibPath, shimsPath, toolchain, hostTriple) = try getDriverArtifactsForScanning()
try withTemporaryDirectory { path in
let cacheSavePath = path.appending(component: "saved.moddepcache")
let main = path.appending(component: "testDependencyScanning.swift")
Expand Down Expand Up @@ -1382,7 +1394,9 @@ final class ExplicitModuleBuildTests: XCTestCase {
scannerCommand.removeFirst()
}

let scanLibPath = try toolchain.lookupSwiftScanLib()
let scanLibPath = try Driver.getScanLibPath(of: toolchain,
hostTriple: hostTriple,
env: ProcessEnv.vars)
// Run the first scan and serialize the cache contents.
let firstDependencyOracle = InterModuleDependencyOracle()
guard try firstDependencyOracle
Expand Down
12 changes: 3 additions & 9 deletions Tests/SwiftDriverTests/SwiftDriverTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6685,8 +6685,6 @@ final class SwiftDriverTests: XCTestCase {
let PATH = "PATH"
#endif
let SWIFT_FRONTEND_EXEC = "SWIFT_DRIVER_SWIFT_FRONTEND_EXEC"
let SWIFT_SCANNER_LIB = "SWIFT_DRIVER_SWIFTSCAN_LIB"


// Reset the environment to ensure tool resolution is exactly run against PATH.
var driver = try Driver(args: ["swiftc", "-print-target-info"], env: [PATH: ProcessEnv.path!])
Expand All @@ -6697,7 +6695,6 @@ final class SwiftDriverTests: XCTestCase {

try withTemporaryDirectory { toolsDirectory in
let customSwiftFrontend = toolsDirectory.appending(component: executableName("swift-frontend"))
let customSwiftScan = toolsDirectory.appending(component: sharedLibraryName("lib_InternalSwiftScan"))
try localFileSystem.createSymbolicLink(customSwiftFrontend, pointingAt: defaultSwiftFrontend, relative: false)

try withTemporaryDirectory { tempDirectory in
Expand All @@ -6710,9 +6707,7 @@ final class SwiftDriverTests: XCTestCase {
// test if SWIFT_DRIVER_TOOLNAME_EXEC is respected
do {
var driver = try Driver(args: ["swiftc", "-print-target-info"],
env: [PATH: ProcessEnv.path!,
SWIFT_FRONTEND_EXEC: customSwiftFrontend.pathString,
SWIFT_SCANNER_LIB: customSwiftScan.pathString])
env: [PATH: ProcessEnv.path!, SWIFT_FRONTEND_EXEC: customSwiftFrontend.pathString])
let jobs = try driver.planBuild()
XCTAssertEqual(jobs.count, 1)
XCTAssertEqual(jobs.first!.tool.name, customSwiftFrontend.pathString)
Expand All @@ -6721,16 +6716,15 @@ final class SwiftDriverTests: XCTestCase {
// test if tools directory is respected
do {
var driver = try Driver(args: ["swiftc", "-print-target-info", "-tools-directory", toolsDirectory.pathString],
env: [PATH: ProcessEnv.path!, SWIFT_SCANNER_LIB: customSwiftScan.pathString])
env: [PATH: ProcessEnv.path!])
let jobs = try driver.planBuild()
XCTAssertEqual(jobs.count, 1)
XCTAssertEqual(jobs.first!.tool.name, customSwiftFrontend.pathString)
}

// test if current working directory is searched before PATH
do {
var driver = try Driver(args: ["swiftc", "-print-target-info"],
env: [PATH: toolsDirectory.pathString, SWIFT_SCANNER_LIB: customSwiftScan.pathString])
var driver = try Driver(args: ["swiftc", "-print-target-info"], env: [PATH: toolsDirectory.pathString])
let jobs = try driver.planBuild()
XCTAssertEqual(jobs.count, 1)
XCTAssertEqual(jobs.first!.tool.name, anotherSwiftFrontend.pathString)
Expand Down