diff options
| author | ruki <[email protected]> | 2022-08-16 12:33:47 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-08-16 12:33:47 +0800 |
| commit | 81aca6fbe9149b377cdd88e8ee4b8f045d5a46da (patch) | |
| tree | 0f138f960ab9fd95265ecbffca7c6ae27d65f4a3 /xmake/rules/c++/modules/xmake.lua | |
| parent | d46b16f8c40493bfc78764931bf7c3209442696b (diff) | |
| parent | d9f82e1bba29adc8b11dc1f7b3887717f03137d6 (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.lua | 129 |
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) |
