Skip to content

Commit 6c819d6

Browse files
authored
Merge pull request #3016 from xmake-io/module
Improve clang/gcc/msvc to better support std modules
2 parents 9fe1d17 + 0fdefd2 commit 6c819d6

File tree

8 files changed

+149
-30
lines changed

8 files changed

+149
-30
lines changed

Diff for: tests/projects/c++/modules/stdmodules/.gitignore

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Xmake cache
2+
.xmake/
3+
build/
4+
5+
# MacOS Cache
6+
.DS_Store
7+
8+
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
module my_module;
2+
3+
#ifdef _MSC_VER
4+
import std.core;
5+
#else
6+
import std;
7+
#endif
8+
9+
auto my_sum(size_t a, size_t b) -> size_t { return a + b; }
+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export module my_module;
2+
3+
#ifdef _MSC_VER
4+
import std.core;
5+
#else
6+
import std;
7+
#endif
8+
9+
export auto my_sum(size_t a, size_t b) -> size_t;

Diff for: tests/projects/c++/modules/stdmodules/test/test.cpp

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifdef _MSC_VER
2+
import std.core;
3+
#else
4+
import std;
5+
#endif
6+
7+
import my_module;
8+
9+
using namespace std;
10+
11+
int main(int argc, char** argv) {
12+
cout << my_sum(1, 1) << endl;
13+
}

Diff for: tests/projects/c++/modules/stdmodules/xmake.lua

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
add_rules("mode.debug", "mode.release")
2+
set_languages("c++20")
3+
4+
add_cxxflags("clang::-stdlib=libc++")
5+
set_values("msvc.modules.stdifcdir", true)
6+
target("mod")
7+
set_kind("shared")
8+
add_files("src/*.cpp", "src/*.mpp")
9+
10+
target("test")
11+
set_kind("binary")
12+
add_files("test/*.cpp")
13+
add_deps("mod")

Diff for: xmake/core/tool/builder.lua

+52-14
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ function builder:_targetkind()
4949
return self._TARGETKIND
5050
end
5151

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

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

79-
-- map gcc flags to the given builder flags
80-
function builder:_mapflags(flags, flagkind, target)
79+
-- map flag
80+
function builder:_mapflag(flag, flagkind, target)
81+
local mapflags = self:get("mapflags")
82+
local auto_map_flags = target and target.policy and target:policy("check.auto_map_flags")
83+
local auto_ignore_flags = target and target.policy and target:policy("check.auto_ignore_flags")
84+
if mapflags and (auto_map_flags ~= false) then
85+
return self:_mapflag_impl(flag, flagkind, mapflags, auto_ignore_flags)
86+
else
87+
if auto_ignore_flags == false or self:has_flags(flag, flagkind) then
88+
return flag
89+
else
90+
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)
91+
end
92+
end
93+
end
8194

95+
-- map flags
96+
function builder:_mapflags(flags, flagkind, target)
8297
local results = {}
8398
local mapflags = self:get("mapflags")
8499
local auto_map_flags = target and target.policy and target:policy("check.auto_map_flags")
85100
local auto_ignore_flags = target and target.policy and target:policy("check.auto_ignore_flags")
86101
flags = table.wrap(flags)
87102
if mapflags and (auto_map_flags ~= false) then
88103
for _, flag in pairs(flags) do
89-
local flag_mapped = self:_mapflag(flag, flagkind, mapflags, auto_ignore_flags)
104+
local flag_mapped = self:_mapflag_impl(flag, flagkind, mapflags, auto_ignore_flags)
90105
if flag_mapped then
91106
table.insert(results, flag_mapped)
92107
end
@@ -132,19 +147,42 @@ end
132147
function builder:_add_flags_from_flagkind(flags, target, flagkind, opt)
133148
local targetflags = target:get(flagkind, opt)
134149
local extraconf = target:extraconf(flagkind)
135-
if extraconf then
136-
for _, flag in ipairs(table.wrap(targetflags)) do
137-
-- @note we need join the single flag with shallow mode, aboid expand table values
138-
-- e.g. add_cflags({"-I", "/tmp/xxx foo"}, {force = true, expand = false})
139-
local flagconf = extraconf[flag]
140-
if flagconf and flagconf.force then
141-
table.shallow_join2(flags, flag)
150+
for _, flag in ipairs(table.wrap(targetflags)) do
151+
-- does this flag belong to this tool?
152+
-- @see https://github.com/xmake-io/xmake/issues/3022
153+
--
154+
-- e.g.
155+
-- for all: add_cxxflags("-g")
156+
-- only for clang: add_cxxflags("clang::-stdlib=libc++")
157+
-- only for clang and multiple flags: add_cxxflags("-stdlib=libc++", "-DFOO", {tools = "clang"})
158+
--
159+
local for_this_tool = true
160+
local flagconf = extraconf and extraconf[flag]
161+
if type(flag) == "string" and flag:find("::", 1, true) then
162+
for_this_tool = false
163+
local splitinfo = flag:split("::", {plain = true})
164+
local toolname = splitinfo[1]
165+
if toolname == self:name() then
166+
flag = splitinfo[2]
167+
for_this_tool = true
168+
end
169+
elseif flagconf and flagconf.tools then
170+
for_this_tool = table.contains(table.wrap(flagconf.tools), self:name())
171+
end
172+
173+
if for_this_tool then
174+
if extraconf then
175+
-- @note we need join the single flag with shallow mode, aboid expand table values
176+
-- e.g. add_cflags({"-I", "/tmp/xxx foo"}, {force = true, expand = false})
177+
if flagconf and flagconf.force then
178+
table.shallow_join2(flags, flag)
179+
else
180+
table.shallow_join2(flags, self:_mapflag(flag, flagkind, target))
181+
end
142182
else
143183
table.shallow_join2(flags, self:_mapflag(flag, flagkind, target))
144184
end
145185
end
146-
else
147-
table.join2(flags, self:_mapflags(targetflags, flagkind, target))
148186
end
149187
end
150188

Diff for: xmake/rules/c++/modules/modules_support/clang.lua

+30-6
Original file line numberDiff line numberDiff line change
@@ -66,21 +66,41 @@ end
6666

6767
-- load module support for the current target
6868
function load(target)
69-
-- get module and module cache flags
7069
local modulesflag = get_modulesflag(target)
7170
local builtinmodulemapflag = get_builtinmodulemapflag(target)
7271
local implicitmodulesflag = get_implicitmodulesflag(target)
73-
local noimplicitmodulemapsflag = get_noimplicitmodulemapsflag(target)
7472

7573
-- add module flags
7674
target:add("cxxflags", modulesflag)
77-
78-
-- add the module cache directory
7975
target:add("cxxflags", builtinmodulemapflag, {force = true})
8076
target:add("cxxflags", implicitmodulesflag, {force = true})
81-
target:add("cxxflags", noimplicitmodulemapsflag, {force = true})
8277

83-
target:data_set("cxx.modules.use_libc++", table.contains(target:get("cxxflags"), "-stdlib=libc++"))
78+
-- fix default visibility for functions and variables [-fvisibility] differs in PCH file vs. current file
79+
-- module.pcm cannot be loaded due to a configuration mismatch with the current compilation.
80+
--
81+
-- it will happen in binary target depend ont shared target with modules, and enable release mode at same time.
82+
local dep_symbols
83+
local has_shared_deps = false
84+
for _, dep in ipairs(target:orderdeps()) do
85+
if dep:is_shared() then
86+
dep_symbols = dep:get("symbols")
87+
has_shared_deps = true
88+
break
89+
end
90+
end
91+
if has_shared_deps then
92+
target:set("symbols", dep_symbols and dep_symbols or "none")
93+
end
94+
95+
-- if use libc++, we need install libc++ and libc++abi
96+
--
97+
-- on ubuntu:
98+
-- sudo apt install libc++-dev libc++abi-15-dev
99+
--
100+
target:data_set("cxx.modules.use_libc++", table.contains(target:get("cxxflags"), "-stdlib=libc++", "clang::-stdlib=libc++"))
101+
if target:data("cxx.modules.use_libc++") then
102+
target:add("syslinks", "c++")
103+
end
84104
end
85105

86106
-- get includedirs for stl headers
@@ -93,6 +113,10 @@ end
93113
function _get_toolchain_includedirs_for_stlheaders(includedirs, clang)
94114
local tmpfile = os.tmpfile() .. ".cc"
95115
io.writefile(tmpfile, "#include <vector>")
116+
local argv = {"-E", "-x", "c++", tmpfile}
117+
if target:data("cxx.modules.use_libc++") then
118+
table.insert(argv, 1, "-stdlib=libc++")
119+
end
96120
local result = try {function () return os.iorunv(clang, {"-E", "-x", "c++", tmpfile}) end}
97121
if result then
98122
for _, line in ipairs(result:split("\n", {plain = true})) do

Diff for: xmake/rules/c++/modules/modules_support/msvc.lua

+15-10
Original file line numberDiff line numberDiff line change
@@ -126,25 +126,30 @@ end
126126

127127
-- load module support for the current target
128128
function load(target)
129-
-- get flags
130-
local modulesflag = get_modulesflag(target)
131129

132130
-- add modules flags
131+
local modulesflag = get_modulesflag(target)
133132
target:add("cxxflags", modulesflag)
134133

135134
-- add stdifcdir in case of if the user ask for it
136-
if target:values("msvc.modules.stdifcdir") then
137-
local stdifcdirflag = get_stdifcdirflag(target)
138-
for _, toolchain_inst in ipairs(target:toolchains()) do
139-
if toolchain_inst:name() == "msvc" then
140-
local vcvars = toolchain_inst:config("vcvars")
141-
if vcvars.VCInstallDir and vcvars.VCToolsVersion then
142-
local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86")
135+
local stdifcdirflag = get_stdifcdirflag(target)
136+
if stdifcdirflag then
137+
local msvc = target:toolchain("msvc")
138+
if msvc then
139+
local vcvars = msvc:config("vcvars")
140+
if vcvars.VCInstallDir and vcvars.VCToolsVersion then
141+
local arch
142+
if target:is_arch("x64", "x86_64") then
143+
arch = "x64"
144+
elseif target:is_arch("x86", "i386") then
145+
arch = "x86"
146+
end
147+
if arch then
148+
local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", arch)
143149
if os.isdir(stdifcdir) then
144150
target:add("cxxflags", {stdifcdirflag, winos.short_path(stdifcdir)}, {force = true, expand = false})
145151
end
146152
end
147-
break
148153
end
149154
end
150155
end

0 commit comments

Comments
 (0)