summaryrefslogtreecommitdiff
path: root/xmake/rules/c++/modules/xmake.lua
diff options
context:
space:
mode:
Diffstat (limited to 'xmake/rules/c++/modules/xmake.lua')
-rw-r--r--xmake/rules/c++/modules/xmake.lua140
1 files changed, 111 insertions, 29 deletions
diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua
index 12132da54..313d932f9 100644
--- a/xmake/rules/c++/modules/xmake.lua
+++ b/xmake/rules/c++/modules/xmake.lua
@@ -21,45 +21,127 @@
-- define rule: c++.build.modules
rule("c++.build.modules")
set_extensions(".mpp", ".mxx", ".cppm", ".ixx")
+ add_deps("c++.build.modules.dependencies")
+ 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)
+
+ -- get modules support
+ local modules_support = common.modules_support(target)
+
+ -- check C++20 module support
+ modules_support.check_module_support(target)
+
+ -- mark this target with modules
+ target:data_set("cxx.has_modules", true)
+
+ -- load parent
+ modules_support.load_parent(target, opt)
+ end
+ end)
+
+
+rule("c++.build.modules.dependencies")
+ before_build(function(target, opt)
+ if not target:data("cxx.has_modules") then
+ return
+ end
+
+ import("modules_support.common")
+ local modules_support = common.modules_support(target)
+
+ -- build dependency data
+ local batch = target:sourcebatches()["c++.build.modules.builder"]
+ common.patch_sourcebatch(target, batch, opt)
+
+ modules_support.generate_dependencies(target, batch, opt)
+
+ local moduleinfos = common.load(target, batch, opt)
+ local modules = common.parse_dependency_data(target, moduleinfos, opt)
+
+ target:data_set("cxx.modules", modules)
+ end)
+
+rule("c++.build.modules.builder")
+ set_sourcekinds("cxx")
+ set_extensions(".mpp", ".mxx", ".cppm", ".ixx")
+
+ before_buildcmd_files(function(target, batchcmds, sourcebatch, opt)
+ if not target:data("cxx.has_modules") then
+ sourcebatch.objectfiles = {}
+ return
+ end
+
+ import("modules_support.common")
+ local modules_support = common.modules_support(target)
+
+ local batch = sourcebatch
+
+ batch.objectfiles = {}
+ batch.dependfiles = {}
+ common.patch_sourcebatch(target, batch, opt)
+
+ local modules = target:data("cxx.modules")
+
+ local headerunits
+ for _, objectfile in ipairs(batch.objectfiles) do
+ for obj, m in pairs(modules) do
+ if obj == objectfile then
+ for name, r in pairs(m.requires) do
+ if r.method ~= "by-name" then
+ headerunits = headerunits or {}
+
+ local type = r.method == "include-angle" and ":angle" or ":quote"
+ table.append(headerunits, { name = name, path = r.path, type = type, stl = common.is_stl_header(name) })
+ end
+ end
+ break
+ end
end
end
+
+ local headerunits_flags
+ local private_headerunits_flags
+ if headerunits then
+ headerunits_flags, private_headerunits_flags = modules_support.generate_headerunits(target, batchcmds, headerunits, opt)
+ end
+
+ if headerunits_flags then
+ target:add("cxxflags", headerunits_flags, {force = true, expand = false})
+ end
+ if private_headerunits_flags then
+ target:add("cxxflags", private_headerunits_flags, {force = true, expand = false})
+ end
+
+ local modules = target:data("cxx.modules")
+
+ -- topological sort
+ local objectfiles = common.sort_modules_by_dependencies(batch.objectfiles, modules)
+
+ modules_support.build_modules(target, batchcmds, objectfiles, modules, opt)
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)
- else
- local _, toolname = target:tool("cxx")
- raise("compiler(%s): does not support c++ module!", toolname)
+
+rule("c++.build.modules.install")
+ set_extensions(".mpp", ".mxx", ".cppm", ".ixx")
+
+ before_install(function (target)
+ if not target:data("cxx.has_modules") then
+ return
end
- end, {batch = true})
+ local sourcebatch = target:sourcebatches()["c++.build.modules.install"]
+ if sourcebatch then
+ target:add("installfiles", sourcebatch.sourcefiles, {prefixdir = "include"})
+ end
+ end) \ No newline at end of file