diff options
| author | ruki <[email protected]> | 2022-08-03 17:20:55 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-08-03 17:20:55 +0800 |
| commit | d1de4d49e4ae33ea5364bc996a64622fa59af9eb (patch) | |
| tree | ff6903a74a1151035253f53fa8cb805f10eb817f /xmake/rules/c++/modules/xmake.lua | |
| parent | 67a3575689b9761677b48bfb4588712f117924fb (diff) | |
| parent | 728126bd7816bbd5fb6b93cedc7163a425343fba (diff) | |
Merge pull request #2623 from Arthapz/cxx20-modules-support
[Draft] Improve C++20 modules support
Diffstat (limited to 'xmake/rules/c++/modules/xmake.lua')
| -rw-r--r-- | xmake/rules/c++/modules/xmake.lua | 140 |
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 |
