diff --git a/pkgs/development/compilers/swift/compiler/default.nix b/pkgs/development/compilers/swift/compiler/default.nix index 222f8e6b1d6b..891e209dca4d 100644 --- a/pkgs/development/compilers/swift/compiler/default.nix +++ b/pkgs/development/compilers/swift/compiler/default.nix @@ -111,6 +111,18 @@ let "swift-remote-mirror-headers" ]; + clangForWrappers = clang.override (prev: { + extraBuildCommands = + prev.extraBuildCommands + # We need to use the resource directory corresponding to Swift’s + # version of Clang instead of passing along the one from the + # `cc-wrapper` flags. + + '' + substituteInPlace $out/nix-support/cc-cflags \ + --replace-fail " -resource-dir=$out/resource-root" "" + ''; + }); + # Build a tool used during the build to create a custom clang wrapper, with # which we wrap the clang produced by the swift build. # @@ -130,7 +142,7 @@ let unwrappedClang="$targetFile-unwrapped" mv "$targetFile" "$unwrappedClang" - sed < '${clang}/bin/clang' > "$targetFile" \ + sed < '${clangForWrappers}/bin/clang' > "$targetFile" \ -e 's|^\s*exec|exec -a "$0"|g' \ -e 's|^\[\[ "${clang.cc}/bin/clang" = \*++ ]]|[[ "$0" = *++ ]]|' \ -e "s|${clang.cc}/bin/clang|$unwrappedClang|g" \ @@ -146,13 +158,12 @@ let # executable uses $0 to detect what tool is called. wrapperParams = { inherit bintools; - default_cc_wrapper = clang; # Instead of `@out@` in the original. coreutils_bin = lib.getBin coreutils; gnugrep_bin = gnugrep; suffixSalt = lib.replaceStrings [ "-" "." ] [ "_" "_" ] targetPlatform.config; use_response_file_by_default = 1; swiftDriver = ""; - # NOTE: @prog@ needs to be filled elsewhere. + # NOTE: @cc_wrapper@ and @prog@ need to be filled elsewhere. }; swiftWrapper = runCommand "swift-wrapper.sh" wrapperParams '' # Make empty to avoid adding the SDK’s modules in the bootstrap wrapper. Otherwise, the SDK conflicts with the @@ -168,6 +179,7 @@ let mv "$targetFile" "$unwrappedSwift" sed < '${swiftWrapper}' > "$targetFile" \ -e "s|@prog@|'$unwrappedSwift'|g" \ + -e 's|@cc_wrapper@|${clangForWrappers}|g' \ -e 's|exec "$prog"|exec -a "$0" "$prog"|g' chmod a+x "$targetFile" ''; @@ -308,9 +320,12 @@ stdenv.mkDerivation { patch -p1 -d swift -i ${./patches/swift-cmake-3.25-compat.patch} patch -p1 -d swift -i ${./patches/swift-wrap.patch} - patch -p1 -d swift -i ${./patches/swift-nix-resource-root.patch} patch -p1 -d swift -i ${./patches/swift-linux-fix-libc-paths.patch} - patch -p1 -d swift -i ${./patches/swift-linux-fix-linking.patch} + patch -p1 -d swift -i ${ + replaceVars ./patches/swift-linux-fix-linking.patch { + inherit clang; + } + } patch -p1 -d swift -i ${./patches/swift-darwin-libcxx-flags.patch} patch -p1 -d swift -i ${ replaceVars ./patches/swift-darwin-plistbuddy-workaround.patch { @@ -507,6 +522,10 @@ stdenv.mkDerivation { " buildProject llvm llvm-project/llvm + # Ensure that the built Clang can find the runtime libraries by + # copying the symlinks from the main wrapper. + cp -P ${clang}/resource-root/{lib,share} $SWIFT_BUILD_ROOT/llvm/lib/clang/15.0.0/ + '' + lib.optionalString stdenv.hostPlatform.isDarwin '' # Add appleSwiftCore to the search paths. Adding the whole SDK results in build failures. @@ -714,14 +733,8 @@ stdenv.mkDerivation { ln -s $lib/lib/swift $out/lib/swift # Swift has a separate resource root from Clang, but locates the Clang - # resource root via subdir or symlink. Provide a default here, but we also - # patch Swift to prefer NIX_CC if set. - # - # NOTE: We don't symlink directly here, because that'd add a run-time dep - # on the full Clang compiler to every Swift executable. The copy here is - # just copying the 3 symlinks inside to smaller closures. - mkdir $lib/lib/swift/clang - cp -P ${clang}/resource-root/* $lib/lib/swift/clang/ + # resource root via subdir or symlink. + mv $SWIFT_BUILD_ROOT/llvm/lib/clang/15.0.0 $lib/lib/swift/clang ''; preFixup = lib.optionalString stdenv.hostPlatform.isLinux '' diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-linux-fix-linking.patch b/pkgs/development/compilers/swift/compiler/patches/swift-linux-fix-linking.patch index e09d5162a93a..c10b4038a9c4 100644 --- a/pkgs/development/compilers/swift/compiler/patches/swift-linux-fix-linking.patch +++ b/pkgs/development/compilers/swift/compiler/patches/swift-linux-fix-linking.patch @@ -1,21 +1,17 @@ +diff --git a/lib/Driver/ToolChains.cpp b/lib/Driver/ToolChains.cpp +index c0ee9217e8..bf7737d6fa 100644 --- a/lib/Driver/ToolChains.cpp +++ b/lib/Driver/ToolChains.cpp -@@ -1475,7 +1475,17 @@ const char *ToolChain::getClangLinkerDriver( - - // If there is a linker driver in the toolchain folder, use that instead. - if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {toolchainPath})) -- LinkerDriver = Args.MakeArgString(tool.get()); -+ return Args.MakeArgString(tool.get()); -+ } -+ -+ // For Nix, prefer linking using the wrapped system clang, instead of using -+ // the unwrapped clang packaged with swift. The latter is unable to link, but -+ // we still want to use it for other purposes (clang importer). -+ if (auto nixCC = llvm::sys::Process::GetEnv("NIX_CC")) { -+ llvm::SmallString<128> binDir(nixCC.getValue()); -+ llvm::sys::path::append(binDir, "bin"); -+ if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {binDir.str()})) -+ return Args.MakeArgString(tool.get()); +@@ -1489,6 +1489,12 @@ + LinkerDriver = Args.MakeArgString(tool.get()); } ++ // For Nix, prefer linking using the wrapped Nixpkgs clang, instead of using ++ // the unwrapped clang packaged with swift. The latter is unable to link, but ++ // we still want to use it for other purposes (clang importer). ++ if (auto tool = llvm::sys::findProgramByName(LinkerDriver, {"@clang@/bin"})) ++ return Args.MakeArgString(tool.get()); ++ return LinkerDriver; + } + diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-nix-resource-root.patch b/pkgs/development/compilers/swift/compiler/patches/swift-nix-resource-root.patch deleted file mode 100644 index b67286a5d1c3..000000000000 --- a/pkgs/development/compilers/swift/compiler/patches/swift-nix-resource-root.patch +++ /dev/null @@ -1,67 +0,0 @@ -Swift normally looks for the Clang resource dir in a subdir/symlink of its own -resource dir. We provide a symlink to the Swift build-time Clang as a default -there, but we also here patch two checks to try locate it via NIX_CC. - -The first (ClangImporter.cpp) happens when Swift code imports C modules. The -second (ToolChains.cpp) happens when Swift is used to link the final product. - ---- a/lib/ClangImporter/ClangImporter.cpp -+++ b/lib/ClangImporter/ClangImporter.cpp -@@ -73,6 +73,7 @@ - #include "llvm/Support/FileSystem.h" - #include "llvm/Support/Memory.h" - #include "llvm/Support/Path.h" -+#include "llvm/Support/Process.h" - #include "llvm/Support/VirtualFileSystem.h" - #include "llvm/Support/YAMLParser.h" - #include -@@ -786,6 +787,17 @@ importer::addCommonInvocationArguments( - - const std::string &overrideResourceDir = importerOpts.OverrideResourceDir; - if (overrideResourceDir.empty()) { -+ // Prefer the Clang resource directory from NIX_CC, to allow swapping in a -+ // different stdenv. -+ // TODO: Figure out how to provide a user override for this. Probably a -+ // niche use case, though, and for now a user can unset NIX_CC to work -+ // around it if necessary. -+ if (auto nixCC = llvm::sys::Process::GetEnv("NIX_CC")) { -+ llvm::SmallString<128> resourceDir(nixCC.getValue()); -+ llvm::sys::path::append(resourceDir, "resource-root"); -+ invocationArgStrs.push_back("-resource-dir"); -+ invocationArgStrs.push_back(std::string(resourceDir.str())); -+ } else { - llvm::SmallString<128> resourceDir(searchPathOpts.RuntimeResourcePath); - - // Adjust the path to refer to our copy of the Clang resource directory -@@ -801,6 +813,7 @@ importer::addCommonInvocationArguments( - // Set the Clang resource directory to the path we computed. - invocationArgStrs.push_back("-resource-dir"); - invocationArgStrs.push_back(std::string(resourceDir.str())); -+ } // nixCC - } else { - invocationArgStrs.push_back("-resource-dir"); - invocationArgStrs.push_back(overrideResourceDir); ---- a/lib/Driver/ToolChains.cpp -+++ b/lib/Driver/ToolChains.cpp -@@ -1393,10 +1393,20 @@ void ToolChain::getClangLibraryPath(const ArgList &Args, - SmallString<128> &LibPath) const { - const llvm::Triple &T = getTriple(); - -+ // Nix: We provide a `clang` symlink in the default Swift resource root, but -+ // prefer detecting the Clang resource root via NIX_CC, to allow swapping in -+ // a different stdenv. However, always honor a user-provided `-resource-dir`. -+ auto nixCC = llvm::sys::Process::GetEnv("NIX_CC"); -+ if (nixCC && !Args.hasArgNoClaim(options::OPT_resource_dir)) { -+ LibPath.assign(nixCC.getValue()); -+ llvm::sys::path::append(LibPath, "resource-root"); -+ } else { - getResourceDirPath(LibPath, Args, /*Shared=*/true); - // Remove platform name. - llvm::sys::path::remove_filename(LibPath); -- llvm::sys::path::append(LibPath, "clang", "lib", -+ llvm::sys::path::append(LibPath, "clang"); -+ } // nixCC -+ llvm::sys::path::append(LibPath, "lib", - T.isOSDarwin() ? "darwin" - : getPlatformNameForTriple(T)); - } diff --git a/pkgs/development/compilers/swift/swift-driver/default.nix b/pkgs/development/compilers/swift/swift-driver/default.nix index d84d5be2ca74..3da4e5bacdf9 100644 --- a/pkgs/development/compilers/swift/swift-driver/default.nix +++ b/pkgs/development/compilers/swift/swift-driver/default.nix @@ -10,6 +10,7 @@ XCTest, sqlite, ncurses, + clang, replaceVars, }: let @@ -40,9 +41,10 @@ stdenv.mkDerivation { ]; patches = [ - ./patches/nix-resource-root.patch ./patches/disable-catalyst.patch - ./patches/linux-fix-linking.patch + (replaceVars ./patches/linux-fix-linking.patch { + inherit clang; + }) # TODO: Replace with branch patch once merged: # https://github.com/apple/swift-driver/pull/1197 (fetchpatch { diff --git a/pkgs/development/compilers/swift/swift-driver/patches/linux-fix-linking.patch b/pkgs/development/compilers/swift/swift-driver/patches/linux-fix-linking.patch index 8f91b3a234b5..be4147d44f07 100644 --- a/pkgs/development/compilers/swift/swift-driver/patches/linux-fix-linking.patch +++ b/pkgs/development/compilers/swift/swift-driver/patches/linux-fix-linking.patch @@ -1,3 +1,5 @@ +diff --git a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift +index a4a735f498..381522cc1f 100644 --- a/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift +++ b/Sources/SwiftDriver/Jobs/GenericUnixToolchain+LinkerSupport.swift @@ -10,6 +10,7 @@ @@ -8,19 +10,17 @@ import SwiftOptions import func TSCBasic.lookupExecutablePath -@@ -120,7 +121,20 @@ extension GenericUnixToolchain { +@@ -120,7 +121,18 @@ // just using `clang` and avoid a dependency on the C++ runtime. let clangTool: Tool = parsedOptions.hasArgument(.enableExperimentalCxxInterop) ? .clangxx : .clang - var clangPath = try getToolPath(clangTool) + -+ // For Nix, prefer linking using the wrapped system clang, instead of using ++ // For Nix, prefer linking using the wrapped Nixpkgs clang, instead of using + // the unwrapped clang packaged with swift. The latter is unable to link, but + // we still want to use it for other purposes (clang importer). + var clangPath: AbsolutePath -+ let env = ProcessInfo.processInfo.environment -+ if let nixCC = env["NIX_CC"], -+ let binPath = try? AbsolutePath(validating: "\(nixCC)/bin"), ++ if let binPath = try? AbsolutePath(validating: "@clang@/bin"), + let tool = lookupExecutablePath(filename: parsedOptions.hasArgument(.enableExperimentalCxxInterop) + ? "clang++" : "clang", + searchPaths: [binPath]) { @@ -30,11 +30,11 @@ if let toolsDirPath = parsedOptions.getLastArgument(.toolsDirectory) { // FIXME: What if this isn't an absolute path? let toolsDir = try AbsolutePath(validating: toolsDirPath.asSingle) -@@ -136,6 +150,7 @@ extension GenericUnixToolchain { +@@ -136,6 +148,7 @@ commandLine.appendFlag("-B") commandLine.appendPath(toolsDir) } -+ } // nixCC ++ } // Nix // Executables on Linux get -pie if targetTriple.os == .linux && linkerOutputType == .executable { diff --git a/pkgs/development/compilers/swift/swift-driver/patches/nix-resource-root.patch b/pkgs/development/compilers/swift/swift-driver/patches/nix-resource-root.patch deleted file mode 100644 index 8c24db5aad1d..000000000000 --- a/pkgs/development/compilers/swift/swift-driver/patches/nix-resource-root.patch +++ /dev/null @@ -1,28 +0,0 @@ -Swift normally looks for the Clang resource dir in a subdir/symlink of its own -resource dir. We provide a symlink to the Swift build-time Clang as a default -there, but we also here patch a check to try locate it via NIX_CC. - ---- a/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift -+++ b/Sources/SwiftDriver/Jobs/Toolchain+LinkerSupport.swift -@@ -10,6 +10,7 @@ - // - //===----------------------------------------------------------------------===// - -+import Foundation - import SwiftOptions - - import protocol TSCBasic.FileSystem -@@ -26,6 +27,13 @@ extension Toolchain { - for targetInfo: FrontendTargetInfo, - parsedOptions: inout ParsedOptions - ) throws -> VirtualPath { -+ let env = ProcessInfo.processInfo.environment -+ if let nixCC = env["NIX_CC"] { -+ return try VirtualPath(path: nixCC) -+ .appending(components: "resource-root", "lib", -+ targetInfo.target.triple.platformName(conflatingDarwin: true)!) -+ } -+ - return VirtualPath.lookup(targetInfo.runtimeResourcePath.path) - .appending(components: "clang", "lib", - targetInfo.target.triple.platformName(conflatingDarwin: true)!) diff --git a/pkgs/development/compilers/swift/wrapper/default.nix b/pkgs/development/compilers/swift/wrapper/default.nix index b291426bc9e4..88bb9a3c2139 100644 --- a/pkgs/development/compilers/swift/wrapper/default.nix +++ b/pkgs/development/compilers/swift/wrapper/default.nix @@ -4,6 +4,7 @@ swift, useSwiftDriver ? true, swift-driver, + clang, }: stdenv.mkDerivation ( @@ -28,6 +29,20 @@ stdenv.mkDerivation ( swiftStaticLibSubdir ; swiftDriver = lib.optionalString useSwiftDriver "${swift-driver}/bin/swift-driver"; + cc_wrapper = clang.override (prev: { + extraBuildCommands = + prev.extraBuildCommands + # We need to use the resource directory corresponding to Swift’s + # version of Clang instead of passing along the one from the + # `cc-wrapper` flags. + + '' + rm -r $out/resource-root + substituteInPlace $out/nix-support/cc-cflags \ + --replace-fail \ + "-resource-dir=$out/resource-root" \ + "-resource-dir=${lib.getLib swift}/lib/swift/clang" + ''; + }); env.darwinMinVersion = lib.optionalString stdenv.targetPlatform.isDarwin ( stdenv.targetPlatform.darwinMinVersion diff --git a/pkgs/development/compilers/swift/wrapper/wrapper.sh b/pkgs/development/compilers/swift/wrapper/wrapper.sh index bb9c07a5b444..a0f706dfbe6c 100644 --- a/pkgs/development/compilers/swift/wrapper/wrapper.sh +++ b/pkgs/development/compilers/swift/wrapper/wrapper.sh @@ -8,7 +8,7 @@ if (( "${NIX_DEBUG:-0}" >= 7 )); then set -x fi -cc_wrapper="${NIX_CC:-@default_cc_wrapper@}" +cc_wrapper="@cc_wrapper@" source $cc_wrapper/nix-support/utils.bash