summaryrefslogtreecommitdiff
path: root/xmake/rules/c++/modules/modules_support
diff options
context:
space:
mode:
authorruki <[email protected]>2022-12-02 08:50:09 +0800
committerGitHub <[email protected]>2022-12-02 08:50:09 +0800
commit427f36fa0fc5250bf5a37b492102736bdd80867f (patch)
tree9095ee99db223c649b102eaee4419332a2609b77 /xmake/rules/c++/modules/modules_support
parent831ef2d7697ceea6c83aaea75c5d7765352969fa (diff)
parent4554eaf6b7aa25027c49803dc5288fdc272c3363 (diff)
Merge pull request #3125 from Arthapz/compile-private-modules
Compile private C++20 modules
Diffstat (limited to 'xmake/rules/c++/modules/modules_support')
-rw-r--r--xmake/rules/c++/modules/modules_support/clang.lua91
-rw-r--r--xmake/rules/c++/modules/modules_support/gcc.lua156
-rw-r--r--xmake/rules/c++/modules/modules_support/msvc.lua94
3 files changed, 257 insertions, 84 deletions
diff --git a/xmake/rules/c++/modules/modules_support/clang.lua b/xmake/rules/c++/modules/modules_support/clang.lua
index 10042abe2..379aa517c 100644
--- a/xmake/rules/c++/modules/modules_support/clang.lua
+++ b/xmake/rules/c++/modules/modules_support/clang.lua
@@ -149,6 +149,43 @@ function _build_modulefile(target, sourcefile, opt)
return
end
+ -- init flags
+ local requiresflags = opt.requiresflags
+ local flags = table.join({"-x", "c++"}, requiresflags or {}, compflags)
+
+ -- trace
+ progress.show(opt.progress, "${color.build.object}build.cxx.module %s", sourcefile)
+ vprint(compinst:compcmd(sourcefile, objectfile, {compflags = flags, rawargs = true}))
+
+ if not dryrun then
+
+ -- do compile
+ dependinfo.files = {}
+ assert(compinst:compile(sourcefile, objectfile, {dependinfo = dependinfo, compflags = flags}))
+
+ -- update files and values to the dependent file
+ dependinfo.values = depvalues
+ table.join2(dependinfo.files, sourcefile)
+ depend.save(dependinfo, dependfile)
+ end
+end
+
+-- build interface module file
+function _build_interfacemodulefile(target, sourcefile, opt)
+ local objectfile = opt.objectfile
+ local dependfile = opt.dependfile
+ local compinst = compiler.load("cxx", {target = target})
+ local compflags = compinst:compflags({target = target})
+ local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {})
+
+ -- need build this object?
+ local dryrun = option.get("dry-run")
+ local depvalues = {compinst:program(), compflags}
+ local lastmtime = os.isfile(objectfile) and os.mtime(dependfile) or 0
+ if not dryrun and not depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then
+ return
+ end
+
local bmifile = opt.bmifile
local common_args = opt.common_args
local requiresflags = opt.requiresflags
@@ -435,7 +472,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op
requiresflags = get_requiresflags(target, module.requires)
end
- _build_modulefile(target, provide.sourcefile, {
+ _build_interfacemodulefile(target, provide.sourcefile, {
objectfile = objectfile,
dependfile = target:dependfile(bmifile),
bmifile = bmifile,
@@ -453,21 +490,31 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op
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)
+ modulesjobs[module.cppfile] = {
+ name = module.cppfile,
+ deps = table.keys(module.requires or {}),
+ sourcefile = module.cppfile,
+ job = batchjobs:newjob(module.cppfile, function(index, total)
+ local requiresflags
+ if module.requires then
+ requiresflags = get_requiresflags(target, module.requires)
+ end
+
+ if common.has_module_extension(module.cppfile) then
+ _build_modulefile(target, module.cppfile, {
+ objectfile = objectfile,
+ dependfile = target:dependfile(objectfile),
+ requiresflags = requiresflags,
+ progress = (index * 100) / total})
+ target:add("objectfiles", objectfile)
+ elseif requiresflags then
-- 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
+ target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}})
+ end
+ end)
+ }
end
end
end
@@ -510,11 +557,21 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op
_add_module_to_mapper(target, name, bmifile)
depmtime = math.max(depmtime, os.mtime(bmifile))
else
+ local requiresflags
if module.requires then
- local requiresflags = get_requiresflags(target, module.requires)
- if requiresflags then
- target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}})
- end
+ requiresflags = get_requiresflags(target, module.requires)
+ end
+
+ if common.has_module_extension(module.cppfile) then
+ local flags = {"-o", path(objectfile), "-c", path(module.cppfile)}
+ batchcmds:show_progress(opt.progress, "${color.build.object}build.cxx.module %s", module.cppfile)
+ batchcmds:mkdir(path.directory(objectfile))
+ batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), requiresflags or {}, flags))
+ batchcmds:add_depfiles(module.cppfile)
+ target:add("objectfiles", objectfile)
+ depmtime = math.max(depmtime, os.mtime(objectfile))
+ elseif requiresflags then
+ target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}})
end
end
end
diff --git a/xmake/rules/c++/modules/modules_support/gcc.lua b/xmake/rules/c++/modules/modules_support/gcc.lua
index dbb8df3bf..d02512e59 100644
--- a/xmake/rules/c++/modules/modules_support/gcc.lua
+++ b/xmake/rules/c++/modules/modules_support/gcc.lua
@@ -111,6 +111,39 @@ function _build_modulefile(target, sourcefile, opt)
end
-- trace
+ progress.show(opt.progress, "${color.build.object}build.cxx.module %s", sourcefile)
+ vprint(compinst:compcmd(sourcefile, objectfile, {compflags = compflags, rawargs = true}))
+
+ if not dryrun then
+
+ -- do compile
+ dependinfo.files = {}
+ assert(compinst:compile(sourcefile, objectfile, {dependinfo = dependinfo, compflags = compflags}))
+
+ -- update files and values to the dependent file
+ dependinfo.values = depvalues
+ table.join2(dependinfo.files, sourcefile)
+ depend.save(dependinfo, dependfile)
+ end
+end
+
+-- build interface module file
+function _build_interfacemodulefile(target, sourcefile, opt)
+ local objectfile = opt.objectfile
+ local dependfile = opt.dependfile
+ local compinst = compiler.load("cxx", {target = target})
+ local compflags = table.join("-x", "c++", compinst:compflags({target = target}))
+ local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {})
+
+ -- need build this object?
+ local dryrun = option.get("dry-run")
+ local depvalues = {compinst:program(), compflags}
+ local lastmtime = os.isfile(objectfile) and os.mtime(dependfile) or 0
+ if not dryrun and not depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then
+ return
+ end
+
+ -- trace
progress.show(opt.progress, "${color.build.object}generating.cxx.module.bmi %s", opt.name)
vprint(compinst:compcmd(sourcefile, objectfile, {compflags = compflags, rawargs = true}))
@@ -356,43 +389,58 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op
-- build modules
local projectdir = os.projectdir()
- local provided_modules = {}
+ local modulesjobs = {}
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!")
+ if m then
+ if 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
- end
- local bmifile = provide.bmi
- local moduleinfo = table.copy(provide)
- moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total)
- _build_modulefile(target, provide.sourcefile, {
- objectfile = objectfile,
- dependfile = target:dependfile(bmifile),
- name = name,
- progress = (index * 100) / total})
- end)
- if m.requires then
- moduleinfo.deps = table.keys(m.requires)
+ local bmifile = provide.bmi
+ local moduleinfo = table.copy(provide)
+ moduleinfo.job = batchjobs:newjob(provide.sourcefile, function (index, total)
+ _build_interfacemodulefile(target, provide.sourcefile, {
+ objectfile = objectfile,
+ dependfile = target:dependfile(bmifile),
+ name = name,
+ progress = (index * 100) / total})
+ end)
+ if m.requires then
+ moduleinfo.deps = table.keys(m.requires)
+ end
+ moduleinfo.name = name
+ modulesjobs[name] = moduleinfo
+ _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir))
+ target:add("objectfiles", objectfile)
+ elseif common.has_module_extension(m.cppfile) then
+ modulesjobs[m.cppfile] = {
+ name = m.cppfile,
+ deps = table.keys(m.requires or {}),
+ sourcefile = m.cppfile,
+ job = batchjobs:newjob(m.cppfile, function(index, total)
+ _build_modulefile(target, m.cppfile, {
+ objectfile = objectfile,
+ dependfile = target:dependfile(objectfile),
+ progress = (index * 100) / total})
+ target:add("objectfiles", objectfile)
+ end)
+ }
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)
+ common.build_batchjobs_for_modules(modulesjobs, batchjobs, opt.rootjob)
end
-- build module files for batchcmds
@@ -407,30 +455,38 @@ function build_modules_for_batchcmds(target, batchcmds, objectfiles, modules, op
local depmtime = 0
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!")
+ if m then
+ if 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
- end
-
- local bmifile = provide.bmi
- local args = {"-o", path(objectfile), "-c", 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, args))
- batchcmds:add_depfiles(provide.sourcefile)
- _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir))
-
- target:add("objectfiles", objectfile)
- depmtime = math.max(depmtime, os.mtime(bmifile))
+ local bmifile = provide.bmi
+ local args = {"-o", path(objectfile), "-c", 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, args))
+ batchcmds:add_depfiles(provide.sourcefile)
+ _add_module_to_mapper(mapper_file, name, path.absolute(bmifile, projectdir))
+ target:add("objectfiles", objectfile)
+ depmtime = math.max(depmtime, os.mtime(bmifile))
+ elseif common.has_module_extension(m.cppfile) then
+ local args = {"-o", path(objectfile), "-c", path(m.cppfile)}
+ batchcmds:show_progress(opt.progress, "${color.build.object}build.cxx.module %s", m.cppfile)
+ batchcmds:mkdir(path.directory(objectfile))
+ batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), args))
+ batchcmds:add_depfiles(m.cppfile)
+ target:add("objectfiles", objectfile)
+ depmtime = math.max(depmtime, os.mtime(objectfile))
+ end
end
end
batchcmds:set_depmtime(depmtime)
diff --git a/xmake/rules/c++/modules/modules_support/msvc.lua b/xmake/rules/c++/modules/modules_support/msvc.lua
index b57ac4520..d9f3019d6 100644
--- a/xmake/rules/c++/modules/modules_support/msvc.lua
+++ b/xmake/rules/c++/modules/modules_support/msvc.lua
@@ -102,6 +102,43 @@ function _build_modulefile(target, sourcefile, opt)
-- init flags
local requiresflags = opt.requiresflags
+ local flags = table.join("-TP", requiresflags or {}, compflags)
+
+ -- trace
+ progress.show(opt.progress, "${color.build.object}build.cxx.module %s", sourcefile)
+ vprint(compinst:compcmd(sourcefile, objectfile, {compflags = flags, rawargs = true}))
+
+ if not dryrun then
+
+ -- do compile
+ dependinfo.files = {}
+ assert(compinst:compile(sourcefile, objectfile, {dependinfo = dependinfo, compflags = flags}))
+
+ -- update files and values to the dependent file
+ dependinfo.values = depvalues
+ table.join2(dependinfo.files, sourcefile)
+ depend.save(dependinfo, dependfile)
+ end
+end
+
+-- build interface module file
+function _build_interfacemodulefile(target, sourcefile, opt)
+ local objectfile = opt.objectfile
+ local dependfile = opt.dependfile
+ local compinst = compiler.load("cxx", {target = target})
+ local compflags = compinst:compflags({target = target})
+ local dependinfo = option.get("rebuild") and {} or (depend.load(dependfile) or {})
+
+ -- need build this object?
+ local dryrun = option.get("dry-run")
+ local depvalues = {compinst:program(), compflags}
+ local lastmtime = os.isfile(objectfile) and os.mtime(dependfile) or 0
+ if not dryrun and not depend.is_changed(dependinfo, {lastmtime = lastmtime, values = depvalues}) then
+ return
+ end
+
+ -- init flags
+ local requiresflags = opt.requiresflags
local interfaceflag = opt.interfaceflag
local ifcoutputflag = opt.ifcoutputflag
local bmifile = opt.bmifile
@@ -440,7 +477,7 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op
requiresflags = get_requiresflags(target, module.requires, {expand = true})
end
- _build_modulefile(target, provide.sourcefile, {
+ _build_interfacemodulefile(target, provide.sourcefile, {
objectfile = objectfile,
dependfile = target:dependfile(bmifile),
name = name,
@@ -459,21 +496,31 @@ function build_modules_for_batchjobs(target, batchjobs, objectfiles, modules, op
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)
+ modulesjobs[module.cppfile] = {
+ name = module.cppfile,
+ deps = table.keys(module.requires or {}),
+ sourcefile = module.cppfile,
+ job = batchjobs:newjob(module.cppfile, function(index, total)
+ local requiresflags
+ if module.requires then
+ requiresflags = get_requiresflags(target, module.requires, {expand = true})
+ end
+
+ if common.has_module_extension(module.cppfile) then
+ _build_modulefile(target, module.cppfile, {
+ objectfile = objectfile,
+ dependfile = target:dependfile(objectfile),
+ requiresflags = requiresflags,
+ progress = (index * 100) / total})
+ target:add("objectfiles", objectfile)
+ elseif requiresflags then
-- 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
+ target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}})
+ end
+ end)
+ }
end
end
end
@@ -523,14 +570,27 @@ 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_flags, requiresflags or {}, flags), {envs = msvc:runenvs()})
batchcmds:add_depfiles(provide.sourcefile)
+ target:add("objectfiles", objectfile)
_add_module_to_mapper(target, referenceflag, name, name, objectfile, bmifile, requiresflags)
depmtime = math.max(depmtime, os.mtime(bmifile))
else
+ local requiresflags
if module.requires then
- local requiresflags = get_requiresflags(target, module.requires)
- if requiresflags then
- target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}})
- end
+ requiresflags = get_requiresflags(target, module.requires, {expand = true})
+ end
+
+ if common.has_module_extension(module.cppfile) then
+ local flags = {"-c",
+ path(objectfile, function (p) return "-Fo" .. p end),
+ path(module.cppfile)}
+ batchcmds:show_progress(opt.progress, "${color.build.object}build.cxx.module %s", module.cppfile)
+ batchcmds:mkdir(path.directory(objectfile))
+ batchcmds:vrunv(compinst:program(), table.join(compinst:compflags({target = target}), requiresflags or {}, flags), {envs = msvc:runenvs()})
+ batchcmds:add_depfiles(module.cppfile)
+ target:add("objectfiles", objectfile)
+ depmtime = math.max(depmtime, os.mtime(objectfile))
+ elseif requiresflags then
+ target:fileconfig_add(module.cppfile, {force = {cxxflags = requiresflags}})
end
end
end