From eac8fac2b08d6d2d16b7b9fe091e5594d091027d Mon Sep 17 00:00:00 2001 From: ruki Date: Sun, 7 Aug 2022 23:20:35 +0800 Subject: improve build rules --- tests/apis/rules/xmake.lua | 7 +++++ xmake/actions/build/build.lua | 62 ++++++++++++++++++------------------------- 2 files changed, 33 insertions(+), 36 deletions(-) diff --git a/tests/apis/rules/xmake.lua b/tests/apis/rules/xmake.lua index 5a6e5d546..1ffc45b04 100644 --- a/tests/apis/rules/xmake.lua +++ b/tests/apis/rules/xmake.lua @@ -148,3 +148,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 -- cgit v1.3.1 From 3652c9429dd47dbf08670f5ee8a89be00cf8693b Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 8 Aug 2022 06:54:49 +0200 Subject: Clean code --- xmake/rules/c++/modules/modules_support/gcc.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 65dc45782..8f3bacf72 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -162,7 +162,6 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, -- build headerunits local projectdir = os.projectdir() - local depmtime = 0 for _, headerunit in ipairs(headerunits) do local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) if not os.isfile(bmifile) then @@ -209,7 +208,6 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- build headerunits local projectdir = os.projectdir() - local depmtime = 0 for _, headerunit in ipairs(headerunits) do local file = path.relative(headerunit.path, projectdir) local objectfile = target:objectfile(file) -- cgit v1.3.1 From e714ded62e800258e228942758fe7e809adca544 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 8 Aug 2022 06:54:59 +0200 Subject: Add batchjobs for clang --- xmake/rules/c++/modules/modules_support/clang.lua | 113 ++++++++++++++++++++-- 1 file changed, 104 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 35b7cdbc5..bff8cb7cb 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -143,13 +143,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,6 +160,38 @@ 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") + + -- get cachedirs + local stlcachedir = common.stlmodules_cachedir(target) + + -- get headerunits flags + local modulecachepathflag = get_modulecachepathflag(target) + local modulefileflag = get_modulefileflag(target) + + -- 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 +end + -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") @@ -191,6 +223,61 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, 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") + assert(has_headerunitsupport(target), "compiler(clang): does not support c++ header units!") + + -- 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) + + -- 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 +end + -- generate target user header units for batchcmds function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") @@ -213,16 +300,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} @@ -292,6 +379,14 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:set_depmtime(depmtime) end +-- build module files for batchjobs +function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) + batchjobs:addjob("TODO", function (index, total) + -- TODO + raise("build modules not supported!") + end, {rootjob = opt.rootjob}) +end + function get_bmi_extension() return ".pcm" end -- cgit v1.3.1 From 3a417fd416d178f8469af0e71610ec4b4f733971 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Mon, 8 Aug 2022 06:55:10 +0200 Subject: Add batchjobs for msvc --- xmake/rules/c++/modules/modules_support/msvc.lua | 96 ++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index b2b2e605a..7cf1c63b1 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -150,6 +150,41 @@ 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 toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + + -- 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!") + + -- get cachedirs + local stlcachedir = common.stlmodules_cachedir(target) + + -- 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 +end + -- generate target stl header units for batchcmds function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") @@ -186,6 +221,59 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:set_depmtime(depmtime) end +-- generate target user header units for batchcmds +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") + + -- 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!") + + -- get cachedirs + local cachedir = common.modules_cachedir(target) + + -- 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 +end + -- generate target user header units for batchcmds function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, opt) local compinst = target:compiler("cxx") @@ -236,6 +324,14 @@ 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) + batchjobs:addjob("TODO", function (index, total) + -- TODO + raise("build modules not supported!") + end, {rootjob = opt.rootjob}) +end + -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") -- cgit v1.3.1 From 1fb045a19472a8d04d24cb41c49a3bf75b2767d2 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:40:44 +0800 Subject: add batchjobs for gcc --- tests/apis/rules/xmake.lua | 6 ++ xmake/rules/c++/modules/modules_support/common.lua | 32 ++++--- xmake/rules/c++/modules/modules_support/gcc.lua | 105 +++++++++++++++++---- xmake/rules/c++/modules/xmake.lua | 47 +++++---- 4 files changed, 133 insertions(+), 57 deletions(-) diff --git a/tests/apis/rules/xmake.lua b/tests/apis/rules/xmake.lua index 1ffc45b04..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") diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 34d014238..e9ef0fb62 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -411,20 +411,24 @@ 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 modules = _g.modules + if modules == nil then + 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() + end + _g.modules = 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 +439,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,7 +467,7 @@ function generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modu end end --- build modules for batchjobs, TODO +-- 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) @@ -484,4 +488,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..663e4ea07 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,34 @@ 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() + local depmtime = 0 + 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)) + _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + end + 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 +194,67 @@ 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() + local depmtime = 0 + for _, headerunit in ipairs(headerunits) do + 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 file = path.relative(headerunit.path, projectdir) + 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 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" } + local headerunit_path + if headerunit.type == ":quote" then + table.join2(args, { "-I", path.directory(path.relative(headerunit.path, projectdir)), "-x", "c++-user-header", headerunit.name }) + headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) + elseif headerunit.type == ":angle" then + table.join2(args, { "-x", "c++-system-header", headerunit.name }) + -- 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 + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) + _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) + + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = opt.rootjob}) + 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 +263,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" } @@ -336,4 +403,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/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 4117004cc..3efa123e6 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -53,35 +53,34 @@ 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 - --[[ - before_build_files(function(target, batchjobs, sourcebatch, opt) - if not target:data("cxx.has_modules") then - sourcebatch.objectfiles = {} - return + 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}) - -- patch sourcebatch - import("modules_support.common") - common.patch_sourcebatch(target, sourcebatch, opt) - - -- generate dependencies - local modules = common.generate_dependencies(target, sourcebatch, opt) - - -- 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}) + -- 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") + local modules = common.get_module_dependencies(target, sourcebatch, opt) + common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) end - - -- build modules - common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) - end, {batch = true})]] + end, {batch = true}) -- 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 - sourcebatch.objectfiles = {} return end @@ -89,8 +88,8 @@ rule("c++.build.modules.builder") import("modules_support.common") common.patch_sourcebatch(target, sourcebatch, opt) - -- generate dependencies - local modules = common.generate_dependencies(target, sourcebatch, opt) + -- get module dependencies + local modules = common.get_module_dependencies(target, sourcebatch, opt) -- generate headerunits common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) -- cgit v1.3.1 From e96c32a19877939a4e325bb3afccef873b47ce35 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:45:38 +0800 Subject: fix batchjobs for gcc/headerunits --- xmake/rules/c++/modules/modules_support/common.lua | 3 ++- xmake/rules/c++/modules/modules_support/gcc.lua | 23 ++++++++++++++++------ xmake/rules/c++/modules/xmake.lua | 1 + 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index e9ef0fb62..52a428874 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -416,6 +416,7 @@ function get_module_dependencies(target, sourcebatch, opt) local modules = _g.modules if modules == nil then modules = localcache():get("modules") + 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) @@ -470,7 +471,7 @@ 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 diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 663e4ea07..af328b0b2 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -171,10 +171,10 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, 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)) - _add_module_to_mapper(mapper_file, headerunit.path, path.absolute(bmifile, projectdir)) 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 @@ -213,6 +213,13 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, for _, headerunit in ipairs(headerunits) do local bmifilename = path.basename(objectfile) .. get_bmi_extension() local bmifile = (outputdir and path.join(outputdir, bmifilename) or bmifilename) + local headerunit_path + 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) @@ -234,20 +241,16 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- generate headerunit local args = { "-c" } - local headerunit_path if headerunit.type == ":quote" then table.join2(args, { "-I", path.directory(path.relative(headerunit.path, projectdir)), "-x", "c++-user-header", headerunit.name }) - headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) elseif headerunit.type == ":angle" then table.join2(args, { "-x", "c++-system-header", headerunit.name }) - -- 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 os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args)) - _add_module_to_mapper(mapper_file, headerunit_path, path.absolute(bmifile, projectdir)) 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 @@ -296,6 +299,14 @@ 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) + batchjobs:addjob("TODO", function (index, total) + -- TODO + raise("build modules not supported!") + end, {rootjob = opt.rootjob}) +end + -- build module files for batchcmds function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) local compinst = target:compiler("cxx") diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 3efa123e6..c888a83fb 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -52,6 +52,7 @@ rule("c++.build.modules") rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + add_deps("c++.build.modules.dependencies") before_build(function(target, batchjobs, opt) local job -- cgit v1.3.1 From bc068bdb03fa9e75cd8dfe056a06790956934eba Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:46:13 +0800 Subject: fix path --- xmake/rules/c++/modules/modules_support/gcc.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index af328b0b2..65dc45782 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -211,9 +211,17 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local projectdir = os.projectdir() local depmtime = 0 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) - local headerunit_path if headerunit.type == ":quote" then headerunit_path = path.join(".", path.relative(headerunit.path, projectdir)) elseif headerunit.type == ":angle" then @@ -223,14 +231,6 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, 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 file = path.relative(headerunit.path, projectdir) - 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 objectdir = path.directory(objectfile) if not os.isdir(objectdir) then os.mkdir(objectdir) -- cgit v1.3.1 From aaa5b2c37ec355cf2746f2d854517b3f43afcaf5 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:46:26 +0800 Subject: remvoe deps --- xmake/rules/c++/modules/xmake.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index c888a83fb..3efa123e6 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -52,7 +52,6 @@ rule("c++.build.modules") rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") - add_deps("c++.build.modules.dependencies") before_build(function(target, batchjobs, opt) local job -- cgit v1.3.1 From 4abd6737364ffec07d9813c63d89e0ae90240315 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 22:46:33 +0800 Subject: add comments --- xmake/rules/c++/modules/xmake.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 3efa123e6..1d117e78b 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -53,6 +53,7 @@ rule("c++.build.modules.builder") set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") + -- 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 -- cgit v1.3.1 From d0e4316018f9d75742b26b3abf75860d129c31c8 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 23:24:30 +0800 Subject: remove cxx sourcekind for modules --- xmake/rules/c++/modules/xmake.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 1d117e78b..7048ec49b 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -50,7 +50,6 @@ rule("c++.build.modules") -- build modules rule("c++.build.modules.builder") - set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") -- parallel build support to accelerate `xmake build` to build headerunits -- cgit v1.3.1 From ad67a37fe4981f68c52ae1e7497090a60a30edab Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 23:31:35 +0800 Subject: fix module dpes --- xmake/rules/c++/modules/modules_support/common.lua | 9 +++---- xmake/rules/c++/modules/xmake.lua | 28 ++++++++++++---------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 52a428874..ee1016d68 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -413,18 +413,19 @@ end -- get module dependencies function get_module_dependencies(target, sourcebatch, opt) - local modules = _g.modules + local cachekey = target:name() .. "/" .. sourcebatch.rulename + local modules = memcache():get2("modules", cachekey) if modules == nil then - modules = localcache():get("modules") + 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():set("modules", modules) + localcache():set2("modules", cachekey, modules) localcache():save() end - _g.modules = modules + memcache():set2("modules", cachekey, modules) end return modules end diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 7048ec49b..3c69600bd 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -50,6 +50,7 @@ rule("c++.build.modules") -- build modules rule("c++.build.modules.builder") + set_sourcekinds("cxx") set_extensions(".mpp", ".mxx", ".cppm", ".ixx") -- parallel build support to accelerate `xmake build` to build headerunits @@ -75,27 +76,28 @@ rule("c++.build.modules.builder") import("modules_support.common") local modules = common.get_module_dependencies(target, sourcebatch, opt) common.build_modules_for_batchjobs(target, batchjobs, sourcebatch, modules, opt) + else + sourcebatch.objectfiles = {} end end, {batch = true}) -- 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 - return - end - - -- patch sourcebatch - import("modules_support.common") - common.patch_sourcebatch(target, sourcebatch, opt) + if target:data("cxx.has_modules") then + import("modules_support.common") - -- get module dependencies - local modules = common.get_module_dependencies(target, sourcebatch, opt) + -- patch sourcebatch + common.patch_sourcebatch(target, sourcebatch, opt) - -- generate headerunits - common.generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modules, 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) + -- build modules + common.build_modules_for_batchcmds(target, batchcmds, sourcebatch, modules, opt) + else + sourcebatch.objectfiles = {} + end end) before_link(function(target) -- cgit v1.3.1 From 969c1371fde82493d75766681c800107b8359981 Mon Sep 17 00:00:00 2001 From: ruki Date: Mon, 8 Aug 2022 23:31:54 +0800 Subject: add comments --- xmake/rules/c++/modules/xmake.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 3c69600bd..42c1709b4 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -77,6 +77,7 @@ rule("c++.build.modules.builder") 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 = {} end end, {batch = true}) @@ -96,6 +97,7 @@ rule("c++.build.modules.builder") -- 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) -- cgit v1.3.1 From bd1263aa60a502120e06eb3fd077d69c689dc5d7 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 00:27:34 +0800 Subject: build batchjobs modules for gcc --- xmake/rules/c++/modules/modules_support/common.lua | 41 ++++++++++++++++ xmake/rules/c++/modules/modules_support/gcc.lua | 55 +++++++++++++++++++--- xmake/rules/c++/modules/xmake.lua | 5 +- 3 files changed, 93 insertions(+), 8 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index ee1016d68..31ab47a81 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -469,6 +469,46 @@ function generate_headerunits_for_batchcmds(target, batchcmds, sourcebatch, modu end end +-- 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 ;` + _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) @@ -481,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 diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index 8f3bacf72..e62721cf3 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -299,10 +299,55 @@ end -- build module files for batchjobs function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) - batchjobs:addjob("TODO", function (index, total) - -- TODO - raise("build modules not supported!") - end, {rootjob = opt.rootjob}) + 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 depmtime = 0 + 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() + local args = {"-o", objectfile, "-c", provide.sourcefile} + 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 + 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 @@ -310,8 +355,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op 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 diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index 42c1709b4..d6098b95e 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -53,6 +53,7 @@ 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 @@ -60,8 +61,6 @@ rule("c++.build.modules.builder") 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) @@ -70,10 +69,12 @@ rule("c++.build.modules.builder") 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 -- cgit v1.3.1 From a7754666add7c76fe8a255e6c84800fa0cb44320 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 00:31:34 +0800 Subject: build batchjobs for clang/msvc --- xmake/rules/c++/modules/modules_support/clang.lua | 77 +++++++++++++++------ xmake/rules/c++/modules/modules_support/gcc.lua | 3 +- xmake/rules/c++/modules/modules_support/msvc.lua | 83 +++++++++++++++++------ 3 files changed, 121 insertions(+), 42 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index bff8cb7cb..f11350764 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -198,8 +198,6 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, -- get cachedirs local stlcachedir = common.stlmodules_cachedir(target) - - -- get headerunits flags local modulecachepathflag = get_modulecachepathflag(target) local modulefileflag = get_modulefileflag(target) @@ -230,8 +228,6 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, 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) @@ -285,8 +281,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) @@ -329,14 +323,67 @@ 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 cachedir = common.modules_cachedir(target) + 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 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 = {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 + + -- 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") - - -- get cachedirs local cachedir = common.modules_cachedir(target) - - -- get modules flags local modulecachepathflag = get_modulecachepathflag(target) local emitmoduleinterfaceflag = get_emitmoduleinterfaceflag(target) @@ -379,14 +426,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op batchcmds:set_depmtime(depmtime) end --- build module files for batchjobs -function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) - batchjobs:addjob("TODO", function (index, total) - -- TODO - raise("build modules not supported!") - end, {rootjob = opt.rootjob}) -end - function get_bmi_extension() return ".pcm" end @@ -524,4 +563,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/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua index e62721cf3..a37346bad 100644 --- a/xmake/rules/c++/modules/modules_support/gcc.lua +++ b/xmake/rules/c++/modules/modules_support/gcc.lua @@ -306,7 +306,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- build modules local projectdir = os.projectdir() - local depmtime = 0 local provided_modules = {} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] @@ -327,12 +326,12 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op local moduleinfo = table.copy(provide) moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) depend.on_changed(function() - local args = {"-o", objectfile, "-c", provide.sourcefile} 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) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 7cf1c63b1..64ca0dae3 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -155,6 +155,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, 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 +164,6 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") - -- get cachedirs - local stlcachedir = common.stlmodules_cachedir(target) - -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} for _, headerunit in ipairs(headerunits) do @@ -190,6 +188,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, 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) @@ -198,9 +197,6 @@ 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 - local stlcachedir = common.stlmodules_cachedir(target) - -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} local depmtime = 0 @@ -226,6 +222,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, 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) @@ -234,9 +231,6 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local ifcoutputflag = get_ifcoutputflag(target) assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") - -- get cachedirs - local cachedir = common.modules_cachedir(target) - -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} local projectdir = os.projectdir() @@ -279,6 +273,7 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, 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) @@ -287,9 +282,6 @@ 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 - local cachedir = common.modules_cachedir(target) - -- build headerunits local common_args = {"-TP", exportheaderflag, "-c"} local projectdir = os.projectdir() @@ -326,10 +318,63 @@ end -- build module files for batchjobs function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) - batchjobs:addjob("TODO", function (index, total) - -- TODO - raise("build modules not supported!") - end, {rootjob = opt.rootjob}) + 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) + + -- append module mapper flags + local cache = common.localcache():get("mapflags") or {} + target:add("cxxflags", cache, {force = true}) + + -- build modules + local common_args = {"-TP"} + 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 = {"-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 + + -- build batchjobs for modules + common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) end -- build module files for batchcmds @@ -337,8 +382,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op 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 @@ -375,9 +418,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op 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 @@ -526,4 +567,4 @@ function get_scandependenciesflag(target) _g.scandependenciesflag = scandependenciesflag or false end return scandependenciesflag or nil -end \ No newline at end of file +end -- cgit v1.3.1 From 8d2cfef3b5814c32d08e89d7d17d4242b203331b Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 00:35:20 +0800 Subject: fix check for clang/headerunits --- xmake/rules/c++/modules/modules_support/clang.lua | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index f11350764..226756d6c 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -163,13 +163,10 @@ end -- generate target stl header units for batchjobs function generate_stl_headerunits_for_batchjobs(target, batchjobs, 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() @@ -200,6 +197,7 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, 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() -- cgit v1.3.1 From 71ee1cb7b921c2b98dda8eecebc641ddac71681d Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 22:32:22 +0800 Subject: fix mapper for clang --- xmake/rules/c++/modules/modules_support/clang.lua | 76 ++++++++++++++++------- 1 file changed, 53 insertions(+), 23 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 226756d6c..1b086c27a 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) @@ -187,6 +195,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, end end end + _flush_mapflags_to_mapper() end -- generate target stl header units for batchcmds @@ -217,6 +226,7 @@ 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 @@ -270,6 +280,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, end, {rootjob = opt.rootjob}) _add_headerunit_to_mapper(target, bmifile) end + _flush_mapflags_to_mapper() end -- generate target user header units for batchcmds @@ -319,6 +330,7 @@ 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 batchjobs @@ -328,10 +340,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op 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 provided_modules = {} @@ -373,6 +381,13 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op 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 batchjobs for modules common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) @@ -385,13 +400,7 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op 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 + -- we need update mapper first for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m and m.provides then @@ -407,6 +416,31 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op 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) @@ -414,10 +448,6 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op 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 -- cgit v1.3.1 From 02b60934d7425d5dc9f77cf3a07d956cf4922b98 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 22:34:01 +0800 Subject: improve mapper for msvc --- xmake/rules/c++/modules/modules_support/msvc.lua | 70 +++++++++++++++++------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 64ca0dae3..7ac93273f 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 @@ -181,6 +190,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, _add_objectfile_to_link_arguments(objectfile) end end + _flush_mapflags_to_mapper() end -- generate target stl header units for batchcmds @@ -215,6 +225,7 @@ 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 @@ -266,6 +277,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, _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 @@ -314,6 +326,7 @@ 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 batchjobs @@ -328,10 +341,6 @@ function build_modules_for_batchjobs(target, batchjobs, 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 provided_modules = {} @@ -372,6 +381,13 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op 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 batchjobs for modules common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) @@ -389,13 +405,7 @@ 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 + -- we need update mapper first for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] if m and m.provides then @@ -412,18 +422,40 @@ 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} + _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 -- cgit v1.3.1 From 1c039fcf27683545adb20ca316d42b1123282719 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 22:35:50 +0800 Subject: clean module caches --- xmake/rules/c++/modules/xmake.lua | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/xmake/rules/c++/modules/xmake.lua b/xmake/rules/c++/modules/xmake.lua index d6098b95e..23f9a0f77 100644 --- a/xmake/rules/c++/modules/xmake.lua +++ b/xmake/rules/c++/modules/xmake.lua @@ -103,11 +103,22 @@ rule("c++.build.modules.builder") end end) - before_link(function(target) + 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") -- cgit v1.3.1 From af7118dcc94785f628abe1cea5cd030514ea9e88 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 9 Aug 2022 22:42:52 +0800 Subject: improve mapper for clang/msvc --- xmake/rules/c++/modules/modules_support/clang.lua | 15 +++++++++------ xmake/rules/c++/modules/modules_support/msvc.lua | 14 +++++++++----- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua index 1b086c27a..866669257 100644 --- a/xmake/rules/c++/modules/modules_support/clang.lua +++ b/xmake/rules/c++/modules/modules_support/clang.lua @@ -367,6 +367,15 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op 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})) @@ -383,12 +392,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op 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 batchjobs for modules common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 7ac93273f..bcc781248 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -368,6 +368,15 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op 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}}) @@ -383,11 +392,6 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op 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 batchjobs for modules common.build_batchjobs_for_modules(provided_modules, batchjobs, opt.rootjob) -- cgit v1.3.1