1Swiftpm may invoke clang, not clang++, to compile C++. Our cc-wrapper also
2doesn't pick up the arguments that enable C++ compilation in this case. Patch
3swiftpm to properly invoke clang++.
4
5--- a/Sources/Build/BuildPlan.swift
6+++ b/Sources/Build/BuildPlan.swift
7@@ -2089,7 +2089,7 @@ public class BuildPlan: SPMBuildCore.BuildPlan {
8 for target in dependencies.staticTargets {
9 if case let target as ClangTarget = target.underlyingTarget, target.isCXX {
10 if buildParameters.hostTriple.isDarwin() {
11- buildProduct.additionalFlags += ["-lc++"]
12+ buildProduct.additionalFlags += ["-lc++", "-lc++abi"]
13 } else if buildParameters.hostTriple.isWindows() {
14 // Don't link any C++ library.
15 } else {
16--- a/Sources/Build/LLBuildManifestBuilder.swift
17+++ b/Sources/Build/LLBuildManifestBuilder.swift
18@@ -786,7 +786,7 @@ extension LLBuildManifestBuilder {
19
20 args += ["-c", path.source.pathString, "-o", path.object.pathString]
21
22- let clangCompiler = try buildParameters.toolchain.getClangCompiler().pathString
23+ let clangCompiler = try buildParameters.toolchain.getClangCompiler(isCXX: isCXX).pathString
24 args.insert(clangCompiler, at: 0)
25
26 let objectFileNode: Node = .file(path.object)
27--- a/Sources/PackageModel/Toolchain.swift
28+++ b/Sources/PackageModel/Toolchain.swift
29@@ -23,7 +23,7 @@ public protocol Toolchain {
30 var macosSwiftStdlib: AbsolutePath { get throws }
31
32 /// Path of the `clang` compiler.
33- func getClangCompiler() throws -> AbsolutePath
34+ func getClangCompiler(isCXX: Bool) throws -> AbsolutePath
35
36 // FIXME: This is a temporary API until index store is widely available in
37 // the OSS clang compiler. This API should not used for any other purpose.
38--- a/Sources/PackageModel/UserToolchain.swift
39+++ b/Sources/PackageModel/UserToolchain.swift
40@@ -57,7 +57,7 @@ public final class UserToolchain: Toolchain {
41 /// Only use search paths, do not fall back to `xcrun`.
42 let useXcrun: Bool
43
44- private var _clangCompiler: AbsolutePath?
45+ private var _clangCompiler: [Bool: AbsolutePath] = [:]
46
47 private let environment: EnvironmentVariables
48
49@@ -196,29 +196,31 @@ public final class UserToolchain: Toolchain {
50 }
51
52 /// Returns the path to clang compiler tool.
53- public func getClangCompiler() throws -> AbsolutePath {
54+ public func getClangCompiler(isCXX: Bool) throws -> AbsolutePath {
55 // Check if we already computed.
56- if let clang = self._clangCompiler {
57+ if let clang = self._clangCompiler[isCXX] {
58 return clang
59 }
60
61 // Check in the environment variable first.
62- if let toolPath = UserToolchain.lookup(variable: "CC", searchPaths: self.envSearchPaths, environment: environment) {
63- self._clangCompiler = toolPath
64+ let envVar = isCXX ? "CXX" : "CC";
65+ if let toolPath = UserToolchain.lookup(variable: envVar, searchPaths: self.envSearchPaths, environment: environment) {
66+ self._clangCompiler[isCXX] = toolPath
67 return toolPath
68 }
69
70 // Then, check the toolchain.
71+ let tool = isCXX ? "clang++" : "clang";
72 do {
73- if let toolPath = try? UserToolchain.getTool("clang", binDir: self.destination.toolchainBinDir) {
74- self._clangCompiler = toolPath
75+ if let toolPath = try? UserToolchain.getTool(tool, binDir: self.destination.binDir) {
76+ self._clangCompiler[isCXX] = toolPath
77 return toolPath
78 }
79 }
80
81 // Otherwise, lookup it up on the system.
82- let toolPath = try UserToolchain.findTool("clang", envSearchPaths: self.envSearchPaths, useXcrun: useXcrun)
83- self._clangCompiler = toolPath
84+ let toolPath = try UserToolchain.findTool(tool, envSearchPaths: self.envSearchPaths, useXcrun: useXcrun)
85+ self._clangCompiler[isCXX] = toolPath
86 return toolPath
87 }
88
89--- a/Sources/SPMBuildCore/BuildParameters.swift
90+++ b/Sources/SPMBuildCore/BuildParameters.swift
91@@ -394,7 +394,7 @@ private struct _Toolchain: Encodable {
92 public func encode(to encoder: Encoder) throws {
93 var container = encoder.container(keyedBy: CodingKeys.self)
94 try container.encode(toolchain.swiftCompilerPath, forKey: .swiftCompiler)
95- try container.encode(toolchain.getClangCompiler(), forKey: .clangCompiler)
96+ try container.encode(toolchain.getClangCompiler(isCXX: false), forKey: .clangCompiler)
97
98 try container.encode(toolchain.extraFlags.cCompilerFlags, forKey: .extraCCFlags)
99 // Maintaining `extraCPPFlags` key for compatibility with older encoding.
100--- a/Sources/XCBuildSupport/XcodeBuildSystem.swift
101+++ b/Sources/XCBuildSupport/XcodeBuildSystem.swift
102@@ -182,7 +182,7 @@ public final class XcodeBuildSystem: SPMBuildCore.BuildSystem {
103 // Generate a table of any overriding build settings.
104 var settings: [String: String] = [:]
105 // An error with determining the override should not be fatal here.
106- settings["CC"] = try? buildParameters.toolchain.getClangCompiler().pathString
107+ settings["CC"] = try? buildParameters.toolchain.getClangCompiler(isCXX: false).pathString
108 // Always specify the path of the effective Swift compiler, which was determined in the same way as for the native build system.
109 settings["SWIFT_EXEC"] = buildParameters.toolchain.swiftCompilerPath.pathString
110 settings["LIBRARY_SEARCH_PATHS"] = "$(inherited) \(try buildParameters.toolchain.toolchainLibDir.pathString)"
111--- a/Tests/BuildTests/MockBuildTestHelper.swift
112+++ b/Tests/BuildTests/MockBuildTestHelper.swift
113@@ -23,7 +23,7 @@ struct MockToolchain: PackageModel.Toolchain {
114 #else
115 let extraFlags = BuildFlags(cxxCompilerFlags: ["-lstdc++"])
116 #endif
117- func getClangCompiler() throws -> AbsolutePath {
118+ func getClangCompiler(isCXX: Bool) throws -> AbsolutePath {
119 return AbsolutePath(path: "/fake/path/to/clang")
120 }
121