swiftlang / swift

The Swift Programming Language
https://swift.org
Apache License 2.0
67.09k stars 10.33k forks source link

When specifying a `-resource-dir` and an `-sdk`, the `swift-frontend` still looks in the latter for runtime modules to import #73445

Open finagolfin opened 3 months ago

finagolfin commented 3 months ago

Description

I was testing #72161 and #72634 natively on Android last week, by building those pulls in the Termux app with an older, prebuilt host trunk Swift toolchain installed. Those pulls remove the Glibc module on Android, replacing it with a new module called Android. This would cause build errors when building the SwiftPrivate module in the stdlib:

/data/data/com.termux/files/usr/lib/swift/android/Glibc.swiftmodule/aarch64-unknown-linux-android.private.swiftinterface:6:19: error: no such module 'SwiftGlibc'
  4 │ // swift-module-flags-ignorable: -enable-ossa-modules -enable-lexical-lifetimes=false
  5 │ import Swift
  6 │ @_exported import SwiftGlibc
    │                   ╰─ error: no such module 'SwiftGlibc'
  7 │ import SwiftOverlayShims
  8 │ import SwiftShims

/data/data/com.termux/files/home/swift/stdlib/private/SwiftPrivateThreadExtras/SwiftPrivateThreadExtras.swift:21:8: error: failed to build module 'Glibc'; this SDK is not supported by the compiler (the SDK is built with 'Swift version 5.11-dev (LLVM efc2ccb85e795fb, Swift ada2e40efcb58be)', while this compiler is 'Swift version 6.0-dev effective-5.10 (LLVM aa5a99efe7c5734, Swift 2f6e9b392b15bf0)'). Please select a toolchain which matches the SDK.
 19 │ import Darwin
 20 │ #elseif canImport(Glibc)
 21 │ import Glibc
    │        ╰─ error: failed to build module 'Glibc'; this SDK is not supported by the compiler (the SDK is built with 'Swift version 5.11-dev (LLVM efc2ccb85e795fb, Swift ada2e40efcb58be)', while this compiler is 'Swift version 6.0-dev effective-5.10 (LLVM aa5a99efe7c5734, Swift 2f6e9b392b15bf0)'). Please select a toolchain which matches the SDK.
 22 │ #elseif canImport(Musl)
 23 │ import Musl

The issue is that when both -resource-dir and -sdk flags are supplied, the swift-frontend looks in both for the runtime modules to import, so not finding Glibc in the new build directory passed in as the -resource-dir, it also looks for Glibc in the -sdk, where the prebuilt host toolchain happens to be installed, then errors because that is a different Swift version.

I think that if a -resource-dir is specified, the compiler should only look in there for runtime modules, not in -sdk also.

This patch does that and fixes the problem for me:

diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index 6534e5afa9e..fcabef6ae85 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -219,7 +219,7 @@ static void updateRuntimeLibraryPaths(SearchPathOptions &SearchPathOpts,
     RuntimeLibraryImportPaths.push_back(std::string(LibPath.str()));
   }

-  if (!SearchPathOpts.getSDKPath().empty()) {
+  if (!SearchPathOpts.getSDKPath().empty() && SearchPathOpts.RuntimeResourcePath.empty()) {
     if (tripleIsMacCatalystEnvironment(Triple)) {
       LibPath = SearchPathOpts.getSDKPath();
       llvm::sys::path::append(LibPath, "System", "iOSSupport");

Now that a prebuilt host Swift toolchain is pretty much required to build trunk, and it will often be installed in the same sysroot as the -sdk, this problem could hit on any platform, though only likely when moving runtime modules like this. I think this is an edge case worth closing up on all platforms.

Reproduction

Something like this may show it on linux too, haven't tried it:

  1. Install a prebuilt Swift 5.10 toolchain in your -sdk path, usually /.
  2. Check out source for the Swift trunk stdlib and disable building the Glibc module, as shown in the linked Android pulls.
  3. Try to build the Swift stdlib and it will likely try to import the 5.10 Glibc module instead and fail.

Expected behavior

Only look in the -resource-dir specified for Swift runtime modules

Environment

Building the March 1 trunk snapshot natively on Android 13 AArch64 using a prebuilt February 2 trunk snapshot toolchain

Additional information

This issue probably hasn't been hit before because both paths have the same set of runtime modules most of the time, and the compiler looks in -resource-dir first. On Unix, I'm fairly certain it should only look in -resource-dir, if that flag is specified, but I'm not sure about Darwin and Windows, having never built Swift for those platforms.

Pinging @etcwilde and @compnerd, to see what you think of the proposed fix and whether a specified -resource-dir should be the only place to look on all platforms.

finagolfin commented 2 months ago

Hmm, after running the tests on my patch above, looks like that won't work. It turns out that even if -resource-dir is not passed in, the frontend sets SearchPathOpts.RuntimeResourcePath using the executable path, so I can't assume SearchPathOpts.RuntimeResourcePath was only set by the -resource-dir flag.

So to maintain the existing logic, I'll have to track whether SearchPathOpts.RuntimeResourcePath was set by the -resource-dir flag, by adding another boolean signifying that it was and checking that too.