From 47f9d789900a4c3c74b34863915830bd2558747e Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 28 Jun 2024 13:16:47 -0700 Subject: [PATCH] ClangImporter: add support for Android API Notes Introduce the first APINotes injection for the Android platform. This follows the VCRuntime pattern of permitting the SDK to provide API Notes that augment the system SDK. This adds a workaround for incorrect nullability on the `fts_open` function in bionic. The system library itself is fixed at: https://android-review.googlesource.com/c/platform/bionic/+/3151616 --- lib/ClangImporter/ClangIncludePaths.cpp | 51 ++++++++++++++++--- stdlib/public/Platform/CMakeLists.txt | 5 ++ .../public/Platform/posix_filesystem.apinotes | 7 +++ 3 files changed, 56 insertions(+), 7 deletions(-) create mode 100644 stdlib/public/Platform/posix_filesystem.apinotes diff --git a/lib/ClangImporter/ClangIncludePaths.cpp b/lib/ClangImporter/ClangIncludePaths.cpp index 23431af724459..20933c2331e92 100644 --- a/lib/ClangImporter/ClangIncludePaths.cpp +++ b/lib/ClangImporter/ClangIncludePaths.cpp @@ -396,18 +396,19 @@ static void getLibStdCxxFileMapping( namespace { std::string -GetWindowsAuxiliaryFile(StringRef modulemap, const SearchPathOptions &Options) { +GetPlatformAuxiliaryFile(StringRef Platform, StringRef File, + const SearchPathOptions &Options) { StringRef SDKPath = Options.getSDKPath(); if (!SDKPath.empty()) { llvm::SmallString<261> path{SDKPath}; - llvm::sys::path::append(path, "usr", "share", modulemap); + llvm::sys::path::append(path, "usr", "share", File); if (llvm::sys::fs::exists(path)) return path.str().str(); } if (!Options.RuntimeResourcePath.empty()) { llvm::SmallString<261> path{Options.RuntimeResourcePath}; - llvm::sys::path::append(path, "windows", modulemap); + llvm::sys::path::append(path, Platform, File); if (llvm::sys::fs::exists(path)) return path.str().str(); } @@ -415,6 +416,29 @@ GetWindowsAuxiliaryFile(StringRef modulemap, const SearchPathOptions &Options) { return ""; } +SmallVector, 2> +GetAndroidFileMappings( + ASTContext &Context, const std::string &sysroot, + const llvm::IntrusiveRefCntPtr &VFS) { + const llvm::Triple &Triple = Context.LangOpts.Target; + const SearchPathOptions &SearchPathOpts = Context.SearchPathOpts; + SmallVector, 2> Mappings; + std::string AuxiliaryFile; + + if (!Triple.isAndroid()) return Mappings; + + llvm::SmallString<261> NDKInjection{sysroot}; + llvm::sys::path::append(NDKInjection, "posix_filesystem.apinotes"); + + AuxiliaryFile = + GetPlatformAuxiliaryFile("android", "posix_filesystem.apinotes", + SearchPathOpts); + if (!AuxiliaryFile.empty()) + Mappings.emplace_back(std::string(NDKInjection), AuxiliaryFile); + + return Mappings; +} + SmallVector, 2> GetWindowsFileMappings( ASTContext &Context, const llvm::IntrusiveRefCntPtr &driverVFS, @@ -449,7 +473,8 @@ SmallVector, 2> GetWindowsFileMappings( llvm::sys::path::append(WinSDKInjection, WindowsSDK.IncludeVersion, "um"); llvm::sys::path::append(WinSDKInjection, "module.modulemap"); - AuxiliaryFile = GetWindowsAuxiliaryFile("winsdk.modulemap", SearchPathOpts); + AuxiliaryFile = + GetPlatformAuxiliaryFile("windows", "winsdk.modulemap", SearchPathOpts); if (!AuxiliaryFile.empty()) Mappings.emplace_back(std::string(WinSDKInjection), AuxiliaryFile); } @@ -465,7 +490,8 @@ SmallVector, 2> GetWindowsFileMappings( llvm::sys::path::append(UCRTInjection, "Include", UCRTSDK.Version, "ucrt"); llvm::sys::path::append(UCRTInjection, "module.modulemap"); - AuxiliaryFile = GetWindowsAuxiliaryFile("ucrt.modulemap", SearchPathOpts); + AuxiliaryFile = + GetPlatformAuxiliaryFile("windows", "ucrt.modulemap", SearchPathOpts); if (!AuxiliaryFile.empty()) { // The ucrt module map has the C standard library headers all together. // That leads to module cycles with the clang _Builtin_ modules. e.g. @@ -502,14 +528,16 @@ SmallVector, 2> GetWindowsFileMappings( llvm::sys::path::append(VCToolsInjection, "module.modulemap"); AuxiliaryFile = - GetWindowsAuxiliaryFile("vcruntime.modulemap", SearchPathOpts); + GetPlatformAuxiliaryFile("windows", "vcruntime.modulemap", + SearchPathOpts); if (!AuxiliaryFile.empty()) Mappings.emplace_back(std::string(VCToolsInjection), AuxiliaryFile); llvm::sys::path::remove_filename(VCToolsInjection); llvm::sys::path::append(VCToolsInjection, "vcruntime.apinotes"); AuxiliaryFile = - GetWindowsAuxiliaryFile("vcruntime.apinotes", SearchPathOpts); + GetPlatformAuxiliaryFile("windows", "vcruntime.apinotes", + SearchPathOpts); if (!AuxiliaryFile.empty()) Mappings.emplace_back(std::string(VCToolsInjection), AuxiliaryFile); } @@ -525,6 +553,7 @@ ClangInvocationFileMapping swift::getClangInvocationFileMapping( vfs = llvm::vfs::getRealFileSystem(); const llvm::Triple &triple = ctx.LangOpts.Target; + llvm::SmallString<256> sysroot; // For modulemaps that have all the C standard library headers together in // a single module, we end up with module cycles with the clang _Builtin_ @@ -560,6 +589,11 @@ ClangInvocationFileMapping swift::getClangInvocationFileMapping( StringRef headerFiles[] = {"SwiftAndroidNDK.h", "SwiftBionic.h"}; libcFileMapping = getLibcFileMapping(ctx, "android.modulemap", headerFiles, vfs); + + if (!libcFileMapping.empty()) { + sysroot = libcFileMapping[0].first; + llvm::sys::path::remove_filename(sysroot); + } } else if (triple.isOSGlibc() || triple.isOSOpenBSD() || triple.isOSFreeBSD()) { // BSD/Linux Mappings @@ -577,5 +611,8 @@ ClangInvocationFileMapping swift::getClangInvocationFileMapping( result.redirectedFiles.append(GetWindowsFileMappings( ctx, vfs, result.requiresBuiltinHeadersInSystemModules)); + result.redirectedFiles.append(GetAndroidFileMappings(ctx, sysroot.str().str(), + vfs)); + return result; } diff --git a/stdlib/public/Platform/CMakeLists.txt b/stdlib/public/Platform/CMakeLists.txt index 14754a5d67ae3..996e072ee1a31 100644 --- a/stdlib/public/Platform/CMakeLists.txt +++ b/stdlib/public/Platform/CMakeLists.txt @@ -473,6 +473,11 @@ if("ANDROID" IN_LIST SWIFT_SDKS) COMPONENT sdk-overlay) endif() endforeach() + + swift_install_in_component(FILES + posix_filesystem.apinotes + DESTINATION "share" + COMPONENT sdk-overlay) endif() add_custom_target(android_modulemap DEPENDS ${android_modulemap_target_list}) set_property(TARGET android_modulemap PROPERTY FOLDER "Miscellaneous") diff --git a/stdlib/public/Platform/posix_filesystem.apinotes b/stdlib/public/Platform/posix_filesystem.apinotes new file mode 100644 index 0000000000000..b423ebd325685 --- /dev/null +++ b/stdlib/public/Platform/posix_filesystem.apinotes @@ -0,0 +1,7 @@ +--- +Name: bionic +Functions: +- Name: fts_open + Parameters: + - Position: 0 + Type: "char * const _Nullable * _Nonnull"