diff options
| author | Arthur LAURENT <[email protected]> | 2024-02-10 17:35:35 +0100 |
|---|---|---|
| committer | Arthur LAURENT <[email protected]> | 2024-02-12 11:50:02 +0100 |
| commit | 1a6c4c2a93c80d6ed17a70100f62b221b3730000 (patch) | |
| tree | e041b163889ea073a4bbb1ded17807300279a702 /xmake/rules/c++/modules/modules_support/builder.lua | |
| parent | a7396842b55fb3d9747b5da199d6d5ec1afb8aa9 (diff) | |
implement module reusage based on flag comparison
fix gcc
fix msvc
fix msvc
fix msvc
fix
Diffstat (limited to 'xmake/rules/c++/modules/modules_support/builder.lua')
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/builder.lua | 90 |
1 files changed, 85 insertions, 5 deletions
diff --git a/xmake/rules/c++/modules/modules_support/builder.lua b/xmake/rules/c++/modules/modules_support/builder.lua index 936f90414..23515e988 100644 --- a/xmake/rules/c++/modules/modules_support/builder.lua +++ b/xmake/rules/c++/modules/modules_support/builder.lua @@ -33,7 +33,6 @@ import("dependency_scanner") -- build target modules function _build_modules(target, sourcebatch, modules, opt) local objectfiles = sourcebatch.objectfiles - _builder(target).populate_module_map(target, modules) -- build modules for _, objectfile in ipairs(objectfiles) do @@ -81,16 +80,79 @@ function _build_headerunits(target, headerunits, opt) end end +-- check if flags are compatible for module reuse +function _are_flags_compatible(target, other, cppfile) + local compinst1 = target:compiler("cxx") + local flags1 = compinst1:compflags({sourcefile = cppfile, target = target}) + + local compinst2 = other:compiler("cxx") + local flags2 = compinst2:compflags({sourcefile = cppfile, target = other}) + + -- strip unrelevent flags + flags1 = compiler_support.strip_flags(target, flags1) + flags2 = compiler_support.strip_flags(target, flags2) + + if #flags1 ~= #flags2 then + return false + end + + table.sort(flags1) + table.sort(flags2) + + for i = 1,#flags1 do + if flags1[i] ~= flags2[i] then + return false + end + end + + return true +end + +-- try to reuse modules from other target +function _try_reuse_modules(target, modules) + for _, module in pairs(modules) do + local name, provide, cppfile = compiler_support.get_provided_module(module) + if not provide then + goto CONTINUE + end + + cppfile = cppfile or module.cppfile + + local fileconfig = target:fileconfig(cppfile) + local public = fileconfig and (fileconfig.public or fileconfig.external) + if not public then + goto CONTINUE + end + + for _, dep in ipairs(target:orderdeps()) do + if not _are_flags_compatible(target, dep, cppfile) then + goto NEXT + end + local mapped = get_from_target_mapper(dep, name) + if mapped then + compiler_support.memcache():set2(target:name() .. name, "reuse", true) + add_module_to_target_mapper(target, mapped.name, mapped.sourcefile, mapped.bmi, table.join(mapped.opt or {}, {target = dep})) + break + end + ::NEXT:: + end + + ::CONTINUE:: + end + return modules +end + -- should we build this module or headerunit ? function should_build(target, sourcefile, bmifile, opt) -- force rebuild a module if any of its module dependency is rebuilt - local requires = opt.requires + local requires = opt and opt.requires if requires then for required, _ in table.orderpairs(requires) do local m = get_from_target_mapper(target, required) if m then - local rebuild = compiler_support.memcache():get2("should_build_in" .. target:name(), m.key) + local rebuild = (m.opt and m.opt.target) and compiler_support.memcache():get2("should_build_in_" .. m.opt.target:name(), m.key) + or compiler_support.memcache():get2("should_build_in_" .. target:name(), m.key) if rebuild then return true end @@ -98,6 +160,14 @@ function should_build(target, sourcefile, bmifile, opt) end end + -- reused + if opt and opt.name then + local m = get_from_target_mapper(target, opt.name) + if m and m.opt and m.opt.target then + return compiler_support.memcache():get2("should_build_in_" .. m.opt.target:name(), m.key) + end + end + -- or rebuild it if the file changed local objectfile = opt.objectfile local dryrun = option.get("dry-run") @@ -175,7 +245,7 @@ function _builder(target) end function mark_build(target, name) - compiler_support.memcache():set2("should_build_in" .. target:name(), name, true) + compiler_support.memcache():set2("should_build_in_" .. target:name(), name, true) end -- build batchjobs for modules @@ -189,6 +259,11 @@ function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, op opt.rootjob = batchjobs:group_leave() or opt.rootjob batchjobs:group_enter(target:name() .. "/build_modules", {rootjob = opt.rootjob}) + batchjobs:addjob(target:name() .. "_populate_module_map", function(_, _) + _try_reuse_modules(target, modules) + _builder(target).populate_module_map(target, modules) + end, {rootjob = opt.rootjob}) + local modulesjobs = {} _build_modules(target, sourcebatch, modules, table.join(opt, { build_module = function(deps, module, name, objectfile, cppfile) @@ -208,6 +283,9 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op local depmtime = 0 opt.progress = opt.progress or 0 + _try_reuse_modules(target, modules) + _builder(target).populate_module_map(target, modules) + -- build modules _build_modules(target, sourcebatch, modules, table.join(opt, { build_module = function(_, module, _, objectfile, cppfile) @@ -352,7 +430,9 @@ end -- add a module to target mapper function add_module_to_target_mapper(target, name, sourcefile, bmifile, opt) local mapper = get_target_module_mapper(target) - mapper[name] = {name = name, key = name, bmi = bmifile, sourcefile = sourcefile, opt = opt} + if not mapper[name] then + mapper[name] = {name = name, key = name, bmi = bmifile, sourcefile = sourcefile, opt = opt} + end flush_target_module_mapper_keys(target) end |
