summaryrefslogtreecommitdiff
path: root/xmake/modules/core
diff options
context:
space:
mode:
authorruki <[email protected]>2026-08-06 23:35:52 +0800
committerruki <[email protected]>2026-08-06 23:35:52 +0800
commite129ec374599dfddb45f1a157a64f7330f9a6124 (patch)
treeddc29d9843ff25848087bc569a7dc3982f498edb /xmake/modules/core
parent1bd903ce8eb567ddb1847c119e21665255c879bb (diff)
improve libc++ links
Diffstat (limited to 'xmake/modules/core')
-rw-r--r--xmake/modules/core/tools/clang.lua46
1 files changed, 17 insertions, 29 deletions
diff --git a/xmake/modules/core/tools/clang.lua b/xmake/modules/core/tools/clang.lua
index a79e67142..c264f6656 100644
--- a/xmake/modules/core/tools/clang.lua
+++ b/xmake/modules/core/tools/clang.lua
@@ -205,27 +205,6 @@ function _has_nostdlibxx(self)
return has_nostdlibxx
end
--- find the static libc++.a / libc++abi.a archives under the llvm library dirs
-function _get_static_cxxlibs(llvm_dirs)
- local libdirs = {}
- if llvm_dirs.cxxlibdir then
- table.insert(libdirs, llvm_dirs.cxxlibdir)
- end
- if llvm_dirs.libdir then
- table.insert(libdirs, llvm_dirs.libdir)
- end
- local libcxx, libcxxabi
- for _, dir in ipairs(libdirs) do
- if not libcxx and os.isfile(path.join(dir, "libc++.a")) then
- libcxx = path.join(dir, "libc++.a")
- end
- if not libcxxabi and os.isfile(path.join(dir, "libc++abi.a")) then
- libcxxabi = path.join(dir, "libc++abi.a")
- end
- end
- return libcxx, libcxxabi
-end
-
-- make the runtime flag
-- @see https://github.com/xmake-io/xmake/issues/3546
function nf_runtime(self, runtime, opt)
@@ -319,20 +298,29 @@ function nf_runtime(self, runtime, opt)
end
end
if runtime:endswith("_static") then
- -- -static-libstdc++ only pulls in libc++.a, not libc++abi.a, so libc++abi
+ -- -static-libstdc++ only pulls in libc++.a, not libc++abi.a, so the libc++abi
-- symbols (typeinfo, __cxa_*) stay undefined and the link fails, especially
-- once c++ modules reference more of libc++.
--
- -- if we can locate both static archives, link them explicitly in the correct
- -- order (libc++.a before libc++abi.a) and disable the driver's automatic c++
- -- runtime with -nostdlib++, otherwise fall back to -static-libstdc++.
+ -- if we can locate both static archives, link them explicitly in a group
+ -- (they reference each other) and disable the driver's automatic c++ runtime
+ -- with -nostdlib++, otherwise (bundled abi) fall back to -static-libstdc++.
--
-- note: target.runtimes is ordered right before the syslinks in the c++ link
-- order, so these archives are placed after the object files / user links.
- -- @see https://github.com/xmake-io/xmake/issues/7442
- local libcxx, libcxxabi = _get_static_cxxlibs(llvm_dirs)
- if libcxx and libcxxabi and _has_nostdlibxx(self) then
- maps["c++_static"] = table.join(maps["c++_static"], "-nostdlib++", libcxx, libcxxabi)
+ -- @see https://github.com/xmake-io/xmake/issues/7442, https://github.com/xmake-io/xmake/issues/7656
+ if llvm_dirs.libcxx_static and llvm_dirs.libcxxabi_static and _has_nostdlibxx(self) then
+ local cxxlibs = {llvm_dirs.libcxx_static, llvm_dirs.libcxxabi_static}
+ -- apple ld64 does not support --start-group, it always rescans archives
+ if not self:is_plat("macosx", "iphoneos", "watchos", "appletvos", "applexros") then
+ cxxlibs = table.join("-Wl,--start-group", cxxlibs, "-Wl,--end-group")
+ end
+ -- -stdlib=libc++ is unused when linking with -nostdlib++, remove it to avoid
+ -- the `argument unused during compilation` warning
+ local ldflags = table.remove_if(table.wrap(maps["c++_static"]), function (_, flag)
+ return flag == "-stdlib=libc++"
+ end)
+ maps["c++_static"] = table.join(ldflags, "-nostdlib++", cxxlibs)
elseif _has_static_libstdcxx(self) then
maps["c++_static"] = table.join(maps["c++_static"], "-static-libstdc++")
end