diff options
| author | ruki <[email protected]> | 2022-08-09 10:52:30 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-08-09 10:52:30 +0800 |
| commit | d025377baf093a035e11fccc68309a49ae6da471 (patch) | |
| tree | b4b59671a866348f471985125d3382d700cfe78c | |
| parent | 46cf0ad2545d829a255e88371660dfe8bb11de22 (diff) | |
| parent | af7118dcc94785f628abe1cea5cd030514ea9e88 (diff) | |
Merge pull request #2649 from xmake-io/batchjobs
Adding parallel compilation support for c++ modules
| -rw-r--r-- | tests/apis/rules/xmake.lua | 13 | ||||
| -rw-r--r-- | xmake/actions/build/build.lua | 62 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/clang.lua | 239 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/common.lua | 77 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/gcc.lua | 160 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/msvc.lua | 223 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/xmake.lua | 85 |
7 files changed, 690 insertions, 169 deletions
diff --git a/tests/apis/rules/xmake.lua b/tests/apis/rules/xmake.lua index 5a6e5d546..7d67f0dca 100644 --- a/tests/apis/rules/xmake.lua +++ b/tests/apis/rules/xmake.lua @@ -58,6 +58,12 @@ rule("stub2") after_build(function (target) print("rule(stub2): after_build") end) + before_build_files(function (target) + print("rule(stub2): before_build_files") + end) + after_build_files(function (target) + print("rule(stub2): after_build_files") + end) -- define rule: stub1 rule("stub1") @@ -148,3 +154,10 @@ target("test") add_files("src/index.md") add_files("src/test.c.in", {rule = "c code"}) + before_build(function (target) + print("target: before_build") + end) + + after_build(function (target) + print("target: after_build") + end) diff --git a/xmake/actions/build/build.lua b/xmake/actions/build/build.lua index a32b8d705..3eddf1610 100644 --- a/xmake/actions/build/build.lua +++ b/xmake/actions/build/build.lua @@ -37,25 +37,27 @@ function _clean_target(target) end end --- add builtin batch jobs -function _add_batchjobs_builtin(batchjobs, rootjob, target) +-- add batch jobs for rules +function _add_batchjobs_for_rules(batchjobs, rootjob, target, suffix) -- uses the rules script? local job, job_leaf for _, r in irpairs(target:orderules()) do -- reverse rules order for batchjobs:addjob() - local script = r:script("build") + local scriptname = "build" .. (suffix and ("_" .. suffix) or "") + local script = r:script(scriptname) if script then - if r:extraconf("build", "batch") then - job, job_leaf = assert(script(target, batchjobs, {rootjob = job or rootjob}), "rule(%s):on_build(): no returned job!", r:name()) + if r:extraconf(scriptname, "batch") then + job, job_leaf = assert(script(target, batchjobs, {rootjob = job or rootjob}), "rule(%s):%s(): no returned job!", r:name(), scriptname) else - job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total) + job = batchjobs:addjob("rule/" .. r:name() .. "/" .. scriptname, function (index, total) script(target, {progress = (index * 100) / total}) end, {rootjob = job or rootjob}) end else - local buildcmd = r:script("buildcmd") + scriptname = "buildcmd" .. (suffix and ("_" .. suffix) or "") + local buildcmd = r:script(scriptname) if buildcmd then - job = batchjobs:addjob("rule/" .. r:name() .. "/build", function (index, total) + job = batchjobs:addjob("rule/" .. r:name() .. "/" .. scriptname, function (index, total) local batchcmds_ = batchcmds.new({target = target}) buildcmd(target, batchcmds_, {progress = (index * 100) / total}) batchcmds_:runcmds({dryrun = option.get("dry-run")}) @@ -63,6 +65,14 @@ function _add_batchjobs_builtin(batchjobs, rootjob, target) end end end + return job, job_leaf or job +end + +-- add builtin batch jobs +function _add_batchjobs_builtin(batchjobs, rootjob, target) + + -- add batchjobs for rules + local job, job_leaf = _add_batchjobs_for_rules(batchjobs, rootjob, target) -- uses the builtin target script if not job and (target:is_static() or target:is_binary() or target:is_shared() or target:is_object()) then @@ -125,19 +135,6 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target) if after_build then after_build(target, {progress = progress}) end - for _, r in ipairs(target:orderules()) do - local after_build = r:script("build_after") - if after_build then - after_build(target, {progress = progress}) - else - local after_buildcmd = r:script("buildcmd_after") - if after_buildcmd then - local batchcmds_ = batchcmds.new({target = target}) - after_buildcmd(target, batchcmds_, {progress = progress}) - batchcmds_:runcmds({dryrun = option.get("dry-run")}) - end - end - end -- restore environments if oldenvs then @@ -146,8 +143,14 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target) end, {rootjob = rootjob}) + -- add batchjobs for rules/build_after + local rules_job_build_after, rules_job_build_after_leaf = _add_batchjobs_for_rules(batchjobs, job_build_after, target, "after") + -- add batch jobs for target, @note only on_build script support batch jobs - local job_build, job_build_leaf = _add_batchjobs(batchjobs, job_build_after, target) + local job_build, job_build_leaf = _add_batchjobs(batchjobs, rules_job_build_after_leaf or job_build_after, target) + + -- add batchjobs for rules/build_before + local rules_job_build_before, rules_job_build_before_leaf = _add_batchjobs_for_rules(batchjobs, job_build_leaf, target, "before") -- add before_build job for target local job_build_before = batchjobs:addjob(target:name() .. "/before_build", function (index, total) @@ -166,20 +169,7 @@ function _add_batchjobs_for_target(batchjobs, rootjob, target) if before_build then before_build(target, {progress = progress}) end - for _, r in ipairs(target:orderules()) do - local before_build = r:script("build_before") - if before_build then - before_build(target, {progress = progress}) - else - local before_buildcmd = r:script("buildcmd_before") - if before_buildcmd then - local batchcmds_ = batchcmds.new({target = target}) - before_buildcmd(target, batchcmds_, {progress = progress}) - batchcmds_:runcmds({dryrun = option.get("dry-run")}) - end - end - end - end, {rootjob = job_build_leaf}) + end, {rootjob = rules_job_build_before_leaf or job_build_leaf}) return job_build_before, job_build, job_build_after end diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 35b7cdbc5..866669257 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -33,15 +33,14 @@ import("common") -- -fmodule-file=foo=build/.gens/Foo/rules/modules/cache/foo.pcm -- function _add_module_to_mapper(target, module, bmi) - local cache = common.localcache():get("mapflags") or {} + local mapflags = common.localcache():get("mapflags") or {} local modulefileflag = get_modulefileflag(target) local mapflag = format("%s%s=%s", modulefileflag, module, bmi) - if table.contains(cache, mapflag) then + if table.contains(mapflags, mapflag) then return end - table.insert(cache, mapflag) - common.localcache():set("mapflags", cache) - common.localcache():save("mapflags") + table.insert(mapflags, mapflag) + common.localcache():set("mapflags", mapflags) end -- add a header unit into the mapper @@ -50,16 +49,25 @@ end -- -fmodule-file=build/.gens/Foo/rules/modules/cache/foo.hpp.pcm -- function _add_headerunit_to_mapper(target, bmi) - local cache = common.localcache():get("mapflags") or {} + local mapflags = common.memcache():get("mapflags") or {} local mapflag = format("%s%s", modulefileflag, bmi) if table.contains(cache, mapflag) then return end - table.insert(cache, mapflag) - common.localcache():set("mapflags", cache) + table.insert(mapflags, mapflag) + common.localcache():set("mapflags", mapflags) +end + +-- flush mapflags to mapper file cache +function _flush_mapflags_to_mapper() common.localcache():save("mapflags") end +-- get mapflags from mapper +function _get_mapflags_from_mapper() + return common.localcache():get("mapflags") +end + -- load module support for the current target function load(target) local cachedir = common.modules_cachedir(target) @@ -143,13 +151,13 @@ function generate_dependencies(target, sourcebatch, opt) progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) end - local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) - if not os.isdir(outdir) then - os.mkdir(outdir) + local outputdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) + if not os.isdir(outputdir) then + os.mkdir(outputdir) end -- no support of p1689 atm - local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) + local jsonfile = path.translate(path.join(outputdir, path.filename(sourcefile) .. ".json")) common.fallback_generate_dependencies(target, jsonfile, sourcefile) changed = true @@ -160,16 +168,45 @@ function generate_dependencies(target, sourcebatch, opt) return changed end +-- generate target stl header units for batchjobs +function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + local compinst = target:compiler("cxx") + local stlcachedir = common.stlmodules_cachedir(target) + local modulecachepathflag = get_modulecachepathflag(target) + local modulefileflag = get_modulefileflag(target) + assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") + + -- build headerunits + local projectdir = os.projectdir() + for i, headerunit in ipairs(headerunits) do + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + if not os.isfile(bmifile) then + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local args = {modulecachepathflag .. stlcachedir, "-c", "-o", bmifile, "-x", "c++-system-header", headerunit.name} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + + -- libc++ have a builtin module mapper + if not target:data_set("cxx.modules.use_libc++") then + _add_headerunit_to_mapper(target, bmifile) + end + end + end + _flush_mapflags_to_mapper() +end + -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) - - -- get headerunits flags local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) + assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") -- build headerunits local projectdir = os.projectdir() @@ -189,6 +226,61 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper() +end + +-- generate target user header units for batchjobs +function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + local compinst = target:compiler("cxx") + assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") + + -- get cachedirs + local cachedir = common.modules_cachedir(target) + local modulecachepathflag = get_modulecachepathflag(target) + local emitmoduleflag = get_emitmoduleflag(target) + local modulefileflag = get_modulefileflag(target) + + -- build headerunits + local objectfiles = {} + local flags = {} + local projectdir = os.projectdir() + for _, headerunit in ipairs(headerunits) do + local file = path.relative(headerunit.path, target:scriptdir()) + local objectfile = target:objectfile(file) + + local outputdir + if headerunit.type == ":quote" then + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + else + outputdir = path.join(cachedir, path.directory(headerunit.path)) + end + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + if not os.isdir(outputdir) then + os.mkdir(outputdir) + end + + -- generate headerunit + local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} + if headerunit.type == ":quote" then + table.join2(args, {"-I", path.directory(headerunit.path), "-x", "c++-user-header", headerunit.path}) + elseif headerunit.type == ":angle" then + table.join2(args, {"-x", "c++-system-header", headerunit.name}) + end + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + _add_headerunit_to_mapper(target, bmifile) + end + _flush_mapflags_to_mapper() end -- generate target user header units for batchcmds @@ -198,8 +290,6 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, -- get cachedirs local cachedir = common.modules_cachedir(target) - - -- get headerunits flags local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleflag = get_emitmoduleflag(target) local modulefileflag = get_modulefileflag(target) @@ -213,16 +303,16 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local file = path.relative(headerunit.path, target:scriptdir()) local objectfile = target:objectfile(file) - local outdir + local outputdir if headerunit.type == ":quote" then - outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) else - outdir = path.join(cachedir, path.directory(headerunit.path)) + outputdir = path.join(cachedir, path.directory(headerunit.path)) end - batchcmds:mkdir(outdir) + batchcmds:mkdir(outputdir) local bmifilename = path.basename(objectfile) .. get_bmi_extension() - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) batchcmds:mkdir(path.directory(objectfile)) local args = { modulecachepathflag .. cachedir, emitmoduleflag, "-c", "-o", bmifile} @@ -240,26 +330,19 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper() end --- build module files for batchcmds -function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) +-- build module files for batchjobs +function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) local compinst = target:compiler("cxx") - - -- get cachedirs local cachedir = common.modules_cachedir(target) - - -- get modules flags local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) - -- append module mapper flags - local cache = common.localcache():get("mapflags") or {} - target:add("cxxflags", cache, {force = true}) - -- build modules local common_args = {modulecachepathflag .. cachedir} - local depmtime = 0 + local provided_modules = {} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m and m.provides then @@ -276,16 +359,98 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end local bmifile = provide.bmi + local moduleinfo = table.copy(provide) + moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + -- append module mapper flags first + -- @note we add it at the end to ensure that the full mapflags are already stored in the mapper + if not target:data("cxx.add_modules_mapflags") then + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + target:data_set("cxx.add_modules_mapflags", true) + end + local args = {emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + end) + if m.requires then + moduleinfo.deps = table.keys(m.requires) + end + moduleinfo.name = name + provided_modules[name] = moduleinfo + _add_module_to_mapper(target, name, bmifile) + target:add("objectfiles", objectfile) + end + end + _flush_mapflags_to_mapper() + + -- build batchjobs for modules + common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) +end + +-- build module files for batchcmds +function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) + local compinst = target:compiler("cxx") + local cachedir = common.modules_cachedir(target) + local modulecachepathflag = get_modulecachepathflag(target) + local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) + + -- we need update mapper first + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + if m and m.provides then + -- assume there that provides is only one, until we encounter the case + local length = 0 + local name, provide + for k, v in pairs(m.provides) do + length = length + 1 + name = k + provide = v + if length > 1 then + raise("multiple provides are not supported now!") + end + end + + local bmifile = provide.bmi + _add_module_to_mapper(target, name, bmifile) + target:add("objectfiles", objectfile) + end + end + _flush_mapflags_to_mapper() + + -- append module mapper flags + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + + -- build modules + local depmtime = 0 + local common_args = {modulecachepathflag .. cachedir} + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + if m and m.provides then + local name, provide + for k, v in pairs(m.provides) do + name = k + provide = v + break + end + local bmifile = provide.bmi local args = { emitmoduleinterfaceflag, "-c", "-x", "c++-module", "--precompile", provide.sourcefile, "-o", bmifile } batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) batchcmds:mkdir(path.directory(objectfile)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, {bmifile}, {"-c", "-o", objectfile})) batchcmds:add_depfiles(provide.sourcefile) - - _add_module_to_mapper(target, name, bmifile) - - target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end end @@ -429,4 +594,4 @@ function has_headerunitsupport(target) _g.support_headerunits = support_headerunits or false end return support_headerunits or nil -end
\ No newline at end of file +end diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 34d014238..31ab47a81 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -411,20 +411,26 @@ function fallback_generate_dependencies(target, jsonfile, sourcefile) io.writefile(jsonfile, jsondata) end --- generate dependencies -function generate_dependencies(target, sourcebatch, opt) - local modules = localcache():get("modules") - local changed = modules_support(target).generate_dependencies(target, sourcebatch, opt) - if changed or modules == nil then - local moduleinfos = load_moduleinfos(target, sourcebatch) - modules = parse_dependency_data(target, moduleinfos) - localcache():set("modules", modules) - localcache():save() +-- get module dependencies +function get_module_dependencies(target, sourcebatch, opt) + local cachekey = target:name() .. "/" .. sourcebatch.rulename + local modules = memcache():get2("modules", cachekey) + if modules == nil then + modules = localcache():get2("modules", cachekey) + opt.progress = opt.progress or 0 + local changed = modules_support(target).generate_dependencies(target, sourcebatch, opt) + if changed or modules == nil then + local moduleinfos = load_moduleinfos(target, sourcebatch) + modules = parse_dependency_data(target, moduleinfos) + localcache():set2("modules", cachekey, modules) + localcache():save() + end + memcache():set2("modules", cachekey, modules) end return modules end --- generate headerunits for batchjobs, TODO +-- generate headerunits for batchjobs function generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) -- get headerunits info @@ -435,11 +441,11 @@ function generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modu local headerunits_flags if stl_headerunits then headerunits_flags = headerunits_flags or {} --- table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits_for_batchjobs(target, batchjobs, stl_headerunits, opt)) + table.join2(headerunits_flags, modules_support(target).generate_stl_headerunits_for_batchjobs(target, batchjobs, stl_headerunits, opt)) end if headerunits then headerunits_flags = headerunits_flags or {} --- table.join2(headerunits_flags, modules_support(target).generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt)) + table.join2(headerunits_flags, modules_support(target).generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt)) end return headerunits_flags end @@ -463,10 +469,50 @@ function generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modu end end --- build modules for batchjobs, TODO +-- build batch jobs for module dependencies +function _build_batchjobs_for_moduledeps(modules, batchjobs, rootjob, jobrefs, moduleinfo) + local targetjob_ref = jobrefs[moduleinfo.name] + if targetjob_ref then + batchjobs:add(targetjob_ref, rootjob) + else + local modulejob = batchjobs:add(moduleinfo.job, rootjob) + if modulejob then + jobrefs[moduleinfo.name] = modulejob + for _, depname in ipairs(moduleinfo.deps) do + local dep = modules[depname] + if dep then -- maybe nil, e.g. `import <string>;` + _build_batchjobs_for_moduledeps(modules, batchjobs, modulejob, jobrefs, dep) + end + end + end + end +end + +-- build batchjobs for modules +function build_batchjobs_for_modules(modules, batchjobs, rootjob) + local depset = hashset.new() + for _, moduleinfo in pairs(modules) do + assert(moduleinfo.job) + for _, depname in ipairs(moduleinfo.deps) do + depset:insert(depname) + end + end + local modules_root = {} + for _, moduleinfo in pairs(modules) do + if not depset:has(moduleinfo.name) then + table.insert(modules_root, moduleinfo) + end + end + local jobrefs = {} + for _, moduleinfo in pairs(modules_root) do + _build_batchjobs_for_moduledeps(modules, batchjobs, rootjob, jobrefs, moduleinfo) + end +end + +-- build modules for batchjobs function build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) local objectfiles = sort_modules_by_dependencies(sourcebatch.objectfiles, modules) --- modules_support(target).build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) + modules_support(target).build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) end -- build modules for batchcmds @@ -475,6 +521,7 @@ function build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, op modules_support(target).build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) end +-- append headerunits objectfiles to link function append_headerunits_objectfiles(target) local cache = localcache():get("headerunit_objectfiles") or {} if target:is_binary() then @@ -484,4 +531,4 @@ function append_headerunits_objectfiles(target) elseif target:is_shared() == "shared" then target:add("shflags", cache, {force = true}) end -end
\ No newline at end of file +end diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 99045cf54..a37346bad 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -131,15 +131,15 @@ function generate_dependencies(target, sourcebatch, opt) progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) end - local outdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) - if not os.isdir(outdir) then - os.mkdir(outdir) + local outputdir = path.translate(path.join(cachedir, path.directory(path.relative(sourcefile, projectdir)))) + if not os.isdir(outputdir) then + os.mkdir(outputdir) end - local jsonfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".json")) + local jsonfile = path.translate(path.join(outputdir, path.filename(sourcefile) .. ".json")) if trtbdflag and depfileflag and depoutputflag then - local ifile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".i")) - local dfile = path.translate(path.join(outdir, path.filename(sourcefile) .. ".d")) + local ifile = path.translate(path.join(outputdir, path.filename(sourcefile) .. ".i")) + local dfile = path.translate(path.join(outputdir, path.filename(sourcefile) .. ".d")) local args = {sourcefile, "-MD", "-MT", jsonfile, "-MF", dfile, depfileflag .. jsonfile, trtbdflag, depoutputfile .. target:objectfile(sourcefile), "-o", ifile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) else @@ -154,12 +154,33 @@ function generate_dependencies(target, sourcebatch, opt) return changed end +-- generate target stl header units for batchjobs +function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() + local stlcachedir = common.stlmodules_cachedir(target) + + -- build headerunits + local projectdir = os.projectdir() + for _, headerunit in ipairs(headerunits) do + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + if not os.isfile(bmifile) then + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local args = {"-c", "-x", "c++-system-header", headerunit.name} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + end + _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) + end +end + -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() - - -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) -- build headerunits @@ -172,21 +193,69 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) end - batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) end +-- generate target user header units for batchjobs +function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) + local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() + local cachedir = common.modules_cachedir(target) + + -- build headerunits + local projectdir = os.projectdir() + for _, headerunit in ipairs(headerunits) do + local file = path.relative(headerunit.path, projectdir) + local objectfile = target:objectfile(file) + local outputdir + local headerunit_path + if headerunit.type == ":quote" then + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + else + outputdir = path.join(cachedir, path.directory(headerunit.path)) + end + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) + if headerunit.type == ":quote" then + headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) + elseif headerunit.type == ":angle" then + -- if path is relative then its a subtarget path + headerunit_path = path.is_absolute(headerunit.path) and headerunit.path or path.join(".", headerunit.path) + end + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + if not os.isdir(outputdir) then + os.mkdir(outputdir) + end + + -- generate headerunit + local args = { "-c" } + if headerunit.type == ":quote" then + table.join2(args, { "-I", path.directory(path.relative(headerunit.path, projectdir)), "-x", "c++-user-header", headerunit.name }) + elseif headerunit.type == ":angle" then + table.join2(args, { "-x", "c++-system-header", headerunit.name }) + end + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) + end +end + -- generate target user header units for batchcmds function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() - - -- get cachedirs local cachedir = common.modules_cachedir(target) -- build headerunits @@ -195,17 +264,16 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, projectdir) local objectfile = target:objectfile(file) - - local outdir + local outputdir if headerunit.type == ":quote" then - outdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) else - outdir = path.join(cachedir, path.directory(headerunit.path)) + outputdir = path.join(cachedir, path.directory(headerunit.path)) end - batchcmds:mkdir(outdir) + batchcmds:mkdir(outputdir) local bmifilename = path.basename(objectfile) .. get_bmi_extension() - local bmifile = (outdir and path.join(outdir, bmifilename) or bmifilename) + local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) batchcmds:mkdir(path.directory(objectfile)) local args = { "-c" } @@ -229,13 +297,63 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:set_depmtime(depmtime) end +-- build module files for batchjobs +function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) + local compinst = target:compiler("cxx") + local mapper_file = _get_module_mapper() + local common_args = {"-x", "c++"} + local cachedir = common.modules_cachedir(target) + + -- build modules + local projectdir = os.projectdir() + local provided_modules = {} + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + if m and m.provides then + -- assume there that provides is only one, until we encounter the case + local length = 0 + local name, provide + for k, v in pairs(m.provides) do + length = length + 1 + name = k + provide = v + if length > 1 then + raise("multiple provides are not supported now!") + end + end + + local bmifile = provide.bmi + local moduleinfo = table.copy(provide) + moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + local args = {"-o", objectfile, "-c", provide.sourcefile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args)) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + end) + if m.requires then + moduleinfo.deps = table.keys(m.requires) + end + moduleinfo.name = name + provided_modules[name] = moduleinfo + _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir)) + target:add("objectfiles", objectfile) + end + end + + -- build batchjobs for modules + common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) +end + -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") local mapper_file = _get_module_mapper() local common_args = {"-x", "c++"} - - -- get cachedirs local cachedir = common.modules_cachedir(target) -- build modules @@ -336,4 +454,4 @@ function get_depoutputflag(target) _g.depoutputflag = depoutputflag or false end return depoutputflag or nil -end
\ No newline at end of file +end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index b2b2e605a..bcc781248 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -34,16 +34,25 @@ import("common") -- /headerUnit:angle glm/mat4x4.hpp=Users\arthu\AppData\Local\.xmake\packages\g\glm\0.9.9+8\91454f3ee0be416cb9c7452970a2300f\include\glm\mat4x4.hpp.ifc -- function _add_module_to_mapper(argument, module) - local cache = common.localcache():get("mapflags") or {} + local mapflags = common.localcache():get("mapflags") or {} local mapflag = format("%s %s", argument, module) - if table.contains(cache, mapflag) then + if table.contains(mapflags, mapflag) then return end - table.insert(cache, mapflag) - common.localcache():set("mapflags", cache) + table.insert(mapflags, mapflag) + common.localcache():set("mapflags", mapflags) +end + +-- flush mapflags to mapper file cache +function _flush_mapflags_to_mapper() common.localcache():save("mapflags") end +-- get mapflags from mapper +function _get_mapflags_from_mapper() + return common.localcache():get("mapflags") +end + -- add an objectfile to the linker args -- -- e.g @@ -150,11 +159,12 @@ function generate_dependencies(target, sourcebatch, opt) return changed end --- generate target stl header units for batchcmds -function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) +-- generate target stl header units for batchjobs +function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + local stlcachedir = common.stlmodules_cachedir(target) -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -163,9 +173,40 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") - -- get cachedirs + -- build headerunits + local common_args = {"-TP", exportheaderflag, "-c"} + for _, headerunit in ipairs(headerunits) do + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + local objectfile = bmifile .. ".obj" + if not os.isfile(bmifile) or not os.isfile(objectfile) then + batchjobs:addjob(headerunit.name, function(index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, stlcachedir, "-Fo" .. objectfile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + _add_module_to_mapper(headerunitflag .. ":angle", headerunit.name .. "=" .. path.filename(headerunit.name) .. get_bmi_extension()) + _add_objectfile_to_link_arguments(objectfile) + end + end + _flush_mapflags_to_mapper() +end + +-- generate target stl header units for batchcmds +function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") local stlcachedir = common.stlmodules_cachedir(target) + -- get flags + local exportheaderflag = get_exportheaderflag(target) + local headerunitflag = get_headerunitflag(target) + local headernameflag = get_headernameflag(target) + local ifcoutputflag = get_ifcoutputflag(target) + assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") + -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} local depmtime = 0 @@ -184,13 +225,15 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper() end -- generate target user header units for batchcmds -function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) +function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, opt) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") + local cachedir = common.modules_cachedir(target) -- get flags local exportheaderflag = get_exportheaderflag(target) @@ -199,9 +242,58 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") - -- get cachedirs + -- build headerunits + local common_args = {"-TP", exportheaderflag, "-c"} + local projectdir = os.projectdir() + for _, headerunit in ipairs(headerunits) do + local file = path.relative(headerunit.path, target:scriptdir()) + local objectfile = target:objectfile(file) + local outputdir + if headerunit.type == ":quote" then + outputdir = path.join(cachedir, path.directory(path.relative(headerunit.path, projectdir))) + else + -- if path is relative then its a subtarget path + outputdir = path.join(cachedir, path.is_absolute(headerunit.path) and path.directory(headerunit.path):sub(3) or headerunit.path) + end + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = path.join(outputdir, bmifilename) + batchjobs:addjob(headerunit.name, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + if not os.isdir(outputdir) then + os.mkdir(outputdir) + end + + -- generate headerunit + local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/Fo" .. objectfile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + _add_module_to_mapper(headerunitflag .. headerunit.type, headerunit.name .. "=" .. path.relative(bmifile, cachedir)) + _add_objectfile_to_link_arguments(objectfile) + end + _flush_mapflags_to_mapper() +end + +-- generate target user header units for batchcmds +function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") local cachedir = common.modules_cachedir(target) + -- get flags + local exportheaderflag = get_exportheaderflag(target) + local headerunitflag = get_headerunitflag(target) + local headernameflag = get_headernameflag(target) + local ifcoutputflag = get_ifcoutputflag(target) + assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") + -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} local projectdir = os.projectdir() @@ -234,15 +326,14 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) + _flush_mapflags_to_mapper() end --- build module files for batchcmds -function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) +-- build module files for batchjobs +function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) local compinst = target:compiler("cxx") local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") - - -- get cachedirs local cachedir = common.modules_cachedir(target) -- get flags @@ -250,13 +341,9 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) - -- append module mapper flags - local cache = common.localcache():get("mapflags") or {} - target:add("cxxflags", cache, {force = true}) - -- build modules local common_args = {"-TP"} - local depmtime = 0 + local provided_modules = {} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m and m.provides then @@ -273,20 +360,106 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op end local bmifile = provide.bmi - local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} + local moduleinfo = table.copy(provide) + moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) + depend.on_changed(function() + progress.show((index * 100) / total, "${color.build.object}generating.cxx.module.bmi %s", name) + local objectdir = path.directory(objectfile) + if not os.isdir(objectdir) then + os.mkdir(objectdir) + end + -- append module mapper flags first + -- @note we add it at the end to ensure that the full mapflags are already stored in the mapper + if not target:data("cxx.add_modules_mapflags") then + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + target:data_set("cxx.add_modules_mapflags", true) + end + local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + end) + if m.requires then + moduleinfo.deps = table.keys(m.requires) + end + moduleinfo.name = name + provided_modules[name] = moduleinfo + _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) + target:add("objectfiles", objectfile) + end + end + _flush_mapflags_to_mapper() + + + -- build batchjobs for modules + common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) +end + +-- build module files for batchcmds +function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + local cachedir = common.modules_cachedir(target) + + -- get flags + local ifcoutputflag = get_ifcoutputflag(target) + local interfaceflag = get_interfaceflag(target) + local referenceflag = get_referenceflag(target) + + -- we need update mapper first + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + if m and m.provides then + -- assume there that provides is only one, until we encounter the case + local length = 0 + local name, provide + for k, v in pairs(m.provides) do + length = length + 1 + name = k + provide = v + if length > 1 then + raise("multiple provides are not supported now!") + end + end + + local bmifile = provide.bmi + _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) + target:add("objectfiles", objectfile) + end + end + _flush_mapflags_to_mapper() + + -- append module mapper flags + local mapflags = _get_mapflags_from_mapper() + if mapflags then + target:add("cxxflags", mapflags, {force = true}) + end + + -- build modules + local common_args = {"-TP"} + local depmtime = 0 + for _, objectfile in ipairs(objectfiles) do + local m = modules[objectfile] + if m and m.provides then + local name, provide + for k, v in pairs(m.provides) do + name = k + provide = v + break + end + local bmifile = provide.bmi + local args = {"-c", "-Fo" .. objectfile, interfaceflag, ifcoutputflag, bmifile, provide.sourcefile} batchcmds:show_progress(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", name) batchcmds:mkdir(path.directory(objectfile)) batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(provide.sourcefile) - - _add_module_to_mapper(referenceflag, name .. "=" .. path.filename(bmifile)) - - target:add("objectfiles", objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end end - batchcmds:set_depmtime(depmtime) end @@ -430,4 +603,4 @@ function get_scandependenciesflag(target) _g.scandependenciesflag = scandependenciesflag or false end return scandependenciesflag or nil -end
\ No newline at end of file +end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 4117004cc..23f9a0f77 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -53,55 +53,70 @@ rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - -- TODO parallel build support to accelerate `xmake build` to build modules - --[[ + -- 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) + 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 not target:data("cxx.has_modules") then + 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 + -- avoid duplicate linking of object files of non-module programs sourcebatch.objectfiles = {} - return end + end, {batch = true}) - -- patch sourcebatch - import("modules_support.common") - common.patch_sourcebatch(target, sourcebatch, opt) - - -- generate dependencies - local modules = common.generate_dependencies(target, sourcebatch, opt) + -- 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") - -- generate headerunits - local headerunits_flags = common.generate_headerunits_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) - if headerunits_flags then - target:add("cxxflags", headerunits_flags, {force = true, expand = false}) - end + -- patch sourcebatch + common.patch_sourcebatch(target, sourcebatch, opt) - -- build modules - common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) - end, {batch = true})]] + -- generate headerunits + local modules = common.get_module_dependencies(target, sourcebatch, opt) + common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) - -- serial compilation only, usually used to support project generator - before_buildcmd_files(function(target, batchcmds, sourcebatch, opt) - if not target:data("cxx.has_modules") then + -- 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 = {} - return end + end) - -- patch sourcebatch + before_link(function (target) import("modules_support.common") - common.patch_sourcebatch(target, sourcebatch, opt) - - -- generate dependencies - local modules = common.generate_dependencies(target, sourcebatch, opt) - - -- generate headerunits - common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) - - -- build modules - common.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + common.append_headerunits_objectfiles(target) end) - before_link(function(target) + after_clean(function (target) + import("core.base.option") import("modules_support.common") - common.append_headerunits_objectfiles(target) + 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 |
