summaryrefslogtreecommitdiff
path: root/xmake/rules/c++/modules/xmake.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2022-08-16 12:33:47 +0800
committerGitHub <[email protected]>2022-08-16 12:33:47 +0800
commit81aca6fbe9149b377cdd88e8ee4b8f045d5a46da (patch)
tree0f138f960ab9fd95265ecbffca7c6ae27d65f4a3 /xmake/rules/c++/modules/xmake.lua
parentd46b16f8c40493bfc78764931bf7c3209442696b (diff)
parentd9f82e1bba29adc8b11dc1f7b3887717f03137d6 (diff)
Merge pull request #2641 from xmake-io/cxxmodules
Improve C++20 modules support
Diffstat (limited to 'xmake/rules/c++/modules/xmake.lua')
-rw-r--r--xmake/rules/c++/modules/xmake.lua129
1 files changed, 101 insertions, 28 deletions
diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua
index 12132da54..3ef960d7a 100644
--- a/xmake/rules/c++/modules/xmake.lua
+++ b/xmake/rules/c++/modules/xmake.lua
@@ -21,45 +21,118 @@
-- define rule: c++.build.modules
rule("c++.build.modules")
set_extensions(".mpp", ".mxx", ".cppm", ".ixx")
+ add_deps("c++.build.modules.builder")
+ add_deps("c++.build.modules.install")
+
on_config(function (target)
+ import("modules_support.common")
+
-- we disable to build across targets in parallel, because the source files may depend on other target modules
-- @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
+ if common.contains_modules(target) 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)
- if target:has_tool("cxx", "clang", "clangxx") then
- import("build_modules.clang").load_parent(target, opt)
- elseif target:has_tool("cxx", "gcc", "gxx") then
- import("build_modules.gcc").load_parent(target, opt)
- elseif target:has_tool("cxx", "cl") then
- import("build_modules.msvc").load_parent(target, opt)
- else
- local _, toolname = target:tool("cxx")
- raise("compiler(%s): does not support c++ module!", toolname)
- end
+
+ -- get modules support
+ local modules_support = common.modules_support(target)
+
+ -- load module support
+ modules_support.load(target)
+
+ -- mark this target with modules
+ target:data_set("cxx.has_modules", true)
end
end)
- before_build_files(function (target, batchjobs, sourcebatch, opt)
- if target:has_tool("cxx", "clang", "clangxx") then
- import("build_modules.clang").build_with_batchjobs(target, batchjobs, sourcebatch, opt)
- elseif target:has_tool("cxx", "gcc", "gxx") then
- import("build_modules.gcc").build_with_batchjobs(target, batchjobs, sourcebatch, opt)
- elseif target:has_tool("cxx", "cl") then
- import("build_modules.msvc").build_with_batchjobs(target, batchjobs, sourcebatch, opt)
+
+-- build modules
+rule("c++.build.modules.builder")
+ set_sourcekinds("cxx")
+ set_extensions(".mpp", ".mxx", ".cppm", ".ixx")
+
+ -- generate headerunits
+ -- parallel build support to accelerate `xmake build` to build headerunits
+ before_build(function(target, batchjobs, opt)
+ local job
+ if target:data("cxx.has_modules") then
+ import("modules_support.common")
+ local sourcebatch = target:sourcebatches()["c++.build.modules.builder"]
+ common.patch_sourcebatch(target, sourcebatch, opt)
+
+ -- generate headerunits
+ local modules = common.get_module_dependencies(target, sourcebatch, opt)
+ batchjobs:group_enter(target:name() .. "/generate_headerunits")
+ common.generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt)
+ job = batchjobs:group_leave()
+ end
+ return job or opt.rootjob
+ end, {batch = true})
+
+ -- build modules
+ -- parallel build support to accelerate `xmake build` to build modules
+ before_build_files(function(target, batchjobs, sourcebatch, opt)
+ if target:data("cxx.has_modules") then
+ import("modules_support.common")
+ common.patch_sourcebatch(target, sourcebatch, opt)
+ local modules = common.get_module_dependencies(target, sourcebatch, opt)
+ common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt)
else
- local _, toolname = target:tool("cxx")
- raise("compiler(%s): does not support c++ module!", toolname)
+ -- avoid duplicate linking of object files of non-module programs
+ sourcebatch.objectfiles = {}
end
end, {batch = true})
+ -- serial compilation only, usually used to support project generator
+ before_buildcmd_files(function(target, batchcmds, sourcebatch, opt)
+ if target:data("cxx.has_modules") then
+ import("modules_support.common")
+
+ -- patch sourcebatch
+ common.patch_sourcebatch(target, sourcebatch, opt)
+
+ -- generate headerunits
+ local modules = common.get_module_dependencies(target, sourcebatch, opt)
+ common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt)
+
+ -- build modules
+ common.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt)
+ else
+ -- avoid duplicate linking of object files of non-module programs
+ sourcebatch.objectfiles = {}
+ end
+ end)
+
+ before_link(function (target)
+ import("modules_support.common")
+ common.append_headerunits_objectfiles(target)
+ end)
+
+ after_clean(function (target)
+ import("core.base.option")
+ import("modules_support.common")
+ os.tryrm(common.modules_cachedir(target))
+ if option.get("all") then
+ os.tryrm(common.stlmodules_cachedir(target))
+ common.localcache():clear()
+ common.localcache():save()
+ end
+ end)
+
+-- install modules
+rule("c++.build.modules.install")
+ set_extensions(".mpp", ".mxx", ".cppm", ".ixx")
+
+ before_install(function (target)
+ import("modules_support.common")
+
+ -- we cannot use target:data("cxx.has_modules"),
+ -- because on_config will be not called when installing targets
+ if common.contains_modules(target) then
+ local sourcebatch = target:sourcebatches()["c++.build.modules.install"]
+ if sourcebatch then
+ target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"})
+ end
+ end
+ end)