diff options
| author | ruki <[email protected]> | 2022-12-02 08:50:09 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-12-02 08:50:09 +0800 |
| commit | 427f36fa0fc5250bf5a37b492102736bdd80867f (patch) | |
| tree | 9095ee99db223c649b102eaee4419332a2609b77 /xmake/rules/c++/modules/modules_support | |
| parent | 831ef2d7697ceea6c83aaea75c5d7765352969fa (diff) | |
| parent | 4554eaf6b7aa25027c49803dc5288fdc272c3363 (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.lua | 91 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/gcc.lua | 156 | ||||
| -rw-r--r-- | xmake/rules/c++/modules/modules_support/msvc.lua | 94 |
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 |
