projects/guix·blob python-team · refs

116 lines · 5.0 KiB

1Author: Danny Milosavljevic <[email protected]>
2Date: 2025-10-20
3Subject: Make clang importer heed CPLUS_INCLUDE_PATH
4
5--- a/include/swift/ClangImporter/ClangImporter.h 1970-01-01 00:00:01.000000000 +0000
6+++ b/include/swift/ClangImporter/ClangImporter.h 2025-10-21 14:31:53.328441417 +0000
7@@ -787,6 +787,9 @@
8 SmallVector<std::pair<std::string, std::string>, 1> overridenFiles;
9
10 bool requiresBuiltinHeadersInSystemModules;
11+
12+ /// Extra arguments to pass to the Clang invocation (e.g., -isystem paths).
13+ std::vector<std::string> extraArgs;
14 };
15
16 /// On Linux, some platform libraries (glibc, libstdc++) are not modularized.
17--- a/lib/ClangImporter/ClangImporter.cpp 1970-01-01 00:00:01.000000000 +0000
18+++ b/lib/ClangImporter/ClangImporter.cpp 2025-10-21 14:34:20.744234737 +0000
19@@ -1326,6 +1326,12 @@
20 importer->requiresBuiltinHeadersInSystemModules =
21 fileMapping.requiresBuiltinHeadersInSystemModules;
22
23+ // Add extra arguments from file mapping (e.g., C++ stdlib include paths).
24+ ctx.ClangImporterOpts.ExtraArgs.insert(
25+ ctx.ClangImporterOpts.ExtraArgs.end(),
26+ fileMapping.extraArgs.begin(),
27+ fileMapping.extraArgs.end());
28+
29 // Create a new Clang compiler invocation.
30 {
31 if (auto ClangArgs = importer->getClangCC1Arguments(ctx, VFS))
32--- a/lib/ClangImporter/ClangIncludePaths.cpp 1970-01-01 00:00:01.000000000 +0000
33+++ b/lib/ClangImporter/ClangIncludePaths.cpp 2025-10-21 14:32:26.864394627 +0000
34@@ -21,6 +21,7 @@
35 #include "clang/Driver/ToolChain.h"
36 #include "clang/Frontend/CompilerInstance.h"
37 #include "llvm/WindowsDriver/MSVCPaths.h"
38+#include <cstdlib>
39
40 using namespace swift;
41
42@@ -306,9 +307,71 @@
43 {"cstdlib", "string", "vector"}, vfs)) {
44 cxxStdlibDir = dir.value();
45 } else {
46- if (!suppressDiagnostic)
47- ctx.Diags.diagnose(SourceLoc(), diag::libstdcxx_not_found, triple.str());
48- return;
49+ // FALLBACK: Try reading CPLUS_INCLUDE_PATH from environment.
50+ // This is needed because Swift doesn't go through the full clang driver
51+ // command construction that processes environment variables into -cxx-isystem
52+ // arguments. When AddClangCXXStdlibIncludeArgs fails to find GCC (e.g., due
53+ // to --gcc-toolchain pointing to wrong location or GCC detection failing),
54+ // parsedStdlibArgs will be empty and findFirstIncludeDir returns nullopt.
55+ // In Guix, CPLUS_INCLUDE_PATH is set by the build environment.
56+ const char *cplusIncludePath = std::getenv("CPLUS_INCLUDE_PATH");
57+ if (cplusIncludePath) {
58+ llvm::SmallVector<llvm::StringRef, 8> envPaths;
59+ llvm::StringRef(cplusIncludePath).split(envPaths, ':', -1, false);
60+
61+ for (const auto &envPath : envPaths) {
62+ Path dir(envPath.str());
63+ // Check if this directory contains C++ stdlib headers
64+ Path testFile(dir);
65+ llvm::sys::path::append(testFile, "cstdlib");
66+ if (vfs->exists(testFile)) {
67+ llvm::sys::path::remove_dots(dir, /*remove_dot_dot=*/true);
68+ cxxStdlibDir = dir;
69+ break;
70+ }
71+ }
72+ }
73+
74+ if (cxxStdlibDir.empty()) {
75+ if (!suppressDiagnostic)
76+ ctx.Diags.diagnose(SourceLoc(), diag::libstdcxx_not_found, triple.str());
77+ return;
78+ }
79+ }
80+
81+ // ADD INCLUDE PATHS FOR ARCH-SPECIFIC HEADERS:
82+ // GCC's libstdc++ has architecture-specific headers in subdirectories.
83+ // Standard clang driver adds THREE separate -internal-isystem include paths:
84+ // 1. /path/to/gcc/include/c++ (base: cstdlib, string, vector, etc.)
85+ // 2. /path/to/gcc/include/c++/TRIPLE (arch: bits/c++config.h, ext/*, etc.)
86+ // 3. /path/to/gcc/include/c++/backward (backward compatibility headers)
87+ // This allows clang to find both generic headers (cstddef) and arch-specific
88+ // headers (bits/c++config.h) in their respective directories.
89+ //
90+ // We add these three paths as -isystem arguments via fileMapping.extraArgs.
91+ // This is equivalent to what clang's AddClangCXXStdlibIncludeArgs does when
92+ // it calls addSystemInclude three times in Gnu.cpp:addLibStdCXXIncludePaths.
93+ // Using -isystem instead of VFS redirects ensures error messages reference
94+ // real filesystem paths that users can verify exist.
95+
96+ // 1. Base directory (already found above in cxxStdlibDir)
97+ fileMapping.extraArgs.push_back("-isystem");
98+ fileMapping.extraArgs.push_back(std::string(cxxStdlibDir));
99+
100+ // 2. Architecture-specific subdirectory (e.g., x86_64-unknown-linux-gnu)
101+ Path archSpecificDir(cxxStdlibDir);
102+ llvm::sys::path::append(archSpecificDir, triple.str());
103+ if (vfs->exists(archSpecificDir)) {
104+ fileMapping.extraArgs.push_back("-isystem");
105+ fileMapping.extraArgs.push_back(std::string(archSpecificDir));
106+ }
107+
108+ // 3. Backward compatibility directory
109+ Path backwardDir(cxxStdlibDir);
110+ llvm::sys::path::append(backwardDir, "backward");
111+ if (vfs->exists(backwardDir)) {
112+ fileMapping.extraArgs.push_back("-isystem");
113+ fileMapping.extraArgs.push_back(std::string(backwardDir));
114 }
115
116 Path actualModuleMapPath;