summaryrefslogtreecommitdiff
path: root/xmake/rules/c++/modules/modules_support/msvc.lua
diff options
context:
space:
mode:
authorArthur LAURENT <[email protected]>2022-08-03 04:10:04 +0200
committerArthur LAURENT <[email protected]>2022-08-03 08:32:49 +0200
commit728126bd7816bbd5fb6b93cedc7163a425343fba (patch)
treeb3b355973fa7b53e11ed74daf0c360f874d5d026 /xmake/rules/c++/modules/modules_support/msvc.lua
parenta9ed54fd3af64a04bb7d617a51dde689d23c80de (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.lua292
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