@@ -24,6 +24,7 @@ import("core.base.hashset")
2424import (" core.base.graph" )
2525import (" core.base.option" )
2626import (" core.base.profiler" )
27+ import (" core.base.bytes" )
2728import (" private.async.jobpool" )
2829import (" async.runjobs" )
2930import (" support" )
@@ -373,51 +374,93 @@ end
373374-- patch sourcebatch
374375function _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
414456end
415457
416458function _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
479537end
480538
481539function _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
849906end
850907
0 commit comments