Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions tests/projects/c++/modules/test_base.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ MSVC_MIN_VER = "14.29"
function _build(check_outdata)
local flags = ""
if ci_is_running() then
flags = "-vD"
flags = "-vD"
end
if check_outdata then
local outdata
Expand Down Expand Up @@ -101,9 +101,12 @@ function build_tests(toolchain_name, opt)
if opt.flags then
flags = " " .. table.concat(opt.flags, " ")
end
if ci_is_running() then
flags = flags .. " -vD"
end

os.exec("xmake clean -a")
os.exec("xmake f" .. platform .. "--toolchain=" .. toolchain_name .. runtimes .. "-cD --yes " .. policies .. flags)
os.exec("xmake f" .. platform .. "--toolchain=" .. toolchain_name .. runtimes .. "-c --yes " .. policies .. flags)
if opt.build then
opt.build()
else
Expand Down
5 changes: 5 additions & 0 deletions tests/projects/c/llvm_compiler_rt/src/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
int main(int argc, char **argv) {
__int128 a = 123;
__int128 b = 1;
return a / b;
}
24 changes: 24 additions & 0 deletions tests/projects/c/llvm_compiler_rt/test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import("lib.detect.find_tool")
import("core.tool.toolchain")
import("utils.ci.is_running", {alias = "ci_is_running"})

function run_test(toolchain_name)
local flags = ""
if ci_is_running() then
flags = "-vD"
end

local llvm = toolchain.load("llvm")
if not llvm or not llvm:check() then
wprint("llvm not found, skipping tests")
return
end
os.exec("xmake clean -a")
os.exec("xmake f --toolchain=llvm -c --yes " .. flags)
os.run("xmake -r " .. flags)
end

function main(t)
run_test("llvm")
run_test("clang")
end
3 changes: 3 additions & 0 deletions tests/projects/c/llvm_compiler_rt/xmake.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
target("foo")
set_kind("binary")
add_files("src/main.c")
1 change: 1 addition & 0 deletions xmake/core/sandbox/modules/import/core/tool/toolchain.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ local raise = require("sandbox/modules/raise")
sandbox_core_tool_toolchain.apis = toolchain.apis
sandbox_core_tool_toolchain.directories = toolchain.directories
sandbox_core_tool_toolchain.save = toolchain.save
sandbox_core_tool_toolchain.memcache = toolchain.memcache
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need not to add it. only add a instace api. toolchain:memcache()

like this

function _instance:_memcache()


-- get all toolchains list
function sandbox_core_tool_toolchain.list()
Expand Down
12 changes: 6 additions & 6 deletions xmake/core/tool/toolchain.lua
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ function _instance:_checktool(toolkind, toolpath)

-- get result from cache first
local cachekey = self:cachekey() .. "_checktool" .. toolkind
local result = toolchain._memcache():get3(cachekey, toolkind, toolpath)
local result = toolchain.memcache():get3(cachekey, toolkind, toolpath)
if result then
return result[1], result[2]
end
Expand Down Expand Up @@ -552,12 +552,12 @@ function _instance:_checktool(toolkind, toolpath)
utils.cprint("${dim}checking for %s (%s: ${bright}%s${clear}) ... ${color.nothing}${text.nothing}", description, toolkind, toolpath)
end
end
toolchain._memcache():set3(cachekey, toolkind, toolpath, {program, toolname})
toolchain.memcache():set3(cachekey, toolkind, toolpath, {program, toolname})
return program, toolname
end

-- get memcache
function toolchain._memcache()
function toolchain.memcache()
return memcache.cache("core.tool.toolchain")
end

Expand Down Expand Up @@ -722,7 +722,7 @@ function toolchain.load(name, opt)
configs.arch = opt.arch or config.get("arch") or os.arch()

-- get cache
local cache = toolchain._memcache()
local cache = toolchain.memcache()
local cachekey = toolchain._cachekey(name, configs)

-- get it directly from cache dirst
Expand Down Expand Up @@ -787,7 +787,7 @@ function toolchain.load_withinfo(name, info, opt)
configs.arch = opt.arch or config.get("arch") or os.arch()

-- get cache key
local cache = toolchain._memcache()
local cache = toolchain.memcache()
local cachekey = toolchain._cachekey(name, configs)

-- get it directly from cache dirst
Expand Down Expand Up @@ -899,7 +899,7 @@ function toolchain.toolconfig(toolchains, name, opt)
local arch = opt.arch or config.get("arch") or os.arch()

-- get cache and cachekey
local cache = toolchain._memcache()
local cache = toolchain.memcache()
local cachekey = "toolconfig_" .. (opt.cachekey or "") .. "_" .. plat .. "_" .. arch

-- get configuration
Expand Down
111 changes: 42 additions & 69 deletions xmake/modules/core/tools/clang.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
-- inherit gcc
inherit("gcc")
import("core.language.language")
import("private.utils.toolchain", {alias = "toolchain_utils"})

-- init it
function init(self)
Expand Down Expand Up @@ -191,35 +192,6 @@ function _has_static_libstdcxx(self)
return has_static_libstdcxx
end

-- get llvm sdk root directory
function _get_llvm_rootdir(self)
local llvm_rootdir = _g._LLVM_ROOTDIR
if llvm_rootdir == nil then
local outdata = try { function() return os.iorunv(self:program(), {"-print-resource-dir"}, {envs = self:runenvs()}) end }
if outdata then
llvm_rootdir = path.normalize(path.join(outdata:trim(), "..", "..", ".."))
if not os.isdir(llvm_rootdir) then
llvm_rootdir = nil
end
end
_g._LLVM_ROOTDIR = llvm_rootdir or false
end
return llvm_rootdir or nil
end

-- get llvm target triple
function _get_llvm_target_triple(self)
local llvm_targettriple = _g._LLVM_TARGETTRIPLE
if llvm_targettriple == nil then
local outdata = try { function() return os.iorunv(self:program(), {"-print-target-triple"}, {envs = self:runenvs()}) end }
if outdata then
llvm_targettriple = outdata:trim()
end
_g._LLVM_TARGETTRIPLE = llvm_targettriple or false
end
return llvm_targettriple or nil
end

-- make the runtime flag
-- @see https://github.com/xmake-io/xmake/issues/3546
function nf_runtime(self, runtime, opt)
Expand Down Expand Up @@ -250,58 +222,59 @@ function nf_runtime(self, runtime, opt)
}
end
end
if not self:is_plat("android") then -- we will set runtimes in android ndk toolchain
local target = opt.target or opt
-- llvm on windows still doesn't support autolinking of libc++ and compiler-rt builtins
-- @see https://discourse.llvm.org/t/improve-autolinking-of-compiler-rt-and-libc-on-windows-with-lld-link/71392/10
-- and need manual setting of libc++ headerdirectory
-- @see https://github.com/llvm/llvm-project/issues/79647
local llvm_dirs = toolchain_utils.get_llvm_dirs(self:toolchain())
-- we will set runtimes in android ndk toolchain
if not self:is_plat("android") then
maps = maps or {}
local llvm_rootdir = self:toolchain():sdkdir()
if kind == "cxx" then
if kind == "cxx" or kind == "ld" or kind == "sh" then
maps["c++_static"] = "-stdlib=libc++"
maps["c++_shared"] = "-stdlib=libc++"
maps["stdc++_static"] = "-stdlib=libstdc++"
maps["stdc++_shared"] = "-stdlib=libstdc++"
if not llvm_rootdir and self:is_plat("windows") then
-- clang on windows fail to add libc++ includepath when using -stdlib=libc++ so we manually add it
if kind == "cxx" then
-- force the toolchain libc++ headers to prevent clang picking the systems one
-- @see https://github.com/llvm/llvm-project/issues/79647
llvm_rootdir = _get_llvm_rootdir(self)
if llvm_dirs.cxxinclude then
maps["c++_static"] = table.join(maps["c++_static"], "-cxx-isystem" .. llvm_dirs.cxxinclude)
maps["c++_shared"] = table.join(maps["c++_shared"], "-cxx-isystem" .. llvm_dirs.cxxinclude)
end
end
end

if self:is_plat("windows") and language.sourcekinds()[kind] then
-- on windows force link to compiler_rt builtins
if llvm_dirs.rt and llvm_dirs.rtlink then
for name, _ in pairs(maps) do
maps[name] = table.join({"-Xclang", "--dependent-lib=" .. llvm_dirs.rtlink}, maps[name])
end
end
if llvm_rootdir then
maps["c++_static"] = table.join(maps["c++_static"], "-cxx-isystem" .. path.join(llvm_rootdir, "include", "c++", "v1"))
maps["c++_shared"] = table.join(maps["c++_shared"], "-cxx-isystem" .. path.join(llvm_rootdir, "include", "c++", "v1"))
end
if kind == "ld" or kind == "sh" then
if self:is_plat("windows") and llvm_dirs.rt then
-- on windows force add compiler_rt link directories
for name, _ in pairs(maps) do
maps[name] = table.join(nf_linkdir(self, llvm_dirs.rt), maps[name])
maps[name] = table.join("-resource-dir=" .. llvm_dirs.res, maps[name])
end
end
elseif kind == "ld" or kind == "sh" then
local target = opt.target or opt
local is_cxx = target and (target.sourcekinds and table.contains(table.wrap(target:sourcekinds()), "cxx"))
if is_cxx then
maps["c++_static"] = "-stdlib=libc++"
maps["c++_shared"] = "-stdlib=libc++"
maps["stdc++_static"] = "-stdlib=libstdc++"
maps["stdc++_shared"] = "-stdlib=libstdc++"
if not llvm_rootdir and self:is_plat("windows") then
-- clang on windows fail to add libc++ librarypath when using -stdlib=libc++ so we manually add it
-- @see https://github.com/llvm/llvm-project/issues/79647
llvm_rootdir = _get_llvm_rootdir(self)
end
if llvm_rootdir then
local libdir = path.absolute(path.join(llvm_rootdir, "lib"))
maps["c++_static"] = table.join(maps["c++_static"], "-L" .. libdir)
maps["c++_shared"] = table.join(maps["c++_shared"], "-L" .. libdir)
if llvm_dirs.lib then
maps["c++_static"] = table.join(maps["c++_static"], nf_linkdir(self, llvm_dirs.lib))
maps["c++_shared"] = table.join(maps["c++_shared"], nf_linkdir(self, llvm_dirs.lib))

-- sometimes llvm c++ runtimes are located in c++ subfolder (e.g homebrew llvm)
local cxx_libdir = path.join(libdir, "c++")
if os.isdir(cxx_libdir) then
maps["c++_static"] = table.join(maps["c++_static"], "-L" .. cxx_libdir)
maps["c++_shared"] = table.join(maps["c++_shared"], "-L" .. cxx_libdir)
end
-- sometimes llvm runtimes are located in a target-triple subfolder
local target_triple = _get_llvm_target_triple(self)
local triple_libdir = (target_triple and os.isdir(path.join(libdir, target_triple))) and path.join(libdir, target_triple)
if triple_libdir then
maps["c++_static"] = table.join(maps["c++_static"], "-L" .. triple_libdir)
maps["c++_shared"] = table.join(maps["c++_shared"], "-L" .. triple_libdir)
end
-- add rpath to avoid the user need to set LD_LIBRARY_PATH by hand
maps["c++_shared"] = table.join(maps["c++_shared"], nf_rpathdir(self, libdir))
if triple_libdir then
maps["c++_shared"] = table.join(maps["c++_shared"], nf_rpathdir(self, triple_libdir))
if llvm_dirs.cxxlib then
maps["c++_static"] = table.join(maps["c++_static"], nf_linkdir(self, llvm_dirs.cxxlib))
maps["c++_shared"] = table.join(maps["c++_shared"], nf_linkdir(self, llvm_dirs.cxxlib))
end

-- add rpath to avoid the user need to set DYLD_LIBRARY_PATH by hand
if target.is_shared and target:is_shared() and target.filename and self:is_plat("macosx", "iphoneos", "watchos") then
maps["c++_shared"] = table.join(maps["c++_shared"], "-install_name")
maps["c++_shared"] = table.join(maps["c++_shared"], "@rpath/" .. target:filename())
Expand Down
Loading
Loading