1Swift normally looks for the Clang resource dir in a subdir/symlink of its own
2resource dir. We provide a symlink to the Swift build-time Clang as a default
3there, but we also here patch two checks to try locate it via NIX_CC.
4
5The first (ClangImporter.cpp) happens when Swift code imports C modules. The
6second (ToolChains.cpp) happens when Swift is used to link the final product.
7
8--- a/lib/ClangImporter/ClangImporter.cpp
9+++ b/lib/ClangImporter/ClangImporter.cpp
10@@ -73,6 +73,7 @@
11 #include "llvm/Support/FileSystem.h"
12 #include "llvm/Support/Memory.h"
13 #include "llvm/Support/Path.h"
14+#include "llvm/Support/Process.h"
15 #include "llvm/Support/VirtualFileSystem.h"
16 #include "llvm/Support/YAMLParser.h"
17 #include <algorithm>
18@@ -786,6 +787,17 @@ importer::addCommonInvocationArguments(
19
20 const std::string &overrideResourceDir = importerOpts.OverrideResourceDir;
21 if (overrideResourceDir.empty()) {
22+ // Prefer the Clang resource directory from NIX_CC, to allow swapping in a
23+ // different stdenv.
24+ // TODO: Figure out how to provide a user override for this. Probably a
25+ // niche use case, though, and for now a user can unset NIX_CC to work
26+ // around it if necessary.
27+ if (auto nixCC = llvm::sys::Process::GetEnv("NIX_CC")) {
28+ llvm::SmallString<128> resourceDir(nixCC.getValue());
29+ llvm::sys::path::append(resourceDir, "resource-root");
30+ invocationArgStrs.push_back("-resource-dir");
31+ invocationArgStrs.push_back(std::string(resourceDir.str()));
32+ } else {
33 llvm::SmallString<128> resourceDir(searchPathOpts.RuntimeResourcePath);
34
35 // Adjust the path to refer to our copy of the Clang resource directory
36@@ -801,6 +813,7 @@ importer::addCommonInvocationArguments(
37 // Set the Clang resource directory to the path we computed.
38 invocationArgStrs.push_back("-resource-dir");
39 invocationArgStrs.push_back(std::string(resourceDir.str()));
40+ } // nixCC
41 } else {
42 invocationArgStrs.push_back("-resource-dir");
43 invocationArgStrs.push_back(overrideResourceDir);
44--- a/lib/Driver/ToolChains.cpp
45+++ b/lib/Driver/ToolChains.cpp
46@@ -1393,10 +1393,20 @@ void ToolChain::getClangLibraryPath(const ArgList &Args,
47 SmallString<128> &LibPath) const {
48 const llvm::Triple &T = getTriple();
49
50+ // Nix: We provide a `clang` symlink in the default Swift resource root, but
51+ // prefer detecting the Clang resource root via NIX_CC, to allow swapping in
52+ // a different stdenv. However, always honor a user-provided `-resource-dir`.
53+ auto nixCC = llvm::sys::Process::GetEnv("NIX_CC");
54+ if (nixCC && !Args.hasArgNoClaim(options::OPT_resource_dir)) {
55+ LibPath.assign(nixCC.getValue());
56+ llvm::sys::path::append(LibPath, "resource-root");
57+ } else {
58 getResourceDirPath(LibPath, Args, /*Shared=*/true);
59 // Remove platform name.
60 llvm::sys::path::remove_filename(LibPath);
61- llvm::sys::path::append(LibPath, "clang", "lib",
62+ llvm::sys::path::append(LibPath, "clang");
63+ } // nixCC
64+ llvm::sys::path::append(LibPath, "lib",
65 T.isOSDarwin() ? "darwin"
66 : getPlatformNameForTriple(T));
67 }