summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorruki <[email protected]>2021-11-24 00:56:24 +0800
committerruki <[email protected]>2021-11-24 00:56:24 +0800
commit12ee3ed6eb196f5d9e5cdeb619c40f51b2bec144 (patch)
tree15757810c3fb3f7d953d681c803236c770705921
parent499b857f587073a09145c44d4ab9c312afb9a69a (diff)
improve c++ modules
-rw-r--r--tests/projects/c++/modules/staticlib/xmake.lua2
-rw-r--r--xmake/rules/c++/modules/build_modules/clang.lua26
-rw-r--r--xmake/rules/c++/modules/build_modules/gcc.lua14
-rw-r--r--xmake/rules/c++/modules/build_modules/msvc.lua15
-rw-r--r--xmake/rules/c++/modules/xmake.lua34
5 files changed, 84 insertions, 7 deletions
diff --git a/tests/projects/c++/modules/staticlib/xmake.lua b/tests/projects/c++/modules/staticlib/xmake.lua
index 3aa743c64..93045c18f 100644
--- a/tests/projects/c++/modules/staticlib/xmake.lua
+++ b/tests/projects/c++/modules/staticlib/xmake.lua
@@ -1,7 +1,5 @@
set_languages("c++20")
-add_cxxflags("-fmodules-ts")
-
target("mod")
set_kind("static")
add_files("src/mod.mpp", "src/mod.cpp")
diff --git a/xmake/rules/c++/modules/build_modules/clang.lua b/xmake/rules/c++/modules/build_modules/clang.lua
index 06b5aa1db..523c61ad9 100644
--- a/xmake/rules/c++/modules/build_modules/clang.lua
+++ b/xmake/rules/c++/modules/build_modules/clang.lua
@@ -23,6 +23,32 @@ import("core.tool.compiler")
import("private.action.build.object", {alias = "objectbuilder"})
import("module_parser")
+-- load parent target with modules files
+function load_parent(target, opt)
+ -- get modules flag
+ local modulesflag
+ local compinst = compiler.load("cxx", {target = target})
+ if compinst:has_flags("-fmodules") then
+ modulesflag = "-fmodules"
+ elseif compinst:has_flags("-fmodules-ts") then
+ modulesflag = "-fmodules-ts"
+ end
+ assert(modulesflag, "compiler(clang): does not support c++ module!")
+
+ -- add module flags
+ target:add("cxxflags", modulesflag)
+
+ -- the module cache directory
+ for _, dep in ipairs(target:orderdeps()) do
+ local sourcebatches = dep:sourcebatches()
+ if sourcebatches and sourcebatches["c++.build.modules"] then
+ local cachedir = path.join(dep:autogendir(), "rules", "modules", "cache")
+ target:add("cxxflags", "-fmodules-cache-path=" .. cachedir, {force = true})
+ target:add("cxxflags", "-fimplicit-modules", "-fimplicit-module-maps", "-fprebuilt-module-path=" .. cachedir, {force = true})
+ end
+ end
+end
+
-- build module files
function build_with_batchjobs(target, batchjobs, sourcebatch, opt)
diff --git a/xmake/rules/c++/modules/build_modules/gcc.lua b/xmake/rules/c++/modules/build_modules/gcc.lua
index 1264f29c2..2abaa4f7f 100644
--- a/xmake/rules/c++/modules/build_modules/gcc.lua
+++ b/xmake/rules/c++/modules/build_modules/gcc.lua
@@ -23,6 +23,20 @@ import("core.tool.compiler")
import("private.action.build.object", {alias = "objectbuilder"})
import("module_parser")
+-- load parent target with modules files
+function load_parent(target, opt)
+ -- get modules flag
+ local modulesflag
+ local compinst = compiler.load("cxx", {target = target})
+ if compinst:has_flags("-fmodules-ts") then
+ modulesflag = "-fmodules-ts"
+ end
+ assert(modulesflag, "compiler(gcc): does not support c++ module!")
+
+ -- add module flags
+ target:add("cxxflags", modulesflag)
+end
+
-- build module files
function build_with_batchjobs(target, batchjobs, sourcebatch, opt)
diff --git a/xmake/rules/c++/modules/build_modules/msvc.lua b/xmake/rules/c++/modules/build_modules/msvc.lua
index 4606edb7e..4cc8500ab 100644
--- a/xmake/rules/c++/modules/build_modules/msvc.lua
+++ b/xmake/rules/c++/modules/build_modules/msvc.lua
@@ -23,6 +23,21 @@ import("core.tool.compiler")
import("private.action.build.object", {alias = "objectbuilder"})
import("module_parser")
+-- load parent target with modules files
+function load_parent(target, opt)
+
+ -- get modules flag
+ local modulesflag
+ local compinst = compiler.load("cxx", {target = target})
+ if compinst:has_flags("/experimental:module", "cxxflags") then
+ modulesflag = "/experimental:module"
+ end
+ assert(modulesflag, "compiler(msvc): does not support c++ module!")
+
+ -- add module flags
+ target:add("cxxflags", modulesflag)
+end
+
-- build module files
function build_with_batchjobs(target, batchjobs, sourcebatch, opt)
diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua
index 9018f5e2d..78f754521 100644
--- a/xmake/rules/c++/modules/xmake.lua
+++ b/xmake/rules/c++/modules/xmake.lua
@@ -21,12 +21,36 @@
-- define rule: c++.build.modules
rule("c++.build.modules")
set_extensions(".mpp", ".mxx", ".cppm", ".ixx")
- before_build_files(function (target, batchjobs, sourcebatch, opt)
+ after_load(function (target)
-- we disable to build across targets in parallel, because the source files may depend on other target modules
- -- @note we cannot set it in on_load, because it will affect all c++ projects
- target:set("policy", "build.across_targets_in_parallel", false)
-
- -- build module files with batchjobs
+ -- @see https://github.com/xmake-io/xmake/issues/1858
+ local target_with_modules
+ for _, dep in ipairs(target:orderdeps()) do
+ local sourcebatches = dep:sourcebatches()
+ if sourcebatches and sourcebatches["c++.build.modules"] then
+ target_with_modules = true
+ break
+ end
+ end
+ if target_with_modules then
+ -- @note this will cause cross-parallel builds to be disabled for all sub-dependent targets,
+ -- even if some sub-targets do not contain C++ modules.
+ --
+ -- maybe we will have a more fine-grained configuration strategy to disable it in the future.
+ target:set("policy", "build.across_targets_in_parallel", false)
+ local _, toolname = target:tool("cxx")
+ if toolname:find("clang", 1, true) then
+ import("build_modules.clang").load_parent(target, opt)
+ elseif toolname:find("gcc", 1, true) then
+ import("build_modules.gcc").load_parent(target, opt)
+ elseif toolname == "cl" then
+ import("build_modules.msvc").load_parent(target, opt)
+ else
+ raise("compiler(%s): does not support c++ module!", toolname)
+ end
+ end
+ end)
+ before_build_files(function (target, batchjobs, sourcebatch, opt)
local _, toolname = target:tool("cxx")
if toolname:find("clang", 1, true) then
import("build_modules.clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt)