summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2022-11-04 22:44:52 +0800
committerGitHub <[email protected]>2022-11-04 22:44:52 +0800
commit6c819d681111add7afa70920b788d8d56f620d77 (patch)
tree9a7f2af95e6e16541fd05dc7dec3957f79df69b3
parent9fe1d17945bc670c0ec3b394c39e17e0cedb7b44 (diff)
parent0fdefd2f7280db640ed09df068e09f98649ce7ec (diff)
Merge pull request #3016 from xmake-io/module
Improve clang/gcc/msvc to better support std modules
-rw-r--r--tests/projects/c++/modules/stdmodules/.gitignore8
-rw-r--r--tests/projects/c++/modules/stdmodules/src/my_module.cpp9
-rw-r--r--tests/projects/c++/modules/stdmodules/src/my_module.mpp9
-rw-r--r--tests/projects/c++/modules/stdmodules/test/test.cpp13
-rw-r--r--tests/projects/c++/modules/stdmodules/xmake.lua13
-rw-r--r--xmake/core/tool/builder.lua66
-rw-r--r--xmake/rules/c++/modules/modules_support/clang.lua36
-rw-r--r--xmake/rules/c++/modules/modules_support/msvc.lua25
8 files changed, 149 insertions, 30 deletions
diff --git a/tests/projects/c++/modules/stdmodules/.gitignore b/tests/projects/c++/modules/stdmodules/.gitignore
new file mode 100644
index 000000000..152105761
--- /dev/null
+++ b/tests/projects/c++/modules/stdmodules/.gitignore
@@ -0,0 +1,8 @@
+# Xmake cache
+.xmake/
+build/
+
+# MacOS Cache
+.DS_Store
+
+
diff --git a/tests/projects/c++/modules/stdmodules/src/my_module.cpp b/tests/projects/c++/modules/stdmodules/src/my_module.cpp
new file mode 100644
index 000000000..5264da821
--- /dev/null
+++ b/tests/projects/c++/modules/stdmodules/src/my_module.cpp
@@ -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; }
diff --git a/tests/projects/c++/modules/stdmodules/src/my_module.mpp b/tests/projects/c++/modules/stdmodules/src/my_module.mpp
new file mode 100644
index 000000000..5c0e44bc9
--- /dev/null
+++ b/tests/projects/c++/modules/stdmodules/src/my_module.mpp
@@ -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;
diff --git a/tests/projects/c++/modules/stdmodules/test/test.cpp b/tests/projects/c++/modules/stdmodules/test/test.cpp
new file mode 100644
index 000000000..a12813c24
--- /dev/null
+++ b/tests/projects/c++/modules/stdmodules/test/test.cpp
@@ -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;
+}
diff --git a/tests/projects/c++/modules/stdmodules/xmake.lua b/tests/projects/c++/modules/stdmodules/xmake.lua
new file mode 100644
index 000000000..b3521e74b
--- /dev/null
+++ b/tests/projects/c++/modules/stdmodules/xmake.lua
@@ -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")
diff --git a/xmake/core/tool/builder.lua b/xmake/core/tool/builder.lua
index ff792325a..9fa225155 100644
--- a/xmake/core/tool/builder.lua
+++ b/xmake/core/tool/builder.lua
@@ -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]
@@ -76,9 +76,24 @@ 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")
@@ -86,7 +101,7 @@ function builder:_mapflags(flags, flagkind, target)
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
@@ -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
diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua
index 100830046..a3cf06e79 100644
--- a/xmake/rules/c++/modules/modules_support/clang.lua
+++ b/xmake/rules/c++/modules/modules_support/clang.lua
@@ -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
@@ -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
diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua
index 04ab2bf7a..b57ac4520 100644
--- a/xmake/rules/c++/modules/modules_support/msvc.lua
+++ b/xmake/rules/c++/modules/modules_support/msvc.lua
@@ -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