diff options
| author | Arthur LAURENT <[email protected]> | 2022-08-03 04:10:04 +0200 |
|---|---|---|
| committer | Arthur LAURENT <[email protected]> | 2022-08-03 08:32:49 +0200 |
| commit | 728126bd7816bbd5fb6b93cedc7163a425343fba (patch) | |
| tree | b3b355973fa7b53e11ed74daf0c360f874d5d026 /xmake/rules/c++/modules/modules_support/msvc.lua | |
| parent | a9ed54fd3af64a04bb7d617a51dde689d23c80de (diff) | |
[C++20 Modules] Improve support
Diffstat (limited to 'xmake/rules/c++/modules/modules_support/msvc.lua')
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/msvc.lua | 292 |
1 files changed, 182 insertions, 110 deletions
diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua index 0a701e0f6..1851d678c 100644 --- a/xmake/rules/c++/modules/modules_support/msvc.lua +++ b/xmake/rules/c++/modules/modules_support/msvc.lua @@ -24,42 +24,35 @@ import("core.project.project") import("core.project.depend") import("utils.progress") import("private.action.build.object", {alias = "objectbuilder"}) +import("common") -modulesflag = nil -ifcoutputflag = nil -ifcsearchdirflag = nil -interfaceflag = nil -referenceflag = nil -headernameflag = nil -headerunitflag = nil -exportheaderflag = nil -stdifcdirflag = nil -scandependenciesflag = nil -cxxsourcefileflag = "/TP" +-- load parent target with modules files +function load_parent(target, opt) + local ifcsearchdirflag = get_ifcsearchdirflag(target) -function get_bmi_ext() - return ".ifc" + for _, dep in ipairs(target:orderdeps()) do + cachedir = common.get_cache_dir(dep) + target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) + end end --- load parent target with modules files -function load_parent(target, opt) - local common = import("common") - -- get modules flag +-- check C++20 module support +function check_module_support(target) local compinst = target:compiler("cxx") - - -- add module flags local cachedir = common.get_cache_dir(target) local stlcachedir = common.get_stlcache_dir(target) + -- get flags + local modulesflag = get_modulesflag(target) + local ifcsearchdirflag = get_ifcsearchdirflag(target) + + -- add modules flags target:add("cxxflags", modulesflag) target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) target:add("cxxflags", {ifcsearchdirflag, stlcachedir}, {force = true, expand = false}) - for _, dep in ipairs(target:orderdeps()) do - cachedir = common.get_cache_dir(dep) - target:add("cxxflags", {ifcsearchdirflag, cachedir}, {force = true, expand = false}) - end - + -- add stdifcdir in case of if the user want to use Microsoft modularised STL + 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") @@ -74,83 +67,6 @@ function load_parent(target, opt) end end --- check C++20 module support -function check_module_support(target) - 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!") - - -- get ifcoutput flag - if compinst:has_flags("/ifcOutput", "cxxflags", {flagskey = "cl_ifc_output"}) then - ifcoutputflag = "/ifcOutput" - end - assert(ifcoutputflag, "compiler(msvc): does not support c++ module!") - - -- get ifcsearchdir flag - if compinst:has_flags("/ifcSearchDir", "cxxflags", {flagskey = "cl_ifc_search_dir"}) then - ifcsearchdirflag = "/ifcSearchDir" - end - assert(ifcsearchdirflag, "compiler(msvc): does not support c++ module!") - - -- get interface flag - if compinst:has_flags("/interface", "cxxflags", {flagskey = "cl_interface"}) then - interfaceflag = "/interface" - end - assert(interfaceflag, "compiler(msvc): does not support c++ module!") - - -- get reference flag - if compinst:has_flags("/reference", "cxxflags", {flagskey = "cl_reference"}) then - referenceflag = "/reference" - end - assert(referenceflag, "compiler(msvc): does not support c++ module!") - - -- get headername flag - 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 - assert(headernameflag, "compiler(msvc): does not support c++ module!") - - -- get headerunit flag - 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 - assert(headerunitflag, "compiler(msvc): does not support c++ module!") - - -- get exportheader flag - if compinst:has_flags(modulesflag .. " /exportHeader", "cxxflags", {flagskey = "cl_export_header"}) then - exportheaderflag = "/exportHeader" - end - assert(exportheaderflag, "compiler(msvc): does not support c++ module!") - - -- get stdifcdir flag - if compinst:has_flags("/stdIfcDir", "cxxflags", {flagskey = "cl_ifc_dir"}) then - stdifcdirflag = "/stdIfcDir" - end - assert(stdifcdirflag, "compiler(msvc): does not support c++ module!") - - -- get scandependencies flag - 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 -end - -- provide toolchain include dir for stl headerunit when p1689 is not supported function toolchain_include_directories(target) for _, toolchain_inst in ipairs(target:toolchains()) do @@ -162,7 +78,6 @@ function toolchain_include_directories(target) break end end - assert(false) end @@ -172,13 +87,14 @@ function generate_dependencies(target, sourcebatch, opt) local toolchain = target:toolchain("msvc") local vcvars = toolchain:config("vcvars") - local common = import("common") + local scandependenciesflag = get_scandependenciesflag(target) + local cachedir = common.get_cache_dir(target) - local common_args = {cxxsourcefileflag, scandependenciesflag} + local common_args = {"/TP", scandependenciesflag} for _, sourcefile in ipairs(sourcebatch.sourcefiles) do local dependfile = target:dependfile(sourcefile) - depend.on_changed(function() + depend.on_changed(function () progress.show(opt.progress, "${color.build.object}generating.cxx.module.deps %s", sourcefile) local outdir = path.join(cachedir, path.directory(path.relative(sourcefile, target:scriptdir()))) @@ -205,17 +121,23 @@ end -- generate target header units function generate_headerunits(target, batchcmds, sourcebatch, opt) - local common = import("common") - 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!") + local cachedir = common.get_cache_dir(target) local stlcachedir = common.get_stlcache_dir(target) -- build headerunits - local common_args = {cxxsourcefileflag, exportheaderflag, "/c"} + local common_args = {"/TP", exportheaderflag, "/c"} local objectfiles = {} local public_flags = {} local private_flags = {} @@ -281,13 +203,18 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) 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) + -- append deps modules for _, dep in ipairs(target:orderdeps()) do target:add("cxxflags", dep:data("cxx.modules.flags"), {force = true, expand = false}) end -- compile module files to bmi files - local common_args = {cxxsourcefileflag} + local common_args = {"/TP"} for _, objectfile in ipairs(objectfiles) do local m = modules[objectfile] @@ -309,7 +236,7 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) batchcmds:set_depmtime(os.mtime(bmifile)) batchcmds:set_depcache(target:dependfile(bmifile)) - flag = {"/reference", name .. "=" .. path.filename(bmifile)} + flag = {referenceflag, name .. "=" .. path.filename(bmifile)} end batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), common_args, args, bmi_args), {envs = vcvars}) @@ -325,3 +252,148 @@ function build_modules(target, batchcmds, objectfiles, modules, opt) end end end + +function get_bmi_ext() + 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 +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 +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 +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 +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 +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 +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 +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 +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 +end |
