diff options
Diffstat (limited to 'xmake/rules/c++/modules/modules_support/msvc.lua')
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/msvc.lua | 688 |
1 files changed, 688 insertions, 0 deletions
diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua new file mode 100644 index 000000000..5214f12df --- /dev/null +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -0,0 +1,688 @@ +--!A cross-platform build utility based on Lua +-- +-- Licensed under the Apache License, Version 2.0 (the "License"); +-- you may not use this file except in compliance with the License. +-- You may obtain a copy of the License at +-- +-- http://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the License is distributed on an "AS IS" BASIS, +-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-- See the License for the specific language governing permissions and +-- limitations under the License. +-- +-- Copyright (C) 2015-present, TBOOX Open Source Group. +-- +-- @author ruki, Arthapz +-- @file msvc.lua +-- + +-- imports +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") + +-- add a module or header unit into the mapper +-- +-- e.g +-- /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, name, bmifile, deps) + local modulemap = _get_modulemap_from_mapper(target) + if modulemap[name] then + return + end + local mapflag = {argument, name .. "=" .. bmifile} + modulemap[name] = {flag = mapflag, deps = deps} + common.localcache():set2(_mapper_cachekey(target), "modulemap", modulemap) +end + +function _mapper_cachekey(target) + return target:name() .. "_modulemap" +end + +-- 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 modulemap from mapper +function _get_modulemap_from_mapper(target) + return common.localcache():get2(_mapper_cachekey(target), "modulemap") or {} +end + +-- add an objectfile to the linker args +-- +-- e.g +-- foo.obj +-- +function _add_objectfile_to_link_arguments(target, objectfile) + local cachekey = target:name() .. "headerunit_objectfiles" + local cache = common.localcache():get(cachekey) or {} + if table.contains(cache, objectfile) then + return + end + table.insert(cache, objectfile) + common.localcache():set(cachekey, cache) + common.localcache():save(cachekey) +end + +-- load module support for the current target +function load(target) + -- get flags + local modulesflag = get_modulesflag(target) + + -- add modules flags + target:add("cxxflags", modulesflag) + + -- add stdifcdir in case of if the user ask for it + if target:values("msvc.modules.stdifcdir") then + local stdifcdirflag = get_stdifcdirflag(target) + for _, toolchain_inst in ipairs(target:toolchains()) do + if toolchain_inst:name() == "msvc" then + local vcvars = toolchain_inst:config("vcvars") + if vcvars.VCInstallDir and vcvars.VCToolsVersion then + local stdifcdir = path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "ifc", target:is_arch("x64") and "x64" or "x86") + if os.isdir(stdifcdir) then + target:add("cxxflags", {stdifcdirflag, winos.short_path(stdifcdir)}, {force = true, expand = false}) + end + end + break + end + end + end +end + +-- provide toolchain include dir for stl headerunit when p1689 is not supported +function toolchain_includedirs(target) + for _, toolchain_inst in ipairs(target:toolchains()) do + if toolchain_inst:name() == "msvc" then + local vcvars = toolchain_inst:config("vcvars") + if vcvars.VCInstallDir and vcvars.VCToolsVersion then + return { path.join(vcvars.VCInstallDir, "Tools", "MSVC", vcvars.VCToolsVersion, "include") } + end + break + end + end + raise("msvc toolchain includedirs not found!") +end + +-- generate dependency files +function generate_dependencies(target, sourcebatch, opt) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + local scandependenciesflag = get_scandependenciesflag(target) + local common_args = {"-TP", scandependenciesflag} + local cachedir = common.modules_cachedir(target) + local changed = false + for _, sourcefile in ipairs(sourcebatch.sourcefiles) do + local dependfile = target:dependfile(sourcefile) + depend.on_changed(function () + if opt.progress then + progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) + end + local outputdir = path.join(cachedir, path.directory(path.relative(sourcefile, projectdir))) + if not os.isdir(outputdir) then + os.mkdir(outputdir) + end + + local jsonfile = path.join(outputdir, path.filename(sourcefile) .. ".json") + if scandependenciesflag then + local args = {jsonfile, sourcefile, "-Fo" .. target:objectfile(sourcefile)} + os.vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args), {envs = vcvars}) + else + common.fallback_generate_dependencies(target, jsonfile, sourcefile) + end + changed = true + + local dependinfo = io.readfile(jsonfile) + return { moduleinfo = dependinfo } + end, {dependfile = dependfile, files = {sourcefile}}) + end + 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") + local stlcachedir = common.stlmodules_cachedir(target) + + -- get flags + local exportheaderflag = get_exportheaderflag(target) + local headerunitflag = get_headerunitflag(target) + local headernameflag = get_headernameflag(target) + local ifcoutputflag = get_ifcoutputflag(target) + assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") + + -- flush job + local flushjob = batchjobs:addjob(target:name() .. "_stl_headerunits_flush_mapper", function(index, total) + _flush_mapper(target) + end, {rootjob = opt.rootjob}) + + -- 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() + -- 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}) + end + + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) + if os.isfile(objectfile) then + _add_objectfile_to_link_arguments(target, objectfile) + end + end, {rootjob = flushjob}) + 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 toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + local stlcachedir = common.stlmodules_cachedir(target) + + -- get flags + local exportheaderflag = get_exportheaderflag(target) + local headerunitflag = get_headerunitflag(target) + local headernameflag = get_headernameflag(target) + local ifcoutputflag = get_ifcoutputflag(target) + assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") + + -- build headerunits + local common_args = {"-TP", exportheaderflag, "-c"} + local depmtime = 0 + for _, headerunit in ipairs(headerunits) do + local bmifile = path.join(stlcachedir, headerunit.name .. get_bmi_extension()) + local objectfile = bmifile .. ".obj" + -- 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, + path(headerunit.name:startswith("experimental/") and path.join(stlcachedir, "experimental") or stlcachedir), + path(objectfile, function (p) return "-Fo" .. p end)} + 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) + end + _add_module_to_mapper(target, headerunitflag .. ":angle", headerunit.name, bmifile) + if os.isfile(objectfile) then + _add_objectfile_to_link_arguments(target, objectfile) + end + depmtime = math.max(depmtime, os.mtime(bmifile)) + end + batchcmds:set_depmtime(depmtime) + _flush_mapper(target) +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") + local cachedir = common.modules_cachedir(target) + + -- get flags + local exportheaderflag = get_exportheaderflag(target) + local headerunitflag = get_headerunitflag(target) + local headernameflag = get_headernameflag(target) + local ifcoutputflag = get_ifcoutputflag(target) + assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") + + -- flush job + local flushjob = batchjobs:addjob(target:name() .. "_user_headerunits_flush_mapper", function(index, total) + _flush_mapper(target) + end, {rootjob = opt.rootjob}) + + -- 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() + 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 + 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 + _add_module_to_mapper(target, headerunitflag .. headerunit.type, headerunit.name, bmifile) + if os.isfile(objectfile) then + _add_objectfile_to_link_arguments(target, objectfile) + end + end, {dependfile = target:dependfile(bmifile), files = {headerunit.path}}) + end, {rootjob = flushjob}) + 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 toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + local cachedir = common.modules_cachedir(target) + + -- get flags + local exportheaderflag = get_exportheaderflag(target) + local headerunitflag = get_headerunitflag(target) + local headernameflag = get_headernameflag(target) + local ifcoutputflag = get_ifcoutputflag(target) + assert(headerunitflag and headernameflag and exportheaderflag, "compiler(msvc): does not support c++ header units!") + + -- build headerunits + local common_args = {"-TP", exportheaderflag, "-c"} + local projectdir = os.projectdir() + local depmtime = 0 + 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 + batchcmds:mkdir(outputdir) + + local bmifilename = path.basename(objectfile) .. get_bmi_extension() + local bmifile = path.join(outputdir, bmifilename) + batchcmds:mkdir(path.directory(objectfile)) + + local args = {headernameflag .. headerunit.type, headerunit.path, ifcoutputflag, outputdir, "/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_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_mapper(target) +end + +-- build module files for batchjobs +function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, opt) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + + -- get flags + local ifcoutputflag = get_ifcoutputflag(target) + local interfaceflag = get_interfaceflag(target) + local referenceflag = get_referenceflag(target) + + -- flush job + local flushjob = batchjobs:addjob(target:name() .. "_modules", function(index, total) + _flush_mapper(target) + end, {rootjob = opt.rootjob}) + + local common_args = {"-TP"} + local modulesjobs = {} + for _, objectfile in ipairs(objectfiles) do + 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 + + 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 modulemap are already stored in the mapper + local requiresflags + if module.requires then + requiresflags = get_requiresflags(target, module.requires, {expand = true}) + end + 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, requiresflags or {}, args), {envs = vcvars}) + end, {dependfile = target:dependfile(bmifile), files = {provide.sourcefile}}) + _add_module_to_mapper(target, referenceflag, name, bmifile, requiresflags) + 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 + modulesjobs[module.cppfile] = { + name = module.cppfile, + deps = table.keys(module.requires), + sourcefile = module.cppfile, + job = batchjobs:newjob(module.cppfile, function(index, total) + function contains(t, v) + for _, flag in ipairs(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 requiresflags = get_requiresflags(target, module.requires) + if requiresflags then + target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}}) + end + end) + } + end + end + end + end + + -- build batchjobs for modules + common.build_batchjobs_for_modules(modulesjobs, batchjobs, flushjob) +end + +-- build module files for batchcmds +function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, opt) + local compinst = target:compiler("cxx") + local toolchain = target:toolchain("msvc") + local vcvars = toolchain:config("vcvars") + local cachedir = common.modules_cachedir(target) + + -- get flags + local ifcoutputflag = get_ifcoutputflag(target) + local interfaceflag = get_interfaceflag(target) + local referenceflag = get_referenceflag(target) + + -- build modules + local common_args = {"-TP"} + local depmtime = 0 + for _, objectfile in ipairs(objectfiles) do + 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 + + -- append required modulemap flags to module + local requiresflags + if module.requires then + requiresflags = get_requiresflags(target, module.requires, {expand = true}) + end + + local bmifile = provide.bmi + local args = {"-c", + path(objectfile, function (p) return "-Fo" .. p end), + interfaceflag, + ifcoutputflag, + path(bmifile), + path(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, requiresflags or {}, args), {envs = vcvars}) + batchcmds:add_depfiles(provide.sourcefile) + _add_module_to_mapper(target, referenceflag, name, bmifile, requiresflags) + depmtime = math.max(depmtime, os.mtime(bmifile)) + else + if module.requires then + local requiresflags = get_requiresflags(target, module.requires) + if requiresflags then + target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}}) + end + end + end + end + end + + batchcmds:set_depmtime(depmtime) + _flush_mapper(target) +end + +function get_bmi_extension() + return ".ifc" +end + +function get_modulesflag(target) + local modulesflag = _g.modulesflag + if modulesflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-experimental:module", "cxxflags", {flagskey = "cl_experimental_module"}) then + modulesflag = "-experimental:module" + end + assert(modulesflag, "compiler(msvc): does not support c++ module!") + _g.modulesflag = modulesflag or false + end + return modulesflag or nil +end + +function get_ifcoutputflag(target) + local ifcoutputflag = _g.ifcoutputflag + if ifcoutputflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-ifcOutput", "cxxflags", {flagskey = "cl_ifc_output"}) then + ifcoutputflag = "-ifcOutput" + end + assert(ifcoutputflag, "compiler(msvc): does not support c++ module!") + _g.ifcoutputflag = ifcoutputflag or false + end + return ifcoutputflag or nil +end + +function get_ifcsearchdirflag(target) + local ifcsearchdirflag = _g.ifcsearchdirflag + if ifcsearchdirflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-ifcSearchDir", "cxxflags", {flagskey = "cl_ifc_search_dir"}) then + ifcsearchdirflag = "-ifcSearchDir" + end + assert(ifcsearchdirflag, "compiler(msvc): does not support c++ module!") + _g.ifcsearchdirflag = ifcsearchdirflag or false + end + return ifcsearchdirflag or nil +end + +function get_interfaceflag(target) + local interfaceflag = _g.interfaceflag + if interfaceflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-interface", "cxxflags", {flagskey = "cl_interface"}) then + interfaceflag = "-interface" + end + assert(interfaceflag, "compiler(msvc): does not support c++ module!") + _g.interfaceflag = interfaceflag or false + end + return interfaceflag +end + +function get_referenceflag(target) + local referenceflag = _g.referenceflag + if referenceflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-reference", "cxxflags", {flagskey = "cl_reference"}) then + referenceflag = "-reference" + end + assert(referenceflag, "compiler(msvc): does not support c++ module!") + _g.referenceflag = referenceflag or false + end + return referenceflag or nil +end + +function get_headernameflag(target) + local headernameflag = _g.headernameflag + if headernameflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-headerName:quote", "cxxflags", {flagskey = "cl_header_name_quote"}) and + compinst:has_flags("-headerName:angle", "cxxflags", {flagskey = "cl_header_name_angle"}) then + headernameflag = "-headerName" + end + _g.headernameflag = headernameflag or false + end + return headernameflag or nil +end + +function get_headerunitflag(target) + local headerunitflag = _g.headerunitflag + if headerunitflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-headerUnit:quote", "cxxflags", {flagskey = "cl_header_unit_quote"}) and + compinst:has_flags("-headerUnit:angle", "cxxflags", {flagskey = "cl_header_unit_angle"}) then + headerunitflag = "-headerUnit" + end + _g.headerunitflag = headerunitflag or false + end + return headerunitflag or nil +end + +function get_exportheaderflag(target) + local modulesflag = get_modulesflag(target) + local exportheaderflag = _g.exportheaderflag + if exportheaderflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags(modulesflag .. " -exportHeader", "cxxflags", {flagskey = "cl_export_header"}) then + exportheaderflag = "-exportHeader" + end + _g.exportheaderflag = exportheaderflag or false + end + return exportheaderflag or nil +end + +function get_stdifcdirflag(target) + local stdifcdirflag = _g.stdifcdirflag + if stdifcdirflag == nil then + local compinst = target:compiler("cxx") + if compinst:has_flags("-stdIfcDir", "cxxflags", {flagskey = "cl_std_ifc_dir"}) then + stdifcdirflag = "-stdIfcDir" + end + _g.stdifcdirflag = stdifcdirflag or false + end + return stdifcdirflag or nil +end + +function get_scandependenciesflag(target) + local scandependenciesflag = _g.scandependenciesflag + if scandependenciesflag == nil then + local compinst = target:compiler("cxx") + local scan_dependencies_jsonfile = os.tmpfile() .. ".json" + if compinst:has_flags("-scanDependencies " .. scan_dependencies_jsonfile, "cxflags", {flagskey = "cl_scan_dependencies", + on_check = function (ok, errors) + if os.isfile(scan_dependencies_jsonfile) then + ok = true + end + if ok and not os.isfile(scan_dependencies_jsonfile) then + ok = false + end + return ok, errors + end}) then + scandependenciesflag = "-scanDependencies" + end + _g.scandependenciesflag = scandependenciesflag or false + end + return scandependenciesflag or nil +end + +-- get requireflags from module mapper +function get_requiresflags(target, requires, opt) + opt = opt or {} + local flags = {} + local modulemap = _get_modulemap_from_mapper(target) + -- add deps required module flags + for name, _ 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 + 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 + + ::continue:: + end + local requireflags = {} + local contains = {} + for i = 1, #flags, 2 do + local value = flags[i + 1] + if not contains[value] then + local key = flags[i] + if opt.expand then + table.insert(requireflags, key) + table.insert(requireflags, value) + else + table.insert(requireflags, {key, value}) + end + contains[value] = true + end + end + if #requireflags > 0 then + return requireflags + end +end |
