Skip to content

Commit

Permalink
Merge pull request #3016 from xmake-io/module
Browse files Browse the repository at this point in the history
Improve clang/gcc/msvc to better support std modules
  • Loading branch information
waruqi committed Nov 4, 2022
2 parents 9fe1d17 + 0fdefd2 commit 6c819d6
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 30 deletions.
8 changes: 8 additions & 0 deletions tests/projects/c++/modules/stdmodules/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Xmake cache
.xmake/
build/

# MacOS Cache
.DS_Store


9 changes: 9 additions & 0 deletions tests/projects/c++/modules/stdmodules/src/my_module.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module my_module;

#ifdef _MSC_VER
import std.core;
#else
import std;
#endif

auto my_sum(size_t a, size_t b) -> size_t { return a + b; }
9 changes: 9 additions & 0 deletions tests/projects/c++/modules/stdmodules/src/my_module.mpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export module my_module;

#ifdef _MSC_VER
import std.core;
#else
import std;
#endif

export auto my_sum(size_t a, size_t b) -> size_t;
13 changes: 13 additions & 0 deletions tests/projects/c++/modules/stdmodules/test/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifdef _MSC_VER
import std.core;
#else
import std;
#endif

import my_module;

using namespace std;

int main(int argc, char** argv) {
cout << my_sum(1, 1) << endl;
}
13 changes: 13 additions & 0 deletions tests/projects/c++/modules/stdmodules/xmake.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
add_rules("mode.debug", "mode.release")
set_languages("c++20")

add_cxxflags("clang::-stdlib=libc++")
set_values("msvc.modules.stdifcdir", true)
target("mod")
set_kind("shared")
add_files("src/*.cpp", "src/*.mpp")

target("test")
set_kind("binary")
add_files("test/*.cpp")
add_deps("mod")
66 changes: 52 additions & 14 deletions xmake/core/tool/builder.lua
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ function builder:_targetkind()
return self._TARGETKIND
end

-- map gcc flag to the given builder flag
function builder:_mapflag(flag, flagkind, mapflags, auto_ignore_flags)
-- map flag implementation
function builder:_mapflag_impl(flag, flagkind, mapflags, auto_ignore_flags)

-- attempt to map it directly
local flag_mapped = mapflags[flag]
Expand All @@ -76,17 +76,32 @@ function builder:_mapflag(flag, flagkind, mapflags, auto_ignore_flags)
end
end

-- map gcc flags to the given builder flags
function builder:_mapflags(flags, flagkind, target)
-- map flag
function builder:_mapflag(flag, flagkind, target)
local mapflags = self:get("mapflags")
local auto_map_flags = target and target.policy and target:policy("check.auto_map_flags")
local auto_ignore_flags = target and target.policy and target:policy("check.auto_ignore_flags")
if mapflags and (auto_map_flags ~= false) then
return self:_mapflag_impl(flag, flagkind, mapflags, auto_ignore_flags)
else
if auto_ignore_flags == false or self:has_flags(flag, flagkind) then
return flag
else
utils.warning("add_%s(\"%s\") is ignored, please pass `{force = true}` or call `set_policy(\"check.auto_ignore_flags\", false)` if you want to set it.", flagkind, flag)
end
end
end

-- map flags
function builder:_mapflags(flags, flagkind, target)
local results = {}
local mapflags = self:get("mapflags")
local auto_map_flags = target and target.policy and target:policy("check.auto_map_flags")
local auto_ignore_flags = target and target.policy and target:policy("check.auto_ignore_flags")
flags = table.wrap(flags)
if mapflags and (auto_map_flags ~= false) then
for _, flag in pairs(flags) do
local flag_mapped = self:_mapflag(flag, flagkind, mapflags, auto_ignore_flags)
local flag_mapped = self:_mapflag_impl(flag, flagkind, mapflags, auto_ignore_flags)
if flag_mapped then
table.insert(results, flag_mapped)
end
Expand Down Expand Up @@ -132,19 +147,42 @@ end
function builder:_add_flags_from_flagkind(flags, target, flagkind, opt)
local targetflags = target:get(flagkind, opt)
local extraconf = target:extraconf(flagkind)
if extraconf then
for _, flag in ipairs(table.wrap(targetflags)) do
-- @note we need join the single flag with shallow mode, aboid expand table values
-- e.g. add_cflags({"-I", "/tmp/xxx foo"}, {force = true, expand = false})
local flagconf = extraconf[flag]
if flagconf and flagconf.force then
table.shallow_join2(flags, flag)
for _, flag in ipairs(table.wrap(targetflags)) do
-- does this flag belong to this tool?
-- @see https://github.com/xmake-io/xmake/issues/3022
--
-- e.g.
-- for all: add_cxxflags("-g")
-- only for clang: add_cxxflags("clang::-stdlib=libc++")
-- only for clang and multiple flags: add_cxxflags("-stdlib=libc++", "-DFOO", {tools = "clang"})
--
local for_this_tool = true
local flagconf = extraconf and extraconf[flag]
if type(flag) == "string" and flag:find("::", 1, true) then
for_this_tool = false
local splitinfo = flag:split("::", {plain = true})
local toolname = splitinfo[1]
if toolname == self:name() then
flag = splitinfo[2]
for_this_tool = true
end
elseif flagconf and flagconf.tools then
for_this_tool = table.contains(table.wrap(flagconf.tools), self:name())
end

if for_this_tool then
if extraconf then
-- @note we need join the single flag with shallow mode, aboid expand table values
-- e.g. add_cflags({"-I", "/tmp/xxx foo"}, {force = true, expand = false})
if flagconf and flagconf.force then
table.shallow_join2(flags, flag)
else
table.shallow_join2(flags, self:_mapflag(flag, flagkind, target))
end
else
table.shallow_join2(flags, self:_mapflag(flag, flagkind, target))
end
end
else
table.join2(flags, self:_mapflags(targetflags, flagkind, target))
end
end

Expand Down
36 changes: 30 additions & 6 deletions xmake/rules/c++/modules/modules_support/clang.lua
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,41 @@ end

-- load module support for the current target
function load(target)
-- get module and module cache flags
local modulesflag = get_modulesflag(target)
local builtinmodulemapflag = get_builtinmodulemapflag(target)
local implicitmodulesflag = get_implicitmodulesflag(target)
local noimplicitmodulemapsflag = get_noimplicitmodulemapsflag(target)

-- add module flags
target:add("cxxflags", modulesflag)

-- add the module cache directory
target:add("cxxflags", builtinmodulemapflag, {force = true})
target:add("cxxflags", implicitmodulesflag, {force = true})
target:add("cxxflags", noimplicitmodulemapsflag, {force = true})

target:data_set("cxx.modules.use_libc++", table.contains(target:get("cxxflags"), "-stdlib=libc++"))
-- fix default visibility for functions and variables [-fvisibility] differs in PCH file vs. current file
-- module.pcm cannot be loaded due to a configuration mismatch with the current compilation.
--
-- it will happen in binary target depend ont shared target with modules, and enable release mode at same time.
local dep_symbols
local has_shared_deps = false
for _, dep in ipairs(target:orderdeps()) do
if dep:is_shared() then
dep_symbols = dep:get("symbols")
has_shared_deps = true
break
end
end
if has_shared_deps then
target:set("symbols", dep_symbols and dep_symbols or "none")
end

-- if use libc++, we need install libc++ and libc++abi
--
-- on ubuntu:
-- sudo apt install libc++-dev libc++abi-15-dev
--
target:data_set("cxx.modules.use_libc++", table.contains(target:get("cxxflags"), "-stdlib=libc++", "clang::-stdlib=libc++"))
if target:data("cxx.modules.use_libc++") then
target:add("syslinks", "c++")
end
end

-- get includedirs for stl headers
Expand All @@ -93,6 +113,10 @@ end
function _get_toolchain_includedirs_for_stlheaders(includedirs, clang)
local tmpfile = os.tmpfile() .. ".cc"
io.writefile(tmpfile, "#include <vector>")
local argv = {"-E", "-x", "c++", tmpfile}
if target:data("cxx.modules.use_libc++") then
table.insert(argv, 1, "-stdlib=libc++")
end
local result = try {function () return os.iorunv(clang, {"-E", "-x", "c++", tmpfile}) end}
if result then
for _, line in ipairs(result:split("\n", {plain = true})) do
Expand Down
25 changes: 15 additions & 10 deletions xmake/rules/c++/modules/modules_support/msvc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -126,25 +126,30 @@ end

-- load module support for the current target
function load(target)
-- get flags
local modulesflag = get_modulesflag(target)

-- add modules flags
local modulesflag = get_modulesflag(target)
target:add("cxxflags", modulesflag)

-- add stdifcdir in case of if the user ask for it
if target:values("msvc.modules.stdifcdir") then
local stdifcdirflag = get_stdifcdirflag(target)
for _, toolchain_inst in ipairs(target:toolchains()) do
if toolchain_inst:name() == "msvc" then
local vcvars = toolchain_inst:config("vcvars")
if vcvars.VCInstallDir and vcvars.VCToolsVersion then
local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86")
local stdifcdirflag = get_stdifcdirflag(target)
if stdifcdirflag then
local msvc = target:toolchain("msvc")
if msvc then
local vcvars = msvc:config("vcvars")
if vcvars.VCInstallDir and vcvars.VCToolsVersion then
local arch
if target:is_arch("x64", "x86_64") then
arch = "x64"
elseif target:is_arch("x86", "i386") then
arch = "x86"
end
if arch then
local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", arch)
if os.isdir(stdifcdir) then
target:add("cxxflags", {stdifcdirflag, winos.short_path(stdifcdir)}, {force = true, expand = false})
end
end
break
end
end
end
Expand Down

0 comments on commit 6c819d6

Please sign in to comment.