Skip to content

Commit 93415f9

Browse files
authored
Merge pull request #58962 from apple/egorzhdan/libstdcxx-path
[cxx-interop] Extract libstdc++ installation path from Clang
2 parents 025e919 + abf56bc commit 93415f9

File tree

4 files changed

+35
-46
lines changed

4 files changed

+35
-46
lines changed

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ WARNING(nonmutating_without_mutable_fields,none,
117117

118118
ERROR(module_map_not_found, none, "module map file '%0' not found", (StringRef))
119119

120+
WARNING(libstdcxx_not_found, none,
121+
"libstdc++ not found for '$0'; C++ stdlib may be unavailable",
122+
(StringRef))
123+
120124
NOTE(macro_not_imported_unsupported_operator, none, "operator not supported in macro arithmetic", ())
121125
NOTE(macro_not_imported_unsupported_named_operator, none, "operator '%0' not supported in macro arithmetic", (StringRef))
122126
NOTE(macro_not_imported_invalid_string_literal, none, "invalid string literal", ())

lib/ClangImporter/ClangImporter.cpp

Lines changed: 31 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "clang/Basic/TargetInfo.h"
5353
#include "clang/Basic/Version.h"
5454
#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
55+
#include "clang/Driver/Driver.h"
5556
#include "clang/Frontend/FrontendActions.h"
5657
#include "clang/Frontend/Utils.h"
5758
#include "clang/Index/IndexingAction.h"
@@ -875,19 +876,27 @@ getClangInvocationFileMapping(ASTContext &ctx) {
875876
if (!triple.isOSLinux())
876877
return {};
877878

878-
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts;
879-
880-
Path sdkPath(searchPathOpts.getSDKPath());
881-
if (sdkPath.empty())
882-
sdkPath = "/";
879+
auto clangDiags = clang::CompilerInstance::createDiagnostics(
880+
new clang::DiagnosticOptions());
881+
clang::driver::Driver clangDriver(ctx.ClangImporterOpts.clangPath,
882+
triple.str(), *clangDiags);
883+
auto cxxStdlibDirs =
884+
clangDriver.getLibStdCxxIncludePaths(llvm::opt::InputArgList(), triple);
885+
if (cxxStdlibDirs.empty()) {
886+
ctx.Diags.diagnose(SourceLoc(), diag::libstdcxx_not_found, triple.str());
887+
return {};
888+
}
889+
Path cxxStdlibDir(cxxStdlibDirs.front());
890+
// VFS does not allow mapping paths that contain `../` or `./`.
891+
llvm::sys::path::remove_dots(cxxStdlibDir, /*remove_dot_dot=*/true);
883892

884893
// Currently only a modulemap for libstdc++ is injected.
885894
if (!ctx.LangOpts.EnableCXXInterop)
886895
return {};
887896

888897
Path actualModuleMapPath;
889898
Path buffer;
890-
if (auto path = getLibStdCxxModuleMapPath(searchPathOpts, triple, buffer))
899+
if (auto path = getLibStdCxxModuleMapPath(ctx.SearchPathOpts, triple, buffer))
891900
actualModuleMapPath = path.getValue();
892901
else
893902
return {};
@@ -905,48 +914,26 @@ getClangInvocationFileMapping(ASTContext &ctx) {
905914
llvm::sys::path::remove_filename(actualHeaderPath);
906915
llvm::sys::path::append(actualHeaderPath, "libstdcxx.h");
907916

908-
Path cxxStdlibsRoot(sdkPath);
909-
llvm::sys::path::append(cxxStdlibsRoot, "usr", "include", "c++");
910-
if (!llvm::sys::fs::exists(cxxStdlibsRoot))
917+
// Inject a modulemap into VFS for the libstdc++ directory.
918+
// Only inject the module map if the module does not already exist at
919+
// {sysroot}/usr/include/module.{map,modulemap}.
920+
Path injectedModuleMapLegacyPath(cxxStdlibDir);
921+
llvm::sys::path::append(injectedModuleMapLegacyPath, "module.map");
922+
if (llvm::sys::fs::exists(injectedModuleMapLegacyPath))
911923
return {};
912924

913-
// Collect all installed versions of libstdc++. We currently have no way to
914-
// know which libstdc++ version will be used for this Clang invocation.
915-
// TODO: extract this information from the Clang driver.
916-
SmallVector<Path, 1> cxxStdlibDirs;
917-
std::error_code errorCode;
918-
for (llvm::vfs::directory_iterator
919-
iter = ctx.SourceMgr.getFileSystem()->dir_begin(cxxStdlibsRoot,
920-
errorCode),
921-
endIter;
922-
!errorCode && iter != endIter; iter = iter.increment(errorCode)) {
923-
cxxStdlibDirs.push_back(Path(iter->path()));
924-
}
925-
926-
SmallVector<std::pair<std::string, std::string>, 16> result;
927-
// Inject a modulemap into the VFS for each of the libstdc++ versions.
928-
for (const Path &cxxStdlibDir : cxxStdlibDirs) {
929-
// Only inject the module map if the module does not already exist at
930-
// {sysroot}/usr/include/module.{map,modulemap}.
931-
Path injectedModuleMapLegacyPath(cxxStdlibDir);
932-
llvm::sys::path::append(injectedModuleMapLegacyPath, "module.map");
933-
if (llvm::sys::fs::exists(injectedModuleMapLegacyPath))
934-
continue;
935-
936-
Path injectedModuleMapPath = cxxStdlibDir;
937-
llvm::sys::path::append(injectedModuleMapPath, "module.modulemap");
938-
if (llvm::sys::fs::exists(injectedModuleMapPath))
939-
continue;
925+
Path injectedModuleMapPath(cxxStdlibDir);
926+
llvm::sys::path::append(injectedModuleMapPath, "module.modulemap");
927+
if (llvm::sys::fs::exists(injectedModuleMapPath))
928+
return {};
940929

941-
Path injectedHeaderPath = cxxStdlibDir;
942-
llvm::sys::path::append(injectedHeaderPath, "libstdcxx.h");
930+
Path injectedHeaderPath(cxxStdlibDir);
931+
llvm::sys::path::append(injectedHeaderPath, "libstdcxx.h");
943932

944-
result.push_back(
945-
{std::string(injectedModuleMapPath), std::string(actualModuleMapPath)});
946-
result.push_back(
947-
{std::string(injectedHeaderPath), std::string(actualHeaderPath)});
948-
}
949-
return result;
933+
return {
934+
{std::string(injectedModuleMapPath), std::string(actualModuleMapPath)},
935+
{std::string(injectedHeaderPath), std::string(actualHeaderPath)},
936+
};
950937
}
951938

952939
bool ClangImporter::canReadPCH(StringRef PCHFilename) {

test/Interop/Cxx/stdlib/libstdcxx-module-interface.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99

1010
// This test is specific to libstdc++ and only runs on platforms where libstdc++ is used.
1111
// REQUIRES: OS=linux-gnu
12-
// REQUIRES: rdar93341210
1312

1413
// CHECK-STD: enum std {
1514
// CHECK-STRING: struct {{__CxxTemplateInstNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE|__CxxTemplateInstSs}} {

test/Interop/Cxx/stdlib/use-std-string.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
//
55
// Enable this everywhere once we have a solution for modularizing other C++ stdlibs: rdar://87654514
66
// REQUIRES: OS=macosx || OS=linux-gnu
7-
// REQUIRES: rdar93341210
87

98
import StdlibUnittest
109
import StdString

0 commit comments

Comments
 (0)