Skip to content

Commit

Permalink
Merge pull request #3125 from Arthapz/compile-private-modules
Browse files Browse the repository at this point in the history
Compile private C++20 modules
  • Loading branch information
waruqi authored Dec 2, 2022
2 parents 831ef2d + 4554eaf commit 427f36f
Show file tree
Hide file tree
Showing 8 changed files with 282 additions and 84 deletions.
5 changes: 5 additions & 0 deletions tests/projects/c++/modules/private_module/src/dep1.mpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export module dep1;

export int m() {
return 0;
}
7 changes: 7 additions & 0 deletions tests/projects/c++/modules/private_module/src/dep2.mpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export module dep2;

import dep1;

export int i() {
return m();
}
6 changes: 6 additions & 0 deletions tests/projects/c++/modules/private_module/src/use.mpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import dep1;
import dep2;

int lib() {
return m() + i();
}
1 change: 1 addition & 0 deletions tests/projects/c++/modules/private_module/test.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
inherit(".test_base")
6 changes: 6 additions & 0 deletions tests/projects/c++/modules/private_module/xmake.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
add_rules("mode.release", "mode.debug")
set_languages("c++20")
target("private_module")
add_rules("c++")
set_kind("$(kind)")
add_files("src/*.mpp")
91 changes: 74 additions & 17 deletions xmake/rules/c++/modules/modules_support/clang.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
156 changes: 106 additions & 50 deletions xmake/rules/c++/modules/modules_support/gcc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,39 @@ function _build_modulefile(target, sourcefile, opt)
return
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}))
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand Down
Loading

0 comments on commit 427f36f

Please sign in to comment.