diff options
| author | Arthur LAURENT <[email protected]> | 2022-08-10 16:51:34 +0200 |
|---|---|---|
| committer | Arthur LAURENT <[email protected]> | 2022-08-10 16:52:51 +0200 |
| commit | f4fda8f0fb19a16a19a1f26e7b7e9d52cc36b1ea (patch) | |
| tree | 5ceb362b57a6e905dc1c449734c3b318c0565faa /xmake/rules/c++/modules/modules_support | |
| parent | fa4ada819810fe6b2760e36e6ff7b5f7afe5303d (diff) | |
Improve MSVC
Diffstat (limited to 'xmake/rules/c++/modules/modules_support')
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/common.lua | 40 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/msvc.lua | 323 |
2 files changed, 221 insertions, 142 deletions
diff --git a/xmake/rules/c++/modules/modules_support/common.lua b/xmake/rules/c++/modules/modules_support/common.lua index 96468456f..8072800bc 100644 --- a/xmake/rules/c++/modules/modules_support/common.lua +++ b/xmake/rules/c++/modules/modules_support/common.lua @@ -131,7 +131,7 @@ function contains_modules(target) if not target_with_modules then for _, dep in ipairs(target:orderdeps()) do local sourcebatches = dep:sourcebatches() - if sourcebatches and sourcebatches["c++.build.modules"] then + if sourcebatches["c++.build.modules"] then target_with_modules = true break end @@ -196,24 +196,28 @@ function parse_dependency_data(target, moduleinfos) for _, rule in ipairs(moduleinfo.rules) do modules = modules or {} local m = {} - for _, provide in ipairs(rule.provides) do - m.provides = m.provides or {} - assert(provide["logical-name"]) - if provide["compiled-module-path"] then - if not path.is_absolute(provide["compiled-module-path"]) then - m.provides[provide["logical-name"]] = path.absolute(path.translate(provide["compiled-module-path"])) + if rule.provides then + for _, provide in ipairs(rule.provides) do + m.provides = m.provides or {} + assert(provide["logical-name"]) + if provide["compiled-module-path"] then + if not path.is_absolute(provide["compiled-module-path"]) then + m.provides[provide["logical-name"]] = path.absolute(path.translate(provide["compiled-module-path"])) + else + m.provides[provide["logical-name"]] = path.translate(provide["compiled-module-path"]) + end else - m.provides[provide["logical-name"]] = path.translate(provide["compiled-module-path"]) + -- assume path with name + local name = provide["logical-name"] .. bmi_extension(target) + name:replace(":", "-") + m.provides[provide["logical-name"]] = { + bmi = path.join(cachedir, name), + sourcefile = moduleinfo.sourcefile + } end - else - -- assume path with name - local name = provide["logical-name"] .. bmi_extension(target) - name:replace(":", "-") - m.provides[provide["logical-name"]] = { - bmi = path.join(cachedir, name), - sourcefile = moduleinfo.sourcefile - } end + else + m.cppfile = moduleinfo.sourcefile end assert(rule["primary-output"]) modules[path.translate(rule["primary-output"])] = m @@ -527,9 +531,9 @@ function append_headerunits_objectfiles(target) local cache = localcache():get(cachekey) or {} if target:is_binary() then target:add("ldflags", cache, {force = true}) - elseif target:is_static() == "static" then + elseif target:is_static() then target:add("arflags", cache, {force = true}) - elseif target:is_shared() == "shared" then + elseif target:is_shared() then target:add("shflags", cache, {force = true}) end end diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 5a89af95f..68f75444e 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -23,6 +23,7 @@ import("core.tool.compiler") import("core.project.project") import("core.project.depend") import("core.project.config") +import("core.base.hashset") import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) import("common") @@ -33,40 +34,46 @@ import("common") -- /headerUnit:angle Foo=build/.gens/Foo/rules/modules/cache/Foo.ifc -- /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(target, argument, module, bmifile) - local mapflags = _get_mapflags_from_mapper(target) - local mapflag = format("%s %s=%s", argument, module, bmifile) - local tosearch = format("%s %s=", argument, module) - for _, line in ipairs(mapflags) do - if line:startswith(tosearch) then - return - end +function _add_module_to_mapper(target, argument, name, bmifile, deps) + local modulemap = _get_modulemap_from_mapper(target) + local mapflag = {argument, name .. "=" .. bmifile} + + if modulemap[name] then + return end - for _, dep in ipairs(target:orderdeps()) do - local mapflags_ = _get_mapflags_from_mapper(dep) - for _, line in ipairs(mapflags_) do - if line:startswith(tosearch) then - return + + for _, t in ipairs(project:targets()) do + if not t:name() == target:name() then + local t_modulemap = _get_modulemap_from_mapper(t) + if t_modulemap[name] then + mapflag = t_modulemap[name].flag + break end end end - table.insert(mapflags, mapflag) - common.localcache():set(_mapper_cachekey(target), mapflags) + + modulemap[name] = {flag = mapflag, deps = deps} + common.localcache():set2(_mapper_cachekey(target), "modulemap", modulemap) end function _mapper_cachekey(target) - return target:name() .. "_mapflags" + return target:name() .. "_modulemap" end --- flush mapflags to mapper file cache -function _flush_mapflags_to_mapper(target) +-- flush mapper file cache +function _flush_mapper(target) -- not using set2/get2 to flush only current target mapper common.localcache():save(_mapper_cachekey(target)) end --- get mapflags from mapper -function _get_mapflags_from_mapper(target) - return common.localcache():get(_mapper_cachekey(target)) or {} +-- get modulemap from mapper +function _get_modulemap_from_mapper(target) + return common.localcache():get2(_mapper_cachekey(target), "modulemap") or {} +end + +-- get modulenames from mapper +function _get_modulenames_from_mapper(target) + return common.localcache():get2(_mapper_cachekey(target), "modulenames") or {} end -- add an objectfile to the linker args @@ -181,7 +188,7 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, -- flush job local flushjob = batchjobs:addjob(target:name() .. "_stl_headerunits_flush_mapper", function(index, total) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end, {rootjob = opt.rootjob}) -- build headerunits @@ -192,16 +199,16 @@ function generate_stl_headerunits_for_batchjobs(target, batchjobs, headerunits, if not os.isfile(bmifile) or not os.isfile(objectfile) then batchjobs:addjob(headerunit.name, function(index, total) depend.on_changed(function() - if not common.localcache():get2(headerunit.name, "building") then - common.localcache():set2(headerunit.name, "building", true) + -- don't build same header unit at the same time + if not common.memcache():get2(headerunit.name, "building") then + common.memcache():set2(headerunit.name, "building", true) progress.show((index * 100) / total, "${color.build.object}generating.cxx.headerunit.bmi %s", headerunit.name) local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir, "-Fo" .. objectfile} os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) - common.localcache():set2(headerunit.name, "building", false) end end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) - _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, path.translate(bmifile)) + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) end, {rootjob = flushjob}) _add_objectfile_to_link_arguments(target, objectfile) end @@ -228,19 +235,20 @@ function generate_stl_headerunits_for_batchcmds(target, batchcmds, headerunits, 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 + -- don't build same header unit at the same time + if not common.memcache():get2(headerunit.name, "building") then + common.memcache():set2(headerunit.name, "building", true) local args = {headernameflag .. ":angle", headerunit.name, ifcoutputflag, headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir, "-Fo" .. objectfile} 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}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) - - _add_objectfile_to_link_arguments(target, objectfile) end - _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, path.translate(bmifile)) + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) + _add_objectfile_to_link_arguments(target, objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end -- generate target user header units for batchcmds @@ -259,7 +267,7 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- flush job local flushjob = batchjobs:addjob(target:name() .. "_user_headerunits_flush_mapper", function(index, total) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end, {rootjob = opt.rootjob}) -- build headerunits @@ -279,8 +287,8 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, local bmifile = path.join(outputdir, bmifilename) batchjobs:addjob(headerunit.name, function (index, total) depend.on_changed(function() - if not common.localcache():get2(headerunit.name, "building") then - common.localcache():set2(headerunit.name, "building", true) + if not common.memcache():get2(headerunit.name, "building") then + common.memcache():set2(headerunit.name, "building", true) 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 @@ -293,10 +301,9 @@ function generate_user_headerunits_for_batchjobs(target, batchjobs, headerunits, -- 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}) - common.localcache():set2(headerunit.name, "building", false) end + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, bmifile) - _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, path.translate(bmifile)) end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) end, {rootjob = flushjob}) _add_objectfile_to_link_arguments(target, objectfile) @@ -343,13 +350,13 @@ function generate_user_headerunits_for_batchcmds(target, batchcmds, headerunits, batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) batchcmds:add_depfiles(headerunit.path) - _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, path.translate(bmifile)) + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, bmifile) _add_objectfile_to_link_arguments(target, objectfile) depmtime = math.max(depmtime, os.mtime(bmifile)) end batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end -- build module files for batchjobs @@ -366,73 +373,96 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op -- flush job local flushjob = batchjobs:addjob(target:name() .. "_modules", function(index, total) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end, {rootjob = opt.rootjob}) - -- build modules local common_args = {"-TP"} - local provided_modules = {} + local modulesjobs = {} + local cpp_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!") + local module = modules[objectfile] + if module then + if module.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(module.provides) do + length = length + 1 + name = k + provide = v + if length > 1 then + raise("multiple provides are not supported now!") + end 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 bmifile = provide.bmi + local moduleinfo = table.copy(provide) + moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total) -- 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 - -- append target module mapper flags - local mapflags = _get_mapflags_from_mapper(target) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end + -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper + local flags + if module.requires then + local flags_ = get_requiresflags(target, module.requires) - -- append deps module mapper flags - for _, dep in ipairs(target:orderdeps()) do - local mapflags = _get_mapflags_from_mapper(dep) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) + flags = flags or {} + for i=1, #flags_, 2 do + if not table.contains(flags, flags_[i + 1]) then + table.join2(flags, {flags_[i], flags_[i + 1]}) end 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}}) - local flag = name .. "=" .. path.translate(bmifile) - _add_module_to_mapper(target, referenceflag, name, path.translate(bmifile)) - target:add("cxxflags", {referenceflag, flag}, {force = true, expand = false}) - end) - if m.requires then - moduleinfo.deps = table.keys(m.requires) + + 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, flags or {}, args), {envs = vcvars}) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + _add_module_to_mapper(target, referenceflag, name, bmifile, flags) + end) + if module.requires then + moduleinfo.deps = table.keys(module.requires) + end + moduleinfo.name = name + modulesjobs[name] = moduleinfo + target:add("objectfiles", objectfile) + else + if module.requires then + local moduleinfo = {} + moduleinfo.name = module.cppfile + moduleinfo.deps = table.keys(module.requires) + moduleinfo.sourcefile = module.cppfile + moduleinfo.job = batchjobs:newjob(module.cppfile, function(index, total) + function contains(t, v) + for _, flag in pairs(t) do + if table.contains(flag, v) then + return true + end + end + return false + end + -- append module mapper flags + -- @note we add it at the end to ensure that the full modulemap are already stored in the mapper + local flags_ = get_requiresflags(target, module.requires) + local flags = {} + for i=1, #flags_, 2 do + if not contains(flags, flags_[i + 1]) then + table.insert(flags, {flags_[i], flags_[i + 1]}) + end + end + target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) + end) + modulesjobs[moduleinfo.name] = moduleinfo + end end - moduleinfo.name = name - provided_modules[name] = moduleinfo - target:add("objectfiles", objectfile) end end -- build batchjobs for modules - common.build_batchjobs_for_modules(provided_modules, batchjobs, flushjob) + common.build_batchjobs_for_modules(modulesjobs, batchjobs, flushjob) end -- build module files for batchcmds @@ -447,50 +477,64 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op local interfaceflag = get_interfaceflag(target) local referenceflag = get_referenceflag(target) - -- make sure mapper is flushed - _flush_mapflags_to_mapper(target) - - -- append target module mapper flags - local mapflags = _get_mapflags_from_mapper(target) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end - - -- append deps module mapper flags - for _, dep in ipairs(target:orderdeps()) do - local mapflags = _get_mapflags_from_mapper(dep) - if mapflags then - target:add("cxxflags", mapflags, {force = true}) - end - end -- build modules local common_args = {"-TP"} local depmtime = 0 + local requiresflags 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 module = modules[objectfile] + if module then + if module.provides then + local name, provide + for k, v in pairs(module.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) - local flag = name .. "=" .. bmifile - _add_module_to_mapper(target, referenceflag, name, bmifile) - target:add("cxxflags", {referenceflag, flag}, {force = true, expand = false}) - depmtime = math.max(depmtime, os.mtime(bmifile)) + -- append required modulemap flags to module + local flags + if module.requires then + local flags_ = get_requiresflags(target, module.requires) + + flags = flags or {} + for i=1, #flags_, 2 do + if not table.contains(flags, flags_[i + 1]) then + table.join2(flags, {flags_[i], flags_[i + 1]}) + end + end + 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, flags or {}, args), {envs = vcvars}) + batchcmds:add_depfiles(provide.sourcefile) + _add_module_to_mapper(target, referenceflag, name, bmifile, flags) + depmtime = math.max(depmtime, os.mtime(bmifile)) + else + if module.requires then + local flags + if module.requires then + local flags_ = get_requiresflags(target, module.requires) + + flags = flags or {} + for i=1, #flags_, 2 do + if not table.contains(flags, flags_[i + 1]) then + table.join2(flags, {flags_[i], flags_[i + 1]}) + end + end + end + target:fileconfig_add(module.cppfile, {force = {cxxflags = flags}}) + end + end end end + batchcmds:set_depmtime(depmtime) - _flush_mapflags_to_mapper(target) + _flush_mapper(target) end function get_bmi_extension() @@ -634,3 +678,34 @@ function get_scandependenciesflag(target) end return scandependenciesflag or nil end + +function get_requiresflags(target, requires) + local flags = {} + local modulemap = _get_modulemap_from_mapper(target) + -- add deps required module flags + for name, required in pairs(requires) do + for _, dep in ipairs(target:orderdeps()) do + local modulemap_ = _get_modulemap_from_mapper(dep) + if modulemap_[name] then + table.join2(flags, modulemap_[name].flag) + table.join2(flags, modulemap_[name].deps or {}) + goto CONTINUE + else + print(modulemap) + end + end + + -- append target required module mapper flags + if modulemap[name] then + table.join2(flags, modulemap[name].flag) + table.join2(flags, modulemap[name].deps or {}) + goto CONTINUE + end + + assert(false, "Missing dependency " .. name .. " for " .. target:name()) + + + ::CONTINUE:: + end + return flags +end
\ No newline at end of file |
