Skip to content

Commit 396cb8f

Browse files
committed
(C++ modules support) cache patched sourcebatch and save localcache only one time
1 parent abe7d65 commit 396cb8f

File tree

2 files changed

+78
-16
lines changed

2 files changed

+78
-16
lines changed

xmake/rules/c++/modules/config.lua

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ function main(target)
7676
target:add("files")
7777
end
7878

79+
local memcache = support.memcache()
80+
local targets = memcache:get("targets") or {}
81+
targets[target:fullname()] = {}
82+
targets[target:fullname()].finished_parsing = false
83+
memcache:set("targets", targets)
7984
-- moduleonly modules are implicitly public
8085
if target:is_moduleonly() then
8186
local sourcebatches = target:sourcebatches()

xmake/rules/c++/modules/scanner.lua

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import("core.base.hashset")
2424
import("core.base.graph")
2525
import("core.base.option")
2626
import("core.base.profiler")
27+
import("core.base.bytes")
2728
import("private.async.jobpool")
2829
import("async.runjobs")
2930
import("support")
@@ -373,51 +374,93 @@ end
373374
-- patch sourcebatch
374375
function _patch_sourcebatch(target, sourcebatch)
375376

377+
local cachekey = target:fullname() .. ".patched_sourcebatch"
378+
376379
-- target deps modules
377380
local depsmodules = _get_targetdeps_modules(target) or {}
378381

379382
-- package modules
380383
local pkgmodules = _get_packages_modules(target) or {}
381384

382-
-- insert std package and deps modules, try to reused them if possible
383-
local reuse = target:policy("build.c++.modules.reuse") or
384-
target:policy("build.c++.modules.tryreuse")
385-
for sourcefile, fileconfig in pairs(table.join(depsmodules, pkgmodules)) do
386-
if reuse and fileconfig.external then
387-
local nocheck = target:policy("build.c++.modules.reuse.nocheck")
388-
local strict = target:policy("build.c++.modules.reuse.strict") or
389-
target:policy("build.c++.modules.tryreuse.discriminate_on_defines")
390-
local dep = target:dep(fileconfig.external)
391-
assert(dep, "dep target <%s> for <%s>", fileconfig.external, target:fullname())
392-
393-
local can_reuse = nocheck or _are_flags_compatible(target, dep, sourcefile, {strict = strict})
394-
if can_reuse then
395-
support.set_reused(target, dep, sourcefile)
385+
local externalmodules = table.join(depsmodules, pkgmodules)
386+
local keys = #externalmodules > 0 and table.concat(table.orderkeys(externalmodules)) or " "
387+
local md5sum = hash.md5(bytes(keys))
388+
local localcache = support.localcache()
389+
local cached_patched_sourcebatch = localcache:get(cachekey)
390+
if not cached_patched_sourcebatch or md5sum ~= cached_patched_sourcebatch.md5sum then
391+
-- insert std package and deps modules, try to reused them if possible
392+
local reuse = target:policy("build.c++.modules.reuse") or
393+
target:policy("build.c++.modules.tryreuse")
394+
local reused = {}
395+
for sourcefile, fileconfig in pairs(externalmodules) do
396+
if reuse and fileconfig.external then
397+
local nocheck = target:policy("build.c++.modules.reuse.nocheck")
398+
local strict = target:policy("build.c++.modules.reuse.strict") or
399+
target:policy("build.c++.modules.tryreuse.discriminate_on_defines")
400+
local dep = target:dep(fileconfig.external)
401+
assert(dep, "dep target <%s> for <%s>", fileconfig.external, target:fullname())
402+
403+
local can_reuse = nocheck or _are_flags_compatible(target, dep, sourcefile, {strict = strict})
404+
if can_reuse then
405+
support.set_reused(target, dep, sourcefile)
406+
table.insert(reused, sourcefile)
407+
if dep:is_moduleonly() then
408+
dep:data_set("cxx.modules.reused", true)
409+
end
410+
end
411+
end
412+
table.insert(sourcebatch.sourcefiles, sourcefile)
413+
target:fileconfig_add(sourcefile, fileconfig)
414+
end
415+
416+
sourcebatch.sourcekind = "cxx"
417+
sourcebatch.objectfiles = {}
418+
sourcebatch.dependfiles = {}
419+
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
420+
local reused, from = support.is_reused(target, sourcefile)
421+
local _target = reused and from or target
422+
local objectfile = _target:objectfile(sourcefile)
423+
local dependfile = _target:dependfile(sourcefile or objectfile)
424+
table.insert(sourcebatch.dependfiles, dependfile)
425+
end
426+
localcache:set(cachekey, {sourcefile = sourcebatch.sourcefiles, dependfiles = sourcebatch.dependfiles, reused = reused, md5sum = md5sum})
427+
else
428+
local reused = hashset.from(cached_patched_sourcebatch.reused)
429+
for sourcefile, fileconfig in pairs(externalmodules) do
430+
target:fileconfig_add(sourcefile, fileconfig)
431+
if reused:has(sourcefile) then
432+
local dep = target:dep(fileconfig.external)
396433
if dep:is_moduleonly() then
397434
dep:data_set("cxx.modules.reused", true)
398435
end
436+
support.set_reused(target, dep, sourcefile)
399437
end
400438
end
401439
table.insert(sourcebatch.sourcefiles, sourcefile)
402440
target:fileconfig_add(sourcefile, fileconfig)
403441
end
404442

405443
sourcebatch.sourcekind = "cxx"
444+
sourcebatch.objectfiles = {}
406445
sourcebatch.dependfiles = {}
407446
for _, sourcefile in ipairs(sourcebatch.sourcefiles) do
408447
local reused, from = support.is_reused(target, sourcefile)
409448
local _target = reused and from or target
410449
local objectfile = _target:objectfile(sourcefile)
411450
local dependfile = _target:dependfile(objectfile)
412451
table.insert(sourcebatch.dependfiles, dependfile)
452+
sourcebatch.sourcekind = "cxx"
453+
sourcebatch.dependfiles= cached_patched_sourcebatch.dependfiles
454+
sourcebatch.sourcefiles = cached_patched_sourcebatch.sourcefiles
413455
end
414456
end
415457

416458
function _do_parse(target, sourcebatch)
417459

418460
profiler.enter(target:fullname(), "c++ modules", "scanner", "parse module dependencies and compute dependency graph")
419461
local localcache = support.localcache()
420-
local changed = support.memcache():get2(target:fullname(), "modules.changed")
462+
local memcache = support.memcache()
463+
local changed = memcache:get2(target:fullname(), "modules.changed")
421464
local modules
422465
if changed then
423466
local moduleinfos = support.load_moduleinfos(target, sourcebatch)
@@ -476,6 +519,21 @@ function _do_parse(target, sourcebatch)
476519
-- sort modules
477520
sort_modules_by_dependencies(target, modules, {jobgraph = target:policy("build.jobgraph")})
478521
profiler.leave(target:fullname(), "c++ modules", "scanner", "parse module dependencies and compute dependency graph")
522+
523+
-- save cache if all other target finished
524+
local targets = memcache:get("targets")
525+
targets[target:fullname()].finished_parsing = true
526+
527+
local save_cache = true
528+
for _, _target in pairs(targets) do
529+
if not _target.finished_parsing then
530+
save_cache = false
531+
break
532+
end
533+
end
534+
if save_cache then
535+
support.localcache():save()
536+
end
479537
end
480538

481539
function _do_scan(target, sourcefile, opt)
@@ -844,7 +902,6 @@ function after_scan(target)
844902
assert(sourcebatch_builder)
845903
sourcebatch_builder.objectfiles = objectfiles
846904
end
847-
support.localcache():save()
848905
end
849906
end
850907

0 commit comments

Comments
 (0)