|
21 | 21 | -- inherit gcc |
22 | 22 | inherit("gcc") |
23 | 23 | import("core.language.language") |
| 24 | +import("private.utils.toolchain", {alias = "toolchain_utils"}) |
24 | 25 |
|
25 | 26 | -- init it |
26 | 27 | function init(self) |
@@ -191,76 +192,6 @@ function _has_static_libstdcxx(self) |
191 | 192 | return has_static_libstdcxx |
192 | 193 | end |
193 | 194 |
|
194 | | --- get llvm sdk root directory |
195 | | -function _get_llvm_rootdir(self) |
196 | | - local llvm_rootdir = _g._LLVM_ROOTDIR |
197 | | - if llvm_rootdir == nil then |
198 | | - local outdata = try { function() return os.iorunv(self:program(), {"-print-resource-dir"}, {envs = self:runenvs()}) end } |
199 | | - if outdata then |
200 | | - llvm_rootdir = path.normalize(path.join(outdata:trim(), "..", "..", "..")) |
201 | | - if not os.isdir(llvm_rootdir) then |
202 | | - llvm_rootdir = nil |
203 | | - end |
204 | | - end |
205 | | - _g._LLVM_ROOTDIR = llvm_rootdir or false |
206 | | - end |
207 | | - return llvm_rootdir or nil |
208 | | -end |
209 | | - |
210 | | --- get llvm target triple |
211 | | -function _get_llvm_target_triple(self) |
212 | | - local llvm_targettriple = _g._LLVM_TARGETTRIPLE |
213 | | - if llvm_targettriple == nil then |
214 | | - local outdata = try { function() return os.iorunv(self:program(), {"-print-target-triple"}, {envs = self:runenvs()}) end } |
215 | | - if outdata then |
216 | | - llvm_targettriple = outdata:trim() |
217 | | - end |
218 | | - _g._LLVM_TARGETTRIPLE = llvm_targettriple or false |
219 | | - end |
220 | | - return llvm_targettriple or nil |
221 | | -end |
222 | | - |
223 | | --- find compiler-rt dir |
224 | | -function _get_llvm_compiler_rtdir(self, target, llvm_rootdir) |
225 | | - import("lib.detect.find_tool") |
226 | | - import("core.base.semver") |
227 | | - |
228 | | - local libdir = path.absolute(path.join(llvm_rootdir, "lib", "clang")) |
229 | | - local target_triple = _get_llvm_target_triple(self) |
230 | | - |
231 | | - local cc = target:tool("cc") |
232 | | - local cc_tool = find_tool(cc, {version = true}) |
233 | | - if cc_tool and cc_tool.version then |
234 | | - local version = semver.new(cc_tool.version):major() |
235 | | - local basedir = path.join(libdir, version, "lib") |
236 | | - |
237 | | - local compiler_rtdir |
238 | | - -- sometimes llvm is built with -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON, compiler_rt is located in a target-triple subfolder |
239 | | - local tripletdir = path.join(basedir, target_triple) |
240 | | - if os.isdir(tripletdir) then |
241 | | - compiler_rtdir = tripletdir |
242 | | - else |
243 | | - -- sometimes llvm is built with -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF, compiler_rt is located in a platform name subfolder |
244 | | - if target:is_plat("windows") then |
245 | | - compiler_rtdir = os.isdir(path.join(basedir, "windows")) and path.join(basedir, "windows") |
246 | | - elseif target:is_plat("linux") then |
247 | | - compiler_rtdir = os.isdir(path.join(basedir, "linux")) and path.join(basedir, "linux") |
248 | | - elseif target:is_plat("macosx") then |
249 | | - compiler_rtdir = os.isdir(path.join(basedir, "darwin")) and path.join(basedir, "darwin") |
250 | | - end |
251 | | - end |
252 | | - |
253 | | - if compiler_rtdir and target_triple then |
254 | | - local arch = target_triple:split("-")[1] |
255 | | - local compiler_rtlink = "clang_rt.builtins-" .. arch |
256 | | - if os.isfile(path.join(compiler_rtdir, compiler_rtlink .. ".lib")) then |
257 | | - return compiler_rtdir, path.join(compiler_rtdir, compiler_rtlink .. ".lib") |
258 | | - end |
259 | | - end |
260 | | - return compiler_rtdir |
261 | | - end |
262 | | -end |
263 | | - |
264 | 195 | -- make the runtime flag |
265 | 196 | -- @see https://github.com/xmake-io/xmake/issues/3546 |
266 | 197 | function nf_runtime(self, runtime, opt) |
@@ -291,58 +222,72 @@ function nf_runtime(self, runtime, opt) |
291 | 222 | } |
292 | 223 | end |
293 | 224 | end |
294 | | - if not self:is_plat("android") then -- we will set runtimes in android ndk toolchain |
295 | | - maps = maps or {} |
296 | | - local llvm_rootdir = self:toolchain():sdkdir() |
297 | | - if not llvm_rootdir and self:is_plat("windows") then |
298 | | - llvm_rootdir = _get_llvm_rootdir(self) |
| 225 | + local target = opt.target or opt |
| 226 | + -- llvm on windows still doesn't support autolinking of libc++ and compiler-rt builtins |
| 227 | + -- @see https://discourse.llvm.org/t/improve-autolinking-of-compiler-rt-and-libc-on-windows-with-lld-link/71392/10 |
| 228 | + -- and need manual setting of libc++ headerdirectory |
| 229 | + -- @see https://github.com/llvm/llvm-project/issues/79647 |
| 230 | + local llvm_dirs = toolchain_utils.get_llvm_dirs(self) |
| 231 | + |
| 232 | + if self:is_plat("windows") and runtime == "c++_shared" then |
| 233 | + if llvm_dirs.bin then |
| 234 | + self:add("runenvs", "PATHS", llvm_dirs.bin) |
299 | 235 | end |
300 | | - if kind == "cxx" then |
| 236 | + if llvm_dirs.rt then |
| 237 | + self:add("runenvs", "PATHS", llvm_dirs.rt) |
| 238 | + end |
| 239 | + end |
| 240 | + |
| 241 | + -- we will set runtimes in android ndk toolchain |
| 242 | + if not self:is_plat("android") then |
| 243 | + maps = maps or {} |
| 244 | + if kind == "cxx" or kind == "ld" or kind == "sh" then |
301 | 245 | maps["c++_static"] = "-stdlib=libc++" |
302 | 246 | maps["c++_shared"] = "-stdlib=libc++" |
303 | 247 | maps["stdc++_static"] = "-stdlib=libstdc++" |
304 | 248 | maps["stdc++_shared"] = "-stdlib=libstdc++" |
305 | | - -- clang on windows fail to add libc++ includepath when using -stdlib=libc++ so we manually add it |
306 | | - -- @see https://github.com/llvm/llvm-project/issues/79647 |
307 | | - if llvm_rootdir then |
308 | | - maps["c++_static"] = table.join(maps["c++_static"], "-cxx-isystem" .. path.join(llvm_rootdir, "include", "c++", "v1")) |
309 | | - maps["c++_shared"] = table.join(maps["c++_shared"], "-cxx-isystem" .. path.join(llvm_rootdir, "include", "c++", "v1")) |
| 249 | + if kind == "cxx" then |
| 250 | + -- force the toolchain libc++ headers to prevent clang picking the systems one |
| 251 | + if llvm_dirs.cxxinclude then |
| 252 | + maps["c++_static"] = table.join(maps["c++_static"], "-cxx-isystem" .. llvm_dirs.cxxinclude) |
| 253 | + maps["c++_shared"] = table.join(maps["c++_shared"], "-cxx-isystem" .. llvm_dirs.cxxinclude) |
| 254 | + end |
310 | 255 | end |
311 | | - elseif kind == "ld" or kind == "sh" then |
312 | | - local target = opt.target or opt |
313 | | - local is_cxx_or_c = target and (target.sourcekinds and table.contains(table.wrap(target:sourcekinds()), "cxx", "cc")) |
314 | | - if is_cxx_or_c then |
315 | | - maps["c++_static"] = "-stdlib=libc++" |
316 | | - maps["c++_shared"] = "-stdlib=libc++" |
317 | | - maps["stdc++_static"] = "-stdlib=libstdc++" |
318 | | - maps["stdc++_shared"] = "-stdlib=libstdc++" |
319 | | - -- clang on windows fail to add libc++ librarypath when using -stdlib=libc++ so we manually add it |
320 | | - -- @see https://github.com/llvm/llvm-project/issues/79647 |
321 | | - if llvm_rootdir then |
322 | | - local libdir = path.absolute(path.join(llvm_rootdir, "lib")) |
323 | | - maps["c++_static"] = table.join(maps["c++_static"], nf_linkdir(self, libdir)) |
324 | | - maps["c++_shared"] = table.join(maps["c++_shared"], nf_linkdir(self, libdir)) |
| 256 | + end |
| 257 | + |
| 258 | + if self:is_plat("windows") and language.sourcekinds()[kind] then |
| 259 | + -- on windows force link to compiler_rt builtins |
| 260 | + if llvm_dirs.rt and llvm_dirs.rtlink then |
| 261 | + for name, _ in pairs(maps) do |
| 262 | + maps[name] = table.join({"-Xclang", "--dependent-lib=" .. llvm_dirs.rtlink}, maps[name]) |
| 263 | + end |
| 264 | + end |
| 265 | + end |
| 266 | + if kind == "ld" or kind == "sh" then |
| 267 | + if self:is_plat("windows") and llvm_dirs.rt then |
| 268 | + -- on windows force add compiler_rt link directories |
| 269 | + for name, _ in pairs(maps) do |
| 270 | + maps[name] = table.join(nf_linkdir(self, llvm_dirs.rt), maps[name]) |
| 271 | + maps[name] = table.join("-resource-dir=" .. llvm_dirs.res, maps[name]) |
| 272 | + end |
| 273 | + end |
| 274 | + |
| 275 | + local is_cxx = target and (target.sourcekinds and table.contains(table.wrap(target:sourcekinds()), "cxx")) |
| 276 | + if is_cxx then |
| 277 | + if llvm_dirs.lib then |
| 278 | + maps["c++_static"] = table.join(maps["c++_static"], nf_linkdir(self, llvm_dirs.lib)) |
| 279 | + maps["c++_shared"] = table.join(maps["c++_shared"], nf_linkdir(self, llvm_dirs.lib)) |
| 280 | + maps["c++_shared"] = table.join(maps["c++_shared"], nf_rpathdir(self, llvm_dirs.lib)) |
325 | 281 | -- sometimes llvm c++ runtimes are located in c++ subfolder (e.g homebrew llvm) |
326 | | - local cxx_libdir = path.join(libdir, "c++") |
327 | | - if os.isdir(cxx_libdir) then |
328 | | - maps["c++_static"] = table.join(maps["c++_static"], nf_linkdir(self, cxx_libdir)) |
329 | | - maps["c++_shared"] = table.join(maps["c++_shared"], "-L" .. nf_linkdir(self, cxx_libdir)) |
| 282 | + if llvm_dirs.cxxlib then |
| 283 | + maps["c++_static"] = table.join(maps["c++_static"], nf_linkdir(self, llvm_dirs.cxxlib)) |
| 284 | + maps["c++_shared"] = table.join(maps["c++_shared"], nf_linkdir(self, llvm_dirs.cxxlib)) |
| 285 | + maps["c++_shared"] = table.join(maps["c++_shared"], nf_rpathdir(self, llvm_dirs.cxxlib)) |
330 | 286 | end |
331 | | - local compiler_rtdir, compiler_rtlink = _get_llvm_compiler_rtdir(self, target, llvm_rootdir) |
332 | | - if compiler_rtdir then |
333 | | - for name, _ in pairs(maps) do |
334 | | - maps[name] = table.join(nf_linkdir(self, compiler_rtdir), maps[name]) |
335 | | - if compiler_rtlink then |
336 | | - maps[name] = table.join(compiler_rtlink, maps[name]) |
337 | | - end |
338 | | - end |
| 287 | + if llvm_dirs.rt then |
| 288 | + maps["c++_shared"] = table.join(maps["c++_shared"], nf_rpathdir(self, llvm_dirs.rt)) |
339 | 289 | end |
340 | 290 | -- add rpath to avoid the user need to set LD_LIBRARY_PATH by hand |
341 | | - maps["c++_shared"] = table.join(maps["c++_shared"], nf_rpathdir(self, libdir)) |
342 | | - if compiler_rtdir then |
343 | | - maps["c++_shared"] = table.join(maps["c++_shared"], nf_rpathdir(self, compiler_rtdir)) |
344 | | - maps["MD"] = table.join(maps["MD"], nf_rpathdir(self, compiler_rtdir)) |
345 | | - end |
346 | 291 | if target.is_shared and target:is_shared() and target.filename and self:is_plat("macosx", "iphoneos", "watchos") then |
347 | 292 | maps["c++_shared"] = table.join(maps["c++_shared"], "-install_name") |
348 | 293 | maps["c++_shared"] = table.join(maps["c++_shared"], "@rpath/" .. target:filename()) |
|
0 commit comments