From 40244a2935ba024dcc0c37af89fa47f37c41721f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferri=C3=A8re?= Date: Fri, 21 Feb 2025 11:43:00 -0800 Subject: [PATCH 1/2] Frontend: Ignore resilient binary swiftmodules under usr/lib/swift Most SDKs use only swiftinterfaces under usr/lib/swift. Let's make sure we standardize this behavior and use only swiftinterface when they are present, even if there are also binary swiftmodule files available. Apply the same logic to SubFrameworks as well while we're at it. rdar://145316821 --- include/swift/AST/DiagnosticsFrontend.def | 1 + lib/Frontend/ModuleInterfaceLoader.cpp | 30 ++++++++++++++++++- .../ignore-adjacent-swiftmodules.swift | 25 ++++++++++++++++ .../Modules/SubSwift.swiftmodule/source.swift | 1 + .../source.swift | 1 + 5 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/Sema/Inputs/public-private-sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/source.swift create mode 100644 test/Sema/Inputs/public-private-sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/source.swift diff --git a/include/swift/AST/DiagnosticsFrontend.def b/include/swift/AST/DiagnosticsFrontend.def index 7fa4d6fefd823..dc5d82d37657a 100644 --- a/include/swift/AST/DiagnosticsFrontend.def +++ b/include/swift/AST/DiagnosticsFrontend.def @@ -440,6 +440,7 @@ NOTE(sdk_version_pbm_version,none, NOTE(compiled_module_ignored_reason,none, "compiled module '%0' was ignored because %select{%error" "|it belongs to a framework in the SDK" + "|it's a library module in the SDK" "|loading from module interfaces is preferred" "|it's a compiler host module" "|the module name is blocklisted," diff --git a/lib/Frontend/ModuleInterfaceLoader.cpp b/lib/Frontend/ModuleInterfaceLoader.cpp index b5854d422990b..afca2671a31af 100644 --- a/lib/Frontend/ModuleInterfaceLoader.cpp +++ b/lib/Frontend/ModuleInterfaceLoader.cpp @@ -237,6 +237,7 @@ struct ModuleRebuildInfo { enum class ReasonIgnored { NotIgnored, PublicFramework, + PublicLibrary, InterfacePreferred, CompilerHostModule, Blocklisted, @@ -762,6 +763,28 @@ class ModuleInterfaceLoaderImpl { return pathStartsWith(frameworksPath, path); } + bool isInSystemSubFrameworks(StringRef path) { + StringRef sdkPath = ctx.SearchPathOpts.getSDKPath(); + if (sdkPath.empty()) return false; + + SmallString<128> frameworksPath; + llvm::sys::path::append(frameworksPath, + sdkPath, "System", "Library", "SubFrameworks"); + + return pathStartsWith(frameworksPath, path); + } + + bool isInSystemLibraries(StringRef path) { + StringRef sdkPath = ctx.SearchPathOpts.getSDKPath(); + if (sdkPath.empty()) return false; + + SmallString<128> frameworksPath; + llvm::sys::path::append(frameworksPath, + sdkPath, "usr", "lib", "swift"); + + return pathStartsWith(frameworksPath, path); + } + std::pair getCompiledModuleCandidates() { using ReasonIgnored = ModuleRebuildInfo::ReasonIgnored; using ReasonModuleInterfaceIgnored = @@ -813,10 +836,15 @@ class ModuleInterfaceLoaderImpl { // Don't use the adjacent swiftmodule for frameworks from the public // Frameworks folder of the SDK. - if (isInSystemFrameworks(modulePath, /*publicFramework*/true)) { + if (isInSystemFrameworks(modulePath, /*publicFramework*/true) || + isInSystemSubFrameworks(modulePath)) { shouldLoadAdjacentModule = false; rebuildInfo.addIgnoredModule(modulePath, ReasonIgnored::PublicFramework); + } else if (isInSystemLibraries(modulePath) && moduleName != STDLIB_NAME) { + shouldLoadAdjacentModule = false; + rebuildInfo.addIgnoredModule(modulePath, + ReasonIgnored::PublicLibrary); } else if (isInResourceHostDir(modulePath)) { shouldLoadAdjacentModule = false; rebuildInfo.addIgnoredModule(modulePath, diff --git a/test/ModuleInterface/ignore-adjacent-swiftmodules.swift b/test/ModuleInterface/ignore-adjacent-swiftmodules.swift index 77d9ffda8b712..47dd519e97faf 100644 --- a/test/ModuleInterface/ignore-adjacent-swiftmodules.swift +++ b/test/ModuleInterface/ignore-adjacent-swiftmodules.swift @@ -3,21 +3,40 @@ // REQUIRES: VENDOR=apple /// Prepare the SDK. +//// Public framework // RUN: cp -r %S/../Sema/Inputs/public-private-sdk %t/sdk // RUN: %target-swift-frontend -emit-module -module-name PublicSwift -enable-library-evolution -swift-version 5 \ // RUN: %t/sdk/System/Library/Frameworks/PublicSwift.framework/Modules/PublicSwift.swiftmodule/source.swift \ // RUN: -o %t/sdk/System/Library/Frameworks/PublicSwift.framework/Modules/PublicSwift.swiftmodule/%target-swiftmodule-name \ // RUN: -emit-module-interface-path %t/sdk/System/Library/Frameworks/PublicSwift.framework/Modules/PublicSwift.swiftmodule/%target-swiftinterface-name // RUN: %target-swift-typecheck-module-from-interface(%t/sdk/System/Library/Frameworks/PublicSwift.framework/Modules/PublicSwift.swiftmodule/%target-swiftinterface-name) -module-name PublicSwift + +//// Private framework // RUN: %target-swift-frontend -emit-module -module-name PrivateSwift -enable-library-evolution -swift-version 5 \ // RUN: %t/sdk/System/Library/PrivateFrameworks/PrivateSwift.framework/Modules/PrivateSwift.swiftmodule/source.swift \ // RUN: -o %t/sdk/System/Library/PrivateFrameworks/PrivateSwift.framework/Modules/PrivateSwift.swiftmodule/%target-swiftmodule-name \ // RUN: -emit-module-interface-path %t/sdk/System/Library/PrivateFrameworks/PrivateSwift.framework/Modules/PrivateSwift.swiftmodule/%target-swiftinterface-name // RUN: %target-swift-typecheck-module-from-interface(%t/sdk/System/Library/PrivateFrameworks/PrivateSwift.framework/Modules/PrivateSwift.swiftmodule/%target-swiftinterface-name) -module-name PrivateSwift +//// Public library +// RUN: %target-swift-frontend -emit-module -module-name PublicSwiftLibrary -enable-library-evolution -swift-version 5 \ +// RUN: %t/sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/source.swift \ +// RUN: -o %t/sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/%target-swiftmodule-name \ +// RUN: -emit-module-interface-path %t/sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/%target-swiftinterface-name +// RUN: %target-swift-typecheck-module-from-interface(%t/sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/%target-swiftinterface-name) -module-name PublicSwiftLibrary + +//// Public subframework +// RUN: %target-swift-frontend -emit-module -module-name SubSwift -enable-library-evolution -swift-version 5 \ +// RUN: %t/sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/source.swift \ +// RUN: -o %t/sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/%target-swiftmodule-name \ +// RUN: -emit-module-interface-path %t/sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/%target-swiftinterface-name +// RUN: %target-swift-typecheck-module-from-interface(%t/sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/%target-swiftinterface-name) -module-name SubSwift + /// Break the swiftmodules. // RUN: echo "This is a malformed swiftmodule" > %t/sdk/System/Library/Frameworks/PublicSwift.framework/Modules/PublicSwift.swiftmodule/%target-swiftmodule-name // RUN: echo "This is a malformed swiftmodule" > %t/sdk/System/Library/PrivateFrameworks/PrivateSwift.framework/Modules/PrivateSwift.swiftmodule/%target-swiftmodule-name +// RUN: echo "This is a malformed swiftmodule" > %t/sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/%target-swiftmodule-name +// RUN: echo "This is a malformed swiftmodule" > %t/sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/%target-swiftmodule-name /// There should be no attempt at loading the malformed PublicSwift swiftmodule. /// This means no notes about: @@ -36,3 +55,9 @@ import PrivateSwift // expected-remark @-1 {{rebuilding module 'PrivateSwift' from interface}} // expected-note @-2 {{compiled module is out of date}} // expected-note @-3 {{: malformed}} + +import PublicSwiftLibrary // expected-remark {{rebuilding module 'PublicSwiftLibrary' from interface}} +// expected-note @-1 {{was ignored because it's a library module in the SDK}} + +import SubSwift // expected-remark {{rebuilding module 'SubSwift' from interface}} +// expected-note @-1 {{was ignored because it belongs to a framework in the SDK}} diff --git a/test/Sema/Inputs/public-private-sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/source.swift b/test/Sema/Inputs/public-private-sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/source.swift new file mode 100644 index 0000000000000..6d71fe5d9cef6 --- /dev/null +++ b/test/Sema/Inputs/public-private-sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/source.swift @@ -0,0 +1 @@ +public func foo() {} diff --git a/test/Sema/Inputs/public-private-sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/source.swift b/test/Sema/Inputs/public-private-sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/source.swift new file mode 100644 index 0000000000000..6d71fe5d9cef6 --- /dev/null +++ b/test/Sema/Inputs/public-private-sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/source.swift @@ -0,0 +1 @@ +public func foo() {} From f6ef819ecf2edbcbff3024b6f8924a0e7c72fa9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexis=20Laferri=C3=A8re?= Date: Mon, 24 Feb 2025 12:00:04 -0800 Subject: [PATCH 2/2] Frontend: Test that we still use the adjacent swiftmodule for the stdlib --- .../ignore-adjacent-swiftmodules.swift | 45 ++++++++++++++++--- .../lib/swift/Swift.swiftmodule/source.swift | 1 + 2 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 test/Sema/Inputs/public-private-sdk/usr/lib/swift/Swift.swiftmodule/source.swift diff --git a/test/ModuleInterface/ignore-adjacent-swiftmodules.swift b/test/ModuleInterface/ignore-adjacent-swiftmodules.swift index 47dd519e97faf..106c17c3891e0 100644 --- a/test/ModuleInterface/ignore-adjacent-swiftmodules.swift +++ b/test/ModuleInterface/ignore-adjacent-swiftmodules.swift @@ -1,11 +1,22 @@ // RUN: %empty-directory(%t) -// RUN: %empty-directory(%t/cache) +// RUN: %empty-directory(%t/cache0) +// RUN: %empty-directory(%t/cache1) +// RUN: cp -r %S/../Sema/Inputs/public-private-sdk %t/sdk // REQUIRES: VENDOR=apple /// Prepare the SDK. +//// stdlib +// RUN: %target-swift-frontend -emit-module -module-name Swift -enable-library-evolution -swift-version 5 \ +// RUN: -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Osize \ +// RUN: %t/sdk/usr/lib/swift/Swift.swiftmodule/source.swift \ +// RUN: -o %t/sdk/usr/lib/swift/Swift.swiftmodule/%target-swiftmodule-name \ +// RUN: -emit-module-interface-path %t/sdk/usr/lib/swift/Swift.swiftmodule/%target-swiftinterface-name \ +// RUN: -parse-stdlib +// RUN: %target-swift-typecheck-module-from-interface(%t/sdk/usr/lib/swift/Swift.swiftmodule/%target-swiftinterface-name) -module-name Swift -parse-stdlib + //// Public framework -// RUN: cp -r %S/../Sema/Inputs/public-private-sdk %t/sdk // RUN: %target-swift-frontend -emit-module -module-name PublicSwift -enable-library-evolution -swift-version 5 \ +// RUN: -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Osize -sdk %t/sdk \ // RUN: %t/sdk/System/Library/Frameworks/PublicSwift.framework/Modules/PublicSwift.swiftmodule/source.swift \ // RUN: -o %t/sdk/System/Library/Frameworks/PublicSwift.framework/Modules/PublicSwift.swiftmodule/%target-swiftmodule-name \ // RUN: -emit-module-interface-path %t/sdk/System/Library/Frameworks/PublicSwift.framework/Modules/PublicSwift.swiftmodule/%target-swiftinterface-name @@ -13,6 +24,7 @@ //// Private framework // RUN: %target-swift-frontend -emit-module -module-name PrivateSwift -enable-library-evolution -swift-version 5 \ +// RUN: -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Osize -sdk %t/sdk \ // RUN: %t/sdk/System/Library/PrivateFrameworks/PrivateSwift.framework/Modules/PrivateSwift.swiftmodule/source.swift \ // RUN: -o %t/sdk/System/Library/PrivateFrameworks/PrivateSwift.framework/Modules/PrivateSwift.swiftmodule/%target-swiftmodule-name \ // RUN: -emit-module-interface-path %t/sdk/System/Library/PrivateFrameworks/PrivateSwift.framework/Modules/PrivateSwift.swiftmodule/%target-swiftinterface-name @@ -20,6 +32,7 @@ //// Public library // RUN: %target-swift-frontend -emit-module -module-name PublicSwiftLibrary -enable-library-evolution -swift-version 5 \ +// RUN: -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Osize -sdk %t/sdk \ // RUN: %t/sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/source.swift \ // RUN: -o %t/sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/%target-swiftmodule-name \ // RUN: -emit-module-interface-path %t/sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/%target-swiftinterface-name @@ -27,6 +40,7 @@ //// Public subframework // RUN: %target-swift-frontend -emit-module -module-name SubSwift -enable-library-evolution -swift-version 5 \ +// RUN: -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import -Osize -sdk %t/sdk \ // RUN: %t/sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/source.swift \ // RUN: -o %t/sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/%target-swiftmodule-name \ // RUN: -emit-module-interface-path %t/sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/%target-swiftinterface-name @@ -38,14 +52,31 @@ // RUN: echo "This is a malformed swiftmodule" > %t/sdk/System/Library/SubFrameworks/SubSwift.framework/Modules/SubSwift.swiftmodule/%target-swiftmodule-name // RUN: echo "This is a malformed swiftmodule" > %t/sdk/usr/lib/swift/PublicSwiftLibrary.swiftmodule/%target-swiftmodule-name -/// There should be no attempt at loading the malformed PublicSwift swiftmodule. -/// This means no notes about: +/// Check the loading behavior from attempts at loading the malformed swiftmodules, +/// printing the notes: /// * compiled module is out of date /// * unable to load compiled module '*': malformed + +/// Check diagnostics in the local file: // RUN: %target-swift-frontend -typecheck %s -sdk %t/sdk \ -// RUN: -module-name Main -module-cache-path %t/cache \ -// RUN: -F %t/sdk/System/Library/PrivateFrameworks/ \ -// RUN: -verify -Rmodule-interface-rebuild +// RUN: -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import \ +// RUN: -module-name Main -module-cache-path %t/cache0 \ +// RUN: -F %t/sdk/System/Library/PrivateFrameworks/ -resource-dir "" \ +// RUN: -verify -verify-ignore-unknown -Rmodule-interface-rebuild -diagnostic-style=llvm + +/// Check diagnostic for implicit imports: +// RUN: echo "This is a malformed swiftmodule" > %t/sdk/usr/lib/swift/Swift.swiftmodule/%target-swiftmodule-name +// RUN: %target-swift-frontend -typecheck %s -sdk %t/sdk \ +// RUN: -disable-implicit-concurrency-module-import -disable-implicit-string-processing-module-import \ +// RUN: -module-name Main -module-cache-path %t/cache1 \ +// RUN: -F %t/sdk/System/Library/PrivateFrameworks/ -resource-dir "" \ +// RUN: -Rmodule-interface-rebuild -Rmodule-loading -diagnostic-style=llvm 2> %t/out +// RUN: %FileCheck --input-file %t/out %s + +import Swift +// CHECK: rebuilding module 'Swift' from interface +// CHECK-NEXT: compiled module is out of date +// CHECK-NEXT: : malformed import PublicSwift // expected-remark {{rebuilding module 'PublicSwift' from interface}} // expected-note @-1 {{was ignored because it belongs to a framework in the SDK}} diff --git a/test/Sema/Inputs/public-private-sdk/usr/lib/swift/Swift.swiftmodule/source.swift b/test/Sema/Inputs/public-private-sdk/usr/lib/swift/Swift.swiftmodule/source.swift new file mode 100644 index 0000000000000..6d71fe5d9cef6 --- /dev/null +++ b/test/Sema/Inputs/public-private-sdk/usr/lib/swift/Swift.swiftmodule/source.swift @@ -0,0 +1 @@ +public func foo() {}